X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0d57be459406c2830f6abc9d99ae99166c6d133b..4cb1706ae52c02214a4540c6c4b6882bed5af416:/src/motif/textctrl.cpp diff --git a/src/motif/textctrl.cpp b/src/motif/textctrl.cpp index 3016f39932..3a66bd8ff8 100644 --- a/src/motif/textctrl.cpp +++ b/src/motif/textctrl.cpp @@ -6,93 +6,124 @@ // Created: 17/09/98 // RCS-ID: $Id$ // Copyright: (c) Julian Smart -// Licence: wxWindows licence +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + #ifdef __GNUG__ -#pragma implementation "textctrl.h" + #pragma implementation "textctrl.h" +#endif + +#ifdef __VMS +#define XtParent XTPARENT #endif #include #include #include +#include #include "wx/textctrl.h" #include "wx/settings.h" #include "wx/filefn.h" #include "wx/utils.h" -#if defined(__BORLANDC__) && !defined(__WIN32__) -#include -#else -#ifndef __GNUWIN32__ -#include +#ifdef __VMS__ +#pragma message disable nosimpint #endif -#endif - #include -#include -#include -#include +#ifdef __VMS__ +#pragma message enable nosimpint +#endif #include "wx/motif/private.h" -static void -wxTextWindowChangedProc (Widget w, XtPointer clientData, XtPointer ptr); -static void -wxTextWindowModifyProc (Widget w, XtPointer clientData, XmTextVerifyCallbackStruct *cbs); -static void -wxTextWindowGainFocusProc (Widget w, XtPointer clientData, XmAnyCallbackStruct *cbs); -static void -wxTextWindowLoseFocusProc (Widget w, XtPointer clientData, XmAnyCallbackStruct *cbs); -static void wxTextWindowActivateProc(Widget w, XtPointer clientData, - XmAnyCallbackStruct *ptr); +// ---------------------------------------------------------------------------- +// private functions +// ---------------------------------------------------------------------------- -#if !USE_SHARED_LIBRARY -IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl) +// helper: inserts the new text in the value of the text ctrl and returns the +// result in place +static void MergeChangesIntoString(wxString& value, + XmTextVerifyCallbackStruct *textStruct); -BEGIN_EVENT_TABLE(wxTextCtrl, wxControl) - EVT_DROP_FILES(wxTextCtrl::OnDropFiles) - EVT_CHAR(wxTextCtrl::OnChar) -END_EVENT_TABLE() -#endif +// callbacks +static void wxTextWindowChangedProc(Widget w, XtPointer clientData, XtPointer ptr); +static void wxTextWindowModifyProc(Widget w, XtPointer clientData, XmTextVerifyCallbackStruct *cbs); +static void wxTextWindowGainFocusProc(Widget w, XtPointer clientData, XmAnyCallbackStruct *cbs); +static void wxTextWindowLoseFocusProc(Widget w, XtPointer clientData, XmAnyCallbackStruct *cbs); +static void wxTextWindowActivateProc(Widget w, XtPointer clientData, XmAnyCallbackStruct *ptr); + + IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl) + + BEGIN_EVENT_TABLE(wxTextCtrl, wxControl) + EVT_DROP_FILES(wxTextCtrl::OnDropFiles) + EVT_CHAR(wxTextCtrl::OnChar) + + EVT_MENU(wxID_CUT, wxTextCtrl::OnCut) + EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy) + EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste) + EVT_MENU(wxID_UNDO, wxTextCtrl::OnUndo) + EVT_MENU(wxID_REDO, wxTextCtrl::OnRedo) + + EVT_UPDATE_UI(wxID_CUT, wxTextCtrl::OnUpdateCut) + EVT_UPDATE_UI(wxID_COPY, wxTextCtrl::OnUpdateCopy) + EVT_UPDATE_UI(wxID_PASTE, wxTextCtrl::OnUpdatePaste) + EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo) + EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo) + + END_EVENT_TABLE() + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// wxTextCtrl +// ---------------------------------------------------------------------------- // Text item wxTextCtrl::wxTextCtrl() -#ifndef NO_TEXT_WINDOW_STREAM - :streambuf() -#endif { - m_fileName = ""; m_tempCallbackStruct = (void*) NULL; m_modified = FALSE; m_processedDefault = FALSE; } -bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, - const wxString& value, - const wxPoint& pos, - const wxSize& size, long style, - const wxValidator& validator, - const wxString& name) +bool wxTextCtrl::Create(wxWindow *parent, + wxWindowID id, + const wxString& value, + const wxPoint& pos, + const wxSize& size, + long style, + const wxValidator& validator, + const wxString& name) { m_tempCallbackStruct = (void*) NULL; m_modified = FALSE; m_processedDefault = FALSE; - m_fileName = ""; - m_backgroundColour = parent->GetBackgroundColour(); + // m_backgroundColour = parent->GetBackgroundColour(); + m_backgroundColour = * wxWHITE; m_foregroundColour = parent->GetForegroundColour(); SetName(name); SetValidator(validator); - if (parent) parent->AddChild(this); + if (parent) + parent->AddChild(this); m_windowStyle = style; if ( id == -1 ) - m_windowId = (int)NewControlId(); + m_windowId = (int)NewControlId(); else - m_windowId = id; + m_windowId = id; Widget parentWidget = (Widget) parent->GetClientWidget(); @@ -107,32 +138,64 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, XtSetArg (args[0], XmNscrollHorizontal, wantHorizScrolling ? True : False); XtSetArg (args[1], XmNwordWrap, wantWordWrap ? True : False); - m_mainWidget = (WXWidget) XmCreateScrolledText (parentWidget, (char*) (const char*) name, args, 2); + 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); + XmNeditable, ((style & wxTE_READONLY) ? False : True), + XmNeditMode, XmMULTI_LINE_EDIT, + NULL); XtManageChild ((Widget) m_mainWidget); } else { - m_mainWidget = (WXWidget) XtVaCreateManagedWidget ((char*) (const char*) name, - xmTextWidgetClass, parentWidget, - NULL); + m_mainWidget = (WXWidget)XtVaCreateManagedWidget + ( + (char*)name.c_str(), + xmTextWidgetClass, + parentWidget, + NULL + ); + + XtVaSetValues ((Widget) m_mainWidget, + XmNeditable, ((style & wxTE_READONLY) ? False : True), + NULL); // TODO: Is this relevant? What does it do? int noCols = 2; if (!value.IsNull() && (value.Length() > (unsigned int) noCols)) noCols = value.Length(); - XtVaSetValues ((Widget) m_mainWidget, - XmNcolumns, noCols, - NULL); + XtVaSetValues((Widget) m_mainWidget, + XmNcolumns, noCols, + NULL); } - if (!value.IsNull()) - XmTextSetString ((Widget) m_mainWidget, (char*) (const char*) value); + // remove border if asked for + if ( style & wxNO_BORDER ) + { + XtVaSetValues((Widget)m_mainWidget, + XmNshadowThickness, 0, + 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); XtAddCallback((Widget) m_mainWidget, XmNmodifyVerifyCallback, (XtCallbackProc)wxTextWindowModifyProc, (XtPointer)this); @@ -143,10 +206,13 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, 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); - SetFont(* parent->GetFont()); ChangeBackgroundColour(); return TRUE; @@ -159,30 +225,52 @@ WXWidget wxTextCtrl::GetTopWidget() const wxString wxTextCtrl::GetValue() const { + wxString str; // result + if (m_windowStyle & wxTE_PASSWORD) - return m_value; + { + // the value is stored always in m_value because it can't be retrieved + // from the text control + str = m_value; + } else { + // just get the string from Motif char *s = XmTextGetString ((Widget) m_mainWidget); - if (s) + if ( s ) { - wxString str(s); + str = s; XtFree (s); - return str; - } - else + } + //else: return empty string + + if ( m_tempCallbackStruct ) { - return wxEmptyString; + // the string in the control isn't yet updated, can't use it as is + MergeChangesIntoString(str, (XmTextVerifyCallbackStruct *) + m_tempCallbackStruct); } } + + return str; } void wxTextCtrl::SetValue(const wxString& value) { - wxASSERT_MSG( (!value.IsNull()), "Must not pass a null string to wxTextCtrl::SetValue." ) ; m_inSetValue = TRUE; - XmTextSetString ((Widget) m_mainWidget, (char*) (const char*) 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 m_inSetValue = FALSE; } @@ -203,6 +291,67 @@ 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); @@ -232,20 +381,20 @@ long wxTextCtrl::GetLastPosition() const void wxTextCtrl::Replace(long from, long to, const wxString& value) { XmTextReplace ((Widget) m_mainWidget, (XmTextPosition) from, (XmTextPosition) to, - (char*) (const char*) value); + (char*) (const char*) value); } void wxTextCtrl::Remove(long from, long to) { XmTextSetSelection ((Widget) m_mainWidget, (XmTextPosition) from, (XmTextPosition) to, - (Time) 0); + (Time) 0); XmTextRemove ((Widget) m_mainWidget); } void wxTextCtrl::SetSelection(long from, long to) { XmTextSetSelection ((Widget) m_mainWidget, (XmTextPosition) from, (XmTextPosition) to, - (Time) 0); + (Time) 0); } bool wxTextCtrl::LoadFile(const wxString& file) @@ -257,37 +406,36 @@ bool wxTextCtrl::LoadFile(const wxString& file) Clear(); - ifstream input((char*) (const char*) file, ios::nocreate | ios::in); + Widget textWidget = (Widget) m_mainWidget; + FILE *fp = 0; - if (!input.bad()) + 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 { - struct stat stat_buf; - if (stat(file, &stat_buf) < 0) + long len = statb.st_size; + char *text; + if (!(text = XtMalloc ((unsigned) (len + 1)))) + { + fclose (fp); return FALSE; - // This may need to be a bigger buffer than the file size suggests, - // if it's a UNIX file. Give it an extra 1000 just in case. - char *tmp_buffer = (char*)malloc((size_t)(stat_buf.st_size+1+1000)); - long no_lines = 0; - long pos = 0; - while (!input.eof() && input.peek() != EOF) + } + if (fread (text, sizeof (char), len, fp) != (size_t) len) { - input.getline(wxBuffer, 500); - int len = strlen(wxBuffer); - wxBuffer[len] = 13; - wxBuffer[len+1] = 10; - wxBuffer[len+2] = 0; - strcpy(tmp_buffer+pos, wxBuffer); - pos += strlen(wxBuffer); - no_lines++; - } - - // TODO add line - - free(tmp_buffer); - - return TRUE; + } + fclose (fp); + + text[len] = 0; + XmTextSetString (textWidget, text); + // m_textPosition = len; + XtFree (text); + m_modified = FALSE; + return TRUE; } - return FALSE; } // If file is null, try saved file name first @@ -301,13 +449,31 @@ bool wxTextCtrl::SaveFile(const wxString& file) return FALSE; m_fileName = theFile; - ofstream output((char*) (const char*) theFile); - if (output.bad()) - return FALSE; + Widget textWidget = (Widget) m_mainWidget; + FILE *fp; - // TODO get and save text + if (!(fp = fopen ((char*) (const char*) theFile, "w"))) + { + return FALSE; + } + else + { + char *text = XmTextGetString (textWidget); + long len = XmTextGetLastPosition (textWidget); - return FALSE; + 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) @@ -320,6 +486,16 @@ void wxTextCtrl::WriteText(const wxString& text) 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() { XmTextSetString ((Widget) m_mainWidget, ""); @@ -334,7 +510,6 @@ bool wxTextCtrl::IsModified() const // Makes 'unmodified' void wxTextCtrl::DiscardEdits() { - XmTextSetString ((Widget) m_mainWidget, ""); m_modified = FALSE; } @@ -344,27 +519,27 @@ int wxTextCtrl::GetNumberOfLines() const char *s = XmTextGetString ((Widget) m_mainWidget); if (s) { - long i = 0; - int currentLine = 0; - bool finished = FALSE; - while (!finished) - { - int ch = s[i]; - if (ch == '\n') - { - currentLine++; - i++; - } - else if (ch == 0) - { - finished = TRUE; - } - else - i++; - } - - XtFree (s); - return currentLine; + long i = 0; + int currentLine = 0; + bool finished = FALSE; + while (!finished) + { + int ch = s[i]; + if (ch == '\n') + { + currentLine++; + i++; + } + else if (ch == 0) + { + finished = TRUE; + } + else + i++; + } + + XtFree (s); + return currentLine; } return 0; } @@ -372,22 +547,27 @@ int wxTextCtrl::GetNumberOfLines() const long wxTextCtrl::XYToPosition(long x, long y) const { /* It seems, that there is a bug in some versions of the Motif library, - so the original wxWin-Code doesn't work. */ -/* - Widget textWidget = (Widget) handle; - return (long) XmTextXYToPos (textWidget, (Position) x, (Position) y); -*/ + so the original wxWin-Code doesn't work. */ + /* + Widget textWidget = (Widget) handle; + return (long) XmTextXYToPos (textWidget, (Position) x, (Position) y); + */ /* Now a little workaround: */ long r=0; for (int i=0; i pbase() ) return overflow(EOF); - - return 0; -/* OLD CODE - int len = pptr() - pbase(); - char *txt = new char[len+1]; - strncpy(txt, pbase(), len); - txt[len] = '\0'; - (*this) << txt; - setp(pbase(), epptr()); - delete[] txt; - return 0; -*/ + if (m_tempCallbackStruct) + { + XmTextVerifyCallbackStruct *textStruct = + (XmTextVerifyCallbackStruct *) m_tempCallbackStruct; + textStruct->doit = True; + if (isascii(event.m_keyCode) && (textStruct->text->length == 1)) + { + textStruct->text->ptr[0] = ((event.m_keyCode == WXK_RETURN) ? 10 : event.m_keyCode); + } + } } -//========================================================================= -// Should not be called by a "ostream". Used by a "istream" -//========================================================================= -int wxTextCtrl::underflow() +void wxTextCtrl::ChangeFont(bool keepOriginalSize) { - return EOF; + wxWindow::ChangeFont(keepOriginalSize); } -#endif -wxTextCtrl& wxTextCtrl::operator<<(const wxString& s) +void wxTextCtrl::ChangeBackgroundColour() { - WriteText(s); - return *this; -} + wxWindow::ChangeBackgroundColour(); -wxTextCtrl& wxTextCtrl::operator<<(float f) -{ - wxString str; - str.Printf("%.2f", f); - WriteText(str); - return *this; + /* TODO: should scrollbars be affected? Should probably have separate + * function to change them (by default, taken from wxSystemSettings) + */ + if (m_windowStyle & wxTE_MULTILINE) + { + Widget parent = XtParent ((Widget) m_mainWidget); + Widget hsb, vsb; + + XtVaGetValues (parent, + XmNhorizontalScrollBar, &hsb, + XmNverticalScrollBar, &vsb, + NULL); + wxColour backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE); + if (hsb) + DoChangeBackgroundColour((WXWidget) hsb, backgroundColour, TRUE); + if (vsb) + DoChangeBackgroundColour((WXWidget) vsb, backgroundColour, TRUE); + + DoChangeBackgroundColour((WXWidget) parent, m_backgroundColour, TRUE); + } } -wxTextCtrl& wxTextCtrl::operator<<(double d) +void wxTextCtrl::ChangeForegroundColour() { - wxString str; - str.Printf("%.2f", d); - WriteText(str); - return *this; -} + wxWindow::ChangeForegroundColour(); -wxTextCtrl& wxTextCtrl::operator<<(int i) -{ - wxString str; - str.Printf("%d", i); - WriteText(str); - return *this; + if (m_windowStyle & wxTE_MULTILINE) + { + Widget parent = XtParent ((Widget) m_mainWidget); + Widget hsb, vsb; + + XtVaGetValues (parent, + XmNhorizontalScrollBar, &hsb, + XmNverticalScrollBar, &vsb, + NULL); + + /* TODO: should scrollbars be affected? Should probably have separate + * function to change them (by default, taken from wxSystemSettings) + if (hsb) + DoChangeForegroundColour((WXWidget) hsb, m_foregroundColour); + if (vsb) + DoChangeForegroundColour((WXWidget) vsb, m_foregroundColour); + */ + DoChangeForegroundColour((WXWidget) parent, m_foregroundColour); + } } -wxTextCtrl& wxTextCtrl::operator<<(long i) +void wxTextCtrl::DoSendEvents(void *wxcbs, long keycode) { - wxString str; - str.Printf("%ld", i); - WriteText(str); - return *this; -} + // we're in process of updating the text control + m_tempCallbackStruct = wxcbs; -wxTextCtrl& wxTextCtrl::operator<<(const char c) -{ - char buf[2]; + XmTextVerifyCallbackStruct *cbs = (XmTextVerifyCallbackStruct *)wxcbs; - buf[0] = c; - buf[1] = 0; - WriteText(buf); - return *this; -} + wxKeyEvent event (wxEVT_CHAR); + event.SetId(GetId()); + event.m_keyCode = keycode; + event.SetEventObject(this); -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; - - if (m_tempCallbackStruct) - { - XmTextVerifyCallbackStruct *textStruct = - (XmTextVerifyCallbackStruct *) m_tempCallbackStruct; - textStruct->doit = True; - if (isascii(event.m_keyCode) && (textStruct->text->length == 1)) + // Only if wxTextCtrl::OnChar is called will this be set to True (and + // the character passed through) + cbs->doit = False; + + GetEventHandler()->ProcessEvent(event); + + if ( !InSetValue() && m_processedDefault ) { - textStruct->text->ptr[0] = ((event.m_keyCode == WXK_RETURN) ? 10 : event.m_keyCode); + // Can generate a command + wxCommandEvent commandEvent(wxEVT_COMMAND_TEXT_UPDATED, GetId()); + commandEvent.SetEventObject(this); + ProcessCommand(commandEvent); } - } -} -void wxTextCtrl::ChangeFont() -{ - // TODO + // do it after the (user) event handlers processed the events because + // otherwise GetValue() would return incorrect (not yet updated value) + m_tempCallbackStruct = NULL; } -void wxTextCtrl::ChangeBackgroundColour() -{ - // TODO -} +// ---------------------------------------------------------------------------- +// helpers and Motif callbacks +// ---------------------------------------------------------------------------- -void wxTextCtrl::ChangeForegroundColour() +static void MergeChangesIntoString(wxString& value, + XmTextVerifyCallbackStruct *cbs) { - // TODO -} + /* _sm_ + * At least on my system (SunOS 4.1.3 + Motif 1.2), you need to think of + * every event as a replace event. cbs->text->ptr gives the replacement + * text, cbs->startPos gives the index of the first char affected by the + * replace, and cbs->endPos gives the index one more than the last char + * affected by the replace (startPos == endPos implies an empty range). + * Hence, a deletion is represented by replacing all input text with a + * blank string ("", *not* NULL!). A simple insertion that does not + * overwrite any text has startPos == endPos. + */ -static void wxTextWindowChangedProc (Widget w, XtPointer clientData, XtPointer ptr) -{ - if (!wxGetWindowFromTable(w)) - // Widget has been deleted! - return; + if ( !value ) + { + // easy case: the ol value was empty + value = cbs->text->ptr; + } + else + { + // merge the changes into the value + const char * const passwd = value; + int len = value.length(); - wxTextCtrl *tw = (wxTextCtrl *) clientData; - tw->SetModified(TRUE); -} + len += strlen(cbs->text->ptr) + 1; // + new text (if any) + NUL + len -= cbs->endPos - cbs->startPos; // - text from affected region. -static void -wxTextWindowModifyProc (Widget w, XtPointer clientData, XmTextVerifyCallbackStruct *cbs) -{ - wxTextCtrl *tw = (wxTextCtrl *) clientData; - tw->m_processedDefault = FALSE; + char * newS = new char [len]; + char * dest = newS, + * insert = cbs->text->ptr; - // First, do some stuff if it's a password control. - // (What does this do exactly?) + // Copy (old) text from passwd, up to the start posn of the change. + int i; + const char * p = passwd; + for (i = 0; i < cbs->startPos; ++i) + *dest++ = *p++; - if (tw->GetWindowStyleFlag() & wxTE_PASSWORD) - { - /* _sm_ - * At least on my system (SunOS 4.1.3 + Motif 1.2), you need to think of - * every event as a replace event. cbs->text->ptr gives the replacement - * text, cbs->startPos gives the index of the first char affected by the - * replace, and cbs->endPos gives the index one more than the last char - * affected by the replace (startPos == endPos implies an empty range). - * Hence, a deletion is represented by replacing all input text with a - * blank string ("", *not* NULL!). A simple insertion that does not - * overwrite any text has startPos == endPos. - */ - - if (tw->m_value.IsNull()) - { - tw->m_value = cbs->text->ptr; - } - else - { - char * passwd = (char*) (const char*) tw->m_value; // Set up a more convenient alias. + // Copy the text to be inserted). + while (*insert) + *dest++ = *insert++; - int len = passwd ? strlen(passwd) : 0; // Enough room for old text - len += strlen(cbs->text->ptr) + 1; // + new text (if any) + NUL - len -= cbs->endPos - cbs->startPos; // - text from affected region. + // Finally, copy into newS any remaining text from passwd[endPos] on. + for (p = passwd + cbs->endPos; *p; ) + *dest++ = *p++; + *dest = 0; - char * newS = new char [len]; - char * p = passwd, * dest = newS, * insert = cbs->text->ptr; + value = newS; - // Copy (old) text from passwd, up to the start posn of the change. - int i; - for (i = 0; i < cbs->startPos; ++i) - *dest++ = *p++; + delete[] newS; + } +} - // Copy the text to be inserted). - while (*insert) - *dest++ = *insert++; +static void +wxTextWindowChangedProc (Widget w, XtPointer clientData, XtPointer WXUNUSED(ptr)) +{ + if (!wxGetWindowFromTable(w)) + // Widget has been deleted! + return; - // Finally, copy into newS any remaining text from passwd[endPos] on. - for (p = passwd + cbs->endPos; *p; ) - *dest++ = *p++; - *dest = 0; + wxTextCtrl *tw = (wxTextCtrl *) clientData; + tw->SetModified(TRUE); +} - tw->m_value = newS; +static void +wxTextWindowModifyProc (Widget WXUNUSED(w), XtPointer clientData, XmTextVerifyCallbackStruct *cbs) +{ + wxTextCtrl *tw = (wxTextCtrl *) clientData; + tw->m_processedDefault = FALSE; - delete[] newS; - } + // 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 + // it from the text ctrl. We do *not* do it in other circumstances because + // it would double the amount of memory needed. - if (cbs->text->length>0) + if ( tw->GetWindowStyleFlag() & wxTE_PASSWORD ) + { + MergeChangesIntoString(tw->m_value, cbs); + + if ( cbs->text->length > 0 ) { int i; for (i = 0; i < cbs->text->length; ++i) cbs->text->ptr[i] = '*'; - cbs->text->ptr[i] = 0; + cbs->text->ptr[i] = '\0'; } } - // If we're already within an OnChar, return: probably - // a programmatic insertion. + // If we're already within an OnChar, return: probably a programmatic + // insertion. if (tw->m_tempCallbackStruct) return; // Check for a backspace if (cbs->startPos == (cbs->currInsert - 1)) { - tw->m_tempCallbackStruct = (void*) cbs; - - wxKeyEvent event (wxEVT_CHAR); - event.SetId(tw->GetId()); - event.m_keyCode = WXK_DELETE; - event.SetEventObject(tw); - - // Only if wxTextCtrl::OnChar is called - // will this be set to True (and the character - // passed through) - cbs->doit = False; - - tw->GetEventHandler()->ProcessEvent(event); - - tw->m_tempCallbackStruct = NULL; - - if (tw->InSetValue()) - return; - - if (tw->m_processedDefault) - { - // Can generate a command - wxCommandEvent commandEvent(wxEVT_COMMAND_TEXT_UPDATED, tw->GetId()); - commandEvent.SetEventObject(tw); - tw->ProcessCommand(commandEvent); - } + tw->DoSendEvents((void *)cbs, WXK_DELETE); return; } - // Pasting operation: let it through without - // calling OnChar + // Pasting operation: let it through without calling OnChar if (cbs->text->length > 1) return; @@ -756,80 +844,98 @@ wxTextWindowModifyProc (Widget w, XtPointer clientData, XmTextVerifyCallbackStru if (cbs->text->ptr == NULL) return; - tw->m_tempCallbackStruct = (void*) cbs; + // normal key press + char ch = cbs->text->ptr[0]; + tw->DoSendEvents((void *)cbs, ch == '\n' ? '\r' : ch); +} - wxKeyEvent event (wxEVT_CHAR); - event.SetId(tw->GetId()); +static void +wxTextWindowGainFocusProc (Widget w, XtPointer clientData, XmAnyCallbackStruct *WXUNUSED(cbs)) +{ + if (!wxGetWindowFromTable(w)) + return; + + wxTextCtrl *tw = (wxTextCtrl *) clientData; + wxFocusEvent event(wxEVT_SET_FOCUS, tw->GetId()); event.SetEventObject(tw); - event.m_keyCode = (cbs->text->ptr[0] == 10 ? 13 : cbs->text->ptr[0]); + tw->GetEventHandler()->ProcessEvent(event); +} - // Only if wxTextCtrl::OnChar is called - // will this be set to True (and the character - // passed through) - cbs->doit = False; +static void +wxTextWindowLoseFocusProc (Widget w, XtPointer clientData, XmAnyCallbackStruct *WXUNUSED(cbs)) +{ + if (!wxGetWindowFromTable(w)) + return; + wxTextCtrl *tw = (wxTextCtrl *) clientData; + wxFocusEvent event(wxEVT_KILL_FOCUS, tw->GetId()); + event.SetEventObject(tw); tw->GetEventHandler()->ProcessEvent(event); +} - tw->m_tempCallbackStruct = NULL; +static void wxTextWindowActivateProc(Widget w, XtPointer clientData, + XmAnyCallbackStruct *WXUNUSED(ptr)) +{ + if (!wxGetWindowFromTable(w)) + return; + + wxTextCtrl *tw = (wxTextCtrl *) clientData; if (tw->InSetValue()) return; - - if (tw->m_processedDefault) - { - // Can generate a command - wxCommandEvent commandEvent(wxEVT_COMMAND_TEXT_UPDATED, tw->GetId()); - commandEvent.SetEventObject(tw); - tw->ProcessCommand(commandEvent); - } + + wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER); + event.SetId(tw->GetId()); + event.SetEventObject(tw); + tw->ProcessCommand(event); } -static void -wxTextWindowGainFocusProc (Widget w, XtPointer clientData, XmAnyCallbackStruct *cbs) +void wxTextCtrl::OnCut(wxCommandEvent& WXUNUSED(event)) { - if (!wxGetWindowFromTable(w)) - return; + Cut(); +} - wxTextCtrl *tw = (wxTextCtrl *) clientData; - wxFocusEvent event(wxEVT_SET_FOCUS, tw->GetId()); - event.SetEventObject(tw); - tw->GetEventHandler()->ProcessEvent(event); +void wxTextCtrl::OnCopy(wxCommandEvent& WXUNUSED(event)) +{ + Copy(); } -static void -wxTextWindowLoseFocusProc (Widget w, XtPointer clientData, XmAnyCallbackStruct *cbs) +void wxTextCtrl::OnPaste(wxCommandEvent& WXUNUSED(event)) { - if (!wxGetWindowFromTable(w)) - return; + Paste(); +} - wxTextCtrl *tw = (wxTextCtrl *) clientData; - wxFocusEvent event(wxEVT_KILL_FOCUS, tw->GetId()); - event.SetEventObject(tw); - tw->GetEventHandler()->ProcessEvent(event); +void wxTextCtrl::OnUndo(wxCommandEvent& WXUNUSED(event)) +{ + Undo(); } -static void wxTextWindowActivateProc(Widget w, XtPointer clientData, - XmAnyCallbackStruct *ptr) -{ - if (!wxGetWindowFromTable(w)) - return; - - wxTextCtrl *tw = (wxTextCtrl *) clientData; - /* - case XmCR_ACTIVATE: - type_event = wxEVENT_TYPE_TEXT_ENTER_COMMAND ; - break; - default: - type_event = wxEVENT_TYPE_TEXT_COMMAND ; - break; - } - */ - - if (tw->InSetValue()) - return; - - wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER); - event.SetId(tw->GetId()); - event.SetEventObject(tw); - tw->ProcessCommand(event); +void wxTextCtrl::OnRedo(wxCommandEvent& WXUNUSED(event)) +{ + Redo(); +} + +void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event) +{ + event.Enable( CanCut() ); +} + +void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event) +{ + event.Enable( CanCopy() ); +} + +void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event) +{ + event.Enable( CanPaste() ); +} + +void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event) +{ + event.Enable( CanUndo() ); +} + +void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event) +{ + event.Enable( CanRedo() ); }