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