📄 sldostty.c
字号:
/* Copyright (c) 1992, 1999, 2001, 2002, 2003 John E. Davis * This file is part of the S-Lang library. * * You may distribute under the terms of either the GNU General Public * License or the Perl Artistic License. */#include "slinclud.h"#ifdef __DJGPP__# define _NAIVE_DOS_REGS#endif#include <dos.h>#if defined (__EMX__)# define int86 _int86# define delay _sleep2#endif /* __EMX__ */#if defined (__WATCOMC__)# include <conio.h># include <bios.h># define int86 int386#endif#if defined (__DJGPP__)# include <sys/farptr.h># include <go32.h># include <bios.h>#endif#ifndef _NKEYBRD_READ# define _NKEYBRD_READ 0x0#endif#ifndef _NKEYBRD_READY# define _NKEYBRD_READY 0x1#endif#ifndef _NKEYBRD_SHIFTSTATUS# define _NKEYBRD_SHIFTSTATUS 0x2#endif#define BIOSKEY slbioskey#if defined(__WATCOMC__)# define keyWaiting() _bios_keybrd(_NKEYBRD_READY)#else# define keyWaiting() BIOSKEY(_NKEYBRD_READY)#endif#ifndef __EMX__# define USE_MOUSE_CODE 1#else# define USE_MOUSE_CODE 0#endif#include "slang.h"#include "_slang.h"#ifdef __cplusplus# define _DOTS_ ...#else# define _DOTS_ void#endif#if !defined (__EMX__) && !defined (__GO32__) && !defined (__WATCOMC__)#define HAS_INT9#endif#ifdef __GO32__# include <signal.h>#endif#if defined (HAS_INT9)static void interrupt (*int9_old) (_DOTS_);static unsigned char far *shift = (unsigned char far *) 0x417;static unsigned int Abort_Scan_Code = 34; /* 34 = scan code for ^G *//*----------------------------------------------------------------------*\ * an interrupt 9 handler, not for use with most 32 bit compilers\*----------------------------------------------------------------------*/static void interrupt int9_handler (_DOTS_){ unsigned char s, s1; s1 = *shift & 0xF; /* ignore caps, ins, num lock, scroll lock */ s = inp (0x60); if (s1 & 0x04) /* control key */ { if (s == Abort_Scan_Code) { if (SLang_Ignore_User_Abort == 0) SLang_Error = SL_USER_BREAK; SLKeyBoard_Quit = 1; } } (*int9_old) ();}#endif /* HAS_INT9 */static void int9_change (int set){#if defined (HAS_INT9) if (set) /* install a new handler */ { if (int9_old != NULL) return; int9_old = getvect (9); setvect (9, int9_handler); } else if (int9_old != NULL) /* restore the old handler */ { setvect (9, int9_old); int9_old = NULL; }#else (void) set;#endif /* HAS_INT9 */}/*----------------------------------------------------------------------*\ * Function: static void set_ctrl_break (int state); * * set the control-break setting\*----------------------------------------------------------------------*/static void set_ctrl_break (int state){#if defined (__EMX__) (void) state; /* not really required */#else /* __EMX__ */ static int prev = 0;# if defined (__GO32__) if (state == 0) {# if __DJGPP__ >= 2 signal (SIGINT, SIG_IGN);# endif prev = getcbrk (); setcbrk (0); } else {# if __DJGPP__ >= 2 signal (SIGINT, SIG_DFL);# endif setcbrk (prev); }# else /* __GO32__ */# if defined(__WATCOMC__) fprintf (stderr, "Have not yet defined set_ctrl_break for __WATCOMC__\n"); prev = state;# else asm mov dl, byte ptr prev asm mov ax, state asm cmp ax, 0 asm jne L1 asm mov ah, 33h asm mov al, 0 asm mov dl, byte ptr prev asm int 21h asm xor ax, ax asm mov al, dl asm mov prev, ax asm mov dl, 0 L1: asm mov al, 1 asm mov ah, 33h asm int 21h# endif /* __WATCOMC__ */# endif /* __GO32__ */#endif /* __EMX__ */}/*----------------------------------------------------------------------*\ * static unsigned int slbioskey (int op); * * op 0-2 (standard) and 0x10-0x12 (extended) are valid * * 0, 0x10 _NKEYBRD_READ - read the key * 1, 0x11 _NKEYBRD_READY - check if a key is waiting * if so give a peek of its value, otherwise return 0 * 2, 0x12 _NKEYBRD_SHIFTSTATUS - get shift flags * (Ins, Cap, Num, Scroll, Alt, ^Ctrl L_shift, R_shift) * flags = ICNSA^LR only the lower byte is valid!\*----------------------------------------------------------------------*/static int bios_key_f = 0;static unsigned int slbioskey (int op){ union REGS r; r.h.ah = (op & 0x03) | bios_key_f; int86 (0x16, &r, &r);#if defined(__WATCOMC__) /* return (_bios_keybrd ((op & 0x03) | bios_key_f)); */# if 1 /* the correct zero flag for watcom? */ /* is zero flag set? (no key waiting) */ if ((op & _NKEYBRD_READY) && (r.x.cflag & 0x40) == 0x40) return 0;# else /* the correct zero flag for watcom? */ /* is zero flag set? (no key waiting) */ if ((op & _NKEYBRD_READY) && (r.x.cflag & 0x4)) return 0;# endif return (r.x.eax & 0xffff);#else /* is zero flag set? (no key waiting) */ if (op & _NKEYBRD_READY) { if ((r.x.flags & 0x40) == 0x40) return 0; if (r.x.ax == 0) /* CTRL-BREAK */ return -1; } return (r.x.ax & 0xffff);#endif}#if USE_MOUSE_CODE/*----------------------------------------------------------------------*\ * Simple mouse routines for 16/32-bit DOS-targets. * Gisle Vanem <giva@bgnett.no>\*----------------------------------------------------------------------*/#define HARD_MOUSE_RESET 0static int Have_Mouse = 0;static int Process_Mouse_Events = 0;/*----------------------------------------------------------------------*\ * peem_far_mem() *\*----------------------------------------------------------------------*/static unsigned long peek_dos_mem (unsigned long dos_addr, unsigned char *pentry){ unsigned long vector; unsigned char entry;#if defined(__DJGPP__)# define MAKE_LINEAR(seg,ofs) ((unsigned long)(((seg) << 4) + (ofs))) vector = _farpeekl (_dos_ds, dos_addr); entry = _farpeekb (_dos_ds, MAKE_LINEAR(vector >> 16, vector & 0xffff));#elif defined(__EMX__) vector = 0; entry = 0; /* to-do!! */#elif defined(__WATCOMC__) && defined(__FLAT__) /* wcc386 */ vector = *(unsigned long*) dos_addr; entry = *(unsigned char*) vector;#else vector = *(unsigned long far*) dos_addr; entry = *(unsigned char far*) vector;#endif if (pentry) *pentry = entry; return (vector);}/*----------------------------------------------------------------------*\ * mouse_pressed (int button, int *x_pos, int *y_pos) * * Return 1 if left (0) or right (1) mouse-button was pressed.\*----------------------------------------------------------------------*/static int mouse_pressed (int button, int *x_pos, int *y_pos){ union REGS r; r.x.ax = 5; r.x.bx = button; int86 (0x33, &r, &r); *x_pos = r.x.cx; *y_pos = r.x.dx; return (r.x.bx);}/*----------------------------------------------------------------------*\ * mouse_show (int show) * * Show (show=1) or hide (show=0) the mouse cursor\*----------------------------------------------------------------------*/static int mouse_show (int show){ union REGS r; if (Have_Mouse == 0) return -1; r.x.ax = show ? 1 : 2; int86 (0x33, &r, &r); return 0;}/*----------------------------------------------------------------------*\ * mouse_exit (void) * * Do a soft-reset of the mouse-driver (hides cursor)\*----------------------------------------------------------------------*/static void mouse_exit (void){ union REGS r; r.x.ax = 0x21; int86 (0x33, &r, &r);}/*----------------------------------------------------------------------*\ * mouse_init (void) * * Peek at mouse interrupt vector for a driver. * Do a soft/hard-reset of the mouse-driver. * Add a SLang atexit function\*----------------------------------------------------------------------*/static int mouse_init (void){ union REGS r; unsigned char entry = 0; unsigned long vector = peek_dos_mem (4*0x33, &entry); if (!vector || entry == 0xCF) /* NULL or points to IRET */ return -1;#if HARD_MOUSE_RESET r.x.ax = 0; /* mouse hard-reset and reinit */#else r.x.ax = 0x21; /* mouse soft-reset and reinit */#endif int86 (0x33, &r, &r); if (r.x.ax != 0xFFFF) return -1; (void) SLang_add_cleanup_function (mouse_exit); Have_Mouse = 1; return 0;}/*----------------------------------------------------------------------*\ * static int mouse_get_event (void); * * Poll mouse for changed button-state and encode x/y position and * button state into an escape sequence "\e[M.."\*----------------------------------------------------------------------*/static int mouse_get_event (void){ char buf [6]; int x, y; if (!Have_Mouse || Process_Mouse_Events == 0) return (0); if (mouse_pressed(0, &x, &y)) /* left button pressed? */ buf[3] = 040; else if (mouse_pressed(1, &x, &y)) /* right button pressed */ buf[3] = 041; else return (0);#if 0 /* test */ fprintf (stderr, "mouse_get_event: x=%d, y=%d\n", x, y);#endif /* * Taken from slw32tty.c / process_mouse_event(): * * We have a simple press or release. Encode it as an escape sequence * and buffer the result. The encoding is: * 'ESC [ M b x y' * where b represents the button state, and x,y represent the coordinates. * The ESC is handled by the calling routine. */ buf[0] = 27; buf[1] = '['; buf[2] = 'M'; buf[4] = 1 + ' ' + (x >> 3); /* textmode co-ordinates are 1/8th of */ buf[5] = 1 + ' ' + (y >> 3); /* graphics-mode co-ordinates */ if (SLang_buffer_keystring (buf, sizeof(buf)) < 0) return (0); return (1);}#endif /* USE_MOUSE_CODE *//*----------------------------------------------------------------------*\ * Function: int SLang_init_tty (int abort_char, int no_flow_control, * int opost); * * initialize the keyboard interface and attempt to set-up the interrupt 9 * handler if ABORT_CHAR is non-zero. * NO_FLOW_CONTROL and OPOST are only for compatiblity and are ignored.\*----------------------------------------------------------------------*/int SLang_init_tty (int abort_char, int no_flow_control, int opost){ (void) no_flow_control; (void) opost; bios_key_f = 0x10; /* assume it's an enhanced keyboard */#if defined (HAS_INT9) bios_key_f &= peekb (0x40,0x96); /* verify it's true */ if (abort_char > 0) Abort_Scan_Code = (unsigned int) abort_char;#else (void) abort_char;#endif set_ctrl_break (0); return 0;}/*----------------------------------------------------------------------*\ * Function: void SLang_reset_tty (void); * * reset the tty before exiting\*----------------------------------------------------------------------*/void SLang_reset_tty (void){ int9_change (0); set_ctrl_break (1);}/*----------------------------------------------------------------------*\ * Function: int _SLsys_input_pending (int tsecs); * * sleep for *tsecs tenths of a sec waiting for input\*----------------------------------------------------------------------*/int _SLsys_input_pending (int tsecs){ if (keyWaiting()) return 1; /* Convert tsecs to units of 20 ms */ tsecs = tsecs * 5; /* If tsecs is less than 0, it represents millisecs */ if (tsecs < 0) tsecs = -tsecs / 100; while ((tsecs > 0) && (SLang_Input_Buffer_Len == 0)) { delay (20); /* 20 ms or 1/50 sec */#if USE_MOUSE_CODE if (1 == mouse_get_event ()) return SLang_Input_Buffer_Len;#endif if (keyWaiting()) break; tsecs--; } return (tsecs);}/*----------------------------------------------------------------------*\ * Function: unsigned int _SLsys_getkey (void); * * Wait for and get the next available mouse-event / keystroke. * Also re-maps some useful keystrokes. * * Backspace (^H) => Del (127) * Ctrl-Space => ^@ (^@^3 - a pc NUL char) * extended keys are prefixed by a null character\*----------------------------------------------------------------------*/unsigned int _SLsys_getkey (void){ unsigned int key, scan, ch, shift; while ((SLang_Input_Buffer_Len == 0) && (0 == _SLsys_input_pending (300))) ; if (SLang_Input_Buffer_Len) return SLang_getkey (); key = BIOSKEY(_NKEYBRD_READ); ch = key & 0xff; scan = key >> 8; shift = BIOSKEY(_NKEYBRD_SHIFTSTATUS) & 0xf; if (key == 0x0e08) return 127; /* Backspace key */ switch (ch) { case 32: if (0 == (shift & 0x04)) break; /* ^space = ^@ */ scan = 3; /* send back Ctrl-@ => ^@^C */ /* drop */ case 0xe0: case 0: /* extended key code */ ch = _SLpc_convert_scancode (scan, 0, 1); } return (ch);}/*----------------------------------------------------------------------*\ * Function: void SLang_set_abort_signal (void (*handler)(int));\*----------------------------------------------------------------------*/int SLang_set_abort_signal (void (*handler)(int)){ if (handler == NULL) int9_change (1); return 0;}int SLtt_set_mouse_mode (int mode, int force){#if USE_MOUSE_CODE (void) force; if ((Have_Mouse == 0) && (-1 == mouse_init ())) { Process_Mouse_Events = 0; return -1; } Process_Mouse_Events = mode; return mouse_show (mode);#else (void) mode; (void) force; return -1;#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -