1 /* NetHack 3.6 winami.c $NHDT-Date: 1501981093 2017/08/06 00:58:13 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.20 $ */
2 /* Copyright (c) Gregg Wonderly, Naperville, Illinois, 1991,1992,1993,1996.
4 /* NetHack may be freely redistributed. See license for details. */
6 #include "NH:sys/amiga/windefs.h"
7 #include "NH:sys/amiga/winext.h"
8 #include "NH:sys/amiga/winproto.h"
11 #ifdef AMIGA_INTUITION
13 static int FDECL(put_ext_cmd, (char *, int, struct amii_WinDesc *, int));
15 struct amii_DisplayDesc *amiIDisplay; /* the Amiga Intuition descriptor */
16 struct Rectangle lastinvent, lastmsg;
27 /* Interface definition, for use by windows.c and winprocs.h to provide
28 * the intuition interface for the amiga...
30 struct window_procs amii_procs = {
31 "amii", WC_COLOR | WC_HILITE_PET | WC_INVERSE, 0L, amii_init_nhwindows,
32 amii_player_selection, amii_askname, amii_get_nh_event,
33 amii_exit_nhwindows, amii_suspend_nhwindows, amii_resume_nhwindows,
34 amii_create_nhwindow, amii_clear_nhwindow, amii_display_nhwindow,
35 amii_destroy_nhwindow, amii_curs, amii_putstr, genl_putmixed,
36 amii_display_file, amii_start_menu, amii_add_menu, amii_end_menu,
37 amii_select_menu, genl_message_menu, amii_update_inventory,
38 amii_mark_synch, amii_wait_synch,
45 amii_print_glyph, amii_raw_print, amii_raw_print_bold, amii_nhgetch,
46 amii_nh_poskey, amii_bell, amii_doprev_message, amii_yn_function,
47 amii_getlin, amii_get_ext_cmd, amii_number_pad, amii_delay_output,
48 #ifdef CHANGE_COLOR /* only a Mac option currently */
49 amii_change_color, amii_get_color_string,
51 /* other defs that really should go away (they're tty specific) */
52 amii_delay_output, amii_delay_output, amii_outrip, genl_preference_update,
53 genl_getmsghistory, genl_putmsghistory,
54 genl_status_init, genl_status_finish, genl_status_enablefield,
59 /* The view window layout uses the same function names so we can use
60 * a shared library to allow the executable to be smaller.
62 struct window_procs amiv_procs = {
63 "amitile", WC_COLOR | WC_HILITE_PET | WC_INVERSE, 0L, amii_init_nhwindows,
64 amii_player_selection, amii_askname, amii_get_nh_event,
65 amii_exit_nhwindows, amii_suspend_nhwindows, amii_resume_nhwindows,
66 amii_create_nhwindow, amii_clear_nhwindow, amii_display_nhwindow,
67 amii_destroy_nhwindow, amii_curs, amii_putstr, genl_putmixed,
68 amii_display_file, amii_start_menu, amii_add_menu, amii_end_menu,
69 amii_select_menu, genl_message_menu, amii_update_inventory,
70 amii_mark_synch, amii_wait_synch,
77 amii_print_glyph, amii_raw_print, amii_raw_print_bold, amii_nhgetch,
78 amii_nh_poskey, amii_bell, amii_doprev_message, amii_yn_function,
79 amii_getlin, amii_get_ext_cmd, amii_number_pad, amii_delay_output,
80 #ifdef CHANGE_COLOR /* only a Mac option currently */
81 amii_change_color, amii_get_color_string,
83 /* other defs that really should go away (they're tty specific) */
84 amii_delay_output, amii_delay_output, amii_outrip, genl_preference_update,
85 genl_getmsghistory, genl_putmsghistory,
86 genl_status_init, genl_status_finish, genl_status_enablefield,
91 unsigned short amii_initmap[AMII_MAXCOLORS];
92 /* Default pens used unless user overides in nethack.cnf. */
93 unsigned short amii_init_map[AMII_MAXCOLORS] = {
94 0x0000, /* color #0 C_BLACK */
95 0x0FFF, /* color #1 C_WHITE */
96 0x0830, /* color #2 C_BROWN */
97 0x07ac, /* color #3 C_CYAN */
98 0x0181, /* color #4 C_GREEN */
99 0x0C06, /* color #5 C_MAGENTA */
100 0x023E, /* color #6 C_BLUE */
101 0x0c00, /* color #7 C_RED */
104 unsigned short amiv_init_map[AMII_MAXCOLORS] = {
105 0x0000, /* color #0 C_BLACK */
106 0x0fff, /* color #1 C_WHITE */
107 0x00bf, /* color #2 C_CYAN */
108 0x0f60, /* color #3 C_ORANGE */
109 0x000f, /* color #4 C_BLUE */
110 0x0090, /* color #5 C_GREEN */
111 0x069b, /* color #6 C_GREY */
112 0x0f00, /* color #7 C_RED */
113 0x06f0, /* color #8 C_LTGREEN */
114 0x0ff0, /* color #9 C_YELLOW */
115 0x0f0f, /* color #10 C_MAGENTA */
116 0x0940, /* color #11 C_BROWN */
117 0x0466, /* color #12 C_GREYBLUE */
118 0x0c40, /* color #13 C_LTBROWN */
119 0x0ddb, /* color #14 C_LTGREY */
120 0x0fb9, /* color #15 C_PEACH */
122 /* Pens for dripens etc under AA or better */
123 0x0222, /* color #16 */
124 0x0fdc, /* color #17 */
125 0x0000, /* color #18 */
126 0x0ccc, /* color #19 */
127 0x0bbb, /* color #20 */
128 0x0BA9, /* color #21 */
129 0x0999, /* color #22 */
130 0x0987, /* color #23 */
131 0x0765, /* color #24 */
132 0x0666, /* color #25 */
133 0x0555, /* color #26 */
134 0x0533, /* color #27 */
135 0x0333, /* color #28 */
136 0x018f, /* color #29 */
137 0x0f81, /* color #30 */
138 0x0fff, /* color #31 */
141 #if !defined(TTY_GRAPHICS) \
142 || defined(SHAREDLIB) /* this should be shared better */
143 char morc; /* the character typed in response to a --more-- prompt */
145 char spaces[76] = " "
148 winid WIN_BASE = WIN_ERR;
149 winid WIN_OVER = WIN_ERR;
150 winid amii_rawprwin = WIN_ERR;
152 /* Changed later during window/screen opens... */
153 int txwidth = FONTWIDTH, txheight = FONTHEIGHT, txbaseline = FONTBASELINE;
155 /* If a 240 or more row screen is in front when we start, this will be
156 * set to 1, and the windows will be given borders to allow them to be
157 * arranged differently. The Message window may eventually get a scroller...
161 /* This gadget data is replicated for menu/text windows... */
162 struct PropInfo PropScroll = {
163 AUTOKNOB | FREEVERT, 0xffff, 0xffff, 0xffff, 0xffff,
165 struct Image Image1 = { 0, 0, 7, 102, 0, NULL, 0x0000, 0x0000, NULL };
166 struct Gadget MenuScroll = { NULL, -15, 10, 15, -19, GRELRIGHT | GRELHEIGHT,
167 RELVERIFY | FOLLOWMOUSE | RIGHTBORDER
168 | GADGIMMEDIATE | RELVERIFY,
169 PROPGADGET, (APTR) &Image1, NULL, NULL, NULL,
170 (APTR) &PropScroll, 1, NULL };
172 /* This gadget is for the message window... */
173 struct PropInfo MsgPropScroll = {
174 AUTOKNOB | FREEVERT, 0xffff, 0xffff, 0xffff, 0xffff,
176 struct Image MsgImage1 = { 0, 0, 7, 102, 0, NULL, 0x0000, 0x0000, NULL };
177 struct Gadget MsgScroll = { NULL, -15, 10, 14, -19, GRELRIGHT | GRELHEIGHT,
178 RELVERIFY | FOLLOWMOUSE | RIGHTBORDER
179 | GADGIMMEDIATE | RELVERIFY,
180 PROPGADGET, (APTR) &MsgImage1, NULL, NULL, NULL,
181 (APTR) &MsgPropScroll, 1, NULL };
183 int wincnt = 0; /* # of nh windows opened */
185 /* We advertise a public screen to allow some people to do other things
186 * while they are playing... like compiling...
189 #ifdef INTUI_NEW_LOOK
190 extern struct Hook fillhook;
191 struct TagItem tags[] = {
192 { WA_BackFill, (ULONG) &fillhook },
193 { WA_PubScreenName, (ULONG) "NetHack" },
199 * The default dimensions and status values for each window type. The
200 * data here is generally changed in create_nhwindow(), so beware that
201 * what you see here may not be exactly what you get.
203 struct win_setup new_wins[] = {
205 /* First entry not used, types are based at 1 */
209 { { 0, 1, 640, 11, 0xff, 0xff,
210 NEWSIZE | GADGETUP | GADGETDOWN | MOUSEMOVE | MOUSEBUTTONS | RAWKEY,
211 BORDERLESS | ACTIVATE | SMART_REFRESH
212 #ifdef INTUI_NEW_LOOK
216 NULL, NULL, (UBYTE *) "Messages", NULL, NULL, 320, 40, 0xffff, 0xffff,
217 #ifdef INTUI_NEW_LOOK
231 { { 0, 181, 640, 24, 0xff, 0xff, RAWKEY | MENUPICK | DISKINSERTED,
232 BORDERLESS | ACTIVATE | SMART_REFRESH | BACKDROP
233 #ifdef INTUI_NEW_LOOK
237 NULL, NULL, (UBYTE *) "Game Status", NULL, NULL, 0, 0, 0xffff, 0xffff,
238 #ifdef INTUI_NEW_LOOK
252 { { 0, 0, WIDTH, WINDOWHEIGHT, 0xff, 0xff,
253 RAWKEY | MENUPICK | MOUSEBUTTONS | ACTIVEWINDOW | MOUSEMOVE,
254 BORDERLESS | ACTIVATE | SMART_REFRESH | BACKDROP
255 #ifdef INTUI_NEW_LOOK
259 NULL, NULL, (UBYTE *) "Dungeon Map", NULL, NULL, 64, 64, 0xffff,
261 #ifdef INTUI_NEW_LOOK
275 { { 400, 10, 10, 10, 0xff, 0xff,
276 RAWKEY | MENUPICK | DISKINSERTED | MOUSEMOVE | MOUSEBUTTONS | GADGETUP
277 | GADGETDOWN | CLOSEWINDOW | VANILLAKEY | NEWSIZE
279 WINDOWSIZING | WINDOWCLOSE | WINDOWDRAG | ACTIVATE | SMART_REFRESH
280 #ifdef INTUI_NEW_LOOK
284 &MenuScroll, NULL, NULL, NULL, NULL, 64, 32, 0xffff, 0xffff,
285 #ifdef INTUI_NEW_LOOK
299 { { 0, 0, 640, 200, 0xff, 0xff,
300 RAWKEY | MENUPICK | DISKINSERTED | MOUSEMOVE | GADGETUP | CLOSEWINDOW
301 | VANILLAKEY | NEWSIZE,
302 WINDOWSIZING | WINDOWCLOSE | WINDOWDRAG | ACTIVATE | SMART_REFRESH
303 #ifdef INTUI_NEW_LOOK
307 &MenuScroll, NULL, (UBYTE *) NULL, NULL, NULL, 100, 32, 0xffff,
309 #ifdef INTUI_NEW_LOOK
323 { { 0, 0, WIDTH, WINDOWHEIGHT, 0xff, 0xff,
324 RAWKEY | MENUPICK | MOUSEBUTTONS,
325 BORDERLESS | ACTIVATE | SMART_REFRESH | BACKDROP
326 #ifdef INTUI_NEW_LOOK
330 NULL, NULL, (UBYTE *) NULL, NULL, NULL, -1, -1, 0xffff, 0xffff,
331 #ifdef INTUI_NEW_LOOK
345 { { 320, 20, 319, 179, 0xff, 0xff, RAWKEY | MENUPICK | MOUSEBUTTONS,
346 BORDERLESS | ACTIVATE | SMART_REFRESH | BACKDROP
347 #ifdef INTUI_NEW_LOOK
351 NULL, NULL, (UBYTE *) NULL, NULL, NULL, 64, 32, 0xffff, 0xffff,
352 #ifdef INTUI_NEW_LOOK
366 const char winpanicstr[] = "Bad winid %d in %s()";
368 /* The opened windows information */
369 struct amii_WinDesc *amii_wins[MAXWIN + 1];
371 #ifdef INTUI_NEW_LOOK
373 * NUMDRIPENS varies based on headers, so don't use it
374 * here, its value is used elsewhere.
376 UWORD amii_defpens[20];
378 struct TagItem scrntags[] = {
379 { SA_PubName, (ULONG) "NetHack" },
380 { SA_Overscan, OSCAN_TEXT },
381 { SA_AutoScroll, TRUE },
382 #if LIBRARY_VERSION >= 39
383 { SA_Interleaved, TRUE },
385 { SA_Pens, (ULONG) 0 },
392 struct NewScreen NewHackScreen = { 0, 0, WIDTH, SCREENHEIGHT, 3, 0,
393 1, /* DetailPen, BlockPen */
395 #ifdef INTUI_NEW_LOOK
400 NULL, /*(UBYTE *)" NetHack X.Y.Z" */
402 NULL, /* CustomBitmap */
403 #ifdef INTUI_NEW_LOOK
409 * plname is filled either by an option (-u Player or -uPlayer) or
410 * explicitly (by being the wizard) or by askname.
411 * It may still contain a suffix denoting pl_character.
412 * Always called after init_nhwindows() and before display_gamewindows().
417 char plnametmp[300]; /* From winreq.c: sizeof(StrStringSIBuff) */
420 amii_getlin("Who are you?", plnametmp);
421 } while (strlen(plnametmp) == 0);
423 strncpy(plname, plnametmp, PL_NSIZ - 1); /* Avoid overflowing plname[] */
424 plname[PL_NSIZ - 1] = 0;
426 if (*plname == '\33') {
428 exit_nhwindows(NULL);
433 /* Discarded ... -jhsa
434 #include "NH:sys/amiga/char.c"
437 /* Get the player selection character */
439 #if 0 /* New function at the bottom */
441 amii_player_selection()
443 register struct Window *cwin;
444 register struct IntuiMessage *imsg;
445 register int aredone = 0;
446 register struct Gadget *gd;
450 amii_clear_nhwindow( WIN_BASE );
451 if (validrole(flags.initrole))
454 flags.initrole = randrole(FALSE);
457 #if 0 /* Don't query the user ... instead give random character -jhsa */
461 pl_character[ 0 ] = toupper( pl_character[ 0 ] );
462 if( index( pl_classes, pl_character[ 0 ] ) )
469 Type_NewWindowStructure1.TopEdge =
470 (HackScreen->Height/2) - (Type_NewWindowStructure1.Height/2);
472 for( gd = Type_NewWindowStructure1.FirstGadget; gd;
473 gd = gd->NextGadget )
475 if( gd->GadgetID != 0 )
483 #ifdef INTUI_NEW_LOOK
484 Type_NewWindowStructure1.Extension = wintags;
485 Type_NewWindowStructure1.Flags |= WFLG_NW_EXTENDED;
486 fillhook.h_Entry = (ULONG(*)())LayerFillHook;
487 fillhook.h_Data = (void *)-2;
488 fillhook.h_SubEntry = 0;
492 Type_NewWindowStructure1.Screen = HackScreen;
493 if( ( cwin = OpenShWindow( (void *)&Type_NewWindowStructure1 ) ) == NULL )
498 WindowToFront( cwin );
503 WaitPort( cwin->UserPort );
504 while( ( imsg = (void *) GetMsg( cwin->UserPort ) ) != NULL )
508 gd = (struct Gadget *)imsg->IAddress;
509 ReplyMsg( (struct Message *)imsg );
514 if( index( pl_classes, toupper( code ) ) )
516 pl_character[0] = toupper( code );
519 else if( code == ' ' || code == '\n' || code == '\r' )
521 flags.initrole = randrole(FALSE);
523 strcpy( pl_character, roles[ rnd( 11 ) ] );
526 amii_clear_nhwindow( WIN_BASE );
527 CloseShWindow( cwin );
528 RandomWindow( pl_character );
531 else if( code == 'q' || code == 'Q' )
533 CloseShWindow( cwin );
535 exit_nhwindows(NULL);
543 switch( gd->GadgetID )
545 case 1: /* Random Character */
546 flags.initrole = randrole(FALSE);
548 strcpy( pl_character, roles[ rnd( 11 ) ] );
550 amii_clear_nhwindow( WIN_BASE );
551 CloseShWindow( cwin );
552 RandomWindow( pl_character );
556 pl_character[0] = gd->GadgetID;
563 CloseShWindow( cwin );
565 exit_nhwindows(NULL);
571 amii_clear_nhwindow( WIN_BASE );
572 CloseShWindow( cwin );
573 #endif /* Do not query user ... -jhsa */
575 #endif /* Function elsewhere */
577 #if 0 /* Unused ... -jhsa */
579 #include "NH:sys/amiga/randwin.c"
585 struct MsgPort *tport;
586 struct timerequest *trq;
590 struct IntuiMessage *imsg;
591 int ticks = 0, aredone = 0, timerdone = 0;
594 tport = CreateMsgPort();
595 trq = (struct timerequest *)CreateIORequest( tport, sizeof( *trq ) );
596 if( tport == NULL || trq == NULL )
599 if( tport ) DeleteMsgPort( tport );
600 if( trq ) DeleteIORequest( (struct IORequest *)trq );
605 if( OpenDevice( TIMERNAME, UNIT_VBLANK, (struct IORequest *)trq, 0L ) != 0 )
608 trq->tr_node.io_Command = TR_ADDREQUEST;
609 trq->tr_time.tv_secs = 8;
610 trq->tr_time.tv_micro = 0;
612 SendIO( (struct IORequest *)trq );
614 /* Place the name in the center of the screen */
615 Rnd_IText5.IText = name;
616 Rnd_IText6.LeftEdge = Rnd_IText4.LeftEdge +
617 (strlen(Rnd_IText4.IText)+1)*8;
618 Rnd_NewWindowStructure1.Width = (
619 (strlen( Rnd_IText2.IText )+1) * 8 ) +
620 HackScreen->WBorLeft + HackScreen->WBorRight;
621 Rnd_IText5.LeftEdge = (Rnd_NewWindowStructure1.Width -
624 gd = Rnd_NewWindowStructure1.FirstGadget;
625 gd->LeftEdge = (Rnd_NewWindowStructure1.Width - gd->Width)/2;
626 /* Chose correct modifier */
627 Rnd_IText6.IText = "a";
630 case 'a': case 'e': case 'i': case 'o':
631 case 'u': case 'A': case 'E': case 'I':
633 Rnd_IText6.IText = "an";
641 Rnd_NewWindowStructure1.TopEdge =
642 (HackScreen->Height/2) - (Rnd_NewWindowStructure1.Height/2);
644 for( gd = Rnd_NewWindowStructure1.FirstGadget; gd; gd = gd->NextGadget )
646 if( gd->GadgetID != 0 )
649 Rnd_NewWindowStructure1.IDCMPFlags |= VANILLAKEY;
656 #ifdef INTUI_NEW_LOOK
657 Rnd_NewWindowStructure1.Extension = wintags;
658 Rnd_NewWindowStructure1.Flags |= WFLG_NW_EXTENDED;
659 fillhook.h_Entry = (ULONG(*)())LayerFillHook;
660 fillhook.h_Data = (void *)-2;
661 fillhook.h_SubEntry = 0;
665 Rnd_NewWindowStructure1.Screen = HackScreen;
666 if( ( w = OpenShWindow( (void *)&Rnd_NewWindowStructure1 ) ) == NULL )
668 AbortIO( (struct IORequest *)trq );
669 WaitIO( (struct IORequest *)trq );
670 CloseDevice( (struct IORequest *)trq );
671 DeleteIORequest( (struct IORequest *) trq );
672 DeleteMsgPort( tport );
677 PrintIText( w->RPort, &Rnd_IntuiTextList1, 0, 0 );
679 mask = (1L << tport->mp_SigBit)|(1L << w->UserPort->mp_SigBit);
683 if( got & (1L << tport->mp_SigBit ) )
689 while( w && ( imsg = (struct IntuiMessage *) GetMsg( w->UserPort ) ) )
691 switch( (long)imsg->Class )
693 /* Must be up for a little while... */
708 if(imsg->Code=='\n' || imsg->Code==' ' || imsg->Code=='\r')
712 ReplyMsg( (struct Message *)imsg );
718 AbortIO( (struct IORequest *)trq );
719 WaitIO( (struct IORequest *)trq );
722 CloseDevice( (struct IORequest *)trq );
723 DeleteIORequest( (struct IORequest *) trq );
724 DeleteMsgPort( tport );
725 if(w) CloseShWindow( w );
727 #endif /* Discarded randwin ... -jhsa */
729 /* this should probably not be needed (or be renamed)
733 /* Read in an extended command - doing command line completion for
734 * when enough characters have been entered to make a unique command.
737 amii_get_ext_cmd(void)
741 struct amii_WinDesc *cw;
751 register char *bufp = obufp;
753 int com_index, oindex;
754 int did_comp = 0; /* did successful completion? */
757 if (WIN_MESSAGE == WIN_ERR || (cw = amii_wins[WIN_MESSAGE]) == NULL)
758 panic(winpanicstr, WIN_MESSAGE, "get_ext_cmd");
760 bottom = amii_msgborder(w);
764 if (iflags.extmenu) {
765 win = amii_create_nhwindow(NHW_MENU);
766 amii_start_menu(win);
768 amii_putstr(WIN_MESSAGE, -1, " ");
770 for (i = 0; extcmdlist[i].ef_txt != NULL; ++i) {
771 id.a_char = *extcmdlist[i].ef_txt;
772 sprintf(buf, "%-10s - %s ", extcmdlist[i].ef_txt,
773 extcmdlist[i].ef_desc);
774 amii_add_menu(win, NO_GLYPH, &id, extcmdlist[i].ef_txt[0], 0, 0,
775 buf, MENU_UNSELECTED);
778 amii_end_menu(win, (char *) 0);
779 sel = amii_select_menu(win, PICK_ONE, &mip);
780 amii_destroy_nhwindow(win);
783 sel = mip->item.a_char;
784 for (i = 0; extcmdlist[i].ef_txt != NULL; ++i) {
785 if (sel == extcmdlist[i].ef_txt[0])
789 /* copy in the text */
790 if (extcmdlist[i].ef_txt != NULL) {
791 amii_clear_nhwindow(WIN_MESSAGE);
792 (void) put_ext_cmd((char *) extcmdlist[i].ef_txt, 0, cw,
803 amii_clear_nhwindow(WIN_MESSAGE); /* Was NHW_MESSAGE */
812 while ((c = WindowGetchar()) != EOF) {
813 amii_curs(WIN_MESSAGE, colx, bottom);
819 while (bufp != obufp) {
821 amii_curs(WIN_MESSAGE, --colx, bottom);
822 Text(w->RPort, spaces, 1);
823 amii_curs(WIN_MESSAGE, colx, bottom);
828 win = amii_create_nhwindow(NHW_MENU);
829 amii_start_menu(win);
831 for (i = 0; extcmdlist[i].ef_txt != NULL; ++i) {
832 id.a_char = extcmdlist[i].ef_txt[0];
833 sprintf(buf, "%-10s - %s ", extcmdlist[i].ef_txt,
834 extcmdlist[i].ef_desc);
835 amii_add_menu(win, NO_GLYPH, &id, extcmdlist[i].ef_txt[0], 0,
836 0, buf, MENU_UNSELECTED);
839 amii_end_menu(win, (char *) 0);
840 sel = amii_select_menu(win, PICK_ONE, &mip);
841 amii_destroy_nhwindow(win);
846 sel = mip->item.a_char;
847 for (i = 0; extcmdlist[i].ef_txt != NULL; ++i) {
848 if (sel == extcmdlist[i].ef_txt[0])
852 /* copy in the text */
853 if (extcmdlist[i].ef_txt != NULL) {
854 amii_clear_nhwindow(WIN_MESSAGE);
855 strcpy(bufp = obufp, extcmdlist[i].ef_txt);
856 (void) put_ext_cmd(obufp, colx, cw, bottom);
861 } else if (c == '\033') {
863 } else if (c == '\b') {
865 while (bufp != obufp) {
867 amii_curs(WIN_MESSAGE, --colx, bottom);
868 Text(w->RPort, spaces, 1);
869 amii_curs(WIN_MESSAGE, colx, bottom);
873 } else if (bufp != obufp) {
876 amii_curs(WIN_MESSAGE, --colx, bottom);
877 Text(w->RPort, spaces, 1);
878 amii_curs(WIN_MESSAGE, colx, bottom);
881 } else if (c == '\n' || c == '\r') {
883 } else if (c >= ' ' && c < '\177') {
884 /* avoid isprint() - some people don't have it
885 ' ' is not always a printing char */
891 while (extcmdlist[oindex].ef_txt != NULL) {
892 if (!strnicmp(obufp, (char *) extcmdlist[oindex].ef_txt,
894 if (com_index == -1) /* No matches yet*/
896 else /* More than 1 match */
902 if (com_index >= 0 && *obufp) {
903 Strcpy(obufp, extcmdlist[com_index].ef_txt);
904 /* finish printing our string */
905 colx = put_ext_cmd(obufp, colx, cw, bottom);
906 bufp = obufp; /* reset it */
907 if (strlen(obufp) < BUFSZ - 1 && strlen(obufp) < COLNO)
908 bufp += strlen(obufp);
912 colx = put_ext_cmd(obufp, colx, cw, bottom);
913 if (bufp - obufp < BUFSZ - 1 && bufp - obufp < COLNO)
916 } else if (c == ('X' - 64) || c == '\177') {
918 amii_clear_nhwindow(WIN_MESSAGE);
928 put_ext_cmd(obufp, colx, cw, bottom)
931 struct amii_WinDesc *cw;
933 struct Window *w = cw->win;
936 t = (char *) alloc(strlen(obufp) + 7);
939 sprintf(t, "xxx%s", obufp);
943 amii_curs(WIN_MESSAGE, 0, bottom);
944 SetAPen(w->RPort, C_WHITE);
945 Text(w->RPort, "># ", 3);
946 /* SetAPen( w->RPort, C_BLACK ); */ /* Black text on black
947 * screen doesn't look
948 * too well ... -jhsa */
949 Text(w->RPort, t + 3, strlen(t) - 3);
951 sprintf(t, "# %s", obufp);
952 amii_curs(WIN_MESSAGE, 0, bottom);
953 SetAPen(w->RPort, C_WHITE);
954 Text(w->RPort, t, strlen(t));
957 SetAPen(w->RPort, C_WHITE);
958 if (cw->data[cw->maxrow - 1])
959 free(cw->data[cw->maxrow - 1]);
960 cw->data[cw->maxrow - 1] = t;
962 amii_curs(WIN_MESSAGE, 0, bottom);
963 SetAPen(w->RPort, C_WHITE);
964 Text(w->RPort, "# ", 2);
965 /* SetAPen( w->RPort, C_BLACK ); */ /* Black on black ... -jhsa */
966 Text(w->RPort, obufp, strlen(obufp));
967 SetAPen(w->RPort, C_WHITE);
969 amii_curs(WIN_MESSAGE, colx = strlen(obufp) + 3 + (scrollmsg != 0),
974 /* Ask a question and get a response */
976 amii_yn_function(query, resp, def)
977 const char * query, *resp;
981 * Generic yes/no function. 'def' is the default (returned by space or
982 * return; 'esc' returns 'q', or 'n', or the default, depending on
983 * what's in the string. The 'query' string is printed before the user
984 * is asked about the string.
985 * If resp is NULL, any single character is accepted and returned.
986 * If not-NULL, only characters in it are allowed (exceptions: the
987 * quitchars are always allowed, and if it contains '#' then digits
988 * are allowed); if it includes an <esc>, anything beyond that won't
989 * be shown in the prompt to the user but will be acceptable as input.
993 boolean digit_ok, allow_num;
995 register struct amii_WinDesc *cw;
997 if (cw = amii_wins[WIN_MESSAGE])
1000 char *rb, respbuf[QBUFSZ];
1002 allow_num = (index(resp, '#') != 0);
1003 Strcpy(respbuf, resp);
1004 /* any acceptable responses that follow <esc> aren't displayed */
1005 if ((rb = index(respbuf, '\033')) != 0)
1007 (void) strncpy(prompt, query, QBUFSZ - 1);
1008 prompt[QBUFSZ - 1] = '\0';
1009 Sprintf(eos(prompt), " [%s]", respbuf);
1011 Sprintf(eos(prompt), " (%c)", def);
1012 Strcat(prompt, " ");
1013 pline("%s", prompt);
1015 amii_putstr(WIN_MESSAGE, 0, query);
1016 cursor_on(WIN_MESSAGE);
1017 q = WindowGetchar();
1018 cursor_off(WIN_MESSAGE);
1025 do { /* loop until we get valid input */
1026 cursor_on(WIN_MESSAGE);
1027 q = lowc(WindowGetchar());
1028 cursor_off(WIN_MESSAGE);
1031 if (q == '\020') { /* ctrl-P */
1033 (void) tty_doprev_message(); /* need two initially */
1034 (void) tty_doprev_message();
1038 } else if (doprev) {
1039 tty_clear_nhwindow(WIN_MESSAGE);
1040 cw->maxcol = cw->maxrow;
1042 amii_addtopl(prompt);
1046 digit_ok = allow_num && isdigit(q);
1048 if (index(resp, 'q'))
1050 else if (index(resp, 'n'))
1055 } else if (index(quitchars, q)) {
1059 if (!index(resp, q) && !digit_ok) {
1062 } else if (q == '#' || digit_ok) {
1063 char z, digit_string[2];
1067 amii_addtopl("#"), n_len++;
1068 digit_string[1] = '\0';
1070 digit_string[0] = q;
1071 amii_addtopl(digit_string), n_len++;
1075 do { /* loop until we get a non-digit */
1076 cursor_on(WIN_MESSAGE);
1077 z = lowc(WindowGetchar());
1078 cursor_off(WIN_MESSAGE);
1080 value = (10 * value) + (z - '0');
1082 break; /* overflow: try again */
1083 digit_string[0] = z;
1084 amii_addtopl(digit_string), n_len++;
1085 } else if (z == 'y' || index(quitchars, z)) {
1087 value = -1; /* abort */
1088 z = '\n'; /* break */
1089 } else if (z == '\b') {
1095 removetopl(1), n_len--;
1098 value = -1; /* abort */
1102 } while (z != '\n');
1105 else if (value == 0)
1106 q = 'n'; /* 0 => "no" */
1107 else { /* remove number from top line, then try again */
1108 removetopl(n_len), n_len = 0;
1114 if (q != '#' && q != '\033') {
1115 Sprintf(rtmp, "%c", q);
1119 cursor_off(WIN_MESSAGE);
1120 clear_nhwindow(WIN_MESSAGE);
1125 amii_display_file(fn, complain)
1129 register struct amii_WinDesc *cw;
1133 register char buf[200];
1136 panic("NULL file name in display_file()");
1138 if ((fp = dlb_fopen(fn, RDTMODE)) == (dlb *) NULL) {
1140 sprintf(buf, "Can't display %s: %s", fn,
1141 #if defined(_DCC) || defined(__GNUC__)
1145 __sys_errlist[errno]
1155 win = amii_create_nhwindow(NHW_TEXT);
1157 /* Set window title to file name */
1158 if (cw = amii_wins[win])
1159 cw->morestr = (char *) fn;
1161 while (dlb_fgets(buf, sizeof(buf), fp) != NULL) {
1162 if (t = index(buf, '\n'))
1164 amii_putstr(win, 0, buf);
1168 /* If there were lines in the file, display those lines */
1169 if (amii_wins[win]->cury > 0)
1170 amii_display_nhwindow(win, TRUE);
1172 amii_wins[win]->morestr = NULL; /* don't free title string */
1173 amii_destroy_nhwindow(win);
1176 /* Put a 3-D motif border around the gadget. String gadgets or those
1177 * which do not have highlighting are rendered down. Boolean gadgets
1178 * are rendered in the up position by default.
1182 register struct Gadget * gd;
1184 register struct Border *bp;
1186 register int i, inc = -1, dec = -1;
1188 int hipen = sysflags.amii_dripens[SHINEPEN],
1189 shadowpen = sysflags.amii_dripens[SHADOWPEN];
1190 #ifdef INTUI_NEW_LOOK
1191 struct DrawInfo *dip;
1194 #ifdef INTUI_NEW_LOOK
1195 if (IntuitionBase->LibNode.lib_Version >= 37) {
1196 if ((dip = GetScreenDrawInfo(HackScreen)) != 0) {
1197 hipen = dip->dri_Pens[SHINEPEN];
1198 shadowpen = dip->dri_Pens[SHADOWPEN];
1199 FreeScreenDrawInfo(HackScreen, dip);
1203 /* Allocate two border structures one for up image and one for down
1204 * image, plus vector arrays for the border lines.
1206 if (gd->GadgetType == STRGADGET)
1208 if ((bp = (struct Border *) alloc(((sizeof (struct Border) * 2)
1209 + (sizeof (short) * borders)) * 2))
1214 /* For a string gadget, we expand the border beyond the area where
1215 * the text will be entered.
1218 /* Remove any special rendering flags to avoid confusing intuition */
1219 gd->Flags &= ~(GADGHIGHBITS | GADGIMAGE);
1221 sp = (short *) (bp + 4);
1222 if (gd->GadgetType == STRGADGET
1223 || (gd->GadgetType == BOOLGADGET
1224 && (gd->Flags & GADGHIGHBITS) == GADGHNONE)) {
1226 sp[1] = gd->Height - 1;
1229 sp[4] = gd->Width - 1;
1232 sp[6] = gd->Width + 1;
1234 sp[8] = gd->Width + 1;
1235 sp[9] = gd->Height + 1;
1237 sp[11] = gd->Height + 1;
1240 sp[13] = gd->Height;
1246 sp[19] = gd->Height;
1248 sp[21] = gd->Height;
1250 for (i = 0; i < 3; ++i) {
1251 bp[i].LeftEdge = bp[i].TopEdge = -1;
1252 bp[i].FrontPen = (i == 0 || i == 1) ? shadowpen : hipen;
1254 /* Have to use JAM2 so that the old colors disappear. */
1255 bp[i].BackPen = C_BLACK;
1256 bp[i].DrawMode = JAM2;
1257 bp[i].Count = (i == 0 || i == 1) ? 3 : 5;
1258 bp[i].XY = &sp[i * 6];
1259 bp[i].NextBorder = (i == 2) ? NULL : &bp[i + 1];
1262 /* bp[0] and bp[1] two pieces for the up image */
1263 gd->GadgetRender = (APTR) bp;
1265 /* No image change for select */
1266 gd->SelectRender = (APTR) bp;
1270 gd->Flags |= GADGHCOMP;
1272 /* Create the border vector values for up and left side, and
1273 * also the lower and right side.
1276 sp[1] = gd->Height + inc;
1279 sp[4] = gd->Width + inc;
1282 sp[6] = gd->Width + inc;
1284 sp[8] = gd->Width + inc;
1285 sp[9] = gd->Height + inc;
1287 sp[11] = gd->Height + inc;
1289 /* We are creating 4 sets of borders, the two sides of the
1290 * rectangle share the border vectors with the opposite image,
1291 * but specify different colors.
1293 for (i = 0; i < 4; ++i) {
1294 bp[i].TopEdge = bp[i].LeftEdge = 0;
1296 /* A GADGHNONE is always down */
1297 if (gd->GadgetType == BOOLGADGET
1298 && (gd->Flags & GADGHIGHBITS) != GADGHNONE) {
1299 bp[i].FrontPen = (i == 1 || i == 2) ? shadowpen : hipen;
1301 bp[i].FrontPen = (i == 1 || i == 3) ? hipen : shadowpen;
1304 /* Have to use JAM2 so that the old colors disappear. */
1305 bp[i].BackPen = C_BLACK;
1306 bp[i].DrawMode = JAM2;
1308 bp[i].XY = &sp[6 * ((i & 1) != 0)];
1309 bp[i].NextBorder = (i == 1 || i == 3) ? NULL : &bp[i + 1];
1312 /* bp[0] and bp[1] two pieces for the up image */
1313 gd->GadgetRender = (APTR) bp;
1315 /* bp[2] and bp[3] two pieces for the down image */
1316 gd->SelectRender = (APTR)(bp + 2);
1317 gd->Flags |= GADGHIMAGE;
1321 /* Following function copied from wintty.c;
1322 Modified slightly to fit amiga needs */
1324 amii_player_selection()
1327 char pick4u = 'n', thisch, lastch = 0;
1328 char pbuf[QBUFSZ], plbuf[QBUFSZ], rolenamebuf[QBUFSZ];
1331 menu_item *selected = 0;
1333 rigid_role_checks();
1335 /* Should we randomly pick for the player? */
1336 if (flags.initrole == ROLE_NONE || flags.initrace == ROLE_NONE
1337 || flags.initgend == ROLE_NONE || flags.initalign == ROLE_NONE) {
1340 prompt = build_plselection_prompt(pbuf, QBUFSZ,
1341 flags.initrole, flags.initrace,
1342 flags.initgend, flags.initalign);
1343 pline("%s", prompt);
1344 do { /* loop until we get valid input */
1345 cursor_on(WIN_MESSAGE);
1346 pick4u = lowc(WindowGetchar());
1347 cursor_off(WIN_MESSAGE);
1348 if (index(quitchars, pick4u))
1350 } while (!index(ynqchars, pick4u));
1355 if (pick4u != 'y' && pick4u != 'n') {
1358 free((genericptr_t) selected);
1360 exit_nhwindows(NULL);
1367 (void) root_plselection_prompt(plbuf, QBUFSZ - 1,
1368 flags.initrole, flags.initrace,
1369 flags.initgend, flags.initalign);
1371 /* Select a role, if necessary */
1372 /* we'll try to be compatible with pre-selected race/gender/alignment,
1373 * but may not succeed */
1374 if (flags.initrole < 0) {
1375 /* Process the choice */
1376 if (pick4u == 'y' || flags.initrole == ROLE_RANDOM
1377 || flags.randomall) {
1378 /* Pick a random role */
1379 flags.initrole = pick_role(flags.initrace, flags.initgend,
1380 flags.initalign, PICK_RANDOM);
1381 if (flags.initrole < 0) {
1382 amii_putstr(WIN_MESSAGE, 0, "Incompatible role!");
1383 flags.initrole = randrole(FALSE);
1386 /* Prompt for a role */
1387 win = create_nhwindow(NHW_MENU);
1389 any.a_void = 0; /* zero out all bits */
1390 for (i = 0; roles[i].name.m; i++) {
1391 if (ok_role(i, flags.initrace, flags.initgend,
1393 any.a_int = i + 1; /* must be non-zero */
1394 thisch = lowc(roles[i].name.m[0]);
1395 if (thisch == lastch)
1396 thisch = highc(thisch);
1397 if (flags.initgend != ROLE_NONE
1398 && flags.initgend != ROLE_RANDOM) {
1399 if (flags.initgend == 1 && roles[i].name.f)
1400 Strcpy(rolenamebuf, roles[i].name.f);
1402 Strcpy(rolenamebuf, roles[i].name.m);
1404 if (roles[i].name.f) {
1405 Strcpy(rolenamebuf, roles[i].name.m);
1406 Strcat(rolenamebuf, "/");
1407 Strcat(rolenamebuf, roles[i].name.f);
1409 Strcpy(rolenamebuf, roles[i].name.m);
1411 add_menu(win, NO_GLYPH, &any, thisch, 0, ATR_NONE,
1412 an(rolenamebuf), MENU_UNSELECTED);
1416 any.a_int = pick_role(flags.initrace, flags.initgend,
1417 flags.initalign, PICK_RANDOM) + 1;
1418 if (any.a_int == 0) /* must be non-zero */
1419 any.a_int = randrole(FALSE) + 1;
1420 add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random",
1422 any.a_int = i + 1; /* must be non-zero */
1423 add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit",
1425 Sprintf(pbuf, "Pick a role for your %s", plbuf);
1426 end_menu(win, pbuf);
1427 n = select_menu(win, PICK_ONE, &selected);
1428 destroy_nhwindow(win);
1430 /* Process the choice */
1431 if (n != 1 || selected[0].item.a_int == any.a_int)
1432 goto give_up; /* Selected quit */
1434 flags.initrole = selected[0].item.a_int - 1;
1435 free((genericptr_t) selected), selected = 0;
1437 (void) root_plselection_prompt(plbuf, QBUFSZ - 1,
1438 flags.initrole, flags.initrace,
1439 flags.initgend, flags.initalign);
1442 /* Select a race, if necessary */
1443 /* force compatibility with role, try for compatibility with
1444 * pre-selected gender/alignment */
1445 if (flags.initrace < 0
1446 || !validrace(flags.initrole, flags.initrace)) {
1447 /* pre-selected race not valid */
1448 if (pick4u == 'y' || flags.initrace == ROLE_RANDOM
1449 || flags.randomall) {
1450 flags.initrace = pick_race(flags.initrole, flags.initgend,
1451 flags.initalign, PICK_RANDOM);
1452 if (flags.initrace < 0) {
1453 amii_putstr(WIN_MESSAGE, 0, "Incompatible race!");
1454 flags.initrace = randrace(flags.initrole);
1456 } else { /* pick4u == 'n' */
1457 /* Count the number of valid races */
1458 n = 0; /* number valid */
1459 k = 0; /* valid race */
1460 for (i = 0; races[i].noun; i++) {
1461 if (ok_race(flags.initrole, i, flags.initgend,
1468 for (i = 0; races[i].noun; i++) {
1469 if (validrace(flags.initrole, i)) {
1476 /* Permit the user to pick, if there is more than one */
1478 win = create_nhwindow(NHW_MENU);
1480 any.a_void = 0; /* zero out all bits */
1481 for (i = 0; races[i].noun; i++)
1482 if (ok_race(flags.initrole, i, flags.initgend,
1484 any.a_int = i + 1; /* must be non-zero */
1485 add_menu(win, NO_GLYPH, &any, races[i].noun[0], 0,
1486 ATR_NONE, races[i].noun,
1489 any.a_int = pick_race(flags.initrole, flags.initgend,
1490 flags.initalign, PICK_RANDOM) + 1;
1491 if (any.a_int == 0) /* must be non-zero */
1492 any.a_int = randrace(flags.initrole) + 1;
1493 add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random",
1495 any.a_int = i + 1; /* must be non-zero */
1496 add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit",
1498 Sprintf(pbuf, "Pick the race of your %s", plbuf);
1499 end_menu(win, pbuf);
1500 n = select_menu(win, PICK_ONE, &selected);
1501 destroy_nhwindow(win);
1502 if (n != 1 || selected[0].item.a_int == any.a_int)
1503 goto give_up; /* Selected quit */
1505 k = selected[0].item.a_int - 1;
1506 free((genericptr_t) selected), selected = 0;
1510 (void) root_plselection_prompt(plbuf, QBUFSZ - 1,
1511 flags.initrole, flags.initrace,
1512 flags.initgend, flags.initalign);
1515 /* Select a gender, if necessary */
1516 /* force compatibility with role/race, try for compatibility with
1517 * pre-selected alignment */
1518 if (flags.initgend < 0
1519 || !validgend(flags.initrole, flags.initrace, flags.initgend)) {
1520 /* pre-selected gender not valid */
1521 if (pick4u == 'y' || flags.initgend == ROLE_RANDOM
1522 || flags.randomall) {
1523 flags.initgend = pick_gend(flags.initrole, flags.initrace,
1524 flags.initalign, PICK_RANDOM);
1525 if (flags.initgend < 0) {
1526 amii_putstr(WIN_MESSAGE, 0, "Incompatible gender!");
1527 flags.initgend = randgend(flags.initrole, flags.initrace);
1529 } else { /* pick4u == 'n' */
1530 /* Count the number of valid genders */
1531 n = 0; /* number valid */
1532 k = 0; /* valid gender */
1533 for (i = 0; i < ROLE_GENDERS; i++) {
1534 if (ok_gend(flags.initrole, flags.initrace, i,
1541 for (i = 0; i < ROLE_GENDERS; i++) {
1542 if (validgend(flags.initrole, flags.initrace, i)) {
1549 /* Permit the user to pick, if there is more than one */
1551 win = create_nhwindow(NHW_MENU);
1553 any.a_void = 0; /* zero out all bits */
1554 for (i = 0; i < ROLE_GENDERS; i++)
1555 if (ok_gend(flags.initrole, flags.initrace, i,
1558 add_menu(win, NO_GLYPH, &any, genders[i].adj[0], 0,
1559 ATR_NONE, genders[i].adj, MENU_UNSELECTED);
1561 any.a_int = pick_gend(flags.initrole, flags.initrace,
1562 flags.initalign, PICK_RANDOM) + 1;
1563 if (any.a_int == 0) /* must be non-zero */
1564 any.a_int = randgend(flags.initrole, flags.initrace) + 1;
1565 add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random",
1567 any.a_int = i + 1; /* must be non-zero */
1568 add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit",
1570 Sprintf(pbuf, "Pick the gender of your %s", plbuf);
1571 end_menu(win, pbuf);
1572 n = select_menu(win, PICK_ONE, &selected);
1573 destroy_nhwindow(win);
1574 if (n != 1 || selected[0].item.a_int == any.a_int)
1575 goto give_up; /* Selected quit */
1577 k = selected[0].item.a_int - 1;
1578 free((genericptr_t) selected), selected = 0;
1582 (void) root_plselection_prompt(plbuf, QBUFSZ - 1,
1583 flags.initrole, flags.initrace,
1584 flags.initgend, flags.initalign);
1587 /* Select an alignment, if necessary */
1588 /* force compatibility with role/race/gender */
1589 if (flags.initalign < 0
1590 || !validalign(flags.initrole, flags.initrace, flags.initalign)) {
1591 /* pre-selected alignment not valid */
1592 if (pick4u == 'y' || flags.initalign == ROLE_RANDOM
1593 || flags.randomall) {
1594 flags.initalign = pick_align(flags.initrole, flags.initrace,
1595 flags.initgend, PICK_RANDOM);
1596 if (flags.initalign < 0) {
1597 amii_putstr(WIN_MESSAGE, 0, "Incompatible alignment!");
1598 flags.initalign = randalign(flags.initrole, flags.initrace);
1600 } else { /* pick4u == 'n' */
1601 /* Count the number of valid alignments */
1602 n = 0; /* number valid */
1603 k = 0; /* valid alignment */
1604 for (i = 0; i < ROLE_ALIGNS; i++) {
1605 if (ok_align(flags.initrole, flags.initrace,
1606 flags.initgend, i)) {
1612 for (i = 0; i < ROLE_ALIGNS; i++) {
1613 if (validalign(flags.initrole, flags.initrace, i)) {
1620 /* Permit the user to pick, if there is more than one */
1622 win = create_nhwindow(NHW_MENU);
1624 any.a_void = 0; /* zero out all bits */
1625 for (i = 0; i < ROLE_ALIGNS; i++)
1626 if (ok_align(flags.initrole, flags.initrace,
1627 flags.initgend, i)) {
1629 add_menu(win, NO_GLYPH, &any, aligns[i].adj[0], 0,
1630 ATR_NONE, aligns[i].adj, MENU_UNSELECTED);
1632 any.a_int = pick_align(flags.initrole, flags.initrace,
1633 flags.initgend, PICK_RANDOM) + 1;
1634 if (any.a_int == 0) /* must be non-zero */
1635 any.a_int = randalign(flags.initrole, flags.initrace) + 1;
1636 add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random",
1638 any.a_int = i + 1; /* must be non-zero */
1639 add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit",
1641 Sprintf(pbuf, "Pick the alignment of your %s", plbuf);
1642 end_menu(win, pbuf);
1643 n = select_menu(win, PICK_ONE, &selected);
1644 destroy_nhwindow(win);
1645 if (n != 1 || selected[0].item.a_int == any.a_int)
1646 goto give_up; /* Selected quit */
1648 k = selected[0].item.a_int - 1;
1649 free((genericptr_t) selected), selected = 0;
1651 flags.initalign = k;
1656 #endif /* AMIGA_INTUITION */