]> git.saurik.com Git - wxWidgets.git/blame - src/os2/textctrl.cpp
My iconv (GLIBC 2.2) uses char** as the second
[wxWidgets.git] / src / os2 / textctrl.cpp
CommitLineData
0e320a79
DW
1/////////////////////////////////////////////////////////////////////////////
2// Name: textctrl.cpp
3// Purpose: wxTextCtrl
d90895ac 4// Author: David Webster
0e320a79 5// Modified by:
d90895ac 6// Created: 10/17/99
0e320a79 7// RCS-ID: $Id$
d90895ac
DW
8// Copyright: (c) David Webster
9// Licence: wxWindows licence
0e320a79
DW
10/////////////////////////////////////////////////////////////////////////////
11
d90895ac
DW
12// ----------------------------------------------------------------------------
13// headers
14// ----------------------------------------------------------------------------
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifndef WX_PRECOMP
20 #include "wx/textctrl.h"
21 #include "wx/settings.h"
22 #include "wx/brush.h"
23 #include "wx/utils.h"
24 #include "wx/log.h"
0e320a79
DW
25#endif
26
d90895ac
DW
27#if wxUSE_CLIPBOARD
28 #include "wx/app.h"
29 #include "wx/clipbrd.h"
30#endif
0e320a79 31
d90895ac
DW
32#include "wx/textfile.h"
33
34#include "wx/os2/private.h"
35
36#include <string.h>
37#include <stdlib.h>
38#include <sys/types.h>
0e320a79 39
d90895ac
DW
40#if wxUSE_IOSTREAMH
41# include <fstream.h>
0e320a79 42#else
d90895ac 43# include <fstream>
0e320a79
DW
44#endif
45
d90895ac
DW
46
47// ----------------------------------------------------------------------------
48// event tables and other macros
49// ----------------------------------------------------------------------------
50
0e320a79
DW
51IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
52
53BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
d90895ac
DW
54 EVT_CHAR(wxTextCtrl::OnChar)
55 EVT_DROP_FILES(wxTextCtrl::OnDropFiles)
56
0e320a79
DW
57 EVT_MENU(wxID_CUT, wxTextCtrl::OnCut)
58 EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy)
59 EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste)
60 EVT_MENU(wxID_UNDO, wxTextCtrl::OnUndo)
61 EVT_MENU(wxID_REDO, wxTextCtrl::OnRedo)
62
63 EVT_UPDATE_UI(wxID_CUT, wxTextCtrl::OnUpdateCut)
64 EVT_UPDATE_UI(wxID_COPY, wxTextCtrl::OnUpdateCopy)
65 EVT_UPDATE_UI(wxID_PASTE, wxTextCtrl::OnUpdatePaste)
66 EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo)
67 EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo)
68END_EVENT_TABLE()
0e320a79 69
d90895ac
DW
70
71// ============================================================================
72// implementation
73// ============================================================================
74
75// ----------------------------------------------------------------------------
76// creation
77// ----------------------------------------------------------------------------
78
0e320a79 79wxTextCtrl::wxTextCtrl()
0e320a79 80{
0e320a79
DW
81}
82
3bd418ca
DW
83bool wxTextCtrl::Create(
84 wxWindow* pParent
85, wxWindowID vId
86, const wxString& rsValue
87, const wxPoint& rPos
88, const wxSize& rSize
89, long lStyle
5d4b632b 90#if wxUSE_VALIDATORS
3bd418ca 91, const wxValidator& rValidator
5d4b632b 92#endif
3bd418ca
DW
93, const wxString& rsName
94)
95{
96 //
97 // Base initialization
98 //
99 if ( !CreateBase( pParent
100 ,vId
101 ,rPos
102 ,rSize
103 ,lStyle
104#if wxUSE_VALIDATORS
105 ,rValidator
106#endif
107 ,rsName
108 ))
d90895ac 109 return FALSE;
0e320a79 110
45bfc84b
DW
111 wxPoint vPos = rPos; // The OS/2 position
112
3bd418ca 113 if (pParent )
45bfc84b 114 {
3bd418ca 115 pParent->AddChild(this);
45bfc84b
DW
116 //
117 // OS2 uses normal coordinates, no bassackwards Windows ones
118 //
119 vPos.y = pParent->GetSize().y - (vPos.y + rSize.y);
120 }
121 else
122 {
123 RECTL vRect;
124
125 ::WinQueryWindowRect(HWND_DESKTOP, &vRect);
126 vPos.y = vRect.yTop - (vPos.y + rSize.y);
127 }
0e320a79 128
3bd418ca 129 m_windowStyle = lStyle;
d90895ac 130
3bd418ca
DW
131 long lSstyle = WS_VISIBLE | WS_TABSTOP;
132
133 //
134 // Single and multiline edit fields are two different controls in PM
135 //
d90895ac
DW
136 if ( m_windowStyle & wxTE_MULTILINE )
137 {
3bd418ca
DW
138 m_bIsMLE = TRUE;
139 m_windowStyle |= wxTE_PROCESS_ENTER;
d90895ac 140
d90895ac 141 if ((m_windowStyle & wxTE_NO_VSCROLL) == 0)
3bd418ca
DW
142 lSstyle |= MLS_VSCROLL;
143 if (m_windowStyle & wxHSCROLL)
144 lSstyle |= MLS_HSCROLL;
145 if (m_windowStyle & wxTE_READONLY)
146 lSstyle |= MLS_READONLY;
d90895ac 147 }
0e320a79 148 else
3bd418ca
DW
149 {
150 lSstyle |= ES_LEFT;
151
152 if (m_windowStyle & wxHSCROLL)
153 lSstyle |= ES_AUTOSCROLL;
154 if (m_windowStyle & wxTE_READONLY)
155 lSstyle |= ES_READONLY;
156 if (m_windowStyle & wxTE_PASSWORD) // hidden input
157 lSstyle |= ES_UNREADABLE;
158 }
159 if (m_bIsMLE)
160 {
161 m_hWnd = (WXHWND)::WinCreateWindow( (HWND)GetHwndOf(pParent) // Parent window handle
162 ,WC_MLE // Window class
163 ,(PSZ)rsValue.c_str() // Initial Text
164 ,(ULONG)lSstyle // Style flags
45bfc84b
DW
165 ,(LONG)vPos.x // X pos of origin
166 ,(LONG)vPos.y // Y pos of origin
3bd418ca
DW
167 ,(LONG)rSize.x // field width
168 ,(LONG)rSize.y // field height
169 ,(HWND)GetHwndOf(pParent) // owner window handle (same as parent
170 ,HWND_TOP // initial z position
171 ,(ULONG)vId // Window identifier
172 ,NULL // no control data
173 ,NULL // no Presentation parameters
174 );
175 }
176 else
177 {
178 m_hWnd = (WXHWND)::WinCreateWindow( (HWND)GetHwndOf(pParent) // Parent window handle
179 ,WC_ENTRYFIELD // Window class
180 ,(PSZ)rsValue.c_str() // Initial Text
181 ,(ULONG)lSstyle // Style flags
45bfc84b
DW
182 ,(LONG)vPos.x // X pos of origin
183 ,(LONG)vPos.y // Y pos of origin
3bd418ca
DW
184 ,(LONG)rSize.x // field width
185 ,(LONG)rSize.y // field height
186 ,(HWND)GetHwndOf(pParent) // owner window handle (same as parent
187 ,HWND_TOP // initial z position
188 ,(ULONG)vId // Window identifier
189 ,NULL // no control data
190 ,NULL // no Presentation parameters
191 );
192 }
193
194 if (m_hWnd == 0)
195 {
196 return FALSE;
197 }
198
d90895ac
DW
199 SubclassWin(GetHWND());
200
3bd418ca
DW
201 //
202 // Set font, position, size and initial value
203 //
204 wxFont& vFontParent = pParent->GetFont();
205
206 if (vFontParent.Ok())
d90895ac 207 {
3bd418ca 208 SetFont(vFontParent);
d90895ac
DW
209 }
210 else
211 {
212 SetFont(wxSystemSettings::GetSystemFont(wxSYS_SYSTEM_FONT));
213 }
3bd418ca
DW
214 if (!rsValue.IsEmpty())
215 {
216 SetValue(rsValue);
217 }
218 SetupColours();
219 SetSize( rPos.x
220 ,rPos.y
221 ,rSize.x
222 ,rSize.y
223 );
0e320a79 224 return TRUE;
3bd418ca 225} // end of wxTextCtrl::Create
0e320a79 226
3bd418ca 227//
d90895ac 228// Make sure the window style (etc.) reflects the HWND style (roughly)
3bd418ca 229//
d90895ac
DW
230void wxTextCtrl::AdoptAttributesFromHWND()
231{
3bd418ca
DW
232 HWND hWnd = GetHwnd();
233 LONG lStyle = ::WinQueryWindowULong(hWnd, QWL_STYLE);
d90895ac 234
3bd418ca 235 wxWindow::AdoptAttributesFromHWND();
d90895ac 236
3bd418ca
DW
237 if (m_bIsMLE)
238 {
239 m_windowStyle |= wxTE_MULTILINE;
240 if (lStyle & MLS_READONLY)
241 m_windowStyle |= wxTE_READONLY;
242 }
243 else
244 {
245 if (lStyle & ES_UNREADABLE)
246 m_windowStyle |= wxTE_PASSWORD;
247 if (lStyle & ES_READONLY)
248 m_windowStyle |= wxTE_READONLY;
249 }
c4955899 250} // end of wxTextCtrl::AdoptAttributesFromHWND
d90895ac
DW
251
252void wxTextCtrl::SetupColours()
253{
c4955899
DW
254 wxColour vBkgndColour;
255
256 vBkgndColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW);
257 SetBackgroundColour(vBkgndColour);
d90895ac 258 SetForegroundColour(GetParent()->GetForegroundColour());
c4955899 259} // end of wxTextCtrl::SetupColours
d90895ac
DW
260
261// ----------------------------------------------------------------------------
262// set/get the controls text
263// ----------------------------------------------------------------------------
264
0e320a79
DW
265wxString wxTextCtrl::GetValue() const
266{
c4955899
DW
267 wxString sStr = wxGetWindowText(GetHWND());
268 char* zStr = (char*)sStr.c_str();
d90895ac 269
c4955899
DW
270 for ( ; *zStr; zStr++ )
271 {
272 //
273 // this will replace \r\n with just \n
274 //
275 if (*zStr == '\n')
276 *zStr = '\0';
277 if (*zStr == '\r')
278 *zStr = '\n';
279 }
280 sStr = zStr;
281 return sStr;
282} // end of wxTextCtrl::GetValue
0e320a79 283
c4955899
DW
284void wxTextCtrl::SetValue(
285 const wxString& rsValue
286)
0e320a79 287{
c4955899
DW
288 //
289 // If the text is long enough, it's faster to just set it instead of first
290 // comparing it with the old one (chances are that it will be different
291 // anyhow, this comparison is there to avoid flicker for small single-line
292 // edit controls mostly)
293 //
294 if ((rsValue.length() > 0x400) || (rsValue != GetValue()))
295 {
296 ::WinSetWindowText(GetHwnd(), rsValue.c_str());
297 AdjustSpaceLimit();
298 }
299} // end of wxTextCtrl::SetValue
d90895ac 300
c4955899
DW
301void wxTextCtrl::WriteText(
302 const wxString& rsValue
303)
304{
305 ::WinSetWindowText(GetHwnd(), rsValue.c_str());
d90895ac 306 AdjustSpaceLimit();
c4955899 307} // end of wxTextCtrl::WriteText
0e320a79 308
c4955899
DW
309void wxTextCtrl::AppendText(
310 const wxString& rsText
311)
d90895ac 312{
d90895ac 313 SetInsertionPointEnd();
c4955899
DW
314 WriteText(rsText);
315} // end of wxTextCtrl::AppendText
d90895ac
DW
316
317void wxTextCtrl::Clear()
318{
c4955899
DW
319 ::WinSetWindowText(GetHwnd(), "");
320} // end of wxTextCtrl::Clear
d90895ac
DW
321
322// ----------------------------------------------------------------------------
0e320a79 323// Clipboard operations
d90895ac
DW
324// ----------------------------------------------------------------------------
325
0e320a79
DW
326void wxTextCtrl::Copy()
327{
d90895ac
DW
328 if (CanCopy())
329 {
330 HWND hWnd = GetHwnd();
3bd418ca
DW
331 if (m_bIsMLE)
332 ::WinSendMsg(hWnd, MLM_COPY, 0, 0);
333 else
334 ::WinSendMsg(hWnd, EM_COPY, 0, 0);
d90895ac 335 }
3bd418ca 336} // end of wxTextCtrl::Copy
0e320a79
DW
337
338void wxTextCtrl::Cut()
339{
d90895ac
DW
340 if (CanCut())
341 {
342 HWND hWnd = GetHwnd();
3bd418ca
DW
343
344 if (m_bIsMLE)
345 ::WinSendMsg(hWnd, MLM_CUT, 0, 0);
346 else
347 ::WinSendMsg(hWnd, EM_CUT, 0, 0);
d90895ac 348 }
c4955899 349} // end of wxTextCtrl::Cut
0e320a79
DW
350
351void wxTextCtrl::Paste()
352{
d90895ac
DW
353 if (CanPaste())
354 {
c4955899
DW
355 HWND hWnd = GetHwnd();
356
357 ::WinSendMsg(hWnd, EM_PASTE, 0, 0);
d90895ac 358 }
c4955899 359} // end of wxTextCtrl::Paste
d90895ac
DW
360
361bool wxTextCtrl::CanCopy() const
362{
c4955899 363 //
d90895ac 364 // Can copy if there's a selection
c4955899
DW
365 //
366 long lFrom = 0L;
367 long lTo = 0L;
368
369 GetSelection(&lFrom, &lTo);
370 return (lFrom != lTo);
371} // end of wxTextCtrl::CanCopy
d90895ac
DW
372
373bool wxTextCtrl::CanCut() const
374{
c4955899 375 //
d90895ac 376 // Can cut if there's a selection
c4955899
DW
377 //
378 long lFrom = 0L;
379 long lTo = 0L;
380
381 GetSelection(&lFrom, &lTo);
382 return (lFrom != lTo);
383} // end of wxTextCtrl::CanCut
d90895ac
DW
384
385bool wxTextCtrl::CanPaste() const
386{
3bd418ca
DW
387 bool bIsTextAvailable = FALSE;
388
d90895ac
DW
389 if (!IsEditable())
390 return FALSE;
391
3bd418ca
DW
392 //
393 // Check for straight text on clipboard
394 //
395 if (::WinOpenClipbrd(vHabmain))
d90895ac 396 {
3bd418ca
DW
397 bIsTextAvailable = (::WinQueryClipbrdData(vHabmain, CF_TEXT) != 0);
398 ::WinCloseClipbrd(vHabmain);
d90895ac 399 }
3bd418ca
DW
400 return bIsTextAvailable;
401} // end of wxTextCtrl::CanPaste
0e320a79 402
d90895ac
DW
403// ----------------------------------------------------------------------------
404// Accessors
405// ----------------------------------------------------------------------------
406
c4955899
DW
407void wxTextCtrl::SetEditable(
408 bool bEditable
409)
0e320a79 410{
c4955899
DW
411 HWND hWnd = GetHwnd();
412
413 if (m_bIsMLE)
414 ::WinSendMsg(hWnd, MLM_SETREADONLY, MPFROMLONG(!bEditable), (MPARAM)0);
415 else
416 ::WinSendMsg(hWnd, EM_SETREADONLY, MPFROMLONG(!bEditable), (MPARAM)0);
417} // end of wxTextCtrl::SetEditable
0e320a79 418
c4955899
DW
419void wxTextCtrl::SetInsertionPoint(
420 long lPos
421)
0e320a79 422{
c4955899
DW
423 HWND hWnd = GetHwnd();
424
425 if (m_bIsMLE)
426 ::WinSendMsg(hWnd, MLM_SETSEL, (MPARAM)lPos, (MPARAM)lPos);
427 else
428 ::WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT((USHORT)lPos, (USHORT)lPos), (MPARAM)0);
429} // end of wxTextCtrl::SetInsertionPoint
0e320a79
DW
430
431void wxTextCtrl::SetInsertionPointEnd()
432{
c4955899
DW
433 long lPos = GetLastPosition();
434
435 SetInsertionPoint(lPos);
436} // end of wxTextCtrl::SetInsertionPointEnd
0e320a79
DW
437
438long wxTextCtrl::GetInsertionPoint() const
439{
3bd418ca
DW
440 WXDWORD dwPos = 0L;
441
442 if (m_bIsMLE)
443 dwPos = (WXDWORD)::WinSendMsg(GetHwnd(), MLM_QUERYSEL, (MPARAM)MLFQS_MINSEL, 0);
444 else
445 {
446 dwPos = (WXDWORD)::WinSendMsg(GetHwnd(), EM_QUERYSEL, 0, 0);
447 dwPos = SHORT1FROMMP((MPARAM)dwPos); // the first 16 bit value is the min pos
448 }
449 return (dwPos & 0xFFFF);
450} // end of wxTextCtrl::GetInsertionPoint
0e320a79
DW
451
452long wxTextCtrl::GetLastPosition() const
453{
3bd418ca
DW
454 HWND hWnd = GetHwnd();
455 long lCharIndex;
456 long lLineLength;
0e320a79 457
3bd418ca
DW
458 if (m_bIsMLE)
459 {
460 lCharIndex = 0;
d90895ac 461
3bd418ca
DW
462 //
463 // This just gets the total text length. The last will be this value
464 //
465 lLineLength = (long)::WinSendMsg(hWnd, MLM_QUERYTEXTLENGTH, 0, 0);
466 }
467 else
468 {
469 WNDPARAMS vParams;
470
471 lCharIndex = 0;
472 vParams.fsStatus = WPM_CCHTEXT;
473 if (::WinSendMsg( GetHwnd()
474 ,WM_QUERYWINDOWPARAMS
475 ,&vParams
476 ,0
477 ))
478 {
479 lLineLength = (long)vParams.cchText;
480 }
481 else
482 lLineLength = 0;
483 }
484 return(lCharIndex + lLineLength);
485} // end of wxTextCtrl::GetLastPosition
0e320a79 486
d90895ac
DW
487// If the return values from and to are the same, there is no
488// selection.
c4955899
DW
489void wxTextCtrl::GetSelection(
490 long* plFrom
491, long* plTo
492) const
0e320a79 493{
c4955899 494 WXDWORD dwPos;
0e320a79 495
c4955899
DW
496 if (m_bIsMLE)
497 dwPos = (WXDWORD)::WinSendMsg(GetHwnd(), MLM_QUERYSEL, (MPARAM)MLFQS_MINSEL, 0);
498 else
499 {
500 dwPos = (WXDWORD)::WinSendMsg(GetHwnd(), EM_QUERYSEL, 0, 0);
501 }
502 *plFrom = SHORT1FROMMP((MPARAM)dwPos); // the first 16 bit value is the min pos
503 *plTo = SHORT2FROMMP((MPARAM)dwPos); // the first 16 bit value is the min pos
504} // end of wxTextCtrl::GetSelection
0e320a79 505
d90895ac
DW
506bool wxTextCtrl::IsEditable() const
507{
c4955899
DW
508 if (m_bIsMLE)
509 return((bool)LONGFROMMR(::WinSendMsg(GetHwnd(), MLM_QUERYREADONLY, 0, 0)));
510 else
511 return((bool)LONGFROMMR(::WinSendMsg(GetHwnd(), EM_QUERYREADONLY, 0, 0)));
512} // end of wxTextCtrl::IsEditable
0e320a79 513
d90895ac
DW
514// ----------------------------------------------------------------------------
515// Editing
516// ----------------------------------------------------------------------------
517
c4955899
DW
518void wxTextCtrl::Replace(
519 long lFrom
520, long lTo
521, const wxString& rsValue
522)
0e320a79 523{
d90895ac 524#if wxUSE_CLIPBOARD
c4955899
DW
525 HWND hWnd = GetHwnd();
526 long lFromChar = lFrom;
527 long lToChar = lTo;
0e320a79 528
c4955899 529 //
d90895ac 530 // Set selection and remove it
c4955899
DW
531 //
532 if (m_bIsMLE)
533 {
534 ::WinSendMsg(hWnd, MLM_SETSEL, MPFROM2SHORT((USHORT)lFrom, (USHORT)lTo), 0);
535 ::WinSendMsg(hWnd, MLM_CUT, 0, 0);
536 }
537 else
538 {
539 ::WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT((USHORT)lFrom, (USHORT)lTo), 0);
540 ::WinSendMsg(hWnd, EM_CUT, 0, 0);
541 }
0e320a79 542
c4955899 543 //
d90895ac 544 // Now replace with 'value', by pasting.
c4955899
DW
545 //
546 wxSetClipboardData(wxDF_TEXT, (wxObject *) (const wxChar *)rsValue, 0, 0);
0e320a79 547
d90895ac 548 // Paste into edit control
c4955899
DW
549 if (m_bIsMLE)
550 ::WinSendMsg(hWnd, MLM_PASTE, (MPARAM)0, (MPARAM)0);
551 else
552 ::WinSendMsg(hWnd, EM_PASTE, (MPARAM)0, (MPARAM)0);
d90895ac
DW
553#else
554 wxFAIL_MSG("wxTextCtrl::Replace not implemented if wxUSE_CLIPBOARD is 0.");
555#endif
c4955899 556} // end of wxTextCtrl::Replace
0e320a79 557
c4955899
DW
558void wxTextCtrl::Remove(
559 long lFrom
560, long lTo
561)
0e320a79 562{
c4955899
DW
563 HWND hWnd = GetHwnd();
564 long lFromChar = lFrom;
565 long lToChar = lTo;
d90895ac 566
c4955899
DW
567 if (m_bIsMLE)
568 {
569 ::WinSendMsg(hWnd, MLM_SETSEL, MPFROM2SHORT((USHORT)lFrom, (USHORT)lTo), 0);
570 ::WinSendMsg(hWnd, MLM_CUT, 0, 0);
571 }
572 else
573 {
574 ::WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT((USHORT)lFrom, (USHORT)lTo), 0);
575 ::WinSendMsg(hWnd, EM_CUT, 0, 0);
576 }
577} // end of wxTextCtrl::Remove
0e320a79 578
c4955899
DW
579void wxTextCtrl::SetSelection(
580 long lFrom
581, long lTo
582)
0e320a79 583{
c4955899
DW
584 HWND hWnd = GetHwnd();
585 long lFromChar = lFrom;
586 long lToChar = lTo;
d90895ac 587
c4955899
DW
588 //
589 // If from and to are both -1, it means (in wxWindows) that all text should
d90895ac 590 // be selected. Translate into Windows convention
c4955899
DW
591 //
592 if ((lFrom == -1L) && (lTo == -1L))
d90895ac 593 {
c4955899
DW
594 lFromChar = 0L;
595 lToChar = -1L;
d90895ac 596 }
c4955899
DW
597 if (m_bIsMLE)
598 ::WinSendMsg(hWnd, MLM_SETSEL, (MPARAM)lFromChar, (MPARAM)lToChar);
599 else
600 ::WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT((USHORT)lFromChar, (USHORT)lToChar), (MPARAM)0);
601} // end of wxTextCtrl::SetSelection
d90895ac 602
c4955899
DW
603bool wxTextCtrl::LoadFile(
604 const wxString& rsFile
605)
0e320a79 606{
c4955899 607 if ( wxTextCtrlBase::LoadFile(rsFile) )
d90895ac 608 {
c4955899
DW
609 //
610 // Update the size limit if needed
611 //
d90895ac 612 AdjustSpaceLimit();
d90895ac
DW
613 return TRUE;
614 }
d90895ac 615 return FALSE;
c4955899 616} // end of wxTextCtrl::LoadFile
0e320a79
DW
617
618bool wxTextCtrl::IsModified() const
619{
c4955899
DW
620 bool bRc;
621
622 if (m_bIsMLE)
623 bRc = (bool)LONGFROMMR(::WinSendMsg(GetHwnd(), MLM_QUERYCHANGED, 0, 0));
624 else
625 bRc = (bool)LONGFROMMR(::WinSendMsg(GetHwnd(), EM_QUERYCHANGED, 0, 0));
626 return bRc;
627} // end of wxTextCtrl::IsModified
0e320a79 628
3bd418ca 629//
0e320a79 630// Makes 'unmodified'
3bd418ca 631//
0e320a79
DW
632void wxTextCtrl::DiscardEdits()
633{
3bd418ca
DW
634 if (m_bIsMLE)
635 ::WinSendMsg(GetHwnd(), MLM_SETCHANGED, MPFROMLONG(FALSE), 0);
636 else
637 //
638 // EM controls do not have a SETCHANGED but issuing a query should reset it
639 //
640 ::WinSendMsg(GetHwnd(), EM_QUERYCHANGED, 0, 0);
641} // end of wxTextCtrl::DiscardEdits
0e320a79
DW
642
643int wxTextCtrl::GetNumberOfLines() const
644{
c4955899 645 int nNumLines;
0e320a79 646
c4955899
DW
647 if (m_bIsMLE)
648 nNumLines = (int)::WinSendMsg(GetHwnd(), MLM_QUERYLINECOUNT, 0, 0);
649 else
650 nNumLines = 1;
651 return nNumLines;
652} // end of wxTextCtrl::GetNumberOfLines
d90895ac 653
c4955899
DW
654long wxTextCtrl::XYToPosition(
655 long lX
656, long lY
657) const
658{
659 HWND hWnd = GetHwnd();
660 long lCharIndex = 0L;
661 long lLen;
0e320a79 662
c4955899
DW
663 if (m_bIsMLE)
664 {
665 lLen = (long)::WinSendMsg(GetHwnd(), MLM_QUERYLINELENGTH, 0, 0);
666 lCharIndex = ((lLen * lY) + lX);
667 }
668 else
669 lCharIndex = lX;
670 return lCharIndex;
671} // end of wxTextCtrl::XYToPosition
672
673bool wxTextCtrl::PositionToXY(
674 long lPos
675, long* plX
676, long* plY
677) const
0e320a79 678{
c4955899
DW
679 HWND hWnd = GetHwnd();
680 long nLineNo = -1;
681 long lCharIndex = 0;
d90895ac 682
c4955899
DW
683 if (m_bIsMLE)
684 nLineNo = (long)::WinSendMsg(hWnd, MLM_LINEFROMCHAR, (MPARAM)lPos, 0);
685 else
686 nLineNo = 0;
d90895ac 687
c4955899 688 if (nLineNo == -1)
d90895ac
DW
689 {
690 // no such line
691 return FALSE;
692 }
693
c4955899 694 //
d90895ac 695 // This gets the char index for the _beginning_ of this line
c4955899
DW
696 //
697 long lLineWidth;
698
699 if (m_bIsMLE)
700 {
701 lLineWidth = (long)::WinSendMsg(hWnd, MLM_QUERYLINELENGTH, (MPARAM)0, (MPARAM)0);
702 lCharIndex = (nLineNo + 1) * lLineWidth;
703 }
704 else
705 {
706 WNDPARAMS vParams;
707
708 vParams.fsStatus = WPM_CCHTEXT;
709 if (::WinSendMsg( hWnd
710 ,WM_QUERYWINDOWPARAMS
711 ,&vParams
712 ,0
713 ))
714 {
715 lCharIndex = vParams.cchText;
716 }
717 else
718 lCharIndex = 32;
719 }
720
721 if (lCharIndex == -1)
d90895ac
DW
722 {
723 return FALSE;
724 }
725
c4955899
DW
726 //
727 // The X position must therefore be the difference between pos and charIndex
728 //
729 if (plX)
730 *plX = lPos - lCharIndex;
731 if (plY)
732 *plY = nLineNo;
d90895ac
DW
733
734 return TRUE;
c4955899 735} // end of wxTextCtrl::PositionToXY
0e320a79 736
c4955899
DW
737void wxTextCtrl::ShowPosition(
738 long lPos
739)
0e320a79 740{
c4955899
DW
741 HWND hWnd = GetHwnd();
742 long lCurrentLineLineNo = 0L;
d90895ac
DW
743
744 // To scroll to a position, we pass the number of lines and characters
745 // to scroll *by*. This means that we need to:
746 // (1) Find the line position of the current line.
747 // (2) Find the line position of pos.
748 // (3) Scroll by (pos - current).
749 // For now, ignore the horizontal scrolling.
750
c4955899 751 //
d90895ac
DW
752 // Is this where scrolling is relative to - the line containing the caret?
753 // Or is the first visible line??? Try first visible line.
c4955899
DW
754 //
755 if (m_bIsMLE)
756 {
757 //
758 // In PM this is the actual char position
759 //
760 lCurrentLineLineNo = (long)::WinSendMsg(hWnd, MLM_QUERYFIRSTCHAR, (MPARAM)0, (MPARAM)0);
d90895ac 761
c4955899
DW
762 //
763 // This will cause a scroll to the selected position
764 //
765 ::WinSendMsg(hWnd, MLM_SETSEL, (MPARAM)lCurrentLineLineNo, (MPARAM)lCurrentLineLineNo);
766 }
767} // end of wxTextCtrl::ShowPosition
0e320a79 768
3bd418ca
DW
769int wxTextCtrl::GetLineLength(
770 long lLineNo
771) const
0e320a79 772{
3bd418ca 773 long lLen = 0L;
d90895ac 774
3bd418ca
DW
775 if (m_bIsMLE)
776 lLen = (long)::WinSendMsg(GetHwnd(), MLM_QUERYLINELENGTH, 0, 0);
777 else
778 {
779 WNDPARAMS vParams;
780
781 vParams.fsStatus = WPM_CCHTEXT;
782 if (::WinSendMsg( GetHwnd()
783 ,WM_QUERYWINDOWPARAMS
784 ,&vParams
785 ,0
786 ))
787 {
788 lLen = vParams.cchText;
789 }
790 else
791 lLen = 32;
792 }
793 return lLen;
c4955899 794} // end ofwxTextCtrl::GetLineLength
0e320a79 795
c4955899
DW
796wxString wxTextCtrl::GetLineText(
797 long lLineNo
798) const
0e320a79 799{
c4955899
DW
800 long lLen = (long)GetLineLength((long)lLineNo) + 1;
801 wxString sStr;
802 char* zBuf;
0e320a79 803
c4955899
DW
804 //
805 // There must be at least enough place for the length WORD in the
806 // buffer
807 //
808 lLen += sizeof(WORD);
809 zBuf = new char[lLen];
810 if (m_bIsMLE)
811 {
812 long lIndex;
813 long lBuflen;
814 long lCopied;
0e320a79 815
c4955899
DW
816 lLen = (long)::WinSendMsg(GetHwnd(), MLM_QUERYLINELENGTH, 0, 0);
817 lIndex = lLen * lLineNo;
0e320a79 818
c4955899
DW
819 ::WinSendMsg(GetHwnd(), MLM_SETSEL, (MPARAM)lIndex, (MPARAM)lIndex);
820 ::WinSendMsg(GetHwnd(), MLM_SETIMPORTEXPORT, MPFROMP(zBuf), MPFROMSHORT((USHORT)sizeof(zBuf)));
821 lBuflen = (long)::WinSendMsg(GetHwnd(), MLM_QUERYFORMATTEXTLENGTH, MPFROMLONG(lIndex), MPFROMLONG(-1));
822 lCopied = (long)::WinSendMsg(GetHwnd(), MLM_EXPORT, MPFROMP(&lIndex), MPFROMP(&lBuflen));
823 zBuf[lCopied] = '\0';
824 }
825 else
826 {
827 WNDPARAMS vParams;
828
829 vParams.fsStatus = WPM_CCHTEXT;
830 if (::WinSendMsg( GetHwnd()
831 ,WM_QUERYWINDOWPARAMS
832 ,&vParams
833 ,0
834 ))
835 memcpy(zBuf, vParams.pszText, vParams.cchText);
836 zBuf[vParams.cchText] = '\0';
837 }
838 sStr = zBuf;
839 delete [] zBuf;
840 return sStr;
841} // end of wxTextCtrl::GetLineText
0e320a79 842
d90895ac 843// ----------------------------------------------------------------------------
0e320a79 844// Undo/redo
d90895ac
DW
845// ----------------------------------------------------------------------------
846
0e320a79
DW
847void wxTextCtrl::Undo()
848{
d90895ac
DW
849 if (CanUndo())
850 {
c4955899
DW
851 if (m_bIsMLE)
852 ::WinSendMsg(GetHwnd(), MLM_UNDO, 0, 0);
853 // Simple entryfields cannot be undone
d90895ac 854 }
c4955899 855} // end of wxTextCtrl::Undo
0e320a79
DW
856
857void wxTextCtrl::Redo()
858{
d90895ac
DW
859 if (CanRedo())
860 {
c4955899
DW
861 if (m_bIsMLE)
862 ::WinSendMsg(GetHwnd(), MLM_UNDO, 0, 0);
863 // Simple entryfields cannot be undone
d90895ac 864 }
c4955899 865} // end of wxTextCtrl::Redo
0e320a79
DW
866
867bool wxTextCtrl::CanUndo() const
868{
3bd418ca
DW
869 bool bOk;
870
871 if (m_bIsMLE)
872 bOk = (::WinSendMsg(GetHwnd(), MLM_QUERYUNDO, 0, 0) != 0);
873 else
874 bOk = FALSE; // can't undo regular edit fields in PM
875 return bOk;
876} // end of wxTextCtrl::CanUndo
0e320a79
DW
877
878bool wxTextCtrl::CanRedo() const
879{
3bd418ca
DW
880 bool bOk;
881
882 if (m_bIsMLE)
883 bOk = (::WinSendMsg(GetHwnd(), MLM_QUERYUNDO, 0, 0) != 0);
884 else
885 bOk = FALSE; // can't undo regular edit fields in PM
886 return bOk;
887} // end of wxTextCtrl::CanRedo
0e320a79 888
d90895ac
DW
889// ----------------------------------------------------------------------------
890// implemenation details
891// ----------------------------------------------------------------------------
0e320a79 892
c4955899
DW
893void wxTextCtrl::Command(
894 wxCommandEvent& rEvent
895)
0e320a79 896{
c4955899
DW
897 SetValue(rEvent.GetString());
898 ProcessCommand (rEvent);
899} // end of wxTextCtrl::Command
0e320a79 900
c4955899
DW
901void wxTextCtrl::OnDropFiles(
902 wxDropFilesEvent& rEvent
903)
0e320a79
DW
904{
905 // By default, load the first file into the text window.
c4955899 906 if (rEvent.GetNumberOfFiles() > 0)
0e320a79 907 {
c4955899 908 LoadFile(rEvent.GetFiles()[0]);
0e320a79 909 }
c4955899
DW
910} // end of wxTextCtrl::OnDropFiles
911
912WXHBRUSH wxTextCtrl::OnCtlColor(
913 WXHDC hWxDC
914, WXHWND hWnd
915, WXUINT uCtlColor
916, WXUINT uMessage
917, WXWPARAM wParam
918, WXLPARAM lParam
919)
d90895ac 920{
c4955899
DW
921 HPS hPS = (HPS)hWxDC;
922 wxBrush* pBrush = NULL;
923 wxColour vColBack = GetBackgroundColour();
924 wxColour vColFore = GetForegroundColour();
925 wxBrush* pBackgroundBrush = wxTheBrushList->FindOrCreateBrush( GetBackgroundColour()
926 ,wxSOLID
927 );
928
929 if (m_bUseCtl3D)
930 {
931 HBRUSH hBrush = NULLHANDLE;
0e320a79 932
c4955899
DW
933 return hBrush;
934 }
935 if (GetParent()->GetTransparentBackground())
936 ::GpiSetBackMix(hPS, BM_LEAVEALONE);
937 else
938 ::GpiSetBackMix(hPS, BM_OVERPAINT);
939 if (!IsEnabled() && (GetWindowStyle() & wxTE_MULTILINE) == 0)
940 vColBack = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE);
941 ::GpiSetBackColor(hPS, vColBack.GetPixel());
942 ::GpiSetColor(hPS, vColFore.GetPixel());
943 return (WXHBRUSH)pBackgroundBrush->GetResourceHandle();
944} // end of wxTextCtrl::OnCtlColor
945
946void wxTextCtrl::OnChar(
947 wxKeyEvent& rEvent
948)
0e320a79 949{
c4955899 950 switch (rEvent.KeyCode())
d90895ac 951 {
d90895ac
DW
952 case WXK_RETURN:
953 if ( !(m_windowStyle & wxTE_MULTILINE) )
954 {
c4955899
DW
955 wxCommandEvent vEvent(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
956
957 vEvent.SetEventObject(this);
958 if ( GetEventHandler()->ProcessEvent(vEvent))
d90895ac
DW
959 return;
960 }
961 //else: multiline controls need Enter for themselves
962
963 break;
964
965 case WXK_TAB:
966 // always produce navigation event - even if we process TAB
967 // ourselves the fact that we got here means that the user code
968 // decided to skip processing of this TAB - probably to let it
969 // do its default job.
970 //
971 // NB: Notice that Ctrl-Tab is handled elsewhere and Alt-Tab is
972 // handled by Windows
973 {
c4955899 974 wxNavigationKeyEvent vEventNav;
d90895ac 975
c4955899
DW
976 vEventNav.SetDirection(!rEvent.ShiftDown());
977 vEventNav.SetWindowChange(FALSE);
978 vEventNav.SetEventObject(this);
979
980 if ( GetEventHandler()->ProcessEvent(vEventNav) )
d90895ac
DW
981 return;
982 }
983 break;
d90895ac 984 }
c4955899
DW
985 rEvent.Skip();
986} // end of wxTextCtrl::OnChar
0e320a79 987
c4955899
DW
988bool wxTextCtrl::OS2Command(
989 WXUINT uParam
990, WXWORD WXUNUSED(vId)
991)
0e320a79 992{
c4955899 993 switch (uParam)
d90895ac 994 {
d90895ac
DW
995 case EN_SETFOCUS:
996 case EN_KILLFOCUS:
997 {
c4955899
DW
998 wxFocusEvent vEvent( uParam == EN_KILLFOCUS ? wxEVT_KILL_FOCUS
999 : wxEVT_SET_FOCUS
1000 ,m_windowId
1001 );
1002
1003 vEvent.SetEventObject(this);
1004 GetEventHandler()->ProcessEvent(vEvent);
d90895ac
DW
1005 }
1006 break;
1007
1008 case EN_CHANGE:
1009 {
c4955899
DW
1010 wxCommandEvent vEvent( wxEVT_COMMAND_TEXT_UPDATED
1011 ,m_windowId
1012 );
1013
1014 InitCommandEvent(vEvent);
1015 vEvent.SetString((char*)GetValue().c_str());
1016 ProcessCommand(vEvent);
d90895ac
DW
1017 }
1018 break;
1019
c4955899
DW
1020 case EN_OVERFLOW:
1021 //
1022 // The text size limit has been hit - increase it
1023 //
d90895ac
DW
1024 AdjustSpaceLimit();
1025 break;
1026
c4955899
DW
1027 case EN_SCROLL:
1028 case EN_INSERTMODETOGGLE:
1029 case EN_MEMERROR:
1030 return FALSE;
d90895ac
DW
1031 default:
1032 return FALSE;
1033 }
1034
c4955899
DW
1035 //
1036 // Processed
1037 //
d90895ac 1038 return TRUE;
c4955899 1039} // end of wxTextCtrl::OS2Command
0e320a79 1040
d90895ac 1041void wxTextCtrl::AdjustSpaceLimit()
0e320a79 1042{
3bd418ca
DW
1043 unsigned int uLen = 0;
1044 unsigned int uLimit = 0;
d90895ac 1045
3bd418ca
DW
1046 uLen = ::WinQueryWindowTextLength(GetHwnd());
1047 if (m_bIsMLE)
1048 {
1049 uLimit = (unsigned int)::WinSendMsg( GetHwnd()
1050 ,MLM_QUERYTEXTLIMIT
1051 ,0
1052 ,0
1053 );
1054 }
1055 else
1056 {
1057 ENTRYFDATA* pEfd;
1058 WNDPARAMS vParams;
1059
1060 vParams.fsStatus = WPM_CBCTLDATA;
1061 vParams.cbCtlData = sizeof(ENTRYFDATA);
1062
1063 if (::WinSendMsg( GetHwnd()
1064 ,WM_QUERYWINDOWPARAMS
1065 ,&vParams
1066 ,0
1067 ))
1068 {
1069 pEfd = (ENTRYFDATA*)vParams.pCtlData;
1070 uLimit = (unsigned int)pEfd->cchEditLimit;
1071 }
d90895ac 1072 else
3bd418ca 1073 uLimit = 32; //PM's default
d90895ac 1074 }
3bd418ca
DW
1075 if (uLen >= uLimit)
1076 {
1077 uLimit = uLen + 0x8000; // 32Kb
1078 if (uLimit > 0xffff)
1079 {
1080 uLimit = 0L;
1081 }
1082 if (m_bIsMLE)
1083 ::WinSendMsg(GetHwnd(), MLM_SETTEXTLIMIT, MPFROMLONG(uLimit), 0);
1084 else
1085 ::WinSendMsg(GetHwnd(), EM_SETTEXTLIMIT, MPFROMLONG(uLimit), 0);
1086 }
1087} // end of wxTextCtrl::AdjustSpaceLimit
0e320a79 1088
d90895ac 1089bool wxTextCtrl::AcceptsFocus() const
0e320a79 1090{
c4955899
DW
1091 //
1092 // We don't want focus if we can't be edited
1093 //
d90895ac 1094 return IsEditable() && wxControl::AcceptsFocus();
c4955899 1095} // end of wxTextCtrl::Command
0e320a79 1096
e78c4d50 1097wxSize wxTextCtrl::DoGetBestSize() const
0e320a79 1098{
c4955899
DW
1099 int nCx;
1100 int nCy;
0e320a79 1101
c4955899 1102 wxGetCharSize(GetHWND(), &nCx, &nCy, (wxFont*)&GetFont());
d90895ac 1103
c4955899
DW
1104 int wText = DEFAULT_ITEM_WIDTH;
1105 int hText = EDIT_HEIGHT_FROM_CHAR_HEIGHT(nCy);
1106
1107 if (m_windowStyle & wxTE_MULTILINE)
d90895ac
DW
1108 {
1109 hText *= wxMin(GetNumberOfLines(), 5);
1110 }
1111 //else: for single line control everything is ok
d90895ac 1112 return wxSize(wText, hText);
c4955899 1113} // end of wxTextCtrl::DoGetBestSize
0e320a79 1114
d90895ac
DW
1115// ----------------------------------------------------------------------------
1116// standard handlers for standard edit menu events
1117// ----------------------------------------------------------------------------
1118
c4955899
DW
1119void wxTextCtrl::OnCut(
1120 wxCommandEvent& rEvent
1121)
0e320a79
DW
1122{
1123 Cut();
c4955899 1124} // end of wxTextCtrl::OnCut
0e320a79 1125
c4955899
DW
1126void wxTextCtrl::OnCopy(
1127 wxCommandEvent& rEvent
1128)
0e320a79
DW
1129{
1130 Copy();
c4955899 1131} // end of wxTextCtrl::OnCopy
0e320a79 1132
c4955899
DW
1133void wxTextCtrl::OnPaste(
1134 wxCommandEvent& rEvent
1135)
0e320a79
DW
1136{
1137 Paste();
c4955899 1138} // end of wxTextCtrl::OnPaste
0e320a79 1139
c4955899
DW
1140void wxTextCtrl::OnUndo(
1141 wxCommandEvent& rEvent
1142)
0e320a79
DW
1143{
1144 Undo();
c4955899 1145} // end of wxTextCtrl::OnUndo
0e320a79 1146
c4955899
DW
1147void wxTextCtrl::OnRedo(
1148 wxCommandEvent& rEvent
1149)
0e320a79
DW
1150{
1151 Redo();
c4955899 1152} // end of wxTextCtrl::OnRedo
0e320a79 1153
c4955899
DW
1154void wxTextCtrl::OnUpdateCut(
1155 wxUpdateUIEvent& rEvent
1156)
0e320a79 1157{
c4955899
DW
1158 rEvent.Enable(CanCut());
1159} // end of wxTextCtrl::OnUpdateCut
0e320a79 1160
c4955899
DW
1161void wxTextCtrl::OnUpdateCopy(
1162 wxUpdateUIEvent& rEvent
1163)
0e320a79 1164{
c4955899
DW
1165 rEvent.Enable(CanCopy());
1166} // end of wxTextCtrl::OnUpdateCopy
0e320a79 1167
c4955899
DW
1168void wxTextCtrl::OnUpdatePaste(
1169 wxUpdateUIEvent& rEvent
1170)
0e320a79 1171{
c4955899
DW
1172 rEvent.Enable(CanPaste());
1173} // end of wxTextCtrl::OnUpdatePaste
0e320a79 1174
c4955899
DW
1175void wxTextCtrl::OnUpdateUndo(
1176 wxUpdateUIEvent& rEvent
1177)
0e320a79 1178{
c4955899
DW
1179 rEvent.Enable(CanUndo());
1180} // end of wxTextCtrl::OnUpdateUndo
1181
1182void wxTextCtrl::OnUpdateRedo(
1183 wxUpdateUIEvent& rEvent
1184)
1185{
1186 rEvent.Enable(CanRedo());
1187} // end of wxTextCtrl::OnUpdateRedo
0e320a79 1188
c4955899
DW
1189bool wxTextCtrl::SetBackgroundColour(
1190 const wxColour& rColour
1191)
0e320a79 1192{
c4955899
DW
1193 if (m_bIsMLE)
1194 ::WinSendMsg(GetHwnd(), MLM_SETBACKCOLOR, (MPARAM)rColour.GetPixel(), MLE_INDEX);
1195 return TRUE;
1196} // end of wxTextCtrl::SetBackgroundColour
1197
1198bool wxTextCtrl::SetForegroundColour(
1199 const wxColour& rColour
1200)
1201{
1202 if (m_bIsMLE)
1203 ::WinSendMsg(GetHwnd(), MLM_SETTEXTCOLOR, (MPARAM)rColour.GetPixel(), MLE_INDEX);
1204 return TRUE;
1205} // end of wxTextCtrl::SetForegroundColour
d90895ac 1206