1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*	Copyright (c) 1988 AT&T	*/
23 /*	  All Rights Reserved	*/
24 
25 
26 /*
27  * Copyright (c) 1997, by Sun Mircrosystems, Inc.
28  * All rights reserved.
29  */
30 
31 /*LINTLIBRARY*/
32 
33 #include <sys/types.h>
34 #include "private.h"
35 
36 int
menu_driver(MENU * m,int c)37 menu_driver(MENU *m, int c)
38 {
39 	int i, n;
40 	int top;
41 	ITEM *current;
42 	int ret;
43 
44 	if (!m) {
45 		return (E_BAD_ARGUMENT);
46 	}
47 	ret = E_OK;
48 	if (Indriver(m)) {
49 		return (E_BAD_STATE);
50 	}
51 	if (!Posted(m)) {
52 		return (E_NOT_POSTED);
53 	}
54 	top = Top(m);
55 	current = Current(m);
56 
57 	if (c > KEY_MAX && c < MAX_COMMAND) {
58 
59 		/* Clear the pattern buffer if not one of these requests */
60 		if (c != REQ_BACK_PATTERN &&
61 		    c != REQ_NEXT_MATCH &&
62 		    c != REQ_PREV_MATCH) {
63 			Pindex(m) = 0;
64 			IthPattern(m, 0) = '\0';
65 		}
66 
67 		switch (c) {
68 
69 		case REQ_RIGHT_ITEM: {
70 			if (Right(current) == (ITEM *)0) {
71 					ret = E_REQUEST_DENIED;
72 					break;
73 			}
74 			current = Right(current);
75 			break;
76 		}
77 		case REQ_LEFT_ITEM: {
78 			if (Left(current) == (ITEM *)0) {
79 				ret = E_REQUEST_DENIED;
80 				break;
81 			}
82 			current = Left(current);
83 			break;
84 		}
85 		case REQ_UP_ITEM: {
86 			if (Up(current) == (ITEM *)0) {
87 				ret = E_REQUEST_DENIED;
88 				break;
89 			}
90 			current = Up(current);
91 			break;
92 		}
93 		case REQ_DOWN_ITEM: {
94 			if (Down(current) == (ITEM *)0) {
95 				ret = E_REQUEST_DENIED;
96 				break;
97 			}
98 			current = Down(current);
99 			break;
100 		}
101 		case REQ_SCR_ULINE: {
102 			if (--top < 0) {
103 				++top;
104 				ret = E_REQUEST_DENIED;
105 				break;
106 			}
107 			current = Up(current);
108 			break;
109 		}
110 		case REQ_SCR_DLINE: {
111 			if (++top > Rows(m) - Height(m)) {
112 				--top;
113 				ret = E_REQUEST_DENIED;
114 				break;
115 			}
116 			current = Down(current);
117 			break;
118 		}
119 		case REQ_SCR_UPAGE: {
120 			n = min(Height(m), top);
121 			if (n) {
122 				top -= n;
123 				for (i = n; i--; ) {
124 					current = Up(current);
125 				}
126 			} else {
127 				ret = E_REQUEST_DENIED;
128 				break;
129 			}
130 			break;
131 		}
132 		case REQ_SCR_DPAGE: {
133 			n = min(Height(m), Rows(m) - Height(m) - top);
134 			if (n) {
135 				top += n;
136 				for (i = n; i--; ) {
137 					current = Down(current);
138 				}
139 			} else {
140 				ret = E_REQUEST_DENIED;
141 				break;
142 			}
143 			break;
144 		}
145 		case REQ_FIRST_ITEM: {
146 			current = IthItem(m, 0);
147 			break;
148 		}
149 		case REQ_LAST_ITEM: {
150 			current = IthItem(m, Nitems(m)-1);
151 			break;
152 		}
153 		case REQ_NEXT_MATCH: {
154 			if (IthPattern(m, 0) != '\0') {
155 				ret = _match(m, '\0', &current);
156 			} else {
157 				if (Index(current)+1 >= Nitems(m)) {
158 					current = IthItem(m, 0);
159 				} else {
160 					current = IthItem(m, Index(current)+1);
161 				}
162 			}
163 			break;
164 		}
165 		case REQ_NEXT_ITEM: {
166 			if (Index(current)+1 >= Nitems(m)) {
167 				if (Cyclic(m)) {
168 					current = IthItem(m, 0);
169 				} else {
170 					ret = E_REQUEST_DENIED;
171 				}
172 			} else {
173 				current = IthItem(m, Index(current)+1);
174 			}
175 			break;
176 		}
177 		case REQ_PREV_MATCH: {
178 			if (IthPattern(m, 0) != '\0') {
179 				ret = _match(m, '\b', &current);
180 			} else {
181 				/* This differs from PREV_ITEM in that */
182 				/* it is cyclic */
183 				if (Index(current)-1 < 0) {
184 					current = IthItem(m, Nitems(m)-1);
185 				} else {
186 					current = IthItem(m, Index(current)-1);
187 				}
188 			}
189 			break;
190 		}
191 		case REQ_PREV_ITEM: {
192 			if (Index(current)-1 < 0) {
193 				if (Cyclic(m)) {
194 					current = IthItem(m, Nitems(m)-1);
195 				} else {
196 					ret = E_REQUEST_DENIED;
197 				}
198 			} else {
199 				current = IthItem(m, Index(current)-1);
200 			}
201 			break;
202 		}
203 		case REQ_TOGGLE_ITEM: {
204 			if (!OneValue(m)) {
205 				if (Selectable(Current(m))) {
206 					Value(Current(m)) ^= TRUE;
207 					_move_post_item(m, Current(m));
208 					_show(m);
209 				} else {
210 					ret = E_NOT_SELECTABLE;
211 				}
212 			} else {
213 				ret = E_REQUEST_DENIED;
214 			}
215 			break;
216 		}
217 		case REQ_BACK_PATTERN: {
218 			if (Pindex(m) > 0) {
219 				Pindex(m) -= 1;
220 				IthPattern(m, Pindex(m)) = '\0';
221 				_position_cursor(m);
222 			} else {
223 				ret = E_REQUEST_DENIED;
224 			}
225 			break;
226 		}
227 		case REQ_CLEAR_PATTERN: {
228 			/* This was already done at the top */
229 			break;
230 		}
231 		default: {
232 			ret = E_UNKNOWN_COMMAND;
233 		}
234 		}
235 	} else {
236 		if (c > 037 && c < 0177) {
237 			/*LINTED [E_PASS_INT_TO_SMALL_INT]*/
238 			ret = _match(m, c, &current);
239 		} else {
240 			ret = E_UNKNOWN_COMMAND;
241 		}
242 	}
243 
244 	/* Verify the location of the top row */
245 
246 	_chk_top(m, &top, current);
247 
248 	/* Go change the actual values of Top and Current and do init/term */
249 
250 	_affect_change(m, top, current);
251 
252 	return (ret);
253 }
254