Line discipline module now uses dynamically allocated data. Also
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sat, 26 Oct 2002 10:16:19 +0000 (10:16 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sat, 26 Oct 2002 10:16:19 +0000 (10:16 +0000)
fixed one or two other minor problems.

git-svn-id: svn://svn.tartarus.org/sgt/putty@2141 cda61777-01e9-0310-a592-d414129be87e

16 files changed:
console.c
ldisc.c
plink.c
putty.h
raw.c
rlogin.c
ssh.c
telnet.c
terminal.c
terminal.h
unicode.c
unix/pterm.c
unix/pty.c
unix/uxucs.c
window.c
winstuff.h

index 80bca3c..85f99dc 100644 (file)
--- a/console.c
+++ b/console.c
@@ -304,7 +304,7 @@ int console_get_line(const char *prompt, char *str,
     return 1;
 }
 
-void frontend_keypress(void)
+void frontend_keypress(void *handle)
 {
     /*
      * This is nothing but a stub, in console code.
diff --git a/ldisc.c b/ldisc.c
index d7b6e40..d9335c9 100644 (file)
--- a/ldisc.c
+++ b/ldisc.c
 #include "putty.h"
 #include "terminal.h"
 
+typedef struct ldisc_tag {
+    Terminal *term;
+    Backend *back;
+    void *backhandle;
+    void *frontend;
+
+    char *buf;
+    int buflen, bufsiz, quotenext;
+} *Ldisc;
+
 #define ECHOING (cfg.localecho == LD_YES || \
                  (cfg.localecho == LD_BACKEND && \
-                      (back->ldisc(backhandle, LD_ECHO) || \
-                          term_ldisc(term, LD_ECHO))))
+                      (ldisc->back->ldisc(ldisc->backhandle, LD_ECHO) || \
+                          term_ldisc(ldisc->term, LD_ECHO))))
 #define EDITING (cfg.localedit == LD_YES || \
                  (cfg.localedit == LD_BACKEND && \
-                      (back->ldisc(backhandle, LD_EDIT) || \
-                          term_ldisc(term, LD_EDIT))))
+                      (ldisc->back->ldisc(ldisc->backhandle, LD_EDIT) || \
+                          term_ldisc(ldisc->term, LD_EDIT))))
 
-static void c_write(char *buf, int len)
+static void c_write(Ldisc ldisc, char *buf, int len)
 {
-    from_backend(term, 0, buf, len);
+    from_backend(ldisc->term, 0, buf, len);
 }
 
-static char *term_buf = NULL;
-static int term_buflen = 0, term_bufsiz = 0, term_quotenext = 0;
-
-static int plen(unsigned char c)
+static int plen(Ldisc ldisc, unsigned char c)
 {
-    if ((c >= 32 && c <= 126) || (c >= 160 && !in_utf(term)))
+    if ((c >= 32 && c <= 126) || (c >= 160 && !in_utf(ldisc->term)))
        return 1;
     else if (c < 128)
        return 2;                      /* ^x for some x */
@@ -38,41 +45,66 @@ static int plen(unsigned char c)
        return 4;                      /* <XY> for hex XY */
 }
 
-static void pwrite(unsigned char c)
+static void pwrite(Ldisc ldisc, unsigned char c)
 {
-    if ((c >= 32 && c <= 126) || (c >= 160 && !in_utf(term))) {
-       c_write(&c, 1);
+    if ((c >= 32 && c <= 126) || (c >= 160 && !in_utf(ldisc->term))) {
+       c_write(ldisc, &c, 1);
     } else if (c < 128) {
        char cc[2];
        cc[1] = (c == 127 ? '?' : c + 0x40);
        cc[0] = '^';
-       c_write(cc, 2);
+       c_write(ldisc, cc, 2);
     } else {
        char cc[5];
        sprintf(cc, "<%02X>", c);
-       c_write(cc, 4);
+       c_write(ldisc, cc, 4);
     }
 }
 
-static void bsb(int n)
+static void bsb(Ldisc ldisc, int n)
 {
     while (n--)
-       c_write("\010 \010", 3);
+       c_write(ldisc, "\010 \010", 3);
 }
 
 #define CTRL(x) (x^'@')
 #define KCTRL(x) ((x^'@') | 0x100)
 
-void ldisc_send(char *buf, int len, int interactive)
+void *ldisc_create(Terminal *term,
+                  Backend *back, void *backhandle,
+                  void *frontend)
 {
+    Ldisc ldisc = smalloc(sizeof(*ldisc));
+
+    ldisc->buf = NULL;
+    ldisc->buflen = 0;
+    ldisc->bufsiz = 0;
+    ldisc->quotenext = 0;
+
+    ldisc->back = back;
+    ldisc->backhandle = backhandle;
+    ldisc->term = term;
+    ldisc->frontend = frontend;
+
+    /* Link ourselves into the backend and the terminal */
+    if (term)
+       term->ldisc = ldisc;
+    if (back)
+       back->provide_ldisc(backhandle, ldisc);
+
+    return ldisc;
+}
+
+void ldisc_send(void *handle, char *buf, int len, int interactive)
+{
+    Ldisc ldisc = (Ldisc) handle;
     int keyflag = 0;
     /*
      * Called with len=0 when the options change. We must inform
      * the front end in case it needs to know.
      */
     if (len == 0) {
-       void ldisc_update(int echo, int edit);
-       ldisc_update(ECHOING, EDITING);
+       ldisc_update(ldisc->frontend, ECHOING, EDITING);
        return;
     }
     /*
@@ -80,7 +112,8 @@ void ldisc_send(char *buf, int len, int interactive)
      * it's depending on finding out (e.g. keypress termination for
      * Close On Exit). 
      */
-    frontend_keypress();
+    frontend_keypress(ldisc->frontend);
+
     /*
      * Less than zero means null terminated special string.
      */
@@ -97,7 +130,7 @@ void ldisc_send(char *buf, int len, int interactive)
            c = *buf++ + keyflag;
            if (!interactive && c == '\r')
                c += KCTRL('@');
-           switch (term_quotenext ? ' ' : c) {
+           switch (ldisc->quotenext ? ' ' : c) {
                /*
                 * ^h/^?: delete one char and output one BSB
                 * ^w: delete, and output BSBs, to return to last
@@ -114,20 +147,20 @@ void ldisc_send(char *buf, int len, int interactive)
                 */
              case KCTRL('H'):
              case KCTRL('?'):         /* backspace/delete */
-               if (term_buflen > 0) {
+               if (ldisc->buflen > 0) {
                    if (ECHOING)
-                       bsb(plen(term_buf[term_buflen - 1]));
-                   term_buflen--;
+                       bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1]));
+                   ldisc->buflen--;
                }
                break;
              case CTRL('W'):          /* delete word */
-               while (term_buflen > 0) {
+               while (ldisc->buflen > 0) {
                    if (ECHOING)
-                       bsb(plen(term_buf[term_buflen - 1]));
-                   term_buflen--;
-                   if (term_buflen > 0 &&
-                       isspace(term_buf[term_buflen - 1]) &&
-                       !isspace(term_buf[term_buflen]))
+                       bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1]));
+                   ldisc->buflen--;
+                   if (ldisc->buflen > 0 &&
+                       isspace(ldisc->buf[ldisc->buflen - 1]) &&
+                       !isspace(ldisc->buf[ldisc->buflen]))
                        break;
                }
                break;
@@ -135,12 +168,12 @@ void ldisc_send(char *buf, int len, int interactive)
              case CTRL('C'):          /* Send IP */
              case CTRL('\\'):         /* Quit */
              case CTRL('Z'):          /* Suspend */
-               while (term_buflen > 0) {
+               while (ldisc->buflen > 0) {
                    if (ECHOING)
-                       bsb(plen(term_buf[term_buflen - 1]));
-                   term_buflen--;
+                       bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1]));
+                   ldisc->buflen--;
                }
