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