1 ///////////////////////////////////////////////////////////////////////////// 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  11 #pragma implementation "textctrl.h" 
  14 #include "wx/textctrl.h" 
  19 #include "wx/settings.h" 
  21 #include "wx/clipbrd.h" 
  22 #include "wx/tokenzr.h" 
  23 #include "wx/dcclient.h" 
  25 #include "wx/univ/inphand.h" 
  26 #include "wx/univ/renderer.h" 
  27 #include "wx/univ/colschem.h" 
  28 #include "wx/univ/theme.h" 
  30 //----------------------------------------------------------------------------- 
  32 //----------------------------------------------------------------------------- 
  34 wxSourceUndoStep::wxSourceUndoStep( wxSourceUndo type
, int y1
, int y2
, wxTextCtrl 
*owner 
) 
  41     m_cursorX 
= m_owner
->GetCursorX(); 
  42     m_cursorY 
= m_owner
->GetCursorY(); 
  44     if (m_type 
== wxSOURCE_UNDO_LINE
) 
  46         m_text 
= m_owner
->m_lines
[m_y1
].m_text
; 
  48     if (m_type 
== wxSOURCE_UNDO_ENTER
) 
  50         m_text 
= m_owner
->m_lines
[m_y1
].m_text
; 
  52     if (m_type 
== wxSOURCE_UNDO_BACK
) 
  54         for (int i 
= m_y1
; i 
< m_y2
+2; i
++) 
  56             if (i 
>= (int)m_owner
->m_lines
.GetCount()) 
  57                 m_lines
.Add( wxT("") ); 
  59                 m_lines
.Add( m_owner
->m_lines
[i
].m_text 
); 
  62     if (m_type 
== wxSOURCE_UNDO_DELETE
) 
  64         for (int i 
= m_y1
; i 
< m_y2
+1; i
++) 
  66             m_lines
.Add( m_owner
->m_lines
[i
].m_text 
); 
  69     if (m_type 
== wxSOURCE_UNDO_PASTE
) 
  71         m_text 
= m_owner
->m_lines
[m_y1
].m_text
; 
  75 void wxSourceUndoStep::Undo() 
  77     if (m_type 
== wxSOURCE_UNDO_LINE
) 
  79         m_owner
->m_lines
[m_y1
].m_text 
= m_text
; 
  80         m_owner
->MoveCursor( m_cursorX
, m_cursorY 
); 
  81         m_owner
->RefreshLine( m_y1 
); 
  83     if (m_type 
== wxSOURCE_UNDO_ENTER
) 
  85         m_owner
->m_lines
[m_y1
].m_text 
= m_text
; 
  86         m_owner
->m_lines
.RemoveAt( m_y1
+1 ); 
  87         m_owner
->MoveCursor( m_cursorX
, m_cursorY 
); 
  88         m_owner
->RefreshDown( m_y1 
); 
  90     if (m_type 
== wxSOURCE_UNDO_BACK
) 
  92         m_owner
->m_lines
[m_y1
].m_text 
= m_lines
[0]; 
  93         m_owner
->m_lines
.Insert( new wxSourceLine( m_lines
[1] ), m_y1
+1 ); 
  94         m_owner
->MyAdjustScrollbars(); 
  95         m_owner
->MoveCursor( m_cursorX
, m_cursorY 
); 
  96         m_owner
->RefreshDown( m_y1 
); 
  98     if (m_type 
== wxSOURCE_UNDO_DELETE
) 
 100         m_owner
->m_lines
[m_y1
].m_text 
= m_lines
[0]; 
 101         for (int i 
= 1; i 
< (int)m_lines
.GetCount(); i
++) 
 102             m_owner
->m_lines
.Insert( new wxSourceLine( m_lines
[i
] ), m_y1
+i 
); 
 103         m_owner
->MyAdjustScrollbars(); 
 104         m_owner
->MoveCursor( m_cursorX
, m_cursorY 
); 
 105         m_owner
->RefreshDown( m_y1 
); 
 107     if (m_type 
== wxSOURCE_UNDO_PASTE
) 
 109         m_owner
->m_lines
[m_y1
].m_text 
= m_text
; 
 110         for (int i 
= 0; i 
< m_y2
-m_y1
; i
++) 
 111             m_owner
->m_lines
.RemoveAt( m_y1
+1 ); 
 112         m_owner
->MyAdjustScrollbars(); 
 113         m_owner
->MoveCursor( m_cursorX
, m_cursorY 
); 
 114         m_owner
->RefreshDown( m_y1 
); 
 116     if (m_type 
== wxSOURCE_UNDO_INSERT_LINE
) 
 118         m_owner
->m_lines
.RemoveAt( m_y1 
); 
 119         m_owner
->MyAdjustScrollbars(); 
 120         m_owner
->MoveCursor( 0, m_y1 
); 
 121         m_owner
->RefreshDown( m_y1 
); 
 125 #include "wx/arrimpl.cpp" 
 126 WX_DEFINE_OBJARRAY(wxSourceLineArray
); 
 128 //----------------------------------------------------------------------------- 
 130 //----------------------------------------------------------------------------- 
 132 IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl
,wxControl
) 
 134 BEGIN_EVENT_TABLE(wxTextCtrl
, wxControl
) 
 135     EVT_PAINT(wxTextCtrl::OnPaint
) 
 136     EVT_ERASE_BACKGROUND(wxTextCtrl::OnEraseBackground
) 
 137     EVT_CHAR(wxTextCtrl::OnChar
) 
 138     EVT_MOUSE_EVENTS(wxTextCtrl::OnMouse
) 
 139     EVT_KILL_FOCUS(wxTextCtrl::OnKillFocus
) 
 140     EVT_SET_FOCUS(wxTextCtrl::OnSetFocus
) 
 142     EVT_MENU(wxID_CUT
, wxTextCtrl::OnCut
) 
 143     EVT_MENU(wxID_COPY
, wxTextCtrl::OnCopy
) 
 144     EVT_MENU(wxID_PASTE
, wxTextCtrl::OnPaste
) 
 145     EVT_MENU(wxID_UNDO
, wxTextCtrl::OnUndo
) 
 146     EVT_MENU(wxID_REDO
, wxTextCtrl::OnRedo
) 
 148     EVT_UPDATE_UI(wxID_CUT
, wxTextCtrl::OnUpdateCut
) 
 149     EVT_UPDATE_UI(wxID_COPY
, wxTextCtrl::OnUpdateCopy
) 
 150     EVT_UPDATE_UI(wxID_PASTE
, wxTextCtrl::OnUpdatePaste
) 
 151     EVT_UPDATE_UI(wxID_UNDO
, wxTextCtrl::OnUpdateUndo
) 
 152     EVT_UPDATE_UI(wxID_REDO
, wxTextCtrl::OnUpdateRedo
) 
 155 void wxTextCtrl::Init() 
 160     m_lang 
= wxSOURCE_LANG_NONE
; 
 173     m_ignoreInput 
= FALSE
; 
 177     m_keywordColour 
= wxColour( 10, 140, 10 ); 
 179     m_defineColour 
= *wxRED
; 
 181     m_variableColour 
= wxColour( 50, 120, 150 ); 
 183     m_commentColour 
= wxColour( 130, 130, 130 ); 
 185     m_stringColour 
= wxColour( 10, 140, 10 ); 
 188 wxTextCtrl::wxTextCtrl( wxWindow 
*parent
, 
 190                         const wxString 
&value
, 
 194                         const wxValidator
& validator
, 
 195                         const wxString 
&name 
) 
 196     : wxScrollHelper(this) 
 200     Create( parent
, id
, value
, pos
, size
, style
, validator
, name 
); 
 203 wxTextCtrl::~wxTextCtrl() 
 205     WX_CLEAR_LIST(wxList
, m_undos
); 
 208 bool wxTextCtrl::Create( wxWindow 
*parent
, 
 210                          const wxString 
&value
, 
 214                          const wxValidator
& validator
, 
 215                          const wxString 
&name 
) 
 217     if ((style 
& wxBORDER_MASK
) == 0) 
 218         style 
|= wxBORDER_SUNKEN
; 
 220     if ((style 
& wxTE_MULTILINE
) != 0) 
 221         style 
|= wxALWAYS_SHOW_SB
; 
 223     wxTextCtrlBase::Create( parent
, id
, pos 
/* wxDefaultPosition */, size
, 
 224                             style 
| wxVSCROLL 
| wxHSCROLL
); 
 226     SetBackgroundColour( *wxWHITE 
); 
 228     SetCursor( wxCursor( wxCURSOR_IBEAM 
) ); 
 230     m_editable 
= ((m_windowStyle 
& wxTE_READONLY
) == 0); 
 232     if (HasFlag(wxTE_PASSWORD
)) 
 233         m_sourceFont 
= wxFont( 12, wxMODERN
, wxNORMAL
, wxNORMAL 
); 
 235         m_sourceFont 
= GetFont(); 
 238     dc
.SetFont( m_sourceFont 
); 
 239     m_lineHeight 
= dc
.GetCharHeight(); 
 240     m_charWidth 
= dc
.GetCharWidth(); 
 244     wxSize 
size_best( DoGetBestSize() ); 
 245     wxSize 
new_size( size 
); 
 246     if (new_size
.x 
== -1) 
 247         new_size
.x 
= size_best
.x
; 
 248     if (new_size
.y 
== -1) 
 249         new_size
.y 
= size_best
.y
; 
 250     if ((new_size
.x 
!= size
.x
) || (new_size
.y 
!= size
.y
)) 
 251         SetSize( new_size
.x
, new_size
.y 
); 
 253     // We create an input handler since it might be useful 
 254     CreateInputHandler(wxINP_HANDLER_TEXTCTRL
); 
 256     MyAdjustScrollbars(); 
 261 //----------------------------------------------------------------------------- 
 263 //----------------------------------------------------------------------------- 
 265 wxString 
wxTextCtrl::GetValue() const 
 268     for (size_t i 
= 0; i 
< m_lines
.GetCount(); i
++) 
 270         ret 
+= m_lines
[i
].m_text
; 
 271         if (i
+1 < m_lines
.GetCount()) 
 278 void wxTextCtrl::SetValue(const wxString
& value
) 
 282     wxString oldValue 
= GetValue(); 
 292         m_lines
.Add( new wxSourceLine( wxT("") ) ); 
 300             pos 
= value
.find( wxT('\n'), begin 
); 
 303                 wxSourceLine 
*sl 
= new wxSourceLine( value
.Mid( begin
, value
.Len()-begin 
) ); 
 306                 // if (sl->m_text.Len() > m_longestLine) 
 307                 //    m_longestLine = sl->m_text.Len(); 
 309                 GetTextExtent( sl
->m_text
, &ww
, NULL
, NULL
, NULL 
); 
 311                 if (ww 
> m_longestLine
) 
 318                 wxSourceLine 
*sl 
= new wxSourceLine( value
.Mid( begin
, pos
-begin 
) ); 
 321                 // if (sl->m_text.Len() > m_longestLine) 
 322                 //      m_longestLine = sl->m_text.Len(); 
 324                 GetTextExtent( sl
->m_text
, &ww
, NULL
, NULL
, NULL 
); 
 326                 if (ww 
> m_longestLine
) 
 334     // Don't need to refresh if the value hasn't changed 
 335     if ((GetWindowStyle() & wxTE_MULTILINE
) == 0) 
 337         if (value 
== oldValue
) 
 341     MyAdjustScrollbars(); 
 346 int wxTextCtrl::GetLineLength(long lineNo
) const 
 348     if (lineNo 
>= (long)m_lines
.GetCount()) 
 351     return m_lines
[lineNo
].m_text
.Len(); 
 354 wxString 
wxTextCtrl::GetLineText(long lineNo
) const 
 356     if (lineNo 
>= (long)m_lines
.GetCount()) 
 359     return m_lines
[lineNo
].m_text
; 
 362 int wxTextCtrl::GetNumberOfLines() const 
 364     return  m_lines
.GetCount(); 
 367 bool wxTextCtrl::IsModified() const 
 372 bool wxTextCtrl::IsEditable() const 
 377 void wxTextCtrl::GetSelection(long* from
, long* to
) const 
 379     if (m_selStartX 
== -1 || m_selStartY 
== -1 || 
 380         m_selEndX 
== -1 || m_selEndY 
== -1) 
 382         *from 
= GetInsertionPoint(); 
 383         *to 
= GetInsertionPoint(); 
 387         *from 
= XYToPosition(m_selStartX
, m_selStartY
); 
 388         *to 
= XYToPosition(m_selEndX
, m_selEndY
); 
 392 void wxTextCtrl::Clear() 
 400     m_lines
.Add( new wxSourceLine( wxT("") ) ); 
 402     SetScrollbars( m_charWidth
, m_lineHeight
, 0, 0, 0, 0 ); 
 404     WX_CLEAR_LIST(wxList
, m_undos
); 
 407 void wxTextCtrl::Replace(long from
, long to
, const wxString
& value
) 
 411 void wxTextCtrl::Remove(long from
, long to
) 
 416 void wxTextCtrl::DiscardEdits() 
 422 void wxTextCtrl::SetMaxLength(unsigned long len
) 
 426 int wxTextCtrl::PosToPixel( int line
, int pos 
) 
 428     // TODO add support for Tabs 
 430     if (line 
>= (int)m_lines
.GetCount()) return 0; 
 431     if (pos 
< 0) return 0; 
 433     wxString text 
= m_lines
[line
].m_text
; 
 435     if (text
.IsEmpty()) return 0; 
 437     if (pos 
< (int)text
.Len()) 
 438         text
.Remove( pos
, text
.Len()-pos 
); 
 442     GetTextExtent( text
, &w
, NULL
, NULL
, NULL 
); 
 447 int wxTextCtrl::PixelToPos( int line
, int pixel 
) 
 449     if (pixel 
< 2) return 0; 
 451     if (line 
>= (int)m_lines
.GetCount()) return 0; 
 453     wxString text 
= m_lines
[line
].m_text
; 
 456     int res 
= text
.Len(); 
 459         GetTextExtent( text
, &w
, NULL
, NULL
, NULL 
); 
 465         text
.Remove( res
,1 ); 
 471 void wxTextCtrl::SetLanguage( wxSourceLanguage lang 
) 
 478 void wxTextCtrl::WriteText(const wxString
& text2
) 
 480     if (text2
.IsEmpty()) return; 
 484     wxString 
text( text2 
); 
 487     while ( (pos 
= text
.Find('\n')) != -1 ) 
 489        lines
.Add( text
.Left( pos 
) ); 
 490        text
.Remove( 0, pos
+1 ); 
 493     int count 
= (int)lines
.GetCount(); 
 495     wxString 
tmp1( m_lines
[m_cursorY
].m_text 
); 
 496     wxString 
tmp2( tmp1 
); 
 497     int len 
= (int)tmp1
.Len(); 
 502         for (int i 
= 0; i 
< m_cursorX
-len
; i
++) 
 504         m_lines
[m_cursorY
].m_text
.Append( tmp 
); 
 509     tmp1
.Remove( m_cursorX 
); 
 510     tmp2
.Remove( 0, m_cursorX 
); 
 511     tmp1
.Append( lines
[0] ); 
 515         m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE
, m_cursorY
, m_cursorY
, this ) ); 
 518         m_lines
[m_cursorY
].m_text 
= tmp1
; 
 519         RefreshLine( m_cursorY 
); 
 523         m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_PASTE
, m_cursorY
, m_cursorY
+count
-1, this ) ); 
 525         m_lines
[m_cursorY
].m_text 
= tmp1
; 
 527         for (i 
= 1; i 
< count
; i
++) 
 528             m_lines
.Insert( new wxSourceLine( lines
[i
] ), m_cursorY
+i 
); 
 529         m_lines
[m_cursorY
+i
-1].m_text
.Append( tmp2 
); 
 531         MyAdjustScrollbars(); 
 532         RefreshDown( m_cursorY 
); 
 536 void wxTextCtrl::AppendText(const wxString
& text2
) 
 538     if (text2
.IsEmpty()) return; 
 542     wxString 
text( text2 
); 
 545     while ( (pos 
= text
.Find('\n')) != -1 ) 
 547        lines
.Add( text
.Left( pos 
) ); 
 548        text
.Remove( 0, pos
+1 ); 
 551     int count 
= (int)lines
.GetCount(); 
 553     size_t y 
= m_lines
.GetCount()-1; 
 555     wxString 
tmp( m_lines
[y
].m_text 
); 
 556     tmp
.Append( lines
[0] ); 
 560         m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE
, y
, y
, this ) ); 
 562         m_lines
[y
].m_text 
= tmp
; 
 567         m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_PASTE
, y
, y
+count
-1, this ) ); 
 569         m_lines
[y
].m_text 
= tmp
; 
 571         for (i 
= 1; i 
< count
; i
++) 
 572             m_lines
.Insert( new wxSourceLine( lines
[i
] ), y
+i 
); 
 574         MyAdjustScrollbars(); 
 579 bool wxTextCtrl::SetStyle(long start
, long end
, const wxTextAttr
& style
) 
 584 long wxTextCtrl::XYToPosition(long x
, long y
) const 
 588     for (size_t i 
= 0; i 
< m_lines
.GetCount(); i
++) 
 592             // Add one for the end-of-line character 
 593             ret 
