svn commit: r258090 - user/ed/newcons/sys/dev/vt
Aleksandr Rybalko
ray at FreeBSD.org
Wed Nov 13 12:32:43 UTC 2013
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 at 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
More information about the svn-src-user
mailing list