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 43static Boolean exited; 44 45int 46dmenuDisplayFile(dialogMenuItem *tmp) 47{ 48 systemDisplayHelp((char *)tmp->data); 49 return DITEM_SUCCESS; 50} 51 52int 53dmenuSubmenu(dialogMenuItem *tmp) 54{ 55 return (dmenuOpenSimple((DMenu *)(tmp->data), FALSE) ? DITEM_SUCCESS : DITEM_FAILURE); 56} 57 58int 59dmenuSystemCommand(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 72int 73dmenuSystemCommandBox(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 84int 85dmenuExit(dialogMenuItem *tmp) 86{ 87 exited = TRUE; 88 return DITEM_LEAVE_MENU; 89} 90 91int 92dmenuSetVariable(dialogMenuItem *tmp) 93{ 94 variable_set((char *)tmp->data, *((char *)tmp->data) != '_'); 95 return DITEM_SUCCESS; 96} 97 98int 99dmenuSetVariables(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 114int 115dmenuSetCountryVariable(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 129int 130dmenuSetKmapVariable(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 148int 149dmenuToggleVariable(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 169int 170dmenuISetVariable(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 192int 193dmenuSetFlag(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 202int 203dmenuSetValue(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 */ 210Boolean 211dmenuOpenSimple(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 */ 220int 221dmenuFlagCheck(dialogMenuItem *item) 222{ 223 return (*((unsigned int *)item->data) & item->aux); 224} 225 226int 227dmenuVarCheck(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 237int 238dmenuVarsCheck(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 265int 266dmenuRadioCheck(dialogMenuItem *item) 267{ 268 return (*((int *)item->data) == item->aux); 269} 270 271static int 272menu_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. */ 288int 289dmenuFindItem(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. */ 304void 305dmenuSetDefaultIndex(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. */ 325Boolean 326dmenuSetDefaultItem(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 */ 342Boolean 343dmenuOpen(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} 394