📄 console.c
字号:
/*
#include "tdestr.h"
#include "common.h"
#include "define.h"
#include "tdefunc.h"
#include <bios.h> /* for direct BIOS keyboard input */
/*******************************************************/
/* */
/* 1) initialize the video and keyboard structures */
/* */
/*******************************************************/
/*
* 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.
*/
_fmemmove( 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 );
}
/*********************************************/
/* */
/* 2) keyboard i/o routines, PC specific */
/* */
/*********************************************/
/*
* 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 buff[MAX_COLS];
* ultoa( _memavl( ), buff, 10 );
* s_output( "h= ", g_display.mode_line, 37, g_display.mode_color );
* s_output( buff, 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.
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -