edce12a8adb362fa67f0820780bdf2f9e0c0b9ff
[xtoys] / xmsg.c
1 /* -*-c-*-
2 *
3 * $Id$
4 *
5 * Display a message to the user
6 *
7 * (c) 2001 Straylight/Edgeware
8 */
9
10 /*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of the Edgeware X tools collection.
13 *
14 * X tools is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * X tools is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with X tools; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 */
28
29 /*----- Header files ------------------------------------------------------*/
30
31 #include <ctype.h>
32 #include <errno.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37 #include <mLib/darray.h>
38 #include <mLib/dstr.h>
39 #include <mLib/mdwopt.h>
40 #include <mLib/quis.h>
41 #include <mLib/report.h>
42
43 #include <mgLib/msg.h>
44
45 /*----- Data structures ---------------------------------------------------*/
46
47 typedef struct button {
48 unsigned f;
49 const char *text;
50 } button;
51
52 #define f_cancel 1u
53 #define f_default 2u
54
55 DA_DECL(button_v, button);
56
57 /*----- Main code ---------------------------------------------------------*/
58
59 /* --- @version@ --- */
60
61 static void version(FILE *fp)
62 {
63 fprintf(fp, "%s (xtoys version " VERSION ")\n", QUIS);
64 }
65
66 /* --- @usage@ --- */
67
68 static void usage(FILE *fp)
69 {
70 fprintf(fp, "Usage: %s [-f] [-t TITLE] [-c|d BUTTON] MSG [BUTTON...]\n",
71 QUIS);
72 }
73
74 /* --- @findbutton@ --- */
75
76 static button *findbutton(button_v *bv, const char *tag)
77 {
78 size_t i, n = DA_LEN(bv);
79 button *b = DA(bv);
80 char *q;
81
82 if (!tag)
83 return (0);
84 for (i = 0; i < n; i++) {
85 if (strcmp(b[i].text, tag) == 0)
86 return (&b[i]);
87 }
88 while (*tag && isspace((unsigned char)*tag))
89 tag++;
90 i = strtoul(tag, &q, 0);
91 if (!*q && i < n)
92 return (&b[i]);
93 die(EXIT_FAILURE, "unknown button `%s'", tag);
94 return (0);
95 }
96
97
98 /* --- @main@ --- *
99 *
100 * Main program.
101 */
102
103 int main(int argc, char *argv[])
104 {
105 const char *title;
106 const char *message;
107 const char *b_cancel = 0, *b_default = 0;
108 button_v bv = DA_INIT;
109 button *b;
110 dstr d = DSTR_INIT;
111 dstr msgbuf = DSTR_INIT;
112 size_t n, i;
113 unsigned f = 0;
114
115 #define f_focus 256u
116
117 ego(argv[0]);
118 gtk_init(&argc, &argv);
119
120 /* --- Parse options --- */
121
122 title = QUIS;
123 for (;;) {
124 static struct option opt[] = {
125 { "help", 0, 0, 'h' },
126 { "usage", 0, 0, 'u' },
127 { "version", 0, 0, 'v' },
128 { "focus", 0, 0, 'f' },
129 { "title", OPTF_ARGREQ, 0, 't' },
130 { "cancel", OPTF_ARGREQ, 0, 'c' },
131 { "default", OPTF_ARGREQ, 0, 'd' },
132 { 0, 0, 0, 0 }
133 };
134 int i;
135
136 i = getopt_long(argc, argv, "huv t:c:d:q", opt, 0);
137
138 if (i < 0)
139 break;
140
141 switch (i) {
142 case 'h':
143 version(stdout);
144 fputs("\n", stdout);
145 usage(stdout);
146 fputs(
147 "\n"
148 "Pops up a message box containing a message and some buttons, reporting\n"
149 "which button was selected.\n"
150 "\n"
151 "Options available are:\n"
152 "\n"
153 "-h, --help Display this help text\n"
154 "-u, --usage Display a short usage summary\n"
155 "-v, --version Display the program's version number\n"
156 "\n"
157 "-f, --focus Give the window the focus (obsolete mdw thing)\n"
158 "-t, --title=TITLE Select the title string in the message box\n"
159 "-c, --cancel=BUTTON Select which button is to have the Cancel action\n"
160 "-d, --default=BUTTON Select which button is the default\n",
161 stdout);
162 exit(0);
163 break;
164 case 'u':
165 usage(stdout);
166 exit(0);
167 break;
168 case 'v':
169 version(stdout);
170 exit(0);
171 break;
172
173 case 'f':
174 f |= f_focus;
175 break;
176 case 't':
177 title = optarg;
178 break;
179 case 'c':
180 b_cancel = optarg;
181 break;
182 case 'd':
183 b_default = optarg;
184 break;
185
186 default:
187 usage(stderr);
188 exit(EXIT_FAILURE);
189 }
190 }
191
192 if (optind >= argc) {
193 usage(stderr);
194 exit(EXIT_FAILURE);
195 }
196 message = argv[optind++];
197 if (*message == '%')
198 message++;
199 else if (strcmp(message, "-") == 0) {
200 for (;;) {
201 size_t n;
202
203 dstr_ensure(&msgbuf, 4096);
204 n = fread(msgbuf.buf + msgbuf.len, 1,
205 msgbuf.sz - msgbuf.len, stdin);
206 if (!n)
207 break;
208 msgbuf.len += n;
209 }
210 if (msgbuf.len && msgbuf.buf[msgbuf.len - 1])
211 msgbuf.len--;
212 dstr_putz(&msgbuf);
213 message = msgbuf.buf;
214 }
215
216 if (optind >= argc) {
217 DA_ENSURE(&bv, 1);
218 b = &DA(&bv)[0];
219 b->f = 0;
220 b->text = "OK";
221 DA_UNSAFE_EXTEND(&bv, 1);
222 } else for (; optind < argc; optind++) {
223 DA_ENSURE(&bv, 1);
224 b = &DA(&bv)[DA_LEN(&bv)];
225 b->f = 0;
226 b->text = argv[optind];
227 DA_UNSAFE_EXTEND(&bv, 1);
228 }
229
230 if ((b = findbutton(&bv, b_cancel)) != 0)
231 b->f |= f_cancel;
232 else
233 DA(&bv)[DA_LEN(&bv) - 1].f |= f_cancel;
234
235 if ((b = findbutton(&bv, b_default)) != 0)
236 b->f |= f_default;
237 else
238 DA(&bv)[0].f |= f_default;
239
240 b = DA(&bv);
241 n = DA_LEN(&bv);
242 if (f & f_focus)
243 DPUTC(&d, '!');
244 for (i = 0; i < n; i++) {
245 if (b[i].f & f_default)
246 DPUTC(&d, ':');
247 if (b[i].f & f_cancel)
248 DPUTC(&d, '~');
249 DPUTS(&d, b[i].text);
250 DPUTC(&d, ',');
251 }
252 d.buf[--d.len] = 0;
253
254 i = msg(title, d.buf, "%s", message);
255 if (n > 1)
256 puts(b[i].text);
257 return (0);
258 }
259
260 /*----- That's all, folks -------------------------------------------------*/