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