+= m_lines
[i
].m_text
.Len() + 1; 
 597         if ((size_t)x 
< (m_lines
[i
].m_text
.Len()+1)) 
 600             return (ret 
+ m_lines
[i
].m_text
.Len() + 1); 
 606 bool wxTextCtrl::PositionToXY(long pos
, long *x
, long *y
) const 
 608     if (m_lines
.GetCount() == 0) 
 619     for (size_t i 
= 0; i 
< m_lines
.GetCount(); i
++) 
 621         //pos -= m_lines[i].m_text.Len(); 
 624         // Add one for the end-of-line character. (In Windows, 
 625         // there are _two_ positions for each end of line.) 
 626         if (pos 
<= ((int)m_lines
[i
].m_text
.Len())) 
 633         pos 
-= (m_lines
[i
].m_text
.Len() + 1); 
 638     //xx = m_lines[ m_lines.GetCount()-1 ].m_text.Len(); 
 646 void wxTextCtrl::ShowPosition(long pos
) 
 650 void wxTextCtrl::Copy() 
 652     if (!HasSelection()) return; 
 656     int selStartY 
= m_selStartY
; 
 657     int selEndY 
= m_selEndY
; 
 658     int selStartX 
= m_selStartX
; 
 659     int selEndX 
= m_selEndX
; 
 661     if ((selStartY 
> selEndY
) || 
 662         ((selStartY 
== selEndY
) && (selStartX 
> selEndX
))) 
 672     if (selStartY 
== selEndY
) 
 674         sel 
= m_lines
[selStartY
].m_text
; 
 676         if (selStartX 
>= (int)sel
.Len()) return; 
 677         if (selEndX 
> (int)sel
.Len()) 
 680         sel
.Remove( selEndX
, sel
.Len()-selEndX 
); 
 681         sel
.Remove( 0, selStartX 
); 
 685         wxString 
tmp( m_lines
[selStartY
].m_text 
); 
 687         if (selStartX 
< (int)tmp
.Len()) 
 689             tmp
.Remove( 0, selStartX 
); 
 691             sel
.Append( wxT("\n") ); 
 693         for (int i 
= selStartY
+1; i 
< selEndY
; i
++) 
 695             sel
.Append( m_lines
[i
].m_text 
); 
 696             sel
.Append( wxT("\n") ); 
 698         tmp 
= m_lines
[selEndY
].m_text
; 
 699         if (selEndX 
> (int)tmp
.Len()) 
 703             tmp
.Remove( selEndX
, tmp
.Len()-selEndX 
); 
 708     if (wxTheClipboard
->Open()) 
 710         wxTheClipboard
->SetData( new wxTextDataObject( sel 
) ); 
 711         wxTheClipboard
->Close(); 
 715 void wxTextCtrl::Cut() 
 722 void wxTextCtrl::Paste() 
 726     if (!wxTheClipboard
->Open()) return; 
 728     if (!wxTheClipboard
->IsSupported( wxDF_TEXT 
)) 
 730         wxTheClipboard
->Close(); 
 735     wxTextDataObject data
; 
 737     bool ret 
= wxTheClipboard
->GetData( data 
); 
 739     wxTheClipboard
->Close(); 
 745     wxString 
text( data
.GetText() ); 
 748     while ( (pos 
= text
.Find('\n')) != -1 ) 
 750        lines
.Add( text
.Left( pos 
) ); 
 751        text
.Remove( 0, pos
+1 ); 
 754     int count 
= (int)lines
.GetCount(); 
 756     wxString 
tmp1( m_lines
[m_cursorY
].m_text 
); 
 757     wxString 
tmp2( tmp1 
); 
 758     int len 
= (int)tmp1
.Len(); 
 763         for (int i 
= 0; i 
< m_cursorX
-len
; i
++) 
 765         m_lines
[m_cursorY
].m_text
.Append( tmp 
); 
 770     tmp1
.Remove( m_cursorX 
); 
 771     tmp2
.Remove( 0, m_cursorX 
); 
 772     tmp1
.Append( lines
[0] ); 
 776         m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE
, m_cursorY
, m_cursorY
, this ) ); 
 779         m_lines
[m_cursorY
].m_text 
= tmp1
; 
 780         RefreshLine( m_cursorY 
); 
 784         m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_PASTE
, m_cursorY
, m_cursorY
+count
-1, this ) ); 
 786         m_lines
[m_cursorY
].m_text 
= tmp1
; 
 788         for (i 
= 1; i 
< count
; i
++) 
 789             m_lines
.Insert( new wxSourceLine( lines
[i
] ), m_cursorY
+i 
); 
 790         m_lines
[m_cursorY
+i
-1].m_text
.Append( tmp2 
); 
 792         MyAdjustScrollbars(); 
 793         RefreshDown( m_cursorY 
); 
 797 void wxTextCtrl::Undo() 
 799     if (m_undos
.GetCount() == 0) return; 
 801     wxList::compatibility_iterator node 
= m_undos
.Item( m_undos
.GetCount()-1 ); 
 802     wxSourceUndoStep 
*undo 
= (wxSourceUndoStep
*) node
->GetData(); 
 807     m_undos
.Erase( node 
); 
 812 void wxTextCtrl::SetInsertionPoint(long pos
) 
 816     PositionToXY(pos
, & x
, & y
); 
 819     // TODO: scroll to this position if necessary 
 823 void wxTextCtrl::SetInsertionPointEnd() 
 825     SetInsertionPoint(GetLastPosition()); 
 828 long wxTextCtrl::GetInsertionPoint() const 
 830     return XYToPosition( m_cursorX
, m_cursorY 
); 
 833 long wxTextCtrl::GetLastPosition() const 
 835     size_t lineCount 
= m_lines
.GetCount() - 1; 
 836     // It's the length of the line, not the length - 1, 
 837     // because there's a position after the last character. 
 838     return XYToPosition( m_lines
[lineCount
].m_text
.Len(), lineCount 
); 
 841 void wxTextCtrl::SetSelection(long from
, long to
) 
 845 void wxTextCtrl::SetEditable(bool editable
) 
 847     m_editable 
= editable
; 
 850 bool wxTextCtrl::Enable( bool enable 
) 
 855 bool wxTextCtrl::SetFont(const wxFont
& font
) 
 857     wxTextCtrlBase::SetFont( font 
); 
 862     dc
.SetFont( m_sourceFont 
); 
 863     m_lineHeight 
= dc
.GetCharHeight(); 
 864     m_charWidth 
= dc
.GetCharWidth(); 
 866     // TODO: recalc longest lines 
 868     MyAdjustScrollbars(); 
 873 bool wxTextCtrl::SetForegroundColour(const wxColour
& colour
) 
 875     return wxWindow::SetForegroundColour( colour 
); 
 878 bool wxTextCtrl::SetBackgroundColour(const wxColour
& colour
) 
 880     return wxWindow::SetBackgroundColour( colour 
); 
 883 //----------------------------------------------------------------------------- 
 884 //  private code and handlers 
 885 //----------------------------------------------------------------------------- 
 887 void wxTextCtrl::SearchForBrackets() 
 889     int oldBracketY 
= m_bracketY
; 
 890     int oldBracketX 
= m_bracketX
; 
 892     if (m_cursorY 
< 0 || m_cursorY 
>= (int)m_lines
.GetCount()) return; 
 894     wxString current 
= m_lines
[m_cursorY
].m_text
; 
 896     // reverse search first 
 901         bracket 
= current
[(size_t) (m_cursorX
-1)]; 
 903     if (bracket 
== ')' || bracket 
== ']' || bracket 
== '}') 
 905         char antibracket 
= '('; 
 906         if (bracket 
== ']') antibracket 
= '['; 
 907         if (bracket 
== '}') antibracket 
= '{'; 
 911         int endY 
= m_cursorY
-60; 
 912         if (endY 
< 0) endY 
= 0; 
 913         for (int y 
= m_cursorY
; y 
>= endY
; y
--) 
 915             current 
= m_lines
[y
].m_text
; 
 917                 current
