X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/44d130a35e7973911686d664bcf275a538990d52..4f320d7c57daa1cd4bc86cbe1da1ef1619b22edc:/src/motif/textctrl.cpp diff --git a/src/motif/textctrl.cpp b/src/motif/textctrl.cpp index 5e602b8a44..4cd726bc04 100644 --- a/src/motif/textctrl.cpp +++ b/src/motif/textctrl.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: textctrl.cpp +// Name: src/motif/textctrl.cpp // Purpose: wxTextCtrl // Author: Julian Smart // Modified by: @@ -17,23 +17,21 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ - #pragma implementation "textctrl.h" -#endif - -#ifdef __VMS -#define XtParent XTPARENT -#endif +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" #include #include -#include #include #include "wx/textctrl.h" -#include "wx/settings.h" + +#ifndef WX_PRECOMP + #include "wx/utils.h" + #include "wx/settings.h" +#endif + #include "wx/filefn.h" -#include "wx/utils.h" #ifdef __VMS__ #pragma message disable nosimpint @@ -61,9 +59,9 @@ static void wxTextWindowGainFocusProc(Widget w, XtPointer clientData, XmAnyCallb static void wxTextWindowLoseFocusProc(Widget w, XtPointer clientData, XmAnyCallbackStruct *cbs); static void wxTextWindowActivateProc(Widget w, XtPointer clientData, XmAnyCallbackStruct *ptr); - IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl) + IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxTextCtrlBase) - BEGIN_EVENT_TABLE(wxTextCtrl, wxControl) + BEGIN_EVENT_TABLE(wxTextCtrl, wxTextCtrlBase) EVT_DROP_FILES(wxTextCtrl::OnDropFiles) EVT_CHAR(wxTextCtrl::OnChar) @@ -92,9 +90,9 @@ static void wxTextWindowActivateProc(Widget w, XtPointer clientData, XmAnyCallba // Text item wxTextCtrl::wxTextCtrl() { - m_tempCallbackStruct = (void*) NULL; - m_modified = FALSE; - m_processedDefault = FALSE; + m_tempCallbackStruct = NULL; + m_modified = false; + m_processedDefault = false; } bool wxTextCtrl::Create(wxWindow *parent, @@ -106,69 +104,71 @@ bool wxTextCtrl::Create(wxWindow *parent, const wxValidator& validator, const wxString& name) { - m_tempCallbackStruct = (void*) NULL; - m_modified = FALSE; - m_processedDefault = FALSE; - // m_backgroundColour = parent->GetBackgroundColour(); - m_backgroundColour = * wxWHITE; - m_foregroundColour = parent->GetForegroundColour(); - - SetName(name); - SetValidator(validator); - if (parent) - parent->AddChild(this); + if( !CreateControl( parent, id, pos, size, style, validator, name ) ) + return false; + PreCreation(); - m_windowStyle = style; - - if ( id == -1 ) - m_windowId = (int)NewControlId(); - else - m_windowId = id; + m_tempCallbackStruct = NULL; + m_modified = false; + m_processedDefault = false; Widget parentWidget = (Widget) parent->GetClientWidget(); - bool wantHorizScrolling = ((m_windowStyle & wxHSCROLL) != 0); - + Bool wantHorizScroll = (m_windowStyle & wxHSCROLL) != 0 ? True : False; // If we don't have horizontal scrollbars, we want word wrap. - bool wantWordWrap = !wantHorizScrolling; + // OpenMotif 2.1 crashes if wantWordWrap is True in Japanese + // locale (and probably other multibyte locales). The check might be + // more precise +#if wxCHECK_LESSTIF() || wxCHECK_MOTIF_VERSION( 2, 2 ) + Bool wantWordWrap = wantHorizScroll == True ? False : True; +#else + Bool wantWordWrap = False; +#endif if (m_windowStyle & wxTE_MULTILINE) { - Arg args[2]; - XtSetArg (args[0], XmNscrollHorizontal, wantHorizScrolling ? True : False); - XtSetArg (args[1], XmNwordWrap, wantWordWrap ? True : False); - - m_mainWidget = (WXWidget) XmCreateScrolledText(parentWidget, - (char*)name.c_str(), - args, 2); - - XtVaSetValues ((Widget) m_mainWidget, - XmNeditable, ((style & wxTE_READONLY) ? False : True), - XmNeditMode, XmMULTI_LINE_EDIT, - NULL); + Arg args[8]; + int count = 0; + XtSetArg (args[count], XmNscrollHorizontal, wantHorizScroll); ++count; + if( m_font.IsOk() ) + XtSetArg (args[count], (String) wxFont::GetFontTag(), + m_font.GetFontType( XtDisplay(parentWidget) ) ); ++count; + XtSetArg (args[count], XmNwordWrap, wantWordWrap); ++count; + XtSetArg (args[count], XmNvalue, (const char*)value.mb_str()); ++count; + XtSetArg (args[count], XmNeditable, + style & wxTE_READONLY ? False : True); ++count; + XtSetArg (args[count], XmNeditMode, XmMULTI_LINE_EDIT ); ++count; + + m_mainWidget = + (WXWidget) XmCreateScrolledText(parentWidget, + name.char_str(), + args, count); + XtManageChild ((Widget) m_mainWidget); } else { m_mainWidget = (WXWidget)XtVaCreateManagedWidget ( - (char*)name.c_str(), + name.mb_str(), xmTextWidgetClass, parentWidget, + wxFont::GetFontTag(), m_font.GetFontType( XtDisplay(parentWidget) ), + XmNvalue, (const char*)value.mb_str(), + XmNeditable, (style & wxTE_READONLY) ? + False : True, NULL ); - XtVaSetValues ((Widget) m_mainWidget, - XmNeditable, ((style & wxTE_READONLY) ? False : True), - NULL); - +#if 0 // TODO: Is this relevant? What does it do? int noCols = 2; - if (!value.IsNull() && (value.Length() > (unsigned int) noCols)) - noCols = value.Length(); + if (!value.IsNull() && (value.length() > (unsigned int) noCols)) + noCols = value.length(); XtVaSetValues((Widget) m_mainWidget, XmNcolumns, noCols, NULL); +#endif } // remove border if asked for @@ -179,22 +179,6 @@ bool wxTextCtrl::Create(wxWindow *parent, NULL); } - if ( !!value ) - { -#if 0 - // don't do this because it is just linking the text to a source - // string which is unsafe. MB - // - XmTextSetString ((Widget) m_mainWidget, (char*)value.c_str()); -#else - // do this instead... MB - // - XtVaSetValues( (Widget) m_mainWidget, - XmNvalue, (char *)value.c_str(), - NULL); -#endif - } - // install callbacks XtAddCallback((Widget) m_mainWidget, XmNvalueChangedCallback, (XtCallbackProc)wxTextWindowChangedProc, (XtPointer)this); @@ -206,21 +190,17 @@ bool wxTextCtrl::Create(wxWindow *parent, XtAddCallback((Widget) m_mainWidget, XmNlosingFocusCallback, (XtCallbackProc)wxTextWindowLoseFocusProc, (XtPointer)this); - // font - m_font = parent->GetFont(); - ChangeFont(FALSE); - - SetCanAddEventHandler(TRUE); - AttachWidget (parent, m_mainWidget, (WXWidget) NULL, pos.x, pos.y, size.x, size.y); + PostCreation(); + AttachWidget (parent, m_mainWidget, (WXWidget) NULL, + pos.x, pos.y, size.x, size.y); - ChangeBackgroundColour(); - - return TRUE; + return true; } WXWidget wxTextCtrl::GetTopWidget() const { - return ((m_windowStyle & wxTE_MULTILINE) ? (WXWidget) XtParent((Widget) m_mainWidget) : m_mainWidget); + return IsMultiLine() ? (WXWidget)XtParent((Widget)m_mainWidget) + : m_mainWidget; } wxString wxTextCtrl::GetValue() const @@ -235,14 +215,7 @@ wxString wxTextCtrl::GetValue() const } else { - // just get the string from Motif - char *s = XmTextGetString ((Widget) m_mainWidget); - if ( s ) - { - str = s; - XtFree (s); - } - //else: return empty string + str = wxTextEntry::GetValue(); if ( m_tempCallbackStruct ) { @@ -255,265 +228,39 @@ wxString wxTextCtrl::GetValue() const return str; } -void wxTextCtrl::SetValue(const wxString& value) +void wxTextCtrl::DoSetValue(const wxString& text, int flags) { - m_inSetValue = TRUE; + m_inSetValue = true; -#if 0 - // don't do this because it is just linking the text to a source - // string which is unsafe. MB - // - XmTextSetString ((Widget) m_mainWidget, (char*)value.c_str()); -#else - // do this instead... MB - // - XtVaSetValues( (Widget) m_mainWidget, - XmNvalue, (char *)value.c_str(), + XmTextSetString ((Widget) m_mainWidget, text.char_str()); + XtVaSetValues ((Widget) m_mainWidget, + XmNcursorPosition, text.length(), NULL); -#endif - m_inSetValue = FALSE; -} + SetInsertionPoint(text.length()); + XmTextShowPosition ((Widget) m_mainWidget, text.length()); + m_modified = true; -// Clipboard operations -void wxTextCtrl::Copy() -{ - XmTextCopy((Widget) m_mainWidget, CurrentTime); -} + m_inSetValue = false; -void wxTextCtrl::Cut() -{ - XmTextCut((Widget) m_mainWidget, CurrentTime); -} - -void wxTextCtrl::Paste() -{ - XmTextPaste((Widget) m_mainWidget); -} - -bool wxTextCtrl::CanCopy() const -{ - // Can copy if there's a selection - long from, to; - GetSelection(& from, & to); - return (from != to) ; -} - -bool wxTextCtrl::CanCut() const -{ - // Can cut if there's a selection - long from, to; - GetSelection(& from, & to); - return (from != to) && (IsEditable()); -} - -bool wxTextCtrl::CanPaste() const -{ - return IsEditable() ; -} - -// Undo/redo -void wxTextCtrl::Undo() -{ - // Not possible in Motif -} - -void wxTextCtrl::Redo() -{ - // Not possible in Motif -} - -bool wxTextCtrl::CanUndo() const -{ - // No Undo in Motif - return FALSE; -} - -bool wxTextCtrl::CanRedo() const -{ - // No Redo in Motif - return FALSE; -} - -// If the return values from and to are the same, there is no -// selection. -void wxTextCtrl::GetSelection(long* from, long* to) const -{ - XmTextPosition left, right; - - XmTextGetSelectionPosition((Widget) m_mainWidget, & left, & right); - - *from = (long) left; - *to = (long) right; -} - -bool wxTextCtrl::IsEditable() const -{ - return (XmTextGetEditable((Widget) m_mainWidget) != 0); -} - -void wxTextCtrl::SetEditable(bool editable) -{ - XmTextSetEditable((Widget) m_mainWidget, (Boolean) editable); -} - -void wxTextCtrl::SetInsertionPoint(long pos) -{ - XmTextSetInsertionPosition ((Widget) m_mainWidget, (XmTextPosition) pos); -} - -void wxTextCtrl::SetInsertionPointEnd() -{ - long pos = GetLastPosition(); - SetInsertionPoint(pos); + if ( flags & SetValue_SendEvent ) + SendTextUpdatedEvent(); } -long wxTextCtrl::GetInsertionPoint() const -{ - return (long) XmTextGetInsertionPosition ((Widget) m_mainWidget); -} - -long wxTextCtrl::GetLastPosition() const -{ - return (long) XmTextGetLastPosition ((Widget) m_mainWidget); -} - -void wxTextCtrl::Replace(long from, long to, const wxString& value) -{ - XmTextReplace ((Widget) m_mainWidget, (XmTextPosition) from, (XmTextPosition) to, - (char*) (const char*) value); -} - -void wxTextCtrl::Remove(long from, long to) -{ - XmTextSetSelection ((Widget) m_mainWidget, (XmTextPosition) from, (XmTextPosition) to, - (Time) 0); - XmTextRemove ((Widget) m_mainWidget); -} - -void wxTextCtrl::SetSelection(long from, long to) -{ - if( to == -1 ) - to = GetLastPosition(); - - XmTextSetSelection ((Widget) m_mainWidget, (XmTextPosition) from, (XmTextPosition) to, - (Time) 0); -} - -bool wxTextCtrl::LoadFile(const wxString& file) -{ - if (!wxFileExists(file)) - return FALSE; - - m_fileName = file; - - Clear(); - - Widget textWidget = (Widget) m_mainWidget; - FILE *fp = 0; - - struct stat statb; - if ((stat ((char*) (const char*) file, &statb) == -1) || (statb.st_mode & S_IFMT) != S_IFREG || - !(fp = fopen ((char*) (const char*) file, "r"))) - { - return FALSE; - } - else - { - long len = statb.st_size; - char *text; - if (!(text = XtMalloc ((unsigned) (len + 1)))) - { - fclose (fp); - return FALSE; - } - if (fread (text, sizeof (char), len, fp) != (size_t) len) - { - } - fclose (fp); - - text[len] = 0; - XmTextSetString (textWidget, text); - // m_textPosition = len; - XtFree (text); - m_modified = FALSE; - return TRUE; - } -} - -// If file is null, try saved file name first -// Returns TRUE if succeeds. -bool wxTextCtrl::SaveFile(const wxString& file) -{ - wxString theFile(file); - if (theFile == "") - theFile = m_fileName; - if (theFile == "") - return FALSE; - m_fileName = theFile; - - Widget textWidget = (Widget) m_mainWidget; - FILE *fp; - - if (!(fp = fopen ((char*) (const char*) theFile, "w"))) - { - return FALSE; - } - else - { - char *text = XmTextGetString (textWidget); - long len = XmTextGetLastPosition (textWidget); - - if (fwrite (text, sizeof (char), len, fp) != (size_t) len) - { - // Did not write whole file - } - // Make sure newline terminates the file - if (text[len - 1] != '\n') - fputc ('\n', fp); - - fclose (fp); - XtFree (text); - m_modified = FALSE; - return TRUE; - } -} - -void wxTextCtrl::WriteText(const wxString& text) -{ - long textPosition = GetInsertionPoint() + strlen (text); - XmTextInsert ((Widget) m_mainWidget, GetInsertionPoint(), (char*) (const char*) text); - XtVaSetValues ((Widget) m_mainWidget, XmNcursorPosition, textPosition, NULL); - SetInsertionPoint(textPosition); - XmTextShowPosition ((Widget) m_mainWidget, textPosition); - m_modified = TRUE; -} - -void wxTextCtrl::AppendText(const wxString& text) -{ - long textPosition = GetLastPosition() + strlen(text); - XmTextInsert ((Widget) m_mainWidget, GetLastPosition(), (char*) (const char*) text); - XtVaSetValues ((Widget) m_mainWidget, XmNcursorPosition, textPosition, NULL); - SetInsertionPoint(textPosition); - XmTextShowPosition ((Widget) m_mainWidget, textPosition); - m_modified = TRUE; -} - -void wxTextCtrl::Clear() +bool wxTextCtrl::IsModified() const { - XmTextSetString ((Widget) m_mainWidget, ""); - m_modified = FALSE; + return m_modified; } -bool wxTextCtrl::IsModified() const +// Makes modified or unmodified +void wxTextCtrl::MarkDirty() { - return m_modified; + m_modified = true; } -// Makes 'unmodified' void wxTextCtrl::DiscardEdits() { - m_modified = FALSE; + m_modified = false; } int wxTextCtrl::GetNumberOfLines() const @@ -524,7 +271,7 @@ int wxTextCtrl::GetNumberOfLines() const { long i = 0; int currentLine = 0; - bool finished = FALSE; + bool finished = false; while (!finished) { int ch = s[i]; @@ -535,7 +282,7 @@ int wxTextCtrl::GetNumberOfLines() const } else if (ch == 0) { - finished = TRUE; + finished = true; } else i++; @@ -570,7 +317,7 @@ bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const if ( y ) *y = yy; - return TRUE; + return true; } void wxTextCtrl::ShowPosition(long pos) @@ -581,7 +328,7 @@ void wxTextCtrl::ShowPosition(long pos) int wxTextCtrl::GetLineLength(long lineNo) const { wxString str = GetLineText (lineNo); - return (int) str.Length(); + return (int) str.length(); } wxString wxTextCtrl::GetLineText(long lineNo) const @@ -591,7 +338,7 @@ wxString wxTextCtrl::GetLineText(long lineNo) const if (s) { - wxString buf(""); + wxString buf; long i; int currentLine = 0; for (i = 0; currentLine != lineNo && s[i]; i++ ) @@ -633,16 +380,16 @@ void wxTextCtrl::OnChar(wxKeyEvent& event) // Indicates that we should generate a normal command, because // we're letting default behaviour happen (otherwise it's vetoed // by virtue of overriding OnChar) - m_processedDefault = TRUE; + m_processedDefault = true; if (m_tempCallbackStruct) { XmTextVerifyCallbackStruct *textStruct = (XmTextVerifyCallbackStruct *) m_tempCallbackStruct; textStruct->doit = True; - if (isascii(event.m_keyCode) && (textStruct->text->length == 1)) + if (wxIsascii(event.m_keyCode) && (textStruct->text->length == 1)) { - textStruct->text->ptr[0] = ((event.m_keyCode == WXK_RETURN) ? 10 : event.m_keyCode); + textStruct->text->ptr[0] = (char)((event.m_keyCode == WXK_RETURN) ? 10 : event.m_keyCode); } } } @@ -670,11 +417,12 @@ void wxTextCtrl::ChangeBackgroundColour() NULL); wxColour backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE); if (hsb) - DoChangeBackgroundColour((WXWidget) hsb, backgroundColour, TRUE); + wxDoChangeBackgroundColour((WXWidget) hsb, backgroundColour, true); if (vsb) - DoChangeBackgroundColour((WXWidget) vsb, backgroundColour, TRUE); + wxDoChangeBackgroundColour((WXWidget) vsb, backgroundColour, true); - DoChangeBackgroundColour((WXWidget) parent, m_backgroundColour, TRUE); + // MBN: why change parent background? + // DoChangeBackgroundColour((WXWidget) parent, m_backgroundColour, true); } } @@ -699,7 +447,7 @@ void wxTextCtrl::ChangeForegroundColour() if (vsb) DoChangeForegroundColour((WXWidget) vsb, m_foregroundColour); */ - DoChangeForegroundColour((WXWidget) parent, m_foregroundColour); + wxDoChangeForegroundColour((WXWidget) parent, m_foregroundColour); } } @@ -719,7 +467,7 @@ void wxTextCtrl::DoSendEvents(void *wxcbs, long keycode) // the character passed through) cbs->doit = False; - GetEventHandler()->ProcessEvent(event); + HandleWindowEvent(event); if ( !InSetValue() && m_processedDefault ) { @@ -734,6 +482,54 @@ void wxTextCtrl::DoSendEvents(void *wxcbs, long keycode) m_tempCallbackStruct = NULL; } +wxSize wxDoGetSingleTextCtrlBestSize( Widget textWidget, + const wxWindow* window ) +{ + Dimension xmargin, ymargin, highlight, shadow; + char* value; + + XtVaGetValues( textWidget, + XmNmarginWidth, &xmargin, + XmNmarginHeight, &ymargin, + XmNvalue, &value, + XmNhighlightThickness, &highlight, + XmNshadowThickness, &shadow, + NULL ); + + if( !value ) + value = wxMOTIF_STR("|"); + + int x, y; + window->GetTextExtent( value, &x, &y ); + + if( x < 90 ) + x = 90; + + return wxSize( x + 2 * xmargin + 2 * highlight + 2 * shadow, + // MBN: +2 necessary: Lesstif bug or mine? + y + 2 * ymargin + 2 * highlight + 2 * shadow + 2 ); +} + +wxSize wxTextCtrl::DoGetBestSize() const +{ + if( IsSingleLine() ) + { + wxSize best = wxControl::DoGetBestSize(); +#if wxCHECK_MOTIF_VERSION( 2, 3 ) + // OpenMotif 2.3 gives way too big X sizes + wxSize other_best = wxDoGetSingleTextCtrlBestSize + ( (Widget) GetTopWidget(), this ); + return wxSize( other_best.x, best.y ); +#else + if( best.x < 90 ) best.x = 90; + + return best; +#endif + } + else + return wxWindow::DoGetBestSize(); +} + // ---------------------------------------------------------------------------- // helpers and Motif callbacks // ---------------------------------------------------------------------------- @@ -802,14 +598,14 @@ wxTextWindowChangedProc (Widget w, XtPointer clientData, XtPointer WXUNUSED(ptr) return; wxTextCtrl *tw = (wxTextCtrl *) clientData; - tw->SetModified(TRUE); + tw->SetModified(true); } static void wxTextWindowModifyProc (Widget WXUNUSED(w), XtPointer clientData, XmTextVerifyCallbackStruct *cbs) { wxTextCtrl *tw = (wxTextCtrl *) clientData; - tw->m_processedDefault = FALSE; + tw->m_processedDefault = false; // First, do some stuff if it's a password control: in this case, we need // to store the string inside the class because GetValue() can't retrieve @@ -829,6 +625,9 @@ wxTextWindowModifyProc (Widget WXUNUSED(w), XtPointer clientData, XmTextVerifyCa } } + if(tw->InSetValue()) + return; + // If we're already within an OnChar, return: probably a programmatic // insertion. if (tw->m_tempCallbackStruct) @@ -864,7 +663,7 @@ wxTextWindowGainFocusProc (Widget w, XtPointer clientData, XmAnyCallbackStruct * wxTextCtrl *tw = (wxTextCtrl *) clientData; wxFocusEvent event(wxEVT_SET_FOCUS, tw->GetId()); event.SetEventObject(tw); - tw->GetEventHandler()->ProcessEvent(event); + tw->HandleWindowEvent(event); } static void @@ -876,7 +675,7 @@ wxTextWindowLoseFocusProc (Widget w, XtPointer clientData, XmAnyCallbackStruct * wxTextCtrl *tw = (wxTextCtrl *) clientData; wxFocusEvent event(wxEVT_KILL_FOCUS, tw->GetId()); event.SetEventObject(tw); - tw->GetEventHandler()->ProcessEvent(event); + tw->HandleWindowEvent(event); } static void wxTextWindowActivateProc(Widget w, XtPointer clientData,