Initial revision
[ssr] / StraySrc / Libraries / Steel / c / werr
1 /*
2 * werr
3 * Just like the old one, only nicer.
4 *
5 * v. 1.00 (8 Aug 1993)
6 *
7 * © 1993-1998 Straylight
8 */
9
10 /*----- Licensing note ----------------------------------------------------*
11 *
12 * This file is part of Straylight's Steel library.
13 *
14 * Steel 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, or (at your option)
17 * any later version.
18 *
19 * Steel 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 Steel. If not, write to the Free Software Foundation,
26 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 */
28
29 #include "werr.h"
30 #include "dbox.h"
31 #include "template.h"
32 #include "nopoll.h"
33 #include "bbc.h"
34 #include "wimp.h"
35 #include "wimpt.h"
36 #include "win.h"
37 #include "msgs.h"
38 #include "kernel.h"
39 #include "swiv.h"
40 #include "swis.h"
41 #include "exception.h"
42 #include "calltrace.h"
43 #include <stdlib.h>
44 #include <stdarg.h>
45 #include <string.h>
46 #include <stdio.h>
47
48 #define werr__TITLE 0
49 #define werr__OK 3
50 #define werr__CANCEL 6
51 #define werr__ERROR 4
52 #define werr__BACKTRACE 7
53
54 static dbox werr__errorBox;
55 static BOOL werr__initialised;
56
57 /*
58 * void werr_bleepy(void)
59 *
60 * Use
61 * Bleeps if and only if the appropriate WimpFlags bit is right for
62 * bleeping.
63 */
64
65 void werr_bleepy(void)
66 {
67 int bleepy=_kernel_osbyte(161,197,0);
68 if (bleepy>0)
69 {
70 if ((bleepy&4096)==0)
71 bbc_vdu(7);
72 }
73 }
74
75 /*
76 * void werr_init(void)
77 *
78 * Use
79 * Sets up the werr system ready for action.
80 */
81
82 void werr_init(void)
83 {
84 char *title=template_syshandle("error")->title.indirecttext.buffer;
85 if (!win_anyWindows())
86 {
87 werr(FALSE,msgs_lookup("werrSEM:Could not initialise."));
88 exit(0);
89 }
90 sprintf(title,"Error from %s",wimpt_programname());
91 werr__errorBox=dbox_create("error");
92 werr__initialised=TRUE;
93 }
94
95 /*
96 * wimp_icon *werr__idef(wimp_wind *w,wimp_i i)
97 *
98 * Use
99 * Vaguely similar to the dbox version, only different. Returns a pointer
100 * to the icon, at any rate.
101 *
102 * Parameters
103 * wimp_wind *w == the window definition.
104 * wimp_i i == the icon number
105 *
106 * Returns
107 * Pointer to the icon definition.
108 */
109
110 static wimp_icon *werr__idef(wimp_wind *w,wimp_i i)
111 {
112 return ((wimp_icon *)(w+1)+i);
113 }
114
115 /*
116 * int werr__wimpBox(char *string,int buttons)
117 *
118 * Use
119 * Displays a WIMP error box to show the specified message
120 *
121 * Parameters
122 * char *string == the error string to display
123 * int buttons == the number of buttons to display
124 */
125
126 static int werr__wimpBox(char *string,int buttons)
127 {
128 os_error err;
129 static BOOL threaded;
130 int f;
131
132 /* --- If we crashed in here before, abort damned quick --- */
133
134 if (threaded)
135 {
136 _swi(Wimp_CommandWindow,_in(0),"Unrecoverable error");
137 fprintf(stderr,
138 "%s has suffered a fatal error and must quit.",
139 wimpt_programname());
140 abort();
141 }
142
143 /* --- Display the error message --- */
144
145 threaded=TRUE;
146 strcpy(err.errmess,string);
147 err.errnum=1; /* Stop new WindowManglers thinking this is serious :-/ */
148 if (buttons==1)
149 f=wimp_EOK;
150 else
151 f=wimp_EOK | wimp_ECANCEL;
152 f=_swi(Wimp_ReportError,_inr(0,2)+_return(1),&err,f,wimpt_programname());
153 threaded=FALSE;
154
155 return (f==2 ? 0 : 1);
156 }
157
158 /*
159 * int werr__reportError(int buttons,char *error,va_list ap)
160 *
161 * Use
162 * Error reporting primitive. Called by all both the old and new werr()s.
163 *
164 * Parameters
165 * int buttons == how many buttons we need (1 or 2)
166 * char *error == a printf() type format string for the error text
167 * va_list ap == the variable arg list to use.
168 *
169 * Returns
170 * 1 if OK clicked, 0 if Cancel clicked.
171 */
172
173 static int werr__reportError(int buttons,char *error,va_list ap)
174 {
175 wimp_wind *wind;
176 wimp_icon *ok;
177 wimp_icon *cancel;
178 wimp_icon *backtrace=(wimp_icon *)(-80);
179 int cancelButt=-1;
180 int backButt=-1;
181 int clicked;
182 char errString[256];
183 BOOL hasBacktrace;
184
185 /* --- Set up the dialogue box --- */
186
187 vsprintf(errString,error,ap);
188 if (werr__initialised==FALSE)
189 return (werr__wimpBox(errString,buttons));
190
191 /* --- Find all the definitions we need --- */
192
193 werr__initialised=FALSE; /* Use the WIMP box if this fails */
194 wind=template_syshandle("error");
195 hasBacktrace=(wind->nicons>=werr__BACKTRACE);
196 ok=werr__idef(wind,werr__OK);
197 cancel=werr__idef(wind,werr__CANCEL);
198 if (hasBacktrace)
199 backtrace=werr__idef(wind,werr__BACKTRACE);
200 dbox_delete(werr__errorBox);
201
202 /* --- Zap any unwanted buttons --- */
203
204 if (buttons>=2)
205 {
206 cancel->flags&=~(1<<23);
207 cancelButt=werr__CANCEL;
208 }
209 else
210 cancel->flags|=(1<<23);
211
212 if (hasBacktrace)
213 {
214 if (buttons>=3)
215 {
216 backtrace->flags&=~(1<<23);
217 backButt=werr__BACKTRACE;
218 }
219 else
220 backtrace->flags|=(1<<23);
221 }
222
223 /* --- Display the error box on the screen --- */
224
225 werr__errorBox=dbox_create("error");
226 if (!werr__errorBox)
227 return (werr__wimpBox(errString,buttons));
228 if (!dbox_hasTitle(werr__errorBox))
229 dbox_setEmbeddedTitle(werr__errorBox,werr__TITLE,FALSE);
230 dbox_setfield(werr__errorBox,werr__ERROR,"%s",errString);
231
232 /* --- Display backtraces for as long we're asked to --- */
233
234 werr_bleepy();
235 do
236 {
237 clicked=nopoll_doDbox(werr__errorBox,
238 nopoll_CENTRE,
239 werr__OK,
240 cancelButt,
241 backButt);
242 if (clicked==nopoll_OTHER)
243 _calltrace();
244 }
245 while (clicked==nopoll_OTHER);
246
247 /* --- Return the result to the user --- */
248
249 werr__initialised=TRUE; /* Use fancy box for next error */
250 return (clicked==nopoll_OK);
251 }
252
253 /*
254 * void werr(int fatal,char *error,...)
255 *
256 * Use
257 * Compatibility with the old werr segment mainly. If the error is fatal,
258 * a STEEL exception is generated, which eventually gets round to the
259 * error box handlers and dumps back out to top level.
260 *
261 * Parameters
262 * int fatal == 1 if the error is fatal, or 0 otherwise.
263 * char *error == printf()-type format string.
264 */
265
266 void werr(int fatal,char *error,...)
267 {
268 va_list ap;
269 va_start(ap,error);
270 if (fatal==0)
271 {
272 werr__reportError(1,error,ap);
273 va_end(ap);
274 }
275 else
276 {
277 char buffer[256];
278 vsprintf(buffer,error,ap);
279 va_end(ap);
280 exception_generate("%s",buffer);
281 }
282 }
283
284 /*
285 * int werr_error(int buttons,char *error,...)
286 *
287 * Use
288 * Reports an error. You can have two buttons, OK and Cancel if you really
289 * want, now.
290 *
291 * Parameters
292 * int buttons == 1 for 1 button, 2 for 2 buttons, or anything else for an
293 * unpredictable result.
294 * char *error == printf()-like format string.
295 *
296 * Returns
297 * 1 for OK, 0 for cancel.
298 */
299
300 int werr_error(int buttons,char *error,...)
301 {
302 va_list ap;
303 int clicked;
304 va_start(ap,error);
305 clicked=werr__reportError(buttons,error,ap);
306 va_end(ap);
307 return (clicked);
308 }