1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/os2/textctrl.cpp 
   4 // Author:      David Webster 
   8 // Copyright:   (c) David Webster 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ---------------------------------------------------------------------------- 
  14 // ---------------------------------------------------------------------------- 
  16 // For compilers that support precompilation, includes "wx.h". 
  17 #include "wx/wxprec.h" 
  19 #include "wx/textctrl.h" 
  22     #include "wx/scrolwin.h" 
  23     #include "wx/settings.h" 
  31     #include "wx/clipbrd.h" 
  34 #include "wx/textfile.h" 
  36 #include "wx/os2/private.h" 
  40 #include <sys/types.h> 
  48 #if !defined(MLE_INDEX) 
  54 // ---------------------------------------------------------------------------- 
  55 // event tables and other macros 
  56 // ---------------------------------------------------------------------------- 
  58 IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl
, wxTextCtrlBase
) 
  60 BEGIN_EVENT_TABLE(wxTextCtrl
, wxTextCtrlBase
) 
  61     EVT_CHAR(wxTextCtrl::OnChar
) 
  62     EVT_DROP_FILES(wxTextCtrl::OnDropFiles
) 
  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
) 
  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
) 
  78 // ============================================================================ 
  80 // ============================================================================ 
  82 // ---------------------------------------------------------------------------- 
  84 // ---------------------------------------------------------------------------- 
  86 wxTextCtrl::wxTextCtrl() 
  90 wxTextCtrl::~wxTextCtrl() 
  94 bool wxTextCtrl::Create( 
  97 , const wxString
&                   rsValue
 
 101 , const wxValidator
&                rValidator
 
 102 , const wxString
&                   rsName
 
 106     // Base initialization 
 108     if ( !CreateBase( pParent
 
 118     wxPoint                         vPos 
= rPos
; // The OS/2 position 
 123         pParent
->AddChild(this); 
 126     m_windowStyle 
= lStyle
; 
 128     m_bSkipUpdate 
= false; 
 130     long                            lSstyle 
= WS_VISIBLE 
| WS_TABSTOP
; 
 133     // Single and multiline edit fields are two different controls in PM 
 135     if ( m_windowStyle 
& wxTE_MULTILINE 
) 
 137         lSstyle 
|= MLS_BORDER 
| MLS_WORDWRAP
; 
 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
; 
 149         lSstyle 
|= ES_LEFT 
| ES_AUTOSCROLL 
| ES_MARGIN
; 
 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
; 
 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 
 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 
 199     SubclassWin(GetHWND()); 
 202     // Set font, position, size and initial value 
 204     wxFont
*                          pTextFont 
= new wxFont( 8 
 210     if (!rsValue
.empty()) 
 216     // If X and/or Y are not zero the difference is the compensation value 
 217     // for margins for OS/2 controls. 
 219     ::WinQueryWindowPos(m_hWnd
, &vSwp
); 
 222     SetSize( vPos
.x 
- GetXComp() 
 229 } // end of wxTextCtrl::Create 
 232 // Make sure the window style (etc.) reflects the HWND style (roughly) 
 234 void wxTextCtrl::AdoptAttributesFromHWND() 
 236     HWND                            hWnd 
= GetHwnd(); 
 237     LONG                            lStyle 
= ::WinQueryWindowULong(hWnd
, QWL_STYLE
); 
 239     wxWindow::AdoptAttributesFromHWND(); 
 243         m_windowStyle 
|= wxTE_MULTILINE
; 
 244         if (lStyle 
& MLS_READONLY
) 
 245             m_windowStyle 
|= wxTE_READONLY
; 
 249         if (lStyle 
& ES_UNREADABLE
) 
 250             m_windowStyle 
|= wxTE_PASSWORD
; 
 251         if (lStyle 
& ES_READONLY
) 
 252             m_windowStyle 
|= wxTE_READONLY
; 
 254 } // end of wxTextCtrl::AdoptAttributesFromHWND 
 256 WXDWORD 
wxTextCtrl::OS2GetStyle( 
 258 , WXDWORD
*                          pdwExstyle
 
 262     // Default border for the text controls is the sunken one 
 264     if ((lStyle 
& wxBORDER_MASK
) == wxBORDER_DEFAULT 
) 
 266         lStyle 
|= wxBORDER_SUNKEN
; 
 269     long                            dwStyle 
= wxControl::OS2GetStyle( lStyle
 
 273     dwStyle 
= WS_VISIBLE 
| WS_TABSTOP
; 
 276     // Single and multiline edit fields are two different controls in PM 
 278     if ( m_windowStyle 
& wxTE_MULTILINE 
) 
 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
; 
 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
; 
 299 } // end of wxTextCtrl::OS2GetStyle 
 301 void wxTextCtrl::SetWindowStyleFlag( 
 305     wxControl::SetWindowStyleFlag(lStyle
); 
 306 } // end of wxTextCtrl::SetWindowStyleFlag 
 308 void wxTextCtrl::SetupColours() 
 310     wxColour                        vBkgndColour
; 
 312     vBkgndColour 
= wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
); 
 313     SetBackgroundColour(vBkgndColour
); 
 314     SetForegroundColour(GetParent()->GetForegroundColour()); 
 317         ::WinSendMsg( GetHwnd() 
 319                      ,(MPARAM
)GetParent()->GetForegroundColour().GetPixel() 
 323 } // end of wxTextCtrl::SetupColours 
 325 // ---------------------------------------------------------------------------- 
 326 // set/get the controls text 
 327 // ---------------------------------------------------------------------------- 
 329 wxString 
wxTextCtrl::GetValue() const 
 331     wxString                        sStr 
= wxGetWindowText(GetHWND()); 
 332     wxCharBuffer                    
buf(sStr
.char_str()); 
 333     char*                           zStr 
= buf
.data(); 
 335     for ( ; *zStr
; zStr
++ ) 
 338         // this will replace \r\n with just \n 
 346 } // end of wxTextCtrl::GetValue 
 348 void wxTextCtrl::DoSetValue( 
 349   const wxString
&                   rsValue
, 
 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) 
 359     if ((rsValue
.length() > 0x400) || (rsValue 
!= GetValue())) 
 361         if ( flags 
& SetValue_SendEvent 
) 
 362             m_bSkipUpdate 
= true; 
 364         ::WinSetWindowText(GetHwnd(), rsValue
.c_str()); 
 367 } // end of wxTextCtrl::SetValue 
 369 void wxTextCtrl::WriteText( 
 370   const wxString
&                   rsValue
 
 374         ::WinSendMsg(GetHwnd(), MLM_INSERT
, MPARAM(rsValue
.wx_str()), MPARAM(0)); 
 376         ::WinSetWindowText(GetHwnd(), rsValue
.c_str()); 
 378 } // end of wxTextCtrl::WriteText 
 380 void wxTextCtrl::AppendText( 
 381   const wxString
&                   rsText
 
 384     SetInsertionPointEnd(); 
 386 } // end of wxTextCtrl::AppendText 
 388 void wxTextCtrl::Clear() 
 390     ::WinSetWindowText(GetHwnd(), ""); 
 391 } // end of wxTextCtrl::Clear 
 393 bool wxTextCtrl::EmulateKeyPress( 
 394   const wxKeyEvent
&                 rEvent
 
 398     return(wxTextCtrlBase::EmulateKeyPress(rEvent
)); 
 399 } // end of wxTextCtrl::EmulateKeyPress 
 401 // ---------------------------------------------------------------------------- 
 402 // Clipboard operations 
 403 // ---------------------------------------------------------------------------- 
 405 void wxTextCtrl::Copy() 
 409         HWND hWnd 
