/* SCCS Id: @(#)winami.c 3.2 2000/01/12 */ /* 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", 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, 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 }; /* 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", 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, 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 }; unsigned short amii_initmap[ AMII_MAXCOLORS ]; /* Default pens used unless use 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 struct TagItem tags[] = { { 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,CUSTOMSCREEN, #ifdef INTUI_NEW_LOOK tags #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,CUSTOMSCREEN, #ifdef INTUI_NEW_LOOK tags #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,CUSTOMSCREEN, #ifdef INTUI_NEW_LOOK tags #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,CUSTOMSCREEN, #ifdef INTUI_NEW_LOOK tags #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,CUSTOMSCREEN, #ifdef INTUI_NEW_LOOK tags #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,CUSTOMSCREEN, #ifdef INTUI_NEW_LOOK tags #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,CUSTOMSCREEN, #ifdef INTUI_NEW_LOOK tags #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() { *plname = 0; do { amii_getlin( "Who are you?", plname ); } while( strlen( plname ) == 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 */ #ifdef TOURIST strcpy( pl_character, roles[ rnd( 11 ) ] ); #else strcpy( pl_character, roles[ rnd( 10 ) ] ); #endif #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 */ #ifdef TOURIST strcpy( pl_character, roles[ rnd( 11 ) ] ); #else strcpy( pl_character, roles[ rnd( 10 ) ] ); #endif #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 = CreatePort( 0, 0 ); trq = (struct timerequest *)CreateExtIO( tport, sizeof( *trq ) ); if( tport == NULL || trq == NULL ) { allocerr: if( tport ) DeletePort( tport ); if( trq ) DeleteExtIO( (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 ); DeleteExtIO( (struct IORequest *) trq ); DeletePort( 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 ); DeleteExtIO( (struct IORequest *) trq ); DeletePort( 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 , 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[QBUFSZ]; 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'; Sprintf(prompt, "%s [%s] ", query, respbuf); if (def) Sprintf(eos(prompt), "(%c) ", def); 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, #ifdef _DCC 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 = flags.amii_dripens[ SHINEPEN ], shadowpen = flags.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]; winid win; anything any; menu_item *selected = 0; /* Should we randomly pick for the player? */ if (flags.initrole == ROLE_NONE || flags.initrace == ROLE_NONE || flags.initgend == ROLE_NONE || flags.initalign == ROLE_NONE) { const char *prompt = "Shall I pick a character for you?"; pick4u = amii_yn_function(prompt, "ynq", 'y'); if (pick4u != 'y' && pick4u != 'n') { give_up: /* Quit */ if (selected) free((genericptr_t) selected); exit_nhwindows(NULL); terminate(0); /*NOTREACHED*/ return; } } /* 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) { /* Pick a random role */ flags.initrole = pick_role(flags.initrace, flags.initgend, flags.initalign); 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); add_menu(win, NO_GLYPH, &any, thisch, 0, ATR_NONE, an(roles[i].name.m), MENU_UNSELECTED); lastch = thisch; } } any.a_int = pick_role(flags.initrace, flags.initgend, flags.initalign)+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); end_menu(win, "Pick a role"); 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; } } /* 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.initrace = pick_race(flags.initrole, flags.initgend, flags.initalign); 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)+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", roles[flags.initrole].name.m); 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; } } /* 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.initgend = pick_gend(flags.initrole, flags.initrace, flags.initalign); 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)+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 %s", races[flags.initrace].adj, roles[flags.initrole].name.m); 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; } } /* 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.initalign = pick_align(flags.initrole, flags.initrace, flags.initgend); 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)+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 %s %s", genders[flags.initgend].adj, races[flags.initrace].adj, (flags.initgend && roles[flags.initrole].name.f) ? roles[flags.initrole].name.f : roles[flags.initrole].name.m); 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 */