mouse.h - Change to be not per-architecture.
[dragonfly.git] / sys / dev / misc / syscons / scmouse.c
CommitLineData
984263bc
MD
1/*-
2 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer as
10 * the first lines of this file unmodified.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * $FreeBSD: src/sys/dev/syscons/scmouse.c,v 1.12.2.3 2001/07/28 12:51:47 yokota Exp $
da923c26 27 * $DragonFly: src/sys/dev/misc/syscons/scmouse.c,v 1.14 2008/08/10 19:47:31 swildner Exp $
984263bc
MD
28 */
29
30#include "opt_syscons.h"
31
984263bc
MD
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/conf.h>
35#include <sys/signalvar.h>
36#include <sys/proc.h>
37#include <sys/tty.h>
76b8f52a 38#include <sys/thread2.h>
984263bc
MD
39
40#include <machine/console.h>
62770245 41#include <sys/mouse.h>
984263bc 42
1f2de5d4 43#include "syscons.h"
984263bc
MD
44
45#ifdef SC_TWOBUTTON_MOUSE
46#define SC_MOUSE_PASTEBUTTON MOUSE_BUTTON3DOWN /* right button */
47#define SC_MOUSE_EXTENDBUTTON MOUSE_BUTTON2DOWN /* not really used */
48#else
49#define SC_MOUSE_PASTEBUTTON MOUSE_BUTTON2DOWN /* middle button */
50#define SC_MOUSE_EXTENDBUTTON MOUSE_BUTTON3DOWN /* right button */
51#endif /* SC_TWOBUTTON_MOUSE */
52
53#define SC_WAKEUP_DELTA 20
54
984263bc
MD
55#ifndef SC_NO_SYSMOUSE
56
57/* local variables */
58static int cut_buffer_size;
59static u_char *cut_buffer;
60
61/* local functions */
62static void set_mouse_pos(scr_stat *scp);
63#ifndef SC_NO_CUTPASTE
64static int skip_spc_right(scr_stat *scp, int p);
65static int skip_spc_left(scr_stat *scp, int p);
66static void mouse_cut(scr_stat *scp);
67static void mouse_cut_start(scr_stat *scp);
68static void mouse_cut_end(scr_stat *scp);
69static void mouse_cut_word(scr_stat *scp);
70static void mouse_cut_line(scr_stat *scp);
71static void mouse_cut_extend(scr_stat *scp);
72static void mouse_paste(scr_stat *scp);
73#endif /* SC_NO_CUTPASTE */
74
75#ifndef SC_NO_CUTPASTE
76/* allocate a cut buffer */
77void
78sc_alloc_cut_buffer(scr_stat *scp, int wait)
79{
80 u_char *p;
81
82 if ((cut_buffer == NULL)
83 || (cut_buffer_size < scp->xsize * scp->ysize + 1)) {
84 p = cut_buffer;
85 cut_buffer = NULL;
86 if (p != NULL)
efda3bd0 87 kfree(p, M_SYSCONS);
984263bc 88 cut_buffer_size = scp->xsize * scp->ysize + 1;
efda3bd0 89 p = kmalloc(cut_buffer_size, M_SYSCONS, (wait) ? M_WAITOK : M_NOWAIT);
984263bc
MD
90 if (p != NULL)
91 p[0] = '\0';
92 cut_buffer = p;
93 }
94}
95#endif /* SC_NO_CUTPASTE */
96
97/* move mouse */
98void
99sc_mouse_move(scr_stat *scp, int x, int y)
100{
6bc31f17 101 crit_enter();
984263bc
MD
102 scp->mouse_xpos = scp->mouse_oldxpos = x;
103 scp->mouse_ypos = scp->mouse_oldypos = y;
104 if (scp->font_size <= 0)
105 scp->mouse_pos = scp->mouse_oldpos = 0;
106 else
107 scp->mouse_pos = scp->mouse_oldpos =
108 (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
109 scp->status |= MOUSE_MOVED;
6bc31f17 110 crit_exit();
984263bc
MD
111}
112
113/* adjust mouse position */
114static void
115set_mouse_pos(scr_stat *scp)
116{
117 if (scp->mouse_xpos < scp->xoff*8)
118 scp->mouse_xpos = scp->xoff*8;
119 if (scp->mouse_ypos < scp->yoff*scp->font_size)
120 scp->mouse_ypos = scp->yoff*scp->font_size;
121 if (ISGRAPHSC(scp)) {
122 if (scp->mouse_xpos > scp->xpixel-1)
123 scp->mouse_xpos = scp->xpixel-1;
124 if (scp->mouse_ypos > scp->ypixel-1)
125 scp->mouse_ypos = scp->ypixel-1;
126 return;
127 } else {
128 if (scp->mouse_xpos > (scp->xsize + scp->xoff)*8 - 1)
129 scp->mouse_xpos = (scp->xsize + scp->xoff)*8 - 1;
130 if (scp->mouse_ypos > (scp->ysize + scp->yoff)*scp->font_size - 1)
131 scp->mouse_ypos = (scp->ysize + scp->yoff)*scp->font_size - 1;
132 }
133
134 if (scp->mouse_xpos != scp->mouse_oldxpos || scp->mouse_ypos != scp->mouse_oldypos) {
135 scp->status |= MOUSE_MOVED;
136 scp->mouse_pos =
137 (scp->mouse_ypos/scp->font_size - scp->yoff)*scp->xsize
138 + scp->mouse_xpos/8 - scp->xoff;
139#ifndef SC_NO_CUTPASTE
140 if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING))
141 mouse_cut(scp);
142#endif
143 }
144}
145
146#ifndef SC_NO_CUTPASTE
147
148void
149sc_draw_mouse_image(scr_stat *scp)
150{
151 if (ISGRAPHSC(scp))
152 return;
153
154 ++scp->sc->videoio_in_progress;
155 (*scp->rndr->draw_mouse)(scp, scp->mouse_xpos, scp->mouse_ypos, TRUE);
156 scp->mouse_oldpos = scp->mouse_pos;
157 scp->mouse_oldxpos = scp->mouse_xpos;
158 scp->mouse_oldypos = scp->mouse_ypos;
159 scp->status |= MOUSE_VISIBLE;
160 --scp->sc->videoio_in_progress;
161}
162
163void
164sc_remove_mouse_image(scr_stat *scp)
165{
166 int size;
167 int i;
168
169 if (ISGRAPHSC(scp))
170 return;
171
172 ++scp->sc->videoio_in_progress;
173 (*scp->rndr->draw_mouse)(scp,
174 (scp->mouse_oldpos%scp->xsize + scp->xoff)*8,
175 (scp->mouse_oldpos/scp->xsize + scp->yoff)
176 * scp->font_size,
177 FALSE);
178 size = scp->xsize*scp->ysize;
179 i = scp->mouse_oldpos;
180 mark_for_update(scp, i);
181 mark_for_update(scp, i);
984263bc
MD
182 if (i + scp->xsize + 1 < size) {
183 mark_for_update(scp, i + scp->xsize + 1);
184 } else if (i + scp->xsize < size) {
185 mark_for_update(scp, i + scp->xsize);
186 } else if (i + 1 < size) {
187 mark_for_update(scp, i + 1);
188 }
984263bc
MD
189 scp->status &= ~MOUSE_VISIBLE;
190 --scp->sc->videoio_in_progress;
191}
192
193int
194sc_inside_cutmark(scr_stat *scp, int pos)
195{
196 int start;
197 int end;
198
199 if (scp->mouse_cut_end < 0)
200 return FALSE;
201 if (scp->mouse_cut_start <= scp->mouse_cut_end) {
202 start = scp->mouse_cut_start;
203 end = scp->mouse_cut_end;
204 } else {
205 start = scp->mouse_cut_end;
206 end = scp->mouse_cut_start - 1;
207 }
208 return ((start <= pos) && (pos <= end));
209}
210
211void
212sc_remove_cutmarking(scr_stat *scp)
213{
6bc31f17 214 crit_enter();
984263bc
MD
215 if (scp->mouse_cut_end >= 0) {
216 mark_for_update(scp, scp->mouse_cut_start);
217 mark_for_update(scp, scp->mouse_cut_end);
218 }
219 scp->mouse_cut_start = scp->xsize*scp->ysize;
220 scp->mouse_cut_end = -1;
6bc31f17 221 crit_exit();
984263bc
MD
222 scp->status &= ~MOUSE_CUTTING;
223}
224
225void
226sc_remove_all_cutmarkings(sc_softc_t *sc)
227{
228 scr_stat *scp;
229 int i;
230
231 /* delete cut markings in all vtys */
232 for (i = 0; i < sc->vtys; ++i) {
233 scp = SC_STAT(sc->dev[i]);
234 if (scp == NULL)
235 continue;
236 sc_remove_cutmarking(scp);
237 }
238}
239
240void
241sc_remove_all_mouse(sc_softc_t *sc)
242{
243 scr_stat *scp;
244 int i;
245
246 for (i = 0; i < sc->vtys; ++i) {
247 scp = SC_STAT(sc->dev[i]);
248 if (scp == NULL)
249 continue;
250 if (scp->status & MOUSE_VISIBLE) {
251 scp->status &= ~MOUSE_VISIBLE;
252 mark_all(scp);
253 }
254 }
255}
256
257#define IS_SPACE_CHAR(c) (((c) & 0xff) == ' ')
258
259/* skip spaces to right */
260static int
261skip_spc_right(scr_stat *scp, int p)
262{
263 int c;
264 int i;
265
266 for (i = p % scp->xsize; i < scp->xsize; ++i) {
267 c = sc_vtb_getc(&scp->vtb, p);
268 if (!IS_SPACE_CHAR(c))
269 break;
270 ++p;
271 }
272 return i;
273}
274
275/* skip spaces to left */
276static int
277skip_spc_left(scr_stat *scp, int p)
278{
279 int c;
280 int i;
281
282 for (i = p-- % scp->xsize - 1; i >= 0; --i) {
283 c = sc_vtb_getc(&scp->vtb, p);
284 if (!IS_SPACE_CHAR(c))
285 break;
286 --p;
287 }
288 return i;
289}
290
291/* copy marked region to the cut buffer */
292static void
293mouse_cut(scr_stat *scp)
294{
295 int start;
296 int end;
297 int from;
298 int to;
299 int blank;
300 int c;
301 int p;
984263bc
MD
302 int i;
303
304 start = scp->mouse_cut_start;
984263bc
MD
305 if (scp->mouse_pos >= start) {
306 from = start;
307 to = end = scp->mouse_pos;
308 } else {
309 from = end = scp->mouse_pos;
310 to = start - 1;
311 }
312 for (p = from, i = blank = 0; p <= to; ++p) {
313 cut_buffer[i] = sc_vtb_getc(&scp->vtb, p);
314 /* remember the position of the last non-space char */
315 if (!IS_SPACE_CHAR(cut_buffer[i++]))
316 blank = i; /* the first space after the last non-space */
317 /* trim trailing blank when crossing lines */
318 if ((p % scp->xsize) == (scp->xsize - 1)) {
319 cut_buffer[blank] = '\r';
320 i = blank + 1;
321 }
322 }
323 cut_buffer[i] = '\0';
324
325 /* scan towards the end of the last line */
326 --p;
327 for (i = p % scp->xsize; i < scp->xsize; ++i) {
328 c = sc_vtb_getc(&scp->vtb, p);
329 if (!IS_SPACE_CHAR(c))
330 break;
331 ++p;
332 }
333 /* if there is nothing but blank chars, trim them, but mark towards eol */
334 if (i >= scp->xsize) {
335 if (end >= start)
336 to = end = p - 1;
337 else
338 to = start = p;
339 cut_buffer[blank++] = '\r';
340 cut_buffer[blank] = '\0';
341 }
342
343 /* remove the current marking */
6bc31f17 344 crit_enter();
984263bc
MD
345 if (scp->mouse_cut_start <= scp->mouse_cut_end) {
346 mark_for_update(scp, scp->mouse_cut_start);
347 mark_for_update(scp, scp->mouse_cut_end);
348 } else if (scp->mouse_cut_end >= 0) {
349 mark_for_update(scp, scp->mouse_cut_end);
350 mark_for_update(scp, scp->mouse_cut_start);
351 }
352
353 /* mark the new region */
354 scp->mouse_cut_start = start;
355 scp->mouse_cut_end = end;
356 mark_for_update(scp, from);
357 mark_for_update(scp, to);
6bc31f17 358 crit_exit();
984263bc
MD
359}
360
361/* a mouse button is pressed, start cut operation */
362static void
363mouse_cut_start(scr_stat *scp)
364{
365 int i;
366 int j;
984263bc
MD
367
368 if (scp->status & MOUSE_VISIBLE) {
369 i = scp->mouse_cut_start;
370 j = scp->mouse_cut_end;
371 sc_remove_all_cutmarkings(scp->sc);
372 if (scp->mouse_pos == i && i == j) {
373 cut_buffer[0] = '\0';
374 } else if (skip_spc_right(scp, scp->mouse_pos) >= scp->xsize) {
375 /* if the pointer is on trailing blank chars, mark towards eol */
376 i = skip_spc_left(scp, scp->mouse_pos) + 1;
6bc31f17 377 crit_enter();
984263bc
MD
378 scp->mouse_cut_start =
379 (scp->mouse_pos / scp->xsize) * scp->xsize + i;
380 scp->mouse_cut_end =
381 (scp->mouse_pos / scp->xsize + 1) * scp->xsize - 1;
6bc31f17 382 crit_exit();
984263bc
MD
383 cut_buffer[0] = '\r';
384 cut_buffer[1] = '\0';
385 scp->status |= MOUSE_CUTTING;
386 } else {
6bc31f17 387 crit_enter();
984263bc
MD
388 scp->mouse_cut_start = scp->mouse_pos;
389 scp->mouse_cut_end = scp->mouse_cut_start;
6bc31f17 390 crit_exit();
984263bc
MD
391 cut_buffer[0] = sc_vtb_getc(&scp->vtb, scp->mouse_cut_start);
392 cut_buffer[1] = '\0';
393 scp->status |= MOUSE_CUTTING;
394 }
395 mark_all(scp); /* this is probably overkill XXX */
396 }
397}
398
399/* end of cut operation */
400static void
401mouse_cut_end(scr_stat *scp)
402{
403 if (scp->status & MOUSE_VISIBLE)
404 scp->status &= ~MOUSE_CUTTING;
405}
406
407/* copy a word under the mouse pointer */
408static void
409mouse_cut_word(scr_stat *scp)
410{
411 int start;
412 int end;
413 int sol;
414 int eol;
415 int c;
984263bc
MD
416 int i;
417 int j;
418
419 /*
420 * Because we don't have locale information in the kernel,
421 * we only distinguish space char and non-space chars. Punctuation
422 * chars, symbols and other regular chars are all treated alike.
423 */
424 if (scp->status & MOUSE_VISIBLE) {
425 /* remove the current cut mark */
6bc31f17 426 crit_enter();
984263bc
MD
427 if (scp->mouse_cut_start <= scp->mouse_cut_end) {
428 mark_for_update(scp, scp->mouse_cut_start);
429 mark_for_update(scp, scp->mouse_cut_end);
430 } else if (scp->mouse_cut_end >= 0) {
431 mark_for_update(scp, scp->mouse_cut_end);
432 mark_for_update(scp, scp->mouse_cut_start);
433 }
434 scp->mouse_cut_start = scp->xsize*scp->ysize;
435 scp->mouse_cut_end = -1;
6bc31f17 436 crit_exit();
984263bc
MD
437
438 sol = (scp->mouse_pos / scp->xsize) * scp->xsize;
439 eol = sol + scp->xsize;
440 c = sc_vtb_getc(&scp->vtb, scp->mouse_pos);
441 if (IS_SPACE_CHAR(c)) {
442 /* blank space */
443 for (j = scp->mouse_pos; j >= sol; --j) {
444 c = sc_vtb_getc(&scp->vtb, j);
445 if (!IS_SPACE_CHAR(c))
446 break;
447 }
448 start = ++j;
449 for (j = scp->mouse_pos; j < eol; ++j) {
450 c = sc_vtb_getc(&scp->vtb, j);
451 if (!IS_SPACE_CHAR(c))
452 break;
453 }
454 end = j - 1;
455 } else {
456 /* non-space word */
457 for (j = scp->mouse_pos; j >= sol; --j) {
458 c = sc_vtb_getc(&scp->vtb, j);
459 if (IS_SPACE_CHAR(c))
460 break;
461 }
462 start = ++j;
463 for (j = scp->mouse_pos; j < eol; ++j) {
464 c = sc_vtb_getc(&scp->vtb, j);
465 if (IS_SPACE_CHAR(c))
466 break;
467 }
468 end = j - 1;
469 }
470
471 /* copy the found word */
472 for (i = 0, j = start; j <= end; ++j)
473 cut_buffer[i++] = sc_vtb_getc(&scp->vtb, j);
474 cut_buffer[i] = '\0';
475 scp->status |= MOUSE_CUTTING;
476
477 /* mark the region */
6bc31f17 478 crit_enter();
984263bc
MD
479 scp->mouse_cut_start = start;
480 scp->mouse_cut_end = end;
481 mark_for_update(scp, start);
482 mark_for_update(scp, end);
6bc31f17 483 crit_exit();
984263bc
MD
484 }
485}
486
487/* copy a line under the mouse pointer */
488static void
489mouse_cut_line(scr_stat *scp)
490{
984263bc
MD
491 int i;
492 int j;
493
494 if (scp->status & MOUSE_VISIBLE) {
495 /* remove the current cut mark */
6bc31f17 496 crit_enter();
984263bc
MD
497 if (scp->mouse_cut_start <= scp->mouse_cut_end) {
498 mark_for_update(scp, scp->mouse_cut_start);
499 mark_for_update(scp, scp->mouse_cut_end);
500 } else if (scp->mouse_cut_end >= 0) {
501 mark_for_update(scp, scp->mouse_cut_end);
502 mark_for_update(scp, scp->mouse_cut_start);
503 }
504
505 /* mark the entire line */
506 scp->mouse_cut_start =
507 (scp->mouse_pos / scp->xsize) * scp->xsize;
508 scp->mouse_cut_end = scp->mouse_cut_start + scp->xsize - 1;
509 mark_for_update(scp, scp->mouse_cut_start);
510 mark_for_update(scp, scp->mouse_cut_end);
6bc31f17 511 crit_exit();
984263bc
MD
512
513 /* copy the line into the cut buffer */
514 for (i = 0, j = scp->mouse_cut_start; j <= scp->mouse_cut_end; ++j)
515 cut_buffer[i++] = sc_vtb_getc(&scp->vtb, j);
516 cut_buffer[i++] = '\r';
517 cut_buffer[i] = '\0';
518 scp->status |= MOUSE_CUTTING;
519 }
520}
521
522/* extend the marked region to the mouse pointer position */
523static void
524mouse_cut_extend(scr_stat *scp)
525{
526 int start;
527 int end;
984263bc
MD
528
529 if ((scp->status & MOUSE_VISIBLE) && !(scp->status & MOUSE_CUTTING)
530 && (scp->mouse_cut_end >= 0)) {
531 if (scp->mouse_cut_start <= scp->mouse_cut_end) {
532 start = scp->mouse_cut_start;
533 end = scp->mouse_cut_end;
534 } else {
535 start = scp->mouse_cut_end;
536 end = scp->mouse_cut_start - 1;
537 }
6bc31f17 538 crit_enter();
984263bc
MD
539 if (scp->mouse_pos > end) {
540 scp->mouse_cut_start = start;
541 scp->mouse_cut_end = end;
542 } else if (scp->mouse_pos < start) {
543 scp->mouse_cut_start = end + 1;
544 scp->mouse_cut_end = start;
545 } else {
546 if (scp->mouse_pos - start > end + 1 - scp->mouse_pos) {
547 scp->mouse_cut_start = start;
548 scp->mouse_cut_end = end;
549 } else {
550 scp->mouse_cut_start = end + 1;
551 scp->mouse_cut_end = start;
552 }
553 }
6bc31f17 554 crit_exit();
984263bc
MD
555 mouse_cut(scp);
556 scp->status |= MOUSE_CUTTING;
557 }
558}
559
560/* paste cut buffer contents into the current vty */
561static void
562mouse_paste(scr_stat *scp)
563{
564 if (scp->status & MOUSE_VISIBLE)
565 sc_paste(scp, cut_buffer, strlen(cut_buffer));
566}
567
568#endif /* SC_NO_CUTPASTE */
569
570int
fef8985e 571sc_mouse_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag)
984263bc
MD
572{
573 mouse_info_t *mouse;
984263bc
MD
574 scr_stat *cur_scp;
575 scr_stat *scp;
984263bc
MD
576 int f;
577
578 scp = SC_STAT(tp->t_dev);
579
580 switch (cmd) {
581
582 case CONS_MOUSECTL: /* control mouse arrow */
984263bc 583 mouse = (mouse_info_t*)data;
984263bc
MD
584 cur_scp = scp->sc->cur_scp;
585
586 switch (mouse->operation) {
587 case MOUSE_MODE:
588 if (ISSIGVALID(mouse->u.mode.signal)) {
589 scp->mouse_signal = mouse->u.mode.signal;
fef8985e
MD
590 scp->mouse_proc = curproc;
591 scp->mouse_pid = curproc->p_pid;
984263bc
MD
592 }
593 else {
594 scp->mouse_signal = 0;
595 scp->mouse_proc = NULL;
596 scp->mouse_pid = 0;
597 }
598 return 0;
599
600 case MOUSE_SHOW:
6bc31f17 601 crit_enter();
984263bc
MD
602 if (!(scp->sc->flags & SC_MOUSE_ENABLED)) {
603 scp->sc->flags |= SC_MOUSE_ENABLED;
604 cur_scp->status &= ~MOUSE_HIDDEN;
605 if (!ISGRAPHSC(cur_scp))
606 mark_all(cur_scp);
6bc31f17 607 crit_exit();
984263bc
MD
608 return 0;
609 } else {
6bc31f17 610 crit_exit();
984263bc
MD
611 return EINVAL;
612 }
613 break;
614
615 case MOUSE_HIDE:
6bc31f17 616 crit_enter();
984263bc
MD
617 if (scp->sc->flags & SC_MOUSE_ENABLED) {
618 scp->sc->flags &= ~SC_MOUSE_ENABLED;
619 sc_remove_all_mouse(scp->sc);
6bc31f17 620 crit_exit();
984263bc
MD
621 return 0;
622 } else {
6bc31f17 623 crit_exit();
984263bc
MD
624 return EINVAL;
625 }
626 break;
627
628 case MOUSE_MOVEABS:
6bc31f17 629 crit_enter();
984263bc
MD
630 scp->mouse_xpos = mouse->u.data.x;
631 scp->mouse_ypos = mouse->u.data.y;
632 set_mouse_pos(scp);
6bc31f17 633 crit_exit();
984263bc
MD
634 break;
635
636 case MOUSE_MOVEREL:
6bc31f17 637 crit_enter();
984263bc
MD
638 scp->mouse_xpos += mouse->u.data.x;
639 scp->mouse_ypos += mouse->u.data.y;
640 set_mouse_pos(scp);
6bc31f17 641 crit_exit();
984263bc
MD
642 break;
643
644 case MOUSE_GETINFO:
645 mouse->u.data.x = scp->mouse_xpos;
646 mouse->u.data.y = scp->mouse_ypos;
647 mouse->u.data.z = 0;
648 mouse->u.data.buttons = scp->mouse_buttons;
649 return 0;
650
651 case MOUSE_ACTION:
652 case MOUSE_MOTION_EVENT:
653 /* send out mouse event on /dev/sysmouse */
654#if 0
655 /* this should maybe only be settable from /dev/consolectl SOS */
656 if (SC_VTY(tp->t_dev) != SC_CONSOLECTL)
657 return ENOTTY;
658#endif
6bc31f17 659 crit_enter();
984263bc
MD
660 if (mouse->u.data.x != 0 || mouse->u.data.y != 0) {
661 cur_scp->mouse_xpos += mouse->u.data.x;
662 cur_scp->mouse_ypos += mouse->u.data.y;
663 set_mouse_pos(cur_scp);
664 }
665 f = 0;
666 if (mouse->operation == MOUSE_ACTION) {
667 f = cur_scp->mouse_buttons ^ mouse->u.data.buttons;
668 cur_scp->mouse_buttons = mouse->u.data.buttons;
669 }
6bc31f17 670 crit_exit();
984263bc
MD
671
672 if (sysmouse_event(mouse) == 0)
673 return 0;
674
675 /*
676 * If any buttons are down or the mouse has moved a lot,
677 * stop the screen saver.
678 */
679 if (((mouse->operation == MOUSE_ACTION) && mouse->u.data.buttons)
680 || (mouse->u.data.x*mouse->u.data.x
681 + mouse->u.data.y*mouse->u.data.y
682 >= SC_WAKEUP_DELTA*SC_WAKEUP_DELTA)) {
683 sc_touch_scrn_saver();
684 }
685
686 cur_scp->status &= ~MOUSE_HIDDEN;
687
688 if (cur_scp->mouse_signal) {
689 /* has controlling process died? */
690 if (cur_scp->mouse_proc &&
691 (cur_scp->mouse_proc != pfind(cur_scp->mouse_pid))){
692 cur_scp->mouse_signal = 0;
693 cur_scp->mouse_proc = NULL;
694 cur_scp->mouse_pid = 0;
695 } else {
84204577 696 ksignal(cur_scp->mouse_proc, cur_scp->mouse_signal);
984263bc
MD
697 break;
698 }
699 }
700
701 if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL))
702 break;
703
704#ifndef SC_NO_CUTPASTE
705 if ((mouse->operation == MOUSE_ACTION) && f) {
706 /* process button presses */
707 if (cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN)
708 mouse_cut_start(cur_scp);
709 else
710 mouse_cut_end(cur_scp);
711 if (cur_scp->mouse_buttons & MOUSE_BUTTON2DOWN ||
712 cur_scp->mouse_buttons & MOUSE_BUTTON3DOWN)
713 mouse_paste(cur_scp);
714 }
715#endif /* SC_NO_CUTPASTE */
716 break;
717
718 case MOUSE_BUTTON_EVENT:
719 if ((mouse->u.event.id & MOUSE_BUTTONS) == 0)
720 return EINVAL;
721 if (mouse->u.event.value < 0)
722 return EINVAL;
723#if 0
724 /* this should maybe only be settable from /dev/consolectl SOS */
725 if (SC_VTY(tp->t_dev) != SC_CONSOLECTL)
726 return ENOTTY;
727#endif
728 if (mouse->u.event.value > 0)
729 cur_scp->mouse_buttons |= mouse->u.event.id;
730 else
731 cur_scp->mouse_buttons &= ~mouse->u.event.id;
732
733 if (sysmouse_event(mouse) == 0)
734 return 0;
735
736 /* if a button is held down, stop the screen saver */
737 if (mouse->u.event.value > 0)
738 sc_touch_scrn_saver();
739
740 cur_scp->status &= ~MOUSE_HIDDEN;
741
742 if (cur_scp->mouse_signal) {
743 if (cur_scp->mouse_proc &&
744 (cur_scp->mouse_proc != pfind(cur_scp->mouse_pid))){
745 cur_scp->mouse_signal = 0;
746 cur_scp->mouse_proc = NULL;
747 cur_scp->mouse_pid = 0;
748 } else {
84204577 749 ksignal(cur_scp->mouse_proc, cur_scp->mouse_signal);
984263bc
MD
750 break;
751 }
752 }
753
754 if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL))
755 break;
756
757#ifndef SC_NO_CUTPASTE
758 switch (mouse->u.event.id) {
759 case MOUSE_BUTTON1DOWN:
760 switch (mouse->u.event.value % 4) {
761 case 0: /* up */
762 mouse_cut_end(cur_scp);
763 break;
764 case 1: /* single click: start cut operation */
765 mouse_cut_start(cur_scp);
766 break;
767 case 2: /* double click: cut a word */
768 mouse_cut_word(cur_scp);
769 mouse_cut_end(cur_scp);
770 break;
771 case 3: /* triple click: cut a line */
772 mouse_cut_line(cur_scp);
773 mouse_cut_end(cur_scp);
774 break;
775 }
776 break;
777 case SC_MOUSE_PASTEBUTTON:
778 switch (mouse->u.event.value) {
779 case 0: /* up */
780 break;
781 default:
782 mouse_paste(cur_scp);
783 break;
784 }
785 break;
786 case SC_MOUSE_EXTENDBUTTON:
787 switch (mouse->u.event.value) {
788 case 0: /* up */
789 if (!(cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN))
790 mouse_cut_end(cur_scp);
791 break;
792 default:
793 mouse_cut_extend(cur_scp);
794 break;
795 }
796 break;
797 }
798#endif /* SC_NO_CUTPASTE */
799 break;
800
801 case MOUSE_MOUSECHAR:
802 if (mouse->u.mouse_char < 0) {
803 mouse->u.mouse_char = scp->sc->mouse_char;
804 } else {
1f2de5d4 805 if (mouse->u.mouse_char >= (unsigned char)-1 - 4)
984263bc 806 return EINVAL;
6bc31f17 807 crit_enter();
984263bc
MD
808 sc_remove_all_mouse(scp->sc);
809#ifndef SC_NO_FONT_LOADING
810 if (ISTEXTSC(cur_scp) && (cur_scp->font != NULL))
811 sc_load_font(cur_scp, 0, cur_scp->font_size, cur_scp->font,
812 cur_scp->sc->mouse_char, 4);
813#endif
814 scp->sc->mouse_char = mouse->u.mouse_char;
6bc31f17 815 crit_exit();
984263bc
MD
816 }
817 break;
818
819 default:
820 return EINVAL;
821 }
822
823 return 0;
824 }
825
826 return ENOIOCTL;
827}
828
829#endif /* SC_NO_SYSMOUSE */