mirror of
				https://gitlab.freedesktop.org/wayland/wayland.git
				synced 2025-11-03 09:01:42 -05:00 
			
		
		
		
	terminal: vt102 editing commands
Implement the vt102 editing commands, and insert/replace mode. Signed-off-by: Callum Lowcay <callum@callumscode.com>
This commit is contained in:
		
							parent
							
								
									8e57dd5071
								
							
						
					
					
						commit
						69e9658da0
					
				
					 1 changed files with 97 additions and 2 deletions
				
			
		| 
						 | 
					@ -62,6 +62,7 @@ static int option_fullscreen;
 | 
				
			||||||
#define MODE_AUTOWRAP		0x00000004
 | 
					#define MODE_AUTOWRAP		0x00000004
 | 
				
			||||||
#define MODE_AUTOREPEAT		0x00000008
 | 
					#define MODE_AUTOREPEAT		0x00000008
 | 
				
			||||||
#define MODE_LF_NEWLINE		0x00000010
 | 
					#define MODE_LF_NEWLINE		0x00000010
 | 
				
			||||||
 | 
					#define MODE_IRM		0x00000020
 | 
				
			||||||
 | 
					
 | 
				
			||||||
union utf8_char {
 | 
					union utf8_char {
 | 
				
			||||||
	unsigned char byte[4];
 | 
						unsigned char byte[4];
 | 
				
			||||||
| 
						 | 
					@ -393,6 +394,40 @@ terminal_scroll(struct terminal *terminal, int d)
 | 
				
			||||||
		terminal_scroll_window(terminal, d);
 | 
							terminal_scroll_window(terminal, d);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					terminal_shift_line(struct terminal *terminal, int d)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						union utf8_char *row;
 | 
				
			||||||
 | 
						struct attr *attr_row, attr;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						row = terminal_get_row(terminal, terminal->row);
 | 
				
			||||||
 | 
						attr_row = terminal_get_attr_row(terminal, terminal->row);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((terminal->width + d) <= terminal->column)
 | 
				
			||||||
 | 
							d = terminal->column + 1 - terminal->width;
 | 
				
			||||||
 | 
						if ((terminal->column + d) >= terminal->width)
 | 
				
			||||||
 | 
							d = terminal->width - terminal->column - 1;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						if (d < 0) {
 | 
				
			||||||
 | 
							d = 0 - d;
 | 
				
			||||||
 | 
							memmove(&row[terminal->column],
 | 
				
			||||||
 | 
							        &row[terminal->column + d],
 | 
				
			||||||
 | 
								(terminal->width - terminal->column - d) * sizeof(union utf8_char));
 | 
				
			||||||
 | 
							attr = attr_row[terminal->width - 1];
 | 
				
			||||||
 | 
							memmove(&attr_row[terminal->column], &attr_row[terminal->column + d],
 | 
				
			||||||
 | 
							        (terminal->width - terminal->column - d) * sizeof(struct attr));
 | 
				
			||||||
 | 
							memset(&row[terminal->width - d], 0, d * sizeof(union utf8_char));
 | 
				
			||||||
 | 
							attr_init(&attr_row[terminal->width - d], terminal->curr_attr, d);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							memmove(&row[terminal->column + d], &row[terminal->column],
 | 
				
			||||||
 | 
								(terminal->width - terminal->column - d) * sizeof(union utf8_char));
 | 
				
			||||||
 | 
							memmove(&attr_row[terminal->column + d], &attr_row[terminal->column],
 | 
				
			||||||
 | 
								(terminal->width - terminal->column - d) * sizeof(struct attr));
 | 
				
			||||||
 | 
							memset(&row[terminal->column], 0, d * sizeof(union utf8_char));
 | 
				
			||||||
 | 
							attr_init(&attr_row[terminal->column], terminal->curr_attr, d);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
terminal_resize(struct terminal *terminal, int width, int height)
 | 
					terminal_resize(struct terminal *terminal, int width, int height)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -724,6 +759,10 @@ handle_term_parameter(struct terminal *terminal, int code, int sr)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		switch(code) {
 | 
							switch(code) {
 | 
				
			||||||
 | 
							case 4:  /* IRM */
 | 
				
			||||||
 | 
								if (sr)	terminal->mode |=  MODE_IRM;
 | 
				
			||||||
 | 
								else	terminal->mode &= ~MODE_IRM;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
		case 20: /* LNM */
 | 
							case 20: /* LNM */
 | 
				
			||||||
			if (sr)	terminal->mode |=  MODE_LF_NEWLINE;
 | 
								if (sr)	terminal->mode |=  MODE_LF_NEWLINE;
 | 
				
			||||||
			else	terminal->mode &= ~MODE_LF_NEWLINE;
 | 
								else	terminal->mode &= ~MODE_LF_NEWLINE;
 | 
				
			||||||
| 
						 | 
					@ -763,6 +802,11 @@ handle_escape(struct terminal *terminal)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	switch (*p) {
 | 
						switch (*p) {
 | 
				
			||||||
 | 
						case '@':    /* ICH */
 | 
				
			||||||
 | 
							count = set[0] ? args[0] : 1;
 | 
				
			||||||
 | 
							if (count == 0) count = 1;
 | 
				
			||||||
 | 
							terminal_shift_line(terminal, count);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	case 'A':    /* CUU */
 | 
						case 'A':    /* CUU */
 | 
				
			||||||
		count = set[0] ? args[0] : 1;
 | 
							count = set[0] ? args[0] : 1;
 | 
				
			||||||
		if (count == 0) count = 1;
 | 
							if (count == 0) count = 1;
 | 
				
			||||||
| 
						 | 
					@ -893,12 +937,59 @@ handle_escape(struct terminal *terminal)
 | 
				
			||||||
			attr_init(attr_row, terminal->curr_attr, terminal->width);
 | 
								attr_init(attr_row, terminal->curr_attr, terminal->width);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
						case 'L':    /* IL */
 | 
				
			||||||
 | 
							count = set[0] ? args[0] : 1;
 | 
				
			||||||
 | 
							if (count == 0) count = 1;
 | 
				
			||||||
 | 
							if (terminal->row >= terminal->margin_top &&
 | 
				
			||||||
 | 
								terminal->row < terminal->margin_bottom)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								top = terminal->margin_top;
 | 
				
			||||||
 | 
								terminal->margin_top = terminal->row;
 | 
				
			||||||
 | 
								terminal_scroll(terminal, 0 - count);
 | 
				
			||||||
 | 
								terminal->margin_top = top;
 | 
				
			||||||
 | 
							} else if (terminal->row == terminal->margin_bottom) {
 | 
				
			||||||
 | 
								memset(terminal_get_row(terminal, terminal->row),
 | 
				
			||||||
 | 
								       0, terminal->data_pitch);
 | 
				
			||||||
 | 
								attr_init(terminal_get_attr_row(terminal, terminal->row),
 | 
				
			||||||
 | 
									terminal->curr_attr, terminal->width);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case 'M':    /* DL */
 | 
				
			||||||
 | 
							count = set[0] ? args[0] : 1;
 | 
				
			||||||
 | 
							if (count == 0) count = 1;
 | 
				
			||||||
 | 
							if (terminal->row >= terminal->margin_top &&
 | 
				
			||||||
 | 
								terminal->row < terminal->margin_bottom)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								top = terminal->margin_top;
 | 
				
			||||||
 | 
								terminal->margin_top = terminal->row;
 | 
				
			||||||
 | 
								terminal_scroll(terminal, count);
 | 
				
			||||||
 | 
								terminal->margin_top = top;
 | 
				
			||||||
 | 
							} else if (terminal->row == terminal->margin_bottom) {
 | 
				
			||||||
 | 
								memset(terminal_get_row(terminal, terminal->row),
 | 
				
			||||||
 | 
								       0, terminal->data_pitch);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case 'P':    /* DCH */
 | 
				
			||||||
 | 
							count = set[0] ? args[0] : 1;
 | 
				
			||||||
 | 
							if (count == 0) count = 1;
 | 
				
			||||||
 | 
							terminal_shift_line(terminal, 0 - count);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	case 'S':    /* SU */
 | 
						case 'S':    /* SU */
 | 
				
			||||||
		terminal_scroll(terminal, set[0] ? args[0] : 1);
 | 
							terminal_scroll(terminal, set[0] ? args[0] : 1);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case 'T':    /* SD */
 | 
						case 'T':    /* SD */
 | 
				
			||||||
		terminal_scroll(terminal, 0 - (set[0] ? args[0] : 1));
 | 
							terminal_scroll(terminal, 0 - (set[0] ? args[0] : 1));
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
						case 'X':    /* ECH */
 | 
				
			||||||
 | 
							count = set[0] ? args[0] : 1;
 | 
				
			||||||
 | 
							if (count == 0) count = 1;
 | 
				
			||||||
 | 
							if ((terminal->column + count) > terminal->width)
 | 
				
			||||||
 | 
								count = terminal->width - terminal->column;
 | 
				
			||||||
 | 
							row = terminal_get_row(terminal, terminal->row);
 | 
				
			||||||
 | 
							attr_row = terminal_get_attr_row(terminal, terminal->row);
 | 
				
			||||||
 | 
							memset(&row[terminal->column], 0, count * sizeof(union utf8_char));
 | 
				
			||||||
 | 
							attr_init(&attr_row[terminal->column], terminal->curr_attr, count);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	case 'Z':    /* CBT */
 | 
						case 'Z':    /* CBT */
 | 
				
			||||||
		count = set[0] ? args[0] : 1;
 | 
							count = set[0] ? args[0] : 1;
 | 
				
			||||||
		if (count == 0) count = 1;
 | 
							if (count == 0) count = 1;
 | 
				
			||||||
| 
						 | 
					@ -923,7 +1014,7 @@ handle_escape(struct terminal *terminal)
 | 
				
			||||||
		terminal->last_char.byte[0] = 0;
 | 
							terminal->last_char.byte[0] = 0;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case 'c':    /* Primary DA */
 | 
						case 'c':    /* Primary DA */
 | 
				
			||||||
		write(terminal->master, "\e[?1;2c", 7);
 | 
							write(terminal->master, "\e[?6c", 5);
 | 
				
			||||||
		sleep(1);
 | 
							sleep(1);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case 'd':    /* VPA */
 | 
						case 'd':    /* VPA */
 | 
				
			||||||
| 
						 | 
					@ -1186,6 +1277,8 @@ handle_special_char(struct terminal *terminal, char c)
 | 
				
			||||||
	case '\t':
 | 
						case '\t':
 | 
				
			||||||
		while (terminal->column < terminal->width) {
 | 
							while (terminal->column < terminal->width) {
 | 
				
			||||||
			if (terminal->tab_ruler[terminal->column]) break;
 | 
								if (terminal->tab_ruler[terminal->column]) break;
 | 
				
			||||||
 | 
								if (terminal->mode & MODE_IRM)
 | 
				
			||||||
 | 
									terminal_shift_line(terminal, +1);
 | 
				
			||||||
			row[terminal->column].byte[0] = ' ';
 | 
								row[terminal->column].byte[0] = ' ';
 | 
				
			||||||
			row[terminal->column].byte[1] = '\0';
 | 
								row[terminal->column].byte[1] = '\0';
 | 
				
			||||||
			attr_row[terminal->column] = terminal->curr_attr;
 | 
								attr_row[terminal->column] = terminal->curr_attr;
 | 
				
			||||||
| 
						 | 
					@ -1259,6 +1352,8 @@ handle_char(struct terminal *terminal, union utf8_char utf8)
 | 
				
			||||||
	row = terminal_get_row(terminal, terminal->row);
 | 
						row = terminal_get_row(terminal, terminal->row);
 | 
				
			||||||
	attr_row = terminal_get_attr_row(terminal, terminal->row);
 | 
						attr_row = terminal_get_attr_row(terminal, terminal->row);
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
 | 
						if (terminal->mode & MODE_IRM)
 | 
				
			||||||
 | 
							terminal_shift_line(terminal, +1);
 | 
				
			||||||
	row[terminal->column] = utf8;
 | 
						row[terminal->column] = utf8;
 | 
				
			||||||
	attr_row[terminal->column++] = terminal->curr_attr;
 | 
						attr_row[terminal->column++] = terminal->curr_attr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1508,7 +1603,7 @@ terminal_run(struct terminal *terminal, const char *path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pid = forkpty(&master, NULL, NULL, NULL);
 | 
						pid = forkpty(&master, NULL, NULL, NULL);
 | 
				
			||||||
	if (pid == 0) {
 | 
						if (pid == 0) {
 | 
				
			||||||
		setenv("TERM", "vt100", 1);
 | 
							setenv("TERM", "vt102", 1);
 | 
				
			||||||
		if (execl(path, path, NULL)) {
 | 
							if (execl(path, path, NULL)) {
 | 
				
			||||||
			printf("exec failed: %m\n");
 | 
								printf("exec failed: %m\n");
 | 
				
			||||||
			exit(EXIT_FAILURE);
 | 
								exit(EXIT_FAILURE);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue