]> git.saurik.com Git - wxWidgets.git/blobdiff - src/os2/textctrl.cpp
Try to better revert to the original string value in wxBitmapComboBox::RecreateControl()
[wxWidgets.git] / src / os2 / textctrl.cpp
index 720e6082be0ddc57b38b5d63999634d7d0435d1c..a3ae1dcb3e54c8f7e924e4d3bddba880e19ac74c 100644 (file)
@@ -1,40 +1,66 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        textctrl.cpp
+// Name:        src/os2/textctrl.cpp
 // Purpose:     wxTextCtrl
-// Author:      AUTHOR
+// Author:      David Webster
 // Modified by:
-// Created:     ??/??/98
+// Created:     10/17/99
 // RCS-ID:      $Id$
-// Copyright:   (c) AUTHOR
-// Licence:    wxWindows licence
+// Copyright:   (c) David Webster
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
-#ifdef __GNUG__
-#pragma implementation "textctrl.h"
-#endif
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
 
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fstream.h>
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
 
 #include "wx/textctrl.h"
-#include "wx/settings.h"
-#include "wx/filefn.h"
-#include "wx/utils.h"
 
-#if defined(__BORLANDC__) && !defined(__WIN32__)
-#include <alloc.h>
+#ifndef WX_PRECOMP
+    #include "wx/scrolwin.h"
+    #include "wx/settings.h"
+    #include "wx/brush.h"
+    #include "wx/utils.h"
+    #include "wx/log.h"
+    #include "wx/app.h"
+#endif
+
+#if wxUSE_CLIPBOARD
+    #include "wx/clipbrd.h"
+#endif
+
+#include "wx/textfile.h"
+
+#include "wx/os2/private.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#if wxUSE_IOSTREAMH
+#   include <fstream.h>
 #else
-#ifndef __GNUWIN32__
-#include <malloc.h>
+#   include <fstream>
 #endif
+
+#if !defined(MLE_INDEX)
+#define MLE_INDEX  0
+#define MLE_RGB    1
 #endif
 
-#if !USE_SHARED_LIBRARY
-IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
 
-BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
-       EVT_DROP_FILES(wxTextCtrl::OnDropFiles)
+// ----------------------------------------------------------------------------
+// event tables and other macros
+// ----------------------------------------------------------------------------
+
+IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxTextCtrlBase)
+
+BEGIN_EVENT_TABLE(wxTextCtrl, wxTextCtrlBase)
+    EVT_CHAR(wxTextCtrl::OnChar)
+    EVT_DROP_FILES(wxTextCtrl::OnDropFiles)
+
     EVT_MENU(wxID_CUT, wxTextCtrl::OnCut)
     EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy)
     EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste)
@@ -47,512 +73,1285 @@ BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
     EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo)
     EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo)
 END_EVENT_TABLE()
-#endif
 
-// Text item
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// creation
+// ----------------------------------------------------------------------------
+
 wxTextCtrl::wxTextCtrl()
-#ifndef NO_TEXT_WINDOW_STREAM
- :streambuf()
-#endif
 {
-    m_fileName = "";
 }
 
-bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
-                  const wxString& value,
-           const wxPoint& pos,
-           const wxSize& size, long style,
-           const wxValidator& validator,
-           const wxString& name)
+wxTextCtrl::~wxTextCtrl()
 {
-    m_fileName = "";
-    SetName(name);
-    SetValidator(validator);
-    if (parent) parent->AddChild(this);
+}
 
