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