home *** CD-ROM | disk | FTP | other *** search
- /**
- * CMKEY.C Example of a keyboard macro processor.
- *
- * CMKEY is a terminate and stay resident program that recognizes
- * certain "hot keys," and stuffs expansion strings into the
- * keyboard buffer when these hot keys are pressed. It stuffs
- * the string into the keyboard buffer, then gives control back
- * to the foreground process. All of the interrupt support for
- * running the keyboard enhancer is provided by Turbo C TOOLS
- * intervention code (IV) routines.
- *
- * CMKEY requests that the scheduler give it control every timer
- * tick, so that if it can only stuff a portion of the
- * specified string, it can stuff more of it on the next timer
- * tick, until the whole string has been stuffed.
- *
- * If CMKEY receives a hot key when another hot key is being
- * processed, the second hot key is ignored.
- *
- * CMKEY retrieves the hot key pressed from the IV_EVENT structure
- * passed to it by the intervention code scheduler.
- *
- * The command line format is as follows:
- *
- * cmkey [-r]
- *
- * CMKEY is a self-removing interrupt service routine. If CMKEY is
- * invoked with no arguments, it installs itself (if not already
- * installed); if it is invoked with the "-r" argument, it
- * removes a running copy of CMKEY (if present).
- *
- * The purpose of CMKEY is to exhibit the intervention capabilities
- * of Turbo C TOOLS, and to provide an example of construction and
- * use of intervention code in a moderately complex program.
- *
- * Version 6.00 (C)Copyright Blaise Computing Inc. 1987-1989
- *
- **/
-
-
- #include <dos.h>
- #include <stdio.h>
-
- #include <binterv.h>
- #include <bintrupt.h>
- #include <bkeybrd.h>
- #include <bkeys.h>
-
- /* The declaration of the intervention function. */
- /* It will be called on every timer tick, and also */
- /* when a hot key is pressed. */
- void tickhandler (IV_EVENT *);
-
- #define TRUE 1
- #define FALSE 0
- #define NUL '\0'
-
- #define STKSIZE 2000
- #define OK 0
- #define FALL_OUT 101
-
- #define NOT_FOUND 1
- #define ERROR_DISABLING 2
- #define ERROR_REMOVING 3
- #define ALREADY_INSTALLED 4
-
- /* Definitive signature for this version of CMKEY. */
- #define CMKEY_SIGN "CMKEY 03/31/89"
-
- /* Allocation of stack space for the intervention */
- /* scheduler and user function. */
- char schedstk [STKSIZE];
-
- /* This is the data structure to pass to the */
- /* scheduler so that it will give control every */
- /* clock tick. */
- IV_TIME timetab = {1, IV_TM_INTERVAL};
-
- /* This is the data structure to pass to the */
- /* scheduler so that it will give control every */
- /* time ALT 1, 2, or 3 is pressed, and will put the */
- /* intervention code to sleep when ALT-minus is */
- /* detected, and will wake it up again when ALT- */
- /* equals is selected. */
- IV_KEY keytab [] =
- {
- {KB_C_A_1, KB_S_A_1, IV_KY_SERVICE},
- {KB_C_A_2, KB_S_A_2, IV_KY_SERVICE},
- {KB_C_A_3, KB_S_A_3, IV_KY_SERVICE},
- {KB_C_A_MINUS, KB_S_A_MINUS, IV_KY_SLEEP },
- {KB_C_A_EQUALS, KB_S_A_EQUALS, IV_KY_WAKE }
- };
-
- #define k(c) kbscanof(c)
- static char *string_table [] =
- {
- "cls\r",
- "dir /w /p *.c\rdir /w /p *.asm\r",
- "<this is a test of the emergency broadcast system>"
- };
-
- static char *pstuff = NIL;
- static int awake = TRUE;
-
-
- /* Internal functions -- install and remove */
- /* intervention function. */
- int install_iv (void);
- int remove_iv (void);
-
- void main(int, char **);
-
-
- void main (argc, argv)
- int argc;
- char *argv [];
- {
- if (argc == 1)
- exit (install_iv ());
-
- if ((argc == 2) &&
- (((argv [1][0] == '-') || (argv [1][0] == '/')) &&
- ((argv [1][1] == 'r') || (argv [1][1] == 'R'))))
- exit (remove_iv ());
-
- printf ("usage: cmkey [-r]\n");
- exit (0);
- }
-
-
-
- /**
- *
- * Name INSTALL_IV -- Install interrupt vectors for CMKEY, then
- * terminate and stay resident.
- *
- * Synopsis ret = install_iv ();
- *
- * int ret Return code from IVINSTAL if an
- * error condition was encountered.
- *
- * Description This function installs CMKEY if another copy of
- * CMKEY is not already installed.
- *
- * Returns ret ALREADY_INSTALLED (4)
- * A copy of CMKEY is already installed.
- * FALL_OUT (101)
- * ISRESEXT() failed.
- * IV_INSTALLED (5)
- * A copy of CMKEY is already installed.
- *
- **/
-
- int install_iv ()
- {
- int ercode;
- IV_VECTORS vecs;
-
- /* Check to see if CMKEY already installed. */
- ivvecs (IV_RETVEC, &vecs);
- if (ivsense (&vecs, CMKEY_SIGN) != FARNIL)
- {
- puts ("CMKEY already installed.");
- return (ALREADY_INSTALLED);
- }
-
- /* Install the interrupt service routine--i.e. tell */
- /* the scheduler about our tick and keypress */
- /* handler routine. */
- if (0 !=
- (ercode =
- ivinstal (tickhandler, CMKEY_SIGN, schedstk, STKSIZE,
- keytab,
- sizeof(keytab) / sizeof(IV_KEY),
- &timetab,
- sizeof(timetab) / sizeof(IV_TIME),
- /* Neither DOS services nor DOS "key" services nor */
- /* TURBO C floating point support is needed. */
- IV_NO_DOS_NEED | IV_NO_DKEY_NEED | IV_NO_FLOAT_NEED)))
- { /* Error! */
- printf ("IVINSTAL error %d.\n", ercode);
- return (ercode);
- }
-
- /* Terminate and stay resident. */
- isresext (OK);
-
- /* Should never get here. */
- return (FALL_OUT);
- }
-
-
-
- /**
- *
- * Name REMOVE_IV -- Remove a previously installed copy of CMKEY.
- *
- * Synopsis ret = remove_iv ();
- *
- * int ret Return code.
- * NO_ERROR (0)-
- * No error encountered.
- * NOT_FOUND (1)-
- * CMKEY not found.
- * ERROR_DISABLING (2)-
- * CMKEY could not be disabled.
- * This error should *never* be
- * seen.
- * ERROR_REMOVING (3)--
- * CMKEY could not be removed (most
- * likely overwritten MALLOC
- * pointers).
- *
- * Description This function removes a currently-active copy of CMKEY
- * from memory, restoring interrupt vectors and freeing
- * memory in the process.
- *
- * Returns ret (nonzero if error--see above).
- *
- **/
-
- int remove_iv ()
- {
- IV_VECTORS vecs;
- IV_CTRL far *pivctrl;
-
- /* Check to see if CMKEY installed. */
- ivvecs (IV_RETVEC, &vecs);
- if ((pivctrl = ivsense (&vecs, CMKEY_SIGN)) == FARNIL)
- {
- puts ("CMKEY not found.");
- return (NOT_FOUND);
- }
-
- if (ivdisabl (pivctrl))
- {
- puts ("Error disabling CMKEY.");
- return (ERROR_DISABLING);
- }
-
- if (isremove (pivctrl->psp))
- {
- puts ("Error removing CMKEY.");
- return (ERROR_REMOVING);
- }
-
- return (0);
- }
-
-
-
- /**
- *
- * Name TICKHANDLER -- Handle clock tick and hot key
- * events.
- *
- * Synopsis (To be called only by intervention code scheduler)
- *
- * tickhandler (pevent);
- *
- * IV_EVENT *pevent Pointer to intervention event
- * structure. The structure
- * contains the hot key which
- * was detected (if any), as
- * well as other data.
- *
- * Description This function accepts control from the scheduler
- * every timer tick, and also every time one of the
- * defined hot keys is pressed. The two cases are
- * dissimilar:
- * 1. Hot key: Ignore it if we are already
- * processing another hot key. If not, CMKEY
- * stuffs as much of the hot key expansion
- * as it can into the keyboard buffer, then
- * leaves a pointer to the remainder for the
- * timer tick invocation to clean up.
- * 2. Timer tick: CMKEY tries to stuff any
- * remaining hot key expansions into the
- * keyboard buffer. If it cannot stuff the
- * complete string, it schedules the rest for
- * the next timer tick.
- *
- * Returns None.
- *
- **/
-
- void tickhandler (pevent)
- IV_EVENT *pevent;
- {
- /* Do a key action, if one exists. */
- switch (pevent->key.action)
- {
- /* If there is no key action, ignore the hot key */
- /* part of the handler. */
- case IV_KY_NONE:
- break;
-
- /* If the user typed a "service" key, start stuffing*/
- /* the appropriate string. */
- case IV_KY_SERVICE:
- /* If we are already stuffing a string, discard this*/
- /* hot key. If we are asleep, ignore it. */
- if ((pstuff == NIL) && awake)
- switch (pevent->key.keycode)
- {
- case KB_S_A_1:
- pstuff = string_table [0];
- break;
-
- case KB_S_A_2:
- pstuff = string_table [1];
- break;
-
- case KB_S_A_3:
- pstuff = string_table [2];
- break;
- }
- break;
-
- /* If we get a message to go to sleep, do it. */
- case IV_KY_SLEEP:
- awake = FALSE;
- utsound (800, 1);
- break;
-
- /* If we get a message to wake up, do it. */
- case IV_KY_WAKE:
- awake = TRUE;
- utsound (1600, 1);
- break;
- }
-
- /* No we do the actual stuffing of the string, if */
- /* any. */
- if (pstuff != NIL)
- {
- /* Use KBPLACE to stuff them in, character by */
- /* character, until full. */
- for (;
- (*pstuff != NUL) &&
- (kbplace (KB_TAIL, (int) *pstuff, kbscanof (*pstuff)) == 0);
- pstuff++)
- ;
-
- /* If we have come to the end of the string, we */
- /* must set pstuff to NIL so that we know we can */
- /* accept another hot key now. */
- if (*pstuff == NUL)
- pstuff = NIL;
- }
- }