.erase(m_cursorX
-1,current
.Len()-m_cursorX
+1); 
 919             for (int n 
= current
.Len()-1; n 
>= 0; n
--) 
 922                 if (current
[(size_t) (n
)] == '\'') 
 924                     for (int m 
= n
-1; m 
>= 0; m
--) 
 926                         if (current
[(size_t) (m
)] == '\'') 
 928                             if (m 
== 0 || current
[(size_t) (m
-1)] != '\\') 
 937                 if (current
[(size_t) (n
)] == '\"') 
 939                     for (int m 
= n
-1; m 
>= 0; m
--) 
 941                         if (current
[(size_t) (m
)] == '\"') 
 943                             if (m 
== 0 || current
[(size_t) (m
-1)] != '\\') 
 951                 if (current
[(size_t) (n
)] == antibracket
) 
 958                         if (oldBracketY 
!= m_bracketY 
&& oldBracketY 
!= -1) 
 959                             RefreshLine( oldBracketY 
); 
 960                         if (m_bracketY 
!= oldBracketY 
|| m_bracketX 
!= oldBracketX
) 
 961                             RefreshLine( m_bracketY 
); 
 965                 else if (current
[(size_t) (n
)] == bracket
) 
 976     if ((int)current
.Len() > m_cursorX
) 
 977         bracket 
= current
[(size_t) (m_cursorX
)]; 
 978     if (bracket 
== '(' || bracket 
== '[' || bracket 
== '{') 
 980         char antibracket 
= ')'; 
 981         if (bracket 
== '[') antibracket 
= ']'; 
 982         if (bracket 
== '{') antibracket 
= '}'; 
 986         int endY 
= m_cursorY
+60; 
 987         if (endY 
> (int)(m_lines
.GetCount()-1)) endY 
= m_lines
.GetCount()-1; 
 988         for (int y 
= m_cursorY
; y 
<= endY
; y
++) 
 990             current 
