127cf7d04SAleksandr Rybalko /*- 227cf7d04SAleksandr Rybalko * Copyright (c) 2009, 2013 The FreeBSD Foundation 327cf7d04SAleksandr Rybalko * All rights reserved. 427cf7d04SAleksandr Rybalko * 527cf7d04SAleksandr Rybalko * This software was developed by Ed Schouten under sponsorship from the 627cf7d04SAleksandr Rybalko * FreeBSD Foundation. 727cf7d04SAleksandr Rybalko * 827cf7d04SAleksandr Rybalko * Portions of this software were developed by Oleksandr Rybalko 927cf7d04SAleksandr Rybalko * under sponsorship from the FreeBSD Foundation. 1027cf7d04SAleksandr Rybalko * 1127cf7d04SAleksandr Rybalko * Redistribution and use in source and binary forms, with or without 1227cf7d04SAleksandr Rybalko * modification, are permitted provided that the following conditions 1327cf7d04SAleksandr Rybalko * are met: 1427cf7d04SAleksandr Rybalko * 1. Redistributions of source code must retain the above copyright 1527cf7d04SAleksandr Rybalko * notice, this list of conditions and the following disclaimer. 1627cf7d04SAleksandr Rybalko * 2. Redistributions in binary form must reproduce the above copyright 1727cf7d04SAleksandr Rybalko * notice, this list of conditions and the following disclaimer in the 1827cf7d04SAleksandr Rybalko * documentation and/or other materials provided with the distribution. 1927cf7d04SAleksandr Rybalko * 2027cf7d04SAleksandr Rybalko * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2127cf7d04SAleksandr Rybalko * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2227cf7d04SAleksandr Rybalko * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2327cf7d04SAleksandr Rybalko * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2427cf7d04SAleksandr Rybalko * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2527cf7d04SAleksandr Rybalko * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2627cf7d04SAleksandr Rybalko * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2727cf7d04SAleksandr Rybalko * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2827cf7d04SAleksandr Rybalko * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2927cf7d04SAleksandr Rybalko * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3027cf7d04SAleksandr Rybalko * SUCH DAMAGE. 3127cf7d04SAleksandr Rybalko */ 3227cf7d04SAleksandr Rybalko 3327cf7d04SAleksandr Rybalko #include <sys/cdefs.h> 3427cf7d04SAleksandr Rybalko __FBSDID("$FreeBSD$"); 3527cf7d04SAleksandr Rybalko 3627cf7d04SAleksandr Rybalko #include <sys/param.h> 3727cf7d04SAleksandr Rybalko #include <sys/kernel.h> 3827cf7d04SAleksandr Rybalko #include <sys/lock.h> 3927cf7d04SAleksandr Rybalko #include <sys/malloc.h> 4027cf7d04SAleksandr Rybalko #include <sys/mutex.h> 417344ee18SMarius Strobl #include <sys/reboot.h> 4227cf7d04SAleksandr Rybalko #include <sys/systm.h> 4327cf7d04SAleksandr Rybalko 4427cf7d04SAleksandr Rybalko #include <dev/vt/vt.h> 4527cf7d04SAleksandr Rybalko 4627cf7d04SAleksandr Rybalko static MALLOC_DEFINE(M_VTBUF, "vtbuf", "vt buffer"); 4727cf7d04SAleksandr Rybalko 4827cf7d04SAleksandr Rybalko #define VTBUF_LOCK(vb) mtx_lock_spin(&(vb)->vb_lock) 4927cf7d04SAleksandr Rybalko #define VTBUF_UNLOCK(vb) mtx_unlock_spin(&(vb)->vb_lock) 5027cf7d04SAleksandr Rybalko 5127cf7d04SAleksandr Rybalko #define POS_INDEX(c, r) (((r) << 12) + (c)) 5227cf7d04SAleksandr Rybalko #define POS_COPY(d, s) do { \ 5327cf7d04SAleksandr Rybalko (d).tp_col = (s).tp_col; \ 5427cf7d04SAleksandr Rybalko (d).tp_row = (s).tp_row; \ 5527cf7d04SAleksandr Rybalko } while (0) 5627cf7d04SAleksandr Rybalko 5727cf7d04SAleksandr Rybalko 5827cf7d04SAleksandr Rybalko /* 5927cf7d04SAleksandr Rybalko * line4 6027cf7d04SAleksandr Rybalko * line5 <--- curroffset (terminal output to that line) 6127cf7d04SAleksandr Rybalko * line0 6227cf7d04SAleksandr Rybalko * line1 <--- roffset (history display from that point) 6327cf7d04SAleksandr Rybalko * line2 6427cf7d04SAleksandr Rybalko * line3 6527cf7d04SAleksandr Rybalko */ 6627cf7d04SAleksandr Rybalko int 6727cf7d04SAleksandr Rybalko vthistory_seek(struct vt_buf *vb, int offset, int whence) 6827cf7d04SAleksandr Rybalko { 6927cf7d04SAleksandr Rybalko int diff, top, bottom, roffset; 7027cf7d04SAleksandr Rybalko 7127cf7d04SAleksandr Rybalko /* No scrolling if not enabled. */ 7227cf7d04SAleksandr Rybalko if ((vb->vb_flags & VBF_SCROLL) == 0) { 7327cf7d04SAleksandr Rybalko if (vb->vb_roffset != vb->vb_curroffset) { 7427cf7d04SAleksandr Rybalko vb->vb_roffset = vb->vb_curroffset; 7527cf7d04SAleksandr Rybalko return (0xffff); 7627cf7d04SAleksandr Rybalko } 7727cf7d04SAleksandr Rybalko return (0); /* No changes */ 7827cf7d04SAleksandr Rybalko } 7927cf7d04SAleksandr Rybalko top = (vb->vb_flags & VBF_HISTORY_FULL)? 8027cf7d04SAleksandr Rybalko (vb->vb_curroffset + vb->vb_scr_size.tp_row):vb->vb_history_size; 8127cf7d04SAleksandr Rybalko bottom = vb->vb_curroffset + vb->vb_history_size; 8227cf7d04SAleksandr Rybalko 8327cf7d04SAleksandr Rybalko /* 8427cf7d04SAleksandr Rybalko * Operate on copy of offset value, since it temporary can be bigger 8527cf7d04SAleksandr Rybalko * than amount of rows in buffer. 8627cf7d04SAleksandr Rybalko */ 8727cf7d04SAleksandr Rybalko roffset = vb->vb_roffset + vb->vb_history_size; 8827cf7d04SAleksandr Rybalko switch (whence) { 8927cf7d04SAleksandr Rybalko case VHS_SET: 9027cf7d04SAleksandr Rybalko roffset = offset + vb->vb_history_size; 9127cf7d04SAleksandr Rybalko break; 9227cf7d04SAleksandr Rybalko case VHS_CUR: 9327cf7d04SAleksandr Rybalko roffset += offset; 9427cf7d04SAleksandr Rybalko break; 9527cf7d04SAleksandr Rybalko case VHS_END: 9627cf7d04SAleksandr Rybalko /* Go to current offset. */ 9727cf7d04SAleksandr Rybalko roffset = vb->vb_curroffset + vb->vb_history_size; 9827cf7d04SAleksandr Rybalko break; 9927cf7d04SAleksandr Rybalko } 10027cf7d04SAleksandr Rybalko 10127cf7d04SAleksandr Rybalko roffset = (roffset < top)?top:roffset; 10227cf7d04SAleksandr Rybalko roffset = (roffset > bottom)?bottom:roffset; 10327cf7d04SAleksandr Rybalko 10427cf7d04SAleksandr Rybalko roffset %= vb->vb_history_size; 10527cf7d04SAleksandr Rybalko 10627cf7d04SAleksandr Rybalko if (vb->vb_roffset != roffset) { 10727cf7d04SAleksandr Rybalko diff = vb->vb_roffset - roffset; 10827cf7d04SAleksandr Rybalko vb->vb_roffset = roffset; 10927cf7d04SAleksandr Rybalko /* 11027cf7d04SAleksandr Rybalko * Offset changed, please update Nth lines on sceen. 11127cf7d04SAleksandr Rybalko * +N - Nth lines at top; 11227cf7d04SAleksandr Rybalko * -N - Nth lines at bottom. 11327cf7d04SAleksandr Rybalko */ 11427cf7d04SAleksandr Rybalko return (diff); 11527cf7d04SAleksandr Rybalko } 11627cf7d04SAleksandr Rybalko return (0); /* No changes */ 11727cf7d04SAleksandr Rybalko } 11827cf7d04SAleksandr Rybalko 11927cf7d04SAleksandr Rybalko void 12027cf7d04SAleksandr Rybalko vthistory_addlines(struct vt_buf *vb, int offset) 12127cf7d04SAleksandr Rybalko { 12227cf7d04SAleksandr Rybalko 12327cf7d04SAleksandr Rybalko vb->vb_curroffset += offset; 12427cf7d04SAleksandr Rybalko if (vb->vb_curroffset < 0) 12527cf7d04SAleksandr Rybalko vb->vb_curroffset = 0; 12627cf7d04SAleksandr Rybalko vb->vb_curroffset %= vb->vb_history_size; 12727cf7d04SAleksandr Rybalko if ((vb->vb_flags & VBF_SCROLL) == 0) { 12827cf7d04SAleksandr Rybalko vb->vb_roffset = vb->vb_curroffset; 12927cf7d04SAleksandr Rybalko } 13027cf7d04SAleksandr Rybalko } 13127cf7d04SAleksandr Rybalko 13227cf7d04SAleksandr Rybalko void 13327cf7d04SAleksandr Rybalko vthistory_getpos(const struct vt_buf *vb, unsigned int *offset) 13427cf7d04SAleksandr Rybalko { 13527cf7d04SAleksandr Rybalko 13627cf7d04SAleksandr Rybalko *offset = vb->vb_roffset; 13727cf7d04SAleksandr Rybalko } 13827cf7d04SAleksandr Rybalko 1390f49db6eSAleksandr Rybalko #ifndef SC_NO_CUTPASTE /* Only mouse support use it now. */ 14027cf7d04SAleksandr Rybalko /* Translate current view row number to history row. */ 14127cf7d04SAleksandr Rybalko static int 14227cf7d04SAleksandr Rybalko vtbuf_wth(struct vt_buf *vb, int row) 14327cf7d04SAleksandr Rybalko { 14427cf7d04SAleksandr Rybalko 14527cf7d04SAleksandr Rybalko return ((vb->vb_roffset + row) % vb->vb_history_size); 14627cf7d04SAleksandr Rybalko } 1470f49db6eSAleksandr Rybalko #endif 14827cf7d04SAleksandr Rybalko 14927cf7d04SAleksandr Rybalko /* Translate history row to current view row number. */ 15027cf7d04SAleksandr Rybalko static int 151c6e1a987SJean-Sébastien Pédron vtbuf_htw(const struct vt_buf *vb, int row) 15227cf7d04SAleksandr Rybalko { 15327cf7d04SAleksandr Rybalko 15427cf7d04SAleksandr Rybalko /* 15527cf7d04SAleksandr Rybalko * total 1000 rows. 15627cf7d04SAleksandr Rybalko * History offset roffset winrow 15727cf7d04SAleksandr Rybalko * 205 200 ((205 - 200 + 1000) % 1000) = 5 15827cf7d04SAleksandr Rybalko * 90 990 ((90 - 990 + 1000) % 1000) = 100 15927cf7d04SAleksandr Rybalko */ 16027cf7d04SAleksandr Rybalko return ((row - vb->vb_roffset + vb->vb_history_size) % 16127cf7d04SAleksandr Rybalko vb->vb_history_size); 16227cf7d04SAleksandr Rybalko } 16327cf7d04SAleksandr Rybalko 16427cf7d04SAleksandr Rybalko int 165c6e1a987SJean-Sébastien Pédron vtbuf_iscursor(const struct vt_buf *vb, int row, int col) 16627cf7d04SAleksandr Rybalko { 16727cf7d04SAleksandr Rybalko int sc, sr, ec, er, tmp; 16827cf7d04SAleksandr Rybalko 16927cf7d04SAleksandr Rybalko if ((vb->vb_flags & (VBF_CURSOR|VBF_SCROLL)) == VBF_CURSOR && 17027cf7d04SAleksandr Rybalko (vb->vb_cursor.tp_row == row) && (vb->vb_cursor.tp_col == col)) 17127cf7d04SAleksandr Rybalko return (1); 17227cf7d04SAleksandr Rybalko 17327cf7d04SAleksandr Rybalko /* Mark cut/paste region. */ 17427cf7d04SAleksandr Rybalko 17527cf7d04SAleksandr Rybalko /* 17627cf7d04SAleksandr Rybalko * Luckily screen view is not like circular buffer, so we will 17727cf7d04SAleksandr Rybalko * calculate in screen coordinates. Translate first. 17827cf7d04SAleksandr Rybalko */ 17927cf7d04SAleksandr Rybalko sc = vb->vb_mark_start.tp_col; 18027cf7d04SAleksandr Rybalko sr = vtbuf_htw(vb, vb->vb_mark_start.tp_row); 18127cf7d04SAleksandr Rybalko ec = vb->vb_mark_end.tp_col; 18227cf7d04SAleksandr Rybalko er = vtbuf_htw(vb, vb->vb_mark_end.tp_row); 18327cf7d04SAleksandr Rybalko 18427cf7d04SAleksandr Rybalko 18527cf7d04SAleksandr Rybalko /* Swap start and end if start > end. */ 18627cf7d04SAleksandr Rybalko if (POS_INDEX(sc, sr) > POS_INDEX(ec, er)) { 18727cf7d04SAleksandr Rybalko tmp = sc; sc = ec; ec = tmp; 18827cf7d04SAleksandr Rybalko tmp = sr; sr = er; er = tmp; 18927cf7d04SAleksandr Rybalko } 19027cf7d04SAleksandr Rybalko 19127cf7d04SAleksandr Rybalko if ((POS_INDEX(sc, sr) <= POS_INDEX(col, row)) && 19227cf7d04SAleksandr Rybalko (POS_INDEX(col, row) < POS_INDEX(ec, er))) 19327cf7d04SAleksandr Rybalko return (1); 19427cf7d04SAleksandr Rybalko 19527cf7d04SAleksandr Rybalko return (0); 19627cf7d04SAleksandr Rybalko } 19727cf7d04SAleksandr Rybalko 19827cf7d04SAleksandr Rybalko static inline void 19900c33067SJean-Sébastien Pédron vtbuf_dirty_locked(struct vt_buf *vb, const term_rect_t *area) 20027cf7d04SAleksandr Rybalko { 20127cf7d04SAleksandr Rybalko 20227cf7d04SAleksandr Rybalko if (vb->vb_dirtyrect.tr_begin.tp_row > area->tr_begin.tp_row) 20327cf7d04SAleksandr Rybalko vb->vb_dirtyrect.tr_begin.tp_row = area->tr_begin.tp_row; 20427cf7d04SAleksandr Rybalko if (vb->vb_dirtyrect.tr_begin.tp_col > area->tr_begin.tp_col) 20527cf7d04SAleksandr Rybalko vb->vb_dirtyrect.tr_begin.tp_col = area->tr_begin.tp_col; 20627cf7d04SAleksandr Rybalko if (vb->vb_dirtyrect.tr_end.tp_row < area->tr_end.tp_row) 20727cf7d04SAleksandr Rybalko vb->vb_dirtyrect.tr_end.tp_row = area->tr_end.tp_row; 20827cf7d04SAleksandr Rybalko if (vb->vb_dirtyrect.tr_end.tp_col < area->tr_end.tp_col) 20927cf7d04SAleksandr Rybalko vb->vb_dirtyrect.tr_end.tp_col = area->tr_end.tp_col; 21000c33067SJean-Sébastien Pédron } 21100c33067SJean-Sébastien Pédron 21282276bbbSJean-Sébastien Pédron void 21300c33067SJean-Sébastien Pédron vtbuf_dirty(struct vt_buf *vb, const term_rect_t *area) 21400c33067SJean-Sébastien Pédron { 21500c33067SJean-Sébastien Pédron 21600c33067SJean-Sébastien Pédron VTBUF_LOCK(vb); 21700c33067SJean-Sébastien Pédron vtbuf_dirty_locked(vb, area); 21827cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 21927cf7d04SAleksandr Rybalko } 22027cf7d04SAleksandr Rybalko 22127cf7d04SAleksandr Rybalko static inline void 22200c33067SJean-Sébastien Pédron vtbuf_dirty_cell_locked(struct vt_buf *vb, const term_pos_t *p) 22327cf7d04SAleksandr Rybalko { 22427cf7d04SAleksandr Rybalko term_rect_t area; 22527cf7d04SAleksandr Rybalko 22627cf7d04SAleksandr Rybalko area.tr_begin = *p; 22727cf7d04SAleksandr Rybalko area.tr_end.tp_row = p->tp_row + 1; 22827cf7d04SAleksandr Rybalko area.tr_end.tp_col = p->tp_col + 1; 22900c33067SJean-Sébastien Pédron vtbuf_dirty_locked(vb, &area); 23027cf7d04SAleksandr Rybalko } 23127cf7d04SAleksandr Rybalko 23227cf7d04SAleksandr Rybalko static void 23327cf7d04SAleksandr Rybalko vtbuf_make_undirty(struct vt_buf *vb) 23427cf7d04SAleksandr Rybalko { 23527cf7d04SAleksandr Rybalko 23627cf7d04SAleksandr Rybalko vb->vb_dirtyrect.tr_begin = vb->vb_scr_size; 23727cf7d04SAleksandr Rybalko vb->vb_dirtyrect.tr_end.tp_row = vb->vb_dirtyrect.tr_end.tp_col = 0; 23827cf7d04SAleksandr Rybalko } 23927cf7d04SAleksandr Rybalko 24027cf7d04SAleksandr Rybalko void 241*c3a05e54SJean-Sébastien Pédron vtbuf_undirty(struct vt_buf *vb, term_rect_t *r) 24227cf7d04SAleksandr Rybalko { 24327cf7d04SAleksandr Rybalko 24427cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 24527cf7d04SAleksandr Rybalko *r = vb->vb_dirtyrect; 24627cf7d04SAleksandr Rybalko vtbuf_make_undirty(vb); 24727cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 24827cf7d04SAleksandr Rybalko } 24927cf7d04SAleksandr Rybalko 25027cf7d04SAleksandr Rybalko void 25127cf7d04SAleksandr Rybalko vtbuf_copy(struct vt_buf *vb, const term_rect_t *r, const term_pos_t *p2) 25227cf7d04SAleksandr Rybalko { 25327cf7d04SAleksandr Rybalko const term_pos_t *p1 = &r->tr_begin; 25427cf7d04SAleksandr Rybalko term_rect_t area; 25527cf7d04SAleksandr Rybalko unsigned int rows, cols; 25627cf7d04SAleksandr Rybalko int pr, rdiff; 25727cf7d04SAleksandr Rybalko 25827cf7d04SAleksandr Rybalko KASSERT(r->tr_begin.tp_row < vb->vb_scr_size.tp_row, 25927cf7d04SAleksandr Rybalko ("vtbuf_copy begin.tp_row %d must be less than screen width %d", 26027cf7d04SAleksandr Rybalko r->tr_begin.tp_row, vb->vb_scr_size.tp_row)); 26127cf7d04SAleksandr Rybalko KASSERT(r->tr_begin.tp_col < vb->vb_scr_size.tp_col, 26227cf7d04SAleksandr Rybalko ("vtbuf_copy begin.tp_col %d must be less than screen height %d", 26327cf7d04SAleksandr Rybalko r->tr_begin.tp_col, vb->vb_scr_size.tp_col)); 26427cf7d04SAleksandr Rybalko 26527cf7d04SAleksandr Rybalko KASSERT(r->tr_end.tp_row <= vb->vb_scr_size.tp_row, 26627cf7d04SAleksandr Rybalko ("vtbuf_copy end.tp_row %d must be less than screen width %d", 26727cf7d04SAleksandr Rybalko r->tr_end.tp_row, vb->vb_scr_size.tp_row)); 26827cf7d04SAleksandr Rybalko KASSERT(r->tr_end.tp_col <= vb->vb_scr_size.tp_col, 26927cf7d04SAleksandr Rybalko ("vtbuf_copy end.tp_col %d must be less than screen height %d", 27027cf7d04SAleksandr Rybalko r->tr_end.tp_col, vb->vb_scr_size.tp_col)); 27127cf7d04SAleksandr Rybalko 27227cf7d04SAleksandr Rybalko KASSERT(p2->tp_row < vb->vb_scr_size.tp_row, 27327cf7d04SAleksandr Rybalko ("vtbuf_copy tp_row %d must be less than screen width %d", 27427cf7d04SAleksandr Rybalko p2->tp_row, vb->vb_scr_size.tp_row)); 27527cf7d04SAleksandr Rybalko KASSERT(p2->tp_col < vb->vb_scr_size.tp_col, 27627cf7d04SAleksandr Rybalko ("vtbuf_copy tp_col %d must be less than screen height %d", 27727cf7d04SAleksandr Rybalko p2->tp_col, vb->vb_scr_size.tp_col)); 27827cf7d04SAleksandr Rybalko 27927cf7d04SAleksandr Rybalko rows = r->tr_end.tp_row - r->tr_begin.tp_row; 28027cf7d04SAleksandr Rybalko rdiff = r->tr_begin.tp_row - p2->tp_row; 28127cf7d04SAleksandr Rybalko cols = r->tr_end.tp_col - r->tr_begin.tp_col; 28227cf7d04SAleksandr Rybalko if (r->tr_begin.tp_row > p2->tp_row && r->tr_begin.tp_col == 0 && 28327cf7d04SAleksandr Rybalko r->tr_end.tp_col == vb->vb_scr_size.tp_col && /* Full row. */ 28427cf7d04SAleksandr Rybalko (rows + rdiff) == vb->vb_scr_size.tp_row && /* Whole screen. */ 28513c6f8a0SAleksandr Rybalko rdiff > 0) { /* Only forward direction. Do not eat history. */ 28627cf7d04SAleksandr Rybalko vthistory_addlines(vb, rdiff); 28727cf7d04SAleksandr Rybalko } else if (p2->tp_row < p1->tp_row) { 28827cf7d04SAleksandr Rybalko /* Handle overlapping copies of line segments. */ 28927cf7d04SAleksandr Rybalko /* Move data up. */ 29027cf7d04SAleksandr Rybalko for (pr = 0; pr < rows; pr++) 29127cf7d04SAleksandr Rybalko memmove( 29227cf7d04SAleksandr Rybalko &VTBUF_FIELD(vb, p2->tp_row + pr, p2->tp_col), 29327cf7d04SAleksandr Rybalko &VTBUF_FIELD(vb, p1->tp_row + pr, p1->tp_col), 29427cf7d04SAleksandr Rybalko cols * sizeof(term_char_t)); 29527cf7d04SAleksandr Rybalko } else { 29627cf7d04SAleksandr Rybalko /* Move data down. */ 29727cf7d04SAleksandr Rybalko for (pr = rows - 1; pr >= 0; pr--) 29827cf7d04SAleksandr Rybalko memmove( 29927cf7d04SAleksandr Rybalko &VTBUF_FIELD(vb, p2->tp_row + pr, p2->tp_col), 30027cf7d04SAleksandr Rybalko &VTBUF_FIELD(vb, p1->tp_row + pr, p1->tp_col), 30127cf7d04SAleksandr Rybalko cols * sizeof(term_char_t)); 30227cf7d04SAleksandr Rybalko } 30327cf7d04SAleksandr Rybalko 30427cf7d04SAleksandr Rybalko area.tr_begin = *p2; 30527cf7d04SAleksandr Rybalko area.tr_end.tp_row = MIN(p2->tp_row + rows, vb->vb_scr_size.tp_row); 30627cf7d04SAleksandr Rybalko area.tr_end.tp_col = MIN(p2->tp_col + cols, vb->vb_scr_size.tp_col); 30727cf7d04SAleksandr Rybalko vtbuf_dirty(vb, &area); 30827cf7d04SAleksandr Rybalko } 30927cf7d04SAleksandr Rybalko 31027cf7d04SAleksandr Rybalko static void 31127cf7d04SAleksandr Rybalko vtbuf_fill(struct vt_buf *vb, const term_rect_t *r, term_char_t c) 31227cf7d04SAleksandr Rybalko { 31327cf7d04SAleksandr Rybalko unsigned int pr, pc; 31427cf7d04SAleksandr Rybalko term_char_t *row; 31527cf7d04SAleksandr Rybalko 31627cf7d04SAleksandr Rybalko for (pr = r->tr_begin.tp_row; pr < r->tr_end.tp_row; pr++) { 31727cf7d04SAleksandr Rybalko row = vb->vb_rows[(vb->vb_curroffset + pr) % 31827cf7d04SAleksandr Rybalko VTBUF_MAX_HEIGHT(vb)]; 31927cf7d04SAleksandr Rybalko for (pc = r->tr_begin.tp_col; pc < r->tr_end.tp_col; pc++) { 32027cf7d04SAleksandr Rybalko row[pc] = c; 32127cf7d04SAleksandr Rybalko } 32227cf7d04SAleksandr Rybalko } 32327cf7d04SAleksandr Rybalko } 32427cf7d04SAleksandr Rybalko 32527cf7d04SAleksandr Rybalko void 32627cf7d04SAleksandr Rybalko vtbuf_fill_locked(struct vt_buf *vb, const term_rect_t *r, term_char_t c) 32727cf7d04SAleksandr Rybalko { 32827cf7d04SAleksandr Rybalko KASSERT(r->tr_begin.tp_row < vb->vb_scr_size.tp_row, 329ba23b435SEd Maste ("vtbuf_fill_locked begin.tp_row %d must be < screen height %d", 33027cf7d04SAleksandr Rybalko r->tr_begin.tp_row, vb->vb_scr_size.tp_row)); 33127cf7d04SAleksandr Rybalko KASSERT(r->tr_begin.tp_col < vb->vb_scr_size.tp_col, 332ba23b435SEd Maste ("vtbuf_fill_locked begin.tp_col %d must be < screen width %d", 33327cf7d04SAleksandr Rybalko r->tr_begin.tp_col, vb->vb_scr_size.tp_col)); 33427cf7d04SAleksandr Rybalko 33527cf7d04SAleksandr Rybalko KASSERT(r->tr_end.tp_row <= vb->vb_scr_size.tp_row, 336ba23b435SEd Maste ("vtbuf_fill_locked end.tp_row %d must be <= screen height %d", 33727cf7d04SAleksandr Rybalko r->tr_end.tp_row, vb->vb_scr_size.tp_row)); 33827cf7d04SAleksandr Rybalko KASSERT(r->tr_end.tp_col <= vb->vb_scr_size.tp_col, 339ba23b435SEd Maste ("vtbuf_fill_locked end.tp_col %d must be <= screen width %d", 34027cf7d04SAleksandr Rybalko r->tr_end.tp_col, vb->vb_scr_size.tp_col)); 34127cf7d04SAleksandr Rybalko 34227cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 34327cf7d04SAleksandr Rybalko vtbuf_fill(vb, r, c); 34400c33067SJean-Sébastien Pédron vtbuf_dirty_locked(vb, r); 34527cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 34627cf7d04SAleksandr Rybalko } 34727cf7d04SAleksandr Rybalko 34827cf7d04SAleksandr Rybalko static void 34927cf7d04SAleksandr Rybalko vtbuf_init_rows(struct vt_buf *vb) 35027cf7d04SAleksandr Rybalko { 35127cf7d04SAleksandr Rybalko int r; 35227cf7d04SAleksandr Rybalko 35327cf7d04SAleksandr Rybalko vb->vb_history_size = MAX(vb->vb_history_size, vb->vb_scr_size.tp_row); 35427cf7d04SAleksandr Rybalko 35527cf7d04SAleksandr Rybalko for (r = 0; r < vb->vb_history_size; r++) 3567344ee18SMarius Strobl vb->vb_rows[r] = &vb->vb_buffer[r * vb->vb_scr_size.tp_col]; 35727cf7d04SAleksandr Rybalko } 35827cf7d04SAleksandr Rybalko 35927cf7d04SAleksandr Rybalko void 36027cf7d04SAleksandr Rybalko vtbuf_init_early(struct vt_buf *vb) 36127cf7d04SAleksandr Rybalko { 3627344ee18SMarius Strobl term_rect_t rect; 36327cf7d04SAleksandr Rybalko 36427cf7d04SAleksandr Rybalko vb->vb_flags |= VBF_CURSOR; 36527cf7d04SAleksandr Rybalko vb->vb_roffset = 0; 36627cf7d04SAleksandr Rybalko vb->vb_curroffset = 0; 36727cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_row = 0; 36827cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col = 0; 36927cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_row = 0; 37027cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col = 0; 37127cf7d04SAleksandr Rybalko 37227cf7d04SAleksandr Rybalko vtbuf_init_rows(vb); 3737344ee18SMarius Strobl rect.tr_begin.tp_row = rect.tr_begin.tp_col = 0; 374cb81897aSJean-Sébastien Pédron rect.tr_end.tp_col = vb->vb_scr_size.tp_col; 375cb81897aSJean-Sébastien Pédron rect.tr_end.tp_row = vb->vb_history_size; 376cb81897aSJean-Sébastien Pédron vtbuf_fill(vb, &rect, VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR)); 37727cf7d04SAleksandr Rybalko vtbuf_make_undirty(vb); 37827cf7d04SAleksandr Rybalko if ((vb->vb_flags & VBF_MTX_INIT) == 0) { 37927cf7d04SAleksandr Rybalko mtx_init(&vb->vb_lock, "vtbuf", NULL, MTX_SPIN); 38027cf7d04SAleksandr Rybalko vb->vb_flags |= VBF_MTX_INIT; 38127cf7d04SAleksandr Rybalko } 38227cf7d04SAleksandr Rybalko } 38327cf7d04SAleksandr Rybalko 38427cf7d04SAleksandr Rybalko void 38527cf7d04SAleksandr Rybalko vtbuf_init(struct vt_buf *vb, const term_pos_t *p) 38627cf7d04SAleksandr Rybalko { 38727cf7d04SAleksandr Rybalko int sz; 38827cf7d04SAleksandr Rybalko 38927cf7d04SAleksandr Rybalko vb->vb_scr_size = *p; 39027cf7d04SAleksandr Rybalko vb->vb_history_size = VBF_DEFAULT_HISTORY_SIZE; 39127cf7d04SAleksandr Rybalko 39227cf7d04SAleksandr Rybalko if ((vb->vb_flags & VBF_STATIC) == 0) { 39327cf7d04SAleksandr Rybalko sz = vb->vb_history_size * p->tp_col * sizeof(term_char_t); 39427cf7d04SAleksandr Rybalko vb->vb_buffer = malloc(sz, M_VTBUF, M_WAITOK | M_ZERO); 39527cf7d04SAleksandr Rybalko 39627cf7d04SAleksandr Rybalko sz = vb->vb_history_size * sizeof(term_char_t *); 39727cf7d04SAleksandr Rybalko vb->vb_rows = malloc(sz, M_VTBUF, M_WAITOK | M_ZERO); 39827cf7d04SAleksandr Rybalko } 39927cf7d04SAleksandr Rybalko 40027cf7d04SAleksandr Rybalko vtbuf_init_early(vb); 40127cf7d04SAleksandr Rybalko } 40227cf7d04SAleksandr Rybalko 40327cf7d04SAleksandr Rybalko void 40427cf7d04SAleksandr Rybalko vtbuf_sethistory_size(struct vt_buf *vb, int size) 40527cf7d04SAleksandr Rybalko { 40627cf7d04SAleksandr Rybalko term_pos_t p; 40727cf7d04SAleksandr Rybalko 40827cf7d04SAleksandr Rybalko /* With same size */ 40927cf7d04SAleksandr Rybalko p.tp_row = vb->vb_scr_size.tp_row; 41027cf7d04SAleksandr Rybalko p.tp_col = vb->vb_scr_size.tp_col; 41127cf7d04SAleksandr Rybalko vtbuf_grow(vb, &p, size); 41227cf7d04SAleksandr Rybalko } 41327cf7d04SAleksandr Rybalko 41427cf7d04SAleksandr Rybalko void 415b7fe4961SJean-Sébastien Pédron vtbuf_grow(struct vt_buf *vb, const term_pos_t *p, unsigned int history_size) 41627cf7d04SAleksandr Rybalko { 41727cf7d04SAleksandr Rybalko term_char_t *old, *new, **rows, **oldrows, **copyrows, *row; 41827cf7d04SAleksandr Rybalko int bufsize, rowssize, w, h, c, r; 41927cf7d04SAleksandr Rybalko term_rect_t rect; 42027cf7d04SAleksandr Rybalko 42127cf7d04SAleksandr Rybalko history_size = MAX(history_size, p->tp_row); 42227cf7d04SAleksandr Rybalko 4238a25d545SAleksandr Rybalko /* If new screen/history size bigger or buffer is VBF_STATIC. */ 4248a25d545SAleksandr Rybalko if ((history_size > vb->vb_history_size) || (p->tp_col > 4258a25d545SAleksandr Rybalko vb->vb_scr_size.tp_col) || (vb->vb_flags & VBF_STATIC)) { 42627cf7d04SAleksandr Rybalko /* Allocate new buffer. */ 42727cf7d04SAleksandr Rybalko bufsize = history_size * p->tp_col * sizeof(term_char_t); 42827cf7d04SAleksandr Rybalko new = malloc(bufsize, M_VTBUF, M_WAITOK | M_ZERO); 42927cf7d04SAleksandr Rybalko rowssize = history_size * sizeof(term_pos_t *); 43027cf7d04SAleksandr Rybalko rows = malloc(rowssize, M_VTBUF, M_WAITOK | M_ZERO); 43127cf7d04SAleksandr Rybalko 43227cf7d04SAleksandr Rybalko /* Toggle it. */ 43327cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 43427cf7d04SAleksandr Rybalko old = vb->vb_flags & VBF_STATIC ? NULL : vb->vb_buffer; 43527cf7d04SAleksandr Rybalko oldrows = vb->vb_flags & VBF_STATIC ? NULL : vb->vb_rows; 43627cf7d04SAleksandr Rybalko copyrows = vb->vb_rows; 43727cf7d04SAleksandr Rybalko w = vb->vb_scr_size.tp_col; 43827cf7d04SAleksandr Rybalko h = vb->vb_history_size; 43927cf7d04SAleksandr Rybalko 44027cf7d04SAleksandr Rybalko vb->vb_history_size = history_size; 44127cf7d04SAleksandr Rybalko vb->vb_buffer = new; 44227cf7d04SAleksandr Rybalko vb->vb_rows = rows; 44327cf7d04SAleksandr Rybalko vb->vb_flags &= ~VBF_STATIC; 44427cf7d04SAleksandr Rybalko vb->vb_scr_size = *p; 44527cf7d04SAleksandr Rybalko vtbuf_init_rows(vb); 44627cf7d04SAleksandr Rybalko 44727cf7d04SAleksandr Rybalko /* Copy history and fill extra space. */ 44827cf7d04SAleksandr Rybalko for (r = 0; r < history_size; r ++) { 4497344ee18SMarius Strobl /* 4507344ee18SMarius Strobl * XXX VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR) will 4517344ee18SMarius Strobl * extended lines of kernel text using the wrong 4527344ee18SMarius Strobl * background color. 4537344ee18SMarius Strobl */ 45427cf7d04SAleksandr Rybalko row = rows[r]; 45527cf7d04SAleksandr Rybalko if (r < h) { /* Copy. */ 45627cf7d04SAleksandr Rybalko memmove(rows[r], copyrows[r], 45727cf7d04SAleksandr Rybalko MIN(p->tp_col, w) * sizeof(term_char_t)); 45827cf7d04SAleksandr Rybalko for (c = MIN(p->tp_col, w); c < p->tp_col; 45927cf7d04SAleksandr Rybalko c++) { 4607344ee18SMarius Strobl row[c] = VTBUF_SPACE_CHAR( 4617344ee18SMarius Strobl TERMINAL_NORM_ATTR); 46227cf7d04SAleksandr Rybalko } 46327cf7d04SAleksandr Rybalko } else { /* Just fill. */ 46427cf7d04SAleksandr Rybalko rect.tr_begin.tp_col = 0; 46527cf7d04SAleksandr Rybalko rect.tr_begin.tp_row = r; 46627cf7d04SAleksandr Rybalko rect.tr_end.tp_col = p->tp_col; 46727cf7d04SAleksandr Rybalko rect.tr_end.tp_row = p->tp_row; 4687344ee18SMarius Strobl vtbuf_fill(vb, &rect, 4697344ee18SMarius Strobl VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR)); 47027cf7d04SAleksandr Rybalko break; 47127cf7d04SAleksandr Rybalko } 47227cf7d04SAleksandr Rybalko } 47327cf7d04SAleksandr Rybalko vtbuf_make_undirty(vb); 47427cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 47527cf7d04SAleksandr Rybalko /* Deallocate old buffer. */ 47627cf7d04SAleksandr Rybalko free(old, M_VTBUF); 47727cf7d04SAleksandr Rybalko free(oldrows, M_VTBUF); 4787cd5ec40SEd Maste } else { 4797cd5ec40SEd Maste /* Just update the size. */ 4807cd5ec40SEd Maste vb->vb_scr_size = *p; 48127cf7d04SAleksandr Rybalko } 48227cf7d04SAleksandr Rybalko } 48327cf7d04SAleksandr Rybalko 48427cf7d04SAleksandr Rybalko void 48527cf7d04SAleksandr Rybalko vtbuf_putchar(struct vt_buf *vb, const term_pos_t *p, term_char_t c) 48627cf7d04SAleksandr Rybalko { 48727cf7d04SAleksandr Rybalko term_char_t *row; 48827cf7d04SAleksandr Rybalko 48927cf7d04SAleksandr Rybalko KASSERT(p->tp_row < vb->vb_scr_size.tp_row, 49027cf7d04SAleksandr Rybalko ("vtbuf_putchar tp_row %d must be less than screen width %d", 49127cf7d04SAleksandr Rybalko p->tp_row, vb->vb_scr_size.tp_row)); 49227cf7d04SAleksandr Rybalko KASSERT(p->tp_col < vb->vb_scr_size.tp_col, 49327cf7d04SAleksandr Rybalko ("vtbuf_putchar tp_col %d must be less than screen height %d", 49427cf7d04SAleksandr Rybalko p->tp_col, vb->vb_scr_size.tp_col)); 49527cf7d04SAleksandr Rybalko 49627cf7d04SAleksandr Rybalko row = vb->vb_rows[(vb->vb_curroffset + p->tp_row) % 49727cf7d04SAleksandr Rybalko VTBUF_MAX_HEIGHT(vb)]; 49827cf7d04SAleksandr Rybalko if (row[p->tp_col] != c) { 49927cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 50027cf7d04SAleksandr Rybalko row[p->tp_col] = c; 50100c33067SJean-Sébastien Pédron vtbuf_dirty_cell_locked(vb, p); 50227cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 50327cf7d04SAleksandr Rybalko } 50427cf7d04SAleksandr Rybalko } 50527cf7d04SAleksandr Rybalko 50627cf7d04SAleksandr Rybalko void 50727cf7d04SAleksandr Rybalko vtbuf_cursor_position(struct vt_buf *vb, const term_pos_t *p) 50827cf7d04SAleksandr Rybalko { 50927cf7d04SAleksandr Rybalko 51027cf7d04SAleksandr Rybalko if (vb->vb_flags & VBF_CURSOR) { 51100c33067SJean-Sébastien Pédron VTBUF_LOCK(vb); 51200c33067SJean-Sébastien Pédron vtbuf_dirty_cell_locked(vb, &vb->vb_cursor); 51327cf7d04SAleksandr Rybalko vb->vb_cursor = *p; 51400c33067SJean-Sébastien Pédron vtbuf_dirty_cell_locked(vb, &vb->vb_cursor); 51500c33067SJean-Sébastien Pédron VTBUF_UNLOCK(vb); 51627cf7d04SAleksandr Rybalko } else { 51727cf7d04SAleksandr Rybalko vb->vb_cursor = *p; 51827cf7d04SAleksandr Rybalko } 51927cf7d04SAleksandr Rybalko } 52027cf7d04SAleksandr Rybalko 5210f49db6eSAleksandr Rybalko #ifndef SC_NO_CUTPASTE 52227cf7d04SAleksandr Rybalko static void 52327cf7d04SAleksandr Rybalko vtbuf_flush_mark(struct vt_buf *vb) 52427cf7d04SAleksandr Rybalko { 52527cf7d04SAleksandr Rybalko term_rect_t area; 52627cf7d04SAleksandr Rybalko int s, e; 52727cf7d04SAleksandr Rybalko 52827cf7d04SAleksandr Rybalko /* Notify renderer to update marked region. */ 52927cf7d04SAleksandr Rybalko if (vb->vb_mark_start.tp_col || vb->vb_mark_end.tp_col || 53027cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_row || vb->vb_mark_end.tp_row) { 53127cf7d04SAleksandr Rybalko 53227cf7d04SAleksandr Rybalko s = vtbuf_htw(vb, vb->vb_mark_start.tp_row); 53327cf7d04SAleksandr Rybalko e = vtbuf_htw(vb, vb->vb_mark_end.tp_row); 53427cf7d04SAleksandr Rybalko 53527cf7d04SAleksandr Rybalko area.tr_begin.tp_col = 0; 53627cf7d04SAleksandr Rybalko area.tr_begin.tp_row = MIN(s, e); 53727cf7d04SAleksandr Rybalko 53827cf7d04SAleksandr Rybalko area.tr_end.tp_col = vb->vb_scr_size.tp_col; 53927cf7d04SAleksandr Rybalko area.tr_end.tp_row = MAX(s, e) + 1; 54027cf7d04SAleksandr Rybalko 54127cf7d04SAleksandr Rybalko vtbuf_dirty(vb, &area); 54227cf7d04SAleksandr Rybalko } 54327cf7d04SAleksandr Rybalko } 54427cf7d04SAleksandr Rybalko 54527cf7d04SAleksandr Rybalko int 54627cf7d04SAleksandr Rybalko vtbuf_get_marked_len(struct vt_buf *vb) 54727cf7d04SAleksandr Rybalko { 54827cf7d04SAleksandr Rybalko int ei, si, sz; 54927cf7d04SAleksandr Rybalko term_pos_t s, e; 55027cf7d04SAleksandr Rybalko 55127cf7d04SAleksandr Rybalko /* Swap according to window coordinates. */ 55227cf7d04SAleksandr Rybalko if (POS_INDEX(vtbuf_htw(vb, vb->vb_mark_start.tp_row), 55327cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col) > 55427cf7d04SAleksandr Rybalko POS_INDEX(vtbuf_htw(vb, vb->vb_mark_end.tp_row), 55527cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col)) { 55627cf7d04SAleksandr Rybalko POS_COPY(e, vb->vb_mark_start); 55727cf7d04SAleksandr Rybalko POS_COPY(s, vb->vb_mark_end); 55827cf7d04SAleksandr Rybalko } else { 55927cf7d04SAleksandr Rybalko POS_COPY(s, vb->vb_mark_start); 56027cf7d04SAleksandr Rybalko POS_COPY(e, vb->vb_mark_end); 56127cf7d04SAleksandr Rybalko } 56227cf7d04SAleksandr Rybalko 56327cf7d04SAleksandr Rybalko si = s.tp_row * vb->vb_scr_size.tp_col + s.tp_col; 56427cf7d04SAleksandr Rybalko ei = e.tp_row * vb->vb_scr_size.tp_col + e.tp_col; 56527cf7d04SAleksandr Rybalko 56627cf7d04SAleksandr Rybalko /* Number symbols and number of rows to inject \n */ 56744f751a2SAleksandr Rybalko sz = ei - si + ((e.tp_row - s.tp_row) * 2); 56827cf7d04SAleksandr Rybalko 56927cf7d04SAleksandr Rybalko return (sz * sizeof(term_char_t)); 57027cf7d04SAleksandr Rybalko } 57127cf7d04SAleksandr Rybalko 57227cf7d04SAleksandr Rybalko void 57327cf7d04SAleksandr Rybalko vtbuf_extract_marked(struct vt_buf *vb, term_char_t *buf, int sz) 57427cf7d04SAleksandr Rybalko { 57527cf7d04SAleksandr Rybalko int i, r, c, cs, ce; 57627cf7d04SAleksandr Rybalko term_pos_t s, e; 57727cf7d04SAleksandr Rybalko 57827cf7d04SAleksandr Rybalko /* Swap according to window coordinates. */ 57927cf7d04SAleksandr Rybalko if (POS_INDEX(vtbuf_htw(vb, vb->vb_mark_start.tp_row), 58027cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col) > 58127cf7d04SAleksandr Rybalko POS_INDEX(vtbuf_htw(vb, vb->vb_mark_end.tp_row), 58227cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col)) { 58327cf7d04SAleksandr Rybalko POS_COPY(e, vb->vb_mark_start); 58427cf7d04SAleksandr Rybalko POS_COPY(s, vb->vb_mark_end); 58527cf7d04SAleksandr Rybalko } else { 58627cf7d04SAleksandr Rybalko POS_COPY(s, vb->vb_mark_start); 58727cf7d04SAleksandr Rybalko POS_COPY(e, vb->vb_mark_end); 58827cf7d04SAleksandr Rybalko } 58927cf7d04SAleksandr Rybalko 59027cf7d04SAleksandr Rybalko i = 0; 59127cf7d04SAleksandr Rybalko for (r = s.tp_row; r <= e.tp_row; r ++) { 59227cf7d04SAleksandr Rybalko cs = (r == s.tp_row)?s.tp_col:0; 59327cf7d04SAleksandr Rybalko ce = (r == e.tp_row)?e.tp_col:vb->vb_scr_size.tp_col; 59427cf7d04SAleksandr Rybalko for (c = cs; c < ce; c ++) { 59527cf7d04SAleksandr Rybalko buf[i++] = vb->vb_rows[r][c]; 59627cf7d04SAleksandr Rybalko } 59727cf7d04SAleksandr Rybalko /* Add new line for all rows, but not for last one. */ 59827cf7d04SAleksandr Rybalko if (r != e.tp_row) { 59927cf7d04SAleksandr Rybalko buf[i++] = '\r'; 60027cf7d04SAleksandr Rybalko buf[i++] = '\n'; 60127cf7d04SAleksandr Rybalko } 60227cf7d04SAleksandr Rybalko } 60327cf7d04SAleksandr Rybalko } 60427cf7d04SAleksandr Rybalko 60527cf7d04SAleksandr Rybalko int 60627cf7d04SAleksandr Rybalko vtbuf_set_mark(struct vt_buf *vb, int type, int col, int row) 60727cf7d04SAleksandr Rybalko { 60827cf7d04SAleksandr Rybalko term_char_t *r; 60927cf7d04SAleksandr Rybalko int i; 61027cf7d04SAleksandr Rybalko 61127cf7d04SAleksandr Rybalko switch (type) { 61227cf7d04SAleksandr Rybalko case VTB_MARK_END: /* B1 UP */ 61327cf7d04SAleksandr Rybalko if (vb->vb_mark_last != VTB_MARK_MOVE) 61427cf7d04SAleksandr Rybalko return (0); 61527cf7d04SAleksandr Rybalko /* FALLTHROUGH */ 61627cf7d04SAleksandr Rybalko case VTB_MARK_MOVE: 61727cf7d04SAleksandr Rybalko case VTB_MARK_EXTEND: 61827cf7d04SAleksandr Rybalko vtbuf_flush_mark(vb); /* Clean old mark. */ 61927cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col = col; 62027cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_row = vtbuf_wth(vb, row); 62127cf7d04SAleksandr Rybalko break; 62227cf7d04SAleksandr Rybalko case VTB_MARK_START: 62327cf7d04SAleksandr Rybalko vtbuf_flush_mark(vb); /* Clean old mark. */ 62427cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col = col; 62527cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_row = vtbuf_wth(vb, row); 62627cf7d04SAleksandr Rybalko /* Start again, so clear end point. */ 62727cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col = col; 62827cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_row = vtbuf_wth(vb, row); 62927cf7d04SAleksandr Rybalko break; 63027cf7d04SAleksandr Rybalko case VTB_MARK_WORD: 63127cf7d04SAleksandr Rybalko vtbuf_flush_mark(vb); /* Clean old mark. */ 63227cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_row = vb->vb_mark_end.tp_row = 63327cf7d04SAleksandr Rybalko vtbuf_wth(vb, row); 63427cf7d04SAleksandr Rybalko r = vb->vb_rows[vb->vb_mark_start.tp_row]; 63527cf7d04SAleksandr Rybalko for (i = col; i >= 0; i --) { 63627cf7d04SAleksandr Rybalko if (TCHAR_CHARACTER(r[i]) == ' ') { 63727cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col = i + 1; 63827cf7d04SAleksandr Rybalko break; 63927cf7d04SAleksandr Rybalko } 64027cf7d04SAleksandr Rybalko } 64127cf7d04SAleksandr Rybalko for (i = col; i < vb->vb_scr_size.tp_col; i ++) { 64227cf7d04SAleksandr Rybalko if (TCHAR_CHARACTER(r[i]) == ' ') { 64327cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col = i; 64427cf7d04SAleksandr Rybalko break; 64527cf7d04SAleksandr Rybalko } 64627cf7d04SAleksandr Rybalko } 64727cf7d04SAleksandr Rybalko if (vb->vb_mark_start.tp_col > vb->vb_mark_end.tp_col) 64827cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col = vb->vb_mark_end.tp_col; 64927cf7d04SAleksandr Rybalko break; 65027cf7d04SAleksandr Rybalko case VTB_MARK_ROW: 65127cf7d04SAleksandr Rybalko vtbuf_flush_mark(vb); /* Clean old mark. */ 65227cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col = 0; 65327cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col = vb->vb_scr_size.tp_col; 65427cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_row = vb->vb_mark_end.tp_row = 65527cf7d04SAleksandr Rybalko vtbuf_wth(vb, row); 65627cf7d04SAleksandr Rybalko break; 65727cf7d04SAleksandr Rybalko case VTB_MARK_NONE: 65827cf7d04SAleksandr Rybalko vb->vb_mark_last = type; 65927cf7d04SAleksandr Rybalko /* FALLTHROUGH */ 66027cf7d04SAleksandr Rybalko default: 66127cf7d04SAleksandr Rybalko /* panic? */ 66227cf7d04SAleksandr Rybalko return (0); 66327cf7d04SAleksandr Rybalko } 66427cf7d04SAleksandr Rybalko 66527cf7d04SAleksandr Rybalko vb->vb_mark_last = type; 66627cf7d04SAleksandr Rybalko /* Draw new marked region. */ 66727cf7d04SAleksandr Rybalko vtbuf_flush_mark(vb); 66827cf7d04SAleksandr Rybalko return (1); 66927cf7d04SAleksandr Rybalko } 6700f49db6eSAleksandr Rybalko #endif 67127cf7d04SAleksandr Rybalko 67227cf7d04SAleksandr Rybalko void 67327cf7d04SAleksandr Rybalko vtbuf_cursor_visibility(struct vt_buf *vb, int yes) 67427cf7d04SAleksandr Rybalko { 67527cf7d04SAleksandr Rybalko int oflags, nflags; 67627cf7d04SAleksandr Rybalko 67727cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 67827cf7d04SAleksandr Rybalko oflags = vb->vb_flags; 67927cf7d04SAleksandr Rybalko if (yes) 68027cf7d04SAleksandr Rybalko vb->vb_flags |= VBF_CURSOR; 68127cf7d04SAleksandr Rybalko else 68227cf7d04SAleksandr Rybalko vb->vb_flags &= ~VBF_CURSOR; 68327cf7d04SAleksandr Rybalko nflags = vb->vb_flags; 68427cf7d04SAleksandr Rybalko 68527cf7d04SAleksandr Rybalko if (oflags != nflags) 68600c33067SJean-Sébastien Pédron vtbuf_dirty_cell_locked(vb, &vb->vb_cursor); 68700c33067SJean-Sébastien Pédron VTBUF_UNLOCK(vb); 68827cf7d04SAleksandr Rybalko } 68927cf7d04SAleksandr Rybalko 69027cf7d04SAleksandr Rybalko void 69127cf7d04SAleksandr Rybalko vtbuf_scroll_mode(struct vt_buf *vb, int yes) 69227cf7d04SAleksandr Rybalko { 69327cf7d04SAleksandr Rybalko int oflags, nflags; 69427cf7d04SAleksandr Rybalko 69527cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 69627cf7d04SAleksandr Rybalko oflags = vb->vb_flags; 69727cf7d04SAleksandr Rybalko if (yes) 69827cf7d04SAleksandr Rybalko vb->vb_flags |= VBF_SCROLL; 69927cf7d04SAleksandr Rybalko else 70027cf7d04SAleksandr Rybalko vb->vb_flags &= ~VBF_SCROLL; 70127cf7d04SAleksandr Rybalko nflags = vb->vb_flags; 70227cf7d04SAleksandr Rybalko 70327cf7d04SAleksandr Rybalko if (oflags != nflags) 70400c33067SJean-Sébastien Pédron vtbuf_dirty_cell_locked(vb, &vb->vb_cursor); 70500c33067SJean-Sébastien Pédron VTBUF_UNLOCK(vb); 70627cf7d04SAleksandr Rybalko } 70727cf7d04SAleksandr Rybalko 708