1 /****************************************************************************
3 * The SuperVGA Kit - UniVBE Software Development Kit
5 * ========================================================================
7 * The contents of this file are subject to the SciTech MGL Public
8 * License Version 1.0 (the "License"); you may not use this file
9 * except in compliance with the License. You may obtain a copy of
10 * the License at http://www.scitechsoft.com/mgl-license.txt
12 * Software distributed under the License is distributed on an
13 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * rights and limitations under the License.
17 * The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
19 * The Initial Developer of the Original Code is SciTech Software, Inc.
20 * All Rights Reserved.
22 * ========================================================================
25 * Environment: IBM PC (MS DOS)
27 * Description: Routines to provide a Linux event queue, which automatically
28 * handles keyboard and mouse events for the Linux compatability
29 * libraries. Based on the event handling code in the MGL.
31 ****************************************************************************/
45 #include <sys/types.h>
46 #include <linux/keyboard.h>
54 /*--------------------------- Global variables ----------------------------*/
56 #define EVENTQSIZE 100 /* Number of events in event queue */
58 static int head = -1; /* Head of event queue */
59 static int tail = -1; /* Tail of event queue */
60 static int freeHead = -1; /* Head of free list */
61 static int count = 0; /* No. of items currently in queue */
62 static WD_event evtq[EVENTQSIZE]; /* The queue structure itself */
63 static int oldMove = -1; /* Previous movement event */
64 static int oldKey = -1; /* Previous key repeat event */
65 static int mx,my; /* Current mouse position */
66 static int xRes,yRes; /* Screen resolution coordinates */
67 static void *stateBuf; /* Pointer to console state buffer */
68 static int conn; /* GPM file descriptor for mouse handling */
69 static int tty_fd; /* File descriptor for /dev/console */
70 extern int tty_vc; /* Virtual console ID, from the PM/Pro library */
71 static ibool key_down[128]; /* State of all keyboard keys */
72 static struct termios old_conf; /* Saved terminal configuration */
73 static int oldkbmode; /* and previous keyboard mode */
74 struct vt_mode oldvtmode; /* Old virtual terminal mode */
75 static int old_flags; /* Old flags for fcntl */
76 static ulong key_modifiers; /* Keyboard modifiers */
77 static int forbid_vt_release=0;/* Flag to forbid release of VT */
78 static int forbid_vt_acquire=0;/* Flag to forbid cature of VT */
79 static int oldmode; /* Old SVGA mode saved for VT switch*/
80 static int initmode; /* Initial text mode */
81 static ibool installed = false; /* True if we are installed */
82 static void (_ASMAPI *moveCursor)(int x,int y) = NULL;
83 static int (_ASMAPI *suspendAppCallback)(int flags) = NULL;
86 /* Keyboard Translation table from scancodes to ASCII */
88 static uchar keyTable[128] =
89 "\0\0331234567890-=\010"
90 "\011qwertyuiop[]\015"
93 "\0\0\0\0\0\0\0\0\0\0\0\0" /* Function keys */
94 "789-456+1230.\0\0\0\0\0" /* Keypad keys */
95 "\0\0\0\0\0\0\0\015\0/";
97 static uchar keyTableShifted[128] =
98 "\0\033!@#$%^&*()_+\010"
99 "\011QWERTYUIOP{}\015"
102 "\0\0\0\0\0\0\0\0\0\0\0\0" /* Function keys */
103 "789-456+1230.\0\0\0\0\0" /* Keypad keys */
104 "\0\0\0\0\0\0\0\015\0/";
107 /* Macros to keep track of the CAPS and NUM lock states */
109 #define EVT_CAPSSTATE 0x0100
110 #define EVT_NUMSTATE 0x0200
112 /* Helper macros for dealing with timers */
114 #define TICKS_TO_USEC(t) ((t)*65536.0/1.193180)
115 #define USEC_TO_TICKS(u) ((u)*1.193180/65536.0)
117 /* Number of keycodes to read at a time from the console */
119 #define KBDREADBUFFERSIZE 32
121 /*---------------------------- Implementation -----------------------------*/
123 /****************************************************************************
125 Returns the current time stamp in units of 18.2 ticks per second.
126 ****************************************************************************/
127 static ulong getTimeStamp(void)
129 return (ulong)(clock() / (CLOCKS_PER_SEC / 18.2));
132 /****************************************************************************
134 evt - Event to place onto event queue
137 Adds an event to the event queue by tacking it onto the tail of the event
138 queue. This routine assumes that at least one spot is available on the
139 freeList for the event to be inserted.
140 ****************************************************************************/
141 static void addEvent(
146 /* Get spot to place the event from the free list */
148 freeHead = evtq[freeHead].next;
150 /* Add to the tail of the event queue */
154 evtq[tail].next = evtID;
162 /****************************************************************************
165 message - Event message
166 modifiers - keyboard modifiers
167 x - Mouse X position at time of event
168 y - Mouse Y position at time of event
169 but_stat - Mouse button status at time of event
172 Adds a new mouse event to the event queue. This routine is called from
173 within the mouse interrupt subroutine, so it must be efficient.
174 ****************************************************************************/
175 static void addMouseEvent(
184 if (count < EVENTQSIZE) {
186 evt.when = getTimeStamp();
187 evt.message = message;
188 evt.modifiers = but_stat | key_modifiers;
191 fprintf(stderr, "(%d,%d), buttons %ld\n", x,y, evt.modifiers);
192 addEvent(&evt); /* Add to tail of event queue */
196 /****************************************************************************
198 scancode - Raw keyboard scan code
199 modifiers - Keyboard modifiers flags
202 Converts the raw scan code into the appropriate ASCII code using the scan
203 code and the keyboard modifier flags.
204 ****************************************************************************/
205 static ulong getKeyMessage(
209 ushort code = scancode << 8;
213 ke.kb_index = scancode;
215 /* Find the basic ASCII code for the scan code */
216 if (modifiers & EVT_CAPSSTATE) {
217 if (modifiers & EVT_SHIFTKEY)
218 ke.kb_table = K_NORMTAB;
219 // ascii = tolower(keyTableShifted[scancode]);
221 ke.kb_table = K_SHIFTTAB;
222 // ascii = toupper(keyTable[scancode]);
225 if (modifiers & EVT_SHIFTKEY)
226 ke.kb_table = K_SHIFTTAB;
227 // ascii = keyTableShifted[scancode];
229 ke.kb_table = K_NORMTAB;
230 // ascii = keyTable[scancode];
232 if(modifiers & EVT_ALTSTATE)
233 ke.kb_table |= K_ALTTAB;
235 if (ioctl(tty_fd, KDGKBENT, (unsigned long)&ke)) {
236 fprintf(stderr, "KDGKBENT at index %d in table %d: ",
237 scancode, ke.kb_table);
242 /* Add ASCII code if key is not alt'ed or ctrl'ed */
243 if (!(modifiers & (EVT_ALTSTATE | EVT_CTRLSTATE)))
249 /****************************************************************************
252 scancode - Raw scancode of keyboard event to add
255 Adds a new keyboard event to the event queue. We only take KEYUP and
256 KEYDOWN event codes, however if a key is already down we convert the KEYDOWN
258 ****************************************************************************/
259 static void addKeyEvent(
265 if (count < EVENTQSIZE) {
267 evt.when = getTimeStamp();
268 evt.message = getKeyMessage(scancode,key_modifiers) | 0x10000UL;
269 evt.where_x = evt.where_y = 0;
270 evt.modifiers = key_modifiers;
271 if (evt.what == EVT_KEYUP)
272 key_down[scancode] = false;
273 else if (evt.what == EVT_KEYDOWN) {
274 if (key_down[scancode]) {
276 evtq[oldKey].message += 0x10000UL;
279 evt.what = EVT_KEYREPEAT;
286 key_down[scancode] = true;
294 /****************************************************************************
296 sig - Signal being sent to this signal handler
299 Signal handler for the timer. This routine takes care of periodically
300 posting timer events to the event queue.
301 ****************************************************************************/
307 if (sig == SIGALRM) {
308 if (count < EVENTQSIZE) {
309 evt.when = getTimeStamp();
310 evt.what = EVT_TIMERTICK;
312 evt.where_x = evt.where_y = 0;
318 signal(SIGALRM, timerHandler);
322 /****************************************************************************
324 Restore the terminal to normal operation on exit
325 ****************************************************************************/
326 static void restore_term(void)
331 /* Restore text mode and the state of the console */
333 PM_int86(0x10,®s,®s);
334 PM_restoreConsoleState(stateBuf,tty_fd);
336 /* Restore console to normal operation */
337 ioctl(tty_fd, VT_SETMODE, &oldvtmode);
338 ioctl(tty_fd, KDSKBMODE, oldkbmode);
339 tcsetattr(tty_fd, TCSAFLUSH, &old_conf);
340 fcntl(tty_fd,F_SETFL,old_flags &= ~O_NONBLOCK);
341 PM_closeConsole(tty_fd);
343 /* Close the mouse driver */
346 /* Flag that we are not no longer installed */
351 /****************************************************************************
353 Signal handler to capture forced program termination conditions so that
354 we can clean up properly.
355 ****************************************************************************/
356 static void exitHandler(int sig)
361 /****************************************************************************
363 Sleep until the virtual terminal is active
364 ****************************************************************************/
365 void wait_vt_active(void)
367 while (ioctl(tty_fd, VT_WAITACTIVE, tty_vc) < 0) {
368 if ((errno != EAGAIN) && (errno != EINTR)) {
369 perror("ioctl(VT_WAITACTIVE)");
376 /****************************************************************************
378 Signal handler called when our virtual terminal has been released and we are
379 losing the active focus.
380 ****************************************************************************/
381 static void release_vt_signal(int n)
383 forbid_vt_acquire = 1;
384 if (forbid_vt_release) {
385 forbid_vt_acquire = 0;
386 ioctl(tty_fd, VT_RELDISP, 0);
390 // TODO: Call the user supplied suspendAppCallback and restore text
391 // mode (saving the existing mode so we can restore it).
393 // Also if the suspendAppCallback is NULL then we have to
394 // ignore the switch request!
395 if(suspendAppCallback){
396 oldmode = VBE_getVideoMode();
397 suspendAppCallback(true);
398 VBE_setVideoMode(initmode);
401 ioctl(tty_fd, VT_RELDISP, 1);
402 forbid_vt_acquire = 0;
406 /****************************************************************************
408 Signal handler called when our virtual terminal has been re-aquired and we
409 are now regaiing the active focus.
410 ****************************************************************************/
411 static void acquire_vt_signal(int n)
413 forbid_vt_release = 1;
414 if (forbid_vt_acquire) {
415 forbid_vt_release = 0;
419 // TODO: Restore the old display mode, call the user suspendAppCallback
420 // and and we will be back in graphics mode.
422 if(suspendAppCallback){
423 VBE_setVideoMode(oldmode);
424 suspendAppCallback(false);
427 ioctl(tty_fd, VT_RELDISP, VT_ACKACQ);
428 forbid_vt_release = 0;
431 /****************************************************************************
433 Function to set the action for a specific signal to call our signal handler.
434 ****************************************************************************/
435 static void set_sigaction(int sig,void (*handler)(int))
437 struct sigaction siga;
439 siga.sa_handler = handler;
440 siga.sa_flags = SA_RESTART;
441 memset(&(siga.sa_mask), 0, sizeof(sigset_t));
442 sigaction(sig, &siga, NULL);
445 /****************************************************************************
447 Function to take over control of VT switching so that we can capture
448 virtual terminal release and aquire signals, allowing us to properly
449 support VT switching while in graphics modes.
450 ****************************************************************************/
451 static void take_vt_control(void)
453 struct vt_mode vtmode;
455 ioctl(tty_fd, VT_GETMODE, &vtmode);
457 vtmode.mode = VT_PROCESS;
458 vtmode.relsig = SIGUSR1;
459 vtmode.acqsig = SIGUSR2;
460 set_sigaction(SIGUSR1, release_vt_signal);
461 set_sigaction(SIGUSR2, acquire_vt_signal);
462 ioctl(tty_fd, VT_SETMODE, &oldvtmode);
465 /****************************************************************************
467 Set the shift keyboard LED's based on the current keyboard modifiers flags.
468 ****************************************************************************/
469 static void updateLEDStatus(void)
472 if (key_modifiers & EVT_CAPSSTATE)
474 if (key_modifiers & EVT_NUMSTATE)
476 ioctl(tty_fd,KDSETLED,state);
479 /****************************************************************************
481 scancode - Raw scan code to handle
484 Handles the shift key modifiers and keeps track of the shift key states
485 so that we can return the correct ASCII codes for the keyboard.
486 ****************************************************************************/
487 static void toggleModifiers(
490 static int caps_down = 0,num_down = 0;
492 if (scancode & 0x80) {
493 /* Handle key-release function */
495 if (scancode == 0x2A || scancode == 0x36)
496 key_modifiers &= ~EVT_SHIFTKEY;
497 else if (scancode == 0x1D || scancode == 0x61)
498 key_modifiers &= ~EVT_CTRLSTATE;
499 else if (scancode == 0x38 || scancode == 0x64)
500 key_modifiers &= ~EVT_ALTSTATE;
501 else if (scancode == 0x3A)
503 else if (scancode == 0x45)
507 /* Handle key-down function */
509 if (scancode == 0x2A || scancode == 0x36)
510 key_modifiers |= EVT_SHIFTKEY;
511 else if (scancode == 0x1D || scancode == 0x61)
512 key_modifiers |= EVT_CTRLSTATE;
513 else if (scancode == 0x38 || scancode == 0x64)
514 key_modifiers |= EVT_ALTSTATE;
515 else if (scancode == 0x3A) {
517 key_modifiers ^= EVT_CAPSSTATE;
522 else if (scancode == 0x45) {
524 key_modifiers ^= EVT_NUMSTATE;
532 /***************************************************************************
534 Returns the number of bits that have changed from 0 to 1
535 (a negative value means the number of bits that have changed from 1 to 0)
536 **************************************************************************/
537 static int compareBits(short a, short b)
540 if( (a&1) != (b&1) ) ret += (b&1) ? 1 : -1;
541 if( (a&2) != (b&2) ) ret += (b&2) ? 1 : -1;
542 if( (a&4) != (b&4) ) ret += (b&4) ? 1 : -1;
546 /***************************************************************************
548 Turns off all keyboard state because we can't rely on them anymore as soon
550 ***************************************************************************/
551 static void keyboard_clearstate(void)
554 memset(key_down, 0, sizeof(key_down));
557 /****************************************************************************
559 Pumps all events from the console event queue into the WinDirect event queue.
560 ****************************************************************************/
561 static void pumpEvents(void)
563 static uchar buf[KBDREADBUFFERSIZE];
565 static int old_buts, old_mx, old_my;
566 static struct timeval t;
571 /* Read all pending keypresses from keyboard buffer and process */
572 while ((numkeys = read(tty_fd, buf, KBDREADBUFFERSIZE)) > 0) {
573 for (i = 0; i < numkeys; i++) {
574 toggleModifiers(buf[i]);
575 if (key_modifiers & EVT_ALTSTATE){
578 // Do VT switching here for Alt+Fx keypresses
579 switch(buf[i] & 0x7F){
580 case 59 ... 68: /* F1 to F10 */
581 fkey = (buf[i] & 0x7F) - 58;
585 fkey = (buf[i] & 0x7F) - 76;
590 ioctl(tty_fd, VT_GETSTATE, &vts);
592 if(fkey != vts.v_active){
593 keyboard_clearstate();
594 ioctl(tty_fd, VT_ACTIVATE, fkey);
600 addKeyEvent(EVT_KEYUP,buf[i] & 0x7F);
602 addKeyEvent(EVT_KEYDOWN,buf[i] & 0x7F);
605 // TODO: If we want to handle VC switching we will need to do it
606 // in here so that we can switch away from the VC and then
607 // switch back to it later. Right now VC switching is disabled
608 // and in order to enable it we need to save/restore the state
609 // of the graphics screen (using the suspendAppCallback and
610 // saving/restoring the state of the current display mode).
614 /* Read all pending mouse events and process them */
618 t.tv_sec = t.tv_usec = 0L;
619 while (select(conn+1, &fds, NULL, NULL, &t) > 0) {
620 if(read(conn, data, 5) == 5){
621 buts = (~data[0]) & 0x07;
622 dx = (char)(data[1]) + (char)(data[3]);
623 dy = -((char)(data[2]) + (char)(data[4]));
628 addMouseEvent(EVT_MOUSEMOVE, 0, mx, my, buts);
630 if (buts != old_buts){
631 int c = compareBits(buts,old_buts);
633 addMouseEvent(EVT_MOUSEDOWN, 0, mx, my, buts);
635 addMouseEvent(EVT_MOUSEUP, 0, mx, my, buts);
637 old_mx = mx; old_my = my;
640 t.tv_sec = t.tv_usec = 0L;
646 /*------------------------ Public interface routines ----------------------*/
648 /****************************************************************************
650 which - Which code for event to post
651 what - Event code for event to post
652 message - Event message
653 modifiers - Shift key/mouse button modifiers
656 True if the event was posted, false if queue is full.
659 Posts an event to the event queue. This routine can be used to post any type
660 of event into the queue.
661 ****************************************************************************/
662 ibool _WDAPI WD_postEvent(
670 if (count < EVENTQSIZE) {
671 /* Save information in event record */
674 evt.when = getTimeStamp();
675 evt.message = message;
676 evt.modifiers = modifiers;
677 addEvent(&evt); /* Add to tail of event queue */
684 /****************************************************************************
686 mask - Event mask to use
689 Flushes all the event specified in 'mask' from the event queue.
690 ****************************************************************************/
691 void _WDAPI WD_flushEvent(
696 do { /* Flush all events */
697 WD_getEvent(&evt,mask);
698 } while (evt.what != EVT_NULLEVT);
701 /****************************************************************************
703 evt - Place to store event
704 mask - Event mask to use
707 Halts program execution until a specified event occurs. The event is
708 returned. All pending events not in the specified mask will be ignored and
709 removed from the queue.
710 ****************************************************************************/
711 void _WDAPI WD_haltEvent(
715 do { /* Wait for an event */
716 WD_getEvent(evt,EVT_EVERYEVT);
717 } while (!(evt->what & mask));
720 /****************************************************************************
722 evt - Place to store event
723 mask - Event mask to use
726 True if an event was pending.
729 Retrieves the next pending event defined in 'mask' from the event queue.
730 The event queue is adjusted to reflect the new state after the event has
732 ****************************************************************************/
733 ibool _WDAPI WD_getEvent(
741 moveCursor(mx,my); /* Move the mouse cursor */
742 evt->what = EVT_NULLEVT; /* Default to null event */
745 for (evtID = head; evtID != -1; evtID = evtq[evtID].next) {
746 if (evtq[evtID].what & mask)
747 break; /* Found an event */
750 return false; /* Event was not found */
751 next = evtq[evtID].next;
752 prev = evtq[evtID].prev;
754 evtq[prev].next = next;
758 evtq[next].prev = prev;
761 *evt = evtq[evtID]; /* Return the event */
762 evtq[evtID].next = freeHead; /* and return to free list */
765 if (evt->what == EVT_MOUSEMOVE)
767 if (evt->what == EVT_KEYREPEAT)
770 return evt->what != EVT_NULLEVT;
773 /****************************************************************************
775 evt - Place to store event
776 mask - Event mask to use
779 True if an event is pending.
782 Peeks at the next pending event defined in 'mask' in the event queue. The
783 event is not removed from the event queue.
784 ****************************************************************************/
785 ibool _WDAPI WD_peekEvent(
793 moveCursor(mx,my); /* Move the mouse cursor */
794 evt->what = EVT_NULLEVT; /* Default to null event */
797 for (evtID = head; evtID != -1; evtID = evtq[evtID].next) {
798 if (evtq[evtID].what & mask)
799 break; /* Found an event */
802 return false; /* Event was not found */
804 *evt = evtq[evtID]; /* Return the event */
806 return evt->what != EVT_NULLEVT;
809 /****************************************************************************
811 hwndMain - Handle to main window
812 _xRes - X resolution of graphics mode to be used
813 _yRes - Y resolulion of graphics mode to be used
816 Handle to the fullscreen event window if (we return hwndMain on Linux)
819 Initiliase the event handling module. Here we install our mouse handling
820 ISR to be called whenever any button's are pressed or released. We also
821 build the free list of events in the event queue.
822 ****************************************************************************/
823 WD_HWND _WDAPI WD_startFullScreen(
833 /* Build free list, and initialise global data structures */
834 for (i = 0; i < EVENTQSIZE; i++)
836 evtq[EVENTQSIZE-1].next = -1; /* Terminate list */
837 count = freeHead = 0;
844 /* Open the console device and initialise it for raw mode */
845 tty_fd = PM_openConsole();
847 /* Wait until virtual terminal is active and take over control */
851 /* Initialise keyboard handling to raw mode */
852 if (ioctl(tty_fd, KDGKBMODE, &oldkbmode)) {
853 printf("WD_startFullScreen: cannot get keyboard mode.\n");
856 old_flags = fcntl(tty_fd,F_GETFL);
857 fcntl(tty_fd,F_SETFL,old_flags |= O_NONBLOCK);
858 tcgetattr(tty_fd, &conf);
860 conf.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | NOFLSH | ISIG);
861 conf.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | BRKINT | PARMRK | INPCK | IUCLC | IXON | IXOFF);
862 conf.c_iflag |= (IGNBRK | IGNPAR);
864 conf.c_cc[VTIME] = 0;
865 conf.c_cc[VSUSP] = 0;
866 tcsetattr(tty_fd, TCSAFLUSH, &conf);
867 ioctl(tty_fd, KDSKBMODE, K_MEDIUMRAW);
869 /* Clear the keyboard state information */
870 memset(key_down, 0, sizeof(key_down));
871 ioctl(tty_fd,KDSETLED,key_modifiers = 0);
873 /* Initialize the mouse connection
874 The user *MUST* run gpm with the option -R for this to work (or have a MouseSystems mouse)
876 if(Gpm_Open(&gpm,0) > 0){ /* GPM available */
877 if ((conn = open(GPM_NODE_FIFO,O_RDONLY|O_SYNC)) < 0)
878 fprintf(stderr,"WD_startFullScreen: Can't open mouse connection.\n");
880 fprintf(stderr,"Warning: when not using gpm -R, only MouseSystems mice are currently supported.\n");
881 if ((conn = open("/dev/mouse",O_RDONLY|O_SYNC)) < 0)
882 fprintf(stderr,"WD_startFullScreen: Can't open /dev/mouse.\n");
886 /* TODO: Scale the mouse coordinates to the specific resolution */
888 /* Save the state of the console */
889 if ((stateBuf = malloc(PM_getConsoleStateSize())) == NULL) {
890 printf("Out of memory!\n");
893 PM_saveConsoleState(stateBuf,tty_fd);
894 initmode = VBE_getVideoMode();
896 /* Initialize the signal handler for timer events */
897 signal(SIGALRM, timerHandler);
899 /* Capture termination signals so we can clean up properly */
900 signal(SIGTERM, exitHandler);
901 signal(SIGINT, exitHandler);
902 signal(SIGQUIT, exitHandler);
903 atexit(restore_term);
905 /* Signal that we are installed */
911 /****************************************************************************
913 Lets the library know when fullscreen graphics mode has been initialized so
914 that we can properly scale the mouse driver coordinates.
915 ****************************************************************************/
916 void _WDAPI WD_inFullScreen(void)
918 /* Nothing to do in here */
921 /****************************************************************************
923 Suspends all of our event handling operations. This is also used to
924 de-install the event handling code.
925 ****************************************************************************/
926 void _WDAPI WD_restoreGDI(void)
931 /****************************************************************************
933 ticks - Number of ticks between timer tick messages
936 Previous value for the timer tick event spacing.
939 The event module will automatically generate periodic timer tick events for
940 you, with 'ticks' between each event posting. If you set the value of
941 'ticks' to 0, the timer tick events are turned off.
942 ****************************************************************************/
943 int _WDAPI WD_setTimerTick(
947 struct itimerval tim;
948 long ms = TICKS_TO_USEC(ticks);
950 getitimer(ITIMER_REAL, &tim);
951 old = USEC_TO_TICKS(tim.it_value.tv_sec*1000000.0 + tim.it_value.tv_usec);
952 tim.it_interval.tv_sec = ms / 1000000;
953 tim.it_interval.tv_usec = ms % 1000000;
954 setitimer(ITIMER_REAL, &tim, NULL);
958 /****************************************************************************
960 saveState - Address of suspend app callback to register
963 Registers a user application supplied suspend application callback so that
964 we can properly handle virtual terminal switching.
965 ****************************************************************************/
966 void _WDAPI WD_setSuspendAppCallback(
967 int (_ASMAPI *saveState)(int flags))
969 suspendAppCallback = saveState;
972 /****************************************************************************
974 x - New X coordinate to move the mouse cursor to
975 y - New Y coordinate to move the mouse cursor to
978 Moves to mouse cursor to the specified coordinate.
979 ****************************************************************************/
980 void _WDAPI WD_setMousePos(
988 /****************************************************************************
990 x - Place to store X coordinate of mouse cursor
991 y - Place to store Y coordinate of mouse cursor
994 Reads the current mouse cursor location int *screen* coordinates.
995 ****************************************************************************/
996 void _WDAPI WD_getMousePos(
1004 /****************************************************************************
1006 mcb - Address of mouse callback function
1009 Registers an application supplied mouse callback function that is called
1010 whenever the mouse cursor moves.
1011 ****************************************************************************/
1012 void _WDAPI WD_setMouseCallback(
1013 void (_ASMAPI *mcb)(int x,int y))
1018 /****************************************************************************
1020 xRes - New X resolution of graphics mode
1021 yRes - New Y resolution of graphics mode
1024 This is called to inform the event handling code that the screen resolution
1025 has changed so that the mouse coordinates can be scaled appropriately.
1026 ****************************************************************************/
1027 void _WDAPI WD_changeResolution(
1031 // Gpm_FitValues(xRes, yRes); // ??
1034 /****************************************************************************
1036 scancode - Scan code to check if a key is down
1039 Determines if a particular key is down based on the scan code for the key.
1040 ****************************************************************************/
1041 ibool _WDAPI WD_isKeyDown(
1044 return key_down[scancode];
1047 /****************************************************************************
1049 Determines if the application needs to run in safe mode. Not necessary for
1050 anything but broken Windows 95 display drivers so we return false for
1052 ****************************************************************************/
1053 int _WDAPI WD_isSafeMode(void)