#ifdef OPTIMISE_SCROLL
static void scroll_display(Terminal *, int, int, int);
#endif /* OPTIMISE_SCROLL */
-static void term_resume_pasting(Terminal *term);
-static void term_paste_callback(void *vterm);
-static void term_paste_queue(Terminal *term, int timed);
static termline *newline(Terminal *term, int cols, int bce)
{
{
int dir = (n < 0 ? -1 : +1);
int m, j;
- pos cursplus;
+ pos eol;
termline *ldata;
n = (n < 0 ? -n : n);
if (n > term->cols - term->curs.x)
n = term->cols - term->curs.x;
m = term->cols - term->curs.x - n;
- cursplus.y = term->curs.y;
- cursplus.x = term->curs.x + n;
- check_selection(term, term->curs, cursplus);
+
+ /*
+ * We must de-highlight the selection if it overlaps any part of
+ * the region affected by this operation, i.e. the region from the
+ * current cursor position to end-of-line, _unless_ the entirety
+ * of the selection is going to be moved to the left or right by
+ * this operation but otherwise unchanged, in which case we can
+ * simply move the highlight with the text.
+ */
+ eol.y = term->curs.y;
+ eol.x = term->cols;
+ if (poslt(term->curs, term->selend) && poslt(term->selstart, eol)) {
+ pos okstart = term->curs;
+ pos okend = eol;
+ if (dir > 0) {
+ /* Insertion: n characters at EOL will be splatted. */
+ okend.x -= n;
+ } else {
+ /* Deletion: n characters at cursor position will be splatted. */
+ okstart.x += n;
+ }
+ if (posle(okstart, term->selstart) && posle(term->selend, okend)) {
+ /* Selection is contained entirely in the interval
+ * [okstart,okend), so we need only adjust the selection
+ * bounds. */
+ term->selstart.x += dir * n;
+ term->selend.x += dir * n;
+ assert(term->selstart.x >= term->curs.x);
+ assert(term->selstart.x < term->cols);
+ assert(term->selend.x > term->curs.x);
+ assert(term->selend.x <= term->cols);
+ } else {
+ /* Selection is not wholly contained in that interval, so
+ * we must unhighlight it. */
+ deselect(term);
+ }
+ }
+
check_boundary(term, term->curs.x, term->curs.y);
if (dir < 0)
check_boundary(term, term->curs.x + n, term->curs.y);
term->curs.x = 0;
term->wrapnext = FALSE;
seen_disp_event(term);
- term_resume_pasting(term);
if (term->crhaslf) {
if (term->curs.y == term->marg_b)
term->curs.x = 0;
term->wrapnext = FALSE;
seen_disp_event(term);
- term_resume_pasting(term);
if (term->logctx)
logtraffic(term->logctx, (unsigned char) c, LGTYP_ASCII);
break;
}
}
-static void term_resume_pasting(Terminal *term)
-{
- expire_timer_context(&term->paste_timer_ctx);
- term_paste_queue(term, FALSE);
-}
-
-static void term_paste_timing_callback(void *vterm, unsigned long now)
-{
- Terminal *term = *(Terminal **)vterm;
- term_resume_pasting(term);
-}
-
-static void term_paste_queue(Terminal *term, int timed)
-{
- if (timed) {
- /*
- * Delay sending the rest of the paste buffer until we have
- * seen a newline coming back from the server (indicating that
- * it's absorbed the data we've sent so far). As a fallback,
- * continue sending anyway after a longish timeout.
- *
- * We use the pointless structure field term->paste_timer_ctx
- * (which is a Terminal *, and we'll make sure it points
- * straight back to term) as our timer context, so that it can
- * be distinguished from term itself. That way, if we see a
- * reason to continue pasting before the timer goes off, we
- * can cancel just this timer and none of the other terminal
- * timers handling display updates, blinking text and cursor,
- * and visual bells.
- */
- term->paste_timer_ctx = term;
- schedule_timer(450, term_paste_timing_callback,
- &term->paste_timer_ctx);
- } else {
- /*
- * Just arrange to call term_paste_callback from the top level
- * at the next opportunity.
- */
- queue_toplevel_callback(term_paste_callback, term);
- }
-}
-
static void term_paste_callback(void *vterm)
{
Terminal *term = (Terminal *)vterm;
term->paste_pos += n;
if (term->paste_pos < term->paste_len) {
- term_paste_queue(term, TRUE);
+ queue_toplevel_callback(term_paste_callback, term);
return;
}
}
}
get_clip(term->frontend, NULL, NULL);
- term_paste_queue(term, FALSE);
+ queue_toplevel_callback(term_paste_callback, term);
}
void term_mouse(Terminal *term, Mouse_Button braw, Mouse_Button bcooked,
{
if (term->paste_len == 0)
return;
- expire_timer_context(&term->paste_timer_ctx);
sfree(term->paste_buffer);
term->paste_buffer = NULL;
term->paste_len = 0;