-    m_windowStyle = style;
+bool wxTextCtrl::Create(
+  wxWindow*                         pParent
+, wxWindowID                        vId
+, const wxString&                   rsValue
+, const wxPoint&                    rPos
+, const wxSize&                     rSize
+, long                              lStyle
+, const wxValidator&                rValidator
+, const wxString&                   rsName
+)
+{
+    //
+    // Base initialization
+    //
+    if ( !CreateBase( pParent
+                     ,vId
+                     ,rPos
+                     ,rSize
+                     ,lStyle
+                     ,rValidator
+                     ,rsName
+                    ))
+        return false;
+
+    wxPoint                         vPos = rPos; // The OS/2 position
+    SWP                             vSwp;
+
+    if (pParent )
+    {
+        pParent->AddChild(this);
+    }
+
+    m_windowStyle = lStyle;
+    m_bIsMLE = false;
+    m_bSkipUpdate = false;
 
-    if ( id == -1 )
-           m_windowId = (int)NewControlId();
+    long                            lSstyle = WS_VISIBLE | WS_TABSTOP;
+
+    //
+    // Single and multiline edit fields are two different controls in PM
+    //
+    if ( m_windowStyle & wxTE_MULTILINE )
+    {
+        lSstyle |= MLS_BORDER | MLS_WORDWRAP;
+        m_bIsMLE = true;
+
+        if ((m_windowStyle & wxTE_NO_VSCROLL) == 0)
+            lSstyle |= MLS_VSCROLL;
+        if (m_windowStyle & wxHSCROLL)
+            lSstyle |= MLS_HSCROLL;
+        if (m_windowStyle & wxTE_READONLY)
+            lSstyle |= MLS_READONLY;
+    }
     else
-           m_windowId = id;
+    {
+        lSstyle |= ES_LEFT | ES_AUTOSCROLL | ES_MARGIN;
+
+        if (m_windowStyle & wxHSCROLL)
+            lSstyle |=  ES_AUTOSCROLL;
+        if (m_windowStyle & wxTE_READONLY)
+            lSstyle |= ES_READONLY;
+        if (m_windowStyle & wxTE_PASSWORD) // hidden input
+            lSstyle |= ES_UNREADABLE;
+    }
 
-    return TRUE;
-}
+    if (m_bIsMLE)
+    {
+        m_hWnd = (WXHWND)::WinCreateWindow( (HWND)GetHwndOf(pParent) // Parent window handle
+                                           ,WC_MLE                   // Window class
+                                           ,rsValue.c_str()     // Initial Text
+                                           ,(ULONG)lSstyle           // Style flags
+                                           ,(LONG)0                  // X pos of origin
+                                           ,(LONG)0                  // Y pos of origin
+                                           ,(LONG)0                  // field width
+                                           ,(LONG)0                  // field height
+                                           ,(HWND)GetHwndOf(pParent) // owner window handle (same as parent
+                                           ,HWND_TOP                 // initial z position
+                                           ,(ULONG)vId               // Window identifier
+                                           ,NULL                     // no control data
+                                           ,NULL                     // no Presentation parameters
+                                          );
+    }
+    else
+    {
+        m_hWnd = (WXHWND)::WinCreateWindow( (HWND)GetHwndOf(pParent) // Parent window handle
+                                           ,WC_ENTRYFIELD            // Window class
+                                           ,rsValue.c_str()     // Initial Text
+                                           ,(ULONG)lSstyle           // Style flags
+                                           ,(LONG)0                  // X pos of origin
+                                           ,(LONG)0                  // Y pos of origin
+                                           ,(LONG)0                  // field width
+                                           ,(LONG)0                  // field height
+                                           ,(HWND)GetHwndOf(pParent) // owner window handle (same as parent
+                                           ,HWND_TOP                 // initial z position
+                                           ,(ULONG)vId               // Window identifier
+                                           ,NULL                     // no control data
+                                           ,NULL                     // no Presentation parameters
+                                          );
+    }
+
+    if (m_hWnd == 0)
+    {
+        return false;
+    }
+
+    SubclassWin(GetHWND());
+
+    //
+    // Set font, position, size and initial value
+    //
+    wxFont*                          pTextFont = new wxFont( 8
+                                                            ,wxMODERN
+                                                            ,wxNORMAL
+                                                            ,wxNORMAL
+                                                           );
+    SetFont(*pTextFont);
+    if (!rsValue.empty())
+    {
+        SetValue(rsValue);
+    }
+    SetupColours();
+    //
+    // If X and/or Y are not zero the difference is the compensation value
+    // for margins for OS/2 controls.
+    //
+    ::WinQueryWindowPos(m_hWnd, &vSwp);
+    SetXComp(vSwp.x);
+    SetYComp(vSwp.y);
+    SetSize( vPos.x - GetXComp()
+            ,vPos.y - GetYComp()
+            ,rSize.x
+            ,rSize.y
+           );
+    delete pTextFont;
+    return true;
+} // end of wxTextCtrl::Create
+
+//
+// Make sure the window style (etc.) reflects the HWND style (roughly)
+//
+void wxTextCtrl::AdoptAttributesFromHWND()
+{
+    HWND                            hWnd = GetHwnd();
+    LONG                            lStyle = ::WinQueryWindowULong(hWnd, QWL_STYLE);
+
+    wxWindow::AdoptAttributesFromHWND();
+
+    if (m_bIsMLE)
+    {
+        m_windowStyle |= wxTE_MULTILINE;
+        if (lStyle & MLS_READONLY)
+            m_windowStyle |= wxTE_READONLY;
+    }
+    else
+    {
+        if (lStyle & ES_UNREADABLE)
+            m_windowStyle |= wxTE_PASSWORD;
+        if (lStyle & ES_READONLY)
+            m_windowStyle |= wxTE_READONLY;
+    }
+} // end of wxTextCtrl::AdoptAttributesFromHWND
+
+WXDWORD wxTextCtrl::OS2GetStyle(
+  long                              lStyle
+, WXDWORD*                          pdwExstyle
+) const
+{
+    //
+    // Default border for the text controls is the sunken one
+    //
+    if ((lStyle & wxBORDER_MASK) == wxBORDER_DEFAULT )
+    {
+        lStyle |= wxBORDER_SUNKEN;
+    }
+
+    long                            dwStyle = wxControl::OS2GetStyle( lStyle
+                                                                     ,pdwExstyle
+                                                                    );
+
+    dwStyle = WS_VISIBLE | WS_TABSTOP;
+
+    //
+    // Single and multiline edit fields are two different controls in PM
+    //
+    if ( m_windowStyle & wxTE_MULTILINE )
+    {
+        dwStyle |= MLS_BORDER | MLS_WORDWRAP;
+        if ((m_windowStyle & wxTE_NO_VSCROLL) == 0)
+            dwStyle |= MLS_VSCROLL;
+        if (m_windowStyle & wxHSCROLL)
+            dwStyle |= MLS_HSCROLL;
+        if (m_windowStyle & wxTE_READONLY)
+            dwStyle |= MLS_READONLY;
+    }
+    else
+    {
+        dwStyle |= ES_LEFT | ES_AUTOSCROLL | ES_MARGIN;
+        if (m_windowStyle & wxHSCROLL)
+            dwStyle |=  ES_AUTOSCROLL;
+        if (m_windowStyle & wxTE_READONLY)
+            dwStyle |= ES_READONLY;
+        if (m_windowStyle & wxTE_PASSWORD) // hidden input
+            dwStyle |= ES_UNREADABLE;
+    }
+    return dwStyle;
+} // end of wxTextCtrl::OS2GetStyle
+
+void wxTextCtrl::SetWindowStyleFlag(
+  long                              lStyle
+)
+{
+    wxControl::SetWindowStyleFlag(lStyle);
+} // end of wxTextCtrl::SetWindowStyleFlag
+
+void wxTextCtrl::SetupColours()
+{
+    wxColour                        vBkgndColour;
+
+    vBkgndColour = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
+    SetBackgroundColour(vBkgndColour);
+    SetForegroundColour(GetParent()->GetForegroundColour());
+    if (m_bIsMLE)
+    {
+        ::WinSendMsg( GetHwnd()
+                     ,MLM_SETTEXTCOLOR
+                     ,(MPARAM)GetParent()->GetForegroundColour().GetPixel()
+                     ,(MPARAM)MLE_RGB
+                    );
+    }
+} // end of wxTextCtrl::SetupColours
+
+// ----------------------------------------------------------------------------
+// set/get the controls text
+// ----------------------------------------------------------------------------
 
 wxString wxTextCtrl::GetValue() const
 {
-    // TODO
-    return wxString("");
-}
+    wxString                        sStr = wxGetWindowText(GetHWND());
+    wxCharBuffer                    buf(sStr.char_str());
+    char*                           zStr = buf.data();
+
+    for ( ; *zStr; zStr++ )
+    {
+        //
+        // this will replace \r\n with just \n
+        //
+        if (*zStr == '\n')
+            *zStr = '\0';
+        if (*zStr == '\r')
+            *zStr = '\n';
+    }
+    return zStr;
+} // end of wxTextCtrl::GetValue
 
-void wxTextCtrl::SetValue(const wxString& value)
+void wxTextCtrl::DoSetValue(
+  const wxString&                   rsValue,
+  int flags
+)
 {
-    // TODO
-}
+    //
+    // If the text is long enough, it's faster to just set it instead of first
+    // comparing it with the old one (chances are that it will be different
+    // anyhow, this comparison is there to avoid flicker for small single-line
+    // edit controls mostly)
+    //
+    if ((rsValue.length() > 0x400) || (rsValue != GetValue()))
+    {
+        if ( flags & SetValue_SendEvent )
+            m_bSkipUpdate = true;
+
+        ::WinSetWindowText(GetHwnd(), rsValue.c_str());
+        AdjustSpaceLimit();
+    }
+} // end of wxTextCtrl::SetValue
 
-void wxTextCtrl::SetSize(int x, int y, int width, int height, int sizeFlags)
+void wxTextCtrl::WriteText(
+  const wxString&                   rsValue
+)
 {
-    // TODO
-}
+    if (m_bIsMLE)
+        ::WinSendMsg(GetHwnd(), MLM_INSERT, MPARAM(rsValue.wx_str()), MPARAM(0));
+    else
+        ::WinSetWindowText(GetHwnd(), rsValue.c_str());
+    AdjustSpaceLimit();
+} // end of wxTextCtrl::WriteText
+
+void wxTextCtrl::AppendText(
+  const wxString&                   rsText
+)
+{
+    SetInsertionPointEnd();
+    WriteText(rsText);
+} // end of wxTextCtrl::AppendText
 
+void wxTextCtrl::Clear()
+{
+    ::WinSetWindowText(GetHwnd(), "");
+} // end of wxTextCtrl::Clear
+
+bool wxTextCtrl::EmulateKeyPress(
+  const wxKeyEvent&                 rEvent
+)
+{
+    SetFocus();
+    return(wxTextCtrlBase::EmulateKeyPress(rEvent));
+} // end of wxTextCtrl::EmulateKeyPress
+
+// ----------------------------------------------------------------------------
 // Clipboard operations
