home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
drdobbs
/
1991
/
07
/
dflat.791
< prev
next >
Wrap
Text File
|
1991-06-11
|
25KB
|
722 lines
_C PROGRAMMING COLUMN_
by Al Stevens
[LISTING ONE]
/* ----------- message.h ------------ */
#ifndef MESSAGES_H
#define MESSGAES_H
#define MAXMESSAGES 50
#define DELAYTICKS 1
#define FIRSTDELAY 7
#define DOUBLETICKS 5
typedef enum messages {
/* ------------- process communication messages --------- */
START, /* start message processing */
STOP, /* stop message processing */
COMMAND, /* send a command to a window */
/* ------------- window management messages ------------- */
CREATE_WINDOW, /* create a window */
SHOW_WINDOW, /* show a window */
HIDE_WINDOW, /* hide a window */
CLOSE_WINDOW, /* delete a window */
SETFOCUS, /* set and clear the focus */
PAINT, /* paint the window's data space */
BORDER, /* paint the window's border */
TITLE, /* display the window's title */
MOVE, /* move the window */
SIZE, /* change the window's size */
MAXIMIZE, /* maximize the window */
MINIMIZE, /* minimize the window */
RESTORE, /* restore the window */
INSIDE_WINDOW, /* test x/y inside a window */
/* ------------- clock messages ------------------------- */
CLOCKTICK, /* the clock ticked */
CAPTURE_CLOCK, /* capture clock into a window */
RELEASE_CLOCK, /* release clock to the system */
/* ------------- keyboard and screen messages ----------- */
KEYBOARD, /* key was pressed */
CAPTURE_KEYBOARD, /* capture keyboard into a window */
RELEASE_KEYBOARD, /* release keyboard to system */
KEYBOARD_CURSOR, /* position the keyboard cursor */
CURRENT_KEYBOARD_CURSOR,/* read the cursor position */
HIDE_CURSOR, /* hide the keyboard cursor */
SHOW_CURSOR, /* display the keyboard cursor */
SAVE_CURSOR, /* save the cursor's configuration*/
RESTORE_CURSOR, /* restore the saved cursor */
SHIFT_CHANGED, /* the shift status changed */
/* ------------- mouse messages ------------------------- */
MOUSE_INSTALLED, /* test for mouse installed */
RIGHT_BUTTON, /* right button pressed */
LEFT_BUTTON, /* left button pressed */
DOUBLE_CLICK, /* right button double-clicked */
MOUSE_MOVED, /* mouse changed position */
BUTTON_RELEASED, /* mouse button released */
CURRENT_MOUSE_CURSOR, /* get mouse position */
MOUSE_CURSOR, /* set mouse position */
SHOW_MOUSE, /* make mouse cursor visible */
HIDE_MOUSE, /* hide mouse cursor */
WAITMOUSE, /* wait until button released */
TESTMOUSE, /* test any mouse button pressed */
CAPTURE_MOUSE, /* capture mouse into a window */
RELEASE_MOUSE, /* release the mouse to system */
/* ------------- text box messages ---------------------- */
ADDTEXT, /* add text to the text box */
CLEARTEXT, /* clear the edit box */
SETTEXT, /* set address of text buffer */
SCROLL, /* vertical scroll of text box */
HORIZSCROLL, /* horizontal scroll of text box */
/* ------------- edit box messages ---------------------- */
EB_GETTEXT, /* get text from an edit box */
EB_PUTTEXT, /* put text into an edit box */
/* ------------- menubar messages ----------------------- */
BUILDMENU, /* build the menu display */
SELECTION, /* menubar selection */
/* ------------- popdown messages ----------------------- */
BUILD_SELECTIONS, /* build the menu display */
CLOSE_POPDOWN, /* tell parent popdown is closing */
/* ------------- list box messages ---------------------- */
LB_SELECTION, /* sent to parent on selection */
LB_CHOOSE, /* sent when user chooses */
LB_CURRENTSELECTION, /* return the current selection */
LB_GETTEXT, /* return the text of selection */
LB_SETSELECTION, /* sets the listbox selection */
/* ------------- dialog box messages -------------------- */
INITIATE_DIALOG, /* begin a dialog */
ENTERFOCUS, /* tell DB control got focus */
LEAVEFOCUS, /* tell DB control lost focus */
ENDDIALOG /* end a dialog */
} MESSAGE;
/* --------- message prototypes ----------- */
void init_messages(void);
void PostMessage(WINDOW, MESSAGE, PARAM, PARAM);
int SendMessage(WINDOW, MESSAGE, PARAM, PARAM);
int dispatch_message(void);
int TestCriticalError(void);
#endif
[LISTING TWO]
/* --------- message.c ---------- */
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#include <string.h>
#include <time.h>
#include "dflat.h"
static int px = -1, py = -1;
static int pmx = -1, pmy = -1;
static int mx, my;
static int CriticalError;
/* ---------- 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;
static void (interrupt far *oldtimer)(void) = NULL;
WINDOW CaptureMouse = NULLWND;
WINDOW CaptureKeyboard = NULLWND;
static int NoChildCaptureMouse = FALSE;
static int NoChildCaptureKeyboard = FALSE;
static int doubletimer = -1;
static int delaytimer = -1;
static int clocktimer = -1;
WINDOW Cwnd = NULLWND;
/* ------- timer interrupt service routine ------- */
static void interrupt far newtimer(void)
{
if (timer_running(doubletimer))
countdown(doubletimer);
if (timer_running(delaytimer))
countdown(delaytimer);
if (timer_running(clocktimer))
countdown(clocktimer);
oldtimer();
}
static char ermsg[] = "Error accessing drive x";
/* -------- test for critical errors --------- */
int TestCriticalError(void)
{
int rtn = 0;
if (CriticalError) {
rtn = 1;
CriticalError = FALSE;
if (TestErrorMessage(ermsg) == FALSE)
rtn = 2;
}
return rtn;
}
/* ------ critical error interrupt service routine ------ */
static void interrupt far newcrit(IREGS ir)
{
if (!(ir.ax & 0x8000)) {
ermsg[sizeof(ermsg) - 2] = (ir.ax & 0xff) + 'A';
CriticalError = TRUE;
}
ir.ax = 0;
}
/* ------------ initialize the message system --------- */
void init_messages(void)
{
resetmouse();
show_mousecursor();
px = py = -1;
pmx = pmy = -1;
mx = my = 0;
CaptureMouse = CaptureKeyboard = NULLWND;
NoChildCaptureMouse = FALSE;
NoChildCaptureKeyboard = FALSE;
MsgQueueOnCtr = MsgQueueOffCtr = MsgQueueCtr = 0;
EventQueueOnCtr = EventQueueOffCtr = EventQueueCtr = 0;
if (oldtimer == NULL) {
oldtimer = getvect(TIMER);
setvect(TIMER, newtimer);
}
setvect(CRIT, newcrit);
PostMessage(NULLWND,START,0,0);
lagdelay = FIRSTDELAY;
}
/* ----- 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)
{
struct tm *now;
static int flipflop = FALSE;
static char timestr[8];
int hr, sk;
static int ShiftKeys = 0;
/* -------- test for a clock event (one/second) ------- */
if (timed_out(clocktimer)) {
/* ----- get the current time ----- */
time_t t = time(NULL);
now = localtime(&t);
hr = now->tm_hour > 12 ?
now->tm_hour - 12 :
now->tm_hour;
if (hr == 0)
hr = 12;
sprintf(timestr, "%2.2d:%02d", hr, now->tm_min);
strcpy(timestr+5, now->tm_hour > 11 ? "pm" : "am");
/* ------- blink the : at one-second intervals ----- */
if (flipflop)
*(timestr+2) = ' ';
flipflop ^= TRUE;
/* -------- reset the timer -------- */
set_timer(clocktimer, 1);
/* -------- post the clock event -------- */
PostEvent(CLOCKTICK, FP_SEG(timestr), FP_OFF(timestr));
}
/* --------- keyboard events ---------- */
if ((sk = getshift()) != ShiftKeys) {
ShiftKeys = sk;
/* ---- the shift status changed ---- */
PostEvent(SHIFT_CHANGED, sk, 0);
}
/* ---- build keyboard events for key combinations that
BIOS doesn't report --------- */
if (sk & ALTKEY)
if (inp(0x60) == 14) {
while (!(inp(0x60) & 0x80))
;
PostEvent(KEYBOARD, ALT_BS, sk);
}
if (sk & CTRLKEY)
if (inp(0x60) == 82) {
while (!(inp(0x60) & 0x80))
;
PostEvent(KEYBOARD, CTRL_INS, sk);
}
/* ----------- test for keystroke ------- */
if (keyhit()) {
static int cvt[] = {SHIFT_INS,END,DN,PGDN,BS,'5',
FWD,HOME,UP,PGUP};
int c = getkey();
/* -------- convert numeric pad keys ------- */
if (sk & (LEFTSHIFT | RIGHTSHIFT)) {
if (c >= '0' && c <= '9')
c = cvt[c-'0'];
else if (c == '.' || c == DEL)
c = SHIFT_DEL;
else if (c == INS)
c = SHIFT_INS;
}
/* -------- clear the BIOS readahead buffer -------- */
*(int far *)(MK_FP(0x40,0x1a)) =
*(int far *)(MK_FP(0x40,0x1c));
/* ---- if help key call generic help function ---- */
if (c == F1)
HelpFunction();
else
/* ------ post the keyboard event ------ */
PostEvent(KEYBOARD, c, sk);
}
/* ------------ test for mouse events --------- */
get_mouseposition(&mx, &my);
if (mx != px || my != py) {
px = mx;
py = my;
PostEvent(MOUSE_MOVED, mx, my);
}
if (rightbutton())
PostEvent(RIGHT_BUTTON, mx, my);
if (leftbutton()) {
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 ---- */
delaytimer = lagdelay;
lagdelay = DELAYTICKS;
/* ---- post a typematic-like button ---- */
PostEvent(LEFT_BUTTON, mx, my);
}
}
else {
/* --------- new button press ------- */
disable_timer(doubletimer);
delaytimer = FIRSTDELAY;
lagdelay = DELAYTICKS;
PostEvent(LEFT_BUTTON, mx, my);
pmx = mx;
pmy = my;
}
}
else
lagdelay = FIRSTDELAY;
if (button_releases()) {
/* ------- the button was released -------- */
doubletimer = DOUBLETICKS;
PostEvent(BUTTON_RELEASED, mx, my);
disable_timer(delaytimer);
}
}
/* ----- 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;
if (wnd != NULLWND)
switch (msg) {
case PAINT:
case BORDER:
case RIGHT_BUTTON:
case LEFT_BUTTON:
case DOUBLE_CLICK:
case BUTTON_RELEASED:
case KEYBOARD:
case SHIFT_CHANGED:
/* ------- don't send these messages unless the
window is visible -------- */
if (!isVisible(wnd))
break;
default:
rtn = wnd->wndproc(wnd, msg, p1, p2);
break;
}
/* ----- window processor returned or the message was sent
to no window at all (NULLWND) ----- */
if (rtn != FALSE) {
/* --------- process messages that a window sends to the
system itself ---------- */
switch (msg) {
case STOP:
hide_mousecursor();
if (oldtimer != NULL) {
setvect(TIMER, oldtimer);
oldtimer = NULL;
}
break;
/* ------- clock messages --------- */
case CAPTURE_CLOCK:
Cwnd = wnd;
set_timer(clocktimer, 0);
break;
case RELEASE_CLOCK:
Cwnd = NULLWND;
disable_timer(clocktimer);
break;
/* -------- keyboard messages ------- */
case KEYBOARD_CURSOR:
if (wnd == NULLWND)
cursor((int)p1, (int)p2);
else
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:
CaptureKeyboard = wnd->PrevKeyboard;
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(0x0106);
else
set_cursor_type(0x0607);
unhidecursor();
break;
/* -------- mouse messages -------- */
case MOUSE_INSTALLED:
rtn = mouse_installed();
break;
case SHOW_MOUSE:
show_mousecursor();
break;
case HIDE_MOUSE:
hide_mousecursor();
break;
case MOUSE_CURSOR:
set_mouseposition((int)p1, (int)p2);
break;
case CURRENT_MOUSE_CURSOR:
get_mouseposition((int*)p1,(int*)p2);
break;
case WAITMOUSE:
waitformouse();
break;
case TESTMOUSE:
rtn = mousebuttons();
break;
case CAPTURE_MOUSE:
if (p2)
((WINDOW)p2)->PrevMouse = CaptureMouse;
else
wnd->PrevMouse = CaptureMouse;
CaptureMouse = wnd;
NoChildCaptureMouse = (int)p1;
break;
case RELEASE_MOUSE:
CaptureMouse = wnd->PrevMouse;
NoChildCaptureMouse = FALSE;
break;
default:
break;
}
}
return rtn;
}
/* ---- dispatch messages to the message proc function ---- */
int dispatch_message(void)
{
WINDOW Mwnd, Kwnd;
/* -------- collect mouse and keyboard events ------- */
collect_events();
/* --------- dequeue and process events -------- */
while (EventQueueCtr > 0) {
struct events ev = EventQueue[EventQueueOffCtr];
if (++EventQueueOffCtr == MAXMESSAGES)
EventQueueOffCtr = 0;
--EventQueueCtr;
/* ------ get the window in which a
mouse event occurred ------ */
Mwnd = inWindow(ev.mx, ev.my);
/* ---- process mouse captures ----- */
if (CaptureMouse != NULLWND)
if (Mwnd == NULLWND ||
NoChildCaptureMouse ||
GetParent(Mwnd) != CaptureMouse)
Mwnd = CaptureMouse;
/* ------ get the window in which a
keyboard event occurred ------ */
Kwnd = inFocus;
/* ---- process keyboard captures ----- */
if (CaptureKeyboard != NULLWND)
if (Kwnd == NULLWND ||
NoChildCaptureKeyboard ||
GetParent(Kwnd) != CaptureKeyboard)
Kwnd = CaptureKeyboard;
/* -------- send mouse and keyboard messages to the
window that should get them -------- */
switch (ev.event) {
case SHIFT_CHANGED:
case KEYBOARD:
SendMessage(Kwnd, ev.event, ev.mx, ev.my);
break;
case LEFT_BUTTON:
if (!CaptureMouse ||
(!NoChildCaptureMouse &&
GetParent(Mwnd) == CaptureMouse))
if (Mwnd != inFocus)
SendMessage(Mwnd, SETFOCUS, TRUE, 0);
case BUTTON_RELEASED:
case DOUBLE_CLICK:
case RIGHT_BUTTON:
case MOUSE_MOVED:
SendMessage(Mwnd, ev.event, ev.mx, ev.my);
break;
case CLOCKTICK:
SendMessage(Cwnd, ev.event,
(PARAM) MK_FP(ev.mx, ev.my), 0);
default:
break;
}
}
/* ------ dequeue and process messages ----- */
while (MsgQueueCtr > 0) {
struct msgs mq = MsgQueue[MsgQueueOffCtr];
if (++MsgQueueOffCtr == MAXMESSAGES)
MsgQueueOffCtr = 0;
--MsgQueueCtr;
SendMessage(mq.wnd, mq.msg, mq.p1, mq.p2);
if (mq.msg == STOP || mq.msg == ENDDIALOG)
return FALSE;
}
return TRUE;
}
[LISTING THREE]
/* ------- display a window's border ----- */
void RepaintBorder(WINDOW wnd, RECT *rcc)
{
int y;
int lin, side, ne, nw, se, sw;
RECT rc, clrc;
if (!TestAttribute(wnd, HASBORDER))
return;
if (rcc == NULL) {
rc = SetRect(0, 0, WindowWidth(wnd)-1,
WindowHeight(wnd)-1);
if (TestAttribute(wnd, SHADOW)) {
rc.rt++;
rc.bt++;
}
}
else
rc = *rcc;
clrc = rc;
/* -------- adjust the client rectangle ------- */
if (RectLeft(rc) == 0)
--clrc.rt;
else
--clrc.lf;
if (RectTop(rc) == 0)
--clrc.bt;
else
--clrc.tp;
RectRight(clrc) = min(RectRight(clrc), WindowWidth(wnd)-3);
RectBottom(clrc) = min(RectBottom(clrc), WindowHeight(wnd)-3);
if (wnd == inFocus) {
lin = FOCUS_LINE;
side = FOCUS_SIDE;
ne = FOCUS_NE;
nw = FOCUS_NW;
se = FOCUS_SE;
sw = FOCUS_SW;
}
else {
lin = LINE;
side = SIDE;
ne = NE;
nw = NW;
se = SE;
sw = SW;
}
line[WindowWidth(wnd)] = '\0';
/* ---------- window title ------------ */
if (RectTop(rc) == 0)
if (RectLeft(rc) < WindowWidth(wnd))
if (TestAttribute(wnd, TITLEBAR))
DisplayTitle(wnd, clrc);
foreground = FrameForeground(wnd);
background = FrameBackground(wnd);
/* -------- top frame corners --------- */
if (RectTop(rc) == 0) {
if (RectLeft(rc) == 0)
PutWindowChar(wnd, -1, -1, nw);
if (RectLeft(rc) < RectRight(rc)) {
if (RectRight(rc) >= WindowWidth(wnd)-1)
PutWindowChar(wnd, WindowWidth(wnd)-2, -1, ne);
if (TestAttribute(wnd, TITLEBAR) == 0) {
/* ----------- top line ------------- */
memset(line,lin,WindowWidth(wnd)-1);
line[RectRight(clrc)+1] = '\0';
if (strlen(line+RectLeft(clrc)) > 1 ||
TestAttribute(wnd, SHADOW) == 0)
writeline(wnd, line+RectLeft(clrc),
RectLeft(clrc), -1, FALSE);
}
}
}
/* ----------- window body ------------ */
for (y = 0; y < ClientHeight(wnd); y++) {
int ch;
if (y >= RectTop(clrc) && y <= RectBottom(clrc)) {
if (RectLeft(rc) == 0)
PutWindowChar(wnd, -1, y, side);
if (RectLeft(rc) < RectRight(rc)) {
if (RectRight(rc) >= ClientWidth(wnd)) {
if (TestAttribute(wnd, VSCROLLBAR))
ch = ( y == 0 ? UPSCROLLBOX :
y == WindowHeight(wnd)-3 ?
DOWNSCROLLBOX :
y == wnd->VScrollBox ?
SCROLLBOXCHAR :
SCROLLBARCHAR );
else
ch = side;
PutWindowChar(wnd,WindowWidth(wnd)-2,y,ch);
}
}
if (RectRight(rc) == WindowWidth(wnd))
shadow_char(wnd, y);
}
}
if (RectTop(rc) < RectBottom(rc) &&
RectBottom(rc) >= WindowHeight(wnd)-1) {
/* -------- bottom frame corners ---------- */
if (RectLeft(rc) == 0)
PutWindowChar(wnd, -1, WindowHeight(wnd)-2, sw);
if (RectRight(rc) >= WindowWidth(wnd)-1)
PutWindowChar(wnd, WindowWidth(wnd)-2,
WindowHeight(wnd)-2, se);
/* ----------- bottom line ------------- */
memset(line,lin,WindowWidth(wnd)-1);
if (TestAttribute(wnd, HSCROLLBAR)) {
line[0] = LEFTSCROLLBOX;
line[WindowWidth(wnd)-3] = RIGHTSCROLLBOX;
memset(line+1, SCROLLBARCHAR, WindowWidth(wnd)-4);
line[wnd->HScrollBox] = SCROLLBOXCHAR;
}
line[RectRight(clrc)+1] = '\0';
if (strlen(line+RectLeft(clrc)) > 1 || TestAttribute(wnd, SHADOW) == 0)
writeline(wnd,
line+RectLeft(clrc),
RectLeft(clrc),
WindowHeight(wnd)-2,
FALSE);
if (RectRight(rc) == WindowWidth(wnd))
shadow_char(wnd, WindowHeight(wnd)-2);
}
if (RectBottom(rc) == WindowHeight(wnd))
/* ---------- bottom shadow ------------- */
shadowline(wnd, clrc);
}
Example 1:
#include <stdio.h>
main()
{
int x=1,y=1;
x = (y++,y+3);
printf("x=%d,y=%d\n",x,y);
printf("++y=%d,x=%d\n",(--x,++y),x);
}