2 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
26 * $FreeBSD: src/sys/dev/syscons/scmouse.c,v 1.12.2.3 2001/07/28 12:51:47 yokota Exp $
29 #include "opt_syscons.h"
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/kernel.h>
35 #include <sys/signalvar.h>
38 #include <sys/thread2.h>
39 #include <sys/mplock2.h>
41 #include <machine/console.h>
42 #include <sys/mouse.h>
46 #ifdef SC_TWOBUTTON_MOUSE
47 #define SC_MOUSE_PASTEBUTTON MOUSE_BUTTON3DOWN /* right button */
48 #define SC_MOUSE_EXTENDBUTTON MOUSE_BUTTON2DOWN /* not really used */
50 #define SC_MOUSE_PASTEBUTTON MOUSE_BUTTON2DOWN /* middle button */
51 #define SC_MOUSE_EXTENDBUTTON MOUSE_BUTTON3DOWN /* right button */
52 #endif /* SC_TWOBUTTON_MOUSE */
54 #define SC_WAKEUP_DELTA 20
56 #ifndef SC_NO_SYSMOUSE
58 static int cut_buffer_size;
59 static u_char *cut_buffer;
62 static void sc_mouse_init(void *);
63 static void sc_mouse_uninit(void *);
65 static void set_mouse_pos(scr_stat *scp);
66 #ifndef SC_NO_CUTPASTE
67 static int skip_spc_right(scr_stat *scp, int p);
68 static int skip_spc_left(scr_stat *scp, int p);
69 static void mouse_cut(scr_stat *scp);
70 static void mouse_cut_start(scr_stat *scp);
71 static void mouse_cut_end(scr_stat *scp);
72 static void mouse_cut_word(scr_stat *scp);
73 static void mouse_cut_line(scr_stat *scp);
74 static void mouse_cut_extend(scr_stat *scp);
75 static void mouse_paste(scr_stat *scp);
76 #endif /* SC_NO_CUTPASTE */
78 #ifndef SC_NO_CUTPASTE
79 /* allocate a cut buffer */
81 sc_alloc_cut_buffer(scr_stat *scp, int wait)
85 if ((cut_buffer == NULL)
86 || (cut_buffer_size < scp->xsize * scp->ysize + 1)) {
91 cut_buffer_size = scp->xsize * scp->ysize + 1;
92 p = kmalloc(cut_buffer_size, M_SYSCONS, (wait) ? M_WAITOK : M_NOWAIT);
98 #endif /* SC_NO_CUTPASTE */
102 sc_mouse_move(scr_stat *scp, int x, int y)
105 scp->mouse_xpos = scp->mouse_oldxpos = x;
106 scp->mouse_ypos = scp->mouse_oldypos = y;
107 if (scp->font_height <= 0)
108 scp->mouse_pos = scp->mouse_oldpos = 0;
110 scp->mouse_pos = scp->mouse_oldpos =
111 (y / scp->font_height - scp->yoff) * scp->xsize +
112 x / scp->font_width - scp->xoff;
113 scp->status |= MOUSE_MOVED;
117 /* adjust mouse position */
119 set_mouse_pos(scr_stat *scp)
121 if (scp->mouse_xpos < scp->xoff * scp->font_width)
122 scp->mouse_xpos = scp->xoff * scp->font_width;
123 if (scp->mouse_ypos < scp->yoff * scp->font_height)
124 scp->mouse_ypos = scp->yoff * scp->font_height;
125 if (ISGRAPHSC(scp)) {
126 if (scp->mouse_xpos > scp->xpixel - 1)
127 scp->mouse_xpos = scp->xpixel - 1;
128 if (scp->mouse_ypos > scp->ypixel - 1)
129 scp->mouse_ypos = scp->ypixel - 1;
132 if (scp->mouse_xpos > (scp->xsize + scp->xoff) * scp->font_width - 1)
133 scp->mouse_xpos = (scp->xsize + scp->xoff) * scp->font_width - 1;
134 if (scp->mouse_ypos > (scp->ysize + scp->yoff) * scp->font_height - 1)
135 scp->mouse_ypos = (scp->ysize + scp->yoff) * scp->font_height - 1;
138 if (scp->mouse_xpos != scp->mouse_oldxpos ||
139 scp->mouse_ypos != scp->mouse_oldypos) {
140 scp->status |= MOUSE_MOVED;
142 (scp->mouse_ypos / scp->font_height - scp->yoff) * scp->xsize +
143 scp->mouse_xpos / scp->font_width - scp->xoff;
144 #ifndef SC_NO_CUTPASTE
145 if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING))
151 #ifndef SC_NO_CUTPASTE
154 sc_draw_mouse_image(scr_stat *scp)
159 atomic_add_int(&scp->sc->videoio_in_progress, 1);
160 (*scp->rndr->draw_mouse)(scp, scp->mouse_xpos, scp->mouse_ypos, TRUE);
161 scp->mouse_oldpos = scp->mouse_pos;
162 scp->mouse_oldxpos = scp->mouse_xpos;
163 scp->mouse_oldypos = scp->mouse_ypos;
164 scp->status |= MOUSE_VISIBLE;
165 atomic_add_int(&scp->sc->videoio_in_progress, -1);
169 sc_remove_mouse_image(scr_stat *scp)
177 atomic_add_int(&scp->sc->videoio_in_progress, 1);
178 (*scp->rndr->draw_mouse)(scp,
179 (scp->mouse_oldpos%scp->xsize + scp->xoff) *
181 (scp->mouse_oldpos/scp->xsize + scp->yoff) *
184 size = scp->xsize * scp->ysize;
185 i = scp->mouse_oldpos;
186 mark_for_update(scp, i);
187 mark_for_update(scp, i);
188 if (i + scp->xsize + 1 < size) {
189 mark_for_update(scp, i + scp->xsize + 1);
190 } else if (i + scp->xsize < size) {
191 mark_for_update(scp, i + scp->xsize);
192 } else if (i + 1 < size) {
193 mark_for_update(scp, i + 1);
195 scp->status &= ~MOUSE_VISIBLE;
196 atomic_add_int(&scp->sc->videoio_in_progress, -1);
200 sc_inside_cutmark(scr_stat *scp, int pos)
205 if (scp->mouse_cut_end < 0)
207 if (scp->mouse_cut_start <= scp->mouse_cut_end) {
208 start = scp->mouse_cut_start;
209 end = scp->mouse_cut_end;
211 start = scp->mouse_cut_end;
212 end = scp->mouse_cut_start - 1;
214 return ((start <= pos) && (pos <= end));
218 sc_remove_cutmarking(scr_stat *scp)
221 if (scp->mouse_cut_end >= 0) {
222 mark_for_update(scp, scp->mouse_cut_start);
223 mark_for_update(scp, scp->mouse_cut_end);
225 scp->mouse_cut_start = scp->xsize*scp->ysize;
226 scp->mouse_cut_end = -1;
228 scp->status &= ~MOUSE_CUTTING;
232 sc_remove_all_cutmarkings(sc_softc_t *sc)
237 /* delete cut markings in all vtys */
238 for (i = 0; i < sc->vtys; ++i) {
239 scp = SC_STAT(sc->dev[i]);
242 sc_remove_cutmarking(scp);
247 sc_remove_all_mouse(sc_softc_t *sc)
252 for (i = 0; i < sc->vtys; ++i) {
253 scp = SC_STAT(sc->dev[i]);
256 if (scp->status & MOUSE_VISIBLE) {
257 scp->status &= ~MOUSE_VISIBLE;
263 #define IS_SPACE_CHAR(c) (((c) & 0xff) == ' ')
265 /* skip spaces to right */
267 skip_spc_right(scr_stat *scp, int p)
272 for (i = p % scp->xsize; i < scp->xsize; ++i) {
273 c = sc_vtb_getc(&scp->vtb, p);
274 if (!IS_SPACE_CHAR(c))
281 /* skip spaces to left */
283 skip_spc_left(scr_stat *scp, int p)
288 for (i = p-- % scp->xsize - 1; i >= 0; --i) {
289 c = sc_vtb_getc(&scp->vtb, p);
290 if (!IS_SPACE_CHAR(c))
297 /* copy marked region to the cut buffer */
299 mouse_cut(scr_stat *scp)
310 start = scp->mouse_cut_start;
311 if (scp->mouse_pos >= start) {
313 to = end = scp->mouse_pos;
315 from = end = scp->mouse_pos;
318 for (p = from, i = blank = 0; p <= to; ++p) {
319 cut_buffer[i] = sc_vtb_getc(&scp->vtb, p);
320 /* remember the position of the last non-space char */
321 if (!IS_SPACE_CHAR(cut_buffer[i++]))
322 blank = i; /* the first space after the last non-space */
323 /* trim trailing blank when crossing lines */
324 if ((p % scp->xsize) == (scp->xsize - 1)) {
325 cut_buffer[blank] = '\r';
329 cut_buffer[i] = '\0';
331 /* scan towards the end of the last line */
333 for (i = p % scp->xsize; i < scp->xsize; ++i) {
334 c = sc_vtb_getc(&scp->vtb, p);
335 if (!IS_SPACE_CHAR(c))
339 /* if there is nothing but blank chars, trim them, but mark towards eol */
340 if (i >= scp->xsize) {
345 cut_buffer[blank++] = '\r';
346 cut_buffer[blank] = '\0';
349 /* remove the current marking */
351 if (scp->mouse_cut_start <= scp->mouse_cut_end) {
352 mark_for_update(scp, scp->mouse_cut_start);
353 mark_for_update(scp, scp->mouse_cut_end);
354 } else if (scp->mouse_cut_end >= 0) {
355 mark_for_update(scp, scp->mouse_cut_end);
356 mark_for_update(scp, scp->mouse_cut_start);
359 /* mark the new region */
360 scp->mouse_cut_start = start;
361 scp->mouse_cut_end = end;
362 mark_for_update(scp, from);
363 mark_for_update(scp, to);
367 /* a mouse button is pressed, start cut operation */
369 mouse_cut_start(scr_stat *scp)
374 if (scp->status & MOUSE_VISIBLE) {
375 i = scp->mouse_cut_start;
376 j = scp->mouse_cut_end;
377 sc_remove_all_cutmarkings(scp->sc);
378 if (scp->mouse_pos == i && i == j) {
379 cut_buffer[0] = '\0';
380 } else if (skip_spc_right(scp, scp->mouse_pos) >= scp->xsize) {
381 /* if the pointer is on trailing blank chars, mark towards eol */
382 i = skip_spc_left(scp, scp->mouse_pos) + 1;
384 scp->mouse_cut_start =
385 (scp->mouse_pos / scp->xsize) * scp->xsize + i;
387 (scp->mouse_pos / scp->xsize + 1) * scp->xsize - 1;
389 cut_buffer[0] = '\r';
390 cut_buffer[1] = '\0';
391 scp->status |= MOUSE_CUTTING;
394 scp->mouse_cut_start = scp->mouse_pos;
395 scp->mouse_cut_end = scp->mouse_cut_start;
397 cut_buffer[0] = sc_vtb_getc(&scp->vtb, scp->mouse_cut_start);
398 cut_buffer[1] = '\0';
399 scp->status |= MOUSE_CUTTING;
401 mark_all(scp); /* this is probably overkill XXX */
405 /* end of cut operation */
407 mouse_cut_end(scr_stat *scp)
409 if (scp->status & MOUSE_VISIBLE)
410 scp->status &= ~MOUSE_CUTTING;
413 /* copy a word under the mouse pointer */
415 mouse_cut_word(scr_stat *scp)
426 * Because we don't have locale information in the kernel,
427 * we only distinguish space char and non-space chars. Punctuation
428 * chars, symbols and other regular chars are all treated alike.
430 if (scp->status & MOUSE_VISIBLE) {
431 /* remove the current cut mark */
433 if (scp->mouse_cut_start <= scp->mouse_cut_end) {
434 mark_for_update(scp, scp->mouse_cut_start);
435 mark_for_update(scp, scp->mouse_cut_end);
436 } else if (scp->mouse_cut_end >= 0) {
437 mark_for_update(scp, scp->mouse_cut_end);
438 mark_for_update(scp, scp->mouse_cut_start);
440 scp->mouse_cut_start = scp->xsize*scp->ysize;
441 scp->mouse_cut_end = -1;
444 sol = (scp->mouse_pos / scp->xsize) * scp->xsize;
445 eol = sol + scp->xsize;
446 c = sc_vtb_getc(&scp->vtb, scp->mouse_pos);
447 if (IS_SPACE_CHAR(c)) {
449 for (j = scp->mouse_pos; j >= sol; --j) {
450 c = sc_vtb_getc(&scp->vtb, j);
451 if (!IS_SPACE_CHAR(c))
455 for (j = scp->mouse_pos; j < eol; ++j) {
456 c = sc_vtb_getc(&scp->vtb, j);
457 if (!IS_SPACE_CHAR(c))
463 for (j = scp->mouse_pos; j >= sol; --j) {
464 c = sc_vtb_getc(&scp->vtb, j);
465 if (IS_SPACE_CHAR(c))
469 for (j = scp->mouse_pos; j < eol; ++j) {
470 c = sc_vtb_getc(&scp->vtb, j);
471 if (IS_SPACE_CHAR(c))
477 /* copy the found word */
478 for (i = 0, j = start; j <= end; ++j)
479 cut_buffer[i++] = sc_vtb_getc(&scp->vtb, j);
480 cut_buffer[i] = '\0';
481 scp->status |= MOUSE_CUTTING;
483 /* mark the region */
485 scp->mouse_cut_start = start;
486 scp->mouse_cut_end = end;
487 mark_for_update(scp, start);
488 mark_for_update(scp, end);
493 /* copy a line under the mouse pointer */
495 mouse_cut_line(scr_stat *scp)
500 if (scp->status & MOUSE_VISIBLE) {
501 /* remove the current cut mark */
503 if (scp->mouse_cut_start <= scp->mouse_cut_end) {
504 mark_for_update(scp, scp->mouse_cut_start);
505 mark_for_update(scp, scp->mouse_cut_end);
506 } else if (scp->mouse_cut_end >= 0) {
507 mark_for_update(scp, scp->mouse_cut_end);
508 mark_for_update(scp, scp->mouse_cut_start);
511 /* mark the entire line */
512 scp->mouse_cut_start =
513 (scp->mouse_pos / scp->xsize) * scp->xsize;
514 scp->mouse_cut_end = scp->mouse_cut_start + scp->xsize - 1;
515 mark_for_update(scp, scp->mouse_cut_start);
516 mark_for_update(scp, scp->mouse_cut_end);
519 /* copy the line into the cut buffer */
520 for (i = 0, j = scp->mouse_cut_start; j <= scp->mouse_cut_end; ++j)
521 cut_buffer[i++] = sc_vtb_getc(&scp->vtb, j);
522 cut_buffer[i++] = '\r';
523 cut_buffer[i] = '\0';
524 scp->status |= MOUSE_CUTTING;
528 /* extend the marked region to the mouse pointer position */
530 mouse_cut_extend(scr_stat *scp)
535 if ((scp->status & MOUSE_VISIBLE) && !(scp->status & MOUSE_CUTTING)
536 && (scp->mouse_cut_end >= 0)) {
537 if (scp->mouse_cut_start <= scp->mouse_cut_end) {
538 start = scp->mouse_cut_start;
539 end = scp->mouse_cut_end;
541 start = scp->mouse_cut_end;
542 end = scp->mouse_cut_start - 1;
545 if (scp->mouse_pos > end) {
546 scp->mouse_cut_start = start;
547 scp->mouse_cut_end = end;
548 } else if (scp->mouse_pos < start) {
549 scp->mouse_cut_start = end + 1;
550 scp->mouse_cut_end = start;
552 if (scp->mouse_pos - start > end + 1 - scp->mouse_pos) {
553 scp->mouse_cut_start = start;
554 scp->mouse_cut_end = end;
556 scp->mouse_cut_start = end + 1;
557 scp->mouse_cut_end = start;
562 scp->status |= MOUSE_CUTTING;
566 /* paste cut buffer contents into the current vty */
568 mouse_paste(scr_stat *scp)
570 if (scp->status & MOUSE_VISIBLE)
571 sc_paste(scp, cut_buffer, strlen(cut_buffer));
574 #endif /* SC_NO_CUTPASTE */
577 sc_mouse_exit1_proc(struct proc *p)
582 KKASSERT(scp != NULL);
585 KKASSERT(scp->mouse_proc == p);
586 KKASSERT(scp->mouse_pid == p->p_pid);
588 scp->mouse_signal = 0;
589 scp->mouse_proc = NULL;
594 p->p_flags &= ~P_SCMOUSE;
595 p->p_drv_priv = NULL;
601 * Handle exit1 for processes registered as MOUSE_MODE handlers.
602 * We must remove a process hold, established when MOUSE_MODE
606 sc_mouse_exit1(struct thread *td)
613 if ((p->p_flags & P_SCMOUSE) == 0)
617 sc_mouse_exit1_proc(p);
621 sc_mouse_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag)
628 scp = SC_STAT(tp->t_dev);
632 case CONS_MOUSECTL: /* control mouse arrow */
633 mouse = (mouse_info_t*) data;
634 cur_scp = scp->sc->cur_scp;
636 switch (mouse->operation) {
638 * Setup a process to receive signals on mouse events.
643 if (!ISSIGVALID(mouse->u.mode.signal)) {
644 /* Setting MOUSE_MODE w/ an invalid signal is used to disarm */
645 if (scp->mouse_proc == curproc) {
646 sc_mouse_exit1_proc(curproc);
654 /* Only one mouse process per syscons */
655 if (scp->mouse_proc) {
660 /* Only one syscons signal source per process */
661 if (curproc->p_flags & P_SCMOUSE) {
667 * Process is stabilized by a hold, which is removed from
668 * sc_mouse_exit1. scp's mouse_{signal,proc,pid} fields
669 * are synchronized by the MP Lock.
671 scp->mouse_signal = mouse->u.mode.signal;
672 scp->mouse_proc = curproc;
673 scp->mouse_pid = curproc->p_pid;
674 curproc->p_flags |= P_SCMOUSE;
675 KKASSERT(curproc->p_drv_priv == NULL);
676 curproc->p_drv_priv = scp;
687 if (!(scp->sc->flags & SC_MOUSE_ENABLED)) {
688 scp->sc->flags |= SC_MOUSE_ENABLED;
689 cur_scp->status &= ~MOUSE_HIDDEN;
690 if (!ISGRAPHSC(cur_scp))
702 if (scp->sc->flags & SC_MOUSE_ENABLED) {
703 scp->sc->flags &= ~SC_MOUSE_ENABLED;
704 sc_remove_all_mouse(scp->sc);
715 scp->mouse_xpos = mouse->u.data.x;
716 scp->mouse_ypos = mouse->u.data.y;
723 scp->mouse_xpos += mouse->u.data.x;
724 scp->mouse_ypos += mouse->u.data.y;
730 mouse->u.data.x = scp->mouse_xpos;
731 mouse->u.data.y = scp->mouse_ypos;
733 mouse->u.data.buttons = scp->mouse_buttons;
737 case MOUSE_MOTION_EVENT:
738 /* send out mouse event on /dev/sysmouse */
740 /* this should maybe only be settable from /dev/consolectl SOS */
741 if (SC_VTY(tp->t_dev) != SC_CONSOLECTL)
745 if (mouse->u.data.x != 0 || mouse->u.data.y != 0) {
746 cur_scp->mouse_xpos += mouse->u.data.x;
747 cur_scp->mouse_ypos += mouse->u.data.y;
748 set_mouse_pos(cur_scp);
751 if (mouse->operation == MOUSE_ACTION) {
752 f = cur_scp->mouse_buttons ^ mouse->u.data.buttons;
753 cur_scp->mouse_buttons = mouse->u.data.buttons;
757 if (sysmouse_event(mouse) == 0)
761 * If any buttons are down or the mouse has moved a lot,
762 * stop the screen saver.
764 if (((mouse->operation == MOUSE_ACTION) && mouse->u.data.buttons)
765 || (mouse->u.data.x*mouse->u.data.x
766 + mouse->u.data.y*mouse->u.data.y
767 >= SC_WAKEUP_DELTA*SC_WAKEUP_DELTA)) {
768 sc_touch_scrn_saver();
771 cur_scp->status &= ~MOUSE_HIDDEN;
774 if (cur_scp->mouse_signal) {
775 KKASSERT(cur_scp->mouse_proc != NULL);
776 ksignal(cur_scp->mouse_proc, cur_scp->mouse_signal);
782 if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL))
785 #ifndef SC_NO_CUTPASTE
786 if ((mouse->operation == MOUSE_ACTION) && f) {
787 /* process button presses */
788 if (cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN)
789 mouse_cut_start(cur_scp);
791 mouse_cut_end(cur_scp);
792 if (cur_scp->mouse_buttons & MOUSE_BUTTON2DOWN ||
793 cur_scp->mouse_buttons & MOUSE_BUTTON3DOWN)
794 mouse_paste(cur_scp);
796 #endif /* SC_NO_CUTPASTE */
799 case MOUSE_BUTTON_EVENT:
800 if ((mouse->u.event.id & MOUSE_BUTTONS) == 0)
802 if (mouse->u.event.value < 0)
805 /* this should maybe only be settable from /dev/consolectl SOS */
806 if (SC_VTY(tp->t_dev) != SC_CONSOLECTL)
809 if (mouse->u.event.value > 0)
810 cur_scp->mouse_buttons |= mouse->u.event.id;
812 cur_scp->mouse_buttons &= ~mouse->u.event.id;
814 if (sysmouse_event(mouse) == 0)
817 /* if a button is held down, stop the screen saver */
818 if (mouse->u.event.value > 0)
819 sc_touch_scrn_saver();
821 cur_scp->status &= ~MOUSE_HIDDEN;
824 if (cur_scp->mouse_signal) {
825 KKASSERT(cur_scp->mouse_proc != NULL);
826 ksignal(cur_scp->mouse_proc, cur_scp->mouse_signal);
832 if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL))
835 #ifndef SC_NO_CUTPASTE
836 switch (mouse->u.event.id) {
837 case MOUSE_BUTTON1DOWN:
838 switch (mouse->u.event.value % 4) {
840 mouse_cut_end(cur_scp);
842 case 1: /* single click: start cut operation */
843 mouse_cut_start(cur_scp);
845 case 2: /* double click: cut a word */
846 mouse_cut_word(cur_scp);
847 mouse_cut_end(cur_scp);
849 case 3: /* triple click: cut a line */
850 mouse_cut_line(cur_scp);
851 mouse_cut_end(cur_scp);
855 case SC_MOUSE_PASTEBUTTON:
856 switch (mouse->u.event.value) {
860 mouse_paste(cur_scp);
864 case SC_MOUSE_EXTENDBUTTON:
865 switch (mouse->u.event.value) {
867 if (!(cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN))
868 mouse_cut_end(cur_scp);
871 mouse_cut_extend(cur_scp);
876 #endif /* SC_NO_CUTPASTE */
879 case MOUSE_MOUSECHAR:
880 if (mouse->u.mouse_char < 0) {
881 mouse->u.mouse_char = scp->sc->mouse_char;
883 if (mouse->u.mouse_char >= (unsigned char)-1 - 4)
886 sc_remove_all_mouse(scp->sc);
887 #ifndef SC_NO_FONT_LOADING
888 if (ISTEXTSC(cur_scp) && (cur_scp->font != NULL))
889 sc_load_font(cur_scp, 0, cur_scp->font_height,
891 cur_scp->sc->mouse_char, 4);
893 scp->sc->mouse_char = mouse->u.mouse_char;
909 sc_mouse_init(void *unused)
911 at_exit(sc_mouse_exit1);
915 sc_mouse_uninit(void *unused)
919 SYSINIT(sc_mouse_init, SI_SUB_DRIVERS, SI_ORDER_ANY, sc_mouse_init, NULL);
920 SYSUNINIT(sc_mouse_uninit, SI_SUB_DRIVERS, SI_ORDER_ANY, sc_mouse_uninit, NULL);
922 #endif /* SC_NO_SYSMOUSE */