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