vt.c

来自「linux 内核源代码」· C语言 代码 · 共 2,565 行 · 第 1/5 页

C
2,565
字号
	vc->vc_G0_charset	= vc->vc_saved_G0;	vc->vc_G1_charset	= vc->vc_saved_G1;	vc->vc_translate	= set_translate(vc->vc_charset ? vc->vc_G1_charset : vc->vc_G0_charset, vc);	update_attr(vc);	vc->vc_need_wrap = 0;}enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,	EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd,	ESpalette };/* console_sem is held (except via vc_init()) */static void reset_terminal(struct vc_data *vc, int do_clear){	vc->vc_top		= 0;	vc->vc_bottom		= vc->vc_rows;	vc->vc_state		= ESnormal;	vc->vc_ques		= 0;	vc->vc_translate	= set_translate(LAT1_MAP, vc);	vc->vc_G0_charset	= LAT1_MAP;	vc->vc_G1_charset	= GRAF_MAP;	vc->vc_charset		= 0;	vc->vc_need_wrap	= 0;	vc->vc_report_mouse	= 0;	vc->vc_utf              = default_utf8;	vc->vc_utf_count	= 0;	vc->vc_disp_ctrl	= 0;	vc->vc_toggle_meta	= 0;	vc->vc_decscnm		= 0;	vc->vc_decom		= 0;	vc->vc_decawm		= 1;	vc->vc_deccm		= 1;	vc->vc_decim		= 0;	set_kbd(vc, decarm);	clr_kbd(vc, decckm);	clr_kbd(vc, kbdapplic);	clr_kbd(vc, lnm);	kbd_table[vc->vc_num].lockstate = 0;	kbd_table[vc->vc_num].slockstate = 0;	kbd_table[vc->vc_num].ledmode = LED_SHOW_FLAGS;	kbd_table[vc->vc_num].ledflagstate = kbd_table[vc->vc_num].default_ledflagstate;	/* do not do set_leds here because this causes an endless tasklet loop	   when the keyboard hasn't been initialized yet */	vc->vc_cursor_type = CUR_DEFAULT;	vc->vc_complement_mask = vc->vc_s_complement_mask;	default_attr(vc);	update_attr(vc);	vc->vc_tab_stop[0]	= 0x01010100;	vc->vc_tab_stop[1]	=	vc->vc_tab_stop[2]	=	vc->vc_tab_stop[3]	=	vc->vc_tab_stop[4]	= 0x01010101;	vc->vc_bell_pitch = DEFAULT_BELL_PITCH;	vc->vc_bell_duration = DEFAULT_BELL_DURATION;	gotoxy(vc, 0, 0);	save_cur(vc);	if (do_clear)	    csi_J(vc, 2);}/* console_sem is held */static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c){	/*	 *  Control characters can be used in the _middle_	 *  of an escape sequence.	 */	switch (c) {	case 0:		return;	case 7:		if (vc->vc_bell_duration)			kd_mksound(vc->vc_bell_pitch, vc->vc_bell_duration);		return;	case 8:		bs(vc);		return;	case 9:		vc->vc_pos -= (vc->vc_x << 1);		while (vc->vc_x < vc->vc_cols - 1) {			vc->vc_x++;			if (vc->vc_tab_stop[vc->vc_x >> 5] & (1 << (vc->vc_x & 31)))				break;		}		vc->vc_pos += (vc->vc_x << 1);		notify_write(vc, '\t');		return;	case 10: case 11: case 12:		lf(vc);		if (!is_kbd(vc, lnm))			return;	case 13:		cr(vc);		return;	case 14:		vc->vc_charset = 1;		vc->vc_translate = set_translate(vc->vc_G1_charset, vc);		vc->vc_disp_ctrl = 1;		return;	case 15:		vc->vc_charset = 0;		vc->vc_translate = set_translate(vc->vc_G0_charset, vc);		vc->vc_disp_ctrl = 0;		return;	case 24: case 26:		vc->vc_state = ESnormal;		return;	case 27:		vc->vc_state = ESesc;		return;	case 127:		del(vc);		return;	case 128+27:		vc->vc_state = ESsquare;		return;	}	switch(vc->vc_state) {	case ESesc:		vc->vc_state = ESnormal;		switch (c) {		case '[':			vc->vc_state = ESsquare;			return;		case ']':			vc->vc_state = ESnonstd;			return;		case '%':			vc->vc_state = ESpercent;			return;		case 'E':			cr(vc);			lf(vc);			return;		case 'M':			ri(vc);			return;		case 'D':			lf(vc);			return;		case 'H':			vc->vc_tab_stop[vc->vc_x >> 5] |= (1 << (vc->vc_x & 31));			return;		case 'Z':			respond_ID(tty);			return;		case '7':			save_cur(vc);			return;		case '8':			restore_cur(vc);			return;		case '(':			vc->vc_state = ESsetG0;			return;		case ')':			vc->vc_state = ESsetG1;			return;		case '#':			vc->vc_state = EShash;			return;		case 'c':			reset_terminal(vc, 1);			return;		case '>':  /* Numeric keypad */			clr_kbd(vc, kbdapplic);			return;		case '=':  /* Appl. keypad */			set_kbd(vc, kbdapplic);			return;		}		return;	case ESnonstd:		if (c=='P') {   /* palette escape sequence */			for (vc->vc_npar = 0; vc->vc_npar < NPAR; vc->vc_npar++)				vc->vc_par[vc->vc_npar] = 0;			vc->vc_npar = 0;			vc->vc_state = ESpalette;			return;		} else if (c=='R') {   /* reset palette */			reset_palette(vc);			vc->vc_state = ESnormal;		} else			vc->vc_state = ESnormal;		return;	case ESpalette:		if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) {			vc->vc_par[vc->vc_npar++] = (c > '9' ? (c & 0xDF) - 'A' + 10 : c - '0');			if (vc->vc_npar == 7) {				int i = vc->vc_par[0] * 3, j = 1;				vc->vc_palette[i] = 16 * vc->vc_par[j++];				vc->vc_palette[i++] += vc->vc_par[j++];				vc->vc_palette[i] = 16 * vc->vc_par[j++];				vc->vc_palette[i++] += vc->vc_par[j++];				vc->vc_palette[i] = 16 * vc->vc_par[j++];				vc->vc_palette[i] += vc->vc_par[j];				set_palette(vc);				vc->vc_state = ESnormal;			}		} else			vc->vc_state = ESnormal;		return;	case ESsquare:		for (vc->vc_npar = 0; vc->vc_npar < NPAR; vc->vc_npar++)			vc->vc_par[vc->vc_npar] = 0;		vc->vc_npar = 0;		vc->vc_state = ESgetpars;		if (c == '[') { /* Function key */			vc->vc_state=ESfunckey;			return;		}		vc->vc_ques = (c == '?');		if (vc->vc_ques)			return;	case ESgetpars:		if (c == ';' && vc->vc_npar < NPAR - 1) {			vc->vc_npar++;			return;		} else if (c>='0' && c<='9') {			vc->vc_par[vc->vc_npar] *= 10;			vc->vc_par[vc->vc_npar] += c - '0';			return;		} else			vc->vc_state = ESgotpars;	case ESgotpars:		vc->vc_state = ESnormal;		switch(c) {		case 'h':			set_mode(vc, 1);			return;		case 'l':			set_mode(vc, 0);			return;		case 'c':			if (vc->vc_ques) {				if (vc->vc_par[0])					vc->vc_cursor_type = vc->vc_par[0] | (vc->vc_par[1] << 8) | (vc->vc_par[2] << 16);				else					vc->vc_cursor_type = CUR_DEFAULT;				return;			}			break;		case 'm':			if (vc->vc_ques) {				clear_selection();				if (vc->vc_par[0])					vc->vc_complement_mask = vc->vc_par[0] << 8 | vc->vc_par[1];				else					vc->vc_complement_mask = vc->vc_s_complement_mask;				return;			}			break;		case 'n':			if (!vc->vc_ques) {				if (vc->vc_par[0] == 5)					status_report(tty);				else if (vc->vc_par[0] == 6)					cursor_report(vc, tty);			}			return;		}		if (vc->vc_ques) {			vc->vc_ques = 0;			return;		}		switch(c) {		case 'G': case '`':			if (vc->vc_par[0])				vc->vc_par[0]--;			gotoxy(vc, vc->vc_par[0], vc->vc_y);			return;		case 'A':			if (!vc->vc_par[0])				vc->vc_par[0]++;			gotoxy(vc, vc->vc_x, vc->vc_y - vc->vc_par[0]);			return;		case 'B': case 'e':			if (!vc->vc_par[0])				vc->vc_par[0]++;			gotoxy(vc, vc->vc_x, vc->vc_y + vc->vc_par[0]);			return;		case 'C': case 'a':			if (!vc->vc_par[0])				vc->vc_par[0]++;			gotoxy(vc, vc->vc_x + vc->vc_par[0], vc->vc_y);			return;		case 'D':			if (!vc->vc_par[0])				vc->vc_par[0]++;			gotoxy(vc, vc->vc_x - vc->vc_par[0], vc->vc_y);			return;		case 'E':			if (!vc->vc_par[0])				vc->vc_par[0]++;			gotoxy(vc, 0, vc->vc_y + vc->vc_par[0]);			return;		case 'F':			if (!vc->vc_par[0])				vc->vc_par[0]++;			gotoxy(vc, 0, vc->vc_y - vc->vc_par[0]);			return;		case 'd':			if (vc->vc_par[0])				vc->vc_par[0]--;			gotoxay(vc, vc->vc_x ,vc->vc_par[0]);			return;		case 'H': case 'f':			if (vc->vc_par[0])				vc->vc_par[0]--;			if (vc->vc_par[1])				vc->vc_par[1]--;			gotoxay(vc, vc->vc_par[1], vc->vc_par[0]);			return;		case 'J':			csi_J(vc, vc->vc_par[0]);			return;		case 'K':			csi_K(vc, vc->vc_par[0]);			return;		case 'L':			csi_L(vc, vc->vc_par[0]);			return;		case 'M':			csi_M(vc, vc->vc_par[0]);			return;		case 'P':			csi_P(vc, vc->vc_par[0]);			return;		case 'c':			if (!vc->vc_par[0])				respond_ID(tty);			return;		case 'g':			if (!vc->vc_par[0])				vc->vc_tab_stop[vc->vc_x >> 5] &= ~(1 << (vc->vc_x & 31));			else if (vc->vc_par[0] == 3) {				vc->vc_tab_stop[0] =					vc->vc_tab_stop[1] =					vc->vc_tab_stop[2] =					vc->vc_tab_stop[3] =					vc->vc_tab_stop[4] = 0;			}			return;		case 'm':			csi_m(vc);			return;		case 'q': /* DECLL - but only 3 leds */			/* map 0,1,2,3 to 0,1,2,4 */			if (vc->vc_par[0] < 4)				setledstate(kbd_table + vc->vc_num,					    (vc->vc_par[0] < 3) ? vc->vc_par[0] : 4);			return;		case 'r':			if (!vc->vc_par[0])				vc->vc_par[0]++;			if (!vc->vc_par[1])				vc->vc_par[1] = vc->vc_rows;			/* Minimum allowed region is 2 lines */			if (vc->vc_par[0] < vc->vc_par[1] &&			    vc->vc_par[1] <= vc->vc_rows) {				vc->vc_top = vc->vc_par[0] - 1;				vc->vc_bottom = vc->vc_par[1];				gotoxay(vc, 0, 0);			}			return;		case 's':			save_cur(vc);			return;		case 'u':			restore_cur(vc);			return;		case 'X':			csi_X(vc, vc->vc_par[0]);			return;		case '@':			csi_at(vc, vc->vc_par[0]);			return;		case ']': /* setterm functions */			setterm_command(vc);			return;		}		return;	case ESpercent:		vc->vc_state = ESnormal;		switch (c) {		case '@':  /* defined in ISO 2022 */			vc->vc_utf = 0;			return;		case 'G':  /* prelim official escape code */		case '8':  /* retained for compatibility */			vc->vc_utf = 1;			return;		}		return;	case ESfunckey:		vc->vc_state = ESnormal;		return;	case EShash:		vc->vc_state = ESnormal;		if (c == '8') {			/* DEC screen alignment test. kludge :-) */			vc->vc_video_erase_char =				(vc->vc_video_erase_char & 0xff00) | 'E';			csi_J(vc, 2);			vc->vc_video_erase_char =				(vc->vc_video_erase_char & 0xff00) | ' ';			do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2);		}		return;	case ESsetG0:		if (c == '0')			vc->vc_G0_charset = GRAF_MAP;		else if (c == 'B')			vc->vc_G0_charset = LAT1_MAP;		else if (c == 'U')			vc->vc_G0_charset = IBMPC_MAP;		else if (c == 'K')			vc->vc_G0_charset = USER_MAP;		if (vc->vc_charset == 0)			vc->vc_translate = set_translate(vc->vc_G0_charset, vc);		vc->vc_state = ESnormal;		return;	case ESsetG1:		if (c == '0')			vc->vc_G1_charset = GRAF_MAP;		else if (c == 'B')			vc->vc_G1_charset = LAT1_MAP;		else if (c == 'U')			vc->vc_G1_charset = IBMPC_MAP;		else if (c == 'K')			vc->vc_G1_charset = USER_MAP;		if (vc->vc_charset == 1)			vc->vc_translate = set_translate(vc->vc_G1_charset, vc);		vc->vc_state = ESnormal;		return;	default:		vc->vc_state = ESnormal;	}}/* This is a temporary buffer used to prepare a tty console write * so that we can easily avoid touching user space while holding the * console spinlock.  It is allocated in con_init and is shared by * this code and the vc_screen read/write tty calls. * * We have to allocate this statically in the kernel data section * since console_init (and thus con_init) are called before any * kernel memory allocation is available. */char con_buf[CON_BUF_SIZE];DEFINE_MUTEX(con_buf_mtx);/* is_double_width() is based on the wcwidth() implementation by * Markus Kuhn -- 2007-05-26 (Unicode 5.0) * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c */struct interval {	uint32_t first;	uint32_t last;};static int bisearch(uint32_t ucs, const struct interval *table, int max){	int min = 0;	int mid;	if (ucs < table[0].first || ucs > table[max].last)		return 0;	while (max >= min) {		mid = (min + max) / 2;		if (ucs > table[mid].last)			min = mid + 1;		else if (ucs < table[mid].first)			max = mid - 1;		else			return 1;	}	return 0;}static int is_double_width(uint32_t ucs){	static const struct interval double_width[] = {		{ 0x1100, 0x115F }, { 0x2329, 0x232A }, { 0x2E80, 0x303E },		{ 0x3040, 0xA4CF }, { 0xAC00, 0xD7A3 }, { 0xF900, 0xFAFF },		{ 0xFE10, 0xFE19 }, { 0xFE30, 0xFE6F }, { 0xFF00, 0xFF60 },		{ 0xFFE0, 0xFFE6 }, { 0x20000, 0x2FFFD }, { 0x30000, 0x3FFFD }	};	return bisearch(ucs, double_width, ARRAY_SIZE(double_width) - 1);}/* acquires console_sem */static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int count){#ifdef VT_BUF_VRAM_ONLY#define FLUSH do { } while(0);#else#define FLUSH if (draw_x >= 0) { \	vc->vc_sw->con_putcs(vc, (u16 *)draw_from, (u16 *)draw_to - (u16 *)draw_from, vc->vc_y, draw_x); \	draw_x = -1; \	}#endif	int c, tc, ok, n = 0, draw_x = -1;	unsigned int currcons;

⌨️ 快捷键说明

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