Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 13 Nov 2013 12:32:42 +0000 (UTC)
From:      Aleksandr Rybalko <ray@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r258090 - user/ed/newcons/sys/dev/vt
Message-ID:  <201311131232.rADCWgID021239@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <clbuisson@orange.fr> (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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201311131232.rADCWgID021239>