]> 4ch.mooo.com Git - 16.git/blob - 16/ted5/MENU.C
ted5 added
[16.git] / 16 / ted5 / MENU.C
1 /////////////////////////////////////////////////////////////////
2 //
3 // Pull-Down Menu Interface
4 // by John Romero (C) 1991 Id Software
5 //
6 /////////////////////////////////////////////////////////////////
7 #include "ted5.h"
8 #pragma hdrstop
9
10 #define NUMFLASHES      10
11 #define ALT             0x38
12 #define CTRL            0x1d
13
14 #define CGASIZE         0x4000
15 #define EGA1SIZE        0x2000
16 #define EGA2SIZE        0x9600
17 #define EGA3SIZE        60000
18 #define VGASIZE         64000
19
20 void (*HookRoutine)(int x,int y);
21 void (*ItemRoutine)(void);
22 char MenuStr[20][80],tempstr[80];
23 memptr Background[10];
24 int WhichBack;
25 struct { int savex,savey,savew,saveh;  } Back[10];
26 MBarDef *MBarPtr;
27 MInfoType MenuInfo[10];
28 int ScreenWidth,OpenMenu,NumMenus,ItemOn,KeybdOn;
29
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);
38
39 /////////////////////////////////////////////////////////////////
40 //
41 // Desktop Event Loop
42 //
43 /////////////////////////////////////////////////////////////////
44 void DeskEventLoop(void (*UserRoutine)(void),void (*ConstantRoutine)(void))
45 {
46  int buttonstatus=0,oldmenu,olditem;
47  enum clicks {upup,updown,downup,downdown};
48
49  if (KeybdOn)
50    {
51     HandleOpenMenu(UserRoutine,2);
52     ChangeItem(1);
53    }
54
55  MouseShow();
56  while(1)
57    {
58     int temp=MouseButton()&1,temp1=(MouseButton()>>1)&1;
59
60     sx=0;
61     sy=3;
62
63     if (!OpenMenu)
64       ConstantRoutine();
65     switch(buttonstatus=((buttonstatus<<1)|temp|temp1)&3)
66       {
67        case upup: break;
68        case updown: HandleOpenMenu(UserRoutine,0);
69                     break;
70        case downdown: HandleHighlight(UserRoutine);
71                       break;
72        case downup: HandleCloseMenu(UserRoutine);
73                     if (ItemOn && ItemRoutine)
74                       ItemRoutine();
75                     ItemOn=0;
76                     break;
77       }
78
79     if (bioskey(1))
80       {
81        char key=bioskey(1)>>8;
82        int nitems;
83
84        if (OpenMenu)
85          {
86           bioskey(0);
87
88           nitems=(MBarPtr+OpenMenu-1)->num_items;
89
90           switch(key)
91             {
92              case 0x48: if (OpenMenu)
93                           if (ItemOn)
94                             if (ItemOn==1)
95                               ChangeItem(nitems);
96                             else
97                               ChangeItem(ItemOn-1);
98                         break;
99              case 0x50: if (OpenMenu)
100                           if (ItemOn)
101                             if (ItemOn==nitems)
102                               ChangeItem(1);
103                             else
104                               ChangeItem(ItemOn+1);
105                         break;
106              case 0x1c: oldmenu=OpenMenu;
107                         olditem=ItemOn;
108                         HandleCloseMenu(UserRoutine);
109                         if (ItemOn)
110                           ItemRoutine();
111
112                         break;
113              case 0x4b: if (OpenMenu)
114                           {
115                            int newmenu;
116
117                            ItemOn=0;
118                            if (OpenMenu==1)
119                              newmenu=NumMenus;
120                            else
121                              newmenu=OpenMenu-1;
122
123                            HandleCloseMenu(UserRoutine);
124                            HandleOpenMenu(UserRoutine,newmenu);
125
126                            ChangeItem(1);
127                           }
128                         break;
129              case 0x4d: if (OpenMenu)
130                           {
131                            int newmenu;
132
133                            ItemOn=0;
134                            if (OpenMenu==NumMenus)
135                              newmenu=1;
136                            else
137                              newmenu=OpenMenu+1;
138
139                            HandleCloseMenu(UserRoutine);
140                            HandleOpenMenu(UserRoutine,newmenu);
141
142                            ChangeItem(1);
143                           }
144                         break;
145              case 0x01: if (!OpenMenu)
146                           {
147                            HandleOpenMenu(UserRoutine,oldmenu);
148                            ChangeItem(olditem);
149                           }
150                         break;
151             }
152          }
153        else
154          {
155           int i,j,numitems,run=0;
156           MenuDef *items;
157
158           for (i=0;i<NumMenus;i++)
159             {
160              numitems=(MBarPtr+i)->num_items;
161              items=(MBarPtr+i)->menu_def;
162
163              for (j=0;j<numitems;j++)
164                if ((items+j)->hotkey==key && (items+j)->hotkey)
165                  {
166                   if (((items+j)->shiftflag) &&
167                       (!keydown[(items+j)->shiftflag]))
168                     continue;
169
170                   ItemRoutine=(items+j)->routine;
171                   ItemRoutine();
172                   run=1;
173                   break;
174                  }
175              if (run)
176                {
177                 if (bioskey(1))
178                   bioskey(0);
179                 break;
180                }
181             }
182           if (!run)
183             UserRoutine();
184          }
185       }
186    }
187 }
188
189
190
191 /////////////////////////////////////////////////////////////////
192 //
193 // See if a menu was opened
194 //
195 /////////////////////////////////////////////////////////////////
196 void HandleOpenMenu(void (*UserRoutine)(void),int which)
197 {
198  int x,y,loop,flag,tempx,tempw,maxw,loopsize;
199  MenuDef *items;
200
201  if (!which)
202    {
203     MouseCoords(&x,&y);
204     if (y>8 && !OpenMenu)
205       {
206        UserRoutine();
207        return;
208       }
209
210     flag=DetectMenu(x,y);
211     if (!flag) return;
212    }
213  else
214    flag=which;
215
216
217  tempx=MenuInfo[flag-1].menux;
218  tempw=MenuInfo[flag-1].menuwidth;
219  items=(MBarPtr+flag-1)->menu_def;
220
221  sx=tempx+1;
222  sy=0;
223  maxw=0;
224
225  MouseHide();
226
227
228  //
229  // BUILD MENU STRINGS
230  //
231  loopsize=(MBarPtr+flag-1)->num_items;
232
233  for (loop=0;loop<loopsize;loop++)
234    {
235     int len;
236
237     memset(MenuStr[loop],0,80);
238
239     MenuStr[loop][0]=4; // leftedge
240     strcat(MenuStr[loop],(items+loop)->item_name);
241
242     len=strlen(MenuStr[loop]);
243     memset(&MenuStr[loop][len],' ',tempw-len+1);
244
245     switch((items+loop)->shiftflag)
246       {
247        case ALT: strcat(MenuStr[loop]," ALT-"); break;
248        case CTRL:strcat(MenuStr[loop],"CTRL-");
249       }
250
251     strcat(MenuStr[loop],PassScancode((items+loop)->hotkey));
252
253     len=strlen(MenuStr[loop]);
254     if (len>maxw)
255       maxw=len;
256    }
257
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);
261
262  //
263  // PRINT MENU STRINGS
264  //
265  xormask=0xffff;
266  print((MBarPtr+flag-1)->menu_name);
267  xormask=0;
268
269  for (loop=0;loop<loopsize;loop++)
270    {
271     int len;
272
273     len=strlen(MenuStr[loop]);
274     if (len<maxw)
275       memset(&MenuStr[loop][len],' ',maxw-len);
276     strcat(MenuStr[loop],"\x5");
277
278     sx=tempx;
279     sy=loop+1;
280     print(MenuStr[loop]);
281    }
282
283   sx=tempx;
284   sy=loopsize+1;
285   print("\x6");
286   bar(sx,sy,sx+maxw-2,sy,7);
287   sx=tempx+maxw;
288   print("\x8");
289
290  MouseShow();
291  OpenMenu=flag;
292  ItemOn=0;
293 }
294
295
296
297 /////////////////////////////////////////////////////////////////
298 //
299 // Detect whether a menu is clicked on or not
300 //
301 /////////////////////////////////////////////////////////////////
302 int DetectMenu(int x,int y)
303 {
304  int flag,loop;
305
306  if (y>10)
307    return 0;
308
309  flag=0;
310  for (loop=0;loop<NumMenus;loop++)
311    if (x/8>=MenuInfo[loop].menux && x/8<MenuInfo[loop].menux+MenuInfo[loop].menunamelen)
312      {
313       flag=loop+1;
314       break;
315      }
316  return flag;
317 }
318
319
320
321 /////////////////////////////////////////////////////////////////
322 //
323 // Highlight & De-highlight items
324 //
325 /////////////////////////////////////////////////////////////////
326 void HandleHighlight(void (*UserRoutine)(void))
327 {
328  int x,y,nitems,tempx,tempw,tempy,opmen;
329
330  if (!OpenMenu)
331    {
332     UserRoutine();
333     return;
334    }
335
336  MouseCoords(&x,&y);
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;
342
343  opmen=DetectMenu(x,y);
344  if (opmen && opmen!=OpenMenu)
345    {
346     OpenMenu=0;
347     RestoreBackground();
348     HandleOpenMenu(UserRoutine,0);
349     return;
350    }
351
352  //
353  // IS USER IN A MENU?
354  //
355
356  if (x/8>tempx && x/8<tempx+tempw+4 && y>8 && y<(nitems+1)*8)
357    {
358     if (y/8==ItemOn)
359       return;   // EXIT IF ON SAME ITEM
360
361     //
362     // IF AN ITEM IS CURRENTLY SELECTED, DEHIGHLIGHT IT
363     // AND HIGHLIGHT A NEW ITEM
364     //
365
366     ChangeItem(y/8);
367    }
368  else
369    //
370    // USER MOVED POINTER OUTSIDE OF MENU; DEHIGHLIGHT ITEM
371    //
372
373    if (ItemOn)
374      {
375       MouseHide();
376
377       sx=tempx;
378       sy=ItemOn;
379       print(MenuStr[ItemOn-1]);
380
381       ItemOn=0;
382       MouseShow();
383      }
384 }
385
386
387
388 /////////////////////////////////////////////////////////////////
389 //
390 // Set new item highlighted
391 //
392 /////////////////////////////////////////////////////////////////
393 void ChangeItem(int newitem)
394 {
395  int tempx,tempw;
396  MenuDef *items;
397  char tempstr[80]="";
398
399  tempx=MenuInfo[OpenMenu-1].menux;
400  if (tempx+strlen(MenuStr[0])>ScreenWidth)
401    tempx=ScreenWidth-strlen(MenuStr[0]);
402
403  MouseHide();
404  if (ItemOn)
405    {
406     sx=tempx;
407     sy=ItemOn;
408     print(MenuStr[ItemOn-1]);
409    }
410
411  xormask=0xffff;
412  ItemOn=newitem;
413  strncpy(tempstr,&MenuStr[ItemOn-1][1],strlen(MenuStr[ItemOn-1])-2);
414  sx=tempx+1;
415  sy=ItemOn;
416  print(tempstr);
417  xormask=0;
418
419  MouseShow();
420 }
421
422
423
424 /////////////////////////////////////////////////////////////////
425 //
426 // See if a menu was closed
427 //
428 /////////////////////////////////////////////////////////////////
429 void HandleCloseMenu(void (*UserRoutine)(void))
430 {
431  MenuDef *items;
432  int loop,tempx;
433  char tempstr[80]="";
434
435  if (!OpenMenu)
436    {
437     UserRoutine();
438     return;
439    }
440
441  if (ItemOn)
442    {
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]);
447
448     for (loop=0;loop<NUMFLASHES;loop++)
449       {
450        xormask^=0xffff;
451        MouseHide();
452
453        strncpy(tempstr,&MenuStr[ItemOn-1][1],strlen(MenuStr[ItemOn-1])-2);
454        sx=tempx+1;
455        sy=ItemOn;
456        print(tempstr);
457
458        MouseShow();
459        WaitVBL(3);
460       }
461     xormask=0;
462     ItemRoutine=(items+ItemOn-1)->routine;
463    }
464
465  OpenMenu=0;
466  RestoreBackground();
467 }
468
469
470 /////////////////////////////////////////////////////////////////
471 //
472 // Save the background
473 //
474 /////////////////////////////////////////////////////////////////
475 void SaveBackground(int x,int y,int w,int h)
476 {
477  long size;
478  unsigned loc,loop,loop1,seg,planelen;
479
480  Back[WhichBack].savex=x;
481  Back[WhichBack].savey=y;
482  Back[WhichBack].savew=w;
483  Back[WhichBack].saveh=h;
484
485  MouseHide();
486  switch (videomode)
487    {
488     case CGA:
489       MMAllocate(&Background[WhichBack],(w/4)*h);
490
491       for(loop=y;loop<y+h;loop++)
492         {
493          loc=(loop/2)*80+0x2000*(loop&1)+x/4;
494          movedata(0xb800,loc,(unsigned)Background[WhichBack],(loop-y)*(w/4),w/4);
495         }
496       break;
497
498     case EGA2:
499     case EGA1:
500       {
501        unsigned tempw=w/8,tempx=x/8,psize;
502
503        planelen=tempw*h;
504        MMAllocate(&Background[WhichBack],5L*planelen);
505        outport(GCindex,GCmode);
506        for (loop=0;loop<4;loop++)
507          {
508           psize=loop*planelen;
509
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);
515          }
516       }
517       break;
518
519     case VGA:
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);
523    }
524  MouseShow();
525  if (WhichBack<10)
526    WhichBack++;
527 }
528
529
530
531 /////////////////////////////////////////////////////////////////
532 //
533 // Restore the background
534 //
535 /////////////////////////////////////////////////////////////////
536 void setfarmem(char huge *mem,unsigned char val,unsigned len)
537 {
538  int i;
539  for (i=0;i<len;i++)
540    *(mem+i)=val;
541 }
542
543 void RestoreBackground(void)
544 {
545  long size;
546  unsigned loc,loop1,x,y,w,h,loop,planelen;
547
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!");
553
554  x=Back[WhichBack-1].savex;
555  y=Back[WhichBack-1].savey;
556  w=Back[WhichBack-1].savew;
557  h=Back[WhichBack-1].saveh;
558
559  MouseHide();
560  switch (videomode)
561    {
562     case CGA:
563       for(loop=y;loop<y+h;loop++)
564         {
565          loc=(loop/2)*80+0x2000*(loop&1)+x/4;
566          movedata((unsigned)Background[WhichBack-1],(loop-y)*(w/4),0xb800,loc,w/4);
567         }
568       break;
569
570     case EGA2:
571     case EGA1:
572       planelen=(w/8)*h;
573       outport(GCindex,GCmode);
574       for (loop=0;loop<4;loop++)
575         {
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);
581         }
582       break;
583
584     case VGA:
585       for(loop=y;loop<y+h;loop++)
586         movedata((unsigned)Background[WhichBack-1],(loop-y)*w,0xa000,loop*320+x,w);
587    }
588
589  MMFreePtr(&Background[WhichBack-1]);
590
591  MouseShow();
592
593  WhichBack--;
594  Back[WhichBack].savex=0;
595  Back[WhichBack].savey=0;
596  Back[WhichBack].savew=0;
597  Back[WhichBack].saveh=0;
598 }
599
600
601 /////////////////////////////////////////////////////////////////
602 //
603 // Draw the Desktop
604 //
605 /////////////////////////////////////////////////////////////////
606 void RedrawDesktop(void)
607 {
608  int flag,count,i;
609
610  ClearScreen();
611
612  sx=sy=0;
613  bar(0,0,ScreenWidth-1,0,' ');
614
615  flag=0;
616  count=0;
617  NumMenus=0;
618  while((MBarPtr+count)->num_items && !flag)
619    {
620     int len,max_width,loop;
621     MenuDef *the_item;
622     char string[80];
623
624     //
625     // First, determine xcoord & namewidth & print
626     //
627
628     strcpy(string,(MBarPtr+count)->menu_name);
629     len=strlen(string);
630     MenuInfo[NumMenus].menux=sx;
631     MenuInfo[NumMenus].menunamelen=len+2;
632     if (len+sx>ScreenWidth-1)
633       {
634        string[ScreenWidth-1-sx]=0;
635        MenuInfo[NumMenus].menunamelen=ScreenWidth-1-sx;
636        MenuInfo[NumMenus].menux=ScreenWidth-MenuInfo[NumMenus].menunamelen;
637        flag++;
638       }
639
640     drawchar(sx++,sy,' ');
641     print(string);
642     drawchar(sx++,sy,' ');
643
644     //
645     // Now, figure out length of widest item
646     //
647
648     max_width=0;
649     the_item=(MBarPtr+count)->menu_def;
650
651     for (loop=0;loop<(MBarPtr+count)->num_items;loop++)
652       {
653        int len;
654
655        len=strlen((the_item+loop)->item_name);
656        if (len>max_width)
657          max_width=len;
658       }
659
660     MenuInfo[NumMenus].menuwidth=max_width+1;
661
662     count++;
663     NumMenus++;
664    }
665
666  //
667  // clear bottom line of menubar
668  //
669  switch(videomode)
670  {
671   case CGA:
672     {
673      unsigned huge *CGAmem=MK_FP(0xb800,240+0x2000);
674      for(i=0;i<40;i++)
675        *(CGAmem+i)=0;
676     }
677     break;
678   case EGA1:
679   case EGA2:
680     {
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;
686     }
687     break;
688   case VGA:
689     {
690     unsigned huge *VGAmem=MK_FP(0xa000,320*7);
691     for (i=0;i<160;i++)
692       *(VGAmem+i)=0;
693     }
694  }
695 }
696
697
698
699 /////////////////////////////////////////////////////////////////
700 //
701 // Init Desktop
702 //
703 /////////////////////////////////////////////////////////////////
704 void InitDesktop(MBarDef *menubar,int initmouse)
705 {
706  switch(videomode)
707    {
708     case CGA: ScreenWidth=40; break;
709     case EGA1: ScreenWidth=40; break;
710     case EGA2: ScreenWidth=80; break;
711     case VGA: ScreenWidth=40;
712    }
713
714  MBarPtr=menubar;
715  RedrawDesktop();
716  if (initmouse)
717    MouseInit();
718  OpenMenu=KeybdOn=0;
719  if (!MouseStatus)
720    KeybdOn=1;
721 }
722
723
724
725
726 ////////////////////////////////////////////////////////////////////
727 //
728 // Clear the current screen
729 //
730 ////////////////////////////////////////////////////////////////////
731 void ClearScreen(void)
732 {
733  unsigned size,segment;
734
735  segment=0xa000;
736  switch(videomode)
737    {
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;
742    }
743
744  MouseHide();
745
746  asm    push    di
747  asm    push    es
748  asm    xor     di,di
749  asm    mov     ax,segment
750  asm    mov     es,ax
751  asm    mov     cx,size
752  asm    cld
753  asm    xor     ax,ax
754  asm    rep stosw
755  asm    pop     es
756  asm    pop     di
757
758  MouseShow();
759 }
760
761
762
763 /////////////////////////////////////////////////////////
764 //
765 // print a representation of the scan code key
766 //
767 /////////////////////////////////////////////////////////
768 char *PassScancode(int sc)
769 {
770  char smallstr[2];
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   ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
780
781  sc = sc & 0x7f;
782
783  if (sc==1)
784    strcpy(tempstr,"ESC");
785  else if (sc==0x48)
786    strcpy(tempstr,"\xb");
787  else if (sc==0x50)
788    strcpy(tempstr,"\xc");
789  else if (sc==0xe)
790    strcpy(tempstr,"BKSP");
791  else if (sc==0xf)
792    strcpy(tempstr,"TAB");
793  else if (sc==0x1d)
794    strcpy(tempstr,"CTRL");
795  else if (sc==0x2A)
796    strcpy(tempstr,"LSHIFT");
797  else if (sc==0x39)
798    strcpy(tempstr,"SPACE");
799  else if (sc==0x3A)
800    strcpy(tempstr,"CAPSLK");
801  else if (sc>=0x3b && sc<=0x44)
802  {
803    char str[3];
804    strcpy(tempstr,"F");
805    itoa (sc-0x3a,str,10);
806    strcat(tempstr,str);
807  }
808  else if (sc==0x57)
809    strcpy(tempstr,"F11");
810  else if (sc==0x59)
811    strcpy(tempstr,"F12");
812  else if (sc==0x46)
813    strcpy(tempstr,"SCRLLK");
814  else if (sc==0x1c)
815    strcpy(tempstr,"ENTER");
816  else if (sc==0x36)
817    strcpy(tempstr,"RSHIFT");
818  else if (sc==0x37)
819    strcpy(tempstr,"PRTSC");
820  else if (sc==0x38)
821    strcpy(tempstr,"ALT");
822  else if (sc==0x47)
823    strcpy(tempstr,"HOME");
824  else if (sc==0x49)
825    strcpy(tempstr,"PGUP");
826  else if (sc==0x4f)
827    strcpy(tempstr,"END");
828  else if (sc==0x51)
829    strcpy(tempstr,"PGDN");
830  else if (sc==0x52)
831    strcpy(tempstr,"INS");
832  else if (sc==0x53)
833    strcpy(tempstr,"DEL");
834  else if (sc==0x45)
835    strcpy(tempstr,"NUMLK");
836  else
837    {
838     smallstr[0]=chartable[sc];
839     smallstr[1]=0;
840     strcpy(tempstr,smallstr);
841    }
842
843  return tempstr;
844 }
845
846 /////////////////////////////////////////////////////////
847 /////////////////////////////////////////////////////////
848 /////////////////////////////////////////////////////////
849 //
850 //
851 // DIALOG MANAGER CODE
852 //
853 //
854 /////////////////////////////////////////////////////////
855 /////////////////////////////////////////////////////////
856 /////////////////////////////////////////////////////////
857
858 /////////////////////////////////////////////////////////
859 //
860 // Dialog Boxes!
861 //
862 /////////////////////////////////////////////////////////
863 int DoDialog(DialogDef *TheDialog)
864 {
865  btype *TheButton;
866  int i,ox,oy,Float=0,Released=0,Clicked=0,xc[30],yc[30],wid[30];
867
868  for (i=0;i<30;i++)
869    xc[i]=yc[i]=wid[i]=0;
870
871  MouseHide();
872  SaveBackground((screencenterx-TheDialog->width/2)*8,
873    (screencentery-TheDialog->height/2)*8,(TheDialog->width+2)*8,
874    (TheDialog->height+2)*8);
875
876  xormask=0;
877  centerwindow(TheDialog->width,TheDialog->height);
878  ox=sx;
879  oy=sy;
880  print(TheDialog->text);
881  for (i=0;i<TheDialog->numbuttons;i++)
882    {
883     int xx,yy,j;
884
885     TheButton=TheDialog->buttons;
886
887     xc[i]=sx=ox+(TheButton+i)->xoff;
888     yc[i]=sy=oy+(TheButton+i)->yoff;
889     xx=sx-1;
890     yy=sy-1;
891     print((TheButton+i)->text);
892     wid[i]=strlen((TheButton+i)->text);
893
894     if ((TheButton+i)->border)
895       DrawBorder(xx,yy,wid[i]+1,2,(TheButton+i)->border);
896    }
897
898  if (TheDialog->hook)
899    {
900     HookRoutine=(void (*)(int x,int y))TheDialog->hook;
901     HookRoutine(ox,oy);
902    }
903  MouseShow();
904
905  clearkeys();
906  do
907  {
908   char temp;
909   int mx,my;
910
911   temp=((temp<<1)|(MouseButton()&1))&3;
912   MouseCoords(&mx,&my);
913   mx/=8;
914   my/=8;
915
916   //
917   // ENTER press
918   //
919   if (keydown[0x1c])
920     for(i=0;i<TheDialog->numbuttons;i++)
921       {
922        TheButton=TheDialog->buttons;
923        if ((TheButton+i)->border==2)
924          {
925           Clicked=i+1;
926           Released=1;
927           temp=Float=0;
928           while(keydown[0x1c]);
929           clearkeys();
930          }
931       }
932
933   //
934   // ESC press
935   //
936   if (keydown[1])
937     {
938      temp=Float=Clicked=0;
939      Released=1;
940      while(keydown[1]);
941     }
942
943   switch(temp)
944   {
945    case 0: // upup (no press)
946      break;
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]))
950        {
951         xormask=0;
952         sx=xc[Clicked-1];
953         sy=yc[Clicked-1];
954         MouseHide();
955         print((TheButton+Clicked-1)->text);
956         MouseShow();
957         xormask=1;
958         Float=1;
959        }
960      else
961      if (Float && mx>=xc[Clicked-1] &&
962          mx<xc[Clicked-1]+wid[Clicked-1] && my==yc[Clicked-1])
963        {
964         xormask=1;
965         sx=xc[Clicked-1];
966         sy=yc[Clicked-1];
967         MouseHide();
968         print((TheButton+Clicked-1)->text);
969         MouseShow();
970         xormask=0;
971         Float=0;
972        }
973      break;
974    case 1: // updown (press)
975      for (i=0;i<TheDialog->numbuttons;i++)
976        {
977         if (mx>=xc[i] && mx<xc[i]+wid[i] && my==yc[i])
978           {
979            Clicked=i+1;
980            xormask=1;
981            sx=xc[i];
982            sy=yc[i];
983            MouseHide();
984            print((TheButton+i)->text);
985            MouseShow();
986            xormask=0;
987            break;
988           }
989        }
990      break;
991    case 2: // downup (release)
992      if (Clicked && !Float)
993        Released++;
994   }
995  } while (!Released);
996
997  RestoreBackground();
998  return Clicked;
999 }
1000
1001
1002 /////////////////////////////////////////////////////////
1003 //
1004 // Just CHECK a Dialog Box's BUTTONS
1005 //
1006 /////////////////////////////////////////////////////////
1007 int CheckButtons(DialogDef *TheDialog)
1008 {
1009  btype *TheButton;
1010  int i,ox,oy,Float=0,Released=0,Clicked=0,xc[30],yc[30],wid[30];
1011
1012  for (i=0;i<30;i++)
1013    xc[i]=yc[i]=wid[i]=0;
1014
1015  ox=screencenterx-TheDialog->width/2+1;
1016  oy=screencentery-TheDialog->height/2+1;
1017  for (i=0;i<TheDialog->numbuttons;i++)
1018    {
1019     int xx,yy,j;
1020
1021     TheButton=TheDialog->buttons;
1022
1023     xc[i]=ox+(TheButton+i)->xoff;
1024     yc[i]=oy+(TheButton+i)->yoff;
1025     wid[i]=strlen((TheButton+i)->text);
1026    }
1027
1028
1029  clearkeys();
1030  do
1031  {
1032   char temp;
1033   int mx,my;
1034
1035   temp=((temp<<1)|(MouseButton()&1))&3;
1036   MouseCoords(&mx,&my);
1037   mx/=8;
1038   my/=8;
1039
1040   //
1041   // ENTER press
1042   //
1043   if (keydown[0x1c])
1044     for(i=0;i<TheDialog->numbuttons;i++)
1045       {
1046        TheButton=TheDialog->buttons;
1047        if ((TheButton+i)->border==2)
1048          {
1049           Clicked=i+1;
1050           Released=1;
1051           temp=Float=0;
1052           while(keydown[0x1c]);
1053           clearkeys();
1054          }
1055       }
1056
1057   //
1058   // ESC press
1059   //
1060   if (keydown[1])
1061     {
1062      temp=Float=Clicked=0;
1063      Released=1;
1064      while(keydown[1]);
1065     }
1066
1067   switch(temp)
1068   {
1069    case 0: // upup (no press)
1070      break;
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]))
1074        {
1075         xormask=0;
1076         sx=xc[Clicked-1];
1077         sy=yc[Clicked-1];
1078         MouseHide();
1079         print((TheButton+Clicked-1)->text);
1080         MouseShow();
1081         xormask=1;
1082         Float=1;
1083        }
1084      else
1085      if (Float && mx>=xc[Clicked-1] &&
1086          mx<xc[Clicked-1]+wid[Clicked-1] && my==yc[Clicked-1])
1087        {
1088         xormask=1;
1089         sx=xc[Clicked-1];
1090         sy=yc[Clicked-1];
1091         MouseHide();
1092         print((TheButton+Clicked-1)->text);
1093         MouseShow();
1094         xormask=0;
1095         Float=0;
1096        }
1097      break;
1098    case 1: // updown (press)
1099      for (i=0;i<TheDialog->numbuttons;i++)
1100        {
1101         if (mx>=xc[i] && mx<xc[i]+wid[i] && my==yc[i])
1102           {
1103            Clicked=i+1;
1104            xormask=1;
1105            sx=xc[i];
1106            sy=yc[i];
1107            MouseHide();
1108            print((TheButton+i)->text);
1109            MouseShow();
1110            xormask=0;
1111            break;
1112           }
1113        }
1114      break;
1115    case 2: // downup (release)
1116      if (Clicked && !Float)
1117        Released++;
1118   }
1119  } while (!Released);
1120  clearkeys();
1121
1122  if (Clicked)
1123  {
1124   sx=xc[Clicked-1];
1125   sy=yc[Clicked-1];
1126   MouseHide();
1127   print((TheButton+Clicked-1)->text);
1128   MouseShow();
1129  }
1130
1131  return Clicked;
1132 }
1133
1134
1135 /////////////////////////////////////////////////////////
1136 //
1137 // Just CHECK a Dialog Box's BUTTONS
1138 // BUT!...RETURN IF MOUSE BUTTON IS PRESSED OUTSIDE DIALOG BUTTON!
1139 //
1140 /////////////////////////////////////////////////////////
1141 int CheckButtonsRet(DialogDef *TheDialog)
1142 {
1143  btype *TheButton;
1144  int i,ox,oy,Float=0,Released=0,Clicked=0,xc[30],yc[30],wid[30];
1145
1146  for (i=0;i<30;i++)
1147    xc[i]=yc[i]=wid[i]=0;
1148
1149  ox=screencenterx-TheDialog->width/2+1;
1150  oy=screencentery-TheDialog->height/2+1;
1151  for (i=0;i<TheDialog->numbuttons;i++)
1152    {
1153     int xx,yy,j;
1154
1155     TheButton=TheDialog->buttons;
1156
1157     xc[i]=ox+(TheButton+i)->xoff;
1158     yc[i]=oy+(TheButton+i)->yoff;
1159     wid[i]=strlen((TheButton+i)->text);
1160    }
1161
1162  do
1163  {
1164   char temp;
1165   int mx,my;
1166
1167   temp=((temp<<1)|(MouseButton()&1))&3;
1168   if (MouseButton()&2)
1169     return -1;
1170
1171   MouseCoords(&mx,&my);
1172   mx/=8;
1173   my/=8;
1174
1175   //
1176   // ENTER press
1177   //
1178   if (keydown[0x1c])
1179     for(i=0;i<TheDialog->numbuttons;i++)
1180       {
1181        TheButton=TheDialog->buttons;
1182        if ((TheButton+i)->border==2)
1183          {
1184           Clicked=i+1;
1185           Released=1;
1186           temp=Float=0;
1187           while(keydown[0x1c]);
1188           clearkeys();
1189          }
1190       }
1191
1192   //
1193   // ESC press
1194   //
1195   if (keydown[1])
1196     {
1197      temp=Float=Clicked=0;
1198      Released=1;
1199      while(keydown[1]);
1200     }
1201
1202   //
1203   // arrows or PgUp/PgDn/Home/End
1204   //
1205   if (keydown[0x48] || keydown[0x50] || keydown[0x4b] || keydown[0x4d] ||
1206       keydown[0x49] || keydown[0x51] || keydown[0x47] || keydown[0x4f] ||
1207       keydown[0x39] || keydown[0x2e])
1208     return -1;
1209
1210   switch(temp)
1211   {
1212    case 0: // upup (no press)
1213      break;
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]))
1217        {
1218         xormask=0;
1219         sx=xc[Clicked-1];
1220         sy=yc[Clicked-1];
1221         MouseHide();
1222         print((TheButton+Clicked-1)->text);
1223         MouseShow();
1224         xormask=1;
1225         Float=1;
1226        }
1227      else
1228      if (Float && mx>=xc[Clicked-1] &&
1229          mx<xc[Clicked-1]+wid[Clicked-1] && my==yc[Clicked-1])
1230        {
1231         xormask=1;
1232         sx=xc[Clicked-1];
1233         sy=yc[Clicked-1];
1234         MouseHide();
1235         print((TheButton+Clicked-1)->text);
1236         MouseShow();
1237         xormask=0;
1238         Float=0;
1239        }
1240      break;
1241    case 1: // updown (press)
1242      for (i=0;i<TheDialog->numbuttons;i++)
1243        {
1244         if (mx>=xc[i] && mx<xc[i]+wid[i] && my==yc[i])
1245           {
1246            Clicked=i+1;
1247            xormask=1;
1248            sx=xc[i];
1249            sy=yc[i];
1250            MouseHide();
1251            print((TheButton+i)->text);
1252            MouseShow();
1253            xormask=0;
1254            break;
1255           }
1256        }
1257
1258      if (!Clicked)      // MOD TO ORIGINAL CHECKBUTTONS
1259        return -1;
1260
1261      break;
1262    case 2: // downup (release)
1263      if (Clicked && !Float)
1264        Released++;
1265   }
1266  } while (!Released);
1267  clearkeys();
1268  return Clicked;
1269 }
1270
1271
1272 /////////////////////////////////////////////////////////
1273 //
1274 // Just DRAW a Dialog Box
1275 //
1276 /////////////////////////////////////////////////////////
1277 void DrawDialog(DialogDef *TheDialog,int saveback)
1278 {
1279  btype *TheButton;
1280  int i,ox,oy,xc[30],yc[30],wid[30];
1281
1282  for (i=0;i<30;i++)
1283    xc[i]=yc[i]=wid[i]=0;
1284
1285  MouseHide();
1286  if (saveback)
1287    SaveBackground((screencenterx-TheDialog->width/2)*8,
1288      (screencentery-TheDialog->height/2)*8,(TheDialog->width+2)*8,
1289      (TheDialog->height+2)*8);
1290
1291  xormask=0;
1292  centerwindow(TheDialog->width,TheDialog->height);
1293  ox=sx;
1294  oy=sy;
1295  print(TheDialog->text);
1296  for (i=0;i<TheDialog->numbuttons;i++)
1297    {
1298     int xx,yy,j;
1299
1300     TheButton=TheDialog->buttons;
1301
1302     xc[i]=sx=ox+(TheButton+i)->xoff;
1303     yc[i]=sy=oy+(TheButton+i)->yoff;
1304     xx=sx-1;
1305     yy=sy-1;
1306     print((TheButton+i)->text);
1307     wid[i]=strlen((TheButton+i)->text);
1308
1309     if ((TheButton+i)->border)
1310       DrawBorder(xx,yy,wid[i]+1,2,(TheButton+i)->border);
1311    }
1312
1313  if (TheDialog->hook)
1314    {
1315     HookRoutine=(void (*)(int x,int y))TheDialog->hook;
1316     HookRoutine(ox,oy);
1317    }
1318
1319  MouseShow();
1320 }
1321
1322
1323 /////////////////////////////////////////////////////////
1324 //
1325 // Error Dialog Box
1326 //
1327 /////////////////////////////////////////////////////////
1328 char errstring[200],bstring[20];
1329 btype ERROKb={bstring,0,0,2};
1330 DialogDef ERRR={errstring,0,0,1,&ERROKb,NULL};
1331
1332 void ErrDialog(char *string,char *bstr)
1333 {
1334  int maxw=0,width=0,height=1,i;
1335
1336  if (strlen(string)>200)
1337    Quit("Programmer Error: ErrDialog string is too long!");
1338
1339  for (i=0;i<strlen(string);i++)
1340    {
1341     width++;
1342     if (width>maxw)
1343       maxw=width;
1344
1345     if (string[i]=='\n')
1346       {
1347        height++;
1348        width=0;
1349       }
1350    }
1351  height+=3;     // add for button!
1352
1353  if (strlen(bstr)>maxw)
1354    Quit("Programmer Error: ErrDialog BUTTONstring is longer than dialog!");
1355
1356  strcpy(bstring,bstr);
1357  strcpy(errstring,string);
1358  ERRR.width=maxw;
1359  ERRR.height=height;
1360  ERRR.numbuttons=1;
1361  if (!bstr[0])
1362    {
1363     ERRR.numbuttons=0;
1364     ERRR.height-=3;
1365    }
1366
1367  ERROKb.xoff=(maxw/2)-(strlen(bstr)/2);
1368  ERROKb.yoff=height-2;
1369
1370  if (bstr[0])
1371    DoDialog(&ERRR);
1372  else
1373    DrawDialog(&ERRR,1);
1374 }
1375
1376
1377 /////////////////////////////////////////////////////////
1378 //
1379 // Draw a border
1380 //
1381 /////////////////////////////////////////////////////////
1382 void DrawBorder(int x,int y,int w,int h,int b)
1383 {
1384  int xx=x,yy=y,j;
1385
1386  if (b==2)
1387    {
1388     drawchar(xx,yy,15);
1389     drawchar(xx+w,yy,17);
1390     drawchar(xx,yy+h,20);
1391     drawchar(xx+w,yy+h,22);
1392
1393     for (j=yy+1;j<yy+h;j++)
1394       {
1395        drawchar(xx,j,18);
1396        drawchar(xx+w,j,19);
1397       }
1398     for (j=xx+1;j<xx+w;j++)
1399       {
1400        drawchar(j,yy,16);
1401        drawchar(j,yy+h,21);
1402       }
1403    }
1404
1405  if (b==1)
1406    {
1407     drawchar(xx,yy,23);
1408     drawchar(xx+w,yy,25);
1409     drawchar(xx,yy+h,28);
1410     drawchar(xx+w,yy+h,30);
1411
1412     for (j=yy+1;j<yy+h;j++)
1413       {
1414        drawchar(xx,j,26);
1415        drawchar(xx+w,j,27);
1416       }
1417     for (j=xx+1;j<xx+w;j++)
1418       {
1419        drawchar(j,yy,24);
1420        drawchar(j,yy+h,29);
1421       }
1422    }
1423
1424 }
1425
1426
1427 /////////////////////////////////////////////////////////
1428 //
1429 // Get the XY coords of a dialog's button
1430 //
1431 /////////////////////////////////////////////////////////
1432 void GetButtonXY(DialogDef *TheDialog,int button,unsigned *x,unsigned *y)
1433 {
1434  btype *TheButton;
1435
1436  TheButton=TheDialog->buttons;
1437
1438  *x=(TheButton+button)->xoff+screencenterx-TheDialog->width/2+1;
1439  *y=(TheButton+button)->yoff+screencentery-TheDialog->height/2+1;
1440 }
1441
1442
1443 /////////////////////////////////////////////////////////
1444 //
1445 // Get the XY coords of a dialog
1446 //
1447 /////////////////////////////////////////////////////////
1448 void GetDialogXY(DialogDef *TheDialog,unsigned *x,unsigned *y)
1449 {
1450  *x=screencenterx-TheDialog->width/2+1;
1451  *y=screencentery-TheDialog->height/2+1;
1452 }
1453
1454
1455 ////////////////////////////////////////////////////
1456 //
1457 // Allow user to select a list item (like the menus)
1458 //
1459 ////////////////////////////////////////////////////
1460 int CheckList(int x,int y,int w,int h,void (*oncode)(),void (*offcode)(),int blink)
1461 {
1462  enum {upup,updown,downup,downdown} clicks;
1463  static char bpress=0;
1464  unsigned mx,my,i;
1465  int high=-1;
1466
1467
1468  while(1)
1469  {
1470   MouseCoords(&(int)mx,&(int)my);
1471   mx/=8;
1472   my/=8;
1473   bpress=((bpress<<1)|(MouseButton()&1))&3;
1474   switch(bpress)
1475   {
1476    case upup:
1477      return -1;
1478    case updown:
1479      if (mx>=x && mx<x+w && my>=y && my<y+h)
1480        {
1481         high=my-y;
1482         MouseHide();
1483         oncode(x,my,high);
1484         MouseShow();
1485        }
1486      else
1487        return -1;
1488
1489      break;
1490    case downup:
1491      if (high!=-1)
1492        {
1493         if (blink)
1494           for(i=0;i<5;i++)
1495           {
1496            MouseHide();
1497            oncode(x,my,high);
1498            MouseShow();
1499            WaitVBL(3);
1500
1501            MouseHide();
1502            offcode(x,my,high);
1503            WaitVBL(3);
1504            MouseShow();
1505           }
1506        }
1507      return high;
1508
1509    case downdown:
1510      if (mx>=x && mx<x+w && my>=y && my<y+h)
1511        {
1512         if (my-y != high && high!=-1)
1513           {
1514            MouseHide();
1515            offcode(x,high+y,high);
1516            MouseShow();
1517
1518           }
1519
1520         if (my-y != high)
1521           {
1522            high=my-y;
1523            MouseHide();
1524            oncode(x,y+high,high);
1525            MouseShow();
1526           }
1527        }
1528      else
1529        {
1530         if (high!=-1)
1531           {
1532            MouseHide();
1533            offcode(x,high+y,high);
1534            MouseShow();
1535           }
1536         high=-1;
1537         return -1;
1538        }
1539   }
1540  }
1541 }
1542
1543
1544 /////////////////////////////////////////////////
1545 //
1546 // Message dialog
1547 // Returns: -1=ESC, 0=No, 1=Yes
1548 //
1549 /////////////////////////////////////////////////
1550 char MessStr[200];
1551 btype MessOKb[]={{" No ",0,0,1},{" Yes ",0,0,2}};
1552 DialogDef Mess={MessStr,0,0,2,&MessOKb[0],NULL};
1553
1554 int Message(char *string)
1555 {
1556  int maxw=0,width=0,height=1,i;
1557
1558  if (strlen(string)>200)
1559    Quit("Programmer Error: Message string is too long!");
1560
1561  for (i=0;i<strlen(string);i++)
1562    {
1563     width++;
1564     if (width>maxw)
1565       maxw=width;
1566
1567     if (string[i]=='\n')
1568       {
1569        height++;
1570        width=0;
1571       }
1572    }
1573  height+=3;     // add for buttons!
1574
1575  strcpy(MessStr,string);
1576  Mess.width=maxw;
1577  Mess.height=height;
1578
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;
1583
1584  return DoDialog(&Mess);
1585 }
1586
1587
1588 /////////////////////////////////////////////////
1589 //
1590 // GetPath dialog
1591 // *path is returned
1592 // (exit:0 if OK,-1 if Not Successful,-2 if Canceled)
1593 //
1594 /////////////////////////////////////////////////
1595 #define LISTX   1
1596 #define LISTY   3
1597
1598 char dstr[80];
1599 btype GPb={"Cancel",15,3,1};
1600 DialogDef GPd={dstr,22,14,1,&GPb,NULL};
1601 char NameList[MAXFDNAMES][13];
1602 int base;
1603 struct ffblk f;
1604
1605 int GetPath(char *string,char *filter,char *path)
1606 {
1607  char pname[64];
1608  unsigned int numnames=0,max,dx,dy,redraw,exit;
1609  int select,zset,i;
1610
1611
1612  strcpy(pname,filter);
1613  for (zset=0,i=strlen(pname);i>=0;i--)
1614    if (pname[i]=='\\')
1615      {
1616       pname[i+1]=0;
1617       zset++;
1618       break;
1619      }
1620  if (!zset)
1621    pname[0]=0;
1622
1623  strcpy(dstr,string);
1624  //
1625  // FIRST, GET THE NAMES FROM THE DIRECTORY
1626  //
1627  if (findfirst(filter,&f,FA_ARCH))
1628    return -1;
1629  strcpy(NameList[numnames++],f.ff_name);
1630
1631  while(!findnext(&f) && numnames<MAXFDNAMES)
1632    strcpy(NameList[numnames++],f.ff_name);
1633
1634  DrawDialog(&GPd,1);
1635  MouseHide();
1636  GetDialogXY(&GPd,&dx,&dy);
1637  DrawBorder(dx+LISTX-1,dy+LISTY-1,13,11,1);
1638  MouseShow();
1639
1640  base=exit=0;
1641
1642  //
1643  // THIS LOOP DRAWS THE DIALOG
1644  //
1645  do
1646  {
1647   redraw=0;
1648   MouseHide();
1649   max=10;
1650   if (numnames<10)
1651     max=numnames;
1652   for (i=0;i<max;i++)
1653     {
1654      bar(dx+LISTX,dy+LISTY+i,dx+LISTX+11,dy+LISTY+i,' ');
1655      FDoff(dx+LISTX,dy+LISTY+i,i);
1656     }
1657   MouseShow();
1658
1659   //
1660   // THIS LOOP CHECKS INPUT
1661   //
1662   do
1663   {
1664    select=CheckList(dx+LISTX,dy+LISTY,12,max,FDon,FDoff,0);
1665    if (select>=0)
1666      {
1667       redraw=exit=1;
1668       continue;
1669      }
1670
1671    GetButtonXY(&GPd,0,&sx,&sy);
1672    select=CheckList(sx,sy,strlen(GPb.text),1,CancelOn,CancelOff,0);
1673    if (!select || keydown[1])
1674      {
1675       RestoreBackground();
1676       while(keydown[1]);
1677       clearkeys();
1678       return -2;
1679      }
1680
1681    //
1682    // CHECK ARROWS & PGUP/DN
1683    //
1684    if (keydown[0x48] && base)
1685      {
1686       base--;
1687       redraw=1;
1688       if (!keydown[0x1d])
1689         while(keydown[0x48]);
1690      }
1691    else
1692    if (keydown[0x50] && base+10<numnames)
1693      {
1694       base++;
1695       redraw=1;
1696       if (!keydown[0x1d])
1697         while(keydown[0x50]);
1698      }
1699    else
1700    if (keydown[0x49])
1701      {
1702       base-=10;
1703       if (base<0)
1704         base=0;
1705       redraw=1;
1706       if (!keydown[0x1d])
1707         while(keydown[0x49]);
1708      }
1709    else
1710    if (keydown[0x51])
1711      {
1712       base+=10;
1713       if (base+10>numnames)
1714         base=numnames-10;
1715       redraw=1;
1716       if (!keydown[0x1d])
1717         while(keydown[0x51]);
1718      }
1719
1720   } while(!redraw);
1721  } while(!exit);
1722
1723  //
1724  // RETURN PATHNAME
1725  //
1726  RestoreBackground();
1727  strcpy(path,pname);
1728  strcat(path,NameList[select+base]);
1729  findfirst(path,&f,FA_ARCH);
1730  return 0;
1731 }
1732
1733
1734 static void FDon(int x,int y,int w)
1735 {
1736  xormask=1;
1737  FDoff(x,y,w);
1738  xormask=0;
1739 }
1740
1741 static void FDoff(int x,int y,int w)
1742 {
1743  MouseHide();
1744  sx=x;
1745  sy=y;
1746  print(NameList[w+base]);
1747  MouseShow();
1748 }
1749
1750
1751 static void CancelOn(int x,int y)
1752 {
1753  xormask=1;
1754  CancelOff(x,y);
1755  xormask=0;
1756 }
1757
1758 static void CancelOff(int x,int y)
1759 {
1760  MouseHide();
1761  sx=x;
1762  sy=y;
1763  print("Cancel");
1764  MouseShow();
1765 }
1766
1767
1768 /////////////////////////////////////////////////
1769 //
1770 // GetList dialog
1771 // Fill "NameList[?][13]" with your strings
1772 // (exit:>=0 is selection,-1 if Not Successful,-2 if Canceled)
1773 //
1774 /////////////////////////////////////////////////
1775 int GetList(char *string,int numnames)
1776 {
1777  unsigned int max,dx,dy,redraw,exit,i;
1778  int select;
1779
1780
1781  strcpy(dstr,string);
1782
1783  DrawDialog(&GPd,1);
1784  MouseHide();
1785  GetDialogXY(&GPd,&dx,&dy);
1786  DrawBorder(dx+LISTX-1,dy+LISTY-1,13,11,1);
1787  MouseShow();
1788
1789  base=exit=0;
1790
1791  //
1792  // THIS LOOP DRAWS THE DIALOG
1793  //
1794  do
1795  {
1796   redraw=0;
1797   MouseHide();
1798   max=10;
1799   if (numnames<10)
1800     max=numnames;
1801   for (i=0;i<max;i++)
1802     {
1803      bar(dx+LISTX,dy+LISTY+i,dx+LISTX+11,dy+LISTY+i,' ');
1804      FDoff(dx+LISTX,dy+LISTY+i,i);
1805     }
1806   MouseShow();
1807
1808   //
1809   // THIS LOOP CHECKS INPUT
1810   //
1811   do
1812   {
1813    select=CheckList(dx+LISTX,dy+LISTY,12,max,FDon,FDoff,0);
1814    if (select>=0)
1815      {
1816       redraw=exit=1;
1817       continue;
1818      }
1819
1820    GetButtonXY(&GPd,0,&sx,&sy);
1821    select=CheckList(sx,sy,strlen(GPb.text),1,CancelOn,CancelOff,0);
1822    if (!select || keydown[1])
1823      {
1824       RestoreBackground();
1825       while(keydown[1]);
1826       clearkeys();
1827       return -2;
1828      }
1829
1830    //
1831    // CHECK ARROWS & PGUP/DN
1832    //
1833    if (keydown[0x48] && base)
1834      {
1835       base--;
1836       redraw=1;
1837       if (!keydown[0x1d])
1838         while(keydown[0x48]);
1839      }
1840    else
1841    if (keydown[0x50] && base+10<numnames)
1842      {
1843       base++;
1844       redraw=1;
1845       if (!keydown[0x1d])
1846         while(keydown[0x50]);
1847      }
1848    else
1849    if (keydown[0x49])
1850      {
1851       base-=10;
1852       if (base<0)
1853         base=0;
1854       redraw=1;
1855       if (!keydown[0x1d])
1856         while(keydown[0x49]);
1857      }
1858    else
1859    if (keydown[0x51])
1860      {
1861       base+=10;
1862       if (base+10>numnames)
1863         base=numnames-10;
1864       redraw=1;
1865       if (!keydown[0x1d])
1866         while(keydown[0x51]);
1867      }
1868
1869   } while(!redraw);
1870  } while(!exit);
1871
1872  //
1873  // RETURN SELECTION
1874  //
1875  RestoreBackground();
1876  return select+base;
1877 }