📄 minedio.c
字号:
* own low-level input routine since (at least with Turbo-C) the use * of getch () from conio.h makes the runtime system switch to normal * text mode on startup so that extended text modes could not be used. * This is really a very stupid chicane of Turbo-C. */int wincheck = 1;intgetch (){ union REGS Regs; int result; Regs.h.ah = 0x07; intdos (& Regs, & Regs); result = Regs.h.al; if (wincheck && checkwin ()) { winchg = TRUE; /* in MSDOS, RDwin calls getch, so it cannot be called directly here */ } return result;}voidset_video_lines (r)/* 0/1/2: 200/350/400 lines */ int r;{ union REGS Regs; Regs.h.ah = 0x12; Regs.h.bl = 0x30; Regs.h.al = r; int86 (0x10, & Regs, & Regs);}int font_height = 16;voidset_font_height (r)/* set font height in character pixels, <= 32 */ int r;{#define useintr#ifdef useintr struct REGPACK Regs; Regs.r_ax = 0x1130; Regs.r_bx = 0; intr (0x10, & Regs); Regs.r_ax = 0x1110; Regs.r_bx = r << 8; Regs.r_cx = 256; Regs.r_dx = 0;/* Regs.r_bp = 0; Regs.r_es = 0;*/ intr (0x10, & Regs);#else union REGS Regs; Regs.h.ah = 0x11; Regs.h.al = 0x10; Regs.h.bh = r; font_height = r; Regs.h.bl = 0; Regs.x.cx = 256; Regs.x.dx = 0;/* Regs.x.bp = 0; ignored by Turbo-C's int86 function *//* Regs.x.es = 0; not in structure but accepted by rotten C */ int86 (0x10, & Regs, & Regs);#endif}voidset_grafmode_height (r, l)/* 0/1/2: font height 8/14/16 ; 1/2/3/n: 14/25/43/n lines */ int r, l;{ union REGS Regs; Regs.h.ah = 0x11; if (r == 0) Regs.h.al = 0x23; else if (r == 1) Regs.h.al = 0x22; else Regs.h.al = 0x24; if (l <= 0) Regs.h.bl = 1; else if (l <= 3) Regs.h.bl = l; else { Regs.h.bl = 0; Regs.h.dl = l; } int86 (0x10, & Regs, & Regs);}voidset_fontbank (f)/* 0..7 */ int f;{ union REGS Regs; Regs.h.ah = 0x11; Regs.h.al = 0x03; Regs.h.bl = (f & 3) * 5 + (f & 4) * 12; int86 (0x10, & Regs, & Regs);}#ifdef conio#include <conio.h>FLAG can_add_line = TRUE, can_delete_line = TRUE, can_scroll_reverse = TRUE, can_clear_eol = TRUE;voidclear_screen (){ clrscr (); }voidclear_eol (){ clreol (); }voidscroll_forward (){ move_cursor (0, YMAX); putchar ('\n');}voidscroll_reverse (){ /* only called if cursor is at top of screen */ insline ();}voidadd_line (y) register int y;{ move_cursor (0, y); insline ();}voiddelete_line (y) register int y;{ move_cursor (0, y); delline ();}voidmove_cursor (x, y){ gotoxy (x + 1, y + 1);}voidreverse_on (){ highvideo ();}voidreverse_off (){ normvideo ();}voidstart_screen_mode (){}voidend_screen_mode (){}voidget_term (){ getwinsize ();}voidgetwinsize (){/* this has to be extended to request the current screen size */ struct text_info scrinfo; gettextinfo (& scrinfo); /* This seems to be a junk procedure since no other information than 25 * 80 comes out in 50 lines mode */ YMAX = scrinfo.screenheight - 1; XMAX = scrinfo.screenwidth - 1;}#else /* ndef conio - use ANSI driver: *//* adjust the following values to the capabilities of your ANSI driver: */FLAG can_add_line = TRUE, can_delete_line = TRUE, can_scroll_reverse = TRUE, can_clear_eol = TRUE;char CUP1 [] = "\033[1;1H";char CUD1 [] = "\033[B";char CUF1 [] = "\033[C";char DSR [] = "\033[6n";char ED2 [] = "\033[2J";char EL [] = "\033[K";char IL1 [] = "\033[L";char DL1 [] = "\033[M";voidclear_screen (){ putstring (ED2); }voidclear_eol (){ if (can_clear_eol == TRUE) putstring (EL);}voidscroll_forward (){ move_cursor (0, YMAX); putchar ('\n');}voidscroll_reverse (){ /* only called if cursor is at top of screen */ putstring (IL1);}voidadd_line (y) register int y;{ move_cursor (0, y); putstring (IL1);}voiddelete_line (y) register int y;{ move_cursor (0, y); putstring (DL1);}voidmove_cursor (x, y) register int x, y;{ static char s [11]; build_string (s, "\033[%d;%dH", y + 1, x + 1); putstring (s);}char reverse_on_str [30] = "\033[7m"; /* inverse mode */char reverse_off_str [30] = "\033[27m"; /* inverse off */voidreverse_on (){ putstring (reverse_on_str); /* 1m | 7m | 7m | 7;2m */}voidreverse_off (){ putstring (reverse_off_str); /* m | 0m | 0m 1m | m */}voidstart_screen_mode (){}voidend_screen_mode (){}FLAG noCPR = FALSE;intgetANSIpos ()/* returns FALSE if indicated position is upper left corner *//* also leaves position in XMAX+1, YMAX+1 *//* Checks characters input against ANSI CPR (cursor position report) sequence. If it does not comply, sets noCPR flag, does not check again and reports as if cursor had been moved. By this trick, we implement the following auxiliary behaviour: If an ANSI driver cannot deliver cursor reports, mined may be stuffed the screen size as its first input, at the positions of an ANSI CPR sequence but embedded in different characters, e.g. xx25x80xx */{ if (noCPR == TRUE) return 1; wincheck = 0; /* prevent recursive calls of checkwin and getANSIpos */ putstring (DSR); flush (); if (readchar () != '\033') noCPR = TRUE; if (readchar () != '[') noCPR = TRUE; if (get_digits (& YMAX) != ';') noCPR = TRUE; if (get_digits (& XMAX) != 'R') noCPR = TRUE; (void) readchar (); /* MSDOS ANSI drivers send a final return */ YMAX = YMAX - 1; XMAX = XMAX - 1; wincheck = 1; return YMAX != 0 || XMAX != 0;}intfailANSI (check)/* returns FALSE if control string does not change screen position */ char * check;{ putstring (CUP1); putstring (check); return getANSIpos ();}voidget_term (){ char * colstr = unnull (getenv ("MINEDCOL")); char * colrev = colstr; while (* colrev != '\0' && * colrev != ' ') colrev ++; if (* colrev == ' ') {* colrev = '\0'; colrev ++;}/* first do some harmless checks to set noCPR if simple ANSI driver *//* if (failANSI (EL)) can_clear_eol = FALSE; probably every driver can do this */ if (failANSI (DL1)) can_delete_line = FALSE; if (failANSI (IL1)) { can_add_line = FALSE; can_scroll_reverse = FALSE; }/* heuristics: if driver cannot delete line we assume if can neither set extended attributes like our default inverse and inverse off, so change the default */ if (can_delete_line == FALSE) { build_string (reverse_off_str, "\033[32;40m"); build_string (reverse_on_str, "\033[30;42m"); }/* if MINEDCOL set, use it for display attributes instead of defaults */ if (* colstr != '\0') build_string (reverse_off_str, "\033[%sm", colstr); if (* colrev != '\0') build_string (reverse_on_str, "\033[%sm", colrev);/* if cursor reports are available, check display attribute strings */ if (noCPR == FALSE) { if (failANSI (reverse_on_str)) panic ("Invalid control sequence for exposed display", NIL_PTR); if (failANSI (reverse_off_str)) panic ("Invalid control sequence for normal display", NIL_PTR); } getwinsize ();}voidgetwinsize (){#define stepcur 9 int oldx = -1; int oldy = -1; int i; if (noCPR == FALSE) { putstring (CUP1); XMAX = 0; YMAX = 0; do { for (i = 0; i < stepcur; i ++) { if (oldx < XMAX) putstring (CUF1); if (oldy < YMAX) putstring (CUD1); } oldx = XMAX + (stepcur - 1); oldy = YMAX + (stepcur - 1); (void) getANSIpos (); } while (oldx < XMAX || oldy < YMAX); } if (getenv ("LINES")) {make_number (& YMAX, getenv ("LINES")); YMAX --;} if (getenv ("COLUMNS")) {make_number (& XMAX, getenv ("COLUMNS")); XMAX --;} if (getenv ("NOCLEAREOL")) can_clear_eol = FALSE; /* for debugging *//* move_cursor (999, 999); *//* (void) getANSIpos (); */}#endif /* ndef conio */#endif /* def msdos *//**************************************************************************** * screen mode setting functions, alternatively by MSDOS BIOS calls or * ANSI sequences */int textmode_height = 2;#ifdef msdosvoidset_screen_mode (m) int m;{ union REGS Regs; if (m >= 0) { Regs.h.ah = 0x00; Regs.h.al = m; int86 (0x10, & Regs, & Regs); }}voidset_textmode_height (r)/* 0/1/2: font height 8/14/16 */ int r;{ union REGS Regs; Regs.h.ah = 0x11; Regs.h.bl = 0; textmode_height = r; if (r == 0) Regs.h.al = 0x12; else if (r == 1) Regs.h.al = 0x11; else Regs.h.al = 0x14; int86 (0x10, & Regs, & Regs);}#else /* ndef msdos - use ANSI driver: */int screen_mode = 3 /* just an assumption, cannot be determined */;voidset_screen_mode (m) int m;{ char resize_str [8]; if (m >= 0) { if (m != 50 && m != 43) screen_mode = m; build_string (resize_str, "\033[=%dh", m); putstring (resize_str); }}voidset_textmode_height (r)/* 0/1/2: font height 8/14/16 */ int r;{ textmode_height = r; if (r == 0) set_screen_mode (50); else if (r == 1) set_screen_mode (43); else set_screen_mode (screen_mode);}#endifvoidswitch_textmode_height (cycle)/* TRUE: cycle through font heights 8/14/16 FALSE: switch between font heights 8/16 */ FLAG cycle;{ if (textmode_height >= 2) set_textmode_height (0); else if (cycle == TRUE) set_textmode_height (textmode_height + 1); else set_textmode_height (2);}externstruct { int mode, cols, lins;} modetab [] /* in minedmp.c together with other configurable stuff */;voidresize_screen (sb, keep_columns) FLAG sb, keep_columns;{/* char resize_str [8]; */ int totalchars = (XMAX + 1) * (YMAX + 1); int newtotal = 0; int curtotal; int newmode = -1; int i; if (keep_columns == TRUE && ((sb == SMALLER && textmode_height > 0) || (sb == BIGGER && textmode_height < 2))) { if (sb == SMALLER) set_textmode_height (textmode_height - 1); else set_textmode_height (textmode_height + 1); } else { i = 0; while (modetab [i].mode >= 0) { curtotal = modetab [i].cols * modetab [i].lins; if (((sb == SMALLER && curtotal < totalchars && curtotal > newtotal) || (sb == BIGGER && curtotal > totalchars && (newtotal == 0 || curtotal < newtotal))) && (keep_columns == FALSE || modetab [i].cols == XMAX + 1)) { newtotal = curtotal; newmode = modetab [i].mode; } i ++; } if (newmode >= 0) { set_screen_mode (newmode); if (keep_columns == TRUE) if (sb == BIGGER) set_textmode_height (0); else set_textmode_height (2); } }}#endif /* ndef CURSES *//*------------------------------------------------------------------------*//* * Read a character from the operating system and handle interrupts. * Concerning problems due to the interference of read operations and * incoming signals (QUIT, WINCH) see the comments at readchar (). */intstrange (err) char * err;{ ring_bell (); error ("Read interrupted: ", err); sleep (1); ring_bell (); return QUITCHAR;}/* * Is a character available within msec milliseconds from file no fid? */intinputreadyafter (fid, msec) int fid; int msec;{#ifdef selectread int readfds; static struct timeval timeoutstru = {0, 0}; register int nfds; readfds = 1 << fid; timeoutstru.tv_usec = 1000 * msec; nfds = select (fid + 1, & readfds, 0, 0, & timeoutstru); return nfds;#else if (msec < 500) return 1; else return fid - fid;#endif}/* * Read a char from operating system, handle interrupts if possible, * handle window size changes if possible. */#ifdef selectreadint__readchar (){ uchar c; register int n; int readfds, exceptfds; do { if (winchg == TRUE) RDwin (); readfds = 1 << input_fd; exceptfds = readfds; select (input_fd + 1, & readfds, 0, & exceptfds, 0); if (exceptfds) { if (quit == TRUE) return QUITCHAR; else if (winchg == TRUE) ; else if (intr_char == TRUE) {intr_char = FALSE; return '\003';} else return strange ("exception"); } else#ifdef _getch_ return getch ();#else { if ((n = read (input_fd, & c, 1)) == 1) return c; else if ((n == 0) || (geterrno () != EINTR)) panicio ("Error during character input", serror ()); else return strange (serror ()); }#endif } while (TRUE);}#elseint__readchar (){ uchar c;#ifdef _getch_ c = getch (); if (intr_char == TRUE) {intr_char = FALSE; c = '\003';}#else if (read (input_fd, & c, 1) != 1 && quit == FALSE) { if (geterrno () == EINTR) return __readchar (); else panicio ("Error during character input", serror ()); }#endif if (quit == TRUE) c = QUITCHAR; return c;}#endif/*------------------------------------------------------------------------*/#ifdef vmsvoidget_term (){ get_term_cap (NIL_PTR);}voidgetwinsize (){/* Can this be determined on VMS? Any advise by someone? */}#endif /* vms */#ifdef unix/* * Get current window size */voidgetwinsize (){#ifdef TIOCGWINSZ struct winsize winsiz; ioctl (output_fd, TIOCGWINSZ, & winsiz); if (winsiz.ws_row != 0) YMAX = winsiz.ws_row - 1; if (winsiz.ws_col != 0) XMAX = winsiz.ws_col - 1;#else#ifdef TIOCGSIZE struct ttysize ttysiz; ioctl (output_fd, TIOCGSIZE, & ttysiz); if (ttysiz.ts_lines != 0) YMAX = ttysiz.ts_lines - 1; if (ttysiz.ts_cols != 0) XMAX = ttysiz.ts_cols - 1;#else#ifdef WIOCGETD struct uwdata uwdat; ioctl (output_fd, WIOCGETD, & uwdat); if (uwdat.uw_height > 0) YMAX = uwdat.uw_height / uwdat.uw_vs - 1; if (uwdat.uw_width > 0) XMAX = uwdat.uw_width / uwdat.uw_hs - 1;#else/* Who can tell me how to do this on different systems? */#endif#endif#endif}/* * Get terminal information */voidget_term (){ char * TERMname = getenv ("TERM"); if (TERMname == NIL_PTR) panic ("Terminal not specified", NIL_PTR); get_term_cap (TERMname);/* build_string (text_buffer, "Terminal is %s, %d * %d.\n", TERMname, YMAX+1, XMAX+1); putstring (text_buffer); */}#endif /* unix *//* ================================================================== * * End * * ================================================================== */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -