Files
nethack/sys/amiga/winami.c
2015-02-27 19:33:12 -05:00

1748 lines
44 KiB
C

/* NetHack 3.5 winami.c $NHDT-Date$ $NHDT-Branch$:$NHDT-Revision$ */
/* NetHack 3.5 winami.c $Date: 2012/01/10 17:47:21 $ $Revision: 1.13 $ */
/* 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,
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,
#ifdef STATUS_VIA_WINDOWPORT
genl_status_init,
genl_status_finish,
genl_status_enablefield,
genl_status_update,
# ifdef STATUS_HILITES
genl_status_threshold,
# endif
#endif
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,
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,
#ifdef STATUS_VIA_WINDOWPORT
genl_status_init,
genl_status_finish,
genl_status_enablefield,
genl_status_update,
# ifdef STATUS_HILITES
genl_status_threshold,
# endif
#endif
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(plname, plnametmp, PL_NSIZ-1); /* Avoid overflowing plname[] */
plname[PL_NSIZ-1] = 0;
if( *plname == '\33' )
{
clearlocks();
exit_nhwindows(NULL);
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();
return;
}
#if 0 /* Don't query the user ... instead give random character -jhsa */
#if 0 /* OBSOLETE */
if( *pl_character ){
pl_character[ 0 ] = toupper( pl_character[ 0 ] );
if( index( pl_classes, 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 ) ) )
{
pl_character[0] = toupper( code );
aredone = 1;
}
else if( code == ' ' || code == '\n' || code == '\r' )
{
flags.initrole = randrole();
#if 0 /* OBSOLETE */
strcpy( pl_character, roles[ rnd( 11 ) ] );
#endif
aredone = 1;
amii_clear_nhwindow( WIN_BASE );
CloseShWindow( cwin );
RandomWindow( pl_character );
return;
}
else if( code == 'q' || code == 'Q' )
{
CloseShWindow( cwin );
clearlocks();
exit_nhwindows(NULL);
terminate(0);
}
else
DisplayBeep( NULL );
break;
case GADGETUP:
switch( gd->GadgetID )
{
case 1: /* Random Character */
flags.initrole = randrole();
#if 0 /* OBSOLETE */
strcpy( pl_character, roles[ rnd( 11 ) ] );
#endif
amii_clear_nhwindow( WIN_BASE );
CloseShWindow( cwin );
RandomWindow( pl_character );
return;
default:
pl_character[0] = gd->GadgetID;
break;
}
aredone = 1;
break;
case CLOSEWINDOW:
CloseShWindow( cwin );
clearlocks();
exit_nhwindows(NULL);
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 );
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_UNSELECTED);
}
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 );
} else {
#else
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 );
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_UNSELECTED);
}
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);
#endif
}
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 <esc>, 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 <esc> 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
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 ) )
{
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 = 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);
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();
}
} else {
/* Prompt for a role */
win = create_nhwindow(NHW_MENU);
start_menu(win);
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_UNSELECTED);
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()+1;
add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE,
"Random", MENU_UNSELECTED);
any.a_int = i+1; /* must be non-zero */
add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE,
"Quit", MENU_UNSELECTED);
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);
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_UNSELECTED);
}
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_UNSELECTED);
any.a_int = i+1; /* must be non-zero */
add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE,
"Quit", MENU_UNSELECTED);
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);
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_UNSELECTED);
}
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_UNSELECTED);
any.a_int = i+1; /* must be non-zero */
add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE,
"Quit", MENU_UNSELECTED);
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);
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_UNSELECTED);
}
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_UNSELECTED);
any.a_int = i+1; /* must be non-zero */
add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE,
"Quit", MENU_UNSELECTED);
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 */