chiark / gitweb /
debian: Fix maintainer email address.
[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 -------------------------------------------------*/