1878 lines
35 KiB
C++
1878 lines
35 KiB
C++
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Pull-Down Menu Interface
|
|
// by John Romero (C) 1991 Id Software
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
#include "ted5.h"
|
|
#pragma hdrstop
|
|
|
|
#define NUMFLASHES 10
|
|
#define ALT 0x38
|
|
#define CTRL 0x1d
|
|
|
|
#define CGASIZE 0x4000
|
|
#define EGA1SIZE 0x2000
|
|
#define EGA2SIZE 0x9600
|
|
#define EGA3SIZE 60000
|
|
#define VGASIZE 64000
|
|
|
|
void (*HookRoutine)(int x,int y);
|
|
void (*ItemRoutine)(void);
|
|
char MenuStr[20][80],tempstr[80];
|
|
memptr Background[10];
|
|
int WhichBack;
|
|
struct { int savex,savey,savew,saveh; } Back[10];
|
|
MBarDef *MBarPtr;
|
|
MInfoType MenuInfo[10];
|
|
int ScreenWidth,OpenMenu,NumMenus,ItemOn,KeybdOn;
|
|
|
|
void HandleOpenMenu(void (*UserRoutine)(void),int which);
|
|
void HandleCloseMenu(void (*UserRoutine)(void));
|
|
void HandleHighlight(void (*UserRoutine)(void));
|
|
int DetectMenu(int x,int y);
|
|
void ChangeItem(int newitem);
|
|
void ClearScreen(void);
|
|
void RedrawDesktop(void);
|
|
char *PassScancode(int sc);
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Desktop Event Loop
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
void DeskEventLoop(void (*UserRoutine)(void),void (*ConstantRoutine)(void))
|
|
{
|
|
int buttonstatus=0,oldmenu,olditem;
|
|
enum clicks {upup,updown,downup,downdown};
|
|
|
|
if (KeybdOn)
|
|
{
|
|
HandleOpenMenu(UserRoutine,2);
|
|
ChangeItem(1);
|
|
}
|
|
|
|
MouseShow();
|
|
while(1)
|
|
{
|
|
int temp=MouseButton()&1,temp1=(MouseButton()>>1)&1;
|
|
|
|
sx=0;
|
|
sy=3;
|
|
|
|
if (!OpenMenu)
|
|
ConstantRoutine();
|
|
switch(buttonstatus=((buttonstatus<<1)|temp|temp1)&3)
|
|
{
|
|
case upup: break;
|
|
case updown: HandleOpenMenu(UserRoutine,0);
|
|
break;
|
|
case downdown: HandleHighlight(UserRoutine);
|
|
break;
|
|
case downup: HandleCloseMenu(UserRoutine);
|
|
if (ItemOn && ItemRoutine)
|
|
ItemRoutine();
|
|
ItemOn=0;
|
|
break;
|
|
}
|
|
|
|
if (bioskey(1))
|
|
{
|
|
char key=bioskey(1)>>8;
|
|
int nitems;
|
|
|
|
if (OpenMenu)
|
|
{
|
|
bioskey(0);
|
|
|
|
nitems=(MBarPtr+OpenMenu-1)->num_items;
|
|
|
|
switch(key)
|
|
{
|
|
case 0x48: if (OpenMenu)
|
|
if (ItemOn)
|
|
if (ItemOn==1)
|
|
ChangeItem(nitems);
|
|
else
|
|
ChangeItem(ItemOn-1);
|
|
break;
|
|
case 0x50: if (OpenMenu)
|
|
if (ItemOn)
|
|
if (ItemOn==nitems)
|
|
ChangeItem(1);
|
|
else
|
|
ChangeItem(ItemOn+1);
|
|
break;
|
|
case 0x1c: oldmenu=OpenMenu;
|
|
olditem=ItemOn;
|
|
HandleCloseMenu(UserRoutine);
|
|
if (ItemOn)
|
|
ItemRoutine();
|
|
|
|
break;
|
|
case 0x4b: if (OpenMenu)
|
|
{
|
|
int newmenu;
|
|
|
|
ItemOn=0;
|
|
if (OpenMenu==1)
|
|
newmenu=NumMenus;
|
|
else
|
|
newmenu=OpenMenu-1;
|
|
|
|
HandleCloseMenu(UserRoutine);
|
|
HandleOpenMenu(UserRoutine,newmenu);
|
|
|
|
ChangeItem(1);
|
|
}
|
|
break;
|
|
case 0x4d: if (OpenMenu)
|
|
{
|
|
int newmenu;
|
|
|
|
ItemOn=0;
|
|
if (OpenMenu==NumMenus)
|
|
newmenu=1;
|
|
else
|
|
newmenu=OpenMenu+1;
|
|
|
|
HandleCloseMenu(UserRoutine);
|
|
HandleOpenMenu(UserRoutine,newmenu);
|
|
|
|
ChangeItem(1);
|
|
}
|
|
break;
|
|
case 0x01: if (!OpenMenu)
|
|
{
|
|
HandleOpenMenu(UserRoutine,oldmenu);
|
|
ChangeItem(olditem);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int i,j,numitems,run=0;
|
|
MenuDef *items;
|
|
|
|
for (i=0;i<NumMenus;i++)
|
|
{
|
|
numitems=(MBarPtr+i)->num_items;
|
|
items=(MBarPtr+i)->menu_def;
|
|
|
|
for (j=0;j<numitems;j++)
|
|
if ((items+j)->hotkey==key && (items+j)->hotkey)
|
|
{
|
|
if (((items+j)->shiftflag) &&
|
|
(!keydown[(items+j)->shiftflag]))
|
|
continue;
|
|
|
|
ItemRoutine=(items+j)->routine;
|
|
ItemRoutine();
|
|
run=1;
|
|
break;
|
|
}
|
|
if (run)
|
|
{
|
|
if (bioskey(1))
|
|
bioskey(0);
|
|
break;
|
|
}
|
|
}
|
|
if (!run)
|
|
UserRoutine();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// See if a menu was opened
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
void HandleOpenMenu(void (*UserRoutine)(void),int which)
|
|
{
|
|
int x,y,loop,flag,tempx,tempw,maxw,loopsize;
|
|
MenuDef *items;
|
|
|
|
if (!which)
|
|
{
|
|
MouseCoords(&x,&y);
|
|
if (y>8 && !OpenMenu)
|
|
{
|
|
UserRoutine();
|
|
return;
|
|
}
|
|
|
|
flag=DetectMenu(x,y);
|
|
if (!flag) return;
|
|
}
|
|
else
|
|
flag=which;
|
|
|
|
|
|
tempx=MenuInfo[flag-1].menux;
|
|
tempw=MenuInfo[flag-1].menuwidth;
|
|
items=(MBarPtr+flag-1)->menu_def;
|
|
|
|
sx=tempx+1;
|
|
sy=0;
|
|
maxw=0;
|
|
|
|
MouseHide();
|
|
|
|
|
|
//
|
|
// BUILD MENU STRINGS
|
|
//
|
|
loopsize=(MBarPtr+flag-1)->num_items;
|
|
|
|
for (loop=0;loop<loopsize;loop++)
|
|
{
|
|
int len;
|
|
|
|
memset(MenuStr[loop],0,80);
|
|
|
|
MenuStr[loop][0]=4; // leftedge
|
|
strcat(MenuStr[loop],(items+loop)->item_name);
|
|
|
|
len=strlen(MenuStr[loop]);
|
|
memset(&MenuStr[loop][len],' ',tempw-len+1);
|
|
|
|
switch((items+loop)->shiftflag)
|
|
{
|
|
case ALT: strcat(MenuStr[loop]," ALT-"); break;
|
|
case CTRL:strcat(MenuStr[loop],"CTRL-");
|
|
}
|
|
|
|
strcat(MenuStr[loop],PassScancode((items+loop)->hotkey));
|
|
|
|
len=strlen(MenuStr[loop]);
|
|
if (len>maxw)
|
|
maxw=len;
|
|
}
|
|
|
|
if (tempx+maxw>ScreenWidth)
|
|
tempx=ScreenWidth-1-maxw;
|
|
SaveBackground(tempx*8,0,(maxw+1)*8,(MBarPtr+flag-1)->num_items*8+16);
|
|
|
|
//
|
|
// PRINT MENU STRINGS
|
|
//
|
|
xormask=0xffff;
|
|
print((MBarPtr+flag-1)->menu_name);
|
|
xormask=0;
|
|
|
|
for (loop=0;loop<loopsize;loop++)
|
|
{
|
|
int len;
|
|
|
|
len=strlen(MenuStr[loop]);
|
|
if (len<maxw)
|
|
memset(&MenuStr[loop][len],' ',maxw-len);
|
|
strcat(MenuStr[loop],"\x5");
|
|
|
|
sx=tempx;
|
|
sy=loop+1;
|
|
print(MenuStr[loop]);
|
|
}
|
|
|
|
sx=tempx;
|
|
sy=loopsize+1;
|
|
print("\x6");
|
|
bar(sx,sy,sx+maxw-2,sy,7);
|
|
sx=tempx+maxw;
|
|
print("\x8");
|
|
|
|
MouseShow();
|
|
OpenMenu=flag;
|
|
ItemOn=0;
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Detect whether a menu is clicked on or not
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
int DetectMenu(int x,int y)
|
|
{
|
|
int flag,loop;
|
|
|
|
if (y>10)
|
|
return 0;
|
|
|
|
flag=0;
|
|
for (loop=0;loop<NumMenus;loop++)
|
|
if (x/8>=MenuInfo[loop].menux && x/8<MenuInfo[loop].menux+MenuInfo[loop].menunamelen)
|
|
{
|
|
flag=loop+1;
|
|
break;
|
|
}
|
|
return flag;
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Highlight & De-highlight items
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
void HandleHighlight(void (*UserRoutine)(void))
|
|
{
|
|
int x,y,nitems,tempx,tempw,tempy,opmen;
|
|
|
|
if (!OpenMenu)
|
|
{
|
|
UserRoutine();
|
|
return;
|
|
}
|
|
|
|
MouseCoords(&x,&y);
|
|
nitems=(MBarPtr+OpenMenu-1)->num_items;
|
|
tempx=MenuInfo[OpenMenu-1].menux;
|
|
tempw=strlen(MenuStr[0])-5;
|
|
if (tempx+tempw+5>ScreenWidth)
|
|
tempx=ScreenWidth-tempw-5;
|
|
|
|
opmen=DetectMenu(x,y);
|
|
if (opmen && opmen!=OpenMenu)
|
|
{
|
|
OpenMenu=0;
|
|
RestoreBackground();
|
|
HandleOpenMenu(UserRoutine,0);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// IS USER IN A MENU?
|
|
//
|
|
|
|
if (x/8>tempx && x/8<tempx+tempw+4 && y>8 && y<(nitems+1)*8)
|
|
{
|
|
if (y/8==ItemOn)
|
|
return; // EXIT IF ON SAME ITEM
|
|
|
|
//
|
|
// IF AN ITEM IS CURRENTLY SELECTED, DEHIGHLIGHT IT
|
|
// AND HIGHLIGHT A NEW ITEM
|
|
//
|
|
|
|
ChangeItem(y/8);
|
|
}
|
|
else
|
|
//
|
|
// USER MOVED POINTER OUTSIDE OF MENU; DEHIGHLIGHT ITEM
|
|
//
|
|
|
|
if (ItemOn)
|
|
{
|
|
MouseHide();
|
|
|
|
sx=tempx;
|
|
sy=ItemOn;
|
|
print(MenuStr[ItemOn-1]);
|
|
|
|
ItemOn=0;
|
|
MouseShow();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Set new item highlighted
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
void ChangeItem(int newitem)
|
|
{
|
|
int tempx,tempw;
|
|
MenuDef *items;
|
|
char tempstr[80]="";
|
|
|
|
tempx=MenuInfo[OpenMenu-1].menux;
|
|
if (tempx+strlen(MenuStr[0])>ScreenWidth)
|
|
tempx=ScreenWidth-strlen(MenuStr[0]);
|
|
|
|
MouseHide();
|
|
if (ItemOn)
|
|
{
|
|
sx=tempx;
|
|
sy=ItemOn;
|
|
print(MenuStr[ItemOn-1]);
|
|
}
|
|
|
|
xormask=0xffff;
|
|
ItemOn=newitem;
|
|
strncpy(tempstr,&MenuStr[ItemOn-1][1],strlen(MenuStr[ItemOn-1])-2);
|
|
sx=tempx+1;
|
|
sy=ItemOn;
|
|
print(tempstr);
|
|
xormask=0;
|
|
|
|
MouseShow();
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// See if a menu was closed
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
void HandleCloseMenu(void (*UserRoutine)(void))
|
|
{
|
|
MenuDef *items;
|
|
int loop,tempx;
|
|
char tempstr[80]="";
|
|
|
|
if (!OpenMenu)
|
|
{
|
|
UserRoutine();
|
|
return;
|
|
}
|
|
|
|
if (ItemOn)
|
|
{
|
|
items=(MBarPtr+OpenMenu-1)->menu_def;
|
|
tempx=MenuInfo[OpenMenu-1].menux;
|
|
if (tempx+strlen(MenuStr[0])>ScreenWidth)
|
|
tempx=ScreenWidth-strlen(MenuStr[0]);
|
|
|
|
for (loop=0;loop<NUMFLASHES;loop++)
|
|
{
|
|
xormask^=0xffff;
|
|
MouseHide();
|
|
|
|
strncpy(tempstr,&MenuStr[ItemOn-1][1],strlen(MenuStr[ItemOn-1])-2);
|
|
sx=tempx+1;
|
|
sy=ItemOn;
|
|
print(tempstr);
|
|
|
|
MouseShow();
|
|
WaitVBL(3);
|
|
}
|
|
xormask=0;
|
|
ItemRoutine=(items+ItemOn-1)->routine;
|
|
}
|
|
|
|
OpenMenu=0;
|
|
RestoreBackground();
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Save the background
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
void SaveBackground(int x,int y,int w,int h)
|
|
{
|
|
long size;
|
|
unsigned loc,loop,loop1,seg,planelen;
|
|
|
|
Back[WhichBack].savex=x;
|
|
Back[WhichBack].savey=y;
|
|
Back[WhichBack].savew=w;
|
|
Back[WhichBack].saveh=h;
|
|
|
|
MouseHide();
|
|
switch (videomode)
|
|
{
|
|
case CGA:
|
|
MMAllocate(&Background[WhichBack],(w/4)*h);
|
|
|
|
for(loop=y;loop<y+h;loop++)
|
|
{
|
|
loc=(loop/2)*80+0x2000*(loop&1)+x/4;
|
|
movedata(0xb800,loc,(unsigned)Background[WhichBack],(loop-y)*(w/4),w/4);
|
|
}
|
|
break;
|
|
|
|
case EGA2:
|
|
case EGA1:
|
|
{
|
|
unsigned tempw=w/8,tempx=x/8,psize;
|
|
|
|
planelen=tempw*h;
|
|
MMAllocate(&Background[WhichBack],5L*planelen);
|
|
outport(GCindex,GCmode);
|
|
for (loop=0;loop<4;loop++)
|
|
{
|
|
psize=loop*planelen;
|
|
|
|
outport(GCindex,GCreadmap | loop*256);
|
|
for (loop1=y;loop1<y+h;loop1++)
|
|
movedata(0xa000,((unsigned)loop1*ScreenWidth)+tempx,
|
|
((unsigned)Background[WhichBack])+(psize/16),
|
|
(psize&15)+((loop1-y)*tempw),tempw);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case VGA:
|
|
MMAllocate(&Background[WhichBack],(long)w*h);
|
|
for(loop=y;loop<y+h;loop++)
|
|
movedata(0xa000,loop*320+x,(unsigned)Background[WhichBack],(loop-y)*w,w);
|
|
}
|
|
MouseShow();
|
|
if (WhichBack<10)
|
|
WhichBack++;
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Restore the background
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
void setfarmem(char huge *mem,unsigned char val,unsigned len)
|
|
{
|
|
int i;
|
|
for (i=0;i<len;i++)
|
|
*(mem+i)=val;
|
|
}
|
|
|
|
void RestoreBackground(void)
|
|
{
|
|
long size;
|
|
unsigned loc,loop1,x,y,w,h,loop,planelen;
|
|
|
|
if (!Back[WhichBack-1].savex &&
|
|
!Back[WhichBack-1].savey &&
|
|
!Back[WhichBack-1].savew &&
|
|
!Back[WhichBack-1].saveh)
|
|
Quit("Can't RestoreBackground with no information!");
|
|
|
|
x=Back[WhichBack-1].savex;
|
|
y=Back[WhichBack-1].savey;
|
|
w=Back[WhichBack-1].savew;
|
|
h=Back[WhichBack-1].saveh;
|
|
|
|
MouseHide();
|
|
switch (videomode)
|
|
{
|
|
case CGA:
|
|
for(loop=y;loop<y+h;loop++)
|
|
{
|
|
loc=(loop/2)*80+0x2000*(loop&1)+x/4;
|
|
movedata((unsigned)Background[WhichBack-1],(loop-y)*(w/4),0xb800,loc,w/4);
|
|
}
|
|
break;
|
|
|
|
case EGA2:
|
|
case EGA1:
|
|
planelen=(w/8)*h;
|
|
outport(GCindex,GCmode);
|
|
for (loop=0;loop<4;loop++)
|
|
{
|
|
outport(SCindex,SCmapmask | (1<<loop)*256);
|
|
for (loop1=y;loop1<y+h;loop1++)
|
|
movedata(((unsigned)Background[WhichBack-1])+((loop*planelen)/16),
|
|
((loop*planelen)&15)+(loop1-y)*(w/8),
|
|
0xa000,loop1*ScreenWidth+x/8,w/8);
|
|
}
|
|
break;
|
|
|
|
case VGA:
|
|
for(loop=y;loop<y+h;loop++)
|
|
movedata((unsigned)Background[WhichBack-1],(loop-y)*w,0xa000,loop*320+x,w);
|
|
}
|
|
|
|
MMFreePtr(&Background[WhichBack-1]);
|
|
|
|
MouseShow();
|
|
|
|
WhichBack--;
|
|
Back[WhichBack].savex=0;
|
|
Back[WhichBack].savey=0;
|
|
Back[WhichBack].savew=0;
|
|
Back[WhichBack].saveh=0;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Draw the Desktop
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
void RedrawDesktop(void)
|
|
{
|
|
int flag,count,i;
|
|
|
|
ClearScreen();
|
|
|
|
sx=sy=0;
|
|
bar(0,0,ScreenWidth-1,0,' ');
|
|
|
|
flag=0;
|
|
count=0;
|
|
NumMenus=0;
|
|
while((MBarPtr+count)->num_items && !flag)
|
|
{
|
|
int len,max_width,loop;
|
|
MenuDef *the_item;
|
|
char string[80];
|
|
|
|
//
|
|
// First, determine xcoord & namewidth & print
|
|
//
|
|
|
|
strcpy(string,(MBarPtr+count)->menu_name);
|
|
len=strlen(string);
|
|
MenuInfo[NumMenus].menux=sx;
|
|
MenuInfo[NumMenus].menunamelen=len+2;
|
|
if (len+sx>ScreenWidth-1)
|
|
{
|
|
string[ScreenWidth-1-sx]=0;
|
|
MenuInfo[NumMenus].menunamelen=ScreenWidth-1-sx;
|
|
MenuInfo[NumMenus].menux=ScreenWidth-MenuInfo[NumMenus].menunamelen;
|
|
flag++;
|
|
}
|
|
|
|
drawchar(sx++,sy,' ');
|
|
print(string);
|
|
drawchar(sx++,sy,' ');
|
|
|
|
//
|
|
// Now, figure out length of widest item
|
|
//
|
|
|
|
max_width=0;
|
|
the_item=(MBarPtr+count)->menu_def;
|
|
|
|
for (loop=0;loop<(MBarPtr+count)->num_items;loop++)
|
|
{
|
|
int len;
|
|
|
|
len=strlen((the_item+loop)->item_name);
|
|
if (len>max_width)
|
|
max_width=len;
|
|
}
|
|
|
|
MenuInfo[NumMenus].menuwidth=max_width+1;
|
|
|
|
count++;
|
|
NumMenus++;
|
|
}
|
|
|
|
//
|
|
// clear bottom line of menubar
|
|
//
|
|
switch(videomode)
|
|
{
|
|
case CGA:
|
|
{
|
|
unsigned huge *CGAmem=MK_FP(0xb800,240+0x2000);
|
|
for(i=0;i<40;i++)
|
|
*(CGAmem+i)=0;
|
|
}
|
|
break;
|
|
case EGA1:
|
|
case EGA2:
|
|
{
|
|
char huge *EGAmem=MK_FP(0xa000,0);
|
|
outport(GCindex,GCmode);
|
|
outport(SCindex,0x0f00 | SCmapmask);
|
|
for (i=0;i<ScreenWidth;i++)
|
|
*(EGAmem+7*ScreenWidth+i)=0;
|
|
}
|
|
break;
|
|
case VGA:
|
|
{
|
|
unsigned huge *VGAmem=MK_FP(0xa000,320*7);
|
|
for (i=0;i<160;i++)
|
|
*(VGAmem+i)=0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Init Desktop
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
void InitDesktop(MBarDef *menubar,int initmouse)
|
|
{
|
|
switch(videomode)
|
|
{
|
|
case CGA: ScreenWidth=40; break;
|
|
case EGA1: ScreenWidth=40; break;
|
|
case EGA2: ScreenWidth=80; break;
|
|
case VGA: ScreenWidth=40;
|
|
}
|
|
|
|
MBarPtr=menubar;
|
|
RedrawDesktop();
|
|
if (initmouse)
|
|
MouseInit();
|
|
OpenMenu=KeybdOn=0;
|
|
if (!MouseStatus)
|
|
KeybdOn=1;
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Clear the current screen
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
void ClearScreen(void)
|
|
{
|
|
unsigned size,segment;
|
|
|
|
segment=0xa000;
|
|
switch(videomode)
|
|
{
|
|
case CGA: segment=0xb800; size=CGASIZE/2; break;
|
|
case EGA1: size=EGA1SIZE/2; break;
|
|
case EGA2: size=EGA2SIZE/2; break;
|
|
case VGA: size=VGASIZE/2;
|
|
}
|
|
|
|
MouseHide();
|
|
|
|
asm push di
|
|
asm push es
|
|
asm xor di,di
|
|
asm mov ax,segment
|
|
asm mov es,ax
|
|
asm mov cx,size
|
|
asm cld
|
|
asm xor ax,ax
|
|
asm rep stosw
|
|
asm pop es
|
|
asm pop di
|
|
|
|
MouseShow();
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////
|
|
//
|
|
// print a representation of the scan code key
|
|
//
|
|
/////////////////////////////////////////////////////////
|
|
char *PassScancode(int sc)
|
|
{
|
|
char smallstr[2];
|
|
char static chartable[128] =
|
|
{' ',' ','1','2','3','4','5','6','7','8','9','0','-','+','?','?',
|
|
'Q','W','E','R','T','Y','U','I','O','P','[',']','|','?','A','S',
|
|
'D','F','G','H','J','K','L',';','"',' ',' ',' ','Z','X','C','V',
|
|
'B','N','M',',','.','/','?',' ',' ',' ',' ',' ',' ',' ',' ',' ',
|
|
' ',' ',' ',' ',' ',' ',' ',' ', 15,' ','-', 14,'5', 31,'+',' ',
|
|
19,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
|
|
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
|
|
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
|
|
|
|
sc = sc & 0x7f;
|
|
|
|
if (sc==1)
|
|
strcpy(tempstr,"ESC");
|
|
else if (sc==0x48)
|
|
strcpy(tempstr,"\xb");
|
|
else if (sc==0x50)
|
|
strcpy(tempstr,"\xc");
|
|
else if (sc==0xe)
|
|
strcpy(tempstr,"BKSP");
|
|
else if (sc==0xf)
|
|
strcpy(tempstr,"TAB");
|
|
else if (sc==0x1d)
|
|
strcpy(tempstr,"CTRL");
|
|
else if (sc==0x2A)
|
|
strcpy(tempstr,"LSHIFT");
|
|
else if (sc==0x39)
|
|
strcpy(tempstr,"SPACE");
|
|
else if (sc==0x3A)
|
|
strcpy(tempstr,"CAPSLK");
|
|
else if (sc>=0x3b && sc<=0x44)
|
|
{
|
|
char str[3];
|
|
strcpy(tempstr,"F");
|
|
itoa (sc-0x3a,str,10);
|
|
strcat(tempstr,str);
|
|
}
|
|
else if (sc==0x57)
|
|
strcpy(tempstr,"F11");
|
|
else if (sc==0x59)
|
|
strcpy(tempstr,"F12");
|
|
else if (sc==0x46)
|
|
strcpy(tempstr,"SCRLLK");
|
|
else if (sc==0x1c)
|
|
strcpy(tempstr,"ENTER");
|
|
else if (sc==0x36)
|
|
strcpy(tempstr,"RSHIFT");
|
|
else if (sc==0x37)
|
|
strcpy(tempstr,"PRTSC");
|
|
else if (sc==0x38)
|
|
strcpy(tempstr,"ALT");
|
|
else if (sc==0x47)
|
|
strcpy(tempstr,"HOME");
|
|
else if (sc==0x49)
|
|
strcpy(tempstr,"PGUP");
|
|
else if (sc==0x4f)
|
|
strcpy(tempstr,"END");
|
|
else if (sc==0x51)
|
|
strcpy(tempstr,"PGDN");
|
|
else if (sc==0x52)
|
|
strcpy(tempstr,"INS");
|
|
else if (sc==0x53)
|
|
strcpy(tempstr,"DEL");
|
|
else if (sc==0x45)
|
|
strcpy(tempstr,"NUMLK");
|
|
else
|
|
{
|
|
smallstr[0]=chartable[sc];
|
|
smallstr[1]=0;
|
|
strcpy(tempstr,smallstr);
|
|
}
|
|
|
|
return tempstr;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
// DIALOG MANAGER CODE
|
|
//
|
|
//
|
|
/////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////
|
|
|
|
/////////////////////////////////////////////////////////
|
|
//
|
|
// Dialog Boxes!
|
|
//
|
|
/////////////////////////////////////////////////////////
|
|
int DoDialog(DialogDef *TheDialog)
|
|
{
|
|
btype *TheButton;
|
|
int i,ox,oy,Float=0,Released=0,Clicked=0,xc[30],yc[30],wid[30];
|
|
|
|
for (i=0;i<30;i++)
|
|
xc[i]=yc[i]=wid[i]=0;
|
|
|
|
MouseHide();
|
|
SaveBackground((screencenterx-TheDialog->width/2)*8,
|
|
(screencentery-TheDialog->height/2)*8,(TheDialog->width+2)*8,
|
|
(TheDialog->height+2)*8);
|
|
|
|
xormask=0;
|
|
centerwindow(TheDialog->width,TheDialog->height);
|
|
ox=sx;
|
|
oy=sy;
|
|
print(TheDialog->text);
|
|
for (i=0;i<TheDialog->numbuttons;i++)
|
|
{
|
|
int xx,yy,j;
|
|
|
|
TheButton=TheDialog->buttons;
|
|
|
|
xc[i]=sx=ox+(TheButton+i)->xoff;
|
|
yc[i]=sy=oy+(TheButton+i)->yoff;
|
|
xx=sx-1;
|
|
yy=sy-1;
|
|
print((TheButton+i)->text);
|
|
wid[i]=strlen((TheButton+i)->text);
|
|
|
|
if ((TheButton+i)->border)
|
|
DrawBorder(xx,yy,wid[i]+1,2,(TheButton+i)->border);
|
|
}
|
|
|
|
if (TheDialog->hook)
|
|
{
|
|
HookRoutine=(void (*)(int x,int y))TheDialog->hook;
|
|
HookRoutine(ox,oy);
|
|
}
|
|
MouseShow();
|
|
|
|
clearkeys();
|
|
do
|
|
{
|
|
char temp;
|
|
int mx,my;
|
|
|
|
temp=((temp<<1)|(MouseButton()&1))&3;
|
|
MouseCoords(&mx,&my);
|
|
mx/=8;
|
|
my/=8;
|
|
|
|
//
|
|
// ENTER press
|
|
//
|
|
if (keydown[0x1c])
|
|
for(i=0;i<TheDialog->numbuttons;i++)
|
|
{
|
|
TheButton=TheDialog->buttons;
|
|
if ((TheButton+i)->border==2)
|
|
{
|
|
Clicked=i+1;
|
|
Released=1;
|
|
temp=Float=0;
|
|
while(keydown[0x1c]);
|
|
clearkeys();
|
|
}
|
|
}
|
|
|
|
//
|
|
// ESC press
|
|
//
|
|
if (keydown[1])
|
|
{
|
|
temp=Float=Clicked=0;
|
|
Released=1;
|
|
while(keydown[1]);
|
|
}
|
|
|
|
switch(temp)
|
|
{
|
|
case 0: // upup (no press)
|
|
break;
|
|
case 3: // downdown (held down)
|
|
if (!Float && Clicked && (mx<xc[Clicked-1] ||
|
|
mx>xc[Clicked-1]+wid[Clicked-1]-1 || my!=yc[Clicked-1]))
|
|
{
|
|
xormask=0;
|
|
sx=xc[Clicked-1];
|
|
sy=yc[Clicked-1];
|
|
MouseHide();
|
|
print((TheButton+Clicked-1)->text);
|
|
MouseShow();
|
|
xormask=1;
|
|
Float=1;
|
|
}
|
|
else
|
|
if (Float && mx>=xc[Clicked-1] &&
|
|
mx<xc[Clicked-1]+wid[Clicked-1] && my==yc[Clicked-1])
|
|
{
|
|
xormask=1;
|
|
sx=xc[Clicked-1];
|
|
sy=yc[Clicked-1];
|
|
MouseHide();
|
|
print((TheButton+Clicked-1)->text);
|
|
MouseShow();
|
|
xormask=0;
|
|
Float=0;
|
|
}
|
|
break;
|
|
case 1: // updown (press)
|
|
for (i=0;i<TheDialog->numbuttons;i++)
|
|
{
|
|
if (mx>=xc[i] && mx<xc[i]+wid[i] && my==yc[i])
|
|
{
|
|
Clicked=i+1;
|
|
xormask=1;
|
|
sx=xc[i];
|
|
sy=yc[i];
|
|
MouseHide();
|
|
print((TheButton+i)->text);
|
|
MouseShow();
|
|
xormask=0;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case 2: // downup (release)
|
|
if (Clicked && !Float)
|
|
Released++;
|
|
}
|
|
} while (!Released);
|
|
|
|
RestoreBackground();
|
|
return Clicked;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////
|
|
//
|
|
// Just CHECK a Dialog Box's BUTTONS
|
|
//
|
|
/////////////////////////////////////////////////////////
|
|
int CheckButtons(DialogDef *TheDialog)
|
|
{
|
|
btype *TheButton;
|
|
int i,ox,oy,Float=0,Released=0,Clicked=0,xc[30],yc[30],wid[30];
|
|
|
|
for (i=0;i<30;i++)
|
|
xc[i]=yc[i]=wid[i]=0;
|
|
|
|
ox=screencenterx-TheDialog->width/2+1;
|
|
oy=screencentery-TheDialog->height/2+1;
|
|
for (i=0;i<TheDialog->numbuttons;i++)
|
|
{
|
|
int xx,yy,j;
|
|
|
|
TheButton=TheDialog->buttons;
|
|
|
|
xc[i]=ox+(TheButton+i)->xoff;
|
|
yc[i]=oy+(TheButton+i)->yoff;
|
|
wid[i]=strlen((TheButton+i)->text);
|
|
}
|
|
|
|
|
|
clearkeys();
|
|
do
|
|
{
|
|
char temp;
|
|
int mx,my;
|
|
|
|
temp=((temp<<1)|(MouseButton()&1))&3;
|
|
MouseCoords(&mx,&my);
|
|
mx/=8;
|
|
my/=8;
|
|
|
|
//
|
|
// ENTER press
|
|
//
|
|
if (keydown[0x1c])
|
|
for(i=0;i<TheDialog->numbuttons;i++)
|
|
{
|
|
TheButton=TheDialog->buttons;
|
|
if ((TheButton+i)->border==2)
|
|
{
|
|
Clicked=i+1;
|
|
Released=1;
|
|
temp=Float=0;
|
|
while(keydown[0x1c]);
|
|
clearkeys();
|
|
}
|
|
}
|
|
|
|
//
|
|
// ESC press
|
|
//
|
|
if (keydown[1])
|
|
{
|
|
temp=Float=Clicked=0;
|
|
Released=1;
|
|
while(keydown[1]);
|
|
}
|
|
|
|
switch(temp)
|
|
{
|
|
case 0: // upup (no press)
|
|
break;
|
|
case 3: // downdown (held down)
|
|
if (!Float && Clicked && (mx<xc[Clicked-1] ||
|
|
mx>xc[Clicked-1]+wid[Clicked-1]-1 || my!=yc[Clicked-1]))
|
|
{
|
|
xormask=0;
|
|
sx=xc[Clicked-1];
|
|
sy=yc[Clicked-1];
|
|
MouseHide();
|
|
print((TheButton+Clicked-1)->text);
|
|
MouseShow();
|
|
xormask=1;
|
|
Float=1;
|
|
}
|
|
else
|
|
if (Float && mx>=xc[Clicked-1] &&
|
|
mx<xc[Clicked-1]+wid[Clicked-1] && my==yc[Clicked-1])
|
|
{
|
|
xormask=1;
|
|
sx=xc[Clicked-1];
|
|
sy=yc[Clicked-1];
|
|
MouseHide();
|
|
print((TheButton+Clicked-1)->text);
|
|
MouseShow();
|
|
xormask=0;
|
|
Float=0;
|
|
}
|
|
break;
|
|
case 1: // updown (press)
|
|
for (i=0;i<TheDialog->numbuttons;i++)
|
|
{
|
|
if (mx>=xc[i] && mx<xc[i]+wid[i] && my==yc[i])
|
|
{
|
|
Clicked=i+1;
|
|
xormask=1;
|
|
sx=xc[i];
|
|
sy=yc[i];
|
|
MouseHide();
|
|
print((TheButton+i)->text);
|
|
MouseShow();
|
|
xormask=0;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case 2: // downup (release)
|
|
if (Clicked && !Float)
|
|
Released++;
|
|
}
|
|
} while (!Released);
|
|
clearkeys();
|
|
|
|
if (Clicked)
|
|
{
|
|
sx=xc[Clicked-1];
|
|
sy=yc[Clicked-1];
|
|
MouseHide();
|
|
print((TheButton+Clicked-1)->text);
|
|
MouseShow();
|
|
}
|
|
|
|
return Clicked;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////
|
|
//
|
|
// Just CHECK a Dialog Box's BUTTONS
|
|
// BUT!...RETURN IF MOUSE BUTTON IS PRESSED OUTSIDE DIALOG BUTTON!
|
|
//
|
|
/////////////////////////////////////////////////////////
|
|
int CheckButtonsRet(DialogDef *TheDialog)
|
|
{
|
|
btype *TheButton;
|
|
int i,ox,oy,Float=0,Released=0,Clicked=0,xc[30],yc[30],wid[30];
|
|
|
|
for (i=0;i<30;i++)
|
|
xc[i]=yc[i]=wid[i]=0;
|
|
|
|
ox=screencenterx-TheDialog->width/2+1;
|
|
oy=screencentery-TheDialog->height/2+1;
|
|
for (i=0;i<TheDialog->numbuttons;i++)
|
|
{
|
|
int xx,yy,j;
|
|
|
|
TheButton=TheDialog->buttons;
|
|
|
|
xc[i]=ox+(TheButton+i)->xoff;
|
|
yc[i]=oy+(TheButton+i)->yoff;
|
|
wid[i]=strlen((TheButton+i)->text);
|
|
}
|
|
|
|
do
|
|
{
|
|
char temp;
|
|
int mx,my;
|
|
|
|
temp=((temp<<1)|(MouseButton()&1))&3;
|
|
if (MouseButton()&2)
|
|
return -1;
|
|
|
|
MouseCoords(&mx,&my);
|
|
mx/=8;
|
|
my/=8;
|
|
|
|
//
|
|
// ENTER press
|
|
//
|
|
if (keydown[0x1c])
|
|
for(i=0;i<TheDialog->numbuttons;i++)
|
|
{
|
|
TheButton=TheDialog->buttons;
|
|
if ((TheButton+i)->border==2)
|
|
{
|
|
Clicked=i+1;
|
|
Released=1;
|
|
temp=Float=0;
|
|
while(keydown[0x1c]);
|
|
clearkeys();
|
|
}
|
|
}
|
|
|
|
//
|
|
// ESC press
|
|
//
|
|
if (keydown[1])
|
|
{
|
|
temp=Float=Clicked=0;
|
|
Released=1;
|
|
while(keydown[1]);
|
|
}
|
|
|
|
//
|
|
// arrows or PgUp/PgDn/Home/End
|
|
//
|
|
if (keydown[0x48] || keydown[0x50] || keydown[0x4b] || keydown[0x4d] ||
|
|
keydown[0x49] || keydown[0x51] || keydown[0x47] || keydown[0x4f] ||
|
|
keydown[0x39] || keydown[0x2e])
|
|
return -1;
|
|
|
|
switch(temp)
|
|
{
|
|
case 0: // upup (no press)
|
|
break;
|
|
case 3: // downdown (held down)
|
|
if (!Float && Clicked && (mx<xc[Clicked-1] ||
|
|
mx>xc[Clicked-1]+wid[Clicked-1]-1 || my!=yc[Clicked-1]))
|
|
{
|
|
xormask=0;
|
|
sx=xc[Clicked-1];
|
|
sy=yc[Clicked-1];
|
|
MouseHide();
|
|
print((TheButton+Clicked-1)->text);
|
|
MouseShow();
|
|
xormask=1;
|
|
Float=1;
|
|
}
|
|
else
|
|
if (Float && mx>=xc[Clicked-1] &&
|
|
mx<xc[Clicked-1]+wid[Clicked-1] && my==yc[Clicked-1])
|
|
{
|
|
xormask=1;
|
|
sx=xc[Clicked-1];
|
|
sy=yc[Clicked-1];
|
|
MouseHide();
|
|
print((TheButton+Clicked-1)->text);
|
|
MouseShow();
|
|
xormask=0;
|
|
Float=0;
|
|
}
|
|
break;
|
|
case 1: // updown (press)
|
|
for (i=0;i<TheDialog->numbuttons;i++)
|
|
{
|
|
if (mx>=xc[i] && mx<xc[i]+wid[i] && my==yc[i])
|
|
{
|
|
Clicked=i+1;
|
|
xormask=1;
|
|
sx=xc[i];
|
|
sy=yc[i];
|
|
MouseHide();
|
|
print((TheButton+i)->text);
|
|
MouseShow();
|
|
xormask=0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!Clicked) // MOD TO ORIGINAL CHECKBUTTONS
|
|
return -1;
|
|
|
|
break;
|
|
case 2: // downup (release)
|
|
if (Clicked && !Float)
|
|
Released++;
|
|
}
|
|
} while (!Released);
|
|
clearkeys();
|
|
return Clicked;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////
|
|
//
|
|
// Just DRAW a Dialog Box
|
|
//
|
|
/////////////////////////////////////////////////////////
|
|
void DrawDialog(DialogDef *TheDialog,int saveback)
|
|
{
|
|
btype *TheButton;
|
|
int i,ox,oy,xc[30],yc[30],wid[30];
|
|
|
|
for (i=0;i<30;i++)
|
|
xc[i]=yc[i]=wid[i]=0;
|
|
|
|
MouseHide();
|
|
if (saveback)
|
|
SaveBackground((screencenterx-TheDialog->width/2)*8,
|
|
(screencentery-TheDialog->height/2)*8,(TheDialog->width+2)*8,
|
|
(TheDialog->height+2)*8);
|
|
|
|
xormask=0;
|
|
centerwindow(TheDialog->width,TheDialog->height);
|
|
ox=sx;
|
|
oy=sy;
|
|
print(TheDialog->text);
|
|
for (i=0;i<TheDialog->numbuttons;i++)
|
|
{
|
|
int xx,yy,j;
|
|
|
|
TheButton=TheDialog->buttons;
|
|
|
|
xc[i]=sx=ox+(TheButton+i)->xoff;
|
|
yc[i]=sy=oy+(TheButton+i)->yoff;
|
|
xx=sx-1;
|
|
yy=sy-1;
|
|
print((TheButton+i)->text);
|
|
wid[i]=strlen((TheButton+i)->text);
|
|
|
|
if ((TheButton+i)->border)
|
|
DrawBorder(xx,yy,wid[i]+1,2,(TheButton+i)->border);
|
|
}
|
|
|
|
if (TheDialog->hook)
|
|
{
|
|
HookRoutine=(void (*)(int x,int y))TheDialog->hook;
|
|
HookRoutine(ox,oy);
|
|
}
|
|
|
|
MouseShow();
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////
|
|
//
|
|
// Error Dialog Box
|
|
//
|
|
/////////////////////////////////////////////////////////
|
|
char errstring[200],bstring[20];
|
|
btype ERROKb={bstring,0,0,2};
|
|
DialogDef ERRR={errstring,0,0,1,&ERROKb,NULL};
|
|
|
|
void ErrDialog(char *string,char *bstr)
|
|
{
|
|
int maxw=0,width=0,height=1,i;
|
|
|
|
if (strlen(string)>200)
|
|
Quit("Programmer Error: ErrDialog string is too long!");
|
|
|
|
for (i=0;i<strlen(string);i++)
|
|
{
|
|
width++;
|
|
if (width>maxw)
|
|
maxw=width;
|
|
|
|
if (string[i]=='\n')
|
|
{
|
|
height++;
|
|
width=0;
|
|
}
|
|
}
|
|
height+=3; // add for button!
|
|
|
|
if (strlen(bstr)>maxw)
|
|
Quit("Programmer Error: ErrDialog BUTTONstring is longer than dialog!");
|
|
|
|
strcpy(bstring,bstr);
|
|
strcpy(errstring,string);
|
|
ERRR.width=maxw;
|
|
ERRR.height=height;
|
|
ERRR.numbuttons=1;
|
|
if (!bstr[0])
|
|
{
|
|
ERRR.numbuttons=0;
|
|
ERRR.height-=3;
|
|
}
|
|
|
|
ERROKb.xoff=(maxw/2)-(strlen(bstr)/2);
|
|
ERROKb.yoff=height-2;
|
|
|
|
if (bstr[0])
|
|
DoDialog(&ERRR);
|
|
else
|
|
DrawDialog(&ERRR,1);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////
|
|
//
|
|
// Draw a border
|
|
//
|
|
/////////////////////////////////////////////////////////
|
|
void DrawBorder(int x,int y,int w,int h,int b)
|
|
{
|
|
int xx=x,yy=y,j;
|
|
|
|
if (b==2)
|
|
{
|
|
drawchar(xx,yy,15);
|
|
drawchar(xx+w,yy,17);
|
|
drawchar(xx,yy+h,20);
|
|
drawchar(xx+w,yy+h,22);
|
|
|
|
for (j=yy+1;j<yy+h;j++)
|
|
{
|
|
drawchar(xx,j,18);
|
|
drawchar(xx+w,j,19);
|
|
}
|
|
for (j=xx+1;j<xx+w;j++)
|
|
{
|
|
drawchar(j,yy,16);
|
|
drawchar(j,yy+h,21);
|
|
}
|
|
}
|
|
|
|
if (b==1)
|
|
{
|
|
drawchar(xx,yy,23);
|
|
drawchar(xx+w,yy,25);
|
|
drawchar(xx,yy+h,28);
|
|
drawchar(xx+w,yy+h,30);
|
|
|
|
for (j=yy+1;j<yy+h;j++)
|
|
{
|
|
drawchar(xx,j,26);
|
|
drawchar(xx+w,j,27);
|
|
}
|
|
for (j=xx+1;j<xx+w;j++)
|
|
{
|
|
drawchar(j,yy,24);
|
|
drawchar(j,yy+h,29);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////
|
|
//
|
|
// Get the XY coords of a dialog's button
|
|
//
|
|
/////////////////////////////////////////////////////////
|
|
void GetButtonXY(DialogDef *TheDialog,int button,unsigned *x,unsigned *y)
|
|
{
|
|
btype *TheButton;
|
|
|
|
TheButton=TheDialog->buttons;
|
|
|
|
*x=(TheButton+button)->xoff+screencenterx-TheDialog->width/2+1;
|
|
*y=(TheButton+button)->yoff+screencentery-TheDialog->height/2+1;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////
|
|
//
|
|
// Get the XY coords of a dialog
|
|
//
|
|
/////////////////////////////////////////////////////////
|
|
void GetDialogXY(DialogDef *TheDialog,unsigned *x,unsigned *y)
|
|
{
|
|
*x=screencenterx-TheDialog->width/2+1;
|
|
*y=screencentery-TheDialog->height/2+1;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////
|
|
//
|
|
// Allow user to select a list item (like the menus)
|
|
//
|
|
////////////////////////////////////////////////////
|
|
int CheckList(int x,int y,int w,int h,void (*oncode)(),void (*offcode)(),int blink)
|
|
{
|
|
enum {upup,updown,downup,downdown} clicks;
|
|
static char bpress=0;
|
|
unsigned mx,my,i;
|
|
int high=-1;
|
|
|
|
|
|
while(1)
|
|
{
|
|
MouseCoords(&(int)mx,&(int)my);
|
|
mx/=8;
|
|
my/=8;
|
|
bpress=((bpress<<1)|(MouseButton()&1))&3;
|
|
switch(bpress)
|
|
{
|
|
case upup:
|
|
return -1;
|
|
case updown:
|
|
if (mx>=x && mx<x+w && my>=y && my<y+h)
|
|
{
|
|
high=my-y;
|
|
MouseHide();
|
|
oncode(x,my,high);
|
|
MouseShow();
|
|
}
|
|
else
|
|
return -1;
|
|
|
|
break;
|
|
case downup:
|
|
if (high!=-1)
|
|
{
|
|
if (blink)
|
|
for(i=0;i<5;i++)
|
|
{
|
|
MouseHide();
|
|
oncode(x,my,high);
|
|
MouseShow();
|
|
WaitVBL(3);
|
|
|
|
MouseHide();
|
|
offcode(x,my,high);
|
|
WaitVBL(3);
|
|
MouseShow();
|
|
}
|
|
}
|
|
return high;
|
|
|
|
case downdown:
|
|
if (mx>=x && mx<x+w && my>=y && my<y+h)
|
|
{
|
|
if (my-y != high && high!=-1)
|
|
{
|
|
MouseHide();
|
|
offcode(x,high+y,high);
|
|
MouseShow();
|
|
|
|
}
|
|
|
|
if (my-y != high)
|
|
{
|
|
high=my-y;
|
|
MouseHide();
|
|
oncode(x,y+high,high);
|
|
MouseShow();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (high!=-1)
|
|
{
|
|
MouseHide();
|
|
offcode(x,high+y,high);
|
|
MouseShow();
|
|
}
|
|
high=-1;
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////
|
|
//
|
|
// Message dialog
|
|
// Returns: -1=ESC, 0=No, 1=Yes
|
|
//
|
|
/////////////////////////////////////////////////
|
|
char MessStr[200];
|
|
btype MessOKb[]={{" No ",0,0,1},{" Yes ",0,0,2}};
|
|
DialogDef Mess={MessStr,0,0,2,&MessOKb[0],NULL};
|
|
|
|
int Message(char *string)
|
|
{
|
|
int maxw=0,width=0,height=1,i;
|
|
|
|
if (strlen(string)>200)
|
|
Quit("Programmer Error: Message string is too long!");
|
|
|
|
for (i=0;i<strlen(string);i++)
|
|
{
|
|
width++;
|
|
if (width>maxw)
|
|
maxw=width;
|
|
|
|
if (string[i]=='\n')
|
|
{
|
|
height++;
|
|
width=0;
|
|
}
|
|
}
|
|
height+=3; // add for buttons!
|
|
|
|
strcpy(MessStr,string);
|
|
Mess.width=maxw;
|
|
Mess.height=height;
|
|
|
|
MessOKb[1].xoff=(maxw/4)-(strlen(MessOKb[0].text)/2);
|
|
MessOKb[1].yoff=height-2;
|
|
MessOKb[0].xoff=(maxw/4)*3-(strlen(MessOKb[1].text)/2);
|
|
MessOKb[0].yoff=height-2;
|
|
|
|
return DoDialog(&Mess);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////
|
|
//
|
|
// GetPath dialog
|
|
// *path is returned
|
|
// (exit:0 if OK,-1 if Not Successful,-2 if Canceled)
|
|
//
|
|
/////////////////////////////////////////////////
|
|
#define LISTX 1
|
|
#define LISTY 3
|
|
|
|
char dstr[80];
|
|
btype GPb={"Cancel",15,3,1};
|
|
DialogDef GPd={dstr,22,14,1,&GPb,NULL};
|
|
char NameList[MAXFDNAMES][13];
|
|
int base;
|
|
struct ffblk f;
|
|
|
|
int GetPath(char *string,char *filter,char *path)
|
|
{
|
|
char pname[64];
|
|
unsigned int numnames=0,max,dx,dy,redraw,exit;
|
|
int select,zset,i;
|
|
|
|
|
|
strcpy(pname,filter);
|
|
for (zset=0,i=strlen(pname);i>=0;i--)
|
|
if (pname[i]=='\\')
|
|
{
|
|
pname[i+1]=0;
|
|
zset++;
|
|
break;
|
|
}
|
|
if (!zset)
|
|
pname[0]=0;
|
|
|
|
strcpy(dstr,string);
|
|
//
|
|
// FIRST, GET THE NAMES FROM THE DIRECTORY
|
|
//
|
|
if (findfirst(filter,&f,FA_ARCH))
|
|
return -1;
|
|
strcpy(NameList[numnames++],f.ff_name);
|
|
|
|
while(!findnext(&f) && numnames<MAXFDNAMES)
|
|
strcpy(NameList[numnames++],f.ff_name);
|
|
|
|
DrawDialog(&GPd,1);
|
|
MouseHide();
|
|
GetDialogXY(&GPd,&dx,&dy);
|
|
DrawBorder(dx+LISTX-1,dy+LISTY-1,13,11,1);
|
|
MouseShow();
|
|
|
|
base=exit=0;
|
|
|
|
//
|
|
// THIS LOOP DRAWS THE DIALOG
|
|
//
|
|
do
|
|
{
|
|
redraw=0;
|
|
MouseHide();
|
|
max=10;
|
|
if (numnames<10)
|
|
max=numnames;
|
|
for (i=0;i<max;i++)
|
|
{
|
|
bar(dx+LISTX,dy+LISTY+i,dx+LISTX+11,dy+LISTY+i,' ');
|
|
FDoff(dx+LISTX,dy+LISTY+i,i);
|
|
}
|
|
MouseShow();
|
|
|
|
//
|
|
// THIS LOOP CHECKS INPUT
|
|
//
|
|
do
|
|
{
|
|
select=CheckList(dx+LISTX,dy+LISTY,12,max,FDon,FDoff,0);
|
|
if (select>=0)
|
|
{
|
|
redraw=exit=1;
|
|
continue;
|
|
}
|
|
|
|
GetButtonXY(&GPd,0,&sx,&sy);
|
|
select=CheckList(sx,sy,strlen(GPb.text),1,CancelOn,CancelOff,0);
|
|
if (!select || keydown[1])
|
|
{
|
|
RestoreBackground();
|
|
while(keydown[1]);
|
|
clearkeys();
|
|
return -2;
|
|
}
|
|
|
|
//
|
|
// CHECK ARROWS & PGUP/DN
|
|
//
|
|
if (keydown[0x48] && base)
|
|
{
|
|
base--;
|
|
redraw=1;
|
|
if (!keydown[0x1d])
|
|
while(keydown[0x48]);
|
|
}
|
|
else
|
|
if (keydown[0x50] && base+10<numnames)
|
|
{
|
|
base++;
|
|
redraw=1;
|
|
if (!keydown[0x1d])
|
|
while(keydown[0x50]);
|
|
}
|
|
else
|
|
if (keydown[0x49])
|
|
{
|
|
base-=10;
|
|
if (base<0)
|
|
base=0;
|
|
redraw=1;
|
|
if (!keydown[0x1d])
|
|
while(keydown[0x49]);
|
|
}
|
|
else
|
|
if (keydown[0x51])
|
|
{
|
|
base+=10;
|
|
if (base+10>numnames)
|
|
base=numnames-10;
|
|
redraw=1;
|
|
if (!keydown[0x1d])
|
|
while(keydown[0x51]);
|
|
}
|
|
|
|
} while(!redraw);
|
|
} while(!exit);
|
|
|
|
//
|
|
// RETURN PATHNAME
|
|
//
|
|
RestoreBackground();
|
|
strcpy(path,pname);
|
|
strcat(path,NameList[select+base]);
|
|
findfirst(path,&f,FA_ARCH);
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void FDon(int x,int y,int w)
|
|
{
|
|
xormask=1;
|
|
FDoff(x,y,w);
|
|
xormask=0;
|
|
}
|
|
|
|
static void FDoff(int x,int y,int w)
|
|
{
|
|
MouseHide();
|
|
sx=x;
|
|
sy=y;
|
|
print(NameList[w+base]);
|
|
MouseShow();
|
|
}
|
|
|
|
|
|
static void CancelOn(int x,int y)
|
|
{
|
|
xormask=1;
|
|
CancelOff(x,y);
|
|
xormask=0;
|
|
}
|
|
|
|
static void CancelOff(int x,int y)
|
|
{
|
|
MouseHide();
|
|
sx=x;
|
|
sy=y;
|
|
print("Cancel");
|
|
MouseShow();
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////
|
|
//
|
|
// GetList dialog
|
|
// Fill "NameList[?][13]" with your strings
|
|
// (exit:>=0 is selection,-1 if Not Successful,-2 if Canceled)
|
|
//
|
|
/////////////////////////////////////////////////
|
|
int GetList(char *string,int numnames)
|
|
{
|
|
unsigned int max,dx,dy,redraw,exit,i;
|
|
int select;
|
|
|
|
|
|
strcpy(dstr,string);
|
|
|
|
DrawDialog(&GPd,1);
|
|
MouseHide();
|
|
GetDialogXY(&GPd,&dx,&dy);
|
|
DrawBorder(dx+LISTX-1,dy+LISTY-1,13,11,1);
|
|
MouseShow();
|
|
|
|
base=exit=0;
|
|
|
|
//
|
|
// THIS LOOP DRAWS THE DIALOG
|
|
//
|
|
do
|
|
{
|
|
redraw=0;
|
|
MouseHide();
|
|
max=10;
|
|
if (numnames<10)
|
|
max=numnames;
|
|
for (i=0;i<max;i++)
|
|
{
|
|
bar(dx+LISTX,dy+LISTY+i,dx+LISTX+11,dy+LISTY+i,' ');
|
|
FDoff(dx+LISTX,dy+LISTY+i,i);
|
|
}
|
|
MouseShow();
|
|
|
|
//
|
|
// THIS LOOP CHECKS INPUT
|
|
//
|
|
do
|
|
{
|
|
select=CheckList(dx+LISTX,dy+LISTY,12,max,FDon,FDoff,0);
|
|
if (select>=0)
|
|
{
|
|
redraw=exit=1;
|
|
continue;
|
|
}
|
|
|
|
GetButtonXY(&GPd,0,&sx,&sy);
|
|
select=CheckList(sx,sy,strlen(GPb.text),1,CancelOn,CancelOff,0);
|
|
if (!select || keydown[1])
|
|
{
|
|
RestoreBackground();
|
|
while(keydown[1]);
|
|
clearkeys();
|
|
return -2;
|
|
}
|
|
|
|
//
|
|
// CHECK ARROWS & PGUP/DN
|
|
//
|
|
if (keydown[0x48] && base)
|
|
{
|
|
base--;
|
|
redraw=1;
|
|
if (!keydown[0x1d])
|
|
while(keydown[0x48]);
|
|
}
|
|
else
|
|
if (keydown[0x50] && base+10<numnames)
|
|
{
|
|
base++;
|
|
redraw=1;
|
|
if (!keydown[0x1d])
|
|
while(keydown[0x50]);
|
|
}
|
|
else
|
|
if (keydown[0x49])
|
|
{
|
|
base-=10;
|
|
if (base<0)
|
|
base=0;
|
|
redraw=1;
|
|
if (!keydown[0x1d])
|
|
while(keydown[0x49]);
|
|
}
|
|
else
|
|
if (keydown[0x51])
|
|
{
|
|
base+=10;
|
|
if (base+10>numnames)
|
|
base=numnames-10;
|
|
redraw=1;
|
|
if (!keydown[0x1d])
|
|
while(keydown[0x51]);
|
|
}
|
|
|
|
} while(!redraw);
|
|
} while(!exit);
|
|
|
|
//
|
|
// RETURN SELECTION
|
|
//
|
|
RestoreBackground();
|
|
return select+base;
|
|
}
|