28 procedure CleanupInput; |
28 procedure CleanupInput; |
29 procedure AddChatString(s: shortstring); |
29 procedure AddChatString(s: shortstring); |
30 procedure DrawChat; |
30 procedure DrawChat; |
31 procedure KeyPressChat(Key, Sym: Longword; Modifier: Word); |
31 procedure KeyPressChat(Key, Sym: Longword; Modifier: Word); |
32 procedure SendHogSpeech(s: shortstring); |
32 procedure SendHogSpeech(s: shortstring); |
|
33 procedure CopyToClipboard(var newContent: shortstring); |
33 |
34 |
34 implementation |
35 implementation |
35 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; |
36 |
37 |
37 const MaxStrIndex = 27; |
38 const MaxStrIndex = 27; |
|
39 MaxInputStrLen = 240; |
38 |
40 |
39 type TChatLine = record |
41 type TChatLine = record |
40 Tex: PTexture; |
42 Tex: PTexture; |
41 Time: Longword; |
43 Time: Longword; |
42 Width: LongInt; |
44 Width: LongInt; |
61 ChatReady: boolean; |
63 ChatReady: boolean; |
62 showAll: boolean; |
64 showAll: boolean; |
63 liveLua: boolean; |
65 liveLua: boolean; |
64 ChatHidden: boolean; |
66 ChatHidden: boolean; |
65 firstDraw: boolean; |
67 firstDraw: boolean; |
66 InputLinePrefix: shortstring; |
68 InputLinePrefix: TChatLine; |
67 // cursor |
69 // cursor |
68 cursorPos, cursorX, selectedPos, selectionDx: LongInt; |
70 cursorPos, cursorX, selectedPos, selectionDx: LongInt; |
69 LastKeyPressTick: LongWord; |
71 LastKeyPressTick: LongWord; |
|
72 |
70 |
73 |
71 const |
74 const |
72 InputStrLNoPred: byte = 255; |
75 InputStrLNoPred: byte = 255; |
73 |
76 |
74 colors: array[#0..#6] of TSDL_Color = ( |
77 colors: array[#0..#6] of TSDL_Color = ( |
108 if cursorPos = selectedPos then |
111 if cursorPos = selectedPos then |
109 ResetSelection(); |
112 ResetSelection(); |
110 |
113 |
111 // calculate cursor offset |
114 // calculate cursor offset |
112 |
115 |
113 str:= InputLinePrefix + InputStr.s; |
116 str:= InputStr.s; |
114 font:= CheckCJKFont(ansistring(str), fnt16); |
117 font:= CheckCJKFont(ansistring(str), fnt16); |
115 |
118 |
116 // get only substring before cursor to determine length |
119 // get only substring before cursor to determine length |
117 // SetLength(str, Length(InputLinePrefix) + cursorPos); // makes pas2c unhappy |
120 // SetLength(str, cursorPos); // makes pas2c unhappy |
118 str[0]:= char(Length(InputLinePrefix) + cursorPos); |
121 str[0]:= char(cursorPos); |
119 // get render size of text |
122 // get render size of text |
120 TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(str), @coff, nil); |
123 TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(str), @coff, nil); |
121 |
124 |
122 cursorX:= 2 + coff; |
125 cursorX:= 2 + coff; |
123 |
126 |
124 // calculate selection width on screen |
127 // calculate selection width on screen |
125 if selectedPos >= 0 then |
128 if selectedPos >= 0 then |
126 begin |
129 begin |
127 if selectedPos > cursorPos then |
130 if selectedPos > cursorPos then |
128 str:= InputLinePrefix + InputStr.s; |
131 str:= InputStr.s; |
129 // SetLength(str, Length(InputLinePrefix) + selectedPos); // makes pas2c unhappy |
132 // SetLength(str, selectedPos); // makes pas2c unhappy |
130 str[0]:= char(Length(InputLinePrefix) + selectedPos); |
133 str[0]:= char(selectedPos); |
131 TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(str), @soff, nil); |
134 TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(str), @soff, nil); |
132 selectionDx:= soff - coff; |
135 selectionDx:= soff - coff; |
133 end |
136 end |
134 else |
137 else |
135 selectionDx:= 0; |
138 selectionDx:= 0; |
246 SetLine(Strs[lastStr], s, false); |
249 SetLine(Strs[lastStr], s, false); |
247 |
250 |
248 inc(visibleCount) |
251 inc(visibleCount) |
249 end; |
252 end; |
250 |
253 |
|
254 procedure CheckPasteBuffer(); forward; |
|
255 |
|
256 procedure UpdateInputLinePrefix(); |
|
257 begin |
|
258 if liveLua then |
|
259 begin |
|
260 InputLinePrefix.color:= colors[#1]; |
|
261 InputLinePrefix.s:= '[Lua] >'; |
|
262 end |
|
263 else |
|
264 begin |
|
265 InputLinePrefix.color:= colors[#6]; |
|
266 InputLinePrefix.s:= UserNick + '>'; |
|
267 end; |
|
268 |
|
269 FreeAndNilTexture(InputLinePrefix.Tex); |
|
270 end; |
|
271 |
251 procedure DrawChat; |
272 procedure DrawChat; |
252 var i, t, left, top, cnt: LongInt; |
273 var i, t, left, top, cnt: LongInt; |
253 selRect: TSDL_Rect; |
274 selRect: TSDL_Rect; |
254 begin |
275 begin |
255 ChatReady:= true; // maybe move to somewhere else? |
276 ChatReady:= true; // maybe move to somewhere else? |
262 top := 10 + visibleCount * ClHeight; // we start with input line (if any) |
283 top := 10 + visibleCount * ClHeight; // we start with input line (if any) |
263 |
284 |
264 // draw chat input line first and under all other lines |
285 // draw chat input line first and under all other lines |
265 if (GameState = gsChat) and (InputStr.Tex <> nil) then |
286 if (GameState = gsChat) and (InputStr.Tex <> nil) then |
266 begin |
287 begin |
|
288 CheckPasteBuffer(); |
|
289 |
|
290 if InputLinePrefix.Tex = nil then |
|
291 RenderChatLineTex(InputLinePrefix, InputLinePrefix.s); |
|
292 |
|
293 DrawTexture(left, top, InputLinePrefix.Tex); |
|
294 inc(left, InputLinePrefix.Width); |
|
295 DrawTexture(left, top, InputStr.Tex); |
|
296 |
267 if firstDraw then |
297 if firstDraw then |
268 begin |
298 begin |
269 UpdateCursorCoords(); |
299 UpdateCursorCoords(); |
270 firstDraw:= false; |
300 firstDraw:= false; |
271 end; |
301 end; |
272 |
302 |
273 DrawTexture(left, top, InputStr.Tex); |
|
274 if selectedPos < 0 then |
303 if selectedPos < 0 then |
275 begin |
304 begin |
276 // draw cursor |
305 // draw cursor |
277 if ((RealTicks - LastKeyPressTick) and 512) < 256 then |
306 if ((RealTicks - LastKeyPressTick) and 512) < 256 then |
278 DrawLineOnScreen(left + cursorX, top + 2, left + cursorX, top + ClHeight - 2, 2.0, $00, $FF, $FF, $FF); |
307 DrawLineOnScreen(left + cursorX, top + 2, left + cursorX, top + ClHeight - 2, 2.0, $00, $FF, $FF, $FF); |
292 selRect.w:= selectionDx; |
321 selRect.w:= selectionDx; |
293 end; |
322 end; |
294 |
323 |
295 DrawRect(selRect, $FF, $FF, $FF, $40, true); |
324 DrawRect(selRect, $FF, $FF, $FF, $40, true); |
296 end; |
325 end; |
|
326 |
|
327 dec(left, InputLinePrefix.Width); |
297 end; |
328 end; |
298 |
|
299 |
329 |
300 // draw chat lines |
330 // draw chat lines |
301 if ((not ChatHidden) or showAll) and (UIDisplay <> uiNone) then |
331 if ((not ChatHidden) or showAll) and (UIDisplay <> uiNone) then |
302 begin |
332 begin |
303 if MissedCount <> 0 then // there are chat strings we missed, so print them now |
333 if MissedCount <> 0 then // there are chat strings we missed, so print them now |
656 cursorPos:= InputStrL[cursorPos]; |
688 cursorPos:= InputStrL[cursorPos]; |
657 break; |
689 break; |
658 end; |
690 end; |
659 end; |
691 end; |
660 end; |
692 end; |
|
693 end; |
|
694 |
|
695 procedure CopyToClipboard(var newContent: shortstring); |
|
696 begin |
|
697 SendIPC(_S'y' + copy(newContent, 1, 253) + #0); |
|
698 end; |
|
699 |
|
700 procedure CopySelectionToClipboard(); |
|
701 var selection: shortstring; |
|
702 begin |
|
703 if selectedPos >= 0 then |
|
704 begin |
|
705 selection:= copy(InputStr.s, min(CursorPos, selectedPos) + 1, abs(CursorPos - selectedPos)); |
|
706 CopyToClipboard(selection); |
|
707 end; |
|
708 end; |
|
709 |
|
710 // TODO: honor utf8, don't break utf8 chars when shifting chars beyond limit |
|
711 procedure InsertIntoInputStr(s: shortstring); |
|
712 var i, l, il, lastc: integer; |
|
713 begin |
|
714 // safe length for string |
|
715 l:= min(MaxInputStrLen-cursorPos, Length(s)); |
|
716 s:= copy(s,1,l); |
|
717 |
|
718 // if we insert rather than append, shift info in InputStrL accordingly |
|
719 if cursorPos < Length(InputStr.s) then |
|
720 begin |
|
721 for i:= Length(InputStr.s) downto cursorPos + 1 do |
|
722 begin |
|
723 if InputStrL[i] <> InputStrLNoPred then |
|
724 begin |
|
725 il:= i + l; |
|
726 // only shift if not overflowing |
|
727 if il <= MaxInputStrLen then |
|
728 InputStrL[il]:= InputStrL[i] + l; |
|
729 InputStrL[i]:= InputStrLNoPred; |
|
730 end; |
|
731 end; |
|
732 end; |
|
733 |
|
734 InputStrL[cursorPos + l]:= cursorPos; |
|
735 // insert string truncated to safe length |
|
736 Insert(s, InputStr.s, cursorPos + 1); |
|
737 if Length(InputStr.s) > MaxInputStrLen then |
|
738 InputStr.s[0]:= char(MaxInputStrLen); |
|
739 |
|
740 SetLine(InputStr, InputStr.s, true); |
|
741 |
|
742 // move cursor to end of inserted string |
|
743 lastc:= MaxInputStrLen; |
|
744 cursorPos:= min(lastc, cursorPos + l); |
|
745 UpdateCursorCoords(); |
|
746 end; |
|
747 |
|
748 procedure PasteFromClipboard(); |
|
749 begin |
|
750 SendIPC(_S'Y'); |
|
751 end; |
|
752 |
|
753 procedure CheckPasteBuffer(); |
|
754 begin |
|
755 if Length(ChatPasteBuffer) > 0 then |
|
756 begin |
|
757 InsertIntoInputStr(ChatPasteBuffer); |
|
758 ChatPasteBuffer:= ''; |
|
759 end; |
661 end; |
760 end; |
662 |
761 |
663 procedure KeyPressChat(Key, Sym: Longword; Modifier: Word); |
762 procedure KeyPressChat(Key, Sym: Longword; Modifier: Word); |
664 const firstByteMark: array[0..3] of byte = (0, $C0, $E0, $F0); |
763 const firstByteMark: array[0..3] of byte = (0, $C0, $E0, $F0); |
665 var i, btw, index: integer; |
764 var i, btw, index: integer; |
886 Key:= Key shr 6 |
1016 Key:= Key shr 6 |
887 end; |
1017 end; |
888 |
1018 |
889 utf8:= char(Key or firstByteMark[Pred(btw)]) + utf8; |
1019 utf8:= char(Key or firstByteMark[Pred(btw)]) + utf8; |
890 |
1020 |
891 if Length(InputStr.s) + btw > 240 then |
1021 if Length(InputStr.s) + btw > MaxInputStrLen then |
892 exit; |
1022 exit; |
893 |
1023 |
894 // if we insert rather than append, shift info in InputStrL accordingly |
1024 InsertIntoInputStr(utf8); |
895 if cursorPos < Length(InputStr.s) then |
|
896 begin |
|
897 for i:= Length(InputStr.s) downto cursorPos + 1 do |
|
898 begin |
|
899 if InputStrL[i] <> InputStrLNoPred then |
|
900 begin |
|
901 InputStrL[i+btw]:= InputStrL[i] + btw; |
|
902 InputStrL[i]:= InputStrLNoPred; |
|
903 end; |
|
904 end; |
|
905 end; |
|
906 |
|
907 InputStrL[cursorPos + btw]:= cursorPos; |
|
908 Insert(utf8, InputStr.s, cursorPos + 1); |
|
909 SetLine(InputStr, InputStr.s, true); |
|
910 |
|
911 cursorPos:= cursorPos + btw; |
|
912 UpdateCursorCoords(); |
|
913 end |
1025 end |
914 end; |
1026 end; |
915 |
1027 |
916 procedure chChatMessage(var s: shortstring); |
1028 procedure chChatMessage(var s: shortstring); |
917 begin |
1029 begin |