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