📄 console.c
字号:
/* * 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 * Date: June 5, 1994, version 4.0 * Date: December 5, 1998, version 5.0 (jmh) * * 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"#include "keys.h"#include <sys/ioctl.h>#include <linux/kd.h>#include <sys/io.h>#if defined( PC_CHARS )# define pc_chars A_ALTCHARSET#else# define pc_chars 0#endifint stdoutput; /* the redirected stdout */int xterm; /* running in an xterm? */static int port_access; /* is VGA IO allowed? */static void set_colors( int );static chtype c_xlat( int, int );/* * Name: console_init * Purpose: initialise the console (video and keyboard) * Author: Jason Hood * Date: October 23, 2002 * Passed: cfg: pointer to hold video config data * Notes: initialises both video and keyboard hardware. * moved some stuff from main.c into here. * * jmh 031125: turn on bright background (VGA, console, root) */void console_init( struct vcfg *cfg ){char *term; /* * if output has been redirected, remember where and restore it to screen. */ if (g_status.output_redir) { stdoutput = dup( 1 ); freopen( STDFILE, "w", stdout ); } term = getenv( "TERM" ); xterm = (term != NULL && strncmp( term, "xterm", 5 ) == 0); page( 1 ); video_config( cfg ); if (!xterm && cfg->color) { if (ioperm( 0x3c0, 0x1b, TRUE ) == 0) { port_access = TRUE; inb( 0x3da ); /* switch flip-flop to index mode */ outb( 0x30, 0x3c0 ); /* display enable, register 0x10 */ outb( 0x04, 0x3c0 ); /* 9-bit chars, blink mode off */ } }}/* * Name: console_suspend * Purpose: temporarily shutdown the console * Author: Jason Hood * Date: October 23, 2002 * Notes: readies the console for a shell */void console_suspend( void ){ bkgdset( COLOR_PAIR( 0 ) ); cls( ); endwin( ); page( 0 ); set_overscan_color( 0 );}/* * Name: console_resume * Purpose: restore the console * Author: Jason Hood * Date: October 23, 2002 * Notes: restores the console for TDE */void console_resume( int pause ){ if (pause) getkey( ); page( 1 ); refresh( ); set_overscan_color( Color( Overscan ) );}/* * Name: console_exit * Purpose: resets the console * Author: Jason Hood * Date: October 23, 2002 * Notes: resets the console after TDE has finished */void console_exit( void ){ /* * shutdown curses. */ curs_set( CURSES_SMALL ); bkgdset( COLOR_PAIR( 0 ) ); nl( ); noraw( ); endwin( ); page( 0 ); /* * restore stdout to the redirection. */ if (g_status.output_redir) dup2( stdoutput, 1 );}/* * Name: video_config * Purpose: initialise the curses package * Date: November 13, 1993 * Passed: cfg: flag to initialise or shut down * Notes: curses has three (?) cursor shapes: invisible, normal, large. * * jmh 990213: moved some stuff here from hw_initialise(). * jmh 990408: moved some stuff here from terminate() - if cfg is NULL, shut * down curses, otherwise initialise curses. * jmh 990414: reset cursor size, background color. * jmh 010808: set scrollok to FALSE. * jmh 030403: moved curses shutdown to console_exit(). */void video_config( struct vcfg *cfg ){ initscr( ); start_color( ); noecho( ); raw( ); nonl( ); scrollok( stdscr, FALSE ); nodelay( stdscr, TRUE ); g_display.cursor[SMALL_CURSOR] = CURSES_SMALL; g_display.cursor[MEDIUM_CURSOR] = g_display.cursor[LARGE_CURSOR] = CURSES_LARGE; g_display.curses_cursor = CURSES_INVISBL; cfg->color = has_colors( ); g_display.adapter = (cfg->color) ? CGA : MDA; set_colors( cfg->color ); getmaxyx( stdscr, cfg->rows, cfg->cols );#if defined( __linux__ ) g_display.shadow_width = (xterm || cfg->rows > 30) ? 1 : 2;#else g_display.shadow_width = 1;#endif}/* * Name: set_colors * Purpose: translate curses colors to DOS colors. * Date: October 24, 1999 * Passed: color: TRUE for color, FALSE for monochrome. * Notes: moved from hw_initialize(). */static void set_colors( int color ){int i;int j;/* * Ensure the colors are in the same order as DOS. */static const int col[8] = { COLOR_BLACK, COLOR_BLUE, COLOR_GREEN, COLOR_CYAN, COLOR_RED, COLOR_MAGENTA, COLOR_YELLOW, COLOR_WHITE}; if (color) { if (COLOR_PAIRS >= 64) { for (i = 0; i < 64; ++i) init_pair( i, col[i%8], col[i/8] ); for (j = 0; j < 8; ++j) { for (i = 0; i < 8; ++i) { tde_color_table[i+j*16] = COLOR_PAIR( (i+j*8) ); tde_color_table[i+j*16+8] = COLOR_PAIR( (i+j*8) ) | A_BOLD; } } /* * jmh 010629: pair 0 can't be initialised (remains white on black), * which means color 8 ("bright black" on black) is not * set correctly, causing the shadow to look wrong. * Let's use blue on blue for "bright black" on black. */ init_pair( 9, COLOR_BLACK, COLOR_BLACK ); tde_color_table[8] = COLOR_PAIR( 9 ) | A_BOLD; } else { init_pair( 0, COLOR_WHITE, COLOR_BLACK ); init_pair( 1, COLOR_WHITE, COLOR_BLUE ); init_pair( 2, COLOR_BLUE, COLOR_BLACK ); init_pair( 3, COLOR_YELLOW, COLOR_CYAN ); init_pair( 4, COLOR_WHITE, COLOR_RED ); init_pair( 5, COLOR_GREEN, COLOR_MAGENTA ); init_pair( 6, COLOR_GREEN, COLOR_BLACK ); init_pair( 7, COLOR_BLUE, COLOR_WHITE ); /* * lets try to emulate the PC color table. in normal color mode, * there are 8 background colors and 16 foreground colors. */ for (i=0; i<8; i++) { tde_color_table[i] = COLOR_PAIR( 0 ); tde_color_table[i+16] = COLOR_PAIR( 1 ); tde_color_table[i+32] = COLOR_PAIR( 2 ); tde_color_table[i+48] = COLOR_PAIR( 3 ); tde_color_table[i+64] = COLOR_PAIR( 4 ); tde_color_table[i+80] = COLOR_PAIR( 5 ); tde_color_table[i+96] = COLOR_PAIR( 6 ); tde_color_table[i+112] = COLOR_PAIR( 7 ); } for (i=0; i<8; i++) { tde_color_table[i+8] = COLOR_PAIR( 0 ) | A_BOLD; tde_color_table[i+24] = COLOR_PAIR( 1 ) | A_BOLD; tde_color_table[i+40] = COLOR_PAIR( 2 ) | A_BOLD; tde_color_table[i+56] = COLOR_PAIR( 3 ) | A_BOLD; tde_color_table[i+72] = COLOR_PAIR( 4 ) | A_BOLD; tde_color_table[i+88] = COLOR_PAIR( 5 ) | A_BOLD; tde_color_table[i+104] = COLOR_PAIR( 6 ) | A_BOLD; tde_color_table[i+120] = COLOR_PAIR( 7 ) | A_BOLD; } } } else { for (i = 0; i < 128; ++i) tde_color_table[i] = A_NORMAL; tde_color_table[1] = A_UNDERLINE; tde_color_table[15] = A_BOLD; tde_color_table[112] = A_REVERSE; tde_color_table[127] = A_STANDOUT; } for (i = 0; i < 128; ++i) tde_color_table[i+128] = tde_color_table[i] | A_BLINK;}/* * Name: kbReadShiftState * Purpose: to determine the state of shift, control and alt keys * Author: Jason Hood * Date: April 17, 1999 * Passed: Nothing * Returns: Shift state * Notes: based on the same function in Rhide 1.4 by Robert Hoehne. */static int kbReadShiftState( void ){int arg = 6; /* TIOCLINUX function #6 */int shift; if (ioctl( 0, TIOCLINUX, &arg ) != -1) { shift = 0; if (arg & 1) shift |= _SHIFT; if (arg & 4) shift |= _CTRL; if (arg & (2 | 8)) shift |= _ALT; } else shift = ERROR; return( shift );}/* * 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.c. * this function is based on the ncurses package in Linux. It * probably needs to be modified for curses in other unices. * * jmh 980725: translate keys. * jmh 990417: now that the shift state is known, map keys to DOS equivalents. * I don't think all the keys I've defined here are actually * available (such as those used for terminal switching). * jmh 990419: eat escape prefix characters (type esc-esc, 'cos it's quicker; * is there any way to remove that delay?). * jmh 990426: use KDGKBLED ioctl to test for NumLock. * jmh 020908: updated to new keyboard mapping. * jmh 031123: translate escape sequences myself (remove curses_to_tde[]). */long getkey( void ){int key, ch;long new_key;int shift_state;int alt_esc;char escape[8];int esclen;int j, k;go_again: g_status.control_break = FALSE; alt_esc = FALSE; key = esclen = 0; while ((ch = getch( )) == ERR) ; if (g_status.control_break) return( _CONTROL_BREAK ); if (ch >= 128) return( ch ); if (ch == 27) { while ((ch = getch()) != ERR) { if (esclen == 5) { while (getch() != ERR) ; goto go_again; } escape[esclen++] = ch; } if (esclen == 0) ch = 27; else if (esclen == 1) { alt_esc = TRUE; ch = escape[0]; } else { if (escape[0] == 27 && escape[1] == '[') { alt_esc = TRUE; key = 2; esclen -= 2; } else if (escape[0] == '[') { key = 1; --esclen; } else goto go_again; if (esclen > 3) goto go_again; k = esc_idx[esclen - 1].last; for (j = esc_idx[esclen - 1].first; j <= k; ++j) { if (memcmp( esc_seq[j].seq, escape + key, esclen ) == 0) { key = esc_seq[j].key; ch = 0; break; } } if (j > k) goto go_again; } } if (key == 0 && ch < 128) key = char_to_scan[ch]; if (xterm || (shift_state = kbReadShiftState( )) == ERROR) { shift_state = (alt_esc) ? _ALT : 0; shift_state |= key & ~511; } key &= 511; /* * separate control keys from their counterparts; unfortunately, this * doesn't allow the counterparts to be CTRLed (eg. ^I is indisting- * uishable from ^Tab). * In an xterm, use the normal key instead of the control key. */ if (ch == 8 || ch == 9 || ch == 13 || ch == 27) { if (xterm) shift_state &= ~_CTRL; if (!(shift_state & _CTRL)) { if (ch == 8) key = _BACKSPACE; else if (ch == 9) key = _TAB; else if (ch == 13) { if ((shift_state & _ALT) && !alt_esc) key = _GREY_ENTER; else key = _ENTER; } else /* if (ch == 27) */ key = _ESC; } } else if (xterm && ch == 127) { key = _DEL, ch = 0; /* * try and separate the keypad characters */ } else if (ch == '/' || ch == '*' || ch == '-' || ch == '+') { if (((shift_state & _ALT) && !alt_esc) || (shift_state & _CTRL)) { if (ch == '/') key = _GREY_SLASH; else if (ch == '*') key = _GREY_STAR; else if (ch == '-') key = _GREY_MINUS; else if (ch == '+') key = _GREY_PLUS; } else if (shift_state & _SHIFT) { if (ch == '/') key = _GREY_SLASH; else if (ch == '-') key = _GREY_MINUS; } } if (key >= _HOME && key <= _DEL) shift_state |= _FUNCTION; new_key = translate_key( key, shift_state, ch ); if (new_key == ERROR) goto go_again; return( new_key );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -