]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/textctrl.cpp
moved SEH stuff to crashrpt.cpp
[wxWidgets.git] / src / msw / textctrl.cpp
index 4d90bd0d7220a6f5d61ed6ff997d8ce12b0bfb49..05df7e86d299124d2adcc028d3ae79b4ee27a0c9 100644 (file)
@@ -5,8 +5,8 @@
 // Modified by:
 // Created:     04/01/98
 // RCS-ID:      $Id$
 // Modified by:
 // Created:     04/01/98
 // RCS-ID:      $Id$
-// Copyright:   (c) Julian Smart and Markus Holzem
-// Licence:     wxWindows license
+// Copyright:   (c) Julian Smart
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 // ============================================================================
 /////////////////////////////////////////////////////////////////////////////
 
 // ============================================================================
 
 #include <string.h>
 #include <stdlib.h>
 
 #include <string.h>
 #include <stdlib.h>
+
+#ifndef __WXWINCE__
 #include <sys/types.h>
 #include <sys/types.h>
+#endif
 
 #if wxUSE_RICHEDIT
 
 
 #if wxUSE_RICHEDIT
 
     #include <richedit.h>
 #endif
 
     #include <richedit.h>
 #endif
 
-// old mingw32 doesn't define this
-#ifndef CFM_CHARSET
-    #define CFM_CHARSET 0x08000000
-#endif // CFM_CHARSET
-
-#ifndef CFM_BACKCOLOR
-    #define CFM_BACKCOLOR 0x04000000
-#endif
-
-// cygwin does not have these defined for richedit
-#ifndef ENM_LINK
-    #define ENM_LINK 0x04000000
-#endif
-
-#ifndef EM_AUTOURLDETECT
-    #define EM_AUTOURLDETECT (WM_USER + 91)
-#endif
-
-#ifndef EN_LINK
-    #define EN_LINK 0x070b
-
-    typedef struct _enlink
-    {
-        NMHDR nmhdr;
-        UINT msg;
-        WPARAM wParam;
-        LPARAM lParam;
-        CHARRANGE chrg;
-    } ENLINK;
-#endif // ENLINK
-
-#ifndef SF_UNICODE
-    #define SF_UNICODE 0x0010
-#endif
-
-// Watcom C++ doesn't define this
-#ifndef SCF_ALL
-    #define SCF_ALL 0x0004
-#endif
+#include "wx/msw/missing.h"
 
 #endif // wxUSE_RICHEDIT
 
 
 #endif // wxUSE_RICHEDIT
 
@@ -393,12 +358,6 @@ void wxTextCtrl::AdoptAttributesFromHWND()
 
 WXDWORD wxTextCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const
 {
 
 WXDWORD wxTextCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const
 {
-    // default border for the text controls is the sunken one
-    if ( (style & wxBORDER_MASK) == wxBORDER_DEFAULT )
-    {
-        style |= wxBORDER_SUNKEN;
-    }
-
     long msStyle = wxControl::MSWGetStyle(style, exstyle);
 
     // styles which we alaways add by default
     long msStyle = wxControl::MSWGetStyle(style, exstyle);
 
     // styles which we alaways add by default
@@ -413,6 +372,7 @@ WXDWORD wxTextCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const
             // always adjust the vertical scrollbar automatically if we have it
             msStyle |= WS_VSCROLL | ES_AUTOVSCROLL;
 
             // always adjust the vertical scrollbar automatically if we have it
             msStyle |= WS_VSCROLL | ES_AUTOVSCROLL;
 
+#if wxUSE_RICHEDIT
             // we have to use this style for the rich edit controls because
             // without it the vertical scrollbar never appears at all in
             // richedit 3.0 because of our ECO_NOHIDESEL hack (search for it)
             // we have to use this style for the rich edit controls because
             // without it the vertical scrollbar never appears at all in
             // richedit 3.0 because of our ECO_NOHIDESEL hack (search for it)
@@ -420,6 +380,7 @@ WXDWORD wxTextCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const
             {
                 msStyle |= ES_DISABLENOSCROLL;
             }
             {
                 msStyle |= ES_DISABLENOSCROLL;
             }
+#endif // wxUSE_RICHEDIT
         }
 
         style |= wxTE_PROCESS_ENTER;
         }
 
         style |= wxTE_PROCESS_ENTER;
