X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=terminal.c;h=d6a754c916faace187bb6347933006b6cb521498;hb=6f6e9db932589470975ecc23261cd57eb9e710be;hp=cc4b0d8f91862df48be0141cf93ce4009bfd3530;hpb=8acd57afb51e2facb1c3db7783800f45fda9fda0;p=PuTTY.git diff --git a/terminal.c b/terminal.c index cc4b0d8f..d6a754c9 100644 --- a/terminal.c +++ b/terminal.c @@ -1065,32 +1065,32 @@ static termline *lineptr(Terminal *term, int y, int lineno, int screen) static void term_schedule_tblink(Terminal *term); static void term_schedule_cblink(Terminal *term); -static void term_timer(void *ctx, long now) +static void term_timer(void *ctx, unsigned long now) { Terminal *term = (Terminal *)ctx; int update = FALSE; - if (term->tblink_pending && now - term->next_tblink >= 0) { + if (term->tblink_pending && now == term->next_tblink) { term->tblinker = !term->tblinker; term->tblink_pending = FALSE; term_schedule_tblink(term); update = TRUE; } - if (term->cblink_pending && now - term->next_cblink >= 0) { + if (term->cblink_pending && now == term->next_cblink) { term->cblinker = !term->cblinker; term->cblink_pending = FALSE; term_schedule_cblink(term); update = TRUE; } - if (term->in_vbell && now - term->vbell_end >= 0) { + if (term->in_vbell && now == term->vbell_end) { term->in_vbell = FALSE; update = TRUE; } if (update || - (term->window_update_pending && now - term->next_update >= 0)) + (term->window_update_pending && now == term->next_update)) term_update(term); } @@ -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; @@ -1978,7 +1979,7 @@ static void check_selection(Terminal *term, pos from, pos to) static void scroll(Terminal *term, int topline, int botline, int lines, int sb) { termline *line; - int i, seltop; + int i, seltop, scrollwinsize; #ifdef OPTIMISE_SCROLL int olddisptop, shift; #endif /* OPTIMISE_SCROLL */ @@ -1990,8 +1991,14 @@ static void scroll(Terminal *term, int topline, int botline, int lines, int sb) olddisptop = term->disptop; shift = lines; #endif /* OPTIMISE_SCROLL */ + + scrollwinsize = botline - topline + 1; + if (lines < 0) { - while (lines < 0) { + lines = -lines; + if (lines > scrollwinsize) + lines = scrollwinsize; + while (lines-- > 0) { line = delpos234(term->screen, botline); resizeline(term, line, term->cols); for (i = 0; i < term->cols; i++) @@ -2013,11 +2020,11 @@ static void scroll(Terminal *term, int topline, int botline, int lines, int sb) term->selend.x = 0; } } - - lines++; } } else { - while (lines > 0) { + if (lines > scrollwinsize) + lines = scrollwinsize; + while (lines-- > 0) { line = delpos234(term->screen, topline); #ifdef TERM_CC_DIAGS cc_check(line); @@ -2103,8 +2110,6 @@ static void scroll(Terminal *term, int topline, int botline, int lines, int sb) } } } - - lines--; } } #ifdef OPTIMISE_SCROLL @@ -2487,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); @@ -2955,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) @@ -2986,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; @@ -5622,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)) @@ -5693,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; @@ -5706,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) { @@ -5749,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, @@ -5813,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 */ } @@ -5842,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: @@ -5856,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; } @@ -5979,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); } @@ -6027,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; @@ -6078,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)