1/*
2 * $FreeBSD$
3 *
4 * Copyright (c) 1995
5 *	Jordan Hubbard.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer,
12 *    verbatim and that no modifications are made prior to this
13 *    point in the file.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED.  IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 */
31
32#include "sade.h"
33#include <errno.h>
34
35#define MAX_MENU		15
36
37static Boolean exited;
38
39int
40dmenuDisplayFile(dialogMenuItem *tmp)
41{
42    systemDisplayHelp((char *)tmp->data);
43    return DITEM_SUCCESS;
44}
45
46int
47dmenuSubmenu(dialogMenuItem *tmp)
48{
49    return (dmenuOpenSimple((DMenu *)(tmp->data), FALSE) ? DITEM_SUCCESS : DITEM_FAILURE);
50}
51
52int
53dmenuSystemCommand(dialogMenuItem *self)
54{
55    WINDOW *w = NULL;	/* Keep lint happy */
56
57    /* If aux is set, the command is known not to produce any screen-spoiling output */
58    if (!self->aux)
59	w = savescr();
60    systemExecute((char *)self->data);
61    if (!self->aux)
62	restorescr(w);
63    return DITEM_SUCCESS;
64}
65
66int
67dmenuSystemCommandBox(dialogMenuItem *tmp)
68{
69    WINDOW *w = savescr();
70
71    use_helpfile(NULL);
72    use_helpline("Select OK to dismiss this dialog");
73    dialog_prgbox(tmp->title, (char *)tmp->data, 22, 76, 1, 1);
74    restorescr(w);
75    return DITEM_SUCCESS;
76}
77
78int
79dmenuExit(dialogMenuItem *tmp)
80{
81    exited = TRUE;
82    return DITEM_LEAVE_MENU;
83}
84
85int
86dmenuSetVariable(dialogMenuItem *tmp)
87{
88    variable_set((char *)tmp->data, *((char *)tmp->data) != '_');
89    return DITEM_SUCCESS;
90}
91
92int
93dmenuSetVariables(dialogMenuItem *tmp)
94{
95    char *cp1, *cp2;
96    char *copy = strdup((char *)tmp->data);
97
98    for (cp1 = copy; cp1 != NULL;) {
99	cp2 = index(cp1, ',');
100	if (cp2 != NULL) *cp2++ = '\0';
101	variable_set(cp1, *cp1 != '_');
102	cp1 = cp2;
103    }
104    free(copy);
105    return DITEM_SUCCESS;
106}
107
108int
109dmenuToggleVariable(dialogMenuItem *tmp)
110{
111    char *var, *cp;
112    int status;
113
114    if (!(var = strdup((char *)tmp->data))) {
115	msgConfirm("Incorrect data field for `%s'!", tmp->title);
116	return DITEM_FAILURE;
117    }
118    if (!(cp = index(var, '='))) {
119	msgConfirm("Data field for %s is not in var=value format!", tmp->title);
120	return DITEM_FAILURE;
121    }
122    status = variable_check(var);
123    *cp = '\0';
124    variable_set2(var, status ? "NO" : "YES", *var != '_');
125    free(var);
126    return DITEM_SUCCESS;
127}
128
129int
130dmenuISetVariable(dialogMenuItem *tmp)
131{
132    char *ans, *var;
133
134    if (!(var = (char *)tmp->data)) {
135	msgConfirm("Incorrect data field for `%s'!", tmp->title);
136	return DITEM_FAILURE;
137    }
138    ans = msgGetInput(variable_get(var), tmp->title, 1);
139    if (!ans)
140	return DITEM_FAILURE;
141    else if (!*ans)
142	variable_unset(var);
143    else
144	variable_set2(var, ans, *var != '_');
145    return DITEM_SUCCESS;
146}
147
148int
149dmenuSetFlag(dialogMenuItem *tmp)
150{
151    if (*((unsigned int *)tmp->data) & tmp->aux)
152	*((unsigned int *)tmp->data) &= ~tmp->aux;
153    else
154	*((unsigned int *)tmp->data) |= tmp->aux;
155    return DITEM_SUCCESS;
156}
157
158int
159dmenuSetValue(dialogMenuItem *tmp)
160{
161    *((unsigned int *)tmp->data) = tmp->aux;
162    return DITEM_SUCCESS;
163}
164
165/* Traverse menu but give user no control over positioning */
166Boolean
167dmenuOpenSimple(DMenu *menu, Boolean buttons)
168{
169    int choice, scroll, curr, max;
170
171    choice = scroll = curr = max = 0;
172    return dmenuOpen(menu, &choice, &scroll, &curr, &max, buttons);
173}
174
175/* Work functions for the state hook */
176int
177dmenuFlagCheck(dialogMenuItem *item)
178{
179    return (*((unsigned int *)item->data) & item->aux);
180}
181
182int
183dmenuVarCheck(dialogMenuItem *item)
184{
185    char *w;
186
187    w = (char *)item->aux;
188    if (!w)
189	w = (char *)item->data;
190    return variable_check(w);
191}
192
193int
194dmenuVarsCheck(dialogMenuItem *item)
195{
196    int res, init;
197    char *w, *cp1, *cp2;
198    char *copy;
199
200    w = (char *)item->aux;
201    if (!w)
202	w = (char *)item->data;
203    if (!w)
204	return FALSE;
205
206    copy = strdup(w);
207    res = TRUE;
208    init = FALSE;
209    for (cp1 = copy; cp1 != NULL;) {
210        init = TRUE;
211	cp2 = index(cp1, ',');
212	if (cp2 != NULL)
213	    *cp2++ = '\0';
214	res = res && variable_check(cp1);
215	cp1 = cp2;
216    }
217    free(copy);
218    return res && init;
219}
220
221int
222dmenuRadioCheck(dialogMenuItem *item)
223{
224    return (*((long *)item->data) == item->aux);
225}
226
227static int
228menu_height(DMenu *menu, int n)
229{
230    int max;
231    char *t;
232
233    max = MAX_MENU;
234    if (StatusLine > 24)
235	max += StatusLine - 24;
236    for (t = menu->prompt; *t; t++) {
237	if (*t == '\n')
238	    --max;
239    }
240    return n > max ? max : n;
241}
242
243/* Traverse over an internal menu */
244Boolean
245dmenuOpen(DMenu *menu, int *choice, int *scroll, int *curr, int *max, Boolean buttons)
246{
247    int n, rval = 0;
248    dialogMenuItem *items;
249
250    items = menu->items;
251    if (buttons)
252	items += 2;
253    /* Count up all the items */
254    for (n = 0; items[n].title; n++);
255
256    while (1) {
257	char buf[FILENAME_MAX];
258	WINDOW *w = savescr();
259
260	/* Any helpful hints, put 'em up! */
261	use_helpline(menu->helpline);
262	use_helpfile(systemHelpFile(menu->helpfile, buf));
263	dialog_clear_norefresh();
264	/* Pop up that dialog! */
265	if (menu->type & DMENU_NORMAL_TYPE)
266	    rval = dialog_menu((u_char *)menu->title, (u_char *)menu->prompt,
267		-1, -1, menu_height(menu, n), -n, items,
268		(char *)(uintptr_t)buttons, choice, scroll);
269
270	else if (menu->type & DMENU_RADIO_TYPE)
271	    rval = dialog_radiolist((u_char *)menu->title,
272		(u_char *)menu->prompt, -1, -1, menu_height(menu, n), -n,
273		items, (char *)(uintptr_t)buttons);
274
275	else if (menu->type & DMENU_CHECKLIST_TYPE)
276	    rval = dialog_checklist((u_char *)menu->title,
277		(u_char *)menu->prompt, -1, -1, menu_height(menu, n), -n,
278		items, (char *)(uintptr_t)buttons);
279	else
280	    msgFatal("Menu: `%s' is of an unknown type\n", menu->title);
281	if (exited) {
282	    exited = FALSE;
283	    restorescr(w);
284	    return TRUE;
285	}
286	else if (rval) {
287	    restorescr(w);
288	    return FALSE;
289	}
290	else if (menu->type & DMENU_SELECTION_RETURNS) {
291	    restorescr(w);
292	    return TRUE;
293	}
294    }
295}
296