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> 41*7344ee18SMarius 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 15127cf7d04SAleksandr Rybalko vtbuf_htw(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 16527cf7d04SAleksandr Rybalko vtbuf_iscursor(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 uint64_t 19927cf7d04SAleksandr Rybalko vtbuf_dirty_axis(unsigned int begin, unsigned int end) 20027cf7d04SAleksandr Rybalko { 20127cf7d04SAleksandr Rybalko uint64_t left, right, mask; 20227cf7d04SAleksandr Rybalko 20327cf7d04SAleksandr Rybalko /* 20427cf7d04SAleksandr Rybalko * Mark all bits between begin % 64 and end % 64 dirty. 20527cf7d04SAleksandr Rybalko * This code is functionally equivalent to: 20627cf7d04SAleksandr Rybalko * 20727cf7d04SAleksandr Rybalko * for (i = begin; i < end; i++) 20827cf7d04SAleksandr Rybalko * mask |= (uint64_t)1 << (i % 64); 20927cf7d04SAleksandr Rybalko */ 21027cf7d04SAleksandr Rybalko 21127cf7d04SAleksandr Rybalko /* Obvious case. Mark everything dirty. */ 21227cf7d04SAleksandr Rybalko if (end - begin >= 64) 21327cf7d04SAleksandr Rybalko return (VBM_DIRTY); 21427cf7d04SAleksandr Rybalko 21527cf7d04SAleksandr Rybalko /* 1....0; used bits on the left. */ 21627cf7d04SAleksandr Rybalko left = VBM_DIRTY << begin % 64; 21727cf7d04SAleksandr Rybalko /* 0....1; used bits on the right. */ 21827cf7d04SAleksandr Rybalko right = VBM_DIRTY >> -end % 64; 21927cf7d04SAleksandr Rybalko 22027cf7d04SAleksandr Rybalko /* 22127cf7d04SAleksandr Rybalko * Only take the intersection. If the result of that is 0, it 22227cf7d04SAleksandr Rybalko * means that the selection crossed a 64 bit boundary along the 22327cf7d04SAleksandr Rybalko * way, which means we have to take the complement. 22427cf7d04SAleksandr Rybalko */ 22527cf7d04SAleksandr Rybalko mask = left & right; 22627cf7d04SAleksandr Rybalko if (mask == 0) 22727cf7d04SAleksandr Rybalko mask = left | right; 22827cf7d04SAleksandr Rybalko return (mask); 22927cf7d04SAleksandr Rybalko } 23027cf7d04SAleksandr Rybalko 23127cf7d04SAleksandr Rybalko static inline void 23227cf7d04SAleksandr Rybalko vtbuf_dirty(struct vt_buf *vb, const term_rect_t *area) 23327cf7d04SAleksandr Rybalko { 23427cf7d04SAleksandr Rybalko 23527cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 23627cf7d04SAleksandr Rybalko if (vb->vb_dirtyrect.tr_begin.tp_row > area->tr_begin.tp_row) 23727cf7d04SAleksandr Rybalko vb->vb_dirtyrect.tr_begin.tp_row = area->tr_begin.tp_row; 23827cf7d04SAleksandr Rybalko if (vb->vb_dirtyrect.tr_begin.tp_col > area->tr_begin.tp_col) 23927cf7d04SAleksandr Rybalko vb->vb_dirtyrect.tr_begin.tp_col = area->tr_begin.tp_col; 24027cf7d04SAleksandr Rybalko if (vb->vb_dirtyrect.tr_end.tp_row < area->tr_end.tp_row) 24127cf7d04SAleksandr Rybalko vb->vb_dirtyrect.tr_end.tp_row = area->tr_end.tp_row; 24227cf7d04SAleksandr Rybalko if (vb->vb_dirtyrect.tr_end.tp_col < area->tr_end.tp_col) 24327cf7d04SAleksandr Rybalko vb->vb_dirtyrect.tr_end.tp_col = area->tr_end.tp_col; 24427cf7d04SAleksandr Rybalko vb->vb_dirtymask.vbm_row |= 24527cf7d04SAleksandr Rybalko vtbuf_dirty_axis(area->tr_begin.tp_row, area->tr_end.tp_row); 24627cf7d04SAleksandr Rybalko vb->vb_dirtymask.vbm_col |= 24727cf7d04SAleksandr Rybalko vtbuf_dirty_axis(area->tr_begin.tp_col, area->tr_end.tp_col); 24827cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 24927cf7d04SAleksandr Rybalko } 25027cf7d04SAleksandr Rybalko 25127cf7d04SAleksandr Rybalko static inline void 25227cf7d04SAleksandr Rybalko vtbuf_dirty_cell(struct vt_buf *vb, const term_pos_t *p) 25327cf7d04SAleksandr Rybalko { 25427cf7d04SAleksandr Rybalko term_rect_t area; 25527cf7d04SAleksandr Rybalko 25627cf7d04SAleksandr Rybalko area.tr_begin = *p; 25727cf7d04SAleksandr Rybalko area.tr_end.tp_row = p->tp_row + 1; 25827cf7d04SAleksandr Rybalko area.tr_end.tp_col = p->tp_col + 1; 25927cf7d04SAleksandr Rybalko vtbuf_dirty(vb, &area); 26027cf7d04SAleksandr Rybalko } 26127cf7d04SAleksandr Rybalko 26227cf7d04SAleksandr Rybalko static void 26327cf7d04SAleksandr Rybalko vtbuf_make_undirty(struct vt_buf *vb) 26427cf7d04SAleksandr Rybalko { 26527cf7d04SAleksandr Rybalko 26627cf7d04SAleksandr Rybalko vb->vb_dirtyrect.tr_begin = vb->vb_scr_size; 26727cf7d04SAleksandr Rybalko vb->vb_dirtyrect.tr_end.tp_row = vb->vb_dirtyrect.tr_end.tp_col = 0; 26827cf7d04SAleksandr Rybalko vb->vb_dirtymask.vbm_row = vb->vb_dirtymask.vbm_col = 0; 26927cf7d04SAleksandr Rybalko } 27027cf7d04SAleksandr Rybalko 27127cf7d04SAleksandr Rybalko void 27227cf7d04SAleksandr Rybalko vtbuf_undirty(struct vt_buf *vb, term_rect_t *r, struct vt_bufmask *m) 27327cf7d04SAleksandr Rybalko { 27427cf7d04SAleksandr Rybalko 27527cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 27627cf7d04SAleksandr Rybalko *r = vb->vb_dirtyrect; 27727cf7d04SAleksandr Rybalko *m = vb->vb_dirtymask; 27827cf7d04SAleksandr Rybalko vtbuf_make_undirty(vb); 27927cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 28027cf7d04SAleksandr Rybalko } 28127cf7d04SAleksandr Rybalko 28227cf7d04SAleksandr Rybalko void 28327cf7d04SAleksandr Rybalko vtbuf_copy(struct vt_buf *vb, const term_rect_t *r, const term_pos_t *p2) 28427cf7d04SAleksandr Rybalko { 28527cf7d04SAleksandr Rybalko const term_pos_t *p1 = &r->tr_begin; 28627cf7d04SAleksandr Rybalko term_rect_t area; 28727cf7d04SAleksandr Rybalko unsigned int rows, cols; 28827cf7d04SAleksandr Rybalko int pr, rdiff; 28927cf7d04SAleksandr Rybalko 29027cf7d04SAleksandr Rybalko KASSERT(r->tr_begin.tp_row < vb->vb_scr_size.tp_row, 29127cf7d04SAleksandr Rybalko ("vtbuf_copy begin.tp_row %d must be less than screen width %d", 29227cf7d04SAleksandr Rybalko r->tr_begin.tp_row, vb->vb_scr_size.tp_row)); 29327cf7d04SAleksandr Rybalko KASSERT(r->tr_begin.tp_col < vb->vb_scr_size.tp_col, 29427cf7d04SAleksandr Rybalko ("vtbuf_copy begin.tp_col %d must be less than screen height %d", 29527cf7d04SAleksandr Rybalko r->tr_begin.tp_col, vb->vb_scr_size.tp_col)); 29627cf7d04SAleksandr Rybalko 29727cf7d04SAleksandr Rybalko KASSERT(r->tr_end.tp_row <= vb->vb_scr_size.tp_row, 29827cf7d04SAleksandr Rybalko ("vtbuf_copy end.tp_row %d must be less than screen width %d", 29927cf7d04SAleksandr Rybalko r->tr_end.tp_row, vb->vb_scr_size.tp_row)); 30027cf7d04SAleksandr Rybalko KASSERT(r->tr_end.tp_col <= vb->vb_scr_size.tp_col, 30127cf7d04SAleksandr Rybalko ("vtbuf_copy end.tp_col %d must be less than screen height %d", 30227cf7d04SAleksandr Rybalko r->tr_end.tp_col, vb->vb_scr_size.tp_col)); 30327cf7d04SAleksandr Rybalko 30427cf7d04SAleksandr Rybalko KASSERT(p2->tp_row < vb->vb_scr_size.tp_row, 30527cf7d04SAleksandr Rybalko ("vtbuf_copy tp_row %d must be less than screen width %d", 30627cf7d04SAleksandr Rybalko p2->tp_row, vb->vb_scr_size.tp_row)); 30727cf7d04SAleksandr Rybalko KASSERT(p2->tp_col < vb->vb_scr_size.tp_col, 30827cf7d04SAleksandr Rybalko ("vtbuf_copy tp_col %d must be less than screen height %d", 30927cf7d04SAleksandr Rybalko p2->tp_col, vb->vb_scr_size.tp_col)); 31027cf7d04SAleksandr Rybalko 31127cf7d04SAleksandr Rybalko rows = r->tr_end.tp_row - r->tr_begin.tp_row; 31227cf7d04SAleksandr Rybalko rdiff = r->tr_begin.tp_row - p2->tp_row; 31327cf7d04SAleksandr Rybalko cols = r->tr_end.tp_col - r->tr_begin.tp_col; 31427cf7d04SAleksandr Rybalko if (r->tr_begin.tp_row > p2->tp_row && r->tr_begin.tp_col == 0 && 31527cf7d04SAleksandr Rybalko r->tr_end.tp_col == vb->vb_scr_size.tp_col && /* Full row. */ 31627cf7d04SAleksandr Rybalko (rows + rdiff) == vb->vb_scr_size.tp_row && /* Whole screen. */ 31727cf7d04SAleksandr Rybalko rdiff > 0) { /* Only forward dirrection. Do not eat history. */ 31827cf7d04SAleksandr Rybalko vthistory_addlines(vb, rdiff); 31927cf7d04SAleksandr Rybalko } else if (p2->tp_row < p1->tp_row) { 32027cf7d04SAleksandr Rybalko /* Handle overlapping copies of line segments. */ 32127cf7d04SAleksandr Rybalko /* Move data up. */ 32227cf7d04SAleksandr Rybalko for (pr = 0; pr < rows; pr++) 32327cf7d04SAleksandr Rybalko memmove( 32427cf7d04SAleksandr Rybalko &VTBUF_FIELD(vb, p2->tp_row + pr, p2->tp_col), 32527cf7d04SAleksandr Rybalko &VTBUF_FIELD(vb, p1->tp_row + pr, p1->tp_col), 32627cf7d04SAleksandr Rybalko cols * sizeof(term_char_t)); 32727cf7d04SAleksandr Rybalko } else { 32827cf7d04SAleksandr Rybalko /* Move data down. */ 32927cf7d04SAleksandr Rybalko for (pr = rows - 1; pr >= 0; pr--) 33027cf7d04SAleksandr Rybalko memmove( 33127cf7d04SAleksandr Rybalko &VTBUF_FIELD(vb, p2->tp_row + pr, p2->tp_col), 33227cf7d04SAleksandr Rybalko &VTBUF_FIELD(vb, p1->tp_row + pr, p1->tp_col), 33327cf7d04SAleksandr Rybalko cols * sizeof(term_char_t)); 33427cf7d04SAleksandr Rybalko } 33527cf7d04SAleksandr Rybalko 33627cf7d04SAleksandr Rybalko area.tr_begin = *p2; 33727cf7d04SAleksandr Rybalko area.tr_end.tp_row = MIN(p2->tp_row + rows, vb->vb_scr_size.tp_row); 33827cf7d04SAleksandr Rybalko area.tr_end.tp_col = MIN(p2->tp_col + cols, vb->vb_scr_size.tp_col); 33927cf7d04SAleksandr Rybalko vtbuf_dirty(vb, &area); 34027cf7d04SAleksandr Rybalko } 34127cf7d04SAleksandr Rybalko 34227cf7d04SAleksandr Rybalko static void 34327cf7d04SAleksandr Rybalko vtbuf_fill(struct vt_buf *vb, const term_rect_t *r, term_char_t c) 34427cf7d04SAleksandr Rybalko { 34527cf7d04SAleksandr Rybalko unsigned int pr, pc; 34627cf7d04SAleksandr Rybalko term_char_t *row; 34727cf7d04SAleksandr Rybalko 34827cf7d04SAleksandr Rybalko for (pr = r->tr_begin.tp_row; pr < r->tr_end.tp_row; pr++) { 34927cf7d04SAleksandr Rybalko row = vb->vb_rows[(vb->vb_curroffset + pr) % 35027cf7d04SAleksandr Rybalko VTBUF_MAX_HEIGHT(vb)]; 35127cf7d04SAleksandr Rybalko for (pc = r->tr_begin.tp_col; pc < r->tr_end.tp_col; pc++) { 35227cf7d04SAleksandr Rybalko row[pc] = c; 35327cf7d04SAleksandr Rybalko } 35427cf7d04SAleksandr Rybalko } 35527cf7d04SAleksandr Rybalko } 35627cf7d04SAleksandr Rybalko 35727cf7d04SAleksandr Rybalko void 35827cf7d04SAleksandr Rybalko vtbuf_fill_locked(struct vt_buf *vb, const term_rect_t *r, term_char_t c) 35927cf7d04SAleksandr Rybalko { 36027cf7d04SAleksandr Rybalko KASSERT(r->tr_begin.tp_row < vb->vb_scr_size.tp_row, 361ba23b435SEd Maste ("vtbuf_fill_locked begin.tp_row %d must be < screen height %d", 36227cf7d04SAleksandr Rybalko r->tr_begin.tp_row, vb->vb_scr_size.tp_row)); 36327cf7d04SAleksandr Rybalko KASSERT(r->tr_begin.tp_col < vb->vb_scr_size.tp_col, 364ba23b435SEd Maste ("vtbuf_fill_locked begin.tp_col %d must be < screen width %d", 36527cf7d04SAleksandr Rybalko r->tr_begin.tp_col, vb->vb_scr_size.tp_col)); 36627cf7d04SAleksandr Rybalko 36727cf7d04SAleksandr Rybalko KASSERT(r->tr_end.tp_row <= vb->vb_scr_size.tp_row, 368ba23b435SEd Maste ("vtbuf_fill_locked end.tp_row %d must be <= screen height %d", 36927cf7d04SAleksandr Rybalko r->tr_end.tp_row, vb->vb_scr_size.tp_row)); 37027cf7d04SAleksandr Rybalko KASSERT(r->tr_end.tp_col <= vb->vb_scr_size.tp_col, 371ba23b435SEd Maste ("vtbuf_fill_locked end.tp_col %d must be <= screen width %d", 37227cf7d04SAleksandr Rybalko r->tr_end.tp_col, vb->vb_scr_size.tp_col)); 37327cf7d04SAleksandr Rybalko 37427cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 37527cf7d04SAleksandr Rybalko vtbuf_fill(vb, r, c); 37627cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 37727cf7d04SAleksandr Rybalko 37827cf7d04SAleksandr Rybalko vtbuf_dirty(vb, r); 37927cf7d04SAleksandr Rybalko } 38027cf7d04SAleksandr Rybalko 38127cf7d04SAleksandr Rybalko static void 38227cf7d04SAleksandr Rybalko vtbuf_init_rows(struct vt_buf *vb) 38327cf7d04SAleksandr Rybalko { 38427cf7d04SAleksandr Rybalko int r; 38527cf7d04SAleksandr Rybalko 38627cf7d04SAleksandr Rybalko vb->vb_history_size = MAX(vb->vb_history_size, vb->vb_scr_size.tp_row); 38727cf7d04SAleksandr Rybalko 38827cf7d04SAleksandr Rybalko for (r = 0; r < vb->vb_history_size; r++) 389*7344ee18SMarius Strobl vb->vb_rows[r] = &vb->vb_buffer[r * vb->vb_scr_size.tp_col]; 39027cf7d04SAleksandr Rybalko } 39127cf7d04SAleksandr Rybalko 39227cf7d04SAleksandr Rybalko void 39327cf7d04SAleksandr Rybalko vtbuf_init_early(struct vt_buf *vb) 39427cf7d04SAleksandr Rybalko { 395*7344ee18SMarius Strobl term_rect_t rect; 39627cf7d04SAleksandr Rybalko 39727cf7d04SAleksandr Rybalko vb->vb_flags |= VBF_CURSOR; 39827cf7d04SAleksandr Rybalko vb->vb_roffset = 0; 39927cf7d04SAleksandr Rybalko vb->vb_curroffset = 0; 40027cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_row = 0; 40127cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col = 0; 40227cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_row = 0; 40327cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col = 0; 40427cf7d04SAleksandr Rybalko 40527cf7d04SAleksandr Rybalko vtbuf_init_rows(vb); 406*7344ee18SMarius Strobl rect.tr_begin.tp_row = rect.tr_begin.tp_col = 0; 407*7344ee18SMarius Strobl rect.tr_end = vb->vb_scr_size; 408*7344ee18SMarius Strobl vtbuf_fill(vb, &rect, VTBUF_SPACE_CHAR((boothowto & RB_MUTE) == 0 ? 409*7344ee18SMarius Strobl TERMINAL_KERN_ATTR : TERMINAL_NORM_ATTR)); 41027cf7d04SAleksandr Rybalko vtbuf_make_undirty(vb); 41127cf7d04SAleksandr Rybalko if ((vb->vb_flags & VBF_MTX_INIT) == 0) { 41227cf7d04SAleksandr Rybalko mtx_init(&vb->vb_lock, "vtbuf", NULL, MTX_SPIN); 41327cf7d04SAleksandr Rybalko vb->vb_flags |= VBF_MTX_INIT; 41427cf7d04SAleksandr Rybalko } 41527cf7d04SAleksandr Rybalko } 41627cf7d04SAleksandr Rybalko 41727cf7d04SAleksandr Rybalko void 41827cf7d04SAleksandr Rybalko vtbuf_init(struct vt_buf *vb, const term_pos_t *p) 41927cf7d04SAleksandr Rybalko { 42027cf7d04SAleksandr Rybalko int sz; 42127cf7d04SAleksandr Rybalko 42227cf7d04SAleksandr Rybalko vb->vb_scr_size = *p; 42327cf7d04SAleksandr Rybalko vb->vb_history_size = VBF_DEFAULT_HISTORY_SIZE; 42427cf7d04SAleksandr Rybalko 42527cf7d04SAleksandr Rybalko if ((vb->vb_flags & VBF_STATIC) == 0) { 42627cf7d04SAleksandr Rybalko sz = vb->vb_history_size * p->tp_col * sizeof(term_char_t); 42727cf7d04SAleksandr Rybalko vb->vb_buffer = malloc(sz, M_VTBUF, M_WAITOK | M_ZERO); 42827cf7d04SAleksandr Rybalko 42927cf7d04SAleksandr Rybalko sz = vb->vb_history_size * sizeof(term_char_t *); 43027cf7d04SAleksandr Rybalko vb->vb_rows = malloc(sz, M_VTBUF, M_WAITOK | M_ZERO); 43127cf7d04SAleksandr Rybalko } 43227cf7d04SAleksandr Rybalko 43327cf7d04SAleksandr Rybalko vtbuf_init_early(vb); 43427cf7d04SAleksandr Rybalko } 43527cf7d04SAleksandr Rybalko 43627cf7d04SAleksandr Rybalko void 43727cf7d04SAleksandr Rybalko vtbuf_sethistory_size(struct vt_buf *vb, int size) 43827cf7d04SAleksandr Rybalko { 43927cf7d04SAleksandr Rybalko term_pos_t p; 44027cf7d04SAleksandr Rybalko 44127cf7d04SAleksandr Rybalko /* With same size */ 44227cf7d04SAleksandr Rybalko p.tp_row = vb->vb_scr_size.tp_row; 44327cf7d04SAleksandr Rybalko p.tp_col = vb->vb_scr_size.tp_col; 44427cf7d04SAleksandr Rybalko vtbuf_grow(vb, &p, size); 44527cf7d04SAleksandr Rybalko } 44627cf7d04SAleksandr Rybalko 44727cf7d04SAleksandr Rybalko void 44827cf7d04SAleksandr Rybalko vtbuf_grow(struct vt_buf *vb, const term_pos_t *p, int history_size) 44927cf7d04SAleksandr Rybalko { 45027cf7d04SAleksandr Rybalko term_char_t *old, *new, **rows, **oldrows, **copyrows, *row; 45127cf7d04SAleksandr Rybalko int bufsize, rowssize, w, h, c, r; 45227cf7d04SAleksandr Rybalko term_rect_t rect; 45327cf7d04SAleksandr Rybalko 45427cf7d04SAleksandr Rybalko history_size = MAX(history_size, p->tp_row); 45527cf7d04SAleksandr Rybalko 4568a25d545SAleksandr Rybalko /* If new screen/history size bigger or buffer is VBF_STATIC. */ 4578a25d545SAleksandr Rybalko if ((history_size > vb->vb_history_size) || (p->tp_col > 4588a25d545SAleksandr Rybalko vb->vb_scr_size.tp_col) || (vb->vb_flags & VBF_STATIC)) { 45927cf7d04SAleksandr Rybalko /* Allocate new buffer. */ 46027cf7d04SAleksandr Rybalko bufsize = history_size * p->tp_col * sizeof(term_char_t); 46127cf7d04SAleksandr Rybalko new = malloc(bufsize, M_VTBUF, M_WAITOK | M_ZERO); 46227cf7d04SAleksandr Rybalko rowssize = history_size * sizeof(term_pos_t *); 46327cf7d04SAleksandr Rybalko rows = malloc(rowssize, M_VTBUF, M_WAITOK | M_ZERO); 46427cf7d04SAleksandr Rybalko 46527cf7d04SAleksandr Rybalko /* Toggle it. */ 46627cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 46727cf7d04SAleksandr Rybalko old = vb->vb_flags & VBF_STATIC ? NULL : vb->vb_buffer; 46827cf7d04SAleksandr Rybalko oldrows = vb->vb_flags & VBF_STATIC ? NULL : vb->vb_rows; 46927cf7d04SAleksandr Rybalko copyrows = vb->vb_rows; 47027cf7d04SAleksandr Rybalko w = vb->vb_scr_size.tp_col; 47127cf7d04SAleksandr Rybalko h = vb->vb_history_size; 47227cf7d04SAleksandr Rybalko 47327cf7d04SAleksandr Rybalko vb->vb_history_size = history_size; 47427cf7d04SAleksandr Rybalko vb->vb_buffer = new; 47527cf7d04SAleksandr Rybalko vb->vb_rows = rows; 47627cf7d04SAleksandr Rybalko vb->vb_flags &= ~VBF_STATIC; 47727cf7d04SAleksandr Rybalko vb->vb_scr_size = *p; 47827cf7d04SAleksandr Rybalko vtbuf_init_rows(vb); 47927cf7d04SAleksandr Rybalko 48027cf7d04SAleksandr Rybalko /* Copy history and fill extra space. */ 48127cf7d04SAleksandr Rybalko for (r = 0; r < history_size; r ++) { 482*7344ee18SMarius Strobl /* 483*7344ee18SMarius Strobl * XXX VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR) will 484*7344ee18SMarius Strobl * extended lines of kernel text using the wrong 485*7344ee18SMarius Strobl * background color. 486*7344ee18SMarius Strobl */ 48727cf7d04SAleksandr Rybalko row = rows[r]; 48827cf7d04SAleksandr Rybalko if (r < h) { /* Copy. */ 48927cf7d04SAleksandr Rybalko memmove(rows[r], copyrows[r], 49027cf7d04SAleksandr Rybalko MIN(p->tp_col, w) * sizeof(term_char_t)); 49127cf7d04SAleksandr Rybalko for (c = MIN(p->tp_col, w); c < p->tp_col; 49227cf7d04SAleksandr Rybalko c++) { 493*7344ee18SMarius Strobl row[c] = VTBUF_SPACE_CHAR( 494*7344ee18SMarius Strobl TERMINAL_NORM_ATTR); 49527cf7d04SAleksandr Rybalko } 49627cf7d04SAleksandr Rybalko } else { /* Just fill. */ 49727cf7d04SAleksandr Rybalko rect.tr_begin.tp_col = 0; 49827cf7d04SAleksandr Rybalko rect.tr_begin.tp_row = r; 49927cf7d04SAleksandr Rybalko rect.tr_end.tp_col = p->tp_col; 50027cf7d04SAleksandr Rybalko rect.tr_end.tp_row = p->tp_row; 501*7344ee18SMarius Strobl vtbuf_fill(vb, &rect, 502*7344ee18SMarius Strobl VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR)); 50327cf7d04SAleksandr Rybalko break; 50427cf7d04SAleksandr Rybalko } 50527cf7d04SAleksandr Rybalko } 50627cf7d04SAleksandr Rybalko vtbuf_make_undirty(vb); 50727cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 50827cf7d04SAleksandr Rybalko /* Deallocate old buffer. */ 50927cf7d04SAleksandr Rybalko free(old, M_VTBUF); 51027cf7d04SAleksandr Rybalko free(oldrows, M_VTBUF); 5117cd5ec40SEd Maste } else { 5127cd5ec40SEd Maste /* Just update the size. */ 5137cd5ec40SEd Maste vb->vb_scr_size = *p; 51427cf7d04SAleksandr Rybalko } 51527cf7d04SAleksandr Rybalko } 51627cf7d04SAleksandr Rybalko 51727cf7d04SAleksandr Rybalko void 51827cf7d04SAleksandr Rybalko vtbuf_putchar(struct vt_buf *vb, const term_pos_t *p, term_char_t c) 51927cf7d04SAleksandr Rybalko { 52027cf7d04SAleksandr Rybalko term_char_t *row; 52127cf7d04SAleksandr Rybalko 52227cf7d04SAleksandr Rybalko KASSERT(p->tp_row < vb->vb_scr_size.tp_row, 52327cf7d04SAleksandr Rybalko ("vtbuf_putchar tp_row %d must be less than screen width %d", 52427cf7d04SAleksandr Rybalko p->tp_row, vb->vb_scr_size.tp_row)); 52527cf7d04SAleksandr Rybalko KASSERT(p->tp_col < vb->vb_scr_size.tp_col, 52627cf7d04SAleksandr Rybalko ("vtbuf_putchar tp_col %d must be less than screen height %d", 52727cf7d04SAleksandr Rybalko p->tp_col, vb->vb_scr_size.tp_col)); 52827cf7d04SAleksandr Rybalko 52927cf7d04SAleksandr Rybalko row = vb->vb_rows[(vb->vb_curroffset + p->tp_row) % 53027cf7d04SAleksandr Rybalko VTBUF_MAX_HEIGHT(vb)]; 53127cf7d04SAleksandr Rybalko if (row[p->tp_col] != c) { 53227cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 53327cf7d04SAleksandr Rybalko row[p->tp_col] = c; 53427cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 53527cf7d04SAleksandr Rybalko vtbuf_dirty_cell(vb, p); 53627cf7d04SAleksandr Rybalko } 53727cf7d04SAleksandr Rybalko } 53827cf7d04SAleksandr Rybalko 53927cf7d04SAleksandr Rybalko void 54027cf7d04SAleksandr Rybalko vtbuf_cursor_position(struct vt_buf *vb, const term_pos_t *p) 54127cf7d04SAleksandr Rybalko { 54227cf7d04SAleksandr Rybalko 54327cf7d04SAleksandr Rybalko if (vb->vb_flags & VBF_CURSOR) { 54427cf7d04SAleksandr Rybalko vtbuf_dirty_cell(vb, &vb->vb_cursor); 54527cf7d04SAleksandr Rybalko vb->vb_cursor = *p; 54627cf7d04SAleksandr Rybalko vtbuf_dirty_cell(vb, &vb->vb_cursor); 54727cf7d04SAleksandr Rybalko } else { 54827cf7d04SAleksandr Rybalko vb->vb_cursor = *p; 54927cf7d04SAleksandr Rybalko } 55027cf7d04SAleksandr Rybalko } 55127cf7d04SAleksandr Rybalko 5520f49db6eSAleksandr Rybalko #ifndef SC_NO_CUTPASTE 55327cf7d04SAleksandr Rybalko void 55427cf7d04SAleksandr Rybalko vtbuf_mouse_cursor_position(struct vt_buf *vb, int col, int row) 55527cf7d04SAleksandr Rybalko { 55627cf7d04SAleksandr Rybalko term_rect_t area; 55727cf7d04SAleksandr Rybalko 55827cf7d04SAleksandr Rybalko area.tr_begin.tp_row = MAX(row - 1, 0); 55927cf7d04SAleksandr Rybalko area.tr_begin.tp_col = MAX(col - 1, 0); 56027cf7d04SAleksandr Rybalko area.tr_end.tp_row = MIN(row + 2, vb->vb_scr_size.tp_row); 56127cf7d04SAleksandr Rybalko area.tr_end.tp_col = MIN(col + 2, vb->vb_scr_size.tp_col); 56227cf7d04SAleksandr Rybalko vtbuf_dirty(vb, &area); 56327cf7d04SAleksandr Rybalko } 56427cf7d04SAleksandr Rybalko 56527cf7d04SAleksandr Rybalko static void 56627cf7d04SAleksandr Rybalko vtbuf_flush_mark(struct vt_buf *vb) 56727cf7d04SAleksandr Rybalko { 56827cf7d04SAleksandr Rybalko term_rect_t area; 56927cf7d04SAleksandr Rybalko int s, e; 57027cf7d04SAleksandr Rybalko 57127cf7d04SAleksandr Rybalko /* Notify renderer to update marked region. */ 57227cf7d04SAleksandr Rybalko if (vb->vb_mark_start.tp_col || vb->vb_mark_end.tp_col || 57327cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_row || vb->vb_mark_end.tp_row) { 57427cf7d04SAleksandr Rybalko 57527cf7d04SAleksandr Rybalko s = vtbuf_htw(vb, vb->vb_mark_start.tp_row); 57627cf7d04SAleksandr Rybalko e = vtbuf_htw(vb, vb->vb_mark_end.tp_row); 57727cf7d04SAleksandr Rybalko 57827cf7d04SAleksandr Rybalko area.tr_begin.tp_col = 0; 57927cf7d04SAleksandr Rybalko area.tr_begin.tp_row = MIN(s, e); 58027cf7d04SAleksandr Rybalko 58127cf7d04SAleksandr Rybalko area.tr_end.tp_col = vb->vb_scr_size.tp_col; 58227cf7d04SAleksandr Rybalko area.tr_end.tp_row = MAX(s, e) + 1; 58327cf7d04SAleksandr Rybalko 58427cf7d04SAleksandr Rybalko vtbuf_dirty(vb, &area); 58527cf7d04SAleksandr Rybalko } 58627cf7d04SAleksandr Rybalko } 58727cf7d04SAleksandr Rybalko 58827cf7d04SAleksandr Rybalko int 58927cf7d04SAleksandr Rybalko vtbuf_get_marked_len(struct vt_buf *vb) 59027cf7d04SAleksandr Rybalko { 59127cf7d04SAleksandr Rybalko int ei, si, sz; 59227cf7d04SAleksandr Rybalko term_pos_t s, e; 59327cf7d04SAleksandr Rybalko 59427cf7d04SAleksandr Rybalko /* Swap according to window coordinates. */ 59527cf7d04SAleksandr Rybalko if (POS_INDEX(vtbuf_htw(vb, vb->vb_mark_start.tp_row), 59627cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col) > 59727cf7d04SAleksandr Rybalko POS_INDEX(vtbuf_htw(vb, vb->vb_mark_end.tp_row), 59827cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col)) { 59927cf7d04SAleksandr Rybalko POS_COPY(e, vb->vb_mark_start); 60027cf7d04SAleksandr Rybalko POS_COPY(s, vb->vb_mark_end); 60127cf7d04SAleksandr Rybalko } else { 60227cf7d04SAleksandr Rybalko POS_COPY(s, vb->vb_mark_start); 60327cf7d04SAleksandr Rybalko POS_COPY(e, vb->vb_mark_end); 60427cf7d04SAleksandr Rybalko } 60527cf7d04SAleksandr Rybalko 60627cf7d04SAleksandr Rybalko si = s.tp_row * vb->vb_scr_size.tp_col + s.tp_col; 60727cf7d04SAleksandr Rybalko ei = e.tp_row * vb->vb_scr_size.tp_col + e.tp_col; 60827cf7d04SAleksandr Rybalko 60927cf7d04SAleksandr Rybalko /* Number symbols and number of rows to inject \n */ 61027cf7d04SAleksandr Rybalko sz = ei - si + ((e.tp_row - s.tp_row) * 2) + 1; 61127cf7d04SAleksandr Rybalko 61227cf7d04SAleksandr Rybalko return (sz * sizeof(term_char_t)); 61327cf7d04SAleksandr Rybalko } 61427cf7d04SAleksandr Rybalko 61527cf7d04SAleksandr Rybalko void 61627cf7d04SAleksandr Rybalko vtbuf_extract_marked(struct vt_buf *vb, term_char_t *buf, int sz) 61727cf7d04SAleksandr Rybalko { 61827cf7d04SAleksandr Rybalko int i, r, c, cs, ce; 61927cf7d04SAleksandr Rybalko term_pos_t s, e; 62027cf7d04SAleksandr Rybalko 62127cf7d04SAleksandr Rybalko /* Swap according to window coordinates. */ 62227cf7d04SAleksandr Rybalko if (POS_INDEX(vtbuf_htw(vb, vb->vb_mark_start.tp_row), 62327cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col) > 62427cf7d04SAleksandr Rybalko POS_INDEX(vtbuf_htw(vb, vb->vb_mark_end.tp_row), 62527cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col)) { 62627cf7d04SAleksandr Rybalko POS_COPY(e, vb->vb_mark_start); 62727cf7d04SAleksandr Rybalko POS_COPY(s, vb->vb_mark_end); 62827cf7d04SAleksandr Rybalko } else { 62927cf7d04SAleksandr Rybalko POS_COPY(s, vb->vb_mark_start); 63027cf7d04SAleksandr Rybalko POS_COPY(e, vb->vb_mark_end); 63127cf7d04SAleksandr Rybalko } 63227cf7d04SAleksandr Rybalko 63327cf7d04SAleksandr Rybalko i = 0; 63427cf7d04SAleksandr Rybalko for (r = s.tp_row; r <= e.tp_row; r ++) { 63527cf7d04SAleksandr Rybalko cs = (r == s.tp_row)?s.tp_col:0; 63627cf7d04SAleksandr Rybalko ce = (r == e.tp_row)?e.tp_col:vb->vb_scr_size.tp_col; 63727cf7d04SAleksandr Rybalko for (c = cs; c < ce; c ++) { 63827cf7d04SAleksandr Rybalko buf[i++] = vb->vb_rows[r][c]; 63927cf7d04SAleksandr Rybalko } 64027cf7d04SAleksandr Rybalko /* Add new line for all rows, but not for last one. */ 64127cf7d04SAleksandr Rybalko if (r != e.tp_row) { 64227cf7d04SAleksandr Rybalko buf[i++] = '\r'; 64327cf7d04SAleksandr Rybalko buf[i++] = '\n'; 64427cf7d04SAleksandr Rybalko } 64527cf7d04SAleksandr Rybalko } 64627cf7d04SAleksandr Rybalko } 64727cf7d04SAleksandr Rybalko 64827cf7d04SAleksandr Rybalko int 64927cf7d04SAleksandr Rybalko vtbuf_set_mark(struct vt_buf *vb, int type, int col, int row) 65027cf7d04SAleksandr Rybalko { 65127cf7d04SAleksandr Rybalko term_char_t *r; 65227cf7d04SAleksandr Rybalko int i; 65327cf7d04SAleksandr Rybalko 65427cf7d04SAleksandr Rybalko switch (type) { 65527cf7d04SAleksandr Rybalko case VTB_MARK_END: /* B1 UP */ 65627cf7d04SAleksandr Rybalko if (vb->vb_mark_last != VTB_MARK_MOVE) 65727cf7d04SAleksandr Rybalko return (0); 65827cf7d04SAleksandr Rybalko /* FALLTHROUGH */ 65927cf7d04SAleksandr Rybalko case VTB_MARK_MOVE: 66027cf7d04SAleksandr Rybalko case VTB_MARK_EXTEND: 66127cf7d04SAleksandr Rybalko vtbuf_flush_mark(vb); /* Clean old mark. */ 66227cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col = col; 66327cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_row = vtbuf_wth(vb, row); 66427cf7d04SAleksandr Rybalko break; 66527cf7d04SAleksandr Rybalko case VTB_MARK_START: 66627cf7d04SAleksandr Rybalko vtbuf_flush_mark(vb); /* Clean old mark. */ 66727cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col = col; 66827cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_row = vtbuf_wth(vb, row); 66927cf7d04SAleksandr Rybalko /* Start again, so clear end point. */ 67027cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col = col; 67127cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_row = vtbuf_wth(vb, row); 67227cf7d04SAleksandr Rybalko break; 67327cf7d04SAleksandr Rybalko case VTB_MARK_WORD: 67427cf7d04SAleksandr Rybalko vtbuf_flush_mark(vb); /* Clean old mark. */ 67527cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_row = vb->vb_mark_end.tp_row = 67627cf7d04SAleksandr Rybalko vtbuf_wth(vb, row); 67727cf7d04SAleksandr Rybalko r = vb->vb_rows[vb->vb_mark_start.tp_row]; 67827cf7d04SAleksandr Rybalko for (i = col; i >= 0; i --) { 67927cf7d04SAleksandr Rybalko if (TCHAR_CHARACTER(r[i]) == ' ') { 68027cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col = i + 1; 68127cf7d04SAleksandr Rybalko break; 68227cf7d04SAleksandr Rybalko } 68327cf7d04SAleksandr Rybalko } 68427cf7d04SAleksandr Rybalko for (i = col; i < vb->vb_scr_size.tp_col; i ++) { 68527cf7d04SAleksandr Rybalko if (TCHAR_CHARACTER(r[i]) == ' ') { 68627cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col = i; 68727cf7d04SAleksandr Rybalko break; 68827cf7d04SAleksandr Rybalko } 68927cf7d04SAleksandr Rybalko } 69027cf7d04SAleksandr Rybalko if (vb->vb_mark_start.tp_col > vb->vb_mark_end.tp_col) 69127cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col = vb->vb_mark_end.tp_col; 69227cf7d04SAleksandr Rybalko break; 69327cf7d04SAleksandr Rybalko case VTB_MARK_ROW: 69427cf7d04SAleksandr Rybalko vtbuf_flush_mark(vb); /* Clean old mark. */ 69527cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col = 0; 69627cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col = vb->vb_scr_size.tp_col; 69727cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_row = vb->vb_mark_end.tp_row = 69827cf7d04SAleksandr Rybalko vtbuf_wth(vb, row); 69927cf7d04SAleksandr Rybalko break; 70027cf7d04SAleksandr Rybalko case VTB_MARK_NONE: 70127cf7d04SAleksandr Rybalko vb->vb_mark_last = type; 70227cf7d04SAleksandr Rybalko /* FALLTHROUGH */ 70327cf7d04SAleksandr Rybalko default: 70427cf7d04SAleksandr Rybalko /* panic? */ 70527cf7d04SAleksandr Rybalko return (0); 70627cf7d04SAleksandr Rybalko } 70727cf7d04SAleksandr Rybalko 70827cf7d04SAleksandr Rybalko vb->vb_mark_last = type; 70927cf7d04SAleksandr Rybalko /* Draw new marked region. */ 71027cf7d04SAleksandr Rybalko vtbuf_flush_mark(vb); 71127cf7d04SAleksandr Rybalko return (1); 71227cf7d04SAleksandr Rybalko } 7130f49db6eSAleksandr Rybalko #endif 71427cf7d04SAleksandr Rybalko 71527cf7d04SAleksandr Rybalko void 71627cf7d04SAleksandr Rybalko vtbuf_cursor_visibility(struct vt_buf *vb, int yes) 71727cf7d04SAleksandr Rybalko { 71827cf7d04SAleksandr Rybalko int oflags, nflags; 71927cf7d04SAleksandr Rybalko 72027cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 72127cf7d04SAleksandr Rybalko oflags = vb->vb_flags; 72227cf7d04SAleksandr Rybalko if (yes) 72327cf7d04SAleksandr Rybalko vb->vb_flags |= VBF_CURSOR; 72427cf7d04SAleksandr Rybalko else 72527cf7d04SAleksandr Rybalko vb->vb_flags &= ~VBF_CURSOR; 72627cf7d04SAleksandr Rybalko nflags = vb->vb_flags; 72727cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 72827cf7d04SAleksandr Rybalko 72927cf7d04SAleksandr Rybalko if (oflags != nflags) 73027cf7d04SAleksandr Rybalko vtbuf_dirty_cell(vb, &vb->vb_cursor); 73127cf7d04SAleksandr Rybalko } 73227cf7d04SAleksandr Rybalko 73327cf7d04SAleksandr Rybalko void 73427cf7d04SAleksandr Rybalko vtbuf_scroll_mode(struct vt_buf *vb, int yes) 73527cf7d04SAleksandr Rybalko { 73627cf7d04SAleksandr Rybalko int oflags, nflags; 73727cf7d04SAleksandr Rybalko 73827cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 73927cf7d04SAleksandr Rybalko oflags = vb->vb_flags; 74027cf7d04SAleksandr Rybalko if (yes) 74127cf7d04SAleksandr Rybalko vb->vb_flags |= VBF_SCROLL; 74227cf7d04SAleksandr Rybalko else 74327cf7d04SAleksandr Rybalko vb->vb_flags &= ~VBF_SCROLL; 74427cf7d04SAleksandr Rybalko nflags = vb->vb_flags; 74527cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 74627cf7d04SAleksandr Rybalko 74727cf7d04SAleksandr Rybalko if (oflags != nflags) 74827cf7d04SAleksandr Rybalko vtbuf_dirty_cell(vb, &vb->vb_cursor); 74927cf7d04SAleksandr Rybalko } 75027cf7d04SAleksandr Rybalko 751