The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/syscons/scmouse.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 197eff5b9486f0a9e6c8481e57d54538


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.