2
0
Эх сурвалжийг харах

Support non-lating Alt+char hotkeys in legacy terminals also

Ivan Sorokin 1 долоо хоног өмнө
parent
commit
a6c2ea2a98

+ 69 - 19
packages/rtl-console/src/unix/keyboard.pp

@@ -2460,6 +2460,10 @@ var
   k: TEnhancedKeyEvent;
   k: TEnhancedKeyEvent;
   UnicodeCodePoint: LongInt;
   UnicodeCodePoint: LongInt;
   i : dword;
   i : dword;
+  // Variables for Alt+UTF8 sequence handling
+  ch1: AnsiChar;
+  utf8_bytes_to_read, loop_idx: Integer;
+  full_sequence_ok: boolean;
 begin
 begin
 {Check Buffer first}
 {Check Buffer first}
   if KeySend<>KeyPut then
   if KeySend<>KeyPut then
@@ -2570,29 +2574,67 @@ begin
                 end;
                 end;
             end;
             end;
 
 
-       NPT:=FoundNPT;
-       if assigned(NPT) and NPT^.CanBeTerminal then
+        if not assigned(FoundNPT) then
         begin
         begin
-          if assigned(NPT^.SpecialHandler) then
-            begin
-              NPT^.SpecialHandler;
-              k.AsciiChar := #0;
-              k.UnicodeChar := WideChar(#0);
-              k.VirtualScanCode := 0;
-              PushKey(k);
-            end
-          else if (NPT^.CharValue<>0) or (NPT^.ScanValue<>0) then
+          // This handles the case for non-kitty terminals sending ESC + UTF-8 bytes for Alt+key
+          if (arrayind > 1) and (store[0] = #27) and not isKittyKeys then
+          begin
+            ch1 := store[1];
+            utf8_bytes_to_read := DetectUtf8ByteSequenceStart(ch1) - 1;
+            full_sequence_ok := (arrayind - 1) = (utf8_bytes_to_read + 1);
+
+            if full_sequence_ok then
             begin
             begin
-              k.AsciiChar := chr(NPT^.CharValue);
-              k.UnicodeChar := WideChar(NPT^.CharValue);
-              k.VirtualScanCode := (NPT^.ScanValue shl 8) or Ord(k.AsciiChar);
-              k.ShiftState:=k.ShiftState+NPT^.ShiftValue;
-              PushKey(k);
+              // Push continuation bytes back to be re-read by ReadUtf8
+              for loop_idx := arrayind - 1 downto 2 do
+                PutBackIntoInBuf(store[loop_idx]);
+
+              UnicodeCodePoint := ReadUtf8(ch1);
+
+              if UnicodeCodePoint > 0 then
+              begin
+                k.ShiftState := [essAlt];
+                k.VirtualScanCode := 0;
+
+                PushUnicodeKey(k, UnicodeCodePoint, ReplacementAsciiChar);
+                ReadKey := PopKey;
+                exit;
+              end
+              else
+              begin
+                // Failed to parse, push everything back as-is
+                PutBackIntoInBuf(ch1);
+                for loop_idx := 2 to arrayind - 1 do
+                  PutBackIntoInBuf(store[loop_idx]);
+              end;
             end;
             end;
+          end;
+          RestoreArray;
         end
         end
-      else
-        RestoreArray;
-   end;
+        else
+        NPT:=FoundNPT;
+        if assigned(NPT) and NPT^.CanBeTerminal then
+         begin
+           if assigned(NPT^.SpecialHandler) then
+             begin
+               NPT^.SpecialHandler;
+               k.AsciiChar := #0;
+               k.UnicodeChar := WideChar(#0);
+               k.VirtualScanCode := 0;
+               PushKey(k);
+             end
+           else if (NPT^.CharValue<>0) or (NPT^.ScanValue<>0) then
+             begin
+               k.AsciiChar := chr(NPT^.CharValue);
+               k.UnicodeChar := WideChar(NPT^.CharValue);
+               k.VirtualScanCode := (NPT^.ScanValue shl 8) or Ord(k.AsciiChar);
+               k.ShiftState:=k.ShiftState+NPT^.ShiftValue;
+               PushKey(k);
+             end;
+         end
+       else
+         RestoreArray;
+    end;
 {$ifdef logging}
 {$ifdef logging}
        writeln(f);
        writeln(f);
 {$endif logging}
 {$endif logging}
@@ -2798,6 +2840,14 @@ begin {main}
       exit;
       exit;
     end;
     end;
   SysGetEnhancedKeyEvent:=NilEnhancedKeyEvent;
   SysGetEnhancedKeyEvent:=NilEnhancedKeyEvent;
+  // FAST PATH for pre-constructed events from ReadKey's Alt+UTF8 logic
+  MyKey:=ReadKey;
+  if (MyKey.ShiftState <> []) and (MyKey.VirtualScanCode = 0) and (MyKey.UnicodeChar <> #0) then
+  begin
+    SysGetEnhancedKeyEvent := MyKey;
+    LastShiftState := MyKey.ShiftState;
+    exit;
+  end;
   MyKey:=ReadKey;
   MyKey:=ReadKey;
   MyChar:=MyKey.AsciiChar;
   MyChar:=MyKey.AsciiChar;
   MyUniChar:=MyKey.UnicodeChar;
   MyUniChar:=MyKey.UnicodeChar;