Author: dumbbell Date: Fri Sep 19 12:20:43 2014 New Revision: 271871 URL: http://svnweb.freebsd.org/changeset/base/271871
Log: vt(4): Rewrite history scrolling It's now possible to scroll up the 500 hard-coded lines of history, not just a fraction of them. For instance, one can reach the top of the boot process. Sometimes, when scrolling or when changing the screen size (by changing the font or loading a KMS driver for instance), one could see the history cycling (old content appeared below latest lines). This is fixed. Now, when the resolution changes are more lines can be shown, the displayed area is adjusted so that, if the screen was filled with content before, it's filled with content after as well: more history is visible, instead of having blank lines below the previously visible content. MFC after: 3 days Modified: head/sys/dev/vt/vt_buf.c head/sys/dev/vt/vt_core.c Modified: head/sys/dev/vt/vt_buf.c ============================================================================== --- head/sys/dev/vt/vt_buf.c Fri Sep 19 11:49:41 2014 (r271870) +++ head/sys/dev/vt/vt_buf.c Fri Sep 19 12:20:43 2014 (r271871) @@ -76,44 +76,46 @@ vthistory_seek(struct vt_buf *vb, int of } return (0); /* No changes */ } - top = (vb->vb_flags & VBF_HISTORY_FULL)? - (vb->vb_curroffset + vb->vb_scr_size.tp_row):vb->vb_history_size; - bottom = vb->vb_curroffset + vb->vb_history_size; - /* - * Operate on copy of offset value, since it temporary can be bigger - * than amount of rows in buffer. - */ - roffset = vb->vb_roffset + vb->vb_history_size; + /* "top" may be a negative integer. */ + bottom = vb->vb_curroffset; + top = (vb->vb_flags & VBF_HISTORY_FULL) ? + bottom + vb->vb_scr_size.tp_row - vb->vb_history_size : + 0; + switch (whence) { case VHS_SET: - roffset = offset + vb->vb_history_size; + if (offset < 0) + offset = 0; + roffset = top + offset; break; case VHS_CUR: + /* + * Operate on copy of offset value, since it temporary + * can be bigger than amount of rows in buffer. + */ + roffset = vb->vb_roffset; + if (roffset >= bottom + vb->vb_scr_size.tp_row) + roffset -= vb->vb_history_size; + roffset += offset; + roffset = MAX(roffset, top); + roffset = MIN(roffset, bottom); + + if (roffset < 0) + roffset = vb->vb_history_size + roffset; + break; case VHS_END: /* Go to current offset. */ - roffset = vb->vb_curroffset + vb->vb_history_size; + roffset = vb->vb_curroffset; break; } - roffset = (roffset < top)?top:roffset; - roffset = (roffset > bottom)?bottom:roffset; - - roffset %= vb->vb_history_size; + diff = vb->vb_roffset != roffset; + vb->vb_roffset = roffset; - if (vb->vb_roffset != roffset) { - diff = vb->vb_roffset - roffset; - vb->vb_roffset = roffset; - /* - * Offset changed, please update Nth lines on sceen. - * +N - Nth lines at top; - * -N - Nth lines at bottom. - */ - return (diff); - } - return (0); /* No changes */ + return (diff); } void @@ -123,6 +125,8 @@ vthistory_addlines(struct vt_buf *vb, in vb->vb_curroffset += offset; if (vb->vb_curroffset < 0) vb->vb_curroffset = 0; + if (vb->vb_curroffset + vb->vb_scr_size.tp_row >= vb->vb_history_size) + vb->vb_flags |= VBF_HISTORY_FULL; vb->vb_curroffset %= vb->vb_history_size; if ((vb->vb_flags & VBF_SCROLL) == 0) { vb->vb_roffset = vb->vb_curroffset; @@ -414,71 +418,155 @@ vtbuf_sethistory_size(struct vt_buf *vb, void vtbuf_grow(struct vt_buf *vb, const term_pos_t *p, unsigned int history_size) { - term_char_t *old, *new, **rows, **oldrows, **copyrows, *row; - int bufsize, rowssize, w, h, c, r; + term_char_t *old, *new, **rows, **oldrows, **copyrows, *row, *oldrow; + int bufsize, rowssize, w, h, c, r, history_was_full; + unsigned int old_history_size; term_rect_t rect; history_size = MAX(history_size, p->tp_row); - /* If new screen/history size bigger or buffer is VBF_STATIC. */ - if ((history_size > vb->vb_history_size) || (p->tp_col > - vb->vb_scr_size.tp_col) || (vb->vb_flags & VBF_STATIC)) { - /* Allocate new buffer. */ - bufsize = history_size * p->tp_col * sizeof(term_char_t); - new = malloc(bufsize, M_VTBUF, M_WAITOK | M_ZERO); - rowssize = history_size * sizeof(term_pos_t *); - rows = malloc(rowssize, M_VTBUF, M_WAITOK | M_ZERO); + /* Allocate new buffer. */ + bufsize = history_size * p->tp_col * sizeof(term_char_t); + new = malloc(bufsize, M_VTBUF, M_WAITOK | M_ZERO); + rowssize = history_size * sizeof(term_pos_t *); + rows = malloc(rowssize, M_VTBUF, M_WAITOK | M_ZERO); - /* Toggle it. */ - VTBUF_LOCK(vb); - old = vb->vb_flags & VBF_STATIC ? NULL : vb->vb_buffer; - oldrows = vb->vb_flags & VBF_STATIC ? NULL : vb->vb_rows; - copyrows = vb->vb_rows; - w = vb->vb_scr_size.tp_col; - h = vb->vb_history_size; - - vb->vb_history_size = history_size; - vb->vb_buffer = new; - vb->vb_rows = rows; - vb->vb_flags &= ~VBF_STATIC; - vb->vb_scr_size = *p; - vtbuf_init_rows(vb); + /* Toggle it. */ + VTBUF_LOCK(vb); + old = vb->vb_flags & VBF_STATIC ? NULL : vb->vb_buffer; + oldrows = vb->vb_flags & VBF_STATIC ? NULL : vb->vb_rows; + copyrows = vb->vb_rows; + + w = vb->vb_scr_size.tp_col; + h = vb->vb_scr_size.tp_row; + old_history_size = vb->vb_history_size; + history_was_full = vb->vb_flags & VBF_HISTORY_FULL; + + vb->vb_history_size = history_size; + vb->vb_buffer = new; + vb->vb_rows = rows; + vb->vb_flags &= ~VBF_STATIC; + vb->vb_scr_size = *p; + vtbuf_init_rows(vb); + + /* Copy history and fill extra space if needed. */ + if (history_size > old_history_size) { + /* + * Copy rows to the new buffer. The first row in the history + * is back to index 0, ie. the new buffer doesn't cycle. + * + * The rest of the new buffer is initialized with blank + * content. + */ + for (r = 0; r < old_history_size; r ++) { + row = rows[r]; + + /* Compute the corresponding row in the old buffer. */ + if (history_was_full) + /* + * The buffer is full, the "top" row is + * the one just after the viewable area + * (curroffset + viewable height) in the + * cycling buffer. The corresponding row + * is computed from this top row. + */ + oldrow = copyrows[ + (vb->vb_curroffset + h + r) % + old_history_size]; + else + /* + * The buffer is not full, therefore, + * we didn't cycle already. The + * corresponding rows are the same in + * both buffers. + */ + oldrow = copyrows[r]; + + memmove(row, oldrow, + MIN(p->tp_col, w) * sizeof(term_char_t)); - /* Copy history and fill extra space. */ - for (r = 0; r < history_size; r ++) { /* * XXX VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR) will * extended lines of kernel text using the wrong * background color. */ - row = rows[r]; - if (r < h) { /* Copy. */ - memmove(rows[r], copyrows[r], - MIN(p->tp_col, w) * sizeof(term_char_t)); - for (c = MIN(p->tp_col, w); c < p->tp_col; - c++) { - row[c] = VTBUF_SPACE_CHAR( - TERMINAL_NORM_ATTR); - } - } else { /* Just fill. */ - rect.tr_begin.tp_col = 0; - rect.tr_begin.tp_row = r; - rect.tr_end.tp_col = p->tp_col; - rect.tr_end.tp_row = p->tp_row; - vtbuf_fill(vb, &rect, - VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR)); - break; + for (c = MIN(p->tp_col, w); c < p->tp_col; c++) { + row[c] = VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR); } } - vtbuf_make_undirty(vb); - VTBUF_UNLOCK(vb); - /* Deallocate old buffer. */ - free(old, M_VTBUF); - free(oldrows, M_VTBUF); + + /* Fill remaining rows. */ + rect.tr_begin.tp_col = 0; + rect.tr_begin.tp_row = old_history_size; + rect.tr_end.tp_col = p->tp_col; + rect.tr_end.tp_row = p->tp_row; + vtbuf_fill(vb, &rect, VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR)); + + vb->vb_flags &= ~VBF_HISTORY_FULL; } else { - /* Just update the size. */ - vb->vb_scr_size = *p; + /* + * Copy rows to the new buffer. The first row in the history + * is back to index 0, ie. the new buffer doesn't cycle. + * + * (old_history_size - history_size) lines of history are + * dropped. + */ + for (r = 0; r < history_size; r ++) { + row = rows[r]; + + /* + * Compute the corresponding row in the old buffer. + * + * See the equivalent if{} block above for an + * explanation. + */ + if (history_was_full) + oldrow = copyrows[ + (vb->vb_curroffset + h + r + + (old_history_size - history_size)) % + old_history_size]; + else + oldrow = copyrows[ + (r + (old_history_size - history_size)) % + old_history_size]; + + memmove(row, oldrow, + MIN(p->tp_col, w) * sizeof(term_char_t)); + + /* + * XXX VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR) will + * extended lines of kernel text using the wrong + * background color. + */ + for (c = MIN(p->tp_col, w); c < p->tp_col; c++) { + row[c] = VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR); + } + } + + if (!history_was_full && + (vb->vb_curroffset + h) >= history_size) + vb->vb_flags |= VBF_HISTORY_FULL; } + + /* + * If the screen is already filled (there are non-visible lines + * above the current viewable area), adjust curroffset to the + * new viewable area. + */ + if (!history_was_full && vb->vb_curroffset > 0) { + vb->vb_curroffset = vb->vb_curroffset + h - p->tp_row; + if (vb->vb_curroffset < 0) + vb->vb_curroffset += vb->vb_history_size; + vb->vb_curroffset %= vb->vb_history_size; + vb->vb_roffset = vb->vb_curroffset; + } + + vtbuf_make_undirty(vb); + VTBUF_UNLOCK(vb); + + /* Deallocate old buffer. */ + free(old, M_VTBUF); + free(oldrows, M_VTBUF); } void Modified: head/sys/dev/vt/vt_core.c ============================================================================== --- head/sys/dev/vt/vt_core.c Fri Sep 19 11:49:41 2014 (r271870) +++ head/sys/dev/vt/vt_core.c Fri Sep 19 12:20:43 2014 (r271871) @@ -484,18 +484,8 @@ vt_scroll(struct vt_window *vw, int offs vt_termsize(vw->vw_device, vw->vw_font, &size); diff = vthistory_seek(&vw->vw_buf, offset, whence); - /* - * Offset changed, please update Nth lines on screen. - * +N - Nth lines at top; - * -N - Nth lines at bottom. - */ - - if (diff < -size.tp_row || diff > size.tp_row) { + if (diff) vw->vw_device->vd_flags |= VDF_INVALID; - vt_resume_flush_timer(vw->vw_device, 0); - return; - } - vw->vw_device->vd_flags |= VDF_INVALID; /*XXX*/ vt_resume_flush_timer(vw->vw_device, 0); } @@ -1181,6 +1171,13 @@ vtterm_cnprobe(struct terminal *tm, stru vt_compute_drawable_area(vw); } + /* + * The original screen size was faked (_VTDEFW x _VTDEFH). Now + * that we have the real viewable size, fix the it in the static + * buffer. + */ + vt_termsize(vd, vw->vw_font, &vw->vw_buf.vb_scr_size); + vtbuf_init_early(&vw->vw_buf); vt_winsize(vd, vw->vw_font, &wsz); c = (boothowto & RB_MUTE) == 0 ? TERMINAL_KERN_ATTR : _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"