@@ -460,9 +421,6 @@ WXDWORD wxTextCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const
 
 void wxTextCtrl::SetWindowStyleFlag(long style)
 {
 
 void wxTextCtrl::SetWindowStyleFlag(long style)
 {
-    if ( (style & wxBORDER_MASK) == wxBORDER_DEFAULT )
-        style |= wxBORDER_SUNKEN;
-
 #if wxUSE_RICHEDIT
     // we have to deal with some styles separately because they can't be
     // changed by simply calling SetWindowLong(GWL_STYLE) but can be changed
 #if wxUSE_RICHEDIT
     // we have to deal with some styles separately because they can't be
     // changed by simply calling SetWindowLong(GWL_STYLE) but can be changed
@@ -568,14 +526,16 @@ void wxTextCtrl::SetValue(const wxString& value)
     if ( (value.length() > 0x400) || (value != GetValue()) )
     {
         DoWriteText(value, FALSE /* not selection only */);
     if ( (value.length() > 0x400) || (value != GetValue()) )
     {
         DoWriteText(value, FALSE /* not selection only */);
+    }
 
 
-        // mark the control as being not dirty - we changed its text, not the
-        // user
-        DiscardEdits();
+    // we should reset the modified flag even if the value didn't really change
 
 
-        // for compatibility, don't move the cursor when doing SetValue()
-        SetInsertionPoint(0);
-    }
+    // mark the control as being not dirty - we changed its text, not the
+    // user
+    DiscardEdits();
+
+    // for compatibility, don't move the cursor when doing SetValue()
+    SetInsertionPoint(0);
 }
 
 #if wxUSE_RICHEDIT && (!wxUSE_UNICODE || wxUSE_UNICODE_MSLU)
 }
 
 #if wxUSE_RICHEDIT && (!wxUSE_UNICODE || wxUSE_UNICODE_MSLU)
@@ -599,7 +559,8 @@ DWORD CALLBACK wxRichEditStreamIn(DWORD dwCookie, BYTE *buf, LONG cb, LONG *pcb)
     return 0;
 }
 
     return 0;
 }
 
