Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/vt/vt_buf.c
Show First 20 Lines • Show All 128 Lines • ▼ Show 20 Lines | |||||
void | void | ||||
vthistory_addlines(struct vt_buf *vb, int offset) | vthistory_addlines(struct vt_buf *vb, int offset) | ||||
{ | { | ||||
#ifndef SC_NO_CUTPASTE | #ifndef SC_NO_CUTPASTE | ||||
int cur, sz; | int cur, sz; | ||||
#endif | #endif | ||||
vb->vb_curroffset += offset; | vb->vb_curroffset += offset; | ||||
if (vb->vb_curroffset < 0) | if (vb->vb_curroffset + vb->vb_scr_size.tp_row >= vb->vb_history_size) { | ||||
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_flags |= VBF_HISTORY_FULL; | ||||
vb->vb_curroffset %= vb->vb_history_size; | vb->vb_curroffset %= vb->vb_history_size; | ||||
} | |||||
if ((vb->vb_flags & VBF_SCROLL) == 0) { | if ((vb->vb_flags & VBF_SCROLL) == 0) { | ||||
vb->vb_roffset = vb->vb_curroffset; | vb->vb_roffset = vb->vb_curroffset; | ||||
} | } | ||||
#ifndef SC_NO_CUTPASTE | #ifndef SC_NO_CUTPASTE | ||||
sz = vb->vb_history_size; | sz = vb->vb_history_size; | ||||
cur = vb->vb_roffset + vb->vb_scr_size.tp_row + sz - 1; | cur = vb->vb_roffset + vb->vb_scr_size.tp_row + sz - 1; | ||||
if (vtbuf_in_this_range(cur, vb->vb_mark_start.tp_row, cur + offset, sz) || | if (vtbuf_in_this_range(cur, vb->vb_mark_start.tp_row, cur + offset, sz) || | ||||
▲ Show 20 Lines • Show All 305 Lines • ▼ Show 20 Lines | if ((vb->vb_flags & VBF_STATIC) == 0) { | ||||
sz = vb->vb_history_size * sizeof(term_char_t *); | sz = vb->vb_history_size * sizeof(term_char_t *); | ||||
vb->vb_rows = malloc(sz, M_VTBUF, M_WAITOK | M_ZERO); | vb->vb_rows = malloc(sz, M_VTBUF, M_WAITOK | M_ZERO); | ||||
} | } | ||||
vtbuf_init_early(vb); | vtbuf_init_early(vb); | ||||
} | } | ||||
void | void | ||||
vtbuf_sethistory_size(struct vt_buf *vb, int size) | vtbuf_sethistory_size(struct vt_buf *vb, unsigned int size) | ||||
{ | { | ||||
term_pos_t p; | term_pos_t p; | ||||
/* With same size */ | /* With same size */ | ||||
p.tp_row = vb->vb_scr_size.tp_row; | p.tp_row = vb->vb_scr_size.tp_row; | ||||
p.tp_col = vb->vb_scr_size.tp_col; | p.tp_col = vb->vb_scr_size.tp_col; | ||||
vtbuf_grow(vb, &p, size); | vtbuf_grow(vb, &p, size); | ||||
} | } | ||||
void | void | ||||
vtbuf_grow(struct vt_buf *vb, const term_pos_t *p, unsigned int history_size) | vtbuf_grow(struct vt_buf *vb, const term_pos_t *p, unsigned int history_size) | ||||
{ | { | ||||
term_char_t *old, *new, **rows, **oldrows, **copyrows, *row, *oldrow; | term_char_t *old, *new, **rows, **oldrows, **copyrows, *row, *oldrow; | ||||
int bufsize, rowssize, w, h, c, r, history_was_full; | unsigned int w, h, c, r, old_history_size; | ||||
unsigned int old_history_size; | size_t bufsize, rowssize; | ||||
term_rect_t rect; | int history_full; | ||||
history_size = MAX(history_size, p->tp_row); | history_size = MAX(history_size, p->tp_row); | ||||
/* Allocate new buffer. */ | /* Allocate new buffer. */ | ||||
bufsize = history_size * p->tp_col * sizeof(term_char_t); | bufsize = history_size * p->tp_col * sizeof(term_char_t); | ||||
new = malloc(bufsize, M_VTBUF, M_WAITOK | M_ZERO); | new = malloc(bufsize, M_VTBUF, M_WAITOK | M_ZERO); | ||||
rowssize = history_size * sizeof(term_pos_t *); | rowssize = history_size * sizeof(term_pos_t *); | ||||
rows = malloc(rowssize, M_VTBUF, M_WAITOK | M_ZERO); | rows = malloc(rowssize, M_VTBUF, M_WAITOK | M_ZERO); | ||||
/* Toggle it. */ | /* Toggle it. */ | ||||
VTBUF_LOCK(vb); | VTBUF_LOCK(vb); | ||||
old = vb->vb_flags & VBF_STATIC ? NULL : vb->vb_buffer; | old = vb->vb_flags & VBF_STATIC ? NULL : vb->vb_buffer; | ||||
oldrows = vb->vb_flags & VBF_STATIC ? NULL : vb->vb_rows; | oldrows = vb->vb_flags & VBF_STATIC ? NULL : vb->vb_rows; | ||||
copyrows = vb->vb_rows; | copyrows = vb->vb_rows; | ||||
w = vb->vb_scr_size.tp_col; | w = vb->vb_scr_size.tp_col; | ||||
h = vb->vb_scr_size.tp_row; | h = vb->vb_scr_size.tp_row; | ||||
old_history_size = vb->vb_history_size; | old_history_size = vb->vb_history_size; | ||||
history_was_full = vb->vb_flags & VBF_HISTORY_FULL; | history_full = vb->vb_flags & VBF_HISTORY_FULL || | ||||
vb->vb_curroffset + h >= history_size; | |||||
vb->vb_history_size = history_size; | vb->vb_history_size = history_size; | ||||
vb->vb_buffer = new; | vb->vb_buffer = new; | ||||
vb->vb_rows = rows; | vb->vb_rows = rows; | ||||
vb->vb_flags &= ~VBF_STATIC; | vb->vb_flags &= ~VBF_STATIC; | ||||
vb->vb_scr_size = *p; | vb->vb_scr_size = *p; | ||||
vtbuf_init_rows(vb); | 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 | * Copy rows to the new buffer. The first row in the history | ||||
* is back to index 0, ie. the new buffer doesn't cycle. | * is back to index 0, ie. the new buffer doesn't cycle. | ||||
* | |||||
* The rest of the new buffer is initialized with blank | |||||
* content. | |||||
*/ | */ | ||||
if (history_size > old_history_size) { | |||||
for (r = 0; r < old_history_size; r ++) { | for (r = 0; r < old_history_size; r ++) { | ||||
row = rows[r]; | row = rows[r]; | ||||
/* Compute the corresponding row in the old buffer. */ | /* Compute the corresponding row in the old buffer. */ | ||||
if (history_was_full) | if (history_full) | ||||
/* | /* | ||||
* The buffer is full, the "top" row is | * The buffer is full, the "top" row is | ||||
* the one just after the viewable area | * the one just after the viewable area | ||||
* (curroffset + viewable height) in the | * (curroffset + viewable height) in the | ||||
* cycling buffer. The corresponding row | * cycling buffer. The corresponding row | ||||
* is computed from this top row. | * is computed from this top row. | ||||
*/ | */ | ||||
oldrow = copyrows[ | oldrow = copyrows[ | ||||
Show All 17 Lines | for (r = 0; r < old_history_size; r ++) { | ||||
* background color. | * background color. | ||||
*/ | */ | ||||
for (c = MIN(p->tp_col, w); c < p->tp_col; c++) { | for (c = MIN(p->tp_col, w); c < p->tp_col; c++) { | ||||
row[c] = VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR); | row[c] = VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR); | ||||
} | } | ||||
} | } | ||||
/* Fill remaining rows. */ | /* Fill remaining rows. */ | ||||
rect.tr_begin.tp_col = 0; | for (r = old_history_size; r < history_size; r++) { | ||||
rect.tr_begin.tp_row = old_history_size; | row = rows[r]; | ||||
rect.tr_end.tp_col = p->tp_col; | for (c = MIN(p->tp_col, w); c < p->tp_col; c++) { | ||||
rect.tr_end.tp_row = p->tp_row; | row[c] = VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR); | ||||
vtbuf_fill(vb, &rect, VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR)); | } | ||||
} | |||||
vb->vb_flags &= ~VBF_HISTORY_FULL; | vb->vb_flags &= ~VBF_HISTORY_FULL; | ||||
} else { | |||||
/* | /* | ||||
* Copy rows to the new buffer. The first row in the history | * If the screen is already filled (there are non-visible lines | ||||
* is back to index 0, ie. the new buffer doesn't cycle. | * above the current viewable area), adjust curroffset to the | ||||
* new viewable area. | |||||
* | * | ||||
* If the old buffer was full, set curroffset to the | |||||
* <h>th most recent line of history in the new, non-cycled | |||||
* buffer. Otherwise, it didn't cycle, so the old curroffset | |||||
* is the same in the new buffer. | |||||
*/ | |||||
if (history_full) | |||||
vb->vb_curroffset = old_history_size - h; | |||||
} else { | |||||
/* | |||||
* (old_history_size - history_size) lines of history are | * (old_history_size - history_size) lines of history are | ||||
* dropped. | * dropped. | ||||
*/ | */ | ||||
for (r = 0; r < history_size; r ++) { | for (r = 0; r < history_size; r ++) { | ||||
row = rows[r]; | row = rows[r]; | ||||
/* | /* | ||||
* Compute the corresponding row in the old buffer. | * Compute the corresponding row in the old buffer. | ||||
* | * | ||||
* See the equivalent if{} block above for an | * See the equivalent if{} block above for an | ||||
* explanation. | * explanation. | ||||
*/ | */ | ||||
if (history_was_full) | if (history_full) | ||||
oldrow = copyrows[ | oldrow = copyrows[ | ||||
(vb->vb_curroffset + h + r + | (vb->vb_curroffset + h + r + | ||||
(old_history_size - history_size)) % | (old_history_size - history_size)) % | ||||
old_history_size]; | old_history_size]; | ||||
else | else | ||||
oldrow = copyrows[ | oldrow = copyrows[r]; | ||||
(r + (old_history_size - history_size)) % | |||||
old_history_size]; | |||||
memmove(row, oldrow, | memmove(row, oldrow, | ||||
MIN(p->tp_col, w) * sizeof(term_char_t)); | MIN(p->tp_col, w) * sizeof(term_char_t)); | ||||
/* | /* | ||||
* XXX VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR) will | * XXX VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR) will | ||||
* extended lines of kernel text using the wrong | * extended lines of kernel text using the wrong | ||||
* background color. | * background color. | ||||
*/ | */ | ||||
for (c = MIN(p->tp_col, w); c < p->tp_col; c++) { | for (c = MIN(p->tp_col, w); c < p->tp_col; c++) { | ||||
row[c] = VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR); | row[c] = VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR); | ||||
} | } | ||||
} | } | ||||
if (!history_was_full && | if (history_full) { | ||||
(vb->vb_curroffset + h) >= history_size) | vb->vb_curroffset = history_size - h; | ||||
vb->vb_flags |= VBF_HISTORY_FULL; | 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; | vb->vb_roffset = vb->vb_curroffset; | ||||
} | |||||
/* Adjust cursor position. */ | /* Adjust cursor position. */ | ||||
if (vb->vb_cursor.tp_col > p->tp_col - 1) | if (vb->vb_cursor.tp_col > p->tp_col - 1) | ||||
/* | /* | ||||
* Move cursor to the last column, in case its previous | * Move cursor to the last column, in case its previous | ||||
* position is outside of the new screen area. | * position is outside of the new screen area. | ||||
*/ | */ | ||||
vb->vb_cursor.tp_col = p->tp_col - 1; | vb->vb_cursor.tp_col = p->tp_col - 1; | ||||
if (vb->vb_curroffset > 0 || vb->vb_cursor.tp_row > p->tp_row - 1) | if (vb->vb_curroffset > 0 || vb->vb_cursor.tp_row > p->tp_row - 1) | ||||
/* Move cursor to the last line on the screen. */ | /* Move cursor to the last line on the screen. */ | ||||
vb->vb_cursor.tp_row = p->tp_row - 1; | vb->vb_cursor.tp_row = p->tp_row - 1; | ||||
vtbuf_make_undirty(vb); | |||||
VTBUF_UNLOCK(vb); | VTBUF_UNLOCK(vb); | ||||
/* Deallocate old buffer. */ | /* Deallocate old buffer. */ | ||||
free(old, M_VTBUF); | free(old, M_VTBUF); | ||||
free(oldrows, M_VTBUF); | free(oldrows, M_VTBUF); | ||||
} | } | ||||
void | void | ||||
▲ Show 20 Lines • Show All 223 Lines • Show Last 20 Lines |