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