576 end |
576 end |
577 else |
577 else |
578 ResetSelection(); |
578 ResetSelection(); |
579 end; |
579 end; |
580 |
580 |
|
581 type TCharSkip = ( none, wspace, numalpha, special ); |
|
582 |
|
583 function GetInputCharSkipClass(index: LongInt): TCharSkip; |
|
584 var c: char; |
|
585 begin |
|
586 // multi-byte chars counts as letter |
|
587 if (index > 1) and (InputStrL[index] <> index - 1) then |
|
588 exit(numalpha); |
|
589 |
|
590 c:= InputStr.s[index]; |
|
591 |
|
592 // non-ascii counts as letter |
|
593 if c > #127 then |
|
594 exit(numalpha); |
|
595 |
|
596 // low-ascii whitespaces and DEL |
|
597 if (c < #33) or (c = #127) then |
|
598 exit(wspace); |
|
599 |
|
600 // low-ascii special chars |
|
601 if c < #48 then |
|
602 exit(special); |
|
603 |
|
604 // digits |
|
605 if c < #58 then |
|
606 exit(numalpha); |
|
607 |
|
608 // make c upper-case |
|
609 if c > #96 then |
|
610 c:= char(byte(c) - 32); |
|
611 |
|
612 // letters |
|
613 if (c > #64) and (c < #90) then |
|
614 exit(numalpha); |
|
615 |
|
616 // remaining ascii are special chars |
|
617 exit(special); |
|
618 end; |
|
619 |
|
620 // skip from word to word, similar to Qt |
|
621 procedure skipInputChars(skip: TCharSkip; backwards: boolean); |
|
622 begin |
|
623 if backwards then |
|
624 begin |
|
625 // skip trailing whitespace, similar to Qt |
|
626 while (skip = wspace) and (cursorPos > 0) do |
|
627 begin |
|
628 skip:= GetInputCharSkipClass(cursorPos); |
|
629 if skip = wspace then |
|
630 cursorPos:= InputStrL[cursorPos]; |
|
631 end; |
|
632 // skip same-type chars |
|
633 while (cursorPos > 0) and (GetInputCharSkipClass(cursorPos) = skip) do |
|
634 cursorPos:= InputStrL[cursorPos]; |
|
635 end |
|
636 else |
|
637 begin |
|
638 // skip same-type chars |
|
639 while cursorPos < Length(InputStr.s) do |
|
640 begin |
|
641 DoCursorStepForward(); |
|
642 if (GetInputCharSkipClass(cursorPos) <> skip) then |
|
643 begin |
|
644 // go back 1 char |
|
645 cursorPos:= InputStrL[cursorPos]; |
|
646 break; |
|
647 end; |
|
648 end; |
|
649 // skip trailing whitespace, similar to Qt |
|
650 while cursorPos < Length(InputStr.s) do |
|
651 begin |
|
652 DoCursorStepForward(); |
|
653 if (GetInputCharSkipClass(cursorPos) <> wspace) then |
|
654 begin |
|
655 // go back 1 char |
|
656 cursorPos:= InputStrL[cursorPos]; |
|
657 break; |
|
658 end; |
|
659 end; |
|
660 end; |
|
661 end; |
|
662 |
581 procedure KeyPressChat(Key, Sym: Longword; Modifier: Word); |
663 procedure KeyPressChat(Key, Sym: Longword; Modifier: Word); |
582 const firstByteMark: array[0..3] of byte = (0, $C0, $E0, $F0); |
664 const firstByteMark: array[0..3] of byte = (0, $C0, $E0, $F0); |
583 var i, btw, index: integer; |
665 var i, btw, index: integer; |
584 utf8: shortstring; |
666 utf8: shortstring; |
585 action, selMode, ctrl: boolean; |
667 action, selMode, ctrl: boolean; |
|
668 skip: TCharSkip; |
586 begin |
669 begin |
587 LastKeyPressTick:= RealTicks; |
670 LastKeyPressTick:= RealTicks; |
588 action:= true; |
671 action:= true; |
589 |
672 |
590 selMode:= (modifier and (KMOD_LSHIFT or KMOD_RSHIFT)) <> 0; |
673 selMode:= (modifier and (KMOD_LSHIFT or KMOD_RSHIFT)) <> 0; |
591 ctrl:= (modifier and (KMOD_LCTRL or KMOD_RCTRL)) <> 0; |
674 ctrl:= (modifier and (KMOD_LCTRL or KMOD_RCTRL)) <> 0; |
|
675 skip:= none; |
592 |
676 |
593 case Sym of |
677 case Sym of |
594 SDLK_BACKSPACE: |
678 SDLK_BACKSPACE: |
595 begin |
679 begin |
596 if selectedPos < 0 then |
680 if selectedPos < 0 then |
689 else // if we're leaving selection mode, jump to its left end |
777 else // if we're leaving selection mode, jump to its left end |
690 begin |
778 begin |
691 cursorPos:= min(cursorPos, selectedPos); |
779 cursorPos:= min(cursorPos, selectedPos); |
692 ResetSelection(); |
780 ResetSelection(); |
693 end; |
781 end; |
|
782 |
|
783 if ctrl then |
|
784 skipInputChars(skip, true); |
|
785 |
694 UpdateCursorCoords(); |
786 UpdateCursorCoords(); |
695 end; |
787 end; |
696 end; |
788 end; |
697 SDLK_RIGHT: |
789 SDLK_RIGHT: |
698 begin |
790 begin |
699 if cursorPos < Length(InputStr.s) then |
791 if cursorPos < Length(InputStr.s) then |
700 begin |
792 begin |
|
793 |
701 if selMode or (selectedPos < 0) then |
794 if selMode or (selectedPos < 0) then |
702 begin |
795 begin |
703 HandleSelection(selMode); |
796 HandleSelection(selMode); |
704 DoCursorStepForward(); |
797 DoCursorStepForward(); |
705 end |
798 end |
706 else // if we're leaving selection mode, jump to its right end |
799 else // if we're leaving selection mode, jump to its right end |
707 begin |
800 begin |
708 cursorPos:= max(cursorPos, selectedPos); |
801 cursorPos:= max(cursorPos, selectedPos); |
709 ResetSelection(); |
802 ResetSelection(); |
710 end; |
803 end; |
|
804 |
|
805 if ctrl then |
|
806 skipInputChars(GetInputCharSkipClass(cursorPos), false); |
|
807 |
711 UpdateCursorCoords(); |
808 UpdateCursorCoords(); |
712 end; |
809 end; |
713 end; |
810 end; |
714 SDLK_PAGEUP, SDLK_PAGEDOWN: |
811 SDLK_PAGEUP, SDLK_PAGEDOWN: |
715 begin |
812 begin |