Listing 1

#include <dos.h>
#include <conio.h>

void show_char();
int  poll_kb();
int  readch();
int  push_kb();
int  kb_count();
int  kb_peek();
void kb_clear();

void main(void)        /*  testing the KB functions */
   {
   int x, y;
      
      /*  Put some characters into the buffer */
      /*  For most applications the scan codes are not */
      /*  important, but for extended char it must have */
      /*  the scan code and 0 for the char: */
   for (x : 0; x < 12; x++)
      push_kb(1,32 + x);
   push_kb(59,0);
   
   printf("\n%d key(s) in the buffer. \n\n",kb_count());
   printf("Key number %d is '%c' \n\n", 5, kb peek(5));
   printf("Key number %d is '%c' \n\n", 7, kb_peek(7));
   
   show_char();
   }

void show_char(void)     /*  This is just a test function */
   {
   int c;
   while((c = readch()) != 59 << 8)         /*  27 = ESC */
      {
      putch(c);
      printf(" the code for this is %d \n",c);
      }
   putch(c);
   printf(" the code for this is %d \n",c);
   }

/*  poll_kb(): returns 0 if the buffer is empty, */
/*  else ascii code or scan codes * 256 for extended: */

int poll_kb(void)
   {
   int head, tail;
   unsigned int code;
   
   head = peek(0x40, 0x1A);
   tail = peek(0x40, 0x1C);
   
   if(head == tail)
      return(0);
   
   code = (peek(0x40,head) & 0xFF);
   if(code == 0)                       /*  extended char */
      code = (peek(0x40,head) & 0xFF00);
   
   if(head < 60)
      poke(0x40,0x1A,(head += 2));
   else
      poke(0x40,0x1A,(head = 30));
   
   return(code);
   }

/*  readch(): keep checking buffer until something  */
/*       is there. Can also be done with "kbhit()"  */

int readch(void)
   {
   int code;
   while((code = poll_kb()) == 0)
      {       /*  can run any fast function here */
      }
   return(code);
   }

/*  putsh_kb(): key = the key code, ascii = asc code */
int push_kb(int key, int ascii)
   {
   unsigned int code;
   int head, tail;
   
   head = peek(0x40, 0x1A);
   tail = peek(0x40, 0x1C);
   
   code = (key << 8) + ascii;
   poke(0x40,tail,code);
   
   if(tail < 60)
      {
      tail += 2;
      if(tail == head)
         return(0);
      poke(0x40,0x1C,tail);
      }
   else
      {
      tail = 30;
      if(tail == head)
         return(0);
      poke(0x40,0x1C,tail);
      }
   return(1);
   }

int kb_count(void)
   {
   int head, tail;
   int count;
   
   head = peek(0x40, 0x1A);
   tail = peek(0x40, 0x1C);
   
   if(head == tail)    /*  buffer is empty */
      return(0);
   
   if(head > tail)     /*  adjust for the roll over */
      tail += 32;
   count = (tail - head) / 2;
   
   return(count);
   }
/*  "kb_peek" will return the ascii code of  */
/*  the number of keys back specified.       */
/*  If it is an extended char the scan code  */
/*  will be left shifted 8 and returned      */

int kb_peek(int key_number)
   {
   int head, tail, code;

/*  see if key_number of items are in the buffer: */
   
   if(key_number > kb_count())
      return(0);
   
   head = peek(0x40, 0x1A);
   tail = peek(0x40, 0x1C);
   
   /*  advance the desired number of words: */
   head += (key_number - 1) * 2;
   if(head > 60)
      head -= 32;      /*  if head needs to wrap around */
   
   code = (peek(0x40,head) & 0xFF);
   
   if(code == 0)   /*  exten. scan sent instead of ascii */
      code = (peek(0x40,head) & 0xFF00);
   
   return(code);
   }

void kb_clear(void)  /*  empty buffer data */
   {
   int head, tail;
   
   head = peek(0x40, 0x1A);
   tail = peek(0x40, 0x1C);
   
   poke(0x40,0x1C,head);  /*  set tail = head */
   }