]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/os2/textctrl.cpp
added support for item attributes in virtual list control
[wxWidgets.git] / src / os2 / textctrl.cpp
... / ...
CommitLineData
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
56IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
57
58BEGIN_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)
73END_EVENT_TABLE()
74
75
76// ============================================================================
77// implementation
78// ============================================================================
79
80// ----------------------------------------------------------------------------
81// creation
82// ----------------------------------------------------------------------------
83
84wxTextCtrl::wxTextCtrl()
85{
86}
87
88bool 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//
257void 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
279void 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
292wxString 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
311void 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
328void wxTextCtrl::WriteText(
329 const wxString& rsValue
330)
331{
332 ::WinSetWindowText(GetHwnd(), rsValue.c_str());
333 AdjustSpaceLimit();
334} // end of wxTextCtrl::WriteText
335
336void wxTextCtrl::AppendText(
337 const wxString& rsText
338)
339{
340 SetInsertionPointEnd();
341 WriteText(rsText);
342} // end of wxTextCtrl::AppendText
343
344void wxTextCtrl::Clear()
345{
346 ::WinSetWindowText(GetHwnd(), "");
347} // end of wxTextCtrl::Clear
348
349// ----------------------------------------------------------------------------
350// Clipboard operations
351// ----------------------------------------------------------------------------
352
353void 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
365void 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
378void 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
388bool 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
400bool 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
412bool 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
434void 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
446void 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
458void wxTextCtrl::SetInsertionPointEnd()
459{
460 long lPos = GetLastPosition();
461
462 SetInsertionPoint(lPos);
463} // end of wxTextCtrl::SetInsertionPointEnd
464
465long 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
479long 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.
516void 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
533bool 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
545void 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
585void 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
606void 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
630bool 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
645bool 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//
659void 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
670int 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
681long 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
700bool 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
764void 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
796int 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
823wxString 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
874void 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
884void 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
894bool 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
905bool 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
920void wxTextCtrl::Command(
921 wxCommandEvent& rEvent
922)
923{
924 SetValue(rEvent.GetString());
925 ProcessCommand (rEvent);
926} // end of wxTextCtrl::Command
927
928void 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
939WXHBRUSH 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
973void 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
1015bool 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
1068void 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
1116bool 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
1124wxSize 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
1146void wxTextCtrl::OnCut(
1147 wxCommandEvent& rEvent
1148)
1149{
1150 Cut();
1151} // end of wxTextCtrl::OnCut
1152
1153void wxTextCtrl::OnCopy(
1154 wxCommandEvent& rEvent
1155)
1156{
1157 Copy();
1158} // end of wxTextCtrl::OnCopy
1159
1160void wxTextCtrl::OnPaste(
1161 wxCommandEvent& rEvent
1162)
1163{
1164 Paste();
1165} // end of wxTextCtrl::OnPaste
1166
1167void wxTextCtrl::OnUndo(
1168 wxCommandEvent& rEvent
1169)
1170{
1171 Undo();
1172} // end of wxTextCtrl::OnUndo
1173
1174void wxTextCtrl::OnRedo(
1175 wxCommandEvent& rEvent
1176)
1177{
1178 Redo();
1179} // end of wxTextCtrl::OnRedo
1180
1181void wxTextCtrl::OnUpdateCut(
1182 wxUpdateUIEvent& rEvent
1183)
1184{
1185 rEvent.Enable(CanCut());
1186} // end of wxTextCtrl::OnUpdateCut
1187
1188void wxTextCtrl::OnUpdateCopy(
1189 wxUpdateUIEvent& rEvent
1190)
1191{
1192 rEvent.Enable(CanCopy());
1193} // end of wxTextCtrl::OnUpdateCopy
1194
1195void wxTextCtrl::OnUpdatePaste(
1196 wxUpdateUIEvent& rEvent
1197)
1198{
1199 rEvent.Enable(CanPaste());
1200} // end of wxTextCtrl::OnUpdatePaste
1201
1202void wxTextCtrl::OnUpdateUndo(
1203 wxUpdateUIEvent& rEvent
1204)
1205{
1206 rEvent.Enable(CanUndo());
1207} // end of wxTextCtrl::OnUpdateUndo
1208
1209void wxTextCtrl::OnUpdateRedo(
1210 wxUpdateUIEvent& rEvent
1211)
1212{
1213 rEvent.Enable(CanRedo());
1214} // end of wxTextCtrl::OnUpdateRedo
1215
1216bool 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
1225bool 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
1234bool 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