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