📄 window.c
字号:
/* window.c - Handle I/O to terminal */#include "vt.h"#include <sys/ioctl.h>#include <errno.h>#ifdef USE_STDARG#include <stdarg.h>#else#include <varargs.h>#endif#ifdef hpux#include <termio.h>#else /* not HP-UX */#ifdef SYSVTTY#include <termio.h>#else /* BSD */#include <sgtty.h>#endif#endif#ifdef PROTOTYPES#ifdef TERMCAPstatic void chrpt(int, int);static void get_ospeed(void);static void output_one(int);static void getccap(char *, char *);static void tp(char *, int);#endif /* TERMCAP */static void cap_formatted(char *, int, int);static void clear_end(int);static void clear_space(int, int);static void move_left(int, int);static void init_window(Unode *, int, int);static void mark(Unode *, int);static void draw_prompt(void);static void clear_input_window(void);#else /* not PROTOTYPES */#ifdef TERMCAPstatic void get_ospeed(), output_one(), getccap(), tp();#endif /* TERMCAP */static void chrpt(), cap_formatted(), clear_end(), clear_space(), move_left();static void init_window(), mark(), draw_prompt(), clear_input_window();#endif /* not PROTOTYPES */extern int errno;extern char *sys_errlist[];/* Global variables and externs for the terminal routines *//* The termcap library has no length-checking facilities. We use 32** bytes for a string that's not pre-compiled with tputs(), and 64** bytes for one that is. This is somewhat kludgy, but then, so are** the termcap routines. */static char s_cmove[32]; /* Move cursor */static char s_scroll[32]; /* Set scroll area */static char s_scr_rev[32]; /* Scroll region reverse */char s_clrscr[64]; /* Clear screen */char s_clreol[64]; /* Clear to end of line */char s_bold_on[64]; /* Turn boldface on */char s_bold_off[64]; /* Turn boldface off */#ifdef HARDCODE#define HC_CMOVE "\033[%d;%dH"#define HC_SCROLL "\033[%d;%dr"#define HC_SCR_REV "\033M"#define HC_CLRSCR "\033[2J"#define HC_CLREOL "\033[K"#define HC_BOLD_ON "\033[1m"#define HC_BOLD_OFF "\033[m"#define cap_normal(x, y) Bwritea(x)#endif#define HC_ROWS 24#define HC_COLS 80int rows = 0, cols = 0; /* Screen size */static int scr_top = -1, scr_bot = -1; /* Current scroll area */#ifdef TERMCAPstatic char *cptr;extern char *tgetstr(), *tgoto();#ifndef AIXextern short ospeed;#endif /* not AIX */#define cap_normal(x, y) tp(x, y)#endif /* TERMCAP *//* Global variables for windowing routines */#define CURS_INPUT 0#define CURS_WINDOW 1#define CURS_ELSEWHERE 2Unode win_ring; /* Dummy node in windows ring */Unode *active_win; /* Keyboard text is sent here */Unode *cur_win = NULL; /* Where text is being processed */int curs_loc = CURS_ELSEWHERE; /* General idea of where cursor is */static Unode *curs_win; /* More info for CURS_WINDOW pos */extern Unode *cur_rmt;static String outbuf = { { "", 0 }, 0 };/* Output buffering */#define Die(s) if (1) { puts(s); exit(1); } else#define Bwrite(cstr) s_cat(&outbuf, cstr)#define Bwritea(s) s_acat(&outbuf, s)#define Bwriteal(s, l) s_cat(&outbuf, cstr_sl(s, l))#define Bwritem(s, y, z) Bwriteal(s, min(y, z))#define Bputch(c) s_add(&outbuf, c)#define Bflush if (1) { vtwrite(outbuf.c); s_term(&outbuf, 0); } elsevoid bflushfunc() { Bflush; }/* Global variables for input routines */int icol; /* Column of cursor on bottom line */char *prompt; /* Text of prompt */int plen = 0; /* Length of prompt */int vtc_mode = 0; /* Flag: input window in VTC mode */extern String kbuf;extern int kpos;static int echo_mode = 1;#define Divider (win_ring.prev->Wbot + 1)#define Itop (Divider + 1)#define Isize (rows - Itop)#define Margin (cols - 1)#define Round(x, y) ((x) - (x) % (y))#define Klen (kbuf.c.l)#define Kptr (kbuf.c.s)#define Oplen (vtc_mode ? 0 : plen)#define Iscr_rev if (1) { \ if (Isize > 1) { scroll(Itop, rows - 1); scr_rev(1); } \ else { cmove(0, rows - 1); Bwritea(s_clreol); } \} else#define Iscr_fwd if (1) { \ if (Isize > 1) { scroll(Itop, rows - 1); scr_fwd(1); } \ else { cmove(0, rows - 1); Bwritea(s_clreol); } \} else/* Low-level I/O */void vtwrite(cstr) Cstr cstr;{ int written; while (cstr.l > 0) { written = write(1, cstr.s, cstr.l); if (written == -1) { if (errno != EWOULDBLOCK && errno != EINTR) { perror("write"); vterror("Write failed in vtwrite()"); } written = 0; } cstr = cstr_sl(cstr.s + written, cstr.l - written); if (cstr.l) sleep(1); }}static void chrpt(c, num) int c, num;{ while (num-- > 0) Bputch(c);}int getch(){ char c; int rs; while ((rs = read(0, &c, 1)) <= 0) { if (rs < 0 && errno != EINTR) { perror("read"); vterror("Read failed in getch()"); } } return c;}void tty_mode(state) int state;{#ifdef hpux struct termio blob; if (ioctl(0, TCGETA, &blob) == -1) { perror("TCGETA ioctl()"); exit(1); } if (state) { blob.c_lflag &= ~ECHO; blob.c_lflag &= ~ECHOE; blob.c_lflag &= ~ICANON; blob.c_cc[VMIN] = 0; blob.c_cc[VTIME] = 0; } else { blob.c_lflag |= ECHO; blob.c_lflag |= ECHOE; blob.c_lflag |= ICANON; } ioctl(0, TCSETAF, &blob);#else /* Not HP-UX */#ifdef SYSVTTY struct termio blob; static struct termio old_tty_state; static int first = 1; if (first) { ioctl(0, TCGETA, &old_tty_state); first = 0; } if (state) { ioctl(0, TCGETA, &blob); blob.c_cc[VMIN] = 0; blob.c_cc[VTIME] = 0; blob.c_iflag = IGNBRK | IGNPAR | ICRNL; blob.c_oflag = OPOST | ONLCR; blob.c_lflag = ISIG; ioctl(0, TCSETA, &blob); } else if (!first) ioctl(0, TCSETA, &old_tty_state);#else /* BSD */ struct sgttyb blob; if (ioctl(0, TIOCGETP, &blob) == -1) { perror("TIOCGETP ioctl()"); exit(1); } blob.sg_flags |= state ? CBREAK : ECHO; blob.sg_flags &= state ? ~ECHO : ~CBREAK; ioctl(0, TIOCSETP, &blob);#endif#endif}/* Terminal routines */#ifdef TERMCAPstatic void get_ospeed(){#ifndef hpux#ifndef AIX struct sgttyb sgttyb; ioctl(0, TIOCGETP, &sgttyb); ospeed = sgttyb.sg_ospeed;#endif#endif}static void output_one(c) int c;{ *cptr++ = c;}static void gettcap(dest, cap) char *dest, *cap;{ if (!tgetstr(cap, &dest)) Die("Insufficient terminal capabilities.");}static void getccap(dest, cap) char *dest, *cap;{ char temp[64]; gettcap(temp, cap); cptr = dest; tputs(temp, 1, output_one); *cptr = '\0';}#endifvoid init_term(){#ifdef HARDCODE strcpy(s_cmove , HC_CMOVE ); strcpy(s_scroll , HC_SCROLL ); strcpy(s_scr_rev , HC_SCR_REV ); strcpy(s_clrscr , HC_CLRSCR ); strcpy(s_clreol , HC_CLREOL ); strcpy(s_bold_on , HC_BOLD_ON ); strcpy(s_bold_off , HC_BOLD_OFF); rows = HC_ROWS; cols = HC_COLS;#else /* HARDCODE not defined */ char tinfo[1024], *termname, *bon, *boff; bon = getenv("VTBOLDON"); if (!bon) bon = "md"; boff = getenv("VTBOLDOFF"); if (!boff) boff = "me"; termname = getenv("TERM"); if (!termname) Die("TERM not set"); if (tgetent(tinfo, termname) != 1) Die("Terminal type not defined."); rows = tgetnum("li"); if (rows == -1) rows = HC_ROWS; cols = tgetnum("co"); if (cols == -1) cols = HC_COLS; get_ospeed(); gettcap(s_cmove , "cm"); gettcap(s_scroll , "cs"); gettcap(s_scr_rev , "sr"); getccap(s_clrscr , "cl"); getccap(s_clreol , "ce"); getccap(s_bold_on , bon); getccap(s_bold_off , boff);#endif /* HARDCODE not defined */#ifdef TIOCGWINSZ { struct winsize size; ioctl(0, TIOCGWINSZ, &size); if (size.ws_row && size.ws_col) { rows = size.ws_row; cols = size.ws_col; } }#endif /* TIOCGWINSZ */ prompt = vtstrdup("");}#ifdef TERMCAPstatic void bfuncputch(c) int c; { s_fadd(&outbuf, c); }static void tp(s, affcnt) char *s; int affcnt;{ tputs(s, affcnt, bfuncputch); s_nt(&outbuf);}#endifstatic void cap_formatted(cbuf, arg1, arg2) char *cbuf; int arg1, arg2;{#ifdef HARDCODE static char buffer[24]; sprintf(buffer, cbuf, arg2 + 1, arg1 + 1); Bwritea(buffer);#else tp(tgoto(cbuf, arg1, arg2), 1);#endif}void cmove(col, row) int col, row;{ cap_formatted(s_cmove, col, row);}void scroll(top, bottom) int top, bottom;{ if (scr_top == top && scr_bot == bottom) return; cap_formatted(s_scroll, bottom, top); scr_top = top; scr_bot = bottom;}void scr_fwd(num) int num;{ cmove(0, scr_bot); while (num--) Bputch('\n');}void scr_rev(num) int num;{ cmove(0, scr_top); while (num--) cap_normal(s_scr_rev, scr_bot - scr_top + 1);}/* Slightly higher-level termcap routines */static void clear_end(len) int len;{ if (len > 1) Bwritea(s_clreol); else if (len == 1) Bwritea(" \010");}static void clear_space(top, bottom) int top, bottom;{ int i; scroll(0, rows - 1); cmove(0, top); Bwritea(s_clreol); for (i = top; i < bottom; i++) { Bputch('\n'); Bwritea(s_clreol); } Bflush;}static void move_left(n, new) int n, new;{ if (n < 7) chrpt('\010', n); else cmove(new, rows - 1);}/* Windowing routines *//* Ensure that cursor and scroll area are in window */void curs_window(win) Unode *win;{ if (curs_loc == CURS_WINDOW && curs_win == win) return; scroll(win->Wtop, win->Wbot); cmove(win->Wcol, win->Wbot); Bflush; curs_loc = CURS_WINDOW; curs_win = win;}/* Ensure that cursor is in input window */void curs_input(){ if (curs_loc == CURS_INPUT) return; cmove(icol, rows - 1); Bflush; curs_loc = CURS_INPUT;}static void init_window(win, top, bottom) Unode *win; int top, bottom;{ win->Wtop = top; win->Wbot = bottom; win->Wcol = win->Wnl = 0; win->Wrmt = NULL; win->Wtermread = NULL; win->Wobj = NULL; win->Wghstack = NULL; win->Wglstack = NULL; win->Wrstack = NULL;}void draw_Divider(win) Unode *win;{ scroll(0, rows - 1); cmove(0, win->Wbot + 1); Bputch((win == active_win) ? '*' : '_'); chrpt('_', win->next->dummy ? cols - 6 : cols - 1); if (win->next->dummy) Bwritea(vtc_mode ? "VTC__" : "Text_"); Bflush; curs_loc = CURS_ELSEWHERE;}void toggle_imode(){ scroll(0, rows - 1); vtc_mode = !vtc_mode; cmove(cols - 5, Divider); Bwritea(vtc_mode ? "VTC__" : "Text_"); curs_loc = CURS_ELSEWHERE; if (plen) { clear_input_window(); draw_prompt(); input_draw(); }}static void mark(win, value) Unode *win; int value;{ cmove(0, win->Wbot + 1); Bputch(value ? '*' : '_'); Bflush; curs_loc = CURS_ELSEWHERE;}void init_screen(){ Unode *first_win; first_win = unalloc(); init_window(first_win, 0, rows - 5); win_ring.next = win_ring.prev = first_win; win_ring.dummy = 1; first_win->next = first_win->prev = &win_ring; active_win = first_win;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -