]> git.saurik.com Git - wxWidgets.git/blob - src/motif/textctrl.cpp
More Motif 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 m_inSetValue = FALSE;
71 }
72
73 bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
74 const wxString& value,
75 const wxPoint& pos,
76 const wxSize& size, long style,
77 const wxValidator& validator,
78 const wxString& name)
79 {
80 m_tempCallbackStruct = (void*) NULL;
81 m_modified = FALSE;
82 m_processedDefault = FALSE;
83 m_fileName = "";
84 m_inSetValue = FALSE;
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 ChangeColour(m_mainWidget);
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 ifstream input((char*) (const char*) file, ios::nocreate | ios::in);
261
262 if (!input.bad())
263 {
264 struct stat stat_buf;
265 if (stat(file, &stat_buf) < 0)
266 return FALSE;
267 // This may need to be a bigger buffer than the file size suggests,
268 // if it's a UNIX file. Give it an extra 1000 just in case.
269 char *tmp_buffer = (char*)malloc((size_t)(stat_buf.st_size+1+1000));
270 long no_lines = 0;
271 long pos = 0;
272 while (!input.eof() && input.peek() != EOF)
273 {
274 input.getline(wxBuffer, 500);
275 int len = strlen(wxBuffer);
276 wxBuffer[len] = 13;
277 wxBuffer[len+1] = 10;
278 wxBuffer[len+2] = 0;
279 strcpy(tmp_buffer+pos, wxBuffer);
280 pos += strlen(wxBuffer);
281 no_lines++;
282 }
283
284 // TODO add line
285
286 free(tmp_buffer);
287
288 return TRUE;
289 }
290 return FALSE;
291 }
292
293 // If file is null, try saved file name first
294 // Returns TRUE if succeeds.
295 bool wxTextCtrl::SaveFile(const wxString& file)
296 {
297 wxString theFile(file);
298 if (theFile == "")
299 theFile = m_fileName;
300 if (theFile == "")
301 return FALSE;
302 m_fileName = theFile;
303
304 ofstream output((char*) (const char*) theFile);
305 if (output.bad())
306 return FALSE;
307
308 // TODO get and save text
309
310 return FALSE;
311 }
312
313 void wxTextCtrl::WriteText(const wxString& text)
314 {
315 long textPosition = GetInsertionPoint() + strlen (text);
316 XmTextInsert ((Widget) m_mainWidget, GetInsertionPoint(), (char*) (const char*) text);
317 XtVaSetValues ((Widget) m_mainWidget, XmNcursorPosition, textPosition, NULL);
318 SetInsertionPoint(textPosition);
319 XmTextShowPosition ((Widget) m_mainWidget, textPosition);
320 m_modified = TRUE;
321 }
322
323 void wxTextCtrl::Clear()
324 {
325 XmTextSetString ((Widget) m_mainWidget, "");
326 m_modified = FALSE;
327 }
328
329 bool wxTextCtrl::IsModified() const
330 {
331 return m_modified;
332 }
333
334 // Makes 'unmodified'
335 void wxTextCtrl::DiscardEdits()
336 {
337 XmTextSetString ((Widget) m_mainWidget, "");
338 m_modified = FALSE;
339 }
340
341 int wxTextCtrl::GetNumberOfLines() const
342 {
343 // HIDEOUSLY inefficient, but we have no choice.
344 char *s = XmTextGetString ((Widget) m_mainWidget);
345 if (s)
346 {
347 long i = 0;
348 int currentLine = 0;
349 bool finished = FALSE;
350 while (!finished)
351 {
352 int ch = s[i];
353 if (ch == '\n')
354 {
355 currentLine++;
356 i++;
357 }
358 else if (ch == 0)
359 {
360 finished = TRUE;
361 }
362 else
363 i++;
364 }
365
366 XtFree (s);
367 return currentLine;
368 }
369 return 0;
370 }
371
372 long wxTextCtrl::XYToPosition(long x, long y) const
373 {
374 /* It seems, that there is a bug in some versions of the Motif library,
375 so the original wxWin-Code doesn't work. */
376 /*
377 Widget textWidget = (Widget) handle;
378 return (long) XmTextXYToPos (textWidget, (Position) x, (Position) y);
379 */
380 /* Now a little workaround: */
381 long r=0;
382 for (int i=0; i<y; i++) r+=(GetLineLength(i)+1);
383 return r+x;
384 }
385
386 void wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
387 {
388 Position xx, yy;
389 XmTextPosToXY((Widget) m_mainWidget, pos, &xx, &yy);
390 *x = xx; *y = yy;
391 }
392
393 void wxTextCtrl::ShowPosition(long pos)
394 {
395 XmTextShowPosition ((Widget) m_mainWidget, (XmTextPosition) pos);
396 }
397
398 int wxTextCtrl::GetLineLength(long lineNo) const
399 {
400 wxString str = GetLineText (lineNo);
401 return (int) str.Length();
402 }
403
404 wxString wxTextCtrl::GetLineText(long lineNo) const
405 {
406 // HIDEOUSLY inefficient, but we have no choice.
407 char *s = XmTextGetString ((Widget) m_mainWidget);
408
409 if (s)
410 {
411 wxString buf("");
412 long i;
413 int currentLine = 0;
414 for (i = 0; currentLine != lineNo && s[i]; i++ )
415 if (s[i] == '\n')
416 currentLine++;
417 // Now get the text
418 int j;
419 for (j = 0; s[i] && s[i] != '\n'; i++, j++ )
420 buf += s[i];
421
422 XtFree(s);
423 return buf;
424 }
425 else
426 return wxEmptyString;
427 }
428
429 /*
430 * Text item
431 */
432
433 void wxTextCtrl::Command(wxCommandEvent & event)
434 {
435 SetValue (event.GetString());
436 ProcessCommand (event);
437 }
438
439 void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event)
440 {
441 // By default, load the first file into the text window.
442 if (event.GetNumberOfFiles() > 0)
443 {
444 LoadFile(event.GetFiles()[0]);
445 }
446 }
447
448 // The streambuf code was partly taken from chapter 3 by Jerry Schwarz of
449 // AT&T's "C++ Lanuage System Release 3.0 Library Manual" - Stein Somers
450
451 //=========================================================================
452 // Called then the buffer is full (gcc 2.6.3)
453 // or when "endl" is output (Borland 4.5)
454 //=========================================================================
455 // Class declaration using multiple inheritance doesn't work properly for
456 // Borland. See note in wb_text.h.
457 #ifndef NO_TEXT_WINDOW_STREAM
458 int wxTextCtrl::overflow(int c)
459 {
460 // Make sure there is a holding area
461 if ( allocate()==EOF )
462 {
463 wxError("Streambuf allocation failed","Internal error");
464 return EOF;
465 }
466
467 // Verify that there are no characters in get area
468 if ( gptr() && gptr() < egptr() )
469 {
470 wxError("Who's trespassing my get area?","Internal error");
471 return EOF;
472 }
473
474 // Reset get area
475 setg(0,0,0);
476
477 // Make sure there is a put area
478 if ( ! pptr() )
479 {
480 /* This doesn't seem to be fatal so comment out error message */
481 // wxError("Put area not opened","Internal error");
482 setp( base(), base() );
483 }
484
485 // Determine how many characters have been inserted but no consumed
486 int plen = pptr() - pbase();
487
488 // Now Jerry relies on the fact that the buffer is at least 2 chars
489 // long, but the holding area "may be as small as 1" ???
490 // And we need an additional \0, so let's keep this inefficient but
491 // safe copy.
492
493 // If c!=EOF, it is a character that must also be comsumed
494 int xtra = c==EOF? 0 : 1;
495
496 // Write temporary C-string to wxTextWindow
497 {
498 char *txt = new char[plen+xtra+1];
499 memcpy(txt, pbase(), plen);
500 txt[plen] = (char)c; // append c
501 txt[plen+xtra] = '\0'; // append '\0' or overwrite c
502 // If the put area already contained \0, output will be truncated there
503 WriteText(txt);
504 delete[] txt;
505 }
506
507 // Reset put area
508 setp(pbase(), epptr());
509
510 #if defined(__WATCOMC__)
511 return __NOT_EOF;
512 #elif defined(zapeof) // HP-UX (all cfront based?)
513 return zapeof(c);
514 #else
515 return c!=EOF ? c : 0; // this should make everybody happy
516 #endif
517 }
518
519 //=========================================================================
520 // called then "endl" is output (gcc) or then explicit sync is done (Borland)
521 //=========================================================================
522 int wxTextCtrl::sync()
523 {
524 // Verify that there are no characters in get area
525 if ( gptr() && gptr() < egptr() )
526 {
527 wxError("Who's trespassing my get area?","Internal error");
528 return EOF;
529 }
530
531 if ( pptr() && pptr() > pbase() ) return overflow(EOF);
532
533 return 0;
534 /* OLD CODE
535 int len = pptr() - pbase();
536 char *txt = new char[len+1];
537 strncpy(txt, pbase(), len);
538 txt[len] = '\0';
539 (*this) << txt;
540 setp(pbase(), epptr());
541 delete[] txt;
542 return 0;
543 */
544 }
545
546 //=========================================================================
547 // Should not be called by a "ostream". Used by a "istream"
548 //=========================================================================
549 int wxTextCtrl::underflow()
550 {
551 return EOF;
552 }
553 #endif
554
555 wxTextCtrl& wxTextCtrl::operator<<(const wxString& s)
556 {
557 WriteText(s);
558 return *this;
559 }
560
561 wxTextCtrl& wxTextCtrl::operator<<(float f)
562 {
563 wxString str;
564 str.Printf("%.2f", f);
565 WriteText(str);
566 return *this;
567 }
568
569 wxTextCtrl& wxTextCtrl::operator<<(double d)
570 {
571 wxString str;
572 str.Printf("%.2f", d);
573 WriteText(str);
574 return *this;
575 }
576
577 wxTextCtrl& wxTextCtrl::operator<<(int i)
578 {
579 wxString str;
580 str.Printf("%d", i);
581 WriteText(str);
582 return *this;
583 }
584
585 wxTextCtrl& wxTextCtrl::operator<<(long i)
586 {
587 wxString str;
588 str.Printf("%ld", i);
589 WriteText(str);
590 return *this;
591 }
592
593 wxTextCtrl& wxTextCtrl::operator<<(const char c)
594 {
595 char buf[2];
596
597 buf[0] = c;
598 buf[1] = 0;
599 WriteText(buf);
600 return *this;
601 }
602
603 void wxTextCtrl::OnChar(wxKeyEvent& event)
604 {
605 // Indicates that we should generate a normal command, because
606 // we're letting default behaviour happen (otherwise it's vetoed
607 // by virtue of overriding OnChar)
608 m_processedDefault = TRUE;
609
610 if (m_tempCallbackStruct)
611 {
612 XmTextVerifyCallbackStruct *textStruct =
613 (XmTextVerifyCallbackStruct *) m_tempCallbackStruct;
614 textStruct->doit = True;
615 if (isascii(event.m_keyCode) && (textStruct->text->length == 1))
616 {
617 textStruct->text->ptr[0] = ((event.m_keyCode == WXK_RETURN) ? 10 : event.m_keyCode);
618 }
619 }
620 }
621
622 static void wxTextWindowChangedProc (Widget w, XtPointer clientData, XtPointer ptr)
623 {
624 if (!wxGetWindowFromTable(w))
625 // Widget has been deleted!
626 return;
627
628 wxTextCtrl *tw = (wxTextCtrl *) clientData;
629 tw->SetModified(TRUE);
630 }
631
632 static void
633 wxTextWindowModifyProc (Widget w, XtPointer clientData, XmTextVerifyCallbackStruct *cbs)
634 {
635 wxTextCtrl *tw = (wxTextCtrl *) clientData;
636 tw->m_processedDefault = FALSE;
637
638 // First, do some stuff if it's a password control.
639 // (What does this do exactly?)
640
641 if (tw->GetWindowStyleFlag() & wxTE_PASSWORD)
642 {
643 /* _sm_
644 * At least on my system (SunOS 4.1.3 + Motif 1.2), you need to think of
645 * every event as a replace event. cbs->text->ptr gives the replacement
646 * text, cbs->startPos gives the index of the first char affected by the
647 * replace, and cbs->endPos gives the index one more than the last char
648 * affected by the replace (startPos == endPos implies an empty range).
649 * Hence, a deletion is represented by replacing all input text with a
650 * blank string ("", *not* NULL!). A simple insertion that does not
651 * overwrite any text has startPos == endPos.
652 */
653
654 if (tw->m_value.IsNull())
655 {
656 tw->m_value = cbs->text->ptr;
657 }
658 else
659 {
660 char * passwd = (char*) (const char*) tw->m_value; // Set up a more convenient alias.
661
662 int len = passwd ? strlen(passwd) : 0; // Enough room for old text
663 len += strlen(cbs->text->ptr) + 1; // + new text (if any) + NUL
664 len -= cbs->endPos - cbs->startPos; // - text from affected region.
665
666 char * newS = new char [len];
667 char * p = passwd, * dest = newS, * insert = cbs->text->ptr;
668
669 // Copy (old) text from passwd, up to the start posn of the change.
670 int i;
671 for (i = 0; i < cbs->startPos; ++i)
672 *dest++ = *p++;
673
674 // Copy the text to be inserted).
675 while (*insert)
676 *dest++ = *insert++;
677
678 // Finally, copy into newS any remaining text from passwd[endPos] on.
679 for (p = passwd + cbs->endPos; *p; )
680 *dest++ = *p++;
681 *dest = 0;
682
683 tw->m_value = newS;
684
685 delete[] newS;
686 }
687
688 if (cbs->text->length>0)
689 {
690 int i;
691 for (i = 0; i < cbs->text->length; ++i)
692 cbs->text->ptr[i] = '*';
693 cbs->text->ptr[i] = 0;
694 }
695 }
696
697 // If we're already within an OnChar, return: probably
698 // a programmatic insertion.
699 if (tw->m_tempCallbackStruct)
700 return;
701
702 // Check for a backspace
703 if (cbs->startPos == (cbs->currInsert - 1))
704 {
705 tw->m_tempCallbackStruct = (void*) cbs;
706
707 wxKeyEvent event (wxEVT_CHAR);
708 event.SetId(tw->GetId());
709 event.m_keyCode = WXK_DELETE;
710 event.SetEventObject(tw);
711
712 // Only if wxTextCtrl::OnChar is called
713 // will this be set to True (and the character
714 // passed through)
715 cbs->doit = False;
716
717 tw->GetEventHandler()->ProcessEvent(event);
718
719 tw->m_tempCallbackStruct = NULL;
720
721 if (tw->m_inSetValue)
722 return;
723
724 if (tw->m_processedDefault)
725 {
726 // Can generate a command
727 wxCommandEvent commandEvent(wxEVT_COMMAND_TEXT_UPDATED, tw->GetId());
728 commandEvent.SetEventObject(tw);
729 tw->ProcessCommand(commandEvent);
730 }
731
732 return;
733 }
734
735 // Pasting operation: let it through without
736 // calling OnChar
737 if (cbs->text->length > 1)
738 return;
739
740 // Something other than text
741 if (cbs->text->ptr == NULL)
742 return;
743
744 tw->m_tempCallbackStruct = (void*) cbs;
745
746 wxKeyEvent event (wxEVT_CHAR);
747 event.SetId(tw->GetId());
748 event.SetEventObject(tw);
749 event.m_keyCode = (cbs->text->ptr[0] == 10 ? 13 : cbs->text->ptr[0]);
750
751 // Only if wxTextCtrl::OnChar is called
752 // will this be set to True (and the character
753 // passed through)
754 cbs->doit = False;
755
756 tw->GetEventHandler()->ProcessEvent(event);
757
758 tw->m_tempCallbackStruct = NULL;
759
760 if (tw->m_inSetValue)
761 return;
762
763 if (tw->m_processedDefault)
764 {
765 // Can generate a command
766 wxCommandEvent commandEvent(wxEVT_COMMAND_TEXT_UPDATED, tw->GetId());
767 commandEvent.SetEventObject(tw);
768 tw->ProcessCommand(commandEvent);
769 }
770 }
771
772 static void
773 wxTextWindowGainFocusProc (Widget w, XtPointer clientData, XmAnyCallbackStruct *cbs)
774 {
775 if (!wxGetWindowFromTable(w))
776 return;
777
778 wxTextCtrl *tw = (wxTextCtrl *) clientData;
779 wxFocusEvent event(wxEVT_SET_FOCUS, tw->GetId());
780 event.SetEventObject(tw);
781 tw->GetEventHandler()->ProcessEvent(event);
782 }
783
784 static void
785 wxTextWindowLoseFocusProc (Widget w, XtPointer clientData, XmAnyCallbackStruct *cbs)
786 {
787 if (!wxGetWindowFromTable(w))
788 return;
789
790 wxTextCtrl *tw = (wxTextCtrl *) clientData;
791 wxFocusEvent event(wxEVT_KILL_FOCUS, tw->GetId());
792 event.SetEventObject(tw);
793 tw->GetEventHandler()->ProcessEvent(event);
794 }
795
796 static void wxTextWindowActivateProc(Widget w, XtPointer clientData,
797 XmAnyCallbackStruct *ptr)
798 {
799 if (!wxGetWindowFromTable(w))
800 return;
801
802 wxTextCtrl *tw = (wxTextCtrl *) clientData;
803 /*
804 case XmCR_ACTIVATE:
805 type_event = wxEVENT_TYPE_TEXT_ENTER_COMMAND ;
806 break;
807 default:
808 type_event = wxEVENT_TYPE_TEXT_COMMAND ;
809 break;
810 }
811 */
812
813 if (tw->m_inSetValue)
814 return;
815
816 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER);
817 event.SetId(tw->GetId());
818 event.SetEventObject(tw);
819 tw->ProcessCommand(event);
820 }