/* * PCIO.C: terminal io for IBM PC type things * C Durland Public Domain * John Burnell Added support for the grey keypad, C for some of the asm * routines. 3/92 * John Burnell Added some more support for the grey keypad. 5/92 */ /* * The functions in this file negotiate with the operating system for * characters, and write characters in a barely buffered fashion on the * display. * Notes: * If using FASTVIDEO, also link in pcfv.c or pcfv.asm. * If not using FASTVIDEO, use ansi.c or something else. */ #include #include #include #include "ed.h" #include "term.h" #include "config.h" void t_eeol(); /* may or may not be extern */ static char read_kbd = 0x00, check_kbd = 0x01; /* for DOS calls */ static int break_on; /* * This function is called to set up the terminal device streams. */ void ttopen() { union REGS in, out; /* check to see if control checking is on */ in.h.ah = 0x33; in.h.al = 0x00; int86(0x21,&in,&out); break_on = out.h.dl; bdos(0x33,0,1); /* turn off control C checking */ /* t_ncol = *(char *)0x40004AL; /* screen columns */ if (*(char *)0x400096L & 0x10) /* we have an extended keyboard */ { read_kbd = 0x10, check_kbd = 0x11; } } /* * This function gets called just before we go back home to the command * interpreter. */ void t_close() { if (break_on) bdos(0x33,1,1); /* turn on control C checking */ } /* * Write a character to the display. * Use the rawest console output routine that handles backspace, \r and \n. * On MS-DOS terminal I/O is unbuffered, so we just write the byte out. */ void t_putchar(c) unsigned char c; { bdos(6,c,0); } /* * Flush terminal buffer. Does real work where the terminal output is * buffered up. A no-operation on systems where byte at a time terminal * I/O is done. */ void t_flush() {} /* * Read a character from the terminal, performing no editing and doing no * echo at all. * Map terminal softkeys, etc to ME keys. Do *NOT* map control keys. */ KeyCode t_getchar() { KeyCode keycode; union REGS in, out; while (TRUE) { in.h.ah = read_kbd; int86(0x16,&in,&out); /* Distinguish the grey / * - + and */ if (out.h.ah >= 55 && out.h.al > 0) /* do this in 2 goes to save time */ if (out.h.ah == 55 || out.h.ah == 74 || out.h.ah == 78 || out.h.ah == 0xE0) { out.h.ah = out.h.al; out.h.al = 0xE0; } /* Check for an extended key, pass AL to distinguish grey keypad */ if (out.h.al == 0 || (out.h.al == 0xE0 && out.h.ah != 0)) { if (map_key(out.h.ah | (out.h.al << 8), &keycode)) return keycode; } else return (KeyCode)out.h.al; } /* NOTREACHED */ } #define Z 0x40 /* 8086 zero flag */ /* * Check to see is a key is waiting. * Used to interrupt processing if input is pending or to detect if a soft * key has been hit (the terminal sends multiple characters for each * softkey). * Don't use function B because it checks for ^C. */ int keywaiting() { register int flags; union REGS r; #ifdef __TSC__ /* my int86 doesn't return the flags */ r.h.ah = check_kbd; int86(0x16,&r,&r); flags = r.x.flags; #else r.h.ah = check_kbd; flags = int86(0x16,&r,&r); #endif return !(flags & Z); } static long int get_time(init) { static int day; long int time = 0; union REGS r; r.h.ah = 0x2A; int86(0x21,&r,&r); /* read day, month, year */ if (init) day = r.h.al; /* day of week */ else if (r.h.al != day) time = 86400L; /* day changed */ r.h.ah = 0x2C; int86(0x21,&r,&r); /* read hrs, mins, secs */ time += r.h.ch*3600L + r.h.cl*60 + r.h.dh; /* convert hhmmss to seconds */ return time; } /* Wait for a key to be pressed for no more than sec seconds. * Use 0 seconds to check to see if a key is in the input que. * Warning: This rouine is only good for 32K seconds (about 9 hours). * If sec is a long the limit is still 24 hours. */ wait_for_key(sec) { long int times_up; if (sec == 0) return keywaiting(); times_up = get_time(TRUE) + sec; do { if (keywaiting()) return TRUE; } while (get_time(FALSE) < times_up); return FALSE; } #if FASTVIDEO /* Also use pcfv.c or pcfv.asm */ /* Things to note about FastVideo: * putline() will do all of the writing to the text area (except for * help messages). * t_eeol() will only be called for the message line or for help * messages. * t_eeop() need only clear the message line. It should use t_eeol() to * do this. * t_putchar() will only write to the message line, help messages or * (puts "message"). * So, this means that the message line is really seprate from the text * areas and t_putchar() and t_eeol() should use the same color (others * will use tcolor and mcolor). Default for the message line would be * tcolor. Help and (puts ...) messages will be written in message * color (which is (I hope) reasonable). * PC note: Due to the way the BIOS is done, it is easier to have * t_putchar() and t_eeol() use the BIOS character attribute as the * color. */ int t_nrow = 24, t_ncol = 0; /* * Called to set up the terminal. Also called after a spawn. */ void t_open() { ttopen(); if (t_ncol == 0) fv_init(); /* only call fv_init() once */ } /* Erase to end of page or screen. * For fast video, each line of the screen (except for the message line) * will be completely filled by putline() so all this routine needs to * clear is the message (last) line of the screen. */ void t_eeop() { movecursor(t_nrow,0,TRUE); t_eeol(); } /* Ring the bell. beeper controls the volume: 0 (don't beep), n (some * volume value). */ void t_beep() { extern int beeper; if (beeper) t_putchar(BEL); } #endif /* FASTVIDEO */