/* NetHack 3.6 winami.c $NHDT-Date: 1501981093 2017/08/06 00:58:13 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.20 $ */ /* Copyright (c) Gregg Wonderly, Naperville, Illinois, 1991,1992,1993,1996. */ /* NetHack may be freely redistributed. See license for details. */ #include "NH:sys/amiga/windefs.h" #include "NH:sys/amiga/winext.h" #include "NH:sys/amiga/winproto.h" #include "dlb.h" #ifdef AMIGA_INTUITION static int FDECL(put_ext_cmd, (char *, int, struct amii_WinDesc *, int)); struct amii_DisplayDesc *amiIDisplay; /* the Amiga Intuition descriptor */ struct Rectangle lastinvent, lastmsg; int clipping = 0; int clipx = 0; int clipy = 0; int clipxmax = 0; int clipymax = 0; int scrollmsg = 1; int alwaysinvent = 0; int amii_numcolors; long amii_scrnmode; /* Interface definition, for use by windows.c and winprocs.h to provide * the intuition interface for the amiga... */ struct window_procs amii_procs = { "amii", WC_COLOR | WC_HILITE_PET | WC_INVERSE, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* color availability */ 0L, amii_init_nhwindows, amii_player_selection, amii_askname, amii_get_nh_event, amii_exit_nhwindows, amii_suspend_nhwindows, amii_resume_nhwindows, amii_create_nhwindow, amii_clear_nhwindow, amii_display_nhwindow, amii_destroy_nhwindow, amii_curs, amii_putstr, genl_putmixed, amii_display_file, amii_start_menu, amii_add_menu, amii_end_menu, amii_select_menu, genl_message_menu, amii_update_inventory, amii_mark_synch, amii_wait_synch, #ifdef CLIPPING amii_cliparound, #endif #ifdef POSITIONBAR donull, #endif amii_print_glyph, amii_raw_print, amii_raw_print_bold, amii_nhgetch, amii_nh_poskey, amii_bell, amii_doprev_message, amii_yn_function, amii_getlin, amii_get_ext_cmd, amii_number_pad, amii_delay_output, #ifdef CHANGE_COLOR /* only a Mac option currently */ amii_change_color, amii_get_color_string, #endif /* other defs that really should go away (they're tty specific) */ amii_delay_output, amii_delay_output, amii_outrip, genl_preference_update, genl_getmsghistory, genl_putmsghistory, genl_status_init, genl_status_finish, genl_status_enablefield, genl_status_update, genl_can_suspend_yes, }; /* The view window layout uses the same function names so we can use * a shared library to allow the executable to be smaller. */ struct window_procs amiv_procs = { "amitile", WC_COLOR | WC_HILITE_PET | WC_INVERSE, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* color availability */ 0L, amii_init_nhwindows, amii_player_selection, amii_askname, amii_get_nh_event, amii_exit_nhwindows, amii_suspend_nhwindows, amii_resume_nhwindows, amii_create_nhwindow, amii_clear_nhwindow, amii_display_nhwindow, amii_destroy_nhwindow, amii_curs, amii_putstr, genl_putmixed, amii_display_file, amii_start_menu, amii_add_menu, amii_end_menu, amii_select_menu, genl_message_menu, amii_update_inventory, amii_mark_synch, amii_wait_synch, #ifdef CLIPPING amii_cliparound, #endif #ifdef POSITIONBAR donull, #endif amii_print_glyph, amii_raw_print, amii_raw_print_bold, amii_nhgetch, amii_nh_poskey, amii_bell, amii_doprev_message, amii_yn_function, amii_getlin, amii_get_ext_cmd, amii_number_pad, amii_delay_output, #ifdef CHANGE_COLOR /* only a Mac option currently */ amii_change_color, amii_get_color_string, #endif /* other defs that really should go away (they're tty specific) */ amii_delay_output, amii_delay_output, amii_outrip, genl_preference_update, genl_getmsghistory, genl_putmsghistory, genl_status_init, genl_status_finish, genl_status_enablefield, genl_status_update, genl_can_suspend_yes, }; unsigned short amii_initmap[AMII_MAXCOLORS]; /* Default pens used unless user overides in nethack.cnf. */ unsigned short amii_init_map[AMII_MAXCOLORS] = { 0x0000, /* color #0 C_BLACK */ 0x0FFF, /* color #1 C_WHITE */ 0x0830, /* color #2 C_BROWN */ 0x07ac, /* color #3 C_CYAN */ 0x0181, /* color #4 C_GREEN */ 0x0C06, /* color #5 C_MAGENTA */ 0x023E, /* color #6 C_BLUE */ 0x0c00, /* color #7 C_RED */ }; unsigned short amiv_init_map[AMII_MAXCOLORS] = { 0x0000, /* color #0 C_BLACK */ 0x0fff, /* color #1 C_WHITE */ 0x00bf, /* color #2 C_CYAN */ 0x0f60, /* color #3 C_ORANGE */ 0x000f, /* color #4 C_BLUE */ 0x0090, /* color #5 C_GREEN */ 0x069b, /* color #6 C_GREY */ 0x0f00, /* color #7 C_RED */ 0x06f0, /* color #8 C_LTGREEN */ 0x0ff0, /* color #9 C_YELLOW */ 0x0f0f, /* color #10 C_MAGENTA */ 0x0940, /* color #11 C_BROWN */ 0x0466, /* color #12 C_GREYBLUE */ 0x0c40, /* color #13 C_LTBROWN */ 0x0ddb, /* color #14 C_LTGREY */ 0x0fb9, /* color #15 C_PEACH */ /* Pens for dripens etc under AA or better */ 0x0222, /* color #16 */ 0x0fdc, /* color #17 */ 0x0000, /* color #18 */ 0x0ccc, /* color #19 */ 0x0bbb, /* color #20 */ 0x0BA9, /* color #21 */ 0x0999, /* color #22 */ 0x0987, /* color #23 */ 0x0765, /* color #24 */ 0x0666, /* color #25 */ 0x0555, /* color #26 */ 0x0533, /* color #27 */ 0x0333, /* color #28 */ 0x018f, /* color #29 */ 0x0f81, /* color #30 */ 0x0fff, /* color #31 */ }; #if !defined(TTY_GRAPHICS) \ || defined(SHAREDLIB) /* this should be shared better */ char morc; /* the character typed in response to a --more-- prompt */ #endif char spaces[76] = " " " "; winid WIN_BASE = WIN_ERR; winid WIN_OVER = WIN_ERR; winid amii_rawprwin = WIN_ERR; /* Changed later during window/screen opens... */ int txwidth = FONTWIDTH, txheight = FONTHEIGHT, txbaseline = FONTBASELINE; /* If a 240 or more row screen is in front when we start, this will be * set to 1, and the windows will be given borders to allow them to be * arranged differently. The Message window may eventually get a scroller... */ int bigscreen = 0; /* This gadget data is replicated for menu/text windows... */ struct PropInfo PropScroll = { AUTOKNOB | FREEVERT, 0xffff, 0xffff, 0xffff, 0xffff, }; struct Image Image1 = { 0, 0, 7, 102, 0, NULL, 0x0000, 0x0000, NULL }; struct Gadget MenuScroll = { NULL, -15, 10, 15, -19, GRELRIGHT | GRELHEIGHT, RELVERIFY | FOLLOWMOUSE | RIGHTBORDER | GADGIMMEDIATE | RELVERIFY, PROPGADGET, (APTR) &Image1, NULL, NULL, NULL, (APTR) &PropScroll, 1, NULL }; /* This gadget is for the message window... */ struct PropInfo MsgPropScroll = { AUTOKNOB | FREEVERT, 0xffff, 0xffff, 0xffff, 0xffff, }; struct Image MsgImage1 = { 0, 0, 7, 102, 0, NULL, 0x0000, 0x0000, NULL }; struct Gadget MsgScroll = { NULL, -15, 10, 14, -19, GRELRIGHT | GRELHEIGHT, RELVERIFY | FOLLOWMOUSE | RIGHTBORDER | GADGIMMEDIATE | RELVERIFY, PROPGADGET, (APTR) &MsgImage1, NULL, NULL, NULL, (APTR) &MsgPropScroll, 1, NULL }; int wincnt = 0; /* # of nh windows opened */ /* We advertise a public screen to allow some people to do other things * while they are playing... like compiling... */ #ifdef INTUI_NEW_LOOK extern struct Hook fillhook; struct TagItem tags[] = { { WA_BackFill, (ULONG) &fillhook }, { WA_PubScreenName, (ULONG) "NetHack" }, { TAG_DONE, 0 }, }; #endif /* * The default dimensions and status values for each window type. The * data here is generally changed in create_nhwindow(), so beware that * what you see here may not be exactly what you get. */ struct win_setup new_wins[] = { /* First entry not used, types are based at 1 */ { { 0 } }, /* NHW_MESSAGE */ { { 0, 1, 640, 11, 0xff, 0xff, NEWSIZE | GADGETUP | GADGETDOWN | MOUSEMOVE | MOUSEBUTTONS | RAWKEY, BORDERLESS | ACTIVATE | SMART_REFRESH #ifdef INTUI_NEW_LOOK | WFLG_NW_EXTENDED #endif , NULL, NULL, (UBYTE *) "Messages", NULL, NULL, 320, 40, 0xffff, 0xffff, #ifdef INTUI_NEW_LOOK PUBLICSCREEN, tags #else CUSTOMSCREEN #endif }, 0, 0, 1, 1, 80, 80 }, /* NHW_STATUS */ { { 0, 181, 640, 24, 0xff, 0xff, RAWKEY | MENUPICK | DISKINSERTED, BORDERLESS | ACTIVATE | SMART_REFRESH | BACKDROP #ifdef INTUI_NEW_LOOK | WFLG_NW_EXTENDED #endif , NULL, NULL, (UBYTE *) "Game Status", NULL, NULL, 0, 0, 0xffff, 0xffff, #ifdef INTUI_NEW_LOOK PUBLICSCREEN, tags #else CUSTOMSCREEN #endif }, 0, 0, 2, 2, 78, 78 }, /* NHW_MAP */ { { 0, 0, WIDTH, WINDOWHEIGHT, 0xff, 0xff, RAWKEY | MENUPICK | MOUSEBUTTONS | ACTIVEWINDOW | MOUSEMOVE, BORDERLESS | ACTIVATE | SMART_REFRESH | BACKDROP #ifdef INTUI_NEW_LOOK | WFLG_NW_EXTENDED #endif , NULL, NULL, (UBYTE *) "Dungeon Map", NULL, NULL, 64, 64, 0xffff, 0xffff, #ifdef INTUI_NEW_LOOK PUBLICSCREEN, tags #else CUSTOMSCREEN #endif }, 0, 0, 22, 22, 80, 80 }, /* NHW_MENU */ { { 400, 10, 10, 10, 0xff, 0xff, RAWKEY | MENUPICK | DISKINSERTED | MOUSEMOVE | MOUSEBUTTONS | GADGETUP | GADGETDOWN | CLOSEWINDOW | VANILLAKEY | NEWSIZE | INACTIVEWINDOW, WINDOWSIZING | WINDOWCLOSE | WINDOWDRAG | ACTIVATE | SMART_REFRESH #ifdef INTUI_NEW_LOOK | WFLG_NW_EXTENDED #endif , &MenuScroll, NULL, NULL, NULL, NULL, 64, 32, 0xffff, 0xffff, #ifdef INTUI_NEW_LOOK PUBLICSCREEN, tags #else CUSTOMSCREEN #endif }, 0, 0, 1, 1, 22, 78 }, /* NHW_TEXT */ { { 0, 0, 640, 200, 0xff, 0xff, RAWKEY | MENUPICK | DISKINSERTED | MOUSEMOVE | GADGETUP | CLOSEWINDOW | VANILLAKEY | NEWSIZE, WINDOWSIZING | WINDOWCLOSE | WINDOWDRAG | ACTIVATE | SMART_REFRESH #ifdef INTUI_NEW_LOOK | WFLG_NW_EXTENDED #endif , &MenuScroll, NULL, (UBYTE *) NULL, NULL, NULL, 100, 32, 0xffff, 0xffff, #ifdef INTUI_NEW_LOOK PUBLICSCREEN, tags #else CUSTOMSCREEN #endif }, 0, 0, 1, 1, 22, 78 }, /* NHW_BASE */ { { 0, 0, WIDTH, WINDOWHEIGHT, 0xff, 0xff, RAWKEY | MENUPICK | MOUSEBUTTONS, BORDERLESS | ACTIVATE | SMART_REFRESH | BACKDROP #ifdef INTUI_NEW_LOOK | WFLG_NW_EXTENDED #endif , NULL, NULL, (UBYTE *) NULL, NULL, NULL, -1, -1, 0xffff, 0xffff, #ifdef INTUI_NEW_LOOK PUBLICSCREEN, tags #else CUSTOMSCREEN #endif }, 0, 0, 22, 22, 80, 80 }, /* NHW_OVER */ { { 320, 20, 319, 179, 0xff, 0xff, RAWKEY | MENUPICK | MOUSEBUTTONS, BORDERLESS | ACTIVATE | SMART_REFRESH | BACKDROP #ifdef INTUI_NEW_LOOK | WFLG_NW_EXTENDED #endif , NULL, NULL, (UBYTE *) NULL, NULL, NULL, 64, 32, 0xffff, 0xffff, #ifdef INTUI_NEW_LOOK PUBLICSCREEN, tags #else CUSTOMSCREEN #endif }, 0, 0, 22, 22, 80, 80 }, }; const char winpanicstr[] = "Bad winid %d in %s()"; /* The opened windows information */ struct amii_WinDesc *amii_wins[MAXWIN + 1]; #ifdef INTUI_NEW_LOOK /* * NUMDRIPENS varies based on headers, so don't use it * here, its value is used elsewhere. */ UWORD amii_defpens[20]; struct TagItem scrntags[] = { { SA_PubName, (ULONG) "NetHack" }, { SA_Overscan, OSCAN_TEXT }, { SA_AutoScroll, TRUE }, #if LIBRARY_VERSION >= 39 { SA_Interleaved, TRUE }, #endif { SA_Pens, (ULONG) 0 }, { SA_DisplayID, 0 }, { TAG_DONE, 0 }, }; #endif struct NewScreen NewHackScreen = { 0, 0, WIDTH, SCREENHEIGHT, 3, 0, 1, /* DetailPen, BlockPen */ HIRES, CUSTOMSCREEN #ifdef INTUI_NEW_LOOK | NS_EXTENDED #endif , &Hack80, /* Font */ NULL, /*(UBYTE *)" NetHack X.Y.Z" */ NULL, /* Gadgets */ NULL, /* CustomBitmap */ #ifdef INTUI_NEW_LOOK scrntags #endif }; /* * plname is filled either by an option (-u Player or -uPlayer) or * explicitly (by being the wizard) or by askname. * It may still contain a suffix denoting pl_character. * Always called after init_nhwindows() and before display_gamewindows(). */ void amii_askname() { char plnametmp[300]; /* From winreq.c: sizeof(StrStringSIBuff) */ *plnametmp = 0; do { amii_getlin("Who are you?", plnametmp); } while (strlen(plnametmp) == 0); strncpy(g.plname, plnametmp, PL_NSIZ - 1); /* Avoid overflowing plname[] */ g.plname[PL_NSIZ - 1] = 0; if (*g.plname == '\33') { clearlocks(); exit_nhwindows(NULL); nh_terminate(0); } } /* Discarded ... -jhsa #include "NH:sys/amiga/char.c" */ /* Get the player selection character */ #if 0 /* New function at the bottom */ void amii_player_selection() { register struct Window *cwin; register struct IntuiMessage *imsg; register int aredone = 0; register struct Gadget *gd; static int once = 0; long class, code; amii_clear_nhwindow( WIN_BASE ); if (validrole(flags.initrole)) return; else { flags.initrole = randrole(FALSE); return; } #if 0 /* Don't query the user ... instead give random character -jhsa */ #if 0 /* OBSOLETE */ if( *g.pl_character ){ g.pl_character[ 0 ] = toupper( g.pl_character[ 0 ] ); if( index( pl_classes, g.pl_character[ 0 ] ) ) return; } #endif if( !once ){ if( bigscreen ){ Type_NewWindowStructure1.TopEdge = (HackScreen->Height/2) - (Type_NewWindowStructure1.Height/2); } for( gd = Type_NewWindowStructure1.FirstGadget; gd; gd = gd->NextGadget ) { if( gd->GadgetID != 0 ) SetBorder( gd ); } once = 1; } if( WINVERS_AMIV ) { #ifdef INTUI_NEW_LOOK Type_NewWindowStructure1.Extension = wintags; Type_NewWindowStructure1.Flags |= WFLG_NW_EXTENDED; fillhook.h_Entry = (ULONG(*)())LayerFillHook; fillhook.h_Data = (void *)-2; fillhook.h_SubEntry = 0; #endif } Type_NewWindowStructure1.Screen = HackScreen; if( ( cwin = OpenShWindow( (void *)&Type_NewWindowStructure1 ) ) == NULL ) { return; } #if 0 WindowToFront( cwin ); #endif while( !aredone ) { WaitPort( cwin->UserPort ); while( ( imsg = (void *) GetMsg( cwin->UserPort ) ) != NULL ) { class = imsg->Class; code = imsg->Code; gd = (struct Gadget *)imsg->IAddress; ReplyMsg( (struct Message *)imsg ); switch( class ) { case VANILLAKEY: if( index( pl_classes, toupper( code ) ) ) { g.pl_character[0] = toupper( code ); aredone = 1; } else if( code == ' ' || code == '\n' || code == '\r' ) { flags.initrole = randrole(FALSE); #if 0 /* OBSOLETE */ strcpy( g.pl_character, roles[ rnd( 11 ) ] ); #endif aredone = 1; amii_clear_nhwindow( WIN_BASE ); CloseShWindow( cwin ); RandomWindow( g.pl_character ); return; } else if( code == 'q' || code == 'Q' ) { CloseShWindow( cwin ); clearlocks(); exit_nhwindows(NULL); nh_terminate(0); } else DisplayBeep( NULL ); break; case GADGETUP: switch( gd->GadgetID ) { case 1: /* Random Character */ flags.initrole = randrole(FALSE); #if 0 /* OBSOLETE */ strcpy( g.pl_character, roles[ rnd( 11 ) ] ); #endif amii_clear_nhwindow( WIN_BASE ); CloseShWindow( cwin ); RandomWindow( g.pl_character ); return; default: g.pl_character[0] = gd->GadgetID; break; } aredone = 1; break; case CLOSEWINDOW: CloseShWindow( cwin ); clearlocks(); exit_nhwindows(NULL); nh_terminate(0); break; } } } amii_clear_nhwindow( WIN_BASE ); CloseShWindow( cwin ); #endif /* Do not query user ... -jhsa */ } #endif /* Function elsewhere */ #if 0 /* Unused ... -jhsa */ #include "NH:sys/amiga/randwin.c" void RandomWindow( name ) char *name; { struct MsgPort *tport; struct timerequest *trq; static int once = 0; struct Gadget *gd; struct Window *w; struct IntuiMessage *imsg; int ticks = 0, aredone = 0, timerdone = 0; long mask, got; tport = CreateMsgPort(); trq = (struct timerequest *)CreateIORequest( tport, sizeof( *trq ) ); if( tport == NULL || trq == NULL ) { allocerr: if( tport ) DeleteMsgPort( tport ); if( trq ) DeleteIORequest( (struct IORequest *)trq ); Delay( 8 * 50 ); return; } if( OpenDevice( TIMERNAME, UNIT_VBLANK, (struct IORequest *)trq, 0L ) != 0 ) goto allocerr; trq->tr_node.io_Command = TR_ADDREQUEST; trq->tr_time.tv_secs = 8; trq->tr_time.tv_micro = 0; SendIO( (struct IORequest *)trq ); /* Place the name in the center of the screen */ Rnd_IText5.IText = name; Rnd_IText6.LeftEdge = Rnd_IText4.LeftEdge + (strlen(Rnd_IText4.IText)+1)*8; Rnd_NewWindowStructure1.Width = ( (strlen( Rnd_IText2.IText )+1) * 8 ) + HackScreen->WBorLeft + HackScreen->WBorRight; Rnd_IText5.LeftEdge = (Rnd_NewWindowStructure1.Width - (strlen(name)*8))/2; gd = Rnd_NewWindowStructure1.FirstGadget; gd->LeftEdge = (Rnd_NewWindowStructure1.Width - gd->Width)/2; /* Chose correct modifier */ Rnd_IText6.IText = "a"; switch( *name ) { case 'a': case 'e': case 'i': case 'o': case 'u': case 'A': case 'E': case 'I': case 'O': case 'U': Rnd_IText6.IText = "an"; break; } if( !once ) { if( bigscreen ) { Rnd_NewWindowStructure1.TopEdge = (HackScreen->Height/2) - (Rnd_NewWindowStructure1.Height/2); } for( gd = Rnd_NewWindowStructure1.FirstGadget; gd; gd = gd->NextGadget ) { if( gd->GadgetID != 0 ) SetBorder( gd ); } Rnd_NewWindowStructure1.IDCMPFlags |= VANILLAKEY; once = 1; } if( WINVERS_AMIV ) { #ifdef INTUI_NEW_LOOK Rnd_NewWindowStructure1.Extension = wintags; Rnd_NewWindowStructure1.Flags |= WFLG_NW_EXTENDED; fillhook.h_Entry = (ULONG(*)())LayerFillHook; fillhook.h_Data = (void *)-2; fillhook.h_SubEntry = 0; #endif } Rnd_NewWindowStructure1.Screen = HackScreen; if( ( w = OpenShWindow( (void *)&Rnd_NewWindowStructure1 ) ) == NULL ) { AbortIO( (struct IORequest *)trq ); WaitIO( (struct IORequest *)trq ); CloseDevice( (struct IORequest *)trq ); DeleteIORequest( (struct IORequest *) trq ); DeleteMsgPort( tport ); Delay( 50 * 8 ); return; } PrintIText( w->RPort, &Rnd_IntuiTextList1, 0, 0 ); mask = (1L << tport->mp_SigBit)|(1L << w->UserPort->mp_SigBit); while( !aredone ) { got = Wait( mask ); if( got & (1L << tport->mp_SigBit ) ) { aredone = 1; timerdone = 1; GetMsg( tport ); } while( w && ( imsg = (struct IntuiMessage *) GetMsg( w->UserPort ) ) ) { switch( (long)imsg->Class ) { /* Must be up for a little while... */ case INACTIVEWINDOW: if( ticks >= 40 ) aredone = 1; break; case INTUITICKS: ++ticks; break; case GADGETUP: aredone = 1; break; case VANILLAKEY: if(imsg->Code=='\n' || imsg->Code==' ' || imsg->Code=='\r') aredone = 1; break; } ReplyMsg( (struct Message *)imsg ); } } if( !timerdone ) { AbortIO( (struct IORequest *)trq ); WaitIO( (struct IORequest *)trq ); } CloseDevice( (struct IORequest *)trq ); DeleteIORequest( (struct IORequest *) trq ); DeleteMsgPort( tport ); if(w) CloseShWindow( w ); } #endif /* Discarded randwin ... -jhsa */ /* this should probably not be needed (or be renamed) void flush_output(){} */ /* Read in an extended command - doing command line completion for * when enough characters have been entered to make a unique command. */ int amii_get_ext_cmd(void) { menu_item *mip; anything id; struct amii_WinDesc *cw; #ifdef EXTMENU winid win; int i; char buf[256]; #endif int colx; int bottom = 0; struct Window *w; char obufp[100]; register char *bufp = obufp; register int c; int com_index, oindex; int did_comp = 0; /* did successful completion? */ int sel = -1; if (WIN_MESSAGE == WIN_ERR || (cw = amii_wins[WIN_MESSAGE]) == NULL) panic(winpanicstr, WIN_MESSAGE, "get_ext_cmd"); w = cw->win; bottom = amii_msgborder(w); colx = 3; #ifdef EXTMENU if (iflags.extmenu) { win = amii_create_nhwindow(NHW_MENU); amii_start_menu(win, MENU_BEHAVE_STANDARD); pline("#"); amii_putstr(WIN_MESSAGE, -1, " "); for (i = 0; extcmdlist[i].ef_txt != NULL; ++i) { id.a_char = *extcmdlist[i].ef_txt; sprintf(buf, "%-10s - %s ", extcmdlist[i].ef_txt, extcmdlist[i].ef_desc); amii_add_menu(win, NO_GLYPH, &id, extcmdlist[i].ef_txt[0], 0, 0, buf, MENU_ITEMFLAGS_NONE); } amii_end_menu(win, (char *) 0); sel = amii_select_menu(win, PICK_ONE, &mip); amii_destroy_nhwindow(win); if (sel == 1) { sel = mip->item.a_char; for (i = 0; extcmdlist[i].ef_txt != NULL; ++i) { if (sel == extcmdlist[i].ef_txt[0]) break; } /* copy in the text */ if (extcmdlist[i].ef_txt != NULL) { amii_clear_nhwindow(WIN_MESSAGE); (void) put_ext_cmd((char *) extcmdlist[i].ef_txt, 0, cw, bottom); return (i); } else DisplayBeep(NULL); } return (-1); } #endif amii_clear_nhwindow(WIN_MESSAGE); /* Was NHW_MESSAGE */ if (scrollmsg) { pline("#"); amii_addtopl(" "); } else { pline("# "); } sel = -1; while ((c = WindowGetchar()) != EOF) { amii_curs(WIN_MESSAGE, colx, bottom); if (c == '?') { int win, i; char buf[100]; if (did_comp) { while (bufp != obufp) { bufp--; amii_curs(WIN_MESSAGE, --colx, bottom); Text(w->RPort, spaces, 1); amii_curs(WIN_MESSAGE, colx, bottom); did_comp = 0; } } win = amii_create_nhwindow(NHW_MENU); amii_start_menu(win, MENU_BEHAVE_STANDARD); for (i = 0; extcmdlist[i].ef_txt != NULL; ++i) { id.a_char = extcmdlist[i].ef_txt[0]; sprintf(buf, "%-10s - %s ", extcmdlist[i].ef_txt, extcmdlist[i].ef_desc); amii_add_menu(win, NO_GLYPH, &id, extcmdlist[i].ef_txt[0], 0, 0, buf, MENU_ITEMFLAGS_NONE); } amii_end_menu(win, (char *) 0); sel = amii_select_menu(win, PICK_ONE, &mip); amii_destroy_nhwindow(win); if (sel == 0) { return (-1); } else { sel = mip->item.a_char; for (i = 0; extcmdlist[i].ef_txt != NULL; ++i) { if (sel == extcmdlist[i].ef_txt[0]) break; } /* copy in the text */ if (extcmdlist[i].ef_txt != NULL) { amii_clear_nhwindow(WIN_MESSAGE); strcpy(bufp = obufp, extcmdlist[i].ef_txt); (void) put_ext_cmd(obufp, colx, cw, bottom); return (i); } else DisplayBeep(NULL); } } else if (c == '\033') { return (-1); } else if (c == '\b') { if (did_comp) { while (bufp != obufp) { bufp--; amii_curs(WIN_MESSAGE, --colx, bottom); Text(w->RPort, spaces, 1); amii_curs(WIN_MESSAGE, colx, bottom); did_comp = 0; sel = -1; } } else if (bufp != obufp) { sel = -1; bufp--; amii_curs(WIN_MESSAGE, --colx, bottom); Text(w->RPort, spaces, 1); amii_curs(WIN_MESSAGE, colx, bottom); } else DisplayBeep(NULL); } else if (c == '\n' || c == '\r') { return (sel); } else if (c >= ' ' && c < '\177') { /* avoid isprint() - some people don't have it ' ' is not always a printing char */ *bufp = c; bufp[1] = 0; oindex = 0; com_index = -1; while (extcmdlist[oindex].ef_txt != NULL) { if (!strnicmp(obufp, (char *) extcmdlist[oindex].ef_txt, strlen(obufp))) { if (com_index == -1) /* No matches yet*/ com_index = oindex; else /* More than 1 match */ com_index = -2; } oindex++; } if (com_index >= 0 && *obufp) { Strcpy(obufp, extcmdlist[com_index].ef_txt); /* finish printing our string */ colx = put_ext_cmd(obufp, colx, cw, bottom); bufp = obufp; /* reset it */ if (strlen(obufp) < BUFSZ - 1 && strlen(obufp) < COLNO) bufp += strlen(obufp); did_comp = 1; sel = com_index; } else { colx = put_ext_cmd(obufp, colx, cw, bottom); if (bufp - obufp < BUFSZ - 1 && bufp - obufp < COLNO) bufp++; } } else if (c == ('X' - 64) || c == '\177') { colx = 0; amii_clear_nhwindow(WIN_MESSAGE); pline("# "); bufp = obufp; } else DisplayBeep(NULL); } return (-1); } static int put_ext_cmd(obufp, colx, cw, bottom) char * obufp; int colx, bottom; struct amii_WinDesc *cw; { struct Window *w = cw->win; char *t; t = (char *) alloc(strlen(obufp) + 7); if (t != NULL) { if (scrollmsg) { sprintf(t, "xxx%s", obufp); t[0] = 1; t[1] = 1; t[2] = '#'; amii_curs(WIN_MESSAGE, 0, bottom); SetAPen(w->RPort, C_WHITE); Text(w->RPort, "># ", 3); /* SetAPen( w->RPort, C_BLACK ); */ /* Black text on black * screen doesn't look * too well ... -jhsa */ Text(w->RPort, t + 3, strlen(t) - 3); } else { sprintf(t, "# %s", obufp); amii_curs(WIN_MESSAGE, 0, bottom); SetAPen(w->RPort, C_WHITE); Text(w->RPort, t, strlen(t)); } if (scrollmsg) SetAPen(w->RPort, C_WHITE); if (cw->data[cw->maxrow - 1]) free(cw->data[cw->maxrow - 1]); cw->data[cw->maxrow - 1] = t; } else { amii_curs(WIN_MESSAGE, 0, bottom); SetAPen(w->RPort, C_WHITE); Text(w->RPort, "# ", 2); /* SetAPen( w->RPort, C_BLACK ); */ /* Black on black ... -jhsa */ Text(w->RPort, obufp, strlen(obufp)); SetAPen(w->RPort, C_WHITE); } amii_curs(WIN_MESSAGE, colx = strlen(obufp) + 3 + (scrollmsg != 0), bottom); return colx; } /* Ask a question and get a response */ char amii_yn_function(query, resp, def) const char * query, *resp; char def; { /* * Generic yes/no function. 'def' is the default (returned by space or * return; 'esc' returns 'q', or 'n', or the default, depending on * what's in the string. The 'query' string is printed before the user * is asked about the string. * If resp is NULL, any single character is accepted and returned. * If not-NULL, only characters in it are allowed (exceptions: the * quitchars are always allowed, and if it contains '#' then digits * are allowed); if it includes an , anything beyond that won't * be shown in the prompt to the user but will be acceptable as input. */ register char q; char rtmp[40]; boolean digit_ok, allow_num; char prompt[BUFSZ]; register struct amii_WinDesc *cw; if (cw = amii_wins[WIN_MESSAGE]) cw->disprows = 0; if (resp) { char *rb, respbuf[QBUFSZ]; allow_num = (index(resp, '#') != 0); Strcpy(respbuf, resp); /* any acceptable responses that follow aren't displayed */ if ((rb = index(respbuf, '\033')) != 0) *rb = '\0'; (void) strncpy(prompt, query, QBUFSZ - 1); prompt[QBUFSZ - 1] = '\0'; Sprintf(eos(prompt), " [%s]", respbuf); if (def) Sprintf(eos(prompt), " (%c)", def); Strcat(prompt, " "); pline("%s", prompt); } else { amii_putstr(WIN_MESSAGE, 0, query); cursor_on(WIN_MESSAGE); q = WindowGetchar(); cursor_off(WIN_MESSAGE); *rtmp = q; rtmp[1] = '\0'; amii_addtopl(rtmp); goto clean_up; } do { /* loop until we get valid input */ cursor_on(WIN_MESSAGE); q = lowc(WindowGetchar()); cursor_off(WIN_MESSAGE); #if 0 /* fix for PL2 */ if (q == '\020') { /* ctrl-P */ if(!doprev) (void) tty_doprev_message(); /* need two initially */ (void) tty_doprev_message(); q = (char)0; doprev = 1; continue; } else if (doprev) { tty_clear_nhwindow(WIN_MESSAGE); cw->maxcol = cw->maxrow; doprev = 0; amii_addtopl(prompt); continue; } #endif /*0*/ digit_ok = allow_num && isdigit(q); if (q == '\033') { if (index(resp, 'q')) q = 'q'; else if (index(resp, 'n')) q = 'n'; else q = def; break; } else if (index(quitchars, q)) { q = def; break; } if (!index(resp, q) && !digit_ok) { amii_bell(); q = (char) 0; } else if (q == '#' || digit_ok) { char z, digit_string[2]; int n_len = 0; long value = 0; amii_addtopl("#"), n_len++; digit_string[1] = '\0'; if (q != '#') { digit_string[0] = q; amii_addtopl(digit_string), n_len++; value = q - '0'; q = '#'; } do { /* loop until we get a non-digit */ cursor_on(WIN_MESSAGE); z = lowc(WindowGetchar()); cursor_off(WIN_MESSAGE); if (isdigit(z)) { value = (10 * value) + (z - '0'); if (value < 0) break; /* overflow: try again */ digit_string[0] = z; amii_addtopl(digit_string), n_len++; } else if (z == 'y' || index(quitchars, z)) { if (z == '\033') value = -1; /* abort */ z = '\n'; /* break */ } else if (z == '\b') { if (n_len <= 1) { value = -1; break; } else { value /= 10; removetopl(1), n_len--; } } else { value = -1; /* abort */ amii_bell(); break; } } while (z != '\n'); if (value > 0) yn_number = value; else if (value == 0) q = 'n'; /* 0 => "no" */ else { /* remove number from top line, then try again */ removetopl(n_len), n_len = 0; q = '\0'; } } } while (!q); if (q != '#' && q != '\033') { Sprintf(rtmp, "%c", q); amii_addtopl(rtmp); } clean_up: cursor_off(WIN_MESSAGE); clear_nhwindow(WIN_MESSAGE); return q; } void amii_display_file(fn, complain) const char * fn; boolean complain; { register struct amii_WinDesc *cw; register int win; register dlb *fp; register char *t; register char buf[200]; if (fn == NULL) panic("NULL file name in display_file()"); if ((fp = dlb_fopen(fn, RDTMODE)) == (dlb *) NULL) { if (complain) { sprintf(buf, "Can't display %s: %s", fn, #if defined(_DCC) || defined(__GNUC__) strerror(errno) #else #ifdef __SASC_60 __sys_errlist[errno] #else sys_errlist[errno] #endif #endif ); amii_addtopl(buf); } return; } win = amii_create_nhwindow(NHW_TEXT); /* Set window title to file name */ if (cw = amii_wins[win]) cw->morestr = (char *) fn; while (dlb_fgets(buf, sizeof(buf), fp) != NULL) { if (t = index(buf, '\n')) *t = 0; amii_putstr(win, 0, buf); } dlb_fclose(fp); /* If there were lines in the file, display those lines */ if (amii_wins[win]->cury > 0) amii_display_nhwindow(win, TRUE); amii_wins[win]->morestr = NULL; /* don't free title string */ amii_destroy_nhwindow(win); } /* Put a 3-D motif border around the gadget. String gadgets or those * which do not have highlighting are rendered down. Boolean gadgets * are rendered in the up position by default. */ void SetBorder(gd) register struct Gadget * gd; { register struct Border *bp; register short *sp; register int i, inc = -1, dec = -1; int borders = 6; int hipen = sysflags.amii_dripens[SHINEPEN], shadowpen = sysflags.amii_dripens[SHADOWPEN]; #ifdef INTUI_NEW_LOOK struct DrawInfo *dip; #endif #ifdef INTUI_NEW_LOOK if (IntuitionBase->LibNode.lib_Version >= 37) { if ((dip = GetScreenDrawInfo(HackScreen)) != 0) { hipen = dip->dri_Pens[SHINEPEN]; shadowpen = dip->dri_Pens[SHADOWPEN]; FreeScreenDrawInfo(HackScreen, dip); } } #endif /* Allocate two border structures one for up image and one for down * image, plus vector arrays for the border lines. */ if (gd->GadgetType == STRGADGET) borders = 12; if ((bp = (struct Border *) alloc(((sizeof (struct Border) * 2) + (sizeof (short) * borders)) * 2)) == NULL) { return; } /* For a string gadget, we expand the border beyond the area where * the text will be entered. */ /* Remove any special rendering flags to avoid confusing intuition */ gd->Flags &= ~(GADGHIGHBITS | GADGIMAGE); sp = (short *) (bp + 4); if (gd->GadgetType == STRGADGET || (gd->GadgetType == BOOLGADGET && (gd->Flags & GADGHIGHBITS) == GADGHNONE)) { sp[0] = -1; sp[1] = gd->Height - 1; sp[2] = -1; sp[3] = -1; sp[4] = gd->Width - 1; sp[5] = -1; sp[6] = gd->Width + 1; sp[7] = -2; sp[8] = gd->Width + 1; sp[9] = gd->Height + 1; sp[10] = -2; sp[11] = gd->Height + 1; sp[12] = -2; sp[13] = gd->Height; sp[14] = -2; sp[15] = -2; sp[16] = gd->Width; sp[17] = -2; sp[18] = gd->Width; sp[19] = gd->Height; sp[20] = -2; sp[21] = gd->Height; for (i = 0; i < 3; ++i) { bp[i].LeftEdge = bp[i].TopEdge = -1; bp[i].FrontPen = (i == 0 || i == 1) ? shadowpen : hipen; /* Have to use JAM2 so that the old colors disappear. */ bp[i].BackPen = C_BLACK; bp[i].DrawMode = JAM2; bp[i].Count = (i == 0 || i == 1) ? 3 : 5; bp[i].XY = &sp[i * 6]; bp[i].NextBorder = (i == 2) ? NULL : &bp[i + 1]; } /* bp[0] and bp[1] two pieces for the up image */ gd->GadgetRender = (APTR) bp; /* No image change for select */ gd->SelectRender = (APTR) bp; gd->LeftEdge++; gd->TopEdge++; gd->Flags |= GADGHCOMP; } else { /* Create the border vector values for up and left side, and * also the lower and right side. */ sp[0] = dec; sp[1] = gd->Height + inc; sp[2] = dec; sp[3] = dec; sp[4] = gd->Width + inc; sp[5] = dec; sp[6] = gd->Width + inc; sp[7] = dec; sp[8] = gd->Width + inc; sp[9] = gd->Height + inc; sp[10] = dec; sp[11] = gd->Height + inc; /* We are creating 4 sets of borders, the two sides of the * rectangle share the border vectors with the opposite image, * but specify different colors. */ for (i = 0; i < 4; ++i) { bp[i].TopEdge = bp[i].LeftEdge = 0; /* A GADGHNONE is always down */ if (gd->GadgetType == BOOLGADGET && (gd->Flags & GADGHIGHBITS) != GADGHNONE) { bp[i].FrontPen = (i == 1 || i == 2) ? shadowpen : hipen; } else { bp[i].FrontPen = (i == 1 || i == 3) ? hipen : shadowpen; } /* Have to use JAM2 so that the old colors disappear. */ bp[i].BackPen = C_BLACK; bp[i].DrawMode = JAM2; bp[i].Count = 3; bp[i].XY = &sp[6 * ((i & 1) != 0)]; bp[i].NextBorder = (i == 1 || i == 3) ? NULL : &bp[i + 1]; } /* bp[0] and bp[1] two pieces for the up image */ gd->GadgetRender = (APTR) bp; /* bp[2] and bp[3] two pieces for the down image */ gd->SelectRender = (APTR)(bp + 2); gd->Flags |= GADGHIMAGE; } } /* Following function copied from wintty.c; Modified slightly to fit amiga needs */ void amii_player_selection() { int i, k, n; char pick4u = 'n', thisch, lastch = 0; char pbuf[QBUFSZ], plbuf[QBUFSZ], rolenamebuf[QBUFSZ]; winid win; anything any; menu_item *selected = 0; rigid_role_checks(); /* Should we randomly pick for the player? */ if (flags.initrole == ROLE_NONE || flags.initrace == ROLE_NONE || flags.initgend == ROLE_NONE || flags.initalign == ROLE_NONE) { char *prompt; prompt = build_plselection_prompt(pbuf, QBUFSZ, flags.initrole, flags.initrace, flags.initgend, flags.initalign); pline("%s", prompt); do { /* loop until we get valid input */ cursor_on(WIN_MESSAGE); pick4u = lowc(WindowGetchar()); cursor_off(WIN_MESSAGE); if (index(quitchars, pick4u)) pick4u = 'y'; } while (!index(ynqchars, pick4u)); pbuf[0] = pick4u; pbuf[1] = 0; amii_addtopl(pbuf); if (pick4u != 'y' && pick4u != 'n') { give_up: /* Quit */ if (selected) free((genericptr_t) selected); clearlocks(); exit_nhwindows(NULL); nh_terminate(0); /*NOTREACHED*/ return; } } (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole, flags.initrace, flags.initgend, flags.initalign); /* Select a role, if necessary */ /* we'll try to be compatible with pre-selected race/gender/alignment, * but may not succeed */ if (flags.initrole < 0) { /* Process the choice */ if (pick4u == 'y' || flags.initrole == ROLE_RANDOM || flags.randomall) { /* Pick a random role */ flags.initrole = pick_role(flags.initrace, flags.initgend, flags.initalign, PICK_RANDOM); if (flags.initrole < 0) { amii_putstr(WIN_MESSAGE, 0, "Incompatible role!"); flags.initrole = randrole(FALSE); } } else { /* Prompt for a role */ win = create_nhwindow(NHW_MENU); start_menu(win, MENU_BEHAVE_STANDARD); any.a_void = 0; /* zero out all bits */ for (i = 0; roles[i].name.m; i++) { if (ok_role(i, flags.initrace, flags.initgend, flags.initalign)) { any.a_int = i + 1; /* must be non-zero */ thisch = lowc(roles[i].name.m[0]); if (thisch == lastch) thisch = highc(thisch); if (flags.initgend != ROLE_NONE && flags.initgend != ROLE_RANDOM) { if (flags.initgend == 1 && roles[i].name.f) Strcpy(rolenamebuf, roles[i].name.f); else Strcpy(rolenamebuf, roles[i].name.m); } else { if (roles[i].name.f) { Strcpy(rolenamebuf, roles[i].name.m); Strcat(rolenamebuf, "/"); Strcat(rolenamebuf, roles[i].name.f); } else Strcpy(rolenamebuf, roles[i].name.m); } add_menu(win, NO_GLYPH, &any, thisch, 0, ATR_NONE, an(rolenamebuf), MENU_ITEMFLAGS_NONE); lastch = thisch; } } any.a_int = pick_role(flags.initrace, flags.initgend, flags.initalign, PICK_RANDOM) + 1; if (any.a_int == 0) /* must be non-zero */ any.a_int = randrole(FALSE) + 1; add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random", MENU_ITEMFLAGS_NONE); any.a_int = i + 1; /* must be non-zero */ add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit", MENU_ITEMFLAGS_NONE); Sprintf(pbuf, "Pick a role for your %s", plbuf); end_menu(win, pbuf); n = select_menu(win, PICK_ONE, &selected); destroy_nhwindow(win); /* Process the choice */ if (n != 1 || selected[0].item.a_int == any.a_int) goto give_up; /* Selected quit */ flags.initrole = selected[0].item.a_int - 1; free((genericptr_t) selected), selected = 0; } (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole, flags.initrace, flags.initgend, flags.initalign); } /* Select a race, if necessary */ /* force compatibility with role, try for compatibility with * pre-selected gender/alignment */ if (flags.initrace < 0 || !validrace(flags.initrole, flags.initrace)) { /* pre-selected race not valid */ if (pick4u == 'y' || flags.initrace == ROLE_RANDOM || flags.randomall) { flags.initrace = pick_race(flags.initrole, flags.initgend, flags.initalign, PICK_RANDOM); if (flags.initrace < 0) { amii_putstr(WIN_MESSAGE, 0, "Incompatible race!"); flags.initrace = randrace(flags.initrole); } } else { /* pick4u == 'n' */ /* Count the number of valid races */ n = 0; /* number valid */ k = 0; /* valid race */ for (i = 0; races[i].noun; i++) { if (ok_race(flags.initrole, i, flags.initgend, flags.initalign)) { n++; k = i; } } if (n == 0) { for (i = 0; races[i].noun; i++) { if (validrace(flags.initrole, i)) { n++; k = i; } } } /* Permit the user to pick, if there is more than one */ if (n > 1) { win = create_nhwindow(NHW_MENU); start_menu(win, MENU_BEHAVE_STANDARD); any.a_void = 0; /* zero out all bits */ for (i = 0; races[i].noun; i++) if (ok_race(flags.initrole, i, flags.initgend, flags.initalign)) { any.a_int = i + 1; /* must be non-zero */ add_menu(win, NO_GLYPH, &any, races[i].noun[0], 0, ATR_NONE, races[i].noun, MENU_ITEMFLAGS_NONE); } any.a_int = pick_race(flags.initrole, flags.initgend, flags.initalign, PICK_RANDOM) + 1; if (any.a_int == 0) /* must be non-zero */ any.a_int = randrace(flags.initrole) + 1; add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random", MENU_ITEMFLAGS_NONE); any.a_int = i + 1; /* must be non-zero */ add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit", MENU_ITEMFLAGS_NONE); Sprintf(pbuf, "Pick the race of your %s", plbuf); end_menu(win, pbuf); n = select_menu(win, PICK_ONE, &selected); destroy_nhwindow(win); if (n != 1 || selected[0].item.a_int == any.a_int) goto give_up; /* Selected quit */ k = selected[0].item.a_int - 1; free((genericptr_t) selected), selected = 0; } flags.initrace = k; } (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole, flags.initrace, flags.initgend, flags.initalign); } /* Select a gender, if necessary */ /* force compatibility with role/race, try for compatibility with * pre-selected alignment */ if (flags.initgend < 0 || !validgend(flags.initrole, flags.initrace, flags.initgend)) { /* pre-selected gender not valid */ if (pick4u == 'y' || flags.initgend == ROLE_RANDOM || flags.randomall) { flags.initgend = pick_gend(flags.initrole, flags.initrace, flags.initalign, PICK_RANDOM); if (flags.initgend < 0) { amii_putstr(WIN_MESSAGE, 0, "Incompatible gender!"); flags.initgend = randgend(flags.initrole, flags.initrace); } } else { /* pick4u == 'n' */ /* Count the number of valid genders */ n = 0; /* number valid */ k = 0; /* valid gender */ for (i = 0; i < ROLE_GENDERS; i++) { if (ok_gend(flags.initrole, flags.initrace, i, flags.initalign)) { n++; k = i; } } if (n == 0) { for (i = 0; i < ROLE_GENDERS; i++) { if (validgend(flags.initrole, flags.initrace, i)) { n++; k = i; } } } /* Permit the user to pick, if there is more than one */ if (n > 1) { win = create_nhwindow(NHW_MENU); start_menu(win, MENU_BEHAVE_STANDARD); any.a_void = 0; /* zero out all bits */ for (i = 0; i < ROLE_GENDERS; i++) if (ok_gend(flags.initrole, flags.initrace, i, flags.initalign)) { any.a_int = i + 1; add_menu(win, NO_GLYPH, &any, genders[i].adj[0], 0, ATR_NONE, genders[i].adj, MENU_ITEMFLAGS_NONE); } any.a_int = pick_gend(flags.initrole, flags.initrace, flags.initalign, PICK_RANDOM) + 1; if (any.a_int == 0) /* must be non-zero */ any.a_int = randgend(flags.initrole, flags.initrace) + 1; add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random", MENU_ITEMFLAGS_NONE); any.a_int = i + 1; /* must be non-zero */ add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit", MENU_ITEMFLAGS_NONE); Sprintf(pbuf, "Pick the gender of your %s", plbuf); end_menu(win, pbuf); n = select_menu(win, PICK_ONE, &selected); destroy_nhwindow(win); if (n != 1 || selected[0].item.a_int == any.a_int) goto give_up; /* Selected quit */ k = selected[0].item.a_int - 1; free((genericptr_t) selected), selected = 0; } flags.initgend = k; } (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole, flags.initrace, flags.initgend, flags.initalign); } /* Select an alignment, if necessary */ /* force compatibility with role/race/gender */ if (flags.initalign < 0 || !validalign(flags.initrole, flags.initrace, flags.initalign)) { /* pre-selected alignment not valid */ if (pick4u == 'y' || flags.initalign == ROLE_RANDOM || flags.randomall) { flags.initalign = pick_align(flags.initrole, flags.initrace, flags.initgend, PICK_RANDOM); if (flags.initalign < 0) { amii_putstr(WIN_MESSAGE, 0, "Incompatible alignment!"); flags.initalign = randalign(flags.initrole, flags.initrace); } } else { /* pick4u == 'n' */ /* Count the number of valid alignments */ n = 0; /* number valid */ k = 0; /* valid alignment */ for (i = 0; i < ROLE_ALIGNS; i++) { if (ok_align(flags.initrole, flags.initrace, flags.initgend, i)) { n++; k = i; } } if (n == 0) { for (i = 0; i < ROLE_ALIGNS; i++) { if (validalign(flags.initrole, flags.initrace, i)) { n++; k = i; } } } /* Permit the user to pick, if there is more than one */ if (n > 1) { win = create_nhwindow(NHW_MENU); start_menu(win, MENU_BEHAVE_STANDARD); any.a_void = 0; /* zero out all bits */ for (i = 0; i < ROLE_ALIGNS; i++) if (ok_align(flags.initrole, flags.initrace, flags.initgend, i)) { any.a_int = i + 1; add_menu(win, NO_GLYPH, &any, aligns[i].adj[0], 0, ATR_NONE, aligns[i].adj, MENU_ITEMFLAGS_NONE); } any.a_int = pick_align(flags.initrole, flags.initrace, flags.initgend, PICK_RANDOM) + 1; if (any.a_int == 0) /* must be non-zero */ any.a_int = randalign(flags.initrole, flags.initrace) + 1; add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random", MENU_ITEMFLAGS_NONE); any.a_int = i + 1; /* must be non-zero */ add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit", MENU_ITEMFLAGS_NONE); Sprintf(pbuf, "Pick the alignment of your %s", plbuf); end_menu(win, pbuf); n = select_menu(win, PICK_ONE, &selected); destroy_nhwindow(win); if (n != 1 || selected[0].item.a_int == any.a_int) goto give_up; /* Selected quit */ k = selected[0].item.a_int - 1; free((genericptr_t) selected), selected = 0; } flags.initalign = k; } } /* Success! */ } #endif /* AMIGA_INTUITION */