-extern long wxEncodingToCodepage(wxFontEncoding encoding); // from utils.cpp
+// from utils.cpp
+extern WXDLLIMPEXP_BASE long wxEncodingToCodepage(wxFontEncoding encoding);
 
 #if wxUSE_UNICODE_MSLU
 bool wxTextCtrl::StreamIn(const wxString& value,
 
 #if wxUSE_UNICODE_MSLU
 bool wxTextCtrl::StreamIn(const wxString& value,
@@ -791,7 +752,7 @@ void wxTextCtrl::AppendText(const wxString& text)
 
 void wxTextCtrl::Clear()
 {
 
 void wxTextCtrl::Clear()
 {
-    ::SetWindowText(GetHwnd(), wxT(""));
+    ::SetWindowText(GetHwnd(), wxEmptyString);
 
 #if wxUSE_RICHEDIT
     if ( !IsRich() )
 
 #if wxUSE_RICHEDIT
     if ( !IsRich() )
@@ -1106,7 +1067,7 @@ void wxTextCtrl::Replace(long from, long to, const wxString& value)
 
 void wxTextCtrl::Remove(long from, long to)
 {
 
 void wxTextCtrl::Remove(long from, long to)
 {
-    Replace(from, to, _T(""));
+    Replace(from, to, wxEmptyString);
 }
 
 bool wxTextCtrl::LoadFile(const wxString& file)
 }
 
 bool wxTextCtrl::LoadFile(const wxString& file)
@@ -1525,11 +1486,6 @@ WXHBRUSH wxTextCtrl::OnCtlColor(WXHDC pDC, WXHWND WXUNUSED(pWnd), WXUINT WXUNUSE
 #endif // wxUSE_CTL3D
 
     HDC hdc = (HDC)pDC;
 #endif // wxUSE_CTL3D
 
     HDC hdc = (HDC)pDC;
-    if (GetParent()->GetTransparentBackground())
-        SetBkMode(hdc, TRANSPARENT);
-    else
-        SetBkMode(hdc, OPAQUE);
-
     wxColour colBack = GetBackgroundColour();
 
     if (!IsEnabled() && (GetWindowStyle() & wxTE_MULTILINE) == 0)
     wxColour colBack = GetBackgroundColour();
 
     if (!IsEnabled() && (GetWindowStyle() & wxTE_MULTILINE) == 0)
@@ -1914,7 +1870,9 @@ bool wxTextCtrl::SetStyle(long start, long end, const wxTextAttr& style)
 
     // the richedit 1.0 doesn't handle setting background colour, so don't
     // even try to do anything if it's the only thing we want to change
 
     // the richedit 1.0 doesn't handle setting background colour, so don't
     // even try to do anything if it's the only thing we want to change
-    if ( m_verRichEdit == 1 && !style.HasFont() && !style.HasTextColour() )
+    if ( m_verRichEdit == 1 && !style.HasFont() && !style.HasTextColour() &&
+        !style.HasLeftIndent() && !style.HasRightIndent() && !style.HasAlignment() &&
+        !style.HasTabs() )
     {
         // nothing to do: return TRUE if there was really nothing to do and
         // FALSE if we failed to set bg colour
     {
         // nothing to do: return TRUE if there was really nothing to do and
         // FALSE if we failed to set bg colour
@@ -2028,6 +1986,81 @@ bool wxTextCtrl::SetStyle(long start, long end, const wxTextAttr& style)
         wxLogDebug(_T("SendMessage(EM_SETCHARFORMAT, SCF_SELECTION) failed"));
     }
 
         wxLogDebug(_T("SendMessage(EM_SETCHARFORMAT, SCF_SELECTION) failed"));
     }
 
+    // now do the paragraph formatting
+    PARAFORMAT2 pf;
+    wxZeroMemory(pf);
+    // we can't use PARAFORMAT2 with RichEdit 1.0, so pretend it is a simple
+    // PARAFORMAT in that case
+#if wxUSE_RICHEDIT2
+    if ( m_verRichEdit == 1 )
+    {
+        // this is the only thing the control is going to grok
+        pf.cbSize = sizeof(PARAFORMAT);
+    }
+    else
+#endif
+    {
+        // PARAFORMAT or PARAFORMAT2
+        pf.cbSize = sizeof(pf);
+    }
+
+    if (style.HasAlignment())
+    {
+        pf.dwMask |= PFM_ALIGNMENT;
+        if (style.GetAlignment() == wxTEXT_ALIGNMENT_RIGHT)
+            pf.wAlignment = PFA_RIGHT;
+        else if (style.GetAlignment() == wxTEXT_ALIGNMENT_CENTRE)
+            pf.wAlignment = PFA_CENTER;
+        else if (style.GetAlignment() == wxTEXT_ALIGNMENT_JUSTIFIED)
+            pf.wAlignment = PFA_JUSTIFY;
+        else
+            pf.wAlignment = PFA_LEFT;
+    }
+
+    if (style.HasLeftIndent())
+    {
+        pf.dwMask |= PFM_STARTINDENT;
+
+        // Convert from 1/10 mm to TWIPS
+        pf.dxStartIndent = (int) (((double) style.GetLeftIndent()) * mm2twips / 10.0) ;
+
+        // TODO: do we need to specify dxOffset?
+    }
+
+    if (style.HasRightIndent())
+    {
+        pf.dwMask |= PFM_RIGHTINDENT;
+
+        // Convert from 1/10 mm to TWIPS
+        pf.dxRightIndent = (int) (((double) style.GetRightIndent()) * mm2twips / 10.0) ;
+    }
+
+    if (style.HasTabs())
+    {
+        pf.dwMask |= PFM_TABSTOPS;
+
+        const wxArrayInt& tabs = style.GetTabs();
+
+        pf.cTabCount = wxMin(tabs.GetCount(), MAX_TAB_STOPS);
+        size_t i;
+        for (i = 0; i < (size_t) pf.cTabCount; i++)
+        {
+            // Convert from 1/10 mm to TWIPS
+            pf.rgxTabs[i] = (int) (((double) tabs[i]) * mm2twips / 10.0) ;
+        }
+    }
+
+    if (pf.dwMask != 0)
+    {
+        // do format the selection
+        bool ok = ::SendMessage(GetHwnd(), EM_SETPARAFORMAT,
+            0, (LPARAM) &pf) != 0;
+        if ( !ok )
+        {
+            wxLogDebug(_T("SendMessage(EM_SETPARAFORMAT, 0) failed"));
+        }
+    }
+
     if ( changeSel )
     {
         // restore the original selection
     if ( changeSel )
     {
         // restore the original selection
@@ -2050,6 +2083,137 @@ bool wxTextCtrl::SetDefaultStyle(const wxTextAttr& style)
     return TRUE;
 }
 
     return TRUE;
 }
 
+bool wxTextCtrl::GetStyle(long position, wxTextAttr& style)
+{
+    if ( !IsRich() )
+    {
+        // can't do it with normal text control
+        return FALSE;
+    }
+
+    // initialize CHARFORMAT struct
+#if wxUSE_RICHEDIT2
+    CHARFORMAT2 cf;
+#else
+    CHARFORMAT cf;
+#endif
+
+    wxZeroMemory(cf);
+
+    // we can't use CHARFORMAT2 with RichEdit 1.0, so pretend it is a simple
+    // CHARFORMAT in that case
+#if wxUSE_RICHEDIT2
+    if ( m_verRichEdit == 1 )
+    {
+        // this is the only thing the control is going to grok
+        cf.cbSize = sizeof(CHARFORMAT);
+    }
+    else
+#endif
+    {
+        // CHARFORMAT or CHARFORMAT2
+        cf.cbSize = sizeof(cf);
+    }
+    // we can only change the format of the selection, so select the range we
+    // want and restore the old selection later
+    long startOld, endOld;
+    GetSelection(&startOld, &endOld);
+
+    // but do we really have to change the selection?
+    bool changeSel = position != startOld || position != endOld;
+
+    if ( changeSel )
+    {
+        DoSetSelection(position, position, FALSE /* don't scroll caret into view */);
+    }
+
+    // get the selection formatting
+    (void) ::SendMessage(GetHwnd(), EM_GETCHARFORMAT,
+                            SCF_SELECTION, (LPARAM)&cf) ;
+
+    LOGFONT lf;
+    lf.lfHeight = cf.yHeight;
+    lf.lfWidth = 0;
+    lf.lfCharSet = ANSI_CHARSET; // FIXME: how to get correct charset?
+    lf.lfClipPrecision = 0;
+    lf.lfEscapement = 0;
+    wxStrcpy(lf.lfFaceName, cf.szFaceName);
+    if (cf.dwEffects & CFE_ITALIC)
+        lf.lfItalic = TRUE;
+    lf.lfOrientation = 0;
+    lf.lfPitchAndFamily = cf.bPitchAndFamily;
+    lf.lfQuality = 0;
+    if (cf.dwEffects & CFE_STRIKEOUT)
+        lf.lfStrikeOut = TRUE;
+    if (cf.dwEffects & CFE_UNDERLINE)
+        lf.lfUnderline = TRUE;
+    if (cf.dwEffects & CFE_BOLD)
+        lf.lfWeight = FW_BOLD;
+
+    wxFont font = wxCreateFontFromLogFont(& lf);
+    if (font.Ok())
+    {
+        style.SetFont(font);
+    }
+    style.SetTextColour(wxColour(cf.crTextColor));
+
+#if wxUSE_RICHEDIT2
+    if ( m_verRichEdit != 1 )
+    {
+        // cf.dwMask |= CFM_BACKCOLOR;
+        style.SetBackgroundColour(wxColour(cf.crBackColor));
+    }
+#endif // wxUSE_RICHEDIT2
+
+    // now get the paragraph formatting
+    PARAFORMAT2 pf;
+    wxZeroMemory(pf);
+    // we can't use PARAFORMAT2 with RichEdit 1.0, so pretend it is a simple
+    // PARAFORMAT in that case
+#if wxUSE_RICHEDIT2
+    if ( m_verRichEdit == 1 )
+    {
+        // this is the only thing the control is going to grok
+        pf.cbSize = sizeof(PARAFORMAT);
+    }
+    else
+#endif
+    {
+        // PARAFORMAT or PARAFORMAT2
+        pf.cbSize = sizeof(pf);
+    }
+
+    // do format the selection
+    (void) ::SendMessage(GetHwnd(), EM_GETPARAFORMAT, 0, (LPARAM) &pf) ;
+
+    style.SetLeftIndent( (int) ((double) pf.dxStartIndent * twips2mm * 10.0) );
+    style.SetRightIndent( (int) ((double) pf.dxRightIndent * twips2mm * 10.0) );
+
+    if (pf.wAlignment == PFA_CENTER)
+        style.SetAlignment(wxTEXT_ALIGNMENT_CENTRE);
+    else if (pf.wAlignment == PFA_RIGHT)
+        style.SetAlignment(wxTEXT_ALIGNMENT_RIGHT);
+    else if (pf.wAlignment == PFA_JUSTIFY)
+        style.SetAlignment(wxTEXT_ALIGNMENT_JUSTIFIED);
+    else
+        style.SetAlignment(wxTEXT_ALIGNMENT_LEFT);
+
+    wxArrayInt tabStops;
+    size_t i;
+    for (i = 0; i < (size_t) pf.cTabCount; i++)
+    {
+        tabStops[i] = (int) ((double) (pf.rgxTabs[i] & 0xFFFF) * twips2mm * 10.0) ;
+    }
+
+    if ( changeSel )
+    {
+        // restore the original selection
+        DoSetSelection(startOld, endOld, FALSE);
+    }
+
+    return TRUE;
+}
+
 #endif
 
 // ----------------------------------------------------------------------------
 #endif
 
 // ----------------------------------------------------------------------------