diff options
author | Nalin Dahyabhai <nalin@src.gnome.org> | 2002-05-02 08:33:23 +0000 |
---|---|---|
committer | Nalin Dahyabhai <nalin@src.gnome.org> | 2002-05-02 08:33:23 +0000 |
commit | 386e1b45a5e205f28a29f1c3da82c7fcd6342c91 (patch) | |
tree | b35999b03d2452813fc36cc06e06830135212c13 | |
parent | 92d904d5dd39221b2ab942c2cc59056a50b357cc (diff) |
Rework trie matching to return the address of the character which endedvte_0_3_3
* 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.
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | src/interpret.c | 2 | ||||
-rw-r--r-- | src/ring.c | 2 | ||||
-rw-r--r-- | src/trie.c | 127 | ||||
-rw-r--r-- | src/trie.h | 3 | ||||
-rw-r--r-- | src/vte.c | 490 | ||||
-rw-r--r-- | src/vte.h | 13 | ||||
-rw-r--r-- | src/vteaccess.c | 5 | ||||
-rw-r--r-- | src/vteapp.c | 2 | ||||
-rw-r--r-- | vte.spec | 2 |
10 files changed, 496 insertions, 160 deletions
@@ -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; @@ -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) @@ -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); @@ -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); @@ -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, + ¶ms); + /* 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, ¶ms); + /* 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, + ¶ms); + if ((match != NULL) && (match[0] == '\0')) { + vte_trie_match(terminal->pvt->trie, + &wbuf[start], + next - (wbuf + start) + 1, + &match, + &next, + &quark, + ¶ms); + } + } +#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; +} @@ -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 @@ -1,5 +1,5 @@ Name: vte -Version: 0.3.2 +Version: 0.3.3 Release: 1 Summary: An experimental terminal emulator. License: LGPL |