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