summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--src/caps.c4
-rw-r--r--src/trie.c96
-rw-r--r--src/trie.h3
-rw-r--r--src/vte.c647
-rw-r--r--termcaps/xterm7
-rw-r--r--vte.spec5
7 files changed, 533 insertions, 239 deletions
diff --git a/ChangeLog b/ChangeLog
index 09069180..f6f43fe1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
2002-05-14 nalin
- * src/vte.c: Don't try to draw nul characters, most fonts can't.
+ * src/vte.c: Don't try to draw nul characters, most fonts can't. Don't
+ send motion-tracking events to the child unless we're dragging. Fix
+ ce so that it works even right after startup. Make sure that repainting
+ the entire window actually exposes the visible parts of the window. Fix
+ tab clearing to also allow removal of the current tabstop. Implement
+ save-mode and restore-mode. Start on reverse-video mode. Don't scroll
+ on modifier keypress events. Rework part of clipboard copy.
+ * termcaps/xterm: Add missing F11/F12/End keysyms to bundled xterm
+ termcap.
2002-05-13 nalin
* src/debug.c: Add "ALL" as a debug flag, aliased to everything.
* src/pty.c: Print debug info after redirecting stdio.
diff --git a/src/caps.c b/src/caps.c
index 76cb9880..3d179206 100644
--- a/src/caps.c
+++ b/src/caps.c
@@ -498,8 +498,8 @@ struct vte_capability_string vte_xterm_capability_strings[] = {
{CSI "%d;%d\"p", "set-conformance-level", 0},
{CSI "%d\"q", "select-character-protection", 0},
{CSI "%d;%dr", "set-scrolling-region", 0},
- {CSI "?%dr", "restore-mode", 0},
- {CSI "?%ds", "save-mode", 0},
+ {CSI "?%mr", "restore-mode", 0},
+ {CSI "?%ms", "save-mode", 0},
{CSI "%mt", "window-manipulation", 0},
diff --git a/src/trie.c b/src/trie.c
index d958aa4a..a6dd0600 100644
--- a/src/trie.c
+++ b/src/trie.c
@@ -73,6 +73,11 @@ struct char_class {
/* Extract a parameter. */
};
+/* A table to hold shortcuts. */
+struct vte_trie_table {
+ struct trie_path *paths[128];
+};
+
/* A trie to hold control sequences. */
struct vte_trie {
const char *result; /* If this is a terminal node, then this
@@ -80,12 +85,14 @@ struct vte_trie {
GQuark quark; /* The quark for the value of the
result. */
size_t trie_path_count; /* Number of children of this node. */
- struct {
+ struct trie_path {
struct char_class *cclass;
struct char_class_data data;
struct vte_trie *trie; /* The child node corresponding to this
character. */
} *trie_paths;
+ struct vte_trie_table *table; /* A table filled with pointers to the
+ child nodes. */
};
/* Functions for checking if a particular character is part of a class, and
@@ -342,6 +349,10 @@ vte_trie_free(struct vte_trie *trie)
if (trie->trie_path_count > 0) {
g_free(trie->trie_paths);
}
+ if (trie->table != NULL) {
+ g_free(trie->table);
+ trie->table = NULL;
+ }
g_free(trie);
}
@@ -486,6 +497,8 @@ vte_trie_matchx(struct vte_trie *trie, const wchar_t *pattern, size_t length,
unsigned int i;
const char *hres;
enum cclass cc;
+ ssize_t partial;
+ struct trie_path *path;
const char *best = NULL;
GValueArray *bestarray = NULL;
GQuark bestquark = 0;
@@ -518,6 +531,36 @@ vte_trie_matchx(struct vte_trie *trie, const wchar_t *pattern, size_t length,
}
}
+ /* Try the precomputed table. */
+ if ((trie->table != NULL) &&
+ (pattern[0] < G_N_ELEMENTS(trie->table->paths))) {
+ if (trie->table->paths[pattern[0]] != NULL) {
+ path = trie->table->paths[pattern[0]];
+ if (path->cclass->multiple) {
+ for (partial = 0; partial < length; partial++) {
+ if (trie->table->paths[pattern[partial]] != path) {
+ break;
+ }
+ }
+ } else {
+ partial = 1;
+ }
+ if (partial > 0) {
+ path->cclass->extract(pattern,
+ partial,
+ &path->data,
+ array);
+ return vte_trie_matchx(path->trie,
+ pattern + partial,
+ length - partial,
+ res,
+ consumed,
+ quark,
+ array);
+ }
+ }
+ }
+
/* Now figure out which (if any) subtrees to search. First, see
* which character class this character matches. */
for (cc = exact; cc < invalid; cc++)
@@ -595,6 +638,52 @@ vte_trie_matchx(struct vte_trie *trie, const wchar_t *pattern, size_t length,
return *res;
}
+/* Attempt to precompute all of the paths we might take when passing this
+ * node, and use that information to fill in a table. */
+TRIE_MAYBE_STATIC void
+vte_trie_precompute(struct vte_trie *trie)
+{
+ struct vte_trie_table *table;
+ enum cclass cc;
+ int i;
+ wchar_t c;
+
+ /* Free the precomputed table (if there is one). */
+ if (trie->table != NULL) {
+ g_free(trie->table);
+ trie->table = NULL;
+ }
+
+ /* If there are no child nodes, then there's nothing for us to do. */
+ if (trie->trie_path_count == 0) {
+ return;
+ }
+
+ /* Create a new table and clear it. */
+ table = trie->table = g_malloc(sizeof(*table));
+ for (c = 0; c < G_N_ELEMENTS(trie->table->paths); c++) {
+ trie->table->paths[c] = NULL;
+ }
+
+ /* Decide which path a given character would cause us to take, and
+ * store it at a fixed offset in the table. */
+ for (cc = exact; cc < invalid; cc++)
+ for (i = 0; i < trie->trie_path_count; i++) {
+ struct char_class *cclass = trie->trie_paths[i].cclass;
+ if (cclass->type == cc)
+ for (c = 0; c < G_N_ELEMENTS(trie->table->paths); c++)
+ if (trie->table->paths[c] == NULL)
+ if (cclass->check(c, &trie->trie_paths[i].data)) {
+ trie->table->paths[c] = &trie->trie_paths[i];
+ }
+ }
+
+ /* Precompute the node's children. */
+ for (i = 0; i < trie->trie_path_count; i++) {
+ vte_trie_precompute(trie->trie_paths[i].trie);
+ }
+}
+
/* Check if the given pattern matches part of the given trie, returning an
* empty string on a partial initial match, a NULL if there's no match in the
* works, and the result string if we have an exact match. */
@@ -810,6 +899,11 @@ main(int argc, char **argv)
g_quark_from_string("multimatch"));
vte_trie_add(trie, "<esc>]2;%sh", 11, "decset-title",
g_quark_from_string("decset-title"));
+ if (argc > 1) {
+ if (strcmp(argv[1], "--precompute") == 0) {
+ vte_trie_precompute(trie);
+ }
+ }
vte_trie_print(trie);
g_print("\n");
diff --git a/src/trie.h b/src/trie.h
index 02dc0763..84d8dbfa 100644
--- a/src/trie.h
+++ b/src/trie.h
@@ -57,6 +57,9 @@ const char *vte_trie_match(struct vte_trie *trie,
/* Print the contents of the trie (mainly for diagnostic purposes). */
void vte_trie_print(struct vte_trie *trie);
+/* Precompute internal information to hopefully make traversal faster. */
+void vte_trie_precompute(struct vte_trie *trie);
+
G_END_DECLS
#endif
diff --git a/src/vte.c b/src/vte.c
index b4d0c3f5..73a74ba3 100644
--- a/src/vte.c
+++ b/src/vte.c
@@ -160,7 +160,7 @@ struct _VteTerminalPrivate {
gboolean use_pango;
/* Emulation state. */
- VteKeypad keypad;
+ int keypad;
/* Screen data. We support the normal screen, and an alternate
* screen, which seems to be a DEC-specific feature. */
@@ -173,7 +173,8 @@ struct _VteTerminalPrivate {
/* the current and saved positions of
the [insertion] cursor */
gboolean cursor_visible;
- gboolean insert; /* insert mode */
+ gboolean reverse_mode; /* reverse mode */
+ gboolean insert_mode; /* insert mode */
struct {
int start, end;
} scrolling_region; /* the region we scroll in */
@@ -185,6 +186,9 @@ struct _VteTerminalPrivate {
characters */
} normal_screen, alternate_screen, *screen;
+ /* Saved settings. */
+ GHashTable *dec_saved;
+
/* Selection information. */
gboolean has_selection;
char *selection;
@@ -253,6 +257,7 @@ typedef void (*VteTerminalSequenceHandler)(VteTerminal *terminal,
const char *match,
GQuark match_quark,
GValueArray *params);
+static void vte_terminal_ensure_cursor(VteTerminal *terminal);
static void vte_terminal_insert_char(GtkWidget *widget, wchar_t c,
gboolean force_insert);
static void vte_sequence_handler_clear_screen(VteTerminal *terminal,
@@ -370,6 +375,21 @@ vte_invalidate_cells(VteTerminal *terminal,
gdk_window_invalidate_rect(widget->window, &rect, TRUE);
}
+/* Redraw the entire window. */
+static void
+vte_invalidate_all(VteTerminal *terminal)
+{
+ g_return_if_fail(VTE_IS_TERMINAL(terminal));
+ if (!GTK_IS_WIDGET(terminal) ||
+ !GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
+ return;
+ }
+ vte_invalidate_cells(terminal,
+ 0, terminal->column_count,
+ terminal->pvt->screen->scroll_delta,
+ terminal->row_count);
+}
+
/* Find the character in the given "virtual" position. */
static struct vte_charcell *
vte_terminal_find_charcell(VteTerminal *terminal, long row, long col)
@@ -588,9 +608,7 @@ vte_terminal_deselect_all(VteTerminal *terminal)
if (terminal->pvt->has_selection) {
terminal->pvt->has_selection = FALSE;
vte_terminal_emit_selection_changed (terminal);
- vte_invalidate_cells(terminal,
- 0, terminal->column_count,
- 0, terminal->row_count);
+ vte_invalidate_all(terminal);
}
}
@@ -607,6 +625,18 @@ vte_terminal_set_tabstop(VteTerminal *terminal, int column)
}
}
+/* Remove a tabstop. */
+static void
+vte_terminal_clear_tabstop(VteTerminal *terminal, int column)
+{
+ g_return_if_fail(VTE_IS_TERMINAL(terminal));
+ if (terminal->pvt->tabstops != NULL) {
+ /* Remove a tab stop from the hash table. */
+ g_hash_table_remove(terminal->pvt->tabstops,
+ GINT_TO_POINTER(2 * column + 1));
+ }
+}
+
/* Check if we have a tabstop at a given position. */
static gboolean
vte_terminal_get_tabstop(VteTerminal *terminal, int column)
@@ -1072,18 +1102,24 @@ vte_sequence_handler_cb(VteTerminal *terminal,
/* If the cursor is actually on the screen, clear data in the row
* which corresponds to the cursor. */
if (vte_ring_next(screen->row_data) > screen->cursor_current.row) {
+ struct vte_charcell defaults;
/* Get the data for the row which the cursor points to. */
rowdata = vte_ring_index(screen->row_data,
GArray*,
screen->cursor_current.row);
/* Clear the data up to the current column with the default
* attributes. */
+ memset(&defaults, 0, sizeof(defaults));
+ defaults.fore = screen->defaults.fore;
+ defaults.back = screen->defaults.back;
+ defaults.c = 0;
+ defaults.columns = 1;
for (i = 0;
(i < screen->cursor_current.col) && (i < rowdata->len);
i++) {
pcell = &g_array_index(rowdata, struct vte_charcell, i);
if (pcell != NULL) {
- *pcell = screen->defaults;
+ *pcell = defaults;
}
}
/* Repaint this row. */
@@ -1134,25 +1170,22 @@ vte_sequence_handler_ce(VteTerminal *terminal,
VteScreen *screen;
g_return_if_fail(VTE_IS_TERMINAL(terminal));
screen = terminal->pvt->screen;
- /* If the cursor is actually on the screen, clear data in the row
- * which corresponds to the cursor. */
- if (vte_ring_next(screen->row_data) > screen->cursor_current.row) {
- /* Get the data for the row which the cursor points to. */
- rowdata = vte_ring_index(screen->row_data, GArray*,
- screen->cursor_current.row);
- /* Remove the data at the end of the array. */
- while (rowdata->len > screen->cursor_current.col) {
- g_array_remove_index(rowdata, rowdata->len - 1);
- }
- /* Now insert empty cells with the default attributes. */
- while (rowdata->len < terminal->column_count) {
- g_array_append_val(rowdata, screen->defaults);
- }
- /* Repaint this row. */
- vte_invalidate_cells(terminal,
- 0, terminal->column_count,
- screen->cursor_current.row, 1);
+ /* Get the data for the row which the cursor points to. */
+ vte_terminal_ensure_cursor(terminal);
+ rowdata = vte_ring_index(screen->row_data, GArray*,
+ screen->cursor_current.row);
+ /* Remove the data at the end of the array. */
+ while (rowdata->len > screen->cursor_current.col) {
+ g_array_remove_index(rowdata, rowdata->len - 1);
+ }
+ /* Now insert empty cells with the default attributes. */
+ while (rowdata->len < terminal->column_count) {
+ g_array_append_val(rowdata, screen->defaults);
}
+ /* Repaint this row. */
+ vte_invalidate_cells(terminal,
+ 0, terminal->column_count,
+ screen->cursor_current.row, 1);
}
/* Move the cursor to the given column (horizontal position). */
@@ -1422,11 +1455,7 @@ vte_sequence_handler_dl(VteTerminal *terminal,
vte_remove_line_int(terminal, screen->cursor_current.row);
vte_insert_line_int(terminal, end);
/* Repaint the entire screen. */
- vte_invalidate_cells(terminal,
- 0,
- terminal->column_count,
- terminal->pvt->screen->insert_delta,
- terminal->row_count);
+ vte_invalidate_all(terminal);
}
/* Delete N lines at the current cursor position. */
@@ -1657,7 +1686,7 @@ vte_sequence_handler_ei(VteTerminal *terminal,
GValueArray *params)
{
g_return_if_fail(VTE_IS_TERMINAL(terminal));
- terminal->pvt->screen->insert = FALSE;
+ terminal->pvt->screen->insert_mode = FALSE;
}
/* Move the cursor to the home position. */
@@ -1715,7 +1744,7 @@ vte_sequence_handler_im(VteTerminal *terminal,
GValueArray *params)
{
g_return_if_fail(VTE_IS_TERMINAL(terminal));
- terminal->pvt->screen->insert = TRUE;
+ terminal->pvt->screen->insert_mode = TRUE;
}
/* Send me a backspace key sym, will you? Guess that the application meant
@@ -2167,6 +2196,34 @@ vte_sequence_handler_ta(VteTerminal *terminal,
#endif
}
+/* Clear tabs selectively. */
+static void
+vte_sequence_handler_tab_clear(VteTerminal *terminal,
+ const char *match,
+ GQuark match_quark,
+ GValueArray *params)
+{
+ GValue *value;
+ long param = 0;
+ g_return_if_fail(VTE_IS_TERMINAL(terminal));
+ if ((params != NULL) && (params->n_values > 0)) {
+ value = g_value_array_get_nth(params, 0);
+ if (G_VALUE_HOLDS_LONG(value)) {
+ param = g_value_get_long(value);
+ }
+ }
+ if (param == 0) {
+ vte_terminal_clear_tabstop(terminal,
+ terminal->pvt->screen->cursor_current.col);
+ } else
+ if (param == 3) {
+ if (terminal->pvt->tabstops != NULL) {
+ g_hash_table_destroy(terminal->pvt->tabstops);
+ terminal->pvt->tabstops = NULL;
+ }
+ }
+}
+
/* Terminal usage starts. */
static void
vte_sequence_handler_ts(VteTerminal *terminal,
@@ -2297,20 +2354,12 @@ vte_sequence_handler_up(VteTerminal *terminal,
terminal->row_count - 1,
1);
#else
- vte_invalidate_cells(terminal,
- 0,
- terminal->column_count,
- screen->scroll_delta,
- terminal->row_count);
+ vte_invalidate_all(terminal);
#endif
} else {
/* If we have a background image, we need to
* redraw the entire window. */
- vte_invalidate_cells(terminal,
- 0,
- terminal->column_count,
- screen->scroll_delta,
- terminal->row_count);
+ vte_invalidate_all(terminal);
}
} else {
/* Move the cursor up. */
@@ -2376,11 +2425,7 @@ vte_sequence_handler_vb(VteTerminal *terminal,
terminal->row_count * terminal->char_height);
gdk_window_process_all_updates();
- vte_invalidate_cells(terminal,
- 0,
- terminal->column_count,
- terminal->pvt->screen->scroll_delta,
- terminal->row_count);
+ vte_invalidate_all(terminal);
gdk_window_process_all_updates();
}
}
@@ -2773,141 +2818,148 @@ vte_terminal_set_pointer_visible(VteTerminal *terminal, gboolean visible)
/* Manipulate certain terminal attributes. */
static void
vte_sequence_handler_decset_internal(VteTerminal *terminal,
- const char *match,
- GQuark match_quark,
- GValueArray *params,
+ int setting,
+ gboolean restore,
+ gboolean save,
gboolean set)
{
- GValue *value;
- GtkWidget *widget;
- long param;
+ gpointer p;
int i;
+ struct {
+ int setting;
+ gboolean *bvalue;
+ gint *ivalue;
+ gpointer *pvalue;
+ gpointer fvalue;
+ gpointer tvalue;
+ } settings[] = {
+ /* Application/normal keypad. */
+ {1, NULL, &terminal->pvt->keypad, NULL,
+ GINT_TO_POINTER(VTE_KEYPAD_NORMAL),
+ GINT_TO_POINTER(VTE_KEYPAD_APPLICATION),},
+ /* Reverse video. */
+ {5, &terminal->pvt->screen->reverse_mode, NULL, NULL,
+ GINT_TO_POINTER(FALSE),
+ GINT_TO_POINTER(TRUE),},
+ /* Send-coords-on-click. */
+ {9, &terminal->pvt->mouse_send_xy_on_click, NULL, NULL,
+ GINT_TO_POINTER(FALSE),
+ GINT_TO_POINTER(TRUE),},
+ /* Cursor visible. */
+ {25, &terminal->pvt->screen->cursor_visible, NULL, NULL,
+ GINT_TO_POINTER(FALSE),
+ GINT_TO_POINTER(TRUE),},
+ /* Alternate screen. */
+ {47, NULL, NULL, (gpointer*) &terminal->pvt->screen,
+ &terminal->pvt->normal_screen,
+ &terminal->pvt->alternate_screen,},
+ /* Send-coords-on-button. */
+ {1000, &terminal->pvt->mouse_send_xy_on_button, NULL, NULL,
+ GINT_TO_POINTER(FALSE),
+ GINT_TO_POINTER(TRUE),},
+ /* Hilite tracking*/
+ {1001, &terminal->pvt->mouse_hilite_tracking, NULL, NULL,
+ GINT_TO_POINTER(FALSE),
+ GINT_TO_POINTER(TRUE),},
+ /* Cell motion tracking*/
+ {1002, &terminal->pvt->mouse_cell_motion_tracking, NULL, NULL,
+ GINT_TO_POINTER(FALSE),
+ GINT_TO_POINTER(TRUE),},
+ /* All motion tracking*/
+ {1003, &terminal->pvt->mouse_all_motion_tracking, NULL, NULL,
+ GINT_TO_POINTER(FALSE),
+ GINT_TO_POINTER(TRUE),},
+ };
+
g_return_if_fail(VTE_IS_TERMINAL(terminal));
- widget = GTK_WIDGET(terminal);
- if ((params == NULL) || (params->n_values == 0)) {
- return;
- }
- for (i = 0; i < params->n_values; i++) {
- value = g_value_array_get_nth(params, i);
- if (!G_VALUE_HOLDS_LONG(value)) {
- continue;
- }
- param = g_value_get_long(value);
- switch (param) {
- case 1:
- /* Set the application keypad. */
- terminal->pvt->keypad = set ?
- VTE_KEYPAD_NORMAL :
- VTE_KEYPAD_APPLICATION;
- break;
- case 2:
- /* FIXME: reset alternate character sets to
- * ASCII. */
- break;
- case 3:
- /* FIXME: set 132 (reset to 80) column mode. */
- break;
- case 4:
- /* FIXME: set or unset smooth-scrolling. */
- break;
- case 5:
- /* normal or reverse video. */
- terminal->pvt->screen->defaults.reverse = set;
- break;
- case 6:
- /* FIXME: origin or normal cursor mode. */
- break;
- case 7:
- /* FIXME: set or unset wraparound mode. */
- break;
- case 8:
- /* FIXME: set or unset autorepeat keys. */
- break;
- case 9:
-#ifdef VTE_DEBUG
- if (vte_debug_on(VTE_DEBUG_IO)) {
- fprintf(stderr, "Setting send-coords-on-click "
- "to %s.\n", set ? "ON" : "OFF");
- }
-#endif
- terminal->pvt->mouse_send_xy_on_click = set;
- break;
- case 25:
- terminal->pvt->screen->cursor_visible = set;
- break;
- case 38:
- /* FIXME: Tektronix/Xterm mode. */
- break;
- case 40:
- /* FIXME: Allow/disallow 80/132 column mode. */
- break;
- case 41:
- /* FIXME: more(1) fix. */
- break;
- case 44:
- /* FIXME: set/unset margin bell. */
- break;
- case 45:
- /* FIXME: set/unset reverse-wraparound mode. */
- break;
- case 46:
- /* FIXME(?): enable/disable logging. */
- break;
- case 47:
- /* Set or restore alternate screen. */
- terminal->pvt->screen = set ?
- &terminal->pvt->alternate_screen :
- &terminal->pvt->normal_screen;
- /* Fixup the scrollbars. */
- vte_terminal_adjust_adjustments(terminal);
- /* Force the screen to be redrawn. */
- vte_invalidate_cells(terminal,
- 0,
- terminal->column_count,
- terminal->pvt->screen->scroll_delta,
- terminal->row_count);
- break;
- case 1000:
-#ifdef VTE_DEBUG
- if (vte_debug_on(VTE_DEBUG_PARSE)) {
- fprintf(stderr, "Setting send-coords-on"
- "-button to %s.\n",
- set ? "ON" : "OFF");
- }
-#endif
- terminal->pvt->mouse_send_xy_on_button = set;
- break;
- case 1001:
+
+ /* Handle the setting. */
+ for (i = 0; i < G_N_ELEMENTS(settings); i++)
+ if (settings[i].setting == setting) {
+ /* Read the old setting. */
+ if (restore) {
+ p = g_hash_table_lookup(terminal->pvt->dec_saved,
+ GINT_TO_POINTER(setting));
+ set = (p != NULL);
#ifdef VTE_DEBUG
- if (vte_debug_on(VTE_DEBUG_PARSE)) {
- fprintf(stderr, "Setting hilite-"
- "tracking to %s.\n",
- set ? "ON" : "OFF");
- }
+ if (vte_debug_on(VTE_DEBUG_PARSE)) {
+ fprintf(stderr, "Setting %d was %s.\n",
+ setting, set ? "set" : "unset");
+ }
#endif
- terminal->pvt->mouse_hilite_tracking = set;
- break;
- case 1002:
+ }
+ /* Save the current setting. */
+ if (save) {
+ if (settings[i].bvalue) {
+ set = *(settings[i].bvalue) != FALSE;
+ } else
+ if (settings[i].ivalue) {
+ set = *(settings[i].ivalue) ==
+ GPOINTER_TO_INT(settings[i].tvalue);
+ } else
+ if (settings[i].pvalue) {
+ set = *(settings[i].pvalue) ==
+ settings[i].tvalue;
+ }
#ifdef VTE_DEBUG
- if (vte_debug_on(VTE_DEBUG_PARSE)) {
- fprintf(stderr, "Setting cell-tracking "
- "to %s.\n", set ? "ON" : "OFF");
- }
+ if (vte_debug_on(VTE_DEBUG_PARSE)) {
+ fprintf(stderr, "Setting %d is %s, saving.\n",
+ setting, set ? "set" : "unset");
+ }
#endif
- terminal->pvt->mouse_cell_motion_tracking = set;
- break;
- case 1003:
+ g_hash_table_insert(terminal->pvt->dec_saved,
+ GINT_TO_POINTER(setting),
+ GINT_TO_POINTER(set));
+ }
+ /* Change the current setting to match the new/saved value. */
+ if (!save) {
#ifdef VTE_DEBUG
- if (vte_debug_on(VTE_DEBUG_PARSE)) {
- fprintf(stderr, "Setting all-tracking "
- "to %s.\n", set ? "ON" : "OFF");
- }
+ if (vte_debug_on(VTE_DEBUG_PARSE)) {
+ fprintf(stderr, "Setting %d to %s.\n",
+ setting, set ? "set" : "unset");
+ }
#endif
- terminal->pvt->mouse_all_motion_tracking = set;
- default:
- break;
+ if (settings[i].bvalue) {
+ *(settings[i].bvalue) = set;
+ } else
+ if (settings[i].ivalue) {
+ *(settings[i].ivalue) = set ?
+ GPOINTER_TO_INT(settings[i].tvalue) :
+ GPOINTER_TO_INT(settings[i].fvalue);
+ } else
+ if (settings[i].pvalue) {
+ *(settings[i].pvalue) = set ?
+ settings[i].tvalue :
+ settings[i].fvalue;
+ }
}
- vte_terminal_set_pointer_visible(terminal, TRUE);
+ }
+
+ /* Do whatever's necessary when the setting changes. */
+ switch (setting) {
+ case 5:
+ /* Repaint everything in reverse mode. */
+ vte_invalidate_all(terminal);
+ break;
+ case 25:
+ /* Repaint the cell the cursor is in. */
+ vte_invalidate_cursor_once(terminal);
+ break;
+ case 47:
+ /* Reset scrollbars and repaint everything. */
+ vte_terminal_adjust_adjustments(terminal);
+ vte_invalidate_all(terminal);
+ break;
+ case 9:
+ case 1000:
+ case 1001:
+ case 1002:
+ case 1003:
+ /* Make the pointer visible. */
+ vte_terminal_set_pointer_visible(terminal, TRUE);
+ break;
+ default:
+ break;
}
}
@@ -2961,9 +3013,22 @@ vte_sequence_handler_decset(VteTerminal *terminal,
GQuark match_quark,
GValueArray *params)
{
+ GValue *value;
+ long setting;
+ int i;
g_return_if_fail(VTE_IS_TERMINAL(terminal));
- vte_sequence_handler_decset_internal(terminal, match, match_quark,
- params, TRUE);
+ if ((params == NULL) || (params->n_values == 0)) {
+ return;
+ }
+ for (i = 0; i < params->n_values; i++) {
+ value = g_value_array_get_nth(params, i);
+ if (!G_VALUE_HOLDS_LONG(value)) {
+ continue;
+ }
+ setting = g_value_get_long(value);
+ vte_sequence_handler_decset_internal(terminal, setting,
+ FALSE, FALSE, TRUE);
+ }
}
/* Unset certain terminal attributes. */
@@ -2973,9 +3038,22 @@ vte_sequence_handler_decreset(VteTerminal *terminal,
GQuark match_quark,
GValueArray *params)
{
+ GValue *value;
+ long setting;
+ int i;
g_return_if_fail(VTE_IS_TERMINAL(terminal));
- vte_sequence_handler_decset_internal(terminal, match, match_quark,
- params, FALSE);
+ if ((params == NULL) || (params->n_values == 0)) {
+ return;
+ }
+ for (i = 0; i < params->n_values; i++) {
+ value = g_value_array_get_nth(params, i);
+ if (!G_VALUE_HOLDS_LONG(value)) {
+ continue;
+ }
+ setting = g_value_get_long(value);
+ vte_sequence_handler_decset_internal(terminal, setting,
+ FALSE, FALSE, FALSE);
+ }
}
/* Erase certain lines in the display. */
@@ -3303,6 +3381,56 @@ vte_sequence_handler_dec_device_status_report(VteTerminal *terminal,
}
}
+/* Restore a certain terminal attribute. */
+static void
+vte_sequence_handler_restore_mode(VteTerminal *terminal,
+ const char *match,
+ GQuark match_quark,
+ GValueArray *params)
+{
+ GValue *value;
+ long setting;
+ int i;
+ g_return_if_fail(VTE_IS_TERMINAL(terminal));
+ if ((params == NULL) || (params->n_values == 0)) {
+ return;
+ }
+ for (i = 0; i < params->n_values; i++) {
+ value = g_value_array_get_nth(params, i);
+ if (!G_VALUE_HOLDS_LONG(value)) {
+ continue;
+ }
+ setting = g_value_get_long(value);
+ vte_sequence_handler_decset_internal(terminal, setting,
+ TRUE, FALSE, FALSE);
+ }
+}
+
+/* Save a certain terminal attribute. */
+static void
+vte_sequence_handler_save_mode(VteTerminal *terminal,
+ const char *match,
+ GQuark match_quark,
+ GValueArray *params)
+{
+ GValue *value;
+ long setting;
+ int i;
+ g_return_if_fail(VTE_IS_TERMINAL(terminal));
+ if ((params == NULL) || (params->n_values == 0)) {
+ return;
+ }
+ for (i = 0; i < params->n_values; i++) {
+ value = g_value_array_get_nth(params, i);
+ if (!G_VALUE_HOLDS_LONG(value)) {
+ continue;
+ }
+ setting = g_value_get_long(value);
+ vte_sequence_handler_decset_internal(terminal, setting,
+ FALSE, TRUE, FALSE);
+ }
+}
+
/* Perform a soft reset. */
static void
vte_sequence_handler_soft_reset(VteTerminal *terminal,
@@ -3418,9 +3546,7 @@ vte_sequence_handler_window_manipulation(VteTerminal *terminal,
fprintf(stderr, "Refreshing window.\n");
}
#endif
- vte_invalidate_cells(terminal,
- 0, terminal->column_count,
- 0, terminal->row_count);
+ vte_invalidate_all(terminal);
vte_terminal_emit_refresh_window(terminal);
break;
case 8:
@@ -4074,11 +4200,11 @@ static struct {
{"request-terminal-parameters", NULL},
{"reset-mode", NULL},
{"restore-cursor", vte_sequence_handler_rc},
- {"restore-mode", NULL},
+ {"restore-mode", vte_sequence_handler_restore_mode},
{"return-terminal-id", NULL},
{"reverse-index", vte_sequence_handler_reverse_index},
{"save-cursor", vte_sequence_handler_sc},
- {"save-mode", NULL},
+ {"save-mode", vte_sequence_handler_save_mode},
{"screen-alignment-test", NULL},
{"scroll-down", NULL},
{"scroll-up", NULL},
@@ -4099,7 +4225,7 @@ static struct {
{"single-width", NULL},
{"soft-reset", vte_sequence_handler_soft_reset},
{"start-of-guarded-area", NULL},
- {"tab-clear", vte_sequence_handler_ct},
+ {"tab-clear", vte_sequence_handler_tab_clear},
{"tab-set", vte_sequence_handler_st},
{"utf-8-character-set", vte_sequence_handler_utf_8_charset},
{"window-manipulation", vte_sequence_handler_window_manipulation},
@@ -4221,11 +4347,7 @@ vte_terminal_set_colors(VteTerminal *terminal,
/* This may have changed the default background color, so trigger
* a repaint. */
- vte_invalidate_cells(terminal,
- 0,
- terminal->column_count,
- terminal->pvt->screen->scroll_delta,
- terminal->row_count);
+ vte_invalidate_all(terminal);
}
/* Reset palette defaults for character colors. */
@@ -4273,7 +4395,7 @@ vte_terminal_insert_char(GtkWidget *widget, wchar_t c, gboolean force_insert)
g_return_if_fail(VTE_IS_TERMINAL(widget));
terminal = VTE_TERMINAL(widget);
screen = terminal->pvt->screen;
- insert = terminal->pvt->screen->insert || force_insert;
+ insert = terminal->pvt->screen->insert_mode || force_insert;
#ifdef VTE_DEBUG
if (vte_debug_on(VTE_DEBUG_IO)) {
@@ -4310,11 +4432,7 @@ vte_terminal_insert_char(GtkWidget *widget, wchar_t c, gboolean force_insert)
/* Read the deltas. */
for (i = 0; i < columns; i++) {
col = terminal->pvt->screen->cursor_current.col;
-
- /* Initialize a spare cell which we may insert many times. */
- cell = terminal->pvt->screen->defaults;
- cell.c = ' ';
- cell.columns = wcwidth(cell.c);
+ cell = screen->defaults;
/* Make sure we have enough columns in this row. */
if (array->len <= col) {
@@ -4345,8 +4463,12 @@ vte_terminal_insert_char(GtkWidget *widget, wchar_t c, gboolean force_insert)
}
}
- /* Set the character cell to match the current defaults. */
+ /* Set the character cell's attributes to match the current
+ * defaults, preserving any previous contents. */
+ cell = *pcell;
*pcell = terminal->pvt->screen->defaults;
+ pcell->c = cell.c;
+ pcell->columns = cell.columns;
if (i == 0) {
if ((pcell->c != 0) &&
(c == '_') &&
@@ -4356,7 +4478,7 @@ vte_terminal_insert_char(GtkWidget *widget, wchar_t c, gboolean force_insert)
} else {
/* Insert the character. */
pcell->c = c;
- pcell->columns = wcwidth(c);
+ pcell->columns = columns;
}
}
@@ -4448,7 +4570,7 @@ vte_terminal_handle_sequence(GtkWidget *widget,
/* Signal that the cursor's current position needs redrawing. */
vte_invalidate_cells(terminal,
- screen->cursor_current.col - 1, 3,
+ screen->cursor_current.col - 1, 1,
screen->cursor_current.row, 1);
/* Find the handler for this control sequence. */
@@ -4468,7 +4590,7 @@ vte_terminal_handle_sequence(GtkWidget *widget,
/* We probably need to update the cursor's new position, too. */
vte_invalidate_cells(terminal,
- screen->cursor_current.col - 1, 3,
+ screen->cursor_current.col - 1, 1,
screen->cursor_current.row, 1);
/* Let the updating begin. */
@@ -4974,7 +5096,9 @@ vte_terminal_process_incoming(gpointer data)
if ((cursor_row != terminal->pvt->screen->cursor_current.row) ||
(cursor_col != terminal->pvt->screen->cursor_current.col)) {
- /* Signal that the cursor moved. */
+ /* Signal that the cursor moved and ensure that we have row
+ * data for the current row. */
+ vte_terminal_ensure_cursor(terminal);
vte_terminal_emit_cursor_moved(terminal);
}
@@ -5421,7 +5545,7 @@ vte_terminal_key_press(GtkWidget *widget, GdkEventKey *event)
struct termios tio;
struct timeval tv;
struct timezone tz;
- gboolean scrolled = FALSE, steal = FALSE;
+ gboolean scrolled = FALSE, steal = FALSE, modifier = FALSE;
g_return_val_if_fail(widget != NULL, FALSE);
g_return_val_if_fail(VTE_IS_TERMINAL(widget), FALSE);
@@ -5464,8 +5588,36 @@ vte_terminal_key_press(GtkWidget *widget, GdkEventKey *event)
steal = FALSE;
}
}
- /* Hide the mouse cursor. */
- vte_terminal_set_pointer_visible(terminal, FALSE);
+ /* Determine if this is just a modifier key. */
+ switch (event->keyval) {
+ case GDK_Caps_Lock:
+ case GDK_Control_L:
+ case GDK_Control_R:
+ case GDK_Eisu_Shift:
+ case GDK_ISO_First_Group_Lock:
+ case GDK_ISO_Group_Lock:
+ case GDK_ISO_Group_Shift:
+ case GDK_ISO_Last_Group_Lock:
+ case GDK_ISO_Level3_Lock:
+ case GDK_ISO_Level3_Shift:
+ case GDK_ISO_Lock:
+ case GDK_ISO_Next_Group_Lock:
+ case GDK_ISO_Prev_Group_Lock:
+ case GDK_Kana_Lock:
+ case GDK_Kana_Shift:
+ case GDK_Num_Lock:
+ case GDK_Scroll_Lock:
+ case GDK_Shift_L:
+ case GDK_Shift_Lock:
+ case GDK_Shift_R:
+ modifier = TRUE;
+ default:
+ modifier = FALSE;
+ }
+ /* Unless it's a modifier key, hide the pointer. */
+ if (!modifier) {
+ vte_terminal_set_pointer_visible(terminal, FALSE);
+ }
}
/* Let the input method at this one first. */
@@ -5689,7 +5841,7 @@ vte_terminal_key_press(GtkWidget *widget, GdkEventKey *event)
g_free(special);
}
/* Keep the cursor on-screen. */
- if (!scrolled &&
+ if (!scrolled && !modifier &&
((normal != NULL) || (special != NULL)) &&
terminal->pvt->scroll_on_keystroke) {
vte_terminal_scroll_to_bottom(terminal);
@@ -6039,7 +6191,8 @@ vte_terminal_motion_notify(GtkWidget *widget, GdkEventMotion *event)
modifiers = 0;
}
/* Handle a drag event. */
- if ((terminal->pvt->mouse_send_xy_on_button ||
+ if ((terminal->pvt->mouse_last_button != 0) &&
+ (terminal->pvt->mouse_send_xy_on_button ||
terminal->pvt->mouse_send_xy_on_click ||
terminal->pvt->mouse_hilite_tracking ||
terminal->pvt->mouse_cell_motion_tracking ||
@@ -6166,7 +6319,8 @@ vte_terminal_copy(VteTerminal *terminal, GdkAtom board)
{
GtkClipboard *clipboard;
GtkWidget *widget;
- long x, y;
+ GArray *row_data;
+ long x, y, nuls;
VteScreen *screen;
struct vte_charcell *pcell;
wchar_t *buffer;
@@ -6187,24 +6341,46 @@ vte_terminal_copy(VteTerminal *terminal, GdkAtom board)
/* Build a buffer with the selected wide chars. */
screen = terminal->pvt->screen;
- buffer = g_malloc((terminal->column_count + 1) *
- terminal->row_count * sizeof(wchar_t));
+ length = 0;
+ for (y = screen->scroll_delta;
+ y < terminal->row_count + screen->scroll_delta;
+ y++) {
+ row_data = vte_ring_index(screen->row_data, GArray *, y);
+ if (row_data != NULL) {
+ length += row_data->len;
+ }
+ }
+ buffer = g_malloc((length * 2 + 1) * sizeof(wchar_t));
+
length = 0;
for (y = screen->scroll_delta;
y < terminal->row_count + screen->scroll_delta;
y++) {
x = 0;
+ nuls = 0;
do {
pcell = vte_terminal_find_charcell(terminal, y, x);
if (vte_cell_is_selected(terminal, y, x)) {
- if ((pcell != NULL) && (pcell->c != 0)) {
- if (pcell->columns > 0) {
- buffer[length++] = pcell->c;
- }
- } else {
+ if (pcell == NULL) {
+ /* If there are no more cells on this
+ * line, and we've hit the right margin,
+ * add a newline. */
if (x < terminal->column_count) {
buffer[length++] = '\n';
}
+ break;
+ } else
+ if (pcell->c == 0) {
+ /* Count this NUL in case there's
+ * something to the right of it. */
+ nuls++;
+ } else {
+ /* Stuff any saved NULs in as spaces. */
+ while (nuls-- > 0) {
+ buffer[length++] = ' ';
+ }
+ /* Stuff the charcter in this cell. */
+ buffer[length++] = pcell->c;
}
}
x++;
@@ -6950,9 +7126,7 @@ vte_terminal_set_font(VteTerminal *terminal,
}
/* Make sure the entire window gets repainted. */
- vte_invalidate_cells(terminal,
- 0, terminal->column_count,
- 0, terminal->row_count);
+ vte_invalidate_all(terminal);
}
void
@@ -7055,11 +7229,7 @@ vte_handle_scroll(VteTerminal *terminal)
} else {
/* If we have a background image, we need to redraw
* the entire window. */
- vte_invalidate_cells(terminal,
- 0,
- terminal->column_count,
- screen->scroll_delta,
- terminal->row_count);
+ vte_invalidate_all(terminal);
}
}
/* Let the refreshing begin. */
@@ -7239,6 +7409,13 @@ vte_terminal_reset_rowdata(VteRing **ring, long lines)
VteRing *new_ring;
GArray *row;
long i, next;
+
+#ifdef VTE_DEBUG
+ if (vte_debug_on(VTE_DEBUG_MISC)) {
+ fprintf(stderr, "Sizing scrollback buffer to %ld lines.\n",
+ lines);
+ }
+#endif
new_ring = vte_ring_new(lines, vte_free_row_data, NULL);
if (*ring) {
next = vte_ring_next(*ring);
@@ -7386,7 +7563,8 @@ vte_terminal_init(VteTerminal *terminal, gpointer *klass)
pvt->normal_screen.cursor_visible = TRUE;
pvt->normal_screen.insert_delta = 0;
pvt->normal_screen.scroll_delta = 0;
- pvt->normal_screen.insert = FALSE;
+ pvt->normal_screen.insert_mode = FALSE;
+ pvt->normal_screen.reverse_mode = FALSE;
vte_terminal_reset_rowdata(&pvt->alternate_screen.row_data,
pvt->scrollback_lines);
@@ -7397,7 +7575,8 @@ vte_terminal_init(VteTerminal *terminal, gpointer *klass)
pvt->alternate_screen.cursor_visible = TRUE;
pvt->alternate_screen.insert_delta = 0;
pvt->alternate_screen.scroll_delta = 0;
- pvt->alternate_screen.insert = FALSE;
+ pvt->alternate_screen.insert_mode = FALSE;
+ pvt->alternate_screen.reverse_mode = FALSE;
pvt->screen = &terminal->pvt->alternate_screen;
vte_terminal_set_default_attributes(terminal);
@@ -7441,6 +7620,7 @@ vte_terminal_init(VteTerminal *terminal, gpointer *klass)
/* Set various other settings. */
pvt->xterm_font_tweak = FALSE;
vte_terminal_set_default_tabstops(terminal);
+ pvt->dec_saved = g_hash_table_new(g_direct_hash, g_direct_equal);
}
/* Tell GTK+ how much space we need. */
@@ -7675,6 +7855,12 @@ vte_terminal_finalize(GObject *object)
vte_ring_free(terminal->pvt->alternate_screen.row_data, TRUE);
terminal->pvt->alternate_screen.row_data = NULL;
+ /* Remove hash tables. */
+ if (terminal->pvt->dec_saved != NULL) {
+ g_hash_table_destroy(terminal->pvt->dec_saved);
+ terminal->pvt->dec_saved = NULL;
+ }
+
/* Free strings. */
g_free(terminal->window_title);
terminal->window_title = NULL;
@@ -7909,9 +8095,10 @@ vte_terminal_draw_char(VteTerminal *terminal,
/* Determine what the foreground and background colors for rendering
* text should be. */
- reverse = cell && cell->reverse;
- reverse = reverse ^ vte_cell_is_selected(terminal, row, col);
- reverse = reverse || cursor;
+ reverse = (cell && cell->reverse)
+ ^ vte_cell_is_selected(terminal, row, col)
+ ^ screen->reverse_mode
+ ^ cursor;
vte_terminal_determine_colors(terminal, cell, reverse, &fore, &back);
/* Paint the background for the cell. */
@@ -9488,11 +9675,7 @@ vte_terminal_setup_background(VteTerminal *terminal,
}
/* Force a redraw for everything. */
- vte_invalidate_cells(terminal,
- 0,
- terminal->column_count,
- terminal->pvt->screen->scroll_delta,
- terminal->row_count);
+ vte_invalidate_all(terminal);
}
void
@@ -9776,9 +9959,7 @@ vte_terminal_set_scrollback_lines(VteTerminal *terminal, long lines)
/* Adjust the scrollbars to the new locations. */
vte_terminal_adjust_adjustments(terminal);
- vte_invalidate_cells(terminal,
- 0, terminal->column_count,
- 0, terminal->row_count);
+ vte_invalidate_all(terminal);
}
/* Get a snapshot of what's in the visible part of the window. */
@@ -10023,10 +10204,12 @@ vte_terminal_reset(VteTerminal *terminal, gboolean full, gboolean clear_history)
/* Reset restricted scrolling regions, leave insert mode, make
* the cursor visible again. */
terminal->pvt->normal_screen.scrolling_restricted = FALSE;
- terminal->pvt->normal_screen.insert = FALSE;
+ terminal->pvt->normal_screen.insert_mode = FALSE;
+ terminal->pvt->normal_screen.reverse_mode = FALSE;
terminal->pvt->normal_screen.cursor_visible = TRUE;
terminal->pvt->alternate_screen.scrolling_restricted = FALSE;
- terminal->pvt->alternate_screen.insert = FALSE;
+ terminal->pvt->alternate_screen.insert_mode = FALSE;
+ terminal->pvt->alternate_screen.reverse_mode = FALSE;
terminal->pvt->alternate_screen.cursor_visible = TRUE;
/* Reset the input and output buffers. */
if (terminal->pvt->n_incoming > 0) {
diff --git a/termcaps/xterm b/termcaps/xterm
index 2222b20c..c6e97316 100644
--- a/termcaps/xterm
+++ b/termcaps/xterm
@@ -1,4 +1,5 @@
-# This is a cut-down version of the termcap file from my box.
+# This is a cut-down version of the termcap file from my box, with @7,
+# F1-FA added.
xterm-xfree86|xterm-new|xterm terminal emulator (XFree86):\
:am:km:mi:ms:xn:\
:co#80:it#8:li#24:\
@@ -15,7 +16,9 @@ xterm-xfree86|xterm-new|xterm terminal emulator (XFree86):\
:me=\E[m\017:mr=\E[7m:nd=\E[C:rc=\E8:sc=\E7:se=\E[27m:\
:sf=^J:so=\E[7m:sr=\EM:st=\EH:ta=^I:te=\E[?1047l\E[?1048l:\
:ti=\E[?1048h\E[?1047h:ue=\E[24m:up=\E[A:us=\E[4m:\
- :vb=\E[?5h\E[?5l:ve=\E[?25h:vi=\E[?25l:vs=\E[?25h:
+ :vb=\E[?5h\E[?5l:ve=\E[?25h:vi=\E[?25l:vs=\E[?25h:@7=\E[4~:\
+ :F1=\E[23~:F2=\E[24~:F3=\E[25~:F4=\E[26~:F5=\E[28~:\
+ :F6=\E[29~:F7=\E[31~:F8=\E[32~:F9=\E[33~:FA=\E[34~:
# xterm-redhat is identical to xterm-xfree86 with the addition of a small
# VT220-ism regarding the backspace and delete keys; this is mandated by
# the keyboard configuration section of the Debian Policy Manual.
diff --git a/vte.spec b/vte.spec
index 22ee4287..62b30dd6 100644
--- a/vte.spec
+++ b/vte.spec
@@ -1,5 +1,5 @@
Name: vte
-Version: 0.3.14
+Version: 0.3.15
Release: 1
Summary: An experimental terminal emulator.
License: LGPL
@@ -53,6 +53,9 @@ make install DESTDIR=$RPM_BUILD_ROOT
%{_libdir}/pkgconfig/*
%changelog
+* Wed May 15 2002 Nalin Dahyabhai <nalin@redhat.com> 0.3.15-1
+- fix ce, implement save/restore mode
+
* Tue May 14 2002 Nalin Dahyabhai <nalin@redhat.com> 0.3.14-1
- don't draw nul chars