OSDN Git Service

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