Child positioning fixes and font adjustments
[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/scrolwin.h"
22 #include "wx/settings.h"
23 #include "wx/brush.h"
24 #include "wx/utils.h"
25 #include "wx/log.h"
26 #endif
27
28 #if wxUSE_CLIPBOARD
29 #include "wx/app.h"
30 #include "wx/clipbrd.h"
31 #endif
32
33 #include "wx/textfile.h"
34
35 #include "wx/os2/private.h"
36
37 #include <string.h>
38 #include <stdlib.h>
39 #include <sys/types.h>
40
41 #if wxUSE_IOSTREAMH
42 # include <fstream.h>
43 #else
44 # include <fstream>
45 #endif
46
47 #if !defined(MLE_INDEX)
48 #define MLE_INDEX 0
49 #define MLE_RGB 1
50 #endif
51
52
53 // ----------------------------------------------------------------------------
54 // event tables and other macros
55 // ----------------------------------------------------------------------------
56
57 IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
58
59 BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
60 EVT_CHAR(wxTextCtrl::OnChar)
61 EVT_DROP_FILES(wxTextCtrl::OnDropFiles)
62
63 EVT_MENU(wxID_CUT, wxTextCtrl::OnCut)
64 EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy)
65 EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste)
66 EVT_MENU(wxID_UNDO, wxTextCtrl::OnUndo)
67 EVT_MENU(wxID_REDO, wxTextCtrl::OnRedo)
68
69 EVT_UPDATE_UI(wxID_CUT, wxTextCtrl::OnUpdateCut)
70 EVT_UPDATE_UI(wxID_COPY, wxTextCtrl::OnUpdateCopy)
71 EVT_UPDATE_UI(wxID_PASTE, wxTextCtrl::OnUpdatePaste)
72 EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo)
73 EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo)
74 END_EVENT_TABLE()
75
76
77 // ============================================================================
78 // implementation
79 // ============================================================================
80
81 // ----------------------------------------------------------------------------
82 // creation
83 // ----------------------------------------------------------------------------
84
85 wxTextCtrl::wxTextCtrl()
86 {
87 }
88
89 bool wxTextCtrl::Create(
90 wxWindow* pParent
91 , wxWindowID vId
92 , const wxString& rsValue
93 , const wxPoint& rPos
94 , const wxSize& rSize
95 , long lStyle
96 #if wxUSE_VALIDATORS
97 , const wxValidator& rValidator
98 #endif
99 , const wxString& rsName
100 )
101 {
102 HWND hParent;
103 int nTempy;
104 //
105 // Base initialization
106 //
107 if ( !CreateBase( pParent
108 ,vId
109 ,rPos
110 ,rSize
111 ,lStyle
112 #if wxUSE_VALIDATORS
113 ,rValidator
114 #endif
115 ,rsName
116 ))
117 return FALSE;
118
119 wxPoint vPos = rPos; // The OS/2 position
120 SWP vSwp;
121
122 if (pParent )
123 {
124 pParent->AddChild(this);
125 }
126
127 m_windowStyle = lStyle;
128
129 long lSstyle = WS_VISIBLE | WS_TABSTOP;
130
131 //
132 // Single and multiline edit fields are two different controls in PM
133 //
134 if ( m_windowStyle & wxTE_MULTILINE )
135 {
136 lSstyle |= MLS_BORDER | MLS_WORDWRAP;
137 m_bIsMLE = TRUE;
138
139 if ((m_windowStyle & wxTE_NO_VSCROLL) == 0)
140 lSstyle |= MLS_VSCROLL;
141 if (m_windowStyle & wxHSCROLL)
142 lSstyle |= MLS_HSCROLL;
143 if (m_windowStyle & wxTE_READONLY)
144 lSstyle |= MLS_READONLY;
145 }
146 else
147 {
148 lSstyle |= ES_LEFT | ES_AUTOSCROLL | ES_MARGIN;
149
150 if (m_windowStyle & wxHSCROLL)
151 lSstyle |= ES_AUTOSCROLL;
152 if (m_windowStyle & wxTE_READONLY)
153 lSstyle |= ES_READONLY;
154 if (m_windowStyle & wxTE_PASSWORD) // hidden input
155 lSstyle |= ES_UNREADABLE;
156 }
157 //
158 // If the parent is a scrolled window the controls must
159 // have this style or they will overlap the scrollbars
160 //
161 if (pParent)
162 if (pParent->IsKindOf(CLASSINFO(wxScrolledWindow)) ||
163 pParent->IsKindOf(CLASSINFO(wxGenericScrolledWindow)))
164 lSstyle |= WS_CLIPSIBLINGS;
165
166 if (m_bIsMLE)
167 {
168 m_hWnd = (WXHWND)::WinCreateWindow( (HWND)GetHwndOf(pParent) // Parent window handle
169 ,WC_MLE // Window class
170 ,(PSZ)rsValue.c_str() // Initial Text
171 ,(ULONG)lSstyle // Style flags
172 ,(LONG)0 // X pos of origin
173 ,(LONG)0 // Y pos of origin
174 ,(LONG)0 // field width
175 ,(LONG)0 // field height
176 ,(HWND)GetHwndOf(pParent) // owner window handle (same as parent
177 ,HWND_TOP // initial z position
178 ,(ULONG)vId // Window identifier
179 ,NULL // no control data
180 ,NULL // no Presentation parameters
181 );
182 }
183 else
184 {
185 m_hWnd = (WXHWND)::WinCreateWindow( (HWND)GetHwndOf(pParent) // Parent window handle
186 ,WC_ENTRYFIELD // Window class
187 ,(PSZ)rsValue.c_str() // Initial Text
188 ,(ULONG)lSstyle // Style flags
189 ,(LONG)0 // X pos of origin
190 ,(LONG)0 // Y pos of origin
191 ,(LONG)0 // field width
192 ,(LONG)0 // field height
193 ,(HWND)GetHwndOf(pParent) // owner window handle (same as parent
194 ,HWND_TOP // initial z position
195 ,(ULONG)vId // Window identifier
196 ,NULL // no control data
197 ,NULL // no Presentation parameters
198 );
199 }
200
201 if (m_hWnd == 0)
202 {
203 return FALSE;
204 }
205
206 SubclassWin(GetHWND());
207
208 //
209 // Set font, position, size and initial value
210 //
211 wxFont* pTextFont = new wxFont( 10
212 ,wxMODERN
213 ,wxNORMAL
214 ,wxNORMAL
215 );
216 SetFont(*pTextFont);
217 if (!rsValue.IsEmpty())
218 {
219 SetValue(rsValue);
220 }
221 SetupColours();
222 //
223 // If X and/or Y are not zero the difference is the compensation value
224 // for margins for OS/2 controls.
225 //
226 ::WinQueryWindowPos(m_hWnd, &vSwp);
227 SetXComp(vSwp.x);
228 SetYComp(vSwp.y);
229 SetSize( vPos.x
230 ,vPos.y
231 ,rSize.x
232 ,rSize.y
233 );
234 return TRUE;
235 } // end of wxTextCtrl::Create
236
237 //
238 // Make sure the window style (etc.) reflects the HWND style (roughly)
239 //
240 void wxTextCtrl::AdoptAttributesFromHWND()
241 {
242 HWND hWnd = GetHwnd();
243 LONG lStyle = ::WinQueryWindowULong(hWnd, QWL_STYLE);
244
245 wxWindow::AdoptAttributesFromHWND();
246
247 if (m_bIsMLE)
248 {
249 m_windowStyle |= wxTE_MULTILINE;
250 if (lStyle & MLS_READONLY)
251 m_windowStyle |= wxTE_READONLY;
252 }
253 else
254 {
255 if (lStyle & ES_UNREADABLE)
256 m_windowStyle |= wxTE_PASSWORD;
257 if (lStyle & ES_READONLY)
258 m_windowStyle |= wxTE_READONLY;
259 }
260 } // end of wxTextCtrl::AdoptAttributesFromHWND
261
262 void wxTextCtrl::SetupColours()
263 {
264 wxColour vBkgndColour;
265
266 vBkgndColour = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
267 SetBackgroundColour(vBkgndColour);
268 SetForegroundColour(GetParent()->GetForegroundColour());
269 if (m_bIsMLE)
270 {
271 ::WinSendMsg( GetHwnd()
272 ,MLM_SETTEXTCOLOR
273 ,(MPARAM)GetParent()->GetForegroundColour().GetPixel()
274 ,(MPARAM)MLE_RGB
275 );
276 }
277 } // end of wxTextCtrl::SetupColours
278
279 // ----------------------------------------------------------------------------
280 // set/get the controls text
281 // ----------------------------------------------------------------------------
282
283 wxString wxTextCtrl::GetValue() const
284 {
285 wxString sStr = wxGetWindowText(GetHWND());
286 char* zStr = (char*)sStr.c_str();
287
288 for ( ; *zStr; zStr++ )
289 {
290 //
291 // this will replace \r\n with just \n
292 //
293 if (*zStr == '\n')
294 *zStr = '\0';
295 if (*zStr == '\r')
296 *zStr = '\n';
297 }
298 sStr = zStr;
299 return sStr;
300 } // end of wxTextCtrl::GetValue
301
302 void wxTextCtrl::SetValue(
303 const wxString& rsValue
304 )
305 {
306 //
307 // If the text is long enough, it's faster to just set it instead of first
308 // comparing it with the old one (chances are that it will be different
309 // anyhow, this comparison is there to avoid flicker for small single-line
310 // edit controls mostly)
311 //
312 if ((rsValue.length() > 0x400) || (rsValue != GetValue()))
313 {
314 ::WinSetWindowText(GetHwnd(), rsValue.c_str());
315 AdjustSpaceLimit();
316 }
317 } // end of wxTextCtrl::SetValue
318
319 void wxTextCtrl::WriteText(
320 const wxString& rsValue
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::LoadFile(
622 const wxString& rsFile
623 )
624 {
625 if ( wxTextCtrlBase::LoadFile(rsFile) )
626 {
627 //
628 // Update the size limit if needed
629 //
630 AdjustSpaceLimit();
631 return TRUE;
632 }
633 return FALSE;
634 } // end of wxTextCtrl::LoadFile
635
636 bool wxTextCtrl::IsModified() const
637 {
638 bool bRc;
639
640 if (m_bIsMLE)
641 bRc = (bool)LONGFROMMR(::WinSendMsg(GetHwnd(), MLM_QUERYCHANGED, 0, 0));
642 else
643 bRc = (bool)LONGFROMMR(::WinSendMsg(GetHwnd(), EM_QUERYCHANGED, 0, 0));
644 return bRc;
645 } // end of wxTextCtrl::IsModified
646
647 //
648 // Makes 'unmodified'
649 //
650 void wxTextCtrl::DiscardEdits()
651 {
652 if (m_bIsMLE)
653 ::WinSendMsg(GetHwnd(), MLM_SETCHANGED, MPFROMLONG(FALSE), 0);
654 else
655 //
656 // EM controls do not have a SETCHANGED but issuing a query should reset it
657 //
658 ::WinSendMsg(GetHwnd(), EM_QUERYCHANGED, 0, 0);
659 } // end of wxTextCtrl::DiscardEdits
660
661 int wxTextCtrl::GetNumberOfLines() const
662 {
663 int nNumLines;
664
665 if (m_bIsMLE)
666 nNumLines = (int)::WinSendMsg(GetHwnd(), MLM_QUERYLINECOUNT, 0, 0);
667 else
668 nNumLines = 1;
669 return nNumLines;
670 } // end of wxTextCtrl::GetNumberOfLines
671
672 long wxTextCtrl::XYToPosition(
673 long lX
674 , long lY
675 ) const
676 {
677 HWND hWnd = GetHwnd();
678 long lCharIndex = 0L;
679 long lLen;
680
681 if (m_bIsMLE)
682 {
683 lLen = (long)::WinSendMsg(GetHwnd(), MLM_QUERYLINELENGTH, 0, 0);
684 lCharIndex = ((lLen * lY) + lX);
685 }
686 else
687 lCharIndex = lX;
688 return lCharIndex;
689 } // end of wxTextCtrl::XYToPosition
690
691 bool wxTextCtrl::PositionToXY(
692 long lPos
693 , long* plX
694 , long* plY
695 ) const
696 {
697 HWND hWnd = GetHwnd();
698 long nLineNo = -1;
699 long lCharIndex = 0;
700
701 if (m_bIsMLE)
702 nLineNo = (long)::WinSendMsg(hWnd, MLM_LINEFROMCHAR, (MPARAM)lPos, 0);
703 else
704 nLineNo = 0;
705
706 if (nLineNo == -1)
707 {
708 // no such line
709 return FALSE;
710 }
711
712 //
713 // This gets the char index for the _beginning_ of this line
714 //
715 long lLineWidth;
716
717 if (m_bIsMLE)
718 {
719 lLineWidth = (long)::WinSendMsg(hWnd, MLM_QUERYLINELENGTH, (MPARAM)0, (MPARAM)0);
720 lCharIndex = (nLineNo + 1) * lLineWidth;
721 }
722 else
723 {
724 WNDPARAMS vParams;
725
726 vParams.fsStatus = WPM_CCHTEXT;
727 if (::WinSendMsg( hWnd
728 ,WM_QUERYWINDOWPARAMS
729 ,&vParams
730 ,0
731 ))
732 {
733 lCharIndex = vParams.cchText;
734 }
735 else
736 lCharIndex = 32;
737 }
738
739 if (lCharIndex == -1)
740 {
741 return FALSE;
742 }
743
744 //
745 // The X position must therefore be the difference between pos and charIndex
746 //
747 if (plX)
748 *plX = lPos - lCharIndex;
749 if (plY)
750 *plY = nLineNo;
751
752 return TRUE;
753 } // end of wxTextCtrl::PositionToXY
754
755 void wxTextCtrl::ShowPosition(
756 long lPos
757 )
758 {
759 HWND hWnd = GetHwnd();
760 long lCurrentLineLineNo = 0L;
761
762 // To scroll to a position, we pass the number of lines and characters
763 // to scroll *by*. This means that we need to:
764 // (1) Find the line position of the current line.
765 // (2) Find the line position of pos.
766 // (3) Scroll by (pos - current).
767 // For now, ignore the horizontal scrolling.
768
769 //
770 // Is this where scrolling is relative to - the line containing the caret?
771 // Or is the first visible line??? Try first visible line.
772 //
773 if (m_bIsMLE)
774 {
775 //
776 // In PM this is the actual char position
777 //
778 lCurrentLineLineNo = (long)::WinSendMsg(hWnd, MLM_QUERYFIRSTCHAR, (MPARAM)0, (MPARAM)0);
779
780 //
781 // This will cause a scroll to the selected position
782 //
783 ::WinSendMsg(hWnd, MLM_SETSEL, (MPARAM)lCurrentLineLineNo, (MPARAM)lCurrentLineLineNo);
784 }
785 } // end of wxTextCtrl::ShowPosition
786
787 int wxTextCtrl::GetLineLength(
788 long lLineNo
789 ) const
790 {
791 long lLen = 0L;
792
793 if (m_bIsMLE)
794 lLen = (long)::WinSendMsg(GetHwnd(), MLM_QUERYLINELENGTH, 0, 0);
795 else
796 {
797 WNDPARAMS vParams;
798
799 vParams.fsStatus = WPM_CCHTEXT;
800 if (::WinSendMsg( GetHwnd()
801 ,WM_QUERYWINDOWPARAMS
802 ,&vParams
803 ,0
804 ))
805 {
806 lLen = vParams.cchText;
807 }
808 else
809 lLen = 32;
810 }
811 return lLen;
812 } // end ofwxTextCtrl::GetLineLength
813
814 wxString wxTextCtrl::GetLineText(
815 long lLineNo
816 ) const
817 {
818 long lLen = (long)GetLineLength((long)lLineNo) + 1;
819 wxString sStr;
820 char* zBuf;
821
822 //
823 // There must be at least enough place for the length WORD in the
824 // buffer
825 //
826 lLen += sizeof(WORD);
827 zBuf = new char[lLen];
828 if (m_bIsMLE)
829 {
830 long lIndex;
831 long lBuflen;
832 long lCopied;
833
834 lLen = (long)::WinSendMsg(GetHwnd(), MLM_QUERYLINELENGTH, 0, 0);
835 lIndex = lLen * lLineNo;
836
837 ::WinSendMsg(GetHwnd(), MLM_SETSEL, (MPARAM)lIndex, (MPARAM)lIndex);
838 ::WinSendMsg(GetHwnd(), MLM_SETIMPORTEXPORT, MPFROMP(zBuf), MPFROMSHORT((USHORT)sizeof(zBuf)));
839 lBuflen = (long)::WinSendMsg(GetHwnd(), MLM_QUERYFORMATTEXTLENGTH, MPFROMLONG(lIndex), MPFROMLONG(-1));
840 lCopied = (long)::WinSendMsg(GetHwnd(), MLM_EXPORT, MPFROMP(&lIndex), MPFROMP(&lBuflen));
841 zBuf[lCopied] = '\0';
842 }
843 else
844 {
845 WNDPARAMS vParams;
846
847 vParams.fsStatus = WPM_CCHTEXT;
848 if (::WinSendMsg( GetHwnd()
849 ,WM_QUERYWINDOWPARAMS
850 ,&vParams
851 ,0
852 ))
853 memcpy(zBuf, vParams.pszText, vParams.cchText);
854 zBuf[vParams.cchText] = '\0';
855 }
856 sStr = zBuf;
857 delete [] zBuf;
858 return sStr;
859 } // end of wxTextCtrl::GetLineText
860
861 // ----------------------------------------------------------------------------
862 // Undo/redo
863 // ----------------------------------------------------------------------------
864
865 void wxTextCtrl::Undo()
866 {
867 if (CanUndo())
868 {
869 if (m_bIsMLE)
870 ::WinSendMsg(GetHwnd(), MLM_UNDO, 0, 0);
871 // Simple entryfields cannot be undone
872 }
873 } // end of wxTextCtrl::Undo
874
875 void wxTextCtrl::Redo()
876 {
877 if (CanRedo())
878 {
879 if (m_bIsMLE)
880 ::WinSendMsg(GetHwnd(), MLM_UNDO, 0, 0);
881 // Simple entryfields cannot be undone
882 }
883 } // end of wxTextCtrl::Redo
884
885 bool wxTextCtrl::CanUndo() const
886 {
887 bool bOk;
888
889 if (m_bIsMLE)
890 bOk = (::WinSendMsg(GetHwnd(), MLM_QUERYUNDO, 0, 0) != 0);
891 else
892 bOk = FALSE; // can't undo regular edit fields in PM
893 return bOk;
894 } // end of wxTextCtrl::CanUndo
895
896 bool wxTextCtrl::CanRedo() const
897 {
898 bool bOk;
899
900 if (m_bIsMLE)
901 bOk = (::WinSendMsg(GetHwnd(), MLM_QUERYUNDO, 0, 0) != 0);
902 else
903 bOk = FALSE; // can't undo regular edit fields in PM
904 return bOk;
905 } // end of wxTextCtrl::CanRedo
906
907 // ----------------------------------------------------------------------------
908 // implemenation details
909 // ----------------------------------------------------------------------------
910
911 void wxTextCtrl::Command(
912 wxCommandEvent& rEvent
913 )
914 {
915 SetValue(rEvent.GetString());
916 ProcessCommand (rEvent);
917 } // end of wxTextCtrl::Command
918
919 void wxTextCtrl::OnDropFiles(
920 wxDropFilesEvent& rEvent
921 )
922 {
923 // By default, load the first file into the text window.
924 if (rEvent.GetNumberOfFiles() > 0)
925 {
926 LoadFile(rEvent.GetFiles()[0]);
927 }
928 } // end of wxTextCtrl::OnDropFiles
929
930 WXHBRUSH wxTextCtrl::OnCtlColor(
931 WXHDC hWxDC
932 , WXHWND hWnd
933 , WXUINT uCtlColor
934 , WXUINT uMessage
935 , WXWPARAM wParam
936 , WXLPARAM lParam
937 )
938 {
939 HPS hPS = (HPS)hWxDC;
940 wxBrush* pBrush = NULL;
941 wxColour vColBack = GetBackgroundColour();
942 wxColour vColFore = GetForegroundColour();
943 wxBrush* pBackgroundBrush = wxTheBrushList->FindOrCreateBrush( GetBackgroundColour()
944 ,wxSOLID
945 );
946
947 if (m_bUseCtl3D)
948 {
949 HBRUSH hBrush = NULLHANDLE;
950
951 return hBrush;
952 }
953 if (GetParent()->GetTransparentBackground())
954 ::GpiSetBackMix(hPS, BM_LEAVEALONE);
955 else
956 ::GpiSetBackMix(hPS, BM_OVERPAINT);
957 if (!IsEnabled() && (GetWindowStyle() & wxTE_MULTILINE) == 0)
958 vColBack = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
959 ::GpiSetBackColor(hPS, vColBack.GetPixel());
960 ::GpiSetColor(hPS, vColFore.GetPixel());
961 return (WXHBRUSH)pBackgroundBrush->GetResourceHandle();
962 } // end of wxTextCtrl::OnCtlColor
963
964 bool wxTextCtrl::OS2ShouldPreProcessMessage(
965 WXMSG* pMsg
966 )
967 {
968 return wxControl::OS2ShouldPreProcessMessage(pMsg);
969 } // end of wxTextCtrl::OS2ShouldPreProcessMessage
970
971 void wxTextCtrl::OnChar(
972 wxKeyEvent& rEvent
973 )
974 {
975 switch (rEvent.KeyCode())
976 {
977 case WXK_RETURN:
978 if ( !(m_windowStyle & wxTE_MULTILINE) )
979 {
980 wxCommandEvent vEvent(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
981
982 vEvent.SetEventObject(this);
983 if ( GetEventHandler()->ProcessEvent(vEvent))
984 return;
985 }
986 //else: multiline controls need Enter for themselves
987
988 break;
989
990 case WXK_TAB:
991 // always produce navigation event - even if we process TAB
992 // ourselves the fact that we got here means that the user code
993 // decided to skip processing of this TAB - probably to let it
994 // do its default job.
995 //
996 // NB: Notice that Ctrl-Tab is handled elsewhere and Alt-Tab is
997 // handled by Windows
998 {
999 wxNavigationKeyEvent vEventNav;
1000
1001 vEventNav.SetDirection(!rEvent.ShiftDown());
1002 vEventNav.SetWindowChange(FALSE);
1003 vEventNav.SetEventObject(this);
1004
1005 if ( GetEventHandler()->ProcessEvent(vEventNav) )
1006 return;
1007 }
1008 break;
1009 }
1010 rEvent.Skip();
1011 } // end of wxTextCtrl::OnChar
1012
1013 bool wxTextCtrl::OS2Command(
1014 WXUINT uParam
1015 , WXWORD WXUNUSED(vId)
1016 )
1017 {
1018 switch (uParam)
1019 {
1020 case EN_SETFOCUS:
1021 case EN_KILLFOCUS:
1022 {
1023 wxFocusEvent vEvent( uParam == EN_KILLFOCUS ? wxEVT_KILL_FOCUS
1024 : wxEVT_SET_FOCUS
1025 ,m_windowId
1026 );
1027
1028 vEvent.SetEventObject(this);
1029 GetEventHandler()->ProcessEvent(vEvent);
1030 }
1031 break;
1032
1033 case EN_CHANGE:
1034 {
1035 wxCommandEvent vEvent( wxEVT_COMMAND_TEXT_UPDATED
1036 ,m_windowId
1037 );
1038
1039 InitCommandEvent(vEvent);
1040 vEvent.SetString((char*)GetValue().c_str());
1041 ProcessCommand(vEvent);
1042 }
1043 break;
1044
1045 case EN_OVERFLOW:
1046 //
1047 // The text size limit has been hit - increase it
1048 //
1049 AdjustSpaceLimit();
1050 break;
1051
1052 case EN_SCROLL:
1053 case EN_INSERTMODETOGGLE:
1054 case EN_MEMERROR:
1055 return FALSE;
1056 default:
1057 return FALSE;
1058 }
1059
1060 //
1061 // Processed
1062 //
1063 return TRUE;
1064 } // end of wxTextCtrl::OS2Command
1065
1066 void wxTextCtrl::AdjustSpaceLimit()
1067 {
1068 unsigned int uLen = 0;
1069 unsigned int uLimit = 0;
1070
1071 uLen = ::WinQueryWindowTextLength(GetHwnd());
1072 if (m_bIsMLE)
1073 {
1074 uLimit = (unsigned int)::WinSendMsg( GetHwnd()
1075 ,MLM_QUERYTEXTLIMIT
1076 ,0
1077 ,0
1078 );
1079 }
1080 else
1081 {
1082 ENTRYFDATA* pEfd;
1083 WNDPARAMS vParams;
1084
1085 vParams.fsStatus = WPM_CBCTLDATA;
1086 vParams.cbCtlData = sizeof(ENTRYFDATA);
1087
1088 if (::WinSendMsg( GetHwnd()
1089 ,WM_QUERYWINDOWPARAMS
1090 ,&vParams
1091 ,0
1092 ))
1093 {
1094 pEfd = (ENTRYFDATA*)vParams.pCtlData;
1095 uLimit = (unsigned int)pEfd->cchEditLimit;
1096 }
1097 else
1098 uLimit = 32; //PM's default
1099 }
1100 if (uLen >= uLimit)
1101 {
1102 uLimit = uLen + 0x8000; // 32Kb
1103 if (uLimit > 0xffff)
1104 {
1105 uLimit = 0L;
1106 }
1107 if (m_bIsMLE)
1108 ::WinSendMsg(GetHwnd(), MLM_SETTEXTLIMIT, MPFROMLONG(uLimit), 0);
1109 else
1110 ::WinSendMsg(GetHwnd(), EM_SETTEXTLIMIT, MPFROMLONG(uLimit), 0);
1111 }
1112 } // end of wxTextCtrl::AdjustSpaceLimit
1113
1114 bool wxTextCtrl::AcceptsFocus() const
1115 {
1116 //
1117 // We don't want focus if we can't be edited
1118 //
1119 return IsEditable() && wxControl::AcceptsFocus();
1120 } // end of wxTextCtrl::Command
1121
1122 wxSize wxTextCtrl::DoGetBestSize() const
1123 {
1124 int nCx;
1125 int nCy;
1126
1127 wxGetCharSize(GetHWND(), &nCx, &nCy, (wxFont*)&GetFont());
1128
1129 int wText = DEFAULT_ITEM_WIDTH;
1130 int hText = (EDIT_HEIGHT_FROM_CHAR_HEIGHT(nCy) * .8);
1131
1132 if (m_windowStyle & wxTE_MULTILINE)
1133 {
1134 hText *= wxMin(GetNumberOfLines(), 5);
1135 }
1136 //else: for single line control everything is ok
1137 return wxSize(wText, hText);
1138 } // end of wxTextCtrl::DoGetBestSize
1139
1140 // ----------------------------------------------------------------------------
1141 // standard handlers for standard edit menu events
1142 // ----------------------------------------------------------------------------
1143
1144 void wxTextCtrl::OnCut(
1145 wxCommandEvent& rEvent
1146 )
1147 {
1148 Cut();
1149 } // end of wxTextCtrl::OnCut
1150
1151 void wxTextCtrl::OnCopy(
1152 wxCommandEvent& rEvent
1153 )
1154 {
1155 Copy();
1156 } // end of wxTextCtrl::OnCopy
1157
1158 void wxTextCtrl::OnPaste(
1159 wxCommandEvent& rEvent
1160 )
1161 {
1162 Paste();
1163 } // end of wxTextCtrl::OnPaste
1164
1165 void wxTextCtrl::OnUndo(
1166 wxCommandEvent& rEvent
1167 )
1168 {
1169 Undo();
1170 } // end of wxTextCtrl::OnUndo
1171
1172 void wxTextCtrl::OnRedo(
1173 wxCommandEvent& rEvent
1174 )
1175 {
1176 Redo();
1177 } // end of wxTextCtrl::OnRedo
1178
1179 void wxTextCtrl::OnUpdateCut(
1180 wxUpdateUIEvent& rEvent
1181 )
1182 {
1183 rEvent.Enable(CanCut());
1184 } // end of wxTextCtrl::OnUpdateCut
1185
1186 void wxTextCtrl::OnUpdateCopy(
1187 wxUpdateUIEvent& rEvent
1188 )
1189 {
1190 rEvent.Enable(CanCopy());
1191 } // end of wxTextCtrl::OnUpdateCopy
1192
1193 void wxTextCtrl::OnUpdatePaste(
1194 wxUpdateUIEvent& rEvent
1195 )
1196 {
1197 rEvent.Enable(CanPaste());
1198 } // end of wxTextCtrl::OnUpdatePaste
1199
1200 void wxTextCtrl::OnUpdateUndo(
1201 wxUpdateUIEvent& rEvent
1202 )
1203 {
1204 rEvent.Enable(CanUndo());
1205 } // end of wxTextCtrl::OnUpdateUndo
1206
1207 void wxTextCtrl::OnUpdateRedo(
1208 wxUpdateUIEvent& rEvent
1209 )
1210 {
1211 rEvent.Enable(CanRedo());
1212 } // end of wxTextCtrl::OnUpdateRedo
1213
1214 bool wxTextCtrl::SetBackgroundColour(
1215 const wxColour& rColour
1216 )
1217 {
1218 if (m_bIsMLE)
1219 ::WinSendMsg(GetHwnd(), MLM_SETBACKCOLOR, (MPARAM)rColour.GetPixel(), MLE_INDEX);
1220 return TRUE;
1221 } // end of wxTextCtrl::SetBackgroundColour
1222
1223 bool wxTextCtrl::SetForegroundColour(
1224 const wxColour& rColour
1225 )
1226 {
1227 if (m_bIsMLE)
1228 ::WinSendMsg(GetHwnd(), MLM_SETTEXTCOLOR, (MPARAM)rColour.GetPixel(), MLE_INDEX);
1229 return TRUE;
1230 } // end of wxTextCtrl::SetForegroundColour
1231
1232 bool wxTextCtrl::SetStyle(
1233 long lStart
1234 , long lEnd
1235 , const wxTextAttr& rStyle
1236 )
1237 {
1238 HWND hWnd = GetHwnd();
1239
1240 if (lStart > lEnd)
1241 {
1242 long lTmp = lStart;
1243
1244 lStart = lEnd;
1245 lEnd = lTmp;
1246 }
1247
1248 //
1249 // We can only change the format of the selection, so select the range we
1250 // want and restore the old selection later
1251 //
1252 long lStartOld;
1253 long lEndOld;
1254
1255 GetSelection( &lStartOld
1256 ,&lEndOld
1257 );
1258
1259 //
1260 // But do we really have to change the selection?
1261 //
1262 bool bChangeSel = lStart != lStartOld ||
1263 lEnd != lEndOld;
1264
1265 if (bChangeSel)
1266 {
1267 if (m_bIsMLE)
1268 ::WinSendMsg(hWnd, MLM_SETSEL, MPFROM2SHORT((USHORT)lStart, (USHORT)lEnd), 0);
1269 else
1270 ::WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT((USHORT)lStart, (USHORT)lEnd), 0);
1271 }
1272
1273 //
1274 // TODO:: finish this part
1275 //
1276 return TRUE;
1277 } // end of wxTextCtrl::SetStyle
1278