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> 4127cf7d04SAleksandr Rybalko #include <sys/systm.h> 4227cf7d04SAleksandr Rybalko 4327cf7d04SAleksandr Rybalko #include <dev/vt/vt.h> 4427cf7d04SAleksandr Rybalko 4527cf7d04SAleksandr Rybalko static MALLOC_DEFINE(M_VTBUF, "vtbuf", "vt buffer"); 4627cf7d04SAleksandr Rybalko 4727cf7d04SAleksandr Rybalko #define VTBUF_LOCK(vb) mtx_lock_spin(&(vb)->vb_lock) 4827cf7d04SAleksandr Rybalko #define VTBUF_UNLOCK(vb) mtx_unlock_spin(&(vb)->vb_lock) 4927cf7d04SAleksandr Rybalko 5027cf7d04SAleksandr Rybalko #define POS_INDEX(c, r) (((r) << 12) + (c)) 5127cf7d04SAleksandr Rybalko #define POS_COPY(d, s) do { \ 5227cf7d04SAleksandr Rybalko (d).tp_col = (s).tp_col; \ 5327cf7d04SAleksandr Rybalko (d).tp_row = (s).tp_row; \ 5427cf7d04SAleksandr Rybalko } while (0) 5527cf7d04SAleksandr Rybalko 5627cf7d04SAleksandr Rybalko 5727cf7d04SAleksandr Rybalko /* 5827cf7d04SAleksandr Rybalko * line4 5927cf7d04SAleksandr Rybalko * line5 <--- curroffset (terminal output to that line) 6027cf7d04SAleksandr Rybalko * line0 6127cf7d04SAleksandr Rybalko * line1 <--- roffset (history display from that point) 6227cf7d04SAleksandr Rybalko * line2 6327cf7d04SAleksandr Rybalko * line3 6427cf7d04SAleksandr Rybalko */ 6527cf7d04SAleksandr Rybalko int 6627cf7d04SAleksandr Rybalko vthistory_seek(struct vt_buf *vb, int offset, int whence) 6727cf7d04SAleksandr Rybalko { 6827cf7d04SAleksandr Rybalko int diff, top, bottom, roffset; 6927cf7d04SAleksandr Rybalko 7027cf7d04SAleksandr Rybalko /* No scrolling if not enabled. */ 7127cf7d04SAleksandr Rybalko if ((vb->vb_flags & VBF_SCROLL) == 0) { 7227cf7d04SAleksandr Rybalko if (vb->vb_roffset != vb->vb_curroffset) { 7327cf7d04SAleksandr Rybalko vb->vb_roffset = vb->vb_curroffset; 7427cf7d04SAleksandr Rybalko return (0xffff); 7527cf7d04SAleksandr Rybalko } 7627cf7d04SAleksandr Rybalko return (0); /* No changes */ 7727cf7d04SAleksandr Rybalko } 7827cf7d04SAleksandr Rybalko top = (vb->vb_flags & VBF_HISTORY_FULL)? 7927cf7d04SAleksandr Rybalko (vb->vb_curroffset + vb->vb_scr_size.tp_row):vb->vb_history_size; 8027cf7d04SAleksandr Rybalko bottom = vb->vb_curroffset + vb->vb_history_size; 8127cf7d04SAleksandr Rybalko 8227cf7d04SAleksandr Rybalko /* 8327cf7d04SAleksandr Rybalko * Operate on copy of offset value, since it temporary can be bigger 8427cf7d04SAleksandr Rybalko * than amount of rows in buffer. 8527cf7d04SAleksandr Rybalko */ 8627cf7d04SAleksandr Rybalko roffset = vb->vb_roffset + vb->vb_history_size; 8727cf7d04SAleksandr Rybalko switch (whence) { 8827cf7d04SAleksandr Rybalko case VHS_SET: 8927cf7d04SAleksandr Rybalko roffset = offset + vb->vb_history_size; 9027cf7d04SAleksandr Rybalko break; 9127cf7d04SAleksandr Rybalko case VHS_CUR: 9227cf7d04SAleksandr Rybalko roffset += offset; 9327cf7d04SAleksandr Rybalko break; 9427cf7d04SAleksandr Rybalko case VHS_END: 9527cf7d04SAleksandr Rybalko /* Go to current offset. */ 9627cf7d04SAleksandr Rybalko roffset = vb->vb_curroffset + vb->vb_history_size; 9727cf7d04SAleksandr Rybalko break; 9827cf7d04SAleksandr Rybalko } 9927cf7d04SAleksandr Rybalko 10027cf7d04SAleksandr Rybalko roffset = (roffset < top)?top:roffset; 10127cf7d04SAleksandr Rybalko roffset = (roffset > bottom)?bottom:roffset; 10227cf7d04SAleksandr Rybalko 10327cf7d04SAleksandr Rybalko roffset %= vb->vb_history_size; 10427cf7d04SAleksandr Rybalko 10527cf7d04SAleksandr Rybalko if (vb->vb_roffset != roffset) { 10627cf7d04SAleksandr Rybalko diff = vb->vb_roffset - roffset; 10727cf7d04SAleksandr Rybalko vb->vb_roffset = roffset; 10827cf7d04SAleksandr Rybalko /* 10927cf7d04SAleksandr Rybalko * Offset changed, please update Nth lines on sceen. 11027cf7d04SAleksandr Rybalko * +N - Nth lines at top; 11127cf7d04SAleksandr Rybalko * -N - Nth lines at bottom. 11227cf7d04SAleksandr Rybalko */ 11327cf7d04SAleksandr Rybalko return (diff); 11427cf7d04SAleksandr Rybalko } 11527cf7d04SAleksandr Rybalko return (0); /* No changes */ 11627cf7d04SAleksandr Rybalko } 11727cf7d04SAleksandr Rybalko 11827cf7d04SAleksandr Rybalko void 11927cf7d04SAleksandr Rybalko vthistory_addlines(struct vt_buf *vb, int offset) 12027cf7d04SAleksandr Rybalko { 12127cf7d04SAleksandr Rybalko 12227cf7d04SAleksandr Rybalko vb->vb_curroffset += offset; 12327cf7d04SAleksandr Rybalko if (vb->vb_curroffset < 0) 12427cf7d04SAleksandr Rybalko vb->vb_curroffset = 0; 12527cf7d04SAleksandr Rybalko vb->vb_curroffset %= vb->vb_history_size; 12627cf7d04SAleksandr Rybalko if ((vb->vb_flags & VBF_SCROLL) == 0) { 12727cf7d04SAleksandr Rybalko vb->vb_roffset = vb->vb_curroffset; 12827cf7d04SAleksandr Rybalko } 12927cf7d04SAleksandr Rybalko } 13027cf7d04SAleksandr Rybalko 13127cf7d04SAleksandr Rybalko void 13227cf7d04SAleksandr Rybalko vthistory_getpos(const struct vt_buf *vb, unsigned int *offset) 13327cf7d04SAleksandr Rybalko { 13427cf7d04SAleksandr Rybalko 13527cf7d04SAleksandr Rybalko *offset = vb->vb_roffset; 13627cf7d04SAleksandr Rybalko } 13727cf7d04SAleksandr Rybalko 138*0f49db6eSAleksandr Rybalko #ifndef SC_NO_CUTPASTE /* Only mouse support use it now. */ 13927cf7d04SAleksandr Rybalko /* Translate current view row number to history row. */ 14027cf7d04SAleksandr Rybalko static int 14127cf7d04SAleksandr Rybalko vtbuf_wth(struct vt_buf *vb, int row) 14227cf7d04SAleksandr Rybalko { 14327cf7d04SAleksandr Rybalko 14427cf7d04SAleksandr Rybalko return ((vb->vb_roffset + row) % vb->vb_history_size); 14527cf7d04SAleksandr Rybalko } 146*0f49db6eSAleksandr Rybalko #endif 14727cf7d04SAleksandr Rybalko 14827cf7d04SAleksandr Rybalko /* Translate history row to current view row number. */ 14927cf7d04SAleksandr Rybalko static int 15027cf7d04SAleksandr Rybalko vtbuf_htw(struct vt_buf *vb, int row) 15127cf7d04SAleksandr Rybalko { 15227cf7d04SAleksandr Rybalko 15327cf7d04SAleksandr Rybalko /* 15427cf7d04SAleksandr Rybalko * total 1000 rows. 15527cf7d04SAleksandr Rybalko * History offset roffset winrow 15627cf7d04SAleksandr Rybalko * 205 200 ((205 - 200 + 1000) % 1000) = 5 15727cf7d04SAleksandr Rybalko * 90 990 ((90 - 990 + 1000) % 1000) = 100 15827cf7d04SAleksandr Rybalko */ 15927cf7d04SAleksandr Rybalko return ((row - vb->vb_roffset + vb->vb_history_size) % 16027cf7d04SAleksandr Rybalko vb->vb_history_size); 16127cf7d04SAleksandr Rybalko } 16227cf7d04SAleksandr Rybalko 16327cf7d04SAleksandr Rybalko int 16427cf7d04SAleksandr Rybalko vtbuf_iscursor(struct vt_buf *vb, int row, int col) 16527cf7d04SAleksandr Rybalko { 16627cf7d04SAleksandr Rybalko int sc, sr, ec, er, tmp; 16727cf7d04SAleksandr Rybalko 16827cf7d04SAleksandr Rybalko if ((vb->vb_flags & (VBF_CURSOR|VBF_SCROLL)) == VBF_CURSOR && 16927cf7d04SAleksandr Rybalko (vb->vb_cursor.tp_row == row) && (vb->vb_cursor.tp_col == col)) 17027cf7d04SAleksandr Rybalko return (1); 17127cf7d04SAleksandr Rybalko 17227cf7d04SAleksandr Rybalko /* Mark cut/paste region. */ 17327cf7d04SAleksandr Rybalko 17427cf7d04SAleksandr Rybalko /* 17527cf7d04SAleksandr Rybalko * Luckily screen view is not like circular buffer, so we will 17627cf7d04SAleksandr Rybalko * calculate in screen coordinates. Translate first. 17727cf7d04SAleksandr Rybalko */ 17827cf7d04SAleksandr Rybalko sc = vb->vb_mark_start.tp_col; 17927cf7d04SAleksandr Rybalko sr = vtbuf_htw(vb, vb->vb_mark_start.tp_row); 18027cf7d04SAleksandr Rybalko ec = vb->vb_mark_end.tp_col; 18127cf7d04SAleksandr Rybalko er = vtbuf_htw(vb, vb->vb_mark_end.tp_row); 18227cf7d04SAleksandr Rybalko 18327cf7d04SAleksandr Rybalko 18427cf7d04SAleksandr Rybalko /* Swap start and end if start > end. */ 18527cf7d04SAleksandr Rybalko if (POS_INDEX(sc, sr) > POS_INDEX(ec, er)) { 18627cf7d04SAleksandr Rybalko tmp = sc; sc = ec; ec = tmp; 18727cf7d04SAleksandr Rybalko tmp = sr; sr = er; er = tmp; 18827cf7d04SAleksandr Rybalko } 18927cf7d04SAleksandr Rybalko 19027cf7d04SAleksandr Rybalko if ((POS_INDEX(sc, sr) <= POS_INDEX(col, row)) && 19127cf7d04SAleksandr Rybalko (POS_INDEX(col, row) < POS_INDEX(ec, er))) 19227cf7d04SAleksandr Rybalko return (1); 19327cf7d04SAleksandr Rybalko 19427cf7d04SAleksandr Rybalko return (0); 19527cf7d04SAleksandr Rybalko } 19627cf7d04SAleksandr Rybalko 19727cf7d04SAleksandr Rybalko static inline uint64_t 19827cf7d04SAleksandr Rybalko vtbuf_dirty_axis(unsigned int begin, unsigned int end) 19927cf7d04SAleksandr Rybalko { 20027cf7d04SAleksandr Rybalko uint64_t left, right, mask; 20127cf7d04SAleksandr Rybalko 20227cf7d04SAleksandr Rybalko /* 20327cf7d04SAleksandr Rybalko * Mark all bits between begin % 64 and end % 64 dirty. 20427cf7d04SAleksandr Rybalko * This code is functionally equivalent to: 20527cf7d04SAleksandr Rybalko * 20627cf7d04SAleksandr Rybalko * for (i = begin; i < end; i++) 20727cf7d04SAleksandr Rybalko * mask |= (uint64_t)1 << (i % 64); 20827cf7d04SAleksandr Rybalko */ 20927cf7d04SAleksandr Rybalko 21027cf7d04SAleksandr Rybalko /* Obvious case. Mark everything dirty. */ 21127cf7d04SAleksandr Rybalko if (end - begin >= 64) 21227cf7d04SAleksandr Rybalko return (VBM_DIRTY); 21327cf7d04SAleksandr Rybalko 21427cf7d04SAleksandr Rybalko /* 1....0; used bits on the left. */ 21527cf7d04SAleksandr Rybalko left = VBM_DIRTY << begin % 64; 21627cf7d04SAleksandr Rybalko /* 0....1; used bits on the right. */ 21727cf7d04SAleksandr Rybalko right = VBM_DIRTY >> -end % 64; 21827cf7d04SAleksandr Rybalko 21927cf7d04SAleksandr Rybalko /* 22027cf7d04SAleksandr Rybalko * Only take the intersection. If the result of that is 0, it 22127cf7d04SAleksandr Rybalko * means that the selection crossed a 64 bit boundary along the 22227cf7d04SAleksandr Rybalko * way, which means we have to take the complement. 22327cf7d04SAleksandr Rybalko */ 22427cf7d04SAleksandr Rybalko mask = left & right; 22527cf7d04SAleksandr Rybalko if (mask == 0) 22627cf7d04SAleksandr Rybalko mask = left | right; 22727cf7d04SAleksandr Rybalko return (mask); 22827cf7d04SAleksandr Rybalko } 22927cf7d04SAleksandr Rybalko 23027cf7d04SAleksandr Rybalko static inline void 23127cf7d04SAleksandr Rybalko vtbuf_dirty(struct vt_buf *vb, const term_rect_t *area) 23227cf7d04SAleksandr Rybalko { 23327cf7d04SAleksandr Rybalko 23427cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 23527cf7d04SAleksandr Rybalko if (vb->vb_dirtyrect.tr_begin.tp_row > area->tr_begin.tp_row) 23627cf7d04SAleksandr Rybalko vb->vb_dirtyrect.tr_begin.tp_row = area->tr_begin.tp_row; 23727cf7d04SAleksandr Rybalko if (vb->vb_dirtyrect.tr_begin.tp_col > area->tr_begin.tp_col) 23827cf7d04SAleksandr Rybalko vb->vb_dirtyrect.tr_begin.tp_col = area->tr_begin.tp_col; 23927cf7d04SAleksandr Rybalko if (vb->vb_dirtyrect.tr_end.tp_row < area->tr_end.tp_row) 24027cf7d04SAleksandr Rybalko vb->vb_dirtyrect.tr_end.tp_row = area->tr_end.tp_row; 24127cf7d04SAleksandr Rybalko if (vb->vb_dirtyrect.tr_end.tp_col < area->tr_end.tp_col) 24227cf7d04SAleksandr Rybalko vb->vb_dirtyrect.tr_end.tp_col = area->tr_end.tp_col; 24327cf7d04SAleksandr Rybalko vb->vb_dirtymask.vbm_row |= 24427cf7d04SAleksandr Rybalko vtbuf_dirty_axis(area->tr_begin.tp_row, area->tr_end.tp_row); 24527cf7d04SAleksandr Rybalko vb->vb_dirtymask.vbm_col |= 24627cf7d04SAleksandr Rybalko vtbuf_dirty_axis(area->tr_begin.tp_col, area->tr_end.tp_col); 24727cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 24827cf7d04SAleksandr Rybalko } 24927cf7d04SAleksandr Rybalko 25027cf7d04SAleksandr Rybalko static inline void 25127cf7d04SAleksandr Rybalko vtbuf_dirty_cell(struct vt_buf *vb, const term_pos_t *p) 25227cf7d04SAleksandr Rybalko { 25327cf7d04SAleksandr Rybalko term_rect_t area; 25427cf7d04SAleksandr Rybalko 25527cf7d04SAleksandr Rybalko area.tr_begin = *p; 25627cf7d04SAleksandr Rybalko area.tr_end.tp_row = p->tp_row + 1; 25727cf7d04SAleksandr Rybalko area.tr_end.tp_col = p->tp_col + 1; 25827cf7d04SAleksandr Rybalko vtbuf_dirty(vb, &area); 25927cf7d04SAleksandr Rybalko } 26027cf7d04SAleksandr Rybalko 26127cf7d04SAleksandr Rybalko static void 26227cf7d04SAleksandr Rybalko vtbuf_make_undirty(struct vt_buf *vb) 26327cf7d04SAleksandr Rybalko { 26427cf7d04SAleksandr Rybalko 26527cf7d04SAleksandr Rybalko vb->vb_dirtyrect.tr_begin = vb->vb_scr_size; 26627cf7d04SAleksandr Rybalko vb->vb_dirtyrect.tr_end.tp_row = vb->vb_dirtyrect.tr_end.tp_col = 0; 26727cf7d04SAleksandr Rybalko vb->vb_dirtymask.vbm_row = vb->vb_dirtymask.vbm_col = 0; 26827cf7d04SAleksandr Rybalko } 26927cf7d04SAleksandr Rybalko 27027cf7d04SAleksandr Rybalko void 27127cf7d04SAleksandr Rybalko vtbuf_undirty(struct vt_buf *vb, term_rect_t *r, struct vt_bufmask *m) 27227cf7d04SAleksandr Rybalko { 27327cf7d04SAleksandr Rybalko 27427cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 27527cf7d04SAleksandr Rybalko *r = vb->vb_dirtyrect; 27627cf7d04SAleksandr Rybalko *m = vb->vb_dirtymask; 27727cf7d04SAleksandr Rybalko vtbuf_make_undirty(vb); 27827cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 27927cf7d04SAleksandr Rybalko } 28027cf7d04SAleksandr Rybalko 28127cf7d04SAleksandr Rybalko void 28227cf7d04SAleksandr Rybalko vtbuf_copy(struct vt_buf *vb, const term_rect_t *r, const term_pos_t *p2) 28327cf7d04SAleksandr Rybalko { 28427cf7d04SAleksandr Rybalko const term_pos_t *p1 = &r->tr_begin; 28527cf7d04SAleksandr Rybalko term_rect_t area; 28627cf7d04SAleksandr Rybalko unsigned int rows, cols; 28727cf7d04SAleksandr Rybalko int pr, rdiff; 28827cf7d04SAleksandr Rybalko 28927cf7d04SAleksandr Rybalko KASSERT(r->tr_begin.tp_row < vb->vb_scr_size.tp_row, 29027cf7d04SAleksandr Rybalko ("vtbuf_copy begin.tp_row %d must be less than screen width %d", 29127cf7d04SAleksandr Rybalko r->tr_begin.tp_row, vb->vb_scr_size.tp_row)); 29227cf7d04SAleksandr Rybalko KASSERT(r->tr_begin.tp_col < vb->vb_scr_size.tp_col, 29327cf7d04SAleksandr Rybalko ("vtbuf_copy begin.tp_col %d must be less than screen height %d", 29427cf7d04SAleksandr Rybalko r->tr_begin.tp_col, vb->vb_scr_size.tp_col)); 29527cf7d04SAleksandr Rybalko 29627cf7d04SAleksandr Rybalko KASSERT(r->tr_end.tp_row <= vb->vb_scr_size.tp_row, 29727cf7d04SAleksandr Rybalko ("vtbuf_copy end.tp_row %d must be less than screen width %d", 29827cf7d04SAleksandr Rybalko r->tr_end.tp_row, vb->vb_scr_size.tp_row)); 29927cf7d04SAleksandr Rybalko KASSERT(r->tr_end.tp_col <= vb->vb_scr_size.tp_col, 30027cf7d04SAleksandr Rybalko ("vtbuf_copy end.tp_col %d must be less than screen height %d", 30127cf7d04SAleksandr Rybalko r->tr_end.tp_col, vb->vb_scr_size.tp_col)); 30227cf7d04SAleksandr Rybalko 30327cf7d04SAleksandr Rybalko KASSERT(p2->tp_row < vb->vb_scr_size.tp_row, 30427cf7d04SAleksandr Rybalko ("vtbuf_copy tp_row %d must be less than screen width %d", 30527cf7d04SAleksandr Rybalko p2->tp_row, vb->vb_scr_size.tp_row)); 30627cf7d04SAleksandr Rybalko KASSERT(p2->tp_col < vb->vb_scr_size.tp_col, 30727cf7d04SAleksandr Rybalko ("vtbuf_copy tp_col %d must be less than screen height %d", 30827cf7d04SAleksandr Rybalko p2->tp_col, vb->vb_scr_size.tp_col)); 30927cf7d04SAleksandr Rybalko 31027cf7d04SAleksandr Rybalko rows = r->tr_end.tp_row - r->tr_begin.tp_row; 31127cf7d04SAleksandr Rybalko rdiff = r->tr_begin.tp_row - p2->tp_row; 31227cf7d04SAleksandr Rybalko cols = r->tr_end.tp_col - r->tr_begin.tp_col; 31327cf7d04SAleksandr Rybalko if (r->tr_begin.tp_row > p2->tp_row && r->tr_begin.tp_col == 0 && 31427cf7d04SAleksandr Rybalko r->tr_end.tp_col == vb->vb_scr_size.tp_col && /* Full row. */ 31527cf7d04SAleksandr Rybalko (rows + rdiff) == vb->vb_scr_size.tp_row && /* Whole screen. */ 31627cf7d04SAleksandr Rybalko rdiff > 0) { /* Only forward dirrection. Do not eat history. */ 31727cf7d04SAleksandr Rybalko vthistory_addlines(vb, rdiff); 31827cf7d04SAleksandr Rybalko } else if (p2->tp_row < p1->tp_row) { 31927cf7d04SAleksandr Rybalko /* Handle overlapping copies of line segments. */ 32027cf7d04SAleksandr Rybalko /* Move data up. */ 32127cf7d04SAleksandr Rybalko for (pr = 0; pr < rows; pr++) 32227cf7d04SAleksandr Rybalko memmove( 32327cf7d04SAleksandr Rybalko &VTBUF_FIELD(vb, p2->tp_row + pr, p2->tp_col), 32427cf7d04SAleksandr Rybalko &VTBUF_FIELD(vb, p1->tp_row + pr, p1->tp_col), 32527cf7d04SAleksandr Rybalko cols * sizeof(term_char_t)); 32627cf7d04SAleksandr Rybalko } else { 32727cf7d04SAleksandr Rybalko /* Move data down. */ 32827cf7d04SAleksandr Rybalko for (pr = rows - 1; pr >= 0; pr--) 32927cf7d04SAleksandr Rybalko memmove( 33027cf7d04SAleksandr Rybalko &VTBUF_FIELD(vb, p2->tp_row + pr, p2->tp_col), 33127cf7d04SAleksandr Rybalko &VTBUF_FIELD(vb, p1->tp_row + pr, p1->tp_col), 33227cf7d04SAleksandr Rybalko cols * sizeof(term_char_t)); 33327cf7d04SAleksandr Rybalko } 33427cf7d04SAleksandr Rybalko 33527cf7d04SAleksandr Rybalko area.tr_begin = *p2; 33627cf7d04SAleksandr Rybalko area.tr_end.tp_row = MIN(p2->tp_row + rows, vb->vb_scr_size.tp_row); 33727cf7d04SAleksandr Rybalko area.tr_end.tp_col = MIN(p2->tp_col + cols, vb->vb_scr_size.tp_col); 33827cf7d04SAleksandr Rybalko vtbuf_dirty(vb, &area); 33927cf7d04SAleksandr Rybalko } 34027cf7d04SAleksandr Rybalko 34127cf7d04SAleksandr Rybalko static void 34227cf7d04SAleksandr Rybalko vtbuf_fill(struct vt_buf *vb, const term_rect_t *r, term_char_t c) 34327cf7d04SAleksandr Rybalko { 34427cf7d04SAleksandr Rybalko unsigned int pr, pc; 34527cf7d04SAleksandr Rybalko term_char_t *row; 34627cf7d04SAleksandr Rybalko 34727cf7d04SAleksandr Rybalko for (pr = r->tr_begin.tp_row; pr < r->tr_end.tp_row; pr++) { 34827cf7d04SAleksandr Rybalko row = vb->vb_rows[(vb->vb_curroffset + pr) % 34927cf7d04SAleksandr Rybalko VTBUF_MAX_HEIGHT(vb)]; 35027cf7d04SAleksandr Rybalko for (pc = r->tr_begin.tp_col; pc < r->tr_end.tp_col; pc++) { 35127cf7d04SAleksandr Rybalko row[pc] = c; 35227cf7d04SAleksandr Rybalko } 35327cf7d04SAleksandr Rybalko } 35427cf7d04SAleksandr Rybalko } 35527cf7d04SAleksandr Rybalko 35627cf7d04SAleksandr Rybalko void 35727cf7d04SAleksandr Rybalko vtbuf_fill_locked(struct vt_buf *vb, const term_rect_t *r, term_char_t c) 35827cf7d04SAleksandr Rybalko { 35927cf7d04SAleksandr Rybalko KASSERT(r->tr_begin.tp_row < vb->vb_scr_size.tp_row, 36027cf7d04SAleksandr Rybalko ("vtbuf_fill_locked begin.tp_row %d must be < screen width %d", 36127cf7d04SAleksandr Rybalko r->tr_begin.tp_row, vb->vb_scr_size.tp_row)); 36227cf7d04SAleksandr Rybalko KASSERT(r->tr_begin.tp_col < vb->vb_scr_size.tp_col, 36327cf7d04SAleksandr Rybalko ("vtbuf_fill_locked begin.tp_col %d must be < screen height %d", 36427cf7d04SAleksandr Rybalko r->tr_begin.tp_col, vb->vb_scr_size.tp_col)); 36527cf7d04SAleksandr Rybalko 36627cf7d04SAleksandr Rybalko KASSERT(r->tr_end.tp_row <= vb->vb_scr_size.tp_row, 36727cf7d04SAleksandr Rybalko ("vtbuf_fill_locked end.tp_row %d must be <= screen width %d", 36827cf7d04SAleksandr Rybalko r->tr_end.tp_row, vb->vb_scr_size.tp_row)); 36927cf7d04SAleksandr Rybalko KASSERT(r->tr_end.tp_col <= vb->vb_scr_size.tp_col, 37027cf7d04SAleksandr Rybalko ("vtbuf_fill_locked end.tp_col %d must be <= screen height %d", 37127cf7d04SAleksandr Rybalko r->tr_end.tp_col, vb->vb_scr_size.tp_col)); 37227cf7d04SAleksandr Rybalko 37327cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 37427cf7d04SAleksandr Rybalko vtbuf_fill(vb, r, c); 37527cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 37627cf7d04SAleksandr Rybalko 37727cf7d04SAleksandr Rybalko vtbuf_dirty(vb, r); 37827cf7d04SAleksandr Rybalko } 37927cf7d04SAleksandr Rybalko 38027cf7d04SAleksandr Rybalko static void 38127cf7d04SAleksandr Rybalko vtbuf_init_rows(struct vt_buf *vb) 38227cf7d04SAleksandr Rybalko { 38327cf7d04SAleksandr Rybalko int r; 38427cf7d04SAleksandr Rybalko 38527cf7d04SAleksandr Rybalko vb->vb_history_size = MAX(vb->vb_history_size, vb->vb_scr_size.tp_row); 38627cf7d04SAleksandr Rybalko 38727cf7d04SAleksandr Rybalko for (r = 0; r < vb->vb_history_size; r++) 38827cf7d04SAleksandr Rybalko vb->vb_rows[r] = &vb->vb_buffer[r * 38927cf7d04SAleksandr Rybalko vb->vb_scr_size.tp_col]; 39027cf7d04SAleksandr Rybalko } 39127cf7d04SAleksandr Rybalko 39227cf7d04SAleksandr Rybalko void 39327cf7d04SAleksandr Rybalko vtbuf_init_early(struct vt_buf *vb) 39427cf7d04SAleksandr Rybalko { 39527cf7d04SAleksandr Rybalko 39627cf7d04SAleksandr Rybalko vb->vb_flags |= VBF_CURSOR; 39727cf7d04SAleksandr Rybalko vb->vb_roffset = 0; 39827cf7d04SAleksandr Rybalko vb->vb_curroffset = 0; 39927cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_row = 0; 40027cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col = 0; 40127cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_row = 0; 40227cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col = 0; 40327cf7d04SAleksandr Rybalko 40427cf7d04SAleksandr Rybalko vtbuf_init_rows(vb); 40527cf7d04SAleksandr Rybalko vtbuf_make_undirty(vb); 40627cf7d04SAleksandr Rybalko if ((vb->vb_flags & VBF_MTX_INIT) == 0) { 40727cf7d04SAleksandr Rybalko mtx_init(&vb->vb_lock, "vtbuf", NULL, MTX_SPIN); 40827cf7d04SAleksandr Rybalko vb->vb_flags |= VBF_MTX_INIT; 40927cf7d04SAleksandr Rybalko } 41027cf7d04SAleksandr Rybalko } 41127cf7d04SAleksandr Rybalko 41227cf7d04SAleksandr Rybalko void 41327cf7d04SAleksandr Rybalko vtbuf_init(struct vt_buf *vb, const term_pos_t *p) 41427cf7d04SAleksandr Rybalko { 41527cf7d04SAleksandr Rybalko int sz; 41627cf7d04SAleksandr Rybalko 41727cf7d04SAleksandr Rybalko vb->vb_scr_size = *p; 41827cf7d04SAleksandr Rybalko vb->vb_history_size = VBF_DEFAULT_HISTORY_SIZE; 41927cf7d04SAleksandr Rybalko 42027cf7d04SAleksandr Rybalko if ((vb->vb_flags & VBF_STATIC) == 0) { 42127cf7d04SAleksandr Rybalko sz = vb->vb_history_size * p->tp_col * sizeof(term_char_t); 42227cf7d04SAleksandr Rybalko vb->vb_buffer = malloc(sz, M_VTBUF, M_WAITOK | M_ZERO); 42327cf7d04SAleksandr Rybalko 42427cf7d04SAleksandr Rybalko sz = vb->vb_history_size * sizeof(term_char_t *); 42527cf7d04SAleksandr Rybalko vb->vb_rows = malloc(sz, M_VTBUF, M_WAITOK | M_ZERO); 42627cf7d04SAleksandr Rybalko } 42727cf7d04SAleksandr Rybalko 42827cf7d04SAleksandr Rybalko vtbuf_init_early(vb); 42927cf7d04SAleksandr Rybalko } 43027cf7d04SAleksandr Rybalko 43127cf7d04SAleksandr Rybalko void 43227cf7d04SAleksandr Rybalko vtbuf_sethistory_size(struct vt_buf *vb, int size) 43327cf7d04SAleksandr Rybalko { 43427cf7d04SAleksandr Rybalko term_pos_t p; 43527cf7d04SAleksandr Rybalko 43627cf7d04SAleksandr Rybalko /* With same size */ 43727cf7d04SAleksandr Rybalko p.tp_row = vb->vb_scr_size.tp_row; 43827cf7d04SAleksandr Rybalko p.tp_col = vb->vb_scr_size.tp_col; 43927cf7d04SAleksandr Rybalko vtbuf_grow(vb, &p, size); 44027cf7d04SAleksandr Rybalko } 44127cf7d04SAleksandr Rybalko 44227cf7d04SAleksandr Rybalko void 44327cf7d04SAleksandr Rybalko vtbuf_grow(struct vt_buf *vb, const term_pos_t *p, int history_size) 44427cf7d04SAleksandr Rybalko { 44527cf7d04SAleksandr Rybalko term_char_t *old, *new, **rows, **oldrows, **copyrows, *row; 44627cf7d04SAleksandr Rybalko int bufsize, rowssize, w, h, c, r; 44727cf7d04SAleksandr Rybalko term_rect_t rect; 44827cf7d04SAleksandr Rybalko 44927cf7d04SAleksandr Rybalko history_size = MAX(history_size, p->tp_row); 45027cf7d04SAleksandr Rybalko 45127cf7d04SAleksandr Rybalko if (history_size > vb->vb_history_size || p->tp_col > 45227cf7d04SAleksandr Rybalko vb->vb_scr_size.tp_col) { 45327cf7d04SAleksandr Rybalko /* Allocate new buffer. */ 45427cf7d04SAleksandr Rybalko bufsize = history_size * p->tp_col * sizeof(term_char_t); 45527cf7d04SAleksandr Rybalko new = malloc(bufsize, M_VTBUF, M_WAITOK | M_ZERO); 45627cf7d04SAleksandr Rybalko rowssize = history_size * sizeof(term_pos_t *); 45727cf7d04SAleksandr Rybalko rows = malloc(rowssize, M_VTBUF, M_WAITOK | M_ZERO); 45827cf7d04SAleksandr Rybalko 45927cf7d04SAleksandr Rybalko /* Toggle it. */ 46027cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 46127cf7d04SAleksandr Rybalko old = vb->vb_flags & VBF_STATIC ? NULL : vb->vb_buffer; 46227cf7d04SAleksandr Rybalko oldrows = vb->vb_flags & VBF_STATIC ? NULL : vb->vb_rows; 46327cf7d04SAleksandr Rybalko copyrows = vb->vb_rows; 46427cf7d04SAleksandr Rybalko w = vb->vb_scr_size.tp_col; 46527cf7d04SAleksandr Rybalko h = vb->vb_history_size; 46627cf7d04SAleksandr Rybalko 46727cf7d04SAleksandr Rybalko vb->vb_history_size = history_size; 46827cf7d04SAleksandr Rybalko vb->vb_buffer = new; 46927cf7d04SAleksandr Rybalko vb->vb_rows = rows; 47027cf7d04SAleksandr Rybalko vb->vb_flags &= ~VBF_STATIC; 47127cf7d04SAleksandr Rybalko vb->vb_scr_size = *p; 47227cf7d04SAleksandr Rybalko vtbuf_init_rows(vb); 47327cf7d04SAleksandr Rybalko 47427cf7d04SAleksandr Rybalko /* Copy history and fill extra space. */ 47527cf7d04SAleksandr Rybalko for (r = 0; r < history_size; r ++) { 47627cf7d04SAleksandr Rybalko row = rows[r]; 47727cf7d04SAleksandr Rybalko if (r < h) { /* Copy. */ 47827cf7d04SAleksandr Rybalko memmove(rows[r], copyrows[r], 47927cf7d04SAleksandr Rybalko MIN(p->tp_col, w) * sizeof(term_char_t)); 48027cf7d04SAleksandr Rybalko for (c = MIN(p->tp_col, w); c < p->tp_col; 48127cf7d04SAleksandr Rybalko c++) { 48227cf7d04SAleksandr Rybalko row[c] = VTBUF_SPACE_CHAR; 48327cf7d04SAleksandr Rybalko } 48427cf7d04SAleksandr Rybalko } else { /* Just fill. */ 48527cf7d04SAleksandr Rybalko rect.tr_begin.tp_col = 0; 48627cf7d04SAleksandr Rybalko rect.tr_begin.tp_row = r; 48727cf7d04SAleksandr Rybalko rect.tr_end.tp_col = p->tp_col; 48827cf7d04SAleksandr Rybalko rect.tr_end.tp_row = p->tp_row; 48927cf7d04SAleksandr Rybalko vtbuf_fill(vb, &rect, VTBUF_SPACE_CHAR); 49027cf7d04SAleksandr Rybalko break; 49127cf7d04SAleksandr Rybalko } 49227cf7d04SAleksandr Rybalko } 49327cf7d04SAleksandr Rybalko vtbuf_make_undirty(vb); 49427cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 49527cf7d04SAleksandr Rybalko /* Deallocate old buffer. */ 49627cf7d04SAleksandr Rybalko free(old, M_VTBUF); 49727cf7d04SAleksandr Rybalko free(oldrows, M_VTBUF); 49827cf7d04SAleksandr Rybalko } 49927cf7d04SAleksandr Rybalko } 50027cf7d04SAleksandr Rybalko 50127cf7d04SAleksandr Rybalko void 50227cf7d04SAleksandr Rybalko vtbuf_putchar(struct vt_buf *vb, const term_pos_t *p, term_char_t c) 50327cf7d04SAleksandr Rybalko { 50427cf7d04SAleksandr Rybalko term_char_t *row; 50527cf7d04SAleksandr Rybalko 50627cf7d04SAleksandr Rybalko KASSERT(p->tp_row < vb->vb_scr_size.tp_row, 50727cf7d04SAleksandr Rybalko ("vtbuf_putchar tp_row %d must be less than screen width %d", 50827cf7d04SAleksandr Rybalko p->tp_row, vb->vb_scr_size.tp_row)); 50927cf7d04SAleksandr Rybalko KASSERT(p->tp_col < vb->vb_scr_size.tp_col, 51027cf7d04SAleksandr Rybalko ("vtbuf_putchar tp_col %d must be less than screen height %d", 51127cf7d04SAleksandr Rybalko p->tp_col, vb->vb_scr_size.tp_col)); 51227cf7d04SAleksandr Rybalko 51327cf7d04SAleksandr Rybalko row = vb->vb_rows[(vb->vb_curroffset + p->tp_row) % 51427cf7d04SAleksandr Rybalko VTBUF_MAX_HEIGHT(vb)]; 51527cf7d04SAleksandr Rybalko if (row[p->tp_col] != c) { 51627cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 51727cf7d04SAleksandr Rybalko row[p->tp_col] = c; 51827cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 51927cf7d04SAleksandr Rybalko vtbuf_dirty_cell(vb, p); 52027cf7d04SAleksandr Rybalko } 52127cf7d04SAleksandr Rybalko } 52227cf7d04SAleksandr Rybalko 52327cf7d04SAleksandr Rybalko void 52427cf7d04SAleksandr Rybalko vtbuf_cursor_position(struct vt_buf *vb, const term_pos_t *p) 52527cf7d04SAleksandr Rybalko { 52627cf7d04SAleksandr Rybalko 52727cf7d04SAleksandr Rybalko if (vb->vb_flags & VBF_CURSOR) { 52827cf7d04SAleksandr Rybalko vtbuf_dirty_cell(vb, &vb->vb_cursor); 52927cf7d04SAleksandr Rybalko vb->vb_cursor = *p; 53027cf7d04SAleksandr Rybalko vtbuf_dirty_cell(vb, &vb->vb_cursor); 53127cf7d04SAleksandr Rybalko } else { 53227cf7d04SAleksandr Rybalko vb->vb_cursor = *p; 53327cf7d04SAleksandr Rybalko } 53427cf7d04SAleksandr Rybalko } 53527cf7d04SAleksandr Rybalko 536*0f49db6eSAleksandr Rybalko #ifndef SC_NO_CUTPASTE 53727cf7d04SAleksandr Rybalko void 53827cf7d04SAleksandr Rybalko vtbuf_mouse_cursor_position(struct vt_buf *vb, int col, int row) 53927cf7d04SAleksandr Rybalko { 54027cf7d04SAleksandr Rybalko term_rect_t area; 54127cf7d04SAleksandr Rybalko 54227cf7d04SAleksandr Rybalko area.tr_begin.tp_row = MAX(row - 1, 0); 54327cf7d04SAleksandr Rybalko area.tr_begin.tp_col = MAX(col - 1, 0); 54427cf7d04SAleksandr Rybalko area.tr_end.tp_row = MIN(row + 2, vb->vb_scr_size.tp_row); 54527cf7d04SAleksandr Rybalko area.tr_end.tp_col = MIN(col + 2, vb->vb_scr_size.tp_col); 54627cf7d04SAleksandr Rybalko vtbuf_dirty(vb, &area); 54727cf7d04SAleksandr Rybalko } 54827cf7d04SAleksandr Rybalko 54927cf7d04SAleksandr Rybalko static void 55027cf7d04SAleksandr Rybalko vtbuf_flush_mark(struct vt_buf *vb) 55127cf7d04SAleksandr Rybalko { 55227cf7d04SAleksandr Rybalko term_rect_t area; 55327cf7d04SAleksandr Rybalko int s, e; 55427cf7d04SAleksandr Rybalko 55527cf7d04SAleksandr Rybalko /* Notify renderer to update marked region. */ 55627cf7d04SAleksandr Rybalko if (vb->vb_mark_start.tp_col || vb->vb_mark_end.tp_col || 55727cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_row || vb->vb_mark_end.tp_row) { 55827cf7d04SAleksandr Rybalko 55927cf7d04SAleksandr Rybalko s = vtbuf_htw(vb, vb->vb_mark_start.tp_row); 56027cf7d04SAleksandr Rybalko e = vtbuf_htw(vb, vb->vb_mark_end.tp_row); 56127cf7d04SAleksandr Rybalko 56227cf7d04SAleksandr Rybalko area.tr_begin.tp_col = 0; 56327cf7d04SAleksandr Rybalko area.tr_begin.tp_row = MIN(s, e); 56427cf7d04SAleksandr Rybalko 56527cf7d04SAleksandr Rybalko area.tr_end.tp_col = vb->vb_scr_size.tp_col; 56627cf7d04SAleksandr Rybalko area.tr_end.tp_row = MAX(s, e) + 1; 56727cf7d04SAleksandr Rybalko 56827cf7d04SAleksandr Rybalko vtbuf_dirty(vb, &area); 56927cf7d04SAleksandr Rybalko } 57027cf7d04SAleksandr Rybalko } 57127cf7d04SAleksandr Rybalko 57227cf7d04SAleksandr Rybalko int 57327cf7d04SAleksandr Rybalko vtbuf_get_marked_len(struct vt_buf *vb) 57427cf7d04SAleksandr Rybalko { 57527cf7d04SAleksandr Rybalko int ei, si, sz; 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 si = s.tp_row * vb->vb_scr_size.tp_col + s.tp_col; 59127cf7d04SAleksandr Rybalko ei = e.tp_row * vb->vb_scr_size.tp_col + e.tp_col; 59227cf7d04SAleksandr Rybalko 59327cf7d04SAleksandr Rybalko /* Number symbols and number of rows to inject \n */ 59427cf7d04SAleksandr Rybalko sz = ei - si + ((e.tp_row - s.tp_row) * 2) + 1; 59527cf7d04SAleksandr Rybalko 59627cf7d04SAleksandr Rybalko return (sz * sizeof(term_char_t)); 59727cf7d04SAleksandr Rybalko } 59827cf7d04SAleksandr Rybalko 59927cf7d04SAleksandr Rybalko void 60027cf7d04SAleksandr Rybalko vtbuf_extract_marked(struct vt_buf *vb, term_char_t *buf, int sz) 60127cf7d04SAleksandr Rybalko { 60227cf7d04SAleksandr Rybalko int i, r, c, cs, ce; 60327cf7d04SAleksandr Rybalko term_pos_t s, e; 60427cf7d04SAleksandr Rybalko 60527cf7d04SAleksandr Rybalko /* Swap according to window coordinates. */ 60627cf7d04SAleksandr Rybalko if (POS_INDEX(vtbuf_htw(vb, vb->vb_mark_start.tp_row), 60727cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col) > 60827cf7d04SAleksandr Rybalko POS_INDEX(vtbuf_htw(vb, vb->vb_mark_end.tp_row), 60927cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col)) { 61027cf7d04SAleksandr Rybalko POS_COPY(e, vb->vb_mark_start); 61127cf7d04SAleksandr Rybalko POS_COPY(s, vb->vb_mark_end); 61227cf7d04SAleksandr Rybalko } else { 61327cf7d04SAleksandr Rybalko POS_COPY(s, vb->vb_mark_start); 61427cf7d04SAleksandr Rybalko POS_COPY(e, vb->vb_mark_end); 61527cf7d04SAleksandr Rybalko } 61627cf7d04SAleksandr Rybalko 61727cf7d04SAleksandr Rybalko i = 0; 61827cf7d04SAleksandr Rybalko for (r = s.tp_row; r <= e.tp_row; r ++) { 61927cf7d04SAleksandr Rybalko cs = (r == s.tp_row)?s.tp_col:0; 62027cf7d04SAleksandr Rybalko ce = (r == e.tp_row)?e.tp_col:vb->vb_scr_size.tp_col; 62127cf7d04SAleksandr Rybalko for (c = cs; c < ce; c ++) { 62227cf7d04SAleksandr Rybalko buf[i++] = vb->vb_rows[r][c]; 62327cf7d04SAleksandr Rybalko } 62427cf7d04SAleksandr Rybalko /* Add new line for all rows, but not for last one. */ 62527cf7d04SAleksandr Rybalko if (r != e.tp_row) { 62627cf7d04SAleksandr Rybalko buf[i++] = '\r'; 62727cf7d04SAleksandr Rybalko buf[i++] = '\n'; 62827cf7d04SAleksandr Rybalko } 62927cf7d04SAleksandr Rybalko } 63027cf7d04SAleksandr Rybalko } 63127cf7d04SAleksandr Rybalko 63227cf7d04SAleksandr Rybalko int 63327cf7d04SAleksandr Rybalko vtbuf_set_mark(struct vt_buf *vb, int type, int col, int row) 63427cf7d04SAleksandr Rybalko { 63527cf7d04SAleksandr Rybalko term_char_t *r; 63627cf7d04SAleksandr Rybalko int i; 63727cf7d04SAleksandr Rybalko 63827cf7d04SAleksandr Rybalko switch (type) { 63927cf7d04SAleksandr Rybalko case VTB_MARK_END: /* B1 UP */ 64027cf7d04SAleksandr Rybalko if (vb->vb_mark_last != VTB_MARK_MOVE) 64127cf7d04SAleksandr Rybalko return (0); 64227cf7d04SAleksandr Rybalko /* FALLTHROUGH */ 64327cf7d04SAleksandr Rybalko case VTB_MARK_MOVE: 64427cf7d04SAleksandr Rybalko case VTB_MARK_EXTEND: 64527cf7d04SAleksandr Rybalko vtbuf_flush_mark(vb); /* Clean old mark. */ 64627cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col = col; 64727cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_row = vtbuf_wth(vb, row); 64827cf7d04SAleksandr Rybalko break; 64927cf7d04SAleksandr Rybalko case VTB_MARK_START: 65027cf7d04SAleksandr Rybalko vtbuf_flush_mark(vb); /* Clean old mark. */ 65127cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col = col; 65227cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_row = vtbuf_wth(vb, row); 65327cf7d04SAleksandr Rybalko /* Start again, so clear end point. */ 65427cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col = col; 65527cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_row = vtbuf_wth(vb, row); 65627cf7d04SAleksandr Rybalko break; 65727cf7d04SAleksandr Rybalko case VTB_MARK_WORD: 65827cf7d04SAleksandr Rybalko vtbuf_flush_mark(vb); /* Clean old mark. */ 65927cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_row = vb->vb_mark_end.tp_row = 66027cf7d04SAleksandr Rybalko vtbuf_wth(vb, row); 66127cf7d04SAleksandr Rybalko r = vb->vb_rows[vb->vb_mark_start.tp_row]; 66227cf7d04SAleksandr Rybalko for (i = col; i >= 0; i --) { 66327cf7d04SAleksandr Rybalko if (TCHAR_CHARACTER(r[i]) == ' ') { 66427cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col = i + 1; 66527cf7d04SAleksandr Rybalko break; 66627cf7d04SAleksandr Rybalko } 66727cf7d04SAleksandr Rybalko } 66827cf7d04SAleksandr Rybalko for (i = col; i < vb->vb_scr_size.tp_col; i ++) { 66927cf7d04SAleksandr Rybalko if (TCHAR_CHARACTER(r[i]) == ' ') { 67027cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col = i; 67127cf7d04SAleksandr Rybalko break; 67227cf7d04SAleksandr Rybalko } 67327cf7d04SAleksandr Rybalko } 67427cf7d04SAleksandr Rybalko if (vb->vb_mark_start.tp_col > vb->vb_mark_end.tp_col) 67527cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col = vb->vb_mark_end.tp_col; 67627cf7d04SAleksandr Rybalko break; 67727cf7d04SAleksandr Rybalko case VTB_MARK_ROW: 67827cf7d04SAleksandr Rybalko vtbuf_flush_mark(vb); /* Clean old mark. */ 67927cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col = 0; 68027cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col = vb->vb_scr_size.tp_col; 68127cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_row = vb->vb_mark_end.tp_row = 68227cf7d04SAleksandr Rybalko vtbuf_wth(vb, row); 68327cf7d04SAleksandr Rybalko break; 68427cf7d04SAleksandr Rybalko case VTB_MARK_NONE: 68527cf7d04SAleksandr Rybalko vb->vb_mark_last = type; 68627cf7d04SAleksandr Rybalko /* FALLTHROUGH */ 68727cf7d04SAleksandr Rybalko default: 68827cf7d04SAleksandr Rybalko /* panic? */ 68927cf7d04SAleksandr Rybalko return (0); 69027cf7d04SAleksandr Rybalko } 69127cf7d04SAleksandr Rybalko 69227cf7d04SAleksandr Rybalko vb->vb_mark_last = type; 69327cf7d04SAleksandr Rybalko /* Draw new marked region. */ 69427cf7d04SAleksandr Rybalko vtbuf_flush_mark(vb); 69527cf7d04SAleksandr Rybalko return (1); 69627cf7d04SAleksandr Rybalko } 697*0f49db6eSAleksandr Rybalko #endif 69827cf7d04SAleksandr Rybalko 69927cf7d04SAleksandr Rybalko void 70027cf7d04SAleksandr Rybalko vtbuf_cursor_visibility(struct vt_buf *vb, int yes) 70127cf7d04SAleksandr Rybalko { 70227cf7d04SAleksandr Rybalko int oflags, nflags; 70327cf7d04SAleksandr Rybalko 70427cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 70527cf7d04SAleksandr Rybalko oflags = vb->vb_flags; 70627cf7d04SAleksandr Rybalko if (yes) 70727cf7d04SAleksandr Rybalko vb->vb_flags |= VBF_CURSOR; 70827cf7d04SAleksandr Rybalko else 70927cf7d04SAleksandr Rybalko vb->vb_flags &= ~VBF_CURSOR; 71027cf7d04SAleksandr Rybalko nflags = vb->vb_flags; 71127cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 71227cf7d04SAleksandr Rybalko 71327cf7d04SAleksandr Rybalko if (oflags != nflags) 71427cf7d04SAleksandr Rybalko vtbuf_dirty_cell(vb, &vb->vb_cursor); 71527cf7d04SAleksandr Rybalko } 71627cf7d04SAleksandr Rybalko 71727cf7d04SAleksandr Rybalko void 71827cf7d04SAleksandr Rybalko vtbuf_scroll_mode(struct vt_buf *vb, int yes) 71927cf7d04SAleksandr Rybalko { 72027cf7d04SAleksandr Rybalko int oflags, nflags; 72127cf7d04SAleksandr Rybalko 72227cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 72327cf7d04SAleksandr Rybalko oflags = vb->vb_flags; 72427cf7d04SAleksandr Rybalko if (yes) 72527cf7d04SAleksandr Rybalko vb->vb_flags |= VBF_SCROLL; 72627cf7d04SAleksandr Rybalko else 72727cf7d04SAleksandr Rybalko vb->vb_flags &= ~VBF_SCROLL; 72827cf7d04SAleksandr Rybalko nflags = vb->vb_flags; 72927cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 73027cf7d04SAleksandr Rybalko 73127cf7d04SAleksandr Rybalko if (oflags != nflags) 73227cf7d04SAleksandr Rybalko vtbuf_dirty_cell(vb, &vb->vb_cursor); 73327cf7d04SAleksandr Rybalko } 73427cf7d04SAleksandr Rybalko 735