scmouse.c revision 58872
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 * 2650477Speter * $FreeBSD: head/sys/dev/syscons/scmouse.c 58872 2000-03-31 16:05:46Z yokota $ 2748104Syokota */ 2848104Syokota 2948104Syokota#include "opt_syscons.h" 3048104Syokota 3155849Syokota#include <limits.h> 3248104Syokota#include <sys/param.h> 3348104Syokota#include <sys/systm.h> 3448104Syokota#include <sys/conf.h> 3548104Syokota#include <sys/signalvar.h> 3648104Syokota#include <sys/proc.h> 3748104Syokota#include <sys/tty.h> 3848104Syokota#include <sys/malloc.h> 3948104Syokota 4048104Syokota#include <machine/console.h> 4148104Syokota#include <machine/mouse.h> 4248104Syokota 4348104Syokota#include <dev/syscons/syscons.h> 4448104Syokota 4553011Syokota#ifdef SC_TWOBUTTON_MOUSE 4653011Syokota#define SC_MOUSE_PASTEBUTTON MOUSE_BUTTON3DOWN /* right button */ 4753011Syokota#define SC_MOUSE_EXTENDBUTTON MOUSE_BUTTON2DOWN /* not really used */ 4853011Syokota#else 4953011Syokota#define SC_MOUSE_PASTEBUTTON MOUSE_BUTTON2DOWN /* middle button */ 5053011Syokota#define SC_MOUSE_EXTENDBUTTON MOUSE_BUTTON3DOWN /* right button */ 5153011Syokota#endif /* SC_TWOBUTTON_MOUSE */ 5253011Syokota 5348104Syokota#define SC_WAKEUP_DELTA 20 5448104Syokota 5548104Syokota/* for backward compatibility */ 5648104Syokota#define OLD_CONS_MOUSECTL _IOWR('c', 10, old_mouse_info_t) 5748104Syokota 5848104Syokotatypedef struct old_mouse_data { 5948104Syokota int x; 6048104Syokota int y; 6148104Syokota int buttons; 6248104Syokota} old_mouse_data_t; 6348104Syokota 6448104Syokotatypedef struct old_mouse_info { 6548104Syokota int operation; 6648104Syokota union { 6748104Syokota struct old_mouse_data data; 6848104Syokota struct mouse_mode mode; 6948104Syokota } u; 7048104Syokota} old_mouse_info_t; 7148104Syokota 7256043Syokota#ifndef SC_NO_SYSMOUSE 7356043Syokota 7448104Syokota/* local variables */ 7548104Syokotastatic int cut_buffer_size; 7648104Syokotastatic u_char *cut_buffer; 7748104Syokota 7848104Syokota/* local functions */ 7948104Syokotastatic void set_mouse_pos(scr_stat *scp); 8048104Syokota#ifndef SC_NO_CUTPASTE 8148104Syokotastatic int skip_spc_right(scr_stat *scp, int p); 8248104Syokotastatic int skip_spc_left(scr_stat *scp, int p); 8348104Syokotastatic void mouse_cut(scr_stat *scp); 8448104Syokotastatic void mouse_cut_start(scr_stat *scp); 8548104Syokotastatic void mouse_cut_end(scr_stat *scp); 8648104Syokotastatic void mouse_cut_word(scr_stat *scp); 8748104Syokotastatic void mouse_cut_line(scr_stat *scp); 8848104Syokotastatic void mouse_cut_extend(scr_stat *scp); 8948104Syokotastatic void mouse_paste(scr_stat *scp); 9048104Syokota#endif /* SC_NO_CUTPASTE */ 9148104Syokota 9248104Syokota#ifndef SC_NO_CUTPASTE 9348104Syokota/* allocate a cut buffer */ 9448104Syokotavoid 9548104Syokotasc_alloc_cut_buffer(scr_stat *scp, int wait) 9648104Syokota{ 9748104Syokota u_char *p; 9848104Syokota 9948104Syokota if ((cut_buffer == NULL) 10048104Syokota || (cut_buffer_size < scp->xsize * scp->ysize + 1)) { 10148104Syokota p = cut_buffer; 10248104Syokota cut_buffer = NULL; 10348104Syokota if (p != NULL) 10448104Syokota free(p, M_DEVBUF); 10548104Syokota cut_buffer_size = scp->xsize * scp->ysize + 1; 10648104Syokota p = (u_char *)malloc(cut_buffer_size, 10748104Syokota M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT); 10848104Syokota if (p != NULL) 10948104Syokota p[0] = '\0'; 11048104Syokota cut_buffer = p; 11148104Syokota } 11248104Syokota} 11348104Syokota#endif /* SC_NO_CUTPASTE */ 11448104Syokota 11548104Syokota/* move mouse */ 11648104Syokotavoid 11748104Syokotasc_mouse_move(scr_stat *scp, int x, int y) 11848104Syokota{ 11948104Syokota int s; 12048104Syokota 12148104Syokota s = spltty(); 12258872Syokota scp->mouse_xpos = scp->mouse_oldxpos = x; 12358872Syokota scp->mouse_ypos = scp->mouse_oldypos = y; 12458872Syokota if (scp->font_size <= 0) 12556528Syokota scp->mouse_pos = scp->mouse_oldpos = 0; 12656528Syokota else 12756528Syokota scp->mouse_pos = scp->mouse_oldpos = 12856528Syokota (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff; 12958872Syokota scp->status |= MOUSE_MOVED; 13048104Syokota splx(s); 13148104Syokota} 13248104Syokota 13348104Syokota/* adjust mouse position */ 13448104Syokotastatic void 13548104Syokotaset_mouse_pos(scr_stat *scp) 13648104Syokota{ 13748104Syokota if (scp->mouse_xpos < scp->xoff*8) 13848104Syokota scp->mouse_xpos = scp->xoff*8; 13948104Syokota if (scp->mouse_ypos < scp->yoff*scp->font_size) 14048104Syokota scp->mouse_ypos = scp->yoff*scp->font_size; 14148104Syokota if (ISGRAPHSC(scp)) { 14248104Syokota if (scp->mouse_xpos > scp->xpixel-1) 14348104Syokota scp->mouse_xpos = scp->xpixel-1; 14448104Syokota if (scp->mouse_ypos > scp->ypixel-1) 14548104Syokota scp->mouse_ypos = scp->ypixel-1; 14648104Syokota return; 14748104Syokota } else { 14848104Syokota if (scp->mouse_xpos > (scp->xsize + scp->xoff)*8 - 1) 14948104Syokota scp->mouse_xpos = (scp->xsize + scp->xoff)*8 - 1; 15048104Syokota if (scp->mouse_ypos > (scp->ysize + scp->yoff)*scp->font_size - 1) 15148104Syokota scp->mouse_ypos = (scp->ysize + scp->yoff)*scp->font_size - 1; 15248104Syokota } 15348104Syokota 15458872Syokota if (scp->mouse_xpos != scp->mouse_oldxpos || scp->mouse_ypos != scp->mouse_oldypos) { 15548104Syokota scp->status |= MOUSE_MOVED; 15648104Syokota scp->mouse_pos = 15748104Syokota (scp->mouse_ypos/scp->font_size - scp->yoff)*scp->xsize 15848104Syokota + scp->mouse_xpos/8 - scp->xoff; 15948104Syokota#ifndef SC_NO_CUTPASTE 16048104Syokota if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING)) 16148104Syokota mouse_cut(scp); 16248104Syokota#endif 16348104Syokota } 16448104Syokota} 16548104Syokota 16648104Syokota#ifndef SC_NO_CUTPASTE 16748104Syokota 16848104Syokotavoid 16948104Syokotasc_draw_mouse_image(scr_stat *scp) 17048104Syokota{ 17148104Syokota if (ISGRAPHSC(scp)) 17248104Syokota return; 17348104Syokota 17448104Syokota ++scp->sc->videoio_in_progress; 17548104Syokota (*scp->rndr->draw_mouse)(scp, scp->mouse_xpos, scp->mouse_ypos, TRUE); 17648104Syokota scp->mouse_oldpos = scp->mouse_pos; 17758872Syokota scp->mouse_oldxpos = scp->mouse_xpos; 17858872Syokota scp->mouse_oldypos = scp->mouse_ypos; 17958872Syokota scp->status |= MOUSE_VISIBLE; 18048104Syokota --scp->sc->videoio_in_progress; 18148104Syokota} 18248104Syokota 18348104Syokotavoid 18448104Syokotasc_remove_mouse_image(scr_stat *scp) 18548104Syokota{ 18648104Syokota int size; 18748104Syokota int i; 18848104Syokota 18948104Syokota if (ISGRAPHSC(scp)) 19048104Syokota return; 19148104Syokota 19248104Syokota ++scp->sc->videoio_in_progress; 19348104Syokota (*scp->rndr->draw_mouse)(scp, 19448104Syokota (scp->mouse_oldpos%scp->xsize + scp->xoff)*8, 19548104Syokota (scp->mouse_oldpos/scp->xsize + scp->yoff) 19648104Syokota * scp->font_size, 19748104Syokota FALSE); 19848104Syokota size = scp->xsize*scp->ysize; 19948104Syokota i = scp->mouse_oldpos; 20048104Syokota mark_for_update(scp, i); 20148104Syokota mark_for_update(scp, i); 20248104Syokota#ifndef PC98 20348104Syokota if (i + scp->xsize + 1 < size) { 20448104Syokota mark_for_update(scp, i + scp->xsize + 1); 20548104Syokota } else if (i + scp->xsize < size) { 20648104Syokota mark_for_update(scp, i + scp->xsize); 20748104Syokota } else if (i + 1 < size) { 20848104Syokota mark_for_update(scp, i + 1); 20948104Syokota } 21048104Syokota#endif /* PC98 */ 21158872Syokota scp->status &= ~MOUSE_VISIBLE; 21248104Syokota --scp->sc->videoio_in_progress; 21348104Syokota} 21448104Syokota 21548104Syokotaint 21648104Syokotasc_inside_cutmark(scr_stat *scp, int pos) 21748104Syokota{ 21848104Syokota int start; 21948104Syokota int end; 22048104Syokota 22148104Syokota if (scp->mouse_cut_end < 0) 22248104Syokota return FALSE; 22348104Syokota if (scp->mouse_cut_start <= scp->mouse_cut_end) { 22448104Syokota start = scp->mouse_cut_start; 22548104Syokota end = scp->mouse_cut_end; 22648104Syokota } else { 22748104Syokota start = scp->mouse_cut_end; 22848104Syokota end = scp->mouse_cut_start - 1; 22948104Syokota } 23048104Syokota return ((start <= pos) && (pos <= end)); 23148104Syokota} 23248104Syokota 23348104Syokotavoid 23448104Syokotasc_remove_cutmarking(scr_stat *scp) 23548104Syokota{ 23648104Syokota int s; 23748104Syokota 23848104Syokota s = spltty(); 23948104Syokota if (scp->mouse_cut_end >= 0) { 24048104Syokota mark_for_update(scp, scp->mouse_cut_start); 24148104Syokota mark_for_update(scp, scp->mouse_cut_end); 24248104Syokota } 24348104Syokota scp->mouse_cut_start = scp->xsize*scp->ysize; 24448104Syokota scp->mouse_cut_end = -1; 24548104Syokota splx(s); 24648104Syokota scp->status &= ~MOUSE_CUTTING; 24748104Syokota} 24848104Syokota 24948104Syokotavoid 25048104Syokotasc_remove_all_cutmarkings(sc_softc_t *sc) 25148104Syokota{ 25251404Syokota scr_stat *scp; 25348104Syokota int i; 25448104Syokota 25548104Syokota /* delete cut markings in all vtys */ 25648104Syokota for (i = 0; i < sc->vtys; ++i) { 25751404Syokota scp = SC_STAT(sc->dev[i]); 25851404Syokota if (scp == NULL) 25948104Syokota continue; 26051404Syokota sc_remove_cutmarking(scp); 26148104Syokota } 26248104Syokota} 26348104Syokota 26448104Syokotavoid 26548104Syokotasc_remove_all_mouse(sc_softc_t *sc) 26648104Syokota{ 26751404Syokota scr_stat *scp; 26848104Syokota int i; 26948104Syokota 27048104Syokota for (i = 0; i < sc->vtys; ++i) { 27151404Syokota scp = SC_STAT(sc->dev[i]); 27251404Syokota if (scp == NULL) 27348104Syokota continue; 27451404Syokota if (scp->status & MOUSE_VISIBLE) { 27551404Syokota scp->status &= ~MOUSE_VISIBLE; 27651404Syokota mark_all(scp); 27748104Syokota } 27848104Syokota } 27948104Syokota} 28048104Syokota 28152813Sarchie#define IS_SPACE_CHAR(c) (((c) & 0xff) == ' ') 28248104Syokota 28348104Syokota/* skip spaces to right */ 28448104Syokotastatic int 28548104Syokotaskip_spc_right(scr_stat *scp, int p) 28648104Syokota{ 28748104Syokota int c; 28848104Syokota int i; 28948104Syokota 29048104Syokota for (i = p % scp->xsize; i < scp->xsize; ++i) { 29148104Syokota c = sc_vtb_getc(&scp->vtb, p); 29252813Sarchie if (!IS_SPACE_CHAR(c)) 29348104Syokota break; 29448104Syokota ++p; 29548104Syokota } 29648104Syokota return i; 29748104Syokota} 29848104Syokota 29948104Syokota/* skip spaces to left */ 30048104Syokotastatic int 30148104Syokotaskip_spc_left(scr_stat *scp, int p) 30248104Syokota{ 30348104Syokota int c; 30448104Syokota int i; 30548104Syokota 30648104Syokota for (i = p-- % scp->xsize - 1; i >= 0; --i) { 30748104Syokota c = sc_vtb_getc(&scp->vtb, p); 30852813Sarchie if (!IS_SPACE_CHAR(c)) 30948104Syokota break; 31048104Syokota --p; 31148104Syokota } 31248104Syokota return i; 31348104Syokota} 31448104Syokota 31548104Syokota/* copy marked region to the cut buffer */ 31648104Syokotastatic void 31748104Syokotamouse_cut(scr_stat *scp) 31848104Syokota{ 31948104Syokota int start; 32048104Syokota int end; 32148104Syokota int from; 32248104Syokota int to; 32348104Syokota int blank; 32448104Syokota int c; 32548104Syokota int p; 32648104Syokota int s; 32748104Syokota int i; 32848104Syokota 32948104Syokota start = scp->mouse_cut_start; 33048104Syokota end = scp->mouse_cut_end; 33148104Syokota if (scp->mouse_pos >= start) { 33248104Syokota from = start; 33348104Syokota to = end = scp->mouse_pos; 33448104Syokota } else { 33548104Syokota from = end = scp->mouse_pos; 33648104Syokota to = start - 1; 33748104Syokota } 33848104Syokota for (p = from, i = blank = 0; p <= to; ++p) { 33948104Syokota cut_buffer[i] = sc_vtb_getc(&scp->vtb, p); 34048104Syokota /* remember the position of the last non-space char */ 34152813Sarchie if (!IS_SPACE_CHAR(cut_buffer[i++])) 34248104Syokota blank = i; /* the first space after the last non-space */ 34348104Syokota /* trim trailing blank when crossing lines */ 34448104Syokota if ((p % scp->xsize) == (scp->xsize - 1)) { 34548104Syokota cut_buffer[blank] = '\r'; 34648104Syokota i = blank + 1; 34748104Syokota } 34848104Syokota } 34948104Syokota cut_buffer[i] = '\0'; 35048104Syokota 35148104Syokota /* scan towards the end of the last line */ 35248104Syokota --p; 35348104Syokota for (i = p % scp->xsize; i < scp->xsize; ++i) { 35448104Syokota c = sc_vtb_getc(&scp->vtb, p); 35552813Sarchie if (!IS_SPACE_CHAR(c)) 35648104Syokota break; 35748104Syokota ++p; 35848104Syokota } 35948104Syokota /* if there is nothing but blank chars, trim them, but mark towards eol */ 36048104Syokota if (i >= scp->xsize) { 36148104Syokota if (end >= start) 36248104Syokota to = end = p - 1; 36348104Syokota else 36448104Syokota to = start = p; 36548104Syokota cut_buffer[blank++] = '\r'; 36648104Syokota cut_buffer[blank] = '\0'; 36748104Syokota } 36848104Syokota 36948104Syokota /* remove the current marking */ 37048104Syokota s = spltty(); 37148104Syokota if (scp->mouse_cut_start <= scp->mouse_cut_end) { 37248104Syokota mark_for_update(scp, scp->mouse_cut_start); 37348104Syokota mark_for_update(scp, scp->mouse_cut_end); 37448104Syokota } else if (scp->mouse_cut_end >= 0) { 37548104Syokota mark_for_update(scp, scp->mouse_cut_end); 37648104Syokota mark_for_update(scp, scp->mouse_cut_start); 37748104Syokota } 37848104Syokota 37948104Syokota /* mark the new region */ 38048104Syokota scp->mouse_cut_start = start; 38148104Syokota scp->mouse_cut_end = end; 38248104Syokota mark_for_update(scp, from); 38348104Syokota mark_for_update(scp, to); 38448104Syokota splx(s); 38548104Syokota} 38648104Syokota 38748104Syokota/* a mouse button is pressed, start cut operation */ 38848104Syokotastatic void 38948104Syokotamouse_cut_start(scr_stat *scp) 39048104Syokota{ 39148104Syokota int i; 39248104Syokota int j; 39348104Syokota int s; 39448104Syokota 39548104Syokota if (scp->status & MOUSE_VISIBLE) { 39648104Syokota i = scp->mouse_cut_start; 39748104Syokota j = scp->mouse_cut_end; 39848104Syokota sc_remove_all_cutmarkings(scp->sc); 39948104Syokota if (scp->mouse_pos == i && i == j) { 40048104Syokota cut_buffer[0] = '\0'; 40148104Syokota } else if (skip_spc_right(scp, scp->mouse_pos) >= scp->xsize) { 40248104Syokota /* if the pointer is on trailing blank chars, mark towards eol */ 40348104Syokota i = skip_spc_left(scp, scp->mouse_pos) + 1; 40448104Syokota s = spltty(); 40548104Syokota scp->mouse_cut_start = 40648104Syokota (scp->mouse_pos / scp->xsize) * scp->xsize + i; 40748104Syokota scp->mouse_cut_end = 40848104Syokota (scp->mouse_pos / scp->xsize + 1) * scp->xsize - 1; 40948104Syokota splx(s); 41048104Syokota cut_buffer[0] = '\r'; 41148104Syokota cut_buffer[1] = '\0'; 41248104Syokota scp->status |= MOUSE_CUTTING; 41348104Syokota } else { 41448104Syokota s = spltty(); 41548104Syokota scp->mouse_cut_start = scp->mouse_pos; 41648104Syokota scp->mouse_cut_end = scp->mouse_cut_start; 41748104Syokota splx(s); 41848104Syokota cut_buffer[0] = sc_vtb_getc(&scp->vtb, scp->mouse_cut_start); 41948104Syokota cut_buffer[1] = '\0'; 42048104Syokota scp->status |= MOUSE_CUTTING; 42148104Syokota } 42248104Syokota mark_all(scp); /* this is probably overkill XXX */ 42348104Syokota } 42448104Syokota} 42548104Syokota 42648104Syokota/* end of cut operation */ 42748104Syokotastatic void 42848104Syokotamouse_cut_end(scr_stat *scp) 42948104Syokota{ 43048104Syokota if (scp->status & MOUSE_VISIBLE) 43148104Syokota scp->status &= ~MOUSE_CUTTING; 43248104Syokota} 43348104Syokota 43448104Syokota/* copy a word under the mouse pointer */ 43548104Syokotastatic void 43648104Syokotamouse_cut_word(scr_stat *scp) 43748104Syokota{ 43848104Syokota int start; 43948104Syokota int end; 44048104Syokota int sol; 44148104Syokota int eol; 44248104Syokota int c; 44348104Syokota int s; 44448104Syokota int i; 44548104Syokota int j; 44648104Syokota 44748104Syokota /* 44848104Syokota * Because we don't have locale information in the kernel, 44948104Syokota * we only distinguish space char and non-space chars. Punctuation 45048104Syokota * chars, symbols and other regular chars are all treated alike. 45148104Syokota */ 45248104Syokota if (scp->status & MOUSE_VISIBLE) { 45348104Syokota /* remove the current cut mark */ 45448104Syokota s = spltty(); 45548104Syokota if (scp->mouse_cut_start <= scp->mouse_cut_end) { 45648104Syokota mark_for_update(scp, scp->mouse_cut_start); 45748104Syokota mark_for_update(scp, scp->mouse_cut_end); 45848104Syokota } else if (scp->mouse_cut_end >= 0) { 45948104Syokota mark_for_update(scp, scp->mouse_cut_end); 46048104Syokota mark_for_update(scp, scp->mouse_cut_start); 46148104Syokota } 46248104Syokota scp->mouse_cut_start = scp->xsize*scp->ysize; 46348104Syokota scp->mouse_cut_end = -1; 46448104Syokota splx(s); 46548104Syokota 46648104Syokota sol = (scp->mouse_pos / scp->xsize) * scp->xsize; 46748104Syokota eol = sol + scp->xsize; 46848104Syokota c = sc_vtb_getc(&scp->vtb, scp->mouse_pos); 46952813Sarchie if (IS_SPACE_CHAR(c)) { 47048104Syokota /* blank space */ 47148104Syokota for (j = scp->mouse_pos; j >= sol; --j) { 47248104Syokota c = sc_vtb_getc(&scp->vtb, j); 47352813Sarchie if (!IS_SPACE_CHAR(c)) 47448104Syokota break; 47548104Syokota } 47648104Syokota start = ++j; 47748104Syokota for (j = scp->mouse_pos; j < eol; ++j) { 47848104Syokota c = sc_vtb_getc(&scp->vtb, j); 47952813Sarchie if (!IS_SPACE_CHAR(c)) 48048104Syokota break; 48148104Syokota } 48248104Syokota end = j - 1; 48348104Syokota } else { 48448104Syokota /* non-space word */ 48548104Syokota for (j = scp->mouse_pos; j >= sol; --j) { 48648104Syokota c = sc_vtb_getc(&scp->vtb, j); 48752813Sarchie if (IS_SPACE_CHAR(c)) 48848104Syokota break; 48948104Syokota } 49048104Syokota start = ++j; 49148104Syokota for (j = scp->mouse_pos; j < eol; ++j) { 49248104Syokota c = sc_vtb_getc(&scp->vtb, j); 49352813Sarchie if (IS_SPACE_CHAR(c)) 49448104Syokota break; 49548104Syokota } 49648104Syokota end = j - 1; 49748104Syokota } 49848104Syokota 49948104Syokota /* copy the found word */ 50048104Syokota for (i = 0, j = start; j <= end; ++j) 50148104Syokota cut_buffer[i++] = sc_vtb_getc(&scp->vtb, j); 50248104Syokota cut_buffer[i] = '\0'; 50348104Syokota scp->status |= MOUSE_CUTTING; 50448104Syokota 50548104Syokota /* mark the region */ 50648104Syokota s = spltty(); 50748104Syokota scp->mouse_cut_start = start; 50848104Syokota scp->mouse_cut_end = end; 50948104Syokota mark_for_update(scp, start); 51048104Syokota mark_for_update(scp, end); 51148104Syokota splx(s); 51248104Syokota } 51348104Syokota} 51448104Syokota 51548104Syokota/* copy a line under the mouse pointer */ 51648104Syokotastatic void 51748104Syokotamouse_cut_line(scr_stat *scp) 51848104Syokota{ 51948104Syokota int s; 52048104Syokota int i; 52148104Syokota int j; 52248104Syokota 52348104Syokota if (scp->status & MOUSE_VISIBLE) { 52448104Syokota /* remove the current cut mark */ 52548104Syokota s = spltty(); 52648104Syokota if (scp->mouse_cut_start <= scp->mouse_cut_end) { 52748104Syokota mark_for_update(scp, scp->mouse_cut_start); 52848104Syokota mark_for_update(scp, scp->mouse_cut_end); 52948104Syokota } else if (scp->mouse_cut_end >= 0) { 53048104Syokota mark_for_update(scp, scp->mouse_cut_end); 53148104Syokota mark_for_update(scp, scp->mouse_cut_start); 53248104Syokota } 53348104Syokota 53448104Syokota /* mark the entire line */ 53548104Syokota scp->mouse_cut_start = 53648104Syokota (scp->mouse_pos / scp->xsize) * scp->xsize; 53748104Syokota scp->mouse_cut_end = scp->mouse_cut_start + scp->xsize - 1; 53848104Syokota mark_for_update(scp, scp->mouse_cut_start); 53948104Syokota mark_for_update(scp, scp->mouse_cut_end); 54048104Syokota splx(s); 54148104Syokota 54248104Syokota /* copy the line into the cut buffer */ 54348104Syokota for (i = 0, j = scp->mouse_cut_start; j <= scp->mouse_cut_end; ++j) 54448104Syokota cut_buffer[i++] = sc_vtb_getc(&scp->vtb, j); 54548104Syokota cut_buffer[i++] = '\r'; 54648104Syokota cut_buffer[i] = '\0'; 54748104Syokota scp->status |= MOUSE_CUTTING; 54848104Syokota } 54948104Syokota} 55048104Syokota 55148104Syokota/* extend the marked region to the mouse pointer position */ 55248104Syokotastatic void 55348104Syokotamouse_cut_extend(scr_stat *scp) 55448104Syokota{ 55548104Syokota int start; 55648104Syokota int end; 55748104Syokota int s; 55848104Syokota 55948104Syokota if ((scp->status & MOUSE_VISIBLE) && !(scp->status & MOUSE_CUTTING) 56048104Syokota && (scp->mouse_cut_end >= 0)) { 56148104Syokota if (scp->mouse_cut_start <= scp->mouse_cut_end) { 56248104Syokota start = scp->mouse_cut_start; 56348104Syokota end = scp->mouse_cut_end; 56448104Syokota } else { 56548104Syokota start = scp->mouse_cut_end; 56648104Syokota end = scp->mouse_cut_start - 1; 56748104Syokota } 56848104Syokota s = spltty(); 56948104Syokota if (scp->mouse_pos > end) { 57048104Syokota scp->mouse_cut_start = start; 57148104Syokota scp->mouse_cut_end = end; 57248104Syokota } else if (scp->mouse_pos < start) { 57348104Syokota scp->mouse_cut_start = end + 1; 57448104Syokota scp->mouse_cut_end = start; 57548104Syokota } else { 57648104Syokota if (scp->mouse_pos - start > end + 1 - scp->mouse_pos) { 57748104Syokota scp->mouse_cut_start = start; 57848104Syokota scp->mouse_cut_end = end; 57948104Syokota } else { 58048104Syokota scp->mouse_cut_start = end + 1; 58148104Syokota scp->mouse_cut_end = start; 58248104Syokota } 58348104Syokota } 58448104Syokota splx(s); 58548104Syokota mouse_cut(scp); 58648104Syokota scp->status |= MOUSE_CUTTING; 58748104Syokota } 58848104Syokota} 58948104Syokota 59048104Syokota/* paste cut buffer contents into the current vty */ 59148104Syokotastatic void 59248104Syokotamouse_paste(scr_stat *scp) 59348104Syokota{ 59448104Syokota if (scp->status & MOUSE_VISIBLE) 59548104Syokota sc_paste(scp, cut_buffer, strlen(cut_buffer)); 59648104Syokota} 59748104Syokota 59848104Syokota#endif /* SC_NO_CUTPASTE */ 59948104Syokota 60048104Syokotaint 60148104Syokotasc_mouse_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, 60248104Syokota struct proc *p) 60348104Syokota{ 60456043Syokota mouse_info_t *mouse; 60556043Syokota mouse_info_t buf; 60656043Syokota scr_stat *cur_scp; 60748104Syokota scr_stat *scp; 60848104Syokota int s; 60956043Syokota int f; 61048104Syokota 61151404Syokota scp = SC_STAT(tp->t_dev); 61248104Syokota 61348104Syokota switch (cmd) { 61448104Syokota 61548104Syokota case CONS_MOUSECTL: /* control mouse arrow */ 61648104Syokota case OLD_CONS_MOUSECTL: 61748104Syokota 61856043Syokota mouse = (mouse_info_t*)data; 61948104Syokota if (cmd == OLD_CONS_MOUSECTL) { 62048104Syokota static u_char swapb[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; 62148104Syokota old_mouse_info_t *old_mouse = (old_mouse_info_t *)data; 62248104Syokota 62348104Syokota mouse = &buf; 62448104Syokota mouse->operation = old_mouse->operation; 62548104Syokota switch (mouse->operation) { 62648104Syokota case MOUSE_MODE: 62748104Syokota mouse->u.mode = old_mouse->u.mode; 62848104Syokota break; 62948104Syokota case MOUSE_SHOW: 63048104Syokota case MOUSE_HIDE: 63148104Syokota break; 63248104Syokota case MOUSE_MOVEABS: 63348104Syokota case MOUSE_MOVEREL: 63448104Syokota case MOUSE_ACTION: 63548104Syokota mouse->u.data.x = old_mouse->u.data.x; 63648104Syokota mouse->u.data.y = old_mouse->u.data.y; 63748104Syokota mouse->u.data.z = 0; 63848104Syokota mouse->u.data.buttons = swapb[old_mouse->u.data.buttons & 0x7]; 63948104Syokota break; 64048104Syokota case MOUSE_GETINFO: 64148104Syokota old_mouse->u.data.x = scp->mouse_xpos; 64248104Syokota old_mouse->u.data.y = scp->mouse_ypos; 64348104Syokota old_mouse->u.data.buttons = swapb[scp->mouse_buttons & 0x7]; 64448104Syokota break; 64548104Syokota default: 64648104Syokota return EINVAL; 64748104Syokota } 64848104Syokota } 64948104Syokota 65048104Syokota cur_scp = scp->sc->cur_scp; 65148104Syokota 65248104Syokota switch (mouse->operation) { 65348104Syokota case MOUSE_MODE: 65448104Syokota if (ISSIGVALID(mouse->u.mode.signal)) { 65548104Syokota scp->mouse_signal = mouse->u.mode.signal; 65648104Syokota scp->mouse_proc = p; 65748104Syokota scp->mouse_pid = p->p_pid; 65848104Syokota } 65948104Syokota else { 66048104Syokota scp->mouse_signal = 0; 66148104Syokota scp->mouse_proc = NULL; 66248104Syokota scp->mouse_pid = 0; 66348104Syokota } 66448104Syokota return 0; 66548104Syokota 66648104Syokota case MOUSE_SHOW: 66748104Syokota if (!ISMOUSEAVAIL(scp->sc->adp->va_flags)) 66848104Syokota return EINVAL; 66948104Syokota s = spltty(); 67048104Syokota if (!(scp->sc->flags & SC_MOUSE_ENABLED)) { 67148104Syokota scp->sc->flags |= SC_MOUSE_ENABLED; 67258872Syokota cur_scp->status &= ~MOUSE_HIDDEN; 67358872Syokota if (!ISGRAPHSC(cur_scp)) 67448104Syokota mark_all(cur_scp); 67548104Syokota splx(s); 67648104Syokota return 0; 67748104Syokota } else { 67848104Syokota splx(s); 67948104Syokota return EINVAL; 68048104Syokota } 68148104Syokota break; 68248104Syokota 68348104Syokota case MOUSE_HIDE: 68448104Syokota s = spltty(); 68548104Syokota if (scp->sc->flags & SC_MOUSE_ENABLED) { 68648104Syokota scp->sc->flags &= ~SC_MOUSE_ENABLED; 68748104Syokota sc_remove_all_mouse(scp->sc); 68848104Syokota splx(s); 68948104Syokota return 0; 69048104Syokota } else { 69148104Syokota splx(s); 69248104Syokota return EINVAL; 69348104Syokota } 69448104Syokota break; 69548104Syokota 69648104Syokota case MOUSE_MOVEABS: 69748104Syokota s = spltty(); 69848104Syokota scp->mouse_xpos = mouse->u.data.x; 69948104Syokota scp->mouse_ypos = mouse->u.data.y; 70048104Syokota set_mouse_pos(scp); 70148104Syokota splx(s); 70248104Syokota break; 70348104Syokota 70448104Syokota case MOUSE_MOVEREL: 70548104Syokota s = spltty(); 70648104Syokota scp->mouse_xpos += mouse->u.data.x; 70748104Syokota scp->mouse_ypos += mouse->u.data.y; 70848104Syokota set_mouse_pos(scp); 70948104Syokota splx(s); 71048104Syokota break; 71148104Syokota 71248104Syokota case MOUSE_GETINFO: 71348104Syokota mouse->u.data.x = scp->mouse_xpos; 71448104Syokota mouse->u.data.y = scp->mouse_ypos; 71548104Syokota mouse->u.data.z = 0; 71648104Syokota mouse->u.data.buttons = scp->mouse_buttons; 71748104Syokota return 0; 71848104Syokota 71948104Syokota case MOUSE_ACTION: 72048104Syokota case MOUSE_MOTION_EVENT: 72148104Syokota /* send out mouse event on /dev/sysmouse */ 72248104Syokota#if 0 72348104Syokota /* this should maybe only be settable from /dev/consolectl SOS */ 72448104Syokota if (SC_VTY(tp->t_dev) != SC_CONSOLECTL) 72548104Syokota return ENOTTY; 72648104Syokota#endif 72753057Syokota s = spltty(); 72853057Syokota if (mouse->u.data.x != 0 || mouse->u.data.y != 0) { 72953057Syokota cur_scp->mouse_xpos += mouse->u.data.x; 73053057Syokota cur_scp->mouse_ypos += mouse->u.data.y; 73153057Syokota set_mouse_pos(cur_scp); 73253057Syokota } 73353057Syokota f = 0; 73453057Syokota if (mouse->operation == MOUSE_ACTION) { 73553057Syokota f = cur_scp->mouse_buttons ^ mouse->u.data.buttons; 73653057Syokota cur_scp->mouse_buttons = mouse->u.data.buttons; 73753057Syokota } 73853057Syokota splx(s); 73953057Syokota 74056043Syokota if (sysmouse_event(mouse) == 0) 74148104Syokota return 0; 74248104Syokota 74348104Syokota /* 74448104Syokota * If any buttons are down or the mouse has moved a lot, 74548104Syokota * stop the screen saver. 74648104Syokota */ 74748104Syokota if (((mouse->operation == MOUSE_ACTION) && mouse->u.data.buttons) 74848104Syokota || (mouse->u.data.x*mouse->u.data.x 74948104Syokota + mouse->u.data.y*mouse->u.data.y 75048104Syokota >= SC_WAKEUP_DELTA*SC_WAKEUP_DELTA)) { 75148104Syokota sc_touch_scrn_saver(); 75248104Syokota } 75348104Syokota 75458872Syokota cur_scp->status &= ~MOUSE_HIDDEN; 75554182Syokota 75654182Syokota if (cur_scp->mouse_signal) { 75754182Syokota /* has controlling process died? */ 75854182Syokota if (cur_scp->mouse_proc && 75954182Syokota (cur_scp->mouse_proc != pfind(cur_scp->mouse_pid))){ 76054182Syokota cur_scp->mouse_signal = 0; 76154182Syokota cur_scp->mouse_proc = NULL; 76254182Syokota cur_scp->mouse_pid = 0; 76354182Syokota } else { 76454182Syokota psignal(cur_scp->mouse_proc, cur_scp->mouse_signal); 76554182Syokota break; 76654182Syokota } 76754182Syokota } 76854182Syokota 76948104Syokota if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL)) 77048104Syokota break; 77148104Syokota 77248104Syokota#ifndef SC_NO_CUTPASTE 77353057Syokota if ((mouse->operation == MOUSE_ACTION) && f) { 77448104Syokota /* process button presses */ 77553057Syokota if (cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN) 77653057Syokota mouse_cut_start(cur_scp); 77753057Syokota else 77853057Syokota mouse_cut_end(cur_scp); 77953057Syokota if (cur_scp->mouse_buttons & MOUSE_BUTTON2DOWN || 78053057Syokota cur_scp->mouse_buttons & MOUSE_BUTTON3DOWN) 78153057Syokota mouse_paste(cur_scp); 78248104Syokota } 78348104Syokota#endif /* SC_NO_CUTPASTE */ 78448104Syokota break; 78548104Syokota 78648104Syokota case MOUSE_BUTTON_EVENT: 78748104Syokota if ((mouse->u.event.id & MOUSE_BUTTONS) == 0) 78848104Syokota return EINVAL; 78948104Syokota if (mouse->u.event.value < 0) 79048104Syokota return EINVAL; 79148104Syokota#if 0 79248104Syokota /* this should maybe only be settable from /dev/consolectl SOS */ 79348104Syokota if (SC_VTY(tp->t_dev) != SC_CONSOLECTL) 79448104Syokota return ENOTTY; 79548104Syokota#endif 79656043Syokota if (mouse->u.event.value > 0) 79748104Syokota cur_scp->mouse_buttons |= mouse->u.event.id; 79856043Syokota else 79948104Syokota cur_scp->mouse_buttons &= ~mouse->u.event.id; 80056043Syokota 80156043Syokota if (sysmouse_event(mouse) == 0) 80248104Syokota return 0; 80348104Syokota 80454182Syokota /* if a button is held down, stop the screen saver */ 80554182Syokota if (mouse->u.event.value > 0) 80654182Syokota sc_touch_scrn_saver(); 80754182Syokota 80858872Syokota cur_scp->status &= ~MOUSE_HIDDEN; 80954182Syokota 81048104Syokota if (cur_scp->mouse_signal) { 81148104Syokota if (cur_scp->mouse_proc && 81248104Syokota (cur_scp->mouse_proc != pfind(cur_scp->mouse_pid))){ 81348104Syokota cur_scp->mouse_signal = 0; 81448104Syokota cur_scp->mouse_proc = NULL; 81548104Syokota cur_scp->mouse_pid = 0; 81654182Syokota } else { 81754182Syokota psignal(cur_scp->mouse_proc, cur_scp->mouse_signal); 81854182Syokota break; 81948104Syokota } 82048104Syokota } 82148104Syokota 82248104Syokota if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL)) 82348104Syokota break; 82448104Syokota 82548104Syokota#ifndef SC_NO_CUTPASTE 82648104Syokota switch (mouse->u.event.id) { 82748104Syokota case MOUSE_BUTTON1DOWN: 82848104Syokota switch (mouse->u.event.value % 4) { 82948104Syokota case 0: /* up */ 83048104Syokota mouse_cut_end(cur_scp); 83148104Syokota break; 83248104Syokota case 1: /* single click: start cut operation */ 83348104Syokota mouse_cut_start(cur_scp); 83448104Syokota break; 83548104Syokota case 2: /* double click: cut a word */ 83648104Syokota mouse_cut_word(cur_scp); 83748104Syokota mouse_cut_end(cur_scp); 83848104Syokota break; 83948104Syokota case 3: /* triple click: cut a line */ 84048104Syokota mouse_cut_line(cur_scp); 84148104Syokota mouse_cut_end(cur_scp); 84248104Syokota break; 84348104Syokota } 84448104Syokota break; 84553011Syokota case SC_MOUSE_PASTEBUTTON: 84648104Syokota switch (mouse->u.event.value) { 84748104Syokota case 0: /* up */ 84848104Syokota break; 84948104Syokota default: 85048104Syokota mouse_paste(cur_scp); 85148104Syokota break; 85248104Syokota } 85348104Syokota break; 85453011Syokota case SC_MOUSE_EXTENDBUTTON: 85548104Syokota switch (mouse->u.event.value) { 85648104Syokota case 0: /* up */ 85748104Syokota if (!(cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN)) 85848104Syokota mouse_cut_end(cur_scp); 85948104Syokota break; 86048104Syokota default: 86148104Syokota mouse_cut_extend(cur_scp); 86248104Syokota break; 86348104Syokota } 86448104Syokota break; 86548104Syokota } 86648104Syokota#endif /* SC_NO_CUTPASTE */ 86748104Syokota break; 86848104Syokota 86955849Syokota case MOUSE_MOUSECHAR: 87055849Syokota if (mouse->u.mouse_char < 0) { 87155849Syokota mouse->u.mouse_char = scp->sc->mouse_char; 87255849Syokota } else { 87355849Syokota if (mouse->u.mouse_char >= UCHAR_MAX - 4) 87455849Syokota return EINVAL; 87556043Syokota s = spltty(); 87655849Syokota sc_remove_all_mouse(scp->sc); 87755849Syokota#ifndef SC_NO_FONT_LOADING 87856328Syokota if (ISTEXTSC(cur_scp) && (cur_scp->font != NULL)) 87956043Syokota sc_load_font(cur_scp, 0, cur_scp->font_size, cur_scp->font, 88056043Syokota cur_scp->sc->mouse_char, 4); 88155849Syokota#endif 88255849Syokota scp->sc->mouse_char = mouse->u.mouse_char; 88355849Syokota splx(s); 88455849Syokota } 88555849Syokota break; 88655849Syokota 88748104Syokota default: 88848104Syokota return EINVAL; 88948104Syokota } 89048104Syokota 89148104Syokota return 0; 89248104Syokota } 89348104Syokota 89448104Syokota return ENOIOCTL; 89548104Syokota} 89648104Syokota 89748104Syokota#endif /* SC_NO_SYSMOUSE */ 898