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 "sc.h" 30 #include "opt_syscons.h" 31 32 #if NSC > 0 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/conf.h> 37 #include <sys/signalvar.h> 38 #include <sys/proc.h> 39 #include <sys/tty.h> 40 #include <sys/kernel.h> 41 #include <sys/malloc.h> 42 43 #include <machine/console.h> 44 #include <machine/mouse.h> 45 46 #include <dev/syscons/syscons.h> 47 48 #define SC_WAKEUP_DELTA 20 49 50 /* for backward compatibility */ 51 #define OLD_CONS_MOUSECTL _IOWR('c', 10, old_mouse_info_t) 52 53 typedef struct old_mouse_data { 54 int x; 55 int y; 56 int buttons; 57 } old_mouse_data_t; 58 59 typedef struct old_mouse_info { 60 int operation; 61 union { 62 struct old_mouse_data data; 63 struct mouse_mode mode; 64 } u; 65 } old_mouse_info_t; 66 67 /* local variables */ 68 #ifndef SC_NO_SYSMOUSE 69 static int mouse_level; /* sysmouse protocol level */ 70 static mousestatus_t mouse_status = { 0, 0, 0, 0, 0, 0 }; 71 static int cut_buffer_size; 72 static u_char *cut_buffer; 73 #endif /* SC_NO_SYSMOUE */ 74 75 /* local functions */ 76 #ifndef SC_NO_SYSMOUSE 77 static void set_mouse_pos(scr_stat *scp); 78 #ifndef SC_NO_CUTPASTE 79 static int skip_spc_right(scr_stat *scp, int p); 80 static int skip_spc_left(scr_stat *scp, int p); 81 static void mouse_cut(scr_stat *scp); 82 static void mouse_cut_start(scr_stat *scp); 83 static void mouse_cut_end(scr_stat *scp); 84 static void mouse_cut_word(scr_stat *scp); 85 static void mouse_cut_line(scr_stat *scp); 86 static void mouse_cut_extend(scr_stat *scp); 87 static void mouse_paste(scr_stat *scp); 88 #endif /* SC_NO_CUTPASTE */ 89 #endif /* SC_NO_SYSMOUE */ 90 91 #ifndef SC_NO_CUTPASTE 92 /* allocate a cut buffer */ 93 void 94 sc_alloc_cut_buffer(scr_stat *scp, int wait) 95 { 96 u_char *p; 97 98 if ((cut_buffer == NULL) 99 || (cut_buffer_size < scp->xsize * scp->ysize + 1)) { 100 p = cut_buffer; 101 cut_buffer = NULL; 102 if (p != NULL) 103 free(p, M_DEVBUF); 104 cut_buffer_size = scp->xsize * scp->ysize + 1; 105 p = (u_char *)malloc(cut_buffer_size, 106 M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT); 107 if (p != NULL) 108 p[0] = '\0'; 109 cut_buffer = p; 110 } 111 } 112 #endif /* SC_NO_CUTPASTE */ 113 114 #ifndef SC_NO_SYSMOUSE 115 116 /* modify the sysmouse software level */ 117 void 118 sc_mouse_set_level(int level) 119 { 120 mouse_level = level; 121 } 122 123 /* move mouse */ 124 void 125 sc_mouse_move(scr_stat *scp, int x, int y) 126 { 127 int s; 128 129 s = spltty(); 130 scp->mouse_xpos = x; 131 scp->mouse_ypos = y; 132 scp->mouse_pos = scp->mouse_oldpos = 133 (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff; 134 splx(s); 135 } 136 137 /* adjust mouse position */ 138 static void 139 set_mouse_pos(scr_stat *scp) 140 { 141 static int last_xpos = -1, last_ypos = -1; 142 143 if (scp->mouse_xpos < scp->xoff*8) 144 scp->mouse_xpos = scp->xoff*8; 145 if (scp->mouse_ypos < scp->yoff*scp->font_size) 146 scp->mouse_ypos = scp->yoff*scp->font_size; 147 if (ISGRAPHSC(scp)) { 148 if (scp->mouse_xpos > scp->xpixel-1) 149 scp->mouse_xpos = scp->xpixel-1; 150 if (scp->mouse_ypos > scp->ypixel-1) 151 scp->mouse_ypos = scp->ypixel-1; 152 return; 153 } else { 154 if (scp->mouse_xpos > (scp->xsize + scp->xoff)*8 - 1) 155 scp->mouse_xpos = (scp->xsize + scp->xoff)*8 - 1; 156 if (scp->mouse_ypos > (scp->ysize + scp->yoff)*scp->font_size - 1) 157 scp->mouse_ypos = (scp->ysize + scp->yoff)*scp->font_size - 1; 158 } 159 160 if (scp->mouse_xpos != last_xpos || scp->mouse_ypos != last_ypos) { 161 scp->status |= MOUSE_MOVED; 162 scp->mouse_pos = 163 (scp->mouse_ypos/scp->font_size - scp->yoff)*scp->xsize 164 + scp->mouse_xpos/8 - scp->xoff; 165 #ifndef SC_NO_CUTPASTE 166 if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING)) 167 mouse_cut(scp); 168 #endif 169 } 170 } 171 172 #ifndef SC_NO_CUTPASTE 173 174 void 175 sc_draw_mouse_image(scr_stat *scp) 176 { 177 if (ISGRAPHSC(scp)) 178 return; 179 180 ++scp->sc->videoio_in_progress; 181 (*scp->rndr->draw_mouse)(scp, scp->mouse_xpos, scp->mouse_ypos, TRUE); 182 scp->mouse_oldpos = scp->mouse_pos; 183 --scp->sc->videoio_in_progress; 184 } 185 186 void 187 sc_remove_mouse_image(scr_stat *scp) 188 { 189 int size; 190 int i; 191 192 if (ISGRAPHSC(scp)) 193 return; 194 195 ++scp->sc->videoio_in_progress; 196 (*scp->rndr->draw_mouse)(scp, 197 (scp->mouse_oldpos%scp->xsize + scp->xoff)*8, 198 (scp->mouse_oldpos/scp->xsize + scp->yoff) 199 * scp->font_size, 200 FALSE); 201 size = scp->xsize*scp->ysize; 202 i = scp->mouse_oldpos; 203 mark_for_update(scp, i); 204 mark_for_update(scp, i); 205 #ifndef PC98 206 if (i + scp->xsize + 1 < size) { 207 mark_for_update(scp, i + scp->xsize + 1); 208 } else if (i + scp->xsize < size) { 209 mark_for_update(scp, i + scp->xsize); 210 } else if (i + 1 < size) { 211 mark_for_update(scp, i + 1); 212 } 213 #endif /* PC98 */ 214 --scp->sc->videoio_in_progress; 215 } 216 217 int 218 sc_inside_cutmark(scr_stat *scp, int pos) 219 { 220 int start; 221 int end; 222 223 if (scp->mouse_cut_end < 0) 224 return FALSE; 225 if (scp->mouse_cut_start <= scp->mouse_cut_end) { 226 start = scp->mouse_cut_start; 227 end = scp->mouse_cut_end; 228 } else { 229 start = scp->mouse_cut_end; 230 end = scp->mouse_cut_start - 1; 231 } 232 return ((start <= pos) && (pos <= end)); 233 } 234 235 void 236 sc_remove_cutmarking(scr_stat *scp) 237 { 238 int s; 239 240 s = spltty(); 241 if (scp->mouse_cut_end >= 0) { 242 mark_for_update(scp, scp->mouse_cut_start); 243 mark_for_update(scp, scp->mouse_cut_end); 244 } 245 scp->mouse_cut_start = scp->xsize*scp->ysize; 246 scp->mouse_cut_end = -1; 247 splx(s); 248 scp->status &= ~MOUSE_CUTTING; 249 } 250 251 void 252 sc_remove_all_cutmarkings(sc_softc_t *sc) 253 { 254 scr_stat *scp; 255 int i; 256 257 /* delete cut markings in all vtys */ 258 for (i = 0; i < sc->vtys; ++i) { 259 scp = SC_STAT(sc->dev[i]); 260 if (scp == NULL) 261 continue; 262 sc_remove_cutmarking(scp); 263 } 264 } 265 266 void 267 sc_remove_all_mouse(sc_softc_t *sc) 268 { 269 scr_stat *scp; 270 int i; 271 272 for (i = 0; i < sc->vtys; ++i) { 273 scp = SC_STAT(sc->dev[i]); 274 if (scp == NULL) 275 continue; 276 if (scp->status & MOUSE_VISIBLE) { 277 scp->status &= ~MOUSE_VISIBLE; 278 mark_all(scp); 279 } 280 } 281 } 282 283 #define IS_SPACE_CHAR(c) (((c) & 0xff) == ' ') 284 285 /* skip spaces to right */ 286 static int 287 skip_spc_right(scr_stat *scp, int p) 288 { 289 int c; 290 int i; 291 292 for (i = p % scp->xsize; i < scp->xsize; ++i) { 293 c = sc_vtb_getc(&scp->vtb, p); 294 if (!IS_SPACE_CHAR(c)) 295 break; 296 ++p; 297 } 298 return i; 299 } 300 301 /* skip spaces to left */ 302 static int 303 skip_spc_left(scr_stat *scp, int p) 304 { 305 int c; 306 int i; 307 308 for (i = p-- % scp->xsize - 1; i >= 0; --i) { 309 c = sc_vtb_getc(&scp->vtb, p); 310 if (!IS_SPACE_CHAR(c)) 311 break; 312 --p; 313 } 314 return i; 315 } 316 317 /* copy marked region to the cut buffer */ 318 static void 319 mouse_cut(scr_stat *scp) 320 { 321 int start; 322 int end; 323 int from; 324 int to; 325 int blank; 326 int c; 327 int p; 328 int s; 329 int i; 330 331 start = scp->mouse_cut_start; 332 end = scp->mouse_cut_end; 333 if (scp->mouse_pos >= start) { 334 from = start; 335 to = end = scp->mouse_pos; 336 } else { 337 from = end = scp->mouse_pos; 338 to = start - 1; 339 } 340 for (p = from, i = blank = 0; p <= to; ++p) { 341 cut_buffer[i] = sc_vtb_getc(&scp->vtb, p); 342 /* remember the position of the last non-space char */ 343 if (!IS_SPACE_CHAR(cut_buffer[i++])) 344 blank = i; /* the first space after the last non-space */ 345 /* trim trailing blank when crossing lines */ 346 if ((p % scp->xsize) == (scp->xsize - 1)) { 347 cut_buffer[blank] = '\r'; 348 i = blank + 1; 349 } 350 } 351 cut_buffer[i] = '\0'; 352 353 /* scan towards the end of the last line */ 354 --p; 355 for (i = p % scp->xsize; i < scp->xsize; ++i) { 356 c = sc_vtb_getc(&scp->vtb, p); 357 if (!IS_SPACE_CHAR(c)) 358 break; 359 ++p; 360 } 361 /* if there is nothing but blank chars, trim them, but mark towards eol */ 362 if (i >= scp->xsize) { 363 if (end >= start) 364 to = end = p - 1; 365 else 366 to = start = p; 367 cut_buffer[blank++] = '\r'; 368 cut_buffer[blank] = '\0'; 369 } 370 371 /* remove the current marking */ 372 s = spltty(); 373 if (scp->mouse_cut_start <= scp->mouse_cut_end) { 374 mark_for_update(scp, scp->mouse_cut_start); 375 mark_for_update(scp, scp->mouse_cut_end); 376 } else if (scp->mouse_cut_end >= 0) { 377 mark_for_update(scp, scp->mouse_cut_end); 378 mark_for_update(scp, scp->mouse_cut_start); 379 } 380 381 /* mark the new region */ 382 scp->mouse_cut_start = start; 383 scp->mouse_cut_end = end; 384 mark_for_update(scp, from); 385 mark_for_update(scp, to); 386 splx(s); 387 } 388 389 /* a mouse button is pressed, start cut operation */ 390 static void 391 mouse_cut_start(scr_stat *scp) 392 { 393 int i; 394 int j; 395 int s; 396 397 if (scp->status & MOUSE_VISIBLE) { 398 i = scp->mouse_cut_start; 399 j = scp->mouse_cut_end; 400 sc_remove_all_cutmarkings(scp->sc); 401 if (scp->mouse_pos == i && i == j) { 402 cut_buffer[0] = '\0'; 403 } else if (skip_spc_right(scp, scp->mouse_pos) >= scp->xsize) { 404 /* if the pointer is on trailing blank chars, mark towards eol */ 405 i = skip_spc_left(scp, scp->mouse_pos) + 1; 406 s = spltty(); 407 scp->mouse_cut_start = 408 (scp->mouse_pos / scp->xsize) * scp->xsize + i; 409 scp->mouse_cut_end = 410 (scp->mouse_pos / scp->xsize + 1) * scp->xsize - 1; 411 splx(s); 412 cut_buffer[0] = '\r'; 413 cut_buffer[1] = '\0'; 414 scp->status |= MOUSE_CUTTING; 415 } else { 416 s = spltty(); 417 scp->mouse_cut_start = scp->mouse_pos; 418 scp->mouse_cut_end = scp->mouse_cut_start; 419 splx(s); 420 cut_buffer[0] = sc_vtb_getc(&scp->vtb, scp->mouse_cut_start); 421 cut_buffer[1] = '\0'; 422 scp->status |= MOUSE_CUTTING; 423 } 424 mark_all(scp); /* this is probably overkill XXX */ 425 } 426 } 427 428 /* end of cut operation */ 429 static void 430 mouse_cut_end(scr_stat *scp) 431 { 432 if (scp->status & MOUSE_VISIBLE) 433 scp->status &= ~MOUSE_CUTTING; 434 } 435 436 /* copy a word under the mouse pointer */ 437 static void 438 mouse_cut_word(scr_stat *scp) 439 { 440 int start; 441 int end; 442 int sol; 443 int eol; 444 int c; 445 int s; 446 int i; 447 int j; 448 449 /* 450 * Because we don't have locale information in the kernel, 451 * we only distinguish space char and non-space chars. Punctuation 452 * chars, symbols and other regular chars are all treated alike. 453 */ 454 if (scp->status & MOUSE_VISIBLE) { 455 /* remove the current cut mark */ 456 s = spltty(); 457 if (scp->mouse_cut_start <= scp->mouse_cut_end) { 458 mark_for_update(scp, scp->mouse_cut_start); 459 mark_for_update(scp, scp->mouse_cut_end); 460 } else if (scp->mouse_cut_end >= 0) { 461 mark_for_update(scp, scp->mouse_cut_end); 462 mark_for_update(scp, scp->mouse_cut_start); 463 } 464 scp->mouse_cut_start = scp->xsize*scp->ysize; 465 scp->mouse_cut_end = -1; 466 splx(s); 467 468 sol = (scp->mouse_pos / scp->xsize) * scp->xsize; 469 eol = sol + scp->xsize; 470 c = sc_vtb_getc(&scp->vtb, scp->mouse_pos); 471 if (IS_SPACE_CHAR(c)) { 472 /* blank space */ 473 for (j = scp->mouse_pos; j >= sol; --j) { 474 c = sc_vtb_getc(&scp->vtb, j); 475 if (!IS_SPACE_CHAR(c)) 476 break; 477 } 478 start = ++j; 479 for (j = scp->mouse_pos; j < eol; ++j) { 480 c = sc_vtb_getc(&scp->vtb, j); 481 if (!IS_SPACE_CHAR(c)) 482 break; 483 } 484 end = j - 1; 485 } else { 486 /* non-space word */ 487 for (j = scp->mouse_pos; j >= sol; --j) { 488 c = sc_vtb_getc(&scp->vtb, j); 489 if (IS_SPACE_CHAR(c)) 490 break; 491 } 492 start = ++j; 493 for (j = scp->mouse_pos; j < eol; ++j) { 494 c = sc_vtb_getc(&scp->vtb, j); 495 if (IS_SPACE_CHAR(c)) 496 break; 497 } 498 end = j - 1; 499 } 500 501 /* copy the found word */ 502 for (i = 0, j = start; j <= end; ++j) 503 cut_buffer[i++] = sc_vtb_getc(&scp->vtb, j); 504 cut_buffer[i] = '\0'; 505 scp->status |= MOUSE_CUTTING; 506 507 /* mark the region */ 508 s = spltty(); 509 scp->mouse_cut_start = start; 510 scp->mouse_cut_end = end; 511 mark_for_update(scp, start); 512 mark_for_update(scp, end); 513 splx(s); 514 } 515 } 516 517 /* copy a line under the mouse pointer */ 518 static void 519 mouse_cut_line(scr_stat *scp) 520 { 521 int s; 522 int i; 523 int j; 524 525 if (scp->status & MOUSE_VISIBLE) { 526 /* remove the current cut mark */ 527 s = spltty(); 528 if (scp->mouse_cut_start <= scp->mouse_cut_end) { 529 mark_for_update(scp, scp->mouse_cut_start); 530 mark_for_update(scp, scp->mouse_cut_end); 531 } else if (scp->mouse_cut_end >= 0) { 532 mark_for_update(scp, scp->mouse_cut_end); 533 mark_for_update(scp, scp->mouse_cut_start); 534 } 535 536 /* mark the entire line */ 537 scp->mouse_cut_start = 538 (scp->mouse_pos / scp->xsize) * scp->xsize; 539 scp->mouse_cut_end = scp->mouse_cut_start + scp->xsize - 1; 540 mark_for_update(scp, scp->mouse_cut_start); 541 mark_for_update(scp, scp->mouse_cut_end); 542 splx(s); 543 544 /* copy the line into the cut buffer */ 545 for (i = 0, j = scp->mouse_cut_start; j <= scp->mouse_cut_end; ++j) 546 cut_buffer[i++] = sc_vtb_getc(&scp->vtb, j); 547 cut_buffer[i++] = '\r'; 548 cut_buffer[i] = '\0'; 549 scp->status |= MOUSE_CUTTING; 550 } 551 } 552 553 /* extend the marked region to the mouse pointer position */ 554 static void 555 mouse_cut_extend(scr_stat *scp) 556 { 557 int start; 558 int end; 559 int s; 560 561 if ((scp->status & MOUSE_VISIBLE) && !(scp->status & MOUSE_CUTTING) 562 && (scp->mouse_cut_end >= 0)) { 563 if (scp->mouse_cut_start <= scp->mouse_cut_end) { 564 start = scp->mouse_cut_start; 565 end = scp->mouse_cut_end; 566 } else { 567 start = scp->mouse_cut_end; 568 end = scp->mouse_cut_start - 1; 569 } 570 s = spltty(); 571 if (scp->mouse_pos > end) { 572 scp->mouse_cut_start = start; 573 scp->mouse_cut_end = end; 574 } else if (scp->mouse_pos < start) { 575 scp->mouse_cut_start = end + 1; 576 scp->mouse_cut_end = start; 577 } else { 578 if (scp->mouse_pos - start > end + 1 - scp->mouse_pos) { 579 scp->mouse_cut_start = start; 580 scp->mouse_cut_end = end; 581 } else { 582 scp->mouse_cut_start = end + 1; 583 scp->mouse_cut_end = start; 584 } 585 } 586 splx(s); 587 mouse_cut(scp); 588 scp->status |= MOUSE_CUTTING; 589 } 590 } 591 592 /* paste cut buffer contents into the current vty */ 593 static void 594 mouse_paste(scr_stat *scp) 595 { 596 if (scp->status & MOUSE_VISIBLE) 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 proc *p) 605 { 606 607 scr_stat *scp; 608 int s; 609 int i; 610 611 /* scp == NULL, if tp == sc_get_mouse_tty() (/dev/sysmouse) */ 612 scp = SC_STAT(tp->t_dev); 613 614 switch (cmd) { 615 616 case CONS_MOUSECTL: /* control mouse arrow */ 617 case OLD_CONS_MOUSECTL: 618 { 619 /* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */ 620 static int butmap[8] = { 621 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, 622 MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, 623 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP, 624 MOUSE_MSC_BUTTON3UP, 625 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP, 626 MOUSE_MSC_BUTTON2UP, 627 MOUSE_MSC_BUTTON1UP, 628 0, 629 }; 630 mouse_info_t *mouse = (mouse_info_t*)data; 631 mouse_info_t buf; 632 scr_stat *cur_scp; 633 struct tty *mtty; 634 635 if (scp == NULL) 636 return ENOTTY; 637 638 if (cmd == OLD_CONS_MOUSECTL) { 639 static u_char swapb[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; 640 old_mouse_info_t *old_mouse = (old_mouse_info_t *)data; 641 642 mouse = &buf; 643 mouse->operation = old_mouse->operation; 644 switch (mouse->operation) { 645 case MOUSE_MODE: 646 mouse->u.mode = old_mouse->u.mode; 647 break; 648 case MOUSE_SHOW: 649 case MOUSE_HIDE: 650 break; 651 case MOUSE_MOVEABS: 652 case MOUSE_MOVEREL: 653 case MOUSE_ACTION: 654 mouse->u.data.x = old_mouse->u.data.x; 655 mouse->u.data.y = old_mouse->u.data.y; 656 mouse->u.data.z = 0; 657 mouse->u.data.buttons = swapb[old_mouse->u.data.buttons & 0x7]; 658 break; 659 case MOUSE_GETINFO: 660 old_mouse->u.data.x = scp->mouse_xpos; 661 old_mouse->u.data.y = scp->mouse_ypos; 662 old_mouse->u.data.buttons = swapb[scp->mouse_buttons & 0x7]; 663 break; 664 default: 665 return EINVAL; 666 } 667 } 668 669 cur_scp = scp->sc->cur_scp; 670 671 switch (mouse->operation) { 672 case MOUSE_MODE: 673 if (ISSIGVALID(mouse->u.mode.signal)) { 674 scp->mouse_signal = mouse->u.mode.signal; 675 scp->mouse_proc = p; 676 scp->mouse_pid = p->p_pid; 677 } 678 else { 679 scp->mouse_signal = 0; 680 scp->mouse_proc = NULL; 681 scp->mouse_pid = 0; 682 } 683 return 0; 684 685 case MOUSE_SHOW: 686 if (!ISMOUSEAVAIL(scp->sc->adp->va_flags)) 687 return EINVAL; 688 s = spltty(); 689 if (!(scp->sc->flags & SC_MOUSE_ENABLED)) { 690 scp->sc->flags |= SC_MOUSE_ENABLED; 691 if (!ISGRAPHSC(cur_scp)) { 692 cur_scp->status |= MOUSE_VISIBLE; 693 mark_all(cur_scp); 694 } 695 splx(s); 696 return 0; 697 } else { 698 splx(s); 699 return EINVAL; 700 } 701 break; 702 703 case MOUSE_HIDE: 704 s = spltty(); 705 if (scp->sc->flags & SC_MOUSE_ENABLED) { 706 scp->sc->flags &= ~SC_MOUSE_ENABLED; 707 sc_remove_all_mouse(scp->sc); 708 splx(s); 709 return 0; 710 } else { 711 splx(s); 712 return EINVAL; 713 } 714 break; 715 716 case MOUSE_MOVEABS: 717 s = spltty(); 718 scp->mouse_xpos = mouse->u.data.x; 719 scp->mouse_ypos = mouse->u.data.y; 720 set_mouse_pos(scp); 721 splx(s); 722 break; 723 724 case MOUSE_MOVEREL: 725 s = spltty(); 726 scp->mouse_xpos += mouse->u.data.x; 727 scp->mouse_ypos += mouse->u.data.y; 728 set_mouse_pos(scp); 729 splx(s); 730 break; 731 732 case MOUSE_GETINFO: 733 mouse->u.data.x = scp->mouse_xpos; 734 mouse->u.data.y = scp->mouse_ypos; 735 mouse->u.data.z = 0; 736 mouse->u.data.buttons = scp->mouse_buttons; 737 return 0; 738 739 case MOUSE_ACTION: 740 case MOUSE_MOTION_EVENT: 741 /* send out mouse event on /dev/sysmouse */ 742 #if 0 743 /* this should maybe only be settable from /dev/consolectl SOS */ 744 if (SC_VTY(tp->t_dev) != SC_CONSOLECTL) 745 return ENOTTY; 746 #endif 747 mouse_status.dx += mouse->u.data.x; 748 mouse_status.dy += mouse->u.data.y; 749 mouse_status.dz += mouse->u.data.z; 750 if (mouse->operation == MOUSE_ACTION) 751 mouse_status.button = mouse->u.data.buttons; 752 mouse_status.flags |= 753 ((mouse->u.data.x || mouse->u.data.y || mouse->u.data.z) ? 754 MOUSE_POSCHANGED : 0) 755 | (mouse_status.obutton ^ mouse_status.button); 756 if (mouse_status.flags == 0) 757 return 0; 758 759 mtty = sc_get_mouse_tty(); 760 if (mtty->t_state & TS_ISOPEN) { 761 u_char buf[MOUSE_SYS_PACKETSIZE]; 762 763 /* the first five bytes are compatible with MouseSystems' */ 764 buf[0] = MOUSE_MSC_SYNC 765 | butmap[mouse_status.button & MOUSE_STDBUTTONS]; 766 i = imax(imin(mouse->u.data.x, 255), -256); 767 buf[1] = i >> 1; 768 buf[3] = i - buf[1]; 769 i = -imax(imin(mouse->u.data.y, 255), -256); 770 buf[2] = i >> 1; 771 buf[4] = i - buf[2]; 772 for (i = 0; i < MOUSE_MSC_PACKETSIZE; i++) 773 (*linesw[mtty->t_line].l_rint)(buf[i], mtty); 774 if (mouse_level >= 1) { /* extended part */ 775 i = imax(imin(mouse->u.data.z, 127), -128); 776 buf[5] = (i >> 1) & 0x7f; 777 buf[6] = (i - (i >> 1)) & 0x7f; 778 /* buttons 4-10 */ 779 buf[7] = (~mouse_status.button >> 3) & 0x7f; 780 for (i = MOUSE_MSC_PACKETSIZE; 781 i < MOUSE_SYS_PACKETSIZE; i++) 782 (*linesw[mtty->t_line].l_rint)(buf[i], mtty); 783 } 784 } 785 786 if (cur_scp->mouse_signal) { 787 cur_scp->mouse_buttons = mouse->u.data.buttons; 788 /* has controlling process died? */ 789 if (cur_scp->mouse_proc && 790 (cur_scp->mouse_proc != pfind(cur_scp->mouse_pid))){ 791 cur_scp->mouse_signal = 0; 792 cur_scp->mouse_proc = NULL; 793 cur_scp->mouse_pid = 0; 794 } 795 else 796 psignal(cur_scp->mouse_proc, cur_scp->mouse_signal); 797 break; 798 } 799 800 /* 801 * If any buttons are down or the mouse has moved a lot, 802 * stop the screen saver. 803 */ 804 if (((mouse->operation == MOUSE_ACTION) && mouse->u.data.buttons) 805 || (mouse->u.data.x*mouse->u.data.x 806 + mouse->u.data.y*mouse->u.data.y 807 >= SC_WAKEUP_DELTA*SC_WAKEUP_DELTA)) { 808 sc_touch_scrn_saver(); 809 } 810 811 if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL)) 812 break; 813 814 #ifndef SC_NO_CUTPASTE 815 if (cur_scp->sc->flags & SC_MOUSE_ENABLED) 816 cur_scp->status |= MOUSE_VISIBLE; 817 818 if (mouse->operation == MOUSE_ACTION) { 819 /* process button presses */ 820 if (cur_scp->mouse_buttons ^ mouse->u.data.buttons) { 821 cur_scp->mouse_buttons = mouse->u.data.buttons; 822 if (cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN) 823 mouse_cut_start(cur_scp); 824 else 825 mouse_cut_end(cur_scp); 826 if (cur_scp->mouse_buttons & MOUSE_BUTTON2DOWN || 827 cur_scp->mouse_buttons & MOUSE_BUTTON3DOWN) 828 mouse_paste(cur_scp); 829 } 830 } 831 #else /* SC_NO_CUTPASTE */ 832 if (mouse->operation == MOUSE_ACTION) 833 cur_scp->mouse_buttons = mouse->u.data.buttons; 834 #endif /* SC_NO_CUTPASTE */ 835 836 if (mouse->u.data.x != 0 || mouse->u.data.y != 0) { 837 s = spltty(); 838 cur_scp->mouse_xpos += mouse->u.data.x; 839 cur_scp->mouse_ypos += mouse->u.data.y; 840 set_mouse_pos(cur_scp); 841 splx(s); 842 } 843 break; 844 845 case MOUSE_BUTTON_EVENT: 846 if ((mouse->u.event.id & MOUSE_BUTTONS) == 0) 847 return EINVAL; 848 if (mouse->u.event.value < 0) 849 return EINVAL; 850 #if 0 851 /* this should maybe only be settable from /dev/consolectl SOS */ 852 if (SC_VTY(tp->t_dev) != SC_CONSOLECTL) 853 return ENOTTY; 854 #endif 855 if (mouse->u.event.value > 0) { 856 cur_scp->mouse_buttons |= mouse->u.event.id; 857 mouse_status.button |= mouse->u.event.id; 858 } else { 859 cur_scp->mouse_buttons &= ~mouse->u.event.id; 860 mouse_status.button &= ~mouse->u.event.id; 861 } 862 mouse_status.flags |= mouse_status.obutton ^ mouse_status.button; 863 if (mouse_status.flags == 0) 864 return 0; 865 866 mtty = sc_get_mouse_tty(); 867 if (mtty->t_state & TS_ISOPEN) { 868 u_char buf[MOUSE_SYS_PACKETSIZE]; 869 870 buf[0] = MOUSE_MSC_SYNC 871 | butmap[mouse_status.button & MOUSE_STDBUTTONS]; 872 buf[7] = (~mouse_status.button >> 3) & 0x7f; 873 buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0; 874 for (i = 0; 875 i < ((mouse_level >= 1) ? MOUSE_SYS_PACKETSIZE 876 : MOUSE_MSC_PACKETSIZE); i++) 877 (*linesw[mtty->t_line].l_rint)(buf[i], mtty); 878 } 879 880 if (cur_scp->mouse_signal) { 881 if (cur_scp->mouse_proc && 882 (cur_scp->mouse_proc != pfind(cur_scp->mouse_pid))){ 883 cur_scp->mouse_signal = 0; 884 cur_scp->mouse_proc = NULL; 885 cur_scp->mouse_pid = 0; 886 } 887 else 888 psignal(cur_scp->mouse_proc, cur_scp->mouse_signal); 889 break; 890 } 891 892 /* if a button is held down, stop the screen saver */ 893 if (mouse->u.event.value > 0) 894 sc_touch_scrn_saver(); 895 896 if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL)) 897 break; 898 899 #ifndef SC_NO_CUTPASTE 900 if (cur_scp->sc->flags & SC_MOUSE_ENABLED) 901 cur_scp->status |= MOUSE_VISIBLE; 902 903 switch (mouse->u.event.id) { 904 case MOUSE_BUTTON1DOWN: 905 switch (mouse->u.event.value % 4) { 906 case 0: /* up */ 907 mouse_cut_end(cur_scp); 908 break; 909 case 1: /* single click: start cut operation */ 910 mouse_cut_start(cur_scp); 911 break; 912 case 2: /* double click: cut a word */ 913 mouse_cut_word(cur_scp); 914 mouse_cut_end(cur_scp); 915 break; 916 case 3: /* triple click: cut a line */ 917 mouse_cut_line(cur_scp); 918 mouse_cut_end(cur_scp); 919 break; 920 } 921 break; 922 case MOUSE_BUTTON2DOWN: 923 switch (mouse->u.event.value) { 924 case 0: /* up */ 925 break; 926 default: 927 mouse_paste(cur_scp); 928 break; 929 } 930 break; 931 case MOUSE_BUTTON3DOWN: 932 switch (mouse->u.event.value) { 933 case 0: /* up */ 934 if (!(cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN)) 935 mouse_cut_end(cur_scp); 936 break; 937 default: 938 mouse_cut_extend(cur_scp); 939 break; 940 } 941 break; 942 } 943 #endif /* SC_NO_CUTPASTE */ 944 break; 945 946 default: 947 return EINVAL; 948 } 949 950 return 0; 951 } 952 953 /* MOUSE_XXX: /dev/sysmouse ioctls */ 954 case MOUSE_GETHWINFO: /* get device information */ 955 { 956 mousehw_t *hw = (mousehw_t *)data; 957 958 if (tp != sc_get_mouse_tty()) 959 return ENOTTY; 960 hw->buttons = 10; /* XXX unknown */ 961 hw->iftype = MOUSE_IF_SYSMOUSE; 962 hw->type = MOUSE_MOUSE; 963 hw->model = MOUSE_MODEL_GENERIC; 964 hw->hwid = 0; 965 return 0; 966 } 967 968 case MOUSE_GETMODE: /* get protocol/mode */ 969 { 970 mousemode_t *mode = (mousemode_t *)data; 971 972 if (tp != sc_get_mouse_tty()) 973 return ENOTTY; 974 mode->level = mouse_level; 975 switch (mode->level) { 976 case 0: 977 /* at this level, sysmouse emulates MouseSystems protocol */ 978 mode->protocol = MOUSE_PROTO_MSC; 979 mode->rate = -1; /* unknown */ 980 mode->resolution = -1; /* unknown */ 981 mode->accelfactor = 0; /* disabled */ 982 mode->packetsize = MOUSE_MSC_PACKETSIZE; 983 mode->syncmask[0] = MOUSE_MSC_SYNCMASK; 984 mode->syncmask[1] = MOUSE_MSC_SYNC; 985 break; 986 987 case 1: 988 /* at this level, sysmouse uses its own protocol */ 989 mode->protocol = MOUSE_PROTO_SYSMOUSE; 990 mode->rate = -1; 991 mode->resolution = -1; 992 mode->accelfactor = 0; 993 mode->packetsize = MOUSE_SYS_PACKETSIZE; 994 mode->syncmask[0] = MOUSE_SYS_SYNCMASK; 995 mode->syncmask[1] = MOUSE_SYS_SYNC; 996 break; 997 } 998 return 0; 999 } 1000 1001 case MOUSE_SETMODE: /* set protocol/mode */ 1002 { 1003 mousemode_t *mode = (mousemode_t *)data; 1004 1005 if (tp != sc_get_mouse_tty()) 1006 return ENOTTY; 1007 if ((mode->level < 0) || (mode->level > 1)) 1008 return EINVAL; 1009 sc_mouse_set_level(mode->level); 1010 return 0; 1011 } 1012 1013 case MOUSE_GETLEVEL: /* get operation level */ 1014 if (tp != sc_get_mouse_tty()) 1015 return ENOTTY; 1016 *(int *)data = mouse_level; 1017 return 0; 1018 1019 case MOUSE_SETLEVEL: /* set operation level */ 1020 if (tp != sc_get_mouse_tty()) 1021 return ENOTTY; 1022 if ((*(int *)data < 0) || (*(int *)data > 1)) 1023 return EINVAL; 1024 sc_mouse_set_level(*(int *)data); 1025 return 0; 1026 1027 case MOUSE_GETSTATUS: /* get accumulated mouse events */ 1028 if (tp != sc_get_mouse_tty()) 1029 return ENOTTY; 1030 s = spltty(); 1031 *(mousestatus_t *)data = mouse_status; 1032 mouse_status.flags = 0; 1033 mouse_status.obutton = mouse_status.button; 1034 mouse_status.dx = 0; 1035 mouse_status.dy = 0; 1036 mouse_status.dz = 0; 1037 splx(s); 1038 return 0; 1039 1040 #if notyet 1041 case MOUSE_GETVARS: /* get internal mouse variables */ 1042 case MOUSE_SETVARS: /* set internal mouse variables */ 1043 if (tp != sc_get_mouse_tty()) 1044 return ENOTTY; 1045 return ENODEV; 1046 #endif 1047 1048 case MOUSE_READSTATE: /* read status from the device */ 1049 case MOUSE_READDATA: /* read data from the device */ 1050 if (tp != sc_get_mouse_tty()) 1051 return ENOTTY; 1052 return ENODEV; 1053 } 1054 1055 return ENOIOCTL; 1056 } 1057 1058 #endif /* SC_NO_SYSMOUSE */ 1059 1060 #endif /* NSC */ 1061