-               back->special(backhandle, TS_EL);
+               ldisc->back->special(ldisc->backhandle, TS_EL);
                 /*
                  * We don't send IP, SUSP or ABORT if the user has
                  * configured telnet specials off! This breaks
@@ -149,29 +182,29 @@ void ldisc_send(char *buf, int len, int interactive)
                 if (!cfg.telnet_keyboard)
                     goto default_case;
                if (c == CTRL('C'))
-                   back->special(backhandle, TS_IP);
+                   ldisc->back->special(ldisc->backhandle, TS_IP);
                if (c == CTRL('Z'))
-                   back->special(backhandle, TS_SUSP);
+                   ldisc->back->special(ldisc->backhandle, TS_SUSP);
                if (c == CTRL('\\'))
-                   back->special(backhandle, TS_ABORT);
+                   ldisc->back->special(ldisc->backhandle, TS_ABORT);
                break;
              case CTRL('R'):          /* redraw line */
                if (ECHOING) {
                    int i;
-                   c_write("^R\r\n", 4);
-                   for (i = 0; i < term_buflen; i++)
-                       pwrite(term_buf[i]);
+                   c_write(ldisc, "^R\r\n", 4);
+                   for (i = 0; i < ldisc->buflen; i++)
+                       pwrite(ldisc, ldisc->buf[i]);
                }
                break;
              case CTRL('V'):          /* quote next char */
-               term_quotenext = TRUE;
+               ldisc->quotenext = TRUE;
                break;
              case CTRL('D'):          /* logout or send */
-               if (term_buflen == 0) {
-                   back->special(backhandle, TS_EOF);
+               if (ldisc->buflen == 0) {
+                   ldisc->back->special(ldisc->backhandle, TS_EOF);
                } else {
-                   back->send(backhandle, term_buf, term_buflen);
-                   term_buflen = 0;
+                   ldisc->back->send(ldisc->backhandle, ldisc->buf, ldisc->buflen);
+                   ldisc->buflen = 0;
                }
                break;
                /*
@@ -199,81 +232,81 @@ void ldisc_send(char *buf, int len, int interactive)
                 */
              case CTRL('J'):
                if (cfg.protocol == PROT_RAW &&
-                   term_buflen > 0 && term_buf[term_buflen - 1] == '\r') {
+                   ldisc->buflen > 0 && ldisc->buf[ldisc->buflen - 1] == '\r') {
                    if (ECHOING)
-                       bsb(plen(term_buf[term_buflen - 1]));
-                   term_buflen--;
+                       bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1]));
+                   ldisc->buflen--;
                    /* FALLTHROUGH */
              case KCTRL('M'):         /* send with newline */
-                   if (term_buflen > 0)
-                       back->send(backhandle, term_buf, term_buflen);
+                   if (ldisc->buflen > 0)
+                       ldisc->back->send(ldisc->backhandle, ldisc->buf, ldisc->buflen);
                    if (cfg.protocol == PROT_RAW)
-                       back->send(backhandle, "\r\n", 2);
+                       ldisc->back->send(ldisc->backhandle, "\r\n", 2);
                    else if (cfg.protocol == PROT_TELNET && cfg.telnet_newline)
-                       back->special(backhandle, TS_EOL);
+                       ldisc->back->special(ldisc->backhandle, TS_EOL);
                    else
-                       back->send(backhandle, "\r", 1);
+                       ldisc->back->send(ldisc->backhandle, "\r", 1);
                    if (ECHOING)
-                       c_write("\r\n", 2);
-                   term_buflen = 0;
+                       c_write(ldisc, "\r\n", 2);
+                   ldisc->buflen = 0;
                    break;
                }
                /* FALLTHROUGH */
              default:                 /* get to this label from ^V handler */
                 default_case:
