//accdis.cpp Copyright (C) 1990-91 I.Pedley (CTPP) Mon 24-Feb-1992 at 16:57:27
//first TSR application
//accdis.ctp Copyright (C) 1989-97 I.Pedley (CTPP) Sun 27-Apr-1997 at 15:30:02
//time to grow up this is our OS version
#include {chaoskey.htm}
#include {ctype.htm}
#include {string.htm}
#include {stdlib.htm}
#include {accdis.htm}
VD dvblit(VD);
#define SUCCESS 0L
#define FAILURE -1L
struct FIELD
{
SI pos;
SI row;
SI col;
UI w;
SI sign;
SI digits;
SI dec_digits;
SI argsize;
SI base;
CH fgd;
CH bgd;
CH type;
CH* shadow;
CH* dest;
SI limits;
SI isarray;
CH* format;
SI zerofill;
};
struct FIELD_ARRAY
{
FIELD* first;
SI width;
SI depth;
SI home;
SI end;
};
VD longtoascii(UL longint,CH* buf,UL digits,UL sign,
UL zerofill,UL base,UL dec_digits,UL shift);
VD doubletoascii(DB* d,CH* buf,UL fw,UL dec_digits,UL sign,UL zerofill);
VD numtoascii(FIELD* f);
VD idle(VD){}
#define CGA_ADDRESS 0xb8000
#define MDA_ADDRESS 0xb0000
UI mda_mode;
ACCDIS cga={
(VD*)&cga,
idle,
mdafgd,mdabgd,
mdasetcurpos,
NULL, //hardware cursor needs no clrcursor
mdasetcursiz,
mdaputc,
mdaprint,
mdaprin,
mdascroll,
getkey,
NULL,
NULL,
NULL,
(CH*)CGA_ADDRESS,
// 7,0,0,0,80,2,25,0
// 7,0,0,0,80,2,200,0
7,0,0,0,80,2,50,0
};
ACCDIS mda={
(VD*)&mda,
idle,
mdafgd,mdabgd,
mdasetcurpos,
NULL, //hardware cursor needs no clrcursor
mdasetcursiz,
mdaputc,
mdaprint,
mdaprin,
mdascroll,
getkey,
NULL,
NULL,
NULL,
(CH*)MDA_ADDRESS,
// 7,0,0,0,80,2,25,0
7,0,0,0,80,2,200,0
};
ACCDIS mem={
(VD*)&mem,
idle,
memfgd,membgd,
memsetcurpos,
NULL, //needs no clrcursor
memsetcursiz,
memputc,
memprint,
memprin,
memscroll,
getkey, //<--allows accept to memory buffer
NULL, //...may allow password entry?
NULL,
NULL,
NULL,
7,0,0,0,80,1,100,0
};
ACCDIS vmem={
(VD*)&vmem,
idle,
vmemfgd,vmembgd,
NULL, //needs no clrcursor
vmemsetcurpos,
vmemsetcursiz,
vmemputc,
vmemprint,
vmemprin,
vmemscroll,
getkey, //<--allows accept to memory buffer
NULL, //...may allow password entry?
NULL,
NULL,
NULL,
7,0,0,0,80,2,50,0
};
VD vesaputc(VD* usr,CH c,UL row,UL col);
VD vesaprin(VD* usr,CH* str,UL row,UL col,UL len);
VD vesaprint(VD* usr,CH* str,UL row,UL col);
VD vesasetcurpos(VD* usr,UL row,UL col);
VD vesaclrcurpos(VD* usr,UL row,UL col);
VD vesascroll (VD* usr);
ACCDIS avesa={
(VD*)&avesa,
idle,
mdafgd,mdabgd,
vesasetcurpos,
vesaclrcurpos,
memsetcursiz,
vesaputc,
vesaprint,
vesaprin,
vesascroll,
getkey,
NULL,
NULL,
NULL,
NULL,
7,0,0,0,80,2,200,0
};
ACCDIS* AA=&cga;
SL mdaset(UL mode)
{
mda_mode=mode;
SI screen_rows=25;
switch(mode)
{
case 0:
// _setvideomode(_TEXTMONO);
AA=&mda;
break;
default:
case 1:
// _setvideomode(_TEXTC80);
// _settextrows (screen_rows=cga.rows=25);
AA=&cga;
break;
case 2:
// _setvideomode(_VRES16COLOR);
break;
case 3:
// _setvideomode(_TEXTC80);
// _settextrows (screen_rows=cga.rows=50);
AA=&cga;
break;
}
return screen_rows;
}
VD AccdisSet(ACCDIS* a)
{
if(!a){AA=&cga;}
else {AA=a;}
}
//VD AccdisSetIdleFunction(VD(*idlefunc)(VD))
VD AccdisSetIdleFunction(VD* idlefunc)
{
if(idlefunc==NULL){AA->idle=idle;}
else {AA->idle=idlefunc;}
}
VD sound_beep(UL hz)
{
// sound(hz);
// delay(150);
// nosound();
}
#define MID_FIELD 0
#define HOME_FIELD 1
#define END_FIELD 2
#define TOP_FIELD 4
#define BOTTOM_FIELD 8
#define HASH_FIELD 0x80
#define BADARG -1
VD fieldchar(ACCDIS* A,FIELD* cf,CH c,UL field_pos)
{
(*A->putc)(A->usr,c,cf->row,cf->col+field_pos);
CH* ptr=cf->shadow;
ptr[field_pos]=c;
}
VD makepattern(FIELD* cf,CH* pattern)
{
CH fill;
switch(cf->base)
{
case 2:
fill='1';break;
case 10:
fill='9';break;
case 16:
fill='x';break;
default:
fill='X';break;
}
memset(pattern,fill,cf->w);
if(cf->dec_digits){pattern[cf->digits]='.';}
switch(cf->type)
{
case '&':
pattern[0]=pattern[1]='z';break;
case 'M':
case 'D':
pattern[2]=pattern[5]='/';break;
case 'T':
pattern[5]=':';
case 't':
pattern[2]=':';break;
case 'f':
case 'F':
pattern[4]=':';break;
case 'H':
for(fill=0;fillw/3;fill++)
{
pattern[fill*3+2]=' ';
}
break;
default:
break;
}
if(cf->sign)
{
switch(cf->type)
{
case 't':
case 'D':break;
default:*pattern='+';
}
}
}
VD outhexdword(UL dword,UL row,UL col);
//SL getkey(VD);
UL inkey (ACCDIS* A,UL* key,CH* c,UL row,UL col)
{
(*A->setcurpos)(A->usr,row,col);
if(A->insert) //if insert on
{(*A->setcursiz)(A->usr,0x0007);} //set block cursor
// else{(*A->setcursiz)(A->usr,0x0c0e);}
else{(*A->setcursiz)(A->usr,0x0607);}
// while(!((*A->getkey)(_NKEYBRD_READY))){(*A->idle)();}
// while(!(*A->getkey)(_NKEYBRD_READY)){(*A->idle)();}
// *key= (*A->getkey)(_NKEYBRD_READ);
*key= (*A->getkey1)();
*c=*key;
if(A->callback!=NULL)
{
//A->callback(*key,row,col,A->callbackuserptr);//COMPILER BUG TO FIX
(*A->callback)(*key,row,col,A->callbackuserptr);//works OK like this
}
if(A->clrcurpos){(*A->clrcurpos)(A->usr,row,col);}
return *key;
}
VD netutility(VD);
VD sysutility(VD);
SL fieldedit(ACCDIS* A,FIELD* cf,SL *curpos)
{
CH* ptr;
CH* ptr1;
CH* fptr;
CH* pattern;
SL n,row,col;
SL fgd,bgd;
SL acol=cf->col;
SL arow=cf->row;
SL digits=cf->digits;
SL field_width=cf->w;
SL sign=cf->sign&1;
SL min;
SL max;
SL field_pos;
CH c,d;
UL key;
UL day,month,year; //for date field immediate validation
UL end=0;
pattern=(CH*)malloc(field_width);
if(pattern==NULL){return ESC;}
makepattern(cf,pattern);
if(*curpos>field_width-1){*curpos=field_width-1;} //set initial cursor position
field_pos=*curpos;row=arow;
fgd=cf->fgd;
bgd=cf->bgd;
(*A->setfgd)(A->usr,fgd);
(*A->setbgd)(A->usr,bgd);
// (*A->setfgd)(cf->fgd);
// (*A->setbgd)(cf->bgd);
switch(cf->type)
{
case 'H':max--;break;
case '&':min=2;break;
case 'M':
case 'D':
case 't':sign=0;break;
}
min=sign;max=cf->w-1;
L01:
// (*A->putstrn)(A->usr,cf->shadow,cf->row+1,cf->col,cf->w);
if(field_poscpl+1))
// {field_pos+=A->cpl; goto L01;}
// else if(cf->limits&END_FIELD)
if(cf->limits&END_FIELD)
{
if(field_posmin) {field_pos=0; goto L01;}
else if(cf->limits&HOME_FIELD){sound_beep(500);goto L01;}
else {end=0; goto L02;}
break;
case BACKSPACE: //overwrite this char with space
if(field_pos>min){fieldchar(A,cf,0x20,field_pos);field_pos--;goto L01;}
else if(cf->limits&HOME_FIELD){sound_beep(500);goto L01;}
else {end=0; goto L02;}
break;
case NLCUR:
if(field_pos>min) {field_pos--; goto L01;}
else if(cf->limits&HOME_FIELD){sound_beep(500);goto L01;}
else {end=0; goto L02;}
break;
case NRCUR:
if(field_poslimits&END_FIELD) {sound_beep(500);goto L01;}
else { goto L02;}
break;
case NHOME:
if(cf->limits&HOME_FIELD)
{if(field_pos>min) {field_pos=0; goto L01;}
else {sound_beep(500);goto L01;} }
else {end=0; goto L02;}
break;
case NEND:
if((cf->type=='s')&&(cf->shadow[field_pos]!=0x20))
{
field_pos=max;
while(cf->shadow[field_pos]==0x20)
{
field_pos--;
if(!field_pos){goto L01;}
}
field_pos++;
goto L01;
}
else if(field_poslimits&END_FIELD) {sound_beep(500);goto L01;}
else { goto L02;}
break;
case NUCUR:
if(cf->limits&TOP_FIELD) {sound_beep(500);goto L01;}
else {end=0; goto L02;}
break;
case NDCUR:
if(cf->limits&BOTTOM_FIELD) {sound_beep(500);goto L01;}
else { goto L02;}
break;
case (CTRL|'a'):
if (cf->type=='s')
{for(n=0;ninsert^=1;goto L01;break;
case NDEL:
if(*fptr=='X')
{
for(n=field_pos+1;nshadow;
d=ptr[n];
fieldchar(A,cf,d,n-1);
}
fieldchar(A,cf,' ',field_width-1);
}
end=0;
goto L01;
break;
default:
//chuck out other keys we don't want
if((key&0x7f)<=0x1b){goto L01;} //ignore ESC and F1-F12 combinations
//(raw ESC ie 0x1b is handled above)
if (key&0x80) {goto L01;} //ignore control keys
if(c==0)
{if(end)
{sound_beep(500);goto L01;}
else {end=1;goto L01;}
}
if(*fptr=='9')
{if(c=='.'&&field_pos<=digits) //*******debug this
{
if((cf->type=='D')||(cf->type=='M'))
{
fieldchar(A,cf,'/',2);
fieldchar(A,cf,'/',5);
field_pos=max;
}
else if(cf->type=='T')
{
fieldchar(A,cf,':',2);
fieldchar(A,cf,':',5);
field_pos=max;
}
else if(cf->type=='t')
{
fieldchar(A,cf,':',2);
field_pos=max;
}
else
{
n=digits-1;
while(fptr>pattern+sign)
{
ptr=cf->shadow;
c=ptr[--field_pos];
fieldchar(A,cf,' ',field_pos);
fieldchar(A,cf,c,n);
n--;fptr--;
}
// for(;n>sign;n--) //subtle change 19.9.97
for(;n>=sign;n--)
{fieldchar(A,cf,' ',n);}
}
if((cf->type=='d'|cf->type=='v')&&cf->dec_digits)
{
field_pos=digits+1;
fptr=pattern+field_pos;col=acol+field_pos;
fieldchar(A,cf,'.',digits);goto L01;
}
else{field_pos=max;
if(cf->limits&END_FIELD){sound_beep(500);goto L01;}
else {key=NRCUR; goto L02;}
}
}
else if(c<'0'|c>'9')
{
if(cf->sign)
{if(c=='+'|c=='-')
{
fieldchar(A,cf,c,0);goto L01;
}
else
{sound_beep(500);goto L01;}
}
else{sound_beep(500);goto L01;}
}
}
else if(*fptr=='X')
{if(A->insert) //if insert on
{
if(field_posshadow+field_pos;
memmove(ptr+1,ptr,field_width-field_pos-1);
*ptr=c;
(*A->putstrn)(A->usr,cf->shadow,cf->row,cf->col,cf->w);
// goto L03a;
}
// for(n=field_width-2;n>=field_pos;n--)
// {
// ptr=cf->shadow;
// d=ptr[n];
// fieldchar(A,cf,d,n+1);
// }
}
}
else if(*fptr=='.')
{if(c!='.') {sound_beep(500);goto L01;} }
else if(*fptr=='x')
{if(c<'0'|c>'9')
{if(c<'a'|c>'f')
{sound_beep(500);goto L01;}
}
}
break;
}//switch key
if(cf->type=='?'){c='?';}
L03:
fieldchar(A,cf,c,field_pos); //char into screen_buffer and shadow
L03a:
if(field_pos==max){
if(cf->limits&END_FIELD)
{
if(end){sound_beep(500);}
else {end=1;}
goto L01;
}
else{key=NRCUR;goto L02;}
}
//overflow into next field
field_pos++;
goto L01;
L02:
if((cf->type=='D')||(cf->type=='M'))
{
fptr=cf->shadow;
day =atoi(fptr); fptr+=3;
month=atoi(fptr); fptr+=3;
year =atoi(fptr);
if((!day)&&(!month)&&(!year)) {goto AOK;} //OK if field left blank
//Millennium date adjustment
if(cf->type=='D')//zero year in 99/99/99 dates means year 2000
{if((!day)|(!month)) {goto FAIL;}}
else{if((!day)|(!month)|(!year)) {goto FAIL;}
if((year/100)!=19)
if((year/100)!=20) {goto FAIL;}
}
// if(!day |!month |!year) {goto FAIL;}
if(day>31|month>12) {goto FAIL;}
if(month==4|month==6|month==9|month==11)
{if(day>30){goto FAIL;}}
else if(month==2)
{if(!(year%4))
{if(day>29){goto FAIL;}}
else{if(day>28){goto FAIL;}}
}
AOK:
goto L04;
FAIL:
sound_beep(500);goto L01;
}
L04:
free(pattern);
*curpos=field_pos;
if(cf->sign) //zero backfill signed numerics
{for(n=0;nshadow;
c=ptr[n];
if(c==' '){fieldchar(A,cf,'0',n);}
}
}
(*A->setcursiz)(A->usr,0x2000);
return key&0xffff;
}
//386 processor EFLAGS register bit meanings
#define FLGPAGING 0x80000000
#define FLGVM 0x00020000
#define FLGRESTART 0x00010000
#define FLGNT 0x00004000
#define FLGIOPL 0x00003000
#define FLGOF 0x00000800
#define FLGDF 0x00000400
#define FLGIF 0x00000200
#define FLGTF 0x00000100
#define FLGSF 0x00000080
#define FLGZF 0x00000040
#define FLGAF 0x00000010
#define FLGPF 0x00000004
#define FLGCF 0x00000001
#define LINPRESENT 0x00000001
#define LINRW 0x00000002
#define LINUS 0x00000004
#define LINACCESSED 0x00000020
#define LINDIRTY 0x00000040
#define mLINAVL 0x00000e00
#define FALSE 0
#define TRUE 1
UL getcr0(VD)
{
#asm
mov eax,cr0
#endasm
}
UL getcr3(VD)
{
#asm
mov eax,cr3
#endasm
}
SL linvalid(UL lin)
{
UL cr0=getcr0();
// if(!(cr0&FLGPAGING))
// {
// if(lin&0x80000000){return FALSE;}
//catch-all for memory accesses which fault a 4Gb selector
if((lin&-8)==-8){return FALSE;}
return TRUE;
// }
UL cr3=getcr3();
UL direntry=lin>>22;
direntry<<=2;
direntry+=cr3;
if(!(*(UL*)direntry&LINPRESENT)){return FALSE;}
UL page=*(UL*)direntry;
page&=0xfffff000;
UL tableentry=lin>>12;
tableentry&=0x3ff;
tableentry<<=2;
tableentry+=page;
if(!(*(UL*)tableentry&LINPRESENT)){return FALSE;}
return TRUE;
}
SL evaluatefield(CH* format,CH** nextptr,FIELD* f,UL row,UL col,UL fgd,UL bgd,CH** args)
{
CH* fptr=format;
CH* argptr=*args;
SL m,argctr=0;
memset(f,0,sizeof(FIELD));
f->row=row;
f->col=col;
f->fgd=fgd;
f->bgd=bgd;
f->format=format;
fptr++;
if(*fptr=='#') //field width precedes arg on stack
{
fptr++;
argptr=args[argctr];
f->w=*(UL*)argptr;
// if(f->w==0){return 0;}
argctr++;
f->limits|=HASH_FIELD;
goto DOTYPE; //skip numeric evaluation
} //as this type is mainly for strings
if(*fptr=='&') //display actual data address itself
{fptr++; //as 32 bit hex rather than data at address
}
//handle sign attribute
switch(*fptr)
{
case '+':f->sign=1;fptr++;break;
case '-':f->sign=5;fptr++;break;
case '(':f->sign=3;fptr++;break;
case ')':f->sign=7;fptr++;break;
default :f->sign=0;
}
//handle zerofill attribute
switch(*fptr)
{
case '0':f->zerofill=1;break;
default :f->zerofill=0;
}
//get field width
f->w=f->digits=strtol(fptr,&fptr,10);
//handle decimal point if present
switch(*fptr)
{
case '.':fptr++;
f->dec_digits=strtol(fptr,&fptr,10);
f->digits -=(f->dec_digits+1);
if(f->dec_digits<0){return 0;}
break;
default :f->dec_digits=0;
}
DOTYPE:
//type should be next
f->type=*fptr++;
//assign field destination pointer
f->dest=args[argctr];
//handle field width for special types
switch(f->type)
{
case 'M':f->w=f->digits=10;break; //special Millennium Date type
case 'D':f->w=f->digits=8 ;break; //special Date type
case 't':f->w=f->digits=5 ;break; //special Time type
// case 'T':f->w=f->digits=11;break; //special Time type
case 'T':f->w=f->digits=8 ;break; //special Time type
case 'f':f->w=f->digits=9 ;break; //special seg:offset type
case 'F':f->w=f->digits=13;break; //special seg:offset32 type
case 'h':f->w=f->digits=f->w*2;break;
case 'H':f->w=f->digits=f->w*3;break;
}
//TEST FOR INVALID LINEAR ADDRESSING now field widths are known
if(!(linvalid((UL)f->dest))){f->type='?';}
//do default field widths if f->w is still 0
if(!f->w)
{
switch(f->type)
{
// case 'a':f->w=*(UC*)f->dest; break;
case 'a':if(*(UC*)f->dest!=0xff){f->w=*(UC*)f->dest;}else{f->w=2;}break;
// case 's':if(!(f->limits&HASH_FIELD)){f->w=astrlen(f->dest);}break;
case 's':if(!(f->limits&HASH_FIELD)){f->w=strlen(f->dest);}break;
case 'c':f->w=2;break;
case 'p':
case 'x':
case 'i':f->w=*(UI*)f->dest;f->digits=0;
do{f->digits++;f->w/=10;}while(f->w);f->w=f->digits;break;//f->w=4;
case 'P':
case 'X':
case 'v':
case 'd':
case 'l':f->w=8;break;
case '&':f->digits=f->w=10;f->zerofill=1;break;
case 'I':f->w=15;break; //16.8.09 new IP display type
}
}
//allocate shadow
if(f->sign&2){f->w++;} //allow for bracketed signed numbers
if(f->w)
{
f->shadow=(CH*)calloc(f->w+1,1);
if(f->shadow==NULL){return 0;}
}
//initialise shadow to spaces
memset(f->shadow,0x20,f->w);
//set argsize and filter bad arg type specifiers
switch(f->type)
{
case '?':
case 'a':
case 'S':
case 's':f->argsize=f->w; break;
case 'h':f->argsize=f->w/2;break;
case 'H':f->argsize=f->w/3;break;
case 'c':f->argsize=1; break;
case 'i':
case 'p':
case 'x':f->argsize=2; break;
case 'f':
case 'l':
case 'P':
case 'X':
case 'v':
case 'V':
case 'Z':
case 'M':
case 'D':
case 't':
case '&':
case 'T':
case 'I':f->argsize=4; break;
case 'F':f->argsize=6; break;
case 'd':f->argsize=8; break;
default :return 0;
}
//set base for special types x&X (although these can be represented by %ix %lx)
switch(f->type)
{
case 'c':
case 'i':
case 'p':
case 'l':
case 'v':
case 'V':
case 'Z':
case 'd':
case 'M':
case 'D':
case 't':
case 'T':
case 'P':
case 'I':f->base=10; break;
case '&':
case 'h':
case 'H':
case 'f':
case 'F':
case 'x':
case 'X':f->base=16; break;
default :f->base=0; break; //strings are set to base 0
}
//check for base postfix
switch(*fptr)
{
case 'b':f->base=2; fptr++;break;
case 'd':f->base=10;fptr++;break;
case 'x':f->base=16;fptr++;break;
case 'n':fptr++;f->base=strtol(fptr,&fptr,10);
if(!f->base){return 0;}
break;
}
if(*fptr=='p') //evaluate change in position
{fptr++;
m=strtol(fptr,&fptr,10);
row=m/100;
col=m%100;
}
if(*fptr=='C') //evaluate change in column
{fptr++;
m=strtol(fptr,&fptr,10);
col=m%100;
}
f->pos=(row<<8)+col;
f->row=row;
f->col=col;
if(*fptr=='c')
{fptr++;
m=strtol(fptr,&fptr,10);
if(m>=100){fgd=m/100;}else{fgd=0;}
bgd=m%100;
}
f->fgd=fgd;
f->bgd=bgd;
*nextptr=fptr;
return argctr+1;
// return SUCCESS;
}
//NEW accdis.cpp Copyright (C) 1989-95 I.Pedley (CTPP) Tue 11-Jul-1995 at 20:14:10
//hard-linked jobby
SL display(CH* format,...)
{
return vaccept(AA,AA->row,AA->col,format,0,&format+1); //watch
}
SL accept(CH* format,...)
{
return vaccept(AA,AA->row,AA->col,format,1,&format+1); //watch
}
SL count_arrays(CH* format)
{
//Determine number of arrays present in format string
SL arrays=0;
CH* fptr=format;
while(*fptr!=0)
{
if(*fptr=='%')
{
switch(*(fptr+1))
{
case '%':
case '|':
case '{':
case '}':
case '&':
fptr++;
break;
}
}
else if(*fptr=='{')
{if(*(fptr+1)=='{'){fptr++;}arrays++;}
fptr++;
}
return arrays;
}
SL count_fields(CH* format)
{
//simple count of % characters, skipping %z's and special characters
SL fields=0;
CH* fptr=format;
CH* sptr;
while(*fptr!=0)
{if(*fptr=='%')
{
strtol(fptr+1,&sptr,10);
if(*sptr=='z')
{
fptr=sptr+1;
}
else
{
switch(*(fptr+1))
{
case '%':
case '|':
case '{':
case '}':
fptr+=2;
break;
default:
fields++;
break;
}
}
}
fptr++;
}
return fields;
}
VD column_sort(FIELD* cf,SL width)
{
SL n,m,o;
FIELD* first=cf-width;
FIELD tmp;
for(n=0;nfirst[m].col)
{
tmp=first[n];
first[n]=first[m];
first[m]=tmp;
o=first[n].limits;
first[n].limits=first[m].limits;
first[m].limits=o;
}
}
}
}
//#pragma 0xffffff7f
//#pragma 1
UL accdisarrayinc=1;
VD displaychar(ACCDIS* A,CH c,SL fgd,SL bgd,SL* row,SL* col)
{
if(c=='$') {c='%';}
if(c=='\r'){if(A->bpc==2){*col=0;return;}}
if((c=='\n')&&(A->bpc==2))
{
(*row)+=1;
if((*row)>=A->rows)
{
UL n=0;
UL m;
m=((A->cpl*(A->rows-1))*A->bpc);
while(nmem[n]=A->mem[n+(A->cpl*A->bpc)];
n++;
}
(*A->setfgd)(A->usr,fgd);(*A->setbgd)(A->usr,bgd);
(*row)=A->rows-1;
for(n=0;ncpl;n++)
{
(*A->putc)(A->usr,' ',(*row),n);
}
*col=0;
}
return;
}
(*A->setfgd)(A->usr,fgd);(*A->setbgd)(A->usr,bgd);
(*A->putc)(A->usr,c,*row,*col);(*col)+=1;
if(*col>A->cpl-1){(*row)+=1;(*col)-=A->cpl;}
}
#pragma breakpoints on
SL evaluate_array(ACCDIS* A,CH* format,CH** nextptr,FIELD_ARRAY* cfa,UL nfa,FIELD* cf,UL nf,SL* fctr,CH** args,SL* row,SL* col,SL fgd,SL bgd,SL ffgd,SL fbgd)
{
CH* nptr,*sptr,*argptr;
UL acol,o,fret,argctr=0,sa=0,fl,structsize;
format++;
if(*format=='{') //it's a structure array
{
format++;sa=1;
}
if(*format=='%')
{
format++;argctr++; //skip array size argument already known
}
else{strtol(format,&format,10);}//skip array size digits already known
nptr=format;
acol=*col;
cfa->first=cf;
argptr=*args;
for(o=0;odepth;o++)
{
*col=acol;
format=nptr;
structsize=0;
while(*format!='}')
{
if(*format=='%')
{
fl=strtol(format+1,&sptr,10);
if(*sptr=='z')
{
structsize+=fl;
format=sptr+1;
}
else
{
switch(*(format+1))
{
case '%':
case '|':
case '{':
case '}':
displaychar(A,*(format+1),fgd,bgd,row,col);
format+=2;
break;
default:
fret=evaluatefield(format,&format,cf,*row,*col,ffgd,fbgd,&args[argctr]);
if(!fret){goto ARGERR;}
cf->limits=0;
// if(cfa->first==cf)
// {cf->limits|=HOME_FIELD;}
if(*fctr==0)
{cf->limits|=HOME_FIELD;}
if(*fctr==nf-1)
{cf->limits|=END_FIELD;}
if(o==0)
{cf->limits|=TOP_FIELD;}
if(o==cfa->depth-1)
{cf->limits|=BOTTOM_FIELD;}
cf->isarray=nfa+1;
*col=cf->w+cf->col;
while(*col>A->cpl-1)
{
// (*row)+=accdisarrayinc;
*col-=A->cpl;
}
if(sa)
{
//NB don't use # in structure arrays!
cf->dest=argptr+structsize;
argptr+=cf->argsize;
}
else
{
cf->dest=args[argctr]+(o*cf->argsize);
argctr+=fret;
}
cf++;
(*fctr)++;
break;
}
}
}
else
{
displaychar(A,*format++,fgd,bgd,row,col);
}
}
if(cfa->width>1){column_sort(cf,cfa->width);}
(*row)+=accdisarrayinc;
if(sa){argptr+=structsize;}
else {argctr-=cfa->width;} //fctr+=cfa->width;
}
format++; //finally skip closing brace & adjust argptr
*nextptr=format;
if(sa){return argctr+1;}
else {return argctr+cfa->width;}
ARGERR:
return -1;
}
#pragma breakpoints off
UL inaccdis;
SL vaccept(ACCDIS* A,SL row,SL col,CH* format,SL disp,CH*args[])
{
if((*format)&&!(isprint(*format))){brk return 1;} //is this the sodding bug? (YES!!)
if(inaccdis>2){return 0;} //abort accdis if called by an interrupt handler
inaccdis++;
CH* ptr;
CH* ptr1;
CH* fptr;
CH* nptr;
SL argctr; //argument array counter
SL fgdsav=A->fgd;
SL bgdsav=A->bgd;
SL rowsav=A->row;
SL colsav=A->col;
SL fgd=7;
SL bgd=0;
SL ffgd=7;
SL fbgd=0;
SL ret;
SL arraycol;
SL limits;
SL curpos;
SL n,m,o,sa,fret;
SL fctr;
UL ul;
SL arrays;
SL fields;
FIELD* field =NULL;
FIELD* cf;
FIELD_ARRAY* field_array=NULL;
FIELD_ARRAY* cfa;
SL return_code;
UL* uiptr;
CH* dptr;
//zero critical variables
start:
return_code=limits=curpos=fields=n=sa=m=o=arrays=0;
//Display and set up field array
fptr=format;
//Determine number of arrays present
arrays=count_arrays(format);
//allocate some space for FIELD_ARRAYs
argctr=0;
if(arrays)
{
field_array=(FIELD_ARRAY*)calloc(arrays,sizeof(FIELD_ARRAY));
if(field_array==NULL){goto MEMERR;}
//and get array sizes
fptr=format;m=n=o=0;
cfa=field_array;
while(nwidth=sa=0;
fptr++;
if(*fptr=='{'){sa=1;fptr++;}
if(*fptr=='%')
{
uiptr=(UL*)args+argctr;
cfa->depth=*uiptr;
argctr++;fptr++;
}
else{cfa->depth=strtol(fptr,&fptr,10);}
if(!cfa->depth)
{(*A->putstr)(A->usr,"Expected array size after opening brace",0,0);goto escape;}
while(*fptr!='}')
{if(!*fptr)
{(*A->putstr)(A->usr,"No closing brace for array",0,0);goto escape;}
else if(*fptr=='%')
{
switch(*(fptr+1))
{
case '%':
case '|':
case '{':
case '}':
fptr+=2;
break;
default:
fptr++;
strtol(fptr,&fptr,10);
if(*fptr!='z'){cfa->width++;}
break;
}
}
fptr++;
}
//note zero array width is possible, to shorthand column displays
m+=cfa->width;
o+=cfa->width*cfa->depth;
if(sa){argctr++;}
else {argctr+=cfa->width;}
n++;
cfa++;
}
} //m=field format strings within arrays;
//o=total fields required for arrays;
//Determine number of fields in total
n=count_fields(format); //n=field format strings
n-=m; //less those within arrays
fields=n+o; //total fields on screen
if(fields){
field=(FIELD*)calloc(fields,sizeof(FIELD));
if(field==NULL){goto MEMERR;}
}
fptr=format;fctr=arrays=argctr=0;
//Initial display and initialise FIELDS
cf=field;
cfa=field_array;
while(*fptr!=0)
{
if(*fptr=='%')
{
switch(*(fptr+1))
{
case '%':
case '|':
case '{':
case '}':
displaychar(A,*(fptr+1),fgd,bgd,&row,&col);
fptr+=2;
break;
default:
fret=evaluatefield(fptr,&fptr,cf,row,col,ffgd,fbgd,(CH**)args+argctr);
if(!fret){goto ARGERR;}
else {argctr+=fret;}
col=cf->w+cf->col;
while(col>A->cpl-1){row++;col-=A->cpl;}
// cf->dest=args[argctr];
cf->limits=0;
if(fctr==0) {cf->limits|=HOME_FIELD|TOP_FIELD|BOTTOM_FIELD;}
if(fctr==fields-1){cf->limits|=END_FIELD |BOTTOM_FIELD|TOP_FIELD;}
else {cf->limits|=TOP_FIELD|BOTTOM_FIELD;}
cf->isarray=0;
fctr++;
// argctr++;
cf++;
break;
}
}
else if(*fptr=='|')
{fptr++;
if(*fptr=='p') //evaluate change in position
{fptr++;
m=strtol(fptr,&fptr,10);
row=m/100;
col=m%100;
}
if(*fptr=='C') //evaluate change in column
{fptr++;
m=strtol(fptr,&fptr,10);
col=m%100;
}
if(*fptr=='R') //evaluate relative change
{fptr++; //in position
m=strtol(fptr,&fptr,10);
row+=m;
m=strtol(fptr,&fptr,10);
col+=m;
}
if(*fptr=='c') //evaluate change in colours
{fptr++;
m=strtol(fptr,&fptr,10);
if(m>=100){fgd=m/100;}else{fgd=0;}
bgd=m%100;
}
}
else if(*fptr=='{') //array to handle
{
o=evaluate_array(A,fptr,&fptr,cfa,arrays,cf,fields,&fctr,(CH**)args+argctr,&row,&col,fgd,bgd,ffgd,fbgd);
if(o==-1){goto ARGERR;}
argctr+=o;
cf+=cfa->width*cfa->depth;
arrays++; //maybe another array to follow
cfa++;
}
else
{
displaychar(A,*fptr++,fgd,bgd,&row,&col);
}
}
if(!fields){goto escape;} //format string is display only
cf=field;
UL ltmp;
UI itmp;
for(m=0;mfgd;
bgd=cf->bgd;
(*A->setfgd)(A->usr,fgd);
(*A->setbgd)(A->usr,bgd);
ptr =cf->shadow;
ptr1=cf->dest;
switch(cf->type)
{
case 's':
// n=astrlen(ptr1);if(n>cf->w){n=cf->w;}
n=strlen(ptr1);if(n>cf->w){n=cf->w;}
memcpy(ptr,ptr1,n);
break;
case 'a': //pascal-type string
n=*ptr1;n&=0xff;if(n>cf->w){n=cf->w;}
memcpy(ptr,ptr1+1,n);
break;
case 'S':
memcpy(ptr,ptr1,cf->w);
for(n=0;nw;n++)
{
if(!isprint(ptr[n])){ptr[n]='.';}
}
break;
case 'P':
case 'p':
case 'l':
case 'i':
case 'c':
case 'v':
case 'V':
case 'Z':
case 'd':
case 'x':
case 'X':
case '&':
numtoascii(cf);
break;
case 'D':
if(cf->sign)
{
ltmp=*(UL*)cf->dest;
}
else
{
ltmp=*(UM*)cf->dest;
}
longtoascii(ltmp%100,ptr,2,0,1,10,0,0);
ptr[2]='/';
longtoascii((ltmp/100)%100,ptr+3,2,0,1,10,0,0);
ptr[5]='/';
longtoascii((ltmp/10000)%100,ptr+6,2,0,1,10,0,0);
break;
case 'M':
if(cf->sign)
{
ltmp=*(UL*)cf->dest;
}
else
{
ltmp=*(UM*)cf->dest;
}
longtoascii(ltmp%100,cf->shadow,2,0,1,10,0,0);
cf->shadow[2]='/';
longtoascii((ltmp/100)%100,cf->shadow+3,2,0,1,10,0,0);
cf->shadow[5]='/';
longtoascii((ltmp/10000)%10000,cf->shadow+6,4,0,1,10,0,0);
break;
case 'I':
ltmp=*(UL*)cf->dest;
longtoascii((ltmp&0xff000000)>>24,cf->shadow,3,0,0,10,0,0);
cf->shadow[3]='.';
longtoascii((ltmp&0x00ff0000)>>16,cf->shadow+4,3,0,0,10,0,0);
cf->shadow[7]='.';
longtoascii((ltmp&0x0000ff00)>>8 ,cf->shadow+8,3,0,0,10,0,0);
cf->shadow[11]='.';
longtoascii((ltmp&0x000000ff) ,cf->shadow+12,3,0,0,10,0,0);
break;
break;
case 'T':
case 't':
if(cf->sign)
{
ltmp=*(UL*)cf->dest;
}
else
{
ltmp=*(UM*)cf->dest;
}
longtoascii((ltmp/1000000)%100,ptr,2,0,0,10,0,0);
ptr[2]=':';
longtoascii((ltmp/10000)%100,ptr+3,2,0,1,10,0,0);
if(cf->type=='t'){break;}
ptr[5]=':';
longtoascii((ltmp/100)%100,ptr+6,2,0,1,10,0,0);
break;
case 'f':
ltmp=*(UL*)cf->dest;
longtoascii(ltmp>>16,ptr,4,0,1,16,0,0);
ptr[4]=':';
longtoascii(ltmp, ptr+5,4,0,1,16,0,0);
break;
case 'F':
ltmp=*(UL*)cf->dest;
itmp=*(UI*)(cf->dest+4);
longtoascii(itmp,ptr,4,0,1,16,0,0);
ptr[4]=':';
longtoascii(ltmp, ptr+5,8,0,1,16,0,0);
break;
case 'h':
for(n=0;nw/2;n++)
{
longtoascii(ptr1[n],ptr+2*n,2,0,1,16,0,0);
}
break;
case 'H':
for(n=0;nw/3;n++)
{
longtoascii(ptr1[n],ptr+3*n,2,0,1,16,0,0);
ptr[2+3*n]=0x20;
}
break;
case '?':
memset(ptr,'?',cf->w);
default:
break;
}
(*A->putstrn)(A->usr,ptr,cf->row,cf->col,cf->w);
cf++;
}
if(A->switchframe)
{
(*A->switchframe)(A->usr);
}
if(!disp){goto escape;}
// MAIN edit loop
dvblit();
cf=field; //start in home field
while(1)
{
ret=fieldedit(A,cf,&curpos);
switch(ret)
{
case ENTER:
case NUMENTER:
goto update;
case (CTRL|ALT|F12):
return_code=ret;goto escape;
case ESC:
return_code=-1; goto escape;
case BADARG:
goto ARGERR;
case NRCUR:
case TAB :
cf++;curpos=0;break;
case NLCUR:
case BACKSPACE :
cf--;curpos=4000;break;
case SHIFTTAB:
cf--;curpos=0;break;
case NHOME:
cf=field;curpos=0;break;
case NEND:
cf=field+fields-1;curpos=0;break;
case NDCUR:
cf+=field_array[cf->isarray-1].width;break;
case NUCUR:
cf-=field_array[cf->isarray-1].width;break;
default:
sound_beep(500);
}
}
update:
cf=field;
for(m=0;mshadow;
ptr1=cf->dest;
switch(cf->type)
{
case 's':
memcpy(ptr1,ptr,cf->w);
break;
case 'a':
memcpy(ptr1+1,ptr,cf->w);
break;
case '&':
//after all that, accept to an address is not really valid!
break;
case 'X':
case 'l':
if(cf->sign)
{*(SL*)ptr1=strtol (ptr,&dptr,cf->base);}
else{*(UL*)ptr1=strtoul(ptr,&dptr,cf->base);}
break;
case 'P':
if(cf->sign)
{*(UM*)ptr1=strtol (ptr,&dptr,cf->base);}
else{*(UM*)ptr1=strtoul(ptr,&dptr,cf->base);}
break;
case 'p':
if(cf->sign)
{*(Um*)ptr1=strtol (ptr,&dptr,cf->base);}
else{*(Um*)ptr1=strtoul(ptr,&dptr,cf->base);}
break;
case 'x':
case 'i':
if(cf->sign)
{*(SI*)ptr1=strtol (ptr,&dptr,cf->base);}
else{*(UI*)ptr1=strtoul(ptr,&dptr,cf->base);}
break;
case 'c':
*(CH*)ptr1=strtol(ptr,&dptr,cf->base);break;
case 'd':
*(DB*)ptr1=atof(ptr);break;
case 'v':
SL l; //not right for IPOS yet
UL divisor;
divisor=cf->base;
l=cf->dec_digits;
while(--l)
{
divisor*=cf->base;
}
if(cf->sign&1){l=strtol(cf->shadow+1,&dptr,cf->base);}
else {l=strtol(cf->shadow,&dptr,cf->base);}
if(*cf->shadow=='-'){l=-l;}
ptr=cf->shadow+cf->digits;
if(cf->sign){*ptr=*cf->shadow;} //shove sign or zero into
else {*ptr='0';} //point space to correctly
l*=divisor; //evaluate fractional part
l+=strtol(ptr,&dptr,cf->base); //e.g.-005 or 0005
*(SL*)ptr1=l;break;
case 'D':
ul =(UL)atol(cf->shadow);
ul+=(UL)atol(cf->shadow+3)*100;
ul+=(UL)atol(cf->shadow+6)*10000;
if(ul)//if non-zero date convert to Millennium format
{ //i.e. if year < 1980, assume 21st century
if ((ul/10000)<80){ul+=20000000;}
else {ul+=19000000;}
}
if(cf->sign) //%+D format string UL date
{
*(UL*)cf->dest=(UL)ul;
}
else //%D format string for UQ date
{
*(UM*)cf->dest=(UL)ul;
}
break;
case 'M':
if(cf->sign)
{
*(UL*)cf->dest =(UL)atol(cf->shadow);
*(UL*)cf->dest+=(UL)atol(cf->shadow+3)*100;
*(UL*)cf->dest+=(UL)atol(cf->shadow+6)*10000;
}
else
{
*(UM*)cf->dest =(UL)atol(cf->shadow);
*(UM*)cf->dest+=(UL)atol(cf->shadow+3)*100;
*(UM*)cf->dest+=(UL)atol(cf->shadow+6)*10000;
}
break;
case 't':
l =atoi(ptr)*100;
l+=atoi(ptr+3);
l*=10000;
if(cf->sign)
{
*(UL*)ptr1=l;
}
else
{
*(UM*)ptr1=l;
}
break;
case 'f':
*(UL*)ptr1 =((UL)strtol(ptr,&dptr,16))<<16;
*(UL*)ptr1+=((UL)strtol(ptr+5,&dptr,16));
break;
case 'F':
*(UI*)(ptr1+4)=((UL)strtol (ptr,&dptr,16));
*(UL*)ptr1 =((UL)strtoul(ptr+5,&dptr,16));
break;
case 'h':
for(n=cf->w/2;n>=0;)
{
ptr[n*2]=0;n--;
ptr1[n]=strtoul(ptr+2*n,&dptr,cf->base);
}
break;
case 'H':
for(n=0;nw/3;n++)
{
ptr1[n]=strtoul(ptr+3*n,&dptr,cf->base);
}
break;
default:
break;
}
cf++;
}
return_code=0;
escape:
cf=field;
for(n=0;nshadow!=NULL){free(cf->shadow);}
cf++;
}
if(field_array!=NULL){free(field_array);}
if(field!=NULL){free(field);}
(*A->setfgd)(A->usr,7);(*A->setbgd)(A->usr,0);
// (*A->setcursiz)(A->usr,0x0607); //normal cursor
// (*A->setcursiz)(A->usr,0x0000); //hide cursor
A->row=row;
A->col=col;
inaccdis--;
A->fgd=fgdsav;
A->bgd=bgdsav;
// A->row=rowsav;
// A->col=colsav;
accdisarrayinc=1;
return return_code;
ARGERR:
(*A->putstr)(A->usr,"Unknown type specifier in format string",0,0);
return_code=-1;goto escape;
MEMERR:
(*A->putstr)(A->usr,"Out of memory for Accept/Display",0,0);
return_code=-1;goto escape;
}
// KEYCALLBACK keycallback;
// VD* keycallbackuserptr;
//VD accdis_setkeycallback(VD* callbackfunc,VD* ptr)
VD accdis_setkeycallback(KEYCALLBACK callbackfunc,VD* ptr)
{
AA->callback=callbackfunc;
AA->callbackuserptr=ptr;
}
//UI getkey(UI* key,CH* c,UI row,UI col)
//{
// while(!_bios_keybrd(_NKEYBRD_READY)){(*AA->idle)();}
// *key=_bios_keybrd(_NKEYBRD_READ);
// *c=*key;
// if(keycallback!=NULL){keycallback(*key,row,col,keycallbackuserptr);}
// return *key;
//}
//supplementary list functions
SL selectlist (CH* str,UL recsize,UL displen,UL items,UL row,UL col,UL visibles,UL scroll)
{
UL visibleoffset=0;
if(visibles>items) {visibles=items;} //poss clip to screen here
if(scroll>visibles) {scroll=visibles;}
UL current=0;
UL key,ret;
CH* startstring;
CH c;
L01:
startstring=str+(visibleoffset*recsize);
displaylist(startstring,recsize,displen,visibles,row,col,0);
highlightlistitem(current,startstring,recsize,displen,row,col);
switch(key=dgetkey()&0xffff)
{
case ESC: ret=-1;goto OUT;
case ENTER:
case NUMENTER:ret=current+visibleoffset;goto OUT;
case NUCUR:
if(current){current--;}
else
{
if(visibleoffset>=scroll)
{visibleoffset-=scroll;current+=scroll;current--;}
else if(visibleoffset)
{current=visibleoffset-1;visibleoffset=0;}
else{sound_beep(500);}
}
break;
case NDCUR:
if(currentvisibleoffset+visibles+scroll)
{visibleoffset+=scroll;current-=scroll;current++;}
else if((visibleoffset==items-visibles)&(current==visibles-1))
{sound_beep(500);}
else{visibleoffset=items-visibles;current=0;}
}
break;
case NPGUP:
if(visibleoffset>=scroll)
{visibleoffset-=scroll;}
else {goto H1;}
break;
case NPGDN:
if(items-1>visibleoffset+visibles+scroll)
{visibleoffset+=scroll;}
else {goto E1;}
break;
case NHOME:
H1:
if(visibleoffset|current)
{visibleoffset=current=0;}
else{sound_beep(500);}
break;
case NEND:
E1:
if((visibleoffset==items-visibles)&(current==visibles-1))
{sound_beep(500);}
else{visibleoffset=items-visibles;current=visibles-1;}
break;
default:
c=key;
if(c>=0x61&c<=0x7a){c-=0x20;}
CH* ptr=str;
UL n=0;UL m;
while(n=items)
{m=visibleoffset+visibles-items;
visibleoffset-=m;current=m;
}
goto L01;
}
ptr+=recsize;
n++;
}
sound_beep(500);
}
goto L01;
OUT:
unhighlightlistitem(current,startstring,recsize,displen,row,col);
return ret;
}
VD displaylist(CH* str,UL recsize,UL displen,UL items,UL row,UL col,UL offset)
{
UL n;
CH* ptr=str+(offset*recsize);
for(n=0;ndest;
DB* dptr;
CH* ptr;
switch(f->type)
{
case 'd':
ptr=f->dest;
dptr=(DB*)ptr;
doubletoascii(dptr,f->shadow,f->w,f->dec_digits,f->sign,f->zerofill);
return;
// goto OUT;
// doubletoascii(d,f->shadow,f->w,f->dec_digits,f->sign,f->zerofill);
case '&':
l=(SL)f->dest;break;
case 'P':
l=*(UM*)iptr;break;
case 'p':
l=(SI)*(Um*)iptr;break;
case 'X':
case 'l':
case 'v':
if(f->sign)
{l= *(SL*)iptr;}
else{l= *(UL*)iptr;}
break;
case 'x':
case 'i':
if(f->sign)
{l= *(SI*)iptr;}
else{l= *(UI*)iptr;}
break;
case 'c':
if(f->sign)
{l= *(SC*)iptr;}
else{l= *(UC*)iptr;}
break;
case 'V': //capital V type suppresses zero 0.00 display
if(f->sign)
{l= *(SL*)f->dest;}
else{l= *(UL*)f->dest;}
if(!l)
{
return;
}
break;
case 'Z': //upper case Z type prints Nil for zero
if(f->sign)
{l= *(SL*)f->dest;}
else{l= *(UL*)f->dest;}
if(!l)
{
memcpy(&f->shadow[f->w-4],"Nil",3);
return;
}
break;
default:
return;
}
longtoascii(l,f->shadow,f->w,f->sign,f->zerofill,f->base,f->dec_digits,0);
if(f->type=='&'){f->shadow[1]='x';} //cobbler 0x notation for new type '&'
OUT:
l++;
}
VD longtoascii(UL longint,CH* buf,UL digits,UL sign,
UL zerofill,UL base,UL dec_digits,UL shift)
{
UL n,minus=0,fw=digits;
CH fill=' ';
if(zerofill){fill='0';}
if(sign&2)
{//bracketed signed number:subtract one digit for ')'
digits--;
}
if(sign&4)
{//reverse sign before display
longint=-longint;
}
if(sign)
{
digits--; //make room for '+','-',or '('
if(longint&0x8000000)
{
longint=-longint;
minus=1;
}
}
CH digit=0;
while(digits)
{
if(longint==0)
{
if(digit)
{
digit=fill;
}
else
{
digit=0x30; //force at least one zero to
} //be displayed
}
else
{
digit=longint%base;
if(digit>9){digit+=0x57;}
else {digit+=0x30;}
}
buf[digits+(sign&1)-1]=digit;
longint/=base;
if(dec_digits)
{
dec_digits--;
digit=0;
if(!dec_digits)
{
digits--;
buf[digits+(sign&1)-1]='.';
}
}
if(digits){digits--;}
}
switch(sign)
{
case 1:
if(minus){digit='-';}
else {digit='+';}
buf[0]=digit;
break;
case 3:
if(minus)
{
buf[0] ='(';
buf[fw-1]=')';
}
else
{
buf[0] =' ';
buf[fw-1]=' ';
}
break;
}
}
//VD doubletoascii(DB* d,CH* buf,UL fw,UL dec_digits,UL sign,UL zerofill)
//{
// UL sig,lsig,shift,integer,fraction,idigits,carry;
// UL digits=fw-(dec_digits+1);
// CH fill=' ';
// memset(buf,0x20,fw+1);
// buf[digits]='.';
// if(sign){digits--;}
// UC digit=0;
// UC* ptr=(UC*)d;
// SL asign=((*(ptr+7))&0x80)>>7;
// if(sign)
// {
// if(asign)
// {buf[0]='-';}
// else{buf[0]='+';}
// }
// SL exp= *(SL*)(ptr+4);
// exp>>=20;
// exp&=0x7ff; //mask off sign bit
// if(!exp)
// { //it's a zero
// buf[sign+digits+1]=buf[sign+digits-1]='0';
// }
// else{exp-=0x3ff;
// sig= *(SL*)(ptr+4);
// sig<<=12;
// sig>>=1; //get 20 bits from top of significand
// sig|=0x80000000; //add 21st hidden bit
// lsig= *(SL*)(ptr);
// lsig>>=21; //get 11 bits from bottom of significand
// sig|=lsig; //most significant 32 bits in sig
//
// if(exp>=0) //branch now to handle positive and negative
// { //exponents
// fraction=-1;
// fraction<<=exp+1;
// fraction>>=exp+1; //knock off top (hidden) bit
// fraction&=sig;
// fraction>>=3;
// shift=exp;
// fraction<<=shift;
// shift=31-exp;
// integer=sig>>shift;
// }
// else
// {
// shift=-exp;
// integer=0;
// fraction=sig>>(shift+3);
// }
// idigits=digits;
// if(zerofill){fill='0';}
// while(idigits)
// {
// if(integer==0)
// {
// if(digit)
// {
// digit=fill;
// }
// else
// {
// digit=0x30; //force at least one zero to
// } //be displayed
// }
// else
// {
// digit=integer%10;
// digit+=0x30;
// }
// buf[idigits+sign-1]=digit;
// integer/=10;
// idigits--;
// }
//
// while(dec_digits)
// {
// fraction*=10;
// digit=fraction>>28;
// fraction&=0xfffffff;
// buf[sign+1+digits++]=digit+0x30;
// dec_digits--;
// }
// if(fraction)
// {
// fraction*=10;
// digit=fraction>>28;
// if(digit>=5)
// {
// carry=1;
// digits=fw-sign;
// while(digits)
// {
// buf[digits]+=carry;
// if(buf[digits]==0x3a)
// {
// buf[digits]=0x30;
// carry=1;
// }
// else
// {
// carry=0;
// }
// digits--;
// if(buf[digits]=='.'){digits--;}
// }
// }
// }
// }
//}
VD doubletoascii(DB* d,CH* buf,UL fw,UL dec_digits,UL sign,UL zerofill)
{
UL sig,lsig,shift,integer,fraction,fr,idigits,carry;
UL digits=fw-(dec_digits+1);
CH fill=' ';
memset(buf,0x20,fw+1);
buf[digits]='.';
if(sign){digits--;}
UC digit=0;
UC* ptr=(UC*)d;
SL asign=((*(ptr+7))&0x80)>>7;
if(sign)
{
if(asign)
{buf[0]='-';}
else{buf[0]='+';}
}
SL exp= *(SL*)(ptr+4);
exp>>=20;
exp&=0x7ff; //mask off sign bit
if(!exp)
{ //it's a zero
buf[sign+digits+1]='0';
buf[sign+digits-1]='0';
}
else{exp-=0x3ff;
sig= *(SL*)(ptr+4);
sig<<=12;
sig>>=1; //get 20 bits from top of significand
sig|=0x80000000; //add 21st hidden bit
lsig= *(SL*)(ptr);
lsig>>=21; //get 11 bits from bottom of significand
sig|=lsig; //most significant 32 bits in sig
if(exp>=0) //branch now to handle positive and negative
{ //exponents
fraction=-1;
fraction<<=exp+1;
fraction>>=exp+1; //knock off top (hidden) bit
fraction&=sig;
fraction>>=3;
shift=exp;
fraction<<=shift;
shift=31-exp;
integer=sig>>shift;
}
else
{
shift=-exp;
integer=0;
fraction=sig>>(shift+3);
}
idigits=digits;
if(zerofill){fill='0';}
while(idigits)
{
if(integer==0)
{
if(digit)
{
digit=fill;
}
else
{
digit=0x30; //force at least one zero to
} //be displayed
}
else
{
digit=integer%10;
digit+=0x30;
}
buf[idigits+sign-1]=digit;
integer/=10;
idigits--;
}
fr=fraction;
while(dec_digits)
{
fraction*=10;
digit=fraction>>28;
fraction&=0xfffffff;
// buf[sign+1+digits++]=digit+0x30;
buf[sign+1+digits]=digit+0x30;
digits++;
dec_digits--;
}
if(fraction)
{//round fractional values up for display, e.g. 0.99999995
//becomes 1.00000000
fraction*=10;
digit=fraction>>28;
if(digit>=5)
{
carry=1;
digits=fw-sign;
while(digits)
{
if(buf[digits+sign-1]==0x20)
{//change leading space to zero before adding carry
//otherwise 9.9999995 becomes !0.0000000
buf[digits+sign-1]=0x30;
}
buf[digits+sign-1]+=carry;
if(buf[digits+sign-1]==0x3a)
{
buf[digits+sign-1]=0x30;
carry=1;
}
else
{
carry=0;
break;
}
digits--;
if(buf[digits+sign-1]=='.'){digits--;}
}
}
}
}
}
#pragma breakpoints off
//Function set for CGA, MDA and VGA text modes////////////////////////
// mdaset(0)=MDA
// mdaset(1)=CGA
// mdaset(2)=VGA
// mdaset(3)=VGA text 50-lines
VD mdaclear(VD)
{
// _clearscreen(_GCLEARSCREEN);
memset16(AA->mem,0x0720,50*AA->rows);
mdasetcurpos(AA->usr,0,0);
}
VD mdaclear(UL rows)
{
memset16(AA->mem,0x0720,50*rows);
mdasetcurpos(AA->usr,0,0);
}
VD mdacurb(UL row,UL col)
{
mdasetcurpos(AA->usr,row,col);
}
VD mdaread (CH* dst,UL row,UL col,UL n)
{
CH* ptr=AA->mem+((row*AA->cpl+col)*2);
while(n--)
{
*dst++=*ptr++;
ptr++;
}
*dst=0;
}
VD mdasave (CH* dst,UL row,UL col,UL n)
{
CH* ptr=AA->mem+((row*AA->cpl+col)*2);
while(n--)
{
*dst++=*ptr++;
*dst++=*ptr++;
}
}
VD mdarestore (CH* src,UL row,UL col,UL n)
{
CH* ptr=AA->mem+((row*AA->cpl+col)*2);
while(n--)
{
*ptr++=*src++;
*ptr++=*src++;
}
}
EX SL clistartline;
EX SL cliendline;
EX SL clicur;
VD mdascroll(VD* usr)
{
CH* vptr=AA->mem+clistartline*160;
UL rows=cliendline-clistartline;
memmove(vptr,vptr+160,rows*160);
vptr=AA->mem+cliendline*160;
memset(vptr,0,160);
}
VD mdaprint(VD* usr,CH* str,UL row,UL col)
{
CH* ptr=AA->mem+((row*AA->cpl+col)*2);
CH colour=(AA->bgd<<4)+AA->fgd;
while(*str)
{
*ptr++=*str++;
*ptr++=colour;
}
}
VD mdaprin(VD* usr,CH* str,UL row,UL col,UL len)
{
CH* ptr=AA->mem+((row*AA->cpl+col)*2);
CH colour=(AA->bgd<<4)+AA->fgd;
while(len--)
{
*ptr++=*str++;
*ptr++=colour;
}
}
//#pragma 7
VD mdafgd(VD* usr,UL colour)
{
AA->fgd=colour;return;
if(AA==&cga){AA->fgd=colour;}
else {
switch(colour)
{
case 6: AA->fgd=7;break;
default:AA->fgd=7;break;
}
}
// _settextcolor(col);
}
VD mdabgd(VD* usr,UL colour)
{
AA->bgd=colour;return;
if(AA==&cga){AA->bgd=colour;}
else {
switch(colour)
{
case 6: AA->bgd=15;break;
case 4: AA->bgd=7;AA->fgd=0;break;
default:AA->bgd=0; break;
}
}
// _setbkcolor(col);
}
VD mdaputc(VD* usr,CH c,UL row,UL col)
{
UL n=AA->cpl*row;
n+=col;
n*=2;
n+=(UL)AA->mem;
CH* ptr=(CH*)n;
CH colour=(AA->bgd<<4);
colour+=AA->fgd;
*ptr++=c;
*ptr=colour;
}
VD mdasetcurpos(VD* usr,UL row,UL col)
{
AA->row=row;
AA->col=col;
// row%=25;
row*=AA->cpl;
row+=col;
UL port;
if(AA==&mda){port=0x3b4;}
else {port=0x3d4;}
#asm
cli
mov ecx,row
mov edx,port
mov al,0x0f
out dx,al
mov al,cl
inc dx
out dx,al
mov al,0x0e
dec dx
out dx,al
shr ecx,8
mov al,cl
inc dx
out dx,al
sti
#endasm
// _settextposition(row+1,col+1);
}
VD mdagetcurpos(UL* row,UL* col)
{
UL port,addr;
if(AA==&mda){port=0x3b4;}
else {port=0x3d4;}
asm{
cli
sub eax,eax
mov ecx,0
mov edx,port
mov al,0x0f
out dx,al
mov al,cl
inc dx
in al,dx
mov cl,al
mov al,0x0e
dec dx
out dx,al
inc dx
in al,dx
mov ah,al
mov al,cl
mov addr,eax
sti
}
*col=addr%AA->cpl;
*row=addr/AA->cpl;
}
VD mdasetcursiz(VD* usr,UL val)
{
UL port;
if(AA==&mda){port=0x3b4;}
else {port=0x3d4;}
#asm
cli
mov ecx,val
mov edx,port
mov al,0x0b
out dx,al
mov al,cl
inc dx
out dx,al
mov al,0x0a
dec dx
out dx,al
shr ecx,8
mov al,cl
inc dx
out dx,al
sti
#endasm
}
//membuf ACCDIS support
//SL ctprintf(CH* buf,CH* format,...)
//{
// mem.mem=buf;
// return vaccept(&mem,mem.row,mem.col,format,0,&format+1); //watch
//}
VD memscroll(VD* usr)
{
}
VD memprint(VD* usr,CH* str,UL row,UL col)
{
ACCDIS* a=(ACCDIS*)usr;
CH* ptr=a->mem+(a->bpc*(row*a->cpl+col));
while(*str)
{
*ptr++=*str++;
if(a->bpc==2){*ptr++=(a->bgd<<4)|(a->fgd&0x0f);}
}
}
VD memprin(VD* usr,CH* str,UL row,UL col,UL len)
{
ACCDIS* a=(ACCDIS*)usr;
CH* ptr=a->mem+(a->bpc*(row*a->cpl+col));
while(len--)
{
*ptr++=*str++;
if(a->bpc==2){*ptr++=(a->bgd<<4)|(a->fgd&0x0f);}
}
}
VD memputc(VD* usr,CH c,UL row,UL col)
{
ACCDIS* a=(ACCDIS*)usr;
CH* ptr=a->mem+(a->bpc*(row*a->cpl+col));
*ptr=c;
if(a->bpc==2){ptr++;*ptr=(a->bgd<<4)|(a->fgd&0x0f);}
}
VD memsetcurpos(VD* usr,UL row,UL col)
{
ACCDIS* a=(ACCDIS*)usr;
a->row=row;
a->col=col;
}
VD memsetcursiz(VD* usr,UL val)
{
}
VD memfgd(VD* usr,UL val)
{
}
VD membgd(VD* usr,UL val)
{
}
//vmem buffer ACCDIS support
VD vmemscroll(VD* usr)
{
}
VD vmemprint(VD* usr,CH* str,UL row,UL col)
{
CH* ptr=vmem.mem+((row*vmem.cpl+col)*vmem.bpc);
CH colour=(vmem.bgd<<4)+vmem.fgd;
while(str)
{
*ptr++=*str++;
*ptr++=colour;
}
}
VD vmemprin(VD* usr,CH* str,UL row,UL col,UL len)
{
CH* ptr=vmem.mem+((row*vmem.cpl+col)*vmem.bpc);
CH colour=(vmem.bgd<<4)+vmem.fgd;
while(len--)
{
*ptr++=*str++;
*ptr++=colour;
}
}
VD vmemputc(VD* usr,CH c,UL row,UL col)
{
CH* ptr=vmem.mem+((row*vmem.cpl+col)*vmem.bpc);
CH colour=(vmem.bgd<<4)+vmem.fgd;
*ptr++=c;
*ptr=colour;
}
VD vmemsetcurpos(VD* usr,UL row,UL col)
{
vmem.row=row;
vmem.col=col;
}
VD vmemsetcursiz(VD* usr,UL val)
{
}
VD vmemfgd(VD* usr,UL val)
{
vmem.fgd=val;
}
VD vmembgd(VD* usr,UL val)
{
vmem.bgd=val;
}