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

📄 terminal.c

📁 大名鼎鼎的远程登录软件putty的Symbian版源码
💻 C
📖 第 1 页 / 共 5 页
字号:
static void save_cursor(Terminal *term, int save){    if (save) {	term->savecurs = term->curs;	term->save_attr = term->curr_attr;	term->save_cset = term->cset;	term->save_utf = term->utf;	term->save_wnext = term->wrapnext;	term->save_csattr = term->cset_attr[term->cset];	term->save_sco_acs = term->sco_acs;    } else {	term->curs = term->savecurs;	/* Make sure the window hasn't shrunk since the save */	if (term->curs.x >= term->cols)	    term->curs.x = term->cols - 1;	if (term->curs.y >= term->rows)	    term->curs.y = term->rows - 1;	term->curr_attr = term->save_attr;	term->cset = term->save_cset;	term->utf = term->save_utf;	term->wrapnext = term->save_wnext;	/*	 * wrapnext might reset to False if the x position is no	 * longer at the rightmost edge.	 */	if (term->wrapnext && term->curs.x < term->cols-1)	    term->wrapnext = FALSE;	term->cset_attr[term->cset] = term->save_csattr;	term->sco_acs = term->save_sco_acs;	set_erase_char(term);    }}/* * This function is called before doing _anything_ which affects * only part of a line of text. It is used to mark the boundary * between two character positions, and it indicates that some sort * of effect is going to happen on only one side of that boundary. *  * The effect of this function is to check whether a CJK * double-width character is straddling the boundary, and to remove * it and replace it with two spaces if so. (Of course, one or * other of those spaces is then likely to be replaced with * something else again, as a result of whatever happens next.) *  * Also, if the boundary is at the right-hand _edge_ of the screen, * it implies something deliberate is being done to the rightmost * column position; hence we must clear LATTR_WRAPPED2. *  * The input to the function is the coordinates of the _second_ * character of the pair. */static void check_boundary(Terminal *term, int x, int y){    termline *ldata;    /* Validate input coordinates, just in case. */    if (x == 0 || x > term->cols)	return;    ldata = scrlineptr(y);    if (x == term->cols) {	ldata->lattr &= ~LATTR_WRAPPED2;    } else {	if (ldata->chars[x].chr == UCSWIDE) {	    clear_cc(ldata, x-1);	    clear_cc(ldata, x);	    ldata->chars[x-1].chr = ' ' | CSET_ASCII;	    ldata->chars[x] = ldata->chars[x-1];	}    }}/* * Erase a large portion of the screen: the whole screen, or the * whole line, or parts thereof. */static void erase_lots(Terminal *term,		       int line_only, int from_begin, int to_end){    pos start, end;    int erase_lattr;    int erasing_lines_from_top = 0;    if (line_only) {	start.y = term->curs.y;	start.x = 0;	end.y = term->curs.y + 1;	end.x = 0;	erase_lattr = FALSE;    } else {	start.y = 0;	start.x = 0;	end.y = term->rows;	end.x = 0;	erase_lattr = TRUE;    }    if (!from_begin) {	start = term->curs;    }    if (!to_end) {	end = term->curs;	incpos(end);    }    if (!from_begin || !to_end)	check_boundary(term, term->curs.x, term->curs.y);    check_selection(term, start, end);    /* Clear screen also forces a full window redraw, just in case. */    if (start.y == 0 && start.x == 0 && end.y == term->rows)	term_invalidate(term);    /* Lines scrolled away shouldn't be brought back on if the terminal     * resizes. */    if (start.y == 0 && start.x == 0 && end.x == 0 && erase_lattr)	erasing_lines_from_top = 1;    if (term->cfg.erase_to_scrollback && erasing_lines_from_top) {	/* If it's a whole number of lines, starting at the top, and	 * we're fully erasing them, erase by scrolling and keep the	 * lines in the scrollback. */	int scrolllines = end.y;	if (end.y == term->rows) {	    /* Shrink until we find a non-empty row.*/	    scrolllines = find_last_nonempty_line(term, term->screen) + 1;	}	if (scrolllines > 0)	    scroll(term, 0, scrolllines - 1, scrolllines, TRUE);    } else {	termline *ldata = scrlineptr(start.y);	while (poslt(start, end)) {	    if (start.x == term->cols) {		if (!erase_lattr)		    ldata->lattr &= ~(LATTR_WRAPPED | LATTR_WRAPPED2);		else		    ldata->lattr = LATTR_NORM;	    } else {		copy_termchar(ldata, start.x, &term->erase_char);	    }	    if (incpos(start) && start.y < term->rows) {		ldata = scrlineptr(start.y);	    }	}    }    /* After an erase of lines from the top of the screen, we shouldn't     * bring the lines back again if the terminal enlarges (since the user or     * application has explictly thrown them away). */    if (erasing_lines_from_top && !(term->alt_which))	term->tempsblines = 0;}/* * Insert or delete characters within the current line. n is +ve if * insertion is desired, and -ve for deletion. */static void insch(Terminal *term, int n){    int dir = (n < 0 ? -1 : +1);    int m, j;    pos cursplus;    termline *ldata;    n = (n < 0 ? -n : n);    if (n > term->cols - term->curs.x)	n = term->cols - term->curs.x;    m = term->cols - term->curs.x - n;    cursplus.y = term->curs.y;    cursplus.x = term->curs.x + n;    check_selection(term, term->curs, cursplus);    check_boundary(term, term->curs.x, term->curs.y);    if (dir < 0)	check_boundary(term, term->curs.x + n, term->curs.y);    ldata = scrlineptr(term->curs.y);    if (dir < 0) {	for (j = 0; j < m; j++)	    move_termchar(ldata,			  ldata->chars + term->curs.x + j,			  ldata->chars + term->curs.x + j + n);	while (n--)	    copy_termchar(ldata, term->curs.x + m++, &term->erase_char);    } else {	for (j = m; j-- ;)	    move_termchar(ldata,			  ldata->chars + term->curs.x + j + n,			  ldata->chars + term->curs.x + j);	while (n--)	    copy_termchar(ldata, term->curs.x + n, &term->erase_char);    }}/* * Toggle terminal mode `mode' to state `state'. (`query' indicates * whether the mode is a DEC private one or a normal one.) */static void toggle_mode(Terminal *term, int mode, int query, int state){    unsigned long ticks;    if (query)	switch (mode) {	  case 1:		       /* DECCKM: application cursor keys */	    term->app_cursor_keys = state;	    break;	  case 2:		       /* DECANM: VT52 mode */	    term->vt52_mode = !state;	    if (term->vt52_mode) {		term->blink_is_real = FALSE;		term->vt52_bold = FALSE;	    } else {		term->blink_is_real = term->cfg.blinktext;	    }	    break;	  case 3:		       /* DECCOLM: 80/132 columns */	    deselect(term);	    if (!term->cfg.no_remote_resize)		request_resize(term->frontend, state ? 132 : 80, term->rows);	    term->reset_132 = state;	    term->alt_t = term->marg_t = 0;	    term->alt_b = term->marg_b = term->rows - 1;	    move(term, 0, 0, 0);	    erase_lots(term, FALSE, TRUE, TRUE);	    break;	  case 5:		       /* DECSCNM: reverse video */	    /*	     * Toggle reverse video. If we receive an OFF within the	     * visual bell timeout period after an ON, we trigger an	     * effective visual bell, so that ESC[?5hESC[?5l will	     * always be an actually _visible_ visual bell.	     */	    ticks = GETTICKCOUNT();	    /* turn off a previous vbell to avoid inconsistencies */	    if (ticks - term->vbell_startpoint >= VBELL_TIMEOUT)		term->in_vbell = FALSE;	    if (term->rvideo && !state &&    /* we're turning it off... */		(ticks - term->rvbell_startpoint) < VBELL_TIMEOUT) {/*...soon*/		/* If there's no vbell timeout already, or this one lasts		 * longer, replace vbell_timeout with ours. */		if (!term->in_vbell ||		    (term->rvbell_startpoint - term->vbell_startpoint <		     VBELL_TIMEOUT))		    term->vbell_startpoint = term->rvbell_startpoint;		term->in_vbell = TRUE; /* may clear rvideo but set in_vbell */	    } else if (!term->rvideo && state) {		/* This is an ON, so we notice the time and save it. */		term->rvbell_startpoint = ticks;	    }	    term->rvideo = state;	    term->seen_disp_event = TRUE;	    if (state)		term_update(term);	    break;	  case 6:		       /* DECOM: DEC origin mode */	    term->dec_om = state;	    break;	  case 7:		       /* DECAWM: auto wrap */	    term->wrap = state;	    break;	  case 8:		       /* DECARM: auto key repeat */	    term->repeat_off = !state;	    break;	  case 10:		       /* DECEDM: set local edit mode */	    term->term_editing = state;	    if (term->ldisc)	       /* cause ldisc to notice changes */		ldisc_send(term->ldisc, NULL, 0, 0);	    break;	  case 25:		       /* DECTCEM: enable/disable cursor */	    compatibility2(OTHER, VT220);	    term->cursor_on = state;	    term->seen_disp_event = TRUE;	    break;	  case 47:		       /* alternate screen */	    compatibility(OTHER);	    deselect(term);	    swap_screen(term, term->cfg.no_alt_screen ? 0 : state, FALSE, FALSE);	    term->disptop = 0;	    break;	  case 1000:		       /* xterm mouse 1 */	    term->xterm_mouse = state ? 1 : 0;	    set_raw_mouse_mode(term->frontend, state);	    break;	  case 1002:		       /* xterm mouse 2 */	    term->xterm_mouse = state ? 2 : 0;	    set_raw_mouse_mode(term->frontend, state);	    break;	  case 1047:                   /* alternate screen */	    compatibility(OTHER);	    deselect(term);	    swap_screen(term, term->cfg.no_alt_screen ? 0 : state, TRUE, TRUE);	    term->disptop = 0;	    break;	  case 1048:                   /* save/restore cursor */	    if (!term->cfg.no_alt_screen)                save_cursor(term, state);	    if (!state) term->seen_disp_event = TRUE;	    break;	  case 1049:                   /* cursor & alternate screen */	    if (state && !term->cfg.no_alt_screen)		save_cursor(term, state);	    if (!state) term->seen_disp_event = TRUE;	    compatibility(OTHER);	    deselect(term);	    swap_screen(term, term->cfg.no_alt_screen ? 0 : state, TRUE, FALSE);	    if (!state && !term->cfg.no_alt_screen)		save_cursor(term, state);	    term->disptop = 0;	    break;    } else	switch (mode) {	  case 4:		       /* IRM: set insert mode */	    compatibility(VT102);	    term->insert = state;	    break;	  case 12:		       /* SRM: set echo mode */	    term->term_echoing = !state;	    if (term->ldisc)	       /* cause ldisc to notice changes */		ldisc_send(term->ldisc, NULL, 0, 0);	    break;	  case 20:		       /* LNM: Return sends ... */	    term->cr_lf_return = state;	    break;	  case 34:		       /* WYULCURM: Make cursor BIG */	    compatibility2(OTHER, VT220);	    term->big_cursor = !state;	}}/* * Process an OSC sequence: set window title or icon name. */static void do_osc(Terminal *term){    if (term->osc_w) {	while (term->osc_strlen--)	    term->wordness[(unsigned char)		term->osc_string[term->osc_strlen]] = term->esc_args[0];    } else {	term->osc_string[term->osc_strlen] = '\0';	switch (term->esc_args[0]) {	  case 0:	  case 1:	    if (!term->cfg.no_remote_wintitle)		set_icon(term->frontend, term->osc_string);	    if (term->esc_args[0] == 1)		break;	    /* fall through: parameter 0 means set both */	  case 2:	  case 21:	    if (!term->cfg.no_remote_wintitle)		set_title(term->frontend, term->osc_string);	    break;	}    }}/* * ANSI printing routines. */static void term_print_setup(Terminal *term){    bufchain_clear(&term->printer_buf);    term->print_job = printer_start_job(term->cfg.printer);}static void term_print_flush(Terminal *term){    void *data;    int len;    int size;    while ((size = bufchain_size(&term->printer_buf)) > 5) {	bufchain_prefix(&term->printer_buf, &data, &len);	if (len > size-5)	    len = size-5;	printer_job_data(term->print_job, data, len);	bufchain_consume(&term->printer_buf, len);    }}static void term_print_finish(Terminal *term){    void *data;    int len, size;    char c;    if (!term->printing && !term->only_printing)	return;			       /* we need do nothing */    term_print_flush(term);    while ((size = bufchain_size(&term->printer_buf)) > 0) {	bufchain_prefix(&term->printer_buf, &data, &len);	c = *(char *)data;	if (c == '\033' || c == '\233') {	    bufchain_consume(&term->printer_buf, size);	    break;	} else {	    printer_job_data(term->print_job, &c, 1);	    bufchain_consume(&term->printer_buf, 1);	}    }    printer_finish_job(term->print_job);    term->print_job = NULL;    term->printing = term->only_printing = FALSE;}/* * Remove everything currently in `inbuf' and stick it up on the * in-memory display. There's a big state machine in here to * process escape sequences... */void term_out(Terminal *term){    unsigned long c;    int unget;    unsigned char localbuf[256], *chars;    int nchars = 0;    unget = -1;    chars = NULL;		       /* placate compiler warnings */    while (nchars > 0 || bufchain_size(&term->inbuf) > 0) {	if (unget == -1) {	    if (nchars == 0) {		void *ret;		bufchain_prefix(&term->inbuf, &ret, &nchars);		if (nchars > sizeof(localbuf))		    nchars = sizeof(localbuf);		memcpy(localbuf, ret, nchars);		bufchain_consume(&term->inbuf, nchars);		chars = localbuf;		assert(chars != NULL);	    }	    c = *chars++;	    nchars--;	    /*	     * Optionally log the session traffic to a file. Useful for	     * debugging and possibly also useful for actual logging.	     */	    if (term->cfg.logtype == LGTYP_DEBUG && term->logctx)		logtraffic(term->logctx, (unsigned char) c, LGTYP_DEBUG);	} else {	    c = unget;	    unget = -1;	}	/* Note only VT220+ are 8-bit VT102 is seven bit, it shouldn't even	 * be able to display 8-bit characters, but I'll let that go 'cause	 * of i18n.	 */	/*	 * If we're printing, add the character to the printer	 * buffer.	 */	if (term->printing) {	    bufchain_add(&term->printer_buf, &c, 1);	    /*	     * If we're in print-only mode, we use a much simpler	     * state machine 

⌨️ 快捷键说明

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