1 /////////////////////////////////////////////////////////////////
3 // Pull-Down Menu Interface
4 // by John Romero (C) 1991 Id Software
6 /////////////////////////////////////////////////////////////////
14 #define CGASIZE 0x4000
15 #define EGA1SIZE 0x2000
16 #define EGA2SIZE 0x9600
17 #define EGA3SIZE 60000
20 void (*HookRoutine)(int x,int y);
21 void (*ItemRoutine)(void);
22 char MenuStr[20][80],tempstr[80];
23 memptr Background[10];
25 struct { int savex,savey,savew,saveh; } Back[10];
27 MInfoType MenuInfo[10];
28 int ScreenWidth,OpenMenu,NumMenus,ItemOn,KeybdOn;
30 void HandleOpenMenu(void (*UserRoutine)(void),int which);
31 void HandleCloseMenu(void (*UserRoutine)(void));
32 void HandleHighlight(void (*UserRoutine)(void));
33 int DetectMenu(int x,int y);
34 void ChangeItem(int newitem);
35 void ClearScreen(void);
36 void RedrawDesktop(void);
37 char *PassScancode(int sc);
39 /////////////////////////////////////////////////////////////////
43 /////////////////////////////////////////////////////////////////
44 void DeskEventLoop(void (*UserRoutine)(void),void (*ConstantRoutine)(void))
46 int buttonstatus=0,oldmenu,olditem;
47 enum clicks {upup,updown,downup,downdown};
51 HandleOpenMenu(UserRoutine,2);
58 int temp=MouseButton()&1,temp1=(MouseButton()>>1)&1;
65 switch(buttonstatus=((buttonstatus<<1)|temp|temp1)&3)
68 case updown: HandleOpenMenu(UserRoutine,0);
70 case downdown: HandleHighlight(UserRoutine);
72 case downup: HandleCloseMenu(UserRoutine);
73 if (ItemOn && ItemRoutine)
81 char key=bioskey(1)>>8;
88 nitems=(MBarPtr+OpenMenu-1)->num_items;
92 case 0x48: if (OpenMenu)
99 case 0x50: if (OpenMenu)
104 ChangeItem(ItemOn+1);
106 case 0x1c: oldmenu=OpenMenu;
108 HandleCloseMenu(UserRoutine);
113 case 0x4b: if (OpenMenu)
123 HandleCloseMenu(UserRoutine);
124 HandleOpenMenu(UserRoutine,newmenu);
129 case 0x4d: if (OpenMenu)
134 if (OpenMenu==NumMenus)
139 HandleCloseMenu(UserRoutine);
140 HandleOpenMenu(UserRoutine,newmenu);
145 case 0x01: if (!OpenMenu)
147 HandleOpenMenu(UserRoutine,oldmenu);
155 int i,j,numitems,run=0;
158 for (i=0;i<NumMenus;i++)
160 numitems=(MBarPtr+i)->num_items;
161 items=(MBarPtr+i)->menu_def;
163 for (j=0;j<numitems;j++)
164 if ((items+j)->hotkey==key && (items+j)->hotkey)
166 if (((items+j)->shiftflag) &&
167 (!keydown[(items+j)->shiftflag]))
170 ItemRoutine=(items+j)->routine;
191 /////////////////////////////////////////////////////////////////
193 // See if a menu was opened
195 /////////////////////////////////////////////////////////////////
196 void HandleOpenMenu(void (*UserRoutine)(void),int which)
198 int x,y,loop,flag,tempx,tempw,maxw,loopsize;
204 if (y>8 && !OpenMenu)
210 flag=DetectMenu(x,y);
217 tempx=MenuInfo[flag-1].menux;
218 tempw=MenuInfo[flag-1].menuwidth;
219 items=(MBarPtr+flag-1)->menu_def;
229 // BUILD MENU STRINGS
231 loopsize=(MBarPtr+flag-1)->num_items;
233 for (loop=0;loop<loopsize;loop++)
237 memset(MenuStr[loop],0,80);
239 MenuStr[loop][0]=4; // leftedge
240 strcat(MenuStr[loop],(items+loop)->item_name);
242 len=strlen(MenuStr[loop]);
243 memset(&MenuStr[loop][len],' ',tempw-len+1);
245 switch((items+loop)->shiftflag)
247 case ALT: strcat(MenuStr[loop]," ALT-"); break;
248 case CTRL:strcat(MenuStr[loop],"CTRL-");
251 strcat(MenuStr[loop],PassScancode((items+loop)->hotkey));
253 len=strlen(MenuStr[loop]);
258 if (tempx+maxw>ScreenWidth)
259 tempx=ScreenWidth-1-maxw;
260 SaveBackground(tempx*8,0,(maxw+1)*8,(MBarPtr+flag-1)->num_items*8+16);
263 // PRINT MENU STRINGS
266 print((MBarPtr+flag-1)->menu_name);
269 for (loop=0;loop<loopsize;loop++)
273 len=strlen(MenuStr[loop]);
275 memset(&MenuStr[loop][len],' ',maxw-len);
276 strcat(MenuStr[loop],"\x5");
280 print(MenuStr[loop]);
286 bar(sx,sy,sx+maxw-2,sy,7);
297 /////////////////////////////////////////////////////////////////
299 // Detect whether a menu is clicked on or not
301 /////////////////////////////////////////////////////////////////
302 int DetectMenu(int x,int y)
310 for (loop=0;loop<NumMenus;loop++)
311 if (x/8>=MenuInfo[loop].menux && x/8<MenuInfo[loop].menux+MenuInfo[loop].menunamelen)
321 /////////////////////////////////////////////////////////////////
323 // Highlight & De-highlight items
325 /////////////////////////////////////////////////////////////////
326 void HandleHighlight(void (*UserRoutine)(void))
328 int x,y,nitems,tempx,tempw,tempy,opmen;
337 nitems=(MBarPtr+OpenMenu-1)->num_items;
338 tempx=MenuInfo[OpenMenu-1].menux;
339 tempw=strlen(MenuStr[0])-5;
340 if (tempx+tempw+5>ScreenWidth)
341 tempx=ScreenWidth-tempw-5;
343 opmen=DetectMenu(x,y);
344 if (opmen && opmen!=OpenMenu)
348 HandleOpenMenu(UserRoutine,0);
353 // IS USER IN A MENU?
356 if (x/8>tempx && x/8<tempx+tempw+4 && y>8 && y<(nitems+1)*8)
359 return; // EXIT IF ON SAME ITEM
362 // IF AN ITEM IS CURRENTLY SELECTED, DEHIGHLIGHT IT
363 // AND HIGHLIGHT A NEW ITEM
370 // USER MOVED POINTER OUTSIDE OF MENU; DEHIGHLIGHT ITEM
379 print(MenuStr[ItemOn-1]);
388 /////////////////////////////////////////////////////////////////
390 // Set new item highlighted
392 /////////////////////////////////////////////////////////////////
393 void ChangeItem(int newitem)
399 tempx=MenuInfo[OpenMenu-1].menux;
400 if (tempx+strlen(MenuStr[0])>ScreenWidth)
401 tempx=ScreenWidth-strlen(MenuStr[0]);
408 print(MenuStr[ItemOn-1]);
413 strncpy(tempstr,&MenuStr[ItemOn-1][1],strlen(MenuStr[ItemOn-1])-2);
424 /////////////////////////////////////////////////////////////////
426 // See if a menu was closed
428 /////////////////////////////////////////////////////////////////
429 void HandleCloseMenu(void (*UserRoutine)(void))
443 items=(MBarPtr+OpenMenu-1)->menu_def;
444 tempx=MenuInfo[OpenMenu-1].menux;
445 if (tempx+strlen(MenuStr[0])>ScreenWidth)
446 tempx=ScreenWidth-strlen(MenuStr[0]);
448 for (loop=0;loop<NUMFLASHES;loop++)
453 strncpy(tempstr,&MenuStr[ItemOn-1][1],strlen(MenuStr[ItemOn-1])-2);
462 ItemRoutine=(items+ItemOn-1)->routine;
470 /////////////////////////////////////////////////////////////////
472 // Save the background
474 /////////////////////////////////////////////////////////////////
475 void SaveBackground(int x,int y,int w,int h)
478 unsigned loc,loop,loop1,seg,planelen;
480 Back[WhichBack].savex=x;
481 Back[WhichBack].savey=y;
482 Back[WhichBack].savew=w;
483 Back[WhichBack].saveh=h;
489 MMAllocate(&Background[WhichBack],(w/4)*h);
491 for(loop=y;loop<y+h;loop++)
493 loc=(loop/2)*80+0x2000*(loop&1)+x/4;
494 movedata(0xb800,loc,(unsigned)Background[WhichBack],(loop-y)*(w/4),w/4);
501 unsigned tempw=w/8,tempx=x/8,psize;
504 MMAllocate(&Background[WhichBack],5L*planelen);
505 outport(GCindex,GCmode);
506 for (loop=0;loop<4;loop++)
510 outport(GCindex,GCreadmap | loop*256);
511 for (loop1=y;loop1<y+h;loop1++)
512 movedata(0xa000,((unsigned)loop1*ScreenWidth)+tempx,
513 ((unsigned)Background[WhichBack])+(psize/16),
514 (psize&15)+((loop1-y)*tempw),tempw);
520 MMAllocate(&Background[WhichBack],(long)w*h);
521 for(loop=y;loop<y+h;loop++)
522 movedata(0xa000,loop*320+x,(unsigned)Background[WhichBack],(loop-y)*w,w);
531 /////////////////////////////////////////////////////////////////
533 // Restore the background
535 /////////////////////////////////////////////////////////////////
536 void setfarmem(char huge *mem,unsigned char val,unsigned len)
543 void RestoreBackground(void)
546 unsigned loc,loop1,x,y,w,h,loop,planelen;
548 if (!Back[WhichBack-1].savex &&
549 !Back[WhichBack-1].savey &&
550 !Back[WhichBack-1].savew &&
551 !Back[WhichBack-1].saveh)
552 Quit("Can't RestoreBackground with no information!");
554 x=Back[WhichBack-1].savex;
555 y=Back[WhichBack-1].savey;
556 w=Back[WhichBack-1].savew;
557 h=Back[WhichBack-1].saveh;
563 for(loop=y;loop<y+h;loop++)
565 loc=(loop/2)*80+0x2000*(loop&1)+x/4;
566 movedata((unsigned)Background[WhichBack-1],(loop-y)*(w/4),0xb800,loc,w/4);
573 outport(GCindex,GCmode);
574 for (loop=0;loop<4;loop++)
576 outport(SCindex,SCmapmask | (1<<loop)*256);
577 for (loop1=y;loop1<y+h;loop1++)
578 movedata(((unsigned)Background[WhichBack-1])+((loop*planelen)/16),
579 ((loop*planelen)&15)+(loop1-y)*(w/8),
580 0xa000,loop1*ScreenWidth+x/8,w/8);
585 for(loop=y;loop<y+h;loop++)
586 movedata((unsigned)Background[WhichBack-1],(loop-y)*w,0xa000,loop*320+x,w);
589 MMFreePtr(&Background[WhichBack-1]);
594 Back[WhichBack].savex=0;
595 Back[WhichBack].savey=0;
596 Back[WhichBack].savew=0;
597 Back[WhichBack].saveh=0;
601 /////////////////////////////////////////////////////////////////
605 /////////////////////////////////////////////////////////////////
606 void RedrawDesktop(void)
613 bar(0,0,ScreenWidth-1,0,' ');
618 while((MBarPtr+count)->num_items && !flag)
620 int len,max_width,loop;
625 // First, determine xcoord & namewidth & print
628 strcpy(string,(MBarPtr+count)->menu_name);
630 MenuInfo[NumMenus].menux=sx;
631 MenuInfo[NumMenus].menunamelen=len+2;
632 if (len+sx>ScreenWidth-1)
634 string[ScreenWidth-1-sx]=0;
635 MenuInfo[NumMenus].menunamelen=ScreenWidth-1-sx;
636 MenuInfo[NumMenus].menux=ScreenWidth-MenuInfo[NumMenus].menunamelen;
640 drawchar(sx++,sy,' ');
642 drawchar(sx++,sy,' ');
645 // Now, figure out length of widest item
649 the_item=(MBarPtr+count)->menu_def;
651 for (loop=0;loop<(MBarPtr+count)->num_items;loop++)
655 len=strlen((the_item+loop)->item_name);
660 MenuInfo[NumMenus].menuwidth=max_width+1;
667 // clear bottom line of menubar
673 unsigned huge *CGAmem=MK_FP(0xb800,240+0x2000);
681 char huge *EGAmem=MK_FP(0xa000,0);
682 outport(GCindex,GCmode);
683 outport(SCindex,0x0f00 | SCmapmask);
684 for (i=0;i<ScreenWidth;i++)
685 *(EGAmem+7*ScreenWidth+i)=0;
690 unsigned huge *VGAmem=MK_FP(0xa000,320*7);
699 /////////////////////////////////////////////////////////////////
703 /////////////////////////////////////////////////////////////////
704 void InitDesktop(MBarDef *menubar,int initmouse)
708 case CGA: ScreenWidth=40; break;
709 case EGA1: ScreenWidth=40; break;
710 case EGA2: ScreenWidth=80; break;
711 case VGA: ScreenWidth=40;
726 ////////////////////////////////////////////////////////////////////
728 // Clear the current screen
730 ////////////////////////////////////////////////////////////////////
731 void ClearScreen(void)
733 unsigned size,segment;
738 case CGA: segment=0xb800; size=CGASIZE/2; break;
739 case EGA1: size=EGA1SIZE/2; break;
740 case EGA2: size=EGA2SIZE/2; break;
741 case VGA: size=VGASIZE/2;
763 /////////////////////////////////////////////////////////
765 // print a representation of the scan code key
767 /////////////////////////////////////////////////////////
768 char *PassScancode(int sc)
771 char static chartable[128] =
772 {' ',' ','1','2','3','4','5','6','7','8','9','0','-','+','?','?',
773 'Q','W','E','R','T','Y','U','I','O','P','[',']','|','?','A','S',
774 'D','F','G','H','J','K','L',';','"',' ',' ',' ','Z','X','C','V',
775 'B','N','M',',','.','/','?',' ',' ',' ',' ',' ',' ',' ',' ',' ',
776 ' ',' ',' ',' ',' ',' ',' ',' ', 15,' ','-', 14,'5', 31,'+',' ',
777 19,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
778 ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
779 ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
784 strcpy(tempstr,"ESC");
786 strcpy(tempstr,"\xb");
788 strcpy(tempstr,"\xc");
790 strcpy(tempstr,"BKSP");
792 strcpy(tempstr,"TAB");
794 strcpy(tempstr,"CTRL");
796 strcpy(tempstr,"LSHIFT");
798 strcpy(tempstr,"SPACE");
800 strcpy(tempstr,"CAPSLK");
801 else if (sc>=0x3b && sc<=0x44)
805 itoa (sc-0x3a,str,10);
809 strcpy(tempstr,"F11");
811 strcpy(tempstr,"F12");
813 strcpy(tempstr,"SCRLLK");
815 strcpy(tempstr,"ENTER");
817 strcpy(tempstr,"RSHIFT");
819 strcpy(tempstr,"PRTSC");
821 strcpy(tempstr,"ALT");
823 strcpy(tempstr,"HOME");
825 strcpy(tempstr,"PGUP");
827 strcpy(tempstr,"END");
829 strcpy(tempstr,"PGDN");
831 strcpy(tempstr,"INS");
833 strcpy(tempstr,"DEL");
835 strcpy(tempstr,"NUMLK");
838 smallstr[0]=chartable[sc];
840 strcpy(tempstr,smallstr);
846 /////////////////////////////////////////////////////////
847 /////////////////////////////////////////////////////////
848 /////////////////////////////////////////////////////////
851 // DIALOG MANAGER CODE
854 /////////////////////////////////////////////////////////
855 /////////////////////////////////////////////////////////
856 /////////////////////////////////////////////////////////
858 /////////////////////////////////////////////////////////
862 /////////////////////////////////////////////////////////
863 int DoDialog(DialogDef *TheDialog)
866 int i,ox,oy,Float=0,Released=0,Clicked=0,xc[30],yc[30],wid[30];
869 xc[i]=yc[i]=wid[i]=0;
872 SaveBackground((screencenterx-TheDialog->width/2)*8,
873 (screencentery-TheDialog->height/2)*8,(TheDialog->width+2)*8,
874 (TheDialog->height+2)*8);
877 centerwindow(TheDialog->width,TheDialog->height);
880 print(TheDialog->text);
881 for (i=0;i<TheDialog->numbuttons;i++)
885 TheButton=TheDialog->buttons;
887 xc[i]=sx=ox+(TheButton+i)->xoff;
888 yc[i]=sy=oy+(TheButton+i)->yoff;
891 print((TheButton+i)->text);
892 wid[i]=strlen((TheButton+i)->text);
894 if ((TheButton+i)->border)
895 DrawBorder(xx,yy,wid[i]+1,2,(TheButton+i)->border);
900 HookRoutine=(void (*)(int x,int y))TheDialog->hook;
911 temp=((temp<<1)|(MouseButton()&1))&3;
912 MouseCoords(&mx,&my);
920 for(i=0;i<TheDialog->numbuttons;i++)
922 TheButton=TheDialog->buttons;
923 if ((TheButton+i)->border==2)
928 while(keydown[0x1c]);
938 temp=Float=Clicked=0;
945 case 0: // upup (no press)
947 case 3: // downdown (held down)
948 if (!Float && Clicked && (mx<xc[Clicked-1] ||
949 mx>xc[Clicked-1]+wid[Clicked-1]-1 || my!=yc[Clicked-1]))
955 print((TheButton+Clicked-1)->text);
961 if (Float && mx>=xc[Clicked-1] &&
962 mx<xc[Clicked-1]+wid[Clicked-1] && my==yc[Clicked-1])
968 print((TheButton+Clicked-1)->text);
974 case 1: // updown (press)
975 for (i=0;i<TheDialog->numbuttons;i++)
977 if (mx>=xc[i] && mx<xc[i]+wid[i] && my==yc[i])
984 print((TheButton+i)->text);
991 case 2: // downup (release)
992 if (Clicked && !Float)
1002 /////////////////////////////////////////////////////////
1004 // Just CHECK a Dialog Box's BUTTONS
1006 /////////////////////////////////////////////////////////
1007 int CheckButtons(DialogDef *TheDialog)
1010 int i,ox,oy,Float=0,Released=0,Clicked=0,xc[30],yc[30],wid[30];
1013 xc[i]=yc[i]=wid[i]=0;
1015 ox=screencenterx-TheDialog->width/2+1;
1016 oy=screencentery-TheDialog->height/2+1;
1017 for (i=0;i<TheDialog->numbuttons;i++)
1021 TheButton=TheDialog->buttons;
1023 xc[i]=ox+(TheButton+i)->xoff;
1024 yc[i]=oy+(TheButton+i)->yoff;
1025 wid[i]=strlen((TheButton+i)->text);
1035 temp=((temp<<1)|(MouseButton()&1))&3;
1036 MouseCoords(&mx,&my);
1044 for(i=0;i<TheDialog->numbuttons;i++)
1046 TheButton=TheDialog->buttons;
1047 if ((TheButton+i)->border==2)
1052 while(keydown[0x1c]);
1062 temp=Float=Clicked=0;
1069 case 0: // upup (no press)
1071 case 3: // downdown (held down)
1072 if (!Float && Clicked && (mx<xc[Clicked-1] ||
1073 mx>xc[Clicked-1]+wid[Clicked-1]-1 || my!=yc[Clicked-1]))
1079 print((TheButton+Clicked-1)->text);
1085 if (Float && mx>=xc[Clicked-1] &&
1086 mx<xc[Clicked-1]+wid[Clicked-1] && my==yc[Clicked-1])
1092 print((TheButton+Clicked-1)->text);
1098 case 1: // updown (press)
1099 for (i=0;i<TheDialog->numbuttons;i++)
1101 if (mx>=xc[i] && mx<xc[i]+wid[i] && my==yc[i])
1108 print((TheButton+i)->text);
1115 case 2: // downup (release)
1116 if (Clicked && !Float)
1119 } while (!Released);
1127 print((TheButton+Clicked-1)->text);
1135 /////////////////////////////////////////////////////////
1137 // Just CHECK a Dialog Box's BUTTONS
1138 // BUT!...RETURN IF MOUSE BUTTON IS PRESSED OUTSIDE DIALOG BUTTON!
1140 /////////////////////////////////////////////////////////
1141 int CheckButtonsRet(DialogDef *TheDialog)
1144 int i,ox,oy,Float=0,Released=0,Clicked=0,xc[30],yc[30],wid[30];
1147 xc[i]=yc[i]=wid[i]=0;
1149 ox=screencenterx-TheDialog->width/2+1;
1150 oy=screencentery-TheDialog->height/2+1;
1151 for (i=0;i<TheDialog->numbuttons;i++)
1155 TheButton=TheDialog->buttons;
1157 xc[i]=ox+(TheButton+i)->xoff;
1158 yc[i]=oy+(TheButton+i)->yoff;
1159 wid[i]=strlen((TheButton+i)->text);
1167 temp=((temp<<1)|(MouseButton()&1))&3;
1168 if (MouseButton()&2)
1171 MouseCoords(&mx,&my);
1179 for(i=0;i<TheDialog->numbuttons;i++)
1181 TheButton=TheDialog->buttons;
1182 if ((TheButton+i)->border==2)
1187 while(keydown[0x1c]);
1197 temp=Float=Clicked=0;
1203 // arrows or PgUp/PgDn/Home/End
1205 if (keydown[0x48] || keydown[0x50] || keydown[0x4b] || keydown[0x4d] ||
1206 keydown[0x49] || keydown[0x51] || keydown[0x47] || keydown[0x4f] ||
1207 keydown[0x39] || keydown[0x2e])
1212 case 0: // upup (no press)
1214 case 3: // downdown (held down)
1215 if (!Float && Clicked && (mx<xc[Clicked-1] ||
1216 mx>xc[Clicked-1]+wid[Clicked-1]-1 || my!=yc[Clicked-1]))
1222 print((TheButton+Clicked-1)->text);
1228 if (Float && mx>=xc[Clicked-1] &&
1229 mx<xc[Clicked-1]+wid[Clicked-1] && my==yc[Clicked-1])
1235 print((TheButton+Clicked-1)->text);
1241 case 1: // updown (press)
1242 for (i=0;i<TheDialog->numbuttons;i++)
1244 if (mx>=xc[i] && mx<xc[i]+wid[i] && my==yc[i])
1251 print((TheButton+i)->text);
1258 if (!Clicked) // MOD TO ORIGINAL CHECKBUTTONS
1262 case 2: // downup (release)
1263 if (Clicked && !Float)
1266 } while (!Released);
1272 /////////////////////////////////////////////////////////
1274 // Just DRAW a Dialog Box
1276 /////////////////////////////////////////////////////////
1277 void DrawDialog(DialogDef *TheDialog,int saveback)
1280 int i,ox,oy,xc[30],yc[30],wid[30];
1283 xc[i]=yc[i]=wid[i]=0;
1287 SaveBackground((screencenterx-TheDialog->width/2)*8,
1288 (screencentery-TheDialog->height/2)*8,(TheDialog->width+2)*8,
1289 (TheDialog->height+2)*8);
1292 centerwindow(TheDialog->width,TheDialog->height);
1295 print(TheDialog->text);
1296 for (i=0;i<TheDialog->numbuttons;i++)
1300 TheButton=TheDialog->buttons;
1302 xc[i]=sx=ox+(TheButton+i)->xoff;
1303 yc[i]=sy=oy+(TheButton+i)->yoff;
1306 print((TheButton+i)->text);
1307 wid[i]=strlen((TheButton+i)->text);
1309 if ((TheButton+i)->border)
1310 DrawBorder(xx,yy,wid[i]+1,2,(TheButton+i)->border);
1313 if (TheDialog->hook)
1315 HookRoutine=(void (*)(int x,int y))TheDialog->hook;
1323 /////////////////////////////////////////////////////////
1327 /////////////////////////////////////////////////////////
1328 char errstring[200],bstring[20];
1329 btype ERROKb={bstring,0,0,2};
1330 DialogDef ERRR={errstring,0,0,1,&ERROKb,NULL};
1332 void ErrDialog(char *string,char *bstr)
1334 int maxw=0,width=0,height=1,i;
1336 if (strlen(string)>200)
1337 Quit("Programmer Error: ErrDialog string is too long!");
1339 for (i=0;i<strlen(string);i++)
1345 if (string[i]=='\n')
1351 height+=3; // add for button!
1353 if (strlen(bstr)>maxw)
1354 Quit("Programmer Error: ErrDialog BUTTONstring is longer than dialog!");
1356 strcpy(bstring,bstr);
1357 strcpy(errstring,string);
1367 ERROKb.xoff=(maxw/2)-(strlen(bstr)/2);
1368 ERROKb.yoff=height-2;
1373 DrawDialog(&ERRR,1);
1377 /////////////////////////////////////////////////////////
1381 /////////////////////////////////////////////////////////
1382 void DrawBorder(int x,int y,int w,int h,int b)
1389 drawchar(xx+w,yy,17);
1390 drawchar(xx,yy+h,20);
1391 drawchar(xx+w,yy+h,22);
1393 for (j=yy+1;j<yy+h;j++)
1396 drawchar(xx+w,j,19);
1398 for (j=xx+1;j<xx+w;j++)
1401 drawchar(j,yy+h,21);
1408 drawchar(xx+w,yy,25);
1409 drawchar(xx,yy+h,28);
1410 drawchar(xx+w,yy+h,30);
1412 for (j=yy+1;j<yy+h;j++)
1415 drawchar(xx+w,j,27);
1417 for (j=xx+1;j<xx+w;j++)
1420 drawchar(j,yy+h,29);
1427 /////////////////////////////////////////////////////////
1429 // Get the XY coords of a dialog's button
1431 /////////////////////////////////////////////////////////
1432 void GetButtonXY(DialogDef *TheDialog,int button,unsigned *x,unsigned *y)
1436 TheButton=TheDialog->buttons;
1438 *x=(TheButton+button)->xoff+screencenterx-TheDialog->width/2+1;
1439 *y=(TheButton+button)->yoff+screencentery-TheDialog->height/2+1;
1443 /////////////////////////////////////////////////////////
1445 // Get the XY coords of a dialog
1447 /////////////////////////////////////////////////////////
1448 void GetDialogXY(DialogDef *TheDialog,unsigned *x,unsigned *y)
1450 *x=screencenterx-TheDialog->width/2+1;
1451 *y=screencentery-TheDialog->height/2+1;
1455 ////////////////////////////////////////////////////
1457 // Allow user to select a list item (like the menus)
1459 ////////////////////////////////////////////////////
1460 int CheckList(int x,int y,int w,int h,void (*oncode)(),void (*offcode)(),int blink)
1462 enum {upup,updown,downup,downdown} clicks;
1463 static char bpress=0;
1470 MouseCoords(&(int)mx,&(int)my);
1473 bpress=((bpress<<1)|(MouseButton()&1))&3;
1479 if (mx>=x && mx<x+w && my>=y && my<y+h)
1510 if (mx>=x && mx<x+w && my>=y && my<y+h)
1512 if (my-y != high && high!=-1)
1515 offcode(x,high+y,high);
1524 oncode(x,y+high,high);
1533 offcode(x,high+y,high);
1544 /////////////////////////////////////////////////
1547 // Returns: -1=ESC, 0=No, 1=Yes
1549 /////////////////////////////////////////////////
1551 btype MessOKb[]={{" No ",0,0,1},{" Yes ",0,0,2}};
1552 DialogDef Mess={MessStr,0,0,2,&MessOKb[0],NULL};
1554 int Message(char *string)
1556 int maxw=0,width=0,height=1,i;
1558 if (strlen(string)>200)
1559 Quit("Programmer Error: Message string is too long!");
1561 for (i=0;i<strlen(string);i++)
1567 if (string[i]=='\n')
1573 height+=3; // add for buttons!
1575 strcpy(MessStr,string);
1579 MessOKb[1].xoff=(maxw/4)-(strlen(MessOKb[0].text)/2);
1580 MessOKb[1].yoff=height-2;
1581 MessOKb[0].xoff=(maxw/4)*3-(strlen(MessOKb[1].text)/2);
1582 MessOKb[0].yoff=height-2;
1584 return DoDialog(&Mess);
1588 /////////////////////////////////////////////////
1591 // *path is returned
1592 // (exit:0 if OK,-1 if Not Successful,-2 if Canceled)
1594 /////////////////////////////////////////////////
1599 btype GPb={"Cancel",15,3,1};
1600 DialogDef GPd={dstr,22,14,1,&GPb,NULL};
1601 char NameList[MAXFDNAMES][13];
1605 int GetPath(char *string,char *filter,char *path)
1608 unsigned int numnames=0,max,dx,dy,redraw,exit;
1612 strcpy(pname,filter);
1613 for (zset=0,i=strlen(pname);i>=0;i--)
1623 strcpy(dstr,string);
1625 // FIRST, GET THE NAMES FROM THE DIRECTORY
1627 if (findfirst(filter,&f,FA_ARCH))
1629 strcpy(NameList[numnames++],f.ff_name);
1631 while(!findnext(&f) && numnames<MAXFDNAMES)
1632 strcpy(NameList[numnames++],f.ff_name);
1636 GetDialogXY(&GPd,&dx,&dy);
1637 DrawBorder(dx+LISTX-1,dy+LISTY-1,13,11,1);
1643 // THIS LOOP DRAWS THE DIALOG
1654 bar(dx+LISTX,dy+LISTY+i,dx+LISTX+11,dy+LISTY+i,' ');
1655 FDoff(dx+LISTX,dy+LISTY+i,i);
1660 // THIS LOOP CHECKS INPUT
1664 select=CheckList(dx+LISTX,dy+LISTY,12,max,FDon,FDoff,0);
1671 GetButtonXY(&GPd,0,&sx,&sy);
1672 select=CheckList(sx,sy,strlen(GPb.text),1,CancelOn,CancelOff,0);
1673 if (!select || keydown[1])
1675 RestoreBackground();
1682 // CHECK ARROWS & PGUP/DN
1684 if (keydown[0x48] && base)
1689 while(keydown[0x48]);
1692 if (keydown[0x50] && base+10<numnames)
1697 while(keydown[0x50]);
1707 while(keydown[0x49]);
1713 if (base+10>numnames)
1717 while(keydown[0x51]);
1726 RestoreBackground();
1728 strcat(path,NameList[select+base]);
1729 findfirst(path,&f,FA_ARCH);
1734 static void FDon(int x,int y,int w)
1741 static void FDoff(int x,int y,int w)
1746 print(NameList[w+base]);
1751 static void CancelOn(int x,int y)
1758 static void CancelOff(int x,int y)
1768 /////////////////////////////////////////////////
1771 // Fill "NameList[?][13]" with your strings
1772 // (exit:>=0 is selection,-1 if Not Successful,-2 if Canceled)
1774 /////////////////////////////////////////////////
1775 int GetList(char *string,int numnames)
1777 unsigned int max,dx,dy,redraw,exit,i;
1781 strcpy(dstr,string);
1785 GetDialogXY(&GPd,&dx,&dy);
1786 DrawBorder(dx+LISTX-1,dy+LISTY-1,13,11,1);
1792 // THIS LOOP DRAWS THE DIALOG
1803 bar(dx+LISTX,dy+LISTY+i,dx+LISTX+11,dy+LISTY+i,' ');
1804 FDoff(dx+LISTX,dy+LISTY+i,i);
1809 // THIS LOOP CHECKS INPUT
1813 select=CheckList(dx+LISTX,dy+LISTY,12,max,FDon,FDoff,0);
1820 GetButtonXY(&GPd,0,&sx,&sy);
1821 select=CheckList(sx,sy,strlen(GPb.text),1,CancelOn,CancelOff,0);
1822 if (!select || keydown[1])
1824 RestoreBackground();
1831 // CHECK ARROWS & PGUP/DN
1833 if (keydown[0x48] && base)
1838 while(keydown[0x48]);
1841 if (keydown[0x50] && base+10<numnames)
1846 while(keydown[0x50]);
1856 while(keydown[0x49]);
1862 if (base+10>numnames)
1866 while(keydown[0x51]);
1875 RestoreBackground();