home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / nethack-3.1 / sys / amiga / wbcli.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-22  |  37.5 KB  |  1,991 lines

  1. /*    SCCS Id: @(#)wbcli.c  2.1   93/01/08              */
  2. /*    Copyright (c) Kenneth Lorber, Bethesda, Maryland, 1991      */
  3. /*    Copyright (c) Gregg Wonderly, Naperville, IL, 1992, 1993    */
  4. /* NetHack may be freely redistributed.  See license for details. */
  5.  
  6. /* Friendly Intuition interface for NetHack 3.1 on the Amiga */
  7.  
  8. /*
  9.  * This file contains many routines common to the CLI and WB interfaces,
  10.  * along with a few specific to each.  #defining CLI supports the CLI
  11.  * interface; not #defining it supports (along with wb.c) the WB interface.
  12.  */
  13.  
  14. #include "Incl:date.h"          /* this gives us the version string */
  15.  
  16. #ifdef AZTEC_C
  17. /* Aztec doesn't recognize __chip syntax */
  18. # define __chip
  19. #endif
  20.  
  21. #include "Amiga:wbdefs.h"       /* Miscellany information */
  22. #ifdef  INTUI_NEW_LOOK
  23. #define NewWindow   ExtNewWindow
  24. #define NewScreen   ExtNewScreen
  25. #endif
  26. #include "Amiga:wbstruct.h"
  27. #include "Amiga:wbprotos.h"
  28.  
  29. #ifdef CLI
  30. #include "Amiga:wbdata.c"       /* All structures and global data */
  31.  
  32. #undef NetHackCnf
  33. char NetHackCnf[50]="NetHack:NetHack.cnf";
  34. #endif  /* CLI */
  35.  
  36. #define C_GREY  0
  37. #define C_BLACK 1
  38. #define C_WHITE 2
  39. #define C_BLUE  3
  40.  
  41. #ifndef __SASC_60
  42. extern char *sys_errlist[];
  43. #endif
  44. extern int errno;
  45.  
  46. #define SPLIT           /* use splitter, if available */
  47.  
  48. void diskobj_filter(struct DiskObject *);
  49. BPTR s_LoadSeg(char *);
  50. void s_UnLoadSeg(void);
  51.  
  52. #ifdef CLI
  53. char *cnfsavedir="NetHack:save";    /* unless overridden in cnf file */
  54. char argline[255];  /* no overflow - bigger than ADOS will pass */
  55.  
  56. void WaitEOG(GPTR);
  57. char *eos(char *);
  58. void condaddslash(char *);
  59.  
  60. # ifdef SPLIT
  61. int running_split=0;        /* if 0, using normal LoadSeg/UnLoadSeg */
  62. # endif
  63. #else
  64. extern char *options[NUMIDX+1];
  65. extern GPTR gamehead,gameavail;
  66. extern DEFAULTS defgame;
  67. extern struct Window *win;
  68. #endif  /* CLI */
  69.  
  70. #ifdef AZTEC_C
  71. extern char *strdup(char *);
  72.  
  73. /*
  74.  * Aztec has a strnicmp, but it doesn't work properly.
  75.  *
  76.  * Note: this came out of NHS:hacklib.c
  77.  */
  78. static char
  79. lowc(c)         /* force 'c' into lowercase */
  80.     char c;
  81. {
  82.     return ('A' <= c && c <= 'Z') ? (c | 040) : c;
  83. }
  84.  
  85. int
  86. strnicmp(s1, s2, n)
  87.     register const char *s1, *s2;
  88.     register int n;
  89. {
  90.     register char t1, t2;
  91.  
  92.     while (n--) {
  93.     if (!*s2) return (*s1 != 0);    /* s1 >= s2 */
  94.     else if (!*s1) return -1;   /* s1  < s2 */
  95.     t1 = lowc(*s1++);
  96.     t2 = lowc(*s2++);
  97.     if (t1 != t2) return (t1 > t2) ? 1 : -1;
  98.     }
  99.     return 0;               /* s1 == s2 */
  100. }
  101. #endif
  102.  
  103. #ifndef max
  104. # define max(a, b) ((a) > (b) ? (a) : (b))
  105. #endif
  106. #ifndef min
  107. # define min(x,y) ((x) < (y) ? (x) : (y))
  108. #endif
  109.  
  110. char *copyright_text[]={
  111. "NetHack, Copyright 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993.",
  112. "         By Stichting Mathematisch Centrum and M. Stephenson.",
  113. "         See license for details.",
  114. 0
  115. };
  116.  
  117. #ifdef CLI
  118.  
  119. main( argc, wbs )
  120.     int argc;
  121.     struct WBStartup *wbs;
  122. {
  123.     GPTR gptr;
  124.     BPTR lc,lc2;
  125.     struct FileInfoBlock finfo;
  126.     char *name;
  127.     char namebuf[50];
  128.     char **argv=(char **)wbs;
  129.  
  130.     ZapOptions( curopts );
  131.     InitWB( argc, (struct WBStartup *)argv );
  132.     errmsg( NO_FLASH, "Welcome to NetHack Version 3.1!\n" );
  133.     CopyRight( );
  134.  
  135.     ReadConfig( );
  136.  
  137.     /* Wait till user quits */
  138.  
  139.     while( !quit )
  140.     {
  141.     char tbuf[8];
  142.     char *p=tbuf;
  143.     char *dirname=cnfsavedir;
  144. /* play a game */
  145.     {
  146.         int c;
  147.         argline[0]='\0';
  148.         name="NewGame.info";        /* this will fail - it's in NetHack: */
  149.         for(c=1;c<argc;c++){
  150.         /* slow but easy - not a critical path */
  151.         strcpy(eos(argline),argv[c]);
  152.         if(!strncmp(argv[c],"-u",2)){
  153.             if(!strcmp(argv[c],"-u")){
  154.             name= argv[c+1];
  155.             }else{
  156.             name= &argv[c][1];
  157.             }
  158.         }
  159.         if(c<argc)strcpy(eos(argline)," ");
  160.         }
  161.         eos(argline)[-1]='\0';
  162.     }
  163.     strcpy(namebuf,cnfsavedir);
  164.     condaddslash(namebuf);
  165.     strcpy(eos(namebuf),name);
  166.     lc=Lock(namebuf,ACCESS_READ);
  167.     if(!lc){
  168.         dirname="NetHack:";
  169.         strcpy(namebuf,dirname);
  170.         strcpy(eos(namebuf),"NewGame.info");
  171.         lc=Lock(namebuf,ACCESS_READ);
  172.         if(!lc){
  173.         errmsg(NO_FLASH,"can't find NewGame.info");
  174.         cleanup(1);
  175.         }
  176.     }
  177.     Examine(lc,&finfo);
  178.     lc2=ParentDir(lc);
  179.     UnLock(lc);
  180.     gptr=GetWBIcon(lc2,dirname,&finfo);
  181.     UnLock(lc2);
  182.     run_game(gptr);
  183.  
  184. /* wait for game to end */
  185.     WaitEOG(gptr);
  186.     FreeGITEM(gptr);
  187. /* ask about another? */
  188.     printf("Play again? [yn] ");
  189.     fgets(tbuf,sizeof(tbuf),stdin);
  190.     while(*p && isspace(*p))p++;
  191.     switch(*p){
  192.     case 'n':
  193.     case 'N':
  194.         quit=1;
  195.     }
  196.     }
  197.     cleanup(0);
  198. }
  199.  
  200. /* CLI */
  201.  
  202. void
  203. WaitEOG(target)
  204.     GPTR target;
  205. {
  206.     long mask, rmask;
  207.     struct WBStartup *wbs;
  208.     struct WBArg *wba;
  209.     int i;
  210.     /* Get a message */
  211.     while(1){
  212.     mask = ( 1L << dosport->mp_SigBit ) ;
  213.     rmask = Wait( mask );
  214.  
  215.  
  216.     if( rmask & ( 1L << dosport->mp_SigBit ) )
  217.     {
  218.         /* Get process termination messages */
  219.  
  220.         while( wbs = (struct WBStartup *) GetMsg( dosport ) )
  221.         {
  222.         /* Find the game that has terminated */
  223.  
  224.         if(target->seglist == wbs->sm_Segment)
  225.         {
  226. #ifdef SPLIT
  227.             if(!running_split)
  228. #endif
  229.             /* Unload the code */
  230.             UnLoadSeg( wbs->sm_Segment );
  231.             /* Free the startup message resources */
  232.  
  233.             wba = (struct WBArg *)
  234.             ((long)wbs + sizeof( struct WBStartup ));
  235.             for( i = 0; i < wbs->sm_NumArgs; ++i )
  236.             {
  237.             FreeMem( wba[i].wa_Name, strlen( wba[i].wa_Name ) + 1 );
  238.             UnLock( wba[i].wa_Lock );
  239.             }
  240.             FreeMem( wbs, wbs->sm_Message.mn_Length );
  241.             wbs = NULL;
  242.  
  243.             return;
  244.         }
  245.         }
  246.  
  247.     }
  248.     }
  249. }
  250.  
  251. /* CLI */
  252.  
  253. void CopyRight()
  254. {
  255.     int line;
  256.     for(line=0;copyright_text[line];line++){
  257.     printf("%s\n",copyright_text[line]);
  258.     }
  259. }
  260.  
  261. /* CLI */
  262.  
  263. /*
  264.  * Do the one time initialization things.
  265.  */
  266.  
  267. void
  268. InitWB( argc, wbs )
  269.     int argc;
  270.     register struct WBStartup *wbs;
  271. {
  272.  
  273.     /* Open Libraries */
  274.     GfxBase= (struct GfxBase *) OldOpenLibrary("graphics.library");
  275.     IconBase= OldOpenLibrary("icon.library");
  276.     DiskfontBase= (struct DiskfontBase *)OldOpenLibrary("diskfont.library");
  277.     IntuitionBase= (struct IntuitionBase *)OldOpenLibrary("intuition.library");
  278.  
  279.     if(!GfxBase || !IconBase || !DiskfontBase || !IntuitionBase)
  280.     {
  281.     error("library open failed");
  282.     cleanup( 1 );
  283.     }
  284.  
  285.     /* Get Port for replied WBStartup messages */
  286.  
  287.     if( ( dosport = CreatePort( NULL, 0 ) ) == NULL )
  288.     {
  289.     error("failed to create dosport" );
  290.     cleanup( 1 );
  291.     }
  292.  
  293.     /* If started from CLI */
  294.     if( argc == 0 ){
  295.     printf("Run this program from CLI only.\n");
  296.     DisplayBeep(0);     /* could be more specific */
  297.     Delay(400);
  298.     cleanup(1);
  299.     }
  300. }
  301.  
  302. /* CLI */
  303.  
  304. /*
  305.  * Read a nethack.cnf like file and collect the configuration
  306.  * information from it.
  307.  */
  308. void ReadConfig()
  309. {
  310.     register FILE *fp;
  311.     register char *buf, *t;
  312.  
  313.     /* Use a dynamic buffer to limit stack use */
  314.  
  315.     if( ( buf = xmalloc( 1024 ) ) == NULL )
  316.     {
  317.     error( "Can't alloc space to read config file" );
  318.     cleanup( 1 );
  319.     }
  320.  
  321.     /* If the file is not there, can't load it */
  322.  
  323.     if( ( fp = fopen( NetHackCnf, "r" ) ) == NULL )
  324.     {
  325.     errmsg( FLASH, "Can't load config file %s", NetHackCnf );
  326.     free( buf );
  327.     return;
  328.     }
  329.  
  330.     /* Read the lines... */
  331.  
  332.     while( fgets( buf, 1024, fp ) != NULL )
  333.     {
  334.     if( *buf == '#' )
  335.         continue;
  336.  
  337.     if( ( t = strchr( buf, '\n' ) ) != NULL )
  338.         *t = 0;
  339.  
  340.     if( strnicmp( buf, "SAVE=", 5 ) == 0 )
  341.     {
  342.         cnfsavedir=strdup(buf+5);
  343.     }
  344.     else
  345.     {
  346.         /* We don't care about the rest */
  347.     }
  348.     }
  349.     fclose( fp );
  350.     free( buf );
  351. }
  352.  
  353. /* CLI */
  354.  
  355. void
  356. run_game( gptr )
  357.     register GPTR gptr;
  358. {
  359.     struct Task *ctask;
  360.     register struct MsgPort *proc = NULL;
  361.     int tidx;
  362.  
  363.     tidx = 0;
  364.  
  365.     gptr->gname = xmalloc( 20 + strlen( gptr->name ) );
  366.  
  367.     SetToolLine(gptr, "INTERNALCLI", argline);
  368.     gptr->wbs = AllocMem( sizeof( struct WBStartup ) +
  369.     ( sizeof( struct WBArg ) * 2 ), MEMF_PUBLIC | MEMF_CLEAR );
  370.  
  371.     /* Check if we got everything */
  372.  
  373.     if( !gptr->gname || !gptr->wbs )
  374.     {
  375.     fprintf( stderr, "Can't allocate memory\n" );
  376.     goto freemem;
  377.     }
  378.  
  379.     /* Get the arguments structure space */
  380.  
  381.     gptr->wba = ( struct WBArg * ) ((long)gptr->wbs + 
  382.     sizeof( struct WBStartup ) );
  383.     /* Load the game into memory */
  384. #ifdef SPLIT
  385.     /* Which version do we run? */
  386.     {
  387.     char gi[80];
  388.     BPTR tmplock;
  389.  
  390.     sprintf( gi, "%s.dir", GAMEIMAGE );
  391.     tmplock=Lock( gi, ACCESS_READ );
  392.     if( tmplock ){
  393.     UnLock( tmplock );
  394.     gptr->seglist = (BPTR)s_LoadSeg( gi );
  395.     if(gptr->seglist)running_split=1;
  396.     }else{
  397.     gptr->seglist = (BPTR)LoadSeg( GAMEIMAGE );
  398.     }
  399.     }
  400. #else
  401.     gptr->seglist = (BPTR)LoadSeg( GAMEIMAGE );
  402. #endif
  403.  
  404.     if( gptr->seglist == NULL)
  405.     {
  406.     errmsg( FLASH, "Can't load %s", GAMEIMAGE );
  407.     goto freemem;
  408.     }
  409.  
  410.     /* Set the game name for the status command */
  411.     sprintf( gptr->gname, "NetHack 3.1 %s", gptr->name );
  412.  
  413.     /* Create a process for the game to execute in */
  414.     ctask = FindTask( NULL );
  415.     proc = CreateProc( gptr->gname, ctask->tc_Node.ln_Pri,
  416.             gptr->seglist, GAMESTACK );
  417.  
  418.     /* Check if the create failed */
  419.  
  420.     if( proc == NULL )
  421.     {
  422.     fprintf(stderr, "Error creating process %d\n", IoErr() );
  423. #ifdef SPLIT
  424.     if(!running_split)
  425. #endif
  426.         UnLoadSeg( gptr->seglist );
  427. freemem:
  428.     if( gptr->gname ) free( gptr->gname );
  429.     gptr->gname = NULL;
  430.  
  431.     if( gptr->wbs ) FreeMem( gptr->wbs,
  432.         sizeof( struct WBStartup ) + sizeof( struct WBArg ) * 2 );
  433.     gptr->wbs = NULL;
  434.     return;
  435.     }
  436.  
  437.     /* Get the Process structure pointer */
  438.     gptr->prc = (struct Process *) (((long)proc) - sizeof( struct Task ));
  439.  
  440.     /* Set the current directory */
  441.     gptr->prc->pr_CurrentDir=((struct Process *)FindTask(NULL))->pr_CurrentDir;
  442.  
  443.     /* Fill in the startup message */
  444.     gptr->wbs->sm_Process = proc;
  445.     gptr->wbs->sm_Segment = gptr->seglist;
  446.     gptr->wbs->sm_NumArgs = 2;
  447.     gptr->wbs->sm_ToolWindow = "con:0/0/100/300/NetHack 3.1";
  448.     gptr->wbs->sm_ArgList = gptr->wba;
  449.  
  450.     /* Fill in the args */
  451.  
  452.     gptr->wba[0].wa_Name = Strdup( GAMEIMAGE );
  453.     gptr->wba[0].wa_Lock = Lock( dirname( GAMEIMAGE ), ACCESS_READ );
  454.  
  455.     gptr->wba[1].wa_Name = Strdup( gptr->name );
  456.     gptr->wba[1].wa_Lock = Lock( gptr->dname, ACCESS_READ );
  457.  
  458.     /* Write the updated tools types entries */
  459.  
  460.     WriteDObj( gptr, gptr->wba[1].wa_Lock );
  461.  
  462.     /* Set the message fields correctly */
  463.  
  464.     gptr->wbs->sm_Message.mn_Node.ln_Type = NT_MESSAGE;
  465.     gptr->wbs->sm_Message.mn_Node.ln_Pri = 0;
  466.     gptr->wbs->sm_Message.mn_ReplyPort = dosport;
  467.     gptr->wbs->sm_Message.mn_Length =
  468.     sizeof( struct WBStartup ) + ( sizeof( struct WBArg ) * 2 );
  469.  
  470.     /* Send the WB Startup message to let the game go... */
  471.  
  472.     PutMsg( proc, &gptr->wbs->sm_Message );
  473. }
  474.  
  475. #else   /* CLI */
  476.  
  477. void RPText( rp, s )
  478.     struct RastPort *rp;
  479.     register char *s;
  480. {
  481.     Text( rp, s, strlen( s ) );
  482. }
  483.  
  484. /* !CLI */
  485.  
  486. void
  487. SetUpMenus( mp, scrn )
  488.     register struct Menu *mp;
  489.     register struct Screen *scrn;
  490. {
  491.     register struct MenuItem *mip;
  492.     register int i, leftoff = 0, horiz=0, len;
  493.     register int com, chk;
  494.  
  495.     for( ; mp; mp = mp->NextMenu )
  496.     {
  497.     i = 0;
  498.     horiz = (scrn->RastPort.TxWidth*strlen(mp->MenuName))+16;
  499.     /*mp->LeftEdge = leftoff;*/
  500.     com = chk = 0;
  501.     for( mip = mp->FirstItem; mip; mip = mip->NextItem )
  502.     {
  503.         if( mip->Flags & COMMSEQ )
  504.         com = scrn->RastPort.TxWidth * 6;
  505.         if( mip->Flags & CHECKIT )
  506.         chk = scrn->RastPort.TxWidth * 3;
  507.     }
  508.     for( mip = mp->FirstItem; mip; mip = mip->NextItem )
  509.     {
  510.         mip->Height = scrn->RastPort.TxHeight;
  511.         mip->TopEdge = scrn->RastPort.TxHeight * i++;
  512.  
  513.         len = IntuiTextLength((struct IntuiText *)
  514.             (mip->ItemFill))+8+com+chk;
  515.         horiz = max( horiz,len );
  516.     }
  517.  
  518.     for( mip = mp->FirstItem; mip; mip = mip->NextItem )
  519.     {
  520.         mip->Width = horiz;
  521.     }
  522.     leftoff += horiz;
  523.     }
  524. }
  525.  
  526. /* !CLI */
  527.  
  528. /* Get a text line from the indicated file based on an array of per
  529.  * line offsets.
  530.  */
  531.  
  532. void getline( fp, offarr, which, buf, size )
  533.     FILE *fp;
  534.     long *offarr;
  535.     int which, size;
  536.     char *buf;
  537. {
  538.     fseek( fp, offarr[ which ], 0 );
  539.     fgets( buf, size, fp );
  540. }
  541.  
  542. /* !CLI */
  543.  
  544. void
  545. do_closewindow()
  546. {
  547.     /*set close flag - cleanup must be done elsewhere*/
  548.     cleanup( 0 );
  549. }
  550.  
  551. /* !CLI */
  552.  
  553. void
  554. menu_copyopt()
  555. {
  556.     GPTR gptr;
  557.     char newname[ 100 ], oldname[ 100 ], cmd[ 200 ];
  558.  
  559.     if( ( gptr = NeedGame() ) == NULL )
  560.     return;
  561.  
  562.     if( StrRequest( "Enter new player name", newname, gptr->fname ) == 0 )
  563.     return;
  564.  
  565.     if( strcmp( newname, gptr->fname ) == 0 )
  566.     {
  567.     errmsg( FLASH, "Copying aborted, new name same as old" );
  568.     return;
  569.     }
  570.  
  571.     strcpy( oldname, GameName( gptr, NULL ) );
  572.     strcpy( newname, GameName( gptr, newname ) );
  573.  
  574.     sprintf( cmd, "c:copy \"%s\" \"%s\"", oldname, newname );
  575.     Execute( cmd, NULL, NULL );
  576.     MapGadgets( R_DISK, 1 );
  577. }
  578.  
  579. /* !CLI */
  580.  
  581. void
  582. menu_rename()
  583. {
  584.     register GPTR gptr;
  585.     char newname[ 100 ], oldname[ 100 ], cmd[ 200 ], name[100], *t;
  586.  
  587.     if( ( gptr = NeedGame() ) == NULL )
  588.     return;
  589.  
  590.     strcpy( newname, gptr->name );
  591.     if( t = strrchr( newname, '.' ) )
  592.     {
  593.     if( strcmp( t, ".sav" ) == 0 )
  594.         *t = 0;
  595.     }
  596.  
  597.     if( StrRequest( "Enter New Name For Game", name, newname ) == 0)
  598.     return;
  599.  
  600.     /* Name can only be this long to allow inclusion of appropriate suffix */
  601.     name[ 30 - strlen( ".sav.info " ) ] = '\0';
  602.  
  603.     if( strcmp( name, newname ) == 0 )
  604.     {
  605.     errmsg( FLASH, "Rename aborted, name unchanged from %s", newname );
  606.     return;
  607.     }
  608.  
  609.     strcat( name, ".sav" );
  610.  
  611.     strcpy( oldname, GameName( gptr, NULL ) );
  612.  
  613.     strcpy( newname, GameName( gptr, name ) );
  614.     strcat( newname, ".info" );
  615.  
  616.     /* Rename icon file */
  617.     sprintf( cmd, "c:rename \"%s\" \"%s\"", oldname, newname );
  618.     Execute( cmd, NULL, NULL );
  619.  
  620.     strcpy( oldname, GameName( gptr, gptr->name ) );
  621.  
  622.     strcpy( newname, GameName( gptr, name ) );
  623.  
  624.     /* Rename save file if it is actually there */
  625.     if( access( oldname, 0 ) == 0 )
  626.     {
  627.     sprintf( cmd, "c:rename \"%s\" \"%s\"", oldname, newname );
  628.     Execute( cmd, NULL, NULL );
  629.     }
  630.  
  631.     MapGadgets( R_DISK, 1 );
  632. }
  633.  
  634. #endif  /* CLI */
  635.  
  636. void CleanUpLists( )
  637. {
  638.     register GPTR gptr;
  639.  
  640.     while( gptr = gamehead )
  641.     {
  642.     gamehead = gamehead->next;
  643.     FreeGITEM( gptr );
  644.     }
  645.  
  646.     while( gptr = gameavail )
  647.     {
  648.     gameavail = gameavail->next;
  649.     free( gptr );
  650.     }
  651. }
  652.  
  653. #ifndef CLI
  654.  
  655. void SafeCloseWindow( window )
  656.     register struct Window *window;
  657. {
  658.     register struct Message *msg;
  659.  
  660.     if( !window )
  661.     return;
  662.  
  663.     /* Remove any attached menu */
  664.  
  665.     if( window->MenuStrip )
  666.     {
  667.     ClearMenuStrip( window );
  668.     }
  669.  
  670.     Forbid();
  671.     while( window->UserPort != NULL &&
  672.         ( msg = GetMsg( window->UserPort) ) != NULL )
  673.     {
  674.     ReplyMsg( msg );
  675.     }
  676.  
  677.     CloseWindow( window );
  678.     Permit();
  679. }
  680.  
  681. #else   /* CLI */
  682.  
  683. void CloseLibraries( )
  684. {
  685.     if( IntuitionBase )     CloseLibrary( (void *) IntuitionBase );
  686.     IntuitionBase = 0;
  687.     if( DiskfontBase )      CloseLibrary( (void *) DiskfontBase );
  688.     DiskfontBase = 0;
  689.     if( IconBase )          CloseLibrary(  IconBase );
  690.     IconBase = 0;
  691.     if( GfxBase )           CloseLibrary( (void *) GfxBase );
  692.     GfxBase = 0;
  693. }
  694.  
  695. /* CLI */
  696.  
  697. void cleanup( code )
  698.     int code;
  699. {
  700.     if( dosport ) DeletePort( dosport );
  701.     dosport = NULL;
  702.  
  703.     CleanUpLists( );
  704.     CloseLibraries( );
  705.  
  706. #ifdef SPLIT
  707.     if(running_split){
  708.     s_UnLoadSeg();
  709.     }
  710. #endif
  711.     exit( code );
  712. }
  713.  
  714. /* CLI */
  715.  
  716. GPTR AllocGITEM( )
  717. {
  718.     register GPTR gptr;
  719.  
  720.     if( gameavail )
  721.     {
  722.     gptr = gameavail;
  723.     gameavail = gameavail->next;
  724.     }
  725.     else
  726.     {
  727.     gptr = xmalloc( sizeof( GAMEITEM ) );
  728.     }
  729.  
  730.     if( gptr )
  731.     memset( gptr, 0, sizeof( GAMEITEM ) );
  732.  
  733.     return( gptr );
  734. }
  735.  
  736. /* CLI */
  737.  
  738. void FreeGITEM( gptr )
  739.     register GPTR gptr;
  740. {
  741.     /* Free all of the pieces first */
  742.  
  743.     if( gptr->talloc )
  744.     FreeTools( gptr );
  745.  
  746.     if( gptr->dobj )
  747.     FreeDObj( gptr->dobj );
  748.  
  749.     gptr->dobj = NULL;
  750.  
  751.     if( gptr->name )
  752.     free( gptr->name );
  753.     gptr->name = NULL;
  754.  
  755.     if( gptr->dname )
  756.     free( gptr->dname );
  757.     gptr->dname = NULL;
  758.  
  759.     if( gptr->fname )
  760.     free( gptr->fname );
  761.     gptr->fname = NULL;
  762.  
  763.     /* Connect it to free list */
  764.  
  765.     gptr->next = gameavail;
  766.     gameavail = gptr;
  767. }
  768.  
  769. /* CLI */
  770.  
  771. struct DiskObject *AllocDObj( str )
  772.     register char *str;
  773. {
  774.     register struct DiskObject *doptr;
  775.     register char *t, *t1;
  776.  
  777.     if( ( t = strrchr( str, '.' ) ) && stricmp( t, ".info" ) == 0 )
  778.     {
  779.     *t = 0;
  780.     } else {
  781.     t = NULL;
  782.     }
  783.  
  784.     if( doptr = GetDiskObject( str ) )
  785.     {
  786.     struct IntuiText *ip;
  787.  
  788.     diskobj_filter(doptr);  /* delete all but INTERNALCLI */
  789.  
  790.     if( ip = xmalloc( sizeof( struct IntuiText ) ) )
  791.     {
  792.         memset( ip, 0, sizeof( struct IntuiText ) );
  793.         ip->FrontPen = C_BLACK;
  794.         ip->DrawMode = JAM1;
  795.         ip->IText = strdup( str );
  796.         doptr->do_Gadget.GadgetText = ip;
  797.  
  798.         /* Trim any .sav off of the end. */
  799.  
  800.         if( ( t1 = strrchr( ip->IText, '.' ) ) &&
  801.         stricmp( t1, ".sav" ) == 0 )
  802.         {
  803.         *t1 = 0;
  804.         ip->LeftEdge = (2 * win->RPort->TxWidth);
  805.         }
  806.         }
  807.     }
  808.     if( t ) *t = '.';
  809.  
  810.     return( doptr );
  811. }
  812.  
  813. #endif  /* CLI */
  814.  
  815. void FreeDObj( doptr )
  816.     register struct DiskObject *doptr;
  817. {
  818.     if( doptr->do_Gadget.GadgetText )
  819.     {
  820.     free( doptr->do_Gadget.GadgetText->IText );
  821.     free( doptr->do_Gadget.GadgetText );
  822.     }
  823.     doptr->do_Gadget.GadgetText = NULL;
  824.     FreeDiskObject( doptr );
  825. }
  826.  
  827. #ifdef CLI
  828. #ifdef AZTEC_C
  829. void errmsg(int flash, char *str, ...)
  830. #else
  831. void errmsg( flash, str )
  832. char *str;
  833. int flash;
  834. #endif
  835. {
  836.     va_list vp;
  837.  
  838.     va_start( vp, str );
  839.  
  840. /*  if( !win || !wbopen ) */
  841.     {
  842.     vprintf( str, vp );
  843.     va_end( vp );
  844.     return;
  845.     }
  846.  
  847. }
  848.  
  849. /* CLI */
  850.  
  851. /*
  852.  * Issue an error message to the users window because it can not be done
  853.  * any other way.
  854.  */
  855.  
  856. void error( str )
  857.     register char *str;
  858. {
  859.     char s[ 50 ];
  860.     if( scrn ) ScreenToBack( scrn );
  861.     Delay( 10 );
  862.     fprintf( stderr, "%s\n", str );
  863.     fprintf( stderr, "Hit Return: " );
  864.     fflush( stderr );
  865.     gets( s );
  866.     if( scrn ) ScreenToFront( scrn );
  867. }
  868.  
  869. #else   /* CLI */
  870.  
  871. void menu_scores()
  872. {
  873.     register char buf1[50];
  874.     register char **oldtools;
  875.     register GPTR gptr;
  876.     int oldalloc;
  877.     extern GPTR windowgads;
  878.  
  879.     if( StrRequest( "Scores for whom?", buf1, "all" ) != 0 )
  880.     {
  881.     for( gptr = windowgads; gptr; gptr = gptr->nextwgad )
  882.     {
  883.         if( gptr->dobj->do_Gadget.GadgetID == GADNEWGAME )
  884.         break;
  885.     }
  886.  
  887.     if( !gptr )
  888.     {
  889.         errmsg( FLASH, "Can't find NewGame icon" );
  890.         return;
  891.     }
  892.  
  893.     /* Save current tools */
  894.     oldtools = gptr->dobj->do_ToolTypes;
  895.  
  896.     /* Force a new tooltypes array to be allocated */
  897.     if( oldalloc = gptr->talloc )
  898.     {
  899.         gptr->dobj->do_ToolTypes = gptr->otools;
  900.         gptr->talloc = 0;
  901.     }
  902.  
  903.     /* Add the scores entry */
  904.         SetToolLine( gptr, "SCORES", *buf1 ? buf1 : "all" );
  905.  
  906.     /* Get the scores */
  907.     run_game( gptr );
  908.  
  909.     /* Free the tools which contain "SCORES=" */
  910.     FreeTools( gptr );
  911.  
  912.     /* Restore the old tools.  When this game exits, the tools
  913.      * will be written back out to disk to update things
  914.      */
  915.     gptr->dobj->do_ToolTypes = oldtools;
  916.     gptr->talloc = oldalloc;
  917.     Delay( 100 );
  918.     UpdateGameIcon( gptr );
  919.     }
  920. }
  921.  
  922. /* !CLI */
  923.  
  924. CheckAndCopy( gadstr, origstr )
  925.     char *gadstr, *origstr;
  926. {
  927.     char *t;
  928.     int i;
  929.  
  930.     if( t = strchr( gadstr, '=' ) )
  931.     {
  932.     i = t - gadstr;
  933.     /* Check for original string and don't allow one line to be replaced with
  934.      * another.
  935.      */
  936.     if( *origstr != 0 && strncmp( gadstr, origstr, i ) != 0 )
  937.     {
  938.         strcpy( gadstr, origstr );
  939.         DisplayBeep( NULL );
  940.         return( 0 );
  941.     }
  942.     }
  943.     else
  944.     {
  945.     /* If added an equals, there wasn't one previously, so signal an error */
  946.     if( t = strchr( origstr, '=' ) )
  947.     {
  948.         strcpy( gadstr, origstr );
  949.         DisplayBeep( NULL );
  950.         return( 0 );
  951.     }
  952.     }
  953.     return( 1 );
  954. }
  955.  
  956. /* !CLI */
  957.  
  958. int IsEditEntry( str, gptr )
  959.     char *str;
  960.     register GPTR gptr;
  961. {
  962.     if( gptr->dobj->do_Gadget.GadgetID == GADNEWGAME )
  963.     return( 1 );
  964.     if( strncmp( str, "CHARACTER=", 10 ) == 0 )
  965.     return( 0 );
  966.     return( 1 );
  967. }
  968.  
  969. /* !CLI */
  970.  
  971. void menu_comment( )
  972. {
  973.     register GPTR gptr;
  974.     struct FileInfoBlock *finfo;
  975.     BPTR lock;
  976.     char commentstr[ 100 ];
  977.  
  978.     if( ( gptr = NeedGame() ) == NULL )
  979.     return;
  980.  
  981.     if( ( lock = Lock( GameName( gptr, NULL ), ACCESS_READ ) ) == NULL )
  982.     {
  983.     /* Can't get lock, reload and return */
  984.  
  985.     errmsg( FLASH, "Can't Lock game save file: %s",
  986.             GameName( gptr, NULL ) );
  987.     MapGadgets( R_DISK, 1 );
  988.     return;
  989.     }
  990.  
  991.     finfo = (struct FileInfoBlock *) xmalloc(sizeof(struct FileInfoBlock));
  992.     Examine( lock, finfo );
  993.     UnLock( lock );
  994.     strncpy( commentstr, finfo->fib_Comment, sizeof( finfo->fib_Comment ) );
  995.     commentstr[ sizeof( finfo->fib_Comment ) ] = 0;
  996.     free( finfo );
  997.  
  998.     /* Set the correct size */
  999.     if( StrRequest( "Edit Comment as Desired",
  1000.         commentstr, commentstr ) == 0 )
  1001.     {
  1002.     return;
  1003.     }
  1004.  
  1005.     SetComment( GameName( gptr, NULL ), commentstr );
  1006. }
  1007.  
  1008. /* !CLI */
  1009.  
  1010. /*
  1011.  * Make the proportional gadget position match the values passed
  1012.  */
  1013.  
  1014. void UpdatePropGad( win, gad, vis, total, top )
  1015.     struct Window *win;
  1016.     struct Gadget *gad;
  1017.     register long vis, total, top;
  1018. {
  1019.     register long hidden;
  1020.     register int body, pot;
  1021.  
  1022.     hidden = max( total-vis, 0 );
  1023.  
  1024.     if( top > hidden )
  1025.     top = hidden;
  1026.  
  1027.     if( hidden > 0 )
  1028.     body = (ULONG) (vis * MAXBODY) / total;
  1029.     else
  1030.     body = MAXBODY;
  1031.  
  1032.     if( hidden > 0 )
  1033.     pot = (top * MAXPOT) / hidden;
  1034.     else
  1035.     pot = 0;
  1036.  
  1037.     NewModifyProp( gad, win, NULL,
  1038.         AUTOKNOB|FREEHORIZ, pot, 0, body, MAXBODY, 1 );
  1039. }
  1040.  
  1041. #endif  /* CLI */
  1042.  
  1043. /*
  1044.  * Allocate some memory
  1045.  */
  1046.  
  1047. void *xmalloc( nbytes )
  1048.     unsigned nbytes;
  1049. {
  1050.     return( malloc( nbytes ) );
  1051. }
  1052.  
  1053. #ifndef CLI
  1054. /*
  1055.  * Delete the game associated with the GAME structure passed
  1056.  */
  1057.  
  1058. int DeleteGame( gptr )
  1059.     register GPTR gptr;
  1060. {
  1061.     register int err;
  1062.  
  1063.     err = DeleteFile( GameName( gptr, gptr->name ) );
  1064.     err += DeleteFile( GameName( gptr, NULL ) );
  1065.     return( err );
  1066. }
  1067. #endif  /* CLI */
  1068.  
  1069. /*
  1070.  * Look through the list of games for one named 'name'
  1071.  */
  1072.  
  1073. GPTR FindGame( name )
  1074.     char *name;
  1075. {
  1076.     register GPTR gptr;
  1077.  
  1078.     for( gptr = gamehead; gptr; gptr = gptr->next )
  1079.     {
  1080.     if( stricmp( gptr->fname, name ) == 0 )
  1081.         break;
  1082.     }
  1083.  
  1084.     return( gptr );
  1085. }
  1086. /*
  1087.  * Set the option string indicated by idx to 'str'
  1088.  */
  1089.  
  1090. void setoneopt( idx, str )
  1091.     int idx;
  1092.     char *str;
  1093. {
  1094.     /* This space accumulates, but is recovered at process exit */
  1095.  
  1096.     options[ idx ] = strdup( str );
  1097. }
  1098.  
  1099. /*
  1100.  * Get just the directory name of str
  1101.  */
  1102.  
  1103. char *dirname( str )
  1104.     char *str;
  1105. {
  1106.     static char buf[ 300 ];
  1107.     char *t;
  1108.  
  1109.     strncpy( buf, str, sizeof( buf ) );
  1110.     buf[ sizeof( buf ) - 1 ] = 0;
  1111.  
  1112.     if( (t = strrchr( buf, '/' ) ) == NULL ||
  1113.         (t = strrchr( buf, ':' ) ) == NULL )
  1114.     {
  1115.     return( "/" );
  1116.     }
  1117.     *t = 0;
  1118.     return( buf );
  1119. }
  1120.  
  1121. #ifndef CLI
  1122.  
  1123. /*
  1124.  * Make sure that only itemno is checked in 'menu' off of menuptr
  1125.  */
  1126.  
  1127. void CheckOnly( menuptr, menu, itemno )
  1128.     register struct Menu *menuptr;
  1129.     register int menu, itemno;
  1130. {
  1131.     register struct MenuItem *ip;
  1132.  
  1133.     while( menuptr && menu-- )
  1134.     menuptr = menuptr->NextMenu;
  1135.  
  1136.     if( menuptr )
  1137.     {
  1138.     for( ip = menuptr->FirstItem; ip && itemno; itemno--)
  1139.     {
  1140.         ip->Flags &= ~CHECKED;
  1141.         ip = ip->NextItem;
  1142.     }
  1143.  
  1144.     if( ip )
  1145.     {
  1146.         ip->Flags |= CHECKED;
  1147.         ip = ip->NextItem;
  1148.     }
  1149.  
  1150.     while( ip )
  1151.     {
  1152.         ip->Flags &= ~CHECKED;
  1153.         ip = ip->NextItem;
  1154.     }
  1155.     }
  1156. }
  1157.  
  1158. /* !CLI */
  1159.  
  1160. int FindChecked( menuptr, menu )
  1161.     register struct Menu *menuptr;
  1162.     register int menu;
  1163. {
  1164.     register int itemno;
  1165.     register struct MenuItem *ip;
  1166.  
  1167.     while( menuptr && menu-- )
  1168.     menuptr = menuptr->NextMenu;
  1169.  
  1170.     if( menuptr )
  1171.     {
  1172.     for( itemno = 0, ip = menuptr->FirstItem; ip; ip = ip->NextItem )
  1173.     {
  1174.         if( ip->Flags & CHECKED )
  1175.         return( itemno );
  1176.         ++itemno;
  1177.     }
  1178.     }
  1179.     return( 0 );
  1180. }
  1181.  
  1182. /* !CLI */
  1183.  
  1184. /*
  1185.  * Create a file name based in the GAMEs directory.  If file is NULL,
  1186.  * the file name is the icon file.  Otherwise it is 'file'.
  1187.  */
  1188.  
  1189. char *GameName( gptr, file )
  1190.     GPTR gptr;
  1191.     char *file;
  1192. {
  1193.     static char buf[200];
  1194.  
  1195.     if( file == NULL )
  1196.     file = gptr->fname;
  1197.  
  1198.     if( strchr( "/:", gptr->dname[ strlen( gptr->dname ) - 1 ] ) )
  1199.     sprintf( buf, "%s%s", gptr->dname, file );
  1200.     else
  1201.     sprintf( buf, "%s/%s", gptr->dname, file );
  1202.     return( buf );
  1203. }
  1204.  
  1205. #endif  /* CLI */
  1206.  
  1207. /*
  1208.  * Allocate a new GAME structure for the file passed and fill it in
  1209.  */
  1210.  
  1211. GPTR GetWBIcon( lock, dir, finfo )
  1212.     register BPTR lock;
  1213.     register char *dir;
  1214.     register struct FileInfoBlock *finfo;
  1215. {
  1216.     register BPTR odir;
  1217.     register char *t;
  1218.     register GPTR gptr;
  1219.  
  1220.     if( ( gptr = AllocGITEM( ) ) == NULL )
  1221.     goto noitems;
  1222.  
  1223.     if( ( gptr->dname = strdup( dir ) ) == NULL )
  1224.     goto outofmem;
  1225.  
  1226.     if( ( gptr->fname = strdup( finfo->fib_FileName ) ) == NULL )
  1227.     goto outofmem;
  1228.  
  1229.     /* Strip the .info off. */
  1230.     if( t = strrchr( finfo->fib_FileName, '.' ) )
  1231.     {
  1232.     if( stricmp( t, ".info" ) == 0 )
  1233.         *t = 0;
  1234.     else
  1235.         t = NULL;
  1236.     }
  1237.  
  1238.     if( ( gptr->name = strdup( finfo->fib_FileName ) ) == NULL )
  1239.     goto outofmem;
  1240.  
  1241.     /* If removed .info, put it back */
  1242.  
  1243.     if( t )
  1244.     *t = '.';
  1245.  
  1246.     /* Change to saved game directory */
  1247.  
  1248.     odir = CurrentDir( lock );
  1249.  
  1250.     /* Allocate a diskobj structure */
  1251.  
  1252.     if( ( gptr->dobj = AllocDObj( finfo->fib_FileName ) ) == NULL )
  1253.     {
  1254.     (void) CurrentDir( odir );
  1255. outofmem:
  1256.     FreeGITEM( gptr );
  1257.  
  1258.     if( gptr->fname )
  1259.         free( gptr->fname );
  1260.     gptr->fname = NULL;
  1261.  
  1262.     if( gptr->name )
  1263.         free( gptr->name );
  1264.     gptr->name = NULL;
  1265.  
  1266.     if( gptr->dname )
  1267.         free( gptr->dname );
  1268.     gptr->dname = NULL;
  1269.  
  1270. noitems:
  1271.     errmsg( FLASH, "Can't get Disk Object: %s", finfo->fib_FileName );
  1272.     return( NULL );
  1273.     }
  1274.     gptr->oflag = gptr->dobj->do_Gadget.Flags;
  1275.     gptr->oact = gptr->dobj->do_Gadget.Activation;
  1276.     gptr->dobj->do_Gadget.Activation |=
  1277.         ( RELVERIFY | GADGIMMEDIATE | FOLLOWMOUSE );
  1278.     gptr->dobj->do_Gadget.Flags &= ~(GADGHIGHBITS);
  1279.     gptr->dobj->do_Gadget.Flags |= GADGHNONE;
  1280.  
  1281.     /* Make sure gptr->dobj->do_ToolTypes is not NULL */
  1282.     ReallocTools( gptr, 0 );
  1283.  
  1284.     (void) CurrentDir( odir );
  1285.     return( gptr );
  1286. }
  1287.  
  1288. #ifndef CLI
  1289.  
  1290. /*
  1291.  * Put a 3-D motif border around the gadget.  String gadgets or those
  1292.  * which do not have highlighting are rendered down.  Boolean gadgets
  1293.  * are rendered in the up position by default.
  1294.  */
  1295.  
  1296. void SetBorder( gd, val )
  1297.     register struct Gadget *gd;
  1298.     int val;
  1299. {
  1300.     register struct Border *bp;
  1301.     register short *sp;
  1302.     register int i;
  1303.     int borders = 6;
  1304.  
  1305.     /* Allocate two border structures one for up image and one for down
  1306.      * image, plus vector arrays for the border lines.
  1307.      */
  1308.  
  1309.     if( gd->GadgetType == STRGADGET )
  1310.     borders = 12;
  1311.  
  1312.     if( ( bp = xmalloc( ( ( sizeof( struct Border ) * 2 ) +
  1313.         ( sizeof( short ) * borders ) ) * 2 ) ) == NULL )
  1314.     {
  1315.     return;
  1316.     }
  1317.  
  1318.     /* Remove any special rendering flags to avoid confusing intuition
  1319.      */
  1320.  
  1321.     gd->Flags &= ~(GADGHIGHBITS|GADGIMAGE|GRELWIDTH|
  1322.             GRELHEIGHT|GRELRIGHT|GRELBOTTOM);
  1323.  
  1324.     sp = (short *)(bp + 4);
  1325.     if( val == 0 || val == 2 ||
  1326.     gd->GadgetType == STRGADGET || ( gd->GadgetType == BOOLGADGET &&
  1327.         ( gd->Flags & GADGHIGHBITS ) == GADGHNONE ) )
  1328.     {
  1329.     /* For a string gadget, we expand the border beyond the area where
  1330.      * the text will be entered.
  1331.      */
  1332.  
  1333.     sp[0] = -1;
  1334.     sp[1] = gd->Height - 1;
  1335.     sp[2] = -1;
  1336.     sp[3] = -1;
  1337.     sp[4] = gd->Width - 1;
  1338.     sp[5] = -1;
  1339.  
  1340.     sp[6] = gd->Width + 1;
  1341.     sp[7] = -2;
  1342.     sp[8] = gd->Width + 1;
  1343.     sp[9] = gd->Height + 1;
  1344.     sp[10] = -2;
  1345.     sp[11] = gd->Height + 1;
  1346.  
  1347.     sp[12] = -2;
  1348.     sp[13] = gd->Height;
  1349.     sp[14] = -2;
  1350.     sp[15] = -2;
  1351.     sp[16] = gd->Width;
  1352.     sp[17] = -2;
  1353.     sp[18] = gd->Width;
  1354.     sp[19] = gd->Height;
  1355.     sp[20] = -2;
  1356.     sp[21] = gd->Height;
  1357.  
  1358.     for( i = 0; i < 3; ++i )
  1359.     {
  1360.         bp[ i ].LeftEdge = bp[ i ].TopEdge = -1;
  1361.         if( val == 2 )
  1362.         bp[ i ].FrontPen = ( i == 0 || i == 1 ) ? C_WHITE : C_BLACK;
  1363.         else
  1364.         bp[ i ].FrontPen = ( i == 0 || i == 1 ) ? C_BLACK : C_WHITE;
  1365.  
  1366.         /* Have to use JAM2 so that the old colors disappear. */
  1367.         bp[ i ].BackPen = C_GREY;
  1368.         bp[ i ].DrawMode = JAM2;
  1369.         bp[ i ].Count = ( i == 0 || i == 1 ) ? 3 : 5;
  1370.         bp[ i ].XY = &sp[ i*6 ];
  1371.         bp[ i ].NextBorder = ( i == 2 ) ? NULL : &bp[ i + 1 ];
  1372.     }
  1373.  
  1374.     /* Set the up image */
  1375.     gd->GadgetRender = (APTR) bp;
  1376.  
  1377.     /* Same image for select image */
  1378.     gd->SelectRender = (APTR) bp;
  1379.  
  1380.     gd->LeftEdge++;
  1381.     gd->TopEdge++;
  1382.     gd->Flags |= GADGHCOMP;
  1383.     }
  1384.     else
  1385.     {
  1386.     /* Create the border vector values for up and left side, and
  1387.      * also the lower and right side.
  1388.      */
  1389.  
  1390.     sp[0] = 0;
  1391.     sp[1] = gd->Height;
  1392.     sp[2] = 0;
  1393.     sp[3] = 0;
  1394.     sp[4] = gd->Width;
  1395.     sp[5] = 0;
  1396.  
  1397.     sp[6] = gd->Width;
  1398.     sp[7] = 0;
  1399.     sp[8] = gd->Width;
  1400.     sp[9] = gd->Height;
  1401.     sp[10] = 0;
  1402.     sp[11] = gd->Height;
  1403.  
  1404.     /* We are creating 4 sets of borders, the two sides of the
  1405.      * rectangle share the border vectors with the opposite image,
  1406.      * but specify different colors.
  1407.      */
  1408.  
  1409.     for( i = 0; i < 4; ++i )
  1410.     {
  1411.         bp[ i ].TopEdge = bp[ i ].LeftEdge = 0;
  1412.  
  1413.         /* A GADGHNONE is always down */
  1414.  
  1415.         if( val != 3 && gd->GadgetType == BOOLGADGET &&
  1416.         ( gd->Flags & GADGHIGHBITS ) != GADGHNONE )
  1417.         {
  1418.         bp[ i ].FrontPen =
  1419.             ( i == 1 || i == 2 ) ? C_BLACK : C_WHITE;
  1420.         }
  1421.         else
  1422.         {
  1423.         bp[ i ].FrontPen =
  1424.             ( i == 1 || i == 3 ) ? C_WHITE : C_BLACK;
  1425.         }
  1426.  
  1427.         /* Have to use JAM2 so that the old colors disappear. */
  1428.         bp[ i ].BackPen = C_GREY;
  1429.         bp[ i ].DrawMode = JAM2;
  1430.         bp[ i ].Count = 3;
  1431.         bp[ i ].XY = &sp[ 6 * ((i &1) != 0) ];
  1432.         bp[ i ].NextBorder =
  1433.         ( i == 1 || i == 3 ) ? NULL : &bp[ i + 1 ];
  1434.     }
  1435.  
  1436.     /* bp[0] and bp[1] two pieces for the up image */
  1437.     gd->GadgetRender = (APTR) bp;
  1438.  
  1439.     /* bp[2] and bp[3] two pieces for the down image */
  1440.     gd->SelectRender = (APTR) (bp + 2);
  1441.     gd->Flags |= GADGHIMAGE;
  1442.     }
  1443. }
  1444.  
  1445. /* !CLI */
  1446.  
  1447. struct Gadget *FindGadget( window, newwindow, id )
  1448.     struct Window *window;
  1449.     struct NewWindow *newwindow;
  1450.     int id;
  1451. {
  1452.     struct Gadget *gd = NULL;
  1453.  
  1454.     if( window )
  1455.     gd = window->FirstGadget;
  1456.     else if( newwindow )
  1457.     gd = newwindow->FirstGadget;
  1458.  
  1459.     while( gd )
  1460.     {
  1461.     if( gd->GadgetID == id )
  1462.         break;
  1463.     gd = gd->NextGadget;
  1464.     }
  1465.  
  1466.     return( gd );
  1467. }
  1468.  
  1469. #endif  /* CLI */
  1470.  
  1471. /*
  1472.  * Clear all previous values from passed options array
  1473.  */
  1474. void ZapOptions( optr )
  1475.     OPTR optr;
  1476. {
  1477.     int i;
  1478.  
  1479.     for( i = 0; optr[ i ].name; ++i )
  1480.     {
  1481.     if( optr[i].optstr )
  1482.     {
  1483.         if( *optr[i].optstr )
  1484.         {
  1485.         free( optr[i].optstr );
  1486.         optr[i].optstr = "";
  1487.         }
  1488.     }
  1489.     else
  1490.     {
  1491.         optr[i].optval = optr[i].defval;
  1492.     }
  1493.     }
  1494. }
  1495.  
  1496. #ifndef CLI
  1497.  
  1498. /*
  1499.  * Copy Options from GAMES OPTIONS= tooltypes element to the gadgets
  1500.  */
  1501. void CopyOptions( optr, gptr )
  1502.     OPTR optr;
  1503.     GPTR gptr;
  1504. {
  1505.     char **sp;
  1506.  
  1507.     for( sp = gptr->dobj->do_ToolTypes; *sp; ++sp )
  1508.     {
  1509.     if( strnicmp( *sp, "options=", 8 ) == 0 )
  1510.     {
  1511.         break;
  1512.     }
  1513.     }
  1514.  
  1515.     if( *sp == NULL )
  1516.     {
  1517.     errmsg( NO_FLASH, "Options not set for %s", gptr->name );
  1518.     return;
  1519.     }
  1520.  
  1521.     CopyOptionStr( optr, *sp + 8 );
  1522. }
  1523.  
  1524. /* !CLI */
  1525.  
  1526. void CopyOptionStr( optr, str )
  1527.     OPTR optr;
  1528.     char *str;
  1529. {
  1530.     char *s, *t, buf[ 100 ];
  1531.     int i, sidx, state = 0;
  1532.     int done = 0;
  1533.  
  1534.     ZapOptions( optr );
  1535.     s = buf;
  1536.     *buf = 0;
  1537.     sidx = -1;
  1538.  
  1539.     /* Start past the 'options=' part */
  1540.     for( t = str; !done; ++t )
  1541.     {
  1542.     if( state == 0 && isspace( *t ) )
  1543.         continue;
  1544.  
  1545.     /* If at end remember so... */
  1546.     if( !*t )
  1547.         done = 1;
  1548.  
  1549.     /* If looking for an option value */
  1550.     if( state == 0 )
  1551.     {
  1552.         /* If found string value... */
  1553.         if( *t == ':' )
  1554.         {
  1555.         *s = 0;
  1556.         state = 1;
  1557.         sidx = -1;
  1558.  
  1559.         /* Look for the particular named option */
  1560.         for( i = 0; optr[i].name; ++i )
  1561.         {
  1562.             if( stricmp( optr[i].name, buf ) == 0 )
  1563.             {
  1564.             sidx = i;
  1565.             break;
  1566.             }
  1567.         }
  1568.  
  1569.         /* Set buffer pointer */
  1570.         *(s = buf) = 0;
  1571.  
  1572.         if( sidx == -1 )
  1573.         {
  1574.             errmsg( FLASH, "Invalid option name %s", buf );
  1575.             return;
  1576.         }
  1577.         if( !optr[i].optstr )
  1578.         {
  1579.             errmsg( FLASH, "%s is not a string option", buf );
  1580.             return;
  1581.         }
  1582.         continue;
  1583.         }
  1584.     }
  1585.  
  1586.     /* If at end of string or comma and we have some text... */
  1587.     if( !*t || *t == ',' && *buf )
  1588.     {
  1589.         /* Mark end */
  1590.         *s = 0;
  1591.  
  1592.         /* If have collected string option value... */
  1593.         if( sidx != -1 )
  1594.         {
  1595.         /* Free old string */
  1596.         if( optr[sidx].optstr )
  1597.         {
  1598.             if( *optr[sidx].optstr )
  1599.             free( optr[sidx].optstr );
  1600.         }
  1601.  
  1602.         /* Store new string */
  1603.         if( *buf )
  1604.             optr[sidx].optstr = strdup( buf );
  1605.         else
  1606.             optr[sidx].optstr = "";
  1607.         sidx = -1;
  1608.         }
  1609.         else
  1610.         {
  1611.         /* Look for boolean option */
  1612.         for( i = 0; optr[i].name; ++i )
  1613.         {
  1614.             if( *buf == '!' )
  1615.             {
  1616.             if( stricmp( optr[i].name, buf + 1 ) == 0 )
  1617.                 break;
  1618.             }
  1619.             else
  1620.             {
  1621.             if( stricmp( optr[i].name, buf ) == 0 )
  1622.                 break;
  1623.             }
  1624.         }
  1625.  
  1626.         if( optr[i].name )
  1627.         {
  1628.             optr[i].optval = *buf != '!';
  1629.         }
  1630.         else
  1631.         {
  1632.             errmsg( FLASH, "Unrecognized option %s", buf );
  1633.             return;
  1634.         }
  1635.         }
  1636.         *(s = buf) = 0;
  1637.         state = 0;
  1638.     }
  1639.     else
  1640.     {
  1641.         if( *t == ',' )
  1642.         *(s = buf) = 0;
  1643.         else
  1644.         *s++ = *t;
  1645.     }
  1646.     }
  1647. }
  1648.  
  1649. /* !CLI */
  1650.  
  1651. /*
  1652.  *  Set the GAMES OPTIONS tooltypes to the data in the Options windows
  1653.  *  gadgetry.
  1654.  */
  1655. void SetOptions( optr, gptr )
  1656.     register OPTR optr;
  1657.     register GPTR gptr;
  1658. {
  1659.     PutOptions( optr );
  1660.     SetToolLine( gptr, "OPTIONS", options[ OPTIONS_IDX ] );
  1661.     UpdateGameIcon( gptr );
  1662. }
  1663.  
  1664. void
  1665. UpdateGameIcon( gptr )
  1666.     register GPTR gptr;
  1667. {
  1668.     register long lock;
  1669.  
  1670.     if( lock = Lock( gptr->dname, ACCESS_READ ) )
  1671.     {
  1672.     /* Write out the DiskObject */
  1673.  
  1674.     WriteDObj( gptr, lock );
  1675.     UnLock( lock );
  1676.     }
  1677.     else
  1678.     {
  1679.     errmsg( FLASH, "Can't change directory to %s", gptr->dname );
  1680.     }
  1681. }
  1682.  
  1683. #endif  /* CLI */
  1684.  
  1685. char *ToolsEntry( gptr, name )
  1686.     GPTR gptr;
  1687.     char *name;
  1688. {
  1689.     char *str;
  1690.  
  1691.     if( ! ( str = FindToolType( (char **) gptr->dobj->do_ToolTypes, name ) ) )
  1692.     str = "";
  1693.  
  1694.     return( str );
  1695. }
  1696.  
  1697. /* Reallocate the toolstype information into dynamic memory so that some
  1698.  * parts of it can be easily changed, but we can still do "FreeDiskObject"
  1699.  * later to clean up whatever "GetDiskObject" allocated.
  1700.  */
  1701. void ReallocTools( gptr, add )
  1702.     GPTR gptr;
  1703.     int add;
  1704. {
  1705.     int i, cnt;
  1706.     char **sp, **tp;
  1707.  
  1708.     for( cnt = 0, tp = gptr->dobj->do_ToolTypes; tp && *tp ; ++tp )
  1709.     ++cnt;
  1710.  
  1711.     if( !tp )
  1712.     {
  1713.     /* If no tooltypes array, fudge something to start with */
  1714.     if( sp = xmalloc( 2 * sizeof( char * ) ) )
  1715.     {
  1716.         sp[0] = strdup("HACKDIR=NetHack:");
  1717.         sp[1] = NULL;
  1718.     }
  1719.     }
  1720.     else if( sp = xmalloc( (cnt+1+add) * sizeof( char * ) ) )
  1721.     {
  1722.     for( i = 0, tp = gptr->dobj->do_ToolTypes;
  1723.             tp && *tp && i < cnt; ++tp )
  1724.     {
  1725.         sp[i++] = strdup( *tp );
  1726.     }
  1727.  
  1728.     sp[i] = NULL;
  1729.     }
  1730.     gptr->otools = gptr->dobj->do_ToolTypes;
  1731.     gptr->dobj->do_ToolTypes = sp;
  1732.     gptr->toolcnt = cnt + 1;
  1733.     gptr->talloc = 1;
  1734. }
  1735.  
  1736. void FreeTools( gptr )
  1737.     GPTR gptr;
  1738. {
  1739.     int i;
  1740.     char **sp;
  1741.  
  1742.     if( !gptr->talloc )
  1743.     return;
  1744.  
  1745.     for( i = 0, sp = gptr->dobj->do_ToolTypes; sp[i]; ++i )
  1746.     {
  1747.     free( sp[ i ] );
  1748.     sp[ i ] = NULL;
  1749.     }
  1750.     free( sp );
  1751.     gptr->dobj->do_ToolTypes = gptr->otools;
  1752.     gptr->talloc = 0;
  1753. }
  1754.  
  1755. void SetToolLine( gptr, name, value )
  1756.     GPTR gptr;
  1757.     char *name, *value;
  1758. {
  1759.     char **sp, **osp;
  1760.     int i, len;
  1761.  
  1762.     /* Realloc ToolTypes to be in memory we know how to manage */
  1763.  
  1764.     if( gptr->talloc == 0 )
  1765.     ReallocTools( gptr, 0 );
  1766.  
  1767.     sp = gptr->dobj->do_ToolTypes;
  1768.     len = strlen( name );
  1769.  
  1770.     /* Find any previous definition */
  1771.     for( i = 0; sp[i] && i < gptr->toolcnt - 1; ++i )
  1772.     {
  1773.     if( strnicmp( name, sp[i], len ) == 0 && sp[i][len] == '=' )
  1774.         break;
  1775.     }
  1776.  
  1777.     /* Free up the space, or allocate new space if not there */
  1778.     if( sp[ i ] )
  1779.     free( sp[ i ] );
  1780.     else
  1781.     {
  1782.     /* Check for need to realloc */
  1783.  
  1784.     if( i >= gptr->toolcnt - 1 )
  1785.     {
  1786.         int j=i;
  1787.         osp = sp;
  1788.         sp = xmalloc( ( i + 2 ) * sizeof( char * ) );
  1789.         gptr->toolcnt = i + 2;
  1790.         sp[ i + 1 ] = NULL;
  1791.         while( j >= 0 )
  1792.         {
  1793.         sp[ j ] = osp[ j ];
  1794.         --j;
  1795.         }
  1796.         free( osp );
  1797.         /* i = gptr->toolcnt - 1; */
  1798.         gptr->dobj->do_ToolTypes = sp;
  1799.     }
  1800.     else
  1801.     {
  1802.         sp[ i + 1 ] = NULL;
  1803.     }
  1804.     }
  1805.  
  1806.     /* Set the string */
  1807.  
  1808.     if( sp[ i ] = xmalloc( strlen (value) + strlen( name ) + 2 ) )
  1809.     sprintf( sp[i], "%s=%s", name, value );
  1810.     else
  1811.     {
  1812.     sp[ i ] = NULL;     /* redundant */
  1813.     errmsg( FLASH, "Could not allocate string for value" );
  1814.     }
  1815. }
  1816.  
  1817. void WriteDObj( gptr, lock )
  1818.     register GPTR gptr;
  1819.     long lock;
  1820. {
  1821.     register long odir;
  1822.     long flag, act;
  1823.  
  1824.     /* Don't write gadget out as selected */
  1825.  
  1826.     flag = gptr->dobj->do_Gadget.Flags;
  1827.     act = gptr->dobj->do_Gadget.Activation;
  1828.     gptr->dobj->do_Gadget.Flags = gptr->oflag;
  1829.     gptr->dobj->do_Gadget.Activation = gptr->oact;
  1830.     odir = CurrentDir( lock );
  1831.  
  1832.     if( PutDiskObject( gptr->name, gptr->dobj ) == 0 )
  1833.     errmsg( FLASH, "Could not write disk object values" );
  1834.  
  1835.     gptr->dobj->do_Gadget.Flags = flag;
  1836.     gptr->dobj->do_Gadget.Activation = act;
  1837.  
  1838.     if( odir )
  1839.     (void) CurrentDir( odir );
  1840. }
  1841.  
  1842. char *Strdup( str )
  1843.     char *str;
  1844. {
  1845.     char *t;
  1846.  
  1847.     if( t = AllocMem( strlen( str ) + 1, MEMF_PUBLIC ) )
  1848.     strcpy( t, str );
  1849.     return( t );
  1850. }
  1851.  
  1852. #ifdef CLI
  1853.  
  1854. char *
  1855. eos(s)
  1856.     char *s;
  1857. {
  1858.     while(*s)s++;
  1859.     return s;
  1860. }
  1861.  
  1862. /* CLI */
  1863.  
  1864. void
  1865. condaddslash(s)
  1866.     char *s;
  1867. {
  1868.     s=eos(s);
  1869.     switch(s[-1]){
  1870.     case ':':
  1871.     case '/':
  1872.     break;
  1873.     default:
  1874.     s[0]='/';
  1875.     s[1]='\0';
  1876.     break;
  1877.     }
  1878.     return;
  1879. }
  1880.  
  1881. /* CLI */
  1882.  
  1883. #if 0
  1884. /* for debug only */
  1885. #define BP __builtin_printf
  1886. dumptools(sp,i)
  1887.     char **sp;
  1888.     int i;
  1889. {
  1890.     int x;
  1891.     BP("Dumptools: cnt=%d\n",i);
  1892.     for(x=0;sp[x];x++)
  1893.     BP("%d: '%s'\n",x,sp[x]);
  1894. }
  1895. #endif
  1896.  
  1897. #else   /* CLI */
  1898.  
  1899. void ClearDelGames()
  1900. {
  1901.     register GPTR gptr, pgptr = NULL;
  1902.  
  1903.     for( gptr = gamehead; gptr; )
  1904.     {
  1905.     /* Skip New Game */
  1906.  
  1907.     if( gptr->fname == NULL )
  1908.     {
  1909.         gptr = gptr->next;
  1910.         continue;
  1911.     }
  1912.  
  1913.     /* If gone, then remove structures */
  1914.  
  1915.     if( access( GameName( gptr, NULL ), 0 ) == -1 )
  1916.     {
  1917.         if( pgptr )
  1918.         pgptr->next = gptr->next;
  1919.         else
  1920.         gamehead = gptr->next;
  1921.  
  1922.         FreeGITEM( gptr );
  1923.         gptr = pgptr ? pgptr : gamehead;
  1924.     }
  1925.     else
  1926.     {
  1927.         pgptr = gptr;
  1928.         gptr = gptr->next;
  1929.     }
  1930.     }
  1931. }
  1932.  
  1933. /* !CLI */
  1934.  
  1935. struct TagItem tags[] =
  1936. {
  1937.     TAG_DONE, 0l,
  1938. };
  1939.  
  1940. struct Window *
  1941. MyOpenWindow( nw )
  1942. #ifdef  INTUI_NEW_LOOK
  1943.     struct ExtNewWindow *nw;
  1944. #else
  1945.     struct NewWindow *nw;
  1946. #endif
  1947. {
  1948. #ifdef  INTUI_NEW_LOOK
  1949.     /*nw->Extension = tags;
  1950.     nw->Flags = WFLG_NW_EXTENDED;*/
  1951. #endif
  1952. #undef  NewWindow
  1953.     return( OpenWindow( (struct NewWindow *) nw ) );
  1954. }
  1955.  
  1956. #endif  /* CLI */
  1957.  
  1958. void
  1959. diskobj_filter( dobj )
  1960.     struct DiskObject *dobj;
  1961. {
  1962.     char **ta=dobj->do_ToolTypes;
  1963.     int x;
  1964.  
  1965.     /* if nothing there, just return. */
  1966.     if( !ta )
  1967.         return;
  1968.  
  1969. #ifdef CLI
  1970.     /* kill everything except INTERNALCLI */
  1971.  
  1972.     for(x=0;ta[x];x++){
  1973.     if(!strncmp(ta[x],"INTERNALCLI=",12)){
  1974.         ta[0]=ta[x];
  1975.         ta[1]=0;
  1976.         return;
  1977.     }
  1978.     }
  1979.     ta[0]=0;
  1980. #else
  1981.     /* kill INTERNALCLI */
  1982.     for(x=0;ta[x];x++){
  1983.         int offset=0;
  1984.     while(ta[x+offset] && !strncmp(ta[x+offset],"INTERNALCLI=",12)){
  1985.         offset++;
  1986.         }
  1987.         ta[x]=ta[x+offset];
  1988.     }
  1989. #endif
  1990. }
  1991.