OSDN Git Service

5f32f7711dde879450825c5f893475cc658de5ff
[jnethack/source.git] / sys / amiga / winami.c
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. */
5
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"
10
11 #ifdef AMIGA_INTUITION
12
13 static int FDECL(put_ext_cmd, (char *, int, struct amii_WinDesc *, int));
14
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;
26
27 /* Interface definition, for use by windows.c and winprocs.h to provide
28  * the intuition interface for the amiga...
29  */
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,
62 };
63
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.
66  */
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,
99 };
100
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      */
112 };
113
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    */
131
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 */
149 };
150
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                   "                 ";
157
158 winid WIN_BASE = WIN_ERR;
159 winid WIN_OVER = WIN_ERR;
160 winid amii_rawprwin = WIN_ERR;
161
162 /* Changed later during window/screen opens... */
163 int txwidth = FONTWIDTH, txheight = FONTHEIGHT, txbaseline = FONTBASELINE;
164
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...
168  */
169 int bigscreen = 0;
170
171 /* This gadget data is replicated for menu/text windows... */
172 struct PropInfo PropScroll = {
173     AUTOKNOB | FREEVERT, 0xffff, 0xffff, 0xffff, 0xffff,
174 };
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 };
181
182 /* This gadget is for the message window... */
183 struct PropInfo MsgPropScroll = {
184     AUTOKNOB | FREEVERT, 0xffff, 0xffff, 0xffff, 0xffff,
185 };
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 };
192
193 int wincnt = 0; /* # of nh windows opened */
194
195 /* We advertise a public screen to allow some people to do other things
196  * while they are playing...  like compiling...
197  */
198
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 },
205 };
206 #endif
207
208 /*
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.
212  */
213 struct win_setup new_wins[] = {
214
215     /* First entry not used, types are based at 1 */
216     { { 0 } },
217
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
225         ,
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
232       },
233       0,
234       0,
235       1,
236       1,
237       80,
238       80 },
239
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
246         ,
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
253       },
254       0,
255       0,
256       2,
257       2,
258       78,
259       78 },
260
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
268         ,
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
276       },
277       0,
278       0,
279       22,
280       22,
281       80,
282       80 },
283
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
293         ,
294         &MenuScroll, NULL, NULL, NULL, NULL, 64, 32, 0xffff, 0xffff,
295 #ifdef INTUI_NEW_LOOK
296         PUBLICSCREEN, tags
297 #else
298         CUSTOMSCREEN
299 #endif
300       },
301       0,
302       0,
303       1,
304       1,
305       22,
306       78 },
307
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
316         ,
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
324       },
325       0,
326       0,
327       1,
328       1,
329       22,
330       78 },
331
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
339         ,
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
346       },
347       0,
348       0,
349       22,
350       22,
351       80,
352       80 },
353
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
360         ,
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
367       },
368       0,
369       0,
370       22,
371       22,
372       80,
373       80 },
374 };
375
376 const char winpanicstr[] = "Bad winid %d in %s()";
377
378 /* The opened windows information */
379 struct amii_WinDesc *amii_wins[MAXWIN + 1];
380
381 #ifdef INTUI_NEW_LOOK
382 /*
383  * NUMDRIPENS varies based on headers, so don't use it
384  * here, its value is used elsewhere.
385  */
386 UWORD amii_defpens[20];
387
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 },
398 };
399
400 #endif
401
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
408                                    ,
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
416 };
417
418 /*
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().
423  */
424 void
425 amii_askname()
426 {
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);
432
433     strncpy(plname, plnametmp, PL_NSIZ - 1); /* Avoid overflowing plname[] */
434     plname[PL_NSIZ - 1] = 0;
435
436     if (*plname == '\33') {
437         clearlocks();
438         exit_nhwindows(NULL);
439         terminate(0);
440     }
441 }
442
443 /* Discarded ... -jhsa
444 #include "NH:sys/amiga/char.c"
445 */
446
447 /* Get the player selection character */
448
449 #if 0 /* New function at the bottom */
450 void
451 amii_player_selection()
452 {
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;
459
460     amii_clear_nhwindow( WIN_BASE );
461     if (validrole(flags.initrole))
462         return;
463     else {
464         flags.initrole=randrole();
465         return;
466     }
467 #if 0 /* Don't query the user ... instead give random character -jhsa */
468
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;
474     }
475 #endif
476
477     if( !once ){
478         if( bigscreen ){
479             Type_NewWindowStructure1.TopEdge =
480               (HackScreen->Height/2) - (Type_NewWindowStructure1.Height/2);
481         }
482         for( gd = Type_NewWindowStructure1.FirstGadget; gd;
483           gd = gd->NextGadget )
484         {
485             if( gd->GadgetID != 0 )
486                 SetBorder( gd );
487         }
488         once = 1;
489     }
490
491     if( WINVERS_AMIV )
492     {
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
500     }
501
502     Type_NewWindowStructure1.Screen = HackScreen;
503     if( ( cwin = OpenShWindow( (void *)&Type_NewWindowStructure1 ) ) == NULL )
504     {
505         return;
506     }
507 #if 0
508     WindowToFront( cwin );
509 #endif
510
511     while( !aredone )
512     {
513         WaitPort( cwin->UserPort );
514         while( ( imsg = (void *) GetMsg( cwin->UserPort ) ) != NULL )
515         {
516             class = imsg->Class;
517             code = imsg->Code;
518             gd = (struct Gadget *)imsg->IAddress;
519             ReplyMsg( (struct Message *)imsg );
520
521             switch( class )
522             {
523             case VANILLAKEY:
524                 if( index( pl_classes, toupper( code ) ) )
525                 {
526                     pl_character[0] = toupper( code );
527                     aredone = 1;
528                 }
529                 else if( code == ' ' || code == '\n' || code == '\r' )
530                 {
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;
540                 }
541                 else if( code == 'q' || code == 'Q' )
542                 {
543                 CloseShWindow( cwin );
544                 clearlocks();
545                 exit_nhwindows(NULL);
546                 terminate(0);
547                 }
548                 else
549                     DisplayBeep( NULL );
550                 break;
551
552             case GADGETUP:
553                 switch( gd->GadgetID )
554                 {
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;
564
565                 default:
566                     pl_character[0] = gd->GadgetID;
567                     break;
568                 }
569                 aredone = 1;
570                 break;
571
572             case CLOSEWINDOW:
573                 CloseShWindow( cwin );
574                 clearlocks();
575                 exit_nhwindows(NULL);
576                 terminate(0);
577                 break;
578             }
579         }
580     }
581     amii_clear_nhwindow( WIN_BASE );
582     CloseShWindow( cwin );
583 #endif /* Do not query user ... -jhsa */
584 }
585 #endif /* Function elsewhere */
586
587 #if 0 /* Unused ... -jhsa */
588
589 #include "NH:sys/amiga/randwin.c"
590
591 void
592 RandomWindow( name )
593     char *name;
594 {
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;
603
604     tport = CreateMsgPort();
605     trq = (struct timerequest *)CreateIORequest( tport, sizeof( *trq ) );
606     if( tport == NULL || trq == NULL )
607     {
608 allocerr:
609         if( tport ) DeleteMsgPort( tport );
610         if( trq ) DeleteIORequest( (struct IORequest *)trq );
611         Delay( 8 * 50 );
612         return;
613     }
614
615     if( OpenDevice( TIMERNAME, UNIT_VBLANK, (struct IORequest *)trq, 0L ) != 0 )
616         goto allocerr;
617
618     trq->tr_node.io_Command = TR_ADDREQUEST;
619     trq->tr_time.tv_secs = 8;
620     trq->tr_time.tv_micro = 0;
621
622     SendIO( (struct IORequest *)trq );
623
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;
633
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 )
639     {
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;
645     }
646
647     if( !once )
648     {
649         if( bigscreen )
650         {
651             Rnd_NewWindowStructure1.TopEdge =
652                 (HackScreen->Height/2) - (Rnd_NewWindowStructure1.Height/2);
653         }
654         for( gd = Rnd_NewWindowStructure1.FirstGadget; gd; gd = gd->NextGadget )
655         {
656             if( gd->GadgetID != 0 )
657                 SetBorder( gd );
658         }
659         Rnd_NewWindowStructure1.IDCMPFlags |= VANILLAKEY;
660
661         once = 1;
662     }
663
664     if( WINVERS_AMIV )
665     {
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
673     }
674
675     Rnd_NewWindowStructure1.Screen = HackScreen;
676     if( ( w = OpenShWindow( (void *)&Rnd_NewWindowStructure1 ) ) == NULL )
677     {
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;
685     }
686
687     PrintIText( w->RPort, &Rnd_IntuiTextList1, 0, 0 );
688
689     mask = (1L << tport->mp_SigBit)|(1L << w->UserPort->mp_SigBit);
690     while( !aredone )
691     {
692         got = Wait( mask );
693         if( got & (1L << tport->mp_SigBit ) )
694         {
695             aredone = 1;
696             timerdone = 1;
697             GetMsg( tport );
698         }
699         while( w && ( imsg = (struct IntuiMessage *) GetMsg( w->UserPort ) ) )
700         {
701             switch( (long)imsg->Class )
702             {
703                 /* Must be up for a little while... */
704             case INACTIVEWINDOW:
705                 if( ticks >= 40 )
706                     aredone = 1;
707                 break;
708
709             case INTUITICKS:
710                 ++ticks;
711                 break;
712
713             case GADGETUP:
714                 aredone = 1;
715                 break;
716
717             case VANILLAKEY:
718                 if(imsg->Code=='\n' || imsg->Code==' ' || imsg->Code=='\r')
719                     aredone = 1;
720                 break;
721             }
722             ReplyMsg( (struct Message *)imsg );
723         }
724     }
725
726     if( !timerdone )
727     {
728         AbortIO( (struct IORequest *)trq );
729         WaitIO( (struct IORequest *)trq );
730     }
731
732     CloseDevice( (struct IORequest *)trq );
733     DeleteIORequest( (struct IORequest *) trq );
734     DeleteMsgPort( tport );
735     if(w) CloseShWindow( w );
736 }
737 #endif /* Discarded randwin ... -jhsa */
738
739 /* this should probably not be needed (or be renamed)
740 void
741 flush_output(){} */
742
743 /* Read in an extended command - doing command line completion for
744  * when enough characters have been entered to make a unique command.
745  */
746 int
747 amii_get_ext_cmd(void)
748 {
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;
766
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;
772
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, " ");
779
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);
786         }
787
788         amii_end_menu(win, (char *) 0);
789         sel = amii_select_menu(win, PICK_ONE, &mip);
790         amii_destroy_nhwindow(win);
791
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;
797             }
798
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);
807         }
808
809         return (-1);
810     } else {
811 #else
812
813     amii_clear_nhwindow(WIN_MESSAGE); /* Was NHW_MESSAGE */
814     if (scrollmsg) {
815         pline("#");
816         amii_addtopl(" ");
817     } else {
818         pline("# ");
819     }
820
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];
827
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;
835                 }
836             }
837
838             win = amii_create_nhwindow(NHW_MENU);
839             amii_start_menu(win);
840
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);
847             }
848
849             amii_end_menu(win, (char *) 0);
850             sel = amii_select_menu(win, PICK_ONE, &mip);
851             amii_destroy_nhwindow(win);
852
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;
860                 }
861
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);
870             }
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;
882                 }
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;
900
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;
908                 }
909                 oindex++;
910             }
911
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++;
925             }
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);
933     }
934     return (-1);
935 #endif
936     }
937
938     static int put_ext_cmd(obufp, colx, cw, bottom) char * obufp;
939     int colx, bottom;
940     struct amii_WinDesc *cw;
941     {
942         struct Window *w = cw->win;
943         char *t;
944
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));
964             }
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);
977         }
978         amii_curs(WIN_MESSAGE, colx = strlen(obufp) + 3 + (scrollmsg != 0),
979                   bottom);
980         return (colx);
981     }
982
983     /* Ask a question and get a response */
984
985     char amii_yn_function(query, resp, def) const char * query, *resp;
986     char def;
987     /*
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.
997      */
998     {
999         register char q;
1000         char rtmp[40];
1001         boolean digit_ok, allow_num;
1002         char prompt[BUFSZ];
1003         register struct amii_WinDesc *cw;
1004
1005         if (cw = amii_wins[WIN_MESSAGE])
1006             cw->disprows = 0;
1007         if (resp) {
1008             char *rb, respbuf[QBUFSZ];
1009
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;
1031         }
1032
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;
1051             }
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;
1065             }
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 = '#';
1080                 }
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--;
1102                         }
1103                     } else {
1104                         value = -1; /* abort */
1105                         amii_bell();
1106                         break;
1107                     }
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';
1116                 }
1117             }
1118         } while (!q);
1119
1120         if (q != '#' && q != '\033') {
1121             Sprintf(rtmp, "%c", q);
1122             amii_addtopl(rtmp);
1123         }
1124     clean_up:
1125         cursor_off(WIN_MESSAGE);
1126         clear_nhwindow(WIN_MESSAGE);
1127         return q;
1128     }
1129
1130     void amii_display_file(fn, complain) const char * fn;
1131     boolean complain;
1132     {
1133         register struct amii_WinDesc *cw;
1134         register int win;
1135         register dlb *fp;
1136         register char *t;
1137         register char buf[200];
1138
1139         if (fn == NULL)
1140             panic("NULL file name in display_file()");
1141
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
1154                             );
1155                 amii_addtopl(buf);
1156             }
1157             return;
1158         }
1159         win = amii_create_nhwindow(NHW_TEXT);
1160
1161         /* Set window title to file name */
1162         if (cw = amii_wins[win])
1163             cw->morestr = (char *) fn;
1164
1165         while (dlb_fgets(buf, sizeof(buf), fp) != NULL) {
1166             if (t = index(buf, '\n'))
1167                 *t = 0;
1168             amii_putstr(win, 0, buf);
1169         }
1170         dlb_fclose(fp);
1171
1172         /* If there were lines in the file, display those lines */
1173
1174         if (amii_wins[win]->cury > 0)
1175             amii_display_nhwindow(win, TRUE);
1176
1177         amii_wins[win]->morestr = NULL; /* don't free title string */
1178         amii_destroy_nhwindow(win);
1179     }
1180
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.
1184      */
1185
1186     void SetBorder(gd) register struct Gadget * gd;
1187     {
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
1197
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);
1204             }
1205         }
1206 #endif
1207         /* Allocate two border structures one for up image and one for down
1208          * image, plus vector arrays for the border lines.
1209          */
1210
1211         if (gd->GadgetType == STRGADGET)
1212             borders = 12;
1213
1214         if ((bp = (struct Border *) alloc(((sizeof(struct Border) * 2)
1215                                            + (sizeof(short) * borders)) * 2))
1216             == NULL) {
1217             return;
1218         }
1219
1220         /* For a string gadget, we expand the border beyond the area where
1221          * the text will be entered.
1222          */
1223
1224         /* Remove any special rendering flags to avoid confusing intuition
1225          */
1226
1227         gd->Flags &= ~(GADGHIGHBITS | GADGIMAGE);
1228
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;
1239
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;
1246
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;
1257
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;
1261
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];
1268             }
1269
1270             /* bp[0] and bp[1] two pieces for the up image */
1271             gd->GadgetRender = (APTR) bp;
1272
1273             /* No image change for select */
1274             gd->SelectRender = (APTR) bp;
1275
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.
1282              */
1283
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;
1290
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;
1297
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.
1301              */
1302
1303             for (i = 0; i < 4; ++i) {
1304                 bp[i].TopEdge = bp[i].LeftEdge = 0;
1305
1306                 /* A GADGHNONE is always down */
1307
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;
1313                 }
1314
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];
1321             }
1322
1323             /* bp[0] and bp[1] two pieces for the up image */
1324             gd->GadgetRender = (APTR) bp;
1325
1326             /* bp[2] and bp[3] two pieces for the down image */
1327             gd->SelectRender = (APTR)(bp + 2);
1328             gd->Flags |= GADGHIMAGE;
1329         }
1330     }
1331
1332     /* Following function copied from wintty.c */
1333     /* Modified slightly to fit amiga needs */
1334
1335     void amii_player_selection()
1336     {
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;
1343
1344         rigid_role_checks();
1345
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);
1363
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;
1373             }
1374         }
1375
1376         (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole,
1377                                        flags.initrace, flags.initgend,
1378                                        flags.initalign);
1379
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();
1393                 }
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);
1419                         }
1420                         add_menu(win, NO_GLYPH, &any, thisch, 0, ATR_NONE,
1421                                  an(rolenamebuf), MENU_UNSELECTED);
1422                         lastch = thisch;
1423                     }
1424                 }
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);
1438
1439                 /* Process the choice */
1440                 if (n != 1 || selected[0].item.a_int == any.a_int)
1441                     goto give_up; /* Selected quit */
1442
1443                 flags.initrole = selected[0].item.a_int - 1;
1444                 free((genericptr_t) selected), selected = 0;
1445             }
1446             (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole,
1447                                            flags.initrace, flags.initgend,
1448                                            flags.initalign);
1449         }
1450
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);
1464                 }
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;
1474                     }
1475                 }
1476                 if (n == 0) {
1477                     for (i = 0; races[i].noun; i++) {
1478                         if (validrace(flags.initrole, i)) {
1479                             n++;
1480                             k = i;
1481                         }
1482                     }
1483                 }
1484
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);
1497                         }
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 */
1513
1514                     k = selected[0].item.a_int - 1;
1515                     free((genericptr_t) selected), selected = 0;
1516                 }
1517                 flags.initrace = k;
1518             }
1519             (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole,
1520                                            flags.initrace, flags.initgend,
1521                                            flags.initalign);
1522         }
1523
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);
1537                 }
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;
1547                     }
1548                 }
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;
1554                         }
1555                     }
1556                 }
1557
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);
1570                         }
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 */
1587
1588                     k = selected[0].item.a_int - 1;
1589                     free((genericptr_t) selected), selected = 0;
1590                 }
1591                 flags.initgend = k;
1592             }
1593             (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole,
1594                                            flags.initrace, flags.initgend,
1595                                            flags.initalign);
1596         }
1597
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);
1611                 }
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;
1621                     }
1622                 }
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;
1628                         }
1629                     }
1630                 }
1631
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);
1644                         }
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 */
1661
1662                     k = selected[0].item.a_int - 1;
1663                     free((genericptr_t) selected), selected = 0;
1664                 }
1665                 flags.initalign = k;
1666             }
1667         }
1668         /* Success! */
1669     }
1670 #endif /* AMIGA_INTUITION */