⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eventlow.c

📁 dos 1.0 其中包含quick basic源代码、内存管理himem emm386 发展历史
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
	COW : Character Oriented Windows

	event.c - Main event handler
*/

#define COW
#include <cow.h>

#define EVENT
#include <uevent.h>
#include <vkey.h>
#include <umenu.h>
#include <uwindow.h>
#include <uscreen.h>
#include <kinput.h>
#include <kkeyboar.h>
#include <uutil.h>
#ifdef EXTRAS
#include <cowextra.h>
#endif

#ifdef KK_UNIT
BOOL	FARPUBLIC KKFilter(PMSG);
#endif

#ifdef WINDOW_OVERLAP
#include "overlap.h"
#endif

#include "window.h"
#include "menu.h"
#include "util.h"

#ifdef DUAL
#include <os2.h>
extern	WORD	fProtectMode;
#else
#ifdef DOS5
#include <os2.h>
#endif
#endif

#include "event.h"
#include "_event.h"

/* ----------------------------------------------------------------------- */

#ifdef RECORD_PLAYBACK
/* Forward declarations */
BOOL FAR PASCAL PlayBackMsg(MSG *);
VOID FAR PASCAL RecordMsg(MSG *);
#endif


#ifdef PROFILE
int PASCAL crefCow = 0;		/* reference count of Cow Public entries */
#endif

#ifdef DOS5
/* NOTE : semaphore is CLEARED when a message is ready !! */
PUBLIC DWORD PASCAL semaMessage = 0;	/* RAM semaphore */
#else
#ifdef	DUAL
PUBLIC DWORD PASCAL semaMessage = 0;	/* RAM semaphore */
#endif
PUBLIC BOOL PASCAL fMessage = FALSE;
#endif

PRIVATE PWND PASCAL pwndRoot = NULL;		/* root window */

MSG msgNull = {0, WM_NULL, 0, 0l, timeMsgMax};	/* a NULL message */

MSGQ msgqAppl = {0, &msgNull, &msgqAppl.rgmsg[0]};
MSGQ msgqKeyboard = {0, &msgNull, &msgqKeyboard.rgmsg[0]};
MSGQ msgqMouse = {0, &msgNull, &msgqMouse.rgmsg[0]};

PMSG pmsgLast = &msgNull;
	/* last message queued used by keyboard and mouse handlers */
PMSG pmsgLastKeyboard = &msgNull;	/* for TSR kludge */

/* window with the focus */
PWND pwndFocus = NULL;
/* window with the mouse capture */
PWND pwndCapture = NULL;

/* Filter of messages */
PRIVATE BOOL FARPRIVATE DummyFilter(PMSG);	/* forward declaration */
PRIVATE PFFN_FILTER pfnFilter = DummyFilter;
#ifdef WINDOW_OVERLAP
PRIVATE PFFN_FILTER pfnOverlapFilter = OverlapFilter;
#endif /*WINDOW_OVERLAP*/

/* Mouse control */
WORD timeDoubleClick = timeDoubleClickDefault;
MSP mspPrev = { 0xff, 0xff, 0xff, 0xff }; /* position of last move */

/* for 1 level of UngetMessage */
BYTE fUseCache = FALSE;
MSG msgCache;

/* Menu Info : see note in MENU.H */
PRIVATE MNI mniCur = { imenuNil, iitemNil, NULL, FALSE, FALSE, FALSE };

/* ----------------------------------------------------------------------- */

/* forward */
STATIC BOOL FNextMsg(MSG *);
STATIC VOID DequeueTopMsg(MSGQ *);
STATIC PWND PwndLocate(PWND, AX, AY);
STATIC VOID CheckDoubleClick(MSG *);

/* ----------------------------------------------------------------------- */