= GetHwnd(); 
 411             ::WinSendMsg(hWnd
, MLM_COPY
, 0, 0); 
 413             ::WinSendMsg(hWnd
, EM_COPY
, 0, 0); 
 415 } // end of wxTextCtrl::Copy 
 417 void wxTextCtrl::Cut() 
 421         HWND hWnd 
= GetHwnd(); 
 424             ::WinSendMsg(hWnd
, MLM_CUT
, 0, 0); 
 426             ::WinSendMsg(hWnd
, EM_CUT
, 0, 0); 
 428 } // end of wxTextCtrl::Cut 
 430 void wxTextCtrl::Paste() 
 434         HWND                        hWnd 
= GetHwnd(); 
 436         ::WinSendMsg(hWnd
, EM_PASTE
, 0, 0); 
 438 } // end of wxTextCtrl::Paste 
 440 bool wxTextCtrl::CanCopy() const 
 443     // Can copy if there's a selection 
 448     GetSelection(&lFrom
, &lTo
); 
 449     return (lFrom 
!= lTo
); 
 450 } // end of wxTextCtrl::CanCopy 
 452 bool wxTextCtrl::CanCut() const 
 455     // Can cut if there's a selection 
 460     GetSelection(&lFrom
, &lTo
); 
 461     return (lFrom 
!= lTo
); 
 462 } // end of wxTextCtrl::CanCut 
 464 bool wxTextCtrl::CanPaste() const 
 466     bool                            bIsTextAvailable 
