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$ 27 */ 28 29 #include "opt_syscons.h" 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/conf.h> 34 #include <sys/consio.h> 35 #include <sys/fbio.h> 36 #include <sys/limits.h> 37 #include <sys/lock.h> 38 #include <sys/malloc.h> 39 #include <sys/mouse.h> 40 #include <sys/mutex.h> 41 #include <sys/proc.h> 42 #include <sys/random.h> 43 #include <sys/signalvar.h> 44 #include <sys/tty.h> 45 46 #include <dev/syscons/syscons.h> 47 48 #ifdef SC_TWOBUTTON_MOUSE 49 #define SC_MOUSE_PASTEBUTTON MOUSE_BUTTON3DOWN /* right button */ 50 #define SC_MOUSE_EXTENDBUTTON MOUSE_BUTTON2DOWN /* not really used */ 51 #else 52 #define SC_MOUSE_PASTEBUTTON MOUSE_BUTTON2DOWN /* middle button */ 53 #define SC_MOUSE_EXTENDBUTTON MOUSE_BUTTON3DOWN /* right button */ 54 #endif /* SC_TWOBUTTON_MOUSE */ 55 56 #define SC_WAKEUP_DELTA 20 57 58 /* for backward compatibility */ 59 #define OLD_CONS_MOUSECTL _IOWR('c', 10, old_mouse_info_t) 60 61 typedef struct old_mouse_data { 62 int x; 63 int y; 64 int buttons; 65 } old_mouse_data_t; 66 67 typedef struct old_mouse_info { 68 int operation; 69 union { 70 struct old_mouse_data data; 71 struct mouse_mode mode; 72 } u; 73 } old_mouse_info_t; 74 75 #ifndef SC_NO_SYSMOUSE 76 77 /* local variables */ 78 #ifndef SC_NO_CUTPASTE 79 static int cut_buffer_size; 80 static u_char *cut_buffer; 81 #endif 82 83 /* local functions */ 84 static void set_mouse_pos(scr_stat *scp); 85 #ifndef SC_NO_CUTPASTE 86 static int skip_spc_right(scr_stat *scp, int p); 87 static int skip_spc_left(scr_stat *scp, int p); 88 static void mouse_cut(scr_stat *scp); 89 static void mouse_cut_start(scr_stat *scp); 90 static void mouse_cut_end(scr_stat *scp); 91 static void mouse_cut_word(scr_stat *scp); 92 static void mouse_cut_line(scr_stat *scp); 93 static void mouse_cut_extend(scr_stat *scp); 94 #endif /* SC_NO_CUTPASTE */ 95 96 #ifndef SC_NO_CUTPASTE 97 /* allocate a cut buffer */ 98 void 99 sc_alloc_cut_buffer(scr_stat *scp, int wait) 100 { 101 u_char *p; 102 103 if ((cut_buffer == NULL) 104 || (cut_buffer_size < scp->xsize * scp->ysize + 1)) { 105 p = cut_buffer; 106 cut_buffer = NULL; 107 if (p != NULL) 108 free(p, M_DEVBUF); 109 cut_buffer_size = scp->xsize * scp->ysize + 1; 110 p = (u_char *)malloc(cut_buffer_size, 111 M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT); 112 if (p != NULL) 113 p[0] = '\0'; 114 cut_buffer = p; 115 } 116 } 117 #endif /* SC_NO_CUTPASTE */ 118 119 /* move mouse */ 120 void 121 sc_mouse_move(scr_stat *scp, int x, int y) 122 { 123 int s; 124 125 s = spltty(); 126 scp->mouse_xpos = scp->mouse_oldxpos = x; 127 scp->mouse_ypos = scp->mouse_oldypos = y; 128 if (scp->font_size <= 0) 129 scp->mouse_pos = scp->mouse_oldpos = 0; 130 else 131 scp->mouse_pos = scp->mouse_oldpos = 132 (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff; 133 scp->status |= MOUSE_MOVED; 134 splx(s); 135 } 136 137 /* adjust mouse position */ 138 static void 139 set_mouse_pos(scr_stat *scp) 140 { 141 if (scp->mouse_xpos < scp->xoff*8) 142 scp->mouse_xpos = scp->xoff*8; 143 if (scp->mouse_ypos < scp->yoff*scp->font_size) 144 scp->mouse_ypos = scp->yoff*scp->font_size; 145 if (ISGRAPHSC(scp)) { 146 if (scp->mouse_xpos > scp->xpixel-1) 147 scp->mouse_xpos = scp->xpixel-1; 148 if (scp->mouse_ypos > scp->ypixel-1) 149 scp->mouse_ypos = scp->ypixel-1; 150 return; 151 } else { 152 if (scp->mouse_xpos > (scp->xsize + scp->xoff)*8 - 1) 153 scp->mouse_xpos = (scp->xsize + scp->xoff)*8 - 1; 154 if (scp->mouse_ypos > (scp->ysize + scp->yoff)*scp->font_size - 1) 155 scp->mouse_ypos = (scp->ysize + scp->yoff)*scp->font_size - 1; 156 } 157 158 if (scp->mouse_xpos != scp->mouse_oldxpos || scp->mouse_ypos != scp->mouse_oldypos) { 159 scp->status |= MOUSE_MOVED; 160 scp->mouse_pos = 161 (scp->mouse_ypos/scp->font_size - scp->yoff)*scp->xsize 162 + scp->mouse_xpos/8 - scp->xoff; 163 #ifndef SC_NO_CUTPASTE 164 if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING)) 165 mouse_cut(scp); 166 #endif 167 } 168 } 169 170 #ifndef SC_NO_CUTPASTE 171 172 void 173 sc_draw_mouse_image(scr_stat *scp) 174 { 175 if (ISGRAPHSC(scp)) 176 return; 177 178 ++scp->sc->videoio_in_progress; 179 (*scp->rndr->draw_mouse)(scp, scp->mouse_xpos, scp->mouse_ypos, TRUE); 180 scp->mouse_oldpos = scp->mouse_pos; 181 scp->mouse_oldxpos = scp->mouse_xpos; 182 scp->mouse_oldypos = scp->mouse_ypos; 183 scp->status |= MOUSE_VISIBLE; 184 --scp->sc->videoio_in_progress; 185 } 186 187 void 188 sc_remove_mouse_image(scr_stat *scp) 189 { 190 int size; 191 int i; 192 193 if (ISGRAPHSC(scp)) 194 return; 195 196 ++scp->sc->videoio_in_progress; 197 (*scp->rndr->draw_mouse)(scp, 198 (scp->mouse_oldpos%scp->xsize + scp->xoff)*8, 199 (scp->mouse_oldpos/scp->xsize + scp->yoff) 200 * scp->font_size, 201 FALSE); 202 size = scp->xsize*scp->ysize; 203 i = scp->mouse_oldpos; 204 mark_for_update(scp, i); 205 mark_for_update(scp, i); 206 #ifndef PC98 207 if (i + scp->xsize + 1 < size) { 208 mark_for_update(scp, i + scp->xsize + 1); 209 } else if (i + scp->xsize < size) { 210 mark_for_update(scp, i + scp->xsize); 211 } else if (i + 1 < size) { 212 mark_for_update(scp, i + 1); 213 } 214 #endif /* PC98 */ 215 scp->status &= ~MOUSE_VISIBLE; 216 --scp->sc->videoio_in_progress; 217 } 218 219 int 220 sc_inside_cutmark(scr_stat *scp, int pos) 221 { 222 int start; 223 int end; 224 225 if (scp->mouse_cut_end < 0) 226 return FALSE; 227 if (scp->mouse_cut_start <= scp->mouse_cut_end) { 228 start = scp->mouse_cut_start; 229 end = scp->mouse_cut_end; 230 } else { 231 start = scp->mouse_cut_end; 232 end = scp->mouse_cut_start - 1; 233 } 234 return ((start <= pos) && (pos <= end)); 235 } 236 237 void 238 sc_remove_cutmarking(scr_stat *scp) 239 { 240 int s; 241 242 s = spltty(); 243 if (scp->mouse_cut_end >= 0) { 244 mark_for_update(scp, scp->mouse_cut_start); 245 mark_for_update(scp, scp->mouse_cut_end); 246 } 247 scp->mouse_cut_start = scp->xsize*scp->ysize; 248 scp->mouse_cut_end = -1; 249 splx(s); 250 scp->status &= ~MOUSE_CUTTING; 251 } 252 253 void 254 sc_remove_all_cutmarkings(sc_softc_t *sc) 255 { 256 scr_stat *scp; 257 int i; 258 259 /* delete cut markings in all vtys */ 260 for (i = 0; i < sc->vtys; ++i) { 261 scp = SC_STAT(sc->dev[i]); 262 if (scp == NULL) 263 continue; 264 sc_remove_cutmarking(scp); 265 } 266 } 267 268 void 269 sc_remove_all_mouse(sc_softc_t *sc) 270 { 271 scr_stat *scp; 272 int i; 273 274 for (i = 0; i < sc->vtys; ++i) { 275 scp = SC_STAT(sc->dev[i]); 276 if (scp == NULL) 277 continue; 278 if (scp->status & MOUSE_VISIBLE) { 279 scp->status &= ~MOUSE_VISIBLE; 280 mark_all(scp); 281 } 282 } 283 } 284 285 #define IS_SPACE_CHAR(c) (((c) & 0xff) == ' ') 286 287 #ifdef SC_CUT_SPACES2TABS 288 #define IS_BLANK_CHAR(c) (((c) & 0xff) == ' ' || ((c) & 0xff) == '\t') 289 #else 290 #define IS_BLANK_CHAR(c) IS_SPACE_CHAR(c) 291 #endif /* SC_CUT_SPACES2TABS */ 292 293 #ifdef SC_CUT_SEPCHARS 294 #define IS_SEP_CHAR(c) (index(SC_CUT_SEPCHARS, (c) & 0xff) != NULL) 295 #else 296 #define IS_SEP_CHAR(c) IS_SPACE_CHAR(c) 297 #endif /* SC_CUT_SEPCHARS */ 298 299 /* skip spaces to right */ 300 static int 301 skip_spc_right(scr_stat *scp, int p) 302 { 303 int c; 304 int i; 305 306 for (i = p % scp->xsize; i < scp->xsize; ++i) { 307 c = sc_vtb_getc(&scp->vtb, p); 308 if (!IS_SPACE_CHAR(c)) 309 break; 310 ++p; 311 } 312 return i; 313 } 314 315 /* skip spaces to left */ 316 static int 317 skip_spc_left(scr_stat *scp, int p) 318 { 319 int c; 320 int i; 321 322 for (i = p-- % scp->xsize - 1; i >= 0; --i) { 323 c = sc_vtb_getc(&scp->vtb, p); 324 if (!IS_SPACE_CHAR(c)) 325 break; 326 --p; 327 } 328 return i; 329 } 330 331 static void 332 mouse_do_cut(scr_stat *scp, int from, int to) 333 { 334 int blank; 335 int i; 336 int leadspaces; 337 int p; 338 int s; 339 340 for (p = from, i = blank = leadspaces = 0; p <= to; ++p) { 341 cut_buffer[i] = sc_vtb_getc(&scp->vtb, p); 342 /* Be prepared that sc_vtb_getc() can return '\0' */ 343 if (cut_buffer[i] == '\0') 344 cut_buffer[i] = ' '; 345 #ifdef SC_CUT_SPACES2TABS 346 if (leadspaces != -1) { 347 if (IS_SPACE_CHAR(cut_buffer[i])) { 348 leadspaces++; 349 /* Check that we are at tabstop position */ 350 if ((p % scp->xsize) % 8 == 7) { 351 i -= leadspaces - 1; 352 cut_buffer[i] = '\t'; 353 leadspaces = 0; 354 } 355 } else { 356 leadspaces = -1; 357 } 358 } 359 #endif /* SC_CUT_SPACES2TABS */ 360 /* remember the position of the last non-space char */ 361 if (!IS_BLANK_CHAR(cut_buffer[i])) 362 blank = i + 1; /* the first space after the last non-space */ 363 ++i; 364 /* trim trailing blank when crossing lines */ 365 if ((p % scp->xsize) == (scp->xsize - 1)) { 366 cut_buffer[blank++] = '\r'; 367 i = blank; 368 leadspaces = 0; 369 } 370 } 371 cut_buffer[i] = '\0'; 372 373 /* remove the current marking */ 374 s = spltty(); 375 if (scp->mouse_cut_start <= scp->mouse_cut_end) { 376 mark_for_update(scp, scp->mouse_cut_start); 377 mark_for_update(scp, scp->mouse_cut_end); 378 } else if (scp->mouse_cut_end >= 0) { 379 mark_for_update(scp, scp->mouse_cut_end); 380 mark_for_update(scp, scp->mouse_cut_start); 381 } 382 383 /* mark the new region */ 384 scp->mouse_cut_start = from; 385 scp->mouse_cut_end = to; 386 mark_for_update(scp, from); 387 mark_for_update(scp, to); 388 splx(s); 389 } 390 391 /* copy marked region to the cut buffer */ 392 static void 393 mouse_cut(scr_stat *scp) 394 { 395 int start; 396 int end; 397 int from; 398 int to; 399 int c; 400 int p; 401 int s; 402 int i; 403 404 start = scp->mouse_cut_start; 405 end = scp->mouse_cut_end; 406 if (scp->mouse_pos >= start) { 407 from = start; 408 to = end = scp->mouse_pos; 409 } else { 410 from = end = scp->mouse_pos; 411 to = start - 1; 412 } 413 p = to; 414 for (i = p % scp->xsize; i < scp->xsize; ++i) { 415 c = sc_vtb_getc(&scp->vtb, p); 416 if (!IS_SPACE_CHAR(c)) 417 break; 418 ++p; 419 } 420 /* if there is nothing but blank chars, trim them, but mark towards eol */ 421 if (i == scp->xsize) { 422 if (end >= start) 423 to = end = p - 1; 424 else 425 to = start = p; 426 } 427 mouse_do_cut(scp, from, to); 428 s = spltty(); 429 scp->mouse_cut_start = start; 430 scp->mouse_cut_end = end; 431 splx(s); 432 } 433 434 /* a mouse button is pressed, start cut operation */ 435 static void 436 mouse_cut_start(scr_stat *scp) 437 { 438 int i; 439 int s; 440 441 if (scp->status & MOUSE_VISIBLE) { 442 sc_remove_all_cutmarkings(scp->sc); 443 if (scp->mouse_pos == scp->mouse_cut_start == scp->mouse_cut_end) { 444 cut_buffer[0] = '\0'; 445 return; 446 } else if (skip_spc_right(scp, scp->mouse_pos) >= scp->xsize) { 447 /* if the pointer is on trailing blank chars, mark towards eol */ 448 i = skip_spc_left(scp, scp->mouse_pos) + 1; 449 s = spltty(); 450 scp->mouse_cut_start = 451 (scp->mouse_pos / scp->xsize) * scp->xsize + i; 452 scp->mouse_cut_end = 453 (scp->mouse_pos / scp->xsize + 1) * scp->xsize - 1; 454 splx(s); 455 cut_buffer[0] = '\r'; 456 } else { 457 s = spltty(); 458 scp->mouse_cut_start = scp->mouse_pos; 459 scp->mouse_cut_end = scp->mouse_cut_start; 460 splx(s); 461 cut_buffer[0] = sc_vtb_getc(&scp->vtb, scp->mouse_cut_start); 462 } 463 cut_buffer[1] = '\0'; 464 scp->status |= MOUSE_CUTTING; 465 mark_all(scp); /* this is probably overkill XXX */ 466 } 467 } 468 469 /* end of cut operation */ 470 static void 471 mouse_cut_end(scr_stat *scp) 472 { 473 if (scp->status & MOUSE_VISIBLE) 474 scp->status &= ~MOUSE_CUTTING; 475 } 476 477 /* copy a word under the mouse pointer */ 478 static void 479 mouse_cut_word(scr_stat *scp) 480 { 481 int start; 482 int end; 483 int sol; 484 int eol; 485 int c; 486 int j; 487 int len; 488 489 /* 490 * Because we don't have locale information in the kernel, 491 * we only distinguish space char and non-space chars. Punctuation 492 * chars, symbols and other regular chars are all treated alike 493 * unless user specified SC_CUT_SEPCHARS in his kernel config file. 494 */ 495 if (scp->status & MOUSE_VISIBLE) { 496 sol = (scp->mouse_pos / scp->xsize) * scp->xsize; 497 eol = sol + scp->xsize; 498 c = sc_vtb_getc(&scp->vtb, scp->mouse_pos); 499 if (IS_SEP_CHAR(c)) { 500 /* blank space */ 501 for (j = scp->mouse_pos; j >= sol; --j) { 502 c = sc_vtb_getc(&scp->vtb, j); 503 if (!IS_SEP_CHAR(c)) 504 break; 505 } 506 start = ++j; 507 for (j = scp->mouse_pos; j < eol; ++j) { 508 c = sc_vtb_getc(&scp->vtb, j); 509 if (!IS_SEP_CHAR(c)) 510 break; 511 } 512 end = j - 1; 513 } else { 514 /* non-space word */ 515 for (j = scp->mouse_pos; j >= sol; --j) { 516 c = sc_vtb_getc(&scp->vtb, j); 517 if (IS_SEP_CHAR(c)) 518 break; 519 } 520 start = ++j; 521 for (j = scp->mouse_pos; j < eol; ++j) { 522 c = sc_vtb_getc(&scp->vtb, j); 523 if (IS_SEP_CHAR(c)) 524 break; 525 } 526 end = j - 1; 527 } 528 529 /* copy the found word */ 530 mouse_do_cut(scp, start, end); 531 len = strlen(cut_buffer); 532 if (cut_buffer[len - 1] == '\r') 533 cut_buffer[len - 1] = '\0'; 534 } 535 } 536 537 /* copy a line under the mouse pointer */ 538 static void 539 mouse_cut_line(scr_stat *scp) 540 { 541 int len; 542 int from; 543 544 if (scp->status & MOUSE_VISIBLE) { 545 from = (scp->mouse_pos / scp->xsize) * scp->xsize; 546 mouse_do_cut(scp, from, from + scp->xsize - 1); 547 len = strlen(cut_buffer); 548 if (cut_buffer[len - 1] == '\r') 549 cut_buffer[len - 1] = '\0'; 550 scp->status |= MOUSE_CUTTING; 551 } 552 } 553 554 /* extend the marked region to the mouse pointer position */ 555 static void 556 mouse_cut_extend(scr_stat *scp) 557 { 558 int start; 559 int end; 560 int s; 561 562 if ((scp->status & MOUSE_VISIBLE) && !(scp->status & MOUSE_CUTTING) 563 && (scp->mouse_cut_end >= 0)) { 564 if (scp->mouse_cut_start <= scp->mouse_cut_end) { 565 start = scp->mouse_cut_start; 566 end = scp->mouse_cut_end; 567 } else { 568 start = scp->mouse_cut_end; 569 end = scp->mouse_cut_start - 1; 570 } 571 s = spltty(); 572 if (scp->mouse_pos > end) { 573 scp->mouse_cut_start = start; 574 scp->mouse_cut_end = end; 575 } else if (scp->mouse_pos < start) { 576 scp->mouse_cut_start = end + 1; 577 scp->mouse_cut_end = start; 578 } else { 579 if (scp->mouse_pos - start > end + 1 - scp->mouse_pos) { 580 scp->mouse_cut_start = start; 581 scp->mouse_cut_end = end; 582 } else { 583 scp->mouse_cut_start = end + 1; 584 scp->mouse_cut_end = start; 585 } 586 } 587 splx(s); 588 mouse_cut(scp); 589 scp->status |= MOUSE_CUTTING; 590 } 591 } 592 593 /* paste cut buffer contents into the current vty */ 594 void 595 sc_mouse_paste(scr_stat *scp) 596 { 597 sc_paste(scp, cut_buffer, strlen(cut_buffer)); 598 } 599 600 #endif /* SC_NO_CUTPASTE */ 601 602 int 603 sc_mouse_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, 604 struct thread *td) 605 { 606 mouse_info_t *mouse; 607 mouse_info_t buf; 608 scr_stat *cur_scp; 609 scr_stat *scp; 610 struct proc *p1; 611 int s; 612 int f; 613 614 scp = SC_STAT(tp->t_dev); 615 616 switch (cmd) { 617 618 case CONS_MOUSECTL: /* control mouse arrow */ 619 case OLD_CONS_MOUSECTL: 620 621 mouse = (mouse_info_t*)data; 622 623 random_harvest(mouse, sizeof(mouse_info_t), 2, 0, RANDOM_MOUSE); 624 625 if (cmd == OLD_CONS_MOUSECTL) { 626 static u_char swapb[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; 627 old_mouse_info_t *old_mouse = (old_mouse_info_t *)data; 628 629 mouse = &buf; 630 mouse->operation = old_mouse->operation; 631 switch (mouse->operation) { 632 case MOUSE_MODE: 633 mouse->u.mode = old_mouse->u.mode; 634 break; 635 case MOUSE_SHOW: 636 case MOUSE_HIDE: 637 break; 638 case MOUSE_MOVEABS: 639 case MOUSE_MOVEREL: 640 case MOUSE_ACTION: 641 mouse->u.data.x = old_mouse->u.data.x; 642 mouse->u.data.y = old_mouse->u.data.y; 643 mouse->u.data.z = 0; 644 mouse->u.data.buttons = swapb[old_mouse->u.data.buttons & 0x7]; 645 break; 646 case MOUSE_GETINFO: 647 old_mouse->u.data.x = scp->mouse_xpos; 648 old_mouse->u.data.y = scp->mouse_ypos; 649 old_mouse->u.data.buttons = swapb[scp->mouse_buttons & 0x7]; 650 return 0; 651 default: 652 return EINVAL; 653 } 654 } 655 656 cur_scp = scp->sc->cur_scp; 657 658 switch (mouse->operation) { 659 case MOUSE_MODE: 660 if (ISSIGVALID(mouse->u.mode.signal)) { 661 scp->mouse_signal = mouse->u.mode.signal; 662 scp->mouse_proc = td->td_proc; 663 scp->mouse_pid = td->td_proc->p_pid; 664 } 665 else { 666 scp->mouse_signal = 0; 667 scp->mouse_proc = NULL; 668 scp->mouse_pid = 0; 669 } 670 return 0; 671 672 case MOUSE_SHOW: 673 s = spltty(); 674 if (!(scp->sc->flags & SC_MOUSE_ENABLED)) { 675 scp->sc->flags |= SC_MOUSE_ENABLED; 676 cur_scp->status &= ~MOUSE_HIDDEN; 677 if (!ISGRAPHSC(cur_scp)) 678 mark_all(cur_scp); 679 splx(s); 680 return 0; 681 } else { 682 splx(s); 683 return EINVAL; 684 } 685 break; 686 687 case MOUSE_HIDE: 688 s = spltty(); 689 if (scp->sc->flags & SC_MOUSE_ENABLED) { 690 scp->sc->flags &= ~SC_MOUSE_ENABLED; 691 sc_remove_all_mouse(scp->sc); 692 splx(s); 693 return 0; 694 } else { 695 splx(s); 696 return EINVAL; 697 } 698 break; 699 700 case MOUSE_MOVEABS: 701 s = spltty(); 702 scp->mouse_xpos = mouse->u.data.x; 703 scp->mouse_ypos = mouse->u.data.y; 704 set_mouse_pos(scp); 705 splx(s); 706 break; 707 708 case MOUSE_MOVEREL: 709 s = spltty(); 710 scp->mouse_xpos += mouse->u.data.x; 711 scp->mouse_ypos += mouse->u.data.y; 712 set_mouse_pos(scp); 713 splx(s); 714 break; 715 716 case MOUSE_GETINFO: 717 mouse->u.data.x = scp->mouse_xpos; 718 mouse->u.data.y = scp->mouse_ypos; 719 mouse->u.data.z = 0; 720 mouse->u.data.buttons = scp->mouse_buttons; 721 return 0; 722 723 case MOUSE_ACTION: 724 case MOUSE_MOTION_EVENT: 725 /* send out mouse event on /dev/sysmouse */ 726 #if 0 727 /* this should maybe only be settable from /dev/consolectl SOS */ 728 if (SC_VTY(tp->t_dev) != SC_CONSOLECTL) 729 return ENOTTY; 730 #endif 731 s = spltty(); 732 if (mouse->u.data.x != 0 || mouse->u.data.y != 0) { 733 cur_scp->mouse_xpos += mouse->u.data.x; 734 cur_scp->mouse_ypos += mouse->u.data.y; 735 set_mouse_pos(cur_scp); 736 } 737 f = 0; 738 if (mouse->operation == MOUSE_ACTION) { 739 f = cur_scp->mouse_buttons ^ mouse->u.data.buttons; 740 cur_scp->mouse_buttons = mouse->u.data.buttons; 741 } 742 splx(s); 743 744 if (sysmouse_event(mouse) == 0) 745 return 0; 746 747 /* 748 * If any buttons are down or the mouse has moved a lot, 749 * stop the screen saver. 750 */ 751 if (((mouse->operation == MOUSE_ACTION) && mouse->u.data.buttons) 752 || (mouse->u.data.x*mouse->u.data.x 753 + mouse->u.data.y*mouse->u.data.y 754 >= SC_WAKEUP_DELTA*SC_WAKEUP_DELTA)) { 755 sc_touch_scrn_saver(); 756 } 757 758 cur_scp->status &= ~MOUSE_HIDDEN; 759 760 if (cur_scp->mouse_signal && cur_scp->mouse_proc) { 761 /* has controlling process died? */ 762 if (cur_scp->mouse_proc != (p1 = pfind(cur_scp->mouse_pid))) { 763 cur_scp->mouse_signal = 0; 764 cur_scp->mouse_proc = NULL; 765 cur_scp->mouse_pid = 0; 766 if (p1) 767 PROC_UNLOCK(p1); 768 } else { 769 psignal(cur_scp->mouse_proc, cur_scp->mouse_signal); 770 PROC_UNLOCK(cur_scp->mouse_proc); 771 break; 772 } 773 } 774 775 #ifndef SC_NO_CUTPASTE 776 if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL)) 777 break; 778 779 if ((mouse->operation == MOUSE_ACTION) && f) { 780 /* process button presses */ 781 if (cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN) 782 mouse_cut_start(cur_scp); 783 else 784 mouse_cut_end(cur_scp); 785 if (cur_scp->mouse_buttons & MOUSE_BUTTON2DOWN || 786 cur_scp->mouse_buttons & MOUSE_BUTTON3DOWN) 787 sc_mouse_paste(cur_scp); 788 } 789 #endif /* SC_NO_CUTPASTE */ 790 break; 791 792 case MOUSE_BUTTON_EVENT: 793 if ((mouse->u.event.id & MOUSE_BUTTONS) == 0) 794 return EINVAL; 795 if (mouse->u.event.value < 0) 796 return EINVAL; 797 #if 0 798 /* this should maybe only be settable from /dev/consolectl SOS */ 799 if (SC_VTY(tp->t_dev) != SC_CONSOLECTL) 800 return ENOTTY; 801 #endif 802 if (mouse->u.event.value > 0) 803 cur_scp->mouse_buttons |= mouse->u.event.id; 804 else 805 cur_scp->mouse_buttons &= ~mouse->u.event.id; 806 807 if (sysmouse_event(mouse) == 0) 808 return 0; 809 810 /* if a button is held down, stop the screen saver */ 811 if (mouse->u.event.value > 0) 812 sc_touch_scrn_saver(); 813 814 cur_scp->status &= ~MOUSE_HIDDEN; 815 816 if (cur_scp->mouse_signal && cur_scp->mouse_proc) { 817 if (cur_scp->mouse_proc != (p1 = pfind(cur_scp->mouse_pid))){ 818 cur_scp->mouse_signal = 0; 819 cur_scp->mouse_proc = NULL; 820 cur_scp->mouse_pid = 0; 821 if (p1) 822 PROC_UNLOCK(p1); 823 } else { 824 psignal(cur_scp->mouse_proc, cur_scp->mouse_signal); 825 PROC_UNLOCK(cur_scp->mouse_proc); 826 break; 827 } 828 } 829 830 #ifndef SC_NO_CUTPASTE 831 if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL)) 832 break; 833 834 switch (mouse->u.event.id) { 835 case MOUSE_BUTTON1DOWN: 836 switch (mouse->u.event.value % 4) { 837 case 0: /* up */ 838 mouse_cut_end(cur_scp); 839 break; 840 case 1: /* single click: start cut operation */ 841 mouse_cut_start(cur_scp); 842 break; 843 case 2: /* double click: cut a word */ 844 mouse_cut_word(cur_scp); 845 mouse_cut_end(cur_scp); 846 break; 847 case 3: /* triple click: cut a line */ 848 mouse_cut_line(cur_scp); 849 mouse_cut_end(cur_scp); 850 break; 851 } 852 break; 853 case SC_MOUSE_PASTEBUTTON: 854 switch (mouse->u.event.value) { 855 case 0: /* up */ 856 break; 857 default: 858 sc_mouse_paste(cur_scp); 859 break; 860 } 861 break; 862 case SC_MOUSE_EXTENDBUTTON: 863 switch (mouse->u.event.value) { 864 case 0: /* up */ 865 if (!(cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN)) 866 mouse_cut_end(cur_scp); 867 break; 868 default: 869 mouse_cut_extend(cur_scp); 870 break; 871 } 872 break; 873 } 874 #endif /* SC_NO_CUTPASTE */ 875 break; 876 877 case MOUSE_MOUSECHAR: 878 if (mouse->u.mouse_char < 0) { 879 mouse->u.mouse_char = scp->sc->mouse_char; 880 } else { 881 if (mouse->u.mouse_char > UCHAR_MAX - 3) 882 return EINVAL; 883 s = spltty(); 884 sc_remove_all_mouse(scp->sc); 885 #ifndef SC_NO_FONT_LOADING 886 if (ISTEXTSC(cur_scp) && (cur_scp->font != NULL)) 887 sc_load_font(cur_scp, 0, cur_scp->font_size, 888 cur_scp->font + cur_scp->font_size 889 * cur_scp->sc->mouse_char, 890 cur_scp->sc->mouse_char, 4); 891 #endif 892 scp->sc->mouse_char = mouse->u.mouse_char; 893 splx(s); 894 } 895 break; 896 897 default: 898 return EINVAL; 899 } 900 901 return 0; 902 } 903 904 return ENOIOCTL; 905 } 906 907 #endif /* SC_NO_SYSMOUSE */ 908