1 /* $NetBSD: driver.c,v 1.9 2003/03/09 01:08:48 lukem Exp $ */
4 * Copyright (c) 1998-1999 Brett Lymn (blymn@baea.com.au, brett_lymn@yahoo.com.au)
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
29 #include <sys/cdefs.h>
30 __RCSID("$NetBSD: driver.c,v 1.9 2003/03/09 01:08:48 lukem Exp $");
35 #include "internals.h"
38 * The guts of the menu library. This function processes the character
39 * in c and performs actions based on the value of the character. If the
40 * character is a normal one then the driver attempts to match the character
41 * against the items. If the character is a recognised request then the
42 * request is processed by the driver, if the character is not a recognised
43 * request and is not printable then it assumed to be a user defined command.
46 menu_driver(MENU
*menu
, int c
)
48 int drv_top_row
, drv_scroll
, i
, it
, status
= E_OK
;
54 return E_BAD_ARGUMENT
;
55 if (menu
->posted
== 0)
57 if (menu
->items
== NULL
)
58 return E_NOT_CONNECTED
;
59 if (*menu
->items
== NULL
)
60 return E_NOT_CONNECTED
;
61 if (menu
->in_init
== 1)
64 /* this one should never happen but just in case.... */
65 if (menu
->items
[menu
->cur_item
] == NULL
)
66 return E_SYSTEM_ERROR
;
68 drv_new_item
= menu
->items
[menu
->cur_item
];
70 drv_top_row
= menu
->top_row
;
72 if ((c
> REQ_BASE_NUM
) && (c
<= MAX_COMMAND
)) {
73 /* is a known driver request - first check if the pattern
74 * buffer needs to be cleared, we do this on non-search
77 if (! ((c
== REQ_BACK_PATTERN
) || (c
== REQ_NEXT_MATCH
) ||
78 (c
== REQ_PREV_MATCH
))) {
79 if ((c
== REQ_CLEAR_PATTERN
)
80 && (menu
->pattern
== NULL
))
81 return E_REQUEST_DENIED
;
90 drv_new_item
= drv_new_item
->left
;
93 drv_new_item
= drv_new_item
->right
;
96 drv_new_item
= drv_new_item
->up
;
99 drv_new_item
= drv_new_item
->down
;
102 if (drv_top_row
== 0)
103 return E_REQUEST_DENIED
;
105 drv_new_item
= drv_new_item
->up
;
109 if ((drv_top_row
+ menu
->rows
- 1)> menu
->item_rows
)
110 return E_REQUEST_DENIED
;
111 drv_new_item
= drv_new_item
->down
;
114 drv_scroll
= menu
->item_rows
- menu
->rows
116 if (drv_scroll
> menu
->rows
) {
117 drv_scroll
= menu
->rows
;
120 if (drv_scroll
<= 0) {
121 return E_REQUEST_DENIED
;
123 drv_top_row
+= drv_scroll
;
124 while (drv_scroll
-- > 0)
125 drv_new_item
= drv_new_item
->down
;
129 if (menu
->rows
< menu
->top_row
) {
130 drv_scroll
= menu
->rows
;
132 drv_scroll
= menu
->top_row
;
135 return E_REQUEST_DENIED
;
137 drv_top_row
-= drv_scroll
;
138 while (drv_scroll
-- > 0)
139 drv_new_item
= drv_new_item
->up
;
142 drv_new_item
= menu
->items
[0];
145 drv_new_item
= menu
->items
[menu
->item_count
- 1];
148 if ((menu
->cur_item
+ 1) >= menu
->item_count
) {
149 if ((menu
->opts
& O_NONCYCLIC
)
151 return E_REQUEST_DENIED
;
153 drv_new_item
= menu
->items
[0];
157 menu
->items
[menu
->cur_item
+ 1];
161 if (menu
->cur_item
== 0) {
162 if ((menu
->opts
& O_NONCYCLIC
)
164 return E_REQUEST_DENIED
;
166 drv_new_item
= menu
->items
[
167 menu
->item_count
- 1];
171 menu
->items
[menu
->cur_item
- 1];
174 case REQ_TOGGLE_ITEM
:
175 if ((menu
->opts
& (O_RADIO
| O_ONEVALUE
)) != 0) {
176 if ((menu
->opts
& O_RADIO
) == O_RADIO
) {
177 if ((drv_new_item
->opts
& O_SELECTABLE
)
179 return E_NOT_SELECTABLE
;
181 /* don't deselect selected item */
182 if (drv_new_item
->selected
== 1)
183 return E_REQUEST_DENIED
;
185 /* deselect all items */
186 for (i
= 0; i
< menu
->item_count
; i
++) {
187 if ((menu
->items
[i
]->selected
) &&
188 (drv_new_item
->index
!= i
)) {
189 menu
->items
[i
]->selected
^= 1;
190 _menui_draw_item(menu
,
191 menu
->items
[i
]->index
);
195 /* turn on selected item */
196 drv_new_item
->selected
^= 1;
197 _menui_draw_item(menu
, drv_new_item
->index
);
199 return E_REQUEST_DENIED
;
202 if ((drv_new_item
->opts
203 & O_SELECTABLE
) == O_SELECTABLE
) {
204 /* toggle select flag */
205 drv_new_item
->selected
^= 1;
206 /* update item in menu */
207 _menui_draw_item(menu
,
208 drv_new_item
->index
);
210 return E_NOT_SELECTABLE
;
214 case REQ_CLEAR_PATTERN
:
215 /* this action is taken before the
218 case REQ_BACK_PATTERN
:
219 if (menu
->pattern
== NULL
)
220 return E_REQUEST_DENIED
;
223 return E_REQUEST_DENIED
;
224 menu
->pattern
[menu
->plen
--] = '\0';
227 if (menu
->pattern
== NULL
)
228 return E_REQUEST_DENIED
;
230 status
= _menui_match_pattern(menu
, 0,
233 drv_new_item
= menu
->items
[it
];
236 if (menu
->pattern
== NULL
)
237 return E_REQUEST_DENIED
;
239 status
= _menui_match_pattern(menu
, 0,
242 drv_new_item
= menu
->items
[it
];
245 } else if (c
> MAX_COMMAND
) {
246 /* must be a user command */
247 return E_UNKNOWN_COMMAND
;
248 } else if (isprint((unsigned char) c
)) {
249 /* otherwise search items for the character. */
250 status
= _menui_match_pattern(menu
, (unsigned char) c
,
252 drv_new_item
= menu
->items
[it
];
254 /* update the position of the cursor if we are doing
255 * show match and the current item has not changed. If
256 * we don't do this here it won't get done since the
257 * display will not be updated due to the current item
260 if ((drv_new_item
->index
== menu
->cur_item
)
261 && ((menu
->opts
& O_SHOWMATCH
) == O_SHOWMATCH
)) {
262 pos_menu_cursor(menu
);
268 return E_BAD_ARGUMENT
;
271 if (drv_new_item
== NULL
)
272 return E_REQUEST_DENIED
;
274 if (drv_new_item
->row
< drv_top_row
) drv_top_row
= drv_new_item
->row
;
275 if (drv_new_item
->row
>= (drv_top_row
+ menu
->rows
))
276 drv_top_row
= drv_new_item
->row
- menu
->rows
+ 1;
278 if ((drv_new_item
->index
!= menu
->cur_item
)
279 || (drv_top_row
!= menu
->top_row
))
280 _menui_goto_item(menu
, drv_new_item
, drv_top_row
);