50 type TInputStrL = array[0..260] of byte; |
50 type TInputStrL = array[0..260] of byte; |
51 |
51 |
52 var Strs: array[0 .. MaxStrIndex] of TChatLine; |
52 var Strs: array[0 .. MaxStrIndex] of TChatLine; |
53 MStrs: array[0 .. MaxStrIndex] of shortstring; |
53 MStrs: array[0 .. MaxStrIndex] of shortstring; |
54 LocalStrs: array[0 .. MaxStrIndex] of shortstring; |
54 LocalStrs: array[0 .. MaxStrIndex] of shortstring; |
55 LocalStrsL: array[0 .. MaxStrIndex] of TInputStrL; |
|
56 missedCount: LongWord; |
55 missedCount: LongWord; |
57 lastStr: LongWord; |
56 lastStr: LongWord; |
58 localLastStr: LongInt; |
57 localLastStr: LongInt; |
59 history: LongInt; |
58 history: LongInt; |
60 visibleCount: LongWord; |
59 visibleCount: LongWord; |
746 selection:= copy(InputStr.s, min(CursorPos, selectedPos) + 1, abs(CursorPos - selectedPos)); |
744 selection:= copy(InputStr.s, min(CursorPos, selectedPos) + 1, abs(CursorPos - selectedPos)); |
747 CopyToClipboard(selection); |
745 CopyToClipboard(selection); |
748 end; |
746 end; |
749 end; |
747 end; |
750 |
748 |
751 // TODO: honor utf8, don't break utf8 chars when shifting chars beyond limit |
749 // regenerate UTF-8 info for current input string |
|
750 procedure RegenInputStrL(); |
|
751 var i, n, lastL: integer; |
|
752 b: byte; |
|
753 begin |
|
754 lastL:= InputStrLNoPred; |
|
755 i:= 0; |
|
756 n:= Length(InputStr.s); |
|
757 while i <= n do |
|
758 begin |
|
759 |
|
760 // also save lastL if we reached the end |
|
761 if i = n then |
|
762 b:= 0 |
|
763 else |
|
764 b:= byte(InputStr.s[i+1]); |
|
765 |
|
766 // start of char, based on https://en.wikipedia.org/wiki/UTF-8#Description |
|
767 if (b and $C0) <> $80 then |
|
768 begin |
|
769 InputStrL[i]:= lastL; |
|
770 lastL:= i; |
|
771 end |
|
772 else |
|
773 InputStrL[i]:= InputStrLNoPred; |
|
774 |
|
775 inc(i); |
|
776 end; |
|
777 end; |
|
778 |
752 procedure InsertIntoInputStr(s: shortstring); |
779 procedure InsertIntoInputStr(s: shortstring); |
753 var i, l, il, lastc: integer; |
780 var i, l, il, lastc: integer; |
754 begin |
781 begin |
755 // safe length for string |
782 // safe length for string |
756 l:= min(MaxInputStrLen-cursorPos, Length(s)); |
783 l:= min(MaxInputStrLen-cursorPos, Length(s)); |
757 s:= copy(s,1,l); |
784 s:= copy(s,1,l); |
758 |
785 |
759 // if we insert rather than append, shift info in InputStrL accordingly |
|
760 if cursorPos < Length(InputStr.s) then |
|
761 begin |
|
762 for i:= Length(InputStr.s) downto cursorPos + 1 do |
|
763 begin |
|
764 if InputStrL[i] <> InputStrLNoPred then |
|
765 begin |
|
766 il:= i + l; |
|
767 // only shift if not overflowing |
|
768 if il <= MaxInputStrLen then |
|
769 InputStrL[il]:= InputStrL[i] + l; |
|
770 InputStrL[i]:= InputStrLNoPred; |
|
771 end; |
|
772 end; |
|
773 end; |
|
774 |
|
775 InputStrL[cursorPos + l]:= cursorPos; |
|
776 // insert string truncated to safe length |
786 // insert string truncated to safe length |
|
787 // TODO: honor utf8, don't break utf8 chars when shifting chars beyond limit |
777 Insert(s, InputStr.s, cursorPos + 1); |
788 Insert(s, InputStr.s, cursorPos + 1); |
778 if Length(InputStr.s) > MaxInputStrLen then |
789 if Length(InputStr.s) > MaxInputStrLen then |
779 InputStr.s[0]:= char(MaxInputStrLen); |
790 InputStr.s[0]:= char(MaxInputStrLen); |
780 |
791 |
781 SetLine(InputStr, InputStr.s, true); |
792 SetLine(InputStr, InputStr.s, true); |
|
793 |
|
794 // update InputStrL to also reflect whatever was inserted |
|
795 RegenInputStrL(); |
782 |
796 |
783 // move cursor to end of inserted string |
797 // move cursor to end of inserted string |
784 lastc:= MaxInputStrLen; |
798 lastc:= MaxInputStrLen; |
785 cursorPos:= min(lastc, cursorPos + l); |
799 cursorPos:= min(lastc, cursorPos + l); |
786 UpdateCursorCoords(); |
800 UpdateCursorCoords(); |