📄 console.c
字号:
_F1, _F2, _F3, _F4, _F5, _F6, _F7, _F8, _F9, _F10, /* Shift */ _F1, _F2, _F3, _F4, _F5, _F6, _F7, _F8, _F9, _F10, /* Ctrl (unused) */ _F1, _F2, _F3, _F4, _F5, _F6, _F7, _F8, _F9, _F10, /* Alt */ _PRTSC, /* Ctrl */ _LEFT, _RIGHT, _END, _PGDN, _HOME, /* Ctrl (unused) */ _1, _2, _3, _4, _5, _6, _7, _8, _9, _0, _MINUS, _EQUALS, /* Alt */ _PGUP, /* Ctrl */ _F11, _F12, _F11, _F12, _F11, _F12, _F11, _F12, /* plain Shift Ctrl Alt */ _UP, _GREY_MINUS, _CENTER, _GREY_PLUS, _DOWN, /* Ctrl (unused) */ _INS, _DEL, _TAB, _GREY_SLASH, _GREY_STAR, /* Ctrl (unused) */ _HOME, _UP, _PGUP, 0, _LEFT, 0, _RIGHT, 0, _END, /* Alt */ _DOWN, _PGDN, _INS, _DEL, _GREY_SLASH, _TAB, _GREY_ENTER /* Alt */};extern volatile unsigned int far kbd_shift; /* defined in dos/kbdint.asm */extern volatile unsigned char far kbd_menu; /* ditto *//* * Name: getkey * Purpose: get keyboard input * Author: Jason Hood * Date: August 17, 2002 * 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. * * This function works in conjunction with a keyboard interrupt * handler installed in dos/kbdint.asm. * * 020903: updated to reflect the new translate_key(). */long getkey( void ){unsigned key;register int scan, ch;long kee;go_again: kbd_shift &= ~_FUNCTION; /* turn off any previous extended key */ /* * 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 )) if (kbd_menu) { kbd_menu = FALSE; return( PullDown | _FUNCTION ); } /* * _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 ); /* * 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 &= 0xff00; kbd_shift |= _FUNCTION; } } else key = _bios_keybrd( 0 ); if (key == 0xffffU) return( _CONTROL_BREAK ); scan = (key & 0xff00) >> 8; ch = key & 0x00ff; /* * 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." */ if (scan == 0xe0) { if (ch == 13) { scan = _GREY_ENTER; ch = 0; } else if (ch == '/') scan = _GREY_SLASH; /* * Remap the BIOS scan code to the hardware. */ } else if (scan >= 0x54 && scan <= 0xA6) scan = bios_to_scan[scan - 0x54]; /* * 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? */ else if (scan == 0 || scan >= 0x80) return( ch ); /* * Convert the scan code to the function key. */ else { scan += 255; /* * Special case for Alt+KP0 to enter the NUL character, and to * test for AltGr characters. */ if (kbd_shift & _ALT) { if (scan == _INS && !(kbd_shift & _FUNCTION)) return( 0 ); if (ch != 0) return( ch ); } } kee = translate_key( scan, kbd_shift, (text_t)ch ); if (kee == ERROR) goto go_again; return( kee );}/* * Name: waitkey * Purpose: call the BIOS keyboard status subfunction * Date: October 31, 1992 * Modified: August 11, 1997, Jason Hood - Borland (BC3.1) falsely returns 0 * for Ctrl-Break; it should be -1 * 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 ){#if defined( __TURBOC__ ) return( (_bios_keybrd( enh_keyboard ? 0x11 : 0x01 ) == 0 && !g_status.control_break) ? 1 : 0 );#else return( _bios_keybrd( enh_keyboard ? 0x11 : 0x01 ) == 0 ? 1 : 0 );#endif}#if defined( __MSC__ )/* * Name: getcbrk * Purpose: get the control-break checking flag * Author: Jason Hood * Date: October 23, 2002 * Returns: the state of the flag */static int getcbrk( void ){union REGS regs; regs.h.ah = 0x33; regs.h.al = 0; intdos( ®s, ®s ); return( regs.h.dl );}/* * Name: setcbrk * Purpose: set the control-break checking flag * Author: Jason Hood * Date: October 23, 2002 * Passed: flag: the new state */static void setcbrk( int flag ){union REGS regs; regs.h.ah = 0x33; regs.h.al = 1; regs.h.dl = (char)flag; intdos( ®s, ®s );}#endif/* * Name: harmless * Purpose: Do nothing when control-C is pressed * Date: June 5, 1991 * Notes: Interrupt 23, the Control-C handler, is a MS DOS system function. * Since we want to use Control-C as a regular function key, * let's do absolutely nothing when Control-C is pressed. */#if defined( __MSC__ )static void interrupt harmless( void ){}#elsestatic int harmless( void ){ return 1;}#endif/* * Name: ctrl_break * Purpose: Set our control-break flag when control-break is pressed. * Date: June 5, 1992 * Notes: Control-break is a little different from Control-C. When * Control-C is pressed, MS DOS processes it as soon as possible, * which may be quite a while. On the other hand, when * Control-break is pressed on IBM and compatibles, interrupt 0x1b * is generated immediately. Since an interrupt is generated * immediately, we can gain control of run-away functions, like * recursive macros, by checking our Control-break flag. */void interrupt ctrl_break( void ){ g_status.control_break = TRUE;}/* * Name: capslock_active * Purpose: To find out if Caps Lock is active * Date: September 1, 1993 * Author: Byrial Jensen * Returns: Non zero if Caps Lock is active, * Zero if Caps Lock is not active. * Note: The function reads directly the BIOS variable * at address 0040h:0017h bit 6 */int capslock_active( void ){ return( (int)( *((unsigned char far *)0x00400017L) & 0x40 ) );}/* * Name: numlock_active * Purpose: To find out if Num Lock is active * Date: September 3, 2002 * Returns: Non zero if Num Lock is active, * Zero if Num Lock is not active. * Note: Same as Caps Lock, but using bit 5. */int numlock_active( void ){ return( (int)( *((unsigned char far *)0x00400017L) & 0x20 ) );}/* * 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 ); }}/* Name: page * Purpose: Change the text screen page * Author: Jason Hood * Date: December 28, 1996 * Passed: payg: desired page number * Notes: use standard BIOS video interrupt 0x10 to set the set. */void page( unsigned char payg ){union REGS inregs, outregs; inregs.h.ah = 5; inregs.h.al = payg; int86( VIDEO_INT, &inregs, &outregs );}/* * 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. * * jmh 991026: (-1, -1) doesn't work for (my) 132-column mode. Use one * more than the screen height, instead. */void xygoto( int col, int line ){union REGS inregs, outregs; if (col < 0 || line < 0) { col = 0; line = g_display.nlines; } inregs.h.ah = 2; inregs.h.bh = 1; /* jmh - the editor is on page 1 */ inregs.h.dh = (unsigned char)line; inregs.h.dl = (unsigned char)col; int86( VIDEO_INT, &inregs, &outregs );}/* * Name: display_line * Purpose: display a line in the file * Author: Jason Hood * Date: October 27, 1999 * Passed: text: characters to display * attr: attributes to use * len: length to display * line: row of display * col: column of display * Notes: all parameters are assumed valid (and len > 0). * Assumes text and attr to be in the same segment. */void display_line( text_ptr text, unsigned char *attr, int len, int line, int col ){char *screen_ptr = SCREEN_PTR( line, col ); ASSEMBLE { push ds push si push di les di, screen_ptr lds si, text mov bx, WORD PTR attr mov cx, len } char_out: ASSEMBLE { lodsb mov ah, [bx] inc bx stosw dec cx jnz char_out pop di pop si pop ds }}/* * 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 ){char *screen_ptr = SCREEN_PTR( line, col ); ASSEMBLE { les bx, screen_ptr /* load SEGMENT+OFFSET of screen ptr */ mov al, BYTE PTR c /* get character */ mov ah, BYTE PTR attr /* get attribute */ mov es:[bx], ax /* show char on screen */ }}/* * Name: c_repeat * Purpose: Output one character many times * Author: Jason Hood * Date: November 18, 2003 * Passed: c: character to output to screen * cnt: number of times to output it * col: column to display character * line: line number to display character * attr: attribute of character * Notes: if the count is negative, repeat the row, not the column. */void c_repeat( int c, int cnt, int col, int line, int attr ){char *screen_ptr = SCREEN_PTR( line, col );int max_col = g_display.ncols;int max_row = g_display.nlines; ASSEMBLE { push di mov cx, cnt test cx, cx jg fill_row neg cx mov ax, max_row sub ax, line mov bx, max_col shl bx, 1 jmp test_count }fill_row: ASSEMBLE { mov ax, max_col sub ax, col mov bx, 2 }test_count: ASSEMBLE { cmp cx, ax /* is count within the maximum? */ jle display mov cx, ax }display: ASSEMBLE {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -