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