home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ARM Club 3
/
TheARMClub_PDCD3.iso
/
hensa
/
drivers
/
a066_1
/
!VMode
/
c
/
vmode
Wrap
Text File
|
1992-03-03
|
25KB
|
1,172 lines
/* #define DEBUG */
/* $Id: c.vmode 1.5 92/03/04 16:34:11 bdb Exp $
*
* $Log: c.vmode $
* Revision 1.5 92/03/04 16:34:11 bdb
* Better start up
*
* Revision 1.4 92/03/02 17:24:51 bdb
* Trap and use palette changes.
* Added magnifier - fixed cursor vs this
* Title changing
* Fixed rogue cursor bug
* Only pass on f12 and send other keys to task.
* And mode number with 127
* Trapped VDU 21
* Prevented status lag update on menu allowing multiple resumes
*
* Revision 1.3 92/02/25 11:45:32 bdb
* Changed newtasks behaviour to only trap on -ctrl ones,
* and no longer use weird patch. This supports a newtask
* command to replace taskwindow.
*
* Revision 1.2 92/02/20 11:03:22 bdb
* Added cursor, passing on keys
* dbox_query replaces error box.
*
* Revision 1.1 92/02/19 16:28:10 bdb
* Initial revision
*
*/
#define REVISION "$Revision: 1.5 $"
#define VERSION ( REVISION " " __DATE__ " " __TIME__ + 11 )
#include "wimp.h"
#include "wimpt.h"
#include "win.h"
#include "event.h"
#include "res.h"
#include "resspr.h"
#include "menu.h"
#include "template.h"
#include "dbox.h"
#include "dboxquery.h"
#include "alarm.h"
#include "baricon.h"
#include "xfersend.h"
#include "saveas.h"
#include "werr.h"
#include "magnify.h"
#include "flex.h"
#include "visdelay.h"
#include "akbd.h"
#include "pointer.h"
#include "bbc.h"
#include "colourtran.h"
#include "kernel.h"
#include "swis.h"
#include "swiv.h"
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <signal.h>
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))
enum themenu { MNULL, MKILL, MRECONNECT, MSUSPEND, MRESUME, MZOOM, MSAVE };
#define themenuinit "Kill,Reconnect,Suspend,Resume,>Zoom,>Save"
enum state { TDEAD, TSUSPENDED, TRUNNING };
/* Container for info about a window */
typedef struct win
{ wimp_w w; /* window handle */
struct win *next;
sprite_area *area;
int osx,osy;
int winx,winy;
int *save_area;
char *pixtrans;
wimp_t task;
int mode;
int l2bpp;
int xeig,yeig;
int changed;
enum state state;
int charx,chary;
int curx,cury;
char xvduq[10];
int xvduqwant;
int xvduqpos;
int magm,magd;
int tlen;
char title[256]; /* displayed title of window - indirecttext pts here */
} win;
static os_error NoMem = { 0, "Out of Memory" };
static win *thewins = NULL;
static int newtasks = 1; /* Catch new taskwindows */
static menu themenu;
static menu barmenu=NULL;
static wimp_i theicon;
static int wimpversion;
/* Saved win during drag or save/open message bounce */
static win *savewin = NULL;
/* Prototypes */
#include "VMode.h"
int main
( int argc, char *argv[] )
{
int i;
init(argc,argv);
for (;;)
{ event_process();
}
return 0;
}
void init
( int argc, char *argv[] )
{
wimp_msgstr m;
int i;
wimpversion = wimpt_init("VMode");
#ifdef DEBUG
signal(SIGABRT, SIG_DFL);
signal(SIGFPE, SIG_DFL);
signal(SIGILL, SIG_DFL);
signal(SIGSEGV, SIG_DFL);
signal(SIGTERM, SIG_DFL);
#endif
res_init("VMode");
resspr_init();
template_init();
dbox_init();
alarm_init();
visdelay_init();
flex_init();
win_add_unknown_event_processor( unknownevent, NULL );
theicon = baricon( "!VMode", 1, barclick );
event_attachmenumaker( win_ICONBAR, barmenumaker, barmenuproc, NULL );
themenu = menu_new( "VMode", themenuinit );
newtasks = atoi(getenv("VMode$NewTasks"));
if (argc>1)
{ m.data.chars[0]=0;
for (i=1;i<argc;i++)
{ strcat(m.data.chars,argv[i]);
strcat(m.data.chars," ");
}
m.hdr.action = 0x808c5; /* TaskWindow_NewTask */
m.hdr.your_ref = 0;
m.hdr.size = sizeof(m.hdr)+( ( strlen( m.data.chars ) + 4 ) & -4 );
wimpt_noerr(wimp_sendmessage(wimp_ESENDWANTACK, &m, NULL));
}
}
sprite_id *SprPtr
(sprite_header *s)
{
static sprite_id id;
id.tag = sprite_id_addr;
id.s.addr = s;
return &id;
}
sprite_id *SprNam
(char *s)
{
static sprite_id id;
id.tag = sprite_id_name;
id.s.name = s;
return &id;
}
menu menumaker
( void *h )
{ win *w = h;
menu_setflags( themenu, MKILL, 0, (w->state==TDEAD) );
menu_setflags( themenu, MRECONNECT, 0, (w->state!=TDEAD) );
menu_setflags( themenu, MSUSPEND, 0, (w->state!=TRUNNING) );
menu_setflags( themenu, MRESUME, 0, (w->state!=TSUSPENDED) );
return themenu;
}
void menuproc
( void *h, char *hit )
{ wimp_mousestr m;
wimp_msgstr msg;
win *w = h;
wimpt_noerr( wimp_get_point_info( &m ) );
switch ( hit[0] )
{ case MKILL:
msg.hdr.action = 0x808c4; /* TaskWindow_Morite */
w->state = TDEAD;
newtitleflag(w," Terminating");
goto sendit;
case MRECONNECT:
if (w->state==TDEAD)
startit(w);
break;
case MSUSPEND:
if (w->state==TDEAD)
break;
msg.hdr.action = 0x808c6; /* TaskWindow_Suspend */
w->state = TSUSPENDED;
newtitleflag(w," Suspended");
goto sendit;
case MRESUME:
if (w->state==TDEAD)
break;
msg.hdr.action = 0x808c7; /* TaskWindow_Resume */
w->state = TRUNNING;
newtitleflag(w," Running");
sendit:
msg.hdr.your_ref = 0;
msg.hdr.size = 20;
wimpt_noerr( wimp_sendmessage( wimp_ESEND, &msg, w->task ) );
break;
case MZOOM:
magnify_select(&w->magm,&w->magd,999,999,&magchange,w);
break;
case MSAVE:
saveas( 0xff9, "screendump", 1, saveproc, 0, 0, w );
break;
}
}
void magchange
( void *h )
{ win *w = h;
newwinsize(w);
}
BOOL saveproc
( char *filename, void *h )
{ win *w = h;
wimp_paletteword *p = paladdr(w);
BOOL b;
int i,n;
n = 1<<(1<<w->l2bpp);
if (3 != w->l2bpp)
for (i = n; --i >= 0; )
p[2*i+1] = p[2*i] = p[i];
b = !wimpt_complain(sprite_area_save(w->area,filename));
if (3 != w->l2bpp)
for (i = 0; i < n; i++)
p[i] = p[2*i];
if ( b && xfersend_file_is_safe() )
h = NULL; /* maybe fiddle title */
return b;
}
void winevent
( wimp_eventstr *e, void *h )
{ BOOL more;
win *w = h;
wimp_redrawstr r;
switch ( e->e )
{ case wimp_EREDRAW:
if (wimpt_checkmode())
coltable(w);
r.w = e->data.o.w;
wimpt_noerr(wimp_redraw_wind(&r,&more));
while (more)
{ wimp_box cur;
sprite_factors scale;
scale.xmag=w->magm<<w->xeig;
scale.ymag=w->magm<<w->yeig;
scale.xdiv=w->magd*wimpt_dx();
scale.ydiv=w->magd*wimpt_dy();
wimpt_noerr(sprite_put_scaled( w->area, SprNam("screen"), 0,
r.box.x0-r.scx, r.box.y1-r.scy-w->winy, &scale, w->pixtrans));
bbc_gcol(4,0);
cur.x0 = w->curx*w->charx*w->magm/w->magd;
cur.y1 = -w->cury*w->chary*w->magm/w->magd;
cur.x1 = (w->curx+1)*w->charx*w->magm/w->magd;
cur.y0 = -(w->cury+1)*w->chary*w->magm/w->magd;
bbc_rectanglefill(cur.x0+r.box.x0-r.scx,cur.y0+r.box.y1-r.scy,cur.x1-cur.x0-wimpt_dx(),cur.y1-cur.y0-wimpt_dy());
wimpt_noerr(wimp_get_rectangle(&r,&more));
}
break;
case wimp_EOPEN:
wimp_open_wind( &e->data.o );
break;
case wimp_ECLOSE:
if (w->state==TDEAD || confirm("Task active. Kill and close?"))
freewin( w );
break;
case wimp_EBUT:
{
switch ( e->data.but.m.bbits )
{ case wimp_BCLICKLEFT:
case wimp_BCLICKRIGHT:
case wimp_BDRAGLEFT:
case wimp_BDRAGRIGHT:
case wimp_BRIGHT:
case wimp_BLEFT:
grabcaret(w);
break;
}
break;
}
case wimp_EKEY:
{ int code = e->data.key.chcode;
if ((code&~0x30)==0x1CC) /* pass f12 through */
wimp_processkey(code);
else
{ e->data.msg.hdr.action = 0x808c0; /* TaskWindow_Input */
e->data.msg.hdr.your_ref = 0;
e->data.msg.hdr.size = 28;
e->data.msg.data.words[0]=1;
e->data.msg.data.words[1]=code;
wimpt_noerr( wimp_sendmessage( wimp_ESEND, &e->data.msg, w->task ) );
} }
break;
case wimp_ESEND: case wimp_ESENDWANTACK:
switch ( e->data.msg.hdr.action )
{ case wimp_MCLOSEDOWN:
while (thewins)
freewin(thewins);
exit(0);
break;
}
break;
}
}
BOOL oktoquit
( void )
{
win *w;
for ( w=thewins; w ; w=w->next)
if (w->state!=TDEAD)
break;
if ( w )
if ( confirm( "There are still tasks running under !VMode. Really quit?" ) )
w=NULL;
return w==NULL;
}
BOOL unknownevent
( wimp_eventstr *e, void *h )
{ win *w=h;
sprite_state s, s2;
wimp_redrawstr r;
int *box;
int s1;
switch ( e->e )
{ case wimp_ENULL:
s1 = 0;
for (w = thewins; w; w = w->next)
{ if (w->changed)
{ int cx,cy;
wimpt_noerr(sprite_outputtosprite(w->area, SprNam("screen"), w->save_area, s1?&s2:&s));
s1 = 1;
swix(OS_ChangedBox,IN(R0)|OUT(R1),-1,&box);
r.w = w->w;
r.box.x0 = (box[1]<<w->xeig)*w->magm/w->magd;
r.box.y0 = (box[2]<<w->yeig)*w->magm/w->magd-w->winy;
r.box.x1 = (box[3]+1<<w->xeig)*w->magm/w->magd;
r.box.y1 = (box[4]+1<<w->yeig)*w->magm/w->magd-w->winy;
swix(OS_ChangedBox,IN(R0),2);
if (r.box.x1>r.box.x0 && r.box.y1>r.box.y0)
wimpt_noerr(wimp_force_redraw(&r));
cx = bbc_pos();
cy = bbc_vpos();
if ( cx!=w->curx || cy!=w->cury )
{ r.w = w->w;
r.box.x0 = w->curx*w->charx*w->magm/w->magd;
r.box.y1 = -w->cury*w->chary*w->magm/w->magd;
r.box.x1 = (w->curx+1)*w->charx*w->magm/w->magd;
r.box.y0 = -(w->cury+1)*w->chary*w->magm/w->magd;
wimpt_noerr(wimp_force_redraw(&r));
w->curx = cx;
w->cury = cy;
r.w = w->w;
r.box.x0 = w->curx*w->charx*w->magm/w->magd;
r.box.y1 = -w->cury*w->chary*w->magm/w->magd;
r.box.x1 = (w->curx+1)*w->charx*w->magm/w->magd;
r.box.y0 = -(w->cury+1)*w->chary*w->magm/w->magd;
wimpt_noerr(wimp_force_redraw(&r));
}
w->changed = 0;
} }
if (s1)
wimpt_noerr(sprite_restorestate(s));
break;
case wimp_ESEND: case wimp_ESENDWANTACK:
w = savewin;
switch ( e->data.msg.hdr.action )
{ case wimp_MPREQUIT:
if ( !oktoquit() )
{ ack( &e->data.msg );
return TRUE;
}
break;
case wimp_SAVEDESK:
{ int fh = e->data.msg.data.savedesk.filehandle;
rofprintf( fh, "Run %s\n", getenv("VMode$Dir") );
}
break;
case 0x808c5: /* TaskWindow_NewTask */
if (e->data.msg.hdr.your_ref)
{ if (!thewins)
exit(0);
else
break;
}
if (newtasks && strstr(&e->data.msg.data.chars[0],"-ctrl"))
{
ack(&e->data.msg);
/* the weird flag is now set to 0, since the above message cannot have really
* come from taskwindow as its too broken to pass -ctrl through, and so we
* don't have to worry about its other bugs
*/
launchone(&e->data.msg.data.chars[0]);
}
break;
case 0x808c3: /* TaskWindow_Morio */
for (w = thewins; w; w = w->next )
if (w->task==e->data.msg.hdr.task)
{ w->state = TDEAD;
newtitleflag(w, " Finished");
}
break;
case 0x808c2: /* TaskWindow_Ego */
w = (win *)e->data.msg.data.words[0];
w->task = e->data.msg.hdr.task;
w->state = TRUNNING;
newtitleflag(w, " Running");
break;
case 0x808c1: /* TaskWindow_Output */
for ( w=thewins ; w ; w=w->next )
if (w->task==e->data.msg.hdr.task)
break;
if (w)
scribble( w, (char *)&e->data.msg.data.words[1], e->data.msg.data.words[0] );
break;
}
break;
case wimp_EACK:
break;
}
return FALSE;
}
void barclick
( wimp_i i )
{ i = i;
launchone("taskwindow -ctrl");
}
void launchone
( char *cmd )
{ wimp_wind *t;
wimp_wstate s;
win *w=claim(sizeof(win));
w->next = thewins;
thewins = w;
t = template_syshandle( "window" );
strcpy(w->title,cmd);
w->tlen = strlen(w->title);
t->title.indirecttext.buffer = w->title;
t->title.indirecttext.bufflen = 256;
wimpt_noerr( wimp_create_wind( t, &w->w ) );
win_register_event_handler( w->w, winevent, (void *)w );
event_attachmenumaker( w->w, menumaker, menuproc, (void *)w );
w->area = NULL;
w->pixtrans = NULL;
w->save_area = NULL;
w->magm = w->magd = 1;
if (!modeclear(w,0))
{
wimpt_noerr( wimp_get_wind_state( w->w, &s ) );
wimpt_noerr( wimp_open_wind( &s.o ) );
event_setmask( 0 );
startit(w);
grabcaret(w);
}
else
freewin(w);
}
void startit
( win *w )
{ char buf[256];
/* NB taskwindow seems only to recognise a reply to a request for a server if
* hex no.s with no &'s or flag names are used... odd!
*/
/* if (weird)
sprintf( buf,"%s %08x %08x ", w->title, wimpt_task(), (int)w );
else */
w->title[w->tlen] = 0;
sprintf( buf,"%s -task &%08x -txt &%08x ", w->title, wimpt_task(), (int)w );
wimp_starttask(buf);
w->state = TDEAD;
strcpy(w->title+w->tlen," Starting");
}
void grabcaret
( win *w )
{ wimp_caretstr c;
c.w = w->w;
c.i = -1;
c.x = 100;
c.y = -100;
c.height = 0|(1<<25); /* invisible */
c.index = 0;
wimpt_noerr(wimp_set_caret_pos(&c));
}
static int pal2[2]=
{
0x0,
0xF0F0F007,
};
static int pal4[4]=
{
0x0,
0xF001,
0xF0F003,
0xF0F0F007,
};
static int pal16[16]=
{
0x0,
0xF001,
0xF00002,
0xF0F003,
0xF0000004,
0xF000F005,
0xF0F00006,
0xF0F0F007,
0x8,
0xF009,
0xF0000A,
0xF0F00B,
0xF000000C,
0xF000F00D,
0xF0F0000E,
0xF0F0F00F,
};
static int pal256[256]=
{
0x10,
0x10101010,
0x20202010,
0x30303010,
0x4010,
0x10105010,
0x20206010,
0x30307010,
0x40000010,
0x50101010,
0x60202010,
0x70303010,
0x40004010,
0x50105010,
0x60206010,
0x70307010,
0x8010,
0x10109010,
0x2020A010,
0x3030B010,
0xC010,
0x1010D010,
0x2020E010,
0x3030F010,
0x40008010,
0x50109010,
0x6020A010,
0x7030B010,
0x4000C010,
0x5010D010,
0x6020E010,
0x7030F010,
0x400010,
0x10501010,
0x20602010,
0x30703010,
0x404010,
0x10505010,
0x20606010,
0x30707010,
0x40400010,
0x50501010,
0x60602010,
0x70703010,
0x40404010,
0x50505010,
0x60606010,
0x70707010,
0x408010,
0x10509010,
0x2060A010,
0x3070B010,
0x40C010,
0x1050D010,
0x2060E010,
0x3070F010,
0x40408010,
0x50509010,
0x6060A010,
0x7070B010,
0x4040C010,
0x5050D010,
0x6060E010,
0x7070F010,
0x800010,
0x10901010,
0x20A02010,
0x30B03010,
0x804010,
0x10905010,
0x20A06010,
0x30B07010,
0x40800010,
0x50901010,
0x60A02010,
0x70B03010,
0x40804010,
0x50905010,
0x60A06010,
0x70B07010,
0x808010,
0x10909010,
0x20A0A010,
0x30B0B010,
0x80C010,
0x1090D010,
0x20A0E010,
0x30B0F010,
0x40808010,
0x50909010,
0x60A0A010,
0x70B0B010,
0x4080C010,
0x5090D010,
0x60A0E010,
0x70B0F010,
0xC00010,
0x10D01010,
0x20E02010,
0x30F03010,
0xC04010,
0x10D05010,
0x20E06010,
0x30F07010,
0x40C00010,
0x50D01010,
0x60E02010,
0x70F03010,
0x40C04010,
0x50D05010,
0x60E06010,
0x70F07010,
0xC08010,
0x10D09010,
0x20E0A010,
0x30F0B010,
0xC0C010,
0x10D0D010,
0x20E0E010,
0x30F0F010,
0x40C08010,
0x50D09010,
0x60E0A010,
0x70F0B010,
0x40C0C010,
0x50D0D010,
0x60E0E010,
0x70F0F010,
0x80000010,
0x90101010,
0xA0202010,
0xB0303010,
0x80004010,
0x90105010,
0xA0206010,
0xB0307010,
0xC0000010,
0xD0101010,
0xE0202010,
0xF0303010,
0xC0004010,
0xD0105010,
0xE0206010,
0xF0307010,
0x80008010,
0x90109010,
0xA020A010,
0xB030B010,
0x8000C010,
0x9010D010,
0xA020E010,
0xB030F010,
0xC0008010,
0xD0109010,
0xE020A010,
0xF030B010,
0xC000C010,
0xD010D010,
0xE020E010,
0xF030F010,
0x80400010,
0x90501010,
0xA0602010,
0xB0703010,
0x80404010,
0x90505010,
0xA0606010,
0xB0707010,
0xC0400010,
0xD0501010,
0xE0602010,
0xF0703010,
0xC0404010,
0xD0505010,
0xE0606010,
0xF0707010,
0x80408010,
0x90509010,
0xA060A010,
0xB070B010,
0x8040C010,
0x9050D010,
0xA060E010,
0xB070F010,
0xC0408010,
0xD0509010,
0xE060A010,
0xF070B010,
0xC040C010,
0xD050D010,
0xE060E010,
0xF070F010,
0x80800010,
0x90901010,
0xA0A02010,
0xB0B03010,
0x80804010,
0x90905010,
0xA0A06010,
0xB0B07010,
0xC0800010,
0xD0901010,
0xE0A02010,
0xF0B03010,
0xC0804010,
0xD0905010,
0xE0A06010,
0xF0B07010,
0x80808010,
0x90909010,
0xA0A0A010,
0xB0B0B010,
0x8080C010,
0x9090D010,
0xA0A0E010,
0xB0B0F010,
0xC0808010,
0xD0909010,
0xE0A0A010,
0xF0B0B010,
0xC080C010,
0xD090D010,
0xE0A0E010,
0xF0B0F010,
0x80C00010,
0x90D01010,
0xA0E02010,
0xB0F03010,
0x80C04010,
0x90D05010,
0xA0E06010,
0xB0F07010,
0xC0C00010,
0xD0D01010,
0xE0E02010,
0xF0F03010,
0xC0C04010,
0xD0D05010,
0xE0E06010,
0xF0F07010,
0x80C08010,
0x90D09010,
0xA0E0A010,
0xB0F0B010,
0x80C0C010,
0x90D0D010,
0xA0E0E010,
0xB0F0F010,
0xC0C08010,
0xD0D09010,
0xE0E0A010,
0xF0F0B010,
0xC0C0C010,
0xD0D0D010,
0xE0E0E010,
0xF0F0F010,
};
static int *bpptab[4]={pal2,pal4,pal16,pal256};
void modefree
( win *w )
{
if (w->area)
flex_free((flex_ptr)&w->area);
if (w->save_area)
free(w->save_area);
w->save_area=NULL;
if (w->pixtrans)
free(w->pixtrans);
w->pixtrans=NULL;
}
os_error *modeclear
( win*w, int mode )
{
int size,bpp,x,y,wid;
sprite_state s;
os_error *err;
w->mode = mode;
x = bbc_modevar(mode,bbc_XWindLimit)+1;
y = bbc_modevar(mode,bbc_YWindLimit)+1;
w->l2bpp = bbc_modevar(mode,bbc_Log2BPP);
bpp = 1 << w->l2bpp;
wid = x*bpp+31&~31;
w->osx = x << (w->xeig=bbc_modevar(mode,bbc_XEigFactor));
w->osy = y << (w->yeig=bbc_modevar(mode,bbc_YEigFactor));
w->charx = 8 << w->xeig;
w->chary = (bbc_modevar(mode,bbc_ModeFlags)&(1<<5)?16:8) << w->yeig;
size = sizeof(sprite_area)+sizeof(sprite_header)+wid/8*y+(8<<bpp);
if (!flex_alloc((flex_ptr)&w->area, size))
return wimpt_complain(&NoMem);
sprite_area_initialise(w->area, size);
err=wimpt_complain(sprite_create(w->area, "screen", sprite_haspalette, x, y, mode));
if (err) return err;
wimpt_noerr(sprite_sizeof_spritecontext(w->area, SprNam("screen"), &size));
w->save_area = claim(size);
w->save_area[0]=0;
if (3!=w->l2bpp)
memcpy(paladdr(w),bpptab[w->l2bpp],sizeof(int)<<bpp);
w->pixtrans = claim(1<<bpp);
if (!w->save_area || !w->pixtrans)
return wimpt_complain(&NoMem);
wimpt_noerr(sprite_outputtosprite(w->area, SprNam("screen"), w->save_area, &s));
swix(OS_ChangedBox,IN(R0),1);
swix(OS_ChangedBox,IN(R0),2);
w->xvduqpos = 0;
w->curx = -1;
wimpt_noerr(sprite_restorestate(s));
coltable(w);
newwinsize(w);
return NULL;
}
void newwinsize
( win *w )
{
wimp_redrawstr r;
wimp_wstate state;
w->winx = w->osx*w->magm/w->magd;
w->winy = w->osy*w->magm/w->magd;
r.w = w->w;
r.box.x0 = 0; r.box.x1 = w->winx; r.box.y0 = -w->winy; r.box.y1 = 0;
wimpt_noerr( wimp_get_wind_state( w->w, &state ) );
if (state.o.box.x1 > state.o.box.x0+w->winx)
state.o.box.x1 = state.o.box.x0+w->winx;
if (state.o.box.y0 < state.o.box.y1-w->winy)
state.o.box.y0 = state.o.box.y1-w->winy;
if (state.o.x < w->winx - (state.o.box.x1 - state.o.box.x0))
state.o.x = w->winx - (state.o.box.x1 - state.o.box.x0);
if (state.o.y < (state.o.box.y1 - state.o.box.y0) - w->winy)
state.o.y = (state.o.box.y1 - state.o.box.y0) - w->winy;
wimpt_noerr(wimp_open_wind(&state.o));
wimpt_noerr(wimp_set_extent(&r));
wimpt_noerr(wimp_force_redraw(&r));
}
wimp_paletteword *paladdr
( win *w )
{
sprite_ptr p;
if (3==w->l2bpp)
return (wimp_paletteword *)pal256;
wimpt_noerr(sprite_select_rp(w->area,SprNam("screen"),&p));
return (wimp_paletteword *)((sprite_header *)p+1);
}
void coltable
( win *w )
{
wimpt_noerr(colourtran_select_table(w->mode,paladdr(w),-1,(wimp_paletteword *)-1,w->pixtrans));
}
void scribble
( win *w, char *data, int size )
{
sprite_state s;
char *p;
int q,n;
wimpt_noerr(sprite_outputtosprite(w->area, SprNam("screen"), w->save_area, &s));
if (w->xvduqpos>0)
{ n = w->xvduqwant;
memcpy(w->xvduq+w->xvduqpos,data,n);
if (size<n)
{ w->xvduqpos += size;
w->xvduqwant = n-size;
goto ret;
}
else
{ p = w->xvduq;
goto doq;
}
}
for (p=data; size>0; p++,size--)
{ if (!(19<=*p && *p<=22))
continue;
if (p-data)
swix( OS_WriteN, IN(R0|R1), data, p-data );
data = p;
swix(OS_Byte,IN(R0|R1|R2)|OUT(R1),218,0,255,&q);
if (q)
continue;
n = *data==19?6:
*data==20?1:
*data==21?1:
2;
if (size<n)
{ memcpy(w->xvduq,p,size);
w->xvduqpos = size;
w->xvduqwant = n-size;
n = size;
}
else
{ wimpt_noerr(sprite_restorestate(s));
doq: switch(*p)
{
case 22:
modefree(w);
if (modeclear(w,p[1]&127))
{ freewin(w);
return;
}
break;
case 19:
if (3!=w->l2bpp)
{ int c=p[1]%(1<<(1<<w->l2bpp));
if (0<=p[2] && p[2]<16)
paladdr(w)[c].word = pal16[p[2]];
else if (p[2]==16)
memcpy(&paladdr(w)[c].bytes.gcol,&p[2],4);
coltable(w);
newwinsize(w);
}
break;
case 20:
if (3!=w->l2bpp)
memcpy(paladdr(w),bpptab[w->l2bpp],sizeof(int)<<(1<<w->l2bpp));
coltable(w);
newwinsize(w);
break;
}
wimpt_noerr(sprite_outputtosprite(w->area, SprNam("screen"), w->save_area, &s));
}
--n;
size -= n;
p = data += n;
data++; /* to match what will happen to p */
}
if (p-data)
swix( OS_WriteN, IN(R0|R1), data, p-data );
ret:
w->changed = 1;
wimpt_noerr(sprite_restorestate(s));
}
menu barmenumaker
( void *h )
{
h=h;
if ( !event_is_menu_being_recreated() )
{ if ( barmenu )
menu_dispose( &barmenu, 0 );
barmenu = menu_new( "VMode", ">Info,NewTasks,Quit" );
menu_setflags( barmenu, 2, newtasks, 0 );
}
return barmenu;
}
void barmenuproc
( void *h, char *hit )
{
h=h;
switch (hit[0])
{ case 1:
infobox();
break;
case 2:
newtasks = ! newtasks;
break;
case 3:
if ( oktoquit() )
{ while (thewins)
freewin(thewins);
exit(0);
}
break;
}
}
/*
* Window manipulation
*/
void newtitleflag
( win *w, char *n )
{ wimp_redrawstr r;
wimp_wstate s;
strcpy( w->title+w->tlen, n );
r.w = w->w;
wimpt_noerr( wimp_getwindowoutline( &r ) );
wimpt_noerr( wimp_get_wind_state( w->w, &s ) );
r.w = -1;
r.box.y0 = s.o.box.y1;
wimpt_noerr( wimp_force_redraw( &r ) );
}
void behind
( win *w, int where )
{ wimp_wstate s;
wimpt_noerr( wimp_get_wind_state( w->w, &s ) );
s.o.behind = where;
wimpt_noerr( wimp_open_wind( &s.o ) );
}
void freewin
( win *w )
{
win **w1;
if ( w->w )
{ win_register_event_handler( w->w, 0, 0 );
alarm_removeall( (void *)w );
wimpt_noerr(wimp_delete_wind(w->w));
}
for ( w1=&thewins; *w1!=w; w1=&(*w1)->next )
if ( !*w1 )
werr( 1, "Chain of windows broken" );
if (w->state!=TDEAD)
{ wimp_msgstr msg;
msg.hdr.action = 0x808c4; /* TaskWindow_Morite */
msg.hdr.your_ref = 0;
msg.hdr.size = 20;
wimpt_noerr( wimp_sendmessage( wimp_ESEND, &msg, w->task ) );
}
*w1 = w->next;
modefree(w);
free(w);
}
/*
* Wimp utility
*/
int confirm
( char *s )
{ return dboxquery(s)==dboxquery_YES;
}
void infobox
( void )
{ dbox d;
d = dbox_new("info");
dbox_setfield(d, 3, VERSION );
dbox_show(d);
dbox_fillin(d);
dbox_dispose(&d);
}
/*
* Safe memory allocation
*/
void *claim
( int size )
{ void *p;
p = malloc( size );
if ( !p )
werr( 1, "out of memory" );
return p;
}
void *reclaim
( void *q, int size )
{ void *p;
p = realloc( q, size );
if ( !p )
werr( 1, "out of memory" );
return p;
}
/*
* Stuff to deal with sending Wimp messages
*/
void ack
( wimp_msgstr* msg )
{
msg->hdr.your_ref = msg->hdr.my_ref;
wimpt_noerr( wimp_sendmessage( wimp_ESEND, msg, msg->hdr.task ) );
}
void rofprintf
( int fh, char *fmt, ... )
{ char buf[256];
va_list arg;
_kernel_osgbpb_block b;
va_start( arg, fmt );
vsprintf( buf, fmt, arg );
va_end( arg );
b.dataptr = buf;
b.nbytes = strlen( buf );
if (_kernel_osgbpb( 2, fh, &b )==_kernel_ERROR)
wimpt_complain( (os_error *)_kernel_last_oserror() );
}
void strins
( char *d, char *s )
/* Insert string s at the beginning of string d */
{
int l=strlen(s);
int m=strlen(d);
memmove(&d[l],d,m+1);
memmove(d,s,l);
}
char *strdup
( char *d )
{
int m=strlen(d);
char *p = claim(m+1);
if (p)
strcpy( p, d );
return p;
}
char *strjoin
( char *s, char *t )
{
int m=strlen(s);
int n=strlen(t);
char *p = claim( m+n+1 );
if (p)
{ strcpy( p, s );
strcpy( p+m, t );
}
return p;
}