UTF-8 Terminal I/O recoding patch for Links 0.99
"BC Sittler" <[email protected]>
| Newsgroups | gmane.comp.web.links.list |
|---|---|
| Message-ID | <[email protected]> |
Hi Links-ers, New features (like FreeBSD line-drawing graphics support) have broken the earlier patch. The new one is attached to this message in two forms, plaintext and binary. Also, has anyone considered adding full support for the FreeBSD console character set, so that e.g. CP437 webpages appear correctly under FreeBSD in Links? Anyhow, it's good to see a new version of Links :) Full description of the patch: Do you use xterm, screen, gnome-terminal, the Linux console, the os x terminal, or another UCS/Unicode- capable terminal or terminal emulator with the UTF-8 character encoding, and want to use the Links web browser with non-ASCII webpages? If so, this patch may be of use. It allows use of any of the Links display charsets (collectively covering about 750 Unicode characters in Links 0.99) with a UTF-8 terminal. It even allows fast switching back and forth at run-time between different display charsets without any terminal reconfiguration. This is a new version of the UTF-8 Terminal I/O recoding patch for Links 0.99. It allows limited use of non-ASCII characters in UTF-8 terminals and terminal emulators by translating Links's internal display charset (and line- drawing graphics) to UTF-8 before sending them to the terminal, and by translating keystroke input from UTF-8 to Link's internal display charset before processing it. While this is not full UTF-8 support by any means, it is enough to use non-ASCII web sites on a UTF-8 terminal exactly as you would on a non-UTF-8 terminal, with the added feature of being able to switch between the different Links display charsets without reconfiguring your terminal. By default, the UTF-8 Terminal I/O recoding does not occur, so you may continue to use Links as you are accustomed to on non-UTF-8 terminals. To use it, you must enable the "UTF-8 I/O" option in the "Terminal options" screen. This setting is specific to a terminal type, just like the other Terminal options, and is saved in the config file by appending the word "utf-8" to the "terminal" or "terminal2" line in links.cfg, so it is backward-compatible and degrades nicely (versions of Links without the patch simply ignore that word.) NOTE: In concept this is similar to the "luit" program, but integrated into Links. It does not magically make Links UCS/Unicode-aware. So e.g. this does not add CJK support. Anyhow, enjoy! -Ben -- ___________________________________________________________ Sign-up for Ads Free at Mail.com http://promo.mail.com/adsfreejump.htm _______________________________________________ Links-list mailing list [email protected] http://linuxfromscratch.org/mailman/listinfo/links-list
links-0.99-utf-8.txt
(text/plain, 11.2 KB)
diff -u --recursive links-0.99.orig/charsets.c links-0.99/charsets.c
--- links-0.99.orig/charsets.c 2003-02-05 02:18:17.000000000 -0800
+++ links-0.99/charsets.c 2004-01-05 18:35:02.000000000 -0800
@@ -89,7 +89,7 @@
0x007e, 0x2122, 0x0161, 0x003e, 0x0153, 0x0000, 0x0000, 0x0000,
};
-static inline unsigned char *u2cp(int u, int to)
+unsigned char *u2cp(int u, int to)
{
int j, s;
if (u < 128) return strings[u];
@@ -140,6 +140,22 @@
return utf_buffer;
}
+/* this slow and ugly code is used by the terminal utf_8_io */
+unsigned char *cp2utf_8(int from, int c)
+{
+ int j;
+
+ if (codepages[from].table == table_utf_8) return strings[c];
+ for (j = 0; codepages[from].table[j].c; j++) {
+ if (codepages[from].table[j].c == c)
+ {
+ return encode_utf_8(codepages[from].table[j].u);
+ }
+ }
+ if (c < 128) return strings[c];
+ return encode_utf_8(UCS_NO_CHAR);
+}
+
void add_utf_8(struct conv_table *ct, int u, unsigned char *str)
{
unsigned char *p = encode_utf_8(u);
diff -u --recursive links-0.99.orig/default.c links-0.99/default.c
--- links-0.99.orig/default.c 2003-11-18 14:38:22.000000000 -0800
+++ links-0.99/default.c 2004-01-05 18:35:02.000000000 -0800
@@ -575,6 +575,7 @@
}
}
+/* terminal NAME(str) MODE(0-3) M11_HACK(0-1) BLOCK_CURSOR.RESTRICT_852.COL(0-7) CHARSET(str) [ UTF_8_IO("utf-8") ]*/
unsigned char *term_rd(struct option *o, unsigned char *c)
{
struct term_spec *ts;
@@ -585,6 +586,7 @@
mem_free(w);
goto end;
}
+ ts->utf_8_io = 0;
mem_free(w);
if (!(w = get_token(&c))) goto err;
if (strlen(w) != 1 || w[0] < '0' || w[0] > '4') goto err_f;
@@ -604,6 +606,9 @@
if ((i = get_cp_index(w)) == -1) goto err_f;
ts->charset = i;
mem_free(w);
+ if (!(w = get_token(&c))) goto end;
+ if (!(strcasecmp(w, "utf-8"))) ts->utf_8_io = 1;
+ mem_free(w);
end:
return NULL;
err_f:
@@ -612,6 +617,7 @@
return "Error reading terminal specification";
}
+/* terminal2 NAME(str) MODE(0-3) M11_HACK(0-1) RESTRICT_852(0-1) COL(0-1) CHARSET(str) [ UTF_8_IO("utf-8") ]*/
unsigned char *term2_rd(struct option *o, unsigned char *c)
{
struct term_spec *ts;
@@ -622,6 +628,7 @@
mem_free(w);
goto end;
}
+ ts->utf_8_io = 0;
mem_free(w);
if (!(w = get_token(&c))) goto err;
if (strlen(w) != 1 || w[0] < '0' || w[0] > '4') goto err_f;
@@ -643,6 +650,9 @@
if ((i = get_cp_index(w)) == -1) goto err_f;
ts->charset = i;
mem_free(w);
+ if (!(w = get_token(&c))) goto end;
+ if (!(strcasecmp(w, "utf-8"))) ts->utf_8_io = 1;
+ mem_free(w);
end:
return NULL;
err_f:
@@ -665,6 +675,10 @@
add_num_to_str(s, l, !!ts->col + !!ts->restrict_852 * 2 + !!ts->block_cursor * 4);
add_to_str(s, l, " ");
add_to_str(s, l, get_cp_mime_name(ts->charset));
+ if (ts->utf_8_io)
+ {
+ add_to_str(s, l, " utf-8");
+ }
}
}
diff -u --recursive links-0.99.orig/intl/english.lng links-0.99/intl/english.lng
--- links-0.99.orig/intl/english.lng 2003-12-14 13:33:27.000000000 -0800
+++ links-0.99/intl/english.lng 2004-01-05 18:35:29.000000000 -0800
@@ -49,6 +49,7 @@
T_KOI8R_FRAMES, "KOI8-R frames",
T_FREEBSD_FRAMES, "FreeBSD frames",
T_USE_11M, "Use ^[[11m",
+T_UTF_8_IO, "UTF-8 I/O",
T_RESTRICT_FRAMES_IN_CP850_852, "Restrict frames in cp850/852",
T_BLOCK_CURSOR, "Block cursor",
T_COLOR, "Color",
diff -u --recursive links-0.99.orig/links.h links-0.99/links.h
--- links-0.99.orig/links.h 2003-12-14 13:29:45.000000000 -0800
+++ links-0.99/links.h 2004-01-05 19:05:35.000000000 -0800
@@ -1020,6 +1020,11 @@
int qlen;
struct list_head windows;
unsigned char *title;
+ struct {
+ int ucs;
+ int len;
+ int min;
+ } utf_8;
};
struct term_spec {
@@ -1028,6 +1033,7 @@
unsigned char term[MAX_TERM_LEN];
int mode;
int m11_hack;
+ int utf_8_io;
int restrict_852;
int block_cursor;
int col;
@@ -1729,6 +1735,9 @@
void do_auth_dialog(struct session *);
/* charsets.c */
+/* UCS/Unicode replacement character */
+#define UCS_NO_CHAR 0xFFFD
+
#include "codepage.h"
struct conv_table {
@@ -1747,6 +1756,8 @@
unsigned char *get_cp_mime_name(int);
int is_cp_special(int);
void free_conv_table();
+unsigned char *cp2utf_8(int, int);
+unsigned char *u2cp(int, int);
/* view.c */
diff -u --recursive links-0.99.orig/menu.c links-0.99/menu.c
--- links-0.99.orig/menu.c 2003-11-18 14:38:24.000000000 -0800
+++ links-0.99/menu.c 2004-01-05 18:46:26.000000000 -0800
@@ -385,15 +385,15 @@
cls_redraw_all_terminals();
}
-unsigned char *td_labels[] = { TEXT(T_NO_FRAMES), TEXT(T_VT_100_FRAMES), TEXT(T_LINUX_OR_OS2_FRAMES), TEXT(T_KOI8R_FRAMES), TEXT(T_FREEBSD_FRAMES), TEXT(T_USE_11M), TEXT(T_RESTRICT_FRAMES_IN_CP850_852), TEXT(T_BLOCK_CURSOR), TEXT(T_COLOR), NULL };
+unsigned char *td_labels[] = { TEXT(T_NO_FRAMES), TEXT(T_VT_100_FRAMES), TEXT(T_LINUX_OR_OS2_FRAMES), TEXT(T_KOI8R_FRAMES), TEXT(T_FREEBSD_FRAMES), TEXT(T_USE_11M), TEXT(T_RESTRICT_FRAMES_IN_CP850_852), TEXT(T_BLOCK_CURSOR), TEXT(T_COLOR), TEXT(T_UTF_8_IO), NULL };
void terminal_options(struct terminal *term, void *xxx, struct session *ses)
{
struct dialog *d;
struct term_spec *ts = new_term_spec(term->term);
if (!ts) return;
- if (!(d = mem_alloc(sizeof(struct dialog) + 12 * sizeof(struct dialog_item)))) return;
- memset(d, 0, sizeof(struct dialog) + 12 * sizeof(struct dialog_item));
+ if (!(d = mem_alloc(sizeof(struct dialog) + 13 * sizeof(struct dialog_item)))) return;
+ memset(d, 0, sizeof(struct dialog) + 13 * sizeof(struct dialog_item));
d->title = TEXT(T_TERMINAL_OPTIONS);
d->fn = checkbox_list_fn;
d->udata = td_labels;
@@ -439,15 +439,19 @@
d->items[8].gid = 0;
d->items[8].dlen = sizeof(int);
d->items[8].data = (void *)&ts->col;
- d->items[9].type = D_BUTTON;
- d->items[9].gid = B_ENTER;
- d->items[9].fn = ok_dialog;
- d->items[9].text = TEXT(T_OK);
+ d->items[9].type = D_CHECKBOX;
+ d->items[9].gid = 0;
+ d->items[9].dlen = sizeof(int);
+ d->items[9].data = (void *)&ts->utf_8_io;
d->items[10].type = D_BUTTON;
- d->items[10].gid = B_ESC;
- d->items[10].fn = cancel_dialog;
- d->items[10].text = TEXT(T_CANCEL);
- d->items[11].type = D_END;
+ d->items[10].gid = B_ENTER;
+ d->items[10].fn = ok_dialog;
+ d->items[10].text = TEXT(T_OK);
+ d->items[11].type = D_BUTTON;
+ d->items[11].gid = B_ESC;
+ d->items[11].fn = cancel_dialog;
+ d->items[11].text = TEXT(T_CANCEL);
+ d->items[12].type = D_END;
do_dialog(term, d, getml(d, NULL));
}
diff -u --recursive links-0.99.orig/terminal.c links-0.99/terminal.c
--- links-0.99.orig/terminal.c 2003-11-28 06:36:27.000000000 -0800
+++ links-0.99/terminal.c 2004-01-05 19:20:43.000000000 -0800
@@ -345,6 +345,25 @@
return term;
}
+static inline void term_send_event(struct terminal *term, struct event *ev)
+{
+ ((struct window *)&term->windows)->next->handler(term->windows.next, ev, 0);
+}
+
+static inline void term_send_ucs(struct terminal *term, struct event *ev, int u)
+{
+ unsigned char *recoded;
+
+ if (u == 0xA0) u = ' ';
+ recoded = u2cp(u, term->spec->charset);
+ if (! recoded) recoded = "*";
+ while (*recoded) {
+ ev->x = *recoded;
+ term_send_event(term, ev);
+ recoded ++;
+ }
+}
+
void in_term(struct terminal *term)
{
struct event *ev;
@@ -405,7 +424,40 @@
goto send_redraw;
}
else if (ev->ev == EV_KBD && ev->x == KBD_CTRL_C) ((struct window *)&term->windows)->prev->handler(term->windows.prev, ev, 0);
- else ((struct window *)&term->windows)->next->handler(term->windows.next, ev, 0);
+ else if (ev->ev == EV_KBD) {
+ if (term->utf_8.len) {
+ if ((ev->x & 0xC0) == 0x80 && term->spec->utf_8_io) {
+ term->utf_8.ucs <<= 6;
+ term->utf_8.ucs |= ev->x & 0x3F;
+ if (! --term->utf_8.len) {
+ int u = term->utf_8.ucs;
+
+ if (u < term->utf_8.min) u = UCS_NO_CHAR;
+ term_send_ucs(term, ev, u);
+ }
+ goto mm;
+ } else {
+ term->utf_8.len = 0;
+ term_send_ucs(term, ev, UCS_NO_CHAR);
+ }
+ }
+ if (ev->x < 0x80 || ev->x > 0xFF || ! term->spec->utf_8_io) {
+ term_send_event(term, ev);
+ goto mm;
+ } else if ((ev->x & 0xC0) == 0xC0 && (ev->x & 0xFE) != 0xFE) {
+ int mask, len = 0, cov = 0x80;
+
+ for (mask = 0x80; ev->x & mask; mask >>= 1) {
+ len++;
+ term->utf_8.min = cov;
+ cov = 1 << (1 + 5 * len);
+ }
+ term->utf_8.len = len - 1;
+ term->utf_8.ucs = ev->x & (mask - 1);
+ goto mm;
+ }
+ term_send_ucs(term, ev, UCS_NO_CHAR);
+ } else term_send_event(term, ev);
}
if (ev->ev == EV_ABORT) {
destroy_terminal(term);
@@ -425,6 +477,14 @@
unsigned char frame_dumb[48] = " ||||++||++++++--|-+||++--|-+----++++++++ ";
unsigned char frame_vt100[48] = "aaaxuuukkuxkjjjkmvwtqnttmlvwtqnvvwwmmllnnjla ";
+unsigned char frame_vt100_u[48] = {
+ 177,177,177,179,180,180,180,191,
+ 191,180,179,191,217,217,217,191,
+ 192,193,194,195,196,197,195,195,
+ 192,218,193,194,195,196,197,193,
+ 193,194,194,192,192,218,218,197,
+ 197,217,218,177, 32, 32, 32, 32
+};
unsigned char frame_koi[48] = {
144,145,146,129,135,178,180,167,
166,181,161,168,174,173,172,131,
@@ -456,7 +516,7 @@
unsigned char c = ch & 0xff; \
unsigned char A = ch >> 8 & 0x7f; \
if (s->mode == TERM_LINUX) { \
- if (s->m11_hack) { \
+ if (s->m11_hack && !s->utf_8_io) { \
if (ch >> 15 != mode) { \
if (!(mode = ch >> 15)) add_to_str(&a, &l, "\033[10m"); \
else add_to_str(&a, &l, "\033[11m"); \
@@ -465,14 +525,16 @@
if (s->restrict_852 && (ch >> 15) && c >= 176 && c < 224) { \
if (frame_restrict[c - 176]) c = frame_restrict[c - 176]; \
} \
- } else if (s->mode == TERM_VT100) { \
+ } else if (s->mode == TERM_VT100 && !s->utf_8_io) { \
if (ch >> 15 != mode) { \
if (!(mode = ch >> 15)) add_to_str(&a, &l, "\x0f"); \
else add_to_str(&a, &l, "\x0e"); \
} \
if (mode && c >= 176 && c < 224) c = frame_vt100[c - 176]; \
+ } else if (s->mode == TERM_VT100 && (ch >> 15) && c >= 176 && c < 224) { \
+ c = frame_vt100_u[c - 176]; \
} else if (s->mode == TERM_KOI8 && (ch >> 15) && c >= 176 && c < 224) { c = frame_koi[c - 176];\
- } else if (s->mode == TERM_FREEBSD && (ch >> 15) && c >= 176 && c < 224) { c = frame_freebsd[c - 176];\
+ } else if (s->mode == TERM_FREEBSD && (ch >> 15) && c >= 176 && c < 224 && !s->utf_8_io) { c = frame_freebsd[c - 176];\
} else if (s->mode == TERM_DUMB && (ch >> 15) && c >= 176 && c < 224) c = frame_dumb[c - 176];\
if (!(A & 0100) && (A >> 3) == (A & 7)) A = (A & 070) | 7 * !(A & 020); \
if (A != attrib) { \
@@ -491,7 +553,20 @@
if (attrib & 0100) add_to_str(&a, &l, ";1"); \
add_to_str(&a, &l, "m"); \
} \
- if (c >= ' ' && c != 127/* && c != 155*/) add_chr_to_str(&a, &l, c); \
+ if (c >= ' ' && c != 127/* && c != 155*/) { \
+ int charset = s->charset; \
+ \
+ if (ch >> 15) { \
+ int frames_charset = (s->mode == TERM_LINUX || s->mode == TERM_VT100 || s->mode == TERM_FREEBSD) \
+ ? get_cp_index("cp437") \
+ : s->mode == TERM_KOI8 \
+ ? get_cp_index("koi8-r") \
+ : -1; \
+ if (frames_charset != -1) charset = frames_charset; \
+ } \
+ if (s->utf_8_io) add_to_str(&a, &l, cp2utf_8(charset, c)); \
+ else add_chr_to_str(&a, &l, c); \
+ } \
else if (!c || c == 1) add_chr_to_str(&a, &l, ' '); \
else add_chr_to_str(&a, &l, '.'); \
cx++; \
links-0.99-utf-8.diff
(application/octet-stream, 11.2 KB)
diff -u --recursive links-0.99.orig/charsets.c links-0.99/charsets.c
--- links-0.99.orig/charsets.c 2003-02-05 02:18:17.000000000 -0800
+++ links-0.99/charsets.c 2004-01-05 18:35:02.000000000 -0800
@@ -89,7 +89,7 @@
0x007e, 0x2122, 0x0161, 0x003e, 0x0153, 0x0000, 0x0000, 0x0000,
};
-static inline unsigned char *u2cp(int u, int to)
+unsigned char *u2cp(int u, int to)
{
int j, s;
if (u < 128) return strings[u];
@@ -140,6 +140,22 @@
return utf_buffer;
}
+/* this slow and ugly code is used by the terminal utf_8_io */
+unsigned char *cp2utf_8(int from, int c)
+{
+ int j;
+
+ if (codepages[from].table == table_utf_8) return strings[c];
+ for (j = 0; codepages[from].table[j].c; j++) {
+ if (codepages[from].table[j].c == c)
+ {
+ return encode_utf_8(codepages[from].table[j].u);
+ }
+ }
+ if (c < 128) return strings[c];
+ return encode_utf_8(UCS_NO_CHAR);
+}
+
void add_utf_8(struct conv_table *ct, int u, unsigned char *str)
{
unsigned char *p = encode_utf_8(u);
diff -u --recursive links-0.99.orig/default.c links-0.99/default.c
--- links-0.99.orig/default.c 2003-11-18 14:38:22.000000000 -0800
+++ links-0.99/default.c 2004-01-05 18:35:02.000000000 -0800
@@ -575,6 +575,7 @@
}
}
+/* terminal NAME(str) MODE(0-3) M11_HACK(0-1) BLOCK_CURSOR.RESTRICT_852.COL(0-7) CHARSET(str) [ UTF_8_IO("utf-8") ]*/
unsigned char *term_rd(struct option *o, unsigned char *c)
{
struct term_spec *ts;
@@ -585,6 +586,7 @@
mem_free(w);
goto end;
}
+ ts->utf_8_io = 0;
mem_free(w);
if (!(w = get_token(&c))) goto err;
if (strlen(w) != 1 || w[0] < '0' || w[0] > '4') goto err_f;
@@ -604,6 +606,9 @@
if ((i = get_cp_index(w)) == -1) goto err_f;
ts->charset = i;
mem_free(w);
+ if (!(w = get_token(&c))) goto end;
+ if (!(strcasecmp(w, "utf-8"))) ts->utf_8_io = 1;
+ mem_free(w);
end:
return NULL;
err_f:
@@ -612,6 +617,7 @@
return "Error reading terminal specification";
}
+/* terminal2 NAME(str) MODE(0-3) M11_HACK(0-1) RESTRICT_852(0-1) COL(0-1) CHARSET(str) [ UTF_8_IO("utf-8") ]*/
unsigned char *term2_rd(struct option *o, unsigned char *c)
{
struct term_spec *ts;
@@ -622,6 +628,7 @@
mem_free(w);
goto end;
}
+ ts->utf_8_io = 0;
mem_free(w);
if (!(w = get_token(&c))) goto err;
if (strlen(w) != 1 || w[0] < '0' || w[0] > '4') goto err_f;
@@ -643,6 +650,9 @@
if ((i = get_cp_index(w)) == -1) goto err_f;
ts->charset = i;
mem_free(w);
+ if (!(w = get_token(&c))) goto end;
+ if (!(strcasecmp(w, "utf-8"))) ts->utf_8_io = 1;
+ mem_free(w);
end:
return NULL;
err_f:
@@ -665,6 +675,10 @@
add_num_to_str(s, l, !!ts->col + !!ts->restrict_852 * 2 + !!ts->block_cursor * 4);
add_to_str(s, l, " ");
add_to_str(s, l, get_cp_mime_name(ts->charset));
+ if (ts->utf_8_io)
+ {
+ add_to_str(s, l, " utf-8");
+ }
}
}
diff -u --recursive links-0.99.orig/intl/english.lng links-0.99/intl/english.lng
--- links-0.99.orig/intl/english.lng 2003-12-14 13:33:27.000000000 -0800
+++ links-0.99/intl/english.lng 2004-01-05 18:35:29.000000000 -0800
@@ -49,6 +49,7 @@
T_KOI8R_FRAMES, "KOI8-R frames",
T_FREEBSD_FRAMES, "FreeBSD frames",
T_USE_11M, "Use ^[[11m",
+T_UTF_8_IO, "UTF-8 I/O",
T_RESTRICT_FRAMES_IN_CP850_852, "Restrict frames in cp850/852",
T_BLOCK_CURSOR, "Block cursor",
T_COLOR, "Color",
diff -u --recursive links-0.99.orig/links.h links-0.99/links.h
--- links-0.99.orig/links.h 2003-12-14 13:29:45.000000000 -0800
+++ links-0.99/links.h 2004-01-05 19:05:35.000000000 -0800
@@ -1020,6 +1020,11 @@
int qlen;
struct list_head windows;
unsigned char *title;
+ struct {
+ int ucs;
+ int len;
+ int min;
+ } utf_8;
};
struct term_spec {
@@ -1028,6 +1033,7 @@
unsigned char term[MAX_TERM_LEN];
int mode;
int m11_hack;
+ int utf_8_io;
int restrict_852;
int block_cursor;
int col;
@@ -1729,6 +1735,9 @@
void do_auth_dialog(struct session *);
/* charsets.c */
+/* UCS/Unicode replacement character */
+#define UCS_NO_CHAR 0xFFFD
+
#include "codepage.h"
struct conv_table {
@@ -1747,6 +1756,8 @@
unsigned char *get_cp_mime_name(int);
int is_cp_special(int);
void free_conv_table();
+unsigned char *cp2utf_8(int, int);
+unsigned char *u2cp(int, int);
/* view.c */
diff -u --recursive links-0.99.orig/menu.c links-0.99/menu.c
--- links-0.99.orig/menu.c 2003-11-18 14:38:24.000000000 -0800
+++ links-0.99/menu.c 2004-01-05 18:46:26.000000000 -0800
@@ -385,15 +385,15 @@
cls_redraw_all_terminals();
}
-unsigned char *td_labels[] = { TEXT(T_NO_FRAMES), TEXT(T_VT_100_FRAMES), TEXT(T_LINUX_OR_OS2_FRAMES), TEXT(T_KOI8R_FRAMES), TEXT(T_FREEBSD_FRAMES), TEXT(T_USE_11M), TEXT(T_RESTRICT_FRAMES_IN_CP850_852), TEXT(T_BLOCK_CURSOR), TEXT(T_COLOR), NULL };
+unsigned char *td_labels[] = { TEXT(T_NO_FRAMES), TEXT(T_VT_100_FRAMES), TEXT(T_LINUX_OR_OS2_FRAMES), TEXT(T_KOI8R_FRAMES), TEXT(T_FREEBSD_FRAMES), TEXT(T_USE_11M), TEXT(T_RESTRICT_FRAMES_IN_CP850_852), TEXT(T_BLOCK_CURSOR), TEXT(T_COLOR), TEXT(T_UTF_8_IO), NULL };
void terminal_options(struct terminal *term, void *xxx, struct session *ses)
{
struct dialog *d;
struct term_spec *ts = new_term_spec(term->term);
if (!ts) return;
- if (!(d = mem_alloc(sizeof(struct dialog) + 12 * sizeof(struct dialog_item)))) return;
- memset(d, 0, sizeof(struct dialog) + 12 * sizeof(struct dialog_item));
+ if (!(d = mem_alloc(sizeof(struct dialog) + 13 * sizeof(struct dialog_item)))) return;
+ memset(d, 0, sizeof(struct dialog) + 13 * sizeof(struct dialog_item));
d->title = TEXT(T_TERMINAL_OPTIONS);
d->fn = checkbox_list_fn;
d->udata = td_labels;
@@ -439,15 +439,19 @@
d->items[8].gid = 0;
d->items[8].dlen = sizeof(int);
d->items[8].data = (void *)&ts->col;
- d->items[9].type = D_BUTTON;
- d->items[9].gid = B_ENTER;
- d->items[9].fn = ok_dialog;
- d->items[9].text = TEXT(T_OK);
+ d->items[9].type = D_CHECKBOX;
+ d->items[9].gid = 0;
+ d->items[9].dlen = sizeof(int);
+ d->items[9].data = (void *)&ts->utf_8_io;
d->items[10].type = D_BUTTON;
- d->items[10].gid = B_ESC;
- d->items[10].fn = cancel_dialog;
- d->items[10].text = TEXT(T_CANCEL);
- d->items[11].type = D_END;
+ d->items[10].gid = B_ENTER;
+ d->items[10].fn = ok_dialog;
+ d->items[10].text = TEXT(T_OK);
+ d->items[11].type = D_BUTTON;
+ d->items[11].gid = B_ESC;
+ d->items[11].fn = cancel_dialog;
+ d->items[11].text = TEXT(T_CANCEL);
+ d->items[12].type = D_END;
do_dialog(term, d, getml(d, NULL));
}
diff -u --recursive links-0.99.orig/terminal.c links-0.99/terminal.c
--- links-0.99.orig/terminal.c 2003-11-28 06:36:27.000000000 -0800
+++ links-0.99/terminal.c 2004-01-05 19:20:43.000000000 -0800
@@ -345,6 +345,25 @@
return term;
}
+static inline void term_send_event(struct terminal *term, struct event *ev)
+{
+ ((struct window *)&term->windows)->next->handler(term->windows.next, ev, 0);
+}
+
+static inline void term_send_ucs(struct terminal *term, struct event *ev, int u)
+{
+ unsigned char *recoded;
+
+ if (u == 0xA0) u = ' ';
+ recoded = u2cp(u, term->spec->charset);
+ if (! recoded) recoded = "*";
+ while (*recoded) {
+ ev->x = *recoded;
+ term_send_event(term, ev);
+ recoded ++;
+ }
+}
+
void in_term(struct terminal *term)
{
struct event *ev;
@@ -405,7 +424,40 @@
goto send_redraw;
}
else if (ev->ev == EV_KBD && ev->x == KBD_CTRL_C) ((struct window *)&term->windows)->prev->handler(term->windows.prev, ev, 0);
- else ((struct window *)&term->windows)->next->handler(term->windows.next, ev, 0);
+ else if (ev->ev == EV_KBD) {
+ if (term->utf_8.len) {
+ if ((ev->x & 0xC0) == 0x80 && term->spec->utf_8_io) {
+ term->utf_8.ucs <<= 6;
+ term->utf_8.ucs |= ev->x & 0x3F;
+ if (! --term->utf_8.len) {
+ int u = term->utf_8.ucs;
+
+ if (u < term->utf_8.min) u = UCS_NO_CHAR;
+ term_send_ucs(term, ev, u);
+ }
+ goto mm;
+ } else {
+ term->utf_8.len = 0;
+ term_send_ucs(term, ev, UCS_NO_CHAR);
+ }
+ }
+ if (ev->x < 0x80 || ev->x > 0xFF || ! term->spec->utf_8_io) {
+ term_send_event(term, ev);
+ goto mm;
+ } else if ((ev->x & 0xC0) == 0xC0 && (ev->x & 0xFE) != 0xFE) {
+ int mask, len = 0, cov = 0x80;
+
+ for (mask = 0x80; ev->x & mask; mask >>= 1) {
+ len++;
+ term->utf_8.min = cov;
+ cov = 1 << (1 + 5 * len);
+ }
+ term->utf_8.len = len - 1;
+ term->utf_8.ucs = ev->x & (mask - 1);
+ goto mm;
+ }
+ term_send_ucs(term, ev, UCS_NO_CHAR);
+ } else term_send_event(term, ev);
}
if (ev->ev == EV_ABORT) {
destroy_terminal(term);
@@ -425,6 +477,14 @@
unsigned char frame_dumb[48] = " ||||++||++++++--|-+||++--|-+----++++++++ ";
unsigned char frame_vt100[48] = "aaaxuuukkuxkjjjkmvwtqnttmlvwtqnvvwwmmllnnjla ";
+unsigned char frame_vt100_u[48] = {
+ 177,177,177,179,180,180,180,191,
+ 191,180,179,191,217,217,217,191,
+ 192,193,194,195,196,197,195,195,
+ 192,218,193,194,195,196,197,193,
+ 193,194,194,192,192,218,218,197,
+ 197,217,218,177, 32, 32, 32, 32
+};
unsigned char frame_koi[48] = {
144,145,146,129,135,178,180,167,
166,181,161,168,174,173,172,131,
@@ -456,7 +516,7 @@
unsigned char c = ch & 0xff; \
unsigned char A = ch >> 8 & 0x7f; \
if (s->mode == TERM_LINUX) { \
- if (s->m11_hack) { \
+ if (s->m11_hack && !s->utf_8_io) { \
if (ch >> 15 != mode) { \
if (!(mode = ch >> 15)) add_to_str(&a, &l, "\033[10m"); \
else add_to_str(&a, &l, "\033[11m"); \
@@ -465,14 +525,16 @@
if (s->restrict_852 && (ch >> 15) && c >= 176 && c < 224) { \
if (frame_restrict[c - 176]) c = frame_restrict[c - 176]; \
} \
- } else if (s->mode == TERM_VT100) { \
+ } else if (s->mode == TERM_VT100 && !s->utf_8_io) { \
if (ch >> 15 != mode) { \
if (!(mode = ch >> 15)) add_to_str(&a, &l, "\x0f"); \
else add_to_str(&a, &l, "\x0e"); \
} \
if (mode && c >= 176 && c < 224) c = frame_vt100[c - 176]; \
+ } else if (s->mode == TERM_VT100 && (ch >> 15) && c >= 176 && c < 224) { \
+ c = frame_vt100_u[c - 176]; \
} else if (s->mode == TERM_KOI8 && (ch >> 15) && c >= 176 && c < 224) { c = frame_koi[c - 176];\
- } else if (s->mode == TERM_FREEBSD && (ch >> 15) && c >= 176 && c < 224) { c = frame_freebsd[c - 176];\
+ } else if (s->mode == TERM_FREEBSD && (ch >> 15) && c >= 176 && c < 224 && !s->utf_8_io) { c = frame_freebsd[c - 176];\
} else if (s->mode == TERM_DUMB && (ch >> 15) && c >= 176 && c < 224) c = frame_dumb[c - 176];\
if (!(A & 0100) && (A >> 3) == (A & 7)) A = (A & 070) | 7 * !(A & 020); \
if (A != attrib) { \
@@ -491,7 +553,20 @@
if (attrib & 0100) add_to_str(&a, &l, ";1"); \
add_to_str(&a, &l, "m"); \
} \
- if (c >= ' ' && c != 127/* && c != 155*/) add_chr_to_str(&a, &l, c); \
+ if (c >= ' ' && c != 127/* && c != 155*/) { \
+ int charset = s->charset; \
+ \
+ if (ch >> 15) { \
+ int frames_charset = (s->mode == TERM_LINUX || s->mode == TERM_VT100 || s->mode == TERM_FREEBSD) \
+ ? get_cp_index("cp437") \
+ : s->mode == TERM_KOI8 \
+ ? get_cp_index("koi8-r") \
+ : -1; \
+ if (frames_charset != -1) charset = frames_charset; \
+ } \
+ if (s->utf_8_io) add_to_str(&a, &l, cp2utf_8(charset, c)); \
+ else add_chr_to_str(&a, &l, c); \
+ } \
else if (!c || c == 1) add_chr_to_str(&a, &l, ' '); \
else add_chr_to_str(&a, &l, '.'); \
cx++; \