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