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