⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keys.pas

📁 雷神之锤2(Quake2)Delphi源码
💻 PAS
📖 第 1 页 / 共 2 页
字号:
      Dec(chat_bufferlen);
      chat_buffer[chat_bufferlen] := #0;
    end;
    exit;
  end;

  if (chat_bufferlen = sizeof(chat_buffer) - 1) then
    exit; // all full

  chat_buffer[chat_bufferlen] := Char(key);
  inc(chat_bufferlen);
  chat_buffer[chat_bufferlen] := #0;
end; {Key_Message}

//============================================================================

{
===================
Key_StringToKeynum

Returns a key number to be used to index keybindings[] by looking at
the given string.  Single ascii characters return themselves, while
the K_* names are matched up.
===================
int Key_StringToKeynum (char *str)
}

function Key_StringToKeynum(str: PChar): integer;
var
  kn: keyname_p;
begin
  if (str = nil) or (str[0] = #0) then
  begin
    Result := -1;
    exit;
  end;

  if str[1] = #0 then
  begin
    Result := Ord(str[0]);
    exit;
  end;

  kn := @keynames[0];
  while kn.name <> nil do
  begin
    // TODO -cDependancy : Check to see if Q_strcasecmp is case sensitive
 //   if StrIComp(str,kn.name) = 0 then // case insensitive version
    if StrComp(str, kn.name) = 0 then
    begin
      Result := kn.keynum;
      exit;
    end;
    Inc(kn);
  end;
  Result := -1;
end; {Key_StringToKeynum}

{
===================
Key_KeynumToString

Returns a string (either a single ascii char, or a K_* name) for the
given keynum.
FIXME: handle quote special (general escape sequence?)
===================
char *Key_KeynumToString (int keynum)
}
var // TODO : This Should be replaced with a delphi string!
  tinystr: array[0..1] of char = (' ', ' ');

function Key_KeynumToString(keynum: Integer): Pchar;
var
  kn: keyname_p;
begin
  if (keynum = -1) then
  begin
    result := '<KEY NOT FOUND>';
    exit;
  end;

  if (keynum > 32) and (keynum < 127) then
  begin // printable ascii
    tinystr[0] := Char(keynum);
    tinystr[1] := #0;
    result := tinystr;
    exit;
  end;

  kn := @keynames[0];
  while kn.name <> nil do
  begin
    if keynum = kn.keynum then
    begin
      Result := kn.name;
      exit;
    end;
    Inc(kn);
  end;
  Result := '<UNKNOWN KEYNUM>';
end; {Key_KeynumToString}

{
===================
Key_SetBinding
===================
void Key_SetBinding (int keynum, char *binding)
}

procedure Key_SetBinding(keynum: integer; binding: PChar);
var
  new: Pchar;
  size: integer;
begin
  if keynum = -1 then
    exit;

  // free old bindings
  if keybindings[keynum] <> nil then
  begin
    Z_Free(keybindings[keynum]);
    keybindings[keynum] := nil;
  end;

  // allocate memory for new binding
  size := strlen(binding);
  if size <> 0 then
  begin
    new := Z_Malloc(size + 1);
    strcopy(new, binding);
    new[size] := #0;
    keybindings[keynum] := new;
  end;
end; {Key_SetBinding}

{
===================
Key_Unbind_f
===================
void Key_Unbind_f (void)
}

procedure Key_Unbind_f; cdecl;
var
  B: integer;
  keystr: Pchar;
begin
  if Cmd_Argc <> 2 then
  begin
    Com_Printf('unbind <key> : remove commands from a key'#10, []);
    exit;
  end;

  keystr := Cmd_Argv(1);
  b := Key_StringToKeynum(keystr);
  if b = -1 then
  begin
    Com_Printf('"%d" isn''''t a valid key'#10, [keystr]);
    exit;
  end;
  Key_SetBinding(b, '');
end; {Key_Unbind_f}

procedure Key_Unbindall_f; cdecl;
var
  Index: integer;
begin
  for index := 0 to 255 do
    if keybindings[index] <> nil then
      Key_SetBinding(Index, '');
end; {Key_Unbindall_f}

{
===================
Key_Bind_f
===================
void Key_Bind_f (void)
}

procedure Key_Bind_f; cdecl;
var
  index, count, Keynum: integer;
  cmd: array[0..1023] of char;
  keystr: Pchar;
begin
  count := Cmd_Argc();

  if count < 2 then
  begin
    Com_Printf('bind <key> [command] : attach a command to a key'#10, []);
    exit;
  end;

  keystr := Cmd_Argv(1);
  Keynum := Key_StringToKeynum(keystr);
  if Keynum = -1 then
  begin
    Com_Printf('"%s" isn''t a valid key'#10, [keystr]);
    exit;
  end;

  if count = 2 then
  begin
    if (keybindings[Keynum] <> nil) then
      Com_Printf('"%s" = "%s"'#10, [keystr, keybindings[Keynum]])
    else
      Com_Printf('"%s" is not bound'#10, [Cmd_Argv(1)]);
    exit;
  end;

  // copy the rest of the command line
  cmd[0] := #0; // start out with a null string
  for index := 2 to count - 1 do
  begin
    strcat(cmd, Cmd_Argv(index));
    if index <> count - 1 then
      strcat(cmd, ' ');
  end;
  Key_SetBinding(Keynum, cmd);
end; {Key_Bind_f}

{
============
Key_WriteBindings

Writes lines containing "bind key value"
============
void Key_WriteBindings (FILE *f);
}

procedure Key_WriteBindings(var f: integer);
var
  Index: integer;
  tmp: string;
begin
  For index := 0 to 255 do
    if (keybindings[index] <> nil) and (keybindings[index][0] <> #0) then begin
      tmp := 'bind ' + Key_KeynumToString(index) + ' "' + keybindings[index] + '"' + #13#10;
      FileWrite(f, tmp[1], Length(tmp));
    end;
end; {Key_WriteBindings}

{
============
Key_Bindlist_f
============
void Key_Bindlist_f (void)
}

procedure Key_Bindlist_f; cdecl;
var
  Index: integer;
begin
  for index := 0 to 255 do
    if (keybindings[index] <> nil) and (keybindings[index][0] <> #0) then
      Com_Printf('%s "%s"'#10, [Key_KeynumToString(index), keybindings[index]]);
end; {Key_Bindlist_f}

{
===================
Key_Init
===================
void Key_Init (void);
}

procedure Key_Init;
var
  Index: integer;
begin
  for Index := 0 to 31 do
  begin
    key_lines[Index][0] := ']';
    key_lines[Index][1] := #0;
  end;
  key_linepos := 1;

  //
  // init ascii characters in console mode
  //
  for Index := 32 to 127 do
    consolekeys[Index] := true;
  consolekeys[K_ENTER] := true;
  consolekeys[K_KP_ENTER] := true;
  consolekeys[K_TAB] := true;
  consolekeys[K_LEFTARROW] := true;
  consolekeys[K_KP_LEFTARROW] := true;
  consolekeys[K_RIGHTARROW] := true;
  consolekeys[K_KP_RIGHTARROW] := true;
  consolekeys[K_UPARROW] := true;
  consolekeys[K_KP_UPARROW] := true;
  consolekeys[K_DOWNARROW] := true;
  consolekeys[K_KP_DOWNARROW] := true;
  consolekeys[K_BACKSPACE] := true;
  consolekeys[K_HOME] := true;
  consolekeys[K_KP_HOME] := true;
  consolekeys[K_END] := true;
  consolekeys[K_KP_END] := true;
  consolekeys[K_PGUP] := true;
  consolekeys[K_KP_PGUP] := true;
  consolekeys[K_PGDN] := true;
  consolekeys[K_KP_PGDN] := true;
  consolekeys[K_SHIFT] := true;
  consolekeys[K_INS] := true;
  consolekeys[K_KP_INS] := true;
  consolekeys[K_KP_DEL] := true;
  consolekeys[K_KP_SLASH] := true;
  consolekeys[K_KP_PLUS] := true;
  consolekeys[K_KP_MINUS] := true;
  consolekeys[K_KP_5] := true;

  consolekeys[Ord('`')] := false;
  consolekeys[Ord('~')] := false;

  for Index := 0 to 255 do
    keyshift[Index] := Index;
  for Index := ord('a') to ord('z') do
    keyshift[Index] := Index - Ord('a') + Ord('A');
  keyshift[Ord('1')] := Ord('!');
  keyshift[Ord('2')] := Ord('@');
  keyshift[Ord('3')] := Ord('#');
  keyshift[Ord('4')] := Ord('$');
  keyshift[Ord('5')] := Ord('%');
  keyshift[Ord('6')] := Ord('^');
  keyshift[Ord('7')] := Ord('&');
  keyshift[Ord('8')] := Ord('*');
  keyshift[Ord('9')] := Ord('(');
  keyshift[Ord('0')] := Ord(')');
  keyshift[Ord('-')] := Ord('_');
  keyshift[Ord('=')] := Ord('+');
  keyshift[Ord(',')] := Ord('<');
  keyshift[Ord('.')] := Ord('>');
  keyshift[Ord('/')] := Ord('?');
  keyshift[Ord(';')] := Ord(':');
  keyshift[Ord('''')] := Ord('"');
  keyshift[Ord('[')] := Ord('{');
  keyshift[Ord(']')] := Ord('}');
  keyshift[Ord('`')] := Ord('~');
  keyshift[Ord('\')] := Ord('|');

  menubound[K_ESCAPE] := true;
  for Index := 0 to 12 do
    menubound[K_F1 + Index] := true;

  //
  // register our functions
  //
  Cmd_AddCommand('bind', @Key_Bind_f);
  Cmd_AddCommand('unbind', @Key_Unbind_f);
  Cmd_AddCommand('unbindall', @Key_Unbindall_f);
  Cmd_AddCommand('bindlist', @Key_Bindlist_f);
end; {Key_Init}

{
===================
Key_Event

Called by the system between frames for both key up and key down events
Should NOT be called during an interrupt!
===================
void Key_Event (int key, qboolean down, unsigned time);
}

procedure Key_Event(key: integer; Down: qboolean; time: Longword);
var
  kb: pchar;
var
  cmd: array[0..1023] of char;
begin
  // hack for modal presses
  if key_waiting = -1 then
  begin
    if down then
      key_waiting := key;
    exit;
  end;

  // update auto-repeat status
  if down then
  begin
    Inc(key_repeats[key]);
    if (key <> K_BACKSPACE) and
      (key <> K_PAUSE) and
      (key <> K_PGUP) and
      (key <> K_KP_PGUP) and
      (key <> K_PGDN) and
      (key <> K_KP_PGDN) and
      (key_repeats[key] > 1) then
      exit; // ignore most autorepeats

    if (key >= 200) and (keybindings[key] = nil) then
      Com_Printf('%s is unbound, hit F4 to set.'#10, [Key_KeynumToString(key)]);
  end
  else
    key_repeats[key] := 0;

  if (key = K_SHIFT) then
    shift_down := down;

  // console key is hardcoded, so the user can never unbind it
  if (key = ord('`')) or (key = ord('~')) then
  begin
    if not down then
      exit;
    Con_ToggleConsole_f();
    exit;
  end;

  // any key during the attract mode will bring up the menu
  if cl.attractloop and (cls.key_dest <> Client.key_menu) and
    not ((key >= K_F1) and (key <= K_F12)) then
    key := K_ESCAPE;
  // menu key is hardcoded, so the user can never unbind it
  if key = K_ESCAPE then
  begin
    if not down then
      exit;
    if (cl.frame.playerstate.stats[STAT_LAYOUTS] <> 0) and (cls.key_dest = Client.key_game) then
    begin // put away help computer / inventory
      Cbuf_AddText('cmd putaway'#10);
      exit;
    end;

    case cls.key_dest of
      Client.key_message: Key_Message(key);
      Client.key_menu: M_Keydown(key);
      Client.key_game,
        Client.key_console: M_Menu_Main_f ();
    else
      Com_Error(ERR_FATAL, 'Bad cls.key_dest', []);
    end;
    exit;
  end;

  // track if any key is down for BUTTON_ANY
  keydown[key] := down;
  if down then
  begin
    if (key_repeats[key] = 1) then
      inc(anykeydown);
  end
  else
  begin
    Dec(anykeydown);
    if anykeydown < 0 then
      anykeydown := 0;
  end;

  //
  // key up events only generate commands if the game key binding is
  // a button command (leading + sign).  These will occur even in console mode,
  // to keep the character from continuing an action started before a console
  // switch.  Button commands include the kenum as a parameter, so multiple
  // downs can be matched with ups
  //
  if not down then
  begin
    kb := keybindings[key];
    if (kb <> nil) and (kb[0] = '+') then
    begin
      Com_sprintf(cmd, sizeof(cmd), '-%s %d %d'#10, [kb + 1, key, time]);
      Cbuf_AddText(@cmd[0]);
    end;
    if (keyshift[key] <> key) then
    begin
      kb := keybindings[keyshift[key]];
      if (kb <> nil) and (kb[0] = '+') then
      begin
        Com_sprintf(cmd, sizeof(cmd), '-%s %d %d'#10, [kb + 1, key, time]);
        Cbuf_AddText(@cmd[0]);
      end;
    end;
    exit;
  end;

  //
  // if not a consolekey, send to the interpreter no matter what mode is
  //
  if ((cls.key_dest = Client.key_menu) and menubound[key]) or
    ((cls.key_dest = Client.key_console) and (not consolekeys[key])) or
    ((cls.key_dest = Client.key_game) and ((cls.state = ca_active) or (not consolekeys[key]))) then
  begin
    kb := keybindings[key];
    if (kb <> nil) then
    begin
      if (kb[0] = '+') then
      begin
        // button commands add keynum and time as a parm
        Com_sprintf(cmd, sizeof(cmd), '%s %d %d'#10, [kb, key, time]);
        Cbuf_AddText(cmd);
      end
      else
      begin
        Cbuf_AddText(kb);
        Cbuf_AddText(#10);
      end;
    end;
    exit;
  end;

  if not down then
    exit; // other systems only care about key down events

  if shift_down then
    key := keyshift[key];
  case cls.key_dest of
    Client.key_message: Key_Message(key);
    Client.key_menu: M_Keydown (key);
    Client.key_game,
      Client.key_console: Key_Console(key);
  else
    Com_Error(ERR_FATAL, 'Bad cls.key_dest', []);
  end;
end; {Key_Event}

{
==========
Key_ClearStates
==========
void Key_ClearStates (void);
}

procedure Key_ClearStates;
var
  Index: integer;
begin
  anykeydown := 0;
  for index := 0 to 255 do
  begin
    if keydown[index] and (key_repeats[index] <> 0) then
      Key_Event(index, false, 0);
    keydown[index] := false;
    key_repeats[index] := 0;
  end;
end; {Key_ClearStates}

{
==========
Key_GetKey
==========
int Key_GetKey (void);
}

function Key_GetKey: integer;
begin
  key_waiting := -1;
  while key_waiting = -1 do
    Sys_SendKeyEvents;
  result := key_waiting;
end;

initialization
finalization
  // make sure the memory allocated for the key bindings is freed
  Key_Unbindall_f;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -