From owner-svn-src-user@FreeBSD.ORG Wed Nov 13 12:32:43 2013 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 056A1F3C; Wed, 13 Nov 2013 12:32:43 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id D9BA12DA0; Wed, 13 Nov 2013 12:32:42 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id rADCWg3e021242; Wed, 13 Nov 2013 12:32:42 GMT (envelope-from ray@svn.freebsd.org) Received: (from ray@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id rADCWgID021239; Wed, 13 Nov 2013 12:32:42 GMT (envelope-from ray@svn.freebsd.org) Message-Id: <201311131232.rADCWgID021239@svn.freebsd.org> From: Aleksandr Rybalko Date: Wed, 13 Nov 2013 12:32:42 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r258090 - user/ed/newcons/sys/dev/vt X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 13 Nov 2013 12:32:43 -0000 Author: ray Date: Wed Nov 13 12:32:41 2013 New Revision: 258090 URL: http://svnweb.freebsd.org/changeset/base/258090 Log: o Simplify POS_INDEX macro calculation. o New macro POS_COPY to copy between term_pos_t. o Add vtbuf_wth/vtbuf_htw helpers, to translate between screen coordinates and circular history buffer location. o Update vtbuf_iscursor to mark region selected by mouse. o New helper vtbuf_flush_mark, to update regions where copy/paste mark changed. o New method vtbuf_get_marked_len to get storage size for paste buffer. o vtbuf_extract_marked fill (caller allocated buffer) with selected region data. o Simplify mouse handler for copy/paste, and use vtbuf_flush_mark to update. o New method vtbuf_scroll_mode, to help indicate Scroll mode by hiding cursor. o Update header with new vtbuf methods. o Add new vt_driver method vd_markedwin, to hold last window with selection. o Enable paste support in core module. Sponsored by: The FreeBSD Foundation Pointed by: Claude Buisson (Scroll mode indication) Modified: user/ed/newcons/sys/dev/vt/vt.h user/ed/newcons/sys/dev/vt/vt_buf.c user/ed/newcons/sys/dev/vt/vt_core.c Modified: user/ed/newcons/sys/dev/vt/vt.h ============================================================================== --- user/ed/newcons/sys/dev/vt/vt.h Wed Nov 13 09:32:11 2013 (r258089) +++ user/ed/newcons/sys/dev/vt/vt.h Wed Nov 13 12:32:41 2013 (r258090) @@ -102,6 +102,7 @@ struct vt_device { struct vt_window *vd_windows[VT_MAXWINDOWS]; /* (c) Windows. */ struct vt_window *vd_curwindow; /* (d) Current window. */ struct vt_window *vd_savedwindow;/* (?) Saved for suspend. */ + struct vt_window *vd_markedwin; /* (?) Copy/paste buf owner. */ const struct vt_driver *vd_driver; /* (c) Graphics driver. */ void *vd_softc; /* (u) Driver data. */ uint16_t vd_mx; /* (?) Mouse X. */ @@ -174,19 +175,23 @@ void vtbuf_putchar(struct vt_buf *, cons void vtbuf_cursor_position(struct vt_buf *, const term_pos_t *); void vtbuf_mouse_cursor_position(struct vt_buf *vb, int col, int row); void vtbuf_cursor_visibility(struct vt_buf *, int); +void vtbuf_scroll_mode(struct vt_buf *vb, int yes); void vtbuf_undirty(struct vt_buf *, term_rect_t *, struct vt_bufmask *); void vtbuf_sethistory_size(struct vt_buf *, int); -void vtbuf_set_mark(struct vt_buf *vb, int type, int col, int row); +int vtbuf_set_mark(struct vt_buf *vb, int type, int col, int row); int vtbuf_iscursor(struct vt_buf *vb, int row, int col); +int vtbuf_get_marked_len(struct vt_buf *vb); +void vtbuf_extract_marked(struct vt_buf *vb, term_char_t *buf, int sz); +#define VTB_MARK_NONE 0 #define VTB_MARK_END 1 #define VTB_MARK_START 2 #define VTB_MARK_WORD 3 #define VTB_MARK_ROW 4 #define VTB_MARK_EXTEND 5 -#define VTBUF_SLCK_ENABLE(vb) (vb)->vb_flags |= VBF_SCROLL -#define VTBUF_SLCK_DISABLE(vb) (vb)->vb_flags &= ~VBF_SCROLL +#define VTBUF_SLCK_ENABLE(vb) vtbuf_scroll_mode((vb), 1) +#define VTBUF_SLCK_DISABLE(vb) vtbuf_scroll_mode((vb), 0) #define VTBUF_MAX_HEIGHT(vb) \ ((vb)->vb_history_size) @@ -310,6 +315,7 @@ static struct vt_device driver ## _consd .vd_flags = VDF_INVALID, \ .vd_windows = { [VT_CONSWINDOW] = &driver ## _conswindow, }, \ .vd_curwindow = &driver ## _conswindow, \ + .vd_markedwin = NULL, \ }; \ static term_char_t driver ## _constextbuf[(width) * \ (VBF_DEFAULT_HISTORY_SIZE)]; \ Modified: user/ed/newcons/sys/dev/vt/vt_buf.c ============================================================================== --- user/ed/newcons/sys/dev/vt/vt_buf.c Wed Nov 13 09:32:11 2013 (r258089) +++ user/ed/newcons/sys/dev/vt/vt_buf.c Wed Nov 13 12:32:41 2013 (r258090) @@ -47,7 +47,12 @@ static MALLOC_DEFINE(M_VTBUF, "vtbuf", " #define VTBUF_LOCK(vb) mtx_lock_spin(&(vb)->vb_lock) #define VTBUF_UNLOCK(vb) mtx_unlock_spin(&(vb)->vb_lock) -#define POS_INDEX(vb, c, r) ((r) * (vb)->vb_scr_size.tp_col + (c)) +#define POS_INDEX(c, r) (((r) << 12) + (c)) +#define POS_COPY(d, s) do { \ + (d).tp_col = (s).tp_col; \ + (d).tp_row = (s).tp_row; \ +} while (0) + /* * line4 @@ -130,16 +135,58 @@ vthistory_getpos(const struct vt_buf *vb *offset = vb->vb_roffset; } +/* Translate current view row number to history row. */ +static int +vtbuf_wth(struct vt_buf *vb, int row) +{ + + return ((vb->vb_roffset + row) % vb->vb_history_size); +} + +/* Translate history row to current view row number. */ +static int +vtbuf_htw(struct vt_buf *vb, int row) +{ + + /* + * total 1000 rows. + * History offset roffset winrow + * 205 200 ((205 - 200 + 1000) % 1000) = 5 + * 90 990 ((90 - 990 + 1000) % 1000) = 100 + */ + return ((row - vb->vb_roffset + vb->vb_history_size) % + vb->vb_history_size); +} + int vtbuf_iscursor(struct vt_buf *vb, int row, int col) { - if ((vb->vb_flags & VBF_CURSOR) && (vb->vb_cursor.tp_row == row) && - (vb->vb_cursor.tp_col == col)) + int sc, sr, ec, er, tmp; + + if ((vb->vb_flags & (VBF_CURSOR|VBF_SCROLL)) == VBF_CURSOR && + (vb->vb_cursor.tp_row == row) && (vb->vb_cursor.tp_col == col)) return (1); - if ((POS_INDEX(vb, vb->vb_mark_start.tp_col, vb->vb_mark_start.tp_row) < - POS_INDEX(vb, col, row)) && (POS_INDEX(vb, col, row) <= - POS_INDEX(vb, vb->vb_mark_start.tp_col, vb->vb_mark_start.tp_row))) + /* Mark cut/paste region. */ + + /* + * Luckily screen view is not like circular buffer, so we will + * calculate in screen coordinates. Translate first. + */ + sc = vb->vb_mark_start.tp_col; + sr = vtbuf_htw(vb, vb->vb_mark_start.tp_row); + ec = vb->vb_mark_end.tp_col; + er = vtbuf_htw(vb, vb->vb_mark_end.tp_row); + + + /* Swap start and end if start > end. */ + if (POS_INDEX(sc, sr) > POS_INDEX(ec, er)) { + tmp = sc; sc = ec; ec = tmp; + tmp = sr; sr = er; er = tmp; + } + + if ((POS_INDEX(sc, sr) <= POS_INDEX(col, row)) && + (POS_INDEX(col, row) < POS_INDEX(ec, er))) return (1); return (0); @@ -347,6 +394,10 @@ vtbuf_init_early(struct vt_buf *vb) vb->vb_flags |= VBF_CURSOR; vb->vb_roffset = 0; vb->vb_curroffset = 0; + vb->vb_mark_start.tp_row = 0; + vb->vb_mark_start.tp_col = 0; + vb->vb_mark_end.tp_row = 0; + vb->vb_mark_end.tp_col = 0; vtbuf_init_rows(vb); vtbuf_make_undirty(vb); @@ -492,63 +543,127 @@ vtbuf_mouse_cursor_position(struct vt_bu vtbuf_dirty(vb, &area); } +static void +vtbuf_flush_mark(struct vt_buf *vb) +{ + term_rect_t area; + int s, e; + + /* Notify renderer to update marked region. */ + if (vb->vb_mark_start.tp_col || vb->vb_mark_end.tp_col || + vb->vb_mark_start.tp_row || vb->vb_mark_end.tp_row) { + + s = vtbuf_htw(vb, vb->vb_mark_start.tp_row); + e = vtbuf_htw(vb, vb->vb_mark_end.tp_row); + + area.tr_begin.tp_col = 0; + area.tr_begin.tp_row = MIN(s, e); + + area.tr_end.tp_col = vb->vb_scr_size.tp_col; + area.tr_end.tp_row = MAX(s, e) + 1; + + vtbuf_dirty(vb, &area); + } +} + +int +vtbuf_get_marked_len(struct vt_buf *vb) +{ + int ei, si, sz; + term_pos_t s, e; + + /* Swap according to window coordinates. */ + if (POS_INDEX(vtbuf_htw(vb, vb->vb_mark_start.tp_row), vb->vb_mark_start.tp_col) > + POS_INDEX(vtbuf_htw(vb, vb->vb_mark_end.tp_row), vb->vb_mark_end.tp_col)) { + POS_COPY(e, vb->vb_mark_start); + POS_COPY(s, vb->vb_mark_end); + } else { + POS_COPY(s, vb->vb_mark_start); + POS_COPY(e, vb->vb_mark_end); + } + + si = s.tp_row * vb->vb_scr_size.tp_col + s.tp_col; + ei = e.tp_row * vb->vb_scr_size.tp_col + e.tp_col; + + /* Number symbols and number of rows to inject \n */ + sz = ei - si + ((e.tp_row - s.tp_row) * 2) + 1; + + return (sz * sizeof(term_char_t)); +} + void +vtbuf_extract_marked(struct vt_buf *vb, term_char_t *buf, int sz) +{ + int i, r, c, cs, ce; + term_pos_t s, e; + + /* Swap according to window coordinates. */ + if (POS_INDEX(vtbuf_htw(vb, vb->vb_mark_start.tp_row), vb->vb_mark_start.tp_col) > + POS_INDEX(vtbuf_htw(vb, vb->vb_mark_end.tp_row), vb->vb_mark_end.tp_col)) { + POS_COPY(e, vb->vb_mark_start); + POS_COPY(s, vb->vb_mark_end); + } else { + POS_COPY(s, vb->vb_mark_start); + POS_COPY(e, vb->vb_mark_end); + } + + i = 0; + for (r = s.tp_row; r <= e.tp_row; r ++) { + cs = (r == s.tp_row)?s.tp_col:0; + ce = (r == e.tp_row)?e.tp_col:vb->vb_scr_size.tp_col; + for (c = cs; c < ce; c ++) { + buf[i++] = vb->vb_rows[r][c]; + } + buf[i++] = '\r'; + buf[i++] = '\n'; + } +} + +int vtbuf_set_mark(struct vt_buf *vb, int type, int col, int row) { - term_rect_t area; - vt_axis_t tmp; switch (type) { case VTB_MARK_END: case VTB_MARK_EXTEND: + vtbuf_flush_mark(vb); /* Clean old mark. */ vb->vb_mark_end.tp_col = col; - vb->vb_mark_end.tp_row = row; + vb->vb_mark_end.tp_row = vtbuf_wth(vb, row); break; case VTB_MARK_START: + vtbuf_flush_mark(vb); /* Clean old mark. */ vb->vb_mark_start.tp_col = col; - vb->vb_mark_start.tp_row = row; + vb->vb_mark_start.tp_row = vtbuf_wth(vb, row); /* Start again, so clear end point. */ - vb->vb_mark_end.tp_col = 0; - vb->vb_mark_end.tp_row = 0; + vb->vb_mark_end.tp_col = col; + vb->vb_mark_end.tp_row = vtbuf_wth(vb, row); break; case VTB_MARK_WORD: + vtbuf_flush_mark(vb); /* Clean old mark. */ vb->vb_mark_start.tp_col = 0; /* XXX */ vb->vb_mark_end.tp_col = 10; /* XXX */ - vb->vb_mark_start.tp_row = vb->vb_mark_end.tp_row = row; + vb->vb_mark_start.tp_row = vb->vb_mark_end.tp_row = + vtbuf_wth(vb, row); break; case VTB_MARK_ROW: + vtbuf_flush_mark(vb); /* Clean old mark. */ vb->vb_mark_start.tp_col = 0; vb->vb_mark_end.tp_col = vb->vb_scr_size.tp_col; - vb->vb_mark_start.tp_row = vb->vb_mark_end.tp_row = row; + vb->vb_mark_start.tp_row = vb->vb_mark_end.tp_row = + vtbuf_wth(vb, row); break; + case VTB_MARK_NONE: + break; + default: + /* panic? */ + return (0); + } + if (type != VTB_MARK_NONE) { + /* Draw new marked region. */ + vtbuf_flush_mark(vb); + return (1); } - - /* Swap start and end if start > end. */ - if (POS_INDEX(vb, vb->vb_mark_start.tp_col, vb->vb_mark_start.tp_row) > - POS_INDEX(vb, vb->vb_mark_end.tp_col, vb->vb_mark_end.tp_row)) { - tmp = vb->vb_mark_start.tp_col; - vb->vb_mark_start.tp_col = vb->vb_mark_end.tp_col; - vb->vb_mark_end.tp_col = tmp; - tmp = vb->vb_mark_start.tp_row; - vb->vb_mark_start.tp_row = vb->vb_mark_end.tp_row; - vb->vb_mark_end.tp_row = tmp; - } - - /* Notify renderer to update marked region. */ - if (vb->vb_mark_start.tp_col || vb->vb_mark_end.tp_col || - vb->vb_mark_start.tp_row || vb->vb_mark_end.tp_row) { - - area.tr_begin.tp_col = 0; - area.tr_begin.tp_row = MIN(vb->vb_mark_start.tp_row, - vb->vb_mark_end.tp_row); - - area.tr_end.tp_col = vb->vb_scr_size.tp_col; - area.tr_end.tp_row = MAX(vb->vb_mark_start.tp_row, - vb->vb_mark_end.tp_row); - - vtbuf_dirty(vb, &area); - } - + return (0); } void @@ -568,3 +683,22 @@ vtbuf_cursor_visibility(struct vt_buf *v if (oflags != nflags) vtbuf_dirty_cell(vb, &vb->vb_cursor); } + +void +vtbuf_scroll_mode(struct vt_buf *vb, int yes) +{ + int oflags, nflags; + + VTBUF_LOCK(vb); + oflags = vb->vb_flags; + if (yes) + vb->vb_flags |= VBF_SCROLL; + else + vb->vb_flags &= ~VBF_SCROLL; + nflags = vb->vb_flags; + VTBUF_UNLOCK(vb); + + if (oflags != nflags) + vtbuf_dirty_cell(vb, &vb->vb_cursor); +} + Modified: user/ed/newcons/sys/dev/vt/vt_core.c ============================================================================== --- user/ed/newcons/sys/dev/vt/vt_core.c Wed Nov 13 09:32:11 2013 (r258089) +++ user/ed/newcons/sys/dev/vt/vt_core.c Wed Nov 13 12:32:41 2013 (r258090) @@ -1069,7 +1069,8 @@ vt_mouse_event(int type, int x, int y, i struct vt_window *vw; struct vt_font *vf; term_pos_t size; - int mark; + term_char_t *buf; + int i, len, mark; vd = main_vd; vw = vd->vd_curwindow; @@ -1100,10 +1101,17 @@ vt_mouse_event(int type, int x, int y, i vd->vd_mx = x; vd->vd_my = y; - if (vd->vd_mstate & MOUSE_BUTTON1DOWN) - vtbuf_set_mark(&vw->vw_buf, VTB_MARK_END, - vd->vd_mx / vf->vf_width, - vd->vd_my / vf->vf_height); + if ((vd->vd_mstate & MOUSE_BUTTON1DOWN) && + (vtbuf_set_mark(&vw->vw_buf, VTB_MARK_END, + vd->vd_mx / vf->vf_width, + vd->vd_my / vf->vf_height) == 1)) { + + /* + * We have something marked to copy, so update pointer + * to window with selection. + */ + vd->vd_markedwin = vw; + } return; /* Done */ case MOUSE_BUTTON_EVENT: /* Buttons */ @@ -1134,7 +1142,27 @@ vt_mouse_event(int type, int x, int y, i case 0: /* up */ break; default: - //sc_mouse_paste(cur_scp); + if (vd->vd_markedwin == NULL) + return; + /* Get current selecton size in bytes. */ + len = vtbuf_get_marked_len(&vd->vd_markedwin->vw_buf); + if (len <= 0) + return; + + buf = malloc(len, M_VT, M_WAITOK | M_ZERO); + /* Request cupy/paste buffer data, no more than `len' */ + vtbuf_extract_marked(&vd->vd_markedwin->vw_buf, buf, + len); + + len /= sizeof(term_char_t); + for (i = 0; i < len; i++ ) { + if (buf[i] == '\0') + continue; + terminal_input_char(vw->vw_terminal, buf[i]); + } + + /* Done, so cleanup. */ + free(buf, M_VT); break; } return; /* Done */ @@ -1161,8 +1189,14 @@ vt_mouse_event(int type, int x, int y, i else vd->vd_mstate &= ~event; - vtbuf_set_mark(&vw->vw_buf, mark, vd->vd_mx / vf->vf_width, - vd->vd_my / vf->vf_height); + if (vtbuf_set_mark(&vw->vw_buf, mark, vd->vd_mx / vf->vf_width, + vd->vd_my / vf->vf_height) == 1) { + /* + * We have something marked to copy, so update pointer to + * window with selection. + */ + vd->vd_markedwin = vw; + } } static int