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