Robert de Bath's Big Patch, part 1
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Wed, 26 Jul 2000 12:13:51 +0000 (12:13 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Wed, 26 Jul 2000 12:13:51 +0000 (12:13 +0000)
git-svn-id: svn://svn.tartarus.org/sgt/putty@516 cda61777-01e9-0310-a592-d414129be87e

Makefile
ldisc.c
putty.h
raw.c
ssh.c
telnet.c
terminal.c
win_res.h
win_res.rc
windlg.c
window.c

index e663d3a..dd7b067 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -33,7 +33,7 @@ CFLAGS = /nologo /W3 /YX /O2 /Yd /D_WINDOWS /DDEBUG /ML /Fd
 # LFLAGS = /debug
 
 # Use MSVC DLL
-# CFLAGS = /nologo /W3 /YX /O2 /Yd /D_WINDOWS /DDEBUG /ML /Fd
+# CFLAGS = /nologo /W3 /YX /O2 /Yd /D_WINDOWS /DDEBUG /MD /Fd
 
 # Disable debug and incremental linking
 LFLAGS = /incremental:no
diff --git a/ldisc.c b/ldisc.c
index 59bddb2..819360d 100644 (file)
--- a/ldisc.c
+++ b/ldisc.c
@@ -9,13 +9,8 @@
  */
 
 static void c_write (char *buf, int len) {
-    while (len--) {
-       int new_head = (inbuf_head + 1) & INBUF_MASK;
-       if (new_head != inbuf_reap) {
-           inbuf[inbuf_head] = *buf++;
-           inbuf_head = new_head;
-       }
-    }
+    while (len--) 
+        c_write1(*buf++);
 }
 
 static char *term_buf = NULL;
@@ -34,8 +29,7 @@ static int plen(unsigned char c) {
 static void pwrite(unsigned char c) {
     if ((c >= 32 && c <= 126) ||
         (c >= 160)) {
-        char cc = (char)c;
-        c_write(&cc, 1);
+        c_write1(c);
     } else if (c < 128) {
         char cc[2];
         cc[1] = (c == 127 ? '?' : c + 0x40);
diff --git a/putty.h b/putty.h
index 0971fab..3b2257a 100644 (file)
--- a/putty.h
+++ b/putty.h
@@ -21,6 +21,12 @@ GLOBAL HINSTANCE putty_inst;
 #define ATTR_INVALID 0x20000000UL
 #define ATTR_WRAPPED 0x10000000UL
 
+#define LATTR_NORM   0x00000000UL
+#define LATTR_WIDE   0x01000000UL
+#define LATTR_TOP    0x02000000UL
+#define LATTR_BOT    0x03000000UL
+#define LATTR_MODE   0x03000000UL
+
 #define ATTR_ASCII   0x00000000UL      /* normal ASCII charset ESC ( B */
 #define ATTR_GBCHR   0x00100000UL      /* UK variant   charset ESC ( A */
 #define ATTR_LINEDRW 0x00200000UL      /* line drawing charset ESC ( 0 */
@@ -49,10 +55,11 @@ GLOBAL int rows, cols, savelines;
 
 GLOBAL int font_width, font_height;
 
+#define c_write1(_C) do { if (inbuf_head >= INBUF_SIZE) term_out(); \
+                         inbuf[inbuf_head++] = (_C) ; } while(0)
 #define INBUF_SIZE 2048
-#define INBUF_MASK (INBUF_SIZE-1)
 GLOBAL unsigned char inbuf[INBUF_SIZE];
-GLOBAL int inbuf_head, inbuf_reap;
+GLOBAL int inbuf_head;
 
 #define OUTBUF_SIZE 2048
 #define OUTBUF_MASK (OUTBUF_SIZE-1)
@@ -61,19 +68,14 @@ GLOBAL int outbuf_head, outbuf_reap;
 
 GLOBAL int has_focus;
 
-GLOBAL int app_cursor_keys, app_keypad_keys;
+GLOBAL int app_cursor_keys, app_keypad_keys, vt52_mode;
+GLOBAL int repeat_off, cr_lf_return;
 
 GLOBAL int seen_key_event;
 GLOBAL int seen_disp_event;
 
 GLOBAL int session_closed;
 
-typedef enum {
-    US_NONE = 0, US_KEY = 1, US_DISP = 2, US_BOTH = 3
-} Unscroll_Trigger;
-
-GLOBAL Unscroll_Trigger unscroll_event;
-
 GLOBAL char *logfile;
 
 /*
@@ -143,27 +145,31 @@ typedef struct {
     /* Keyboard options */
     int bksp_is_delete;
     int rxvt_homeend;
-    int linux_funkeys;
+    int funky_type;
     int app_cursor;
     int app_keypad;
     int nethack_keypad;
     int alt_f4;                               /* is it special? */
     int alt_space;                    /* is it special? */
     int ldisc_term;
-    int blink_cur;
-    int beep;
+    int scroll_on_key;
     /* Terminal options */
     int savelines;
     int dec_om;
     int wrap_mode;
     int lfhascr;
+    int blink_cur;
+    int beep;
+    int scrollbar;
+    int locksize;
+    int bce;
+    int blinktext;
     int win_name_always;
     int width, height;
     char font[64];
     int fontisbold;
     int fontheight;
     int fontcharset;
-    VT_Mode vtmode;
     /* Colour options */
     int try_palette;
     int bold_colour;
@@ -171,7 +177,8 @@ typedef struct {
     /* Selection options */
     int mouse_is_xterm;
     short wordness[256];
-    /* russian language translation */
+    /* translations */
+    VT_Mode vtmode;
     int xlat_enablekoiwin;
     int xlat_88592w1250;
     int xlat_capslockcyr;
@@ -198,7 +205,7 @@ struct RSAKey;                             /* be a little careful of scope */
  * Exports from window.c.
  */
 void request_resize (int, int, int);
-void do_text (Context, int, int, char *, int, unsigned long);
+void do_text (Context, int, int, char *, int, unsigned long, int);
 void set_title (char *);
 void set_icon (char *);
 void set_sbar (int, int, int);
@@ -210,7 +217,7 @@ void write_clip (void *, int);
 void get_clip (void **, int *);
 void optimised_move (int, int, int);
 void fatalbox (char *, ...);
-void beep (void);
+void beep (int);
 #define OPTIMISE_IS_SCROLL 1
 
 /*
@@ -252,6 +259,8 @@ void term_deselect (void);
 void term_update (void);
 void term_invalidate(void);
 void term_blink(int set_cursor);
+void term_paste(void);
+void term_nopaste(void);
 
 /*
  * Exports from raw.c.
diff --git a/raw.c b/raw.c
index 3023d95..e65190f 100644 (file)
--- a/raw.c
+++ b/raw.c
@@ -14,8 +14,6 @@
 
 static SOCKET s = INVALID_SOCKET;
 
-#define iswritable(x) ( (x) != IAC && (x) != CR )
-
 static void raw_size(void);
 
 static int sb_opt, sb_len;
@@ -50,16 +48,8 @@ static void s_write (void *buf, int len) {
 }
 
 static void c_write (char *buf, int len) {
-    while (len--) {
-       int new_head = (inbuf_head + 1) & INBUF_MASK;
-       if (new_head != inbuf_reap) {
-           inbuf[inbuf_head] = *buf++;
-           inbuf_head = new_head;
-       } else {
-            term_out();
-            if( inbuf_head == inbuf_reap ) len++; else break;
-       }
-    }
+    while (len--) 
+        c_write1(*buf++);
 }
 
 /*
diff --git a/ssh.c b/ssh.c
index acc89cf..65f0075 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -128,16 +128,8 @@ static void c_write (char *buf, int len) {
        if (len > 0) { fwrite(buf, len, 1, stderr); fputc('\n', stderr); }
        return;
     }
-    while (len--) {
-       int new_head = (inbuf_head + 1) & INBUF_MASK;
-       if (new_head != inbuf_reap) {
-           inbuf[inbuf_head] = *buf++;
-           inbuf_head = new_head;
-       } else {
-            term_out();
-            if( inbuf_head == inbuf_reap ) len++; else break;
-       }
-    }
+    while (len--) 
+        c_write1(*buf++);
 }
 
 struct Packet {
index 6b09a4a..1b83a31 100644 (file)
--- a/telnet.c
+++ b/telnet.c
@@ -165,19 +165,6 @@ static void s_write (void *buf, int len) {
     try_write();
 }
 
-static void c_write (char *buf, int len) {
-    while (len--) {
-       int new_head = (inbuf_head + 1) & INBUF_MASK;
-       if (new_head != inbuf_reap) {
-           inbuf[inbuf_head] = *buf++;
-           inbuf_head = new_head;
-       } else {
-            term_out();
-            if( inbuf_head == inbuf_reap ) len++; else break;
-       }
-    }
-}
-
 static void log_option (char *sender, int cmd, int option) {
     char buf[50];
     sprintf(buf, "%s:\t%s %s", sender,
@@ -384,7 +371,6 @@ static enum {
 } telnet_state = TOPLEVEL;
 
 static void do_telnet_read (char *buf, int len) {
-    unsigned char b[10];
 
     while (len--) {
        int c = (unsigned char) *buf++;
@@ -397,9 +383,8 @@ static void do_telnet_read (char *buf, int len) {
            else if (c == IAC)
                telnet_state = SEENIAC;
            else {
-               b[0] = c;
                if (!in_synch)
-                   c_write (b, 1);
+                   c_write1(c);
 
 #if 1
                /* I can't get the F***ing winsock to insert the urgent IAC
@@ -431,8 +416,7 @@ static void do_telnet_read (char *buf, int len) {
            else {
                /* ignore everything else; print it if it's IAC */
                if (c == IAC) {
-                   b[0] = c;
-                   c_write(b,1);
+                   c_write1(c);
                }
                telnet_state = TOPLEVEL;
            }
@@ -467,8 +451,8 @@ static void do_telnet_read (char *buf, int len) {
                    char *newbuf;
                    sb_size += SB_DELTA;
                    newbuf = (sb_buf ?
-                             realloc(sb_buf, sb_size) :
-                             malloc(sb_size));
+                             srealloc(sb_buf, sb_size) :
+                             smalloc(sb_size));
                    if (newbuf)
                        sb_buf = newbuf;
                    else
@@ -608,7 +592,11 @@ static char *telnet_init (HWND hwnd, char *host, int port, char **realhost) {
  */
 static int telnet_msg (WPARAM wParam, LPARAM lParam) {
     int ret;
-    char buf[256];
+    /* This needs to be larger than the packet size now that inbuf
+     * cannot overflow, in fact the fewer calls we make to windows
+     * the faster we will run!
+     */
+    char buf[16384];   
 
     /*
      * Because reading less than the whole of the available pending
index 856d5b1..d567f7d 100644 (file)
@@ -5,7 +5,7 @@
 
 #include "putty.h"
 
-#define CL_ANSIMIN     0x0001  /* Everybody has these even MSDOS */
+#define CL_ANSIMIN     0x0001  /* Codes in all ANSI like terminals. */
 #define CL_VT100       0x0002  /* VT100 */
 #define CL_VT100AVO    0x0004  /* VT100 +AVO; 132x24 (not 132x14) & attrs */
 #define CL_VT102       0x0008  /* VT102 */
 #define CL_VT420       0x0040  /* VT420 */
 #define CL_VT510       0x0080  /* VT510, NB VT510 includes ANSI */
 #define CL_VT340TEXT   0x0100  /* VT340 extensions that appear in the VT420 */
-#define CL_ANSI                0x1000  /* ANSI ECMA-48 not in the VT100..VT420 */
-#define CL_OTHER       0x2000  /* Others, Xterm, linux, putty, dunno, etc */
+#define CL_SCOANSI     0x1000  /* SCOANSI not in ANSIMIN. */
+#define CL_ANSI                0x2000  /* ANSI ECMA-48 not in the VT100..VT420 */
+#define CL_OTHER       0x4000  /* Others, Xterm, linux, putty, dunno, etc */
 
 #define TM_ANSIMIN     (CL_ANSIMIN)
-#define TM_VT100       (CL_ANSIMIN+CL_VT100)
-#define TM_VT100AVO    (TM_VT100+CL_VT100AVO)
-#define TM_VT102       (TM_VT100AVO+CL_VT102)
-#define TM_PUTTY       (-1)
+#define TM_VT100       (CL_ANSIMIN|CL_VT100)
+#define TM_VT100AVO    (TM_VT100|CL_VT100AVO)
+#define TM_VT102       (TM_VT100AVO|CL_VT102)
+#define TM_VT220       (TM_VT102|CL_VT220)
+#define TM_VTXXX       (TM_VT220|CL_VT340TEXT|CL_VT510|CL_VT420|CL_VT320)
+#define TM_SCOANSI     (CL_ANSIMIN|CL_SCOANSI)
+
+#define TM_PUTTY       (0xFFFF)
 
 #define compatibility(x) \
     if ( ((CL_##x)&compatibility_level) == 0 ) {       \
        termstate=TOPLEVEL;                             \
        break;                                          \
     }
+#define compatibility2(x,y) \
+    if ( ((CL_##x|CL_##y)&compatibility_level) == 0 ) { \
+       termstate=TOPLEVEL;                             \
+       break;                                          \
+    }
 
 #define has_compat(x) ( ((CL_##x)&compatibility_level) != 0 )
 
@@ -38,6 +48,7 @@ static unsigned long *text;          /* buffer of text on terminal screen */
 static unsigned long *scrtop;         /* top of working screen */
 static unsigned long *disptop;        /* top of displayed screen */
 static unsigned long *sbtop;          /* top of scrollback */
+static unsigned long *sbbot;          /* furthest extent of scrollback */
 static unsigned long *cpos;           /* cursor position (convenience) */
 static unsigned long *disptext;               /* buffer of text on real screen */
 static unsigned long *wanttext;               /* buffer of text we want on screen */
@@ -64,7 +75,8 @@ static int cursor_on;                /* cursor enabled flag */
 static int reset_132;                 /* Flag ESC c resets to 80 cols */
 static int use_bce;                   /* Use Background coloured erase */
 static int blinker;                   /* When blinking is the cursor on ? */
-static int vt52_mode;                 /* Is VT100+ in vt52 mode ? */
+static int tblinker;                  /* When the blinking text is on */
+static int blink_is_real;             /* Actually blink blinking text */
 
 static unsigned long cset_attr[2];
 
@@ -89,6 +101,8 @@ static int osc_strlen;
 static char osc_string[OSC_STR_MAX+1];
 static int osc_w;
 
+static char id_string[1024] = "\033[?6c";
+
 static unsigned char *tabs;
 
 static enum {
@@ -130,6 +144,8 @@ static short wordness[256] = {
 };
 
 static unsigned char sel_nl[] = SEL_NL;
+static char * paste_buffer = 0;
+static int paste_len, paste_pos, paste_hold;
 
 /*
  * Internal prototypes.
@@ -165,7 +181,8 @@ static void power_on(void) {
     save_attr = curr_attr = ATTR_DEFAULT;
     app_cursor_keys = cfg.app_cursor;
     app_keypad_keys = cfg.app_keypad;
-    use_bce = 0;
+    use_bce = cfg.bce;
+    blink_is_real = cfg.blinktext;
     erase_char = ERASE_CHAR;
     alt_which = 0;
     {
@@ -188,8 +205,8 @@ void term_update(void) {
     Context ctx;
     ctx = get_ctx();
     if (ctx) {
-        if ( (seen_key_event && (unscroll_event & US_KEY)) ||
-            (seen_disp_event && (unscroll_event & US_DISP)) ) {
+        if ( (seen_key_event && (cfg.scroll_on_key)) ||
+            (seen_disp_event && (!cfg.scroll_on_key)) ) {
            disptop = scrtop;
            seen_disp_event = seen_key_event = 0;
        }
@@ -221,7 +238,7 @@ void term_clrsb(void) {
  * Initialise the terminal.
  */
 void term_init(void) {
-    text = sbtop = scrtop = disptop = cpos = NULL;
+    text = sbtop = sbbot = scrtop = disptop = cpos = NULL;
     disptext = wanttext = NULL;
     tabs = NULL;
     selspace = NULL;
@@ -249,27 +266,32 @@ void term_size(int newrows, int newcols, int newsavelines) {
     alt_b = marg_b = newrows - 1;
 
     newtext = smalloc ((newrows+newsavelines)*(newcols+1)*TSIZE);
-    disptop = newtext + newsavelines*(newcols+1);
+    sbbot = newtext + newsavelines*(newcols+1);
     for (i=0; i<(newrows+newsavelines)*(newcols+1); i++)
-       newtext[i] = ERASE_CHAR;
+       newtext[i] = erase_char;
     if (rows != -1) {
        crows = rows + (scrtop - sbtop) / (cols+1);
        if (crows > newrows+newsavelines)
            crows = newrows+newsavelines;
+       if (newrows>crows)
+           disptop = newtext;
+       else
+            disptop = newtext + (crows-newrows)*(newcols+1);
        ccols = (cols < newcols ? cols : newcols);
        for (i=0; i<crows; i++) {
-           int oldidx = (rows + savelines - crows + i) * (cols+1);
-           int newidx = (newrows + newsavelines - crows + i) * (newcols+1);
+           int oldidx = (rows - crows + i) * (cols+1);
+           int newidx = (newrows - crows + i) * (newcols+1);
+
            for (j=0; j<ccols; j++)
-               newtext[newidx+j] = text[oldidx+j];
-           newtext[newidx+newcols] =
-               (cols == newcols ? text[oldidx+cols] : 0);
+               disptop[newidx+j] = scrtop[oldidx+j];
+           disptop[newidx+newcols] =
+               (cols == newcols ? scrtop[oldidx+cols] 
+                                : (scrtop[oldidx+cols]&LATTR_MODE));
        }
-       sbtop = disptop - (crows - newrows) * (newcols+1);
-       if (sbtop > disptop)
-           sbtop = disptop;
-    } else
-       sbtop = disptop;
+       sbtop = newtext;
+    } else {
+       sbtop = disptop = newtext;
+    }
     scrtop = disptop;
     sfree (text);
     text = newtext;
@@ -354,19 +376,6 @@ static void swap_screen (int which) {
 }
 
 /*
- * Retrieve a character from `inbuf'.
- */
-static int inbuf_getc(void) {
-    if (inbuf_head == inbuf_reap)
-       return -1;                     /* EOF */
-    else {
-       int n = inbuf_reap;
-       inbuf_reap = (inbuf_reap+1) & INBUF_MASK;
-       return inbuf[n];
-    }
-}
-
-/*
  * Update the scroll bar.
  */
 static void update_sbar(void) {
@@ -394,7 +403,14 @@ static void check_selection (unsigned long *from, unsigned long *to) {
  */
 static void scroll (int topline, int botline, int lines, int sb) {
     unsigned long *scroll_top;
+    unsigned long *newscr;
     int scroll_size, size, i;
+    int scrtop_is_disptop = (scrtop==disptop);
+static int recursive = 0;
+
+    /* Only scroll more than the window if we're doing a 10% scroll */
+    if (!recursive && lines > botline - topline + 1)
+        lines = botline - topline + 1;
 
     scroll_top = scrtop + topline*(cols+1);
     size = (lines < 0 ? -lines : lines) * (cols+1);
@@ -403,14 +419,89 @@ static void scroll (int topline, int botline, int lines, int sb) {
     if (lines > 0 && topline == 0 && alt_which == 0 && sb) {
        /*
         * Since we're going to scroll the top line and we're on the 
-        * scrolling screen let's also affect the scrollback buffer.
+        * scrolling screen let's also effect the scrollback buffer.
+        *
+        * This is normally done by moving the position the screen
+        * painter reads from to reduce the amount of memory copying
+        * required.
         */
-       sbtop -= lines * (cols+1);
-       if (sbtop < text)
-           sbtop = text;
-       scroll_size += scroll_top - sbtop;
-       scroll_top = sbtop;
-       update_sbar();
+       if (scroll_size >= 0 && !recursive) {
+           newscr = scrtop + lines * (cols+1);
+
+           if (newscr > sbbot && botline == rows-1) {
+               /* We've hit the bottom of memory, so we have to do a 
+                * physical scroll. But instead of just 1 line do it
+                * by 10% of the available memory.
+                *
+                * If the scroll region isn't the whole screen then we can't
+                * do this as it stands. We would need to recover the bottom
+                * of the screen from the scroll buffer after being sure that
+                * it doesn't get deleted.
+                */
+
+               i = (rows+savelines)/10;
+
+               /* Make it simple and ensure safe recursion */
+               if ( i<savelines-1) {
+                   recursive ++;
+                   scroll(topline, botline, i, sb);
+                   recursive --;
+
+                   newscr = scrtop - i * (cols+1);
+                   if (scrtop_is_disptop) disptop = newscr;
+                   scrtop = newscr;
+               }
+
+               newscr = scrtop + lines * (cols+1);
+           }
+
+           if (newscr <= sbbot) {
+               if (scrtop_is_disptop) disptop = newscr;
+               scrtop = newscr;
+
+               if (botline == rows-1 )
+                   for (i = 0; i < size; i++)
+                       scrtop[i+scroll_size] = erase_char;
+
+               update_sbar();
+               fix_cpos;
+
+               if (botline != rows-1) {
+                   /* This fastscroll only works for full window scrolls. 
+                    * If the caller wanted a partial one we have to reverse
+                    * scroll the bottom of the screen.
+                    */
+                   scroll(botline-lines+1, rows-1, -lines, 0);
+               }
+               return ;
+           }
+
+           /* If we can't scroll by memory remapping do it physically.
+            * But rather than expensivly doing the scroll buffer just
+            * scroll the screen. All it means is that sometimes we choose
+            * to not add lines from a scroll region to the scroll buffer.
+            */
+
+           if (savelines <= 400) {
+               sbtop -= lines * (cols+1);
+               if (sbtop < text)
+                   sbtop = text;
+               scroll_size += scroll_top - sbtop;
+               scroll_top = sbtop;
+    
+               update_sbar();
+           }
+       } else { 
+           /* Ho hum, expensive scroll required. */
+
+           sbtop -= lines * (cols+1);
+           if (sbtop < text)
+               sbtop = text;
+           scroll_size += scroll_top - sbtop;
+           scroll_top = sbtop;
+
+           update_sbar();
+       }
     }
 
     if (scroll_size < 0) {
@@ -435,6 +526,15 @@ static void scroll (int topline, int botline, int lines, int sb) {
            if (selend < scroll_top)
                selend = scroll_top;
        }
+       if (scrtop_is_disptop)
+           disptop = scrtop;
+       else
+           if (disptop > scroll_top &&
+               disptop < scroll_top + size + scroll_size) {
+               disptop -= size;
+               if (disptop < scroll_top)
+                   disptop = scroll_top;
+       }
     } else {
        if (scroll_size)
            memmove (scroll_top + size, scroll_top, scroll_size*TSIZE);
@@ -452,6 +552,14 @@ static void scroll (int topline, int botline, int lines, int sb) {
            if (selend > scroll_top + size + scroll_size)
                selend = scroll_top + size + scroll_size;
        }
+       if (scrtop_is_disptop)
+           disptop = scrtop;
+       else if (disptop > scroll_top &&
+               disptop < scroll_top + size + scroll_size) {
+               disptop += size;
+               if (disptop > scroll_top + size + scroll_size)
+                   disptop = scroll_top + size + scroll_size;
+       }
     }
 }
 
@@ -495,6 +603,10 @@ static void save_cursor(int save) {
     } else {
        curs_x = save_x;
        curs_y = save_y;
+       /* Make sure the window hasn't shrunk since the save */
+       if (curs_x >= cols) curs_x = cols-1;
+       if (curs_y >= rows) curs_y = rows-1;
+
        curr_attr = save_attr;
        cset = save_cset;
        cset_attr[cset] = save_csattr;
@@ -512,7 +624,10 @@ static void erase_lots (int line_only, int from_begin, int to_end) {
 
     if (line_only) {
        startpos = cpos - curs_x;
-       endpos = startpos + cols+1;
+       endpos = startpos + cols;
+       /* I've removed the +1 so that the Wide screen stuff is not
+        * removed when it shouldn't be.
+        */
     } else {
        startpos = scrtop;
        endpos = startpos + rows * (cols+1);
@@ -583,6 +698,9 @@ static void toggle_mode (int mode, int query, int state) {
       case 7:                         /* auto wrap */
        wrap = state;
        break;
+      case 8:                         /* auto key repeat */
+       repeat_off = !state;
+       break;
       case 25:                        /* enable/disable cursor */
        compatibility(VT220);
        cursor_on = state;
@@ -611,6 +729,9 @@ static void toggle_mode (int mode, int query, int state) {
        compatibility(VT220);
         ldisc = (state? &ldisc_simple : &ldisc_term);
        break;
+      case 20:                        /* Return sends ... */
+       cr_lf_return = state;
+       break;
     }
 }
 
@@ -644,10 +765,16 @@ static void do_osc(void) {
  * process escape sequences...
  */
 void term_out(void) {
-    int c;
+    int c, inbuf_reap;
+
+static int beep_overload = 0;
+    int beep_count = 0;
+
+    for(inbuf_reap = 0; inbuf_reap < inbuf_head; inbuf_reap++)
+    {
+        c = inbuf[inbuf_reap];
 
-    while ( (c = inbuf_getc()) != -1) {
-        /*
+       /*
          * Optionally log the session traffic to a file. Useful for
          * debugging and possibly also useful for actual logging.
          */
@@ -660,7 +787,8 @@ void term_out(void) {
         * be able to display 8-bit characters, but I'll let that go 'cause
         * of i18n.
         */
-       if( (c&0x60) == 0 && termstate < DO_CTRLS &&
+       if( ( (c&0x60) == 0 || c == '\177') && 
+            termstate < DO_CTRLS &&
            ( (c&0x80) == 0 || has_compat(VT220))) {
            switch (c) {
              case '\005':             /* terminal type query */
@@ -676,11 +804,14 @@ void term_out(void) {
                ldisc->send ("PuTTY", 5);
                break;
              case '\007':
-                if(cfg.beep) beep();
+               beep_count++; 
+               if(beep_count>6) beep_overload=1;
                disptop = scrtop;
                break;
              case '\b':
-               if (curs_x == 0 && curs_y > 0)
+               if (curs_x == 0 && curs_y == 0)
+                   ;
+               else if (curs_x == 0 && curs_y > 0)
                    curs_x = cols-1, curs_y--;
                else if (wrapnext)
                    wrapnext = FALSE;
@@ -722,6 +853,7 @@ void term_out(void) {
                wrapnext = FALSE;
                fix_cpos;
                seen_disp_event = TRUE;
+               paste_hold = 0;
                break;
              case '\013':
              case '\014':
@@ -736,15 +868,28 @@ void term_out(void) {
                fix_cpos;
                wrapnext = FALSE;
                seen_disp_event = 1;
+               paste_hold = 0;
                break;
              case '\t':
-               do {
-                   curs_x++;
-               } while (curs_x < cols-1 && !tabs[curs_x]);
-               if (curs_x >= cols)
-                   curs_x = cols-1;
                {
                    unsigned long *old_cpos = cpos;
+                   unsigned long *p = scrtop + curs_y * (cols+1) + cols;
+
+                   do {
+                       curs_x++;
+                   } while (curs_x < cols-1 && !tabs[curs_x]);
+
+                   if ((*p & LATTR_MODE) != LATTR_NORM)
+                   {
+                       if (curs_x >= cols/2)
+                           curs_x = cols/2-1;
+                   }
+                   else
+                   {
+                       if (curs_x >= cols)
+                           curs_x = cols-1;
+                   }
+
                    fix_cpos;
                    check_selection (old_cpos, cpos);
                }
@@ -756,7 +901,7 @@ void term_out(void) {
          case TOPLEVEL:
          /* Only graphic characters get this far, ctrls are stripped above */
            if (wrapnext) {
-               cpos[1] = ATTR_WRAPPED;
+               cpos[1] |= ATTR_WRAPPED;
                if (curs_y == marg_b)
                    scroll (marg_t, marg_b, 1, TRUE);
                else if (curs_y < rows-1)
@@ -867,7 +1012,6 @@ void term_out(void) {
              case 'E':                /* exactly equivalent to CR-LF */
                compatibility(VT100);
                curs_x = 0;
-               wrapnext = FALSE;
                if (curs_y == marg_b)
                    scroll (marg_t, marg_b, 1, TRUE);
                else if (curs_y < rows-1)
@@ -888,7 +1032,7 @@ void term_out(void) {
                break;
              case 'Z':                /* terminal type query */
                compatibility(VT100);
-               ldisc->send ("\033[?6c", 5);
+               ldisc->send (id_string, strlen(id_string));
                break;
              case 'c':                /* restore power-on settings */
                compatibility(VT100);
@@ -1031,19 +1175,15 @@ void term_out(void) {
              case 'c':                /* terminal type query */
                compatibility(VT100);
                /* This is the response for a VT102 */
-               ldisc->send ("\033[?6c", 5);
+               ldisc->send (id_string, strlen(id_string));
                break;
              case 'n':                /* cursor position query */
                if (esc_args[0] == 6) {
-                   /* Wonder of wonders ANSI.SYS has this!! */
                    char buf[32];
                    sprintf (buf, "\033[%d;%dR", curs_y + 1, curs_x + 1);
                    ldisc->send (buf, strlen(buf));
                }
                else if (esc_args[0] == 5) {
-                   /* Are we working ... well I suppose so :-) */
-                   /* But ANSI.SYS doesn't say it's working :-) :-) */
-                   compatibility(VT100);
                    ldisc->send ("\033[0n", 4);
                }
                break;
@@ -1190,7 +1330,10 @@ void term_out(void) {
                        }
                    }
                    if (use_bce) 
-                      erase_char = (' '|(curr_attr&(ATTR_FGMASK|ATTR_BGMASK)));
+                      erase_char = 
+                           (' '|
+                             (curr_attr&(ATTR_FGMASK|ATTR_BGMASK|ATTR_BLINK))
+                           );
                }
                break;
              case 's':                /* save cursor */
@@ -1209,11 +1352,7 @@ void term_out(void) {
                 */
                compatibility(VT340TEXT);
                if (esc_nargs<=1 && (esc_args[0]<1 || esc_args[0]>=24)) {
-                   unsigned int newrows = def(esc_args[0], 24);
-                   /* Hack: prevent big-resize DoS attack. */
-                   if (newrows > max(512, cfg.height))
-                       newrows = max(512, cfg.height);
-                   request_resize (cols, newrows, 0);
+                   request_resize (cols, def(esc_args[0], 24), 0);
                    deselect();
                }
                break;
@@ -1224,12 +1363,8 @@ void term_out(void) {
                 * reasonable range (24..49 AIUI) with no default specified.
                 */
                compatibility(VT420);
-               if (esc_nargs==1 && esc_args[0]>=24) {
-                   unsigned int newrows = def(esc_args[0], cfg.height);
-                   /* Hack: prevent big-resize DoS attack. */
-                   if (newrows > max(512, cfg.height))
-                       newrows = max(512, cfg.height);
-                   request_resize (cols, newrows, 0);
+               if (esc_nargs==1 && esc_args[0]>0) {
+                   request_resize (cols, def(esc_args[0], cfg.height), 0);
                    deselect();
                }
                break;
@@ -1240,17 +1375,13 @@ void term_out(void) {
                 */
                compatibility(VT340TEXT);
                if (esc_nargs<=1) {
-                   unsigned int newcols = def(esc_args[0], cfg.width);
-                   /* Hack: prevent big-resize DoS attack. */
-                   if (newcols > max(512, cfg.width))
-                       newcols = max(512, cfg.width);
-                   request_resize (newcols, rows, 0);
+                   request_resize (def(esc_args[0], cfg.width), rows, 0);
                    deselect();
                }
                break;
              case 'X':                /* write N spaces w/o moving cursor */
                /* XXX VTTEST says this is vt220, vt510 manual says vt100 */
-               compatibility(VT100);
+               compatibility(ANSIMIN);
                {
                    int n = def(esc_args[0], 1);
                    unsigned long *p = cpos;
@@ -1281,6 +1412,10 @@ void term_out(void) {
                if (use_bce)
                    erase_char = (' '|(curr_attr&(ATTR_FGMASK|ATTR_BGMASK)));
                break;
+             case ANSI('E','='):
+               compatibility(OTHER);
+               blink_is_real = (esc_args[0]>=1);
+               break;
              case ANSI('p','"'):
                /* Allow the host to make this emulator a 'perfect' VT102.
                 * This first appeared in the VT220, but we do need to get 
@@ -1419,14 +1554,31 @@ void term_out(void) {
            }
            break;
          case SEEN_ESCHASH:
-           if (c == '8') {
-               unsigned long *p = scrtop;
-               int n = rows * (cols+1);
-               while (n--)
-                   *p++ = ATTR_DEFAULT | 'E';
-               disptop = scrtop;
-               seen_disp_event = TRUE;
-               check_selection (scrtop, scrtop + rows * (cols+1));
+           {
+               unsigned long *p;
+               unsigned long nlattr;
+               int n;
+
+               switch (c) {
+               case '8':
+                   p = scrtop;
+                   n = rows * (cols+1);
+                   while (n--)
+                       *p++ = ATTR_DEFAULT | 'E';
+                   disptop = scrtop;
+                   seen_disp_event = TRUE;
+                   check_selection (scrtop, scrtop + rows * (cols+1));
+                   break;
+
+               case '3': nlattr = LATTR_TOP;     if(0) {
+               case '4': nlattr = LATTR_BOT;   } if(0) {
+               case '5': nlattr = LATTR_NORM;  } if(0) {
+               case '6': nlattr = LATTR_WIDE;  }
+
+                   p = scrtop + curs_y * (cols+1) + cols;
+                   *p &= ~LATTR_MODE;
+                   *p |=  nlattr;
+               }
            }
            termstate = TOPLEVEL;
            break;
@@ -1521,6 +1673,14 @@ void term_out(void) {
        if (selstate != NO_SELECTION)
            check_selection (cpos, cpos+1);
     }
+    inbuf_head = 0;
+
+    if (beep_overload)
+    {
+       if(!beep_count) beep_overload=0;
+    }
+    else if(beep_count && beep_count<5 && cfg.beep)
+       beep(beep_count/3);
 }
 
 /*
@@ -1561,12 +1721,22 @@ static void do_paint (Context ctx, int may_optimise){
 
     for (i=0; i<rows; i++) {
        int idx = i*(cols+1);
+       int lattr = (disptop[idx+cols] & LATTR_MODE);
        for (j=0; j<=cols; j++,idx++) {
            unsigned long *d = disptop+idx;
-           wanttext[idx] = ((*d ^ rv
+           wanttext[idx] = lattr | ((*d ^ rv
                              ^ (selstart <= d && d < selend ?
                                 ATTR_REVERSE : 0)) |
                             (i==our_curs_y && j==curs_x ? cursor : 0));
+
+           if (blink_is_real) {
+               if (has_focus && tblinker && (wanttext[idx]&ATTR_BLINK) )
+               {
+                   wanttext[idx] &= ATTR_MASK;
+                   wanttext[idx] += ' ';
+               }
+               wanttext[idx] &= ~ATTR_BLINK;
+           }
        }
     }
 
@@ -1579,6 +1749,7 @@ static void do_paint (Context ctx, int may_optimise){
 
     for (i=0; i<rows; i++) {
        int idx = i*(cols+1);
+       int lattr = (wanttext[idx+cols] & LATTR_MODE);
        start = -1;
        for (j=0; j<=cols; j++,idx++) {
            unsigned long t = wanttext[idx];
@@ -1587,7 +1758,7 @@ static void do_paint (Context ctx, int may_optimise){
                              (t & ATTR_MASK) == attr &&
                              j-start < sizeof(ch));
            if (start != -1 && !keep_going) {
-               do_text (ctx, start, i, ch, j-start, attr);
+               do_text (ctx, start, i, ch, j-start, attr, lattr);
                start = -1;
            }
            if (needs_update) {
@@ -1608,14 +1779,24 @@ static void do_paint (Context ctx, int may_optimise){
 
 void term_blink(int flg) {
 static long last_blink = 0;
+static long last_tblink = 0;
     long now, blink_diff;
 
+    now = GetTickCount();
+    blink_diff = now-last_tblink;
+
+    /* Make sure the text blinks no more than 2Hz */
+    if (blink_diff<0 || blink_diff>450)
+    {
+        last_tblink = now;
+       tblinker = !tblinker;
+    }
+
     if (flg) {
         blinker = 1;
-        last_blink = GetTickCount();
+        last_blink = now;
        return;
     } 
-    now = GetTickCount();
 
     blink_diff = now-last_blink;
 
@@ -1648,8 +1829,14 @@ void term_paint (Context ctx, int l, int t, int r, int b) {
     top = t / font_height;
     bottom = (b - 1) / font_height;
     for (i = top; i <= bottom && i < rows ; i++)
-      for (j = left; j <= right && j < cols ; j++)
-           disptext[i*(cols+1)+j] = ATTR_INVALID;
+    {
+       if ( (disptext[i*(cols+1)+cols]&LATTR_MODE) == LATTR_NORM)
+           for (j = left; j <= right && j < cols ; j++)
+               disptext[i*(cols+1)+j] = ATTR_INVALID;
+       else
+           for (j = left/2; j <= right/2+1 && j < cols ; j++)
+               disptext[i*(cols+1)+j] = ATTR_INVALID;
+    }
 
     /* This should happen soon enough, also for some reason it sometimes 
      * fails to actually do anything when re-sizing ... painting the wrong
@@ -1749,7 +1936,11 @@ void term_mouse (Mouse_Button b, Mouse_Action a, int x, int y) {
     }
     if (x>=cols) x = cols-1;
 
-    selpoint = disptop + y * (cols+1) + x;
+    selpoint = disptop + y * (cols+1);
+    if ((selpoint[cols]&LATTR_MODE) != LATTR_NORM)
+       selpoint += x/2;
+    else
+       selpoint += x;
 
     if (b == MB_SELECT && a == MA_CLICK) {
        deselect();
@@ -1825,6 +2016,11 @@ void term_mouse (Mouse_Button b, Mouse_Action a, int x, int y) {
        get_clip((void **) &data, &len);
        if (data) {
            char *p, *q;
+
+           if (paste_buffer) sfree(paste_buffer);
+           paste_pos = paste_hold = paste_len = 0;
+           paste_buffer = smalloc(len);
+
            p = q = data;
            while (p < data+len) {
                while (p < data+len &&
@@ -1838,17 +2034,25 @@ void term_mouse (Mouse_Button b, Mouse_Action a, int x, int y) {
                    for(i=0;i<p-q;i++)
                    {
                        c=xlat_kbd2tty(q[i]);
-                       ldisc->send(&c,1);
+                       paste_buffer[paste_len++] = c;
                    }
                }
 
                if (p <= data+len-sizeof(sel_nl) &&
                    !memcmp(p, sel_nl, sizeof(sel_nl))) {
-                   ldisc->send ("\r", 1);
+                   paste_buffer[paste_len++] = '\r';
                    p += sizeof(sel_nl);
                }
                q = p;
            }
+
+           /* Assume a small paste will be OK in one go. */
+           if (paste_len<256) {
+               ldisc->send (paste_buffer, paste_len);
+               if (paste_buffer) sfree(paste_buffer);
+               paste_buffer = 0;
+               paste_pos = paste_hold = paste_len = 0;
+           }
        }
        get_clip(NULL, NULL);
     }
@@ -1856,6 +2060,43 @@ void term_mouse (Mouse_Button b, Mouse_Action a, int x, int y) {
     term_update();
 }
 
+void term_nopaste() {
+    if(paste_len == 0) return;
+    sfree(paste_buffer);
+    paste_buffer = 0;
+    paste_len = 0;
+}
+
+void term_paste() {
+static long last_paste = 0;
+    long now, paste_diff;
+
+    if(paste_len == 0) return;
+
+    /* Don't wait forever to paste */
+    if(paste_hold) {
+       now = GetTickCount();
+       paste_diff = now-last_paste;
+       if (paste_diff>=0 && paste_diff<450)
+           return;
+    }
+    paste_hold = 0;
+
+    while(paste_pos<paste_len)
+    {
+       char c = paste_buffer[paste_pos++];
+       ldisc->send (&c, 1);
+
+       if (c =='\r') {
+           paste_hold = 1;
+           return;
+       }
+    }
+    sfree(paste_buffer);
+    paste_buffer = 0;
+    paste_len = 0;
+}
+
 static void deselect (void) {
     selstate = NO_SELECTION;
     selstart = selend = scrtop;
index 6ea558c..5d6675e 100644 (file)
--- a/win_res.h
+++ b/win_res.h
 #define IDC1_FUNCSTATIC 1007
 #define IDC1_FUNCTILDE  1008
 #define IDC1_FUNCLINUX  1009
-#define IDC1_KPSTATIC   1010
-#define IDC1_KPNORMAL   1011
-#define IDC1_KPAPPLIC   1012
-#define IDC1_KPNH       1013
-#define IDC1_CURSTATIC  1014
-#define IDC1_CURNORMAL  1015
-#define IDC1_CURAPPLIC  1016
-#define IDC1_ALTF4      1017
-#define IDC1_ALTSPACE   1018
-#define IDC1_LDISCTERM  1019
-#define IDC1_BLINKCUR   1020
-#define IDC1_BEEP       1021
+#define IDC1_FUNCXTERM  1010
+#define IDC1_KPSTATIC   1011
+#define IDC1_KPNORMAL   1012
+#define IDC1_KPAPPLIC   1013
+#define IDC1_KPNH       1014
+#define IDC1_CURSTATIC  1015
+#define IDC1_CURNORMAL  1016
+#define IDC1_CURAPPLIC  1017
+#define IDC1_ALTF4      1018
+#define IDC1_ALTSPACE   1019
+#define IDC1_LDISCTERM  1020
+#define IDC1_SCROLLKEY  1021
 
 #define IDC2_WRAPMODE   1001
 #define IDC2_DECOM      1002
 #define IDC2_SAVEEDIT   1010
 #define IDC2_FONTSTATIC 1011
 #define IDC2_CHOOSEFONT 1012
-#define IDC2_VTSTATIC   1013
-#define IDC2_VTXWINDOWS 1014
-#define IDC2_VTOEMANSI  1015
-#define IDC2_VTOEMONLY  1016
-#define IDC2_VTPOORMAN  1017
 #define IDC2_LFHASCR    1018
+#define IDC1_BLINKCUR   1020
+#define IDC1_BEEP       1021
+#define IDC2_SCROLLBAR  1022
+#define IDC2_LOCKSIZE   1023
+#define IDC2_BCE       1024
+#define IDC2_BLINKTEXT 1025
 
 #define IDC3_TTSTATIC   1001
 #define IDC3_TTEDIT     1002
 #define IDC6_KOI8WIN1251 1003
 #define IDC6_88592WIN1250 1004
 #define IDC6_CAPSLOCKCYR 1005
+#define IDC2_VTSTATIC   1013
+#define IDC2_VTXWINDOWS 1014
+#define IDC2_VTOEMANSI  1015
+#define IDC2_VTOEMONLY  1016
+#define IDC2_VTPOORMAN  1017
 
 #endif
index 49b429c..a9d0e60 100644 (file)
@@ -61,193 +61,254 @@ END
 IDD_PANEL0 DIALOG DISCARDABLE 6, 30, 168, 163
 STYLE WS_CHILD | WS_VISIBLE | NOT WS_BORDER
 FONT 8, "MS Sans Serif"
 BEGIN
-    LTEXT "Host &Name", IDC0_HOSTSTATIC, 3, 3, 122, 8
-    EDITTEXT IDC0_HOST, 3, 11, 122, 12, ES_AUTOHSCROLL
-    LTEXT "&Port", IDC0_PORTSTATIC, 131, 3, 34, 8
-    EDITTEXT IDC0_PORT, 131, 11, 34, 12
+    
+    LTEXT "Host &Name", IDC0_HOSTSTATIC, 3, 3, 119, 8
+    EDITTEXT IDC0_HOST,  3, 11, 119, 12, ES_AUTOHSCROLL
+    LTEXT "&Port", IDC0_PORTSTATIC, 129, 3, 35, 8
+    EDITTEXT IDC0_PORT,  129, 11, 35, 12
+    
+    
 #ifdef FWHACK
-    RTEXT "Protocol:", IDC0_PROTSTATIC, 3, 29, 42, 8
-    AUTORADIOBUTTON "&Raw", IDC0_PROTRAW, 51, 29, 33, 10, WS_GROUP
-    AUTORADIOBUTTON "&Telnet", IDC0_PROTTELNET, 86, 29, 33, 10
-    AUTORADIOBUTTON "SS&H/hack", IDC0_PROTSSH, 122, 29, 43, 10
+    RTEXT "Protocol:", IDC0_PROTSTATIC, 3, 27, 35, 8
+    AUTORADIOBUTTON "&Raw", IDC0_PROTRAW, 45, 27, 35, 8, WS_GROUP
+    AUTORADIOBUTTON "&Telnet", IDC0_PROTTELNET, 87, 27, 35, 8
+    AUTORADIOBUTTON "SS&H/hack", IDC0_PROTSSH, 129, 27, 35, 8
 #else
-    RTEXT "Protocol:", IDC0_PROTSTATIC, 3, 29, 52, 8
-    AUTORADIOBUTTON "&Raw", IDC0_PROTRAW, 61, 29, 33, 10, WS_GROUP
-    AUTORADIOBUTTON "&Telnet", IDC0_PROTTELNET, 96, 29, 33, 10
+    RTEXT "Protocol:", IDC0_PROTSTATIC, 3, 27, 35, 8
+    AUTORADIOBUTTON "&Raw", IDC0_PROTRAW, 45, 27, 35, 8, WS_GROUP
+    AUTORADIOBUTTON "&Telnet", IDC0_PROTTELNET, 87, 27, 35, 8
 #ifndef NO_SSH
-    AUTORADIOBUTTON "SS&H", IDC0_PROTSSH, 132, 29, 33, 10
+    AUTORADIOBUTTON "SS&H", IDC0_PROTSSH, 129, 27, 35, 8
 #endif
 #endif
-    LTEXT "Stor&ed Sessions", IDC0_SESSSTATIC, 3, 40, 122, 8
-    EDITTEXT IDC0_SESSEDIT, 3, 48, 122, 12, ES_AUTOHSCROLL
-    LISTBOX IDC0_SESSLIST, 3, 63, 122, 81,
+    
+    
+    LTEXT "Stor&ed Sessions", IDC0_SESSSTATIC, 3, 37, 162, 8
+    
+    EDITTEXT IDC0_SESSEDIT, 3, 45, 119, 12, ES_AUTOHSCROLL
+    
+    
+    LISTBOX IDC0_SESSLIST, 3, 59, 119, 71,
         LBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
-    PUSHBUTTON "&Load", IDC0_SESSLOAD, 131, 63, 34, 14
-    PUSHBUTTON "&Save", IDC0_SESSSAVE, 131, 80, 34, 14
-    PUSHBUTTON "&Delete", IDC0_SESSDEL, 131, 97, 34, 14
-    AUTOCHECKBOX "Close &Window on Exit", IDC0_CLOSEEXIT, 3, 147, 91, 10
-    AUTOCHECKBOX "Warn on C&lose", IDC0_CLOSEWARN, 96, 147, 69, 10
+    
+    PUSHBUTTON "&Load",  IDC0_SESSLOAD, 129, 59,  35, 14
+    PUSHBUTTON "&Save",  IDC0_SESSSAVE, 129, 76,  35, 14
+    PUSHBUTTON "&Delete", IDC0_SESSDEL, 129, 93,  35, 14
+    
+
+    
+    AUTOCHECKBOX "Close &Window on Exit", IDC0_CLOSEEXIT, 3, 130, 162, 8
+    AUTOCHECKBOX "Warn on C&lose", IDC0_CLOSEWARN, 3, 140, 162, 8
 END
 
 IDD_PANEL1 DIALOG DISCARDABLE 6, 30, 168, 163
 STYLE WS_CHILD | WS_VISIBLE | NOT WS_BORDER
 FONT 8, "MS Sans Serif"
+  
 BEGIN
     LTEXT "Action of Backspace:", IDC1_DELSTATIC, 3, 3, 162, 8
-    AUTORADIOBUTTON "Control-&H", IDC1_DEL008, 3, 12, 50, 10, WS_GROUP
-    AUTORADIOBUTTON "Control-&? (127)", IDC1_DEL127, 62, 12, 100, 10
+    AUTORADIOBUTTON "Control-&H", IDC1_DEL008, 3, 13, 49, 8, WS_GROUP
+    AUTORADIOBUTTON "Control-&? (127)", IDC1_DEL127, 59, 13, 105, 8
+    
     LTEXT "Action of Home and End:", IDC1_HOMESTATIC, 3, 25, 162, 8
-    AUTORADIOBUTTON "&Standard",
-       IDC1_HOMETILDE, 3, 34, 50, 10, WS_GROUP
-    AUTORADIOBUTTON "&rxvt",
-       IDC1_HOMERXVT, 62, 34, 50, 10
-    LTEXT "Action of F1 through F5:", IDC1_FUNCSTATIC, 3, 47, 162, 8
-    AUTORADIOBUTTON "S&tandard",
-       IDC1_FUNCTILDE, 3, 56, 50, 10, WS_GROUP
-    AUTORADIOBUTTON "&Linux console",
-       IDC1_FUNCLINUX, 62, 56, 100, 10
+    AUTORADIOBUTTON "&Standard", IDC1_HOMETILDE, 3, 35, 49, 8, WS_GROUP
+    AUTORADIOBUTTON "&rxvt", IDC1_HOMERXVT, 59, 35, 49, 8
+    
+    LTEXT "Function key and keypad layout:", IDC1_FUNCSTATIC, 3, 47, 162, 8
+    AUTORADIOBUTTON "&VT400", IDC1_FUNCTILDE, 3, 57, 49, 8, WS_GROUP
+    AUTORADIOBUTTON "&Linux", IDC1_FUNCLINUX, 59, 57, 49, 8
+    AUTORADIOBUTTON "&Xterm R6", IDC1_FUNCXTERM, 115, 57, 49, 8
+    
     LTEXT "Initial state of cursor keys:", IDC1_CURSTATIC, 3, 69, 162, 8
-    AUTORADIOBUTTON "&Normal",
-       IDC1_CURNORMAL, 3, 78, 50, 10, WS_GROUP
-    AUTORADIOBUTTON "A&pplication",
-       IDC1_CURAPPLIC, 62, 78, 50, 10
+    AUTORADIOBUTTON "&Normal", IDC1_CURNORMAL, 3, 79, 49, 8, WS_GROUP
+    AUTORADIOBUTTON "A&pplication", IDC1_CURAPPLIC, 59, 79, 49, 8
+    
     LTEXT "Initial state of numeric keypad:", IDC1_KPSTATIC, 3, 91, 162, 8
-    AUTORADIOBUTTON "Nor&mal",
-       IDC1_KPNORMAL, 3, 100, 50, 10, WS_GROUP
-    AUTORADIOBUTTON "Appl&ication",
-       IDC1_KPAPPLIC, 62, 100, 50, 10
-    AUTORADIOBUTTON "N&etHack",
-       IDC1_KPNH, 121, 100, 50, 10
-    AUTOCHECKBOX "ALT-F&4 is special (closes window)",
-        IDC1_ALTF4, 3, 113, 162, 10
-    AUTOCHECKBOX "ALT-Space is special (S&ystem menu)",
-        IDC1_ALTSPACE, 3, 123, 162, 10
-    AUTOCHECKBOX "&Use local terminal line discipline",
-        IDC1_LDISCTERM, 3, 133, 162, 10
-    AUTOCHECKBOX "&Blinking cursor",
-        IDC1_BLINKCUR, 3, 143, 162, 10
-    AUTOCHECKBOX "Bee&p enabled",
-        IDC1_BEEP, 3, 153, 162, 10
+    AUTORADIOBUTTON "Nor&mal", IDC1_KPNORMAL, 3, 101, 49, 8, WS_GROUP
+    AUTORADIOBUTTON "Appl&ication", IDC1_KPAPPLIC, 59, 101, 49, 8
+    AUTORADIOBUTTON "N&etHack", IDC1_KPNH, 115, 101, 49, 8
+    
+    AUTOCHECKBOX "ALT-F&4 is special (closes window)", IDC1_ALTF4, 3, 113, 162, 8
+    AUTOCHECKBOX "ALT-Space is special (S&ystem menu)", IDC1_ALTSPACE, 3, 123, 162, 8
+    AUTOCHECKBOX "&Use local terminal line discipline", IDC1_LDISCTERM, 3, 133, 162, 8
+    AUTOCHECKBOX "Reset scrollback on &keypress", IDC1_SCROLLKEY, 3, 143, 162, 8
 END
 
 IDD_PANEL2 DIALOG DISCARDABLE 6, 30, 168, 163
 STYLE WS_CHILD | WS_VISIBLE | NOT WS_BORDER
 FONT 8, "MS Sans Serif"
+  
 BEGIN
-    AUTOCHECKBOX "Auto &wrap mode initially on", IDC2_WRAPMODE, 3, 3, 162, 10
-    AUTOCHECKBOX "&DEC Origin Mode initially on", IDC2_DECOM, 3, 13, 162, 10
-    AUTOCHECKBOX "Avoid ever using &icon title", IDC2_WINNAME, 3, 23, 162, 10
-    AUTOCHECKBOX "Implicit CR in every &LF", IDC2_LFHASCR, 3, 33, 162, 10
-    LTEXT "Terminal screen dimensions:", IDC2_DIMSTATIC, 3, 48, 162, 8
-    RTEXT "&Rows", IDC2_ROWSSTATIC, 10, 59, 32, 8
-    EDITTEXT IDC2_ROWSEDIT, 50, 57, 30, 12
-    RTEXT "Colu&mns", IDC2_COLSSTATIC, 95, 59, 32, 8
-    EDITTEXT IDC2_COLSEDIT, 135, 57, 30, 12
-    RTEXT "&Saved lines of scrollback", IDC2_SAVESTATIC, 20, 74, 107, 8
-    EDITTEXT IDC2_SAVEEDIT, 135, 72, 30, 12
-    LTEXT "Font:", IDC2_FONTSTATIC, 3, 93, 99, 8
-    PUSHBUTTON "C&hange...", IDC2_CHOOSEFONT, 105, 90, 60, 14
-    LTEXT "Handling of VT100 line drawing characters:",IDC2_VTSTATIC, 3, 111, 162, 8
-    AUTORADIOBUTTON "Font has &XWindows encoding",
-       IDC2_VTXWINDOWS, 3, 120, 162, 10, WS_GROUP
-    AUTORADIOBUTTON "Use font in &both ANSI and OEM modes",
-       IDC2_VTOEMANSI, 3, 130, 162, 10
-    AUTORADIOBUTTON "Use font in O&EM mode only",
-       IDC2_VTOEMONLY, 3, 140, 162, 10
-    AUTORADIOBUTTON "&Poor man's line drawing (""+"", ""-"" and ""|"")",
-       IDC2_VTPOORMAN, 3, 150, 162, 10
+    
+    LTEXT "Terminal screen dimensions:", IDC2_DIMSTATIC, 3, 3, 162, 8
+    
+    RTEXT "&Rows", IDC2_ROWSSTATIC,  3, 15, 35, 8
+    EDITTEXT IDC2_ROWSEDIT, 45, 13, 35, 12
+    RTEXT "Colu&mns", IDC2_COLSSTATIC,  87, 15, 35, 8 
+    EDITTEXT IDC2_COLSEDIT, 129, 13, 35, 12
+    
+    RTEXT "&Saved lines of scrollback", IDC2_SAVESTATIC,  3, 30, 119, 8
+    EDITTEXT IDC2_SAVEEDIT, 129, 28, 35, 12
+    
+    
+    RTEXT "Font:", IDC2_FONTSTATIC,  3, 48, 105, 8
+    
+    PUSHBUTTON "C&hange...", IDC2_CHOOSEFONT, 115, 45, 49, 14
+    
+    
+    AUTOCHECKBOX "Auto &wrap mode initially on", IDC2_WRAPMODE, 3, 62, 162, 8
+    AUTOCHECKBOX "&DEC Origin Mode initially on", IDC2_DECOM, 3, 72, 162, 8
+    AUTOCHECKBOX "Avoid ever using &icon title", IDC2_WINNAME, 3, 82, 162, 8
+    AUTOCHECKBOX "Implicit CR in every &LF", IDC2_LFHASCR, 3, 92, 162, 8
+    AUTOCHECKBOX "&Blinking cursor", IDC1_BLINKCUR, 3, 102, 162, 8
+    AUTOCHECKBOX "Bee&p enabled", IDC1_BEEP, 3, 112, 162, 8
+    AUTOCHECKBOX "Displa&y scrollbar", IDC2_SCROLLBAR, 3, 122, 162, 8
+    AUTOCHECKBOX "Loc&k Window size", IDC2_LOCKSIZE, 3, 132, 162, 8
+    AUTOCHECKBOX "Use Backgroud colour erase", IDC2_BCE, 3, 142, 162, 8
+    AUTOCHECKBOX "Enable blinking text", IDC2_BLINKTEXT, 3, 152, 162, 8
+    
+    
+    
 END
 
 IDD_PANEL3 DIALOG DISCARDABLE 6, 30, 168, 163
 STYLE WS_CHILD | WS_VISIBLE | NOT WS_BORDER
 FONT 8, "MS Sans Serif"
+  
 BEGIN
-    LTEXT "Terminal-&type string", IDC3_TTSTATIC, 3, 5, 90, 8
-    EDITTEXT IDC3_TTEDIT, 96, 3, 69, 12, ES_AUTOHSCROLL
-    LTEXT "Terminal-&speed string", IDC3_TSSTATIC, 3, 20, 90, 8
-    EDITTEXT IDC3_TSEDIT, 96, 18, 69, 12, ES_AUTOHSCROLL
-    LTEXT "Auto-login &username", IDC3_LOGSTATIC, 3, 35, 90, 8
-    EDITTEXT IDC3_LOGEDIT, 96, 33, 69, 12, ES_AUTOHSCROLL
+    
+    LTEXT "Terminal-&type string", IDC3_TTSTATIC,  3, 5, 77, 8
+    EDITTEXT IDC3_TTEDIT, 87, 3, 77, 12, ES_AUTOHSCROLL
+    
+    LTEXT "Terminal-&speed string", IDC3_TSSTATIC,  3, 19, 77, 8
+    EDITTEXT IDC3_TSEDIT, 87, 17, 77, 12, ES_AUTOHSCROLL
+    
+    LTEXT "Auto-login &username", IDC3_LOGSTATIC,  3, 33, 77, 8
+    EDITTEXT IDC3_LOGEDIT, 87, 31, 77, 12, ES_AUTOHSCROLL
+    
+    
+    
     LTEXT "Environment variables:", IDC3_ENVSTATIC, 3, 53, 162, 8
-    LTEXT "&Variable", IDC3_VARSTATIC, 3, 70, 29, 8
-    EDITTEXT IDC3_VAREDIT, 35, 68, 35, 12, ES_AUTOHSCROLL
-    LTEXT "Va&lue", IDC3_VALSTATIC, 76, 70, 19, 8
-    EDITTEXT IDC3_VALEDIT, 98, 68, 67, 12, ES_AUTOHSCROLL
-    LISTBOX IDC3_ENVLIST, 3, 85, 122, 55,
+    
+    LTEXT "&Variable", IDC3_VARSTATIC,  3, 65, 26, 8
+    EDITTEXT IDC3_VAREDIT, 36, 63, 26, 12, ES_AUTOHSCROLL
+    LTEXT "Va&lue", IDC3_VALSTATIC,  70, 65, 26, 8
+    EDITTEXT IDC3_VALEDIT, 104, 63, 59, 12, ES_AUTOHSCROLL
+    
+    
+    
+    LISTBOX IDC3_ENVLIST, 3, 81, 119, 55,
        LBS_HASSTRINGS | LBS_USETABSTOPS | WS_VSCROLL | WS_TABSTOP
-    PUSHBUTTON "A&dd", IDC3_ENVADD, 131, 85, 34, 14
-    PUSHBUTTON "&Remove", IDC3_ENVREMOVE, 131, 102, 34, 14
-    LTEXT "ENVIRON interpretation:", IDC3_EMSTATIC, 3, 147, 90, 8
-    AUTORADIOBUTTON "&BSD", IDC3_EMBSD, 96, 147, 33, 10, WS_GROUP
-    AUTORADIOBUTTON "R&FC", IDC3_EMRFC, 132, 147, 33, 10
+    
+    PUSHBUTTON "A&dd", IDC3_ENVADD, 129, 81,  35, 14
+    PUSHBUTTON "&Remove", IDC3_ENVREMOVE, 129, 98,  35, 14
+    
+
+    
+    LTEXT "ENVIRON interpretation:", IDC3_EMSTATIC, 3, 136, 77, 8
+    AUTORADIOBUTTON "&BSD", IDC3_EMBSD, 87, 136, 35, 8, WS_GROUP
+    AUTORADIOBUTTON "R&FC", IDC3_EMRFC, 129, 136, 35, 8
+    
 END
 
 IDD_PANEL35 DIALOG DISCARDABLE 6, 30, 168, 163
 STYLE WS_CHILD | WS_VISIBLE | NOT WS_BORDER
 FONT 8, "MS Sans Serif"
+  
 BEGIN
-    LTEXT "Terminal-&type string", IDC3_TTSTATIC, 3, 5, 90, 8
-    EDITTEXT IDC3_TTEDIT, 96, 3, 69, 12, ES_AUTOHSCROLL
-    AUTOCHECKBOX "Don't allocate a &pseudo-terminal", IDC3_NOPTY,
-       3, 19, 162, 10
-    LTEXT "Auto-login &username", IDC3_LOGSTATIC, 3, 35, 90, 8
-    EDITTEXT IDC3_LOGEDIT, 96, 33, 69, 12, ES_AUTOHSCROLL
-    LTEXT "Cipher:", IDC3_CIPHERSTATIC, 3, 50, 40, 8
-    AUTORADIOBUTTON "&3DES", IDC3_CIPHER3DES, 46, 50, 35, 10, WS_GROUP
-    AUTORADIOBUTTON "&Blowfish", IDC3_CIPHERBLOWF, 84, 50, 40, 10
-    AUTORADIOBUTTON "&DES", IDC3_CIPHERDES, 127, 50, 30, 10
-    AUTOCHECKBOX "Attempt TIS authentication", IDC3_AUTHTIS, 3, 60, 162, 10
+    
+    LTEXT "Terminal-&type string", IDC3_TTSTATIC,  3, 5, 77, 8
+    EDITTEXT IDC3_TTEDIT, 87, 3, 77, 12, ES_AUTOHSCROLL
+    
+    
+    AUTOCHECKBOX "Don't allocate a &pseudo-terminal", IDC3_NOPTY, 3, 19, 162, 8
+    
+    LTEXT "Auto-login &username", IDC3_LOGSTATIC,  3, 31, 77, 8
+    EDITTEXT IDC3_LOGEDIT, 87, 29, 77, 12, ES_AUTOHSCROLL
+    
+    
+    LTEXT "Cipher:", IDC3_CIPHERSTATIC, 3, 45, 35, 8
+    AUTORADIOBUTTON "&3DES", IDC3_CIPHER3DES, 45, 45, 35, 8, WS_GROUP
+    AUTORADIOBUTTON "&Blowfish", IDC3_CIPHERBLOWF, 87, 45, 35, 8
+    AUTORADIOBUTTON "&DES", IDC3_CIPHERDES, 129, 45, 35, 8
+    
+    
+    AUTOCHECKBOX "Attempt TIS authentication", IDC3_AUTHTIS, 3, 55, 162, 8
 END
 
 IDD_PANEL4 DIALOG DISCARDABLE 6, 30, 168, 163
 STYLE WS_CHILD | WS_VISIBLE | NOT WS_BORDER
 FONT 8, "MS Sans Serif"
 BEGIN
+    
     LTEXT "Action of mouse buttons:", IDC4_MBSTATIC, 3, 3, 162, 8
     AUTORADIOBUTTON "&Windows (Right pastes, Middle extends)",
-       IDC4_MBWINDOWS, 3, 12, 162, 10, WS_GROUP
+       IDC4_MBWINDOWS, 3, 13, 162, 8, WS_GROUP
     AUTORADIOBUTTON "&xterm (Right extends, Middle pastes)",
-       IDC4_MBXTERM, 3, 22, 162, 10
-    LTEXT "Character classes:", IDC4_CCSTATIC, 3, 35, 162, 8
-    LISTBOX IDC4_CCLIST, 3, 45, 162, 96,
+       IDC4_MBXTERM, 3, 23, 162, 8
+    
+    LTEXT "Character classes:", IDC4_CCSTATIC, 3, 37, 162, 8
+    
+    LISTBOX IDC4_CCLIST, 3, 47, 162, 96,
        LBS_HASSTRINGS | WS_VSCROLL | LBS_USETABSTOPS | LBS_MULTIPLESEL | WS_TABSTOP
-    PUSHBUTTON "&Set", IDC4_CCSET, 33, 145, 34, 14
-    LTEXT "&to class", IDC4_CCSTATIC2, 73, 148, 26, 8
-    EDITTEXT IDC4_CCEDIT, 105, 146, 36, 12
+    
+    PUSHBUTTON "&Set", IDC4_CCSET, 33, 147, 34, 14
+    LTEXT "&to class", IDC4_CCSTATIC2, 73, 147+3, 26, 8
+    EDITTEXT IDC4_CCEDIT, 105, 147+1, 36, 12
+    
 END
 
 IDD_PANEL5 DIALOG DISCARDABLE 6, 30, 168, 163
 STYLE WS_CHILD | WS_VISIBLE | NOT WS_BORDER
 FONT 8, "MS Sans Serif"
 BEGIN
-    AUTOCHECKBOX "&Bolded text is a different colour", IDC5_BOLDCOLOUR,3, 10, 162, 10
-    AUTOCHECKBOX "Attempt to use &logical palettes", IDC5_PALETTE, 3, 25, 162, 10
-    LTEXT "C&olours:", IDC5_STATIC, 3, 40, 162, 8
-    LISTBOX IDC5_LIST, 3, 50, 100, 110,
+    
+    AUTOCHECKBOX "&Bolded text is a different colour", IDC5_BOLDCOLOUR, 3, 3, 162, 8
+    
+    AUTOCHECKBOX "Attempt to use &logical palettes", IDC5_PALETTE, 3, 19, 162, 8
+    
+    LTEXT "C&olours:", IDC5_STATIC, 3, 35, 162, 8
+
+    LISTBOX IDC5_LIST, 3, 45, 100, 110,
         LBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
-    LTEXT "Red:", IDC5_RSTATIC, 109, 50, 27, 8
-    RTEXT "", IDC5_RVALUE, 138, 50, 27, 8
-    LTEXT "Green:", IDC5_GSTATIC, 109, 58, 27, 8
-    RTEXT "", IDC5_GVALUE, 138, 58, 27, 8
-    LTEXT "Blue:", IDC5_BSTATIC, 109, 66, 27, 8
-    RTEXT "", IDC5_BVALUE, 138, 66, 27, 8
-    PUSHBUTTON "C&hange...", IDC5_CHANGE, 109, 140, 56, 14
+    LTEXT "Red:", IDC5_RSTATIC, 109, 45, 27, 8
+    RTEXT "", IDC5_RVALUE, 138, 45, 27, 8
+    LTEXT "Green:", IDC5_GSTATIC, 109, 45+8, 27, 8
+    RTEXT "", IDC5_GVALUE, 138, 45+8, 27, 8
+    LTEXT "Blue:", IDC5_BSTATIC, 109, 45+16, 27, 8
+    RTEXT "", IDC5_BVALUE, 138, 45+16, 27, 8
+    
+    PUSHBUTTON "C&hange...", IDC5_CHANGE, 109, 135, 56, 14
+    
 END
 
 IDD_PANEL6 DIALOG DISCARDABLE  6, 30, 168, 163
 STYLE WS_CHILD | WS_VISIBLE
 FONT 8, "MS Sans Serif"
 BEGIN
-    LTEXT "Character set translation:", IDC6_XLATSTATIC, 3, 3, 162, 8
-    AUTORADIOBUTTON "&None",
-       IDC6_NOXLAT, 3, 12, 162, 10, WS_GROUP
-    AUTORADIOBUTTON "&KOI8 / Win-1251",
-       IDC6_KOI8WIN1251, 3, 22, 162, 10
-    AUTORADIOBUTTON "&ISO-8859-2 / Win-1250",
-       IDC6_88592WIN1250, 3, 32, 162, 10
-    AUTOCHECKBOX "CA&PS LOCK acts as cyrillic switch",
-        IDC6_CAPSLOCKCYR, 3, 46, 162, 10
+    
+    LTEXT "Handling of VT100 line drawing characters:",IDC2_VTSTATIC, 3, 3, 162, 8
+    AUTORADIOBUTTON "Font has &XWindows encoding",
+       IDC2_VTXWINDOWS, 3, 13, 162, 8, WS_GROUP
+    AUTORADIOBUTTON "Use font in &both ANSI and OEM modes",
+       IDC2_VTOEMANSI, 3, 23, 162, 8
+    AUTORADIOBUTTON "Use font in O&EM mode only",
+       IDC2_VTOEMONLY, 3, 33, 162, 8
+    AUTORADIOBUTTON "&Poor man's line drawing (""+"", ""-"" and ""|"")",
+       IDC2_VTPOORMAN, 3, 43, 162, 8
+    
+    LTEXT "Character set translation:", IDC6_XLATSTATIC, 3, 59, 162, 8
+    AUTORADIOBUTTON "&None", IDC6_NOXLAT, 3, 69, 162, 8, WS_GROUP
+    AUTORADIOBUTTON "&KOI8 / Win-1251", IDC6_KOI8WIN1251, 3, 79, 162, 8
+    AUTORADIOBUTTON "&ISO-8859-2 / Win-1250", IDC6_88592WIN1250, 3, 89, 162, 8
+    
+    AUTOCHECKBOX "CA&PS LOCK acts as cyrillic switch", IDC6_CAPSLOCKCYR, 3, 105, 162, 8
+    
 END
 
 IDD_LOGBOX DIALOG DISCARDABLE 100, 20, 160, 119
index c9c00bd..23bf2cb 100644 (file)
--- a/windlg.c
+++ b/windlg.c
@@ -155,7 +155,7 @@ static void save_settings (char *section, int do_host) {
     wppi (sesskey, "RFCEnviron", cfg.rfc_environ);
     wppi (sesskey, "BackspaceIsDelete", cfg.bksp_is_delete);
     wppi (sesskey, "RXVTHomeEnd", cfg.rxvt_homeend);
-    wppi (sesskey, "LinuxFunctionKeys", cfg.linux_funkeys);
+    wppi (sesskey, "LinuxFunctionKeys", cfg.funky_type);
     wppi (sesskey, "ApplicationCursorKeys", cfg.app_cursor);
     wppi (sesskey, "ApplicationKeypad", cfg.app_keypad);
     wppi (sesskey, "NetHackKeypad", cfg.nethack_keypad);
@@ -200,6 +200,11 @@ static void save_settings (char *section, int do_host) {
     wppi (sesskey, "KoiWinXlat", cfg.xlat_enablekoiwin);
     wppi (sesskey, "88592Xlat", cfg.xlat_88592w1250);
     wppi (sesskey, "CapsLockCyr", cfg.xlat_capslockcyr);
+    wppi (sesskey, "ScrollBar", cfg.scrollbar);
+    wppi (sesskey, "ScrollOnKey", cfg.scroll_on_key);
+    wppi (sesskey, "LockSize", cfg.locksize);
+    wppi (sesskey, "BCE", cfg.bce);
+    wppi (sesskey, "BlinkText", cfg.blinktext);
 
     RegCloseKey(sesskey);
 }
@@ -291,7 +296,7 @@ static void load_settings (char *section, int do_host) {
     gppi (sesskey, "RFCEnviron", 0, &cfg.rfc_environ);
     gppi (sesskey, "BackspaceIsDelete", 1, &cfg.bksp_is_delete);
     gppi (sesskey, "RXVTHomeEnd", 0, &cfg.rxvt_homeend);
-    gppi (sesskey, "LinuxFunctionKeys", 0, &cfg.linux_funkeys);
+    gppi (sesskey, "LinuxFunctionKeys", 0, &cfg.funky_type);
     gppi (sesskey, "ApplicationCursorKeys", 0, &cfg.app_cursor);
     gppi (sesskey, "ApplicationKeypad", 0, &cfg.app_keypad);
     gppi (sesskey, "NetHackKeypad", 0, &cfg.nethack_keypad);
@@ -359,10 +364,33 @@ static void load_settings (char *section, int do_host) {
     gppi (sesskey, "KoiWinXlat", 0, &cfg.xlat_enablekoiwin);
     gppi (sesskey, "88592Xlat", 0, &cfg.xlat_88592w1250);
     gppi (sesskey, "CapsLockCyr", 0, &cfg.xlat_capslockcyr);
+    gppi (sesskey, "ScrollBar", 1, &cfg.scrollbar);
+    gppi (sesskey, "ScrollOnKey", 0, &cfg.scroll_on_key);
+    gppi (sesskey, "LockSize", 0, &cfg.locksize);
+    gppi (sesskey, "BCE", 0, &cfg.bce);
+    gppi (sesskey, "BlinkText", 0, &cfg.blinktext);
 
     RegCloseKey(sesskey);
 }
 
+static void force_normal(HWND hwnd)
+{
+static int recurse = 0;
+
+    WINDOWPLACEMENT wp;
+
+    if(recurse) return;
+    recurse = 1;
+
+    wp.length = sizeof(wp);
+    if (GetWindowPlacement(hwnd, &wp))
+    {
+       wp.showCmd = SW_SHOWNORMAL;
+       SetWindowPlacement(hwnd, &wp);
+    }
+    recurse = 0;
+}
+
 static void MyGetDlgItemInt (HWND hwnd, int id, int *result) {
     BOOL ok;
     int n;
@@ -642,8 +670,11 @@ static int CALLBACK KeyboardProc (HWND hwnd, UINT msg,
                          cfg.bksp_is_delete ? IDC1_DEL127 : IDC1_DEL008);
        CheckRadioButton (hwnd, IDC1_HOMETILDE, IDC1_HOMERXVT,
                          cfg.rxvt_homeend ? IDC1_HOMERXVT : IDC1_HOMETILDE);
-       CheckRadioButton (hwnd, IDC1_FUNCTILDE, IDC1_FUNCLINUX,
-                         cfg.linux_funkeys ? IDC1_FUNCLINUX : IDC1_FUNCTILDE);
+       CheckRadioButton (hwnd, IDC1_FUNCTILDE, IDC1_FUNCXTERM,
+                         cfg.funky_type ? 
+                         (cfg.funky_type==2 ? IDC1_FUNCXTERM 
+                          : IDC1_FUNCLINUX )
+                         : IDC1_FUNCTILDE);
        CheckRadioButton (hwnd, IDC1_CURNORMAL, IDC1_CURAPPLIC,
                          cfg.app_cursor ? IDC1_CURAPPLIC : IDC1_CURNORMAL);
        CheckRadioButton (hwnd, IDC1_KPNORMAL, IDC1_KPNH,
@@ -652,8 +683,7 @@ static int CALLBACK KeyboardProc (HWND hwnd, UINT msg,
        CheckDlgButton (hwnd, IDC1_ALTF4, cfg.alt_f4);
        CheckDlgButton (hwnd, IDC1_ALTSPACE, cfg.alt_space);
        CheckDlgButton (hwnd, IDC1_LDISCTERM, cfg.ldisc_term);
-       CheckDlgButton (hwnd, IDC1_BLINKCUR, cfg.blink_cur);
-        CheckDlgButton (hwnd, IDC1_BEEP, cfg.beep);
+       CheckDlgButton (hwnd, IDC1_SCROLLKEY, cfg.scroll_on_key);
        break;
       case WM_COMMAND:
        if (HIWORD(wParam) == BN_CLICKED ||
@@ -667,9 +697,12 @@ static int CALLBACK KeyboardProc (HWND hwnd, UINT msg,
              case IDC1_HOMERXVT:
                cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC1_HOMERXVT);
                break;
+             case IDC1_FUNCXTERM:
+               cfg.funky_type = 2;
+               break;
              case IDC1_FUNCTILDE:
              case IDC1_FUNCLINUX:
-               cfg.linux_funkeys = IsDlgButtonChecked (hwnd, IDC1_FUNCLINUX);
+               cfg.funky_type = IsDlgButtonChecked (hwnd, IDC1_FUNCLINUX);
                break;
              case IDC1_KPNORMAL:
              case IDC1_KPAPPLIC:
@@ -699,14 +732,10 @@ static int CALLBACK KeyboardProc (HWND hwnd, UINT msg,
                    HIWORD(wParam) == BN_DOUBLECLICKED)
                    cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC1_LDISCTERM);
                break;
-             case IDC1_BLINKCUR:
+             case IDC1_SCROLLKEY:
                if (HIWORD(wParam) == BN_CLICKED ||
                    HIWORD(wParam) == BN_DOUBLECLICKED)
-                   cfg.blink_cur = IsDlgButtonChecked (hwnd, IDC1_BLINKCUR);
-              case IDC1_BEEP:
-                if (HIWORD(wParam) == BN_CLICKED ||
-                    HIWORD(wParam) == BN_DOUBLECLICKED)
-                    cfg.beep = IsDlgButtonChecked (hwnd, IDC1_BEEP);
+                   cfg.scroll_on_key = IsDlgButtonChecked (hwnd, IDC1_SCROLLKEY);
                break;
            }
     }
@@ -742,11 +771,12 @@ static int CALLBACK TerminalProc (HWND hwnd, UINT msg,
        SetDlgItemInt (hwnd, IDC2_SAVEEDIT, cfg.savelines, FALSE);
        fmtfont (fontstatic);
        SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
-       CheckRadioButton (hwnd, IDC2_VTXWINDOWS, IDC2_VTPOORMAN,
-                         cfg.vtmode == VT_XWINDOWS ? IDC2_VTXWINDOWS :
-                         cfg.vtmode == VT_OEMANSI ? IDC2_VTOEMANSI :
-                         cfg.vtmode == VT_OEMONLY ? IDC2_VTOEMONLY :
-                         IDC2_VTPOORMAN);
+       CheckDlgButton (hwnd, IDC1_BLINKCUR, cfg.blink_cur);
+        CheckDlgButton (hwnd, IDC1_BEEP, cfg.beep);
+        CheckDlgButton (hwnd, IDC2_SCROLLBAR, cfg.scrollbar);
+        CheckDlgButton (hwnd, IDC2_LOCKSIZE, cfg.locksize);
+        CheckDlgButton (hwnd, IDC2_BCE, cfg.bce);
+        CheckDlgButton (hwnd, IDC2_BLINKTEXT, cfg.blinktext);
        break;
       case WM_COMMAND:
        switch (LOWORD(wParam)) {
@@ -811,16 +841,36 @@ static int CALLBACK TerminalProc (HWND hwnd, UINT msg,
                SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
            }
            break;
-         case IDC2_VTXWINDOWS:
-         case IDC2_VTOEMANSI:
-         case IDC2_VTOEMONLY:
-         case IDC2_VTPOORMAN:
-           cfg.vtmode =
-               (IsDlgButtonChecked (hwnd, IDC2_VTXWINDOWS) ? VT_XWINDOWS :
-                IsDlgButtonChecked (hwnd, IDC2_VTOEMANSI) ? VT_OEMANSI :
-                IsDlgButtonChecked (hwnd, IDC2_VTOEMONLY) ? VT_OEMONLY :
-                VT_POORMAN);
-           break;
+          case IDC1_BLINKCUR:
+            if (HIWORD(wParam) == BN_CLICKED ||
+                HIWORD(wParam) == BN_DOUBLECLICKED)
+                cfg.blink_cur = IsDlgButtonChecked (hwnd, IDC1_BLINKCUR);
+            break;
+          case IDC1_BEEP:
+            if (HIWORD(wParam) == BN_CLICKED ||
+                HIWORD(wParam) == BN_DOUBLECLICKED)
+                cfg.beep = IsDlgButtonChecked (hwnd, IDC1_BEEP);
+            break;
+          case IDC2_SCROLLBAR:
+            if (HIWORD(wParam) == BN_CLICKED ||
+                HIWORD(wParam) == BN_DOUBLECLICKED)
+                cfg.scrollbar = IsDlgButtonChecked (hwnd, IDC2_SCROLLBAR);
+            break;
+          case IDC2_LOCKSIZE:
+            if (HIWORD(wParam) == BN_CLICKED ||
+                HIWORD(wParam) == BN_DOUBLECLICKED)
+                cfg.locksize = IsDlgButtonChecked (hwnd, IDC2_LOCKSIZE);
+            break;
+          case IDC2_BLINKTEXT:
+            if (HIWORD(wParam) == BN_CLICKED ||
+                HIWORD(wParam) == BN_DOUBLECLICKED)
+                cfg.blinktext = IsDlgButtonChecked (hwnd, IDC2_BLINKTEXT);
+            break;
+          case IDC2_BCE:
+            if (HIWORD(wParam) == BN_CLICKED ||
+                HIWORD(wParam) == BN_DOUBLECLICKED)
+                cfg.bce = IsDlgButtonChecked (hwnd, IDC2_BCE);
+            break;
        }
        break;
     }
@@ -1171,7 +1221,7 @@ static int CALLBACK ColourProc (HWND hwnd, UINT msg,
     return GeneralPanelProc (hwnd, msg, wParam, lParam);
 }
 
-static int CALLBACK LanguageProc (HWND hwnd, UINT msg,
+static int CALLBACK TranslationProc (HWND hwnd, UINT msg,
                                  WPARAM wParam, LPARAM lParam) {
     switch (msg) {
       case WM_INITDIALOG:
@@ -1180,6 +1230,11 @@ static int CALLBACK LanguageProc (HWND hwnd, UINT msg,
                          cfg.xlat_enablekoiwin ? IDC6_KOI8WIN1251 :
                          IDC6_NOXLAT);
        CheckDlgButton (hwnd, IDC6_CAPSLOCKCYR, cfg.xlat_capslockcyr);
+       CheckRadioButton (hwnd, IDC2_VTXWINDOWS, IDC2_VTPOORMAN,
+                         cfg.vtmode == VT_XWINDOWS ? IDC2_VTXWINDOWS :
+                         cfg.vtmode == VT_OEMANSI ? IDC2_VTOEMANSI :
+                         cfg.vtmode == VT_OEMONLY ? IDC2_VTOEMONLY :
+                         IDC2_VTPOORMAN);
       case WM_COMMAND:
        switch (LOWORD(wParam)) {
          case IDC6_NOXLAT:
@@ -1197,6 +1252,16 @@ static int CALLBACK LanguageProc (HWND hwnd, UINT msg,
                    IsDlgButtonChecked (hwnd, IDC6_CAPSLOCKCYR);
            }
            break;
+         case IDC2_VTXWINDOWS:
+         case IDC2_VTOEMANSI:
+         case IDC2_VTOEMONLY:
+         case IDC2_VTPOORMAN:
+           cfg.vtmode =
+               (IsDlgButtonChecked (hwnd, IDC2_VTXWINDOWS) ? VT_XWINDOWS :
+                IsDlgButtonChecked (hwnd, IDC2_VTOEMANSI) ? VT_OEMANSI :
+                IsDlgButtonChecked (hwnd, IDC2_VTOEMONLY) ? VT_OEMONLY :
+                VT_POORMAN);
+           break;
        }
     }
     return GeneralPanelProc (hwnd, msg, wParam, lParam);
@@ -1204,7 +1269,7 @@ static int CALLBACK LanguageProc (HWND hwnd, UINT msg,
 
 static DLGPROC panelproc[NPANELS] = {
     ConnectionProc, KeyboardProc, TerminalProc,
-    TelnetProc, SshProc, SelectionProc, ColourProc, LanguageProc
+    TelnetProc, SshProc, SelectionProc, ColourProc, TranslationProc
 };
 static char *panelids[NPANELS] = {
     MAKEINTRESOURCE(IDD_PANEL0),
@@ -1219,7 +1284,7 @@ static char *panelids[NPANELS] = {
 
 static char *names[NPANELS] = {
     "Connection", "Keyboard", "Terminal", "Telnet",
-    "SSH", "Selection", "Colours", "Language"
+    "SSH", "Selection", "Colours", "Translation"
 };
 
 static int mainp[MAIN_NPANELS] = { 0, 1, 2, 3, 4, 5, 6, 7};
@@ -1297,6 +1362,12 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
       case WM_CLOSE:
        EndDialog (hwnd, 0);
        return 0;
+
+       /* Grrr Explorer will maximize Dialogs! */
+      case WM_SIZE:
+       if (wParam == SIZE_MAXIMIZED)
+          force_normal(hwnd);
+       return 0;
     }
     return 0;
 }
@@ -1412,6 +1483,9 @@ int do_reconfig (HWND hwnd) {
     ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
     if (!ret)
        cfg = backup_cfg;              /* structure copy */
+    else
+        force_normal(hwnd);
+
     return ret;
 }
 
@@ -1462,8 +1536,8 @@ void verify_ssh_host_key(char *host, char *keystr) {
      * Now read a saved key in from the registry and see what it
      * says.
      */
-    otherstr = malloc(len);
-    mungedhost = malloc(3*strlen(host)+1);
+    otherstr = smalloc(len);
+    mungedhost = smalloc(3*strlen(host)+1);
     if (!otherstr || !mungedhost)
        fatalbox("Out of memory");
 
index aa6fda5..5acddc7 100644 (file)
--- a/window.c
+++ b/window.c
@@ -38,7 +38,7 @@
 #define WM_IGNORE_CLIP (WM_XUSER + 2)
 
 static LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
-static int TranslateKey(WPARAM wParam, LPARAM lParam, unsigned char *output);
+static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, unsigned char *output);
 static void cfgtopalette(void);
 static void init_palette(void);
 static void init_fonts(int);
@@ -283,11 +283,16 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
            guess_height = r.bottom - r.top;
     }
 
-    hwnd = CreateWindow (appname, appname,
-                        WS_OVERLAPPEDWINDOW | WS_VSCROLL,
-                        CW_USEDEFAULT, CW_USEDEFAULT,
-                        guess_width, guess_height,
-                        NULL, NULL, inst, NULL);
+    {
+       int winmode = WS_OVERLAPPEDWINDOW|WS_VSCROLL;
+       if (!cfg.scrollbar) winmode &= ~(WS_VSCROLL);
+       if (cfg.locksize)   winmode &= ~(WS_THICKFRAME|WS_MAXIMIZEBOX);
+       hwnd = CreateWindow (appname, appname,
+                           winmode,
+                           CW_USEDEFAULT, CW_USEDEFAULT,
+                           guess_width, guess_height,
+                           NULL, NULL, inst, NULL);
+    }
 
     /*
      * Initialise the fonts, simultaneously correcting the guesses
@@ -325,7 +330,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
        SCROLLINFO si;
 
        si.cbSize = sizeof(si);
-       si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_DISABLENOSCROLL;
+       si.fMask = SIF_ALL | SIF_DISABLENOSCROLL;
        si.nMin = 0;
        si.nMax = rows-1;
        si.nPage = rows;
@@ -358,14 +363,9 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
     /*
      * Set up the input and output buffers.
      */
-    inbuf_reap = inbuf_head = 0;
+    inbuf_head = 0;
     outbuf_reap = outbuf_head = 0;
 
-    /* 
-     * Choose unscroll method
-     */
-    unscroll_event = US_DISP;
-
     /*
      * Prepare the mouse handler.
      */
@@ -458,6 +458,9 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
             */
            term_blink(0);
 
+           /* Send the paste buffer if there's anything to send */
+           term_paste();
+
            /* If there's nothing new in the queue then we can do everything
             * we've delayed, reading the socket, writing, and repainting
             * the window.
@@ -474,10 +477,15 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
                    KillTimer(hwnd, timer_id);
                    timer_id = 0;
                }
-               if (inbuf_reap != inbuf_head)
+               if (inbuf_head)
                    term_out();
                term_update();
-               timer_id = SetTimer(hwnd, 1, 500, NULL);
+               if (!has_focus)
+                  timer_id = SetTimer(hwnd, 1, 2000, NULL);
+               else if (cfg.blinktext)
+                  timer_id = SetTimer(hwnd, 1, 250, NULL);
+               else
+                  timer_id = SetTimer(hwnd, 1, 500, NULL);
                long_timer = 1;
            }
        }
@@ -764,6 +772,9 @@ font_messup:
 
 void request_resize (int w, int h, int refont) {
     int width, height;
+
+    /* If the window is maximized supress resizing attempts */
+    if(IsZoomed(hwnd)) return;
     
 #ifdef CHECKOEMFONT
     /* Don't do this in OEMANSI, you may get disable messages */
@@ -788,6 +799,29 @@ void request_resize (int w, int h, int refont) {
         und_mode = UND_FONT;
         init_fonts(font_width);
     }
+    else
+    {
+       static int first_time = 1;
+       static RECT ss;
+
+       switch(first_time)
+       {
+       case 1:
+            /* Get the size of the screen */
+            if (GetClientRect(GetDesktopWindow(),&ss))
+               /* first_time = 0 */;
+            else { first_time = 2; break; }
+       case 0:
+            /* Make sure the values are sane */
+            width  = (ss.right-ss.left-extra_width  ) / font_width;
+            height = (ss.bottom-ss.top-extra_height ) / font_height;
+
+            if (w>width)  w=width;
+            if (h>height) h=height;
+            if (w<15) w = 15;
+            if (h<1) w = 1;
+       }
+    }
 
     width = extra_width + font_width * w;
     height = extra_height + font_height * h;
@@ -824,7 +858,7 @@ static LRESULT CALLBACK WndProc (HWND hwnd, UINT message,
       case WM_TIMER:
        if (pending_netevent)
            enact_pending_netevent();
-       if (inbuf_reap != inbuf_head)
+       if (inbuf_head)
            term_out();
        term_update();
        return 0;
@@ -936,6 +970,37 @@ static LRESULT CALLBACK WndProc (HWND hwnd, UINT message,
            pal = NULL;
            cfgtopalette();
            init_palette();
+
+           /* Enable or disable the scroll bar, etc */
+           {
+               LONG nflg, flag = GetWindowLong(hwnd, GWL_STYLE);
+
+               nflg = flag;
+               if (cfg.scrollbar) nflg |=  WS_VSCROLL;
+               else               nflg &= ~WS_VSCROLL;
+               if (cfg.locksize) 
+                  nflg &= ~(WS_THICKFRAME|WS_MAXIMIZEBOX);
+               else              
+                  nflg |= (WS_THICKFRAME|WS_MAXIMIZEBOX);
+
+               if (nflg != flag)
+               {
+                   RECT cr, wr;
+
+                   SetWindowLong(hwnd, GWL_STYLE, nflg);
+                   SendMessage (hwnd, WM_IGNORE_SIZE, 0, 0);
+                   SetWindowPos(hwnd, NULL, 0,0,0,0,
+                        SWP_NOACTIVATE|SWP_NOCOPYBITS|
+                        SWP_NOMOVE|SWP_NOSIZE| SWP_NOZORDER|
+                        SWP_FRAMECHANGED);
+
+                   GetWindowRect (hwnd, &wr);
+                   GetClientRect (hwnd, &cr);
+                   extra_width = wr.right - wr.left - cr.right + cr.left;
+                   extra_height = wr.bottom - wr.top - cr.bottom + cr.top;
+               }
+           }
+
            term_size(cfg.height, cfg.width, cfg.savelines);
            InvalidateRect(hwnd, NULL, TRUE);
            SetWindowPos (hwnd, NULL, 0, 0,
@@ -1199,6 +1264,8 @@ static LRESULT CALLBACK WndProc (HWND hwnd, UINT message,
        return FALSE;
       case WM_KEYDOWN:
       case WM_SYSKEYDOWN:
+      case WM_KEYUP:
+      case WM_SYSKEYUP:
        /*
         * Add the scan code and keypress timing to the random
         * number noise, if we're using ssh.
@@ -1217,39 +1284,12 @@ static LRESULT CALLBACK WndProc (HWND hwnd, UINT message,
            unsigned char buf[20];
            int len;
 
-           len = TranslateKey (wParam, lParam, buf);
+           len = TranslateKey (message, wParam, lParam, buf);
            if (len == -1)
                return DefWindowProc (hwnd, message, wParam, lParam);
            ldisc->send (buf, len);
        }
        return 0;
-      case WM_KEYUP:
-      case WM_SYSKEYUP:
-       /*
-        * We handle KEYUP ourselves in order to distinghish left
-        * and right Alt or Control keys, which Windows won't do
-        * right if left to itself. See also the special processing
-        * at the top of TranslateKey.
-        */
-       {
-            BYTE keystate[256];
-            int ret = GetKeyboardState(keystate);
-            if (ret && wParam == VK_MENU) {
-               if (lParam & 0x1000000) keystate[VK_RMENU] = 0;
-               else keystate[VK_LMENU] = 0;
-                SetKeyboardState (keystate);
-            }
-            if (ret && wParam == VK_CONTROL) {
-               if (lParam & 0x1000000) keystate[VK_RCONTROL] = 0;
-               else keystate[VK_LCONTROL] = 0;
-                SetKeyboardState (keystate);
-            }
-       }
-        /*
-         * We don't return here, in order to allow Windows to do
-         * its own KEYUP processing as well.
-         */
-       break;
       case WM_CHAR:
       case WM_SYSCHAR:
        /*
@@ -1275,33 +1315,31 @@ static LRESULT CALLBACK WndProc (HWND hwnd, UINT message,
  * We are allowed to fiddle with the contents of `text'.
  */
 void do_text (Context ctx, int x, int y, char *text, int len,
-             unsigned long attr) {
-    int lattr = 0;     /* Will be arg later for line attribute type */
+             unsigned long attr, int lattr) {
     COLORREF fg, bg, t;
     int nfg, nbg, nfont;
     HDC hdc = ctx;
     RECT line_box;
     int force_manual_underline = 0;
+    int fnt_width = font_width*(1+(lattr!=LATTR_NORM));
 static int *IpDx = 0, IpDxLEN = 0;;
 
-    if (len>IpDxLEN || IpDx[0] != font_width*(1+!lattr)) {
+    if (len>IpDxLEN || IpDx[0] != fnt_width) {
        int i;
        if (len>IpDxLEN) {
            sfree(IpDx);
            IpDx = smalloc((len+16)*sizeof(int));
            IpDxLEN = (len+16);
        }
-       for(i=0; i<len; i++)
-           IpDx[i] = font_width;
+       for(i=0; i<IpDxLEN; i++)
+           IpDx[i] = fnt_width;
     }
 
-    x *= font_width;
+    x *= fnt_width;
     y *= font_height;
 
-    if (lattr) x *= 2;
-
     if (attr & ATTR_ACTCURS) {
-       attr &= (bold_mode == BOLD_COLOURS ? 0x200 : 0x300);
+       attr &= (bold_mode == BOLD_COLOURS ? 0x300200 : 0x300300);
        attr ^= ATTR_CUR_XOR;
     }
 
@@ -1442,7 +1480,7 @@ static int *IpDx = 0, IpDxLEN = 0;;
     SetBkMode (hdc, OPAQUE);
     line_box.left   = x;
     line_box.top    = y;
-    line_box.right  = x+font_width*len;
+    line_box.right  = x+fnt_width*len;
     line_box.bottom = y+font_height;
     ExtTextOut (hdc, x, y, ETO_CLIPPED|ETO_OPAQUE, &line_box, text, len, IpDx);
     if (bold_mode == BOLD_SHADOW && (attr & ATTR_BOLD)) {
@@ -1450,7 +1488,11 @@ static int *IpDx = 0, IpDxLEN = 0;;
 
        /* GRR: This draws the character outside it's box and can leave
        * 'droppings' even with the clip box! I suppose I could loop it
-       * one character at a time ... yuk. */
+       * one character at a time ... yuk. 
+       * 
+       * Or ... I could do a test print with "W", and use +1 or -1 for this
+       * shift depending on if the leftmost column is blank...
+       */
         ExtTextOut (hdc, x-1, y, ETO_CLIPPED, &line_box, text, len, IpDx);
     }
     if (force_manual_underline || 
@@ -1458,7 +1500,7 @@ static int *IpDx = 0, IpDxLEN = 0;;
         HPEN oldpen;
        oldpen = SelectObject (hdc, CreatePen(PS_SOLID, 0, fg));
        MoveToEx (hdc, x, y+descent, NULL);
-       LineTo (hdc, x+len*font_width, y+descent);
+       LineTo (hdc, x+len*fnt_width, y+descent);
         oldpen = SelectObject (hdc, oldpen);
         DeleteObject (oldpen);
     }
@@ -1466,7 +1508,7 @@ static int *IpDx = 0, IpDxLEN = 0;;
        POINT pts[5];
         HPEN oldpen;
        pts[0].x = pts[1].x = pts[4].x = x;
-       pts[2].x = pts[3].x = x+font_width-1;
+       pts[2].x = pts[3].x = x+fnt_width-1;
        pts[0].y = pts[3].y = pts[4].y = y;
        pts[1].y = pts[2].y = y+font_height-1;
        oldpen = SelectObject (hdc, CreatePen(PS_SOLID, 0, colours[23]));
@@ -1476,21 +1518,129 @@ static int *IpDx = 0, IpDxLEN = 0;;
     }
 }
 
+static int check_compose(int first, int second) {
+
+    static char * composetbl[] = {
+       "++#", "AA@", "(([", "//\\", "))]", "(-{", "-)}", "/^|", "!!¡", "C/¢",
+       "C|¢", "L-£", "L=£", "XO¤", "X0¤", "Y-¥", "Y=¥", "||¦", "SO§", "S!§",
+       "S0§", "\"\"¨", "CO©", "C0©", "A_ª", "<<«", ",-¬", "--­", "RO®",
+       "-^¯", "0^°", "+-±", "2^²", "3^³", "''´", "/Uµ", "P!¶", ".^·", ",,¸",
+       "1^¹", "O_º", ">>»", "14¼", "12½", "34¾", "??¿", "`AÀ", "'AÁ", "^AÂ",
+       "~AÃ", "\"AÄ", "*AÅ", "AEÆ", ",CÇ", "`EÈ", "'EÉ", "^EÊ", "\"EË",
+       "`IÌ", "'IÍ", "^IÎ", "\"IÏ", "-DÐ", "~NÑ", "`OÒ", "'OÓ", "^OÔ",
+       "~OÕ", "\"OÖ", "XX×", "/OØ", "`UÙ", "'UÚ", "^UÛ", "\"UÜ", "'YÝ",
+       "HTÞ", "ssß", "`aà", "'aá", "^aâ", "~aã", "\"aä", "*aå", "aeæ", ",cç",
+       "`eè", "'eé", "^eê", "\"eë", "`iì", "'ií", "^iî", "\"iï", "-dð", "~nñ",
+       "`oò", "'oó", "^oô", "~oõ", "\"oö", ":-÷", "o/ø", "`uù", "'uú", "^uû",
+       "\"uü", "'yý", "htþ", "\"yÿ",
+    0};
+
+    char ** c;
+    static int recurse = 0;
+    int nc = -1;
+
+    if(0)
+    {
+       char buf[256];
+       char * p;
+       sprintf(buf, "cc(%d,%d)", first, second);
+       for(p=buf; *p; p++)
+           c_write1(*p);
+    }
+
+    for(c=composetbl; *c; c++) {
+       if( (*c)[0] == first && (*c)[1] == second)
+       {
+           return (*c)[2] & 0xFF;
+       }
+    }
+
+    if(recurse==0)
+    {
+       recurse=1;
+       nc = check_compose(second, first);
+       if(nc == -1)
+           nc = check_compose(toupper(first), toupper(second));
+       if(nc == -1)
+           nc = check_compose(toupper(second), toupper(first));
+       recurse=0;
+    }
+    return nc;
+}
+
+
 /*
- * Translate a WM_(SYS)?KEYDOWN message into a string of ASCII
- * codes. Returns number of bytes used.
+ * Translate a WM_(SYS)?KEY(UP|DOWN) message into a string of ASCII
+ * codes. Returns number of bytes used or zero to drop the message
+ * or -1 to forward the message to windows.
  */
-static int TranslateKey(WPARAM wParam, LPARAM lParam, unsigned char *output) {
-    unsigned char *p = output;
+static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, unsigned char *output) {
     BYTE keystate[256];
-    int ret, code;
-    int cancel_alt = FALSE;
+    int  scan, left_alt = 0, key_down, shift_state;
+    int  r, i, code;
+    unsigned char * p = output;
 
-    /*
-     * Get hold of the keyboard state, because we'll need it a few
-     * times shortly.
-     */
-    ret = GetKeyboardState(keystate);
+static WORD keys[3];
+static int compose_state = 0;
+static int compose_char = 0;
+static WPARAM compose_key = 0;
+
+    r = GetKeyboardState(keystate);
+    if (!r) memset(keystate, 0, sizeof(keystate));
+    else
+    {
+       /* Note if AltGr was pressed and if it was used as a compose key */
+       if (wParam == VK_MENU && (HIWORD(lParam)&KF_EXTENDED))
+       {
+           keystate[VK_RMENU] = keystate[VK_MENU];
+           if (!compose_state) compose_key = wParam;
+       }
+       if (wParam == VK_APPS && !compose_state)
+           compose_key = wParam;
+
+       if (wParam == compose_key)
+       {
+            if (compose_state == 0 && (HIWORD(lParam)&(KF_UP|KF_REPEAT))==0)
+              compose_state = 1;
+           else if (compose_state == 1 && (HIWORD(lParam)&KF_UP))
+              compose_state = 2;
+           else
+              compose_state = 0;
+       }
+       else if (compose_state==1 && wParam != VK_CONTROL)
+          compose_state = 0;
+
+       /* Nastyness with NUMLock - Shift-NUMLock is left alone though */
+       if ( (cfg.funky_type == 0 || (cfg.funky_type == 1 && app_keypad_keys))
+             && wParam==VK_NUMLOCK && !(keystate[VK_SHIFT]&0x80)) {
+
+           wParam = VK_EXECUTE;
+
+           /* UnToggle NUMLock */
+            if ((HIWORD(lParam)&(KF_UP|KF_REPEAT))==0)
+               keystate[VK_NUMLOCK] ^= 1;
+       }
+
+       /* And write back the 'adjusted' state */
+       SetKeyboardState (keystate);
+    }
+
+    /* Disable Auto repeat if required */
+    if (repeat_off && (HIWORD(lParam)&(KF_UP|KF_REPEAT))==KF_REPEAT)
+       return 0;
+
+    if ((HIWORD(lParam)&KF_ALTDOWN) && (keystate[VK_RMENU]&0x80) == 0)
+       left_alt = 1;
+
+    key_down = ((HIWORD(lParam)&KF_UP)==0);
+
+    /* Make sure Ctrl-ALT is not the same as AltGr for ToAscii */
+    if (left_alt && (keystate[VK_CONTROL]&0x80))
+       keystate[VK_MENU] = 0;
+
+    scan = (HIWORD(lParam) & (KF_UP | KF_EXTENDED | 0xFF));
+    shift_state = ((keystate[VK_SHIFT]&0x80)!=0)
+                + ((keystate[VK_CONTROL]&0x80)!=0)*2;
 
     /* 
      * Record that we pressed key so the scroll window can be reset, but
@@ -1500,305 +1650,311 @@ static int TranslateKey(WPARAM wParam, LPARAM lParam, unsigned char *output) {
         seen_key_event = 1; 
     }
 
-    /* 
-     * Windows does not always want to distinguish left and right
-     * Alt or Control keys. Thus we keep track of them ourselves.
-     * See also the WM_KEYUP handler.
-     */
-    if (wParam == VK_MENU) {
-        if (lParam & 0x1000000) keystate[VK_RMENU] = 0x80;
-        else keystate[VK_LMENU] = 0x80;
-        SetKeyboardState (keystate);
-        return 0;
-    }
-    if (wParam == VK_CONTROL) {
-        if (lParam & 0x1000000) keystate[VK_RCONTROL] = 0x80;
-        else keystate[VK_LCONTROL] = 0x80;
-        SetKeyboardState (keystate);
-        return 0;
-    }
+    /* Make sure we're not pasting */
+    if (key_down) term_nopaste();
 
-    /*
-     * Prepend ESC, and cancel ALT, if ALT was pressed at the time
-     * and it wasn't AltGr.
-     */
-    if (lParam & 0x20000000 && (keystate[VK_LMENU] & 0x80)) {
-        *p++ = 0x1B;
-        cancel_alt = TRUE;
-    }
+    if (compose_state>1 && left_alt) compose_state = 0;
 
-    /*
-     * NetHack keypad mode. This may conflict with Shift-PgUp/PgDn,
-     * so we do it first.
-     */
-    if (cfg.nethack_keypad) {
-       int shift = keystate[VK_SHIFT] & 0x80;
-        /*
-         * NB the shifted versions only work with numlock off.
-         */
-       switch ( (lParam >> 16) & 0x1FF ) {
-         case 0x047: *p++ = shift ? 'Y' : 'y'; return p - output;
-         case 0x048: *p++ = shift ? 'K' : 'k'; return p - output;
-         case 0x049: *p++ = shift ? 'U' : 'u'; return p - output;
-         case 0x04B: *p++ = shift ? 'H' : 'h'; return p - output;
-         case 0x04C: *p++ = '.'; return p - output;
-         case 0x04D: *p++ = shift ? 'L' : 'l'; return p - output;
-         case 0x04F: *p++ = shift ? 'B' : 'b'; return p - output;
-         case 0x050: *p++ = shift ? 'J' : 'j'; return p - output;
-         case 0x051: *p++ = shift ? 'N' : 'n'; return p - output;
-         case 0x053: *p++ = '.'; return p - output;
+    /* Sanitize the number pad if not using a PC NumPad */
+    if( left_alt || (app_keypad_keys && cfg.funky_type != 2)
+         || cfg.nethack_keypad || compose_state )
+    {
+       if ((HIWORD(lParam)&KF_EXTENDED) == 0)
+       {
+           int nParam = 0;
+           switch(wParam)
+           {
+           case VK_INSERT:     nParam = VK_NUMPAD0; break;
+           case VK_END:        nParam = VK_NUMPAD1; break;
+           case VK_DOWN:       nParam = VK_NUMPAD2; break;
+           case VK_NEXT:       nParam = VK_NUMPAD3; break;
+           case VK_LEFT:       nParam = VK_NUMPAD4; break;
+           case VK_CLEAR:      nParam = VK_NUMPAD5; break;
+           case VK_RIGHT:      nParam = VK_NUMPAD6; break;
+           case VK_HOME:       nParam = VK_NUMPAD7; break;
+           case VK_UP:         nParam = VK_NUMPAD8; break;
+           case VK_PRIOR:      nParam = VK_NUMPAD9; break;
+           case VK_DELETE:     nParam = VK_DECIMAL; break;
+           }
+           if (nParam)
+           {
+               if (keystate[VK_NUMLOCK]&1) shift_state |= 1;
+               wParam = nParam;
+           }
        }
     }
 
-    /*
-     * Shift-PgUp, Shift-PgDn, and Alt-F4 all produce window
-     * events: we'll deal with those now.
-     */
-    if (ret && (keystate[VK_SHIFT] & 0x80) && wParam == VK_PRIOR) {
-       SendMessage (hwnd, WM_VSCROLL, SB_PAGEUP, 0);
-       return 0;
-    }
-    if (ret && (keystate[VK_SHIFT] & 0x80) && wParam == VK_NEXT) {
-       SendMessage (hwnd, WM_VSCROLL, SB_PAGEDOWN, 0);
-       return 0;
-    }
-    if ((lParam & 0x20000000) && wParam == VK_F4 && cfg.alt_f4) {
-       return -1;
-    }
-    if ((lParam & 0x20000000) && wParam == VK_SPACE && cfg.alt_space) {
-       SendMessage (hwnd, WM_SYSCOMMAND, SC_KEYMENU, 0);
-       return -1;
-    }
+    /* If a key is pressed and AltGr is not active */
+    if (key_down && (keystate[VK_RMENU]&0x80) == 0 && !compose_state)
+    {
+       /* Okay, prepare for most alts then ...*/
+       if (left_alt) *p++ = '\033';
 
-    /*
-     * In general, the strategy is to see what the Windows keymap
-     * translation has to say for itself, and then process function
-     * keys and suchlike ourselves if that fails. But first we must
-     * deal with the small number of special cases which the
-     * Windows keymap translator thinks it can do but gets wrong.
-     *
-     * First special case: we might want the Backspace key to send
-     * 0x7F not 0x08.
-     */
-    if (wParam == VK_BACK) {
-       *p++ = (cfg.bksp_is_delete ? 0x7F : 0x08);
-       return p - output;
-    }
+       /* Lets see if it's a pattern we know all about ... */
+       if (wParam == VK_PRIOR && shift_state == 1) {
+          SendMessage (hwnd, WM_VSCROLL, SB_PAGEUP, 0);
+          return 0;
+       }
+       if (wParam == VK_NEXT && shift_state == 1) {
+          SendMessage (hwnd, WM_VSCROLL, SB_PAGEDOWN, 0);
+          return 0;
+       }
+       if (left_alt && wParam == VK_F4 && cfg.alt_f4) {
+          return -1;
+       }
+       if (left_alt && wParam == VK_SPACE && cfg.alt_space) {
+          SendMessage (hwnd, WM_SYSCOMMAND, SC_KEYMENU, 0);
+          return -1;
+       }
 
-    /*
-     * Control-Space should send ^@ (0x00), not Space.
-     */
-    if (ret && (keystate[VK_CONTROL] & 0x80) && wParam == VK_SPACE) {
-       *p++ = 0x00;
-       return p - output;
-    }
+       /* Nethack keypad */
+       if (cfg.nethack_keypad && !left_alt) {
+          switch(wParam) {
+              case VK_NUMPAD1: *p++ = shift_state ? 'B': 'b'; return p-output;
+              case VK_NUMPAD2: *p++ = shift_state ? 'J': 'j'; return p-output;
+              case VK_NUMPAD3: *p++ = shift_state ? 'N': 'n'; return p-output;
+              case VK_NUMPAD4: *p++ = shift_state ? 'H': 'h'; return p-output;
+              case VK_NUMPAD5: *p++ = shift_state ? '.': '.'; return p-output;
+              case VK_NUMPAD6: *p++ = shift_state ? 'L': 'l'; return p-output;
+              case VK_NUMPAD7: *p++ = shift_state ? 'Y': 'y'; return p-output;
+              case VK_NUMPAD8: *p++ = shift_state ? 'K': 'k'; return p-output;
+              case VK_NUMPAD9: *p++ = shift_state ? 'U': 'u'; return p-output;
+          }
+       }
+
+       /* Application Keypad */
+       if (!left_alt) {
+          int xkey = 0;
+
+          if ( cfg.funky_type == 0 ||
+             ( cfg.funky_type == 1 && app_keypad_keys)) switch(wParam) {
+              case VK_EXECUTE: xkey = 'P'; break;
+              case VK_DIVIDE:  xkey = 'Q'; break;
+              case VK_MULTIPLY:xkey = 'R'; break;
+              case VK_SUBTRACT:xkey = 'S'; break;
+          }
+          if(app_keypad_keys) switch(wParam) {
+              case VK_NUMPAD0: xkey = 'p'; break;
+              case VK_NUMPAD1: xkey = 'q'; break;
+              case VK_NUMPAD2: xkey = 'r'; break;
+              case VK_NUMPAD3: xkey = 's'; break;
+              case VK_NUMPAD4: xkey = 't'; break;
+              case VK_NUMPAD5: xkey = 'u'; break;
+              case VK_NUMPAD6: xkey = 'v'; break;
+              case VK_NUMPAD7: xkey = 'w'; break;
+              case VK_NUMPAD8: xkey = 'x'; break;
+              case VK_NUMPAD9: xkey = 'y'; break;
+
+              case VK_DECIMAL: xkey = 'n'; break;
+              case VK_ADD:     if(shift_state) xkey = 'm'; 
+                               else            xkey = 'l';
+                               break;
+              case VK_RETURN:
+                               if (HIWORD(lParam)&KF_EXTENDED)
+                                   xkey = 'M';
+                               break;
+           }
+           if(xkey)
+           {
+               if (vt52_mode)
+               {
+                   if (xkey>='P' && xkey<='S')
+                       p += sprintf((char *)p, "\x1B%c", xkey); 
+                   else
+                       p += sprintf((char *)p, "\x1B?%c", xkey); 
+               }
+               else 
+                   p += sprintf((char *)p, "\x1BO%c", xkey); 
+               return p - output;
+           }
+       }
+
+       if (wParam == VK_BACK && shift_state == 0 )     /* Backspace */
+       {
+           *p++ = (cfg.bksp_is_delete ? 0x7F : 0x08);
+           return p-output;
+       }
+       if (wParam == VK_TAB && shift_state == 1 )      /* Shift tab */
+       {
+           *p++ = 0x1B; *p++ = '['; *p++ = 'Z'; return p - output;
+       }
+       if (wParam == VK_SPACE && shift_state == 2 )    /* Ctrl-Space */
+       {
+           *p++ = 0; return p - output;
+       }
+       if (wParam == VK_SPACE && shift_state == 3 )    /* Ctrl-Shift-Space */
+       {
+           *p++ = 160; return p - output;
+       }
+       if (wParam == VK_CANCEL && shift_state == 2 )   /* Ctrl-Break */
+       {
+           *p++ = 3; return p - output;
+       }
+       /* Control-2 to Control-8 are special */
+       if (shift_state == 2 && wParam >= '2' && wParam <= '8')
+       {
+           *p++ = "\000\033\034\035\036\037\177"[wParam-'2'];
+           return p - output;
+       }
+       if (shift_state == 2 && wParam == 0xBD) {
+           *p++ = 0x1F;
+           return p - output;
+       }
+       if (shift_state == 2 && wParam == 0xDF) {
+           *p++ = 0x1C;
+           return p - output;
+       }
+       if (shift_state == 0 && wParam == VK_RETURN && cr_lf_return) {
+           *p++ = '\r'; *p++ = '\n';
+           return p - output;
+       }
 
-    if (app_keypad_keys) {
        /*
-        * If we're in applications keypad mode, we have to process it
-        * before char-map translation, because it will pre-empt lots
-        * of stuff, even if NumLock is off.
+        * Next, all the keys that do tilde codes. (ESC '[' nn '~',
+        * for integer decimal nn.)
+        *
+        * We also deal with the weird ones here. Linux VCs replace F1
+        * to F5 by ESC [ [ A to ESC [ [ E. rxvt doesn't do _that_, but
+        * does replace Home and End (1~ and 4~) by ESC [ H and ESC O w
+        * respectively.
         */
-       if (ret) {
-           /*
-            * Hack to ensure NumLock doesn't interfere with
-            * perception of Shift for Keypad Plus. I don't pretend
-            * to understand this, but it seems to work as is.
-            * Leave it alone, or die.
-            */
-           keystate[VK_NUMLOCK] = 0;
-           SetKeyboardState (keystate);
-           GetKeyboardState (keystate);
+       code = 0;
+       switch (wParam) {
+         case VK_F1: code = (keystate[VK_SHIFT] & 0x80 ? 23 : 11); break;
+         case VK_F2: code = (keystate[VK_SHIFT] & 0x80 ? 24 : 12); break;
+         case VK_F3: code = (keystate[VK_SHIFT] & 0x80 ? 25 : 13); break;
+         case VK_F4: code = (keystate[VK_SHIFT] & 0x80 ? 26 : 14); break;
+         case VK_F5: code = (keystate[VK_SHIFT] & 0x80 ? 28 : 15); break;
+         case VK_F6: code = (keystate[VK_SHIFT] & 0x80 ? 29 : 17); break;
+         case VK_F7: code = (keystate[VK_SHIFT] & 0x80 ? 31 : 18); break;
+         case VK_F8: code = (keystate[VK_SHIFT] & 0x80 ? 32 : 19); break;
+         case VK_F9: code = (keystate[VK_SHIFT] & 0x80 ? 33 : 20); break;
+         case VK_F10: code = (keystate[VK_SHIFT] & 0x80 ? 34 : 21); break;
+         case VK_F11: code = 23; break;
+         case VK_F12: code = 24; break;
+         case VK_F13: code = 25; break;
+         case VK_F14: code = 26; break;
+         case VK_F15: code = 28; break;
+         case VK_F16: code = 29; break;
+         case VK_F17: code = 31; break;
+         case VK_F18: code = 32; break;
+         case VK_F19: code = 33; break;
+         case VK_F20: code = 34; break;
+         case VK_HOME: code = 1; break;
+         case VK_INSERT: code = 2; break;
+         case VK_DELETE: code = 3; break;
+         case VK_END: code = 4; break;
+         case VK_PRIOR: code = 5; break;
+         case VK_NEXT: code = 6; break;
        }
-       switch ( (lParam >> 16) & 0x1FF ) {
-         case 0x145: p += sprintf((char *)p, "\x1BOP"); return p - output;
-         case 0x135: p += sprintf((char *)p, "\x1BOQ"); return p - output;
-         case 0x037: p += sprintf((char *)p, "\x1BOR"); return p - output;
-         case 0x047: p += sprintf((char *)p, "\x1BOw"); return p - output;
-         case 0x048: p += sprintf((char *)p, "\x1BOx"); return p - output;
-         case 0x049: p += sprintf((char *)p, "\x1BOy"); return p - output;
-         case 0x04A: p += sprintf((char *)p, "\x1BOS"); return p - output;
-         case 0x04B: p += sprintf((char *)p, "\x1BOt"); return p - output;
-         case 0x04C: p += sprintf((char *)p, "\x1BOu"); return p - output;
-         case 0x04D: p += sprintf((char *)p, "\x1BOv"); return p - output;
-         case 0x04E: /* keypad + is ^[Ol, but ^[Om with Shift */
-           p += sprintf((char *)p,
-                        (ret && (keystate[VK_SHIFT] & 0x80)) ?
-                        "\x1BOm" : "\x1BOl");
+       if (cfg.funky_type == 1 && code >= 11 && code <= 15) {
+           p += sprintf((char *)p, "\x1B[[%c", code + 'A' - 11);
+           return p - output;
+       }
+       if (cfg.funky_type == 2 && code >= 11 && code <= 14) {
+           p += sprintf((char *)p, "\x1BO%c", code + 'P' - 11);
+           return p - output;
+       }
+       if (cfg.rxvt_homeend && (code == 1 || code == 4)) {
+           p += sprintf((char *)p, code == 1 ? "\x1B[H" : "\x1BOw");
+           return p - output;
+       }
+       if (code) {
+           p += sprintf((char *)p, "\x1B[%d~", code);
            return p - output;
-         case 0x04F: p += sprintf((char *)p, "\x1BOq"); return p - output;
-         case 0x050: p += sprintf((char *)p, "\x1BOr"); return p - output;
-         case 0x051: p += sprintf((char *)p, "\x1BOs"); return p - output;
-         case 0x052: p += sprintf((char *)p, "\x1BOp"); return p - output;
-         case 0x053: p += sprintf((char *)p, "\x1BOn"); return p - output;
-         case 0x11C: p += sprintf((char *)p, "\x1BOM"); return p - output;
        }
-    }
-
-    /*
-     * Shift-Tab should send ESC [ Z.
-     */
-    if (ret && (keystate[VK_SHIFT] & 0x80) && wParam == VK_TAB) {
-        *p++ = 0x1B;                   /* ESC */
-        *p++ = '[';
-        *p++ = 'Z';
-       return p - output;
-    }
 
-    /*
-     * Before doing Windows charmap translation, remove LeftALT
-     * from the keymap, since its sole effect should be to prepend
-     * ESC, which we've already done. Note that removal of LeftALT
-     * has to happen _after_ the above call to SetKeyboardState, or
-     * dire things will befall.
-     */
-    if (cancel_alt) {
-        keystate[VK_MENU] = keystate[VK_RMENU];
-        keystate[VK_LMENU] = 0;
+       /*
+        * Now the remaining keys (arrows and Keypad 5. Keypad 5 for
+        * some reason seems to send VK_CLEAR to Windows...).
+        */
+       {
+           char xkey = 0;
+           switch (wParam) {
+               case VK_UP:     xkey = 'A'; break;
+               case VK_DOWN:   xkey = 'B'; break;
+               case VK_RIGHT:  xkey = 'C'; break;
+               case VK_LEFT:   xkey = 'D'; break;
+               case VK_CLEAR:  xkey = 'G'; break;
+           }
+           if (xkey)
+           {
+               if (vt52_mode)
+                   p += sprintf((char *)p, "\x1B%c", xkey);
+               else if (app_cursor_keys)
+                   p += sprintf((char *)p, "\x1BO%c", xkey);
+               else
+                   p += sprintf((char *)p, "\x1B[%c", xkey);
+               return p - output;
+           }
+       }
     }
 
-    /*
-     * Attempt the Windows char-map translation.
-     */
-    if (ret) {
-       WORD chr;
-       int r;
+    /* Okay we've done everything interesting; let windows deal with 
+     * the boring stuff */
+    {
        BOOL capsOn=keystate[VK_CAPITAL] !=0;
 
        /* helg: clear CAPS LOCK state if caps lock switches to cyrillic */
        if(cfg.xlat_capslockcyr)
            keystate[VK_CAPITAL] = 0;
 
-       r = ToAscii (wParam, (lParam >> 16) & 0xFF,
-                    keystate, &chr, 0);
+       r = ToAscii (wParam, scan, keystate, keys, 0);
+       if(r>0)
+       {
+           p = output;
+           for(i=0; i<r; i++)
+           {
+               unsigned char ch = (unsigned char)keys[i];
 
-       if(capsOn)
-           chr = xlat_latkbd2win((unsigned char)(chr & 0xFF));
-       if (r == 1) {
-           *p++ = xlat_kbd2tty((unsigned char)(chr & 0xFF));
-           return p - output;
-       }
-    }
+               if (compose_state==2 && (ch&0x80) == 0 && ch>' ') {
+                   compose_char = ch;
+                   compose_state ++;
+                   continue;
+               }
+               if (compose_state==3 && (ch&0x80) == 0 && ch>' ') {
+                   int nc;
+                   compose_state = 0;
+
+                   if ((nc=check_compose(compose_char,ch)) == -1)
+                   {
+                       c_write1('\007');
+                       return 0;
+                   }
+                   *p++ = xlat_kbd2tty((unsigned char)nc);
+                   return p-output;
+               }
 
-    /*
-     * OK, we haven't had a key code from the keymap translation.
-     * We'll try our various special cases and function keys, and
-     * then give up. (There's nothing wrong with giving up:
-     * Scrollock, Pause/Break, and of course the various buckybit
-     * keys all produce KEYDOWN events that we really _do_ want to
-     * ignore.)
-     */
+               compose_state = 0;
 
-    /*
-     * Control-2 should return ^@ (0x00), Control-6 should return
-     * ^^ (0x1E), and Control-Minus should return ^_ (0x1F). Since
-     * the DOS keyboard handling did it, and we have nothing better
-     * to do with the key combo in question, we'll also map
-     * Control-Backquote to ^\ (0x1C).
-     *
-     * In addition a real VT100 maps Ctrl-3/4/5/7 and 8.
-     */
-    if (ret && (keystate[VK_CONTROL] & 0x80) && wParam == '2') {
-       *p++ = 0x00;
-       return p - output;
-    }
-    if (ret && (keystate[VK_CONTROL] & 0x80) && wParam == '3') {
-       *p++ = 0x1B;
-       return p - output;
-    }
-    if (ret && (keystate[VK_CONTROL] & 0x80) && wParam == '4') {
-       *p++ = 0x1C;
-       return p - output;
-    }
-    if (ret && (keystate[VK_CONTROL] & 0x80) && wParam == '5') {
-       *p++ = 0x1D;
-       return p - output;
-    }
-    if (ret && (keystate[VK_CONTROL] & 0x80) && wParam == '6') {
-       *p++ = 0x1E;
-       return p - output;
-    }
-    if (ret && (keystate[VK_CONTROL] & 0x80) && wParam == '7') {
-       *p++ = 0x1F;
-       return p - output;
-    }
-    if (ret && (keystate[VK_CONTROL] & 0x80) && wParam == '8') {
-       *p++ = 0x7F;
-       return p - output;
-    }
-    if (ret && (keystate[VK_CONTROL] & 0x80) && wParam == 0xBD) {
-       *p++ = 0x1F;
-       return p - output;
-    }
-    if (ret && (keystate[VK_CONTROL] & 0x80) && wParam == 0xDF) {
-       *p++ = 0x1C;
-       return p - output;
-    }
+               if( left_alt && key_down ) *p++ = '\033';
+               if (!key_down)
+                   *p++ = ch;
+               else
+               {
+                   if(capsOn)
+                       ch = xlat_latkbd2win(ch);
+                   *p++ = xlat_kbd2tty(ch);
+               }
+           }
 
-    /*
-     * First, all the keys that do tilde codes. (ESC '[' nn '~',
-     * for integer decimal nn.)
-     *
-     * We also deal with the weird ones here. Linux VCs replace F1
-     * to F5 by ESC [ [ A to ESC [ [ E. rxvt doesn't do _that_, but
-     * does replace Home and End (1~ and 4~) by ESC [ H and ESC O w
-     * respectively.
-     */
-    code = 0;
-    switch (wParam) {
-      case VK_F1: code = (keystate[VK_SHIFT] & 0x80 ? 23 : 11); break;
-      case VK_F2: code = (keystate[VK_SHIFT] & 0x80 ? 24 : 12); break;
-      case VK_F3: code = (keystate[VK_SHIFT] & 0x80 ? 25 : 13); break;
-      case VK_F4: code = (keystate[VK_SHIFT] & 0x80 ? 26 : 14); break;
-      case VK_F5: code = (keystate[VK_SHIFT] & 0x80 ? 28 : 15); break;
-      case VK_F6: code = (keystate[VK_SHIFT] & 0x80 ? 29 : 17); break;
-      case VK_F7: code = (keystate[VK_SHIFT] & 0x80 ? 31 : 18); break;
-      case VK_F8: code = (keystate[VK_SHIFT] & 0x80 ? 32 : 19); break;
-      case VK_F9: code = (keystate[VK_SHIFT] & 0x80 ? 33 : 20); break;
-      case VK_F10: code = (keystate[VK_SHIFT] & 0x80 ? 34 : 21); break;
-      case VK_F11: code = 23; break;
-      case VK_F12: code = 24; break;
-      case VK_HOME: code = 1; break;
-      case VK_INSERT: code = 2; break;
-      case VK_DELETE: code = 3; break;
-      case VK_END: code = 4; break;
-      case VK_PRIOR: code = 5; break;
-      case VK_NEXT: code = 6; break;
-    }
-    if (cfg.linux_funkeys && code >= 11 && code <= 15) {
-       p += sprintf((char *)p, "\x1B[[%c", code + 'A' - 11);
-       return p - output;
-    }
-    if (cfg.rxvt_homeend && (code == 1 || code == 4)) {
-       p += sprintf((char *)p, code == 1 ? "\x1B[H" : "\x1BOw");
-       return p - output;
-    }
-    if (code) {
-       p += sprintf((char *)p, "\x1B[%d~", code);
-       return p - output;
+           /* This is so the ALT-Numpad and dead keys work correctly. */
+           keys[0] = 0;
+
+           return p-output;
+       }
     }
 
-    /*
-     * Now the remaining keys (arrows and Keypad 5. Keypad 5 for
-     * some reason seems to send VK_CLEAR to Windows...).
-     */
-    switch (wParam) {
-      case VK_UP:
-       p += sprintf((char *)p, app_cursor_keys ? "\x1BOA" : "\x1B[A");
-       return p - output;
-      case VK_DOWN:
-       p += sprintf((char *)p, app_cursor_keys ? "\x1BOB" : "\x1B[B");
-       return p - output;
-      case VK_RIGHT:
-       p += sprintf((char *)p, app_cursor_keys ? "\x1BOC" : "\x1B[C");
-       return p - output;
-      case VK_LEFT:
-       p += sprintf((char *)p, app_cursor_keys ? "\x1BOD" : "\x1B[D");
-       return p - output;
-      case VK_CLEAR: p += sprintf((char *)p, "\x1B[G"); return p - output;
+    /* This stops ALT press-release doing a 'COMMAND MENU' function */
+#if 0
+    if (message == WM_SYSKEYUP && wParam == VK_MENU) 
+    {
+       keystate[VK_MENU] = 0;
+       return 0;
     }
+#endif
 
-    return 0;
+    return -1;
 }
 
 void set_title (char *title) {
@@ -1819,8 +1975,11 @@ void set_icon (char *title) {
 
 void set_sbar (int total, int start, int page) {
     SCROLLINFO si;
+
+    if (!cfg.scrollbar) return;
+
     si.cbSize = sizeof(si);
-    si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_DISABLENOSCROLL;
+    si.fMask = SIF_ALL | SIF_DISABLENOSCROLL;
     si.nMin = 0;
     si.nMax = total - 1;
     si.nPage = page;
@@ -1984,6 +2143,21 @@ void fatalbox(char *fmt, ...) {
 /*
  * Beep.
  */
-void beep(void) {
-    MessageBeep(MB_OK);
+void beep(int errorbeep) {
+    static long last_beep = 0;
+    long now, beep_diff;
+
+    now = GetTickCount();
+    beep_diff = now-last_beep;
+
+    /* Make sure we only respond to one beep per packet or so */
+    if (beep_diff>=0 && beep_diff<50)
+        return;
+
+    if(errorbeep)
+       MessageBeep(MB_ICONHAND);
+    else
+       MessageBeep(MB_OK);
+
+    last_beep = GetTickCount();
 }