mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-24 11:29:10 +00:00
6e8394b8ba
- Split syscons source code into manageable chunks and reorganize some of complicated functions. - Many static variables are moved to the softc structure. - Added a new key function, PREV. When this key is pressed, the vty immediately before the current vty will become foreground. Analogue to PREV, which is usually assigned to the PrntScrn key. PR: kern/10113 Submitted by: Christian Weisgerber <naddy@mips.rhein-neckar.de> - Modified the kernel console input function sccngetc() so that it handles function keys properly. - Reorganized the screen update routine. - VT switching code is reorganized. It now should be slightly more robust than before. - Added the DEVICE_RESUME function so that syscons no longer hooks the APM resume event directly. - New kernel configuration options: SC_NO_CUTPASTE, SC_NO_FONT_LOADING, SC_NO_HISTORY and SC_NO_SYSMOUSE. Various parts of syscons can be omitted so that the kernel size is reduced. SC_PIXEL_MODE Made the VESA 800x600 mode an option, rather than a standard part of syscons. SC_DISABLE_DDBKEY Disables the `debug' key combination. SC_ALT_MOUSE_IMAGE Inverse the character cell at the mouse cursor position in the text console, rather than drawing an arrow on the screen. Submitted by: Nick Hibma (n_hibma@FreeBSD.ORG) SC_DFLT_FONT makeoptions "SC_DFLT_FONT=_font_name_" Include the named font as the default font of syscons. 16-line, 14-line and 8-line font data will be compiled in. This option replaces the existing STD8X16FONT option, which loads 16-line font data only. - The VGA driver is split into /sys/dev/fb/vga.c and /sys/isa/vga_isa.c. - The video driver provides a set of ioctl commands to manipulate the frame buffer. - New kernel configuration option: VGA_WIDTH90 Enables 90 column modes: 90x25, 90x30, 90x43, 90x50, 90x60. These modes are mot always supported by the video card. PR: i386/7510 Submitted by: kbyanc@freedomnet.com and alexv@sui.gda.itesm.mx. - The header file machine/console.h is reorganized; its contents is now split into sys/fbio.h, sys/kbio.h (a new file) and sys/consio.h (another new file). machine/console.h is still maintained for compatibility reasons. - Kernel console selection/installation routines are fixed and slightly rebumped so that it should now be possible to switch between the interanl kernel console (sc or vt) and a remote kernel console (sio) again, as it was in 2.x, 3.0 and 3.1. - Screen savers and splash screen decoders Because of the header file reorganization described above, screen savers and splash screen decoders are slightly modified. After this update, /sys/modules/syscons/saver.h is no longer necessary and is removed.
1084 lines
27 KiB
C
1084 lines
27 KiB
C
/*-
|
|
* Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
|
|
* All rights reserved.
|
|
*
|
|
* 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 as
|
|
* the first lines of this file unmodified.
|
|
* 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.
|
|
*
|
|
* 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.
|
|
*
|
|
* $Id:$
|
|
*/
|
|
|
|
#include "sc.h"
|
|
#include "opt_syscons.h"
|
|
|
|
#if NSC > 0
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/systm.h>
|
|
#include <sys/conf.h>
|
|
#include <sys/signalvar.h>
|
|
#include <sys/proc.h>
|
|
#include <sys/tty.h>
|
|
#include <sys/kernel.h>
|
|
#include <sys/malloc.h>
|
|
|
|
#include <machine/console.h>
|
|
#include <machine/mouse.h>
|
|
|
|
#include <dev/syscons/syscons.h>
|
|
|
|
#define SC_WAKEUP_DELTA 20
|
|
|
|
/* for backward compatibility */
|
|
#define OLD_CONS_MOUSECTL _IOWR('c', 10, old_mouse_info_t)
|
|
|
|
typedef struct old_mouse_data {
|
|
int x;
|
|
int y;
|
|
int buttons;
|
|
} old_mouse_data_t;
|
|
|
|
typedef struct old_mouse_info {
|
|
int operation;
|
|
union {
|
|
struct old_mouse_data data;
|
|
struct mouse_mode mode;
|
|
} u;
|
|
} old_mouse_info_t;
|
|
|
|
/* local variables */
|
|
#ifndef SC_NO_SYSMOUSE
|
|
static int mouse_level; /* sysmouse protocol level */
|
|
static mousestatus_t mouse_status = { 0, 0, 0, 0, 0, 0 };
|
|
static int cut_buffer_size;
|
|
static u_char *cut_buffer;
|
|
#endif /* SC_NO_SYSMOUE */
|
|
|
|
/* local functions */
|
|
#ifndef SC_NO_SYSMOUSE
|
|
static void set_mouse_pos(scr_stat *scp);
|
|
#ifndef SC_NO_CUTPASTE
|
|
static int skip_spc_right(scr_stat *scp, int p);
|
|
static int skip_spc_left(scr_stat *scp, int p);
|
|
static void mouse_cut(scr_stat *scp);
|
|
static void mouse_cut_start(scr_stat *scp);
|
|
static void mouse_cut_end(scr_stat *scp);
|
|
static void mouse_cut_word(scr_stat *scp);
|
|
static void mouse_cut_line(scr_stat *scp);
|
|
static void mouse_cut_extend(scr_stat *scp);
|
|
static void mouse_paste(scr_stat *scp);
|
|
#endif /* SC_NO_CUTPASTE */
|
|
#endif /* SC_NO_SYSMOUE */
|
|
|
|
#ifndef SC_NO_CUTPASTE
|
|
/* allocate a cut buffer */
|
|
void
|
|
sc_alloc_cut_buffer(scr_stat *scp, int wait)
|
|
{
|
|
u_char *p;
|
|
|
|
if ((cut_buffer == NULL)
|
|
|| (cut_buffer_size < scp->xsize * scp->ysize + 1)) {
|
|
p = cut_buffer;
|
|
cut_buffer = NULL;
|
|
if (p != NULL)
|
|
free(p, M_DEVBUF);
|
|
cut_buffer_size = scp->xsize * scp->ysize + 1;
|
|
p = (u_char *)malloc(cut_buffer_size,
|
|
M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT);
|
|
if (p != NULL)
|
|
p[0] = '\0';
|
|
cut_buffer = p;
|
|
}
|
|
}
|
|
#endif /* SC_NO_CUTPASTE */
|
|
|
|
#ifndef SC_NO_SYSMOUSE
|
|
|
|
/* modify the sysmouse software level */
|
|
void
|
|
sc_mouse_set_level(int level)
|
|
{
|
|
mouse_level = level;
|
|
}
|
|
|
|
/* move mouse */
|
|
void
|
|
sc_mouse_move(scr_stat *scp, int x, int y)
|
|
{
|
|
int s;
|
|
|
|
s = spltty();
|
|
scp->mouse_xpos = x;
|
|
scp->mouse_ypos = y;
|
|
scp->mouse_pos = scp->mouse_oldpos =
|
|
(y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
|
|
splx(s);
|
|
}
|
|
|
|
/* adjust mouse position */
|
|
static void
|
|
set_mouse_pos(scr_stat *scp)
|
|
{
|
|
static int last_xpos = -1, last_ypos = -1;
|
|
|
|
if (scp->mouse_xpos < scp->xoff*8)
|
|
scp->mouse_xpos = scp->xoff*8;
|
|
if (scp->mouse_ypos < scp->yoff*scp->font_size)
|
|
scp->mouse_ypos = scp->yoff*scp->font_size;
|
|
if (ISGRAPHSC(scp)) {
|
|
if (scp->mouse_xpos > scp->xpixel-1)
|
|
scp->mouse_xpos = scp->xpixel-1;
|
|
if (scp->mouse_ypos > scp->ypixel-1)
|
|
scp->mouse_ypos = scp->ypixel-1;
|
|
return;
|
|
} else {
|
|
if (scp->mouse_xpos > (scp->xsize + scp->xoff)*8 - 1)
|
|
scp->mouse_xpos = (scp->xsize + scp->xoff)*8 - 1;
|
|
if (scp->mouse_ypos > (scp->ysize + scp->yoff)*scp->font_size - 1)
|
|
scp->mouse_ypos = (scp->ysize + scp->yoff)*scp->font_size - 1;
|
|
}
|
|
|
|
if (scp->mouse_xpos != last_xpos || scp->mouse_ypos != last_ypos) {
|
|
scp->status |= MOUSE_MOVED;
|
|
scp->mouse_pos =
|
|
(scp->mouse_ypos/scp->font_size - scp->yoff)*scp->xsize
|
|
+ scp->mouse_xpos/8 - scp->xoff;
|
|
#ifndef SC_NO_CUTPASTE
|
|
if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING))
|
|
mouse_cut(scp);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#ifndef SC_NO_CUTPASTE
|
|
|
|
void
|
|
sc_draw_mouse_image(scr_stat *scp)
|
|
{
|
|
if (ISGRAPHSC(scp))
|
|
return;
|
|
|
|
++scp->sc->videoio_in_progress;
|
|
(*scp->rndr->draw_mouse)(scp, scp->mouse_xpos, scp->mouse_ypos, TRUE);
|
|
scp->mouse_oldpos = scp->mouse_pos;
|
|
--scp->sc->videoio_in_progress;
|
|
}
|
|
|
|
void
|
|
sc_remove_mouse_image(scr_stat *scp)
|
|
{
|
|
int size;
|
|
int i;
|
|
|
|
if (ISGRAPHSC(scp))
|
|
return;
|
|
|
|
++scp->sc->videoio_in_progress;
|
|
(*scp->rndr->draw_mouse)(scp,
|
|
(scp->mouse_oldpos%scp->xsize + scp->xoff)*8,
|
|
(scp->mouse_oldpos/scp->xsize + scp->yoff)
|
|
* scp->font_size,
|
|
FALSE);
|
|
size = scp->xsize*scp->ysize;
|
|
i = scp->mouse_oldpos;
|
|
mark_for_update(scp, i);
|
|
mark_for_update(scp, i);
|
|
#ifndef PC98
|
|
if (i + scp->xsize + 1 < size) {
|
|
mark_for_update(scp, i + scp->xsize + 1);
|
|
} else if (i + scp->xsize < size) {
|
|
mark_for_update(scp, i + scp->xsize);
|
|
} else if (i + 1 < size) {
|
|
mark_for_update(scp, i + 1);
|
|
}
|
|
#endif /* PC98 */
|
|
--scp->sc->videoio_in_progress;
|
|
}
|
|
|
|
int
|
|
sc_inside_cutmark(scr_stat *scp, int pos)
|
|
{
|
|
int start;
|
|
int end;
|
|
|
|
if (scp->mouse_cut_end < 0)
|
|
return FALSE;
|
|
if (scp->mouse_cut_start <= scp->mouse_cut_end) {
|
|
start = scp->mouse_cut_start;
|
|
end = scp->mouse_cut_end;
|
|
} else {
|
|
start = scp->mouse_cut_end;
|
|
end = scp->mouse_cut_start - 1;
|
|
}
|
|
return ((start <= pos) && (pos <= end));
|
|
}
|
|
|
|
void
|
|
sc_remove_cutmarking(scr_stat *scp)
|
|
{
|
|
int s;
|
|
|
|
s = spltty();
|
|
if (scp->mouse_cut_end >= 0) {
|
|
mark_for_update(scp, scp->mouse_cut_start);
|
|
mark_for_update(scp, scp->mouse_cut_end);
|
|
}
|
|
scp->mouse_cut_start = scp->xsize*scp->ysize;
|
|
scp->mouse_cut_end = -1;
|
|
splx(s);
|
|
scp->status &= ~MOUSE_CUTTING;
|
|
}
|
|
|
|
void
|
|
sc_remove_all_cutmarkings(sc_softc_t *sc)
|
|
{
|
|
int i;
|
|
|
|
/* delete cut markings in all vtys */
|
|
for (i = 0; i < sc->vtys; ++i) {
|
|
if (sc->console[i] == NULL)
|
|
continue;
|
|
sc_remove_cutmarking(sc->console[i]);
|
|
}
|
|
}
|
|
|
|
void
|
|
sc_remove_all_mouse(sc_softc_t *sc)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < sc->vtys; ++i) {
|
|
if (sc->console[i] == NULL)
|
|
continue;
|
|
if (sc->console[i]->status & MOUSE_VISIBLE) {
|
|
sc->console[i]->status &= ~MOUSE_VISIBLE;
|
|
mark_all(sc->console[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
#define isspace(c) (((c) & 0xff) == ' ')
|
|
|
|
/* skip spaces to right */
|
|
static int
|
|
skip_spc_right(scr_stat *scp, int p)
|
|
{
|
|
int c;
|
|
int i;
|
|
|
|
for (i = p % scp->xsize; i < scp->xsize; ++i) {
|
|
c = sc_vtb_getc(&scp->vtb, p);
|
|
if (!isspace(c))
|
|
break;
|
|
++p;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
/* skip spaces to left */
|
|
static int
|
|
skip_spc_left(scr_stat *scp, int p)
|
|
{
|
|
int c;
|
|
int i;
|
|
|
|
for (i = p-- % scp->xsize - 1; i >= 0; --i) {
|
|
c = sc_vtb_getc(&scp->vtb, p);
|
|
if (!isspace(c))
|
|
break;
|
|
--p;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
/* copy marked region to the cut buffer */
|
|
static void
|
|
mouse_cut(scr_stat *scp)
|
|
{
|
|
int start;
|
|
int end;
|
|
int from;
|
|
int to;
|
|
int blank;
|
|
int c;
|
|
int p;
|
|
int s;
|
|
int i;
|
|
|
|
start = scp->mouse_cut_start;
|
|
end = scp->mouse_cut_end;
|
|
if (scp->mouse_pos >= start) {
|
|
from = start;
|
|
to = end = scp->mouse_pos;
|
|
} else {
|
|
from = end = scp->mouse_pos;
|
|
to = start - 1;
|
|
}
|
|
for (p = from, i = blank = 0; p <= to; ++p) {
|
|
cut_buffer[i] = sc_vtb_getc(&scp->vtb, p);
|
|
/* remember the position of the last non-space char */
|
|
if (!isspace(cut_buffer[i++]))
|
|
blank = i; /* the first space after the last non-space */
|
|
/* trim trailing blank when crossing lines */
|
|
if ((p % scp->xsize) == (scp->xsize - 1)) {
|
|
cut_buffer[blank] = '\r';
|
|
i = blank + 1;
|
|
}
|
|
}
|
|
cut_buffer[i] = '\0';
|
|
|
|
/* scan towards the end of the last line */
|
|
--p;
|
|
for (i = p % scp->xsize; i < scp->xsize; ++i) {
|
|
c = sc_vtb_getc(&scp->vtb, p);
|
|
if (!isspace(c))
|
|
break;
|
|
++p;
|
|
}
|
|
/* if there is nothing but blank chars, trim them, but mark towards eol */
|
|
if (i >= scp->xsize) {
|
|
if (end >= start)
|
|
to = end = p - 1;
|
|
else
|
|
to = start = p;
|
|
cut_buffer[blank++] = '\r';
|
|
cut_buffer[blank] = '\0';
|
|
}
|
|
|
|
/* remove the current marking */
|
|
s = spltty();
|
|
if (scp->mouse_cut_start <= scp->mouse_cut_end) {
|
|
mark_for_update(scp, scp->mouse_cut_start);
|
|
mark_for_update(scp, scp->mouse_cut_end);
|
|
} else if (scp->mouse_cut_end >= 0) {
|
|
mark_for_update(scp, scp->mouse_cut_end);
|
|
mark_for_update(scp, scp->mouse_cut_start);
|
|
}
|
|
|
|
/* mark the new region */
|
|
scp->mouse_cut_start = start;
|
|
scp->mouse_cut_end = end;
|
|
mark_for_update(scp, from);
|
|
mark_for_update(scp, to);
|
|
splx(s);
|
|
}
|
|
|
|
/* a mouse button is pressed, start cut operation */
|
|
static void
|
|
mouse_cut_start(scr_stat *scp)
|
|
{
|
|
int i;
|
|
int j;
|
|
int s;
|
|
|
|
if (scp->status & MOUSE_VISIBLE) {
|
|
i = scp->mouse_cut_start;
|
|
j = scp->mouse_cut_end;
|
|
sc_remove_all_cutmarkings(scp->sc);
|
|
if (scp->mouse_pos == i && i == j) {
|
|
cut_buffer[0] = '\0';
|
|
} else if (skip_spc_right(scp, scp->mouse_pos) >= scp->xsize) {
|
|
/* if the pointer is on trailing blank chars, mark towards eol */
|
|
i = skip_spc_left(scp, scp->mouse_pos) + 1;
|
|
s = spltty();
|
|
scp->mouse_cut_start =
|
|
(scp->mouse_pos / scp->xsize) * scp->xsize + i;
|
|
scp->mouse_cut_end =
|
|
(scp->mouse_pos / scp->xsize + 1) * scp->xsize - 1;
|
|
splx(s);
|
|
cut_buffer[0] = '\r';
|
|
cut_buffer[1] = '\0';
|
|
scp->status |= MOUSE_CUTTING;
|
|
} else {
|
|
s = spltty();
|
|
scp->mouse_cut_start = scp->mouse_pos;
|
|
scp->mouse_cut_end = scp->mouse_cut_start;
|
|
splx(s);
|
|
cut_buffer[0] = sc_vtb_getc(&scp->vtb, scp->mouse_cut_start);
|
|
cut_buffer[1] = '\0';
|
|
scp->status |= MOUSE_CUTTING;
|
|
}
|
|
mark_all(scp); /* this is probably overkill XXX */
|
|
}
|
|
}
|
|
|
|
/* end of cut operation */
|
|
static void
|
|
mouse_cut_end(scr_stat *scp)
|
|
{
|
|
if (scp->status & MOUSE_VISIBLE)
|
|
scp->status &= ~MOUSE_CUTTING;
|
|
}
|
|
|
|
/* copy a word under the mouse pointer */
|
|
static void
|
|
mouse_cut_word(scr_stat *scp)
|
|
{
|
|
int start;
|
|
int end;
|
|
int sol;
|
|
int eol;
|
|
int c;
|
|
int s;
|
|
int i;
|
|
int j;
|
|
|
|
/*
|
|
* Because we don't have locale information in the kernel,
|
|
* we only distinguish space char and non-space chars. Punctuation
|
|
* chars, symbols and other regular chars are all treated alike.
|
|
*/
|
|
if (scp->status & MOUSE_VISIBLE) {
|
|
/* remove the current cut mark */
|
|
s = spltty();
|
|
if (scp->mouse_cut_start <= scp->mouse_cut_end) {
|
|
mark_for_update(scp, scp->mouse_cut_start);
|
|
mark_for_update(scp, scp->mouse_cut_end);
|
|
} else if (scp->mouse_cut_end >= 0) {
|
|
mark_for_update(scp, scp->mouse_cut_end);
|
|
mark_for_update(scp, scp->mouse_cut_start);
|
|
}
|
|
scp->mouse_cut_start = scp->xsize*scp->ysize;
|
|
scp->mouse_cut_end = -1;
|
|
splx(s);
|
|
|
|
sol = (scp->mouse_pos / scp->xsize) * scp->xsize;
|
|
eol = sol + scp->xsize;
|
|
c = sc_vtb_getc(&scp->vtb, scp->mouse_pos);
|
|
if (isspace(c)) {
|
|
/* blank space */
|
|
for (j = scp->mouse_pos; j >= sol; --j) {
|
|
c = sc_vtb_getc(&scp->vtb, j);
|
|
if (!isspace(c))
|
|
break;
|
|
}
|
|
start = ++j;
|
|
for (j = scp->mouse_pos; j < eol; ++j) {
|
|
c = sc_vtb_getc(&scp->vtb, j);
|
|
if (!isspace(c))
|
|
break;
|
|
}
|
|
end = j - 1;
|
|
} else {
|
|
/* non-space word */
|
|
for (j = scp->mouse_pos; j >= sol; --j) {
|
|
c = sc_vtb_getc(&scp->vtb, j);
|
|
if (isspace(c))
|
|
break;
|
|
}
|
|
start = ++j;
|
|
for (j = scp->mouse_pos; j < eol; ++j) {
|
|
c = sc_vtb_getc(&scp->vtb, j);
|
|
if (isspace(c))
|
|
break;
|
|
}
|
|
end = j - 1;
|
|
}
|
|
|
|
/* copy the found word */
|
|
for (i = 0, j = start; j <= end; ++j)
|
|
cut_buffer[i++] = sc_vtb_getc(&scp->vtb, j);
|
|
cut_buffer[i] = '\0';
|
|
scp->status |= MOUSE_CUTTING;
|
|
|
|
/* mark the region */
|
|
s = spltty();
|
|
scp->mouse_cut_start = start;
|
|
scp->mouse_cut_end = end;
|
|
mark_for_update(scp, start);
|
|
mark_for_update(scp, end);
|
|
splx(s);
|
|
}
|
|
}
|
|
|
|
/* copy a line under the mouse pointer */
|
|
static void
|
|
mouse_cut_line(scr_stat *scp)
|
|
{
|
|
int s;
|
|
int i;
|
|
int j;
|
|
|
|
if (scp->status & MOUSE_VISIBLE) {
|
|
/* remove the current cut mark */
|
|
s = spltty();
|
|
if (scp->mouse_cut_start <= scp->mouse_cut_end) {
|
|
mark_for_update(scp, scp->mouse_cut_start);
|
|
mark_for_update(scp, scp->mouse_cut_end);
|
|
} else if (scp->mouse_cut_end >= 0) {
|
|
mark_for_update(scp, scp->mouse_cut_end);
|
|
mark_for_update(scp, scp->mouse_cut_start);
|
|
}
|
|
|
|
/* mark the entire line */
|
|
scp->mouse_cut_start =
|
|
(scp->mouse_pos / scp->xsize) * scp->xsize;
|
|
scp->mouse_cut_end = scp->mouse_cut_start + scp->xsize - 1;
|
|
mark_for_update(scp, scp->mouse_cut_start);
|
|
mark_for_update(scp, scp->mouse_cut_end);
|
|
splx(s);
|
|
|
|
/* copy the line into the cut buffer */
|
|
for (i = 0, j = scp->mouse_cut_start; j <= scp->mouse_cut_end; ++j)
|
|
cut_buffer[i++] = sc_vtb_getc(&scp->vtb, j);
|
|
cut_buffer[i++] = '\r';
|
|
cut_buffer[i] = '\0';
|
|
scp->status |= MOUSE_CUTTING;
|
|
}
|
|
}
|
|
|
|
/* extend the marked region to the mouse pointer position */
|
|
static void
|
|
mouse_cut_extend(scr_stat *scp)
|
|
{
|
|
int start;
|
|
int end;
|
|
int s;
|
|
|
|
if ((scp->status & MOUSE_VISIBLE) && !(scp->status & MOUSE_CUTTING)
|
|
&& (scp->mouse_cut_end >= 0)) {
|
|
if (scp->mouse_cut_start <= scp->mouse_cut_end) {
|
|
start = scp->mouse_cut_start;
|
|
end = scp->mouse_cut_end;
|
|
} else {
|
|
start = scp->mouse_cut_end;
|
|
end = scp->mouse_cut_start - 1;
|
|
}
|
|
s = spltty();
|
|
if (scp->mouse_pos > end) {
|
|
scp->mouse_cut_start = start;
|
|
scp->mouse_cut_end = end;
|
|
} else if (scp->mouse_pos < start) {
|
|
scp->mouse_cut_start = end + 1;
|
|
scp->mouse_cut_end = start;
|
|
} else {
|
|
if (scp->mouse_pos - start > end + 1 - scp->mouse_pos) {
|
|
scp->mouse_cut_start = start;
|
|
scp->mouse_cut_end = end;
|
|
} else {
|
|
scp->mouse_cut_start = end + 1;
|
|
scp->mouse_cut_end = start;
|
|
}
|
|
}
|
|
splx(s);
|
|
mouse_cut(scp);
|
|
scp->status |= MOUSE_CUTTING;
|
|
}
|
|
}
|
|
|
|
/* paste cut buffer contents into the current vty */
|
|
static void
|
|
mouse_paste(scr_stat *scp)
|
|
{
|
|
if (scp->status & MOUSE_VISIBLE)
|
|
sc_paste(scp, cut_buffer, strlen(cut_buffer));
|
|
}
|
|
|
|
#endif /* SC_NO_CUTPASTE */
|
|
|
|
int
|
|
sc_mouse_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag,
|
|
struct proc *p)
|
|
{
|
|
|
|
scr_stat *scp;
|
|
int s;
|
|
int i;
|
|
|
|
/* scp == NULL, if tp == sc_get_mouse_tty() (/dev/sysmouse) */
|
|
scp = sc_get_scr_stat(tp->t_dev);
|
|
|
|
switch (cmd) {
|
|
|
|
case CONS_MOUSECTL: /* control mouse arrow */
|
|
case OLD_CONS_MOUSECTL:
|
|
{
|
|
/* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */
|
|
static int butmap[8] = {
|
|
MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP,
|
|
MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP,
|
|
MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP,
|
|
MOUSE_MSC_BUTTON3UP,
|
|
MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP,
|
|
MOUSE_MSC_BUTTON2UP,
|
|
MOUSE_MSC_BUTTON1UP,
|
|
0,
|
|
};
|
|
mouse_info_t *mouse = (mouse_info_t*)data;
|
|
mouse_info_t buf;
|
|
scr_stat *cur_scp;
|
|
struct tty *mtty;
|
|
|
|
if (scp == NULL)
|
|
return ENOTTY;
|
|
|
|
if (cmd == OLD_CONS_MOUSECTL) {
|
|
static u_char swapb[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
|
|
old_mouse_info_t *old_mouse = (old_mouse_info_t *)data;
|
|
|
|
mouse = &buf;
|
|
mouse->operation = old_mouse->operation;
|
|
switch (mouse->operation) {
|
|
case MOUSE_MODE:
|
|
mouse->u.mode = old_mouse->u.mode;
|
|
break;
|
|
case MOUSE_SHOW:
|
|
case MOUSE_HIDE:
|
|
break;
|
|
case MOUSE_MOVEABS:
|
|
case MOUSE_MOVEREL:
|
|
case MOUSE_ACTION:
|
|
mouse->u.data.x = old_mouse->u.data.x;
|
|
mouse->u.data.y = old_mouse->u.data.y;
|
|
mouse->u.data.z = 0;
|
|
mouse->u.data.buttons = swapb[old_mouse->u.data.buttons & 0x7];
|
|
break;
|
|
case MOUSE_GETINFO:
|
|
old_mouse->u.data.x = scp->mouse_xpos;
|
|
old_mouse->u.data.y = scp->mouse_ypos;
|
|
old_mouse->u.data.buttons = swapb[scp->mouse_buttons & 0x7];
|
|
break;
|
|
default:
|
|
return EINVAL;
|
|
}
|
|
}
|
|
|
|
cur_scp = scp->sc->cur_scp;
|
|
|
|
switch (mouse->operation) {
|
|
case MOUSE_MODE:
|
|
if (ISSIGVALID(mouse->u.mode.signal)) {
|
|
scp->mouse_signal = mouse->u.mode.signal;
|
|
scp->mouse_proc = p;
|
|
scp->mouse_pid = p->p_pid;
|
|
}
|
|
else {
|
|
scp->mouse_signal = 0;
|
|
scp->mouse_proc = NULL;
|
|
scp->mouse_pid = 0;
|
|
}
|
|
return 0;
|
|
|
|
case MOUSE_SHOW:
|
|
if (!ISMOUSEAVAIL(scp->sc->adp->va_flags))
|
|
return EINVAL;
|
|
s = spltty();
|
|
if (!(scp->sc->flags & SC_MOUSE_ENABLED)) {
|
|
scp->sc->flags |= SC_MOUSE_ENABLED;
|
|
if (!ISGRAPHSC(cur_scp)) {
|
|
cur_scp->status |= MOUSE_VISIBLE;
|
|
mark_all(cur_scp);
|
|
}
|
|
splx(s);
|
|
return 0;
|
|
} else {
|
|
splx(s);
|
|
return EINVAL;
|
|
}
|
|
break;
|
|
#if 0
|
|
if (!(scp->status & MOUSE_ENABLED)) {
|
|
scp->mouse_oldpos = scp->mouse_pos;
|
|
scp->status |= MOUSE_ENABLED;
|
|
if (!ISGRAPHSC(scp))
|
|
scp->status |= MOUSE_VISIBLE;
|
|
splx(s);
|
|
mark_all(scp);
|
|
return 0;
|
|
} else {
|
|
splx(s);
|
|
return EINVAL;
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case MOUSE_HIDE:
|
|
s = spltty();
|
|
if (scp->sc->flags & SC_MOUSE_ENABLED) {
|
|
scp->sc->flags &= ~SC_MOUSE_ENABLED;
|
|
sc_remove_all_mouse(scp->sc);
|
|
splx(s);
|
|
return 0;
|
|
} else {
|
|
splx(s);
|
|
return EINVAL;
|
|
}
|
|
break;
|
|
#if 0
|
|
if (scp->status & MOUSE_ENABLED) {
|
|
scp->status &= ~(MOUSE_ENABLED | MOUSE_VISIBLE);
|
|
mark_all(scp);
|
|
splx(s);
|
|
return 0;
|
|
} else {
|
|
splx(s);
|
|
return EINVAL;
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case MOUSE_MOVEABS:
|
|
s = spltty();
|
|
scp->mouse_xpos = mouse->u.data.x;
|
|
scp->mouse_ypos = mouse->u.data.y;
|
|
set_mouse_pos(scp);
|
|
splx(s);
|
|
break;
|
|
|
|
case MOUSE_MOVEREL:
|
|
s = spltty();
|
|
scp->mouse_xpos += mouse->u.data.x;
|
|
scp->mouse_ypos += mouse->u.data.y;
|
|
set_mouse_pos(scp);
|
|
splx(s);
|
|
break;
|
|
|
|
case MOUSE_GETINFO:
|
|
mouse->u.data.x = scp->mouse_xpos;
|
|
mouse->u.data.y = scp->mouse_ypos;
|
|
mouse->u.data.z = 0;
|
|
mouse->u.data.buttons = scp->mouse_buttons;
|
|
return 0;
|
|
|
|
case MOUSE_ACTION:
|
|
case MOUSE_MOTION_EVENT:
|
|
/* send out mouse event on /dev/sysmouse */
|
|
#if 0
|
|
/* this should maybe only be settable from /dev/consolectl SOS */
|
|
if (SC_VTY(tp->t_dev) != SC_CONSOLECTL)
|
|
return ENOTTY;
|
|
#endif
|
|
mouse_status.dx += mouse->u.data.x;
|
|
mouse_status.dy += mouse->u.data.y;
|
|
mouse_status.dz += mouse->u.data.z;
|
|
if (mouse->operation == MOUSE_ACTION)
|
|
mouse_status.button = mouse->u.data.buttons;
|
|
mouse_status.flags |=
|
|
((mouse->u.data.x || mouse->u.data.y || mouse->u.data.z) ?
|
|
MOUSE_POSCHANGED : 0)
|
|
| (mouse_status.obutton ^ mouse_status.button);
|
|
if (mouse_status.flags == 0)
|
|
return 0;
|
|
|
|
mtty = sc_get_mouse_tty();
|
|
if (mtty->t_state & TS_ISOPEN) {
|
|
u_char buf[MOUSE_SYS_PACKETSIZE];
|
|
|
|
/* the first five bytes are compatible with MouseSystems' */
|
|
buf[0] = MOUSE_MSC_SYNC
|
|
| butmap[mouse_status.button & MOUSE_STDBUTTONS];
|
|
i = imax(imin(mouse->u.data.x, 255), -256);
|
|
buf[1] = i >> 1;
|
|
buf[3] = i - buf[1];
|
|
i = -imax(imin(mouse->u.data.y, 255), -256);
|
|
buf[2] = i >> 1;
|
|
buf[4] = i - buf[2];
|
|
for (i = 0; i < MOUSE_MSC_PACKETSIZE; i++)
|
|
(*linesw[mtty->t_line].l_rint)(buf[i], mtty);
|
|
if (mouse_level >= 1) { /* extended part */
|
|
i = imax(imin(mouse->u.data.z, 127), -128);
|
|
buf[5] = (i >> 1) & 0x7f;
|
|
buf[6] = (i - (i >> 1)) & 0x7f;
|
|
/* buttons 4-10 */
|
|
buf[7] = (~mouse_status.button >> 3) & 0x7f;
|
|
for (i = MOUSE_MSC_PACKETSIZE;
|
|
i < MOUSE_SYS_PACKETSIZE; i++)
|
|
(*linesw[mtty->t_line].l_rint)(buf[i], mtty);
|
|
}
|
|
}
|
|
|
|
if (cur_scp->mouse_signal) {
|
|
cur_scp->mouse_buttons = mouse->u.data.buttons;
|
|
/* has controlling process died? */
|
|
if (cur_scp->mouse_proc &&
|
|
(cur_scp->mouse_proc != pfind(cur_scp->mouse_pid))){
|
|
cur_scp->mouse_signal = 0;
|
|
cur_scp->mouse_proc = NULL;
|
|
cur_scp->mouse_pid = 0;
|
|
}
|
|
else
|
|
psignal(cur_scp->mouse_proc, cur_scp->mouse_signal);
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* If any buttons are down or the mouse has moved a lot,
|
|
* stop the screen saver.
|
|
*/
|
|
if (((mouse->operation == MOUSE_ACTION) && mouse->u.data.buttons)
|
|
|| (mouse->u.data.x*mouse->u.data.x
|
|
+ mouse->u.data.y*mouse->u.data.y
|
|
>= SC_WAKEUP_DELTA*SC_WAKEUP_DELTA)) {
|
|
sc_touch_scrn_saver();
|
|
}
|
|
|
|
if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL))
|
|
break;
|
|
|
|
#ifndef SC_NO_CUTPASTE
|
|
if (cur_scp->sc->flags & SC_MOUSE_ENABLED)
|
|
cur_scp->status |= MOUSE_VISIBLE;
|
|
|
|
if (mouse->operation == MOUSE_ACTION) {
|
|
/* process button presses */
|
|
if (cur_scp->mouse_buttons ^ mouse->u.data.buttons) {
|
|
cur_scp->mouse_buttons = mouse->u.data.buttons;
|
|
if (cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN)
|
|
mouse_cut_start(cur_scp);
|
|
else
|
|
mouse_cut_end(cur_scp);
|
|
if (cur_scp->mouse_buttons & MOUSE_BUTTON2DOWN ||
|
|
cur_scp->mouse_buttons & MOUSE_BUTTON3DOWN)
|
|
mouse_paste(cur_scp);
|
|
}
|
|
}
|
|
#else /* SC_NO_CUTPASTE */
|
|
if (mouse->operation == MOUSE_ACTION)
|
|
cur_scp->mouse_buttons = mouse->u.data.buttons;
|
|
#endif /* SC_NO_CUTPASTE */
|
|
|
|
if (mouse->u.data.x != 0 || mouse->u.data.y != 0) {
|
|
s = spltty();
|
|
cur_scp->mouse_xpos += mouse->u.data.x;
|
|
cur_scp->mouse_ypos += mouse->u.data.y;
|
|
set_mouse_pos(cur_scp);
|
|
splx(s);
|
|
}
|
|
break;
|
|
|
|
case MOUSE_BUTTON_EVENT:
|
|
if ((mouse->u.event.id & MOUSE_BUTTONS) == 0)
|
|
return EINVAL;
|
|
if (mouse->u.event.value < 0)
|
|
return EINVAL;
|
|
#if 0
|
|
/* this should maybe only be settable from /dev/consolectl SOS */
|
|
if (SC_VTY(tp->t_dev) != SC_CONSOLECTL)
|
|
return ENOTTY;
|
|
#endif
|
|
if (mouse->u.event.value > 0) {
|
|
cur_scp->mouse_buttons |= mouse->u.event.id;
|
|
mouse_status.button |= mouse->u.event.id;
|
|
} else {
|
|
cur_scp->mouse_buttons &= ~mouse->u.event.id;
|
|
mouse_status.button &= ~mouse->u.event.id;
|
|
}
|
|
mouse_status.flags |= mouse_status.obutton ^ mouse_status.button;
|
|
if (mouse_status.flags == 0)
|
|
return 0;
|
|
|
|
mtty = sc_get_mouse_tty();
|
|
if (mtty->t_state & TS_ISOPEN) {
|
|
u_char buf[MOUSE_SYS_PACKETSIZE];
|
|
|
|
buf[0] = MOUSE_MSC_SYNC
|
|
| butmap[mouse_status.button & MOUSE_STDBUTTONS];
|
|
buf[7] = (~mouse_status.button >> 3) & 0x7f;
|
|
buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0;
|
|
for (i = 0;
|
|
i < ((mouse_level >= 1) ? MOUSE_SYS_PACKETSIZE
|
|
: MOUSE_MSC_PACKETSIZE); i++)
|
|
(*linesw[mtty->t_line].l_rint)(buf[i], mtty);
|
|
}
|
|
|
|
if (cur_scp->mouse_signal) {
|
|
if (cur_scp->mouse_proc &&
|
|
(cur_scp->mouse_proc != pfind(cur_scp->mouse_pid))){
|
|
cur_scp->mouse_signal = 0;
|
|
cur_scp->mouse_proc = NULL;
|
|
cur_scp->mouse_pid = 0;
|
|
}
|
|
else
|
|
psignal(cur_scp->mouse_proc, cur_scp->mouse_signal);
|
|
break;
|
|
}
|
|
|
|
/* if a button is held down, stop the screen saver */
|
|
if (mouse->u.event.value > 0)
|
|
sc_touch_scrn_saver();
|
|
|
|
if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL))
|
|
break;
|
|
|
|
#ifndef SC_NO_CUTPASTE
|
|
if (cur_scp->sc->flags & SC_MOUSE_ENABLED)
|
|
cur_scp->status |= MOUSE_VISIBLE;
|
|
|
|
switch (mouse->u.event.id) {
|
|
case MOUSE_BUTTON1DOWN:
|
|
switch (mouse->u.event.value % 4) {
|
|
case 0: /* up */
|
|
mouse_cut_end(cur_scp);
|
|
break;
|
|
case 1: /* single click: start cut operation */
|
|
mouse_cut_start(cur_scp);
|
|
break;
|
|
case 2: /* double click: cut a word */
|
|
mouse_cut_word(cur_scp);
|
|
mouse_cut_end(cur_scp);
|
|
break;
|
|
case 3: /* triple click: cut a line */
|
|
mouse_cut_line(cur_scp);
|
|
mouse_cut_end(cur_scp);
|
|
break;
|
|
}
|
|
break;
|
|
case MOUSE_BUTTON2DOWN:
|
|
switch (mouse->u.event.value) {
|
|
case 0: /* up */
|
|
break;
|
|
default:
|
|
mouse_paste(cur_scp);
|
|
break;
|
|
}
|
|
break;
|
|
case MOUSE_BUTTON3DOWN:
|
|
switch (mouse->u.event.value) {
|
|
case 0: /* up */
|
|
if (!(cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN))
|
|
mouse_cut_end(cur_scp);
|
|
break;
|
|
default:
|
|
mouse_cut_extend(cur_scp);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
#endif /* SC_NO_CUTPASTE */
|
|
break;
|
|
|
|
default:
|
|
return EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* MOUSE_XXX: /dev/sysmouse ioctls */
|
|
case MOUSE_GETHWINFO: /* get device information */
|
|
{
|
|
mousehw_t *hw = (mousehw_t *)data;
|
|
|
|
if (tp != sc_get_mouse_tty())
|
|
return ENOTTY;
|
|
hw->buttons = 10; /* XXX unknown */
|
|
hw->iftype = MOUSE_IF_SYSMOUSE;
|
|
hw->type = MOUSE_MOUSE;
|
|
hw->model = MOUSE_MODEL_GENERIC;
|
|
hw->hwid = 0;
|
|
return 0;
|
|
}
|
|
|
|
case MOUSE_GETMODE: /* get protocol/mode */
|
|
{
|
|
mousemode_t *mode = (mousemode_t *)data;
|
|
|
|
if (tp != sc_get_mouse_tty())
|
|
return ENOTTY;
|
|
mode->level = mouse_level;
|
|
switch (mode->level) {
|
|
case 0:
|
|
/* at this level, sysmouse emulates MouseSystems protocol */
|
|
mode->protocol = MOUSE_PROTO_MSC;
|
|
mode->rate = -1; /* unknown */
|
|
mode->resolution = -1; /* unknown */
|
|
mode->accelfactor = 0; /* disabled */
|
|
mode->packetsize = MOUSE_MSC_PACKETSIZE;
|
|
mode->syncmask[0] = MOUSE_MSC_SYNCMASK;
|
|
mode->syncmask[1] = MOUSE_MSC_SYNC;
|
|
break;
|
|
|
|
case 1:
|
|
/* at this level, sysmouse uses its own protocol */
|
|
mode->protocol = MOUSE_PROTO_SYSMOUSE;
|
|
mode->rate = -1;
|
|
mode->resolution = -1;
|
|
mode->accelfactor = 0;
|
|
mode->packetsize = MOUSE_SYS_PACKETSIZE;
|
|
mode->syncmask[0] = MOUSE_SYS_SYNCMASK;
|
|
mode->syncmask[1] = MOUSE_SYS_SYNC;
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
case MOUSE_SETMODE: /* set protocol/mode */
|
|
{
|
|
mousemode_t *mode = (mousemode_t *)data;
|
|
|
|
if (tp != sc_get_mouse_tty())
|
|
return ENOTTY;
|
|
if ((mode->level < 0) || (mode->level > 1))
|
|
return EINVAL;
|
|
sc_mouse_set_level(mode->level);
|
|
return 0;
|
|
}
|
|
|
|
case MOUSE_GETLEVEL: /* get operation level */
|
|
if (tp != sc_get_mouse_tty())
|
|
return ENOTTY;
|
|
*(int *)data = mouse_level;
|
|
return 0;
|
|
|
|
case MOUSE_SETLEVEL: /* set operation level */
|
|
if (tp != sc_get_mouse_tty())
|
|
return ENOTTY;
|
|
if ((*(int *)data < 0) || (*(int *)data > 1))
|
|
return EINVAL;
|
|
sc_mouse_set_level(*(int *)data);
|
|
return 0;
|
|
|
|
case MOUSE_GETSTATUS: /* get accumulated mouse events */
|
|
if (tp != sc_get_mouse_tty())
|
|
return ENOTTY;
|
|
s = spltty();
|
|
*(mousestatus_t *)data = mouse_status;
|
|
mouse_status.flags = 0;
|
|
mouse_status.obutton = mouse_status.button;
|
|
mouse_status.dx = 0;
|
|
mouse_status.dy = 0;
|
|
mouse_status.dz = 0;
|
|
splx(s);
|
|
return 0;
|
|
|
|
#if notyet
|
|
case MOUSE_GETVARS: /* get internal mouse variables */
|
|
case MOUSE_SETVARS: /* set internal mouse variables */
|
|
if (tp != sc_get_mouse_tty())
|
|
return ENOTTY;
|
|
return ENODEV;
|
|
#endif
|
|
|
|
case MOUSE_READSTATE: /* read status from the device */
|
|
case MOUSE_READDATA: /* read data from the device */
|
|
if (tp != sc_get_mouse_tty())
|
|
return ENOTTY;
|
|
return ENODEV;
|
|
}
|
|
|
|
return ENOIOCTL;
|
|
}
|
|
|
|
#endif /* SC_NO_SYSMOUSE */
|
|
|
|
#endif /* NSC */
|