= m_lines
[y
].m_text
; 
 995             for (int n 
= start
; n 
< (int)current
.Len(); n
++) 
 998                 if (current
[(size_t) (n
)] == '\'') 
1000                     for (int m 
= n
+1; m 
< (int)current
.Len(); m
++) 
1002                         if (current
[(size_t) (m
)] == '\'') 
1004                             if (m 
== 0 || (current
[(size_t) (m
-1)] != '\\') || (m 
>= 2 && current
[(size_t) (m
-2)] == '\\')) 
1013                 if (current
[(size_t) (n
)] == '\"') 
1015                     for (int m 
= n
+1; m 
< (int)current
.Len(); m
++) 
1017                         if (current
[(size_t) (m
)] == '\"') 
1019                             if (m 
== 0 || (current
[(size_t) (m
-1)] != '\\') || (m 
>= 2 && current
[(size_t) (m
-2)] == '\\')) 
1027                 if (current
[(size_t) (n
)] == antibracket
) 
1034                         if (oldBracketY 
!= m_bracketY 
&& oldBracketY 
!= -1) 
1035                             RefreshLine( oldBracketY 
); 
1036                         if (m_bracketY 
!= oldBracketY 
|| m_bracketX 
!= oldBracketX
) 
1037                             RefreshLine( m_bracketY 
); 
1041                 else if (current
[(size_t) (n
)] == bracket
) 
1049     if (oldBracketY 
!= -1) 
1052         RefreshLine( oldBracketY 
); 
1056 void wxTextCtrl::Delete() 
1058     if (!HasSelection()) return; 
1062     int selStartY 
= m_selStartY
; 
1063     int selEndY 
= m_selEndY
; 
1064     int selStartX 
= m_selStartX
; 
1065     int selEndX 
= m_selEndX
; 
1067     if ((selStartY 
> selEndY
) || 
1068         ((selStartY 
== selEndY
) && (selStartX 
> selEndX
))) 
1070         int tmp 
= selStartX
; 
1071         selStartX 
= selEndX
; 
1074         selStartY 
= selEndY
; 
1078     int len 
= (int)m_lines
[selStartY
].m_text
.Len(); 
1080     if (selStartY 
== selEndY
) 
1082         m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE
, selStartY
, selStartY
, this ) ); 
1084         wxString 
tmp( m_lines
[selStartY
].m_text 
); 
1085         if (selStartX 
< len
) 
1089             tmp
.Remove( selStartX
, selEndX
-selStartX 
); 
1090             m_lines
[selStartY
].m_text 
= tmp
; 
1093         m_cursorX 
= selStartX
; 
1094         RefreshLine( selStartY 
); 
1098         m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_DELETE
, selStartY
, selEndY
, this ) ); 
1100         if (selStartX 
< len
) 
1101             m_lines
[selStartY
].m_text
.Remove( selStartX 
); 
1103         for (int i 
= 0; i 
< selEndY
-selStartY
-1; i
++) 
1104             m_lines
.RemoveAt( selStartY
+1 ); 
1106         if (selEndX 
< (int)m_lines
[selStartY
+1].m_text
.Len()) 
1107             m_lines
[selStartY
+1].m_text
.Remove( 0, selEndX 
); 
1109             m_lines
[selStartY
+1].m_text
.Remove( 0 ); 
1111         m_lines
[selStartY
].m_text
.Append( m_lines
[selStartY
+1].m_text 
); 
1112         m_lines
.RemoveAt( selStartY
+1 ); 
1115         MoveCursor( selStartX
, selStartY 
); 
1116         MyAdjustScrollbars(); 
1118         RefreshDown( selStartY 
); 
1122 void wxTextCtrl::DeleteLine() 
1124     if (HasSelection()) return; 
1126     if (m_cursorY 
< 0 || m_cursorY 
>= (int)m_lines
.GetCount()-1) return;  // TODO 
1128     m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_DELETE
, m_cursorY
, m_cursorY
+1, this ) ); 
1130     m_lines
.RemoveAt( m_cursorY 
); 
1132     if (m_cursorY 
>= (int)m_lines
.GetCount()) m_cursorY
--; 
1134     MyAdjustScrollbars(); 
1135     RefreshDown( m_cursorY 
); 
1138 void wxTextCtrl::DoChar( char c 
) 
1142     m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE
, m_cursorY
, m_cursorY
, this ) ); 
1144     wxString 
tmp( m_lines
[m_cursorY
].m_text 
); 
1146     if (m_cursorX 
>= (int)tmp
.Len()) 
1148         int len 
= tmp
.Len(); 
1149         for (int i 
= 0; i 
< m_cursorX 
- len
; i
++) 
1156             tmp
.SetChar( m_cursorX
, c 
); 
1158             tmp
.insert( m_cursorX
, 1, c 
); 
1161     m_lines
[m_cursorY
].m_text 
= tmp
; 
1163 //    if (tmp.Len() > m_longestLine) 
1165 //        m_longestLine = tmp.Len(); 
1166 //        MyAdjustScrollbars(); 
1170     GetTextExtent( tmp
, &ww
, NULL
, NULL
, NULL 
); 
1172     if (ww 
> m_longestLine
) 
1175         MyAdjustScrollbars(); 
1180     int y 
= m_cursorY
*m_lineHeight
; 
1181     // int x = (m_cursorX-1)*m_charWidth; 
1182     int x 
= PosToPixel( m_cursorY
, m_cursorX
-1 ); 
1183     CalcScrolledPosition( x
, y
, &x
, &y 
); 
1184     wxRect 
rect( x
+2, y
+2, 10000, m_lineHeight 
); 
1185     Refresh( TRUE
, &rect 
); 
1186     // refresh whole line for syntax colour highlighting 
1188     Refresh( FALSE
, &rect 
); 
1192     GetClientSize( &size_x
, &size_y 
); 
1193     size_x 
/= m_charWidth
; 
1197     GetViewStart( &view_x
, &view_y 
); 
1199     //int xx = m_cursorX; 
1200     int xx 
= PosToPixel( m_cursorY
, m_cursorX 
) / m_charWidth
; 
1204     else if (xx 
> view_x
+size_x
-1) 
1205         Scroll( xx
-size_x
+1, -1 ); 
1208 void wxTextCtrl::DoBack() 
1214         if (m_cursorY 
== 0) return; 
1216         m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_BACK
, m_cursorY
-1, m_cursorY
, this ) ); 
1218         wxString 
tmp1( m_lines
[m_cursorY
-1].m_text 
); 
1220         wxString 
tmp2( m_lines
[m_cursorY
].m_text 
); 
1222         m_cursorX 
= tmp1
.Len(); 
1224         tmp1
.Append( tmp2 
); 
1225         m_lines
[m_cursorY
].m_text 
= tmp1
; 
1226         m_lines
.RemoveAt( m_cursorY
+1 ); 
1228         MyAdjustScrollbars(); 
1229         RefreshDown( m_cursorY
-1 ); 
1233         m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE
, m_cursorY
, m_cursorY
, this ) ); 
1235         if (m_cursorX 
<= (int)m_lines
[m_cursorY
].m_text
.Len()) 
1236             m_lines
[m_cursorY
].m_text
.Remove( m_cursorX
-1, 1 ); 
1239         int y 
= m_cursorY
*m_lineHeight
; 
1240         // int x = m_cursorX*m_charWidth; 
1241         int x 
= PosToPixel( m_cursorY
, m_cursorX 
); 
1242         CalcScrolledPosition( x
, y
, &x
, &y 
); 
1243         wxRect 
rect( x
+2, y
+2, 10000, m_lineHeight 
); 
1244         Refresh( TRUE
, &rect 
); 
1245         // refresh whole line for syntax colour highlighting 
1247         Refresh( FALSE
, &rect 
); 
1251 void wxTextCtrl::DoDelete() 
1255     wxString 
tmp( m_lines
[m_cursorY
].m_text 
); 
1257     int len 
= (int)tmp
.Len(); 
1258     if (m_cursorX 
>= len
) 
1260         if (m_cursorY 
== (int)m_lines
.GetCount()-1) return; 
1262         m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_DELETE
, m_cursorY
, m_cursorY
+1, this ) ); 
1264         for (int i 
= 0; i 
< (m_cursorX
-len
); i
++) 
1267         tmp 
+= m_lines
[m_cursorY
+1].m_text
; 
1269         m_lines
[m_cursorY
] = tmp
; 
1270         m_lines
.RemoveAt( m_cursorY
+1 ); 
1272         MyAdjustScrollbars(); 
1273         RefreshDown( m_cursorY 
); 
1277         m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE
, m_cursorY
, m_cursorY
, this ) ); 
1279         tmp
.Remove( m_cursorX
, 1 ); 
1280         m_lines
[m_cursorY
].m_text 
= tmp
; 
1282         int y 
= m_cursorY
*m_lineHeight
; 
1283         // int x = m_cursorX*m_charWidth; 
1284         int x 
= PosToPixel( m_cursorY
, m_cursorX 
); 
1285         CalcScrolledPosition( x
, y
, &x
, &y 
); 
1286         wxRect 
rect( x
+2, y
+2, 10000, m_lineHeight 
); 
1287         Refresh( TRUE
, &rect 
); 
1288         // refresh whole line for syntax colour highlighting 
1290         Refresh( FALSE
, &rect 
); 
1294 void wxTextCtrl::DoReturn() 
1298     m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_ENTER
, m_cursorY
, m_cursorY
, this ) ); 
1300     wxString 
tmp( m_lines
[m_cursorY
].m_text 
); 
1301     size_t indent 
= tmp
.find_first_not_of( ' ' ); 
1302     if (indent 
== wxSTRING_MAXLEN
) indent 
= 0; 
1304     if (m_cursorX 
>= (int)tmp
.Len()) 
1306         int cursorX 
= indent
; 
1307         int cursorY 
= m_cursorY 
+ 1; 
1310         for (size_t i 
= 0; i 
< indent
; i
++) new_tmp
.Append( ' ' ); 
1311         m_lines
.Insert( new wxSourceLine( new_tmp 
), cursorY 
); 
1313         MyAdjustScrollbars(); 
1314         MoveCursor( cursorX
, cursorY 
); 
1315         RefreshDown( m_cursorY 
); 
1319         wxString 
tmp1( tmp 
); 
1320         tmp1
.Remove( m_cursorX
, tmp
.Len()-m_cursorX 
); 
1321         m_lines
[m_cursorY
].m_text 
= tmp1
; 
1323         wxString 
tmp2( tmp 
); 
1324         tmp2
.Remove( 0, m_cursorX 
); 
1326         int cursorX 
= indent
; 
1327         int cursorY 
= m_cursorY 
+ 1; 
1330         for (size_t i 
= 0; i 
< indent
; i
++) new_tmp
.Append( ' ' ); 
1331         new_tmp
.Append( tmp2 
); 
1332         m_lines
.Insert( new wxSourceLine( new_tmp 
), cursorY 
); 
1334         MyAdjustScrollbars(); 
1335         MoveCursor( cursorX
, cursorY 
); 
1336         RefreshDown( m_cursorY
-1 ); 
1340 void wxTextCtrl::DoDClick() 
1342     wxString 
line( m_lines
[ m_cursorY 
].m_text 
); 
1343     if (m_cursorX 
>= (int)line
.Len()) return; 
1345     char ch 
= line
[(size_t) (p
)]; 
1346     if (((ch 
>= 'a') && (ch 
<= 'z')) || 
1347         ((ch 
>= 'A') && (ch 
<= 'Z')) || 
1348         ((ch 
>= '0') && (ch 
<= '9')) || 
1351         m_selStartY 
= m_cursorY
; 
1352         m_selEndY 
= m_cursorY
; 
1355             ch 
= line
[(size_t) (p
-1)]; 
1356             while (((ch 
>= 'a') && (ch 
<= 'z')) || 
1357                    ((ch 
>= 'A') && (ch 
<= 'Z')) || 
1358                    ((ch 
>= '0') && (ch 
<= '9')) || 
1363                 ch 
= line
[(size_t) (p
-1)]; 
1369         if (p 
< (int)line
.Len()) 
1371             ch 
= line
[(size_t) (p
)]; 
1372             while (((ch 
>= 'a') && (ch 
<= 'z')) || 
1373                    ((ch 
>= 'A') && (ch 
<= 'Z')) || 
1374                    ((ch 
>= '0') && (ch 
<= '9')) || 
1377                 if (p 
>= (int)line
.Len()) break; 
1379                 ch 
= line
[(size_t) (p
)]; 
1383         RefreshLine( m_cursorY 
); 
1387 wxString 
wxTextCtrl::GetNextToken( wxString 
&line
, size_t &pos 
) 
1390     size_t len 
= line
.Len(); 
1391     for (size_t p 
= pos
; p 
< len
; p
++) 
1393         if ((m_lang 
== wxSOURCE_LANG_PYTHON
) || (m_lang 
== wxSOURCE_LANG_PERL
)) 
1397                 for (size_t q 
= p
; q 
< len
; q
++) 
1398                     ret
.Append( line
[q
] ); 
1405             if ((line
[p
] == '/') && (p
+1 < len
) && (line
[(size_t) (p
+1)] == '/')) 
1407                 for (size_t q 
= p
; q 
< len
; q
++) 
1408                     ret
.Append( line
[q
] ); 
1416             ret
.Append( line
[p
] ); 
1417             for (size_t q 
= p
+1; q 
< len
; q
++) 
1419                 ret
.Append( line
[q
] ); 
1420                 if ((line
[q
] == '"') && ((line
[(size_t) (q
-1)] != '\\') || (q 
>= 2 && line
[(size_t) (q
-2)] == '\\'))) 
1427         if (line
[p
] == '\'') 
1429             ret
.Append( line
[p
] ); 
1430             for (size_t q 
= p
+1; q 
< len
; q
++) 
1432                 ret
.Append( line
[q
] ); 
1433                 if ((line
[q
] == '\'') && ((line
[(size_t) (q
-1)] != '\\') || (q 
>= 2 && line
[(size_t) (q
-2)] == '\\'))) 
1440         if (((line
[p
] >= 'a') && (line
[p
] <= 'z')) || 
1441             ((line
[p
] >= 'A') && (line
[p
] <= 'Z')) || 
1445            ret
.Append( line
[p
] ); 
1446            for (size_t q 
= p
+1; q 
< len
; q
++) 
1448                 if (((line
[q
] >= 'a') && (line
[q
] <= 'z')) || 
1449                    ((line
[q
] >= 'A') && (line
[q
] <= 'Z')) || 
1450                    ((line
[q
] >= '0') && (line
[q
] <= '9')) || 
1453                     ret
.Append( line
[q
] ); 
1470 void wxTextCtrl::OnEraseBackground( wxEraseEvent 
&event 
) 
1475 void wxTextCtrl::DrawLinePart( wxDC 
&dc
, int x
, int y
, const wxString 
&toDraw
, const wxString 
&origin
, const wxColour 
&colour 
) 
1478     size_t len 
= origin
.Len(); 
1479     dc
.SetTextForeground( colour 
); 
1482         while (toDraw
[pos
] == wxT(' ')) 
1485             if (pos 
== len
) return; 
1491         current 
+= toDraw
[pos
]; 
1493         while ( (toDraw
[pos
] == origin
[pos
]) && (pos 
< len
)) 
1495             current 
+= toDraw
[pos
]; 
1500         wxString tmp 
= origin
.Left( start 
); 
1501         GetTextExtent( tmp
, &xx
, NULL
, NULL
, NULL 
); 
1504         dc
.DrawText( current
, xx
, yy 
); 
1508 void wxTextCtrl::DrawLine( wxDC 
&dc
, int x
, int y
, const wxString 
&line2
, int lineNum 
) 
1510     int selStartY 
= m_selStartY
; 
1511     int selEndY 
= m_selEndY
; 
1512     int selStartX 
= m_selStartX
; 
1513     int selEndX 
= m_selEndX
; 
1515     if ((selStartY 
> selEndY
) || 
1516         ((selStartY 
== selEndY
) && (selStartX 
> selEndX
))) 
1518         int tmp 
= selStartX
; 
1519         selStartX 
= selEndX
; 
1522         selStartY 
= selEndY
; 
1526     wxString 
line( line2 
); 
1527     if (HasFlag(wxTE_PASSWORD
)) 
1529         size_t len 
= line
.Len(); 
1530         line 
= wxString( wxT('*'), len 
); 
1533     wxString 
keyword( ' ', line
.Len() ); 
1534     wxString 
define( ' ', line
.Len() ); 
1535     wxString 
variable( ' ', line
.Len() ); 
1536     wxString 
comment( ' ', line
.Len() ); 
1537     wxString 
my_string( ' ', line
.Len() ); 
1538     wxString 
selection( ' ', line
.Len() ); 
1540     if (m_lang 
!= wxSOURCE_LANG_NONE
) 
1542         if (lineNum 
== m_bracketY
) 
1544             wxString 
red( ' ', line
.Len() ); 
1545             if (m_bracketX 
< (int)line
.Len()) 
1547                 red
.SetChar( m_bracketX
, line
[(size_t) (m_bracketX
)] ); 
1548                 line
.SetChar( m_bracketX
, ' ' ); 
1549                 dc
.SetTextForeground( *wxRED 
); 
1550                 dc
.DrawText( red
, x
, y 
); 
1551                 dc
.SetTextForeground( *wxBLACK 
); 
1556         wxString 
token( GetNextToken( line
, pos 
) ); 
1557         while (!token
.IsNull()) 
1559             if (m_keywords
.Index( token 
) != wxNOT_FOUND
) 
1561                 size_t end_pos 
= pos 
+ token
.Len(); 
1562                 for (size_t i 
= pos
; i 
< end_pos
; i
++) 
1564                     keyword
[i
] = line
[i
]; 
1568             if (m_defines
.Index( token 
) != wxNOT_FOUND
) 
1570                 size_t end_pos 
= pos 
+ token
.Len(); 
1571                 for (size_t i 
= pos
; i 
< end_pos
; i
++) 
1573                     define
[i
] = line
[i
]; 
1577             if ((m_variables
.Index( token 
) != wxNOT_FOUND
) || 
1578                 ((token
.Len() > 2) && (token
[(size_t) (0)] == 'w') && (token
[(size_t) (1)] == 'x'))) 
1580                 size_t end_pos 
= pos 
+ token
.Len(); 
1581                 for (size_t i 
= pos
; i 
< end_pos
; i
++) 
1583                     variable
[i
] = line
[i
]; 
1587             if ((token
.Len() >= 2) && (token
[(size_t) (0)] == '/') && (token
[(size_t) (1)] == '/') && (m_lang 
== wxSOURCE_LANG_CPP
)) 
1589                 size_t end_pos 
= pos 
+ token
.Len(); 
1590                 for (size_t i 
= pos
; i 
< end_pos
; i
++) 
1592                     comment
[i
] = line
[i
]; 
1596             if ((token
[(size_t) (0)] == '#') && 
1597                 ((m_lang 
== wxSOURCE_LANG_PYTHON
) || (m_lang 
== wxSOURCE_LANG_PERL
))) 
1599                 size_t end_pos 
= pos 
+ token
.Len(); 
1600                 for (size_t i 
= pos
; i 
< end_pos
; i
++) 
1602                     comment
[i
] = line
[i
]; 
1606             if ((token
[(size_t) (0)] == '"') || (token
[(size_t) (0)] == '\'')) 
1608                 size_t end_pos 
= pos 
+ token
.Len(); 
1609                 for (size_t i 
= pos
; i 
< end_pos
; i
++) 
1611                     my_string
[i
] = line
[i
]; 
1616             token 
= GetNextToken( line
, pos 
); 
1620     if ((lineNum 
< selStartY
) || (lineNum 
> selEndY
)) 
1622         DrawLinePart( dc
, x
, y
, line
, line2
, *wxBLACK 
); 
1623         DrawLinePart( dc
, x
, y
, selection
, line2
, *wxWHITE 
); 
1624         DrawLinePart( dc
, x
, y
, keyword
, line2
, m_keywordColour 
); 
1625         DrawLinePart( dc
, x
, y
, define
, line2
, m_defineColour 
); 
1626         DrawLinePart( dc
, x
, y
, variable
, line2
, m_variableColour 
); 
1627         DrawLinePart( dc
, x
, y
, comment
, line2
, m_commentColour 
); 
1628         DrawLinePart( dc
, x
, y
, my_string
, line2
, m_stringColour 
); 
1632     if (selStartY 
== selEndY
) 
1634         // int xx = selStartX*m_charWidth; 
1635         int xx 
= PosToPixel( lineNum
, selStartX 
); 
1636         // int ww = (selEndX-selStartX)*m_charWidth; 
1637         int ww 
= PosToPixel( lineNum
, selEndX 
) - xx
; 
1638         dc
.DrawRectangle( xx
+2, lineNum
*m_lineHeight
+2, ww
, m_lineHeight 
); 
1640         for (size_t i 
= (size_t)selStartX
; i 
< (size_t)selEndX
; i
++) 
1642             selection
[i
] = line
[i
]; 
1646     if ((lineNum 
> selStartY
) && (lineNum 
< selEndY
)) 
1648         dc
.DrawRectangle( 0+2, lineNum
*m_lineHeight
+2, 10000, m_lineHeight 
); 
1650         for (size_t i 
= 0; i 
< line
.Len(); i
++) 
1652             selection
[i
] = line
[i
]; 
1656     if (lineNum 
== selStartY
) 
1658         // int xx = selStartX*m_charWidth; 
1659         int xx 
= PosToPixel( lineNum
, selStartX 
); 
1660         dc
.DrawRectangle( xx
+2, lineNum
*m_lineHeight
+2, 10000, m_lineHeight 
); 
1662         for (size_t i 
= (size_t)selStartX
; i 
< line
.Len(); i
++) 
1664             selection
[i
] = line
[i
]; 
1668     if (lineNum 
== selEndY
) 
1670         // int ww = selEndX*m_charWidth; 
1671         int ww 
= PosToPixel( lineNum
, selEndX 
); 
1672         dc
.DrawRectangle( 0+2, lineNum
*m_lineHeight
+2, ww
, m_lineHeight 
); 
1674         for (size_t i 
= 0; i 
< (size_t)selEndX
; i
++) 
1676             selection
[i
] = line
[i
]; 
1681     DrawLinePart( dc
, x
, y
, line
, line2
, *wxBLACK 
); 
1682     DrawLinePart( dc
, x
, y
, selection
, line2
, *wxWHITE 
); 
1683     DrawLinePart( dc
, x
, y
, keyword
, line2
, m_keywordColour 
); 
1684     DrawLinePart( dc
, x
, y
, define
, line2
, m_defineColour 
); 
1685     DrawLinePart( dc
, x
, y
, variable
, line2
, m_variableColour 
); 
1686     DrawLinePart( dc
, x
, y
, comment
, line2
, m_commentColour 
); 
1687     DrawLinePart( dc
, x
, y
, my_string
, line2
, m_stringColour 
); 
1690 void wxTextCtrl::OnPaint( wxPaintEvent 
&event 
) 
1694     if (m_lines
.GetCount() == 0) return; 
1698     dc
.SetFont( m_sourceFont 
); 
1701     GetViewStart( NULL
, &scroll_y 
); 
1703     // We have a inner border of two pixels 
1704     // around the text, so scroll units do 
1705     // not correspond to lines. 
1706     if (scroll_y 
> 0) scroll_y
--; 
1710     GetClientSize( &size_x
, &size_y 
); 
1712     dc
.SetPen( *wxTRANSPARENT_PEN 
); 
1713     dc
.SetBrush( wxBrush( wxTHEME_COLOUR(HIGHLIGHT
), wxSOLID 
) ); 
1714     int upper 
= wxMin( (int)m_lines
.GetCount(), scroll_y
+(size_y
/m_lineHeight
)+2 ); 
1715     for (int i 
= scroll_y
; i 
< upper
; i
++) 
1718         int y 
= i
*m_lineHeight
+2; 
1720         int h 
= m_lineHeight
; 
1721         CalcScrolledPosition( x
,y
,&x
,&y 
); 
1722         if (IsExposed(x
,y
,w
,h
)) 
1723             DrawLine( dc
, 0+2, i
*m_lineHeight
+2, m_lines
[i
].m_text
, i 
); 
1726     if (m_editable 
&& (FindFocus() == this)) 
1728         ///dc.SetBrush( *wxRED_BRUSH ); 
1729         dc
.SetBrush( *wxBLACK_BRUSH 
); 
1730         // int xx = m_cursorX*m_charWidth; 
1731         int xx 
= PosToPixel( m_cursorY
, m_cursorX 
); 
1732         dc
.DrawRectangle( xx
+2, m_cursorY
*m_lineHeight
+2, 2, m_lineHeight 
); 
1736 void wxTextCtrl::OnMouse( wxMouseEvent 
&event 
) 
1738     if (m_lines
.GetCount() == 0) return; 
1741 #if 0  // there is no middle button on iPAQs 
1742     if (event
.MiddleDown()) 
1749     if (event
.LeftDClick()) 
1755     if (event
.LeftDown()) 
1763         m_capturing 
= FALSE
; 
1767     if (event
.LeftDown() ||  
1768         (event
.LeftIsDown() && m_capturing
)) 
1770         int x 
= event
.GetX(); 
1771         int y 
= event
.GetY(); 
1772         CalcUnscrolledPosition( x
, y
, &x
, &y 
); 
1774         // x /= m_charWidth; 
1775         x 
= PixelToPos( y
, x 
); 
1777             wxMin( 1000, wxMax( 0, x 
) ),  
1778             wxMin( (int)m_lines
.GetCount()-1, wxMax( 0, y 
) ), 
1779             event
.ShiftDown() || !event
.LeftDown() ); 
1783 void wxTextCtrl::OnChar( wxKeyEvent 
&event 
) 
1785     if (m_lines
.GetCount() == 0) return; 
1787     if (!m_editable
) return; 
1791     GetClientSize( &size_x
, &size_y 
); 
1792     size_x 
/= m_charWidth
; 
1793     size_y 
/= m_lineHeight
; 
1796     if (event
.ShiftDown()) 
1798         switch (event
.GetKeyCode()) 
1800             case '4': event
.m_keyCode 
= WXK_LEFT
;   break; 
1801             case '8': event
.m_keyCode 
= WXK_UP
;     break; 
1802             case '6': event
.m_keyCode 
= WXK_RIGHT
;  break; 
1803             case '2': event
.m_keyCode 
= WXK_DOWN
;   break; 
1804             case '9': event
.m_keyCode 
= WXK_PRIOR
;  break; 
1805             case '3': event
.m_keyCode 
= WXK_NEXT
;   break; 
1806             case '7': event
.m_keyCode 
= WXK_HOME
;   break; 
1807             case '1': event
.m_keyCode 
= WXK_END
;    break; 
1808             case '0': event
.m_keyCode 
= WXK_INSERT
; break; 
1812     switch (event
.GetKeyCode()) 
1816             if (m_ignoreInput
) return; 
1818                 MoveCursor( m_cursorX
, m_cursorY
-1, event
.ShiftDown() ); 
1819             m_ignoreInput 
= TRUE
; 
1824             if (m_ignoreInput
) return; 
1825             if (m_cursorY 
< (int)(m_lines
.GetCount()-1)) 
1826                 MoveCursor( m_cursorX
, m_cursorY
+1, event
.ShiftDown() ); 
1827             m_ignoreInput 
= TRUE
; 
1832             if (m_ignoreInput
) return; 
1835                 MoveCursor( m_cursorX
-1, m_cursorY
, event
.ShiftDown() ); 
1840                     MoveCursor( m_lines
[m_cursorY
-1].m_text
.Len(), m_cursorY
-1, event
.ShiftDown() ); 
1842             m_ignoreInput 
= TRUE
; 
1847             if (m_ignoreInput
) return; 
1848             if (m_cursorX 
< 1000) 
1849                 MoveCursor( m_cursorX
+1, m_cursorY
, event
.ShiftDown() ); 
1850             m_ignoreInput 
= TRUE
; 
1855             if (event
.ControlDown()) 
1856                 MoveCursor( 0, 0, event
.ShiftDown() ); 
1858                 MoveCursor( 0, m_cursorY
, event
.ShiftDown() ); 
1863             if (event
.ControlDown()) 
1864                 MoveCursor( 0, m_lines
.GetCount()-1, event
.ShiftDown() ); 
1866                 MoveCursor( m_lines
[m_cursorY
].m_text
.Len(), m_cursorY
, event
.ShiftDown() ); 
1871             if (m_ignoreInput
) return; 
1872             MoveCursor( m_cursorX
, wxMin( (int)(m_lines
.GetCount()-1), m_cursorY
+size_y 
), event
.ShiftDown() ); 
1873             m_ignoreInput 
= TRUE
; 
1878             if (m_ignoreInput
) return; 
1879             MoveCursor( m_cursorX
, wxMax( 0, m_cursorY
-size_y 
), event
.ShiftDown() ); 
1880             m_ignoreInput 
= TRUE
; 
1885             if (event
.ShiftDown()) 
1887             else if (event
.ControlDown()) 
1890                 m_overwrite 
= !m_overwrite
; 
1895             if (m_windowStyle 
& wxPROCESS_ENTER
) 
1897                 wxCommandEvent 
event(wxEVT_COMMAND_TEXT_ENTER
, m_windowId
); 
1898                 event
.SetEventObject(this); 
1899                 event
.SetString(GetValue()); 
1900                 if (GetEventHandler()->ProcessEvent(event
)) return; 
1918             bool save_overwrite 
= m_overwrite
; 
1919             m_overwrite 
= FALSE
; 
1920             int i 
= 4-(m_cursorX 
% 4); 
1922             for (int c 
= 0; c 
< i
; c
++) 
1924             m_overwrite 
= save_overwrite
; 
1945             if (  (event
.GetKeyCode() >= 'a') && 
1946                   (event
.GetKeyCode() <= 'z') && 
1954             if (  (event
.GetKeyCode() >= 32) &&  
1955                   (event
.GetKeyCode() <= 255) && 
1956                  !(event
.ControlDown() && !event
.AltDown()) ) // filters out Ctrl-X but leaves Alt-Gr 
1960                 DoChar( (char) event
.GetKeyCode() ); 
1969 void wxTextCtrl::OnInternalIdle() 
1971     wxControl::OnInternalIdle(); 
1973     m_ignoreInput 
= FALSE
; 
1975     if (m_lang 
!= wxSOURCE_LANG_NONE
) 
1976         SearchForBrackets(); 
1979 void wxTextCtrl::Indent() 
1981     int startY 
= m_cursorY
; 
1982     int endY 
= m_cursorY
; 
1985         startY 
= m_selStartY
; 
1995     m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE
, startY
, endY
, this ) ); 
1997     for (int i 
= startY
; i 
<= endY
; i
++) 
1999         m_lines
[i
].m_text
.insert( 0u, wxT("    ") ); 
2004 void wxTextCtrl::Unindent() 
2006     int startY 
= m_cursorY
; 
2007     int endY 
= m_cursorY
; 
2010         startY 
= m_selStartY
; 
2020     m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE
, startY
, endY
, this ) ); 
2022     for (int i 
= startY
; i 
<= endY
; i
++) 
2024         for (int n 
= 0; n 
< 4; n
++) 
2026             if (m_lines
[i
].m_text
[0u] == wxT(' ')) 
2027                 m_lines
[i
].m_text
.erase(0u,1u); 
2032 bool wxTextCtrl::HasSelection() 
2034     return ((m_selStartY 
!= m_selEndY
) || (m_selStartX 
!= m_selEndX
)); 
2037 void wxTextCtrl::ClearSelection() 
2045 void wxTextCtrl::RefreshLine( int n 
) 
2047     int y 
= n
*m_lineHeight
; 
2049     CalcScrolledPosition( x
, y
, &x
, &y 
); 
2050     wxRect 
rect( 0+2, y
+2, 10000, m_lineHeight 
); 
2051     Refresh( TRUE
, &rect 
); 
2054 void wxTextCtrl::RefreshDown( int n 
) 
2058     GetClientSize( &size_x
, &size_y 
); 
2062     GetViewStart( &view_x
, &view_y 
); 
2070         int y 
= n
*m_lineHeight
; 
2072         CalcScrolledPosition( x
, y
, &x
, &y 
); 
2074         wxRect 
rect( 0+2, y
+2, 10000, size_y 
); 
2075         Refresh( TRUE
, &rect 
); 
2079 void wxTextCtrl::MoveCursor( int new_x
, int new_y
, bool shift
, bool centre 
) 
2081     if (!m_editable
) return; 
2083     // if (IsSingleLine() || (m_lang == wxSOURCE_LANG_NONE)) 
2085         if (new_x 
> (int) (m_lines
[new_y
].m_text
.Len())) 
2086             new_x 
= m_lines
[new_y
].m_text
.Len(); 
2089     if ((new_x 
== m_cursorX
) && (new_y 
== m_cursorY
)) return; 
2091     bool no_cursor_refresh 
= FALSE
; 
2092     bool has_selection 
= HasSelection(); 
2097         bool erase_background 
= TRUE
; 
2101             m_selStartX 
= m_cursorX
; 
2102             m_selStartY 
= m_cursorY
; 
2106             if (new_y 
> m_selStartY
) 
2108                 y 
= m_selStartY
*m_lineHeight
; 
2109                 h 
= (new_y
-m_selStartY
+1)*m_lineHeight
; 
2111             else if (new_y 
== m_selStartY
) 
2113                 x 
= PosToPixel( new_y
, m_selStartX 
); 
2114                 w 
= PosToPixel( new_y
, new_x 
) - x
; 
2118                     w 
= -w 
+ 2; // +2 for the cursor 
2120                 y 
= m_selStartY
*m_lineHeight
; 
2125                 y 
= new_y
*m_lineHeight
; 
2126                 h 
= (-new_y
+m_selStartY
+1)*m_lineHeight
; 
2129             no_cursor_refresh 
= TRUE
; 
2135             if (new_y 
== m_selEndY
) 
2137                 y 
= new_y 
*m_lineHeight
; 
2139                 if (m_selEndX 
> new_x
) 
2141                     // x = new_x*m_charWidth; 
2142                     x 
= PosToPixel( new_y
, new_x 
); 
2143                     // w = (m_selEndX-new_x)*m_charWidth; 
2144                     w 
= PosToPixel( new_y
, m_selEndX 
) - x
; 
2148                     // x = m_selEndX*m_charWidth; 
2149                     x 
= PosToPixel( new_y
, m_selEndX 
); 
2150                     // w = (-m_selEndX+new_x)*m_charWidth; 
2151                     w 
= PosToPixel( new_y
, new_x 
) - x
; 
2158                 if (new_y 
> m_selEndY
) 
2160                     y 
= m_selEndY
*m_lineHeight
; 
2161                     h 
= (new_y
-m_selEndY
+1) * m_lineHeight
; 
2163                     erase_background 
= ((m_selEndY 
< m_selStartY
) || 
2164                                         ((m_selEndY 
== m_selStartY
) && (m_selEndX 
< m_selStartX
))); 
2168                     y 
= new_y
*m_lineHeight
; 
2169                     h 
= (-new_y
+m_selEndY
+1) * m_lineHeight
; 
2171                     erase_background 
= ((m_selEndY 
> m_selStartY
) || 
2172                                         ((m_selEndY 
== m_selStartY
) && (m_selEndX 
> m_selStartX
))); 
2174                 no_cursor_refresh 
= TRUE
; 
2183         CalcScrolledPosition( x
, y
, &x
, &y 
); 
2184         wxRect 
rect( x
+2, y
+2, w
, h 
); 
2185         Refresh( erase_background
, &rect 
); 
2191             int ry1 
= m_selEndY
; 
2192             int ry2 
= m_selStartY
; 
2206             int y 
= ry1
*m_lineHeight
; 
2207             CalcScrolledPosition( x
, y
, &x
, &y 
); 
2208             wxRect 
rect( 0, y
+2, 10000, (ry2
-ry1
+1)*m_lineHeight 
); 
2210             Refresh( TRUE
, &rect 
); 
2215     printf( "startx %d starty %d endx %d endy %d\n",  
2216             m_selStartX, m_selStartY, m_selEndX, m_selEndY ); 
2218     printf( "has %d\n", (int)HasSelection() ); 
2221     if (!no_cursor_refresh
) 
2223         // int x = m_cursorX*m_charWidth; 
2224         int x 
= PosToPixel( m_cursorY
, m_cursorX 
); 
2225         int y 
= m_cursorY
*m_lineHeight
; 
2226         CalcScrolledPosition( x
, y
, &x
, &y 
); 
2227         wxRect 
rect( x
+2, y
+2, 4, m_lineHeight
+2 ); 
2232         Refresh( TRUE
, &rect 
); 
2234         if (FindFocus() == this) 
2236             wxClientDC 
dc(this); 
2238             dc
.SetPen( *wxTRANSPARENT_PEN 
); 
2239             //dc.SetBrush( *wxRED_BRUSH ); 
2240             dc
.SetBrush( *wxBLACK_BRUSH 
); 
2241             // int xx = m_cursorX*m_charWidth; 
2242             int xx 
= PosToPixel( m_cursorY
, m_cursorX 
); 
2243             dc
.DrawRectangle( xx
+2, m_cursorY
*m_lineHeight
+2, 2, m_lineHeight 
); 
2249     GetClientSize( &size_x
, &size_y 
); 
2250     size_x 
/= m_charWidth
; 
2251     size_y 
/= m_lineHeight
; 
2255     GetViewStart( &view_x
, &view_y 
); 
2259         int sy 
= m_cursorY 
- (size_y
/2); 
2265         if (m_cursorY 
< view_y
) 
2266             Scroll( -1, m_cursorY 
); 
2267         else if (m_cursorY 
> view_y
+size_y
-1) 
2268             Scroll( -1, m_cursorY
-size_y
+1 ); 
2271     //int xx = m_cursorX; 
2272     int xx 
= PosToPixel( m_cursorY
, m_cursorX 
) / m_charWidth
; 
2276     else if (xx 
> view_x
+size_x
-1) 
2277         Scroll( xx
-size_x
+1, -1 ); 
2280 void wxTextCtrl::MyAdjustScrollbars() 
2285     int y_range 
= m_lines
.GetCount(); 
2288     GetClientSize( NULL
, &height 
); 
2290     if (height 
>= (int)m_lines
.GetCount() *m_lineHeight
) 
2295     GetViewStart( &view_x
, &view_y 
); 
2297     SetScrollbars( m_charWidth
, m_lineHeight
, m_longestLine
+2, y_range
, view_x
, view_y 
); 
2300 //----------------------------------------------------------------------------- 
2301 //  clipboard handlers 
2302 //----------------------------------------------------------------------------- 
2304 void wxTextCtrl::OnCut(wxCommandEvent
& WXUNUSED(event
)) 
2309 void wxTextCtrl::OnCopy(wxCommandEvent
& WXUNUSED(event
)) 
2314 void wxTextCtrl::OnPaste(wxCommandEvent
& WXUNUSED(event
)) 
2319 void wxTextCtrl::OnUndo(wxCommandEvent
& WXUNUSED(event
)) 
2324 void wxTextCtrl::OnRedo(wxCommandEvent
& WXUNUSED(event
)) 
2329 void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent
& event
) 
2331     event
.Enable( CanCut() ); 
2334 void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent
& event
) 
2336     event
.Enable( CanCopy() ); 
2339 void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent
& event
) 
2341     event
.Enable( CanPaste() ); 
2344 void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent
& event
) 
2346     event
.Enable( CanUndo() ); 
2349 void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent
& event
) 
2351     event
.Enable( CanRedo() ); 
2354 wxSize 
wxTextCtrl::DoGetBestSize() const 
2358         wxSize 
ret(80, m_lineHeight 
+ 4); 
2360         if (HasFlag(wxBORDER_SUNKEN
) || HasFlag(wxBORDER_RAISED
)) 
2363         if (HasFlag(wxBORDER_SIMPLE
)) 
2370         return wxSize(80, 60); 
2374 // ---------------------------------------------------------------------------- 
2376 // ---------------------------------------------------------------------------- 
2378 void wxTextCtrl::Freeze() 
2382 void wxTextCtrl::Thaw() 
2386 void wxTextCtrl::OnSetFocus( wxFocusEvent
& event 
) 
2388     // To hide or show caret, as appropriate 
2392 void wxTextCtrl::OnKillFocus( wxFocusEvent
& event 
) 
2394     // To hide or show caret, as appropriate 
2398 // ---------------------------------------------------------------------------- 
2399 // text control scrolling 
2400 // ---------------------------------------------------------------------------- 
2402 bool wxTextCtrl::ScrollLines(int lines
) 
2404     wxFAIL_MSG( "wxTextCtrl::ScrollLines not implemented"); 
2409 bool wxTextCtrl::ScrollPages(int pages
) 
2411     wxFAIL_MSG( "wxTextCtrl::ScrollPages not implemented");