1 /* $OpenBSD: kbd.c,v 1.25 2012/04/12 04:47:59 lum Exp $ */
3 /* This file is in the public domain. */
6 * Terminal independent keyboard handling.
20 char prompt[PROMPTL] = "", *promptp = prompt;
21 #endif /* !NO_DPROMPT */
23 static int mgwrap(PF, int, int);
25 static int use_metakey = TRUE;
26 static int pushed = FALSE;
29 struct map_element *ele;
34 * Toggle the value of use_metakey
42 use_metakey = !use_metakey;
43 ewprintf("Meta keys %sabled", use_metakey ? "en" : "dis");
47 static int bs_map = 0;
50 * Toggle backspace mapping
59 ewprintf("Backspace mapping %sabled", bs_map ? "en" : "dis");
66 if (use_metakey && pushed && c == CCHR('['))
79 if (flag && !pushed) {
80 if (prompt[0] != '\0' && ttwait(2000)) {
81 /* avoid problems with % */
82 ewprintf("%s", prompt);
83 /* put the cursor back */
90 #endif /* !NO_DPROMPT */
100 else if (c == CCHR('?'))
103 if (use_metakey && (c & METABIT)) {
104 pushedc = c & ~METABIT;
109 if (flag && promptp < &prompt[PROMPTL - 5]) {
110 promptp = getkeyname(promptp,
111 sizeof(prompt) - (promptp - prompt) - 1, c);
115 #endif /* !NO_DPROMPT */
120 * doscan scans a keymap for a keyboard character and returns a pointer
121 * to the function associated with that character. Sets ele to the
122 * keymap element the keyboard was found in as a side effect.
125 doscan(KEYMAP *map, int c, KEYMAP **newmap)
127 struct map_element *elec = &map->map_element[0];
128 struct map_element *last = &map->map_element[map->map_num];
131 while (elec < last && c > elec->k_num)
134 /* used by prefix and binding code */
136 if (elec >= last || c < elec->k_base)
137 ret = map->map_default;
139 ret = elec->k_funcp[c - elec->k_base];
140 if (ret == NULL && newmap != NULL)
141 *newmap = elec->k_prefmap;
153 *(promptp = prompt) = '\0';
154 #endif /* !NO_DPROMPT */
155 curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
157 while ((funct = doscan(curmap, (key.k_chars[key.k_count++] =
158 getkey(TRUE)), &curmap)) == NULL)
161 if (macrodef && macrocount < MAXMACRO)
162 macro[macrocount++].m_funct = funct;
164 return (mgwrap(funct, 0, 1));
174 int md = curbp->b_nmodes;
177 if (ISUPPER(key.k_chars[key.k_count - 1])) {
178 c = TOLOWER(key.k_chars[key.k_count - 1]);
179 curmap = curbp->b_modes[md]->p_map;
180 for (i = 0; i < key.k_count - 1; i++) {
181 if ((fp = doscan(curmap, (key.k_chars[i]),
186 if ((fp = doscan(curmap, c, NULL)) == NULL)
187 while ((fp = doscan(curmap,
188 key.k_chars[key.k_count++] =
189 getkey(TRUE), &curmap)) == NULL)
192 if (macrodef && macrocount <= MAXMACRO)
193 macro[macrocount - 1].m_funct
195 return (mgwrap(fp, f, n));
199 /* try previous mode */
202 curmap = curbp->b_modes[md]->p_map;
203 for (i = 0; i < key.k_count; i++) {
204 if ((fp = doscan(curmap, (key.k_chars[i]), &curmap)) != NULL)
208 while ((fp = doscan(curmap, key.k_chars[i++] =
209 getkey(TRUE), &curmap)) == NULL)
213 if (fp != rescan && i >= key.k_count - 1) {
214 if (macrodef && macrocount <= MAXMACRO)
215 macro[macrocount - 1].m_funct = fp;
216 return (mgwrap(fp, f, n));
222 universal_argument(int f, int n)
231 key.k_chars[0] = c = getkey(TRUE);
234 return (negative_argument(f, nn));
235 if (c >= '0' && c <= '9')
236 return (digit_argument(f, nn));
237 curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
238 while ((funct = doscan(curmap, c, &curmap)) == NULL) {
239 key.k_chars[key.k_count++] = c = getkey(TRUE);
241 if (funct != universal_argument) {
242 if (macrodef && macrocount < MAXMACRO - 1) {
245 macro[macrocount++].m_count = nn;
246 macro[macrocount++].m_funct = funct;
248 return (mgwrap(funct, FFUNIV, nn));
256 digit_argument(int f, int n)
262 nn = key.k_chars[key.k_count - 1] - '0';
265 if (c < '0' || c > '9')
272 curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
273 while ((funct = doscan(curmap, c, &curmap)) == NULL) {
274 key.k_chars[key.k_count++] = c = getkey(TRUE);
276 if (macrodef && macrocount < MAXMACRO - 1) {
280 macro[macrocount - 1].m_funct = universal_argument;
281 macro[macrocount++].m_count = nn;
282 macro[macrocount++].m_funct = funct;
284 return (mgwrap(funct, FFOTHARG, nn));
288 negative_argument(int f, int n)
297 if (c < '0' || c > '9')
308 curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
309 while ((funct = doscan(curmap, c, &curmap)) == NULL) {
310 key.k_chars[key.k_count++] = c = getkey(TRUE);
312 if (macrodef && macrocount < MAXMACRO - 1) {
316 macro[macrocount - 1].m_funct = universal_argument;
317 macro[macrocount++].m_count = nn;
318 macro[macrocount++].m_funct = funct;
320 return (mgwrap(funct, FFNEGARG, nn));
324 * Insert a character. While defining a macro, create a "LINE" containing
325 * all inserted characters.
328 selfinsert(int f, int n)
338 c = key.k_chars[key.k_count - 1];
340 if (macrodef && macrocount < MAXMACRO) {
344 /* last command was insert -- tack on the end */
345 if (lastflag & CFINS) {
347 /* Ensure the line can handle the new characters */
348 if (maclcur->l_size < maclcur->l_used + n) {
349 if (lrealloc(maclcur, maclcur->l_used + n) ==
353 maclcur->l_used += n;
354 /* Copy in the new data */
355 for (count = maclcur->l_used - n;
356 count < maclcur->l_used; count++)
357 maclcur->l_text[count] = c;
359 macro[macrocount - 1].m_funct = insert;
360 if ((lp = lalloc(n)) == NULL)
363 lp->l_fp = maclcur->l_fp;
366 for (count = 0; count < n; count++)
367 lp->l_text[count] = c;
374 } while (--n && count == TRUE);
379 if (curbp->b_flag & BFOVERWRITE) {
381 while (curwp->w_doto < llength(curwp->w_dotp) && n--)
382 lputc(curwp->w_dotp, curwp->w_doto++, c);
386 return (linsert(n, c));
390 * This could be implemented as a keymap with everything defined as self-insert.
398 if ((key.k_chars[0] = getkey(TRUE)) >= '0' && key.k_chars[0] <= '7') {
399 key.k_chars[0] -= '0';
400 if ((c = getkey(TRUE)) >= '0' && c <= '7') {
401 key.k_chars[0] <<= 3;
402 key.k_chars[0] += c - '0';
403 if ((c = getkey(TRUE)) >= '0' && c <= '7') {
404 key.k_chars[0] <<= 3;
405 key.k_chars[0] += c - '0';
411 return (selfinsert(f, n));
415 * Wraper function to count invocation repeats.
416 * We ignore any function whose sole purpose is to get us
417 * to the intended function.
420 mgwrap(PF funct, int f, int n)
424 if (funct != rescan &&
425 funct != negative_argument &&
426 funct != digit_argument &&
427 funct != universal_argument) {
435 return ((*funct)(f, n));