Initial import from FreeBSD RELENG_4:
[games.git] / sys / dev / video / pcvt / i386 / pcvt_kbd.c
1 /*
2  * Copyright (c) 1999 Hellmuth Michaelis
3  *
4  * Copyright (c) 1992, 1995 Hellmuth Michaelis and Joerg Wunsch.
5  *
6  * Copyright (c) 1992, 1993 Brian Dunford-Shore and Holger Veit.
7  *
8  * All rights reserved.
9  *
10  * This code is derived from software contributed to Berkeley by
11  * William Jolitz and Don Ahn.
12  *
13  * This code is derived from software contributed to 386BSD by
14  * Holger Veit.
15  *
16  * Redistribution and use in source and binary forms, with or without
17  * modification, are permitted provided that the following conditions
18  * are met:
19  * 1. Redistributions of source code must retain the above copyright
20  *    notice, this list of conditions and the following disclaimer.
21  * 2. Redistributions in binary form must reproduce the above copyright
22  *    notice, this list of conditions and the following disclaimer in the
23  *    documentation and/or other materials provided with the distribution.
24  * 3. All advertising materials mentioning features or use of this software
25  *    must display the following acknowledgement:
26  *      This product includes software developed by Hellmuth Michaelis,
27  *      Brian Dunford-Shore and Joerg Wunsch.
28  * 4. The name authors may not be used to endorse or promote products
29  *    derived from this software without specific prior written permission.
30  *
31  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
32  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
33  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
34  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
35  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
40  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41  */
42
43 /*---------------------------------------------------------------------------*
44  *
45  *      pcvt_kbd.c      VT220 Driver Keyboard Interface Code
46  *      ----------------------------------------------------
47  *
48  *      Last Edit-Date: [Mon Dec 27 14:01:50 1999]
49  *
50  * $FreeBSD: src/sys/i386/isa/pcvt/pcvt_kbd.c,v 1.32.2.1 2000/10/29 16:59:28 dwmalone Exp $
51  *
52  *---------------------------------------------------------------------------*/
53
54 #include "vt.h"
55 #include "opt_ddb.h"
56
57 #if NVT > 0
58
59 #include <i386/isa/pcvt/pcvt_hdr.h>     /* global include */
60
61 #define LEDSTATE_UPDATE_PENDING (1 << 3)
62
63 static void fkey1(void), fkey2(void),  fkey3(void),  fkey4(void);
64 static void fkey5(void), fkey6(void),  fkey7(void),  fkey8(void);
65 static void fkey9(void), fkey10(void), fkey11(void), fkey12(void);
66
67 static void sfkey1(void), sfkey2(void),  sfkey3(void),  sfkey4(void);
68 static void sfkey5(void), sfkey6(void),  sfkey7(void),  sfkey8(void);
69 static void sfkey9(void), sfkey10(void), sfkey11(void), sfkey12(void);
70
71 static void cfkey1(void), cfkey2(void),  cfkey3(void),  cfkey4(void);
72 static void cfkey5(void), cfkey6(void),  cfkey7(void),  cfkey8(void);
73 static void cfkey9(void), cfkey10(void), cfkey11(void), cfkey12(void);
74
75 static void     doreset ( void );
76 static void     ovlinit ( int force );
77 static void     settpmrate ( int rate );
78 static void     setlockkeys ( int snc );
79 #ifndef _DEV_KBD_KBDREG_H_
80 static int      kbc_8042cmd ( int val );
81 #endif /* !_DEV_KBD_KBDREG_H_ */
82 static int      getokeydef ( unsigned key, struct kbd_ovlkey *thisdef );
83 static int      getckeydef ( unsigned key, struct kbd_ovlkey *thisdef );
84 static int      rmkeydef ( int key );
85 static int      setkeydef ( struct kbd_ovlkey *data );
86 static u_char * xlatkey2ascii( U_short key );
87
88 static int      ledstate  = LEDSTATE_UPDATE_PENDING;    /* keyboard led's */
89 static int      tpmrate   = KBD_TPD500|KBD_TPM100;
90 static u_char   altkpflag = 0;
91 static u_short  altkpval  = 0;
92
93 static u_short *scrollback_savedscreen = (u_short *)0;
94 static size_t scrnsv_size = (size_t)-1;
95 static void scrollback_save_screen ( void );
96 static void scrollback_restore_screen ( void );
97
98 #if PCVT_SHOWKEYS
99 u_char rawkeybuf[80];
100 #endif
101
102 #include <i386/isa/pcvt/pcvt_kbd.h>     /* tables etc */
103
104 #if PCVT_SHOWKEYS
105 /*---------------------------------------------------------------------------*
106  *      keyboard debugging: put kbd communication char into some buffer
107  *---------------------------------------------------------------------------*/
108 static void showkey (char delim, u_char val)
109 {
110         int rki;
111
112         for(rki = 3; rki < 80; rki++)           /* shift left buffer */
113                 rawkeybuf[rki-3] = rawkeybuf[rki];
114
115         rawkeybuf[77] = delim;          /* delimiter */
116
117         rki = (val & 0xf0) >> 4;        /* ms nibble */
118
119         if(rki <= 9)
120                 rki = rki + '0';
121         else
122                 rki = rki - 10 + 'A';
123
124         rawkeybuf[78] = rki;
125
126         rki = val & 0x0f;               /* ls nibble */
127
128         if(rki <= 9)
129                 rki = rki + '0';
130         else
131                 rki = rki - 10 + 'A';
132
133         rawkeybuf[79] = rki;
134 }
135 #endif  /* PCVT_SHOWKEYS */
136
137 /*---------------------------------------------------------------------------*
138  *      function to switch to another virtual screen
139  *---------------------------------------------------------------------------*/
140 static void
141 do_vgapage(int page)
142 {
143         if(critical_scroll)             /* executing critical region ? */
144                 switch_page = page;     /* yes, auto switch later */
145         else
146                 vgapage(page);          /* no, switch now */
147 }
148
149
150 /*
151  * This code from Lon Willett enclosed in #if PCVT_UPDLED_LOSES_INTR is
152  * abled because it crashes FreeBSD 1.1.5.1 at boot time.
153  * The cause is obviously that the timeout queue is not yet initialized
154  * timeout is called from here the first time.
155  * Anyway it is a pointer in the right direction so it is included for
156  * reference here.
157  */
158
159 #define PCVT_UPDLED_LOSES_INTR  0       /* disabled for now */
160
161 #if PCVT_UPDLED_LOSES_INTR || defined(_DEV_KBD_KBDREG_H_)
162
163 /*---------------------------------------------------------------------------*
164  *      check for lost keyboard interrupts
165  *---------------------------------------------------------------------------*/
166
167 /*
168  * The two commands to change the LEDs generate two KEYB_R_ACK responses
169  * from the keyboard, which aren't explicitly checked for (maybe they
170  * should be?).  However, when a lot of other I/O is happening, one of
171  * the interrupts sometimes gets lost (I'm not sure of the details of
172  * how and why and what hardware this happens with).
173  *
174  * This may have had something to do with spltty() previously not being
175  * called before the kbd_cmd() calls in update_led().
176  *
177  * This is a real problem, because normally the keyboard is only polled
178  * by pcrint(), and no more interrupts will be generated until the ACK
179  * has been read.  So the keyboard is hung.  This code polls a little
180  * while after changing the LEDs to make sure that this hasn't happened.
181  *
182  * XXX Quite possibly we should poll the kbd on a regular basis anyway,
183  * in the interest of robustness.  It may be possible that interrupts
184  * get lost other times as well.
185  */
186
187 static int lost_intr_timeout_queued = 0;
188 static struct callout_handle lost_intr_ch =
189     CALLOUT_HANDLE_INITIALIZER(&lost_intr_ch);
190
191 static void
192 check_for_lost_intr (void *arg)
193 {
194 #ifndef _DEV_KBD_KBDREG_H_
195         lost_intr_timeout_queued = 0;
196         if (inb(CONTROLLER_CTRL) & STATUS_OUTPBF)
197         {
198                 int opri = spltty ();
199                 pcrint ();
200                 splx (opri);
201         }
202 #else
203         int opri;
204
205         lost_intr_timeout_queued = 0;
206         if (kbd && (*kbdsw[kbd->kb_index]->lock)(kbd, TRUE)) {
207                 opri = spltty ();
208                 (*kbdsw[kbd->kb_index]->lock)(kbd, FALSE);
209                 if ((*kbdsw[kbd->kb_index]->check)(kbd))
210                         pcrint (0);
211                 splx (opri);
212         }
213
214         lost_intr_ch = timeout(check_for_lost_intr, (void *)NULL, hz);
215         lost_intr_timeout_queued = 1;
216 #endif /* !_DEV_KBD_KBDREG_H_ */
217 }
218
219 #endif /* PCVT_UPDLED_LOSES_INTR || defined(_DEV_KBD_KBDREG_H_) */
220
221 /*---------------------------------------------------------------------------*
222  *      update keyboard led's
223  *---------------------------------------------------------------------------*/
224 void
225 update_led(void)
226 {
227 #if !PCVT_NO_LED_UPDATE
228
229         /* Don't update LED's unless necessary. */
230
231         int opri, new_ledstate;
232
233         opri = spltty();
234 #ifndef _DEV_KBD_KBDREG_H_
235         new_ledstate = (vsp->scroll_lock) |
236                        (vsp->num_lock * 2) |
237                        (vsp->caps_lock * 4);
238 #else
239         new_ledstate = ((vsp->scroll_lock) ? LED_SCR : 0) |
240                        ((vsp->num_lock) ? LED_NUM : 0) |
241                        ((vsp->caps_lock) ? LED_CAP : 0);
242 #endif /* _DEV_KBD_KBDREG_H_ */
243
244         if (new_ledstate != ledstate)
245         {
246 #ifndef _DEV_KBD_KBDREG_H_
247                 int response1, response2;
248
249                 ledstate = LEDSTATE_UPDATE_PENDING;
250
251                 if(kbd_cmd(KEYB_C_LEDS) != 0)
252                 {
253                         printf("Keyboard LED command timeout\n");
254                         splx(opri);
255                         return;
256                 }
257
258                 /*
259                  * For some keyboards or keyboard controllers, it is an
260                  * error to issue a command without waiting long enough
261                  * for an ACK for the previous command.  The keyboard
262                  * gets confused, and responds with KEYB_R_RESEND, but
263                  * we ignore that.  Wait for the ACK here.  The busy
264                  * waiting doesn't matter much, since we lose anyway by
265                  * busy waiting to send the command.
266                  *
267                  * XXX actually wait for any response, since we can't
268                  * handle normal scancodes here.
269                  *
270                  * XXX all this should be interrupt driven.  Issue only
271                  * one command at a time wait for a ACK before proceeding.
272                  * Retry after a timeout or on receipt of a KEYB_R_RESEND.
273                  * KEYB_R_RESENDs seem to be guaranteed by working
274                  * keyboard controllers with broken (or disconnected)
275                  * keyboards.  There is another code for keyboard
276                  * reconnects.  The keyboard hardware is very simple and
277                  * well designed :-).
278                  */
279                 response1 = kbd_response();
280
281                 if(kbd_cmd(new_ledstate) != 0) {
282                         printf("Keyboard LED data timeout\n");
283                         splx(opri);
284                         return;
285                 }
286                 response2 = kbd_response();
287
288                 if (response1 == KEYB_R_ACK && response2 == KEYB_R_ACK)
289                         ledstate = new_ledstate;
290                 else
291                         printf(
292                         "Keyboard LED command not ACKed (responses %#x %#x)\n",
293                                response1, response2);
294 #else /* _DEV_KBD_KBDREG_H_ */
295
296                 if (kbd == NULL) {
297                         ledstate = new_ledstate;
298                         splx(opri);
299                 } else {
300                         ledstate = LEDSTATE_UPDATE_PENDING;
301                         splx(opri);
302                         if ((*kbdsw[kbd->kb_index]->ioctl)(kbd, KDSETLED,
303                                         (caddr_t)&new_ledstate) == 0) 
304                                 ledstate = new_ledstate;
305                 }
306
307 #endif /* !_DEV_KBD_KBDREG_H_ */
308
309 #if PCVT_UPDLED_LOSES_INTR
310                 if (lost_intr_timeout_queued)
311                         untimeout(check_for_lost_intr, NULL, lost_intr_ch);
312
313                 lost_intr_ch = timeout(check_for_lost_intr, NULL, hz);
314                 lost_intr_timeout_queued = 1;
315 #endif /* PCVT_UPDLED_LOSES_INTR */
316
317         }
318
319 #ifndef _DEV_KBD_KBDREG_H_
320         splx(opri);
321 #endif 
322
323 #endif /* !PCVT_NO_LED_UPDATE */
324 }
325
326 /*---------------------------------------------------------------------------*
327  *      set typematic rate
328  *---------------------------------------------------------------------------*/
329 static void
330 settpmrate(int rate)
331 {
332 #ifndef _DEV_KBD_KBDREG_H_
333         tpmrate = rate & 0x7f;
334         if(kbd_cmd(KEYB_C_TYPEM) != 0)
335                 printf("Keyboard TYPEMATIC command timeout\n");
336         else if(kbd_cmd(tpmrate) != 0)
337                 printf("Keyboard TYPEMATIC data timeout\n");
338 #else
339         if (kbd == NULL)
340                 return;
341         tpmrate = rate & 0x7f;
342         if ((*kbdsw[kbd->kb_index]->ioctl)(kbd, KDSETRAD, (caddr_t)&tpmrate))
343                 printf("pcvt: failed to set keyboard TYPEMATIC.\n");
344 #endif /* !_DEV_KBD_KBDREG_H_ */
345 }
346
347 #ifndef _DEV_KBD_KBDREG_H_
348 /*---------------------------------------------------------------------------*
349  *      Pass command to keyboard controller (8042)
350  *---------------------------------------------------------------------------*/
351 static int
352 kbc_8042cmd(int val)
353 {
354         unsigned timeo;
355
356         timeo = 100000;         /* > 100 msec */
357         while (inb(CONTROLLER_CTRL) & STATUS_INPBF)
358                 if (--timeo == 0)
359                         return (-1);
360         outb(CONTROLLER_CTRL, val);
361         return (0);
362 }
363
364 /*---------------------------------------------------------------------------*
365  *      Pass command to keyboard itself
366  *---------------------------------------------------------------------------*/
367 int
368 kbd_cmd(int val)
369 {
370         unsigned timeo;
371
372         timeo = 100000;         /* > 100 msec */
373         while (inb(CONTROLLER_CTRL) & STATUS_INPBF)
374                 if (--timeo == 0)
375                         return (-1);
376         outb(CONTROLLER_DATA, val);
377
378 #if PCVT_SHOWKEYS
379         showkey ('>', val);
380 #endif  /* PCVT_SHOWKEYS */
381
382         return (0);
383 }
384
385 /*---------------------------------------------------------------------------*
386  *      Read response from keyboard
387  *      NB: make sure to call spltty() before kbd_cmd(), kbd_response().
388  *---------------------------------------------------------------------------*/
389 int
390 kbd_response(void)
391 {
392         u_char ch;
393         unsigned timeo;
394
395         timeo = 500000;         /* > 500 msec (KEYB_R_SELFOK requires 87) */
396         while (!(inb(CONTROLLER_CTRL) & STATUS_OUTPBF))
397                 if (--timeo == 0)
398                         return (-1);
399
400         PCVT_KBD_DELAY();               /* 7 us delay */
401         ch = inb(CONTROLLER_DATA);
402
403 #if PCVT_SHOWKEYS
404         showkey ('<', ch);
405 #endif  /* PCVT_SHOWKEYS */
406
407         return ch;
408 }
409 #endif /* _DEV_KBD_KBDREG_H_ */
410
411 #if PCVT_SCANSET > 1
412 /*---------------------------------------------------------------------------*
413  *      switch PC scan code emulation mode
414  *---------------------------------------------------------------------------*/
415 void
416 kbd_emulate_pc(int do_emulation)
417 {
418 #ifndef _DEV_KBD_KBDREG_H_
419         int cmd, timeo = 10000;
420
421         cmd = COMMAND_SYSFLG|COMMAND_IRQEN; /* common base cmd */
422
423 #if !PCVT_USEKBDSEC
424         cmd |= COMMAND_INHOVR;
425 #endif
426
427         if(do_emulation)
428                 cmd |= COMMAND_PCSCAN;
429
430         kbc_8042cmd(CONTR_WRITE);
431         while (inb(CONTROLLER_CTRL) & STATUS_INPBF)
432                 if (--timeo == 0)
433                         break;
434         outb(CONTROLLER_DATA, cmd);
435 #else
436         set_controller_command_byte(*(KBDC *)kbd->kb_data, KBD_TRANSLATION, 
437                 (do_emulation) ? KBD_TRANSLATION : 0);
438 #endif /* !_DEV_KBD_KBDREG_H_ */
439 }
440
441 #endif /* PCVT_SCANSET > 1 */
442
443
444 #ifndef PCVT_NONRESP_KEYB_TRY
445 #define PCVT_NONRESP_KEYB_TRY   25      /* no of times to try to detect */
446 #endif                                  /* a nonresponding keyboard     */
447
448 /*---------------------------------------------------------------------------*
449  *      try to force keyboard into a known state ..
450  *---------------------------------------------------------------------------*/
451 static
452 void doreset(void)
453 {
454 #ifndef _DEV_KBD_KBDREG_H_
455         int again = 0;
456         int once = 0;
457         int response, opri;
458
459         /* Enable interrupts and keyboard, etc. */
460         if (kbc_8042cmd(CONTR_WRITE) != 0)
461                 printf("pcvt: doreset() - timeout controller write command\n");
462
463 #if PCVT_USEKBDSEC              /* security enabled */
464
465 #  if PCVT_SCANSET == 2
466 #    define KBDINITCMD COMMAND_SYSFLG|COMMAND_IRQEN
467 #  else /* PCVT_SCANSET != 2 */
468 #    define KBDINITCMD COMMAND_PCSCAN|COMMAND_SYSFLG|COMMAND_IRQEN
469 #  endif /* PCVT_SCANSET == 2 */
470
471 #else /* ! PCVT_USEKBDSEC */    /* security disabled */
472
473 #  if PCVT_SCANSET == 2
474 #    define KBDINITCMD COMMAND_INHOVR|COMMAND_SYSFLG|COMMAND_IRQEN
475 #  else /* PCVT_SCANSET != 2 */
476 #    define KBDINITCMD COMMAND_PCSCAN|COMMAND_INHOVR|COMMAND_SYSFLG\
477         |COMMAND_IRQEN
478 #  endif /* PCVT_SCANSET == 2 */
479
480 #endif /* PCVT_USEKBDSEC */
481
482         if (kbd_cmd(KBDINITCMD) != 0)
483                 printf("pcvt: doreset() - timeout writing keyboard init command\n");
484
485         /*
486          * Discard any stale keyboard activity.  The 0.1 boot code isn't
487          * very careful and sometimes leaves a KEYB_R_RESEND.  Versions
488          * between 1992 and Oct 1996 didn't have the delay and sometimes
489          * left a KEYB_R_RESEND.
490          */
491         while (1) {
492                 if (inb(CONTROLLER_CTRL) & STATUS_OUTPBF)
493                         kbd_response();
494                 else {
495                         DELAY(10000);
496                         if (!(inb(CONTROLLER_CTRL) & STATUS_OUTPBF))
497                                 break;
498                 }
499         }
500
501         /* Start keyboard reset */
502
503         opri = spltty ();
504
505         if (kbd_cmd(KEYB_C_RESET) != 0)
506         {
507                 printf("pcvt: doreset() - timeout for keyboard reset command\n");
508                 outb(CONTROLLER_DATA, KEYB_C_RESET);    /* force */
509         }
510
511         /* Wait for the first response to reset and handle retries */
512         while ((response = kbd_response()) != KEYB_R_ACK)
513         {
514                 if (response < 0)
515                 {
516                         if(!again)      /* print message only once ! */
517                                 printf("pcvt: doreset() - response != ack and response < 0 [one time only msg]\n");
518                         response = KEYB_R_RESEND;
519                 }
520                 else if (response == KEYB_R_RESEND)
521                 {
522                         if(!again)      /* print message only once ! */
523                                 printf("pcvt: doreset() - got KEYB_R_RESEND response ... [one time only msg]\n");
524                 }
525                 if (response == KEYB_R_RESEND)
526                 {
527                         if(++again > PCVT_NONRESP_KEYB_TRY)
528                         {
529                                 printf("pcvt: doreset() - Caution - no PC keyboard detected!\n");
530                                 keyboard_type = KB_UNKNOWN;
531                                 splx(opri);
532                                 return;
533                         }
534
535                         if((kbd_cmd(KEYB_C_RESET) != 0) && (once == 0))
536                         {
537                                 once++;         /* print message only once ! */
538                                 printf("pcvt: doreset() - timeout for loop keyboard reset command [one time only msg]\n");
539                                 outb(CONTROLLER_DATA, KEYB_C_RESET);    /* force */
540                         }
541                 }
542         }
543
544         /* Wait for the second response to reset */
545
546         while ((response = kbd_response()) != KEYB_R_SELFOK)
547         {
548                 if (response < 0)
549                 {
550                         printf("pcvt: doreset() - response != OK and resonse < 0\n");
551                         /*
552                          * If KEYB_R_SELFOK never arrives, the loop will
553                          * finish here unless the keyboard babbles or
554                          * STATUS_OUTPBF gets stuck.
555                          */
556                         break;
557                 }
558         }
559
560         splx (opri);
561
562 #if PCVT_KEYBDID
563
564         opri = spltty ();
565
566         if(kbd_cmd(KEYB_C_ID) != 0)
567         {
568                 printf("pcvt: doreset() - timeout for keyboard ID command\n");
569                 keyboard_type = KB_UNKNOWN;
570         }
571         else
572         {
573
574 r_entry:
575
576                 if((response = kbd_response()) == KEYB_R_MF2ID1)
577                 {
578                         if((response = kbd_response()) == KEYB_R_MF2ID2)
579                         {
580                                 keyboard_type = KB_MFII;
581                         }
582                         else if(response == KEYB_R_MF2ID2HP)
583                         {
584                                 keyboard_type = KB_MFII;
585                         }
586                         else
587                         {
588                                 printf("\npcvt: doreset() - kbdid, response 2 = [%d]\n",
589                                        response);
590                                 keyboard_type = KB_UNKNOWN;
591                         }
592                 }
593                 else if (response == KEYB_R_ACK)
594                 {
595                         goto r_entry;
596                 }
597                 else if (response == -1)
598                 {
599                         keyboard_type = KB_AT;
600                 }
601                 else
602                 {
603                         printf("\npcvt: doreset() - kbdid, response 1 = [%d]\n", response);
604                 }
605         }
606
607         splx (opri);
608
609 #else /* PCVT_KEYBDID */
610
611         keyboard_type = KB_MFII;        /* force it .. */
612
613 #endif /* PCVT_KEYBDID */
614
615 #else /* _DEV_KBD_KBDREG_H_ */
616         int type;
617
618         if (!reset_keyboard)    /* no, we are not ready to reset */
619                 return;
620
621         if (lost_intr_timeout_queued) {
622                 untimeout(check_for_lost_intr, (void *)NULL, lost_intr_ch);
623                 lost_intr_timeout_queued = 0;
624         }
625
626         if (kbd == NULL)
627                 return;         /* shouldn't happen */
628         kbd_configure(0);
629
630         ledstate = LEDSTATE_UPDATE_PENDING;
631
632 #if PCVT_USEKBDSEC              /* security enabled */
633
634 #  if PCVT_SCANSET == 2
635 #    define KBDINITCMD 0
636 #  else /* PCVT_SCANSET != 2 */
637 #    define KBDINITCMD KBD_TRANSLATION
638 #  endif /* PCVT_SCANSET == 2 */
639
640 #else /* ! PCVT_USEKBDSEC */    /* security disabled */
641
642 #  if PCVT_SCANSET == 2
643 #    define KBDINITCMD KBD_OVERRIDE_KBD_LOCK
644 #  else /* PCVT_SCANSET != 2 */
645 #    define KBDINITCMD KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK
646 #  endif /* PCVT_SCANSET == 2 */
647
648 #endif /* PCVT_USEKBDSEC */
649
650         set_controller_command_byte(*(KBDC *)kbd->kb_data,
651                 KBD_OVERRIDE_KBD_LOCK | KBD_TRANSLATION, KBDINITCMD);
652
653         keyboard_type = KB_MFII;        /* force it .. */
654 #if PCVT_KEYBDID
655         type = KB_101;
656         (*kbdsw[kbd->kb_index]->ioctl)(kbd, KDGKBTYPE, (caddr_t)&type);
657         switch (type)
658         {
659         case KB_84:
660                 keyboard_type = KB_AT;
661                 break;
662         case KB_101:
663                 keyboard_type = KB_MFII;
664                 break;
665         default:
666                 keyboard_type = KB_UNKNOWN;
667                 break;
668         }
669 #endif /* PCVT_KEYBDID */
670
671         update_led();
672
673         lost_intr_ch = timeout(check_for_lost_intr, (void *)NULL, hz);
674         lost_intr_timeout_queued = 1;
675
676 #endif /* !_DEV_KBD_KBDREG_H_ */
677 }
678
679 /*---------------------------------------------------------------------------*
680  *      init keyboard code
681  *---------------------------------------------------------------------------*/
682 void
683 kbd_code_init(void)
684 {
685         doreset();
686         ovlinit(0);
687         keyboard_is_initialized = 1;
688 }
689
690 /*---------------------------------------------------------------------------*
691  *      init keyboard code, this initializes the keyboard subsystem
692  *      just "a bit" so the very very first ddb session is able to
693  *      get proper keystrokes - in other words, it's a hack ....
694  *---------------------------------------------------------------------------*/
695 void
696 kbd_code_init1(void)
697 {
698         doreset();
699         keyboard_is_initialized = 1;
700 }
701
702 /*---------------------------------------------------------------------------*
703  *      init keyboard overlay table
704  *---------------------------------------------------------------------------*/
705 static
706 void ovlinit(int force)
707 {
708         register int i;
709
710         if(force || ovlinitflag==0)
711         {
712                 if(ovlinitflag == 0 &&
713                    (ovltbl = (Ovl_tbl *)malloc(sizeof(Ovl_tbl) * OVLTBL_SIZE,
714                                                M_DEVBUF, M_WAITOK)) == NULL)
715                         panic("pcvt_kbd: malloc of Ovl_tbl failed");
716
717                 for(i=0; i<OVLTBL_SIZE; i++)
718                 {
719                         ovltbl[i].keynum =
720                         ovltbl[i].type = 0;
721                         ovltbl[i].unshift[0] =
722                         ovltbl[i].shift[0] =
723                         ovltbl[i].ctrl[0] =
724                         ovltbl[i].altgr[0] = 0;
725                         ovltbl[i].subu =
726                         ovltbl[i].subs =
727                         ovltbl[i].subc =
728                         ovltbl[i].suba = KBD_SUBT_STR;  /* just strings .. */
729                 }
730                 for(i=0; i<=MAXKEYNUM; i++)
731                         key2ascii[i].type &= KBD_MASK;
732                 ovlinitflag = 1;
733         }
734 }
735
736 /*---------------------------------------------------------------------------*
737  *      get original key definition
738  *---------------------------------------------------------------------------*/
739 static int
740 getokeydef(unsigned key, Ovl_tbl *thisdef)
741 {
742         if(key == 0 || key > MAXKEYNUM)
743                 return EINVAL;
744
745         thisdef->keynum = key;
746         thisdef->type = key2ascii[key].type;
747
748         if(key2ascii[key].unshift.subtype == STR)
749         {
750                 bcopy((u_char *)(key2ascii[key].unshift.what.string),
751                        thisdef->unshift, CODE_SIZE);
752                 thisdef->subu = KBD_SUBT_STR;
753         }
754         else
755         {
756                 bcopy("", thisdef->unshift, CODE_SIZE);
757                 thisdef->subu = KBD_SUBT_FNC;
758         }
759
760         if(key2ascii[key].shift.subtype == STR)
761         {
762                 bcopy((u_char *)(key2ascii[key].shift.what.string),
763                        thisdef->shift, CODE_SIZE);
764                 thisdef->subs = KBD_SUBT_STR;
765         }
766         else
767         {
768                 bcopy("",thisdef->shift,CODE_SIZE);
769                 thisdef->subs = KBD_SUBT_FNC;
770         }
771
772         if(key2ascii[key].ctrl.subtype == STR)
773         {
774                 bcopy((u_char *)(key2ascii[key].ctrl.what.string),
775                        thisdef->ctrl, CODE_SIZE);
776                 thisdef->subc = KBD_SUBT_STR;
777         }
778         else
779         {
780                 bcopy("",thisdef->ctrl,CODE_SIZE);
781                 thisdef->subc = KBD_SUBT_FNC;
782         }
783
784         /* deliver at least anything for ALTGR settings ... */
785
786         if(key2ascii[key].unshift.subtype == STR)
787         {
788                 bcopy((u_char *)(key2ascii[key].unshift.what.string),
789                        thisdef->altgr, CODE_SIZE);
790                 thisdef->suba = KBD_SUBT_STR;
791         }
792         else
793         {
794                 bcopy("",thisdef->altgr, CODE_SIZE);
795                 thisdef->suba = KBD_SUBT_FNC;
796         }
797         return 0;
798 }
799
800 /*---------------------------------------------------------------------------*
801  *      get current key definition
802  *---------------------------------------------------------------------------*/
803 static int
804 getckeydef(unsigned key, Ovl_tbl *thisdef)
805 {
806         u_short type = key2ascii[key].type;
807
808         if(key>MAXKEYNUM)
809                 return EINVAL;
810
811         if(type & KBD_OVERLOAD)
812                 *thisdef = ovltbl[key2ascii[key].ovlindex];
813         else
814                 getokeydef(key,thisdef);
815
816         return 0;
817 }
818
819 /*---------------------------------------------------------------------------*
820  *      translate keynumber and returns ptr to associated ascii string
821  *      if key is bound to a function, executes it, and ret empty ptr
822  *---------------------------------------------------------------------------*/
823 static u_char *
824 xlatkey2ascii(U_short key)
825 {
826         static u_char   capchar[2] = {0, 0};
827 #if PCVT_META_ESC
828         static u_char   metachar[3] = {0x1b, 0, 0};
829 #else
830         static u_char   metachar[2] = {0, 0};
831 #endif
832         static Ovl_tbl  thisdef;
833         int             n;
834         void            (*fnc)(void);
835
836         if(key==0)                      /* ignore the NON-KEY */
837                 return 0;
838
839         getckeydef(key&0x7F, &thisdef); /* get the current ASCII value */
840
841         thisdef.type &= KBD_MASK;
842
843         if(key&0x80)                    /* special handling of ALT-KEYPAD */
844         {
845                 /* is the ALT Key released? */
846                 if(thisdef.type==KBD_META || thisdef.type==KBD_ALTGR)
847                 {
848                         if(altkpflag)   /* have we been in altkp mode? */
849                         {
850                                 capchar[0] = altkpval;
851                                 altkpflag = 0;
852                                 altkpval = 0;
853                                 return capchar;
854                         }
855                 }
856                 return 0;
857         }
858
859         switch(thisdef.type)            /* convert the keys */
860         {
861                 case KBD_BREAK:
862                 case KBD_ASCII:
863                 case KBD_FUNC:
864                         fnc = NULL;
865                         more_chars = NULL;
866
867                         if(altgr_down)
868                         {
869                                 more_chars = (u_char *)thisdef.altgr;
870                         }
871                         else if(!ctrl_down && (shift_down || vsp->shift_lock))
872                         {
873                                 if(key2ascii[key].shift.subtype == STR)
874                                         more_chars = (u_char *)thisdef.shift;
875                                 else
876                                         fnc = key2ascii[key].shift.what.func;
877                         }
878
879                         else if(ctrl_down)
880                         {
881                                 if(key2ascii[key].ctrl.subtype == STR)
882                                         more_chars = (u_char *)thisdef.ctrl;
883                                 else
884                                         fnc = key2ascii[key].ctrl.what.func;
885                         }
886
887                         else
888                         {
889                                 if(key2ascii[key].unshift.subtype == STR)
890                                         more_chars = (u_char *)thisdef.unshift;
891                                 else
892                                         fnc = key2ascii[key].unshift.what.func;
893                         }
894
895                         if(fnc)
896                                 (*fnc)();       /* execute function */
897
898                         if((more_chars != NULL) && (more_chars[1] == 0))
899                         {
900                                 if(vsp->caps_lock && more_chars[0] >= 'a'
901                                    && more_chars[0] <= 'z')
902                                 {
903                                         capchar[0] = *more_chars - ('a'-'A');
904                                         more_chars = capchar;
905                                 }
906                                 if(meta_down)
907                                 {
908 #if PCVT_META_ESC
909                                         metachar[1] = *more_chars;
910 #else
911                                         metachar[0] = *more_chars | 0x80;
912 #endif
913                                         more_chars = metachar;
914                                 }
915                         }
916                         return(more_chars);
917
918                 case KBD_KP:
919                         fnc = NULL;
920                         more_chars = NULL;
921
922                         if(meta_down)
923                         {
924                                 switch(key)
925                                 {
926                                         case 95:        /* / */
927                                                 altkpflag = 0;
928                                                 more_chars =
929                                                  (u_char *)"\033OQ";
930                                                 return(more_chars);
931
932                                         case 100:       /* * */
933                                                 altkpflag = 0;
934                                                 more_chars =
935                                                  (u_char *)"\033OR";
936                                                 return(more_chars);
937
938                                         case 105:       /* - */
939                                                 altkpflag = 0;
940                                                 more_chars =
941                                                  (u_char *)"\033OS";
942                                                 return(more_chars);
943                                 }
944                         }
945
946                         if(meta_down || altgr_down)
947                         {
948                                 if((n = keypad2num[key-91]) >= 0)
949                                 {
950                                         if(!altkpflag)
951                                         {
952                                                 /* start ALT-KP mode */
953                                                 altkpflag = 1;
954                                                 altkpval = 0;
955                                         }
956                                         altkpval *= 10;
957                                         altkpval += n;
958                                 }
959                                 else
960                                         altkpflag = 0;
961                                 return 0;
962                         }
963
964                         if(!(vsp->num_lock))
965                         {
966                                 if(key2ascii[key].shift.subtype == STR)
967                                         more_chars = (u_char *)thisdef.shift;
968                                 else
969                                         fnc = key2ascii[key].shift.what.func;
970                         }
971                         else
972                         {
973                                 if(key2ascii[key].unshift.subtype == STR)
974                                         more_chars = (u_char *)thisdef.unshift;
975                                 else
976                                         fnc = key2ascii[key].unshift.what.func;
977                         }
978
979                         if(fnc)
980                                 (*fnc)();       /* execute function */
981                         return(more_chars);
982
983                 case KBD_CURSOR:
984                         fnc = NULL;
985                         more_chars = NULL;
986
987                         if(vsp->ckm)
988                         {
989                                 if(key2ascii[key].shift.subtype == STR)
990                                         more_chars = (u_char *)thisdef.shift;
991                                 else
992                                         fnc = key2ascii[key].shift.what.func;
993                         }
994                         else
995                         {
996                                 if(key2ascii[key].unshift.subtype == STR)
997                                         more_chars = (u_char *)thisdef.unshift;
998                                 else
999                                         fnc = key2ascii[key].unshift.what.func;
1000                         }
1001
1002                         if(fnc)
1003                                 (*fnc)();       /* execute function */
1004                         return(more_chars);
1005
1006                 case KBD_NUM:           /*  special kp-num handling */
1007                         more_chars = NULL;
1008
1009                         if(meta_down)
1010                         {
1011                                 more_chars = (u_char *)"\033OP"; /* PF1 */
1012                         }
1013                         else
1014                         {
1015                                 vsp->num_lock ^= 1;
1016                                 update_led();
1017                         }
1018                         return(more_chars);
1019
1020                 case KBD_RETURN:
1021                         more_chars = NULL;
1022
1023                         if(!(vsp->num_lock))
1024                         {
1025                                 more_chars = (u_char *)thisdef.shift;
1026                         }
1027                         else
1028                         {
1029                                 more_chars = (u_char *)thisdef.unshift;
1030                         }
1031                         if(vsp->lnm && (*more_chars == '\r'))
1032                         {
1033                                 more_chars = (u_char *)"\r\n"; /* CR LF */
1034                         }
1035                         if(meta_down)
1036                         {
1037 #if PCVT_META_ESC
1038                                 metachar[1] = *more_chars;
1039 #else
1040                                 metachar[0] = *more_chars | 0x80;
1041 #endif
1042                                 more_chars = metachar;
1043                         }
1044                         return(more_chars);
1045
1046                 case KBD_META:          /* these keys are       */
1047                 case KBD_ALTGR:         /*  handled directly    */
1048                 case KBD_SCROLL:        /*  by the keyboard     */
1049                 case KBD_CAPS:          /*  handler - they are  */
1050                 case KBD_SHFTLOCK:      /*  ignored here        */
1051                 case KBD_CTL:
1052                 case KBD_NONE:
1053                 default:
1054                         return 0;
1055         }
1056 }
1057
1058 /*---------------------------------------------------------------------------*
1059  *      get keystrokes from the keyboard.
1060  *      if noblock = 0, wait until a key is pressed.
1061  *      else return NULL if no characters present.
1062  *---------------------------------------------------------------------------*/
1063
1064 #if PCVT_KBD_FIFO
1065 extern  u_char  pcvt_kbd_fifo[];
1066 extern  int     pcvt_kbd_rptr;
1067 extern  short   pcvt_kbd_count;
1068 #endif
1069
1070 u_char *
1071 sgetc(int noblock)
1072 {
1073         u_char          *cp;
1074         u_char          dt = 0;
1075         u_char          key = 0;
1076         u_short         type;
1077
1078 #if PCVT_KBD_FIFO && PCVT_SLOW_INTERRUPT
1079         int             s;
1080 #endif
1081
1082         static u_char   kbd_lastkey = 0; /* last keystroke */
1083
1084         static struct
1085         {
1086                 u_char extended: 1;     /* extended prefix seen */
1087                 u_char ext1: 1;         /* extended prefix 1 seen */
1088                 u_char breakseen: 1;    /* break code seen */
1089                 u_char vshift: 1;       /* virtual shift pending */
1090                 u_char vcontrol: 1;     /* virtual control pending */
1091                 u_char sysrq: 1;        /* sysrq pressed */
1092         } kbd_status = {0};
1093
1094 #ifdef XSERVER
1095         static char     keybuf[2] = {0}; /* the second 0 is a delimiter! */
1096 #endif /* XSERVER */
1097
1098 #ifdef _DEV_KBD_KBDREG_H_
1099         int             c;
1100 #endif /* _DEV_KBD_KBDREG_H_ */
1101
1102 loop:
1103
1104         if(noblock == 31337)
1105         {
1106                 vsp->scrolling = 1;
1107                 goto scroll_reset;
1108         }
1109
1110 #ifdef XSERVER
1111
1112 #ifndef _DEV_KBD_KBDREG_H_
1113
1114 #if PCVT_KBD_FIFO
1115
1116         /* see if there is data from the keyboard available either from */
1117         /* the keyboard fifo or from the 8042 keyboard controller       */
1118
1119         if (pcvt_kbd_count || (inb(CONTROLLER_CTRL) & STATUS_OUTPBF))
1120         {
1121                 if (!pcvt_kbd_count)    /* source = 8042 */
1122                 {
1123                         PCVT_KBD_DELAY();       /* 7 us delay */
1124                         dt = inb(CONTROLLER_DATA);      /* get from obuf */
1125                 }
1126                 else                    /* source = keyboard fifo */
1127                 {
1128                         dt = pcvt_kbd_fifo[pcvt_kbd_rptr++];
1129                         PCVT_DISABLE_INTR();
1130                         pcvt_kbd_count--;
1131                         PCVT_ENABLE_INTR();
1132                         if (pcvt_kbd_rptr >= PCVT_KBD_FIFO_SZ)
1133                                 pcvt_kbd_rptr = 0;
1134                 }
1135
1136 #else /* !PCVT_KB_FIFO */
1137
1138         /* see if there is data from the keyboard available from the 8042 */
1139
1140         if (inb(CONTROLLER_CTRL) & STATUS_OUTPBF)
1141         {
1142                 PCVT_KBD_DELAY();               /* 7 us delay */
1143                 dt = inb(CONTROLLER_DATA);      /* yes, get data */
1144
1145 #endif /* !PCVT_KBD_FIFO */
1146
1147 #else /* _DEV_KBD_KBDREG_H_ */
1148
1149 #if PCVT_KBD_FIFO
1150         if (pcvt_kbd_count) {
1151                 dt = pcvt_kbd_fifo[pcvt_kbd_rptr++];
1152                 PCVT_DISABLE_INTR();
1153                 pcvt_kbd_count--;
1154                 PCVT_ENABLE_INTR();
1155                 if (pcvt_kbd_rptr >= PCVT_KBD_FIFO_SZ)
1156                         pcvt_kbd_rptr = 0;
1157         } else
1158 #endif /* PCVT_KBD_FIFO */
1159         if (!noblock) {
1160                 while ((c = (*kbdsw[kbd->kb_index]->read)(kbd, TRUE)) == -1)
1161                         ;
1162                 dt = c;
1163         } else {
1164                 if ((c = (*kbdsw[kbd->kb_index]->read)(kbd, FALSE)) == -1)
1165                         return NULL;
1166                 dt = c;
1167         }
1168
1169         {
1170
1171 #endif /* !_DEV_KBD_KBDREG_H_ */
1172
1173                 /*
1174                  * If x mode is active, only care for locking keys, then
1175                  * return the scan code instead of any key translation.
1176                  * Additionally, this prevents us from any attempts to
1177                  * execute pcvt internal functions caused by keys (such
1178                  * as screen flipping).
1179                  * XXX For now, only the default locking key definitions
1180                  * are recognized (i.e. if you have overloaded you "A" key
1181                  * as NUMLOCK, that wont effect X mode:-)
1182                  * Changing this would be nice, but would require modifi-
1183                  * cations to the X server. After having this, X will
1184                  * deal with the LEDs itself, so we are committed.
1185                  */
1186                 /*
1187                  * Iff PCVT_USL_VT_COMPAT is defined, the behaviour has
1188                  * been fixed. We need not care about any keys here, since
1189                  * there are ioctls that deal with the lock key / LED stuff.
1190                  */
1191                 if (pcvt_kbd_raw)
1192                 {
1193                         keybuf[0] = dt;
1194
1195 #if PCVT_FREEBSD > 210
1196                         add_keyboard_randomness(dt);
1197 #endif  /* PCVT_FREEBSD > 210 */
1198
1199 #if !PCVT_USL_VT_COMPAT
1200                         if ((dt & 0x80) == 0)
1201                                 /* key make */
1202                                 switch(dt)
1203                                 {
1204                                 case 0x45:
1205                                         /* XXX on which virt screen? */                                 vsp->num_lock ^= 1;
1206                                         update_led();
1207                                         break;
1208
1209                                 case 0x3a:
1210                                         vsp->caps_lock ^= 1;
1211                                         update_led();
1212                                         break;
1213
1214                                 case 0x46:
1215                                         vsp->scroll_lock ^= 1;
1216                                         update_led();
1217                                         break;
1218                                 }
1219 #endif /* !PCVT_USL_VT_COMPAT */
1220
1221 #if PCVT_EMU_MOUSE
1222                         /*
1223                          * The (mouse systems) mouse emulator. The mouse
1224                          * device allocates the first device node that is
1225                          * not used by a virtual terminal. (E.g., you have
1226                          * eight vtys, /dev/ttyv0 thru /dev/ttyv7, so the
1227                          * mouse emulator were /dev/ttyv8.)
1228                          * Currently the emulator only works if the keyboard
1229                          * is in raw (PC scan code) mode. This is the typic-
1230                          * al case when running the X server.
1231                          * It is activated if the num locks LED is active
1232                          * for the current vty, and if the mouse device
1233                          * has been opened by at least one process. It
1234                          * grabs the numerical keypad events (but only
1235                          * the "non-extended", so the separate arrow keys
1236                          * continue to work), and three keys for the "mouse
1237                          * buttons", preferrably F1 thru F3. Any of the
1238                          * eight directions (N, NE, E, SE, S, SW, W, NW)
1239                          * is supported, and frequent key presses (less
1240                          * than e.g. half a second between key presses)
1241                          * cause the emulator to accelerate the pointer
1242                          * movement by 6, while single presses result in
1243                          * single moves, so each point can be reached.
1244                          */
1245                         /*
1246                          * NB: the following code is spagghetti.
1247                          * Only eat it with lotta tomato ketchup and
1248                          * Parmesan cheese:-)
1249                          */
1250                         /*
1251                          * look whether we will have to steal the keys
1252                          * and cook them into mouse events
1253                          */
1254                         if(vsp->num_lock && mouse.opened)
1255                         {
1256                                 int button, accel, i;
1257                                 enum mouse_dir
1258                                 {
1259                                         MOUSE_NW, MOUSE_N, MOUSE_NE,
1260                                         MOUSE_W,  MOUSE_0, MOUSE_E,
1261                                         MOUSE_SW, MOUSE_S, MOUSE_SE
1262                                 }
1263                                 move;
1264                                 struct timeval now;
1265                                 dev_t dummy = makedev(0, mouse.minor);
1266                                 struct tty *mousetty = get_pccons(dummy);
1267                                 /*
1268                                  * strings to send for each mouse event,
1269                                  * indexed by the movement direction and
1270                                  * the "accelerator" value (TRUE for frequent
1271                                  * key presses); note that the first byte
1272                                  * of each string is actually overwritten
1273                                  * by the current button value before sending
1274                                  * the string
1275                                  */
1276                                 static u_char mousestrings[2][MOUSE_SE+1][5] =
1277                                 {
1278                                 {
1279                                         /* first, the non-accelerated strings*/
1280                                         {0x87,  -1,   1,   0,   0}, /* NW */
1281                                         {0x87,   0,   1,   0,   0}, /* N */
1282                                         {0x87,   1,   1,   0,   0}, /* NE */
1283                                         {0x87,  -1,   0,   0,   0}, /* W */
1284                                         {0x87,   0,   0,   0,   0}, /* 0 */
1285                                         {0x87,   1,   0,   0,   0}, /* E */
1286                                         {0x87,  -1,  -1,   0,   0}, /* SW */
1287                                         {0x87,   0,  -1,   0,   0}, /* S */
1288                                         {0x87,   1,  -1,   0,   0}  /* SE */
1289                                 },
1290                                 {
1291                                         /* now, 6 steps at once */
1292                                         {0x87,  -4,   4,   0,   0}, /* NW */
1293                                         {0x87,   0,   6,   0,   0}, /* N */
1294                                         {0x87,   4,   4,   0,   0}, /* NE */
1295                                         {0x87,  -6,   0,   0,   0}, /* W */
1296                                         {0x87,   0,   0,   0,   0}, /* 0 */
1297                                         {0x87,   6,   0,   0,   0}, /* E */
1298                                         {0x87,  -4,  -4,   0,   0}, /* SW */
1299                                         {0x87,   0,  -6,   0,   0}, /* S */
1300                                         {0x87,   4,  -4,   0,   0}  /* SE */
1301                                 }
1302                                 };
1303
1304                                 if(dt == 0xe0)
1305                                 {
1306                                         /* ignore extended scan codes */
1307                                         mouse.extendedseen = 1;
1308                                         goto no_mouse_event;
1309                                 }
1310                                 if(mouse.extendedseen)
1311                                 {
1312                                         mouse.extendedseen = 0;
1313                                         goto no_mouse_event;
1314                                 }
1315                                 mouse.extendedseen = 0;
1316
1317                                 /*
1318                                  * Note that we cannot use a switch here
1319                                  * since we want to have the keycodes in
1320                                  * a variable
1321                                  */
1322                                 if((dt & 0x7f) == mousedef.leftbutton) {
1323                                         button = 4;
1324                                         goto do_button;
1325                                 }
1326                                 else if((dt & 0x7f) == mousedef.middlebutton) {
1327                                         button = 2;
1328                                         goto do_button;
1329                                 }
1330                                 else if((dt & 0x7f) == mousedef.rightbutton) {
1331                                         button = 1;
1332                                 do_button:
1333
1334                                         /*
1335                                          * i would really like to give
1336                                          * some acustical support
1337                                          * (pling/plong); i am not sure
1338                                          * whether it is safe to call
1339                                          * sysbeep from within an intr
1340                                          * service, since it calls
1341                                          * timeout in turn which mani-
1342                                          * pulates the spl mask - jw
1343                                          */
1344
1345 # define PLING sysbeep(PCVT_SYSBEEPF / 1500, 2)
1346 # define PLONG sysbeep(PCVT_SYSBEEPF / 1200, 2)
1347
1348                                         if(mousedef.stickybuttons)
1349                                         {
1350                                                 if(dt & 0x80) {
1351                                                         mouse.breakseen = 1;
1352                                                         return (u_char *)0;
1353                                                 }
1354                                                 else if(mouse.buttons == button
1355                                                         && !mouse.breakseen) {
1356                                                         /* ignore repeats */
1357                                                         return (u_char *)0;
1358                                                 }
1359                                                 else
1360                                                         mouse.breakseen = 0;
1361                                                 if(mouse.buttons == button) {
1362                                                         /* release it */
1363                                                         mouse.buttons = 0;
1364                                                         PLONG;
1365                                                 } else {
1366                                                         /*
1367                                                          * eventually, release
1368                                                          * any other button,
1369                                                          * and stick this one
1370                                                          */
1371                                                         mouse.buttons = button;
1372                                                         PLING;
1373                                                 }
1374                                         }
1375                                         else
1376                                         {
1377                                                 if(dt & 0x80) {
1378                                                         mouse.buttons &=
1379                                                                 ~button;
1380                                                         PLONG;
1381                                                 }
1382                                                 else if((mouse.buttons
1383                                                         & button) == 0) {
1384                                                         mouse.buttons |=
1385                                                                 button;
1386                                                         PLING;
1387                                                 }
1388                                                 /*else: ignore same btn press*/
1389                                         }
1390                                         move = MOUSE_0;
1391                                         accel = 0;
1392                                 }
1393 # undef PLING
1394 # undef PLONG
1395                                 else switch(dt & 0x7f)
1396                                 {
1397                                 /* the arrow keys - KP 1 thru KP 9 */
1398                                 case 0x47:      move = MOUSE_NW; goto do_move;
1399                                 case 0x48:      move = MOUSE_N; goto do_move;
1400                                 case 0x49:      move = MOUSE_NE; goto do_move;
1401                                 case 0x4b:      move = MOUSE_W; goto do_move;
1402                                 case 0x4c:      move = MOUSE_0; goto do_move;
1403                                 case 0x4d:      move = MOUSE_E; goto do_move;
1404                                 case 0x4f:      move = MOUSE_SW; goto do_move;
1405                                 case 0x50:      move = MOUSE_S; goto do_move;
1406                                 case 0x51:      move = MOUSE_SE;
1407                                 do_move:
1408                                         if(dt & 0x80)
1409                                                 /*
1410                                                  * arrow key break events are
1411                                                  * of no importance for us
1412                                                  */
1413                                                 return (u_char *)0;
1414                                         /*
1415                                          * see whether the last move did
1416                                          * happen "recently", i.e. before
1417                                          * less than half a second
1418                                          */
1419                                         getmicrotime(&now);
1420                                         timevalsub(&now, &mouse.lastmove);
1421                                         getmicrotime(&mouse.lastmove);
1422                                         accel = (now.tv_sec == 0
1423                                                  && now.tv_usec
1424                                                  < mousedef.acceltime);
1425                                         break;
1426
1427                                 default: /* not a mouse-emulating key */
1428                                         goto no_mouse_event;
1429                                 }
1430                                 mousestrings[accel][move][0] =
1431                                         0x80 + (~mouse.buttons & 7);
1432                                 /* finally, send the string */
1433                                 for(i = 0; i < 5; i++)
1434                                         (*linesw[mousetty->t_line].l_rint)
1435                                                 (mousestrings[accel][move][i],
1436                                                  mousetty);
1437                                 return (u_char *)0; /* not a kbd event */
1438                         }
1439 no_mouse_event:
1440
1441 #endif /* PCVT_EMU_MOUSE */
1442
1443                         return ((u_char *)keybuf);
1444                 }
1445         }
1446
1447 #else /* !XSERVER */
1448
1449 #ifndef  _DEV_KBD_KBDREG_H_
1450
1451 #  if PCVT_KBD_FIFO
1452
1453         /* see if there is data from the keyboard available either from */
1454         /* the keyboard fifo or from the 8042 keyboard controller       */
1455
1456         if (pcvt_kbd_count || (inb(CONTROLLER_CTRL) & STATUS_OUTPBF))
1457         {
1458                 if (!noblock || kbd_polling)    /* source = 8042 */
1459                 {
1460                         PCVT_KBD_DELAY();       /* 7 us delay */
1461                         dt = inb(CONTROLLER_DATA);
1462                 }
1463                 else                    /* source = keyboard fifo */
1464                 {
1465                         dt = pcvt_kbd_fifo[pcvt_kbd_rptr++]; /* yes, get it ! */
1466                         PCVT_DISABLE_INTR();
1467                         pcvt_kbd_count--;
1468                         PCVT_ENABLE_INTR();
1469                         if (pcvt_kbd_rptr >= PCVT_KBD_FIFO_SZ)
1470                                 pcvt_kbd_rptr = 0;
1471                 }
1472         }
1473
1474 #else /* !PCVT_KBD_FIFO */
1475
1476         /* see if there is data from the keyboard available from the 8042 */
1477
1478         if(inb(CONTROLLER_CTRL) & STATUS_OUTPBF)
1479         {
1480                 PCVT_KBD_DELAY();               /* 7 us delay */
1481                 dt = inb(CONTROLLER_DATA);      /* yes, get data ! */
1482         }
1483
1484 #endif /* !PCVT_KBD_FIFO */
1485
1486 #else /* _DEV_KBD_KBDREG_H_ */
1487
1488 #if PCVT_KBD_FIFO
1489         if (pcvt_kbd_count) {
1490                 dt = pcvt_kbd_fifo[pcvt_kbd_rptr++];
1491                 PCVT_DISABLE_INTR();
1492                 pcvt_kbd_count--;
1493                 PCVT_ENABLE_INTR();
1494                 if (pcvt_kbd_rptr >= PCVT_KBD_FIFO_SZ)
1495                         pcvt_kbd_rptr = 0;
1496         } else
1497 #endif /* PCVT_KBD_FIFO */
1498         if (!noblock) {
1499                 while ((c = (*kbdsw[kbd->kb_index]->read)(kbd, TRUE)) == -1)
1500                         ;
1501                 dt = c;
1502         } else {
1503                 if ((c = (*kbdsw[kbd->kb_index]->read)(kbd, FALSE)) == -1)
1504                         return NULL;
1505                 dt = c;
1506         }
1507
1508 #endif /* !_DEV_KBD_KBDREG_H_ */
1509
1510 #endif /* !XSERVER */
1511
1512 #ifndef _DEV_KBD_KBDREG_H_
1513         else
1514         {
1515                 if(noblock)
1516                         return NULL;
1517                 else
1518                         goto loop;
1519         }
1520 #endif /* !_DEV_KBD_KBDREG_H_ */
1521
1522 #if PCVT_SHOWKEYS
1523         showkey (' ', dt);
1524 #endif  /* PCVT_SHOWKEYS */
1525
1526         /* lets look what we got */
1527         switch(dt)
1528         {
1529                 case KEYB_R_OVERRUN0:   /* keyboard buffer overflow */
1530
1531 #if PCVT_SCANSET == 2
1532                 case KEYB_R_SELFOK:     /* keyboard selftest ok */
1533 #endif /* PCVT_SCANSET == 2 */
1534
1535                 case KEYB_R_ECHO:       /* keyboard response to KEYB_C_ECHO */
1536                 case KEYB_R_ACK:        /* acknowledge after command has rx'd*/
1537                 case KEYB_R_SELFBAD:    /* keyboard selftest FAILED */
1538                 case KEYB_R_DIAGBAD:    /* keyboard self diagnostic failure */
1539                 case KEYB_R_RESEND:     /* keyboard wants us to resend cmnd */
1540                 case KEYB_R_OVERRUN1:   /* keyboard buffer overflow */
1541                         break;
1542
1543                 case KEYB_R_EXT1:       /* keyboard extended scancode pfx 2 */
1544                         kbd_status.ext1 = 1;
1545                         /* FALLTHROUGH */
1546                 case KEYB_R_EXT0:       /* keyboard extended scancode pfx 1 */
1547                         kbd_status.extended = 1;
1548                         break;
1549
1550 #if PCVT_SCANSET == 2
1551                 case KEYB_R_BREAKPFX:   /* break code prefix for set 2 and 3 */
1552                         kbd_status.breakseen = 1;
1553                         break;
1554 #endif /* PCVT_SCANSET == 2 */
1555
1556                 default:
1557                         goto regular;   /* regular key */
1558         }
1559
1560         if(noblock)
1561                 return NULL;
1562         else
1563                 goto loop;
1564
1565         /* got a normal scan key */
1566 regular:
1567
1568 #if PCVT_FREEBSD > 210
1569         add_keyboard_randomness(dt);
1570 #endif  /* PCVT_FREEBSD > 210 */
1571
1572 #if PCVT_SCANSET == 1
1573         kbd_status.breakseen = dt & 0x80 ? 1 : 0;
1574         dt &= 0x7f;
1575 #endif  /* PCVT_SCANSET == 1 */
1576
1577         /*   make a keycode from scan code      */
1578         if(dt >= sizeof scantokey / sizeof(u_char))
1579                 key = 0;
1580         else
1581                 key = kbd_status.extended ? extscantokey[dt] : scantokey[dt];
1582
1583         if(kbd_status.ext1 && key == 64)
1584                 /* virtual control key */
1585                 key = 129;
1586
1587         kbd_status.extended = kbd_status.ext1 = 0;
1588
1589         if ((key == 85) && shift_down && kbd_lastkey != 85)
1590         {
1591                 if (vsp->scr_offset > (vsp->screen_rows - 1))
1592                 {
1593                         if (!vsp->scrolling)
1594                         {
1595                                 vsp->scrolling += vsp->screen_rows - 2;
1596                                 if (vsp->Scrollback)
1597                                 {
1598                                         scrollback_save_screen();
1599                                         if (vsp->scr_offset == vsp->max_off)
1600                                         {
1601                                                 bcopy(vsp->Scrollback +
1602                                                       vsp->maxcol,
1603                                                       vsp->Scrollback,
1604                                                       vsp->maxcol *
1605                                                       vsp->max_off * CHR);
1606                                                 vsp->scr_offset--;
1607                                         }
1608                                         bcopy(vsp->Crtat + vsp->cur_offset -
1609                                               vsp->col, vsp->Scrollback +
1610                                               ((vsp->scr_offset + 1) *
1611                                               vsp->maxcol), vsp->maxcol * CHR);
1612                                 }
1613
1614                                 if (vsp->cursor_on)
1615                                         sw_cursor(0);
1616                         }
1617
1618                         vsp->scrolling += vsp->screen_rows - 1;
1619
1620                         if (vsp->scrolling > vsp->scr_offset)
1621                                 vsp->scrolling = vsp->scr_offset;
1622
1623                         bcopy(vsp->Scrollback + ((vsp->scr_offset -
1624                               vsp->scrolling) * vsp->maxcol), vsp->Crtat,
1625                               vsp->screen_rows * vsp->maxcol * CHR);
1626                 }
1627
1628                 kbd_lastkey = 85;
1629                 goto loop;
1630         }
1631         else if ((key == 86) && shift_down && kbd_lastkey != 86)
1632         {
1633
1634 scroll_reset:
1635                 if (vsp->scrolling > 0)
1636                 {
1637                         vsp->scrolling -= vsp->screen_rows - 1;
1638                         if (vsp->scrolling < 0)
1639                                 vsp->scrolling = 0;
1640
1641                         if (vsp->scrolling <= vsp->screen_rows)
1642                         {
1643                                 vsp->scrolling = 0;
1644                                 scrollback_restore_screen();
1645                         }
1646                         else
1647                         {
1648                                 bcopy(vsp->Scrollback + ((vsp->scr_offset -
1649                                       vsp->scrolling) * vsp->maxcol),
1650                                       vsp->Crtat, vsp->screen_rows *
1651                                       vsp->maxcol * CHR);
1652                         }
1653                 }
1654
1655                 if (vsp->scrolling == 0)
1656                 {
1657                         if (vsp->cursor_on)
1658                         {
1659                                 sw_cursor(1);
1660                         }
1661                 }
1662
1663                 if (noblock == 31337)
1664                         return NULL;
1665
1666                 if (key != 86)
1667                 {
1668                         goto regular;
1669                 }
1670                 else
1671                 {
1672                         kbd_lastkey = 86;
1673                         goto loop;
1674                 }
1675         }
1676         else if (vsp->scrolling && key != 128 && key != 44 && key != 85 &&
1677                  key != 86)
1678         {
1679                 vsp->scrolling = 1;
1680                 goto scroll_reset;
1681         }
1682
1683 #if PCVT_CTRL_ALT_DEL           /*   Check for cntl-alt-del     */
1684         if((key == 76) && ctrl_down && (meta_down||altgr_down))
1685                 shutdown_nice(0);
1686 #endif /* PCVT_CTRL_ALT_DEL */
1687
1688 #if !(PCVT_NETBSD || PCVT_FREEBSD >= 200)
1689 #include "ddb.h"
1690 #endif /* !(PCVT_NETBSD || PCVT_FREEBSD >= 200) */
1691
1692 #if NDDB > 0 || defined(DDB)             /*   Check for cntl-alt-esc    */
1693
1694         if((key == 110) && ctrl_down && (meta_down || altgr_down))
1695         {
1696                 static u_char in_Debugger;
1697
1698                 if(!in_Debugger)
1699                 {
1700                         in_Debugger = 1;
1701 #if PCVT_FREEBSD
1702                         /* the string is actually not used... */
1703                         Debugger("kbd");
1704 #else
1705                         Debugger();
1706 #endif
1707                         in_Debugger = 0;
1708                         if(noblock)
1709                                 return NULL;
1710                         else
1711                                 goto loop;
1712                 }
1713         }
1714 #endif /* NDDB > 0 || defined(DDB) */
1715
1716         /* look for keys with special handling */
1717         if(key == 128)
1718         {
1719                 /*
1720                  * virtual shift; sent around PrtScr, and around the arrow
1721                  * keys if the NumLck LED is on
1722                  */
1723                 kbd_status.vshift = !kbd_status.breakseen;
1724                 key = 0;        /* no key */
1725         }
1726         else if(key == 129)
1727         {
1728                 /*
1729                  * virtual control - the most ugly thingie at all
1730                  * the Pause key sends:
1731                  * <virtual control make> <numlock make> <virtual control
1732                  * break> <numlock break>
1733                  */
1734                 if(!kbd_status.breakseen)
1735                         kbd_status.vcontrol = 1;
1736                 /* else: let the numlock hook clear this */
1737                 key = 0;        /* no key */
1738         }
1739         else if(key == 90)
1740         {
1741                 /* NumLock, look whether this is rather a Pause */
1742                 if(kbd_status.vcontrol)
1743                         key = 126;
1744                 /*
1745                  * if this is the final break code of a Pause key,
1746                  * clear the virtual control status, too
1747                  */
1748                 if(kbd_status.vcontrol && kbd_status.breakseen)
1749                         kbd_status.vcontrol = 0;
1750         }
1751         else if(key == 127)
1752         {
1753                 /*
1754                  * a SysRq; some keyboards are brain-dead enough to
1755                  * repeat the SysRq key make code by sending PrtScr
1756                  * make codes; other keyboards do not repeat SysRq
1757                  * at all. We keep track of the SysRq state here.
1758                  */
1759                 kbd_status.sysrq = !kbd_status.breakseen;
1760         }
1761         else if(key == 124)
1762         {
1763                 /*
1764                  * PrtScr; look whether this is really PrtScr or rather
1765                  * a silly repeat of a SysRq key
1766                  */
1767                 if(kbd_status.sysrq)
1768                         /* ignore the garbage */
1769                         key = 0;
1770         }
1771
1772         /* in NOREPEAT MODE ignore the key if it was the same as before */
1773
1774         if(!kbrepflag && key == kbd_lastkey && !kbd_status.breakseen)
1775         {
1776                 if(noblock)
1777                         return NULL;
1778                 else
1779                         goto loop;
1780         }
1781
1782         type = key2ascii[key].type;
1783
1784         if(type & KBD_OVERLOAD)
1785                 type = ovltbl[key2ascii[key].ovlindex].type;
1786
1787         type &= KBD_MASK;
1788
1789         switch(type)
1790         {
1791                 case KBD_SHFTLOCK:
1792                         if(!kbd_status.breakseen && key != kbd_lastkey)
1793                         {
1794                                 vsp->shift_lock ^= 1;
1795                         }
1796                         break;
1797
1798                 case KBD_CAPS:
1799                         if(!kbd_status.breakseen && key != kbd_lastkey)
1800                         {
1801                                 vsp->caps_lock ^= 1;
1802                                 update_led();
1803                         }
1804                         break;
1805
1806                 case KBD_SCROLL:
1807                         if(!kbd_status.breakseen && key != kbd_lastkey)
1808                         {
1809                                 vsp->scroll_lock ^= 1;
1810                                 update_led();
1811
1812                                 if(!(vsp->scroll_lock))
1813                                 {
1814                                         /* someone may be sleeping */
1815                                         wakeup((caddr_t)&(vsp->scroll_lock));
1816                                 }
1817                         }
1818                         break;
1819
1820                 case KBD_SHIFT:
1821                         shift_down = kbd_status.breakseen ? 0 : 1;
1822                         break;
1823
1824                 case KBD_META:
1825                         meta_down = kbd_status.breakseen ? 0 : 0x80;
1826                         break;
1827
1828                 case KBD_ALTGR:
1829                         altgr_down = kbd_status.breakseen ? 0 : 1;
1830                         break;
1831
1832                 case KBD_CTL:
1833                         ctrl_down = kbd_status.breakseen ? 0 : 1;
1834                         break;
1835
1836                 case KBD_NONE:
1837                 default:
1838                         break;                  /* deliver a key */
1839         }
1840
1841         if(kbd_status.breakseen)
1842         {
1843                 key |= 0x80;
1844                 kbd_status.breakseen = 0;
1845                 kbd_lastkey = 0; /* -hv- I know this is a bug with */
1846         }                        /* N-Key-Rollover, but I ignore that */
1847         else                     /* because avoidance is too complicated */
1848                 kbd_lastkey = key;
1849
1850         cp = xlatkey2ascii(key);        /* have a key */
1851
1852         if(cp == NULL && !noblock)
1853                 goto loop;
1854
1855         return cp;
1856 }
1857
1858 /*---------------------------------------------------------------------------*
1859  *      reflect status of locking keys & set led's
1860  *---------------------------------------------------------------------------*/
1861 static void
1862 setlockkeys(int snc)
1863 {
1864         vsp->scroll_lock = snc & 1;
1865         vsp->num_lock    = (snc & 2) ? 1 : 0;
1866         vsp->caps_lock   = (snc & 4) ? 1 : 0;
1867         update_led();
1868 }
1869
1870 /*---------------------------------------------------------------------------*
1871  *      remove a key definition
1872  *---------------------------------------------------------------------------*/
1873 static int
1874 rmkeydef(int key)
1875 {
1876         register Ovl_tbl *ref;
1877
1878         if(key==0 || key > MAXKEYNUM)
1879                 return EINVAL;
1880
1881         if(key2ascii[key].type & KBD_OVERLOAD)
1882         {
1883                 ref = &ovltbl[key2ascii[key].ovlindex];
1884                 ref->keynum = 0;
1885                 ref->type = 0;
1886                 ref->unshift[0] =
1887                 ref->shift[0] =
1888                 ref->ctrl[0] =
1889                 ref->altgr[0] = 0;
1890                 key2ascii[key].type &= KBD_MASK;
1891         }
1892         return 0;
1893 }
1894
1895 /*---------------------------------------------------------------------------*
1896  *      overlay a key
1897  *---------------------------------------------------------------------------*/
1898 static int
1899 setkeydef(Ovl_tbl *data)
1900 {
1901         register int i;
1902
1903         if( data->keynum > MAXKEYNUM             ||
1904             (data->type & KBD_MASK) == KBD_BREAK ||
1905             (data->type & KBD_MASK) > KBD_SHFTLOCK)
1906                 return EINVAL;
1907
1908         data->unshift[KBDMAXOVLKEYSIZE] =
1909         data->shift[KBDMAXOVLKEYSIZE] =
1910         data->ctrl[KBDMAXOVLKEYSIZE] =
1911         data->altgr[KBDMAXOVLKEYSIZE] = 0;
1912
1913         data->subu =
1914         data->subs =
1915         data->subc =
1916         data->suba = KBD_SUBT_STR;              /* just strings .. */
1917
1918         data->type |= KBD_OVERLOAD;             /* mark overloaded */
1919
1920         /* if key already overloaded, use that slot else find free slot */
1921
1922         if(key2ascii[data->keynum].type & KBD_OVERLOAD)
1923         {
1924                 i = key2ascii[data->keynum].ovlindex;
1925         }
1926         else
1927         {
1928                 for(i=0; i<OVLTBL_SIZE; i++)
1929                         if(ovltbl[i].keynum==0)
1930                                 break;
1931
1932                 if(i==OVLTBL_SIZE)
1933                         return ENOSPC;  /* no space, abuse of ENOSPC(!) */
1934         }
1935
1936         ovltbl[i] = *data;              /* copy new data string */
1937
1938         key2ascii[data->keynum].type |= KBD_OVERLOAD;   /* mark key */
1939         key2ascii[data->keynum].ovlindex = i;
1940
1941         return 0;
1942 }
1943
1944 /*---------------------------------------------------------------------------*
1945  *      keyboard ioctl's entry
1946  *---------------------------------------------------------------------------*/
1947 int
1948 kbdioctl(Dev_t dev, int cmd, caddr_t data, int flag)
1949 {
1950         int key;
1951
1952         switch(cmd)
1953         {
1954                 case KBDRESET:
1955                         doreset();
1956                         ovlinit(1);
1957                         settpmrate(KBD_TPD500|KBD_TPM100);
1958                         setlockkeys(0);
1959                         break;
1960
1961                 case KBDGTPMAT:
1962                         *(int *)data = tpmrate;
1963                         break;
1964
1965                 case KBDSTPMAT:
1966                         settpmrate(*(int *)data);
1967                         break;
1968
1969                 case KBDGREPSW:
1970                         *(int *)data = kbrepflag;
1971                         break;
1972
1973                 case KBDSREPSW:
1974                         kbrepflag = (*(int *)data) & 1;
1975                         break;
1976
1977                 case KBDGLEDS:
1978                         *(int *)data = ledstate;
1979                         break;
1980
1981                 case KBDSLEDS:
1982                         update_led();   /* ? */
1983                         break;
1984
1985                 case KBDGLOCK:
1986                         *(int *)data = ( (vsp->scroll_lock) |
1987                                          (vsp->num_lock * 2) |
1988                                          (vsp->caps_lock * 4));
1989                         break;
1990
1991                 case KBDSLOCK:
1992                         setlockkeys(*(int *)data);
1993                         break;
1994
1995                 case KBDGCKEY:
1996                         key = ((Ovl_tbl *)data)->keynum;
1997                         return getckeydef(key,(Ovl_tbl *)data);
1998
1999                 case KBDSCKEY:
2000                         key = ((Ovl_tbl *)data)->keynum;
2001                         return setkeydef((Ovl_tbl *)data);
2002
2003                 case KBDGOKEY:
2004                         key = ((Ovl_tbl *)data)->keynum;
2005                         return getokeydef(key,(Ovl_tbl *)data);
2006
2007                 case KBDRMKEY:
2008                         key = *(int *)data;
2009                         return rmkeydef(key);
2010
2011                 case KBDDEFAULT:
2012                         ovlinit(1);
2013                         break;
2014
2015                 default:
2016                         /* proceed with vga ioctls */
2017                         return -1;
2018         }
2019         return 0;
2020 }
2021
2022 #if PCVT_EMU_MOUSE
2023 /*--------------------------------------------------------------------------*
2024  *      mouse emulator ioctl
2025  *--------------------------------------------------------------------------*/
2026 int
2027 mouse_ioctl(Dev_t dev, int cmd, caddr_t data)
2028 {
2029         struct mousedefs *def = (struct mousedefs *)data;
2030
2031         switch(cmd)
2032         {
2033                 case KBDMOUSEGET:
2034                         *def = mousedef;
2035                         break;
2036
2037                 case KBDMOUSESET:
2038                         mousedef = *def;
2039                         break;
2040
2041                 default:
2042                         return -1;
2043         }
2044         return 0;
2045 }
2046 #endif  /* PCVT_EMU_MOUSE */
2047
2048 #if PCVT_USL_VT_COMPAT
2049 /*---------------------------------------------------------------------------*
2050  *      convert ISO-8859 style keycode into IBM 437
2051  *---------------------------------------------------------------------------*/
2052 static __inline u_char
2053 iso2ibm(u_char c)
2054 {
2055         if(c < 0x80)
2056                 return c;
2057         return iso2ibm437[c - 0x80];
2058 }
2059
2060 /*---------------------------------------------------------------------------*
2061  *      build up a USL style keyboard map
2062  *---------------------------------------------------------------------------*/
2063 void
2064 get_usl_keymap(keymap_t *map)
2065 {
2066         int i;
2067
2068         bzero((caddr_t)map, sizeof(keymap_t));
2069
2070         map->n_keys = 0x59;     /* that many keys we know about */
2071
2072         for(i = 1; i < N_KEYNUMS; i++)
2073         {
2074                 Ovl_tbl kdef;
2075                 u_char c;
2076                 int j;
2077                 int idx = key2scan1[i];
2078
2079                 if(idx == 0 || idx >= map->n_keys)
2080                         continue;
2081
2082                 getckeydef(i, &kdef);
2083                 kdef.type &= KBD_MASK;
2084                 switch(kdef.type)
2085                 {
2086                 case KBD_ASCII:
2087                 case KBD_RETURN:
2088                         map->key[idx].map[0] = iso2ibm(kdef.unshift[0]);
2089                         map->key[idx].map[1] = iso2ibm(kdef.shift[0]);
2090                         map->key[idx].map[2] = map->key[idx].map[3] =
2091                                 iso2ibm(kdef.ctrl[0]);
2092                         map->key[idx].map[4] = map->key[idx].map[5] =
2093                                 iso2ibm(c = kdef.altgr[0]);
2094                         /*
2095                          * XXX this is a hack
2096                          * since we currently do not map strings to AltGr +
2097                          * shift, we attempt to use the unshifted AltGr
2098                          * definition here and try to toggle the case
2099                          * this should at least work for ISO8859 letters,
2100                          * but also for (e.g.) russian KOI-8 style
2101                          */
2102                         if((c & 0x7f) >= 0x40)
2103                                 map->key[idx].map[5] = iso2ibm(c ^ 0x20);
2104                         break;
2105
2106                 case KBD_FUNC:
2107                         /* we are only interested in F1 thru F12 here */
2108                         if(i >= 112 && i <= 123) {
2109                                 map->key[idx].map[0] = i - 112 + 27;
2110                                 map->key[idx].spcl = 0x80;
2111                         }
2112                         break;
2113
2114                 case KBD_SHIFT:
2115                         c = i == 44? 2 /* lSh */: 3 /* rSh */; goto special;
2116
2117                 case KBD_CAPS:
2118                         c = 4; goto special;
2119
2120                 case KBD_NUM:
2121                         c = 5; goto special;
2122
2123                 case KBD_SCROLL:
2124                         c = 6; goto special;
2125
2126                 case KBD_META:
2127                         c = 7; goto special;
2128
2129                 case KBD_CTL:
2130                         c = 9; goto special;
2131                 special:
2132                         for(j = 0; j < NUM_STATES; j++)
2133                                 map->key[idx].map[j] = c;
2134                         map->key[idx].spcl = 0xff;
2135                         break;
2136
2137                 default:
2138                         break;
2139                 }
2140         }
2141 }
2142
2143 #endif /* PCVT_USL_VT_COMPAT */
2144
2145 /*---------------------------------------------------------------------------*
2146  *      switch keypad to numeric mode
2147  *---------------------------------------------------------------------------*/
2148 void
2149 vt_keynum(struct video_state *svsp)
2150 {
2151         svsp->num_lock = 1;
2152         update_led();
2153 }
2154
2155 /*---------------------------------------------------------------------------*
2156  *      switch keypad to application mode
2157  *---------------------------------------------------------------------------*/
2158 void
2159 vt_keyappl(struct video_state *svsp)
2160 {
2161         svsp->num_lock = 0;
2162         update_led();
2163 }
2164
2165 #if !PCVT_VT220KEYB     /* !PCVT_VT220KEYB, HP-like Keyboard layout */
2166
2167 /*---------------------------------------------------------------------------*
2168  *      function bound to function key 1
2169  *---------------------------------------------------------------------------*/
2170 static void
2171 fkey1(void)
2172 {
2173         if(!meta_down)
2174         {
2175                 if((vsp->vt_pure_mode == M_HPVT)
2176                    && (vsp->which_fkl == SYS_FKL))
2177                         toggl_columns(vsp);
2178                 else
2179                         more_chars = (u_char *)"\033[17~";      /* F6 */
2180         }
2181         else
2182         {
2183                 if(vsp->vt_pure_mode == M_PUREVT
2184                    || (vsp->which_fkl == USR_FKL))
2185                         more_chars = (u_char *)"\033[26~";      /* F14 */
2186         }
2187 }
2188
2189 /*---------------------------------------------------------------------------*
2190  *      function bound to function key 2
2191  *---------------------------------------------------------------------------*/
2192 static void
2193 fkey2(void)
2194 {
2195         if(!meta_down)
2196         {
2197                 if((vsp->vt_pure_mode == M_HPVT)
2198                    && (vsp->which_fkl == SYS_FKL))
2199                         vt_ris(vsp);
2200                 else
2201                         more_chars = (u_char *)"\033[18~";      /* F7 */
2202         }
2203         else
2204         {
2205                 if(vsp->vt_pure_mode == M_PUREVT
2206                    || (vsp->which_fkl == USR_FKL))
2207                         more_chars = (u_char *)"\033[28~";      /* HELP */
2208         }
2209 }
2210
2211 /*---------------------------------------------------------------------------*
2212  *      function bound to function key 3
2213  *---------------------------------------------------------------------------*/
2214 static void
2215 fkey3(void)
2216 {
2217         if(!meta_down)
2218         {
2219                 if((vsp->vt_pure_mode == M_HPVT)
2220                    && (vsp->which_fkl == SYS_FKL))
2221                         toggl_24l(vsp);
2222                 else
2223                         more_chars = (u_char *)"\033[19~";      /* F8 */
2224         }
2225         else
2226         {
2227                 if(vsp->vt_pure_mode == M_PUREVT
2228                    || (vsp->which_fkl == USR_FKL))
2229                         more_chars = (u_char *)"\033[29~";      /* DO */
2230         }
2231 }
2232
2233 /*---------------------------------------------------------------------------*
2234  *      function bound to function key 4
2235  *---------------------------------------------------------------------------*/
2236 static void
2237 fkey4(void)
2238 {
2239         if(!meta_down)
2240         {
2241
2242 #if PCVT_SHOWKEYS
2243                 if((vsp->vt_pure_mode == M_HPVT)
2244                    && (vsp->which_fkl == SYS_FKL))
2245                         toggl_kbddbg(vsp);
2246                 else
2247                         more_chars = (u_char *)"\033[20~";      /* F9 */
2248 #else
2249                 if(vsp->vt_pure_mode == M_PUREVT
2250                    || (vsp->which_fkl == USR_FKL))
2251                         more_chars = (u_char *)"\033[20~";      /* F9 */
2252 #endif /* PCVT_SHOWKEYS */
2253
2254         }
2255         else
2256         {
2257                 if(vsp->vt_pure_mode == M_PUREVT
2258                    || (vsp->which_fkl == USR_FKL))
2259                         more_chars = (u_char *)"\033[31~";      /* F17 */
2260         }
2261 }
2262
2263 /*---------------------------------------------------------------------------*
2264  *      function bound to function key 5
2265  *---------------------------------------------------------------------------*/
2266 static void
2267 fkey5(void)
2268 {
2269         if(!meta_down)
2270         {
2271                 if((vsp->vt_pure_mode == M_HPVT)
2272                    && (vsp->which_fkl == SYS_FKL))
2273                         toggl_bell(vsp);
2274                 else
2275                         more_chars = (u_char *)"\033[21~";      /* F10 */
2276         }
2277         else
2278         {
2279                 if(vsp->vt_pure_mode == M_PUREVT
2280                    || (vsp->which_fkl == USR_FKL))
2281                         more_chars = (u_char *)"\033[32~";      /* F18 */
2282         }
2283 }
2284
2285 /*---------------------------------------------------------------------------*
2286  *      function bound to function key 6
2287  *---------------------------------------------------------------------------*/
2288 static void
2289 fkey6(void)
2290 {
2291         if(!meta_down)
2292         {
2293                 if((vsp->vt_pure_mode == M_HPVT)
2294                    && (vsp->which_fkl == SYS_FKL))
2295                         toggl_sevenbit(vsp);
2296                 else
2297                         more_chars = (u_char *)"\033[23~";      /* F11 */
2298         }
2299         else
2300         {
2301                 if(vsp->vt_pure_mode == M_PUREVT
2302                    || (vsp->which_fkl == USR_FKL))
2303                         more_chars = (u_char *)"\033[33~";      /* F19 */
2304         }
2305 }
2306
2307 /*---------------------------------------------------------------------------*
2308  *      function bound to function key 7
2309  *---------------------------------------------------------------------------*/
2310 static void
2311 fkey7(void)
2312 {
2313         if(!meta_down)
2314         {
2315                 if((vsp->vt_pure_mode == M_HPVT)
2316                    && (vsp->which_fkl == SYS_FKL))
2317                         toggl_dspf(vsp);
2318                 else
2319                         more_chars = (u_char *)"\033[24~";      /* F12 */
2320         }
2321         else
2322         {
2323                 if(vsp->vt_pure_mode == M_PUREVT
2324                    || (vsp->which_fkl == USR_FKL))
2325                         more_chars = (u_char *)"\033[34~";      /* F20 */
2326         }
2327 }
2328
2329 /*---------------------------------------------------------------------------*
2330  *      function bound to function key 8
2331  *---------------------------------------------------------------------------*/
2332 static void
2333 fkey8(void)
2334 {
2335         if(!meta_down)
2336         {
2337                 if((vsp->vt_pure_mode == M_HPVT)
2338                    && (vsp->which_fkl == SYS_FKL))
2339                         toggl_awm(vsp);
2340                 else
2341                         more_chars = (u_char *)"\033[25~";      /* F13 */
2342         }
2343         else
2344         {
2345                 if(vsp->vt_pure_mode == M_PUREVT
2346                    || (vsp->which_fkl == USR_FKL))
2347                         more_chars = (u_char *)"\033[35~";      /* F21 ? !! */
2348         }
2349 }
2350
2351 /*---------------------------------------------------------------------------*
2352  *      function bound to function key 9
2353  *---------------------------------------------------------------------------*/
2354 static void
2355 fkey9(void)
2356 {
2357         if(meta_down)
2358         {
2359                 if(vsp->vt_pure_mode == M_PUREVT)
2360                         return;
2361
2362                 if(vsp->labels_on)      /* toggle label display on/off */
2363                         fkl_off(vsp);
2364                 else
2365                         fkl_on(vsp);
2366         }
2367         else
2368         {
2369                 do_vgapage(0);
2370         }
2371 }
2372
2373 /*---------------------------------------------------------------------------*
2374  *      function bound to function key 10
2375  *---------------------------------------------------------------------------*/
2376 static void
2377 fkey10(void)
2378 {
2379         if(meta_down)
2380         {
2381                 if(vsp->vt_pure_mode != M_PUREVT && vsp->labels_on)
2382                 {
2383                         if(vsp->which_fkl == USR_FKL)
2384                                 sw_sfkl(vsp);
2385                         else if(vsp->which_fkl == SYS_FKL)
2386                                 sw_ufkl(vsp);
2387                 }
2388         }
2389         else
2390         {
2391                 do_vgapage(1);
2392         }
2393 }
2394
2395 /*---------------------------------------------------------------------------*
2396  *      function bound to function key 11
2397  *---------------------------------------------------------------------------*/
2398 static void
2399 fkey11(void)
2400 {
2401         if(meta_down)
2402         {
2403                 if(vsp->vt_pure_mode == M_PUREVT)
2404                         set_emulation_mode(vsp, M_HPVT);
2405                 else if(vsp->vt_pure_mode == M_HPVT)
2406                         set_emulation_mode(vsp, M_PUREVT);
2407         }
2408         else
2409         {
2410                 do_vgapage(2);
2411         }
2412 }
2413
2414 /*---------------------------------------------------------------------------*
2415  *      function bound to function key 12
2416  *---------------------------------------------------------------------------*/
2417 static void
2418 fkey12(void)
2419 {
2420         if(meta_down)
2421         {
2422                 if(current_video_screen + 1 > totalscreens-1)
2423                         do_vgapage(0);
2424                 else
2425                         do_vgapage(current_video_screen + 1);
2426         }
2427         else
2428         {
2429                 do_vgapage(3);
2430         }
2431 }
2432
2433 /*---------------------------------------------------------------------------*
2434  *      function bound to SHIFTED function key 1
2435  *---------------------------------------------------------------------------*/
2436 static void
2437 sfkey1(void)
2438 {
2439         if(!meta_down)
2440         {
2441                 if(vsp->ukt.length[0])  /* entry available ? */
2442                         more_chars = (u_char *)
2443                                 &(vsp->udkbuf[vsp->ukt.first[0]]);
2444         }
2445         else
2446         {
2447                 if(vsp->ukt.length[9])  /* entry available ? */
2448                         more_chars = (u_char *)
2449                                 &(vsp->udkbuf[vsp->ukt.first[9]]);
2450         }
2451 }
2452
2453 /*---------------------------------------------------------------------------*
2454  *      function bound to SHIFTED function key 2
2455  *---------------------------------------------------------------------------*/
2456 static void
2457 sfkey2(void)
2458 {
2459         if(!meta_down)
2460         {
2461                 if(vsp->ukt.length[1])  /* entry available ? */
2462                         more_chars = (u_char *)
2463                                 &(vsp->udkbuf[vsp->ukt.first[1]]);
2464         }
2465         else
2466         {
2467                 if(vsp->ukt.length[11]) /* entry available ? */
2468                         more_chars = (u_char *)
2469                                 &(vsp->udkbuf[vsp->ukt.first[11]]);
2470         }
2471 }
2472
2473 /*---------------------------------------------------------------------------*
2474  *      function bound to SHIFTED function key 3
2475  *---------------------------------------------------------------------------*/
2476 static void
2477 sfkey3(void)
2478 {
2479         if(!meta_down)
2480         {
2481                 if(vsp->ukt.length[2])  /* entry available ? */
2482                         more_chars = (u_char *)
2483                                 &(vsp->udkbuf[vsp->ukt.first[2]]);
2484         }
2485         else
2486         {
2487                 if(vsp->ukt.length[12]) /* entry available ? */
2488                         more_chars = (u_char *)
2489                                 &(vsp->udkbuf[vsp->ukt.first[12]]);
2490         }
2491 }
2492
2493 /*---------------------------------------------------------------------------*
2494  *      function bound to SHIFTED function key 4
2495  *---------------------------------------------------------------------------*/
2496 static void
2497 sfkey4(void)
2498 {
2499         if(!meta_down)
2500         {
2501                 if(vsp->ukt.length[3])  /* entry available ? */
2502                         more_chars = (u_char *)
2503                                 &(vsp->udkbuf[vsp->ukt.first[3]]);
2504         }
2505         else
2506         {
2507                 if(vsp->ukt.length[13]) /* entry available ? */
2508                         more_chars = (u_char *)
2509                                 &(vsp->udkbuf[vsp->ukt.first[13]]);
2510         }
2511 }
2512
2513 /*---------------------------------------------------------------------------*
2514  *      function bound to SHIFTED function key 5
2515  *---------------------------------------------------------------------------*/
2516 static void
2517 sfkey5(void)
2518 {
2519         if(!meta_down)
2520         {
2521                 if(vsp->ukt.length[4])  /* entry available ? */
2522                         more_chars = (u_char *)
2523                                 &(vsp->udkbuf[vsp->ukt.first[4]]);
2524         }
2525         else
2526         {
2527                 if(vsp->ukt.length[14]) /* entry available ? */
2528                         more_chars = (u_char *)
2529                                 &(vsp->udkbuf[vsp->ukt.first[14]]);
2530         }
2531 }
2532
2533 /*---------------------------------------------------------------------------*
2534  *      function bound to SHIFTED function key 6
2535  *---------------------------------------------------------------------------*/
2536 static void
2537 sfkey6(void)
2538 {
2539         if(!meta_down)
2540         {
2541                 if(vsp->ukt.length[6])  /* entry available ? */
2542                         more_chars = (u_char *)
2543                                 &(vsp->udkbuf[vsp->ukt.first[6]]);
2544         }
2545         else
2546         {
2547                 if(vsp->ukt.length[15]) /* entry available ? */
2548                         more_chars = (u_char *)
2549                                 &(vsp->udkbuf[vsp->ukt.first[15]]);
2550         }
2551 }
2552
2553 /*---------------------------------------------------------------------------*
2554  *      function bound to SHIFTED function key 7
2555  *---------------------------------------------------------------------------*/
2556 static void
2557 sfkey7(void)
2558 {
2559         if(!meta_down)
2560         {
2561                 if(vsp->ukt.length[7])  /* entry available ? */
2562                         more_chars = (u_char *)
2563                                 &(vsp->udkbuf[vsp->ukt.first[7]]);
2564         }
2565         else
2566         {
2567                 if(vsp->ukt.length[16]) /* entry available ? */
2568                         more_chars = (u_char *)
2569                                 &(vsp->udkbuf[vsp->ukt.first[16]]);
2570         }
2571 }
2572
2573 /*---------------------------------------------------------------------------*
2574  *      function bound to SHIFTED function key 8
2575  *---------------------------------------------------------------------------*/
2576 static void
2577 sfkey8(void)
2578 {
2579         if(!meta_down)
2580         {
2581                 if(vsp->ukt.length[8])  /* entry available ? */
2582                         more_chars = (u_char *)
2583                                 &(vsp->udkbuf[vsp->ukt.first[8]]);
2584         }
2585         else
2586         {
2587                 if(vsp->ukt.length[17]) /* entry available ? */
2588                         more_chars = (u_char *)
2589                                 &(vsp->udkbuf[vsp->ukt.first[17]]);
2590         }
2591 }
2592 /*---------------------------------------------------------------------------*
2593  *      function bound to SHIFTED function key 9
2594  *---------------------------------------------------------------------------*/
2595 static void
2596 sfkey9(void)
2597 {
2598 }
2599
2600 /*---------------------------------------------------------------------------*
2601  *      function bound to SHIFTED function key 10
2602  *---------------------------------------------------------------------------*/
2603 static void
2604 sfkey10(void)
2605 {
2606 }
2607
2608 /*---------------------------------------------------------------------------*
2609  *      function bound to SHIFTED function key 11
2610  *---------------------------------------------------------------------------*/
2611 static void
2612 sfkey11(void)
2613 {
2614 }
2615
2616 /*---------------------------------------------------------------------------*
2617  *      function bound to SHIFTED function key 12
2618  *---------------------------------------------------------------------------*/
2619 static void
2620 sfkey12(void)
2621 {
2622 }
2623
2624 /*---------------------------------------------------------------------------*
2625  *      function bound to control function key 1
2626  *---------------------------------------------------------------------------*/
2627 static void
2628 cfkey1(void)
2629 {
2630         if(meta_down)
2631                 do_vgapage(0);
2632 }
2633
2634 /*---------------------------------------------------------------------------*
2635  *      function bound to control function key 2
2636  *---------------------------------------------------------------------------*/
2637 static void
2638 cfkey2(void)
2639 {
2640         if(meta_down)
2641                 do_vgapage(1);
2642 }
2643
2644 /*---------------------------------------------------------------------------*
2645  *      function bound to control function key 3
2646  *---------------------------------------------------------------------------*/
2647 static void
2648 cfkey3(void)
2649 {
2650         if(meta_down)
2651                 do_vgapage(2);
2652 }
2653
2654 /*---------------------------------------------------------------------------*
2655  *      function bound to control function key 4
2656  *---------------------------------------------------------------------------*/
2657 static void
2658 cfkey4(void)
2659 {
2660         if(meta_down)
2661                 do_vgapage(3);
2662 }
2663
2664 /*---------------------------------------------------------------------------*
2665  *      function bound to control function key 5
2666  *---------------------------------------------------------------------------*/
2667 static void
2668 cfkey5(void)
2669 {
2670         if(meta_down)
2671                 do_vgapage(4);
2672 }
2673
2674 /*---------------------------------------------------------------------------*
2675  *      function bound to control function key 6
2676  *---------------------------------------------------------------------------*/
2677 static void
2678 cfkey6(void)
2679 {
2680         if(meta_down)
2681                 do_vgapage(5);
2682 }
2683
2684 /*---------------------------------------------------------------------------*
2685  *      function bound to control function key 7
2686  *---------------------------------------------------------------------------*/
2687 static void
2688 cfkey7(void)
2689 {
2690         if(meta_down)
2691                 do_vgapage(6);
2692 }
2693
2694 /*---------------------------------------------------------------------------*
2695  *      function bound to control function key 8
2696  *---------------------------------------------------------------------------*/
2697 static void
2698 cfkey8(void)
2699 {
2700         if(meta_down)
2701                 do_vgapage(7);
2702 }
2703
2704 /*---------------------------------------------------------------------------*
2705  *      function bound to control function key 9
2706  *---------------------------------------------------------------------------*/
2707 static void
2708 cfkey9(void)
2709 {
2710         if(meta_down)
2711                 do_vgapage(8);
2712 }
2713
2714 /*---------------------------------------------------------------------------*
2715  *      function bound to control function key 10
2716  *---------------------------------------------------------------------------*/
2717 static void
2718 cfkey10(void)
2719 {
2720         if(meta_down)
2721                 do_vgapage(9);
2722 }
2723
2724 /*---------------------------------------------------------------------------*
2725  *      function bound to control function key 11
2726  *---------------------------------------------------------------------------*/
2727 static void
2728 cfkey11(void)
2729 {
2730         if(meta_down)
2731                 do_vgapage(10);
2732 }
2733
2734 /*---------------------------------------------------------------------------*
2735  *      function bound to control function key 12
2736  *---------------------------------------------------------------------------*/
2737 static void
2738 cfkey12(void)
2739 {
2740         if(meta_down)
2741                 do_vgapage(11);
2742 }
2743
2744 #else   /* PCVT_VT220  -  VT220-like Keyboard layout */
2745
2746 /*---------------------------------------------------------------------------*
2747  *      function bound to function key 1
2748  *---------------------------------------------------------------------------*/
2749 static void
2750 fkey1(void)
2751 {
2752         if(meta_down)
2753                 more_chars = (u_char *)"\033[23~"; /* F11 */
2754         else
2755                 do_vgapage(0);
2756 }
2757
2758 /*---------------------------------------------------------------------------*
2759  *      function bound to function key 2
2760  *---------------------------------------------------------------------------*/
2761 static void
2762 fkey2(void)
2763 {
2764         if(meta_down)
2765                 more_chars = (u_char *)"\033[24~"; /* F12 */
2766         else
2767                 do_vgapage(1);
2768 }
2769
2770 /*---------------------------------------------------------------------------*
2771  *      function bound to function key 3
2772  *---------------------------------------------------------------------------*/
2773 static void
2774 fkey3(void)
2775 {
2776         if(meta_down)
2777                 more_chars = (u_char *)"\033[25~"; /* F13 */
2778         else
2779                 do_vgapage(2);
2780 }
2781
2782 /*---------------------------------------------------------------------------*
2783  *      function bound to function key 4
2784  *---------------------------------------------------------------------------*/
2785 static void
2786 fkey4(void)
2787 {
2788         if(meta_down)
2789                 more_chars = (u_char *)"\033[26~"; /* F14 */
2790         else
2791                 do_vgapage(3);
2792 }
2793
2794 /*---------------------------------------------------------------------------*
2795  *      function bound to function key 5
2796  *---------------------------------------------------------------------------*/
2797 static void
2798 fkey5(void)
2799 {
2800         if(meta_down)
2801                 more_chars = (u_char *)"\033[28~"; /* Help */
2802         else
2803         {
2804                 if((current_video_screen + 1) > totalscreens-1)
2805                         do_vgapage(0);
2806                 else
2807                         do_vgapage(current_video_screen + 1);
2808         }
2809 }
2810
2811 /*---------------------------------------------------------------------------*
2812  *      function bound to function key 6
2813  *---------------------------------------------------------------------------*/
2814 static void
2815 fkey6(void)
2816 {
2817         if(meta_down)
2818                 more_chars = (u_char *)"\033[29~"; /* DO */
2819         else
2820                 more_chars = (u_char *)"\033[17~"; /* F6 */
2821 }
2822
2823 /*---------------------------------------------------------------------------*
2824  *      function bound to function key 7
2825  *---------------------------------------------------------------------------*/
2826 static void
2827 fkey7(void)
2828 {
2829         if(meta_down)
2830                 more_chars = (u_char *)"\033[31~"; /* F17 */
2831         else
2832                 more_chars = (u_char *)"\033[18~"; /* F7 */
2833 }
2834
2835 /*---------------------------------------------------------------------------*
2836  *      function bound to function key 8
2837  *---------------------------------------------------------------------------*/
2838 static void
2839 fkey8(void)
2840 {
2841         if(meta_down)
2842                 more_chars = (u_char *)"\033[32~"; /* F18 */
2843         else
2844                 more_chars = (u_char *)"\033[19~"; /* F8 */
2845 }
2846
2847 /*---------------------------------------------------------------------------*
2848  *      function bound to function key 9
2849  *---------------------------------------------------------------------------*/
2850 static void
2851 fkey9(void)
2852 {
2853         if(meta_down)
2854                 more_chars = (u_char *)"\033[33~"; /* F19 */
2855         else
2856                 more_chars = (u_char *)"\033[20~"; /* F9 */
2857 }
2858
2859 /*---------------------------------------------------------------------------*
2860  *      function bound to function key 10
2861  *---------------------------------------------------------------------------*/
2862 static void
2863 fkey10(void)
2864 {
2865         if(meta_down)
2866                 more_chars = (u_char *)"\033[34~"; /* F20 */
2867         else
2868                 more_chars = (u_char *)"\033[21~"; /* F10 */
2869 }
2870
2871 /*---------------------------------------------------------------------------*
2872  *      function bound to function key 11
2873  *---------------------------------------------------------------------------*/
2874 static void
2875 fkey11(void)
2876 {
2877         if(meta_down)
2878                 more_chars = (u_char *)"\0x8FP"; /* PF1 */
2879         else
2880                 more_chars = (u_char *)"\033[23~"; /* F11 */
2881 }
2882
2883 /*---------------------------------------------------------------------------*
2884  *      function bound to function key 12
2885  *---------------------------------------------------------------------------*/
2886 static void
2887 fkey12(void)
2888 {
2889         if(meta_down)
2890                 more_chars = (u_char *)"\0x8FQ"; /* PF2 */
2891         else
2892                 more_chars = (u_char *)"\033[24~"; /* F12 */
2893 }
2894
2895 /*---------------------------------------------------------------------------*
2896  *      function bound to SHIFTED function key 1
2897  *---------------------------------------------------------------------------*/
2898 static void
2899 sfkey1(void)
2900 {
2901         if(meta_down)
2902         {
2903                 if(vsp->ukt.length[6])  /* entry available ? */
2904                         more_chars = (u_char *)
2905                                 &(vsp->udkbuf[vsp->ukt.first[6]]);
2906                 else
2907                         more_chars = (u_char *)"\033[23~"; /* F11 */
2908         }
2909         else
2910         {
2911                 do_vgapage(4);
2912         }
2913 }
2914
2915 /*---------------------------------------------------------------------------*
2916  *      function bound to SHIFTED function key 2
2917  *---------------------------------------------------------------------------*/
2918 static void
2919 sfkey2(void)
2920 {
2921         if(meta_down)
2922         {
2923                 if(vsp->ukt.length[7])  /* entry available ? */
2924                         more_chars = (u_char *)
2925                                 &(vsp->udkbuf[vsp->ukt.first[7]]);
2926                 else
2927                         more_chars = (u_char *)"\033[24~"; /* F12 */
2928         }
2929         else
2930         {
2931                 do_vgapage(5);
2932         }
2933 }
2934
2935 /*---------------------------------------------------------------------------*
2936  *      function bound to SHIFTED function key 3
2937  *---------------------------------------------------------------------------*/
2938 static void
2939 sfkey3(void)
2940 {
2941         if(meta_down)
2942         {
2943                 if(vsp->ukt.length[8])  /* entry available ? */
2944                         more_chars = (u_char *)
2945                                 &(vsp->udkbuf[vsp->ukt.first[8]]);
2946                 else
2947                         more_chars = (u_char *)"\033[25~"; /* F13 */
2948         }
2949         else
2950         {
2951                 do_vgapage(6);
2952         }
2953 }
2954
2955 /*---------------------------------------------------------------------------*
2956  *      function bound to SHIFTED function key 4
2957  *---------------------------------------------------------------------------*/
2958 static void
2959 sfkey4(void)
2960 {
2961         if(meta_down)
2962         {
2963                 if(vsp->ukt.length[9])  /* entry available ? */
2964                         more_chars = (u_char *)
2965                                 &(vsp->udkbuf[vsp->ukt.first[9]]);
2966                 else
2967                         more_chars = (u_char *)"\033[26~"; /* F14 */
2968         }
2969         else
2970         {
2971                 do_vgapage(7);
2972         }
2973 }
2974
2975 /*---------------------------------------------------------------------------*
2976  *      function bound to SHIFTED function key 5
2977  *---------------------------------------------------------------------------*/
2978 static void
2979 sfkey5(void)
2980 {
2981         if(meta_down)
2982         {
2983                 if(vsp->ukt.length[11]) /* entry available ? */
2984                         more_chars = (u_char *)
2985                                 &(vsp->udkbuf[vsp->ukt.first[11]]);
2986                 else
2987                         more_chars = (u_char *)"\033[28~"; /* Help */
2988         }
2989         else
2990         {
2991                 if(current_video_screen <= 0)
2992                         do_vgapage(totalscreens-1);
2993                 else
2994                         do_vgapage(current_video_screen - 1);
2995         }
2996 }
2997
2998 /*---------------------------------------------------------------------------*
2999  *      function bound to SHIFTED function key 6
3000  *---------------------------------------------------------------------------*/
3001 static void
3002 sfkey6(void)
3003 {
3004         if(!meta_down)
3005         {
3006                 if(vsp->ukt.length[0])  /* entry available ? */
3007                         more_chars = (u_char *)
3008                                 &(vsp->udkbuf[vsp->ukt.first[0]]);
3009                 else
3010                         more_chars = (u_char *)"\033[17~"; /* F6 */
3011         }
3012         else if(vsp->ukt.length[12])    /* entry available ? */
3013                         more_chars = (u_char *)
3014                                 &(vsp->udkbuf[vsp->ukt.first[12]]);
3015              else
3016                         more_chars = (u_char *)"\033[29~"; /* DO */
3017 }
3018
3019 /*---------------------------------------------------------------------------*
3020  *      function bound to SHIFTED function key 7
3021  *---------------------------------------------------------------------------*/
3022 static void
3023 sfkey7(void)
3024 {
3025         if(!meta_down)
3026         {
3027                 if(vsp->ukt.length[1])  /* entry available ? */
3028                         more_chars = (u_char *)
3029                                 &(vsp->udkbuf[vsp->ukt.first[1]]);
3030                 else
3031                         more_chars = (u_char *)"\033[18~"; /* F7 */
3032         }
3033         else if(vsp->ukt.length[14])    /* entry available ? */
3034                         more_chars = (u_char *)
3035                                 &(vsp->udkbuf[vsp->ukt.first[14]]);
3036              else
3037                         more_chars = (u_char *)"\033[31~"; /* F17 */
3038 }
3039
3040 /*---------------------------------------------------------------------------*
3041  *      function bound to SHIFTED function key 8
3042  *---------------------------------------------------------------------------*/
3043 static void
3044 sfkey8(void)
3045 {
3046         if(!meta_down)
3047         {
3048                 if(vsp->ukt.length[2])  /* entry available ? */
3049                         more_chars = (u_char *)
3050                                 &(vsp->udkbuf[vsp->ukt.first[2]]);
3051                 else
3052                         more_chars = (u_char *)"\033[19~"; /* F8 */
3053         }
3054         else if(vsp->ukt.length[14])    /* entry available ? */
3055                         more_chars = (u_char *)
3056                                 &(vsp->udkbuf[vsp->ukt.first[15]]);
3057              else
3058                         more_chars = (u_char *)"\033[32~"; /* F18 */
3059 }
3060
3061 /*---------------------------------------------------------------------------*
3062  *      function bound to SHIFTED function key 9
3063  *---------------------------------------------------------------------------*/
3064 static void
3065 sfkey9(void)
3066 {
3067         if(!meta_down)
3068         {
3069                 if(vsp->ukt.length[3])  /* entry available ? */
3070                         more_chars = (u_char *)
3071                                 &(vsp->udkbuf[vsp->ukt.first[3]]);
3072                 else
3073                         more_chars = (u_char *)"\033[20~"; /* F9 */
3074         }
3075         else if(vsp->ukt.length[16])    /* entry available ? */
3076                         more_chars = (u_char *)
3077                                 &(vsp->udkbuf[vsp->ukt.first[16]]);
3078              else
3079                         more_chars = (u_char *)"\033[33~"; /* F19 */
3080 }
3081
3082 /*---------------------------------------------------------------------------*
3083  *      function bound to SHIFTED function key 10
3084  *---------------------------------------------------------------------------*/
3085 static void
3086 sfkey10(void)
3087 {
3088         if(!meta_down)
3089         {
3090                 if(vsp->ukt.length[4])  /* entry available ? */
3091                         more_chars = (u_char *)
3092                                 &(vsp->udkbuf[vsp->ukt.first[4]]);
3093                 else
3094                         more_chars = (u_char *)"\033[21~"; /* F10 */
3095         }
3096         else if(vsp->ukt.length[17])    /* entry available ? */
3097                         more_chars = (u_char *)
3098                                 &(vsp->udkbuf[vsp->ukt.first[17]]);
3099              else
3100                         more_chars = (u_char *)"\033[34~"; /* F20 */
3101 }
3102
3103 /*---------------------------------------------------------------------------*
3104  *      function bound to SHIFTED function key 11
3105  *---------------------------------------------------------------------------*/
3106 static void
3107 sfkey11(void)
3108 {
3109         if(!meta_down)
3110         {
3111                 if(vsp->ukt.length[6])  /* entry available ? */
3112                         more_chars = (u_char *)
3113                                 &(vsp->udkbuf[vsp->ukt.first[6]]);
3114                 else
3115                         more_chars = (u_char *)"\033[23~"; /* F11 */
3116         }
3117 }
3118
3119 /*---------------------------------------------------------------------------*
3120  *      function bound to SHIFTED function key 12
3121  *---------------------------------------------------------------------------*/
3122 static void
3123 sfkey12(void)
3124 {
3125         if(!meta_down)
3126         {
3127                 if(vsp->ukt.length[7])  /* entry available ? */
3128                         more_chars = (u_char *)
3129                                 &(vsp->udkbuf[vsp->ukt.first[7]]);
3130                 else
3131                         more_chars = (u_char *)"\033[24~"; /* F12 */
3132         }
3133 }
3134
3135 /*---------------------------------------------------------------------------*
3136  *      function bound to control function key 1
3137  *---------------------------------------------------------------------------*/
3138 static void
3139 cfkey1(void)
3140 {
3141         if(vsp->which_fkl == SYS_FKL)
3142                 toggl_columns(vsp);
3143 }
3144
3145 /*---------------------------------------------------------------------------*
3146  *      function bound to control function key 2
3147  *---------------------------------------------------------------------------*/
3148 static void
3149 cfkey2(void)
3150 {
3151         if(vsp->which_fkl == SYS_FKL)
3152                 vt_ris(vsp);
3153 }
3154
3155 /*---------------------------------------------------------------------------*
3156  *      function bound to control function key 3
3157  *---------------------------------------------------------------------------*/
3158 static void
3159 cfkey3(void)
3160 {
3161         if(vsp->which_fkl == SYS_FKL)
3162                 toggl_24l(vsp);
3163 }
3164
3165 /*---------------------------------------------------------------------------*
3166  *      function bound to control function key 4
3167  *---------------------------------------------------------------------------*/
3168 static void
3169 cfkey4(void)
3170 {
3171
3172 #if PCVT_SHOWKEYS
3173         if(vsp->which_fkl == SYS_FKL)
3174                 toggl_kbddbg(vsp);
3175 #endif /* PCVT_SHOWKEYS */
3176
3177 }
3178
3179 /*---------------------------------------------------------------------------*
3180  *      function bound to control function key 5
3181  *---------------------------------------------------------------------------*/
3182 static void
3183 cfkey5(void)
3184 {
3185         if(vsp->which_fkl == SYS_FKL)
3186                 toggl_bell(vsp);
3187 }
3188
3189 /*---------------------------------------------------------------------------*
3190  *      function bound to control function key 6
3191  *---------------------------------------------------------------------------*/
3192 static void
3193 cfkey6(void)
3194 {
3195         if(vsp->which_fkl == SYS_FKL)
3196                 toggl_sevenbit(vsp);
3197 }
3198
3199 /*---------------------------------------------------------------------------*
3200  *      function bound to control function key 7
3201  *---------------------------------------------------------------------------*/
3202 static void
3203 cfkey7(void)
3204 {
3205         if(vsp->which_fkl == SYS_FKL)
3206                 toggl_dspf(vsp);
3207 }
3208
3209 /*---------------------------------------------------------------------------*
3210  *      function bound to control function key 8
3211  *---------------------------------------------------------------------------*/
3212 static void
3213 cfkey8(void)
3214 {
3215         if(vsp->which_fkl == SYS_FKL)
3216                 toggl_awm(vsp);
3217 }
3218
3219 /*---------------------------------------------------------------------------*
3220  *      function bound to control function key 9
3221  *---------------------------------------------------------------------------*/
3222 static void
3223 cfkey9(void)
3224 {
3225         if(vsp->labels_on)      /* toggle label display on/off */
3226                 fkl_off(vsp);
3227         else
3228                 fkl_on(vsp);
3229 }
3230
3231 /*---------------------------------------------------------------------------*
3232  *      function bound to control function key 10
3233  *---------------------------------------------------------------------------*/
3234 static void
3235 cfkey10(void)
3236 {
3237         if(vsp->labels_on)      /* toggle user/system fkey labels */
3238         {
3239                 if(vsp->which_fkl == USR_FKL)
3240                         sw_sfkl(vsp);
3241                 else if(vsp->which_fkl == SYS_FKL)
3242                         sw_ufkl(vsp);
3243         }
3244 }
3245
3246 /*---------------------------------------------------------------------------*
3247  *      function bound to control function key 11
3248  *---------------------------------------------------------------------------*/
3249 static void
3250 cfkey11(void)
3251 {
3252         if(vsp->vt_pure_mode == M_PUREVT)
3253                 set_emulation_mode(vsp, M_HPVT);
3254         else if(vsp->vt_pure_mode == M_HPVT)
3255                 set_emulation_mode(vsp, M_PUREVT);
3256 }
3257
3258 /*---------------------------------------------------------------------------*
3259  *      function bound to control function key 12
3260  *---------------------------------------------------------------------------*/
3261 static void
3262 cfkey12(void)
3263 {
3264 }
3265
3266 #endif  /* PCVT_VT220KEYB */
3267
3268 /*---------------------------------------------------------------------------*
3269  *      
3270  *---------------------------------------------------------------------------*/
3271 static void
3272 scrollback_save_screen(void)
3273 {
3274         int x = spltty();
3275         register size_t s;
3276
3277         s = sizeof(u_short) * vsp->screen_rowsize * vsp->maxcol;
3278
3279         if (scrollback_savedscreen)
3280                 free(scrollback_savedscreen, M_TEMP);
3281
3282         scrnsv_size = s;
3283
3284         if (!(scrollback_savedscreen = (u_short *)malloc(s, M_TEMP, M_NOWAIT)))
3285         {
3286                 splx(x);
3287                 return;
3288         }
3289         bcopy(vsp->Crtat, scrollback_savedscreen, scrnsv_size);
3290         splx(x);
3291 }
3292
3293 /*---------------------------------------------------------------------------*
3294  *      
3295  *---------------------------------------------------------------------------*/
3296 static void
3297 scrollback_restore_screen(void)
3298 {
3299         if (scrollback_savedscreen)
3300                 bcopy(scrollback_savedscreen, vsp->Crtat, scrnsv_size);
3301 }
3302  
3303
3304 #endif  /* NVT > 0 */
3305
3306 /* ------------------------------- EOF -------------------------------------*/