]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/motif/textctrl.cpp
Warning fix and source cleaning.
[wxWidgets.git] / src / motif / textctrl.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: textctrl.cpp
3// Purpose: wxTextCtrl
4// Author: Julian Smart
5// Modified by:
6// Created: 17/09/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "textctrl.h"
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __VMS
28#define XtParent XTPARENT
29#endif
30
31#include "wx/defs.h"
32
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <ctype.h>
36
37#include "wx/textctrl.h"
38#include "wx/settings.h"
39#include "wx/filefn.h"
40#include "wx/utils.h"
41
42#ifdef __VMS__
43#pragma message disable nosimpint
44#endif
45#include <Xm/Text.h>
46#ifdef __VMS__
47#pragma message enable nosimpint
48#endif
49
50#include "wx/motif/private.h"
51
52// ----------------------------------------------------------------------------
53// private functions
54// ----------------------------------------------------------------------------
55
56// helper: inserts the new text in the value of the text ctrl and returns the
57// result in place
58static void MergeChangesIntoString(wxString& value,
59 XmTextVerifyCallbackStruct *textStruct);
60
61// callbacks
62static void wxTextWindowChangedProc(Widget w, XtPointer clientData, XtPointer ptr);
63static void wxTextWindowModifyProc(Widget w, XtPointer clientData, XmTextVerifyCallbackStruct *cbs);
64static void wxTextWindowGainFocusProc(Widget w, XtPointer clientData, XmAnyCallbackStruct *cbs);
65static void wxTextWindowLoseFocusProc(Widget w, XtPointer clientData, XmAnyCallbackStruct *cbs);
66static void wxTextWindowActivateProc(Widget w, XtPointer clientData, XmAnyCallbackStruct *ptr);
67
68 IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
69
70 BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
71 EVT_DROP_FILES(wxTextCtrl::OnDropFiles)
72 EVT_CHAR(wxTextCtrl::OnChar)
73
74 EVT_MENU(wxID_CUT, wxTextCtrl::OnCut)
75 EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy)
76 EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste)
77 EVT_MENU(wxID_UNDO, wxTextCtrl::OnUndo)
78 EVT_MENU(wxID_REDO, wxTextCtrl::OnRedo)
79
80 EVT_UPDATE_UI(wxID_CUT, wxTextCtrl::OnUpdateCut)
81 EVT_UPDATE_UI(wxID_COPY, wxTextCtrl::OnUpdateCopy)
82 EVT_UPDATE_UI(wxID_PASTE, wxTextCtrl::OnUpdatePaste)
83 EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo)
84 EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo)
85
86 END_EVENT_TABLE()
87
88// ============================================================================
89// implementation
90// ============================================================================
91
92// ----------------------------------------------------------------------------
93// wxTextCtrl
94// ----------------------------------------------------------------------------
95
96// Text item
97wxTextCtrl::wxTextCtrl()
98{
99 m_tempCallbackStruct = (void*) NULL;
100 m_modified = FALSE;
101 m_processedDefault = FALSE;
102}
103
104bool wxTextCtrl::Create(wxWindow *parent,
105 wxWindowID id,
106 const wxString& value,
107 const wxPoint& pos,
108 const wxSize& size,
109 long style,
110 const wxValidator& validator,
111 const wxString& name)
112{
113 if( !CreateControl( parent, id, pos, size, style, validator, name ) )
114 return false;
115
116 m_tempCallbackStruct = (void*) NULL;
117 m_modified = FALSE;
118 m_processedDefault = FALSE;
119
120 m_backgroundColour = *wxWHITE;
121
122 Widget parentWidget = (Widget) parent->GetClientWidget();
123
124 bool wantHorizScrolling = ((m_windowStyle & wxHSCROLL) != 0);
125
126 // If we don't have horizontal scrollbars, we want word wrap.
127 bool wantWordWrap = !wantHorizScrolling;
128
129 if (m_windowStyle & wxTE_MULTILINE)
130 {
131 Arg args[2];
132 XtSetArg (args[0], XmNscrollHorizontal, wantHorizScrolling ? True : False);
133 XtSetArg (args[1], XmNwordWrap, wantWordWrap ? True : False);
134
135 m_mainWidget = (WXWidget) XmCreateScrolledText(parentWidget,
136 wxConstCast(name.c_str(), char),
137 args, 2);
138
139 XtVaSetValues ((Widget) m_mainWidget,
140 XmNeditable, ((style & wxTE_READONLY) ? False : True),
141 XmNeditMode, XmMULTI_LINE_EDIT,
142 NULL);
143 XtManageChild ((Widget) m_mainWidget);
144 }
145 else
146 {
147 m_mainWidget = (WXWidget)XtVaCreateManagedWidget
148 (
149 wxConstCast(name.c_str(), char),
150 xmTextWidgetClass,
151 parentWidget,
152 NULL
153 );
154
155 XtVaSetValues ((Widget) m_mainWidget,
156 XmNeditable, ((style & wxTE_READONLY) ? False : True),
157 NULL);
158
159 // TODO: Is this relevant? What does it do?
160 int noCols = 2;
161 if (!value.IsNull() && (value.Length() > (unsigned int) noCols))
162 noCols = value.Length();
163 XtVaSetValues((Widget) m_mainWidget,
164 XmNcolumns, noCols,
165 NULL);
166 }
167
168 // remove border if asked for
169 if ( style & wxNO_BORDER )
170 {
171 XtVaSetValues((Widget)m_mainWidget,
172 XmNshadowThickness, 0,
173 NULL);
174 }
175
176 if ( !value.empty() )
177 {
178 // do this instead... MB
179 //
180 XtVaSetValues( (Widget) m_mainWidget,
181 XmNvalue, wxConstCast(value.c_str(), char),
182 NULL);
183 }
184
185 // install callbacks
186 XtAddCallback((Widget) m_mainWidget, XmNvalueChangedCallback, (XtCallbackProc)wxTextWindowChangedProc, (XtPointer)this);
187
188 XtAddCallback((Widget) m_mainWidget, XmNmodifyVerifyCallback, (XtCallbackProc)wxTextWindowModifyProc, (XtPointer)this);
189
190 XtAddCallback((Widget) m_mainWidget, XmNactivateCallback, (XtCallbackProc)wxTextWindowActivateProc, (XtPointer)this);
191
192 XtAddCallback((Widget) m_mainWidget, XmNfocusCallback, (XtCallbackProc)wxTextWindowGainFocusProc, (XtPointer)this);
193
194 XtAddCallback((Widget) m_mainWidget, XmNlosingFocusCallback, (XtCallbackProc)wxTextWindowLoseFocusProc, (XtPointer)this);
195
196 // font
197 ChangeFont(FALSE);
198
199 wxSize best = GetBestSize();
200 if( size.x != -1 ) best.x = size.x;
201 if( size.y != -1 ) best.y = size.y;
202
203 AttachWidget (parent, m_mainWidget, (WXWidget) NULL,
204 pos.x, pos.y, best.x, best.y);
205
206 ChangeBackgroundColour();
207
208 return TRUE;
209}
210
211WXWidget wxTextCtrl::GetTopWidget() const
212{
213 return IsMultiLine() ? (WXWidget)XtParent((Widget)m_mainWidget)
214 : m_mainWidget;
215}
216
217wxString wxTextCtrl::GetValue() const
218{
219 wxString str; // result
220
221 if (m_windowStyle & wxTE_PASSWORD)
222 {
223 // the value is stored always in m_value because it can't be retrieved
224 // from the text control
225 str = m_value;
226 }
227 else
228 {
229 // just get the string from Motif
230 char *s = XmTextGetString ((Widget) m_mainWidget);
231 if ( s )
232 {
233 str = s;
234 XtFree (s);
235 }
236 //else: return empty string
237
238 if ( m_tempCallbackStruct )
239 {
240 // the string in the control isn't yet updated, can't use it as is
241 MergeChangesIntoString(str, (XmTextVerifyCallbackStruct *)
242 m_tempCallbackStruct);
243 }
244 }
245
246 return str;
247}
248
249void wxTextCtrl::SetValue(const wxString& value)
250{
251 m_inSetValue = TRUE;
252
253 // do this instead... MB
254 //
255 // with (at least) OpenMotif 2.1 this causes a lot of flicker
256#if 0
257 XtVaSetValues( (Widget) m_mainWidget,
258 XmNvalue, wxConstCast(value.c_str(), char),
259 NULL);
260#endif
261
262 Clear();
263 AppendText( value );
264
265 m_inSetValue = FALSE;
266}
267
268// Clipboard operations
269void wxTextCtrl::Copy()
270{
271 XmTextCopy((Widget) m_mainWidget, CurrentTime);
272}
273
274void wxTextCtrl::Cut()
275{
276 XmTextCut((Widget) m_mainWidget, CurrentTime);
277}
278
279void wxTextCtrl::Paste()
280{
281 XmTextPaste((Widget) m_mainWidget);
282}
283
284bool wxTextCtrl::CanCopy() const
285{
286 // Can copy if there's a selection
287 long from, to;
288 GetSelection(& from, & to);
289 return (from != to) ;
290}
291
292bool wxTextCtrl::CanCut() const
293{
294 // Can cut if there's a selection
295 long from, to;
296 GetSelection(& from, & to);
297 return (from != to) && (IsEditable());
298}
299
300bool wxTextCtrl::CanPaste() const
301{
302 return IsEditable() ;
303}
304
305// Undo/redo
306void wxTextCtrl::Undo()
307{
308 // Not possible in Motif
309}
310
311void wxTextCtrl::Redo()
312{
313 // Not possible in Motif
314}
315
316bool wxTextCtrl::CanUndo() const
317{
318 // No Undo in Motif
319 return FALSE;
320}
321
322bool wxTextCtrl::CanRedo() const
323{
324 // No Redo in Motif
325 return FALSE;
326}
327
328// If the return values from and to are the same, there is no
329// selection.
330void wxTextCtrl::GetSelection(long* from, long* to) const
331{
332 XmTextPosition left, right;
333
334 XmTextGetSelectionPosition((Widget) m_mainWidget, & left, & right);
335
336 *from = (long) left;
337 *to = (long) right;
338}
339
340bool wxTextCtrl::IsEditable() const
341{
342 return (XmTextGetEditable((Widget) m_mainWidget) != 0);
343}
344
345void wxTextCtrl::SetEditable(bool editable)
346{
347 XmTextSetEditable((Widget) m_mainWidget, (Boolean) editable);
348}
349
350void wxTextCtrl::SetInsertionPoint(long pos)
351{
352 XmTextSetInsertionPosition ((Widget) m_mainWidget, (XmTextPosition) pos);
353}
354
355void wxTextCtrl::SetInsertionPointEnd()
356{
357 long pos = GetLastPosition();
358 SetInsertionPoint(pos);
359}
360
361long wxTextCtrl::GetInsertionPoint() const
362{
363 return (long) XmTextGetInsertionPosition ((Widget) m_mainWidget);
364}
365
366long wxTextCtrl::GetLastPosition() const
367{
368 return (long) XmTextGetLastPosition ((Widget) m_mainWidget);
369}
370
371void wxTextCtrl::Replace(long from, long to, const wxString& value)
372{
373 XmTextReplace ((Widget) m_mainWidget, (XmTextPosition) from, (XmTextPosition) to,
374 wxConstCast(value.c_str(), char));
375}
376
377void wxTextCtrl::Remove(long from, long to)
378{
379 XmTextSetSelection ((Widget) m_mainWidget, (XmTextPosition) from, (XmTextPosition) to,
380 (Time) 0);
381 XmTextRemove ((Widget) m_mainWidget);
382}
383
384void wxTextCtrl::SetSelection(long from, long to)
385{
386 if( to == -1 )
387 to = GetLastPosition();
388
389 XmTextSetSelection ((Widget) m_mainWidget, (XmTextPosition) from, (XmTextPosition) to,
390 (Time) 0);
391}
392
393void wxTextCtrl::WriteText(const wxString& text)
394{
395 long textPosition = GetInsertionPoint() + strlen (text);
396 XmTextInsert ((Widget) m_mainWidget, GetInsertionPoint(),
397 wxConstCast(text.c_str(), char));
398 XtVaSetValues ((Widget) m_mainWidget, XmNcursorPosition, textPosition, NULL);
399 SetInsertionPoint(textPosition);
400 XmTextShowPosition ((Widget) m_mainWidget, textPosition);
401 m_modified = TRUE;
402}
403
404void wxTextCtrl::AppendText(const wxString& text)
405{
406 long textPosition = GetLastPosition() + text.length();
407 XmTextInsert ((Widget) m_mainWidget, GetLastPosition(),
408 wxConstCast(text.c_str(), char));
409 XtVaSetValues ((Widget) m_mainWidget, XmNcursorPosition, textPosition, NULL);
410 SetInsertionPoint(textPosition);
411 XmTextShowPosition ((Widget) m_mainWidget, textPosition);
412 m_modified = TRUE;
413}
414
415void wxTextCtrl::Clear()
416{
417 XmTextSetString ((Widget) m_mainWidget, "");
418 m_modified = FALSE;
419}
420
421bool wxTextCtrl::IsModified() const
422{
423 return m_modified;
424}
425
426// Makes modified or unmodified
427void wxTextCtrl::MarkDirty()
428{
429 m_modified = TRUE;
430}
431
432void wxTextCtrl::DiscardEdits()
433{
434 m_modified = FALSE;
435}
436
437int wxTextCtrl::GetNumberOfLines() const
438{
439 // HIDEOUSLY inefficient, but we have no choice.
440 char *s = XmTextGetString ((Widget) m_mainWidget);
441 if (s)
442 {
443 long i = 0;
444 int currentLine = 0;
445 bool finished = FALSE;
446 while (!finished)
447 {
448 int ch = s[i];
449 if (ch == '\n')
450 {
451 currentLine++;
452 i++;
453 }
454 else if (ch == 0)
455 {
456 finished = TRUE;
457 }
458 else
459 i++;
460 }
461
462 XtFree (s);
463 return currentLine;
464 }
465 return 0;
466}
467
468long wxTextCtrl::XYToPosition(long x, long y) const
469{
470/* It seems, that there is a bug in some versions of the Motif library,
471 so the original wxWin-Code doesn't work. */
472 /*
473 Widget textWidget = (Widget) handle;
474 return (long) XmTextXYToPos (textWidget, (Position) x, (Position) y);
475 */
476 /* Now a little workaround: */
477 long r=0;
478 for (int i=0; i<y; i++) r+=(GetLineLength(i)+1);
479 return r+x;
480}
481
482bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
483{
484 Position xx, yy;
485 XmTextPosToXY((Widget) m_mainWidget, pos, &xx, &yy);
486 if ( x )
487 *x = xx;
488 if ( y )
489 *y = yy;
490
491 return TRUE;
492}
493
494void wxTextCtrl::ShowPosition(long pos)
495{
496 XmTextShowPosition ((Widget) m_mainWidget, (XmTextPosition) pos);
497}
498
499int wxTextCtrl::GetLineLength(long lineNo) const
500{
501 wxString str = GetLineText (lineNo);
502 return (int) str.Length();
503}
504
505wxString wxTextCtrl::GetLineText(long lineNo) const
506{
507 // HIDEOUSLY inefficient, but we have no choice.
508 char *s = XmTextGetString ((Widget) m_mainWidget);
509
510 if (s)
511 {
512 wxString buf("");
513 long i;
514 int currentLine = 0;
515 for (i = 0; currentLine != lineNo && s[i]; i++ )
516 if (s[i] == '\n')
517 currentLine++;
518 // Now get the text
519 int j;
520 for (j = 0; s[i] && s[i] != '\n'; i++, j++ )
521 buf += s[i];
522
523 XtFree(s);
524 return buf;
525 }
526 else
527 return wxEmptyString;
528}
529
530/*
531* Text item
532*/
533
534void wxTextCtrl::Command(wxCommandEvent & event)
535{
536 SetValue (event.GetString());
537 ProcessCommand (event);
538}
539
540void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event)
541{
542 // By default, load the first file into the text window.
543 if (event.GetNumberOfFiles() > 0)
544 {
545 LoadFile(event.GetFiles()[0]);
546 }
547}
548
549void wxTextCtrl::OnChar(wxKeyEvent& event)
550{
551 // Indicates that we should generate a normal command, because
552 // we're letting default behaviour happen (otherwise it's vetoed
553 // by virtue of overriding OnChar)
554 m_processedDefault = TRUE;
555
556 if (m_tempCallbackStruct)
557 {
558 XmTextVerifyCallbackStruct *textStruct =
559 (XmTextVerifyCallbackStruct *) m_tempCallbackStruct;
560 textStruct->doit = True;
561 if (isascii(event.m_keyCode) && (textStruct->text->length == 1))
562 {
563 textStruct->text->ptr[0] = ((event.m_keyCode == WXK_RETURN) ? 10 : event.m_keyCode);
564 }
565 }
566}
567
568void wxTextCtrl::ChangeFont(bool keepOriginalSize)
569{
570 wxWindow::ChangeFont(keepOriginalSize);
571}
572
573void wxTextCtrl::ChangeBackgroundColour()
574{
575 wxWindow::ChangeBackgroundColour();
576
577 /* TODO: should scrollbars be affected? Should probably have separate
578 * function to change them (by default, taken from wxSystemSettings)
579 */
580 if (m_windowStyle & wxTE_MULTILINE)
581 {
582 Widget parent = XtParent ((Widget) m_mainWidget);
583 Widget hsb, vsb;
584
585 XtVaGetValues (parent,
586 XmNhorizontalScrollBar, &hsb,
587 XmNverticalScrollBar, &vsb,
588 NULL);
589 wxColour backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
590 if (hsb)
591 wxDoChangeBackgroundColour((WXWidget) hsb, backgroundColour, TRUE);
592 if (vsb)
593 wxDoChangeBackgroundColour((WXWidget) vsb, backgroundColour, TRUE);
594
595 // MBN: why change parent background?
596 // DoChangeBackgroundColour((WXWidget) parent, m_backgroundColour, TRUE);
597 }
598}
599
600void wxTextCtrl::ChangeForegroundColour()
601{
602 wxWindow::ChangeForegroundColour();
603
604 if (m_windowStyle & wxTE_MULTILINE)
605 {
606 Widget parent = XtParent ((Widget) m_mainWidget);
607 Widget hsb, vsb;
608
609 XtVaGetValues (parent,
610 XmNhorizontalScrollBar, &hsb,
611 XmNverticalScrollBar, &vsb,
612 NULL);
613
614 /* TODO: should scrollbars be affected? Should probably have separate
615 * function to change them (by default, taken from wxSystemSettings)
616 if (hsb)
617 DoChangeForegroundColour((WXWidget) hsb, m_foregroundColour);
618 if (vsb)
619 DoChangeForegroundColour((WXWidget) vsb, m_foregroundColour);
620 */
621 wxDoChangeForegroundColour((WXWidget) parent, m_foregroundColour);
622 }
623}
624
625void wxTextCtrl::DoSendEvents(void *wxcbs, long keycode)
626{
627 // we're in process of updating the text control
628 m_tempCallbackStruct = wxcbs;
629
630 XmTextVerifyCallbackStruct *cbs = (XmTextVerifyCallbackStruct *)wxcbs;
631
632 wxKeyEvent event (wxEVT_CHAR);
633 event.SetId(GetId());
634 event.m_keyCode = keycode;
635 event.SetEventObject(this);
636
637 // Only if wxTextCtrl::OnChar is called will this be set to True (and
638 // the character passed through)
639 cbs->doit = False;
640
641 GetEventHandler()->ProcessEvent(event);
642
643 if ( !InSetValue() && m_processedDefault )
644 {
645 // Can generate a command
646 wxCommandEvent commandEvent(wxEVT_COMMAND_TEXT_UPDATED, GetId());
647 commandEvent.SetEventObject(this);
648 ProcessCommand(commandEvent);
649 }
650
651 // do it after the (user) event handlers processed the events because
652 // otherwise GetValue() would return incorrect (not yet updated value)
653 m_tempCallbackStruct = NULL;
654}
655
656wxSize wxDoGetSingleTextCtrlBestSize( Widget textWidget,
657 const wxWindow* window )
658{
659 Dimension xmargin, ymargin, highlight, shadow;
660 char* value;
661
662 XtVaGetValues( textWidget,
663 XmNmarginWidth, &xmargin,
664 XmNmarginHeight, &ymargin,
665 XmNvalue, &value,
666 XmNhighlightThickness, &highlight,
667 XmNshadowThickness, &shadow,
668 NULL );
669
670 if( !value )
671 value = "|";
672
673 int x, y;
674 window->GetTextExtent( value, &x, &y );
675
676 if( x < 100 ) x = 100;
677
678 return wxSize( x + 2 * xmargin + 2 * highlight + 2 * shadow,
679 // MBN: +2 necessary: Lesstif bug or mine?
680 y + 2 * ymargin + 2 * highlight + 2 * shadow + 2 );
681}
682
683wxSize wxTextCtrl::DoGetBestSize() const
684{
685 if( IsSingleLine() )
686 return wxDoGetSingleTextCtrlBestSize( (Widget)m_mainWidget, this );
687 else
688 return wxWindow::DoGetBestSize();
689}
690
691// ----------------------------------------------------------------------------
692// helpers and Motif callbacks
693// ----------------------------------------------------------------------------
694
695static void MergeChangesIntoString(wxString& value,
696 XmTextVerifyCallbackStruct *cbs)
697{
698 /* _sm_
699 * At least on my system (SunOS 4.1.3 + Motif 1.2), you need to think of
700 * every event as a replace event. cbs->text->ptr gives the replacement
701 * text, cbs->startPos gives the index of the first char affected by the
702 * replace, and cbs->endPos gives the index one more than the last char
703 * affected by the replace (startPos == endPos implies an empty range).
704 * Hence, a deletion is represented by replacing all input text with a
705 * blank string ("", *not* NULL!). A simple insertion that does not
706 * overwrite any text has startPos == endPos.
707 */
708
709 if ( !value )
710 {
711 // easy case: the ol value was empty
712 value = cbs->text->ptr;
713 }
714 else
715 {
716 // merge the changes into the value
717 const char * const passwd = value;
718 int len = value.length();
719
720 len += ( cbs->text->ptr ?
721 strlen(cbs->text->ptr) :
722 0 ) + 1; // + new text (if any) + NUL
723 len -= cbs->endPos - cbs->startPos; // - text from affected region.
724
725 char * newS = new char [len];
726 char * dest = newS,
727 * insert = cbs->text->ptr;
728
729 // Copy (old) text from passwd, up to the start posn of the change.
730 int i;
731 const char * p = passwd;
732 for (i = 0; i < cbs->startPos; ++i)
733 *dest++ = *p++;
734
735 // Copy the text to be inserted).
736 if (insert)
737 while (*insert)
738 *dest++ = *insert++;
739
740 // Finally, copy into newS any remaining text from passwd[endPos] on.
741 for (p = passwd + cbs->endPos; *p; )
742 *dest++ = *p++;
743 *dest = 0;
744
745 value = newS;
746
747 delete[] newS;
748 }
749}
750
751static void
752wxTextWindowChangedProc (Widget w, XtPointer clientData, XtPointer WXUNUSED(ptr))
753{
754 if (!wxGetWindowFromTable(w))
755 // Widget has been deleted!
756 return;
757
758 wxTextCtrl *tw = (wxTextCtrl *) clientData;
759 tw->SetModified(TRUE);
760}
761
762static void
763wxTextWindowModifyProc (Widget WXUNUSED(w), XtPointer clientData, XmTextVerifyCallbackStruct *cbs)
764{
765 wxTextCtrl *tw = (wxTextCtrl *) clientData;
766 tw->m_processedDefault = FALSE;
767
768 // First, do some stuff if it's a password control: in this case, we need
769 // to store the string inside the class because GetValue() can't retrieve
770 // it from the text ctrl. We do *not* do it in other circumstances because
771 // it would double the amount of memory needed.
772
773 if ( tw->GetWindowStyleFlag() & wxTE_PASSWORD )
774 {
775 MergeChangesIntoString(tw->m_value, cbs);
776
777 if ( cbs->text->length > 0 )
778 {
779 int i;
780 for (i = 0; i < cbs->text->length; ++i)
781 cbs->text->ptr[i] = '*';
782 cbs->text->ptr[i] = '\0';
783 }
784 }
785
786 if(tw->InSetValue())
787 return;
788
789 // If we're already within an OnChar, return: probably a programmatic
790 // insertion.
791 if (tw->m_tempCallbackStruct)
792 return;
793
794 // Check for a backspace
795 if (cbs->startPos == (cbs->currInsert - 1))
796 {
797 tw->DoSendEvents((void *)cbs, WXK_DELETE);
798
799 return;
800 }
801
802 // Pasting operation: let it through without calling OnChar
803 if (cbs->text->length > 1)
804 return;
805
806 // Something other than text
807 if (cbs->text->ptr == NULL)
808 return;
809
810 // normal key press
811 char ch = cbs->text->ptr[0];
812 tw->DoSendEvents((void *)cbs, ch == '\n' ? '\r' : ch);
813}
814
815static void
816wxTextWindowGainFocusProc (Widget w, XtPointer clientData, XmAnyCallbackStruct *WXUNUSED(cbs))
817{
818 if (!wxGetWindowFromTable(w))
819 return;
820
821 wxTextCtrl *tw = (wxTextCtrl *) clientData;
822 wxFocusEvent event(wxEVT_SET_FOCUS, tw->GetId());
823 event.SetEventObject(tw);
824 tw->GetEventHandler()->ProcessEvent(event);
825}
826
827static void
828wxTextWindowLoseFocusProc (Widget w, XtPointer clientData, XmAnyCallbackStruct *WXUNUSED(cbs))
829{
830 if (!wxGetWindowFromTable(w))
831 return;
832
833 wxTextCtrl *tw = (wxTextCtrl *) clientData;
834 wxFocusEvent event(wxEVT_KILL_FOCUS, tw->GetId());
835 event.SetEventObject(tw);
836 tw->GetEventHandler()->ProcessEvent(event);
837}
838
839static void wxTextWindowActivateProc(Widget w, XtPointer clientData,
840 XmAnyCallbackStruct *WXUNUSED(ptr))
841{
842 if (!wxGetWindowFromTable(w))
843 return;
844
845 wxTextCtrl *tw = (wxTextCtrl *) clientData;
846
847 if (tw->InSetValue())
848 return;
849
850 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER);
851 event.SetId(tw->GetId());
852 event.SetEventObject(tw);
853 tw->ProcessCommand(event);
854}
855
856void wxTextCtrl::OnCut(wxCommandEvent& WXUNUSED(event))
857{
858 Cut();
859}
860
861void wxTextCtrl::OnCopy(wxCommandEvent& WXUNUSED(event))
862{
863 Copy();
864}
865
866void wxTextCtrl::OnPaste(wxCommandEvent& WXUNUSED(event))
867{
868 Paste();
869}
870
871void wxTextCtrl::OnUndo(wxCommandEvent& WXUNUSED(event))
872{
873 Undo();
874}
875
876void wxTextCtrl::OnRedo(wxCommandEvent& WXUNUSED(event))
877{
878 Redo();
879}
880
881void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event)
882{
883 event.Enable( CanCut() );
884}
885
886void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event)
887{
888 event.Enable( CanCopy() );
889}
890
891void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event)
892{
893 event.Enable( CanPaste() );
894}
895
896void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event)
897{
898 event.Enable( CanUndo() );
899}
900
901void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event)
902{
903 event.Enable( CanRedo() );
904}