-               if (term_buflen >= term_bufsiz) {
-                   term_bufsiz = term_buflen + 256;
-                   term_buf = saferealloc(term_buf, term_bufsiz);
+               if (ldisc->buflen >= ldisc->bufsiz) {
+                   ldisc->bufsiz = ldisc->buflen + 256;
+                   ldisc->buf = srealloc(ldisc->buf, ldisc->bufsiz);
                }
-               term_buf[term_buflen++] = c;
+               ldisc->buf[ldisc->buflen++] = c;
                if (ECHOING)
-                   pwrite((unsigned char) c);
-               term_quotenext = FALSE;
+                   pwrite(ldisc, (unsigned char) c);
+               ldisc->quotenext = FALSE;
                break;
            }
        }
     } else {
-       if (term_buflen != 0) {
-           back->send(backhandle, term_buf, term_buflen);
-           while (term_buflen > 0) {
-               bsb(plen(term_buf[term_buflen - 1]));
-               term_buflen--;
+       if (ldisc->buflen != 0) {
+           ldisc->back->send(ldisc->backhandle, ldisc->buf, ldisc->buflen);
+           while (ldisc->buflen > 0) {
+               bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1]));
+               ldisc->buflen--;
            }
        }
        if (len > 0) {
            if (ECHOING)
-               c_write(buf, len);
+               c_write(ldisc, buf, len);
            if (keyflag && cfg.protocol == PROT_TELNET && len == 1) {
                switch (buf[0]) {
                  case CTRL('M'):
                    if (cfg.protocol == PROT_TELNET && cfg.telnet_newline)
-                       back->special(backhandle, TS_EOL);
+                       ldisc->back->special(ldisc->backhandle, TS_EOL);
                    else
-                       back->send(backhandle, "\r", 1);
+                       ldisc->back->send(ldisc->backhandle, "\r", 1);
                    break;
                  case CTRL('?'):
                  case CTRL('H'):
                    if (cfg.telnet_keyboard) {
-                       back->special(backhandle, TS_EC);
+                       ldisc->back->special(ldisc->backhandle, TS_EC);
                        break;
                    }
                  case CTRL('C'):
                    if (cfg.telnet_keyboard) {
-                       back->special(backhandle, TS_IP);
+                       ldisc->back->special(ldisc->backhandle, TS_IP);
                        break;
                    }
                  case CTRL('Z'):
                    if (cfg.telnet_keyboard) {
-                       back->special(backhandle, TS_SUSP);
+                       ldisc->back->special(ldisc->backhandle, TS_SUSP);
                        break;
                    }
 
                  default:
-                   back->send(backhandle, buf, len);
+                   ldisc->back->send(ldisc->backhandle, buf, len);
                    break;
                }
            } else
-               back->send(backhandle, buf, len);
+               ldisc->back->send(ldisc->backhandle, buf, len);
        }
     }
 }
diff --git a/plink.c b/plink.c
index 34fe30a..3b33264 100644 (file)
--- a/plink.c
+++ b/plink.c
@@ -73,7 +73,7 @@ int term_ldisc(Terminal *term, int mode)
 {
     return FALSE;
 }
