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

📄 terminal.c

📁 大名鼎鼎的远程登录软件putty的Symbian版源码
💻 C
📖 第 1 页 / 共 5 页
字号:
#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <time.h>#include <assert.h>#include "putty.h"#include "terminal.h"#define poslt(p1,p2) ( (p1).y < (p2).y || ( (p1).y == (p2).y && (p1).x < (p2).x ) )#define posle(p1,p2) ( (p1).y < (p2).y || ( (p1).y == (p2).y && (p1).x <= (p2).x ) )#define poseq(p1,p2) ( (p1).y == (p2).y && (p1).x == (p2).x )#define posdiff(p1,p2) ( ((p1).y - (p2).y) * (term->cols+1) + (p1).x - (p2).x )/* Product-order comparisons for rectangular block selection. */#define posPlt(p1,p2) ( (p1).y <= (p2).y && (p1).x < (p2).x )#define posPle(p1,p2) ( (p1).y <= (p2).y && (p1).x <= (p2).x )#define incpos(p) ( (p).x == term->cols ? ((p).x = 0, (p).y++, 1) : ((p).x++, 0) )#define decpos(p) ( (p).x == 0 ? ((p).x = term->cols, (p).y--, 1) : ((p).x--, 0) )#define VT52_PLUS#define CL_ANSIMIN	0x0001	       /* Codes in all ANSI like terminals. */#define CL_VT100	0x0002	       /* VT100 */#define CL_VT100AVO	0x0004	       /* VT100 +AVO; 132x24 (not 132x14) & attrs */#define CL_VT102	0x0008	       /* VT102 */#define CL_VT220	0x0010	       /* VT220 */#define CL_VT320	0x0020	       /* VT320 */#define CL_VT420	0x0040	       /* VT420 */#define CL_VT510	0x0080	       /* VT510, NB VT510 includes ANSI */#define CL_VT340TEXT	0x0100	       /* VT340 extensions that appear in the VT420 */#define CL_SCOANSI	0x1000	       /* SCOANSI not in ANSIMIN. */#define CL_ANSI		0x2000	       /* ANSI ECMA-48 not in the VT100..VT420 */#define CL_OTHER	0x4000	       /* Others, Xterm, linux, putty, dunno, etc */#define TM_VT100	(CL_ANSIMIN|CL_VT100)#define TM_VT100AVO	(TM_VT100|CL_VT100AVO)#define TM_VT102	(TM_VT100AVO|CL_VT102)#define TM_VT220	(TM_VT102|CL_VT220)#define TM_VTXXX	(TM_VT220|CL_VT340TEXT|CL_VT510|CL_VT420|CL_VT320)#define TM_SCOANSI	(CL_ANSIMIN|CL_SCOANSI)#define TM_PUTTY	(0xFFFF)#define compatibility(x) \    if ( ((CL_##x)&term->compatibility_level) == 0 ) { 	\       term->termstate=TOPLEVEL;			\       break;						\    }#define compatibility2(x,y) \    if ( ((CL_##x|CL_##y)&term->compatibility_level) == 0 ) { \       term->termstate=TOPLEVEL;			\       break;						\    }#define has_compat(x) ( ((CL_##x)&term->compatibility_level) != 0 )const char sco2ansicolour[] = { 0, 4, 2, 6, 1, 5, 3, 7 };#define sel_nl_sz  (sizeof(sel_nl)/sizeof(wchar_t))const wchar_t sel_nl[] = SEL_NL;/* * Fetch the character at a particular position in a line array, * for purposes of `wordtype'. The reason this isn't just a simple * array reference is that if the character we find is UCSWIDE, * then we must look one space further to the left. */#define UCSGET(a, x) \    ( (x)>0 && (a)[(x)].chr == UCSWIDE ? (a)[(x)-1].chr : (a)[(x)].chr )/* * Detect the various aliases of U+0020 SPACE. */#define IS_SPACE_CHR(chr) \	((chr) == 0x20 || (DIRECT_CHAR(chr) && ((chr) & 0xFF) == 0x20))/* * Spot magic CSETs. */#define CSET_OF(chr) (DIRECT_CHAR(chr)||DIRECT_FONT(chr) ? (chr)&CSET_MASK : 0)/* * Internal prototypes. */static void resizeline(Terminal *, termline *, int);static termline *lineptr(Terminal *, int, int, int);static void unlineptr(termline *);static void do_paint(Terminal *, Context, int);static void erase_lots(Terminal *, int, int, int);static void swap_screen(Terminal *, int, int, int);static void update_sbar(Terminal *);static void deselect(Terminal *);static void term_print_finish(Terminal *);#ifdef OPTIMISE_SCROLLstatic void scroll_display(Terminal *, int, int, int);#endif /* OPTIMISE_SCROLL */static termline *newline(Terminal *term, int cols, int bce){    termline *line;    int j;    line = snew(termline);    line->chars = snewn(cols, termchar);    for (j = 0; j < cols; j++)	line->chars[j] = (bce ? term->erase_char : term->basic_erase_char);    line->cols = line->size = cols;    line->lattr = LATTR_NORM;    line->temporary = FALSE;    line->cc_free = 0;    return line;}static void freeline(termline *line){    if (line) {	sfree(line->chars);	sfree(line);    }}static void unlineptr(termline *line){    if (line->temporary)	freeline(line);}/* * Diagnostic function: verify that a termline has a correct * combining character structure. *  * XXX-REMOVE-BEFORE-RELEASE: This is a performance-intensive * check. Although it's currently really useful for getting all the * bugs out of the new cc stuff, it will want to be absent when we * make a proper release. */static void cc_check(termline *line){    unsigned char *flags;    int i, j;    assert(line->size >= line->cols);    flags = snewn(line->size, unsigned char);    for (i = 0; i < line->size; i++)	flags[i] = (i < line->cols);    for (i = 0; i < line->cols; i++) {	j = i;	while (line->chars[j].cc_next) {	    j += line->chars[j].cc_next;	    assert(j >= line->cols && j < line->size);	    assert(!flags[j]);	    flags[j] = TRUE;	}    }    j = line->cc_free;    if (j) {	while (1) {	    assert(j >= line->cols && j < line->size);	    assert(!flags[j]);	    flags[j] = TRUE;	    if (line->chars[j].cc_next)		j += line->chars[j].cc_next;	    else		break;	}    }    j = 0;    for (i = 0; i < line->size; i++)	j += (flags[i] != 0);    assert(j == line->size);    sfree(flags);}/* * Add a combining character to a character cell. */static void add_cc(termline *line, int col, unsigned long chr){    int newcc;    assert(col >= 0 && col < line->cols);    /*     * Start by extending the cols array if the free list is empty.     */    if (!line->cc_free) {	int n = line->size;	line->size += 16 + (line->size - line->cols) / 2;	line->chars = sresize(line->chars, line->size, termchar);	line->cc_free = n;	while (n < line->size) {	    if (n+1 < line->size)		line->chars[n].cc_next = 1;	    else		line->chars[n].cc_next = 0;	    n++;	}    }    /*     * Now walk the cc list of the cell in question.     */    while (line->chars[col].cc_next)	col += line->chars[col].cc_next;    /*     * `col' now points at the last cc currently in this cell; so     * we simply add another one.     */    newcc = line->cc_free;    if (line->chars[newcc].cc_next)	line->cc_free = newcc + line->chars[newcc].cc_next;    else	line->cc_free = 0;    line->chars[newcc].cc_next = 0;    line->chars[newcc].chr = chr;    line->chars[col].cc_next = newcc - col;    cc_check(line);		       /* XXX-REMOVE-BEFORE-RELEASE */}/* * Clear the combining character list in a character cell. */static void clear_cc(termline *line, int col){    int oldfree, origcol = col;    assert(col >= 0 && col < line->cols);    if (!line->chars[col].cc_next)	return;			       /* nothing needs doing */    oldfree = line->cc_free;    line->cc_free = col + line->chars[col].cc_next;    while (line->chars[col].cc_next)	col += line->chars[col].cc_next;    if (oldfree)	line->chars[col].cc_next = oldfree - col;    else	line->chars[col].cc_next = 0;    line->chars[origcol].cc_next = 0;    cc_check(line);		       /* XXX-REMOVE-BEFORE-RELEASE */}/* * Compare two character cells for equality. Special case required * in do_paint() where we override what we expect the chr and attr * fields to be. */static int termchars_equal_override(termchar *a, termchar *b,				    unsigned long bchr, unsigned long battr){    /* FULL-TERMCHAR */    if (a->chr != bchr)	return FALSE;    if (a->attr != battr)	return FALSE;    while (a->cc_next || b->cc_next) {	if (!a->cc_next || !b->cc_next)	    return FALSE;	       /* one cc-list ends, other does not */	a += a->cc_next;	b += b->cc_next;	if (a->chr != b->chr)	    return FALSE;    }    return TRUE;}static int termchars_equal(termchar *a, termchar *b){    return termchars_equal_override(a, b, b->chr, b->attr);}/* * Copy a character cell. (Requires a pointer to the destination * termline, so as to access its free list.) */static void copy_termchar(termline *destline, int x, termchar *src){    clear_cc(destline, x);    destline->chars[x] = *src;	       /* copy everything except cc-list */    destline->chars[x].cc_next = 0;    /* and make sure this is zero */    while (src->cc_next) {	src += src->cc_next;	add_cc(destline, x, src->chr);    }    cc_check(destline);		       /* XXX-REMOVE-BEFORE-RELEASE */}/* * Move a character cell within its termline. */static void move_termchar(termline *line, termchar *dest, termchar *src){    /* First clear the cc list from the original char, just in case. */    clear_cc(line, dest - line->chars);    /* Move the character cell and adjust its cc_next. */    *dest = *src;		       /* copy everything except cc-list */    if (src->cc_next)	dest->cc_next = src->cc_next - (dest-src);    /* Ensure the original cell doesn't have a cc list. */    src->cc_next = 0;    cc_check(line);		       /* XXX-REMOVE-BEFORE-RELEASE */}/* * Compress and decompress a termline into an RLE-based format for * storing in scrollback. (Since scrollback almost never needs to * be modified and exists in huge quantities, this is a sensible * tradeoff, particularly since it allows us to continue adding * features to the main termchar structure without proportionally * bloating the terminal emulator's memory footprint unless those * features are in constant use.) */struct buf {    unsigned char *data;    int len, size;};static void add(struct buf *b, unsigned char c){    if (b->len >= b->size) {	b->size = (b->len * 3 / 2) + 512;	b->data = sresize(b->data, b->size, unsigned char);    }    b->data[b->len++] = c;}static int get(struct buf *b){    return b->data[b->len++];}static void makerle(struct buf *b, termline *ldata,		    void (*makeliteral)(struct buf *b, termchar *c,					unsigned long *state)){    int hdrpos, hdrsize, n, prevlen, prevpos, thislen, thispos, prev2;    termchar *c = ldata->chars;    unsigned long state = 0, oldstate;    n = ldata->cols;    hdrpos = b->len;    hdrsize = 0;    add(b, 0);    prevlen = prevpos = 0;    prev2 = FALSE;    while (n-- > 0) {	thispos = b->len;	makeliteral(b, c++, &state);	thislen = b->len - thispos;	if (thislen == prevlen &&	    !memcmp(b->data + prevpos, b->data + thispos, thislen)) {	    /*	     * This literal precisely matches the previous one.	     * Turn it into a run if it's worthwhile.	     * 	     * With one-byte literals, it costs us two bytes to	     * encode a run, plus another byte to write the header	     * to resume normal output; so a three-element run is	     * neutral, and anything beyond that is unconditionally	     * worthwhile. With two-byte literals or more, even a	     * 2-run is a win.	     */	    if (thislen > 1 || prev2) {		int runpos, runlen;		/*		 * It's worth encoding a run. Start at prevpos,		 * unless hdrsize==0 in which case we can back up		 * another one and start by overwriting hdrpos.		 */		hdrsize--;	       /* remove the literal at prevpos */		if (prev2) {		    assert(hdrsize > 0);		    hdrsize--;		    prevpos -= prevlen;/* and possibly another one */		}		if (hdrsize == 0) {		    assert(prevpos == hdrpos + 1);		    runpos = hdrpos;		    b->len = prevpos+prevlen;		} else {		    memmove(b->data + prevpos+1, b->data + prevpos, prevlen);		    runpos = prevpos;		    b->len = prevpos+prevlen+1;		    /*		     * Terminate the previous run of ordinary		     * literals.		     */		    assert(hdrsize >= 1 && hdrsize <= 128);		    b->data[hdrpos] = hdrsize - 1;		}		runlen = prev2 ? 3 : 2;		while (n > 0 && runlen < 129) {		    int tmppos, tmplen;		    tmppos = b->len;		    oldstate = state;		    makeliteral(b, c, &state);		    tmplen = b->len - tmppos;		    b->len = tmppos;		    if (tmplen != thislen ||			memcmp(b->data + runpos+1, b->data + tmppos, tmplen)) {			state = oldstate;			break;	       /* run over */		    }		    n--, c++, runlen++;		}		assert(runlen >= 2 && runlen <= 129);		b->data[runpos] = runlen + 0x80 - 2;		hdrpos = b->len;		hdrsize = 0;		add(b, 0);		/* And ensure this run doesn't interfere with the next. */		prevlen = prevpos = 0;		prev2 = FALSE;		continue;	    } else {		/*		 * Just flag that the previous two literals were		 * identical, in case we find a third identical one		 * we want to turn into a run.		 */		prev2 = TRUE;		prevlen = thislen;		prevpos = thispos;	    }	} else {	    prev2 = FALSE;	    prevlen = thislen;	    prevpos = thispos;	}	/*	 * This character isn't (yet) part of a run. Add it to	 * hdrsize.	 */

⌨️ 快捷键说明

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