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