⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 terminal.c

📁 putty
💻 C
📖 第 1 页 / 共 5 页
字号:

    /*
     * 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_tblink) {
	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);
    }
    term_schedule_tblink(term);
    term_schedule_cblink(term);
}

/*
 * Clear the scrollback.
 */
void term_clrsb(Terminal *term)
{
    unsigned char *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->cblink_pending = term->tblink_pending = FALSE;
    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->cblinker = 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, TRUE);
    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->window_update_pending = FALSE;

    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);

    expire_timer_context(term);

    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 */

    /* Behave sensibly if we're given zero (or negative) rows/cols */

    if (newrows < 1) newrows = 1;
    if (newcols < 1) newcols = 1;

    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);
	    sfree(cline);
	    line->temporary = FALSE;   /* reconstituted line is now real */
	    term->tempsblines -= 1;
	    addpos234(term->screen, line, 0);
	    term->curs.y += 1;
	    term->savecurs.y += 1;
	} else {
	    /* Add a new blank line at the bottom of the screen. */
	    line = newline(term, newcols, FALSE);
	    addpos234(term->screen, line, count234(term->screen));
	}
	term->rows += 1;
    }
    /* Do this loop to shrink the screen if newrows < rows */
    while (term->rows > newrows) {
	if (term->curs.y < term->rows - 1) {
	    /* delete bottom row, unless it contains the cursor */
	    sfree(delpos234(term->screen, term->rows - 1));
	} else {
	    /* push top row to scrollback */
	    line = delpos234(term->screen, 0);
	    addpos234(term->scrollback, compressline(line), sblen++);
	    freeline(line);
	    term->tempsblines += 1;
	    term->curs.y -= 1;
	    term->savecurs.y -= 1;
	}
	term->rows -= 1;
    }
    assert(term->rows == newrows);
    assert(count234(term->screen) == newrows);

    /* Delete any excess lines from the scrollback. */
    while (sblen > newsavelines) {
	line = delpos234(term->scrollback, 0);
	sfree(line);
	sblen--;
    }
    if (sblen < term->tempsblines)
	term->tempsblines = sblen;
    assert(count234(term->scrollback) <= newsavelines);
    assert(count234(term->scrollback) >= term->tempsblines);
    term->disptop = 0;

    /* Make a new displayed text buffer. */
    newdisp = snewn(newrows, termline *);
    for (i = 0; i < newrows; i++) {
	newdisp[i] = newline(term, newcols, FALSE);
	for (j = 0; j < newcols; j++)
	    newdisp[i]->chars[j].attr = ATTR_INVALID;
    }
    if (term->disptext) {
	for (i = 0; i < oldrows; i++)
	    freeline(term->disptext[i]);
    }
    sfree(term->disptext);
    term->disptext = newdisp;
    term->dispcursx = term->dispcursy = -1;

    /* Make a new alternate screen. */
    newalt = newtree234(NULL);
    for (i = 0; i < newrows; i++) {
	line = newline(term, newcols, TRUE);
	addpos234(newalt, line, i);
    }
    if (term->alt_screen) {
	while (NULL != (line = delpos234(term->alt_screen, 0)))
	    freeline(line);
	freetree234(term->alt_screen);
    }
    term->alt_screen = newalt;
    term->alt_sblines = 0;

    term->tabs = sresize(term->tabs, newcols, unsigned char);
    {
	int i;
	for (i = (term->cols > 0 ? term->cols : 0); i < newcols; i++)
	    term->tabs[i] = (i % 8 == 0 ? TRUE : FALSE);
    }

    /* Check that the cursor positions are still valid. */
    if (term->savecurs.y < 0)
	term->savecurs.y = 0;
    if (term->savecurs.y >= newrows)
	term->savecurs.y = newrows - 1;
    if (term->curs.y < 0)
	term->curs.y = 0;
    if (term->curs.y >= newrows)
	term->curs.y = newrows - 1;
    if (term->curs.x >= newcols)
	term->curs.x = newcols - 1;
    term->alt_x = term->alt_y = 0;
    term->wrapnext = term->alt_wnext = FALSE;

    term->rows = newrows;
    term->cols = newcols;
    term->savelines = newsavelines;

    swap_screen(term, save_alt_which, FALSE, FALSE);

    update_sbar(term);
    term_update(term);
    if (term->resize_fn)
	term->resize_fn(term->resize_ctx, term->cols, term->rows);
}

/*
 * Hand a function and context pointer to the terminal which it can
 * use to notify a back end of resizes.
 */
void term_provide_resize_fn(Terminal *term,
			    void (*resize_fn)(void *, int, int),
			    void *resize_ctx)
{
    term->resize_fn = resize_fn;
    term->resize_ctx = resize_ctx;
    if (resize_fn && term->cols > 0 && term->rows > 0)
	resize_fn(resize_ctx, term->cols, term->rows);
}

/* Find the bottom line on the screen that has any content.
 * If only the top line has content, returns 0.
 * If no lines have content, return -1.
 */ 
static int find_last_nonempty_line(Terminal * term, tree234 * screen)
{
    int i;
    for (i = count234(screen) - 1; i >= 0; i--) {
	termline *line = index234(screen, i);
	int j;
	for (j = 0; j < line->cols; j++)
	    if (!termchars_equal(&line->chars[j], &term->erase_char))
		break;
	if (j != line->cols) break;
    }
    return i;
}

/*
 * Swap screens. If `reset' is TRUE and we have been asked to
 * switch to the alternate screen, we must bring most of its
 * configuration from the main screen and erase the contents of the
 * alternate screen completely. (This is even true if we're already
 * on it! Blame xterm.)
 */
static void swap_screen(Terminal *term, int which, int reset, int keep_cur_pos)
{
    int t;
    pos tp;
    tree234 *ttr;

    if (!which)
	reset = FALSE;		       /* do no weird resetting if which==0 */

    if (which != term->alt_which) {
	term->alt_which = which;

	ttr = term->alt_screen;
	term->alt_screen = term->screen;
	term->screen = ttr;
	term->alt_sblines = find_last_nonempty_line(term, term->alt_screen) + 1;
	t = term->curs.x;
	if (!reset && !keep_cur_pos)
	    term->curs.x = term->alt_x;
	term->alt_x = t;
	t = term->curs.y;
	if (!reset && !keep_cur_pos)
	    term->curs.y = term->alt_y;
	term->alt_y = t;
	t = term->marg_t;
	if (!reset) term->marg_t = term->alt_t;
	term->alt_t = t;
	t = term->marg_b;
	if (!reset) term->marg_b = term->alt_b;
	term->alt_b = t;
	t = term->dec_om;
	if (!reset) term->dec_om = term->alt_om;
	term->alt_om = t;
	t = term->wrap;
	if (!reset) term->wrap = term->alt_wrap;
	term->alt_wrap = t;
	t = term->wrapnext;
	if (!reset) term->wrapnext = term->alt_wnext;
	term->alt_wnext = t;
	t = term->insert;
	if (!reset) term->insert = term->alt_ins;
	term->alt_ins = t;
	t = term->cset;
	if (!reset) term->cset = term->alt_cset;
	term->alt_cset = t;
	t = term->utf;
	if (!reset) term->utf = term->alt_utf;
	term->alt_utf = t;
	t = term->sco_acs;
	if (!reset) term->sco_acs = term->alt_sco_acs;
	term->alt_sco_acs = t;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -