📄 keys.pas
字号:
unit keys;
{----------------------------------------------------------------------------}
{ }
{ File(s): keys.h,Keys.c - Input handling }
{ }
{ }
{ Initial conversion by : ggs (tazipper@lyocs.com) }
{ Initial conversion on : -Jan-2002 }
{ }
{ This File contains part of convertion of Quake2 source to ObjectPascal. }
{ More information about this project can be found at: }
{ http://www.sulaco.co.za/quake2/ }
{ }
{ Copyright (C) 1997-2001 Id Software, Inc. }
{ }
{ This program is free software; you can redistribute it and/or }
{ modify it under the terms of the GNU General Public License }
{ as published by the Free Software Foundation; either version 2 }
{ of the License, or (at your option) any later version. }
{ }
{ This program is distributed in the hope that it will be useful, }
{ but WITHOUT ANY WARRANTY; without even the implied warranty of }
{ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. }
{ }
{ See the GNU General Public License for more details. }
{ }
{----------------------------------------------------------------------------}
{ Updated on : 03-jun-2002 }
{ Updated by : Juha Hartikainen (juha@linearteam.org) }
{ - added needed units to uses clause }
{ - removed NODEPEND hack }
{}
{ Updated on : 04-jun-2002 }
{ Updated by : Juha Hartikainen (juha@linearteam.org) }
{ - Moved keydown variable to globalscopy as qmenu.pas needs it}
{}
{ Updated on : 05-jun-2002 }
{ Updated by : Juha Hartikainen (juha@linearteam.org) }
{ - conversion fixes}
{}
{ Updated on : 25-jul-2002 }
{ Updated by : burnin (leonel@linuxbr.com.br) }
{ - Uncommented menu calls }
{----------------------------------------------------------------------------}
{ Key.h is used by Clients.h }
{ Key.h is used by Clients.h }
{ * Still dependent (to compile correctly) on: }
{----------------------------------------------------------------------------}
{ * TODO: }
{----------------------------------------------------------------------------}
interface
uses
Windows, Client, q_shared;
const
//
// these are the key numbers that should be passed to Key_Event
//
K_TAB = 9;
K_ENTER = 13;
K_ESCAPE = 27;
K_SPACE = 32;
// normal keys should be passed as lowercased ascii
K_BACKSPACE = 127;
K_UPARROW = 128;
K_DOWNARROW = 129;
K_LEFTARROW = 130;
K_RIGHTARROW = 131;
K_ALT = 132;
K_CTRL = 133;
K_SHIFT = 134;
K_F1 = 135;
K_F2 = 136;
K_F3 = 137;
K_F4 = 138;
K_F5 = 139;
K_F6 = 140;
K_F7 = 141;
K_F8 = 142;
K_F9 = 143;
K_F10 = 144;
K_F11 = 145;
K_F12 = 146;
K_INS = 147;
K_DEL = 148;
K_PGDN = 149;
K_PGUP = 150;
K_HOME = 151;
K_END = 152;
K_KP_HOME = 160;
K_KP_UPARROW = 161;
K_KP_PGUP = 162;
K_KP_LEFTARROW = 163;
K_KP_5 = 164;
K_KP_RIGHTARROW = 165;
K_KP_END = 166;
K_KP_DOWNARROW = 167;
K_KP_PGDN = 168;
K_KP_ENTER = 169;
K_KP_INS = 170;
K_KP_DEL = 171;
K_KP_SLASH = 172;
K_KP_MINUS = 173;
K_KP_PLUS = 174;
K_PAUSE = 255;
//
// mouse buttons generate virtual keys
//
K_MOUSE1 = 200;
K_MOUSE2 = 201;
K_MOUSE3 = 202;
//
// joystick buttons
//
K_JOY1 = 203;
K_JOY2 = 204;
K_JOY3 = 205;
K_JOY4 = 206;
//
// aux keys are for multi-buttoned joysticks to generate so they can use
// the normal binding process
//
K_AUX1 = 207;
K_AUX2 = 208;
K_AUX3 = 209;
K_AUX4 = 210;
K_AUX5 = 211;
K_AUX6 = 212;
K_AUX7 = 213;
K_AUX8 = 214;
K_AUX9 = 215;
K_AUX10 = 216;
K_AUX11 = 217;
K_AUX12 = 218;
K_AUX13 = 219;
K_AUX14 = 220;
K_AUX15 = 221;
K_AUX16 = 222;
K_AUX17 = 223;
K_AUX18 = 224;
K_AUX19 = 225;
K_AUX20 = 226;
K_AUX21 = 227;
K_AUX22 = 228;
K_AUX23 = 229;
K_AUX24 = 230;
K_AUX25 = 231;
K_AUX26 = 232;
K_AUX27 = 233;
K_AUX28 = 234;
K_AUX29 = 235;
K_AUX30 = 236;
K_AUX31 = 237;
K_AUX32 = 238;
K_MWHEELDOWN = 239;
K_MWHEELUP = 240;
procedure Key_Event(key: integer; Down: qboolean; time: Longword);
procedure Key_Init;
procedure Key_WriteBindings(var f: integer);
procedure Key_SetBinding(keynum: integer; binding: Pchar);
procedure Key_ClearStates;
function Key_GetKey: integer;
function Key_KeynumToString(keynum: Integer): Pchar;
// variable that need to be put in the Interface section
var
chat_team: qboolean;
chat_buffer: array[0..255] of char;
chat_bufferlen: integer;
anykeydown: integer;
key_repeats: array[0..255] of Integer; // if > 1, it is autorepeating
keybindings: array[0..255] of Pchar; //char *keybindings[256];
keydown: array[0..255] of qboolean;
const
MaxCmdLine = 256;
var
key_lines: array[0..32-1, 0..MAXCMDLINE - 1] of char;
key_linepos: integer;
edit_line: integer = 0;
implementation
uses
Sysutils,
Cmd,
Common,
CVar,
Console,
sys_win,
cl_main,
menu,
cl_scrn;
// key up events are sent even if in console mode
var
shift_down: qBoolean = false; // int shift_down=false;
history_line: integer = 0;
key_waiting: integer;
consolekeys: array[0..255] of qboolean; // if true, can't be rebound while in console
menubound: array[0..255] of qboolean; // if true, can't be rebound while in menu
keyshift: array[0..255] of Integer; // key to map to if shift held down in console
type
keyname_p = ^keyname_t;
keyname_t = record
name: pchar;
keynum: integer;
end;
const
keynames: array[0..88] of keyname_t =
(
(name: 'TAB'; keynum: K_TAB),
(name: 'ENTER'; keynum: K_ENTER),
(name: 'ESCAPE'; keynum: K_ESCAPE),
(name: 'SPACE'; keynum: K_SPACE),
(name: 'BACKSPACE'; keynum: K_BACKSPACE),
(name: 'UPARROW'; keynum: K_UPARROW),
(name: 'DOWNARROW'; keynum: K_DOWNARROW),
(name: 'LEFTARROW'; keynum: K_LEFTARROW),
(name: 'RIGHTARROW'; keynum: K_RIGHTARROW),
(name: 'ALT'; keynum: K_ALT),
(name: 'CTRL'; keynum: K_CTRL),
(name: 'SHIFT'; keynum: K_SHIFT),
(name: 'F1'; keynum: K_F1),
(name: 'F2'; keynum: K_F2),
(name: 'F3'; keynum: K_F3),
(name: 'F4'; keynum: K_F4),
(name: 'F5'; keynum: K_F5),
(name: 'F6'; keynum: K_F6),
(name: 'F7'; keynum: K_F7),
(name: 'F8'; keynum: K_F8),
(name: 'F9'; keynum: K_F9),
(name: 'F10'; keynum: K_F10),
(name: 'F11'; keynum: K_F11),
(name: 'F12'; keynum: K_F12),
(name: 'INS'; keynum: K_INS),
(name: 'DEL'; keynum: K_DEL),
(name: 'PGDN'; keynum: K_PGDN),
(name: 'PGUP'; keynum: K_PGUP),
(name: 'HOME'; keynum: K_HOME),
(name: 'END'; keynum: K_END),
(name: 'MOUSE1'; keynum: K_MOUSE1),
(name: 'MOUSE2'; keynum: K_MOUSE2),
(name: 'MOUSE3'; keynum: K_MOUSE3),
(name: 'JOY1'; keynum: K_JOY1),
(name: 'JOY2'; keynum: K_JOY2),
(name: 'JOY3'; keynum: K_JOY3),
(name: 'JOY4'; keynum: K_JOY4),
(name: 'AUX1'; keynum: K_AUX1),
(name: 'AUX2'; keynum: K_AUX2),
(name: 'AUX3'; keynum: K_AUX3),
(name: 'AUX4'; keynum: K_AUX4),
(name: 'AUX5'; keynum: K_AUX5),
(name: 'AUX6'; keynum: K_AUX6),
(name: 'AUX7'; keynum: K_AUX7),
(name: 'AUX8'; keynum: K_AUX8),
(name: 'AUX9'; keynum: K_AUX9),
(name: 'AUX10'; keynum: K_AUX10),
(name: 'AUX11'; keynum: K_AUX11),
(name: 'AUX12'; keynum: K_AUX12),
(name: 'AUX13'; keynum: K_AUX13),
(name: 'AUX14'; keynum: K_AUX14),
(name: 'AUX15'; keynum: K_AUX15),
(name: 'AUX16'; keynum: K_AUX16),
(name: 'AUX17'; keynum: K_AUX17),
(name: 'AUX18'; keynum: K_AUX18),
(name: 'AUX19'; keynum: K_AUX19),
(name: 'AUX20'; keynum: K_AUX20),
(name: 'AUX21'; keynum: K_AUX21),
(name: 'AUX22'; keynum: K_AUX22),
(name: 'AUX23'; keynum: K_AUX23),
(name: 'AUX24'; keynum: K_AUX24),
(name: 'AUX25'; keynum: K_AUX25),
(name: 'AUX26'; keynum: K_AUX26),
(name: 'AUX27'; keynum: K_AUX27),
(name: 'AUX28'; keynum: K_AUX28),
(name: 'AUX29'; keynum: K_AUX29),
(name: 'AUX30'; keynum: K_AUX30),
(name: 'AUX31'; keynum: K_AUX31),
(name: 'AUX32'; keynum: K_AUX32),
(name: 'KP_HOME'; keynum: K_KP_HOME),
(name: 'KP_UPARROW'; keynum: K_KP_UPARROW),
(name: 'KP_PGUP'; keynum: K_KP_PGUP),
(name: 'KP_LEFTARROW'; keynum: K_KP_LEFTARROW),
(name: 'KP_5'; keynum: K_KP_5),
(name: 'KP_RIGHTARROW'; keynum: K_KP_RIGHTARROW),
(name: 'KP_END'; keynum: K_KP_END),
(name: 'KP_DOWNARROW'; keynum: K_KP_DOWNARROW),
(name: 'KP_PGDN'; keynum: K_KP_PGDN),
(name: 'KP_ENTER'; keynum: K_KP_ENTER),
(name: 'KP_INS'; keynum: K_KP_INS),
(name: 'KP_DEL'; keynum: K_KP_DEL),
(name: 'KP_SLASH'; keynum: K_KP_SLASH),
(name: 'KP_MINUS'; keynum: K_KP_MINUS),
(name: 'KP_PLUS'; keynum: K_KP_PLUS),
(name: 'MWHEELUP'; keynum: K_MWHEELUP),
(name: 'MWHEELDOWN'; keynum: K_MWHEELDOWN),
(name: 'PAUSE'; keynum: K_PAUSE),
(name: 'SEMICOLON'; keynum: ord(';')), // because a raw semicolon seperates commands
(name: nil; keynum: - 1)
);
{
==============================================================================
LINE TYPING INTO THE CONSOLE
==============================================================================
}
procedure CompleteCommand;
var
s, cmd: Pchar; // s,cmd : String;
begin
// TODO : Conferm string handling translation
s := @key_lines[edit_line][1]; // key_lines[edit_line]+1; this works to, but isnt clear
if (s[0] = '/') or (s[0] = '\') then
Inc(s);
cmd := Cmd_CompleteCommand(s);
if cmd = nil then
cmd := Cvar_CompleteVariable(s);
if cmd <> nil then
begin
key_lines[edit_line][1] := '/';
strcopy(@key_lines[edit_line][2], cmd); // strcpy (key_lines[edit_line]+2, cmd);
key_linepos := strlen(cmd) + 2;
key_lines[edit_line][key_linepos] := ' ';
Inc(key_linepos);
key_lines[edit_line][key_linepos] := #0;
end;
end; {CompleteCommand}
{
====================
Key_Console
Interactive line editing and console scrollback
====================
void Key_Console (int key)
}
procedure Key_Console(Key: integer);
var
cbd: pchar;
Index: integer;
begin
case key of
K_KP_SLASH: key := Ord('/');
K_KP_MINUS: key := Ord('-');
K_KP_PLUS: key := Ord('+');
K_KP_HOME: key := Ord('7');
K_KP_UPARROW: key := Ord('8');
K_KP_PGUP: key := Ord('9');
K_KP_LEFTARROW: key := Ord('4');
K_KP_5: key := Ord('5');
K_KP_RIGHTARROW: key := Ord('6');
K_KP_END: key := Ord('1');
K_KP_DOWNARROW: key := Ord('2');
K_KP_PGDN: key := Ord('3');
K_KP_INS: key := Ord('0');
K_KP_DEL: key := Ord('.');
end; {case}
if ((UpCase(Char(key)) = 'V') and keydown[K_CTRL]) or
(((key = K_INS) or (key = K_KP_INS)) and keydown[K_SHIFT]) then
begin
cbd := Sys_GetClipboardData;
if cbd <> nil then
begin
// TODO : doesnt use the function result!
//StrScan( cbd, #10#13#08); // strtok( cbd, "\n\r\b" );
Index := strlen(cbd);
if Index + key_linepos >= MAXCMDLINE then
Index := MAXCMDLINE - key_linepos;
if Index > 0 then
begin
cbd[Index] := #0;
strcat(key_lines[edit_line], cbd);
Inc(key_linepos, Index);
end;
FreeMem(cbd);
end;
exit;
end;
if (key = Ord('l')) and keydown[K_CTRL] then
begin
Cbuf_AddText('clear'#10);
Exit;
end;
if (key = K_ENTER) or (key = K_KP_ENTER) then
begin
// backslash text are commands, else chat
if (key_lines[edit_line][1] = '\') or (key_lines[edit_line][1] = '/') then
Cbuf_AddText(@key_lines[edit_line][2]) //(key_lines[edit_line]+2) // skip the >
else
Cbuf_AddText(@key_lines[edit_line][1]); //(key_lines[edit_line]+1); // valid command
Cbuf_AddText(#10);
Com_Printf('%s'#10, [key_lines[edit_line]]); // Com_Printf ("%s\n",key_lines[edit_line]);
// edit_line := (edit_line + 1) & 31;
history_line := edit_line;
key_lines[edit_line][0] := ']';
key_linepos := 1;
// TODO -cDependancy : Unknown dependancy
if (cls.state = ca_disconnected) then
// force an update, because the command. may take some time
SCR_UpdateScreen();
exit;
end;
if key = K_TAB then
begin // command completion
CompleteCommand();
Exit;
end;
if (key = K_BACKSPACE) or (key = K_LEFTARROW) or (key = K_KP_LEFTARROW) or
((UpCase(char(key)) = 'H') and keydown[K_CTRL]) then
begin
if key_linepos > 1 then
Dec(key_linepos);
exit;
end;
if (key = K_UPARROW) or (key = K_KP_UPARROW) or
((UpCase(char(key)) = 'p') and keydown[K_CTRL]) then
begin
while (history_line <> edit_line) and (key_lines[history_line][1] <> #0) do
history_line := (history_line - 1) and 31;
if history_line = edit_line then
history_line := (edit_line + 1) and 31;
strcopy(key_lines[edit_line], key_lines[history_line]);
key_linepos := strlen(key_lines[edit_line]);
exit;
end;
if (key = K_DOWNARROW) or (key = K_KP_DOWNARROW) or
((UpCase(char(key)) = 'n') and keydown[K_CTRL]) then
begin
if history_line = edit_line then
exit;
while (history_line <> edit_line) and (key_lines[history_line][1] <> #0) do
history_line := (history_line + 1) and 31;
if history_line = edit_line then
begin
key_lines[edit_line][0] := ']';
key_linepos := 1;
end
else
begin
strcopy(key_lines[edit_line], key_lines[history_line]);
key_linepos := strlen(key_lines[edit_line]);
end;
exit;
end;
if (key = K_PGUP) or (key = K_KP_PGUP) then
begin
con.display := con.display - 2;
exit;
end;
if (key = K_PGDN) or (key = K_KP_PGDN) then
begin
con.display := con.display + 2;
if (con.display > con.current) then
con.display := con.current;
exit;
end;
if (key = K_HOME) or (key = K_KP_HOME) then
begin
con.display := con.current - con.totallines + 10;
exit;
end;
if (key = K_END) or (key = K_KP_END) then
begin
con.display := con.current;
exit;
end;
if (key < 32) or (key > 127) then
exit; // non printable
if (key_linepos < MAXCMDLINE - 1) then
begin
key_lines[edit_line][key_linepos] := Char(key);
Inc(key_linepos);
key_lines[edit_line][key_linepos] := #0;
end;
end; {Key_Console}
//============================================================================
procedure Key_Message(key: integer);
begin
if (key = K_ENTER) or (key = K_KP_ENTER) then
begin
if chat_team then
Cbuf_AddText('say_team "')
else
Cbuf_AddText('say "');
Cbuf_AddText(chat_buffer);
Cbuf_AddText('"'#10);
cls.key_dest := Client.key_game;
chat_bufferlen := 0;
chat_buffer[0] := #0;
exit;
end;
if (key = K_ESCAPE) then
begin
cls.key_dest := Client.key_game;
chat_bufferlen := 0;
chat_buffer[0] := #0;
exit;
end;
if (key < 32) or (key > 127) then
exit; // non printable
if (key = K_BACKSPACE) then
begin
if chat_bufferlen <> 0 then
begin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -