📄 message.c
字号:
/* --------- message.c ---------- */
#include "dflat.h"
#define USECBRKHNLDR 1
static int px = -1, py = -1;
static int pmx = -1, pmy = -1;
static int mx, my;
static int handshaking=0;
static volatile BOOL CriticalError;
BOOL AllocTesting=FALSE,AltDown=FALSE;
jmp_buf AllocError;
/* ---------- event queue ---------- */
static struct events {
MESSAGE event;
int mx;
int my;
} EventQueue[MAXMESSAGES];
/* ---------- message queue --------- */
static struct msgs {
WINDOW wnd;
MESSAGE msg;
PARAM p1;
PARAM p2;
} MsgQueue[MAXMESSAGES];
static int EventQueueOnCtr;
static int EventQueueOffCtr;
static int EventQueueCtr;
static int MsgQueueOnCtr;
static int MsgQueueOffCtr;
static int MsgQueueCtr;
static int lagdelay = FIRSTDELAY;
WINDOW CaptureMouse;
WINDOW CaptureKeyboard;
static BOOL NoChildCaptureMouse;
static BOOL NoChildCaptureKeyboard;
static int doubletimer = 0;
static int delaytimer = 1;
static int clocktimer = 2;
static char timerused[3] = {0, 0, 0};
static long unsigned int timerend[3] = {0, 0, 0};
static long unsigned int timerstart[3] = {0, 0, 0};
volatile long unsigned int *biostimer = MK_FP(0x40,0x6c);
char time_string[] = "12:34pm ";
static WINDOW Cwnd;
static void StopMsg(void);
/* ------- timer interrupt service routine ------- */
/* More complex countdown handling by Eric Auer */
/* Allows us to work without hooking intr. 0x08 */
int timed_out(int timer) /* was: countdown 0? */
{
if ((timer > 2) || (timer < 0))
return -1; /* invalid -> always elapsed */
if (timerused[timer] == 0) /* not active at all? */
return 0;
if (timerused[timer] == 2) /* timeout already known? */
return 1;
if ((biostimer[0] < timerstart[timer]) || (biostimer[0] >= timerend[timer]))
{
timerused[timer] = 2; /* countdown elapsed */
return 1;
}
return 0; /* still waiting */
}
int timer_running(int timer) /* was: countdown > 0? */
{
if ((timer > 2) || (timer < 0))
return 0; /* invalid -> never running */
if (timerused[timer] == 1) /* running? */
{
return (1 - timed_out(timer)); /* if not elapsed, running */
}
else
return 0; /* certainly not running */
}
int timer_disabled(int timer) /* was: countdown -1? */
{
if ((timer > 2) || (timer < 0))
return 1; /* invalid -> always disabled */
return (timerused[timer] == 0);
}
void disable_timer(int timer) /* was: countdown = -1 */
{
if ((timer > 2) || (timer < 0))
return;
timerused[timer] = 0;
}
void set_timer(int timer, int secs)
{
if ((timer > 2) || (timer < 0))
return;
timerstart[timer]=biostimer[0];
timerend[timer]=timerstart[timer] + (secs*182UL/10) + 1;
timerused[timer]=1; /* mark as running */
}
void set_timer_ticks(int timer, int ticks)
{
if ((timer > 2) || (timer < 0))
return;
timerstart[timer]=biostimer[0];
timerend[timer]=timerstart[timer] + ticks;
timerused[timer]=1; /* mark as running */
}
#ifdef OLDCRITERR
static char ermsg[] = "Error accessing drive x:";
#else
static char ermsg[] = "Error accessing drive";
#endif
/* -------- test for critical errors --------- */
int TestCriticalError(void)
{
int rtn = 0;
if (CriticalError)
{
beep();
rtn = 1;
CriticalError = FALSE;
if (TestErrorMessage(ermsg) == FALSE)
rtn = 2;
}
return rtn;
}
/* ------ critical error interrupt service routine ------ */
#ifdef OLDCRITERR
static void interrupt far newcrit(IREGS ir);
static void interrupt far newcrit(IREGS ir)
{
if (!(ir.ax & 0x8000)) /* If any drive affected... */
{
ermsg[sizeof(ermsg)-2]=(ir.ax & 0xff) + 'A';
CriticalError=TRUE; /* ... only then we have a crit. error */
}
ir.ax = 0;
}
#else
int crit_error(void);
/* ----- critical error handler ----- */
int crit_error(void)
{
CriticalError = TRUE;
hardretn(-1); /* return an error! */
return 2; /* is this correct??? */
/* some possibilities: hardresume(1) is retry, */
/* hardresume(2) is abort. Or return to the caller */
/* with a fake function result: hardretn(result) */
}
#endif
static void StopMsg(void)
{
ClearClipboard();
ClearDialogBoxes();
restorecursor();
unhidecursor();
hide_mousecursor();
}
#ifdef USECBRKHNLDR
/* ------ control break handler --------- */
#define ABORT 0
#define CONTINUE 1 /* any non-zero # will continue */
int c_break(void)
{
/* PostMessage(NULL, STOP, 0, 0);
StopMsg();
*/
return CONTINUE; /* JUST IGNORE CTRL BREAK ... */
}
#endif
/* ------------ initialize the message system --------- */
BOOL init_messages(void)
{
AllocTesting = TRUE;
if (setjmp(AllocError) != 0)
{
StopMsg();
return FALSE;
}
resetmouse();
set_mousetravel(0, SCREENWIDTH-1, 0, SCREENHEIGHT-1);
savecursor();
hidecursor();
px = py = -1;
pmx = pmy = -1;
mx = my = 0;
CaptureMouse = CaptureKeyboard = NULL;
NoChildCaptureMouse = FALSE;
NoChildCaptureKeyboard = FALSE;
MsgQueueOnCtr = MsgQueueOffCtr = MsgQueueCtr = 0;
EventQueueOnCtr = EventQueueOffCtr = EventQueueCtr = 0;
#ifdef OLDCRITERR /* old style: hook intr 0x24 manually */
setvect(CRIT, newcrit); /* (vector save/restore not needed here) */
#else
harderr(crit_error); /* set critical error handler (dos.h) */
/* handler uses hardretn / hardresume */
#endif
#ifdef USECBRKHNLDR
ctrlbrk(c_break); /* set ctrl break handler (dos.h) */
/* handler returns 0 to abort program */
setcbrk(0); /* 1 = all / 0 = only con calls check */
#endif
PostMessage(NULL,START,0,0);
lagdelay = FIRSTDELAY;
return TRUE;
}
/* ----- post an event and parameters to event queue ---- */
static void PostEvent(MESSAGE event, int p1, int p2)
{
if (EventQueueCtr != MAXMESSAGES)
{
EventQueue[EventQueueOnCtr].event = event;
EventQueue[EventQueueOnCtr].mx = p1;
EventQueue[EventQueueOnCtr].my = p2;
if (++EventQueueOnCtr == MAXMESSAGES)
EventQueueOnCtr = 0;
EventQueueCtr++;
}
}
/* ------ collect mouse, clock, and keyboard events ----- */
static void near collect_events(void)
{
static int ShiftKeys=0;
int sk,hr;
struct tm *now;
/* Test for a clock event (one/second) */
if (timed_out(clocktimer))
{
struct COUNTRY thiscountry; /* Country support new 0.8 */
time_t t=time(NULL); /* The current time */
char timesep=':'; /* Default 12:12am separator */
int ampmflag=1;
if (country(0, &thiscountry)) /* dos.h (int 21.38) */
{
timesep=thiscountry.co_tmsep[0];
ampmflag=(thiscountry.co_time == 0); /* 0 ampm 1 24h clock */
}
/* Get the current time */
now=localtime(&t);
hr=now->tm_hour;
if (ampmflag && (hr > 12)) hr -= 12;
if (ampmflag && (hr == 0)) hr = 12;
if (ampmflag)
{
sprintf(time_string, "%2d%c%02d%s", hr, timesep, now->tm_min, ((now->tm_hour > 11) ? "pm " : "am "));
}
else
sprintf(time_string, "%2d%c%02d", hr, timesep, now->tm_min);
set_timer(clocktimer, 1); /* Reset the timer */
PostEvent(CLOCKTICK, FP_SEG(time_string), FP_OFF(time_string));
}
/* Keyboard events */
if ((sk=getshift()) != ShiftKeys)
{
ShiftKeys=sk;
/* The shift status changed */
PostEvent(SHIFT_CHANGED, sk, 0);
if (sk & ALTKEY)
AltDown=TRUE;
}
/* Test for keystroke */
if (keyhit())
{
int c=getkey();
AltDown=FALSE;
PostEvent(KEYBOARD, c, sk);
}
/* Test for mouse events */
if (button_releases())
{
/* The button was released */
AltDown=FALSE;
set_timer_ticks(doubletimer, DOUBLETICKS);
PostEvent(BUTTON_RELEASED, mx, my);
disable_timer(delaytimer);
}
get_mouseposition(&mx, &my);
if (mx != px || my != py)
{
px=mx;
py=my;
PostEvent(MOUSE_MOVED, mx, my);
}
if (rightbutton())
{
AltDown=FALSE;
PostEvent(RIGHT_BUTTON, mx, my);
}
if (leftbutton())
{
AltDown=FALSE;
if (mx == pmx && my == pmy)
{
/* Same position as last left button */
if (timer_running(doubletimer))
{
/* Second click before double timeout */
disable_timer(doubletimer);
PostEvent(DOUBLE_CLICK, mx, my);
}
else if (!timer_running(delaytimer))
{
/* Button held down a while */
set_timer_ticks(delaytimer, lagdelay);
lagdelay=DELAYTICKS;
PostEvent(LEFT_BUTTON, mx, my);
}
}
else
{
/* New button press */
disable_timer(doubletimer);
set_timer_ticks(delaytimer, FIRSTDELAY);
lagdelay=DELAYTICKS;
PostEvent(LEFT_BUTTON, mx, my);
pmx=mx;
pmy=my;
}
}
else
lagdelay=FIRSTDELAY;
}
/* ----- post a message and parameters to msg queue ---- */
void PostMessage(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
{
if (MsgQueueCtr != MAXMESSAGES)
{
MsgQueue[MsgQueueOnCtr].wnd=wnd;
MsgQueue[MsgQueueOnCtr].msg=msg;
MsgQueue[MsgQueueOnCtr].p1=p1;
MsgQueue[MsgQueueOnCtr].p2=p2;
if (++MsgQueueOnCtr == MAXMESSAGES)
MsgQueueOnCtr=0;
MsgQueueCtr++;
}
}
/* --------- send a message to a window ----------- */
int SendMessage(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
{
int rtn=TRUE,x,y;
#ifdef INCLUDE_LOGGING
LogMessages(wnd, msg, p1, p2);
#endif
if (wnd != NULL)
switch (msg)
{
case PAINT:
case BORDER:
/* Don't send these messages unless the window is visible */
if (isVisible(wnd))
rtn=(*wnd->wndproc)(wnd, msg, p1, p2);
break;
case RIGHT_BUTTON:
case LEFT_BUTTON:
case DOUBLE_CLICK:
case BUTTON_RELEASED:
/* Don't send these messages unless the window is
visible or has captured the mouse */
if (isVisible(wnd) || wnd == CaptureMouse)
rtn=(*wnd->wndproc)(wnd, msg, p1, p2);
break;
case KEYBOARD:
case SHIFT_CHANGED:
/* Don't send these messages unless the window is
visible or has captured the keyboard */
if (!(isVisible(wnd) || wnd == CaptureKeyboard))
break;
default:
rtn=(*wnd->wndproc)(wnd, msg, p1, p2);
break;
}
/* Window processor returned true or the message was sent to no window at all. */
if (rtn != FALSE)
{
/* Process messages that a window sends to the system itself */
switch (msg)
{
case STOP:
StopMsg();
break;
/* Clock messages */
case CAPTURE_CLOCK:
if (Cwnd == NULL)
set_timer(clocktimer, 0);
wnd->PrevClock = Cwnd;
Cwnd = wnd;
break;
case RELEASE_CLOCK:
Cwnd = wnd->PrevClock;
if (Cwnd == NULL)
disable_timer(clocktimer);
break;
/* Keyboard messages */
case KEYBOARD_CURSOR:
if (wnd == NULL)
cursor((int)p1, (int)p2);
else if (wnd == inFocus)
cursor(GetClientLeft(wnd)+(int)p1,GetClientTop(wnd)+(int)p2);
break;
case CAPTURE_KEYBOARD:
if (p2)
((WINDOW)p2)->PrevKeyboard=CaptureKeyboard;
else
wnd->PrevKeyboard = CaptureKeyboard;
CaptureKeyboard=wnd;
NoChildCaptureKeyboard=(int)p1;
break;
case RELEASE_KEYBOARD:
if (wnd != NULL)
{
if (CaptureKeyboard == wnd || (int)p1)
CaptureKeyboard=wnd->PrevKeyboard;
else
{
WINDOW twnd=CaptureKeyboard;
while (twnd != NULL)
{
if (twnd->PrevKeyboard == wnd)
{
twnd->PrevKeyboard=wnd->PrevKeyboard;
break;
}
twnd=twnd->PrevKeyboard;
}
if (twnd == NULL)
CaptureKeyboard = NULL;
}
wnd->PrevKeyboard = NULL;
}
else
CaptureKeyboard = NULL;
NoChildCaptureKeyboard = FALSE;
break;
case CURRENT_KEYBOARD_CURSOR:
curr_cursor(&x, &y);
*(int*)p1=x;
*(int*)p2=y;
break;
case SAVE_CURSOR:
savecursor();
break;
case RESTORE_CURSOR:
restorecursor();
break;
case HIDE_CURSOR:
normalcursor();
hidecursor();
break;
case SHOW_CURSOR:
if (p1)
set_cursor_type(0x0607); /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -