1*c7ef0cfcSnicm /* $OpenBSD: m_driver.c,v 1.9 2023/10/17 09:52:10 nicm Exp $ */
29f1aa62bSmillert
3457960bfSmillert /****************************************************************************
4*c7ef0cfcSnicm * Copyright 2020,2021 Thomas E. Dickey *
5*c7ef0cfcSnicm * Copyright 1998-2012,2016 Free Software Foundation, Inc. *
6457960bfSmillert * *
7457960bfSmillert * Permission is hereby granted, free of charge, to any person obtaining a *
8457960bfSmillert * copy of this software and associated documentation files (the *
9457960bfSmillert * "Software"), to deal in the Software without restriction, including *
10457960bfSmillert * without limitation the rights to use, copy, modify, merge, publish, *
11457960bfSmillert * distribute, distribute with modifications, sublicense, and/or sell *
12457960bfSmillert * copies of the Software, and to permit persons to whom the Software is *
13457960bfSmillert * furnished to do so, subject to the following conditions: *
14457960bfSmillert * *
15457960bfSmillert * The above copyright notice and this permission notice shall be included *
16457960bfSmillert * in all copies or substantial portions of the Software. *
17457960bfSmillert * *
18457960bfSmillert * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
19457960bfSmillert * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
20457960bfSmillert * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
21457960bfSmillert * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
22457960bfSmillert * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
23457960bfSmillert * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
24457960bfSmillert * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
25457960bfSmillert * *
26457960bfSmillert * Except as contained in this notice, the name(s) of the above copyright *
27457960bfSmillert * holders shall not be used in advertising or otherwise to promote the *
28457960bfSmillert * sale, use or other dealings in this Software without prior written *
29457960bfSmillert * authorization. *
30457960bfSmillert ****************************************************************************/
31457960bfSmillert
32457960bfSmillert /****************************************************************************
3381d8c4e1Snicm * Author: Juergen Pfeifer, 1995,1997 *
34457960bfSmillert ****************************************************************************/
35c166cd22Stholo
36c166cd22Stholo /***************************************************************************
379f1aa62bSmillert * Module m_driver *
389f1aa62bSmillert * Central dispatching routine *
39c166cd22Stholo ***************************************************************************/
40c166cd22Stholo
41c166cd22Stholo #include "menu.priv.h"
42c166cd22Stholo
43*c7ef0cfcSnicm MODULE_ID("$Id: m_driver.c,v 1.9 2023/10/17 09:52:10 nicm Exp $")
440107aba4Smillert
45c166cd22Stholo /* Macros */
46c166cd22Stholo
47c166cd22Stholo /* Remove the last character from the match pattern buffer */
48c166cd22Stholo #define Remove_Character_From_Pattern(menu) \
49c166cd22Stholo (menu)->pattern[--((menu)->pindex)] = '\0'
50c166cd22Stholo
51c166cd22Stholo /* Add a new character to the match pattern buffer */
52c166cd22Stholo #define Add_Character_To_Pattern(menu,ch) \
53*c7ef0cfcSnicm { (menu)->pattern[((menu)->pindex)++] = (char) (ch);\
54c166cd22Stholo (menu)->pattern[(menu)->pindex] = '\0'; }
55c166cd22Stholo
56c166cd22Stholo /*---------------------------------------------------------------------------
57c166cd22Stholo | Facility : libnmenu
58c166cd22Stholo | Function : static bool Is_Sub_String(
59c166cd22Stholo | bool IgnoreCaseFlag,
60c166cd22Stholo | const char *part,
61c166cd22Stholo | const char *string)
62c166cd22Stholo |
63c166cd22Stholo | Description : Checks whether or not part is a substring of string.
64c166cd22Stholo |
65c166cd22Stholo | Return Values : TRUE - if it is a substring
66c166cd22Stholo | FALSE - if it is not a substring
67c166cd22Stholo +--------------------------------------------------------------------------*/
6881d8c4e1Snicm static bool
Is_Sub_String(bool IgnoreCaseFlag,const char * part,const char * string)6981d8c4e1Snicm Is_Sub_String(
70c166cd22Stholo bool IgnoreCaseFlag,
71c166cd22Stholo const char *part,
72c166cd22Stholo const char *string
73c166cd22Stholo )
74c166cd22Stholo {
75c166cd22Stholo assert(part && string);
76c166cd22Stholo if (IgnoreCaseFlag)
77c166cd22Stholo {
78c166cd22Stholo while (*string && *part)
79c166cd22Stholo {
8081d8c4e1Snicm if (toupper(UChar(*string++)) != toupper(UChar(*part)))
8181d8c4e1Snicm break;
82c166cd22Stholo part++;
83c166cd22Stholo }
84c166cd22Stholo }
85c166cd22Stholo else
86c166cd22Stholo {
87c166cd22Stholo while (*string && *part)
8881d8c4e1Snicm if (*part != *string++)
8981d8c4e1Snicm break;
90c166cd22Stholo part++;
91c166cd22Stholo }
92c166cd22Stholo return ((*part) ? FALSE : TRUE);
93c166cd22Stholo }
94c166cd22Stholo
95c166cd22Stholo /*---------------------------------------------------------------------------
96c166cd22Stholo | Facility : libnmenu
979f1aa62bSmillert | Function : int _nc_Match_Next_Character_In_Item_Name(
98c166cd22Stholo | MENU *menu,
99c166cd22Stholo | int ch,
100c166cd22Stholo | ITEM **item)
101c166cd22Stholo |
102c166cd22Stholo | Description : This internal routine is called for a menu positioned
103c166cd22Stholo | at an item with three different classes of characters:
104c166cd22Stholo | - a printable character; the character is added to
105c166cd22Stholo | the current pattern and the next item matching
106c166cd22Stholo | this pattern is searched.
107c166cd22Stholo | - NUL; the pattern stays as it is and the next item
108c166cd22Stholo | matching the pattern is searched
109c166cd22Stholo | - BS; the pattern stays as it is and the previous
110c166cd22Stholo | item matching the pattern is searched
111c166cd22Stholo |
112c166cd22Stholo | The item parameter contains on call a pointer to
113c166cd22Stholo | the item where the search starts. On return - if
114c166cd22Stholo | a match was found - it contains a pointer to the
115c166cd22Stholo | matching item.
116c166cd22Stholo |
117c166cd22Stholo | Return Values : E_OK - an item matching the pattern was found
118c166cd22Stholo | E_NO_MATCH - nothing found
119c166cd22Stholo +--------------------------------------------------------------------------*/
120*c7ef0cfcSnicm MENU_EXPORT(int)
_nc_Match_Next_Character_In_Item_Name(MENU * menu,int ch,ITEM ** item)12184af20ceSmillert _nc_Match_Next_Character_In_Item_Name
12284af20ceSmillert (MENU *menu, int ch, ITEM **item)
123c166cd22Stholo {
124c166cd22Stholo bool found = FALSE, passed = FALSE;
125c166cd22Stholo int idx, last;
126c166cd22Stholo
127*c7ef0cfcSnicm T((T_CALLED("_nc_Match_Next_Character(%p,%d,%p)"),
128*c7ef0cfcSnicm (void *)menu, ch, (void *)item));
12981d8c4e1Snicm
130c166cd22Stholo assert(menu && item && *item);
131c166cd22Stholo idx = (*item)->index;
132c166cd22Stholo
133c166cd22Stholo if (ch && ch != BS)
134c166cd22Stholo {
135c166cd22Stholo /* if we become to long, we need no further checking : there can't be
136c166cd22Stholo a match ! */
137c166cd22Stholo if ((menu->pindex + 1) > menu->namelen)
138c166cd22Stholo RETURN(E_NO_MATCH);
139c166cd22Stholo
140c166cd22Stholo Add_Character_To_Pattern(menu, ch);
141c166cd22Stholo /* we artificially position one item back, because in the do...while
142c166cd22Stholo loop we start with the next item. This means, that with a new
143c166cd22Stholo pattern search we always start the scan with the actual item. If
144*c7ef0cfcSnicm we do a NEXT_PATTERN or PREV_PATTERN search, we start with the
145c166cd22Stholo one after or before the actual item. */
146c166cd22Stholo if (--idx < 0)
147c166cd22Stholo idx = menu->nitems - 1;
148c166cd22Stholo }
149c166cd22Stholo
150c166cd22Stholo last = idx; /* this closes the cycle */
151c166cd22Stholo
15281d8c4e1Snicm do
15381d8c4e1Snicm {
154c166cd22Stholo if (ch == BS)
155c166cd22Stholo { /* we have to go backward */
156c166cd22Stholo if (--idx < 0)
157c166cd22Stholo idx = menu->nitems - 1;
158c166cd22Stholo }
159c166cd22Stholo else
160c166cd22Stholo { /* otherwise we always go forward */
161c166cd22Stholo if (++idx >= menu->nitems)
162c166cd22Stholo idx = 0;
163c166cd22Stholo }
16481d8c4e1Snicm if (Is_Sub_String((bool)((menu->opt & O_IGNORECASE) != 0),
165c166cd22Stholo menu->pattern,
166c166cd22Stholo menu->items[idx]->name.str)
167c166cd22Stholo )
168c166cd22Stholo found = TRUE;
169c166cd22Stholo else
170c166cd22Stholo passed = TRUE;
17181d8c4e1Snicm }
17281d8c4e1Snicm while (!found && (idx != last));
173c166cd22Stholo
174c166cd22Stholo if (found)
175c166cd22Stholo {
176c166cd22Stholo if (!((idx == (*item)->index) && passed))
177c166cd22Stholo {
178c166cd22Stholo *item = menu->items[idx];
179c166cd22Stholo RETURN(E_OK);
180c166cd22Stholo }
181c166cd22Stholo /* This point is reached, if we fully cycled through the item list
182c166cd22Stholo and the only match we found is the starting item. With a NEXT_PATTERN
183c166cd22Stholo or PREV_PATTERN scan this means, that there was no additional match.
184c166cd22Stholo If we searched with an expanded new pattern, we should never reach
185c166cd22Stholo this point, because if the expanded pattern matches also the actual
186c166cd22Stholo item we will find it in the first attempt (passed==FALSE) and we
187c166cd22Stholo will never cycle through the whole item array.
188c166cd22Stholo */
189c166cd22Stholo assert(ch == 0 || ch == BS);
190c166cd22Stholo }
191c166cd22Stholo else
192c166cd22Stholo {
193c166cd22Stholo if (ch && ch != BS && menu->pindex > 0)
194c166cd22Stholo {
195c166cd22Stholo /* if we had no match with a new pattern, we have to restore it */
196c166cd22Stholo Remove_Character_From_Pattern(menu);
197c166cd22Stholo }
198c166cd22Stholo }
199c166cd22Stholo RETURN(E_NO_MATCH);
200c166cd22Stholo }
201c166cd22Stholo
202c166cd22Stholo /*---------------------------------------------------------------------------
203c166cd22Stholo | Facility : libnmenu
204c166cd22Stholo | Function : int menu_driver(MENU* menu, int c)
205c166cd22Stholo |
206c166cd22Stholo | Description : Central dispatcher for the menu. Translates the logical
207c166cd22Stholo | request 'c' into a menu action.
208c166cd22Stholo |
209c166cd22Stholo | Return Values : E_OK - success
210c166cd22Stholo | E_BAD_ARGUMENT - invalid menu pointer
211c166cd22Stholo | E_BAD_STATE - menu is in user hook routine
212c166cd22Stholo | E_NOT_POSTED - menu is not posted
213c166cd22Stholo +--------------------------------------------------------------------------*/
214*c7ef0cfcSnicm MENU_EXPORT(int)
menu_driver(MENU * menu,int c)21584af20ceSmillert menu_driver(MENU *menu, int c)
216c166cd22Stholo {
217c166cd22Stholo #define NAVIGATE(dir) \
218c166cd22Stholo if (!item->dir)\
219c166cd22Stholo result = E_REQUEST_DENIED;\
220c166cd22Stholo else\
221c166cd22Stholo item = item->dir
222c166cd22Stholo
223c166cd22Stholo int result = E_OK;
224c166cd22Stholo ITEM *item;
225*c7ef0cfcSnicm int my_top_row;
226c166cd22Stholo
227*c7ef0cfcSnicm T((T_CALLED("menu_driver(%p,%d)"), (void *)menu, c));
22881d8c4e1Snicm
229c166cd22Stholo if (!menu)
230c166cd22Stholo RETURN(E_BAD_ARGUMENT);
231c166cd22Stholo
232c166cd22Stholo if (menu->status & _IN_DRIVER)
233c166cd22Stholo RETURN(E_BAD_STATE);
234c166cd22Stholo if (!(menu->status & _POSTED))
235c166cd22Stholo RETURN(E_NOT_POSTED);
236c166cd22Stholo
237c166cd22Stholo item = menu->curitem;
2385be68eb8Smillert
2395be68eb8Smillert my_top_row = menu->toprow;
240c166cd22Stholo assert(item);
241c166cd22Stholo
242c166cd22Stholo if ((c > KEY_MAX) && (c <= MAX_MENU_COMMAND))
243c166cd22Stholo {
244*c7ef0cfcSnicm int rdiff;
245*c7ef0cfcSnicm
246c166cd22Stholo if (!((c == REQ_BACK_PATTERN)
247c166cd22Stholo || (c == REQ_NEXT_MATCH) || (c == REQ_PREV_MATCH)))
248c166cd22Stholo {
249c166cd22Stholo assert(menu->pattern);
250c166cd22Stholo Reset_Pattern(menu);
251c166cd22Stholo }
252c166cd22Stholo
253c166cd22Stholo switch (c)
254c166cd22Stholo {
255c166cd22Stholo case REQ_LEFT_ITEM:
256c166cd22Stholo /*=================*/
257c166cd22Stholo NAVIGATE(left);
258c166cd22Stholo break;
259c166cd22Stholo
260c166cd22Stholo case REQ_RIGHT_ITEM:
261c166cd22Stholo /*==================*/
262c166cd22Stholo NAVIGATE(right);
263c166cd22Stholo break;
264c166cd22Stholo
265c166cd22Stholo case REQ_UP_ITEM:
266c166cd22Stholo /*===============*/
267c166cd22Stholo NAVIGATE(up);
268c166cd22Stholo break;
269c166cd22Stholo
270c166cd22Stholo case REQ_DOWN_ITEM:
271c166cd22Stholo /*=================*/
272c166cd22Stholo NAVIGATE(down);
273c166cd22Stholo break;
274c166cd22Stholo
275c166cd22Stholo case REQ_SCR_ULINE:
276c166cd22Stholo /*=================*/
2775be68eb8Smillert if (my_top_row == 0 || !(item->up))
278c166cd22Stholo result = E_REQUEST_DENIED;
279c166cd22Stholo else
280c166cd22Stholo {
281c166cd22Stholo --my_top_row;
282c166cd22Stholo item = item->up;
283c166cd22Stholo }
284c166cd22Stholo break;
285c166cd22Stholo
286c166cd22Stholo case REQ_SCR_DLINE:
287c166cd22Stholo /*=================*/
2885be68eb8Smillert if ((my_top_row + menu->arows >= menu->rows) || !(item->down))
289c166cd22Stholo {
290c166cd22Stholo /* only if the menu has less items than rows, we can deny the
291c166cd22Stholo request. Otherwise the epilogue of this routine adjusts the
292c166cd22Stholo top row if necessary */
293c166cd22Stholo result = E_REQUEST_DENIED;
294c166cd22Stholo }
29581d8c4e1Snicm else
29681d8c4e1Snicm {
2975be68eb8Smillert my_top_row++;
298c166cd22Stholo item = item->down;
2995be68eb8Smillert }
300c166cd22Stholo break;
301c166cd22Stholo
302c166cd22Stholo case REQ_SCR_DPAGE:
303c166cd22Stholo /*=================*/
3045be68eb8Smillert rdiff = menu->rows - (menu->arows + my_top_row);
3050107aba4Smillert if (rdiff > menu->arows)
3060107aba4Smillert rdiff = menu->arows;
3075be68eb8Smillert if (rdiff <= 0)
308c166cd22Stholo result = E_REQUEST_DENIED;
309c166cd22Stholo else
310c166cd22Stholo {
311c166cd22Stholo my_top_row += rdiff;
31281d8c4e1Snicm while (rdiff-- > 0 && item != 0 && item->down != 0)
313c166cd22Stholo item = item->down;
314c166cd22Stholo }
315c166cd22Stholo break;
316c166cd22Stholo
317c166cd22Stholo case REQ_SCR_UPAGE:
318c166cd22Stholo /*=================*/
3195be68eb8Smillert rdiff = (menu->arows < my_top_row) ? menu->arows : my_top_row;
3205be68eb8Smillert if (rdiff <= 0)
321c166cd22Stholo result = E_REQUEST_DENIED;
322c166cd22Stholo else
323c166cd22Stholo {
324c166cd22Stholo my_top_row -= rdiff;
32581d8c4e1Snicm while (rdiff-- > 0 && item != 0 && item->up != 0)
326c166cd22Stholo item = item->up;
327c166cd22Stholo }
328c166cd22Stholo break;
329c166cd22Stholo
330c166cd22Stholo case REQ_FIRST_ITEM:
331c166cd22Stholo /*==================*/
332c166cd22Stholo item = menu->items[0];
333c166cd22Stholo break;
334c166cd22Stholo
335c166cd22Stholo case REQ_LAST_ITEM:
336c166cd22Stholo /*=================*/
337c166cd22Stholo item = menu->items[menu->nitems - 1];
338c166cd22Stholo break;
339c166cd22Stholo
340c166cd22Stholo case REQ_NEXT_ITEM:
341c166cd22Stholo /*=================*/
342c166cd22Stholo if ((item->index + 1) >= menu->nitems)
343c166cd22Stholo {
344c166cd22Stholo if (menu->opt & O_NONCYCLIC)
345c166cd22Stholo result = E_REQUEST_DENIED;
346c166cd22Stholo else
347c166cd22Stholo item = menu->items[0];
348c166cd22Stholo }
349c166cd22Stholo else
350c166cd22Stholo item = menu->items[item->index + 1];
351c166cd22Stholo break;
352c166cd22Stholo
353c166cd22Stholo case REQ_PREV_ITEM:
354c166cd22Stholo /*=================*/
355c166cd22Stholo if (item->index <= 0)
356c166cd22Stholo {
357c166cd22Stholo if (menu->opt & O_NONCYCLIC)
358c166cd22Stholo result = E_REQUEST_DENIED;
359c166cd22Stholo else
360c166cd22Stholo item = menu->items[menu->nitems - 1];
361c166cd22Stholo }
362c166cd22Stholo else
363c166cd22Stholo item = menu->items[item->index - 1];
364c166cd22Stholo break;
365c166cd22Stholo
366c166cd22Stholo case REQ_TOGGLE_ITEM:
367c166cd22Stholo /*===================*/
368c166cd22Stholo if (menu->opt & O_ONEVALUE)
369c166cd22Stholo {
370c166cd22Stholo result = E_REQUEST_DENIED;
371c166cd22Stholo }
372c166cd22Stholo else
373c166cd22Stholo {
374c166cd22Stholo if (menu->curitem->opt & O_SELECTABLE)
375c166cd22Stholo {
3760107aba4Smillert menu->curitem->value = !menu->curitem->value;
377c166cd22Stholo Move_And_Post_Item(menu, menu->curitem);
378c166cd22Stholo _nc_Show_Menu(menu);
379c166cd22Stholo }
380c166cd22Stholo else
381c166cd22Stholo result = E_NOT_SELECTABLE;
382c166cd22Stholo }
383c166cd22Stholo break;
384c166cd22Stholo
385c166cd22Stholo case REQ_CLEAR_PATTERN:
386c166cd22Stholo /*=====================*/
387c166cd22Stholo /* already cleared in prologue */
388c166cd22Stholo break;
389c166cd22Stholo
390c166cd22Stholo case REQ_BACK_PATTERN:
391c166cd22Stholo /*====================*/
392c166cd22Stholo if (menu->pindex > 0)
393c166cd22Stholo {
394c166cd22Stholo assert(menu->pattern);
395c166cd22Stholo Remove_Character_From_Pattern(menu);
396c166cd22Stholo pos_menu_cursor(menu);
397c166cd22Stholo }
398c166cd22Stholo else
399c166cd22Stholo result = E_REQUEST_DENIED;
400c166cd22Stholo break;
401c166cd22Stholo
402c166cd22Stholo case REQ_NEXT_MATCH:
403c166cd22Stholo /*==================*/
404c166cd22Stholo assert(menu->pattern);
405c166cd22Stholo if (menu->pattern[0])
4069f1aa62bSmillert result = _nc_Match_Next_Character_In_Item_Name(menu, 0, &item);
407c166cd22Stholo else
408c166cd22Stholo {
409c166cd22Stholo if ((item->index + 1) < menu->nitems)
410c166cd22Stholo item = menu->items[item->index + 1];
411c166cd22Stholo else
412c166cd22Stholo {
413c166cd22Stholo if (menu->opt & O_NONCYCLIC)
414c166cd22Stholo result = E_REQUEST_DENIED;
415c166cd22Stholo else
416c166cd22Stholo item = menu->items[0];
417c166cd22Stholo }
418c166cd22Stholo }
419c166cd22Stholo break;
420c166cd22Stholo
421c166cd22Stholo case REQ_PREV_MATCH:
422c166cd22Stholo /*==================*/
423c166cd22Stholo assert(menu->pattern);
424c166cd22Stholo if (menu->pattern[0])
4259f1aa62bSmillert result = _nc_Match_Next_Character_In_Item_Name(menu, BS, &item);
426c166cd22Stholo else
427c166cd22Stholo {
428c166cd22Stholo if (item->index)
429c166cd22Stholo item = menu->items[item->index - 1];
430c166cd22Stholo else
431c166cd22Stholo {
432c166cd22Stholo if (menu->opt & O_NONCYCLIC)
433c166cd22Stholo result = E_REQUEST_DENIED;
434c166cd22Stholo else
435c166cd22Stholo item = menu->items[menu->nitems - 1];
436c166cd22Stholo }
437c166cd22Stholo }
438c166cd22Stholo break;
439c166cd22Stholo
440c166cd22Stholo default:
441c166cd22Stholo /*======*/
442c166cd22Stholo result = E_UNKNOWN_COMMAND;
443c166cd22Stholo break;
444c166cd22Stholo }
445c166cd22Stholo }
446c166cd22Stholo else
447c166cd22Stholo { /* not a command */
44881d8c4e1Snicm if (!(c & ~((int)MAX_REGULAR_CHARACTER)) && isprint(UChar(c)))
4499f1aa62bSmillert result = _nc_Match_Next_Character_In_Item_Name(menu, c, &item);
4505be68eb8Smillert #ifdef NCURSES_MOUSE_VERSION
4515be68eb8Smillert else if (KEY_MOUSE == c)
4525be68eb8Smillert {
4535be68eb8Smillert MEVENT event;
4545be68eb8Smillert WINDOW *uwin = Get_Menu_UserWin(menu);
4555be68eb8Smillert
4565be68eb8Smillert getmouse(&event);
4575be68eb8Smillert if ((event.bstate & (BUTTON1_CLICKED |
4585be68eb8Smillert BUTTON1_DOUBLE_CLICKED |
4595be68eb8Smillert BUTTON1_TRIPLE_CLICKED))
4605be68eb8Smillert && wenclose(uwin, event.y, event.x))
4615be68eb8Smillert { /* we react only if the click was in the userwin, that means
4625be68eb8Smillert * inside the menu display area or at the decoration window.
4635be68eb8Smillert */
4645be68eb8Smillert WINDOW *sub = Get_Menu_Window(menu);
4655be68eb8Smillert int ry = event.y, rx = event.x; /* screen coordinates */
4665be68eb8Smillert
4675be68eb8Smillert result = E_REQUEST_DENIED;
4685be68eb8Smillert if (mouse_trafo(&ry, &rx, FALSE))
4695be68eb8Smillert { /* rx, ry are now "curses" coordinates */
4705be68eb8Smillert if (ry < sub->_begy)
4715be68eb8Smillert { /* we clicked above the display region; this is
4725be68eb8Smillert * interpreted as "scroll up" request
4735be68eb8Smillert */
4745be68eb8Smillert if (event.bstate & BUTTON1_CLICKED)
4755be68eb8Smillert result = menu_driver(menu, REQ_SCR_ULINE);
4765be68eb8Smillert else if (event.bstate & BUTTON1_DOUBLE_CLICKED)
4775be68eb8Smillert result = menu_driver(menu, REQ_SCR_UPAGE);
4785be68eb8Smillert else if (event.bstate & BUTTON1_TRIPLE_CLICKED)
4795be68eb8Smillert result = menu_driver(menu, REQ_FIRST_ITEM);
4805be68eb8Smillert RETURN(result);
4815be68eb8Smillert }
48281d8c4e1Snicm else if (ry > sub->_begy + sub->_maxy)
4835be68eb8Smillert { /* we clicked below the display region; this is
4845be68eb8Smillert * interpreted as "scroll down" request
4855be68eb8Smillert */
4865be68eb8Smillert if (event.bstate & BUTTON1_CLICKED)
4875be68eb8Smillert result = menu_driver(menu, REQ_SCR_DLINE);
4885be68eb8Smillert else if (event.bstate & BUTTON1_DOUBLE_CLICKED)
4895be68eb8Smillert result = menu_driver(menu, REQ_SCR_DPAGE);
4905be68eb8Smillert else if (event.bstate & BUTTON1_TRIPLE_CLICKED)
4915be68eb8Smillert result = menu_driver(menu, REQ_LAST_ITEM);
4925be68eb8Smillert RETURN(result);
4935be68eb8Smillert }
4945be68eb8Smillert else if (wenclose(sub, event.y, event.x))
4955be68eb8Smillert { /* Inside the area we try to find the hit item */
496*c7ef0cfcSnicm int x, y;
49781d8c4e1Snicm
49881d8c4e1Snicm ry = event.y;
49981d8c4e1Snicm rx = event.x;
5005be68eb8Smillert if (wmouse_trafo(sub, &ry, &rx, FALSE))
5015be68eb8Smillert {
502*c7ef0cfcSnicm int i;
503*c7ef0cfcSnicm
5045be68eb8Smillert for (i = 0; i < menu->nitems; i++)
5055be68eb8Smillert {
506*c7ef0cfcSnicm int err = _nc_menu_cursor_pos(menu,
507*c7ef0cfcSnicm menu->items[i],
5085be68eb8Smillert &y, &x);
509*c7ef0cfcSnicm
5105be68eb8Smillert if (E_OK == err)
5115be68eb8Smillert {
5125be68eb8Smillert if ((ry == y) &&
5135be68eb8Smillert (rx >= x) &&
5145be68eb8Smillert (rx < x + menu->itemlen))
5155be68eb8Smillert {
5165be68eb8Smillert item = menu->items[i];
5175be68eb8Smillert result = E_OK;
5185be68eb8Smillert break;
5195be68eb8Smillert }
5205be68eb8Smillert }
5215be68eb8Smillert }
5225be68eb8Smillert if (E_OK == result)
5235be68eb8Smillert { /* We found an item, now we can handle the click.
5245be68eb8Smillert * A single click just positions the menu cursor
5255be68eb8Smillert * to the clicked item. A double click toggles
5265be68eb8Smillert * the item.
5275be68eb8Smillert */
5285be68eb8Smillert if (event.bstate & BUTTON1_DOUBLE_CLICKED)
5295be68eb8Smillert {
5305be68eb8Smillert _nc_New_TopRow_and_CurrentItem(menu,
5315be68eb8Smillert my_top_row,
5325be68eb8Smillert item);
5335be68eb8Smillert menu_driver(menu, REQ_TOGGLE_ITEM);
5345be68eb8Smillert result = E_UNKNOWN_COMMAND;
5355be68eb8Smillert }
5365be68eb8Smillert }
5375be68eb8Smillert }
5385be68eb8Smillert }
5395be68eb8Smillert }
5405be68eb8Smillert }
5415be68eb8Smillert else
542*c7ef0cfcSnicm {
543*c7ef0cfcSnicm if (menu->opt & O_MOUSE_MENU)
544*c7ef0cfcSnicm ungetmouse(&event); /* let someone else handle this */
5455be68eb8Smillert result = E_REQUEST_DENIED;
5465be68eb8Smillert }
547*c7ef0cfcSnicm }
5485be68eb8Smillert #endif /* NCURSES_MOUSE_VERSION */
549c166cd22Stholo else
550c166cd22Stholo result = E_UNKNOWN_COMMAND;
551c166cd22Stholo }
552c166cd22Stholo
553*c7ef0cfcSnicm if (item == 0)
554*c7ef0cfcSnicm {
555*c7ef0cfcSnicm result = E_BAD_STATE;
556*c7ef0cfcSnicm }
557*c7ef0cfcSnicm else if (E_OK == result)
5585be68eb8Smillert {
559c166cd22Stholo /* Adjust the top row if it turns out that the current item unfortunately
560c166cd22Stholo doesn't appear in the menu window */
561c166cd22Stholo if (item->y < my_top_row)
562c166cd22Stholo my_top_row = item->y;
5630107aba4Smillert else if (item->y >= (my_top_row + menu->arows))
5640107aba4Smillert my_top_row = item->y - menu->arows + 1;
565c166cd22Stholo
566c166cd22Stholo _nc_New_TopRow_and_CurrentItem(menu, my_top_row, item);
567c166cd22Stholo
5685be68eb8Smillert }
5695be68eb8Smillert
570c166cd22Stholo RETURN(result);
571c166cd22Stholo }
572c166cd22Stholo
573c166cd22Stholo /* m_driver.c ends here */
574