"Fossies" - the Fresh Open Source Software Archive

Member "PDCurses-3.9/pdcurses/mouse.c" (4 Sep 2019, 12376 Bytes) of package /linux/misc/PDCurses-3.9.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "mouse.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.8_vs_3.9.

    1 /* PDCurses */
    2 
    3 #include <curspriv.h>
    4 
    5 /*man-start**************************************************************
    6 
    7 mouse
    8 -----
    9 
   10 ### Synopsis
   11 
   12     int mouse_set(mmask_t mbe);
   13     int mouse_on(mmask_t mbe);
   14     int mouse_off(mmask_t mbe);
   15     int request_mouse_pos(void);
   16     void wmouse_position(WINDOW *win, int *y, int *x);
   17     mmask_t getmouse(void);
   18 
   19     int mouseinterval(int wait);
   20     bool wenclose(const WINDOW *win, int y, int x);
   21     bool wmouse_trafo(const WINDOW *win, int *y, int *x, bool to_screen);
   22     bool mouse_trafo(int *y, int *x, bool to_screen);
   23     mmask_t mousemask(mmask_t mask, mmask_t *oldmask);
   24     int nc_getmouse(MEVENT *event);
   25     int ungetmouse(MEVENT *event);
   26     bool has_mouse(void);
   27 
   28 ### Description
   29 
   30    As of PDCurses 3.0, there are two separate mouse interfaces: the
   31    classic interface, which is based on the undocumented Sys V mouse
   32    functions; and an ncurses-compatible interface. Both are active at
   33    all times, and you can mix and match functions from each, though it's
   34    not recommended. The ncurses interface is essentially an emulation
   35    layer built on top of the classic interface; it's here to allow
   36    easier porting of ncurses apps.
   37 
   38    The classic interface: mouse_set(), mouse_on(), mouse_off(),
   39    request_mouse_pos(), wmouse_position(), and getmouse(). An
   40    application using this interface would start by calling mouse_set()
   41    or mouse_on() with a non-zero value, often ALL_MOUSE_EVENTS. Then it
   42    would check for a KEY_MOUSE return from getch(). If found, it would
   43    call request_mouse_pos() to get the current mouse status.
   44 
   45    mouse_set(), mouse_on() and mouse_off() are analagous to attrset(),
   46    attron() and attroff(). These functions set the mouse button events
   47    to trap. The button masks used in these functions are defined in
   48    curses.h and can be or'ed together. They are the group of masks
   49    starting with BUTTON1_RELEASED.
   50 
   51    request_mouse_pos() requests curses to fill in the Mouse_status
   52    structure with the current state of the mouse.
   53 
   54    wmouse_position() determines if the current mouse position is within
   55    the window passed as an argument. If the mouse is outside the current
   56    window, -1 is returned in the y and x arguments; otherwise the y and
   57    x coordinates of the mouse (relative to the top left corner of the
   58    window) are returned in y and x.
   59 
   60    getmouse() returns the current status of the trapped mouse buttons as
   61    set by mouse_set() or mouse_on().
   62 
   63    The ncurses interface: mouseinterval(), wenclose(), wmouse_trafo(),
   64    mouse_trafo(), mousemask(), nc_getmouse(), ungetmouse() and
   65    has_mouse(). A typical application using this interface would start
   66    by calling mousemask() with a non-zero value, often ALL_MOUSE_EVENTS.
   67    Then it would check for a KEY_MOUSE return from getch(). If found, it
   68    would call nc_getmouse() to get the current mouse status.
   69 
   70    mouseinterval() sets the timeout for a mouse click. On all current
   71    platforms, PDCurses receives mouse button press and release events,
   72    but must synthesize click events. It does this by checking whether a
   73    release event is queued up after a press event. If it gets a press
   74    event, and there are no more events waiting, it will wait for the
   75    timeout interval, then check again for a release. A press followed by
   76    a release is reported as BUTTON_CLICKED; otherwise it's passed
   77    through as BUTTON_PRESSED. The default timeout is 150ms; valid values
   78    are 0 (no clicks reported) through 1000ms. In x11, the timeout can
   79    also be set via the clickPeriod resource. The return value from
   80    mouseinterval() is the old timeout. To check the old value without
   81    setting a new one, call it with a parameter of -1. Note that although
   82    there's no classic equivalent for this function (apart from the
   83    clickPeriod resource), the value set applies in both interfaces.
   84 
   85    wenclose() reports whether the given screen-relative y, x coordinates
   86    fall within the given window.
   87 
   88    wmouse_trafo() converts between screen-relative and window-relative
   89    coordinates. A to_screen parameter of TRUE means to convert from
   90    window to screen; otherwise the reverse. The function returns FALSE
   91    if the coordinates aren't within the window, or if any of the
   92    parameters are NULL. The coordinates have been converted when the
   93    function returns TRUE.
   94 
   95    mouse_trafo() is the stdscr version of wmouse_trafo().
   96 
   97    mousemask() is nearly equivalent to mouse_set(), but instead of
   98    OK/ERR, it returns the value of the mask after setting it. (This
   99    isn't necessarily the same value passed in, since the mask could be
  100    altered on some platforms.) And if the second parameter is a non-null
  101    pointer, mousemask() stores the previous mask value there. Also,
  102    since the ncurses interface doesn't work with PDCurses' BUTTON_MOVED
  103    events, mousemask() filters them out.
  104 
  105    nc_getmouse() returns the current mouse status in an MEVENT struct.
  106    This is equivalent to ncurses' getmouse(), renamed to avoid conflict
  107    with PDCurses' getmouse(). But if you define PDC_NCMOUSE before
  108    including curses.h, it defines getmouse() to nc_getmouse(), along
  109    with a few other redefintions needed for compatibility with ncurses
  110    code. nc_getmouse() calls request_mouse_pos(), which (not getmouse())
  111    is the classic equivalent.
  112 
  113    ungetmouse() is the mouse equivalent of ungetch(). However, PDCurses
  114    doesn't maintain a queue of mouse events; only one can be pushed
  115    back, and it can overwrite or be overwritten by real mouse events.
  116 
  117    has_mouse() reports whether the mouse is available at all on the
  118    current platform.
  119 
  120 ### Portability
  121                              X/Open  ncurses  NetBSD
  122     mouse_set                   -       -       -
  123     mouse_on                    -       -       -
  124     mouse_off                   -       -       -
  125     request_mouse_pos           -       -       -
  126     wmouse_position             -       -       -
  127     getmouse                    -       *       -
  128     mouseinterval               -       Y       -
  129     wenclose                    -       Y       -
  130     wmouse_trafo                -       Y       -
  131     mouse_trafo                 -       Y       -
  132     mousemask                   -       Y       -
  133     nc_getmouse                 -       *       -
  134     ungetmouse                  -       Y       -
  135     has_mouse                   -       Y       -
  136 
  137     * See above, under Description
  138 
  139 **man-end****************************************************************/
  140 
  141 #include <string.h>
  142 
  143 static bool ungot = FALSE;
  144 
  145 int mouse_set(mmask_t mbe)
  146 {
  147     PDC_LOG(("mouse_set() - called: event %x\n", mbe));
  148 
  149     if (!SP)
  150         return ERR;
  151 
  152     SP->_trap_mbe = mbe;
  153     return PDC_mouse_set();
  154 }
  155 
  156 int mouse_on(mmask_t mbe)
  157 {
  158     PDC_LOG(("mouse_on() - called: event %x\n", mbe));
  159 
  160     if (!SP)
  161         return ERR;
  162 
  163     SP->_trap_mbe |= mbe;
  164     return PDC_mouse_set();
  165 }
  166 
  167 int mouse_off(mmask_t mbe)
  168 {
  169     PDC_LOG(("mouse_off() - called: event %x\n", mbe));
  170 
  171     if (!SP)
  172         return ERR;
  173 
  174     SP->_trap_mbe &= ~mbe;
  175     return PDC_mouse_set();
  176 }
  177 
  178 int request_mouse_pos(void)
  179 {
  180     PDC_LOG(("request_mouse_pos() - called\n"));
  181 
  182     Mouse_status = SP->mouse_status;
  183 
  184     return OK;
  185 }
  186 
  187 void wmouse_position(WINDOW *win, int *y, int *x)
  188 {
  189     PDC_LOG(("wmouse_position() - called\n"));
  190 
  191     if (win && wenclose(win, MOUSE_Y_POS, MOUSE_X_POS))
  192     {
  193         if (y)
  194             *y = MOUSE_Y_POS - win->_begy;
  195         if (x)
  196             *x = MOUSE_X_POS - win->_begx;
  197     }
  198     else
  199     {
  200         if (y)
  201             *y = -1;
  202         if (x)
  203             *x = -1;
  204     }
  205 }
  206 
  207 mmask_t getmouse(void)
  208 {
  209     PDC_LOG(("getmouse() - called\n"));
  210 
  211     return SP ? SP->_trap_mbe : (mmask_t)0;
  212 }
  213 
  214 /* ncurses mouse interface */
  215 
  216 int mouseinterval(int wait)
  217 {
  218     int old_wait;
  219 
  220     PDC_LOG(("mouseinterval() - called: %d\n", wait));
  221 
  222     if (!SP)
  223         return ERR;
  224 
  225     old_wait = SP->mouse_wait;
  226 
  227     if (wait >= 0 && wait <= 1000)
  228         SP->mouse_wait = wait;
  229 
  230     return old_wait;
  231 }
  232 
  233 bool wenclose(const WINDOW *win, int y, int x)
  234 {
  235     PDC_LOG(("wenclose() - called: %p %d %d\n", win, y, x));
  236 
  237     return (win && y >= win->_begy && y < win->_begy + win->_maxy
  238                 && x >= win->_begx && x < win->_begx + win->_maxx);
  239 }
  240 
  241 bool wmouse_trafo(const WINDOW *win, int *y, int *x, bool to_screen)
  242 {
  243     int newy, newx;
  244 
  245     PDC_LOG(("wmouse_trafo() - called\n"));
  246 
  247     if (!win || !y || !x)
  248         return FALSE;
  249 
  250     newy = *y;
  251     newx = *x;
  252 
  253     if (to_screen)
  254     {
  255         newy += win->_begy;
  256         newx += win->_begx;
  257 
  258         if (!wenclose(win, newy, newx))
  259             return FALSE;
  260     }
  261     else
  262     {
  263         if (wenclose(win, newy, newx))
  264         {
  265             newy -= win->_begy;
  266             newx -= win->_begx;
  267         }
  268         else
  269             return FALSE;
  270     }
  271 
  272     *y = newy;
  273     *x = newx;
  274 
  275     return TRUE;
  276 }
  277 
  278 bool mouse_trafo(int *y, int *x, bool to_screen)
  279 {
  280     PDC_LOG(("mouse_trafo() - called\n"));
  281 
  282     return wmouse_trafo(stdscr, y, x, to_screen);
  283 }
  284 
  285 mmask_t mousemask(mmask_t mask, mmask_t *oldmask)
  286 {
  287     PDC_LOG(("mousemask() - called\n"));
  288 
  289     if (!SP)
  290         return (mmask_t)0;
  291 
  292     if (oldmask)
  293         *oldmask = SP->_trap_mbe;
  294 
  295     /* The ncurses interface doesn't work with our move events, so
  296        filter them here */
  297 
  298     mask &= ~(BUTTON1_MOVED | BUTTON2_MOVED | BUTTON3_MOVED);
  299 
  300     mouse_set(mask);
  301 
  302     return SP->_trap_mbe;
  303 }
  304 
  305 int nc_getmouse(MEVENT *event)
  306 {
  307     int i;
  308     mmask_t bstate = 0;
  309 
  310     PDC_LOG(("nc_getmouse() - called\n"));
  311 
  312     if (!event || !SP)
  313         return ERR;
  314 
  315     ungot = FALSE;
  316 
  317     request_mouse_pos();
  318 
  319     event->id = 0;
  320 
  321     event->x = Mouse_status.x;
  322     event->y = Mouse_status.y;
  323     event->z = 0;
  324 
  325     for (i = 0; i < 3; i++)
  326     {
  327         if (Mouse_status.changes & (1 << i))
  328         {
  329             int shf = i * 5;
  330             short button = Mouse_status.button[i] & BUTTON_ACTION_MASK;
  331 
  332             if (button == BUTTON_RELEASED)
  333                 bstate |= (BUTTON1_RELEASED << shf);
  334             else if (button == BUTTON_PRESSED)
  335                 bstate |= (BUTTON1_PRESSED << shf);
  336             else if (button == BUTTON_CLICKED)
  337                 bstate |= (BUTTON1_CLICKED << shf);
  338             else if (button == BUTTON_DOUBLE_CLICKED)
  339                 bstate |= (BUTTON1_DOUBLE_CLICKED << shf);
  340 
  341             button = Mouse_status.button[i] & BUTTON_MODIFIER_MASK;
  342 
  343             if (button & PDC_BUTTON_SHIFT)
  344                 bstate |= BUTTON_MODIFIER_SHIFT;
  345             if (button & PDC_BUTTON_CONTROL)
  346                 bstate |= BUTTON_MODIFIER_CONTROL;
  347             if (button & PDC_BUTTON_ALT)
  348                 bstate |= BUTTON_MODIFIER_ALT;
  349         }
  350     }
  351 
  352     if (MOUSE_WHEEL_UP)
  353         bstate |= BUTTON4_PRESSED;
  354     else if (MOUSE_WHEEL_DOWN)
  355         bstate |= BUTTON5_PRESSED;
  356 
  357     /* extra filter pass -- mainly for button modifiers */
  358 
  359     event->bstate = bstate & SP->_trap_mbe;
  360 
  361     return OK;
  362 }
  363 
  364 int ungetmouse(MEVENT *event)
  365 {
  366     int i;
  367     mmask_t bstate;
  368 
  369     PDC_LOG(("ungetmouse() - called\n"));
  370 
  371     if (!event || ungot)
  372         return ERR;
  373 
  374     ungot = TRUE;
  375 
  376     SP->mouse_status.x = event->x;
  377     SP->mouse_status.y = event->y;
  378 
  379     SP->mouse_status.changes = 0;
  380     bstate = event->bstate;
  381 
  382     for (i = 0; i < 3; i++)
  383     {
  384         int shf = i * 5;
  385         short button = 0;
  386 
  387         if (bstate & ((BUTTON1_RELEASED | BUTTON1_PRESSED |
  388             BUTTON1_CLICKED | BUTTON1_DOUBLE_CLICKED) << shf))
  389         {
  390             SP->mouse_status.changes |= 1 << i;
  391 
  392             if (bstate & (BUTTON1_PRESSED << shf))
  393                 button = BUTTON_PRESSED;
  394             if (bstate & (BUTTON1_CLICKED << shf))
  395                 button = BUTTON_CLICKED;
  396             if (bstate & (BUTTON1_DOUBLE_CLICKED << shf))
  397                 button = BUTTON_DOUBLE_CLICKED;
  398 
  399             if (bstate & BUTTON_MODIFIER_SHIFT)
  400                 button |= PDC_BUTTON_SHIFT;
  401             if (bstate & BUTTON_MODIFIER_CONTROL)
  402                 button |= PDC_BUTTON_CONTROL;
  403             if (bstate & BUTTON_MODIFIER_ALT)
  404                 button |= PDC_BUTTON_ALT;
  405         }
  406 
  407         SP->mouse_status.button[i] = button;
  408     }
  409 
  410     if (bstate & BUTTON4_PRESSED)
  411         SP->mouse_status.changes |= PDC_MOUSE_WHEEL_UP;
  412     else if (bstate & BUTTON5_PRESSED)
  413         SP->mouse_status.changes |= PDC_MOUSE_WHEEL_DOWN;
  414 
  415     return ungetch(KEY_MOUSE);
  416 }
  417 
  418 bool has_mouse(void)
  419 {
  420     return PDC_has_mouse();
  421 }