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 * $Id:$ 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 int i; 255 256 /* delete cut markings in all vtys */ 257 for (i = 0; i < sc->vtys; ++i) { 258 if (sc->console[i] == NULL) 259 continue; 260 sc_remove_cutmarking(sc->console[i]); 261 } 262 } 263 264 void 265 sc_remove_all_mouse(sc_softc_t *sc) 266 { 267 int i; 268 269 for (i = 0; i < sc->vtys; ++i) { 270 if (sc->console[i] == NULL) 271 continue; 272 if (sc->console[i]->status & MOUSE_VISIBLE) { 273 sc->console[i]->status &= ~MOUSE_VISIBLE; 274 mark_all(sc->console[i]); 275 } 276 } 277 } 278 279 #define isspace(c) (((c) & 0xff) == ' ') 280 281 /* skip spaces to right */ 282 static int 283 skip_spc_right(scr_stat *scp, int p) 284 { 285 int c; 286 int i; 287 288 for (i = p % scp->xsize; i < scp->xsize; ++i) { 289 c = sc_vtb_getc(&scp->vtb, p); 290 if (!isspace(c)) 291 break; 292 ++p; 293 } 294 return i; 295 } 296 297 /* skip spaces to left */ 298 static int 299 skip_spc_left(scr_stat *scp, int p) 300 { 301 int c; 302 int i; 303 304 for (i = p-- % scp->xsize - 1; i >= 0; --i) { 305 c = sc_vtb_getc(&scp->vtb, p); 306 if (!isspace(c)) 307 break; 308 --p; 309 } 310 return i; 311 } 312 313 /* copy marked region to the cut buffer */ 314 static void 315 mouse_cut(scr_stat *scp) 316 { 317 int start; 318 int end; 319 int from; 320 int to; 321 int blank; 322 int c; 323 int p; 324 int s; 325 int i; 326 327 start = scp->mouse_cut_start; 328 end = scp->mouse_cut_end; 329 if (scp->mouse_pos >= start) { 330 from = start; 331 to = end = scp->mouse_pos; 332 } else { 333 from = end = scp->mouse_pos; 334 to = start - 1; 335 } 336 for (p = from, i = blank = 0; p <= to; ++p) { 337 cut_buffer[i] = sc_vtb_getc(&scp->vtb, p); 338 /* remember the position of the last non-space char */ 339 if (!isspace(cut_buffer[i++])) 340 blank = i; /* the first space after the last non-space */ 341 /* trim trailing blank when crossing lines */ 342 if ((p % scp->xsize) == (scp->xsize - 1)) { 343 cut_buffer[blank] = '\r'; 344 i = blank + 1; 345 } 346 } 347 cut_buffer[i] = '\0'; 348 349 /* scan towards the end of the last line */ 350 --p; 351 for (i = p % scp->xsize; i < scp->xsize; ++i) { 352 c = sc_vtb_getc(&scp->vtb, p); 353 if (!isspace(c)) 354 break; 355 ++p; 356 } 357 /* if there is nothing but blank chars, trim them, but mark towards eol */ 358 if (i >= scp->xsize) { 359 if (end >= start) 360 to = end = p - 1; 361 else 362 to = start = p; 363 cut_buffer[blank++] = '\r'; 364 cut_buffer[blank] = '\0'; 365 } 366 367 /* remove the current marking */ 368 s = spltty(); 369 if (scp->mouse_cut_start <= scp->mouse_cut_end) { 370 mark_for_update(scp, scp->mouse_cut_start); 371 mark_for_update(scp, scp->mouse_cut_end); 372 } else if (scp->mouse_cut_end >= 0) { 373 mark_for_update(scp, scp->mouse_cut_end); 374 mark_for_update(scp, scp->mouse_cut_start); 375 } 376 377 /* mark the new region */ 378 scp->mouse_cut_start = start; 379 scp->mouse_cut_end = end; 380 mark_for_update(scp, from); 381 mark_for_update(scp, to); 382 splx(s); 383 } 384 385 /* a mouse button is pressed, start cut operation */ 386 static void 387 mouse_cut_start(scr_stat *scp) 388 { 389 int i; 390 int j; 391 int s; 392 393 if (scp->status & MOUSE_VISIBLE) { 394 i = scp->mouse_cut_start; 395 j = scp->mouse_cut_end; 396 sc_remove_all_cutmarkings(scp->sc); 397 if (scp->mouse_pos == i && i == j) { 398 cut_buffer[0] = '\0'; 399 } else if (skip_spc_right(scp, scp->mouse_pos) >= scp->xsize) { 400 /* if the pointer is on trailing blank chars, mark towards eol */ 401 i = skip_spc_left(scp, scp->mouse_pos) + 1; 402 s = spltty(); 403 scp->mouse_cut_start = 404 (scp->mouse_pos / scp->xsize) * scp->xsize + i; 405 scp->mouse_cut_end = 406 (scp->mouse_pos / scp->xsize + 1) * scp->xsize - 1; 407 splx(s); 408 cut_buffer[0] = '\r'; 409 cut_buffer[1] = '\0'; 410 scp->status |= MOUSE_CUTTING; 411 } else { 412 s = spltty(); 413 scp->mouse_cut_start = scp->mouse_pos; 414 scp->mouse_cut_end = scp->mouse_cut_start; 415 splx(s); 416 cut_buffer[0] = sc_vtb_getc(&scp->vtb, scp->mouse_cut_start); 417 cut_buffer[1] = '\0'; 418 scp->status |= MOUSE_CUTTING; 419 } 420 mark_all(scp); /* this is probably overkill XXX */ 421 } 422 } 423 424 /* end of cut operation */ 425 static void 426 mouse_cut_end(scr_stat *scp) 427 { 428 if (scp->status & MOUSE_VISIBLE) 429 scp->status &= ~MOUSE_CUTTING; 430 } 431 432 /* copy a word under the mouse pointer */ 433 static void 434 mouse_cut_word(scr_stat *scp) 435 { 436 int start; 437 int end; 438 int sol; 439 int eol; 440 int c; 441 int s; 442 int i; 443 int j; 444 445 /* 446 * Because we don't have locale information in the kernel, 447 * we only distinguish space char and non-space chars. Punctuation 448 * chars, symbols and other regular chars are all treated alike. 449 */ 450 if (scp->status & MOUSE_VISIBLE) { 451 /* remove the current cut mark */ 452 s = spltty(); 453 if (scp->mouse_cut_start <= scp->mouse_cut_end) { 454 mark_for_update(scp, scp->mouse_cut_start); 455 mark_for_update(scp, scp->mouse_cut_end); 456 } else if (scp->mouse_cut_end >= 0) { 457 mark_for_update(scp, scp->mouse_cut_end); 458 mark_for_update(scp, scp->mouse_cut_start); 459 } 460 scp->mouse_cut_start = scp->xsize*scp->ysize; 461 scp->mouse_cut_end = -1; 462 splx(s); 463 464 sol = (scp->mouse_pos / scp->xsize) * scp->xsize; 465 eol = sol + scp->xsize; 466 c = sc_vtb_getc(&scp->vtb, scp->mouse_pos); 467 if (isspace(c)) { 468 /* blank space */ 469 for (j = scp->mouse_pos; j >= sol; --j) { 470 c = sc_vtb_getc(&scp->vtb, j); 471 if (!isspace(c)) 472 break; 473 } 474 start = ++j; 475 for (j = scp->mouse_pos; j < eol; ++j) { 476 c = sc_vtb_getc(&scp->vtb, j); 477 if (!isspace(c)) 478 break; 479 } 480 end = j - 1; 481 } else { 482 /* non-space word */ 483 for (j = scp->mouse_pos; j >= sol; --j) { 484 c = sc_vtb_getc(&scp->vtb, j); 485 if (isspace(c)) 486 break; 487 } 488 start = ++j; 489 for (j = scp->mouse_pos; j < eol; ++j) { 490 c = sc_vtb_getc(&scp->vtb, j); 491 if (isspace(c)) 492 break; 493 } 494 end = j - 1; 495 } 496 497 /* copy the found word */ 498 for (i = 0, j = start; j <= end; ++j) 499 cut_buffer[i++] = sc_vtb_getc(&scp->vtb, j); 500 cut_buffer[i] = '\0'; 501 scp->status |= MOUSE_CUTTING; 502 503 /* mark the region */ 504 s = spltty(); 505 scp->mouse_cut_start = start; 506 scp->mouse_cut_end = end; 507 mark_for_update(scp, start); 508 mark_for_update(scp, end); 509 splx(s); 510 } 511 } 512 513 /* copy a line under the mouse pointer */ 514 static void 515 mouse_cut_line(scr_stat *scp) 516 { 517 int s; 518 int i; 519 int j; 520 521 if (scp->status & MOUSE_VISIBLE) { 522 /* remove the current cut mark */ 523 s = spltty(); 524 if (scp->mouse_cut_start <= scp->mouse_cut_end) { 525 mark_for_update(scp, scp->mouse_cut_start); 526 mark_for_update(scp, scp->mouse_cut_end); 527 } else if (scp->mouse_cut_end >= 0) { 528 mark_for_update(scp, scp->mouse_cut_end); 529 mark_for_update(scp, scp->mouse_cut_start); 530 } 531 532 /* mark the entire line */ 533 scp->mouse_cut_start = 534 (scp->mouse_pos / scp->xsize) * scp->xsize; 535 scp->mouse_cut_end = scp->mouse_cut_start + scp->xsize - 1; 536 mark_for_update(scp, scp->mouse_cut_start); 537 mark_for_update(scp, scp->mouse_cut_end); 538 splx(s); 539 540 /* copy the line into the cut buffer */ 541 for (i = 0, j = scp->mouse_cut_start; j <= scp->mouse_cut_end; ++j) 542 cut_buffer[i++] = sc_vtb_getc(&scp->vtb, j); 543 cut_buffer[i++] = '\r'; 544 cut_buffer[i] = '\0'; 545 scp->status |= MOUSE_CUTTING; 546 } 547 } 548 549 /* extend the marked region to the mouse pointer position */ 550 static void 551 mouse_cut_extend(scr_stat *scp) 552 { 553 int start; 554 int end; 555 int s; 556 557 if ((scp->status & MOUSE_VISIBLE) && !(scp->status & MOUSE_CUTTING) 558 && (scp->mouse_cut_end >= 0)) { 559 if (scp->mouse_cut_start <= scp->mouse_cut_end) { 560 start = scp->mouse_cut_start; 561 end = scp->mouse_cut_end; 562 } else { 563 start = scp->mouse_cut_end; 564 end = scp->mouse_cut_start - 1; 565 } 566 s = spltty(); 567 if (scp->mouse_pos > end) { 568 scp->mouse_cut_start = start; 569 scp->mouse_cut_end = end; 570 } else if (scp->mouse_pos < start) { 571 scp->mouse_cut_start = end + 1; 572 scp->mouse_cut_end = start; 573 } else { 574 if (scp->mouse_pos - start > end + 1 - scp->mouse_pos) { 575 scp->mouse_cut_start = start; 576 scp->mouse_cut_end = end; 577 } else { 578 scp->mouse_cut_start = end + 1; 579 scp->mouse_cut_end = start; 580 } 581 } 582 splx(s); 583 mouse_cut(scp); 584 scp->status |= MOUSE_CUTTING; 585 } 586 } 587 588 /* paste cut buffer contents into the current vty */ 589 static void 590 mouse_paste(scr_stat *scp) 591 { 592 if (scp->status & MOUSE_VISIBLE) 593 sc_paste(scp, cut_buffer, strlen(cut_buffer)); 594 } 595 596 #endif /* SC_NO_CUTPASTE */ 597 598 int 599 sc_mouse_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, 600 struct proc *p) 601 { 602 603 scr_stat *scp; 604 int s; 605 int i; 606 607 /* scp == NULL, if tp == sc_get_mouse_tty() (/dev/sysmouse) */ 608 scp = sc_get_scr_stat(tp->t_dev); 609 610 switch (cmd) { 611 612 case CONS_MOUSECTL: /* control mouse arrow */ 613 case OLD_CONS_MOUSECTL: 614 { 615 /* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */ 616 static int butmap[8] = { 617 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, 618 MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, 619 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP, 620 MOUSE_MSC_BUTTON3UP, 621 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP, 622 MOUSE_MSC_BUTTON2UP, 623 MOUSE_MSC_BUTTON1UP, 624 0, 625 }; 626 mouse_info_t *mouse = (mouse_info_t*)data; 627 mouse_info_t buf; 628 scr_stat *cur_scp; 629 struct tty *mtty; 630 631 if (scp == NULL) 632 return ENOTTY; 633 634 if (cmd == OLD_CONS_MOUSECTL) { 635 static u_char swapb[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; 636 old_mouse_info_t *old_mouse = (old_mouse_info_t *)data; 637 638 mouse = &buf; 639 mouse->operation = old_mouse->operation; 640 switch (mouse->operation) { 641 case MOUSE_MODE: 642 mouse->u.mode = old_mouse->u.mode; 643 break; 644 case MOUSE_SHOW: 645 case MOUSE_HIDE: 646 break; 647 case MOUSE_MOVEABS: 648 case MOUSE_MOVEREL: 649 case MOUSE_ACTION: 650 mouse->u.data.x = old_mouse->u.data.x; 651 mouse->u.data.y = old_mouse->u.data.y; 652 mouse->u.data.z = 0; 653 mouse->u.data.buttons = swapb[old_mouse->u.data.buttons & 0x7]; 654 break; 655 case MOUSE_GETINFO: 656 old_mouse->u.data.x = scp->mouse_xpos; 657 old_mouse->u.data.y = scp->mouse_ypos; 658 old_mouse->u.data.buttons = swapb[scp->mouse_buttons & 0x7]; 659 break; 660 default: 661 return EINVAL; 662 } 663 } 664 665 cur_scp = scp->sc->cur_scp; 666 667 switch (mouse->operation) { 668 case MOUSE_MODE: 669 if (ISSIGVALID(mouse->u.mode.signal)) { 670 scp->mouse_signal = mouse->u.mode.signal; 671 scp->mouse_proc = p; 672 scp->mouse_pid = p->p_pid; 673 } 674 else { 675 scp->mouse_signal = 0; 676 scp->mouse_proc = NULL; 677 scp->mouse_pid = 0; 678 } 679 return 0; 680 681 case MOUSE_SHOW: 682 if (!ISMOUSEAVAIL(scp->sc->adp->va_flags)) 683 return EINVAL; 684 s = spltty(); 685 if (!(scp->sc->flags & SC_MOUSE_ENABLED)) { 686 scp->sc->flags |= SC_MOUSE_ENABLED; 687 if (!ISGRAPHSC(cur_scp)) { 688 cur_scp->status |= MOUSE_VISIBLE; 689 mark_all(cur_scp); 690 } 691 splx(s); 692 return 0; 693 } else { 694 splx(s); 695 return EINVAL; 696 } 697 break; 698 #if 0 699 if (!(scp->status & MOUSE_ENABLED)) { 700 scp->mouse_oldpos = scp->mouse_pos; 701 scp->status |= MOUSE_ENABLED; 702 if (!ISGRAPHSC(scp)) 703 scp->status |= MOUSE_VISIBLE; 704 splx(s); 705 mark_all(scp); 706 return 0; 707 } else { 708 splx(s); 709 return EINVAL; 710 } 711 break; 712 #endif 713 714 case MOUSE_HIDE: 715 s = spltty(); 716 if (scp->sc->flags & SC_MOUSE_ENABLED) { 717 scp->sc->flags &= ~SC_MOUSE_ENABLED; 718 sc_remove_all_mouse(scp->sc); 719 splx(s); 720 return 0; 721 } else { 722 splx(s); 723 return EINVAL; 724 } 725 break; 726 #if 0 727 if (scp->status & MOUSE_ENABLED) { 728 scp->status &= ~(MOUSE_ENABLED | MOUSE_VISIBLE); 729 mark_all(scp); 730 splx(s); 731 return 0; 732 } else { 733 splx(s); 734 return EINVAL; 735 } 736 break; 737 #endif 738 739 case MOUSE_MOVEABS: 740 s = spltty(); 741 scp->mouse_xpos = mouse->u.data.x; 742 scp->mouse_ypos = mouse->u.data.y; 743 set_mouse_pos(scp); 744 splx(s); 745 break; 746 747 case MOUSE_MOVEREL: 748 s = spltty(); 749 scp->mouse_xpos += mouse->u.data.x; 750 scp->mouse_ypos += mouse->u.data.y; 751 set_mouse_pos(scp); 752 splx(s); 753 break; 754 755 case MOUSE_GETINFO: 756 mouse->u.data.x = scp->mouse_xpos; 757 mouse->u.data.y = scp->mouse_ypos; 758 mouse->u.data.z = 0; 759 mouse->u.data.buttons = scp->mouse_buttons; 760 return 0; 761 762 case MOUSE_ACTION: 763 case MOUSE_MOTION_EVENT: 764 /* send out mouse event on /dev/sysmouse */ 765 #if 0 766 /* this should maybe only be settable from /dev/consolectl SOS */ 767 if (SC_VTY(tp->t_dev) != SC_CONSOLECTL) 768 return ENOTTY; 769 #endif 770 mouse_status.dx += mouse->u.data.x; 771 mouse_status.dy += mouse->u.data.y; 772 mouse_status.dz += mouse->u.data.z; 773 if (mouse->operation == MOUSE_ACTION) 774 mouse_status.button = mouse->u.data.buttons; 775 mouse_status.flags |= 776 ((mouse->u.data.x || mouse->u.data.y || mouse->u.data.z) ? 777 MOUSE_POSCHANGED : 0) 778 | (mouse_status.obutton ^ mouse_status.button); 779 if (mouse_status.flags == 0) 780 return 0; 781 782 mtty = sc_get_mouse_tty(); 783 if (mtty->t_state & TS_ISOPEN) { 784 u_char buf[MOUSE_SYS_PACKETSIZE]; 785 786 /* the first five bytes are compatible with MouseSystems' */ 787 buf[0] = MOUSE_MSC_SYNC 788 | butmap[mouse_status.button & MOUSE_STDBUTTONS]; 789 i = imax(imin(mouse->u.data.x, 255), -256); 790 buf[1] = i >> 1; 791 buf[3] = i - buf[1]; 792 i = -imax(imin(mouse->u.data.y, 255), -256); 793 buf[2] = i >> 1; 794 buf[4] = i - buf[2]; 795 for (i = 0; i < MOUSE_MSC_PACKETSIZE; i++) 796 (*linesw[mtty->t_line].l_rint)(buf[i], mtty); 797 if (mouse_level >= 1) { /* extended part */ 798 i = imax(imin(mouse->u.data.z, 127), -128); 799 buf[5] = (i >> 1) & 0x7f; 800 buf[6] = (i - (i >> 1)) & 0x7f; 801 /* buttons 4-10 */ 802 buf[7] = (~mouse_status.button >> 3) & 0x7f; 803 for (i = MOUSE_MSC_PACKETSIZE; 804 i < MOUSE_SYS_PACKETSIZE; i++) 805 (*linesw[mtty->t_line].l_rint)(buf[i], mtty); 806 } 807 } 808 809 if (cur_scp->mouse_signal) { 810 cur_scp->mouse_buttons = mouse->u.data.buttons; 811 /* has controlling process died? */ 812 if (cur_scp->mouse_proc && 813 (cur_scp->mouse_proc != pfind(cur_scp->mouse_pid))){ 814 cur_scp->mouse_signal = 0; 815 cur_scp->mouse_proc = NULL; 816 cur_scp->mouse_pid = 0; 817 } 818 else 819 psignal(cur_scp->mouse_proc, cur_scp->mouse_signal); 820 break; 821 } 822 823 /* 824 * If any buttons are down or the mouse has moved a lot, 825 * stop the screen saver. 826 */ 827 if (((mouse->operation == MOUSE_ACTION) && mouse->u.data.buttons) 828 || (mouse->u.data.x*mouse->u.data.x 829 + mouse->u.data.y*mouse->u.data.y 830 >= SC_WAKEUP_DELTA*SC_WAKEUP_DELTA)) { 831 sc_touch_scrn_saver(); 832 } 833 834 if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL)) 835 break; 836 837 #ifndef SC_NO_CUTPASTE 838 if (cur_scp->sc->flags & SC_MOUSE_ENABLED) 839 cur_scp->status |= MOUSE_VISIBLE; 840 841 if (mouse->operation == MOUSE_ACTION) { 842 /* process button presses */ 843 if (cur_scp->mouse_buttons ^ mouse->u.data.buttons) { 844 cur_scp->mouse_buttons = mouse->u.data.buttons; 845 if (cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN) 846 mouse_cut_start(cur_scp); 847 else 848 mouse_cut_end(cur_scp); 849 if (cur_scp->mouse_buttons & MOUSE_BUTTON2DOWN || 850 cur_scp->mouse_buttons & MOUSE_BUTTON3DOWN) 851 mouse_paste(cur_scp); 852 } 853 } 854 #else /* SC_NO_CUTPASTE */ 855 if (mouse->operation == MOUSE_ACTION) 856 cur_scp->mouse_buttons = mouse->u.data.buttons; 857 #endif /* SC_NO_CUTPASTE */ 858 859 if (mouse->u.data.x != 0 || mouse->u.data.y != 0) { 860 s = spltty(); 861 cur_scp->mouse_xpos += mouse->u.data.x; 862 cur_scp->mouse_ypos += mouse->u.data.y; 863 set_mouse_pos(cur_scp); 864 splx(s); 865 } 866 break; 867 868 case MOUSE_BUTTON_EVENT: 869 if ((mouse->u.event.id & MOUSE_BUTTONS) == 0) 870 return EINVAL; 871 if (mouse->u.event.value < 0) 872 return EINVAL; 873 #if 0 874 /* this should maybe only be settable from /dev/consolectl SOS */ 875 if (SC_VTY(tp->t_dev) != SC_CONSOLECTL) 876 return ENOTTY; 877 #endif 878 if (mouse->u.event.value > 0) { 879 cur_scp->mouse_buttons |= mouse->u.event.id; 880 mouse_status.button |= mouse->u.event.id; 881 } else { 882 cur_scp->mouse_buttons &= ~mouse->u.event.id; 883 mouse_status.button &= ~mouse->u.event.id; 884 } 885 mouse_status.flags |= mouse_status.obutton ^ mouse_status.button; 886 if (mouse_status.flags == 0) 887 return 0; 888 889 mtty = sc_get_mouse_tty(); 890 if (mtty->t_state & TS_ISOPEN) { 891 u_char buf[MOUSE_SYS_PACKETSIZE]; 892 893 buf[0] = MOUSE_MSC_SYNC 894 | butmap[mouse_status.button & MOUSE_STDBUTTONS]; 895 buf[7] = (~mouse_status.button >> 3) & 0x7f; 896 buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0; 897 for (i = 0; 898 i < ((mouse_level >= 1) ? MOUSE_SYS_PACKETSIZE 899 : MOUSE_MSC_PACKETSIZE); i++) 900 (*linesw[mtty->t_line].l_rint)(buf[i], mtty); 901 } 902 903 if (cur_scp->mouse_signal) { 904 if (cur_scp->mouse_proc && 905 (cur_scp->mouse_proc != pfind(cur_scp->mouse_pid))){ 906 cur_scp->mouse_signal = 0; 907 cur_scp->mouse_proc = NULL; 908 cur_scp->mouse_pid = 0; 909 } 910 else 911 psignal(cur_scp->mouse_proc, cur_scp->mouse_signal); 912 break; 913 } 914 915 /* if a button is held down, stop the screen saver */ 916 if (mouse->u.event.value > 0) 917 sc_touch_scrn_saver(); 918 919 if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL)) 920 break; 921 922 #ifndef SC_NO_CUTPASTE 923 if (cur_scp->sc->flags & SC_MOUSE_ENABLED) 924 cur_scp->status |= MOUSE_VISIBLE; 925 926 switch (mouse->u.event.id) { 927 case MOUSE_BUTTON1DOWN: 928 switch (mouse->u.event.value % 4) { 929 case 0: /* up */ 930 mouse_cut_end(cur_scp); 931 break; 932 case 1: /* single click: start cut operation */ 933 mouse_cut_start(cur_scp); 934 break; 935 case 2: /* double click: cut a word */ 936 mouse_cut_word(cur_scp); 937 mouse_cut_end(cur_scp); 938 break; 939 case 3: /* triple click: cut a line */ 940 mouse_cut_line(cur_scp); 941 mouse_cut_end(cur_scp); 942 break; 943 } 944 break; 945 case MOUSE_BUTTON2DOWN: 946 switch (mouse->u.event.value) { 947 case 0: /* up */ 948 break; 949 default: 950 mouse_paste(cur_scp); 951 break; 952 } 953 break; 954 case MOUSE_BUTTON3DOWN: 955 switch (mouse->u.event.value) { 956 case 0: /* up */ 957 if (!(cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN)) 958 mouse_cut_end(cur_scp); 959 break; 960 default: 961 mouse_cut_extend(cur_scp); 962 break; 963 } 964 break; 965 } 966 #endif /* SC_NO_CUTPASTE */ 967 break; 968 969 default: 970 return EINVAL; 971 } 972 973 return 0; 974 } 975 976 /* MOUSE_XXX: /dev/sysmouse ioctls */ 977 case MOUSE_GETHWINFO: /* get device information */ 978 { 979 mousehw_t *hw = (mousehw_t *)data; 980 981 if (tp != sc_get_mouse_tty()) 982 return ENOTTY; 983 hw->buttons = 10; /* XXX unknown */ 984 hw->iftype = MOUSE_IF_SYSMOUSE; 985 hw->type = MOUSE_MOUSE; 986 hw->model = MOUSE_MODEL_GENERIC; 987 hw->hwid = 0; 988 return 0; 989 } 990 991 case MOUSE_GETMODE: /* get protocol/mode */ 992 { 993 mousemode_t *mode = (mousemode_t *)data; 994 995 if (tp != sc_get_mouse_tty()) 996 return ENOTTY; 997 mode->level = mouse_level; 998 switch (mode->level) { 999 case 0: 1000 /* at this level, sysmouse emulates MouseSystems protocol */ 1001 mode->protocol = MOUSE_PROTO_MSC; 1002 mode->rate = -1; /* unknown */ 1003 mode->resolution = -1; /* unknown */ 1004 mode->accelfactor = 0; /* disabled */ 1005 mode->packetsize = MOUSE_MSC_PACKETSIZE; 1006 mode->syncmask[0] = MOUSE_MSC_SYNCMASK; 1007 mode->syncmask[1] = MOUSE_MSC_SYNC; 1008 break; 1009 1010 case 1: 1011 /* at this level, sysmouse uses its own protocol */ 1012 mode->protocol = MOUSE_PROTO_SYSMOUSE; 1013 mode->rate = -1; 1014 mode->resolution = -1; 1015 mode->accelfactor = 0; 1016 mode->packetsize = MOUSE_SYS_PACKETSIZE; 1017 mode->syncmask[0] = MOUSE_SYS_SYNCMASK; 1018 mode->syncmask[1] = MOUSE_SYS_SYNC; 1019 break; 1020 } 1021 return 0; 1022 } 1023 1024 case MOUSE_SETMODE: /* set protocol/mode */ 1025 { 1026 mousemode_t *mode = (mousemode_t *)data; 1027 1028 if (tp != sc_get_mouse_tty()) 1029 return ENOTTY; 1030 if ((mode->level < 0) || (mode->level > 1)) 1031 return EINVAL; 1032 sc_mouse_set_level(mode->level); 1033 return 0; 1034 } 1035 1036 case MOUSE_GETLEVEL: /* get operation level */ 1037 if (tp != sc_get_mouse_tty()) 1038 return ENOTTY; 1039 *(int *)data = mouse_level; 1040 return 0; 1041 1042 case MOUSE_SETLEVEL: /* set operation level */ 1043 if (tp != sc_get_mouse_tty()) 1044 return ENOTTY; 1045 if ((*(int *)data < 0) || (*(int *)data > 1)) 1046 return EINVAL; 1047 sc_mouse_set_level(*(int *)data); 1048 return 0; 1049 1050 case MOUSE_GETSTATUS: /* get accumulated mouse events */ 1051 if (tp != sc_get_mouse_tty()) 1052 return ENOTTY; 1053 s = spltty(); 1054 *(mousestatus_t *)data = mouse_status; 1055 mouse_status.flags = 0; 1056 mouse_status.obutton = mouse_status.button; 1057 mouse_status.dx = 0; 1058 mouse_status.dy = 0; 1059 mouse_status.dz = 0; 1060 splx(s); 1061 return 0; 1062 1063 #if notyet 1064 case MOUSE_GETVARS: /* get internal mouse variables */ 1065 case MOUSE_SETVARS: /* set internal mouse variables */ 1066 if (tp != sc_get_mouse_tty()) 1067 return ENOTTY; 1068 return ENODEV; 1069 #endif 1070 1071 case MOUSE_READSTATE: /* read status from the device */ 1072 case MOUSE_READDATA: /* read data from the device */ 1073 if (tp != sc_get_mouse_tty()) 1074 return ENOTTY; 1075 return ENODEV; 1076 } 1077 1078 return ENOIOCTL; 1079 } 1080 1081 #endif /* SC_NO_SYSMOUSE */ 1082 1083 #endif /* NSC */ 1084