+// ----------------------------------------------------------------------------
+
 void wxTextCtrl::Copy()
 {
-    // TODO
-}
+    if (CanCopy())
+    {
+        HWND hWnd = GetHwnd();
+        if (m_bIsMLE)
+            ::WinSendMsg(hWnd, MLM_COPY, 0, 0);
+        else
+            ::WinSendMsg(hWnd, EM_COPY, 0, 0);
+    }
+} // end of wxTextCtrl::Copy
 
 void wxTextCtrl::Cut()
 {
-    // TODO
-}
+    if (CanCut())
+    {
+        HWND hWnd = GetHwnd();
+
+        if (m_bIsMLE)
+            ::WinSendMsg(hWnd, MLM_CUT, 0, 0);
+        else
+            ::WinSendMsg(hWnd, EM_CUT, 0, 0);
+    }
+} // end of wxTextCtrl::Cut
 
 void wxTextCtrl::Paste()
 {
-    // TODO
-}
+    if (CanPaste())
+    {
+        HWND                        hWnd = GetHwnd();
 
-void wxTextCtrl::SetEditable(bool editable)
-{
-    // TODO
-}
+        ::WinSendMsg(hWnd, EM_PASTE, 0, 0);
+    }
+} // end of wxTextCtrl::Paste
 
-void wxTextCtrl::SetInsertionPoint(long pos)
+bool wxTextCtrl::CanCopy() const
 {
-    // TODO
-}
+    //
+    // Can copy if there's a selection
+    //
+    long                            lFrom = 0L;
+    long                            lTo = 0L;
 
-void wxTextCtrl::SetInsertionPointEnd()
-{
-    long pos = GetLastPosition();
-    SetInsertionPoint(pos);
-}
+    GetSelection(&lFrom, &lTo);
+    return (lFrom != lTo);
+} // end of wxTextCtrl::CanCopy
 
-long wxTextCtrl::GetInsertionPoint() const
+bool wxTextCtrl::CanCut() const
 {
-    // TODO
-    return 0;
-}
+    //
+    // Can cut if there's a selection
+    //
+    long                            lFrom = 0L;
+    long                            lTo = 0L;
 
-long wxTextCtrl::GetLastPosition() const
+    GetSelection(&lFrom, &lTo);
+    return (lFrom != lTo);
+} // end of wxTextCtrl::CanCut
+
+bool wxTextCtrl::CanPaste() const
 {
-    // TODO
-    return 0;
-}
+    bool                            bIsTextAvailable = false;
+
+    if (!IsEditable())
+        return false;
+
+    //
+    // Check for straight text on clipboard
+    //
+    if (::WinOpenClipbrd(vHabmain))
+    {
+        bIsTextAvailable = (::WinQueryClipbrdData(vHabmain, CF_TEXT) != 0);
+        ::WinCloseClipbrd(vHabmain);
+    }
+    return bIsTextAvailable;
+} // end of wxTextCtrl::CanPaste
 
-void wxTextCtrl::Replace(long from, long to, const wxString& value)
+// ----------------------------------------------------------------------------
+// Accessors
+// ----------------------------------------------------------------------------
+
+void wxTextCtrl::SetEditable(
+  bool                              bEditable
+)
 {
-    // TODO
-}
+    HWND                            hWnd = GetHwnd();
 
-void wxTextCtrl::Remove(long from, long to)
+    if (m_bIsMLE)
+        ::WinSendMsg(hWnd, MLM_SETREADONLY, MPFROMLONG(!bEditable), (MPARAM)0);
+    else
+        ::WinSendMsg(hWnd, EM_SETREADONLY, MPFROMLONG(!bEditable), (MPARAM)0);
+} // end of wxTextCtrl::SetEditable
+
+void wxTextCtrl::SetInsertionPoint(
+  long                              lPos
+)
 {
-    // TODO
-}
+    HWND                            hWnd = GetHwnd();
 
-void wxTextCtrl::SetSelection(long from, long to)
+    if (m_bIsMLE)
+        ::WinSendMsg(hWnd, MLM_SETSEL, (MPARAM)lPos, (MPARAM)lPos);
+    else
+        ::WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT((USHORT)lPos, (USHORT)lPos), (MPARAM)0);
+} // end of wxTextCtrl::SetInsertionPoint
+
+void wxTextCtrl::SetInsertionPointEnd()
 {
-    // TODO
-}
+    wxTextPos                       lPos = GetLastPosition();
+
+    //
+    // We must not do anything if the caret is already there because calling
+    // SetInsertionPoint() thaws the controls if Freeze() had been called even
+    // if it doesn't actually move the caret anywhere and so the simple fact of
+    // doing it results in horrible flicker when appending big amounts of text
+    // to the control in a few chunks (see DoAddText() test in the text sample)
+    //
+    if (GetInsertionPoint() == GetLastPosition())
+        return;
+    SetInsertionPoint(lPos);
+} // end of wxTextCtrl::SetInsertionPointEnd
 
-bool wxTextCtrl::LoadFile(const wxString& file)
+long wxTextCtrl::GetInsertionPoint() const
 {
-    if (!wxFileExists(file))
-        return FALSE;
+    WXDWORD                         dwPos = 0L;
 
-    m_fileName = file;
+    if (m_bIsMLE)
+        dwPos = (WXDWORD)::WinSendMsg(GetHwnd(), MLM_QUERYSEL, (MPARAM)MLFQS_MINSEL, 0);
+    else
+    {
+        dwPos = (WXDWORD)::WinSendMsg(GetHwnd(), EM_QUERYSEL, 0, 0);
+        dwPos = SHORT1FROMMP((MPARAM)dwPos);  // the first 16 bit value is the min pos
+    }
+    return (dwPos & 0xFFFF);
+} // end of wxTextCtrl::GetInsertionPoint
 
-    Clear();
+wxTextPos wxTextCtrl::GetLastPosition() const
+{
+    HWND                            hWnd = GetHwnd();
+    long                            lCharIndex;
+    long                            lLineLength;
 
-    ifstream input((char*) (const char*) file, ios::nocreate | ios::in);
+    if (m_bIsMLE)
+    {
+        lCharIndex = 0;
 
-    if (!input.bad())
+        //
+        // This just gets the total text length.  The last will be this value
+        //
+        lLineLength = (long)::WinSendMsg(hWnd, MLM_QUERYTEXTLENGTH, 0, 0);
+    }
+    else
     {
-        struct stat stat_buf;
-        if (stat(file, &stat_buf) < 0)
-            return FALSE;
-        // This may need to be a bigger buffer than the file size suggests,
-        // if it's a UNIX file. Give it an extra 1000 just in case.
-        char *tmp_buffer = (char*)malloc((size_t)(stat_buf.st_size+1+1000));
-        long no_lines = 0;
-        long pos = 0;
-        while (!input.eof() && input.peek() != EOF)
+        WNDPARAMS                   vParams;
+
+        lCharIndex = 0;
+        vParams.fsStatus = WPM_CCHTEXT;
+        if (::WinSendMsg( GetHwnd()
+                         ,WM_QUERYWINDOWPARAMS
+                         ,&vParams
+                         ,0
+                        ))
         {
-            input.getline(wxBuffer, 500);
-               int len = strlen(wxBuffer);
-               wxBuffer[len] = 13;
-               wxBuffer[len+1] = 10;
-               wxBuffer[len+2] = 0;
-               strcpy(tmp_buffer+pos, wxBuffer);
-               pos += strlen(wxBuffer);
-               no_lines++;
-         }
-
-         // TODO add line
+            lLineLength = (long)vParams.cchText;
+        }
+        else
+            lLineLength = 0;
+    }
+    return(lCharIndex + lLineLength);
+} // end of wxTextCtrl::GetLastPosition
 
