home *** CD-ROM | disk | FTP | other *** search
- /* The routines in this file provide keyboard and mouse input support
- under the Microsoft Windows environment on an IBM-PC or compatible
- computer.
-
- Must be compiled with Borland C++ 2.0.
-
- It should not be compiled if the WINDOW_MSWIN symbol is not set */
-
- #include "estruct.h"
- #include "elang.h"
- #include <stdio.h>
- #include <time.h>
- #include "eproto.h"
- #include "edef.h"
-
- #include "mswin.h"
-
- #define IBUFSIZE 64 /* this must be a power of 2 */
-
- static unsigned char in_buf[IBUFSIZE]; /* input character buffer */
- static int in_next = 0; /* pos to retrieve next input character */
- static int in_last = 0; /* pos to place most recent input character */
- static int in_free = 0; /* number of unused char entries */
-
- static int vk_at = -1; /* VK code for '@' key */
-
- /* in_init: initialize the input stream buffer */
- /* ======= */
-
- void in_init (void)
- {
- /*-initialize input stream buffer */
- in_next = in_last = 0;
- in_free = IBUFSIZE;
-
- /*-initialize vk_at to try to support the popular ^@ */
- vk_at = VkKeyScan ('@');
- if (HIBYTE(vk_at) != 1) {
- /* not a shifted key. no cigar! */
- vk_at = -1;
- }
- } /* in_init */
-
- /* in_room: is there enough room for n chars ? */
- /* ======= */
-
- BOOL in_room (int n)
- {
- if (n <= in_free) return TRUE;
- else {
- MessageBeep (0);
- return FALSE;
- }
- } /* in_room */
-
- /* in_check: is the input buffer non empty? */
- /* ======== */
-
- BOOL in_check (void)
- {
- if (in_next == in_last)
- return(FALSE);
- else
- return(TRUE);
- } /* in_check */
-
- /* in_put: enter an event into the input buffer */
- /* ====== */
-
- void in_put (int event)
- {
- in_buf[in_last++] = event;
- in_last &= (IBUFSIZE - 1);
- --in_free;
- } /* in_put */
-
- /* in_get: get an event from the input buffer */
- /* ====== */
-
- int in_get (void)
- {
- register int event; /* event to return */
-
- event = in_buf[in_next++];
- in_next &= (IBUFSIZE - 1);
- ++in_free;
- return(event);
- } /* in_get */
-
- /* typahead: TRUE if there are typeahead characters in the input stream */
- /* ======== */
-
- PASCAL typahead (void)
- {
- if (in_check()) return TRUE;
- else return FALSE;
- } /* typahead */
-
- /* EatKey: processes WM_(SYS)KEYxxx and WM_(SYS/MENU)CHAR messages */
- /* ====== */
-
- BOOL far pascal EatKey (WORD MsgCode, WORD Key, DWORD lParam)
-
- /* This function must be called for each WM_(SYS)KEYxxx or
- WM_(SYS/MENU)CHAR message. It returns TRUE if it has taken possesion
- of the keyboard action. In that case, the message processing should
- be terminated */
- {
- WORD evt = -1; /* -1 means: key not for emacs */
- WORD prefix = 0;
-
- if (IsIconic (hFrameWnd)) return FALSE; /* no input while fully
- iconic */
- switch (MsgCode) {
-
- case WM_KEYDOWN:
- KeyDown:
- /*-process the non-ascii keys (Page-up, Page-down, End, Home,
- Arrows, Insert, Delete, function keys) */
- prefix = SPEC;
- if (GetKeyState (VK_CONTROL) < 0) prefix |= CTRL;
- if (GetKeyState (VK_SHIFT) < 0) prefix |= SHFT;
- switch (Key) {
-
- case VK_HOME:
- evt = '<';
- break;
- case VK_UP:
- evt = 'P';
- break;
- case VK_PRIOR: /* Page-up */
- evt = 'Z';
- break;
- case VK_LEFT:
- evt = 'B';
- break;
- case VK_RIGHT:
- evt = 'F';
- break;
- case VK_END:
- evt = '>';
- break;
- case VK_DOWN:
- evt = 'N';
- break;
- case VK_NEXT: /* Page-down */
- evt = 'V';
- break;
- case VK_INSERT:
- evt = 'C';
- break;
- case VK_DELETE:
- evt = 'D';
- break;
- default:
- if ((Key >= VK_F1) && (Key <= VK_F10)) { /* function key */
- if (Key == VK_F10) evt = '0';
- else evt = Key - VK_F1 + '1';
- }
- else if ((vk_at > 0) && (Key == LOBYTE(vk_at)) &&
- ((prefix & (SHFT | CTRL)) == CTRL)) {
- /* we assume a ^@ or A-^@ */
- prefix &= ALTD;
- evt = 0;
- }
- break;
- }
- break;
-
- case WM_SYSKEYDOWN:
- /*-process ALT'ed function keys */
- if (!(lParam & 0x20000000)) goto KeyDown;
- /* for some reason, plain F10 arrives as a SYS message ! */
- if (Key == VK_F4) return FALSE; /* standard accelerator for
- Frame's SC_CLOSE */
- goto KeyDown;
-
- case WM_CHAR:
- /*-process regular ASCII, with CTRL & SHFT embedded in event */
- evt = Key;
- break;
-
- case WM_SYSCHAR:
- if (lParam & 0x20000000) { /*-process ALT'ed ASCII char */
- evt = upperc(Key);
- prefix = ALTD;
- if (getbind(ALTD | evt) == NULL) {
- /* that key is not bound, let's ignore it to have
- Windows check for a menu-bar accelerator */
- evt = -1;
- }
- }
- break;
-
- case WM_MENUCHAR:
- if (!(LOWORD(lParam) & MF_POPUP) && (GetKeyState (VK_MENU) < 0)) {
- /* it is an ALT'ed char that does not match any accelerator */
- evt = upperc(Key);
- prefix = ALTD;
- }
- break;
- }
-
- if (evt == -1) return FALSE; /* nothing of interest ! */
-
- if (in_room (3)) {
- if ((prefix != 0) || (evt == 0)) {
- in_put (0);
- in_put (prefix >> 8);
- }
- in_put (evt);
- }
- return TRUE;
- } /* EatKey */
-
- /* PutMouseMessage: feeds a mouse message into the in_put queue */
- /* =============== */
-
- void pascal near PutMouseMessage (WORD wMsg, WORD wParam, POINT Position)
-
- {
- char c;
- int prefix;
-
- if (!mouseflag) return; /* mouse input is disabled */
-
- switch (wMsg) {
- case WM_LBUTTONDOWN:
- c = 'a';
- break;
- case WM_LBUTTONUP:
- c = 'b';
- break;
- case WM_MBUTTONDOWN:
- c = 'c';
- break;
- case WM_MBUTTONUP:
- c = 'd';
- break;
- case WM_RBUTTONDOWN:
- c = 'e';
- break;
- case WM_RBUTTONUP:
- c = 'f';
- break;
- default:
- return; /* should not happen, but let's be safe! */
- }
- prefix = MOUS;
- if (wParam & (MK_CONTROL | MK_SHIFT)) {
- c = toupper(c);
- if (wParam & MK_CONTROL) prefix |= CTRL;
- }
- in_put (0);
- in_put (prefix >> 8);
- in_put ((unsigned char)Position.x);
- in_put ((unsigned char)Position.y);
- in_put (c);
- } /* PutMouseMessage */
-
- /* MouseMessage: handles client area mouse messages */
- /* ============ */
-
- void far pascal MouseMessage (HWND hWnd, WORD wMsg, WORD wParam, DWORD lParam)
- {
- POINT Position;
-
- ClientToCell (hWnd, *(POINT*)&lParam, &Position);
-
- switch (wMsg) {
- case WM_MOUSEMOVE:
- if (MouseTracking && !notquiescent) {
- MoveEmacsCaret (hWnd, Position.x, Position.y);
- }
- break;
-
- case WM_LBUTTONDOWN:
- case WM_MBUTTONDOWN:
- case WM_RBUTTONDOWN:
- if (in_room (5) && mouseflag) {
- PutMouseMessage (wMsg, wParam, Position);
- MouseTracking = TRUE;
- SetCapture (hWnd);
- if (!notquiescent) MoveEmacsCaret (hWnd, Position.x, Position.y);
- }
- break;
-
- case WM_LBUTTONUP:
- case WM_MBUTTONUP:
- case WM_RBUTTONUP:
- if (MouseTracking) {
- if (in_room (5)) PutMouseMessage (wMsg, wParam, Position);
- MouseTracking = FALSE;
- ReleaseCapture (); /* let go of the mouse */
- if (!notquiescent) {
- MoveEmacsCaret (hWnd, CurrentCol, CurrentRow);
- /* restore the caret */
- }
- }
- break;
- }
- } /* MouseMessage */
-