]> git.saurik.com Git - wxWidgets.git/blame - src/motif/textctrl.cpp
Fix splitting message into title in body in MSW wxProgressDialog.
[wxWidgets.git] / src / motif / textctrl.cpp
CommitLineData
4bb6408c 1/////////////////////////////////////////////////////////////////////////////
355b4d3d 2// Name: src/motif/textctrl.cpp
4bb6408c
JS
3// Purpose: wxTextCtrl
4// Author: Julian Smart
5// Modified by:
6// Created: 17/09/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
65571936 9// Licence: wxWindows licence
4bb6408c
JS
10/////////////////////////////////////////////////////////////////////////////
11
66a007fb
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
1248b41f
MB
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
4bb6408c
JS
23#include <sys/types.h>
24#include <sys/stat.h>
66a007fb 25#include <ctype.h>
4bb6408c
JS
26
27#include "wx/textctrl.h"
de6185e2
WS
28
29#ifndef WX_PRECOMP
30 #include "wx/utils.h"
9eddec69 31 #include "wx/settings.h"
de6185e2
WS
32#endif
33
4bb6408c 34#include "wx/filefn.h"
4bb6408c 35
338dd992
JJ
36#ifdef __VMS__
37#pragma message disable nosimpint
38#endif
02e8b2f9 39#include <Xm/Text.h>
338dd992
JJ
40#ifdef __VMS__
41#pragma message enable nosimpint
42#endif
02e8b2f9
JS
43
44#include "wx/motif/private.h"
45
66a007fb
VZ
46// ----------------------------------------------------------------------------
47// private functions
48// ----------------------------------------------------------------------------
49
c27eab7e
VZ
50// helper: inserts the new text in the value of the text ctrl and returns the
51// result in place
52static void MergeChangesIntoString(wxString& value,
53 XmTextVerifyCallbackStruct *textStruct);
54
66a007fb
VZ
55// callbacks
56static void wxTextWindowChangedProc(Widget w, XtPointer clientData, XtPointer ptr);
57static void wxTextWindowModifyProc(Widget w, XtPointer clientData, XmTextVerifyCallbackStruct *cbs);
58static void wxTextWindowGainFocusProc(Widget w, XtPointer clientData, XmAnyCallbackStruct *cbs);
59static void wxTextWindowLoseFocusProc(Widget w, XtPointer clientData, XmAnyCallbackStruct *cbs);
60static void wxTextWindowActivateProc(Widget w, XtPointer clientData, XmAnyCallbackStruct *ptr);
02e8b2f9 61
9d112688 62 BEGIN_EVENT_TABLE(wxTextCtrl, wxTextCtrlBase)
66a007fb
VZ
63 EVT_DROP_FILES(wxTextCtrl::OnDropFiles)
64 EVT_CHAR(wxTextCtrl::OnChar)
e702ff0f
JS
65
66 EVT_MENU(wxID_CUT, wxTextCtrl::OnCut)
67 EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy)
68 EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste)
69 EVT_MENU(wxID_UNDO, wxTextCtrl::OnUndo)
70 EVT_MENU(wxID_REDO, wxTextCtrl::OnRedo)
71
72 EVT_UPDATE_UI(wxID_CUT, wxTextCtrl::OnUpdateCut)
73 EVT_UPDATE_UI(wxID_COPY, wxTextCtrl::OnUpdateCopy)
74 EVT_UPDATE_UI(wxID_PASTE, wxTextCtrl::OnUpdatePaste)
75 EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo)
76 EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo)
77
66a007fb 78 END_EVENT_TABLE()
4bb6408c 79
66a007fb
VZ
80// ============================================================================
81// implementation
82// ============================================================================
83
84// ----------------------------------------------------------------------------
85// wxTextCtrl
86// ----------------------------------------------------------------------------
87
4bb6408c
JS
88// Text item
89wxTextCtrl::wxTextCtrl()
4bb6408c 90{
d3b9f782 91 m_tempCallbackStruct = NULL;
7d8268a1
WS
92 m_modified = false;
93 m_processedDefault = false;
4bb6408c
JS
94}
95
66a007fb
VZ
96bool wxTextCtrl::Create(wxWindow *parent,
97 wxWindowID id,
2d120f83
JS
98 const wxString& value,
99 const wxPoint& pos,
66a007fb
VZ
100 const wxSize& size,
101 long style,
2d120f83
JS
102 const wxValidator& validator,
103 const wxString& name)
4bb6408c 104{
e1aae528
MB
105 if( !CreateControl( parent, id, pos, size, style, validator, name ) )
106 return false;
105fbe1f 107 PreCreation();
e1aae528 108
d3b9f782 109 m_tempCallbackStruct = NULL;
7d8268a1
WS
110 m_modified = false;
111 m_processedDefault = false;
66a007fb 112
02e8b2f9 113 Widget parentWidget = (Widget) parent->GetClientWidget();
66a007fb 114
996994c7 115 Bool wantHorizScroll = (m_windowStyle & wxHSCROLL) != 0 ? True : False;
02e8b2f9 116 // If we don't have horizontal scrollbars, we want word wrap.
996994c7
MB
117 // OpenMotif 2.1 crashes if wantWordWrap is True in Japanese
118 // locale (and probably other multibyte locales). The check might be
119 // more precise
120#if wxCHECK_LESSTIF() || wxCHECK_MOTIF_VERSION( 2, 2 )
121 Bool wantWordWrap = wantHorizScroll == True ? False : True;
122#else
123 Bool wantWordWrap = False;
124#endif
66a007fb 125
02e8b2f9
JS
126 if (m_windowStyle & wxTE_MULTILINE)
127 {
996994c7
MB
128 Arg args[8];
129 int count = 0;
130 XtSetArg (args[count], XmNscrollHorizontal, wantHorizScroll); ++count;
105fbe1f
MB
131 if( m_font.IsOk() )
132 XtSetArg (args[count], (String) wxFont::GetFontTag(),
133 m_font.GetFontType( XtDisplay(parentWidget) ) ); ++count;
996994c7 134 XtSetArg (args[count], XmNwordWrap, wantWordWrap); ++count;
6991087b 135 XtSetArg (args[count], XmNvalue, (const char*)value.mb_str()); ++count;
996994c7
MB
136 XtSetArg (args[count], XmNeditable,
137 style & wxTE_READONLY ? False : True); ++count;
138 XtSetArg (args[count], XmNeditMode, XmMULTI_LINE_EDIT ); ++count;
139
140 m_mainWidget =
141 (WXWidget) XmCreateScrolledText(parentWidget,
6991087b 142 name.char_str(),
996994c7
MB
143 args, count);
144
02e8b2f9
JS
145 XtManageChild ((Widget) m_mainWidget);
146 }
147 else
148 {
66a007fb
VZ
149 m_mainWidget = (WXWidget)XtVaCreateManagedWidget
150 (
6991087b 151 name.mb_str(),
66a007fb
VZ
152 xmTextWidgetClass,
153 parentWidget,
996994c7 154 wxFont::GetFontTag(), m_font.GetFontType( XtDisplay(parentWidget) ),
6991087b 155 XmNvalue, (const char*)value.mb_str(),
996994c7
MB
156 XmNeditable, (style & wxTE_READONLY) ?
157 False : True,
66a007fb
VZ
158 NULL
159 );
160
996994c7 161#if 0
02e8b2f9
JS
162 // TODO: Is this relevant? What does it do?
163 int noCols = 2;
6636ef8d 164 if (!value.empty() && (value.length() > (unsigned int) noCols))
de6185e2 165 noCols = value.length();
66a007fb
VZ
166 XtVaSetValues((Widget) m_mainWidget,
167 XmNcolumns, noCols,
168 NULL);
996994c7 169#endif
02e8b2f9 170 }
66a007fb
VZ
171
172 // remove border if asked for
173 if ( style & wxNO_BORDER )
174 {
175 XtVaSetValues((Widget)m_mainWidget,
176 XmNshadowThickness, 0,
177 NULL);
178 }
179
66a007fb 180 // install callbacks
02e8b2f9 181 XtAddCallback((Widget) m_mainWidget, XmNvalueChangedCallback, (XtCallbackProc)wxTextWindowChangedProc, (XtPointer)this);
66a007fb 182
02e8b2f9 183 XtAddCallback((Widget) m_mainWidget, XmNmodifyVerifyCallback, (XtCallbackProc)wxTextWindowModifyProc, (XtPointer)this);
66a007fb 184
dfc54541 185 XtAddCallback((Widget) m_mainWidget, XmNactivateCallback, (XtCallbackProc)wxTextWindowActivateProc, (XtPointer)this);
66a007fb 186
02e8b2f9 187 XtAddCallback((Widget) m_mainWidget, XmNfocusCallback, (XtCallbackProc)wxTextWindowGainFocusProc, (XtPointer)this);
66a007fb 188
02e8b2f9 189 XtAddCallback((Widget) m_mainWidget, XmNlosingFocusCallback, (XtCallbackProc)wxTextWindowLoseFocusProc, (XtPointer)this);
66a007fb 190
105fbe1f 191 PostCreation();
e1aae528 192 AttachWidget (parent, m_mainWidget, (WXWidget) NULL,
f9204363 193 pos.x, pos.y, size.x, size.y);
66a007fb 194
7d8268a1 195 return true;
4bb6408c
JS
196}
197
02e8b2f9 198WXWidget wxTextCtrl::GetTopWidget() const
4bb6408c 199{
ccb234b4
MB
200 return IsMultiLine() ? (WXWidget)XtParent((Widget)m_mainWidget)
201 : m_mainWidget;
4bb6408c
JS
202}
203
02e8b2f9 204wxString wxTextCtrl::GetValue() const
4bb6408c 205{
c27eab7e
VZ
206 wxString str; // result
207
dfc54541 208 if (m_windowStyle & wxTE_PASSWORD)
c27eab7e
VZ
209 {
210 // the value is stored always in m_value because it can't be retrieved
211 // from the text control
212 str = m_value;
213 }
dfc54541
JS
214 else
215 {
89954433 216 str = wxTextEntry::GetValue();
c27eab7e
VZ
217
218 if ( m_tempCallbackStruct )
dfc54541 219 {
c27eab7e
VZ
220 // the string in the control isn't yet updated, can't use it as is
221 MergeChangesIntoString(str, (XmTextVerifyCallbackStruct *)
222 m_tempCallbackStruct);
dfc54541
JS
223 }
224 }
c27eab7e
VZ
225
226 return str;
4bb6408c
JS
227}
228
ee2ec18e 229void wxTextCtrl::DoSetValue(const wxString& text, int flags)
4bb6408c 230{
7d8268a1 231 m_inSetValue = true;
66a007fb 232
6991087b 233 XmTextSetString ((Widget) m_mainWidget, text.char_str());
996994c7
MB
234 XtVaSetValues ((Widget) m_mainWidget,
235 XmNcursorPosition, text.length(),
b86de524 236 NULL);
ccb234b4 237
996994c7
MB
238 SetInsertionPoint(text.length());
239 XmTextShowPosition ((Widget) m_mainWidget, text.length());
355b4d3d 240 m_modified = true;
66a007fb 241
7d8268a1 242 m_inSetValue = false;
ee2ec18e
VZ
243
244 if ( flags & SetValue_SendEvent )
245 SendTextUpdatedEvent();
4bb6408c
JS
246}
247
4bb6408c
JS
248bool wxTextCtrl::IsModified() const
249{
02e8b2f9 250 return m_modified;
4bb6408c
JS
251}
252
3a9fa0d6
VZ
253// Makes modified or unmodified
254void wxTextCtrl::MarkDirty()
255{
7d8268a1 256 m_modified = true;
3a9fa0d6
VZ
257}
258
4bb6408c
JS
259void wxTextCtrl::DiscardEdits()
260{
7d8268a1 261 m_modified = false;
4bb6408c
JS
262}
263
264int wxTextCtrl::GetNumberOfLines() const
265{
dfc54541
JS
266 // HIDEOUSLY inefficient, but we have no choice.
267 char *s = XmTextGetString ((Widget) m_mainWidget);
268 if (s)
269 {
2d120f83
JS
270 long i = 0;
271 int currentLine = 0;
7d8268a1 272 bool finished = false;
2d120f83
JS
273 while (!finished)
274 {
275 int ch = s[i];
276 if (ch == '\n')
277 {
278 currentLine++;
279 i++;
280 }
281 else if (ch == 0)
282 {
7d8268a1 283 finished = true;
2d120f83
JS
284 }
285 else
286 i++;
287 }
66a007fb 288
2d120f83
JS
289 XtFree (s);
290 return currentLine;
dfc54541 291 }
4bb6408c
JS
292 return 0;
293}
294
295long wxTextCtrl::XYToPosition(long x, long y) const
296{
dfc54541 297/* It seems, that there is a bug in some versions of the Motif library,
2d120f83
JS
298 so the original wxWin-Code doesn't work. */
299 /*
300 Widget textWidget = (Widget) handle;
301 return (long) XmTextXYToPos (textWidget, (Position) x, (Position) y);
302 */
dfc54541
JS
303 /* Now a little workaround: */
304 long r=0;
305 for (int i=0; i<y; i++) r+=(GetLineLength(i)+1);
66a007fb 306 return r+x;
4bb6408c
JS
307}
308
813c20a6 309bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
4bb6408c 310{
dfc54541
JS
311 Position xx, yy;
312 XmTextPosToXY((Widget) m_mainWidget, pos, &xx, &yy);
813c20a6
VZ
313 if ( x )
314 *x = xx;
315 if ( y )
316 *y = yy;
317
7d8268a1 318 return true;
4bb6408c
JS
319}
320
321void wxTextCtrl::ShowPosition(long pos)
322{
dfc54541 323 XmTextShowPosition ((Widget) m_mainWidget, (XmTextPosition) pos);
4bb6408c
JS
324}
325
326int wxTextCtrl::GetLineLength(long lineNo) const
327{
dfc54541 328 wxString str = GetLineText (lineNo);
7520f3da 329 return (int) str.length();
4bb6408c
JS
330}
331
332wxString wxTextCtrl::GetLineText(long lineNo) const
333{
dfc54541
JS
334 // HIDEOUSLY inefficient, but we have no choice.
335 char *s = XmTextGetString ((Widget) m_mainWidget);
66a007fb 336
dfc54541
JS
337 if (s)
338 {
355b4d3d 339 wxString buf;
dfc54541
JS
340 long i;
341 int currentLine = 0;
342 for (i = 0; currentLine != lineNo && s[i]; i++ )
2d120f83
JS
343 if (s[i] == '\n')
344 currentLine++;
345 // Now get the text
346 int j;
347 for (j = 0; s[i] && s[i] != '\n'; i++, j++ )
348 buf += s[i];
66a007fb 349
2d120f83
JS
350 XtFree(s);
351 return buf;
352 }
353 else
354 return wxEmptyString;
4bb6408c
JS
355}
356
357/*
2d120f83
JS
358* Text item
359*/
360
4bb6408c
JS
361void wxTextCtrl::Command(wxCommandEvent & event)
362{
363 SetValue (event.GetString());
364 ProcessCommand (event);
365}
366
367void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event)
368{
369 // By default, load the first file into the text window.
370 if (event.GetNumberOfFiles() > 0)
371 {
372 LoadFile(event.GetFiles()[0]);
373 }
374}
375
02e8b2f9
JS
376void wxTextCtrl::OnChar(wxKeyEvent& event)
377{
2d120f83
JS
378 // Indicates that we should generate a normal command, because
379 // we're letting default behaviour happen (otherwise it's vetoed
380 // by virtue of overriding OnChar)
7d8268a1 381 m_processedDefault = true;
66a007fb 382
2d120f83 383 if (m_tempCallbackStruct)
02e8b2f9 384 {
2d120f83
JS
385 XmTextVerifyCallbackStruct *textStruct =
386 (XmTextVerifyCallbackStruct *) m_tempCallbackStruct;
387 textStruct->doit = True;
7a0079d5 388 if (wxIsascii(event.m_keyCode) && (textStruct->text->length == 1))
2d120f83 389 {
355b4d3d 390 textStruct->text->ptr[0] = (char)((event.m_keyCode == WXK_RETURN) ? 10 : event.m_keyCode);
2d120f83 391 }
02e8b2f9 392 }
02e8b2f9
JS
393}
394
4b5f3fe6 395void wxTextCtrl::ChangeFont(bool keepOriginalSize)
0d57be45 396{
4b5f3fe6 397 wxWindow::ChangeFont(keepOriginalSize);
0d57be45
JS
398}
399
400void wxTextCtrl::ChangeBackgroundColour()
401{
321db4b6 402 wxWindow::ChangeBackgroundColour();
66a007fb 403
94b49b93 404 /* TODO: should scrollbars be affected? Should probably have separate
2d120f83
JS
405 * function to change them (by default, taken from wxSystemSettings)
406 */
94b49b93
JS
407 if (m_windowStyle & wxTE_MULTILINE)
408 {
409 Widget parent = XtParent ((Widget) m_mainWidget);
410 Widget hsb, vsb;
66a007fb 411
94b49b93 412 XtVaGetValues (parent,
2d120f83
JS
413 XmNhorizontalScrollBar, &hsb,
414 XmNverticalScrollBar, &vsb,
415 NULL);
a756f210 416 wxColour backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
94b49b93 417 if (hsb)
7d8268a1 418 wxDoChangeBackgroundColour((WXWidget) hsb, backgroundColour, true);
94b49b93 419 if (vsb)
7d8268a1 420 wxDoChangeBackgroundColour((WXWidget) vsb, backgroundColour, true);
66a007fb 421
1119b899 422 // MBN: why change parent background?
7d8268a1 423 // DoChangeBackgroundColour((WXWidget) parent, m_backgroundColour, true);
94b49b93 424 }
0d57be45
JS
425}
426
427void wxTextCtrl::ChangeForegroundColour()
428{
321db4b6 429 wxWindow::ChangeForegroundColour();
66a007fb 430
94b49b93
JS
431 if (m_windowStyle & wxTE_MULTILINE)
432 {
433 Widget parent = XtParent ((Widget) m_mainWidget);
434 Widget hsb, vsb;
66a007fb 435
94b49b93 436 XtVaGetValues (parent,
2d120f83
JS
437 XmNhorizontalScrollBar, &hsb,
438 XmNverticalScrollBar, &vsb,
439 NULL);
66a007fb 440
2d120f83
JS
441 /* TODO: should scrollbars be affected? Should probably have separate
442 * function to change them (by default, taken from wxSystemSettings)
443 if (hsb)
94b49b93 444 DoChangeForegroundColour((WXWidget) hsb, m_foregroundColour);
2d120f83 445 if (vsb)
94b49b93 446 DoChangeForegroundColour((WXWidget) vsb, m_foregroundColour);
2d120f83 447 */
a8680e3e 448 wxDoChangeForegroundColour((WXWidget) parent, m_foregroundColour);
94b49b93 449 }
0d57be45
JS
450}
451
c27eab7e
VZ
452void wxTextCtrl::DoSendEvents(void *wxcbs, long keycode)
453{
454 // we're in process of updating the text control
455 m_tempCallbackStruct = wxcbs;
456
457 XmTextVerifyCallbackStruct *cbs = (XmTextVerifyCallbackStruct *)wxcbs;
458
459 wxKeyEvent event (wxEVT_CHAR);
460 event.SetId(GetId());
461 event.m_keyCode = keycode;
462 event.SetEventObject(this);
463
464 // Only if wxTextCtrl::OnChar is called will this be set to True (and
465 // the character passed through)
466 cbs->doit = False;
467
937013e0 468 HandleWindowEvent(event);
c27eab7e
VZ
469
470 if ( !InSetValue() && m_processedDefault )
471 {
472 // Can generate a command
473 wxCommandEvent commandEvent(wxEVT_COMMAND_TEXT_UPDATED, GetId());
474 commandEvent.SetEventObject(this);
475 ProcessCommand(commandEvent);
476 }
477
478 // do it after the (user) event handlers processed the events because
479 // otherwise GetValue() would return incorrect (not yet updated value)
480 m_tempCallbackStruct = NULL;
481}
482
e1aae528
MB
483wxSize wxDoGetSingleTextCtrlBestSize( Widget textWidget,
484 const wxWindow* window )
485{
486 Dimension xmargin, ymargin, highlight, shadow;
487 char* value;
488
489 XtVaGetValues( textWidget,
490 XmNmarginWidth, &xmargin,
491 XmNmarginHeight, &ymargin,
492 XmNvalue, &value,
493 XmNhighlightThickness, &highlight,
494 XmNshadowThickness, &shadow,
495 NULL );
1119b899 496
e1aae528 497 if( !value )
da8cf723 498 value = wxMOTIF_STR("|");
e1aae528
MB
499
500 int x, y;
501 window->GetTextExtent( value, &x, &y );
502
105fbe1f
MB
503 if( x < 90 )
504 x = 90;
1119b899 505
e1aae528
MB
506 return wxSize( x + 2 * xmargin + 2 * highlight + 2 * shadow,
507 // MBN: +2 necessary: Lesstif bug or mine?
7d8268a1 508 y + 2 * ymargin + 2 * highlight + 2 * shadow + 2 );
e1aae528
MB
509}
510
511wxSize wxTextCtrl::DoGetBestSize() const
512{
513 if( IsSingleLine() )
f9204363
MB
514 {
515 wxSize best = wxControl::DoGetBestSize();
105fbe1f
MB
516#if wxCHECK_MOTIF_VERSION( 2, 3 )
517 // OpenMotif 2.3 gives way too big X sizes
518 wxSize other_best = wxDoGetSingleTextCtrlBestSize
519 ( (Widget) GetTopWidget(), this );
520 return wxSize( other_best.x, best.y );
521#else
522 if( best.x < 90 ) best.x = 90;
f9204363
MB
523
524 return best;
105fbe1f 525#endif
f9204363 526 }
e1aae528
MB
527 else
528 return wxWindow::DoGetBestSize();
529}
530
c27eab7e
VZ
531// ----------------------------------------------------------------------------
532// helpers and Motif callbacks
533// ----------------------------------------------------------------------------
534
535static void MergeChangesIntoString(wxString& value,
536 XmTextVerifyCallbackStruct *cbs)
537{
538 /* _sm_
539 * At least on my system (SunOS 4.1.3 + Motif 1.2), you need to think of
540 * every event as a replace event. cbs->text->ptr gives the replacement
541 * text, cbs->startPos gives the index of the first char affected by the
542 * replace, and cbs->endPos gives the index one more than the last char
543 * affected by the replace (startPos == endPos implies an empty range).
544 * Hence, a deletion is represented by replacing all input text with a
545 * blank string ("", *not* NULL!). A simple insertion that does not
546 * overwrite any text has startPos == endPos.
547 */
548
549 if ( !value )
550 {
551 // easy case: the ol value was empty
552 value = cbs->text->ptr;
553 }
554 else
555 {
556 // merge the changes into the value
557 const char * const passwd = value;
558 int len = value.length();
559
44d130a3
MB
560 len += ( cbs->text->ptr ?
561 strlen(cbs->text->ptr) :
562 0 ) + 1; // + new text (if any) + NUL
c27eab7e
VZ
563 len -= cbs->endPos - cbs->startPos; // - text from affected region.
564
565 char * newS = new char [len];
566 char * dest = newS,
567 * insert = cbs->text->ptr;
568
569 // Copy (old) text from passwd, up to the start posn of the change.
570 int i;
571 const char * p = passwd;
572 for (i = 0; i < cbs->startPos; ++i)
573 *dest++ = *p++;
574
575 // Copy the text to be inserted).
44d130a3
MB
576 if (insert)
577 while (*insert)
578 *dest++ = *insert++;
c27eab7e
VZ
579
580 // Finally, copy into newS any remaining text from passwd[endPos] on.
581 for (p = passwd + cbs->endPos; *p; )
582 *dest++ = *p++;
583 *dest = 0;
584
585 value = newS;
586
587 delete[] newS;
588 }
589}
590
591static void
af111fc3 592wxTextWindowChangedProc (Widget w, XtPointer clientData, XtPointer WXUNUSED(ptr))
02e8b2f9 593{
2d120f83
JS
594 if (!wxGetWindowFromTable(w))
595 // Widget has been deleted!
596 return;
66a007fb 597
2d120f83 598 wxTextCtrl *tw = (wxTextCtrl *) clientData;
7d8268a1 599 tw->SetModified(true);
02e8b2f9
JS
600}
601
66a007fb 602static void
af111fc3 603wxTextWindowModifyProc (Widget WXUNUSED(w), XtPointer clientData, XmTextVerifyCallbackStruct *cbs)
02e8b2f9 604{
dfc54541 605 wxTextCtrl *tw = (wxTextCtrl *) clientData;
7d8268a1 606 tw->m_processedDefault = false;
66a007fb 607
c27eab7e
VZ
608 // First, do some stuff if it's a password control: in this case, we need
609 // to store the string inside the class because GetValue() can't retrieve
610 // it from the text ctrl. We do *not* do it in other circumstances because
611 // it would double the amount of memory needed.
66a007fb 612
c27eab7e 613 if ( tw->GetWindowStyleFlag() & wxTE_PASSWORD )
dfc54541 614 {
c27eab7e 615 MergeChangesIntoString(tw->m_value, cbs);
66a007fb 616
c27eab7e 617 if ( cbs->text->length > 0 )
dfc54541
JS
618 {
619 int i;
620 for (i = 0; i < cbs->text->length; ++i)
621 cbs->text->ptr[i] = '*';
c27eab7e 622 cbs->text->ptr[i] = '\0';
dfc54541
JS
623 }
624 }
66a007fb 625
ccb234b4
MB
626 if(tw->InSetValue())
627 return;
628
c27eab7e
VZ
629 // If we're already within an OnChar, return: probably a programmatic
630 // insertion.
dfc54541
JS
631 if (tw->m_tempCallbackStruct)
632 return;
66a007fb 633
dfc54541
JS
634 // Check for a backspace
635 if (cbs->startPos == (cbs->currInsert - 1))
636 {
c27eab7e 637 tw->DoSendEvents((void *)cbs, WXK_DELETE);
66a007fb 638
dfc54541
JS
639 return;
640 }
66a007fb 641
c27eab7e 642 // Pasting operation: let it through without calling OnChar
dfc54541
JS
643 if (cbs->text->length > 1)
644 return;
66a007fb 645
dfc54541
JS
646 // Something other than text
647 if (cbs->text->ptr == NULL)
648 return;
66a007fb 649
c27eab7e
VZ
650 // normal key press
651 char ch = cbs->text->ptr[0];
652 tw->DoSendEvents((void *)cbs, ch == '\n' ? '\r' : ch);
02e8b2f9
JS
653}
654
66a007fb 655static void
af111fc3 656wxTextWindowGainFocusProc (Widget w, XtPointer clientData, XmAnyCallbackStruct *WXUNUSED(cbs))
02e8b2f9 657{
2d120f83
JS
658 if (!wxGetWindowFromTable(w))
659 return;
66a007fb 660
2d120f83
JS
661 wxTextCtrl *tw = (wxTextCtrl *) clientData;
662 wxFocusEvent event(wxEVT_SET_FOCUS, tw->GetId());
663 event.SetEventObject(tw);
937013e0 664 tw->HandleWindowEvent(event);
02e8b2f9
JS
665}
666
66a007fb 667static void
af111fc3 668wxTextWindowLoseFocusProc (Widget w, XtPointer clientData, XmAnyCallbackStruct *WXUNUSED(cbs))
02e8b2f9 669{
2d120f83
JS
670 if (!wxGetWindowFromTable(w))
671 return;
66a007fb 672
2d120f83
JS
673 wxTextCtrl *tw = (wxTextCtrl *) clientData;
674 wxFocusEvent event(wxEVT_KILL_FOCUS, tw->GetId());
675 event.SetEventObject(tw);
937013e0 676 tw->HandleWindowEvent(event);
02e8b2f9 677}
dfc54541
JS
678
679static void wxTextWindowActivateProc(Widget w, XtPointer clientData,
af111fc3 680 XmAnyCallbackStruct *WXUNUSED(ptr))
dfc54541 681{
2d120f83
JS
682 if (!wxGetWindowFromTable(w))
683 return;
66a007fb 684
2d120f83 685 wxTextCtrl *tw = (wxTextCtrl *) clientData;
66a007fb 686
2d120f83
JS
687 if (tw->InSetValue())
688 return;
66a007fb 689
2d120f83
JS
690 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER);
691 event.SetId(tw->GetId());
692 event.SetEventObject(tw);
693 tw->ProcessCommand(event);
dfc54541 694}
c27eab7e 695
e702ff0f
JS
696void wxTextCtrl::OnCut(wxCommandEvent& WXUNUSED(event))
697{
698 Cut();
699}
700
701void wxTextCtrl::OnCopy(wxCommandEvent& WXUNUSED(event))
702{
703 Copy();
704}
705
706void wxTextCtrl::OnPaste(wxCommandEvent& WXUNUSED(event))
707{
708 Paste();
709}
710
711void wxTextCtrl::OnUndo(wxCommandEvent& WXUNUSED(event))
712{
713 Undo();
714}
715
716void wxTextCtrl::OnRedo(wxCommandEvent& WXUNUSED(event))
717{
718 Redo();
719}
720
721void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event)
722{
723 event.Enable( CanCut() );
724}
725
726void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event)
727{
728 event.Enable( CanCopy() );
729}
730
731void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event)
732{
733 event.Enable( CanPaste() );
734}
735
736void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event)
737{
738 event.Enable( CanUndo() );
739}
740
741void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event)
742{
743 event.Enable( CanRedo() );
744}