home *** CD-ROM | disk | FTP | other *** search
- #ifdef MSW
-
- /* Keyboard stuff; in reality, this code performs a lot of tedious
- * mappings of Windows keycodes to something notgnu emacs understands.
- * In some cases, hard-wired mappings are done - ie a key is hit and
- * an entire function name is pushed into the input stream. (For more
- * info on that funcky mechanism, see extend.c. I created something
- * much like Meta-X <name cmd> for parsing input-to-function mapping,
- * the difference being there is no echo, it handles 'interruptions'
- * and is disabled during macro recording).
- *
- * You'll note also that the input queue is initialized, and managed here
- * as well as something called the putback queue. This is to handle
- * interruptions during processing of modeline stuff; the editor base
- * code does not want to deal with the concept of something else being
- * able to happen during a prompt, and this ughly hack got around that
- * problem and a number of others too. Ugh.
- *
- * The worst stuff is the odd switch statements where Microsoft decided
- * that most Fkeys were one kind of message, but some others weren't.
- * That and the (to me) quite strange way some keys generate multiple
- * messages for each press; you'll see comments to that effect.
- */
-
- #include "jam.h"
- #include "stdlib.h"
- #include "def.h"
- #include "keyname.h"
- #include "ttydef.h"
- #include "chrdef.h"
-
- #define MAXCHARS 256
- static KCHAR *kbdinput = 0;
- static KCHAR *putback_kbdinput = 0;
- static int kbdcount = 0;
- static int putback_kbdcount = 0;
-
- static BOOL s_IgnoreWM_CHAR = FALSE; /* WM_KEYDOWN/WM_SYSKEYDOWN may generate
- * a following WM_CHAR to ignore
- */
- static BOOL mapFkey(WPARAM *wKey, BOOL bShifted, BOOL bCtrled, BOOL bAlted);
- static BOOL mapKPkey(WPARAM *wKey);
-
- /* Alloc the internal event queues
- */
- void InitInput(void)
- {
- if (!(kbdinput = (KCHAR *)calloc(MAXCHARS, sizeof(KCHAR))))
- WindowMessage("Unable to init kbdinput!", TRUE);
- if (!(putback_kbdinput = (KCHAR *)calloc(MAXCHARS, sizeof(KCHAR))))
- WindowMessage("Unable to init putback_kbdinput!", TRUE);
- }
-
- /* Putback kchar to to input queue; called to unwind something
- * for replay.
- */
- void PutbackKchar(KCHAR c)
- {
- if (putback_kbdcount < MAXCHARS)
- {
- putback_kbdinput[putback_kbdcount] = c;
- putback_kbdcount++;
- }
- }
-
- /* If putback'ed events, push to normal input stream now for replay.
- */
- void CheckForPutback(void)
- {
- int i, j;
-
- /* if not enough room, die
- */
- if ((MAXCHARS - kbdcount) < putback_kbdcount)
- putback_kbdcount = 0;
- else
- for (j = putback_kbdcount, i = 0; i < j; i++)
- {
- AddKchar(putback_kbdinput[i]);
- putback_kbdcount--;
- }
- }
-
- /* Push normal string to input buf; used all over
- * to push function names and parameters into the input
- * stream just as if the user had typed them.
- */
- void AddString(char *s)
- {
- while (s && *s)
- AddKchar((KCHAR)*s++);
- }
-
- /* Add kchar to internal queue of keypresses; like above,
- * seems like the user just typed them in...
- */
- void AddKchar(KCHAR c)
- {
- if (kbdcount < MAXCHARS)
- {
- kbdinput[kbdcount] = c;
- kbdcount++;
- }
- else
- MessageBeep((UINT)-1); /* no more space, sigh */
- }
-
- /* Return first inqueued char from event into
- * pkchar (if NON_NULL) and return status.
- */
- BOOL WindowReturnKCHAR(KCHAR *pkchar)
- {
- register int i;
- BOOL result = FALSE;
-
- /* If something, remove from queue head
- * and push the queue down
- * (I know, should use head/tail pointers vs this copy down
- * thing, but ...)
- */
- if (kbdcount > 0)
- {
- result = TRUE;
- if (pkchar)
- {
- *pkchar = kbdinput[0];
- kbdcount--;
- for (i = 0; i < kbdcount; i++)
- kbdinput[i] = kbdinput[i+1];
- }
- }
- return(result);
- }
-
- /* Map windows event + keycode to kchar; this gets
- * pretty hairy in spots.
- */
- BOOL WindowMapKey(UINT msg, WPARAM wKey, LPARAM lParam)
- {
- BOOL ignore;
- BOOL bShifted = (GetKeyState(VK_SHIFT) < 0)? 1 : 0;
- BOOL bCtrled = (GetKeyState(VK_CONTROL) < 0)? 1 : 0;
- BOOL bAlted = (GetKeyState(VK_MENU) < 0)? 1 : 0;
-
- /* Events to ignore - we see them in multiple ways. It
- * makes sense to someone.
- */
- if (wKey == VK_SHIFT || wKey == VK_CONTROL ||
- wKey == VK_CAPITAL || wKey == VK_MENU)
- return (FALSE);
-
- /* Pre-processed stuff, with simple mapping
- */
- if (msg == WM_CHAR) /* Windows has created something useful */
- {
- ignore = s_IgnoreWM_CHAR;
- s_IgnoreWM_CHAR = FALSE; /* reset */
-
- /* A prior event triggered this wm_char, so it's
- * not useful.
- */
- if (ignore)
- return(FALSE);
-
- switch (wKey)
- {
- case ' ':
- if (bCtrled) /* a hard-wired key, cntrl-space */
- {
- ExtendedFunction(function_name(setmark));
- return (TRUE);
- }
- else
- break;
- case CCHR('H'):
- if (!bCtrled) /* must be backspace key */
- return(FALSE); /* backspace key sends message w/o cntrl key */
- case CCHR('I'): /* tab is hardwired to C-align function */
- if (bShifted) /* but cntrl or shift tab is the real thing */
- {
- ExtendedFunction(function_name(hardtab));
- return(TRUE);
- }
- }
- AddKchar((KCHAR)wKey);
- return(TRUE);
- }
-
- /* Keys otherwise eaten
- */
- else if (msg == WM_KEYDOWN)
- {
- switch(wKey)
- {
- case VK_TAB: /* tab is hardwired to C-align function */
- if (bCtrled)
- {
- ExtendedFunction(function_name(hardtab));
- return(TRUE);
- }
- return(FALSE);
-
- case VK_BACK:
- wKey = 0x7f; /* ttyio mapped it this way too, ick ! */
- break;
-
- case VK_DELETE:
- if (bCtrled) /* Talk about your hardwired functions! */
- { /* cntrl-delete wipes a line from any position */
- ExtendedFunction(function_name(gotobol));
- ExtendedFunction(function_name(killline));
- ExtendedFunction(function_name(killline));
- return(TRUE);
- }
- else if (bShifted) /* This is hardwired too */
- {
- ExtendedFunction(function_name(delbword));
- return(TRUE);
- }
- else
- wKey = KDELETE;
- break;
-
- case VK_INSERT:
- wKey = KINSERT;
- break;
-
- case VK_HOME:
- if (bCtrled)
- wKey = KCHOME;
- else
- wKey = KHOME;
- break;
-
- case VK_END:
- if (bCtrled)
- wKey = KCEND;
- else
- wKey = KEND;
- break;
-
- case VK_RIGHT:
- if (bCtrled)
- wKey = KCRIGHT;
- else
- wKey = KRIGHT;
- break;
-
- case VK_LEFT:
- if (bCtrled)
- wKey = KCLEFT;
- else
- wKey = KLEFT;
- break;
-
- case VK_DOWN:
- if (bCtrled)
- {
- if (bAlted) /* Down key hardwired for cntrl/alt mix */
- ExtendedFunction(function_name(nextwind));
- else
- ExtendedFunction(function_name(forw1page));
- return (TRUE);
- }
- else
- wKey = KDOWN;
- break;
-
- case VK_UP:
- if (bCtrled)
- {
- if (bAlted) /* Up key hardwired for cntrl/alt mix */
- ExtendedFunction(function_name(prevwind));
- else
- ExtendedFunction(function_name(back1page));
- return (TRUE);
- }
- else
- wKey = KUP;
- break;
-
- case VK_PRIOR:
- if (bCtrled)
- wKey = KCPGUP;
- else
- wKey = KPGUP;
- break;
-
- case VK_NEXT:
- if (bCtrled)
- wKey = KCPGDN;
- else
- wKey = KPGDN;
- break;
-
- case VK_F1:
- case VK_F2:
- case VK_F3:
- case VK_F4:
- case VK_F5:
- case VK_F6:
- case VK_F7:
- case VK_F8:
- case VK_F9:
- case VK_F10: /* only seen in WM_SYSKEYDOWN, why? */
- case VK_F11:
- case VK_F12:
- if (!mapFkey(&wKey, bShifted, bCtrled, bAlted))
- return (FALSE);
- break;
-
- /* keypad keys
- */
- case VK_NUMPAD0:
- case VK_NUMPAD1:
- case VK_NUMPAD2:
- case VK_NUMPAD3:
- case VK_NUMPAD4:
- case VK_NUMPAD5:
- case VK_NUMPAD6:
- case VK_NUMPAD7:
- case VK_NUMPAD8:
- case VK_NUMPAD9:
- case VK_ADD:
- case VK_MULTIPLY:
- case VK_SUBTRACT:
- case VK_DECIMAL:
- case VK_DIVIDE:
- case VK_EXECUTE:
- case VK_NUMLOCK:
- if (!mapKPkey(&wKey))
- return (FALSE);
- break;
-
- /* Alphanumerics which don't generate WM_CHAR msgs
- * when the cntrl key is down (beats me why!?)
- */
- case 'T':
- case 'P':
- case 'R':
- case 'Q':
- if (bCtrled)
- {
- wKey = CCHR(wKey); /* really is cntrl-* this time */
- break;
- }
- /* FALLTHRU */
-
- /* NOTE if not known char, OR possible duplicate,
- * do not process
- */
- case VK_RETURN:
- default:
- return(FALSE);
- }
- AddKchar((KCHAR)wKey);
- return(TRUE);
- }
-
- /* Why on why is only F10 a WM_SYSKEYDOWN??
- */
- else if (msg == WM_SYSKEYDOWN)
- {
- switch(wKey)
- {
- case VK_F1:
- case VK_F2:
- case VK_F3:
- case VK_F4:
- case VK_F5:
- case VK_F6:
- case VK_F7:
- case VK_F8:
- case VK_F9:
- case VK_F10:
- case VK_F11:
- case VK_F12:
- if (!mapFkey(&wKey, bShifted, bCtrled, bAlted))
- return (FALSE);
- break;
- default:
- return (FALSE);
- }
- AddKchar((KCHAR)wKey);
- return(TRUE);
- }
-
- /* Keys with meta-bit set
- */
- else if (msg == WM_SYSCHAR)
- {
- switch(wKey)
- {
- default:
- wKey |= METABIT;
- break;
- }
- AddKchar((KCHAR)wKey);
- return(TRUE);
- }
-
- /* Unsupported key/message combination
- */
- return (FALSE);
- }
- /* Function key mapping - broken out for ease of
- * mapping.
- */
- static BOOL mapFkey(WPARAM *pwKey, BOOL bShifted, BOOL bCtrled, BOOL bAlted)
- {
- WPARAM wKey = *pwKey;
- BOOL mapped = TRUE;
-
- switch(wKey)
- {
- case VK_F1:
- if (bShifted && bCtrled) wKey = KCSF1;
- else if (bShifted) wKey = KSF1;
- else if (bCtrled) wKey = KCF1;
- else if (bAlted) wKey = KMF1;
- else wKey = KF1;
- break;
-
- case VK_F2:
- if (bShifted && bCtrled) wKey = KCSF2;
- else if (bShifted) wKey = KSF2;
- else if (bCtrled) wKey = KCF2;
- else if (bAlted) wKey = KMF2;
- else wKey = KF2;
- break;
-
- case VK_F3:
- if (bShifted && bCtrled) wKey = KCSF3;
- else if (bShifted) wKey = KSF3;
- else if (bCtrled) wKey = KCF3;
- else if (bAlted) wKey = KMF3;
- else wKey = KF3;
- break;
-
- case VK_F4:
- if (bShifted && bCtrled) wKey = KCSF4;
- else if (bShifted) wKey = KSF4;
- else if (bCtrled) wKey = KCF4;
- else if (bAlted) wKey = KMF4;
- else wKey = KF4;
- break;
-
- case VK_F5:
- if (bShifted && bCtrled) wKey = KCSF5;
- else if (bShifted) wKey = KSF5;
- else if (bCtrled) wKey = KCF5;
- else if (bAlted) wKey = KMF5;
- else wKey = KF5;
- break;
-
- case VK_F6:
- if (bShifted && bCtrled) wKey = KCSF6;
- else if (bShifted) wKey = KSF6;
- else if (bCtrled) wKey = KCF6;
- else if (bAlted) wKey = KMF6;
- else wKey = KF6;
- break;
-
- case VK_F7:
- if (bShifted && bCtrled) wKey = KCSF7;
- else if (bShifted) wKey = KSF7;
- else if (bCtrled) wKey = KCF7;
- else if (bAlted) wKey = KMF7;
- else wKey = KF7;
- break;
-
- case VK_F8:
- if (bShifted && bCtrled) wKey = KCSF8;
- else if (bShifted) wKey = KSF8;
- else if (bCtrled) wKey = KCF8;
- else if (bAlted) wKey = KMF8;
- else wKey = KF8;
- break;
-
- case VK_F9:
- if (bShifted && bCtrled) wKey = KCSF9;
- else if (bShifted) wKey = KSF9;
- else if (bCtrled) wKey = KCF9;
- else if (bAlted) wKey = KMF9;
- else wKey = KF9;
- break;
-
- case VK_F10:
- if (bShifted && bCtrled) wKey = KCSF10;
- else if (bShifted) wKey = KSF10;
- else if (bCtrled) wKey = KCF10;
- else if (bAlted) wKey = KMF10;
- else wKey = KF10;
- break;
-
- case VK_F11:
- if (bShifted && bCtrled) wKey = KCSF11;
- else if (bShifted) wKey = KSF11;
- else if (bCtrled) wKey = KCF11;
- else if (bAlted) wKey = KMF11;
- else wKey = KF11;
- break;
-
- case VK_F12:
- if (bShifted && bCtrled) wKey = KCSF12;
- else if (bShifted) wKey = KSF12;
- else if (bCtrled) wKey = KCF12;
- else if (bAlted) wKey = KMF12;
- else wKey = KF12;
- break;
-
- default:
- mapped = FALSE;
- }
-
- *pwKey = wKey;
- return (mapped);
- }
- /* Keypadkey mapping - only partially useful since some
- * keys change in value if NUM LOCK is on, which of course
- * messes me up big time.
- */
- static BOOL mapKPkey(WPARAM *pwKey)
- {
- WPARAM wKey = *pwKey;
- BOOL mapped = TRUE;
-
- switch(wKey)
- {
- case VK_NUMPAD0:
- wKey = KP0;
- break;
-
- case VK_NUMPAD1:
- wKey = KP1;
- break;
-
- case VK_NUMPAD2:
- wKey = KP2;
- break;
-
- case VK_NUMPAD3:
- wKey = KP3;
- break;
-
- case VK_NUMPAD4:
- wKey = KP4;
- break;
-
- case VK_NUMPAD5:
- wKey = KP5;
- break;
-
- case VK_NUMPAD6:
- wKey = KP6;
- break;
-
- case VK_NUMPAD7:
- wKey = KP7;
- break;
-
- case VK_NUMPAD8:
- wKey = KP8;
- break;
-
- case VK_NUMPAD9:
- wKey = KP9;
- break;
-
- case VK_ADD:
- wKey = KPADD;
- break;
-
- case VK_MULTIPLY:
- wKey = KPMUL;
- break;
-
- case VK_SUBTRACT:
- wKey = KPSUB;
- break;
-
- case VK_DECIMAL:
- wKey = KPDEL;
- break;
-
- case VK_DIVIDE:
- wKey = KPDIV;
- break;
-
- case VK_NUMLOCK:
- wKey = KPNUMLK;
- break;
-
- case VK_EXECUTE:
- wKey = KPENTER;
- break;
-
- default:
- mapped = FALSE;
- }
-
- *pwKey = wKey;
- s_IgnoreWM_CHAR = mapped; /* generated an event to ignore? */
- return (mapped);
- }
- #endif
-