mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-23 12:52:46 +00:00
3b586fc0a6
The recent changes to key handling broke using escape to get out of the console (escape would toggle between console and menu). Thus take care of the menu (escape) part of the coupling FIXME by implementing a callback for the escape key (and removing key_togglemenu) and sorting out the escape key handling in console. Seems to work nicely
1376 lines
32 KiB
C
1376 lines
32 KiB
C
/*
|
|
keys.c
|
|
|
|
(description)
|
|
|
|
Copyright (C) 1996-1997 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.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to:
|
|
|
|
Free Software Foundation, Inc.
|
|
59 Temple Place - Suite 330
|
|
Boston, MA 02111-1307, USA
|
|
|
|
*/
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#ifdef HAVE_STRING_H
|
|
# include <string.h>
|
|
#endif
|
|
#ifdef HAVE_STRINGS_H
|
|
# include <strings.h>
|
|
#endif
|
|
|
|
#include <ctype.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "QF/cbuf.h"
|
|
#include "QF/cmd.h"
|
|
#include "QF/cvar.h"
|
|
#include "QF/darray.h"
|
|
#include "QF/dstring.h"
|
|
#include "QF/keys.h"
|
|
#include "QF/sys.h"
|
|
|
|
#include "compat.h"
|
|
#include "old_keys.h"
|
|
|
|
/* key up events are sent even if in console mode */
|
|
|
|
static keydest_t key_dest = key_console;
|
|
static keytarget_t key_targets[key_last];
|
|
VISIBLE knum_t key_toggleconsole = QFK_BACKQUOTE;
|
|
|
|
typedef struct {
|
|
keydest_callback_t *func;
|
|
void *data;
|
|
} keydest_callback_item_t;
|
|
|
|
typedef struct {
|
|
key_escape_t *func;
|
|
void *data;
|
|
} key_escape_item_t;
|
|
|
|
#define CALLBACK_CHUNK 16
|
|
static struct DARRAY_TYPE(keydest_callback_item_t) keydest_callbacks = {
|
|
.grow = CALLBACK_CHUNK
|
|
};
|
|
static struct DARRAY_TYPE(key_escape_item_t) key_escape_callbacks = {
|
|
.grow = CALLBACK_CHUNK
|
|
};
|
|
|
|
VISIBLE int keydown[QFK_LAST];
|
|
|
|
static int keyhelp;
|
|
static cbuf_t *cbuf;
|
|
|
|
static const char *keydest_names[] = {
|
|
"key_unfocused",
|
|
"key_game",
|
|
"key_demo",
|
|
"key_console",
|
|
"key_message",
|
|
"key_menu",
|
|
|
|
"key_last"
|
|
};
|
|
|
|
|
|
typedef struct {
|
|
const char *name;
|
|
imt_t imtnum;
|
|
} imtname_t;
|
|
|
|
typedef struct {
|
|
const char *name;
|
|
knum_t keynum;
|
|
} keyname_t;
|
|
|
|
keyname_t keynames[] = {
|
|
{ "K_UNKNOWN", QFK_UNKNOWN },
|
|
{ "K_FIRST", QFK_FIRST },
|
|
{ "K_BACKSPACE", QFK_BACKSPACE },
|
|
{ "K_TAB", QFK_TAB },
|
|
{ "K_CLEAR", QFK_CLEAR },
|
|
{ "K_RETURN", QFK_RETURN },
|
|
{ "K_PAUSE", QFK_PAUSE },
|
|
{ "K_ESCAPE", QFK_ESCAPE },
|
|
{ "K_SPACE", QFK_SPACE },
|
|
{ "K_EXCLAIM", QFK_EXCLAIM },
|
|
{ "K_QUOTEDBL", QFK_QUOTEDBL },
|
|
{ "K_HASH", QFK_HASH },
|
|
{ "K_DOLLAR", QFK_DOLLAR },
|
|
{ "K_PERCENT", QFK_PERCENT },
|
|
{ "K_AMPERSAND", QFK_AMPERSAND },
|
|
{ "K_QUOTE", QFK_QUOTE },
|
|
{ "K_LEFTPAREN", QFK_LEFTPAREN },
|
|
{ "K_RIGHTPAREN", QFK_RIGHTPAREN },
|
|
{ "K_ASTERISK", QFK_ASTERISK },
|
|
{ "K_PLUS", QFK_PLUS },
|
|
{ "K_COMMA", QFK_COMMA },
|
|
{ "K_MINUS", QFK_MINUS },
|
|
{ "K_PERIOD", QFK_PERIOD },
|
|
{ "K_SLASH", QFK_SLASH },
|
|
{ "K_0", QFK_0 },
|
|
{ "K_1", QFK_1 },
|
|
{ "K_2", QFK_2 },
|
|
{ "K_3", QFK_3 },
|
|
{ "K_4", QFK_4 },
|
|
{ "K_5", QFK_5 },
|
|
{ "K_6", QFK_6 },
|
|
{ "K_7", QFK_7 },
|
|
{ "K_8", QFK_8 },
|
|
{ "K_9", QFK_9 },
|
|
{ "K_COLON", QFK_COLON },
|
|
{ "K_SEMICOLON", QFK_SEMICOLON },
|
|
{ "K_LESS", QFK_LESS },
|
|
{ "K_EQUALS", QFK_EQUALS },
|
|
{ "K_GREATER", QFK_GREATER },
|
|
{ "K_QUESTION", QFK_QUESTION },
|
|
{ "K_AT", QFK_AT },
|
|
{ "K_LEFTBRACKET", QFK_LEFTBRACKET },
|
|
{ "K_BACKSLASH", QFK_BACKSLASH },
|
|
{ "K_RIGHTBRACKET", QFK_RIGHTBRACKET },
|
|
{ "K_CARET", QFK_CARET },
|
|
{ "K_UNDERSCORE", QFK_UNDERSCORE },
|
|
{ "K_BACKQUOTE", QFK_BACKQUOTE },
|
|
{ "K_a", QFK_a },
|
|
{ "K_b", QFK_b },
|
|
{ "K_c", QFK_c },
|
|
{ "K_d", QFK_d },
|
|
{ "K_e", QFK_e },
|
|
{ "K_f", QFK_f },
|
|
{ "K_g", QFK_g },
|
|
{ "K_h", QFK_h },
|
|
{ "K_i", QFK_i },
|
|
{ "K_j", QFK_j },
|
|
{ "K_k", QFK_k },
|
|
{ "K_l", QFK_l },
|
|
{ "K_m", QFK_m },
|
|
{ "K_n", QFK_n },
|
|
{ "K_o", QFK_o },
|
|
{ "K_p", QFK_p },
|
|
{ "K_q", QFK_q },
|
|
{ "K_r", QFK_r },
|
|
{ "K_s", QFK_s },
|
|
{ "K_t", QFK_t },
|
|
{ "K_u", QFK_u },
|
|
{ "K_v", QFK_v },
|
|
{ "K_w", QFK_w },
|
|
{ "K_x", QFK_x },
|
|
{ "K_y", QFK_y },
|
|
{ "K_z", QFK_z },
|
|
{ "K_BRACELEFT", QFK_BRACELEFT },
|
|
{ "K_BAR", QFK_BAR },
|
|
{ "K_BRACERIGHT", QFK_BRACERIGHT },
|
|
{ "K_ASCIITILDE", QFK_ASCIITILDE },
|
|
{ "K_DELETE", QFK_DELETE },
|
|
{ "K_WORLD_0", QFK_WORLD_0 },
|
|
{ "K_WORLD_1", QFK_WORLD_1 },
|
|
{ "K_WORLD_2", QFK_WORLD_2 },
|
|
{ "K_WORLD_3", QFK_WORLD_3 },
|
|
{ "K_WORLD_4", QFK_WORLD_4 },
|
|
{ "K_WORLD_5", QFK_WORLD_5 },
|
|
{ "K_WORLD_6", QFK_WORLD_6 },
|
|
{ "K_WORLD_7", QFK_WORLD_7 },
|
|
{ "K_WORLD_8", QFK_WORLD_8 },
|
|
{ "K_WORLD_9", QFK_WORLD_9 },
|
|
{ "K_WORLD_10", QFK_WORLD_10 },
|
|
{ "K_WORLD_11", QFK_WORLD_11 },
|
|
{ "K_WORLD_12", QFK_WORLD_12 },
|
|
{ "K_WORLD_13", QFK_WORLD_13 },
|
|
{ "K_WORLD_14", QFK_WORLD_14 },
|
|
{ "K_WORLD_15", QFK_WORLD_15 },
|
|
{ "K_WORLD_16", QFK_WORLD_16 },
|
|
{ "K_WORLD_17", QFK_WORLD_17 },
|
|
{ "K_WORLD_18", QFK_WORLD_18 },
|
|
{ "K_WORLD_19", QFK_WORLD_19 },
|
|
{ "K_WORLD_20", QFK_WORLD_20 },
|
|
{ "K_WORLD_21", QFK_WORLD_21 },
|
|
{ "K_WORLD_22", QFK_WORLD_22 },
|
|
{ "K_WORLD_23", QFK_WORLD_23 },
|
|
{ "K_WORLD_24", QFK_WORLD_24 },
|
|
{ "K_WORLD_25", QFK_WORLD_25 },
|
|
{ "K_WORLD_26", QFK_WORLD_26 },
|
|
{ "K_WORLD_27", QFK_WORLD_27 },
|
|
{ "K_WORLD_28", QFK_WORLD_28 },
|
|
{ "K_WORLD_29", QFK_WORLD_29 },
|
|
{ "K_WORLD_30", QFK_WORLD_30 },
|
|
{ "K_WORLD_31", QFK_WORLD_31 },
|
|
{ "K_WORLD_32", QFK_WORLD_32 },
|
|
{ "K_WORLD_33", QFK_WORLD_33 },
|
|
{ "K_WORLD_34", QFK_WORLD_34 },
|
|
{ "K_WORLD_35", QFK_WORLD_35 },
|
|
{ "K_WORLD_36", QFK_WORLD_36 },
|
|
{ "K_WORLD_37", QFK_WORLD_37 },
|
|
{ "K_WORLD_38", QFK_WORLD_38 },
|
|
{ "K_WORLD_39", QFK_WORLD_39 },
|
|
{ "K_WORLD_40", QFK_WORLD_40 },
|
|
{ "K_WORLD_41", QFK_WORLD_41 },
|
|
{ "K_WORLD_42", QFK_WORLD_42 },
|
|
{ "K_WORLD_43", QFK_WORLD_43 },
|
|
{ "K_WORLD_44", QFK_WORLD_44 },
|
|
{ "K_WORLD_45", QFK_WORLD_45 },
|
|
{ "K_WORLD_46", QFK_WORLD_46 },
|
|
{ "K_WORLD_47", QFK_WORLD_47 },
|
|
{ "K_WORLD_48", QFK_WORLD_48 },
|
|
{ "K_WORLD_49", QFK_WORLD_49 },
|
|
{ "K_WORLD_50", QFK_WORLD_50 },
|
|
{ "K_WORLD_51", QFK_WORLD_51 },
|
|
{ "K_WORLD_52", QFK_WORLD_52 },
|
|
{ "K_WORLD_53", QFK_WORLD_53 },
|
|
{ "K_WORLD_54", QFK_WORLD_54 },
|
|
{ "K_WORLD_55", QFK_WORLD_55 },
|
|
{ "K_WORLD_56", QFK_WORLD_56 },
|
|
{ "K_WORLD_57", QFK_WORLD_57 },
|
|
{ "K_WORLD_58", QFK_WORLD_58 },
|
|
{ "K_WORLD_59", QFK_WORLD_59 },
|
|
{ "K_WORLD_60", QFK_WORLD_60 },
|
|
{ "K_WORLD_61", QFK_WORLD_61 },
|
|
{ "K_WORLD_62", QFK_WORLD_62 },
|
|
{ "K_WORLD_63", QFK_WORLD_63 },
|
|
{ "K_WORLD_64", QFK_WORLD_64 },
|
|
{ "K_WORLD_65", QFK_WORLD_65 },
|
|
{ "K_WORLD_66", QFK_WORLD_66 },
|
|
{ "K_WORLD_67", QFK_WORLD_67 },
|
|
{ "K_WORLD_68", QFK_WORLD_68 },
|
|
{ "K_WORLD_69", QFK_WORLD_69 },
|
|
{ "K_WORLD_70", QFK_WORLD_70 },
|
|
{ "K_WORLD_71", QFK_WORLD_71 },
|
|
{ "K_WORLD_72", QFK_WORLD_72 },
|
|
{ "K_WORLD_73", QFK_WORLD_73 },
|
|
{ "K_WORLD_74", QFK_WORLD_74 },
|
|
{ "K_WORLD_75", QFK_WORLD_75 },
|
|
{ "K_WORLD_76", QFK_WORLD_76 },
|
|
{ "K_WORLD_77", QFK_WORLD_77 },
|
|
{ "K_WORLD_78", QFK_WORLD_78 },
|
|
{ "K_WORLD_79", QFK_WORLD_79 },
|
|
{ "K_WORLD_80", QFK_WORLD_80 },
|
|
{ "K_WORLD_81", QFK_WORLD_81 },
|
|
{ "K_WORLD_82", QFK_WORLD_82 },
|
|
{ "K_WORLD_83", QFK_WORLD_83 },
|
|
{ "K_WORLD_84", QFK_WORLD_84 },
|
|
{ "K_WORLD_85", QFK_WORLD_85 },
|
|
{ "K_WORLD_86", QFK_WORLD_86 },
|
|
{ "K_WORLD_87", QFK_WORLD_87 },
|
|
{ "K_WORLD_88", QFK_WORLD_88 },
|
|
{ "K_WORLD_89", QFK_WORLD_89 },
|
|
{ "K_WORLD_90", QFK_WORLD_90 },
|
|
{ "K_WORLD_91", QFK_WORLD_91 },
|
|
{ "K_WORLD_92", QFK_WORLD_92 },
|
|
{ "K_WORLD_93", QFK_WORLD_93 },
|
|
{ "K_WORLD_94", QFK_WORLD_94 },
|
|
{ "K_WORLD_95", QFK_WORLD_95 },
|
|
{ "K_KP0", QFK_KP0 },
|
|
{ "K_KP1", QFK_KP1 },
|
|
{ "K_KP2", QFK_KP2 },
|
|
{ "K_KP3", QFK_KP3 },
|
|
{ "K_KP4", QFK_KP4 },
|
|
{ "K_KP5", QFK_KP5 },
|
|
{ "K_KP6", QFK_KP6 },
|
|
{ "K_KP7", QFK_KP7 },
|
|
{ "K_KP8", QFK_KP8 },
|
|
{ "K_KP9", QFK_KP9 },
|
|
{ "K_KP_PERIOD", QFK_KP_PERIOD },
|
|
{ "K_KP_DIVIDE", QFK_KP_DIVIDE },
|
|
{ "K_KP_MULTIPLY", QFK_KP_MULTIPLY },
|
|
{ "K_KP_MINUS", QFK_KP_MINUS },
|
|
{ "K_KP_PLUS", QFK_KP_PLUS },
|
|
{ "K_KP_ENTER", QFK_KP_ENTER },
|
|
{ "K_KP_EQUALS", QFK_KP_EQUALS },
|
|
{ "K_UP", QFK_UP },
|
|
{ "K_DOWN", QFK_DOWN },
|
|
{ "K_RIGHT", QFK_RIGHT },
|
|
{ "K_LEFT", QFK_LEFT },
|
|
{ "K_INSERT", QFK_INSERT },
|
|
{ "K_HOME", QFK_HOME },
|
|
{ "K_END", QFK_END },
|
|
{ "K_PAGEUP", QFK_PAGEUP },
|
|
{ "K_PAGEDOWN", QFK_PAGEDOWN },
|
|
{ "K_F1", QFK_F1 },
|
|
{ "K_F2", QFK_F2 },
|
|
{ "K_F3", QFK_F3 },
|
|
{ "K_F4", QFK_F4 },
|
|
{ "K_F5", QFK_F5 },
|
|
{ "K_F6", QFK_F6 },
|
|
{ "K_F7", QFK_F7 },
|
|
{ "K_F8", QFK_F8 },
|
|
{ "K_F9", QFK_F9 },
|
|
{ "K_F10", QFK_F10 },
|
|
{ "K_F11", QFK_F11 },
|
|
{ "K_F12", QFK_F12 },
|
|
{ "K_F13", QFK_F13 },
|
|
{ "K_F14", QFK_F14 },
|
|
{ "K_F15", QFK_F15 },
|
|
{ "K_F16", QFK_F16 },
|
|
{ "K_F17", QFK_F17 },
|
|
{ "K_F18", QFK_F18 },
|
|
{ "K_F19", QFK_F19 },
|
|
{ "K_F20", QFK_F20 },
|
|
{ "K_F21", QFK_F21 },
|
|
{ "K_F22", QFK_F22 },
|
|
{ "K_F23", QFK_F23 },
|
|
{ "K_F24", QFK_F24 },
|
|
{ "K_F25", QFK_F25 },
|
|
{ "K_F26", QFK_F26 },
|
|
{ "K_F27", QFK_F27 },
|
|
{ "K_F28", QFK_F28 },
|
|
{ "K_F29", QFK_F29 },
|
|
{ "K_F30", QFK_F30 },
|
|
{ "K_F31", QFK_F31 },
|
|
{ "K_F32", QFK_F32 },
|
|
{ "K_F33", QFK_F33 },
|
|
{ "K_F34", QFK_F34 },
|
|
{ "K_F35", QFK_F35 },
|
|
{ "K_F36", QFK_F36 },
|
|
{ "K_F37", QFK_F37 },
|
|
{ "K_F38", QFK_F38 },
|
|
{ "K_F39", QFK_F39 },
|
|
{ "K_F40", QFK_F40 },
|
|
{ "K_F41", QFK_F41 },
|
|
{ "K_F42", QFK_F42 },
|
|
{ "K_F43", QFK_F43 },
|
|
{ "K_F44", QFK_F44 },
|
|
{ "K_F45", QFK_F45 },
|
|
{ "K_F46", QFK_F46 },
|
|
{ "K_F47", QFK_F47 },
|
|
{ "K_F48", QFK_F48 },
|
|
{ "K_NUMLOCK", QFK_NUMLOCK },
|
|
{ "K_CAPSLOCK", QFK_CAPSLOCK },
|
|
{ "K_SCROLLOCK", QFK_SCROLLOCK },
|
|
{ "K_RSHIFT", QFK_RSHIFT },
|
|
{ "K_LSHIFT", QFK_LSHIFT },
|
|
{ "K_RCTRL", QFK_RCTRL },
|
|
{ "K_LCTRL", QFK_LCTRL },
|
|
{ "K_RALT", QFK_RALT },
|
|
{ "K_LALT", QFK_LALT },
|
|
{ "K_RMETA", QFK_RMETA },
|
|
{ "K_LMETA", QFK_LMETA },
|
|
{ "K_LSUPER", QFK_LSUPER },
|
|
{ "K_RSUPER", QFK_RSUPER },
|
|
{ "K_MODE", QFK_MODE },
|
|
{ "K_COMPOSE", QFK_COMPOSE },
|
|
{ "K_HELP", QFK_HELP },
|
|
{ "K_PRINT", QFK_PRINT },
|
|
{ "K_SYSREQ", QFK_SYSREQ },
|
|
{ "K_BREAK", QFK_BREAK },
|
|
{ "K_MENU", QFK_MENU },
|
|
{ "K_POWER", QFK_POWER },
|
|
{ "K_EURO", QFK_EURO },
|
|
|
|
{ "K_KANJI", QFK_KANJI },
|
|
{ "K_MUHENKAN", QFK_MUHENKAN },
|
|
{ "K_HENKAN", QFK_HENKAN },
|
|
{ "K_ROMAJI", QFK_ROMAJI },
|
|
{ "K_HIRAGANA", QFK_HIRAGANA },
|
|
{ "K_KATAKANA", QFK_KATAKANA },
|
|
{ "K_HIRAGANA_KATAKANA", QFK_HIRAGANA_KATAKANA },
|
|
{ "K_ZENKAKU", QFK_ZENKAKU },
|
|
{ "K_HANKAKU", QFK_HANKAKU },
|
|
{ "K_ZENKAKU_HANKAKU", QFK_ZENKAKU_HANKAKU },
|
|
{ "K_TOUROKU", QFK_TOUROKU },
|
|
{ "K_MASSYO", QFK_MASSYO },
|
|
{ "K_KANA_LOCK", QFK_KANA_LOCK },
|
|
{ "K_KANA_SHIFT", QFK_KANA_SHIFT },
|
|
{ "K_EISU_SHIFT", QFK_EISU_SHIFT },
|
|
{ "K_EISU_TOGGLE", QFK_EISU_TOGGLE },
|
|
{ "K_KANJI_BANGOU", QFK_KANJI_BANGOU },
|
|
{ "K_ZEN_KOHO", QFK_ZEN_KOHO },
|
|
{ "K_MAE_KOHO", QFK_MAE_KOHO },
|
|
|
|
{ "K_HOMEPAGE", QFK_HOMEPAGE },
|
|
{ "K_SEARCH", QFK_SEARCH },
|
|
{ "K_MAIL", QFK_MAIL },
|
|
{ "K_FAVORITES", QFK_FAVORITES },
|
|
{ "K_AUDIOMUTE", QFK_AUDIOMUTE },
|
|
{ "K_AUDIOLOWERVOLUME", QFK_AUDIOLOWERVOLUME },
|
|
{ "K_AUDIORAISEVOLUME", QFK_AUDIORAISEVOLUME },
|
|
{ "K_AUDIOPLAY", QFK_AUDIOPLAY },
|
|
{ "K_CALCULATOR", QFK_CALCULATOR },
|
|
{ "K_UNDO", QFK_UNDO },
|
|
{ "K_REDO", QFK_REDO },
|
|
{ "K_NEW", QFK_NEW },
|
|
{ "K_RELOAD", QFK_RELOAD },
|
|
{ "K_OPEN", QFK_OPEN },
|
|
{ "K_CLOSE", QFK_CLOSE },
|
|
{ "K_REPLY", QFK_REPLY },
|
|
{ "K_MAILFORWARD", QFK_MAILFORWARD },
|
|
{ "K_SEND", QFK_SEND },
|
|
{ "K_SAVE", QFK_SAVE },
|
|
{ "K_BACK", QFK_BACK },
|
|
{ "K_FORWARD", QFK_FORWARD },
|
|
|
|
{ "M_BUTTON1", QFM_BUTTON1 },
|
|
{ "M_BUTTON2", QFM_BUTTON2 },
|
|
{ "M_BUTTON3", QFM_BUTTON3 },
|
|
{ "M_WHEEL_UP", QFM_WHEEL_UP },
|
|
{ "M_WHEEL_DOWN", QFM_WHEEL_DOWN },
|
|
{ "M_BUTTON6", QFM_BUTTON6 },
|
|
{ "M_BUTTON7", QFM_BUTTON7 },
|
|
{ "M_BUTTON8", QFM_BUTTON8 },
|
|
{ "M_BUTTON9", QFM_BUTTON9 },
|
|
{ "M_BUTTON10", QFM_BUTTON10 },
|
|
{ "M_BUTTON11", QFM_BUTTON11 },
|
|
{ "M_BUTTON12", QFM_BUTTON12 },
|
|
{ "M_BUTTON13", QFM_BUTTON13 },
|
|
{ "M_BUTTON14", QFM_BUTTON14 },
|
|
{ "M_BUTTON15", QFM_BUTTON15 },
|
|
{ "M_BUTTON16", QFM_BUTTON16 },
|
|
{ "M_BUTTON17", QFM_BUTTON17 },
|
|
{ "M_BUTTON18", QFM_BUTTON18 },
|
|
{ "M_BUTTON19", QFM_BUTTON19 },
|
|
{ "M_BUTTON20", QFM_BUTTON20 },
|
|
{ "M_BUTTON21", QFM_BUTTON21 },
|
|
{ "M_BUTTON22", QFM_BUTTON22 },
|
|
{ "M_BUTTON23", QFM_BUTTON23 },
|
|
{ "M_BUTTON24", QFM_BUTTON24 },
|
|
{ "M_BUTTON25", QFM_BUTTON25 },
|
|
{ "M_BUTTON26", QFM_BUTTON26 },
|
|
{ "M_BUTTON27", QFM_BUTTON27 },
|
|
{ "M_BUTTON28", QFM_BUTTON28 },
|
|
{ "M_BUTTON29", QFM_BUTTON29 },
|
|
{ "M_BUTTON30", QFM_BUTTON30 },
|
|
{ "M_BUTTON31", QFM_BUTTON31 },
|
|
{ "M_BUTTON32", QFM_BUTTON32 },
|
|
|
|
{ "J_BUTTON1", QFJ_BUTTON1 },
|
|
{ "J_BUTTON2", QFJ_BUTTON2 },
|
|
{ "J_BUTTON3", QFJ_BUTTON3 },
|
|
{ "J_BUTTON4", QFJ_BUTTON4 },
|
|
{ "J_BUTTON5", QFJ_BUTTON5 },
|
|
{ "J_BUTTON6", QFJ_BUTTON6 },
|
|
{ "J_BUTTON7", QFJ_BUTTON7 },
|
|
{ "J_BUTTON8", QFJ_BUTTON8 },
|
|
{ "J_BUTTON9", QFJ_BUTTON9 },
|
|
{ "J_BUTTON10", QFJ_BUTTON10 },
|
|
{ "J_BUTTON11", QFJ_BUTTON11 },
|
|
{ "J_BUTTON12", QFJ_BUTTON12 },
|
|
{ "J_BUTTON13", QFJ_BUTTON13 },
|
|
{ "J_BUTTON14", QFJ_BUTTON14 },
|
|
{ "J_BUTTON15", QFJ_BUTTON15 },
|
|
{ "J_BUTTON16", QFJ_BUTTON16 },
|
|
{ "J_BUTTON17", QFJ_BUTTON17 },
|
|
{ "J_BUTTON18", QFJ_BUTTON18 },
|
|
{ "J_BUTTON19", QFJ_BUTTON19 },
|
|
{ "J_BUTTON20", QFJ_BUTTON20 },
|
|
{ "J_BUTTON21", QFJ_BUTTON21 },
|
|
{ "J_BUTTON22", QFJ_BUTTON22 },
|
|
{ "J_BUTTON23", QFJ_BUTTON23 },
|
|
{ "J_BUTTON24", QFJ_BUTTON24 },
|
|
{ "J_BUTTON25", QFJ_BUTTON25 },
|
|
{ "J_BUTTON26", QFJ_BUTTON26 },
|
|
{ "J_BUTTON27", QFJ_BUTTON27 },
|
|
{ "J_BUTTON28", QFJ_BUTTON28 },
|
|
{ "J_BUTTON29", QFJ_BUTTON29 },
|
|
{ "J_BUTTON30", QFJ_BUTTON30 },
|
|
{ "J_BUTTON31", QFJ_BUTTON31 },
|
|
{ "J_BUTTON32", QFJ_BUTTON32 },
|
|
{ "J_BUTTON33", QFJ_BUTTON33 },
|
|
{ "J_BUTTON34", QFJ_BUTTON34 },
|
|
{ "J_BUTTON35", QFJ_BUTTON35 },
|
|
{ "J_BUTTON36", QFJ_BUTTON36 },
|
|
{ "J_BUTTON37", QFJ_BUTTON37 },
|
|
{ "J_BUTTON38", QFJ_BUTTON38 },
|
|
{ "J_BUTTON39", QFJ_BUTTON39 },
|
|
{ "J_BUTTON40", QFJ_BUTTON40 },
|
|
{ "J_BUTTON41", QFJ_BUTTON41 },
|
|
{ "J_BUTTON42", QFJ_BUTTON42 },
|
|
{ "J_BUTTON43", QFJ_BUTTON43 },
|
|
{ "J_BUTTON44", QFJ_BUTTON44 },
|
|
{ "J_BUTTON45", QFJ_BUTTON45 },
|
|
{ "J_BUTTON46", QFJ_BUTTON46 },
|
|
{ "J_BUTTON47", QFJ_BUTTON47 },
|
|
{ "J_BUTTON48", QFJ_BUTTON48 },
|
|
{ "J_BUTTON49", QFJ_BUTTON49 },
|
|
{ "J_BUTTON50", QFJ_BUTTON50 },
|
|
{ "J_BUTTON51", QFJ_BUTTON51 },
|
|
{ "J_BUTTON52", QFJ_BUTTON52 },
|
|
{ "J_BUTTON53", QFJ_BUTTON53 },
|
|
{ "J_BUTTON54", QFJ_BUTTON54 },
|
|
{ "J_BUTTON55", QFJ_BUTTON55 },
|
|
{ "J_BUTTON56", QFJ_BUTTON56 },
|
|
{ "J_BUTTON57", QFJ_BUTTON57 },
|
|
{ "J_BUTTON58", QFJ_BUTTON58 },
|
|
{ "J_BUTTON59", QFJ_BUTTON59 },
|
|
{ "J_BUTTON60", QFJ_BUTTON60 },
|
|
{ "J_BUTTON61", QFJ_BUTTON61 },
|
|
{ "J_BUTTON62", QFJ_BUTTON62 },
|
|
{ "J_BUTTON63", QFJ_BUTTON63 },
|
|
{ "J_BUTTON64", QFJ_BUTTON64 },
|
|
|
|
{ "J_AXIS1", QFJ_AXIS1 },
|
|
{ "J_AXIS2", QFJ_AXIS2 },
|
|
{ "J_AXIS3", QFJ_AXIS3 },
|
|
{ "J_AXIS4", QFJ_AXIS4 },
|
|
{ "J_AXIS5", QFJ_AXIS5 },
|
|
{ "J_AXIS6", QFJ_AXIS6 },
|
|
{ "J_AXIS7", QFJ_AXIS7 },
|
|
{ "J_AXIS8", QFJ_AXIS8 },
|
|
{ "J_AXIS9", QFJ_AXIS9 },
|
|
{ "J_AXIS10", QFJ_AXIS10 },
|
|
{ "J_AXIS11", QFJ_AXIS11 },
|
|
{ "J_AXIS12", QFJ_AXIS12 },
|
|
{ "J_AXIS13", QFJ_AXIS13 },
|
|
{ "J_AXIS14", QFJ_AXIS14 },
|
|
{ "J_AXIS15", QFJ_AXIS15 },
|
|
{ "J_AXIS16", QFJ_AXIS16 },
|
|
{ "J_AXIS17", QFJ_AXIS17 },
|
|
{ "J_AXIS18", QFJ_AXIS18 },
|
|
{ "J_AXIS19", QFJ_AXIS19 },
|
|
{ "J_AXIS20", QFJ_AXIS20 },
|
|
{ "J_AXIS21", QFJ_AXIS21 },
|
|
{ "J_AXIS22", QFJ_AXIS22 },
|
|
{ "J_AXIS23", QFJ_AXIS23 },
|
|
{ "J_AXIS24", QFJ_AXIS24 },
|
|
{ "J_AXIS25", QFJ_AXIS25 },
|
|
{ "J_AXIS26", QFJ_AXIS26 },
|
|
{ "J_AXIS27", QFJ_AXIS27 },
|
|
{ "J_AXIS28", QFJ_AXIS28 },
|
|
{ "J_AXIS29", QFJ_AXIS29 },
|
|
{ "J_AXIS30", QFJ_AXIS30 },
|
|
{ "J_AXIS31", QFJ_AXIS31 },
|
|
{ "J_AXIS32", QFJ_AXIS32 },
|
|
|
|
{NULL, 0}
|
|
};
|
|
|
|
static __attribute__((pure)) imt_t *
|
|
key_target_find_imt (keytarget_t *kt, const char *imt_name)
|
|
{
|
|
imt_t *imt;
|
|
for (imt = kt->imts; imt; imt = imt->next) {
|
|
if (!strcasecmp (imt->name, imt_name)) {
|
|
return imt;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
VISIBLE imt_t *
|
|
Key_FindIMT (const char *imt_name)
|
|
{
|
|
keydest_t kd;
|
|
imt_t *imt = 0;
|
|
|
|
for (kd = key_unfocused; !imt && kd < key_last; kd++) {
|
|
imt = key_target_find_imt (&key_targets[kd], imt_name);
|
|
}
|
|
return imt;
|
|
}
|
|
|
|
void
|
|
Key_CreateIMT (keydest_t kd, const char *imt_name, const char *chain_imt_name)
|
|
{
|
|
imt_t *imt;
|
|
imt_t *chain_imt = 0;
|
|
keytarget_t *kt = &key_targets[kd];
|
|
|
|
imt = Key_FindIMT (imt_name);
|
|
if (imt) {
|
|
Sys_Printf ("imt error: imt %s already exists\n", imt_name);
|
|
return;
|
|
}
|
|
if (chain_imt_name) {
|
|
chain_imt = Key_FindIMT (chain_imt_name);
|
|
if (!chain_imt) {
|
|
Sys_Printf ("imt error: chain imt %s does not exist\n",
|
|
chain_imt_name);
|
|
return;
|
|
}
|
|
imt = key_target_find_imt (kt, chain_imt_name);
|
|
if (!imt) {
|
|
Sys_Printf ("imt error: chain imt %s not on target key "
|
|
"destination\n", chain_imt_name);
|
|
return;
|
|
}
|
|
}
|
|
imt = calloc (1, sizeof (imt_t));
|
|
imt->name = strdup (imt_name);
|
|
imt->chain = chain_imt;
|
|
imt->next = kt->imts;
|
|
kt->imts = imt;
|
|
if (!kt->active) {
|
|
kt->active = imt;
|
|
}
|
|
}
|
|
|
|
VISIBLE void
|
|
Key_SetBinding (imt_t *imt, knum_t keynum, const char *binding)
|
|
{
|
|
if (keynum == (knum_t) -1)
|
|
return;
|
|
|
|
if (imt->bindings[keynum].str) {
|
|
free (imt->bindings[keynum].str);
|
|
imt->bindings[keynum].str = NULL;
|
|
}
|
|
if (binding) {
|
|
imt->bindings[keynum].str = strdup(binding);
|
|
}
|
|
}
|
|
|
|
static void
|
|
Key_CallDestCallbacks (keydest_t kd)
|
|
{
|
|
for (size_t i = 0; i < keydest_callbacks.size; i++) {
|
|
keydest_callback_item_t *cb = &keydest_callbacks.a[i];
|
|
cb->func (kd, cb->data);
|
|
}
|
|
}
|
|
|
|
static void
|
|
process_binding (knum_t key, const char *kb)
|
|
{
|
|
char cmd[1024];
|
|
|
|
if (kb[0] == '+') {
|
|
if (keydown[key])
|
|
snprintf (cmd, sizeof (cmd), "%s %d\n", kb, key);
|
|
else
|
|
snprintf (cmd, sizeof (cmd), "-%s %d\n", kb + 1, key);
|
|
} else {
|
|
if (!keydown[key])
|
|
return;
|
|
snprintf (cmd, sizeof (cmd), "%s\n", kb);
|
|
}
|
|
Cbuf_AddText (cbuf, cmd);
|
|
}
|
|
|
|
/*
|
|
Key_Game
|
|
|
|
Game key handling.
|
|
*/
|
|
static qboolean
|
|
Key_Game (knum_t key, short unicode)
|
|
{
|
|
const char *kb;
|
|
imt_t *imt = key_targets[key_dest].active;
|
|
|
|
while (imt) {
|
|
kb = imt->bindings[key].str;
|
|
if (kb) {
|
|
if (keydown[key] <= 1)
|
|
process_binding (key, kb);
|
|
return true;
|
|
}
|
|
imt = imt->chain;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
VISIBLE int
|
|
Key_StringToKeynum (const char *str)
|
|
{
|
|
keyname_t *kn;
|
|
|
|
if (!str || !str[0])
|
|
return -1;
|
|
|
|
for (kn = keynames; kn->name; kn++) {
|
|
if (!strcasecmp (str, kn->name))
|
|
return kn->keynum;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
VISIBLE const char *
|
|
Key_KeynumToString (knum_t keynum)
|
|
{
|
|
keyname_t *kn;
|
|
|
|
if (keynum == (knum_t) -1)
|
|
return "<KEY NOT FOUND>";
|
|
|
|
for (kn = keynames; kn->name; kn++)
|
|
if (keynum == kn->keynum)
|
|
return kn->name;
|
|
|
|
return "<UNKNOWN KEYNUM>";
|
|
}
|
|
|
|
static void
|
|
Key_In_Unbind (const char *imt_name, const char *key_name)
|
|
{
|
|
imt_t *imt;
|
|
int key;
|
|
|
|
imt = Key_FindIMT (imt_name);
|
|
if (!imt) {
|
|
Sys_Printf ("\"%s\" is not a valid imt\n", imt_name);
|
|
return;
|
|
}
|
|
|
|
key = Key_StringToKeynum (key_name);
|
|
if (key == -1) {
|
|
Sys_Printf ("\"%s\" is not a valid key\n", key_name);
|
|
return;
|
|
}
|
|
|
|
Key_SetBinding (imt, key, NULL);
|
|
}
|
|
|
|
static void
|
|
Key_In_Unbind_f (void)
|
|
{
|
|
if (Cmd_Argc () != 3) {
|
|
Sys_Printf ("in_unbind <imt> <key> : remove commands from a key\n");
|
|
return;
|
|
}
|
|
Key_In_Unbind (Cmd_Argv (1), Cmd_Argv (2));
|
|
}
|
|
|
|
static void
|
|
Key_Unbindall_f (void)
|
|
{
|
|
imt_t *imt;
|
|
int i;
|
|
|
|
imt = Key_FindIMT ("imt_mod");
|
|
if (imt) {
|
|
for (i = 0; i < QFK_LAST; i++) {
|
|
Key_SetBinding (imt, i, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
Key_In_Type_f (void)
|
|
{
|
|
const char *str, *p;
|
|
if (Cmd_Argc () != 2) {
|
|
Sys_Printf ("in_type <string>\n");
|
|
Sys_Printf (" Send the given string as simulated key presses.\n");
|
|
return;
|
|
}
|
|
str = Cmd_Argv (1);
|
|
for (p = str; *p; p++) {
|
|
Key_Event (QFK_UNKNOWN, *p, 1);
|
|
Key_Event (QFK_UNKNOWN, 0, 0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
Key_In_Clear (void)
|
|
{
|
|
int err = 0;
|
|
imt_t *imt;
|
|
int i, j;
|
|
|
|
if (Cmd_Argc () == 1) {
|
|
Sys_Printf ("in_clear <imt> ...\n");
|
|
return;
|
|
}
|
|
for (i = 1; i < Cmd_Argc (); i++) {
|
|
if (!Key_FindIMT (Cmd_Argv (i))) {
|
|
Sys_Printf ("\"%s\" is not a valid imt\n", Cmd_Argv (i));
|
|
err = 1;
|
|
}
|
|
}
|
|
if (err)
|
|
return;
|
|
for (i = 1; i < Cmd_Argc (); i++) {
|
|
imt = Key_FindIMT (Cmd_Argv (i));
|
|
for (j = 0; j < QFK_LAST; j++)
|
|
Key_SetBinding (imt, j, NULL);
|
|
}
|
|
}
|
|
|
|
static void
|
|
Key_IMT_Create_f (void)
|
|
{
|
|
const char *keydest;
|
|
const char *imt_name;
|
|
const char *chain_imt_name = 0;
|
|
keydest_t kd;
|
|
|
|
if (Cmd_Argc () < 3 || Cmd_Argc () > 4) {
|
|
Sys_Printf ("see help imt_create\n");
|
|
return;
|
|
}
|
|
keydest = Cmd_Argv (1);
|
|
imt_name = Cmd_Argv (2);
|
|
if (Cmd_Argc () == 4) {
|
|
chain_imt_name = Cmd_Argv (3);
|
|
}
|
|
for (kd = key_game; kd < key_last; kd++) {
|
|
if (!strcasecmp (keydest_names[kd], keydest)) {
|
|
break;
|
|
}
|
|
}
|
|
if (kd == key_last) {
|
|
Sys_Printf ("imt error: invalid keydest: %s\n", keydest);
|
|
return;
|
|
}
|
|
Key_CreateIMT (kd, imt_name, chain_imt_name);
|
|
}
|
|
|
|
static void
|
|
Key_IMT_Drop_All_f (void)
|
|
{
|
|
keydest_t kd;
|
|
imt_t *imt;
|
|
|
|
for (kd = key_unfocused; kd < key_last; kd++) {
|
|
while (key_targets[kd].imts) {
|
|
imt = key_targets[kd].imts;
|
|
key_targets[kd].imts = imt->next;
|
|
for (int i = 0; i < QFK_LAST; i++) {
|
|
if (imt->bindings[i].str) {
|
|
free (imt->bindings[i].str);
|
|
}
|
|
}
|
|
free ((char *) imt->name);
|
|
free (imt);
|
|
}
|
|
key_targets[kd].active = 0;
|
|
}
|
|
}
|
|
|
|
static void
|
|
Key_In_Bind (const char *imt_name, const char *key_name, const char *cmd)
|
|
{
|
|
imt_t *imt;
|
|
int key;
|
|
|
|
imt = Key_FindIMT (imt_name);
|
|
if (!imt) {
|
|
Sys_Printf ("\"%s\" is not a valid imt\n", imt_name);
|
|
return;
|
|
}
|
|
|
|
key = Key_StringToKeynum (key_name);
|
|
if (key == -1) {
|
|
Sys_Printf ("\"%s\" is not a valid key\n", key_name);
|
|
return;
|
|
}
|
|
|
|
if (!cmd) {
|
|
if (imt->bindings[key].str)
|
|
Sys_Printf ("%s %s \"%s\"\n", imt_name, key_name,
|
|
imt->bindings[key].str);
|
|
else
|
|
Sys_Printf ("%s %s is not bound\n", imt_name, key_name);
|
|
return;
|
|
}
|
|
Key_SetBinding (imt, key, cmd);
|
|
}
|
|
|
|
static void
|
|
Key_In_Bind_f (void)
|
|
{
|
|
int c, i;
|
|
const char *imt, *key, *cmd = 0;
|
|
dstring_t *cmd_buf = 0;
|
|
|
|
c = Cmd_Argc ();
|
|
|
|
if (c < 3) {
|
|
Sys_Printf ("in_bind <imt> <key> [command] : attach a command to a "
|
|
"key\n");
|
|
return;
|
|
}
|
|
|
|
imt = Cmd_Argv (1);
|
|
|
|
key = Cmd_Argv (2);
|
|
|
|
if (c >= 4) {
|
|
cmd_buf = dstring_newstr ();
|
|
for (i = 3; i < c; i++) {
|
|
dasprintf (cmd_buf, "%s%s", i > 3 ? " " : "", Cmd_Argv (i));
|
|
}
|
|
cmd = cmd_buf->str;
|
|
}
|
|
|
|
Key_In_Bind (imt, key, cmd);
|
|
if (cmd_buf) {
|
|
dstring_delete (cmd_buf);
|
|
}
|
|
}
|
|
|
|
static void
|
|
Key_Unbind_f (void)
|
|
{
|
|
const char *key;
|
|
|
|
if (Cmd_Argc () != 2) {
|
|
Sys_Printf ("unbind <key> : remove commands from a key\n");
|
|
return;
|
|
}
|
|
key = OK_TranslateKeyName (Cmd_Argv (1));
|
|
Key_In_Unbind ("imt_mod", key);
|
|
}
|
|
|
|
static void
|
|
Key_Bind_f (void)
|
|
{
|
|
int c, i;
|
|
const char *key, *cmd = 0;
|
|
dstring_t *cmd_buf = 0;
|
|
|
|
c = Cmd_Argc ();
|
|
|
|
if (c < 2) {
|
|
Sys_Printf ("bind <key> [command] : attach a command to a key\n");
|
|
return;
|
|
}
|
|
|
|
key = OK_TranslateKeyName (Cmd_Argv (1));
|
|
|
|
if (c >= 3) {
|
|
cmd_buf = dstring_newstr ();
|
|
for (i = 2; i < c; i++) {
|
|
dasprintf (cmd_buf, "%s%s", i > 2 ? " " : "", Cmd_Argv (i));
|
|
}
|
|
cmd = cmd_buf->str;
|
|
}
|
|
|
|
Key_In_Bind ("imt_mod", key, cmd);
|
|
if (cmd_buf) {
|
|
dstring_delete (cmd_buf);
|
|
}
|
|
}
|
|
|
|
static void
|
|
in_key_toggleconsole_f (cvar_t *var)
|
|
{
|
|
int k;
|
|
|
|
if (!*var->string) {
|
|
key_toggleconsole = -1;
|
|
return;
|
|
}
|
|
if ((k = Key_StringToKeynum (var->string)) == -1) {
|
|
Sys_Printf ("\"%s\" is not a valid key. not setting\n",
|
|
var->string);
|
|
return;
|
|
}
|
|
key_toggleconsole = k;
|
|
}
|
|
|
|
static void
|
|
Key_InputMappingTable_f (void)
|
|
{
|
|
int c;
|
|
imt_t *imt;
|
|
|
|
c = Cmd_Argc ();
|
|
|
|
if (c != 2) {
|
|
Sys_Printf ("Current imt is %s\n", key_targets[key_game].active->name);
|
|
Sys_Printf ("imt <imt> : set to a specific input mapping table\n");
|
|
return;
|
|
}
|
|
|
|
imt = Key_FindIMT (Cmd_Argv (1));
|
|
if (!imt) {
|
|
Sys_Printf ("\"%s\" is not a valid imt\n", Cmd_Argv (1));
|
|
return;
|
|
}
|
|
|
|
key_targets[key_game].active = imt;
|
|
}
|
|
|
|
static void
|
|
Key_IMT_Keydest_f (void)
|
|
{
|
|
int c;
|
|
imt_t *imt;
|
|
const char *imt_name = 0;
|
|
const char *keydest;
|
|
keydest_t kd;
|
|
|
|
c = Cmd_Argc ();
|
|
switch (c) {
|
|
case 3:
|
|
imt_name = Cmd_Argv (2);
|
|
case 2:
|
|
keydest = Cmd_Argv (1);
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
for (kd = key_game; kd < key_last; kd++) {
|
|
if (!strcasecmp (keydest_names[kd], keydest)) {
|
|
break;
|
|
}
|
|
}
|
|
if (kd == key_last) {
|
|
Sys_Printf ("imt error: invalid keydest: %s\n", keydest);
|
|
return;
|
|
}
|
|
|
|
if (!imt_name) {
|
|
Sys_Printf ("Current imt is %s\n", key_targets[key_game].active->name);
|
|
Sys_Printf ("imt <imt> : set to a specific input mapping table\n");
|
|
return;
|
|
}
|
|
|
|
imt = key_target_find_imt (&key_targets[kd], imt_name);
|
|
if (!imt) {
|
|
Sys_Printf ("\"%s\" is not an imt on %s\n", imt_name, keydest);
|
|
return;
|
|
}
|
|
|
|
key_targets[kd].active = imt;
|
|
}
|
|
|
|
static void __attribute__((format(PRINTF,2,3)))
|
|
key_printf (QFile *f, const char *fmt, ...)
|
|
{
|
|
va_list args;
|
|
static dstring_t *string;
|
|
|
|
if (!string) {
|
|
string = dstring_new ();
|
|
}
|
|
va_start (args, fmt);
|
|
dvsprintf (string, fmt, args);
|
|
va_end (args);
|
|
|
|
if (f) {
|
|
Qprintf (f, "%s", string->str);
|
|
} else {
|
|
Sys_Printf ("%s", string->str);
|
|
}
|
|
}
|
|
|
|
static void
|
|
key_write_imt (QFile *f, keydest_t kd, imt_t *imt)
|
|
{
|
|
int i;
|
|
const char *bind;
|
|
|
|
if (!imt || imt->written) {
|
|
return;
|
|
}
|
|
imt->written = 1;
|
|
key_write_imt (f, kd, imt->chain);
|
|
if (imt->chain) {
|
|
key_printf (f, "imt_create %s %s %s\n", keydest_names[kd],
|
|
imt->name, imt->chain->name);
|
|
} else {
|
|
key_printf (f, "imt_create %s %s\n", keydest_names[kd], imt->name);
|
|
}
|
|
for (i = 0; i < QFK_LAST; i++) {
|
|
bind = imt->bindings[i].str;
|
|
if (bind) {
|
|
key_printf (f, "in_bind %s %s \"%s\"\n", imt->name,
|
|
Key_KeynumToString (i), bind);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
Key_WriteBindings (QFile *f)
|
|
{
|
|
keydest_t kd;
|
|
imt_t *imt;
|
|
|
|
for (kd = key_unfocused; kd < key_last; kd++) {
|
|
for (imt = key_targets[kd].imts; imt; imt = imt->next) {
|
|
imt->written = 0;
|
|
}
|
|
}
|
|
key_printf (f, "imt_drop_all\n");
|
|
for (kd = key_unfocused; kd < key_last; kd++) {
|
|
if (key_targets[kd].imts) {
|
|
for (imt = key_targets[kd].imts; imt; imt = imt->next) {
|
|
key_write_imt (f, kd, imt);
|
|
}
|
|
key_printf (f, "imt_keydest %s %s\n", keydest_names[kd],
|
|
key_targets[kd].active->name);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
Key_Bindlist_f (void)
|
|
{
|
|
Key_WriteBindings (0);
|
|
}
|
|
|
|
static void
|
|
keyhelp_f (void)
|
|
{
|
|
keyhelp = 1;
|
|
}
|
|
|
|
static key_event_t *key_event_handlers[key_last] = { };
|
|
static void *key_event_data[key_last] = { };
|
|
|
|
VISIBLE void
|
|
Key_SetKeyEvent (keydest_t keydest, key_event_t *callback, void *data)
|
|
{
|
|
if (keydest < 0 || keydest >= key_last) {
|
|
Sys_Error ("Key_SetKeyEvent: invalid keydest: %d", keydest);
|
|
}
|
|
key_event_handlers[keydest] = callback;
|
|
key_event_data[keydest] = data;
|
|
}
|
|
|
|
/*
|
|
Key_Event
|
|
|
|
Called by the system between frames for both key up and key down events
|
|
Should NOT be called during an interrupt!
|
|
*/
|
|
VISIBLE void
|
|
Key_Event (knum_t key, short unicode, qboolean down)
|
|
{
|
|
// Sys_Printf ("%d %d %d : %d\n", key_target, key_dest, key, down); //@@@
|
|
|
|
if (down) {
|
|
keydown[key]++;
|
|
if (keyhelp) {
|
|
Sys_Printf ("Key name for that key is \"%s\"\n",
|
|
Key_KeynumToString (key));
|
|
keyhelp = 0;
|
|
return; // gobble the key
|
|
}
|
|
} else {
|
|
keydown[key] = 0;
|
|
}
|
|
|
|
// handle the escape key specially so it can never be overridden or
|
|
// unbound
|
|
if (key == QFK_ESCAPE && keydown[key] == 1) {
|
|
if (key_escape_callbacks.size) {
|
|
int ind = key_escape_callbacks.size - 1;
|
|
key_escape_item_t cb = key_escape_callbacks.a[ind];
|
|
cb.func (cb.data);
|
|
}
|
|
return;
|
|
}
|
|
//FIXME maybe still a tad over-coupled. Use callbacks for menu and console
|
|
//toggles? Should keys know anything about menu and console?
|
|
if (key_dest != key_console && key == key_toggleconsole
|
|
&& keydown[key] == 1) {
|
|
Cbuf_AddText (cbuf, "toggleconsole");
|
|
return;
|
|
}
|
|
|
|
if (key_dest < 0 || key_dest >= key_last) {
|
|
Sys_Error ("Bad key_dest");
|
|
}
|
|
|
|
if (!Key_Game (key, unicode)) {
|
|
if (key_event_handlers[key_dest]) {
|
|
key_event_handlers[key_dest] (key, unicode, down,
|
|
key_event_data[key_dest]);
|
|
}
|
|
}
|
|
}
|
|
|
|
VISIBLE void
|
|
Key_FocusEvent (int gain)
|
|
{
|
|
if (gain) {
|
|
Key_CallDestCallbacks (key_dest);
|
|
} else {
|
|
Key_CallDestCallbacks (key_unfocused);
|
|
}
|
|
}
|
|
|
|
void
|
|
Key_ClearStates (void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < QFK_LAST; i++) {
|
|
if (keydown[i])
|
|
Key_Event (i, 0, false);
|
|
keydown[i] = false;
|
|
}
|
|
}
|
|
|
|
static struct {
|
|
keydest_t kd;
|
|
const char *imt_name;
|
|
const char *chain_imt_name;
|
|
} default_imts[] = {
|
|
{key_game, "imt_mod", 0},
|
|
{key_game, "imt_0", "imt_mod"},
|
|
{key_game, "imt_1", "imt_0"},
|
|
{key_game, "imt_2", "imt_0"},
|
|
{key_game, "imt_3", "imt_0"},
|
|
{key_game, "imt_4", "imt_0"},
|
|
{key_game, "imt_5", "imt_0"},
|
|
{key_game, "imt_6", "imt_0"},
|
|
{key_game, "imt_7", "imt_0"},
|
|
{key_game, "imt_8", "imt_0"},
|
|
{key_game, "imt_9", "imt_0"},
|
|
{key_game, "imt_10", "imt_0"},
|
|
{key_game, "imt_11", "imt_0"},
|
|
{key_game, "imt_12", "imt_0"},
|
|
{key_game, "imt_13", "imt_0"},
|
|
{key_game, "imt_14", "imt_0"},
|
|
{key_game, "imt_15", "imt_0"},
|
|
{key_game, "imt_16", "imt_0"},
|
|
{key_demo, "imt_demo", 0},
|
|
{key_console, "imt_console", 0},
|
|
{key_message, "imt_message", 0},
|
|
{key_menu, "imt_menu", 0},
|
|
{key_last, 0, 0},
|
|
};
|
|
|
|
static struct {
|
|
const char *imt;
|
|
const char *key;
|
|
const char *command;
|
|
} default_bindings[] = {
|
|
{"imt_mod", "K_F10", "quit"},
|
|
{"imt_mod", "K_BACKQUOTE", "toggleconsole"},
|
|
{"imt_0", "K_F10", "quit"},
|
|
{"imt_0", "K_BACKQUOTE", "toggleconsole"},
|
|
{"imt_demo", "K_F10", "quit"},
|
|
{"imt_demo", "K_BACKQUOTE", "toggleconsole"},
|
|
{"imt_console", "K_F10", "quit"},
|
|
{"imt_console", "K_BACKQUOTE", "toggleconsole"},
|
|
{"imt_menu", "K_F10", "quit"},
|
|
{"imt_console", "K_BACKQUOTE", "toggleconsole"},
|
|
{ }
|
|
};
|
|
|
|
static void
|
|
Key_CreateDefaultIMTs (void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; default_imts[i].kd != key_last; i++) {
|
|
Key_CreateIMT (default_imts[i].kd, default_imts[i].imt_name,
|
|
default_imts[i].chain_imt_name);
|
|
}
|
|
for (i = 0; default_bindings[i].imt; i++) {
|
|
Key_In_Bind (default_bindings[i].imt, default_bindings[i].key,
|
|
default_bindings[i].command);
|
|
}
|
|
}
|
|
|
|
void
|
|
Key_Init (cbuf_t *cb)
|
|
{
|
|
cbuf = cb;
|
|
|
|
Key_CreateDefaultIMTs ();
|
|
|
|
OK_Init ();
|
|
|
|
// register our functions
|
|
Cmd_AddCommand ("in_bind", Key_In_Bind_f, "Assign a command or a set of "
|
|
"commands to a key.\n"
|
|
"Note: To bind multiple commands to a key, enclose the "
|
|
"commands in quotes and separate with semi-colons.");
|
|
Cmd_AddCommand ("in_unbind", Key_In_Unbind_f,
|
|
"Remove the bind from the the selected key");
|
|
Cmd_AddCommand ("unbindall", Key_Unbindall_f,
|
|
"Remove all binds (USE CAUTIOUSLY!!!)");
|
|
Cmd_AddCommand ("in_clear", Key_In_Clear,
|
|
"Remove all binds from the specified imts");
|
|
Cmd_AddCommand ("in_type", Key_In_Type_f,
|
|
"Send the given string as simulated key presses.");
|
|
Cmd_AddCommand ("imt", Key_InputMappingTable_f, "");
|
|
Cmd_AddCommand ("imt_keydest", Key_IMT_Keydest_f, "");
|
|
Cmd_AddCommand ("imt_create", Key_IMT_Create_f,
|
|
"create a new imt table:\n"
|
|
" imt_create <keydest> <imt_name> [chain_name]\n"
|
|
"\n"
|
|
"The new table will be attached to the specified keydest\n"
|
|
"imt_name must not already exist.\n"
|
|
"If given, chain_name must already exist and be on "
|
|
"keydest.\n");
|
|
Cmd_AddCommand ("imt_drop_all", Key_IMT_Drop_All_f,
|
|
"delete all imt tables\n");
|
|
Cmd_AddCommand ("bind", Key_Bind_f, "wrapper for in_bind that uses "
|
|
"in_bind_imt for the imt parameter");
|
|
Cmd_AddCommand ("unbind", Key_Unbind_f,
|
|
"wrapper for in_unbind that uses in_bind_imt for the imt "
|
|
"parameter");
|
|
Cmd_AddCommand ("bindlist", Key_Bindlist_f, "list all of the key bindings");
|
|
Cmd_AddCommand ("keyhelp", keyhelp_f, "display the keyname for the next "
|
|
"RECOGNIZED key-press. If the key pressed produces no "
|
|
"output, " PACKAGE_NAME " does not recognise that key.");
|
|
}
|
|
|
|
void
|
|
Key_Init_Cvars (void)
|
|
{
|
|
Cvar_Get ("in_key_toggleconsole", "K_BACKQUOTE", CVAR_NONE,
|
|
in_key_toggleconsole_f,
|
|
"Key for toggling the console.");
|
|
}
|
|
|
|
const char *
|
|
Key_GetBinding (imt_t *imt, knum_t key)
|
|
{
|
|
if (imt) {
|
|
return imt->bindings[key].str;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
VISIBLE void
|
|
Key_SetKeyDest(keydest_t kd)
|
|
{
|
|
if (kd < 0 || kd >= key_last) {
|
|
Sys_Error ("Bad key_dest: %d", kd);
|
|
}
|
|
Sys_MaskPrintf (SYS_input, "Key_SetKeyDest: %s\n", keydest_names[kd]);
|
|
if (key_dest != kd) {
|
|
key_dest = kd;
|
|
Key_CallDestCallbacks (key_dest);
|
|
}
|
|
}
|
|
|
|
VISIBLE keydest_t
|
|
Key_GetKeyDest (void)
|
|
{
|
|
return key_dest;
|
|
}
|
|
|
|
VISIBLE void
|
|
Key_KeydestCallback (keydest_callback_t *callback, void *data)
|
|
{
|
|
if (!callback) {
|
|
Sys_Error ("null keydest callback");
|
|
}
|
|
|
|
keydest_callback_item_t cb = { callback, data };
|
|
DARRAY_APPEND (&keydest_callbacks, cb);
|
|
}
|
|
|
|
VISIBLE void
|
|
Key_PushEscape (key_escape_t *callback, void *data)
|
|
{
|
|
if (!callback) {
|
|
Sys_Error ("null escape callback");
|
|
}
|
|
|
|
key_escape_item_t cb = { callback, data };
|
|
DARRAY_APPEND (&key_escape_callbacks, cb);
|
|
}
|
|
|
|
VISIBLE void
|
|
Key_PopEscape (void)
|
|
{
|
|
if (!key_escape_callbacks.size) {
|
|
Sys_Error ("no escape callback to pop");
|
|
}
|
|
DARRAY_REMOVE (&key_escape_callbacks);
|
|
}
|