-         free(tmp_buffer);
+// If the return values from and to are the same, there is no
+// selection.
+void wxTextCtrl::GetSelection(
+  long*                             plFrom
+, long*                             plTo
+) const
+{
+    WXDWORD                         dwPos;
 
-         return TRUE;
+    if (m_bIsMLE)
+        dwPos = (WXDWORD)::WinSendMsg(GetHwnd(), MLM_QUERYSEL, (MPARAM)MLFQS_MINSEL, 0);
+    else
+    {
+        dwPos = (WXDWORD)::WinSendMsg(GetHwnd(), EM_QUERYSEL, 0, 0);
     }
-    return FALSE;
-}
+    *plFrom = SHORT1FROMMP((MPARAM)dwPos);  // the first 16 bit value is the min pos
+    *plTo = SHORT2FROMMP((MPARAM)dwPos);  // the first 16 bit value is the min pos
+} // end of wxTextCtrl::GetSelection
 
-// If file is null, try saved file name first
-// Returns TRUE if succeeds.
-bool wxTextCtrl::SaveFile(const wxString& file)
+bool wxTextCtrl::IsEditable() const
 {
-    wxString theFile(file);
-    if (theFile == "")
-        theFile = m_fileName;
-    if (theFile == "")
-        return FALSE;
-    m_fileName = theFile;
+    if (m_bIsMLE)
+        return((bool)LONGFROMMR(::WinSendMsg(GetHwnd(), MLM_QUERYREADONLY, 0, 0)));
+    else
+        return((bool)LONGFROMMR(::WinSendMsg(GetHwnd(), EM_QUERYREADONLY, 0, 0)));
+} // end of wxTextCtrl::IsEditable
 
-    ofstream output((char*) (const char*) theFile);
-    if (output.bad())
-           return FALSE;
+// ----------------------------------------------------------------------------
+// Editing
+// ----------------------------------------------------------------------------
 
-    // TODO get and save text
+void wxTextCtrl::Replace( long lFrom,
+                          long lTo,
+                          const wxString& rsValue )
+{
+#if wxUSE_CLIPBOARD
+    HWND hWnd = GetHwnd();
 
-    return FALSE;
-}
+    //
+    // Set selection and remove it
+    //
+    if (m_bIsMLE)
+    {
+        ::WinSendMsg(hWnd, MLM_SETSEL, MPFROM2SHORT((USHORT)lFrom, (USHORT)lTo), 0);
+        ::WinSendMsg(hWnd, MLM_CUT, 0, 0);
+    }
+    else
+    {
+        ::WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT((USHORT)lFrom, (USHORT)lTo), 0);
+        ::WinSendMsg(hWnd, EM_CUT, 0, 0);
+    }
+
+    //
+    // Now replace with 'value', by pasting.
+    //
+    wxSetClipboardData(wxDF_TEXT, (wxObject *) (const wxChar *)rsValue, 0, 0);
 
-void wxTextCtrl::WriteText(const wxString& text)
+    // Paste into edit control
+    if (m_bIsMLE)
+        ::WinSendMsg(hWnd, MLM_PASTE, (MPARAM)0, (MPARAM)0);
+    else
+        ::WinSendMsg(hWnd, EM_PASTE, (MPARAM)0, (MPARAM)0);
+#else
+    wxUnusedVar(lFrom);
+    wxUnusedVar(lTo);
+    wxUnusedVar(rsValue);
+    wxFAIL_MSG("wxTextCtrl::Replace not implemented if wxUSE_CLIPBOARD is 0.");
+#endif
+}  // end of wxTextCtrl::Replace
+
+void wxTextCtrl::Remove(
+  long                              lFrom
+, long                              lTo
+)
 {
-    // TODO write text to control
-}
+    HWND                            hWnd      = GetHwnd();
+
+    if (m_bIsMLE)
+    {
+        ::WinSendMsg(hWnd, MLM_SETSEL, MPFROM2SHORT((USHORT)lFrom, (USHORT)lTo), 0);
+        ::WinSendMsg(hWnd, MLM_CUT, 0, 0);
+    }
+    else
+    {
+        ::WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT((USHORT)lFrom, (USHORT)lTo), 0);
+        ::WinSendMsg(hWnd, EM_CUT, 0, 0);
+    }
+} // end of wxTextCtrl::Remove
 
-void wxTextCtrl::AppendText(const wxString& text)
+void wxTextCtrl::SetSelection(
+  long                              lFrom
+, long                              lTo
+)
 {
-    // TODO append text to control
-}
+    HWND                            hWnd = GetHwnd();
+    long                            lFromChar = lFrom;
+    long                            lToChar = lTo;
+
+    //
+    // If from and to are both -1, it means (in wxWidgets) that all text should
+    // be selected. Translate into Windows convention
+    //
+    if ((lFrom == -1L) && (lTo == -1L))
+    {
+        lFromChar = 0L;
+        lToChar   = -1L;
+    }
+    if (m_bIsMLE)
+        ::WinSendMsg(hWnd, MLM_SETSEL, (MPARAM)lFromChar, (MPARAM)lToChar);
+    else
+        ::WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT((USHORT)lFromChar, (USHORT)lToChar), (MPARAM)0);
+} // end of wxTextCtrl::SetSelection
 
-void wxTextCtrl::Clear()
+bool wxTextCtrl::DoLoadFile(
+  const wxString&                   rsFile,
+  int                               fileType
+)
 {
-    // TODO
-}
+    if ( wxTextCtrlBase::DoLoadFile(rsFile, fileType) )
+    {
+        //
+        // Update the size limit if needed
+        //
+        AdjustSpaceLimit();
+        return true;
+    }
+    return false;
+} // end of wxTextCtrl::DoLoadFile
 
 bool wxTextCtrl::IsModified() const
 {
-    // TODO
-    return FALSE;
+    bool                            bRc;
+
+    if (m_bIsMLE)
+        bRc = (bool)LONGFROMMR(::WinSendMsg(GetHwnd(), MLM_QUERYCHANGED, 0, 0));
+    else
+        bRc = (bool)LONGFROMMR(::WinSendMsg(GetHwnd(), EM_QUERYCHANGED, 0, 0));
+    return bRc;
+} // end of wxTextCtrl::IsModified
+
+void wxTextCtrl::MarkDirty()
+{
+    if (m_bIsMLE)
+        ::WinSendMsg(GetHwnd(), MLM_SETCHANGED, MPFROMLONG(TRUE), 0);
+    else
+        // EM controls do not have a SETCHANGED, what can we do??
+        wxFAIL_MSG( wxT("not implemented") );
 }
 
