]> git.saurik.com Git - wxWidgets.git/blame - src/motif/textctrl.cpp
1. Split{Horizontal|Vertical} now accept negative args to set the
[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 69 m_processedDefault = FALSE;
4bb6408c
JS
70}
71
72bool 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{
02e8b2f9
JS
79 m_tempCallbackStruct = (void*) NULL;
80 m_modified = FALSE;
dfc54541 81 m_processedDefault = FALSE;
4bb6408c 82 m_fileName = "";
0d57be45
JS
83 m_backgroundColour = parent->GetBackgroundColour();
84 m_foregroundColour = parent->GetForegroundColour();
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());
0d57be45 150 ChangeBackgroundColour();
02e8b2f9 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
1a3ac83f
JS
260 Widget textWidget = (Widget) m_mainWidget;
261 FILE *fp;
4bb6408c 262
1a3ac83f
JS
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")))
4bb6408c 266 {
1a3ac83f
JS
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;
4bb6408c 289 }
4bb6408c
JS
290}
291
292// If file is null, try saved file name first
293// Returns TRUE if succeeds.
294bool 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
1a3ac83f
JS
303 Widget textWidget = (Widget) m_mainWidget;
304 FILE *fp;
4bb6408c 305
1a3ac83f
JS
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);
4bb6408c 314
1a3ac83f
JS
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 }
4bb6408c
JS
328}
329
330void wxTextCtrl::WriteText(const wxString& text)
331{
dfc54541
JS
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;
4bb6408c
JS
338}
339
340void wxTextCtrl::Clear()
341{
02e8b2f9 342 XmTextSetString ((Widget) m_mainWidget, "");
02e8b2f9 343 m_modified = FALSE;
4bb6408c
JS
344}
345
346bool wxTextCtrl::IsModified() const
347{
02e8b2f9 348 return m_modified;
4bb6408c
JS
349}
350
351// Makes 'unmodified'
352void wxTextCtrl::DiscardEdits()
353{
dfc54541
JS
354 XmTextSetString ((Widget) m_mainWidget, "");
355 m_modified = FALSE;
4bb6408c
JS
356}
357
358int wxTextCtrl::GetNumberOfLines() const
359{
dfc54541
JS
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 }
4bb6408c
JS
386 return 0;
387}
388
389long wxTextCtrl::XYToPosition(long x, long y) const
390{
dfc54541
JS
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;
4bb6408c
JS
401}
402
403void wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
404{
dfc54541
JS
405 Position xx, yy;
406 XmTextPosToXY((Widget) m_mainWidget, pos, &xx, &yy);
407 *x = xx; *y = yy;
4bb6408c
JS
408}
409
410void wxTextCtrl::ShowPosition(long pos)
411{
dfc54541 412 XmTextShowPosition ((Widget) m_mainWidget, (XmTextPosition) pos);
4bb6408c
JS
413}
414
415int wxTextCtrl::GetLineLength(long lineNo) const
416{
dfc54541
JS
417 wxString str = GetLineText (lineNo);
418 return (int) str.Length();
4bb6408c
JS
419}
420
421wxString wxTextCtrl::GetLineText(long lineNo) const
422{
dfc54541
JS
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;
4bb6408c
JS
444}
445
446/*
447 * Text item
448 */
449
450void wxTextCtrl::Command(wxCommandEvent & event)
451{
452 SetValue (event.GetString());
453 ProcessCommand (event);
454}
455
456void 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
475int 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//=========================================================================
539int 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//=========================================================================
566int wxTextCtrl::underflow()
567{
568 return EOF;
569}
570#endif
571
572wxTextCtrl& wxTextCtrl::operator<<(const wxString& s)
573{
574 WriteText(s);
575 return *this;
576}
577
578wxTextCtrl& wxTextCtrl::operator<<(float f)
579{
580 wxString str;
581 str.Printf("%.2f", f);
582 WriteText(str);
583 return *this;
584}
585
586wxTextCtrl& wxTextCtrl::operator<<(double d)
587{
588 wxString str;
589 str.Printf("%.2f", d);
590 WriteText(str);
591 return *this;
592}
593
594wxTextCtrl& wxTextCtrl::operator<<(int i)
595{
596 wxString str;
597 str.Printf("%d", i);
598 WriteText(str);
599 return *this;
600}
601
602wxTextCtrl& wxTextCtrl::operator<<(long i)
603{
604 wxString str;
605 str.Printf("%ld", i);
606 WriteText(str);
607 return *this;
608}
609
610wxTextCtrl& 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
02e8b2f9
JS
620void wxTextCtrl::OnChar(wxKeyEvent& event)
621{
dfc54541
JS
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
02e8b2f9
JS
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
0d57be45
JS
639void wxTextCtrl::ChangeFont()
640{
641 // TODO
642}
643
644void wxTextCtrl::ChangeBackgroundColour()
645{
646 // TODO
647}
648
649void wxTextCtrl::ChangeForegroundColour()
650{
651 // TODO
652}
653
dfc54541 654static void wxTextWindowChangedProc (Widget w, XtPointer clientData, XtPointer ptr)
02e8b2f9
JS
655{
656 if (!wxGetWindowFromTable(w))
657 // Widget has been deleted!
658 return;
659
660 wxTextCtrl *tw = (wxTextCtrl *) clientData;
661 tw->SetModified(TRUE);
662}
663
664static void
665wxTextWindowModifyProc (Widget w, XtPointer clientData, XmTextVerifyCallbackStruct *cbs)
666{
dfc54541
JS
667 wxTextCtrl *tw = (wxTextCtrl *) clientData;
668 tw->m_processedDefault = FALSE;
02e8b2f9 669
dfc54541
JS
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
a4294b78 753 if (tw->InSetValue())
dfc54541
JS
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;
02e8b2f9 775
02e8b2f9
JS
776 tw->m_tempCallbackStruct = (void*) cbs;
777
778 wxKeyEvent event (wxEVT_CHAR);
779 event.SetId(tw->GetId());
02e8b2f9 780 event.SetEventObject(tw);
dfc54541 781 event.m_keyCode = (cbs->text->ptr[0] == 10 ? 13 : cbs->text->ptr[0]);
02e8b2f9
JS
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
a4294b78 792 if (tw->InSetValue())
dfc54541
JS
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 }
02e8b2f9
JS
802}
803
804static void
805wxTextWindowGainFocusProc (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
816static void
817wxTextWindowLoseFocusProc (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}
dfc54541
JS
827
828static 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
a4294b78 845 if (tw->InSetValue())
dfc54541
JS
846 return;
847
848 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER);
849 event.SetId(tw->GetId());
850 event.SetEventObject(tw);
851 tw->ProcessCommand(event);
852}