📄 terminal.c
字号:
/* * Get the number of lines in the scrollback. */static int sblines(Terminal *term){ int sblines = count234(term->scrollback); if (term->cfg.erase_to_scrollback && term->alt_which && term->alt_screen) { sblines += term->alt_sblines; } return sblines;}/* * Retrieve a line of the screen or of the scrollback, according to * whether the y coordinate is non-negative or negative * (respectively). */static termline *lineptr(Terminal *term, int y, int lineno, int screen){ termline *line; tree234 *whichtree; int treeindex; if (y >= 0) { whichtree = term->screen; treeindex = y; } else { int altlines = 0; assert(!screen); if (term->cfg.erase_to_scrollback && term->alt_which && term->alt_screen) { altlines = term->alt_sblines; } if (y < -altlines) { whichtree = term->scrollback; treeindex = y + altlines + count234(term->scrollback); } else { whichtree = term->alt_screen; treeindex = y + term->alt_sblines; /* treeindex = y + count234(term->alt_screen); */ } } if (whichtree == term->scrollback) { unsigned char *cline = index234(whichtree, treeindex); line = decompressline(cline, NULL); } else { line = index234(whichtree, treeindex); } /* We assume that we don't screw up and retrieve something out of range. */ assert(line != NULL); resizeline(term, line, term->cols); /* FIXME: should we sort the compressed scrollback out here? */ return line;}#define lineptr(x) (lineptr)(term,x,__LINE__,FALSE)#define scrlineptr(x) (lineptr)(term,x,__LINE__,TRUE)/* * Set up power-on settings for the terminal. */static void power_on(Terminal *term){ term->curs.x = term->curs.y = 0; term->alt_x = term->alt_y = 0; term->savecurs.x = term->savecurs.y = 0; term->alt_t = term->marg_t = 0; if (term->rows != -1) term->alt_b = term->marg_b = term->rows - 1; else term->alt_b = term->marg_b = 0; if (term->cols != -1) { int i; for (i = 0; i < term->cols; i++) term->tabs[i] = (i % 8 == 0 ? TRUE : FALSE); } term->alt_om = term->dec_om = term->cfg.dec_om; term->alt_ins = term->insert = FALSE; term->alt_wnext = term->wrapnext = term->save_wnext = FALSE; term->alt_wrap = term->wrap = term->cfg.wrap_mode; term->alt_cset = term->cset = term->save_cset = 0; term->alt_utf = term->utf = term->save_utf = 0; term->utf_state = 0; term->alt_sco_acs = term->sco_acs = term->save_sco_acs = 0; term->cset_attr[0] = term->cset_attr[1] = term->save_csattr = CSET_ASCII; term->rvideo = 0; term->in_vbell = FALSE; term->cursor_on = 1; term->big_cursor = 0; term->default_attr = term->save_attr = term->curr_attr = ATTR_DEFAULT; term->term_editing = term->term_echoing = FALSE; term->app_cursor_keys = term->cfg.app_cursor; term->app_keypad_keys = term->cfg.app_keypad; term->use_bce = term->cfg.bce; term->blink_is_real = term->cfg.blinktext; term->erase_char = term->basic_erase_char; term->alt_which = 0; term_print_finish(term); { int i; for (i = 0; i < 256; i++) term->wordness[i] = term->cfg.wordness[i]; } if (term->screen) { swap_screen(term, 1, FALSE, FALSE); erase_lots(term, FALSE, TRUE, TRUE); swap_screen(term, 0, FALSE, FALSE); erase_lots(term, FALSE, TRUE, TRUE); }}/* * Force a screen update. */void term_update(Terminal *term){ Context ctx; ctx = get_ctx(term->frontend); if (ctx) { int need_sbar_update = term->seen_disp_event; if (term->seen_disp_event && term->cfg.scroll_on_disp) { term->disptop = 0; /* return to main screen */ term->seen_disp_event = 0; need_sbar_update = TRUE; } if (need_sbar_update) update_sbar(term); do_paint(term, ctx, TRUE); sys_cursor(term->frontend, term->curs.x, term->curs.y - term->disptop); free_ctx(ctx); }}/* * Called from front end when a keypress occurs, to trigger * anything magical that needs to happen in that situation. */void term_seen_key_event(Terminal *term){ /* * On any keypress, clear the bell overload mechanism * completely, on the grounds that large numbers of * beeps coming from deliberate key action are likely * to be intended (e.g. beeps from filename completion * blocking repeatedly). */ term->beep_overloaded = FALSE; while (term->beephead) { struct beeptime *tmp = term->beephead; term->beephead = tmp->next; sfree(tmp); } term->beeptail = NULL; term->nbeeps = 0; /* * Reset the scrollback on keypress, if we're doing that. */ if (term->cfg.scroll_on_key) { term->disptop = 0; /* return to main screen */ term->seen_disp_event = 1; }}/* * Same as power_on(), but an external function. */void term_pwron(Terminal *term){ power_on(term); if (term->ldisc) /* cause ldisc to notice changes */ ldisc_send(term->ldisc, NULL, 0, 0); term->disptop = 0; deselect(term); term_update(term);}static void set_erase_char(Terminal *term){ term->erase_char = term->basic_erase_char; if (term->use_bce) term->erase_char.attr = (term->curr_attr & (ATTR_FGMASK | ATTR_BGMASK));}/* * When the user reconfigures us, we need to check the forbidden- * alternate-screen config option, disable raw mouse mode if the * user has disabled mouse reporting, and abandon a print job if * the user has disabled printing. */void term_reconfig(Terminal *term, Config *cfg){ /* * Before adopting the new config, check all those terminal * settings which control power-on defaults; and if they've * changed, we will modify the current state as well as the * default one. The full list is: Auto wrap mode, DEC Origin * Mode, BCE, blinking text, character classes. */ int reset_wrap, reset_decom, reset_bce, reset_blink, reset_charclass; int i; reset_wrap = (term->cfg.wrap_mode != cfg->wrap_mode); reset_decom = (term->cfg.dec_om != cfg->dec_om); reset_bce = (term->cfg.bce != cfg->bce); reset_blink = (term->cfg.blinktext != cfg->blinktext); reset_charclass = 0; for (i = 0; i < lenof(term->cfg.wordness); i++) if (term->cfg.wordness[i] != cfg->wordness[i]) reset_charclass = 1; /* * If the bidi or shaping settings have changed, flush the bidi * cache completely. */ if (term->cfg.arabicshaping != cfg->arabicshaping || term->cfg.bidi != cfg->bidi) { for (i = 0; i < term->bidi_cache_size; i++) { sfree(term->pre_bidi_cache[i].chars); sfree(term->post_bidi_cache[i].chars); term->pre_bidi_cache[i].width = -1; term->pre_bidi_cache[i].chars = NULL; term->post_bidi_cache[i].width = -1; term->post_bidi_cache[i].chars = NULL; } } term->cfg = *cfg; /* STRUCTURE COPY */ if (reset_wrap) term->alt_wrap = term->wrap = term->cfg.wrap_mode; if (reset_decom) term->alt_om = term->dec_om = term->cfg.dec_om; if (reset_bce) { term->use_bce = term->cfg.bce; set_erase_char(term); } if (reset_blink) term->blink_is_real = term->cfg.blinktext; if (reset_charclass) for (i = 0; i < 256; i++) term->wordness[i] = term->cfg.wordness[i]; if (term->cfg.no_alt_screen) swap_screen(term, 0, FALSE, FALSE); if (term->cfg.no_mouse_rep) { term->xterm_mouse = 0; set_raw_mouse_mode(term->frontend, 0); } if (term->cfg.no_remote_charset) { term->cset_attr[0] = term->cset_attr[1] = CSET_ASCII; term->sco_acs = term->alt_sco_acs = 0; term->utf = 0; } if (!*term->cfg.printer) { term_print_finish(term); }}/* * Clear the scrollback. */void term_clrsb(Terminal *term){ termline *line; term->disptop = 0; while ((line = delpos234(term->scrollback, 0)) != NULL) { sfree(line); /* this is compressed data, not a termline */ } term->tempsblines = 0; term->alt_sblines = 0; update_sbar(term);}/* * Initialise the terminal. */Terminal *term_init(Config *mycfg, struct unicode_data *ucsdata, void *frontend){ Terminal *term; /* * Allocate a new Terminal structure and initialise the fields * that need it. */ term = snew(Terminal); term->frontend = frontend; term->ucsdata = ucsdata; term->cfg = *mycfg; /* STRUCTURE COPY */ term->logctx = NULL; term->compatibility_level = TM_PUTTY; strcpy(term->id_string, "\033[?6c"); term->last_blink = term->last_tblink = 0; term->paste_buffer = NULL; term->paste_len = 0; term->last_paste = 0; bufchain_init(&term->inbuf); bufchain_init(&term->printer_buf); term->printing = term->only_printing = FALSE; term->print_job = NULL; term->vt52_mode = FALSE; term->cr_lf_return = FALSE; term->seen_disp_event = FALSE; term->xterm_mouse = term->mouse_is_down = FALSE; term->reset_132 = FALSE; term->blinker = term->tblinker = 0; term->has_focus = 1; term->repeat_off = FALSE; term->termstate = TOPLEVEL; term->selstate = NO_SELECTION; term->curstype = 0; term->screen = term->alt_screen = term->scrollback = NULL; term->tempsblines = 0; term->alt_sblines = 0; term->disptop = 0; term->disptext = NULL; term->dispcursx = term->dispcursy = -1; term->tabs = NULL; deselect(term); term->rows = term->cols = -1; power_on(term); term->beephead = term->beeptail = NULL;#ifdef OPTIMISE_SCROLL term->scrollhead = term->scrolltail = NULL;#endif /* OPTIMISE_SCROLL */ term->nbeeps = 0; term->lastbeep = FALSE; term->beep_overloaded = FALSE; term->attr_mask = 0xffffffff; term->resize_fn = NULL; term->resize_ctx = NULL; term->in_term_out = FALSE; term->ltemp = NULL; term->ltemp_size = 0; term->wcFrom = NULL; term->wcTo = NULL; term->wcFromTo_size = 0; term->bidi_cache_size = 0; term->pre_bidi_cache = term->post_bidi_cache = NULL; /* FULL-TERMCHAR */ term->basic_erase_char.chr = CSET_ASCII | ' '; term->basic_erase_char.attr = ATTR_DEFAULT; term->basic_erase_char.cc_next = 0; term->erase_char = term->basic_erase_char; return term;}void term_free(Terminal *term){ termline *line; struct beeptime *beep; int i; while ((line = delpos234(term->scrollback, 0)) != NULL) sfree(line); /* compressed data, not a termline */ freetree234(term->scrollback); while ((line = delpos234(term->screen, 0)) != NULL) freeline(line); freetree234(term->screen); while ((line = delpos234(term->alt_screen, 0)) != NULL) freeline(line); freetree234(term->alt_screen); if (term->disptext) { for (i = 0; i < term->rows; i++) freeline(term->disptext[i]); } sfree(term->disptext); while (term->beephead) { beep = term->beephead; term->beephead = beep->next; sfree(beep); } bufchain_clear(&term->inbuf); if(term->print_job) printer_finish_job(term->print_job); bufchain_clear(&term->printer_buf); sfree(term->paste_buffer); sfree(term->ltemp); sfree(term->wcFrom); sfree(term->wcTo); for (i = 0; i < term->bidi_cache_size; i++) { sfree(term->pre_bidi_cache[i].chars); sfree(term->post_bidi_cache[i].chars); } sfree(term->pre_bidi_cache); sfree(term->post_bidi_cache); sfree(term);}/* * Set up the terminal for a given size. */void term_size(Terminal *term, int newrows, int newcols, int newsavelines){ tree234 *newalt; termline **newdisp, *line; int i, j, oldrows = term->rows; int sblen; int save_alt_which = term->alt_which; if (newrows == term->rows && newcols == term->cols && newsavelines == term->savelines) return; /* nothing to do */ deselect(term); swap_screen(term, 0, FALSE, FALSE); term->alt_t = term->marg_t = 0; term->alt_b = term->marg_b = newrows - 1; if (term->rows == -1) { term->scrollback = newtree234(NULL); term->screen = newtree234(NULL); term->tempsblines = 0; term->rows = 0; } /* * Resize the screen and scrollback. We only need to shift * lines around within our data structures, because lineptr() * will take care of resizing each individual line if * necessary. So: * * - If the new screen is longer, we shunt lines in from temporary * scrollback if possible, otherwise we add new blank lines at * the bottom. * * - If the new screen is shorter, we remove any blank lines at * the bottom if possible, otherwise shunt lines above the cursor * to scrollback if possible, otherwise delete lines below the * cursor. * * - Then, if the new scrollback length is less than the * amount of scrollback we actually have, we must throw some * away. */ sblen = count234(term->scrollback); /* Do this loop to expand the screen if newrows > rows */ assert(term->rows == count234(term->screen)); while (term->rows < newrows) { if (term->tempsblines > 0) { unsigned char *cline; /* Insert a line from the scrollback at the top of the screen. */ assert(sblen >= term->tempsblines); cline = delpos234(term->scrollback, --sblen); line = decompressline(cline, NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -