- Implement clipping for wxSVGFileDC (Steve Benbow).
 - Added wxDirCtrl::GetPath() (troelsk).
 - Added wxEVT_COMMAND_DIRCTRL_CHANGED event (troelsk).
+- Added wxControl::GetSizeFromTextSize() (Manuel Martin).
 
 wxGTK:
 
 
     // wxControl-specific processing after processing the update event
     virtual void DoUpdateWindowUI(wxUpdateUIEvent& event);
 
+    wxSize GetSizeFromTextSize(int xlen, int ylen = -1) const
+        { return DoGetSizeFromTextSize(xlen, ylen); }
+    wxSize GetSizeFromTextSize(const wxSize& tsize) const
+        { return DoGetSizeFromTextSize(tsize.x, tsize.y); }
 
 
     // static utilities for mnemonics char (&) handling
     virtual bool DoSetLabelMarkup(const wxString& markup);
 #endif // wxUSE_MARKUP
 
+    // override this to return the total control's size from a string size
+    virtual wxSize DoGetSizeFromTextSize(int xlen, int ylen = -1) const;
 
     // initialize the common fields of wxCommandEvent
     void InitCommandEvent(wxCommandEvent& event) const;
 
     int m_stringCellIndex;
 
     virtual wxSize DoGetBestSize() const;
+    virtual wxSize DoGetSizeFromTextSize(int xlen, int ylen = -1) const;
     virtual int DoInsertItems(const wxArrayStringsAdapter& items,
                               unsigned int pos,
                               void **clientData, wxClientDataType type);
 
     // custom list stores.
     virtual void GTKCreateComboBoxWidget();
 
+    virtual wxSize DoGetSizeFromTextSize(int xlen, int ylen = -1) const;
+
     virtual GtkEntry *GetEntry() const
         { return m_entry; }
 
 
 
 typedef struct _GtkLabel GtkLabel;
 typedef struct _GtkFrame GtkFrame;
+typedef struct _GtkEntry GtkEntry;
 
 //-----------------------------------------------------------------------------
 // wxControl
     // Fix sensitivity due to bug in GTK+ < 2.14
     void GTKFixSensitivity(bool onlyIfUnderMouse = true);
 
+    // Ask GTK+ for preferred size. Use it after setting the font.
+    wxSize GTKGetPreferredSize(GtkWidget* widget) const;
+
+    // Inner margins in a GtkEntry
+    wxPoint GTKGetEntryMargins(GtkEntry* entry) const;
+
 private:
     DECLARE_DYNAMIC_CLASS(wxControl)
 };
 
     virtual void DoApplyWidgetStyle(GtkRcStyle *style);
     virtual GdkWindow *GTKGetWindow(wxArrayGdkWindows& windows) const;
 
+    virtual wxSize DoGetSizeFromTextSize(int xlen, int ylen = -1) const;
+
     virtual void DoFreeze();
     virtual void DoThaw();
 
 
     */
     wxString GetLabelText() const;
 
