home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / nethack-3.1 / sys / mac / macwin.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-27  |  75.8 KB  |  3,375 lines

  1. /*    SCCS Id: @(#)macwin.c    3.1    93/01/24          */
  2. /* Copyright (c) Jon W{tte, Hao-Yang Wang, Jonathan Handler 1992. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /*
  6.  * macwin.c
  7.  */
  8.  
  9. /*
  10.  * I have to quote X11R5:
  11.  *
  12.  *  "If you think you know what this code is doing, you're probably wrong.
  13.  *   Here be serious and nasty dragons."
  14.  *
  15.  * h+ 92-09-26
  16.  */
  17.  
  18. #include "hack.h"
  19. #include "func_tab.h"
  20.  
  21. #include <osutils.h>
  22. #include <dialogs.h>
  23. #include <textedit.h>
  24. #include <menus.h>
  25. #ifndef MAC_THINKC5
  26. #include <sysequ.h>
  27. #endif
  28. #include <resources.h>
  29. #include <desk.h>
  30. #include <gestaltequ.h>
  31. #include <balloons.h>
  32. #include <toolutils.h>
  33. #include <script.h>
  34. #include <OSEvents.h>
  35. #include <Packages.h>
  36. #include <Sound.h>
  37. #include <DiskInit.h>
  38.  
  39. NhWindow * theWindows = (NhWindow *) NULL ;
  40.  
  41. /*
  42.  * Some useful #defines for the scroll bar width and height
  43.  */
  44. #define        SBARWIDTH    15
  45. #define        SBARHEIGHT    14
  46.  
  47. /*
  48.  * We put a TE on the message window for the "top line" queries.
  49.  * top_line is the TE that holds both the query and the user's
  50.  * response.  The first topl_query_len characters in top_line are
  51.  * the query, the rests are the response.  topl_resp is the valid
  52.  * response to a yn query, while topl_resp[topl_def_idx] is the
  53.  * default response to a yn query.
  54.  */
  55. TEHandle top_line = nil;
  56. int         topl_query_len;
  57. int         topl_def_idx = -1;
  58. char     topl_resp[10] = "";
  59.  
  60. #define CHAR_ANY '\n'
  61.  
  62. /*
  63.  * inSelect means we have a menu window up for selection or
  64.  * something similar. It makes the window with win number ==
  65.  * inSelect a movable modal (unfortunately without the border)
  66.  * and clicking the close box forces an ESC into the key
  67.  * buffer. Don't forget to set inSelect to WIN_ERR when you're
  68.  * done...
  69.  */
  70. winid inSelect = WIN_ERR ;
  71.  
  72. /*
  73.  * The key queue - contains 0 for unused or an ascii value.
  74.  * When getting keys, take the first value and shift the
  75.  * queue, shifting in a 0.
  76.  */
  77. #define QUEUE_LEN 24
  78. static int keyQueue [ QUEUE_LEN ] ;
  79.  
  80. Boolean gClickedToMove = 0 ; /* For ObscureCursor */
  81.  
  82.  
  83. /*
  84.  * Add key to input queue, force means replace last if full
  85.  */
  86. void
  87. addToKeyQueue ( int ch , Boolean force )
  88. {
  89.     int i ;
  90.  
  91.     for ( i = 0 ; i < QUEUE_LEN ; i ++ ) {
  92.  
  93.         if ( ! keyQueue [ i ] ) {
  94.  
  95.             keyQueue [ i ] = ch ;
  96.             return ;
  97.         }
  98.     }
  99.     if ( force ) {
  100.  
  101.         keyQueue [ QUEUE_LEN - 1 ] = ch ;
  102.     }
  103. }
  104.  
  105.  
  106. /*
  107.  * Cursor movement
  108.  */
  109. RgnHandle gMouseRgn = NULL ;
  110.  
  111. /*
  112.  * _Gestalt madness - we rely heavily on the _Gestalt glue, since we
  113.  * don't check for the trap...
  114.  */
  115. MacFlags macFlags ;
  116.  
  117. /*
  118.  * Async flag for keeping track of scrollbars...
  119.  * Used by InvalScrollBar ( )
  120.  */
  121. static NhWindow * asyDSC = (NhWindow *) NULL ;
  122.  
  123. /*
  124.  * The font to be used in the text window
  125.  */
  126. short text_wind_font = geneva;
  127.  
  128. /*
  129.  * Whether to adjust the height of a text window according to its contents
  130.  */
  131. boolean full_screen = FALSE;
  132.  
  133. char macPad = 1 ;
  134.  
  135. Handle mBar ;
  136. MenuHandle appleMenu ;
  137. MenuHandle fileMenu ;
  138. MenuHandle editMenu ;
  139. MenuHandle extendMenu ;
  140. MenuHandle miscMenu ;
  141. MenuHandle helpMenu ;
  142. MenuHandle commandsMenu ;
  143. MenuHandle thingsMenu ;
  144.  
  145. #define NHW_BASE 0
  146. winid BASE_WINDOW ; // Was: , WIN_MAP , WIN_MESSAGE , WIN_INVEN , WIN_STATUS ;
  147.  
  148. void NDECL(port_help);
  149.  
  150. int NDECL(SanePositions);
  151. Boolean FDECL(RetrieveWinPos, (WindowPtr,short *,short *));
  152. void NDECL ( InitMac ) ;
  153. void NDECL(InitRes);
  154. void FDECL(GeneralKey, ( EventRecord * theEvent , WindowPtr theWindow ));
  155. void FDECL(HandleKey, ( EventRecord * theEvent ));
  156. void FDECL(HandleClick, ( EventRecord * theEvent ));
  157. void FDECL(HandleUpdate, ( EventRecord * theEvent ));
  158. void FDECL(HandleEvent, ( EventRecord * theEvent ));
  159. void NDECL(DimMenuBar);
  160. void NDECL(UndimMenuBar);
  161. int FDECL(filter_scroll_key,(const int, NhWindow *));
  162.  
  163. void SetFrameItem ( DialogPtr , short , short ) ;
  164. void FlashButton ( DialogPtr , short ) ;
  165.  
  166. void trans_num_keys ( EventRecord * ) ;
  167.  
  168. #ifndef MAC_THINKC5
  169. /*
  170.  * Why aren't these declared when including hack.h - I thought
  171.  * they were...
  172.  */
  173. void FDECL(putsym, ( winid win , int x , int y , CHAR_P sym ));
  174. #endif
  175.  
  176. #define NUM_FUNCS 6
  177. static void FDECL(macKeyNull, ( EventRecord * , WindowPtr )) ;
  178. static void FDECL(macKeyMessage, ( EventRecord * , WindowPtr )) ;
  179. static void FDECL(macKeyStatus, ( EventRecord * , WindowPtr )) ;
  180. static void FDECL(macKeyMap, ( EventRecord * , WindowPtr )) ;
  181. static void FDECL(macKeyMenu, ( EventRecord * , WindowPtr )) ;
  182. static void FDECL(macKeyText, ( EventRecord * , WindowPtr )) ;
  183.  
  184. static void FDECL(macClickNull, ( EventRecord * , WindowPtr )) ;
  185. static void FDECL(macClickMessage, ( EventRecord * , WindowPtr )) ;
  186. static void FDECL(macClickStatus, ( EventRecord * , WindowPtr )) ;
  187. static void FDECL(macClickMap, ( EventRecord * , WindowPtr )) ;
  188. static void FDECL(macClickMenu, ( EventRecord * , WindowPtr )) ;
  189. static void FDECL(macClickText, ( EventRecord * , WindowPtr )) ;
  190.  
  191. static void FDECL(macUpdateNull, ( EventRecord * , WindowPtr )) ;
  192. static void FDECL(macUpdateMessage, ( EventRecord * , WindowPtr )) ;
  193. static void FDECL(macUpdateStatus, ( EventRecord * , WindowPtr )) ;
  194. static void FDECL(macUpdateMap, ( EventRecord * , WindowPtr )) ;
  195. static void FDECL(macUpdateMenu, ( EventRecord * , WindowPtr )) ;
  196. static void FDECL(macUpdateText, ( EventRecord * , WindowPtr )) ;
  197.  
  198. static void FDECL(macCursorNull, ( EventRecord * , WindowPtr , RgnHandle )) ;
  199. static void FDECL(macCursorMessage, ( EventRecord * , WindowPtr , RgnHandle )) ;
  200. static void FDECL(macCursorStatus, ( EventRecord * , WindowPtr , RgnHandle )) ;
  201. static void FDECL(macCursorMap, ( EventRecord * , WindowPtr , RgnHandle )) ;
  202. static void FDECL(macCursorMenu, ( EventRecord * , WindowPtr , RgnHandle )) ;
  203. static void FDECL(macCursorText, ( EventRecord * , WindowPtr , RgnHandle )) ;
  204.  
  205. static void NDECL(UpdateMenus);
  206. static void FDECL(DoMenu, (long choise));
  207.  
  208. static void FDECL (DrawScrollbar, ( NhWindow * , WindowPtr ));
  209. static void FDECL (InvalScrollBar, ( NhWindow * ));
  210. static void FDECL(DrawMapCursor,(NhWindow *));
  211. static void FDECL(DoScrollBar,(Point, short, ControlHandle, NhWindow *, WindowPtr));
  212. static pascal void FDECL(Up, (ControlHandle, short));
  213. static pascal void FDECL(Down,(ControlHandle, short));
  214.  
  215. typedef void ( * CbFunc ) ( EventRecord * , WindowPtr ) ;
  216. typedef void ( * CbCursFunc ) ( EventRecord * , WindowPtr , RgnHandle ) ;
  217.  
  218. CbFunc winKeyFuncs [ NUM_FUNCS ] = {
  219.     macKeyNull , macKeyMessage , macKeyStatus , macKeyMap , macKeyMenu , macKeyText
  220. } ;
  221.  
  222. CbFunc winClickFuncs [ NUM_FUNCS ] = {
  223.     macClickNull , macClickMessage , macClickStatus , macClickMap , macClickMenu ,
  224.     macClickText
  225. } ;
  226.  
  227. CbFunc winUpdateFuncs [ NUM_FUNCS ] = {
  228.     macUpdateNull , macUpdateMessage , macUpdateStatus , macUpdateMap ,
  229.     macUpdateMenu , macUpdateText
  230. } ;
  231.  
  232. CbCursFunc winCursorFuncs [ NUM_FUNCS ] = {
  233.     macCursorNull , macCursorMessage , macCursorStatus , macCursorMap ,
  234.     macCursorMenu , macCursorText
  235. } ;
  236.  
  237. #ifdef applec
  238.   extern void _DataInit();
  239.   /* This routine is part of the MPW runtime library. This external
  240.      reference to it is done so that we can unload its segment, %A5Init,
  241.      and recover c 250K of memory */
  242. #endif
  243.  
  244.  
  245. void
  246. InitMac( void )
  247. {
  248.     int i ;
  249.     long l ;
  250.  
  251. #ifdef applec
  252.     UnloadSeg((Ptr) _DataInit);
  253. #endif
  254.  
  255.     SetApplLimit ( 
  256.                     ( void * ) 
  257.                     ( 
  258.                     ( ( long ) GetApplLimit() ) - 40 * 1024L 
  259.                     ) 
  260.                  ) ;
  261.     MaxApplZone ( ) ;
  262.     for ( i = 0 ; i < 5 ; i ++ )
  263.         MoreMasters ( ) ;
  264.  
  265.     InitGraf ( & qd . thePort ) ;
  266.     InitFonts ( ) ;
  267.     InitWindows ( ) ;
  268.     InitMenus ( ) ;
  269.     InitDialogs ( ( ResumeProcPtr ) 0L ) ;
  270.     TEInit ( ) ;
  271.     InitSegMgmt( itworked );    /* itworked is always in the main segment */
  272.     
  273.     attemptingto("start up");
  274.     
  275.     if ( Gestalt ( gestaltOSAttr , & l ) ) {
  276.         macFlags . processes = 0 ;
  277.         macFlags . tempMem = 0 ;
  278.     } else {
  279.         macFlags . processes = ( l & ( 1 << gestaltLaunchControl ) ) ? 1 : 0 ;
  280.         macFlags . tempMem = ( l & ( 1 << gestaltRealTempMemory ) ) ? 1 : 0 ;
  281.     }
  282.     if ( Gestalt ( gestaltQuickdrawVersion , & l ) ) {
  283.         macFlags . color = 0 ;
  284.     } else {
  285.         macFlags . color = ( l >= gestalt8BitQD ) ? 1 : 0 ;
  286.     }
  287.     if ( Gestalt ( gestaltFindFolderAttr , & l ) ) {
  288.         macFlags . folders = 0 ;
  289.     } else {
  290.         macFlags . folders = ( l & ( 1 << gestaltFindFolderPresent ) ) ? 1 : 0 ;
  291.     }
  292.     if ( Gestalt ( gestaltHelpMgrAttr , & l ) ) {
  293.         macFlags . help = 0 ;
  294.     } else {
  295.         macFlags . help = ( l & ( 1 << gestaltHelpMgrPresent ) ) ? 1 : 0 ;
  296.     }
  297.     if ( Gestalt ( gestaltFSAttr , & l ) ) {
  298.         macFlags . fsSpec = 0 ;
  299.     } else {
  300.         macFlags . fsSpec = ( l & ( 1 << gestaltHasFSSpecCalls ) ) ? 1 : 0 ;
  301.     }
  302.     if ( Gestalt ( gestaltFontMgrAttr , & l ) ) {
  303.         macFlags . trueType = 0 ;
  304.     } else {
  305.         macFlags . trueType = ( l & ( 1 << gestaltOutlineFonts ) ) ? 1 : 0 ;
  306.     }
  307.     if ( Gestalt ( gestaltAUXVersion , & l ) ) {
  308.         macFlags . aux = 0 ;
  309.     } else {
  310.         macFlags . aux = ( l >= 0x200 ) ? 1 : 0 ;
  311.     }
  312.     if ( Gestalt ( gestaltAliasMgrAttr , & l ) ) {
  313.         macFlags . alias = 0 ;
  314.     } else {
  315.         macFlags . alias = ( l & ( 1 << gestaltAliasMgrPresent ) ) ? 1 : 0 ;
  316.     }
  317.     if ( Gestalt ( gestaltStandardFileAttr , & l ) ) {
  318.         macFlags . standardFile = 0 ;
  319.     } else {
  320.         macFlags . standardFile = ( l & ( 1 << gestaltStandardFile58 ) ) ? 1 : 0 ;
  321.     }
  322.  
  323.     gMouseRgn = NewRgn ( ) ;
  324. }
  325.  
  326.  
  327. #define MAX_HEIGHT 200
  328. #define MIN_HEIGHT 50
  329. #define MIN_WIDTH 300
  330.  
  331. /*
  332.  * This function could be overloaded with any amount of
  333.  * intelligence...
  334.  */
  335. int
  336. SanePositions ( void )
  337. {
  338.     short mainTop , mainLeft , mainWidth , mainHeight ;
  339.     short statTop , statLeft , statWidth , statHeight ;
  340.     short mesgTop , mesgLeft , mesgWidth , mesgHeight ;
  341.     short left , top , width , height ;
  342.     short ix , numText = 0 , numMenu = 0 ;
  343.     Rect screenArea ;
  344.     WindowPtr theWindow ;
  345.     NhWindow * nhWin ;
  346.  
  347.     screenArea = qd . thePort -> portBits . bounds ;
  348.     OffsetRect ( & screenArea , - screenArea . left , - screenArea . top ) ;
  349.  
  350. /* Map Window */
  351.     nhWin = theWindows + WIN_MAP ;
  352.     theWindow = nhWin -> theWindow ;
  353.  
  354.     height = nhWin -> charHeight * NUM_ROWS ;
  355.     width = nhWin -> charWidth * NUM_COLS ;
  356.  
  357.     if ( ! RetrievePosition ( kMapWindow , & top , & left ) ) {
  358.         top = GetMBarHeight ( ) * 2 ;
  359.         left = ( screenArea . right - width ) / 2 ;
  360.     }
  361.  
  362.     mainTop = top ;
  363.     mainLeft = left ;
  364.     mainHeight = height ;
  365.     mainWidth = width ;
  366.  
  367. /* Status Window */
  368.     nhWin = theWindows + WIN_STATUS ;
  369.     theWindow = nhWin -> theWindow ;
  370.  
  371.     height = nhWin -> charHeight * NUM_STAT_ROWS ;
  372.  
  373.     if ( ! RetrievePosition ( kStatusWindow , & top , & left ) ) {
  374.         top = mainTop + mainHeight + 2 ;
  375.         left = mainLeft ;
  376.     }
  377.  
  378.     if ( top + height > screenArea . bottom ) {
  379.         top = screenArea . bottom - height ;
  380.         left += 20 ; /* Edge to the right so we can read it */
  381.     }
  382.     statTop = top ;
  383.     statLeft = left ;
  384.     statHeight = height ;
  385.     statWidth = width ;
  386.  
  387. /* Message Window */
  388.     nhWin = theWindows + WIN_MESSAGE ;
  389.     theWindow = nhWin -> theWindow ;
  390.  
  391.     if ( ! RetrievePosition ( kMessageWindow , & top , & left ) ) {
  392.         top = statTop + statHeight + 20 ;
  393.         left = statLeft ;
  394.     }
  395.  
  396.     if ( ! RetrieveSize ( kMessageWindow , top , left , & height , & width ) ) {
  397.         height = screenArea . bottom - top - 2 ;
  398.         if ( height > MAX_HEIGHT ) {
  399.             height = MAX_HEIGHT ;
  400.         } else if ( height < MIN_HEIGHT ) {
  401.             height = MIN_HEIGHT ;
  402.             width = MIN_WIDTH ;
  403.             left = screenArea . right - width ;
  404.             top = screenArea . bottom - MIN_HEIGHT ;
  405.         }
  406.     }
  407.     mesgTop = top ;
  408.     mesgLeft = left ;
  409.     mesgHeight = height ;
  410.     mesgWidth = width ;
  411.  
  412. /* Move these windows */
  413.     MoveWindow ( theWindows [ WIN_STATUS ] . theWindow , statLeft , statTop , 1 ) ;
  414.     SizeWindow ( theWindows [ WIN_STATUS ] . theWindow , statWidth , statHeight , 1 ) ;
  415.     MoveWindow ( theWindows [ WIN_MESSAGE ] . theWindow , mesgLeft , mesgTop , 1 ) ;
  416.     SizeWindow ( theWindows [ WIN_MESSAGE ] . theWindow , mesgWidth , mesgHeight , 1 ) ;
  417.     MoveWindow ( theWindows [ WIN_MAP ] . theWindow , mainLeft , mainTop , 1 ) ;
  418.     SizeWindow ( theWindows [ WIN_MAP ] . theWindow , mainWidth , mainHeight , 1 ) ;
  419.  
  420. /* Handle other windows */
  421.     for ( ix = 0 ; ix < NUM_MACWINDOWS ; ix ++ ) {
  422.         if ( ix != WIN_STATUS && ix != WIN_MESSAGE && ix != WIN_MAP ) {
  423.             if ( theWindow = theWindows [ ix ] . theWindow ) {
  424.                 if ( ( ( WindowPeek ) theWindow ) -> visible ) {
  425.                     if ( theWindows [ ix ] . kind == NHW_MENU ) {
  426.                         if ( ! RetrievePosition ( kMenuWindow , & top , & left ) ) {
  427.                             top = GetMBarHeight ( ) * 2 ;
  428.                             left = 2 ;
  429.                         }
  430.                         top += ( numMenu * GetMBarHeight ( ) ) ;
  431.                         while ( top > screenArea . bottom - MIN_HEIGHT ) {
  432.                             top -= ( screenArea . bottom - GetMBarHeight ( ) * 2 ) ;
  433.                             left += 20 ;
  434.                         }
  435.                         numMenu ++ ;
  436.                         MoveWindow ( theWindow , left , top , 1 ) ;
  437.                     } else {
  438.                         if ( ! RetrievePosition ( kTextWindow , & top , & left ) ) {
  439.                             top = GetMBarHeight ( ) * 2 ;
  440.                             left = screenArea . right - 3 ;
  441.                         }
  442.                         top += ( numText * GetMBarHeight ( ) ) ;
  443.                         while ( top > screenArea . bottom - MIN_HEIGHT ) {
  444.                             top -= ( screenArea . bottom - GetMBarHeight ( ) * 2 ) ;
  445.                             left -= 20 ;
  446.                         }
  447.                         numText ++ ;
  448.                         MoveWindow ( theWindow , left - ( theWindow -> portRect . right -
  449.                             theWindow -> portRect . left ) , top , 1 ) ;
  450.                     }
  451.                 }
  452.             }
  453.         }
  454.     }
  455.  
  456.     InitCursor ( ) ;
  457.  
  458.     return 0 ;
  459. }
  460.  
  461.  
  462. winid
  463. mac_create_nhwindow ( int type )
  464. {
  465.     int i ;
  466.     Rect siz ;
  467.     NhWindow * aWin ;
  468.  
  469.     if ( type < NHW_BASE || type > NHW_TEXT ) {
  470.         error ( "Invalid window type %d in create_nhwindow." , type ) ;
  471.         return WIN_ERR ;
  472.     }
  473.  
  474.     for ( i = 0 ; i < NUM_MACWINDOWS ; i ++ ) {
  475.         if ( ! theWindows [ i ] . theWindow )
  476.             break ;
  477.     }
  478.     if ( i >= NUM_MACWINDOWS ) {
  479.         for ( i = 0 ; i < NUM_MACWINDOWS ; i ++ ) {
  480.             WindowPeek w = ( WindowPeek ) theWindows [ i ] . theWindow ;
  481.             if ( w -> visible || i == WIN_INVEN || ( w -> windowKind
  482.                 != NHW_MENU && w -> windowKind != NHW_TEXT ) )
  483.                 continue ;
  484.             error ( "The window list is getting full, freeing unnecessary window (%d)..." ,
  485.                 i ) ;
  486.             destroy_nhwindow ( i ) ;
  487.             goto got1 ;
  488.         }
  489.         error ( "Out of window ids in create_nhwindow ! (Max = %d)" ,
  490.             NUM_MACWINDOWS ) ;
  491.         return WIN_ERR ;
  492.     }
  493.  
  494. got1 :
  495.     aWin = & theWindows [ i ] ;
  496.     aWin -> theWindow = GetNewWindow ( WIN_BASE_RES + type ,
  497.         ( WindowPtr ) 0L , ( WindowPtr ) -1L ) ;
  498.     ( ( WindowPeek ) aWin -> theWindow ) -> windowKind = WIN_BASE_KIND
  499.         + type ;
  500.     aWin -> windowTextLen = 0L ;
  501.     aWin -> textBase = 0L ;
  502.     aWin -> clear = 0 ; /* Yes, we need to inval the area on a clear */
  503.     aWin -> scrollBar = (ControlHandle) NULL ;
  504.     switch ( type ) {
  505.     case NHW_MAP :
  506.         if ( ! ( aWin -> windowText = NewHandle
  507.             ( sizeof ( MapData ) ) ) ) {
  508.             error ( "NewHandle failed in create_nhwindow (%ld bytes)" ,
  509.                 ( long ) sizeof ( MapData ) ) ;
  510.             DisposeWindow ( aWin -> theWindow ) ;
  511.             aWin -> theWindow = (WindowPtr) NULL ;
  512.             return WIN_ERR ;
  513.         }
  514.         break ;
  515.     case NHW_STATUS :
  516.         if ( ! ( aWin -> windowText = NewHandle
  517.             ( sizeof ( StatusData ) ) ) ) {
  518.             error ( "NewHandle failed in create_nhwindow (%ld bytes)" ,
  519.                 ( long ) sizeof ( StatusData ) ) ;
  520.             DisposeWindow ( aWin -> theWindow ) ;
  521.             aWin -> theWindow = (WindowPtr) NULL ;
  522.             return WIN_ERR ;
  523.         }
  524.         break ;
  525.     default :
  526.         if ( ! ( aWin -> windowText = NewHandle ( TEXT_BLOCK ) ) ) {
  527.             error ( "NewHandle failed in create_nhwindow (%ld bytes)" ,
  528.                 ( long ) TEXT_BLOCK ) ;
  529.             DisposeWindow ( aWin -> theWindow ) ;
  530.             aWin -> theWindow = (WindowPtr) NULL ;
  531.             return WIN_ERR ;
  532.         }
  533.         break ;
  534.     }
  535.  
  536.     clear_nhwindow ( i ) ;
  537.  
  538. /*HARDCODED*/
  539.  
  540.     SetPort ( aWin -> theWindow ) ;
  541.     PenPat ( &qd . black ) ;
  542.  
  543.     switch ( type ) {
  544.         case NHW_MAP :
  545.         case NHW_STATUS :
  546.             GetFNum ( "\pHackFont", & aWin -> fontNum ) ;
  547.             aWin -> fontSize = flags.large_font ? 12 : 9 ;
  548.             break ;
  549.         case NHW_MESSAGE :
  550.             GetFNum ( "\pPSHackFont", & aWin -> fontNum ) ;
  551.             aWin -> fontSize = flags.large_font ? 12 : 9 ;
  552.             break ;
  553.         default:
  554.             aWin -> fontNum = text_wind_font ;
  555.             aWin -> fontSize = 9 ;
  556.     }
  557.  
  558.     TextFont ( aWin -> fontNum ) ; 
  559.     TextSize ( aWin -> fontSize ) ;
  560.  
  561.     if (type == NHW_MESSAGE && !top_line) {
  562.         const Rect out_of_scr = { 10000, 10000, 10100, 10100 };
  563.         TextFace(bold);
  564.         top_line = TENew(&out_of_scr, &out_of_scr);
  565.         TEActivate(top_line);
  566.         TextFace(normal);
  567.     }
  568.  
  569.     {
  570.         FontInfo fi ;
  571.         GetFontInfo ( & fi ) ;
  572.         aWin -> leading = fi . leading / 2 + fi . descent ;
  573.         aWin -> charHeight = fi . ascent + fi . descent + fi . leading ;
  574.         aWin -> charWidth = fi . widMax ;
  575.     }
  576.     SetPt ( & ( theWindows [ i ] . cursor ) , 0 , 0 ) ;
  577.  
  578.     aWin -> kind = type ;
  579.     aWin -> keyFunc = winKeyFuncs [ type ] ;
  580.     aWin -> clickFunc = winClickFuncs [ type ] ;
  581.     aWin -> updateFunc = winUpdateFuncs [ type ] ;
  582.     aWin -> cursorFunc = winCursorFuncs [ type ] ;
  583.     SetWRefCon ( aWin -> theWindow , ( long ) aWin ) ;
  584.  
  585.     SetRect ( & siz , 0 , 0 , aWin -> charWidth * NUM_COLS ,
  586.         aWin -> charHeight * NUM_ROWS ) ;
  587.     switch ( type ) {
  588.     case NHW_MAP :
  589.         OffsetRect ( & siz , 50 , 50 ) ;
  590.         break ;
  591.     case NHW_BASE :
  592.         OffsetRect ( & siz , 20 , 10 ) ;
  593.         break ;
  594.     default :
  595.         siz = aWin -> theWindow -> portRect ;
  596.         OffsetRect ( & siz , 30 + rn2 ( 20 ) , 250 + rn2 ( 50 ) ) ;
  597.         break ;
  598.     }
  599.     SizeWindow ( aWin -> theWindow , siz . right - siz . left ,
  600.         siz . bottom - siz . top , FALSE ) ;
  601.     MoveWindow ( aWin -> theWindow , siz . left , siz . top , FALSE ) ;
  602.  
  603.     if ( type == NHW_MENU || type == NHW_TEXT ) {
  604.         Rect r = siz ;
  605.         Boolean bool ;
  606.         OffsetRect ( & r , - r . left , - r . top ) ;
  607.         r . left = r . right - SBARWIDTH ;
  608.         r . bottom -= SBARHEIGHT ;
  609.         r . top -= 1 ;
  610.         r . right += 1 ;
  611.         bool = ( r . bottom > r . top + 50 ) ;
  612.         aWin -> scrollBar = NewControl ( aWin -> theWindow , & r , (StringPtr)"" ,
  613.             bool , 0 , 0 , 0 , 16 , 0L ) ;
  614.     }
  615.     aWin -> scrollPos = 0 ;
  616.     aWin -> cursorDrawn = 0 ;
  617.  
  618.     return i ;
  619. }
  620.  
  621.  
  622. void
  623. InitRes ( void )
  624. {
  625.     Str255 str ;
  626.  
  627.     mBar = GetNewMBar ( 128 ) ;
  628.     mustwork(ResError());
  629.     SetMenuBar ( mBar ) ;
  630.     
  631.     appleMenu = GetMHandle ( 128 ) ;
  632.     mustwork(ResError());
  633.     AppendMenu ( appleMenu , ( ConstStr255Param ) "\002(-" ) ;
  634.     AddResMenu ( appleMenu , 'DRVR' ) ;
  635.  
  636.     fileMenu = GetMHandle ( 129 ) ;
  637.     mustwork(ResError());
  638.     editMenu = GetMHandle ( 130 ) ;
  639.     mustwork(ResError());
  640.     extendMenu = GetMHandle ( 131 ) ;
  641.     mustwork(ResError());
  642.     miscMenu = GetMHandle ( 132 ) ;
  643.     mustwork(ResError());
  644.     commandsMenu = GetMHandle ( 133 ) ;
  645.     mustwork ( ResError ( ) ) ;
  646.     thingsMenu = GetMHandle ( 134 ) ;
  647.     mustwork ( ResError ( ) ) ;
  648.  
  649.     if ( macFlags . help ) {
  650.         if ( HMGetHelpMenuHandle ( & helpMenu ) ) {
  651.             helpMenu = (MenuHandle) NULL ;
  652.         }
  653.     }
  654.     if ( helpMenu ) {
  655.         GetIndString ( str , 128 , 1 ) ;
  656.         AppendMenu ( helpMenu , str ) ;
  657.     } else AppendMenu ( appleMenu , str ) ;
  658.     
  659.     DrawMenuBar ( ) ;
  660.  
  661.     return ;
  662. }
  663.  
  664.  
  665. void
  666. mac_init_nhwindows ( void )
  667. {
  668.     int i ;
  669.  
  670.     InitRes ( ) ;
  671.  
  672.     theWindows = ( NhWindow * ) NewPtr ( NUM_MACWINDOWS *
  673.         sizeof ( NhWindow ) ) ;
  674.     mustwork(MemError());
  675.  
  676.     for ( i = 0 ; i < NUM_MACWINDOWS ; i ++ ) {
  677.         theWindows [ i ] . theWindow = (WindowPtr) NULL ;
  678.     }
  679.     for ( i = 0 ; i < QUEUE_LEN ; i ++ ) {
  680.         keyQueue [ i ] = 0 ;
  681.     }
  682.  
  683.     BASE_WINDOW = create_nhwindow ( NHW_TEXT ) ;
  684.     clear_nhwindow(BASE_WINDOW);
  685.     putstr(BASE_WINDOW, 0, "");
  686.     putstr(BASE_WINDOW, 0,
  687.       "NetHack, Copyright 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993");
  688.     putstr(BASE_WINDOW, 0,
  689.       "         By Stichting Mathematisch Centrum and M. Stephenson.");
  690.     putstr(BASE_WINDOW, 0, "         See license for details.");
  691.     putstr(BASE_WINDOW, 0, "  ");
  692.     display_nhwindow(BASE_WINDOW, FALSE);
  693.  
  694.     flags . window_inited = 1 ;
  695.     DimMenuBar ( ) ;
  696. }
  697.  
  698.  
  699. void
  700. mac_nhbell ( void )
  701. {
  702.     Handle h ;
  703.  
  704.     if ( h = GetNamedResource ( 'snd ' , "\PNetHack Bell" ) ) {
  705.  
  706.         HLock ( h ) ;
  707.         SndPlay ( ( SndChannelPtr ) NULL , h , 0 ) ;
  708.         ReleaseResource ( h ) ;
  709.  
  710.     } else {
  711.  
  712.         SysBeep ( 30 ) ;
  713.     }
  714. }
  715.  
  716.  
  717. static void
  718. DrawScrollbar ( NhWindow * aWin , WindowPtr theWindow )
  719. {
  720.     Rect r2 = theWindow -> portRect ;
  721.     Rect r = r2 ;
  722.     Boolean vis ;
  723.     short val ;
  724.  
  725.     if ( ! aWin -> scrollBar ) {
  726.         return ;
  727.     }
  728.  
  729.     r2 . left = r2 . right - SBARWIDTH ;
  730.     r2 . bottom -= SBARHEIGHT ;
  731.     r2 . right += 1 ;
  732.     r2 . top -= 1 ;
  733.     MoveControl ( aWin -> scrollBar , r2 . left , r2 . top ) ;
  734.     SizeControl ( aWin -> scrollBar , r2 . right - r2 . left ,
  735.         r2 . bottom - r2 . top ) ;
  736.     vis = ( r2 . bottom > r2 . top + 50 ) ;
  737.     if ( vis && ! ( * aWin -> scrollBar ) -> contrlVis ) {
  738.         ShowControl ( aWin -> scrollBar ) ;
  739.     } else if ( ! vis && ( * aWin -> scrollBar ) -> contrlVis ) {
  740.         HideControl ( aWin -> scrollBar ) ;
  741.     }
  742.     if ( aWin -> lin ) {
  743.         short max = aWin -> lin - ( r . bottom - r . top ) / aWin ->
  744.             charHeight ;
  745.         if ( max < 0 ) max = 0 ;
  746.         SetCtlMax ( aWin -> scrollBar , max ) ;
  747.         if ( max ) HiliteControl ( aWin -> scrollBar , 0 ) ;
  748.         else HiliteControl ( aWin -> scrollBar , 255 ) ;
  749.     } else {
  750.         HiliteControl ( aWin -> scrollBar , 255 ) ;
  751.     }
  752.     val = GetCtlValue ( aWin -> scrollBar ) ;
  753.     if ( val != aWin -> scrollPos ) {
  754.         InvalRect ( & ( theWindow -> portRect ) ) ;
  755.         aWin -> scrollPos = val ;
  756.     }
  757.     if ( aWin == asyDSC ) {
  758.         asyDSC = (NhWindow *) NULL ;
  759.     }
  760. }
  761.  
  762.  
  763. static void
  764. InvalScrollBar ( NhWindow * aWin )
  765. {
  766.     if ( asyDSC && asyDSC != aWin ) {
  767.         SetPort ( asyDSC -> theWindow ) ;
  768.         DrawScrollbar ( asyDSC , asyDSC -> theWindow ) ;
  769.     }
  770.     asyDSC = aWin ;
  771. }
  772.  
  773.  
  774. void
  775. mac_clear_nhwindow ( winid win )
  776. {
  777.     long l ;
  778.     register char * start , * stop ;
  779.     WindowPtr theWindow ;
  780.     NhWindow * aWin = & theWindows [ win ] ;
  781.  
  782.     if ( win < 0 || win >= NUM_MACWINDOWS ) {
  783.         error ( "Invalid window %d in clear_nhwindow." , win ) ;
  784.         return ;
  785.     }
  786.     if ( aWin -> clear )
  787.         return ;
  788.     theWindow = aWin -> theWindow ;
  789.     if ( ! theWindow ) {
  790.         error ( "Unallocated window %d in clear_nhwindow." , win ) ;
  791.         return ;
  792.     }
  793.     SetPort ( theWindow ) ;
  794.     InvalRect ( & ( theWindow -> portRect ) ) ;
  795.     switch ( ( ( WindowPeek ) theWindow ) -> windowKind - WIN_BASE_KIND ) {
  796.     case NHW_MAP :
  797.         stop = ( char * ) ( ( MapData * ) ( * aWin -> windowText ) )
  798.             -> map ;
  799.         start = stop + NUM_COLS * NUM_ROWS ;
  800.         while ( start > stop ) * -- start = CHAR_BLANK ;
  801.         break ;
  802.     case NHW_STATUS :
  803.         stop = ( char * ) ( ( StatusData * ) ( * aWin -> windowText ) )
  804.             -> map ;
  805.         start = stop + NUM_COLS * NUM_STAT_ROWS ;
  806.         while ( start > stop ) * -- start = CHAR_BLANK ;
  807.         break ;
  808.     case NHW_MESSAGE :
  809.         l = GetHandleSize ( aWin -> windowText ) ;
  810.         if ( l > TEXT_BLOCK * 2 ) {
  811.             BlockMove ( * aWin -> windowText + TEXT_BLOCK ,
  812.                 * aWin -> windowText , l - TEXT_BLOCK ) ;
  813.             SetHandleSize ( aWin -> windowText , l - TEXT_BLOCK ) ;
  814.             aWin -> windowTextLen -= TEXT_BLOCK ;
  815.             if ( aWin -> windowTextLen < 0 ) {
  816.                 aWin -> windowTextLen = 0 ;
  817.             }
  818.         }
  819. #if 1
  820.         aWin->textBase = aWin->windowTextLen;
  821. #else
  822.         stop = * aWin -> windowText ;
  823.         start = stop + aWin -> windowTextLen - 1 ;
  824.         while ( -- start > stop ) {
  825.             if ( * start == CHAR_CR || * start == CHAR_LF )
  826.                 break ;
  827.         }
  828.         if ( start > stop ) {
  829.             aWin -> textBase = start - stop + 1 ;
  830.         } else {
  831.             aWin -> textBase = 0L ;
  832.         }
  833. #endif
  834.         break ;
  835.     default :
  836.         SetHandleSize ( aWin -> windowText , TEXT_BLOCK ) ;
  837.         aWin -> windowTextLen = 0L ;
  838.         aWin -> lin = 0 ;
  839.         aWin -> wid = 0 ;
  840.         aWin -> scrollPos = 0 ;
  841.         aWin -> textBase = 0L ;
  842.         if ( aWin -> scrollBar ) {
  843.             SetCtlMax ( aWin -> scrollBar , 0 ) ;
  844.             InvalScrollBar ( aWin ) ;
  845.         }
  846.         break ;
  847.     }
  848.     SetPt ( & ( aWin -> cursor ) , 0 , 0 ) ;
  849.     aWin -> clear = 1 ;
  850.     aWin -> cursorDrawn = 0 ;
  851. }
  852.  
  853.  
  854. Boolean
  855. ClosingWindowChar(const int c) {
  856.     return  c == CHAR_ESC || c == CHAR_BLANK || c == CHAR_LF || c == CHAR_CR ;
  857. }
  858.  
  859.  
  860. #define BTN_IND 2
  861. #define BTN_W    40
  862. #define BTN_H    (SBARHEIGHT-2)
  863.  
  864. static void
  865. topl_resp_rect(int resp_idx, Rect *r)
  866. {
  867.     r->left      = (BTN_IND + BTN_W) * resp_idx + BTN_IND;
  868.     r->right  = r->left + BTN_W;
  869.     r->bottom = theWindows[WIN_MESSAGE].theWindow->portRect.bottom - 1;
  870.     r->top      = r->bottom - BTN_H;
  871. }
  872.  
  873.  
  874. Boolean
  875. in_topl_mode(void)
  876. {
  877.     return top_line &&
  878.            (*top_line)->viewRect.left < theWindows[WIN_MESSAGE].theWindow->portRect.right;
  879. }
  880.  
  881.  
  882. void
  883. enter_topl_mode(char *query)
  884. {
  885.     if (!top_line || in_topl_mode())
  886.         Debugger();
  887.     (*top_line)->viewRect.left = 0;
  888.  
  889.     topl_query_len = strlen(query);
  890.     (*top_line)->selStart = topl_query_len;
  891.     (*top_line)->selEnd      = topl_query_len;
  892.     PtrToXHand(query, (*top_line)->hText, topl_query_len);
  893.     TECalText(top_line);
  894.  
  895.     display_nhwindow(WIN_MESSAGE, FALSE);
  896.     putstr(WIN_MESSAGE, ATR_BOLD, query);
  897. }
  898.  
  899.  
  900. void
  901. leave_topl_mode(char *answer)
  902. {
  903.     int ans_len = (*top_line)->teLength - topl_query_len;
  904.     NhWindow *aWin = theWindows + WIN_MESSAGE;
  905.     char tmp[3] = "  ";
  906.  
  907.     if (!in_topl_mode())
  908.         Debugger();
  909.     (*top_line)->viewRect.left += 10000;
  910.  
  911.     BlockMove(*(*top_line)->hText + topl_query_len, answer, ans_len);
  912.     answer[ans_len] = '\0';
  913.  
  914.     if ( aWin -> windowTextLen > 0 &&
  915.          ( * aWin -> windowText ) [ aWin -> windowTextLen - 1 ] == CHAR_CR ) {
  916.         -- aWin -> windowTextLen ;
  917.         -- aWin -> lin ;
  918.     }
  919.     if (strlen(answer) <= 1) {
  920.         if (answer[0]) tmp[0] = answer[0];
  921.         putstr(WIN_MESSAGE, ATR_BOLD, tmp);
  922.     } else
  923.         putstr(WIN_MESSAGE, ATR_BOLD, answer);
  924. }
  925.  
  926. /*
  927.  * TESetSelect flushes out all the pending key strokes.  I hate it.
  928.  */
  929. static void
  930. topl_set_select(short selStart, short selEnd)
  931. {
  932.     TEDeactivate(top_line);
  933.     (*top_line)->selStart = selStart;
  934.     (*top_line)->selEnd      = selEnd;
  935.     TEActivate(top_line);
  936. }
  937.  
  938.  
  939. static void
  940. topl_replace(char *new_ans)
  941. {
  942.     topl_set_select(topl_query_len, (*top_line)->teLength);
  943.     TEDelete(top_line);
  944.     TEInsert(new_ans, strlen(new_ans), top_line);
  945. }
  946.  
  947.  
  948. Boolean
  949. topl_key(unsigned char ch)
  950. {
  951.     switch (ch) {
  952.         case CHAR_ESC:
  953.             topl_replace("\x1b");
  954.             return false;
  955.         case CHAR_ENTER: case CHAR_CR: case CHAR_LF:
  956.             return false;
  957.  
  958.         case 0x1f & 'P':
  959.             nh_doprev_message();
  960.             return true;
  961.         case '\x1e'/* up arrow */:
  962.             topl_set_select(topl_query_len, topl_query_len);
  963.             return true;
  964.         case CHAR_BS: case '\x1c'/* left arrow */:
  965.             if ((*top_line)->selEnd > topl_query_len)
  966.                 TEKey(ch, top_line);
  967.             return true;
  968.         default:
  969.             TEKey(ch, top_line);
  970.             return true;
  971.     }
  972. }
  973.  
  974.  
  975. Boolean
  976. topl_ext_key(unsigned char ch)
  977. {
  978.     switch (ch) {
  979.         case CHAR_ESC:
  980.             topl_replace("\x1b");
  981.             return false;
  982.         case CHAR_ENTER: case CHAR_CR: case CHAR_LF:
  983.             return false;
  984.  
  985.         case 0x1f & 'P':
  986.             nh_doprev_message();
  987.             return true;
  988.         case CHAR_BS:
  989.             topl_replace("");
  990.             return true;
  991.         default: {
  992.             int com_index = -1, oindex = 0;
  993.             TEInsert(&ch, 1, top_line);
  994.             while(extcmdlist[oindex].ef_txt != NULL){
  995.                 if(!strncmpi(*(*top_line)->hText + topl_query_len,
  996.                              extcmdlist[oindex].ef_txt,
  997.                              (*top_line)->teLength - topl_query_len))
  998.                     if(com_index == -1) /* No matches yet*/
  999.                         com_index = oindex;
  1000.                     else /* More than 1 match */
  1001.                         com_index = -2;
  1002.                 oindex++;
  1003.             }
  1004.             if(com_index >= 0)
  1005.                 topl_replace(extcmdlist[com_index].ef_txt);
  1006.             return true;
  1007.         }
  1008.     }
  1009. }
  1010.  
  1011.  
  1012. void
  1013. topl_flash_resp(int resp_idx)
  1014. {
  1015.     long dont_care;
  1016.     Rect frame;
  1017.     SetPort(theWindows[WIN_MESSAGE].theWindow);
  1018.     topl_resp_rect(resp_idx, &frame);
  1019.     InsetRect(&frame, 1, 1);
  1020.     InvertRect(&frame);
  1021.     Delay(GetDblTime() / 2, &dont_care);
  1022.     InvertRect(&frame);
  1023. }
  1024.  
  1025.  
  1026. void
  1027. topl_set_def(int new_def_idx)
  1028. {
  1029.     Rect frame;
  1030.     SetPort(theWindows[WIN_MESSAGE].theWindow);
  1031.     topl_resp_rect(topl_def_idx, &frame);
  1032.     InvalRect(&frame);
  1033.     topl_def_idx = new_def_idx;
  1034.     topl_resp_rect(new_def_idx, &frame);
  1035.     InvalRect(&frame);
  1036. }
  1037.  
  1038.  
  1039. void
  1040. topl_set_resp(char *resp, char def)
  1041. {
  1042.     char *loc;
  1043.     Rect frame;
  1044.     int r_len, r_len1;
  1045.  
  1046.     if (!resp) {
  1047.         static char any_str[2] = { CHAR_ANY, '\0' };
  1048.         resp = any_str;
  1049.         def = CHAR_ANY;
  1050.     }
  1051.  
  1052.     r_len1 = strlen(resp);
  1053.     r_len  = strlen(topl_resp);
  1054.     if (r_len < r_len1)
  1055.         r_len = r_len1;
  1056.     topl_resp_rect(0, &frame);
  1057.     frame.right = (BTN_IND + BTN_W) * r_len;
  1058.     InvalRect(&frame);
  1059.  
  1060.     strcpy(topl_resp, resp);
  1061.     loc = strchr (resp, def);
  1062.     topl_def_idx = loc ? loc - resp : -1;
  1063. }
  1064.  
  1065.  
  1066. static char
  1067. topl_resp_key(char ch)
  1068. {
  1069.     if (strlen(topl_resp) > 0) {
  1070.         char *loc = strchr(topl_resp, ch);
  1071.  
  1072.         if (!loc)
  1073.             if (ch == '\x9'/* tab */) {
  1074.                 topl_set_def(topl_def_idx <= 0 ? strlen(topl_resp)-1 : topl_def_idx-1);
  1075.                 ch = '\0';
  1076.  
  1077.             } else if (ch == CHAR_ESC) {
  1078.                 loc = strchr(topl_resp, 'q');
  1079.                 if (!loc) {
  1080.                     loc = strchr(topl_resp, 'n');
  1081.                     if (!loc && topl_def_idx >= 0)
  1082.                         loc = topl_resp + topl_def_idx;
  1083.                 }
  1084.  
  1085.             } else if (ch == (0x1f & 'P')) {
  1086.                 nh_doprev_message();
  1087.                 ch = '\0';
  1088.  
  1089.             } else if (topl_def_idx >= 0) {
  1090.                 if ( ch == CHAR_ENTER || ch == CHAR_CR || ch == CHAR_LF ||
  1091.                      ch == CHAR_BLANK || topl_resp[topl_def_idx] == CHAR_ANY )
  1092.                     loc = topl_resp + topl_def_idx;
  1093.  
  1094.                 else if (strchr(topl_resp, '#')) {
  1095.                     if (digit(ch)) {
  1096.                         topl_set_def(strchr(topl_resp, '#') - topl_resp);
  1097.                         TEKey(ch, top_line);
  1098.                         ch = '\0';
  1099.  
  1100.                     } else if (topl_resp[topl_def_idx] == '#')
  1101.                         if (ch == '\x1e'/* up arrow */) {
  1102.                             topl_set_select(topl_query_len, topl_query_len);
  1103.                             ch = '\0';
  1104.                         } else if (ch == '\x1d'/* right arrow */ ||
  1105.                                    ch == '\x1f'/* down arrow */ ||
  1106.                                    (ch == CHAR_BS || ch == '\x1c'/* left arrow */) &&
  1107.                                         (*top_line)->selEnd > topl_query_len) {
  1108.                             TEKey(ch, top_line);
  1109.                             ch = '\0';
  1110.                         }
  1111.                 }
  1112.             }
  1113.  
  1114.         if (loc) {
  1115.             topl_flash_resp(loc - topl_resp);
  1116.             if (*loc != CHAR_ANY)
  1117.                 ch = *loc;
  1118.             TEKey(ch, top_line);
  1119.         }
  1120.     }
  1121.  
  1122.     return ch;
  1123. }
  1124.  
  1125.  
  1126. /*
  1127.  * display/select/update the window.
  1128.  * If f is true, this window should be "modal" - don't return
  1129.  * until presumed seen.
  1130.  */
  1131. void
  1132. mac_display_nhwindow ( winid win , BOOLEAN_P f )
  1133. {
  1134.     WindowPtr theWindow ;
  1135.     NhWindow * aWin = & theWindows [ win ] ;
  1136.  
  1137.     if ( win < 0 || win >= NUM_MACWINDOWS ) {
  1138.         error ( "Invalid window %d in display_nhwindow." , win ) ;
  1139.         return ;
  1140.     }
  1141.     theWindow = aWin -> theWindow ;
  1142.     if ( ! theWindow ) {
  1143.         error ( "Unallocated window %d in display_nhwindow." , win ) ;
  1144.         return ;
  1145.     }
  1146.  
  1147.     if ( f && inSelect == WIN_ERR && ( win == BASE_WINDOW || win == WIN_MESSAGE ) ) {
  1148.         if ( win == WIN_MESSAGE )
  1149.             topl_set_resp ( NULL , 0 ) ;
  1150.         /* The following piece of code prevents the "-- More --" prompt to be on a new
  1151.            line by itself.  I comment it out because the result looks ugly to me. */
  1152. #ifdef 0
  1153.         if ( aWin -> windowTextLen > 0 &&
  1154.              ( * aWin -> windowText ) [ aWin -> windowTextLen - 1 ] == CHAR_CR ) {
  1155.             -- aWin -> windowTextLen ;
  1156.             -- aWin -> lin ;
  1157.         }
  1158. #endif
  1159.         putstr ( win , ATR_INVERSE , "-- More --" ) ;
  1160.     }
  1161.  
  1162.     if ( ! ( ( WindowPeek ) theWindow ) -> visible ) {
  1163.         const Rect scr_r   = (*GetGrayRgn())->rgnBBox,
  1164.                    win_ind = { 20, 2, 3, 3 };
  1165.         const Point scr_sz = { scr_r.bottom - scr_r.top, scr_r.right - scr_r.left },
  1166.                     wp_sz  = { theWindow->portRect.bottom - theWindow->portRect.top,
  1167.                                theWindow->portRect.right  - theWindow->portRect.left };
  1168.         const short max_h = scr_sz.v - win_ind.top    - win_ind.bottom,
  1169.                     max_w = scr_sz.h - win_ind.left - win_ind.right;
  1170.         const char cr = CHAR_CR;
  1171.  
  1172.         long line_start = 0, line_end;
  1173.         short w = wp_sz.h,
  1174.               h = full_screen ? aWin->lin * aWin->charHeight : wp_sz.v;
  1175.         Point pos = { theWindow->portRect.top, theWindow->portRect.left };
  1176.         SetPort(theWindow);
  1177.         LocalToGlobal(&pos);
  1178.  
  1179.         HLock(aWin->windowText);
  1180.         while (line_start < aWin->windowTextLen) {
  1181.             short line_w;
  1182.             line_end = Munger(aWin->windowText, line_start, &cr, 1, nil, 0);
  1183.             if (line_end < 0)
  1184.                 line_end = aWin->windowTextLen;
  1185.             line_w = TextWidth(*aWin->windowText, line_start, line_end - line_start) +
  1186.                      (SBARWIDTH + 2);
  1187.             if (w < line_w)
  1188.                 w = line_w;
  1189.             line_start = line_end + 1;
  1190.         }
  1191.         HUnlock(aWin->windowText);
  1192.  
  1193.         if (h > max_h) h = max_h;
  1194.         if (w > max_w) w = max_w;
  1195.         SizeWindow(theWindow, w, h, FALSE);
  1196.  
  1197.         if ( ! ( ( WindowPeek ) theWindow ) -> visible ) {
  1198.             short top , left ;
  1199.             if ( ! RetrieveWinPos ( theWindow , & top , & left ) ) {
  1200.                 if (pos.v + h + win_ind.bottom > scr_r.bottom)
  1201.                     pos.v = scr_r.bottom - h - win_ind.bottom;
  1202.                 if (pos.h + w + win_ind.right  > scr_r.right)
  1203.                     pos.h = scr_r.right     - w - win_ind.right;
  1204.                 top = pos . v ;
  1205.                 left = pos . h ;
  1206.             }
  1207.             MoveWindow(theWindow, left, top, FALSE);
  1208.         }
  1209.  
  1210.         SelectWindow ( theWindow ) ;
  1211.         ShowWindow ( theWindow ) ;
  1212.     }
  1213.  
  1214.     SetPort ( theWindow ) ;
  1215.     if ( aWin -> scrollBar ) {
  1216.         InvalScrollBar ( aWin ) ;
  1217.     }
  1218.  
  1219.     if ( f && inSelect == WIN_ERR ) {
  1220.         int ch ;
  1221.  
  1222.         inSelect = win ;
  1223.         do {
  1224.             ch = nhgetch ( ) ;
  1225.         } while ( ! ClosingWindowChar ( ch ) ) ;
  1226.         inSelect = WIN_ERR ;
  1227.  
  1228.         if ( win == WIN_MESSAGE )
  1229.             topl_set_resp ( "" , '\0' ) ;
  1230.         else
  1231.             HideWindow ( theWindow ) ;
  1232.  
  1233.     } else {
  1234.         wait_synch ( ) ;
  1235.     }
  1236. }
  1237.  
  1238.  
  1239. void
  1240. mac_destroy_nhwindow ( winid win )
  1241. {
  1242.     WindowPtr theWindow ;
  1243.     NhWindow * aWin = & theWindows [ win ] ;
  1244.     int kind , visible ;
  1245.  
  1246.     if ( win < 0 || win >= NUM_MACWINDOWS ) {
  1247.         if ( flags . window_inited )
  1248.             error ( "Invalid window number %d (Max %d) in destroy_nhwindow." ,
  1249.                 win , NUM_MACWINDOWS ) ;
  1250.         return ;
  1251.     }
  1252.     theWindow = aWin -> theWindow ;
  1253.     if ( ! theWindow ) {
  1254.         error ( "Not allocated window number %d in destroy_nhwindow." ,
  1255.             win ) ;
  1256.         return ;
  1257.     }
  1258.  
  1259.     /*
  1260.      * Check special windows.
  1261.      * The base window should never go away.
  1262.      * The other "standard" windows should not go away
  1263.      * unless we've exitted nhwindows.
  1264.      */
  1265.     if ( win == BASE_WINDOW ) {
  1266.         return ;
  1267.     }
  1268.     if ( win == WIN_INVEN || win == WIN_STATUS || win == WIN_MAP ||
  1269.         win == WIN_MESSAGE ) {
  1270.         if ( flags . window_inited ) {
  1271.             if ( flags . tombstone && killer ) {
  1272.                 /* Prepare for the coming of the tombstone window. */
  1273.                 mono_font ( ) ;
  1274.                 full_screen = TRUE ;
  1275.             }
  1276.             return ;
  1277.         }
  1278.     }
  1279.  
  1280.     kind = ( ( WindowPeek ) theWindow ) -> windowKind - WIN_BASE_KIND ;
  1281.     visible = ( ( WindowPeek ) theWindow ) -> visible ;
  1282.  
  1283.     if ( ! visible || ( kind != NHW_MENU && kind != NHW_TEXT ) ) {
  1284.         DisposeWindow ( theWindow ) ;
  1285.         if ( aWin -> windowText ) {
  1286.             DisposHandle ( aWin -> windowText ) ;
  1287.         }
  1288.         aWin -> theWindow = (WindowPtr) NULL ;
  1289.         aWin -> windowText = (Handle) NULL ;
  1290.     }
  1291. }
  1292.  
  1293.  
  1294. void
  1295. mac_number_pad ( int pad )
  1296. {
  1297.     macPad = pad ;
  1298. }
  1299.  
  1300.  
  1301. void
  1302. trans_num_keys(EventRecord *theEvent)
  1303. {
  1304.     if (macPad) {
  1305.         Handle h = GetResource('Nump', theEvent->modifiers & shiftKey ? 129 : 128);
  1306.         if (h) {
  1307.             short *ab = (short *)*h;
  1308.             int i = ab[0];
  1309.             while (i) {
  1310.                 if ((theEvent->message & keyCodeMask) == (ab[i] & keyCodeMask)) {
  1311.                     theEvent->message = ab[i];
  1312.                     break;
  1313.                 }
  1314.                 --i;
  1315.             }
  1316.         }
  1317.     }
  1318. }
  1319.  
  1320.  
  1321. /*
  1322.  * Note; theWindow may very well be NULL here, since keyDown may call
  1323.  * it when theres no window !!!
  1324.  */
  1325. void
  1326. GeneralKey ( EventRecord * theEvent , WindowPtr theWindow )
  1327. {
  1328.     int i ;
  1329.  
  1330.     trans_num_keys ( theEvent ) ;
  1331.  
  1332.     addToKeyQueue ( topl_resp_key ( theEvent -> message & 0xff ) , 1 ) ;
  1333. }
  1334.  
  1335.  
  1336. static void
  1337. macKeyNull ( EventRecord * theEvent , WindowPtr theWindow )
  1338. {
  1339.     GeneralKey ( theEvent , theWindow ) ;
  1340. }
  1341.  
  1342.  
  1343. static void
  1344. macKeyMessage ( EventRecord * theEvent , WindowPtr theWindow )
  1345. {
  1346.     GeneralKey ( theEvent , theWindow ) ;
  1347. }
  1348.  
  1349.  
  1350. static void
  1351. macKeyStatus ( EventRecord * theEvent , WindowPtr theWindow )
  1352. {
  1353.     GeneralKey ( theEvent , theWindow ) ;
  1354. }
  1355.  
  1356.  
  1357. static void
  1358. macKeyMap ( EventRecord * theEvent , WindowPtr theWindow )
  1359. {
  1360.     GeneralKey ( theEvent , theWindow ) ;
  1361. }
  1362.  
  1363.  
  1364. static void
  1365. macKeyMenu ( EventRecord * theEvent , WindowPtr theWindow )
  1366. {
  1367.     if ( filter_scroll_key ( theEvent -> message & 0xff ,
  1368.         ( NhWindow * ) GetWRefCon ( theWindow ) ) ) {
  1369.         GeneralKey ( theEvent , theWindow ) ;
  1370.     }
  1371. }
  1372.  
  1373.  
  1374. static void
  1375. macKeyText ( EventRecord * theEvent , WindowPtr theWindow )
  1376. {
  1377.     char c = filter_scroll_key ( theEvent -> message & 0xff ,
  1378.                                  ( NhWindow * ) GetWRefCon ( theWindow ) ) ;
  1379.     if ( c )
  1380.         if ( inSelect == WIN_ERR && ClosingWindowChar ( c ) ) {
  1381.             HideWindow ( theWindow ) ;
  1382.             destroy_nhwindow ( ( NhWindow * ) GetWRefCon ( theWindow ) - theWindows ) ;
  1383.         } else {
  1384.             GeneralKey ( theEvent , theWindow ) ;
  1385.         }
  1386. }
  1387.  
  1388.  
  1389. static void
  1390. macClickNull ( EventRecord * theEvent , WindowPtr theWindow )
  1391. {
  1392.     if ( ! theEvent || ! theWindow ) {
  1393.         Debugger ( ) ;
  1394.     }
  1395. }
  1396.  
  1397.  
  1398. static void
  1399. macClickMessage ( EventRecord * theEvent , WindowPtr theWindow )
  1400. {
  1401.     int r_idx = 0;
  1402.     Point mouse = theEvent->where;
  1403.     GlobalToLocal(&mouse);
  1404.     while (topl_resp[r_idx]) {
  1405.         Rect frame;
  1406.         topl_resp_rect(r_idx, &frame);
  1407.         InsetRect(&frame, 1, 1);
  1408.         if (PtInRect(mouse, &frame)) {
  1409.  
  1410.             Boolean in_btn = true;
  1411.             InvertRect(&frame);
  1412.             while (WaitMouseUp()) {
  1413.                 SystemTask();
  1414.                 GetMouse(&mouse);
  1415.                 if (PtInRect(mouse, &frame) != in_btn) {
  1416.                     in_btn = !in_btn;
  1417.                     InvertRect(&frame);
  1418.                 }
  1419.             }
  1420.             if (in_btn) {
  1421.                 InvertRect(&frame);
  1422.                 addToKeyQueue ( topl_resp [ r_idx ] , 1 ) ;
  1423.             }
  1424.             return;
  1425.  
  1426.         }
  1427.         ++r_idx;
  1428.     }
  1429. }
  1430.  
  1431.  
  1432. static void
  1433. macClickStatus ( EventRecord * theEvent , WindowPtr theWindow )
  1434. {
  1435.     if ( ! theEvent || ! theWindow ) {
  1436.         Debugger ( ) ;
  1437.     }
  1438. }
  1439.  
  1440.  
  1441. static void
  1442. macClickMap ( EventRecord * theEvent , WindowPtr theWindow )
  1443. {
  1444.     if ( ! theEvent || ! theWindow ) {
  1445.         Debugger ( ) ;
  1446.     }
  1447.     {
  1448.         NhWindow * nhw = ( NhWindow * ) GetWRefCon ( theWindow ) ;
  1449.         Point where ;
  1450.         short posX , posY ;
  1451.         short sector ;
  1452.         char theDirectionChar [ 18 ] = {
  1453.             ' ' , 'k' , 'u' , 'l' , 'n' , 'j' , 'b' , 'h' , 'y' ,
  1454.             'o' , 'K' , 'U' , 'L' , 'N' , 'J' , 'B' , 'H' , 'Y' ,
  1455.         } ;
  1456.  
  1457.         where = theEvent -> where ;
  1458.         GlobalToLocal ( & where ) ;
  1459.         posX = where . h / nhw -> charWidth ;
  1460.         posY = where . v / nhw -> charHeight ;
  1461.  
  1462.     /* 0 is ON, 1 is top, then clockwise */
  1463.         sector = clickSector ( u . ux , u . uy , posX , posY ) ;
  1464.         if ( theEvent -> modifiers & shiftKey ) {
  1465.             sector += 9 ;
  1466.         }
  1467.         addToKeyQueue ( theDirectionChar [ sector ] , 0 ) ;
  1468.  
  1469.         gClickedToMove = 1 ;
  1470.     }
  1471. }
  1472.  
  1473. static amtToScroll = 0 ;
  1474. static NhWindow * winToScroll = (NhWindow *) NULL ;
  1475.  
  1476. static pascal void
  1477. Up ( ControlHandle theBar , short part )
  1478. {
  1479.     EventRecord fake ;
  1480.     short now = GetCtlValue ( theBar ) ;
  1481.     short min = GetCtlMin ( theBar ) ;
  1482.     Rect r ;
  1483.     RgnHandle rgn = NewRgn ( ) ;
  1484.  
  1485.     if ( ! part ) {
  1486.         return ;
  1487.     }
  1488.  
  1489.     if ( now - min < amtToScroll ) {
  1490.         amtToScroll = now - min ;
  1491.     }
  1492.     if ( ! amtToScroll ) {
  1493.         return ;
  1494.     }
  1495.     SetCtlValue ( theBar , now - amtToScroll ) ;
  1496.     winToScroll -> scrollPos = now - amtToScroll ;
  1497.     r = winToScroll -> theWindow -> portRect ;
  1498.     r . right -= 15 ;
  1499.     ScrollRect ( & r , 0 , amtToScroll * winToScroll -> charHeight , rgn ) ;
  1500.     if ( rgn ) {
  1501.         InvalRgn ( rgn ) ;
  1502.         r . top = r . bottom - 16 ;
  1503.         r . left = r . right ;
  1504.         r . right += 15 ;
  1505.         InvalRect ( & r ) ;
  1506.         BeginUpdate ( winToScroll -> theWindow ) ;
  1507.     }
  1508.     winToScroll -> updateFunc  ( & fake , winToScroll -> theWindow ) ;
  1509.     if ( rgn ) {
  1510.         EndUpdate ( winToScroll -> theWindow ) ;
  1511.         DisposeRgn ( rgn ) ;
  1512.     }
  1513. }
  1514.  
  1515.  
  1516. static pascal void
  1517. Down ( ControlHandle theBar , short part )
  1518. {
  1519.     EventRecord fake ;
  1520.     short now = GetCtlValue ( theBar ) ;
  1521.     short max = GetCtlMax ( theBar ) ;
  1522.     Rect r ;
  1523.     RgnHandle rgn = NewRgn ( ) ;
  1524.  
  1525.     if ( ! part ) {
  1526.         return ;
  1527.     }
  1528.  
  1529.     if ( max - now < amtToScroll ) {
  1530.         amtToScroll = max - now ;
  1531.     }
  1532.     if ( ! amtToScroll ) {
  1533.         return ;
  1534.     }
  1535.     SetCtlValue ( theBar , now + amtToScroll ) ;
  1536.     winToScroll -> scrollPos = now + amtToScroll ;
  1537.     r = winToScroll -> theWindow -> portRect ;
  1538.     r . right -= 15 ;
  1539.     ScrollRect ( & r , 0 , - amtToScroll * winToScroll -> charHeight , rgn ) ; 
  1540.     if ( rgn ) {
  1541.         InvalRgn ( rgn ) ;
  1542.         r . top = r . bottom - 16 ;
  1543.         r . left = r . right ;
  1544.         r . right += 15 ;
  1545.         InvalRect ( & r ) ;
  1546.         BeginUpdate ( winToScroll -> theWindow ) ;
  1547.     }
  1548.     winToScroll -> updateFunc  ( & fake , winToScroll -> theWindow ) ;
  1549.     if ( rgn ) {
  1550.         EndUpdate ( winToScroll -> theWindow ) ;
  1551.         DisposeRgn ( rgn ) ;
  1552.     }
  1553. }
  1554.  
  1555.  
  1556. static void
  1557. DoScrollBar ( Point p , short code , ControlHandle theBar , NhWindow * aWin ,
  1558.     WindowPtr theWindow )
  1559. {
  1560.     pascal void ( * func ) ( ControlHandle , short ) = 0 ;
  1561.  
  1562.     winToScroll = aWin ;
  1563.     switch ( code ) {
  1564.     case inUpButton :
  1565.         func = Up ;
  1566.         amtToScroll = 1 ;
  1567.         break ;
  1568.     case inDownButton :
  1569.         func = Down ;
  1570.         amtToScroll = 1 ;
  1571.         break ;
  1572.     case inPageUp :
  1573.         func = Up ;
  1574.         amtToScroll = ( theWindow -> portRect . bottom - theWindow ->
  1575.             portRect . top ) / aWin -> charHeight ;
  1576.         break ;
  1577.     case inPageDown :
  1578.         func = Down ;
  1579.         amtToScroll = ( theWindow -> portRect . bottom - theWindow ->
  1580.             portRect . top ) / aWin -> charHeight ;
  1581.         break ;
  1582.     default :
  1583.         break ;
  1584.     }
  1585.  
  1586.     ( void ) TrackControl ( theBar , p , ( ProcPtr ) func );
  1587.     if ( ! func ) {
  1588.         if ( aWin -> scrollPos != GetCtlValue ( theBar ) ) {
  1589.             aWin -> scrollPos = GetCtlValue ( theBar ) ;
  1590.             InvalRect ( & ( theWindow -> portRect ) ) ;
  1591.         }
  1592.     }
  1593. }
  1594.  
  1595.  
  1596. int
  1597. filter_scroll_key(const int ch, NhWindow *aWin)
  1598. {
  1599.     if (aWin->scrollBar && GetCtlValue(aWin->scrollBar) < GetCtlMax(aWin->scrollBar)) {
  1600.         winToScroll = aWin;
  1601.         SetPort(aWin->theWindow);
  1602.         if (ch == CHAR_BLANK) {
  1603.             amtToScroll = ( aWin->theWindow->portRect.bottom
  1604.                           - aWin->theWindow->portRect.top ) / aWin->charHeight;
  1605.             Down(aWin->scrollBar, inPageDown);
  1606.             return 0;
  1607.         }
  1608.         if (ch == CHAR_CR || ch == CHAR_LF) {
  1609.             amtToScroll = 1;
  1610.             Down(aWin->scrollBar, inDownButton);
  1611.             return 0;
  1612.         }
  1613.     }
  1614.     return ch;
  1615. }
  1616.  
  1617.  
  1618. static void
  1619. macClickMenu ( EventRecord * theEvent , WindowPtr theWindow )
  1620. {
  1621.     Point p ;
  1622.     short hiRow = -1 , loRow = -1 ;
  1623.     Rect r ;
  1624.     NhWindow * aWin = ( NhWindow * ) GetWRefCon ( theWindow ) ;
  1625.  
  1626.     r = theWindow -> portRect ;
  1627.     if ( aWin -> scrollBar && ( * aWin -> scrollBar ) -> contrlVis ) {
  1628.         short code ;
  1629.         Point p = theEvent -> where ;
  1630.         ControlHandle theBar ;
  1631.  
  1632.         r . right -= SBARWIDTH ;
  1633.         GlobalToLocal ( & p ) ;
  1634.         code = FindControl ( p , theWindow , & theBar ) ;
  1635.         if ( code ) {
  1636.             DoScrollBar ( p , code , theBar , aWin , theWindow ) ;
  1637.             return ;
  1638.         }
  1639.         if ( p . h >= r . right )
  1640.             return ;
  1641.     }
  1642.     r . top = r . bottom = 0 ;
  1643.     if ( inSelect != WIN_ERR ) {
  1644.         do {
  1645.             SystemTask ( ) ;
  1646.             GetMouse ( & p ) ;
  1647.             if ( p . h < theWindow -> portRect . left || p . h > theWindow ->
  1648.                 portRect . right || p . v < 0 || p . v > theWindow -> portRect .
  1649.                 bottom ) {
  1650.                 hiRow = -1 ;
  1651.             } else {
  1652.                 hiRow = p . v / aWin -> charHeight ;
  1653.                 if ( hiRow >= aWin -> lin )
  1654.                     hiRow = -1 ;
  1655.             }
  1656.             if ( hiRow != loRow ) {
  1657.                 if ( loRow > -1 && aWin -> itemChars [ loRow + aWin ->
  1658.                     scrollPos ] ) {
  1659.                     r . top = loRow * aWin -> charHeight ;
  1660.                     r . bottom = ( loRow + 1 ) * aWin -> charHeight ;
  1661.                     InvertRect ( & r ) ;
  1662.                 }
  1663.                 loRow = hiRow ;
  1664.                 if ( loRow > -1 && aWin -> itemChars [ loRow + aWin ->
  1665.                     scrollPos ] ) {
  1666.                     r . top = loRow * aWin -> charHeight ;
  1667.                     r . bottom = ( loRow + 1 ) * aWin -> charHeight ;
  1668.                     InvertRect ( & r ) ;
  1669.                 }
  1670.             }
  1671.         } while ( StillDown ( ) ) ;
  1672.         if ( loRow > -1 && aWin -> itemChars [ loRow + aWin -> scrollPos ] ) {
  1673.             InvertRect ( & r ) ;
  1674.             addToKeyQueue ( aWin -> itemChars [ loRow + aWin -> scrollPos ] , 1 ) ;
  1675.         }
  1676.     }
  1677. }
  1678.  
  1679.  
  1680. static void
  1681. macClickText ( EventRecord * theEvent , WindowPtr theWindow )
  1682. {
  1683.     short hiRow = -1 , loRow = -1 ;
  1684.     Rect r ;
  1685.     NhWindow * aWin = ( NhWindow * ) GetWRefCon ( theWindow ) ;
  1686.  
  1687.     r = theWindow -> portRect ;
  1688.     if ( aWin -> scrollBar && ( * aWin -> scrollBar ) -> contrlVis ) {
  1689.         short code ;
  1690.         Point p = theEvent -> where ;
  1691.         ControlHandle theBar ;
  1692.  
  1693.         r . right -= SBARWIDTH ;
  1694.         GlobalToLocal ( & p ) ;
  1695.         code = FindControl ( p , theWindow , & theBar ) ;
  1696.         if ( code ) {
  1697.             DoScrollBar ( p , code , theBar , aWin , theWindow ) ;
  1698.             return ;
  1699.         }
  1700.     }
  1701. }
  1702.  
  1703.  
  1704. static void
  1705. macUpdateNull ( EventRecord * theEvent , WindowPtr theWindow )
  1706. {
  1707.     if ( ! theEvent || ! theWindow ) {
  1708.         Debugger ( ) ;
  1709.     }
  1710. }
  1711.  
  1712.  
  1713. static void
  1714. draw_growicon_vert_only(WindowPtr wind) {
  1715.     GrafPtr org_port;
  1716.     RgnHandle org_clip = NewRgn();
  1717.     Rect r = wind->portRect;
  1718.     r.left = r.right - SBARWIDTH;
  1719.  
  1720.     GetPort(&org_port);
  1721.     SetPort(wind);
  1722.     GetClip(org_clip);
  1723.     ClipRect(&r);
  1724.     DrawGrowIcon(wind);
  1725.     SetClip(org_clip);
  1726.     DisposeRgn(org_clip);
  1727.     SetPort(org_port);
  1728. }
  1729.  
  1730.  
  1731. static void
  1732. macUpdateMessage ( EventRecord * theEvent , WindowPtr theWindow )
  1733. {
  1734.     RgnHandle org_clip = NewRgn(), clip = NewRgn();
  1735.     Rect r = theWindow -> portRect ;
  1736.     NhWindow * aWin = ( NhWindow * ) GetWRefCon ( theWindow ) ;
  1737.     int l ;
  1738.  
  1739.     if ( ! theEvent ) {
  1740.         Debugger ( ) ;
  1741.     }
  1742.  
  1743.     GetClip(org_clip);
  1744.  
  1745.     DrawGrowIcon(theWindow);
  1746.  
  1747.     l = 0;
  1748.     while (topl_resp[l]) {
  1749.         StringPtr name;
  1750.         unsigned char tmp[2];
  1751.         FontInfo font;
  1752.         Rect frame;
  1753.         topl_resp_rect(l, &frame);
  1754.         switch (topl_resp[l]) {
  1755.             case 'y':
  1756.                 name = "\pyes";
  1757.                 break;
  1758.             case 'n':
  1759.                 name = "\pno";
  1760.                 break;
  1761.             case 'N':
  1762.                 name = "\pNone";
  1763.                 break;
  1764.             case 'a':
  1765.                 name = "\pall";
  1766.                 break;
  1767.             case 'q':
  1768.                 name = "\pquit";
  1769.                 break;
  1770.             case CHAR_ANY:
  1771.                 name = "\pany key";
  1772.                 break;
  1773.             default:
  1774.                 tmp[0] = 1;
  1775.                 tmp[1] = topl_resp[l];
  1776.                 name = &tmp;
  1777.                 break;
  1778.         }
  1779.         TextFont(geneva);
  1780.         TextSize(9);
  1781.         GetFontInfo(&font);
  1782.         MoveTo((frame.left + frame.right  - StringWidth(name)) / 2,
  1783.                (frame.top  + frame.bottom + font.ascent-font.descent-font.leading-1) / 2);
  1784.         DrawString(name);
  1785.         PenNormal();
  1786.         if (l == topl_def_idx)
  1787.             PenSize(2, 2);
  1788.         FrameRoundRect(&frame, 4, 4);
  1789.         ++l;
  1790.     }
  1791.  
  1792.     r . right -= SBARWIDTH + 2;
  1793.     r . bottom -= SBARHEIGHT + 1;
  1794.     /* Clip to the portrect - scrollbar/growicon *before* adjusting the rect
  1795.         to be larger than the size of the window (!) */
  1796.     RectRgn(clip, &r);
  1797.     if ( r . right < MIN_RIGHT )
  1798.         r . right = MIN_RIGHT ;
  1799.  
  1800.     if (in_topl_mode()) {
  1801.         RgnHandle topl_rgn = NewRgn();
  1802.         Rect topl_r = r;
  1803.         for (l = aWin->windowTextLen - 1; --l >= aWin->textBase; )
  1804.             if ((*aWin->windowText)[l] == CHAR_CR)
  1805.                 topl_r.top += aWin->charHeight;
  1806.         l = (*top_line)->destRect.right - (*top_line)->destRect.left;
  1807.         (*top_line)->viewRect = topl_r;
  1808.         (*top_line)->destRect = topl_r;
  1809.         if (l != topl_r.right - topl_r.left)
  1810.             TECalText(top_line);
  1811.         TEUpdate(&topl_r, top_line);
  1812.         RectRgn(topl_rgn, &topl_r);
  1813.         DiffRgn(clip, topl_rgn, clip);
  1814.         DisposeRgn(topl_rgn);
  1815.     }
  1816.  
  1817.     SectRgn(clip, org_clip, clip);
  1818.     SetClip(clip);
  1819.     DisposeRgn(clip);
  1820.  
  1821.     TextFont ( aWin -> fontNum ) ;
  1822.     TextSize ( aWin -> fontSize ) ;
  1823.     HLock ( aWin -> windowText ) ;
  1824.     TextBox ( * ( aWin -> windowText ) + aWin -> textBase , aWin ->
  1825.         windowTextLen - aWin -> textBase , & r , teJustLeft ) ;
  1826.     HUnlock ( aWin -> windowText ) ;
  1827.  
  1828.     SetClip(org_clip);
  1829.     DisposeRgn(org_clip);
  1830. }
  1831.  
  1832.  
  1833. static void
  1834. macUpdateStatus ( EventRecord * theEvent , WindowPtr theWindow )
  1835. {
  1836.     NhWindow * nhw = ( NhWindow * ) GetWRefCon ( theWindow ) ;
  1837.     int height = nhw -> charHeight ;
  1838.     int leading = nhw -> leading ;
  1839.     int i ;
  1840.  
  1841.     if ( ! theEvent ) {
  1842.         Debugger ( ) ;
  1843.     }
  1844.  
  1845.     TextFont ( nhw -> fontNum ) ;
  1846.     TextSize ( nhw -> fontSize ) ;
  1847.     HLock ( nhw -> windowText ) ;
  1848.     for ( i = 0 ; i < NUM_STAT_ROWS ; i ++ ) {
  1849.         MoveTo ( 0 , ( i + 1 ) * height - leading ) ;
  1850.         DrawText ( ( ( StatusData * ) ( * nhw -> windowText ) ) -> map [ i ] ,
  1851.             0 , NUM_COLS ) ;
  1852.     }
  1853.     HUnlock ( nhw -> windowText ) ;
  1854. }
  1855.  
  1856.  
  1857. static void
  1858. DrawMapCursor ( NhWindow * nhw )
  1859. {
  1860.     Rect r ;
  1861.  
  1862.     /*
  1863.      * We only want a cursor in the map
  1864.      * window...
  1865.      */
  1866.     if ( ! WIN_MAP || nhw - theWindows != WIN_MAP )
  1867.         return ;
  1868.  
  1869.     r . left = nhw -> cursor . h * nhw -> charWidth ;
  1870.     r . right = ( nhw -> cursor . h + 1 ) * nhw -> charWidth ;
  1871.     r . top = nhw -> cursor . v * nhw -> charHeight ;
  1872.     r . bottom = ( nhw -> cursor . v + 1 ) * nhw -> charHeight ;
  1873.     InvertRect ( & r ) ;
  1874.     nhw -> cursorDrawn = 1 ;
  1875. }
  1876.  
  1877.  
  1878. static void
  1879. macUpdateMap ( EventRecord * theEvent , WindowPtr theWindow )
  1880. {
  1881.     NhWindow * nhw = ( NhWindow * ) GetWRefCon ( theWindow ) ;
  1882.     int height = nhw -> charHeight ;
  1883.     int leading = nhw -> leading ;
  1884.     int i ;
  1885.  
  1886.     if ( ! theEvent ) {
  1887.         Debugger ( ) ;
  1888.     }
  1889.  
  1890.     TextFont ( nhw -> fontNum ) ;
  1891.     TextSize ( nhw -> fontSize ) ;
  1892.     HLock ( nhw -> windowText ) ;
  1893.     for ( i = 0 ; i < NUM_ROWS ; i ++ ) {
  1894.         MoveTo ( 0 , ( i + 1 ) * height - leading ) ;
  1895.         DrawText ( ( ( MapData * ) ( * nhw -> windowText ) ) -> map [ i ] ,
  1896.             0 , NUM_COLS ) ;
  1897.     }
  1898.     HUnlock ( nhw -> windowText ) ;
  1899.     if ( nhw -> cursorDrawn ) {
  1900.         DrawMapCursor ( nhw ) ;
  1901.     }
  1902. }
  1903.  
  1904.  
  1905. static void
  1906. macUpdateMenu ( EventRecord * theEvent , WindowPtr theWindow )
  1907. {
  1908.     Rect r = theWindow -> portRect ;
  1909.     Rect r2 = r ;
  1910.     NhWindow * aWin = ( NhWindow * ) GetWRefCon ( theWindow ) ;
  1911.     RgnHandle h ;
  1912.     Boolean vis ;
  1913.  
  1914.     if ( ! theEvent ) {
  1915.         Debugger ( ) ;
  1916.     }
  1917.  
  1918.     draw_growicon_vert_only(theWindow);
  1919.  
  1920.     r2 . left = r2 . right - SBARWIDTH ;
  1921.     r2 . right += 1 ;
  1922.     r2 . top -= 1 ;
  1923.     vis = ( r2 . bottom > r2 . top + 50 ) ;
  1924.     DrawControls ( theWindow ) ;
  1925.  
  1926.     h = (RgnHandle) NULL ;
  1927.     if ( vis && ( h = NewRgn ( ) ) ) {
  1928.         RgnHandle tmp = NewRgn ( ) ;
  1929.         if ( ! tmp ) {
  1930.             DisposeRgn ( h ) ;
  1931.             h = (RgnHandle) NULL ;
  1932.         } else {
  1933.             GetClip ( h ) ;
  1934.             RectRgn ( tmp , & r2 ) ;
  1935.             DiffRgn ( h , tmp , tmp ) ;
  1936.             SetClip ( tmp ) ;
  1937.             DisposeRgn ( tmp ) ;
  1938.         }
  1939.     }
  1940.     if ( r . right < MIN_RIGHT )
  1941.         r . right = MIN_RIGHT ;
  1942.     r . top -= aWin -> scrollPos * aWin -> charHeight ;
  1943.     HLock ( aWin -> windowText ) ;
  1944.     TextBox ( * ( aWin -> windowText ) + aWin -> textBase , aWin ->
  1945.         windowTextLen - aWin -> textBase , & r , teJustLeft ) ;
  1946.     HUnlock ( aWin -> windowText ) ;
  1947.     if ( h ) {
  1948.         SetClip ( h ) ;
  1949.         DisposeRgn ( h ) ;
  1950.     }
  1951. }
  1952.  
  1953.  
  1954. static void
  1955. macUpdateText ( EventRecord * theEvent , WindowPtr theWindow )
  1956. {
  1957.     Rect r = theWindow -> portRect ;
  1958.     Rect r2 = r ;
  1959.     NhWindow * aWin = ( NhWindow * ) GetWRefCon ( theWindow ) ;
  1960.     RgnHandle h ;
  1961.     Boolean vis ;
  1962.  
  1963.     if ( ! theEvent ) {
  1964.         Debugger ( ) ;
  1965.     }
  1966.  
  1967.     r2 . left = r2 . right - SBARWIDTH ;
  1968.     r2 . right += 1 ;
  1969.     r2 . top -= 1 ;
  1970.     vis = ( r2 . bottom > r2 . top + 50 ) ;
  1971.     DrawControls ( theWindow ) ;
  1972.  
  1973.     h = (RgnHandle) NULL ;
  1974.     if ( vis && ( h = NewRgn ( ) ) ) {
  1975.         RgnHandle tmp = NewRgn ( ) ;
  1976.         if ( ! tmp ) {
  1977.             DisposeRgn ( h ) ;
  1978.             h = (RgnHandle) NULL ;
  1979.         } else {
  1980.             GetClip ( h ) ;
  1981.             RectRgn ( tmp , & r2 ) ;
  1982.             DiffRgn ( h , tmp , tmp ) ;
  1983.             SetClip ( tmp ) ;
  1984.             DisposeRgn ( tmp ) ;
  1985.         }
  1986.     }
  1987.     if ( r . right < MIN_RIGHT )
  1988.         r . right = MIN_RIGHT ;
  1989.     r . top -= aWin -> scrollPos * aWin -> charHeight ;
  1990.     r . right -= SBARWIDTH;
  1991.     HLock ( aWin -> windowText ) ;
  1992.     TextBox ( * ( aWin -> windowText ) + aWin -> textBase , aWin ->
  1993.         windowTextLen - aWin -> textBase , & r , teJustLeft ) ;
  1994.     HUnlock ( aWin -> windowText ) ;
  1995.     draw_growicon_vert_only(theWindow);
  1996.     if ( h ) {
  1997.         SetClip ( h ) ;
  1998.         DisposeRgn ( h ) ;
  1999.     }
  2000. }
  2001.  
  2002.  
  2003. static void
  2004. macCursorNull ( EventRecord * theEvent , WindowPtr theWindow , RgnHandle mouseRgn )
  2005. {
  2006.     Rect r = { -1 , -1 , 2 , 2 } ;
  2007.  
  2008.     InitCursor ( ) ;
  2009.     OffsetRect ( & r , theEvent -> where . h , theEvent -> where . v ) ;
  2010.     RectRgn ( mouseRgn , & r ) ;
  2011. }
  2012.  
  2013.  
  2014. static void
  2015. macCursorMessage ( EventRecord * theEvent , WindowPtr theWindow , RgnHandle mouseRgn )
  2016. {
  2017.     Rect r = { -1 , -1 , 2 , 2 } ;
  2018.  
  2019.     InitCursor ( ) ;
  2020.     OffsetRect ( & r , theEvent -> where . h , theEvent -> where . v ) ;
  2021.     RectRgn ( mouseRgn , & r ) ;
  2022. }
  2023.  
  2024.  
  2025. static void
  2026. macCursorStatus ( EventRecord * theEvent , WindowPtr theWindow , RgnHandle mouseRgn )
  2027. {
  2028.     Rect r = { -1 , -1 , 2 , 2 } ;
  2029.  
  2030.     InitCursor ( ) ;
  2031.     OffsetRect ( & r , theEvent -> where . h , theEvent -> where . v ) ;
  2032.     RectRgn ( mouseRgn , & r ) ;
  2033. }
  2034.  
  2035.  
  2036. static void
  2037. macCursorMap ( EventRecord * theEvent , WindowPtr theWindow , RgnHandle mouseRgn )
  2038. {
  2039.     Point where ;
  2040.     CursHandle ch ;
  2041.     GrafPtr gp ;
  2042.     NhWindow * nhw = ( NhWindow * ) GetWRefCon ( theWindow ) ;
  2043.     Rect r = { 0 , 0 , 1 , 1 } ;
  2044.  
  2045.     GetPort ( & gp ) ;
  2046.     SetPort ( theWindow ) ;
  2047.  
  2048.     where = theEvent -> where ;
  2049.     GlobalToLocal ( & where ) ;
  2050.     ch = GetCursor ( 512 + clickSector ( u . ux , u . uy , where . h / nhw -> charWidth ,
  2051.         where . v / nhw -> charHeight ) ) ;
  2052.     if ( ch ) {
  2053.  
  2054.         HLock ( ( Handle ) ch ) ;
  2055.         SetCursor ( * ch ) ;
  2056.         ReleaseResource ( ( Handle ) ch ) ;
  2057.  
  2058.     } else {
  2059.  
  2060.         InitCursor ( ) ;
  2061.     }
  2062.     OffsetRect ( & r , theEvent -> where . h , theEvent -> where . v ) ;
  2063.     RectRgn ( mouseRgn , & r ) ;
  2064.  
  2065.     SetPort ( gp ) ;
  2066. }
  2067.  
  2068.  
  2069. static void
  2070. macCursorMenu ( EventRecord * theEvent , WindowPtr theWindow , RgnHandle mouseRgn )
  2071. {
  2072.     Rect r = { -1 , -1 , 2 , 2 } ;
  2073.  
  2074.     InitCursor ( ) ;
  2075.     OffsetRect ( & r , theEvent -> where . h , theEvent -> where . v ) ;
  2076.     RectRgn ( mouseRgn , & r ) ;
  2077. }
  2078.  
  2079.  
  2080. static void
  2081. macCursorText ( EventRecord * theEvent , WindowPtr theWindow , RgnHandle mouseRgn )
  2082. {
  2083.     Rect r = { -1 , -1 , 2 , 2 } ;
  2084.  
  2085.     InitCursor ( ) ;
  2086.     OffsetRect ( & r , theEvent -> where . h , theEvent -> where . v ) ;
  2087.     RectRgn ( mouseRgn , & r ) ;
  2088. }
  2089.  
  2090.  
  2091. void
  2092. UpdateMenus ( void )
  2093. {
  2094.     WindowPeek w = ( WindowPeek ) FrontWindow ( ) ;
  2095.     Boolean enable = FALSE ;
  2096.     int i ;
  2097.  
  2098.     /* All menu items are OK, except the "edit" menu */
  2099.  
  2100.     if ( w && w -> windowKind < 0 ) {
  2101.         enable = TRUE ;
  2102.     }
  2103.     for ( i = 1 ; i < 7 ; i ++ ) {
  2104.         if ( i == 2 )
  2105.             continue ;
  2106.         if ( enable ) {
  2107.             EnableItem ( editMenu , i ) ;
  2108.         } else {
  2109.             DisableItem ( editMenu , i ) ;
  2110.         }
  2111.     }
  2112. }
  2113.  
  2114.  
  2115. void
  2116. DoMenu ( long choise )
  2117. {
  2118.     WindowPeek w = ( WindowPeek ) FrontWindow ( ) ;
  2119.     short menu = choise >> 16 ;
  2120.     short item = choise & 0xffff ;
  2121.     int i ;
  2122.     Str255 str ;
  2123.  
  2124.     HiliteMenu ( menu ) ;
  2125.  
  2126.     if ( menu == kHMHelpMenuID ) {
  2127.         menu = 128 ;
  2128.         item = 2 ;
  2129.     }
  2130.  
  2131.     if ( menu == 128 && item > 2 ) /* apple, DA */ {
  2132.         GetItem ( appleMenu , item , str ) ;
  2133.         OpenDeskAcc ( str ) ;
  2134.     } else if ( menu == 130 ) /* edit */ {
  2135.         SystemEdit ( item - 1 ) ;
  2136.     } else {
  2137.         GetIndString ( str , menu + 1 , item ) ;
  2138.         if ( str [ 0 ] > QUEUE_LEN ) {
  2139.             error ( "Too long command : menul %d item %d" , menu , item ) ;
  2140.             str [ 0 ] = QUEUE_LEN ;
  2141.         }
  2142.         for ( i = 1 ; i <= str [ 0 ] ; i ++ ) {
  2143.             addToKeyQueue ( str [ i ] , 0 ) ;
  2144.         }
  2145.     }
  2146.  
  2147.     HiliteMenu ( 0 ) ;
  2148. }
  2149.  
  2150.  
  2151. void
  2152. HandleKey ( EventRecord * theEvent )
  2153. {
  2154.     WindowPtr theWindow = FrontWindow ( ) ;
  2155.  
  2156.     if ( theEvent -> modifiers & cmdKey ) {
  2157.         if ( theEvent -> message & 0xff == '.' ) {
  2158.             int i ;
  2159. /* Flush key queue */
  2160.             for ( i = 0 ; i < QUEUE_LEN ; i ++ ) {
  2161.                 keyQueue [ i ] = 0 ;
  2162.             }
  2163.             theEvent -> message = '\033' ;
  2164.             goto dispatchKey ;
  2165.         } else {
  2166.             UpdateMenus ( ) ;
  2167.             DoMenu ( MenuKey ( theEvent -> message & 0xff ) ) ;
  2168.         }
  2169.     } else {
  2170.  
  2171. dispatchKey :
  2172.         if ( theWindow ) {
  2173.             ( ( NhWindow * ) GetWRefCon ( theWindow ) ) -> keyFunc ( theEvent ,
  2174.                 theWindow ) ;
  2175.         } else {
  2176.             GeneralKey ( theEvent , (WindowPtr) NULL ) ;
  2177.         }
  2178.     }
  2179. }
  2180.  
  2181.  
  2182. void
  2183. HandleClick ( EventRecord * theEvent )
  2184. {
  2185.     int code ;
  2186.     unsigned long l ;
  2187.     WindowPtr theWindow ;
  2188.     Rect r = ( * GetGrayRgn ( ) ) -> rgnBBox ;
  2189.     NhWindow * aWin ;
  2190.  
  2191.     InsetRect ( & r , 4 , 4 ) ;
  2192.  
  2193.     code = FindWindow ( theEvent -> where , & theWindow ) ;
  2194.     aWin = ( NhWindow * ) GetWRefCon ( theWindow ) ;
  2195.  
  2196.     if ( code != inContent ) {
  2197.         InitCursor ( ) ;
  2198.     } else {
  2199.         aWin -> cursorFunc ( theEvent , theWindow , gMouseRgn ) ; /* Correct direction */
  2200.     }
  2201.     switch ( code ) {
  2202.  
  2203.     case inContent :
  2204.         if ( inSelect == WIN_ERR || aWin - theWindows == inSelect ) {
  2205.             SelectWindow ( theWindow ) ;
  2206.             SetPort ( theWindow ) ;
  2207.             ( ( NhWindow * ) GetWRefCon ( theWindow ) ) -> clickFunc ( theEvent ,
  2208.                 theWindow ) ;
  2209.         } else {
  2210.             nhbell ( ) ;
  2211.         }
  2212.         break ;
  2213.  
  2214.     case inDrag :
  2215.         if ( inSelect == WIN_ERR || aWin - theWindows == inSelect ) {
  2216.             InitCursor ( ) ;
  2217.             DragWindow ( theWindow , theEvent -> where , & r ) ;
  2218.             SaveWindowPos ( theWindow ) ;
  2219.         } else {
  2220.             nhbell ( ) ;
  2221.         }
  2222.         break ;
  2223.  
  2224.     case inGrow :
  2225.         if ( inSelect == WIN_ERR || aWin - theWindows == inSelect ) {
  2226.             InitCursor ( ) ;
  2227.             SetRect ( & r , 80 , 2 * aWin -> charHeight + 1 , r . right ,
  2228.                 r . bottom ) ;
  2229.             l = GrowWindow ( theWindow , theEvent -> where , & r ) ;
  2230.             SizeWindow ( theWindow , l & 0xffff , l >> 16 , FALSE ) ;
  2231.             SaveWindowSize ( theWindow ) ;
  2232.             SetPort ( theWindow ) ;
  2233.             InvalRect ( & ( theWindow -> portRect ) ) ;
  2234.             if ( aWin -> scrollBar ) {
  2235.                 InvalScrollBar ( aWin ) ;
  2236.             }
  2237.         } else {
  2238.             nhbell ( ) ;
  2239.         }
  2240.         break ;
  2241.  
  2242.     case inGoAway :
  2243.         if ( TrackGoAway ( theWindow , theEvent -> where ) ) {
  2244.             if ( aWin - theWindows == BASE_WINDOW && ! flags . window_inited ) {
  2245.                 addToKeyQueue ( '\033' , 1 ) ;
  2246.                 break ;
  2247.             } else {
  2248.                 HideWindow ( theWindow ) ;
  2249.             }
  2250.             if ( inSelect == WIN_ERR || aWin - theWindows != inSelect ) {
  2251.                 destroy_nhwindow ( aWin - theWindows ) ;
  2252.             } else {
  2253.                 addToKeyQueue ( '\033' , 1 ) ;
  2254.             }
  2255.         }
  2256.         break ;
  2257.  
  2258.     case inMenuBar :
  2259.         UpdateMenus ( ) ;
  2260.         DoMenu ( MenuSelect ( theEvent -> where ) ) ;
  2261.         break ;
  2262.  
  2263.     case inSysWindow :
  2264.         SystemClick( theEvent, theWindow ) ;
  2265.         break ;
  2266.  
  2267.     default :
  2268.         break ;
  2269.     }
  2270. }
  2271.  
  2272.  
  2273. void
  2274. HandleUpdate ( EventRecord * theEvent )
  2275. {
  2276.     WindowPtr theWindow = ( WindowPtr ) theEvent -> message ;
  2277.  
  2278.     BeginUpdate ( theWindow ) ;
  2279.     SetPort ( theWindow ) ;
  2280.     EraseRect ( & ( theWindow -> portRect ) ) ;
  2281.     ( ( NhWindow * ) GetWRefCon ( theWindow ) ) -> updateFunc ( theEvent ,
  2282.         theWindow ) ;
  2283.     EndUpdate ( theWindow ) ;
  2284. }
  2285.  
  2286.  
  2287. static void
  2288. DoOsEvt ( EventRecord * theEvent )
  2289. {
  2290.     WindowPtr wp ;
  2291.     short code ;
  2292.  
  2293.     if ( ( theEvent -> message & 0xff000000 ) == 0xfa000000 ) { /* Mouse Moved */
  2294.  
  2295.         code = FindWindow ( theEvent -> where , & wp ) ;
  2296.         if ( code != inContent ) {
  2297.  
  2298.             Rect r = { -1 , -1 , 2 , 2 } ;
  2299.  
  2300.             InitCursor ( ) ;
  2301.             OffsetRect ( & r , theEvent -> where . h , theEvent -> where . v ) ;
  2302.             RectRgn ( gMouseRgn , & r ) ;
  2303.  
  2304.         } else {
  2305.  
  2306.             NhWindow * nhw = ( ( NhWindow * ) GetWRefCon ( wp ) ) ;
  2307.             if ( nhw ) {
  2308.                 nhw -> cursorFunc ( theEvent , wp , gMouseRgn ) ;
  2309.             }
  2310.         }
  2311.     } else {
  2312.  
  2313.         /* Suspend/resume */
  2314.     }
  2315. }
  2316.  
  2317.  
  2318. void
  2319. HandleEvent ( EventRecord * theEvent )
  2320. {
  2321.     switch ( theEvent -> what ) {
  2322.     case autoKey :
  2323.     case keyDown :
  2324.         HandleKey ( theEvent ) ;
  2325.         break ;
  2326.     case updateEvt :
  2327.         HandleUpdate ( theEvent ) ;
  2328.         break ;
  2329.     case mouseDown :
  2330.         HandleClick ( theEvent ) ;
  2331.         break ;
  2332.     case diskEvt :
  2333.         if ( ( theEvent -> message & 0xffff0000 ) != 0 ) {
  2334.  
  2335.             Point p = { 150 , 150 } ;
  2336.             ( void ) DIBadMount ( p , theEvent -> message ) ;
  2337.         }
  2338.         break ;
  2339.     case osEvt :
  2340.         DoOsEvt ( theEvent ) ;
  2341.         break ;
  2342.     default :
  2343.         if ( multi < 0 ) { // Get frozen, so stop repeating
  2344.             int ix;
  2345.             for ( ix = 0 ; ix < QUEUE_LEN ; ix ++ ) {
  2346.                 keyQueue [ ix ] = 0 ;
  2347.             }
  2348.             FlushEvents ( keyDownMask , 0 ) ;
  2349.         }
  2350.         /*
  2351.          * This somewhat elaborate hack is needed to make the menu
  2352.          * commands work right. They're also needed for fast typists.
  2353.          */
  2354.         if ( keyQueue [ 0 ] && in_topl_mode() ) {
  2355.             int i ;
  2356.  
  2357.             theEvent -> what = keyDown ;
  2358.             theEvent -> modifiers = 0 ;
  2359.             theEvent -> message = keyQueue [ 0 ] ;
  2360.  
  2361. /* extract from key queue */
  2362.             for ( i = 0 ; i < QUEUE_LEN - 1 ; i ++ ) {
  2363.                 keyQueue [ i ] = keyQueue [ i + 1 ] ;
  2364.             }
  2365.             keyQueue [ i ] = 0 ;
  2366.             SetPort ( theWindows [ WIN_MESSAGE ] . theWindow ) ;
  2367.             theWindows [ WIN_MESSAGE ] . keyFunc ( theEvent ,
  2368.                 theWindows [ WIN_MESSAGE ] . theWindow ) ;
  2369.         }
  2370.         break ;
  2371.     }
  2372. }
  2373.  
  2374.  
  2375. long doDawdle = 0L ;
  2376.  
  2377. void
  2378. DimMenuBar ( void )
  2379. {
  2380.     DisableItem ( appleMenu , 0 ) ;
  2381.     DisableItem ( fileMenu , 0 ) ;
  2382.     DisableItem ( editMenu , 0 ) ;
  2383.     DisableItem ( extendMenu , 0 ) ;
  2384.     DisableItem ( miscMenu , 0 ) ;
  2385.     DisableItem ( commandsMenu , 0 ) ;
  2386.     DisableItem ( thingsMenu , 0 ) ;
  2387.     DrawMenuBar ( ) ;
  2388. }
  2389.  
  2390.  
  2391. void
  2392. UndimMenuBar ( void )
  2393. {
  2394.     EnableItem ( appleMenu , 0 ) ;
  2395.     EnableItem ( fileMenu , 0 ) ;
  2396.     EnableItem ( editMenu , 0 ) ;
  2397.     EnableItem ( extendMenu , 0 ) ;
  2398.     EnableItem ( miscMenu , 0 ) ;
  2399.     EnableItem ( commandsMenu , 0 ) ;
  2400.     EnableItem ( thingsMenu , 0 ) ;
  2401.     DrawMenuBar ( ) ;
  2402. }
  2403.  
  2404. static int mBarDimmed = 0 ;
  2405.  
  2406. void
  2407. mac_get_nh_event( void )
  2408. {
  2409.     EventRecord anEvent ;
  2410.  
  2411.     if ( ( inSelect != WIN_ERR || ! flags . window_inited || in_topl_mode() ) &&
  2412.         ! mBarDimmed ) {
  2413.         DimMenuBar ( ) ;
  2414.         mBarDimmed = 1 ;
  2415.     } else if ( inSelect == WIN_ERR && flags . window_inited && mBarDimmed &&
  2416.                 ! in_topl_mode() ) {
  2417.         UndimMenuBar ( ) ;
  2418.         mBarDimmed = 0 ;
  2419.     }
  2420.     /*
  2421.      * We want to take care of keys in the buffer as fast as
  2422.      * possible
  2423.      */
  2424.     if ( keyQueue [ 0 ] ) {
  2425.         doDawdle = 0L ;
  2426.     }
  2427.     if ( asyDSC ) {
  2428.         SetPort ( asyDSC -> theWindow ) ;
  2429.         DrawScrollbar ( asyDSC , asyDSC -> theWindow ) ;
  2430.     }
  2431.     if ( ! WaitNextEvent ( -1 , & anEvent , doDawdle , gMouseRgn ) ) {
  2432.         anEvent . what = nullEvent ;
  2433.     }
  2434.     doDawdle = 0L ;
  2435.     HandleEvent ( & anEvent ) ;
  2436.  
  2437.     if (top_line && theWindows) {
  2438.         WindowPeek win = (WindowPeek)theWindows[WIN_MESSAGE].theWindow;
  2439.         if (win && win->visible)
  2440.             TEIdle(top_line);
  2441.     }
  2442. }
  2443.  
  2444.  
  2445. int
  2446. mac_nhgetch( void )
  2447. {
  2448.     int ch ;
  2449.     register int i ;
  2450.  
  2451.     wait_synch ( ) ;
  2452.  
  2453.     if ( flags . window_inited && ! theWindows [ WIN_MAP ] . cursorDrawn &&
  2454.         theWindows [ WIN_MAP ] . theWindow ) {
  2455.         SetPort ( theWindows [ WIN_MAP ] . theWindow ) ;
  2456.         DrawMapCursor ( & theWindows [ WIN_MAP ] ) ;
  2457.     }
  2458.  
  2459.     if ( ! keyQueue [ 0 ] ) {
  2460.         long total , contig ;
  2461.         static char warn = 0 ;
  2462.  
  2463.         PurgeSpace ( & total , & contig ) ;
  2464.         if ( contig < 64000L || total < 256000L ) {
  2465.             if ( ! warn ) {
  2466.                 DebugStr ( ( ConstStr255Param ) "\014Low Memory !" ) ;
  2467.                 warn = 1 ;
  2468.             }
  2469.         } else {
  2470.             warn = 0 ;
  2471.         }
  2472.     }
  2473.  
  2474.     do {
  2475.         doDawdle = ( in_topl_mode() ? GetCaretTime ( ) : 120L ) ;
  2476.         get_nh_event ( ) ;
  2477.         ch = keyQueue [ 0 ] ;
  2478.     } while ( ! ch ) ;
  2479.  
  2480.     if ( ! gClickedToMove ) {
  2481.         ObscureCursor ( ) ;
  2482.     } else {
  2483.         gClickedToMove = 0 ;
  2484.     }
  2485.     for ( i = 0 ; i < QUEUE_LEN - 1 ; i ++ ) {
  2486.         keyQueue [ i ] = keyQueue [ i + 1 ] ;
  2487.     }
  2488.     keyQueue [ i ] = 0 ;
  2489.  
  2490. #ifdef MAC_THINKC5
  2491.     if (ch == '\r') ch = '\n';
  2492. #endif
  2493.  
  2494.     return ch ;
  2495. }
  2496.  
  2497.  
  2498. void
  2499. mac_delay_output( void )
  2500. {
  2501.     long destTicks = TickCount ( ) + 1 ;
  2502.  
  2503.     while ( TickCount ( ) < destTicks ) {
  2504.         wait_synch ( ) ;
  2505.     }
  2506. }
  2507.  
  2508.  
  2509. void
  2510. mac_wait_synch( void )
  2511. {
  2512.     get_nh_event ( ) ;
  2513. }
  2514.  
  2515.  
  2516. void
  2517. mac_mark_synch( void )
  2518. {
  2519.     get_nh_event ( ) ;
  2520. }
  2521.  
  2522.  
  2523. void
  2524. mac_cliparound ( int x , int y )
  2525. {
  2526.     /* TODO */
  2527.     if ( ! ( x * ( y + 1 ) ) ) {
  2528.         Debugger ( ) ;
  2529.     }
  2530. }
  2531.  
  2532.  
  2533. void
  2534. mac_raw_print ( const char * str )
  2535. {
  2536.     /* Here and in mac_raw_print_bold I assume that once theWindows got
  2537.        allocated by mac_init_nhwindows we can safely do putstr on BASE_WINDOW,
  2538.        even after mac_exit_nhwindows is called or flags.window_inited is reset
  2539.        to zero.  Is this assumption correct? */
  2540.     if ( theWindows ) {
  2541.  
  2542.         ShowWindow ( theWindows [ BASE_WINDOW ] . theWindow ) ;
  2543.         SelectWindow ( theWindows [ BASE_WINDOW ] . theWindow ) ;
  2544.  
  2545.         putstr ( BASE_WINDOW , 0 , str ) ;
  2546.  
  2547.     } else
  2548.         showerror ( str , NULL ) ;
  2549. }
  2550.  
  2551.  
  2552. void
  2553. mac_raw_print_bold ( const char * str )
  2554. {
  2555.     if ( theWindows ) {
  2556.  
  2557.         ShowWindow ( theWindows [ BASE_WINDOW ] . theWindow ) ;
  2558.         SelectWindow ( theWindows [ BASE_WINDOW ] . theWindow ) ;
  2559.  
  2560.         putstr ( BASE_WINDOW , ATR_BOLD , str ) ;
  2561.  
  2562.     } else {
  2563.         nhbell ( ) ;
  2564.         showerror ( str , NULL ) ;
  2565.     }
  2566. }
  2567.  
  2568.  
  2569. void
  2570. mac_exit_nhwindows ( const char * s )
  2571. {
  2572.     if ( s ) {
  2573.         raw_print ( s ) ;
  2574.         display_nhwindow ( BASE_WINDOW , TRUE ) ;
  2575.     }
  2576.  
  2577.     clear_nhwindow ( BASE_WINDOW ) ;
  2578.     flags . window_inited = 0 ;
  2579.     destroy_nhwindow ( WIN_MAP ) ;
  2580.     destroy_nhwindow ( WIN_MESSAGE ) ;
  2581.     destroy_nhwindow ( WIN_STATUS ) ;
  2582.     destroy_nhwindow ( WIN_INVEN ) ;
  2583. }
  2584.  
  2585.  
  2586. /*
  2587.  * Don't forget to decrease in_putstr before returning...
  2588.  */
  2589. void
  2590. mac_putstr ( winid win , int attr , const char * str )
  2591. {
  2592.     long len , slen ;
  2593.     NhWindow * aWin = & theWindows [ win ] ;
  2594.     int kind ;
  2595.     static char in_putstr = 0 ;
  2596.     Rect r ;
  2597.  
  2598.     if ( in_putstr > 3 ) {
  2599.         DebugStr ( ( ConstStr255Param ) "\012Recursion!" ) ;
  2600.         return ;
  2601.     }
  2602.     if ( win < 0 || win >= NUM_MACWINDOWS ) {
  2603.         error ( "Invalid window %d (Max %d) in putstr." , win ,
  2604.             NUM_MACWINDOWS , attr ) ;
  2605.         return ;
  2606.     }
  2607.     if ( ! aWin -> theWindow ) {
  2608.         error ( "Unallocated window %d in putstr." , win ) ;
  2609.         return ;
  2610.     }
  2611.  
  2612.     in_putstr ++ ;
  2613.     kind = ( ( WindowPeek ) ( aWin -> theWindow ) ) -> windowKind -
  2614.         WIN_BASE_KIND ;
  2615.  
  2616.     if ( kind == NHW_MAP || kind == NHW_STATUS ) {
  2617.         short    h = ( NUM_COLS - aWin->cursor.h - strlen(str) );
  2618.         /*
  2619.          * The "dungeon" window
  2620.          * putsym will call curs, so no updates necessary.
  2621.          */
  2622.         while ( * str ) {
  2623.             putsym ( win , aWin -> cursor . h , aWin -> cursor . v , * str ) ;
  2624.             curs ( win , aWin -> cursor . h + 1 , aWin -> cursor . v ) ;
  2625.             str ++ ;
  2626.         }
  2627.         h = (h < 0) ? 0 : h;
  2628.         while( h-- ) {
  2629.             putsym ( win , aWin -> cursor . h , aWin -> cursor . v , CHAR_BLANK ) ;
  2630.             curs ( win , aWin -> cursor . h + 1 , aWin -> cursor . v ) ;
  2631.         }
  2632.     } else {
  2633.         char * sr , * ds ;
  2634.         /*
  2635.          * A "default" text window - uses TextBox
  2636.          * We just add the text, without attributes for now
  2637.          */
  2638.         len = GetHandleSize ( aWin -> windowText ) ;
  2639.         slen = strlen ( str ) ;
  2640.         while ( aWin -> windowTextLen + slen + 1 > len ) {
  2641.             len = ( len > 2048 ) ? ( len + 2048 ) : ( len * 2 ) ;
  2642.             SetHandleSize ( aWin -> windowText , len ) ;
  2643.             if ( MemError ( ) ) {
  2644.                 error ( "SetHandleSize (putstr)" ) ;
  2645.                 aWin -> windowTextLen = 0L ;
  2646.                 aWin -> textBase = 0 ;
  2647.                 aWin -> lin = 0 ;
  2648.             }
  2649.         }
  2650.     
  2651.         len = aWin -> windowTextLen ;
  2652.         sr = (char *)str ;
  2653.         ds = * ( aWin -> windowText ) + len ;
  2654.         while ( * sr ) {
  2655.             if ( * sr == CHAR_LF )
  2656.                 * ds = CHAR_CR ;
  2657.             else
  2658.                 * ds = * sr ;
  2659.             if ( * ds == CHAR_CR && kind != NHW_MENU ) {
  2660.                 aWin -> lin ++ ;
  2661.             }
  2662.             sr ++ ;
  2663.             ds ++ ;
  2664.         }
  2665.         if ( slen > 1 ) {
  2666.             ( * ( aWin -> windowText ) ) [ len + slen ] = CHAR_CR ;
  2667.             aWin -> windowTextLen += slen + 1 ;
  2668.             aWin -> lin ++ ;
  2669.         } else {
  2670.             aWin -> windowTextLen += slen ;
  2671.         }
  2672.     
  2673.         SetPort ( aWin -> theWindow ) ;
  2674.         r = aWin -> theWindow -> portRect ;
  2675.         if ( win && win == WIN_MESSAGE ) {
  2676.             r . bottom -= SBARHEIGHT + 1 ;
  2677.         }
  2678.         InvalRect ( & r ) ;
  2679.         aWin -> clear = 0 ;
  2680.         if ( kind == NHW_MESSAGE ) {
  2681.             char * ptr , * stop ;
  2682.             long oldBase = aWin -> textBase ;
  2683.             short lines = ( r . bottom - r . top ) / aWin -> charHeight - 1 ;
  2684.  
  2685.             stop = * aWin -> windowText ;
  2686.             ptr = stop + aWin -> windowTextLen - 1 ;
  2687.             while ( lines >= 0 && -- ptr > stop ) {
  2688.                 if ( * ptr == CHAR_CR || * ptr == CHAR_LF )
  2689.                     lines -- ;
  2690.             }
  2691.             if ( ptr <= stop ) {
  2692.                 aWin -> textBase = 0L ;
  2693.             } else {
  2694.                 aWin -> textBase = ptr - stop + 1 ;
  2695.             }
  2696.             if ( oldBase > aWin -> textBase ) {
  2697.                 aWin -> textBase = oldBase ;
  2698.             }
  2699.         }
  2700.         if ( aWin -> scrollBar ) {
  2701.             InvalScrollBar ( aWin ) ;
  2702.         }
  2703.     }
  2704.     in_putstr -- ;
  2705. }
  2706.  
  2707.  
  2708. void
  2709. putsym ( winid win , int x , int y , CHAR_P sym )
  2710. {
  2711.     NhWindow * aWin = & theWindows [ win ] ;
  2712.     int kind = ( ( WindowPeek ) ( aWin -> theWindow ) ) -> windowKind
  2713.         - WIN_BASE_KIND ;
  2714.     Rect update ;
  2715.  
  2716.     aWin -> clear = 0 ;
  2717.     /*
  2718.      * We don't need to invalidate the old position or set the window,
  2719.      * since curs() will do that.
  2720.      */
  2721.     curs ( win , x , y ) ;
  2722.     x = aWin -> cursor . h ;
  2723.     y = aWin -> cursor . v ;
  2724.  
  2725.     if ( kind == NHW_MAP || kind == NHW_STATUS) {
  2726.         switch ( sym ) {
  2727.         case CHAR_LF :
  2728.         case CHAR_CR :
  2729.             curs ( win , 1 , y + 1 ) ;
  2730.             break ;
  2731.         case CHAR_BS :
  2732.             if ( x ) {
  2733.                 curs ( win , x - 1 , y ) ;
  2734.             }
  2735.             break ;
  2736.         default :
  2737.             /*
  2738.              * Curs() takes care of getting cursor . v within range even for
  2739.              * the shorter status window - note; this assumes the status and
  2740.              * the map windows have the same width !
  2741.              */
  2742.             update . top = y * aWin -> charHeight ;
  2743.             update . bottom = ( y + 1 ) * aWin -> charHeight ;
  2744.             update . left = x * aWin -> charWidth ;
  2745.             update . right = ( x + 1 ) * aWin -> charWidth ;
  2746.             EraseRect ( & update ) ;
  2747.             MoveTo ( x * aWin -> charWidth , ( y + 1 ) * aWin -> charHeight -
  2748.                 aWin -> leading ) ;
  2749.             ( ( MapData * ) * aWin -> windowText ) -> map [ y ] [ x ] = sym ;
  2750.             DrawChar ( sym ) ;
  2751.             break ;
  2752.         }
  2753.     } else {
  2754.         char ss [ 2 ] ;
  2755.         ss [ 0 ] = sym ;
  2756.         ss [ 1 ] = 0 ;
  2757.         putstr ( win , 0 , ss ) ;
  2758.     }
  2759. }
  2760.  
  2761.  
  2762. void
  2763. mac_curs ( winid win , int x , int y )
  2764. {
  2765.     NhWindow * aWin = & theWindows [ win ] ;
  2766.     int kind = ( ( WindowPeek ) ( aWin -> theWindow ) ) -> windowKind -
  2767.         WIN_BASE_KIND ;
  2768.  
  2769.     SetPort  ( aWin -> theWindow ) ;
  2770.     if ( kind == NHW_MAP || kind == NHW_STATUS ) {
  2771.         Rect update ;
  2772.         if ( x >= NUM_COLS ) {
  2773.             x = 1 ; y ++ ;
  2774.         }
  2775.         if ( y >= ( kind == NHW_STATUS ? NUM_STAT_ROWS : NUM_ROWS ) ) {
  2776.             y = 0 ; x = 1 ;
  2777.         }
  2778.         if ( aWin -> cursorDrawn ) {
  2779.             update . top = aWin -> cursor . v * aWin -> charHeight ;
  2780.             update . bottom = ( aWin -> cursor . v + 1 ) * aWin -> charHeight ;
  2781.             update . left = aWin -> cursor . h * aWin -> charWidth ;
  2782.             update . right = ( aWin -> cursor . h + 1 ) * aWin -> charWidth ;
  2783.             EraseRect ( & update ) ;
  2784.             MoveTo ( aWin -> cursor . h * aWin -> charWidth , ( aWin ->
  2785.                 cursor . v + 1 ) * aWin -> charHeight - aWin -> leading ) ;
  2786.             DrawChar ( ( ( MapData * ) * ( aWin -> windowText ) ) -> map
  2787.                 [ aWin -> cursor . v ] [ aWin -> cursor . h ] ) ;
  2788.             aWin -> cursorDrawn = 0 ;
  2789.         }
  2790.     }
  2791.     MoveTo ( x * aWin -> charWidth , ( y + 1 ) * aWin -> charHeight -
  2792.         aWin -> leading ) ;
  2793.     SetPt ( & ( aWin -> cursor ) , x , y ) ;
  2794. }
  2795.  
  2796.  
  2797. /*
  2798.  *  print_glyph
  2799.  *
  2800.  *  Print the glyph to the output device.  Don't flush the output device.
  2801.  *
  2802.  *  Since this is only called from show_glyph(), it is assumed that the
  2803.  *  position and glyph are always correct (checked there)!
  2804.  */
  2805. void
  2806. mac_print_glyph ( winid window , XCHAR_P x , XCHAR_P y , int glyph )
  2807. {
  2808.     unsigned int    ch;
  2809.     register int    offset;
  2810.  
  2811. #define zap_color(n)
  2812. #define cmap_color(n)
  2813. #define trap_color(n)
  2814. #define obj_color(n)
  2815. #define mon_color(n)
  2816. #define pet_color(c)
  2817.  
  2818.     /*
  2819.      *  Map the glyph back to a character.
  2820.      *
  2821.      *  Warning:  For speed, this makes an assumption on the order of
  2822.      *          offsets.  The order is set in display.h.
  2823.      */
  2824.     if ((offset = (glyph - GLYPH_SWALLOW_OFF)) >= 0) {        /* swallow */
  2825.  
  2826.         /* see swallow_to_glyph() in display.c */
  2827.         ch = (uchar) showsyms[S_sw_tl + (offset & 0x7)];
  2828.         mon_color(offset >> 3);
  2829.  
  2830.     } else if ((offset = (glyph - GLYPH_ZAP_OFF)) >= 0) {    /* zap beam */
  2831.  
  2832.         /* see zapdir_to_glyph() in display.c */
  2833.         ch = showsyms[S_vbeam + (offset & 0x3)];
  2834.         zap_color((offset >> 2));
  2835.  
  2836.     } else if ((offset = (glyph - GLYPH_CMAP_OFF)) >= 0) {    /* cmap */
  2837.  
  2838.         ch = showsyms[offset];
  2839.         cmap_color(offset);
  2840.  
  2841.     } else if ((offset = (glyph - GLYPH_TRAP_OFF)) >= 0) {    /* trap */
  2842.  
  2843.         ch = (offset == WEB) ? showsyms[S_web] : showsyms[S_trap];
  2844.         trap_color(offset);
  2845.  
  2846.     } else if ((offset = (glyph - GLYPH_OBJ_OFF)) >= 0) {    /* object */
  2847.  
  2848.         ch = oc_syms[objects[offset].oc_class];
  2849.         obj_color(offset);
  2850.  
  2851.     } else if ((offset = (glyph - GLYPH_BODY_OFF)) >= 0) {    /* a corpse */
  2852.  
  2853.         ch = oc_syms[objects[CORPSE].oc_class];
  2854.         mon_color(offset);
  2855.  
  2856.     } else if ((offset = (glyph - GLYPH_PET_OFF)) >= 0) {    /* a pet */
  2857.  
  2858.         ch = monsyms[mons[offset].mlet];
  2859.         pet_color(offset);
  2860.  
  2861.     } else {                            /* a monster */
  2862.  
  2863.         ch = monsyms[mons[glyph].mlet];
  2864.         mon_color(glyph);
  2865.     }
  2866.  
  2867.     if ( ch > 255 ) {
  2868.         error ( "cicn plotting is not supported." ) ;
  2869.         /*
  2870.          * cicn plotting goes here
  2871.          */
  2872.     } else {
  2873.         /*
  2874.          * Print a char from the hack font.
  2875.          */
  2876.         putsym ( window , x , y , ch ) ;
  2877.     }
  2878. }
  2879.  
  2880.  
  2881. int
  2882. mac_nh_poskey ( int * a , int * b , int * c )
  2883. {
  2884.     if ( ! a || ! b || ! c ) {
  2885.         Debugger ( ) ;
  2886.     }
  2887.     return nhgetch ( ) ;
  2888. }
  2889.  
  2890.  
  2891. void
  2892. mac_start_menu ( winid win )
  2893. {
  2894.     NhWindow * aWin = & theWindows [ win ] ;
  2895.  
  2896.     HideWindow ( aWin -> theWindow ) ;
  2897.     SetHandleSize ( aWin -> windowText , TEXT_BLOCK ) ;
  2898.     aWin -> wid = 0 ;
  2899.     aWin -> lin = 0 ;
  2900.     clear_nhwindow ( win ) ;
  2901. }
  2902.  
  2903.  
  2904. void
  2905. mac_add_menu ( winid win , CHAR_P menuChar , int attr , const char * str )
  2906. {
  2907.     long addSize ;
  2908.     int newWid ;
  2909.     NhWindow * aWin = & theWindows [ win ] ;
  2910.  
  2911.     if ( ! str || aWin -> lin >= NUM_MENU_ITEMS )
  2912.         return ;
  2913.  
  2914.     SetPort ( aWin -> theWindow ) ;
  2915.     aWin -> itemChars [ aWin -> lin ] = menuChar ;
  2916.  
  2917.     addSize = strlen ( str ) ;
  2918.     newWid = TextWidth ( str , 0 , addSize ) ;
  2919.     if ( newWid > aWin -> wid )
  2920.         aWin -> wid = newWid ;
  2921.     putstr ( win , attr , str ) ;
  2922. }
  2923.  
  2924.  
  2925. /*
  2926.  * End a menu in this window, window must a type NHW_MENU.
  2927.  * ch is the value to return if the menu is canceled,
  2928.  * str is a list of cancel characters (values that may be input)
  2929.  * morestr is a prompt to display, rather than the default.
  2930.  * str and morestr might be ignored by some ports.
  2931.  */
  2932. void
  2933. mac_end_menu ( winid win , CHAR_P ch , const char * str , const char * morestr )
  2934. {
  2935.     unsigned char buf [ 256 ] ;
  2936.     int len ;
  2937.     NhWindow * aWin = & theWindows [ win ] ;
  2938.  
  2939.     strncpy ( aWin -> cancelStr , str , NUM_CANCEL_ITEMS ) ;
  2940.     aWin -> cancelStr [ NUM_CANCEL_ITEMS - 1 ] = 0 ;
  2941.     aWin -> cancelChar = ch ;
  2942.  
  2943.     buf [ 0 ] = 0 ;
  2944.     if ( morestr ) {
  2945.         strncpy ( (char *)& buf [ 1 ] , morestr , 255 ) ;
  2946.         len = strlen ( morestr ) ;
  2947.         if ( len > 255 )
  2948.             buf [ 0 ] = 255 ;
  2949.         else
  2950.             buf [ 0 ] = len ;
  2951.     }
  2952.     SetWTitle ( aWin -> theWindow , buf ) ;
  2953. }
  2954.  
  2955.  
  2956. char
  2957. mac_select_menu ( winid win )
  2958. {
  2959.     short w , h ;
  2960.     int c , l ;
  2961.     WindowPtr theWin = theWindows [ win ] . theWindow ;
  2962.     NhWindow * aWin = & theWindows [ win ] ;
  2963.  
  2964.     inSelect = win ;
  2965.  
  2966.     SetPort ( theWin ) ;
  2967.     if ( aWin -> wid && aWin -> lin ) {
  2968.         w = aWin -> wid + 16 ;
  2969.         h = aWin -> lin * aWin -> charHeight ;
  2970.         if ( w > 450 ) {
  2971.             w = 450 ;
  2972.         }
  2973.         if ( h > 300 ) {
  2974.             h = 300 ;
  2975.         }
  2976.         SizeWindow ( theWin , w , h , TRUE ) ;
  2977.         if ( aWin -> scrollBar ) {
  2978.             InvalScrollBar ( aWin ) ;
  2979.         }
  2980.     }
  2981.     SelectWindow ( theWin ) ;
  2982.     ShowWindow ( theWin ) ;
  2983.     InvalRect ( & ( theWin -> portRect ) ) ;
  2984.  
  2985.     do {
  2986.         while ( ! ( c =  nhgetch ( ) ) ) ;
  2987.         for ( l = 0 ; l < aWin -> lin ; l ++ ) {
  2988.             if ( aWin -> itemChars [ l ] == c )
  2989.                 goto done ;
  2990.         }
  2991.         if ( ClosingWindowChar ( c ) ) {
  2992.             c = aWin -> cancelChar ;
  2993.         }
  2994.     } while ( ! strchr ( aWin -> cancelStr , c ) &&
  2995.         c != aWin -> cancelChar ) ;
  2996.  
  2997. done :
  2998.  
  2999.     HideWindow ( theWin ) ;
  3000.  
  3001.     inSelect = WIN_ERR ;
  3002.  
  3003.     return c ;
  3004. }
  3005.  
  3006.  
  3007. void
  3008. mac_display_file ( name, complain )
  3009. const char * name;
  3010. boolean    complain;
  3011. {
  3012.     long l ;
  3013.     short refNum ;
  3014.     Ptr buf ;
  3015.     int win ;
  3016.  
  3017.     if ( 0 > ( refNum = macopen ( name , O_RDONLY , TEXT_TYPE ) ) ) {
  3018.         if (complain) error ( "Cannot open file %s." , name ) ;
  3019.     } else {
  3020.         l = macseek ( refNum , 0 , SEEK_END ) ;
  3021.         ( void ) macseek ( refNum , 0 , 0L ) ;
  3022.         win = create_nhwindow ( NHW_TEXT ) ;
  3023.         if ( win == WIN_ERR ) {
  3024.             if (complain) error ( "Cannot make window." ) ;
  3025.             goto out ;
  3026.         }
  3027.         buf = NewPtr(l+1);
  3028.         if (buf)
  3029.             l = macread(refNum, buf, l);
  3030.         if (buf && l > 0) {
  3031.             buf[l] = '\0';
  3032.             putstr(win, 0, buf);
  3033.             display_nhwindow(win, FALSE);
  3034.         } else {
  3035.             HideWindow(theWindows[win].theWindow);
  3036.             destroy_nhwindow(win);
  3037.         }
  3038.         if (buf)
  3039.             DisposPtr(buf);
  3040. out :
  3041.         macclose ( refNum ) ;
  3042.     }
  3043. }
  3044.  
  3045.  
  3046. void
  3047. port_help ( )
  3048. {
  3049.     display_file ( PORT_HELP , TRUE ) ;
  3050. }
  3051.  
  3052.  
  3053. short frame_corner ;
  3054.  
  3055.  
  3056. static pascal void
  3057. FrameItem ( DialogPtr dlog , short item )
  3058. {
  3059.     short k ;
  3060.     Handle h ;
  3061.     Rect r ;
  3062.  
  3063.     GetDItem ( dlog , item , & k , & h , & r ) ;
  3064.     PenSize ( 3 , 3 ) ;
  3065.     FrameRoundRect ( & r , frame_corner , frame_corner ) ;
  3066.     PenNormal ( ) ;
  3067. }
  3068.  
  3069.  
  3070. void
  3071. SetFrameItem ( DialogPtr dlog , short frame , short item )
  3072. {
  3073.     Rect r , r2 ;
  3074.     short kind ;
  3075.     Handle h ;
  3076.  
  3077.     GetDItem ( dlog , item , & kind , & h , & r ) ;
  3078.     InsetRect ( & r , -4 , -4 ) ;
  3079.     r2 = r ;
  3080.     GetDItem ( dlog , frame , & kind , & h , & r ) ;
  3081.     SetDItem ( dlog , frame , kind , ( Handle ) FrameItem , & r2 ) ;
  3082.     frame_corner = 16 ;
  3083. }
  3084.  
  3085.  
  3086. //    Flash a button (for instance OK if you press enter)
  3087. //
  3088. void
  3089. FlashButton ( DialogPtr dlog , short item )
  3090. {
  3091.     short k ;
  3092.     Handle h ;
  3093.     Rect r ;
  3094.     long l ;
  3095.  
  3096.     GetDItem ( dlog , item , & k , & h , &  r ) ;
  3097.     if ( k == ctrlItem + btnCtrl ) {
  3098.         HiliteControl ( ( ControlHandle ) h , 1 ) ;
  3099.         Delay ( GetDblTime ( ) / 2 , & l ) ;
  3100.         HiliteControl ( ( ControlHandle ) h , 0 ) ;
  3101.     }
  3102. }
  3103.  
  3104.  
  3105. pascal Boolean
  3106. CharacterDialogFilter ( DialogPtr dp , EventRecord * ev , short * item )
  3107. {
  3108.     int ix ;
  3109.     Handle h ;
  3110.     Rect r ;
  3111.     short k ;
  3112.     Str255 s ;
  3113.     unsigned char com [ 2 ] ;
  3114.  
  3115.     if ( ev -> what == mouseDown ) {
  3116.  
  3117.         int code ;
  3118.         WindowPtr wp ;
  3119.         Rect r ;
  3120.  
  3121.         code = FindWindow ( ev -> where , & wp ) ;
  3122.         if ( wp != dp || code != inDrag ) {
  3123.     
  3124.             return 0 ;
  3125.         }
  3126.         r = ( * GetGrayRgn ( ) ) -> rgnBBox ;
  3127.         InsetRect ( & r , 3 , 3 ) ;
  3128.     
  3129.         DragWindow ( wp , ev -> where , & r ) ;
  3130.         SaveWindowPos ( wp ) ;
  3131.  
  3132.         ev -> what = nullEvent ;
  3133.         return 1 ;
  3134.     }
  3135.     if ( ev -> what != keyDown ) {
  3136.  
  3137.         return 0 ;
  3138.     }
  3139.     com [ 0 ] = 1 ;
  3140.     com [ 1 ] = ev -> message & 0xff ;
  3141.  
  3142.     if ( com [ 1 ] == 10 || com [ 1 ] == 13 || com [ 1 ] == 32 ||
  3143.         com [ 1 ] == 3 ) { // various "OK"
  3144.  
  3145.         * item = 1 ;
  3146.         FlashButton ( dp , 1 ) ;
  3147.         return 1 ;
  3148.     }
  3149.     if ( com [ 1 ] == 'Q' || com [ 1 ] == 'q' ||
  3150.          com [ 1 ] == 27 || ( ev -> message & 0xff00 == 0x3500 ) ) { // escape
  3151.  
  3152.         * item = 2 ;
  3153.         FlashButton ( dp , 2 ) ;
  3154.         return 1 ;
  3155.     }
  3156.     for ( ix = 3 ; ix ; ix ++ ) {
  3157.  
  3158.         h = ( Handle ) NULL ;
  3159.         k = 0 ;
  3160.         GetDItem ( dp , ix , & k , & h , & r ) ;
  3161.         if ( ! k || ! h ) {
  3162.  
  3163.             return 0 ;
  3164.         }
  3165.         if ( k == 6 ) { // Radio Button Item
  3166.  
  3167.             GetCTitle ( ( ControlHandle ) h , s ) ;
  3168.             s [ 0 ] = 1 ;
  3169.             if ( ! IUEqualString ( com , s ) ) {
  3170.  
  3171.                 * item = ix ;
  3172.                 return 1 ;
  3173.             }
  3174.         }
  3175.     }
  3176. /*NOTREACHED*/
  3177.     return 0 ;
  3178. }
  3179.  
  3180.  
  3181. void
  3182. mac_player_selection ( void )
  3183. {
  3184.     ControlHandle    ctrl;
  3185.     DialogPtr        characterDialog;
  3186.     short            itemHit, lastItemSelected, type;
  3187.     Rect            box;
  3188.     
  3189.     characterDialog = GetNewDialog(132, (Ptr) NULL, (WindowPtr) -1);
  3190.     
  3191.     /*
  3192.     ** Default selection is random, beginning at the first item after the "Cancel" button.
  3193.     */
  3194.     
  3195.     lastItemSelected = rn1(12, 3);
  3196.  
  3197.     /*
  3198.     ** Mark the default selection.
  3199.     */
  3200.     
  3201.     GetDItem(characterDialog, lastItemSelected, &type, (Handle *) &ctrl, &box);
  3202.     SetCtlValue(ctrl, 1);
  3203.  
  3204.     InitCursor ( ) ;
  3205.     SetFrameItem ( characterDialog , 15 , 1 ) ;
  3206.     do {
  3207.         ModalDialog((ModalFilterProcPtr) CharacterDialogFilter , &itemHit);
  3208.         if ((itemHit != 1) && (itemHit != 2)) {
  3209.             /*
  3210.             ** If OK and Cancel (items 1 and 2) weren't selected then a radio button 
  3211.             ** was pushed.  Unmark the previous selection.
  3212.             */
  3213.             
  3214.             GetDItem(characterDialog, lastItemSelected, &type, (Handle *) &ctrl, &box);
  3215.             SetCtlValue(ctrl, 0);
  3216.             
  3217.             /*
  3218.             ** Mark the current selection.
  3219.             */
  3220.             
  3221.             GetDItem(characterDialog, itemHit, &type, (Handle *) &ctrl, &box);
  3222.             SetCtlValue(ctrl, 1);
  3223.  
  3224.             /*
  3225.             ** Save the item number for use later.
  3226.             */
  3227.             
  3228.             lastItemSelected = itemHit;
  3229.         }
  3230.     } while ((itemHit != 1) && (itemHit != 2));
  3231.     
  3232.     if (itemHit == 2) {
  3233.  
  3234.         clearlocks();
  3235.         ExitToShell();
  3236.  
  3237.     } else {
  3238.         switch (lastItemSelected) {
  3239.         case 3:
  3240.             pl_character [ 0 ] = 'A';
  3241.             break;
  3242.         case 4:
  3243.             pl_character [ 0 ] = 'B';
  3244.             break;
  3245.         case 5:
  3246.             pl_character [ 0 ] = 'C';
  3247.             break;
  3248.         case 6:
  3249.             pl_character [ 0 ] = 'E';
  3250.             break;
  3251.         case 7:
  3252.             pl_character [ 0 ] = 'H';
  3253.             break;
  3254.         case 8:
  3255.             pl_character [ 0 ] = 'K';
  3256.             break;
  3257.         case 9:
  3258.             pl_character [ 0 ] = 'P';
  3259.             break;
  3260.         case 10:
  3261.             pl_character [ 0 ] = 'R';
  3262.             break;
  3263.         case 11:
  3264.             pl_character [ 0 ] = 'S';
  3265.             break;
  3266.         case 12:
  3267.             pl_character [ 0 ] = 'T';
  3268.             break;
  3269.         case 13:
  3270.             pl_character [ 0 ] = 'V';
  3271.             break;
  3272.         case 14:
  3273.             pl_character [ 0 ] = 'W';
  3274.             break;
  3275.         }
  3276.     }
  3277.     
  3278.     DisposDialog(characterDialog);
  3279. }
  3280.  
  3281. void
  3282. mac_update_inventory ( void )
  3283. {
  3284. }
  3285.  
  3286.  
  3287. void
  3288. mac_suspend_nhwindows ( const char * )
  3289. {
  3290.     /*    Can't relly do that :-)        */
  3291. }
  3292.  
  3293.  
  3294. void
  3295. mac_resume_nhwindows ( void )
  3296. {
  3297.     /*    Can't relly do that :-)        */
  3298. }
  3299.  
  3300.  
  3301. int
  3302. try_key_queue ( char * bufp )
  3303. {
  3304.     if ( keyQueue [ 0 ] ) {
  3305.  
  3306.         int ix , flag = 0 ;
  3307.         for ( ix = 0 ; ix < QUEUE_LEN ; ix ++ ) {
  3308.  
  3309.             if ( ! flag ) {
  3310.  
  3311.                 if ( ! ( bufp [ ix ] = keyQueue [ ix ] ) ) {
  3312.  
  3313.                     flag = 1 ;
  3314.                 }
  3315.             }
  3316.             keyQueue [ ix ] = 0 ;
  3317.         }
  3318.         if ( ! flag ) {
  3319.  
  3320.             bufp [ ix ] = 0 ;
  3321.         }
  3322.         return 1 ;
  3323.     }
  3324.  
  3325.     return 0 ;
  3326. }
  3327.  
  3328. /* Interface definition, for windows.c */
  3329. struct window_procs mac_procs = {
  3330.     "mac",
  3331.     mac_init_nhwindows,
  3332.     mac_player_selection,
  3333.     mac_askname,
  3334.     mac_get_nh_event,
  3335.     mac_exit_nhwindows,
  3336.     mac_suspend_nhwindows,
  3337.     mac_resume_nhwindows,
  3338.     mac_create_nhwindow,
  3339.     mac_clear_nhwindow,
  3340.     mac_display_nhwindow,
  3341.     mac_destroy_nhwindow,
  3342.     mac_curs,
  3343.     mac_putstr,
  3344.     mac_display_file,
  3345.     mac_start_menu,
  3346.     mac_add_menu,
  3347.     mac_end_menu,
  3348.     mac_select_menu,
  3349.     mac_update_inventory,
  3350.     mac_mark_synch,
  3351.     mac_wait_synch,
  3352. #ifdef CLIPPING
  3353.     mac_cliparound,
  3354. #endif
  3355.     mac_print_glyph,
  3356.     mac_raw_print,
  3357.     mac_raw_print_bold,
  3358.     mac_nhgetch,
  3359.     mac_nh_poskey,
  3360.     mac_nhbell,
  3361.     mac_doprev_message,
  3362.     mac_yn_function,
  3363.     mac_getlin,
  3364. #ifdef COM_COMPL
  3365.     mac_get_ext_cmd,
  3366. #endif /* COM_COMPL */
  3367.     mac_number_pad,
  3368.     mac_delay_output,
  3369.     /* other defs that really should go away (they're tty specific) */
  3370.     0,    //    mac_start_screen,
  3371.     0, //    mac_end_screen,
  3372. } ;
  3373.  
  3374. /*macwin.c*/
  3375.