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