1 /* 2 Copyright (c) by Valery Goryachev (Wal) 3 */ 4 5 #include "swl.h" 6 7 #include <algorithm> 8 9 namespace wal 10 { 11 12 ///////////////////////////////////////////////// EditBuf 13 SetSize(int n)14 void EditBuf::SetSize( int n ) 15 { 16 if ( size >= n ) { return; } 17 18 n = ( ( n + STEP - 1 ) / STEP ) * STEP; 19 20 std::vector<unicode_t> p( n ); 21 22 if ( count > 0 ) 23 { 24 memcpy( p.data(), data.data(), count * sizeof( unicode_t ) ); 25 } 26 27 size = n; 28 data = p; 29 } 30 InsertBlock(int pos,int n)31 void EditBuf::InsertBlock( int pos, int n ) 32 { 33 ASSERT( pos >= 0 && pos <= count && n > 0 ); 34 SetSize( count + n ); 35 36 if ( pos < count ) 37 { 38 memmove( data.data() + pos + n, data.data() + pos, ( count - pos ) * sizeof( unicode_t ) ); 39 } 40 41 count += n; 42 } 43 DeleteBlock(int pos,int n)44 void EditBuf::DeleteBlock( int pos, int n ) 45 { 46 ASSERT( pos >= 0 && pos < count && n > 0 ); 47 48 if ( pos + n > count ) 49 { 50 n = count - pos; 51 } 52 53 if ( pos + n < count ) 54 { 55 memmove( data.data() + pos, data.data() + pos + n, ( count - ( pos + n ) ) * sizeof( unicode_t ) ); 56 } 57 58 count -= n; 59 } 60 DelMarked()61 bool EditBuf::DelMarked() 62 { 63 if ( cursor == marker ) { return false; } 64 65 int a, b; 66 67 if ( cursor < marker ) { a = cursor; b = marker; } 68 else { a = marker; b = cursor; } 69 70 int n = b - a; 71 DeleteBlock( a, n ); 72 cursor = marker = a; 73 return true; 74 } 75 Insert(unicode_t t)76 void EditBuf::Insert( unicode_t t ) 77 { 78 DelMarked(); 79 InsertBlock( cursor, 1 ); 80 data[cursor] = t; 81 cursor++; 82 marker = cursor; 83 } 84 Insert(const unicode_t * txt)85 void EditBuf::Insert( const unicode_t* txt ) 86 { 87 DelMarked(); 88 89 if ( !txt || !*txt ) { return; } 90 91 int n = unicode_strlen( txt ); 92 InsertBlock( cursor, n ); 93 94 for ( ; *txt; txt++, cursor++ ) 95 { 96 data[cursor] = *txt; 97 } 98 99 marker = cursor; 100 } 101 Del(bool DeleteWord)102 void EditBuf::Del( bool DeleteWord ) 103 { 104 if ( DelMarked() ) { return; } 105 106 if ( DeleteWord ) 107 { 108 int PrevCursor = cursor; 109 110 int group = cursor < count ? EditBuf::GetCharGroup( data[cursor] ) : -1; 111 112 int CharsToDelete = 0; 113 114 while ( cursor < count && EditBuf::GetCharGroup( data[cursor] ) == group ) 115 { 116 cursor++; 117 CharsToDelete++; 118 } 119 120 cursor = PrevCursor; 121 122 CharsToDelete = std::min( CharsToDelete, count - cursor ); 123 124 if ( CharsToDelete > 0 ) { DeleteBlock( cursor, CharsToDelete ); } 125 } 126 else if ( cursor < count ) 127 { 128 DeleteBlock( cursor, 1 ); 129 } 130 } 131 Backspace(bool DeleteWord)132 void EditBuf::Backspace( bool DeleteWord ) 133 { 134 if ( DelMarked() ) { return; } 135 136 int CharsToDelete = 1; 137 138 if ( DeleteWord ) 139 { 140 int PrevCursor = cursor; 141 142 if ( cursor > 0 ) { cursor--; } 143 144 int group = cursor < count ? EditBuf::GetCharGroup( data[cursor] ) : -1; 145 146 while ( cursor > 0 && EditBuf::GetCharGroup( data[cursor - 1] ) == group ) 147 { 148 cursor--; 149 } 150 151 CharsToDelete = PrevCursor - cursor; 152 } 153 else if ( cursor > 0 ) 154 { 155 cursor--; 156 } 157 158 marker = cursor; 159 DeleteBlock( cursor, CharsToDelete ); 160 } 161 Set(const unicode_t * s,bool mark)162 void EditBuf::Set( const unicode_t* s, bool mark ) 163 { 164 marker = cursor = count = 0; 165 166 if ( !s || !*s ) { return; } 167 168 int n = unicode_strlen( s ); 169 SetSize( n ); 170 memcpy( data.data(), s, n * sizeof( unicode_t ) ); 171 cursor = count = n; 172 marker = mark ? 0 : cursor; 173 } 174 CtrlLeft(bool mark)175 void EditBuf::CtrlLeft ( bool mark ) 176 { 177 if ( cursor > 0 ) { cursor--; } 178 179 int group = cursor < count ? EditBuf::GetCharGroup( data[cursor] ) : -1; 180 181 while ( cursor > 0 && EditBuf::GetCharGroup( data[cursor - 1] ) == group ) 182 { 183 cursor--; 184 } 185 186 if ( !mark ) { marker = cursor; } 187 } 188 CtrlRight(bool mark)189 void EditBuf::CtrlRight ( bool mark ) 190 { 191 int group = cursor < count ? EditBuf::GetCharGroup( data[cursor] ) : -1; 192 193 // if (cursor < count) cursor++; 194 195 while ( cursor < count ) 196 { 197 int nextGroup = cursor + 1 < count ? EditBuf::GetCharGroup( data[cursor + 1] ) : -1; 198 cursor++; 199 200 if ( nextGroup != group ) { break; } 201 } 202 203 if ( !mark ) { marker = cursor; } 204 } 205 GetCharGroup(unicode_t c)206 int EditBuf::GetCharGroup( unicode_t c ) 207 { 208 if ( c <= ' ' || ( c >= 0x7F && c <= 0xA0 ) ) 209 { 210 return 0; 211 } 212 213 //нада, все-таки, нормально юникод применить 214 switch ( c ) 215 { 216 case '!': 217 case '"': 218 case '#': 219 case '$': 220 case '%': 221 case '&': 222 case '\'': 223 case '(': 224 case ')': 225 case '*': 226 case '+': 227 case ',': 228 case '-': 229 case '.': 230 case ':': 231 case ';': 232 case '<': 233 case '=': 234 case '>': 235 case '?': 236 case '@': 237 case '[': 238 case '\\': 239 case '/': 240 case ']': 241 case '^': 242 243 // case '_': 244 case '`': 245 case '{': 246 case '|': 247 case '}': 248 return 1; 249 }; 250 251 return 100; 252 } 253 254 255 /////////////////////////////////////////////////////////// EditLine 256 257 int uiClassEditLine = GetUiID( "EditLine" ); UiGetClassId()258 int EditLine::UiGetClassId() { return uiClassEditLine; } 259 OnChangeStyles()260 void EditLine::OnChangeStyles() 261 { 262 GC gc( this ); 263 gc.Set( GetFont() ); 264 265 cpoint ts = gc.GetTextExtents( ABCString ); 266 charW = ts.x / ABCStringLen; 267 charH = ts.y; 268 269 int w = ( ts.x / ABCStringLen ) * _chars; 270 271 int h = ts.y + 2; 272 273 if ( frame3d ) 274 { 275 w += 8; 276 h += 8; 277 } 278 279 LSize ls; 280 ls.x.minimal = ls.x.ideal = w; 281 ls.x.maximal = 16000; 282 ls.y.minimal = ls.y.maximal = ls.y.ideal = h; 283 SetLSize( ls ); 284 } 285 EditLine(int nId,Win * parent,const crect * rect,const unicode_t * txt,int chars,bool frame,unsigned flags)286 EditLine::EditLine( int nId, Win* parent, const crect* rect, const unicode_t* txt, int chars, bool frame, unsigned flags ) 287 : Win( Win::WT_CHILD, Win::WH_TABFOCUS | WH_CLICKFOCUS, parent, rect, nId ) 288 , _use_alt_symbols( false ) 289 , _flags( flags ) 290 , text( txt ) 291 , _chars( chars > 0 ? chars : 10 ) 292 , cursorVisible( false ) 293 , passwordMode( false ) 294 , showSpaces( true ) 295 , doAcceptAltKeys( false ) 296 , first( 0 ) 297 , frame3d( frame ) 298 , charH( 0 ) 299 , charW( 0 ) 300 , m_ReplaceMode( false ) 301 { 302 text.End(); 303 304 if ( !rect ) 305 { 306 OnChangeStyles(); 307 } 308 }; 309 310 static unicode_t passwordSymbol = '*'; 311 DrawCursor(GC & gc)312 void EditLine::DrawCursor( GC& gc ) 313 { 314 int cursor = text.Cursor(); 315 316 if ( cursor < first ) { return; } 317 318 crect cr = ClientRect(); 319 320 if ( frame3d ) { cr.Dec( 4 ); } 321 322 int x = cr.left; 323 int y = cr.bottom - charH / 5; 324 325 gc.Set( GetFont() ); 326 327 328 cpoint prevSize( 0, 0 ); 329 330 if ( cursor > first ) 331 { 332 if ( passwordMode ) 333 { 334 prevSize = gc.GetTextExtents( &passwordSymbol, 1 ); 335 prevSize.x *= cursor - first; 336 } 337 else 338 { 339 prevSize = gc.GetTextExtents( text.Ptr() + first, cursor - first ); 340 } 341 } 342 343 if ( prevSize.x >= cr.Width() ) { return; } 344 345 x += prevSize.x; 346 347 bool marked = text.Marked( cursor ); 348 unsigned bColor = /*GetColor(*/marked ? UiGetColor( uiMarkBackground, 0, 0, 0x800000 ) : UiGetColor( uiBackground, 0, 0, 0xFFFFFF ); //UiIC_EDIT_STEXT_BG : IC_EDIT_TEXT_BG); 349 unsigned fColor = /*GetColor(*/marked ? UiGetColor( uiMarkColor, 0, 0, 0xFFFFFF ) : UiGetColor( uiColor, 0, 0, 0 ); //IC_EDIT_STEXT : IC_EDIT_TEXT); 350 351 cpoint csize( 0, 0 ); 352 353 if ( cursor < text.Count() ) 354 { 355 csize = gc.GetTextExtents( text.Ptr() + cursor, 1 ); 356 } 357 358 if ( csize.x < charW ) 359 { 360 csize.x = charW; 361 } 362 363 gc.SetFillColor( bColor ); 364 gc.FillRect( crect( x, y, x + csize.x, cr.bottom ) ); 365 366 if ( cursor < text.Count() ) 367 { 368 gc.SetTextColor( fColor ); 369 gc.TextOutF( x, cr.top + ( cr.Height() - csize.y ) / 2 , text.Ptr() + cursor, 1 ); 370 } 371 372 if ( cursorVisible ) 373 { 374 gc.SetFillColor( fColor ); 375 gc.FillRect( crect( x, y, x + charW, cr.bottom ) ); 376 } 377 } 378 CheckCursorPos()379 bool EditLine::CheckCursorPos() 380 { 381 int cursor = text.Cursor(); 382 383 if ( first == cursor ) { return false; } 384 385 int oldFirst = first; 386 387 if ( cursor < first ) 388 { 389 first = cursor - 8; 390 391 if ( first < 0 ) { first = 0; } 392 } 393 394 if ( first == cursor ) { return oldFirst != first; } 395 396 crect cr = ClientRect(); 397 398 if ( frame3d ) { cr.Dec( 4 ); } 399 400 GC gc( this ); 401 gc.Set( GetFont() ); 402 403 if ( passwordMode ) 404 { 405 cpoint size = gc.GetTextExtents( &passwordSymbol, 1 ); 406 int n = cursor - first; 407 int m = size.x != 0 ? cr.Width() / size.x : 0; 408 409 if ( n >= m ) 410 { 411 if ( m > 0 ) { m--; } 412 413 first = cursor - m; 414 } 415 } 416 else 417 { 418 cpoint size = gc.GetTextExtents( text.Ptr() + first, cursor - first ); 419 420 //temp (not optimized) 421 for ( ; size.x >= cr.Width() && first < cursor; first++ ) 422 { 423 size = gc.GetTextExtents( text.Ptr() + first, cursor - first ); 424 } 425 } 426 427 return oldFirst != first; 428 } 429 GetText() const430 std::vector<unicode_t> EditLine::GetText() const 431 { 432 int count = text.Count(); 433 std::vector<unicode_t> p( count + 1 ); 434 435 if ( count > 0 ) { memcpy( p.data(), text.Ptr(), sizeof( unicode_t )*count ); } 436 437 p[count] = 0; 438 return p; 439 } 440 GetTextStr() const441 std::string EditLine::GetTextStr() const 442 { 443 std::vector<unicode_t> V = GetText(); 444 445 return unicode_to_utf8_string( V.data() ); 446 } 447 EventSize(cevent_size * pEvent)448 void EditLine::EventSize( cevent_size* pEvent ) 449 { 450 first = 0; 451 CheckCursorPos(); 452 Invalidate(); 453 } 454 EventTimer(int tid)455 void EditLine::EventTimer( int tid ) 456 { 457 cursorVisible = !cursorVisible; 458 wal::GC gc( this ); 459 DrawCursor( gc ); 460 } 461 EventFocus(bool recv)462 bool EditLine::EventFocus( bool recv ) 463 { 464 if ( !IsReadOnly() ) 465 { 466 cursorVisible = recv; 467 468 if ( recv ) 469 { 470 SetTimer( 1, 500 ); 471 } 472 else 473 { 474 DelTimer( 1 ); 475 } 476 } 477 478 Invalidate(); 479 return true; 480 } 481 InFocus()482 bool EditLine::InFocus() 483 { 484 if ( UseParentFocus() ) 485 { 486 return Parent()->InFocus(); 487 } 488 489 return Win::InFocus(); 490 } 491 SetFocus()492 void EditLine::SetFocus() 493 { 494 if ( UseParentFocus() ) 495 { 496 Parent()->SetFocus(); 497 return; 498 } 499 500 Win::SetFocus(); 501 } 502 Paint(GC & gc,const crect & paintRect)503 void EditLine::Paint( GC& gc, const crect& paintRect ) 504 { 505 crect cr = ClientRect(); 506 crect rect = cr; 507 508 unsigned frameColor = UiGetColor( uiFrameColor, 0, 0, 0xFFFFFF ); 509 510 if ( frame3d ) 511 { 512 DrawBorder( gc, rect, ColorTone( frameColor, +20 ) ); 513 rect.Dec(); 514 Draw3DButtonW2( gc, rect, frameColor, false ); 515 rect.Dec(); 516 rect.Dec(); 517 DrawBorder( gc, rect, ColorTone( frameColor, IsEnabled() ? -200 : -80 ) ); 518 rect.Dec(); 519 } 520 521 unsigned colorBg = UiGetColor( uiBackground, 0, 0, 0xFFFFFF ); 522 523 int x = rect.left; 524 525 gc.SetClipRgn( &rect ); 526 527 if ( first < text.Count() ) 528 { 529 gc.Set( GetFont() ); 530 531 int cH = gc.GetTextExtents( text.Ptr() + first, 1 ).y; 532 int y = cr.top + ( cr.Height() - cH ) / 2; 533 534 int cnt = text.Count() - first; 535 int i = first; 536 537 std::vector<unicode_t> pwTextArray; 538 unicode_t* pwText = 0; 539 540 if ( passwordMode && cnt > 0 ) 541 { 542 pwTextArray.resize( cnt ); 543 544 for ( int i = 0; i < cnt; i++ ) { pwTextArray[i] = passwordSymbol; } 545 546 pwText = pwTextArray.data(); 547 } 548 549 int color = UiGetColor( uiColor, 0, 0, 0 ); 550 int background = UiGetColor( uiBackground, 0, 0, 0xFFFFFF ); 551 552 int mark_color = UiGetColor( uiMarkColor, 0, 0, 0xFFFFFF ); 553 int mark_background = UiGetColor( uiMarkBackground, 0, 0, 0 ); 554 555 while ( cnt > 0 ) 556 { 557 bool mark = text.Marked( i ); 558 559 int j; 560 561 for ( j = i + 1; j < text.Count() && text.Marked( j ) == mark; ) { j++; } 562 563 int n = j - i; 564 cpoint size = gc.GetTextExtents( passwordMode ? pwText : ( text.Ptr() + i ), n ); 565 566 gc.SetFillColor( mark ? mark_background : background ); //GetColor(InFocus() && mark ? IC_EDIT_STEXT_BG : IC_EDIT_TEXT_BG)); 567 gc.FillRect( crect( x, cr.top, x + size.x, cr.bottom ) ); 568 gc.SetTextColor( mark ? mark_color : color ); //GetColor(InFocus() && mark ? IC_EDIT_STEXT : (IsEnabled() ? IC_EDIT_TEXT : IC_GRAY_TEXT))); 569 570 std::vector<unicode_t> VisibleText = new_unicode_str( passwordMode ? pwText : ( text.Ptr() + i ) ); 571 572 // https://github.com/corporateshark/WCMCommander/issues/187 573 if ( showSpaces ) 574 { 575 ReplaceSpaces( &VisibleText ); 576 } 577 578 gc.TextOutF( x, y, VisibleText.data(), n ); 579 cnt -= n; 580 x += size.x; 581 i += n; 582 } 583 } 584 585 if ( x < cr.right ) 586 { 587 gc.SetFillColor( colorBg ); //GetColor(IC_EDIT_TEXT_BG)); 588 cr.left = x; 589 gc.FillRect( cr ); 590 } 591 592 593 if ( InFocus() && !IsReadOnly() ) 594 { 595 DrawCursor( gc ); 596 } 597 598 return; 599 } 600 EventMouse(cevent_mouse * pEvent)601 bool EditLine::EventMouse( cevent_mouse* pEvent ) 602 { 603 switch ( pEvent->Type() ) 604 { 605 case EV_MOUSE_MOVE: 606 if ( IsCaptured() ) 607 { 608 int n = GetCharPos( pEvent->Point() ); 609 text.SetCursor( first + n, true ); 610 cursorVisible = true; 611 CheckCursorPos(); 612 Invalidate(); 613 return true; 614 } 615 616 break; 617 618 case EV_MOUSE_DOUBLE: 619 case EV_MOUSE_PRESS: 620 { 621 if ( pEvent->Button() != MB_L ) 622 { 623 break; 624 } 625 626 int n = GetCharPos( pEvent->Point() ); 627 text.SetCursor( first + n ); 628 cursorVisible = true; 629 CheckCursorPos(); 630 Invalidate(); 631 632 SetCapture( &captureSD ); 633 return true; 634 } 635 break; 636 637 case EV_MOUSE_RELEASE: 638 if ( pEvent->Button() != MB_L ) 639 { 640 break; 641 } 642 643 ReleaseCapture( &captureSD ); 644 return true; 645 }; 646 647 return Win::EventMouse( pEvent ); 648 } 649 EventKey(cevent_key * pEvent)650 bool EditLine::EventKey( cevent_key* pEvent ) 651 { 652 if ( !doAcceptAltKeys && ( pEvent->Mod() & KM_ALT ) != 0 ) 653 { 654 return false; 655 } 656 657 if ( pEvent->Type() == EV_KEYDOWN ) 658 { 659 660 bool shift = ( pEvent->Mod() & KM_SHIFT ) != 0; 661 bool ctrl = ( pEvent->Mod() & KM_CTRL ) != 0; 662 bool alt = ( pEvent->Mod() & KM_ALT ) != 0; 663 664 if ( ctrl ) 665 { 666 switch ( pEvent->Key() ) 667 { 668 case VK_A: 669 text.Begin( false ); 670 text.End( true ); 671 CheckCursorPos(); 672 Invalidate(); 673 return true; 674 675 case VK_C: 676 ClipboardCopy(); 677 return true; 678 679 case VK_V: 680 if ( !IsReadOnly() ) 681 { 682 ClipboardPaste(); 683 } 684 685 return true; 686 687 case VK_X: 688 if ( !IsReadOnly() ) 689 { 690 ClipboardCut(); 691 } 692 693 return true; 694 } 695 } 696 697 switch ( pEvent->Key() ) 698 { 699 case VK_BACK: 700 { 701 if ( IsReadOnly() || text.Cursor() == 0 ) 702 { 703 return true; 704 } 705 706 text.Backspace( ctrl ); 707 SendCommand( SCMD_EDITLINE_DELETED ); 708 Changed(); 709 } 710 break; 711 712 case VK_DELETE: 713 { 714 if ( IsReadOnly() || text.Cursor() > text.Count() ) 715 { 716 return true; 717 } 718 719 text.Del( ctrl ); 720 SendCommand( SCMD_EDITLINE_DELETED ); 721 Changed(); 722 } 723 break; 724 725 case VK_LEFT: 726 { 727 if ( text.Marked() == shift && text.Cursor() == 0 ) 728 { 729 return true; 730 } 731 732 if ( ctrl ) 733 { 734 text.CtrlLeft( shift ); 735 } 736 else 737 { 738 text.Left( shift ); 739 } 740 }; 741 742 break; 743 744 case VK_RIGHT: 745 { 746 if ( text.Marked() == shift && text.Cursor() == text.Count() ) 747 { 748 return true; 749 } 750 751 if ( ctrl ) 752 { 753 text.CtrlRight( shift ); 754 } 755 else 756 { 757 text.Right( shift ); 758 } 759 }; 760 761 break; 762 763 case VK_HOME: 764 { 765 if ( text.Marked() == shift && text.Cursor() == 0 ) 766 { 767 return true; 768 } 769 770 text.Begin( shift ); 771 } 772 break; 773 774 case VK_END: 775 { 776 if ( text.Marked() == shift && text.Cursor() == text.Count() ) 777 { 778 return true; 779 } 780 781 text.End( shift ); 782 } 783 break; 784 785 case VK_INSERT: 786 if ( shift ) 787 { 788 if ( IsReadOnly() ) 789 { 790 return true; 791 } 792 793 ClipboardPaste(); 794 } 795 else if ( ctrl && text.Marked() ) 796 { 797 ClipboardCopy(); 798 } 799 800 break; 801 802 default: 803 wchar_t c = pEvent->Char(); 804 std::vector<unicode_t> oldtext = GetText(); 805 806 if ( c && c >= 0x20 && ( !alt || _use_alt_symbols ) ) 807 { 808 if ( IsReadOnly() ) 809 { 810 return true; 811 } 812 813 if ( m_ReplaceMode ) 814 { 815 text.Del( false ); 816 } 817 818 text.Insert( c ); 819 820 if ( m_Validator && !m_Validator->IsValid( GetText() ) ) 821 { 822 SetText( oldtext.data(), false ); 823 } 824 825 SendCommand( SCMD_EDITLINE_INSERTED ); 826 Changed(); 827 } 828 else 829 { 830 return false; 831 } 832 833 break; 834 } 835 836 cursorVisible = true; 837 CheckCursorPos(); 838 Invalidate(); 839 return true; 840 } 841 842 return Win::EventKey( pEvent ); 843 } 844 ClipboardCopy()845 void EditLine::ClipboardCopy() 846 { 847 ClipboardText ctx; 848 int a = text.Cursor(); 849 int b = text.Marker(); 850 851 if ( a > b ) { int t = a; a = b; b = t; } 852 853 for ( int i = a; i < b; i++ ) { ctx.Append( text[i] ); } 854 855 ClipboardSetText( this, ctx ); 856 } 857 858 ClipboardPaste()859 void EditLine::ClipboardPaste() 860 { 861 ClipboardText ctx; 862 ClipboardGetText( this, &ctx ); 863 int count = ctx.Count(); 864 865 if ( count <= 0 ) { return; } 866 867 for ( int i = 0; i < count; i++ ) 868 { 869 unicode_t c = ctx[i]; 870 871 if ( c == 9 || c == 10 || c == 13 ) { c = ' '; } 872 873 if ( c < 32 ) { break; } 874 875 text.Insert( c ); 876 } 877 878 CheckCursorPos(); 879 Changed(); 880 Invalidate(); 881 } 882 ClipboardCut()883 void EditLine::ClipboardCut() 884 { 885 if ( text.Marked() ) 886 { 887 ClipboardCopy(); 888 text.Del( false ); 889 CheckCursorPos(); 890 Invalidate(); 891 } 892 } 893 Clear()894 void EditLine::Clear() 895 { 896 first = 0; 897 text.Clear(); 898 Invalidate(); 899 } 900 SetText(const unicode_t * txt,bool mark)901 void EditLine::SetText( const unicode_t* txt, bool mark ) 902 { 903 first = 0; 904 cursorVisible = true; 905 text.Set( txt, mark ); 906 Invalidate(); 907 } 908 SetText(const std::string & utf8txt,bool mark)909 void EditLine::SetText( const std::string& utf8txt, bool mark ) 910 { 911 SetText( utf8str_to_unicode(utf8txt).data(), mark ); 912 } 913 Insert(unicode_t t)914 void EditLine::Insert( unicode_t t ) 915 { 916 cursorVisible = true; 917 text.Insert( t ); 918 CheckCursorPos(); 919 Invalidate(); 920 } 921 Insert(const unicode_t * txt)922 void EditLine::Insert( const unicode_t* txt ) 923 { 924 cursorVisible = true; 925 text.Insert( txt ); 926 Invalidate(); 927 } 928 GetCharPos(cpoint p)929 int EditLine::GetCharPos( cpoint p ) 930 { 931 if ( !text.Count() ) { return 0; } 932 933 crect cr = ClientRect(); 934 935 if ( frame3d ) { cr.Dec( 4 ); } 936 937 if ( p.x < cr.left ) { return -1; } 938 939 GC gc( this ); 940 gc.Set( GetFont() ); 941 int n = text.Count() - first; 942 943 for ( int i = 0; i < n; i++ ) 944 { 945 cpoint size = gc.GetTextExtents( text.Ptr() + first + i, i + 1 ); 946 947 if ( cr.left + size.x > p.x ) { return i; } 948 } 949 950 return text.Count(); 951 } 952 ~EditLine()953 EditLine::~EditLine() {} 954 955 956 }; // namespace wal 957