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. */
5 #include "NH:sys/amiga/windefs.h"
6 #include "NH:sys/amiga/winext.h"
7 #include "NH:sys/amiga/winproto.h"
10 #ifdef AMIGA_INTUITION
12 static int FDECL( put_ext_cmd, ( char *, int, struct amii_WinDesc *, int ) );
14 struct amii_DisplayDesc *amiIDisplay; /* the Amiga Intuition descriptor */
15 struct Rectangle lastinvent, lastmsg;
26 /* Interface definition, for use by windows.c and winprocs.h to provide
27 * the intuition interface for the amiga...
29 struct window_procs amii_procs =
32 WC_COLOR|WC_HILITE_PET|WC_INVERSE,
35 amii_player_selection,
39 amii_suspend_nhwindows,
40 amii_resume_nhwindows,
43 amii_display_nhwindow,
44 amii_destroy_nhwindow,
53 amii_update_inventory,
74 #ifdef CHANGE_COLOR /* only a Mac option currently */
76 amii_get_color_string,
78 /* other defs that really should go away (they're tty specific) */
82 genl_preference_update
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.
88 struct window_procs amiv_procs =
91 WC_COLOR|WC_HILITE_PET|WC_INVERSE,
94 amii_player_selection,
98 amii_suspend_nhwindows,
99 amii_resume_nhwindows,
100 amii_create_nhwindow,
102 amii_display_nhwindow,
103 amii_destroy_nhwindow,
112 amii_update_inventory,
133 #ifdef CHANGE_COLOR /* only a Mac option currently */
135 amii_get_color_string,
137 /* other defs that really should go away (they're tty specific) */
141 genl_preference_update
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 ] =
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 */
158 unsigned short amiv_init_map[ AMII_MAXCOLORS ] =
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 */
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 */
196 #if !defined( TTY_GRAPHICS ) || defined( SHAREDLIB ) /* this should be shared better */
197 char morc; /* the character typed in response to a --more-- prompt */
202 winid WIN_BASE = WIN_ERR;
203 winid WIN_OVER = WIN_ERR;
204 winid amii_rawprwin = WIN_ERR;
206 /* Changed later during window/screen opens... */
207 int txwidth = FONTWIDTH, txheight = FONTHEIGHT, txbaseline = FONTBASELINE;
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...
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,
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,
237 int wincnt=0; /* # of nh windows opened */
239 /* We advertise a public screen to allow some people to do other things
240 * while they are playing... like compiling...
243 #ifdef INTUI_NEW_LOOK
244 extern struct Hook fillhook;
245 struct TagItem tags[] =
247 { WA_BackFill, (ULONG)&fillhook },
248 { WA_PubScreenName, (ULONG)"NetHack" },
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.
258 struct win_setup new_wins[] =
261 /* First entry not used, types are based at 1 */
267 NEWSIZE|GADGETUP|GADGETDOWN|MOUSEMOVE|MOUSEBUTTONS|RAWKEY,
268 BORDERLESS|ACTIVATE|SMART_REFRESH
269 #ifdef INTUI_NEW_LOOK
273 NULL,NULL,(UBYTE*)"Messages",NULL,NULL,320,40,0xffff,0xffff,
274 #ifdef INTUI_NEW_LOOK
285 RAWKEY|MENUPICK|DISKINSERTED,
286 BORDERLESS|ACTIVATE|SMART_REFRESH|BACKDROP
287 #ifdef INTUI_NEW_LOOK
291 NULL,NULL,(UBYTE*)"Game Status",NULL,NULL,0,0,0xffff,0xffff,
292 #ifdef INTUI_NEW_LOOK
301 {{0,0,WIDTH,WINDOWHEIGHT,
303 RAWKEY|MENUPICK|MOUSEBUTTONS|ACTIVEWINDOW|MOUSEMOVE,
304 BORDERLESS|ACTIVATE|SMART_REFRESH|BACKDROP
305 #ifdef INTUI_NEW_LOOK
309 NULL,NULL,(UBYTE*)"Dungeon Map",NULL,NULL,64,64,0xffff,0xffff,
310 #ifdef INTUI_NEW_LOOK
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
328 &MenuScroll,NULL,NULL,NULL,NULL,64,32,0xffff,0xffff,
329 #ifdef INTUI_NEW_LOOK
340 RAWKEY|MENUPICK|DISKINSERTED|MOUSEMOVE|
341 GADGETUP|CLOSEWINDOW|VANILLAKEY|NEWSIZE,
342 WINDOWSIZING|WINDOWCLOSE|WINDOWDRAG|ACTIVATE|SMART_REFRESH
343 #ifdef INTUI_NEW_LOOK
347 &MenuScroll,NULL,(UBYTE*)NULL,NULL,NULL,100,32,0xffff,0xffff,
348 #ifdef INTUI_NEW_LOOK
357 {{0,0,WIDTH,WINDOWHEIGHT,
359 RAWKEY|MENUPICK|MOUSEBUTTONS,
360 BORDERLESS|ACTIVATE|SMART_REFRESH|BACKDROP
361 #ifdef INTUI_NEW_LOOK
365 NULL,NULL,(UBYTE*)NULL,NULL,NULL,-1,-1,0xffff,0xffff,
366 #ifdef INTUI_NEW_LOOK
377 RAWKEY|MENUPICK|MOUSEBUTTONS,
378 BORDERLESS|ACTIVATE|SMART_REFRESH|BACKDROP
379 #ifdef INTUI_NEW_LOOK
383 NULL,NULL,(UBYTE*)NULL,NULL,NULL,64,32,0xffff,0xffff,
384 #ifdef INTUI_NEW_LOOK
393 const char winpanicstr[] = "Bad winid %d in %s()";
395 /* The opened windows information */
396 struct amii_WinDesc *amii_wins[ MAXWIN + 1 ];
398 #ifdef INTUI_NEW_LOOK
400 * NUMDRIPENS varies based on headers, so don't use it
401 * here, its value is used elsewhere.
403 UWORD amii_defpens[ 20 ];
405 struct TagItem scrntags[] =
407 { SA_PubName, (ULONG)"NetHack" },
408 { SA_Overscan, OSCAN_TEXT },
409 { SA_AutoScroll, TRUE },
410 #if LIBRARY_VERSION >= 39
411 { SA_Interleaved, TRUE },
413 { SA_Pens, (ULONG)0 },
420 struct NewScreen NewHackScreen =
422 0, 0, WIDTH, SCREENHEIGHT, 3,
423 0, 1, /* DetailPen, BlockPen */
426 #ifdef INTUI_NEW_LOOK
431 NULL, /*(UBYTE *)" NetHack X.Y.Z" */
433 NULL, /* CustomBitmap */
434 #ifdef INTUI_NEW_LOOK
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().
448 char plnametmp[300]; /* From winreq.c: sizeof(StrStringSIBuff) */
451 amii_getlin( "Who are you?", plnametmp );
452 } while( strlen( plnametmp ) == 0 );
454 strncpy(plname, plnametmp, PL_NSIZ-1); /* Avoid overflowing plname[] */
455 plname[PL_NSIZ-1] = 0;
457 if( *plname == '\33' )
460 exit_nhwindows(NULL);
465 /* Discarded ... -jhsa
466 #include "NH:sys/amiga/char.c"
469 /* Get the player selection character */
471 #if 0 /* New function at the bottom */
473 amii_player_selection()
475 register struct Window *cwin;
476 register struct IntuiMessage *imsg;
477 register int aredone = 0;
478 register struct Gadget *gd;
482 amii_clear_nhwindow( WIN_BASE );
483 if (validrole(flags.initrole))
486 flags.initrole=randrole();
489 #if 0 /* Don't query the user ... instead give random character -jhsa */
493 pl_character[ 0 ] = toupper( pl_character[ 0 ] );
494 if( index( pl_classes, pl_character[ 0 ] ) )
501 Type_NewWindowStructure1.TopEdge =
502 (HackScreen->Height/2) - (Type_NewWindowStructure1.Height/2);
504 for( gd = Type_NewWindowStructure1.FirstGadget; gd;
505 gd = gd->NextGadget )
507 if( gd->GadgetID != 0 )
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;
524 Type_NewWindowStructure1.Screen = HackScreen;
525 if( ( cwin = OpenShWindow( (void *)&Type_NewWindowStructure1 ) ) == NULL )
530 WindowToFront( cwin );
535 WaitPort( cwin->UserPort );
536 while( ( imsg = (void *) GetMsg( cwin->UserPort ) ) != NULL )
540 gd = (struct Gadget *)imsg->IAddress;
541 ReplyMsg( (struct Message *)imsg );
546 if( index( pl_classes, toupper( code ) ) )
548 pl_character[0] = toupper( code );
551 else if( code == ' ' || code == '\n' || code == '\r' )
553 flags.initrole = randrole();
556 strcpy( pl_character, roles[ rnd( 11 ) ] );
558 strcpy( pl_character, roles[ rnd( 10 ) ] );
562 amii_clear_nhwindow( WIN_BASE );
563 CloseShWindow( cwin );
564 RandomWindow( pl_character );
567 else if( code == 'q' || code == 'Q' )
569 CloseShWindow( cwin );
571 exit_nhwindows(NULL);
579 switch( gd->GadgetID )
581 case 1: /* Random Character */
582 flags.initrole = randrole();
585 strcpy( pl_character, roles[ rnd( 11 ) ] );
587 strcpy( pl_character, roles[ rnd( 10 ) ] );
590 amii_clear_nhwindow( WIN_BASE );
591 CloseShWindow( cwin );
592 RandomWindow( pl_character );
596 pl_character[0] = gd->GadgetID;
603 CloseShWindow( cwin );
605 exit_nhwindows(NULL);
611 amii_clear_nhwindow( WIN_BASE );
612 CloseShWindow( cwin );
613 #endif /* Do not query user ... -jhsa */
615 #endif /* Function elsewhere */
617 #if 0 /* Unused ... -jhsa */
619 #include "NH:sys/amiga/randwin.c"
625 struct MsgPort *tport;
626 struct timerequest *trq;
630 struct IntuiMessage *imsg;
631 int ticks = 0, aredone = 0, timerdone = 0;
634 tport = CreateMsgPort();
635 trq = (struct timerequest *)CreateIORequest( tport, sizeof( *trq ) );
636 if( tport == NULL || trq == NULL )
639 if( tport ) DeleteMsgPort( tport );
640 if( trq ) DeleteIORequest( (struct IORequest *)trq );
645 if( OpenDevice( TIMERNAME, UNIT_VBLANK, (struct IORequest *)trq, 0L ) != 0 )
648 trq->tr_node.io_Command = TR_ADDREQUEST;
649 trq->tr_time.tv_secs = 8;
650 trq->tr_time.tv_micro = 0;
652 SendIO( (struct IORequest *)trq );
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 -
664 gd = Rnd_NewWindowStructure1.FirstGadget;
665 gd->LeftEdge = (Rnd_NewWindowStructure1.Width - gd->Width)/2;
666 /* Chose correct modifier */
667 Rnd_IText6.IText = "a";
670 case 'a': case 'e': case 'i': case 'o':
671 case 'u': case 'A': case 'E': case 'I':
673 Rnd_IText6.IText = "an";
681 Rnd_NewWindowStructure1.TopEdge =
682 (HackScreen->Height/2) - (Rnd_NewWindowStructure1.Height/2);
684 for( gd = Rnd_NewWindowStructure1.FirstGadget; gd; gd = gd->NextGadget )
686 if( gd->GadgetID != 0 )
689 Rnd_NewWindowStructure1.IDCMPFlags |= VANILLAKEY;
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;
705 Rnd_NewWindowStructure1.Screen = HackScreen;
706 if( ( w = OpenShWindow( (void *)&Rnd_NewWindowStructure1 ) ) == NULL )
708 AbortIO( (struct IORequest *)trq );
709 WaitIO( (struct IORequest *)trq );
710 CloseDevice( (struct IORequest *)trq );
711 DeleteIORequest( (struct IORequest *) trq );
712 DeleteMsgPort( tport );
717 PrintIText( w->RPort, &Rnd_IntuiTextList1, 0, 0 );
719 mask = (1L << tport->mp_SigBit)|(1L << w->UserPort->mp_SigBit);
723 if( got & (1L << tport->mp_SigBit ) )
729 while( w && ( imsg = (struct IntuiMessage *) GetMsg( w->UserPort ) ) )
731 switch( (long)imsg->Class )
733 /* Must be up for a little while... */
748 if(imsg->Code=='\n' || imsg->Code==' ' || imsg->Code=='\r')
752 ReplyMsg( (struct Message *)imsg );
758 AbortIO( (struct IORequest *)trq );
759 WaitIO( (struct IORequest *)trq );
762 CloseDevice( (struct IORequest *)trq );
763 DeleteIORequest( (struct IORequest *) trq );
764 DeleteMsgPort( tport );
765 if(w) CloseShWindow( w );
767 #endif /* Discarded randwin ... -jhsa */
769 /* this should probably not be needed (or be renamed)
773 /* Read in an extended command - doing command line completion for
774 * when enough characters have been entered to make a unique command.
777 amii_get_ext_cmd( void )
781 struct amii_WinDesc *cw;
791 register char *bufp = obufp;
793 int com_index, oindex;
794 int did_comp=0; /* did successful completion? */
797 if( WIN_MESSAGE == WIN_ERR || ( cw = amii_wins[ WIN_MESSAGE ] ) == NULL )
798 panic(winpanicstr, WIN_MESSAGE, "get_ext_cmd");
800 bottom = amii_msgborder( w );
804 if (iflags.extmenu) {
805 win = amii_create_nhwindow( NHW_MENU );
806 amii_start_menu( win );
808 amii_putstr( WIN_MESSAGE, -1, " " );
810 for( i = 0; extcmdlist[ i ].ef_txt != NULL; ++i )
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);
819 amii_end_menu( win, (char*)0 );
820 sel = amii_select_menu( win, PICK_ONE, &mip );
821 amii_destroy_nhwindow( win );
825 sel = mip->item.a_char;
826 for( i = 0; extcmdlist[ i ].ef_txt != NULL; ++i )
828 if( sel == extcmdlist[i].ef_txt[0] )
832 /* copy in the text */
833 if( extcmdlist[ i ].ef_txt != NULL )
835 amii_clear_nhwindow( WIN_MESSAGE );
836 (void) put_ext_cmd( (char *)extcmdlist[i].ef_txt, 0, cw, bottom );
847 amii_clear_nhwindow( WIN_MESSAGE ); /* Was NHW_MESSAGE */
859 while((c = WindowGetchar()) != EOF)
861 amii_curs( WIN_MESSAGE, colx, bottom );
871 amii_curs(WIN_MESSAGE, --colx, bottom);
872 Text(w->RPort,spaces,1);
873 amii_curs(WIN_MESSAGE,colx,bottom);
878 win = amii_create_nhwindow( NHW_MENU );
879 amii_start_menu( win );
881 for( i = 0; extcmdlist[ i ].ef_txt != NULL; ++i )
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);
891 amii_end_menu( win, (char*)0 );
892 sel = amii_select_menu( win, PICK_ONE, &mip );
893 amii_destroy_nhwindow( win );
901 sel = mip->item.a_char;
902 for( i = 0; extcmdlist[ i ].ef_txt != NULL; ++i )
904 if( sel == extcmdlist[i].ef_txt[0] )
908 /* copy in the text */
909 if( extcmdlist[ i ].ef_txt != NULL )
911 amii_clear_nhwindow( WIN_MESSAGE );
912 strcpy( bufp = obufp, extcmdlist[ i ].ef_txt );
913 (void) put_ext_cmd( obufp, colx, cw, bottom );
929 amii_curs(WIN_MESSAGE, --colx, bottom);
930 Text(w->RPort,spaces,1);
931 amii_curs(WIN_MESSAGE,colx,bottom);
936 else if(bufp != obufp)
940 amii_curs( WIN_MESSAGE, --colx, bottom);
941 Text( w->RPort, spaces, 1 );
942 amii_curs( WIN_MESSAGE, colx, bottom);
947 else if( c == '\n' || c == '\r' )
951 else if( c >= ' ' && c < '\177')
953 /* avoid isprint() - some people don't have it
954 ' ' is not always a printing char */
960 while(extcmdlist[oindex].ef_txt != NULL)
962 if(!strnicmp(obufp, (char *)extcmdlist[oindex].ef_txt, strlen(obufp)))
964 if(com_index == -1) /* No matches yet*/
966 else /* More than 1 match */
972 if(com_index >= 0 && *obufp )
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);
985 colx = put_ext_cmd( obufp, colx, cw, bottom );
986 if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO)
990 else if(c == ('X'-64) || c == '\177')
993 amii_clear_nhwindow( WIN_MESSAGE );
1004 put_ext_cmd( obufp, colx, cw, bottom )
1007 struct amii_WinDesc *cw;
1009 struct Window *w = cw->win;
1012 t = (char *)alloc( strlen( obufp ) + 7 );
1017 sprintf( t, "xxx%s", obufp );
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 );
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 ) );
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;
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 );
1049 amii_curs( WIN_MESSAGE, colx = strlen( obufp ) + 3 + ( scrollmsg != 0 ), bottom);
1053 /* Ask a question and get a response */
1055 char amii_yn_function(query, resp, def)
1056 const char *query,*resp;
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.
1072 boolean digit_ok, allow_num;
1073 char prompt[QBUFSZ];
1074 register struct amii_WinDesc *cw;
1076 if( cw = amii_wins[ WIN_MESSAGE ] )
1079 char *rb, respbuf[QBUFSZ];
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);
1089 amii_putstr(WIN_MESSAGE, 0, query);
1090 cursor_on(WIN_MESSAGE);
1091 q = WindowGetchar();
1092 cursor_off(WIN_MESSAGE);
1099 do { /* loop until we get valid input */
1100 cursor_on(WIN_MESSAGE);
1101 q = lowc(WindowGetchar());
1102 cursor_off(WIN_MESSAGE);
1105 if (q == '\020') { /* ctrl-P */
1106 if(!doprev) (void) tty_doprev_message(); /* need two initially */
1107 (void) tty_doprev_message();
1112 tty_clear_nhwindow(WIN_MESSAGE);
1113 cw->maxcol = cw->maxrow;
1115 amii_addtopl(prompt);
1119 digit_ok = allow_num && isdigit(q);
1121 if (index(resp, 'q'))
1123 else if (index(resp, 'n'))
1128 } else if (index(quitchars, q)) {
1132 if (!index(resp, q) && !digit_ok) {
1135 } else if (q == '#' || digit_ok) {
1136 char z, digit_string[2];
1139 amii_addtopl("#"), n_len++;
1140 digit_string[1] = '\0';
1142 digit_string[0] = q;
1143 amii_addtopl(digit_string), n_len++;
1147 do { /* loop until we get a non-digit */
1148 cursor_on(WIN_MESSAGE);
1149 z = lowc(WindowGetchar());
1150 cursor_off(WIN_MESSAGE);
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--; }
1163 value = -1; /* abort */
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;
1177 if (q != '#' && q != '\033') {
1178 Sprintf(rtmp, "%c", q);
1182 cursor_off(WIN_MESSAGE);
1183 clear_nhwindow(WIN_MESSAGE);
1188 amii_display_file(fn, complain)
1192 register struct amii_WinDesc *cw;
1196 register char buf[ 200 ];
1199 panic("NULL file name in display_file()");
1201 if( ( fp = dlb_fopen( fn, RDTMODE ) ) == (dlb *)NULL )
1204 sprintf( buf, "Can't display %s: %s", fn,
1205 #if defined(_DCC) || defined(__GNUC__)
1209 __sys_errlist[ errno ]
1211 sys_errlist[ errno ]
1215 amii_addtopl( buf );
1219 win = amii_create_nhwindow( NHW_TEXT );
1221 /* Set window title to file name */
1222 if( cw = amii_wins[ win ] )
1223 cw->morestr = (char *)fn;
1225 while( dlb_fgets( buf, sizeof( buf ), fp ) != NULL )
1227 if( t = index( buf, '\n' ) )
1229 amii_putstr( win, 0, buf );
1233 /* If there were lines in the file, display those lines */
1235 if( amii_wins[ win ]->cury > 0 )
1236 amii_display_nhwindow( win, TRUE );
1238 amii_wins[win]->morestr = NULL; /* don't free title string */
1239 amii_destroy_nhwindow( win );
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.
1249 register struct Gadget *gd;
1251 register struct Border *bp;
1253 register int i, inc = -1, dec = -1;
1255 int hipen = flags.amii_dripens[ SHINEPEN ], shadowpen = flags.amii_dripens[ SHADOWPEN ];
1256 #ifdef INTUI_NEW_LOOK
1257 struct DrawInfo *dip;
1260 #ifdef INTUI_NEW_LOOK
1261 if( IntuitionBase->LibNode.lib_Version >= 37 )
1263 if( dip = GetScreenDrawInfo( HackScreen ) )
1265 hipen = dip->dri_Pens[ SHINEPEN ];
1266 shadowpen = dip->dri_Pens[ SHADOWPEN ];
1267 FreeScreenDrawInfo( HackScreen, dip );
1271 /* Allocate two border structures one for up image and one for down
1272 * image, plus vector arrays for the border lines.
1275 if( gd->GadgetType == STRGADGET )
1278 if( ( bp = (struct Border *)alloc( ( ( sizeof( struct Border ) * 2 ) +
1279 ( sizeof( short ) * borders ) ) * 2 ) ) == NULL )
1284 /* For a string gadget, we expand the border beyond the area where
1285 * the text will be entered.
1288 /* Remove any special rendering flags to avoid confusing intuition
1291 gd->Flags &= ~(GADGHIGHBITS|GADGIMAGE);
1293 sp = (short *)(bp + 4);
1294 if( gd->GadgetType == STRGADGET || ( gd->GadgetType == BOOLGADGET &&
1295 ( gd->Flags & GADGHIGHBITS ) == GADGHNONE ) )
1298 sp[1] = gd->Height - 1;
1301 sp[4] = gd->Width - 1;
1304 sp[6] = gd->Width + 1;
1306 sp[8] = gd->Width + 1;
1307 sp[9] = gd->Height + 1;
1309 sp[11] = gd->Height + 1;
1312 sp[13] = gd->Height;
1318 sp[19] = gd->Height;
1320 sp[21] = gd->Height;
1322 for( i = 0; i < 3; ++i )
1324 bp[ i ].LeftEdge = bp[ i ].TopEdge = -1;
1325 bp[ i ].FrontPen = ( i == 0 || i == 1 ) ? shadowpen : hipen;
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 ];
1335 /* bp[0] and bp[1] two pieces for the up image */
1336 gd->GadgetRender = (APTR) bp;
1338 /* No image change for select */
1339 gd->SelectRender = (APTR) bp;
1343 gd->Flags |= GADGHCOMP;
1347 /* Create the border vector values for up and left side, and
1348 * also the lower and right side.
1352 sp[1] = gd->Height + inc;
1355 sp[4] = gd->Width + inc;
1358 sp[6] = gd->Width + inc;
1360 sp[8] = gd->Width + inc;
1361 sp[9] = gd->Height + inc;
1363 sp[11] = gd->Height + inc;
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.
1370 for( i = 0; i < 4; ++i )
1372 bp[ i ].TopEdge = bp[ i ].LeftEdge = 0;
1374 /* A GADGHNONE is always down */
1376 if( gd->GadgetType == BOOLGADGET &&
1377 ( gd->Flags & GADGHIGHBITS ) != GADGHNONE )
1380 ( i == 1 || i == 2 ) ? shadowpen : hipen;
1385 ( i == 1 || i == 3 ) ? hipen : shadowpen;
1388 /* Have to use JAM2 so that the old colors disappear. */
1389 bp[ i ].BackPen = C_BLACK;
1390 bp[ i ].DrawMode = JAM2;
1392 bp[ i ].XY = &sp[ 6 * ((i &1) != 0) ];
1393 bp[ i ].NextBorder =
1394 ( i == 1 || i == 3 ) ? NULL : &bp[ i + 1 ];
1397 /* bp[0] and bp[1] two pieces for the up image */
1398 gd->GadgetRender = (APTR) bp;
1400 /* bp[2] and bp[3] two pieces for the down image */
1401 gd->SelectRender = (APTR) (bp + 2);
1402 gd->Flags |= GADGHIMAGE;
1406 /* Following function copied from wintty.c */
1407 /* Modified slightly to fit amiga needs */
1410 amii_player_selection()
1413 char pick4u = 'n', thisch, lastch = 0;
1414 char pbuf[QBUFSZ], plbuf[QBUFSZ], rolenamebuf[QBUFSZ];
1417 menu_item *selected = 0;
1419 rigid_role_checks();
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));
1437 if (pick4u != 'y' && pick4u != 'n') {
1439 if (selected) free((genericptr_t) selected);
1441 exit_nhwindows(NULL);
1448 (void) root_plselection_prompt(plbuf, QBUFSZ - 1,
1449 flags.initrole, flags.initrace, flags.initgend, flags.initalign);
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();
1465 /* Prompt for a role */
1466 win = create_nhwindow(NHW_MENU);
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,
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);
1479 Strcpy(rolenamebuf, roles[i].name.m);
1481 if (roles[i].name.f) {
1482 Strcpy(rolenamebuf, roles[i].name.m);
1483 Strcat(rolenamebuf, "/");
1484 Strcat(rolenamebuf, roles[i].name.f);
1486 Strcpy(rolenamebuf, roles[i].name.m);
1488 add_menu(win, NO_GLYPH, &any, thisch,
1489 0, ATR_NONE, an(rolenamebuf), MENU_UNSELECTED);
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);
1507 /* Process the choice */
1508 if (n != 1 || selected[0].item.a_int == any.a_int)
1509 goto give_up; /* Selected quit */
1511 flags.initrole = selected[0].item.a_int - 1;
1512 free((genericptr_t) selected), selected = 0;
1514 (void) root_plselection_prompt(plbuf, QBUFSZ - 1,
1515 flags.initrole, flags.initrace, flags.initgend, flags.initalign);
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);
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,
1542 for (i = 0; races[i].noun; i++) {
1543 if (validrace(flags.initrole, i)) {
1550 /* Permit the user to pick, if there is more than one */
1552 win = create_nhwindow(NHW_MENU);
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,
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);
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 */
1578 k = selected[0].item.a_int - 1;
1579 free((genericptr_t) selected), selected = 0;
1583 (void) root_plselection_prompt(plbuf, QBUFSZ - 1,
1584 flags.initrole, flags.initrace, flags.initgend, flags.initalign);
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,
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);
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,
1612 for (i = 0; i < ROLE_GENDERS; i++) {
1613 if (validgend(flags.initrole, flags.initrace, i)) {
1620 /* Permit the user to pick, if there is more than one */
1622 win = create_nhwindow(NHW_MENU);
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,
1629 add_menu(win, NO_GLYPH, &any, genders[i].adj[0],
1630 0, ATR_NONE, genders[i].adj, MENU_UNSELECTED);
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 */
1648 k = selected[0].item.a_int - 1;
1649 free((genericptr_t) selected), selected = 0;
1653 (void) root_plselection_prompt(plbuf, QBUFSZ - 1,
1654 flags.initrole, flags.initrace, flags.initgend, flags.initalign);
1657 /* Select an alignment, if necessary */
1658 /* force compatibility with role/race/gender */
1659 if (flags.initalign < 0 || !validalign(flags.initrole, flags.initrace,
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);
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,
1681 for (i = 0; i < ROLE_ALIGNS; i++) {
1682 if (validalign(flags.initrole, flags.initrace, i)) {
1689 /* Permit the user to pick, if there is more than one */
1691 win = create_nhwindow(NHW_MENU);
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)) {
1698 add_menu(win, NO_GLYPH, &any, aligns[i].adj[0],
1699 0, ATR_NONE, aligns[i].adj, MENU_UNSELECTED);
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 */
1717 k = selected[0].item.a_int - 1;
1718 free((genericptr_t) selected), selected = 0;
1720 flags.initalign = k;
1725 #endif /* AMIGA_INTUITION */