+    /**
+        Determine the size needed by the control to leave the given area for
+        its text.
+
+        This function is mostly useful with control displaying short amounts of
+        text that can be edited by the user, e.g. wxTextCtrl, wxComboBox,
+        wxSearchCtrl etc. Typically it is used to size these controls for the
+        maximal amount of input they are supposed to contain, for example:
+        @code
+            // Create a control for post code entry.
+            wxTextCtrl* postcode = new wxTextCtrl(this, ...);
+
+            // And set its initial and minimal size to be big enough for
+            // entering 5 digits.
+            postcode->SetInitialSize(
+                postcode->GetSizeFromTextSize(
+                    postcode->GetTextExtent("99999")));
+        @endcode
+
+        Currently this method is only implemented for wxTextCtrl, wxComboBox
+        and wxChoice in wxGTK.
+
+        @param xlen The horizontal extent of the area to leave for text, in
+            pixels.
+        @param ylen The vertical extent of the area to leave for text, in
+            pixels. By default -1 meaning that the vertical component of the
+            returned size should be the default height of this control.
+        @return The size that the control should have to leave the area of the
+            specified size for its text. May return wxDefaultSize if this
+            method is not implemented for this particular control under the
+            current platform.
+
+        @since 2.9.5
+     */
+    wxSize GetSizeFromTextSize(int xlen, int ylen = -1) const;
+
+    /**
+        @overload
+    */
+    wxSize GetSizeFromTextSize(const wxSize& tsize) const;
+
     /**
         Sets the control's label.
 
 
     groupSizer = new wxStaticBoxSizer(new wxStaticBox(dlg,wxID_ANY,wxT(" wxOwnerDrawnComboBox ")),
                                       wxVERTICAL);
 
-    groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Writable, sorted:")), 0,
+    groupSizer->Add( new wxStaticText(dlg, wxID_ANY,
+                     wxT("Writable, with margins, sorted:")), 0,
                      wxALIGN_CENTER_VERTICAL|wxRIGHT|wxEXPAND, border );
 
     odc = new wxOwnerDrawnComboBox(dlg,wxID_ANY,wxEmptyString,
     odc->Append(wxT("H - Appended Item")); // test sorting in append
 
     odc->SetValue(wxT("Dot Dash"));
-
-    groupSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
+    odc->SetMargins(15, 10);
+    groupSizer->Add( odc, 0, wxALIGN_CENTER_VERTICAL|wxALL, border );
+    groupSizer->AddStretchSpacer();
 
     //
     // Readonly ODComboBox
-    groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Read-only:")), 0,
+    groupSizer->Add( new wxStaticText(dlg, wxID_ANY,
+                     wxT("Read-only, big font:")), 0,
                      wxALIGN_CENTER_VERTICAL|wxRIGHT, border );
 
     odc = new wxOwnerDrawnComboBox(dlg,wxID_ANY,wxEmptyString,
                                    wxCB_SORT|wxCB_READONLY // wxNO_BORDER|wxCB_READONLY
                                   );
 
+    odc->SetFont(odc->GetFont().Scale(1.5));
     odc->SetValue(wxT("Dot Dash"));
     odc->SetText(wxT("Dot Dash (Testing SetText)"));
 
-    groupSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
+    groupSizer->Add( odc, 0, wxALL, border );
+    groupSizer->AddStretchSpacer();
 
     //
     // Disabled ODComboBox
     odc->SetValue(wxT("Dot Dash"));
     odc->Enable(false);
 
-    groupSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
+    groupSizer->Add( odc, 3, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
 
     rowSizer->Add( groupSizer, 1, wxEXPAND|wxALL, border );
 
     //
     // wxComboBox
     //
-    groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Writable, sorted:")), 0,
+    groupSizer->Add( new wxStaticText(dlg,wxID_ANY,
+                     wxT("Writable, with margins, sorted:")), 0,
                      wxALIGN_CENTER_VERTICAL|wxRIGHT|wxEXPAND, border );
 
     cb = new wxComboBox(dlg,wxID_ANY,wxEmptyString,
     cb->Append(wxT("H - Appended Item")); // test sorting in append
 
     cb->SetValue(wxT("Dot Dash"));
-
-    groupSizer->Add( cb, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
+    cb->SetMargins(15, 10);
+    groupSizer->Add( cb, 0, wxALIGN_CENTER_VERTICAL|wxALL, border );
+    groupSizer->AddStretchSpacer();
 
     //
     // Readonly wxComboBox
-    groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Read-only:")), 0,
+    groupSizer->Add( new wxStaticText(dlg, wxID_ANY,
+                     wxT("Read-only, big font:")), 0,
                      wxALIGN_CENTER_VERTICAL|wxRIGHT, border );
 
     cb = new wxComboBox(dlg,wxID_ANY,wxEmptyString,
                         wxCB_SORT|wxCB_READONLY // wxNO_BORDER|wxCB_READONLY
                        );
 
+    cb->SetFont(cb->GetFont().Scale(1.5));
     cb->SetValue(wxT("Dot Dash"));
 
-    groupSizer->Add( cb, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
+    groupSizer->Add( cb, 0, wxALL, border );
+    groupSizer->AddStretchSpacer();
 
     //
     // Disabled wxComboBox
     cb->SetValue(wxT("Dot Dash"));
     cb->Enable(false);
 
-    groupSizer->Add( cb, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
+    groupSizer->Add( cb, 3, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
 
     rowSizer->Add( groupSizer, 1, wxEXPAND|wxALL, border );
 
-    colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, border );
+    colSizer->Add( rowSizer, 1, wxEXPAND|wxALL, border );
 
     dlg->SetSizer( colSizer );
     colSizer->SetSizeHints( dlg );
 
     // ------------------------------------------------------------------------
 #if wxUSE_CHOICE
     panel = new wxPanel(m_book);
-    m_choice = new MyChoice( panel, ID_CHOICE, wxPoint(10,10), wxSize(120,wxDefaultCoord), 5, choices );
+    m_choice = new MyChoice( panel, ID_CHOICE, wxPoint(10,10), wxDefaultSize, 5, choices );
     m_choiceSorted = new MyChoice( panel, ID_CHOICE_SORTED, wxPoint(10,70), wxSize(120,wxDefaultCoord),
                                    5, choices, wxCB_SORT );
 
     SetChoiceClientData(wxT("choice"), m_choiceSorted);
 
     m_choice->SetSelection(2);
-    (void)new wxButton( panel, ID_CHOICE_SEL_NUM, wxT("Select #&2"), wxPoint(180,30), wxSize(140,30) );
-    (void)new wxButton( panel, ID_CHOICE_SEL_STR, wxT("&Select 'This'"), wxPoint(340,30), wxSize(140,30) );
-    (void)new wxButton( panel, ID_CHOICE_CLEAR, wxT("&Clear"), wxPoint(180,80), wxSize(140,30) );
-    (void)new wxButton( panel, ID_CHOICE_APPEND, wxT("&Append 'Hi!'"), wxPoint(340,80), wxSize(140,30) );
-    (void)new wxButton( panel, ID_CHOICE_DELETE, wxT("D&elete selected item"), wxPoint(180,130), wxSize(140,30) );
-    (void)new wxButton( panel, ID_CHOICE_FONT, wxT("Set &Italic font"), wxPoint(340,130), wxSize(140,30) );
+    (void)new wxButton( panel, ID_CHOICE_SEL_NUM, wxT("Select #&2"), wxPoint(220,30), wxSize(140,30) );
+    (void)new wxButton( panel, ID_CHOICE_SEL_STR, wxT("&Select 'This'"), wxPoint(380,30), wxSize(140,30) );
+    (void)new wxButton( panel, ID_CHOICE_CLEAR, wxT("&Clear"), wxPoint(220,80), wxSize(140,30) );
+    (void)new wxButton( panel, ID_CHOICE_APPEND, wxT("&Append 'Hi!'"), wxPoint(380,80), wxSize(140,30) );
+    (void)new wxButton( panel, ID_CHOICE_DELETE, wxT("D&elete selected item"), wxPoint(220,130), wxSize(140,30) );
+    (void)new wxButton( panel, ID_CHOICE_FONT, wxT("Set &Italic font"), wxPoint(380,130), wxSize(140,30) );
     (void)new wxCheckBox( panel, ID_CHOICE_ENABLE, wxT("&Disable"), wxPoint(20,130), wxSize(140,30) );
 
     m_book->AddPage(panel, wxT("wxChoice"), false, Image_Choice);
     // combo page
     // ------------------------------------------------------------------------
     panel = new wxPanel(m_book);
-    (void)new wxStaticBox( panel, wxID_ANY, wxT("&Box around combobox"),
-                           wxPoint(5, 5), wxSize(150, 100));
     m_combo = new MyComboBox( panel, ID_COMBO, wxT("This"),
-                              wxPoint(20,25), wxSize(120, wxDefaultCoord),
+                              wxPoint(15,25), wxDefaultSize,
                               5, choices,
                               wxTE_PROCESS_ENTER);
-
-    (void)new wxButton( panel, ID_COMBO_SEL_NUM, wxT("Select #&2"), wxPoint(180,30), wxSize(140,30) );
-    (void)new wxButton( panel, ID_COMBO_SEL_STR, wxT("&Select 'This'"), wxPoint(340,30), wxSize(140,30) );
-    (void)new wxButton( panel, ID_COMBO_CLEAR, wxT("&Clear"), wxPoint(180,80), wxSize(140,30) );
-    (void)new wxButton( panel, ID_COMBO_APPEND, wxT("&Append 'Hi!'"), wxPoint(340,80), wxSize(140,30) );
-    (void)new wxButton( panel, ID_COMBO_DELETE, wxT("D&elete selected item"), wxPoint(180,130), wxSize(140,30) );
-    (void)new wxButton( panel, ID_COMBO_FONT, wxT("Set &Italic font"), wxPoint(340,130), wxSize(140,30) );
-    (void)new wxButton( panel, ID_COMBO_SET_TEXT, wxT("Set 'Hi!' at #2"), wxPoint(340,180), wxSize(140,30) );
+    wxSize combosize(m_combo->GetBestSize().x + 20, 100);
+    (void)new wxStaticBox( panel, wxID_ANY, wxT("&Box around combobox"),
+                           wxPoint(5, 5), combosize);
+
+    (void)new wxButton( panel, ID_COMBO_SEL_NUM, wxT("Select #&2"), wxPoint(220,30), wxSize(140,30) );
+    (void)new wxButton( panel, ID_COMBO_SEL_STR, wxT("&Select 'This'"), wxPoint(380,30), wxSize(140,30) );
+    (void)new wxButton( panel, ID_COMBO_CLEAR, wxT("&Clear"), wxPoint(220,80), wxSize(140,30) );
+    (void)new wxButton( panel, ID_COMBO_APPEND, wxT("&Append 'Hi!'"), wxPoint(380,80), wxSize(140,30) );
+    (void)new wxButton( panel, ID_COMBO_DELETE, wxT("D&elete selected item"), wxPoint(220,130), wxSize(140,30) );
+    (void)new wxButton( panel, ID_COMBO_FONT, wxT("Set &Italic font"), wxPoint(380,130), wxSize(140,30) );
+    (void)new wxButton( panel, ID_COMBO_SET_TEXT, wxT("Set 'Hi!' at #2"), wxPoint(380,180), wxSize(140,30) );
     (void)new wxCheckBox( panel, ID_COMBO_ENABLE, wxT("&Disable"), wxPoint(20,130), wxSize(140,30) );
     m_book->AddPage(panel, wxT("wxComboBox"), false, Image_Combo);
 
 
     m_password = new MyTextCtrl( this, wxID_ANY, wxT(""),
       wxPoint(10,50), wxSize(140,wxDefaultCoord), wxTE_PASSWORD );
 
-    m_readonly = new MyTextCtrl( this, wxID_ANY, wxT("Read only"),
-      wxPoint(10,90), wxSize(140,wxDefaultCoord), wxTE_READONLY );
-
     m_limited = new MyTextCtrl(this, wxID_ANY, "",
-                              wxPoint(10, 130), wxSize(140, wxDefaultCoord));
+                              wxPoint(10, 90), wxDefaultSize);
     m_limited->SetHint("Max 8 ch");
     m_limited->SetMaxLength(8);
+    wxSize size2 = m_limited->GetSizeFromTextSize(m_limited->GetTextExtent("WWWWWWWW"));
+    m_limited->SetSizeHints(size2, size2);
 
     // multi line text controls
 
+    wxString string3L("Read only\nMultiline\nFitted size");
+    m_readonly = new MyTextCtrl( this, wxID_ANY, string3L,
+               wxPoint(10, 120), wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY );
+    wxWindowDC dc(m_readonly);
+    size2 = m_readonly->GetSizeFromTextSize(dc.GetMultiLineTextExtent(string3L));
+    m_readonly->SetMinSize(size2);
+
     m_horizontal = new MyTextCtrl( this, wxID_ANY, wxT("Multiline text control with a horizontal scrollbar.\n"),
       wxPoint(10,170), wxSize(140,70), wxTE_MULTILINE | wxHSCROLL);
 
 #endif
 
     m_tab = new MyTextCtrl( this, 100, wxT("Multiline, allow <TAB> processing."),
-      wxPoint(180,90), wxSize(200,70), wxTE_MULTILINE |  wxTE_PROCESS_TAB );
+      wxPoint(180,90), wxDefaultSize, wxTE_MULTILINE |  wxTE_PROCESS_TAB );
     m_tab->SetClientData((void *)wxT("tab"));
 
     m_enter = new MyTextCtrl( this, 100, wxT("Multiline, allow <ENTER> processing."),
     wxBoxSizer *column1 = new wxBoxSizer(wxVERTICAL);
     column1->Add( m_text, 0, wxALL | wxEXPAND, 10 );
     column1->Add( m_password, 0, wxALL | wxEXPAND, 10 );
-    column1->Add( m_readonly, 0, wxALL | wxEXPAND, 10 );
-    column1->Add( m_limited, 0, wxALL | wxEXPAND, 10 );
+    column1->Add( m_readonly, 0, wxALL, 10 );
+    column1->Add( m_limited, 0, wxALL, 10 );
     column1->Add( m_horizontal, 1, wxALL | wxEXPAND, 10 );
 
     wxBoxSizer *column2 = new wxBoxSizer(wxVERTICAL);
     column2->Add( m_multitext, 1, wxALL | wxEXPAND, 10 );
-    column2->Add( m_tab, 1, wxALL | wxEXPAND, 10 );
+    column2->Add( m_tab, 0, wxALL | wxEXPAND, 10 );
     column2->Add( m_enter, 1, wxALL | wxEXPAND, 10 );
 
     wxBoxSizer *row1 = new wxBoxSizer(wxHORIZONTAL);
 
 #endif // wxUSE_RADIOBTN
 }
 
+wxSize wxControlBase::DoGetSizeFromTextSize(int WXUNUSED(xlen),
+                                            int WXUNUSED(ylen)) const
+{
+    return wxSize(-1, -1);
+}
+
 /* static */
 wxString wxControlBase::GetLabelText(const wxString& label)
 {
 
     // Get the height of the control from GTK+ itself, but use our own version
     // to compute the width large enough to show all our strings as GTK+
     // doesn't seem to take the control contents into account.
-    return wxSize(wxChoiceBase::DoGetBestSize().x + 40,
-                  wxControl::DoGetBestSize().y);
+    return GetSizeFromTextSize(wxChoiceBase::DoGetBestSize().x);
+}
+
+wxSize wxChoice::DoGetSizeFromTextSize(int xlen, int ylen) const
+{
+    wxASSERT_MSG( m_widget, wxS("GetSizeFromTextSize called before creation") );
+
+    // a GtkEntry for wxComboBox and a GtkCellView for wxChoice
+    GtkWidget* childPart = gtk_bin_get_child(GTK_BIN(m_widget));
+
+    // Set a as small as possible size for the control, so preferred sizes
+    // return "natural" sizes, not taking into account the previous ones (which
+    // seems to be GTK+3 behaviour)
+    gtk_widget_set_size_request(m_widget, 0, 0);
+
+    // We are interested in the difference of sizes between the whole contol
+    // and its child part. I.e. arrow, separators, etc.
+    GtkRequisition req;
+    gtk_widget_size_request(childPart, &req);
+    wxSize totalS = GTKGetPreferredSize(m_widget);
+
+    wxSize tsize(xlen + totalS.x - req.width, totalS.y);
+
+    // For a wxChoice, not for wxComboBox, add some margins
+    if ( !GTK_IS_ENTRY(childPart) )
+        tsize.IncBy(5, 0);
+
+    // Perhaps the user wants something different from CharHeight
+    if ( ylen > 0 )
+        tsize.IncBy(0, ylen - GetCharHeight());
+
+    return tsize;
 }
 
 void wxChoice::DoApplyWidgetStyle(GtkRcStyle *style)
 
 {
     gtk_combo_box_popdown( GTK_COMBO_BOX(m_widget) );
 }
+
+wxSize wxComboBox::DoGetSizeFromTextSize(int xlen, int ylen) const
+{
+    wxSize tsize( wxChoice::DoGetSizeFromTextSize(xlen, ylen) );
+
+    // Add the margins we have previously set, but only the horizontal border
+    // as vertical one has been taken account in the prevoius call.
+    // Also get other GTK+ margins.
+    tsize.IncBy( GTKGetEntryMargins(GetEntry()).x, 0);
+
+    return tsize;
+}
+
 #endif // wxUSE_COMBOBOX
 
     }
     else
     {
-        GtkRequisition req;
-#ifdef __WXGTK3__
-        if (gtk_widget_get_request_mode(m_widget) != GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH)
-        {
-            gtk_widget_get_preferred_height(m_widget, NULL, &req.height);
-            gtk_widget_get_preferred_width_for_height(m_widget, req.height, NULL, &req.width);
-        }
-        else
-        {
-            gtk_widget_get_preferred_width(m_widget, NULL, &req.width);
-            gtk_widget_get_preferred_height_for_width(m_widget, req.width, NULL, &req.height);
-        }
-#else
-        GTK_WIDGET_GET_CLASS(m_widget)->size_request(m_widget, &req);
-#endif
-        best.Set(req.width, req.height);
+        best = GTKGetPreferredSize(m_widget);
     }