+//
 // Makes 'unmodified'
+//
 void wxTextCtrl::DiscardEdits()
 {
-    // TODO
-}
+    if (m_bIsMLE)
+        ::WinSendMsg(GetHwnd(), MLM_SETCHANGED, MPFROMLONG(FALSE), 0);
+    else
+        //
+        // EM controls do not have a SETCHANGED but issuing a query should reset it
+        //
+        ::WinSendMsg(GetHwnd(), EM_QUERYCHANGED, 0, 0);
+} // end of wxTextCtrl::DiscardEdits
 
 int wxTextCtrl::GetNumberOfLines() const
 {
-    // TODO
-    return 0;
-}
+    int                             nNumLines;
 
-long wxTextCtrl::XYToPosition(long x, long y) const
+    if (m_bIsMLE)
+        nNumLines = (int)::WinSendMsg(GetHwnd(), MLM_QUERYLINECOUNT, 0, 0);
+    else
+        nNumLines = 1;
+    return nNumLines;
+} // end of wxTextCtrl::GetNumberOfLines
+
+long wxTextCtrl::XYToPosition(
+  long                              lX
+, long                              lY
+) const
 {
-    // TODO
-    return 0;
-}
+    long                            lCharIndex = 0L;
+    long                            lLen;
 
-void wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
+    if (m_bIsMLE)
+    {
+        lLen = (long)::WinSendMsg(GetHwnd(), MLM_QUERYLINELENGTH, 0, 0);
+        lCharIndex = ((lLen * lY) + lX);
+    }
+    else
+        lCharIndex = lX;
+    return lCharIndex;
+} // end of wxTextCtrl::XYToPosition
+
+bool wxTextCtrl::PositionToXY(
+  long                              lPos
+, long*                             plX
+, long*                             plY
+) const
 {
-    // TODO
-}
+    HWND                            hWnd = GetHwnd();
+    long                            nLineNo = -1;
+    long                            lCharIndex = 0;
 
-void wxTextCtrl::ShowPosition(long pos)
-{
-    // TODO
-}
+    if (m_bIsMLE)
+        nLineNo = (long)::WinSendMsg(hWnd, MLM_LINEFROMCHAR, (MPARAM)lPos, 0);
+    else
+        nLineNo = 0;
 
-int wxTextCtrl::GetLineLength(long lineNo) const
-{
-    // TODO
-    return 0;
-}
+    if (nLineNo == -1)
+    {
+        // no such line
+        return false;
+    }
 
-wxString wxTextCtrl::GetLineText(long lineNo) const
-{
-    // TODO
-    return wxString("");
-}
+    //
+    // This gets the char index for the _beginning_ of this line
+    //
+    long                            lLineWidth;
 
-bool wxTextCtrl::CanCopy() const
-{
-    // Can copy if there's a selection
-    long from, to;
-    GetSelection(& from, & to);
-    return (from != to) ;
-}
+    if (m_bIsMLE)
+    {
+        lLineWidth = (long)::WinSendMsg(hWnd, MLM_QUERYLINELENGTH, (MPARAM)0, (MPARAM)0);
+        lCharIndex = (nLineNo + 1) * lLineWidth;
+    }
+    else
+    {
+        WNDPARAMS                   vParams;
+
+        vParams.fsStatus = WPM_CCHTEXT;
+        if (::WinSendMsg( hWnd
+                         ,WM_QUERYWINDOWPARAMS
+                         ,&vParams
+                         ,0
+                        ))
+        {
+            lCharIndex = vParams.cchText;
+        }
+        else
+            lCharIndex = 32;
+    }
 
-bool wxTextCtrl::CanCut() const
+    if (lCharIndex == -1)
+    {
+        return false;
+    }
+
+    //
+    // The X position must therefore be the difference between pos and charIndex
+    //
+    if (plX)
+        *plX = lPos - lCharIndex;
+    if (plY)
+        *plY = nLineNo;
+
+    return true;
+} // end of wxTextCtrl::PositionToXY
+
+void wxTextCtrl::ShowPosition( long WXUNUSED(lPos) )
 {
-    // Can cut if there's a selection
-    long from, to;
-    GetSelection(& from, & to);
-    return (from != to) ;
-}
+    HWND hWnd = GetHwnd();
+    long lCurrentLineLineNo = 0L;
+
+    // To scroll to a position, we pass the number of lines and characters
+    // to scroll *by*. This means that we need to:
+    // (1) Find the line position of the current line.
+    // (2) Find the line position of pos.
+    // (3) Scroll by (pos - current).
+    // For now, ignore the horizontal scrolling.
+
+    //
+    // Is this where scrolling is relative to - the line containing the caret?
+    // Or is the first visible line??? Try first visible line.
+    //
+    if (m_bIsMLE)
+    {
+        //
+        // In PM this is the actual char position
+        //
+        lCurrentLineLineNo = (long)::WinSendMsg(hWnd, MLM_QUERYFIRSTCHAR, (MPARAM)0, (MPARAM)0);
+
+        //
+        // This will cause a scroll to the selected position
+        //
+        ::WinSendMsg(hWnd, MLM_SETSEL, (MPARAM)lCurrentLineLineNo, (MPARAM)lCurrentLineLineNo);
+    }
+} // end of wxTextCtrl::ShowPosition
 
-bool wxTextCtrl::CanPaste() const
+int wxTextCtrl::GetLineLength( long WXUNUSED(lLineNo) ) const
 {
-    return IsEditable() ;
-}
+    long lLen = 0L;
+
+    if (m_bIsMLE)
+    {
+        lLen = (long)::WinSendMsg(GetHwnd(), MLM_QUERYLINELENGTH, 0, 0);
+    }
+    else
+    {
+        WNDPARAMS vParams;
+
+        vParams.fsStatus = WPM_CCHTEXT;
+        if (::WinSendMsg( GetHwnd()
+                         ,WM_QUERYWINDOWPARAMS
+                         ,&vParams
+                         ,0
+                        ))
+        {
+            lLen = vParams.cchText;
+        }
+        else
+            lLen = 32;
+    }
+    return lLen;
+} // end ofwxTextCtrl::GetLineLength
 
