diff --git a/input.c b/input.c index 4cba6e06..4cfd3522 100644 --- a/input.c +++ b/input.c @@ -635,7 +635,7 @@ input_handle_c0_control(u_char ch, struct input_ctx *ictx) case '\0': /* NUL */ break; case '\n': /* LF */ - screen_write_linefeed(&ictx->ctx); + screen_write_linefeed(&ictx->ctx, 0); break; case '\r': /* CR */ screen_write_carriagereturn(&ictx->ctx); @@ -659,7 +659,7 @@ input_handle_c0_control(u_char ch, struct input_ctx *ictx) } while (s->cx < screen_size_x(s) - 1); break; case '\013': /* VT */ - screen_write_linefeed(&ictx->ctx); + screen_write_linefeed(&ictx->ctx, 0); break; case '\016': /* SO */ ictx->cell.attr |= GRID_ATTR_CHARSET; @@ -682,11 +682,11 @@ input_handle_c1_control(u_char ch, struct input_ctx *ictx) switch (ch) { case 'D': /* IND */ - screen_write_linefeed(&ictx->ctx); + screen_write_linefeed(&ictx->ctx, 0); break; case 'E': /* NEL */ screen_write_carriagereturn(&ictx->ctx); - screen_write_linefeed(&ictx->ctx); + screen_write_linefeed(&ictx->ctx, 0); break; case 'H': /* HTS */ if (s->cx < screen_size_x(s)) diff --git a/screen-write.c b/screen-write.c index d9b523c4..4e66b076 100644 --- a/screen-write.c +++ b/screen-write.c @@ -610,13 +610,20 @@ screen_write_mousemode(struct screen_write_ctx *ctx, int state) /* Line feed (down with scroll). */ void -screen_write_linefeed(struct screen_write_ctx *ctx) +screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped) { - struct screen *s = ctx->s; - struct tty_ctx ttyctx; + struct screen *s = ctx->s; + struct grid_line *gl; + struct tty_ctx ttyctx; screen_write_initctx(ctx, &ttyctx); + gl = &s->grid->linedata[s->grid->hsize + s->cy]; + if (wrapped) + gl->flags |= GRID_LINE_WRAPPED; + else + gl->flags &= ~GRID_LINE_WRAPPED; + if (s->cy == s->rlower) grid_view_scroll_region_up(s->grid, s->rupper, s->rlower); else if (s->cy < screen_size_y(s) - 1) @@ -782,10 +789,10 @@ screen_write_cell( insert = 1; } - /* Check this will fit on the current line; scroll if not. */ + /* Check this will fit on the current line and wrap if not. */ if (s->cx > screen_size_x(s) - width) { screen_write_carriagereturn(ctx); - screen_write_linefeed(ctx); + screen_write_linefeed(ctx, 1); } /* Sanity checks. */ diff --git a/tmux.h b/tmux.h index 82099e8e..44c169ef 100644 --- a/tmux.h +++ b/tmux.h @@ -484,6 +484,9 @@ struct mode_key_table { #define GRID_FLAG_PADDING 0x4 #define GRID_FLAG_UTF8 0x8 +/* Grid line flags. */ +#define GRID_LINE_WRAPPED 0x1 + /* Grid cell data. */ struct grid_cell { u_char attr; @@ -507,6 +510,8 @@ struct grid_line { u_int utf8size; struct grid_utf8 *utf8data; + + int flags; } __packed; /* Entire grid of cells. */ @@ -1504,7 +1509,7 @@ void screen_write_reverseindex(struct screen_write_ctx *); void screen_write_scrollregion(struct screen_write_ctx *, u_int, u_int); void screen_write_insertmode(struct screen_write_ctx *, int); void screen_write_mousemode(struct screen_write_ctx *, int); -void screen_write_linefeed(struct screen_write_ctx *); +void screen_write_linefeed(struct screen_write_ctx *, int); void screen_write_carriagereturn(struct screen_write_ctx *); void screen_write_kcursormode(struct screen_write_ctx *, int); void screen_write_kkeypadmode(struct screen_write_ctx *, int); diff --git a/window-copy.c b/window-copy.c index db1c3506..06c10d9c 100644 --- a/window-copy.c +++ b/window-copy.c @@ -449,13 +449,11 @@ window_copy_copy_selection(struct window_pane *wp, struct client *c) if (sy == ey) window_copy_copy_line(wp, &buf, &off, sy, sx, ex); else { - xx = window_copy_find_length(wp, sy); + xx = screen_size_x(s); window_copy_copy_line(wp, &buf, &off, sy, sx, xx); if (ey - sy > 1) { - for (i = sy + 1; i < ey; i++) { - xx = window_copy_find_length(wp, i); + for (i = sy + 1; i < ey; i++) window_copy_copy_line(wp, &buf, &off, i, 0, xx); - } } window_copy_copy_line(wp, &buf, &off, ey, 0, ex); } @@ -473,14 +471,28 @@ void window_copy_copy_line(struct window_pane *wp, char **buf, size_t *off, u_int sy, u_int sx, u_int ex) { + struct grid *gd = wp->base.grid; const struct grid_cell *gc; const struct grid_utf8 *gu; - u_int i, j, xx; + struct grid_line *gl; + u_int i, j, xx, wrapped = 0; if (sx > ex) return; - xx = window_copy_find_length(wp, sy); + /* + * Work out if the line was wrapped at the screen edge and all of it is + * on screen. + */ + gl = &gd->linedata[sy]; + if (gl->flags & GRID_LINE_WRAPPED && gl->cellsize <= gd->sx) + wrapped = 1; + + /* If the line was wrapped, don't strip spaces (use the full length). */ + if (wrapped) + xx = gl->cellsize; + else + xx = window_copy_find_length(wp, sy); if (ex > xx) ex = xx; if (sx > xx) @@ -488,14 +500,14 @@ window_copy_copy_line(struct window_pane *wp, if (sx < ex) { for (i = sx; i < ex; i++) { - gc = grid_peek_cell(wp->base.grid, i, sy); + gc = grid_peek_cell(gd, i, sy); if (gc->flags & GRID_FLAG_PADDING) continue; if (!(gc->flags & GRID_FLAG_UTF8)) { *buf = xrealloc(*buf, 1, (*off) + 1); (*buf)[(*off)++] = gc->data; } else { - gu = grid_peek_utf8(wp->base.grid, i, sy); + gu = grid_peek_utf8(gd, i, sy); *buf = xrealloc(*buf, 1, (*off) + UTF8_SIZE); for (j = 0; j < UTF8_SIZE; j++) { if (gu->data[j] == 0xff) @@ -506,9 +518,11 @@ window_copy_copy_line(struct window_pane *wp, } } - *buf = xrealloc(*buf, 1, (*off) + 1); - (*buf)[*off] = '\n'; - (*off)++; + /* Only add a newline if the line wasn't wrapped. */ + if (!wrapped) { + *buf = xrealloc(*buf, 1, (*off) + 1); + (*buf)[(*off)++] = '\n'; + } } int