= false; 
 472     // Check for straight text on clipboard 
 474     if (::WinOpenClipbrd(vHabmain
)) 
 476         bIsTextAvailable 
= (::WinQueryClipbrdData(vHabmain
, CF_TEXT
) != 0); 
 477         ::WinCloseClipbrd(vHabmain
); 
 479     return bIsTextAvailable
; 
 480 } // end of wxTextCtrl::CanPaste 
 482 // ---------------------------------------------------------------------------- 
 484 // ---------------------------------------------------------------------------- 
 486 void wxTextCtrl::SetEditable( 
 490     HWND                            hWnd 
= GetHwnd(); 
 493         ::WinSendMsg(hWnd
, MLM_SETREADONLY
, MPFROMLONG(!bEditable
), (MPARAM
)0); 
 495         ::WinSendMsg(hWnd
, EM_SETREADONLY
, MPFROMLONG(!bEditable
), (MPARAM
)0); 
 496 } // end of wxTextCtrl::SetEditable 
 498 void wxTextCtrl::SetInsertionPoint( 
 502     HWND                            hWnd 
= GetHwnd(); 
 505         ::WinSendMsg(hWnd
, MLM_SETSEL
, (MPARAM
)lPos
, (MPARAM
)lPos
); 
 507         ::WinSendMsg(hWnd
, EM_SETSEL
, MPFROM2SHORT((USHORT
)lPos
, (USHORT
)lPos
), (MPARAM
)0); 
 508 } // end of wxTextCtrl::SetInsertionPoint 
 510 void wxTextCtrl::SetInsertionPointEnd() 
 512     wxTextPos                       lPos 
= GetLastPosition(); 
 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) 
 521     if (GetInsertionPoint() == GetLastPosition()) 
 523     SetInsertionPoint(lPos
); 
 524 } // end of wxTextCtrl::SetInsertionPointEnd 
 526 long wxTextCtrl::GetInsertionPoint() const 
 531         dwPos 
= (WXDWORD
)::WinSendMsg(GetHwnd(), MLM_QUERYSEL
, (MPARAM
)MLFQS_MINSEL
, 0); 
 534         dwPos 
= (WXDWORD
)::WinSendMsg(GetHwnd(), EM_QUERYSEL
, 0, 0); 
 535         dwPos 
= SHORT1FROMMP((MPARAM
)dwPos
);  // the first 16 bit value is the min pos 
 537     return (dwPos 
& 0xFFFF); 
 538 } // end of wxTextCtrl::GetInsertionPoint 
 540 wxTextPos 
wxTextCtrl::GetLastPosition() const 
 542     HWND                            hWnd 
= GetHwnd(); 
 551         // This just gets the total text length.  The last will be this value 
 553         lLineLength 
= (long)::WinSendMsg(hWnd
, MLM_QUERYTEXTLENGTH
, 0, 0); 
 560         vParams
