]> git.saurik.com Git - wxWidgets.git/blame - src/motif/textctrl.cpp
Dialog unit mods; wxProp tidying
[wxWidgets.git] / src / motif / textctrl.cpp
CommitLineData
4bb6408c
JS
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
02e8b2f9
JS
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
40static void
41wxTextWindowChangedProc (Widget w, XtPointer clientData, XtPointer ptr);
42static void
43wxTextWindowModifyProc (Widget w, XtPointer clientData, XmTextVerifyCallbackStruct *cbs);
44static void
45wxTextWindowGainFocusProc (Widget w, XtPointer clientData, XmAnyCallbackStruct *cbs);
46static void
47wxTextWindowLoseFocusProc (Widget w, XtPointer clientData, XmAnyCallbackStruct *cbs);
dfc54541
JS
48static void wxTextWindowActivateProc(Widget w, XtPointer clientData,
49 XmAnyCallbackStruct *ptr);
02e8b2f9 50
4bb6408c
JS
51#if !USE_SHARED_LIBRARY
52IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
53
54BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
55 EVT_DROP_FILES(wxTextCtrl::OnDropFiles)
02e8b2f9 56 EVT_CHAR(wxTextCtrl::OnChar)
4bb6408c
JS
57END_EVENT_TABLE()
58#endif
59
60// Text item
61wxTextCtrl::wxTextCtrl()
62#ifndef NO_TEXT_WINDOW_STREAM
63 :streambuf()
64#endif
65{
66 m_fileName = "";
02e8b2f9
JS
67 m_tempCallbackStruct = (void*) NULL;
68 m_modified = FALSE;
dfc54541
JS
69 m_processedDefault = FALSE;
70 m_inSetValue = FALSE;
4bb6408c
JS
71}
72
73bool 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{
02e8b2f9
JS
80 m_tempCallbackStruct = (void*) NULL;
81 m_modified = FALSE;
dfc54541 82 m_processedDefault = FALSE;
4bb6408c 83 m_fileName = "";
dfc54541 84 m_inSetValue = FALSE;
02e8b2f9 85
4bb6408c
JS
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
02e8b2f9
JS
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
dfc54541 140 XtAddCallback((Widget) m_mainWidget, XmNactivateCallback, (XtCallbackProc)wxTextWindowActivateProc, (XtPointer)this);
02e8b2f9
JS
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
4bb6408c
JS
152 return TRUE;
153}
154
02e8b2f9 155WXWidget wxTextCtrl::GetTopWidget() const
4bb6408c 156{
dfc54541 157 return ((m_windowStyle & wxTE_MULTILINE) ? (WXWidget) XtParent((Widget) m_mainWidget) : m_mainWidget);
4bb6408c
JS
158}
159
02e8b2f9 160wxString wxTextCtrl::GetValue() const
4bb6408c 161{
dfc54541
JS
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 }
4bb6408c
JS
178}
179
02e8b2f9 180void wxTextCtrl::SetValue(const wxString& value)
4bb6408c 181{
dfc54541
JS
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;
4bb6408c
JS
188}
189
190// Clipboard operations
191void wxTextCtrl::Copy()
192{
dfc54541 193 XmTextCopy((Widget) m_mainWidget, CurrentTime);
4bb6408c
JS
194}
195
196void wxTextCtrl::Cut()
197{
dfc54541 198 XmTextCut((Widget) m_mainWidget, CurrentTime);
4bb6408c
JS
199}
200
201void wxTextCtrl::Paste()
202{
dfc54541 203 XmTextPaste((Widget) m_mainWidget);
4bb6408c
JS
204}
205
206void wxTextCtrl::SetEditable(bool editable)
207{
dfc54541 208 XmTextSetEditable((Widget) m_mainWidget, (Boolean) editable);
4bb6408c
JS
209}
210
211void wxTextCtrl::SetInsertionPoint(long pos)
212{
dfc54541 213 XmTextSetInsertionPosition ((Widget) m_mainWidget, (XmTextPosition) pos);
4bb6408c
JS
214}
215
216void wxTextCtrl::SetInsertionPointEnd()
217{
218 long pos = GetLastPosition();
219 SetInsertionPoint(pos);
220}
221
222long wxTextCtrl::GetInsertionPoint() const
223{
dfc54541 224 return (long) XmTextGetInsertionPosition ((Widget) m_mainWidget);
4bb6408c
JS
225}
226
227long wxTextCtrl::GetLastPosition() const
228{
dfc54541 229 return (long) XmTextGetLastPosition ((Widget) m_mainWidget);
4bb6408c
JS
230}
231
232void wxTextCtrl::Replace(long from, long to, const wxString& value)
233{
dfc54541
JS
234 XmTextReplace ((Widget) m_mainWidget, (XmTextPosition) from, (XmTextPosition) to,
235 (char*) (const char*) value);
4bb6408c
JS
236}
237
238void wxTextCtrl::Remove(long from, long to)
239{
dfc54541
JS
240 XmTextSetSelection ((Widget) m_mainWidget, (XmTextPosition) from, (XmTextPosition) to,
241 (Time) 0);
242 XmTextRemove ((Widget) m_mainWidget);
4bb6408c
JS
243}
244
245void wxTextCtrl::SetSelection(long from, long to)
246{
dfc54541
JS
247 XmTextSetSelection ((Widget) m_mainWidget, (XmTextPosition) from, (XmTextPosition) to,
248 (Time) 0);
4bb6408c
JS
249}
250
251bool 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.
295bool 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
313void wxTextCtrl::WriteText(const wxString& text)
314{
dfc54541
JS
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;
4bb6408c
JS
321}
322
323void wxTextCtrl::Clear()
324{
02e8b2f9 325 XmTextSetString ((Widget) m_mainWidget, "");
02e8b2f9 326 m_modified = FALSE;
4bb6408c
JS
327}
328
329bool wxTextCtrl::IsModified() const
330{
02e8b2f9 331 return m_modified;
4bb6408c
JS
332}
333
334// Makes 'unmodified'
335void wxTextCtrl::DiscardEdits()
336{
dfc54541
JS
337 XmTextSetString ((Widget) m_mainWidget, "");
338 m_modified = FALSE;
4bb6408c
JS
339}
340
341int wxTextCtrl::GetNumberOfLines() const
342{
dfc54541
JS
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 }
4bb6408c
JS
369 return 0;
370}
371
372long wxTextCtrl::XYToPosition(long x, long y) const
373{
dfc54541
JS
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;
4bb6408c
JS
384}
385
386void wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
387{
dfc54541
JS
388 Position xx, yy;
389 XmTextPosToXY((Widget) m_mainWidget, pos, &xx, &yy);
390 *x = xx; *y = yy;
4bb6408c
JS
391}
392
393void wxTextCtrl::ShowPosition(long pos)
394{
dfc54541 395 XmTextShowPosition ((Widget) m_mainWidget, (XmTextPosition) pos);
4bb6408c
JS
396}
397
398int wxTextCtrl::GetLineLength(long lineNo) const
399{
dfc54541
JS
400 wxString str = GetLineText (lineNo);
401 return (int) str.Length();
4bb6408c
JS
402}
403
404wxString wxTextCtrl::GetLineText(long lineNo) const
405{
dfc54541
JS
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;
4bb6408c
JS
427}
428
429/*
430 * Text item
431 */
432
433void wxTextCtrl::Command(wxCommandEvent & event)
434{
435 SetValue (event.GetString());
436 ProcessCommand (event);
437}
438
439void 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
458int 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//=========================================================================
522int 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//=========================================================================
549int wxTextCtrl::underflow()
550{
551 return EOF;
552}
553#endif
554
555wxTextCtrl& wxTextCtrl::operator<<(const wxString& s)
556{
557 WriteText(s);
558 return *this;
559}
560
561wxTextCtrl& wxTextCtrl::operator<<(float f)
562{
563 wxString str;
564 str.Printf("%.2f", f);
565 WriteText(str);
566 return *this;
567}
568
569wxTextCtrl& wxTextCtrl::operator<<(double d)
570{
571 wxString str;
572 str.Printf("%.2f", d);
573 WriteText(str);
574 return *this;
575}
576
577wxTextCtrl& wxTextCtrl::operator<<(int i)
578{
579 wxString str;
580 str.Printf("%d", i);
581 WriteText(str);
582 return *this;
583}
584
585wxTextCtrl& wxTextCtrl::operator<<(long i)
586{
587 wxString str;
588 str.Printf("%ld", i);
589 WriteText(str);
590 return *this;
591}
592
593wxTextCtrl& 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
02e8b2f9
JS
603void wxTextCtrl::OnChar(wxKeyEvent& event)
604{
dfc54541
JS
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
02e8b2f9
JS
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
dfc54541 622static void wxTextWindowChangedProc (Widget w, XtPointer clientData, XtPointer ptr)
02e8b2f9
JS
623{
624 if (!wxGetWindowFromTable(w))
625 // Widget has been deleted!
626 return;
627
628 wxTextCtrl *tw = (wxTextCtrl *) clientData;
629 tw->SetModified(TRUE);
630}
631
632static void
633wxTextWindowModifyProc (Widget w, XtPointer clientData, XmTextVerifyCallbackStruct *cbs)
634{
dfc54541
JS
635 wxTextCtrl *tw = (wxTextCtrl *) clientData;
636 tw->m_processedDefault = FALSE;
02e8b2f9 637
dfc54541
JS
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;
02e8b2f9 743
02e8b2f9
JS
744 tw->m_tempCallbackStruct = (void*) cbs;
745
746 wxKeyEvent event (wxEVT_CHAR);
747 event.SetId(tw->GetId());
02e8b2f9 748 event.SetEventObject(tw);
dfc54541 749 event.m_keyCode = (cbs->text->ptr[0] == 10 ? 13 : cbs->text->ptr[0]);
02e8b2f9
JS
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
dfc54541
JS
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 }
02e8b2f9
JS
770}
771
772static void
773wxTextWindowGainFocusProc (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
784static void
785wxTextWindowLoseFocusProc (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}
dfc54541
JS
795
796static 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}