[PATCH 07/10] terminal: vt102 editing commands

Callum Lowcay callum at callumscode.com
Fri Jan 7 11:47:00 PST 2011


Implement the vt102 editing commands, and insert/replace mode.

Signed-off-by: Callum Lowcay <callum at callumscode.com>
---
 clients/terminal.c |   99 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 97 insertions(+), 2 deletions(-)

diff --git a/clients/terminal.c b/clients/terminal.c
index 60da93a..88864c3 100644
--- a/clients/terminal.c
+++ b/clients/terminal.c
@@ -62,6 +62,7 @@ static int option_fullscreen;
 #define MODE_AUTOWRAP		0x00000004
 #define MODE_AUTOREPEAT		0x00000008
 #define MODE_LF_NEWLINE		0x00000010
+#define MODE_IRM		0x00000020
 
 union utf8_char {
 	unsigned char byte[4];
@@ -394,6 +395,40 @@ terminal_scroll(struct terminal *terminal, int 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
 terminal_resize(struct terminal *terminal, int width, int height)
 {
 	size_t size;
@@ -724,6 +759,10 @@ handle_term_parameter(struct terminal *terminal, int code, int sr)
 		}
 	} else {
 		switch(code) {
+		case 4:  /* IRM */
+			if (sr)	terminal->mode |=  MODE_IRM;
+			else	terminal->mode &= ~MODE_IRM;
+			break;
 		case 20: /* LNM */
 			if (sr)	terminal->mode |=  MODE_LF_NEWLINE;
 			else	terminal->mode &= ~MODE_LF_NEWLINE;
@@ -763,6 +802,11 @@ handle_escape(struct terminal *terminal)
 	}
 	
 	switch (*p) {
+	case '@':    /* ICH */
+		count = set[0] ? args[0] : 1;
+		if (count == 0) count = 1;
+		terminal_shift_line(terminal, count);
+		break;
 	case 'A':    /* CUU */
 		count = set[0] ? args[0] : 1;
 		if (count == 0) count = 1;
@@ -893,12 +937,59 @@ handle_escape(struct terminal *terminal)
 			attr_init(attr_row, terminal->curr_attr, terminal->width);
 		}
 		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 */
 		terminal_scroll(terminal, set[0] ? args[0] : 1);
 		break;
 	case 'T':    /* SD */
 		terminal_scroll(terminal, 0 - (set[0] ? args[0] : 1));
 		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 */
 		count = set[0] ? args[0] : 1;
 		if (count == 0) count = 1;
@@ -923,7 +1014,7 @@ handle_escape(struct terminal *terminal)
 		terminal->last_char.byte[0] = 0;
 		break;
 	case 'c':    /* Primary DA */
-		write(terminal->master, "\e[?1;2c", 7);
+		write(terminal->master, "\e[?6c", 5);
 		sleep(1);
 		break;
 	case 'd':    /* VPA */
@@ -1186,6 +1277,8 @@ handle_special_char(struct terminal *terminal, char c)
 	case '\t':
 		while (terminal->column < terminal->width) {
 			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[1] = '\0';
 			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);
 	attr_row = terminal_get_attr_row(terminal, terminal->row);
 	
+	if (terminal->mode & MODE_IRM)
+		terminal_shift_line(terminal, +1);
 	row[terminal->column] = utf8;
 	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);
 	if (pid == 0) {
-		setenv("TERM", "vt100", 1);
+		setenv("TERM", "vt102", 1);
 		if (execl(path, path, NULL)) {
 			printf("exec failed: %m\n");
 			exit(EXIT_FAILURE);
-- 
1.7.3.3



More information about the wayland-devel mailing list