📄 console.c
字号:
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: 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( WINDOW *arg_filler )
{
s_output( "Next Key..", 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: 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( WINDOW *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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -