/* * wimpt.c * * Low level Wimp interface * * © 1994-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. */ /*----- Header files ------------------------------------------------------*/ #include #include #include #include #include #include "dll.h" #include "swis.h" #include "kernel.h" #include "os.h" #include "bbc.h" #include "wimp.h" #include "font.h" #include "wimpt.h" #include "wimpt.h" #include "werr.h" #include "alarm.h" #include "event.h" #include "flex.h" #include "msgs.h" #include "interface.h" #include "exception.h" #include "mem.h" #include "visdelay.h" #include "caretptr.h" #include "sculptrix.h" #include "resspr.h" /*----- Veneered internal functions ---------------------------------------*/ #ifndef _dll_NODLL extern void _dllEntry(wimpt__signals)(int sig); extern void _dllEntry(wimpt__escapeHandler)(int sig); extern void _dllEntry(wimpt__exit)(void); #endif /*----- Static data -------------------------------------------------------*/ /* --- Event handling --- */ static BOOL wimpt__fakeWaiting; static wimp_eventstr wimpt__fakeEvent; static wimp_eventstr wimpt__lastEvent; /* --- Wimp task management --- */ static wimp_t wimpt__task; static char *wimpt__name=""; static int wimpt__wimpVersion; static int *wimpt__messages; static BOOL wimpt__justChangedMode; static int wimpt__pollingTime=100/50; static int wimpt__options=wimpt_OSCULPTRIX; /* --- Mode information --- */ static int wimpt__currentMode; static int wimpt__dx; static int wimpt__dy; static int wimpt__bpp; static int wimpt__xwind; static int wimpt__ywind; /*----- Internal functions ------------------------------------------------*/ /* --- Signal handling --- */ _dll_static void wimpt__escapeHandler(int sig) { sig=sig; signal(SIGINT,_dllEntry(wimpt__escapeHandler)); } _dll_static void wimpt__signals(int sig) { static char *errors[]= { "?", "SIGABRT", "SIGFPE", "SIGILL", "SIGINT", "SIGSEGV", "SIGTERM", "SIGSTAK", "SIGUSR1", "SIGUSR2", "SIGOSERROR" }; signal(sig,_dllEntry(wimpt__signals)); exception_generate(msgs_lookup("wimptSIGC:%s - code=%s"), _kernel_last_oserror()->errmess, sig>0 && sig<8 ? errors[sig] : "SIGUKN"); } /* --- Exit handler --- */ _dll_static void wimpt__exit(void) { if (wimpt__options & wimpt_OINTERFACE) interface_closeDown(wimpt__task); if (wimpt__options & wimpt_OWIMPEXT) os_swiv(XWimpExt_CloseDown,wimpt__task); wimp_taskclose(wimpt__task); } /*----- Screen mode information -------------------------------------------*/ BOOL wimpt_checkmode(void) { int dummy; int old=wimpt__currentMode; os_byte(135,&dummy,&wimpt__currentMode); wimpt__dx=1<data.o.w; wimpt_noerr(wimp_redraw_wind(&r,&more)); while (more) { if (p) p(&r,handle); if (wimpt__options & wimpt_OSCULPTRIX) { wimpt_noerr(sculptrix_setSpriteArea(resspr_area())); wimpt_noerr(sculptrix_redrawWindow(&r)); } if (wimpt__options & wimpt_OINTERFACE) wimpt_noerr(interface_render3dWindow(&r)); if (wimpt__options & wimpt_OWIMPEXT) wimpt_noerr(os_swiv(XWimpExt_Redraw,0,&r)); wimpt_noerr(wimp_get_rectangle(&r,&more)); } } /*----- Initialisation ----------------------------------------------------*/ void wimpt_setOptions(int eor,int bic) { wimpt__options=(wimpt__options & ~bic) ^ eor; } int wimpt_options(void) { return (wimpt__options); } void wimpt_setMessages(int msg,...) { int i=0; int sz=0; va_list ap; if (!msg) return; if (wimpt__messages=mem_alloc(256*sizeof(int)),!wimpt__messages) { fprintf(stderr, msgs_lookup("wimptNEMI:Not enough memory to initialise.")); exit(1); } sz=256; wimpt__messages[i++]=msg; va_start(ap,msg); while (msg) { msg=va_arg(ap,int); if (i==sz) { sz+=64; if (wimpt__messages=mem_reAlloc(wimpt__messages,sz*sizeof(int)), !wimpt__messages) { fprintf(stderr, msgs_lookup("wimptNEMI:Not enough memory to initialise.")); exit(1); } } wimpt__messages[i++]=msg; } va_end(ap); if (wimpt__wimpVersion<300) wimpt__wimpVersion=300; } void wimpt_wimpversion(int version) { wimpt__wimpVersion=version; } int wimpt_getVersion(void) { return (wimpt__wimpVersion); } void wimpt_init(char *progname) { os_error *e; signal(SIGABRT, _dllEntry(wimpt__signals)); signal(SIGFPE, _dllEntry(wimpt__signals)); signal(SIGILL, _dllEntry(wimpt__signals)); signal(SIGINT, _dllEntry(wimpt__escapeHandler)); signal(SIGSEGV, _dllEntry(wimpt__signals)); signal(SIGTERM, _dllEntry(wimpt__signals)); signal(SIGOSERROR, _dllEntry(wimpt__signals)); wimpt__name=progname; if (!wimpt__wimpVersion) { /* --- Guess the current WIMP version --- */ switch (bbc_inkey(0xFF00)) { case 0xA0: /* Arthur */ fprintf(stderr, msgs_lookup("wimptARTH:Operating system too old. Try " "upgrading to RISC OS!\n")); exit(1); break; case 0xA1: /* OS 2.00 */ case 0xA2: /* OS 2.01 */ wimpt__wimpVersion=200; break; case 0xA3: /* OS 3.00 */ wimpt__wimpVersion=300; break; case 0xA4: /* OS 3.10 */ default: /* Anything later */ wimpt__wimpVersion=310; break; } } if (wimpt__wimpVersion==300 && !wimpt__messages) { /* Set up some sensible default messages for brain-damaged OS */ wimpt_setMessages(1,2,3,4,5,6,7,8,9,10, 0x502,0x503, 0x400c0,0x400c1,0x400c9, 0x80140,0x80145,0x80147, 0); } if (e=wimp_taskinit(progname, &wimpt__wimpVersion, &wimpt__task, wimpt__messages ? wimpt__messages : (int *)-1), e) { fprintf(stderr, msgs_lookup("wimptFTI:Failed to initialise: '%s'"), e->errmess); fprintf(stderr,"\n"); exit(1); } wimpt_checkmode(); atexit(_dllEntry(wimpt__exit)); /* --- Initialise any extensions --- */ if (wimpt__options & wimpt_OINTERFACE) wimpt_noerr(interface_initialise(wimpt__task)); /* --- Handle WimpExtension with care... --- * * * If WimpExtension isn't initialised yet, it will start up its Wimp task, * corrupting the application handle in the process, causing a bad crash * when we return through app__epilogue. */ if (wimpt__options & wimpt_OWIMPEXT) { #ifndef _dll_NODLL int handle; os_error *err; dll_saveHandle(&handle); err=os_swiv(XWimpExt_Initialise,16,wimpt__task,0); dll_restoreHandle(&handle); wimpt_noerr(err); #else wimpt_noerr(os_swiv(XWimpExt_Initialise,16,wimpt__task,0)); #endif } } char *wimpt_programname(void) { return (wimpt__name); } wimp_t wimpt_task(void) { return (wimpt__task); } /*----- Error handling ----------------------------------------------------*/ os_error *wimpt_complain(os_error *e) { if (e) werr_error(1,"%s",e->errmess); return (e); } void wimpt_noerr(os_error *e) { if (e) exception_generate("%s",e->errmess); } void wimpt_reporterror(os_error *e, wimp_errflags f) { werr_error((f & 3==3) ? 2 : 1,"%s",e->errmess); } /*----- Polling the WIMP --------------------------------------------------*/ os_error *wimpt_poll(wimp_emask mask,wimp_eventstr *result) { visdelay_state vs; os_error *e=0; int nextAlarm; BOOL alarming; int timeNow; if (wimpt__fakeWaiting /* && !(mask & (1<data, result->e, (int *)&result->e,0,0)); } if (wimpt__options & wimpt_OINTERFACE) interface_poll(result,wimpt__task); wimpt__lastEvent=*result; switch (result->e) { case wimp_ESEND: case wimp_ESENDWANTACK: if (result->data.msg.hdr.action==0x400C1) { wimpt__justChangedMode=TRUE; wimpt_checkmode(); } else wimpt__justChangedMode=FALSE; break; case wimp_EOPEN: /* Could be part of the mode change */ break; case wimp_EPTRLEAVE: caretPtr__pointer(FALSE); wimpt__justChangedMode=FALSE; break; case wimp_EPTRENTER: caretPtr__pointer(TRUE); wimpt__justChangedMode=FALSE; break; default: wimpt__justChangedMode=FALSE; break; } return(e); } BOOL wimpt_justChangedMode(void) { return (wimpt__justChangedMode); } int wimpt_pollingTime(int new) { int temp=wimpt__pollingTime; if (new>=0) wimpt__pollingTime=new; return (temp); } void wimpt_fake_event(wimp_eventstr * e) { if (!wimpt__fakeWaiting) { wimpt__fakeWaiting=TRUE; wimpt__fakeEvent=*e; } } wimp_eventstr *wimpt_last_event(void) { return (&wimpt__lastEvent); } int wimpt_last_event_was_a_key(void) { return (wimpt__lastEvent.e == wimp_EKEY); } /*----- String width ------------------------------------------------------*/ /* * int wimpt_stringWidth(char *s) * * Use * Determines the width of a string in OS units, taking into account the * fact that it may be represented in a WIMP anti-aliased font. * * Parameters * char *s == pointer to the string to font the length of * * Returns * The width of the string in OS units */ int wimpt_stringWidth(char *s) { font f; font_string fs; if (wimp_readsysinfo(wimp_IFONTHANDLE,&f) || !f) return (strlen(s)*16); font_setfont(f); fs.s=s; font_converttopoints(1000,1000,&fs.x,&fs.y); fs.split=0; fs.term=strlen(s)+1; font_strwidth(&fs); font_converttoos(fs.x,0,&fs.x,&fs.y); return (fs.x); }