-    CacheBestSize(best);
+
     return best;
 }
 
     return attr;
 }
 
+// This is not the same as GetBestSize() because that size may have
+// been recalculated and cached by us. We want GTK+ information.
+wxSize wxControl::GTKGetPreferredSize(GtkWidget* widget) const
+{
+    GtkRequisition req;
+#ifdef __WXGTK3__
+    if (gtk_widget_get_request_mode(widget) != GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH)
+    {
+        gtk_widget_get_preferred_height(widget, NULL, &req.height);
+        gtk_widget_get_preferred_width_for_height(widget, req.height, NULL, &req.width);
+    }
+    else
+    {
+        gtk_widget_get_preferred_width(widget, NULL, &req.width);
+        gtk_widget_get_preferred_height_for_width(widget, req.width, NULL, &req.height);
+    }
+#else
+    GTK_WIDGET_GET_CLASS(widget)->size_request(widget, &req);
+#endif
+
+    return wxSize(req.width, req.height);
+}
+
+wxPoint wxControl::GTKGetEntryMargins(GtkEntry* entry) const
+{
+    wxPoint marg(0, 0);
+
+#ifndef __WXGTK3__
+#if GTK_CHECK_VERSION(2,10,0)
+    // The margins we have previously set
+    const GtkBorder* border = gtk_entry_get_inner_border(entry);
+    if ( border )
+    {
+        marg.x = border->left + border->right;
+        marg.y = border->top + border->bottom;
+    }
+#endif // GTK+ 2.10+
+#else // GTK+ 3
+    // Gtk3 does not use inner border, but StyleContext and CSS
+    // TODO: implement it, starting with wxTextEntry::DoSetMargins()
+#endif // GTK+ 2/3
+
+    int x, y;
+    gtk_entry_get_layout_offsets(entry, &x, &y);
+    // inner borders are included. Substract them so we can get other margins
+    x -= marg.x;
+    y -= marg.y;
+    marg.x += 2 * x + 2;
+    marg.y += 2 * y + 2;
+
+    return marg;
+}
+
+
 #endif // wxUSE_CONTROLS
 
 
 wxSize wxTextCtrl::DoGetBestSize() const
 {
-    // FIXME should be different for multi-line controls...
-    wxSize ret( wxControl::DoGetBestSize() );
-    wxSize best(80, ret.y);
-    CacheBestSize(best);
-    return best;
+    return DoGetSizeFromTextSize(80);
 }
 
