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