1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
11 #pragma implementation "textctrl.h"
14 #include "wx/textctrl.h"
18 #include "wx/settings.h"
20 #include "wx/clipbrd.h"
21 #include "wx/tokenzr.h"
23 #include "wx/univ/inphand.h"
24 #include "wx/univ/renderer.h"
25 #include "wx/univ/colschem.h"
26 #include "wx/univ/theme.h"
28 //-----------------------------------------------------------------------------
30 //-----------------------------------------------------------------------------
32 wxSourceUndoStep::wxSourceUndoStep( wxSourceUndo type
, int y1
, int y2
, wxTextCtrl
*owner
)
39 m_cursorX
= m_owner
->GetCursorX();
40 m_cursorY
= m_owner
->GetCursorY();
42 if (m_type
== wxSOURCE_UNDO_LINE
)
44 m_text
= m_owner
->m_lines
[m_y1
].m_text
;
46 if (m_type
== wxSOURCE_UNDO_ENTER
)
48 m_text
= m_owner
->m_lines
[m_y1
].m_text
;
50 if (m_type
== wxSOURCE_UNDO_BACK
)
52 for (int i
= m_y1
; i
< m_y2
+2; i
++)
54 if (i
>= (int)m_owner
->m_lines
.GetCount())
57 m_lines
.Add( m_owner
->m_lines
[i
].m_text
);
60 if (m_type
== wxSOURCE_UNDO_DELETE
)
62 for (int i
= m_y1
; i
< m_y2
+1; i
++)
64 m_lines
.Add( m_owner
->m_lines
[i
].m_text
);
67 if (m_type
== wxSOURCE_UNDO_PASTE
)
69 m_text
= m_owner
->m_lines
[m_y1
].m_text
;
73 void wxSourceUndoStep::Undo()
75 if (m_type
== wxSOURCE_UNDO_LINE
)
77 m_owner
->m_lines
[m_y1
].m_text
= m_text
;
78 m_owner
->MoveCursor( m_cursorX
, m_cursorY
);
79 m_owner
->RefreshLine( m_y1
);
81 if (m_type
== wxSOURCE_UNDO_ENTER
)
83 m_owner
->m_lines
[m_y1
].m_text
= m_text
;
84 m_owner
->m_lines
.RemoveAt( m_y1
+1 );
85 m_owner
->MoveCursor( m_cursorX
, m_cursorY
);
86 m_owner
->RefreshDown( m_y1
);
88 if (m_type
== wxSOURCE_UNDO_BACK
)
90 m_owner
->m_lines
[m_y1
].m_text
= m_lines
[0];
91 m_owner
->m_lines
.Insert( new wxSourceLine( m_lines
[1] ), m_y1
+1 );
92 m_owner
->MyAdjustScrollbars();
93 m_owner
->MoveCursor( m_cursorX
, m_cursorY
);
94 m_owner
->RefreshDown( m_y1
);
96 if (m_type
== wxSOURCE_UNDO_DELETE
)
98 m_owner
->m_lines
[m_y1
].m_text
= m_lines
[0];
99 for (int i
= 1; i
< (int)m_lines
.GetCount(); i
++)
100 m_owner
->m_lines
.Insert( new wxSourceLine( m_lines
[i
] ), m_y1
+i
);
101 m_owner
->MyAdjustScrollbars();
102 m_owner
->MoveCursor( m_cursorX
, m_cursorY
);
103 m_owner
->RefreshDown( m_y1
);
105 if (m_type
== wxSOURCE_UNDO_PASTE
)
107 m_owner
->m_lines
[m_y1
].m_text
= m_text
;
108 for (int i
= 0; i
< m_y2
-m_y1
; i
++)
109 m_owner
->m_lines
.RemoveAt( m_y1
+1 );
110 m_owner
->MyAdjustScrollbars();
111 m_owner
->MoveCursor( m_cursorX
, m_cursorY
);
112 m_owner
->RefreshDown( m_y1
);
114 if (m_type
== wxSOURCE_UNDO_INSERT_LINE
)
116 m_owner
->m_lines
.RemoveAt( m_y1
);
117 m_owner
->MyAdjustScrollbars();
118 m_owner
->MoveCursor( 0, m_y1
);
119 m_owner
->RefreshDown( m_y1
);
123 #include "wx/arrimpl.cpp"
124 WX_DEFINE_OBJARRAY(wxSourceLineArray
);
126 //-----------------------------------------------------------------------------
128 //-----------------------------------------------------------------------------
130 IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl
,wxControl
)
132 BEGIN_EVENT_TABLE(wxTextCtrl
, wxControl
)
133 EVT_PAINT(wxTextCtrl::OnPaint
)
134 EVT_ERASE_BACKGROUND(wxTextCtrl::OnEraseBackground
)
135 EVT_CHAR(wxTextCtrl::OnChar
)
136 EVT_MOUSE_EVENTS(wxTextCtrl::OnMouse
)
137 EVT_IDLE(wxTextCtrl::OnIdle
)
138 EVT_KILL_FOCUS(wxTextCtrl::OnKillFocus
)
139 EVT_SET_FOCUS(wxTextCtrl::OnSetFocus
)
141 EVT_MENU(wxID_CUT
, wxTextCtrl::OnCut
)
142 EVT_MENU(wxID_COPY
, wxTextCtrl::OnCopy
)
143 EVT_MENU(wxID_PASTE
, wxTextCtrl::OnPaste
)
144 EVT_MENU(wxID_UNDO
, wxTextCtrl::OnUndo
)
145 EVT_MENU(wxID_REDO
, wxTextCtrl::OnRedo
)
147 EVT_UPDATE_UI(wxID_CUT
, wxTextCtrl::OnUpdateCut
)
148 EVT_UPDATE_UI(wxID_COPY
, wxTextCtrl::OnUpdateCopy
)
149 EVT_UPDATE_UI(wxID_PASTE
, wxTextCtrl::OnUpdatePaste
)
150 EVT_UPDATE_UI(wxID_UNDO
, wxTextCtrl::OnUpdateUndo
)
151 EVT_UPDATE_UI(wxID_REDO
, wxTextCtrl::OnUpdateRedo
)
154 void wxTextCtrl::Init()
159 m_undos
.DeleteContents( TRUE
);
161 m_lang
= wxSOURCE_LANG_NONE
;
174 m_ignoreInput
= FALSE
;
178 m_keywordColour
= wxColour( 10, 140, 10 );
180 m_defineColour
= *wxRED
;
182 m_variableColour
= wxColour( 50, 120, 150 );
184 m_commentColour
= wxColour( 130, 130, 130 );
186 m_stringColour
= wxColour( 10, 140, 10 );
189 wxTextCtrl::wxTextCtrl( wxWindow
*parent
,
191 const wxString
&value
,
195 const wxValidator
& validator
,
196 const wxString
&name
)
197 : wxScrollHelper(this)
201 Create( parent
, id
, value
, pos
, size
, style
, validator
, name
);
204 bool wxTextCtrl::Create( wxWindow
*parent
,
206 const wxString
&value
,
210 const wxValidator
& validator
,
211 const wxString
&name
)
213 if ((style
& wxBORDER_MASK
) == 0)
214 style
|= wxBORDER_SUNKEN
;
216 if ((style
& wxTE_MULTILINE
) != 0)
217 style
|= wxALWAYS_SHOW_SB
;
219 wxTextCtrlBase::Create( parent
, id
, pos
/* wxDefaultPosition */, size
,
220 style
|wxVSCROLL
|wxHSCROLL
|wxNO_FULL_REPAINT_ON_RESIZE
);
222 SetBackgroundColour( *wxWHITE
);
224 SetCursor( wxCursor( wxCURSOR_IBEAM
) );
226 m_editable
= ((m_windowStyle
& wxTE_READONLY
) == 0);
228 if (HasFlag(wxTE_PASSWORD
))
229 m_sourceFont
= wxFont( 12, wxMODERN
, wxNORMAL
, wxNORMAL
);
231 m_sourceFont
= GetFont();
234 dc
.SetFont( m_sourceFont
);
235 m_lineHeight
= dc
.GetCharHeight();
236 m_charWidth
= dc
.GetCharWidth();
240 wxSize
size_best( DoGetBestSize() );
241 wxSize
new_size( size
);
242 if (new_size
.x
== -1)
243 new_size
.x
= size_best
.x
;
244 if (new_size
.y
== -1)
245 new_size
.y
= size_best
.y
;
246 if ((new_size
.x
!= size
.x
) || (new_size
.y
!= size
.y
))
247 SetSize( new_size
.x
, new_size
.y
);
249 // We create an input handler since it might be useful
250 CreateInputHandler(wxINP_HANDLER_TEXTCTRL
);
252 MyAdjustScrollbars();
257 //-----------------------------------------------------------------------------
259 //-----------------------------------------------------------------------------
261 wxString
wxTextCtrl::GetValue() const
264 for (size_t i
= 0; i
< m_lines
.GetCount(); i
++)
266 ret
+= m_lines
[i
].m_text
;
267 if (i
+1 < m_lines
.GetCount())
274 void wxTextCtrl::SetValue(const wxString
& value
)
278 wxString oldValue
= GetValue();
288 m_lines
.Add( new wxSourceLine( wxT("") ) );
296 pos
= value
.find( wxT('\n'), begin
);
299 wxSourceLine
*sl
= new wxSourceLine( value
.Mid( begin
, value
.Len()-begin
) );
302 // if (sl->m_text.Len() > m_longestLine)
303 // m_longestLine = sl->m_text.Len();
305 GetTextExtent( sl
->m_text
, &ww
, NULL
, NULL
, NULL
);
307 if (ww
> m_longestLine
)
314 wxSourceLine
*sl
= new wxSourceLine( value
.Mid( begin
, pos
-begin
) );
317 // if (sl->m_text.Len() > m_longestLine)
318 // m_longestLine = sl->m_text.Len();
320 GetTextExtent( sl
->m_text
, &ww
, NULL
, NULL
, NULL
);
322 if (ww
> m_longestLine
)
330 // Don't need to refresh if the value hasn't changed
331 if ((GetWindowStyle() & wxTE_MULTILINE
) == 0)
333 if (value
== oldValue
)
337 MyAdjustScrollbars();
342 int wxTextCtrl::GetLineLength(long lineNo
) const
344 if (lineNo
>= (long)m_lines
.GetCount())
347 return m_lines
[lineNo
].m_text
.Len();
350 wxString
wxTextCtrl::GetLineText(long lineNo
) const
352 if (lineNo
>= (long)m_lines
.GetCount())
355 return m_lines
[lineNo
].m_text
;
358 int wxTextCtrl::GetNumberOfLines() const
360 return m_lines
.GetCount();
363 bool wxTextCtrl::IsModified() const
368 bool wxTextCtrl::IsEditable() const
373 void wxTextCtrl::GetSelection(long* from
, long* to
) const
375 if (m_selStartX
== -1 || m_selStartY
== -1 ||
376 m_selEndX
== -1 || m_selEndY
== -1)
378 *from
= GetInsertionPoint();
379 *to
= GetInsertionPoint();
383 *from
= XYToPosition(m_selStartX
, m_selStartY
);
384 *to
= XYToPosition(m_selEndX
, m_selEndY
);
388 void wxTextCtrl::Clear()
396 m_lines
.Add( new wxSourceLine( wxT("") ) );
398 SetScrollbars( m_charWidth
, m_lineHeight
, 0, 0, 0, 0 );
403 void wxTextCtrl::Replace(long from
, long to
, const wxString
& value
)
407 void wxTextCtrl::Remove(long from
, long to
)
412 void wxTextCtrl::DiscardEdits()
418 void wxTextCtrl::SetMaxLength(unsigned long len
)
422 int wxTextCtrl::PosToPixel( int line
, int pos
)
424 // TODO add support for Tabs
426 if (line
>= (int)m_lines
.GetCount()) return 0;
427 if (pos
< 0) return 0;
429 wxString text
= m_lines
[line
].m_text
;
431 if (text
.IsEmpty()) return 0;
433 if (pos
< (int)text
.Len())
434 text
.Remove( pos
, text
.Len()-pos
);
438 GetTextExtent( text
, &w
, NULL
, NULL
, NULL
);
443 int wxTextCtrl::PixelToPos( int line
, int pixel
)
445 if (pixel
< 2) return 0;
447 if (line
>= (int)m_lines
.GetCount()) return 0;
449 wxString text
= m_lines
[line
].m_text
;
452 int res
= text
.Len();
455 GetTextExtent( text
, &w
, NULL
, NULL
, NULL
);
461 text
.Remove( res
,1 );
467 void wxTextCtrl::SetLanguage( wxSourceLanguage lang
)
473 if (m_lang
== wxSOURCE_LANG_PYTHON
)
475 m_keywords
.Add( "class" );
476 m_keywords
.Add( "__init__" );
477 m_keywords
.Add( "return" );
478 m_keywords
.Add( "def" );
479 m_keywords
.Add( "try" );
480 m_keywords
.Add( "except" );
481 m_keywords
.Add( "if" );
482 m_keywords
.Add( "else" );
483 m_keywords
.Add( "finally" );
484 m_keywords
.Add( "for" );
485 m_keywords
.Add( "if" );
486 m_keywords
.Add( "elif" );
487 m_keywords
.Add( "in" );
488 m_keywords
.Add( "and" );
489 m_keywords
.Add( "del" );
490 m_keywords
.Add( "is" );
491 m_keywords
.Add( "raise" );
492 m_keywords
.Add( "assert" );
493 m_keywords
.Add( "lambda" );
494 m_keywords
.Add( "break" );
495 m_keywords
.Add( "global" );
496 m_keywords
.Add( "not" );
497 m_keywords
.Add( "or" );
498 m_keywords
.Add( "while" );
499 m_keywords
.Add( "continue" );
500 m_keywords
.Add( "exec" );
501 m_keywords
.Add( "pass" );
502 m_keywords
.Add( "print" );
504 if (m_lang
== wxSOURCE_LANG_PERL
)
506 m_keywords
.Add( "main" );
507 m_keywords
.Add( "sub" );
508 m_keywords
.Add( "shift" );
509 m_keywords
.Add( "push" );
510 m_keywords
.Add( "split" );
511 m_keywords
.Add( "join" );
512 m_keywords
.Add( "chop" );
513 m_keywords
.Add( "grep" );
514 m_keywords
.Add( "open" );
515 m_keywords
.Add( "print" );
516 m_keywords
.Add( "sprint" );
517 m_keywords
.Add( "printf" );
518 m_keywords
.Add( "sprintf" );
519 m_keywords
.Add( "my" );
520 m_keywords
.Add( "local" );
521 m_keywords
.Add( "exit" );
522 m_keywords
.Add( "die" );
523 m_keywords
.Add( "return" );
524 m_keywords
.Add( "for" );
525 m_keywords
.Add( "foreach" );
526 m_keywords
.Add( "while" );
527 m_keywords
.Add( "unless" );
528 m_keywords
.Add( "if" );
529 m_keywords
.Add( "next" );
530 m_keywords
.Add( "last" );
531 m_keywords
.Add( "else" );
532 m_keywords
.Add( "elsif" );
533 m_keywords
.Add( "ne" );
534 m_keywords
.Add( "qe" );
537 if (m_lang
== wxSOURCE_LANG_CPP
)
539 m_keywords
.Add( "class" );
540 m_keywords
.Add( "return" );
541 m_keywords
.Add( "if" );
542 m_keywords
.Add( "then" );
543 m_keywords
.Add( "else" );
544 m_keywords
.Add( "struct" );
545 m_keywords
.Add( "enum" );
546 m_keywords
.Add( "while" );
547 m_keywords
.Add( "do" );
548 m_keywords
.Add( "for" );
549 m_keywords
.Add( "continue" );
550 m_keywords
.Add( "break" );
551 m_keywords
.Add( "switch" );
552 m_keywords
.Add( "case" );
553 m_keywords
.Add( "goto" );
554 m_keywords
.Add( "label" );
555 m_keywords
.Add( "inline" );
556 m_keywords
.Add( "operator" );
557 m_keywords
.Add( "virtual" );
558 m_keywords
.Add( "private" );
559 m_keywords
.Add( "public" );
560 m_keywords
.Add( "protected" );
561 m_keywords
.Add( "friend" );
562 m_keywords
.Add( "exception" );
563 m_keywords
.Add( "throw" );
564 m_keywords
.Add( "catch" );
565 m_keywords
.Add( "delete" );
566 m_keywords
.Add( "new" );
567 m_keywords
.Add( "default" );
568 m_keywords
.Add( "overload" );
569 m_keywords
.Add( "using" );
570 m_keywords
.Add( "template" );
571 m_keywords
.Add( "try" );
572 m_keywords
.Add( "typedef" );
573 m_keywords
.Add( "union" );
574 m_keywords
.Add( "volatile" );
575 m_keywords
.Add( "asm" );
580 if (m_lang
== wxSOURCE_LANG_PYTHON
)
582 m_defines
.Add( "from" );
583 m_defines
.Add( "import" );
585 if (m_lang
== wxSOURCE_LANG_PERL
)
587 m_defines
.Add( "use" );
588 m_defines
.Add( "do" );
589 m_defines
.Add( "package" );
590 m_defines
.Add( "defined" );
592 if (m_lang
== wxSOURCE_LANG_CPP
)
594 m_defines
.Add( "#define" );
595 m_defines
.Add( "#if" );
596 m_defines
.Add( "#ifndef" );
597 m_defines
.Add( "#ifdef" );
598 m_defines
.Add( "#else" );
599 m_defines
.Add( "#elif" );
600 m_defines
.Add( "#endif" );
601 m_defines
.Add( "#pragma" );
602 m_defines
.Add( "#include" );
607 if (m_lang
== wxSOURCE_LANG_PYTHON
)
609 m_variables
.Add( "nil" );
610 m_variables
.Add( "None" );
611 m_variables
.Add( "self" );
612 m_variables
.Add( "false" );
613 m_variables
.Add( "true" );
615 if (m_lang
== wxSOURCE_LANG_PERL
)
617 m_variables
.Add( "undef" );
618 m_variables
.Add( "class" );
619 m_variables
.Add( "this" );
620 m_variables
.Add( "IN" );
621 m_variables
.Add( "OUT" );
622 m_variables
.Add( "STDIN" );
623 m_variables
.Add( "STDOUT" );
624 m_variables
.Add( "STDERR" );
626 if (m_lang
== wxSOURCE_LANG_CPP
)
628 m_variables
.Add( "int" );
629 m_variables
.Add( "bool" );
630 m_variables
.Add( "void" );
631 m_variables
.Add( "long" );
632 m_variables
.Add( "short" );
633 m_variables
.Add( "const" );
634 m_variables
.Add( "signed" );
635 m_variables
.Add( "unsigned" );
636 m_variables
.Add( "char" );
637 m_variables
.Add( "size_t" );
638 m_variables
.Add( "wchar_t" );
639 m_variables
.Add( "NULL" );
640 m_variables
.Add( "this" );
641 m_variables
.Add( "TRUE" );
642 m_variables
.Add( "FALSE" );
643 m_variables
.Add( "float" );
644 m_variables
.Add( "double" );
645 m_variables
.Add( "register" );
646 m_variables
.Add( "extern" );
647 m_variables
.Add( "static" );
648 m_variables
.Add( "sizeof" );
652 void wxTextCtrl::WriteText(const wxString
& text2
)
654 if (text2
.IsEmpty()) return;
658 wxString
text( text2
);
661 while ( (pos
= text
.Find('\n')) != -1 )
663 lines
.Add( text
.Left( pos
) );
664 text
.Remove( 0, pos
+1 );
667 int count
= (int)lines
.GetCount();
669 wxString
tmp1( m_lines
[m_cursorY
].m_text
);
670 wxString
tmp2( tmp1
);
671 int len
= (int)tmp1
.Len();
676 for (int i
= 0; i
< m_cursorX
-len
; i
++)
678 m_lines
[m_cursorY
].m_text
.Append( tmp
);
683 tmp1
.Remove( m_cursorX
);
684 tmp2
.Remove( 0, m_cursorX
);
685 tmp1
.Append( lines
[0] );
689 m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE
, m_cursorY
, m_cursorY
, this ) );
692 m_lines
[m_cursorY
].m_text
= tmp1
;
693 RefreshLine( m_cursorY
);
697 m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_PASTE
, m_cursorY
, m_cursorY
+count
-1, this ) );
699 m_lines
[m_cursorY
].m_text
= tmp1
;
701 for (i
= 1; i
< count
; i
++)
702 m_lines
.Insert( new wxSourceLine( lines
[i
] ), m_cursorY
+i
);
703 m_lines
[m_cursorY
+i
-1].m_text
.Append( tmp2
);
705 MyAdjustScrollbars();
706 RefreshDown( m_cursorY
);
710 void wxTextCtrl::AppendText(const wxString
& text2
)
712 if (text2
.IsEmpty()) return;
716 wxString
text( text2
);
719 while ( (pos
= text
.Find('\n')) != -1 )
721 lines
.Add( text
.Left( pos
) );
722 text
.Remove( 0, pos
+1 );
725 int count
= (int)lines
.GetCount();
727 size_t y
= m_lines
.GetCount()-1;
729 wxString
tmp( m_lines
[y
].m_text
);
730 tmp
.Append( lines
[0] );
734 m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE
, y
, y
, this ) );
736 m_lines
[y
].m_text
= tmp
;
741 m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_PASTE
, y
, y
+count
-1, this ) );
743 m_lines
[y
].m_text
= tmp
;
745 for (i
= 1; i
< count
; i
++)
746 m_lines
.Insert( new wxSourceLine( lines
[i
] ), y
+i
);
748 MyAdjustScrollbars();
753 bool wxTextCtrl::SetStyle(long start
, long end
, const wxTextAttr
& style
)
758 long wxTextCtrl::XYToPosition(long x
, long y
) const
762 for (size_t i
= 0; i
< m_lines
.GetCount(); i
++)
766 // Add one for the end-of-line character
767 ret
+= m_lines
[i
].m_text
.Len() + 1;
771 if ((size_t)x
< (m_lines
[i
].m_text
.Len()+1))
774 return (ret
+ m_lines
[i
].m_text
.Len() + 1);
780 bool wxTextCtrl::PositionToXY(long pos
, long *x
, long *y
) const
782 if (m_lines
.GetCount() == 0)
793 for (size_t i
= 0; i
< m_lines
.GetCount(); i
++)
795 //pos -= m_lines[i].m_text.Len();
798 // Add one for the end-of-line character. (In Windows,
799 // there are _two_ positions for each end of line.)
800 if (pos
<= ((int)m_lines
[i
].m_text
.Len()))
807 pos
-= (m_lines
[i
].m_text
.Len() + 1);
812 //xx = m_lines[ m_lines.GetCount()-1 ].m_text.Len();
820 void wxTextCtrl::ShowPosition(long pos
)
824 void wxTextCtrl::Copy()
826 if (!HasSelection()) return;
830 int selStartY
= m_selStartY
;
831 int selEndY
= m_selEndY
;
832 int selStartX
= m_selStartX
;
833 int selEndX
= m_selEndX
;
835 if ((selStartY
> selEndY
) ||
836 ((selStartY
== selEndY
) && (selStartX
> selEndX
)))
846 if (selStartY
== selEndY
)
848 sel
= m_lines
[selStartY
].m_text
;
850 if (selStartX
>= (int)sel
.Len()) return;
851 if (selEndX
> (int)sel
.Len())
854 sel
.Remove( selEndX
, sel
.Len()-selEndX
);
855 sel
.Remove( 0, selStartX
);
859 wxString
tmp( m_lines
[selStartY
].m_text
);
861 if (selStartX
< (int)tmp
.Len())
863 tmp
.Remove( 0, selStartX
);
867 for (int i
= selStartY
+1; i
< selEndY
; i
++)
869 sel
.Append( m_lines
[i
].m_text
);
872 tmp
= m_lines
[selEndY
].m_text
;
873 if (selEndX
> (int)tmp
.Len())
877 tmp
.Remove( selEndX
, tmp
.Len()-selEndX
);
882 if (wxTheClipboard
->Open())
884 wxTheClipboard
->SetData( new wxTextDataObject( sel
) );
885 wxTheClipboard
->Close();
889 void wxTextCtrl::Cut()
896 void wxTextCtrl::Paste()
900 if (!wxTheClipboard
->Open()) return;
902 if (!wxTheClipboard
->IsSupported( wxDF_TEXT
))
904 wxTheClipboard
->Close();
909 wxTextDataObject data
;
911 bool ret
= wxTheClipboard
->GetData( data
);
913 wxTheClipboard
->Close();
919 wxString
text( data
.GetText() );
922 while ( (pos
= text
.Find('\n')) != -1 )
924 lines
.Add( text
.Left( pos
) );
925 text
.Remove( 0, pos
+1 );
928 int count
= (int)lines
.GetCount();
930 wxString
tmp1( m_lines
[m_cursorY
].m_text
);
931 wxString
tmp2( tmp1
);
932 int len
= (int)tmp1
.Len();
937 for (int i
= 0; i
< m_cursorX
-len
; i
++)
939 m_lines
[m_cursorY
].m_text
.Append( tmp
);
944 tmp1
.Remove( m_cursorX
);
945 tmp2
.Remove( 0, m_cursorX
);
946 tmp1
.Append( lines
[0] );
950 m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE
, m_cursorY
, m_cursorY
, this ) );
953 m_lines
[m_cursorY
].m_text
= tmp1
;
954 RefreshLine( m_cursorY
);
958 m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_PASTE
, m_cursorY
, m_cursorY
+count
-1, this ) );
960 m_lines
[m_cursorY
].m_text
= tmp1
;
962 for (i
= 1; i
< count
; i
++)
963 m_lines
.Insert( new wxSourceLine( lines
[i
] ), m_cursorY
+i
);
964 m_lines
[m_cursorY
+i
-1].m_text
.Append( tmp2
);
966 MyAdjustScrollbars();
967 RefreshDown( m_cursorY
);
971 void wxTextCtrl::Undo()
973 if (m_undos
.GetCount() == 0) return;
975 wxNode
*node
= m_undos
.Nth( m_undos
.GetCount()-1 );
976 wxSourceUndoStep
*undo
= (wxSourceUndoStep
*) node
->Data();
985 void wxTextCtrl::SetInsertionPoint(long pos
)
989 PositionToXY(pos
, & x
, & y
);
992 // TODO: scroll to this position if necessary
996 void wxTextCtrl::SetInsertionPointEnd()
998 SetInsertionPoint(GetLastPosition());
1001 long wxTextCtrl::GetInsertionPoint() const
1003 return XYToPosition( m_cursorX
, m_cursorY
);
1006 long wxTextCtrl::GetLastPosition() const
1008 size_t lineCount
= m_lines
.GetCount() - 1;
1009 // It's the length of the line, not the length - 1,
1010 // because there's a position after the last character.
1011 return XYToPosition( m_lines
[lineCount
].m_text
.Len(), lineCount
);
1014 void wxTextCtrl::SetSelection(long from
, long to
)
1018 void wxTextCtrl::SetEditable(bool editable
)
1020 m_editable
= editable
;
1023 bool wxTextCtrl::Enable( bool enable
)
1028 bool wxTextCtrl::SetFont(const wxFont
& font
)
1030 wxTextCtrlBase::SetFont( font
);
1032 m_sourceFont
= font
;
1034 wxClientDC
dc(this);
1035 dc
.SetFont( m_sourceFont
);
1036 m_lineHeight
= dc
.GetCharHeight();
1037 m_charWidth
= dc
.GetCharWidth();
1039 // TODO: recalc longest lines
1041 MyAdjustScrollbars();
1046 bool wxTextCtrl::SetForegroundColour(const wxColour
& colour
)
1048 return wxWindow::SetForegroundColour( colour
);
1051 bool wxTextCtrl::SetBackgroundColour(const wxColour
& colour
)
1053 return wxWindow::SetBackgroundColour( colour
);
1056 //-----------------------------------------------------------------------------
1057 // private code and handlers
1058 //-----------------------------------------------------------------------------
1060 void wxTextCtrl::SearchForBrackets()
1062 int oldBracketY
= m_bracketY
;
1063 int oldBracketX
= m_bracketX
;
1065 if (m_cursorY
< 0 || m_cursorY
>= (int)m_lines
.GetCount()) return;
1067 wxString current
= m_lines
[m_cursorY
].m_text
;
1069 // reverse search first
1074 bracket
= current
[m_cursorX
-1];
1076 if (bracket
== ')' || bracket
== ']' || bracket
== '}')
1078 char antibracket
= '(';
1079 if (bracket
== ']') antibracket
= '[';
1080 if (bracket
== '}') antibracket
= '{';
1084 int endY
= m_cursorY
-60;
1085 if (endY
< 0) endY
= 0;
1086 for (int y
= m_cursorY
; y
>= endY
; y
--)
1088 current
= m_lines
[y
].m_text
;
1090 current
.erase(m_cursorX
-1,current
.Len()-m_cursorX
+1);
1092 for (int n
= current
.Len()-1; n
>= 0; n
--)
1095 if (current
[n
] == '\'')
1097 for (int m
= n
-1; m
>= 0; m
--)
1099 if (current
[m
] == '\'')
1101 if (m
== 0 || current
[m
-1] != '\\')
1110 if (current
[n
] == '\"')
1112 for (int m
= n
-1; m
>= 0; m
--)
1114 if (current
[m
] == '\"')
1116 if (m
== 0 || current
[m
-1] != '\\')
1124 if (current
[n
] == antibracket
)
1131 if (oldBracketY
!= m_bracketY
&& oldBracketY
!= -1)
1132 RefreshLine( oldBracketY
);
1133 if (m_bracketY
!= oldBracketY
|| m_bracketX
!= oldBracketX
)
1134 RefreshLine( m_bracketY
);
1138 else if (current
[n
] == bracket
)
1149 if ((int)current
.Len() > m_cursorX
)
1150 bracket
= current
[m_cursorX
];
1151 if (bracket
== '(' || bracket
== '[' || bracket
== '{')
1153 char antibracket
= ')';
1154 if (bracket
== '[') antibracket
= ']';
1155 if (bracket
== '{') antibracket
= '}';
1159 int endY
= m_cursorY
+60;
1160 if (endY
> (int)(m_lines
.GetCount()-1)) endY
= m_lines
.GetCount()-1;
1161 for (int y
= m_cursorY
; y
<= endY
; y
++)
1163 current
= m_lines
[y
].m_text
;
1166 start
= m_cursorX
+1;
1168 for (int n
= start
; n
< (int)current
.Len(); n
++)
1171 if (current
[n
] == '\'')
1173 for (int m
= n
+1; m
< (int)current
.Len(); m
++)
1175 if (current
[m
] == '\'')
1177 if (m
== 0 || (current
[m
-1] != '\\') || (m
>= 2 && current
[m
-2] == '\\'))
1186 if (current
[n
] == '\"')
1188 for (int m
= n
+1; m
< (int)current
.Len(); m
++)
1190 if (current
[m
] == '\"')
1192 if (m
== 0 || (current
[m
-1] != '\\') || (m
>= 2 && current
[m
-2] == '\\'))
1200 if (current
[n
] == antibracket
)
1207 if (oldBracketY
!= m_bracketY
&& oldBracketY
!= -1)
1208 RefreshLine( oldBracketY
);
1209 if (m_bracketY
!= oldBracketY
|| m_bracketX
!= oldBracketX
)
1210 RefreshLine( m_bracketY
);
1214 else if (current
[n
] == bracket
)
1222 if (oldBracketY
!= -1)
1225 RefreshLine( oldBracketY
);
1229 void wxTextCtrl::Delete()
1231 if (!HasSelection()) return;
1235 int selStartY
= m_selStartY
;
1236 int selEndY
= m_selEndY
;
1237 int selStartX
= m_selStartX
;
1238 int selEndX
= m_selEndX
;
1240 if ((selStartY
> selEndY
) ||
1241 ((selStartY
== selEndY
) && (selStartX
> selEndX
)))
1243 int tmp
= selStartX
;
1244 selStartX
= selEndX
;
1247 selStartY
= selEndY
;
1251 int len
= (int)m_lines
[selStartY
].m_text
.Len();
1253 if (selStartY
== selEndY
)
1255 m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE
, selStartY
, selStartY
, this ) );
1257 wxString
tmp( m_lines
[selStartY
].m_text
);
1258 if (selStartX
< len
)
1262 tmp
.Remove( selStartX
, selEndX
-selStartX
);
1263 m_lines
[selStartY
].m_text
= tmp
;
1266 m_cursorX
= selStartX
;
1267 RefreshLine( selStartY
);
1271 m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_DELETE
, selStartY
, selEndY
, this ) );
1273 if (selStartX
< len
)
1274 m_lines
[selStartY
].m_text
.Remove( selStartX
);
1276 for (int i
= 0; i
< selEndY
-selStartY
-1; i
++)
1277 m_lines
.RemoveAt( selStartY
+1 );
1279 if (selEndX
< (int)m_lines
[selStartY
+1].m_text
.Len())
1280 m_lines
[selStartY
+1].m_text
.Remove( 0, selEndX
);
1282 m_lines
[selStartY
+1].m_text
.Remove( 0 );
1284 m_lines
[selStartY
].m_text
.Append( m_lines
[selStartY
+1].m_text
);
1285 m_lines
.RemoveAt( selStartY
+1 );
1288 MoveCursor( selStartX
, selStartY
);
1289 MyAdjustScrollbars();
1291 RefreshDown( selStartY
);
1295 void wxTextCtrl::DeleteLine()
1297 if (HasSelection()) return;
1299 if (m_cursorY
< 0 || m_cursorY
>= (int)m_lines
.GetCount()-1) return; // TODO
1301 m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_DELETE
, m_cursorY
, m_cursorY
+1, this ) );
1303 m_lines
.RemoveAt( m_cursorY
);
1305 if (m_cursorY
>= (int)m_lines
.GetCount()) m_cursorY
--;
1307 MyAdjustScrollbars();
1308 RefreshDown( m_cursorY
);
1311 void wxTextCtrl::DoChar( char c
)
1315 m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE
, m_cursorY
, m_cursorY
, this ) );
1317 wxString
tmp( m_lines
[m_cursorY
].m_text
);
1319 if (m_cursorX
>= (int)tmp
.Len())
1321 int len
= tmp
.Len();
1322 for (int i
= 0; i
< m_cursorX
- len
; i
++)
1329 tmp
.SetChar( m_cursorX
, c
);
1331 tmp
.insert( m_cursorX
, 1, c
);
1334 m_lines
[m_cursorY
].m_text
= tmp
;
1336 // if (tmp.Len() > m_longestLine)
1338 // m_longestLine = tmp.Len();
1339 // MyAdjustScrollbars();
1343 GetTextExtent( tmp
, &ww
, NULL
, NULL
, NULL
);
1345 if (ww
> m_longestLine
)
1348 MyAdjustScrollbars();
1353 int y
= m_cursorY
*m_lineHeight
;
1354 // int x = (m_cursorX-1)*m_charWidth;
1355 int x
= PosToPixel( m_cursorY
, m_cursorX
-1 );
1356 CalcScrolledPosition( x
, y
, &x
, &y
);
1357 wxRect
rect( x
+2, y
+2, 10000, m_lineHeight
);
1358 Refresh( TRUE
, &rect
);
1359 // refresh whole line for syntax colour highlighting
1361 Refresh( FALSE
, &rect
);
1365 GetClientSize( &size_x
, &size_y
);
1366 size_x
/= m_charWidth
;
1370 GetViewStart( &view_x
, &view_y
);
1372 //int xx = m_cursorX;
1373 int xx
= PosToPixel( m_cursorY
, m_cursorX
) / m_charWidth
;
1377 else if (xx
> view_x
+size_x
-1)
1378 Scroll( xx
-size_x
+1, -1 );
1381 void wxTextCtrl::DoBack()
1387 if (m_cursorY
== 0) return;
1389 m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_BACK
, m_cursorY
-1, m_cursorY
, this ) );
1391 wxString
tmp1( m_lines
[m_cursorY
-1].m_text
);
1393 wxString
tmp2( m_lines
[m_cursorY
].m_text
);
1395 m_cursorX
= tmp1
.Len();
1397 tmp1
.Append( tmp2
);
1398 m_lines
[m_cursorY
].m_text
= tmp1
;
1399 m_lines
.RemoveAt( m_cursorY
+1 );
1401 MyAdjustScrollbars();
1402 RefreshDown( m_cursorY
-1 );
1406 m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE
, m_cursorY
, m_cursorY
, this ) );
1408 if (m_cursorX
<= (int)m_lines
[m_cursorY
].m_text
.Len())
1409 m_lines
[m_cursorY
].m_text
.Remove( m_cursorX
-1, 1 );
1412 int y
= m_cursorY
*m_lineHeight
;
1413 // int x = m_cursorX*m_charWidth;
1414 int x
= PosToPixel( m_cursorY
, m_cursorX
);
1415 CalcScrolledPosition( x
, y
, &x
, &y
);
1416 wxRect
rect( x
+2, y
+2, 10000, m_lineHeight
);
1417 Refresh( TRUE
, &rect
);
1418 // refresh whole line for syntax colour highlighting
1420 Refresh( FALSE
, &rect
);
1424 void wxTextCtrl::DoDelete()
1428 wxString
tmp( m_lines
[m_cursorY
].m_text
);
1430 int len
= (int)tmp
.Len();
1431 if (m_cursorX
>= len
)
1433 if (m_cursorY
== (int)m_lines
.GetCount()-1) return;
1435 m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_DELETE
, m_cursorY
, m_cursorY
+1, this ) );
1437 for (int i
= 0; i
< (m_cursorX
-len
); i
++)
1440 tmp
+= m_lines
[m_cursorY
+1].m_text
;
1442 m_lines
[m_cursorY
] = tmp
;
1443 m_lines
.RemoveAt( m_cursorY
+1 );
1445 MyAdjustScrollbars();
1446 RefreshDown( m_cursorY
);
1450 m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE
, m_cursorY
, m_cursorY
, this ) );
1452 tmp
.Remove( m_cursorX
, 1 );
1453 m_lines
[m_cursorY
].m_text
= tmp
;
1455 int y
= m_cursorY
*m_lineHeight
;
1456 // int x = m_cursorX*m_charWidth;
1457 int x
= PosToPixel( m_cursorY
, m_cursorX
);
1458 CalcScrolledPosition( x
, y
, &x
, &y
);
1459 wxRect
rect( x
+2, y
+2, 10000, m_lineHeight
);
1460 Refresh( TRUE
, &rect
);
1461 // refresh whole line for syntax colour highlighting
1463 Refresh( FALSE
, &rect
);
1467 void wxTextCtrl::DoReturn()
1471 m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_ENTER
, m_cursorY
, m_cursorY
, this ) );
1473 wxString
tmp( m_lines
[m_cursorY
].m_text
);
1474 size_t indent
= tmp
.find_first_not_of( ' ' );
1475 if (indent
== wxSTRING_MAXLEN
) indent
= 0;
1477 if (m_cursorX
>= (int)tmp
.Len())
1479 int cursorX
= indent
;
1480 int cursorY
= m_cursorY
+ 1;
1483 for (size_t i
= 0; i
< indent
; i
++) new_tmp
.Append( ' ' );
1484 m_lines
.Insert( new wxSourceLine( new_tmp
), cursorY
);
1486 MyAdjustScrollbars();
1487 MoveCursor( cursorX
, cursorY
);
1488 RefreshDown( m_cursorY
);
1492 wxString
tmp1( tmp
);
1493 tmp1
.Remove( m_cursorX
, tmp
.Len()-m_cursorX
);
1494 m_lines
[m_cursorY
].m_text
= tmp1
;
1496 wxString
tmp2( tmp
);
1497 tmp2
.Remove( 0, m_cursorX
);
1499 int cursorX
= indent
;
1500 int cursorY
= m_cursorY
+ 1;
1503 for (size_t i
= 0; i
< indent
; i
++) new_tmp
.Append( ' ' );
1504 new_tmp
.Append( tmp2
);
1505 m_lines
.Insert( new wxSourceLine( new_tmp
), cursorY
);
1507 MyAdjustScrollbars();
1508 MoveCursor( cursorX
, cursorY
);
1509 RefreshDown( m_cursorY
-1 );
1513 void wxTextCtrl::DoDClick()
1515 wxString
line( m_lines
[ m_cursorY
].m_text
);
1516 if (m_cursorX
>= (int)line
.Len()) return;
1519 if (((ch
>= 'a') && (ch
<= 'z')) ||
1520 ((ch
>= 'A') && (ch
<= 'Z')) ||
1521 ((ch
>= '0') && (ch
<= '9')) ||
1524 m_selStartY
= m_cursorY
;
1525 m_selEndY
= m_cursorY
;
1529 while (((ch
>= 'a') && (ch
<= 'z')) ||
1530 ((ch
>= 'A') && (ch
<= 'Z')) ||
1531 ((ch
>= '0') && (ch
<= '9')) ||
1542 if (p
< (int)line
.Len())
1545 while (((ch
>= 'a') && (ch
<= 'z')) ||
1546 ((ch
>= 'A') && (ch
<= 'Z')) ||
1547 ((ch
>= '0') && (ch
<= '9')) ||
1550 if (p
>= (int)line
.Len()) break;
1556 RefreshLine( m_cursorY
);
1560 wxString
wxTextCtrl::GetNextToken( wxString
&line
, size_t &pos
)
1563 size_t len
= line
.Len();
1564 for (size_t p
= pos
; p
< len
; p
++)
1566 if ((m_lang
== wxSOURCE_LANG_PYTHON
) || (m_lang
== wxSOURCE_LANG_PERL
))
1570 for (size_t q
= p
; q
< len
; q
++)
1571 ret
.Append( line
[q
] );
1578 if ((line
[p
] == '/') && (p
+1 < len
) && (line
[p
+1] == '/'))
1580 for (size_t q
= p
; q
< len
; q
++)
1581 ret
.Append( line
[q
] );
1589 ret
.Append( line
[p
] );
1590 for (size_t q
= p
+1; q
< len
; q
++)
1592 ret
.Append( line
[q
] );
1593 if ((line
[q
] == '"') && ((line
[q
-1] != '\\') || (q
>= 2 && line
[q
-2] == '\\')))
1600 if (line
[p
] == '\'')
1602 ret
.Append( line
[p
] );
1603 for (size_t q
= p
+1; q
< len
; q
++)
1605 ret
.Append( line
[q
] );
1606 if ((line
[q
] == '\'') && ((line
[q
-1] != '\\') || (q
>= 2 && line
[q
-2] == '\\')))
1613 if (((line
[p
] >= 'a') && (line
[p
] <= 'z')) ||
1614 ((line
[p
] >= 'A') && (line
[p
] <= 'Z')) ||
1618 ret
.Append( line
[p
] );
1619 for (size_t q
= p
+1; q
< len
; q
++)
1621 if (((line
[q
] >= 'a') && (line
[q
] <= 'z')) ||
1622 ((line
[q
] >= 'A') && (line
[q
] <= 'Z')) ||
1623 ((line
[q
] >= '0') && (line
[q
] <= '9')) ||
1626 ret
.Append( line
[q
] );
1643 void wxTextCtrl::OnEraseBackground( wxEraseEvent
&event
)
1648 void wxTextCtrl::DrawLinePart( wxDC
&dc
, int x
, int y
, const wxString
&toDraw
, const wxString
&origin
, const wxColour
&colour
)
1651 size_t len
= origin
.Len();
1652 dc
.SetTextForeground( colour
);
1655 while (toDraw
[pos
] == wxT(' '))
1658 if (pos
== len
) return;
1664 current
+= toDraw
[pos
];
1666 while ( (toDraw
[pos
] == origin
[pos
]) && (pos
< len
))
1668 current
+= toDraw
[pos
];
1673 wxString tmp
= origin
.Left( start
);
1674 GetTextExtent( tmp
, &xx
, NULL
, NULL
, NULL
);
1677 dc
.DrawText( current
, xx
, yy
);
1681 void wxTextCtrl::DrawLine( wxDC
&dc
, int x
, int y
, const wxString
&line2
, int lineNum
)
1683 int selStartY
= m_selStartY
;
1684 int selEndY
= m_selEndY
;
1685 int selStartX
= m_selStartX
;
1686 int selEndX
= m_selEndX
;
1688 if ((selStartY
> selEndY
) ||
1689 ((selStartY
== selEndY
) && (selStartX
> selEndX
)))
1691 int tmp
= selStartX
;
1692 selStartX
= selEndX
;
1695 selStartY
= selEndY
;
1699 wxString
line( line2
);
1700 if (HasFlag(wxTE_PASSWORD
))
1702 size_t len
= line
.Len();
1703 line
= wxString( wxT('*'), len
);
1706 wxString
keyword( ' ', line
.Len() );
1707 wxString
define( ' ', line
.Len() );
1708 wxString
variable( ' ', line
.Len() );
1709 wxString
comment( ' ', line
.Len() );
1710 wxString
my_string( ' ', line
.Len() );
1711 wxString
selection( ' ', line
.Len() );
1713 if (m_lang
!= wxSOURCE_LANG_NONE
)
1715 if (lineNum
== m_bracketY
)
1717 wxString
red( ' ', line
.Len() );
1718 if (m_bracketX
< (int)line
.Len())
1720 red
.SetChar( m_bracketX
, line
[m_bracketX
] );
1721 line
.SetChar( m_bracketX
, ' ' );
1722 dc
.SetTextForeground( *wxRED
);
1723 dc
.DrawText( red
, x
, y
);
1724 dc
.SetTextForeground( *wxBLACK
);
1729 wxString
token( GetNextToken( line
, pos
) );
1730 while (!token
.IsNull())
1732 if (m_keywords
.Index( token
) != wxNOT_FOUND
)
1734 size_t end_pos
= pos
+ token
.Len();
1735 for (size_t i
= pos
; i
< end_pos
; i
++)
1737 keyword
[i
] = line
[i
];
1741 if (m_defines
.Index( token
) != wxNOT_FOUND
)
1743 size_t end_pos
= pos
+ token
.Len();
1744 for (size_t i
= pos
; i
< end_pos
; i
++)
1746 define
[i
] = line
[i
];
1750 if ((m_variables
.Index( token
) != wxNOT_FOUND
) ||
1751 ((token
.Len() > 2) && (token
[0] == 'w') && (token
[1] == 'x')))
1753 size_t end_pos
= pos
+ token
.Len();
1754 for (size_t i
= pos
; i
< end_pos
; i
++)
1756 variable
[i
] = line
[i
];
1760 if ((token
.Len() >= 2) && (token
[0] == '/') && (token
[1] == '/') && (m_lang
== wxSOURCE_LANG_CPP
))
1762 size_t end_pos
= pos
+ token
.Len();
1763 for (size_t i
= pos
; i
< end_pos
; i
++)
1765 comment
[i
] = line
[i
];
1769 if ((token
[0] == '#') &&
1770 ((m_lang
== wxSOURCE_LANG_PYTHON
) || (m_lang
== wxSOURCE_LANG_PERL
)))
1772 size_t end_pos
= pos
+ token
.Len();
1773 for (size_t i
= pos
; i
< end_pos
; i
++)
1775 comment
[i
] = line
[i
];
1779 if ((token
[0] == '"') || (token
[0] == '\''))
1781 size_t end_pos
= pos
+ token
.Len();
1782 for (size_t i
= pos
; i
< end_pos
; i
++)
1784 my_string
[i
] = line
[i
];
1789 token
= GetNextToken( line
, pos
);
1793 if ((lineNum
< selStartY
) || (lineNum
> selEndY
))
1795 DrawLinePart( dc
, x
, y
, line
, line2
, *wxBLACK
);
1796 DrawLinePart( dc
, x
, y
, selection
, line2
, *wxWHITE
);
1797 DrawLinePart( dc
, x
, y
, keyword
, line2
, m_keywordColour
);
1798 DrawLinePart( dc
, x
, y
, define
, line2
, m_defineColour
);
1799 DrawLinePart( dc
, x
, y
, variable
, line2
, m_variableColour
);
1800 DrawLinePart( dc
, x
, y
, comment
, line2
, m_commentColour
);
1801 DrawLinePart( dc
, x
, y
, my_string
, line2
, m_stringColour
);
1805 if (selStartY
== selEndY
)
1807 // int xx = selStartX*m_charWidth;
1808 int xx
= PosToPixel( lineNum
, selStartX
);
1809 // int ww = (selEndX-selStartX)*m_charWidth;
1810 int ww
= PosToPixel( lineNum
, selEndX
) - xx
;
1811 dc
.DrawRectangle( xx
+2, lineNum
*m_lineHeight
+2, ww
, m_lineHeight
);
1813 for (size_t i
= (size_t)selStartX
; i
< (size_t)selEndX
; i
++)
1815 selection
[i
] = line
[i
];
1819 if ((lineNum
> selStartY
) && (lineNum
< selEndY
))
1821 dc
.DrawRectangle( 0+2, lineNum
*m_lineHeight
+2, 10000, m_lineHeight
);
1823 for (size_t i
= 0; i
< line
.Len(); i
++)
1825 selection
[i
] = line
[i
];
1829 if (lineNum
== selStartY
)
1831 // int xx = selStartX*m_charWidth;
1832 int xx
= PosToPixel( lineNum
, selStartX
);
1833 dc
.DrawRectangle( xx
+2, lineNum
*m_lineHeight
+2, 10000, m_lineHeight
);
1835 for (size_t i
= (size_t)selStartX
; i
< line
.Len(); i
++)
1837 selection
[i
] = line
[i
];
1841 if (lineNum
== selEndY
)
1843 // int ww = selEndX*m_charWidth;
1844 int ww
= PosToPixel( lineNum
, selEndX
);
1845 dc
.DrawRectangle( 0+2, lineNum
*m_lineHeight
+2, ww
, m_lineHeight
);
1847 for (size_t i
= 0; i
< (size_t)selEndX
; i
++)
1849 selection
[i
] = line
[i
];
1854 DrawLinePart( dc
, x
, y
, line
, line2
, *wxBLACK
);
1855 DrawLinePart( dc
, x
, y
, selection
, line2
, *wxWHITE
);
1856 DrawLinePart( dc
, x
, y
, keyword
, line2
, m_keywordColour
);
1857 DrawLinePart( dc
, x
, y
, define
, line2
, m_defineColour
);
1858 DrawLinePart( dc
, x
, y
, variable
, line2
, m_variableColour
);
1859 DrawLinePart( dc
, x
, y
, comment
, line2
, m_commentColour
);
1860 DrawLinePart( dc
, x
, y
, my_string
, line2
, m_stringColour
);
1863 void wxTextCtrl::OnPaint( wxPaintEvent
&event
)
1867 if (m_lines
.GetCount() == 0) return;
1871 dc
.SetFont( m_sourceFont
);
1874 GetViewStart( NULL
, &scroll_y
);
1876 // We have a inner border of two pixels
1877 // around the text, so scroll units do
1878 // not correspond to lines.
1879 if (scroll_y
> 0) scroll_y
--;
1883 GetClientSize( &size_x
, &size_y
);
1885 dc
.SetPen( *wxTRANSPARENT_PEN
);
1886 dc
.SetBrush( wxBrush( wxTHEME_COLOUR(HIGHLIGHT
), wxSOLID
) );
1887 int upper
= wxMin( (int)m_lines
.GetCount(), scroll_y
+(size_y
/m_lineHeight
)+2 );
1888 for (int i
= scroll_y
; i
< upper
; i
++)
1891 int y
= i
*m_lineHeight
+2;
1893 int h
= m_lineHeight
;
1894 CalcScrolledPosition( x
,y
,&x
,&y
);
1895 if (IsExposed(x
,y
,w
,h
))
1896 DrawLine( dc
, 0+2, i
*m_lineHeight
+2, m_lines
[i
].m_text
, i
);
1899 if (m_editable
&& (FindFocus() == this))
1901 ///dc.SetBrush( *wxRED_BRUSH );
1902 dc
.SetBrush( *wxBLACK_BRUSH
);
1903 // int xx = m_cursorX*m_charWidth;
1904 int xx
= PosToPixel( m_cursorY
, m_cursorX
);
1905 dc
.DrawRectangle( xx
+2, m_cursorY
*m_lineHeight
+2, 2, m_lineHeight
);
1909 void wxTextCtrl::OnMouse( wxMouseEvent
&event
)
1911 if (m_lines
.GetCount() == 0) return;
1914 #if 0 // there is no middle button on iPAQs
1915 if (event
.MiddleDown())
1922 if (event
.LeftDClick())
1928 if (event
.LeftDown())
1936 m_capturing
= FALSE
;
1940 if (event
.LeftDown() ||
1941 (event
.LeftIsDown() && m_capturing
))
1943 int x
= event
.GetX();
1944 int y
= event
.GetY();
1945 CalcUnscrolledPosition( x
, y
, &x
, &y
);
1947 // x /= m_charWidth;
1948 x
= PixelToPos( y
, x
);
1950 wxMin( 1000, wxMax( 0, x
) ),
1951 wxMin( (int)m_lines
.GetCount()-1, wxMax( 0, y
) ),
1952 event
.ShiftDown() || !event
.LeftDown() );
1956 void wxTextCtrl::OnChar( wxKeyEvent
&event
)
1958 if (m_lines
.GetCount() == 0) return;
1960 if (!m_editable
) return;
1964 GetClientSize( &size_x
, &size_y
);
1965 size_x
/= m_charWidth
;
1966 size_y
/= m_lineHeight
;
1969 if (event
.ShiftDown())
1971 switch (event
.GetKeyCode())
1973 case '4': event
.m_keyCode
= WXK_LEFT
; break;
1974 case '8': event
.m_keyCode
= WXK_UP
; break;
1975 case '6': event
.m_keyCode
= WXK_RIGHT
; break;
1976 case '2': event
.m_keyCode
= WXK_DOWN
; break;
1977 case '9': event
.m_keyCode
= WXK_PRIOR
; break;
1978 case '3': event
.m_keyCode
= WXK_NEXT
; break;
1979 case '7': event
.m_keyCode
= WXK_HOME
; break;
1980 case '1': event
.m_keyCode
= WXK_END
; break;
1981 case '0': event
.m_keyCode
= WXK_INSERT
; break;
1985 switch (event
.GetKeyCode())
1989 if (m_ignoreInput
) return;
1991 MoveCursor( m_cursorX
, m_cursorY
-1, event
.ShiftDown() );
1992 m_ignoreInput
= TRUE
;
1997 if (m_ignoreInput
) return;
1998 if (m_cursorY
< (int)(m_lines
.GetCount()-1))
1999 MoveCursor( m_cursorX
, m_cursorY
+1, event
.ShiftDown() );
2000 m_ignoreInput
= TRUE
;
2005 if (m_ignoreInput
) return;
2008 MoveCursor( m_cursorX
-1, m_cursorY
, event
.ShiftDown() );
2013 MoveCursor( m_lines
[m_cursorY
-1].m_text
.Len(), m_cursorY
-1, event
.ShiftDown() );
2015 m_ignoreInput
= TRUE
;
2020 if (m_ignoreInput
) return;
2021 if (m_cursorX
< 1000)
2022 MoveCursor( m_cursorX
+1, m_cursorY
, event
.ShiftDown() );
2023 m_ignoreInput
= TRUE
;
2028 if (event
.ControlDown())
2029 MoveCursor( 0, 0, event
.ShiftDown() );
2031 MoveCursor( 0, m_cursorY
, event
.ShiftDown() );
2036 if (event
.ControlDown())
2037 MoveCursor( 0, m_lines
.GetCount()-1, event
.ShiftDown() );
2039 MoveCursor( m_lines
[m_cursorY
].m_text
.Len(), m_cursorY
, event
.ShiftDown() );
2044 if (m_ignoreInput
) return;
2045 MoveCursor( m_cursorX
, wxMin( (int)(m_lines
.GetCount()-1), m_cursorY
+size_y
), event
.ShiftDown() );
2046 m_ignoreInput
= TRUE
;
2051 if (m_ignoreInput
) return;
2052 MoveCursor( m_cursorX
, wxMax( 0, m_cursorY
-size_y
), event
.ShiftDown() );
2053 m_ignoreInput
= TRUE
;
2058 if (event
.ShiftDown())
2060 else if (event
.ControlDown())
2063 m_overwrite
= !m_overwrite
;
2068 if (m_windowStyle
& wxPROCESS_ENTER
)
2070 wxCommandEvent
event(wxEVT_COMMAND_TEXT_ENTER
, m_windowId
);
2071 event
.SetEventObject(this);
2072 event
.SetString(GetValue());
2073 if (GetEventHandler()->ProcessEvent(event
)) return;
2091 bool save_overwrite
= m_overwrite
;
2092 m_overwrite
= FALSE
;
2093 int i
= 4-(m_cursorX
% 4);
2095 for (int c
= 0; c
< i
; c
++)
2097 m_overwrite
= save_overwrite
;
2118 if ( (event
.KeyCode() >= 'a') &&
2119 (event
.KeyCode() <= 'z') &&
2127 if ( (event
.KeyCode() >= 32) &&
2128 (event
.KeyCode() <= 255) &&
2129 !(event
.ControlDown() && !event
.AltDown()) ) // filters out Ctrl-X but leaves Alt-Gr
2133 DoChar( (char) event
.KeyCode() );
2142 void wxTextCtrl::OnIdle( wxIdleEvent
&event
)
2144 m_ignoreInput
= FALSE
;
2146 if (m_lang
!= wxSOURCE_LANG_NONE
)
2147 SearchForBrackets();
2152 void wxTextCtrl::Indent()
2154 int startY
= m_cursorY
;
2155 int endY
= m_cursorY
;
2158 startY
= m_selStartY
;
2168 m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE
, startY
, endY
, this ) );
2170 for (int i
= startY
; i
<= endY
; i
++)
2172 m_lines
[i
].m_text
.insert( 0u, " " );
2177 void wxTextCtrl::Unindent()
2179 int startY
= m_cursorY
;
2180 int endY
= m_cursorY
;
2183 startY
= m_selStartY
;
2193 m_undos
.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE
, startY
, endY
, this ) );
2195 for (int i
= startY
; i
<= endY
; i
++)
2197 for (int n
= 0; n
< 4; n
++)
2199 if (m_lines
[i
].m_text
[0u] == ' ')
2200 m_lines
[i
].m_text
.erase(0u,1u);
2205 bool wxTextCtrl::HasSelection()
2207 return ((m_selStartY
!= m_selEndY
) || (m_selStartX
!= m_selEndX
));
2210 void wxTextCtrl::ClearSelection()
2218 void wxTextCtrl::RefreshLine( int n
)
2220 int y
= n
*m_lineHeight
;
2222 CalcScrolledPosition( x
, y
, &x
, &y
);
2223 wxRect
rect( 0+2, y
+2, 10000, m_lineHeight
);
2224 Refresh( TRUE
, &rect
);
2227 void wxTextCtrl::RefreshDown( int n
)
2231 GetClientSize( &size_x
, &size_y
);
2235 GetViewStart( &view_x
, &view_y
);
2243 int y
= n
*m_lineHeight
;
2245 CalcScrolledPosition( x
, y
, &x
, &y
);
2247 wxRect
rect( 0+2, y
+2, 10000, size_y
);
2248 Refresh( TRUE
, &rect
);
2252 void wxTextCtrl::MoveCursor( int new_x
, int new_y
, bool shift
, bool centre
)
2254 if (!m_editable
) return;
2256 // if (IsSingleLine() || (m_lang == wxSOURCE_LANG_NONE))
2258 if (new_x
> (int) (m_lines
[new_y
].m_text
.Len()))
2259 new_x
= m_lines
[new_y
].m_text
.Len();
2262 if ((new_x
== m_cursorX
) && (new_y
== m_cursorY
)) return;
2264 bool no_cursor_refresh
= FALSE
;
2265 bool has_selection
= HasSelection();
2270 bool erase_background
= TRUE
;
2274 m_selStartX
= m_cursorX
;
2275 m_selStartY
= m_cursorY
;
2279 if (new_y
> m_selStartY
)
2281 y
= m_selStartY
*m_lineHeight
;
2282 h
= (new_y
-m_selStartY
+1)*m_lineHeight
;
2284 else if (new_y
== m_selStartY
)
2286 x
= PosToPixel( new_y
, m_selStartX
);
2287 w
= PosToPixel( new_y
, new_x
) - x
;
2291 w
= -w
+ 2; // +2 for the cursor
2293 y
= m_selStartY
*m_lineHeight
;
2298 y
= new_y
*m_lineHeight
;
2299 h
= (-new_y
+m_selStartY
+1)*m_lineHeight
;
2302 no_cursor_refresh
= TRUE
;
2308 if (new_y
== m_selEndY
)
2310 y
= new_y
*m_lineHeight
;
2312 if (m_selEndX
> new_x
)
2314 // x = new_x*m_charWidth;
2315 x
= PosToPixel( new_y
, new_x
);
2316 // w = (m_selEndX-new_x)*m_charWidth;
2317 w
= PosToPixel( new_y
, m_selEndX
) - x
;
2321 // x = m_selEndX*m_charWidth;
2322 x
= PosToPixel( new_y
, m_selEndX
);
2323 // w = (-m_selEndX+new_x)*m_charWidth;
2324 w
= PosToPixel( new_y
, new_x
) - x
;
2331 if (new_y
> m_selEndY
)
2333 y
= m_selEndY
*m_lineHeight
;
2334 h
= (new_y
-m_selEndY
+1) * m_lineHeight
;
2336 erase_background
= ((m_selEndY
< m_selStartY
) ||
2337 ((m_selEndY
== m_selStartY
) && (m_selEndX
< m_selStartX
)));
2341 y
= new_y
*m_lineHeight
;
2342 h
= (-new_y
+m_selEndY
+1) * m_lineHeight
;
2344 erase_background
= ((m_selEndY
> m_selStartY
) ||
2345 ((m_selEndY
== m_selStartY
) && (m_selEndX
> m_selStartX
)));
2347 no_cursor_refresh
= TRUE
;
2356 CalcScrolledPosition( x
, y
, &x
, &y
);
2357 wxRect
rect( x
+2, y
+2, w
, h
);
2358 Refresh( erase_background
, &rect
);
2364 int ry1
= m_selEndY
;
2365 int ry2
= m_selStartY
;
2379 int y
= ry1
*m_lineHeight
;
2380 CalcScrolledPosition( x
, y
, &x
, &y
);
2381 wxRect
rect( 0, y
+2, 10000, (ry2
-ry1
+1)*m_lineHeight
);
2383 Refresh( TRUE
, &rect
);
2388 printf( "startx %d starty %d endx %d endy %d\n",
2389 m_selStartX, m_selStartY, m_selEndX, m_selEndY );
2391 printf( "has %d\n", (int)HasSelection() );
2394 if (!no_cursor_refresh
)
2396 // int x = m_cursorX*m_charWidth;
2397 int x
= PosToPixel( m_cursorY
, m_cursorX
);
2398 int y
= m_cursorY
*m_lineHeight
;
2399 CalcScrolledPosition( x
, y
, &x
, &y
);
2400 wxRect
rect( x
+2, y
+2, 4, m_lineHeight
+2 );
2405 Refresh( TRUE
, &rect
);
2407 if (FindFocus() == this)
2409 wxClientDC
dc(this);
2411 dc
.SetPen( *wxTRANSPARENT_PEN
);
2412 //dc.SetBrush( *wxRED_BRUSH );
2413 dc
.SetBrush( *wxBLACK_BRUSH
);
2414 // int xx = m_cursorX*m_charWidth;
2415 int xx
= PosToPixel( m_cursorY
, m_cursorX
);
2416 dc
.DrawRectangle( xx
+2, m_cursorY
*m_lineHeight
+2, 2, m_lineHeight
);
2422 GetClientSize( &size_x
, &size_y
);
2423 size_x
/= m_charWidth
;
2424 size_y
/= m_lineHeight
;
2428 GetViewStart( &view_x
, &view_y
);
2432 int sy
= m_cursorY
- (size_y
/2);
2438 if (m_cursorY
< view_y
)
2439 Scroll( -1, m_cursorY
);
2440 else if (m_cursorY
> view_y
+size_y
-1)
2441 Scroll( -1, m_cursorY
-size_y
+1 );
2444 //int xx = m_cursorX;
2445 int xx
= PosToPixel( m_cursorY
, m_cursorX
) / m_charWidth
;
2449 else if (xx
> view_x
+size_x
-1)
2450 Scroll( xx
-size_x
+1, -1 );
2453 void wxTextCtrl::MyAdjustScrollbars()
2458 int y_range
= m_lines
.GetCount();
2461 GetClientSize( NULL
, &height
);
2463 if (height
>= (int)m_lines
.GetCount() *m_lineHeight
)
2468 GetViewStart( &view_x
, &view_y
);
2470 SetScrollbars( m_charWidth
, m_lineHeight
, m_longestLine
+2, y_range
, view_x
, view_y
);
2473 //-----------------------------------------------------------------------------
2474 // clipboard handlers
2475 //-----------------------------------------------------------------------------
2477 void wxTextCtrl::OnCut(wxCommandEvent
& WXUNUSED(event
))
2482 void wxTextCtrl::OnCopy(wxCommandEvent
& WXUNUSED(event
))
2487 void wxTextCtrl::OnPaste(wxCommandEvent
& WXUNUSED(event
))
2492 void wxTextCtrl::OnUndo(wxCommandEvent
& WXUNUSED(event
))
2497 void wxTextCtrl::OnRedo(wxCommandEvent
& WXUNUSED(event
))
2502 void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent
& event
)
2504 event
.Enable( CanCut() );
2507 void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent
& event
)
2509 event
.Enable( CanCopy() );
2512 void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent
& event
)
2514 event
.Enable( CanPaste() );
2517 void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent
& event
)
2519 event
.Enable( CanUndo() );
2522 void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent
& event
)
2524 event
.Enable( CanRedo() );
2527 wxSize
wxTextCtrl::DoGetBestSize() const
2531 wxSize
ret(80, m_lineHeight
+ 4);
2533 if (HasFlag(wxBORDER_SUNKEN
) || HasFlag(wxBORDER_RAISED
))
2536 if (HasFlag(wxBORDER_SIMPLE
))
2543 return wxSize(80, 60);
2547 // ----------------------------------------------------------------------------
2549 // ----------------------------------------------------------------------------
2551 void wxTextCtrl::Freeze()
2555 void wxTextCtrl::Thaw()
2559 void wxTextCtrl::OnSetFocus( wxFocusEvent
& event
)
2561 // To hide or show caret, as appropriate
2565 void wxTextCtrl::OnKillFocus( wxFocusEvent
& event
)
2567 // To hide or show caret, as appropriate
2571 // ----------------------------------------------------------------------------
2572 // text control scrolling
2573 // ----------------------------------------------------------------------------
2575 bool wxTextCtrl::ScrollLines(int lines
)
2577 wxFAIL_MSG( "wxTextCtrl::ScrollLines not implemented");
2582 bool wxTextCtrl::ScrollPages(int pages
)
2584 wxFAIL_MSG( "wxTextCtrl::ScrollPages not implemented");