Index: vt.h =================================================================== --- vt.h (revision 271381) +++ vt.h (working copy) @@ -113,11 +113,17 @@ struct vt_mouse_cursor; #endif +struct vt_pastebuf { + term_char_t *vpb_buf; /* Copy-paste buffer. */ + unsigned int vpb_bufsz; /* Buffer size. */ + unsigned int vpb_len; /* Length of a last selection. */ +}; + 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. */ + struct vt_pastebuf vd_pastebuf; /* (?) Copy/paste buf. */ const struct vt_driver *vd_driver; /* (c) Graphics driver. */ void *vd_softc; /* (u) Driver data. */ #ifndef SC_NO_CUTPASTE @@ -151,6 +157,10 @@ unsigned int vd_unit; /* (c) Device unit. */ }; +#define VD_PASTEBUF(vd) ((vd)->vd_pastebuf.vpb_buf) +#define VD_PASTEBUFSZ(vd) ((vd)->vd_pastebuf.vpb_bufsz) +#define VD_PASTEBUFLEN(vd) ((vd)->vd_pastebuf.vpb_len) + /* * Per-window terminal screen buffer. * Index: vt_core.c =================================================================== --- vt_core.c (revision 271385) +++ vt_core.c (working copy) @@ -176,7 +176,11 @@ .vd_flags = VDF_INVALID, .vd_windows = { [VT_CONSWINDOW] = &vt_conswindow, }, .vd_curwindow = &vt_conswindow, - .vd_markedwin = NULL, + .vd_pastebuf = { + .vpb_buf = NULL, + .vpb_bufsz = 0, + .vpb_len = 0 + }, .vd_kbstate = 0, #ifndef SC_NO_CUTPASTE @@ -1665,18 +1669,11 @@ vd->vd_mx = x; vd->vd_my = y; - if ((vd->vd_mstate & MOUSE_BUTTON1DOWN) && - (vtbuf_set_mark(&vw->vw_buf, VTB_MARK_MOVE, - vd->vd_mx / vf->vf_width, - vd->vd_my / vf->vf_height) == 1)) { + if (vd->vd_mstate & MOUSE_BUTTON1DOWN) + vtbuf_set_mark(&vw->vw_buf, VTB_MARK_MOVE, + vd->vd_mx / vf->vf_width, + vd->vd_my / vf->vf_height); - /* - * We have something marked to copy, so update pointer - * to window with selection. - */ - vd->vd_markedwin = vw; - } - vt_resume_flush_timer(vw->vw_device, 0); return; /* Done */ case MOUSE_BUTTON_EVENT: @@ -1708,18 +1705,8 @@ case 0: /* up */ break; default: - 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 copy/paste buffer data, no more than `len' */ - vtbuf_extract_marked(&vd->vd_markedwin->vw_buf, buf, - len); - + len = VD_PASTEBUFLEN(vd); + buf = VD_PASTEBUF(vd); len /= sizeof(term_char_t); for (i = 0; i < len; i++ ) { if (buf[i] == '\0') @@ -1726,9 +1713,6 @@ continue; terminal_input_char(vw->vw_terminal, buf[i]); } - - /* Done, so cleanup. */ - free(buf, M_VT); break; } return; /* Done */ @@ -1761,8 +1745,27 @@ * We have something marked to copy, so update pointer to * window with selection. */ - vd->vd_markedwin = vw; vt_resume_flush_timer(vw->vw_device, 0); + + /* Get current selecton size in bytes. */ + len = vtbuf_get_marked_len(&vw->vw_buf); + if (len <= 0) + return; + + /* Reallocate buffer only if old one too small. */ + if (len > VD_PASTEBUFSZ(vd)) { + VD_PASTEBUF(vd) = realloc(VD_PASTEBUF(vd), len, M_VT, + M_WAITOK | M_ZERO); + /* Update buffer size. */ + VD_PASTEBUFSZ(vd) = len; + } + /* Request copy/paste buffer data, no more than `len' */ + vtbuf_extract_marked(&vw->vw_buf, VD_PASTEBUF(vd), + VD_PASTEBUFSZ(vd)); + + VD_PASTEBUFLEN(vd) = len; + + /* XXX VD_PASTEBUF(vd) have to be freed on shutdown/unload. */ } }