PUBLIC BOOL FARPUBLIC
PeekMessage(pmsg)
/*
  -- check to see if a message is ready
  -- return TRUE if *pmsg filled with a message
  -- return FALSE if no messages pending
  -- always poll the keyboard
*/
PMSG pmsg;
	{
	StartPublic();

	do
		{
		/* don't always poll the keyboard */
		if (fPollKeyboard)
			PollKeyboard();

		ClearMessage();
		fAbort = FALSE;

		/* try to get a message from Cache or Queue */
		if (fUseCache)
			{
			*pmsg = msgCache;
			fUseCache = FALSE;
			/* if cached message is keyboard, use the current
				focus */
			if (msgCache.message >= WM_KEYFIRST &&
			    msgCache.message <= WM_KEYLAST)
				pmsg->pwnd = pwndFocus;
			}
		else
			{
			if (!FNextMsg(pmsg))
				{
				/* event's background process */
				if (!FCheckAlarm(pmsg))
					ReturnPublic(FALSE, BOOL);
				}
#ifdef RECORD_PLAYBACK
			else
				RecordMsg(pmsg);
#endif
			}
		}
#ifndef WINDOW_OVERLAP
#ifdef	KK_UNIT
	while (KKFilter(pmsg) || (*pfnFilter)(pmsg));
#else	// KK_UNIT
	while ((*pfnFilter)(pmsg));
#endif	// KK_UNIT
#else
	while ((*pfnFilter)(pmsg) || (*pfnOverlapFilter)(pmsg));
#endif /*WINDOW_OVERLAP*/

	ReturnPublic(TRUE, BOOL);
	}



STATIC BOOL
FNextMsg(pmsgDest)
/*
  -- Obtain the next message from the queue by looking at the three event queues
  -- return FALSE if there are no messages
  -- fill *pmsgDest with the message
*/
PMSG pmsgDest;
	{
	/* Get a message from each of the queues */
	PMSG pmsgAppl, pmsgKeyboard, pmsgMouse;

retry:
	/* If the menu is active, block application messages */
	pmsgAppl = FMenuActive() ? &msgNull : msgqAppl.pmsgHead;
	pmsgKeyboard = msgqKeyboard.pmsgHead;
	pmsgMouse = msgqMouse.pmsgHead;

	if (pmsgKeyboard->time < pmsgAppl->time)
		{
		if (pmsgMouse->time < pmsgKeyboard->time)
			goto mouse_event;
		/* keyboard earliest */

		pmsgKeyboard->pwnd = pwndFocus;

		*pmsgDest = *pmsgKeyboard;

		DequeueTopMsg(&msgqKeyboard);
		pmsgLastKeyboard = pmsgLast;
#ifdef DOS3
		/* if TSR present, poll to get next message */
		fPollKeyboard = TRUE;
#endif /*DOS3*/

		/* if message is a shift state change, call UpdateShiftKk */
		if (pmsgDest->message == WM_KEYSTATE)
			{
			static WORD	ssOld = 0;
#ifdef KANJI
			static WORD	ssOldKj = 0;
#endif

			UpdateShiftKk(pmsgDest->wParam, ssOld);
			ssOld = pmsgDest->wParam;
#ifdef KANJI
			UpdateShiftKj(LOWORD(pmsgDest->lParam), ssOldKj);
			ssOldKj = LOWORD(pmsgDest->lParam);
#endif
			goto retry;		/* get another */
			}
		}
	else if (pmsgMouse->time < pmsgAppl->time)
		{
		/* mouse earliest */
	mouse_event:
		*pmsgDest = *pmsgMouse;
		DequeueTopMsg(&msgqMouse);
		/* clean up mouse message */
		FindMouseWnd(pmsgDest);
		CheckDoubleClick(pmsgDest);
#ifdef DEBUG
		/* RIGHT BUTTON USED AS DEVELOPMENT HOOK */
		if (pmsgDest->message == WM_RBUTTONDOWN &&
		    FTrapMouseRbutton())
			goto retry;
#endif /*DEBUG*/
		}
	else if (pmsgAppl->time != timeMsgMax)
		{
		/* application earliest */
		*pmsgDest = *pmsgAppl;
		DequeueTopMsg(&msgqAppl);
		}
	else
		{
		/* all 3 queues had null messages when we entered */
#ifdef RECORD_PLAYBACK
		{
		static BOOL fPlayback = FALSE;

		if ((fPlayback = !fPlayback) && PlayBackMsg (pmsgDest))
			{
			if (pmsgDest->message >= WM_MOUSEFIRST &&
			    pmsgDest->message <= WM_MOUSELAST)
				FindMouseWnd(pmsgDest);
			else
				pmsgDest->pwnd = pwndFocus;
			return TRUE;
			}
		}
#endif
		if (!FMenuActive())
			return FALSE;	/* no message available */
		/* never return if inside menu */
		*pmsgDest = msgNull;
		}
	return TRUE;
	}



