home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / nethack-3.1 / sys / amiga / wb.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-23  |  81.5 KB  |  3,812 lines

  1. /*    SCCS Id: @(#)wb.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. #ifdef AZTEC_C
  9. /* Aztec doesn't recognize __chip syntax */
  10. # define __chip
  11. #endif
  12.  
  13. #include "Amiga:wbdefs.h"        /* Miscellany information */
  14. #ifdef  INTUI_NEW_LOOK
  15. #define NewWindow   ExtNewWindow
  16. #define NewScreen   ExtNewScreen
  17. #endif
  18. #include "Amiga:wbstruct.h"
  19. #include "Amiga:wbprotos.h"
  20.  
  21. #include "Amiga:wbdata.c"        /* All structures and global data */
  22. #include "Amiga:wbwin.c"        /* Has static definitions */
  23.  
  24. #define C_GREY  0
  25. #define C_BLACK 1
  26. #define C_WHITE 2
  27. #define C_BLUE  3
  28.  
  29. #ifndef __SASC_60
  30. extern char *sys_errlist[];
  31. #endif
  32. extern int errno;
  33.  
  34. char pubscreen[ 80 ] = { "HackWB" };
  35. char mytitle[ 80 ];
  36.  
  37. #ifdef  INTUI_NEW_LOOK
  38. int scrlocked = 0;
  39. UWORD scrnpens[] = { 0xffff };
  40.  
  41. struct TagItem scrntags[] =
  42. {
  43.     (Tag)SA_Pens, (ULONG)scrnpens,
  44.     TAG_DONE, 0,
  45.     TAG_DONE, 0,
  46.     TAG_DONE, 0,
  47.     TAG_DONE, 0,
  48.     TAG_DONE, 0,
  49.     TAG_DONE, 0,
  50.     TAG_DONE, 0,
  51. };
  52. #endif
  53.  
  54. #define SPLIT            /* use splitter, if available */
  55. #ifdef SPLIT
  56. int running_split=0;        /* if 0, using normal LoadSeg/UnLoadSeg */
  57. #endif
  58.  
  59. #ifdef AZTEC_C
  60. extern char *strdup(char *);
  61. #endif
  62.  
  63. #ifndef max
  64. # define max(a, b) ((a) > (b) ? (a) : (b))
  65. #endif
  66. #ifndef min
  67. # define min(x,y) ((x) < (y) ? (x) : (y))
  68. #endif
  69.  
  70. void diskobj_filter(struct DiskObject *);
  71. static void UpdateInfoWin( struct Window *cwin );
  72. BPTR s_LoadSeg(char *);
  73. void s_UnLoadSeg(void);
  74.  
  75. main( argc, argv )
  76.     int argc;
  77.     struct WBStartup *argv;
  78. {
  79.     long mask, rmask;
  80.     struct WBStartup *wbs;
  81.     struct WBArg *wba;
  82.     GPTR gptr;
  83.     struct IntuiMessage *imsg;
  84.     struct IntuiMessage mimsg;
  85.     int i;
  86.  
  87.     ZapOptions( curopts );
  88.     InitWB( argc, argv );
  89.     SetupWB( ); /* open window, build menus */
  90.     errmsg( NO_FLASH, "Welcome to NetHack Version 3.1!" );
  91.     CopyRight( );
  92.  
  93.     ReadConfig( );
  94.     LoadDefaults( defgname );
  95.  
  96.     /* Initially, no game selected so disable menu items */
  97.  
  98.     ChgGameItems( &MenuList1, 0 );
  99.  
  100.     MapGadgets( R_DISK, 1 ); /* Display the icons */
  101.  
  102.     /* Wait till user quits */
  103.  
  104.     while( !quit )
  105.     {
  106.     /* Wait for a message */
  107.  
  108.     mask = ( 1L << dosport->mp_SigBit ) ;
  109.     if( wbopen )
  110.         mask |= ( 1L << win->UserPort->mp_SigBit );
  111.  
  112.     rmask = Wait( mask );
  113.  
  114.     /* If displayed an error message before, clear it */
  115.  
  116.     if( errup )
  117.     {
  118.         errmsg( NO_FLASH, "" );
  119.         errup = 0;
  120.     }
  121.  
  122.     /* Process the messages on the port unless the workbench is
  123.      * shutdown by a request to play a game.
  124.      */
  125.  
  126.     while( wbopen && ( imsg = ( struct IntuiMessage * )
  127.         GetMsg( win->UserPort ) ) )
  128.     {
  129.         /* Copy the message.  This does not guarantee that all
  130.          * fields will still be valid, but appears to work
  131.          * here.  Note that we have to reply to the message
  132.          * before the workbench window is closed.
  133.          */
  134.  
  135.         mimsg = *imsg;
  136.         ReplyMsg( (struct Message *)imsg );
  137.  
  138.         switch( mimsg.Class )
  139.         {
  140.         case NEWSIZE:
  141.         ((struct Border *) Message.GadgetRender)->XY[2] =
  142.             win->Width - win->BorderLeft -
  143.             win->BorderRight - 1;
  144.         RefreshGList( &Message, win, NULL, 1 );
  145.         MapGadgets( R_SCROLL, 1 ); /* redisplay the icons */
  146. #ifdef  INTUI_NEW_LOOK
  147.         if( IntuitionBase->LibNode.lib_Version >= 37 )
  148.             RefreshWindowFrame( win );
  149. #endif
  150.         break;
  151.  
  152.         case MENUPICK:
  153.         do_menu( mimsg.Code );
  154.         break;
  155.  
  156.         case RAWKEY:
  157.         if( mimsg.Code == 0x5f )
  158.         {
  159.             /* Pick the correct help message */
  160.  
  161.             if( lastgaddown == NULL )
  162.             {
  163.             text_requester( &Help1_NewWindowStructure7,
  164.                 &Help1_IntuiTextList7 );
  165.             }
  166.             else
  167.             {
  168.             text_requester( &Help2_NewWindowStructure8,
  169.                 &Help2_IntuiTextList8 );
  170.             }
  171.         }
  172.         break;
  173.  
  174.         case CLOSEWINDOW:
  175.         if( Ask( "Ready to Quit?" ) )
  176.             do_closewindow( );
  177.         break;
  178.  
  179.         case GADGETDOWN:
  180.         do_gadgetdown( &mimsg );
  181.         break;
  182.  
  183.         case GADGETUP:
  184.         do_gadgetup( &mimsg );
  185.         break;
  186.  
  187.         case DISKINSERTED:
  188.         MapGadgets( R_DISK, 1 );
  189.         break;
  190.  
  191.         case MOUSEBUTTONS:
  192.         do_buttons( &mimsg );
  193.         break;
  194.         }
  195.     }
  196.  
  197.     if( rmask & ( 1L << dosport->mp_SigBit ) )
  198.     {
  199.         /* Get process termination messages */
  200.  
  201.         while( wbs = (struct WBStartup *) GetMsg( dosport ) )
  202.         {
  203.         /* Find the game that has terminated */
  204.  
  205.         for( gptr = gamehead; gptr && gptr->seglist != wbs->sm_Segment;)
  206.             gptr = gptr->next;
  207.  
  208.         /* Make sure it is there */
  209.  
  210.         if( gptr )
  211.         {
  212. #ifdef SPLIT
  213.             if(!running_split)
  214. #endif
  215.             {
  216.             /* Unload the code */
  217.             UnLoadSeg( wbs->sm_Segment );
  218.             }
  219.  
  220.             /* Free the startup message resources */
  221.             wba = (struct WBArg *)
  222.             ((long)wbs + sizeof( struct WBStartup ));
  223.             for( i = 0; i < wbs->sm_NumArgs; ++i )
  224.             {
  225.             FreeMem( wba[i].wa_Name,
  226.                 strlen( wba[i].wa_Name ) + 1 );
  227.             UnLock( wba[i].wa_Lock );
  228.             }
  229.             FreeMem( wbs, wbs->sm_Message.mn_Length );
  230.             wbs = NULL;
  231.  
  232.             /* Say the game has completed */
  233.  
  234.             gptr->prc = NULL;
  235.             gptr->active = 0;
  236.             active_count--;
  237.         }
  238.         }
  239.  
  240.         /* If the workbench was closed, open it back up */
  241.  
  242.         if( !wbopen )
  243.         SetupWB( );
  244.  
  245.         /* Reload to clear any deleted games */
  246.  
  247.         MapGadgets( R_DISK, 1 );
  248.     }
  249.     }
  250.     cleanup( 0 );
  251. }
  252.  
  253. void CopyRight( )
  254. {
  255.     extern char *copyright_text[];
  256.     int line;
  257.  
  258.     SetDrMd( win->RPort, JAM2 );
  259.     SetAPen( win->RPort, C_WHITE );
  260.     SetBPen( win->RPort, C_GREY );
  261.  
  262.     for(line=0;copyright_text[line];line++){
  263.     Move( win->RPort, ORIGINX+3, ORIGINY + win->RPort->TxBaseline +
  264.         (line*win->RPort->TxHeight));
  265.     if(copyright_text[line][0])
  266.          RPText( win->RPort, copyright_text[line]);
  267.     }
  268.  
  269.     Delay( 150 );
  270.     ClearWindow( win );
  271. }
  272.  
  273. /*
  274.  * Do the one time initialization things.
  275.  */
  276.  
  277. void
  278. InitWB( argc, wbs )
  279.     int argc;
  280.     register struct WBStartup *wbs;
  281. {
  282.     register int c, i, j;
  283.     BPTR odir;
  284.     char *s, **tools, **argv;
  285.     register struct DiskObject *dobj;
  286.     register struct WBArg *wba;
  287.  
  288.     /* Open Libraries */
  289.     GfxBase= (struct GfxBase *) OldOpenLibrary("graphics.library");
  290.     IconBase= OldOpenLibrary("icon.library");
  291.     DiskfontBase= (struct DiskfontBase *)OldOpenLibrary("diskfont.library");
  292.     IntuitionBase= (struct IntuitionBase *)OldOpenLibrary("intuition.library");
  293.  
  294.     if(!GfxBase || !IconBase || !DiskfontBase || !IntuitionBase)
  295.     {
  296.     error("library open failed");
  297.     cleanup( 1 );
  298.     }
  299.  
  300.     /* Get Port for replied WBStartup messages */
  301.  
  302.     if( ( dosport = CreatePort( NULL, 0 ) ) == NULL )
  303.     {
  304.     error("failed to create dosport" );
  305.     cleanup( 1 );
  306.     }
  307.  
  308.     /* If started from CLI */
  309.     if( argc != 0 )
  310.     {
  311.     argv = (char **)wbs;
  312.     for( i = 1; i < argc; ++i )
  313.     {
  314.         if( argv[i][0] != '-' )
  315.         break;
  316.         for( j = 1; c = argv[i][j]; ++j )
  317.         {
  318.         switch( c )
  319.         {
  320.         case 'm':   /* Close screen and window during game to
  321.                  * save memory  */
  322.             shutdown++;
  323.             break;
  324.  
  325.         case 'c':       /* Configuration to load */
  326.             if( i + 1 < argc && argv[i][j+1] == 0 )
  327.             {
  328.             strcpy( NetHackCnf, argv[ ++i ] );
  329.             goto nextargv;
  330.             }
  331.             else
  332.             {
  333.             fprintf( stderr,
  334.                 "%s: missing config name after -c\n",
  335.                 argv[ 0 ] );
  336.             cleanup( 1 );
  337.             }
  338.             break;
  339.  
  340.         case 'N':       /* Public screen name */
  341.             if( i + 1 < argc && argv[i][j+1] == 0 )
  342.             {
  343.             strcpy( pubscreen, argv[ ++i ] );
  344.             goto nextargv;
  345.             }
  346.             else
  347.             {
  348.             fprintf( stderr,
  349.                 "%s: missing screen name after -N\n",
  350.                 argv[ 0 ] );
  351.             cleanup( 1 );
  352.             }
  353.             break;
  354.  
  355.         case 'f':       /* Default game "player" */
  356.             if( i + 1 < argc && argv[i][j+1] == 0 )
  357.             {
  358.             strcpy( defgname, argv[ ++i ] );
  359.             goto nextargv;
  360.             }
  361.             else
  362.             {
  363.             fprintf( stderr,
  364.                 "%s: missing name after -f\n",
  365.                 argv[ 0 ] );
  366.                 cleanup( 1 );
  367.             }
  368.             break;
  369.  
  370.         default:
  371.             fprintf( stderr, "%s: invalid option %c\n",
  372.             argv[0], c );
  373.             fprintf( stderr,
  374.             "usage: %s [-m] [-f name] [-c name][ -N screen] \n",
  375.             argv[ 0 ] );
  376.             cleanup( 1 );
  377.         }
  378.         }
  379. nextargv:;
  380.     }
  381.     }
  382.     else
  383.     {
  384.     /* Process icon's ToolTypes */
  385.  
  386.     wba = wbs->sm_ArgList;
  387.     odir = CurrentDir( wba->wa_Lock );
  388.     if( dobj = GetDiskObject( wba->wa_Name ) )
  389.     {
  390.         tools = (char **) dobj->do_ToolTypes;
  391.  
  392.         if( s = FindToolType( tools, "OPTIONS" ) )
  393.         {
  394.         /* OPTIONS=SHUTDOWN will cause the screen to be closed
  395.          * when a game is started
  396.          */
  397.         if( MatchToolValue( s, "SHUTDOWN" ) )
  398.             ++shutdown;
  399.         }
  400.  
  401.         /* A different configuration file name */
  402.  
  403.         if( s = FindToolType( tools, "CONFIG" ) )
  404.         {
  405.         strcpy( NetHackCnf, s );
  406.         }
  407.  
  408.         /* A different set of defaults then 'wbdefaults.def' */
  409.  
  410.         if( s = FindToolType( tools, "DEFAULT" ) )
  411.         {
  412.         strcpy( defgname, s );
  413.         }
  414.  
  415.         /* A Public screen to open onto */
  416.  
  417.         if( s = FindToolType( tools, "SCREEN" ) )
  418.         {
  419.         strcpy( pubscreen, s );
  420.         }
  421.  
  422.         FreeDiskObject( dobj );
  423.     }
  424.     if( odir )
  425.         CurrentDir( odir );
  426.     }
  427. }
  428.  
  429. /*
  430.  * Read a nethack.cnf like file and collect the configuration
  431.  * information from it.
  432.  */
  433. void ReadConfig()
  434. {
  435.     register FILE *fp;
  436.     register char *buf, *t;
  437.  
  438.     /* Use a dynamic buffer to limit stack use */
  439.  
  440.     if( ( buf = xmalloc( 1024 ) ) == NULL )
  441.     {
  442.     error( "Can't alloc space to read config file" );
  443.     cleanup( 1 );
  444.     }
  445.  
  446.     /* If the file is not there, can't load it */
  447.  
  448.     if( ( fp = fopen( NetHackCnf, "r" ) ) == NULL )
  449.     {
  450.     errmsg( FLASH, "Can't load config file %s", NetHackCnf );
  451.     free( buf );
  452.     return;
  453.     }
  454.  
  455.     /* Read the lines... */
  456.  
  457.     while( fgets( buf, 1024, fp ) != NULL )
  458.     {
  459.     if( *buf == '#' )
  460.         continue;
  461.  
  462.     if( ( t = strchr( buf, '\n' ) ) != NULL )
  463.         *t = 0;
  464.  
  465.     if( strnicmp( buf, "PATH=", 5 ) == 0 )
  466.     {
  467.         setoneopt( PATH_IDX, buf + 5 );
  468.     }
  469.     else if( strnicmp( buf, "PENS=", 4 ) == 0 )
  470.     {
  471.         setoneopt( PENS_IDX, buf + 4 );
  472.     }
  473.     else if( strnicmp( buf, "OPTIONS=", 8 ) == 0 )
  474.     {
  475.         setoneopt( OPTIONS_IDX, buf + 8 );
  476.     }
  477.     else if( strnicmp( buf, "HACKDIR=", 8 ) == 0 )
  478.     {
  479.         setoneopt( HACKDIR_IDX, buf + 8 );
  480.     }
  481.     else if( strnicmp( buf, "LEVELS=", 7 ) == 0 )
  482.     {
  483.         setoneopt( LEVELS_IDX, buf + 7 );
  484.     }
  485.     else if( strnicmp( buf, "SAVE=", 5 ) == 0 )
  486.     {
  487.         setoneopt( SAVE_IDX, buf + 5 );
  488.     }
  489.     else
  490.     {
  491.         /* We don't allow manipulation of the other information */
  492.     }
  493.     }
  494.     fclose( fp );
  495.     free( buf );
  496. }
  497.  
  498. /* Close the workbench screen and window */
  499.  
  500. void CloseDownWB( )
  501. {
  502.     ((struct Process *)FindTask( NULL ))->pr_WindowPtr = (APTR)oldwin;
  503.  
  504.     if( win && win->RPort->TmpRas )
  505.     {
  506.     FreeRaster( tmprasp, width, height );
  507.     }
  508.  
  509.     if( win )
  510.     SafeCloseWindow( win );
  511.  
  512. #ifdef  INTUI_NEW_LOOK
  513.     if( IntuitionBase->LibNode.lib_Version >= 37 )
  514.     {
  515.     while( !scrlocked && CloseScreen( scrn ) == FALSE )
  516.     {
  517.         Ask("Close all vistor Windows to exit" );
  518.     }
  519.     }
  520.     else
  521. #endif
  522.     {
  523.     CloseScreen( scrn );
  524.     }
  525.     wbopen = 0;
  526. }
  527.  
  528. /* Open the workbench screen and window. */
  529.  
  530. void SetupWB( )
  531. {
  532.     int cpyrwid, i;
  533.     int txtdiff;
  534. #ifdef  INTUI_NEW_LOOK
  535.     int pubopen = 0;
  536. #endif
  537.     static int once = 0;
  538.  
  539.     scrlocked = 0;
  540. #ifdef  INTUI_NEW_LOOK
  541.     NewScreenStructure.Extension = scrntags;
  542.     NewScreenStructure.Type |= NS_EXTENDED;
  543. #endif
  544.  
  545.     NewScreenStructure.Width = GfxBase->NormalDisplayColumns;
  546.     NewScreenStructure.Height = GfxBase->NormalDisplayRows;
  547.  
  548. #ifdef  INTUI_NEW_LOOK
  549.     if( IntuitionBase->LibNode.lib_Version < 37 )
  550.     {
  551. #endif
  552.     if( ( scrn = OpenScreen( (void *)
  553.         &NewScreenStructure ) ) == NULL )
  554.     {
  555.         error( "Can't create screen" );
  556.         cleanup( 1 );
  557.     }
  558.  
  559.     /* Only set the pens on the screen we open */
  560.     LoadRGB4( &scrn->ViewPort, Palette, PaletteColorCount );
  561. #ifdef  INTUI_NEW_LOOK
  562.     }
  563.     else
  564.     {
  565.     /* No tags beyond here yet */
  566.     scrntags[1].ti_Tag = TAG_DONE;
  567.  
  568.     if( *pubscreen != 0 )
  569.     {
  570.         if( ( scrn = LockPubScreen( pubscreen ) ) == 0 )
  571.         {
  572.         scrntags[1].ti_Tag = SA_PubName;
  573.         scrntags[1].ti_Data = (ULONG) pubscreen;
  574.         scrntags[2].ti_Tag = TAG_DONE;
  575.         if( ( scrn = OpenScreen( (void *)
  576.             &NewScreenStructure ) ) == NULL )
  577.         {
  578.             error( "Can't create screen" );
  579.             cleanup( 1 );
  580.         }
  581.         pubopen = 1;
  582.         scrlocked = 0;
  583.         }
  584.         else
  585.         {
  586.         pubopen = 0;
  587.         scrlocked = 1;
  588.         }
  589.     }
  590.     else
  591.     {
  592.         if( ( scrn = LockPubScreen( NULL ) ) == 0 )
  593.         {
  594.         error( "Can't lock Workbench screen" );
  595.         cleanup( 1 );
  596.         }
  597.         scrlocked = 1;
  598.     }
  599.     }
  600. #endif
  601.  
  602.     cpyrwid = 0;
  603.     for( i = 0; copyright_text[i]; ++i )
  604.     cpyrwid = max(cpyrwid, strlen( copyright_text[i] ) );
  605.  
  606.     /* 28 is magic for the width of the sizing gadget under 2.04 and
  607.      * later.
  608.      */
  609.     NewWindowStructure1.Width = (cpyrwid * scrn->RastPort.TxWidth) +
  610.         scrn->WBorLeft + scrn->WBorRight + 28;
  611.  
  612.     width = NewWindowStructure1.Width;
  613.  
  614.     if( NewWindowStructure1.LeftEdge + width > scrn->Width )
  615.     {
  616.     if( width > scrn->Width )
  617.     {
  618.         NewWindowStructure1.LeftEdge = 0;
  619.         NewWindowStructure1.Width = scrn->Width;
  620.     }
  621.     else
  622.     {
  623.         NewWindowStructure1.LeftEdge = (scrn->Width - width)/2;
  624.     }
  625.     }
  626.     height = NewWindowStructure1.Height;
  627.     NewWindowStructure1.Screen = scrn;
  628.  
  629.     txtdiff = scrn->RastPort.TxHeight - 8;
  630.  
  631. #ifdef  INTUI_NEW_LOOK
  632.     if( scrlocked )
  633.     strcpy( mytitle, "NetHack WB 3.1 - Select a GAME or press HELP" );
  634.     else
  635.     strcpy( mytitle, "Select a GAME or press HELP" );
  636.  
  637.     NewWindowStructure1.Title = mytitle;
  638.     if( IntuitionBase->LibNode.lib_Version >= 37 )
  639.     {
  640.     ((struct PropInfo *)Scroll.SpecialInfo)->Flags |= PROPNEWLOOK;
  641.     }
  642. #endif
  643.  
  644.     if( !once )
  645.     {
  646.     ((struct Border *) Message.GadgetRender)->XY[2] =
  647.         NewWindowStructure1.Width +
  648.         Message.Width - Message.LeftEdge;
  649.     Message.TopEdge = scrn->RastPort.TxHeight + scrn->WBorTop + 1;
  650.     Message.Height = scrn->RastPort.TxHeight + 3;
  651.         ((struct Border *) Message.GadgetRender)->XY[1] =
  652.         (((struct Border *) Message.GadgetRender)->XY[3] +=
  653.         scrn->RastPort.TxHeight - 6 );
  654.     }
  655.  
  656.     if( ( win = MyOpenWindow( &NewWindowStructure1 ) ) == NULL )
  657.     {
  658. #ifdef  INTUI_NEW_LOOK
  659.     if( IntuitionBase->LibNode.lib_Version >= 37 )
  660.     {
  661.         if( scrlocked )
  662.         UnlockPubScreen( NULL, scrn );
  663.     }
  664. #endif
  665.     error( "Can't create window" );
  666.     cleanup( 1 );
  667.     }
  668. #ifdef  INTUI_NEW_LOOK
  669.     if( IntuitionBase->LibNode.lib_Version >= 37 )
  670.     {
  671.     if( scrlocked )
  672.         UnlockPubScreen( NULL, scrn );
  673.     else if( pubopen )
  674.         PubScreenStatus( scrn, 0 );
  675.     }
  676. #endif
  677.  
  678.     ((struct Border *) Message.GadgetRender)->XY[2] =
  679.         win->Width - win->BorderLeft -
  680.         win->BorderRight - 1;
  681.  
  682.     RefreshGList( &Message, win, NULL, 1 );
  683. #ifdef  INTUI_NEW_LOOK
  684.     if( IntuitionBase->LibNode.lib_Version >= 37 )
  685.     RefreshWindowFrame( win );
  686. #endif
  687.  
  688.     oldwin = (struct Window *)((struct Process *)FindTask( NULL ))->pr_WindowPtr;
  689.     ((struct Process *)FindTask( NULL ))->pr_WindowPtr = (APTR)win;
  690.  
  691.     if( ( tmprasp = (void *) AllocRaster( width, height ) ) == NULL )
  692.     {
  693.     win->RPort->TmpRas = NULL;
  694.     fprintf( stderr, "No Space for raster %d x %d\n", height, width );
  695.     cleanup( 1 );
  696.     }
  697.  
  698.     InitTmpRas( &tmpras, tmprasp, RASSIZE( width, height ) );
  699.  
  700.     win->RPort->TmpRas = &tmpras;
  701.  
  702.     SetUpMenus( &MenuList1, scrn );
  703.     SetMenuStrip( win, &MenuList1 );
  704.     wbopen = 1;
  705.     once = 1;
  706. }
  707.  
  708. /* Map the gadgets onto the screen at the correct location */
  709.  
  710. void MapGadgets( reason, update )
  711.     int reason;
  712.     int update;
  713. {
  714.     GPTR gptr;
  715.  
  716.     /* Make sure that any down gadget is popped back up */
  717.  
  718.     if( lastgaddown )
  719.     SetGadgetUP( &lastgaddown->dobj->do_Gadget );
  720.     lastgaddown = NULL;
  721.  
  722.     /* Grey Menu Items, no Game icon will be selected */
  723.  
  724.     ChgGameItems( &MenuList1, 0 );
  725.  
  726.     /* Remove them first */
  727.  
  728.     for( gptr = windowgads; gptr; gptr = gptr->nextwgad )
  729.     {
  730.     RemoveGadget( win, &gptr->dobj->do_Gadget );
  731.     }
  732.     windowgads = NULL;
  733.  
  734.     /* Remove any non-existant games */
  735.  
  736.     ClearDelGames( );
  737.  
  738.     /* If disk changed, reload existing icons */
  739.  
  740.     if( reason == R_DISK )
  741.     {
  742.     LoadIcons( );
  743.     }
  744.  
  745.     /* Always move back to home unless we were scrolling */
  746.  
  747.     if( reason != R_SCROLL )
  748.     {
  749.     curcol = 0;
  750.     }
  751.  
  752.     /* Calculate locations and display gadgets */
  753.  
  754.     CalcLocs( update );
  755. }
  756.  
  757. void ClearWindow( win )
  758.     struct Window *win;
  759. {
  760.     /* Clear the old gadgets from the window */
  761.  
  762.     SetAPen( win->RPort, C_GREY );
  763.     SetOPen( win->RPort, C_GREY );
  764.     SetDrPt( win->RPort, 0xffff );
  765.     SetDrMd( win->RPort, JAM2 );
  766.  
  767.     RectFill( win->RPort, ORIGINX, ORIGINY, CORNERX-1, CORNERY-1 );
  768. }
  769.  
  770. /* Calculate the place for and attach the gadgets to the window */
  771.  
  772. void
  773. CalcLocs( update )
  774.     int update;
  775. {
  776.     register GPTR gptr;
  777.     register USHORT ox, oy, cx, cy;
  778.     int gadid = GADNEWGAME;
  779.     int addx = 0, sizex, sizey;
  780.  
  781.     cols = vcols = 0;
  782.     scol = -1;
  783.  
  784.     /* Upper left corner of window */
  785.  
  786.     ox = ORIGINX;
  787.     oy = ORIGINY;
  788.  
  789.     /* Lower right corner of window */
  790.  
  791.     cx = CORNERX;
  792.  
  793.     /* Account for text labels at the bottom by pulling the bottom up. */
  794.     cy = CORNERY - win->RPort->TxHeight - 3;
  795.  
  796.     ClearWindow( win );
  797.  
  798.     /* Map the current list */
  799.  
  800.     for( gptr = gamehead; gptr; gptr = gptr->next )
  801.     {
  802.     /* If not to the horizontal offset yet, don't display */
  803.  
  804.     sizex = GADWIDTH( &gptr->dobj->do_Gadget );
  805.     sizey = gptr->dobj->do_Gadget.Height;
  806.     addx = max( sizex, addx );
  807.  
  808.     /* If the current column comes before the visible column... */
  809.     if( cols < curcol )
  810.     {
  811.         oy += sizey + GADINCY + 3;
  812.         if( gptr->next )
  813.         {
  814.         if( oy + gptr->next->dobj->do_Gadget.Height + 3 >= cy )
  815.         {
  816.             cols++;
  817.             ox += addx + GADINCX;
  818.             if( GADWIDTH( &gptr->next->dobj->do_Gadget ) >
  819.             gptr->next->dobj->do_Gadget.Width )
  820.             {
  821.             ox += ( GADWIDTH( &gptr->next->dobj->do_Gadget ) -
  822.             gptr->next->dobj->do_Gadget.Width ) / 2 + 1;
  823.             }
  824.             oy = ORIGINY;
  825.             addx = 0;
  826.         }
  827.         }
  828.         continue;
  829.     }
  830.  
  831.     if( scol == -1 )
  832.     {
  833.         ox = ORIGINX;
  834.         scol = cols;
  835.     }
  836.  
  837.     /* If visible, draw it */
  838.  
  839.     if( ox + sizex + GADINCX < cx )
  840.     {
  841.         /* Link to mapped gadgets list */
  842.  
  843.         gptr->nextwgad = windowgads;
  844.         windowgads = gptr;
  845.  
  846.         /* Set screen locations, if text is longer, scoot the
  847.          * gadget over to make room for it.
  848.          */
  849.  
  850.         if( GADWIDTH( &gptr->dobj->do_Gadget ) >
  851.             gptr->dobj->do_Gadget.Width )
  852.         {
  853.         gptr->dobj->do_Gadget.LeftEdge = ox +
  854.             ( GADWIDTH( &gptr->dobj->do_Gadget ) -
  855.             gptr->dobj->do_Gadget.Width ) / 2 + 1;
  856.         }
  857.         else
  858.         gptr->dobj->do_Gadget.LeftEdge = ox;
  859.         addx = max( addx, GADWIDTH( &gptr->dobj->do_Gadget) );
  860.         gptr->dobj->do_Gadget.TopEdge = oy;
  861.         gptr->dobj->do_Gadget.GadgetID = gadid++;
  862.  
  863.         AddGadget( win, &gptr->dobj->do_Gadget, 0 );
  864.     }
  865.  
  866.     /* Stack vertically first, then horizontally */
  867.  
  868.     if( gptr->next )
  869.     {
  870.         oy += sizey + GADINCY + 3;
  871.         if( oy + gptr->next->dobj->do_Gadget.Height + 3 >= cy )
  872.         {
  873.         ox += addx + GADINCX;
  874.         cols++;
  875.         if( ox + GADWIDTH( &gptr->next->dobj->do_Gadget) < cx )
  876.             vcols++;
  877.         addx = 0;
  878.         oy = ORIGINY;
  879.         }
  880.     }
  881.     }
  882.  
  883.     /* Display all of the gadgets */
  884.  
  885.     RefreshGList( win->FirstGadget, win, NULL, -1 );
  886.  
  887.     /* Set up the slider if forcing a new position, otherwise
  888.      * the slider was probably moved and its position should be
  889.      * left where the user put it instead of jerking it around
  890.      */
  891.     if( update )
  892.     UpdatePropGad( win, &Scroll, vcols+1, cols+1, scol );
  893. }
  894.  
  895. /* Open the indicated window and place the IntuiText list passed in that
  896.  * window.  Then wait for the OKAY gadget to be clicked on.
  897.  */
  898. void text_requester( newwin, tlist )
  899.     register struct NewWindow *newwin;
  900.     struct IntuiText *tlist;
  901. {
  902.     register struct Window *win;
  903.     register struct IntuiMessage *imsg;
  904.     register struct Gadget *gd;
  905.     int done = 0;
  906.     int i;
  907.     long class;
  908.     struct NewWindow **aonce;
  909.     static struct NewWindow *once[ 6+1 ];
  910.     int lines[ 10 ], lcnt = 0, avone = -1;
  911.     register int txtdiff = scrn->RastPort.TxHeight - 8;
  912.  
  913.     newwin->Screen = scrn;
  914.  
  915.     for( i = 0; i < 6; ++i )
  916.     {
  917.     if( newwin == once[i] )
  918.         break;
  919.     if( once[i] == 0 && avone == -1 )
  920.         avone = i;
  921.     }
  922.     aonce = &once[avone];
  923.  
  924.     /* If spacing not correct, fix it up now */
  925.     if( *aonce == NULL )
  926.     {
  927.     register struct IntuiText *ip = tlist;
  928.     for( ; ip; ip = ip->NextText )
  929.     {
  930.         if( lcnt == 0 )
  931.         lines[ lcnt++ ] = ip->TopEdge;
  932.         else
  933.         {
  934.         register found = 0;
  935.         for( i = 0; i < lcnt; ++i )
  936.         {
  937.             if( lines[ i ] > ip->TopEdge )
  938.             break;
  939.             if( lines[ i ] == ip->TopEdge )
  940.             {
  941.             found = 1;
  942.             break;
  943.             }
  944.         }
  945.  
  946.         if( !found )
  947.         {
  948.             if( i < lcnt )
  949.             {
  950.             int j;
  951.             for( j = lcnt; j > i; --j )
  952.                 lines[ j ] = lines[ j - 1 ];
  953.             }
  954.             lcnt++;
  955.             lines[ i ] = ip->TopEdge;
  956.         }
  957.         }
  958.     }
  959.  
  960.     for( ip = tlist; ip; ip = ip->NextText )
  961.     {
  962.         for( i = 0; i < lcnt; ++i )
  963.         {
  964.         if( ip->TopEdge == lines[ i ] )
  965.         {
  966.             ip->TopEdge += txtdiff*i;
  967.             break;
  968.         }
  969.         }
  970.     }
  971.  
  972.     gd = FindGadget( NULL, newwin, GADHELPOKAY );
  973.     gd->TopEdge += (lcnt+1)*txtdiff;
  974.     gd->Height += txtdiff;
  975.     SetBorder( gd, -1 );
  976.     newwin->Height += txtdiff * (lcnt+2);
  977.     *aonce = newwin;
  978.     }
  979.  
  980.     if( ( win = MyOpenWindow( newwin ) ) == NULL )
  981.     {
  982.     errmsg( FLASH, "Can't create window" );
  983.     return;
  984.     }
  985.  
  986.     PrintIText( win->RPort, tlist, 0, txtdiff );
  987.  
  988.     while( !done )
  989.     {
  990.     WaitPort( win->UserPort );
  991.     while( ( imsg = (struct IntuiMessage * )
  992.         GetMsg( win->UserPort ) ) != NULL )
  993.     {
  994.         class = imsg->Class;
  995.         ReplyMsg( (struct Message *) imsg );
  996.         switch( class )
  997.         {
  998.         case CLOSEWINDOW: done = 1; break;
  999.         case VANILLAKEY: done = 1; break;
  1000.         /* Should be GADHELPOKAY */
  1001.         case GADGETUP: done = 1; break;
  1002.         }
  1003.     }
  1004.     }
  1005.     SafeCloseWindow( win );
  1006. }
  1007.  
  1008. /* Scroll through a file which is passed by name */
  1009.  
  1010. void help_requester( file )
  1011.     char *file;
  1012. {
  1013.     register struct Window *win;
  1014.     register struct IntuiMessage *imsg;
  1015.     register struct Gadget *gd;
  1016.     FILE *fp;
  1017.     int done = 0, line = 0, lines, topline, tlines, i;
  1018.     static int once = 0, lastdown;
  1019.     char buf[ 100 ];
  1020.     long loff[ 100 ];
  1021.     long class, code;
  1022.     int txtdiff = scrn->RastPort.TxHeight - 8;
  1023.  
  1024.     if( ( fp = fopen( file, "r" ) ) == NULL )
  1025.     {
  1026. #ifdef  __SASC_60
  1027.     errmsg( FLASH, "Can't open %s: %s", file, strerror(errno) );
  1028. #else
  1029.     errmsg( FLASH, "Can't open %s: %s", file, sys_errlist[errno] );
  1030. #endif
  1031.     return;
  1032.     }
  1033.     for( tlines = 0; tlines < 100 ; ++tlines )
  1034.     {
  1035.     loff[ tlines ] = ftell( fp );
  1036.     if( fgets( buf, sizeof( buf ), fp ) == NULL )
  1037.         break;
  1038.     }
  1039.  
  1040.     if( !once )
  1041.     {
  1042.     for( gd = Help3_NewWindowStructure10.FirstGadget;
  1043.             gd; gd = gd->NextGadget )
  1044.     {
  1045.         if( gd->GadgetID != 0 )
  1046.         {
  1047.         if( gd->GadgetID == GADHELPFRWD ||
  1048.             gd->GadgetID == GADHELPBKWD )
  1049.         {
  1050.             gd->Height += txtdiff;
  1051.         }
  1052.         SetBorder( gd, -1 );
  1053.         }
  1054.     }
  1055.     once = 1;
  1056.     Help3_NewWindowStructure10.Height += txtdiff;
  1057.     }
  1058.  
  1059.     Help3_NewWindowStructure10.Screen = scrn;
  1060.     if( ( win = MyOpenWindow( &Help3_NewWindowStructure10 ) ) == NULL )
  1061.     {
  1062.     errmsg( FLASH, "Can't create requester window" );
  1063.     fclose( fp );
  1064.     return;
  1065.     }
  1066.     lines = ( (win->Height - win->BorderTop - 25 ) / win->RPort->TxHeight );
  1067.     topline = win->BorderTop + win->RPort->TxBaseline + 2;
  1068.     Move( win->RPort, win->BorderLeft, topline );
  1069.  
  1070.     SetAPen( win->RPort, C_BLACK );
  1071.     SetBPen( win->RPort, C_GREY );
  1072.     SetDrMd( win->RPort, JAM2 );
  1073.  
  1074.     for( i = 0; i < min( lines, tlines ); ++i )
  1075.     {
  1076.     getline( fp, loff, i, buf, sizeof( buf ) );
  1077.     Move( win->RPort, win->BorderLeft + 2,
  1078.         topline + (i * win->RPort->TxHeight) );
  1079.     Text( win->RPort, buf, strlen( buf )-1 );
  1080.     }
  1081.  
  1082.     while( !done )
  1083.     {
  1084.     WaitPort( win->UserPort );
  1085.     while( ( imsg = (void *) GetMsg( win->UserPort ) ) != NULL )
  1086.     {
  1087.         class = imsg->Class;
  1088.         code = imsg->Code;
  1089.         gd = (struct Gadget *)imsg->IAddress;
  1090.  
  1091.         ReplyMsg( (struct Message *) imsg );
  1092.  
  1093.         switch( class )
  1094.         {
  1095.         case VANILLAKEY:
  1096.             if( code == 'u' || code == ('U'-64))
  1097.             {
  1098.             goto bkwd;
  1099.             }
  1100.             else if( code == 'd' || code == ('D'-64))
  1101.             {
  1102.             goto frwd;
  1103.             }
  1104.             else if( code == '\33' || code == 'q' )
  1105.             {
  1106.             done = 1;
  1107.             }
  1108.             break;
  1109.  
  1110.         case CLOSEWINDOW:
  1111.             done = 1;
  1112.             break;
  1113.  
  1114.         case GADGETUP:
  1115.             lastdown = 0;
  1116.             break;
  1117.  
  1118.         case GADGETDOWN:
  1119.             lastdown = gd->GadgetID;
  1120.             break;
  1121.  
  1122.         case INTUITICKS:
  1123.             if( lastdown == GADHELPFRWD )
  1124.             {
  1125.             frwd:
  1126.             if( line + lines < tlines )
  1127.             {
  1128.                 line++;
  1129.                 WaitTOF();
  1130.                 ScrollRaster( win->RPort, 0,
  1131.                 win->RPort->TxHeight,
  1132.                 win->BorderLeft,
  1133.                 win->BorderTop + 2,
  1134.                 win->Width - win->BorderRight - 1,
  1135.                 win->BorderTop + 2 +
  1136.                 (lines*win->RPort->TxHeight) );
  1137.                 getline( fp, loff, line + lines - 1,
  1138.                 buf, sizeof( buf ) );
  1139.                 Move( win->RPort, win->BorderLeft + 2,
  1140.                 topline + ( ( lines - 1 ) *
  1141.                 win->RPort->TxHeight ) );
  1142.                 WaitTOF();
  1143.                 Text( win->RPort, buf, strlen( buf )-1 );
  1144.             }
  1145.             else
  1146.             {
  1147.                 /* EOF */
  1148.                 DisplayBeep( scrn );
  1149.             }
  1150.             }
  1151.             else if( lastdown == GADHELPBKWD )
  1152.             {
  1153.             bkwd:
  1154.             if( line > 0 )
  1155.             {
  1156.                 line--;
  1157.                 WaitTOF();
  1158.                 ScrollRaster( win->RPort, 0,
  1159.                 -win->RPort->TxHeight,
  1160.                 win->BorderLeft,
  1161.                 win->BorderTop + 2,
  1162.                 win->Width - win->BorderRight - 1,
  1163.                 win->BorderTop + 2 +
  1164.                 (lines*win->RPort->TxHeight) );
  1165.                 getline( fp, loff, line, buf, sizeof( buf ) );
  1166.                 Move( win->RPort, win->BorderLeft + 2, topline );
  1167.                 WaitTOF();
  1168.                 Text( win->RPort, buf, strlen( buf )-1 );
  1169.             }
  1170.             else
  1171.             {
  1172.                 DisplayBeep( scrn );
  1173.             }
  1174.             }
  1175.             break;
  1176.  
  1177.         }
  1178.     }
  1179.     }
  1180.     SafeCloseWindow( win );
  1181.     fclose( fp );
  1182. }
  1183.  
  1184. /* Act on the menu item number passed */
  1185.  
  1186. void
  1187. do_menu(mcode)
  1188.     register int mcode;
  1189. {
  1190.     switch(MENUNUM(mcode))
  1191.     {
  1192.     case MENU_PROJECT:
  1193.         switch(ITEMNUM(mcode))
  1194.         {
  1195.         case ITEM_HELP:
  1196.             help_requester( "NetHack:HackWB.hlp" );
  1197.             break;
  1198.  
  1199.         case ITEM_ABOUT:
  1200.             text_requester( &About_NewWindowStructure9,
  1201.                 &About_IntuiTextList9 );
  1202.             break;
  1203.  
  1204.         case ITEM_SCORES:
  1205.             menu_scores( );
  1206.             break;
  1207.  
  1208.         case ITEM_RECOVER:
  1209.             menu_recover( );
  1210.             break;
  1211.  
  1212.         case ITEM_EDDEF:
  1213.             menu_editdef( GAME_FROM_DEFAULT );
  1214.             break;
  1215.  
  1216.         case ITEM_CONFIG:
  1217.             menu_config( );
  1218.             break;
  1219.  
  1220.         case ITEM_QUIT:
  1221.             quit = Ask( "Ready to Quit?" );
  1222.             break;
  1223.  
  1224.         }
  1225.         break;
  1226.  
  1227.     case MENU_GAME:
  1228.         switch( ITEMNUM( mcode ) )
  1229.         {
  1230.  
  1231.         case ITEM_INFO:
  1232.             menu_info( );
  1233.             break;
  1234.  
  1235.         case ITEM_SETCOMMENT:
  1236.             menu_comment( );
  1237.             break;
  1238.  
  1239.         case ITEM_SETOPT:
  1240.             menu_setopt( );
  1241.             break;
  1242.  
  1243.         case ITEM_COPYOPT:
  1244.             menu_copyopt( );
  1245.             break;
  1246.  
  1247.         case ITEM_DISCARD:
  1248.             menu_discard( );
  1249.             break;
  1250.  
  1251.         case ITEM_RENAME:
  1252.             menu_rename( );
  1253.             break;
  1254.         }
  1255.     }
  1256. }
  1257.  
  1258. void
  1259. menu_discard()
  1260. {
  1261.     register GPTR gptr;
  1262.  
  1263.     if( ( gptr = NeedGame() ) == NULL )
  1264.     return;
  1265.  
  1266.     if( Ask("Discard Selected Game?") )
  1267.     {
  1268.     lastgaddown = NULL;
  1269.     if( DeleteGame( gptr ) == 0 )
  1270.     {
  1271.         errmsg( FLASH, "Discard may have failed for %s",
  1272.             GameName( gptr, NULL ) );
  1273.     }
  1274.  
  1275.     MapGadgets( R_DISK, 1 );
  1276.     }
  1277. }
  1278.  
  1279. void
  1280. run_game( gptr )
  1281.     register GPTR gptr;
  1282. {
  1283.     struct Task *ctask;
  1284.     register struct MsgPort *proc = NULL;
  1285.     char buf[ 100 ], *t;
  1286.     char namebuf[ 100 ];
  1287.     int once, tidx;
  1288.  
  1289.     if( gptr->active )
  1290.     {
  1291.     errmsg( FLASH, "%s is already in progress", gptr->name );
  1292.     return;
  1293.     }
  1294.  
  1295.     tidx = 0;
  1296.  
  1297.     /* If newgame gadget, then check game name */
  1298.  
  1299.     if( gptr->dobj->do_Gadget.GadgetID == GADNEWGAME )
  1300.     {
  1301.         /*
  1302.         if currrent name in use, get new name
  1303.         */
  1304.  
  1305.     if( !defgame.plname )
  1306.         defgame.plname = strdup( defgname );
  1307.  
  1308.     /* Put options from gadgets into options[ OPTIONS_IDX ] */
  1309.  
  1310.     PutOptions( curopts );
  1311.  
  1312.     once = 0;
  1313.     sprintf( buf, "%s/%s.sav", options[ SAVE_IDX ], defgame.plname );
  1314.     while( access( buf, 0 ) == 0 )
  1315.     {
  1316.         if( StrRequest( "Game Already Exists, Enter a New Name",
  1317.         namebuf, once ? namebuf : defgame.plname ) == 0 )
  1318.         {
  1319.         return;
  1320.         }
  1321.         once = 1;
  1322.         sprintf( buf, "%s/%s.sav", options[ SAVE_IDX ], namebuf );
  1323.     }
  1324.  
  1325.     /* Set new name to use, if done one at all */
  1326.     if( once )
  1327.     {
  1328.         if( defgame.plname ) free( defgame.plname );
  1329.         defgame.plname = strdup( namebuf );
  1330.     }
  1331.  
  1332.         /* set defaults for this game from previous defaults. */
  1333.     if( defgame.plname && stricmp( defgame.plname, "wbdefaults" ) )
  1334.         SetToolLine( gptr, "NAME", defgame.plname );
  1335.     if( defgame.pltype )
  1336.         SetToolLine( gptr, "CHARACTER", players[ defgame.pltype ] );
  1337.  
  1338.     gptr->gname = xmalloc( 20 + strlen( defgame.plname ) );
  1339.     }
  1340.     else
  1341.     {
  1342.     gptr->gname = xmalloc( 20 + strlen( gptr->name ) );
  1343.     }
  1344.  
  1345.     SetToolLine( gptr, "PATH", options[ PATH_IDX ] );
  1346.     if( defgame.options )
  1347.     SetToolLine( gptr, "OPTIONS", defgame.options );
  1348.     else
  1349.     SetToolLine( gptr, "OPTIONS", options[ OPTIONS_IDX ] );
  1350.  
  1351.     /* Prefer a setting in the users data over the global one */
  1352.     if( ( ( t = ToolsEntry( gptr, "PENS" ) ) == NULL || *t == 0 ) &&
  1353.       ( ( t = ToolsEntry( gptr, "PEN" ) ) == NULL || *t == 0 ) )
  1354.     {
  1355.     t = options[ PENS_IDX ];
  1356.     }
  1357.     SetToolLine( gptr, "PENS", t );
  1358.     SetToolLine( gptr, "HACKDIR", options[ HACKDIR_IDX ] );
  1359.     SetToolLine( gptr, "LEVELS", options[ LEVELS_IDX ] );
  1360.     SetToolLine( gptr, "SAVE", options[ SAVE_IDX ] );
  1361.  
  1362.     gptr->wbs = AllocMem( sizeof( struct WBStartup ) +
  1363.     ( sizeof( struct WBArg ) * 2 ), MEMF_PUBLIC | MEMF_CLEAR );
  1364.  
  1365.     /* Check if we got everything */
  1366.  
  1367.     if( !gptr->gname || !gptr->wbs )
  1368.     {
  1369.     fprintf( stderr, "Can't allocate memory\n" );
  1370.     goto freemem;
  1371.     }
  1372.  
  1373.     /* Get the arguments structure space */
  1374.  
  1375.     gptr->wba = ( struct WBArg * ) ((long)gptr->wbs +
  1376.         sizeof( struct WBStartup ) );
  1377.  
  1378.     /* Close down window and screen if requested */
  1379.  
  1380.     if( shutdown )
  1381.     CloseDownWB( );
  1382.  
  1383.     /* Load the game into memory */
  1384. #ifdef SPLIT
  1385.     /* Which version do we run? */
  1386.     {
  1387.     char gi[80];
  1388.  
  1389.     sprintf( gi, "%s.dir", GAMEIMAGE );
  1390.     if( access( gi, 0 ) == 0 ){
  1391.     gptr->seglist = (BPTR)s_LoadSeg( gi );
  1392.     if( gptr->seglist ) running_split=1;
  1393.     }else{
  1394.     gptr->seglist = (BPTR)LoadSeg( GAMEIMAGE );
  1395.     }
  1396.     }
  1397. #else
  1398.     gptr->seglist = (BPTR)LoadSeg( GAMEIMAGE );
  1399. #endif
  1400.  
  1401.     if( gptr->seglist == NULL)
  1402.     {
  1403.     if( !wbopen )
  1404.         SetupWB( );
  1405.     errmsg( FLASH, "Can't load %s", GAMEIMAGE );
  1406.     goto freemem;
  1407.     }
  1408.     /* Build WBStartup from current game info */
  1409.  
  1410.     /* Set the game name for the status command */
  1411.  
  1412.     sprintf( gptr->gname, "NetHack 3.1 %s", gptr->name );
  1413.  
  1414.     /* Create a process for the game to execute in */
  1415.  
  1416.     ctask = FindTask( NULL );
  1417.     proc = CreateProc( gptr->gname, ctask->tc_Node.ln_Pri,
  1418.     gptr->seglist, GAMESTACK );
  1419.  
  1420.     /* Check if the create failed */
  1421.  
  1422.     if( proc == NULL )
  1423.     {
  1424.     fprintf(stderr, "Error creating process %d\n", IoErr() );
  1425. #ifdef SPLIT
  1426.     if(!running_split)
  1427. #endif
  1428.         UnLoadSeg( gptr->seglist );
  1429. freemem:
  1430.     if( gptr->gname ) free( gptr->gname );
  1431.     gptr->gname = NULL;
  1432.  
  1433.     if( gptr->wbs ) FreeMem( gptr->wbs,
  1434.     sizeof( struct WBStartup ) + sizeof( struct WBArg ) * 2 );
  1435.     gptr->wbs = NULL;
  1436.     if( !wbopen )
  1437.     SetupWB( );
  1438.     return;
  1439.     }
  1440.  
  1441.     /* Get the Process structure pointer */
  1442.  
  1443.     gptr->prc = (struct Process *) (((long)proc) - sizeof( struct Task ));
  1444.  
  1445.     /* Set the current directory */
  1446.  
  1447.     gptr->prc->pr_CurrentDir=((struct Process *)FindTask(NULL))->pr_CurrentDir;
  1448.  
  1449.     /* Fill in the startup message */
  1450.  
  1451.     gptr->wbs->sm_Process = proc;
  1452.     gptr->wbs->sm_Segment = gptr->seglist;
  1453.     gptr->wbs->sm_NumArgs = 2;
  1454.     gptr->wbs->sm_ToolWindow = "con:0/0/350/50/Amiga NetHack 3.1";
  1455.     gptr->wbs->sm_ArgList = gptr->wba;
  1456.  
  1457.     /* Fill in the args */
  1458.  
  1459.     gptr->wba[0].wa_Name = Strdup( GAMEIMAGE );
  1460.     gptr->wba[0].wa_Lock = Lock( dirname( GAMEIMAGE ), ACCESS_READ );
  1461.  
  1462.     gptr->wba[1].wa_Name = Strdup( gptr->name );
  1463.     gptr->wba[1].wa_Lock = Lock( gptr->dname, ACCESS_READ );
  1464.  
  1465.     /* Write the updated tools types entries */
  1466.  
  1467.     WriteDObj( gptr, gptr->wba[1].wa_Lock );
  1468.  
  1469.     /* Set the message fields correctly */
  1470.  
  1471.     gptr->wbs->sm_Message.mn_Node.ln_Type = NT_MESSAGE;
  1472.     gptr->wbs->sm_Message.mn_Node.ln_Pri = 0;
  1473.     gptr->wbs->sm_Message.mn_ReplyPort = dosport;
  1474.     gptr->wbs->sm_Message.mn_Length =
  1475.     sizeof( struct WBStartup ) + ( sizeof( struct WBArg ) * 2 );
  1476.  
  1477.     /* mark game as in use */
  1478.  
  1479.     active_count++;
  1480.     gptr->active = 1;
  1481.  
  1482.     /* Send the WB Startup message to let the game go... */
  1483.  
  1484.     PutMsg( proc, &gptr->wbs->sm_Message );
  1485. }
  1486.  
  1487. void CloseLibraries( )
  1488. {
  1489.     if( IntuitionBase )     CloseLibrary( (void *) IntuitionBase );
  1490.     IntuitionBase = 0;
  1491.     if( DiskfontBase )      CloseLibrary( (void *) DiskfontBase );
  1492.     DiskfontBase = 0;
  1493.     if( IconBase )          CloseLibrary(  IconBase );
  1494.     IconBase = 0;
  1495.     if( GfxBase )           CloseLibrary( (void *) GfxBase );
  1496.     GfxBase = 0;
  1497. }
  1498.  
  1499. void cleanup( code )
  1500.     int code;
  1501. {
  1502.     if( active_count )
  1503.     {
  1504.     errmsg( FLASH, "There %s still %d game%s active...",
  1505.         active_count > 1 ? "are" : "is",
  1506.         active_count,
  1507.         active_count > 1 ? "s" : "" );
  1508.     return;
  1509.     }
  1510.  
  1511.     if( dosport ) DeletePort( dosport );
  1512.     dosport = NULL;
  1513.  
  1514.     CloseDownWB( );
  1515.     CleanUpLists( );
  1516.     CloseLibraries( );
  1517.  
  1518. #ifdef SPLIT
  1519.     if(running_split)s_UnLoadSeg();
  1520. #endif
  1521.     exit( code );
  1522. }
  1523.  
  1524. GPTR AllocGITEM( )
  1525. {
  1526.     register GPTR gptr;
  1527.  
  1528.     if( gameavail )
  1529.     {
  1530.     gptr = gameavail;
  1531.     gameavail = gameavail->next;
  1532.     }
  1533.     else
  1534.     {
  1535.     gptr = xmalloc( sizeof( GAMEITEM ) );
  1536.     }
  1537.  
  1538.     if( gptr )
  1539.     memset( gptr, 0, sizeof( GAMEITEM ) );
  1540.  
  1541.     return( gptr );
  1542. }
  1543.  
  1544. void FreeGITEM( gptr )
  1545.     register GPTR gptr;
  1546. {
  1547.     /* Free all of the pieces first */
  1548.  
  1549.     if( gptr->talloc )
  1550.     FreeTools( gptr );
  1551.  
  1552.     if( gptr->dobj )
  1553.     FreeDObj( gptr->dobj );
  1554.  
  1555.     gptr->dobj = NULL;
  1556.  
  1557.     if( gptr->name )
  1558.     free( gptr->name );
  1559.     gptr->name = NULL;
  1560.  
  1561.     if( gptr->dname )
  1562.     free( gptr->dname );
  1563.     gptr->dname = NULL;
  1564.  
  1565.     if( gptr->fname )
  1566.     free( gptr->fname );
  1567.     gptr->fname = NULL;
  1568.  
  1569.     /* Connect it to free list */
  1570.  
  1571.     gptr->next = gameavail;
  1572.     gameavail = gptr;
  1573. }
  1574.  
  1575. struct DiskObject *AllocDObj( str )
  1576.     register char *str;
  1577. {
  1578.     register struct DiskObject *doptr;
  1579.     register char *t, *t1;
  1580.  
  1581.     if( ( t = strrchr( str, '.' ) ) && stricmp( t, ".info" ) == 0 )
  1582.     {
  1583.     *t = 0;
  1584.     }
  1585.     else
  1586.     {
  1587.     t = NULL;
  1588.     }
  1589.  
  1590.     if( doptr = GetDiskObject( str ) )
  1591.     {
  1592.     struct IntuiText *ip;
  1593.  
  1594.     diskobj_filter(doptr);  /* delete INTERNALCLI */
  1595.  
  1596.     if( ip = xmalloc( sizeof( struct IntuiText ) ) )
  1597.     {
  1598.         memset( ip, 0, sizeof( struct IntuiText ) );
  1599.         ip->FrontPen = C_BLACK;
  1600.         ip->DrawMode = JAM1;
  1601.         ip->LeftEdge = (doptr->do_Gadget.Width -
  1602.         ( strlen( str ) * win->RPort->TxWidth ))/2;
  1603.         ip->TopEdge = doptr->do_Gadget.Height;
  1604.         ip->IText = strdup( str );
  1605.         doptr->do_Gadget.GadgetText = ip;
  1606.  
  1607.         /* Trim any .sav off of the end. */
  1608.  
  1609.         if( ( t1 = strrchr( ip->IText, '.' ) ) &&
  1610.             stricmp( t1, ".sav" ) == 0 )
  1611.         {
  1612.         *t1 = 0;
  1613.         ip->LeftEdge += (2 * win->RPort->TxWidth);
  1614.         }
  1615.     }
  1616.     }
  1617.     if( t ) *t = '.';
  1618.  
  1619.     return( doptr );
  1620. }
  1621.  
  1622. void LoadIcons( )
  1623. {
  1624.     register GPTR gptr, newgame;
  1625.     register BPTR savedir;
  1626.     register char *t;
  1627.     register struct FileInfoBlock *finfo;
  1628.     char buf[ 200 ];
  1629.  
  1630.     /* Check if we can access the new save directory */
  1631.  
  1632.     if( ( savedir = Lock( options[ SAVE_IDX ], ACCESS_READ ) ) == NULL )
  1633.     {
  1634.     errmsg( FLASH,
  1635.         "Can't access save directory: %s", options[ SAVE_IDX ] );
  1636.     return;
  1637.     }
  1638.  
  1639.     if( ( finfo = (struct FileInfoBlock *)
  1640.             xmalloc( sizeof( struct FileInfoBlock ) ) ) == NULL )
  1641.     {
  1642.     UnLock( savedir );
  1643.     errmsg( FLASH, "Can't alloc memory" );
  1644.     return;
  1645.     }
  1646.  
  1647.     if( newgame = gamehead )
  1648.     gamehead = gamehead->next;
  1649.  
  1650.     if( !Examine( savedir, finfo ) )
  1651.     {
  1652.     UnLock( savedir );
  1653.     free( finfo );
  1654.     errmsg( FLASH, "Can't Examine save directory" );
  1655.     return;
  1656.     }
  1657.  
  1658.     /* Collect all of the entries */
  1659.  
  1660.     while( ExNext( savedir, finfo ) )
  1661.     {
  1662.     /* If already got this game, continue */
  1663.  
  1664.     if( gptr = FindGame( finfo->fib_FileName ) )
  1665.         continue;
  1666.  
  1667.     /* Get just the ones we are interested in */
  1668.  
  1669.     if( ( t = strrchr( finfo->fib_FileName, '.' ) ) == NULL ||
  1670.             stricmp( t, ".info" ) != 0 )
  1671.         continue;
  1672.  
  1673.     if( t == finfo->fib_FileName )
  1674.         continue;
  1675.  
  1676.     /* Get a gadget item */
  1677.  
  1678.     if( gptr = GetWBIcon( savedir, options[ SAVE_IDX ], finfo ) )
  1679.     {
  1680.         gptr->next = gamehead;
  1681.         gamehead = gptr;
  1682.     }
  1683.     }
  1684.  
  1685.     /* Get the NewGame gadget */
  1686.  
  1687.     UnLock( savedir );
  1688.     if( newgame == NULL )
  1689.     {
  1690.     /* Pick up the new game if not there yet. */
  1691.  
  1692.     sprintf( buf, "%sNewGame.info", options[ HACKDIR_IDX ] );
  1693.     if( savedir = Lock( buf, ACCESS_READ ) )
  1694.     {
  1695.         if( Examine( savedir, finfo ) )
  1696.         {
  1697.         UnLock( savedir );
  1698.         savedir = Lock( options[ HACKDIR_IDX ], ACCESS_READ );
  1699.         if( gptr = GetWBIcon( savedir,
  1700.             options[ HACKDIR_IDX ], finfo ) )
  1701.         {
  1702.             gptr->next = gamehead;
  1703.             gamehead = gptr;
  1704.         }
  1705.         }
  1706.         UnLock( savedir );
  1707.         free( finfo );
  1708.     }
  1709.     else
  1710.     {
  1711.         errmsg( FLASH, "No access to %s", buf );
  1712.     }
  1713.     }
  1714.     else
  1715.     {
  1716.     newgame->next = gamehead;
  1717.     gamehead = newgame;
  1718.     }
  1719. }
  1720.  
  1721. void menu_recover()
  1722. {
  1723.     int execit = 1;
  1724.     long class, code;
  1725.     struct Gadget *gd, *lastact = 0;
  1726.     int done = 0;
  1727.     struct IntuiMessage *imsg;
  1728.     struct Window *w;
  1729.     static int once = 0;
  1730.     int txtdiff = scrn->RastPort.TxHeight - 8;
  1731.     struct IntuiText *ip;
  1732.  
  1733.     if( !once )
  1734.     {
  1735.     for( gd = Rst_NewWindowStructure12.FirstGadget;
  1736.             gd; gd = gd->NextGadget )
  1737.     {
  1738.         switch( gd->GadgetID )
  1739.         {
  1740.         case GADRESTDIR:
  1741.             gd->TopEdge += txtdiff;
  1742.             gd->Height += txtdiff;
  1743.             SetBorder( gd, -1 );
  1744.             strcpy(RstDir,options[LEVELS_IDX]);
  1745.             break;
  1746.         case GADRESTOLD:
  1747.             gd->TopEdge += txtdiff*2;
  1748.             gd->Height += txtdiff;
  1749.             SetBorder( gd, -1 );
  1750.             strcpy(RstOld,"levels");
  1751.             break;
  1752.         case GADRESTNEW:
  1753.             gd->TopEdge += txtdiff*3;
  1754.             gd->Height += txtdiff;
  1755.             SetBorder( gd, -1 );
  1756.             break;
  1757.         case GADRESTOKAY:
  1758.             gd->TopEdge += txtdiff*4;
  1759.             gd->Height += txtdiff;
  1760.             SetBorder( gd, -1 );
  1761.             break;
  1762.         case GADRESTCAN:
  1763.             gd->TopEdge += txtdiff*4;
  1764.             gd->Height += txtdiff;
  1765.             SetBorder( gd, -1 );
  1766.             break;
  1767.         }
  1768.     }
  1769.     Rst_NewWindowStructure12.Height += txtdiff*5;
  1770.     for( ip = &Rst_IntuiTextList12; ip; ip = ip->NextText )
  1771.     {
  1772.         if( *ip->IText == 'O' )
  1773.         ip->TopEdge += txtdiff;
  1774.         else if( *ip->IText == 'N' )
  1775.         ip->TopEdge += txtdiff*2;
  1776.     }
  1777.     once = 1;
  1778.     }
  1779.  
  1780.     Rst_NewWindowStructure12.Screen = scrn;
  1781.     if( ( w = MyOpenWindow( &Rst_NewWindowStructure12 ) ) == NULL )
  1782.     {
  1783.     errmsg( FLASH, "Can't create requester window" );
  1784.     return;
  1785.     }
  1786.     PrintIText( w->RPort, &Rst_IntuiTextList12, 0, txtdiff );
  1787.     lastact = FindGadget( w, NULL, GADRESTDIR );
  1788.  
  1789.     while( !done )
  1790.     {
  1791.     WaitPort( w->UserPort );
  1792.     while( imsg = (struct IntuiMessage *) GetMsg( w->UserPort ) )
  1793.     {
  1794.         class = imsg->Class;
  1795.         code = imsg->Code;
  1796.         gd = (struct Gadget *)imsg->IAddress;
  1797.         ReplyMsg( (struct Message *) imsg );
  1798.         switch( class )
  1799.         {
  1800.         case CLOSEWINDOW:
  1801.             done = 1;
  1802.             execit = 0;
  1803.             break;
  1804.  
  1805.         case ACTIVEWINDOW:
  1806.             ActivateGadget( lastact, w, NULL );
  1807.             break;
  1808.  
  1809.         case GADGETUP:
  1810.             if( gd->GadgetID == GADRESTOKAY )
  1811.             done = 1;
  1812.             else if( gd->GadgetID == GADRESTCAN )
  1813.             {
  1814.             execit = 0;
  1815.             done = 1;
  1816.             }
  1817.             else if( gd->GadgetID == GADRESTDIR )
  1818.             {
  1819.             if( gd = FindGadget( w, NULL, GADRESTOLD ) )
  1820.                 ActivateGadget( lastact = gd, w, NULL );
  1821.             }
  1822.             else if( gd->GadgetID == GADRESTOLD )
  1823.             {
  1824.             if( gd = FindGadget( w, NULL, GADRESTNEW ) )
  1825.                 ActivateGadget( lastact = gd, w, NULL );
  1826.             }
  1827.             break;
  1828.  
  1829.         case VANILLAKEY:
  1830.             if( code == '\33' )
  1831.             {
  1832.             done = 1;
  1833.             execit = 0;
  1834.             }
  1835.             break;
  1836.         }
  1837.     }
  1838.     }
  1839.  
  1840.     SafeCloseWindow( w );
  1841.  
  1842.     if( execit )
  1843.     {
  1844.     char buf[255];
  1845.     sprintf( buf, "stack 65000\nNetHack:Recover -d %s %s", RstDir, RstOld );
  1846.     Execute( buf, NULL, NULL );
  1847.     MapGadgets( R_DISK, 1);
  1848.     }
  1849. }
  1850.  
  1851. void menu_config()
  1852. {
  1853.     register struct Window *cwin;
  1854.     int done = 0, quit;
  1855.     long class, code, qual;
  1856.     register struct IntuiMessage *imsg;
  1857.     struct IntuiText *ip;
  1858.     register struct Gadget *gd;
  1859.     static int once = 0;
  1860.     int txtdiff = scrn->RastPort.TxHeight - 8;
  1861.  
  1862.     strcpy( StrPath, options[ PATH_IDX ] );
  1863.     strcpy( StrHackdir, options[ HACKDIR_IDX ] );
  1864.     strcpy( StrPens, options[ PENS_IDX ] );
  1865.     strcpy( StrLevels, options[ LEVELS_IDX ] );
  1866.     strcpy( StrSave, options[ SAVE_IDX ] );
  1867.  
  1868.     if( !once )
  1869.     {
  1870.     for( gd = Conf_NewWindowStructure4.FirstGadget;
  1871.             gd; gd = gd->NextGadget )
  1872.     {
  1873.         switch( gd->GadgetID )
  1874.         {
  1875.         case GADSTRPATH:
  1876.             /* Look for "Path:" string */
  1877.             for( ip = &Conf_IntuiTextList4;
  1878.                 ip && *ip->IText != 'P'; )
  1879.             ip = ip->NextText;
  1880.             gd->TopEdge += txtdiff;
  1881.             gd->Height += txtdiff;
  1882.             SetBorder( gd, -1 );
  1883.             break;
  1884.         case GADSTRHACKDIR:
  1885.             /* Look for "Hackdir:" string */
  1886.             for( ip = &Conf_IntuiTextList4;
  1887.                 ip && *ip->IText != 'H'; )
  1888.             ip = ip->NextText;
  1889.             if( ip )
  1890.             ip->TopEdge += txtdiff;
  1891.             gd->TopEdge += txtdiff*2;
  1892.             gd->Height += txtdiff;
  1893.             SetBorder( gd, -1 );
  1894.             break;
  1895.         case GADSTRPENS:
  1896.             /* Look for "Pens:" string */
  1897.             for( ip = &Conf_IntuiTextList4; ip &&
  1898.             !(*ip->IText == 'P' && ip->IText[1] == 'e'); )
  1899.             {
  1900.             ip = ip->NextText;
  1901.             }
  1902.             if( ip )
  1903.             ip->TopEdge += txtdiff*2;
  1904.             gd->TopEdge += txtdiff*3;
  1905.             gd->Height += txtdiff;
  1906.             SetBorder( gd, -1 );
  1907.             break;
  1908.         case GADSTRLEVELS:
  1909.             /* Look for "Levels:" string */
  1910.             for( ip = &Conf_IntuiTextList4; ip && *ip->IText != 'L'; )
  1911.             ip = ip->NextText;
  1912.             if( ip )
  1913.             ip->TopEdge += txtdiff*3;
  1914.             gd->TopEdge += txtdiff*4;
  1915.             gd->Height += txtdiff;
  1916.             SetBorder( gd, -1 );
  1917.             break;
  1918.         case GADSTRSAVE:
  1919.             /* Look for "Save Dir:" string */
  1920.             for( ip = &Conf_IntuiTextList4; ip && *ip->IText != 'S'; )
  1921.             ip = ip->NextText;
  1922.             if( ip )
  1923.             ip->TopEdge += txtdiff*4;
  1924.             gd->TopEdge += txtdiff*5;
  1925.             gd->Height += txtdiff;
  1926.             SetBorder( gd, -1 );
  1927.             break;
  1928.         case GADCONFLOAD:
  1929.         case GADCONFSAVE:
  1930.             gd->TopEdge += txtdiff*6;
  1931.             gd->Height += txtdiff;
  1932.             SetBorder( gd, -1 );
  1933.             break;
  1934.         case GADCONFNAME:
  1935.             for( ip = &Conf_IntuiTextList4; ip && *ip->IText != 'C'; )
  1936.             ip = ip->NextText;
  1937.             if( ip )
  1938.             ip->TopEdge += txtdiff*6;
  1939.             gd->TopEdge += txtdiff*7;
  1940.             gd->Height += txtdiff;
  1941.             SetBorder( gd, -1 );
  1942.             break;
  1943.  
  1944.         default:
  1945.             break;
  1946.         }
  1947.     }
  1948.     Conf_NewWindowStructure4.Height += txtdiff*8;
  1949.     if( Conf_NewWindowStructure4.TopEdge +
  1950.         Conf_NewWindowStructure4.Height > scrn->Height )
  1951.     {
  1952.         Conf_NewWindowStructure4.TopEdge -=
  1953.         ( Conf_NewWindowStructure4.TopEdge +
  1954.         Conf_NewWindowStructure4.Height ) - scrn->Height + 1;
  1955.         if( Conf_NewWindowStructure4.TopEdge < 0 )
  1956.         {
  1957.         Conf_NewWindowStructure4.TopEdge = 0;
  1958.         Conf_NewWindowStructure4.Height = scrn->Height - 1;
  1959.         }
  1960.     }
  1961.     once = 1;
  1962.     }
  1963.  
  1964.     Conf_NewWindowStructure4.Screen = scrn;
  1965.     if( ( cwin = MyOpenWindow( &Conf_NewWindowStructure4 ) ) == NULL )
  1966.     {
  1967.     errmsg( FLASH, "Can't create requester window" );
  1968.     return;
  1969.     }
  1970.  
  1971.     PrintIText( cwin->RPort, &Conf_IntuiTextList4, 0, txtdiff );
  1972.     while( !done )
  1973.     {
  1974.     WaitPort( cwin->UserPort );
  1975.     while( ( imsg = (void *) GetMsg( cwin->UserPort ) ) != NULL )
  1976.     {
  1977.         class = imsg->Class;
  1978.         code = imsg->Code;
  1979.         qual = imsg->Qualifier;
  1980.         gd = (struct Gadget *)imsg->IAddress;
  1981.  
  1982.         ReplyMsg( (struct Message *)imsg );
  1983.  
  1984.         switch( class )
  1985.         {
  1986.         case VANILLAKEY:
  1987.             if( code == '\33' || (code == 'b' && (qual&AMIGALEFT)))
  1988.             {
  1989.             done = 0;
  1990.             quit = 1;
  1991.             }
  1992.             break;
  1993.  
  1994.         case ACTIVEWINDOW:
  1995.             if( gd = FindGadget( cwin, NULL, GADCONFNAME ) )
  1996.             ActivateGadget( gd, cwin, NULL );
  1997.             break;
  1998.  
  1999.         case CLOSEWINDOW:
  2000.             done = 1;
  2001.             quit = 0;
  2002.             break;
  2003.  
  2004.         case GADGETUP:
  2005.             switch( gd->GadgetID )
  2006.             {
  2007.             case GADSTRPATH:
  2008.                 if( gd = FindGadget( cwin, NULL,GADSTRHACKDIR) )
  2009.                 ActivateGadget( gd, cwin, NULL );
  2010.                 break;
  2011.             case GADSTRHACKDIR:
  2012.                 if( gd = FindGadget( cwin, NULL,GADSTRPENS) )
  2013.                 ActivateGadget( gd, cwin, NULL );
  2014.                 break;
  2015.             case GADSTRPENS:
  2016.                 if( gd = FindGadget( cwin, NULL,GADSTRLEVELS) )
  2017.                 ActivateGadget( gd, cwin, NULL );
  2018.                 break;
  2019.             case GADSTRLEVELS:
  2020.                 if( gd = FindGadget( cwin, NULL, GADSTRSAVE ) )
  2021.                 ActivateGadget( gd, cwin, NULL );
  2022.                 break;
  2023.             case GADSTRSAVE:
  2024.                 if( gd = FindGadget( cwin, NULL, GADCONFNAME ) )
  2025.                 ActivateGadget( gd, cwin, NULL );
  2026.                 break;
  2027.  
  2028.             case GADCONFLOAD: case GADCONFNAME:
  2029.                 ReadConfig( );
  2030.                 strcpy( StrPath, options[ PATH_IDX ] );
  2031.                 strcpy( StrHackdir, options[ HACKDIR_IDX ] );
  2032.                 strcpy( StrPens, options[ PENS_IDX ] );
  2033.                 strcpy( StrLevels, options[ LEVELS_IDX ] );
  2034.                 strcpy( StrSave, options[ SAVE_IDX ] );
  2035.                 RefreshGList( cwin->FirstGadget, cwin, NULL, -1 );
  2036.                 break;
  2037.  
  2038.             case GADCONFSAVE:
  2039.                 errmsg( FLASH, "Save not implemented" );
  2040.                 break;
  2041.  
  2042.             default:
  2043.                 break;
  2044.             }
  2045.             break;
  2046.         }
  2047.     }
  2048.     }
  2049.  
  2050.     setoneopt( PATH_IDX, StrPath );
  2051.     PutOptions( curopts );
  2052.     setoneopt( HACKDIR_IDX, StrHackdir );
  2053.     setoneopt( PENS_IDX, StrPens );
  2054.     setoneopt( LEVELS_IDX, StrLevels );
  2055.     setoneopt( SAVE_IDX, StrSave );
  2056.  
  2057.     SafeCloseWindow( cwin );
  2058.  
  2059.     /* Display icons in possibly new save directory */
  2060.  
  2061.     MapGadgets( R_DISK, 1 );
  2062. }
  2063.  
  2064. void menu_editdef( gametype )
  2065.     int gametype;
  2066. {
  2067.     register struct Window *cwin;
  2068.     int done = 0;
  2069.     USHORT mcode;
  2070.     long class, qual, code;
  2071.     register struct IntuiMessage *imsg;
  2072.     register struct Gadget *gd;
  2073.     char buf[ 100 ];
  2074.     struct IntuiText *ip;
  2075.     static int once = 0;
  2076.     int txtdiff = scrn->RastPort.TxHeight - 8;
  2077.     register GPTR gptr;
  2078.  
  2079.     /* If gametype indicates an INFO request... */
  2080.     if( gametype == GAME_FROM_INFO )
  2081.     {
  2082.     register char *t;
  2083.  
  2084.     if( ( gptr = NeedGame() ) == NULL )
  2085.     {
  2086.         errmsg( FLASH, "No Game selected to edit options for" );
  2087.         return;
  2088.     }
  2089.  
  2090.     strcpy( DefOutFile, gptr->name );
  2091.     if( ( t = strrchr( DefOutFile, '.' ) ) &&
  2092.         stricmp( t, ".sav" ) == 0 )
  2093.     {
  2094.         *t = 0;
  2095.     }
  2096.     LoadDefaults( DefOutFile );
  2097.     }
  2098.     else /* if( gametype == GAME_FROM_DEFAULT ) */
  2099.     {
  2100.     /* Find the newgame gadget... */
  2101.  
  2102.     for( gptr = windowgads; gptr; gptr = gptr->nextwgad )
  2103.     {
  2104.         if( gptr->dobj->do_Gadget.GadgetID == GADNEWGAME )
  2105.         break;
  2106.     }
  2107.  
  2108.     if( !gptr )
  2109.     {
  2110.         errmsg( FLASH, "Can't find NewGame information" );
  2111.         return;
  2112.     }
  2113.  
  2114.     strcpy( DefOutFile, defgname );
  2115.     LoadDefaults( DefOutFile );
  2116.     }
  2117.  
  2118.     /* Copy the defgame.* date into the Defs_ window gadgets */
  2119.     CopyDefs2Gad();
  2120.  
  2121.     /* Do one time window setup and initialization */
  2122.  
  2123.     if( !once )
  2124.     {
  2125.     /* Rearrange the gadgets based on fonts text height */
  2126.  
  2127.     for( gd = Defs_NewWindowStructure11.FirstGadget;
  2128.         gd; gd = gd->NextGadget )
  2129.     {
  2130.         if( gd->GadgetID != 0 )
  2131.         {
  2132.         gd->TopEdge += txtdiff;
  2133.         gd->Height += txtdiff;
  2134.         switch( gd->GadgetID )
  2135.         {
  2136.             case GADOUTFILE:
  2137.             gd->TopEdge += txtdiff;
  2138.             break;
  2139.             case GADDEFLOAD:
  2140.             case GADDEFSAVE:
  2141.             case GADEDOPTIONS:
  2142.             gd->TopEdge += txtdiff * 3;
  2143.             break;
  2144.             default:
  2145.             if( ( gd->Flags & GADGHIGHBITS ) == GADGHNONE )
  2146.                 gd->TopEdge += txtdiff * 2;
  2147.             break;
  2148.         }
  2149.         SetBorder( gd, -1 );
  2150.         }
  2151.     }
  2152.  
  2153.     /* Move the text down as appropriate */
  2154.  
  2155.     for( ip = &Defs_IntuiTextList11; ip; ip = ip->NextText )
  2156.     {
  2157.         if( *ip->IText == 'C' )
  2158.         ip->TopEdge += txtdiff * 2;
  2159.         else if( *ip->IText == 'O' )
  2160.         ip->TopEdge += txtdiff;
  2161.     }
  2162.  
  2163.     /* Adjust the height of the window */
  2164.     Defs_NewWindowStructure11.Height += txtdiff * 5;
  2165.     ++once;
  2166.     }
  2167.  
  2168.     Defs_NewWindowStructure11.Screen = scrn;
  2169.  
  2170.     /* Set Correct title */
  2171.     if( gametype == GAME_FROM_DEFAULT )
  2172.     Defs_NewWindowStructure11.Title = "Edit Default Game Definition";
  2173.     else if( gametype == GAME_FROM_INFO )
  2174.     Defs_NewWindowStructure11.Title = "Edit Game Definition";
  2175.     else
  2176.     {
  2177.     errmsg( FLASH, "Can't edit game of type %d", gametype );
  2178.     return;
  2179.     }
  2180.  
  2181.     if( ( cwin = MyOpenWindow( &Defs_NewWindowStructure11 ) ) == NULL )
  2182.     {
  2183.     errmsg( FLASH, "Can't create requester window" );
  2184.     return;
  2185.     }
  2186.  
  2187.     PrintIText( cwin->RPort, &Defs_IntuiTextList11, 0, txtdiff );
  2188.     UpdateTypes( cwin );
  2189.  
  2190.     /* Do Menu Layouts Based on FontHeight */
  2191.     SetUpMenus( &Defs_MenuList11, scrn );
  2192.     SetMenuStrip( cwin, &Defs_MenuList11 );
  2193.  
  2194.     /* Process messages */
  2195.     while( !done )
  2196.     {
  2197.     WaitPort( cwin->UserPort );
  2198.     while( ( imsg = (void *) GetMsg( cwin->UserPort ) ) != NULL )
  2199.     {
  2200.         mcode = imsg->Code;
  2201.         gd = (struct Gadget *)imsg->IAddress;
  2202.         qual = imsg->Qualifier;
  2203.         class = imsg->Class;
  2204.         code = imsg->Code;
  2205.  
  2206.         ReplyMsg( (struct Message *)imsg );
  2207.  
  2208.         switch( class )
  2209.         {
  2210.         case VANILLAKEY:
  2211.             /* Escape or LEFT_AMIGA-b aborts the requester... */
  2212.             if( code == '\33' || (code == 'b' && (qual&AMIGALEFT)))
  2213.             {
  2214.             done = 1;
  2215.             }
  2216.             break;
  2217.  
  2218.         case ACTIVEWINDOW:
  2219.             if( gd = FindGadget( cwin, NULL, GADCHARNAME ) )
  2220.             ActivateGadget( gd, cwin, NULL );
  2221.             break;
  2222.  
  2223.         case MENUPICK:
  2224.             while( mcode != MENUNULL )
  2225.             {
  2226.             switch(MENUNUM(mcode))
  2227.             {
  2228.                 case PLAYERMENU:
  2229.                 defgame.pltype = ITEMNUM( mcode );
  2230.                 UpdateTypes( cwin );
  2231.                 break;
  2232.             }
  2233.             mcode = ((struct MenuItem *)
  2234.                 ItemAddress( &Defs_MenuList11,
  2235.                 mcode))->NextSelect;
  2236.             }
  2237.             break;
  2238.  
  2239.         case CLOSEWINDOW:
  2240.             CopyGad2Defs( );
  2241.             done = 1;
  2242.             break;
  2243.  
  2244.         case GADGETUP:
  2245.             switch( gd->GadgetID )
  2246.             {
  2247.             case GADEDOPTIONS:
  2248.                 CopyOptions( curopts, gptr );
  2249.                 if( EditOptions( curopts ) )
  2250.                 SetOptions( curopts, gptr );
  2251.                 break;
  2252.  
  2253.             case GADDEFSAVE:
  2254.                 CopyGad2Defs( );
  2255.                 sprintf( buf,
  2256.                 "Game definition saved in: %s", DefOutFile );
  2257.                 errmsg( NO_FLASH, buf );
  2258.                 SaveDefaults( DefOutFile );
  2259.                 break;
  2260.  
  2261.             case GADDEFLOAD:
  2262.                 LoadDefaults( DefPlayerName );
  2263.                 strcpy( DefOutFile, DefPlayerName );
  2264.                 CopyDefs2Gad();
  2265.                 UpdateTypes( cwin );
  2266.                 sprintf( buf, "Game definition loaded from: %s",
  2267.                 DefPlayerName );
  2268.                 errmsg( NO_FLASH, buf );
  2269.                 break;
  2270.  
  2271.             default:
  2272.                 break;
  2273.             }
  2274.             break;
  2275.         }
  2276.     }
  2277.     }
  2278.  
  2279.     SafeCloseWindow( cwin );
  2280. }
  2281.  
  2282. void do_gadgetup( imsg )
  2283.     register struct IntuiMessage *imsg;
  2284. {
  2285.     register struct Gadget *gd;
  2286.     register unsigned long hid;
  2287.     int ncol, pot;
  2288.  
  2289.     gd = (struct Gadget *) imsg->IAddress;
  2290.  
  2291.     switch( gd->GadgetID )
  2292.     {
  2293.     case GADSCROLL:
  2294.         hid = max( cols - vcols, 0 );
  2295.         pot = ( ( struct PropInfo * ) gd->SpecialInfo )->HorizPot;
  2296.         ncol = (hid * pot) / MAXPOT;
  2297.         if( ncol != curcol )
  2298.         {
  2299.         curcol = ncol;
  2300.         MapGadgets( R_SCROLL, 0 ); /* redisplay the icons */
  2301.         }
  2302.         break;
  2303.     }
  2304. }
  2305.  
  2306. void do_buttons( imsg )
  2307.     register struct IntuiMessage *imsg;
  2308. {
  2309.     if( imsg->Code == SELECTDOWN || imsg->Code == SELECTUP )
  2310.     {
  2311.     if( lastgaddown )
  2312.     {
  2313.         SetGadgetUP( &lastgaddown->dobj->do_Gadget );
  2314.         lastgaddown->secs = 0;
  2315.         lastgaddown->mics = 0;
  2316.     }
  2317.     lastgaddown = NULL;
  2318.     ChgGameItems( &MenuList1, 0 );
  2319.     }
  2320. }
  2321.  
  2322. void do_gadgetdown( imsg )
  2323.     register struct IntuiMessage *imsg;
  2324. {
  2325.     register GPTR gptr;
  2326.     register struct Gadget *gd;
  2327.  
  2328.     gd = (struct Gadget *) imsg->IAddress;
  2329.  
  2330.     /* Don't do anything for these gadgets */
  2331.  
  2332.     if( gd->GadgetID < GADNEWGAME )
  2333.     {
  2334.     return;
  2335.     }
  2336.  
  2337.     /* Check just to make sure we got it */
  2338.  
  2339.     for( gptr = windowgads; gptr &&
  2340.     gptr->dobj->do_Gadget.GadgetID != gd->GadgetID; )
  2341.     {
  2342.     gptr = gptr->nextwgad;
  2343.     }
  2344.  
  2345.     if( !gptr )
  2346.     {
  2347.     errmsg( FLASH, "Bad GadgetID for GadgetDOWN" );
  2348.     return;
  2349.     }
  2350.  
  2351.     /* Fix the gadget images */
  2352.  
  2353.     if( lastgaddown && &lastgaddown->dobj->do_Gadget != gd )
  2354.     {
  2355.     SetGadgetUP( &lastgaddown->dobj->do_Gadget );
  2356.     gptr->secs = 0;
  2357.     gptr->mics = 0;
  2358.     }
  2359.     SetGadgetDOWN( &((lastgaddown = gptr)->dobj->do_Gadget) );
  2360.  
  2361.     /* Only allow game gadgets to be manipulated */
  2362.  
  2363.     if( lastgaddown->dobj->do_Gadget.GadgetID == GADNEWGAME )
  2364.     ChgNewGameItems( &MenuList1, 1 );
  2365.     else
  2366.     ChgGameItems( &MenuList1, 1 );
  2367.  
  2368.     /* Check if this gadget has been double clicked */
  2369.  
  2370.     if( DoubleClick( gptr->secs, gptr->mics, imsg->Seconds, imsg->Micros ) )
  2371.     {
  2372.     run_game( gptr );
  2373.     gptr->secs = 0;
  2374.     gptr->mics = 0;
  2375.     return;
  2376.     }
  2377.  
  2378.     gptr->secs = imsg->Seconds;
  2379.     gptr->mics = imsg->Micros;
  2380. }
  2381.  
  2382. void menu_setopt()
  2383. {
  2384.     register GPTR gptr;
  2385.  
  2386.     if( ( gptr = NeedGame() ) == NULL )
  2387.     return;
  2388.     CopyOptions( curopts, gptr );
  2389.     if( EditOptions( curopts ) )
  2390.     SetOptions( curopts, gptr );
  2391. }
  2392.  
  2393. void menu_info()
  2394. {
  2395.     register struct IntuiMessage *imsg;
  2396.     struct IntuiText *ip;
  2397.     char *t;
  2398.     register GPTR gptr;
  2399.     register struct Gadget *gd;
  2400.     register struct FileInfoBlock *finfo;
  2401.     register struct Window *cwin;
  2402.     register int i;
  2403.     int done = 0, quit;
  2404.     char **sp;
  2405.     static int once = 0;
  2406.     register BPTR lock;
  2407.     long code, class, qual;
  2408.     static struct IntuiText itext[ 4 ];
  2409.     char commentstr[ 100 ], namestr[ 50 ];
  2410.     int txtdiff = scrn->RastPort.TxHeight - 8;
  2411.  
  2412.     if( ( gptr = NeedGame() ) == NULL )
  2413.     return;
  2414.  
  2415.     if( ( lock = Lock( GameName( gptr, NULL ), ACCESS_READ ) ) == NULL )
  2416.     {
  2417.     /* Can't get lock, reload and return */
  2418.  
  2419.     errmsg( FLASH, "Can't Lock game save file: %s",
  2420.         GameName( gptr, NULL ) );
  2421.     MapGadgets( R_DISK, 1 );
  2422.     return;
  2423.     }
  2424.  
  2425.     finfo = (struct FileInfoBlock *)xmalloc(sizeof(struct FileInfoBlock));
  2426.     Examine( lock, finfo );
  2427.     UnLock( lock );
  2428.     strncpy( commentstr, finfo->fib_Comment, sizeof( finfo->fib_Comment ) );
  2429.     commentstr[ sizeof( finfo->fib_Comment ) ] = 0;
  2430.     free( finfo );
  2431.  
  2432.     for( i = 0; i < 4; ++i )
  2433.     {
  2434.     itext[ i ].FrontPen = C_BLACK;
  2435.     itext[ i ].BackPen = C_GREY;
  2436.     itext[ i ].DrawMode = JAM2;
  2437.     itext[ i ].TopEdge = 2;
  2438.     itext[ i ].LeftEdge = 4;
  2439.     }
  2440.     ReallocTools( gptr, 0 );
  2441.     sp = gptr->dobj->do_ToolTypes;
  2442.  
  2443.     if( !once )
  2444.     {
  2445.     Info_Comment.TopEdge += txtdiff*2;
  2446.     Info_Class.TopEdge += txtdiff;
  2447.     Info_NewWindowStructure6.Height += txtdiff * 6;
  2448.     for( gd = Info_NewWindowStructure6.FirstGadget;
  2449.         gd; gd = gd->NextGadget )
  2450.     {
  2451.         gd->TopEdge += txtdiff;
  2452.         if( gd->GadgetID != GADTOOLUP && gd->GadgetID != GADTOOLDOWN )
  2453.         gd->Height += txtdiff;
  2454.         switch( gd->GadgetID )
  2455.         {
  2456.         case 0:
  2457.             break;
  2458.  
  2459.         case GADTOOLTYPES:
  2460.             gd->TopEdge += txtdiff*4;
  2461.             SetBorder( gd, -1 );
  2462.             break;
  2463.  
  2464.         case GADDELTOOL:
  2465.             gd->TopEdge += txtdiff*3;
  2466.             SetBorder( gd, -1 );
  2467.             break;
  2468.  
  2469.         case GADADDTOOL:
  2470.             gd->TopEdge += txtdiff*3;
  2471.             SetBorder( gd, -1 );
  2472.             break;
  2473.  
  2474.         case GADTOOLUP:
  2475.             gd->TopEdge += txtdiff*4;
  2476.             gd->Flags &= ~GADGHIGHBITS;
  2477.             gd->Flags |= GADGIMAGE|GADGHIMAGE;
  2478.             gd->GadgetRender = (APTR)&up_selectimage;
  2479.             gd->SelectRender = (APTR)&up_renderimage;
  2480.             break;
  2481.  
  2482.         case GADTOOLDOWN:
  2483.             gd->TopEdge += txtdiff*5;
  2484.             gd->Flags &= ~GADGHIGHBITS;
  2485.             gd->Flags |= GADGIMAGE|GADGHIMAGE;
  2486.             gd->GadgetRender = (APTR)&down_selectimage;
  2487.             gd->SelectRender = (APTR)&down_renderimage;
  2488.             break;
  2489.  
  2490.         default:
  2491.             SetBorder( gd, -1 );
  2492.         }
  2493.     }
  2494.     for( ip = &Info_IntuiTextList6; ip; ip = ip->NextText )
  2495.     {
  2496.         if( *ip->IText == 'C' )
  2497.         {
  2498.         if( ip->IText[1] == 'o' )
  2499.             ip->TopEdge += 2*txtdiff;
  2500.         else
  2501.             ip->TopEdge += txtdiff;
  2502.         }
  2503.         else if( *ip->IText == 'T' )
  2504.         ip->TopEdge += 4*txtdiff;
  2505.     }
  2506.     ++once;
  2507.     }
  2508.  
  2509.     gd = &Info_EditDef;
  2510.     if( access( GameName( gptr, gptr->name ), 1 ) == 0 )
  2511.     gd->Flags |= GADGDISABLED;
  2512.     else
  2513.     gd->Flags &= ~GADGDISABLED;
  2514.  
  2515.     /* Put in the comment */
  2516.  
  2517.     Info_Comment.GadgetText = &itext[ 0 ];
  2518.     itext[ 0 ].IText = commentstr;
  2519.  
  2520.     /* The players name */
  2521.  
  2522.     Info_Player.GadgetText = &itext[ 1 ];
  2523.     strncpy( namestr, ToolsEntry( gptr, "NAME" ), sizeof( namestr ) );
  2524.     namestr[ sizeof( namestr ) - 1 ] = 0;
  2525.     if( *namestr == 0 )
  2526.     {
  2527.     strncpy( namestr, gptr->name, sizeof( namestr ) );
  2528.     namestr[ sizeof( namestr ) - 1 ] = 0;
  2529.     }
  2530.     if( ( t = strrchr( namestr, '.' ) ) && stricmp( t, ".sav" ) == 0 )
  2531.     *t = 0;
  2532.     itext[ 1 ].IText = namestr;
  2533.  
  2534.     /* The character class of the player */
  2535.  
  2536.     Info_Class.GadgetText = &itext[ 2 ];
  2537.     itext[ 2 ].IText = ToolsEntry( gptr, "CHARACTER" );
  2538.  
  2539.     /* If there are ToolTypes entries, put the first one into the gadget */
  2540.  
  2541.     if( sp && *sp )
  2542.     strcpy( StrTools, *sp );
  2543.  
  2544.     if( IsEditEntry( StrTools, gptr ) )
  2545.     Info_ToolTypes.Flags &= ~GADGDISABLED;
  2546.     else
  2547.     Info_ToolTypes.Flags |= GADGDISABLED;
  2548.  
  2549.     Info_NewWindowStructure6.Screen = scrn;
  2550.     if( ( cwin = MyOpenWindow( &Info_NewWindowStructure6 ) ) == NULL )
  2551.     {
  2552.     errmsg( FLASH, "Can't create info window" );
  2553.     return;
  2554.     }
  2555.     PrintIText( cwin->RPort, &Info_IntuiTextList6, 0, txtdiff );
  2556.  
  2557.     while( !done )
  2558.     {
  2559.     WaitPort( cwin->UserPort );
  2560.     while( ( imsg = (void *) GetMsg( cwin->UserPort ) ) != NULL )
  2561.     {
  2562.         class = imsg->Class;
  2563.         code = imsg->Code;
  2564.         qual = imsg->Qualifier;
  2565.         gd = (struct Gadget *)imsg->IAddress;
  2566.  
  2567.         ReplyMsg( (struct Message *)imsg );
  2568.  
  2569.         switch( class )
  2570.         {
  2571.         case VANILLAKEY:
  2572.             if( code == '\33' || (code == 'b' && (qual&AMIGALEFT)) )
  2573.             {
  2574.             done = 1;
  2575.             quit = 0;
  2576.             }
  2577.             break;
  2578.  
  2579.         case CLOSEWINDOW:
  2580.             if( sp )
  2581.             {
  2582.             if( *sp )
  2583.                 free( *sp );
  2584.             *sp = strdup( StrTools );
  2585.             }
  2586.             done = 1;
  2587.             quit = 0;
  2588.             break;
  2589.  
  2590.         case GADGETUP:
  2591.             switch( gd->GadgetID )
  2592.             {
  2593.             case GADEDDEF:
  2594.                 /* Put the game values into the defaults */
  2595.  
  2596.                 Game2Defs( gptr );
  2597.  
  2598.                 /* Put the options into the options array */
  2599.  
  2600.                 CopyOptions( curopts, gptr );
  2601.  
  2602.                 /* Edit the defaults */
  2603.  
  2604.                 menu_editdef( GAME_FROM_INFO );
  2605.  
  2606.                 /* Put the options back in */
  2607.  
  2608.                 SetOptions( curopts, gptr );
  2609.  
  2610.                 /* Move defaults to game */
  2611.  
  2612.                 SetToolLine( gptr, "NAME", defgame.plname );
  2613.                 SetToolLine( gptr, "CHARACTER",
  2614.                 defgame.pltype ?
  2615.                 players[ defgame.pltype ] : "" );
  2616.                 itext[ 2 ].IText =
  2617.                 ToolsEntry( gptr, "CHARACTER" );
  2618.                 strncpy( namestr, ToolsEntry( gptr, "NAME" ),
  2619.                 sizeof( namestr ) );
  2620.                 namestr[ sizeof( namestr ) - 1 ] = 0;
  2621.                 if( *namestr == 0 )
  2622.                 {
  2623.                 strncpy( namestr, gptr->name, sizeof(namestr) );
  2624.                 namestr[ sizeof( namestr ) - 1 ] = 0;
  2625.                 }
  2626.                 if( ( t = strrchr( namestr, '.' ) ) &&
  2627.                 stricmp( t, ".sav" ) == 0 )
  2628.                 {
  2629.                 *t = 0;
  2630.                 }
  2631.                 itext[ 1 ].IText = namestr;
  2632.  
  2633.                 /* Make sure that the correct ToolTypes line
  2634.                  * is displayed in the gadget.
  2635.                  */
  2636.  
  2637.                 strcpy( StrTools, *sp );
  2638.                 UpdateInfoWin( cwin );
  2639.                 break;
  2640.  
  2641.             case GADADDTOOL:
  2642.                 ReallocTools( gptr, 1 );
  2643.                 sp = gptr->dobj->do_ToolTypes;
  2644.                 for( i = 0; sp[ i ]; ++i )
  2645.                 ;
  2646.                 sp[i] = strdup( "" );
  2647.                 sp[i+1] = NULL;
  2648.                 itext[ 2 ].IText =
  2649.                 ToolsEntry( gptr, "CHARACTER" );
  2650.                 *StrTools = 0;
  2651.                 UpdateInfoWin( cwin );
  2652.                 sp += i;
  2653.                 break;
  2654.  
  2655.             case GADDELTOOL:
  2656.                 while( *sp = sp[1] )
  2657.                 ++sp;
  2658.                 sp = gptr->dobj->do_ToolTypes;
  2659.                 strcpy( StrTools, *sp ? *sp : "" );
  2660.                 UpdateInfoWin( cwin );
  2661.                 break;
  2662.  
  2663.             case GADTOOLTYPES:
  2664.                 if( sp && *sp && CheckAndCopy( StrTools, *sp ) )
  2665.                 {
  2666.                 if( *sp )
  2667.                     free( *sp );
  2668.                 *sp = strdup( StrTools );
  2669.                 }
  2670.                 break;
  2671.  
  2672.             case GADTOOLDOWN:
  2673.                 if( sp && *sp && CheckAndCopy( StrTools, *sp ) )
  2674.                 {
  2675.                 if( *sp )
  2676.                     free( *sp );
  2677.                 *sp = strdup( StrTools );
  2678.                 }
  2679.                 if( sp != NULL && sp[1] != NULL )
  2680.                 {
  2681.                 ++sp;
  2682.                 strcpy( StrTools, *sp );
  2683.                 if( IsEditEntry( StrTools, gptr ) )
  2684.                     Info_ToolTypes.Flags &= ~GADGDISABLED;
  2685.                 else
  2686.                     Info_ToolTypes.Flags |= GADGDISABLED;
  2687.                 }
  2688.                 else
  2689.                 {
  2690.                 if( sp && *sp )
  2691.                     strcpy( StrTools, *sp );
  2692.                 DisplayBeep( NULL );
  2693.                 }
  2694.                 break;
  2695.  
  2696.             case GADTOOLUP:
  2697.                 if( sp && *sp && CheckAndCopy( StrTools, *sp ) )
  2698.                 {
  2699.                 if( *sp )
  2700.                     free( *sp );
  2701.                 *sp = strdup( StrTools );
  2702.                 }
  2703.                 if( sp && sp > gptr->dobj->do_ToolTypes )
  2704.                 {
  2705.                 --sp;
  2706.                 strcpy( StrTools, *sp );
  2707.                 if( IsEditEntry( StrTools, gptr ) )
  2708.                     Info_ToolTypes.Flags &= ~GADGDISABLED;
  2709.                 else
  2710.                     Info_ToolTypes.Flags |= GADGDISABLED;
  2711.                 }
  2712.                 else
  2713.                 {
  2714.                 DisplayBeep( NULL );
  2715.                 }
  2716.                 break;
  2717.             }
  2718.             RefreshGList( &Info_ToolTypes, cwin, NULL, 1 );
  2719.             break;
  2720.         }
  2721.     }
  2722.     }
  2723.  
  2724.     SafeCloseWindow( cwin );
  2725. }
  2726.  
  2727. static void
  2728. UpdateInfoWin( cwin )
  2729.     struct Window *cwin;
  2730. {
  2731.     SetAPen( cwin->RPort, 0 );
  2732.     SetBPen( cwin->RPort, 0 );
  2733.     SetDrMd( cwin->RPort, JAM2 );
  2734.     RectFill( cwin->RPort,
  2735.     Info_Class.LeftEdge,
  2736.     Info_Class.TopEdge,
  2737.     Info_Class.LeftEdge + Info_Class.Width-1,
  2738.     Info_Class.TopEdge + Info_Class.Height-1 );
  2739.     RectFill( cwin->RPort,
  2740.     Info_Player.LeftEdge,
  2741.     Info_Player.TopEdge,
  2742.     Info_Player.LeftEdge + Info_Player.Width-1,
  2743.     Info_Player.TopEdge + Info_Player.Height-1 );
  2744.     RefreshGList( cwin->FirstGadget, cwin, NULL, -1 );
  2745. }
  2746.  
  2747. void
  2748. errmsg(int flash, char *str, ...)
  2749. {
  2750.     static char buf[ 200 ];
  2751.     int wid;
  2752.     va_list vp;
  2753.  
  2754.     va_start( vp, str );
  2755.  
  2756.     if( !win || !wbopen )
  2757.     {
  2758.     vprintf( str, vp );
  2759.     va_end( vp );
  2760.     return;
  2761.     }
  2762.     errup = 1;
  2763.     wid = ( win->Width + Message.LeftEdge - win->BorderRight - 3 ) /
  2764.             win->RPort->TxWidth;
  2765.     vsprintf( buf, str, vp );
  2766.     va_end( vp );
  2767.  
  2768.     SetAPen( win->RPort, 0 );
  2769.     SetBPen( win->RPort, 0 );
  2770.     SetDrMd( win->RPort, JAM2 );
  2771.     RectFill( win->RPort, Message.LeftEdge, Message.TopEdge,
  2772.     win->Width + Message.Width,
  2773.     Message.TopEdge + Message.Height - 1 );
  2774.  
  2775.     Message.GadgetText->IText = buf;
  2776.     RefreshGList( &Message, win, 0, 1 );
  2777.  
  2778.     if( flash == FLASH )
  2779.     DisplayBeep( scrn );
  2780. }
  2781.  
  2782. /*
  2783.  * Issue an error message to the users window because it can not be done
  2784.  * any other way.
  2785.  */
  2786.  
  2787. void error( str )
  2788.     register char *str;
  2789. {
  2790.     char s[ 50 ];
  2791.     if( scrn ) ScreenToBack( scrn );
  2792.     Delay( 10 );
  2793.     fprintf( stderr, "%s\n", str );
  2794.     fprintf( stderr, "Hit Return: " );
  2795.     fflush( stderr );
  2796.     gets( s );
  2797.     if( scrn ) ScreenToFront( scrn );
  2798. }
  2799.  
  2800. /*
  2801.  * Make the gadget deselected
  2802.  */
  2803.  
  2804. void SetGadgetUP( gad )
  2805.     register struct Gadget *gad;
  2806. {
  2807.     RemoveGadget( win, gad );
  2808.     gad->Flags &= ~(SELECTED|GADGHIGHBITS);
  2809.     gad->Flags |= GADGHIMAGE|GADGIMAGE;
  2810.     gad->Activation |= TOGGLESELECT;
  2811.     AddGadget( win, gad, 0 );
  2812.     RefreshGList( gad, win, NULL, 1 );
  2813.     RemoveGadget( win, gad );
  2814.     gad->Flags &= ~(GADGHIGHBITS);
  2815.     gad->Flags |= GADGHNONE;
  2816.     gad->Activation &= ~TOGGLESELECT;
  2817.     AddGadget( win, gad, 0 );
  2818. }
  2819.  
  2820. /*
  2821.  * Make the gadget selected
  2822.  */
  2823.  
  2824. void SetGadgetDOWN( gad )
  2825.     register struct Gadget *gad;
  2826. {
  2827.     RemoveGadget( win, gad );
  2828.     gad->Flags &= ~GADGHIGHBITS;
  2829.     gad->Flags |= GADGHIMAGE|GADGIMAGE|SELECTED;
  2830.     gad->Activation |= TOGGLESELECT;
  2831.     AddGadget( win, gad, 0 );
  2832.     RefreshGList( gad, win, NULL, 1 );
  2833.     RemoveGadget( win, gad );
  2834.     gad->Flags &= ~(GADGHIGHBITS);
  2835.     gad->Flags |= GADGHNONE;
  2836.     gad->Activation &= ~TOGGLESELECT;
  2837.     AddGadget( win, gad, 0 );
  2838. }
  2839.  
  2840. /*
  2841.  * Generate a requester for a string value.
  2842.  */
  2843.  
  2844. int StrRequest( prompt, buff, val )
  2845.     char *prompt, *buff, *val;
  2846. {
  2847.     struct Window *cwin;
  2848.     struct IntuiMessage *imsg;
  2849.     int done = 0, notcan = 1;
  2850.     long class, code, qual;
  2851.     struct Gadget *gd;
  2852.     static int once = 0;
  2853.     int txtdiff = scrn->RastPort.TxHeight - 8;
  2854.  
  2855.     *StrString = 0;
  2856.     if( val )
  2857.     strcpy( StrString, val );
  2858.     Str_NewWindowStructure5.Title = prompt;
  2859.  
  2860.     if( !once )
  2861.     {
  2862.     for( gd = Str_NewWindowStructure5.FirstGadget;
  2863.             gd; gd = gd->NextGadget )
  2864.     {
  2865.         if( gd->GadgetID != 0 )
  2866.         {
  2867.         gd->TopEdge += txtdiff;
  2868.         gd->Height += txtdiff;
  2869.         SetBorder( gd, -1 );
  2870.         }
  2871.     }
  2872.     ++once;
  2873.     Str_NewWindowStructure5.Height += txtdiff * 2;
  2874.     }
  2875.  
  2876.     Str_NewWindowStructure5.Screen = scrn;
  2877.     if( ( cwin = MyOpenWindow( &Str_NewWindowStructure5 ) ) == NULL )
  2878.     {
  2879.     errmsg( FLASH, "Can't create requester window" );
  2880.     return( 0 );
  2881.     }
  2882.  
  2883.     while( !done )
  2884.     {
  2885.     WaitPort( cwin->UserPort );
  2886.     while( ( imsg = (void *) GetMsg( cwin->UserPort ) ) != NULL )
  2887.     {
  2888.         class = imsg->Class;
  2889.         code = imsg->Code;
  2890.         qual = imsg->Qualifier;
  2891.         gd = (struct Gadget *) imsg->IAddress;
  2892.         ReplyMsg( (struct Message *) imsg );
  2893.         switch( class )
  2894.         {
  2895.         case ACTIVEWINDOW:
  2896.             ActivateGadget( &Str_String, cwin, NULL );
  2897.             break;
  2898.  
  2899.         case GADGETUP:
  2900.             switch( gd->GadgetID )
  2901.             {
  2902.             case GADSTRCANCEL:
  2903.                 notcan = 0;
  2904.                 done = 1;
  2905.                 break;
  2906.  
  2907.             default:
  2908.                 strcpy( buff, StrString );
  2909.                 done = 1;
  2910.                 break;
  2911.             }
  2912.             break;
  2913.  
  2914.         case CLOSEWINDOW:
  2915.             strcpy( buff, StrString );
  2916.             done = 1;
  2917.             break;
  2918.  
  2919.         case VANILLAKEY:
  2920.             if( code == '\33' || code == 'b' && (qual&AMIGALEFT) )
  2921.             {
  2922.             done = 1;
  2923.             notcan = 0;
  2924.             }
  2925.             break;
  2926.         }
  2927.     }
  2928.     }
  2929.  
  2930.     SafeCloseWindow( cwin );
  2931.     return( notcan );
  2932. }
  2933.  
  2934. /*
  2935.  * Load a defaults file into global structures
  2936.  */
  2937.  
  2938. void LoadDefaults( player )
  2939.     char *player;
  2940. {
  2941.     FILE *fp;
  2942.     int i;
  2943.     char fname[ 100 ];
  2944.     char buf[ 200 ];
  2945.     char *t;
  2946.  
  2947.     sprintf( fname, "%s.def", player );
  2948.  
  2949.     if( ( fp = fopen( fname, "r" ) ) == NULL )
  2950.     {
  2951.     errmsg( FLASH,
  2952.         "Can't open defaults, %s, in current directory", fname );
  2953.     return;
  2954.     }
  2955.  
  2956.     while( fgets( buf, sizeof( buf ), fp ) != NULL )
  2957.     {
  2958.     if( *buf == '#' )
  2959.         continue;
  2960.  
  2961.     if( ( t = strchr( buf, '\n' ) ) != NULL )
  2962.         *t = 0;
  2963.     if( strnicmp( "PLAYER=", buf, 7 ) == 0 )
  2964.     {
  2965.         if( defgame.plname )
  2966.         free( defgame.plname );
  2967.         defgame.plname = strdup( buf + 7 );
  2968.     }
  2969.     else if( strnicmp( "PLAYERTYPE=", buf, 11 ) == 0 )
  2970.     {
  2971.         for( i = 0; players[ i ]; ++i )
  2972.         {
  2973.         if( strnicmp( &buf[11], players[ i ], 1 ) == 0 )
  2974.             break;
  2975.         }
  2976.  
  2977.         if( players[ i ] )
  2978.         defgame.pltype = i;
  2979.         else
  2980.         defgame.pltype = 0;
  2981.     }
  2982.     else if( strnicmp( "OPTIONS=", buf, 8 ) == 0 )
  2983.     {
  2984.         errmsg( FLASH, "OPTIONS set by game configuration" );
  2985.         setoneopt( OPTIONS_IDX, buf+8 );
  2986.         defgame.options = strdup( buf + 8 );
  2987.     }
  2988.     else
  2989.         errmsg( FLASH, "Invalid line in defaults file" );
  2990.     }
  2991.     fclose( fp );
  2992. }
  2993.  
  2994. /*
  2995.  * Create a defaults file my the name given with all of the global
  2996.  * information currently set.
  2997.  */
  2998.  
  2999. void SaveDefaults( player )
  3000.     char *player;
  3001. {
  3002.     FILE *fp;
  3003.     char fname[ 100 ];
  3004.     int err;
  3005.  
  3006.     sprintf( fname, "%s.def", player );
  3007.  
  3008.     if( ( fp = fopen( fname, "w" ) ) == NULL )
  3009.     {
  3010.     errmsg( FLASH, "Can't open defaults file: %s", fname );
  3011.     return;
  3012.     }
  3013.  
  3014.     err = fprintf( fp, "PLAYER=%s\n", defgame.plname );
  3015.     if( defgame.pltype )
  3016.     err |= fprintf( fp, "PLAYERTYPE=%s\n", players[ defgame.pltype ] );
  3017.     else
  3018.     err |= fprintf( fp, "PLAYERTYPE=<RANDOM>\n" );
  3019.  
  3020.     /* Get the options. */
  3021.     PutOptions( curopts );
  3022.  
  3023.     /* Put them in too */
  3024.     err |= fprintf( fp, "OPTIONS=%s\n", options[ OPTIONS_IDX ] );
  3025.     err |= fclose( fp );
  3026.  
  3027.     if( err == EOF )
  3028.     errmsg( FLASH, "Error writing out defaults for: %s", fname );
  3029. }
  3030.  
  3031. /*
  3032.  * Copy the defgame structure values into the Defs windows gadgets
  3033.  */
  3034.  
  3035. void CopyDefs2Gad()
  3036. {
  3037.     if( defgame.plname )
  3038.     strcpy( DefPlayerName, defgame.plname );
  3039.     else
  3040.     *DefPlayerName = 0;
  3041.  
  3042.     CheckOnly( &Defs_MenuList11, 0, defgame.pltype );
  3043.  
  3044.     /* If there are default options fill them in, else reset
  3045.      * to the real defaults.
  3046.      */
  3047.     if( defgame.options )
  3048.     CopyOptionStr( curopts, defgame.options );
  3049.     else
  3050.     ZapOptions( curopts );
  3051. }
  3052.  
  3053. /*
  3054.  * Copy the Defs window gadgets into the defgame structure
  3055.  */
  3056.  
  3057. void CopyGad2Defs( )
  3058. {
  3059.     if( defgame.plname )
  3060.     free( defgame.plname );
  3061.     defgame.plname = strdup( DefPlayerName );
  3062.  
  3063.     defgame.pltype = FindChecked( &Defs_MenuList11, 0 );
  3064. }
  3065.  
  3066. /*
  3067.  * Make sure that the correct character type is checked
  3068.  */
  3069.  
  3070. void UpdateTypes( cwin )
  3071.     register struct Window *cwin;
  3072. {
  3073.     register struct RastPort *rp = cwin->RPort;
  3074.  
  3075.     SetAPen( rp, 0 );
  3076.     SetBPen( rp, 0 );
  3077.     SetDrMd( rp, JAM2 );
  3078.     RectFill( cwin->RPort,
  3079.     Defs_PlayerType.LeftEdge+1,
  3080.     Defs_PlayerType.TopEdge+1,
  3081.     Defs_PlayerType.LeftEdge+Defs_PlayerType.Width-1,
  3082.     Defs_PlayerType.TopEdge+Defs_PlayerType.Height-1 );
  3083.  
  3084.     Defs_PlayerType.GadgetText->IText = players[ defgame.pltype ];
  3085.     RefreshGList( &Defs_PlayerType, cwin, NULL, 1 );
  3086. }
  3087.  
  3088. /*
  3089.  * Ask the user if they really want to do something.
  3090.  */
  3091.  
  3092. Ask( quest )
  3093.     char *quest;
  3094. {
  3095.     register struct Window *qwin;
  3096.     register struct Gadget *gd;
  3097.     register struct IntuiMessage *imsg;
  3098.     register int done = 0, quit = 1;
  3099.     int txtdiff;
  3100.     long class, code, qual;
  3101.     static int once = 0;
  3102.     static WORD areabuffer[ 80 ];
  3103.     static USHORT apat[] = { 0x5555, 0xaaaa };
  3104.     static struct AreaInfo areaInfo = { 0 };
  3105.     PLANEPTR pp;
  3106.     struct TmpRas tmpras;
  3107.  
  3108.     Quest_NewWindowStructure2.Screen = scrn;
  3109.     txtdiff = scrn->RastPort.TxHeight - 8;
  3110.     if( !once )
  3111.     {
  3112.     Quest_IntuiTextList2.TopEdge += txtdiff;
  3113.     Quest_Borders2.TopEdge += txtdiff;
  3114.     Quest_NewWindowStructure2.Height += txtdiff * 2;
  3115.     SetBorder( &Quest_Borders2, 3 );
  3116.     Quest_Yes.TopEdge += txtdiff;
  3117.     Quest_Yes.Height += txtdiff;
  3118.     SetBorder( &Quest_Yes, -1 );
  3119.     Quest_No.TopEdge += txtdiff;
  3120.     Quest_No.Height += txtdiff;
  3121.     SetBorder( &Quest_No, -1 );
  3122.     }
  3123.  
  3124.     memset( areabuffer, 0, sizeof( areabuffer ) );
  3125.     if( ( qwin = MyOpenWindow( &Quest_NewWindowStructure2 ) ) == NULL )
  3126.     {
  3127.     errmsg( FLASH, "Can't create requester window" );
  3128.     return( 1 );
  3129.     }
  3130.  
  3131.     pp = AllocRaster( qwin->Width, qwin->Height );
  3132.     if( pp )
  3133.     {
  3134.     InitArea( &areaInfo, areabuffer, 160/5 );
  3135.     qwin->RPort->AreaInfo = &areaInfo;
  3136.  
  3137.     InitTmpRas( &tmpras, pp, RASSIZE( qwin->Width, qwin->Height ) );
  3138.     qwin->RPort->TmpRas = &tmpras;
  3139.  
  3140.     SetAPen( qwin->RPort, C_WHITE );
  3141.     SetBPen( qwin->RPort, C_GREY );
  3142.     SetDrMd( qwin->RPort, JAM2 );
  3143.     SetAfPt( qwin->RPort, apat, 1 );
  3144.  
  3145.     AreaMove( qwin->RPort, qwin->BorderLeft, qwin->BorderTop );
  3146.     AreaDraw( qwin->RPort, qwin->Width-qwin->BorderRight, qwin->BorderTop );
  3147.     AreaDraw( qwin->RPort, qwin->Width - qwin->BorderRight,
  3148.         qwin->Height - qwin->BorderBottom );
  3149.     AreaDraw( qwin->RPort, qwin->BorderLeft,
  3150.         qwin->Height - qwin->BorderBottom );
  3151.     AreaDraw( qwin->RPort, qwin->BorderLeft, qwin->BorderTop );
  3152.     AreaEnd( qwin->RPort );
  3153.  
  3154.     SetAPen( qwin->RPort, C_GREY );
  3155.     SetBPen( qwin->RPort, C_GREY );
  3156.     SetDrMd( qwin->RPort, JAM2 );
  3157.     SetAfPt( qwin->RPort, NULL, 0 );
  3158.  
  3159.     RectFill( qwin->RPort,
  3160.         Quest_Borders2.LeftEdge,
  3161.         Quest_Borders2.TopEdge,
  3162.         Quest_Borders2.LeftEdge + Quest_Borders2.Width - 1,
  3163.         Quest_Borders2.TopEdge + Quest_Borders2.Height - 1 );
  3164.     RectFill( qwin->RPort,
  3165.         Quest_No.LeftEdge,
  3166.         Quest_No.TopEdge,
  3167.         Quest_No.LeftEdge + Quest_No.Width - 1,
  3168.         Quest_No.TopEdge + Quest_No.Height - 1 );
  3169.     RectFill( qwin->RPort,
  3170.         Quest_Yes.LeftEdge,
  3171.         Quest_Yes.TopEdge,
  3172.         Quest_Yes.LeftEdge + Quest_Yes.Width - 1,
  3173.         Quest_Yes.TopEdge + Quest_Yes.Height - 1 );
  3174.     RefreshGList( qwin->FirstGadget, qwin, NULL, -1 );
  3175.     }
  3176.  
  3177.     Quest_IntuiTextList2.LeftEdge = ( qwin->Width -
  3178.     ( qwin->RPort->TxWidth * strlen( quest ) ) ) / 2;
  3179.     Quest_IntuiTextList2.IText = quest;
  3180.     PrintIText( qwin->RPort, &Quest_IntuiTextList2, 0, 0 );
  3181.     while( !done )
  3182.     {
  3183.     WaitPort( qwin->UserPort );
  3184.     while( ( imsg = (void *) GetMsg( qwin->UserPort ) ) != NULL )
  3185.     {
  3186.         class = imsg->Class;
  3187.         code = imsg->Code;
  3188.         qual = imsg->Qualifier;
  3189.         gd = (struct Gadget *)imsg->IAddress;
  3190.  
  3191.         ReplyMsg( (struct Message *)imsg );
  3192.  
  3193.         switch( class )
  3194.         {
  3195.         case VANILLAKEY:
  3196.             if( imsg->Qualifier & AMIGALEFT )
  3197.             {
  3198.             switch( imsg->Code )
  3199.             {
  3200.                 case 'v': done = 1; quit = 0; break;
  3201.                 case '\33':
  3202.                 case 'b': done = 1; quit = 1; break;
  3203.             }
  3204.             }
  3205.             break;
  3206.  
  3207.         case CLOSEWINDOW:
  3208.             done = 1; quit = 1; break;
  3209.             break;
  3210.  
  3211.         case GADGETUP:
  3212.             switch( gd->GadgetID )
  3213.             {
  3214.             case GADQUESTYES: done = 1; quit = 0; break;
  3215.             case GADQUESTNO: done = 1; quit = 1; break;
  3216.             }
  3217.             break;
  3218.         }
  3219.     }
  3220.     }
  3221.  
  3222.     if( pp )
  3223.     FreeRaster( pp, qwin->Width, qwin->Height );
  3224.     once = 1;
  3225.     SafeCloseWindow( qwin );
  3226.     return( quit == 0 );
  3227. }
  3228.  
  3229. /* Make sure that a game icon is selected and return the pointer to
  3230.  * the GPTR structure associated with it.
  3231.  */
  3232.  
  3233. GPTR NeedGame()
  3234. {
  3235.     register GPTR gptr;
  3236.  
  3237.     if( lastgaddown == NULL )
  3238.     {
  3239.     errmsg( FLASH, "Must select a game" );
  3240.     return( NULL );
  3241.     }
  3242.  
  3243.     for( gptr = windowgads; gptr; gptr = gptr->nextwgad )
  3244.     {
  3245.     if( &gptr->dobj->do_Gadget == &lastgaddown->dobj->do_Gadget )
  3246.         break;
  3247.     }
  3248.  
  3249.     if( !gptr )
  3250.     {
  3251.     errmsg( FLASH, "BUG: invalid gadget selected for processing" );
  3252.     return( NULL );
  3253.     }
  3254.     return( gptr );
  3255. }
  3256.  
  3257. /* Set menu items SELECT flag based on 'enable' */
  3258.  
  3259. void ChgGameItems( menup, enable )
  3260.     struct Menu *menup;
  3261.     int enable;
  3262. {
  3263.     struct MenuItem *ip;
  3264.     int i;
  3265.     int ino;
  3266.  
  3267.     /* Make sure the 'Game' menu is there. */
  3268.  
  3269.     if( !menup || !(menup = menup->NextMenu) || !( ip = menup->FirstItem ) )
  3270.     {
  3271.     errmsg( FLASH, "BUG: invalid menu to disable with" );
  3272.     return;
  3273.     }
  3274.  
  3275.     /* Go through all items */
  3276.  
  3277.     for( i = 0; ip; ip = ip->NextItem, ++i )
  3278.     {
  3279.     switch( i )
  3280.     {
  3281.         case ITEM_INFO:
  3282.         case ITEM_SETCOMMENT:
  3283.         case ITEM_SETOPT:
  3284.         case ITEM_COPYOPT:
  3285.         case ITEM_DISCARD:
  3286.         case ITEM_RENAME:
  3287.         ino = MENUITEMNO( 1,i,NOSUB );
  3288.         if( enable )
  3289.             OnMenu( win, ino );
  3290.         else
  3291.             OffMenu( win, ino );
  3292.         break;
  3293.     }
  3294.     }
  3295. }
  3296.  
  3297. /* Set menu items SELECT flag based on 'enable' for NEWGAME gadget */
  3298.  
  3299. void ChgNewGameItems( menup, enable )
  3300.     struct Menu *menup;
  3301.     int enable;
  3302. {
  3303.     struct MenuItem *ip;
  3304.     int i;
  3305.     int ino;
  3306.  
  3307.     /* Make sure the 'Game' menu is there. */
  3308.  
  3309.     if( !menup || !(menup = menup->NextMenu) || !( ip = menup->FirstItem ) )
  3310.     {
  3311.     errmsg( FLASH, "BUG: invalid menu to disable with" );
  3312.     return;
  3313.     }
  3314.  
  3315.     /* Go through all items */
  3316.  
  3317.     for( i = 0; ip; ip = ip->NextItem, ++i )
  3318.     {
  3319.     switch( i )
  3320.     {
  3321.         case ITEM_SETOPT:
  3322.         case ITEM_RENAME:
  3323.         case ITEM_DISCARD:
  3324.         case ITEM_COPYOPT:
  3325.         ino = MENUITEMNO( 1,i,NOSUB );
  3326.         OffMenu( win, ino );
  3327.         break;
  3328.  
  3329.         case ITEM_INFO:
  3330.         case ITEM_SETCOMMENT:
  3331.         ino = MENUITEMNO( 1,i,NOSUB );
  3332.         if( enable )
  3333.             OnMenu( win, ino );
  3334.         else
  3335.             OffMenu( win, ino );
  3336.         break;
  3337.     }
  3338.     }
  3339. }
  3340.  
  3341. /* Edit the OPTIONS= line with a window.  The optr[] array is set up
  3342.  * for the editing already, and will be returned with the values
  3343.  * of the members changed based on the users input
  3344.  */
  3345.  
  3346. int EditOptions( optr )
  3347.     OPTR optr;
  3348. {
  3349.     int done = 0, quit = 0;
  3350.     register struct Window *cwin;
  3351.     register struct IntuiMessage *imsg;
  3352.     register struct Gadget *gd;
  3353.     long code, class, qual;
  3354.     struct IntuiText *ip;
  3355.     static int once = 0;
  3356.     int i;
  3357.     int txtdiff = scrn->RastPort.TxHeight - 8;
  3358.  
  3359.     if( !once )
  3360.     {
  3361.     if( gd = FindGadget( NULL, &Options_NewWindowStructure3, GADOCOLOR ))
  3362.     {
  3363.         struct Gadget *g;
  3364.         for( g = Options_NewWindowStructure3.FirstGadget;
  3365.                 g; g = g->NextGadget )
  3366.         {
  3367.         if( g == gd )
  3368.             continue;
  3369.         if( g->TopEdge == gd->TopEdge )
  3370.         {
  3371.             g->Height += txtdiff;
  3372.         }
  3373.         }
  3374.         gd->Height += txtdiff;
  3375.     }
  3376.  
  3377.     if( gd = FindGadget( NULL, &Options_NewWindowStructure3, GADOTIME ))
  3378.     {
  3379.         struct Gadget *g;
  3380.         for( g = Options_NewWindowStructure3.FirstGadget;
  3381.                 g; g = g->NextGadget )
  3382.         {
  3383.         if( g == gd )
  3384.             continue;
  3385.         if( g->TopEdge == gd->TopEdge )
  3386.         {
  3387.             g->TopEdge += txtdiff;
  3388.             g->Height += txtdiff;
  3389.         }
  3390.         }
  3391.         gd->TopEdge += txtdiff;
  3392.         gd->Height += txtdiff;
  3393.     }
  3394.  
  3395.     if( gd = FindGadget( NULL, &Options_NewWindowStructure3, GADOPICKUP ))
  3396.     {
  3397.         struct Gadget *g;
  3398.         for( g = Options_NewWindowStructure3.FirstGadget; g; g = g->NextGadget )
  3399.         {
  3400.         if( g == gd )
  3401.             continue;
  3402.         if( g->TopEdge == gd->TopEdge )
  3403.         {
  3404.             g->TopEdge += txtdiff*2;
  3405.             g->Height += txtdiff;
  3406.         }
  3407.         }
  3408.         gd->TopEdge += txtdiff*2;
  3409.         gd->Height += txtdiff;
  3410.     }
  3411.  
  3412.     if( gd = FindGadget( NULL, &Options_NewWindowStructure3, GADOHILITEPET ))
  3413.     {
  3414.         struct Gadget *g;
  3415.         for( g = Options_NewWindowStructure3.FirstGadget; g; g = g->NextGadget )
  3416.         {
  3417.         if( g == gd )
  3418.             continue;
  3419.         if( g->TopEdge == gd->TopEdge )
  3420.         {
  3421.             g->TopEdge += txtdiff*3;
  3422.             g->Height += txtdiff;
  3423.         }
  3424.         }
  3425.         gd->TopEdge += txtdiff*3;
  3426.         gd->Height += txtdiff;
  3427.     }
  3428.  
  3429.     if( gd = FindGadget( NULL, &Options_NewWindowStructure3, GADOPACKORDER ))
  3430.     {
  3431.         gd->TopEdge += txtdiff*4;
  3432.         gd->Height += txtdiff;
  3433.     }
  3434.     if( gd = FindGadget( NULL, &Options_NewWindowStructure3, GADOCATNAME ))
  3435.     {
  3436.         gd->TopEdge += txtdiff*5;
  3437.         gd->Height += txtdiff;
  3438.     }
  3439.     if( gd = FindGadget( NULL, &Options_NewWindowStructure3, GADODOGNAME ))
  3440.     {
  3441.         gd->TopEdge += txtdiff*6;
  3442.         gd->Height += txtdiff;
  3443.     }
  3444.     if( gd = FindGadget( NULL, &Options_NewWindowStructure3, GADOFRUIT ))
  3445.     {
  3446.         gd->TopEdge += txtdiff*7;
  3447.         gd->Height += txtdiff;
  3448.     }
  3449.     if( gd = FindGadget( NULL, &Options_NewWindowStructure3, GADOOBJECTS ))
  3450.     {
  3451.         gd->TopEdge += txtdiff*8;
  3452.         gd->Height += txtdiff;
  3453.     }
  3454.     if( gd = FindGadget( NULL, &Options_NewWindowStructure3, GADOOKAY ))
  3455.     {
  3456.         gd->TopEdge += txtdiff*9;
  3457.         gd->Height += txtdiff;
  3458.     }
  3459.     if( gd = FindGadget( NULL, &Options_NewWindowStructure3, GADOCANCEL ))
  3460.     {
  3461.         gd->TopEdge += txtdiff*9;
  3462.         gd->Height += txtdiff;
  3463.     }
  3464.     Options_NewWindowStructure3.Height += txtdiff*11;
  3465.     Options_NewWindowStructure3.TopEdge -= txtdiff*6;
  3466.     if( Options_NewWindowStructure3.Height +
  3467.         Options_NewWindowStructure3.TopEdge >= scrn->Height )
  3468.     {
  3469.         Options_NewWindowStructure3.TopEdge = scrn->Height -
  3470.         Options_NewWindowStructure3.Height - 1;
  3471.     }
  3472.     if( Options_NewWindowStructure3.TopEdge < 0 )
  3473.         Options_NewWindowStructure3.TopEdge = 0;
  3474.     {
  3475.         if( Options_NewWindowStructure3.Height > scrn->Height )
  3476.         Options_NewWindowStructure3.Height = scrn->Height;
  3477.     }
  3478.  
  3479.     /* Now that heights are correct, render borders */
  3480.     for( gd = Options_NewWindowStructure3.FirstGadget;
  3481.         gd; gd = gd->NextGadget )
  3482.     {
  3483.         if( gd->GadgetID != 0 )
  3484.         {
  3485.         gd->TopEdge += txtdiff;
  3486.         SetBorder( gd, -1 );
  3487.         }
  3488.     }
  3489.     for( ip = &Options_IntuiTextList3; ip; ip = ip->NextText )
  3490.     {
  3491.         if( *ip->IText == 'P' )
  3492.         ip->TopEdge += txtdiff * 5;
  3493.         else if( *ip->IText == 'C' )
  3494.         ip->TopEdge += txtdiff * 6;
  3495.         else if( *ip->IText == 'D' )
  3496.         ip->TopEdge += txtdiff * 7;
  3497.         else if( *ip->IText == 'F' )
  3498.         ip->TopEdge += txtdiff * 8;
  3499.         else if( *ip->IText == 'O' )
  3500.         ip->TopEdge += txtdiff * 9;
  3501.     }
  3502.     once = 1;
  3503.     }
  3504.  
  3505.     /* Set Gadgets based on options settings */
  3506.  
  3507.     for( i = 0; optr[ i ].name; ++i )
  3508.     {
  3509.     if( gd = FindGadget( NULL, &Options_NewWindowStructure3, optr[i].id ))
  3510.     {
  3511.         /* If string valued option, set string */
  3512.         if( optr[ i ].optstr )
  3513.         {
  3514.         strcpy( Sbuff( gd ), optr[i].optstr );
  3515.         }
  3516.         else
  3517.         {
  3518.         /* If binary option, set the gadget state */
  3519.         if( optr[i].optval )
  3520.             gd->Flags |= SELECTED;
  3521.         else
  3522.             gd->Flags &= ~SELECTED;
  3523.         }
  3524.     }
  3525.     else
  3526.     {
  3527.         errmsg( FLASH, "Can't find gadget %d in options window",
  3528.                                 optr[i].id);
  3529.     }
  3530.     }
  3531.  
  3532.     Options_NewWindowStructure3.Screen = scrn;
  3533.     if( ( cwin = MyOpenWindow( &Options_NewWindowStructure3 ) ) == NULL )
  3534.     {
  3535.     errmsg( FLASH, "Can't create requester window" );
  3536.     return(0);
  3537.     }
  3538.     PrintIText( cwin->RPort, &Options_IntuiTextList3, 0, txtdiff );
  3539.  
  3540.     while( !done )
  3541.     {
  3542.     WaitPort( cwin->UserPort );
  3543.     while( ( imsg = (void *) GetMsg( cwin->UserPort ) ) != NULL )
  3544.     {
  3545.         class = imsg->Class;
  3546.         code = imsg->Code;
  3547.         qual = imsg->Qualifier;
  3548.         gd = (struct Gadget *)imsg->IAddress;
  3549.         ReplyMsg( (struct Message *) imsg );
  3550.         switch( class )
  3551.         {
  3552.         case ACTIVEWINDOW:
  3553.             ActivateGadget(
  3554.             FindGadget( cwin, 0, GADOPACKORDER ), cwin, 0 );
  3555.             break;
  3556.  
  3557.         case VANILLAKEY:
  3558.             if( code == '\33' )
  3559.             {
  3560.             done = 1;
  3561.             quit = 1;
  3562.             }
  3563.             else if( code == 'v' && (qual & AMIGALEFT) )
  3564.             done = 1;
  3565.             else if( code == 'b' && (qual & AMIGALEFT) )
  3566.             {
  3567.             done = 1;
  3568.             quit = 1;
  3569.             }
  3570.             else
  3571.             {
  3572.             switch( code )
  3573.             {
  3574.                 case 'p':
  3575.                 case 'P':
  3576.                 ActivateGadget(
  3577.                     FindGadget( cwin, 0, GADOPACKORDER ),
  3578.                     cwin, 0 );
  3579.                 break;
  3580.                 case 'c':
  3581.                 case 'C':
  3582.                 ActivateGadget(
  3583.                     FindGadget( cwin, 0, GADOCATNAME ),
  3584.                     cwin, 0 );
  3585.                 break;
  3586.                 case 'd':
  3587.                 case 'D':
  3588.                 ActivateGadget(
  3589.                     FindGadget( cwin, 0, GADODOGNAME ),
  3590.                     cwin, 0 );
  3591.                 break;
  3592.                 case 'f':
  3593.                 case 'F':
  3594.                 ActivateGadget(
  3595.                     FindGadget( cwin, 0, GADOFRUIT ),
  3596.                     cwin, 0 );
  3597.                 break;
  3598.                 case 'o':
  3599.                 case 'O':
  3600.                 ActivateGadget(
  3601.                     FindGadget( cwin, 0, GADOOBJECTS ),
  3602.                     cwin, 0 );
  3603.                 break;
  3604.             }
  3605.             }
  3606.             break;
  3607.  
  3608.         case CLOSEWINDOW:
  3609.             done = 1;
  3610.             break;
  3611.  
  3612.         case GADGETUP:
  3613.             switch( gd->GadgetID )
  3614.             {
  3615.             case GADOPACKORDER:
  3616.                 ActivateGadget(
  3617.                 FindGadget( cwin, 0, GADOCATNAME ),
  3618.                 cwin, 0 );
  3619.                 break;
  3620.  
  3621.             case GADOCATNAME:
  3622.                 ActivateGadget(
  3623.                 FindGadget( cwin, 0, GADODOGNAME ),
  3624.                 cwin, 0 );
  3625.                 break;
  3626.  
  3627.             case GADODOGNAME:
  3628.                 ActivateGadget(
  3629.                 FindGadget( cwin, 0, GADOFRUIT ),
  3630.                 cwin, 0 );
  3631.                 break;
  3632.  
  3633.             case GADOFRUIT:
  3634.                 ActivateGadget(
  3635.                 FindGadget( cwin, 0, GADOOBJECTS ),
  3636.                 cwin, 0 );
  3637.                 break;
  3638.  
  3639.             case GADOOBJECTS:
  3640.                 break;
  3641.  
  3642.             case GADOOKAY:
  3643.                 done = 1;
  3644.                 break;
  3645.  
  3646.             case GADOCANCEL:
  3647.                 quit = 1;
  3648.                 done = 1;
  3649.                 break;
  3650.  
  3651.             default:
  3652.                 for( i = 0; optr[i].name; ++i )
  3653.                 {
  3654.                 if( optr[i].id == gd->GadgetID )
  3655.                     break;
  3656.                 }
  3657.  
  3658.                 if( optr[i].name )
  3659.                 {
  3660.                 if( optr[ i ].optstr != NULL )
  3661.                 {
  3662.                     if( optr[i].optstr && *optr[i].optstr )
  3663.                     free( optr[i].optstr );
  3664.  
  3665.                     if( *Sbuff(gd) == 0 )
  3666.                     {
  3667.                     optr[i].optstr = "";
  3668.                     }
  3669.                     else
  3670.                     {
  3671.                     optr[i].optstr = strdup(Sbuff(gd));
  3672.                     }
  3673.                 }
  3674.                 else
  3675.                 {
  3676.                     optr[i].optval =
  3677.                         ( gd->Flags & SELECTED ) != 0;
  3678.                 }
  3679.                 }
  3680.                 break;
  3681.             }
  3682.             break;
  3683.         }
  3684.     }
  3685.     }
  3686.  
  3687.     SafeCloseWindow( cwin );
  3688.     return( quit == 0 );
  3689. }
  3690.  
  3691. /*
  3692.  * Put options structure into a string and then make that the
  3693.  * options[ OPTIONS_IDX ] value
  3694.  */
  3695.  
  3696. void PutOptions( optr )
  3697.     register OPTR optr;
  3698. {
  3699.     register struct Gadget *gd;
  3700.     register int i, olen = 4096, rlen, didone;
  3701.     register char *optbuf;
  3702.  
  3703.     while( olen > 256 )
  3704.     {
  3705.     if( ( optbuf = xmalloc( olen ) ) != NULL )
  3706.     {
  3707.         break;
  3708.     }
  3709.     olen /= 2;
  3710.     }
  3711.  
  3712.     if( optbuf == NULL )
  3713.     {
  3714.     errmsg( FLASH, "No memory left for options buffer" );
  3715.     return;
  3716.     }
  3717.  
  3718.     /* Account for nul terminator */
  3719.     *optbuf = 0;
  3720.  
  3721.     for( i = 0; optr[i].name; ++i )
  3722.     {
  3723.     --olen;
  3724.     didone = 0;
  3725.     rlen = 0;
  3726.     gd = FindGadget( 0, &Options_NewWindowStructure3, optr[i].id );
  3727.  
  3728.     /* If name:value option */
  3729.     if( optr[i].optstr != NULL )
  3730.     {
  3731.         /* If gadget contains some text */
  3732.         if( gd && *Sbuff( gd ) )
  3733.         {
  3734.         /* Free a previously allocated string */
  3735.         if( optr[i].optstr && *optr[i].optstr )
  3736.             free( optr[i].optstr );
  3737.  
  3738.         /* Store "" or save string away */
  3739.         if( *Sbuff(gd) == 0 )
  3740.             optr[i].optstr = "";
  3741.         else
  3742.             optr[i].optstr = strdup(Sbuff(gd));
  3743.  
  3744.         rlen = strlen( optr[i].optstr ) + strlen( optr[i].name ) + 1;
  3745.         if( rlen <= olen )
  3746.         {
  3747.             sprintf( optbuf + strlen(optbuf), "%s:%s",
  3748.             optr[i].name, optr[i].optstr );
  3749.         }
  3750.         didone = 1;
  3751.         }
  3752.     }
  3753.     else
  3754.     {
  3755.         if( optr[i].optval != optr[i].defval )
  3756.         {
  3757.         if( olen >= (rlen = strlen( optr[i].name ) +
  3758.             (optr[i].optval == 0 ) ) )
  3759.         {
  3760.             if( optr[i].optval == 0 )
  3761.             strcat( optbuf, "!" );
  3762.             strcat( optbuf, optr[i].name );
  3763.         }
  3764.         didone = 1;
  3765.         }
  3766.     }
  3767.  
  3768.     if( rlen > olen )
  3769.     {
  3770.         errmsg( FLASH, "Out of space for options" );
  3771.         break;
  3772.     }
  3773.     if( didone )
  3774.         strcat( optbuf, "," );
  3775.     }
  3776.  
  3777.     /* Remove trailing ',' */
  3778.  
  3779.     if( *optbuf )
  3780.     optbuf[ strlen( optbuf ) - 1 ] = 0;
  3781.  
  3782.     setoneopt( OPTIONS_IDX, optbuf );
  3783.     free( optbuf );
  3784. }
  3785.  
  3786. void Game2Defs( gptr )
  3787.     register GPTR gptr;
  3788. {
  3789.     register char *s;
  3790.     register int i;
  3791.  
  3792.     if( defgame.plname )
  3793.     free( defgame.plname );
  3794.     defgame.plname = strdup( ToolsEntry( gptr, "NAME" ) );
  3795.  
  3796.     s = ToolsEntry( gptr, "CHARACTER" );
  3797.     for( i = 0; players[ i ]; ++i )
  3798.     {
  3799.     if( strnicmp( s, players[ i ], strlen(s) ) == 0 )
  3800.         break;
  3801.     }
  3802.  
  3803.     if( players[ i ] )
  3804.     defgame.pltype = i;
  3805.     else
  3806.     defgame.pltype = 0;
  3807.  
  3808.     if( defgame.options )
  3809.     free( defgame.options );
  3810.     defgame.options = strdup( ToolsEntry( gptr, "OPTIONS" ) );
  3811. }
  3812.