1*27cf7d04SAleksandr Rybalko /*- 2*27cf7d04SAleksandr Rybalko * Copyright (c) 2009, 2013 The FreeBSD Foundation 3*27cf7d04SAleksandr Rybalko * All rights reserved. 4*27cf7d04SAleksandr Rybalko * 5*27cf7d04SAleksandr Rybalko * This software was developed by Ed Schouten under sponsorship from the 6*27cf7d04SAleksandr Rybalko * FreeBSD Foundation. 7*27cf7d04SAleksandr Rybalko * 8*27cf7d04SAleksandr Rybalko * Portions of this software were developed by Oleksandr Rybalko 9*27cf7d04SAleksandr Rybalko * under sponsorship from the FreeBSD Foundation. 10*27cf7d04SAleksandr Rybalko * 11*27cf7d04SAleksandr Rybalko * Redistribution and use in source and binary forms, with or without 12*27cf7d04SAleksandr Rybalko * modification, are permitted provided that the following conditions 13*27cf7d04SAleksandr Rybalko * are met: 14*27cf7d04SAleksandr Rybalko * 1. Redistributions of source code must retain the above copyright 15*27cf7d04SAleksandr Rybalko * notice, this list of conditions and the following disclaimer. 16*27cf7d04SAleksandr Rybalko * 2. Redistributions in binary form must reproduce the above copyright 17*27cf7d04SAleksandr Rybalko * notice, this list of conditions and the following disclaimer in the 18*27cf7d04SAleksandr Rybalko * documentation and/or other materials provided with the distribution. 19*27cf7d04SAleksandr Rybalko * 20*27cf7d04SAleksandr Rybalko * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21*27cf7d04SAleksandr Rybalko * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22*27cf7d04SAleksandr Rybalko * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23*27cf7d04SAleksandr Rybalko * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24*27cf7d04SAleksandr Rybalko * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25*27cf7d04SAleksandr Rybalko * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26*27cf7d04SAleksandr Rybalko * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27*27cf7d04SAleksandr Rybalko * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28*27cf7d04SAleksandr Rybalko * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29*27cf7d04SAleksandr Rybalko * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30*27cf7d04SAleksandr Rybalko * SUCH DAMAGE. 31*27cf7d04SAleksandr Rybalko */ 32*27cf7d04SAleksandr Rybalko 33*27cf7d04SAleksandr Rybalko #include <sys/cdefs.h> 34*27cf7d04SAleksandr Rybalko __FBSDID("$FreeBSD$"); 35*27cf7d04SAleksandr Rybalko 36*27cf7d04SAleksandr Rybalko #include <sys/param.h> 37*27cf7d04SAleksandr Rybalko #include <sys/kernel.h> 38*27cf7d04SAleksandr Rybalko #include <sys/lock.h> 39*27cf7d04SAleksandr Rybalko #include <sys/malloc.h> 40*27cf7d04SAleksandr Rybalko #include <sys/mutex.h> 41*27cf7d04SAleksandr Rybalko #include <sys/systm.h> 42*27cf7d04SAleksandr Rybalko 43*27cf7d04SAleksandr Rybalko #include <dev/vt/vt.h> 44*27cf7d04SAleksandr Rybalko 45*27cf7d04SAleksandr Rybalko static MALLOC_DEFINE(M_VTBUF, "vtbuf", "vt buffer"); 46*27cf7d04SAleksandr Rybalko 47*27cf7d04SAleksandr Rybalko #define VTBUF_LOCK(vb) mtx_lock_spin(&(vb)->vb_lock) 48*27cf7d04SAleksandr Rybalko #define VTBUF_UNLOCK(vb) mtx_unlock_spin(&(vb)->vb_lock) 49*27cf7d04SAleksandr Rybalko 50*27cf7d04SAleksandr Rybalko #define POS_INDEX(c, r) (((r) << 12) + (c)) 51*27cf7d04SAleksandr Rybalko #define POS_COPY(d, s) do { \ 52*27cf7d04SAleksandr Rybalko (d).tp_col = (s).tp_col; \ 53*27cf7d04SAleksandr Rybalko (d).tp_row = (s).tp_row; \ 54*27cf7d04SAleksandr Rybalko } while (0) 55*27cf7d04SAleksandr Rybalko 56*27cf7d04SAleksandr Rybalko 57*27cf7d04SAleksandr Rybalko /* 58*27cf7d04SAleksandr Rybalko * line4 59*27cf7d04SAleksandr Rybalko * line5 <--- curroffset (terminal output to that line) 60*27cf7d04SAleksandr Rybalko * line0 61*27cf7d04SAleksandr Rybalko * line1 <--- roffset (history display from that point) 62*27cf7d04SAleksandr Rybalko * line2 63*27cf7d04SAleksandr Rybalko * line3 64*27cf7d04SAleksandr Rybalko */ 65*27cf7d04SAleksandr Rybalko int 66*27cf7d04SAleksandr Rybalko vthistory_seek(struct vt_buf *vb, int offset, int whence) 67*27cf7d04SAleksandr Rybalko { 68*27cf7d04SAleksandr Rybalko int diff, top, bottom, roffset; 69*27cf7d04SAleksandr Rybalko 70*27cf7d04SAleksandr Rybalko /* No scrolling if not enabled. */ 71*27cf7d04SAleksandr Rybalko if ((vb->vb_flags & VBF_SCROLL) == 0) { 72*27cf7d04SAleksandr Rybalko if (vb->vb_roffset != vb->vb_curroffset) { 73*27cf7d04SAleksandr Rybalko vb->vb_roffset = vb->vb_curroffset; 74*27cf7d04SAleksandr Rybalko return (0xffff); 75*27cf7d04SAleksandr Rybalko } 76*27cf7d04SAleksandr Rybalko return (0); /* No changes */ 77*27cf7d04SAleksandr Rybalko } 78*27cf7d04SAleksandr Rybalko top = (vb->vb_flags & VBF_HISTORY_FULL)? 79*27cf7d04SAleksandr Rybalko (vb->vb_curroffset + vb->vb_scr_size.tp_row):vb->vb_history_size; 80*27cf7d04SAleksandr Rybalko bottom = vb->vb_curroffset + vb->vb_history_size; 81*27cf7d04SAleksandr Rybalko 82*27cf7d04SAleksandr Rybalko /* 83*27cf7d04SAleksandr Rybalko * Operate on copy of offset value, since it temporary can be bigger 84*27cf7d04SAleksandr Rybalko * than amount of rows in buffer. 85*27cf7d04SAleksandr Rybalko */ 86*27cf7d04SAleksandr Rybalko roffset = vb->vb_roffset + vb->vb_history_size; 87*27cf7d04SAleksandr Rybalko switch (whence) { 88*27cf7d04SAleksandr Rybalko case VHS_SET: 89*27cf7d04SAleksandr Rybalko roffset = offset + vb->vb_history_size; 90*27cf7d04SAleksandr Rybalko break; 91*27cf7d04SAleksandr Rybalko case VHS_CUR: 92*27cf7d04SAleksandr Rybalko roffset += offset; 93*27cf7d04SAleksandr Rybalko break; 94*27cf7d04SAleksandr Rybalko case VHS_END: 95*27cf7d04SAleksandr Rybalko /* Go to current offset. */ 96*27cf7d04SAleksandr Rybalko roffset = vb->vb_curroffset + vb->vb_history_size; 97*27cf7d04SAleksandr Rybalko break; 98*27cf7d04SAleksandr Rybalko } 99*27cf7d04SAleksandr Rybalko 100*27cf7d04SAleksandr Rybalko roffset = (roffset < top)?top:roffset; 101*27cf7d04SAleksandr Rybalko roffset = (roffset > bottom)?bottom:roffset; 102*27cf7d04SAleksandr Rybalko 103*27cf7d04SAleksandr Rybalko roffset %= vb->vb_history_size; 104*27cf7d04SAleksandr Rybalko 105*27cf7d04SAleksandr Rybalko if (vb->vb_roffset != roffset) { 106*27cf7d04SAleksandr Rybalko diff = vb->vb_roffset - roffset; 107*27cf7d04SAleksandr Rybalko vb->vb_roffset = roffset; 108*27cf7d04SAleksandr Rybalko /* 109*27cf7d04SAleksandr Rybalko * Offset changed, please update Nth lines on sceen. 110*27cf7d04SAleksandr Rybalko * +N - Nth lines at top; 111*27cf7d04SAleksandr Rybalko * -N - Nth lines at bottom. 112*27cf7d04SAleksandr Rybalko */ 113*27cf7d04SAleksandr Rybalko return (diff); 114*27cf7d04SAleksandr Rybalko } 115*27cf7d04SAleksandr Rybalko return (0); /* No changes */ 116*27cf7d04SAleksandr Rybalko } 117*27cf7d04SAleksandr Rybalko 118*27cf7d04SAleksandr Rybalko void 119*27cf7d04SAleksandr Rybalko vthistory_addlines(struct vt_buf *vb, int offset) 120*27cf7d04SAleksandr Rybalko { 121*27cf7d04SAleksandr Rybalko 122*27cf7d04SAleksandr Rybalko vb->vb_curroffset += offset; 123*27cf7d04SAleksandr Rybalko if (vb->vb_curroffset < 0) 124*27cf7d04SAleksandr Rybalko vb->vb_curroffset = 0; 125*27cf7d04SAleksandr Rybalko vb->vb_curroffset %= vb->vb_history_size; 126*27cf7d04SAleksandr Rybalko if ((vb->vb_flags & VBF_SCROLL) == 0) { 127*27cf7d04SAleksandr Rybalko vb->vb_roffset = vb->vb_curroffset; 128*27cf7d04SAleksandr Rybalko } 129*27cf7d04SAleksandr Rybalko } 130*27cf7d04SAleksandr Rybalko 131*27cf7d04SAleksandr Rybalko void 132*27cf7d04SAleksandr Rybalko vthistory_getpos(const struct vt_buf *vb, unsigned int *offset) 133*27cf7d04SAleksandr Rybalko { 134*27cf7d04SAleksandr Rybalko 135*27cf7d04SAleksandr Rybalko *offset = vb->vb_roffset; 136*27cf7d04SAleksandr Rybalko } 137*27cf7d04SAleksandr Rybalko 138*27cf7d04SAleksandr Rybalko /* Translate current view row number to history row. */ 139*27cf7d04SAleksandr Rybalko static int 140*27cf7d04SAleksandr Rybalko vtbuf_wth(struct vt_buf *vb, int row) 141*27cf7d04SAleksandr Rybalko { 142*27cf7d04SAleksandr Rybalko 143*27cf7d04SAleksandr Rybalko return ((vb->vb_roffset + row) % vb->vb_history_size); 144*27cf7d04SAleksandr Rybalko } 145*27cf7d04SAleksandr Rybalko 146*27cf7d04SAleksandr Rybalko /* Translate history row to current view row number. */ 147*27cf7d04SAleksandr Rybalko static int 148*27cf7d04SAleksandr Rybalko vtbuf_htw(struct vt_buf *vb, int row) 149*27cf7d04SAleksandr Rybalko { 150*27cf7d04SAleksandr Rybalko 151*27cf7d04SAleksandr Rybalko /* 152*27cf7d04SAleksandr Rybalko * total 1000 rows. 153*27cf7d04SAleksandr Rybalko * History offset roffset winrow 154*27cf7d04SAleksandr Rybalko * 205 200 ((205 - 200 + 1000) % 1000) = 5 155*27cf7d04SAleksandr Rybalko * 90 990 ((90 - 990 + 1000) % 1000) = 100 156*27cf7d04SAleksandr Rybalko */ 157*27cf7d04SAleksandr Rybalko return ((row - vb->vb_roffset + vb->vb_history_size) % 158*27cf7d04SAleksandr Rybalko vb->vb_history_size); 159*27cf7d04SAleksandr Rybalko } 160*27cf7d04SAleksandr Rybalko 161*27cf7d04SAleksandr Rybalko int 162*27cf7d04SAleksandr Rybalko vtbuf_iscursor(struct vt_buf *vb, int row, int col) 163*27cf7d04SAleksandr Rybalko { 164*27cf7d04SAleksandr Rybalko int sc, sr, ec, er, tmp; 165*27cf7d04SAleksandr Rybalko 166*27cf7d04SAleksandr Rybalko if ((vb->vb_flags & (VBF_CURSOR|VBF_SCROLL)) == VBF_CURSOR && 167*27cf7d04SAleksandr Rybalko (vb->vb_cursor.tp_row == row) && (vb->vb_cursor.tp_col == col)) 168*27cf7d04SAleksandr Rybalko return (1); 169*27cf7d04SAleksandr Rybalko 170*27cf7d04SAleksandr Rybalko /* Mark cut/paste region. */ 171*27cf7d04SAleksandr Rybalko 172*27cf7d04SAleksandr Rybalko /* 173*27cf7d04SAleksandr Rybalko * Luckily screen view is not like circular buffer, so we will 174*27cf7d04SAleksandr Rybalko * calculate in screen coordinates. Translate first. 175*27cf7d04SAleksandr Rybalko */ 176*27cf7d04SAleksandr Rybalko sc = vb->vb_mark_start.tp_col; 177*27cf7d04SAleksandr Rybalko sr = vtbuf_htw(vb, vb->vb_mark_start.tp_row); 178*27cf7d04SAleksandr Rybalko ec = vb->vb_mark_end.tp_col; 179*27cf7d04SAleksandr Rybalko er = vtbuf_htw(vb, vb->vb_mark_end.tp_row); 180*27cf7d04SAleksandr Rybalko 181*27cf7d04SAleksandr Rybalko 182*27cf7d04SAleksandr Rybalko /* Swap start and end if start > end. */ 183*27cf7d04SAleksandr Rybalko if (POS_INDEX(sc, sr) > POS_INDEX(ec, er)) { 184*27cf7d04SAleksandr Rybalko tmp = sc; sc = ec; ec = tmp; 185*27cf7d04SAleksandr Rybalko tmp = sr; sr = er; er = tmp; 186*27cf7d04SAleksandr Rybalko } 187*27cf7d04SAleksandr Rybalko 188*27cf7d04SAleksandr Rybalko if ((POS_INDEX(sc, sr) <= POS_INDEX(col, row)) && 189*27cf7d04SAleksandr Rybalko (POS_INDEX(col, row) < POS_INDEX(ec, er))) 190*27cf7d04SAleksandr Rybalko return (1); 191*27cf7d04SAleksandr Rybalko 192*27cf7d04SAleksandr Rybalko return (0); 193*27cf7d04SAleksandr Rybalko } 194*27cf7d04SAleksandr Rybalko 195*27cf7d04SAleksandr Rybalko static inline uint64_t 196*27cf7d04SAleksandr Rybalko vtbuf_dirty_axis(unsigned int begin, unsigned int end) 197*27cf7d04SAleksandr Rybalko { 198*27cf7d04SAleksandr Rybalko uint64_t left, right, mask; 199*27cf7d04SAleksandr Rybalko 200*27cf7d04SAleksandr Rybalko /* 201*27cf7d04SAleksandr Rybalko * Mark all bits between begin % 64 and end % 64 dirty. 202*27cf7d04SAleksandr Rybalko * This code is functionally equivalent to: 203*27cf7d04SAleksandr Rybalko * 204*27cf7d04SAleksandr Rybalko * for (i = begin; i < end; i++) 205*27cf7d04SAleksandr Rybalko * mask |= (uint64_t)1 << (i % 64); 206*27cf7d04SAleksandr Rybalko */ 207*27cf7d04SAleksandr Rybalko 208*27cf7d04SAleksandr Rybalko /* Obvious case. Mark everything dirty. */ 209*27cf7d04SAleksandr Rybalko if (end - begin >= 64) 210*27cf7d04SAleksandr Rybalko return (VBM_DIRTY); 211*27cf7d04SAleksandr Rybalko 212*27cf7d04SAleksandr Rybalko /* 1....0; used bits on the left. */ 213*27cf7d04SAleksandr Rybalko left = VBM_DIRTY << begin % 64; 214*27cf7d04SAleksandr Rybalko /* 0....1; used bits on the right. */ 215*27cf7d04SAleksandr Rybalko right = VBM_DIRTY >> -end % 64; 216*27cf7d04SAleksandr Rybalko 217*27cf7d04SAleksandr Rybalko /* 218*27cf7d04SAleksandr Rybalko * Only take the intersection. If the result of that is 0, it 219*27cf7d04SAleksandr Rybalko * means that the selection crossed a 64 bit boundary along the 220*27cf7d04SAleksandr Rybalko * way, which means we have to take the complement. 221*27cf7d04SAleksandr Rybalko */ 222*27cf7d04SAleksandr Rybalko mask = left & right; 223*27cf7d04SAleksandr Rybalko if (mask == 0) 224*27cf7d04SAleksandr Rybalko mask = left | right; 225*27cf7d04SAleksandr Rybalko return (mask); 226*27cf7d04SAleksandr Rybalko } 227*27cf7d04SAleksandr Rybalko 228*27cf7d04SAleksandr Rybalko static inline void 229*27cf7d04SAleksandr Rybalko vtbuf_dirty(struct vt_buf *vb, const term_rect_t *area) 230*27cf7d04SAleksandr Rybalko { 231*27cf7d04SAleksandr Rybalko 232*27cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 233*27cf7d04SAleksandr Rybalko if (vb->vb_dirtyrect.tr_begin.tp_row > area->tr_begin.tp_row) 234*27cf7d04SAleksandr Rybalko vb->vb_dirtyrect.tr_begin.tp_row = area->tr_begin.tp_row; 235*27cf7d04SAleksandr Rybalko if (vb->vb_dirtyrect.tr_begin.tp_col > area->tr_begin.tp_col) 236*27cf7d04SAleksandr Rybalko vb->vb_dirtyrect.tr_begin.tp_col = area->tr_begin.tp_col; 237*27cf7d04SAleksandr Rybalko if (vb->vb_dirtyrect.tr_end.tp_row < area->tr_end.tp_row) 238*27cf7d04SAleksandr Rybalko vb->vb_dirtyrect.tr_end.tp_row = area->tr_end.tp_row; 239*27cf7d04SAleksandr Rybalko if (vb->vb_dirtyrect.tr_end.tp_col < area->tr_end.tp_col) 240*27cf7d04SAleksandr Rybalko vb->vb_dirtyrect.tr_end.tp_col = area->tr_end.tp_col; 241*27cf7d04SAleksandr Rybalko vb->vb_dirtymask.vbm_row |= 242*27cf7d04SAleksandr Rybalko vtbuf_dirty_axis(area->tr_begin.tp_row, area->tr_end.tp_row); 243*27cf7d04SAleksandr Rybalko vb->vb_dirtymask.vbm_col |= 244*27cf7d04SAleksandr Rybalko vtbuf_dirty_axis(area->tr_begin.tp_col, area->tr_end.tp_col); 245*27cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 246*27cf7d04SAleksandr Rybalko } 247*27cf7d04SAleksandr Rybalko 248*27cf7d04SAleksandr Rybalko static inline void 249*27cf7d04SAleksandr Rybalko vtbuf_dirty_cell(struct vt_buf *vb, const term_pos_t *p) 250*27cf7d04SAleksandr Rybalko { 251*27cf7d04SAleksandr Rybalko term_rect_t area; 252*27cf7d04SAleksandr Rybalko 253*27cf7d04SAleksandr Rybalko area.tr_begin = *p; 254*27cf7d04SAleksandr Rybalko area.tr_end.tp_row = p->tp_row + 1; 255*27cf7d04SAleksandr Rybalko area.tr_end.tp_col = p->tp_col + 1; 256*27cf7d04SAleksandr Rybalko vtbuf_dirty(vb, &area); 257*27cf7d04SAleksandr Rybalko } 258*27cf7d04SAleksandr Rybalko 259*27cf7d04SAleksandr Rybalko static void 260*27cf7d04SAleksandr Rybalko vtbuf_make_undirty(struct vt_buf *vb) 261*27cf7d04SAleksandr Rybalko { 262*27cf7d04SAleksandr Rybalko 263*27cf7d04SAleksandr Rybalko vb->vb_dirtyrect.tr_begin = vb->vb_scr_size; 264*27cf7d04SAleksandr Rybalko vb->vb_dirtyrect.tr_end.tp_row = vb->vb_dirtyrect.tr_end.tp_col = 0; 265*27cf7d04SAleksandr Rybalko vb->vb_dirtymask.vbm_row = vb->vb_dirtymask.vbm_col = 0; 266*27cf7d04SAleksandr Rybalko } 267*27cf7d04SAleksandr Rybalko 268*27cf7d04SAleksandr Rybalko void 269*27cf7d04SAleksandr Rybalko vtbuf_undirty(struct vt_buf *vb, term_rect_t *r, struct vt_bufmask *m) 270*27cf7d04SAleksandr Rybalko { 271*27cf7d04SAleksandr Rybalko 272*27cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 273*27cf7d04SAleksandr Rybalko *r = vb->vb_dirtyrect; 274*27cf7d04SAleksandr Rybalko *m = vb->vb_dirtymask; 275*27cf7d04SAleksandr Rybalko vtbuf_make_undirty(vb); 276*27cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 277*27cf7d04SAleksandr Rybalko } 278*27cf7d04SAleksandr Rybalko 279*27cf7d04SAleksandr Rybalko void 280*27cf7d04SAleksandr Rybalko vtbuf_copy(struct vt_buf *vb, const term_rect_t *r, const term_pos_t *p2) 281*27cf7d04SAleksandr Rybalko { 282*27cf7d04SAleksandr Rybalko const term_pos_t *p1 = &r->tr_begin; 283*27cf7d04SAleksandr Rybalko term_rect_t area; 284*27cf7d04SAleksandr Rybalko unsigned int rows, cols; 285*27cf7d04SAleksandr Rybalko int pr, rdiff; 286*27cf7d04SAleksandr Rybalko 287*27cf7d04SAleksandr Rybalko KASSERT(r->tr_begin.tp_row < vb->vb_scr_size.tp_row, 288*27cf7d04SAleksandr Rybalko ("vtbuf_copy begin.tp_row %d must be less than screen width %d", 289*27cf7d04SAleksandr Rybalko r->tr_begin.tp_row, vb->vb_scr_size.tp_row)); 290*27cf7d04SAleksandr Rybalko KASSERT(r->tr_begin.tp_col < vb->vb_scr_size.tp_col, 291*27cf7d04SAleksandr Rybalko ("vtbuf_copy begin.tp_col %d must be less than screen height %d", 292*27cf7d04SAleksandr Rybalko r->tr_begin.tp_col, vb->vb_scr_size.tp_col)); 293*27cf7d04SAleksandr Rybalko 294*27cf7d04SAleksandr Rybalko KASSERT(r->tr_end.tp_row <= vb->vb_scr_size.tp_row, 295*27cf7d04SAleksandr Rybalko ("vtbuf_copy end.tp_row %d must be less than screen width %d", 296*27cf7d04SAleksandr Rybalko r->tr_end.tp_row, vb->vb_scr_size.tp_row)); 297*27cf7d04SAleksandr Rybalko KASSERT(r->tr_end.tp_col <= vb->vb_scr_size.tp_col, 298*27cf7d04SAleksandr Rybalko ("vtbuf_copy end.tp_col %d must be less than screen height %d", 299*27cf7d04SAleksandr Rybalko r->tr_end.tp_col, vb->vb_scr_size.tp_col)); 300*27cf7d04SAleksandr Rybalko 301*27cf7d04SAleksandr Rybalko KASSERT(p2->tp_row < vb->vb_scr_size.tp_row, 302*27cf7d04SAleksandr Rybalko ("vtbuf_copy tp_row %d must be less than screen width %d", 303*27cf7d04SAleksandr Rybalko p2->tp_row, vb->vb_scr_size.tp_row)); 304*27cf7d04SAleksandr Rybalko KASSERT(p2->tp_col < vb->vb_scr_size.tp_col, 305*27cf7d04SAleksandr Rybalko ("vtbuf_copy tp_col %d must be less than screen height %d", 306*27cf7d04SAleksandr Rybalko p2->tp_col, vb->vb_scr_size.tp_col)); 307*27cf7d04SAleksandr Rybalko 308*27cf7d04SAleksandr Rybalko rows = r->tr_end.tp_row - r->tr_begin.tp_row; 309*27cf7d04SAleksandr Rybalko rdiff = r->tr_begin.tp_row - p2->tp_row; 310*27cf7d04SAleksandr Rybalko cols = r->tr_end.tp_col - r->tr_begin.tp_col; 311*27cf7d04SAleksandr Rybalko if (r->tr_begin.tp_row > p2->tp_row && r->tr_begin.tp_col == 0 && 312*27cf7d04SAleksandr Rybalko r->tr_end.tp_col == vb->vb_scr_size.tp_col && /* Full row. */ 313*27cf7d04SAleksandr Rybalko (rows + rdiff) == vb->vb_scr_size.tp_row && /* Whole screen. */ 314*27cf7d04SAleksandr Rybalko rdiff > 0) { /* Only forward dirrection. Do not eat history. */ 315*27cf7d04SAleksandr Rybalko vthistory_addlines(vb, rdiff); 316*27cf7d04SAleksandr Rybalko } else if (p2->tp_row < p1->tp_row) { 317*27cf7d04SAleksandr Rybalko /* Handle overlapping copies of line segments. */ 318*27cf7d04SAleksandr Rybalko /* Move data up. */ 319*27cf7d04SAleksandr Rybalko for (pr = 0; pr < rows; pr++) 320*27cf7d04SAleksandr Rybalko memmove( 321*27cf7d04SAleksandr Rybalko &VTBUF_FIELD(vb, p2->tp_row + pr, p2->tp_col), 322*27cf7d04SAleksandr Rybalko &VTBUF_FIELD(vb, p1->tp_row + pr, p1->tp_col), 323*27cf7d04SAleksandr Rybalko cols * sizeof(term_char_t)); 324*27cf7d04SAleksandr Rybalko } else { 325*27cf7d04SAleksandr Rybalko /* Move data down. */ 326*27cf7d04SAleksandr Rybalko for (pr = rows - 1; pr >= 0; pr--) 327*27cf7d04SAleksandr Rybalko memmove( 328*27cf7d04SAleksandr Rybalko &VTBUF_FIELD(vb, p2->tp_row + pr, p2->tp_col), 329*27cf7d04SAleksandr Rybalko &VTBUF_FIELD(vb, p1->tp_row + pr, p1->tp_col), 330*27cf7d04SAleksandr Rybalko cols * sizeof(term_char_t)); 331*27cf7d04SAleksandr Rybalko } 332*27cf7d04SAleksandr Rybalko 333*27cf7d04SAleksandr Rybalko area.tr_begin = *p2; 334*27cf7d04SAleksandr Rybalko area.tr_end.tp_row = MIN(p2->tp_row + rows, vb->vb_scr_size.tp_row); 335*27cf7d04SAleksandr Rybalko area.tr_end.tp_col = MIN(p2->tp_col + cols, vb->vb_scr_size.tp_col); 336*27cf7d04SAleksandr Rybalko vtbuf_dirty(vb, &area); 337*27cf7d04SAleksandr Rybalko } 338*27cf7d04SAleksandr Rybalko 339*27cf7d04SAleksandr Rybalko static void 340*27cf7d04SAleksandr Rybalko vtbuf_fill(struct vt_buf *vb, const term_rect_t *r, term_char_t c) 341*27cf7d04SAleksandr Rybalko { 342*27cf7d04SAleksandr Rybalko unsigned int pr, pc; 343*27cf7d04SAleksandr Rybalko term_char_t *row; 344*27cf7d04SAleksandr Rybalko 345*27cf7d04SAleksandr Rybalko for (pr = r->tr_begin.tp_row; pr < r->tr_end.tp_row; pr++) { 346*27cf7d04SAleksandr Rybalko row = vb->vb_rows[(vb->vb_curroffset + pr) % 347*27cf7d04SAleksandr Rybalko VTBUF_MAX_HEIGHT(vb)]; 348*27cf7d04SAleksandr Rybalko for (pc = r->tr_begin.tp_col; pc < r->tr_end.tp_col; pc++) { 349*27cf7d04SAleksandr Rybalko row[pc] = c; 350*27cf7d04SAleksandr Rybalko } 351*27cf7d04SAleksandr Rybalko } 352*27cf7d04SAleksandr Rybalko } 353*27cf7d04SAleksandr Rybalko 354*27cf7d04SAleksandr Rybalko void 355*27cf7d04SAleksandr Rybalko vtbuf_fill_locked(struct vt_buf *vb, const term_rect_t *r, term_char_t c) 356*27cf7d04SAleksandr Rybalko { 357*27cf7d04SAleksandr Rybalko KASSERT(r->tr_begin.tp_row < vb->vb_scr_size.tp_row, 358*27cf7d04SAleksandr Rybalko ("vtbuf_fill_locked begin.tp_row %d must be < screen width %d", 359*27cf7d04SAleksandr Rybalko r->tr_begin.tp_row, vb->vb_scr_size.tp_row)); 360*27cf7d04SAleksandr Rybalko KASSERT(r->tr_begin.tp_col < vb->vb_scr_size.tp_col, 361*27cf7d04SAleksandr Rybalko ("vtbuf_fill_locked begin.tp_col %d must be < screen height %d", 362*27cf7d04SAleksandr Rybalko r->tr_begin.tp_col, vb->vb_scr_size.tp_col)); 363*27cf7d04SAleksandr Rybalko 364*27cf7d04SAleksandr Rybalko KASSERT(r->tr_end.tp_row <= vb->vb_scr_size.tp_row, 365*27cf7d04SAleksandr Rybalko ("vtbuf_fill_locked end.tp_row %d must be <= screen width %d", 366*27cf7d04SAleksandr Rybalko r->tr_end.tp_row, vb->vb_scr_size.tp_row)); 367*27cf7d04SAleksandr Rybalko KASSERT(r->tr_end.tp_col <= vb->vb_scr_size.tp_col, 368*27cf7d04SAleksandr Rybalko ("vtbuf_fill_locked end.tp_col %d must be <= screen height %d", 369*27cf7d04SAleksandr Rybalko r->tr_end.tp_col, vb->vb_scr_size.tp_col)); 370*27cf7d04SAleksandr Rybalko 371*27cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 372*27cf7d04SAleksandr Rybalko vtbuf_fill(vb, r, c); 373*27cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 374*27cf7d04SAleksandr Rybalko 375*27cf7d04SAleksandr Rybalko vtbuf_dirty(vb, r); 376*27cf7d04SAleksandr Rybalko } 377*27cf7d04SAleksandr Rybalko 378*27cf7d04SAleksandr Rybalko static void 379*27cf7d04SAleksandr Rybalko vtbuf_init_rows(struct vt_buf *vb) 380*27cf7d04SAleksandr Rybalko { 381*27cf7d04SAleksandr Rybalko int r; 382*27cf7d04SAleksandr Rybalko 383*27cf7d04SAleksandr Rybalko vb->vb_history_size = MAX(vb->vb_history_size, vb->vb_scr_size.tp_row); 384*27cf7d04SAleksandr Rybalko 385*27cf7d04SAleksandr Rybalko for (r = 0; r < vb->vb_history_size; r++) 386*27cf7d04SAleksandr Rybalko vb->vb_rows[r] = &vb->vb_buffer[r * 387*27cf7d04SAleksandr Rybalko vb->vb_scr_size.tp_col]; 388*27cf7d04SAleksandr Rybalko } 389*27cf7d04SAleksandr Rybalko 390*27cf7d04SAleksandr Rybalko void 391*27cf7d04SAleksandr Rybalko vtbuf_init_early(struct vt_buf *vb) 392*27cf7d04SAleksandr Rybalko { 393*27cf7d04SAleksandr Rybalko 394*27cf7d04SAleksandr Rybalko vb->vb_flags |= VBF_CURSOR; 395*27cf7d04SAleksandr Rybalko vb->vb_roffset = 0; 396*27cf7d04SAleksandr Rybalko vb->vb_curroffset = 0; 397*27cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_row = 0; 398*27cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col = 0; 399*27cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_row = 0; 400*27cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col = 0; 401*27cf7d04SAleksandr Rybalko 402*27cf7d04SAleksandr Rybalko vtbuf_init_rows(vb); 403*27cf7d04SAleksandr Rybalko vtbuf_make_undirty(vb); 404*27cf7d04SAleksandr Rybalko if ((vb->vb_flags & VBF_MTX_INIT) == 0) { 405*27cf7d04SAleksandr Rybalko mtx_init(&vb->vb_lock, "vtbuf", NULL, MTX_SPIN); 406*27cf7d04SAleksandr Rybalko vb->vb_flags |= VBF_MTX_INIT; 407*27cf7d04SAleksandr Rybalko } 408*27cf7d04SAleksandr Rybalko } 409*27cf7d04SAleksandr Rybalko 410*27cf7d04SAleksandr Rybalko void 411*27cf7d04SAleksandr Rybalko vtbuf_init(struct vt_buf *vb, const term_pos_t *p) 412*27cf7d04SAleksandr Rybalko { 413*27cf7d04SAleksandr Rybalko int sz; 414*27cf7d04SAleksandr Rybalko 415*27cf7d04SAleksandr Rybalko vb->vb_scr_size = *p; 416*27cf7d04SAleksandr Rybalko vb->vb_history_size = VBF_DEFAULT_HISTORY_SIZE; 417*27cf7d04SAleksandr Rybalko 418*27cf7d04SAleksandr Rybalko if ((vb->vb_flags & VBF_STATIC) == 0) { 419*27cf7d04SAleksandr Rybalko sz = vb->vb_history_size * p->tp_col * sizeof(term_char_t); 420*27cf7d04SAleksandr Rybalko vb->vb_buffer = malloc(sz, M_VTBUF, M_WAITOK | M_ZERO); 421*27cf7d04SAleksandr Rybalko 422*27cf7d04SAleksandr Rybalko sz = vb->vb_history_size * sizeof(term_char_t *); 423*27cf7d04SAleksandr Rybalko vb->vb_rows = malloc(sz, M_VTBUF, M_WAITOK | M_ZERO); 424*27cf7d04SAleksandr Rybalko } 425*27cf7d04SAleksandr Rybalko 426*27cf7d04SAleksandr Rybalko vtbuf_init_early(vb); 427*27cf7d04SAleksandr Rybalko } 428*27cf7d04SAleksandr Rybalko 429*27cf7d04SAleksandr Rybalko void 430*27cf7d04SAleksandr Rybalko vtbuf_sethistory_size(struct vt_buf *vb, int size) 431*27cf7d04SAleksandr Rybalko { 432*27cf7d04SAleksandr Rybalko term_pos_t p; 433*27cf7d04SAleksandr Rybalko 434*27cf7d04SAleksandr Rybalko /* With same size */ 435*27cf7d04SAleksandr Rybalko p.tp_row = vb->vb_scr_size.tp_row; 436*27cf7d04SAleksandr Rybalko p.tp_col = vb->vb_scr_size.tp_col; 437*27cf7d04SAleksandr Rybalko vtbuf_grow(vb, &p, size); 438*27cf7d04SAleksandr Rybalko } 439*27cf7d04SAleksandr Rybalko 440*27cf7d04SAleksandr Rybalko void 441*27cf7d04SAleksandr Rybalko vtbuf_grow(struct vt_buf *vb, const term_pos_t *p, int history_size) 442*27cf7d04SAleksandr Rybalko { 443*27cf7d04SAleksandr Rybalko term_char_t *old, *new, **rows, **oldrows, **copyrows, *row; 444*27cf7d04SAleksandr Rybalko int bufsize, rowssize, w, h, c, r; 445*27cf7d04SAleksandr Rybalko term_rect_t rect; 446*27cf7d04SAleksandr Rybalko 447*27cf7d04SAleksandr Rybalko history_size = MAX(history_size, p->tp_row); 448*27cf7d04SAleksandr Rybalko 449*27cf7d04SAleksandr Rybalko if (history_size > vb->vb_history_size || p->tp_col > 450*27cf7d04SAleksandr Rybalko vb->vb_scr_size.tp_col) { 451*27cf7d04SAleksandr Rybalko /* Allocate new buffer. */ 452*27cf7d04SAleksandr Rybalko bufsize = history_size * p->tp_col * sizeof(term_char_t); 453*27cf7d04SAleksandr Rybalko new = malloc(bufsize, M_VTBUF, M_WAITOK | M_ZERO); 454*27cf7d04SAleksandr Rybalko rowssize = history_size * sizeof(term_pos_t *); 455*27cf7d04SAleksandr Rybalko rows = malloc(rowssize, M_VTBUF, M_WAITOK | M_ZERO); 456*27cf7d04SAleksandr Rybalko 457*27cf7d04SAleksandr Rybalko /* Toggle it. */ 458*27cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 459*27cf7d04SAleksandr Rybalko old = vb->vb_flags & VBF_STATIC ? NULL : vb->vb_buffer; 460*27cf7d04SAleksandr Rybalko oldrows = vb->vb_flags & VBF_STATIC ? NULL : vb->vb_rows; 461*27cf7d04SAleksandr Rybalko copyrows = vb->vb_rows; 462*27cf7d04SAleksandr Rybalko w = vb->vb_scr_size.tp_col; 463*27cf7d04SAleksandr Rybalko h = vb->vb_history_size; 464*27cf7d04SAleksandr Rybalko 465*27cf7d04SAleksandr Rybalko vb->vb_history_size = history_size; 466*27cf7d04SAleksandr Rybalko vb->vb_buffer = new; 467*27cf7d04SAleksandr Rybalko vb->vb_rows = rows; 468*27cf7d04SAleksandr Rybalko vb->vb_flags &= ~VBF_STATIC; 469*27cf7d04SAleksandr Rybalko vb->vb_scr_size = *p; 470*27cf7d04SAleksandr Rybalko vtbuf_init_rows(vb); 471*27cf7d04SAleksandr Rybalko 472*27cf7d04SAleksandr Rybalko /* Copy history and fill extra space. */ 473*27cf7d04SAleksandr Rybalko for (r = 0; r < history_size; r ++) { 474*27cf7d04SAleksandr Rybalko row = rows[r]; 475*27cf7d04SAleksandr Rybalko if (r < h) { /* Copy. */ 476*27cf7d04SAleksandr Rybalko memmove(rows[r], copyrows[r], 477*27cf7d04SAleksandr Rybalko MIN(p->tp_col, w) * sizeof(term_char_t)); 478*27cf7d04SAleksandr Rybalko for (c = MIN(p->tp_col, w); c < p->tp_col; 479*27cf7d04SAleksandr Rybalko c++) { 480*27cf7d04SAleksandr Rybalko row[c] = VTBUF_SPACE_CHAR; 481*27cf7d04SAleksandr Rybalko } 482*27cf7d04SAleksandr Rybalko } else { /* Just fill. */ 483*27cf7d04SAleksandr Rybalko rect.tr_begin.tp_col = 0; 484*27cf7d04SAleksandr Rybalko rect.tr_begin.tp_row = r; 485*27cf7d04SAleksandr Rybalko rect.tr_end.tp_col = p->tp_col; 486*27cf7d04SAleksandr Rybalko rect.tr_end.tp_row = p->tp_row; 487*27cf7d04SAleksandr Rybalko vtbuf_fill(vb, &rect, VTBUF_SPACE_CHAR); 488*27cf7d04SAleksandr Rybalko break; 489*27cf7d04SAleksandr Rybalko } 490*27cf7d04SAleksandr Rybalko } 491*27cf7d04SAleksandr Rybalko vtbuf_make_undirty(vb); 492*27cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 493*27cf7d04SAleksandr Rybalko /* Deallocate old buffer. */ 494*27cf7d04SAleksandr Rybalko free(old, M_VTBUF); 495*27cf7d04SAleksandr Rybalko free(oldrows, M_VTBUF); 496*27cf7d04SAleksandr Rybalko } 497*27cf7d04SAleksandr Rybalko } 498*27cf7d04SAleksandr Rybalko 499*27cf7d04SAleksandr Rybalko void 500*27cf7d04SAleksandr Rybalko vtbuf_putchar(struct vt_buf *vb, const term_pos_t *p, term_char_t c) 501*27cf7d04SAleksandr Rybalko { 502*27cf7d04SAleksandr Rybalko term_char_t *row; 503*27cf7d04SAleksandr Rybalko 504*27cf7d04SAleksandr Rybalko KASSERT(p->tp_row < vb->vb_scr_size.tp_row, 505*27cf7d04SAleksandr Rybalko ("vtbuf_putchar tp_row %d must be less than screen width %d", 506*27cf7d04SAleksandr Rybalko p->tp_row, vb->vb_scr_size.tp_row)); 507*27cf7d04SAleksandr Rybalko KASSERT(p->tp_col < vb->vb_scr_size.tp_col, 508*27cf7d04SAleksandr Rybalko ("vtbuf_putchar tp_col %d must be less than screen height %d", 509*27cf7d04SAleksandr Rybalko p->tp_col, vb->vb_scr_size.tp_col)); 510*27cf7d04SAleksandr Rybalko 511*27cf7d04SAleksandr Rybalko row = vb->vb_rows[(vb->vb_curroffset + p->tp_row) % 512*27cf7d04SAleksandr Rybalko VTBUF_MAX_HEIGHT(vb)]; 513*27cf7d04SAleksandr Rybalko if (row[p->tp_col] != c) { 514*27cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 515*27cf7d04SAleksandr Rybalko row[p->tp_col] = c; 516*27cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 517*27cf7d04SAleksandr Rybalko vtbuf_dirty_cell(vb, p); 518*27cf7d04SAleksandr Rybalko } 519*27cf7d04SAleksandr Rybalko } 520*27cf7d04SAleksandr Rybalko 521*27cf7d04SAleksandr Rybalko void 522*27cf7d04SAleksandr Rybalko vtbuf_cursor_position(struct vt_buf *vb, const term_pos_t *p) 523*27cf7d04SAleksandr Rybalko { 524*27cf7d04SAleksandr Rybalko 525*27cf7d04SAleksandr Rybalko if (vb->vb_flags & VBF_CURSOR) { 526*27cf7d04SAleksandr Rybalko vtbuf_dirty_cell(vb, &vb->vb_cursor); 527*27cf7d04SAleksandr Rybalko vb->vb_cursor = *p; 528*27cf7d04SAleksandr Rybalko vtbuf_dirty_cell(vb, &vb->vb_cursor); 529*27cf7d04SAleksandr Rybalko } else { 530*27cf7d04SAleksandr Rybalko vb->vb_cursor = *p; 531*27cf7d04SAleksandr Rybalko } 532*27cf7d04SAleksandr Rybalko } 533*27cf7d04SAleksandr Rybalko 534*27cf7d04SAleksandr Rybalko void 535*27cf7d04SAleksandr Rybalko vtbuf_mouse_cursor_position(struct vt_buf *vb, int col, int row) 536*27cf7d04SAleksandr Rybalko { 537*27cf7d04SAleksandr Rybalko term_rect_t area; 538*27cf7d04SAleksandr Rybalko 539*27cf7d04SAleksandr Rybalko area.tr_begin.tp_row = MAX(row - 1, 0); 540*27cf7d04SAleksandr Rybalko area.tr_begin.tp_col = MAX(col - 1, 0); 541*27cf7d04SAleksandr Rybalko area.tr_end.tp_row = MIN(row + 2, vb->vb_scr_size.tp_row); 542*27cf7d04SAleksandr Rybalko area.tr_end.tp_col = MIN(col + 2, vb->vb_scr_size.tp_col); 543*27cf7d04SAleksandr Rybalko vtbuf_dirty(vb, &area); 544*27cf7d04SAleksandr Rybalko } 545*27cf7d04SAleksandr Rybalko 546*27cf7d04SAleksandr Rybalko static void 547*27cf7d04SAleksandr Rybalko vtbuf_flush_mark(struct vt_buf *vb) 548*27cf7d04SAleksandr Rybalko { 549*27cf7d04SAleksandr Rybalko term_rect_t area; 550*27cf7d04SAleksandr Rybalko int s, e; 551*27cf7d04SAleksandr Rybalko 552*27cf7d04SAleksandr Rybalko /* Notify renderer to update marked region. */ 553*27cf7d04SAleksandr Rybalko if (vb->vb_mark_start.tp_col || vb->vb_mark_end.tp_col || 554*27cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_row || vb->vb_mark_end.tp_row) { 555*27cf7d04SAleksandr Rybalko 556*27cf7d04SAleksandr Rybalko s = vtbuf_htw(vb, vb->vb_mark_start.tp_row); 557*27cf7d04SAleksandr Rybalko e = vtbuf_htw(vb, vb->vb_mark_end.tp_row); 558*27cf7d04SAleksandr Rybalko 559*27cf7d04SAleksandr Rybalko area.tr_begin.tp_col = 0; 560*27cf7d04SAleksandr Rybalko area.tr_begin.tp_row = MIN(s, e); 561*27cf7d04SAleksandr Rybalko 562*27cf7d04SAleksandr Rybalko area.tr_end.tp_col = vb->vb_scr_size.tp_col; 563*27cf7d04SAleksandr Rybalko area.tr_end.tp_row = MAX(s, e) + 1; 564*27cf7d04SAleksandr Rybalko 565*27cf7d04SAleksandr Rybalko vtbuf_dirty(vb, &area); 566*27cf7d04SAleksandr Rybalko } 567*27cf7d04SAleksandr Rybalko } 568*27cf7d04SAleksandr Rybalko 569*27cf7d04SAleksandr Rybalko int 570*27cf7d04SAleksandr Rybalko vtbuf_get_marked_len(struct vt_buf *vb) 571*27cf7d04SAleksandr Rybalko { 572*27cf7d04SAleksandr Rybalko int ei, si, sz; 573*27cf7d04SAleksandr Rybalko term_pos_t s, e; 574*27cf7d04SAleksandr Rybalko 575*27cf7d04SAleksandr Rybalko /* Swap according to window coordinates. */ 576*27cf7d04SAleksandr Rybalko if (POS_INDEX(vtbuf_htw(vb, vb->vb_mark_start.tp_row), 577*27cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col) > 578*27cf7d04SAleksandr Rybalko POS_INDEX(vtbuf_htw(vb, vb->vb_mark_end.tp_row), 579*27cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col)) { 580*27cf7d04SAleksandr Rybalko POS_COPY(e, vb->vb_mark_start); 581*27cf7d04SAleksandr Rybalko POS_COPY(s, vb->vb_mark_end); 582*27cf7d04SAleksandr Rybalko } else { 583*27cf7d04SAleksandr Rybalko POS_COPY(s, vb->vb_mark_start); 584*27cf7d04SAleksandr Rybalko POS_COPY(e, vb->vb_mark_end); 585*27cf7d04SAleksandr Rybalko } 586*27cf7d04SAleksandr Rybalko 587*27cf7d04SAleksandr Rybalko si = s.tp_row * vb->vb_scr_size.tp_col + s.tp_col; 588*27cf7d04SAleksandr Rybalko ei = e.tp_row * vb->vb_scr_size.tp_col + e.tp_col; 589*27cf7d04SAleksandr Rybalko 590*27cf7d04SAleksandr Rybalko /* Number symbols and number of rows to inject \n */ 591*27cf7d04SAleksandr Rybalko sz = ei - si + ((e.tp_row - s.tp_row) * 2) + 1; 592*27cf7d04SAleksandr Rybalko 593*27cf7d04SAleksandr Rybalko return (sz * sizeof(term_char_t)); 594*27cf7d04SAleksandr Rybalko } 595*27cf7d04SAleksandr Rybalko 596*27cf7d04SAleksandr Rybalko void 597*27cf7d04SAleksandr Rybalko vtbuf_extract_marked(struct vt_buf *vb, term_char_t *buf, int sz) 598*27cf7d04SAleksandr Rybalko { 599*27cf7d04SAleksandr Rybalko int i, r, c, cs, ce; 600*27cf7d04SAleksandr Rybalko term_pos_t s, e; 601*27cf7d04SAleksandr Rybalko 602*27cf7d04SAleksandr Rybalko /* Swap according to window coordinates. */ 603*27cf7d04SAleksandr Rybalko if (POS_INDEX(vtbuf_htw(vb, vb->vb_mark_start.tp_row), 604*27cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col) > 605*27cf7d04SAleksandr Rybalko POS_INDEX(vtbuf_htw(vb, vb->vb_mark_end.tp_row), 606*27cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col)) { 607*27cf7d04SAleksandr Rybalko POS_COPY(e, vb->vb_mark_start); 608*27cf7d04SAleksandr Rybalko POS_COPY(s, vb->vb_mark_end); 609*27cf7d04SAleksandr Rybalko } else { 610*27cf7d04SAleksandr Rybalko POS_COPY(s, vb->vb_mark_start); 611*27cf7d04SAleksandr Rybalko POS_COPY(e, vb->vb_mark_end); 612*27cf7d04SAleksandr Rybalko } 613*27cf7d04SAleksandr Rybalko 614*27cf7d04SAleksandr Rybalko i = 0; 615*27cf7d04SAleksandr Rybalko for (r = s.tp_row; r <= e.tp_row; r ++) { 616*27cf7d04SAleksandr Rybalko cs = (r == s.tp_row)?s.tp_col:0; 617*27cf7d04SAleksandr Rybalko ce = (r == e.tp_row)?e.tp_col:vb->vb_scr_size.tp_col; 618*27cf7d04SAleksandr Rybalko for (c = cs; c < ce; c ++) { 619*27cf7d04SAleksandr Rybalko buf[i++] = vb->vb_rows[r][c]; 620*27cf7d04SAleksandr Rybalko } 621*27cf7d04SAleksandr Rybalko /* Add new line for all rows, but not for last one. */ 622*27cf7d04SAleksandr Rybalko if (r != e.tp_row) { 623*27cf7d04SAleksandr Rybalko buf[i++] = '\r'; 624*27cf7d04SAleksandr Rybalko buf[i++] = '\n'; 625*27cf7d04SAleksandr Rybalko } 626*27cf7d04SAleksandr Rybalko } 627*27cf7d04SAleksandr Rybalko } 628*27cf7d04SAleksandr Rybalko 629*27cf7d04SAleksandr Rybalko int 630*27cf7d04SAleksandr Rybalko vtbuf_set_mark(struct vt_buf *vb, int type, int col, int row) 631*27cf7d04SAleksandr Rybalko { 632*27cf7d04SAleksandr Rybalko term_char_t *r; 633*27cf7d04SAleksandr Rybalko int i; 634*27cf7d04SAleksandr Rybalko 635*27cf7d04SAleksandr Rybalko switch (type) { 636*27cf7d04SAleksandr Rybalko case VTB_MARK_END: /* B1 UP */ 637*27cf7d04SAleksandr Rybalko if (vb->vb_mark_last != VTB_MARK_MOVE) 638*27cf7d04SAleksandr Rybalko return (0); 639*27cf7d04SAleksandr Rybalko /* FALLTHROUGH */ 640*27cf7d04SAleksandr Rybalko case VTB_MARK_MOVE: 641*27cf7d04SAleksandr Rybalko case VTB_MARK_EXTEND: 642*27cf7d04SAleksandr Rybalko vtbuf_flush_mark(vb); /* Clean old mark. */ 643*27cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col = col; 644*27cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_row = vtbuf_wth(vb, row); 645*27cf7d04SAleksandr Rybalko break; 646*27cf7d04SAleksandr Rybalko case VTB_MARK_START: 647*27cf7d04SAleksandr Rybalko vtbuf_flush_mark(vb); /* Clean old mark. */ 648*27cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col = col; 649*27cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_row = vtbuf_wth(vb, row); 650*27cf7d04SAleksandr Rybalko /* Start again, so clear end point. */ 651*27cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col = col; 652*27cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_row = vtbuf_wth(vb, row); 653*27cf7d04SAleksandr Rybalko break; 654*27cf7d04SAleksandr Rybalko case VTB_MARK_WORD: 655*27cf7d04SAleksandr Rybalko vtbuf_flush_mark(vb); /* Clean old mark. */ 656*27cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_row = vb->vb_mark_end.tp_row = 657*27cf7d04SAleksandr Rybalko vtbuf_wth(vb, row); 658*27cf7d04SAleksandr Rybalko r = vb->vb_rows[vb->vb_mark_start.tp_row]; 659*27cf7d04SAleksandr Rybalko for (i = col; i >= 0; i --) { 660*27cf7d04SAleksandr Rybalko if (TCHAR_CHARACTER(r[i]) == ' ') { 661*27cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col = i + 1; 662*27cf7d04SAleksandr Rybalko break; 663*27cf7d04SAleksandr Rybalko } 664*27cf7d04SAleksandr Rybalko } 665*27cf7d04SAleksandr Rybalko for (i = col; i < vb->vb_scr_size.tp_col; i ++) { 666*27cf7d04SAleksandr Rybalko if (TCHAR_CHARACTER(r[i]) == ' ') { 667*27cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col = i; 668*27cf7d04SAleksandr Rybalko break; 669*27cf7d04SAleksandr Rybalko } 670*27cf7d04SAleksandr Rybalko } 671*27cf7d04SAleksandr Rybalko if (vb->vb_mark_start.tp_col > vb->vb_mark_end.tp_col) 672*27cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col = vb->vb_mark_end.tp_col; 673*27cf7d04SAleksandr Rybalko break; 674*27cf7d04SAleksandr Rybalko case VTB_MARK_ROW: 675*27cf7d04SAleksandr Rybalko vtbuf_flush_mark(vb); /* Clean old mark. */ 676*27cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_col = 0; 677*27cf7d04SAleksandr Rybalko vb->vb_mark_end.tp_col = vb->vb_scr_size.tp_col; 678*27cf7d04SAleksandr Rybalko vb->vb_mark_start.tp_row = vb->vb_mark_end.tp_row = 679*27cf7d04SAleksandr Rybalko vtbuf_wth(vb, row); 680*27cf7d04SAleksandr Rybalko break; 681*27cf7d04SAleksandr Rybalko case VTB_MARK_NONE: 682*27cf7d04SAleksandr Rybalko vb->vb_mark_last = type; 683*27cf7d04SAleksandr Rybalko /* FALLTHROUGH */ 684*27cf7d04SAleksandr Rybalko default: 685*27cf7d04SAleksandr Rybalko /* panic? */ 686*27cf7d04SAleksandr Rybalko return (0); 687*27cf7d04SAleksandr Rybalko } 688*27cf7d04SAleksandr Rybalko 689*27cf7d04SAleksandr Rybalko vb->vb_mark_last = type; 690*27cf7d04SAleksandr Rybalko /* Draw new marked region. */ 691*27cf7d04SAleksandr Rybalko vtbuf_flush_mark(vb); 692*27cf7d04SAleksandr Rybalko return (1); 693*27cf7d04SAleksandr Rybalko } 694*27cf7d04SAleksandr Rybalko 695*27cf7d04SAleksandr Rybalko void 696*27cf7d04SAleksandr Rybalko vtbuf_cursor_visibility(struct vt_buf *vb, int yes) 697*27cf7d04SAleksandr Rybalko { 698*27cf7d04SAleksandr Rybalko int oflags, nflags; 699*27cf7d04SAleksandr Rybalko 700*27cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 701*27cf7d04SAleksandr Rybalko oflags = vb->vb_flags; 702*27cf7d04SAleksandr Rybalko if (yes) 703*27cf7d04SAleksandr Rybalko vb->vb_flags |= VBF_CURSOR; 704*27cf7d04SAleksandr Rybalko else 705*27cf7d04SAleksandr Rybalko vb->vb_flags &= ~VBF_CURSOR; 706*27cf7d04SAleksandr Rybalko nflags = vb->vb_flags; 707*27cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 708*27cf7d04SAleksandr Rybalko 709*27cf7d04SAleksandr Rybalko if (oflags != nflags) 710*27cf7d04SAleksandr Rybalko vtbuf_dirty_cell(vb, &vb->vb_cursor); 711*27cf7d04SAleksandr Rybalko } 712*27cf7d04SAleksandr Rybalko 713*27cf7d04SAleksandr Rybalko void 714*27cf7d04SAleksandr Rybalko vtbuf_scroll_mode(struct vt_buf *vb, int yes) 715*27cf7d04SAleksandr Rybalko { 716*27cf7d04SAleksandr Rybalko int oflags, nflags; 717*27cf7d04SAleksandr Rybalko 718*27cf7d04SAleksandr Rybalko VTBUF_LOCK(vb); 719*27cf7d04SAleksandr Rybalko oflags = vb->vb_flags; 720*27cf7d04SAleksandr Rybalko if (yes) 721*27cf7d04SAleksandr Rybalko vb->vb_flags |= VBF_SCROLL; 722*27cf7d04SAleksandr Rybalko else 723*27cf7d04SAleksandr Rybalko vb->vb_flags &= ~VBF_SCROLL; 724*27cf7d04SAleksandr Rybalko nflags = vb->vb_flags; 725*27cf7d04SAleksandr Rybalko VTBUF_UNLOCK(vb); 726*27cf7d04SAleksandr Rybalko 727*27cf7d04SAleksandr Rybalko if (oflags != nflags) 728*27cf7d04SAleksandr Rybalko vtbuf_dirty_cell(vb, &vb->vb_cursor); 729*27cf7d04SAleksandr Rybalko } 730*27cf7d04SAleksandr Rybalko 731