34 |
34 |
35 implementation |
35 implementation |
36 uses SDLh, uInputHandler, uTypes, uVariables, uCommands, uUtils, uTextures, uRender, uIO, uScript, uRenderUtils; |
36 uses SDLh, uInputHandler, uTypes, uVariables, uCommands, uUtils, uTextures, uRender, uIO, uScript, uRenderUtils; |
37 |
37 |
38 const MaxStrIndex = 27; |
38 const MaxStrIndex = 27; |
39 MaxInputStrLen = 240; |
39 MaxInputStrLen = 200; |
40 |
40 |
41 type TChatLine = record |
41 type TChatLine = record |
42 Tex: PTexture; |
42 Tex: PTexture; |
43 Time: Longword; |
43 Time: Longword; |
44 Width: LongInt; |
44 Width: LongInt; |
66 cursorPos, cursorX, selectedPos, selectionDx: LongInt; |
66 cursorPos, cursorX, selectedPos, selectionDx: LongInt; |
67 LastKeyPressTick: LongWord; |
67 LastKeyPressTick: LongWord; |
68 |
68 |
69 |
69 |
70 const |
70 const |
71 InputStrLNoPred: byte = 255; |
|
72 |
|
73 colors: array[#0..#6] of TSDL_Color = ( |
71 colors: array[#0..#6] of TSDL_Color = ( |
74 (r:$FF; g:$FF; b:$FF; a:$FF), // unused, feel free to take it for anything |
72 (r:$FF; g:$FF; b:$FF; a:$FF), // unused, feel free to take it for anything |
75 (r:$FF; g:$FF; b:$FF; a:$FF), // chat message [White] |
73 (r:$FF; g:$FF; b:$FF; a:$FF), // chat message [White] |
76 (r:$FF; g:$00; b:$FF; a:$FF), // action message [Purple] |
74 (r:$FF; g:$00; b:$FF; a:$FF), // action message [Purple] |
77 (r:$90; g:$FF; b:$90; a:$FF), // join/leave message [Lime] |
75 (r:$90; g:$FF; b:$90; a:$FF), // join/leave message [Lime] |
93 |
91 |
94 const Padding = 2; |
92 const Padding = 2; |
95 ClHeight = 2 * Padding + 16; // font height |
93 ClHeight = 2 * Padding + 16; // font height |
96 |
94 |
97 // relevant for UTF-8 handling |
95 // relevant for UTF-8 handling |
98 function IsFirstCharByte(b: byte): boolean; inline; |
96 function IsFirstCharByte(c: char): boolean; inline; |
99 begin |
97 begin |
100 // based on https://en.wikipedia.org/wiki/UTF-8#Description |
98 // based on https://en.wikipedia.org/wiki/UTF-8#Description |
101 IsFirstCharByte:= (b and $C0) <> $80; |
99 IsFirstCharByte:= (byte(c) and $C0) <> $80; |
102 end; |
100 end; |
103 |
101 |
104 function charIsForHogSpeech(c: char): boolean; |
102 function charIsForHogSpeech(c: char): boolean; |
105 begin |
103 begin |
106 exit((c = '"') or (c = '''') or (c = '-')); |
104 exit((c = '"') or (c = '''') or (c = '-')); |
608 procedure MoveCursorToNextChar(); |
606 procedure MoveCursorToNextChar(); |
609 begin |
607 begin |
610 if cursorPos < Length(InputStr.s) then |
608 if cursorPos < Length(InputStr.s) then |
611 begin |
609 begin |
612 inc(cursorPos, 2); |
610 inc(cursorPos, 2); |
613 while (cursorPos < Length(InputStr.s)) and (not IsFirstCharByte(byte(InputStr.s[cursorPos]))) do |
611 while (cursorPos < Length(InputStr.s)) and (not IsFirstCharByte(InputStr.s[cursorPos])) do |
614 begin |
612 begin |
615 inc(cursorPos); |
613 inc(cursorPos); |
616 end; |
614 end; |
617 dec(cursorPos); |
615 dec(cursorPos); |
618 end; |
616 end; |
|
617 end; |
|
618 |
|
619 procedure DeleteLastUTF8CharFromStr(var s: shortstring); |
|
620 var l: byte; |
|
621 begin |
|
622 l:= Length(s); |
|
623 |
|
624 while (l > 1) and (not IsFirstCharByte(s[l])) do |
|
625 begin |
|
626 dec(l); |
|
627 end; |
|
628 |
|
629 if l > 0 then |
|
630 dec(l); |
|
631 |
|
632 s[0]:= char(l); |
619 end; |
633 end; |
620 |
634 |
621 procedure DeleteSelected(); |
635 procedure DeleteSelected(); |
622 begin |
636 begin |
623 if (selectedPos >= 0) and (cursorPos <> selectedPos) then |
637 if (selectedPos >= 0) and (cursorPos <> selectedPos) then |
730 CopyToClipboard(selection); |
744 CopyToClipboard(selection); |
731 end; |
745 end; |
732 end; |
746 end; |
733 |
747 |
734 procedure InsertIntoInputStr(s: shortstring); |
748 procedure InsertIntoInputStr(s: shortstring); |
735 var l, lastc: integer; |
749 var limit: integer; |
736 begin |
750 begin |
737 // safe length for string |
751 // we check limit for trailing stuff before insertion limit for a reason |
738 l:= min(MaxInputStrLen-cursorPos, Length(s)); |
752 // (possible remaining space after too long UTF8-insertion has been shortened) |
739 // SetLength(s, l); |
753 |
740 s[0]:= char(l); |
754 // length limit for stuff to that will trail the insertion |
741 |
755 limit:= max(cursorPos, MaxInputStrLen-Length(s)); |
742 // insert string truncated to safe length |
756 |
743 Insert(s, InputStr.s, cursorPos + 1); |
757 while Length(InputStr.s) > limit do |
744 // TODO: honor utf8, don't break utf8 chars when shifting chars beyond limit |
758 begin |
745 if Length(InputStr.s) > MaxInputStrLen then |
759 DeleteLastUTF8CharFromStr(InputStr.s); |
746 InputStr.s[0]:= char(MaxInputStrLen); |
760 end; |
747 |
761 |
748 SetLine(InputStr, InputStr.s, true); |
762 // length limit for stuff to insert |
749 |
763 limit:= max(0, MaxInputStrLen-cursorPos); |
750 // move cursor to end of inserted string |
764 |
751 lastc:= MaxInputStrLen; |
765 if limit = 0 then |
752 cursorPos:= min(lastc, cursorPos + l); |
766 s:= '' |
753 UpdateCursorCoords(); |
767 else while Length(s) > limit do |
|
768 begin |
|
769 DeleteLastUTF8CharFromStr(s); |
|
770 end; |
|
771 |
|
772 if Length(s) > 0 then |
|
773 begin |
|
774 // insert string truncated to safe length |
|
775 Insert(s, InputStr.s, cursorPos + 1); |
|
776 |
|
777 if Length(InputStr.s) > MaxInputStrLen then |
|
778 InputStr.s[0]:= char(MaxInputStrLen); |
|
779 |
|
780 SetLine(InputStr, InputStr.s, true); |
|
781 |
|
782 // move cursor to end of inserted string |
|
783 inc(cursorPos, Length(s)); |
|
784 UpdateCursorCoords(); |
|
785 end; |
754 end; |
786 end; |
755 |
787 |
756 procedure PasteFromClipboard(); |
788 procedure PasteFromClipboard(); |
757 begin |
789 begin |
758 SendIPC(_S'Y'); |
790 SendIPC(_S'Y'); |