summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAaron Campbell <aaron@cvs.openbsd.org>2001-04-14 04:44:03 +0000
committerAaron Campbell <aaron@cvs.openbsd.org>2001-04-14 04:44:03 +0000
commitadffc27bad14cc984251f7b99221c20ae0ecef8f (patch)
tree84b49bf57d59cf56b0b0e3b1145d35fdc4351a40 /sys
parentaee43e89e7498e4405fbdcdedcfbf4b2bda7196e (diff)
Kernel support for console mouse functionality which will be controlled by
the wsmoused daemon (replacement for moused which was used with PCVT). Adds a "getchar" method to the display drivers which returns the value of the character currently under the cursor (e.g., so it may be inversed). From jbm@. Still needs a bit of cleanup and improvement, especially X cohabitation features. The pointer moves to fast as well. These sorts of issues will be corrected in-tree.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ic/pcdisplay_subr.c21
-rw-r--r--sys/dev/ic/pcdisplayvar.h3
-rw-r--r--sys/dev/ic/vga.c26
-rw-r--r--sys/dev/wscons/wsconsio.h17
-rw-r--r--sys/dev/wscons/wsdisplay.c1110
-rw-r--r--sys/dev/wscons/wsdisplayvar.h3
-rw-r--r--sys/dev/wscons/wsmoused.h127
7 files changed, 1257 insertions, 50 deletions
diff --git a/sys/dev/ic/pcdisplay_subr.c b/sys/dev/ic/pcdisplay_subr.c
index 3b294330d31..70699e63510 100644
--- a/sys/dev/ic/pcdisplay_subr.c
+++ b/sys/dev/ic/pcdisplay_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcdisplay_subr.c,v 1.3 2001/03/14 02:49:22 mickey Exp $ */
+/* $OpenBSD: pcdisplay_subr.c,v 1.4 2001/04/14 04:44:01 aaron Exp $ */
/* $NetBSD: pcdisplay_subr.c,v 1.16 2000/06/08 07:01:19 cgd Exp $ */
/*
@@ -163,6 +163,25 @@ pcdisplay_putchar(id, row, col, c, attr)
scr->mem[off] = c | (attr << 8);
}
+u_int16_t
+pcdisplay_getchar(id, row, col)
+ void *id;
+ int row, col;
+{
+ struct pcdisplayscreen *scr = id;
+ bus_space_tag_t memt = scr->hdl->ph_memt;
+ bus_space_handle_t memh = scr->hdl->ph_memh;
+ int off;
+
+ off = row * scr->type->ncols + col;
+
+ if (scr->active)
+ return (bus_space_read_2(memt, memh,
+ scr->dispoffset + off * 2));
+ else
+ return (scr->mem[off]);
+}
+
void
pcdisplay_copycols(id, row, srccol, dstcol, ncols)
void *id;
diff --git a/sys/dev/ic/pcdisplayvar.h b/sys/dev/ic/pcdisplayvar.h
index dd563726541..af94e3d32f8 100644
--- a/sys/dev/ic/pcdisplayvar.h
+++ b/sys/dev/ic/pcdisplayvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcdisplayvar.h,v 1.3 2001/04/06 04:42:05 csapuntz Exp $ */
+/* $OpenBSD: pcdisplayvar.h,v 1.4 2001/04/14 04:44:01 aaron Exp $ */
/* $NetBSD: pcdisplayvar.h,v 1.8 2000/01/25 02:44:03 ad Exp $ */
/*
@@ -94,6 +94,7 @@ unsigned int pcdisplay_mapchar_simple __P((void *, int));
#endif
int pcdisplay_mapchar __P((void *, int, unsigned int *));
void pcdisplay_putchar __P((void *, int, int, u_int, long));
+u_int16_t pcdisplay_getchar __P((void *, int, int));
void pcdisplay_copycols __P((void *, int, int, int,int));
void pcdisplay_erasecols __P((void *, int, int, int, long));
void pcdisplay_copyrows __P((void *, int, int, int));
diff --git a/sys/dev/ic/vga.c b/sys/dev/ic/vga.c
index 30426df6abb..ecb9be2ccbd 100644
--- a/sys/dev/ic/vga.c
+++ b/sys/dev/ic/vga.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vga.c,v 1.22 2001/04/01 20:30:02 mickey Exp $ */
+/* $OpenBSD: vga.c,v 1.23 2001/04/14 04:44:01 aaron Exp $ */
/* $NetBSD: vga.c,v 1.28.2.1 2000/06/30 16:27:47 simonb Exp $ */
/*
@@ -120,11 +120,11 @@ void vga_init_screen __P((struct vga_config *, struct vgascreen *,
int, long *));
void vga_init __P((struct vga_config *, bus_space_tag_t,
bus_space_tag_t));
-static void vga_setfont __P((struct vga_config *, struct vgascreen *));
+void vga_setfont __P((struct vga_config *, struct vgascreen *));
-static int vga_mapchar __P((void *, int, unsigned int *));
-static void vga_putchar __P((void *, int, int, u_int, long));
-static int vga_alloc_attr __P((void *, int, int, int, long *));
+int vga_mapchar __P((void *, int, unsigned int *));
+void vga_putchar __P((void *, int, int, u_int, long));
+int vga_alloc_attr __P((void *, int, int, int, long *));
void vga_copyrows __P((void *, int, int, int));
const struct wsdisplay_emulops vga_emulops = {
@@ -245,6 +245,7 @@ int vga_show_screen __P((void *, void *, int,
void (*) (void *, int, int), void *));
int vga_load_font __P((void *, void *, struct wsdisplay_font *));
void vga_scrollback __P((void *, void *, int));
+u_int16_t vga_getchar __P((void *, int, int));
void vga_doswitch __P((struct vga_config *));
@@ -255,7 +256,8 @@ const struct wsdisplay_accessops vga_accessops = {
vga_free_screen,
vga_show_screen,
vga_load_font,
- vga_scrollback
+ vga_scrollback,
+ vga_getchar
};
/*
@@ -1235,7 +1237,7 @@ vga_mapchar(id, uni, index)
return (res1);
}
-static void
+void
vga_putchar(c, row, col, uc, attr)
void *c;
int row;
@@ -1251,6 +1253,16 @@ vga_putchar(c, row, col, uc, attr)
pcdisplay_putchar(c, row, col, uc, attr);
}
+u_int16_t
+vga_getchar(c, row, col)
+ void *c;
+ int row, col;
+{
+ struct vga_config *vc = c;
+
+ return (pcdisplay_getchar(vc->active, row, col));
+}
+
struct cfdriver vga_cd = {
NULL, "vga", DV_DULL
};
diff --git a/sys/dev/wscons/wsconsio.h b/sys/dev/wscons/wsconsio.h
index 983a595bc4c..534946886cf 100644
--- a/sys/dev/wscons/wsconsio.h
+++ b/sys/dev/wscons/wsconsio.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: wsconsio.h,v 1.8 2001/03/14 02:49:22 mickey Exp $ */
+/* $OpenBSD: wsconsio.h,v 1.9 2001/04/14 04:44:01 aaron Exp $ */
/* $NetBSD: wsconsio.h,v 1.31.2.1 2000/07/07 09:49:17 hannken Exp $ */
/*
@@ -73,8 +73,16 @@ struct wscons_event {
#define WSCONS_EVENT_MOUSE_ABSOLUTE_Y 9 /* Y location */
#define WSCONS_EVENT_MOUSE_DELTA_Z 10 /* Z delta amount */
#define WSCONS_EVENT_MOUSE_ABSOLUTE_Z 11 /* Z location */
-
-
+#define WSCONS_EVENT_WSMOUSED_ON 12 /* wsmoused(8) active */
+#define WSCONS_EVENT_WSMOUSED_OFF 13 /* wsmoused(8) inactive */
+
+#define IS_MOTION_EVENT(type) (((type) == WSCONS_EVENT_MOUSE_DELTA_X) || \
+ ((type) == WSCONS_EVENT_MOUSE_DELTA_Y) || \
+ ((type) == WSCONS_EVENT_MOUSE_DELTA_Z))
+#define IS_BUTTON_EVENT(type) (((type) == WSCONS_EVENT_MOUSE_UP) || \
+ ((type) == WSCONS_EVENT_MOUSE_DOWN))
+#define IS_CTRL_EVENT(type) ((type == WSCONS_EVENT_WSMOUSED_ON) || \
+ (type == WSCONS_EVENT_WSMOUSED_OFF))
/*
* Keyboard ioctls (0 - 31)
*/
@@ -351,6 +359,9 @@ struct wsdisplay_kbddata {
};
#define _O_WSDISPLAYIO_SETKEYBOARD _IOWR('W', 81, struct wsdisplay_kbddata)
+/* Mouse console support */
+#define WSDISPLAYIO_WSMOUSED _IOW('W', 82, struct wscons_event)
+
/* Misc control. Not applicable to all display types. */
struct wsdisplay_param {
int param;
diff --git a/sys/dev/wscons/wsdisplay.c b/sys/dev/wscons/wsdisplay.c
index 5a60303b005..9de5ec404cd 100644
--- a/sys/dev/wscons/wsdisplay.c
+++ b/sys/dev/wscons/wsdisplay.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wsdisplay.c,v 1.18 2001/03/14 06:18:48 millert Exp $ */
+/* $OpenBSD: wsdisplay.c,v 1.19 2001/04/14 04:44:01 aaron Exp $ */
/* $NetBSD: wsdisplay.c,v 1.37.4.1 2000/06/30 16:27:53 simonb Exp $ */
/*
@@ -57,6 +57,8 @@
#include <dev/wscons/wscons_callbacks.h>
#include <dev/cons.h>
+#include <dev/ic/pcdisplay.h>
+
#include "wskbd.h"
#include "wsmux.h"
@@ -65,6 +67,8 @@
#include <dev/wscons/wsmuxvar.h>
#endif
+#include "wsmoused.h"
+
struct wsscreen_internal {
const struct wsdisplay_emulops *emulops;
void *emulcookie;
@@ -93,6 +97,34 @@ struct wsscreen {
#endif
struct wsdisplay_softc *sc;
+
+ /* mouse console support via wsmoused(8) */
+ unsigned short mouse; /* mouse cursor position */
+ unsigned short cursor; /* selection cursor position ( if
+ different from mouse cursor pos) */
+ unsigned short cpy_start; /* position of the copy start mark*/
+ unsigned short cpy_end; /* position of the copy end mark */
+ unsigned short orig_start; /* position of the original sel. start*/
+ unsigned short orig_end; /* position of the original sel. end */
+#define MOUSE_VISIBLE (1 << 0) /* flag, the mouse cursor is visible */
+#define SEL_EXISTS (1 << 1) /* flag, a selection exists */
+#define SEL_IN_PROGRESS (1 << 2) /* flag, a selection is in progress */
+#define SEL_EXT_AFTER (1 << 3) /* flag, selection is extended after */
+#define BLANK_TO_EOL (1 << 4) /* flag, there are only blanks
+ characters to eol */
+#define SEL_BY_CHAR (1 << 5) /* flag, select character by character*/
+#define SEL_BY_WORD (1 << 6) /* flag, select word by word */
+#define SEL_BY_LINE (1 << 7) /* flag, select line by line */
+
+#define IS_MOUSE_VISIBLE(ws) ((ws)->mouse_flags & MOUSE_VISIBLE)
+#define IS_SEL_EXISTS(ws) ((ws)->mouse_flags & SEL_EXISTS)
+#define IS_SEL_IN_PROGRESS(ws) ((ws)->mouse_flags & SEL_IN_PROGRESS)
+#define IS_SEL_EXT_AFTER(ws) ((ws)->mouse_flags & SEL_EXT_AFTER)
+#define IS_BLANK_TO_EOL(ws) ((ws)->mouse_flags & BLANK_TO_EOL)
+#define IS_SEL_BY_CHAR(ws) ((ws)->mouse_flags & SEL_BY_CHAR)
+#define IS_SEL_BY_WORD(ws) ((ws)->mouse_flags & SEL_BY_WORD)
+#define IS_SEL_BY_LINE(ws) ((ws)->mouse_flags & SEL_BY_LINE)
+ unsigned char mouse_flags; /* flags, status of the mouse */
};
struct wsscreen *wsscreen_attach __P((struct wsdisplay_softc *, int,
@@ -101,10 +133,9 @@ struct wsscreen *wsscreen_attach __P((struct wsdisplay_softc *, int,
int, int, long));
void wsscreen_detach __P((struct wsscreen *));
int wsdisplay_addscreen __P((struct wsdisplay_softc *, int, const char *, const char *));
-static void wsdisplay_shutdownhook __P((void *));
-static void wsdisplay_addscreen_print __P((struct wsdisplay_softc *, int, int));
-static void wsdisplay_closescreen __P((struct wsdisplay_softc *,
- struct wsscreen *));
+void wsdisplay_shutdownhook __P((void *));
+void wsdisplay_addscreen_print __P((struct wsdisplay_softc *, int, int));
+void wsdisplay_closescreen __P((struct wsdisplay_softc *, struct wsscreen *));
int wsdisplay_delscreen __P((struct wsdisplay_softc *, int, int));
#define WSDISPLAY_MAXSCREEN 12
@@ -141,12 +172,10 @@ struct wsdisplay_softc {
extern struct cfdriver wsdisplay_cd;
/* Autoconfiguration definitions. */
-static int wsdisplay_emul_match __P((struct device *, void *, void *));
-static void wsdisplay_emul_attach __P((struct device *, struct device *,
- void *));
-static int wsdisplay_noemul_match __P((struct device *, void *, void *));
-static void wsdisplay_noemul_attach __P((struct device *, struct device *,
- void *));
+int wsdisplay_emul_match __P((struct device *, void *, void *));
+void wsdisplay_emul_attach __P((struct device *, struct device *, void *));
+int wsdisplay_noemul_match __P((struct device *, void *, void *));
+void wsdisplay_noemul_attach __P((struct device *, struct device *, void *));
struct cfdriver wsdisplay_cd = {
NULL, "wsdisplay", DV_TTY
@@ -167,8 +196,8 @@ struct cfattach wsdisplay_noemul_ca = {
/* Exported tty- and cdevsw-related functions. */
cdev_decl(wsdisplay);
-static void wsdisplaystart __P((struct tty *));
-static int wsdisplayparam __P((struct tty *, struct termios *));
+void wsdisplaystart __P((struct tty *));
+int wsdisplayparam __P((struct tty *, struct termios *));
/* Internal macros, functions, and variables. */
@@ -176,33 +205,32 @@ static int wsdisplayparam __P((struct tty *, struct termios *));
#define CLR(t, f) (t) &= ~(f)
#define ISSET(t, f) ((t) & (f))
-#define WSDISPLAYUNIT(dev) (minor(dev) >> 8)
-#define WSDISPLAYSCREEN(dev) (minor(dev) & 0xff)
-#define ISWSDISPLAYCTL(dev) (WSDISPLAYSCREEN(dev) == 255)
+#define WSDISPLAYUNIT(dev) (minor(dev) >> 8)
+#define WSDISPLAYSCREEN(dev) (minor(dev) & 0xff)
+#define ISWSDISPLAYCTL(dev) (WSDISPLAYSCREEN(dev) == 255)
#define WSDISPLAYMINOR(unit, screen) (((unit) << 8) | (screen))
#define WSSCREEN_HAS_EMULATOR(scr) ((scr)->scr_dconf->wsemul != NULL)
-#define WSSCREEN_HAS_TTY(scr) ((scr)->scr_tty != NULL)
+#define WSSCREEN_HAS_TTY(scr) ((scr)->scr_tty != NULL)
-static void wsdisplay_common_attach __P((struct wsdisplay_softc *sc,
- int console, const struct wsscreen_list *,
- const struct wsdisplay_accessops *accessops,
- void *accesscookie));
+void wsdisplay_common_attach __P((struct wsdisplay_softc *sc, int console,
+ const struct wsscreen_list *,
+ const struct wsdisplay_accessops *accessops,
+ void *accesscookie));
#ifdef WSDISPLAY_COMPAT_RAWKBD
-int wsdisplay_update_rawkbd __P((struct wsdisplay_softc *,
- struct wsscreen *));
+int wsdisplay_update_rawkbd __P((struct wsdisplay_softc *, struct wsscreen *));
#endif
static int wsdisplay_console_initted;
static struct wsdisplay_softc *wsdisplay_console_device;
static struct wsscreen_internal wsdisplay_console_conf;
-static int wsdisplay_getc_dummy __P((dev_t));
-static void wsdisplay_pollc __P((dev_t, int));
+int wsdisplay_getc_dummy __P((dev_t));
+void wsdisplay_pollc __P((dev_t, int));
static int wsdisplay_cons_pollmode;
-static void (*wsdisplay_cons_kbd_pollc) __P((dev_t, int));
+void (*wsdisplay_cons_kbd_pollc) __P((dev_t, int));
static struct consdev wsdisplay_cons = {
NULL, NULL, wsdisplay_getc_dummy, wsdisplay_cnputc,
@@ -277,6 +305,7 @@ wsscreen_attach(sc, console, emul, type, cookie, ccol, crow, defattr)
scr->scr_syncops = 0;
scr->sc = sc;
+ scr->mouse_flags = 0;
#ifdef WSDISPLAY_COMPAT_RAWKBD
scr->scr_rawkbd = 0;
#endif
@@ -326,7 +355,7 @@ wsdisplay_screentype_pick(scrdata, name)
/*
* print info about attached screen
*/
-static void
+void
wsdisplay_addscreen_print(sc, idx, count)
struct wsdisplay_softc *sc;
int idx, count;
@@ -389,10 +418,12 @@ wsdisplay_addscreen(sc, idx, screentype, emul)
sc->sc_focus = scr;
}
splx(s);
+
+ allocate_copybuffer(sc); /* enlarge the copy buffer is necessary */
return (0);
}
-static void
+void
wsdisplay_closescreen(sc, scr)
struct wsdisplay_softc *sc;
struct wsscreen *scr;
@@ -591,7 +622,7 @@ wsdisplaydevprint(aux, pnp)
return (UNCONF);
}
-static void
+void
wsdisplay_common_attach(sc, console, scrdata, accessops, accesscookie)
struct wsdisplay_softc *sc;
int console;
@@ -600,7 +631,7 @@ wsdisplay_common_attach(sc, console, scrdata, accessops, accesscookie)
void *accesscookie;
{
static int hookset = 0;
- int i, start=0;
+ int i, start = 0;
#if NWSKBD > 0
struct device *dv;
@@ -646,7 +677,7 @@ wsdisplay_common_attach(sc, console, scrdata, accessops, accesscookie)
for (i = start; i < wsdisplay_defaultscreens; i++) {
if (wsdisplay_addscreen(sc, i, 0, 0))
break;
-}
+ }
if (i > start)
wsdisplay_addscreen_print(sc, start, i-start);
@@ -808,6 +839,11 @@ wsdisplayclose(dev, flag, mode, p)
scr->scr_flags &= ~SCR_OPEN;
+ /* remove the selection at logout */
+ if (Copybuffer)
+ bzero(Copybuffer, Copybuffer_size);
+ Paste_avail = 0;
+
return (0);
}
@@ -1034,6 +1070,9 @@ wsdisplay_cfg_ioctl(sc, cmd, data, flag, p)
#endif
switch (cmd) {
+ case WSDISPLAYIO_WSMOUSED:
+ error = wsmoused(sc, cmd, data, flag, p);
+ return (error);
case WSDISPLAYIO_ADDSCREEN:
#define d ((struct wsdisplay_addscreendata *)data)
if ((error = wsdisplay_addscreen(sc, d->idx,
@@ -1227,6 +1266,11 @@ wsdisplaystart(tp)
if (!(scr->scr_flags & SCR_GRAPHICS)) {
KASSERT(WSSCREEN_HAS_EMULATOR(scr));
+ if ((scr == sc->sc_focus) && (IS_SEL_EXISTS(sc->sc_focus)))
+ /* hide a potential selection */
+ remove_selection(sc);
+ /* hide a potential mouse cursor */
+ mouse_hide(sc);
(*scr->scr_dconf->wsemul->output)(scr->scr_dconf->wsemulcookie,
buf, n, 0);
}
@@ -1597,6 +1641,12 @@ wsdisplay_switch(dev, no, waitok)
res = EBUSY;
}
+ if (IS_SEL_EXISTS(sc->sc_focus))
+ /* hide a potential selection */
+ remove_selection(sc);
+
+ mouse_hide(sc); /* hide a potential mouse cursor */
+
return (wsdisplay_switch1(sc, res, waitok));
}
@@ -1789,7 +1839,7 @@ wsdisplay_cnputc(dev, i)
(*dc->wsemul->output)(dc->wsemulcookie, &c, 1, 1);
}
-static int
+int
wsdisplay_getc_dummy(dev)
dev_t dev;
{
@@ -1797,7 +1847,7 @@ wsdisplay_getc_dummy(dev)
return (0);
}
-static void
+void
wsdisplay_pollc(dev, on)
dev_t dev;
int on;
@@ -1855,9 +1905,8 @@ wsdisplay_switchtoconsole()
sc = wsdisplay_console_device;
scr = sc->sc_scr[0];
(*sc->sc_accessops->show_screen)(sc->sc_accesscookie,
- scr->scr_dconf->emulcookie,
- 0, NULL, NULL);
-}
+ scr->scr_dconf->emulcookie, 0, NULL, NULL);
+ }
}
void
@@ -1885,9 +1934,996 @@ wsscrollback(arg, op)
/*
* Switch the console at shutdown.
*/
-static void
+void
wsdisplay_shutdownhook(arg)
void *arg;
{
wsdisplay_switchtoconsole();
}
+
+/*
+ * mouse console support functions
+ */
+
+/* pointer to the current screen wsdisplay_softc structure */
+static struct wsdisplay_softc *sc = NULL;
+
+/*
+ * Main function, called in wsdisplay_cfg_ioctl
+ */
+int
+wsmoused(struct wsdisplay_softc *ws_sc, u_long cmd, caddr_t data,
+ int flag, struct proc *p)
+{
+ int error = -1;
+ struct wscons_event mouse_event = *(struct wscons_event *)data;
+
+ if (cmd == WSDISPLAYIO_WSMOUSED) {
+ if (IS_MOTION_EVENT(mouse_event.type)) {
+ motion_event(mouse_event.type, mouse_event.value);
+ return 0;
+ }
+ if (IS_BUTTON_EVENT(mouse_event.type)) {
+ /* XXX tv_sec contains the number of clicks */
+ if (mouse_event.type == WSCONS_EVENT_MOUSE_DOWN)
+ button_event(mouse_event.value,
+ mouse_event.time.tv_sec);
+ else
+ button_event(mouse_event.value, 0);
+ return 0;
+ }
+ if (IS_CTRL_EVENT(mouse_event.type)) {
+ return ctrl_event(mouse_event.type, mouse_event.value,
+ ws_sc, p);
+ }
+ }
+ return (error);
+}
+
+/*
+ * Mouse motion events
+ */
+void
+motion_event(u_int type, int value)
+{
+ switch (type) {
+ case WSCONS_EVENT_MOUSE_DELTA_X:
+ mouse_moverel(value, 0);
+ break;
+ case WSCONS_EVENT_MOUSE_DELTA_Y:
+ mouse_moverel(0, 0 - value);
+ break;
+ case WSCONS_EVENT_MOUSE_DELTA_Z:
+ mouse_zaxis(value);
+ break;
+ default:
+ }
+}
+
+/*
+ * Button clicks events
+ */
+void
+button_event(int button, int clicks)
+{
+ switch (button) {
+ case MOUSE_COPY_BUTTON:
+ switch (clicks % 4) {
+ case 0: /* button is up */
+ mouse_copy_end();
+ mouse_copy_selection();
+ break;
+ case 1: /* single click */
+ mouse_copy_start();
+ mouse_copy_selection();
+ break;
+ case 2: /* double click */
+ mouse_copy_word();
+ mouse_copy_selection();
+ break;
+ case 3: /* triple click */
+ mouse_copy_line();
+ mouse_copy_selection();
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case MOUSE_PASTE_BUTTON:
+ switch (clicks) {
+ case 0: /* button is up */
+ break;
+ default: /* paste */
+ mouse_paste();
+ break;
+ }
+ break;
+
+ case MOUSE_EXTEND_BUTTON:
+ switch (clicks) {
+ case 0: /* button is up */
+ break;
+ default: /* extend the selection */
+ mouse_copy_extend_after();
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*
+ * Control events
+ */
+int
+ctrl_event(u_int type, int value, struct wsdisplay_softc *ws_sc, struct proc *p)
+{
+ int i;
+
+ if (type == WSCONS_EVENT_WSMOUSED_ON) {
+ if (!ws_sc->sc_accessops->getchar)
+ /* no wsmoused support in the display driver */
+ return 1;
+ /* initialization of globals */
+ sc = ws_sc;
+ allocate_copybuffer(sc);
+ Paste_avail = 0;
+ }
+ if (type == WSCONS_EVENT_WSMOUSED_OFF) {
+ Paste_avail = 0;
+ return (0);
+ }
+ for (i = 0 ; i < WSDISPLAY_DEFAULTSCREENS ; i++) {
+ sc->sc_scr[i]->mouse =
+ ((WS_NCOLS(sc->sc_scr[i]) *
+ WS_NROWS(sc->sc_scr[i])) / 2);
+ sc->sc_scr[i]->cursor = sc->sc_scr[i]->mouse;
+ sc->sc_scr[i]->cpy_start = 0;
+ sc->sc_scr[i]->cpy_end = 0;
+ sc->sc_scr[i]->orig_start = 0;
+ sc->sc_scr[i]->orig_end = 0;
+ sc->sc_scr[i]->mouse_flags = 0;
+ }
+ return 0;
+}
+
+void
+mouse_moverel(char dx, char dy)
+{
+ unsigned short old_mouse = MOUSE;
+ unsigned char mouse_col = (MOUSE % N_COLS);
+ unsigned char mouse_row = (MOUSE / N_COLS);
+
+ /* wscons has support for screen saver via the WSDISPLAYIO_{G,S}VIDEO
+ with WSDISPLAY_VIDEO_OFF and WSDISPLAY_VIDEO_ON values.
+ However, none of the pc display driver (pcdisplay.c or vga.c)
+ support this ioctl. Only the alpha display driver (tga.c) support it.
+
+ When screen saver support is available, /usr/sbin/screenblank can be
+ used with the -m option, so that mice movements stop the screen
+ saver.
+ */
+
+ /* update position */
+
+ if (mouse_col + dx >= MAXCOL)
+ mouse_col = MAXCOL;
+ else
+ if (mouse_col + dx <= 0)
+ mouse_col = 0;
+ else
+ mouse_col += dx;
+ if (mouse_row + dy >= MAXROW)
+ mouse_row = MAXROW;
+ else
+ if (mouse_row + dy <= 0)
+ mouse_row = 0;
+ else
+ mouse_row += dy;
+ MOUSE = XY_TO_POS(mouse_col, mouse_row);
+ /* if we have moved */
+ if (old_mouse != MOUSE) {
+ /* hide the previous cursor, if not in a selection */
+ if (IS_MOUSE_VISIBLE(sc->sc_focus)
+ && (!IS_SEL_IN_PROGRESS(sc->sc_focus)))
+ inverse_char(old_mouse);
+ if (IS_SEL_IN_PROGRESS(sc->sc_focus)) {
+ /* selection in progress */
+ mouse_copy_extend();
+ }
+ else {
+ inverse_char(MOUSE);
+ MOUSE_FLAGS |= MOUSE_VISIBLE;
+ }
+ }
+}
+
+void
+inverse_char(unsigned short pos)
+{
+ u_int16_t uc;
+ u_int16_t attr;
+
+ uc = GET_FULLCHAR(pos);
+ attr = uc;
+
+ if ((attr >> 8) == 0)
+ attr = (FG_LIGHTGREY << 8);
+
+ attr = (((attr >> 8) & 0x88) | ((((attr >> 8) >> 4) |
+ ((attr >> 8) << 4)) & 0x77)) ;
+ PUTCHAR(pos, (u_int) (uc & 0x00FF), (long) attr);
+}
+
+void
+inverse_region(unsigned short start, unsigned short end)
+{
+ unsigned short current_pos;
+ unsigned short abs_end;
+
+ /* sanity check, useful because 'end' can be (0 - 1) = 65535 */
+ abs_end = N_COLS * N_ROWS;
+ if (end > abs_end)
+ return ;
+ current_pos = start;
+ while (current_pos <= end)
+ inverse_char(current_pos++);
+}
+
+/*
+ * Return the number of contiguous blank characters between the right margin
+ * if border == 1 or between the next non-blank character and the current mouse
+ * cursor if border == 0
+ */
+unsigned char
+skip_spc_right(char border)
+{
+ unsigned short current = CPY_END;
+ unsigned short mouse_col = (CPY_END % N_COLS);
+ unsigned short limit = current + (N_COLS - mouse_col - 1);
+ unsigned char res = 0;
+
+ while ((GETCHAR(current) == ' ') && (current <= limit)) {
+ current++;
+ res++;
+ }
+ if (border == BORDER) {
+ if (current > limit)
+ return (res - 1);
+ else
+ return (0);
+ }
+ else {
+ if (res)
+ return (res - 1);
+ else
+ return res;
+ }
+}
+
+/*
+ * Return the number of contiguous blank characters between the first of the
+ * contiguous blank characters and the current mouse cursor
+ */
+unsigned char
+skip_spc_left(void)
+{
+ short current = CPY_START;
+ unsigned short mouse_col = (MOUSE % N_COLS);
+ unsigned short limit = current - mouse_col;
+ unsigned char res = 0;
+
+ while ((GETCHAR(current) == ' ') && (current >= limit)) {
+ current--;
+ res++;
+ }
+ if (res)
+ res--;
+ return (res);
+}
+
+/*
+ * Class of characters
+ * Stolen from xterm sources of the Xfree project (see cvs tag below)
+ * $TOG: button.c /main/76 1997/07/30 16:56:19 kaleb $
+ */
+static int charClass[256] = {
+/* NUL SOH STX ETX EOT ENQ ACK BEL */
+ 32, 1, 1, 1, 1, 1, 1, 1,
+/* BS HT NL VT NP CR SO SI */
+ 1, 32, 1, 1, 1, 1, 1, 1,
+/* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */
+ 1, 1, 1, 1, 1, 1, 1, 1,
+/* CAN EM SUB ESC FS GS RS US */
+ 1, 1, 1, 1, 1, 1, 1, 1,
+/* SP ! " # $ % & ' */
+ 32, 33, 34, 35, 36, 37, 38, 39,
+/* ( ) * + , - . / */
+ 40, 41, 42, 43, 44, 45, 46, 47,
+/* 0 1 2 3 4 5 6 7 */
+ 48, 48, 48, 48, 48, 48, 48, 48,
+/* 8 9 : ; < = > ? */
+ 48, 48, 58, 59, 60, 61, 62, 63,
+/* @ A B C D E F G */
+ 64, 48, 48, 48, 48, 48, 48, 48,
+/* H I J K L M N O */
+ 48, 48, 48, 48, 48, 48, 48, 48,
+/* P Q R S T U V W */
+ 48, 48, 48, 48, 48, 48, 48, 48,
+/* X Y Z [ \ ] ^ _ */
+ 48, 48, 48, 91, 92, 93, 94, 48,
+/* ` a b c d e f g */
+ 96, 48, 48, 48, 48, 48, 48, 48,
+/* h i j k l m n o */
+ 48, 48, 48, 48, 48, 48, 48, 48,
+/* p q r s t u v w */
+ 48, 48, 48, 48, 48, 48, 48, 48,
+/* x y z { | } ~ DEL */
+ 48, 48, 48, 123, 124, 125, 126, 1,
+/* x80 x81 x82 x83 IND NEL SSA ESA */
+ 1, 1, 1, 1, 1, 1, 1, 1,
+/* HTS HTJ VTS PLD PLU RI SS2 SS3 */
+ 1, 1, 1, 1, 1, 1, 1, 1,
+/* DCS PU1 PU2 STS CCH MW SPA EPA */
+ 1, 1, 1, 1, 1, 1, 1, 1,
+/* x98 x99 x9A CSI ST OSC PM APC */
+ 1, 1, 1, 1, 1, 1, 1, 1,
+/* - i c/ L ox Y- | So */
+ 160, 161, 162, 163, 164, 165, 166, 167,
+/* .. c0 ip << _ R0 - */
+ 168, 169, 170, 171, 172, 173, 174, 175,
+/* o +- 2 3 ' u q| . */
+ 176, 177, 178, 179, 180, 181, 182, 183,
+/* , 1 2 >> 1/4 1/2 3/4 ? */
+ 184, 185, 186, 187, 188, 189, 190, 191,
+/* A` A' A^ A~ A: Ao AE C, */
+ 48, 48, 48, 48, 48, 48, 48, 48,
+/* E` E' E^ E: I` I' I^ I: */
+ 48, 48, 48, 48, 48, 48, 48, 48,
+/* D- N~ O` O' O^ O~ O: X */
+ 48, 48, 48, 48, 48, 48, 48, 216,
+/* O/ U` U' U^ U: Y' P B */
+ 48, 48, 48, 48, 48, 48, 48, 48,
+/* a` a' a^ a~ a: ao ae c, */
+ 48, 48, 48, 48, 48, 48, 48, 48,
+/* e` e' e^ e: i` i' i^ i: */
+ 48, 48, 48, 48, 48, 48, 48, 48,
+/* d n~ o` o' o^ o~ o: -: */
+ 48, 48, 48, 48, 48, 48, 48, 248,
+/* o/ u` u' u^ u: y' P y: */
+ 48, 48, 48, 48, 48, 48, 48, 48};
+
+/*
+ * Find the first blank beginning after the current cursor position
+ */
+unsigned char
+skip_char_right(unsigned short offset)
+{
+ unsigned short current = offset;
+ unsigned short limit = current + (N_COLS - (MOUSE % N_COLS) - 1);
+ unsigned char class = charClass[GETCHAR(current)];
+ unsigned char res = 0;
+
+ while ((charClass[GETCHAR(current)] == class)
+ && (current <= limit)) {
+ current++;
+ res++;
+ }
+ if (res)
+ res--;
+ return (res);
+}
+
+/*
+ * Find the first non-blank character before the cursor position
+ */
+unsigned char
+skip_char_left(unsigned short offset)
+{
+ short current = offset;
+ unsigned short limit = current - (MOUSE % N_COLS);
+ unsigned char class = charClass[GETCHAR(current)];
+ unsigned char res = 0;
+
+ while ((charClass[GETCHAR(current)] == class) && (current >= limit)) {
+ current--;
+ res++;
+ }
+ if (res)
+ res--;
+ return (res);
+}
+
+/*
+ * Compare character classes
+ */
+unsigned char
+class_cmp(unsigned short first,
+ unsigned short second)
+{
+ unsigned char first_class;
+ unsigned char second_class;
+
+ first_class = charClass[GETCHAR(first)];
+ second_class = charClass[GETCHAR(second)];
+
+ if (first_class != second_class)
+ return (1);
+ else
+ return (0);
+}
+
+/*
+ * Beginning of a copy operation
+ */
+void
+mouse_copy_start(void)
+{
+ unsigned char right;
+ /* if no selection, then that's the first one */
+
+ if (!Paste_avail)
+ Paste_avail = 1;
+
+ /* remove the previous selection */
+
+ if (IS_SEL_EXISTS(sc->sc_focus))
+ remove_selection(sc);
+
+ /* initial show of the cursor */
+ if (!IS_MOUSE_VISIBLE(sc->sc_focus))
+ inverse_char(MOUSE);
+
+ CPY_START = MOUSE;
+ CPY_END = MOUSE;
+ ORIG_START = CPY_START;
+ ORIG_END = CPY_END;
+ CURSOR = CPY_END + 1; /* init value */
+
+ right = skip_spc_right(BORDER); /* useful later, in mouse_copy_extend */
+ if (right)
+ MOUSE_FLAGS |= BLANK_TO_EOL;
+
+ MOUSE_FLAGS |= SEL_IN_PROGRESS;
+ MOUSE_FLAGS |= SEL_EXISTS;
+ MOUSE_FLAGS |= SEL_BY_CHAR; /* select by char */
+ MOUSE_FLAGS &= ~SEL_BY_WORD;
+ MOUSE_FLAGS &= ~SEL_BY_LINE;
+ MOUSE_FLAGS &= ~MOUSE_VISIBLE; /* cursor hidden in selection */
+}
+
+/*
+ * Copy of the word under the cursor
+ */
+void
+mouse_copy_word()
+{
+ unsigned char right;
+ unsigned char left;
+
+ if (IS_SEL_EXISTS(sc->sc_focus))
+ remove_selection(sc);
+
+ if (IS_MOUSE_VISIBLE(sc->sc_focus))
+ inverse_char(MOUSE);
+
+ CPY_START = MOUSE;
+ CPY_END = MOUSE;
+
+ if (IS_ALPHANUM(MOUSE)) {
+ right = skip_char_right(CPY_END);
+ left = skip_char_left(CPY_START);
+ }
+ else {
+ right = skip_spc_right(NO_BORDER);
+ left = skip_spc_left();
+ }
+
+ CPY_START -= left;
+ CPY_END += right;
+ ORIG_START = CPY_START;
+ ORIG_END = CPY_END;
+ CURSOR = CPY_END + 1; /* init value, never happen */
+ inverse_region(CPY_START, CPY_END);
+
+ MOUSE_FLAGS |= SEL_IN_PROGRESS;
+ MOUSE_FLAGS |= SEL_EXISTS;
+ MOUSE_FLAGS &= ~SEL_BY_CHAR;
+ MOUSE_FLAGS |= SEL_BY_WORD;
+ MOUSE_FLAGS &= ~SEL_BY_LINE;
+
+ /* mouse cursor hidden in the selection */
+ MOUSE_FLAGS &= ~BLANK_TO_EOL;
+ MOUSE_FLAGS &= ~MOUSE_VISIBLE;
+}
+
+/*
+ * Copy of the current line
+ */
+void
+mouse_copy_line(void)
+{
+ unsigned char row = MOUSE / N_COLS;
+
+ if (IS_SEL_EXISTS(sc->sc_focus))
+ remove_selection(sc);
+
+ if (IS_MOUSE_VISIBLE(sc->sc_focus))
+ inverse_char(MOUSE);
+
+ CPY_START = row * N_COLS;
+ CPY_END = CPY_START + (N_COLS - 1);
+ ORIG_START = CPY_START;
+ ORIG_END = CPY_END;
+ CURSOR = CPY_END + 1;
+ inverse_region(CPY_START, CPY_END);
+
+ MOUSE_FLAGS |= SEL_IN_PROGRESS;
+ MOUSE_FLAGS |= SEL_EXISTS;
+ MOUSE_FLAGS &= ~SEL_BY_CHAR;
+ MOUSE_FLAGS &= ~SEL_BY_WORD;
+ MOUSE_FLAGS |= SEL_BY_LINE;
+
+ /* mouse cursor hidden in the selection */
+ MOUSE_FLAGS &= ~BLANK_TO_EOL;
+ MOUSE_FLAGS &= ~MOUSE_VISIBLE;
+}
+
+/*
+ * End of a copy operation
+ */
+void
+mouse_copy_end(void)
+{
+ MOUSE_FLAGS &= ~(SEL_IN_PROGRESS);
+ if (IS_SEL_BY_WORD(sc->sc_focus) || IS_SEL_BY_LINE(sc->sc_focus)) {
+ if (CURSOR != (CPY_END + 1))
+ inverse_char(CURSOR);
+ CURSOR = CPY_END + 1;
+ }
+}
+
+
+/*
+ * Generic selection extend function
+ */
+void
+mouse_copy_extend(void)
+{
+ if (IS_SEL_BY_CHAR(sc->sc_focus))
+ mouse_copy_extend_char();
+ if (IS_SEL_BY_WORD(sc->sc_focus))
+ mouse_copy_extend_word();
+ if (IS_SEL_BY_LINE(sc->sc_focus))
+ mouse_copy_extend_line();
+}
+
+/*
+ * Extend a selected region, character by character
+ */
+void
+mouse_copy_extend_char()
+{
+ unsigned char right;
+
+ if (!IS_SEL_EXT_AFTER(sc->sc_focus)) {
+
+ if (IS_BLANK_TO_EOL(sc->sc_focus)) {
+ /*
+ * First extension of selection. We handle special
+ * cases of blank characters to eol
+ */
+
+ right = skip_spc_right(BORDER);
+ if (MOUSE > ORIG_START) {
+ /* the selection goes to the lower part of
+ the screen */
+
+ /* remove the previous cursor, start of
+ selection is now next line */
+ inverse_char(CPY_START);
+ CPY_START += (right + 1);
+ CPY_END = CPY_START;
+ ORIG_START = CPY_START;
+ /* simulate the initial mark */
+ inverse_char(CPY_START);
+ }
+ else {
+ /* the selection goes to the upper part
+ of the screen */
+ /* remove the previous cursor, start of
+ selection is now at the eol */
+ inverse_char(CPY_START);
+ ORIG_START += (right + 1);
+ CPY_START = ORIG_START - 1;
+ CPY_END = ORIG_START - 1;
+ /* simulate the initial mark */
+ inverse_char(CPY_START);
+ }
+ MOUSE_FLAGS &= ~ BLANK_TO_EOL;
+ }
+
+ if (MOUSE < ORIG_START
+ && CPY_END >= ORIG_START) {
+ /* we go to the upper part of the screen */
+
+ /* reverse the old selection region */
+ remove_selection(sc);
+ CPY_END = ORIG_START - 1;
+ CPY_START = ORIG_START;
+ }
+ if (CPY_START < ORIG_START
+ && MOUSE >= ORIG_START) {
+ /* we go to the lower part of the screen */
+
+ /* reverse the old selection region */
+
+ remove_selection(sc);
+ CPY_START = ORIG_START;
+ CPY_END = ORIG_START - 1;
+ }
+ /* restore flags cleared in remove_selection() */
+ MOUSE_FLAGS |= SEL_IN_PROGRESS;
+ MOUSE_FLAGS |= SEL_EXISTS;
+ }
+ /* beginning of common part */
+
+ if (MOUSE >= ORIG_START) {
+
+ /* lower part of the screen */
+ if (MOUSE > CPY_END)
+ /* extending selection */
+ inverse_region(CPY_END + 1, MOUSE);
+ else
+ /* reducing selection */
+ inverse_region(MOUSE + 1, CPY_END);
+ CPY_END = MOUSE;
+ }
+ else {
+ /* upper part of the screen */
+ if (MOUSE < CPY_START)
+ /* extending selection */
+ inverse_region(MOUSE,CPY_START - 1);
+ else
+ /* reducing selection */
+ inverse_region(CPY_START,MOUSE - 1);
+ CPY_START = MOUSE;
+ }
+ /* end of common part */
+}
+
+/*
+ * Extend a selected region, word by word
+ */
+void
+mouse_copy_extend_word(void)
+{
+ unsigned short old_cpy_end;
+ unsigned short old_cpy_start;
+
+ if (!IS_SEL_EXT_AFTER(sc->sc_focus)) {
+
+ /* remove cursor in selection (black one) */
+
+ if (CURSOR != (CPY_END + 1))
+ inverse_char(CURSOR);
+
+ /* now, switch between lower and upper part of the screen */
+
+ if (MOUSE < ORIG_START
+ && CPY_END >= ORIG_START) {
+ /* going to the upper part of the screen */
+ inverse_region(ORIG_END + 1, CPY_END);
+ CPY_END = ORIG_END;
+ }
+
+ if (MOUSE > ORIG_END
+ && CPY_START <= ORIG_START) {
+ /* going to the lower part of the screen */
+ inverse_region(CPY_START, ORIG_START - 1);
+ CPY_START = ORIG_START;
+ }
+ }
+
+ if (MOUSE >= ORIG_START) {
+ /* lower part of the screen */
+
+ if (MOUSE > CPY_END) {
+ /* extending selection */
+
+ old_cpy_end = CPY_END;
+ CPY_END = MOUSE + skip_char_right(MOUSE);
+ inverse_region(old_cpy_end + 1, CPY_END);
+ }
+ else {
+ if (class_cmp(MOUSE, MOUSE + 1)) {
+ /* reducing selection (remove last word) */
+ old_cpy_end = CPY_END;
+ CPY_END = MOUSE;
+ inverse_region(CPY_END + 1, old_cpy_end);
+ }
+ else {
+ old_cpy_end = CPY_END;
+ CPY_END = MOUSE +
+ skip_char_right(MOUSE);
+ if (CPY_END != old_cpy_end) {
+ /* reducing selection, from the end of
+ * next word */
+ inverse_region(CPY_END + 1,
+ old_cpy_end);
+ }
+ }
+ }
+ }
+ else {
+ /* upper part of the screen */
+ if (MOUSE < CPY_START) {
+ /* extending selection */
+ old_cpy_start = CPY_START;
+ CPY_START = MOUSE - skip_char_left(MOUSE);
+ inverse_region(CPY_START, old_cpy_start - 1);
+ }
+ else {
+ if (class_cmp(MOUSE - 1, MOUSE)) {
+ /* reducing selection (remove last word) */
+ old_cpy_start = CPY_START;
+ CPY_START = MOUSE;
+ inverse_region(old_cpy_start,
+ CPY_START - 1);
+ }
+ else {
+ old_cpy_start = CPY_START;
+ CPY_START = MOUSE -
+ skip_char_left(MOUSE);
+ if (CPY_START != old_cpy_start)
+ inverse_region(old_cpy_start,
+ CPY_START - 1);
+ }
+ }
+ }
+
+ if (!IS_SEL_EXT_AFTER(sc->sc_focus)) {
+ /* display new cursor */
+ CURSOR = MOUSE;
+ inverse_char(CURSOR);
+ }
+}
+
+/*
+ * Extend a selected region, line by line
+ */
+void
+mouse_copy_extend_line(void)
+{
+ unsigned short old_row;
+ unsigned short new_row;
+ unsigned short old_cpy_start;
+ unsigned short old_cpy_end;
+
+ if (!IS_SEL_EXT_AFTER(sc->sc_focus)) {
+ /* remove cursor in selection (black one) */
+
+ if (CURSOR != (CPY_END + 1))
+ inverse_char(CURSOR);
+
+ /* now, switch between lower and upper part of the screen */
+
+ if (MOUSE < ORIG_START
+ && CPY_END >= ORIG_START) {
+ /* going to the upper part of the screen */
+ inverse_region(ORIG_END + 1, CPY_END);
+ CPY_END = ORIG_END;
+ }
+
+ if (MOUSE > ORIG_END
+ && CPY_START <= ORIG_START) {
+ /* going to the lower part of the screen */
+ inverse_region(CPY_START, ORIG_START - 1);
+ CPY_START = ORIG_START;
+ }
+ }
+
+ if (MOUSE >= ORIG_START) {
+ /* lower part of the screen */
+ if (CURSOR == (CPY_END + 1))
+ CURSOR = CPY_END;
+ old_row = CURSOR / N_COLS;
+ new_row = MOUSE / N_COLS;
+ old_cpy_end = CPY_END;
+ CPY_END = (new_row * N_COLS) + MAXCOL;
+ if (new_row > old_row)
+ inverse_region(old_cpy_end + 1, CPY_END);
+ else if (new_row < old_row)
+ inverse_region(CPY_END + 1, old_cpy_end);
+ }
+ else {
+ /* upper part of the screen */
+ old_row = CURSOR / N_COLS;
+ new_row = MOUSE / N_COLS;
+ old_cpy_start = CPY_START;
+ CPY_START = new_row * N_COLS;
+ if (new_row < old_row)
+ inverse_region(CPY_START, old_cpy_start - 1);
+ else if (new_row > old_row)
+ inverse_region(old_cpy_start, CPY_START - 1);
+ }
+
+ if (!IS_SEL_EXT_AFTER(sc->sc_focus)) {
+ /* display new cursor */
+ CURSOR = MOUSE;
+ inverse_char(CURSOR);
+ }
+}
+
+void
+mouse_hide(struct wsdisplay_softc *sc)
+{
+ if (IS_MOUSE_VISIBLE(sc->sc_focus)) {
+ inverse_char(MOUSE);
+ MOUSE_FLAGS &= ~MOUSE_VISIBLE;
+ }
+}
+
+/*
+ * Add an extension to a selected region, word by word
+ */
+void
+mouse_copy_extend_after(void)
+{
+ unsigned short start_dist;
+ unsigned short end_dist;
+
+ if (IS_SEL_EXISTS(sc->sc_focus)) {
+ MOUSE_FLAGS |= SEL_EXT_AFTER;
+ mouse_hide(sc); /* hide current cursor */
+
+ if (CPY_START > MOUSE)
+ start_dist = CPY_START - MOUSE;
+ else
+ start_dist = MOUSE - CPY_START;
+ if (MOUSE > CPY_END)
+ end_dist = MOUSE - CPY_END;
+ else
+ end_dist = CPY_END - MOUSE;
+ if (start_dist < end_dist) {
+ /* upper part of the screen*/
+ ORIG_START = MOUSE + 1;
+ /* only used in mouse_copy_extend_line() */
+ CURSOR = CPY_START;
+ }
+ else {
+ /* lower part of the screen */
+ ORIG_START = MOUSE;
+ /* only used in mouse_copy_extend_line() */
+ CURSOR = CPY_END;
+ }
+ if (IS_SEL_BY_CHAR(sc->sc_focus))
+ mouse_copy_extend_char();
+ if (IS_SEL_BY_WORD(sc->sc_focus))
+ mouse_copy_extend_word();
+ if (IS_SEL_BY_LINE(sc->sc_focus))
+ mouse_copy_extend_line();
+ mouse_copy_selection();
+ }
+ else
+ /* no selection yet! */
+ sysbeep(1193182 /* PCVT_SYSBEEPF */ / 1500, hz / 4);
+}
+
+
+/*
+ * Remove a previously selected region
+ */
+void
+remove_selection(struct wsdisplay_softc *sc)
+{
+ if (IS_SEL_EXT_AFTER(sc->sc_focus))
+ /* reset the flag indicating an extension of selection */
+ MOUSE_FLAGS &= ~SEL_EXT_AFTER;
+ inverse_region(CPY_START, CPY_END);
+ MOUSE_FLAGS &= ~SEL_IN_PROGRESS;
+ MOUSE_FLAGS &= ~SEL_EXISTS;
+}
+
+/*
+ * Put the current visual selection in the selection buffer
+ */
+void
+mouse_copy_selection(void)
+{
+ unsigned short current = 0;
+ unsigned short blank = current;
+ unsigned short buf_end = ((N_COLS + 1) * N_ROWS);
+ unsigned short sel_cur;
+ unsigned short sel_end;
+
+ sel_cur = CPY_START;
+ sel_end = CPY_END;
+
+ while (sel_cur <= sel_end && current < buf_end - 1) {
+ Copybuffer[current] = (GETCHAR(sel_cur));
+ if (!IS_SPACE(Copybuffer[current]))
+ blank = current + 1; /* first blank after non-blank */
+ current++;
+ if (POS_TO_X(sel_cur) == MAXCOL) {
+ /* we are on the last col of the screen */
+ Copybuffer[blank] = '\r'; /* carriage return */
+ current = blank + 1; /* restart just after the carriage
+ return in the buffer */
+ blank = current;
+ }
+ sel_cur++;
+ }
+
+ Copybuffer[current] = '\0';
+}
+
+/*
+ * Paste the current selection
+ */
+void
+mouse_paste(void)
+{
+ unsigned short len;
+ char *current = Copybuffer;
+
+ if (Paste_avail) {
+ for (len = strlen(Copybuffer) ; len > 0; len--) {
+ (*linesw[sc->sc_focus->scr_tty->t_line].l_rint)
+ (*current++, sc->sc_focus->scr_tty);
+ }
+ }
+ else
+ sysbeep(1193182 /* PCVT_SYSBEEPF */ / 1500, hz / 4);
+}
+
+
+/*
+ * Handle the z axis
+ * The z axis (roller or wheel) is mapped by default to scrollback
+ */
+void
+mouse_zaxis(int z)
+{
+ if (z < 0)
+ wsscrollback(sc, WSDISPLAY_SCROLL_BACKWARD);
+ else
+ wsscrollback(sc, WSDISPLAY_SCROLL_FORWARD);
+}
+
+/*
+ * Allocate the copy buffer. The size is :
+ * (cols + 1) * (rows)
+ * (+1 for '\n' at the end of lines),
+ * where cols and rows are the maximum of column and rows numbers of all screens
+ */
+void
+allocate_copybuffer(struct wsdisplay_softc *sc)
+{
+ int nscreens = sc->sc_scrdata->nscreens;
+ int i,s;
+ const struct wsscreen_descr **screens_list = sc->sc_scrdata->screens;
+ const struct wsscreen_descr *current;
+ unsigned short size = Copybuffer_size;
+
+ s = splhigh();
+ for ( i = 0 ; i < nscreens ; i++) {
+ current = *screens_list;
+ if (( (current->ncols + 1) * current->nrows) > size)
+ size = ((current->ncols + 1) * current->nrows);
+ screens_list++;
+ }
+ if ((size != Copybuffer_size) && (Copybuffer_size != 0)) {
+ bzero(Copybuffer, Copybuffer_size);
+ free(Copybuffer, M_DEVBUF);
+ }
+ if ((Copybuffer = (char *)malloc(size, M_DEVBUF, M_NOWAIT)) == NULL) {
+ printf("wscons: copybuffer memory malloc failed\n");
+ Copybuffer_size = 0;
+ }
+ Copybuffer_size = size;
+ splx(s);
+}
diff --git a/sys/dev/wscons/wsdisplayvar.h b/sys/dev/wscons/wsdisplayvar.h
index b9b7d5e0225..1674f53d6d6 100644
--- a/sys/dev/wscons/wsdisplayvar.h
+++ b/sys/dev/wscons/wsdisplayvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: wsdisplayvar.h,v 1.8 2001/03/14 02:49:22 mickey Exp $ */
+/* $OpenBSD: wsdisplayvar.h,v 1.9 2001/04/14 04:44:02 aaron Exp $ */
/* $NetBSD: wsdisplayvar.h,v 1.14.4.1 2000/06/30 16:27:53 simonb Exp $ */
/*
@@ -114,6 +114,7 @@ struct wsdisplay_accessops {
void (*) (void *, int, int), void *));
int (*load_font) __P((void *, void *, struct wsdisplay_font *));
void (*scrollback) __P((void *, void *, int));
+ u_int16_t (*getchar) __P((void *, int, int));
void (*pollc) __P((void *, int));
};
diff --git a/sys/dev/wscons/wsmoused.h b/sys/dev/wscons/wsmoused.h
new file mode 100644
index 00000000000..42852fa7f30
--- /dev/null
+++ b/sys/dev/wscons/wsmoused.h
@@ -0,0 +1,127 @@
+/* $OpenBSD: wsmoused.h,v 1.1 2001/04/14 04:44:02 aaron Exp $ */
+
+/*
+ * Copyright (c) 2001 Jean-Baptiste Marchand, Julien Montagne and Jerome Verdon
+ *
+ * All rights reserved.
+ *
+ * This code is for mouse console support under the wscons console driver.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by
+ * Hellmuth Michaelis, Brian Dunford-Shore, Joerg Wunsch, Scott Turner
+ * and Charles Hannum.
+ * 4. The name authors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ */
+
+
+int wsmoused __P((struct wsdisplay_softc *, u_long, caddr_t, int,
+ struct proc *p));
+
+void motion_event __P((u_int, int));
+void button_event __P((int, int));
+int ctrl_event __P((u_int, int, struct wsdisplay_softc *, struct proc *));
+
+void mouse_moverel __P((char, char));
+
+void inverse_char __P((unsigned short c));
+void inverse_region __P((unsigned short start, unsigned short end));
+
+unsigned char skip_spc_right __P((char));
+unsigned char skip_spc_left __P((void));
+unsigned char skip_char_right __P((unsigned short));
+unsigned char skip_char_left __P((unsigned short));
+unsigned char class_cmp __P((unsigned short, unsigned short));
+
+void mouse_copy_start __P((void));
+void mouse_copy_word __P((void));
+void mouse_copy_line __P((void));
+void mouse_copy_end __P((void));
+void mouse_copy_extend __P((void));
+void mouse_copy_extend_char __P((void));
+void mouse_copy_extend_word __P((void));
+void mouse_copy_extend_line __P((void));
+void mouse_hide __P((struct wsdisplay_softc *));
+void mouse_copy_extend_after __P((void));
+void remove_selection __P((struct wsdisplay_softc *));
+void mouse_copy_selection __P((void));
+void mouse_paste __P((void));
+
+void mouse_zaxis __P((int));
+void allocate_copybuffer __P((struct wsdisplay_softc *));
+
+void sysbeep __P((int, int));
+
+char *Copybuffer = NULL; /* buffer that contains mouse selections */
+unsigned int Copybuffer_size = 0;
+char Paste_avail = 0; /* flag, to indicate whether a selection is in the
+ Copy buffer */
+
+#define NO_BORDER 0
+#define BORDER 1
+
+#define WS_NCOLS(ws) ((ws)->scr_dconf->scrdata->ncols)
+#define WS_NROWS(ws) ((ws)->scr_dconf->scrdata->nrows)
+
+#define MAXCOL (WS_NCOLS(sc->sc_focus) - 1)
+#define MAXROW (WS_NROWS(sc->sc_focus) - 1)
+
+#define N_COLS (WS_NCOLS(sc->sc_focus))
+#define N_ROWS (WS_NROWS(sc->sc_focus))
+#define MOUSE (sc->sc_focus->mouse)
+#define CURSOR (sc->sc_focus->cursor)
+#define CPY_START (sc->sc_focus->cpy_start)
+#define CPY_END (sc->sc_focus->cpy_end)
+#define ORIG_START (sc->sc_focus->orig_start)
+#define ORIG_END (sc->sc_focus->orig_end)
+#define MOUSE_FLAGS (sc->sc_focus->mouse_flags)
+
+#define XY_TO_POS(col, row) (((row) * N_COLS) + (col))
+#define POS_TO_X(pos) ((pos) % (N_COLS))
+#define POS_TO_Y(pos) ((pos) / (N_COLS))
+
+#define GET_FULLCHAR(pos)\
+((*sc->sc_accessops->getchar)\
+ (sc->sc_accesscookie,\
+ ((pos) / N_COLS), ((pos) % N_COLS)))
+
+#define GETCHAR(pos)\
+(((*sc->sc_accessops->getchar)\
+ (sc->sc_accesscookie,\
+ ((pos) / N_COLS), ((pos) % N_COLS)))\
+ & 0x000000FF)
+
+#define PUTCHAR(pos, uc, attr)\
+((*sc->sc_focus->scr_dconf->emulops->putchar)\
+(sc->sc_focus->scr_dconf->emulcookie, ((pos) / N_COLS),\
+ ((pos) % N_COLS), (uc), (attr)));
+
+#define MOUSE_COPY_BUTTON 0
+#define MOUSE_PASTE_BUTTON 1
+#define MOUSE_EXTEND_BUTTON 2
+
+#define IS_ALPHANUM(pos) (GETCHAR((pos)) != ' ')
+#define IS_SPACE(c) ((c) == ' ')