more DUMPLOG lint
[aNetHack.git] / sys / amiga / winami.c
blob5f32f7711dde879450825c5f893475cc658de5ff
1 /* NetHack 3.6 winami.c $NHDT-Date: 1432512794 2015/05/25 00:13:14 $ $NHDT-Branch: master $:$NHDT-Revision: 1.19 $ */
2 /* Copyright (c) Gregg Wonderly, Naperville, Illinois, 1991,1992,1993,1996.
3 */
4 /* NetHack may be freely redistributed. See license for details. */
6 #include "NH:sys/amiga/windefs.h"
7 #include "NH:sys/amiga/winext.h"
8 #include "NH:sys/amiga/winproto.h"
9 #include "dlb.h"
11 #ifdef AMIGA_INTUITION
13 static int FDECL(put_ext_cmd, (char *, int, struct amii_WinDesc *, int));
15 struct amii_DisplayDesc *amiIDisplay; /* the Amiga Intuition descriptor */
16 struct Rectangle lastinvent, lastmsg;
17 int clipping = 0;
18 int clipx = 0;
19 int clipy = 0;
20 int clipxmax = 0;
21 int clipymax = 0;
22 int scrollmsg = 1;
23 int alwaysinvent = 0;
24 int amii_numcolors;
25 long amii_scrnmode;
27 /* Interface definition, for use by windows.c and winprocs.h to provide
28 * the intuition interface for the amiga...
30 struct window_procs amii_procs = {
31 "amii", WC_COLOR | WC_HILITE_PET | WC_INVERSE, 0L, amii_init_nhwindows,
32 amii_player_selection, amii_askname, amii_get_nh_event,
33 amii_exit_nhwindows, amii_suspend_nhwindows, amii_resume_nhwindows,
34 amii_create_nhwindow, amii_clear_nhwindow, amii_display_nhwindow,
35 amii_destroy_nhwindow, amii_curs, amii_putstr, genl_putmixed,
36 amii_display_file, amii_start_menu, amii_add_menu, amii_end_menu,
37 amii_select_menu, genl_message_menu, amii_update_inventory,
38 amii_mark_synch, amii_wait_synch,
39 #ifdef CLIPPING
40 amii_cliparound,
41 #endif
42 #ifdef POSITIONBAR
43 donull,
44 #endif
45 amii_print_glyph, amii_raw_print, amii_raw_print_bold, amii_nhgetch,
46 amii_nh_poskey, amii_bell, amii_doprev_message, amii_yn_function,
47 amii_getlin, amii_get_ext_cmd, amii_number_pad, amii_delay_output,
48 #ifdef CHANGE_COLOR /* only a Mac option currently */
49 amii_change_color, amii_get_color_string,
50 #endif
51 /* other defs that really should go away (they're tty specific) */
52 amii_delay_output, amii_delay_output, amii_outrip, genl_preference_update,
53 genl_getmsghistory, genl_putmsghistory,
54 #ifdef STATUS_VIA_WINDOWPORT
55 genl_status_init, genl_status_finish, genl_status_enablefield,
56 genl_status_update,
57 #ifdef STATUS_HILITES
58 genl_status_threshold,
59 #endif
60 #endif
61 genl_can_suspend_yes,
64 /* The view window layout uses the same function names so we can use
65 * a shared library to allow the executable to be smaller.
67 struct window_procs amiv_procs = {
68 "amitile", WC_COLOR | WC_HILITE_PET | WC_INVERSE, 0L, amii_init_nhwindows,
69 amii_player_selection, amii_askname, amii_get_nh_event,
70 amii_exit_nhwindows, amii_suspend_nhwindows, amii_resume_nhwindows,
71 amii_create_nhwindow, amii_clear_nhwindow, amii_display_nhwindow,
72 amii_destroy_nhwindow, amii_curs, amii_putstr, genl_putmixed,
73 amii_display_file, amii_start_menu, amii_add_menu, amii_end_menu,
74 amii_select_menu, genl_message_menu, amii_update_inventory,
75 amii_mark_synch, amii_wait_synch,
76 #ifdef CLIPPING
77 amii_cliparound,
78 #endif
79 #ifdef POSITIONBAR
80 donull,
81 #endif
82 amii_print_glyph, amii_raw_print, amii_raw_print_bold, amii_nhgetch,
83 amii_nh_poskey, amii_bell, amii_doprev_message, amii_yn_function,
84 amii_getlin, amii_get_ext_cmd, amii_number_pad, amii_delay_output,
85 #ifdef CHANGE_COLOR /* only a Mac option currently */
86 amii_change_color, amii_get_color_string,
87 #endif
88 /* other defs that really should go away (they're tty specific) */
89 amii_delay_output, amii_delay_output, amii_outrip, genl_preference_update,
90 genl_getmsghistory, genl_putmsghistory,
91 #ifdef STATUS_VIA_WINDOWPORT
92 genl_status_init, genl_status_finish, genl_status_enablefield,
93 genl_status_update,
94 #ifdef STATUS_HILITES
95 genl_status_threshold,
96 #endif
97 #endif
98 genl_can_suspend_yes,
101 unsigned short amii_initmap[AMII_MAXCOLORS];
102 /* Default pens used unless user overides in nethack.cnf. */
103 unsigned short amii_init_map[AMII_MAXCOLORS] = {
104 0x0000, /* color #0 C_BLACK */
105 0x0FFF, /* color #1 C_WHITE */
106 0x0830, /* color #2 C_BROWN */
107 0x07ac, /* color #3 C_CYAN */
108 0x0181, /* color #4 C_GREEN */
109 0x0C06, /* color #5 C_MAGENTA */
110 0x023E, /* color #6 C_BLUE */
111 0x0c00, /* color #7 C_RED */
114 unsigned short amiv_init_map[AMII_MAXCOLORS] = {
115 0x0000, /* color #0 C_BLACK */
116 0x0fff, /* color #1 C_WHITE */
117 0x00bf, /* color #2 C_CYAN */
118 0x0f60, /* color #3 C_ORANGE */
119 0x000f, /* color #4 C_BLUE */
120 0x0090, /* color #5 C_GREEN */
121 0x069b, /* color #6 C_GREY */
122 0x0f00, /* color #7 C_RED */
123 0x06f0, /* color #8 C_LTGREEN */
124 0x0ff0, /* color #9 C_YELLOW */
125 0x0f0f, /* color #10 C_MAGENTA */
126 0x0940, /* color #11 C_BROWN */
127 0x0466, /* color #12 C_GREYBLUE */
128 0x0c40, /* color #13 C_LTBROWN */
129 0x0ddb, /* color #14 C_LTGREY */
130 0x0fb9, /* color #15 C_PEACH */
132 /* Pens for dripens etc under AA or better */
133 0x0222, /* color #16 */
134 0x0fdc, /* color #17 */
135 0x0000, /* color #18 */
136 0x0ccc, /* color #19 */
137 0x0bbb, /* color #20 */
138 0x0BA9, /* color #21 */
139 0x0999, /* color #22 */
140 0x0987, /* color #23 */
141 0x0765, /* color #24 */
142 0x0666, /* color #25 */
143 0x0555, /* color #26 */
144 0x0533, /* color #27 */
145 0x0333, /* color #28 */
146 0x018f, /* color #29 */
147 0x0f81, /* color #30 */
148 0x0fff, /* color #31 */
151 #if !defined(TTY_GRAPHICS) \
152 || defined(SHAREDLIB) /* this should be shared better */
153 char morc; /* the character typed in response to a --more-- prompt */
154 #endif
155 char spaces[76] = " "
156 " ";
158 winid WIN_BASE = WIN_ERR;
159 winid WIN_OVER = WIN_ERR;
160 winid amii_rawprwin = WIN_ERR;
162 /* Changed later during window/screen opens... */
163 int txwidth = FONTWIDTH, txheight = FONTHEIGHT, txbaseline = FONTBASELINE;
165 /* If a 240 or more row screen is in front when we start, this will be
166 * set to 1, and the windows will be given borders to allow them to be
167 * arranged differently. The Message window may eventually get a scroller...
169 int bigscreen = 0;
171 /* This gadget data is replicated for menu/text windows... */
172 struct PropInfo PropScroll = {
173 AUTOKNOB | FREEVERT, 0xffff, 0xffff, 0xffff, 0xffff,
175 struct Image Image1 = { 0, 0, 7, 102, 0, NULL, 0x0000, 0x0000, NULL };
176 struct Gadget MenuScroll = { NULL, -15, 10, 15, -19, GRELRIGHT | GRELHEIGHT,
177 RELVERIFY | FOLLOWMOUSE | RIGHTBORDER
178 | GADGIMMEDIATE | RELVERIFY,
179 PROPGADGET, (APTR) &Image1, NULL, NULL, NULL,
180 (APTR) &PropScroll, 1, NULL };
182 /* This gadget is for the message window... */
183 struct PropInfo MsgPropScroll = {
184 AUTOKNOB | FREEVERT, 0xffff, 0xffff, 0xffff, 0xffff,
186 struct Image MsgImage1 = { 0, 0, 7, 102, 0, NULL, 0x0000, 0x0000, NULL };
187 struct Gadget MsgScroll = { NULL, -15, 10, 14, -19, GRELRIGHT | GRELHEIGHT,
188 RELVERIFY | FOLLOWMOUSE | RIGHTBORDER
189 | GADGIMMEDIATE | RELVERIFY,
190 PROPGADGET, (APTR) &MsgImage1, NULL, NULL, NULL,
191 (APTR) &MsgPropScroll, 1, NULL };
193 int wincnt = 0; /* # of nh windows opened */
195 /* We advertise a public screen to allow some people to do other things
196 * while they are playing... like compiling...
199 #ifdef INTUI_NEW_LOOK
200 extern struct Hook fillhook;
201 struct TagItem tags[] = {
202 { WA_BackFill, (ULONG) &fillhook },
203 { WA_PubScreenName, (ULONG) "NetHack" },
204 { TAG_DONE, 0 },
206 #endif
209 * The default dimensions and status values for each window type. The
210 * data here is generally changed in create_nhwindow(), so beware that
211 * what you see here may not be exactly what you get.
213 struct win_setup new_wins[] = {
215 /* First entry not used, types are based at 1 */
216 { { 0 } },
218 /* NHW_MESSAGE */
219 { { 0, 1, 640, 11, 0xff, 0xff,
220 NEWSIZE | GADGETUP | GADGETDOWN | MOUSEMOVE | MOUSEBUTTONS | RAWKEY,
221 BORDERLESS | ACTIVATE | SMART_REFRESH
222 #ifdef INTUI_NEW_LOOK
223 | WFLG_NW_EXTENDED
224 #endif
226 NULL, NULL, (UBYTE *) "Messages", NULL, NULL, 320, 40, 0xffff, 0xffff,
227 #ifdef INTUI_NEW_LOOK
228 PUBLICSCREEN, tags
229 #else
230 CUSTOMSCREEN
231 #endif
238 80 },
240 /* NHW_STATUS */
241 { { 0, 181, 640, 24, 0xff, 0xff, RAWKEY | MENUPICK | DISKINSERTED,
242 BORDERLESS | ACTIVATE | SMART_REFRESH | BACKDROP
243 #ifdef INTUI_NEW_LOOK
244 | WFLG_NW_EXTENDED
245 #endif
247 NULL, NULL, (UBYTE *) "Game Status", NULL, NULL, 0, 0, 0xffff, 0xffff,
248 #ifdef INTUI_NEW_LOOK
249 PUBLICSCREEN, tags
250 #else
251 CUSTOMSCREEN
252 #endif
259 78 },
261 /* NHW_MAP */
262 { { 0, 0, WIDTH, WINDOWHEIGHT, 0xff, 0xff,
263 RAWKEY | MENUPICK | MOUSEBUTTONS | ACTIVEWINDOW | MOUSEMOVE,
264 BORDERLESS | ACTIVATE | SMART_REFRESH | BACKDROP
265 #ifdef INTUI_NEW_LOOK
266 | WFLG_NW_EXTENDED
267 #endif
269 NULL, NULL, (UBYTE *) "Dungeon Map", NULL, NULL, 64, 64, 0xffff,
270 0xffff,
271 #ifdef INTUI_NEW_LOOK
272 PUBLICSCREEN, tags
273 #else
274 CUSTOMSCREEN
275 #endif
282 80 },
284 /* NHW_MENU */
285 { { 400, 10, 10, 10, 0xff, 0xff,
286 RAWKEY | MENUPICK | DISKINSERTED | MOUSEMOVE | MOUSEBUTTONS | GADGETUP
287 | GADGETDOWN | CLOSEWINDOW | VANILLAKEY | NEWSIZE
288 | INACTIVEWINDOW,
289 WINDOWSIZING | WINDOWCLOSE | WINDOWDRAG | ACTIVATE | SMART_REFRESH
290 #ifdef INTUI_NEW_LOOK
291 | WFLG_NW_EXTENDED
292 #endif
294 &MenuScroll, NULL, NULL, NULL, NULL, 64, 32, 0xffff, 0xffff,
295 #ifdef INTUI_NEW_LOOK
296 PUBLICSCREEN, tags
297 #else
298 CUSTOMSCREEN
299 #endif
306 78 },
308 /* NHW_TEXT */
309 { { 0, 0, 640, 200, 0xff, 0xff,
310 RAWKEY | MENUPICK | DISKINSERTED | MOUSEMOVE | GADGETUP | CLOSEWINDOW
311 | VANILLAKEY | NEWSIZE,
312 WINDOWSIZING | WINDOWCLOSE | WINDOWDRAG | ACTIVATE | SMART_REFRESH
313 #ifdef INTUI_NEW_LOOK
314 | WFLG_NW_EXTENDED
315 #endif
317 &MenuScroll, NULL, (UBYTE *) NULL, NULL, NULL, 100, 32, 0xffff,
318 0xffff,
319 #ifdef INTUI_NEW_LOOK
320 PUBLICSCREEN, tags
321 #else
322 CUSTOMSCREEN
323 #endif
330 78 },
332 /* NHW_BASE */
333 { { 0, 0, WIDTH, WINDOWHEIGHT, 0xff, 0xff,
334 RAWKEY | MENUPICK | MOUSEBUTTONS,
335 BORDERLESS | ACTIVATE | SMART_REFRESH | BACKDROP
336 #ifdef INTUI_NEW_LOOK
337 | WFLG_NW_EXTENDED
338 #endif
340 NULL, NULL, (UBYTE *) NULL, NULL, NULL, -1, -1, 0xffff, 0xffff,
341 #ifdef INTUI_NEW_LOOK
342 PUBLICSCREEN, tags
343 #else
344 CUSTOMSCREEN
345 #endif
352 80 },
354 /* NHW_OVER */
355 { { 320, 20, 319, 179, 0xff, 0xff, RAWKEY | MENUPICK | MOUSEBUTTONS,
356 BORDERLESS | ACTIVATE | SMART_REFRESH | BACKDROP
357 #ifdef INTUI_NEW_LOOK
358 | WFLG_NW_EXTENDED
359 #endif
361 NULL, NULL, (UBYTE *) NULL, NULL, NULL, 64, 32, 0xffff, 0xffff,
362 #ifdef INTUI_NEW_LOOK
363 PUBLICSCREEN, tags
364 #else
365 CUSTOMSCREEN
366 #endif
373 80 },
376 const char winpanicstr[] = "Bad winid %d in %s()";
378 /* The opened windows information */
379 struct amii_WinDesc *amii_wins[MAXWIN + 1];
381 #ifdef INTUI_NEW_LOOK
383 * NUMDRIPENS varies based on headers, so don't use it
384 * here, its value is used elsewhere.
386 UWORD amii_defpens[20];
388 struct TagItem scrntags[] = {
389 { SA_PubName, (ULONG) "NetHack" },
390 { SA_Overscan, OSCAN_TEXT },
391 { SA_AutoScroll, TRUE },
392 #if LIBRARY_VERSION >= 39
393 { SA_Interleaved, TRUE },
394 #endif
395 { SA_Pens, (ULONG) 0 },
396 { SA_DisplayID, 0 },
397 { TAG_DONE, 0 },
400 #endif
402 struct NewScreen NewHackScreen = { 0, 0, WIDTH, SCREENHEIGHT, 3, 0,
403 1, /* DetailPen, BlockPen */
404 HIRES, CUSTOMSCREEN
405 #ifdef INTUI_NEW_LOOK
406 | NS_EXTENDED
407 #endif
409 &Hack80, /* Font */
410 NULL, /*(UBYTE *)" NetHack X.Y.Z" */
411 NULL, /* Gadgets */
412 NULL, /* CustomBitmap */
413 #ifdef INTUI_NEW_LOOK
414 scrntags
415 #endif
419 * plname is filled either by an option (-u Player or -uPlayer) or
420 * explicitly (by being the wizard) or by askname.
421 * It may still contain a suffix denoting pl_character.
422 * Always called after init_nhwindows() and before display_gamewindows().
424 void
425 amii_askname()
427 char plnametmp[300]; /* From winreq.c: sizeof(StrStringSIBuff) */
428 *plnametmp = 0;
429 do {
430 amii_getlin("Who are you?", plnametmp);
431 } while (strlen(plnametmp) == 0);
433 strncpy(plname, plnametmp, PL_NSIZ - 1); /* Avoid overflowing plname[] */
434 plname[PL_NSIZ - 1] = 0;
436 if (*plname == '\33') {
437 clearlocks();
438 exit_nhwindows(NULL);
439 terminate(0);
443 /* Discarded ... -jhsa
444 #include "NH:sys/amiga/char.c"
447 /* Get the player selection character */
449 #if 0 /* New function at the bottom */
450 void
451 amii_player_selection()
453 register struct Window *cwin;
454 register struct IntuiMessage *imsg;
455 register int aredone = 0;
456 register struct Gadget *gd;
457 static int once = 0;
458 long class, code;
460 amii_clear_nhwindow( WIN_BASE );
461 if (validrole(flags.initrole))
462 return;
463 else {
464 flags.initrole=randrole();
465 return;
467 #if 0 /* Don't query the user ... instead give random character -jhsa */
469 #if 0 /* OBSOLETE */
470 if( *pl_character ){
471 pl_character[ 0 ] = toupper( pl_character[ 0 ] );
472 if( index( pl_classes, pl_character[ 0 ] ) )
473 return;
475 #endif
477 if( !once ){
478 if( bigscreen ){
479 Type_NewWindowStructure1.TopEdge =
480 (HackScreen->Height/2) - (Type_NewWindowStructure1.Height/2);
482 for( gd = Type_NewWindowStructure1.FirstGadget; gd;
483 gd = gd->NextGadget )
485 if( gd->GadgetID != 0 )
486 SetBorder( gd );
488 once = 1;
491 if( WINVERS_AMIV )
493 #ifdef INTUI_NEW_LOOK
494 Type_NewWindowStructure1.Extension = wintags;
495 Type_NewWindowStructure1.Flags |= WFLG_NW_EXTENDED;
496 fillhook.h_Entry = (ULONG(*)())LayerFillHook;
497 fillhook.h_Data = (void *)-2;
498 fillhook.h_SubEntry = 0;
499 #endif
502 Type_NewWindowStructure1.Screen = HackScreen;
503 if( ( cwin = OpenShWindow( (void *)&Type_NewWindowStructure1 ) ) == NULL )
505 return;
507 #if 0
508 WindowToFront( cwin );
509 #endif
511 while( !aredone )
513 WaitPort( cwin->UserPort );
514 while( ( imsg = (void *) GetMsg( cwin->UserPort ) ) != NULL )
516 class = imsg->Class;
517 code = imsg->Code;
518 gd = (struct Gadget *)imsg->IAddress;
519 ReplyMsg( (struct Message *)imsg );
521 switch( class )
523 case VANILLAKEY:
524 if( index( pl_classes, toupper( code ) ) )
526 pl_character[0] = toupper( code );
527 aredone = 1;
529 else if( code == ' ' || code == '\n' || code == '\r' )
531 flags.initrole = randrole();
532 #if 0 /* OBSOLETE */
533 strcpy( pl_character, roles[ rnd( 11 ) ] );
534 #endif
535 aredone = 1;
536 amii_clear_nhwindow( WIN_BASE );
537 CloseShWindow( cwin );
538 RandomWindow( pl_character );
539 return;
541 else if( code == 'q' || code == 'Q' )
543 CloseShWindow( cwin );
544 clearlocks();
545 exit_nhwindows(NULL);
546 terminate(0);
548 else
549 DisplayBeep( NULL );
550 break;
552 case GADGETUP:
553 switch( gd->GadgetID )
555 case 1: /* Random Character */
556 flags.initrole = randrole();
557 #if 0 /* OBSOLETE */
558 strcpy( pl_character, roles[ rnd( 11 ) ] );
559 #endif
560 amii_clear_nhwindow( WIN_BASE );
561 CloseShWindow( cwin );
562 RandomWindow( pl_character );
563 return;
565 default:
566 pl_character[0] = gd->GadgetID;
567 break;
569 aredone = 1;
570 break;
572 case CLOSEWINDOW:
573 CloseShWindow( cwin );
574 clearlocks();
575 exit_nhwindows(NULL);
576 terminate(0);
577 break;
581 amii_clear_nhwindow( WIN_BASE );
582 CloseShWindow( cwin );
583 #endif /* Do not query user ... -jhsa */
585 #endif /* Function elsewhere */
587 #if 0 /* Unused ... -jhsa */
589 #include "NH:sys/amiga/randwin.c"
591 void
592 RandomWindow( name )
593 char *name;
595 struct MsgPort *tport;
596 struct timerequest *trq;
597 static int once = 0;
598 struct Gadget *gd;
599 struct Window *w;
600 struct IntuiMessage *imsg;
601 int ticks = 0, aredone = 0, timerdone = 0;
602 long mask, got;
604 tport = CreateMsgPort();
605 trq = (struct timerequest *)CreateIORequest( tport, sizeof( *trq ) );
606 if( tport == NULL || trq == NULL )
608 allocerr:
609 if( tport ) DeleteMsgPort( tport );
610 if( trq ) DeleteIORequest( (struct IORequest *)trq );
611 Delay( 8 * 50 );
612 return;
615 if( OpenDevice( TIMERNAME, UNIT_VBLANK, (struct IORequest *)trq, 0L ) != 0 )
616 goto allocerr;
618 trq->tr_node.io_Command = TR_ADDREQUEST;
619 trq->tr_time.tv_secs = 8;
620 trq->tr_time.tv_micro = 0;
622 SendIO( (struct IORequest *)trq );
624 /* Place the name in the center of the screen */
625 Rnd_IText5.IText = name;
626 Rnd_IText6.LeftEdge = Rnd_IText4.LeftEdge +
627 (strlen(Rnd_IText4.IText)+1)*8;
628 Rnd_NewWindowStructure1.Width = (
629 (strlen( Rnd_IText2.IText )+1) * 8 ) +
630 HackScreen->WBorLeft + HackScreen->WBorRight;
631 Rnd_IText5.LeftEdge = (Rnd_NewWindowStructure1.Width -
632 (strlen(name)*8))/2;
634 gd = Rnd_NewWindowStructure1.FirstGadget;
635 gd->LeftEdge = (Rnd_NewWindowStructure1.Width - gd->Width)/2;
636 /* Chose correct modifier */
637 Rnd_IText6.IText = "a";
638 switch( *name )
640 case 'a': case 'e': case 'i': case 'o':
641 case 'u': case 'A': case 'E': case 'I':
642 case 'O': case 'U':
643 Rnd_IText6.IText = "an";
644 break;
647 if( !once )
649 if( bigscreen )
651 Rnd_NewWindowStructure1.TopEdge =
652 (HackScreen->Height/2) - (Rnd_NewWindowStructure1.Height/2);
654 for( gd = Rnd_NewWindowStructure1.FirstGadget; gd; gd = gd->NextGadget )
656 if( gd->GadgetID != 0 )
657 SetBorder( gd );
659 Rnd_NewWindowStructure1.IDCMPFlags |= VANILLAKEY;
661 once = 1;
664 if( WINVERS_AMIV )
666 #ifdef INTUI_NEW_LOOK
667 Rnd_NewWindowStructure1.Extension = wintags;
668 Rnd_NewWindowStructure1.Flags |= WFLG_NW_EXTENDED;
669 fillhook.h_Entry = (ULONG(*)())LayerFillHook;
670 fillhook.h_Data = (void *)-2;
671 fillhook.h_SubEntry = 0;
672 #endif
675 Rnd_NewWindowStructure1.Screen = HackScreen;
676 if( ( w = OpenShWindow( (void *)&Rnd_NewWindowStructure1 ) ) == NULL )
678 AbortIO( (struct IORequest *)trq );
679 WaitIO( (struct IORequest *)trq );
680 CloseDevice( (struct IORequest *)trq );
681 DeleteIORequest( (struct IORequest *) trq );
682 DeleteMsgPort( tport );
683 Delay( 50 * 8 );
684 return;
687 PrintIText( w->RPort, &Rnd_IntuiTextList1, 0, 0 );
689 mask = (1L << tport->mp_SigBit)|(1L << w->UserPort->mp_SigBit);
690 while( !aredone )
692 got = Wait( mask );
693 if( got & (1L << tport->mp_SigBit ) )
695 aredone = 1;
696 timerdone = 1;
697 GetMsg( tport );
699 while( w && ( imsg = (struct IntuiMessage *) GetMsg( w->UserPort ) ) )
701 switch( (long)imsg->Class )
703 /* Must be up for a little while... */
704 case INACTIVEWINDOW:
705 if( ticks >= 40 )
706 aredone = 1;
707 break;
709 case INTUITICKS:
710 ++ticks;
711 break;
713 case GADGETUP:
714 aredone = 1;
715 break;
717 case VANILLAKEY:
718 if(imsg->Code=='\n' || imsg->Code==' ' || imsg->Code=='\r')
719 aredone = 1;
720 break;
722 ReplyMsg( (struct Message *)imsg );
726 if( !timerdone )
728 AbortIO( (struct IORequest *)trq );
729 WaitIO( (struct IORequest *)trq );
732 CloseDevice( (struct IORequest *)trq );
733 DeleteIORequest( (struct IORequest *) trq );
734 DeleteMsgPort( tport );
735 if(w) CloseShWindow( w );
737 #endif /* Discarded randwin ... -jhsa */
739 /* this should probably not be needed (or be renamed)
740 void
741 flush_output(){} */
743 /* Read in an extended command - doing command line completion for
744 * when enough characters have been entered to make a unique command.
747 amii_get_ext_cmd(void)
749 menu_item *mip;
750 anything id;
751 struct amii_WinDesc *cw;
752 #ifdef EXTMENU
753 winid win;
754 int i;
755 char buf[256];
756 #endif
757 int colx;
758 int bottom = 0;
759 struct Window *w;
760 char obufp[100];
761 register char *bufp = obufp;
762 register int c;
763 int com_index, oindex;
764 int did_comp = 0; /* did successful completion? */
765 int sel = -1;
767 if (WIN_MESSAGE == WIN_ERR || (cw = amii_wins[WIN_MESSAGE]) == NULL)
768 panic(winpanicstr, WIN_MESSAGE, "get_ext_cmd");
769 w = cw->win;
770 bottom = amii_msgborder(w);
771 colx = 3;
773 #ifdef EXTMENU
774 if (iflags.extmenu) {
775 win = amii_create_nhwindow(NHW_MENU);
776 amii_start_menu(win);
777 pline("#");
778 amii_putstr(WIN_MESSAGE, -1, " ");
780 for (i = 0; extcmdlist[i].ef_txt != NULL; ++i) {
781 id.a_char = *extcmdlist[i].ef_txt;
782 sprintf(buf, "%-10s - %s ", extcmdlist[i].ef_txt,
783 extcmdlist[i].ef_desc);
784 amii_add_menu(win, NO_GLYPH, &id, extcmdlist[i].ef_txt[0], 0, 0,
785 buf, MENU_UNSELECTED);
788 amii_end_menu(win, (char *) 0);
789 sel = amii_select_menu(win, PICK_ONE, &mip);
790 amii_destroy_nhwindow(win);
792 if (sel == 1) {
793 sel = mip->item.a_char;
794 for (i = 0; extcmdlist[i].ef_txt != NULL; ++i) {
795 if (sel == extcmdlist[i].ef_txt[0])
796 break;
799 /* copy in the text */
800 if (extcmdlist[i].ef_txt != NULL) {
801 amii_clear_nhwindow(WIN_MESSAGE);
802 (void) put_ext_cmd((char *) extcmdlist[i].ef_txt, 0, cw,
803 bottom);
804 return (i);
805 } else
806 DisplayBeep(NULL);
809 return (-1);
810 } else {
811 #else
813 amii_clear_nhwindow(WIN_MESSAGE); /* Was NHW_MESSAGE */
814 if (scrollmsg) {
815 pline("#");
816 amii_addtopl(" ");
817 } else {
818 pline("# ");
821 sel = -1;
822 while ((c = WindowGetchar()) != EOF) {
823 amii_curs(WIN_MESSAGE, colx, bottom);
824 if (c == '?') {
825 int win, i;
826 char buf[100];
828 if (did_comp) {
829 while (bufp != obufp) {
830 bufp--;
831 amii_curs(WIN_MESSAGE, --colx, bottom);
832 Text(w->RPort, spaces, 1);
833 amii_curs(WIN_MESSAGE, colx, bottom);
834 did_comp = 0;
838 win = amii_create_nhwindow(NHW_MENU);
839 amii_start_menu(win);
841 for (i = 0; extcmdlist[i].ef_txt != NULL; ++i) {
842 id.a_char = extcmdlist[i].ef_txt[0];
843 sprintf(buf, "%-10s - %s ", extcmdlist[i].ef_txt,
844 extcmdlist[i].ef_desc);
845 amii_add_menu(win, NO_GLYPH, &id, extcmdlist[i].ef_txt[0], 0,
846 0, buf, MENU_UNSELECTED);
849 amii_end_menu(win, (char *) 0);
850 sel = amii_select_menu(win, PICK_ONE, &mip);
851 amii_destroy_nhwindow(win);
853 if (sel == 0) {
854 return (-1);
855 } else {
856 sel = mip->item.a_char;
857 for (i = 0; extcmdlist[i].ef_txt != NULL; ++i) {
858 if (sel == extcmdlist[i].ef_txt[0])
859 break;
862 /* copy in the text */
863 if (extcmdlist[i].ef_txt != NULL) {
864 amii_clear_nhwindow(WIN_MESSAGE);
865 strcpy(bufp = obufp, extcmdlist[i].ef_txt);
866 (void) put_ext_cmd(obufp, colx, cw, bottom);
867 return (i);
868 } else
869 DisplayBeep(NULL);
871 } else if (c == '\033') {
872 return (-1);
873 } else if (c == '\b') {
874 if (did_comp) {
875 while (bufp != obufp) {
876 bufp--;
877 amii_curs(WIN_MESSAGE, --colx, bottom);
878 Text(w->RPort, spaces, 1);
879 amii_curs(WIN_MESSAGE, colx, bottom);
880 did_comp = 0;
881 sel = -1;
883 } else if (bufp != obufp) {
884 sel = -1;
885 bufp--;
886 amii_curs(WIN_MESSAGE, --colx, bottom);
887 Text(w->RPort, spaces, 1);
888 amii_curs(WIN_MESSAGE, colx, bottom);
889 } else
890 DisplayBeep(NULL);
891 } else if (c == '\n' || c == '\r') {
892 return (sel);
893 } else if (c >= ' ' && c < '\177') {
894 /* avoid isprint() - some people don't have it
895 ' ' is not always a printing char */
896 *bufp = c;
897 bufp[1] = 0;
898 oindex = 0;
899 com_index = -1;
901 while (extcmdlist[oindex].ef_txt != NULL) {
902 if (!strnicmp(obufp, (char *) extcmdlist[oindex].ef_txt,
903 strlen(obufp))) {
904 if (com_index == -1) /* No matches yet*/
905 com_index = oindex;
906 else /* More than 1 match */
907 com_index = -2;
909 oindex++;
912 if (com_index >= 0 && *obufp) {
913 Strcpy(obufp, extcmdlist[com_index].ef_txt);
914 /* finish printing our string */
915 colx = put_ext_cmd(obufp, colx, cw, bottom);
916 bufp = obufp; /* reset it */
917 if (strlen(obufp) < BUFSZ - 1 && strlen(obufp) < COLNO)
918 bufp += strlen(obufp);
919 did_comp = 1;
920 sel = com_index;
921 } else {
922 colx = put_ext_cmd(obufp, colx, cw, bottom);
923 if (bufp - obufp < BUFSZ - 1 && bufp - obufp < COLNO)
924 bufp++;
926 } else if (c == ('X' - 64) || c == '\177') {
927 colx = 0;
928 amii_clear_nhwindow(WIN_MESSAGE);
929 pline("# ");
930 bufp = obufp;
931 } else
932 DisplayBeep(NULL);
934 return (-1);
935 #endif
938 static int put_ext_cmd(obufp, colx, cw, bottom) char * obufp;
939 int colx, bottom;
940 struct amii_WinDesc *cw;
942 struct Window *w = cw->win;
943 char *t;
945 t = (char *) alloc(strlen(obufp) + 7);
946 if (t != NULL) {
947 if (scrollmsg) {
948 sprintf(t, "xxx%s", obufp);
949 t[0] = 1;
950 t[1] = 1;
951 t[2] = '#';
952 amii_curs(WIN_MESSAGE, 0, bottom);
953 SetAPen(w->RPort, C_WHITE);
954 Text(w->RPort, "># ", 3);
955 /* SetAPen( w->RPort, C_BLACK ); */ /* Black text on black
956 screen doesn't look too
957 well ... -jhsa */
958 Text(w->RPort, t + 3, strlen(t) - 3);
959 } else {
960 sprintf(t, "# %s", obufp);
961 amii_curs(WIN_MESSAGE, 0, bottom);
962 SetAPen(w->RPort, C_WHITE);
963 Text(w->RPort, t, strlen(t));
965 if (scrollmsg)
966 SetAPen(w->RPort, C_WHITE);
967 if (cw->data[cw->maxrow - 1])
968 free(cw->data[cw->maxrow - 1]);
969 cw->data[cw->maxrow - 1] = t;
970 } else {
971 amii_curs(WIN_MESSAGE, 0, bottom);
972 SetAPen(w->RPort, C_WHITE);
973 Text(w->RPort, "# ", 2);
974 /* SetAPen( w->RPort, C_BLACK ); */ /* Black on black ... -jhsa */
975 Text(w->RPort, obufp, strlen(obufp));
976 SetAPen(w->RPort, C_WHITE);
978 amii_curs(WIN_MESSAGE, colx = strlen(obufp) + 3 + (scrollmsg != 0),
979 bottom);
980 return (colx);
983 /* Ask a question and get a response */
985 char amii_yn_function(query, resp, def) const char * query, *resp;
986 char def;
988 * Generic yes/no function. 'def' is the default (returned by space or
989 * return; 'esc' returns 'q', or 'n', or the default, depending on
990 * what's in the string. The 'query' string is printed before the user
991 * is asked about the string.
992 * If resp is NULL, any single character is accepted and returned.
993 * If not-NULL, only characters in it are allowed (exceptions: the
994 * quitchars are always allowed, and if it contains '#' then digits
995 * are allowed); if it includes an <esc>, anything beyond that won't
996 * be shown in the prompt to the user but will be acceptable as input.
999 register char q;
1000 char rtmp[40];
1001 boolean digit_ok, allow_num;
1002 char prompt[BUFSZ];
1003 register struct amii_WinDesc *cw;
1005 if (cw = amii_wins[WIN_MESSAGE])
1006 cw->disprows = 0;
1007 if (resp) {
1008 char *rb, respbuf[QBUFSZ];
1010 allow_num = (index(resp, '#') != 0);
1011 Strcpy(respbuf, resp);
1012 /* any acceptable responses that follow <esc> aren't displayed */
1013 if ((rb = index(respbuf, '\033')) != 0)
1014 *rb = '\0';
1015 (void) strncpy(prompt, query, QBUFSZ - 1);
1016 prompt[QBUFSZ - 1] = '\0';
1017 Sprintf(eos(prompt), " [%s]", respbuf);
1018 if (def)
1019 Sprintf(eos(prompt), " (%c)", def);
1020 Strcat(prompt, " ");
1021 pline("%s", prompt);
1022 } else {
1023 amii_putstr(WIN_MESSAGE, 0, query);
1024 cursor_on(WIN_MESSAGE);
1025 q = WindowGetchar();
1026 cursor_off(WIN_MESSAGE);
1027 *rtmp = q;
1028 rtmp[1] = 0;
1029 amii_addtopl(rtmp);
1030 goto clean_up;
1033 do { /* loop until we get valid input */
1034 cursor_on(WIN_MESSAGE);
1035 q = lowc(WindowGetchar());
1036 cursor_off(WIN_MESSAGE);
1037 #if 0
1038 /* fix for PL2 */
1039 if (q == '\020') { /* ctrl-P */
1040 if(!doprev) (void) tty_doprev_message(); /* need two initially */
1041 (void) tty_doprev_message();
1042 q = (char)0;
1043 doprev = 1;
1044 continue;
1045 } else if(doprev) {
1046 tty_clear_nhwindow(WIN_MESSAGE);
1047 cw->maxcol = cw->maxrow;
1048 doprev = 0;
1049 amii_addtopl(prompt);
1050 continue;
1052 #endif
1053 digit_ok = allow_num && isdigit(q);
1054 if (q == '\033') {
1055 if (index(resp, 'q'))
1056 q = 'q';
1057 else if (index(resp, 'n'))
1058 q = 'n';
1059 else
1060 q = def;
1061 break;
1062 } else if (index(quitchars, q)) {
1063 q = def;
1064 break;
1066 if (!index(resp, q) && !digit_ok) {
1067 amii_bell();
1068 q = (char) 0;
1069 } else if (q == '#' || digit_ok) {
1070 char z, digit_string[2];
1071 int n_len = 0;
1072 long value = 0;
1073 amii_addtopl("#"), n_len++;
1074 digit_string[1] = '\0';
1075 if (q != '#') {
1076 digit_string[0] = q;
1077 amii_addtopl(digit_string), n_len++;
1078 value = q - '0';
1079 q = '#';
1081 do { /* loop until we get a non-digit */
1082 cursor_on(WIN_MESSAGE);
1083 z = lowc(WindowGetchar());
1084 cursor_off(WIN_MESSAGE);
1085 if (isdigit(z)) {
1086 value = (10 * value) + (z - '0');
1087 if (value < 0)
1088 break; /* overflow: try again */
1089 digit_string[0] = z;
1090 amii_addtopl(digit_string), n_len++;
1091 } else if (z == 'y' || index(quitchars, z)) {
1092 if (z == '\033')
1093 value = -1; /* abort */
1094 z = '\n'; /* break */
1095 } else if (z == '\b') {
1096 if (n_len <= 1) {
1097 value = -1;
1098 break;
1099 } else {
1100 value /= 10;
1101 removetopl(1), n_len--;
1103 } else {
1104 value = -1; /* abort */
1105 amii_bell();
1106 break;
1108 } while (z != '\n');
1109 if (value > 0)
1110 yn_number = value;
1111 else if (value == 0)
1112 q = 'n'; /* 0 => "no" */
1113 else { /* remove number from top line, then try again */
1114 removetopl(n_len), n_len = 0;
1115 q = '\0';
1118 } while (!q);
1120 if (q != '#' && q != '\033') {
1121 Sprintf(rtmp, "%c", q);
1122 amii_addtopl(rtmp);
1124 clean_up:
1125 cursor_off(WIN_MESSAGE);
1126 clear_nhwindow(WIN_MESSAGE);
1127 return q;
1130 void amii_display_file(fn, complain) const char * fn;
1131 boolean complain;
1133 register struct amii_WinDesc *cw;
1134 register int win;
1135 register dlb *fp;
1136 register char *t;
1137 register char buf[200];
1139 if (fn == NULL)
1140 panic("NULL file name in display_file()");
1142 if ((fp = dlb_fopen(fn, RDTMODE)) == (dlb *) NULL) {
1143 if (complain) {
1144 sprintf(buf, "Can't display %s: %s", fn,
1145 #if defined(_DCC) || defined(__GNUC__)
1146 strerror(errno)
1147 #else
1148 #ifdef __SASC_60
1149 __sys_errlist[errno]
1150 #else
1151 sys_errlist[errno]
1152 #endif
1153 #endif
1155 amii_addtopl(buf);
1157 return;
1159 win = amii_create_nhwindow(NHW_TEXT);
1161 /* Set window title to file name */
1162 if (cw = amii_wins[win])
1163 cw->morestr = (char *) fn;
1165 while (dlb_fgets(buf, sizeof(buf), fp) != NULL) {
1166 if (t = index(buf, '\n'))
1167 *t = 0;
1168 amii_putstr(win, 0, buf);
1170 dlb_fclose(fp);
1172 /* If there were lines in the file, display those lines */
1174 if (amii_wins[win]->cury > 0)
1175 amii_display_nhwindow(win, TRUE);
1177 amii_wins[win]->morestr = NULL; /* don't free title string */
1178 amii_destroy_nhwindow(win);
1181 /* Put a 3-D motif border around the gadget. String gadgets or those
1182 * which do not have highlighting are rendered down. Boolean gadgets
1183 * are rendered in the up position by default.
1186 void SetBorder(gd) register struct Gadget * gd;
1188 register struct Border *bp;
1189 register short *sp;
1190 register int i, inc = -1, dec = -1;
1191 int borders = 6;
1192 int hipen = sysflags.amii_dripens[SHINEPEN],
1193 shadowpen = sysflags.amii_dripens[SHADOWPEN];
1194 #ifdef INTUI_NEW_LOOK
1195 struct DrawInfo *dip;
1196 #endif
1198 #ifdef INTUI_NEW_LOOK
1199 if (IntuitionBase->LibNode.lib_Version >= 37) {
1200 if (dip = GetScreenDrawInfo(HackScreen)) {
1201 hipen = dip->dri_Pens[SHINEPEN];
1202 shadowpen = dip->dri_Pens[SHADOWPEN];
1203 FreeScreenDrawInfo(HackScreen, dip);
1206 #endif
1207 /* Allocate two border structures one for up image and one for down
1208 * image, plus vector arrays for the border lines.
1211 if (gd->GadgetType == STRGADGET)
1212 borders = 12;
1214 if ((bp = (struct Border *) alloc(((sizeof(struct Border) * 2)
1215 + (sizeof(short) * borders)) * 2))
1216 == NULL) {
1217 return;
1220 /* For a string gadget, we expand the border beyond the area where
1221 * the text will be entered.
1224 /* Remove any special rendering flags to avoid confusing intuition
1227 gd->Flags &= ~(GADGHIGHBITS | GADGIMAGE);
1229 sp = (short *) (bp + 4);
1230 if (gd->GadgetType == STRGADGET
1231 || (gd->GadgetType == BOOLGADGET
1232 && (gd->Flags & GADGHIGHBITS) == GADGHNONE)) {
1233 sp[0] = -1;
1234 sp[1] = gd->Height - 1;
1235 sp[2] = -1;
1236 sp[3] = -1;
1237 sp[4] = gd->Width - 1;
1238 sp[5] = -1;
1240 sp[6] = gd->Width + 1;
1241 sp[7] = -2;
1242 sp[8] = gd->Width + 1;
1243 sp[9] = gd->Height + 1;
1244 sp[10] = -2;
1245 sp[11] = gd->Height + 1;
1247 sp[12] = -2;
1248 sp[13] = gd->Height;
1249 sp[14] = -2;
1250 sp[15] = -2;
1251 sp[16] = gd->Width;
1252 sp[17] = -2;
1253 sp[18] = gd->Width;
1254 sp[19] = gd->Height;
1255 sp[20] = -2;
1256 sp[21] = gd->Height;
1258 for (i = 0; i < 3; ++i) {
1259 bp[i].LeftEdge = bp[i].TopEdge = -1;
1260 bp[i].FrontPen = (i == 0 || i == 1) ? shadowpen : hipen;
1262 /* Have to use JAM2 so that the old colors disappear. */
1263 bp[i].BackPen = C_BLACK;
1264 bp[i].DrawMode = JAM2;
1265 bp[i].Count = (i == 0 || i == 1) ? 3 : 5;
1266 bp[i].XY = &sp[i * 6];
1267 bp[i].NextBorder = (i == 2) ? NULL : &bp[i + 1];
1270 /* bp[0] and bp[1] two pieces for the up image */
1271 gd->GadgetRender = (APTR) bp;
1273 /* No image change for select */
1274 gd->SelectRender = (APTR) bp;
1276 gd->LeftEdge++;
1277 gd->TopEdge++;
1278 gd->Flags |= GADGHCOMP;
1279 } else {
1280 /* Create the border vector values for up and left side, and
1281 * also the lower and right side.
1284 sp[0] = dec;
1285 sp[1] = gd->Height + inc;
1286 sp[2] = dec;
1287 sp[3] = dec;
1288 sp[4] = gd->Width + inc;
1289 sp[5] = dec;
1291 sp[6] = gd->Width + inc;
1292 sp[7] = dec;
1293 sp[8] = gd->Width + inc;
1294 sp[9] = gd->Height + inc;
1295 sp[10] = dec;
1296 sp[11] = gd->Height + inc;
1298 /* We are creating 4 sets of borders, the two sides of the
1299 * rectangle share the border vectors with the opposite image,
1300 * but specify different colors.
1303 for (i = 0; i < 4; ++i) {
1304 bp[i].TopEdge = bp[i].LeftEdge = 0;
1306 /* A GADGHNONE is always down */
1308 if (gd->GadgetType == BOOLGADGET
1309 && (gd->Flags & GADGHIGHBITS) != GADGHNONE) {
1310 bp[i].FrontPen = (i == 1 || i == 2) ? shadowpen : hipen;
1311 } else {
1312 bp[i].FrontPen = (i == 1 || i == 3) ? hipen : shadowpen;
1315 /* Have to use JAM2 so that the old colors disappear. */
1316 bp[i].BackPen = C_BLACK;
1317 bp[i].DrawMode = JAM2;
1318 bp[i].Count = 3;
1319 bp[i].XY = &sp[6 * ((i & 1) != 0)];
1320 bp[i].NextBorder = (i == 1 || i == 3) ? NULL : &bp[i + 1];
1323 /* bp[0] and bp[1] two pieces for the up image */
1324 gd->GadgetRender = (APTR) bp;
1326 /* bp[2] and bp[3] two pieces for the down image */
1327 gd->SelectRender = (APTR)(bp + 2);
1328 gd->Flags |= GADGHIMAGE;
1332 /* Following function copied from wintty.c */
1333 /* Modified slightly to fit amiga needs */
1335 void amii_player_selection()
1337 int i, k, n;
1338 char pick4u = 'n', thisch, lastch = 0;
1339 char pbuf[QBUFSZ], plbuf[QBUFSZ], rolenamebuf[QBUFSZ];
1340 winid win;
1341 anything any;
1342 menu_item *selected = 0;
1344 rigid_role_checks();
1346 /* Should we randomly pick for the player? */
1347 if (flags.initrole == ROLE_NONE || flags.initrace == ROLE_NONE
1348 || flags.initgend == ROLE_NONE || flags.initalign == ROLE_NONE) {
1349 char *prompt = build_plselection_prompt(
1350 pbuf, QBUFSZ, flags.initrole, flags.initrace, flags.initgend,
1351 flags.initalign);
1352 pline("%s", prompt);
1353 do { /* loop until we get valid input */
1354 cursor_on(WIN_MESSAGE);
1355 pick4u = lowc(WindowGetchar());
1356 cursor_off(WIN_MESSAGE);
1357 if (index(quitchars, pick4u))
1358 pick4u = 'y';
1359 } while (!index(ynqchars, pick4u));
1360 pbuf[0] = pick4u;
1361 pbuf[1] = 0;
1362 amii_addtopl(pbuf);
1364 if (pick4u != 'y' && pick4u != 'n') {
1365 give_up: /* Quit */
1366 if (selected)
1367 free((genericptr_t) selected);
1368 clearlocks();
1369 exit_nhwindows(NULL);
1370 terminate(0);
1371 /*NOTREACHED*/
1372 return;
1376 (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole,
1377 flags.initrace, flags.initgend,
1378 flags.initalign);
1380 /* Select a role, if necessary */
1381 /* we'll try to be compatible with pre-selected race/gender/alignment,
1382 * but may not succeed */
1383 if (flags.initrole < 0) {
1384 /* Process the choice */
1385 if (pick4u == 'y' || flags.initrole == ROLE_RANDOM
1386 || flags.randomall) {
1387 /* Pick a random role */
1388 flags.initrole = pick_role(flags.initrace, flags.initgend,
1389 flags.initalign, PICK_RANDOM);
1390 if (flags.initrole < 0) {
1391 amii_putstr(WIN_MESSAGE, 0, "Incompatible role!");
1392 flags.initrole = randrole();
1394 } else {
1395 /* Prompt for a role */
1396 win = create_nhwindow(NHW_MENU);
1397 start_menu(win);
1398 any.a_void = 0; /* zero out all bits */
1399 for (i = 0; roles[i].name.m; i++) {
1400 if (ok_role(i, flags.initrace, flags.initgend,
1401 flags.initalign)) {
1402 any.a_int = i + 1; /* must be non-zero */
1403 thisch = lowc(roles[i].name.m[0]);
1404 if (thisch == lastch)
1405 thisch = highc(thisch);
1406 if (flags.initgend != ROLE_NONE
1407 && flags.initgend != ROLE_RANDOM) {
1408 if (flags.initgend == 1 && roles[i].name.f)
1409 Strcpy(rolenamebuf, roles[i].name.f);
1410 else
1411 Strcpy(rolenamebuf, roles[i].name.m);
1412 } else {
1413 if (roles[i].name.f) {
1414 Strcpy(rolenamebuf, roles[i].name.m);
1415 Strcat(rolenamebuf, "/");
1416 Strcat(rolenamebuf, roles[i].name.f);
1417 } else
1418 Strcpy(rolenamebuf, roles[i].name.m);
1420 add_menu(win, NO_GLYPH, &any, thisch, 0, ATR_NONE,
1421 an(rolenamebuf), MENU_UNSELECTED);
1422 lastch = thisch;
1425 any.a_int = pick_role(flags.initrace, flags.initgend,
1426 flags.initalign, PICK_RANDOM) + 1;
1427 if (any.a_int == 0) /* must be non-zero */
1428 any.a_int = randrole() + 1;
1429 add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random",
1430 MENU_UNSELECTED);
1431 any.a_int = i + 1; /* must be non-zero */
1432 add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit",
1433 MENU_UNSELECTED);
1434 Sprintf(pbuf, "Pick a role for your %s", plbuf);
1435 end_menu(win, pbuf);
1436 n = select_menu(win, PICK_ONE, &selected);
1437 destroy_nhwindow(win);
1439 /* Process the choice */
1440 if (n != 1 || selected[0].item.a_int == any.a_int)
1441 goto give_up; /* Selected quit */
1443 flags.initrole = selected[0].item.a_int - 1;
1444 free((genericptr_t) selected), selected = 0;
1446 (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole,
1447 flags.initrace, flags.initgend,
1448 flags.initalign);
1451 /* Select a race, if necessary */
1452 /* force compatibility with role, try for compatibility with
1453 * pre-selected gender/alignment */
1454 if (flags.initrace < 0
1455 || !validrace(flags.initrole, flags.initrace)) {
1456 /* pre-selected race not valid */
1457 if (pick4u == 'y' || flags.initrace == ROLE_RANDOM
1458 || flags.randomall) {
1459 flags.initrace = pick_race(flags.initrole, flags.initgend,
1460 flags.initalign, PICK_RANDOM);
1461 if (flags.initrace < 0) {
1462 amii_putstr(WIN_MESSAGE, 0, "Incompatible race!");
1463 flags.initrace = randrace(flags.initrole);
1465 } else { /* pick4u == 'n' */
1466 /* Count the number of valid races */
1467 n = 0; /* number valid */
1468 k = 0; /* valid race */
1469 for (i = 0; races[i].noun; i++) {
1470 if (ok_race(flags.initrole, i, flags.initgend,
1471 flags.initalign)) {
1472 n++;
1473 k = i;
1476 if (n == 0) {
1477 for (i = 0; races[i].noun; i++) {
1478 if (validrace(flags.initrole, i)) {
1479 n++;
1480 k = i;
1485 /* Permit the user to pick, if there is more than one */
1486 if (n > 1) {
1487 win = create_nhwindow(NHW_MENU);
1488 start_menu(win);
1489 any.a_void = 0; /* zero out all bits */
1490 for (i = 0; races[i].noun; i++)
1491 if (ok_race(flags.initrole, i, flags.initgend,
1492 flags.initalign)) {
1493 any.a_int = i + 1; /* must be non-zero */
1494 add_menu(win, NO_GLYPH, &any, races[i].noun[0], 0,
1495 ATR_NONE, races[i].noun,
1496 MENU_UNSELECTED);
1498 any.a_int = pick_race(flags.initrole, flags.initgend,
1499 flags.initalign, PICK_RANDOM) + 1;
1500 if (any.a_int == 0) /* must be non-zero */
1501 any.a_int = randrace(flags.initrole) + 1;
1502 add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random",
1503 MENU_UNSELECTED);
1504 any.a_int = i + 1; /* must be non-zero */
1505 add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit",
1506 MENU_UNSELECTED);
1507 Sprintf(pbuf, "Pick the race of your %s", plbuf);
1508 end_menu(win, pbuf);
1509 n = select_menu(win, PICK_ONE, &selected);
1510 destroy_nhwindow(win);
1511 if (n != 1 || selected[0].item.a_int == any.a_int)
1512 goto give_up; /* Selected quit */
1514 k = selected[0].item.a_int - 1;
1515 free((genericptr_t) selected), selected = 0;
1517 flags.initrace = k;
1519 (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole,
1520 flags.initrace, flags.initgend,
1521 flags.initalign);
1524 /* Select a gender, if necessary */
1525 /* force compatibility with role/race, try for compatibility with
1526 * pre-selected alignment */
1527 if (flags.initgend < 0
1528 || !validgend(flags.initrole, flags.initrace, flags.initgend)) {
1529 /* pre-selected gender not valid */
1530 if (pick4u == 'y' || flags.initgend == ROLE_RANDOM
1531 || flags.randomall) {
1532 flags.initgend = pick_gend(flags.initrole, flags.initrace,
1533 flags.initalign, PICK_RANDOM);
1534 if (flags.initgend < 0) {
1535 amii_putstr(WIN_MESSAGE, 0, "Incompatible gender!");
1536 flags.initgend = randgend(flags.initrole, flags.initrace);
1538 } else { /* pick4u == 'n' */
1539 /* Count the number of valid genders */
1540 n = 0; /* number valid */
1541 k = 0; /* valid gender */
1542 for (i = 0; i < ROLE_GENDERS; i++) {
1543 if (ok_gend(flags.initrole, flags.initrace, i,
1544 flags.initalign)) {
1545 n++;
1546 k = i;
1549 if (n == 0) {
1550 for (i = 0; i < ROLE_GENDERS; i++) {
1551 if (validgend(flags.initrole, flags.initrace, i)) {
1552 n++;
1553 k = i;
1558 /* Permit the user to pick, if there is more than one */
1559 if (n > 1) {
1560 win = create_nhwindow(NHW_MENU);
1561 start_menu(win);
1562 any.a_void = 0; /* zero out all bits */
1563 for (i = 0; i < ROLE_GENDERS; i++)
1564 if (ok_gend(flags.initrole, flags.initrace, i,
1565 flags.initalign)) {
1566 any.a_int = i + 1;
1567 add_menu(win, NO_GLYPH, &any, genders[i].adj[0],
1568 0, ATR_NONE, genders[i].adj,
1569 MENU_UNSELECTED);
1571 any.a_int = pick_gend(flags.initrole, flags.initrace,
1572 flags.initalign, PICK_RANDOM) + 1;
1573 if (any.a_int == 0) /* must be non-zero */
1574 any.a_int =
1575 randgend(flags.initrole, flags.initrace) + 1;
1576 add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random",
1577 MENU_UNSELECTED);
1578 any.a_int = i + 1; /* must be non-zero */
1579 add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit",
1580 MENU_UNSELECTED);
1581 Sprintf(pbuf, "Pick the gender of your %s", plbuf);
1582 end_menu(win, pbuf);
1583 n = select_menu(win, PICK_ONE, &selected);
1584 destroy_nhwindow(win);
1585 if (n != 1 || selected[0].item.a_int == any.a_int)
1586 goto give_up; /* Selected quit */
1588 k = selected[0].item.a_int - 1;
1589 free((genericptr_t) selected), selected = 0;
1591 flags.initgend = k;
1593 (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole,
1594 flags.initrace, flags.initgend,
1595 flags.initalign);
1598 /* Select an alignment, if necessary */
1599 /* force compatibility with role/race/gender */
1600 if (flags.initalign < 0
1601 || !validalign(flags.initrole, flags.initrace, flags.initalign)) {
1602 /* pre-selected alignment not valid */
1603 if (pick4u == 'y' || flags.initalign == ROLE_RANDOM
1604 || flags.randomall) {
1605 flags.initalign = pick_align(flags.initrole, flags.initrace,
1606 flags.initgend, PICK_RANDOM);
1607 if (flags.initalign < 0) {
1608 amii_putstr(WIN_MESSAGE, 0, "Incompatible alignment!");
1609 flags.initalign =
1610 randalign(flags.initrole, flags.initrace);
1612 } else { /* pick4u == 'n' */
1613 /* Count the number of valid alignments */
1614 n = 0; /* number valid */
1615 k = 0; /* valid alignment */
1616 for (i = 0; i < ROLE_ALIGNS; i++) {
1617 if (ok_align(flags.initrole, flags.initrace,
1618 flags.initgend, i)) {
1619 n++;
1620 k = i;
1623 if (n == 0) {
1624 for (i = 0; i < ROLE_ALIGNS; i++) {
1625 if (validalign(flags.initrole, flags.initrace, i)) {
1626 n++;
1627 k = i;
1632 /* Permit the user to pick, if there is more than one */
1633 if (n > 1) {
1634 win = create_nhwindow(NHW_MENU);
1635 start_menu(win);
1636 any.a_void = 0; /* zero out all bits */
1637 for (i = 0; i < ROLE_ALIGNS; i++)
1638 if (ok_align(flags.initrole, flags.initrace,
1639 flags.initgend, i)) {
1640 any.a_int = i + 1;
1641 add_menu(win, NO_GLYPH, &any, aligns[i].adj[0], 0,
1642 ATR_NONE, aligns[i].adj,
1643 MENU_UNSELECTED);
1645 any.a_int = pick_align(flags.initrole, flags.initrace,
1646 flags.initgend, PICK_RANDOM) + 1;
1647 if (any.a_int == 0) /* must be non-zero */
1648 any.a_int =
1649 randalign(flags.initrole, flags.initrace) + 1;
1650 add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random",
1651 MENU_UNSELECTED);
1652 any.a_int = i + 1; /* must be non-zero */
1653 add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit",
1654 MENU_UNSELECTED);
1655 Sprintf(pbuf, "Pick the alignment of your %s", plbuf);
1656 end_menu(win, pbuf);
1657 n = select_menu(win, PICK_ONE, &selected);
1658 destroy_nhwindow(win);
1659 if (n != 1 || selected[0].item.a_int == any.a_int)
1660 goto give_up; /* Selected quit */
1662 k = selected[0].item.a_int - 1;
1663 free((genericptr_t) selected), selected = 0;
1665 flags.initalign = k;
1668 /* Success! */
1670 #endif /* AMIGA_INTUITION */