home *** CD-ROM | disk | FTP | other *** search
- /*
- * All video and keyboard functions were gathered into one file.
- *
- * In version 3.2, this file was split into 3 sections: 1) unix curses
- * made to look and feel like a PC, 2) our PC hardware specific stuff,
- * and 3) hardware independent stuff.
- *
- * This file contains the keyboard and video i/o stuff. Most of this stuff
- * is specific to the PC hardware, but it should be easily modified when
- * porting to other platforms. With a few key functions written in
- * assembly, we have fairly fast video performance and good keyboard control.
- * Incidentally, the commented C code in the functions perform the same
- * function as the assembly code. In earlier versions of TDE, I didn't
- * update the commented C code when I changed the assembly code. The
- * C and assembly should be equivalent in version 2.2.
- *
- * Although using a curses type package would be more portable, curses
- * can be slow on PCs. Let's keep our video and keyboard routines in
- * assembly. I feel the need for speed.
- *
- * Being that TDE 2.2 keeps an accurate count of characters in each line, we
- * can allow the user to enter any ASCII or Extended ASCII key.
- *
- * Determining the video adapter type on the PC requires a function. In
- * TDE, that function is:
- *
- * void video_config( struct vcfg *cfg )
- *
- * video_config( ) is based on Appendix C in _Programmer's Guide to
- * PC & PS/2 Video Systems_ by Richard Wilton.
- *
- * See:
- *
- * Richard Wilton, _Programmer's Guide to PC & PS/2 Video Systems_,
- * Microsoft Press, Redmond, Washington, 1987, Appendix C, pp 511-521.
- * ISBN 1-55615-103-9.
- *
- *
- * New editor name: TDE, the Thomson-Davis Editor.
- * Author: Frank Davis
- * Date: June 5, 1991, version 1.0
- * Date: July 29, 1991, version 1.1
- * Date: October 5, 1991, version 1.2
- * Date: January 20, 1992, version 1.3
- * Date: February 17, 1992, version 1.4
- * Date: April 1, 1992, version 1.5
- * Date: June 5, 1992, version 2.0
- * Date: October 31, 1992, version 2.1
- * Date: April 1, 1993, version 2.2
- * Date: June 5, 1993, version 3.0
- * Date: August 29, 1993 version 3.1
- * Date: November 13, version 3.2
- *
- * This code is released into the public domain, Frank Davis.
- * You may distribute it freely.
- */
-
-
- #include "tdestr.h"
- #include "common.h"
- #include "define.h"
- #include "tdefunc.h"
-
- #if defined( __UNIX__ )
- /*
- **********************************************************************
- ****************************** PART 1 ******************************
- **********************************************************************
- *
- * Let's try to make unix have the look and feel of a PC.
- */
-
-
- /*
- * Name: video_config
- * Purpose: simulate a call the BIOS keyboard status subfunction
- * Date: November 13, 1993
- * Passed: cfg: not used
- * Notes: curses has three (?) cursor shapes: invisible, normal, large.
- */
- void video_config( struct vcfg *cfg )
- {
- /*
- g_display.insert_cursor =
- mode.cursor_size == SMALL_INS ? CURSES_SMALL : CURSES_LARGE;
- g_display.overw_cursor =
- mode.cursor_size == SMALL_INS ? CURSES_LARGE : CURSES_SMALL;
- */
-
- g_display.insert_cursor = g_display.overw_cursor = CURSES_SMALL;
- if (mode.insert)
- g_display.curses_cursor = g_display.insert_cursor;
- else
- g_display.curses_cursor = g_display.overw_cursor;
- }
-
-
- /*
- * Name: getkey
- * Purpose: use unix curses to get keyboard input
- * Date: November 13, 1993
- * Passed: None
- * Notes: the getch( ) function is not part of the ANSI C standard.
- * most (if not all) PC C compilers include getch( ) with the
- * conio stuff. in unix, getch( ) is in the curses package.
- * in TDE, lets try to map the curses function keys to their
- * "natural" positions on PC hardware. most of the key mapping
- * is at the bottom of default.h.
- * this function is based on the ncurses package in Linux. It
- * probably needs to be modified for curses in other unices.
- */
- int getkey( void )
- {
- unsigned key;
-
- key = getch( );
-
- /*
- * map the Control keys to their natural place in TDE.
- */
- if (key < 32)
- key += 430;
- else if (key > 255) {
-
- /*
- * map ncurses keys to their natural place in TDE.
- * ncurses defines function keys in the range 256-408.
- */
- if (key > 408)
- key = 256;
- key = curses_to_tde[key - 256];
- }
- return( key );
- }
-
-
- /*
- * Name: waitkey
- * Purpose: nothing right now
- * Date: November 13, 1993
- * Passed: enh_keyboard: boolean - TRUE if 101 keyboard, FALSE otherwise
- * Returns: 1 if no key ready, 0 if key is waiting
- * Notes: we might do something with this function later...
- */
- int waitkey( int enh_keyboard )
- {
- return( 0 );
- }
-
-
- /*
- * Name: flush_keyboard
- * Purpose: flush keys from the keyboard buffer. flushinp is a curses func.
- * Date: November 13, 1993
- * Passed: none
- */
- void flush_keyboard( void )
- {
- flushinp( );
- }
-
-
- /*
- * Name: xygoto
- * Purpose: To move the cursor to the required column and line.
- * Date: November 13, 1993
- * Passed: col: desired column (0 up to max)
- * line: desired line (0 up to max)
- * Notes; on the PC, we use col = -1 and line = -1 to turn the cursor off.
- * in unix, we try to trap the -1's.
- * curs_set is a curses function.
- */
- void xygoto( int col, int line )
- {
- if (col < 0 || line < 0) {
- curs_set( CURSES_INVISBL );
- g_display.curses_cursor = CURSES_INVISBL;
- } else {
-
- /*
- * if the unix cursor is invisible, lets turn it back on.
- */
- if (g_display.curses_cursor == CURSES_INVISBL) {
- /*
- if (mode.insert == TRUE) {
- if (g_display.insert_cursor == SMALL_INS)
- set_cursor_size( CURSES_SMALL );
- else
- set_cursor_size( CURSES_LARGE );
- } else {
- if (g_display.insert_cursor == SMALL_INS)
- set_cursor_size( CURSES_LARGE );
- else
- set_cursor_size( CURSES_SMALL );
- }
- */
- set_cursor_size( CURSES_SMALL );
- g_display.curses_cursor = CURSES_SMALL;
- }
- move( line, col );
- }
- }
-
-
- /*
- * Name: update_line
- * Purpose: Display the current line in window
- * Date: November 13, 1993
- * Passed: window: pointer to current window
- * Notes: use the curses mvaddch( ) function to put char + attribute
- * on the screen.
- * let's check for control characters before they get to curses.
- * unix and/or curses is brain-damaged when it comes to
- * control characters and extended ASCII characters.
- */
- void update_line( TDE_WIN *window )
- {
- text_ptr text; /* current character of orig begin considered */
- int attr; /* index into TDE's chtype table */
- int line;
- int col;
- int bcol;
- int bc;
- int ec;
- int normal;
- int block;
- int max_col;
- int block_line;
- int len;
- int show_eol;
- unsigned int c;
- long rline;
- file_infos *file;
- chtype curses_attribute; /* chtype is defined in curses.h */
-
- /*
- * we don't use this function the display the EOF message.
- * return if this display is turned off.
- */
- if (window->rline > window->file_info->length || window->ll->len == EOF
- || !g_status.screen_display)
- return;
-
- file = window->file_info;
- max_col = window->end_col + 1 - window->start_col;
- line = window->cline;
- normal = window->ll->dirty == FALSE ? g_display.text_color : g_display.dirty_color;
- block = g_display.block_color;
- show_eol = mode.show_eol;
-
- /*
- * figure which line to display.
- * actually, we could be displaying any line in any file. we display
- * the line_buffer only if window->ll == g_status.buff_node
- * and window->ll-line has been copied to g_status.line_buff.
- */
- text = window->ll->line;
- len = window->ll->len;
- if (g_status.copied && ptoul( window->ll ) == ptoul( g_status.buff_node )) {
- text = (text_ptr)g_status.line_buff;
- len = g_status.line_buff_len;
- }
- if (mode.inflate_tabs)
- text = tabout( text, &len );
-
- /*
- * lets look at the base column. if the line to display is shorter
- * than the base column, then set text to eol and we can't see the
- * eol either.
- */
- bc = window->bcol;
- if (bc > 0) {
- if (text == NULL) {
- show_eol = FALSE;
- len = 0;
- } else {
- if ((col = len) < bc) {
- bc = col;
- show_eol = FALSE;
- }
- text += bc;
- len -= bc;
- }
- }
-
- /*
- * for display purposes, set the line length to screen width if line
- * is longer than screen. our assembly routine uses bytes and the
- * the line length can be longer than a byte.
- */
- if (len > max_col)
- len = max_col;
-
- bcol = window->bcol;
- rline = window->rline;
- if (file->block_type && rline >= file->block_br && rline <= file->block_er)
- block_line = TRUE;
- else
- block_line = FALSE;
-
- /*
- * do this if 1) a box block is marked, or 2) a stream block begins
- * and ends on the same line.
- */
- if (block_line == TRUE && (file->block_type == BOX ||
- (file->block_type == STREAM &&
- rline == file->block_br && rline == file->block_er))) {
-
- /*
- * start with the bc and ec equal to physical block marker.
- */
- bc = file->block_bc;
- ec = file->block_ec;
- if (ec < bcol || bc >= bcol + max_col)
- /*
- * we can't see block if ending column is less than the base col or
- * the beginning column is greater than max_col.
- */
- ec = bc = max_col + 1;
- else if (ec < bcol + max_col) {
- /*
- * if the ec is less than the max column, make ec relative to
- * base column then figure the bc.
- */
- ec = ec - bcol;
- if (bc < bcol)
- bc = 0;
- else
- bc = bc - bcol;
- } else if (bc < bcol + max_col) {
- /*
- * if the bc is less than the max column, make bc relative to
- * base column then figure the ec.
- */
- bc = bc - bcol;
- if (ec > bcol + max_col)
- ec = max_col;
- else
- ec = ec - bcol;
- } else if (bc < bcol && ec >= bcol + max_col) {
- /*
- * if the block is wider than the screen, make bc start at the
- * logical begin and make ec end at the logical end of the
- * window.
- */
- bc = 0;
- ec = max_col;
- }
- bcol = window->start_col;
- for (col=0; col < max_col; col++, bcol++) {
- attr = normal;
- if (col >= bc && col <= ec)
- attr = block;
- if (col < len)
- c = *text++;
- else if (col == len && show_eol)
- c = EOL_CHAR;
- else
- c = ' ';
- if (c < 32)
- mvaddch( line, bcol, (c+64) | tde_color_table[g_display.curl_color] );
- else if (c >= 127)
- mvaddch( line, bcol, '.' | tde_color_table[g_display.curl_color] );
- else
- mvaddch( line, bcol, c | tde_color_table[attr] );
- }
- } else if (block_line == TRUE && file->block_type == STREAM &&
- (rline == file->block_br || rline == file->block_er)) {
- if (rline == file->block_br)
- bc = file->block_bc;
- else {
- bc = file->block_ec + 1;
- ec = normal;
- normal = block;
- block = ec;
- }
-
- ec = max_col + 1;
- if (bc < bcol)
- bc = 0;
- else if (bc < bcol + max_col)
- bc = bc - bcol;
- else
- bc = max_col + 1;
- bcol = window->start_col;
-
- for (col=0; col < max_col; col++, bcol++) {
- attr = normal;
- if (col >= bc && col <= ec)
- attr = block;
- if (col < len)
- c = *text++;
- else if (col == len && show_eol)
- c = EOL_CHAR;
- else
- c = ' ';
- if (c < 32)
- mvaddch( line, bcol, (c+64) | tde_color_table[g_display.curl_color] );
- else if (c >= 127)
- mvaddch( line, bcol, '.' | tde_color_table[g_display.curl_color] );
- else
- mvaddch( line, bcol, c | tde_color_table[attr] );
- }
- } else {
- if (block_line)
- attr = block;
- else
- attr = normal;
-
- assert( len >= 0 );
- assert( len <= g_display.ncols );
-
- curses_attribute = tde_color_table[attr];
- bcol = window->start_col;
- for (col=0; col < max_col; col++, bcol++) {
- if (col < len)
- c = *text++;
- else if (col == len && show_eol)
- c = EOL_CHAR;
- else
- c = ' ';
- if (c < 32)
- mvaddch( line, bcol, (c+64) | tde_color_table[g_display.curl_color] );
- else if (c >= 127)
- mvaddch( line, bcol, '.' | tde_color_table[g_display.curl_color] );
- else
- mvaddch( line, bcol, c | curses_attribute );
- }
- }
- }
-
-
- /*
- * Name: c_output
- * Purpose: Output one character on prompt lines
- * Date: November 13, 1993
- * Passed: c: character to output to screen
- * col: col to display character
- * line: line number to display character
- * attr: attribute of character
- * Returns: none
- */
- void c_output( int c, int col, int line, int attr )
- {
- register unsigned int uc;
-
- uc = c;
-
- if (uc < 32)
- mvaddch( line, col, (uc+64) | tde_color_table[g_display.curl_color] );
- else if (uc >= 127)
- mvaddch( line, col, '.' | tde_color_table[g_display.curl_color] );
- else
- mvaddch( line, col, uc | tde_color_table[attr] );
- }
-
-
- /*
- * Name: s_output
- * Purpose: To output a string
- * Date: November 13, 1993
- * Passed: s: string to output
- * line: line to display
- * col: column to begin display
- * attr: color to display string
- * Notes: This function is used to output most strings not part of file text.
- */
- void s_output( char *s, int line, int col, int attr )
- {
- int max;
- register unsigned int uc;
-
- max = g_display.ncols;
- if (line == g_display.mode_line && (strlen( s ) + col >= g_display.ncols))
- max--;
-
- while ((uc = (unsigned int)*s) && col < max) {
- if (uc < 32)
- mvaddch( line, col, (uc + 64) | tde_color_table[g_display.curl_color] );
- else if (uc >= 127)
- mvaddch( line, col, '.' | tde_color_table[g_display.curl_color] );
- else
- mvaddch( line, col, uc | tde_color_table[attr] );
- col++;
- s++;
- }
- }
-
-
- /*
- * Name: eol_clear
- * Purpose: To clear the line from col to max columns
- * Date: November 13, 1993
- * Passed: col: column to begin clear
- * line: line to clear
- * attr: color to clear
- * Notes: use unix curses clrtoeol( ) to clear the line.
- */
- void eol_clear( int col, int line, int attr )
- {
- move( line, col );
- clrtoeol( );
- }
-
-
- /*
- * Name: window_eol_clear
- * Purpose: To clear the line from start_col to end_col
- * Date: November 13, 1993
- * Passed: window: pointer to window
- * attr: color to clear
- * Notes: don't use unix curses clrtoeol, because we could be in a
- * vertical window. lines don't always extend to end of screen
- * in a vertical window.
- */
- void window_eol_clear( TDE_WIN *window, int attr )
- {
- int max_col;
- chtype c; /* chtype is defined in curses.h */
-
- if (!g_status.screen_display)
- return;
-
- assert( attr >= 0 && attr < 128 );
-
- c = ' ' | tde_color_table[attr];
- max_col = window->start_col;
- while (max_col <= window->end_col)
- mvaddch( window->cline, max_col++, c );
- }
-
-
- /*
- * Name: hlight_line
- * Date: November 13, 1993
- * Passed: x: column to begin hi lite
- * y: line to begin hi lite
- * lgth: number of characters to hi lite
- * attr: attribute color
- */
- void hlight_line( int x, int y, int lgth, int attr )
- {
- int max;
-
- max = g_display.ncols;
- if (y == g_display.mode_line)
- max--;
-
- for (; lgth > 0 && x < max; x++, lgth--) {
- move( y, x );
- addch( (inch( ) & A_CHARTEXT) | tde_color_table[attr] );
- }
- }
-
-
- /*
- * Name: cls
- * Purpose: clear screen
- * Date: November 13, 1993
- * Notes: Call the curses clear screen function.
- */
- void cls( void )
- {
- clear( );
- refresh( );
- }
-
-
- /*
- * Name: set_cursor_size
- * Purpose: To set cursor size according to insert mode.
- * Date: November 13, 1993
- * Passed: csize: not used in unix curses
- * Notes: use the global display structures to set the cursor size
- * curs_set( ) is a curses function.
- */
- void set_cursor_size( int csize )
- {
- /*
- if (mode.insert == TRUE) {
- if (g_display.insert_cursor == SMALL_INS)
- curs_set( CURSES_SMALL );
- else
- curs_set( CURSES_LARGE );
- } else {
- if (g_display.insert_cursor == SMALL_INS)
- curs_set( CURSES_LARGE );
- else
- curs_set( CURSES_SMALL );
- }
- */
- curs_set( CURSES_SMALL );
- g_display.curses_cursor = CURSES_SMALL;
- }
-
-
- /*
- * Name: set_overscan_color
- * Purpose: To set overscan color
- * Date: November 13, 1993
- * Passed: color: overscan color
- * Notes: i'm not sure how to set the overscan in Linux (yet?).
- */
- void set_overscan_color( int color )
- {
- }
-
-
- /*
- * Name: save_screen_line
- * Purpose: To save the characters and attributes of a line on screen.
- * Date: November 13, 1993
- * Passed: col: desired column, usually always zero
- * line: line on screen to save (0 up to max)
- * screen_buffer: buffer for screen contents, must be >= 80 chtype
- * Notes: Save the contents of the line on screen where prompt is
- * to be displayed.
- */
- void save_screen_line( int col, int line, chtype *screen_buffer )
- {
- int i;
-
- for (i=0; col < g_display.ncols; col++, i++)
- screen_buffer[i] = mvinch( line, col );
- }
-
-
- /*
- * Name: restore_screen_line
- * Purpose: To restore the characters and attributes of a line on screen.
- * Date: November 13, 1993
- * Passed: col: usually always zero
- * line: line to restore (0 up to max)
- * screen_buffer: buffer for screen contents, must be >= 80 chtype
- * Notes: Restore the contents of the line on screen where the prompt
- * was displayed
- */
- void restore_screen_line( int col, int line, chtype *screen_buffer )
- {
- int i;
-
- for (i=0; col < g_display.ncols; col++, i++)
- mvaddch( line, col, screen_buffer[i] );
- }
-
-
-
- /*
- * Name: save_minor_area
- * Purpose: save text and attribute under the pulled menu
- * Date: November 13, 1993
- * Passed: buffer: storage for text and attribute
- * wid: width of the pulled menu
- * len: length of pulled menu
- * row: starting row of pulled menu
- * col: starting column of pulled menu
- * Notes: use curses to get char and attr
- */
- void save_minor_area( chtype *buffer, int wid, int len, int row, int col )
- {
- int i;
- int j;
-
- wid--;
- len--;
- for (i=0; len >= 0; len--) {
- for (j=wid; j >= 0; j--, i++)
- buffer[i] = mvinch( row+len, col+j );
- }
- }
-
-
- /*
- * Name: retore_minor_area
- * Purpose: restore text and attribute under the pulled menu
- * Date: November 13, 1993
- * Passed: buffer: storage for text and attribute
- * wid: width of the pulled menu
- * len: length of pulled menu
- * row: starting row of pulled menu
- * col: starting column of pulled menu
- * Notes: use curses to set char and attr
- */
- void restore_minor_area( chtype *buffer, int wid, int len, int row, int col )
- {
- int i;
- int j;
-
- wid--;
- len--;
- for (i=0; len >= 0; len--) {
- for (j=wid; j >= 0; j--, i++)
- mvaddch( row+len, col+j, buffer[i] );
- }
- }
-
-
- #else
- /*
- **********************************************************************
- ****************************** PART 2 ******************************
- **********************************************************************
- *
- * Calls to BIOS and writes to PC hardware.
- */
-
- #include <bios.h> /* for direct BIOS keyboard input */
-
-
- /*
- * BIOS Data Areas
- *
- * See:
- *
- * IBM Corp., _Technical Reference: Personal Computer AT_,
- * Boca Raton, Florida, 1984, IBM part no. 1502494,
- * pp 5-29 thru 5-32.
- *
- * These addresses, variable names, types, and descriptions are directly
- * from the IBM AT Technical Reference manual, BIOS listing, copyright IBM.
- *
- * Address Name Type Description
- * 0x0449 CRT_MODE Byte Current CRT mode
- * 0x044a CRT_COLS Word Number columns on screen
- * 0x044c CRT_LEN Word length of regen buffer, video buffer, bytes
- * 0x044e CRT_START Word Starting address of regen buffer
- * 0x0450 CURSOR_POSN Word cursor for each of up to 8 pages.
- * 0x0460 CURSOR_MODE Word current cursor mode setting.
- * 0x0462 ACTIVE_PAGE Byte Current page
- * 0x0463 ADDR_6845 Word base address for active display card
- * 0x0465 CRT_MODE_SET Byte current mode of display card
- * 0x0466 CRT_PALETTE Byte overscan color for CGA, EGA, and VGA.
- * 0x0467 io_rom_init Word Pointer to optional i/o rom init routine
- * 0x0469 io_rom_seg Word Pointer to io rom segment
- * 0x046b intr_flag Byte Flag to indicate an interrupt happened
- * 0x046c timer_low Word Low word of timer count
- * 0x046e timer_high Word High word of timer count
- * 0x0470 timer_ofl Byte Timer has rolled over since last count
- * 0x0471 bios_break Byte Bit 7 = 1 if Break Key has been hit
- * 0x0472 reset_flag Word Word = 1234h if keyboard reset underway
- * 0x0484 ROWS Byte Number of displayed character rows - 1
- * 0x0485 POINTS Word Height of character matrix
- * 0x0487 INFO Byte EGA and VGA display data
- * 0x0488 INFO_3 Byte Configuration switches for EGA and VGA
- * 0x0489 flags Byte Miscellaneous flags
- * 0x0496 kb_flag_3 Byte Additional keyboard flag
- * 0x048A DCC Byte Display Combination Code
- * 0x04A8 SAVE_PTR Dword Pointer to BIOS save area
- */
- void video_config( struct vcfg *cfg )
- {
- #pragma pack( 1 ) /* Use pragma to force packing on byte boundaries. */
-
- struct LOWMEMVID
- {
- char vidmode; /* 0x449 */
- unsigned scrwid; /* 0x44A */
- unsigned scrlen; /* 0x44C */
- unsigned scroff; /* 0x44E */
- struct LOCATE
- {
- unsigned char col;
- unsigned char row;
- } csrpos[8]; /* 0x450 */
- struct CURSIZE
- {
- unsigned char end;
- unsigned char start;
- } csrsize; /* 0x460 */
- char page; /* 0x462 */
- unsigned addr_6845; /* 0x463 */
- char crt_mode_set; /* 0x465 */
- char crt_palette; /* 0x466 */
- char system_stuff[29]; /* 0x467 */
- char rows; /* 0x484 */
- unsigned points; /* 0x485 */
- char ega_info; /* 0x487 */
- char info_3; /* 0x488 */
- char skip[13]; /* 0x489 */
- char kb_flag_3; /* 0x496 */
- } vid;
- struct LOWMEMVID _far *pvid = &vid;
- #pragma pack( ) /* revert to previously defined pack pragma. */
-
- union REGS in, out;
- unsigned char temp, active_display;
-
- /*
- * Move system information into our video structure.
- */
- my_memmove( pvid, (void FAR *)0x00000449l, sizeof( vid ) );
-
- cfg->rescan = FALSE;
- in.x.ax = 0x1a00;
- int86( VIDEO_INT, &in, &out );
- temp = out.h.al;
- active_display = out.h.bl;
- if (temp == 0x1a && (active_display == 7 || active_display == 8))
- g_display.adapter = VGA;
- else {
- in.h.ah = 0x12;
- in.h.bl = 0x10;
- int86( VIDEO_INT, &in, &out );
- if (out.h.bl != 0x10) { /* EGA */
- if (vid.ega_info & 0x08)
- g_display.adapter = vid.addr_6845 == 0x3d4 ? CGA : MDA;
- else
- g_display.adapter = EGA;
- } else if (vid.addr_6845 == 0x3d4)
- g_display.adapter = CGA;
- else
- g_display.adapter = MDA;
- }
-
- if (g_display.adapter == CGA || g_display.adapter == EGA) {
- if (g_display.adapter == CGA)
- cfg->rescan = TRUE;
- g_display.insert_cursor = mode.cursor_size == SMALL_INS ? 0x0607 : 0x0407;
- g_display.overw_cursor = mode.cursor_size == SMALL_INS ? 0x0407 : 0x0607;
- } else {
- g_display.insert_cursor = mode.cursor_size == SMALL_INS ? 0x0b0c : 0x070b;
- g_display.overw_cursor = mode.cursor_size == SMALL_INS ? 0x070b : 0x0b0c;
- }
-
- cfg->mode = vid.vidmode;
- if (vid.addr_6845 == 0x3D4) {
- cfg->color = TRUE;
- cfg->videomem = (void FAR *)0xb8000000l;
- } else {
- cfg->color = FALSE;
- cfg->videomem = (void FAR *)0xb0000000l;
- }
-
- /*
- * let save the overscan color
- */
- g_display.old_overscan = vid.crt_palette;
-
-
- /*
- * Get keyboard type. Since there is no interrupt that determines
- * keyboard type, use this method. Look at bit 4 in keyboard flag3.
- * This method is not always foolproof on clones.
- */
- if ((vid.kb_flag_3 & 0x10) != 0)
- mode.enh_kbd = TRUE;
- else
- mode.enh_kbd = FALSE;
- if (mode.enh_kbd == FALSE)
- simulate_enh_kbd( 1 );
- }
-
-
- /*
- * The next function was written by Tom Waters, twaters@relay.nswc.navy.mil, and
- * modified extensively by Frank Davis.
- *
- * "I use ANSI.SYS to redefine a few of my function keys and this causes a
- * problem when getch() is used in a program. For example, instead of returning
- * 321 for the F7, I get the redefined string inserted in the text. So, instead
- * of using getch(), I use the following function ..."
- *
- * Tom, thanks for the info and solution. I'm sure your function will be
- * be appreciated by everyone with ANSI key defs, Frank.
- */
-
- /*
- * Name: getkey
- * Purpose: use bios to get keyboard input (getch has trouble w/ ANSI
- * redefined keys)
- * Date: July 2, 1991
- * Modified:July 12, 1991, Frank Davis - accept ALT-xxx keyboard entry
- * September 10, 1991, Frank Davis - add support for Ctrl+Up, etc...
- * Passed: None
- * Notes: Uses the BIOS to read the next keyboard character. Service 0x00
- * is the XT keyboard read. Service 0x10 is the extended keyboard
- * read. Test for a bunch of special cases. Allow the user to enter
- * any ASCII or Extended ASCII code as a normal text characters.
- *
- * Control @ is defined as 0. we need to do a special test
- * for this key, otherwise it's interpretted as an Alt key. It's
- * the only "regular" Control key that returns 0 in AL and the scan
- * byte in AH. The "regular" Control keys are those in the range
- * 0-31 and they return the Control character in AL and the scan
- * code in AH. All of the Alt + keys return 0 in AL and
- * the scan code in ah.
- *
- * This function was written for US keyboards. It may have to be
- * modified for other keyboards, eg. Belgium, Canada, Czech,
- * Slovak, Denmark, France, Germany, etc...
- *
- * if Ctrl-Break is pressed, it returns 0xffff as the key pressed.
- * let's set it to CONTROL_BREAK == 269 and do nothing.
- */
- int getkey( void )
- {
- unsigned key, num_lock, control, shift;
- register scan;
- register unsigned lo;
-
- /*
- * this code is used during testing to check the amount of memory
- * in the near heap.
- *
- * char temp[MAX_COLS+2];
- *
- * ultoa( _memavl( ), temp, 10 );
- * s_output( "h= ", g_display.mode_line, 37, g_display.mode_color );
- * s_output( temp, g_display.mode_line, 39, g_display.mode_color );
- */
-
- /*
- * lets spin on waitkey until the user presses a key. waitkey polls
- * the keyboard and returns 0 when a key is waiting.
- */
- while (waitkey( mode.enh_kbd ));
-
- /*
- * _bios_keybrd == int 16. It returns the scan code in ah, hi part of key,
- * and the ascii key code in al, lo part of key. If the character was
- * entered via ALT-xxx, the scan code, hi part of key, is 0.
- */
- if (mode.enh_kbd) {
- key = _bios_keybrd( 0x10 );
- lo = _bios_keybrd( 0x12 );
-
- /*
- * couple of special cases:
- * on the numeric keypad, some keys return 0xe0 in the lo byte.
- * 1) if user enters Alt-224, then the hi byte == 0 and lo byte == 0xe0.
- * we need to let this get thru as an Extended ASCII char. 2) although
- * we could make the cursor pad keys do different functions than the
- * numeric pad cursor keys, let's set the 0xe0 in the lo byte to zero
- * and forget about support for those keys.
- */
- if ((key & 0x00ff) == 0x00e0 && (key & 0xff00) != 0)
- key = key & 0xff00;
- } else {
- key = _bios_keybrd( 0 );
- lo = _bios_keybrd( 2 );
- }
- num_lock = lo & 0x20;
- control = lo & 0x04;
- shift = lo & 0x03;
- scan = (key & 0xff00) >> 8;
- lo = key & 0X00FF;
-
- if (lo == 0) {
- /*
- * special case for Control @, which is defined as 0 or NULL.
- */
- if (scan == 3)
- lo = 430;
-
- /*
- * when first byte is 0, map it above 256, so that we can
- * let ALT-xxx keys map to their 'natural' place. In
- * otherwords, use 0-255 as normal text characters and
- * those >= 256 are function keys.
- */
- else
- lo = scan | 0x100;
-
- /*
- * now test for Control-Break. let's set this to do nothing in the
- * editor. manually map Control-Break to 269 - DO NOT assign
- * any function to 269.
- */
- } else if (key == 0xffff)
- lo = CONTROL_BREAK;
-
-
- /*
- * Pressing Control+BackSpace generates the 0x7f character. Instead of
- * 0x7f, make lo the ASCII backspace character. If anyone wants the
- * 0x7f character, then they can enter it via ALT+xxx.
- */
- if (scan == 14 && lo == 0x7f)
- lo = 8;
-
- /*
- * At the bottom of page 195 in MASM 6.0 ref manual, "..when the keypad
- * ENTER and / keys are read through the BIOS interrupt 16h, only E0h
- * is seen since the interrupt only gives one-byte scan codes."
- */
- else if (scan == 0xe0) {
- /*
- * plain Grey Enter
- */
- if (lo == 13 && !shift)
- lo = 285;
- /*
- * shift Grey Enter
- */
- else if (lo == 13)
- lo = 298;
- /*
- * control Grey Enter
- */
- else if (lo == 10)
- lo = 299;
- }
-
- /*
- * let's massage all of the control key combinations.
- */
- if (lo < 32) {
-
- /*
- * My machine at home is sorta weird. On every machine that I've
- * tested at the awffice, the ALT-xxx combination returns 0 for the
- * scan byte and xxx for the ASCII code. My machine returns 184 (decimal)
- * as the scan code?!?!? I added the next two lines for my machine at
- * home. I wonder if someone forgot to zero out ah for Alt keypad entry
- * when they wrote my bios?
- */
- if (scan > 0x80)
- scan = 0;
-
- /*
- * Separate the ESC key from the ^[ key. The scan code for the ESC
- * key is 1. Map this to a different index into the key function
- * array just in case someone wants to define ESC or ^[ to different
- * functions. BTW, ESC and ^[ return the same ASCII code, 27.
- */
- else if (scan == 1) {
- if (shift)
- lo = 259;
- else if (control)
- lo = 260;
- else
- lo = 258;
- }
-
- /*
- * Scan code for Enter = 28. Separate the various Enter keys.
- */
- else if (scan == 28) {
- if (shift)
- lo = 263;
- else if (control)
- lo = 264;
- else
- lo = 262;
- }
-
- /*
- * Scan code for Backspace = 14. Separate the various BackSpace keys.
- */
- else if (scan == 14) {
- if (shift)
- lo = 266;
- else if (control)
- lo = 267;
- else
- lo = 265;
- }
-
- /*
- * Scan code for Tab = 15. Separate the tab key.
- */
- else if (scan == 15) {
- lo = 268;
- }
-
- /*
- * if scan code is not 0, then a Control key was pressed. Map
- * those keys to the WordStar commands.
- */
- else if (scan > 0)
- lo += 430;
-
- } else if (!num_lock) {
- switch (scan) {
- /*
- * scan code for grey - == 74. if num_lock is not toggled, assign it
- * to the scroll line up function.
- */
- case 74 :
- lo = 423;
- break;
-
- /*
- * scan code for grey + == 78. if num_lock is not toggled, assign it
- * to the scroll line down function. if shift grey + then stationary
- * scroll down.
- */
- case 78 :
- lo = 424;
- break;
- }
- }
-
-
- /*
- * let's set up for the Shift+Alt and Control+Alt keys.
- * With these key combinations, we can do the International keyboard
- * stuff, see the Microsoft MS DOS 5.0 manual pages 623-637.
- */
- if (lo > 256 && (shift || control)) {
-
- /*
- * add 55 to Ctrl+Left thru Ctrl+Home when the shift key is pressed.
- * this is not part of the International keyboard stuff, just a way
- * to assign the horizontal scroll left and right funcs to cursor keys.
- */
- if (shift) {
- if (lo >= 371 && lo <= 374)
- lo += 55;
-
- /*
- * if shift is down, map alt 1! thru alt =+ to shift alt 1! thru alt =+
- */
- else if (lo >= 376 && lo <= 387)
- lo += 86;
-
- /*
- * internation keyboard stuff
- */
- else if (lo >= 272 && lo <= 309)
- lo += 202;
- }
- }
-
- /*
- * map the enter key to line feed.
- */
- if (lo == 10 && scan != 0)
- lo = 425;
- return( lo );
- }
-
-
- /*
- * Name: waitkey
- * Purpose: call the BIOS keyboard status subfunction
- * Date: October 31, 1992
- * Passed: enh_keyboard: boolean - TRUE if 101 keyboard, FALSE otherwise
- * Returns: 1 if no key ready, 0 if key is waiting
- * Notes: lets get the keyboard status so we can spin on this function until
- * the user presses a key. some OS replacements for DOS want
- * application programs to poll the keyboard instead of rudely
- * sitting on the BIOS read key function.
- */
- int waitkey( int enh_keyboard )
- {
- return( _bios_keybrd( enh_keyboard ? 0x11 : 0x01 ) == 0 ? 1 : 0 );
- }
-
-
- /*
- * Name: flush_keyboard
- * Purpose: flush keys from the keyboard buffer
- * Date: June 5, 1993
- * Passed: enh_keyboard: boolean - TRUE if 101 keyboard, FALSE otherwise
- * Returns: 1 if no key ready, 0 if key is waiting
- * Notes: lets get the keyboard status so we can spin on this function until
- * the user presses a key. some OS replacements for DOS want
- * application programs to poll the keyboard instead of rudely
- * sitting on the BIOS read key function.
- */
- void flush_keyboard( void )
- {
- if (mode.enh_kbd) {
- while (!waitkey( mode.enh_kbd ))
- _bios_keybrd( 0x10 );
- } else {
- while (!waitkey( mode.enh_kbd ))
- _bios_keybrd( 0 );
- }
- }
-
-
- /*********************************************/
- /* */
- /* 3) video output routines, PC specific */
- /* */
- /*********************************************/
-
-
- /*
- * Name: xygoto
- * Purpose: To move the cursor to the required column and line.
- * Date: September 28, 1991
- * Passed: col: desired column (0 up to max)
- * line: desired line (0 up to max)
- * Notes; use standard BIOS video interrupt 0x10 to set the set.
- */
- void xygoto( int col, int line )
- {
- union REGS inregs, outregs;
-
- inregs.h.ah = 2;
- inregs.h.bh = 0;
- inregs.h.dh = (unsigned char)line;
- inregs.h.dl = (unsigned char)col;
- int86( 0x10, &inregs, &outregs );
- }
-
-
- /*
- * Name: update_line
- * Purpose: Display the current line in window
- * Date: June 5, 1991
- * Passed: window: pointer to current window
- * Notes: Show string starting at column zero and if needed blank rest
- * of line. Put max_col in cx and count down. When we run into
- * len, cx contains number of columns to blank out. Use the
- * fast 'rep stosw' to clear the end of line.
- * The C routine was probably fast enough, but let's do some
- * assembly because it's so fun.
- * To handle line lengths longer than 255 characters,
- * block begin and end columns were changed from real
- * to virtual columns in this display routine.
- */
- void update_line( TDE_WIN *window )
- {
- text_ptr text; /* current character of orig begin considered */
- char FAR *screen_ptr;
- int off;
- int attr;
- int line;
- int col;
- int bcol;
- int bc;
- int ec;
- int normal;
- int block;
- int max_col;
- int block_line;
- int len;
- int show_eol;
- int c;
- long rline;
- file_infos *file;
-
- if (window->rline > window->file_info->length || window->ll->len == EOF
- || !g_status.screen_display)
- return;
- file = window->file_info;
- max_col = window->end_col + 1 - window->start_col;
- line = window->cline;
- normal = window->ll->dirty == FALSE ? g_display.text_color : g_display.dirty_color;
- block = g_display.block_color;
- show_eol = mode.show_eol;
-
- /*
- * set the screen pointer to physical screen memory.
- * 160 = 80 chars + 80 attr for each line
- */
- screen_ptr = g_display.display_address;
- off = line * 160 + window->start_col * 2;
-
- /*
- * figure which line to display.
- * actually, we could be displaying any line in any file. we display
- * the line_buffer only if window->ll == g_status.buff_node
- * and window->ll-line has been copied to g_status.line_buff.
- */
- text = window->ll->line;
- len = window->ll->len;
- if (g_status.copied && ptoul( window->ll ) == ptoul( g_status.buff_node )) {
- text = (text_ptr)g_status.line_buff;
- len = g_status.line_buff_len;
- }
- if (mode.inflate_tabs)
- text = tabout( text, &len );
-
- /*
- * lets look at the base column. if the line to display is shorter
- * than the base column, then set text to eol and we can't see the
- * eol either.
- */
- bc = window->bcol;
- if (bc > 0) {
- if (text == NULL) {
- show_eol = FALSE;
- len = 0;
- } else {
- if ((col = len) < bc) {
- bc = col;
- show_eol = FALSE;
- }
- text += bc;
- len -= bc;
- }
- }
-
- /*
- * for display purposes, set the line length to screen width if line
- * is longer than screen. our assembly routine uses bytes and the
- * the line length can be longer than a byte.
- */
- if (len > max_col)
- len = max_col;
-
- bcol = window->bcol;
- rline = window->rline;
- if (file->block_type && rline >= file->block_br && rline <= file->block_er)
- block_line = TRUE;
- else
- block_line = FALSE;
-
- /*
- * do this if 1) a box block is marked, or 2) a stream block begins
- * and ends on the same line.
- */
- if (block_line == TRUE && (file->block_type == BOX ||
- (file->block_type == STREAM &&
- rline == file->block_br && rline == file->block_er))) {
-
- /*
- * start with the bc and ec equal to physical block marker.
- */
- bc = file->block_bc;
- ec = file->block_ec;
- if (ec < bcol || bc >= bcol + max_col)
- /*
- * we can't see block if ending column is less than the base col or
- * the beginning column is greater than max_col.
- */
- ec = bc = max_col + 1;
- else if (ec < bcol + max_col) {
- /*
- * if the ec is less than the max column, make ec relative to
- * base column then figure the bc.
- */
- ec = ec - bcol;
- if (bc < bcol)
- bc = 0;
- else
- bc = bc - bcol;
- } else if (bc < bcol + max_col) {
- /*
- * if the bc is less than the max column, make bc relative to
- * base column then figure the ec.
- */
- bc = bc - bcol;
- if (ec > bcol + max_col)
- ec = max_col;
- else
- ec = ec - bcol;
- } else if (bc < bcol && ec >= bcol + max_col) {
- /*
- * if the block is wider than the screen, make bc start at the
- * logical begin and make ec end at the logical end of the
- * window.
- */
- bc = 0;
- ec = max_col;
- }
-
-
- ASSEMBLE {
- /*
- ; Register strategy:
- ; bl == beginning column
- ; bh == ending column
- ; dl == normal text attribute
- ; dh == block attribute
- ; cl == current virtual column
- ; ch == maximum columns in window
- ; ES:DI == screen pointer (destination)
- ; DS:SI == text pointer (source)
- ; [bp+show_eol] == access for local C variable
- */
-
-
- push ds /* MUST save ds - push it on stack */
- push si /* save si on stack */
- push di /* save di on stack */
-
- /*
- ;
- ; set up local register variables
- ;
- */
- mov ax, WORD PTR bc /* get beginning column */
- mov bl, al /* keep it in bl */
- mov ax, WORD PTR ec /* get ending column */
- mov bh, al /* keep it in bh */
- mov ax, WORD PTR normal /* get normal attribute */
- mov dl, al /* keep it in dl */
- mov ax, WORD PTR block /* get block attribute */
- mov dh, al /* keep it in dh */
- mov ax, WORD PTR max_col /* get max number columns on screen */
- mov ch, al /* keep it in ch */
- xor cl, cl /* col = 0, keep col in cl */
- /*
- ;
- ; load screen and text pointer
- ;
- */
- mov di, WORD PTR screen_ptr /* load OFFSET of screen ptr */
- add di, WORD PTR off /* add offset of line */
- mov ax, WORD PTR screen_ptr+2 /* load SEGMENT of screen ptr */
- mov es, ax
- mov si, WORD PTR text /* load OFFSET of text ptr */
- mov ax, WORD PTR text+2 /* load SEGMENT of text ptr */
- mov ds, ax /* move segment of text in ds */
- cmp si, 0 /* is offset of text ptr == NULL? */
- jne not_null /* no, output string */
- cmp ax, 0 /* is segment of text ptr == NULL? */
- je dspl_eol /* yes, clear end of line */
- }
- not_null:
-
- ASSEMBLE {
- cmp cl, ch /* is col == max_col? */
- jge getout /* yes, thru with line */
- cmp cl, BYTE PTR len /* is col == len? */
- je dspl_eol /* yes, must check block past eol */
- }
- top:
-
- ASSEMBLE {
- lodsb /* get next char in string */
- mov ah, dl /* assume normal attribute */
- cmp cl, bl /* is col < bc? (less than beginning col) */
- jl ch_out1 /* yes, show char and normal attribute */
- cmp cl, bh /* is col > ec? (greater than ending col) */
- jg ch_out1 /* yes, show char and normal attribute */
- mov ah, dh /* must be in a block - block attribute */
- }
- ch_out1:
-
- ASSEMBLE {
- stosw /* now show char on screen w/ attribute */
- inc cl /* ++col */
- cmp cl, ch /* is col == max_col? */
- jge getout /* yes, thru with line */
- cmp cl, BYTE PTR len /* is col == len? */
- jl top /* yes, must check block past eol */
- }
- dspl_eol:
-
- ASSEMBLE {
- cmp WORD PTR show_eol, FALSE /* look at the show_eol flag */
- je block_eol /* show_eol flag is FALSE, blank line */
- mov al, EOL_CHAR /* load some eol indicator */
- mov ah, dl /* assume normal attribute */
- cmp cl, bl /* is col < bc? (less than beginning col) */
- jl ch_out2 /* yes, show char and normal attribute */
- cmp cl, bh /* is col > ec? (greater than ending col) */
- jg ch_out2 /* yes, show char and normal attribute */
- mov ah, dh /* must be in a block - show block attribute */
- }
- ch_out2:
-
- ASSEMBLE {
- stosw /* write eol and attribute to screen */
- inc cl /* ++col */
- cmp cl, ch /* is col == max_col? */
- je getout /* yes, we're done */
- }
- block_eol:
-
- ASSEMBLE {
- mov al, ' ' /* clear rest of line w/ spaces */
- }
- b1:
-
- ASSEMBLE {
- mov ah, dl /* assume normal attribute */
- cmp cl, bl /* is col < bc? (less than beginning col) */
- jl ch_out3 /* yes, show char and normal attribute */
- cmp cl, bh /* is col > ec? (greater than ending col) */
- jg ch_out3 /* yes, show char and normal attribute */
- mov ah, dh /* must be in a block - show block attribute */
- }
- ch_out3:
-
- ASSEMBLE {
- stosw /* write blank and attribute to screen */
- inc cl /* ++col */
- cmp cl, ch /* is col == max_col? */
- jl b1 /* while less output block */
- }
- getout:
-
- ASSEMBLE {
- pop di
- pop si
- pop ds
- }
-
- /*
- screen_ptr += off;
- bcol = window->start_col;
- for (col=0; col < max_col; col++, bcol++) {
- attr = normal;
- if (col >= bc && col <= ec)
- attr = block;
- if (col < len)
- c = *text++;
- else if (col == len && show_eol)
- c = EOL_CHAR;
- else
- c = ' ';
- *screen_ptr++ = c;
- *screen_ptr++ = attr;
-
- c_output( c, bcol, line, attr );
- }
- */
- } else if (block_line == TRUE && file->block_type == STREAM &&
- (rline == file->block_br || rline == file->block_er)) {
- if (rline == file->block_br)
- bc = file->block_bc;
- else {
- bc = file->block_ec + 1;
- ec = normal;
- normal = block;
- block = ec;
- }
- if (bc < bcol)
- bc = 0;
- else if (bc < bcol + max_col)
- bc = bc - bcol;
- else
- bc = max_col + 1;
-
-
- ASSEMBLE {
- /*
- ; Register strategy:
- ; bl == beginning column
- ; bh == relative line length
- ; dl == normal text attribute
- ; dh == block attribute
- ; cl == current virtual column
- ; ch == maximum columns in window
- ; ES:DI == screen pointer (destination)
- ; DS:SI == text pointer (source)
- ; [bp+show_eol] == access for local C variable
- */
-
- push ds /* MUST save ds - push it on stack */
- push si /* save si on stack */
- push di /* save di on stack */
-
- /*
- ;
- ; set up local register variables
- ;
- */
- mov ax, WORD PTR bc /* get beginning column */
- mov bl, al /* keep it in bl */
- mov ax, WORD PTR len /* get relative line length */
- mov bh, al /* keep it in bh */
- mov ax, WORD PTR normal /* get normal attribute */
- mov dl, al /* keep it in dl */
- mov ax, WORD PTR block /* get block attribute */
- mov dh, al /* keep it in dh */
- mov ax, WORD PTR max_col /* get max number columns on screen */
- mov ch, al /* keep it in ch */
- xor cl, cl /* col = 0, keep col in cl */
- /*
- ;
- ; load screen and text pointer
- ;
- */
- mov di, WORD PTR screen_ptr /* load OFFSET of screen ptr */
- add di, WORD PTR off /* add offset of line */
- mov ax, WORD PTR screen_ptr+2 /* load SEGMENT of screen ptr */
- mov es, ax
- mov si, WORD PTR text /* load OFFSET of text ptr */
- mov ax, WORD PTR text+2 /* load SEGMENT of text ptr */
- mov ds, ax /* move segment of text in ds */
- cmp si, 0 /* is offset of text ptr == NULL? */
- jne nott_null /* no, output string */
- cmp ax, 0 /* is segment of text ptr == NULL? */
- je ddspl_eol /* yes, clear end of line */
- }
- nott_null:
-
- ASSEMBLE {
- cmp cl, ch /* is col == max_col? */
- je ggetout /* yes, thru with line */
- cmp cl, bh /* is col == len? */
- je ddspl_eol /* yes, check eol display */
- }
- ttop:
-
- ASSEMBLE {
- lodsb /* get next char in string */
- mov ah, dl /* assume normal attribute */
- cmp cl, bl /* is col < bc? (less than beginning col) */
- jl str_out1 /* yes, show char and normal attribute */
- mov ah, dh /* must be in a block - show block attribute */
- }
- str_out1:
-
- ASSEMBLE {
- stosw /* else show char on screen */
- inc cl /* ++col */
- cmp cl, ch /* is col == max_col? */
- je ggetout /* yes, thru with line */
- cmp cl, bh /* is col == len? */
- jl ttop /* yes, check eol display */
- }
- ddspl_eol:
-
- ASSEMBLE {
- cmp WORD PTR show_eol, FALSE /* look at the show_eol flag */
- je stream_eol /* show_eol flag is FALSE, blank line */
- mov al, EOL_CHAR /* load some eol indicator */
- mov ah, dl /* assume normal attribute */
- cmp cl, bl /* is col < bc? (less than beginning col) */
- jl str_out2 /* yes, show char and normal attribute */
- mov ah, dh /* must be in a block - show block attribute */
- }
- str_out2:
-
- ASSEMBLE {
- stosw /* write blank and attribute to screen */
- inc cl /* ++col */
- cmp cl, ch /* is col == max_col? */
- jge ggetout /* yes, we're done */
- }
- stream_eol:
-
- ASSEMBLE {
- mov al, ' ' /* clear rest of line w/ spaces */
- }
- c1:
-
- ASSEMBLE {
- mov ah, dl /* assume normal attribute */
- cmp cl, bl /* is col < bc? (less than beginning col) */
- jl str_out3 /* yes, show char and normal attribute */
- mov ah, dh /* must be in a block - show block attribute */
- }
- str_out3:
-
- ASSEMBLE {
- stosw /* write blank and attribute to screen */
- inc cl /* ++col */
- cmp cl, ch /* is col == max_col? */
- jl c1 /* while less output block */
- }
- ggetout:
-
- ASSEMBLE {
- pop di
- pop si
- pop ds
- }
-
- /*
- screen_ptr += off;
- bcol = window->start_col;
- for (col=0; col < max_col; col++, bcol++) {
- attr = normal;
- if (col >= bc && col <= ec)
- attr = block;
- if (col < len)
- c = *text++;
- else if (col == len && show_eol)
- c = EOL_CHAR;
- else
- c = ' ';
- *screen_ptr++ = c;
- *screen_ptr++ = attr;
- c_output( c, bcol, line, attr );
- }
- */
- } else {
- if (block_line)
- attr = block;
- else
- attr = normal;
-
- assert( len >= 0 );
- assert( len <= g_display.ncols );
-
- ASSEMBLE {
- /*
- ; Register strategy:
- ; bl == normal text attribute
- ; bh == relative line length
- ; cl == current virtual column
- ; ch == maximum columns in window
- ; ES:DI == screen pointer (destination)
- ; DS:SI == text pointer (source)
- ; [bp+show_eol] == access for local C variable
- */
-
- mov dx, ds /* MUST save ds - keep it in dx */
- push di /* save di on stack */
- push si /* save si on stack */
-
-
- mov bx, WORD PTR attr /* keep attribute in bl */
- mov ax, WORD PTR len /* get normalized len */
- mov bh, al /* keep len in bh */
- mov cx, WORD PTR max_col /* get max_col in cx */
- mov ch, cl /* keep it in ch */
- xor cl, cl /* zero out cl */
- mov di, WORD PTR screen_ptr /* load OFFST of screen ptr */
- add di, WORD PTR off /* add offset of line */
- mov ax, WORD PTR screen_ptr+2 /* load SEGMENT of screen ptr */
- mov es, ax
- mov si, WORD PTR text /* load OFFSET of text ptr */
- mov ax, WORD PTR text+2 /* load SEGMENT of text ptr */
- mov ds, ax /* move segment of text in ds */
- cmp si, 0 /* is offset of pointer == NULL? */
- jne nnot_null /* no, output string */
- cmp ax, 0 /* is segment of pointer == NULL? */
- je normeol /* yes, then clear rest of line */
- }
- nnot_null:
-
- ASSEMBLE {
- mov ah, bl /* get attribute */
- cmp cl, ch /* compare count with max columns */
- jge getoutt /* yes, thru with line */
- cmp cl, bh /* compare count with len */
- je normeol /* yes, clear end of line */
- }
- topp:
-
- ASSEMBLE {
- lodsb /* get next char in string */
- stosw /* else show char on screen */
- inc cl /* ++col, count up to max_column */
- cmp cl, ch /* compare count with max columns */
- jge getoutt /* yes, thru with line */
- cmp cl, bh /* compare count with len */
- jl topp /* yes, clear end of line */
- }
- normeol:
-
- ASSEMBLE {
- cmp WORD PTR show_eol, FALSE /* look at the show_eol flag */
- je clreol /* show_eol flag is FALSE, blank line */
- mov al, EOL_CHAR /* load some eol indicator */
- mov ah, bl /* assume normal attribute */
- stosw /* write blank and attribute to screen */
- inc cl /* ++col */
- cmp cl, ch /* is col == max_col? */
- jge getoutt /* yes, we're done */
- }
- clreol:
-
- ASSEMBLE {
- mov ah, bl /* get attribute */
- mov al, ' ' /* clear eol with ' ' */
- sub ch, cl /* find number of columns left */
- mov cl, ch /* put number of column left in cl */
- xor ch, ch /* clear ch */
- rep stosw /* count is in cx - set rest of line to ' ' */
- }
- getoutt:
-
- ASSEMBLE {
- pop si
- pop di
- mov ds, dx
- }
-
- /*
- screen_ptr += off;
- bcol = window->start_col;
- for (col=0; col < max_col; col++, bcol++) {
- if (col < len)
- c = *text++;
- else if (col == len && show_eol)
- c = EOL_CHAR;
- else
- c = ' ';
- *screen_ptr++ = c;
- *screen_ptr++ = attr;
- c_output( c, bcol, line, attr );
- }
- */
- }
- }
-
-
- /*
- * Name: c_output
- * Purpose: Output one character on prompt lines
- * Date: June 5, 1991
- * Passed: c: character to output to screen
- * col: col to display character
- * line: line number to display character
- * attr: attribute of character
- * Returns: none
- */
- void c_output( int c, int col, int line, int attr )
- {
- void FAR *screen_ptr;
- int off;
-
- screen_ptr = (void FAR *)g_display.display_address;
- off = line * 160 + col * 2;
-
- ASSEMBLE {
- mov bx, WORD PTR screen_ptr /* load OFFSET of screen ptr */
- add bx, WORD PTR off /* add offset of line:col */
- mov ax, WORD PTR screen_ptr+2 /* load SEGMENT of screen ptr */
- mov es, ax
- mov cx, WORD PTR attr /* get attribute */
- mov ah, cl /* put in ah */
- mov cx, WORD PTR c /* get character */
- mov al, cl /* put in al */
- mov WORD PTR es:[bx], ax /* show char on screen */
- }
-
- /*
- screen_ptr = g_display.display_address + line * 160 + col * 2;
- *screen_ptr++ = c;
- *screen_ptr = attr;
- */
- }
-
-
- /*
- * Name: s_output
- * Purpose: To output a string
- * Date: June 5, 1991
- * Passed: s: string to output
- * line: line to display
- * col: column to begin display
- * attr: color to display string
- * Notes: This function is used to output most strings not part of file text.
- */
- void s_output( char FAR *s, int line, int col, int attr )
- {
- void FAR *screen_ptr;
- int off;
- int max_col;
-
- max_col = g_display.ncols;
- screen_ptr = (void FAR *)g_display.display_address;
- off = line * 160 + col * 2;
-
- ASSEMBLE {
- push ds /* save ds on stack */
- push di /* save di on stack */
- push si /* save si on stack */
-
- mov bx, WORD PTR attr /* keep attribute in bx */
- mov cx, WORD PTR col /* put cols in cx */
- mov dx, WORD PTR max_col /* keep max_col in dx */
- mov di, WORD PTR screen_ptr /* load OFFSET of screen ptr */
- add di, WORD PTR off /* add offset of line:col */
- mov ax, WORD PTR screen_ptr+2 /* load SEGMENT of screen ptr */
- mov es, ax
- mov si, WORD PTR s /* load offset of string ptr */
- or si, si /* is it == NULL? */
- je getout /* yes, no output needed */
- mov ax, WORD PTR s+2 /* load segment of string ptr */
- or ax, ax /* is pointer == NULL? */
- je getout /* yes, no output needed */
- mov ds, ax /* load segment of text in ds */
- mov ah, bl /* put attribute in AH */
- }
- top:
-
- ASSEMBLE {
- cmp cx, dx /* col < max_cols? */
- jge getout /* no, thru with line */
- lodsb /* get next char in string - put in al */
- or al, al /* is it '\0' */
- je getout /* yes, end of string */
- cmp al, 0x0a /* is it '\n'? */
- je getout /* yes, end of string */
- stosw /* else show attr + char on screen (ah + al) */
- inc cx /* col++ */
- jmp SHORT top /* get another character */
- }
- getout:
-
- ASSEMBLE {
- pop si /* get back si */
- pop di /* get back di */
- pop ds /* get back ds */
- }
-
- /*
- screen_ptr = g_display.display_address + line * 160 + col * 2;
- max_col = g_display.ncols;
- while (*s && col < max) {
- *screen_ptr++ = *s++;
- *screen_ptr++ = attr;
- }
- */
- }
-
-
- /*
- * Name: eol_clear
- * Purpose: To clear the line from col to max columns
- * Date: June 5, 1991
- * Passed: col: column to begin clear
- * line: line to clear
- * attr: color to clear
- * Notes: Basic assembly
- */
- void eol_clear( int col, int line, int attr )
- {
- int max_col;
- void FAR *screen_ptr;
- int off;
-
- max_col = g_display.ncols;
- screen_ptr = (void FAR *)g_display.display_address;
- off = line * 160 + col * 2;
-
- ASSEMBLE {
- push di /* save di on stack */
-
- mov bx, WORD PTR attr /* keep attribute in bx */
- mov dx, WORD PTR col /* put cols in dx */
- mov cx, WORD PTR max_col /* put max_col in cx */
- cmp dx, cx /* max_cols < cols? */
- jge getout /* no, thru with line */
- sub cx, dx /* number of column to clear */
- mov di, WORD PTR screen_ptr /* load OFFSET of screen ptr */
- add di, WORD PTR off /* add offset of line:col */
- mov ax, WORD PTR screen_ptr+2 /* load SEGMENT of screen ptr */
- mov es, ax
- mov ah, bl /* get attribute in ah */
- mov al, ' ' /* store ' ' in al */
- rep stosw /* clear to end of line */
- }
- getout:
-
- ASSEMBLE {
- pop di /* get back di from stack */
- }
-
- /*
- for (; col < g_display.ncols; col++) {
- *p++ = ' ';
- *p++ = attr;
- }
- */
- }
-
-
- /*
- * Name: window_eol_clear
- * Purpose: To clear the line from start_col to end_col
- * Date: June 5, 1991
- * Passed: window: pointer to window
- * attr: color to clear
- * Notes: Basic assembly
- */
- void window_eol_clear( TDE_WIN *window, int attr )
- {
- int max_col;
- void FAR *screen_ptr;
- int off;
-
- if (!g_status.screen_display)
- return;
- screen_ptr = (void FAR *)g_display.display_address;
- off = window->cline * 160 + window->start_col * 2;
- max_col = window->end_col + 1 - window->start_col;
-
- ASSEMBLE {
- push di /* save di on stack */
-
- mov bx, WORD PTR attr /* keep attribute in bx */
- mov cx, WORD PTR max_col /* put max_col in cx */
- mov di, WORD PTR screen_ptr /* load OFFSET of screen ptr */
- add di, WORD PTR off /* add offset of line:col */
- mov ax, WORD PTR screen_ptr+2 /* load SEGMENT of screen ptr */
- mov es, ax
- mov ah, bl /* get attribute in ah */
- mov al, ' ' /* store ' ' in al */
- rep stosw /* clear to end of line */
-
- pop di /* get back di from stack */
- }
-
- /*
- for (max_col=window->start_col; max_col <= window->end_col; max_col++) {
- *screen_ptr++ = ' ';
- *screen_ptr++ = attr;
- }
- */
- }
-
-
- /*
- * Name: hlight_line
- * Date: July 21, 1991
- * Passed: x: column to begin hi lite
- * y: line to begin hi lite
- * lgth: number of characters to hi lite
- * attr: attribute color
- * Notes: The attribute byte is the hi byte.
- */
- void hlight_line( int x, int y, int lgth, int attr )
- {
- int off;
- void FAR *screen_ptr;
-
- screen_ptr = (void FAR *)g_display.display_address;
- off = y * 160 + 2 * x + 1; /* add one - so it points to attribute byte */
-
- ASSEMBLE {
- push di /* save di */
-
- mov cx, lgth /* number of characters to change color */
-
- mov di, WORD PTR screen_ptr /* get destination - video memory */
- add di, off /* add offset */
- mov ax, WORD PTR screen_ptr+2
- mov es, ax
- mov ax, attr /* attribute */
- }
- lite_len:
-
- ASSEMBLE {
- stosb /* store a BYTE */
- inc di /* skip over character to next attribute */
- loop lite_len /* change next attribute */
- pop di /* restore di */
- }
- }
-
-
- /*
- * Name: cls
- * Purpose: clear screen
- * Date: June 5, 1991
- * Notes: Call the video BIOS routine to clear the screen.
- */
- void cls( void )
- {
- int line;
-
- line = g_display.nlines + 1;
-
- ASSEMBLE {
- xor ch, ch /* starting row in ch = 0 */
- xor cl, cl /* starting column in cl = 0 */
- mov ax, WORD PTR line /* get ending row */
- mov dh, al /* put it in dh */
- mov dl, 79 /* ending column in dl = 79 */
- mov bh, 7 /* attribute in bh = 7 (normal) */
- mov al, 0 /* get number of lines */
- mov ah, 6 /* get function number */
- push bp /* some BIOS versions wipe out bp */
- int 0x10
- pop bp
- }
- }
-
-
- /*
- * Name: set_cursor_size
- * Purpose: To set cursor size according to insert mode.
- * Date: June 5, 1991
- * Passed: csize: desired cursor size
- * Notes: use the global display structures to set the cursor size
- */
- void set_cursor_size( int csize )
- {
- ASSEMBLE {
- mov ah, 1 /* function 1 - set cursor size */
- mov cx, WORD PTR csize /* get cursor size ch:cl == top:bot */
- push bp
- int VIDEO_INT /* video interrupt = 10h */
- pop bp
- }
- }
-
-
- /*
- * Name: set_overscan_color
- * Purpose: To set overscan color
- * Date: April 1, 1993
- * Passed: color: overscan color
- * Notes: before setting the overscan color, the old overscan color
- * needs to be saved so it can be restored.
- */
- void set_overscan_color( int color )
- {
- ASSEMBLE {
- mov ah, 0x0b /* function 0x0b */
- mov bl, BYTE PTR color /* get new overscan color */
- xor bh, bh
- push bp
- int VIDEO_INT /* video interrupt = 10h */
- pop bp
- }
- }
-
-
- /*
- * Name: save_screen_line
- * Purpose: To save the characters and attributes of a line on screen.
- * Date: June 5, 1991
- * Passed: col: desired column, usually always zero
- * line: line on screen to save (0 up to max)
- * screen_buffer: buffer for screen contents, must be >= 160 chars
- * Notes: Save the contents of the line on screen where prompt is
- * to be displayed
- */
- void save_screen_line( int col, int line, char *screen_buffer )
- {
- char FAR *p;
-
- p = g_display.display_address + line * 160 + col * 2;
- _fmemcpy( screen_buffer, p, 160 );
- }
-
-
- /*
- * Name: restore_screen_line
- * Purpose: To restore the characters and attributes of a line on screen.
- * Date: June 5, 1991
- * Passed: col: usually always zero
- * line: line to restore (0 up to max)
- * screen_buffer: buffer for screen contents, must be >= 160 chars
- * Notes: Restore the contents of the line on screen where the prompt
- * was displayed
- */
- void restore_screen_line( int col, int line, char *screen_buffer )
- {
- char FAR *p;
-
- p = g_display.display_address + line * 160 + col * 2;
- _fmemcpy( p, screen_buffer, 160 );
- }
-
-
- /*
- * Name: save_minor_area
- * Purpose: save text and attribute under the pulled menu
- * Date: November 13, 1993
- * Passed: buffer: storage for text and attribute
- * wid: width of the pulled menu
- * len: length of pulled menu
- * row: starting row of pulled menu
- * col: starting column of pulled menu
- * Notes: assume 80 column mode
- */
- void save_minor_area( int *buffer, int wid, int len, int row, int col )
- {
- int off;
- int FAR *pointer;
- int i;
- int j;
-
- wid--;
- off = row * 80 + col;
- pointer = (int FAR *)g_display.display_address + off;
- for (i=0; len > 0; len--) {
- for (j=wid; j >= 0; j--, i++)
- buffer[i] = pointer[j];
- pointer += 80;
- }
- }
-
-
- /*
- * Name: retore_minor_area
- * Purpose: restore text and attribute under the pulled menu
- * Date: November 13, 1993
- * Passed: buffer: storage for text and attribute
- * wid: width of the pulled menu
- * len: length of pulled menu
- * row: starting row of pulled menu
- * col: starting column of pulled menu
- * Notes: assume 80 column mode
- */
- void restore_minor_area( int *buffer, int wid, int len, int row, int col )
- {
- int off;
- int FAR *pointer;
- int i;
- int j;
-
- wid--;
- off = row * 80 + col;
- pointer = (int FAR *)g_display.display_address + off;
- for (i=0; len > 0; len--) {
- for (j=wid; j >= 0; j--, i++)
- pointer[j] = buffer[i];
- pointer += 80;
- }
- }
-
- #endif
-
- /*
- **********************************************************************
- ****************************** PART 3 ******************************
- **********************************************************************
- *
- * System independent keyboard stuff.
- */
-
-
- /*
- * Name: getfunc
- * Purpose: get the function assigned to key c
- * Date: July 11, 1991
- * Passed: c: key just pressed
- * Notes: key codes less than 256 or 0x100 are not assigned a function.
- * The codes in the range 0-255 are ASCII and extended ASCII chars.
- */
- int getfunc( int c )
- {
- register int i = c;
- int key_found;
-
- if (!g_status.key_pending) {
- i = c;
- if (i <= 256)
- i = 0;
- else
- i = key_func.key[i-256];
- } else {
-
- /*
- * allow the user to enter two-key combinations
- */
- key_found = FALSE;
- for (i=0; i < MAX_TWO_KEYS; i++) {
- if (g_status.first_key == two_key_list.key[i].parent_key &&
- c == two_key_list.key[i].child_key) {
- i = two_key_list.key[i].func;
- key_found = TRUE;
- break;
- }
- }
- if (key_found == FALSE)
- i = ERROR;
- }
- return( i );
- }
-
-
- /*
- * Name: two_key
- * Purpose: set the two_key flag and prompt for the next key.
- * Date: April 1, 1992
- * Notes: this function accepts two key commands.
- */
- int two_key( TDE_WIN *arg_filler )
- {
- s_output( console1, g_display.mode_line, 67, g_display.diag_color );
- g_status.key_pending = TRUE;
- g_status.first_key = g_status.key_pressed;
- return( OK );
- }
-
-
- /*
- * Name: getanswerkey
- * Purpose: To get answer to questions etc.
- * Author: Byrial Jensen
- * Date: September 2, 1993
- * Modified: Frank Davis, November 13, 1993 (comments and bj_toupper())
- * Returns: The pressed key, changed to uppercase if alfabetic
- * Notes: If a key of a macro starting with:
- * IfCapsLock character, or IfNotCapsLock character
- * is presed, the character will be returned, changed to uppercase
- * if a letter.
- */
- int getanswerkey( void )
- {
- int key;
- int macrokey;
- int macrofunc;
- int macronext;
-
- /*
- * get a response from the user. if ascii or extended ascii, return upper
- */
- key = getkey( );
- if (key <= 255)
- key = bj_toupper( key );
-
- /*
- * else if key is assigned a character via macro, return upper key
- */
- else if (getfunc( key ) == PlayBack) {
- macronext = macro.first_stroke[key - 256];
- macrokey = macro.strokes[macronext].key;
- macrofunc = getfunc( macrokey );
-
- /*
- * if this a letter, return upper.
- */
- if (macrofunc == IfCapsLock || macrofunc == IfNotCapsLock) {
- macronext = macro.strokes[macronext].next;
- if (macronext != -1) {
- macrokey = macro.strokes[macronext].key;
- if (macrokey <= 255)
- key = bj_toupper( macrokey );
- }
- }
- }
- return( key );
- }
-