]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/sysinstall/dmenu.c
This commit was generated by cvs2svn to compensate for changes in r164146,
[FreeBSD/FreeBSD.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, *var;
173
174     if (!(var = (char *)tmp->data)) {
175         msgConfirm("Incorrect data field for `%s'!", tmp->title);
176         return DITEM_FAILURE;
177     }
178     ans = msgGetInput(variable_get(var), tmp->title, 1);
179     if (!ans)
180         return DITEM_FAILURE;
181     else if (!*ans)
182         variable_unset(var);
183     else
184         variable_set2(var, ans, *var != '_');
185     return DITEM_SUCCESS;
186 }
187
188 int
189 dmenuSetFlag(dialogMenuItem *tmp)
190 {
191     if (*((unsigned int *)tmp->data) & tmp->aux)
192         *((unsigned int *)tmp->data) &= ~tmp->aux;
193     else
194         *((unsigned int *)tmp->data) |= tmp->aux;
195     return DITEM_SUCCESS;
196 }
197
198 int
199 dmenuSetValue(dialogMenuItem *tmp)
200 {
201     *((unsigned int *)tmp->data) = tmp->aux;
202     return DITEM_SUCCESS;
203 }
204
205 /* Traverse menu but give user no control over positioning */
206 Boolean
207 dmenuOpenSimple(DMenu *menu, Boolean buttons)
208 {
209     int choice, scroll, curr, max;
210
211     choice = scroll = curr = max = 0;
212     return dmenuOpen(menu, &choice, &scroll, &curr, &max, buttons);
213 }
214
215 /* Work functions for the state hook */
216 int
217 dmenuFlagCheck(dialogMenuItem *item)
218 {
219     return (*((unsigned int *)item->data) & item->aux);
220 }
221
222 int
223 dmenuVarCheck(dialogMenuItem *item)
224 {
225     char *w;
226
227     w = (char *)item->aux;
228     if (!w)
229         w = (char *)item->data;
230     return variable_check(w);
231 }
232
233 int
234 dmenuVarsCheck(dialogMenuItem *item)
235 {
236     int res, init;
237     char *w, *cp1, *cp2;
238     char *copy;
239
240     w = (char *)item->aux;
241     if (!w)
242         w = (char *)item->data;
243     if (!w)
244         return FALSE;
245     
246     copy = strdup(w);
247     res = TRUE;
248     init = FALSE;
249     for (cp1 = copy; cp1 != NULL;) {
250         init = TRUE;
251         cp2 = index(cp1, ',');
252         if (cp2 != NULL)
253             *cp2++ = '\0';
254         res = res && variable_check(cp1);
255         cp1 = cp2;
256     }
257     free(copy);
258     return res && init;
259 }
260
261 int
262 dmenuRadioCheck(dialogMenuItem *item)
263 {
264     return (*((int *)item->data) == item->aux);
265 }
266
267 static int
268 menu_height(DMenu *menu, int n)
269 {
270     int max;
271     char *t;
272
273     max = MAX_MENU;
274     if (StatusLine > 24)
275         max += StatusLine - 24;
276     for (t = menu->prompt; *t; t++) {
277         if (*t == '\n')
278             --max;
279     }
280     return n > max ? max : n;
281 }
282
283 /* Find a menu item that matches any field. */
284 int
285 dmenuFindItem(DMenu *menu, const char *prompt, const char *title, void *data)
286 {
287     dialogMenuItem *items = menu->items;
288     int i;
289
290     for (i = 0; items[i].prompt; ++i)
291         if ((prompt && !strcmp(items[i].prompt, prompt)) ||
292                 (title && !strcmp(items[i].title, title)) ||
293                 (data && items[i].data == data))
294             return i;
295
296     return -1;
297 }
298
299 /* Set the default item for a menu by index and scroll to it. */
300 void
301 dmenuSetDefaultIndex(DMenu *menu, int *choice, int *scroll, int *curr, int *max)
302 {
303     int nitem;
304     int height;
305
306     *curr = *max = 0;
307
308     for (nitem = 0; menu->items[nitem].prompt; ++nitem);
309
310     height = menu_height(menu, nitem);
311     if (*choice > height)
312     {
313         *scroll = MIN(nitem - height, *choice);
314         *choice = *choice - *scroll;
315     }
316     else
317         *scroll = 0;
318 }
319
320 /* Set the default menu item that matches any field and scroll to it. */
321 Boolean
322 dmenuSetDefaultItem(DMenu *menu, const char *prompt, const char *title, void *data,
323                     int *choice, int *scroll, int *curr, int *max)
324 {
325     if ((*choice = dmenuFindItem(menu, prompt, title, data)) != -1)
326     {
327         dmenuSetDefaultIndex(menu, choice, scroll, curr, max);
328         return TRUE;
329     }
330     else
331     {
332         *choice = *scroll = *curr = *max = 0;
333         return FALSE;
334     }
335 }
336
337 /* Traverse over an internal menu */
338 Boolean
339 dmenuOpen(DMenu *menu, int *choice, int *scroll, int *curr, int *max, Boolean buttons)
340 {
341     int n, rval = 0;
342     dialogMenuItem *items;
343
344     items = menu->items;
345     if (buttons)
346         items += 2;
347     /* Count up all the items */
348     for (n = 0; items[n].title; n++);
349
350     while (1) {
351         char buf[FILENAME_MAX];
352         WINDOW *w = savescr();
353
354         /* Any helpful hints, put 'em up! */
355         use_helpline(menu->helpline);
356         use_helpfile(systemHelpFile(menu->helpfile, buf));
357         dialog_clear_norefresh();
358         /* Pop up that dialog! */
359         if (menu->type & DMENU_NORMAL_TYPE)
360             rval = dialog_menu((u_char *)menu->title, (u_char *)menu->prompt,
361                 -1, -1, menu_height(menu, n), -n, items,
362                 (char *)(uintptr_t)buttons, choice, scroll);
363
364         else if (menu->type & DMENU_RADIO_TYPE)
365             rval = dialog_radiolist((u_char *)menu->title,
366                 (u_char *)menu->prompt, -1, -1, menu_height(menu, n), -n,
367                 items, (char *)(uintptr_t)buttons);
368
369         else if (menu->type & DMENU_CHECKLIST_TYPE)
370             rval = dialog_checklist((u_char *)menu->title,
371                 (u_char *)menu->prompt, -1, -1, menu_height(menu, n), -n,
372                 items, (char *)(uintptr_t)buttons);
373         else
374             msgFatal("Menu: `%s' is of an unknown type\n", menu->title);
375         if (exited) {
376             exited = FALSE;
377             restorescr(w);
378             return TRUE;
379         }
380         else if (rval) {
381             restorescr(w);
382             return FALSE;
383         }
384         else if (menu->type & DMENU_SELECTION_RETURNS) {
385             restorescr(w);
386             return TRUE;
387         }
388     }
389 }