STATIC VOID
DequeueTopMsg(pmsgq)
/*
  -- dequeue the top message of the specified queue
  -- if pmsgLast == the message being dequeued, then set pmsgLast to &msgNull
  -- the queue must be originally non-empty
  -- if queue gets empty, stick &msgNull in head slot
*/
MSGQ *pmsgq;
	{
	DisableInterrupts();
	AssertSz(pmsgq->cmsg > 0, "Dequeueing an empty queue");
	if (pmsgLast == pmsgq->pmsgHead)
		pmsgLast = &msgNull;
	if (--pmsgq->cmsg == 0)
		pmsgq->pmsgHead = &msgNull;
	else if (++(pmsgq->pmsgHead) == &pmsgq->rgmsg[imsgMax])
		pmsgq->pmsgHead = &pmsgq->rgmsg[0];
	EnableInterrupts();
	}



PUBLIC VOID FARPUBLIC
FlushAbort()
/*
  -- Flush all keyboard messages up to the first ESCAPE
  -- for TSR keyboard input there should be 1 escape key only
  -- can be called from TSR with SS != DS
*/
	{
	REGISTER MSG *pmsg;

	/* if a key in the cache, then flush it */
	if (fUseCache && msgCache.message >= WM_KEYFIRST &&
	    msgCache.message <= WM_KEYLAST)
		{
		/* it was a keyboard message */
		fUseCache = FALSE;
		if (msgCache.message == WM_CHAR && msgCache.wParam == VK_ESCAPE)
			return;	/* already have an escape */
		}

	while ((pmsg = msgqKeyboard.pmsgHead) != &msgNull)
		{
		BOOL	fDone;

		fDone = pmsg->wParam == LOBYTE(VK_ESCAPE);
		DequeueTopMsg(&msgqKeyboard);
		if (fDone)
			break;		/* quit after first ESCAPE */
		}
	}



#ifdef	KANJI
VOID FAR PASCAL /* called by kanji keyboard driver */
KeyboardMessage(sc, vw, wParamKey, kk, fKeyUp)
#else	// !KANJI
VOID FAR PASCAL	/* called by keyboard driver */
KeyboardMessage(vw, wParamKey, kk, fKeyUp)
#endif	// KANJI
/*
  -- called by PollKeyboard for polled input
  -- normally generate only WM_CHAR Messages
  -- two special cases for WM_KEYUP :
		VK_SPACE		(needed for buttons)
		VK_MENU			(needed for menus)
  -- all events at this level set Message
*/
#ifdef	KANJI
BYTE sc;		/* Scan code for KANJI KK-unit */
#endif	// KANJI
BYTE vw;		/* Windows virtual key */
WORD wParamKey;		/* wParam for WM_KEY */
REGISTER WORD kk;	/* KK shift states */
BOOL fKeyUp;		/* TRUE => WM_KEYUP, FALSE => WM_CHAR */
	{
	WORD message;
	WORD vk;				/* the virtual key only */
#ifdef KANJI
	WORD kj;	/* KJ shift states */

	kj = kk & KJ_KK;
	Assert((kj & KJ_COUNT) == 0);
	kk &= ~KK_VK;
#endif

	Assert(vw <= 0xff);
	vk = VkOfVw(vw);			/* change virtual key */

#ifndef KANJI
	Assert((kk & KK_VK) == 0);
#endif

	if (!fKeyUp)
		{
		/* key depressed */
		message = WM_CHAR;
		if (vk == VK_ESCAPE)
			{
			/* ABORT case */
			fAbort = TRUE;
			}
		else if (pmsgLast->message == WM_CHAR &&
#ifdef KANJI
		    (pmsgLast->lParam & KJ_COUNT) < KJ_COUNT &&
#endif
		    pmsgLast->wParam == wParamKey &&
		    kk == HIWORD(pmsgLast->lParam) &&

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -