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: src/sys/dev/syscons/scmouse.c,v 1.12.2.3 2001/07/28 12:51:47 yokota Exp $ 27 * $DragonFly: src/sys/dev/misc/syscons/scmouse.c,v 1.3 2003/06/23 17:55:35 dillon Exp $ 28 */ 29 30 #include "opt_syscons.h" 31 32 #include <limits.h> 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/conf.h> 36 #include <sys/signalvar.h> 37 #include <sys/proc.h> 38 #include <sys/tty.h> 39 #include <sys/malloc.h> 40 41 #include <machine/console.h> 42 #include <machine/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 thread *td) 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 if (cmd == OLD_CONS_MOUSECTL) { 621 static u_char swapb[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; 622 old_mouse_info_t *old_mouse = (old_mouse_info_t *)data; 623 624 mouse = &buf; 625 mouse->operation = old_mouse->operation; 626 switch (mouse->operation) { 627 case MOUSE_MODE: 628 mouse->u.mode = old_mouse->u.mode; 629 break; 630 case MOUSE_SHOW: 631 case MOUSE_HIDE: 632 break; 633 case MOUSE_MOVEABS: 634 case MOUSE_MOVEREL: 635 case MOUSE_ACTION: 636 mouse->u.data.x = old_mouse->u.data.x; 637 mouse->u.data.y = old_mouse->u.data.y; 638 mouse->u.data.z = 0; 639 mouse->u.data.buttons = swapb[old_mouse->u.data.buttons & 0x7]; 640 break; 641 case MOUSE_GETINFO: 642 old_mouse->u.data.x = scp->mouse_xpos; 643 old_mouse->u.data.y = scp->mouse_ypos; 644 old_mouse->u.data.buttons = swapb[scp->mouse_buttons & 0x7]; 645 return 0; 646 default: 647 return EINVAL; 648 } 649 } 650 651 cur_scp = scp->sc->cur_scp; 652 653 switch (mouse->operation) { 654 case MOUSE_MODE: 655 if (ISSIGVALID(mouse->u.mode.signal)) { 656 scp->mouse_signal = mouse->u.mode.signal; 657 scp->mouse_proc = td->td_proc; 658 scp->mouse_pid = td->td_proc->p_pid; 659 } 660 else { 661 scp->mouse_signal = 0; 662 scp->mouse_proc = NULL; 663 scp->mouse_pid = 0; 664 } 665 return 0; 666 667 case MOUSE_SHOW: 668 s = spltty(); 669 if (!(scp->sc->flags & SC_MOUSE_ENABLED)) { 670 scp->sc->flags |= SC_MOUSE_ENABLED; 671 cur_scp->status &= ~MOUSE_HIDDEN; 672 if (!ISGRAPHSC(cur_scp)) 673 mark_all(cur_scp); 674 splx(s); 675 return 0; 676 } else { 677 splx(s); 678 return EINVAL; 679 } 680 break; 681 682 case MOUSE_HIDE: 683 s = spltty(); 684 if (scp->sc->flags & SC_MOUSE_ENABLED) { 685 scp->sc->flags &= ~SC_MOUSE_ENABLED; 686 sc_remove_all_mouse(scp->sc); 687 splx(s); 688 return 0; 689 } else { 690 splx(s); 691 return EINVAL; 692 } 693 break; 694 695 case MOUSE_MOVEABS: 696 s = spltty(); 697 scp->mouse_xpos = mouse->u.data.x; 698 scp->mouse_ypos = mouse->u.data.y; 699 set_mouse_pos(scp); 700 splx(s); 701 break; 702 703 case MOUSE_MOVEREL: 704 s = spltty(); 705 scp->mouse_xpos += mouse->u.data.x; 706 scp->mouse_ypos += mouse->u.data.y; 707 set_mouse_pos(scp); 708 splx(s); 709 break; 710 711 case MOUSE_GETINFO: 712 mouse->u.data.x = scp->mouse_xpos; 713 mouse->u.data.y = scp->mouse_ypos; 714 mouse->u.data.z = 0; 715 mouse->u.data.buttons = scp->mouse_buttons; 716 return 0; 717 718 case MOUSE_ACTION: 719 case MOUSE_MOTION_EVENT: 720 /* send out mouse event on /dev/sysmouse */ 721 #if 0 722 /* this should maybe only be settable from /dev/consolectl SOS */ 723 if (SC_VTY(tp->t_dev) != SC_CONSOLECTL) 724 return ENOTTY; 725 #endif 726 s = spltty(); 727 if (mouse->u.data.x != 0 || mouse->u.data.y != 0) { 728 cur_scp->mouse_xpos += mouse->u.data.x; 729 cur_scp->mouse_ypos += mouse->u.data.y; 730 set_mouse_pos(cur_scp); 731 } 732 f = 0; 733 if (mouse->operation == MOUSE_ACTION) { 734 f = cur_scp->mouse_buttons ^ mouse->u.data.buttons; 735 cur_scp->mouse_buttons = mouse->u.data.buttons; 736 } 737 splx(s); 738 739 if (sysmouse_event(mouse) == 0) 740 return 0; 741 742 /* 743 * If any buttons are down or the mouse has moved a lot, 744 * stop the screen saver. 745 */ 746 if (((mouse->operation == MOUSE_ACTION) && mouse->u.data.buttons) 747 || (mouse->u.data.x*mouse->u.data.x 748 + mouse->u.data.y*mouse->u.data.y 749 >= SC_WAKEUP_DELTA*SC_WAKEUP_DELTA)) { 750 sc_touch_scrn_saver(); 751 } 752 753 cur_scp->status &= ~MOUSE_HIDDEN; 754 755 if (cur_scp->mouse_signal) { 756 /* has controlling process died? */ 757 if (cur_scp->mouse_proc && 758 (cur_scp->mouse_proc != pfind(cur_scp->mouse_pid))){ 759 cur_scp->mouse_signal = 0; 760 cur_scp->mouse_proc = NULL; 761 cur_scp->mouse_pid = 0; 762 } else { 763 psignal(cur_scp->mouse_proc, cur_scp->mouse_signal); 764 break; 765 } 766 } 767 768 if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL)) 769 break; 770 771 #ifndef SC_NO_CUTPASTE 772 if ((mouse->operation == MOUSE_ACTION) && f) { 773 /* process button presses */ 774 if (cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN) 775 mouse_cut_start(cur_scp); 776 else 777 mouse_cut_end(cur_scp); 778 if (cur_scp->mouse_buttons & MOUSE_BUTTON2DOWN || 779 cur_scp->mouse_buttons & MOUSE_BUTTON3DOWN) 780 mouse_paste(cur_scp); 781 } 782 #endif /* SC_NO_CUTPASTE */ 783 break; 784 785 case MOUSE_BUTTON_EVENT: 786 if ((mouse->u.event.id & MOUSE_BUTTONS) == 0) 787 return EINVAL; 788 if (mouse->u.event.value < 0) 789 return EINVAL; 790 #if 0 791 /* this should maybe only be settable from /dev/consolectl SOS */ 792 if (SC_VTY(tp->t_dev) != SC_CONSOLECTL) 793 return ENOTTY; 794 #endif 795 if (mouse->u.event.value > 0) 796 cur_scp->mouse_buttons |= mouse->u.event.id; 797 else 798 cur_scp->mouse_buttons &= ~mouse->u.event.id; 799 800 if (sysmouse_event(mouse) == 0) 801 return 0; 802 803 /* if a button is held down, stop the screen saver */ 804 if (mouse->u.event.value > 0) 805 sc_touch_scrn_saver(); 806 807 cur_scp->status &= ~MOUSE_HIDDEN; 808 809 if (cur_scp->mouse_signal) { 810 if (cur_scp->mouse_proc && 811 (cur_scp->mouse_proc != pfind(cur_scp->mouse_pid))){ 812 cur_scp->mouse_signal = 0; 813 cur_scp->mouse_proc = NULL; 814 cur_scp->mouse_pid = 0; 815 } else { 816 psignal(cur_scp->mouse_proc, cur_scp->mouse_signal); 817 break; 818 } 819 } 820 821 if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL)) 822 break; 823 824 #ifndef SC_NO_CUTPASTE 825 switch (mouse->u.event.id) { 826 case MOUSE_BUTTON1DOWN: 827 switch (mouse->u.event.value % 4) { 828 case 0: /* up */ 829 mouse_cut_end(cur_scp); 830 break; 831 case 1: /* single click: start cut operation */ 832 mouse_cut_start(cur_scp); 833 break; 834 case 2: /* double click: cut a word */ 835 mouse_cut_word(cur_scp); 836 mouse_cut_end(cur_scp); 837 break; 838 case 3: /* triple click: cut a line */ 839 mouse_cut_line(cur_scp); 840 mouse_cut_end(cur_scp); 841 break; 842 } 843 break; 844 case SC_MOUSE_PASTEBUTTON: 845 switch (mouse->u.event.value) { 846 case 0: /* up */ 847 break; 848 default: 849 mouse_paste(cur_scp); 850 break; 851 } 852 break; 853 case SC_MOUSE_EXTENDBUTTON: 854 switch (mouse->u.event.value) { 855 case 0: /* up */ 856 if (!(cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN)) 857 mouse_cut_end(cur_scp); 858 break; 859 default: 860 mouse_cut_extend(cur_scp); 861 break; 862 } 863 break; 864 } 865 #endif /* SC_NO_CUTPASTE */ 866 break; 867 868 case MOUSE_MOUSECHAR: 869 if (mouse->u.mouse_char < 0) { 870 mouse->u.mouse_char = scp->sc->mouse_char; 871 } else { 872 if (mouse->u.mouse_char >= UCHAR_MAX - 4) 873 return EINVAL; 874 s = spltty(); 875 sc_remove_all_mouse(scp->sc); 876 #ifndef SC_NO_FONT_LOADING 877 if (ISTEXTSC(cur_scp) && (cur_scp->font != NULL)) 878 sc_load_font(cur_scp, 0, cur_scp->font_size, cur_scp->font, 879 cur_scp->sc->mouse_char, 4); 880 #endif 881 scp->sc->mouse_char = mouse->u.mouse_char; 882 splx(s); 883 } 884 break; 885 886 default: 887 return EINVAL; 888 } 889 890 return 0; 891 } 892 893 return ENOIOCTL; 894 } 895 896 #endif /* SC_NO_SYSMOUSE */ 897