+wxSize wxTextCtrl::DoGetSizeFromTextSize(int xlen, int ylen) const
+{
+    wxASSERT_MSG( m_widget, wxS("GetSizeFromTextSize called before creation") );
+
+    wxSize tsize(xlen, 0);
+    int cHeight = GetCharHeight();
+
+    if ( IsSingleLine() )
+    {
+        // default height
+        tsize.y = GTKGetPreferredSize(m_widget).y;
+        // Add the margins we have previously set, but only the horizontal border
+        // as vertical one has been taken account at GTKGetPreferredSize().
+        // Also get other GTK+ margins.
+        tsize.IncBy( GTKGetEntryMargins(GetEntry()).x, 0);
+    }
+
+    //multiline
+    else
+    {
+        // add space for vertical scrollbar
+        if ( m_scrollBar[1] && !(m_windowStyle & wxTE_NO_VSCROLL) )
+            tsize.IncBy(GTKGetPreferredSize(GTK_WIDGET(m_scrollBar[1])).x + 3, 0);
+
+        // height
+        tsize.y = cHeight;
+        if ( ylen <= 0 )
+        {
+            tsize.y = cHeight * wxMax(wxMin(GetNumberOfLines(), 10), 2);
+            // add space for horizontal scrollbar
+            if ( m_scrollBar[0] && (m_windowStyle & wxHSCROLL) )
+                tsize.IncBy(0, GTKGetPreferredSize(GTK_WIDGET(m_scrollBar[0])).y + 3);
+        }
+
+        // hardcode borders, margins, etc
+        tsize.IncBy(5, 5);
+    }
+
+    // Perhaps the user wants something different from CharHeight
+    if ( ylen > 0 )
+        tsize.IncBy(0, ylen - cHeight);
+
+    return tsize;
+}
+
+
 // ----------------------------------------------------------------------------
 // freeze/thaw
 // ----------------------------------------------------------------------------