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 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; |
43 s: shortstring; |
45 s: shortstring; |
44 Color: TSDL_Color; |
46 Color: TSDL_Color; |
45 end; |
47 end; |
46 TChatCmd = (ccQuit, ccPause, ccFinish, ccShowHistory, ccFullScreen); |
48 TChatCmd = (ccQuit, ccPause, ccFinish, ccShowHistory, ccFullScreen); |
47 |
49 |
|
50 type TInputStrL = array[0..260] of byte; |
|
51 |
48 var Strs: array[0 .. MaxStrIndex] of TChatLine; |
52 var Strs: array[0 .. MaxStrIndex] of TChatLine; |
49 MStrs: array[0 .. MaxStrIndex] of shortstring; |
53 MStrs: array[0 .. MaxStrIndex] of shortstring; |
50 LocalStrs: array[0 .. MaxStrIndex] of shortstring; |
54 LocalStrs: array[0 .. MaxStrIndex] of shortstring; |
|
55 LocalStrsL: array[0 .. MaxStrIndex] of TInputStrL; |
51 missedCount: LongWord; |
56 missedCount: LongWord; |
52 lastStr: LongWord; |
57 lastStr: LongWord; |
53 localLastStr: LongInt; |
58 localLastStr: LongInt; |
54 history: LongInt; |
59 history: LongInt; |
55 visibleCount: LongWord; |
60 visibleCount: LongWord; |
56 InputStr: TChatLine; |
61 InputStr: TChatLine; |
57 InputStrL: array[0..260] of char; // for full str + 4-byte utf-8 char |
62 InputStrL: TInputStrL; // for full str + 4-byte utf-8 char |
58 ChatReady: boolean; |
63 ChatReady: boolean; |
59 showAll: boolean; |
64 showAll: boolean; |
60 liveLua: boolean; |
65 liveLua: boolean; |
61 ChatHidden: boolean; |
66 ChatHidden: boolean; |
|
67 firstDraw: boolean; |
|
68 InputLinePrefix: TChatLine; |
|
69 // cursor |
|
70 cursorPos, cursorX, selectedPos, selectionDx: LongInt; |
|
71 LastKeyPressTick: LongWord; |
|
72 |
62 |
73 |
63 const |
74 const |
|
75 InputStrLNoPred: byte = 255; |
|
76 |
64 colors: array[#0..#6] of TSDL_Color = ( |
77 colors: array[#0..#6] of TSDL_Color = ( |
65 (r:$FF; g:$FF; b:$FF; a:$FF), // unused, feel free to take it for anything |
78 (r:$FF; g:$FF; b:$FF; a:$FF), // unused, feel free to take it for anything |
66 (r:$FF; g:$FF; b:$FF; a:$FF), // chat message [White] |
79 (r:$FF; g:$FF; b:$FF; a:$FF), // chat message [White] |
67 (r:$FF; g:$00; b:$FF; a:$FF), // action message [Purple] |
80 (r:$FF; g:$00; b:$FF; a:$FF), // action message [Purple] |
68 (r:$90; g:$FF; b:$90; a:$FF), // join/leave message [Lime] |
81 (r:$90; g:$FF; b:$90; a:$FF), // join/leave message [Lime] |
202 left:= 4 - cScreenWidth div 2; |
295 left:= 4 - cScreenWidth div 2; |
203 top := 10 + visibleCount * ClHeight; // we start with input line (if any) |
296 top := 10 + visibleCount * ClHeight; // we start with input line (if any) |
204 |
297 |
205 // draw chat input line first and under all other lines |
298 // draw chat input line first and under all other lines |
206 if (GameState = gsChat) and (InputStr.Tex <> nil) then |
299 if (GameState = gsChat) and (InputStr.Tex <> nil) then |
|
300 begin |
|
301 CheckPasteBuffer(); |
|
302 |
|
303 if InputLinePrefix.Tex = nil then |
|
304 RenderChatLineTex(InputLinePrefix, InputLinePrefix.s); |
|
305 |
|
306 DrawTexture(left, top, InputLinePrefix.Tex); |
|
307 inc(left, InputLinePrefix.Width); |
207 DrawTexture(left, top, InputStr.Tex); |
308 DrawTexture(left, top, InputStr.Tex); |
208 |
309 |
|
310 if firstDraw then |
|
311 begin |
|
312 UpdateCursorCoords(); |
|
313 firstDraw:= false; |
|
314 end; |
|
315 |
|
316 if selectedPos < 0 then |
|
317 begin |
|
318 // draw cursor |
|
319 if ((RealTicks - LastKeyPressTick) and 512) < 256 then |
|
320 DrawLineOnScreen(left + cursorX, top + 2, left + cursorX, top + ClHeight - 2, 2.0, $00, $FF, $FF, $FF); |
|
321 end |
|
322 else // draw selection |
|
323 begin |
|
324 selRect.y:= top + 2; |
|
325 selRect.h:= clHeight - 4; |
|
326 if selectionDx < 0 then |
|
327 begin |
|
328 selRect.x:= left + cursorX + selectionDx; |
|
329 selRect.w:= -selectionDx; |
|
330 end |
|
331 else |
|
332 begin |
|
333 selRect.x:= left + cursorX; |
|
334 selRect.w:= selectionDx; |
|
335 end; |
|
336 |
|
337 DrawRect(selRect, $FF, $FF, $FF, $40, true); |
|
338 end; |
|
339 |
|
340 dec(left, InputLinePrefix.Width); |
|
341 |
|
342 |
|
343 if (Length(InputStr.s) > 0) and ((CursorPos = 1) or (CursorPos = 2)) then |
|
344 begin |
|
345 c:= InputStr.s[1]; |
|
346 if charIsForHogSpeech(c) then |
|
347 begin |
|
348 SpeechHogNumber:= 0; |
|
349 if Length(InputStr.s) > 1 then |
|
350 begin |
|
351 c:= InputStr.s[2]; |
|
352 if (c > '0') and (c < '9') then |
|
353 SpeechHogNumber:= byte(c) - 48; |
|
354 end; |
|
355 // default to current hedgehog (if own) or first hedgehog |
|
356 if SpeechHogNumber = 0 then |
|
357 begin |
|
358 if not CurrentTeam^.ExtDriven then |
|
359 SpeechHogNumber:= CurrentTeam^.CurrHedgehog + 1 |
|
360 else |
|
361 SpeechHogNumber:= 1; |
|
362 end; |
|
363 end; |
|
364 end |
|
365 else |
|
366 SpeechHogNumber:= -1; |
|
367 end |
|
368 else |
|
369 SpeechHogNumber:= -1; |
|
370 |
|
371 // draw chat lines |
209 if ((not ChatHidden) or showAll) and (UIDisplay <> uiNone) then |
372 if ((not ChatHidden) or showAll) and (UIDisplay <> uiNone) then |
210 begin |
373 begin |
211 if MissedCount <> 0 then // there are chat strings we missed, so print them now |
374 if MissedCount <> 0 then // there are chat strings we missed, so print them now |
212 begin |
375 begin |
213 for i:= 0 to MissedCount - 1 do |
376 for i:= 0 to MissedCount - 1 do |
408 {$ENDIF} |
573 {$ENDIF} |
409 GameState:= gsGame; |
574 GameState:= gsGame; |
410 ResetKbd; |
575 ResetKbd; |
411 end; |
576 end; |
412 |
577 |
413 procedure KeyPressChat(Key, Sym: Longword); |
578 procedure DelBytesFromInputStrBack(endIdx: integer; count: byte); |
|
579 var i, startIdx: integer; |
|
580 begin |
|
581 // nothing to do if count is 0 |
|
582 if count = 0 then |
|
583 exit; |
|
584 |
|
585 // first byte to delete |
|
586 startIdx:= endIdx - (count - 1); |
|
587 |
|
588 // delete bytes from string |
|
589 Delete(InputStr.s, startIdx, count); |
|
590 |
|
591 // wipe utf8 info for deleted char |
|
592 InputStrL[endIdx]:= InputStrLNoPred; |
|
593 |
|
594 // shift utf8 char info to reflect new string |
|
595 for i:= endIdx + 1 to Length(InputStr.s) + count do |
|
596 begin |
|
597 if InputStrL[i] <> InputStrLNoPred then |
|
598 begin |
|
599 InputStrL[i-count]:= InputStrL[i] - count; |
|
600 InputStrL[i]:= InputStrLNoPred; |
|
601 end; |
|
602 end; |
|
603 |
|
604 SetLine(InputStr, InputStr.s, true); |
|
605 end; |
|
606 |
|
607 // returns count of removed bytes |
|
608 function DelCharFromInputStr(idx: integer): integer; |
|
609 var btw: byte; |
|
610 begin |
|
611 // note: idx is always at last byte of utf8 chars. cuz relevant for InputStrL |
|
612 |
|
613 if (Length(InputStr.s) < 1) or (idx < 1) or (idx > Length(InputStr.s)) then |
|
614 exit(0); |
|
615 |
|
616 btw:= byte(idx) - InputStrL[idx]; |
|
617 |
|
618 DelCharFromInputStr:= btw; |
|
619 |
|
620 DelBytesFromInputStrBack(idx, btw); |
|
621 end; |
|
622 |
|
623 // unchecked |
|
624 procedure DoCursorStepForward(); |
|
625 begin |
|
626 // go to end of next utf8-char |
|
627 repeat |
|
628 inc(cursorPos); |
|
629 until InputStrL[cursorPos] <> InputStrLNoPred; |
|
630 end; |
|
631 |
|
632 procedure DeleteSelected(); |
|
633 begin |
|
634 if (selectedPos >= 0) and (cursorPos <> selectedPos) then |
|
635 begin |
|
636 DelBytesFromInputStrBack(max(cursorPos, selectedPos), abs(selectedPos-cursorPos)); |
|
637 cursorPos:= min(cursorPos, selectedPos); |
|
638 ResetSelection(); |
|
639 end; |
|
640 UpdateCursorCoords(); |
|
641 end; |
|
642 |
|
643 procedure HandleSelection(enabled: boolean); |
|
644 begin |
|
645 if enabled then |
|
646 begin |
|
647 if selectedPos < 0 then |
|
648 selectedPos:= cursorPos; |
|
649 end |
|
650 else |
|
651 ResetSelection(); |
|
652 end; |
|
653 |
|
654 type TCharSkip = ( none, wspace, numalpha, special ); |
|
655 |
|
656 function GetInputCharSkipClass(index: LongInt): TCharSkip; |
|
657 var c: char; |
|
658 begin |
|
659 // multi-byte chars counts as letter |
|
660 if (index > 1) and (InputStrL[index] <> index - 1) then |
|
661 exit(numalpha); |
|
662 |
|
663 c:= InputStr.s[index]; |
|
664 |
|
665 // non-ascii counts as letter |
|
666 if c > #127 then |
|
667 exit(numalpha); |
|
668 |
|
669 // low-ascii whitespaces and DEL |
|
670 if (c < #33) or (c = #127) then |
|
671 exit(wspace); |
|
672 |
|
673 // low-ascii special chars |
|
674 if c < #48 then |
|
675 exit(special); |
|
676 |
|
677 // digits |
|
678 if c < #58 then |
|
679 exit(numalpha); |
|
680 |
|
681 // make c upper-case |
|
682 if c > #96 then |
|
683 c:= char(byte(c) - 32); |
|
684 |
|
685 // letters |
|
686 if (c > #64) and (c < #90) then |
|
687 exit(numalpha); |
|
688 |
|
689 // remaining ascii are special chars |
|
690 exit(special); |
|
691 end; |
|
692 |
|
693 // skip from word to word, similar to Qt |
|
694 procedure SkipInputChars(skip: TCharSkip; backwards: boolean); |
|
695 begin |
|
696 if backwards then |
|
697 begin |
|
698 // skip trailing whitespace, similar to Qt |
|
699 while (skip = wspace) and (cursorPos > 0) do |
|
700 begin |
|
701 skip:= GetInputCharSkipClass(cursorPos); |
|
702 if skip = wspace then |
|
703 cursorPos:= InputStrL[cursorPos]; |
|
704 end; |
|
705 // skip same-type chars |
|
706 while (cursorPos > 0) and (GetInputCharSkipClass(cursorPos) = skip) do |
|
707 cursorPos:= InputStrL[cursorPos]; |
|
708 end |
|
709 else |
|
710 begin |
|
711 // skip same-type chars |
|
712 while cursorPos < Length(InputStr.s) do |
|
713 begin |
|
714 DoCursorStepForward(); |
|
715 if (GetInputCharSkipClass(cursorPos) <> skip) then |
|
716 begin |
|
717 // go back 1 char |
|
718 cursorPos:= InputStrL[cursorPos]; |
|
719 break; |
|
720 end; |
|
721 end; |
|
722 // skip trailing whitespace, similar to Qt |
|
723 while cursorPos < Length(InputStr.s) do |
|
724 begin |
|
725 DoCursorStepForward(); |
|
726 if (GetInputCharSkipClass(cursorPos) <> wspace) then |
|
727 begin |
|
728 // go back 1 char |
|
729 cursorPos:= InputStrL[cursorPos]; |
|
730 break; |
|
731 end; |
|
732 end; |
|
733 end; |
|
734 end; |
|
735 |
|
736 procedure CopyToClipboard(var newContent: shortstring); |
|
737 begin |
|
738 SendIPC(_S'y' + copy(newContent, 1, 253) + #0); |
|
739 end; |
|
740 |
|
741 procedure CopySelectionToClipboard(); |
|
742 var selection: shortstring; |
|
743 begin |
|
744 if selectedPos >= 0 then |
|
745 begin |
|
746 selection:= copy(InputStr.s, min(CursorPos, selectedPos) + 1, abs(CursorPos - selectedPos)); |
|
747 CopyToClipboard(selection); |
|
748 end; |
|
749 end; |
|
750 |
|
751 // TODO: honor utf8, don't break utf8 chars when shifting chars beyond limit |
|
752 procedure InsertIntoInputStr(s: shortstring); |
|
753 var i, l, il, lastc: integer; |
|
754 begin |
|
755 // safe length for string |
|
756 l:= min(MaxInputStrLen-cursorPos, Length(s)); |
|
757 s:= copy(s,1,l); |
|
758 |
|
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 |
|
777 Insert(s, InputStr.s, cursorPos + 1); |
|
778 if Length(InputStr.s) > MaxInputStrLen then |
|
779 InputStr.s[0]:= char(MaxInputStrLen); |
|
780 |
|
781 SetLine(InputStr, InputStr.s, true); |
|
782 |
|
783 // move cursor to end of inserted string |
|
784 lastc:= MaxInputStrLen; |
|
785 cursorPos:= min(lastc, cursorPos + l); |
|
786 UpdateCursorCoords(); |
|
787 end; |
|
788 |
|
789 procedure PasteFromClipboard(); |
|
790 begin |
|
791 SendIPC(_S'Y'); |
|
792 end; |
|
793 |
|
794 procedure CheckPasteBuffer(); |
|
795 begin |
|
796 if Length(ChatPasteBuffer) > 0 then |
|
797 begin |
|
798 InsertIntoInputStr(ChatPasteBuffer); |
|
799 ChatPasteBuffer:= ''; |
|
800 end; |
|
801 end; |
|
802 |
|
803 procedure KeyPressChat(Key, Sym: Longword; Modifier: Word); |
414 const firstByteMark: array[0..3] of byte = (0, $C0, $E0, $F0); |
804 const firstByteMark: array[0..3] of byte = (0, $C0, $E0, $F0); |
415 var i, btw, index: integer; |
805 var i, btw, index: integer; |
416 utf8: shortstring; |
806 utf8: shortstring; |
417 action: boolean; |
807 action, selMode, ctrl: boolean; |
418 begin |
808 skip: TCharSkip; |
|
809 begin |
|
810 LastKeyPressTick:= RealTicks; |
419 action:= true; |
811 action:= true; |
|
812 |
|
813 CheckPasteBuffer(); |
|
814 |
|
815 selMode:= (modifier and (KMOD_LSHIFT or KMOD_RSHIFT)) <> 0; |
|
816 ctrl:= (modifier and (KMOD_LCTRL or KMOD_RCTRL)) <> 0; |
|
817 skip:= none; |
|
818 |
420 case Sym of |
819 case Sym of |
421 SDLK_BACKSPACE: |
820 SDLK_BACKSPACE: |
422 begin |
821 begin |
|
822 if selectedPos < 0 then |
|
823 begin |
|
824 if ctrl then |
|
825 skip:= GetInputCharSkipClass(cursorPos); |
|
826 |
|
827 // remove char before cursor |
|
828 dec(cursorPos, DelCharFromInputStr(cursorPos)); |
|
829 |
|
830 // delete more if ctrl is held |
|
831 if ctrl and (selectedPos < 0) then |
|
832 begin |
|
833 HandleSelection(true); |
|
834 SkipInputChars(skip, true); |
|
835 DeleteSelected(); |
|
836 end |
|
837 else |
|
838 UpdateCursorCoords(); |
|
839 |
|
840 end |
|
841 else |
|
842 DeleteSelected(); |
|
843 end; |
|
844 SDLK_DELETE: |
|
845 begin |
|
846 if selectedPos < 0 then |
|
847 begin |
|
848 // remove char after cursor |
|
849 if cursorPos < Length(InputStr.s) then |
|
850 begin |
|
851 DoCursorStepForward(); |
|
852 if ctrl then |
|
853 skip:= GetInputCharSkipClass(cursorPos); |
|
854 |
|
855 // delete char |
|
856 dec(cursorPos, DelCharFromInputStr(cursorPos)); |
|
857 |
|
858 // delete more if ctrl is held |
|
859 if ctrl and (cursorPos < Length(InputStr.s)) then |
|
860 begin |
|
861 HandleSelection(true); |
|
862 SkipInputChars(skip, false); |
|
863 DeleteSelected(); |
|
864 end; |
|
865 end |
|
866 else |
|
867 UpdateCursorCoords(); |
|
868 end |
|
869 else |
|
870 DeleteSelected(); |
|
871 end; |
|
872 SDLK_ESCAPE: |
|
873 begin |
423 if Length(InputStr.s) > 0 then |
874 if Length(InputStr.s) > 0 then |
424 begin |
875 begin |
425 InputStr.s[0]:= InputStrL[byte(InputStr.s[0])]; |
876 SetLine(InputStr, '', true); |
426 SetLine(InputStr, InputStr.s, true) |
877 FillChar(InputStrL, sizeof(InputStrL), InputStrLNoPred); |
|
878 ResetCursor(); |
427 end |
879 end |
428 end; |
880 else CleanupInput |
429 SDLK_ESCAPE: |
881 end; |
|
882 SDLK_RETURN, SDLK_KP_ENTER: |
430 begin |
883 begin |
431 if Length(InputStr.s) > 0 then |
884 if Length(InputStr.s) > 0 then |
432 SetLine(InputStr, '', true) |
|
433 else CleanupInput |
|
434 end; |
|
435 SDLK_RETURN, SDLK_KP_ENTER: |
|
436 begin |
|
437 if Length(InputStr.s) > 0 then |
|
438 begin |
885 begin |
439 AcceptChatString(InputStr.s); |
886 AcceptChatString(InputStr.s); |
440 SetLine(InputStr, '', false) |
887 SetLine(InputStr, '', false); |
|
888 FillChar(InputStrL, sizeof(InputStrL), InputStrLNoPred); |
|
889 ResetCursor(); |
441 end; |
890 end; |
442 CleanupInput |
891 CleanupInput |
443 end; |
892 end; |
444 SDLK_UP, SDLK_DOWN: |
893 SDLK_UP, SDLK_DOWN: |
445 begin |
894 begin |
446 if (Sym = SDLK_UP) and (history < localLastStr) then inc(history); |
895 if (Sym = SDLK_UP) and (history < localLastStr) then inc(history); |
447 if (Sym = SDLK_DOWN) and (history > 0) then dec(history); |
896 if (Sym = SDLK_DOWN) and (history > 0) then dec(history); |
448 index:= localLastStr - history + 1; |
897 index:= localLastStr - history + 1; |
449 if (index > localLastStr) then |
898 if (index > localLastStr) then |
450 SetLine(InputStr, '', true) |
899 begin |
451 else SetLine(InputStr, LocalStrs[index], true) |
900 SetLine(InputStr, '', true); |
452 end; |
901 FillChar(InputStrL, sizeof(InputStrL), InputStrLNoPred); |
453 SDLK_RIGHT, SDLK_LEFT, SDLK_DELETE, |
902 end |
454 SDLK_HOME, SDLK_END, |
903 else |
|
904 begin |
|
905 SetLine(InputStr, LocalStrs[index], true); |
|
906 InputStrL:= LocalStrsL[index]; |
|
907 end; |
|
908 cursorPos:= Length(InputStr.s); |
|
909 ResetSelection(); |
|
910 UpdateCursorCoords(); |
|
911 end; |
|
912 SDLK_HOME: |
|
913 begin |
|
914 if cursorPos > 0 then |
|
915 begin |
|
916 HandleSelection(selMode); |
|
917 cursorPos:= 0; |
|
918 end |
|
919 else if (not selMode) then |
|
920 ResetSelection(); |
|
921 |
|
922 UpdateCursorCoords(); |
|
923 end; |
|
924 SDLK_END: |
|
925 begin |
|
926 i:= Length(InputStr.s); |
|
927 if cursorPos < i then |
|
928 begin |
|
929 HandleSelection(selMode); |
|
930 cursorPos:= i; |
|
931 end |
|
932 else if (not selMode) then |
|
933 ResetSelection(); |
|
934 |
|
935 UpdateCursorCoords(); |
|
936 end; |
|
937 SDLK_LEFT: |
|
938 begin |
|
939 if cursorPos > 0 then |
|
940 begin |
|
941 |
|
942 if ctrl then |
|
943 skip:= GetInputCharSkipClass(cursorPos); |
|
944 |
|
945 if selMode or (selectedPos < 0) then |
|
946 begin |
|
947 HandleSelection(selMode); |
|
948 // go to end of previous utf8-char |
|
949 cursorPos:= InputStrL[cursorPos]; |
|
950 end |
|
951 else // if we're leaving selection mode, jump to its left end |
|
952 begin |
|
953 cursorPos:= min(cursorPos, selectedPos); |
|
954 ResetSelection(); |
|
955 end; |
|
956 |
|
957 if ctrl then |
|
958 SkipInputChars(skip, true); |
|
959 |
|
960 end |
|
961 else if (not selMode) then |
|
962 ResetSelection(); |
|
963 |
|
964 UpdateCursorCoords(); |
|
965 end; |
|
966 SDLK_RIGHT: |
|
967 begin |
|
968 if cursorPos < Length(InputStr.s) then |
|
969 begin |
|
970 |
|
971 if selMode or (selectedPos < 0) then |
|
972 begin |
|
973 HandleSelection(selMode); |
|
974 DoCursorStepForward(); |
|
975 end |
|
976 else // if we're leaving selection mode, jump to its right end |
|
977 begin |
|
978 cursorPos:= max(cursorPos, selectedPos); |
|
979 ResetSelection(); |
|
980 end; |
|
981 |
|
982 if ctrl then |
|
983 SkipInputChars(GetInputCharSkipClass(cursorPos), false); |
|
984 |
|
985 end |
|
986 else if (not selMode) then |
|
987 ResetSelection(); |
|
988 |
|
989 UpdateCursorCoords(); |
|
990 end; |
455 SDLK_PAGEUP, SDLK_PAGEDOWN: |
991 SDLK_PAGEUP, SDLK_PAGEDOWN: |
456 begin |
992 begin |
457 // ignore me!!! |
993 // ignore me!!! |
|
994 end; |
|
995 SDLK_a: |
|
996 begin |
|
997 // select all |
|
998 if ctrl then |
|
999 begin |
|
1000 ResetSelection(); |
|
1001 cursorPos:= 0; |
|
1002 HandleSelection(true); |
|
1003 cursorPos:= Length(InputStr.s); |
|
1004 UpdateCursorCoords(); |
|
1005 end |
|
1006 else |
|
1007 action:= false; |
|
1008 end; |
|
1009 SDLK_c: |
|
1010 begin |
|
1011 // copy |
|
1012 if ctrl then |
|
1013 CopySelectionToClipboard() |
|
1014 else |
|
1015 action:= false; |
|
1016 end; |
|
1017 SDLK_v: |
|
1018 begin |
|
1019 // paste |
|
1020 if ctrl then |
|
1021 PasteFromClipboard() |
|
1022 else |
|
1023 action:= false; |
|
1024 end; |
|
1025 SDLK_x: |
|
1026 begin |
|
1027 // cut |
|
1028 if ctrl then |
|
1029 begin |
|
1030 CopySelectionToClipboard(); |
|
1031 DeleteSelected(); |
|
1032 end |
|
1033 else |
|
1034 action:= false; |
458 end; |
1035 end; |
459 else |
1036 else |
460 action:= false; |
1037 action:= false; |
461 end; |
1038 end; |
462 if not action and (Key <> 0) then |
1039 if not action and (Key <> 0) then |
463 begin |
1040 begin |
|
1041 DeleteSelected(); |
|
1042 |
464 if (Key < $80) then |
1043 if (Key < $80) then |
465 btw:= 1 |
1044 btw:= 1 |
466 else if (Key < $800) then |
1045 else if (Key < $800) then |
467 btw:= 2 |
1046 btw:= 2 |
468 else if (Key < $10000) then |
1047 else if (Key < $10000) then |