+wxString wxTextCtrl::GetLineText(
+  long                              lLineNo
+) const
+{
+    long                            lLen = (long)GetLineLength((long)lLineNo) + 1;
+    wxString                        sStr;
+    wxChar*                         zBuf;
+
+    //
+    // There must be at least enough place for the length WORD in the
+    // buffer
+    //
+    lLen += sizeof(WORD);
+    zBuf = new wxChar[lLen];
+    if (m_bIsMLE)
+    {
+        long                        lIndex;
+        long                        lBuflen;
+        long                        lCopied;
+
+        lLen = (long)::WinSendMsg(GetHwnd(), MLM_QUERYLINELENGTH, 0, 0);
+        lIndex = lLen * lLineNo;
+
+        ::WinSendMsg(GetHwnd(), MLM_SETSEL, (MPARAM)lIndex, (MPARAM)lIndex);
+        ::WinSendMsg(GetHwnd(), MLM_SETIMPORTEXPORT, MPFROMP(zBuf), MPFROMSHORT((USHORT)WXSIZEOF(zBuf)));
+        lBuflen = (long)::WinSendMsg(GetHwnd(), MLM_QUERYFORMATTEXTLENGTH, MPFROMLONG(lIndex), MPFROMLONG(-1));
+        lCopied = (long)::WinSendMsg(GetHwnd(), MLM_EXPORT, MPFROMP(&lIndex), MPFROMP(&lBuflen));
+        zBuf[lCopied] = '\0';
+    }
+    else
+    {
+        WNDPARAMS                   vParams;
+
+        vParams.fsStatus = WPM_CCHTEXT;
+        if (::WinSendMsg( GetHwnd()
+                         ,WM_QUERYWINDOWPARAMS
+                         ,&vParams
+                         ,0
+                        ))
+         memcpy((char*)zBuf, vParams.pszText, vParams.cchText);
+         zBuf[vParams.cchText] = '\0';
+     }
+     sStr = zBuf;
+     delete [] zBuf;
+     return sStr;
+} // end of wxTextCtrl::GetLineText
+
+// ----------------------------------------------------------------------------
 // Undo/redo
+// ----------------------------------------------------------------------------
+
 void wxTextCtrl::Undo()
 {
-    // TODO
-}
+    if (CanUndo())
+    {
+        if (m_bIsMLE)
+            ::WinSendMsg(GetHwnd(), MLM_UNDO, 0, 0);
+        // Simple entryfields cannot be undone
+    }
+} // end of wxTextCtrl::Undo
 
 void wxTextCtrl::Redo()
 {
-    // TODO
-}
+    if (CanRedo())
+    {
+        if (m_bIsMLE)
+            ::WinSendMsg(GetHwnd(), MLM_UNDO, 0, 0);
+        // Simple entryfields cannot be undone
+    }
+} // end of wxTextCtrl::Redo
 
 bool wxTextCtrl::CanUndo() const
 {
-    // TODO
-    return FALSE;
-}
+    bool                            bOk;
+
+    if (m_bIsMLE)
+        bOk = (::WinSendMsg(GetHwnd(), MLM_QUERYUNDO, 0, 0) != 0);
+    else
+        bOk = false; // can't undo regular edit fields in PM
+    return bOk;
+} // end of wxTextCtrl::CanUndo
 
 bool wxTextCtrl::CanRedo() const
 {
-    // TODO
-    return FALSE;
-}
+    bool                            bOk;
 
-// If the return values from and to are the same, there is no
-// selection.
-void wxTextCtrl::GetSelection(long* from, long* to) const
-{
-    // TODO
-    *from = 0;
-    *to = 0;
-}
+    if (m_bIsMLE)
+        bOk = (::WinSendMsg(GetHwnd(), MLM_QUERYUNDO, 0, 0) != 0);
+    else
+        bOk = false; // can't undo regular edit fields in PM
+    return bOk;
+} // end of wxTextCtrl::CanRedo
 
-bool wxTextCtrl::IsEditable() const
-{
-    // TODO
-    return FALSE;
-}
+// ----------------------------------------------------------------------------
+// implemenation details
+// ----------------------------------------------------------------------------
 
-void wxTextCtrl::Command(wxCommandEvent & event)
+void wxTextCtrl::Command(
+  wxCommandEvent&                   rEvent
+)
 {
-    SetValue (event.GetString());
-    ProcessCommand (event);
-}
+    SetValue(rEvent.GetString());
+    ProcessCommand (rEvent);
+} // end of wxTextCtrl::Command
 
-void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event)
+void wxTextCtrl::OnDropFiles(
+  wxDropFilesEvent&                 rEvent
+)
 {
     // By default, load the first file into the text window.
-    if (event.GetNumberOfFiles() > 0)
+    if (rEvent.GetNumberOfFiles() > 0)
     {
-        LoadFile(event.GetFiles()[0]);
+        LoadFile(rEvent.GetFiles()[0]);
     }
-}
-
-// The streambuf code was partly taken from chapter 3 by Jerry Schwarz of
-// AT&T's "C++ Lanuage System Release 3.0 Library Manual" - Stein Somers
-
-//=========================================================================
-// Called then the buffer is full (gcc 2.6.3) 
-// or when "endl" is output (Borland 4.5)
-//=========================================================================
-// Class declaration using multiple inheritance doesn't work properly for
-// Borland. See note in wb_text.h.
-#ifndef NO_TEXT_WINDOW_STREAM
-int wxTextCtrl::overflow(int c)
-{
-  // Make sure there is a holding area
-  if ( allocate()==EOF )
-  {
-    wxError("Streambuf allocation failed","Internal error");
-    return EOF;
-  }
-  
-  // Verify that there are no characters in get area
-  if ( gptr() && gptr() < egptr() )
-  {
-     wxError("Who's trespassing my get area?","Internal error");
-     return EOF;
-  }
-
-  // Reset get area
-  setg(0,0,0);
-
-  // Make sure there is a put area
-  if ( ! pptr() )
-  {
-/* This doesn't seem to be fatal so comment out error message */
-//    wxError("Put area not opened","Internal error");
-    setp( base(), base() );
-  }
-
-  // Determine how many characters have been inserted but no consumed
-  int plen = pptr() - pbase();
-
-  // Now Jerry relies on the fact that the buffer is at least 2 chars
-  // long, but the holding area "may be as small as 1" ???
-  // And we need an additional \0, so let's keep this inefficient but
-  // safe copy.
-
-  // If c!=EOF, it is a character that must also be comsumed
-  int xtra = c==EOF? 0 : 1;
-
-  // Write temporary C-string to wxTextWindow
-  {
-  char *txt = new char[plen+xtra+1];
-  memcpy(txt, pbase(), plen);
-  txt[plen] = (char)c;     // append c
-  txt[plen+xtra] = '\0';   // append '\0' or overwrite c
-    // If the put area already contained \0, output will be truncated there
-  AppendText(txt);
-    delete[] txt;
-  }
-
-  // Reset put area
-  setp(pbase(), epptr());
-
-#if defined(__WATCOMC__)
-  return __NOT_EOF;
-#elif defined(zapeof)     // HP-UX (all cfront based?)
-  return zapeof(c);
-#else
-  return c!=EOF ? c : 0;  // this should make everybody happy
-#endif
-}
+} // end of wxTextCtrl::OnDropFiles
+
+WXHBRUSH wxTextCtrl::OnCtlColor( WXHDC    hWxDC,
+                                 WXHWND   WXUNUSED(hWnd),
+                                 WXUINT   WXUNUSED(uCtlColor),
+                                 WXUINT   WXUNUSED(uMessage),
+                                 WXWPARAM WXUNUSED(wParam),
+                                 WXLPARAM WXUNUSED(lParam) )
+{
+    HPS      hPS = (HPS)hWxDC;
+    wxColour vColBack = GetBackgroundColour();
+    wxColour vColFore = GetForegroundColour();
+    wxBrush* pBackgroundBrush = wxTheBrushList->FindOrCreateBrush( vColBack, wxSOLID );
 
-//=========================================================================
-// called then "endl" is output (gcc) or then explicit sync is done (Borland)
-//=========================================================================
-int wxTextCtrl::sync()
-{
-  // Verify that there are no characters in get area
-  if ( gptr() && gptr() < egptr() )
-  {
-     wxError("Who's trespassing my get area?","Internal error");
-     return EOF;
-  }
-
-  if ( pptr() && pptr() > pbase() ) return overflow(EOF);
-
-  return 0;
-/* OLD CODE
-  int len = pptr() - pbase();
-  char *txt = new char[len+1];
-  strncpy(txt, pbase(), len);
-  txt[len] = '\0';
-  (*this) << txt;
-  setp(pbase(), epptr());
-  delete[] txt;
-  return 0;
-*/
-}
+    if (m_bUseCtl3D)
+    {
+        HBRUSH                      hBrush = NULLHANDLE;
 
-//=========================================================================
-// Should not be called by a "ostream". Used by a "istream"
-//=========================================================================
-int wxTextCtrl::underflow()
+        return hBrush;
+    }
+    if (GetParent()->GetTransparentBackground())
+        ::GpiSetBackMix(hPS, BM_LEAVEALONE);
+    else
+        ::GpiSetBackMix(hPS, BM_OVERPAINT);
+    if (!IsEnabled() && (GetWindowStyle() & wxTE_MULTILINE) == 0)
+        vColBack = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
+    ::GpiSetBackColor(hPS, vColBack.GetPixel());
+    ::GpiSetColor(hPS, vColFore.GetPixel());
+    return (WXHBRUSH)pBackgroundBrush->GetResourceHandle();
+} // end of wxTextCtrl::OnCtlColor
+
+bool wxTextCtrl::OS2ShouldPreProcessMessage(
+  WXMSG*                            pMsg
+)
 {
-  return EOF;
-}
-#endif
+    return wxControl::OS2ShouldPreProcessMessage(pMsg);
+} // end of wxTextCtrl::OS2ShouldPreProcessMessage
 
