OSDN Git Service

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