-void ldisc_update(int echo, int edit)
+void ldisc_update(void *frontend, int echo, int edit)
 {
     /* Update stdin read mode to reflect changes in line discipline. */
     DWORD mode;
diff --git a/putty.h b/putty.h
index 6c5a3ad..3bc4a4b 100644 (file)
--- a/putty.h
+++ b/putty.h
@@ -200,6 +200,7 @@ struct backend_tag {
     int (*exitcode) (void *handle);
     int (*sendok) (void *handle);
     int (*ldisc) (void *handle, int);
+    void (*provide_ldisc) (void *handle, void *ldisc);
     /*
      * back->unthrottle() tells the back end that the front end
      * buffer is clearing.
@@ -430,7 +431,8 @@ void beep(int);
 void begin_session(void);
 void sys_cursor(int x, int y);
 void request_paste(void);
-void frontend_keypress(void);
+void frontend_keypress(void *frontend);
+void ldisc_update(void *frontend, int echo, int edit);
 #define OPTIMISE_IS_SCROLL 1
 
 void set_iconic(int iconic);
@@ -536,7 +538,8 @@ extern Backend ssh_backend;
  * Exports from ldisc.c.
  */
 
-extern void ldisc_send(char *buf, int len, int interactive);
+void *ldisc_create(Terminal *, Backend *, void *, void *);
+void ldisc_send(void *handle, char *buf, int len, int interactive);
 
 /*
  * Exports from sshrand.c.
@@ -566,8 +569,8 @@ extern char ver[];
 #define CP_UTF8 65001
 #endif
 void init_ucs_tables(void);
-void lpage_send(int codepage, char *buf, int len, int interactive);
-void luni_send(wchar_t * widebuf, int len, int interactive);
+void lpage_send(void *, int codepage, char *buf, int len, int interactive);
+void luni_send(void *, wchar_t * widebuf, int len, int interactive);
 wchar_t xlat_uskbd2cyrllic(int ch);
 int check_compose(int first, int second);
 int decode_codepage(char *cp_name);
diff --git a/raw.c b/raw.c
index f21e3ca..e269a7d 100644 (file)
--- a/raw.c
+++ b/raw.c
@@ -186,6 +186,11 @@ static int raw_ldisc(void *handle, int option)
     return 0;
 }
 
+static void raw_provide_ldisc(void *handle, void *ldisc)
+{
+    /* This is a stub. */
+}
+
 static int raw_exitcode(void *handle)
 {
     /* Exit codes are a meaningless concept in the Raw protocol */
@@ -202,6 +207,7 @@ Backend raw_backend = {
     raw_exitcode,
     raw_sendok,
     raw_ldisc,
+    raw_provide_ldisc,
     raw_unthrottle,
     1
 };
index 52cf356..61f4afb 100644 (file)
--- a/rlogin.c
+++ b/rlogin.c
@@ -250,6 +250,11 @@ static int rlogin_ldisc(void *handle, int option)
     return 0;
 }
 
+static void rlogin_provide_ldisc(void *handle, void *ldisc)
+{
+    /* This is a stub. */
+}
+
 static int rlogin_exitcode(void *handle)
 {
     Rlogin rlogin = (Rlogin) handle;
@@ -267,6 +272,7 @@ Backend rlogin_backend = {
     rlogin_exitcode,
     rlogin_sendok,
     rlogin_ldisc,
+    rlogin_provide_ldisc,
     rlogin_unthrottle,
     1
 };
diff --git a/ssh.c b/ssh.c
index 072a1b3..0a815bb 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -555,6 +555,8 @@ struct ssh_tag {
 
     Socket s;
 
+    void *ldisc;
+
     unsigned char session_key[32];
     int v1_compressing;
     int v1_remote_protoflags;
@@ -3233,7 +3235,8 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt)
     if (ssh->eof_needed)
        ssh_special(ssh, TS_EOF);
 
-    ldisc_send(NULL, 0, 0);           /* cause ldisc to notice changes */
+    if (ssh->ldisc)
+       ldisc_send(ssh->ldisc, NULL, 0, 0);/* cause ldisc to notice changes */
     ssh->send_ok = 1;
     ssh->channels = newtree234(ssh_channelcmp);
     while (1) {
@@ -5379,7 +5382,8 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
     /*
      * Transfer data!
      */
-    ldisc_send(NULL, 0, 0);           /* cause ldisc to notice changes */
+    if (ssh->ldisc)
+       ldisc_send(ssh->ldisc, NULL, 0, 0);/* cause ldisc to notice changes */
     ssh->send_ok = 1;
     while (1) {
        crReturnV;
@@ -5854,6 +5858,7 @@ static char *ssh_init(void *frontend_handle, void **backend_handle,
     ssh->state = SSH_STATE_PREPACKET;
     ssh->size_needed = FALSE;
     ssh->eof_needed = FALSE;
+    ssh->ldisc = NULL;
     {
        static const struct Packet empty = { 0, 0, NULL, NULL, 0 };
        ssh->pktin = ssh->pktout = empty;
@@ -6133,6 +6138,12 @@ static int ssh_ldisc(void *handle, int option)
     return FALSE;
 }
 
+static void ssh_provide_ldisc(void *handle, void *ldisc)
+{
+    Ssh ssh = (Ssh) handle;
+    ssh->ldisc = ldisc;
+}
+
 static int ssh_return_exitcode(void *handle)
 {
     Ssh ssh = (Ssh) handle;
@@ -6160,6 +6171,7 @@ Backend ssh_backend = {
     ssh_return_exitcode,
     ssh_sendok,
     ssh_ldisc,
+    ssh_provide_ldisc,
     ssh_unthrottle,
     22
 };
index 1a85b28..6fcde71 100644 (file)
--- a/telnet.c
+++ b/telnet.c
@@ -192,6 +192,7 @@ typedef struct telnet_tag {
     Socket s;
 
     void *frontend;
+    void *ldisc;
     int term_width, term_height;
 
     int opt_states[NUM_OPTS];
@@ -261,7 +262,8 @@ static void option_side_effects(Telnet telnet, const struct Opt *o, int enabled)
        telnet->echoing = !enabled;
     else if (o->option == TELOPT_SGA && o->send == DO)
        telnet->editing = !enabled;
-    ldisc_send(NULL, 0, 0);           /* cause ldisc to notice the change */
+    if (telnet->ldisc)                /* cause ldisc to notice the change */
+       ldisc_send(telnet->ldisc, NULL, 0, 0);
 
     /* Ensure we get the minimum options */
     if (!telnet->activated) {
@@ -908,6 +910,12 @@ static int telnet_ldisc(void *handle, int option)
     return FALSE;
 }
 
+static void telnet_provide_ldisc(void *handle, void *ldisc)
+{
+    Telnet telnet = (Telnet) handle;
+    telnet->ldisc = ldisc;
+}
+
 static int telnet_exitcode(void *handle)
 {
     Telnet telnet = (Telnet) handle;
@@ -925,6 +933,7 @@ Backend telnet_backend = {
     telnet_exitcode,
     telnet_sendok,
     telnet_ldisc,
+    telnet_provide_ldisc,
     telnet_unthrottle,
     23
 };
index 5a6d50a..0cbf918 100644 (file)
@@ -241,7 +241,8 @@ void term_seen_key_event(Terminal *term)
 void term_pwron(Terminal *term)
 {
     power_on(term);
-    ldisc_send(NULL, 0, 0);           /* cause ldisc to notice changes */
+    if (term->ldisc)                  /* cause ldisc to notice changes */
+       ldisc_send(term->ldisc, NULL, 0, 0);
     fix_cpos;
     term->disptop = 0;
     deselect(term);
@@ -309,7 +310,7 @@ Terminal *term_init(void)
     term->vt52_mode = FALSE;
     term->cr_lf_return = FALSE;
     term->seen_disp_event = FALSE;
-    term->xterm_mouse = FALSE;
+    term->xterm_mouse = term->mouse_is_down = FALSE;
     term->reset_132 = FALSE;
     term->blinker = term->tblinker = 0;
     term->has_focus = 1;
@@ -915,7 +916,8 @@ static void toggle_mode(Terminal *term, int mode, int query, int state)
            break;
          case 10:                     /* set local edit mode */
            term->term_editing = state;
-           ldisc_send(NULL, 0, 0);    /* cause ldisc to notice changes */
+           if (term->ldisc)           /* cause ldisc to notice changes */
+               ldisc_send(term->ldisc, NULL, 0, 0);
            break;
          case 25:                     /* enable/disable cursor */
            compatibility2(OTHER, VT220);
@@ -965,7 +967,8 @@ static void toggle_mode(Terminal *term, int mode, int query, int state)
            break;
          case 12:                     /* set echo mode */
            term->term_echoing = !state;
-           ldisc_send(NULL, 0, 0);    /* cause ldisc to notice changes */
+           if (term->ldisc)           /* cause ldisc to notice changes */
+               ldisc_send(term->ldisc, NULL, 0, 0);
            break;
          case 20:                     /* Return sends ... */
            term->cr_lf_return = state;
@@ -1288,7 +1291,7 @@ void term_out(Terminal *term)
                 * An xterm returns "xterm" (5 characters)
                 */
                compatibility(ANSIMIN);
-               {
+               if (term->ldisc) {
                    char abuf[256], *s, *d;
                    int state = 0;
                    for (s = cfg.answerback, d = abuf; *s; s++) {
@@ -1306,7 +1309,8 @@ void term_out(Terminal *term)
                        } else
                            *d++ = *s;
                    }
-                   lpage_send(DEFAULT_CODEPAGE, abuf, d - abuf, 0);
+                   lpage_send(term->ldisc, DEFAULT_CODEPAGE,
+                              abuf, d - abuf, 0);
                }
                break;
              case '\007':
@@ -1617,12 +1621,15 @@ void term_out(Terminal *term)
                    break;
                  case 'Z':            /* terminal type query */
                    compatibility(VT100);
-                   ldisc_send(term->id_string, strlen(term->id_string), 0);
+                   if (term->ldisc)
+                       ldisc_send(term->ldisc, term->id_string,
+                                  strlen(term->id_string), 0);
                    break;
                  case 'c':            /* restore power-on settings */
                    compatibility(VT100);
                    power_on(term);
-                   ldisc_send(NULL, 0, 0);/* cause ldisc to notice changes */
+                   if (term->ldisc)   /* cause ldisc to notice changes */
+                       ldisc_send(term->ldisc, NULL, 0, 0);
                    if (term->reset_132) {
                        if (!cfg.no_remote_resize)
                            request_resize(80, term->rows);
@@ -1783,7 +1790,8 @@ void term_out(Terminal *term)
                        compatibility(OTHER);
                        /* this reports xterm version 136 so that VIM can
                           use the drag messages from the mouse reporting */
-                       ldisc_send("\033[>0;136;0c", 11, 0);
+                       if (term->ldisc)
+                           ldisc_send(term->ldisc, "\033[>0;136;0c", 11, 0);
                        break;
                      case 'a':       /* move right N cols */
                        compatibility(ANSI);
@@ -1885,17 +1893,20 @@ void term_out(Terminal *term)
                      case 'c':       /* terminal type query */
                        compatibility(VT100);
                        /* This is the response for a VT102 */
-                       ldisc_send(term->id_string,
-                                  strlen(term->id_string), 0);
+                       if (term->ldisc)
+                           ldisc_send(term->ldisc, term->id_string,
+                                      strlen(term->id_string), 0);
                        break;
                      case 'n':       /* cursor position query */
-                       if (term->esc_args[0] == 6) {
-                           char buf[32];
-                           sprintf(buf, "\033[%d;%dR", term->curs.y + 1,
-                                   term->curs.x + 1);
-                           ldisc_send(buf, strlen(buf), 0);
-                       } else if (term->esc_args[0] == 5) {
-                           ldisc_send("\033[0n", 4, 0);
+                       if (term->ldisc) {
+                           if (term->esc_args[0] == 6) {
+                               char buf[32];
+                               sprintf(buf, "\033[%d;%dR", term->curs.y + 1,
+                                       term->curs.x + 1);
+                               ldisc_send(term->ldisc, buf, strlen(buf), 0);
+                           } else if (term->esc_args[0] == 5) {
+                               ldisc_send(term->ldisc, "\033[0n", 4, 0);
+                           }
                        }
                        break;
                      case 'h':       /* toggle modes to high */
@@ -2175,23 +2186,31 @@ void term_out(Terminal *term)
                                               TRUE : FALSE);
                                break;
                              case 11:
-                               ldisc_send(is_iconic() ? "\033[1t" : "\033[2t",
-                                          4, 0);
+                               if (term->ldisc)
+                                   ldisc_send(term->ldisc,
+                                              is_iconic() ? "\033[1t" :
+                                              "\033[2t", 4, 0);
                                break;
                              case 13:
-                               get_window_pos(&x, &y);
-                               len = sprintf(buf, "\033[3;%d;%dt", x, y);
-                               ldisc_send(buf, len, 0);
+                               if (term->ldisc) {
+                                   get_window_pos(&x, &y);
+                                   len = sprintf(buf, "\033[3;%d;%dt", x, y);
+                                   ldisc_send(term->ldisc, buf, len, 0);
+                               }
                                break;
                              case 14:
-                               get_window_pixels(&x, &y);
-                               len = sprintf(buf, "\033[4;%d;%dt", x, y);
-                               ldisc_send(buf, len, 0);
+                               if (term->ldisc) {
+                                   get_window_pixels(&x, &y);
+                                   len = sprintf(buf, "\033[4;%d;%dt", x, y);
+                                   ldisc_send(term->ldisc, buf, len, 0);
+                               }
                                break;
                              case 18:
-                               len = sprintf(buf, "\033[8;%d;%dt",
-                                             term->rows, term->cols);
-                               ldisc_send(buf, len, 0);
+                               if (term->ldisc) {
+                                   len = sprintf(buf, "\033[8;%d;%dt",
+                                                 term->rows, term->cols);
+                                   ldisc_send(term->ldisc, buf, len, 0);
+                               }
                                break;
                              case 19:
                                /*
@@ -2211,18 +2230,22 @@ void term_out(Terminal *term)
                                 */
                                break;
                              case 20:
-                               p = get_window_title(TRUE);
-                               len = strlen(p);
-                               ldisc_send("\033]L", 3, 0);
-                               ldisc_send(p, len, 0);
-                               ldisc_send("\033\\", 2, 0);
+                               if (term->ldisc) {
+                                   p = get_window_title(TRUE);
+                                   len = strlen(p);
+                                   ldisc_send(term->ldisc, "\033]L", 3, 0);
+                                   ldisc_send(term->ldisc, p, len, 0);
+                                   ldisc_send(term->ldisc, "\033\\", 2, 0);
+                               }
                                break;
                              case 21:
-                               p = get_window_title(FALSE);
-                               len = strlen(p);
-                               ldisc_send("\033]l", 3, 0);
-                               ldisc_send(p, len, 0);
-                               ldisc_send("\033\\", 2, 0);
+                               if (term->ldisc) {
+                                   p = get_window_title(FALSE);
+                                   len = strlen(p);
+                                   ldisc_send(term->ldisc, "\033]l", 3, 0);
+                                   ldisc_send(term->ldisc, p, len, 0);
+                                   ldisc_send(term->ldisc, "\033\\", 2, 0);
+                               }
                                break;
                            }
                        }
@@ -2290,13 +2313,13 @@ void term_out(Terminal *term)
                        break;
                      case 'x':       /* report terminal characteristics */
                        compatibility(VT100);
-                       {
+                       if (term->ldisc) {
                            char buf[32];
                            int i = def(term->esc_args[0], 0);
                            if (i == 0 || i == 1) {
                                strcpy(buf, "\033[2;1;1;112;112;1;0x");
                                buf[2] += i;
-                               ldisc_send(buf, 20, 0);
+                               ldisc_send(term->ldisc, buf, 20, 0);
                            }
                        }
                        break;
@@ -2620,7 +2643,8 @@ void term_out(Terminal *term)
                    term->termstate = VT52_Y1;
                    break;
                  case 'Z':
-                   ldisc_send("\033/Z", 3, 0);
+                   if (term->ldisc)
+                       ldisc_send(term->ldisc, "\033/Z", 3, 0);
                    break;
                  case '=':
                    term->app_keypad_keys = TRUE;
@@ -3281,9 +3305,10 @@ void term_copyall(Terminal *term)
  */
 static int wordtype(Terminal *term, int uc)
 {
-    static struct {
+    struct ucsword {
        int start, end, ctype;
-    } *wptr, ucs_words[] = {
+    };
+    static const struct ucsword ucs_words[] = {
        {
        128, 160, 0}, {
        161, 191, 1}, {
@@ -3347,6 +3372,7 @@ static int wordtype(Terminal *term, int uc)
        {
        0, 0, 0}
     };
+    const struct ucsword *wptr;
 
     uc &= (CSET_MASK | CHAR_MASK);
 
@@ -3524,7 +3550,8 @@ void term_do_paste(Terminal *term)
 
         /* Assume a small paste will be OK in one go. */
         if (term->paste_len < 256) {
-            luni_send(term->paste_buffer, term->paste_len, 0);
+            if (term->ldisc)
+               luni_send(term->ldisc, term->paste_buffer, term->paste_len, 0);
             if (term->paste_buffer)
                 sfree(term->paste_buffer);
             term->paste_buffer = 0;
@@ -3573,52 +3600,54 @@ void term_mouse(Terminal *term, Mouse_Button b, Mouse_Action a, int x, int y,
     if (raw_mouse) {
        int encstate = 0, r, c;
        char abuf[16];
-       static int is_down = 0;
 
-       switch (b) {
-         case MBT_LEFT:
-           encstate = 0x20;           /* left button down */
-           break;
-         case MBT_MIDDLE:
-           encstate = 0x21;
-           break;
-         case MBT_RIGHT:
-           encstate = 0x22;
-           break;
-         case MBT_WHEEL_UP:
-           encstate = 0x60;
-           break;
-         case MBT_WHEEL_DOWN:
-           encstate = 0x61;
-           break;
-         default: break;              /* placate gcc warning about enum use */
-       }
-       switch (a) {
-         case MA_DRAG:
-           if (term->xterm_mouse == 1)
-               return;
-           encstate += 0x20;
-           break;
-         case MA_RELEASE:
-           encstate = 0x23;
-           is_down = 0;
-           break;
-         case MA_CLICK:
-           if (is_down == b)
-               return;
-           is_down = b;
-           break;
-         default: break;              /* placate gcc warning about enum use */
+       if (term->ldisc) {
+
+           switch (b) {
+             case MBT_LEFT:
+               encstate = 0x20;               /* left button down */
+               break;
+             case MBT_MIDDLE:
+               encstate = 0x21;
+               break;
+             case MBT_RIGHT:
+               encstate = 0x22;
+               break;
+             case MBT_WHEEL_UP:
+               encstate = 0x60;
+               break;
+             case MBT_WHEEL_DOWN:
+               encstate = 0x61;
+               break;
+             default: break;          /* placate gcc warning about enum use */
+           }
+           switch (a) {
+             case MA_DRAG:
+               if (term->xterm_mouse == 1)
+                   return;
+               encstate += 0x20;
+               break;
+             case MA_RELEASE:
+               encstate = 0x23;
+               term->mouse_is_down = 0;
+               break;
+             case MA_CLICK:
+               if (term->mouse_is_down == b)
+                   return;
+               term->mouse_is_down = b;
+               break;
+             default: break;          /* placate gcc warning about enum use */
+           }
+           if (shift)
+               encstate += 0x04;
+           if (ctrl)
+               encstate += 0x10;
+           r = y + 33;
+           c = x + 33;
+
+           sprintf(abuf, "\033[M%c%c%c", encstate, c, r);
+           ldisc_send(term->ldisc, abuf, 6, 0);
        }
-       if (shift)
-           encstate += 0x04;
-       if (ctrl)
-           encstate += 0x10;
-       r = y + 33;
-       c = x + 33;
-
-       sprintf(abuf, "\033[M%c%c%c", encstate, c, r);
-       ldisc_send(abuf, 6, 0);
        return;
     }
 
@@ -3775,7 +3804,8 @@ void term_paste(Terminal *term)
            if (term->paste_buffer[term->paste_pos + n++] == '\r')
                break;
        }
-       luni_send(term->paste_buffer + term->paste_pos, n, 0);
+       if (term->ldisc)
+           luni_send(term->ldisc, term->paste_buffer + term->paste_pos, n, 0);
        term->paste_pos += n;
 
        if (term->paste_pos < term->paste_len) {
index 792f89b..9628e07 100644 (file)
@@ -94,6 +94,7 @@ struct terminal_tag {
     long last_tblink;
 
     int xterm_mouse;                  /* send mouse messages to app */
+    int mouse_is_down;                /* used while tracking mouse buttons */
 
     unsigned long cset_attr[2];
 
@@ -160,6 +161,8 @@ struct terminal_tag {
 
     void (*resize_fn)(void *, int, int);
     void *resize_ctx;
+
+    void *ldisc;
 };
 
 #define in_utf(term) ((term)->utf || line_codepage==CP_UTF8)
index 182e244..19a2e1d 100644 (file)
--- a/unicode.c
+++ b/unicode.c
@@ -598,14 +598,14 @@ static void link_font(WCHAR * line_tbl, WCHAR * font_tbl, WCHAR attr)
     }
 }
 
-void lpage_send(int codepage, char *buf, int len, int interactive)
+void lpage_send(void *ldisc, int codepage, char *buf, int len, int interactive)
 {
     static wchar_t *widebuffer = 0;
     static int widesize = 0;
     int wclen;
 
     if (codepage < 0) {
-       ldisc_send(buf, len, interactive);
+       ldisc_send(ldisc, buf, len, interactive);
        return;
     }
 
@@ -616,10 +616,10 @@ void lpage_send(int codepage, char *buf, int len, int interactive)
     }
 
     wclen = mb_to_wc(codepage, 0, buf, len, widebuffer, widesize);
-    luni_send(widebuffer, wclen, interactive);
+    luni_send(ldisc, widebuffer, wclen, interactive);
 }
 
-void luni_send(wchar_t * widebuf, int len, int interactive)
+void luni_send(void *ldisc, wchar_t * widebuf, int len, int interactive)
 {
     static char *linebuffer = 0;
     static int linesize = 0;
@@ -677,7 +677,7 @@ void luni_send(wchar_t * widebuf, int len, int interactive)
        }
     }
     if (p > linebuffer)
-       ldisc_send(linebuffer, p - linebuffer, interactive);
+       ldisc_send(ldisc, linebuffer, p - linebuffer, interactive);
 }
 
 wchar_t xlat_uskbd2cyrllic(int ch)
index 53ca442..2791693 100644 (file)
@@ -53,13 +53,14 @@ struct gui_data {
     char wintitle[sizeof(((Config *)0)->wintitle)];
     char icontitle[sizeof(((Config *)0)->wintitle)];
     int master_fd, master_func_id, exited;
+    void *ldisc;
 };
 
 static struct gui_data the_inst;
 static struct gui_data *inst = &the_inst;   /* so we always write `inst->' */
 static int send_raw_mouse;
 
-void ldisc_update(int echo, int edit)
+void ldisc_update(void *frontend, int echo, int edit)
 {
     /*
      * This is a stub in pterm. If I ever produce a Unix
@@ -792,7 +793,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
        printf("\n");
 #endif
 
-       ldisc_send(output+start, end-start, 1);
+       ldisc_send(inst->ldisc, output+start, end-start, 1);
        show_mouseptr(0);
        term_seen_key_event(term);
        term_out(term);
@@ -924,8 +925,10 @@ void done_with_pty(struct gui_data *inst)
     }
 }
 
-void frontend_keypress(void)
+void frontend_keypress(void *handle)
 {
+    struct gui_data *inst = (struct gui_data *)handle;
+
     /*
      * If our child process has exited but not closed, terminate on
      * any keypress.
@@ -1965,7 +1968,9 @@ int main(int argc, char **argv)
     term_provide_resize_fn(term, back->size, backhandle);
 
     term_size(term, cfg.height, cfg.width, cfg.savelines);
-    ldisc_send(NULL, 0, 0);           /* cause ldisc to notice changes */
+
+    inst->ldisc = ldisc_create(term, back, backhandle, inst);
+    ldisc_send(inst->ldisc, NULL, 0, 0);/* cause ldisc to notice changes */
 
     inst->master_fd = pty_master_fd;
     inst->exited = FALSE;
index 44348a3..67addce 100644 (file)
@@ -589,6 +589,11 @@ static int pty_ldisc(void *handle, int option)
     return 0;                         /* neither editing nor echoing */
 }
 
+static void pty_provide_ldisc(void *handle, void *ldisc)
+{
+    /* This is a stub. */
+}
+
 static int pty_exitcode(void *handle)
 {
     if (!pty_child_dead)
@@ -607,6 +612,7 @@ Backend pty_backend = {
     pty_exitcode,
     pty_sendok,
     pty_ldisc,
+    pty_provide_ldisc,
     pty_unthrottle,
     1
 };
index 78d196f..ff8f3a1 100644 (file)
  * are ISO8859-1.
  */
 
-void lpage_send(int codepage, char *buf, int len, int interactive)
+void lpage_send(void *ldisc, int codepage, char *buf, int len, int interactive)
 {
-    ldisc_send(buf, len, interactive);
+    ldisc_send(ldisc, buf, len, interactive);
 }
 
-void luni_send(wchar_t * widebuf, int len, int interactive)
+void luni_send(void *ldisc, wchar_t * widebuf, int len, int interactive)
 {
     static char *linebuffer = 0;
     static int linesize = 0;
@@ -79,7 +79,7 @@ void luni_send(wchar_t * widebuf, int len, int interactive)
        }
     }
     if (p > linebuffer)
-       ldisc_send(linebuffer, p - linebuffer, interactive);
+       ldisc_send(ldisc, linebuffer, p - linebuffer, interactive);
 }
 
 int is_dbcs_leadbyte(int codepage, char byte)
index 0171d52..c53395a 100644 (file)
--- a/window.c
+++ b/window.c
@@ -108,12 +108,15 @@ static LPARAM pend_netevent_lParam = 0;
 static void enact_pending_netevent(void);
 static void flash_window(int mode);
 static void sys_cursor_update(void);
+static int is_shift_pressed(void);
 static int get_fullscreen_rect(RECT * ss);
 
 static time_t last_movement = 0;
 
 static int caret_x = -1, caret_y = -1;
 
+static void *ldisc;
+
 #define FONT_NORMAL 0
 #define FONT_BOLD 1
 #define FONT_UNDERLINE 2
@@ -168,7 +171,7 @@ static OSVERSIONINFO osVersion;
 static UINT wm_mousewheel = WM_MOUSEWHEEL;
 
 /* Dummy routine, only required in plink. */
-void ldisc_update(int echo, int edit)
+void ldisc_update(void *frontend, int echo, int edit)
 {
 }
 
@@ -625,6 +628,11 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
      */
     term_provide_resize_fn(term, back->size, backhandle);
 
+    /*
+     * Set up a line discipline.
+     */
+    ldisc = ldisc_create(term, back, backhandle, NULL);
+
     session_closed = FALSE;
 
     /*
@@ -1748,7 +1756,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
                 * Flush the line discipline's edit buffer in the
                 * case where local editing has just been disabled.
                 */
-               ldisc_send(NULL, 0, 0);
+               ldisc_send(ldisc, NULL, 0, 0);
                if (pal)
                    DeleteObject(pal);
                logpal = NULL;
@@ -1862,7 +1870,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
            break;
          case IDM_RESET:
            term_pwron(term);
-           ldisc_send(NULL, 0, 0);
+           ldisc_send(ldisc, NULL, 0, 0);
            break;
          case IDM_TEL_AYT:
            back->special(backhandle, TS_AYT);
@@ -2450,7 +2458,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
                     * we're sent.
                     */
                    term_seen_key_event(term);
-                   ldisc_send(buf, len, 1);
+                   ldisc_send(ldisc, buf, len, 1);
                    show_mouseptr(0);
                }
            }
@@ -2498,7 +2506,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
                 */
                term_seen_key_event(term);
                for (i = 0; i < n; i += 2) {
-                   luni_send((unsigned short *)(buff+i), 1, 1);
+                   luni_send(ldisc, (unsigned short *)(buff+i), 1, 1);
                }
                free(buff);
            }
@@ -2513,11 +2521,11 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
            buf[1] = wParam;
            buf[0] = wParam >> 8;
            term_seen_key_event(term);
-           lpage_send(kbd_codepage, buf, 2, 1);
+           lpage_send(ldisc, kbd_codepage, buf, 2, 1);
        } else {
            char c = (unsigned char) wParam;
            term_seen_key_event(term);
-           lpage_send(kbd_codepage, &c, 1, 1);
+           lpage_send(ldisc, kbd_codepage, &c, 1, 1);
        }
        return (0);
       case WM_CHAR:
@@ -2531,7 +2539,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
        {
            char c = (unsigned char)wParam;
            term_seen_key_event(term);
-           lpage_send(CP_ACP, &c, 1, 1);
+           lpage_send(ldisc, CP_ACP, &c, 1, 1);
        }
        return 0;
       case WM_SETCURSOR:
@@ -3780,7 +3788,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
                    }
                    keybuf = nc;
                    term_seen_key_event(term);
-                   luni_send(&keybuf, 1, 1);
+                   luni_send(ldisc, &keybuf, 1, 1);
                    continue;
                }
 
@@ -3791,7 +3799,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
                        if (in_utf(term) || dbcs_screenfont) {
                            keybuf = alt_sum;
                            term_seen_key_event(term);
-                           luni_send(&keybuf, 1, 1);
+                           luni_send(ldisc, &keybuf, 1, 1);
                        } else {
                            ch = (char) alt_sum;
                            /*
@@ -3804,25 +3812,26 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
                             * everything we're sent.
                             */
                            term_seen_key_event(term);
-                           ldisc_send(&ch, 1, 1);
+                           ldisc_send(ldisc, &ch, 1, 1);
                        }
                        alt_sum = 0;
                    } else
                        term_seen_key_event(term);
-                       lpage_send(kbd_codepage, &ch, 1, 1);
+                       lpage_send(ldisc, kbd_codepage, &ch, 1, 1);
                } else {
                    if(capsOn && ch < 0x80) {
                        WCHAR cbuf[2];
                        cbuf[0] = 27;
                        cbuf[1] = xlat_uskbd2cyrllic(ch);
                        term_seen_key_event(term);
-                       luni_send(cbuf+!left_alt, 1+!!left_alt, 1);
+                       luni_send(ldisc, cbuf+!left_alt, 1+!!left_alt, 1);
                    } else {
                        char cbuf[2];
                        cbuf[0] = '\033';
                        cbuf[1] = ch;
                        term_seen_key_event(term);
-                       lpage_send(kbd_codepage, cbuf+!left_alt, 1+!!left_alt, 1);
+                       lpage_send(ldisc, kbd_codepage,
+                                  cbuf+!left_alt, 1+!!left_alt, 1);
                    }
                }
                show_mouseptr(0);
@@ -4559,7 +4568,7 @@ void flip_full_screen()
     }
 }
 
-void frontend_keypress(void)
+void frontend_keypress(void *handle)
 {
     /*
      * Keypress termination in non-Close-On-Exit mode is not
index dadce6e..5ce7387 100644 (file)
@@ -174,6 +174,6 @@ void EnableSizeTip(int bEnable);
 #define mb_to_wc(cp, flags, mbstr, mblen, wcstr, wclen) \
        MultiByteToWideChar(cp, flags, mbstr, mblen, wcstr, wclen)
 #define wc_to_mb(cp, flags, wcstr, wclen, mbstr, mblen, def, defused) \
-       WideCharToMultiByte(cp, flags, mbstr, mblen, wcstr, wclen, def,defused)
+       WideCharToMultiByte(cp, flags, wcstr, wclen, mbstr, mblen, def,defused)
 
 #endif