diff options
author | Aaron Campbell <aaron@cvs.openbsd.org> | 2000-09-01 05:46:03 +0000 |
---|---|---|
committer | Aaron Campbell <aaron@cvs.openbsd.org> | 2000-09-01 05:46:03 +0000 |
commit | 3792ae36e016293db570ba44569964b6f1958cf1 (patch) | |
tree | db694f9e74727ef1d7aecfc1af5a4ff2f0bef847 /sys/arch/i386 | |
parent | 001402bb9c907b93d531c87f15f4ce0f9f4bdc4c (diff) |
Kernel support for new PCVT console mouse features.
- Basic cut/paste functionality.
- Wheel mouse support (wheel rolls page-by-page through scrollback buffer).
- Copybuffer ownership. i.e., if User X logs in the console and selects text,
when User Y logs in later the buffer cannot be pasted.
Big thanks to Jean-Baptiste Marchand, Julien Montagne, and Jerome Verdon for
implementing this.
Diffstat (limited to 'sys/arch/i386')
-rw-r--r-- | sys/arch/i386/conf/files.i386 | 3 | ||||
-rw-r--r-- | sys/arch/i386/isa/pcvt/Util/Makefile | 6 | ||||
-rw-r--r-- | sys/arch/i386/isa/pcvt/pcvt_drv.c | 55 | ||||
-rw-r--r-- | sys/arch/i386/isa/pcvt/pcvt_ext.c | 9 | ||||
-rw-r--r-- | sys/arch/i386/isa/pcvt/pcvt_hdr.h | 28 | ||||
-rw-r--r-- | sys/arch/i386/isa/pcvt/pcvt_ioctl.h | 10 | ||||
-rw-r--r-- | sys/arch/i386/isa/pcvt/pcvt_kbd.c | 128 | ||||
-rw-r--r-- | sys/arch/i386/isa/pcvt/pcvt_mouse.c | 723 | ||||
-rw-r--r-- | sys/arch/i386/isa/pcvt/pcvt_mouse.h | 96 | ||||
-rw-r--r-- | sys/arch/i386/isa/pcvt/pcvt_out.c | 15 |
10 files changed, 1041 insertions, 32 deletions
diff --git a/sys/arch/i386/conf/files.i386 b/sys/arch/i386/conf/files.i386 index 3652a1ae64a..29f86df4b78 100644 --- a/sys/arch/i386/conf/files.i386 +++ b/sys/arch/i386/conf/files.i386 @@ -1,4 +1,4 @@ -# $OpenBSD: files.i386,v 1.70 2000/08/17 20:15:33 mickey Exp $ +# $OpenBSD: files.i386,v 1.71 2000/09/01 05:46:01 aaron Exp $ # $NetBSD: files.i386,v 1.73 1996/05/07 00:58:36 thorpej Exp $ # # new style config file for i386 architecture @@ -144,6 +144,7 @@ attach vt at isa file arch/i386/isa/pcvt/pcvt_drv.c vt needs-flag file arch/i386/isa/pcvt/pcvt_ext.c vt needs-flag file arch/i386/isa/pcvt/pcvt_kbd.c vt needs-flag +file arch/i386/isa/pcvt/pcvt_mouse.c vt needs-flag file arch/i386/isa/pcvt/pcvt_out.c vt needs-flag file arch/i386/isa/pcvt/pcvt_sup.c vt needs-flag file arch/i386/isa/pcvt/pcvt_vtf.c vt needs-flag diff --git a/sys/arch/i386/isa/pcvt/Util/Makefile b/sys/arch/i386/isa/pcvt/Util/Makefile index 4680544fa44..8e3fa97792c 100644 --- a/sys/arch/i386/isa/pcvt/Util/Makefile +++ b/sys/arch/i386/isa/pcvt/Util/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.6 2000/05/29 08:17:32 deraadt Exp $ +# $OpenBSD: Makefile,v 1.7 2000/09/01 05:46:02 aaron Exp $ SUBDIR= keycap cursor fontedit kcon loadfont scon \ userkeys vttest ispcvt pcvtdoc fed @@ -16,5 +16,9 @@ includes: ${DESTDIR}/usr/include/machine/pcvt_ioctl.h > /dev/null 2>&1 || \ install -c -o ${BINOWN} -g ${BINGRP} -m 444 ../pcvt_ioctl.h \ ${DESTDIR}/usr/include/machine + -cd ${.CURDIR}; cmp -s ../pcvt_mouse.h \ + ${DESTDIR}/usr/include/machine/pcvt_mouse.h > /dev/null 2>&1 || \ + install -c -o ${BINOWN} -g ${BINGRP} -m 444 ../pcvt_mouse.h \ + ${DESTDIR}/usr/include/machine .include <bsd.subdir.mk> diff --git a/sys/arch/i386/isa/pcvt/pcvt_drv.c b/sys/arch/i386/isa/pcvt/pcvt_drv.c index a816ef307cb..f92fdf6c7bc 100644 --- a/sys/arch/i386/isa/pcvt/pcvt_drv.c +++ b/sys/arch/i386/isa/pcvt/pcvt_drv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pcvt_drv.c,v 1.30 2000/07/19 13:39:34 art Exp $ */ +/* $OpenBSD: pcvt_drv.c,v 1.31 2000/09/01 05:46:01 aaron Exp $ */ /* * Copyright (c) 1992, 1995 Hellmuth Michaelis and Joerg Wunsch. * @@ -97,12 +97,6 @@ void pccnpollc(Dev_t, int); int pcprobe(struct device *, void *, void *); void pcattach(struct device *, struct device *, void *); - -#if PCVT_KBD_FIFO -struct timeout pcvt_to; -void pcvt_timeout(void *); -#endif - int pcprobe(struct device *parent, void *match, void *aux) { @@ -185,10 +179,6 @@ pcattach(struct device *parent, struct device *self, void *aux) async_update(); -#if PCVT_KBD_FIFO - timeout_set(&pcvt_to, pcvt_timeout, NULL); -#endif - sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, IPL_TTY, pcintr, (void *)0, sc->sc_dev.dv_xname); @@ -229,6 +219,10 @@ pcopen(Dev_t dev, int flag, int mode, struct proc *p) vsx = &vs[i]; + if (i == PCVTCTL_MINOR) { + return (0); + } + if((tp = get_pccons(dev)) == NULL) return ENXIO; @@ -342,6 +336,9 @@ pcioctl(Dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) register int error; register struct tty *tp; + if((error = mouse_ioctl(dev, cmd, data, flag, p)) >= 0) + return (error); + if((tp = get_pccons(dev)) == NULL) return(ENXIO); @@ -350,7 +347,7 @@ pcioctl(Dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) * sessions are a suspicious wish. If you really need this make the * appropriate variables arrays */ - + if((error = usl_vt_ioctl(dev, cmd, data, flag, p)) >= 0) return (error == PCVT_ERESTART) ? ERESTART : error; @@ -395,16 +392,19 @@ u_char pcvt_kbd_fifo[PCVT_KBD_FIFO_SZ]; int pcvt_kbd_wptr = 0; int pcvt_kbd_rptr = 0; short pcvt_kbd_count= 0; +static u_char pcvt_timeout_scheduled; -void +static void pcvt_timeout(void *arg) { + int s; u_char *cp; + pcvt_timeout_scheduled = 0; + #if PCVT_SCREENSAVER pcvt_scrnsv_reset(); #endif /* PCVT_SCREENSAVER */ - while (pcvt_kbd_count) { if ((cp = sgetc(1)) && (vs[current_video_screen].openf)) { #if PCVT_NULLCHARS @@ -420,6 +420,13 @@ pcvt_timeout(void *arg) (*linesw[pcconsp->t_line].l_rint)(*cp++ & 0xff, pcconsp); } + + s = spltty(); + + if (!pcvt_kbd_count) + pcvt_timeout_scheduled = 0; + + splx(s); } return; @@ -442,7 +449,6 @@ pcintr(void *arg) #if PCVT_SCREENSAVER pcvt_scrnsv_reset(); #endif /* PCVT_SCREENSAVER */ - #if PCVT_KBD_FIFO if (kbd_polling) { if(sgetc(1) == 0) @@ -473,8 +479,11 @@ pcintr(void *arg) } if (ret == 1) { /* got data from keyboard ? */ - if (!timeout_pending(&pcvt_to)) {/* if not already active .. */ - timeout_add(&pcvt_to, 1); + if (!pcvt_timeout_scheduled) { /* if not already active .. */ + s = spltty(); + pcvt_timeout_scheduled = 1; /* flag active */ + timeout((TIMEOUT_FUNC_T)pcvt_timeout, (caddr_t) 0, 1); + splx(s); } } return (ret); @@ -534,6 +543,14 @@ pcstart(register struct tty *tp) while ((len = q_to_b(&tp->t_outq, buf, PCVT_PCBURST)) != 0) { if (vs[minor(tp->t_dev)].scrolling) sgetc(31337); + if (vsp == &vs[minor(tp->t_dev)]) { + if (IS_SEL_EXISTS(vsp)) { + /* hides a potential selection */ + remove_selection(); + vsp->mouse_flags &= ~SEL_EXISTS; + } + mouse_hide(); /* hides a potential mouse cursor */ + } sput(&buf[0], 0, len, minor(tp->t_dev)); } @@ -542,7 +559,7 @@ pcstart(register struct tty *tp) tp->t_state &= ~TS_BUSY; tp->t_state |= TS_TIMEOUT; - timeout_add(&tp->t_rstrt_to, 1); + timeout(ttrstrt, tp, 1); if (tp->t_outq.c_cc <= tp->t_lowat) { low: @@ -630,7 +647,7 @@ pccngetc(Dev_t dev) cp = sgetc(0); splx(s); async_update(); - + /* this belongs to cons.c */ if (*cp == '\r') return('\n'); diff --git a/sys/arch/i386/isa/pcvt/pcvt_ext.c b/sys/arch/i386/isa/pcvt/pcvt_ext.c index 7088edb424f..d7e3ca381dd 100644 --- a/sys/arch/i386/isa/pcvt/pcvt_ext.c +++ b/sys/arch/i386/isa/pcvt/pcvt_ext.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pcvt_ext.c,v 1.26 1999/12/01 09:59:59 deraadt Exp $ */ +/* $OpenBSD: pcvt_ext.c,v 1.27 2000/09/01 05:46:01 aaron Exp $ */ /* * Copyright (c) 1992, 1995 Hellmuth Michaelis and Joerg Wunsch. @@ -2417,6 +2417,13 @@ vgapage(int new_screen) { int x; + if (IS_SEL_EXISTS(vsp)) { + /* hides a potential selection */ + remove_selection(); + vsp->mouse_flags &= ~SEL_EXISTS; + } + mouse_hide(); /* hides a potential mouse cursor */ + if(new_screen < 0 || new_screen >= totalscreens) return EINVAL; diff --git a/sys/arch/i386/isa/pcvt/pcvt_hdr.h b/sys/arch/i386/isa/pcvt/pcvt_hdr.h index 04b8d41d762..be63f60719a 100644 --- a/sys/arch/i386/isa/pcvt/pcvt_hdr.h +++ b/sys/arch/i386/isa/pcvt/pcvt_hdr.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pcvt_hdr.h,v 1.36 2000/06/08 22:25:20 niklas Exp $ */ +/* $OpenBSD: pcvt_hdr.h,v 1.37 2000/09/01 05:46:01 aaron Exp $ */ /* * Copyright (c) 1992, 1995 Hellmuth Michaelis and Joerg Wunsch. @@ -703,6 +703,18 @@ typedef struct video_state { unsigned vt_status; /* state of the vt */ /* becoming active */ int kbd_state; /* keyboard raw or translated */ + + unsigned short mouse; /* mouse cursor position */ + unsigned short cpy_start; /* position of the copy start mark*/ + unsigned short cpy_end; /* position of the copy end mark */ + unsigned short cpy_orig; /* original copy position */ +#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 IS_MOUSE_VISIBLE(vsp) ((vsp)->mouse_flags & MOUSE_VISIBLE) +#define IS_SEL_EXISTS(vsp) ((vsp)->mouse_flags & SEL_EXISTS) +#define IS_SEL_IN_PROGRESS(vsp) ((vsp)->mouse_flags & SEL_IN_PROGRESS) + unsigned char mouse_flags; /* flags, status of the mouse */ } video_state; EXTERN video_state vs[PCVT_NSCREENS]; /* parameters for screens */ @@ -1113,4 +1125,18 @@ static __inline void vt_selattr(struct video_state *svsp) #define PCVT_KBD_DELAY() delay(7) #endif /* PCVT_PORTIO_DELAY */ +/* mouse console support prototype */ + +char *Copybuffer; /* buffer that contains mouse selections */ +uid_t Copyowner; /* uid of the owner of the selection, useful for verifying + permissions on it + */ +char Paste_avail; /* flag, to indicate whether a selection is in the + Copy buffer */ + +int mouse_ioctl(Dev_t, u_long, caddr_t, int, struct proc *); +void remove_selection(void); +void mouse_hide(void); +void scrollback_mouse(int); + /*---------------------------------- E O F ----------------------------------*/ diff --git a/sys/arch/i386/isa/pcvt/pcvt_ioctl.h b/sys/arch/i386/isa/pcvt/pcvt_ioctl.h index 92bca972f33..03b00f3e586 100644 --- a/sys/arch/i386/isa/pcvt/pcvt_ioctl.h +++ b/sys/arch/i386/isa/pcvt/pcvt_ioctl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pcvt_ioctl.h,v 1.14 2000/01/18 19:34:41 aaron Exp $ */ +/* $OpenBSD: pcvt_ioctl.h,v 1.15 2000/09/01 05:46:02 aaron Exp $ */ /* * Copyright (c) 1992, 1995 Hellmuth Michaelis and Joerg Wunsch. @@ -71,6 +71,10 @@ #ifndef _MACHINE_PCVT_IOCTL_H_ #define _MACHINE_PCVT_IOCTL_H_ +/* Include for mouse console support */ + +#include "pcvt_mouse.h" + /* pcvt version information for VGAPCVTID ioctl */ #define PCVTIDNAME "pcvt" /* driver id - string */ @@ -585,4 +589,8 @@ typedef struct keymap keymap_t; /* end of USL VT compatibility stuff */ +/* Ioctl for mouse console support */ + +#define PCVT_MOUSECTL _IOW('M',1,mouse_info_t) + #endif /* ! _MACHINE_PCVT_IOCTL_H_ */ diff --git a/sys/arch/i386/isa/pcvt/pcvt_kbd.c b/sys/arch/i386/isa/pcvt/pcvt_kbd.c index 00490e6c35b..2c0ec4e3764 100644 --- a/sys/arch/i386/isa/pcvt/pcvt_kbd.c +++ b/sys/arch/i386/isa/pcvt/pcvt_kbd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pcvt_kbd.c,v 1.35 2000/07/19 13:40:26 art Exp $ */ +/* $OpenBSD: pcvt_kbd.c,v 1.36 2000/09/01 05:46:02 aaron Exp $ */ /* * Copyright (c) 1992, 1995 Hellmuth Michaelis and Joerg Wunsch. @@ -169,11 +169,12 @@ do_vgapage(int page) * get lost other times as well. */ -struct timeout kbd_led_intr_to; +static int lost_intr_timeout_queued = 0; static void check_for_lost_intr (void *arg) { + lost_intr_timeout_queued = 0; if (inb(CONTROLLER_CTRL) & STATUS_OUTPBF) { int opri = spltty(); (void)pcrint(); @@ -243,7 +244,11 @@ update_led(void) } #if PCVT_UPDLED_LOSES_INTR - timeout_add(&kbd_led_intr_to, hz); + if (lost_intr_timeout_queued) + untimeout(check_for_lost_intr, (void *)NULL); + + timeout(check_for_lost_intr, (void *)NULL, hz); + lost_intr_timeout_queued = 1; #endif /* PCVT_UPDLED_LOSES_INTR */ } bail: @@ -576,9 +581,6 @@ kbd_code_init(void) doreset(); ovlinit(0); keyboard_is_initialized = 1; -#if !PCVT_NO_LED_UPDATE && PCVT_UPDLED_LOSES_INTR - timeout_set(&kbd_led_intr_to, check_for_lost_intr, NULL); -#endif } /*---------------------------------------------------------------------------* @@ -1104,6 +1106,17 @@ regular: if ((key == 85) && shift_down && (kbd_lastkey != 85 || !kbd_status.breakseen)) { + /* removing of visual regions for mouse console support */ + if (IS_SEL_EXISTS(vsp)) { + remove_selection(); /* remove current selection before + leaving this screen */ + vsp->mouse_flags &= ~SEL_EXISTS; + } + if (IS_MOUSE_VISIBLE(vsp)) { + mouse_hide(); + vsp->mouse_flags &= ~MOUSE_VISIBLE; + } + /* end of visual regions part */ if (vsp->scr_offset && vsp->scr_offset >= vsp->row) { if (!vsp->scrolling) { vsp->scrolling += vsp->row - 1; @@ -1142,6 +1155,17 @@ regular: else if ((key == 86) && shift_down && (kbd_lastkey != 86 || !kbd_status.breakseen)) { scroll_reset: + /* removing of visual regions for mouse console support */ + if (IS_SEL_EXISTS(vsp)) { + remove_selection(); /* remove current selection before + leaving this screen */ + vsp->mouse_flags &= ~SEL_EXISTS; + } + if (IS_MOUSE_VISIBLE(vsp)) { + mouse_hide(); + vsp->mouse_flags &= ~MOUSE_VISIBLE; + } + /* end of visual regions part */ if (vsp->scrolling > 0) { vsp->scrolling -= vsp->screen_rows - 1; if (vsp->scrolling < 0) @@ -2118,4 +2142,96 @@ scrollback_restore_screen(void) bcopy(scrollback_savedscreen, vsp->Crtat, scrnsv_size); } +/* + * Function to handle the wheel + * z == 1 means to scroll to the lower page + * z == -1 means to scroll to the upper page + */ + +void +scrollback_mouse(int z) +{ + + /* removing of visual regions for mouse console support */ + + if (IS_SEL_EXISTS(vsp)) { + remove_selection(); /* remove current selection before + leaving this screen */ + vsp->mouse_flags &= ~SEL_EXISTS; + } + if (IS_MOUSE_VISIBLE(vsp)) { + mouse_hide(); + vsp->mouse_flags &= ~MOUSE_VISIBLE; + } + + if (z <= -1) + + { + if (vsp->scr_offset && vsp->scr_offset >= vsp->row) { + if (!vsp->scrolling) { + vsp->scrolling += vsp->row - 1; + if (vsp->Scrollback) { + scrollback_save_screen(); + if (vsp->scr_offset == vsp->max_off) { + bcopy(vsp->Scrollback + + vsp->maxcol, + vsp->Scrollback, + vsp->maxcol * + vsp->max_off * CHR); + vsp->scr_offset--; + } + bcopy(vsp->Crtat + vsp->cur_offset - + vsp->col, vsp->Scrollback + + (vsp->scr_offset + 1) * + vsp->maxcol, vsp->maxcol * CHR); + } + + if (vsp->cursor_on) + sw_cursor(0); + } + + vsp->scrolling += vsp->screen_rows - 1; + if (vsp->scrolling > vsp->scr_offset) { + vsp->scrolling = vsp->scr_offset; + } + + bcopy(vsp->Scrollback + ((vsp->scr_offset - + vsp->scrolling) * vsp->maxcol), vsp->Crtat, + vsp->screen_rows * vsp->maxcol * CHR); + } + } + else /* positive z */ + { + if (IS_SEL_EXISTS(vsp)) { + remove_selection(); + vsp->mouse_flags &= ~SEL_EXISTS; + } + if (vsp->scrolling > 0) { + vsp->scrolling -= vsp->screen_rows - 1; + if (vsp->scrolling < 0) + vsp->scrolling = 0; + + if (vsp->scrolling <= vsp->row) { + vsp->scrolling = 0; + scrollback_restore_screen(); + } + else { + if (vsp->scrolling + 2 < vsp->screen_rows) + fillw(user_attr | ' ', + (caddr_t)vsp->Crtat, + vsp->screen_rows * vsp->maxcol); + + bcopy(vsp->Scrollback + ((vsp->scr_offset - + vsp->scrolling) * vsp->maxcol), + vsp->Crtat, (vsp->scrolling + 2 < + vsp->screen_rows ? vsp->scrolling + 2 : + vsp->screen_rows) * vsp->maxcol * CHR); + } + } + if (vsp->scrolling == 0) { + if (vsp->cursor_on) + sw_cursor(1); + } + } +} /* ------------------------------- EOF -------------------------------------*/ diff --git a/sys/arch/i386/isa/pcvt/pcvt_mouse.c b/sys/arch/i386/isa/pcvt/pcvt_mouse.c new file mode 100644 index 00000000000..26e355c61a6 --- /dev/null +++ b/sys/arch/i386/isa/pcvt/pcvt_mouse.c @@ -0,0 +1,723 @@ +/* $OpenBSD: pcvt_mouse.c,v 1.1 2000/09/01 05:46:02 aaron Exp $ */ + +/* + * Copyright (c) 2000 Jean-Baptiste Marchand, Julien Montagne and Jerome Verdon + * + * All rights reserved. + * + * This code is for mouse console support under the pcvt 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. + * + * + */ + +#include "pcvt_hdr.h" + +void mouse_moverel(char dx, char dy); + +void inverse_char(unsigned short c); +void inverse_region(unsigned short start, unsigned short end); +void order_region(void); + +unsigned char skip_spc_right(char); +unsigned char skip_spc_left(void); +unsigned char skip_char_right(void); +unsigned char skip_char_left(void); + +void mouse_copy_start(void); +void mouse_copy_end(void); +void mouse_copy_word(void); +void mouse_copy_line(void); +void mouse_copy_extend(void); +void remove_selection(void); +void mouse_copy_selection(void); +void mouse_paste(void); +uid_t current_uid(void); + +void mouse_zaxis(int z); +void mouse_button(int button, int clicks); + +#define NO_BORDER 0 +#define BORDER 1 + +#define MAXCOL (vsp->maxcol - 1) +#define MAXROW (vsp->screen_rows - 1) + +#define XY_TO_X(col,row) (((row) * (vsp->maxcol)) + (col)) +#define XABS_TO_XREL(col) (((col) - vsp->Crtat) % vsp->maxcol) + +#define IS_ALPHANUM(pos) ((*(vsp->Crtat + (pos)) & 0x00ff) != ' ') +#define IS_SPACE(c) ((c) == ' ') + +int +mouse_ioctl(Dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) +{ + int device = minor(dev); + mouse_info_t mouse_infos = *(mouse_info_t *) data; + unsigned char c; + video_state *cs; + + if (device == PCVTCTL_MINOR && cmd == PCVT_MOUSECTL) { + switch (mouse_infos.operation) { + case MOUSE_INIT: + for (c = 0; c < PCVT_NSCREENS; c++) { + cs = &vs[c]; + cs->mouse = (cs->maxcol * + cs->screen_rows) / 2; + cs->mouse_flags = 0; + } + Paste_avail = 0; + break; + + case MOUSE_HIDE: + remove_selection(); + mouse_hide(); + break; + + case MOUSE_MOTION_EVENT : + mouse_moverel(mouse_infos.u.data.x, + mouse_infos.u.data.y); + if (mouse_infos.u.data.z) + mouse_zaxis(mouse_infos.u.data.z); + break; + + case MOUSE_BUTTON_EVENT : + mouse_button(mouse_infos.u.event.id, + mouse_infos.u.event.value); + break; + + default: + return 0; + } + return 0; + } + return (-1); /* continue treatment in pcioctl */ +} + +void +mouse_hide(void) +{ + if (IS_MOUSE_VISIBLE(vsp)) { + inverse_char(vsp->mouse); + vsp->mouse_flags &= ~MOUSE_VISIBLE; + } +} + +/* + * function to move the cursor to a relative new position + */ + +void +mouse_moverel(char dx, char dy) +{ + unsigned short old_mouse = vsp->mouse; + unsigned char mouse_col = (vsp->mouse % vsp->maxcol); + unsigned char mouse_row = (vsp->mouse / vsp->maxcol); + + if (scrnsv_active) /* if the screen saver is active */ + pcvt_scrnsv_reset(); /* unblank NOW ! */ + + /* 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; + vsp->mouse = XY_TO_X(mouse_col, mouse_row); + + /* if we have moved */ + if (old_mouse != vsp->mouse) { + /* hide the previous cursor, if not in a selection */ + if (IS_MOUSE_VISIBLE(vsp) && (!IS_SEL_IN_PROGRESS(vsp))) + inverse_char(old_mouse); + + if (IS_SEL_IN_PROGRESS(vsp)) { + /* selection in progress */ + mouse_copy_extend(); + } + else { + inverse_char(vsp->mouse); + vsp->mouse_flags |= MOUSE_VISIBLE; + } + } +} + +/* + * function to video inverse a character of the display + */ + +void +inverse_char(unsigned short pos) +{ + u_short *current_char = vsp->Crtat + pos; + u_short inverse = *current_char; + + if ((inverse >> 8) == 0) + inverse = (FG_LIGHTGREY << 8); + + inverse = (((inverse >> 8) & 0x88) | ((((inverse >> 8) >> 4) | + ((inverse >> 8) << 4)) & 0x77)) << 8; + + *current_char = inverse | ((*current_char) & 0x00ff); +} + +/* + * Function to order extremum of the selection region + */ + +void +order_region(void) +{ + unsigned short max_pos; + + if (vsp->cpy_start > vsp->cpy_end) { + max_pos = vsp->cpy_start; + vsp->cpy_start = vsp->cpy_end; + vsp->cpy_end = max_pos; + } +} + +/* + * Function to video inverse a region of the display + * start must be inferior to end + */ + +void +inverse_region(unsigned short start, unsigned short end) +{ + unsigned short current_pos; + unsigned char c = 0; + + current_pos = start; + while (current_pos <= end) { + inverse_char(current_pos++); + c++; + } +} + +/* + * Function which returns 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; + unsigned short *limit; + unsigned char mouse_col = (vsp->mouse % vsp->maxcol); + unsigned char res = 0; + + current = vsp->Crtat + vsp->cpy_end; + limit = current + (vsp->maxcol - mouse_col - 1); + while (((*current & 0x00ff) == ' ') && (current <= limit)) { + current++; + res++; + } + if (border == BORDER) { + if (current > limit) + return (res - 1); + else + return (0); + } + else + return (res - 1); +} + +/* + * Function which returns 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) +{ + unsigned short *current; + unsigned short *limit; + unsigned char mouse_col = (vsp->mouse % vsp->maxcol); + unsigned char res = 0; + + current = vsp->Crtat + vsp->cpy_start; + limit = current - mouse_col; + while (((*current & 0x00ff) == ' ') && (current >= limit)) { + current--; + res++; + } + + if (res) + res--; + return (res); +} + +/* + * Function which find the first blank beginning after the current cursor + * position + */ + +unsigned char +skip_char_right(void) +{ + unsigned short *current; + unsigned short *limit; + unsigned char mouse_col = (vsp->mouse % vsp->maxcol); + unsigned char res = 0; + + current = vsp->Crtat + vsp->cpy_end; + limit = current + (vsp->maxcol - mouse_col - 1); + while (((*current & 0x00ff) != ' ') && (current <= limit)) { + current++; + res++; + } + + if (res) + res--; + return (res); +} + +/* + * Function which find the first non-blank character before the cursor position + */ + +unsigned char +skip_char_left(void) +{ + unsigned short *current; + unsigned short *limit; + unsigned char mouse_col = (vsp->mouse % vsp->maxcol); + unsigned char res = 0; + + current = vsp->Crtat + vsp->cpy_start; + limit = current - mouse_col; + while (((*current & 0x00ff) != ' ') && (current >= limit)) { + current--; + res++; + } + + if (res) + res--; + return (res); +} + +/* + * Function to handle beginning of a copy operation + */ + +void +mouse_copy_start(void) +{ +#if 0 + unsigned char right; + unsigned char left; +#endif + + /* if no selection, then that's the first one */ + if (!Paste_avail) + Paste_avail = 1; + + /* remove the previous selection */ + if (IS_SEL_EXISTS(vsp)) { + remove_selection(); + } + + /* initial show of the cursor */ + if (!IS_MOUSE_VISIBLE(vsp)) + inverse_char(vsp->mouse); + + vsp->cpy_start = vsp->mouse; + vsp->cpy_end = vsp->mouse; + +#if 0 + /* if there is a blank region, we select all the region */ + if ((right = skip_spc_right(BORDER)) > 0) { + left = skip_spc_left(); + vsp->cpy_start -= left; + vsp->cpy_end += right; + if (vsp->cpy_start % vsp->maxcol) { + inverse_region(vsp->cpy_start, vsp->cpy_end); + inverse_char(vsp->mouse); /* reverse back the cursor */ + } + else { + /* we select only one character on a full blank line */ + vsp->cpy_start = vsp->mouse; + vsp->cpy_end = vsp->mouse; + } + } +#endif + + /* for correct action in remove_selection() */ + vsp->cpy_orig = vsp->cpy_start; + + vsp->mouse_flags |= SEL_IN_PROGRESS; + vsp->mouse_flags |= SEL_EXISTS; + + /* mouse cursor hidden in the selection */ + vsp->mouse_flags &= ~MOUSE_VISIBLE; +} + +/* + * Function to handle copy of the word under the cursor + */ + +void +mouse_copy_word() +{ + unsigned char right; + unsigned char left; + + if (IS_SEL_EXISTS(vsp)) + remove_selection(); + + if (IS_SEL_IN_PROGRESS(vsp)) + vsp->mouse_flags &= ~SEL_IN_PROGRESS; + + if (IS_MOUSE_VISIBLE(vsp)) + inverse_char(vsp->mouse); + + vsp->cpy_start = vsp->mouse; + vsp->cpy_end = vsp->mouse; + + if (IS_ALPHANUM(vsp->mouse)) { + right = skip_char_right(); + left = skip_char_left(); + } + else { + right = skip_spc_right(NO_BORDER); + left = skip_spc_left(); + } + + vsp->cpy_start -= left; + vsp->cpy_end += right; + vsp->cpy_orig = vsp->cpy_start; + inverse_region(vsp->cpy_start, vsp->cpy_end); + vsp->mouse_flags |= SEL_EXISTS; + + /* mouse cursor hidden in the selection */ + vsp->mouse_flags &= ~MOUSE_VISIBLE; +} + +/* + * Function to handle copy of the current line + */ + +void +mouse_copy_line(void) +{ + unsigned char row = vsp->mouse / vsp->maxcol; + + if (IS_SEL_EXISTS(vsp)) + remove_selection(); + + if (IS_SEL_IN_PROGRESS(vsp)) + vsp->mouse_flags &= ~(SEL_IN_PROGRESS); + + if (IS_MOUSE_VISIBLE(vsp)) + inverse_char(vsp->mouse); + + vsp->cpy_start = row * vsp->maxcol; + vsp->cpy_end = vsp->cpy_start + MAXCOL; + vsp->cpy_orig = vsp->cpy_start; + inverse_region(vsp->cpy_start, vsp->cpy_end); + + vsp->mouse_flags |= SEL_EXISTS; + vsp->mouse_flags &= ~MOUSE_VISIBLE; +} + +/* + * Function to handle the end of a copy operation + */ + +void +mouse_copy_end(void) +{ + vsp->mouse_flags &= ~(SEL_IN_PROGRESS); +} + +/* + * Function to extend a previously selected region + */ + +void +mouse_copy_extend() +{ + if (IS_SEL_EXISTS(vsp)) { + if (vsp->mouse < vsp->cpy_start) { + /* we are over the initial selection position */ + + /* reverse the old selection region */ + if (IS_SEL_EXISTS(vsp)) + remove_selection(); + + /* new delimiters for the selection zone */ + vsp->cpy_start = vsp->mouse; + vsp->cpy_end = vsp->cpy_orig - 1; + inverse_char(vsp->cpy_end); + } + if (vsp->cpy_start < vsp->cpy_orig && vsp->mouse >= vsp->cpy_orig) + { + /* we go back behind the initial selection + position */ + + /* reverse the old selection region */ + if (IS_SEL_EXISTS(vsp)) + remove_selection(); + + vsp->cpy_start = vsp->cpy_orig; + vsp->cpy_end = vsp->cpy_orig; + inverse_char(vsp->cpy_start); + } + + if (vsp->mouse < vsp->cpy_end) { + /* reducing selection */ + if (vsp->mouse >= vsp->cpy_orig) + inverse_region(vsp->mouse + 1, vsp->cpy_end); + else + inverse_region(vsp->mouse, vsp->cpy_end - 1); + } + else { + /* extending selection */ + if (vsp->mouse >= vsp->cpy_orig) + inverse_region(vsp->cpy_end + 1, vsp->mouse); + else + inverse_region(vsp->cpy_end, vsp->mouse - 1); + } + vsp->cpy_end = vsp->mouse; + order_region(); + } + else { + /* no selection yet! */ + sysbeep(PCVT_SYSBEEPF / 1500, hz / 4); + } +} + +/* + * Function to remove a previously selected region + */ + +void +remove_selection() +{ + if (vsp->cpy_start < vsp->cpy_orig) + /* backward selection */ + inverse_region(vsp->cpy_end, vsp->cpy_orig - 1); + else + /* forward selection */ + inverse_region(vsp->cpy_start, vsp->cpy_end); +} + +/* + * Function to get the uid of the user behind the *shell* on the current tty + * We handle su and sudo cases... + */ + +uid_t +current_uid(void) +{ + pid_t pg; /* process group id */ + struct proc *owner_proc; + + pg = vsp->vs_tty->t_pgrp->pg_id; + owner_proc = pfind(pg); + if (!owner_proc) { + Paste_avail = 0; /* this selection will never be available + because the process doesn't exist... */ + return (0); /* the uid of root, just to be sure */ + } + + /* + * We use the real user id and not the *effective* one, as a foreground + * setuid process could permit to paste selection of another user + */ + + return (owner_proc->p_cred->p_ruid); +} + +/* + * Function to 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 = ((vsp->maxcol + 1) * vsp->screen_rows); + unsigned short *sel_cur; + unsigned short *sel_end; + + if (vsp->cpy_start < vsp->cpy_orig) { + /* backward selection */ + sel_cur = vsp->Crtat + vsp->cpy_end; + sel_end = vsp->Crtat + vsp->cpy_orig - 1; + } + else { + /* forward selection */ + sel_cur = vsp->Crtat + vsp->cpy_start; + sel_end = vsp->Crtat + vsp->cpy_end; + } + while (sel_cur <= sel_end && current < buf_end - 1) { + Copybuffer[current] = ((*sel_cur) & 0x00ff); + + if (!IS_SPACE(Copybuffer[current])) + blank = current + 1; /* first blank after non-blank */ + current++; + + if (XABS_TO_XREL(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'; + +#if 0 + /* + examine the last line of selection to see if it finishes with blank. + In that case, we put a carriage return after the last non-blank + character in the buffer + */ + sel_cur = sel_end; + while (IS_SPACE(*sel_cur & 0x00ff) && XABS_TO_XREL(sel_cur) < MAXCOL) { + sel_cur--; + current--; + } + if (sel_cur != sel_end) { + Copybuffer[current++] = '\r'; + Copybuffer[current] = '\0'; + } +#endif + Copyowner = current_uid(); +} +/* + * Function to paste the current selection + */ + +void +mouse_paste(void) +{ + unsigned short len; + char *current = Copybuffer; + uid_t cur_uid; + + cur_uid = current_uid(); + if (Paste_avail && ((cur_uid == Copyowner) || !cur_uid)) { + /* either the owner of the selection or root */ + len = strlen(Copybuffer); + for (; len > 0; len--) { + (*linesw[vsp->vs_tty->t_line].l_rint) + (*current++, vsp->vs_tty); + } + } + else + sysbeep(PCVT_SYSBEEPF / 1500, hz / 4); +} + +/* + * Function to handle button clicks + */ + +void +mouse_button(int button, int clicks) +{ + if (scrnsv_active) /* if the screen saver is active */ + pcvt_scrnsv_reset(); /* unblank NOW ! */ + + 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(); + mouse_copy_selection(); + break; + } + break; + + default: + break; + } +} + +/* + * Function to handle the z axis + * The z axis (roller or wheel) is mapped by default to scrollback + */ + +void +mouse_zaxis(int z) +{ + scrollback_mouse(z); +} diff --git a/sys/arch/i386/isa/pcvt/pcvt_mouse.h b/sys/arch/i386/isa/pcvt/pcvt_mouse.h new file mode 100644 index 00000000000..985f2f512e5 --- /dev/null +++ b/sys/arch/i386/isa/pcvt/pcvt_mouse.h @@ -0,0 +1,96 @@ +/* $OpenBSD: pcvt_mouse.h,v 1.1 2000/09/01 05:46:02 aaron Exp $ */ + +/* + * Copyright (c) 2000 Jean-Baptiste Marchand, Julien Montagne and Jerome Verdon + * + * All rights reserved. + * + * This code is for mouse console support under the pcvt 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. + * + * + */ + +#define PCVTCTL_MINOR 255 + +/* Mouse buttons */ + +#define MOUSE_BUTTON1DOWN 0x0001 /* left */ +#define MOUSE_BUTTON2DOWN 0x0002 /* middle */ +#define MOUSE_BUTTON3DOWN 0x0004 /* right */ +#define MOUSE_BUTTON4DOWN 0x0008 +#define MOUSE_BUTTON5DOWN 0x0010 +#define MOUSE_BUTTON6DOWN 0x0020 +#define MOUSE_BUTTON7DOWN 0x0040 +#define MOUSE_BUTTON8DOWN 0x0080 +#define MOUSE_MAXBUTTON 31 +#define MOUSE_STDBUTTONS 0x0007 /* buttons 1-3 */ +#define MOUSE_EXTBUTTONS 0x7ffffff8 /* the others (28 of them!) */ +#define MOUSE_BUTTONS (MOUSE_STDBUTTONS | MOUSE_EXTBUTTONS) + +#define MOUSE_COPY_BUTTON MOUSE_BUTTON1DOWN +#define MOUSE_PASTE_BUTTON MOUSE_BUTTON2DOWN +#define MOUSE_EXTEND_BUTTON MOUSE_BUTTON3DOWN + +/* Motion event */ + +struct mouse_data { + int x; + int y; + int z; + int buttons; +}; + +/* Click event */ + +struct mouse_event { + int id; /* button clicked */ + int value; /* number of click */ +}; + +/* Mouse_info : either motion or click event */ + +typedef struct mouse_info { + int operation; + /* + * The following operations are used to indicate the action + * when receiving a PCVT_MOUSECTL ioctl + */ + +#define MOUSE_INIT (1 << 0) /* Init of the cursor */ +#define MOUSE_HIDE (1 << 1) /* Hide the cursor */ +#define MOUSE_MOTION_EVENT (1 << 2) /* Motion event */ +#define MOUSE_BUTTON_EVENT (1 << 3) /* Button event */ + + union { + struct mouse_data data; + struct mouse_event event; + }u; +} mouse_info_t; + diff --git a/sys/arch/i386/isa/pcvt/pcvt_out.c b/sys/arch/i386/isa/pcvt/pcvt_out.c index acf176f3dce..50ed63d20a8 100644 --- a/sys/arch/i386/isa/pcvt/pcvt_out.c +++ b/sys/arch/i386/isa/pcvt/pcvt_out.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pcvt_out.c,v 1.25 2000/07/05 03:10:34 aaron Exp $ */ +/* $OpenBSD: pcvt_out.c,v 1.26 2000/09/01 05:46:02 aaron Exp $ */ /* * Copyright (c) 1992, 1995 Hellmuth Michaelis and Joerg Wunsch. @@ -153,7 +153,6 @@ sput (u_char *s, U_char kernel, int len, int page) else reset_screen_saver = 1; /* do it asynchronously */ #endif /* PCVT_SCREENSAVER */ - } attrib = kernel ? kern_attr : svsp->c_attr; @@ -1270,6 +1269,18 @@ vt_coldmalloc(void) printf("pcvt: scrollback memory malloc failed\n"); } + /* + * Copy buffer must be 1 character wider than the screen because we + * need to write '\r' characters in the buffer (carriage return + */ + + if ((Copybuffer = (char *)malloc((vs[0].maxcol + 1) * + vs[0].screen_rows, M_DEVBUF, + M_WAITOK)) == NULL) + { + printf("pcvt: copy memory malloc failed\n"); + } + for(nscr = 0; nscr < PCVT_NSCREENS; nscr++) { if((vs[nscr].Memory = |