📄 term.c
字号:
* move to line <where> (first line == 0) * as efficiently as possible */protected voidterm_move_to_line(EditLine *el, int where){ int del; if (where == el->el_cursor.v) return; if (where > el->el_term.t_size.v) {#ifdef DEBUG_SCREEN (void) fprintf(el->el_errfile, "term_move_to_line: where is ridiculous: %d\r\n", where);#endif /* DEBUG_SCREEN */ return; } if ((del = where - el->el_cursor.v) > 0) { while (del > 0) { if (EL_HAS_AUTO_MARGINS && el->el_display[el->el_cursor.v][0] != '\0') { /* move without newline */ term_move_to_char(el, el->el_term.t_size.h - 1); term_overwrite(el, &el->el_display[el->el_cursor.v][el->el_cursor.h], 1); /* updates Cursor */ del--; } else { if ((del > 1) && GoodStr(T_DO)) { (void) tputs(tgoto(Str(T_DO), del, del), del, term__putc); del = 0; } else { for (; del > 0; del--) term__putc('\n'); /* because the \n will become \r\n */ el->el_cursor.h = 0; } } } } else { /* del < 0 */ if (GoodStr(T_UP) && (-del > 1 || !GoodStr(T_up))) (void) tputs(tgoto(Str(T_UP), -del, -del), -del, term__putc); else { if (GoodStr(T_up)) for (; del < 0; del++) (void) tputs(Str(T_up), 1, term__putc); } } el->el_cursor.v = where;/* now where is here */}/* term_move_to_char(): * Move to the character position specified */protected voidterm_move_to_char(EditLine *el, int where){ int del, i;mc_again: if (where == el->el_cursor.h) return; if (where > el->el_term.t_size.h) {#ifdef DEBUG_SCREEN (void) fprintf(el->el_errfile, "term_move_to_char: where is riduculous: %d\r\n", where);#endif /* DEBUG_SCREEN */ return; } if (!where) { /* if where is first column */ term__putc('\r'); /* do a CR */ el->el_cursor.h = 0; return; } del = where - el->el_cursor.h; if ((del < -4 || del > 4) && GoodStr(T_ch)) /* go there directly */ (void) tputs(tgoto(Str(T_ch), where, where), where, term__putc); else { if (del > 0) { /* moving forward */ if ((del > 4) && GoodStr(T_RI)) (void) tputs(tgoto(Str(T_RI), del, del), del, term__putc); else { /* if I can do tabs, use them */ if (EL_CAN_TAB) { if ((el->el_cursor.h & 0370) != (where & 0370)) { /* if not within tab stop */ for (i = (el->el_cursor.h & 0370); i < (where & 0370); i += 8) term__putc('\t'); /* then tab over */ el->el_cursor.h = where & 0370; } } /* * it's usually cheaper to just write the * chars, so we do. */ /* * NOTE THAT term_overwrite() WILL CHANGE * el->el_cursor.h!!! */ term_overwrite(el, &el->el_display[el->el_cursor.v][el->el_cursor.h], where - el->el_cursor.h); } } else { /* del < 0 := moving backward */ if ((-del > 4) && GoodStr(T_LE)) (void) tputs(tgoto(Str(T_LE), -del, -del), -del, term__putc); else { /* can't go directly there */ /* * if the "cost" is greater than the "cost" * from col 0 */ if (EL_CAN_TAB ? (-del > (((unsigned int) where >> 3) + (where & 07))) : (-del > where)) { term__putc('\r'); /* do a CR */ el->el_cursor.h = 0; goto mc_again; /* and try again */ } for (i = 0; i < -del; i++) term__putc('\b'); } } } el->el_cursor.h = where; /* now where is here */}/* term_overwrite(): * Overstrike num characters */protected voidterm_overwrite(EditLine *el, const char *cp, int n){ if (n <= 0) return; /* catch bugs */ if (n > el->el_term.t_size.h) {#ifdef DEBUG_SCREEN (void) fprintf(el->el_errfile, "term_overwrite: n is riduculous: %d\r\n", n);#endif /* DEBUG_SCREEN */ return; } do { term__putc(*cp++); el->el_cursor.h++; } while (--n); if (el->el_cursor.h >= el->el_term.t_size.h) { /* wrap? */ if (EL_HAS_AUTO_MARGINS) { /* yes */ el->el_cursor.h = 0; el->el_cursor.v++; if (EL_HAS_MAGIC_MARGINS) { /* force the wrap to avoid the "magic" * situation */ char c; if ((c = el->el_display[el->el_cursor.v][el->el_cursor.h]) != '\0') term_overwrite(el, &c, 1); else term__putc(' '); el->el_cursor.h = 1; } } else /* no wrap, but cursor stays on screen */ el->el_cursor.h = el->el_term.t_size.h; }}/* term_deletechars(): * Delete num characters */protected voidterm_deletechars(EditLine *el, int num){ if (num <= 0) return; if (!EL_CAN_DELETE) {#ifdef DEBUG_EDIT (void) fprintf(el->el_errfile, " ERROR: cannot delete \n");#endif /* DEBUG_EDIT */ return; } if (num > el->el_term.t_size.h) {#ifdef DEBUG_SCREEN (void) fprintf(el->el_errfile, "term_deletechars: num is riduculous: %d\r\n", num);#endif /* DEBUG_SCREEN */ return; } if (GoodStr(T_DC)) /* if I have multiple delete */ if ((num > 1) || !GoodStr(T_dc)) { /* if dc would be more * expen. */ (void) tputs(tgoto(Str(T_DC), num, num), num, term__putc); return; } if (GoodStr(T_dm)) /* if I have delete mode */ (void) tputs(Str(T_dm), 1, term__putc); if (GoodStr(T_dc)) /* else do one at a time */ while (num--) (void) tputs(Str(T_dc), 1, term__putc); if (GoodStr(T_ed)) /* if I have delete mode */ (void) tputs(Str(T_ed), 1, term__putc);}/* term_insertwrite(): * Puts terminal in insert character mode or inserts num * characters in the line */protected voidterm_insertwrite(EditLine *el, char *cp, int num){ if (num <= 0) return; if (!EL_CAN_INSERT) {#ifdef DEBUG_EDIT (void) fprintf(el->el_errfile, " ERROR: cannot insert \n");#endif /* DEBUG_EDIT */ return; } if (num > el->el_term.t_size.h) {#ifdef DEBUG_SCREEN (void) fprintf(el->el_errfile, "StartInsert: num is riduculous: %d\r\n", num);#endif /* DEBUG_SCREEN */ return; } if (GoodStr(T_IC)) /* if I have multiple insert */ if ((num > 1) || !GoodStr(T_ic)) { /* if ic would be more expensive */ (void) tputs(tgoto(Str(T_IC), num, num), num, term__putc); term_overwrite(el, cp, num); /* this updates el_cursor.h */ return; } if (GoodStr(T_im) && GoodStr(T_ei)) { /* if I have insert mode */ (void) tputs(Str(T_im), 1, term__putc); el->el_cursor.h += num; do term__putc(*cp++); while (--num); if (GoodStr(T_ip)) /* have to make num chars insert */ (void) tputs(Str(T_ip), 1, term__putc); (void) tputs(Str(T_ei), 1, term__putc); return; } do { if (GoodStr(T_ic)) /* have to make num chars insert */ (void) tputs(Str(T_ic), 1, term__putc); /* insert a char */ term__putc(*cp++); el->el_cursor.h++; if (GoodStr(T_ip)) /* have to make num chars insert */ (void) tputs(Str(T_ip), 1, term__putc); /* pad the inserted char */ } while (--num);}/* term_clear_EOL(): * clear to end of line. There are num characters to clear */protected voidterm_clear_EOL(EditLine *el, int num){ int i; if (EL_CAN_CEOL && GoodStr(T_ce)) (void) tputs(Str(T_ce), 1, term__putc); else { for (i = 0; i < num; i++) term__putc(' '); el->el_cursor.h += num; /* have written num spaces */ }}/* term_clear_screen(): * Clear the screen */protected voidterm_clear_screen(EditLine *el){ /* clear the whole screen and home */ if (GoodStr(T_cl)) /* send the clear screen code */ (void) tputs(Str(T_cl), Val(T_li), term__putc); else if (GoodStr(T_ho) && GoodStr(T_cd)) { (void) tputs(Str(T_ho), Val(T_li), term__putc); /* home */ /* clear to bottom of screen */ (void) tputs(Str(T_cd), Val(T_li), term__putc); } else { term__putc('\r'); term__putc('\n'); }}/* term_beep(): * Beep the way the terminal wants us */protected voidterm_beep(EditLine *el){ if (GoodStr(T_bl)) /* what termcap says we should use */ (void) tputs(Str(T_bl), 1, term__putc); else term__putc('\007'); /* an ASCII bell; ^G */}#ifdef notdef/* term_clear_to_bottom(): * Clear to the bottom of the screen */protected voidterm_clear_to_bottom(EditLine *el){ if (GoodStr(T_cd)) (void) tputs(Str(T_cd), Val(T_li), term__putc); else if (GoodStr(T_ce)) (void) tputs(Str(T_ce), Val(T_li), term__putc);}#endif/* term_set(): * Read in the terminal capabilities from the requested terminal */protected intterm_set(EditLine *el, const char *term){ int i; char buf[TC_BUFSIZE]; char *area; const struct termcapstr *t; sigset_t oset, nset; int lins, cols; (void) sigemptyset(&nset); (void) sigaddset(&nset, SIGWINCH); (void) sigprocmask(SIG_BLOCK, &nset, &oset); area = buf; if (term == NULL) term = getenv("TERM"); if (!term || !term[0]) term = "dumb"; if (strcmp(term, "emacs") == 0) el->el_flags |= EDIT_DISABLED; memset(el->el_term.t_cap, 0, TC_BUFSIZE); i = tgetent(el->el_term.t_cap, term); if (i <= 0) { if (i == -1) (void) fprintf(el->el_errfile, "Cannot read termcap database;\n"); else if (i == 0) (void) fprintf(el->el_errfile, "No entry for terminal type \"%s\";\n", term); (void) fprintf(el->el_errfile, "using dumb terminal settings.\n"); Val(T_co) = 80; /* do a dumb terminal */ Val(T_pt) = Val(T_km) = Val(T_li) = 0; Val(T_xt) = Val(T_MT); for (t = tstr; t->name != NULL; t++) term_alloc(el, t, NULL); } else { /* auto/magic margins */ Val(T_am) = tgetflag("am"); Val(T_xn) = tgetflag("xn"); /* Can we tab */ Val(T_pt) = tgetflag("pt"); Val(T_xt) = tgetflag("xt"); /* do we have a meta? */ Val(T_km) = tgetflag("km"); Val(T_MT) = tgetflag("MT"); /* Get the size */ Val(T_co) = tgetnum("co"); Val(T_li) = tgetnum("li"); for (t = tstr; t->name != NULL; t++) term_alloc(el, t, tgetstr((char *)t->name, &area)); } if (Val(T_co) < 2) Val(T_co) = 80; /* just in case */ if (Val(T_li) < 1) Val(T_li) = 24; el->el_term.t_size.v = Val(T_co); el->el_term.t_size.h = Val(T_li); term_setflags(el); /* get the correct window size */ (void) term_get_size(el, &lins, &cols); if (term_change_size(el, lins, cols) == -1) return (-1); (void) sigprocmask(SIG_SETMASK, &oset, NULL); term_bind_arrow(el); return (i <= 0 ? -1 : 0);}/* term_get_size(): * Return the new window size in lines and cols, and * true if the size was changed. */protected intterm_get_size(EditLine *el, int *lins, int *cols){ *cols = Val(T_co); *lins = Val(T_li);#ifdef TIOCGWINSZ { struct winsize ws; if (ioctl(el->el_infd, TIOCGWINSZ, (ioctl_t) & ws) != -1) { if (ws.ws_col) *cols = ws.ws_col; if (ws.ws_row) *lins = ws.ws_row; } }#endif#ifdef TIOCGSIZE { struct ttysize ts; if (ioctl(el->el_infd, TIOCGSIZE, (ioctl_t) & ts) != -1) { if (ts.ts_cols) *cols = ts.ts_cols; if (ts.ts_lines) *lins = ts.ts_lines; } }#endif return (Val(T_co) != *cols || Val(T_li) != *lins);}/* term_change_size(): * Change the size of the terminal */protected intterm_change_size(EditLine *el, int lins, int cols){ /* * Just in case */ Val(T_co) = (cols < 2) ? 80 : cols; Val(T_li) = (lins < 1) ? 24 : lins; /* re-make display buffers */ if (term_rebuffer_display(el) == -1) return (-1); re_clear_display(el); return (0);}/* term_init_arrow(): * Initialize the arrow key bindings from termcap */private voidterm_init_arrow(EditLine *el){ fkey_t *arrow = el->el_term.t_fkey; arrow[A_K_DN].name = "down"; arrow[A_K_DN].key = T_kd; arrow[A_K_DN].fun.cmd = ED_NEXT_HISTORY; arrow[A_K_DN].type = XK_CMD; arrow[A_K_UP].name = "up"; arrow[A_K_UP].key = T_ku; arrow[A_K_UP].fun.cmd = ED_PREV_HISTORY; arrow[A_K_UP].type = XK_CMD; arrow[A_K_LT].name = "left"; arrow[A_K_LT].key = T_kl; arrow[A_K_LT].fun.cmd = ED_PREV_CHAR; arrow[A_K_LT].type = XK_CMD; arrow[A_K_RT].name = "right"; arrow[A_K_RT].key = T_kr; arrow[A_K_RT].fun.cmd = ED_NEXT_CHAR; arrow[A_K_RT].type = XK_CMD; arrow[A_K_HO].name = "home"; arrow[A_K_HO].key = T_kh; arrow[A_K_HO].fun.cmd = ED_MOVE_TO_BEG; arrow[A_K_HO].type = XK_CMD;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -