summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--src/interpret.c2
-rw-r--r--src/ring.c2
-rw-r--r--src/trie.c127
-rw-r--r--src/trie.h3
-rw-r--r--src/vte.c490
-rw-r--r--src/vte.h13
-rw-r--r--src/vteaccess.c5
-rw-r--r--src/vteapp.c2
-rw-r--r--vte.spec2
10 files changed, 496 insertions, 160 deletions
diff --git a/ChangeLog b/ChangeLog
index fc0cc77..e6b8af2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2002-05-02 nalin
+ * src/trie.c: Rework trie matching to return the address of the
+ character which ended the match attempt, which should cut down on
+ useless initial-substring checks. Remove several gdk_window_scroll()
+ calls which apparently aren't buffered. Convert invalid multibyte
+ characters to '?' instead of just dropping them. Provide a means of
+ setting the backspace/delete bindings. Add a poor xlfd_from_pango
+ mapping function which would need serious work to be useful. Get rid
+ of warnings when we're transparent and the root widnow pixmap isn't as
+ big as the root window because it's tiled.
2002-05-01 nalin
* src/vte.c: Try @pkgdatadir@/termcap/$TERM when reading termcap files.
This fixes the app on systems with no /etc/termcap, and also speeds up
diff --git a/src/interpret.c b/src/interpret.c
index 8eabdd6..c393314 100644
--- a/src/interpret.c
+++ b/src/interpret.c
@@ -100,7 +100,7 @@ main(int argc, char **argv)
size_t wbuflen;
convert_mbstowcs(array->data, i, wbuf, &wbuflen);
vte_trie_match(trie, wbuf, wbuflen,
- &tmp, &quark, &values);
+ &tmp, NULL, &quark, &values);
if (tmp != NULL) {
if (strlen(tmp) > 0) {
int j;
diff --git a/src/ring.c b/src/ring.c
index 134c78f..0c99394 100644
--- a/src/ring.c
+++ b/src/ring.c
@@ -30,6 +30,7 @@ struct _VteRing {
long delta, length, max;
};
+#ifdef VTE_DEBUG
static void
vte_ring_validate(VteRing *ring)
{
@@ -39,6 +40,7 @@ vte_ring_validate(VteRing *ring)
g_assert(ring->array[i % ring->max] != NULL);
}
}
+#endif
VteRing *
vte_ring_new(long max_elements, VteRingFreeFunc free, gpointer data)
diff --git a/src/trie.c b/src/trie.c
index 424eac2..dec2e25 100644
--- a/src/trie.c
+++ b/src/trie.c
@@ -36,7 +36,7 @@
/* Structures and whatnot for tracking character classes. */
struct char_class_data {
- wchar_t c; /* A character. */
+ wchar_t c; /* A character. */
int i; /* An integer. */
char *s; /* A string. */
int inc; /* An increment value. */
@@ -474,7 +474,8 @@ vte_trie_add(struct vte_trie *trie, const char *pattern, size_t length,
* works, and the result string if we have an exact match. */
static const char *
vte_trie_matchx(struct vte_trie *trie, const wchar_t *pattern, size_t length,
- const char **res, GQuark *quark, GValueArray *array)
+ const char **res, const wchar_t **consumed,
+ GQuark *quark, GValueArray *array)
{
unsigned int i;
const char *hres;
@@ -482,6 +483,7 @@ vte_trie_matchx(struct vte_trie *trie, const wchar_t *pattern, size_t length,
const char *best = NULL;
GValueArray *bestarray = NULL;
GQuark bestquark = 0;
+ const wchar_t *bestconsumed = pattern;
/* Make sure that attempting to save output values doesn't kill us. */
if (res == NULL) {
@@ -494,15 +496,18 @@ vte_trie_matchx(struct vte_trie *trie, const wchar_t *pattern, size_t length,
if (trie->result) {
*res = trie->result;
*quark = trie->quark;
+ *consumed = pattern;
return *res;
} else {
if (trie->trie_path_count > 0) {
*res = "";
*quark = g_quark_from_static_string("");
+ *consumed = pattern;
return *res;
} else {
*res = NULL;
*quark = 0;
+ *consumed = pattern;
return *res;
}
}
@@ -542,6 +547,7 @@ vte_trie_matchx(struct vte_trie *trie, const wchar_t *pattern, size_t length,
prospect,
length - (prospect - pattern),
&tmp,
+ consumed,
&tmpquark,
tmparray);
/* If it's a better match than any we've seen
@@ -556,6 +562,7 @@ vte_trie_matchx(struct vte_trie *trie, const wchar_t *pattern, size_t length,
}
bestarray = tmparray;
bestquark = tmpquark;
+ bestconsumed = *consumed;
} else {
g_value_array_free(tmparray);
tmparray = NULL;
@@ -579,6 +586,7 @@ vte_trie_matchx(struct vte_trie *trie, const wchar_t *pattern, size_t length,
#endif
*quark = bestquark;
*res = best;
+ *consumed = bestconsumed;
return *res;
}
@@ -586,13 +594,15 @@ vte_trie_matchx(struct vte_trie *trie, const wchar_t *pattern, size_t length,
* 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. */
TRIE_MAYBE_STATIC const char *
-vte_trie_match(struct vte_trie *trie, wchar_t *pattern, size_t length,
- const char **res, GQuark *quark, GValueArray **array)
+vte_trie_match(struct vte_trie *trie, const wchar_t *pattern, size_t length,
+ const char **res, const wchar_t **consumed,
+ GQuark *quark, GValueArray **array)
{
const char *ret = NULL;
GQuark tmpquark;
GValueArray *valuearray;
GValue *value;
+ const wchar_t *dummyconsumed;
gpointer ptr;
int i;
@@ -602,7 +612,13 @@ vte_trie_match(struct vte_trie *trie, wchar_t *pattern, size_t length,
}
*quark = 0;
- ret = vte_trie_matchx(trie, pattern, length, res, quark, valuearray);
+ if (consumed == NULL) {
+ consumed = &dummyconsumed;
+ }
+ *consumed = pattern;
+
+ ret = vte_trie_matchx(trie, pattern, length, res, consumed,
+ quark, valuearray);
if (((ret == NULL) || (ret[0] == '\0')) || (valuearray->n_values == 0)){
if (valuearray != NULL) {
@@ -689,7 +705,6 @@ TRIE_MAYBE_STATIC void
vte_trie_print(struct vte_trie *trie)
{
vte_trie_printx(trie, "");
- g_print("\n");
}
#ifdef TRIE_MAIN
@@ -730,7 +745,7 @@ convert_mbstowcs(const char *i, size_t ilen,
if (conv != NULL) {
memset(o, 0, max_olen);
outlen = max_olen;
- iconv(conv, &i, &ilen, &o, &outlen);
+ iconv(conv, (char**)&i, &ilen, (char**)&o, &outlen);
iconv_close(conv);
}
if (olen) {
@@ -745,6 +760,7 @@ main(int argc, char **argv)
GValueArray *array = NULL;
GQuark quark;
wchar_t buf[LINE_MAX];
+ const wchar_t *consumed;
size_t buflen;
g_type_init();
@@ -771,12 +787,14 @@ main(int argc, char **argv)
vte_trie_add(trie, "<esc>]2;%sh", 11, "decset-title",
g_quark_from_string("decset-title"));
vte_trie_print(trie);
+ g_print("\n");
quark = 0;
convert_mbstowcs("abc", 3, buf, &buflen, sizeof(buf));
g_print("`%s' = `%s'\n", "abc",
- vte_trie_match(trie, buf, buflen, NULL, &quark, &array));
- g_print("=> `%s'\n", g_quark_to_string(quark));
+ vte_trie_match(trie, buf, buflen,
+ NULL, &consumed, &quark, &array));
+ g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf);
if (array != NULL) {
dump_array(array);
g_value_array_free(array);
@@ -786,8 +804,9 @@ main(int argc, char **argv)
quark = 0;
convert_mbstowcs("abcdef", 6, buf, &buflen, sizeof(buf));
g_print("`%s' = `%s'\n", "abcdef",
- vte_trie_match(trie, buf, buflen, NULL, &quark, &array));
- g_print("=> `%s'\n", g_quark_to_string(quark));
+ vte_trie_match(trie, buf, buflen,
+ NULL, &consumed, &quark, &array));
+ g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf);
if (array != NULL) {
dump_array(array);
g_value_array_free(array);
@@ -797,8 +816,9 @@ main(int argc, char **argv)
quark = 0;
convert_mbstowcs("abcde", 5, buf, &buflen, sizeof(buf));
g_print("`%s' = `%s'\n", "abcde",
- vte_trie_match(trie, buf, buflen, NULL, &quark, &array));
- g_print("=> `%s'\n", g_quark_to_string(quark));
+ vte_trie_match(trie, buf, buflen,
+ NULL, &consumed, &quark, &array));
+ g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf);
if (array != NULL) {
dump_array(array);
g_value_array_free(array);
@@ -808,8 +828,9 @@ main(int argc, char **argv)
quark = 0;
convert_mbstowcs("abcdeg", 6, buf, &buflen, sizeof(buf));
g_print("`%s' = `%s'\n", "abcdeg",
- vte_trie_match(trie, buf, buflen, NULL, &quark, &array));
- g_print("=> `%s'\n", g_quark_to_string(quark));
+ vte_trie_match(trie, buf, buflen,
+ NULL, &consumed, &quark, &array));
+ g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf);
if (array != NULL) {
dump_array(array);
g_value_array_free(array);
@@ -819,8 +840,9 @@ main(int argc, char **argv)
quark = 0;
convert_mbstowcs("abc%deg", 7, buf, &buflen, sizeof(buf));
g_print("`%s' = `%s'\n", "abc%deg",
- vte_trie_match(trie, buf, buflen, NULL, &quark, &array));
- g_print("=> `%s'\n", g_quark_to_string(quark));
+ vte_trie_match(trie, buf, buflen,
+ NULL, &consumed, &quark, &array));
+ g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf);
if (array != NULL) {
dump_array(array);
g_value_array_free(array);
@@ -830,8 +852,9 @@ main(int argc, char **argv)
quark = 0;
convert_mbstowcs("abc10eg", 7, buf, &buflen, sizeof(buf));
g_print("`%s' = `%s'\n", "abc10eg",
- vte_trie_match(trie, buf, buflen, NULL, &quark, &array));
- g_print("=> `%s'\n", g_quark_to_string(quark));
+ vte_trie_match(trie, buf, buflen,
+ NULL, &consumed, &quark, &array));
+ g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf);
if (array != NULL) {
dump_array(array);
g_value_array_free(array);
@@ -841,8 +864,9 @@ main(int argc, char **argv)
quark = 0;
convert_mbstowcs("abc%eg", 6, buf, &buflen, sizeof(buf));
g_print("`%s' = `%s'\n", "abc%eg",
- vte_trie_match(trie, buf, buflen, NULL, &quark, &array));
- g_print("=> `%s'\n", g_quark_to_string(quark));
+ vte_trie_match(trie, buf, buflen,
+ NULL, &consumed, &quark, &array));
+ g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf);
if (array != NULL) {
dump_array(array);
g_value_array_free(array);
@@ -852,8 +876,9 @@ main(int argc, char **argv)
quark = 0;
convert_mbstowcs("abc%10eg", 8, buf, &buflen, sizeof(buf));
g_print("`%s' = `%s'\n", "abc%10eg",
- vte_trie_match(trie, buf, buflen, NULL, &quark, &array));
- g_print("=> `%s'\n", g_quark_to_string(quark));
+ vte_trie_match(trie, buf, buflen,
+ NULL, &consumed, &quark, &array));
+ g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf);
if (array != NULL) {
dump_array(array);
g_value_array_free(array);
@@ -863,8 +888,9 @@ main(int argc, char **argv)
quark = 0;
convert_mbstowcs("abcBeg", 6, buf, &buflen, sizeof(buf));
g_print("`%s' = `%s'\n", "abcBeg",
- vte_trie_match(trie, buf, buflen, NULL, &quark, &array));
- g_print("=> `%s'\n", g_quark_to_string(quark));
+ vte_trie_match(trie, buf, buflen,
+ NULL, &consumed, &quark, &array));
+ g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf);
if (array != NULL) {
dump_array(array);
g_value_array_free(array);
@@ -874,8 +900,9 @@ main(int argc, char **argv)
quark = 0;
convert_mbstowcs("<esc>[25;26H", 12, buf, &buflen, sizeof(buf));
g_print("`%s' = `%s'\n", "<esc>[25;26H",
- vte_trie_match(trie, buf, buflen, NULL, &quark, &array));
- g_print("=> `%s'\n", g_quark_to_string(quark));
+ vte_trie_match(trie, buf, buflen,
+ NULL, &consumed, &quark, &array));
+ g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf);
if (array != NULL) {
dump_array(array);
g_value_array_free(array);
@@ -883,10 +910,22 @@ main(int argc, char **argv)
}
quark = 0;
+ convert_mbstowcs("<esc>[25;2", 10, buf, &buflen, sizeof(buf));
+ g_print("`%s' = `%s'\n", "<esc>[25;2",
+ vte_trie_match(trie, buf, buflen,
+ NULL, &consumed, &quark, &array));
+ g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf);
+ if (array != NULL) {
+ dump_array(array);
+ g_value_array_free(array);
+ }
+
+ quark = 0;
convert_mbstowcs("<esc>[25;26L", 12, buf, &buflen, sizeof(buf));
g_print("`%s' = `%s'\n", "<esc>[25;26L",
- vte_trie_match(trie, buf, buflen, NULL, &quark, &array));
- g_print("=> `%s'\n", g_quark_to_string(quark));
+ vte_trie_match(trie, buf, buflen,
+ NULL, &consumed, &quark, &array));
+ g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf);
if (array != NULL) {
dump_array(array);
g_value_array_free(array);
@@ -895,8 +934,34 @@ main(int argc, char **argv)
quark = 0;
convert_mbstowcs("<esc>]2;WoofWoofh", 17, buf, &buflen, sizeof(buf));
g_print("`%s' = `%s'\n", "<esc>]2;WoofWoofh",
- vte_trie_match(trie, buf, buflen, NULL, &quark, &array));
- g_print("=> `%s'\n", g_quark_to_string(quark));
+ vte_trie_match(trie, buf, buflen,
+ NULL, &consumed, &quark, &array));
+ g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf);
+ if (array != NULL) {
+ dump_array(array);
+ g_value_array_free(array);
+ array = NULL;
+ }
+
+ quark = 0;
+ convert_mbstowcs("<esc>]2;WoofWoofh<esc>]2;WoofWoofh", 34,
+ buf, &buflen, sizeof(buf));
+ g_print("`%s' = `%s'\n", "<esc>]2;WoofWoofh<esc>]2;WoofWoofh",
+ vte_trie_match(trie, buf, buflen,
+ NULL, &consumed, &quark, &array));
+ g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf);
+ if (array != NULL) {
+ dump_array(array);
+ g_value_array_free(array);
+ array = NULL;
+ }
+
+ quark = 0;
+ convert_mbstowcs("<esc>]2;WoofWoofhfoo", 20, buf, &buflen, sizeof(buf));
+ g_print("`%s' = `%s'\n", "<esc>]2;WoofWoofhfoo",
+ vte_trie_match(trie, buf, buflen,
+ NULL, &consumed, &quark, &array));
+ g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf);
if (array != NULL) {
dump_array(array);
g_value_array_free(array);
diff --git a/src/trie.h b/src/trie.h
index 95bdc24..02dc076 100644
--- a/src/trie.h
+++ b/src/trie.h
@@ -48,8 +48,9 @@ void vte_trie_add(struct vte_trie *trie,
* passed-in string can not be an initial substring of one of the strings in
* the trie, then NULL is returned. */
const char *vte_trie_match(struct vte_trie *trie,
- wchar_t *pattern, size_t length,
+ const wchar_t *pattern, size_t length,
const char **res,
+ const wchar_t **consumed,
GQuark *quark,
GValueArray **array);
diff --git a/src/vte.c b/src/vte.c
index 7fdf525..be4eaca 100644
--- a/src/vte.c
+++ b/src/vte.c
@@ -222,6 +222,8 @@ struct _VteTerminalPrivate {
GtkIMContext *im_context;
char *im_preedit;
int im_preedit_cursor;
+
+ VteTerminalEraseBinding backspace_binding, delete_binding;
};
/* A function which can handle a terminal control sequence. */
@@ -771,12 +773,12 @@ vte_sequence_handler_al(VteTerminal *terminal,
#else
vte_invalidate_cells(terminal,
0, terminal->column_count,
- start, end + 1);
+ start, end - start + 1);
#endif
} else {
vte_invalidate_cells(terminal,
0, terminal->column_count,
- start, end + 1);
+ start, end - start + 1);
}
}
@@ -1266,6 +1268,7 @@ vte_sequence_handler_do(VteTerminal *terminal,
vte_insert_line_int(terminal, end);
if ((terminal->pvt->bg_image == NULL) &&
(!terminal->pvt->bg_transparent)) {
+#if 0
/* Scroll the window. */
gdk_window_scroll(widget->window,
0,
@@ -1280,14 +1283,21 @@ vte_sequence_handler_do(VteTerminal *terminal,
vte_invalidate_cells(terminal,
0, terminal->column_count,
0, start);
+#else
+ vte_invalidate_cells(terminal,
+ 0,
+ terminal->column_count,
+ start,
+ end - start + 1);
+#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);
+ start,
+ end - start + 1);
}
} else {
/* Otherwise, just move the cursor down. */
@@ -1666,6 +1676,7 @@ vte_sequence_handler_up(VteTerminal *terminal,
vte_insert_line_int(terminal, start);
if ((terminal->pvt->bg_image == NULL) &&
(!terminal->pvt->bg_transparent)) {
+#if 0
/* Scroll the window. */
gdk_window_scroll(widget->window,
0,
@@ -1680,14 +1691,16 @@ vte_sequence_handler_up(VteTerminal *terminal,
vte_invalidate_cells(terminal,
0, terminal->column_count,
end, terminal->row_count);
+#endif
+ vte_invalidate_cells(terminal,
+ 0, terminal->column_count,
+ start, end - start + 1);
} 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);
+ 0, terminal->column_count,
+ start, end - start + 1);
}
} else {
/* Otherwise, just move the cursor up. */
@@ -1705,6 +1718,7 @@ vte_sequence_handler_up(VteTerminal *terminal,
vte_insert_line_int(terminal, start);
if ((terminal->pvt->bg_image == NULL) &&
(!terminal->pvt->bg_transparent)) {
+#if 0
/* Scroll the window. */
gdk_window_scroll(widget->window,
0,
@@ -1715,6 +1729,13 @@ vte_sequence_handler_up(VteTerminal *terminal,
terminal->column_count,
terminal->row_count - 1,
1);
+#else
+ vte_invalidate_cells(terminal,
+ 0,
+ terminal->column_count,
+ screen->scroll_delta,
+ terminal->row_count);
+#endif
} else {
/* If we have a background image, we need to
* redraw the entire window. */
@@ -3280,6 +3301,30 @@ vte_terminal_im_reset(VteTerminal *terminal)
}
}
+/* Free a parameter array. Most of the GValue elements can clean up after
+ * themselves, but we're using gpointers to hold wide character strings, and
+ * we need to free those ourselves. */
+static void
+free_params_array(GValueArray *params)
+{
+ int i;
+ GValue *value;
+ gpointer ptr;
+ if (params != NULL) {
+ for (i = 0; i < params->n_values; i++) {
+ value = g_value_array_get_nth(params, i);
+ if (G_VALUE_HOLDS_POINTER(value)) {
+ ptr = g_value_get_pointer(value);
+ if (ptr != NULL) {
+ g_free(ptr);
+ }
+ g_value_set_pointer(value, NULL);
+ }
+ }
+ g_value_array_free(params);
+ }
+}
+
/* Process incoming data, first converting it to wide characters, and then
* processing escape sequences. */
static gboolean
@@ -3294,12 +3339,11 @@ vte_terminal_process_incoming(gpointer data)
char *ibuf, *obuf, *obufptr, *ubuf, *ubufptr;
size_t icount, ocount, ucount;
wchar_t *wbuf, c;
- int ind, wcount, start, end;
+ int wcount, start, end, i;
const char *match, *encoding;
iconv_t unconv;
GQuark quark;
- GValue *value;
- gpointer ptr;
+ const wchar_t *next;
gboolean leftovers, inserted, again, bottom;
g_return_val_if_fail(GTK_IS_WIDGET(data), FALSE);
@@ -3340,15 +3384,12 @@ vte_terminal_process_incoming(gpointer data)
}
}
/* Be conservative about discarding data. */
- g_warning("Invalid multibyte sequence detected. Discarding %d bytes of data.", end - start);
+ g_warning("Invalid multibyte sequence detected. Munging up %d bytes of data.", end - start);
/* Remove the offending bytes. */
- obuf = &terminal->pvt->incoming[start];
- ibuf = &terminal->pvt->incoming[end];
- memmove(obuf, ibuf, terminal->pvt->n_incoming - end);
- /* Reset the incoming buffer size. */
- terminal->pvt->n_incoming -= end;
- /* If we still have data, try again right
- * away. */
+ for (i = start; i < end; i++) {
+ terminal->pvt->incoming[i] = '?';
+ }
+ /* Try again right away. */
terminal->pvt->processing = (terminal->pvt->n_incoming > 0);
if (terminal->pvt->processing == FALSE) {
terminal->pvt->processing_tag = -1;
@@ -3382,126 +3423,190 @@ vte_terminal_process_incoming(gpointer data)
start = 0;
inserted = leftovers = FALSE;
while ((start < wcount) && !leftovers) {
- for (end = start + 1; end <= wcount; end++) {
- /* Check if the contents of the array is a control
- * string or not. The match function returns NULL if
- * the data is not a control sequence, the name of
- * the control sequence if it is one, and an empty
- * string if it might be the beginning of a control
- * sequence. */
+ /* Check if the first character is part of a control
+ * sequence. */
+ vte_trie_match(terminal->pvt->trie,
+ &wbuf[start],
+ 1,
+ &match,
+ &next,
+ &quark,
+ &params);
+ /* Next now points to the next character in the buffer we're
+ * uncertain about. The match string falls into one of three
+ * classes, but only one of them is ambiguous, and we want to
+ * clear that up if possible. */
+ if ((match != NULL) && (match[0] == '\0')) {
+#ifdef VTE_DEBUG
+ fprintf(stderr, "Ambiguous sequence (%d/%d). "
+ "Resolving.\n", start, wcount);
+#endif
+ /* Try to match the *entire* string. This will set
+ * "next" to a more useful value. */
+ free_params_array(params);
+ params = NULL;
vte_trie_match(terminal->pvt->trie,
&wbuf[start],
- end - start,
+ wcount - start,
&match,
+ &next,
&quark,
&params);
+ /* Now check just the number of bytes we know about
+ * to determine what we're doing in this iteration. */
if (match == NULL) {
- /* Nothing interesting here, so insert this
- * character into the buffer. */
- c = wbuf[start];
#ifdef VTE_DEBUG
- if (c > 255) {
- fprintf(stderr, "%ld\n", (long) c);
- } else {
- if (c > 127) {
- fprintf(stderr, "%ld = ",
- (long) c);
+ fprintf(stderr,
+ "Looks like a sequence (%d).\n",
+ next - (wbuf + start));
+#endif
+ free_params_array(params);
+ params = NULL;
+ vte_trie_match(terminal->pvt->trie,
+ &wbuf[start],
+ next - (wbuf + start),
+ &match,
+ &next,
+ &quark,
+ &params);
+ if ((match != NULL) && (match[0] == '\0')) {
+ vte_trie_match(terminal->pvt->trie,
+ &wbuf[start],
+ next - (wbuf + start) + 1,
+ &match,
+ &next,
+ &quark,
+ &params);
+ }
+ }
+#ifdef VTE_DEBUG
+ if ((match != NULL) && (match[0] != '\0')) {
+ fprintf(stderr,
+ "Ambiguity resolved -- sequence ");
+ }
+ if ((match != NULL) && (match[0] == '\0')) {
+ int i;
+ fprintf(stderr,
+ "Ambiguity resolved -- incomplete `");
+ for (i = 0; i < wcount; i++) {
+ if (i == start) {
+ fprintf(stderr, "=>");
}
- if (c < 32) {
- fprintf(stderr, "^%lc\n",
- (wint_t)c + 64);
+ if ((wbuf[i] < 32) || (wbuf[i] > 127)) {
+ fprintf(stderr, "{%ld}",
+ (long) wbuf[i]);
} else {
- fprintf(stderr, "`%lc'\n",
- (wint_t)c);
+ fprintf(stderr, "%lc",
+ (wint_t) wbuf[i]);
}
+ if (i == (next - wbuf)) {
+ fprintf(stderr, "<=");
+ }
+ }
+ if (i == (next - wbuf)) {
+ fprintf(stderr, "<=");
}
+ fprintf(stderr, "'.\n");
+ }
+ if (match == NULL) {
+ fprintf(stderr,
+ "Ambiguity resolved -- plain data ");
+ }
+ fprintf(stderr, "(%d).\n", next - wbuf);
#endif
- vte_terminal_insert_char(widget, c);
- inserted = TRUE;
- start++;
- break;
+ }
+
+#ifdef VTE_DEBUG
+ else {
+ if ((match != NULL) && (match[0] != '\0')) {
+ fprintf(stderr,
+ "Sequence (%d).\n", next - wbuf);
}
- if (match[0] != '\0') {
- /* A terminal sequence, force the current
- * position of the cursor to be redrawn, run
- * the sequence handler, and then draw the
- * cursor again. */
- vte_invalidate_cursor_once(terminal);
- vte_terminal_handle_sequence(GTK_WIDGET(terminal),
- match,
- quark,
- params);
- /* Skip over the proper number of wide chars. */
- start = end;
- /* Check if the encoding's changed. */
- if (strcmp(encoding, terminal->pvt->encoding)) {
- leftovers = TRUE;
- }
- inserted = TRUE;
- break;
- } else {
- /* Empty string. */
- if (end == wcount) {
- /* We have the initial portion of a
- * control sequence, but no more
- * data. */
- leftovers = TRUE;
- g_warning("Unhandled data (%s).\n",
- terminal->pvt->incoming + start);
- }
+ if ((match != NULL) && (match[0] == '\0')) {
+ fprintf(stderr,
+ "Incomplete (%d).\n", next - wbuf);
}
- /* Free any wide-character strings we got. */
- if (params != NULL) {
- for (ind = 0; ind < params->n_values; ind++) {
- value = g_value_array_get_nth(params,
- ind);
- if (G_VALUE_HOLDS_POINTER(value)) {
- ptr = g_value_get_pointer(value);
- if (ptr != NULL) {
- g_free(ptr);
- }
- g_value_set_pointer(value,
- NULL);
- }
- }
- g_value_array_free(params);
- params = NULL;
+ if (match == NULL) {
+ fprintf(stderr,
+ "Plain data (%d).\n", next - wbuf);
}
}
- /* Free any wide-character strings we got if we broke out
- * of the loop. */
- if (params != NULL) {
- for (ind = 0; ind < params->n_values; ind++) {
- value = g_value_array_get_nth(params, ind);
- if (G_VALUE_HOLDS_POINTER(value)) {
- ptr = g_value_get_pointer(value);
- if (ptr != NULL) {
- g_free(ptr);
- }
- g_value_set_pointer(value, NULL);
+#endif
+ /* We're in one of three possible situations now.
+ * First, the match string is a non-empty string and next
+ * points to the first character which isn't part of this
+ * sequence. */
+ if ((match != NULL) && (match[0] != '\0')) {
+ vte_invalidate_cursor_once(terminal);
+ vte_terminal_handle_sequence(GTK_WIDGET(terminal),
+ match,
+ quark,
+ params);
+ /* Skip over the proper number of wide chars. */
+ start = (next - wbuf);
+ /* Check if the encoding's changed. If it has, we need
+ * to force our caller to call us again to parse the
+ * rest of the data. */
+ if (strcmp(encoding, terminal->pvt->encoding)) {
+ leftovers = TRUE;
+ }
+ inserted = TRUE;
+ } else
+ /* Second, we have a NULL match, and next points the very
+ * next character in the buffer. Insert the character we're
+ * which we're currently examining. */
+ if (match == NULL) {
+ c = wbuf[start];
+#ifdef VTE_DEBUG
+ if (c > 255) {
+ fprintf(stderr, "%ld\n", (long) c);
+ } else {
+ if (c > 127) {
+ fprintf(stderr, "%ld = ", (long) c);
+ }
+ if (c < 32) {
+ fprintf(stderr, "^%lc\n",
+ (wint_t)c + 64);
+ } else {
+ fprintf(stderr, "`%lc'\n", (wint_t)c);
}
}
- g_value_array_free(params);
- params = NULL;
+#endif
+ vte_terminal_insert_char(widget, c);
+ inserted = TRUE;
+ start++;
+ } else {
+ /* Case three: the read broke in the middle of a
+ * control sequence, so we're undecided with no more
+ * data to consult. */
+ leftovers = TRUE;
}
+ /* Free any parameters we don't care about any more. */
+ free_params_array(params);
+ params = NULL;
}
- again = TRUE;
+
if (leftovers) {
/* There are leftovers, so convert them back to the terminal's
- * encoding and save them for later. */
+ * old encoding and save them for later. */
unconv = iconv_open(encoding, "WCHAR_T");
if (unconv != NULL) {
icount = sizeof(wchar_t) * (wcount - start);
ibuf = (char*) &wbuf[start];
- ucount = VTE_UTF8_BPC * (wcount - start + 1);
+ ucount = VTE_UTF8_BPC * (wcount - start) + 1;
ubuf = ubufptr = g_malloc(ucount);
if (iconv(unconv, &ibuf, &icount,
&ubuf, &ucount) != -1) {
/* Store it. */
- g_free(terminal->pvt->incoming);
+ if (terminal->pvt->incoming) {
+ g_free(terminal->pvt->incoming);
+ }
terminal->pvt->incoming = ubufptr;
terminal->pvt->n_incoming = ubuf - ubufptr;
*ubuf = '\0';
+ /* If we're doing this because the encoding
+ * was changed out from under us, we need to
+ * keep trying to process the incoming data. */
if (strcmp(encoding, terminal->pvt->encoding)) {
again = TRUE;
} else {
@@ -3514,15 +3619,22 @@ vte_terminal_process_incoming(gpointer data)
(long) (sizeof(wchar_t) * (wcount - start)),
strerror(errno));
#endif
+ if (terminal->pvt->incoming) {
+ g_free(terminal->pvt->incoming);
+ }
+ terminal->pvt->incoming = NULL;
+ terminal->pvt->n_incoming = 0;
g_free(ubufptr);
again = FALSE;
}
iconv_close(unconv);
} else {
/* Discard the data, we can't use it. */
- terminal->pvt->n_incoming = 0;
- g_free(terminal->pvt->incoming);
+ if (terminal->pvt->incoming != NULL) {
+ g_free(terminal->pvt->incoming);
+ }
terminal->pvt->incoming = NULL;
+ terminal->pvt->n_incoming = 0;
again = FALSE;
}
} else {
@@ -3553,6 +3665,7 @@ vte_terminal_process_incoming(gpointer data)
/* Signal that the visible contents changed. */
vte_terminal_emit_contents_changed(terminal);
}
+
if ((cursor_row != terminal->pvt->screen->cursor_current.row) ||
(cursor_col != terminal->pvt->screen->cursor_current.col)) {
/* Signal that the cursor moved. */
@@ -3572,6 +3685,8 @@ vte_terminal_process_incoming(gpointer data)
fprintf(stderr, "%d bytes left to process.\n",
terminal->pvt->n_incoming);
#endif
+ /* Decide if we're going to keep on processing data, and if not,
+ * note that our source tag is about to become invalid. */
terminal->pvt->processing = again && (terminal->pvt->n_incoming > 0);
if (terminal->pvt->processing == FALSE) {
terminal->pvt->processing_tag = -1;
@@ -4003,16 +4118,46 @@ vte_terminal_key_press(GtkWidget *widget, GdkEventKey *event)
/* Map the key to a sequence name if we can. */
switch (event->keyval) {
case GDK_BackSpace:
- /* Use the tty's erase character. */
- if (tcgetattr(terminal->pvt->pty_master,
- &tio) != -1) {
- normal = g_strdup_printf("%c",
- tio.c_cc[VERASE]);
- normal_length = 1;
+ switch (terminal->pvt->backspace_binding) {
+ case VTE_ERASE_ASCII_BACKSPACE:
+ normal = g_strdup("");
+ normal_length = 1;
+ break;
+ case VTE_ERASE_ASCII_DELETE:
+ normal = g_strdup("");
+ normal_length = 1;
+ break;
+ case VTE_ERASE_DELETE_SEQUENCE:
+ special = "kD";
+ break;
+ /* Use the tty's erase character. */
+ case VTE_ERASE_AUTO:
+ default:
+ if (tcgetattr(terminal->pvt->pty_master,
+ &tio) != -1) {
+ normal = g_strdup_printf("%c",
+ tio.c_cc[VERASE]);
+ normal_length = 1;
+ }
+ break;
}
break;
case GDK_Delete:
- special = "kD";
+ switch (terminal->pvt->delete_binding) {
+ case VTE_ERASE_ASCII_BACKSPACE:
+ normal = g_strdup("");
+ normal_length = 1;
+ break;
+ case VTE_ERASE_ASCII_DELETE:
+ normal = g_strdup("");
+ normal_length = 1;
+ break;
+ case VTE_ERASE_DELETE_SEQUENCE:
+ case VTE_ERASE_AUTO:
+ default:
+ special = "kD";
+ break;
+ }
break;
case GDK_KP_Home:
case GDK_Home:
@@ -4811,6 +4956,69 @@ xft_pattern_from_pango_font_description(const PangoFontDescription *font_desc)
}
#endif
+static char *
+xlfd_from_pango_font_description(const PangoFontDescription *fontdesc)
+{
+ int weighti, stylei, stretchi, size, count;
+ const char *weight, *style, *stretch, *family;
+ char *ret = NULL;
+ char **fonts;
+
+ family = pango_font_description_get_family(fontdesc);
+ weighti = pango_font_description_get_weight(fontdesc);
+ if (weighti > ((PANGO_WEIGHT_NORMAL + PANGO_WEIGHT_BOLD) / 2)) {
+ weight = "bold";
+ } else {
+ weight = "medium";
+ }
+ stylei = pango_font_description_get_style(fontdesc);
+ switch (stylei) {
+ case PANGO_STYLE_ITALIC:
+ style = "i";
+ break;
+ case PANGO_STYLE_OBLIQUE:
+ style = "o";
+ break;
+ default:
+ style = "r";
+ break;
+ }
+ stretchi = pango_font_description_get_stretch(fontdesc);
+ if (stretchi <= PANGO_STRETCH_CONDENSED) {
+ stretch = "condensed";
+ } else
+ if (stretchi <= PANGO_STRETCH_SEMI_CONDENSED) {
+ stretch = "semicondensed";
+ } else {
+ stretch = "normal";
+ }
+
+ size = pango_font_description_get_size(fontdesc);
+
+ ret = g_strdup_printf("-*-%s*-%s-%s-%s--%d-*-*-*-*-*-*-*",
+ family, weight, style, stretch,
+ PANGO_PIXELS(size));
+ fonts = XListFonts(GDK_DISPLAY(), ret, 1, &count);
+ if (fonts != NULL) {
+#ifdef VTE_DEBUG
+ int i;
+ char *desc = pango_font_description_to_string(fontdesc);
+ for (i = 0; i < count; i++) {
+ fprintf(stderr, "Font `%s' matched `%s'.\n",
+ desc, fonts[i]);
+ }
+ g_free(desc);
+#endif
+ XFreeFontNames(fonts);
+ }
+ if (count > 0) {
+ return ret;
+ } else {
+ g_free(ret);
+ return NULL;
+ }
+}
+
/* Set the fontset used for rendering text into the widget. */
void
vte_terminal_set_font(VteTerminal *terminal,
@@ -4819,7 +5027,7 @@ vte_terminal_set_font(VteTerminal *terminal,
long width, height, ascent, descent;
GtkWidget *widget;
XFontStruct **font_struct_list, font_struct;
- char *xlfds = NULL;
+ char *xlfds;
char **missing_charset_list = NULL, *def_string = NULL;
int missing_charset_count = 0;
char **font_name_list = NULL;
@@ -4829,9 +5037,6 @@ vte_terminal_set_font(VteTerminal *terminal,
widget = GTK_WIDGET(terminal);
/* Choose default font metrics. I like '10x20' as a terminal font. */
- if (xlfds == NULL) {
- xlfds = "-misc-fixed-medium-r-normal--20-*-*-*-*-*-*-*";
- }
width = 10;
height = 20;
descent = 0;
@@ -5033,6 +5238,24 @@ vte_terminal_set_font(VteTerminal *terminal,
if (!terminal->pvt->use_xft && !terminal->pvt->use_pango) {
/* Load the font set, freeing another one if we loaded one
* before. */
+#ifdef VTE_DEBUG
+ if (font_desc) {
+ char *tmp;
+ tmp = pango_font_description_to_string (font_desc);
+ fprintf (stderr, "Using pango font \"%s\".\n", tmp);
+ g_free (tmp);
+ } else {
+ fprintf (stderr, "Using default pango font.\n");
+ }
+#endif
+ if (font_desc) {
+ xlfds = xlfd_from_pango_font_description(font_desc);
+ } else {
+ xlfds = "-misc-fixed-medium-r-normal--12-*-*-*-*-*-*-*";
+ }
+ if (xlfds == NULL) {
+ xlfds = "-misc-fixed-medium-r-normal--12-*-*-*-*-*-*-*";
+ }
if (terminal->pvt->fontset != NULL) {
XFreeFontSet(GDK_DISPLAY(), terminal->pvt->fontset);
}
@@ -5466,7 +5689,7 @@ vte_terminal_init(VteTerminal *terminal, gpointer *klass)
}
}
}
- if (!pvt->use_pango) {
+ if (pvt->use_pango) {
if (getenv("VTE_USE_PANGO") != NULL) {
if (atol(getenv("VTE_USE_PANGO")) == 0) {
pvt->use_pango = FALSE;
@@ -5527,6 +5750,10 @@ vte_terminal_init(VteTerminal *terminal, gpointer *klass)
/* Set up input method support. */
pvt->im_context = NULL;
+
+ /* Set backspace/delete bindings. */
+ pvt->backspace_binding = VTE_ERASE_AUTO;
+ pvt->delete_binding = VTE_ERASE_AUTO;
}
/* Tell GTK+ how much space we need. */
@@ -6891,7 +7118,7 @@ vte_terminal_setup_background(VteTerminal *terminal,
}
/* If we need a new copy of the desktop, get it. */
if (refresh_transparent) {
- guint width, height;
+ guint width, height, pwidth, pheight;
#ifdef VTE_DEBUG
fprintf(stderr, "Fetching new background pixmap.\n");
@@ -6923,14 +7150,15 @@ vte_terminal_setup_background(VteTerminal *terminal,
/* If we got a pixmap, create a pixbuf for
* us to work with. */
if (GDK_IS_PIXMAP(pixmap)) {
+ gdk_drawable_get_size(GDK_DRAWABLE(pixmap), &pwidth, &pheight);
colormap = gdk_drawable_get_colormap(window);
pixbuf = gdk_pixbuf_get_from_drawable(NULL,
pixmap,
colormap,
0, 0,
0, 0,
- width,
- height);
+ MIN(width, pwidth),
+ MIN(pheight, height));
/* Get rid of the pixmap. */
g_object_unref(G_OBJECT(pixmap));
pixmap = NULL;
@@ -7492,3 +7720,19 @@ vte_terminal_set_word_chars(VteTerminal *terminal, const char *spec)
g_free(ibufptr);
g_free(obufptr);
}
+
+void
+vte_terminal_set_backspace_binding(VteTerminal *terminal,
+ VteTerminalEraseBinding binding)
+{
+ g_return_if_fail(VTE_IS_TERMINAL(terminal));
+ terminal->pvt->backspace_binding = binding;
+}
+
+void
+vte_terminal_set_delete_binding(VteTerminal *terminal,
+ VteTerminalEraseBinding binding)
+{
+ g_return_if_fail(VTE_IS_TERMINAL(terminal));
+ terminal->pvt->delete_binding = binding;
+}
diff --git a/src/vte.h b/src/vte.h
index 0cc263f..effc4ec 100644
--- a/src/vte.h
+++ b/src/vte.h
@@ -92,6 +92,13 @@ typedef struct _VteTerminalSnapshot {
} **contents;
} VteTerminalSnapshot;
+typedef enum {
+ VTE_ERASE_AUTO,
+ VTE_ERASE_ASCII_BACKSPACE,
+ VTE_ERASE_ASCII_DELETE,
+ VTE_ERASE_DELETE_SEQUENCE,
+} VteTerminalEraseBinding;
+
/* The widget's type. */
GtkType vte_terminal_get_type(void);
@@ -108,7 +115,6 @@ GtkType vte_terminal_get_type(void);
VTE_TYPE_TERMINAL)
#define VTE_TERMINAL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), VTE_TYPE_TERMINAL, VteTerminalClass))
-
GtkWidget *vte_terminal_new(void);
pid_t vte_terminal_fork_command(VteTerminal *terminal,
const char *command,
@@ -155,6 +161,11 @@ gboolean vte_terminal_get_using_xft(VteTerminal *terminal);
gboolean vte_terminal_is_word_char(VteTerminal *terminal, gunichar c);
const PangoFontDescription *vte_terminal_get_font(VteTerminal *terminal);
+void vte_terminal_set_backspace_binding(VteTerminal *terminal,
+ VteTerminalEraseBinding binding);
+void vte_terminal_set_delete_binding(VteTerminal *terminal,
+ VteTerminalEraseBinding binding);
+
VteTerminalSnapshot *vte_terminal_get_snapshot(VteTerminal *terminal);
void vte_terminal_free_snapshot(VteTerminalSnapshot *snapshot);
diff --git a/src/vteaccess.c b/src/vteaccess.c
index 6d1a7d4..9e2dfcf 100644
--- a/src/vteaccess.c
+++ b/src/vteaccess.c
@@ -242,7 +242,10 @@ vte_terminal_accessible_get_text_somewhere(AtkText *text,
break;
case ATK_TEXT_BOUNDARY_WORD_START:
case ATK_TEXT_BOUNDARY_WORD_END:
- /* Find the wordstart before the requested point. */
+ /* Find the wordstart before the requested point.
+ * FIXME: use pango_break or g_unichar_break_type to
+ * find word boundaries. For now, this should work
+ * only for some locales. */
c = g_array_index(priv->snapshot_cells,
struct VteTerminalSnapshotCell,
offset).c;
diff --git a/src/vteapp.c b/src/vteapp.c
index 404cb90..4c1bd2f 100644
--- a/src/vteapp.c
+++ b/src/vteapp.c
@@ -131,7 +131,7 @@ main(int argc, char **argv)
/* Set the default font. */
vte_terminal_set_font_from_string(VTE_TERMINAL(widget),
- "fixed semi-condensed 12");
+ "fixed 12");
/* Launch a shell. */
#ifdef VTE_DEBUG
diff --git a/vte.spec b/vte.spec
index 7eb31b3..1a2432f 100644
--- a/vte.spec
+++ b/vte.spec
@@ -1,5 +1,5 @@
Name: vte
-Version: 0.3.2
+Version: 0.3.3
Release: 1
Summary: An experimental terminal emulator.
License: LGPL