-wxTextCtrl& wxTextCtrl::operator<<(const wxString& s)
+void wxTextCtrl::OnChar(
+  wxKeyEvent&                       rEvent
+)
 {
-    AppendText(s);
-    return *this;
-}
+    switch (rEvent.GetKeyCode())
+    {
+        case WXK_RETURN:
+            if ( !(m_windowStyle & wxTE_MULTILINE) )
+            {
+                wxCommandEvent      vEvent(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
+
+                vEvent.SetEventObject(this);
+                if ( HandleWindowEvent(vEvent))
+                    return;
+            }
+            //else: multiline controls need Enter for themselves
+
+            break;
+
+        case WXK_TAB:
+            // always produce navigation event - even if we process TAB
+            // ourselves the fact that we got here means that the user code
+            // decided to skip processing of this TAB - probably to let it
+            // do its default job.
+            //
+            // NB: Notice that Ctrl-Tab is handled elsewhere and Alt-Tab is
+            //     handled by Windows
+            {
+                wxNavigationKeyEvent    vEventNav;
+
+                vEventNav.SetDirection(!rEvent.ShiftDown());
+                vEventNav.SetWindowChange(false);
+                vEventNav.SetEventObject(this);
+
+                if ( HandleWindowEvent(vEventNav) )
+                    return;
+            }
+            break;
+    }
+    rEvent.Skip();
+} // end of wxTextCtrl::OnChar
 
-wxTextCtrl& wxTextCtrl::operator<<(float f)
+bool wxTextCtrl::OS2Command(
+  WXUINT                            uParam
+, WXWORD                            WXUNUSED(vId)
+)
 {
-    wxString str;
-    str.Printf("%.2f", f);
-    AppendText(str);
-    return *this;
-}
+    switch (uParam)
+    {
+        case EN_SETFOCUS:
+        case EN_KILLFOCUS:
+            {
+                wxFocusEvent        vEvent( uParam == EN_KILLFOCUS ? wxEVT_KILL_FOCUS
+                                                                   : wxEVT_SET_FOCUS
+                                           ,m_windowId
+                                          );
+
+                vEvent.SetEventObject(this);
+                HandleWindowEvent(vEvent);
+            }
+            break;
+
+        case EN_CHANGE:
+            {
+                if (m_bSkipUpdate)
+                {
+                    m_bSkipUpdate = false;
+                    break;
+                }
+
+                wxCommandEvent      vEvent( wxEVT_COMMAND_TEXT_UPDATED
+                                           ,m_windowId
+                                          );
+
+                InitCommandEvent(vEvent);
+                ProcessCommand(vEvent);
+            }
+            break;
+
+        case EN_OVERFLOW:
+            //
+            // The text size limit has been hit - increase it
+            //
+            AdjustSpaceLimit();
+            break;
+
+        case EN_SCROLL:
+        case EN_INSERTMODETOGGLE:
+        case EN_MEMERROR:
+            return false;
+        default:
+            return false;
+    }
 
-wxTextCtrl& wxTextCtrl::operator<<(double d)
-{
-    wxString str;
-    str.Printf("%.2f", d);
-    AppendText(str);
-    return *this;
-}
+    //
+    // Processed
+    //
+    return true;
+} // end of wxTextCtrl::OS2Command
 
-wxTextCtrl& wxTextCtrl::operator<<(int i)
+void wxTextCtrl::AdjustSpaceLimit()
 {
-    wxString str;
-    str.Printf("%d", i);
-    AppendText(str);
-    return *this;
-}
+    unsigned int                    uLen = 0;
+    unsigned int                    uLimit = 0;
 
-wxTextCtrl& wxTextCtrl::operator<<(long i)
-{
-    wxString str;
-    str.Printf("%ld", i);
-    AppendText(str);
-    return *this;
-}
+    uLen   = ::WinQueryWindowTextLength(GetHwnd());
+    if (m_bIsMLE)
+    {
+        uLimit = (unsigned int)::WinSendMsg( GetHwnd()
+                                            ,MLM_QUERYTEXTLIMIT
+                                            ,0
+                                            ,0
+                                           );
+    }
+    else
+    {
+        ENTRYFDATA                  Efd;
+        WNDPARAMS                   vParams;
+
+        vParams.fsStatus = WPM_CBCTLDATA;
+        vParams.pCtlData = &Efd;
+        vParams.cbCtlData = sizeof(ENTRYFDATA);
+
+        if (::WinSendMsg( GetHwnd()
+                         ,WM_QUERYWINDOWPARAMS
+                         ,&vParams
+                         ,0
+                        ))
+            uLimit = (unsigned int)Efd.cchEditLimit;
+        else
+            uLimit = 32; //PM's default
+    }
+    if (uLen >= uLimit)
+    {
+        if (m_bIsMLE)
+        {
+            uLimit = uLen + 0x8000;    // 32Kb
+            if (uLimit > 0xffff)
+            {
+                uLimit = 0L;
+            }
+        }
+        else
+            uLimit = 0x7fff;
+
+        if (m_bIsMLE)
+            ::WinSendMsg(GetHwnd(), MLM_SETTEXTLIMIT, MPFROMLONG(uLimit), 0);
+        else
+            ::WinSendMsg(GetHwnd(), EM_SETTEXTLIMIT, MPFROMSHORT(uLimit), 0);
+    }
+} // end of wxTextCtrl::AdjustSpaceLimit
 
-wxTextCtrl& wxTextCtrl::operator<<(const char c)
+bool wxTextCtrl::AcceptsFocus() const
+{
+    //
+    // We don't want focus if we can't be edited unless we're a multiline
+    // control because then it might be still nice to get focus from keyboard
+    // to be able to scroll it without mouse
+    //
+    return (IsEditable() || IsMultiLine()) && wxControl::AcceptsFocus();
+} // end of wxTextCtrl::Command
+
+wxSize wxTextCtrl::DoGetBestSize() const
 {
-    char buf[2];
+    int                             nCx;
+    int                             nCy;
+    wxFont                          vFont = (wxFont)GetFont();
 
-    buf[0] = c;
-    buf[1] = 0;
-    AppendText(buf);
-    return *this;
-}
+    wxGetCharSize(GetHWND(), &nCx, &nCy, &vFont);
+
+    int                             wText = DEFAULT_ITEM_WIDTH;
+    int                             hText = (int)(EDIT_HEIGHT_FROM_CHAR_HEIGHT(nCy) * .8);
+
+    if (m_windowStyle & wxTE_MULTILINE)
+    {
+        hText *= wxMax(GetNumberOfLines(), 5);
+    }
+    //else: for single line control everything is ok
+    return wxSize(wText, hText);
+} // end of wxTextCtrl::DoGetBestSize
+
+// ----------------------------------------------------------------------------
+// standard handlers for standard edit menu events
+// ----------------------------------------------------------------------------
 
-void wxTextCtrl::OnCut(wxCommandEvent& event)
+void wxTextCtrl::OnCut( wxCommandEvent& WXUNUSED(rEvent) )
 {
     Cut();
-}
+} // end of wxTextCtrl::OnCut
 
-void wxTextCtrl::OnCopy(wxCommandEvent& event)
+void wxTextCtrl::OnCopy( wxCommandEvent& WXUNUSED(rEvent) )
 {
     Copy();
-}
+} // end of wxTextCtrl::OnCopy
 
-void wxTextCtrl::OnPaste(wxCommandEvent& event)
+void wxTextCtrl::OnPaste( wxCommandEvent& WXUNUSED(rEvent) )
 {
     Paste();
-}
+} // end of wxTextCtrl::OnPaste
 
-void wxTextCtrl::OnUndo(wxCommandEvent& event)
+void wxTextCtrl::OnUndo( wxCommandEvent& WXUNUSED(rEvent) )
 {
     Undo();
-}
+} // end of wxTextCtrl::OnUndo
 
-void wxTextCtrl::OnRedo(wxCommandEvent& event)
+void wxTextCtrl::OnRedo( wxCommandEvent& WXUNUSED(rEvent) )
 {
     Redo();
-}
+} // end of wxTextCtrl::OnRedo
 
-void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event)
+void wxTextCtrl::OnDelete( wxCommandEvent& WXUNUSED(rEvent) )
 {
-    event.Enable( CanCut() );
-}
+    long lFrom, lTo;
+
+    GetSelection( &lFrom, &lTo );
 
-void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event)
+    if (lFrom != -1 && lTo != -1)
+        Remove( lFrom, lTo );
+} // end of wxTextCtrl::OnDelete
+
+void wxTextCtrl::OnSelectAll( wxCommandEvent& WXUNUSED(rEvent) )
 {
-    event.Enable( CanCopy() );
-}
+    SetSelection(-1, -1);
+} // end of wxTextCtrl::OnSelectAll
 
-void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event)
+void wxTextCtrl::OnUpdateCut( wxUpdateUIEvent& rEvent )
 {
-    event.Enable( CanPaste() );
-}
+    rEvent.Enable(CanCut());
+} // end of wxTextCtrl::OnUpdateCut
 
-void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event)
+void wxTextCtrl::OnUpdateCopy( wxUpdateUIEvent& rEvent )
 {
-    event.Enable( CanUndo() );
-}
+    rEvent.Enable(CanCopy());
+} // end of wxTextCtrl::OnUpdateCopy
 
-void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event)
+void wxTextCtrl::OnUpdatePaste( wxUpdateUIEvent& rEvent )
 {
-    event.Enable( CanRedo() );
-}
+    rEvent.Enable(CanPaste());
+} // end of wxTextCtrl::OnUpdatePaste
+
+void wxTextCtrl::OnUpdateUndo( wxUpdateUIEvent& rEvent )
+{
+    rEvent.Enable(CanUndo());
+} // end of wxTextCtrl::OnUpdateUndo
+
+void wxTextCtrl::OnUpdateRedo( wxUpdateUIEvent& rEvent )
+{
+    rEvent.Enable(CanRedo());
+} // end of wxTextCtrl::OnUpdateRedo
+
+void wxTextCtrl::OnUpdateDelete( wxUpdateUIEvent& rEvent )
+{
+    long lFrom, lTo;
+
+    GetSelection( &lFrom, &lTo );
+    rEvent.Enable( lFrom != -1L && lTo != -1L && lFrom != lTo && IsEditable()) ;
+} // end of wxTextCtrl::OnUpdateDelete
+
+void wxTextCtrl::OnUpdateSelectAll( wxUpdateUIEvent& rEvent )
+{
+    rEvent.Enable(GetLastPosition() > 0);
+} // end of wxTextCtrl::OnUpdateSelectAll
+
+bool wxTextCtrl::SetBackgroundColour( const wxColour& rColour )
+{
+    if (m_bIsMLE)
+        ::WinSendMsg(GetHwnd(), MLM_SETBACKCOLOR, (MPARAM)rColour.GetPixel(), MLE_INDEX);
+    return true;
+} // end of wxTextCtrl::SetBackgroundColour
+
+bool wxTextCtrl::SetForegroundColour( const wxColour& rColour )
+{
+    if (m_bIsMLE)
+        ::WinSendMsg(GetHwnd(), MLM_SETTEXTCOLOR, (MPARAM)rColour.GetPixel(), MLE_INDEX);
+    return true;
+} // end of wxTextCtrl::SetForegroundColour
+
+bool wxTextCtrl::SetStyle( long lStart,
+                           long lEnd,
+                           const wxTextAttr& WXUNUSED(rStyle) )
+{
+    HWND hWnd = GetHwnd();
+
+    if (lStart > lEnd)
+    {
+        long lTmp = lStart;
+
+        lStart = lEnd;
+        lEnd   = lTmp;
+    }
+
+    //
+    // We can only change the format of the selection, so select the range we
+    // want and restore the old selection later
+    //
+    long lStartOld, lEndOld;
+
+    GetSelection( &lStartOld, &lEndOld );
+
+    //
+    // But do we really have to change the selection?
+    //
+    bool bChangeSel = lStart != lStartOld ||
+                      lEnd != lEndOld;
+
+    if (bChangeSel)
+    {
+        if (m_bIsMLE)
+            ::WinSendMsg(hWnd, MLM_SETSEL, MPFROM2SHORT((USHORT)lStart, (USHORT)lEnd), 0);
+        else
+            ::WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT((USHORT)lStart, (USHORT)lEnd), 0);
+    }
+
+    //
+    // TODO:: finish this part
+    //
+    return true;
+} // end of wxTextCtrl::SetStyle