1 /* Copyright (c) 2006-2014 Jonas Fonseca <fonseca@diku.dk>
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU General Public License as
5 * published by the Free Software Foundation; either version 2 of
6 * the License, or (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
25 static struct keymap generic_keymap
= { "generic" };
26 #define is_generic_keymap(keymap) ((keymap) == &generic_keymap)
28 static struct keymap
*keymaps
= &generic_keymap
;
37 add_keymap(struct keymap
*keymap
)
39 keymap
->next
= keymaps
;
44 get_keymap(const char *name
)
46 struct keymap
*keymap
= keymaps
;
49 if (!strcasecmp(keymap
->name
, name
))
51 keymap
= keymap
->next
;
59 add_keybinding(struct keymap
*table
, enum request request
, int key
)
63 for (i
= 0; i
< table
->size
; i
++) {
64 if (table
->data
[i
].alias
== key
) {
65 table
->data
[i
].request
= request
;
70 table
->data
= realloc(table
->data
, (table
->size
+ 1) * sizeof(*table
->data
));
72 die("Failed to allocate keybinding");
73 table
->data
[table
->size
].alias
= key
;
74 table
->data
[table
->size
++].request
= request
;
77 /* Looks for a key binding first in the given map, then in the generic map, and
78 * lastly in the default keybindings. */
80 get_keybinding(struct keymap
*keymap
, int key
)
84 for (i
= 0; i
< keymap
->size
; i
++)
85 if (keymap
->data
[i
].alias
== key
)
86 return keymap
->data
[i
].request
;
88 for (i
= 0; i
< generic_keymap
.size
; i
++)
89 if (generic_keymap
.data
[i
].alias
== key
)
90 return generic_keymap
.data
[i
].request
;
92 return (enum request
) key
;
101 static const struct key key_table
[] = {
102 { "Enter", KEY_RETURN
},
104 { "Backspace", KEY_BACKSPACE
},
106 { "Escape", KEY_ESC
},
107 { "Left", KEY_LEFT
},
108 { "Right", KEY_RIGHT
},
110 { "Down", KEY_DOWN
},
111 { "Insert", KEY_IC
},
112 { "Delete", KEY_DC
},
114 { "Home", KEY_HOME
},
116 { "PageUp", KEY_PPAGE
},
117 { "PgUp", KEY_PPAGE
},
118 { "PageDown", KEY_NPAGE
},
119 { "PgDown", KEY_NPAGE
},
129 { "F10", KEY_F(10) },
130 { "F11", KEY_F(11) },
131 { "F12", KEY_F(12) },
135 get_key_value(const char *name
)
139 for (i
= 0; i
< ARRAY_SIZE(key_table
); i
++)
140 if (!strcasecmp(key_table
[i
].name
, name
))
141 return key_table
[i
].value
;
143 if (strlen(name
) == 3 && name
[0] == '^' && name
[1] == '[' && isprint(*name
))
144 return (int)name
[2] + 0x80;
145 if (strlen(name
) == 2 && name
[0] == '^' && isprint(*name
))
146 return (int)name
[1] & 0x1f;
147 if (strlen(name
) == 1 && isprint(*name
))
153 get_key_name(int key_value
)
155 static char key_char
[] = "'X'\0";
156 const char *seq
= NULL
;
159 for (key
= 0; key
< ARRAY_SIZE(key_table
); key
++)
160 if (key_table
[key
].value
== key_value
)
161 seq
= key_table
[key
].name
;
163 if (seq
== NULL
&& key_value
< 0x7f) {
164 char *s
= key_char
+ 1;
166 if (key_value
>= 0x20) {
170 *s
++ = 0x40 | (key_value
& 0x1f);
177 return seq
? seq
: "(no key)";
181 append_key(char *buf
, size_t *pos
, const struct keybinding
*keybinding
)
183 const char *sep
= *pos
> 0 ? ", " : "";
184 const char *keyname
= get_key_name(keybinding
->alias
);
186 return string_nformat(buf
, BUFSIZ
, pos
, "%s%s", sep
, keyname
);
190 append_keymap_request_keys(char *buf
, size_t *pos
, enum request request
,
191 struct keymap
*keymap
, bool all
)
195 for (i
= 0; i
< keymap
->size
; i
++) {
196 if (keymap
->data
[i
].request
== request
) {
197 if (!append_key(buf
, pos
, &keymap
->data
[i
]))
207 #define get_view_key(view, request) get_keys(&(view)->ops->keymap, request, FALSE)
210 get_keys(struct keymap
*keymap
, enum request request
, bool all
)
212 static char buf
[BUFSIZ
];
217 if (!append_keymap_request_keys(buf
, &pos
, request
, keymap
, all
))
218 return "Too many keybindings!";
222 if (!is_generic_keymap(keymap
)) {
223 /* Only the generic keymap includes the default keybindings when
224 * listing all keys. */
228 if (!append_keymap_request_keys(buf
, &pos
, request
, &generic_keymap
, all
))
229 return "Too many keybindings!";
237 static struct run_request
*run_request
;
238 static size_t run_requests
;
240 DEFINE_ALLOCATOR(realloc_run_requests
, struct run_request
, 8)
243 add_run_request(struct keymap
*keymap
, int key
, const char **argv
, enum run_request_flag flags
)
245 bool force
= flags
& RUN_REQUEST_FORCE
;
246 struct run_request
*req
;
248 if (!force
&& get_keybinding(keymap
, key
) != key
)
251 if (!realloc_run_requests(&run_request
, run_requests
, 1))
254 if (!argv_copy(&run_request
[run_requests
].argv
, argv
))
257 req
= &run_request
[run_requests
++];
258 req
->silent
= flags
& RUN_REQUEST_SILENT
;
259 req
->confirm
= flags
& RUN_REQUEST_CONFIRM
;
260 req
->exit
= flags
& RUN_REQUEST_EXIT
;
261 req
->internal
= flags
& RUN_REQUEST_INTERNAL
;
262 req
->keymap
= keymap
;
265 add_keybinding(keymap
, REQ_RUN_REQUESTS
+ run_requests
, key
);
270 get_run_request(enum request request
)
272 if (request
<= REQ_RUN_REQUESTS
|| request
> REQ_RUN_REQUESTS
+ run_requests
)
274 return &run_request
[request
- REQ_RUN_REQUESTS
- 1];
277 /* vim: set ts=8 sw=8 noexpandtab: */