]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - usr.sbin/sysinstall/dmenu.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / usr.sbin / sysinstall / dmenu.c
1 /*
2  * The new sysinstall program.
3  *
4  * This is probably the last attempt in the `sysinstall' line, the next
5  * generation being slated for what's essentially a complete rewrite.
6  *
7  * $FreeBSD$
8  *
9  * Copyright (c) 1995
10  *      Jordan Hubbard.  All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer,
17  *    verbatim and that no modifications are made prior to this
18  *    point in the file.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  *
23  * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  */
36
37 #include "sysinstall.h"
38 #include <sys/param.h>
39 #include <errno.h>
40
41 #define MAX_MENU                15
42
43 static Boolean exited;
44
45 int
46 dmenuDisplayFile(dialogMenuItem *tmp)
47 {
48     systemDisplayHelp((char *)tmp->data);
49     return DITEM_SUCCESS;
50 }
51
52 int
53 dmenuSubmenu(dialogMenuItem *tmp)
54 {
55     return (dmenuOpenSimple((DMenu *)(tmp->data), FALSE) ? DITEM_SUCCESS : DITEM_FAILURE);
56 }
57
58 int
59 dmenuSystemCommand(dialogMenuItem *self)
60 {
61     WINDOW *w = NULL;   /* Keep lint happy */
62
63     /* If aux is set, the command is known not to produce any screen-spoiling output */
64     if (!self->aux)
65         w = savescr();
66     systemExecute((char *)self->data);
67     if (!self->aux)
68         restorescr(w);
69     return DITEM_SUCCESS;
70 }
71
72 int
73 dmenuSystemCommandBox(dialogMenuItem *tmp)
74 {
75     WINDOW *w = savescr();
76     
77     use_helpfile(NULL);
78     use_helpline("Select OK to dismiss this dialog");
79     dialog_prgbox(tmp->title, (char *)tmp->data, 22, 76, 1, 1);
80     restorescr(w);
81     return DITEM_SUCCESS;
82 }
83
84 int
85 dmenuExit(dialogMenuItem *tmp)
86 {
87     exited = TRUE;
88     return DITEM_LEAVE_MENU;
89 }
90
91 int
92 dmenuSetVariable(dialogMenuItem *tmp)
93 {
94     variable_set((char *)tmp->data, *((char *)tmp->data) != '_');
95     return DITEM_SUCCESS;
96 }
97
98 int
99 dmenuSetVariables(dialogMenuItem *tmp)
100 {
101     char *cp1, *cp2;
102     char *copy = strdup((char *)tmp->data);
103
104     for (cp1 = copy; cp1 != NULL;) {
105         cp2 = index(cp1, ',');
106         if (cp2 != NULL) *cp2++ = '\0';
107         variable_set(cp1, *cp1 != '_');
108         cp1 = cp2;
109     }
110     free(copy);
111     return DITEM_SUCCESS;
112 }
113
114 int
115 dmenuSetCountryVariable(dialogMenuItem *tmp)
116 {
117     variable_set((char *)tmp->data, FALSE);
118 #ifdef WITH_SYSCONS
119     /* Don't prompt the user for a keymap if they're using the default locale. */
120     if (!strcmp(variable_get(VAR_COUNTRY), DEFAULT_COUNTRY))
121         return DITEM_SUCCESS;
122
123     return keymapMenuSelect(tmp);
124 #else
125     return DITEM_SUCCESS;
126 #endif
127 }
128
129 int
130 dmenuSetKmapVariable(dialogMenuItem *tmp)
131 {
132     char *lang;
133     int err;
134
135     variable_set((char *)tmp->data, TRUE);
136     lang = variable_get(VAR_KEYMAP);
137     if (lang != NULL)
138     {
139         err = loadKeymap(lang);
140         if (err == -1)
141             msgConfirm("No appropriate keyboard map found, sorry.");
142         else if (err == -2)
143             msgConfirm("Error installing keyboard map, errno = %d.", errno);
144     }
145     return DITEM_SUCCESS;
146 }
147
148 int
149 dmenuToggleVariable(dialogMenuItem *tmp)
150 {
151     char *var, *cp;
152     int status;
153
154     if (!(var = strdup((char *)tmp->data))) {
155         msgConfirm("Incorrect data field for `%s'!", tmp->title);
156         return DITEM_FAILURE;
157     }
158     if (!(cp = index(var, '='))) {
159         msgConfirm("Data field for %s is not in var=value format!", tmp->title);
160         return DITEM_FAILURE;
161     }
162     status = variable_check(var);
163     *cp = '\0';
164     variable_set2(var, status ? "NO" : "YES", *var != '_');
165     free(var);
166     return DITEM_SUCCESS;
167 }
168
169 int
170 dmenuISetVariable(dialogMenuItem *tmp)
171 {
172     char *ans, *p, *var;
173
174     if (!(var = strdup((char *)tmp->data))) {
175         msgConfirm("Incorrect data field for `%s'!", tmp->title);
176         return DITEM_FAILURE;
177     }
178     if ((p = index(var, '=')) != NULL)
179         *p = '\0';
180     ans = msgGetInput(variable_get(var), tmp->title, 1);
181     if (!ans) {
182         free(var);
183         return DITEM_FAILURE;
184     } else if (!*ans)
185         variable_unset(var);
186     else
187         variable_set2(var, ans, *var != '_');
188     free(var);
189     return DITEM_SUCCESS;
190 }
191
192 int
193 dmenuSetFlag(dialogMenuItem *tmp)
194 {
195     if (*((unsigned int *)tmp->data) & tmp->aux)
196         *((unsigned int *)tmp->data) &= ~tmp->aux;
197     else
198         *((unsigned int *)tmp->data) |= tmp->aux;
199     return DITEM_SUCCESS;
200 }
201
202 int
203 dmenuSetValue(dialogMenuItem *tmp)
204 {
205     *((unsigned int *)tmp->data) = tmp->aux;
206     return DITEM_SUCCESS;
207 }
208
209 /* Traverse menu but give user no control over positioning */
210 Boolean
211 dmenuOpenSimple(DMenu *menu, Boolean buttons)
212 {
213     int choice, scroll, curr, max;
214
215     choice = scroll = curr = max = 0;
216     return dmenuOpen(menu, &choice, &scroll, &curr, &max, buttons);
217 }
218
219 /* Work functions for the state hook */
220 int
221 dmenuFlagCheck(dialogMenuItem *item)
222 {
223     return (*((unsigned int *)item->data) & item->aux);
224 }
225
226 int
227 dmenuVarCheck(dialogMenuItem *item)
228 {
229     char *w;
230
231     w = (char *)item->aux;
232     if (!w)
233         w = (char *)item->data;
234     return variable_check(w);
235 }
236
237 int
238 dmenuVarsCheck(dialogMenuItem *item)
239 {
240     int res, init;
241     char *w, *cp1, *cp2;
242     char *copy;
243
244     w = (char *)item->aux;
245     if (!w)
246         w = (char *)item->data;
247     if (!w)
248         return FALSE;
249     
250     copy = strdup(w);
251     res = TRUE;
252     init = FALSE;
253     for (cp1 = copy; cp1 != NULL;) {
254         init = TRUE;
255         cp2 = index(cp1, ',');
256         if (cp2 != NULL)
257             *cp2++ = '\0';
258         res = res && variable_check(cp1);
259         cp1 = cp2;
260     }
261     free(copy);
262     return res && init;
263 }
264
265 int
266 dmenuRadioCheck(dialogMenuItem *item)
267 {
268     return (*((int *)item->data) == item->aux);
269 }
270
271 static int
272 menu_height(DMenu *menu, int n)
273 {
274     int max;
275     char *t;
276
277     max = MAX_MENU;
278     if (StatusLine > 24)
279         max += StatusLine - 24;
280     for (t = menu->prompt; *t; t++) {
281         if (*t == '\n')
282             --max;
283     }
284     return n > max ? max : n;
285 }
286
287 /* Find a menu item that matches any field. */
288 int
289 dmenuFindItem(DMenu *menu, const char *prompt, const char *title, void *data)
290 {
291     dialogMenuItem *items = menu->items;
292     int i;
293
294     for (i = 0; items[i].prompt; ++i)
295         if ((prompt && !strcmp(items[i].prompt, prompt)) ||
296                 (title && !strcmp(items[i].title, title)) ||
297                 (data && items[i].data == data))
298             return i;
299
300     return -1;
301 }
302
303 /* Set the default item for a menu by index and scroll to it. */
304 void
305 dmenuSetDefaultIndex(DMenu *menu, int *choice, int *scroll, int *curr, int *max)
306 {
307     int nitem;
308     int height;
309
310     *curr = *max = 0;
311
312     for (nitem = 0; menu->items[nitem].prompt; ++nitem);
313
314     height = menu_height(menu, nitem);
315     if (*choice > height)
316     {
317         *scroll = MIN(nitem - height, *choice);
318         *choice = *choice - *scroll;
319     }
320     else
321         *scroll = 0;
322 }
323
324 /* Set the default menu item that matches any field and scroll to it. */
325 Boolean
326 dmenuSetDefaultItem(DMenu *menu, const char *prompt, const char *title, void *data,
327                     int *choice, int *scroll, int *curr, int *max)
328 {
329     if ((*choice = dmenuFindItem(menu, prompt, title, data)) != -1)
330     {
331         dmenuSetDefaultIndex(menu, choice, scroll, curr, max);
332         return TRUE;
333     }
334     else
335     {
336         *choice = *scroll = *curr = *max = 0;
337         return FALSE;
338     }
339 }
340
341 /* Traverse over an internal menu */
342 Boolean
343 dmenuOpen(DMenu *menu, int *choice, int *scroll, int *curr, int *max, Boolean buttons)
344 {
345     int n, rval = 0;
346     dialogMenuItem *items;
347
348     items = menu->items;
349     if (buttons)
350         items += 2;
351     /* Count up all the items */
352     for (n = 0; items[n].title; n++);
353
354     while (1) {
355         char buf[FILENAME_MAX];
356         WINDOW *w = savescr();
357
358         /* Any helpful hints, put 'em up! */
359         use_helpline(menu->helpline);
360         use_helpfile(systemHelpFile(menu->helpfile, buf));
361         dialog_clear_norefresh();
362         /* Pop up that dialog! */
363         if (menu->type & DMENU_NORMAL_TYPE)
364             rval = dialog_menu((u_char *)menu->title, (u_char *)menu->prompt,
365                 -1, -1, menu_height(menu, n), -n, items,
366                 (char *)(uintptr_t)buttons, choice, scroll);
367
368         else if (menu->type & DMENU_RADIO_TYPE)
369             rval = dialog_radiolist((u_char *)menu->title,
370                 (u_char *)menu->prompt, -1, -1, menu_height(menu, n), -n,
371                 items, (char *)(uintptr_t)buttons);
372
373         else if (menu->type & DMENU_CHECKLIST_TYPE)
374             rval = dialog_checklist((u_char *)menu->title,
375                 (u_char *)menu->prompt, -1, -1, menu_height(menu, n), -n,
376                 items, (char *)(uintptr_t)buttons);
377         else
378             msgFatal("Menu: `%s' is of an unknown type\n", menu->title);
379         if (exited) {
380             exited = FALSE;
381             restorescr(w);
382             return TRUE;
383         }
384         else if (rval) {
385             restorescr(w);
386             return FALSE;
387         }
388         else if (menu->type & DMENU_SELECTION_RETURNS) {
389             restorescr(w);
390             return TRUE;
391         }
392     }
393 }