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