Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
9214 turbocat 1
/* PDCurses */
2
 
3
#include 
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 
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 PDC_ungetch(KEY_MOUSE);
416
}
417
 
418
bool has_mouse(void)
419
{
420
    return PDC_has_mouse();
421
}