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