/* * werr * Just like the old one, only nicer. * * v. 1.00 (8 Aug 1993) * * © 1993-1998 Straylight */ /*----- Licensing note ----------------------------------------------------* * * This file is part of Straylight's Steel library. * * Steel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * Steel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Steel. If not, write to the Free Software Foundation, * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "werr.h" #include "dbox.h" #include "template.h" #include "nopoll.h" #include "bbc.h" #include "wimp.h" #include "wimpt.h" #include "win.h" #include "msgs.h" #include "kernel.h" #include "swiv.h" #include "swis.h" #include "exception.h" #include "calltrace.h" #include #include #include #include #define werr__TITLE 0 #define werr__OK 3 #define werr__CANCEL 6 #define werr__ERROR 4 #define werr__BACKTRACE 7 static dbox werr__errorBox; static BOOL werr__initialised; /* * void werr_bleepy(void) * * Use * Bleeps if and only if the appropriate WimpFlags bit is right for * bleeping. */ void werr_bleepy(void) { int bleepy=_kernel_osbyte(161,197,0); if (bleepy>0) { if ((bleepy&4096)==0) bbc_vdu(7); } } /* * void werr_init(void) * * Use * Sets up the werr system ready for action. */ void werr_init(void) { char *title=template_syshandle("error")->title.indirecttext.buffer; if (!win_anyWindows()) { werr(FALSE,msgs_lookup("werrSEM:Could not initialise.")); exit(0); } sprintf(title,"Error from %s",wimpt_programname()); werr__errorBox=dbox_create("error"); werr__initialised=TRUE; } /* * wimp_icon *werr__idef(wimp_wind *w,wimp_i i) * * Use * Vaguely similar to the dbox version, only different. Returns a pointer * to the icon, at any rate. * * Parameters * wimp_wind *w == the window definition. * wimp_i i == the icon number * * Returns * Pointer to the icon definition. */ static wimp_icon *werr__idef(wimp_wind *w,wimp_i i) { return ((wimp_icon *)(w+1)+i); } /* * int werr__wimpBox(char *string,int buttons) * * Use * Displays a WIMP error box to show the specified message * * Parameters * char *string == the error string to display * int buttons == the number of buttons to display */ static int werr__wimpBox(char *string,int buttons) { os_error err; static BOOL threaded; int f; /* --- If we crashed in here before, abort damned quick --- */ if (threaded) { _swi(Wimp_CommandWindow,_in(0),"Unrecoverable error"); fprintf(stderr, "%s has suffered a fatal error and must quit.", wimpt_programname()); abort(); } /* --- Display the error message --- */ threaded=TRUE; strcpy(err.errmess,string); err.errnum=1; /* Stop new WindowManglers thinking this is serious :-/ */ if (buttons==1) f=wimp_EOK; else f=wimp_EOK | wimp_ECANCEL; f=_swi(Wimp_ReportError,_inr(0,2)+_return(1),&err,f,wimpt_programname()); threaded=FALSE; return (f==2 ? 0 : 1); } /* * int werr__reportError(int buttons,char *error,va_list ap) * * Use * Error reporting primitive. Called by all both the old and new werr()s. * * Parameters * int buttons == how many buttons we need (1 or 2) * char *error == a printf() type format string for the error text * va_list ap == the variable arg list to use. * * Returns * 1 if OK clicked, 0 if Cancel clicked. */ static int werr__reportError(int buttons,char *error,va_list ap) { wimp_wind *wind; wimp_icon *ok; wimp_icon *cancel; wimp_icon *backtrace=(wimp_icon *)(-80); int cancelButt=-1; int backButt=-1; int clicked; char errString[256]; BOOL hasBacktrace; /* --- Set up the dialogue box --- */ vsprintf(errString,error,ap); if (werr__initialised==FALSE) return (werr__wimpBox(errString,buttons)); /* --- Find all the definitions we need --- */ werr__initialised=FALSE; /* Use the WIMP box if this fails */ wind=template_syshandle("error"); hasBacktrace=(wind->nicons>=werr__BACKTRACE); ok=werr__idef(wind,werr__OK); cancel=werr__idef(wind,werr__CANCEL); if (hasBacktrace) backtrace=werr__idef(wind,werr__BACKTRACE); dbox_delete(werr__errorBox); /* --- Zap any unwanted buttons --- */ if (buttons>=2) { cancel->flags&=~(1<<23); cancelButt=werr__CANCEL; } else cancel->flags|=(1<<23); if (hasBacktrace) { if (buttons>=3) { backtrace->flags&=~(1<<23); backButt=werr__BACKTRACE; } else backtrace->flags|=(1<<23); } /* --- Display the error box on the screen --- */ werr__errorBox=dbox_create("error"); if (!werr__errorBox) return (werr__wimpBox(errString,buttons)); if (!dbox_hasTitle(werr__errorBox)) dbox_setEmbeddedTitle(werr__errorBox,werr__TITLE,FALSE); dbox_setfield(werr__errorBox,werr__ERROR,"%s",errString); /* --- Display backtraces for as long we're asked to --- */ werr_bleepy(); do { clicked=nopoll_doDbox(werr__errorBox, nopoll_CENTRE, werr__OK, cancelButt, backButt); if (clicked==nopoll_OTHER) _calltrace(); } while (clicked==nopoll_OTHER); /* --- Return the result to the user --- */ werr__initialised=TRUE; /* Use fancy box for next error */ return (clicked==nopoll_OK); } /* * void werr(int fatal,char *error,...) * * Use * Compatibility with the old werr segment mainly. If the error is fatal, * a STEEL exception is generated, which eventually gets round to the * error box handlers and dumps back out to top level. * * Parameters * int fatal == 1 if the error is fatal, or 0 otherwise. * char *error == printf()-type format string. */ void werr(int fatal,char *error,...) { va_list ap; va_start(ap,error); if (fatal==0) { werr__reportError(1,error,ap); va_end(ap); } else { char buffer[256]; vsprintf(buffer,error,ap); va_end(ap); exception_generate("%s",buffer); } } /* * int werr_error(int buttons,char *error,...) * * Use * Reports an error. You can have two buttons, OK and Cancel if you really * want, now. * * Parameters * int buttons == 1 for 1 button, 2 for 2 buttons, or anything else for an * unpredictable result. * char *error == printf()-like format string. * * Returns * 1 for OK, 0 for cancel. */ int werr_error(int buttons,char *error,...) { va_list ap; int clicked; va_start(ap,error); clicked=werr__reportError(buttons,error,ap); va_end(ap); return (clicked); }