.fsStatus 
= WPM_CCHTEXT
; 
 561         if (::WinSendMsg( GetHwnd() 
 562                          ,WM_QUERYWINDOWPARAMS
 
 567             lLineLength 
= (long)vParams
.cchText
; 
 572     return(lCharIndex 
+ lLineLength
); 
 573 } // end of wxTextCtrl::GetLastPosition 
 575 // If the return values from and to are the same, there is no 
 577 void wxTextCtrl::GetSelection( 
 585         dwPos 
= (WXDWORD
)::WinSendMsg(GetHwnd(), MLM_QUERYSEL
, (MPARAM
)MLFQS_MINSEL
, 0); 
 588         dwPos 
= (WXDWORD
)::WinSendMsg(GetHwnd(), EM_QUERYSEL
, 0, 0); 
 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 
 594 bool wxTextCtrl::IsEditable() const 
 597         return((bool)LONGFROMMR(::WinSendMsg(GetHwnd(), MLM_QUERYREADONLY
, 0, 0))); 
 599         return((bool)LONGFROMMR(::WinSendMsg(GetHwnd(), EM_QUERYREADONLY
, 0, 0))); 
 600 } // end of wxTextCtrl::IsEditable 
 602 // ---------------------------------------------------------------------------- 
 604 // ---------------------------------------------------------------------------- 
 606 void wxTextCtrl::Replace( long lFrom
, 
 608                           const wxString
& rsValue 
) 
 611     HWND hWnd 
= GetHwnd(); 
 614     // Set selection and remove it 
 618         ::WinSendMsg(hWnd
, MLM_SETSEL
, MPFROM2SHORT((USHORT
)lFrom
, (USHORT
)lTo
), 0); 
 619         ::WinSendMsg(hWnd
, MLM_CUT
, 0, 0); 
 623         ::WinSendMsg(hWnd
, EM_SETSEL
, MPFROM2SHORT((USHORT
)lFrom
, (USHORT
)lTo
), 0); 
 624         ::WinSendMsg(hWnd
, EM_CUT
, 0, 0); 
 628     // Now replace with 'value', by pasting. 
 630     wxSetClipboardData(wxDF_TEXT
, (wxObject 
*) (const wxChar 
*)rsValue
, 0, 0); 
 632     // Paste into edit control 
 634         ::WinSendMsg(hWnd
, MLM_PASTE
, (MPARAM
)0, (MPARAM
)0); 
 636         ::WinSendMsg(hWnd
, EM_PASTE
, (MPARAM
)0, (MPARAM
)0); 
 640     wxUnusedVar(rsValue
); 
 641     wxFAIL_MSG("wxTextCtrl::Replace not implemented if wxUSE_CLIPBOARD is 0."); 
 643 }  // end of wxTextCtrl::Replace 
 645 void wxTextCtrl::Remove( 
 650     HWND                            hWnd      
= GetHwnd(); 
 654         ::WinSendMsg(hWnd
, MLM_SETSEL
, MPFROM2SHORT((USHORT
)lFrom
, (USHORT
)lTo
), 0); 
 655         ::WinSendMsg(hWnd
, MLM_CUT
, 0, 0); 
 659         ::WinSendMsg(hWnd
, EM_SETSEL
, MPFROM2SHORT((USHORT
)lFrom
, (USHORT
)lTo
), 0); 
 660         ::WinSendMsg(hWnd
, EM_CUT
, 0, 0); 
 662 } // end of wxTextCtrl::Remove 
 664 void wxTextCtrl::SetSelection( 
 669     HWND                            hWnd 
= GetHwnd(); 
 670     long                            lFromChar 
= lFrom
; 
 674     // If from and to are both -1, it means (in wxWidgets) that all text should 
 675     // be selected. Translate into Windows convention 
 677     if ((lFrom 
== -1L) && (lTo 
== -1L)) 
 683         ::WinSendMsg(hWnd
, MLM_SETSEL
, (MPARAM
)lFromChar
, (MPARAM
)lToChar
); 
 685         ::WinSendMsg(hWnd
, EM_SETSEL
, MPFROM2SHORT((USHORT
)lFromChar
, (USHORT
)lToChar
), (MPARAM
)0); 
 686 } // end of wxTextCtrl::SetSelection 
 688 bool wxTextCtrl::DoLoadFile( 
 689   const wxString
&                   rsFile
, 
 693     if ( wxTextCtrlBase::DoLoadFile(rsFile
, fileType
) ) 
 696         // Update the size limit if needed 
 702 } // end of wxTextCtrl::DoLoadFile 
 704 bool wxTextCtrl::IsModified() const 
 709         bRc 
= (bool)LONGFROMMR(::WinSendMsg(GetHwnd(), MLM_QUERYCHANGED
, 0, 0)); 
 711         bRc 
