148104Syokota/*- 248104Syokota * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 348104Syokota * All rights reserved. 448104Syokota * 548104Syokota * Redistribution and use in source and binary forms, with or without 648104Syokota * modification, are permitted provided that the following conditions 748104Syokota * are met: 848104Syokota * 1. Redistributions of source code must retain the above copyright 948104Syokota * notice, this list of conditions and the following disclaimer as 1048104Syokota * the first lines of this file unmodified. 1148104Syokota * 2. Redistributions in binary form must reproduce the above copyright 1248104Syokota * notice, this list of conditions and the following disclaimer in the 1348104Syokota * documentation and/or other materials provided with the distribution. 1448104Syokota * 1548104Syokota * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 1648104Syokota * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1748104Syokota * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1848104Syokota * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 1948104Syokota * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2048104Syokota * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2148104Syokota * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2248104Syokota * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2348104Syokota * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2448104Syokota * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2548104Syokota */ 2648104Syokota 27119420Sobrien#include <sys/cdefs.h> 28119420Sobrien__FBSDID("$FreeBSD$"); 29119420Sobrien 3048104Syokota#include "opt_syscons.h" 3148104Syokota 3248104Syokota#include <sys/param.h> 3348104Syokota#include <sys/systm.h> 3448104Syokota#include <sys/conf.h> 3576166Smarkm#include <sys/consio.h> 3676166Smarkm#include <sys/fbio.h> 37114216Skan#include <sys/limits.h> 3876166Smarkm#include <sys/lock.h> 3976166Smarkm#include <sys/malloc.h> 4076166Smarkm#include <sys/mouse.h> 4176166Smarkm#include <sys/mutex.h> 4248104Syokota#include <sys/proc.h> 4365690Smarkm#include <sys/random.h> 4476166Smarkm#include <sys/signalvar.h> 4548104Syokota#include <sys/tty.h> 4648104Syokota 4748104Syokota#include <dev/syscons/syscons.h> 4848104Syokota 4953011Syokota#ifdef SC_TWOBUTTON_MOUSE 5053011Syokota#define SC_MOUSE_PASTEBUTTON MOUSE_BUTTON3DOWN /* right button */ 5153011Syokota#define SC_MOUSE_EXTENDBUTTON MOUSE_BUTTON2DOWN /* not really used */ 5253011Syokota#else 5353011Syokota#define SC_MOUSE_PASTEBUTTON MOUSE_BUTTON2DOWN /* middle button */ 5453011Syokota#define SC_MOUSE_EXTENDBUTTON MOUSE_BUTTON3DOWN /* right button */ 5553011Syokota#endif /* SC_TWOBUTTON_MOUSE */ 5653011Syokota 5748104Syokota#define SC_WAKEUP_DELTA 20 5848104Syokota 5948104Syokota/* for backward compatibility */ 6048104Syokota#define OLD_CONS_MOUSECTL _IOWR('c', 10, old_mouse_info_t) 6148104Syokota 6248104Syokotatypedef struct old_mouse_data { 6348104Syokota int x; 6448104Syokota int y; 6548104Syokota int buttons; 6648104Syokota} old_mouse_data_t; 6748104Syokota 6848104Syokotatypedef struct old_mouse_info { 6948104Syokota int operation; 7048104Syokota union { 7148104Syokota struct old_mouse_data data; 7248104Syokota struct mouse_mode mode; 7348104Syokota } u; 7448104Syokota} old_mouse_info_t; 7548104Syokota 7656043Syokota#ifndef SC_NO_SYSMOUSE 7756043Syokota 7848104Syokota/* local variables */ 79115595Sjmallett#ifndef SC_NO_CUTPASTE 8048104Syokotastatic int cut_buffer_size; 8148104Syokotastatic u_char *cut_buffer; 82115595Sjmallett#endif 8348104Syokota 8448104Syokota/* local functions */ 8548104Syokotastatic void set_mouse_pos(scr_stat *scp); 8648104Syokota#ifndef SC_NO_CUTPASTE 8748104Syokotastatic int skip_spc_right(scr_stat *scp, int p); 8848104Syokotastatic int skip_spc_left(scr_stat *scp, int p); 8948104Syokotastatic void mouse_cut(scr_stat *scp); 9048104Syokotastatic void mouse_cut_start(scr_stat *scp); 9148104Syokotastatic void mouse_cut_end(scr_stat *scp); 9248104Syokotastatic void mouse_cut_word(scr_stat *scp); 9348104Syokotastatic void mouse_cut_line(scr_stat *scp); 9448104Syokotastatic void mouse_cut_extend(scr_stat *scp); 9548104Syokota#endif /* SC_NO_CUTPASTE */ 9648104Syokota 9748104Syokota#ifndef SC_NO_CUTPASTE 9848104Syokota/* allocate a cut buffer */ 9948104Syokotavoid 10048104Syokotasc_alloc_cut_buffer(scr_stat *scp, int wait) 10148104Syokota{ 10248104Syokota u_char *p; 10348104Syokota 10448104Syokota if ((cut_buffer == NULL) 10548104Syokota || (cut_buffer_size < scp->xsize * scp->ysize + 1)) { 10648104Syokota p = cut_buffer; 10748104Syokota cut_buffer = NULL; 10848104Syokota if (p != NULL) 10948104Syokota free(p, M_DEVBUF); 11048104Syokota cut_buffer_size = scp->xsize * scp->ysize + 1; 11148104Syokota p = (u_char *)malloc(cut_buffer_size, 112111119Simp M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT); 11348104Syokota if (p != NULL) 11448104Syokota p[0] = '\0'; 11548104Syokota cut_buffer = p; 11648104Syokota } 11748104Syokota} 11848104Syokota#endif /* SC_NO_CUTPASTE */ 11948104Syokota 120197539Sedstatic void 121197539Sedsc_mouse_input_button(scr_stat *scp, int button) 122197539Sed{ 123197539Sed char mouseb[6] = "\x1B[M"; 124197539Sed 125197539Sed mouseb[3] = ' ' + button; 126197539Sed mouseb[4] = '!' + scp->mouse_pos % scp->xsize; 127197539Sed mouseb[5] = '!' + scp->mouse_pos / scp->xsize; 128197539Sed sc_respond(scp, mouseb, sizeof mouseb, 1); 129197539Sed} 130197539Sed 131197539Sedstatic void 132197539Sedsc_mouse_input(scr_stat *scp, mouse_info_t *mouse) 133197539Sed{ 134197539Sed 135197539Sed switch (mouse->operation) { 136197539Sed case MOUSE_BUTTON_EVENT: 137197539Sed if (mouse->u.event.value > 0) { 138197539Sed /* Mouse button pressed. */ 139197539Sed if (mouse->u.event.id & MOUSE_BUTTON1DOWN) 140197539Sed sc_mouse_input_button(scp, 0); 141197539Sed if (mouse->u.event.id & MOUSE_BUTTON2DOWN) 142197539Sed sc_mouse_input_button(scp, 1); 143197539Sed if (mouse->u.event.id & MOUSE_BUTTON3DOWN) 144197539Sed sc_mouse_input_button(scp, 2); 145197539Sed } else { 146197539Sed /* Mouse button released. */ 147197539Sed sc_mouse_input_button(scp, 3); 148197539Sed } 149197539Sed break; 150197539Sed case MOUSE_MOTION_EVENT: 151197539Sed if (mouse->u.data.z < 0) { 152197539Sed /* Scroll up. */ 153197539Sed sc_mouse_input_button(scp, 64); 154197539Sed } else if (mouse->u.data.z > 0) { 155197539Sed /* Scroll down. */ 156197539Sed sc_mouse_input_button(scp, 65); 157197539Sed } 158197539Sed break; 159197539Sed } 160197539Sed} 161197539Sed 16248104Syokota/* move mouse */ 16348104Syokotavoid 16448104Syokotasc_mouse_move(scr_stat *scp, int x, int y) 16548104Syokota{ 16648104Syokota int s; 16748104Syokota 16848104Syokota s = spltty(); 16958872Syokota scp->mouse_xpos = scp->mouse_oldxpos = x; 17058872Syokota scp->mouse_ypos = scp->mouse_oldypos = y; 171149640Srodrigc if (scp->font_size <= 0 || scp->font_width <= 0) 17256528Syokota scp->mouse_pos = scp->mouse_oldpos = 0; 17356528Syokota else 17456528Syokota scp->mouse_pos = scp->mouse_oldpos = 175119388Sjake (y/scp->font_size - scp->yoff)*scp->xsize + x/scp->font_width - 176119388Sjake scp->xoff; 17758872Syokota scp->status |= MOUSE_MOVED; 17848104Syokota splx(s); 17948104Syokota} 18048104Syokota 18148104Syokota/* adjust mouse position */ 18248104Syokotastatic void 18348104Syokotaset_mouse_pos(scr_stat *scp) 18448104Syokota{ 185119388Sjake if (scp->mouse_xpos < scp->xoff*scp->font_width) 186119388Sjake scp->mouse_xpos = scp->xoff*scp->font_width; 18748104Syokota if (scp->mouse_ypos < scp->yoff*scp->font_size) 18848104Syokota scp->mouse_ypos = scp->yoff*scp->font_size; 18948104Syokota if (ISGRAPHSC(scp)) { 19048104Syokota if (scp->mouse_xpos > scp->xpixel-1) 19148104Syokota scp->mouse_xpos = scp->xpixel-1; 19248104Syokota if (scp->mouse_ypos > scp->ypixel-1) 19348104Syokota scp->mouse_ypos = scp->ypixel-1; 19448104Syokota return; 19548104Syokota } else { 196119388Sjake if (scp->mouse_xpos > (scp->xsize + scp->xoff)*scp->font_width - 1) 197119388Sjake scp->mouse_xpos = (scp->xsize + scp->xoff)*scp->font_width - 1; 19848104Syokota if (scp->mouse_ypos > (scp->ysize + scp->yoff)*scp->font_size - 1) 19948104Syokota scp->mouse_ypos = (scp->ysize + scp->yoff)*scp->font_size - 1; 20048104Syokota } 20148104Syokota 202149855Srodrigc if ((scp->mouse_xpos != scp->mouse_oldxpos || scp->mouse_ypos != scp->mouse_oldypos) 203149855Srodrigc && (scp->font_size != 0 && scp->font_width != 0)) { 20448104Syokota scp->status |= MOUSE_MOVED; 20548104Syokota scp->mouse_pos = 20648104Syokota (scp->mouse_ypos/scp->font_size - scp->yoff)*scp->xsize 207119388Sjake + scp->mouse_xpos/scp->font_width - scp->xoff; 20848104Syokota#ifndef SC_NO_CUTPASTE 20948104Syokota if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING)) 21048104Syokota mouse_cut(scp); 21148104Syokota#endif 21248104Syokota } 21348104Syokota} 21448104Syokota 21548104Syokota#ifndef SC_NO_CUTPASTE 21648104Syokota 21748104Syokotavoid 21848104Syokotasc_draw_mouse_image(scr_stat *scp) 21948104Syokota{ 22048104Syokota if (ISGRAPHSC(scp)) 22148104Syokota return; 22248104Syokota 223162285Sscottl SC_VIDEO_LOCK(scp->sc); 22448104Syokota (*scp->rndr->draw_mouse)(scp, scp->mouse_xpos, scp->mouse_ypos, TRUE); 22548104Syokota scp->mouse_oldpos = scp->mouse_pos; 22658872Syokota scp->mouse_oldxpos = scp->mouse_xpos; 22758872Syokota scp->mouse_oldypos = scp->mouse_ypos; 22858872Syokota scp->status |= MOUSE_VISIBLE; 229162285Sscottl SC_VIDEO_UNLOCK(scp->sc); 23048104Syokota} 23148104Syokota 23248104Syokotavoid 23348104Syokotasc_remove_mouse_image(scr_stat *scp) 23448104Syokota{ 23548104Syokota int size; 23648104Syokota int i; 23748104Syokota 23848104Syokota if (ISGRAPHSC(scp)) 23948104Syokota return; 24048104Syokota 241162285Sscottl SC_VIDEO_LOCK(scp->sc); 24248104Syokota (*scp->rndr->draw_mouse)(scp, 243119388Sjake (scp->mouse_oldpos%scp->xsize + scp->xoff) 244119388Sjake * scp->font_width, 24548104Syokota (scp->mouse_oldpos/scp->xsize + scp->yoff) 24648104Syokota * scp->font_size, 24748104Syokota FALSE); 24848104Syokota size = scp->xsize*scp->ysize; 24948104Syokota i = scp->mouse_oldpos; 25048104Syokota mark_for_update(scp, i); 25148104Syokota mark_for_update(scp, i); 25248104Syokota#ifndef PC98 25348104Syokota if (i + scp->xsize + 1 < size) { 25448104Syokota mark_for_update(scp, i + scp->xsize + 1); 25548104Syokota } else if (i + scp->xsize < size) { 25648104Syokota mark_for_update(scp, i + scp->xsize); 25748104Syokota } else if (i + 1 < size) { 25848104Syokota mark_for_update(scp, i + 1); 25948104Syokota } 26048104Syokota#endif /* PC98 */ 26158872Syokota scp->status &= ~MOUSE_VISIBLE; 262162285Sscottl SC_VIDEO_UNLOCK(scp->sc); 26348104Syokota} 26448104Syokota 26548104Syokotaint 26648104Syokotasc_inside_cutmark(scr_stat *scp, int pos) 26748104Syokota{ 26848104Syokota int start; 26948104Syokota int end; 27048104Syokota 27148104Syokota if (scp->mouse_cut_end < 0) 27248104Syokota return FALSE; 27348104Syokota if (scp->mouse_cut_start <= scp->mouse_cut_end) { 27448104Syokota start = scp->mouse_cut_start; 27548104Syokota end = scp->mouse_cut_end; 27648104Syokota } else { 27748104Syokota start = scp->mouse_cut_end; 27848104Syokota end = scp->mouse_cut_start - 1; 27948104Syokota } 28048104Syokota return ((start <= pos) && (pos <= end)); 28148104Syokota} 28248104Syokota 28348104Syokotavoid 28448104Syokotasc_remove_cutmarking(scr_stat *scp) 28548104Syokota{ 28648104Syokota int s; 28748104Syokota 28848104Syokota s = spltty(); 28948104Syokota if (scp->mouse_cut_end >= 0) { 29048104Syokota mark_for_update(scp, scp->mouse_cut_start); 29148104Syokota mark_for_update(scp, scp->mouse_cut_end); 29248104Syokota } 29348104Syokota scp->mouse_cut_start = scp->xsize*scp->ysize; 29448104Syokota scp->mouse_cut_end = -1; 29548104Syokota splx(s); 29648104Syokota scp->status &= ~MOUSE_CUTTING; 29748104Syokota} 29848104Syokota 29948104Syokotavoid 30048104Syokotasc_remove_all_cutmarkings(sc_softc_t *sc) 30148104Syokota{ 30251404Syokota scr_stat *scp; 30348104Syokota int i; 30448104Syokota 30548104Syokota /* delete cut markings in all vtys */ 30648104Syokota for (i = 0; i < sc->vtys; ++i) { 30751404Syokota scp = SC_STAT(sc->dev[i]); 30851404Syokota if (scp == NULL) 30948104Syokota continue; 31051404Syokota sc_remove_cutmarking(scp); 31148104Syokota } 31248104Syokota} 31348104Syokota 31448104Syokotavoid 31548104Syokotasc_remove_all_mouse(sc_softc_t *sc) 31648104Syokota{ 31751404Syokota scr_stat *scp; 31848104Syokota int i; 31948104Syokota 32048104Syokota for (i = 0; i < sc->vtys; ++i) { 32151404Syokota scp = SC_STAT(sc->dev[i]); 32251404Syokota if (scp == NULL) 32348104Syokota continue; 32451404Syokota if (scp->status & MOUSE_VISIBLE) { 32551404Syokota scp->status &= ~MOUSE_VISIBLE; 32651404Syokota mark_all(scp); 32748104Syokota } 32848104Syokota } 32948104Syokota} 33048104Syokota 33152813Sarchie#define IS_SPACE_CHAR(c) (((c) & 0xff) == ' ') 33248104Syokota 33383791Ssobomax#ifdef SC_CUT_SPACES2TABS 33483791Ssobomax#define IS_BLANK_CHAR(c) (((c) & 0xff) == ' ' || ((c) & 0xff) == '\t') 33583791Ssobomax#else 33683791Ssobomax#define IS_BLANK_CHAR(c) IS_SPACE_CHAR(c) 33783791Ssobomax#endif /* SC_CUT_SPACES2TABS */ 33883791Ssobomax 33983791Ssobomax#ifdef SC_CUT_SEPCHARS 34083791Ssobomax#define IS_SEP_CHAR(c) (index(SC_CUT_SEPCHARS, (c) & 0xff) != NULL) 34183791Ssobomax#else 34283791Ssobomax#define IS_SEP_CHAR(c) IS_SPACE_CHAR(c) 34383791Ssobomax#endif /* SC_CUT_SEPCHARS */ 34483791Ssobomax 34548104Syokota/* skip spaces to right */ 34648104Syokotastatic int 34748104Syokotaskip_spc_right(scr_stat *scp, int p) 34848104Syokota{ 34948104Syokota int c; 35048104Syokota int i; 35148104Syokota 35248104Syokota for (i = p % scp->xsize; i < scp->xsize; ++i) { 35348104Syokota c = sc_vtb_getc(&scp->vtb, p); 35452813Sarchie if (!IS_SPACE_CHAR(c)) 35548104Syokota break; 35648104Syokota ++p; 35748104Syokota } 35848104Syokota return i; 35948104Syokota} 36048104Syokota 36148104Syokota/* skip spaces to left */ 36248104Syokotastatic int 36348104Syokotaskip_spc_left(scr_stat *scp, int p) 36448104Syokota{ 36548104Syokota int c; 36648104Syokota int i; 36748104Syokota 36848104Syokota for (i = p-- % scp->xsize - 1; i >= 0; --i) { 36948104Syokota c = sc_vtb_getc(&scp->vtb, p); 37052813Sarchie if (!IS_SPACE_CHAR(c)) 37148104Syokota break; 37248104Syokota --p; 37348104Syokota } 37448104Syokota return i; 37548104Syokota} 37648104Syokota 37783791Ssobomaxstatic void 37883791Ssobomaxmouse_do_cut(scr_stat *scp, int from, int to) 37983791Ssobomax{ 38083791Ssobomax int blank; 38183791Ssobomax int i; 38283791Ssobomax int leadspaces; 38383791Ssobomax int p; 38483791Ssobomax int s; 38583791Ssobomax 38683791Ssobomax for (p = from, i = blank = leadspaces = 0; p <= to; ++p) { 38783791Ssobomax cut_buffer[i] = sc_vtb_getc(&scp->vtb, p); 38883791Ssobomax /* Be prepared that sc_vtb_getc() can return '\0' */ 38983791Ssobomax if (cut_buffer[i] == '\0') 39083791Ssobomax cut_buffer[i] = ' '; 39183791Ssobomax#ifdef SC_CUT_SPACES2TABS 39283791Ssobomax if (leadspaces != -1) { 39383791Ssobomax if (IS_SPACE_CHAR(cut_buffer[i])) { 39483791Ssobomax leadspaces++; 39583791Ssobomax /* Check that we are at tabstop position */ 39683791Ssobomax if ((p % scp->xsize) % 8 == 7) { 39783791Ssobomax i -= leadspaces - 1; 39883791Ssobomax cut_buffer[i] = '\t'; 39983791Ssobomax leadspaces = 0; 40083791Ssobomax } 40183791Ssobomax } else { 40283791Ssobomax leadspaces = -1; 40383791Ssobomax } 40483791Ssobomax } 40583791Ssobomax#endif /* SC_CUT_SPACES2TABS */ 40683791Ssobomax /* remember the position of the last non-space char */ 40783791Ssobomax if (!IS_BLANK_CHAR(cut_buffer[i])) 40883791Ssobomax blank = i + 1; /* the first space after the last non-space */ 40983791Ssobomax ++i; 41083791Ssobomax /* trim trailing blank when crossing lines */ 41183791Ssobomax if ((p % scp->xsize) == (scp->xsize - 1)) { 41283791Ssobomax cut_buffer[blank++] = '\r'; 41383791Ssobomax i = blank; 41483791Ssobomax leadspaces = 0; 41583791Ssobomax } 41683791Ssobomax } 41783791Ssobomax cut_buffer[i] = '\0'; 41883791Ssobomax 41983791Ssobomax /* remove the current marking */ 42083791Ssobomax s = spltty(); 42183791Ssobomax if (scp->mouse_cut_start <= scp->mouse_cut_end) { 42283791Ssobomax mark_for_update(scp, scp->mouse_cut_start); 42383791Ssobomax mark_for_update(scp, scp->mouse_cut_end); 42483791Ssobomax } else if (scp->mouse_cut_end >= 0) { 42583791Ssobomax mark_for_update(scp, scp->mouse_cut_end); 42683791Ssobomax mark_for_update(scp, scp->mouse_cut_start); 42783791Ssobomax } 42883791Ssobomax 42983791Ssobomax /* mark the new region */ 43083791Ssobomax scp->mouse_cut_start = from; 43183791Ssobomax scp->mouse_cut_end = to; 43283791Ssobomax mark_for_update(scp, from); 43383791Ssobomax mark_for_update(scp, to); 43483791Ssobomax splx(s); 43583791Ssobomax} 43683791Ssobomax 43748104Syokota/* copy marked region to the cut buffer */ 43848104Syokotastatic void 43948104Syokotamouse_cut(scr_stat *scp) 44048104Syokota{ 44148104Syokota int start; 44248104Syokota int end; 44348104Syokota int from; 44448104Syokota int to; 44548104Syokota int c; 44648104Syokota int p; 44748104Syokota int s; 44848104Syokota int i; 44948104Syokota 45048104Syokota start = scp->mouse_cut_start; 45148104Syokota end = scp->mouse_cut_end; 45248104Syokota if (scp->mouse_pos >= start) { 45348104Syokota from = start; 45448104Syokota to = end = scp->mouse_pos; 45548104Syokota } else { 45648104Syokota from = end = scp->mouse_pos; 45748104Syokota to = start - 1; 45848104Syokota } 45983791Ssobomax p = to; 46048104Syokota for (i = p % scp->xsize; i < scp->xsize; ++i) { 46148104Syokota c = sc_vtb_getc(&scp->vtb, p); 46252813Sarchie if (!IS_SPACE_CHAR(c)) 46348104Syokota break; 46448104Syokota ++p; 46548104Syokota } 46648104Syokota /* if there is nothing but blank chars, trim them, but mark towards eol */ 46783791Ssobomax if (i == scp->xsize) { 46848104Syokota if (end >= start) 46948104Syokota to = end = p - 1; 47048104Syokota else 47148104Syokota to = start = p; 47248104Syokota } 47383791Ssobomax mouse_do_cut(scp, from, to); 47448104Syokota s = spltty(); 47548104Syokota scp->mouse_cut_start = start; 47648104Syokota scp->mouse_cut_end = end; 47748104Syokota splx(s); 47848104Syokota} 47948104Syokota 48048104Syokota/* a mouse button is pressed, start cut operation */ 48148104Syokotastatic void 48283791Ssobomaxmouse_cut_start(scr_stat *scp) 48348104Syokota{ 48448104Syokota int i; 48548104Syokota int s; 48648104Syokota 48748104Syokota if (scp->status & MOUSE_VISIBLE) { 48848104Syokota sc_remove_all_cutmarkings(scp->sc); 489169983Sdelphij if ((scp->mouse_pos == scp->mouse_cut_start) && 490169983Sdelphij (scp->mouse_pos == scp->mouse_cut_end)) { 49148104Syokota cut_buffer[0] = '\0'; 49283791Ssobomax return; 49348104Syokota } else if (skip_spc_right(scp, scp->mouse_pos) >= scp->xsize) { 49448104Syokota /* if the pointer is on trailing blank chars, mark towards eol */ 49548104Syokota i = skip_spc_left(scp, scp->mouse_pos) + 1; 49648104Syokota s = spltty(); 49748104Syokota scp->mouse_cut_start = 49848104Syokota (scp->mouse_pos / scp->xsize) * scp->xsize + i; 49948104Syokota scp->mouse_cut_end = 50048104Syokota (scp->mouse_pos / scp->xsize + 1) * scp->xsize - 1; 50148104Syokota splx(s); 50248104Syokota cut_buffer[0] = '\r'; 50348104Syokota } else { 50448104Syokota s = spltty(); 50548104Syokota scp->mouse_cut_start = scp->mouse_pos; 50648104Syokota scp->mouse_cut_end = scp->mouse_cut_start; 50748104Syokota splx(s); 50848104Syokota cut_buffer[0] = sc_vtb_getc(&scp->vtb, scp->mouse_cut_start); 50948104Syokota } 51083791Ssobomax cut_buffer[1] = '\0'; 51183791Ssobomax scp->status |= MOUSE_CUTTING; 51248104Syokota mark_all(scp); /* this is probably overkill XXX */ 51348104Syokota } 51448104Syokota} 51548104Syokota 51648104Syokota/* end of cut operation */ 51748104Syokotastatic void 51848104Syokotamouse_cut_end(scr_stat *scp) 51948104Syokota{ 52048104Syokota if (scp->status & MOUSE_VISIBLE) 52148104Syokota scp->status &= ~MOUSE_CUTTING; 52248104Syokota} 52348104Syokota 52448104Syokota/* copy a word under the mouse pointer */ 52548104Syokotastatic void 52648104Syokotamouse_cut_word(scr_stat *scp) 52748104Syokota{ 52848104Syokota int start; 52948104Syokota int end; 53048104Syokota int sol; 53148104Syokota int eol; 53248104Syokota int c; 53348104Syokota int j; 53488926Ssobomax int len; 53548104Syokota 53648104Syokota /* 53748104Syokota * Because we don't have locale information in the kernel, 53848104Syokota * we only distinguish space char and non-space chars. Punctuation 53983791Ssobomax * chars, symbols and other regular chars are all treated alike 54083791Ssobomax * unless user specified SC_CUT_SEPCHARS in his kernel config file. 54148104Syokota */ 54248104Syokota if (scp->status & MOUSE_VISIBLE) { 54348104Syokota sol = (scp->mouse_pos / scp->xsize) * scp->xsize; 54448104Syokota eol = sol + scp->xsize; 54548104Syokota c = sc_vtb_getc(&scp->vtb, scp->mouse_pos); 54683791Ssobomax if (IS_SEP_CHAR(c)) { 54748104Syokota /* blank space */ 54848104Syokota for (j = scp->mouse_pos; j >= sol; --j) { 54948104Syokota c = sc_vtb_getc(&scp->vtb, j); 55083791Ssobomax if (!IS_SEP_CHAR(c)) 55148104Syokota break; 55248104Syokota } 55348104Syokota start = ++j; 55448104Syokota for (j = scp->mouse_pos; j < eol; ++j) { 55548104Syokota c = sc_vtb_getc(&scp->vtb, j); 55683791Ssobomax if (!IS_SEP_CHAR(c)) 55748104Syokota break; 55848104Syokota } 55948104Syokota end = j - 1; 56048104Syokota } else { 56148104Syokota /* non-space word */ 56248104Syokota for (j = scp->mouse_pos; j >= sol; --j) { 56348104Syokota c = sc_vtb_getc(&scp->vtb, j); 56483791Ssobomax if (IS_SEP_CHAR(c)) 56548104Syokota break; 56648104Syokota } 56748104Syokota start = ++j; 56848104Syokota for (j = scp->mouse_pos; j < eol; ++j) { 56948104Syokota c = sc_vtb_getc(&scp->vtb, j); 57083791Ssobomax if (IS_SEP_CHAR(c)) 57148104Syokota break; 57248104Syokota } 57348104Syokota end = j - 1; 57448104Syokota } 57548104Syokota 57648104Syokota /* copy the found word */ 57783791Ssobomax mouse_do_cut(scp, start, end); 57888926Ssobomax len = strlen(cut_buffer); 57988926Ssobomax if (cut_buffer[len - 1] == '\r') 58088926Ssobomax cut_buffer[len - 1] = '\0'; 58148104Syokota } 58248104Syokota} 58348104Syokota 58448104Syokota/* copy a line under the mouse pointer */ 58548104Syokotastatic void 58648104Syokotamouse_cut_line(scr_stat *scp) 58748104Syokota{ 58886894Ssobomax int len; 58983791Ssobomax int from; 59048104Syokota 59148104Syokota if (scp->status & MOUSE_VISIBLE) { 59283791Ssobomax from = (scp->mouse_pos / scp->xsize) * scp->xsize; 59383791Ssobomax mouse_do_cut(scp, from, from + scp->xsize - 1); 59486894Ssobomax len = strlen(cut_buffer); 59586894Ssobomax if (cut_buffer[len - 1] == '\r') 59686894Ssobomax cut_buffer[len - 1] = '\0'; 59748104Syokota scp->status |= MOUSE_CUTTING; 59848104Syokota } 59948104Syokota} 60048104Syokota 60148104Syokota/* extend the marked region to the mouse pointer position */ 60248104Syokotastatic void 60348104Syokotamouse_cut_extend(scr_stat *scp) 60448104Syokota{ 60548104Syokota int start; 60648104Syokota int end; 60748104Syokota int s; 60848104Syokota 60948104Syokota if ((scp->status & MOUSE_VISIBLE) && !(scp->status & MOUSE_CUTTING) 61048104Syokota && (scp->mouse_cut_end >= 0)) { 61148104Syokota if (scp->mouse_cut_start <= scp->mouse_cut_end) { 61248104Syokota start = scp->mouse_cut_start; 61348104Syokota end = scp->mouse_cut_end; 61448104Syokota } else { 61548104Syokota start = scp->mouse_cut_end; 61648104Syokota end = scp->mouse_cut_start - 1; 61748104Syokota } 61848104Syokota s = spltty(); 61948104Syokota if (scp->mouse_pos > end) { 62048104Syokota scp->mouse_cut_start = start; 62148104Syokota scp->mouse_cut_end = end; 62248104Syokota } else if (scp->mouse_pos < start) { 62348104Syokota scp->mouse_cut_start = end + 1; 62448104Syokota scp->mouse_cut_end = start; 62548104Syokota } else { 62648104Syokota if (scp->mouse_pos - start > end + 1 - scp->mouse_pos) { 62748104Syokota scp->mouse_cut_start = start; 62848104Syokota scp->mouse_cut_end = end; 62948104Syokota } else { 63048104Syokota scp->mouse_cut_start = end + 1; 63148104Syokota scp->mouse_cut_end = start; 63248104Syokota } 63348104Syokota } 63448104Syokota splx(s); 63548104Syokota mouse_cut(scp); 63648104Syokota scp->status |= MOUSE_CUTTING; 63748104Syokota } 63848104Syokota} 63948104Syokota 64048104Syokota/* paste cut buffer contents into the current vty */ 64174118Sachevoid 64274118Sachesc_mouse_paste(scr_stat *scp) 64348104Syokota{ 64474125Sache sc_paste(scp, cut_buffer, strlen(cut_buffer)); 64548104Syokota} 64648104Syokota 64748104Syokota#endif /* SC_NO_CUTPASTE */ 64848104Syokota 64948104Syokotaint 650181905Sedsc_mouse_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td) 65148104Syokota{ 65256043Syokota mouse_info_t *mouse; 65356043Syokota mouse_info_t buf; 65456043Syokota scr_stat *cur_scp; 65548104Syokota scr_stat *scp; 65675893Sjhb struct proc *p1; 65748104Syokota int s; 65856043Syokota int f; 65948104Syokota 660181905Sed scp = SC_STAT(tp); 66148104Syokota 66248104Syokota switch (cmd) { 66348104Syokota 66448104Syokota case CONS_MOUSECTL: /* control mouse arrow */ 66548104Syokota case OLD_CONS_MOUSECTL: 66648104Syokota 66756043Syokota mouse = (mouse_info_t*)data; 66865690Smarkm 66965690Smarkm random_harvest(mouse, sizeof(mouse_info_t), 2, 0, RANDOM_MOUSE); 67065690Smarkm 67148104Syokota if (cmd == OLD_CONS_MOUSECTL) { 67248104Syokota static u_char swapb[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; 67348104Syokota old_mouse_info_t *old_mouse = (old_mouse_info_t *)data; 67448104Syokota 67548104Syokota mouse = &buf; 67648104Syokota mouse->operation = old_mouse->operation; 67748104Syokota switch (mouse->operation) { 67848104Syokota case MOUSE_MODE: 67948104Syokota mouse->u.mode = old_mouse->u.mode; 68048104Syokota break; 68148104Syokota case MOUSE_SHOW: 68248104Syokota case MOUSE_HIDE: 68348104Syokota break; 68448104Syokota case MOUSE_MOVEABS: 68548104Syokota case MOUSE_MOVEREL: 68648104Syokota case MOUSE_ACTION: 68748104Syokota mouse->u.data.x = old_mouse->u.data.x; 68848104Syokota mouse->u.data.y = old_mouse->u.data.y; 68948104Syokota mouse->u.data.z = 0; 69048104Syokota mouse->u.data.buttons = swapb[old_mouse->u.data.buttons & 0x7]; 69148104Syokota break; 69248104Syokota case MOUSE_GETINFO: 69348104Syokota old_mouse->u.data.x = scp->mouse_xpos; 69448104Syokota old_mouse->u.data.y = scp->mouse_ypos; 69548104Syokota old_mouse->u.data.buttons = swapb[scp->mouse_buttons & 0x7]; 69678951Syokota return 0; 69748104Syokota default: 69848104Syokota return EINVAL; 69948104Syokota } 70048104Syokota } 70148104Syokota 70248104Syokota cur_scp = scp->sc->cur_scp; 70348104Syokota 70448104Syokota switch (mouse->operation) { 70548104Syokota case MOUSE_MODE: 70648104Syokota if (ISSIGVALID(mouse->u.mode.signal)) { 70748104Syokota scp->mouse_signal = mouse->u.mode.signal; 70883366Sjulian scp->mouse_proc = td->td_proc; 70983366Sjulian scp->mouse_pid = td->td_proc->p_pid; 71048104Syokota } 71148104Syokota else { 71248104Syokota scp->mouse_signal = 0; 71348104Syokota scp->mouse_proc = NULL; 71448104Syokota scp->mouse_pid = 0; 71548104Syokota } 71648104Syokota return 0; 71748104Syokota 71848104Syokota case MOUSE_SHOW: 71948104Syokota s = spltty(); 72048104Syokota if (!(scp->sc->flags & SC_MOUSE_ENABLED)) { 72148104Syokota scp->sc->flags |= SC_MOUSE_ENABLED; 72258872Syokota cur_scp->status &= ~MOUSE_HIDDEN; 72358872Syokota if (!ISGRAPHSC(cur_scp)) 72448104Syokota mark_all(cur_scp); 72548104Syokota } 726146736Sdelphij splx(s); 727146736Sdelphij return 0; 728146736Sdelphij /* NOTREACHED */ 72948104Syokota 73048104Syokota case MOUSE_HIDE: 73148104Syokota s = spltty(); 73248104Syokota if (scp->sc->flags & SC_MOUSE_ENABLED) { 73348104Syokota scp->sc->flags &= ~SC_MOUSE_ENABLED; 73448104Syokota sc_remove_all_mouse(scp->sc); 73548104Syokota } 736146736Sdelphij splx(s); 737146736Sdelphij return 0; 738146736Sdelphij /* NOTREACHED */ 73948104Syokota 74048104Syokota case MOUSE_MOVEABS: 74148104Syokota s = spltty(); 74248104Syokota scp->mouse_xpos = mouse->u.data.x; 74348104Syokota scp->mouse_ypos = mouse->u.data.y; 74448104Syokota set_mouse_pos(scp); 74548104Syokota splx(s); 74648104Syokota break; 74748104Syokota 74848104Syokota case MOUSE_MOVEREL: 74948104Syokota s = spltty(); 75048104Syokota scp->mouse_xpos += mouse->u.data.x; 75148104Syokota scp->mouse_ypos += mouse->u.data.y; 75248104Syokota set_mouse_pos(scp); 75348104Syokota splx(s); 75448104Syokota break; 75548104Syokota 75648104Syokota case MOUSE_GETINFO: 75748104Syokota mouse->u.data.x = scp->mouse_xpos; 75848104Syokota mouse->u.data.y = scp->mouse_ypos; 75948104Syokota mouse->u.data.z = 0; 76048104Syokota mouse->u.data.buttons = scp->mouse_buttons; 76148104Syokota return 0; 76248104Syokota 76348104Syokota case MOUSE_ACTION: 76448104Syokota case MOUSE_MOTION_EVENT: 76548104Syokota /* send out mouse event on /dev/sysmouse */ 76648104Syokota#if 0 76748104Syokota /* this should maybe only be settable from /dev/consolectl SOS */ 76848104Syokota if (SC_VTY(tp->t_dev) != SC_CONSOLECTL) 76948104Syokota return ENOTTY; 77048104Syokota#endif 77153057Syokota s = spltty(); 77253057Syokota if (mouse->u.data.x != 0 || mouse->u.data.y != 0) { 77353057Syokota cur_scp->mouse_xpos += mouse->u.data.x; 77453057Syokota cur_scp->mouse_ypos += mouse->u.data.y; 77553057Syokota set_mouse_pos(cur_scp); 77653057Syokota } 77753057Syokota f = 0; 77853057Syokota if (mouse->operation == MOUSE_ACTION) { 77953057Syokota f = cur_scp->mouse_buttons ^ mouse->u.data.buttons; 78053057Syokota cur_scp->mouse_buttons = mouse->u.data.buttons; 78153057Syokota } 78253057Syokota splx(s); 78353057Syokota 78456043Syokota if (sysmouse_event(mouse) == 0) 78548104Syokota return 0; 78648104Syokota 78748104Syokota /* 78848104Syokota * If any buttons are down or the mouse has moved a lot, 78948104Syokota * stop the screen saver. 79048104Syokota */ 79148104Syokota if (((mouse->operation == MOUSE_ACTION) && mouse->u.data.buttons) 79248104Syokota || (mouse->u.data.x*mouse->u.data.x 79348104Syokota + mouse->u.data.y*mouse->u.data.y 79448104Syokota >= SC_WAKEUP_DELTA*SC_WAKEUP_DELTA)) { 79548104Syokota sc_touch_scrn_saver(); 79648104Syokota } 79748104Syokota 79858872Syokota cur_scp->status &= ~MOUSE_HIDDEN; 79954182Syokota 800197539Sed if (cur_scp->mouse_level > 0) { 801197539Sed sc_mouse_input(scp, mouse); 802197539Sed break; 803197539Sed } 804197539Sed 80575893Sjhb if (cur_scp->mouse_signal && cur_scp->mouse_proc) { 80654182Syokota /* has controlling process died? */ 80775893Sjhb if (cur_scp->mouse_proc != (p1 = pfind(cur_scp->mouse_pid))) { 80854182Syokota cur_scp->mouse_signal = 0; 80954182Syokota cur_scp->mouse_proc = NULL; 81054182Syokota cur_scp->mouse_pid = 0; 81175893Sjhb if (p1) 81275893Sjhb PROC_UNLOCK(p1); 81354182Syokota } else { 814225617Skmacy kern_psignal(cur_scp->mouse_proc, cur_scp->mouse_signal); 81573929Sjhb PROC_UNLOCK(cur_scp->mouse_proc); 81654182Syokota break; 81754182Syokota } 81854182Syokota } 81954182Syokota 820115595Sjmallett#ifndef SC_NO_CUTPASTE 82148104Syokota if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL)) 82248104Syokota break; 82348104Syokota 82453057Syokota if ((mouse->operation == MOUSE_ACTION) && f) { 82548104Syokota /* process button presses */ 82653057Syokota if (cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN) 82753057Syokota mouse_cut_start(cur_scp); 82853057Syokota else 82953057Syokota mouse_cut_end(cur_scp); 83053057Syokota if (cur_scp->mouse_buttons & MOUSE_BUTTON2DOWN || 83153057Syokota cur_scp->mouse_buttons & MOUSE_BUTTON3DOWN) 83274118Sache sc_mouse_paste(cur_scp); 83348104Syokota } 83448104Syokota#endif /* SC_NO_CUTPASTE */ 83548104Syokota break; 83648104Syokota 83748104Syokota case MOUSE_BUTTON_EVENT: 83848104Syokota if ((mouse->u.event.id & MOUSE_BUTTONS) == 0) 83948104Syokota return EINVAL; 84048104Syokota if (mouse->u.event.value < 0) 84148104Syokota return EINVAL; 84248104Syokota#if 0 84348104Syokota /* this should maybe only be settable from /dev/consolectl SOS */ 84448104Syokota if (SC_VTY(tp->t_dev) != SC_CONSOLECTL) 84548104Syokota return ENOTTY; 84648104Syokota#endif 84756043Syokota if (mouse->u.event.value > 0) 84848104Syokota cur_scp->mouse_buttons |= mouse->u.event.id; 84956043Syokota else 85048104Syokota cur_scp->mouse_buttons &= ~mouse->u.event.id; 85156043Syokota 85256043Syokota if (sysmouse_event(mouse) == 0) 85348104Syokota return 0; 85448104Syokota 85554182Syokota /* if a button is held down, stop the screen saver */ 85654182Syokota if (mouse->u.event.value > 0) 85754182Syokota sc_touch_scrn_saver(); 85854182Syokota 85958872Syokota cur_scp->status &= ~MOUSE_HIDDEN; 86054182Syokota 861197539Sed if (cur_scp->mouse_level > 0) { 862197539Sed sc_mouse_input(scp, mouse); 863197539Sed break; 864197539Sed } 865197539Sed 86675893Sjhb if (cur_scp->mouse_signal && cur_scp->mouse_proc) { 86775893Sjhb if (cur_scp->mouse_proc != (p1 = pfind(cur_scp->mouse_pid))){ 86848104Syokota cur_scp->mouse_signal = 0; 86948104Syokota cur_scp->mouse_proc = NULL; 87048104Syokota cur_scp->mouse_pid = 0; 87175893Sjhb if (p1) 87275893Sjhb PROC_UNLOCK(p1); 87354182Syokota } else { 874225617Skmacy kern_psignal(cur_scp->mouse_proc, cur_scp->mouse_signal); 87573929Sjhb PROC_UNLOCK(cur_scp->mouse_proc); 87654182Syokota break; 87748104Syokota } 87848104Syokota } 87948104Syokota 880115595Sjmallett#ifndef SC_NO_CUTPASTE 88148104Syokota if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL)) 88248104Syokota break; 88348104Syokota 88448104Syokota switch (mouse->u.event.id) { 88548104Syokota case MOUSE_BUTTON1DOWN: 88648104Syokota switch (mouse->u.event.value % 4) { 88748104Syokota case 0: /* up */ 88848104Syokota mouse_cut_end(cur_scp); 88948104Syokota break; 89048104Syokota case 1: /* single click: start cut operation */ 89148104Syokota mouse_cut_start(cur_scp); 89248104Syokota break; 89348104Syokota case 2: /* double click: cut a word */ 89448104Syokota mouse_cut_word(cur_scp); 89548104Syokota mouse_cut_end(cur_scp); 89648104Syokota break; 89748104Syokota case 3: /* triple click: cut a line */ 89848104Syokota mouse_cut_line(cur_scp); 89948104Syokota mouse_cut_end(cur_scp); 90048104Syokota break; 90148104Syokota } 90248104Syokota break; 90353011Syokota case SC_MOUSE_PASTEBUTTON: 90448104Syokota switch (mouse->u.event.value) { 90548104Syokota case 0: /* up */ 90648104Syokota break; 90748104Syokota default: 90874118Sache sc_mouse_paste(cur_scp); 90948104Syokota break; 91048104Syokota } 91148104Syokota break; 91253011Syokota case SC_MOUSE_EXTENDBUTTON: 91348104Syokota switch (mouse->u.event.value) { 91448104Syokota case 0: /* up */ 91548104Syokota if (!(cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN)) 91648104Syokota mouse_cut_end(cur_scp); 91748104Syokota break; 91848104Syokota default: 91948104Syokota mouse_cut_extend(cur_scp); 92048104Syokota break; 92148104Syokota } 92248104Syokota break; 92348104Syokota } 92448104Syokota#endif /* SC_NO_CUTPASTE */ 92548104Syokota break; 92648104Syokota 92755849Syokota case MOUSE_MOUSECHAR: 92855849Syokota if (mouse->u.mouse_char < 0) { 92955849Syokota mouse->u.mouse_char = scp->sc->mouse_char; 93055849Syokota } else { 93175790Sache if (mouse->u.mouse_char > UCHAR_MAX - 3) 93255849Syokota return EINVAL; 93356043Syokota s = spltty(); 93455849Syokota sc_remove_all_mouse(scp->sc); 93555849Syokota#ifndef SC_NO_FONT_LOADING 93656328Syokota if (ISTEXTSC(cur_scp) && (cur_scp->font != NULL)) 93775790Sache sc_load_font(cur_scp, 0, cur_scp->font_size, 938150686Smarius cur_scp->font_width, 93975790Sache cur_scp->font + cur_scp->font_size 94075790Sache * cur_scp->sc->mouse_char, 94156043Syokota cur_scp->sc->mouse_char, 4); 94255849Syokota#endif 94355849Syokota scp->sc->mouse_char = mouse->u.mouse_char; 94455849Syokota splx(s); 94555849Syokota } 94655849Syokota break; 94755849Syokota 94848104Syokota default: 94948104Syokota return EINVAL; 95048104Syokota } 95148104Syokota 95248104Syokota return 0; 95348104Syokota } 95448104Syokota 95548104Syokota return ENOIOCTL; 95648104Syokota} 95748104Syokota 95848104Syokota#endif /* SC_NO_SYSMOUSE */ 959