]> git.saurik.com Git - wxWidgets.git/blob - src/x11/textctrl.cpp
Added support for variable-width fonts
[wxWidgets.git] / src / x11 / textctrl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: textctrl.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation "textctrl.h"
12 #endif
13
14 #include "wx/textctrl.h"
15 #include "wx/utils.h"
16 #include "wx/intl.h"
17 #include "wx/log.h"
18 #include "wx/settings.h"
19 #include "wx/panel.h"
20 #include "wx/clipbrd.h"
21 #include "wx/tokenzr.h"
22
23 #include "wx/univ/inphand.h"
24 #include "wx/univ/renderer.h"
25 #include "wx/univ/colschem.h"
26 #include "wx/univ/theme.h"
27
28 //-----------------------------------------------------------------------------
29 // helpers
30 //-----------------------------------------------------------------------------
31
32 wxSourceUndoStep::wxSourceUndoStep( wxSourceUndo type, int y1, int y2, wxTextCtrl *owner )
33 {
34 m_type = type;
35 m_y1 = y1;
36 m_y2 = y2;
37 m_owner = owner;
38
39 m_cursorX = m_owner->GetCursorX();
40 m_cursorY = m_owner->GetCursorY();
41
42 if (m_type == wxSOURCE_UNDO_LINE)
43 {
44 m_text = m_owner->m_lines[m_y1].m_text;
45 } else
46 if (m_type == wxSOURCE_UNDO_ENTER)
47 {
48 m_text = m_owner->m_lines[m_y1].m_text;
49 } else
50 if (m_type == wxSOURCE_UNDO_BACK)
51 {
52 for (int i = m_y1; i < m_y2+2; i++)
53 {
54 if (i >= (int)m_owner->m_lines.GetCount())
55 m_lines.Add( "" );
56 else
57 m_lines.Add( m_owner->m_lines[i].m_text );
58 }
59 } else
60 if (m_type == wxSOURCE_UNDO_DELETE)
61 {
62 for (int i = m_y1; i < m_y2+1; i++)
63 {
64 m_lines.Add( m_owner->m_lines[i].m_text );
65 }
66 } else
67 if (m_type == wxSOURCE_UNDO_PASTE)
68 {
69 m_text = m_owner->m_lines[m_y1].m_text;
70 }
71 }
72
73 void wxSourceUndoStep::Undo()
74 {
75 if (m_type == wxSOURCE_UNDO_LINE)
76 {
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 );
80 } else
81 if (m_type == wxSOURCE_UNDO_ENTER)
82 {
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 );
87 } else
88 if (m_type == wxSOURCE_UNDO_BACK)
89 {
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 );
95 } else
96 if (m_type == wxSOURCE_UNDO_DELETE)
97 {
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 );
104 } else
105 if (m_type == wxSOURCE_UNDO_PASTE)
106 {
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 );
113 } else
114 if (m_type == wxSOURCE_UNDO_INSERT_LINE)
115 {
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 );
120 }
121 }
122
123 #include "wx/arrimpl.cpp"
124 WX_DEFINE_OBJARRAY(wxSourceLineArray);
125
126 //-----------------------------------------------------------------------------
127 // wxTextCtrl
128 //-----------------------------------------------------------------------------
129
130 IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl,wxControl)
131
132 BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
133 EVT_PAINT(wxTextCtrl::OnPaint)
134 EVT_CHAR(wxTextCtrl::OnChar)
135 EVT_MOUSE_EVENTS(wxTextCtrl::OnMouse)
136 EVT_IDLE(wxTextCtrl::OnIdle)
137
138 EVT_MENU(wxID_CUT, wxTextCtrl::OnCut)
139 EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy)
140 EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste)
141 EVT_MENU(wxID_UNDO, wxTextCtrl::OnUndo)
142 EVT_MENU(wxID_REDO, wxTextCtrl::OnRedo)
143
144 EVT_UPDATE_UI(wxID_CUT, wxTextCtrl::OnUpdateCut)
145 EVT_UPDATE_UI(wxID_COPY, wxTextCtrl::OnUpdateCopy)
146 EVT_UPDATE_UI(wxID_PASTE, wxTextCtrl::OnUpdatePaste)
147 EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo)
148 EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo)
149 END_EVENT_TABLE()
150
151 void wxTextCtrl::Init()
152 {
153 m_editable = TRUE;
154 m_modified = FALSE;
155
156 m_undos.DeleteContents( TRUE );
157
158 m_lang = wxSOURCE_LANG_NONE;
159
160 m_capturing = FALSE;
161
162 m_cursorX = 0;
163 m_cursorY = 0;
164
165 m_longestLine = 0;
166
167 m_bracketX = -1;
168 m_bracketY = -1;
169
170 m_overwrite = FALSE;
171 m_ignoreInput = FALSE;
172
173 ClearSelection();
174
175 m_keywordColour = wxColour( 10, 140, 10 );
176
177 m_defineColour = *wxRED;
178
179 m_variableColour = wxColour( 50, 120, 150 );
180
181 m_commentColour = wxColour( 130, 130, 130 );
182
183 m_stringColour = wxColour( 10, 140, 10 );
184 }
185
186 wxTextCtrl::wxTextCtrl( wxWindow *parent,
187 wxWindowID id,
188 const wxString &value,
189 const wxPoint &pos,
190 const wxSize &size,
191 long style,
192 const wxValidator& validator,
193 const wxString &name )
194 : wxScrollHelper(this)
195 {
196 Init();
197
198 Create( parent, id, value, pos, size, style, validator, name );
199 }
200
201 bool wxTextCtrl::Create( wxWindow *parent,
202 wxWindowID id,
203 const wxString &value,
204 const wxPoint &pos,
205 const wxSize &size,
206 long style,
207 const wxValidator& validator,
208 const wxString &name )
209 {
210 if ((style & wxBORDER_MASK) == 0)
211 style |= wxBORDER_SUNKEN;
212
213 if ((style & wxTE_MULTILINE) != 0)
214 style |= wxALWAYS_SHOW_SB;
215
216 wxTextCtrlBase::Create( parent, id, wxDefaultPosition, size,
217 style|wxVSCROLL|wxHSCROLL|wxNO_FULL_REPAINT_ON_RESIZE );
218
219 SetBackgroundColour( *wxWHITE );
220
221 SetCursor( wxCursor( wxCURSOR_IBEAM ) );
222
223 if (HasFlag(wxTE_PASSWORD))
224 m_sourceFont = wxFont( 12, wxMODERN, wxNORMAL, wxNORMAL );
225 else
226 m_sourceFont = GetFont();
227
228 wxClientDC dc(this);
229 dc.SetFont( m_sourceFont );
230 m_lineHeight = dc.GetCharHeight();
231 m_charWidth = dc.GetCharWidth();
232
233 SetValue( value );
234
235 wxSize size_best( DoGetBestSize() );
236 wxSize new_size( size );
237 if (new_size.x == -1)
238 new_size.x = size_best.x;
239 if (new_size.y == -1)
240 new_size.y = size_best.y;
241 if ((new_size.x != size.x) || (new_size.y != size.y))
242 SetSize( new_size.x, new_size.y );
243
244 // We create an input handler since it might be useful
245 CreateInputHandler(wxINP_HANDLER_TEXTCTRL);
246
247 return TRUE;
248 }
249
250 //-----------------------------------------------------------------------------
251 // public methods
252 //-----------------------------------------------------------------------------
253
254 wxString wxTextCtrl::GetValue() const
255 {
256 wxString ret;
257 for (size_t i = 0; i < m_lines.GetCount(); i++)
258 {
259 ret += m_lines[i].m_text;
260 if (i < m_lines.GetCount())
261 ret += wxT('\n');
262 }
263
264 return ret;
265 }
266
267 void wxTextCtrl::SetValue(const wxString& value)
268 {
269 m_modified = TRUE;
270 m_cursorX = 0;
271 m_cursorY = 0;
272 ClearSelection();
273 m_lines.Clear();
274 m_longestLine = 0;
275
276 if (value.IsEmpty())
277 {
278 m_lines.Add( new wxSourceLine( wxT("") ) );
279 }
280 else
281 {
282 int begin = 0;
283 int pos = 0;
284 for (;;)
285 {
286 pos = value.find( wxT('\n'), begin );
287 if (pos < 0)
288 {
289 wxSourceLine *sl = new wxSourceLine( value.Mid( begin, value.Len()-begin ) );
290 m_lines.Add( sl );
291
292 // if (sl->m_text.Len() > m_longestLine)
293 // m_longestLine = sl->m_text.Len();
294 int ww = 0;
295 GetTextExtent( sl->m_text, &ww, NULL, NULL, NULL );
296 ww /= m_charWidth;
297 if (ww > m_longestLine)
298 m_longestLine = ww;
299
300 break;
301 }
302 else
303 {
304 wxSourceLine *sl = new wxSourceLine( value.Mid( begin, pos-begin ) );
305 m_lines.Add( sl );
306
307 // if (sl->m_text.Len() > m_longestLine)
308 // m_longestLine = sl->m_text.Len();
309 int ww = 0;
310 GetTextExtent( sl->m_text, &ww, NULL, NULL, NULL );
311 ww /= m_charWidth;
312 if (ww > m_longestLine)
313 m_longestLine = ww;
314
315 begin = pos+1;
316 }
317 }
318 }
319
320 MyAdjustScrollbars();
321
322 Refresh();
323 }
324
325 int wxTextCtrl::GetLineLength(long lineNo) const
326 {
327 if (lineNo >= (long)m_lines.GetCount())
328 return 0;
329
330 return m_lines[lineNo].m_text.Len();
331 }
332
333 wxString wxTextCtrl::GetLineText(long lineNo) const
334 {
335 if (lineNo >= (long)m_lines.GetCount())
336 return wxT("");
337
338 return m_lines[lineNo].m_text;
339 }
340
341 int wxTextCtrl::GetNumberOfLines() const
342 {
343 return m_lines.GetCount();
344 }
345
346 bool wxTextCtrl::IsModified() const
347 {
348 return m_modified;
349 }
350
351 bool wxTextCtrl::IsEditable() const
352 {
353 return m_editable;
354 }
355
356 void wxTextCtrl::GetSelection(long* from, long* to) const
357 {
358 }
359
360 void wxTextCtrl::Clear()
361 {
362 m_modified = TRUE;
363 m_cursorX = 0;
364 m_cursorY = 0;
365 ClearSelection();
366
367 m_lines.Clear();
368 m_lines.Add( new wxSourceLine( wxT("") ) );
369
370 SetScrollbars( m_charWidth, m_lineHeight, 0, 0, 0, 0 );
371 Refresh();
372 m_undos.Clear();
373 }
374
375 void wxTextCtrl::Replace(long from, long to, const wxString& value)
376 {
377 }
378
379 void wxTextCtrl::Remove(long from, long to)
380 {
381
382 }
383
384 void wxTextCtrl::DiscardEdits()
385 {
386 ClearSelection();
387 Refresh();
388 }
389
390 void wxTextCtrl::SetMaxLength(unsigned long len)
391 {
392 }
393
394 int wxTextCtrl::PosToPixel( int line, int pos )
395 {
396 // TODO add support for Tabs
397
398 if (line >= m_lines.GetCount()) return 0;
399
400 wxString text = m_lines[line].m_text;
401
402 if (text.IsEmpty()) return 0;
403
404 if (pos < text.Len())
405 text.Remove( pos, text.Len()-pos );
406
407 int w = 0;
408
409 GetTextExtent( text, &w, NULL, NULL, NULL );
410
411 return w;
412 }
413
414 int wxTextCtrl::PixelToPos( int line, int pixel )
415 {
416 if (pixel < 2) return 0;
417
418 if (line >= m_lines.GetCount()) return 0;
419
420 wxString text = m_lines[line].m_text;
421
422 int w = 0;
423 int res = text.Len();
424 while (res > 0)
425 {
426 GetTextExtent( text, &w, NULL, NULL, NULL );
427
428 if (w < pixel)
429 return res;
430
431 res--;
432 text.Remove( res,1 );
433 }
434
435 return 0;
436 }
437
438 void wxTextCtrl::WriteText(const wxString& text2)
439 {
440 if (text2.IsEmpty()) return;
441
442 m_modified = TRUE;
443
444 wxString text( text2 );
445 wxArrayString lines;
446 int pos;
447 while ( (pos = text.Find('\n')) != -1 )
448 {
449 lines.Add( text.Left( pos ) );
450 text.Remove( 0, pos+1 );
451 }
452 lines.Add( text );
453 int count = (int)lines.GetCount();
454
455 wxString tmp1( m_lines[m_cursorY].m_text );
456 wxString tmp2( tmp1 );
457 int len = (int)tmp1.Len();
458
459 if (len < m_cursorX)
460 {
461 wxString tmp;
462 for (int i = 0; i < m_cursorX-len; i++)
463 tmp.Append( ' ' );
464 m_lines[m_cursorY].m_text.Append( tmp );
465 tmp1.Append( tmp );
466 tmp2.Append( tmp );
467 }
468
469 tmp1.Remove( m_cursorX );
470 tmp2.Remove( 0, m_cursorX );
471 tmp1.Append( lines[0] );
472
473 if (count == 1)
474 {
475 m_undos.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE, m_cursorY, m_cursorY, this ) );
476
477 tmp1.Append( tmp2 );
478 m_lines[m_cursorY].m_text = tmp1;
479 RefreshLine( m_cursorY );
480 }
481 else
482 {
483 m_undos.Append( new wxSourceUndoStep( wxSOURCE_UNDO_PASTE, m_cursorY, m_cursorY+count-1, this ) );
484
485 m_lines[m_cursorY].m_text = tmp1;
486 int i;
487 for (i = 1; i < count; i++)
488 m_lines.Insert( new wxSourceLine( lines[i] ), m_cursorY+i );
489 m_lines[m_cursorY+i-1].m_text.Append( tmp2 );
490
491 MyAdjustScrollbars();
492 RefreshDown( m_cursorY );
493 }
494 }
495
496 void wxTextCtrl::AppendText(const wxString& text2)
497 {
498 if (text2.IsEmpty()) return;
499
500 m_modified = TRUE;
501
502 wxString text( text2 );
503 wxArrayString lines;
504 int pos;
505 while ( (pos = text.Find('\n')) != -1 )
506 {
507 lines.Add( text.Left( pos ) );
508 text.Remove( 0, pos+1 );
509 }
510 lines.Add( text );
511 int count = (int)lines.GetCount();
512
513 size_t y = m_lines.GetCount()-1;
514
515 wxString tmp( m_lines[y].m_text );
516 tmp.Append( lines[0] );
517
518 if (count == 1)
519 {
520 m_undos.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE, y, y, this ) );
521
522 m_lines[y].m_text = tmp;
523 RefreshLine( y );
524 }
525 else
526 {
527 m_undos.Append( new wxSourceUndoStep( wxSOURCE_UNDO_PASTE, y, y+count-1, this ) );
528
529 m_lines[y].m_text = tmp;
530 int i;
531 for (i = 1; i < count; i++)
532 m_lines.Insert( new wxSourceLine( lines[i] ), y+i );
533
534 MyAdjustScrollbars();
535 RefreshDown( y );
536 }
537 }
538
539 bool wxTextCtrl::SetStyle(long start, long end, const wxTextAttr& style)
540 {
541 return FALSE;
542 }
543
544 long wxTextCtrl::XYToPosition(long x, long y) const
545 {
546 long ret = 0;
547
548 for (size_t i = 0; i < m_lines.GetCount(); i++)
549 {
550 if (i < (size_t)y)
551 {
552 ret += m_lines[i].m_text.Len();
553 continue;
554 }
555
556 if ((size_t)x < m_lines[i].m_text.Len())
557 return (ret + x);
558 else
559 return (ret + m_lines[i].m_text.Len());
560 }
561
562 return ret;
563 }
564
565 bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
566 {
567 if (m_lines.GetCount() == 0)
568 {
569 if (x) *x = 0;
570 if (y) *y = 0;
571
572 return (pos == 0);
573 }
574
575 long xx = 0;
576 long yy = 0;
577
578 for (size_t i = 0; i < m_lines.GetCount(); i++)
579 {
580 pos -= m_lines[i].m_text.Len();
581 if (pos <= 0)
582 {
583 xx = -pos;
584 if (x) *x = xx;
585 if (y) *y = yy;
586 return TRUE;
587 }
588 yy++;
589 }
590
591 // Last pos
592 xx = m_lines[ m_lines.GetCount()-1 ].m_text.Len();
593 if (x) *x = xx;
594 if (y) *y = yy;
595
596 return FALSE;
597 }
598
599 void wxTextCtrl::ShowPosition(long pos)
600 {
601 }
602
603 void wxTextCtrl::Copy()
604 {
605 if (!HasSelection()) return;
606
607 wxString sel;
608
609 int selStartY = m_selStartY;
610 int selEndY = m_selEndY;
611 int selStartX = m_selStartX;
612 int selEndX = m_selEndX;
613
614 if ((selStartY > selEndY) ||
615 ((selStartY == selEndY) && (selStartX > selEndX)))
616 {
617 int tmp = selStartX;
618 selStartX = selEndX;
619 selEndX = tmp;
620 tmp = selStartY;
621 selStartY = selEndY;
622 selEndY = tmp;
623 }
624
625 if (selStartY == selEndY)
626 {
627 sel = m_lines[selStartY].m_text;
628
629 if (selStartX >= (int)sel.Len()) return;
630 if (selEndX > (int)sel.Len())
631 selEndX = sel.Len();
632
633 sel.Remove( selEndX, sel.Len()-selEndX );
634 sel.Remove( 0, selStartX );
635 }
636 else
637 {
638 wxString tmp( m_lines[selStartY].m_text );
639
640 if (selStartX < (int)tmp.Len())
641 {
642 tmp.Remove( 0, selStartX );
643 sel = tmp;
644 sel.Append( "\n" );
645 }
646 for (int i = selStartY+1; i < selEndY; i++)
647 {
648 sel.Append( m_lines[i].m_text );
649 sel.Append( "\n" );
650 }
651 tmp = m_lines[selEndY].m_text;
652 if (selEndX > (int)tmp.Len())
653 selEndX = tmp.Len();
654 if (selEndX > 0)
655 {
656 tmp.Remove( selEndX, tmp.Len()-selEndX );
657 sel.Append( tmp );
658 }
659 }
660
661 if (wxTheClipboard->Open())
662 {
663 wxTheClipboard->SetData( new wxTextDataObject( sel ) );
664 wxTheClipboard->Close();
665 }
666 }
667
668 void wxTextCtrl::Cut()
669 {
670 Copy();
671
672 Delete();
673 }
674
675 void wxTextCtrl::Paste()
676 {
677 Delete();
678
679 if (!wxTheClipboard->Open()) return;
680
681 if (!wxTheClipboard->IsSupported( wxDF_TEXT ))
682 {
683 wxTheClipboard->Close();
684
685 return;
686 }
687
688 wxTextDataObject data;
689
690 bool ret = wxTheClipboard->GetData( data );
691
692 wxTheClipboard->Close();
693
694 if (!ret) return;
695
696 m_modified = TRUE;
697
698 wxString text( data.GetText() );
699 wxArrayString lines;
700 int pos;
701 while ( (pos = text.Find('\n')) != -1 )
702 {
703 lines.Add( text.Left( pos ) );
704 text.Remove( 0, pos+1 );
705 }
706 lines.Add( text );
707 int count = (int)lines.GetCount();
708
709 wxString tmp1( m_lines[m_cursorY].m_text );
710 wxString tmp2( tmp1 );
711 int len = (int)tmp1.Len();
712
713 if (len < m_cursorX)
714 {
715 wxString tmp;
716 for (int i = 0; i < m_cursorX-len; i++)
717 tmp.Append( ' ' );
718 m_lines[m_cursorY].m_text.Append( tmp );
719 tmp1.Append( tmp );
720 tmp2.Append( tmp );
721 }
722
723 tmp1.Remove( m_cursorX );
724 tmp2.Remove( 0, m_cursorX );
725 tmp1.Append( lines[0] );
726
727 if (count == 1)
728 {
729 m_undos.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE, m_cursorY, m_cursorY, this ) );
730
731 tmp1.Append( tmp2 );
732 m_lines[m_cursorY].m_text = tmp1;
733 RefreshLine( m_cursorY );
734 }
735 else
736 {
737 m_undos.Append( new wxSourceUndoStep( wxSOURCE_UNDO_PASTE, m_cursorY, m_cursorY+count-1, this ) );
738
739 m_lines[m_cursorY].m_text = tmp1;
740 int i;
741 for (i = 1; i < count; i++)
742 m_lines.Insert( new wxSourceLine( lines[i] ), m_cursorY+i );
743 m_lines[m_cursorY+i-1].m_text.Append( tmp2 );
744
745 MyAdjustScrollbars();
746 RefreshDown( m_cursorY );
747 }
748 }
749
750 void wxTextCtrl::Undo()
751 {
752 if (m_undos.GetCount() == 0) return;
753
754 wxNode *node = m_undos.Nth( m_undos.GetCount()-1 );
755 wxSourceUndoStep *undo = (wxSourceUndoStep*) node->Data();
756
757 undo->Undo();
758
759 delete node;
760
761 m_modified = TRUE;
762 }
763
764 void wxTextCtrl::SetInsertionPoint(long pos)
765 {
766 }
767
768 void wxTextCtrl::SetInsertionPointEnd()
769 {
770 }
771
772 long wxTextCtrl::GetInsertionPoint() const
773 {
774 return XYToPosition( m_cursorX, m_cursorY );
775 }
776
777 long wxTextCtrl::GetLastPosition() const
778 {
779 size_t lineCount = m_lines.GetCount() - 1;
780 return XYToPosition( m_lines[lineCount].m_text.Len()-1, lineCount );
781 }
782
783 void wxTextCtrl::SetSelection(long from, long to)
784 {
785 }
786
787 void wxTextCtrl::SetEditable(bool editable)
788 {
789 m_editable = editable;
790 }
791
792 bool wxTextCtrl::Enable( bool enable )
793 {
794 return FALSE;
795 }
796
797 bool wxTextCtrl::SetFont(const wxFont& font)
798 {
799 return FALSE;
800 }
801
802 bool wxTextCtrl::SetForegroundColour(const wxColour& colour)
803 {
804 return wxWindow::SetForegroundColour( colour );
805 }
806
807 bool wxTextCtrl::SetBackgroundColour(const wxColour& colour)
808 {
809 return wxWindow::SetBackgroundColour( colour );
810 }
811
812 //-----------------------------------------------------------------------------
813 // private code and handlers
814 //-----------------------------------------------------------------------------
815
816 void wxTextCtrl::SearchForBrackets()
817 {
818 int oldBracketY = m_bracketY;
819 int oldBracketX = m_bracketX;
820
821 if (m_cursorY < 0 || m_cursorY >= (int)m_lines.GetCount()) return;
822
823 wxString current = m_lines[m_cursorY].m_text;
824
825 // reverse search first
826
827 char bracket = ' ';
828
829 if (m_cursorX > 0)
830 bracket = current[m_cursorX-1];
831
832 if (bracket == ')' || bracket == ']' || bracket == '}')
833 {
834 char antibracket = '(';
835 if (bracket == ']') antibracket = '[';
836 if (bracket == '}') antibracket = '{';
837
838 int count = 1;
839
840 int endY = m_cursorY-60;
841 if (endY < 0) endY = 0;
842 for (int y = m_cursorY; y >= endY; y--)
843 {
844 current = m_lines[y].m_text;
845 if (y == m_cursorY)
846 current.erase(m_cursorX-1,current.Len()-m_cursorX+1);
847
848 for (int n = current.Len()-1; n >= 0; n--)
849 {
850 // ignore chars
851 if (current[n] == '\'')
852 {
853 for (int m = n-1; m >= 0; m--)
854 {
855 if (current[m] == '\'')
856 {
857 if (m == 0 || current[m-1] != '\\')
858 break;
859 }
860 n = m-1;
861 }
862 continue;
863 }
864
865 // ignore strings
866 if (current[n] == '\"')
867 {
868 for (int m = n-1; m >= 0; m--)
869 {
870 if (current[m] == '\"')
871 {
872 if (m == 0 || current[m-1] != '\\')
873 break;
874 }
875 n = m-1;
876 }
877 continue;
878 }
879
880 if (current[n] == antibracket)
881 {
882 count--;
883 if (count == 0)
884 {
885 m_bracketY = y;
886 m_bracketX = n;
887 if (oldBracketY != m_bracketY && oldBracketY != -1)
888 RefreshLine( oldBracketY );
889 if (m_bracketY != oldBracketY || m_bracketX != oldBracketX)
890 RefreshLine( m_bracketY );
891 return;
892 }
893 }
894 else if (current[n] == bracket)
895 {
896 count++;
897 }
898 }
899 }
900 }
901
902 // then forward
903
904 bracket = ' ';
905 if ((int)current.Len() > m_cursorX)
906 bracket = current[m_cursorX];
907 if (bracket == '(' || bracket == '[' || bracket == '{')
908 {
909 char antibracket = ')';
910 if (bracket == '[') antibracket = ']';
911 if (bracket == '{') antibracket = '}';
912
913 int count = 1;
914
915 int endY = m_cursorY+60;
916 if (endY > (int)(m_lines.GetCount()-1)) endY = m_lines.GetCount()-1;
917 for (int y = m_cursorY; y <= endY; y++)
918 {
919 current = m_lines[y].m_text;
920 int start = 0;
921 if (y == m_cursorY)
922 start = m_cursorX+1;
923
924 for (int n = start; n < (int)current.Len(); n++)
925 {
926 // ignore chars
927 if (current[n] == '\'')
928 {
929 for (int m = n+1; m < (int)current.Len(); m++)
930 {
931 if (current[m] == '\'')
932 {
933 if (m == 0 || (current[m-1] != '\\') || (m >= 2 && current[m-2] == '\\'))
934 break;
935 }
936 n = m+1;
937 }
938 continue;
939 }
940
941 // ignore strings
942 if (current[n] == '\"')
943 {
944 for (int m = n+1; m < (int)current.Len(); m++)
945 {
946 if (current[m] == '\"')
947 {
948 if (m == 0 || (current[m-1] != '\\') || (m >= 2 && current[m-2] == '\\'))
949 break;
950 }
951 n = m+1;
952 }
953 continue;
954 }
955
956 if (current[n] == antibracket)
957 {
958 count--;
959 if (count == 0)
960 {
961 m_bracketY = y;
962 m_bracketX = n;
963 if (oldBracketY != m_bracketY && oldBracketY != -1)
964 RefreshLine( oldBracketY );
965 if (m_bracketY != oldBracketY || m_bracketX != oldBracketX)
966 RefreshLine( m_bracketY );
967 return;
968 }
969 }
970 else if (current[n] == bracket)
971 {
972 count++;
973 }
974 }
975 }
976 }
977
978 if (oldBracketY != -1)
979 {
980 m_bracketY = -1;
981 RefreshLine( oldBracketY );
982 }
983 }
984
985 void wxTextCtrl::Delete()
986 {
987 if (!HasSelection()) return;
988
989 m_modified = TRUE;
990
991 int selStartY = m_selStartY;
992 int selEndY = m_selEndY;
993 int selStartX = m_selStartX;
994 int selEndX = m_selEndX;
995
996 if ((selStartY > selEndY) ||
997 ((selStartY == selEndY) && (selStartX > selEndX)))
998 {
999 int tmp = selStartX;
1000 selStartX = selEndX;
1001 selEndX = tmp;
1002 tmp = selStartY;
1003 selStartY = selEndY;
1004 selEndY = tmp;
1005 }
1006
1007 int len = (int)m_lines[selStartY].m_text.Len();
1008
1009 if (selStartY == selEndY)
1010 {
1011 m_undos.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE, selStartY, selStartY, this ) );
1012
1013 wxString tmp( m_lines[selStartY].m_text );
1014 if (selStartX < len)
1015 {
1016 if (selEndX > len)
1017 selEndX = len;
1018 tmp.Remove( selStartX, selEndX-selStartX );
1019 m_lines[selStartY].m_text = tmp;
1020 }
1021 ClearSelection();
1022 m_cursorX = selStartX;
1023 RefreshLine( selStartY );
1024 }
1025 else
1026 {
1027 m_undos.Append( new wxSourceUndoStep( wxSOURCE_UNDO_DELETE, selStartY, selEndY, this ) );
1028
1029 if (selStartX < len)
1030 m_lines[selStartY].m_text.Remove( selStartX );
1031
1032 for (int i = 0; i < selEndY-selStartY-1; i++)
1033 m_lines.RemoveAt( selStartY+1 );
1034
1035 if (selEndX < (int)m_lines[selStartY+1].m_text.Len())
1036 m_lines[selStartY+1].m_text.Remove( 0, selEndX );
1037 else
1038 m_lines[selStartY+1].m_text.Remove( 0 );
1039
1040 m_lines[selStartY].m_text.Append( m_lines[selStartY+1].m_text );
1041 m_lines.RemoveAt( selStartY+1 );
1042
1043 ClearSelection();
1044 MoveCursor( selStartX, selStartY );
1045 MyAdjustScrollbars();
1046
1047 RefreshDown( selStartY );
1048 }
1049 }
1050
1051 void wxTextCtrl::DeleteLine()
1052 {
1053 if (HasSelection()) return;
1054
1055 if (m_cursorY < 0 || m_cursorY >= (int)m_lines.GetCount()-1) return; // TODO
1056
1057 m_undos.Append( new wxSourceUndoStep( wxSOURCE_UNDO_DELETE, m_cursorY, m_cursorY+1, this ) );
1058
1059 m_lines.RemoveAt( m_cursorY );
1060 m_cursorX = 0;
1061 if (m_cursorY >= (int)m_lines.GetCount()) m_cursorY--;
1062
1063 MyAdjustScrollbars();
1064 RefreshDown( m_cursorY );
1065 }
1066
1067 void wxTextCtrl::DoChar( char c )
1068 {
1069 m_modified = TRUE;
1070
1071 m_undos.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE, m_cursorY, m_cursorY, this ) );
1072
1073 wxString tmp( m_lines[m_cursorY].m_text );
1074 tmp.Trim();
1075 if (m_cursorX >= (int)tmp.Len())
1076 {
1077 int len = tmp.Len();
1078 for (int i = 0; i < m_cursorX - len; i++)
1079 tmp.Append( ' ' );
1080 tmp.Append( c );
1081 }
1082 else
1083 {
1084 if (m_overwrite)
1085 tmp.SetChar( m_cursorX, c );
1086 else
1087 tmp.insert( m_cursorX, 1, c );
1088 }
1089
1090 m_lines[m_cursorY].m_text = tmp;
1091
1092 // if (tmp.Len() > m_longestLine)
1093 // {
1094 // m_longestLine = tmp.Len();
1095 // MyAdjustScrollbars();
1096 // }
1097
1098 int ww = 0;
1099 GetTextExtent( tmp, &ww, NULL, NULL, NULL );
1100 ww /= m_charWidth;
1101 if (ww > m_longestLine)
1102 {
1103 m_longestLine = ww;
1104 MyAdjustScrollbars();
1105 }
1106
1107 m_cursorX++;
1108
1109 int y = m_cursorY*m_lineHeight;
1110 // int x = (m_cursorX-1)*m_charWidth;
1111 int x = PosToPixel( m_cursorY, m_cursorX-1 );
1112 CalcScrolledPosition( x, y, &x, &y );
1113 wxRect rect( x+2, y+2, 10000, m_lineHeight );
1114 Refresh( TRUE, &rect );
1115
1116 int size_x = 0;
1117 int size_y = 0;
1118 GetClientSize( &size_x, &size_y );
1119 size_x /= m_charWidth;
1120
1121 int view_x = 0;
1122 int view_y = 0;
1123 GetViewStart( &view_x, &view_y );
1124
1125 //int xx = m_cursorX;
1126 int xx = PosToPixel( m_cursorY, m_cursorX ) / m_charWidth;
1127
1128 if (xx < view_x)
1129 Scroll( xx, -1 );
1130 else if (xx > view_x+size_x-1)
1131 Scroll( xx-size_x+1, -1 );
1132 }
1133
1134 void wxTextCtrl::DoBack()
1135 {
1136 m_modified = TRUE;
1137
1138 if (m_cursorX == 0)
1139 {
1140 if (m_cursorY == 0) return;
1141
1142 m_undos.Append( new wxSourceUndoStep( wxSOURCE_UNDO_BACK, m_cursorY-1, m_cursorY, this ) );
1143
1144 wxString tmp1( m_lines[m_cursorY-1].m_text );
1145 tmp1.Trim();
1146 wxString tmp2( m_lines[m_cursorY].m_text );
1147 tmp2.Trim();
1148 m_cursorX = tmp1.Len();
1149 m_cursorY--;
1150 tmp1.Append( tmp2 );
1151 m_lines[m_cursorY].m_text = tmp1;
1152 m_lines.RemoveAt( m_cursorY+1 );
1153
1154 MyAdjustScrollbars();
1155 RefreshDown( m_cursorY-1 );
1156 }
1157 else
1158 {
1159 m_undos.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE, m_cursorY, m_cursorY, this ) );
1160
1161 if (m_cursorX <= (int)m_lines[m_cursorY].m_text.Len())
1162 m_lines[m_cursorY].m_text.Remove( m_cursorX-1, 1 );
1163 m_cursorX--;
1164
1165 int y = m_cursorY*m_lineHeight;
1166 // int x = m_cursorX*m_charWidth;
1167 int x = PosToPixel( m_cursorY, m_cursorX );
1168 CalcScrolledPosition( x, y, &x, &y );
1169 wxRect rect( x+2, y+2, 10000, m_lineHeight );
1170 Refresh( TRUE, &rect );
1171 }
1172 }
1173
1174 void wxTextCtrl::DoDelete()
1175 {
1176 m_modified = TRUE;
1177
1178 wxString tmp( m_lines[m_cursorY].m_text );
1179 tmp.Trim();
1180 int len = (int)tmp.Len();
1181 if (m_cursorX >= len)
1182 {
1183 if (m_cursorY == (int)m_lines.GetCount()-1) return;
1184
1185 m_undos.Append( new wxSourceUndoStep( wxSOURCE_UNDO_DELETE, m_cursorY, m_cursorY+1, this ) );
1186
1187 for (int i = 0; i < (m_cursorX-len); i++)
1188 tmp += ' ';
1189
1190 tmp += m_lines[m_cursorY+1].m_text;
1191
1192 m_lines[m_cursorY] = tmp;
1193 m_lines.RemoveAt( m_cursorY+1 );
1194
1195 MyAdjustScrollbars();
1196 RefreshDown( m_cursorY );
1197 }
1198 else
1199 {
1200 m_undos.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE, m_cursorY, m_cursorY, this ) );
1201
1202 tmp.Remove( m_cursorX, 1 );
1203 m_lines[m_cursorY].m_text = tmp;
1204
1205 int y = m_cursorY*m_lineHeight;
1206 // int x = m_cursorX*m_charWidth;
1207 int x = PosToPixel( m_cursorY, m_cursorX );
1208 CalcScrolledPosition( x, y, &x, &y );
1209 wxRect rect( x+2, y+2, 10000, m_lineHeight );
1210 Refresh( TRUE, &rect );
1211 }
1212 }
1213
1214 void wxTextCtrl::DoReturn()
1215 {
1216 m_modified = TRUE;
1217
1218 m_undos.Append( new wxSourceUndoStep( wxSOURCE_UNDO_ENTER, m_cursorY, m_cursorY, this ) );
1219
1220 wxString tmp( m_lines[m_cursorY].m_text );
1221 size_t indent = tmp.find_first_not_of( ' ' );
1222 if (indent == wxSTRING_MAXLEN) indent = 0;
1223 tmp.Trim();
1224 if (m_cursorX >= (int)tmp.Len())
1225 {
1226 int cursorX = indent;
1227 int cursorY = m_cursorY + 1;
1228
1229 wxString new_tmp;
1230 for (size_t i = 0; i < indent; i++) new_tmp.Append( ' ' );
1231 m_lines.Insert( new wxSourceLine( new_tmp ), cursorY );
1232
1233 MyAdjustScrollbars();
1234 MoveCursor( cursorX, cursorY );
1235 RefreshDown( m_cursorY );
1236 }
1237 else
1238 {
1239 wxString tmp1( tmp );
1240 tmp1.Remove( m_cursorX, tmp.Len()-m_cursorX );
1241 m_lines[m_cursorY].m_text = tmp1;
1242
1243 wxString tmp2( tmp );
1244 tmp2.Remove( 0, m_cursorX );
1245
1246 int cursorX = indent;
1247 int cursorY = m_cursorY + 1;
1248
1249 wxString new_tmp;
1250 for (size_t i = 0; i < indent; i++) new_tmp.Append( ' ' );
1251 new_tmp.Append( tmp2 );
1252 m_lines.Insert( new wxSourceLine( new_tmp ), cursorY );
1253
1254 MyAdjustScrollbars();
1255 MoveCursor( cursorX, cursorY );
1256 RefreshDown( m_cursorY-1 );
1257 }
1258 }
1259
1260 void wxTextCtrl::DoDClick()
1261 {
1262 wxString line( m_lines[ m_cursorY ].m_text );
1263 if (m_cursorX >= (int)line.Len()) return;
1264 int p = m_cursorX;
1265 char ch = line[p];
1266 if (((ch >= 'a') && (ch <= 'z')) ||
1267 ((ch >= 'A') && (ch <= 'Z')) ||
1268 ((ch >= '0') && (ch <= '9')) ||
1269 (ch == '_'))
1270 {
1271 m_selStartY = m_cursorY;
1272 m_selEndY = m_cursorY;
1273 if (p > 0)
1274 {
1275 ch = line[p-1];
1276 while (((ch >= 'a') && (ch <= 'z')) ||
1277 ((ch >= 'A') && (ch <= 'Z')) ||
1278 ((ch >= '0') && (ch <= '9')) ||
1279 (ch == '_'))
1280 {
1281 p--;
1282 if (p == 0) break;
1283 ch = line[p-1];
1284 }
1285 }
1286 m_selStartX = p;
1287
1288 p = m_cursorX;
1289 if (p < (int)line.Len())
1290 {
1291 ch = line[p];
1292 while (((ch >= 'a') && (ch <= 'z')) ||
1293 ((ch >= 'A') && (ch <= 'Z')) ||
1294 ((ch >= '0') && (ch <= '9')) ||
1295 (ch == '_'))
1296 {
1297 if (p >= (int)line.Len()) break;
1298 p++;
1299 ch = line[p];
1300 }
1301 }
1302 m_selEndX = p;
1303 RefreshLine( m_cursorY );
1304 }
1305 }
1306
1307 wxString wxTextCtrl::GetNextToken( wxString &line, int &pos )
1308 {
1309 wxString ret;
1310 int len = (int)line.Len();
1311 for (int p = pos; p < len; p++)
1312 {
1313 if ((m_lang == wxSOURCE_LANG_PYTHON) || (m_lang == wxSOURCE_LANG_PERL))
1314 {
1315 if (line[p] == '#')
1316 {
1317 for (int q = p; q < len; q++)
1318 ret.Append( line[q] );
1319 pos = p;
1320 return ret;
1321 }
1322 }
1323 else
1324 {
1325 if ((line[p] == '/') && (p+1 < len) && (line[p+1] == '/'))
1326 {
1327 for (int q = p; q < len; q++)
1328 ret.Append( line[q] );
1329 pos = p;
1330 return ret;
1331 }
1332 }
1333
1334 if (line[p] == '"')
1335 {
1336 ret.Append( line[p] );
1337 for (int q = p+1; q < len; q++)
1338 {
1339 ret.Append( line[q] );
1340 if ((line[q] == '"') && ((line[q-1] != '\\') || (q >= 2 && line[q-2] == '\\')))
1341 break;
1342 }
1343 pos = p;
1344 return ret;
1345 }
1346
1347 if (line[p] == '\'')
1348 {
1349 ret.Append( line[p] );
1350 for (int q = p+1; q < len; q++)
1351 {
1352 ret.Append( line[q] );
1353 if ((line[q] == '\'') && ((line[q-1] != '\\') || (q >= 2 && line[q-2] == '\\')))
1354 break;
1355 }
1356 pos = p;
1357 return ret;
1358 }
1359
1360 if (((line[p] >= 'a') && (line[p] <= 'z')) ||
1361 ((line[p] >= 'A') && (line[p] <= 'Z')) ||
1362 (line[p] == '_') ||
1363 (line[p] == '#'))
1364 {
1365 ret.Append( line[p] );
1366 for (int q = p+1; q < len; q++)
1367 {
1368 if (((line[q] >= 'a') && (line[q] <= 'z')) ||
1369 ((line[q] >= 'A') && (line[q] <= 'Z')) ||
1370 ((line[q] >= '0') && (line[q] <= '9')) ||
1371 (line[q] == '_'))
1372 {
1373 ret.Append( line[q] );
1374 continue;
1375 }
1376 else
1377 {
1378 pos = p;
1379 return ret;
1380 }
1381 }
1382 pos = p;
1383 return ret;
1384 }
1385 }
1386
1387 return ret;
1388 }
1389
1390 void wxTextCtrl::DrawLine( wxDC &dc, int x, int y, const wxString &line2, int lineNum )
1391 {
1392 int selStartY = m_selStartY;
1393 int selEndY = m_selEndY;
1394 int selStartX = m_selStartX;
1395 int selEndX = m_selEndX;
1396
1397 if ((selStartY > selEndY) ||
1398 ((selStartY == selEndY) && (selStartX > selEndX)))
1399 {
1400 int tmp = selStartX;
1401 selStartX = selEndX;
1402 selEndX = tmp;
1403 tmp = selStartY;
1404 selStartY = selEndY;
1405 selEndY = tmp;
1406 }
1407
1408 wxString line( line2 );
1409 if (HasFlag(wxTE_PASSWORD))
1410 {
1411 size_t len = line.Len();
1412 line = wxString( wxT('*'), len );
1413 }
1414
1415 wxString keyword( ' ', line.Len() );
1416 wxString define( ' ', line.Len() );
1417 wxString variable( ' ', line.Len() );
1418 wxString comment( ' ', line.Len() );
1419 wxString my_string( ' ', line.Len() );
1420
1421 if (m_lang != wxSOURCE_LANG_NONE)
1422 {
1423 if (lineNum == m_bracketY)
1424 {
1425 wxString red( ' ', line.Len() );
1426 if (m_bracketX < (int)line.Len())
1427 {
1428 red.SetChar( m_bracketX, line[m_bracketX] );
1429 line.SetChar( m_bracketX, ' ' );
1430 dc.SetTextForeground( *wxRED );
1431 dc.DrawText( red, x, y );
1432 dc.SetTextForeground( *wxBLACK );
1433 }
1434 }
1435
1436 int pos = 0;
1437 wxString token( GetNextToken( line, pos) );
1438 while (!token.IsNull())
1439 {
1440 if (m_keywords.Index( token ) != wxNOT_FOUND)
1441 {
1442 int end_pos = pos + (int)token.Len();
1443 for (int i = pos; i < end_pos; i++)
1444 {
1445 keyword.SetChar( i, line[i] );
1446 line.SetChar( i, ' ' );
1447 }
1448 } else
1449 if (m_defines.Index( token ) != wxNOT_FOUND)
1450 {
1451 int end_pos = pos + (int)token.Len();
1452 for (int i = pos; i < end_pos; i++)
1453 {
1454 define.SetChar( i, line[i] );
1455 line.SetChar( i, ' ' );
1456 }
1457 } else
1458 if ((m_variables.Index( token ) != wxNOT_FOUND) ||
1459 ((token.Len() > 2) && (token[0] == 'w') && (token[1] == 'x')))
1460 {
1461 int end_pos = pos + (int)token.Len();
1462 for (int i = pos; i < end_pos; i++)
1463 {
1464 variable.SetChar( i, line[i] );
1465 line.SetChar( i, ' ' );
1466 }
1467 } else
1468 if ((token.Len() >= 2) && (token[0] == '/') && (token[1] == '/') && (m_lang == wxSOURCE_LANG_CPP))
1469 {
1470 int end_pos = pos + (int)token.Len();
1471 for (int i = pos; i < end_pos; i++)
1472 {
1473 comment.SetChar( i, line[i] );
1474 line.SetChar( i, ' ' );
1475 }
1476 } else
1477 if ((token[0] == '#') &&
1478 ((m_lang == wxSOURCE_LANG_PYTHON) || (m_lang == wxSOURCE_LANG_PERL)))
1479 {
1480 int end_pos = pos + (int)token.Len();
1481 for (int i = pos; i < end_pos; i++)
1482 {
1483 comment.SetChar( i, line[i] );
1484 line.SetChar( i, ' ' );
1485 }
1486
1487 } else
1488 if ((token[0] == '"') || (token[0] == '\''))
1489 {
1490 int end_pos = pos + (int)token.Len();
1491 for (int i = pos; i < end_pos; i++)
1492 {
1493 my_string.SetChar( i, line[i] );
1494 line.SetChar( i, ' ' );
1495 }
1496 }
1497 pos += token.Len();
1498 token = GetNextToken( line, pos);
1499 }
1500 }
1501
1502 if ((lineNum < selStartY) || (lineNum > selEndY))
1503 {
1504 dc.DrawText( line, x, y );
1505 if (m_lang != wxSOURCE_LANG_NONE)
1506 {
1507 dc.SetTextForeground( m_keywordColour );
1508 dc.DrawText( keyword, x, y );
1509 dc.SetTextForeground( m_defineColour );
1510 dc.DrawText( define, x, y );
1511 dc.SetTextForeground( m_variableColour );
1512 dc.DrawText( variable, x, y );
1513 dc.SetTextForeground( m_commentColour );
1514 dc.DrawText( comment, x, y );
1515 dc.SetTextForeground( m_stringColour );
1516 dc.DrawText( my_string, x, y );
1517 dc.SetTextForeground( *wxBLACK );
1518 }
1519 return;
1520 }
1521
1522 if (selStartY == selEndY)
1523 {
1524 // int xx = selStartX*m_charWidth;
1525 int xx = PosToPixel( lineNum, selStartX );
1526 // int ww = (selEndX-selStartX)*m_charWidth;
1527 int ww = PosToPixel( lineNum, selEndX ) - xx;
1528 dc.DrawRectangle( xx+2, lineNum*m_lineHeight+2, ww, m_lineHeight );
1529
1530 if (m_lang != wxSOURCE_LANG_NONE)
1531 {
1532 int i;
1533 wxString tmp1( line );
1534 wxString tmp2( line );
1535
1536 for (i = selStartX; i < selEndX; i++)
1537 if ((int)tmp1.Len() > i)
1538 tmp1.SetChar( i, ' ' );
1539 dc.DrawText( tmp1, x, y );
1540 for (i = 0; i < selStartX; i++)
1541 if ((int)tmp2.Len() > i)
1542 tmp2.SetChar( i, ' ' );
1543 for (i = selEndX; i < (int)tmp2.Len(); i++)
1544 if ((int)tmp2.Len() > i)
1545 tmp2.SetChar( i, ' ' );
1546 dc.SetTextForeground( *wxWHITE );
1547 dc.DrawText( tmp2, x, y );
1548 dc.SetTextForeground( *wxBLACK );
1549 }
1550 } else
1551 if ((lineNum > selStartY) && (lineNum < selEndY))
1552 {
1553 dc.DrawRectangle( 0+2, lineNum*m_lineHeight+2, 10000, m_lineHeight );
1554 if (m_lang != wxSOURCE_LANG_NONE)
1555 {
1556 dc.SetTextForeground( *wxWHITE );
1557 dc.DrawText( line, x, y );
1558 dc.SetTextForeground( *wxBLACK );
1559 }
1560 } else
1561 if (lineNum == selStartY)
1562 {
1563 // int xx = selStartX*m_charWidth;
1564 int xx = PosToPixel( lineNum, selStartX );
1565 dc.DrawRectangle( xx+2, lineNum*m_lineHeight+2, 10000, m_lineHeight );
1566
1567 if (m_lang != wxSOURCE_LANG_NONE)
1568 {
1569 int i;
1570 wxString tmp1( line );
1571 wxString tmp2( line );
1572 for (i = selStartX; i < (int)tmp1.Len(); i++)
1573 tmp1.SetChar( i, ' ' );
1574 dc.DrawText( tmp1, x, y );
1575 for (i = 0; i < selStartX; i++)
1576 if ((int)tmp2.Len() > i)
1577 tmp2.SetChar( i, ' ' );
1578 dc.SetTextForeground( *wxWHITE );
1579 dc.DrawText( tmp2, x, y );
1580 dc.SetTextForeground( *wxBLACK );
1581 }
1582 } else
1583 if (lineNum == selEndY)
1584 {
1585 // int ww = selEndX*m_charWidth;
1586 int ww = PosToPixel( lineNum, selEndX );
1587 dc.DrawRectangle( 0+2, lineNum*m_lineHeight+2, ww, m_lineHeight );
1588
1589 if (m_lang != wxSOURCE_LANG_NONE)
1590 {
1591 int i;
1592 wxString tmp1( line );
1593 wxString tmp2( line );
1594 for (i = 0; i < selEndX; i++)
1595 if ((int)tmp1.Len() > i)
1596 tmp1.SetChar( i, ' ' );
1597 dc.DrawText( tmp1, x, y );
1598 for (i = selEndX; i < (int)tmp2.Len(); i++)
1599 tmp2.SetChar( i, ' ' );
1600 dc.SetTextForeground( *wxWHITE );
1601 dc.DrawText( tmp2, x, y );
1602 dc.SetTextForeground( *wxBLACK );
1603 }
1604 }
1605
1606 if (m_lang == wxSOURCE_LANG_NONE)
1607 {
1608 dc.DrawText( line, x, y );
1609 }
1610 else
1611 {
1612 dc.SetTextForeground( m_keywordColour );
1613 dc.DrawText( keyword, x, y );
1614 dc.SetTextForeground( m_defineColour );
1615 dc.DrawText( define, x, y );
1616 dc.SetTextForeground( m_variableColour );
1617 dc.DrawText( variable, x, y );
1618 dc.SetTextForeground( m_commentColour );
1619 dc.DrawText( comment, x, y );
1620 dc.SetTextForeground( m_stringColour );
1621 dc.DrawText( my_string, x, y );
1622 dc.SetTextForeground( *wxBLACK );
1623 }
1624 }
1625
1626 void wxTextCtrl::OnPaint( wxPaintEvent &event )
1627 {
1628 wxPaintDC dc(this);
1629
1630 if (m_lines.GetCount() == 0) return;
1631
1632 PrepareDC( dc );
1633
1634 dc.SetFont( m_sourceFont );
1635
1636 int scroll_y = 0;
1637 GetViewStart( NULL, &scroll_y );
1638
1639 int size_x = 0;
1640 int size_y = 0;
1641 GetClientSize( &size_x, &size_y );
1642
1643 dc.SetPen( *wxTRANSPARENT_PEN );
1644 dc.SetBrush( wxBrush( wxTHEME_COLOUR(HIGHLIGHT), wxSOLID ) );
1645 int upper = wxMin( (int)m_lines.GetCount(), scroll_y+(size_y/m_lineHeight)+1 );
1646 for (int i = scroll_y; i < upper; i++)
1647 {
1648 int x = 0+2;
1649 int y = i*m_lineHeight+2;
1650 int w = 10000;
1651 int h = m_lineHeight;
1652 CalcScrolledPosition( x,y,&x,&y );
1653 if (IsExposed(x,y,w,h))
1654 DrawLine( dc, 0+2, i*m_lineHeight+2, m_lines[i].m_text, i );
1655 }
1656
1657 dc.SetBrush( *wxRED_BRUSH );
1658 // int xx = m_cursorX*m_charWidth;
1659 int xx = PosToPixel( m_cursorY, m_cursorX );
1660 dc.DrawRectangle( xx+2, m_cursorY*m_lineHeight+2, 2, m_lineHeight );
1661 }
1662
1663 void wxTextCtrl::OnMouse( wxMouseEvent &event )
1664 {
1665 if (m_lines.GetCount() == 0) return;
1666
1667
1668 #if 0 // there is no middle button on iPAQs
1669 if (event.MiddleDown())
1670 {
1671 Paste( TRUE );
1672 return;
1673 }
1674 #endif
1675
1676 if (event.LeftDClick())
1677 {
1678 DoDClick();
1679 return;
1680 }
1681
1682 if (event.LeftDown())
1683 {
1684 m_capturing = TRUE;
1685 CaptureMouse();
1686 }
1687
1688 if (event.LeftUp())
1689 {
1690 m_capturing = FALSE;
1691 ReleaseMouse();
1692 }
1693
1694 if (event.LeftDown() ||
1695 (event.LeftIsDown() && m_capturing))
1696 {
1697 int x = event.GetX();
1698 int y = event.GetY();
1699 CalcUnscrolledPosition( x, y, &x, &y );
1700 y /= m_lineHeight;
1701 // x /= m_charWidth;
1702 x = PixelToPos( y, x );
1703 MoveCursor(
1704 wxMin( 1000, wxMax( 0, x ) ),
1705 wxMin( (int)m_lines.GetCount()-1, wxMax( 0, y ) ),
1706 event.ShiftDown() || !event.LeftDown() );
1707 }
1708 }
1709
1710 void wxTextCtrl::OnChar( wxKeyEvent &event )
1711 {
1712 if (m_lines.GetCount() == 0) return;
1713
1714 int size_x = 0;
1715 int size_y = 0;
1716 GetClientSize( &size_x, &size_y );
1717 size_x /= m_charWidth;
1718 size_y /= m_lineHeight;
1719 size_y--;
1720
1721 if (event.ShiftDown())
1722 {
1723 switch (event.GetKeyCode())
1724 {
1725 case '4': event.m_keyCode = WXK_LEFT; break;
1726 case '8': event.m_keyCode = WXK_UP; break;
1727 case '6': event.m_keyCode = WXK_RIGHT; break;
1728 case '2': event.m_keyCode = WXK_DOWN; break;
1729 case '9': event.m_keyCode = WXK_PRIOR; break;
1730 case '3': event.m_keyCode = WXK_NEXT; break;
1731 case '7': event.m_keyCode = WXK_HOME; break;
1732 case '1': event.m_keyCode = WXK_END; break;
1733 case '0': event.m_keyCode = WXK_INSERT; break;
1734 }
1735 }
1736
1737 switch (event.GetKeyCode())
1738 {
1739 case WXK_UP:
1740 {
1741 if (m_ignoreInput) return;
1742 if (m_cursorY > 0)
1743 MoveCursor( m_cursorX, m_cursorY-1, event.ShiftDown() );
1744 m_ignoreInput = TRUE;
1745 return;
1746 }
1747 case WXK_DOWN:
1748 {
1749 if (m_ignoreInput) return;
1750 if (m_cursorY < (int)(m_lines.GetCount()-1))
1751 MoveCursor( m_cursorX, m_cursorY+1, event.ShiftDown() );
1752 m_ignoreInput = TRUE;
1753 return;
1754 }
1755 case WXK_LEFT:
1756 {
1757 if (m_ignoreInput) return;
1758 if (m_cursorX > 0)
1759 {
1760 MoveCursor( m_cursorX-1, m_cursorY, event.ShiftDown() );
1761 }
1762 else
1763 {
1764 if (m_cursorY > 0)
1765 MoveCursor( m_lines[m_cursorY-1].m_text.Len(), m_cursorY-1, event.ShiftDown() );
1766 }
1767 m_ignoreInput = TRUE;
1768 return;
1769 }
1770 case WXK_RIGHT:
1771 {
1772 if (m_ignoreInput) return;
1773 if (m_cursorX < 1000)
1774 MoveCursor( m_cursorX+1, m_cursorY, event.ShiftDown() );
1775 m_ignoreInput = TRUE;
1776 return;
1777 }
1778 case WXK_HOME:
1779 {
1780 if (event.ControlDown())
1781 MoveCursor( 0, 0, event.ShiftDown() );
1782 else
1783 MoveCursor( 0, m_cursorY, event.ShiftDown() );
1784 return;
1785 }
1786 case WXK_END:
1787 {
1788 if (event.ControlDown())
1789 MoveCursor( 0, m_lines.GetCount()-1, event.ShiftDown() );
1790 else
1791 MoveCursor( m_lines[m_cursorY].m_text.Len(), m_cursorY, event.ShiftDown() );
1792 return;
1793 }
1794 case WXK_NEXT:
1795 {
1796 if (m_ignoreInput) return;
1797 MoveCursor( m_cursorX, wxMin( (int)(m_lines.GetCount()-1), m_cursorY+size_y ), event.ShiftDown() );
1798 m_ignoreInput = TRUE;
1799 return;
1800 }
1801 case WXK_PRIOR:
1802 {
1803 if (m_ignoreInput) return;
1804 MoveCursor( m_cursorX, wxMax( 0, m_cursorY-size_y ), event.ShiftDown() );
1805 m_ignoreInput = TRUE;
1806 return;
1807 }
1808 case WXK_INSERT:
1809 {
1810 if (event.ShiftDown())
1811 Paste();
1812 else if (event.ControlDown())
1813 Copy();
1814 else
1815 m_overwrite = !m_overwrite;
1816 return;
1817 }
1818 case WXK_RETURN:
1819 {
1820 if (IsSingleLine())
1821 {
1822 event.Skip();
1823 return;
1824 }
1825
1826 if (HasSelection())
1827 Delete();
1828 DoReturn();
1829 return;
1830 }
1831 case WXK_TAB:
1832 {
1833 if (HasSelection())
1834 Delete();
1835 bool save_overwrite = m_overwrite;
1836 m_overwrite = FALSE;
1837 int i = 4-(m_cursorX % 4);
1838 if (i == 0) i = 4;
1839 for (int c = 0; c < i; c++)
1840 DoChar( ' ' );
1841 m_overwrite = save_overwrite;
1842 return;
1843 }
1844 case WXK_BACK:
1845 {
1846 if (HasSelection())
1847 Delete();
1848 else
1849 DoBack();
1850 return;
1851 }
1852 case WXK_DELETE:
1853 {
1854 if (HasSelection())
1855 Delete();
1856 else
1857 DoDelete();
1858 return;
1859 }
1860 default:
1861 {
1862 if ( (event.KeyCode() >= 'a') &&
1863 (event.KeyCode() <= 'z') &&
1864 (event.AltDown()) )
1865 {
1866 // Alt-F etc.
1867 event.Skip();
1868 return;
1869 }
1870
1871 if ( (event.KeyCode() >= 32) &&
1872 (event.KeyCode() <= 255) &&
1873 !(event.ControlDown() && !event.AltDown()) ) // filters out Ctrl-X but leaves Alt-Gr
1874 {
1875 if (HasSelection())
1876 Delete();
1877 DoChar( (char) event.KeyCode() );
1878 return;
1879 }
1880 }
1881 }
1882
1883 event.Skip();
1884 }
1885
1886 void wxTextCtrl::OnIdle( wxIdleEvent &event )
1887 {
1888 m_ignoreInput = FALSE;
1889
1890 if (m_lang != wxSOURCE_LANG_NONE)
1891 SearchForBrackets();
1892
1893 event.Skip( TRUE );
1894 }
1895
1896 void wxTextCtrl::Indent()
1897 {
1898 int startY = m_cursorY;
1899 int endY = m_cursorY;
1900 if (HasSelection())
1901 {
1902 startY = m_selStartY;
1903 endY = m_selEndY;
1904 if (endY < startY)
1905 {
1906 int tmp = startY;
1907 startY = endY;
1908 endY = tmp;
1909 }
1910 }
1911
1912 m_undos.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE, startY, endY, this ) );
1913
1914 for (int i = startY; i <= endY; i++)
1915 {
1916 m_lines[i].m_text.insert( 0u, " " );
1917 RefreshLine( i );
1918 }
1919 }
1920
1921 void wxTextCtrl::Unindent()
1922 {
1923 int startY = m_cursorY;
1924 int endY = m_cursorY;
1925 if (HasSelection())
1926 {
1927 startY = m_selStartY;
1928 endY = m_selEndY;
1929 if (endY < startY)
1930 {
1931 int tmp = startY;
1932 startY = endY;
1933 endY = tmp;
1934 }
1935 }
1936
1937 m_undos.Append( new wxSourceUndoStep( wxSOURCE_UNDO_LINE, startY, endY, this ) );
1938
1939 for (int i = startY; i <= endY; i++)
1940 {
1941 for (int n = 0; n < 4; n++)
1942 {
1943 if (m_lines[i].m_text[0u] == ' ')
1944 m_lines[i].m_text.erase(0u,1u);
1945 }
1946 RefreshLine( i );
1947 }
1948 }
1949 bool wxTextCtrl::HasSelection()
1950 {
1951 return ((m_selStartY != m_selEndY) || (m_selStartX != m_selEndX));
1952 }
1953
1954 void wxTextCtrl::ClearSelection()
1955 {
1956 m_selStartX = -1;
1957 m_selStartY = -1;
1958 m_selEndX = -1;
1959 m_selEndY = -1;
1960 }
1961
1962 void wxTextCtrl::RefreshLine( int n )
1963 {
1964 int y = n*m_lineHeight;
1965 int x = 0;
1966 CalcScrolledPosition( x, y, &x, &y );
1967 wxRect rect( 0+2, y+2, 10000, m_lineHeight );
1968 Refresh( TRUE, &rect );
1969 }
1970
1971 void wxTextCtrl::RefreshDown( int n )
1972 {
1973 int size_x = 0;
1974 int size_y = 0;
1975 GetClientSize( &size_x, &size_y );
1976
1977 int view_x = 0;
1978 int view_y = 0;
1979 GetViewStart( &view_x, &view_y );
1980
1981 if (n < view_y)
1982 {
1983 Refresh();
1984 }
1985 else
1986 {
1987 int y = n*m_lineHeight;
1988 int x = 0;
1989 CalcScrolledPosition( x, y, &x, &y );
1990
1991 wxRect rect( 0+2, y+2, 10000, size_y );
1992 Refresh( TRUE, &rect );
1993 }
1994 }
1995
1996 void wxTextCtrl::MoveCursor( int new_x, int new_y, bool shift, bool centre )
1997 {
1998 // if (IsSingleLine())
1999 {
2000 if (new_x > m_lines[new_y].m_text.Len())
2001 new_x = m_lines[new_y].m_text.Len();
2002 }
2003
2004 if ((new_x == m_cursorX) && (new_y == m_cursorY)) return;
2005
2006 bool no_cursor_refresh = FALSE;
2007
2008 if (shift)
2009 {
2010 int x,y,w,h;
2011
2012 if (!HasSelection())
2013 {
2014 m_selStartX = m_cursorX;
2015 m_selStartY = m_cursorY;
2016
2017 x = 0;
2018 w = 10000;
2019 if (new_y > m_selStartY)
2020 {
2021 y = m_selStartY*m_lineHeight;
2022 h = (new_y-m_selStartY+1)*m_lineHeight;
2023 }
2024 else if (new_y == m_selStartY)
2025 {
2026 y = m_selStartY*m_lineHeight;
2027 h = m_lineHeight;
2028 }
2029 else
2030 {
2031 y = new_y*m_lineHeight;
2032 h = (-new_y+m_selStartY+1)*m_lineHeight;
2033 }
2034
2035 no_cursor_refresh = TRUE;
2036 m_cursorX = new_x;
2037 m_cursorY = new_y;
2038 }
2039 else
2040 {
2041 if (new_y == m_selEndY)
2042 {
2043 y = new_y *m_lineHeight;
2044 h = m_lineHeight;
2045 if (m_selEndX > new_x)
2046 {
2047 // x = new_x*m_charWidth;
2048 x = PosToPixel( new_y, new_x );
2049 // w = (m_selEndX-new_x)*m_charWidth;
2050 w = PosToPixel( new_y, m_selEndX ) - x;
2051 }
2052 else
2053 {
2054 // x = m_selEndX*m_charWidth;
2055 x = PosToPixel( new_y, m_selEndX );
2056 // w = (-m_selEndX+new_x)*m_charWidth;
2057 w = PosToPixel( new_y, new_x ) - x;
2058 }
2059 }
2060 else
2061 {
2062 x = 0;
2063 w = 10000;
2064 if (new_y > m_selEndY)
2065 {
2066 y = m_selEndY*m_lineHeight;
2067 h = (new_y-m_selEndY+1) * m_lineHeight;
2068 }
2069 else
2070 {
2071 y = new_y*m_lineHeight;
2072 h = (-new_y+m_selEndY+1) * m_lineHeight;
2073 }
2074 no_cursor_refresh = TRUE;
2075 m_cursorX = new_x;
2076 m_cursorY = new_y;
2077 }
2078 }
2079
2080 m_selEndX = new_x;
2081 m_selEndY = new_y;
2082
2083 CalcScrolledPosition( x, y, &x, &y );
2084 wxRect rect( x+2, y+2, w, h );
2085 Refresh( TRUE, &rect );
2086 }
2087 else
2088 {
2089 if (HasSelection())
2090 {
2091 int ry1 = m_selEndY;
2092 int ry2 = m_selStartY;
2093 m_selEndX = -1;
2094 m_selEndY = -1;
2095 m_selStartX = -1;
2096 m_selStartY = -1;
2097
2098 if (ry1 > ry2)
2099 {
2100 int tmp = ry2;
2101 ry2 = ry1;
2102 ry1 = tmp;
2103 }
2104
2105 int x = 0;
2106 int y = ry1*m_lineHeight;
2107 CalcScrolledPosition( x, y, &x, &y );
2108 wxRect rect( 0, y+2, 10000, (ry2-ry1+1)*m_lineHeight );
2109
2110 Refresh( TRUE, &rect );
2111 }
2112 }
2113
2114 /*
2115 printf( "startx %d starty %d endx %d endy %d\n",
2116 m_selStartX, m_selStartY, m_selEndX, m_selEndY );
2117
2118 printf( "has %d\n", (int)HasSelection() );
2119 */
2120
2121 if (!no_cursor_refresh)
2122 {
2123 // int x = m_cursorX*m_charWidth;
2124 int x = PosToPixel( m_cursorY, m_cursorX );
2125 int y = m_cursorY*m_lineHeight;
2126 CalcScrolledPosition( x, y, &x, &y );
2127 wxRect rect( x+2, y+2, 4, m_lineHeight+2 );
2128
2129 m_cursorX = new_x;
2130 m_cursorY = new_y;
2131
2132 Refresh( TRUE, &rect );
2133
2134 wxClientDC dc(this);
2135 PrepareDC( dc );
2136 dc.SetPen( *wxTRANSPARENT_PEN );
2137 dc.SetBrush( *wxRED_BRUSH );
2138 // int xx = m_cursorX*m_charWidth;
2139 int xx = PosToPixel( m_cursorY, m_cursorX );
2140 dc.DrawRectangle( xx+2, m_cursorY*m_lineHeight+2, 2, m_lineHeight );
2141 }
2142
2143 int size_x = 0;
2144 int size_y = 0;
2145 GetClientSize( &size_x, &size_y );
2146 size_x /= m_charWidth;
2147 size_y /= m_lineHeight;
2148
2149 int view_x = 0;
2150 int view_y = 0;
2151 GetViewStart( &view_x, &view_y );
2152
2153 if (centre)
2154 {
2155 int sy = m_cursorY - (size_y/2);
2156 if (sy < 0) sy = 0;
2157 Scroll( -1, sy );
2158 }
2159 else
2160 {
2161 if (m_cursorY < view_y)
2162 Scroll( -1, m_cursorY );
2163 else if (m_cursorY > view_y+size_y-1)
2164 Scroll( -1, m_cursorY-size_y+1 );
2165 }
2166
2167 //int xx = m_cursorX;
2168 int xx = PosToPixel( m_cursorY, m_cursorX ) / m_charWidth;
2169
2170 if (xx < view_x)
2171 Scroll( xx, -1 );
2172 else if (xx > view_x+size_x-1)
2173 Scroll( xx-size_x+1, -1 );
2174 }
2175
2176 void wxTextCtrl::MyAdjustScrollbars()
2177 {
2178 if (IsSingleLine())
2179 return;
2180
2181 int y_range = m_lines.GetCount();
2182
2183 int height = 0;
2184 GetClientSize( NULL, &height );
2185 height -= 4;
2186 if (height >= m_lines.GetCount() *m_lineHeight)
2187 y_range = 0;
2188
2189 int view_x = 0;
2190 int view_y = 0;
2191 GetViewStart( &view_x, &view_y );
2192
2193 SetScrollbars( m_charWidth, m_lineHeight, m_longestLine+2, y_range, view_x, view_y );
2194 }
2195
2196 //-----------------------------------------------------------------------------
2197 // clipboard handlers
2198 //-----------------------------------------------------------------------------
2199
2200 void wxTextCtrl::OnCut(wxCommandEvent& WXUNUSED(event))
2201 {
2202 Cut();
2203 }
2204
2205 void wxTextCtrl::OnCopy(wxCommandEvent& WXUNUSED(event))
2206 {
2207 Copy();
2208 }
2209
2210 void wxTextCtrl::OnPaste(wxCommandEvent& WXUNUSED(event))
2211 {
2212 Paste();
2213 }
2214
2215 void wxTextCtrl::OnUndo(wxCommandEvent& WXUNUSED(event))
2216 {
2217 Undo();
2218 }
2219
2220 void wxTextCtrl::OnRedo(wxCommandEvent& WXUNUSED(event))
2221 {
2222 Redo();
2223 }
2224
2225 void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event)
2226 {
2227 event.Enable( CanCut() );
2228 }
2229
2230 void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event)
2231 {
2232 event.Enable( CanCopy() );
2233 }
2234
2235 void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event)
2236 {
2237 event.Enable( CanPaste() );
2238 }
2239
2240 void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event)
2241 {
2242 event.Enable( CanUndo() );
2243 }
2244
2245 void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event)
2246 {
2247 event.Enable( CanRedo() );
2248 }
2249
2250 wxSize wxTextCtrl::DoGetBestSize() const
2251 {
2252 if (IsSingleLine())
2253 {
2254 wxSize ret(80, m_lineHeight + 4);
2255
2256 if (HasFlag(wxBORDER_SUNKEN) || HasFlag(wxBORDER_RAISED))
2257 ret.y += 4;
2258
2259 if (HasFlag(wxBORDER_SIMPLE))
2260 ret.y += 2;
2261
2262 return ret;
2263 }
2264 else
2265 {
2266 return wxSize(80, 60);
2267 }
2268 }
2269
2270 // ----------------------------------------------------------------------------
2271 // freeze/thaw
2272 // ----------------------------------------------------------------------------
2273
2274 void wxTextCtrl::Freeze()
2275 {
2276 }
2277
2278 void wxTextCtrl::Thaw()
2279 {
2280 }
2281
2282 // ----------------------------------------------------------------------------
2283 // text control scrolling
2284 // ----------------------------------------------------------------------------
2285
2286 bool wxTextCtrl::ScrollLines(int lines)
2287 {
2288 wxFAIL_MSG( "wxTextCtrl::ScrollLines not implemented");
2289
2290 return FALSE;
2291 }
2292
2293 bool wxTextCtrl::ScrollPages(int pages)
2294 {
2295 wxFAIL_MSG( "wxTextCtrl::ScrollPages not implemented");
2296
2297 return FALSE;
2298 }
2299