= (bool)LONGFROMMR(::WinSendMsg(GetHwnd(), EM_QUERYCHANGED
, 0, 0)); 
 713 } // end of wxTextCtrl::IsModified 
 715 void wxTextCtrl::MarkDirty() 
 718         ::WinSendMsg(GetHwnd(), MLM_SETCHANGED
, MPFROMLONG(TRUE
), 0); 
 720         // EM controls do not have a SETCHANGED, what can we do?? 
 721         wxFAIL_MSG( _T("not implemented") ); 
 725 // Makes 'unmodified' 
 727 void wxTextCtrl::DiscardEdits() 
 730         ::WinSendMsg(GetHwnd(), MLM_SETCHANGED
, MPFROMLONG(FALSE
), 0); 
 733         // EM controls do not have a SETCHANGED but issuing a query should reset it 
 735         ::WinSendMsg(GetHwnd(), EM_QUERYCHANGED
, 0, 0); 
 736 } // end of wxTextCtrl::DiscardEdits 
 738 int wxTextCtrl::GetNumberOfLines() const 
 743         nNumLines 
= (int)::WinSendMsg(GetHwnd(), MLM_QUERYLINECOUNT
, 0, 0); 
 747 } // end of wxTextCtrl::GetNumberOfLines 
 749 long wxTextCtrl::XYToPosition( 
 754     long                            lCharIndex 
= 0L; 
 759         lLen 
= (long)::WinSendMsg(GetHwnd(), MLM_QUERYLINELENGTH
, 0, 0); 
 760         lCharIndex 
= ((lLen 
* lY
) + lX
); 
 765 } // end of wxTextCtrl::XYToPosition 
 767 bool wxTextCtrl::PositionToXY( 
 773     HWND                            hWnd 
= GetHwnd(); 
 778         nLineNo 
= (long)::WinSendMsg(hWnd
, MLM_LINEFROMCHAR
, (MPARAM
)lPos
, 0); 
 789     // This gets the char index for the _beginning_ of this line 
 795         lLineWidth 
= (long)::WinSendMsg(hWnd
, MLM_QUERYLINELENGTH
, (MPARAM
)0, (MPARAM
)0); 
 796         lCharIndex 
= (nLineNo 
+ 1) * lLineWidth
; 
 802         vParams
.fsStatus 
= WPM_CCHTEXT
; 
 803         if (::WinSendMsg( hWnd
 
 804                          ,WM_QUERYWINDOWPARAMS
 
 809             lCharIndex 
= vParams
.cchText
; 
 815     if (lCharIndex 
== -1) 
 821     // The X position must therefore be the difference between pos and charIndex 
 824         *plX 
= lPos 
- lCharIndex
; 
 829 } // end of wxTextCtrl::PositionToXY 
 831 void wxTextCtrl::ShowPosition( long WXUNUSED(lPos
) ) 
 833     HWND hWnd 
= GetHwnd(); 
 834     long lCurrentLineLineNo 
= 0L; 
 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. 
 844     // Is this where scrolling is relative to - the line containing the caret? 
 845     // Or is the first visible line??? Try first visible line. 
 850         // In PM this is the actual char position 
 852         lCurrentLineLineNo 
= (long)::WinSendMsg(hWnd
, MLM_QUERYFIRSTCHAR
, (MPARAM
)0, (MPARAM
)0); 
 855         // This will cause a scroll to the selected position 
 857         ::WinSendMsg(hWnd
, MLM_SETSEL
, (MPARAM
)lCurrentLineLineNo
, (MPARAM
)lCurrentLineLineNo
); 
 859 } // end of wxTextCtrl::ShowPosition 
 861 int wxTextCtrl::GetLineLength( long WXUNUSED(lLineNo
) ) const 
 867         lLen 
= (long)::WinSendMsg(GetHwnd(), MLM_QUERYLINELENGTH
, 0, 0); 
 873         vParams
.fsStatus 
= WPM_CCHTEXT
; 
 874         if (::WinSendMsg( GetHwnd() 
 875                          ,WM_QUERYWINDOWPARAMS
 
 880             lLen 
= vParams
.cchText
; 
 886 } // end ofwxTextCtrl::GetLineLength 
 888 wxString 
wxTextCtrl::GetLineText( 
 892     long                            lLen 
= (long)GetLineLength((long)lLineNo
) + 1; 
 897     // There must be at least enough place for the length WORD in the 
 900     lLen 
+= sizeof(WORD
); 
 901     zBuf 
= new wxChar
[lLen
]; 
 908         lLen 
= (long)::WinSendMsg(GetHwnd(), MLM_QUERYLINELENGTH
, 0, 0); 
 909         lIndex 
= lLen 
* lLineNo
; 
 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'; 
 921         vParams
.fsStatus 
= WPM_CCHTEXT
; 
 922         if (::WinSendMsg( GetHwnd() 
 923                          ,WM_QUERYWINDOWPARAMS
 
 927          memcpy((char*)zBuf
, vParams
.pszText
, vParams
.cchText
); 
 928          zBuf
[vParams
.cchText
] = '\0'; 
 933 } // end of wxTextCtrl::GetLineText 
 935 // ---------------------------------------------------------------------------- 
 937 // ---------------------------------------------------------------------------- 
 939 void wxTextCtrl::Undo() 
 944             ::WinSendMsg(GetHwnd(), MLM_UNDO
, 0, 0); 
 945         // Simple entryfields cannot be undone 
 947 } // end of wxTextCtrl::Undo 
 949 void wxTextCtrl::Redo() 
 954             ::WinSendMsg(GetHwnd(), MLM_UNDO
, 0, 0); 
 955         // Simple entryfields cannot be undone 
 957 } // end of wxTextCtrl::Redo 
 959 bool wxTextCtrl::CanUndo() const 
 964         bOk 
= (::WinSendMsg(GetHwnd(), MLM_QUERYUNDO
, 0, 0) != 0); 
 966         bOk 
= false; // can't undo regular edit fields in PM 
 968 } // end of wxTextCtrl::CanUndo 
 970 bool wxTextCtrl::CanRedo() const 
 975         bOk 
= (::WinSendMsg(GetHwnd(), MLM_QUERYUNDO
, 0, 0) != 0); 
 977         bOk 
= false; // can't undo regular edit fields in PM 
 979 } // end of wxTextCtrl::CanRedo 
 981 // ---------------------------------------------------------------------------- 
 982 // implemenation details 
 983 // ---------------------------------------------------------------------------- 
 985 void wxTextCtrl::Command( 
 986   wxCommandEvent
&                   rEvent
 
 989     SetValue(rEvent
.GetString()); 
 990     ProcessCommand (rEvent
); 
 991 } // end of wxTextCtrl::Command 
 993 void wxTextCtrl::OnDropFiles( 
 994   wxDropFilesEvent
&                 rEvent
 
 997     // By default, load the first file into the text window. 
 998     if (rEvent
.GetNumberOfFiles() > 0) 
1000         LoadFile(rEvent
.GetFiles()[0]); 
1002 } // end of wxTextCtrl::OnDropFiles 
1004 WXHBRUSH 
wxTextCtrl::OnCtlColor( WXHDC    hWxDC
, 
1005                                  WXHWND   
WXUNUSED(hWnd
), 
1006                                  WXUINT   
WXUNUSED(uCtlColor
), 
1007                                  WXUINT   
WXUNUSED(uMessage
), 
1008                                  WXWPARAM 
WXUNUSED(wParam
), 
1009                                  WXLPARAM 
WXUNUSED(lParam
) ) 
1011     HPS      hPS 
= (HPS
)hWxDC
; 
1012     wxColour vColBack 
= GetBackgroundColour(); 
1013     wxColour vColFore 
= GetForegroundColour(); 
1014     wxBrush
* pBackgroundBrush 
= wxTheBrushList
->FindOrCreateBrush( vColBack
, wxSOLID 
); 
1018         HBRUSH                      hBrush 
= NULLHANDLE
; 
1022     if (GetParent()->GetTransparentBackground()) 
1023         ::GpiSetBackMix(hPS
, BM_LEAVEALONE
); 
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 
1033 bool wxTextCtrl::OS2ShouldPreProcessMessage( 
1037     return wxControl::OS2ShouldPreProcessMessage(pMsg
); 
1038 } // end of wxTextCtrl::OS2ShouldPreProcessMessage 
1040 void wxTextCtrl::OnChar( 
1044     switch (rEvent
.GetKeyCode()) 
1047             if ( !(m_windowStyle 
& wxTE_MULTILINE
) ) 
1049                 wxCommandEvent      
vEvent(wxEVT_COMMAND_TEXT_ENTER
, m_windowId
); 
1051                 vEvent
.SetEventObject(this); 
1052                 if ( HandleWindowEvent(vEvent
)) 
1055             //else: multiline controls need Enter for themselves 
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. 
1065             // NB: Notice that Ctrl-Tab is handled elsewhere and Alt-Tab is 
1066             //     handled by Windows 
1068                 wxNavigationKeyEvent    vEventNav
; 
1070                 vEventNav
.SetDirection(!rEvent
.ShiftDown()); 
1071                 vEventNav
.SetWindowChange(false); 
1072                 vEventNav
.SetEventObject(this); 
1074                 if ( HandleWindowEvent(vEventNav
) ) 
1080 } // end of wxTextCtrl::OnChar 
1082 bool wxTextCtrl::OS2Command( 
1084 , WXWORD                            
WXUNUSED(vId
) 
1092                 wxFocusEvent        
vEvent( uParam 
== EN_KILLFOCUS 
? wxEVT_KILL_FOCUS
 
1097                 vEvent
.SetEventObject(this); 
1098                 HandleWindowEvent(vEvent
); 
1106                     m_bSkipUpdate 
= false; 
1110                 wxCommandEvent      
vEvent( wxEVT_COMMAND_TEXT_UPDATED
 
1114                 InitCommandEvent(vEvent
); 
1115                 ProcessCommand(vEvent
); 
1121             // The text size limit has been hit - increase it 
1127         case EN_INSERTMODETOGGLE
: 
1138 } // end of wxTextCtrl::OS2Command 
1140 void wxTextCtrl::AdjustSpaceLimit() 
1142     unsigned int                    uLen 
= 0; 
1143     unsigned int                    uLimit 
= 0; 
1145     uLen   
= ::WinQueryWindowTextLength(GetHwnd()); 
1148         uLimit 
= (unsigned int)::WinSendMsg( GetHwnd() 
1159         vParams
.fsStatus 
= WPM_CBCTLDATA
; 
1160         vParams
.pCtlData 
= &Efd
; 
1161         vParams
.cbCtlData 
= sizeof(ENTRYFDATA
); 
1163         if (::WinSendMsg( GetHwnd() 
1164                          ,WM_QUERYWINDOWPARAMS
 
1168             uLimit 
= (unsigned int)Efd
.cchEditLimit
; 
1170             uLimit 
= 32; //PM's default 
1176             uLimit 
= uLen 
+ 0x8000;    // 32Kb 
1177             if (uLimit 
> 0xffff) 
1186             ::WinSendMsg(GetHwnd(), MLM_SETTEXTLIMIT
, MPFROMLONG(uLimit
), 0); 
1188             ::WinSendMsg(GetHwnd(), EM_SETTEXTLIMIT
, MPFROMSHORT(uLimit
), 0); 
1190 } // end of wxTextCtrl::AdjustSpaceLimit 
1192 bool wxTextCtrl::AcceptsFocus() const 
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 
1199     return (IsEditable() || IsMultiLine()) && wxControl::AcceptsFocus(); 
1200 } // end of wxTextCtrl::Command 
1202 wxSize 
wxTextCtrl::DoGetBestSize() const 
1206     wxFont                          vFont 
= (wxFont
)GetFont(); 
1208     wxGetCharSize(GetHWND(), &nCx
, &nCy
, &vFont
); 
1210     int                             wText 
= DEFAULT_ITEM_WIDTH
; 
1211     int                             hText 
= (int)(EDIT_HEIGHT_FROM_CHAR_HEIGHT(nCy
) * .8); 
1213     if (m_windowStyle 
& wxTE_MULTILINE
) 
1215         hText 
*= wxMax(GetNumberOfLines(), 5); 
1217     //else: for single line control everything is ok 
1218     return wxSize(wText
, hText
); 
1219 } // end of wxTextCtrl::DoGetBestSize 
1221 // ---------------------------------------------------------------------------- 
1222 // standard handlers for standard edit menu events 
1223 // ---------------------------------------------------------------------------- 
1225 void wxTextCtrl::OnCut( wxCommandEvent
& WXUNUSED(rEvent
) ) 
1228 } // end of wxTextCtrl::OnCut 
1230 void wxTextCtrl::OnCopy( wxCommandEvent
& WXUNUSED(rEvent
) ) 
1233 } // end of wxTextCtrl::OnCopy 
1235 void wxTextCtrl::OnPaste( wxCommandEvent
& WXUNUSED(rEvent
) ) 
1238 } // end of wxTextCtrl::OnPaste 
1240 void wxTextCtrl::OnUndo( wxCommandEvent
& WXUNUSED(rEvent
) ) 
1243 } // end of wxTextCtrl::OnUndo 
1245 void wxTextCtrl::OnRedo( wxCommandEvent
& WXUNUSED(rEvent
) ) 
1248 } // end of wxTextCtrl::OnRedo 
1250 void wxTextCtrl::OnDelete( wxCommandEvent
& WXUNUSED(rEvent
) ) 
1254     GetSelection( &lFrom
, &lTo 
); 
1256     if (lFrom 
!= -1 && lTo 
!= -1) 
1257         Remove( lFrom
, lTo 
); 
1258 } // end of wxTextCtrl::OnDelete 
1260 void wxTextCtrl::OnSelectAll( wxCommandEvent
& WXUNUSED(rEvent
) ) 
1262     SetSelection(-1, -1); 
1263 } // end of wxTextCtrl::OnSelectAll 
1265 void wxTextCtrl::OnUpdateCut( wxUpdateUIEvent
& rEvent 
) 
1267     rEvent
.Enable(CanCut()); 
1268 } // end of wxTextCtrl::OnUpdateCut 
1270 void wxTextCtrl::OnUpdateCopy( wxUpdateUIEvent
& rEvent 
) 
1272     rEvent
.Enable(CanCopy()); 
1273 } // end of wxTextCtrl::OnUpdateCopy 
1275 void wxTextCtrl::OnUpdatePaste( wxUpdateUIEvent
& rEvent 
) 
1277     rEvent
.Enable(CanPaste()); 
1278 } // end of wxTextCtrl::OnUpdatePaste 
1280 void wxTextCtrl::OnUpdateUndo( wxUpdateUIEvent
& rEvent 
) 
1282     rEvent
.Enable(CanUndo()); 
1283 } // end of wxTextCtrl::OnUpdateUndo 
1285 void wxTextCtrl::OnUpdateRedo( wxUpdateUIEvent
& rEvent 
) 
1287     rEvent
.Enable(CanRedo()); 
1288 } // end of wxTextCtrl::OnUpdateRedo 
1290 void wxTextCtrl::OnUpdateDelete( wxUpdateUIEvent
& rEvent 
) 
1294     GetSelection( &lFrom
, &lTo 
); 
1295     rEvent
.Enable( lFrom 
!= -1L && lTo 
!= -1L && lFrom 
!= lTo 
&& IsEditable()) ; 
1296 } // end of wxTextCtrl::OnUpdateDelete 
1298 void wxTextCtrl::OnUpdateSelectAll( wxUpdateUIEvent
& rEvent 
) 
1300     rEvent
.Enable(GetLastPosition() > 0); 
1301 } // end of wxTextCtrl::OnUpdateSelectAll 
1303 bool wxTextCtrl::SetBackgroundColour( const wxColour
& rColour 
) 
1306         ::WinSendMsg(GetHwnd(), MLM_SETBACKCOLOR
, (MPARAM
)rColour
.GetPixel(), MLE_INDEX
); 
1308 } // end of wxTextCtrl::SetBackgroundColour 
1310 bool wxTextCtrl::SetForegroundColour( const wxColour
& rColour 
) 
1313         ::WinSendMsg(GetHwnd(), MLM_SETTEXTCOLOR
, (MPARAM
)rColour
.GetPixel(), MLE_INDEX
); 
1315 } // end of wxTextCtrl::SetForegroundColour 
1317 bool wxTextCtrl::SetStyle( long lStart
, 
1319                            const wxTextAttr
& WXUNUSED(rStyle
) ) 
1321     HWND hWnd 
= GetHwnd(); 
1332     // We can only change the format of the selection, so select the range we 
1333     // want and restore the old selection later 
1335     long lStartOld
, lEndOld
; 
1337     GetSelection( &lStartOld
, &lEndOld 
); 
1340     // But do we really have to change the selection? 
1342     bool bChangeSel 
= lStart 
!= lStartOld 
|| 
1348             ::WinSendMsg(hWnd
, MLM_SETSEL
, MPFROM2SHORT((USHORT
)lStart
, (USHORT
)lEnd
), 0); 
1350             ::WinSendMsg(hWnd
, EM_SETSEL
, MPFROM2SHORT((USHORT
)lStart
, (USHORT
)lEnd
), 0); 
1354     // TODO:: finish this part 
1357 } // end of wxTextCtrl::SetStyle