diff --recursive -ub links-0.97pre12.orig/charsets.c links-0.97pre12/charsets.c
--- links-0.97pre12.orig/charsets.c     Mon Mar  4 21:48:15 2002
+++ links-0.97pre12/charsets.c  Thu May  9 01:59:38 2002
@@ -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];
@@ -138,6 +138,22 @@
               utf_buffer[4] = 0x80 | ((u >> 6) & 0x3f),
               utf_buffer[5] = 0x80 | (u & 0x3f);
       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)
diff --recursive -ub links-0.97pre12.orig/default.c links-0.97pre12/default.c
--- links-0.97pre12.orig/default.c      Thu Apr  4 10:49:48 2002
+++ links-0.97pre12/default.c   Thu May  9 01:59:38 2002
@@ -556,6 +556,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;
@@ -566,6 +567,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] > '3') goto err_f;
@@ -585,6 +587,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:
@@ -593,6 +598,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;
@@ -603,6 +609,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] > '3') goto err_f;
@@ -624,6 +631,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:
@@ -646,6 +656,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 --recursive -ub links-0.97pre12.orig/intl/english.lng links-0.97pre12/intl/english.lng
--- links-0.97pre12.orig/intl/english.lng       Tue Mar 26 17:35:45 2002
+++ links-0.97pre12/intl/english.lng    Thu May  9 01:59:46 2002
@@ -48,6 +48,7 @@
T_LINUX_OR_OS2_FRAMES, "Linux or OS/2 frames",
T_KOI8R_FRAMES, "KOI8-R 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 --recursive -ub links-0.97pre12.orig/links.h links-0.97pre12/links.h
--- links-0.97pre12.orig/links.h        Wed Apr  3 14:41:02 2002
+++ links-0.97pre12/links.h     Thu May  9 01:59:46 2002
@@ -992,6 +992,11 @@
       int qlen;
       struct list_head windows;
       unsigned char *title;
+       struct {
+               int ucs;
+               int len;
+               int min;
+       } utf_8;
};

struct term_spec {
@@ -1000,6 +1005,7 @@
       unsigned char term[MAX_TERM_LEN];
       int mode;
       int m11_hack;
+       int utf_8_io;
       int restrict_852;
       int block_cursor;
       int col;
@@ -1701,6 +1707,9 @@
void do_auth_dialog(struct session *);
/* charsets.c */

+/* UCS/Unicode replacement character */
+#define UCS_NO_CHAR 0xFFFD
+
#include "codepage.h"

struct conv_table {
@@ -1719,6 +1728,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 --recursive -ub links-0.97pre12.orig/menu.c links-0.97pre12/menu.c
--- links-0.97pre12.orig/menu.c Sat Mar  9 09:52:32 2002
+++ links-0.97pre12/menu.c      Thu May  9 01:59:46 2002
@@ -380,15 +380,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_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_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) + 11 * sizeof(struct dialog_item)))) return;
-       memset(d, 0, sizeof(struct dialog) + 11 * sizeof(struct dialog_item));
+       if (!(d = mem_alloc(sizeof(struct dialog) + 12 * sizeof(struct dialog_item)))) return;
+       memset(d, 0, sizeof(struct dialog) + 12 * sizeof(struct dialog_item));
       d->title = TEXT(T_TERMINAL_OPTIONS);
       d->fn = checkbox_list_fn;
       d->udata = td_labels;
@@ -429,15 +429,19 @@
       d->items[7].gid = 0;
       d->items[7].dlen = sizeof(int);
       d->items[7].data = (void *)&ts->col;
-       d->items[8].type = D_BUTTON;
-       d->items[8].gid = B_ENTER;
-       d->items[8].fn = ok_dialog;
-       d->items[8].text = TEXT(T_OK);
+       d->items[8].type = D_CHECKBOX;
+       d->items[8].gid = 0;
+       d->items[8].dlen = sizeof(int);
+       d->items[8].data = (void *)&ts->utf_8_io;
       d->items[9].type = D_BUTTON;
-       d->items[9].gid = B_ESC;
-       d->items[9].fn = cancel_dialog;
-       d->items[9].text = TEXT(T_CANCEL);
-       d->items[10].type = D_END;
+       d->items[9].gid = B_ENTER;
+       d->items[9].fn = ok_dialog;
+       d->items[9].text = TEXT(T_OK);
+       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;
       do_dialog(term, d, getml(d, NULL));
}

diff --recursive -ub links-0.97pre12.orig/terminal.c links-0.97pre12/terminal.c
--- links-0.97pre12.orig/terminal.c     Wed Jan 30 07:53:48 2002
+++ links-0.97pre12/terminal.c  Thu May  9 02:03:46 2002
@@ -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);
       /*redraw_screen(term);*/
@@ -422,6 +474,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,
@@ -445,7 +505,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");                    \
@@ -454,12 +514,14 @@
               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_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);         \
@@ -479,7 +541,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) \
+                                               ? 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++;                                                                           \