]> git.ipfire.org Git - thirdparty/newt.git/blob - whiptcl.c
split whiptail dialog stuff out; added whiptcl
[thirdparty/newt.git] / whiptcl.c
1 #include <string.h>
2 #include <stdlib.h>
3
4 #include "dialogboxes.h"
5 #include "newt.h"
6 #include "popt.h"
7 #include "tcl.h"
8
9 enum mode { MODE_NONE, MODE_MSGBOX, MODE_YESNO, MODE_CHECKLIST, MODE_INPUTBOX,
10 MODE_RADIOLIST, MODE_MENU };
11
12 #define OPT_MSGBOX 1000
13 #define OPT_CHECKLIST 1001
14 #define OPT_YESNO 1002
15 #define OPT_INPUTBOX 1003
16 #define OPT_MENU 1005
17 #define OPT_RADIOLIST 1006
18
19 static char * setBacktext(ClientData data, Tcl_Interp * interp,
20 char * name1, char * name2, int flags);
21 static char * setHelptext(ClientData data, Tcl_Interp * interp,
22 char * name1, char * name2, int flags);
23 static char * setFullButtons(ClientData data, Tcl_Interp * interp,
24 char * name1, char * name2, int flags);
25
26 static int wtFinish(ClientData clientData, Tcl_Interp * interp, int argc,
27 char ** argv) {
28 newtFinished();
29
30 return TCL_OK;
31 }
32
33 static int wtInit(ClientData clientData, Tcl_Interp * interp, int argc,
34 char ** argv) {
35 newtInit();
36 newtCls();
37
38 newtPushHelpLine("");
39
40 Tcl_TraceVar(interp, "whiptcl_backtext",
41 TCL_TRACE_WRITES | TCL_GLOBAL_ONLY, setBacktext, NULL);
42 Tcl_TraceVar(interp, "whiptcl_helpline",
43 TCL_TRACE_WRITES | TCL_TRACE_UNSETS | TCL_GLOBAL_ONLY,
44 setHelptext, NULL);
45 Tcl_TraceVar(interp, "whiptcl_fullbuttons",
46 TCL_TRACE_WRITES | TCL_TRACE_UNSETS | TCL_GLOBAL_ONLY,
47 setFullButtons, NULL);
48
49 Tcl_SetVar(interp, "whiptcl_helpline", "", TCL_GLOBAL_ONLY);
50 Tcl_SetVar(interp, "whiptcl_fullbuttons", "1", TCL_GLOBAL_ONLY);
51
52 return TCL_OK;
53 }
54
55 static int wtCmd(ClientData clientData, Tcl_Interp * interp, int argc,
56 char ** argv) {
57 enum mode mode = MODE_NONE;
58 poptContext optCon;
59 int arg;
60 char * optArg;
61 char * text;
62 char * nextArg;
63 char * end;
64 int height;
65 int width;
66 int noCancel = 0;
67 int noItem = 0;
68 int scrollText = 0;
69 int rc = 0;
70 int flags = 0;
71 int defaultNo = 0;
72 char * result;
73 char ** selections, ** next;
74 char * title = NULL;
75 struct poptOption optionsTable[] = {
76 { "checklist", '\0', 0, 0, OPT_CHECKLIST },
77 { "defaultno", '\0', 0, &defaultNo, 0 },
78 { "inputbox", '\0', 0, 0, OPT_INPUTBOX },
79 { "menu", '\0', 0, 0, OPT_MENU },
80 { "msgbox", '\0', 0, 0, OPT_MSGBOX },
81 { "nocancel", '\0', 0, &noCancel, 0 },
82 { "noitem", '\0', 0, &noItem, 0 },
83 { "radiolist", '\0', 0, 0, OPT_RADIOLIST },
84 { "scrolltext", '\0', 0, &scrollText, 0 },
85 { "title", '\0', POPT_ARG_STRING, &title, 0 },
86 { "yesno", '\0', 0, 0, OPT_YESNO },
87 { 0, 0, 0, 0, 0 }
88 };
89
90 optCon = poptGetContext("whiptcl", argc, argv, optionsTable, 0);
91
92 while ((arg = poptGetNextOpt(optCon)) > 0) {
93 optArg = poptGetOptArg(optCon);
94
95 switch (arg) {
96 case OPT_MENU:
97 if (mode != MODE_NONE) rc = -1;
98 mode = MODE_MENU;
99 break;
100
101 case OPT_MSGBOX:
102 if (mode != MODE_NONE) rc = -1;
103 mode = MODE_MSGBOX;
104 break;
105
106 case OPT_RADIOLIST:
107 if (mode != MODE_NONE) rc = -1;
108 mode = MODE_RADIOLIST;
109 break;
110
111 case OPT_CHECKLIST:
112 if (mode != MODE_NONE) rc = -1;
113 mode = MODE_CHECKLIST;
114 break;
115
116 case OPT_YESNO:
117 if (mode != MODE_NONE) rc = -1;
118 mode = MODE_YESNO;
119 break;
120
121 case OPT_INPUTBOX:
122 if (mode != MODE_NONE) rc = -1;
123 mode = MODE_INPUTBOX;
124 break;
125 }
126 }
127
128 if (arg < -1) {
129 /* this could buffer oveflow, bug we're not setuid so I don't care */
130 interp->result = malloc(200);
131 interp->freeProc = TCL_DYNAMIC;
132 sprintf(interp->result, "%s: %s\n",
133 poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
134 poptStrerror(arg));
135
136 return TCL_ERROR;
137 }
138
139 if (mode == MODE_NONE) {
140 interp->result = "no dialog mode was specified";
141 return TCL_ERROR;
142 } else if (rc) {
143 interp->result = "multiple modes were specified";
144 return TCL_ERROR;
145 }
146
147 if (!(text = poptGetArg(optCon))) {
148 interp->result = "missing text parameter";
149 return TCL_ERROR;
150 }
151
152 if (!(nextArg = poptGetArg(optCon))) {
153 interp->result = "height missing";
154 return TCL_ERROR;
155 }
156 height = strtoul(nextArg, &end, 10);
157 if (*end) {
158 interp->result = "height is not a number";
159 return TCL_ERROR;
160 }
161
162 if (!(nextArg = poptGetArg(optCon))) {
163 interp->result = "width missing";
164 return TCL_ERROR;
165 }
166 width = strtoul(nextArg, &end, 10);
167 if (*end) {
168 interp->result = "width is not a number";
169 return TCL_ERROR;
170 }
171
172 width -= 2;
173 height -= 2;
174 newtOpenWindow((80 - width) / 2, (24 - height) / 2, width, height, title);
175
176 if (noCancel) flags |= FLAG_NOCANCEL;
177 if (noItem) flags |= FLAG_NOITEM;
178 if (scrollText) flags |= FLAG_SCROLL_TEXT;
179 if (defaultNo) flags |= FLAG_DEFAULT_NO;
180
181 switch (mode) {
182 case MODE_MSGBOX:
183 rc = messageBox(text, height, width, MSGBOX_MSG, flags);
184 break;
185
186 case MODE_YESNO:
187 rc = messageBox(text, height, width, MSGBOX_YESNO, flags);
188 if (rc == DLG_OKAY)
189 interp->result = "yes";
190 else
191 interp->result = "no";
192 if (rc == DLG_ERROR) rc = 0;
193 break;
194
195 case MODE_INPUTBOX:
196 rc = inputBox(text, height, width, optCon, flags, &result);
197 if (!rc) {
198 interp->result = strdup(result);
199 interp->freeProc = TCL_DYNAMIC;
200 }
201 break;
202
203 case MODE_MENU:
204 rc = listBox(text, height, width, optCon, flags, &result);
205 if (!rc) {
206 interp->result = strdup(result);
207 interp->freeProc = TCL_DYNAMIC;
208 }
209 break;
210
211 case MODE_RADIOLIST:
212 rc = checkList(text, height, width, optCon, 1, flags, &selections);
213 if (!rc) {
214 interp->result = strdup(selections[0]);
215 interp->freeProc = TCL_DYNAMIC;
216 }
217 break;
218
219 case MODE_CHECKLIST:
220 rc = checkList(text, height, width, optCon, 0, flags, &selections);
221
222 if (!rc) {
223 for (next = selections; *next; next++)
224 Tcl_AppendElement(interp, *next);
225
226 free(selections);
227 }
228 break;
229
230 case MODE_NONE:
231 /* this can't happen */
232 }
233
234 newtPopWindow();
235
236 if (rc == DLG_ERROR) {
237 interp->result = "bad paramter for whiptcl dialog box";
238 return TCL_ERROR;
239 }
240
241 Tcl_SetVar(interp, "whiptcl_canceled", (rc == DLG_CANCEL) ? "1" : "0",
242 0);
243
244 return TCL_OK;
245 }
246
247 static char * setBacktext(ClientData data, Tcl_Interp * interp,
248 char * name1, char * name2, int flags) {
249 static char blankLine[81] = " "
250 " ";
251
252 newtDrawRootText(0, 0, blankLine);
253 newtDrawRootText(0, 0, Tcl_GetVar(interp, "whiptcl_backtext",
254 TCL_GLOBAL_ONLY));
255
256 return NULL;
257 }
258
259 static char * setHelptext(ClientData data, Tcl_Interp * interp,
260 char * name1, char * name2, int flags) {
261 char * text = Tcl_GetVar(interp, "whiptcl_helpline", TCL_GLOBAL_ONLY);
262
263 if (!text)
264 text = "";
265 else if (!strlen(text))
266 text = NULL;
267
268 newtPopHelpLine();
269 newtPushHelpLine(text);
270
271 return NULL;
272 }
273
274 static char * setFullButtons(ClientData data, Tcl_Interp * interp,
275 char * name1, char * name2, int flags) {
276 char * val = Tcl_GetVar(interp, "whiptcl_fullbuttons", TCL_GLOBAL_ONLY);
277 int rc;
278 int state;
279
280 if ((rc = Tcl_ExprBoolean(interp, val, &state))) {
281 Tcl_FreeResult(interp);
282 return "whiptcl_fullbuttons may only contain a boolean value";
283 }
284
285 useFullButtons(state);
286
287 return NULL;
288 }
289
290 int Whiptcl_Init(Tcl_Interp * interp) {
291 Tcl_CreateCommand(interp, "whiptcl_finish", wtFinish, NULL, NULL);
292 Tcl_CreateCommand(interp, "whiptcl_init", wtInit, NULL, NULL);
293 Tcl_CreateCommand(interp, "whiptcl_cmd", wtCmd, NULL, NULL);
294
295 return TCL_OK;
296 }