More Motif changes (colour/font stuff)
[wxWidgets.git] / src / motif / textctrl.cpp
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 #ifdef __GNUG__
13 #pragma implementation "textctrl.h"
14 #endif
15
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <fstream.h>
19
20 #include "wx/textctrl.h"
21 #include "wx/settings.h"
22 #include "wx/filefn.h"
23 #include "wx/utils.h"
24
25 #if defined(__BORLANDC__) && !defined(__WIN32__)
26 #include <alloc.h>
27 #else
28 #ifndef __GNUWIN32__
29 #include <malloc.h>
30 #endif
31 #endif
32
33 #include <Xm/Text.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <ctype.h>
37
38 #include "wx/motif/private.h"
39
40 static void
41 wxTextWindowChangedProc (Widget w, XtPointer clientData, XtPointer ptr);
42 static void
43 wxTextWindowModifyProc (Widget w, XtPointer clientData, XmTextVerifyCallbackStruct *cbs);
44 static void
45 wxTextWindowGainFocusProc (Widget w, XtPointer clientData, XmAnyCallbackStruct *cbs);
46 static void
47 wxTextWindowLoseFocusProc (Widget w, XtPointer clientData, XmAnyCallbackStruct *cbs);
48 static void wxTextWindowActivateProc(Widget w, XtPointer clientData,
49 XmAnyCallbackStruct *ptr);
50
51 #if !USE_SHARED_LIBRARY
52 IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
53
54 BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
55 EVT_DROP_FILES(wxTextCtrl::OnDropFiles)
56 EVT_CHAR(wxTextCtrl::OnChar)
57 END_EVENT_TABLE()
58 #endif
59
60 // Text item
61 wxTextCtrl::wxTextCtrl()
62 #ifndef NO_TEXT_WINDOW_STREAM
63 :streambuf()
64 #endif
65 {
66 m_fileName = "";
67 m_tempCallbackStruct = (void*) NULL;
68 m_modified = FALSE;
69 m_processedDefault = FALSE;
70 }
71
72 bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
73 const wxString& value,
74 const wxPoint& pos,
75 const wxSize& size, long style,
76 const wxValidator& validator,
77 const wxString& name)
78 {
79 m_tempCallbackStruct = (void*) NULL;
80 m_modified = FALSE;
81 m_processedDefault = FALSE;
82 m_fileName = "";
83 m_backgroundColour = parent->GetBackgroundColour();
84 m_foregroundColour = parent->GetForegroundColour();
85
86 SetName(name);
87 SetValidator(validator);
88 if (parent) parent->AddChild(this);
89
90 m_windowStyle = style;
91
92 if ( id == -1 )
93 m_windowId = (int)NewControlId();
94 else
95 m_windowId = id;
96
97 Widget parentWidget = (Widget) parent->GetClientWidget();
98
99 bool wantHorizScrolling = ((m_windowStyle & wxHSCROLL) != 0);
100
101 // If we don't have horizontal scrollbars, we want word wrap.
102 bool wantWordWrap = !wantHorizScrolling;
103
104 if (m_windowStyle & wxTE_MULTILINE)
105 {
106 Arg args[2];
107 XtSetArg (args[0], XmNscrollHorizontal, wantHorizScrolling ? True : False);
108 XtSetArg (args[1], XmNwordWrap, wantWordWrap ? True : False);
109
110 m_mainWidget = (WXWidget) XmCreateScrolledText (parentWidget, (char*) (const char*) name, args, 2);
111
112 XtVaSetValues ((Widget) m_mainWidget,
113 XmNeditable, ((style & wxTE_READONLY) ? False : True),
114 XmNeditMode, XmMULTI_LINE_EDIT,
115 NULL);
116 XtManageChild ((Widget) m_mainWidget);
117 }
118 else
119 {
120 m_mainWidget = (WXWidget) XtVaCreateManagedWidget ((char*) (const char*) name,
121 xmTextWidgetClass, parentWidget,
122 NULL);
123
124 // TODO: Is this relevant? What does it do?
125 int noCols = 2;
126 if (!value.IsNull() && (value.Length() > (unsigned int) noCols))
127 noCols = value.Length();
128 XtVaSetValues ((Widget) m_mainWidget,
129 XmNcolumns, noCols,
130 NULL);
131 }
132
133 if (!value.IsNull())
134 XmTextSetString ((Widget) m_mainWidget, (char*) (const char*) value);
135
136 XtAddCallback((Widget) m_mainWidget, XmNvalueChangedCallback, (XtCallbackProc)wxTextWindowChangedProc, (XtPointer)this);
137
138 XtAddCallback((Widget) m_mainWidget, XmNmodifyVerifyCallback, (XtCallbackProc)wxTextWindowModifyProc, (XtPointer)this);
139
140 XtAddCallback((Widget) m_mainWidget, XmNactivateCallback, (XtCallbackProc)wxTextWindowActivateProc, (XtPointer)this);
141
142 XtAddCallback((Widget) m_mainWidget, XmNfocusCallback, (XtCallbackProc)wxTextWindowGainFocusProc, (XtPointer)this);
143
144 XtAddCallback((Widget) m_mainWidget, XmNlosingFocusCallback, (XtCallbackProc)wxTextWindowLoseFocusProc, (XtPointer)this);
145
146 SetCanAddEventHandler(TRUE);
147 AttachWidget (parent, m_mainWidget, (WXWidget) NULL, pos.x, pos.y, size.x, size.y);
148
149 SetFont(* parent->GetFont());
150 ChangeBackgroundColour();
151
152 return TRUE;
153 }
154
155 WXWidget wxTextCtrl::GetTopWidget() const
156 {
157 return ((m_windowStyle & wxTE_MULTILINE) ? (WXWidget) XtParent((Widget) m_mainWidget) : m_mainWidget);
158 }
159
160 wxString wxTextCtrl::GetValue() const
161 {
162 if (m_windowStyle & wxTE_PASSWORD)
163 return m_value;
164 else
165 {
166 char *s = XmTextGetString ((Widget) m_mainWidget);
167 if (s)
168 {
169 wxString str(s);
170 XtFree (s);
171 return str;
172 }
173 else
174 {
175 return wxEmptyString;
176 }
177 }
178 }
179
180 void wxTextCtrl::SetValue(const wxString& value)
181 {
182 wxASSERT_MSG( (!value.IsNull()), "Must not pass a null string to wxTextCtrl::SetValue." ) ;
183 m_inSetValue = TRUE;
184
185 XmTextSetString ((Widget) m_mainWidget, (char*) (const char*) value);
186
187 m_inSetValue = FALSE;
188 }
189
190 // Clipboard operations
191 void wxTextCtrl::Copy()
192 {
193 XmTextCopy((Widget) m_mainWidget, CurrentTime);
194 }
195
196 void wxTextCtrl::Cut()
197 {
198 XmTextCut((Widget) m_mainWidget, CurrentTime);
199 }
200
201 void wxTextCtrl::Paste()
202 {
203 XmTextPaste((Widget) m_mainWidget);
204 }
205
206 void wxTextCtrl::SetEditable(bool editable)
207 {
208 XmTextSetEditable((Widget) m_mainWidget, (Boolean) editable);
209 }
210
211 void wxTextCtrl::SetInsertionPoint(long pos)
212 {
213 XmTextSetInsertionPosition ((Widget) m_mainWidget, (XmTextPosition) pos);
214 }
215
216 void wxTextCtrl::SetInsertionPointEnd()
217 {
218 long pos = GetLastPosition();
219 SetInsertionPoint(pos);
220 }
221
222 long wxTextCtrl::GetInsertionPoint() const
223 {
224 return (long) XmTextGetInsertionPosition ((Widget) m_mainWidget);
225 }
226
227 long wxTextCtrl::GetLastPosition() const
228 {
229 return (long) XmTextGetLastPosition ((Widget) m_mainWidget);
230 }
231
232 void wxTextCtrl::Replace(long from, long to, const wxString& value)
233 {
234 XmTextReplace ((Widget) m_mainWidget, (XmTextPosition) from, (XmTextPosition) to,
235 (char*) (const char*) value);
236 }
237
238 void wxTextCtrl::Remove(long from, long to)
239 {
240 XmTextSetSelection ((Widget) m_mainWidget, (XmTextPosition) from, (XmTextPosition) to,
241 (Time) 0);
242 XmTextRemove ((Widget) m_mainWidget);
243 }
244
245 void wxTextCtrl::SetSelection(long from, long to)
246 {
247 XmTextSetSelection ((Widget) m_mainWidget, (XmTextPosition) from, (XmTextPosition) to,
248 (Time) 0);
249 }
250
251 bool wxTextCtrl::LoadFile(const wxString& file)
252 {
253 if (!wxFileExists(file))
254 return FALSE;
255
256 m_fileName = file;
257
258 Clear();
259
260 Widget textWidget = (Widget) m_mainWidget;
261 FILE *fp;
262
263 struct stat statb;
264 if ((stat ((char*) (const char*) file, &statb) == -1) || (statb.st_mode & S_IFMT) != S_IFREG ||
265 !(fp = fopen ((char*) (const char*) file, "r")))
266 {
267 return FALSE;
268 }
269 else
270 {
271 long len = statb.st_size;
272 char *text;
273 if (!(text = XtMalloc ((unsigned) (len + 1))))
274 {
275 fclose (fp);
276 return FALSE;
277 }
278 if (fread (text, sizeof (char), len, fp) != (size_t) len)
279 {
280 }
281 fclose (fp);
282
283 text[len] = 0;
284 XmTextSetString (textWidget, text);
285 // m_textPosition = len;
286 XtFree (text);
287 m_modified = FALSE;
288 return TRUE;
289 }
290 }
291
292 // If file is null, try saved file name first
293 // Returns TRUE if succeeds.
294 bool wxTextCtrl::SaveFile(const wxString& file)
295 {
296 wxString theFile(file);
297 if (theFile == "")
298 theFile = m_fileName;
299 if (theFile == "")
300 return FALSE;
301 m_fileName = theFile;
302
303 Widget textWidget = (Widget) m_mainWidget;
304 FILE *fp;
305
306 if (!(fp = fopen ((char*) (const char*) theFile, "w")))
307 {
308 return FALSE;
309 }
310 else
311 {
312 char *text = XmTextGetString (textWidget);
313 long len = XmTextGetLastPosition (textWidget);
314
315 if (fwrite (text, sizeof (char), len, fp) != (size_t) len)
316 {
317 // Did not write whole file
318 }
319 // Make sure newline terminates the file
320 if (text[len - 1] != '\n')
321 fputc ('\n', fp);
322
323 fclose (fp);
324 XtFree (text);
325 m_modified = FALSE;
326 return TRUE;
327 }
328 }
329
330 void wxTextCtrl::WriteText(const wxString& text)
331 {
332 long textPosition = GetInsertionPoint() + strlen (text);
333 XmTextInsert ((Widget) m_mainWidget, GetInsertionPoint(), (char*) (const char*) text);
334 XtVaSetValues ((Widget) m_mainWidget, XmNcursorPosition, textPosition, NULL);
335 SetInsertionPoint(textPosition);
336 XmTextShowPosition ((Widget) m_mainWidget, textPosition);
337 m_modified = TRUE;
338 }
339
340 void wxTextCtrl::Clear()
341 {
342 XmTextSetString ((Widget) m_mainWidget, "");
343 m_modified = FALSE;
344 }
345
346 bool wxTextCtrl::IsModified() const
347 {
348 return m_modified;
349 }
350
351 // Makes 'unmodified'
352 void wxTextCtrl::DiscardEdits()
353 {
354 XmTextSetString ((Widget) m_mainWidget, "");
355 m_modified = FALSE;
356 }
357
358 int wxTextCtrl::GetNumberOfLines() const
359 {
360 // HIDEOUSLY inefficient, but we have no choice.
361 char *s = XmTextGetString ((Widget) m_mainWidget);
362 if (s)
363 {
364 long i = 0;
365 int currentLine = 0;
366 bool finished = FALSE;
367 while (!finished)
368 {
369 int ch = s[i];
370 if (ch == '\n')
371 {
372 currentLine++;
373 i++;
374 }
375 else if (ch == 0)
376 {
377 finished = TRUE;
378 }
379 else
380 i++;
381 }
382
383 XtFree (s);
384 return currentLine;
385 }
386 return 0;
387 }
388
389 long wxTextCtrl::XYToPosition(long x, long y) const
390 {
391 /* It seems, that there is a bug in some versions of the Motif library,
392 so the original wxWin-Code doesn't work. */
393 /*
394 Widget textWidget = (Widget) handle;
395 return (long) XmTextXYToPos (textWidget, (Position) x, (Position) y);
396 */
397 /* Now a little workaround: */
398 long r=0;
399 for (int i=0; i<y; i++) r+=(GetLineLength(i)+1);
400 return r+x;
401 }
402
403 void wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
404 {
405 Position xx, yy;
406 XmTextPosToXY((Widget) m_mainWidget, pos, &xx, &yy);
407 *x = xx; *y = yy;
408 }
409
410 void wxTextCtrl::ShowPosition(long pos)
411 {
412 XmTextShowPosition ((Widget) m_mainWidget, (XmTextPosition) pos);
413 }
414
415 int wxTextCtrl::GetLineLength(long lineNo) const
416 {
417 wxString str = GetLineText (lineNo);
418 return (int) str.Length();
419 }
420
421 wxString wxTextCtrl::GetLineText(long lineNo) const
422 {
423 // HIDEOUSLY inefficient, but we have no choice.
424 char *s = XmTextGetString ((Widget) m_mainWidget);
425
426 if (s)
427 {
428 wxString buf("");
429 long i;
430 int currentLine = 0;
431 for (i = 0; currentLine != lineNo && s[i]; i++ )
432 if (s[i] == '\n')
433 currentLine++;
434 // Now get the text
435 int j;
436 for (j = 0; s[i] && s[i] != '\n'; i++, j++ )
437 buf += s[i];
438
439 XtFree(s);
440 return buf;
441 }
442 else
443 return wxEmptyString;
444 }
445
446 /*
447 * Text item
448 */
449
450 void wxTextCtrl::Command(wxCommandEvent & event)
451 {
452 SetValue (event.GetString());
453 ProcessCommand (event);
454 }
455
456 void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event)
457 {
458 // By default, load the first file into the text window.
459 if (event.GetNumberOfFiles() > 0)
460 {
461 LoadFile(event.GetFiles()[0]);
462 }
463 }
464
465 // The streambuf code was partly taken from chapter 3 by Jerry Schwarz of
466 // AT&T's "C++ Lanuage System Release 3.0 Library Manual" - Stein Somers
467
468 //=========================================================================
469 // Called then the buffer is full (gcc 2.6.3)
470 // or when "endl" is output (Borland 4.5)
471 //=========================================================================
472 // Class declaration using multiple inheritance doesn't work properly for
473 // Borland. See note in wb_text.h.
474 #ifndef NO_TEXT_WINDOW_STREAM
475 int wxTextCtrl::overflow(int c)
476 {
477 // Make sure there is a holding area
478 if ( allocate()==EOF )
479 {
480 wxError("Streambuf allocation failed","Internal error");
481 return EOF;
482 }
483
484 // Verify that there are no characters in get area
485 if ( gptr() && gptr() < egptr() )
486 {
487 wxError("Who's trespassing my get area?","Internal error");
488 return EOF;
489 }
490
491 // Reset get area
492 setg(0,0,0);
493
494 // Make sure there is a put area
495 if ( ! pptr() )
496 {
497 /* This doesn't seem to be fatal so comment out error message */
498 // wxError("Put area not opened","Internal error");
499 setp( base(), base() );
500 }
501
502 // Determine how many characters have been inserted but no consumed
503 int plen = pptr() - pbase();
504
505 // Now Jerry relies on the fact that the buffer is at least 2 chars
506 // long, but the holding area "may be as small as 1" ???
507 // And we need an additional \0, so let's keep this inefficient but
508 // safe copy.
509
510 // If c!=EOF, it is a character that must also be comsumed
511 int xtra = c==EOF? 0 : 1;
512
513 // Write temporary C-string to wxTextWindow
514 {
515 char *txt = new char[plen+xtra+1];
516 memcpy(txt, pbase(), plen);
517 txt[plen] = (char)c; // append c
518 txt[plen+xtra] = '\0'; // append '\0' or overwrite c
519 // If the put area already contained \0, output will be truncated there
520 WriteText(txt);
521 delete[] txt;
522 }
523
524 // Reset put area
525 setp(pbase(), epptr());
526
527 #if defined(__WATCOMC__)
528 return __NOT_EOF;
529 #elif defined(zapeof) // HP-UX (all cfront based?)
530 return zapeof(c);
531 #else
532 return c!=EOF ? c : 0; // this should make everybody happy
533 #endif
534 }
535
536 //=========================================================================
537 // called then "endl" is output (gcc) or then explicit sync is done (Borland)
538 //=========================================================================
539 int wxTextCtrl::sync()
540 {
541 // Verify that there are no characters in get area
542 if ( gptr() && gptr() < egptr() )
543 {
544 wxError("Who's trespassing my get area?","Internal error");
545 return EOF;
546 }
547
548 if ( pptr() && pptr() > pbase() ) return overflow(EOF);
549
550 return 0;
551 /* OLD CODE
552 int len = pptr() - pbase();
553 char *txt = new char[len+1];
554 strncpy(txt, pbase(), len);
555 txt[len] = '\0';
556 (*this) << txt;
557 setp(pbase(), epptr());
558 delete[] txt;
559 return 0;
560 */
561 }
562
563 //=========================================================================
564 // Should not be called by a "ostream". Used by a "istream"
565 //=========================================================================
566 int wxTextCtrl::underflow()
567 {
568 return EOF;
569 }
570 #endif
571
572 wxTextCtrl& wxTextCtrl::operator<<(const wxString& s)
573 {
574 WriteText(s);
575 return *this;
576 }
577
578 wxTextCtrl& wxTextCtrl::operator<<(float f)
579 {
580 wxString str;
581 str.Printf("%.2f", f);
582 WriteText(str);
583 return *this;
584 }
585
586 wxTextCtrl& wxTextCtrl::operator<<(double d)
587 {
588 wxString str;
589 str.Printf("%.2f", d);
590 WriteText(str);
591 return *this;
592 }
593
594 wxTextCtrl& wxTextCtrl::operator<<(int i)
595 {
596 wxString str;
597 str.Printf("%d", i);
598 WriteText(str);
599 return *this;
600 }
601
602 wxTextCtrl& wxTextCtrl::operator<<(long i)
603 {
604 wxString str;
605 str.Printf("%ld", i);
606 WriteText(str);
607 return *this;
608 }
609
610 wxTextCtrl& wxTextCtrl::operator<<(const char c)
611 {
612 char buf[2];
613
614 buf[0] = c;
615 buf[1] = 0;
616 WriteText(buf);
617 return *this;
618 }
619
620 void wxTextCtrl::OnChar(wxKeyEvent& event)
621 {
622 // Indicates that we should generate a normal command, because
623 // we're letting default behaviour happen (otherwise it's vetoed
624 // by virtue of overriding OnChar)
625 m_processedDefault = TRUE;
626
627 if (m_tempCallbackStruct)
628 {
629 XmTextVerifyCallbackStruct *textStruct =
630 (XmTextVerifyCallbackStruct *) m_tempCallbackStruct;
631 textStruct->doit = True;
632 if (isascii(event.m_keyCode) && (textStruct->text->length == 1))
633 {
634 textStruct->text->ptr[0] = ((event.m_keyCode == WXK_RETURN) ? 10 : event.m_keyCode);
635 }
636 }
637 }
638
639 void wxTextCtrl::ChangeFont()
640 {
641 wxWindow::ChangeFont();
642 }
643
644 void wxTextCtrl::ChangeBackgroundColour()
645 {
646 wxWindow::ChangeBackgroundColour();
647 }
648
649 void wxTextCtrl::ChangeForegroundColour()
650 {
651 wxWindow::ChangeForegroundColour();
652 }
653
654 static void wxTextWindowChangedProc (Widget w, XtPointer clientData, XtPointer ptr)
655 {
656 if (!wxGetWindowFromTable(w))
657 // Widget has been deleted!
658 return;
659
660 wxTextCtrl *tw = (wxTextCtrl *) clientData;
661 tw->SetModified(TRUE);
662 }
663
664 static void
665 wxTextWindowModifyProc (Widget w, XtPointer clientData, XmTextVerifyCallbackStruct *cbs)
666 {
667 wxTextCtrl *tw = (wxTextCtrl *) clientData;
668 tw->m_processedDefault = FALSE;
669
670 // First, do some stuff if it's a password control.
671 // (What does this do exactly?)
672
673 if (tw->GetWindowStyleFlag() & wxTE_PASSWORD)
674 {
675 /* _sm_
676 * At least on my system (SunOS 4.1.3 + Motif 1.2), you need to think of
677 * every event as a replace event. cbs->text->ptr gives the replacement
678 * text, cbs->startPos gives the index of the first char affected by the
679 * replace, and cbs->endPos gives the index one more than the last char
680 * affected by the replace (startPos == endPos implies an empty range).
681 * Hence, a deletion is represented by replacing all input text with a
682 * blank string ("", *not* NULL!). A simple insertion that does not
683 * overwrite any text has startPos == endPos.
684 */
685
686 if (tw->m_value.IsNull())
687 {
688 tw->m_value = cbs->text->ptr;
689 }
690 else
691 {
692 char * passwd = (char*) (const char*) tw->m_value; // Set up a more convenient alias.
693
694 int len = passwd ? strlen(passwd) : 0; // Enough room for old text
695 len += strlen(cbs->text->ptr) + 1; // + new text (if any) + NUL
696 len -= cbs->endPos - cbs->startPos; // - text from affected region.
697
698 char * newS = new char [len];
699 char * p = passwd, * dest = newS, * insert = cbs->text->ptr;
700
701 // Copy (old) text from passwd, up to the start posn of the change.
702 int i;
703 for (i = 0; i < cbs->startPos; ++i)
704 *dest++ = *p++;
705
706 // Copy the text to be inserted).
707 while (*insert)
708 *dest++ = *insert++;
709
710 // Finally, copy into newS any remaining text from passwd[endPos] on.
711 for (p = passwd + cbs->endPos; *p; )
712 *dest++ = *p++;
713 *dest = 0;
714
715 tw->m_value = newS;
716
717 delete[] newS;
718 }
719
720 if (cbs->text->length>0)
721 {
722 int i;
723 for (i = 0; i < cbs->text->length; ++i)
724 cbs->text->ptr[i] = '*';
725 cbs->text->ptr[i] = 0;
726 }
727 }
728
729 // If we're already within an OnChar, return: probably
730 // a programmatic insertion.
731 if (tw->m_tempCallbackStruct)
732 return;
733
734 // Check for a backspace
735 if (cbs->startPos == (cbs->currInsert - 1))
736 {
737 tw->m_tempCallbackStruct = (void*) cbs;
738
739 wxKeyEvent event (wxEVT_CHAR);
740 event.SetId(tw->GetId());
741 event.m_keyCode = WXK_DELETE;
742 event.SetEventObject(tw);
743
744 // Only if wxTextCtrl::OnChar is called
745 // will this be set to True (and the character
746 // passed through)
747 cbs->doit = False;
748
749 tw->GetEventHandler()->ProcessEvent(event);
750
751 tw->m_tempCallbackStruct = NULL;
752
753 if (tw->InSetValue())
754 return;
755
756 if (tw->m_processedDefault)
757 {
758 // Can generate a command
759 wxCommandEvent commandEvent(wxEVT_COMMAND_TEXT_UPDATED, tw->GetId());
760 commandEvent.SetEventObject(tw);
761 tw->ProcessCommand(commandEvent);
762 }
763
764 return;
765 }
766
767 // Pasting operation: let it through without
768 // calling OnChar
769 if (cbs->text->length > 1)
770 return;
771
772 // Something other than text
773 if (cbs->text->ptr == NULL)
774 return;
775
776 tw->m_tempCallbackStruct = (void*) cbs;
777
778 wxKeyEvent event (wxEVT_CHAR);
779 event.SetId(tw->GetId());
780 event.SetEventObject(tw);
781 event.m_keyCode = (cbs->text->ptr[0] == 10 ? 13 : cbs->text->ptr[0]);
782
783 // Only if wxTextCtrl::OnChar is called
784 // will this be set to True (and the character
785 // passed through)
786 cbs->doit = False;
787
788 tw->GetEventHandler()->ProcessEvent(event);
789
790 tw->m_tempCallbackStruct = NULL;
791
792 if (tw->InSetValue())
793 return;
794
795 if (tw->m_processedDefault)
796 {
797 // Can generate a command
798 wxCommandEvent commandEvent(wxEVT_COMMAND_TEXT_UPDATED, tw->GetId());
799 commandEvent.SetEventObject(tw);
800 tw->ProcessCommand(commandEvent);
801 }
802 }
803
804 static void
805 wxTextWindowGainFocusProc (Widget w, XtPointer clientData, XmAnyCallbackStruct *cbs)
806 {
807 if (!wxGetWindowFromTable(w))
808 return;
809
810 wxTextCtrl *tw = (wxTextCtrl *) clientData;
811 wxFocusEvent event(wxEVT_SET_FOCUS, tw->GetId());
812 event.SetEventObject(tw);
813 tw->GetEventHandler()->ProcessEvent(event);
814 }
815
816 static void
817 wxTextWindowLoseFocusProc (Widget w, XtPointer clientData, XmAnyCallbackStruct *cbs)
818 {
819 if (!wxGetWindowFromTable(w))
820 return;
821
822 wxTextCtrl *tw = (wxTextCtrl *) clientData;
823 wxFocusEvent event(wxEVT_KILL_FOCUS, tw->GetId());
824 event.SetEventObject(tw);
825 tw->GetEventHandler()->ProcessEvent(event);
826 }
827
828 static void wxTextWindowActivateProc(Widget w, XtPointer clientData,
829 XmAnyCallbackStruct *ptr)
830 {
831 if (!wxGetWindowFromTable(w))
832 return;
833
834 wxTextCtrl *tw = (wxTextCtrl *) clientData;
835 /*
836 case XmCR_ACTIVATE:
837 type_event = wxEVENT_TYPE_TEXT_ENTER_COMMAND ;
838 break;
839 default:
840 type_event = wxEVENT_TYPE_TEXT_COMMAND ;
841 break;
842 }
843 */
844
845 if (tw->InSetValue())
846 return;
847
848 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER);
849 event.SetId(tw->GetId());
850 event.SetEventObject(tw);
851 tw->ProcessCommand(event);
852 }