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);
}
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;
{
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;
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 */
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++)
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);
}
}
}
-
- lines--;
}
}
#ifdef OPTIMISE_SCROLL
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);
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)
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;
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))
}
}
+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;
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) {
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,
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 */
}
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:
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;
}
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);
}
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;
{
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)