📄 term.c
字号:
/* $NetBSD: term.c,v 1.35 2002/03/18 16:00:59 christos Exp $ *//*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Christos Zoulas of Cornell University. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include "config.h"#if !defined(lint) && !defined(SCCSID)#if 0static char sccsid[] = "@(#)term.c 8.2 (Berkeley) 4/30/95";#else__RCSID("$NetBSD: term.c,v 1.35 2002/03/18 16:00:59 christos Exp $");#endif#endif /* not lint && not SCCSID *//* * term.c: Editor/termcap-curses interface * We have to declare a static variable here, since the * termcap putchar routine does not take an argument! */#include <stdio.h>#include <signal.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#ifdef HAVE_TERMCAP_H#include <termcap.h>#endif#ifdef HAVE_CURSES_H#include <curses.h>#endif#ifdef HAVE_NCURSES_H#include <ncurses.h>#endif#if defined(HAVE_TERM_H)#include "term.h"/* Can not use /usr/include/term.h because of a lot of incompatibilities, so just define some prototypes */extern int tgetent(char *, const char *);extern int tgetflag(const char *);extern int tgetnum(const char *);extern char *tgetstr(const char *, char **);extern int tputs (const char *, int, int (*)(int));extern char *tgoto (const char *, int, int);#endif /* defined(HAVE_TERM_H) */#include <sys/types.h>#include <sys/ioctl.h>#include "el.h"/* * IMPORTANT NOTE: these routines are allowed to look at the current screen * and the current possition assuming that it is correct. If this is not * true, then the update will be WRONG! This is (should be) a valid * assumption... */#define TC_BUFSIZE 2048#define GoodStr(a) (el->el_term.t_str[a] != NULL && \ el->el_term.t_str[a][0] != '\0')#define Str(a) el->el_term.t_str[a]#define Val(a) el->el_term.t_val[a]#ifdef notdefprivate const struct { const char *b_name; int b_rate;} baud_rate[] = {#ifdef B0 { "0", B0 },#endif#ifdef B50 { "50", B50 },#endif#ifdef B75 { "75", B75 },#endif#ifdef B110 { "110", B110 },#endif#ifdef B134 { "134", B134 },#endif#ifdef B150 { "150", B150 },#endif#ifdef B200 { "200", B200 },#endif#ifdef B300 { "300", B300 },#endif#ifdef B600 { "600", B600 },#endif#ifdef B900 { "900", B900 },#endif#ifdef B1200 { "1200", B1200 },#endif#ifdef B1800 { "1800", B1800 },#endif#ifdef B2400 { "2400", B2400 },#endif#ifdef B3600 { "3600", B3600 },#endif#ifdef B4800 { "4800", B4800 },#endif#ifdef B7200 { "7200", B7200 },#endif#ifdef B9600 { "9600", B9600 },#endif#ifdef EXTA { "19200", EXTA },#endif#ifdef B19200 { "19200", B19200 },#endif#ifdef EXTB { "38400", EXTB },#endif#ifdef B38400 { "38400", B38400 },#endif { NULL, 0 }};#endifprivate const struct termcapstr { const char *name; const char *long_name;} tstr[] = {#define T_al 0 { "al", "add new blank line" },#define T_bl 1 { "bl", "audible bell" },#define T_cd 2 { "cd", "clear to bottom" },#define T_ce 3 { "ce", "clear to end of line" },#define T_ch 4 { "ch", "cursor to horiz pos" },#define T_cl 5 { "cl", "clear screen" },#define T_dc 6 { "dc", "delete a character" },#define T_dl 7 { "dl", "delete a line" },#define T_dm 8 { "dm", "start delete mode" },#define T_ed 9 { "ed", "end delete mode" },#define T_ei 10 { "ei", "end insert mode" },#define T_fs 11 { "fs", "cursor from status line" },#define T_ho 12 { "ho", "home cursor" },#define T_ic 13 { "ic", "insert character" },#define T_im 14 { "im", "start insert mode" },#define T_ip 15 { "ip", "insert padding" },#define T_kd 16 { "kd", "sends cursor down" },#define T_kl 17 { "kl", "sends cursor left" },#define T_kr 18 { "kr", "sends cursor right" },#define T_ku 19 { "ku", "sends cursor up" },#define T_md 20 { "md", "begin bold" },#define T_me 21 { "me", "end attributes" },#define T_nd 22 { "nd", "non destructive space" },#define T_se 23 { "se", "end standout" },#define T_so 24 { "so", "begin standout" },#define T_ts 25 { "ts", "cursor to status line" },#define T_up 26 { "up", "cursor up one" },#define T_us 27 { "us", "begin underline" },#define T_ue 28 { "ue", "end underline" },#define T_vb 29 { "vb", "visible bell" },#define T_DC 30 { "DC", "delete multiple chars" },#define T_DO 31 { "DO", "cursor down multiple" },#define T_IC 32 { "IC", "insert multiple chars" },#define T_LE 33 { "LE", "cursor left multiple" },#define T_RI 34 { "RI", "cursor right multiple" },#define T_UP 35 { "UP", "cursor up multiple" },#define T_kh 36 { "kh", "send cursor home" },#define T_at7 37 { "@7", "send cursor end" },#define T_str 38 { NULL, NULL }};private const struct termcapval { const char *name; const char *long_name;} tval[] = {#define T_am 0 { "am", "has automatic margins" },#define T_pt 1 { "pt", "has physical tabs" },#define T_li 2 { "li", "Number of lines" },#define T_co 3 { "co", "Number of columns" },#define T_km 4 { "km", "Has meta key" },#define T_xt 5 { "xt", "Tab chars destructive" },#define T_xn 6 { "xn", "newline ignored at right margin" },#define T_MT 7 { "MT", "Has meta key" }, /* XXX? */#define T_val 8 { NULL, NULL, }};/* do two or more of the attributes use me */private void term_setflags(EditLine *);private int term_rebuffer_display(EditLine *);private void term_free_display(EditLine *);private int term_alloc_display(EditLine *);private void term_alloc(EditLine *, const struct termcapstr *, const char *);private void term_init_arrow(EditLine *);private void term_reset_arrow(EditLine *);private FILE *term_outfile = NULL; /* XXX: How do we fix that? *//* term_setflags(): * Set the terminal capability flags */private voidterm_setflags(EditLine *el){ EL_FLAGS = 0; if (el->el_tty.t_tabs) EL_FLAGS |= (Val(T_pt) && !Val(T_xt)) ? TERM_CAN_TAB : 0; EL_FLAGS |= (Val(T_km) || Val(T_MT)) ? TERM_HAS_META : 0; EL_FLAGS |= GoodStr(T_ce) ? TERM_CAN_CEOL : 0; EL_FLAGS |= (GoodStr(T_dc) || GoodStr(T_DC)) ? TERM_CAN_DELETE : 0; EL_FLAGS |= (GoodStr(T_im) || GoodStr(T_ic) || GoodStr(T_IC)) ? TERM_CAN_INSERT : 0; EL_FLAGS |= (GoodStr(T_up) || GoodStr(T_UP)) ? TERM_CAN_UP : 0; EL_FLAGS |= Val(T_am) ? TERM_HAS_AUTO_MARGINS : 0; EL_FLAGS |= Val(T_xn) ? TERM_HAS_MAGIC_MARGINS : 0; if (GoodStr(T_me) && GoodStr(T_ue)) EL_FLAGS |= (strcmp(Str(T_me), Str(T_ue)) == 0) ? TERM_CAN_ME : 0; else EL_FLAGS &= ~TERM_CAN_ME; if (GoodStr(T_me) && GoodStr(T_se)) EL_FLAGS |= (strcmp(Str(T_me), Str(T_se)) == 0) ? TERM_CAN_ME : 0;#ifdef DEBUG_SCREEN if (!EL_CAN_UP) { (void) fprintf(el->el_errfile, "WARNING: Your terminal cannot move up.\n"); (void) fprintf(el->el_errfile, "Editing may be odd for long lines.\n"); } if (!EL_CAN_CEOL) (void) fprintf(el->el_errfile, "no clear EOL capability.\n"); if (!EL_CAN_DELETE) (void) fprintf(el->el_errfile, "no delete char capability.\n"); if (!EL_CAN_INSERT) (void) fprintf(el->el_errfile, "no insert char capability.\n");#endif /* DEBUG_SCREEN */}/* term_init(): * Initialize the terminal stuff */protected intterm_init(EditLine *el){ el->el_term.t_buf = (char *) el_malloc(TC_BUFSIZE); if (el->el_term.t_buf == NULL) return (-1); el->el_term.t_cap = (char *) el_malloc(TC_BUFSIZE); if (el->el_term.t_cap == NULL) return (-1); el->el_term.t_fkey = (fkey_t *) el_malloc(A_K_NKEYS * sizeof(fkey_t)); if (el->el_term.t_fkey == NULL) return (-1); el->el_term.t_loc = 0; el->el_term.t_str = (char **) el_malloc(T_str * sizeof(char *)); if (el->el_term.t_str == NULL) return (-1); (void) memset(el->el_term.t_str, 0, T_str * sizeof(char *)); el->el_term.t_val = (int *) el_malloc(T_val * sizeof(int)); if (el->el_term.t_val == NULL) return (-1); (void) memset(el->el_term.t_val, 0, T_val * sizeof(int)); term_outfile = el->el_outfile; (void) term_set(el, NULL); term_init_arrow(el); return (0);}/* term_end(): * Clean up the terminal stuff */protected voidterm_end(EditLine *el){ el_free((ptr_t) el->el_term.t_buf); el->el_term.t_buf = NULL; el_free((ptr_t) el->el_term.t_cap); el->el_term.t_cap = NULL; el_free((ptr_t) el->el_term.t_fkey); el->el_term.t_fkey = NULL; el->el_term.t_loc = 0; el_free((ptr_t) el->el_term.t_str); el->el_term.t_str = NULL; el_free((ptr_t) el->el_term.t_val); el->el_term.t_val = NULL; term_free_display(el);}/* term_alloc(): * Maintain a string pool for termcap strings */private voidterm_alloc(EditLine *el, const struct termcapstr *t, const char *cap){ char termbuf[TC_BUFSIZE]; int tlen, clen; char **tlist = el->el_term.t_str; char **tmp, **str = &tlist[t - tstr]; if (cap == NULL || *cap == '\0') { *str = NULL; return; } else clen = strlen(cap); tlen = *str == NULL ? 0 : strlen(*str); /* * New string is shorter; no need to allocate space */ if (clen <= tlen) { (void) strcpy(*str, cap); /* XXX strcpy is safe */ return; } /* * New string is longer; see if we have enough space to append */ if (el->el_term.t_loc + 3 < TC_BUFSIZE) { /* XXX strcpy is safe */ (void) strcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], cap); el->el_term.t_loc += clen + 1; /* one for \0 */ return; } /* * Compact our buffer; no need to check compaction, cause we know it * fits... */ tlen = 0; for (tmp = tlist; tmp < &tlist[T_str]; tmp++) if (*tmp != NULL && *tmp != '\0' && *tmp != *str) { char *ptr; for (ptr = *tmp; *ptr != '\0'; termbuf[tlen++] = *ptr++) continue; termbuf[tlen++] = '\0'; } memcpy(el->el_term.t_buf, termbuf, TC_BUFSIZE); el->el_term.t_loc = tlen; if (el->el_term.t_loc + 3 >= TC_BUFSIZE) { (void) fprintf(el->el_errfile, "Out of termcap string space.\n"); return; } /* XXX strcpy is safe */ (void) strcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], cap); el->el_term.t_loc += clen + 1; /* one for \0 */ return;}/* term_rebuffer_display(): * Rebuffer the display after the screen changed size */private intterm_rebuffer_display(EditLine *el){ coord_t *c = &el->el_term.t_size; term_free_display(el); c->h = Val(T_co); c->v = Val(T_li); if (term_alloc_display(el) == -1) return (-1); return (0);}/* term_alloc_display(): * Allocate a new display. */private intterm_alloc_display(EditLine *el){ int i; char **b; coord_t *c = &el->el_term.t_size; b = (char **) el_malloc((size_t) (sizeof(char *) * (c->v + 1))); if (b == NULL) return (-1); for (i = 0; i < c->v; i++) { b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1))); if (b[i] == NULL) return (-1); } b[c->v] = NULL; el->el_display = b; b = (char **) el_malloc((size_t) (sizeof(char *) * (c->v + 1))); if (b == NULL) return (-1); for (i = 0; i < c->v; i++) { b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1))); if (b[i] == NULL) return (-1); } b[c->v] = NULL; el->el_vdisplay = b; return (0);}/* term_free_display(): * Free the display buffers */private voidterm_free_display(EditLine *el){ char **b; char **bufp; b = el->el_display; el->el_display = NULL; if (b != NULL) { for (bufp = b; *bufp != NULL; bufp++) el_free((ptr_t) * bufp); el_free((ptr_t) b); } b = el->el_vdisplay; el->el_vdisplay = NULL; if (b != NULL) { for (bufp = b; *bufp != NULL; bufp++) el_free((ptr_t) * bufp); el_free((ptr_t) b); }}/* term_move_to_line():
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -