Listing 8 (char.h) Common Reference for Character Device Driver

/* This is used for the escape buffer. This is how many
 * bytes of parameters the escape() routine can save in one
 * sequence. Tune it as you see fit. It needs to be at
 * least long enough to hold the two bytes of an extended
 * key (such as F1), plus the replacement string: */

#define BUF_LEN     80

/* length of the definition field; tune as you see fit.
 * How long a string do you want? */

#define KEY_BUFLEN  21

/* number of re-assignments you can define;
 * tune as you see fit. Don't use it much?
 * make it less. Redefining the entire keyboard?
 * then make it more */

#define NKEYS       20
/*
 * parameters for the ring buffer. If you want to
 * change the size, just change RLOG - the math demands
 * that the size of the buffer be a power of 2. Makes
 * things nice and efficient that way.
 */

#define RLOG    6
#define RLEN    (2 << (RLOG - 1))
#define RLIMIT  (RLEN - 1)

/*
 * macros for reading the system RAM where these neat
 * things are stored
 */

#define CURRENT_MODE   (*(char far *)0x0449)
#define SCREEN_WIDTH   (*(char far *)0x044A)
#define SCREEN_OFFSET  (*(unsigned far *)0x044E)
#define PAGE_TABLE ((POSITION far *)0x0450)
#define CURRENT_PAGE   (*(char far *)0x0462)

/*
 * base addresses for the video memory for the
 * monochrome adaptor (MONOCHROME) and the CGA (GRAPHIC)
 */

#define MONOCHROME  ((char far *)  0x000B0000)
#define GRAPHIC     ((char far *)  0x000B8000)

/*
 * status bits for the return code
 */
 
#define UNKNOWN_COMMAND 03
#define ERROR       0x8000
#define DONE        0x0100
#define BUSY        0x0200

/*
 * the states of the escape sequence:
 *
 * RAW:  no escape sequence begun yet, or previous
 *       sequence has been terminated
 *
 * HAVE_ESC:  an escape has been received; now awaiting
 *            the left bracket
 *
 * HAVE_LBRACE:  an escape followed by a left bracket
 *               have been received; now waiting for a
 *               parameter or terminating character
 *
 * IN_STRING:  a parameter beginning with a delimiter has
 *             been started; until the same delimiter is
 *             received, characters will be placed in the
 *             escape buffer as is
 *
 * IN_NUMBER:  a numeric parameter has been started; each
 *             subsequent digit is 'added' to the number
 *             in the escape buffer
 */

#define RAW    0
#define HAVE_ESC     1
#define HAVE_LBRACE  2
#define IN_STRING    3
#define IN_NUMBER    4

/* typedef for cursor positioning; this union reflects the way
 * that they are stored internally. At the assembly language
 * level, 16-bit registers can be loaded directly with the
 * 16-bit position so that the high and low halves are
 * correctly loaded for BIOS calls
 */

typedef union
    {
    short  position;
    struct
        {
        char  col;
        char  line;
        } loc;
    } POSITION;
/*
 * typedef for the reassignment buffer. keystroke is the key
 * being replaced; length is the number of bytes that the
 * keystroke 'generates'; buffer holds the data that replaces
 * the keystroke.
 */

typedef struct
    {
    int keystroke;
    char  length;
    char  buffer [ KEY_BUFLEN ];
    } KEY;


/*----------- global variables -----------*/

                 /* the current character being output */
extern char outchar;
                 /* the current video mode */
extern char video_mode;
                 /* the current screen attribute */
extern char attrib;
                 /* a count of how many parameter bytes
                  * have been read into the escape buffer
                  */
extern char char_cnt;
                 /* the code being checked for in
                  * reassignment routines; if null, it is
                  * used to find an ununsed buffer; if
                  * the value is non zero and positive,
                  * it is used to look up a regular key;
                  * if non-zero and negative, it is used
                  * to look up an extended key */
extern int keycheck;
                 /* the parameter buffer for ansi escape
                  * sequences */
extern char esc_buf [ BUF_LEN ];
                 /* the current position */
extern POSITION curr;
                 /* the maximum position. Actually, the
                  * maximum line number is not used as
                  * a maximum, but is used simply to
                  * tell the clear-screen and
                  * clear-to-end-of-line code how much screen to
                  * clear */
extern POSITION max;
                 /* the current video page number */
extern char cur_page;
                 /* the current video address. this is
                  * the base address plus the offset to
                  * the current page */
extern char far *video_address;
                 /* the transfer address specified in the
                  * request header */
extern char far *transfer;
                 /* the count specified in the request
                  * header */
extern int count;

/*
 * pointer to the request headerd
 */

extern struct
    {
    char      rlength;
    char      units;
    char      command;
    unsigned  status;
    char      reserved [ 8 ];
    char      data;
    char far  *transfer;
    unsigned  count;
    } far   *rh;
extern int k;          /* generic int */

                   /* pointer to the length field
                    * for the selected buffer */
extern char *len;
                   /* pointer to the definition
                    * field for the selected buffer */
extern char *ptr;

extern KEY kbuffer[NKEYS];  /* the buffers */
extern KEY *kp;         /* pointer to a buffer */

                    /* r_buf[ r_index ] is the
                     * next byte to be read  */
extern unsigned r_index;
                    /* r_buf[ w_index ] is where
                     * the next-byte can be written */
extern unsigned w_index;

extern char r_buf [ RLEN ];     /* ring buffer */

/*
 * a temporary variable for storing either the delimiter while
 * the escape sequence is in the IN_STRING state, or the value
 * being computed if the escape sequence is in the IN_NUMBER
 * state. a convenient way of doubling the utility of a byte
 * of storage while keeping track of just what we're doing
 * with it.
 */

extern union
    {
    char  delim;
    char  value;
    }     tmp;
extern char    state;      /* the escape sequence state */
extern POSITION    saved;  /* the saved cursor position */
extern char  wrap;         /* wrap flag: wrap on if set */
extern char  *cur_val;     /* line or column parameter being
                         manipulated by w_cursor() */
extern char  delta;        /* incr/decr to cur_val */
extern char  limit;        /* limit of *cur_val */