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