home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Breakthrough: Utilities & Productivity
/
SharewearBreakthroughUtil_ProdCol.cdr
/
util
/
mews
/
mswinput.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-10-07
|
10KB
|
375 lines
/* 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 or MSC 6.0 or later versions.
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 ((vk_at >> 8) != 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 (UINT MsgCode, UINT wParam, LONG 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 */
{
int evt = -1; /* -1 means: key not for emacs */
WORD prefix = 0;
WORD Key;
if (IsIconic (hFrameWnd)) return FALSE; /* no input while fully
iconic */
Key = LOWORD(wParam);
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 */
prefix |= ALTD;
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((char)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 WINDOW_MSWIN32
if (!(HIWORD(wParam) & MF_POPUP) && (GetKeyState (VK_MENU) < 0)) {
#else
if (!(LOWORD(lParam) & MF_POPUP) && (GetKeyState (VK_MENU) < 0)) {
#endif
/* it is an ALT'ed char that does not match any accelerator */
evt = upperc((char)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 PutMouseMessage (UINT wMsg, UINT 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 = upperc (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, UINT wMsg, UINT wParam, LONG lParam)
{
POINT Position;
Position.x = (short)LOWORD(lParam);
Position.y = (short)HIWORD(lParam);
ClientToCell (hWnd, Position, &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;
default:
break;
}
} /* MouseMessage */
#if !WIN30SDK
/* DropMessage: handles WM_DROPFILES messages */
/* =========== */
void FAR PASCAL DropMessage (HWND hWnd, HDROP hDrop)
/* Generates a MS! keystroke. $xpos/$ypos contain the position where
the files were dropped, or -1 (actually, 255) if the drop occurred
outside a screen client area. The invisible buffer "Dropped files" is
filled with the list of files dropped (one per line), except the first
line which is either empty or contains the name of the screen where the
drop occurred. */
{
BUFFER *DropBuf;
POINT Point;
DropBuf = bfind("Dropped files", TRUE, BFINVS);
if (DropBuf && bclear (DropBuf)) {
if ((hWnd == hFrameWnd) || (hWnd == hMDIClientWnd)) {
Point.x = -1;
Point.y = -1;
addline (DropBuf, ""); /* no screen name */
}
else {
/* the drop occured on a screen */
addline (DropBuf, ((SCREEN*)GetWindowLong (hWnd, GWL_SCRPTR))->s_screen_name);
if (DragQueryPoint (hDrop, &Point)) {
ClientToCell (hWnd, Point, &Point);
}
else {
/* not within the client area! */
Point.x = -1;
Point.y = -1;
}
}
{ /*-complete the DropBuf with the file name list */
char FileName [NFILEN];
WORD Number;
WORD i;
Number = DragQueryFile (hDrop, -1, NULL, 0);
for (i = 0; i < Number; i++) {
DragQueryFile (hDrop, i, FileName, NFILEN);
addline (DropBuf, FileName);
}
DropBuf->b_dotp = lforw(DropBuf->b_linep);
DropBuf->b_doto = 0;
}
/*-feed the pseudo-keystroke into the in_put stream */
in_put (0);
in_put (MOUS >> 8);
in_put ((unsigned char)Point.x);
in_put ((unsigned char)Point.y);
in_put ('!');
}
DragFinish (hDrop);
} /* DropMessage */
#endif