]> asedeno.scripts.mit.edu Git - PuTTY.git/blobdiff - terminal.c
Add support in uxnet.c for Unix-domain listening sockets.
[PuTTY.git] / terminal.c
index febd897f46ff45282fef909446d343f698acdc69..d6a754c916faace187bb6347933006b6cb521498 100644 (file)
@@ -1224,6 +1224,8 @@ static void power_on(Terminal *term, int clear)
     term->alt_which = 0;
     term_print_finish(term);
     term->xterm_mouse = 0;
+    term->xterm_extended_mouse = 0;
+    term->urxvt_extended_mouse = 0;
     set_raw_mouse_mode(term->frontend, FALSE);
     term->bracketed_paste = FALSE;
     {
@@ -1522,7 +1524,6 @@ Terminal *term_init(Conf *myconf, struct unicode_data *ucsdata,
     term->cblink_pending = term->tblink_pending = FALSE;
     term->paste_buffer = NULL;
     term->paste_len = 0;
-    term->last_paste = 0;
     bufchain_init(&term->inbuf);
     bufchain_init(&term->printer_buf);
     term->printing = term->only_printing = FALSE;
@@ -2491,6 +2492,12 @@ static void toggle_mode(Terminal *term, int mode, int query, int state)
            term->xterm_mouse = state ? 2 : 0;
            set_raw_mouse_mode(term->frontend, state);
            break;
+         case 1006:                   /* xterm extended mouse */
+           term->xterm_extended_mouse = state ? 1 : 0;
+           break;
+         case 1015:                   /* urxvt extended mouse */
+           term->urxvt_extended_mouse = state ? 1 : 0;
+           break;
          case 1047:                   /* alternate screen */
            compatibility(OTHER);
            deselect(term);
@@ -2959,7 +2966,6 @@ static void term_out(Terminal *term)
                term->curs.x = 0;
                term->wrapnext = FALSE;
                seen_disp_event(term);
-               term->paste_hold = 0;
 
                if (term->crhaslf) {
                    if (term->curs.y == term->marg_b)
@@ -2990,7 +2996,6 @@ static void term_out(Terminal *term)
                    term->curs.x = 0;
                term->wrapnext = FALSE;
                seen_disp_event(term);
-               term->paste_hold = 0;
                if (term->logctx)
                    logtraffic(term->logctx, (unsigned char) c, LGTYP_ASCII);
                break;
@@ -5626,7 +5631,8 @@ static pos sel_spread_half(Terminal *term, pos p, int dir)
                    else
                        break;
                } else {
-                   if (ldata->lattr & LATTR_WRAPPED) {
+                   if (p.y+1 < term->rows && 
+                        (ldata->lattr & LATTR_WRAPPED)) {
                        termline *ldata2;
                        ldata2 = lineptr(p.y+1);
                        if (wordtype(term, UCSGET(ldata2->chars, 0))
@@ -5697,6 +5703,33 @@ static void sel_spread(Terminal *term)
     }
 }
 
+static void term_paste_callback(void *vterm)
+{
+    Terminal *term = (Terminal *)vterm;
+
+    if (term->paste_len == 0)
+       return;
+
+    while (term->paste_pos < term->paste_len) {
+       int n = 0;
+       while (n + term->paste_pos < term->paste_len) {
+           if (term->paste_buffer[term->paste_pos + n++] == '\015')
+               break;
+       }
+       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) {
+            queue_toplevel_callback(term_paste_callback, term);
+           return;
+       }
+    }
+    sfree(term->paste_buffer);
+    term->paste_buffer = NULL;
+    term->paste_len = 0;
+}
+
 void term_do_paste(Terminal *term)
 {
     wchar_t *data;
@@ -5710,7 +5743,7 @@ void term_do_paste(Terminal *term)
 
         if (term->paste_buffer)
             sfree(term->paste_buffer);
-        term->paste_pos = term->paste_hold = term->paste_len = 0;
+        term->paste_pos = term->paste_len = 0;
         term->paste_buffer = snewn(len + 12, wchar_t);
 
         if (term->bracketed_paste) {
@@ -5753,10 +5786,12 @@ void term_do_paste(Terminal *term)
             if (term->paste_buffer)
                 sfree(term->paste_buffer);
             term->paste_buffer = 0;
-            term->paste_pos = term->paste_hold = term->paste_len = 0;
+            term->paste_pos = term->paste_len = 0;
         }
     }
     get_clip(term->frontend, NULL, NULL);
+
+    queue_toplevel_callback(term_paste_callback, term);
 }
 
 void term_mouse(Terminal *term, Mouse_Button braw, Mouse_Button bcooked,
@@ -5817,25 +5852,26 @@ void term_mouse(Terminal *term, Mouse_Button braw, Mouse_Button bcooked,
     if (raw_mouse &&
        (term->selstate != ABOUT_TO) && (term->selstate != DRAGGING)) {
        int encstate = 0, r, c;
-       char abuf[16];
+       char abuf[32];
+       int len = 0;
 
        if (term->ldisc) {
 
            switch (braw) {
              case MBT_LEFT:
-               encstate = 0x20;               /* left button down */
+               encstate = 0x00;               /* left button down */
                break;
              case MBT_MIDDLE:
-               encstate = 0x21;
+               encstate = 0x01;
                break;
              case MBT_RIGHT:
-               encstate = 0x22;
+               encstate = 0x02;
                break;
              case MBT_WHEEL_UP:
-               encstate = 0x60;
+               encstate = 0x40;
                break;
              case MBT_WHEEL_DOWN:
-               encstate = 0x61;
+               encstate = 0x41;
                break;
              default: break;          /* placate gcc warning about enum use */
            }
@@ -5846,7 +5882,9 @@ void term_mouse(Terminal *term, Mouse_Button braw, Mouse_Button bcooked,
                encstate += 0x20;
                break;
              case MA_RELEASE:
-               encstate = 0x23;
+               /* If multiple extensions are enabled, the xterm 1006 is used, so it's okay to check for only that */
+               if (!term->xterm_extended_mouse)
+                   encstate = 0x03;
                term->mouse_is_down = 0;
                break;
              case MA_CLICK:
@@ -5860,11 +5898,18 @@ void term_mouse(Terminal *term, Mouse_Button braw, Mouse_Button bcooked,
                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);
+           r = y + 1;
+           c = x + 1;
+
+           /* Check the extensions in decreasing order of preference. Encoding the release event above assumes that 1006 comes first. */
+           if (term->xterm_extended_mouse) {
+               len = sprintf(abuf, "\033[<%d;%d;%d%c", encstate, c, r, a == MA_RELEASE ? 'm' : 'M');
+           } else if (term->urxvt_extended_mouse) {
+               len = sprintf(abuf, "\033[%d;%d;%dM", encstate + 32, c, r);
+           } else if (c <= 223 && r <= 223) {
+               len = sprintf(abuf, "\033[M%c%c%c", encstate + 32, c + 32, r + 32);
+           }
+           ldisc_send(term->ldisc, abuf, len, 0);
        }
        return;
     }
@@ -5983,6 +6028,13 @@ void term_mouse(Terminal *term, Mouse_Button braw, Mouse_Button bcooked,
        request_paste(term->frontend);
     }
 
+    /*
+     * Since terminal output is suppressed during drag-selects, we
+     * should make sure to write any pending output if one has just
+     * finished.
+     */
+    if (term->selstate != DRAGGING)
+        term_out(term);
     term_update(term);
 }
 
@@ -6031,47 +6083,6 @@ void term_nopaste(Terminal *term)
     term->paste_len = 0;
 }
 
-int term_paste_pending(Terminal *term)
-{
-    return term->paste_len != 0;
-}
-
-void term_paste(Terminal *term)
-{
-    long now, paste_diff;
-
-    if (term->paste_len == 0)
-       return;
-
-    /* Don't wait forever to paste */
-    if (term->paste_hold) {
-       now = GETTICKCOUNT();
-       paste_diff = now - term->last_paste;
-       if (paste_diff >= 0 && paste_diff < 450)
-           return;
-    }
-    term->paste_hold = 0;
-
-    while (term->paste_pos < term->paste_len) {
-       int n = 0;
-       while (n + term->paste_pos < term->paste_len) {
-           if (term->paste_buffer[term->paste_pos + n++] == '\015')
-               break;
-       }
-       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) {
-           term->paste_hold = 1;
-           return;
-       }
-    }
-    sfree(term->paste_buffer);
-    term->paste_buffer = NULL;
-    term->paste_len = 0;
-}
-
 static void deselect(Terminal *term)
 {
     term->selstate = NO_SELECTION;
@@ -6082,6 +6093,14 @@ void term_deselect(Terminal *term)
 {
     deselect(term);
     term_update(term);
+
+    /*
+     * Since terminal output is suppressed during drag-selects, we
+     * should make sure to write any pending output if one has just
+     * finished.
+     */
+    if (term->selstate != DRAGGING)
+        term_out(term);
 }
 
 int term_ldisc(Terminal *term, int option)