26 procedure freeModule; |
26 procedure freeModule; |
27 procedure ReloadLines; |
27 procedure ReloadLines; |
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); |
31 procedure KeyPressChat(Key, Sym: Longword; Modifier: Word); |
32 procedure SendHogSpeech(s: shortstring); |
32 procedure SendHogSpeech(s: shortstring); |
33 |
33 |
34 implementation |
34 implementation |
35 uses SDLh, uInputHandler, uTypes, uVariables, uCommands, uUtils, uTextures, uRender, uIO, uScript, uRenderUtils; |
35 uses SDLh, uInputHandler, uTypes, uVariables, uCommands, uUtils, uTextures, uRender, uIO, uScript, uRenderUtils; |
36 |
36 |
92 |
92 |
93 |
93 |
94 const Padding = 2; |
94 const Padding = 2; |
95 ClHeight = 2 * Padding + 16; // font height |
95 ClHeight = 2 * Padding + 16; // font height |
96 |
96 |
|
97 procedure ResetSelection(); |
|
98 begin |
|
99 selectedPos:= -1; |
|
100 end; |
|
101 |
97 procedure UpdateCursorCoords(); |
102 procedure UpdateCursorCoords(); |
98 var font: THWFont; |
103 var font: THWFont; |
99 str : shortstring; |
104 str : shortstring; |
100 coff: LongInt; |
105 coff, soff: LongInt; |
101 begin |
106 begin |
|
107 if cursorPos = selectedPos then |
|
108 ResetSelection(); |
|
109 |
102 // calculate cursor offset |
110 // calculate cursor offset |
103 |
111 |
104 str:= InputLinePrefix + InputStr.s; |
112 str:= InputLinePrefix + InputStr.s; |
105 font:= CheckCJKFont(ansistring(str), fnt16); |
113 font:= CheckCJKFont(ansistring(str), fnt16); |
106 |
114 |
107 // get only substring before cursor to determine length |
115 // get only substring before cursor to determine length |
108 SetLength(str, Length(InputLinePrefix) + cursorPos); |
116 SetLength(str, Length(InputLinePrefix) + cursorPos); |
109 // get render size of text |
117 // get render size of text |
110 TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(str), @coff, nil); |
118 TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(str), @coff, nil); |
111 |
119 |
112 |
|
113 cursorX:= 7 - cScreenWidth div 2 + coff; |
120 cursorX:= 7 - cScreenWidth div 2 + coff; |
114 end; |
121 |
|
122 // calculate selection width on screen |
|
123 if selectedPos >= 0 then |
|
124 begin |
|
125 if selectedPos > cursorPos then |
|
126 str:= InputLinePrefix + InputStr.s; |
|
127 SetLength(str, Length(InputLinePrefix) + selectedPos); |
|
128 TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(str), @soff, nil); |
|
129 selectionDx:= soff - coff; |
|
130 end |
|
131 else |
|
132 selectionDx:= 0; |
|
133 end; |
|
134 |
115 |
135 |
116 procedure ResetCursor(); |
136 procedure ResetCursor(); |
117 begin |
137 begin |
|
138 ResetSelection(); |
118 cursorPos:= 0; |
139 cursorPos:= 0; |
119 UpdateCursorCoords(); |
140 UpdateCursorCoords(); |
120 end; |
141 end; |
121 |
142 |
122 procedure RenderChatLineTex(var cl: TChatLine; var str: shortstring); |
143 procedure RenderChatLineTex(var cl: TChatLine; var str: shortstring); |
238 |
260 |
239 // draw chat input line first and under all other lines |
261 // draw chat input line first and under all other lines |
240 if (GameState = gsChat) and (InputStr.Tex <> nil) then |
262 if (GameState = gsChat) and (InputStr.Tex <> nil) then |
241 begin |
263 begin |
242 DrawTexture(left, top, InputStr.Tex); |
264 DrawTexture(left, top, InputStr.Tex); |
243 // draw cursor |
265 if selectedPos < 0 then |
244 if ((RealTicks - LastKeyPressTick) and 512) < 256 then |
266 begin |
245 DrawLineOnScreen(cursorX, top + 2, cursorX, top + ClHeight - 2, 2.0, $00, $FF, $FF, $FF); |
267 // draw cursor |
|
268 if ((RealTicks - LastKeyPressTick) and 512) < 256 then |
|
269 DrawLineOnScreen(cursorX, top + 2, cursorX, top + ClHeight - 2, 2.0, $00, $FF, $FF, $FF); |
|
270 end |
|
271 else // draw selection |
|
272 begin |
|
273 selRect.y:= top + 2; |
|
274 selRect.h:= clHeight - 4; |
|
275 if selectionDx < 0 then |
|
276 begin |
|
277 selRect.x:= cursorX + selectionDx; |
|
278 selRect.w:= -selectionDx; |
|
279 end |
|
280 else |
|
281 begin |
|
282 selRect.x:= cursorX; |
|
283 selRect.w:= selectionDx; |
|
284 end; |
|
285 |
|
286 DrawRect(selRect, $FF, $FF, $FF, $40, true); |
|
287 end; |
246 end; |
288 end; |
247 |
289 |
248 |
290 |
249 // draw chat lines |
291 // draw chat lines |
250 if ((not ChatHidden) or showAll) and (UIDisplay <> uiNone) then |
292 if ((not ChatHidden) or showAll) and (UIDisplay <> uiNone) then |
492 |
534 |
493 btw:= byte(idx) - InputStrL[idx]; |
535 btw:= byte(idx) - InputStrL[idx]; |
494 |
536 |
495 DelCharFromInputStr:= btw; |
537 DelCharFromInputStr:= btw; |
496 |
538 |
497 DelBytesFromInputStr(idx, btw); |
539 DelBytesFromInputStrBack(idx, btw); |
498 end; |
540 end; |
499 |
541 |
|
542 // unchecked |
500 procedure DoCursorStepForward(); |
543 procedure DoCursorStepForward(); |
501 begin |
544 begin |
502 if cursorPos < Length(InputStr.s) then |
545 // go to end of next utf8-char |
503 begin |
546 repeat |
504 // go to end of next utf8-char |
547 inc(cursorPos); |
505 repeat |
548 until InputStrL[cursorPos] <> InputStrLNoPred; |
506 inc(cursorPos); |
549 end; |
507 until InputStrL[cursorPos] <> InputStrLNoPred; |
550 |
508 end; |
551 procedure DeleteSelected(); |
509 end; |
552 begin |
510 |
553 if (selectedPos >= 0) and (cursorPos <> selectedPos) then |
511 procedure KeyPressChat(Key, Sym: Longword); |
554 begin |
|
555 DelBytesFromInputStrBack(max(cursorPos, selectedPos), abs(selectedPos-cursorPos)); |
|
556 cursorPos:= min(cursorPos, selectedPos); |
|
557 ResetSelection(); |
|
558 end; |
|
559 end; |
|
560 |
|
561 procedure HandleSelection(enabled: boolean); |
|
562 begin |
|
563 if enabled then |
|
564 begin |
|
565 if selectedPos < 0 then |
|
566 selectedPos:= cursorPos; |
|
567 end |
|
568 else |
|
569 ResetSelection(); |
|
570 end; |
|
571 |
|
572 procedure KeyPressChat(Key, Sym: Longword; Modifier: Word); |
512 const firstByteMark: array[0..3] of byte = (0, $C0, $E0, $F0); |
573 const firstByteMark: array[0..3] of byte = (0, $C0, $E0, $F0); |
513 var i, btw, index: integer; |
574 var i, btw, index: integer; |
514 utf8: shortstring; |
575 utf8: shortstring; |
515 action: boolean; |
576 action, selMode, ctrl: boolean; |
516 begin |
577 begin |
517 LastKeyPressTick:= RealTicks; |
578 LastKeyPressTick:= RealTicks; |
518 action:= true; |
579 action:= true; |
|
580 |
|
581 selMode:= (modifier and (KMOD_LSHIFT or KMOD_RSHIFT)) <> 0; |
|
582 ctrl:= (modifier and (KMOD_LCTRL or KMOD_RCTRL)) <> 0; |
|
583 |
519 case Sym of |
584 case Sym of |
520 SDLK_BACKSPACE: |
585 SDLK_BACKSPACE: |
521 begin |
586 begin |
522 // remove char before cursor (note: cursorPos is 0-based, char idx isn't) |
587 if selectedPos < 0 then |
523 dec(cursorPos, DelCharFromInputStr(cursorPos)); |
588 begin |
|
589 // remove char before cursor (note: cursorPos is 0-based, char idx isn't) |
|
590 dec(cursorPos, DelCharFromInputStr(cursorPos)); |
|
591 end |
|
592 else |
|
593 DeleteSelected(); |
524 UpdateCursorCoords(); |
594 UpdateCursorCoords(); |
525 end; |
595 end; |
526 SDLK_DELETE: |
596 SDLK_DELETE: |
527 begin |
597 begin |
528 // remove char after cursor |
598 if selectedPos < 0 then |
529 if cursorPos < Length(InputStr.s) then |
599 begin |
530 begin |
600 // remove char after cursor |
531 DoCursorStepForward(); |
601 if cursorPos < Length(InputStr.s) then |
532 dec(cursorPos, DelCharFromInputStr(cursorPos)); |
602 begin |
533 UpdateCursorCoords(); |
603 DoCursorStepForward(); |
534 end; |
604 dec(cursorPos, DelCharFromInputStr(cursorPos)); |
|
605 end; |
|
606 end |
|
607 else |
|
608 DeleteSelected(); |
|
609 UpdateCursorCoords(); |
535 end; |
610 end; |
536 SDLK_ESCAPE: |
611 SDLK_ESCAPE: |
537 begin |
612 begin |
538 if Length(InputStr.s) > 0 then |
613 if Length(InputStr.s) > 0 then |
539 begin |
614 begin |
567 else |
642 else |
568 begin |
643 begin |
569 SetLine(InputStr, LocalStrs[index], true); |
644 SetLine(InputStr, LocalStrs[index], true); |
570 InputStrL:= LocalStrsL[index]; |
645 InputStrL:= LocalStrsL[index]; |
571 end; |
646 end; |
572 // TODO rebuild/restore InputStrL!! |
|
573 cursorPos:= Length(InputStr.s); |
647 cursorPos:= Length(InputStr.s); |
|
648 ResetSelection(); |
574 UpdateCursorCoords(); |
649 UpdateCursorCoords(); |
575 end; |
650 end; |
576 SDLK_HOME: |
651 SDLK_HOME: |
577 begin |
652 begin |
578 if cursorPos > 0 then |
653 if cursorPos > 0 then |
579 begin |
654 begin |
|
655 HandleSelection(selMode); |
580 cursorPos:= 0; |
656 cursorPos:= 0; |
581 UpdateCursorCoords(); |
657 UpdateCursorCoords(); |
582 end; |
658 end; |
583 end; |
659 end; |
584 SDLK_END: |
660 SDLK_END: |
585 begin |
661 begin |
586 i:= Length(InputStr.s); |
662 i:= Length(InputStr.s); |
587 if cursorPos < i then |
663 if cursorPos < i then |
588 begin |
664 begin |
589 // TODO uft-8 |
665 HandleSelection(selMode); |
590 cursorPos:= i; |
666 cursorPos:= i; |
591 UpdateCursorCoords(); |
667 UpdateCursorCoords(); |
592 end; |
668 end; |
593 end; |
669 end; |
594 SDLK_LEFT: |
670 SDLK_LEFT: |
595 begin |
671 begin |
596 if cursorPos > 0 then |
672 if cursorPos > 0 then |
597 begin |
673 begin |
598 // go to end of previous utf8-char |
674 if selMode or (selectedPos < 0) then |
599 cursorPos:= InputStrL[cursorPos]; |
675 begin |
|
676 HandleSelection(selMode); |
|
677 // go to end of previous utf8-char |
|
678 cursorPos:= InputStrL[cursorPos]; |
|
679 end |
|
680 else // if we're leaving selection mode, jump to its left end |
|
681 begin |
|
682 cursorPos:= min(cursorPos, selectedPos); |
|
683 ResetSelection(); |
|
684 end; |
600 UpdateCursorCoords(); |
685 UpdateCursorCoords(); |
601 end; |
686 end; |
602 end; |
687 end; |
603 SDLK_RIGHT: |
688 SDLK_RIGHT: |
604 begin |
689 begin |
605 DoCursorStepForward(); |
690 if cursorPos < Length(InputStr.s) then |
606 UpdateCursorCoords(); |
691 begin |
|
692 if selMode or (selectedPos < 0) then |
|
693 begin |
|
694 HandleSelection(selMode); |
|
695 DoCursorStepForward(); |
|
696 end |
|
697 else // if we're leaving selection mode, jump to its right end |
|
698 begin |
|
699 cursorPos:= max(cursorPos, selectedPos); |
|
700 ResetSelection(); |
|
701 end; |
|
702 UpdateCursorCoords(); |
|
703 end; |
607 end; |
704 end; |
608 SDLK_PAGEUP, SDLK_PAGEDOWN: |
705 SDLK_PAGEUP, SDLK_PAGEDOWN: |
609 begin |
706 begin |
610 // ignore me!!! |
707 // ignore me!!! |
|
708 end; |
|
709 SDLK_a: |
|
710 begin |
|
711 // select all |
|
712 if ctrl then |
|
713 begin |
|
714 ResetSelection(); |
|
715 cursorPos:= Length(InputStr.s); |
|
716 HandleSelection(true); |
|
717 cursorPos:= 0; |
|
718 UpdateCursorCoords(); |
|
719 end |
|
720 else |
|
721 action:= false; |
611 end; |
722 end; |
612 else |
723 else |
613 action:= false; |
724 action:= false; |
614 end; |
725 end; |
615 if not action and (Key <> 0) then |
726 if not action and (Key <> 0) then |
616 begin |
727 begin |
|
728 DeleteSelected(); |
|
729 |
617 if (Key < $80) then |
730 if (Key < $80) then |
618 btw:= 1 |
731 btw:= 1 |
619 else if (Key < $800) then |
732 else if (Key < $800) then |
620 btw:= 2 |
733 btw:= 2 |
621 else if (Key < $10000) then |
734 else if (Key < $10000) then |