home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / nethack-3.1 / sys / amiga / winami.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-23  |  86.1 KB  |  3,832 lines

  1. /*    SCCS Id: @(#)winami.c    3.1    93/01/07 */
  2. /* Copyright (c) Gregg Wonderly, Naperville, Illinois,  1991,1992,1993. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6. #include "wintype.h"
  7. #include "winami.h"
  8. #include "func_tab.h"
  9.  
  10. #ifdef AMIGA_INTUITION
  11.  
  12. /* These should probably not even be options, but, I will leave them
  13.  * for now... GGW
  14.  */
  15.  
  16. /*#define   TOPL_GETLINE    /* Don't use a window for getlin() */
  17. /*#define   WINDOW_YN        /* Use a window for y/n questions */
  18.  
  19. #include <exec/types.h>
  20. #include <exec/io.h>
  21. #include <exec/alerts.h>
  22. #include <exec/devices.h>
  23. #include <devices/console.h>
  24. #include <devices/conunit.h>
  25. #include <graphics/gfxbase.h>
  26. #include <intuition/intuition.h>
  27. #include <intuition/intuitionbase.h>
  28. #include <libraries/dosextens.h>
  29. #include <ctype.h>
  30. #undef  strcmpi
  31. #include <string.h>
  32. #include <errno.h>
  33.  
  34. #ifdef  IDCMP_CLOSEWINDOW
  35. # define    INTUI_NEW_LOOK
  36. #endif
  37.  
  38. #ifdef AZTEC_C
  39. #include <functions.h>
  40. #else
  41. #include <proto/dos.h>
  42. #include <proto/exec.h>
  43. #include <proto/console.h>
  44. #include <proto/diskfont.h>
  45.  
  46. /* kludge - see amirip for why */
  47. #undef red
  48. #undef green
  49. #undef blue
  50. #include <proto/graphics.h>
  51. #ifndef __SASC_60
  52. #undef index
  53. # define index strchr
  54. #endif
  55.  
  56. #include <proto/intuition.h>
  57. #endif
  58.  
  59. static void RandomWindow( char * );
  60.  
  61. /* cw->data[x] contains 2 characters worth of special information.  These
  62.  * characters are stored at the offsets as described here.
  63.  */
  64. #define VATTR      0    /* Video attribute is in this slot */
  65. #define SEL_ITEM  1    /* If this is a select item, slot is 1 else 0 */
  66. #define SOFF      2    /* The string starts here.  */
  67.  
  68. /* Nethack defines NULL as ((char *)0) which is very inconvienent... */
  69. #undef NULL
  70. #define NULL 0L
  71.  
  72. /*
  73.  * Versions we need of various libraries.  We can't use LIBRARY_VERSION
  74.  * as defined in <exec/types.h> because some of the libraries we need
  75.  * don't have that version number in the 1.2 ROM.
  76.  */
  77.  
  78. #define INTUITION_VERSION    33L
  79. #define GRAPHICS_VERSION    33L
  80. #define DISKFONT_VERSION    34L
  81. #define ICON_VERSION        34L
  82.  
  83. /* These values are just sorta suggestions in use, but are minimum requirements
  84.  * in reality...
  85.  */
  86. #define WINDOWHEIGHT    192
  87. #define SCREENHEIGHT    200
  88. #define WIDTH        640
  89.  
  90. /* This character is a solid block (cursor) in Hack.font */
  91. #define CURSOR_CHAR    0x90
  92.  
  93. /* All we currently support is hack.font at 8x8... */
  94. #define FONTWIDTH    8
  95. #define FONTHEIGHT    8
  96. #define FONTBASELINE    8
  97.  
  98. /* If Compiling with the "New Look", redefine these now */
  99. #ifdef  INTUI_NEW_LOOK
  100. #define NewWindow ExtNewWindow
  101. #define NewScreen ExtNewScreen
  102. #endif
  103.  
  104. /* Get the prototypes for our files */
  105. #include "Amiga:winami.p"
  106. #include "Amiga:amiwind.p"
  107. #include "Amiga:amidos.p"
  108.  
  109. /* Interface definition, for use by windows.c and winprocs.h to provide
  110.  * the intuition interface for the amiga...
  111.  */
  112. struct window_procs amii_procs =
  113. {
  114.     "amii",
  115.     amii_init_nhwindows,
  116.     amii_player_selection,
  117.     amii_askname,
  118.     amii_get_nh_event,
  119.     amii_exit_nhwindows,
  120.     amii_suspend_nhwindows,
  121.     amii_resume_nhwindows,
  122.     amii_create_nhwindow,
  123.     amii_clear_nhwindow,
  124.     amii_display_nhwindow,
  125.     amii_destroy_nhwindow,
  126.     amii_curs,
  127.     amii_putstr,
  128.     amii_display_file,
  129.     amii_start_menu,
  130.     amii_add_menu,
  131.     amii_end_menu,
  132.     amii_select_menu,
  133.     amii_update_inventory,
  134.     amii_mark_synch,
  135.     amii_wait_synch,
  136. #ifdef CLIPPING
  137.     amii_cliparound,
  138. #endif
  139.     amii_print_glyph,
  140.     amii_raw_print,
  141.     amii_raw_print_bold,
  142.     amii_nhgetch,
  143.     amii_nh_poskey,
  144.     amii_bell,
  145.     amii_doprev_message,
  146.     amii_yn_function,
  147.     amii_getlin,
  148. #ifdef COM_COMPL
  149.     amii_get_ext_cmd,
  150. #endif /* COM_COMPL */
  151.     amii_number_pad,
  152.     amii_delay_output,
  153.     /* other defs that really should go away (they're tty specific) */
  154.     amii_delay_output,
  155.     amii_delay_output,
  156. };
  157.  
  158. extern struct GfxBase *GfxBase;
  159. extern struct Library *DiskfontBase;
  160. extern struct IntuitionBase *IntuitionBase;
  161.  
  162. /* All kinds of shared stuff */
  163. extern struct TextAttr Hack80;
  164. extern struct Screen *HackScreen;
  165. extern struct Window *pr_WindowPtr;
  166. extern struct Menu HackMenu[];
  167. extern unsigned char KbdBuffered;
  168. extern struct TextFont *HackFont;
  169. extern struct IOStdReq ConsoleIO;
  170. extern struct Library *ConsoleDevice;
  171. extern struct MsgPort *HackPort;
  172. extern char Initialized;
  173. extern char toplines[BUFSZ];
  174.  
  175. char morc;  /* the character typed in response to a --more-- prompt */
  176. char spaces[] =
  177. "                                                                           ";
  178. extern winid WIN_MESSAGE;
  179. extern winid WIN_MAP;
  180. extern winid WIN_STATUS;
  181. extern winid WIN_INVEN;
  182.  
  183. winid WIN_BASE = WIN_ERR;
  184.  
  185. /* Changed later during window/screen opens... */
  186. int txwidth=FONTWIDTH, txheight=FONTHEIGHT, txbaseline = FONTBASELINE;
  187.  
  188. /* If a 240 or more row screen is in front when we start, this will be
  189.  * set to 1, and the windows will be given borders to allow them to be
  190.  * arranged differently.  The Message window may eventually get a scroller...
  191.  */
  192. int bigscreen = 0;
  193.  
  194. static void outmore(struct WinDesc *);
  195. static void outsubstr(struct WinDesc *,char *,int);
  196. static void dismiss_nhwindow(winid);
  197.  
  198. /* This gadget data is replicated for menu/text windows... */
  199. static struct PropInfo PropScroll = { AUTOKNOB+FREEVERT,
  200.                     0xffff,0xffff, 0xffff,0xffff, };
  201. static struct Image Image1 = { 0,0, 7,102, 0, NULL, 0x0000,0x0000, NULL };
  202. static struct Gadget MenuScroll = {
  203.     NULL, -15,10, 15,-19, GRELRIGHT|GRELHEIGHT,
  204.     RELVERIFY|FOLLOWMOUSE|RIGHTBORDER,
  205.     PROPGADGET, (APTR)&Image1, NULL, NULL, NULL, (APTR)&PropScroll,
  206.     1, NULL
  207. };
  208.  
  209. int wincnt=0;   /* # of nh windows opened */
  210.  
  211. /* We advertise a public screen to allow some people to do other things
  212.  * while they are playing...  like compiling...
  213.  */
  214.  
  215. #ifdef  INTUI_NEW_LOOK
  216. struct TagItem tags[] =
  217. {
  218.     { WA_PubScreenName, (ULONG)"NetHack", },
  219.     { TAG_DONE, 0, },
  220. };
  221. #endif
  222.  
  223. /*
  224.  * The default dimensions and status values for each window type.  The
  225.  * data here is generally changed in create_nhwindow(), so beware that
  226.  * what you see here may not be exactly what you get.
  227.  */
  228. struct win_setup {
  229.     struct NewWindow newwin;
  230.     xchar offx,offy,maxrow,rows,maxcol,cols;    /* CHECK TYPES */
  231. } new_wins[] = {
  232.  
  233.     /* First entry not used, types are based on 1 */
  234.     {{0}},
  235.  
  236.     /* NHW_MESSAGE */
  237.     {{0,1,640,11,0xff,0xff,
  238.     RAWKEY,
  239.     BORDERLESS|ACTIVATE|SMART_REFRESH
  240. #ifdef  INTUI_NEW_LOOK
  241.     |WFLG_NW_EXTENDED
  242. #endif
  243.     ,
  244.     NULL,NULL,(UBYTE*)"Messages",NULL,NULL,-1,-1,0xffff,0xffff,CUSTOMSCREEN,
  245. #ifdef  INTUI_NEW_LOOK
  246.     tags,
  247. #endif
  248.     },
  249.     0,0,1,1,80,80},
  250.  
  251.     /* NHW_STATUS */
  252.     {{0,181,640,24,0xff,0xff,RAWKEY|MENUPICK|DISKINSERTED,
  253.     BORDERLESS|ACTIVATE|SMART_REFRESH
  254. #ifdef  INTUI_NEW_LOOK
  255.     |WFLG_NW_EXTENDED
  256. #endif
  257.     ,
  258.     NULL,NULL,(UBYTE*)"Game Status",NULL,NULL,-1,-1,0xffff,0xffff,CUSTOMSCREEN,
  259. #ifdef  INTUI_NEW_LOOK
  260.     tags,
  261. #endif
  262.     },
  263.     0,0,2,2,78,78},
  264.  
  265.     /* NHW_MAP */
  266.     {{0,0,WIDTH,WINDOWHEIGHT,0xff,0xff,
  267.     RAWKEY|MENUPICK|MOUSEBUTTONS|ACTIVEWINDOW
  268. #ifdef  INTUI_NEW_LOOK
  269.     |WFLG_NW_EXTENDED
  270. #endif
  271.     ,
  272.     BORDERLESS|ACTIVATE|SMART_REFRESH|BACKDROP,
  273.     NULL,NULL,(UBYTE*)"Dungeon Map",NULL,NULL,-1,-1,0xffff,0xffff,CUSTOMSCREEN,
  274. #ifdef  INTUI_NEW_LOOK
  275.     tags,
  276. #endif
  277.     },
  278.     0,0,22,22,80,80},
  279.  
  280.     /* NHW_MENU */
  281.     {{400,10,10,10,80,30,
  282.     RAWKEY|MENUPICK|DISKINSERTED|MOUSEMOVE|MOUSEBUTTONS|
  283.     GADGETUP|GADGETDOWN|CLOSEWINDOW|VANILLAKEY|NEWSIZE
  284. #ifdef  INTUI_NEW_LOOK
  285.     |WFLG_NW_EXTENDED
  286. #endif
  287.     ,
  288.     WINDOWSIZING|WINDOWCLOSE|WINDOWDRAG|ACTIVATE|SMART_REFRESH,
  289.     &MenuScroll,NULL,(UBYTE*)"Pick an Item",
  290.     NULL,NULL,-1,-1,0xffff,0xffff,CUSTOMSCREEN,
  291. #ifdef  INTUI_NEW_LOOK
  292.     tags,
  293. #endif
  294.     },
  295.     0,0,1,1,22,78},
  296.  
  297.     /* NHW_TEXT */
  298.     {{0,0,640,200,0xff,0xff,
  299.     RAWKEY|MENUPICK|DISKINSERTED|MOUSEMOVE|
  300.     GADGETUP|CLOSEWINDOW|VANILLAKEY|NEWSIZE
  301. #ifdef  INTUI_NEW_LOOK
  302.     |WFLG_NW_EXTENDED
  303. #endif
  304.     ,
  305.     WINDOWSIZING|WINDOWCLOSE|WINDOWDRAG|ACTIVATE|SMART_REFRESH,
  306.     &MenuScroll,NULL,(UBYTE*)NULL,NULL,NULL,-1,-1,0xffff,0xffff,CUSTOMSCREEN,
  307. #ifdef  INTUI_NEW_LOOK
  308.     tags,
  309. #endif
  310.     },
  311.     0,0,1,1,22,78},
  312.  
  313.     /* NHW_BASE */
  314.     {{0,0,WIDTH,WINDOWHEIGHT,0xff,0xff,
  315.     RAWKEY|MENUPICK|MOUSEBUTTONS
  316. #ifdef  INTUI_NEW_LOOK
  317.     |WFLG_NW_EXTENDED
  318. #endif
  319.     ,
  320.     BORDERLESS|ACTIVATE|SMART_REFRESH|BACKDROP,
  321.     NULL,NULL,(UBYTE*)NULL,NULL,NULL,-1,-1,0xffff,0xffff,CUSTOMSCREEN,
  322. #ifdef  INTUI_NEW_LOOK
  323.     tags,
  324. #endif
  325.     },
  326.     0,0,22,22,80,80},
  327. };
  328.  
  329. /* The physical screen information */
  330. struct DisplayDesc *amiIDisplay;
  331.  
  332. /* The opened windows information */
  333. struct WinDesc *wins[MAXWIN + 1];
  334.  
  335. /* The last Window event is stored here for reference. */
  336. extern WEVENT lastevent;
  337.  
  338. static const char winpanicstr[]="Bad winid %d in %s()";
  339. #define         SIZEOF_DISKNAME 8
  340.  
  341. /* The current color map */
  342. unsigned short amii_curmap[] = {
  343. #define C_BLACK        0
  344. #define C_WHITE        1
  345. #define C_BROWN        2
  346. #define C_CYAN        3
  347. #define C_GREEN        4
  348. #define C_MAGENTA    5
  349. #define C_BLUE        6
  350. #define C_RED        7
  351.     0x0AAA, /* color #0 */
  352.     0x0FFF, /* color #1 */
  353.     0x0620, /* color #2 */
  354.     0x0B08, /* color #3 */
  355.     0x0181, /* color #4 */
  356.     0x0C06, /* color #5 */
  357.     0x023E, /* color #6 */
  358.     0x0D00  /* color #7 */
  359. };
  360.  
  361. #ifdef  INTUI_NEW_LOOK
  362. UWORD scrnpens[] = {
  363.     C_BROWN,
  364.     C_BLACK,
  365.     C_WHITE,
  366.     C_WHITE,
  367.     C_BROWN,
  368.     C_CYAN,
  369.     C_BROWN,
  370.     C_BLACK,
  371.     C_RED,
  372. };
  373. struct TagItem scrntags[] =
  374. {
  375.     { SA_PubName, (ULONG)"NetHack" },
  376.     { SA_Pens, (ULONG)scrnpens },
  377.     { TAG_DONE, 0 },
  378. };
  379. #endif
  380.  
  381. struct NewScreen NewHackScreen =
  382. {
  383.     0, 0, WIDTH, SCREENHEIGHT, DEPTH,
  384.     C_BLACK, C_WHITE,     /* DetailPen, BlockPen */
  385.     HIRES,
  386.     CUSTOMSCREEN
  387. #ifdef  INTUI_NEW_LOOK
  388.     |NS_EXTENDED
  389. #endif
  390.     ,
  391.     &Hack80,  /* Font */
  392.     (UBYTE *)" NetHack 3.1",
  393.     NULL,     /* Gadgets */
  394.     NULL,     /* CustomBitmap */
  395. #ifdef  INTUI_NEW_LOOK
  396.     scrntags,
  397. #endif
  398. };
  399.  
  400. /* Make sure the user sees a text string when no windowing is available */
  401.  
  402. void
  403. amii_raw_print(s)
  404.     register const char *s;
  405. {
  406.     if( !s )
  407.     return;
  408.     if(amiIDisplay)amiIDisplay->rawprint++;
  409.  
  410.     if( Initialized == 0 && WIN_BASE == WIN_ERR )
  411.         init_nhwindows();
  412.  
  413.     if( WIN_MAP != WIN_ERR && wins[ WIN_MAP ] )
  414.     amii_putstr( WIN_MAP, 0, s );
  415.     else if( WIN_BASE != WIN_ERR && wins[ WIN_BASE ] )
  416.     amii_putstr( WIN_BASE, 0, s );
  417.     else {
  418.     printf("%s\n", s);
  419.     fflush(stdout);
  420.     }
  421. }
  422.  
  423. /* Make sure the user sees a bold text string when no windowing
  424.  * is available
  425.  */
  426.  
  427. void
  428. amii_raw_print_bold(s)
  429.     register const char *s;
  430. {
  431.     if( !s )
  432.     return;
  433.  
  434.     if(amiIDisplay)amiIDisplay->rawprint++;
  435.  
  436.     if( Initialized == 0 && WIN_BASE == WIN_ERR )
  437.         init_nhwindows();
  438.  
  439.     if( WIN_MAP != WIN_ERR && wins[ WIN_MAP ] )
  440.     amii_putstr( WIN_MAP, 1, s );
  441.     else if( WIN_BASE != WIN_ERR && wins[ WIN_BASE ] )
  442.     amii_putstr( WIN_BASE, 1, s );
  443.     else {
  444.     printf("\33[1m%s\33[0m\n",s);
  445.     fflush(stdout);
  446.     }
  447. }
  448.  
  449. /* Start building the text for a menu */
  450. void
  451. amii_start_menu(window)
  452.     register winid window;
  453. {
  454.     register struct WinDesc *cw;
  455.  
  456.     if(window == WIN_ERR || (cw = wins[window]) == NULL || cw->type != NHW_MENU)
  457.     panic(winpanicstr,window, "start_menu");
  458.  
  459.     amii_clear_nhwindow(window);
  460.     if( cw->resp )
  461.     *cw->resp = 0;
  462.     cw->maxrow = cw->maxcol = 0;
  463.  
  464.     return;
  465. }
  466.  
  467. /* Add a string to a menu */
  468. void
  469. amii_add_menu(window,ch,attr,str)
  470.     register winid window;
  471.     register char ch;
  472.     register int attr;
  473.     register const char *str;
  474. {
  475.     register struct WinDesc *cw;
  476.     char tmpbuf[2];
  477.  
  478.     if(str == NULL)return;
  479.  
  480.     if(window == WIN_ERR || (cw = wins[window]) == NULL || cw->type != NHW_MENU)
  481.     panic(winpanicstr,window, "add_menu");
  482.  
  483.     /* this should translate fonts if a title line */
  484.     amii_putstr(window, attr, str);
  485.  
  486.     if( !cw->resp )
  487.     panic("No response buffer in add_menu()");
  488.  
  489.     if( !cw->data )
  490.     panic("No data buffer in add_menu()");
  491.  
  492.     if(ch != '\0')
  493.     {
  494.     tmpbuf[0]=ch;
  495.     tmpbuf[1]=0;
  496.     Strcat(cw->resp, tmpbuf);
  497.     cw->data[ cw->cury - 1 ][ SEL_ITEM ] = 1;
  498.     }
  499.     else
  500.     {
  501.     /* Use something as a place holder.  ^A is probably okay */
  502.  
  503.     tmpbuf[0]=1;
  504.     tmpbuf[1]=0;
  505.     Strcat(cw->resp, tmpbuf);
  506.     cw->data[ cw->cury - 1 ][ SEL_ITEM ] = 0;
  507.     }
  508. }
  509.  
  510. /* Done building a menu. */
  511.  
  512. void
  513. amii_end_menu(window,cancel,str,morestr)
  514.     register winid window;
  515.     register char cancel;
  516.     register const char *str;
  517.     register const char *morestr;
  518. {
  519.     register struct WinDesc *cw;
  520.  
  521.     if(window == WIN_ERR || (cw=wins[window]) == NULL || cw->type != NHW_MENU
  522.       || cw->canresp)
  523.     panic(winpanicstr,window, "end_menu");
  524.  
  525.     if(str)
  526.     {
  527.     cw->canresp = (char*) alloc(strlen(str)+2);
  528.     cw->canresp[0]=cancel;
  529.     Strcpy(&cw->canresp[1],str);
  530.  
  531.     if( !cw->resp )
  532.         panic("No response buffer in end_menu()");
  533.  
  534.     strncat(cw->resp, str, 1);
  535.     }
  536.  
  537.     if(morestr)
  538.     {
  539.     cw->morestr =(char *) alloc(strlen(morestr)+1);
  540.     Strcpy(cw->morestr, morestr);
  541.     }
  542. }
  543.  
  544. /* Select something from the menu. */
  545.  
  546. char
  547. amii_select_menu(window)
  548.     register winid window;
  549. {
  550.     register struct WinDesc *cw;
  551.  
  552.     if( window == WIN_ERR || ( cw=wins[window] ) == NULL ||
  553.       cw->type != NHW_MENU )
  554.     panic(winpanicstr,window, "select_menu");
  555.  
  556.     morc = 0;                       /* very ugly global variable */
  557.     amii_display_nhwindow(window,TRUE); /* this waits for input */
  558.     dismiss_nhwindow(window);       /* Now tear it down */
  559.     return morc;
  560. }
  561.  
  562. /* Rebuild/update the inventory if the window is up.  This is currently
  563.  * a noop for us because we always take any menu window off of the
  564.  * screen by deleting it when the user makes a selection, or cancels
  565.  * the menu.
  566.  */
  567. void
  568. amii_update_inventory()
  569. {
  570.     register struct WinDesc *cw;
  571.  
  572.     if( WIN_INVEN != WIN_ERR && ( cw = wins[ WIN_INVEN ] ) &&
  573.       cw->type == NHW_MENU && cw->win )
  574.     {
  575.     display_inventory( NULL, FALSE );
  576.     WindowToFront( cw->win );
  577.     ActivateWindow( cw->win );
  578.     }
  579. }
  580.  
  581. /* Humm, doesn't really do anything useful */
  582.  
  583. void
  584. amii_mark_synch()
  585. {
  586.     if(!amiIDisplay)
  587.     fflush(stderr);
  588. /* anything else?  do we need this much? */
  589. }
  590.  
  591. /* Wait for everything to sync.  Nothing is asynchronous, so we just
  592.  * ask for a key to be pressed.
  593.  */
  594. void
  595. amii_wait_synch()
  596. {
  597.     if(!amiIDisplay || amiIDisplay->rawprint)
  598.     {
  599.     if(amiIDisplay) amiIDisplay->rawprint=0;
  600.     }
  601.     else
  602.     {
  603.     display_nhwindow(WIN_MAP,TRUE);
  604.     flush_glyph_buffer( wins[ WIN_MAP ]->win );
  605.     }
  606. }
  607.  
  608. #ifdef CLIPPING
  609. void
  610. amii_setclipped()
  611. {
  612.     clipping = TRUE;
  613.     clipx=clipy=0;
  614.     clipxmax=CO;        /* WRONG */
  615.     clipymax=LI-5;      /* WRONG */
  616. }
  617.  
  618. void
  619. amii_cliparound(x,y)
  620.     register int x,y;
  621. {
  622. /* pull this from wintty.c - LATER */
  623. }
  624. #endif
  625.  
  626. /*
  627.  * plname is filled either by an option (-u Player  or  -uPlayer) or
  628.  * explicitly (by being the wizard) or by askname.
  629.  * It may still contain a suffix denoting pl_character.
  630.  * Always called after init_nhwindows() and before display_gamewindows().
  631.  */
  632. void
  633. amii_askname()
  634. {
  635.     *plname = 0;
  636.     do {
  637.     getlin( "Who are you?", plname );
  638.     } while( strlen( plname ) == 0 );
  639.  
  640.     if( *plname == '\33' )
  641.     {
  642.     clearlocks();
  643.     exit_nhwindows(NULL);
  644.     terminate(0);
  645.     }
  646. }
  647.  
  648. #include "Amiga:char.c"
  649.  
  650. /* Get the player selection character */
  651.  
  652. void
  653. amii_player_selection()
  654. {
  655.     extern const char *roles[];
  656.     register struct Window *cwin;
  657.     register struct IntuiMessage *imsg;
  658.     register int aredone = 0;
  659.     register struct Gadget *gd;
  660.     static int once=0;
  661.     long class, code;
  662.     int i;
  663.  
  664.     amii_clear_nhwindow( WIN_BASE );
  665.     if( *pl_character ){
  666.     pl_character[ 0 ] = toupper( pl_character[ 0 ] );
  667.     if( index( pl_classes, pl_character[ 0 ] ) )
  668.         return;
  669.     }
  670.  
  671.     if( !once ){
  672.     if( bigscreen ){
  673.         Type_NewWindowStructure1.TopEdge =
  674.           (HackScreen->Height/2) - (Type_NewWindowStructure1.Height/2);
  675.     }
  676.     for( gd = Type_NewWindowStructure1.FirstGadget; gd;
  677.       gd = gd->NextGadget )
  678.     {
  679.         if( gd->GadgetID != 0 )
  680.         SetBorder( gd );
  681.     }
  682.     once = 1;
  683.     }
  684.  
  685.     Type_NewWindowStructure1.Screen = HackScreen;
  686.     if( ( cwin = OpenShWindow( (void *)&Type_NewWindowStructure1 ) ) == NULL )
  687.     {
  688.     return;
  689.     }
  690.  
  691.     while( !aredone )
  692.     {
  693.     WaitPort( cwin->UserPort );
  694.     while( ( imsg = (void *) GetMsg( cwin->UserPort ) ) != NULL )
  695.     {
  696.         class = imsg->Class;
  697.         code = imsg->Code;
  698.         gd = (struct Gadget *)imsg->IAddress;
  699.         ReplyMsg( (struct Message *)imsg );
  700.  
  701.         switch( class )
  702.         {
  703.         case VANILLAKEY:
  704.         if( index( pl_classes, toupper( code ) ) )
  705.         {
  706.             pl_character[0] = toupper( code );
  707.             aredone = 1;
  708.         }
  709.         else if( code == ' ' || code == '\n' || code == '\r' )
  710.         {
  711. #ifdef  TOURIST
  712.             strcpy( pl_character, roles[ rnd( 11 ) ] );
  713. #else
  714.             strcpy( pl_character, roles[ rnd( 10 ) ] );
  715. #endif
  716.             aredone = 1;
  717.             amii_clear_nhwindow( WIN_BASE );
  718.             CloseShWindow( cwin );
  719.             RandomWindow( pl_character );
  720.             return;
  721.         }
  722.         else if( code == 'q' || code == 'Q' )
  723.         {
  724.         CloseShWindow( cwin );
  725.         clearlocks();
  726.         exit_nhwindows(NULL);
  727.         terminate(0);
  728.         }
  729.         else
  730.             DisplayBeep( NULL );
  731.         break;
  732.  
  733.         case GADGETUP:
  734.         switch( gd->GadgetID )
  735.         {
  736.         case 1: /* Random Character */
  737. #ifdef  TOURIST
  738.             strcpy( pl_character, roles[ rnd( 11 ) ] );
  739. #else
  740.             strcpy( pl_character, roles[ rnd( 10 ) ] );
  741. #endif
  742.             amii_clear_nhwindow( WIN_BASE );
  743.             CloseShWindow( cwin );
  744.             RandomWindow( pl_character );
  745.             return;
  746.  
  747.         default:
  748.             pl_character[0] = gd->GadgetID;
  749.             break;
  750.         }
  751.         aredone = 1;
  752.         break;
  753.  
  754.         case CLOSEWINDOW:
  755.         CloseShWindow( cwin );
  756.         clearlocks();
  757.         exit_nhwindows(NULL);
  758.         terminate(0);
  759.         break;
  760.         }
  761.     }
  762.     }
  763.     amii_clear_nhwindow( WIN_BASE );
  764.     CloseShWindow( cwin );
  765. }
  766.  
  767. #ifndef KENI_S_WAY
  768. #include "Amiga:randwin.c"
  769.  
  770. static void
  771. RandomWindow( name )
  772.     char *name;
  773. {
  774.     struct MsgPort *tport;
  775.     struct timerequest *trq;
  776.     static int once = 0;
  777.     struct Gadget *gd;
  778.     struct Window *w;
  779.     struct IntuiMessage *imsg;
  780.     int ticks = 0, aredone = 0, timerdone = 0;
  781.     long mask, got;
  782.  
  783.     tport = CreatePort( 0, 0 );
  784.     trq = (struct timerequest *)CreateExtIO( tport, sizeof( *trq ) );
  785.     if( tport == NULL || trq == NULL )
  786.     {
  787. allocerr:
  788.     if( tport ) DeletePort( tport );
  789.     if( trq ) DeleteExtIO( (struct IORequest *)trq );
  790.     Delay( 8 * 50 );
  791.     }
  792.  
  793.     if( OpenDevice( TIMERNAME, UNIT_VBLANK, (struct IORequest *)trq, 0L ) != 0 )
  794.     goto allocerr;
  795.  
  796.     trq->tr_node.io_Command = TR_ADDREQUEST;
  797.     trq->tr_time.tv_secs = 8;
  798.     trq->tr_time.tv_micro = 0;
  799.  
  800.     SendIO( (struct IORequest *)trq );
  801.  
  802.     /* Place the name in the center of the screen */
  803.     Rnd_IText5.IText = name;
  804.     Rnd_IText6.LeftEdge = Rnd_IText4.LeftEdge +
  805.         (strlen(Rnd_IText4.IText)+1)*txwidth;
  806.     Rnd_NewWindowStructure1.Width = (
  807.         (strlen( Rnd_IText2.IText )+1) * txwidth ) +
  808.         HackScreen->WBorLeft + HackScreen->WBorRight;
  809.     Rnd_IText5.LeftEdge = (Rnd_NewWindowStructure1.Width -
  810.         (strlen(name)*txwidth))/2;
  811.  
  812.     gd = Rnd_NewWindowStructure1.FirstGadget;
  813.     gd->LeftEdge = (Rnd_NewWindowStructure1.Width - gd->Width)/2;
  814.     /* Chose correct modifier */
  815.     Rnd_IText6.IText = "a";
  816.     switch( *name )
  817.     {
  818.     case 'a': case 'e': case 'i': case 'o':
  819.     case 'u': case 'A': case 'E': case 'I':
  820.     case 'O': case 'U':
  821.     Rnd_IText6.IText = "an";
  822.     break;
  823.     }
  824.  
  825.     if( !once )
  826.     {
  827.     if( bigscreen )
  828.     {
  829.         Rnd_NewWindowStructure1.TopEdge =
  830.         (HackScreen->Height/2) - (Rnd_NewWindowStructure1.Height/2);
  831.     }
  832.     for( gd = Rnd_NewWindowStructure1.FirstGadget; gd; gd = gd->NextGadget )
  833.     {
  834.         if( gd->GadgetID != 0 )
  835.         SetBorder( gd );
  836.     }
  837.     once = 1;
  838.     }
  839.  
  840.     Rnd_NewWindowStructure1.Screen = HackScreen;
  841.     if( ( w = OpenShWindow( (void *)&Rnd_NewWindowStructure1 ) ) == NULL )
  842.     {
  843.     AbortIO( (struct IORequest *)trq );
  844.     WaitIO( (struct IORequest *)trq );
  845.     CloseDevice( (struct IORequest *)trq );
  846.     DeleteExtIO( (struct IORequest *) trq );
  847.     DeletePort( tport );
  848.     Delay( 50 * 8 );
  849.     return;
  850.     }
  851.     PrintIText( w->RPort, &Rnd_IntuiTextList1, 0, 0 );
  852.  
  853.     mask = (1L << tport->mp_SigBit)|(1L << w->UserPort->mp_SigBit);
  854.     while( !aredone )
  855.     {
  856.     got = Wait( mask );
  857.     if( got & (1L << tport->mp_SigBit ) )
  858.     {
  859.         aredone = 1;
  860.         timerdone = 1;
  861.         GetMsg( tport );
  862.         CloseShWindow( w );
  863.         w = NULL;
  864.         }
  865.         while( w && ( imsg = (struct IntuiMessage *) GetMsg( w->UserPort ) ) )
  866.         {
  867.         switch( imsg->Class )
  868.         {
  869.         /* Must be up for a little while... */
  870.         case INACTIVEWINDOW:
  871.         if( ticks >= 40 )
  872.             aredone = 1;
  873.         break;
  874.  
  875.         case INTUITICKS:
  876.         ++ticks;
  877.         break;
  878.  
  879.         case GADGETUP:
  880.         aredone = 1;
  881.         break;
  882.         }
  883.         ReplyMsg( (struct Message *)imsg );
  884.         }
  885.     }
  886.  
  887.     if( !timerdone )
  888.     {
  889.     AbortIO( (struct IORequest *)trq );
  890.     WaitIO( (struct IORequest *)trq );
  891.     }
  892.  
  893.     CloseDevice( (struct IORequest *)trq );
  894.     DeleteExtIO( (struct IORequest *) trq );
  895.     DeletePort( tport );
  896.     if(w) CloseShWindow( w );
  897. }
  898. #endif
  899.  
  900. /* this should probably not be needed (or be renamed)
  901. void
  902. flush_output(){} */
  903.  
  904. void
  905. amii_destroy_nhwindow(win)      /* just hide */
  906.     register winid win;
  907. {
  908.     register struct WinDesc *cw;
  909.     register int i;
  910.  
  911.     if( win == WIN_ERR || ( cw = wins[win] ) == NULL )
  912.     {
  913.     panic(winpanicstr,win,"destroy_nhwindow");
  914.     }
  915.  
  916.     /* Tear down the Intuition stuff */
  917.     dismiss_nhwindow(win);
  918.  
  919.     if( cw->data && cw->type == NHW_MESSAGE ||
  920.                 cw->type == NHW_MENU || cw->type == NHW_TEXT )
  921.     {
  922.     for( i = 0; i < cw->maxrow; ++i )
  923.     {
  924.         if( cw->data[ i ] )
  925.         free( cw->data[ i ] );
  926.     }
  927.     free( cw->data );
  928.     cw->data = NULL;
  929.     }
  930.  
  931.     if( cw->resp )
  932.     free( cw->resp );
  933.     cw->resp = NULL;
  934.  
  935.     if( cw->canresp )
  936.     free( cw->canresp );
  937.     cw->canresp = NULL;
  938.  
  939.     if( cw->morestr )
  940.     free( cw->morestr );
  941.     cw->morestr = NULL;
  942.  
  943.     free( cw );
  944.     wins[win] = NULL;
  945. }
  946.  
  947. amii_create_nhwindow(type)
  948.     register int type;
  949. {
  950.     register struct Window *w = NULL;
  951.     register struct NewWindow *nw = NULL;
  952.     register struct WinDesc *wd = NULL;
  953.     struct Window *mapwin = NULL, *stwin = NULL, *msgwin = NULL;
  954.     register int newid;
  955.  
  956.     if( WIN_STATUS != WIN_ERR && wins[ WIN_STATUS ] )
  957.     stwin = wins[ WIN_STATUS ]->win;
  958.  
  959.     if( WIN_MESSAGE != WIN_ERR && wins[ WIN_MESSAGE ] )
  960.     msgwin = wins[ WIN_MESSAGE ]->win;
  961.  
  962.     if( WIN_MAP != WIN_ERR && wins[ WIN_MAP ] )
  963.     mapwin = wins[ WIN_MAP ]->win;
  964.  
  965.     /* Create Port anytime that we need it */
  966.  
  967.     if( HackPort == NULL )
  968.     {
  969.     HackPort = CreatePort( NULL, 0 );
  970.     if( !HackPort )
  971.         panic( "no memory for msg port" );
  972.     }
  973.  
  974.     nw = &new_wins[ type ].newwin;
  975.     nw->Width = amiIDisplay->xpix;
  976.     nw->Screen = HackScreen;
  977.  
  978.     if( type == NHW_MAP || type == NHW_BASE )
  979.     {
  980.     nw->DetailPen = C_WHITE;
  981.     nw->BlockPen = C_MAGENTA;
  982.     nw->TopEdge = 1;
  983.     nw->LeftEdge = 0;
  984.     nw->Height = amiIDisplay->ypix - nw->TopEdge;
  985.     if( bigscreen && type == NHW_MAP )
  986.     {
  987.         int h;
  988.         if( msgwin && stwin )
  989.         {
  990.         h = (stwin->TopEdge - nw->TopEdge - 1) -
  991.                 (msgwin->TopEdge + msgwin->Height + 1);
  992.         h = h - ( (22 * stwin->RPort->TxHeight) +
  993.                     stwin->BorderTop + stwin->BorderBottom );
  994.         /* h is now the available space excluding the map window so
  995.          * divide by 2 and use it to space out the map window.
  996.          */
  997.         if( h > 0 )
  998.             h /= 2;
  999.         else
  1000.             h = 0;
  1001.         nw->TopEdge = msgwin->TopEdge + msgwin->Height + 1 + h;
  1002.         nw->Height = stwin->TopEdge + 1 - nw->TopEdge - h;
  1003.         }
  1004.         else
  1005.         {
  1006.         h = amiIDisplay->ypix - (22 * FONTHEIGHT) - 12 - 10;
  1007.         if( h > 0 )
  1008.         {
  1009.             nw->TopEdge = h / 2;
  1010.             nw->Height = (22 * FONTHEIGHT) + 12 + 10;
  1011.         }
  1012.         else
  1013.         {
  1014.             nw->Height -= 85;
  1015.             nw->TopEdge += 35;
  1016.         }
  1017.         }
  1018.     }
  1019.     }
  1020.     else if( type == NHW_STATUS )
  1021.     {
  1022.     nw->DetailPen = C_CYAN;
  1023.     nw->BlockPen = C_CYAN;
  1024.     if( WIN_MAP != WIN_ERR && wins[ WIN_MAP ] )
  1025.         w = wins[ WIN_MAP ]->win;
  1026.     else if( WIN_BASE != WIN_ERR && wins[ WIN_BASE ] )
  1027.         w = wins[ WIN_BASE ]->win;
  1028.     else
  1029.         panic( "No window to base STATUS location from" );
  1030.  
  1031.     /* Status window is relative to bottom of WIN_BASE/WIN_MAP */
  1032.  
  1033.     if( mapwin && bigscreen )
  1034.     {
  1035.         nw->TopEdge = mapwin->TopEdge + mapwin->Height;
  1036.         nw->Height = amiIDisplay->ypix - nw->TopEdge - 1;
  1037.     }
  1038.     else
  1039.     {
  1040.         /* Expand the height of window by borders */
  1041.         if( bigscreen )
  1042.         nw->Height = (txheight * 2) + 17;
  1043.  
  1044.         nw->TopEdge = amiIDisplay->ypix - nw->Height;
  1045.         nw->LeftEdge = w->LeftEdge;
  1046.         if( nw->LeftEdge + nw->Width >= amiIDisplay->xpix )
  1047.         nw->LeftEdge = 0;
  1048.         if( nw->Width >= amiIDisplay->xpix - nw->LeftEdge )
  1049.         nw->Width = amiIDisplay->xpix - nw->LeftEdge;
  1050.     }
  1051.     }
  1052.     else if( type == NHW_MESSAGE )
  1053.     {
  1054.     nw->DetailPen = C_RED;
  1055.     nw->BlockPen = C_RED;
  1056.     if( WIN_MAP != WIN_ERR && wins[ WIN_MAP ] )
  1057.         w = wins[ WIN_MAP ]->win;
  1058.     else if( WIN_BASE != WIN_ERR && wins[ WIN_BASE ] )
  1059.         w = wins[ WIN_BASE ]->win;
  1060.     else
  1061.         panic( "No window to base STATUS location from" );
  1062.  
  1063.     nw->TopEdge = 1;
  1064.     if( bigscreen )
  1065.     {
  1066.         if( mapwin )
  1067.         {
  1068.         nw->Height = mapwin->TopEdge - 2;
  1069.         }
  1070.         else
  1071.         {
  1072.         nw->Height += 15;
  1073.         }
  1074.     }
  1075.     }
  1076.     else
  1077.     {
  1078.     nw->DetailPen = C_WHITE;
  1079.     nw->BlockPen = C_MAGENTA;
  1080.     }
  1081.  
  1082.     /* When Interlaced, there is "Room" for all this stuff */
  1083. /* WRONG - still not enough space on MAP for right border */
  1084.     if( bigscreen && type != NHW_BASE )
  1085.     {
  1086.     nw->Flags &= ~( BORDERLESS | BACKDROP );
  1087. #if 1
  1088.     nw->Flags |= ( WINDOWDRAG | WINDOWDEPTH );
  1089. #else
  1090.     nw->Flags |= ( WINDOWDRAG | WINDOWDEPTH | SIZEBRIGHT );
  1091.     if( type == NHW_MAP )
  1092.         nw->Flags |= WINDOWSIZING;
  1093. #endif
  1094.     }
  1095.     /* No titles on a hires only screen */
  1096.     if( !bigscreen )
  1097.     nw->Title = 0;
  1098.  
  1099.     /* Don't open MENU or TEXT windows yet */
  1100.  
  1101.     if( type == NHW_MENU || type == NHW_TEXT )
  1102.     w = NULL;
  1103.     else
  1104.     w=OpenShWindow( (void *)nw );
  1105.  
  1106.     if( w == NULL && type != NHW_MENU && type != NHW_TEXT )
  1107.     panic("bad openwin %d",type);
  1108.  
  1109.     /* Check for an empty slot */
  1110.  
  1111.     for(newid = 0; newid<MAXWIN + 1; newid++)
  1112.     {
  1113.     if(wins[newid] == 0)
  1114.         break;
  1115.     }
  1116.  
  1117.     if(newid==MAXWIN+1)
  1118.     panic("time to write re-alloc code\n");
  1119.  
  1120.     /* Set wincnt accordingly */
  1121.  
  1122.     if( newid > wincnt )
  1123.     wincnt = newid;
  1124.  
  1125.     /* Do common initialization */
  1126.  
  1127.     wd = (struct WinDesc *)alloc(sizeof(struct WinDesc));
  1128.     memset( wd, 0, sizeof( struct WinDesc ) );
  1129.     wins[newid] = wd;
  1130.  
  1131.     wd->newwin = NULL;
  1132.     wd->win = w;
  1133.     wd->type = type;
  1134.     wd->flags = 0;
  1135.     wd->active = FALSE;
  1136.     wd->curx=wd->cury = 0;
  1137.     wd->resp = wd->canresp = wd->morestr = 0;   /* CHECK THESE */
  1138.     wd->offx = new_wins[type].offx;
  1139.     wd->offy = new_wins[type].offy;
  1140.     wd->maxrow = new_wins[type].maxrow;
  1141.     wd->maxcol = new_wins[type].maxcol;
  1142.  
  1143.     if( type != NHW_TEXT && type != NHW_MENU )
  1144.     {
  1145.     wd->rows = ( w->Height - w->BorderTop - w->BorderBottom ) /(txheight+1);
  1146.     wd->cols = ( w->Width - w->BorderLeft - w->BorderRight ) / txwidth;
  1147.     }
  1148.  
  1149.     /* Okay, now do the individual type initialization */
  1150.  
  1151.     switch(type)
  1152.     {
  1153.     /* History lines for MESSAGE windows are stored in cw->data[?].
  1154.      * maxcol and maxrow are used as cursors.  maxrow is the count
  1155.      * of the number of history lines stored.  maxcol is the cursor
  1156.      * to the last line that was displayed by ^P.
  1157.      */
  1158.     case NHW_MESSAGE:
  1159.         if(flags.msg_history<20)flags.msg_history=20;
  1160.         if(flags.msg_history>200)flags.msg_history=200;
  1161.         flags.window_inited=TRUE;
  1162.         wd->data = (char **)alloc( flags.msg_history*sizeof( char * ) );
  1163.         memset( wd->data, 0, flags.msg_history * sizeof( char * ) );
  1164.         wd->maxrow = wd->maxcol = 0;
  1165.         /* Indicate that we have not positioned the cursor yet */
  1166.         wd->curx = -1;
  1167.         break;
  1168.  
  1169.         /* A MENU contains a list of lines in wd->data[?].  These
  1170.          * lines are created in amii_putstr() by reallocating the size
  1171.          * of wd->data to hold enough (char *)'s.  wd->rows is the
  1172.          * number of (char *)'s allocated.  wd->maxrow is the number
  1173.          * used.  wd->maxcol is used to track how wide the menu needs
  1174.          * to be.  wd->resp[x] contains the characters that correspond
  1175.          * to selecting wd->data[x].  wd->resp[x] corresponds to
  1176.          * wd->data[x] for any x. Elements of wd->data[?] that are not
  1177.          * valid selections have the corresponding element of
  1178.          * wd->resp[] set to a value of '\01';  i.e. a ^A which is
  1179.          * not currently a valid keystroke for responding to any
  1180.          * MENU or TEXT window.
  1181.          */
  1182.     case NHW_MENU:
  1183.         wd->resp=(char*)alloc(256);
  1184.         wd->resp[0]=0;
  1185.         wd->rows = wd->maxrow = 0;
  1186.         wd->maxcol = 0;
  1187.         wd->data = NULL;
  1188.         break;
  1189.  
  1190.         /* See the explanation of MENU above.  Except, wd->resp[] is not
  1191.          * used for TEXT windows since there is no selection of a
  1192.          * a line performed/allowed.  The window is always full
  1193.          * screen width.
  1194.          */
  1195.     case NHW_TEXT:
  1196.         wd->rows = wd->maxrow = 0;
  1197.         wd->maxcol = wd->cols = amiIDisplay->cols;
  1198.         wd->data = NULL;
  1199.         wd->morestr = NULL;
  1200.         break;
  1201.  
  1202.         /* The status window has only two lines.  These are stored in
  1203.          * wd->data[], and here we allocate the space for them.
  1204.          */
  1205.     case NHW_STATUS:
  1206.         /* wd->cols is the number of characters which fit across the
  1207.          * screen.
  1208.          */
  1209.         wd->data=(char **)alloc(3*sizeof(char *));
  1210.         wd->data[0] = (char *)alloc(wd->cols + 10);
  1211.         wd->data[1] = (char *)alloc(wd->cols + 10);
  1212.         wd->data[2] = NULL;
  1213.         break;
  1214.  
  1215.         /* NHW_MAP does not use wd->data[] or the other text
  1216.          * manipulating members of the WinDesc structure.
  1217.          */
  1218.     case NHW_MAP:
  1219.         SetMenuStrip(w, HackMenu);
  1220.         break;
  1221.  
  1222.         /* The base window must exist until CleanUp() deletes it. */
  1223.     case NHW_BASE:
  1224.         /* Make our requesters come to our screen */
  1225.         {
  1226.         register struct Process *myProcess =
  1227.                     (struct Process *) FindTask(NULL);
  1228.         pr_WindowPtr = (struct Window *)(myProcess->pr_WindowPtr);
  1229.         myProcess->pr_WindowPtr = (APTR) w;
  1230.         }
  1231.  
  1232.         /* Need this for RawKeyConvert() */
  1233.  
  1234.         ConsoleIO.io_Data = (APTR) w;
  1235.         ConsoleIO.io_Length = sizeof( struct Window * );
  1236.         ConsoleIO.io_Message.mn_ReplyPort = CreatePort(NULL, 0L);
  1237.         if( OpenDevice("console.device", 0L,
  1238.                 (struct IORequest *) &ConsoleIO, 0L) != 0)
  1239.         {
  1240.         Abort(AG_OpenDev | AO_ConsoleDev);
  1241.         }
  1242.  
  1243.         ConsoleDevice = (struct Library *) ConsoleIO.io_Device;
  1244.  
  1245.         KbdBuffered = 0;
  1246.  
  1247. #ifdef HACKFONT
  1248.         if( HackFont )
  1249.         SetFont(w->RPort, HackFont);
  1250. #endif
  1251.         txwidth = w->RPort->TxWidth;
  1252.         txheight = w->RPort->TxHeight;
  1253.         txbaseline = w->RPort->TxBaseline;
  1254.         break;
  1255.  
  1256.     default:
  1257.         panic("bad create_nhwindow( %d )\n",type);
  1258.         return WIN_ERR;
  1259.     }
  1260.  
  1261.     return( newid );
  1262. }
  1263.  
  1264. /* Initialize the windowing environment */
  1265.  
  1266. void
  1267. amii_init_nhwindows()
  1268. {
  1269.     if (IntuitionBase)
  1270.     panic( "init_nhwindow() called twice", 0 );
  1271.  
  1272.     WIN_MESSAGE = WIN_ERR;
  1273.     WIN_MAP = WIN_ERR;
  1274.     WIN_STATUS = WIN_ERR;
  1275.     WIN_INVEN = WIN_ERR;
  1276.     WIN_BASE = WIN_ERR;
  1277.  
  1278.     if ( (IntuitionBase = (struct IntuitionBase *)
  1279.         OpenLibrary("intuition.library", INTUITION_VERSION)) == NULL)
  1280.     {
  1281.     Abort(AG_OpenLib | AO_Intuition);
  1282.     }
  1283.  
  1284.     if ( (GfxBase = (struct GfxBase *)
  1285.         OpenLibrary("graphics.library", GRAPHICS_VERSION)) == NULL)
  1286.     {
  1287.     Abort(AG_OpenLib | AO_GraphicsLib);
  1288.     }
  1289.  
  1290. #ifdef HACKFONT
  1291.     /*
  1292.      *  Force our own font to be loaded, if possible.
  1293.      *  If we can open diskfont.library, but not our font, we can close
  1294.      *  the diskfont.library again since it just wastes memory.
  1295.      *  Even if we can open the font, we don't need the diskfont.library
  1296.      *  anymore, since CloseFont is a graphics.library function.
  1297.      */
  1298.  
  1299.     if ((HackFont = OpenFont(&Hack80)) == NULL)
  1300.     {
  1301.     if (DiskfontBase =
  1302.             OpenLibrary("diskfont.library", DISKFONT_VERSION))
  1303.     {
  1304.         Hack80.ta_Name -= SIZEOF_DISKNAME;
  1305.         HackFont = OpenDiskFont(&Hack80);
  1306.         Hack80.ta_Name += SIZEOF_DISKNAME;
  1307.         CloseLibrary(DiskfontBase);
  1308.         DiskfontBase = NULL;
  1309.     }
  1310.     }
  1311. #endif
  1312.  
  1313.     amiIDisplay=(struct DisplayDesc *)alloc(sizeof(struct DisplayDesc));
  1314.     memset( amiIDisplay, 0, sizeof( struct DisplayDesc ) );
  1315.  
  1316.     /* Use Intuition sizes for overscan screens... */
  1317.  
  1318.     amiIDisplay->ypix = GfxBase->NormalDisplayRows;
  1319.     amiIDisplay->xpix = GfxBase->NormalDisplayColumns;
  1320.  
  1321.     amiIDisplay->cols = amiIDisplay->xpix / FONTWIDTH;
  1322.  
  1323.     amiIDisplay->toplin=0;
  1324.     amiIDisplay->rawprint=0;
  1325.     amiIDisplay->lastwin=0;
  1326.  
  1327.     if( bigscreen == 0 )
  1328.     {
  1329.     if( ( GfxBase->ActiView->ViewPort->Modes & LACE ) == LACE )
  1330.     {
  1331.         amiIDisplay->ypix *= 2;
  1332.         NewHackScreen.ViewModes |= LACE;
  1333.         bigscreen = 1;
  1334.     }
  1335.     else if( GfxBase->NormalDisplayRows >= 240 )
  1336.     {
  1337.         bigscreen = 1;
  1338.     }
  1339.     }
  1340.     else if( bigscreen == -1 )
  1341.     bigscreen = 0;
  1342.     else if( bigscreen )
  1343.     {
  1344.     /* If bigscreen requested and we don't have enough rows in
  1345.      * noninterlaced mode, switch to interlaced...
  1346.      */
  1347.     if( GfxBase->NormalDisplayRows < 240 )
  1348.     {
  1349.         amiIDisplay->ypix *= 2;
  1350.         NewHackScreen.ViewModes |= LACE;
  1351.     }
  1352.     }
  1353.     amiIDisplay->rows = amiIDisplay->ypix / FONTHEIGHT;
  1354.  
  1355.     /* This is the size screen we want to open, within reason... */
  1356.  
  1357.     NewHackScreen.Width = max( WIDTH, amiIDisplay->xpix );
  1358.     NewHackScreen.Height = max( SCREENHEIGHT, amiIDisplay->ypix );
  1359.  
  1360.     if( ( HackScreen = OpenScreen( (void *)&NewHackScreen ) ) == NULL )
  1361.     Abort( AN_OpenScreen & ~AT_DeadEnd );
  1362. #ifdef  INTUI_NEW_LOOK
  1363.     if( IntuitionBase->LibNode.lib_Version >= 37 )
  1364.     {
  1365.     PubScreenStatus( HackScreen, 0 );
  1366.     }
  1367. #endif
  1368.  
  1369. #ifdef TEXTCOLOR
  1370.     LoadRGB4(&HackScreen->ViewPort, amii_curmap, 1L << DEPTH );
  1371. #endif
  1372.  
  1373.     /* Display the copyright etc... */
  1374.  
  1375.     if( WIN_BASE == WIN_ERR )
  1376.     WIN_BASE = amii_create_nhwindow( NHW_BASE );
  1377.     amii_clear_nhwindow( WIN_BASE );
  1378.     amii_putstr( WIN_BASE, 0, "" );
  1379.     amii_putstr( WIN_BASE, 0, "" );
  1380.     amii_putstr( WIN_BASE, 0, "" );
  1381.     amii_putstr( WIN_BASE, 0,
  1382.       "NetHack, Copyright 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993.");
  1383.     amii_putstr( WIN_BASE, 0,
  1384.     "         By Stichting Mathematisch Centrum and M. Stephenson.");
  1385.     amii_putstr( WIN_BASE, 0, "         See license for details.");
  1386.     amii_putstr( WIN_BASE, 0, "");
  1387.  
  1388.     Initialized = 1;
  1389. }
  1390.  
  1391. #ifdef COM_COMPL
  1392. /* Read in an extended command - doing command line completion for
  1393.  * when enough characters have been entered to make a unique command.
  1394.  */
  1395. void
  1396. amii_get_ext_cmd(bufp)
  1397. register char *bufp;
  1398. {
  1399.     register char *obufp = bufp;
  1400.     register int c;
  1401.     int com_index, oindex;
  1402.     struct WinDesc *cw;
  1403.     struct Window *w;
  1404.     int colx;
  1405.  
  1406.     if( WIN_MESSAGE == WIN_ERR || ( cw = wins[ WIN_MESSAGE ] ) == NULL )
  1407.     panic(winpanicstr, WIN_MESSAGE, "get_ext_cmd");
  1408.     amii_clear_nhwindow( NHW_MESSAGE );
  1409.     pline("# ");
  1410.     colx = 3;
  1411.     w = cw->win;
  1412.  
  1413.     while((c = WindowGetchar()) != EOF)
  1414.     {
  1415.     amii_curs( WIN_MESSAGE, colx, 0 );
  1416.     if(c == '?' )
  1417.     {
  1418.         int win, i, sel;
  1419.         char buf[ 100 ];
  1420.  
  1421.         win = amii_create_nhwindow( NHW_MENU );
  1422.         amii_start_menu( win );
  1423.  
  1424.         for( i = 0; extcmdlist[ i ].ef_txt != NULL; ++i )
  1425.         {
  1426.         sprintf( buf, "%-10s - %s ",
  1427.              extcmdlist[ i ].ef_txt,
  1428.              extcmdlist[ i ].ef_desc );
  1429.         amii_add_menu( win, extcmdlist[i].ef_txt[0], 0, buf );
  1430.         }
  1431.  
  1432.         amii_end_menu( win, i, "\33", NULL );
  1433.         sel = amii_select_menu( win );
  1434.         amii_destroy_nhwindow( win );
  1435.  
  1436.         if( sel == '\33' )
  1437.         {
  1438.         *obufp = '\33';
  1439.         obufp[ 1 ] = 0;
  1440.         }
  1441.         else
  1442.         {
  1443.         for( i = 0; extcmdlist[ i ].ef_txt != NULL; ++i )
  1444.         {
  1445.             if( sel == extcmdlist[i].ef_txt[0] )
  1446.             break;
  1447.         }
  1448.  
  1449.         /* copy in the text */
  1450.         amii_clear_nhwindow( WIN_MESSAGE );
  1451.         strcpy( obufp, extcmdlist[ i ].ef_txt );
  1452.         colx = 0;
  1453.         pline( "# " );
  1454.         pline( obufp );
  1455.         bufp = obufp + 2;
  1456.         }
  1457.         return;
  1458.     }
  1459.     else if(c == '\033')
  1460.     {
  1461.         *obufp = c;
  1462.         obufp[1] = 0;
  1463.         return;
  1464.     }
  1465.     else if(c == '\b')
  1466.     {
  1467.         if(bufp != obufp)
  1468.         {
  1469.         bufp--;
  1470.         amii_curs( WIN_MESSAGE, --colx, 0);
  1471.         Text( w->RPort, spaces, 1 );
  1472.         amii_curs( WIN_MESSAGE, colx, 0);
  1473.         }
  1474.         else
  1475.         DisplayBeep( NULL );
  1476.     }
  1477.     else if( c == '\n' || c == '\r' )
  1478.     {
  1479.         *bufp = 0;
  1480.         return;
  1481.     }
  1482.     else if(' ' <= c && c < '\177')
  1483.     {
  1484.         /* avoid isprint() - some people don't have it
  1485.            ' ' is not always a printing char */
  1486.         *bufp = c;
  1487.         bufp[1] = 0;
  1488.         oindex = 0;
  1489.         com_index = -1;
  1490.  
  1491.         while(extcmdlist[oindex].ef_txt != NULL)
  1492.         {
  1493.         if(!strncmpi(obufp, extcmdlist[oindex].ef_txt, strlen(obufp)))
  1494.         {
  1495.             if(com_index == -1) /* No matches yet*/
  1496.             com_index = oindex;
  1497.             else /* More than 1 match */
  1498.             com_index = -2;
  1499.         }
  1500.         oindex++;
  1501.         }
  1502.  
  1503.         if(com_index >= 0 && *obufp )
  1504.         {
  1505.         Strcpy(obufp, extcmdlist[com_index].ef_txt);
  1506.         /* finish printing our string */
  1507.         Text( w->RPort, bufp, strlen( bufp ) );
  1508.         amii_curs( WIN_MESSAGE, colx += strlen( bufp ), 0);
  1509.         bufp = obufp; /* reset it */
  1510.         if(strlen(obufp) < BUFSZ-1 && strlen(obufp) < COLNO)
  1511.             bufp += strlen(obufp);
  1512.         }
  1513.         else
  1514.         {
  1515.         Text( w->RPort, bufp, strlen( bufp ) );
  1516.         amii_curs( WIN_MESSAGE, colx += strlen( bufp ), 0);
  1517.         if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO)
  1518.             bufp++;
  1519.         }
  1520.     }
  1521.     else if(c == ('X'-64) || c == '\177')
  1522.     {
  1523.         colx = 0;
  1524.         amii_clear_nhwindow( WIN_MESSAGE );
  1525.         pline( "# " );
  1526.         bufp = obufp;
  1527.     } else
  1528.         DisplayBeep( NULL );
  1529.     }
  1530.     *bufp = 0;
  1531.     return;
  1532. }
  1533. #endif /* COM_COMPL */
  1534.  
  1535. #ifdef WINDOW_YN
  1536. SHORT Ask_BorderVectors1[] = { 0,0, 29,0, 29,11, 0,11, 0,0 };
  1537. struct Border Ask_Border1 = { -1,-1, 3,0,JAM1, 5, Ask_BorderVectors1, NULL };
  1538. struct IntuiText Ask_IText1 = { 3,0,JAM2, 2,1, NULL, "(?)", NULL };
  1539.  
  1540. struct Gadget Ask_Gadget1 = {
  1541.     NULL, 9,4, 28,10, NULL, RELVERIFY, BOOLGADGET, (APTR)&Ask_Border1,
  1542.     NULL, &Ask_IText1, NULL, NULL, NULL, NULL
  1543. };
  1544.  
  1545. #define Ask_GadgetList1 Ask_Gadget1
  1546.  
  1547. struct IntuiText Ask_IText2 = { 1,0,JAM2, 44,5, NULL, NULL, NULL };
  1548.  
  1549. #define Ask_IntuiTextList1 Ask_IText2
  1550.  
  1551. struct NewWindow Ask_Window = {
  1552.     75,85, 524,18, 0,1, GADGETUP+VANILLAKEY, ACTIVATE+NOCAREREFRESH,
  1553.     &Ask_Gadget1, NULL, NULL, NULL, NULL, 5,5, -1,-1, CUSTOMSCREEN
  1554. };
  1555. #endif
  1556.  
  1557. /* Ask a question and get a response */
  1558.  
  1559. char amii_yn_function( prompt, resp, def )
  1560.     const char *prompt,*resp;
  1561.     char def;
  1562. {
  1563.     char ch;
  1564. #ifndef WINDOW_YN
  1565.     char buf[ 80 ];
  1566.  
  1567.     if( def && def!='q')
  1568.     {
  1569.     sprintf( buf, "%s [%c] ", prompt, def );
  1570.     amii_addtopl( buf );
  1571.     } else {
  1572.     amii_addtopl( prompt );
  1573.     }
  1574.  
  1575.     cursor_on( WIN_MESSAGE );
  1576.     do {
  1577.     ch = WindowGetchar();
  1578.     if( ch == '\33' )
  1579.         break;
  1580.     else if( def && ( ch == '\n' || ch == '\r' ) )
  1581.     {
  1582.         ch = def;
  1583.         break;
  1584.     }
  1585.     } while( resp && *resp && index( resp, ch ) == 0 );
  1586.  
  1587.     cursor_off( WIN_MESSAGE );
  1588.     if( ch == '\33' )
  1589.     {
  1590.     /*amii_addtopl( " you change your mind..." );*/
  1591.     ch = 0;
  1592.     }
  1593.     /* Try this to make topl behave more appropriately? */
  1594.     clear_nhwindow( WIN_MESSAGE );
  1595. #else
  1596.     struct Window *cwin;
  1597.     struct IntuiMessage *imsg;
  1598.     int aredone = 0, xcor;
  1599.     struct Gadget *gd;
  1600.     char buf[ 4 ];
  1601.  
  1602.     *StrString = 0;
  1603.  
  1604.     Ask_Window.Screen = HackScreen;
  1605.     Ask_IText1.IText = buf;
  1606.     Ask_IText2.IText = prompt;
  1607.     if( def )
  1608.     {
  1609.     sprintf( buf, "[%c]", def );
  1610.     Ask_Window.FirstGadget = &Ask_Gadget1;
  1611.     Ask_IText2.LeftEdge = 44;
  1612.     }
  1613.     else
  1614.     {
  1615.     Ask_Window.FirstGadget = NULL;
  1616.     Ask_IText2.LeftEdge = 9;
  1617.     }
  1618.  
  1619.     /* Use this RPort to get needed dimensions */
  1620.  
  1621.     if( cwin = wins[WIN_MAP]->win )
  1622.     {
  1623.     Ask_IText1.LeftEdge =
  1624.     (Ask_Gadget1.Width - cwin->BorderLeft - cwin->BorderRight) / 2;
  1625.     Ask_Window.Width =
  1626.      Ask_IText2.LeftEdge + (5 + strlen( prompt )) * txwidth;
  1627.     xcor = Ask_IText2.LeftEdge + (2 + strlen( prompt )) * txwidth;
  1628.     }
  1629.  
  1630.     if( ( cwin = OpenShWindow( (void *)&Ask_Window ) ) == NULL )
  1631.     return( 0 );
  1632.  
  1633.     PrintIText( cwin->RPort, &Ask_IntuiTextList1, 0, 0 );
  1634.  
  1635.     while( !aredone )
  1636.     {
  1637.     WaitPort( cwin->UserPort );
  1638.     while( ( imsg = (void *) GetMsg( cwin->UserPort ) ) != NULL )
  1639.     {
  1640.         switch( imsg->Class )
  1641.         {
  1642.         case VANILLAKEY:
  1643.             Move( cwin->RPort, xcor,
  1644.             Ask_IText2.TopEdge + txheight - 1 );
  1645.             ch = imsg->Code;
  1646.             if( ch != '\33' )
  1647.             {
  1648.             Text( cwin->RPort, &ch, 1 );
  1649.             if( resp == NULL || *resp == 0 ||
  1650.                             index( resp, ch ) )
  1651.             {
  1652.                 aredone = 1;
  1653.                 Delay( 45 );
  1654.             }
  1655.             else
  1656.                 DisplayBeep( NULL );
  1657.             }
  1658.             else
  1659.             {
  1660.             aredone = 1;
  1661.             }
  1662.             break;
  1663.  
  1664.         case GADGETUP:
  1665.             gd = (struct Gadget *) imsg->IAddress;
  1666.             switch( gd->GadgetID )
  1667.             {
  1668.             case 1:
  1669.                 ch = def;
  1670.                 aredone = 1;
  1671.                 break;
  1672.             }
  1673.             break;
  1674.         }
  1675.         ReplyMsg( (struct Message *) imsg );
  1676.     }
  1677.     }
  1678.  
  1679.     CloseShWindow( cwin );
  1680. #endif
  1681.     return( ch );
  1682. }
  1683.  
  1684. /* Add a line in the message window */
  1685.  
  1686. void
  1687. amii_addtopl(s)
  1688.     const char *s;
  1689. {
  1690.     amii_putstr(WIN_MESSAGE,0,s);   /* is this right? */
  1691. }
  1692.  
  1693. void
  1694. TextSpaces( rp, nr )
  1695.     struct RastPort *rp;
  1696.     int nr;
  1697. {
  1698.     if( nr < 1 )
  1699.     return;
  1700.  
  1701.     while (nr > sizeof(spaces) - 1)
  1702.     {
  1703.     Text(rp, spaces, (long)sizeof(spaces) - 1);
  1704.     nr -= sizeof(spaces) - 1;
  1705.     }
  1706.     if (nr > 0)
  1707.     Text(rp, spaces, (long)nr);
  1708. }
  1709.  
  1710. /* Put a string into the indicated window using the indicated attribute */
  1711.  
  1712. void
  1713. amii_putstr(window,attr,str)
  1714.     winid window;
  1715.     int attr;
  1716.     const char *str;
  1717. {
  1718.     struct Window *w;
  1719.     register struct WinDesc *cw;
  1720.     register char *ob;
  1721.     int i, j, n0;
  1722.  
  1723.     /* Always try to avoid a panic when there is no window */
  1724.     if( window == WIN_ERR )
  1725.     {
  1726.     window = WIN_BASE;
  1727.     if( window == WIN_ERR )
  1728.         window = WIN_BASE = amii_create_nhwindow( NHW_BASE );
  1729.     }
  1730.  
  1731.     if( window == WIN_ERR || ( cw = wins[window] ) == NULL )
  1732.     {
  1733.     /* tty does this differently - is this OK? */
  1734.     flags.window_inited=0;
  1735.     panic(winpanicstr,window, "putstr");
  1736.     }
  1737.  
  1738.     w = cw->win;
  1739.  
  1740.     if(!str)return;
  1741.     amiIDisplay->lastwin=window;    /* do we care??? */
  1742.  
  1743.     /* NHW_MENU windows are not opened immediately, so check if we
  1744.      * have the window pointer yet
  1745.      */
  1746.  
  1747.     if( w )
  1748.     {
  1749.     /* Force the drawing mode and pen colors */
  1750.  
  1751.     SetDrMd( w->RPort, JAM2 );
  1752.     if( cw->type == NHW_STATUS )
  1753.         SetAPen( w->RPort, attr ? C_BLUE : C_CYAN );
  1754.     else if( cw->type == NHW_MESSAGE )
  1755.         SetAPen( w->RPort, attr ? C_RED : C_WHITE );
  1756.     else
  1757.         SetAPen( w->RPort, attr ? C_WHITE : C_RED );
  1758.     SetBPen( w->RPort, C_BLACK );
  1759.     }
  1760.     else if( cw->type != NHW_MENU && cw->type != NHW_TEXT )
  1761.     {
  1762.     panic( "NULL window pointer in putstr 2" );
  1763.     }
  1764.  
  1765.     /* Okay now do the work for each type */
  1766.  
  1767.     switch(cw->type)
  1768.     {
  1769. #define MORE_FUDGE  10  /* 8 for --more--, 1 for preceeding sp, 1 for */
  1770.         /* putstr pad */
  1771.     case NHW_MESSAGE:
  1772.     strncpy( toplines, str, sizeof( toplines ) );
  1773.     toplines[ sizeof( toplines ) - 1 ] = 0;
  1774.         /* Needed for initial message to be visible */
  1775.     if( cw->curx == -1 )
  1776.     {
  1777.         amii_curs( WIN_MESSAGE, 1, 0 );
  1778.         cw->curx = 0;
  1779.     }
  1780.  
  1781.     if(strlen(str) >= (cw->cols-MORE_FUDGE))
  1782.     {
  1783.         int i;
  1784.         char *p;
  1785.  
  1786.         while( strlen( str ) >= (cw->cols-MORE_FUDGE) )
  1787.         {
  1788.         for(p=(&str[ cw->cols ])-MORE_FUDGE; !isspace(*p) && p != str;)
  1789.         {
  1790.             --p;
  1791.         }
  1792.         if( p == str )
  1793.             p = &str[ cw->cols ];
  1794.         outsubstr( cw, str, i = (long)p-(long)str );
  1795.         cw->curx += i;
  1796.         amii_cl_end( cw, cw->curx );
  1797.         str = p+1;
  1798.         }
  1799.         if( *str )
  1800.         {
  1801.         outsubstr( cw, str, i = strlen( str ) );
  1802.         cw->curx += i;
  1803.         amii_cl_end( cw, cw->curx );
  1804.         }
  1805.     }
  1806.     else
  1807.     {
  1808.         outsubstr( cw, str, i = strlen( str ) );
  1809.         cw->curx += i;
  1810.         amii_cl_end( cw, cw->curx );
  1811.     }
  1812.  
  1813.         /* If used all of history lines, move them down */
  1814.  
  1815.         if( cw->maxrow == flags.msg_history )
  1816.         {
  1817.         if( cw->data[ 0 ] )
  1818.             free( cw->data[ 0 ] );
  1819.         memcpy( cw->data, &cw->data[ 1 ],
  1820.             ( flags.msg_history - 1 ) * sizeof( char * ) );
  1821.         cw->data[ flags.msg_history - 1 ] =
  1822.                 (char *) alloc( strlen( toplines ) + 1 );
  1823.         strcpy( cw->data[ flags.msg_history - 1 ], toplines );
  1824.         }
  1825.         else
  1826.         {
  1827.         /* Otherwise, allocate a new one and copy the line in */
  1828.         cw->data[ cw->maxrow ] = (char *)
  1829.                         alloc( strlen( toplines ) + 1 );
  1830.         strcpy( cw->data[ cw->maxrow++ ], toplines );
  1831.         }
  1832.         cw->maxcol = cw->maxrow;
  1833.         break;
  1834.  
  1835.     case NHW_STATUS:
  1836.     if( cw->data[ cw->cury ] == NULL )
  1837.         panic( "NULL pointer for status window" );
  1838.     ob = &cw->data[cw->cury][j = cw->curx];
  1839.     if(flags.botlx) *ob = 0;
  1840.  
  1841.         /* Display when beam at top to avoid flicker... */
  1842.     WaitTOF();
  1843.     Text(w->RPort,str,strlen(str));
  1844.     if( cw->cols > strlen( str ) )
  1845.         TextSpaces( w->RPort, cw->cols - strlen( str ) );
  1846.  
  1847.     (void) strncpy(cw->data[cw->cury], str, cw->cols );
  1848.     cw->data[cw->cury][cw->cols-1] = '\0'; /* null terminate */
  1849.     cw->cury = (cw->cury+1) % 2;
  1850.     cw->curx = 0;
  1851.     break;
  1852.  
  1853.     case NHW_MAP:
  1854.     case NHW_BASE:
  1855.     amii_curs(window, cw->curx+1, cw->cury);
  1856.     Text(w->RPort,str,strlen(str));
  1857.     cw->curx = 0;
  1858.         /* CR-LF is automatic in these windows */
  1859.     cw->cury++;
  1860.     break;
  1861.  
  1862.     case NHW_MENU:
  1863.     case NHW_TEXT:
  1864.  
  1865.     /* always grows one at a time, but alloc 12 at a time */
  1866.  
  1867.     if( cw->cury >= cw->rows || !cw->data ) {
  1868.         char **tmp;
  1869.  
  1870.         /* Allocate 12 more rows */
  1871.         cw->rows += 12;
  1872.         tmp = (char**) alloc(sizeof(char*) * cw->rows);
  1873.  
  1874.         /* Copy the old lines */
  1875.         for(i=0; i<cw->cury; i++)
  1876.         tmp[i] = cw->data[i];
  1877.  
  1878.         if( cw->data )
  1879.         free( cw->data );
  1880.  
  1881.         cw->data = tmp;
  1882.  
  1883.         /* Null out the unused entries. */
  1884.         for(i=cw->cury; i<cw->rows; i++)
  1885.         cw->data[i] = 0;
  1886.     }
  1887.  
  1888.     if( !cw->data )
  1889.         panic("no data storage");
  1890.  
  1891.         /* Shouldn't need to do this, but... */
  1892.  
  1893.     if( cw->data && cw->data[cw->cury] )
  1894.         free( cw->data[cw->cury] );
  1895.  
  1896.     n0 = strlen(str)+1;
  1897.     cw->data[cw->cury] = (char*) alloc(n0+SOFF);
  1898.  
  1899.         /* avoid nuls, for convenience */
  1900.     cw->data[cw->cury][VATTR] = attr+1;
  1901.     cw->data[cw->cury][SEL_ITEM] = 0;
  1902.     Strcpy( cw->data[cw->cury] + SOFF, str);
  1903.  
  1904.     if(n0 > cw->maxcol) cw->maxcol = n0;
  1905.     if(++cw->cury > cw->maxrow) cw->maxrow = cw->cury;
  1906.     break;
  1907.  
  1908.     default:
  1909.     panic("Invalid or unset window type in putstr()");
  1910.     }
  1911. }
  1912.  
  1913. static void
  1914. outmore( cw )
  1915.     register struct WinDesc *cw;
  1916. {
  1917.     struct Window *w = cw->win;
  1918.  
  1919.     Text( w->RPort, " --more--", 9 );
  1920.     /* Allow mouse clicks to clean --more-- */
  1921.     WindowGetevent( );
  1922.     amii_curs( WIN_MESSAGE, 1, 0 );
  1923.     cw->curx = 0;
  1924.     amii_cl_end( cw, cw->curx );
  1925. }
  1926.  
  1927. static void
  1928. outsubstr( cw, str, len )
  1929.     register struct WinDesc *cw;
  1930.     char *str;
  1931.     int len;
  1932. {
  1933.     struct Window *w = cw->win;
  1934.  
  1935.     if( cw->curx )
  1936.     {
  1937.     /* Check if this string and --more-- fit, if not,
  1938.      * then put out --more-- and wait for a key.
  1939.      */
  1940.     if( (len + MORE_FUDGE ) + cw->curx >= cw->cols )
  1941.     {
  1942.         outmore( cw );
  1943.     }
  1944.     else
  1945.     {
  1946.         /* Otherwise, move and put out a blank separator */
  1947.         Text( w->RPort, spaces, 1 );
  1948.         cw->curx += 1;
  1949.     }
  1950.     }
  1951.  
  1952.     Text(w->RPort,str,len);
  1953. }
  1954.  
  1955. /* Put a graphics character onto the screen */
  1956.  
  1957. void
  1958. amii_putsym( st, i, y, c )
  1959.     winid st;
  1960.     int i, y;
  1961.     CHAR_P c;
  1962. {
  1963.     char buf[ 2 ];
  1964.     amii_curs( st, i, y );
  1965.     buf[ 0 ] = c;
  1966.     buf[ 1 ] = 0;
  1967.     amii_putstr( st, 0, buf );
  1968. }
  1969.  
  1970. /* Clear the indicated window */
  1971.  
  1972. void
  1973. amii_clear_nhwindow(win)
  1974.     register winid win;
  1975. {
  1976.     register struct WinDesc *cw;
  1977.     register struct Window *w;
  1978.  
  1979.     if( win == WIN_ERR || ( cw = wins[win] ) == NULL )
  1980.     panic( winpanicstr, win, "clear_nhwindow" );
  1981.  
  1982.     if( w = cw->win )
  1983.     SetDrMd( w->RPort, JAM2);
  1984.  
  1985.     cursor_off( win );
  1986.  
  1987.     /* should be: clear the rastport, reset x,y etc */
  1988.  
  1989.     if( cw->type == NHW_MENU || cw->type == NHW_TEXT )
  1990.     {
  1991.     /* Window might not be opened yet */
  1992.  
  1993.     if( w )
  1994.     {
  1995.         SetAPen( w->RPort, 0 );
  1996.         SetBPen( w->RPort, 0 );
  1997.         RectFill( w->RPort, w->BorderLeft, w->BorderTop,
  1998.           w->Width - w->BorderRight-1,
  1999.           w->Height - w->BorderBottom-1 );
  2000.         SetAPen( w->RPort, 1 );
  2001.     }
  2002.     }
  2003.     else if( w )
  2004.     {
  2005.     if( cw->type == NHW_MESSAGE )
  2006.     {
  2007.         amii_curs( win, 1, 0 );
  2008.         TextSpaces( w->RPort, cw->cols );
  2009.     }
  2010.     else
  2011.     {
  2012.         SetAPen( w->RPort, 0 );
  2013.         SetBPen( w->RPort, 0 );
  2014.         RectFill( w->RPort, w->BorderLeft, w->BorderTop,
  2015.           w->Width - w->BorderRight-1,
  2016.           w->Height - w->BorderBottom-1 );
  2017.         SetAPen( w->RPort, 1 );
  2018.     }
  2019.     }
  2020.  
  2021.     cw->curx = cw->cury = 0;
  2022.     amii_curs( win, 1, 0 );
  2023. }
  2024.  
  2025. /* Dismiss the window from the screen */
  2026.  
  2027. static void
  2028. dismiss_nhwindow(win)
  2029.     register winid win;
  2030. {
  2031.     register struct Window *w;
  2032.     register struct WinDesc *cw;
  2033.  
  2034.     if( win == WIN_ERR || ( cw = wins[win] ) == NULL )
  2035.     {
  2036.     panic(winpanicstr,win, "dismiss_nhwindow");
  2037.     }
  2038.  
  2039.     w = cw->win;
  2040.  
  2041.     if( w )
  2042.     {
  2043.     /* Map Window has this stuff attached to it. */
  2044.     if( win == WIN_MAP )
  2045.         ClearMenuStrip( w );
  2046.  
  2047.     /* Close the window? */
  2048.  
  2049.     CloseShWindow( w );
  2050.     cw->win = NULL;
  2051.  
  2052.     if( cw->newwin )
  2053.         FreeNewWindow( (void *)cw->newwin );
  2054.     cw->newwin = NULL;
  2055.     }
  2056.  
  2057.     if( cw->canresp )
  2058.     free( cw->canresp );
  2059.     cw->canresp = NULL;
  2060.  
  2061.     if( cw->morestr )
  2062.     free( cw->morestr );
  2063.     cw->morestr = NULL;
  2064.  
  2065.     cw->maxrow = cw->maxcol = 0;
  2066. }
  2067.  
  2068. void
  2069. amii_exit_nhwindows(str)
  2070.     const char *str;
  2071. {
  2072.     /* Seems strange to have to do this... but we need the BASE window
  2073.      * left behind...
  2074.      */
  2075.     kill_nhwindows( 0 );
  2076.     if( str ) raw_print( str );
  2077. }
  2078.  
  2079. amii_nh_poskey(x, y, mod)
  2080.     int*x, *y, *mod;
  2081. {
  2082.     struct WinDesc *cw;
  2083.     WETYPE type;
  2084.     struct RastPort *rp;
  2085.     struct Window *w;
  2086.  
  2087.     if( WIN_MAP != WIN_ERR && (cw = wins[ WIN_MAP ]) && ( w = cw->win ) )
  2088.     cursor_on( WIN_MAP );
  2089.     else
  2090.     panic( "no MAP window opened for nh_poskey\n" );
  2091.  
  2092.     rp = w->RPort;
  2093.     while( 1 )
  2094.     {
  2095.     type = WindowGetevent( );
  2096.     if( type == WEMOUSE )
  2097.     {
  2098.         *mod = CLICK_1;
  2099.         if( lastevent.u.mouse.qual )
  2100.         *mod = 0;
  2101.  
  2102.         /* X coordinates are 1 based, Y are zero based. */
  2103.         *x = ( (lastevent.u.mouse.x - w->BorderLeft) / txwidth ) + 1;
  2104.         *y = ( ( lastevent.u.mouse.y - w->BorderTop-txbaseline ) /
  2105.             txheight );
  2106.         return( 0 );
  2107.     }
  2108.     else if( type == WEKEY )
  2109.     {
  2110.         lastevent.type = WEUNK;
  2111.         return( lastevent.u.key );
  2112.     }
  2113.     }
  2114. }
  2115.  
  2116. int
  2117. amii_nhgetch()
  2118. {
  2119.     int ch;
  2120.  
  2121.     if( WIN_MAP != WIN_ERR && wins[ WIN_MAP ] )
  2122.     cursor_on( WIN_MAP );
  2123.     ch = WindowGetchar();
  2124.     return( ch );
  2125. }
  2126.  
  2127. void
  2128. amii_get_nh_event()
  2129. {
  2130.     /* nothing now - later I have no idea.  Is this just a Mac hook? */
  2131. }
  2132.  
  2133. void
  2134. amii_remember_topl()
  2135. {
  2136.     /* ignore for now.  I think this will be done automatically by
  2137.      * the code writing to the message window, but I could be wrong.
  2138.      */
  2139. }
  2140.  
  2141. int
  2142. amii_doprev_message()
  2143. {
  2144.     struct WinDesc *cw;
  2145.     struct Window *w;
  2146.     char *str;
  2147.  
  2148.     if( WIN_MESSAGE == WIN_ERR ||
  2149.         ( cw = wins[ WIN_MESSAGE ] ) == NULL || ( w = cw->win ) == NULL )
  2150.     {
  2151.     panic(winpanicstr,WIN_MESSAGE, "doprev_message");
  2152.     }
  2153.  
  2154.     if( --cw->maxcol < 0 )
  2155.     {
  2156.     cw->maxcol = 0;
  2157.     DisplayBeep( NULL );
  2158.     str = "No more history saved...";
  2159.     }
  2160.     else
  2161.     str = cw->data[ cw->maxcol ];
  2162.  
  2163.     amii_cl_end(cw, 0);
  2164.     amii_curs( WIN_MESSAGE, 1, 0 );
  2165.     Text(w->RPort,str,strlen(str));
  2166.     cw->curx = cw->cols + 1;
  2167.  
  2168.     return( 0 );
  2169. }
  2170.  
  2171. void
  2172. amii_display_nhwindow(win,blocking)
  2173.     winid win;
  2174.     boolean blocking;
  2175. {
  2176.     int i;
  2177.     static int lastwin = -1;
  2178.     struct Window *w;
  2179.     struct WinDesc *cw;
  2180.  
  2181.     if( !Initialized )
  2182.     return;
  2183.     lastwin = win;
  2184.  
  2185.     if( win == WIN_ERR || ( cw = wins[win] ) == NULL )
  2186.     panic(winpanicstr,win,"display_nhwindow");
  2187.  
  2188.     if( cw->type == NHW_MAP || cw->type == NHW_STATUS ||
  2189.                         cw->type == NHW_MESSAGE )
  2190.     {
  2191.     return;
  2192.     }
  2193.  
  2194.     if(cw->type==NHW_MESSAGE)
  2195.     flags.window_inited=TRUE;
  2196.  
  2197.     /* should be:
  2198.     if type != map, WindowToFront
  2199.     if type == map && autoshow, unblock area around cursor
  2200.         (or something like that)
  2201.      */
  2202.  
  2203.     w = cw->win;
  2204.     if( w )
  2205.     {
  2206.     WindowToFront( w );
  2207.     ActivateWindow( w );
  2208.     }
  2209.  
  2210.     if( blocking && WIN_MAP != WIN_ERR && wins[ WIN_MAP ] )
  2211.     {
  2212.     flush_glyph_buffer( wins[ WIN_MAP ]->win );
  2213.     }
  2214.  
  2215.     if( cw->type == NHW_MENU || cw->type == NHW_TEXT )
  2216.     {
  2217.     DoMenuScroll( win, blocking );
  2218.     }
  2219.     else if( cw->type==NHW_MAP )
  2220.     {
  2221.     end_glyphout( win );
  2222.     for( i = 0; i < MAXWIN; ++i )
  2223.     {
  2224.         if( cw = wins[i] )
  2225.         {
  2226.         if( cw->type == NHW_STATUS || cw->type == NHW_MESSAGE )
  2227.         {
  2228.             if( cw->win )
  2229.             {
  2230.             WindowToFront(cw->win);
  2231.             }
  2232.         }
  2233.         }
  2234.     }
  2235.  
  2236.     /* Do more if it is time... */
  2237.     if( blocking == TRUE )
  2238.         outmore( wins[ win ] );
  2239.     }
  2240. }
  2241.  
  2242. void
  2243. amii_display_file(fn, complain)
  2244. const char *fn;
  2245. boolean complain;
  2246. {
  2247.     register struct WinDesc *cw;
  2248.     register int win;
  2249.     register FILE *fp;
  2250.     register char *t;
  2251.     register char buf[ 200 ];
  2252.  
  2253.     if( fn == NULL )
  2254.     panic("NULL file name in display_file()");
  2255.  
  2256.     if( ( fp = fopen( fn, "r" ) ) == NULL )
  2257.     {
  2258.     if (complain) {
  2259.         sprintf( buf, "Can't display %s: %s", fn,
  2260. #ifdef  __SASC_60
  2261.             __sys_errlist[ errno ]
  2262. #else
  2263.             sys_errlist[ errno ]
  2264. #endif
  2265.             );
  2266.         amii_addtopl( buf );
  2267.     }
  2268.     return;
  2269.     }
  2270.     win = amii_create_nhwindow( NHW_TEXT );
  2271.  
  2272.     /* Set window title to file name */
  2273.     if( cw = wins[ win ] )
  2274.     cw->morestr = fn;
  2275.  
  2276.     while( fgets( buf, sizeof( buf ), fp ) != NULL )
  2277.     {
  2278.     if( t = index( buf, '\n' ) )
  2279.         *t = 0;
  2280.     amii_putstr( win, 0, buf );
  2281.     }
  2282.     fclose( fp );
  2283.  
  2284.     /* If there were lines in the file, display those lines */
  2285.  
  2286.     if( wins[ win ]->cury > 0 )
  2287.     amii_display_nhwindow( win, TRUE );
  2288.  
  2289.     amii_destroy_nhwindow( win );
  2290. }
  2291.  
  2292. void
  2293. amii_curs(window, x, y)
  2294. winid window;
  2295. register int x, y;  /* not xchar: perhaps xchar is unsigned and
  2296.            curx-x would be unsigned as well */
  2297. {
  2298.     register struct WinDesc *cw;
  2299.     register struct Window *w;
  2300.     register struct RastPort *rp;
  2301.  
  2302.     if( window == WIN_ERR || ( cw = wins[window] ) == NULL )
  2303.     panic(winpanicstr,  window, "curs");
  2304.     if( (w = cw->win) == NULL )
  2305.     {
  2306.     if( cw->type == NHW_MENU || cw->type == NHW_TEXT )
  2307.         return;
  2308.     else
  2309.         panic( "No window open yet in curs() for winid %d\n", window );
  2310.     }
  2311.     amiIDisplay->lastwin = window;
  2312.  
  2313.     /* Make sure x is within bounds */
  2314.     if( x > 0 )
  2315.     --x;    /* column 0 is never used */
  2316.     else
  2317.     x = 0;
  2318.  
  2319.     cw->curx = x;
  2320.     cw->cury = y;
  2321. #ifdef DEBUG
  2322.     if(x<0 || y<0 || y >= cw->rows || x >= cw->cols)
  2323.     {
  2324.     char *s = "[unknown type]";
  2325.     switch(cw->type)
  2326.     {
  2327.         case NHW_MESSAGE: s = "[topl window]"; break;
  2328.         case NHW_STATUS: s = "[status window]"; break;
  2329.         case NHW_MAP: s = "[map window]"; break;
  2330.         case NHW_MENU: s = "[menu window]"; break;
  2331.         case NHW_TEXT: s = "[text window]"; break;
  2332.     }
  2333.     impossible("bad curs positioning win %d %s (%d,%d)", window, s, x, y);
  2334.     return;
  2335.     }
  2336. #endif
  2337.     x += cw->offx;
  2338.     y += cw->offy;
  2339.  
  2340. #ifdef CLIPPING
  2341.     if(clipping && window == WIN_MAP)
  2342.     {
  2343.     x -= clipx;
  2344.     y -= clipy;
  2345.     }
  2346. #endif
  2347.  
  2348.     /* Output all saved output before doing cursor movements for MAP */
  2349.  
  2350.     if( cw->type == NHW_MAP )
  2351.     flush_glyph_buffer( w );
  2352.  
  2353.     /* Actually do it */
  2354.  
  2355.     rp = w->RPort;
  2356.     if( cw->type == NHW_MENU || cw->type == NHW_TEXT )
  2357.     {
  2358.     Move( rp, (x * txwidth) + w->BorderLeft + 3,
  2359.         (y*(txheight+1) ) + w->RPort->TxBaseline + w->BorderTop + 1 );
  2360.     }
  2361.     else if( cw->type == NHW_MAP || cw->type == NHW_BASE )
  2362.     {
  2363.     /* These coordinate calculations must be synced with those
  2364.      * in flush_glyph_buffer() in amiwind.c.  curs_on_u() will
  2365.      * use this code, all other drawing occurs through the glyph
  2366.      * code.  In order for the cursor to appear on top of the hero,
  2367.      * the code must compute X,Y in the same manner relative to
  2368.      * the RastPort coordinates.
  2369.      */
  2370.     Move( rp, (x * txwidth) + w->BorderLeft,
  2371.             w->BorderTop + ( (y + 1) * txheight ) + txbaseline + 1 );
  2372.     }
  2373.     else if( cw->type == NHW_MESSAGE )
  2374.     {
  2375.     Move( rp, (x * txwidth) + w->BorderLeft + 2,
  2376.                         w->BorderTop + txbaseline + 3 );
  2377.     }
  2378.     else
  2379.     {
  2380.     Move( rp, (x * txwidth) + w->BorderLeft + 2,
  2381.                 (y*txheight) + w->BorderTop + txbaseline + 2 );
  2382.     }
  2383. }
  2384.  
  2385. /*
  2386.  *  print_glyph
  2387.  *
  2388.  *  Print the glyph to the output device.  Don't flush the output device.
  2389.  *
  2390.  *  Since this is only called from show_glyph(), it is assumed that the
  2391.  *  position and glyph are always correct (checked there)!
  2392.  */
  2393.  
  2394. void
  2395. amii_print_glyph(win,x,y,glyph)
  2396.     winid win;
  2397.     xchar x,y;
  2398.     int glyph;
  2399. {
  2400.     struct WinDesc *cw;
  2401.     uchar   ch;
  2402.     register int offset;
  2403. #ifdef TEXTCOLOR
  2404.     int     color;
  2405.     extern int zapcolors[];
  2406.  
  2407.     if( win == WIN_ERR || (cw=wins[win]) == NULL || cw->type != NHW_MAP)
  2408.     panic(winpanicstr,win,"print_glyph");
  2409.  
  2410. #define zap_color(n)  color = flags.use_color ? zapcolors[n] : NO_COLOR
  2411. #define cmap_color(n) color = flags.use_color ? defsyms[n].color : NO_COLOR
  2412. #define trap_color(n) color = flags.use_color ? \
  2413.         (((n) == WEB) ? defsyms[S_web ].color  : \
  2414.                 defsyms[S_trap].color) : \
  2415.             NO_COLOR
  2416. #define obj_color(n)  color = flags.use_color ? objects[n].oc_color : NO_COLOR
  2417. #define mon_color(n)  color = flags.use_color ? mons[n].mcolor : NO_COLOR
  2418. #define pet_color(n)  color = flags.use_color ? mons[n].mcolor :          \
  2419.         /* If no color, try to hilite pets; black  */ \
  2420.         /* should be HI                */ \
  2421.             ((flags.hilite_pet) ? BLACK : NO_COLOR)
  2422.  
  2423. # else /* no text color */
  2424.  
  2425. #define zap_color(n)
  2426. #define cmap_color(n)
  2427. #define trap_color(n)
  2428. #define obj_color(n)
  2429. #define mon_color(n)
  2430. #define pet_color(n)
  2431.  
  2432. #endif
  2433.  
  2434.     /*
  2435.      *  Map the glyph back to a character.
  2436.      *
  2437.      *  Warning:  For speed, this makes an assumption on the order of
  2438.      *        offsets.  The order is set in display.h.
  2439.      */
  2440.     if ((offset = (glyph - GLYPH_SWALLOW_OFF)) >= 0) {  /* swallow */
  2441.     /* see swallow_to_glyph()in display.c */
  2442.     ch = (uchar) showsyms[S_sw_tl + (offset & 0x7)];
  2443.     mon_color(offset >> 3);
  2444.     } else if ((offset = (glyph - GLYPH_ZAP_OFF)) >= 0) {       /* zap beam */
  2445.     ch = showsyms[S_vbeam + (offset & 0x3)];
  2446.     zap_color((offset >> 2));
  2447.     } else if( ( offset = (glyph - GLYPH_CMAP_OFF) ) >= 0 ) {   /* cmap */
  2448.     ch = showsyms[offset];
  2449.     cmap_color(offset);
  2450.     } else if ( ( offset = (glyph - GLYPH_TRAP_OFF) ) >= 0 ) {  /* trap */
  2451.     ch = (offset == WEB) ? showsyms[S_web] : showsyms[S_trap];
  2452.     trap_color(offset);
  2453.     } else if( ( offset = (glyph - GLYPH_OBJ_OFF) ) >= 0 ) {    /* object */
  2454.     ch = oc_syms[objects[offset].oc_class];
  2455.     obj_color(offset);
  2456.     } else if ((offset = (glyph - GLYPH_BODY_OFF)) >= 0) {  /* a corpse */
  2457.     ch = oc_syms[objects[CORPSE].oc_class];
  2458.     mon_color(offset);
  2459.     } else if ((offset = (glyph - GLYPH_PET_OFF)) >= 0) {   /* a pet */
  2460.     ch = (uchar) monsyms[mons[offset].mlet];
  2461.     pet_color(offset);
  2462.     } else /*if( glyph_is_monster(glyph) )*/ {      /* a monster */
  2463.     ch = (uchar) monsyms[mons[glyph].mlet];
  2464.     mon_color(glyph);
  2465.     }
  2466.  
  2467.     /* Move the cursor. */
  2468. #ifdef CLIPPING
  2469.     if (!win_curs(x, y)) return;
  2470. #else
  2471.     amii_curs(win,x,y+2);
  2472. #endif
  2473.  
  2474. #ifdef TEXTCOLOR
  2475.     /* Turn off color if rogue level. */
  2476. # ifdef REINCARNATION
  2477.     if (Is_rogue_level(&u.uz))
  2478.     color = NO_COLOR;
  2479. #  endif
  2480.  
  2481.     amiga_print_glyph(win,color,ch);
  2482. #else
  2483.     g_putch(ch);    /* print the character */
  2484. #endif
  2485.     cw->curx++;     /* one character over */
  2486. }
  2487.  
  2488. void
  2489. DoMenuScroll( win, blocking )
  2490.     int win, blocking;
  2491. {
  2492.     register struct Window *w;
  2493.     register struct NewWindow *nw;
  2494.     struct PropInfo *pip;
  2495.     register struct WinDesc *cw;
  2496.     struct IntuiMessage *imsg;
  2497.     struct Gadget *gd;
  2498.     register int wheight, xsize, ysize, aredone = 0;
  2499.     register int txwd, txh;
  2500.     long mics, secs, class, code;
  2501.     long oldmics = 0, oldsecs = 0;
  2502.     int aidx, oidx, topidx, hidden;
  2503.     char *t;
  2504.     SHORT mx, my;
  2505.     char title[ 100 ];
  2506.     int dosize = 1;
  2507.     struct Screen *scrn = HackScreen;
  2508.  
  2509.     if( win == WIN_ERR || ( cw = wins[ win ] ) == NULL )
  2510.     panic(winpanicstr,win,"DoMenuScroll");
  2511.  
  2512.     /* Check to see if we should open the window, should usually need to */
  2513.  
  2514.     txwd = txwidth;
  2515.     txh = txheight + 1; /* +1 for interline space */
  2516.     w = cw->win;
  2517.     if( w == NULL )
  2518.     {
  2519.     /* Humm, there is only so much... */
  2520.     if( scrn )
  2521.          xsize = scrn->WBorLeft + scrn->WBorRight + MenuScroll.Width + 2;
  2522.     else
  2523.          xsize = 5 + 5 + MenuScroll.Width + 2;
  2524.     xsize += (txwd * cw->maxcol);
  2525.     if( xsize > amiIDisplay->xpix )
  2526.         xsize = amiIDisplay->xpix;
  2527.  
  2528.         /* If next row not off window, use it, else use the bottom */
  2529.  
  2530.     ysize = ( txh * cw->maxrow ) +          /* The text space */
  2531.       HackScreen->WBorTop + txheight + 1 +    /* Top border */
  2532.       HackScreen->WBorBottom + 1;     /* The bottom border */
  2533.     if( ysize > amiIDisplay->ypix )
  2534.         ysize = amiIDisplay->ypix;
  2535.  
  2536.     /* Adjust the size of the menu scroll gadget */
  2537.  
  2538.     nw = (void *)DupNewWindow( (void *)(&new_wins[ cw->type ].newwin) );
  2539.     cw->newwin = (void *)nw;
  2540.     if( nw == NULL )
  2541.         panic("No NewWindow Allocated" );
  2542.  
  2543.     nw->Screen = HackScreen;
  2544.  
  2545.     if( win == WIN_INVEN ){
  2546.         sprintf( title, "%s the %s's Inventory", plname, pl_character );
  2547.         nw->Title = title;
  2548.     }
  2549.     else if( cw->morestr )
  2550.         nw->Title = cw->morestr;
  2551.  
  2552.     /* Adjust the window coordinates and size now that we know
  2553.      * how many items are to be displayed.
  2554.      */
  2555.  
  2556.     nw->Width = xsize;
  2557.     nw->Height = ysize;
  2558.     nw->TopEdge = 0;
  2559.     if( cw->type == NHW_TEXT && ysize < amiIDisplay->ypix )
  2560.         nw->TopEdge += ( amiIDisplay->ypix - ysize ) / 2;
  2561.     nw->LeftEdge = amiIDisplay->xpix - xsize;
  2562.     if( cw->type == NHW_TEXT && xsize < amiIDisplay->xpix )
  2563.         nw->LeftEdge -= ( amiIDisplay->xpix - xsize ) / 2;
  2564.  
  2565.  
  2566.     /* Now, open the window */
  2567.     w = cw->win = OpenShWindow( (void *)nw );
  2568.  
  2569.     if( w == NULL )    panic("No Window Opened For Menu" );
  2570.     }
  2571.  
  2572.     /* Find the scroll gadget */
  2573.  
  2574.     for( gd = w->FirstGadget; gd && gd->GadgetID != 1; gd = gd->NextGadget )
  2575.     continue;
  2576.  
  2577.     if( !gd ) panic("Can't find scroll gadget" );
  2578.  
  2579.     wheight = ( w->Height - w->BorderTop - w->BorderBottom ) / txh;
  2580.     cw->cols = ( w->Width - w->BorderLeft - w->BorderRight
  2581.         /* + MenuScroll.Width*/ ) / txwd;
  2582.     morc = 0;
  2583.     oidx = -1;
  2584.     topidx = 0;
  2585.  
  2586.     /* Make the prop gadget the right size and place */
  2587.  
  2588.     DisplayData( win, topidx, -1 );
  2589.  
  2590.     SetPropInfo( w, gd, wheight, cw->maxrow, topidx );
  2591.     oldsecs = oldmics = 0;
  2592.  
  2593.     while( !aredone )
  2594.     {
  2595.     /* Process window messages */
  2596.  
  2597.     WaitPort( w->UserPort );
  2598.     while( imsg = (struct IntuiMessage * ) GetMsg( w->UserPort ) )
  2599.     {
  2600.         class = imsg->Class;
  2601.         code = imsg->Code;
  2602.         mics = imsg->Micros;
  2603.         secs = imsg->Seconds;
  2604.         gd = (struct Gadget *) imsg->IAddress;
  2605.         mx = imsg->MouseX;
  2606.         my = imsg->MouseY;
  2607.  
  2608.         /* Only do our window or VANILLAKEY from other windows */
  2609.  
  2610.         if( imsg->IDCMPWindow != w && class != VANILLAKEY &&
  2611.                             class != RAWKEY )
  2612.         {
  2613.         ReplyMsg( (struct Message *) imsg );
  2614.         continue;
  2615.         }
  2616.  
  2617.         /* Do DeadKeyConvert() stuff if RAWKEY... */
  2618.         if( class == RAWKEY )
  2619.         {
  2620.         class = VANILLAKEY;
  2621.         code = ConvertKey( imsg );
  2622.         }
  2623.         ReplyMsg( (struct Message *) imsg );
  2624.  
  2625.         switch( class )
  2626.         {
  2627.         case NEWSIZE:
  2628.             /* Ignore every other newsize, no action needed */
  2629.  
  2630.             if( !dosize )
  2631.             {
  2632.             dosize = 1;
  2633.             break;
  2634.             }
  2635.  
  2636.             /* Find the gadget */
  2637.  
  2638.             for( gd = w->FirstGadget; gd && gd->GadgetID != 1; )
  2639.             gd = gd->NextGadget;
  2640.  
  2641.             if( !gd )
  2642.             panic("Can't find scroll gadget" );
  2643.  
  2644.             wheight = ( w->Height - w->BorderTop -
  2645.                         w->BorderBottom - 1) / txh;
  2646.             cw->cols = ( w->Width -
  2647.                 w->BorderLeft - w->BorderRight ) / txwd;
  2648.             if( wheight < 2 )
  2649.             wheight = 2;
  2650.  
  2651.             /* Make the prop gadget the right size and place */
  2652.  
  2653.             DisplayData( win, topidx, oidx );
  2654.             SetPropInfo( w, gd, wheight, cw->maxrow, topidx );
  2655.  
  2656.             /* Force the window to a text line boundry <= to
  2657.              * what the user dragged it to.  This eliminates
  2658.              * having to clean things up on the bottom edge.
  2659.              */
  2660.  
  2661.             SizeWindow( w, 0, ( wheight * txh) +
  2662.                 w->BorderTop + w->BorderBottom + 1 - w->Height );
  2663.  
  2664.             /* Don't do next NEWSIZE, we caused it */
  2665.             dosize = 0;
  2666.             oldsecs = oldmics = 0;
  2667.             break;
  2668.  
  2669.         case VANILLAKEY:
  2670. #define CTRL(x)     ((x)-'@')
  2671.             if( code == CTRL('D') || code == CTRL('U') )
  2672.             {
  2673.             int endcnt, i;
  2674.  
  2675.             for( gd = w->FirstGadget; gd && gd->GadgetID != 1; )
  2676.                 gd = gd->NextGadget;
  2677.  
  2678.             if( !gd )
  2679.                 panic("Can't find scroll gadget" );
  2680.  
  2681.             endcnt = wheight / 2;
  2682.             if( endcnt == 0 )
  2683.                 endcnt = 1;
  2684.  
  2685.             for( i = 0; i < endcnt; ++i )
  2686.             {
  2687.                 if( code == CTRL('D') )
  2688.                 {
  2689.                 if( topidx + wheight < cw->maxrow )
  2690.                     ++topidx;
  2691.                 else
  2692.                     break;
  2693.                 }
  2694.                 else
  2695.                 {
  2696.                 if( topidx > 0 )
  2697.                     --topidx;
  2698.                 else
  2699.                     break;
  2700.                 }
  2701.  
  2702.                 /* Make prop gadget the right size and place */
  2703.  
  2704.                 DisplayData( win, topidx, oidx );
  2705.                 SetPropInfo( w,gd, wheight, cw->maxrow, topidx );
  2706.             }
  2707.             oldsecs = oldmics = 0;
  2708.             }
  2709.             else if( code == '\b' )
  2710.             {
  2711.             for( gd = w->FirstGadget; gd && gd->GadgetID != 1; )
  2712.                 gd = gd->NextGadget;
  2713.  
  2714.             if( !gd )
  2715.                 panic("Can't find scroll gadget" );
  2716.  
  2717.             if( topidx - wheight - 2 < 0 )
  2718.             {
  2719.                 topidx = 0;
  2720.             }
  2721.             else
  2722.             {
  2723.                 topidx -= wheight - 2;
  2724.             }
  2725.             DisplayData( win, topidx, oidx );
  2726.             SetPropInfo( w, gd, wheight, cw->maxrow, topidx );
  2727.             oldsecs = oldmics = 0;
  2728.             }
  2729.             else if( code == ' ' )
  2730.             {
  2731.             for( gd = w->FirstGadget; gd && gd->GadgetID != 1; )
  2732.                 gd = gd->NextGadget;
  2733.  
  2734.             if( !gd )
  2735.                 panic("Can't find scroll gadget" );
  2736.  
  2737.             if( topidx + wheight >= cw->maxrow )
  2738.             {
  2739.                 morc = 0;
  2740.                 aredone = 1;
  2741.             }
  2742.             else
  2743.             {
  2744.                 /*  If there are still lines to be seen */
  2745.  
  2746.                 if( cw->maxrow > topidx + wheight )
  2747.                 {
  2748.                 if( wheight > 2 )
  2749.                     topidx += wheight - 2;
  2750.                 else
  2751.                     ++topidx;
  2752.                 DisplayData( win, topidx, oidx );
  2753.                 SetPropInfo( w, gd, wheight,
  2754.                             cw->maxrow, topidx );
  2755.                 }
  2756.                 oldsecs = oldmics = 0;
  2757.             }
  2758.             }
  2759.             else if( code == '\n' || code == '\r' )
  2760.             {
  2761.             for( gd = w->FirstGadget; gd && gd->GadgetID != 1; )
  2762.                 gd = gd->NextGadget;
  2763.  
  2764.             if( !gd )
  2765.                 panic("Can't find scroll gadget" );
  2766.  
  2767.             /* If all line displayed, we are done */
  2768.  
  2769.             if( topidx + wheight >= cw->maxrow )
  2770.             {
  2771.                 morc = 0;
  2772.                 aredone = 1;
  2773.             }
  2774.             else
  2775.             {
  2776.                 /*  If there are still lines to be seen */
  2777.  
  2778.                 if( cw->maxrow > topidx + 1 )
  2779.                 {
  2780.                 ++topidx;
  2781.                 DisplayData( win, topidx, oidx );
  2782.                 SetPropInfo( w, gd, wheight,
  2783.                             cw->maxrow, topidx );
  2784.                 }
  2785.                 oldsecs = oldmics = 0;
  2786.             }
  2787.             }
  2788.             else if( cw->resp && index( cw->resp, code ) )
  2789.             {
  2790.             morc = code;
  2791.             aredone = 1;
  2792.             }
  2793.             else if( code == '\33' || code == 'q' || code == 'Q' )
  2794.             {
  2795.             morc = '\33';
  2796.             aredone = 1;
  2797.             }
  2798.             break;
  2799.  
  2800.         case CLOSEWINDOW:
  2801.             aredone = 1;
  2802.             morc = '\33';
  2803.             break;
  2804.  
  2805.         case GADGETUP:
  2806.             break;
  2807.  
  2808.         case MOUSEMOVE:
  2809.             for( gd = w->FirstGadget; gd && gd->GadgetID != 1; )
  2810.             gd = gd->NextGadget;
  2811.  
  2812.             pip = (struct PropInfo *)gd->SpecialInfo;
  2813.             hidden = max( cw->maxrow - wheight, 0 );
  2814.             aidx = (((ULONG)hidden * pip->VertPot) + (MAXPOT/2)) >> 16;
  2815.             if( aidx != topidx )
  2816.             DisplayData( win, topidx = aidx, oidx );
  2817.             break;
  2818.  
  2819.         case MOUSEBUTTONS:
  2820.             if( ( code == SELECTUP || code == SELECTDOWN ) &&
  2821.                             cw->type == NHW_MENU )
  2822.             {
  2823.             /* Which one is the mouse pointing at? */
  2824.  
  2825.             aidx = (( (my - w->TopEdge) - w->BorderTop + 1 ) /
  2826.                             txh) + topidx;
  2827.  
  2828.             /* If different lines, don't select double click */
  2829.  
  2830.             if( aidx != oidx )
  2831.             {
  2832.                 oldsecs = 0;
  2833.                 oldmics = 0;
  2834.             }
  2835.  
  2836.             /* If releasing, check for double click */
  2837.  
  2838.             if( code == SELECTUP )
  2839.             {
  2840.                 if( aidx == oidx )
  2841.                 {
  2842.                 if( DoubleClick( oldsecs,
  2843.                             oldmics, secs, mics ) )
  2844.                 {
  2845.                     morc = cw->resp[ aidx ];
  2846.                     aredone = 1;
  2847.                 }
  2848.                 oldsecs = secs;
  2849.                 oldmics = mics;
  2850.                 }
  2851.             }
  2852.             else if( aidx < cw->maxrow && code == SELECTDOWN )
  2853.             {
  2854.                 /* Remove old highlighting if visible */
  2855.  
  2856.                 if( oidx > topidx && oidx - topidx < wheight )
  2857.                 {
  2858.                 t = cw->data[ oidx ] + SOFF;
  2859.                 amii_curs( win, 1, oidx - topidx );
  2860.                 SetDrMd( w->RPort, JAM2 );
  2861.                 SetAPen( w->RPort, C_WHITE );
  2862.                 SetBPen( w->RPort, C_BLACK );
  2863.                 Text( w->RPort, t, strlen( t ) );
  2864.                 oidx = -1;
  2865.                 }
  2866.  
  2867.                 t = cw->data[ aidx ];
  2868.                 if( t[ SEL_ITEM ] == 1 )
  2869.                 {
  2870.                 oidx = aidx;
  2871.  
  2872.                 amii_curs( win, 1, aidx - topidx );
  2873.                 SetDrMd( w->RPort, JAM2 );
  2874.                 SetAPen( w->RPort, C_BLUE );
  2875.                 SetBPen( w->RPort, C_WHITE );
  2876.                 t += SOFF;
  2877.                 Text( w->RPort, t, strlen( t ) );
  2878.                 }
  2879.                 else
  2880.                 {
  2881.                 DisplayBeep( NULL );
  2882.                 oldsecs = 0;
  2883.                 oldmics = 0;
  2884.                 }
  2885.             }
  2886.             }
  2887.             else
  2888.             {
  2889.             DisplayBeep( NULL );
  2890.             }
  2891.             break;
  2892.         }
  2893.     }
  2894.     }
  2895. }
  2896.  
  2897. void
  2898. DisplayData( win, start, where )
  2899.     int win;
  2900.     int start;
  2901.     int where;
  2902. {
  2903.     register struct WinDesc *cw;
  2904.     register struct Window *w;
  2905.     register int i, len, wheight;
  2906.     int col = -1;
  2907.  
  2908.     if( win == WIN_ERR || !(cw = wins[win]) || !( w = cw->win ) )
  2909.     {
  2910.     panic( winpanicstr, win, "No Window in DisplayData" );
  2911.     }
  2912.  
  2913.     SetDrMd( w->RPort, JAM2 );
  2914.     wheight = ( w->Height - w->BorderTop - w->BorderBottom ) / ( txheight + 1 );
  2915.  
  2916.     for( i = start; i < start + wheight; ++i )
  2917.     {
  2918.     amii_curs( win, 1, i - start );
  2919.  
  2920.     if( where == i )
  2921.     {
  2922.         if( col != 1 )
  2923.         {
  2924.         SetAPen( w->RPort, C_BLUE );
  2925.         SetBPen( w->RPort, C_WHITE );
  2926.         col = 1;
  2927.         }
  2928.     }
  2929.     else if( col != 2 )
  2930.     {
  2931.         SetAPen( w->RPort, C_WHITE );
  2932.         SetBPen( w->RPort, C_BLACK );
  2933.         col = 2;
  2934.     }
  2935.  
  2936.     /* Next line out, truncate if too long */
  2937.  
  2938.     len = 0;
  2939.     if( i < cw->maxrow )
  2940.     {
  2941.         register char *t;
  2942.  
  2943.         t = cw->data[ i ] + SOFF;
  2944.         len = strlen( t );
  2945.         if( len > cw->cols )
  2946.         len = cw->cols;
  2947.         Text( w->RPort, t, len );
  2948.     }
  2949.     amii_cl_end( cw, len );
  2950.     }
  2951.     return;
  2952. }
  2953.  
  2954. void SetPropInfo( win, gad, vis, total, top )
  2955.     register struct Window *win;
  2956.     register struct Gadget *gad;
  2957.     register long vis, total, top;
  2958. {
  2959.     register long hidden;
  2960.     register int body, pot;
  2961.  
  2962.     hidden = max( total-vis, 0 );
  2963.  
  2964.     /* Force the last section to be just to the bottom */
  2965.  
  2966.     if( top > hidden )
  2967.     top = hidden;
  2968.  
  2969.     /* Scale the body position. */
  2970.     /* 2 lines overlap */
  2971.  
  2972.     if( hidden > 0 && total != 0 )
  2973.     body = (ULONG) ((vis - 2) * MAXBODY) / (total - 2);
  2974.     else
  2975.     body = MAXBODY;
  2976.  
  2977.     if( hidden > 0 )
  2978.     pot = (ULONG) (top * MAXPOT) / hidden;
  2979.     else
  2980.     pot = 0;
  2981.  
  2982.     NewModifyProp( gad, win, NULL,
  2983.                 AUTOKNOB|FREEVERT, 0, pot, MAXBODY, body, 1 );
  2984. }
  2985.  
  2986. void
  2987. kill_nhwindows( all )
  2988.     register int all;
  2989. {
  2990.     register int i;
  2991.     register struct WinDesc *cw;
  2992.  
  2993.     /* Foreach open window in all of wins[], CloseShWindow, free memory */
  2994.  
  2995.     for( i = 0; i < MAXWIN; ++i )
  2996.     {
  2997.     if( (cw = wins[ i ]) && (cw->type != NHW_BASE || all) )
  2998.     {
  2999.         CloseShWindow( cw->win );
  3000.         free( cw );
  3001.         wins[ i ] = NULL;
  3002.     }
  3003.     }
  3004. }
  3005.  
  3006. void
  3007. amii_cl_end( cw, i )
  3008.     register struct WinDesc *cw;
  3009.     register int i;
  3010. {
  3011.     register struct Window *w = cw->win;
  3012.     register int oy, ox;
  3013.  
  3014.     if( !w )
  3015.     panic("NULL window pointer in amii_cl_end()");
  3016.  
  3017.     oy = w->RPort->cp_y;
  3018.     ox = w->RPort->cp_x;
  3019.  
  3020.     TextSpaces( w->RPort, cw->cols - i );
  3021.  
  3022.     Move( w->RPort, ox, oy );
  3023. }
  3024.  
  3025. void cursor_off( window )
  3026.     winid window;
  3027. {
  3028.     register struct WinDesc *cw;
  3029.     register struct Window *w;
  3030.     register struct RastPort *rp;
  3031.     int curx, cury;
  3032.     long dmode;
  3033.     short apen, bpen;
  3034.     unsigned char ch;
  3035.  
  3036.     if( window == WIN_ERR || ( cw = wins[window] ) == NULL )
  3037.     {
  3038.     /* tty does this differently - is this OK? */
  3039.     flags.window_inited=0;
  3040.     panic(winpanicstr,window, "cursor_off");
  3041.     }
  3042.  
  3043.     if( !(cw->flags & FLMAP_CURSUP ) )
  3044.     return;
  3045.     w = cw->win;
  3046.  
  3047.     if( !w )
  3048.     return;
  3049.  
  3050.     cw->flags &= ~FLMAP_CURSUP;
  3051.     rp = w->RPort;
  3052.  
  3053.     /* Save the current information */
  3054.     curx = rp->cp_x;
  3055.     cury = rp->cp_y;
  3056.     dmode = rp->DrawMode;
  3057.     apen = rp->FgPen;
  3058.     bpen = rp->BgPen;
  3059.     SetAPen( rp, cw->curs_apen );
  3060.     SetBPen( rp, cw->curs_bpen );
  3061.     SetDrMd( rp, COMPLEMENT );
  3062.  
  3063.     ch = CURSOR_CHAR;
  3064.     Move( rp, cw->cursx, cw->cursy );
  3065.     Text( rp, &ch, 1 );
  3066.  
  3067.     /* Put back the other stuff */
  3068.  
  3069.     Move( rp, curx, cury );
  3070.     SetDrMd( rp, dmode );
  3071.     SetAPen( rp, apen );
  3072.     SetBPen( rp, bpen );
  3073. }
  3074.  
  3075. void cursor_on( window )
  3076.     winid window;
  3077. {
  3078.     register struct WinDesc *cw;
  3079.     register struct Window *w;
  3080.     register struct RastPort *rp;
  3081.     unsigned char ch;
  3082.     long dmode;
  3083.     short apen, bpen;
  3084.  
  3085.     if( window == WIN_ERR || ( cw = wins[window] ) == NULL )
  3086.     {
  3087.     /* tty does this differently - is this OK? */
  3088.     flags.window_inited=0;
  3089.     panic(winpanicstr,window, "cursor_on");
  3090.     }
  3091.  
  3092.     if( (cw->flags & FLMAP_CURSUP ) )
  3093.     cursor_off( window );
  3094.  
  3095.     w = cw->win;
  3096.  
  3097.     if( !w )
  3098.     return;
  3099.  
  3100.     cw->flags |= FLMAP_CURSUP;
  3101.     rp = w->RPort;
  3102.  
  3103.     /* Save the current information */
  3104.  
  3105.     cw->cursx = rp->cp_x;
  3106.     cw->cursy = rp->cp_y;
  3107.     apen = rp->FgPen;
  3108.     bpen = rp->BgPen;
  3109.     dmode = rp->DrawMode;
  3110.     ch = CURSOR_CHAR;
  3111.  
  3112.     /* Draw in complement mode. The cursor body will be C_WHITE */
  3113.  
  3114.     cw->curs_apen = C_WHITE;
  3115.     cw->curs_bpen = C_WHITE;
  3116.     SetAPen( rp, cw->curs_apen );
  3117.     SetBPen( rp, cw->curs_bpen );
  3118.     SetDrMd( rp, COMPLEMENT );
  3119.     Move( rp, cw->cursx, cw->cursy );
  3120.     Text( rp, &ch, 1 );
  3121.     Move( rp, cw->cursx, cw->cursy );
  3122.  
  3123.     SetDrMd( rp, dmode );
  3124.     SetAPen( rp, apen );
  3125.     SetBPen( rp, bpen );
  3126. }
  3127.  
  3128. void
  3129. amii_getret()
  3130. {
  3131.     register int c;
  3132.  
  3133.     raw_print( "" );
  3134.     raw_print( "Press Return..." );
  3135.  
  3136.     c = 0;
  3137.  
  3138.     while( c != '\n' && c != '\r' )
  3139.     {
  3140.     if( HackPort )
  3141.         c = WindowGetchar();
  3142.     else
  3143.         c = getchar();
  3144.     }
  3145.     return;
  3146. }
  3147.  
  3148. UBYTE UNDOBUFFER[300];
  3149. SHORT BorderVectors1[] = { 0,0, 57,0, 57,11, 0,11, 0,0 };
  3150. struct Border Border1 = { -1,-1, 3,0,JAM1, 5, BorderVectors1, NULL };
  3151. struct IntuiText IText1 = { 3,0,JAM2, 4,1, NULL, (UBYTE *)"Cancel", NULL };
  3152. struct Gadget Gadget2 = {
  3153.     NULL, 9,15, 56,10, NULL, RELVERIFY, BOOLGADGET, (APTR)&Border1,
  3154.     NULL, &IText1, NULL, NULL, 1, NULL
  3155. };
  3156. UBYTE StrStringSIBuff[300];
  3157. struct StringInfo StrStringSInfo = {
  3158.     StrStringSIBuff, UNDOBUFFER, 0, 300, 0, 0,0,0,0,0, 0, 0, NULL
  3159. };
  3160. SHORT BorderVectors2[] = { 0,0, 439,0, 439,11, 0,11, 0,0 };
  3161. struct Border Border2 = { -1,-1, 3,0,JAM1, 5, BorderVectors2, NULL };
  3162. struct Gadget String = {
  3163.     &Gadget2, 77,15, 438,10, NULL, RELVERIFY+STRINGCENTER, STRGADGET,
  3164.     (APTR)&Border2, NULL, NULL, NULL, (APTR)&StrStringSInfo, 2, NULL
  3165. };
  3166.  
  3167. #define StrString \
  3168.    ((char *)(((struct StringInfo *)(String.SpecialInfo))->Buffer))
  3169.  
  3170. struct NewWindow StrWindow = {
  3171.     57,74, 526,31, 0,1, GADGETUP+CLOSEWINDOW+ACTIVEWINDOW+VANILLAKEY,
  3172.     WINDOWDRAG+WINDOWDEPTH+WINDOWCLOSE+ACTIVATE+NOCAREREFRESH,
  3173.     &String, NULL, NULL, NULL, NULL, 5,5, 0xffff,0xffff, CUSTOMSCREEN
  3174. };
  3175.  
  3176. /* Generate a requester for a string value. */
  3177.  
  3178. void amii_getlin(prompt,bufp)
  3179.     const char *prompt;
  3180.     char *bufp;
  3181. {
  3182.     getlind(prompt,bufp,0);
  3183. }
  3184.  
  3185. /* and with default */
  3186. void getlind(prompt,bufp, dflt)
  3187.     const char *prompt;
  3188.     char *bufp;
  3189.     const char *dflt;
  3190. {
  3191. #ifndef TOPL_GETLINE
  3192.     register struct Window *cwin;
  3193.     register struct IntuiMessage *imsg;
  3194.     register long class, code, qual;
  3195.     register int aredone = 0;
  3196.     register struct Gadget *gd;
  3197.     static int once;
  3198.  
  3199.     *StrString = 0;
  3200.     if( dflt )
  3201.     strcpy( StrString, dflt );
  3202.     StrWindow.Title = (UBYTE *)prompt;
  3203.     StrWindow.Screen = HackScreen;
  3204.  
  3205.     if( !once )
  3206.     {
  3207.     if( bigscreen )
  3208.         StrWindow.TopEdge = (HackScreen->Height/2) - (StrWindow.Height/2);
  3209.     SetBorder( &String );
  3210.     SetBorder( &Gadget2 );
  3211.     once = 1;
  3212.     }
  3213.  
  3214.     if( ( cwin = OpenWindow( (void *)&StrWindow ) ) == NULL )
  3215.     {
  3216.     return;
  3217.     }
  3218.  
  3219.     while( !aredone )
  3220.     {
  3221.     WaitPort( cwin->UserPort );
  3222.     while( ( imsg = (void *) GetMsg( cwin->UserPort ) ) != NULL )
  3223.     {
  3224.         class = imsg->Class;
  3225.         code = imsg->Code;
  3226.         qual = imsg->Qualifier;
  3227.         gd = (struct Gadget *) imsg->IAddress;
  3228.  
  3229.         switch( class )
  3230.         {
  3231.         case VANILLAKEY:
  3232.             if( code == '\033' && (qual &
  3233.                 (IEQUALIFIER_LALT|IEQUALIFIER_RALT|
  3234.                 IEQUALIFIER_LCOMMAND|IEQUALIFIER_RCOMMAND) ) == 0 )
  3235.             {
  3236.             if( bufp )
  3237.             {
  3238.                 bufp[0]='\033';
  3239.                 bufp[1]=0;
  3240.             }
  3241.             aredone = 1;
  3242.             }
  3243.             else
  3244.             {
  3245.             ActivateGadget( &String, cwin, NULL );
  3246.             }
  3247.             break;
  3248.  
  3249.         case ACTIVEWINDOW:
  3250.             ActivateGadget( &String, cwin, NULL );
  3251.             break;
  3252.  
  3253.         case GADGETUP:
  3254.             switch( gd->GadgetID )
  3255.             {
  3256.             case 2:
  3257.                 aredone = 1;
  3258.                 if( bufp )
  3259.                 strcpy( bufp, StrString );
  3260.                 break;
  3261.  
  3262.             case 1:
  3263.                 if( bufp )
  3264.                 {
  3265.                 bufp[0]='\033';
  3266.                 bufp[1]=0;
  3267.                 }
  3268.                 aredone = 1;
  3269.                 break;
  3270.             }
  3271.             break;
  3272.  
  3273.         case CLOSEWINDOW:
  3274.             if( bufp )
  3275.             strcpy( bufp, StrString );
  3276.             aredone = 1;
  3277.             break;
  3278.         }
  3279.         ReplyMsg( (struct Message *) imsg );
  3280.     }
  3281.     }
  3282.  
  3283.     CloseWindow( cwin );
  3284. #else
  3285.     struct WinDesc *cw;
  3286.     struct Window *w;
  3287.     int colx, ocolx, c;
  3288.     char *obufp;
  3289.  
  3290.     amii_clear_nhwindow( WIN_MESSAGE );
  3291.     amii_putstr( WIN_MESSAGE, 0, prompt );
  3292.     cw = wins[ WIN_MESSAGE ];
  3293.     w = cw->win;
  3294.     ocolx = colx = strlen( prompt ) + 1;
  3295.  
  3296.     obufp = bufp;
  3297.     while((c = WindowGetchar()) != EOF)
  3298.     {
  3299.     amii_curs( WIN_MESSAGE, colx, 0 );
  3300.     if(c == '\033')
  3301.     {
  3302.         *obufp = c;
  3303.         obufp[1] = 0;
  3304.         return;
  3305.     }
  3306.     else if(c == '\b')
  3307.     {
  3308.         if(bufp != obufp)
  3309.         {
  3310.         bufp--;
  3311.         amii_curs( WIN_MESSAGE, --colx, 0);
  3312.         Text( w->RPort, "\177 ", 2 );
  3313.         amii_curs( WIN_MESSAGE, colx, 0);
  3314.         }
  3315.         else
  3316.         DisplayBeep( NULL );
  3317.     }
  3318.     else if( c == '\n' || c == '\r' )
  3319.     {
  3320.         *bufp = 0;
  3321.         return;
  3322.     }
  3323.     else if(' ' <= c && c < '\177')
  3324.     {
  3325.         /* avoid isprint() - some people don't have it
  3326.            ' ' is not always a printing char */
  3327.         *bufp = c;
  3328.         bufp[1] = 0;
  3329.  
  3330.         Text( w->RPort, bufp, 1 );
  3331.         Text( w->RPort, "\177", 1 );
  3332.         if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO)
  3333.         {
  3334.         colx++;
  3335.         bufp++;
  3336.         }
  3337.     }
  3338.     else if(c == ('X'-64) || c == '\177')
  3339.     {
  3340.         amii_curs( WIN_MESSAGE, ocolx, 0 );
  3341.         Text( w->RPort,
  3342.         "                                                            ",
  3343.         colx - ocolx );
  3344.         amii_curs( WIN_MESSAGE, colx = ocolx, 0 );
  3345.     } else
  3346.         DisplayBeep( NULL );
  3347.     }
  3348.     *bufp = 0;
  3349. #endif
  3350. }
  3351.  
  3352. void amii_suspend_nhwindows( str )
  3353.     char *str;
  3354. {
  3355.     if( HackScreen )
  3356.     ScreenToBack( HackScreen );
  3357. }
  3358.  
  3359. void amii_resume_nhwindows()
  3360. {
  3361.     if( HackScreen )
  3362.     ScreenToFront( HackScreen );
  3363. }
  3364.  
  3365. void amii_bell()
  3366. {
  3367.     DisplayBeep( NULL );
  3368. }
  3369.  
  3370. #define GADBLUEPEN      2
  3371. #define GADREDPEN       3
  3372. #define GADGREENPEN     4
  3373. #define GADCOLOKAY      5
  3374. #define GADCOLCANCEL    6
  3375.  
  3376. #include "colorwin.c"
  3377.  
  3378. void
  3379. EditColor()
  3380. {
  3381.     int i, done = 0, okay = 0;
  3382.     long code, qual, class;
  3383.     register struct Gadget *gd, *dgad;
  3384.     register struct Window *nw;
  3385.     register struct IntuiMessage *imsg;
  3386.     register struct PropInfo *pip;
  3387.     register struct Screen *scrn;
  3388.     long aidx;
  3389.     int msx, msy;
  3390.     int curcol = 0, drag = 0;
  3391.     int bxorx, bxory, bxxlen, bxylen;
  3392.     UWORD colors[ 1L << DEPTH ];
  3393.     static int once = 0;
  3394.  
  3395.     bxylen = Col_NewWindowStructure1.Height -
  3396.                 ( Col_BluePen.TopEdge + Col_BluePen.Height + 6 );
  3397.     bxxlen = Col_BluePen.Width;
  3398.     bxorx = Col_BluePen.LeftEdge;
  3399.     bxory = Col_BluePen.TopEdge + Col_BluePen.Height + 2;
  3400.     scrn = HackScreen;
  3401.  
  3402.     if( !once )
  3403.     {
  3404.     SetBorder( &Col_Okay );
  3405.     SetBorder( &Col_Cancel );
  3406.     once = 1;
  3407.     }
  3408.  
  3409.     for( i = 0; i < (1L << DEPTH); ++i )
  3410.     {
  3411.     colors[ i ] = GetRGB4( scrn->ViewPort.ColorMap, i );
  3412.     }
  3413.  
  3414.     Col_NewWindowStructure1.Screen = scrn;
  3415. #ifdef  INTUI_NEW_LOOK
  3416.     if( IntuitionBase->LibNode.lib_Version >= 37 )
  3417.     {
  3418.     ((struct PropInfo *)Col_BluePen.SpecialInfo)->Flags |= PROPNEWLOOK;
  3419.     ((struct PropInfo *)Col_RedPen.SpecialInfo)->Flags |=  PROPNEWLOOK;
  3420.     ((struct PropInfo *)Col_GreenPen.SpecialInfo)->Flags |= PROPNEWLOOK;
  3421.     }
  3422. #endif
  3423.     nw = OpenWindow( (void *)&Col_NewWindowStructure1 );
  3424.  
  3425.     DrawCol( nw, curcol, colors );
  3426.     while( !done )
  3427.     {
  3428.     WaitPort( nw->UserPort );
  3429.  
  3430.     while( imsg = (struct IntuiMessage * )GetMsg( nw->UserPort ) )
  3431.     {
  3432.         gd = (struct Gadget *)imsg->IAddress;
  3433.         code = imsg->Code;
  3434.         class = imsg->Class;
  3435.         qual = imsg->Qualifier;
  3436.         msx = imsg->MouseX;
  3437.         msy = imsg->MouseY;
  3438.  
  3439.         ReplyMsg( (struct Message *)imsg );
  3440.  
  3441.         switch( class )
  3442.         {
  3443.         case VANILLAKEY:
  3444.             if( code == 'v' && qual == AMIGALEFT )
  3445.             okay = done = 1;
  3446.             else if( code == 'b' && qual == AMIGALEFT )
  3447.             okay = 0, done = 1;
  3448.             else if( code == 'o' || code == 'O' )
  3449.             okay = done = 1;
  3450.             else if( code == 'c' || code == 'C' )
  3451.             okay = 0, done = 1;
  3452.             break;
  3453.  
  3454.         case CLOSEWINDOW:
  3455.             done = 1;
  3456.             break;
  3457.  
  3458.         case GADGETUP:
  3459.             drag = 0;
  3460.             if( gd->GadgetID == GADREDPEN ||
  3461.                         gd->GadgetID == GADBLUEPEN ||
  3462.                         gd->GadgetID == GADGREENPEN )
  3463.             {
  3464.             pip = (struct PropInfo *)gd->SpecialInfo;
  3465.             aidx = pip->HorizPot / (MAXPOT/15);
  3466.             aidx = aidx;
  3467.             if( gd->GadgetID == GADREDPEN )
  3468.             {
  3469.                 colors[ curcol ] =
  3470.                 ( colors[ curcol ] & ~0xf00 ) | (aidx << 8);
  3471.                 LoadRGB4( &scrn->ViewPort, colors, 1l << DEPTH );
  3472.             }
  3473.             else if( gd->GadgetID == GADBLUEPEN )
  3474.             {
  3475.                 colors[ curcol ] =
  3476.                     ( colors[ curcol ] & ~0xf ) | aidx;
  3477.                 LoadRGB4( &scrn->ViewPort, colors, 1l << DEPTH );
  3478.             }
  3479.             else if( gd->GadgetID == GADGREENPEN )
  3480.             {
  3481.                 colors[ curcol ] =
  3482.                 ( colors[ curcol ] & ~0x0f0 ) | (aidx << 4);
  3483.                 LoadRGB4( &scrn->ViewPort, colors, 1l << DEPTH );
  3484.             }
  3485.             DispCol( nw, curcol, colors );
  3486.             }
  3487.             else if( gd->GadgetID == GADCOLOKAY )
  3488.             {
  3489.             done = 1;
  3490.             okay = 1;
  3491.             }
  3492.             else if( gd->GadgetID == GADCOLCANCEL )
  3493.             {
  3494.             done = 1;
  3495.             okay = 0;
  3496.             }
  3497.             break;
  3498.  
  3499.         case GADGETDOWN:
  3500.             drag = 1;
  3501.             dgad = gd;
  3502.             break;
  3503.  
  3504.         case MOUSEMOVE:
  3505.             if( !drag )
  3506.             break;
  3507.             pip = (struct PropInfo *)dgad->SpecialInfo;
  3508.             aidx = pip->HorizPot / (MAXPOT/15);
  3509.             aidx = aidx;
  3510.             if( dgad->GadgetID == GADREDPEN )
  3511.             {
  3512.             colors[ curcol ] =
  3513.                 ( colors[ curcol ] & ~0xf00 ) | (aidx << 8);
  3514.             LoadRGB4( &scrn->ViewPort, colors, 1l << DEPTH );
  3515.             }
  3516.             else if( dgad->GadgetID == GADBLUEPEN )
  3517.             {
  3518.             colors[ curcol ] = ( colors[ curcol ] & ~0xf ) | aidx;
  3519.             LoadRGB4( &scrn->ViewPort, colors, 1l << DEPTH );
  3520.             }
  3521.             else if( dgad->GadgetID == GADGREENPEN )
  3522.             {
  3523.             colors[ curcol ] =
  3524.                 ( colors[ curcol ] & ~0x0f0 ) | (aidx << 4);
  3525.             LoadRGB4( &scrn->ViewPort, colors, 1l << DEPTH );
  3526.             }
  3527.             DispCol( nw, curcol, colors );
  3528.             break;
  3529.  
  3530.         case MOUSEBUTTONS:
  3531.             if( code == SELECTDOWN )
  3532.             {
  3533.             if( msy > bxory && msy < bxory + bxylen - 1 &&
  3534.                 msx > bxorx && msx < bxorx + bxxlen - 1 )
  3535.             {
  3536.                 curcol = ( msx - bxorx )/(bxxlen / (1l << DEPTH));
  3537.                 DrawCol( nw, curcol, colors );
  3538.             }
  3539.             }
  3540.             break;
  3541.         }
  3542.     }
  3543.     }
  3544.  
  3545.     if( okay )
  3546.     {
  3547.     for( i = 0; i < ( 1L << DEPTH ); ++i )
  3548.         amii_curmap[ i ] = colors[ i ];
  3549.     }
  3550.  
  3551.     LoadRGB4( &scrn->ViewPort, amii_curmap, 1L << DEPTH );
  3552.     CloseWindow( nw );
  3553. }
  3554.  
  3555. /* The colornames, and the default values for the pens */
  3556. static struct
  3557. {
  3558.     char *name, *defval;
  3559. } colnames[] =
  3560. {
  3561.     "Black","(aaa)",
  3562.     "White","(fff)",
  3563.     "Brown","(620)",
  3564.     "Cyan","(b08)",
  3565.     "Green","(181)",
  3566.     "Magenta","(c06)",
  3567.     "Blue","(23e)",
  3568.     "Red","(d00)",
  3569. };
  3570.  
  3571. void
  3572. DrawCol( w, idx, colors )
  3573.     struct Window *w;
  3574.     int idx;
  3575.     UWORD *colors;
  3576. {
  3577.     int bxorx, bxory, bxxlen, bxylen;
  3578.     int i, incx, incy, r, g, b;
  3579.     long flags;
  3580.  
  3581.     bxylen = Col_NewWindowStructure1.Height - Col_Okay.Height - 4 -
  3582.             ( Col_BluePen.TopEdge + Col_BluePen.Height + 6 );
  3583.     bxxlen = Col_BluePen.Width;
  3584.     bxorx = Col_BluePen.LeftEdge;
  3585.     bxory = Col_BluePen.TopEdge + Col_BluePen.Height + 2;
  3586.  
  3587.     incx = bxxlen / (1L << DEPTH);
  3588.     incy = bxylen - 2;
  3589.  
  3590.     SetAPen( w->RPort, 1 );
  3591.     SetBPen( w->RPort, 0 );
  3592.     SetDrMd( w->RPort, JAM2 );
  3593.     RectFill( w->RPort, bxorx, bxory, bxorx + bxxlen - 1, bxory + bxylen );
  3594.     SetAPen( w->RPort, 0 );
  3595.     RectFill( w->RPort, bxorx+2, bxory+1,
  3596.                     bxorx + bxxlen - 4, bxory + bxylen - 1);
  3597.  
  3598.     for( i = 0; i < (1L << DEPTH); ++i )
  3599.     {
  3600.     if( i == idx )
  3601.         SetAPen( w->RPort, 1 );
  3602.     else
  3603.         SetAPen( w->RPort, 0 );
  3604.     SetBPen( w->RPort, 0 );
  3605.     SetDrMd( w->RPort, JAM2 );
  3606.     RectFill( w->RPort, bxorx + 3 + (i*incx)+1, bxory + 2,
  3607.                     bxorx + ((i+1)*incx)-2, bxory+bxylen - 2);
  3608.  
  3609.     SetAPen( w->RPort, 0 );
  3610.     SetBPen( w->RPort, 0 );
  3611.     SetDrMd( w->RPort, JAM2 );
  3612.     RectFill( w->RPort, bxorx + 3 + (i*incx)+2, bxory + 3,
  3613.                     bxorx + ((i+1)*incx)-4, bxory+bxylen - 3);
  3614.  
  3615.     SetAPen( w->RPort, i );
  3616.     SetBPen( w->RPort, 0 );
  3617.     SetDrMd( w->RPort, JAM2 );
  3618.     RectFill( w->RPort, bxorx + 3 +(i*incx)+4, bxory + 4,
  3619.                     bxorx + ((i+1)*incx)-6, bxory+bxylen - 4 );
  3620.     }
  3621.  
  3622.     DispCol( w, idx, colors );
  3623.  
  3624.     r = (colors[ idx ] & 0xf00) >> 8;
  3625.     g = (colors[ idx ] & 0x0f0) >> 4;
  3626.     b = colors[ idx ] & 0x00f;
  3627.  
  3628.     flags = AUTOKNOB|FREEHORIZ;
  3629. #ifdef  INTUI_NEW_LOOK
  3630.     if( IntuitionBase->LibNode.lib_Version >= 37 )
  3631.     {
  3632.     flags |= PROPNEWLOOK;
  3633.     }
  3634. #endif
  3635.     NewModifyProp( &Col_RedPen, w, NULL, flags, (r * MAXPOT ) / 15, 0,
  3636.                                 MAXPOT/15, 0, 1 );
  3637.     NewModifyProp( &Col_GreenPen, w, NULL, flags, (g * MAXPOT ) / 15, 0,
  3638.                                 MAXPOT/15, 0, 1 );
  3639.     NewModifyProp( &Col_BluePen, w, NULL, flags, (b * MAXPOT ) / 15, 0,
  3640.                                 MAXPOT/15, 0, 1 );
  3641. }
  3642.  
  3643. void
  3644. DispCol( w, idx, colors )
  3645.     struct Window *w;
  3646.     int idx;
  3647.     UWORD *colors;
  3648. {
  3649.     char buf[ 50 ];
  3650.  
  3651.     Move( w->RPort, Col_Okay.LeftEdge + Col_Okay.Width +
  3652.     txwidth, Col_Cancel.TopEdge + txbaseline + 2 );
  3653.     sprintf( buf, "%s=%03x %s%s", colnames[idx].name, colors[idx],
  3654.     colnames[idx].defval,
  3655.     "        "+strlen(colnames[idx].name)+1 );
  3656.     SetAPen( w->RPort, C_WHITE );
  3657.     SetBPen( w->RPort, 0 );
  3658.     SetDrMd( w->RPort, JAM2 );
  3659.     Text( w->RPort, buf, strlen( buf ) );
  3660. }
  3661.  
  3662. void
  3663. amii_setpens()
  3664. {
  3665.     /* If the pens are set in NetHack.cnf, we can get called before
  3666.      * HackScreen has been opened...
  3667.      */
  3668.     if( HackScreen != NULL )
  3669.     {
  3670.     LoadRGB4( &HackScreen->ViewPort, amii_curmap, 1L << DEPTH );
  3671.     }
  3672. }
  3673.  
  3674. /* Put a 3-D motif border around the gadget.  String gadgets or those
  3675.  * which do not have highlighting are rendered down.  Boolean gadgets
  3676.  * are rendered in the up position by default.
  3677.  */
  3678.  
  3679. void
  3680. SetBorder( gd )
  3681.     register struct Gadget *gd;
  3682. {
  3683.     register struct Border *bp;
  3684.     register short *sp;
  3685.     register int i, inc = -1, dec = -1;
  3686.     int borders = 6;
  3687.  
  3688.     /* Allocate two border structures one for up image and one for down
  3689.      * image, plus vector arrays for the border lines.
  3690.      */
  3691.  
  3692.     if( gd->GadgetType == STRGADGET )
  3693.     borders = 12;
  3694.  
  3695.     if( ( bp = (struct Border *)alloc( ( ( sizeof( struct Border ) * 2 ) +
  3696.             ( sizeof( short ) * borders ) ) * 2 ) ) == NULL )
  3697.     {
  3698.     return;
  3699.     }
  3700.  
  3701.     /* For a string gadget, we expand the border beyond the area where
  3702.      * the text will be entered.
  3703.      */
  3704.  
  3705.     /* Remove any special rendering flags to avoid confusing intuition
  3706.      */
  3707.  
  3708.     gd->Flags &= ~(GADGHIGHBITS|GADGIMAGE);
  3709.  
  3710.     sp = (short *)(bp + 4);
  3711.     if( gd->GadgetType == STRGADGET || ( gd->GadgetType == BOOLGADGET &&
  3712.                 ( gd->Flags & GADGHIGHBITS ) == GADGHNONE ) )
  3713.     {
  3714.     sp[0] = -1;
  3715.     sp[1] = gd->Height - 1;
  3716.     sp[2] = -1;
  3717.     sp[3] = -1;
  3718.     sp[4] = gd->Width - 1;
  3719.     sp[5] = -1;
  3720.  
  3721.     sp[6] = gd->Width + 1;
  3722.     sp[7] = -2;
  3723.     sp[8] = gd->Width + 1;
  3724.     sp[9] = gd->Height + 1;
  3725.     sp[10] = -2;
  3726.     sp[11] = gd->Height + 1;
  3727.  
  3728.     sp[12] = -2;
  3729.     sp[13] = gd->Height;
  3730.     sp[14] = -2;
  3731.     sp[15] = -2;
  3732.     sp[16] = gd->Width;
  3733.     sp[17] = -2;
  3734.     sp[18] = gd->Width;
  3735.     sp[19] = gd->Height;
  3736.     sp[20] = -2;
  3737.     sp[21] = gd->Height;
  3738.  
  3739.     for( i = 0; i < 3; ++i )
  3740.     {
  3741.         bp[ i ].LeftEdge = bp[ i ].TopEdge = -1;
  3742.         bp[ i ].FrontPen = ( i == 0 || i == 1 ) ? C_BROWN : C_WHITE;
  3743.  
  3744.         /* Have to use JAM2 so that the old colors disappear. */
  3745.         bp[ i ].BackPen = C_BLACK;
  3746.         bp[ i ].DrawMode = JAM2;
  3747.         bp[ i ].Count = ( i == 0 || i == 1 ) ? 3 : 5;
  3748.         bp[ i ].XY = &sp[ i*6 ];
  3749.         bp[ i ].NextBorder = ( i == 2 ) ? NULL : &bp[ i + 1 ];
  3750.     }
  3751.  
  3752.     /* bp[0] and bp[1] two pieces for the up image */
  3753.     gd->GadgetRender = (APTR) bp;
  3754.  
  3755.     /* No image change for select */
  3756.     gd->SelectRender = (APTR) bp;
  3757.  
  3758.     gd->LeftEdge++;
  3759.     gd->TopEdge++;
  3760.     gd->Flags |= GADGHCOMP;
  3761.     }
  3762.     else
  3763.     {
  3764.     /* Create the border vector values for up and left side, and
  3765.      * also the lower and right side.
  3766.      */
  3767.  
  3768.     sp[0] = dec;
  3769.     sp[1] = gd->Height + inc;
  3770.     sp[2] = dec;
  3771.     sp[3] = dec;
  3772.     sp[4] = gd->Width + inc;
  3773.     sp[5] = dec;
  3774.  
  3775.     sp[6] = gd->Width + inc;
  3776.     sp[7] = dec;
  3777.     sp[8] = gd->Width + inc;
  3778.     sp[9] = gd->Height + inc;
  3779.     sp[10] = dec;
  3780.     sp[11] = gd->Height + inc;
  3781.  
  3782.     /* We are creating 4 sets of borders, the two sides of the
  3783.      * rectangle share the border vectors with the opposite image,
  3784.      * but specify different colors.
  3785.      */
  3786.  
  3787.     for( i = 0; i < 4; ++i )
  3788.     {
  3789.         bp[ i ].TopEdge = bp[ i ].LeftEdge = 0;
  3790.  
  3791.         /* A GADGHNONE is always down */
  3792.  
  3793.         if( gd->GadgetType == BOOLGADGET &&
  3794.                 ( gd->Flags & GADGHIGHBITS ) != GADGHNONE )
  3795.         {
  3796.         bp[ i ].FrontPen =
  3797.                 ( i == 1 || i == 2 ) ? C_BROWN : C_WHITE;
  3798.         }
  3799.         else
  3800.         {
  3801.         bp[ i ].FrontPen =
  3802.                 ( i == 1 || i == 3 ) ? C_WHITE : C_BROWN;
  3803.         }
  3804.  
  3805.         /* Have to use JAM2 so that the old colors disappear. */
  3806.         bp[ i ].BackPen = C_BLACK;
  3807.         bp[ i ].DrawMode = JAM2;
  3808.         bp[ i ].Count = 3;
  3809.         bp[ i ].XY = &sp[ 6 * ((i &1) != 0) ];
  3810.         bp[ i ].NextBorder =
  3811.                 ( i == 1 || i == 3 ) ? NULL : &bp[ i + 1 ];
  3812.     }
  3813.  
  3814.     /* bp[0] and bp[1] two pieces for the up image */
  3815.     gd->GadgetRender = (APTR) bp;
  3816.  
  3817.     /* bp[2] and bp[3] two pieces for the down image */
  3818.     gd->SelectRender = (APTR) (bp + 2);
  3819.     gd->Flags |= GADGHIMAGE;
  3820.     }
  3821. }
  3822.  
  3823. #ifdef  PORT_HELP
  3824. void
  3825. port_help()
  3826. {
  3827.     display_file( PORT_HELP, 1 );
  3828. }
  3829. #endif
  3830.  
  3831. #endif /* AMIGA_INTUITION */
  3832.