home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / sys / mac / macwin.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  66.5 KB  |  2,687 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)macwin.c    3.1    93/07/09          */
  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. #include "mactty.h"
  21. #include "wintty.h"
  22.  
  23. #include <osutils.h>
  24. #include <dialogs.h>
  25. #include <textedit.h>
  26. #include <menus.h>
  27. #ifndef THINK_C
  28. #include <sysequ.h>
  29. #else
  30. #include <LoMem.h>
  31. #endif
  32. #include <resources.h>
  33. #include <desk.h>
  34. #include <gestaltequ.h>
  35. #include <balloons.h>
  36. #include <toolutils.h>
  37. #include <script.h>
  38. #include <OSEvents.h>
  39. #include <Packages.h>
  40. #include <Sound.h>
  41. #include <DiskInit.h>
  42.  
  43. static short kApplicInFront = 1;
  44.  
  45. NhWindow * theWindows = (NhWindow *) NULL ;
  46.  
  47. extern pascal short tty_environment_changed ( WindowPtr ) ;
  48.  
  49. /*
  50.  * Borrowed from the Mac tty port
  51.  */
  52. extern WindowPtr _mt_window;
  53.  
  54. /*
  55.  * Some useful #defines for the scroll bar width and height
  56.  */
  57. #define        SBARWIDTH    15
  58. #define        SBARHEIGHT    13
  59.  
  60. /*
  61.  * We put a TE on the message window for the "top line" queries.
  62.  * top_line is the TE that holds both the query and the user's
  63.  * response.  The first topl_query_len characters in top_line are
  64.  * the query, the rests are the response.  topl_resp is the valid
  65.  * response to a yn query, while topl_resp[topl_def_idx] is the
  66.  * default response to a yn query.
  67.  */
  68. TEHandle top_line = (TEHandle) nil;
  69. int         topl_query_len;
  70. int         topl_def_idx = -1;
  71. char     topl_resp[10] = "";
  72.  
  73. #define CHAR_ANY '\n'
  74.  
  75. /*
  76.  * inSelect means we have a menu window up for selection or
  77.  * something similar. It makes the window with win number ==
  78.  * inSelect a movable modal (unfortunately without the border)
  79.  * and clicking the close box forces an ESC into the key
  80.  * buffer. Don't forget to set inSelect to WIN_ERR when you're
  81.  * done...
  82.  */
  83. winid inSelect = WIN_ERR ;
  84.  
  85. /*
  86.  * The key queue - contains 0 for unused or an ascii value.
  87.  * When getting keys, take the first value and shift the
  88.  * queue, shifting in a 0.
  89.  */
  90. #define QUEUE_LEN 24
  91. const int keyQueueLen = QUEUE_LEN ;
  92. static int keyQueue [ QUEUE_LEN ] ;
  93.  
  94. Boolean gClickedToMove = 0 ; /* For ObscureCursor */
  95.  
  96. static unsigned long gNextClickRepeat = 0xffffffff ;
  97.  
  98. static Point clicked_pos ;    /* For nh_poskey */
  99. static int clicked_mod ;
  100.  
  101. static Boolean cursor_locked = false ;
  102.  
  103. extern void dprintf ( char * , ... ) ;
  104.  
  105.  
  106. void
  107. lock_mouse_cursor(Boolean new_cursor_locked)
  108. {
  109.     cursor_locked = new_cursor_locked;
  110.     if (new_cursor_locked)
  111.         PostEvent(osEvt, mouseMovedMessage<<24);
  112. }
  113.  
  114.  
  115. /*
  116.  * Add key to input queue, force means flush left and replace if full
  117.  */
  118. void
  119. AddToKeyQueue ( int ch , Boolean force )
  120. {
  121.     int i ;
  122.  
  123.     for ( i = 0 ; i < QUEUE_LEN ; i ++ ) {
  124.  
  125.         if ( ! keyQueue [ i ] ) {
  126.  
  127.             keyQueue [ i ] = ch ;
  128.             return ;
  129.         }
  130.     }
  131.     if ( force ) {
  132.         for ( i = 0 ; i < QUEUE_LEN - 1 ; i ++ ) {
  133.             keyQueue [ i ] = keyQueue [ i + 1 ] ;
  134.         }
  135.         keyQueue [ QUEUE_LEN - 1 ] = ch ;
  136.     }
  137. }
  138.  
  139.  
  140. /*
  141.  * Cursor movement
  142.  */
  143. RgnHandle gMouseRgn = (RgnHandle) NULL ;
  144.  
  145. /*
  146.  * _Gestalt madness - we rely heavily on the _Gestalt glue, since we
  147.  * don't check for the trap...
  148.  */
  149. MacFlags macFlags ;
  150.  
  151. /*
  152.  * The screen layouts on the small 512x342 screen need special cares.
  153.  */
  154. Boolean small_screen;
  155.  
  156. /*
  157.  * Async flag for keeping track of scrollbars...
  158.  * Used by InvalScrollBar ( )
  159.  */
  160. static NhWindow * asyDSC = (NhWindow *) NULL ;
  161.  
  162. /*
  163.  * The font to be used in the text window
  164.  */
  165. short text_wind_font = geneva;
  166.  
  167. /*
  168.  * Whether to adjust the height of a text window according to its contents
  169.  */
  170. boolean full_screen = FALSE;
  171.  
  172. char macPad = 1 ;
  173.  
  174. Handle mBar ;
  175. MenuHandle appleMenu ;
  176. MenuHandle fileMenu ;
  177. MenuHandle editMenu ;
  178. MenuHandle actionMenu ;
  179. MenuHandle inventoryMenu ;
  180. MenuHandle thingsMenu ;
  181. MenuHandle extendedMenu ;
  182. MenuHandle infoMenu ;
  183. MenuHandle helpMenu ;
  184.  
  185. #ifdef NHW_BASE
  186. # undef NHW_BASE
  187. #endif
  188. #define NHW_BASE 0
  189. extern winid BASE_WINDOW ; // Was: , WIN_MAP , WIN_MESSAGE , WIN_INVEN , WIN_STATUS ;
  190.  
  191. void NDECL(port_help);
  192.  
  193. int NDECL(SanePositions);
  194. Boolean FDECL(RetrieveWinPos, (WindowPtr,short *,short *));
  195. void NDECL ( InitMac ) ;
  196. void NDECL(InitRes);
  197. void FDECL(GeneralKey, ( EventRecord * theEvent , WindowPtr theWindow ));
  198. void FDECL(HandleKey, ( EventRecord * theEvent ));
  199. void FDECL(HandleClick, ( EventRecord * theEvent ));
  200. void FDECL(HandleUpdate, ( EventRecord * theEvent ));
  201. void FDECL(HandleEvent, ( EventRecord * theEvent ));
  202. void FDECL(WindowGoAway, ( EventRecord *, WindowPtr));
  203. void NDECL(DimMenuBar);
  204. void NDECL(UndimMenuBar);
  205. int FDECL(filter_scroll_key,(const int, NhWindow *));
  206.  
  207. void SetFrameItem ( DialogPtr , short , short ) ;
  208. void FlashButton ( DialogPtr , short ) ;
  209.  
  210. void trans_num_keys ( EventRecord * ) ;
  211.  
  212. #ifndef THINK_C
  213. /*
  214.  * Why aren't these declared when including hack.h - I thought
  215.  * they were...
  216.  */
  217. void FDECL(putsym, ( winid win , int x , int y , CHAR_P sym ));
  218. #endif
  219.  
  220. #define NUM_FUNCS 6
  221. static void FDECL(macKeyNull, ( EventRecord * , WindowPtr )) ;
  222. static void FDECL(macKeyMessage, ( EventRecord * , WindowPtr )) ;
  223. static void FDECL(macKeyTerm, ( EventRecord * , WindowPtr )) ;
  224. static void FDECL(macKeyMenu, ( EventRecord * , WindowPtr )) ;
  225. static void FDECL(macKeyText, ( EventRecord * , WindowPtr )) ;
  226.  
  227. static void FDECL(macClickNull, ( EventRecord * , WindowPtr )) ;
  228. static void FDECL(macClickMessage, ( EventRecord * , WindowPtr )) ;
  229. static void FDECL(macClickTerm, ( EventRecord * , WindowPtr )) ;
  230. static void FDECL(macClickMenu, ( EventRecord * , WindowPtr )) ;
  231. static void FDECL(macClickText, ( EventRecord * , WindowPtr )) ;
  232.  
  233. static void FDECL(macUpdateNull, ( EventRecord * , WindowPtr )) ;
  234. static void FDECL(macUpdateMessage, ( EventRecord * , WindowPtr )) ;
  235. static void FDECL(macUpdateTerm, ( EventRecord * , WindowPtr )) ;
  236. static void FDECL(macUpdateMenu, ( EventRecord * , WindowPtr )) ;
  237. static void FDECL(macUpdateText, ( EventRecord * , WindowPtr )) ;
  238.  
  239. static void FDECL(macCursorNull, ( EventRecord * , WindowPtr , RgnHandle )) ;
  240. static void FDECL(macCursorMessage, ( EventRecord * , WindowPtr , RgnHandle )) ;
  241. static void FDECL(macCursorTerm, ( EventRecord * , WindowPtr , RgnHandle )) ;
  242. static void FDECL(macCursorMenu, ( EventRecord * , WindowPtr , RgnHandle )) ;
  243. static void FDECL(macCursorText, ( EventRecord * , WindowPtr , RgnHandle )) ;
  244.  
  245. void NDECL(UpdateMenus);
  246. void FDECL(DoMenu, (long choise));
  247.  
  248. static void FDECL (DrawScrollbar, ( NhWindow * , WindowPtr ));
  249. static void FDECL (InvalScrollBar, ( NhWindow * ));
  250. static void FDECL(DoScrollBar,(Point, short, ControlHandle, NhWindow *, WindowPtr));
  251. static pascal void FDECL(Up, (ControlHandle, short));
  252. static pascal void FDECL(Down,(ControlHandle, short));
  253.  
  254. typedef void ( * CbFunc ) ( EventRecord * , WindowPtr ) ;
  255. typedef void ( * CbCursFunc ) ( EventRecord * , WindowPtr , RgnHandle ) ;
  256.  
  257. CbFunc winKeyFuncs [ NUM_FUNCS ] = {
  258.     macKeyNull , macKeyMessage , macKeyTerm , macKeyTerm , macKeyMenu , macKeyText
  259. } ;
  260.  
  261. CbFunc winClickFuncs [ NUM_FUNCS ] = {
  262.     macClickNull , macClickMessage , macClickTerm , macClickTerm , macClickMenu ,
  263.     macClickText
  264. } ;
  265.  
  266. CbFunc winUpdateFuncs [ NUM_FUNCS ] = {
  267.     macUpdateNull , macUpdateMessage , macUpdateTerm , macUpdateTerm ,
  268.     macUpdateMenu , macUpdateText
  269. } ;
  270.  
  271. CbCursFunc winCursorFuncs [ NUM_FUNCS ] = {
  272.     macCursorNull , macCursorMessage , macCursorTerm , macCursorTerm ,
  273.     macCursorMenu , macCursorText
  274. } ;
  275.  
  276. NhWindow *
  277. GetNhWin(WindowPtr mac_win)
  278. {
  279.     int ix;
  280.     for (ix = 0; ix < NUM_MACWINDOWS; ++ix)
  281.         if (mac_win == theWindows[ix].theWindow)
  282.             return theWindows + ix;
  283.     return ((NhWindow *) nil) ;
  284. }
  285.  
  286.  
  287. #ifdef applec
  288.   extern void _DataInit();
  289.   /* This routine is part of the MPW runtime library. This external
  290.      reference to it is done so that we can unload its segment, %A5Init,
  291.      and recover c 250K of memory */
  292. #endif
  293.  
  294.  
  295. void
  296. InitMac( void )
  297. {
  298.     int i ;
  299.     long l ;
  300.     long applLimit;
  301.  
  302. #ifdef applec
  303.     UnloadSeg((Ptr) _DataInit);
  304. #endif
  305.  
  306.     if ( * ( long * ) DefltStack < 50 * 1024L ) {
  307. #ifdef THINK_C
  308.         applLimit = (long) CurStackBase - (50 * 1024L);
  309. #else
  310.         applLimit = (* (long *) CurStackBase) - (50 * 1024L);
  311. #endif
  312.         SetApplLimit ( ( void * ) applLimit ) ;
  313.     }
  314.     MaxApplZone ( ) ;
  315.     for ( i = 0 ; i < 5 ; i ++ )
  316.         MoreMasters ( ) ;
  317.  
  318.     InitGraf ( & qd . thePort ) ;
  319.     InitFonts ( ) ;
  320.     InitWindows ( ) ;
  321.     InitMenus ( ) ;
  322.     InitDialogs ( ( ResumeProcPtr ) 0L ) ;
  323.     TEInit ( ) ;
  324.     InitSegMgmt( itworked );    /* itworked is always in the main segment */
  325.     
  326.     attemptingto("start up");
  327.  
  328.     if ( Gestalt ( gestaltOSAttr , & l ) ) {
  329.         macFlags . processes = 0 ;
  330.         macFlags . tempMem = 0 ;
  331.     } else {
  332.         macFlags . processes = ( l & ( 1 << gestaltLaunchControl ) ) ? 1 : 0 ;
  333.         macFlags . tempMem = ( l & ( 1 << gestaltRealTempMemory ) ) ? 1 : 0 ;
  334.     }
  335.     if ( Gestalt ( gestaltQuickdrawVersion , & l ) ) {
  336.         macFlags . color = 0 ;
  337.     } else {
  338.         macFlags . color = ( l >= gestalt8BitQD ) ? 1 : 0 ;
  339.     }
  340.     if ( Gestalt ( gestaltFindFolderAttr , & l ) ) {
  341.         macFlags . folders = 0 ;
  342.     } else {
  343.         macFlags . folders = ( l & ( 1 << gestaltFindFolderPresent ) ) ? 1 : 0 ;
  344.     }
  345.     if ( Gestalt ( gestaltHelpMgrAttr , & l ) ) {
  346.         macFlags . help = 0 ;
  347.     } else {
  348.         macFlags . help = ( l & ( 1 << gestaltHelpMgrPresent ) ) ? 1 : 0 ;
  349.     }
  350.     if ( Gestalt ( gestaltFSAttr , & l ) ) {
  351.         macFlags . fsSpec = 0 ;
  352.     } else {
  353.         macFlags . fsSpec = ( l & ( 1 << gestaltHasFSSpecCalls ) ) ? 1 : 0 ;
  354.     }
  355.     if ( Gestalt ( gestaltFontMgrAttr , & l ) ) {
  356.         macFlags . trueType = 0 ;
  357.     } else {
  358.         macFlags . trueType = ( l & ( 1 << gestaltOutlineFonts ) ) ? 1 : 0 ;
  359.     }
  360.     if ( Gestalt ( gestaltAUXVersion , & l ) ) {
  361.         macFlags . aux = 0 ;
  362.     } else {
  363.         macFlags . aux = ( l >= 0x200 ) ? 1 : 0 ;
  364.     }
  365.     if ( Gestalt ( gestaltAliasMgrAttr , & l ) ) {
  366.         macFlags . alias = 0 ;
  367.     } else {
  368.         macFlags . alias = ( l & ( 1 << gestaltAliasMgrPresent ) ) ? 1 : 0 ;
  369.     }
  370.     if ( Gestalt ( gestaltStandardFileAttr , & l ) ) {
  371.         macFlags . standardFile = 0 ;
  372.     } else {
  373.         macFlags . standardFile = ( l & ( 1 << gestaltStandardFile58 ) ) ? 1 : 0 ;
  374.     }
  375.  
  376.     gMouseRgn = NewRgn ( ) ;
  377.     InitCursor ( ) ;
  378.     ObscureCursor ( ) ;
  379. }
  380.  
  381.  
  382. #define MAX_HEIGHT 100
  383. #define MIN_HEIGHT 50
  384. #define MIN_WIDTH 300
  385.  
  386. /*
  387.  * This function could be overloaded with any amount of
  388.  * intelligence...
  389.  */
  390. int
  391. SanePositions ( void )
  392. {
  393.     short mainTop , mainLeft ;
  394.     short mesgTop , mesgLeft , mesgWidth , mesgHeight ;
  395.     short left , top , width , height ;
  396.     short ix , numText = 0 , numMenu = 0 ;
  397.     Rect screenArea ;
  398.     WindowPtr theWindow ;
  399.     NhWindow * nhWin ;
  400.  
  401.     screenArea = qd . thePort -> portBits . bounds ;
  402.     OffsetRect ( & screenArea , - screenArea . left , - screenArea . top ) ;
  403.  
  404. /* Map Window */
  405.     nhWin = theWindows + WIN_MAP ;
  406.     theWindow = nhWin -> theWindow ;
  407.  
  408.     height = nhWin -> charHeight * NUM_ROWS ;
  409.     width = nhWin -> charWidth * NUM_COLS ;
  410.  
  411.     if ( ! RetrievePosition ( kMapWindow , & top , & left ) ) {
  412.         top = GetMBarHeight ( ) + ( small_screen ? 2 : 20 ) ;
  413.         left = ( screenArea . right - width ) / 2 ;
  414.     }
  415.  
  416.     mainTop = top ;
  417.     mainLeft = left ;
  418.  
  419. /* Message Window */
  420.     nhWin = theWindows + WIN_MESSAGE ;
  421.     theWindow = nhWin -> theWindow ;
  422.  
  423.     if ( ! RetrievePosition ( kMessageWindow , & top , & left ) ) {
  424.         top = mainTop + _mt_window->portRect.bottom - _mt_window->portRect.top;
  425.         if ( ! small_screen )
  426.             top += 20 ;
  427.         left = mainLeft ;
  428.     }
  429.  
  430.     if ( ! RetrieveSize ( kMessageWindow , top , left , & height , & width ) ) {
  431.         height = screenArea . bottom - top - ( small_screen ? 2-SBARHEIGHT : 2 ) ;
  432.         if ( height > MAX_HEIGHT ) {
  433.             height = MAX_HEIGHT ;
  434.         } else if ( height < MIN_HEIGHT ) {
  435.             height = MIN_HEIGHT ;
  436.             width = MIN_WIDTH ;
  437.             left = screenArea . right - width ;
  438.             top = screenArea . bottom - MIN_HEIGHT ;
  439.         }
  440.     }
  441.     mesgTop = top ;
  442.     mesgLeft = left ;
  443.     mesgHeight = height ;
  444.     mesgWidth = width ;
  445.  
  446. /* Move these windows */
  447.     MoveWindow ( theWindows [ WIN_MESSAGE ] . theWindow , mesgLeft , mesgTop , 1 ) ;
  448.     SizeWindow ( theWindows [ WIN_MESSAGE ] . theWindow , mesgWidth , mesgHeight , 1 ) ;
  449.     MoveWindow ( _mt_window , mainLeft , mainTop , 1 ) ;
  450.  
  451. /* Handle other windows */
  452.     for ( ix = 0 ; ix < NUM_MACWINDOWS ; ix ++ ) {
  453.         if ( ix != WIN_STATUS && ix != WIN_MESSAGE && ix != WIN_MAP && ix != BASE_WINDOW ) {
  454.             if ( theWindow = theWindows [ ix ] . theWindow ) {
  455.                 if ( ( ( WindowPeek ) theWindow ) -> visible ) {
  456.                     if ( theWindows [ ix ] . kind == NHW_MENU ) {
  457.                         if ( ! RetrievePosition ( kMenuWindow , & top , & left ) ) {
  458.                             top = GetMBarHeight ( ) * 2 ;
  459.                             left = 2 ;
  460.                         }
  461.                         top += ( numMenu * GetMBarHeight ( ) ) ;
  462.                         while ( top > screenArea . bottom - MIN_HEIGHT ) {
  463.                             top -= ( screenArea . bottom - GetMBarHeight ( ) * 2 ) ;
  464.                             left += 20 ;
  465.                         }
  466.                         numMenu ++ ;
  467.                         MoveWindow ( theWindow , left , top , 1 ) ;
  468.                     } else {
  469.                         if ( ! RetrievePosition ( kTextWindow , & top , & left ) ) {
  470.                             top = GetMBarHeight ( ) * 2 ;
  471.                             left = screenArea . right - 3 - ( theWindow -> portRect . right -
  472.                                                               theWindow -> portRect . left ) ;
  473.                         }
  474.                         top += ( numText * GetMBarHeight ( ) ) ;
  475.                         while ( top > screenArea . bottom - MIN_HEIGHT ) {
  476.                             top -= ( screenArea . bottom - GetMBarHeight ( ) * 2 ) ;
  477.                             left -= 20 ;
  478.                         }
  479.                         numText ++ ;
  480.                         MoveWindow ( theWindow , left , top , 1 ) ;
  481.                     }
  482.                 }
  483.             }
  484.         }
  485.     }
  486.  
  487.     InitCursor ( ) ;
  488.  
  489.     return 0 ;
  490. }
  491.  
  492.  
  493. winid
  494. mac_create_nhwindow ( int type )
  495. {
  496.     int i ;
  497.     Rect siz ;
  498.     NhWindow * aWin ;
  499.  
  500.     if ( type < NHW_BASE || type > NHW_TEXT ) {
  501.         error ( "Invalid window type %d in create_nhwindow." , type ) ;
  502.         return WIN_ERR ;
  503.     }
  504.  
  505.     for ( i = 0 ; i < NUM_MACWINDOWS ; i ++ ) {
  506.         if ( ! theWindows [ i ] . theWindow )
  507.             break ;
  508.     }
  509.     if ( i >= NUM_MACWINDOWS ) {
  510.         for ( i = 0 ; i < NUM_MACWINDOWS ; i ++ ) {
  511.             WindowPeek w = ( WindowPeek ) theWindows [ i ] . theWindow ;
  512.             if ( w -> visible || i == WIN_INVEN ||
  513.                  w -> windowKind != WIN_BASE_KIND + NHW_MENU &&
  514.                  w -> windowKind != WIN_BASE_KIND + NHW_TEXT )
  515.                 continue ;
  516.             error ( "The window list is getting full, freeing unnecessary window (%d)..." ,
  517.                 i ) ;
  518.             destroy_nhwindow ( i ) ;
  519.             goto got1 ;
  520.         }
  521.         error ( "Out of window ids in create_nhwindow ! (Max = %d)" ,
  522.             NUM_MACWINDOWS ) ;
  523.         return WIN_ERR ;
  524.     }
  525.  
  526. got1 :
  527.     aWin = & theWindows [ i ] ;
  528.  
  529.     aWin -> windowTextLen = 0L ;
  530.     aWin -> clear = 0 ; /* Yes, we need to inval the area on a clear */
  531.     aWin -> scrollBar = (ControlHandle) NULL ;
  532.  
  533.     dprintf ( "Created window type %d" , type ) ;
  534.     aWin -> kind = type ;
  535.     aWin -> keyFunc = winKeyFuncs [ type ] ;
  536.     aWin -> clickFunc = winClickFuncs [ type ] ;
  537.     aWin -> updateFunc = winUpdateFuncs [ type ] ;
  538.     aWin -> cursorFunc = winCursorFuncs [ type ] ;
  539.  
  540.     if (type == NHW_BASE || type == NHW_MAP || type == NHW_STATUS) {
  541.         short x_sz, x_sz_p, y_sz_p;
  542.         dprintf ( "This is in the TTY window" ) ;
  543.         if (type == NHW_BASE) {
  544.             aWin -> keyFunc = winKeyFuncs [ NHW_MAP ] ;
  545.             aWin -> clickFunc = winClickFuncs [ NHW_MAP ] ;
  546.             aWin -> updateFunc = winUpdateFuncs [ NHW_MAP ] ;
  547.             aWin -> cursorFunc = winCursorFuncs [ NHW_MAP ] ;
  548.         } else {
  549.             if (i != tty_create_nhwindow(type)) {
  550.                 dprintf ( "Cannot create window type %d" , type ) ;
  551.             }
  552.             if (type == NHW_MAP) {
  553.                 wins[i]->offy = 0;    /* the message box is in a separate window */
  554.             }
  555.         }
  556.         aWin->theWindow = _mt_window;
  557.         ((WindowPeek)aWin->theWindow)->windowKind = WIN_BASE_KIND + NHW_MAP;
  558.         get_tty_metrics(aWin->theWindow, &x_sz, &aWin->lin, &x_sz_p, &y_sz_p,
  559.                                          &aWin->fontNum, &aWin->fontSize,
  560.                                          &aWin->charWidth, &aWin->charHeight);
  561.         return i;
  562.     }
  563.  
  564.     aWin -> theWindow = GetNewWindow ( WIN_BASE_RES + type ,
  565.         ( WindowPtr ) 0L , ( WindowPtr ) -1L ) ;
  566.     ( ( WindowPeek ) aWin -> theWindow ) -> windowKind = WIN_BASE_KIND
  567.         + type ;
  568.     if ( ! ( aWin -> windowText = NewHandle ( TEXT_BLOCK ) ) ) {
  569.         error ( "NewHandle failed in create_nhwindow (%ld bytes)" ,
  570.             ( long ) TEXT_BLOCK ) ;
  571.         DisposeWindow ( aWin -> theWindow ) ;
  572.         aWin -> theWindow = (WindowPtr) NULL ;
  573.         return WIN_ERR ;
  574.     }
  575.     aWin -> lin = 0 ;
  576.     clear_nhwindow ( i ) ;
  577.  
  578. /*HARDCODED*/
  579.  
  580.     SetPort ( aWin -> theWindow ) ;
  581.     PenPat ( (void *) &qd . black ) ;
  582.  
  583.     switch ( type ) {
  584.         case NHW_MESSAGE :
  585.             GetFNum ( "\pPSHackFont", & aWin -> fontNum ) ;
  586.             aWin -> fontSize = flags.large_font ? 12 : 9 ;
  587.             break ;
  588.         default:
  589.             aWin -> fontNum = text_wind_font ;
  590.             aWin -> fontSize = 9 ;
  591.     }
  592.  
  593.     TextFont ( aWin -> fontNum ) ; 
  594.     TextSize ( aWin -> fontSize ) ;
  595.  
  596.     if (type == NHW_MESSAGE && !top_line) {
  597.         const Rect out_of_scr = { 10000, 10000, 10100, 10100 };
  598.         TextFace(bold);
  599.         top_line = TENew(&out_of_scr, &out_of_scr);
  600.         TEActivate(top_line);
  601.         TextFace(normal);
  602.     }
  603.  
  604.     {
  605.         FontInfo fi ;
  606.         GetFontInfo ( & fi ) ;
  607.         aWin -> leading = fi . leading / 2 + fi . descent ;
  608.         aWin -> charHeight = fi . ascent + fi . descent + fi . leading ;
  609.         aWin -> charWidth = fi . widMax ;
  610.     }
  611.     SetPt ( & ( theWindows [ i ] . cursor ) , 0 , 0 ) ;
  612.  
  613.     siz = aWin -> theWindow -> portRect ;
  614.     OffsetRect ( & siz , 30 + rn2 ( 20 ) , 250 + rn2 ( 50 ) ) ;
  615.     SizeWindow ( aWin -> theWindow , siz . right - siz . left ,
  616.         siz . bottom - siz . top , FALSE ) ;
  617.     MoveWindow ( aWin -> theWindow , siz . left , siz . top , FALSE ) ;
  618.  
  619.     if ( type == NHW_MENU || type == NHW_TEXT || type == NHW_MESSAGE ) {
  620.         Rect r = siz ;
  621.         Boolean bool ;
  622.         OffsetRect ( & r , - r . left , - r . top ) ;
  623.         r . left = r . right - SBARWIDTH ;
  624.         r . bottom -= SBARHEIGHT ;
  625.         r . top -= 1 ;
  626.         r . right += 1 ;
  627.         bool = ( r . bottom > r . top + 50 ) ;
  628.         aWin -> scrollBar = NewControl ( aWin -> theWindow , & r , "\P" ,
  629.             bool , 0 , 0 , 0 , 16 , 0L ) ;
  630.     }
  631.     aWin -> scrollPos = 0 ;
  632.  
  633.     return i ;
  634. }
  635.  
  636.  
  637. static MenuHandle
  638. mustGetMHandle(int menu_id)
  639. {
  640.     MenuHandle menu = GetMHandle(menu_id);
  641.     if (menu == (MenuHandle)  nil) {
  642.         comment("Cannot find the menu.", menu_id);
  643.         ExitToShell();
  644.     }
  645.     return menu;
  646. }
  647.  
  648.  
  649. #define A_LOT 0x7fffffff
  650. #define HEAP_SPACE 100000
  651. #define RES_FACTOR 1.1
  652.  
  653. static long
  654. SpaceToLoad ( char * name ) {
  655. FCBPBRec fcb ;
  656. long ret ;
  657.  
  658.     memset ( & fcb , 0 , sizeof ( fcb ) ) ;
  659.  
  660.     fcb . ioRefNum = CurResFile ( ) ;
  661.     fcb . ioNamePtr = (uchar *) name ;
  662.     if ( PBGetFCBInfoSync ( & fcb ) ) {
  663.         return A_LOT ;
  664.     }
  665.     ret = fcb . ioFCBEOF * RES_FACTOR + HEAP_SPACE ;
  666.     dprintf ( "Space needed %ld" , ret ) ;
  667.     return ret ;
  668. }
  669.  
  670.  
  671. void
  672. InitRes ( void )
  673. {
  674.     InitMenuRes();
  675. }
  676.  
  677.  
  678. void
  679. mac_init_nhwindows ( void )
  680. {
  681.     int i ;
  682.  
  683.     Rect scr = (*GetGrayRgn())->rgnBBox;
  684.     small_screen = scr.bottom - scr.top <=    9*40 ||
  685.                    scr.bottom - scr.top <= 12*40 && flags.large_font;
  686.  
  687.     InitRes ( ) ;
  688.  
  689.     theWindows = ( NhWindow * ) NewPtr ( NUM_MACWINDOWS *
  690.         sizeof ( NhWindow ) ) ;
  691.     mustwork(MemError());
  692.  
  693.     for ( i = 0 ; i < NUM_MACWINDOWS ; i ++ ) {
  694.         theWindows [ i ] . theWindow = (WindowPtr) NULL ;
  695.     }
  696.     for ( i = 0 ; i < QUEUE_LEN ; i ++ ) {
  697.         keyQueue [ i ] = 0 ;
  698.     }
  699.  
  700.     DimMenuBar ( ) ;
  701.  
  702.     tty_init_nhwindows();
  703.     flags.window_inited = TRUE;
  704.  
  705.     /* Some ugly hacks to make both interfaces happy */
  706.     mac_create_nhwindow(NHW_BASE);
  707.     tty_create_nhwindow(NHW_MESSAGE);
  708. }
  709.  
  710.  
  711. void
  712. mac_nhbell ( void )
  713. {
  714.     Handle h ;
  715.  
  716.     if ( h = GetNamedResource ( 'snd ' , "\PNetHack Bell" ) ) {
  717.  
  718.         HLock ( h ) ;
  719.         SndPlay ( ( SndChannelPtr ) NULL , h , 0 ) ;
  720.         ReleaseResource ( h ) ;
  721.  
  722.     } else {
  723.  
  724.         SysBeep ( 30 ) ;
  725.     }
  726. }
  727.  
  728.  
  729. static void
  730. DrawScrollbar ( NhWindow * aWin , WindowPtr theWindow )
  731. {
  732. Rect r2 = theWindow -> portRect ;
  733. Rect r = r2 ;
  734. Boolean vis ;
  735. short val , lin ;
  736.  
  737.     if ( ! aWin -> scrollBar ) {
  738.         return ;
  739.     }
  740.  
  741.     r2 . left = r2 . right - SBARWIDTH ;
  742.     r2 . bottom -= SBARHEIGHT ;
  743.     r2 . right += 1 ;
  744.     r2 . top -= 1 ;
  745.     if ( ( * aWin -> scrollBar ) -> contrlRect . top  != r2 . top ||
  746.          ( * aWin -> scrollBar ) -> contrlRect . left != r2 . left ) {
  747.         MoveControl ( aWin -> scrollBar , r2 . left , r2 . top ) ;
  748.     }
  749.     if ( ( * aWin -> scrollBar ) -> contrlRect . bottom != r2 . bottom ||
  750.          ( * aWin -> scrollBar ) -> contrlRect . right  != r2 . right ) {
  751.         SizeControl ( aWin -> scrollBar , r2 . right  - r2 . left ,
  752.                                           r2 . bottom - r2 . top ) ;
  753.     }
  754.     vis = ( r2 . bottom > r2 . top + 50 ) ;
  755.     if ( vis && ! ( * aWin -> scrollBar ) -> contrlVis ) {
  756.         ShowControl ( aWin -> scrollBar ) ;
  757.     } else if ( ! vis && ( * aWin -> scrollBar ) -> contrlVis ) {
  758.         HideControl ( aWin -> scrollBar ) ;
  759.     }
  760.     lin = aWin -> lin;
  761.     if ( aWin == theWindows + WIN_MESSAGE ) {
  762.         short min ;
  763.         r . bottom -= SBARHEIGHT + 1 ;
  764.         min = aWin -> save_lin + ( r . bottom - r . top ) / aWin ->
  765.             charHeight ;
  766.         if ( lin < min ) {
  767.             lin = min ;
  768.         }
  769.     }
  770.     if ( lin ) {
  771.         short max = lin - ( r . bottom - r . top ) / aWin -> charHeight ;
  772.         if ( max < 0 ) {
  773.             max = 0 ;
  774.         }
  775.         SetCtlMax ( aWin -> scrollBar , max ) ;
  776.         if ( max ) {
  777.             HiliteControl ( aWin -> scrollBar , 0 ) ;
  778.         } else {
  779.             HiliteControl ( aWin -> scrollBar , 255 ) ;
  780.         }
  781.     } else {
  782.         HiliteControl ( aWin -> scrollBar , 255 ) ;
  783.     }
  784.     val = GetCtlValue ( aWin -> scrollBar ) ;
  785.     if ( val != aWin -> scrollPos ) {
  786.         InvalRect ( & ( theWindow -> portRect ) ) ;
  787.         aWin -> scrollPos = val ;
  788.     }
  789.     if ( aWin == asyDSC ) {
  790.         asyDSC = (NhWindow *) NULL ;
  791.     }
  792. }
  793.  
  794.  
  795. static void
  796. InvalScrollBar ( NhWindow * aWin )
  797. {
  798.     if ( asyDSC && asyDSC != aWin ) {
  799.         SetPort ( asyDSC -> theWindow ) ;
  800.         DrawScrollbar ( asyDSC , asyDSC -> theWindow ) ;
  801.     }
  802.     asyDSC = aWin ;
  803. }
  804.  
  805.  
  806. void
  807. mac_clear_nhwindow ( winid win )
  808. {
  809.     long l ;
  810.     Rect r ;
  811.     WindowPtr theWindow ;
  812.     NhWindow * aWin = & theWindows [ win ] ;
  813.  
  814.     if ( win < 0 || win >= NUM_MACWINDOWS ) {
  815.         error ( "Invalid window %d in clear_nhwindow." , win ) ;
  816.         return ;
  817.     }
  818.  
  819.     theWindow = aWin -> theWindow ;
  820.     if (theWindow == _mt_window) {
  821.         tty_clear_nhwindow(win);
  822.         return;
  823.     }
  824.  
  825.     if ( aWin -> clear )
  826.         return ;
  827.     if ( ! theWindow ) {
  828.         error ( "Unallocated window %d in clear_nhwindow." , win ) ;
  829.         return ;
  830.     }
  831.     SetPort ( theWindow ) ;
  832.     r = theWindow -> portRect ;
  833.     if ( aWin -> scrollBar )
  834.         r . right -= SBARWIDTH + 1 ;
  835.     if ( aWin == theWindows + WIN_MESSAGE )
  836.         r . bottom -= SBARHEIGHT + 1 ;
  837.     InvalRect ( & r ) ;
  838.     switch ( ( ( WindowPeek ) theWindow ) -> windowKind - WIN_BASE_KIND ) {
  839.     case NHW_MESSAGE :
  840.         l = 0;
  841.         while (aWin->lin > flags.msg_history) {
  842.             const char cr = CHAR_CR;
  843.             l = Munger(aWin->windowText, l, &cr, 1, nil, 0) + 1;
  844.             --aWin->lin;
  845.         }
  846.         if (l) {
  847.             aWin->windowTextLen -= l;
  848.             BlockMove(*aWin->windowText + l, *aWin->windowText, aWin->windowTextLen);
  849.         }
  850.         aWin->last_more_lin = aWin->lin;
  851.         aWin->save_lin        = aWin->lin;
  852.         aWin->scrollPos = aWin->lin ? aWin->lin - 1 : 0;
  853.         if (aWin->scrollBar) {
  854.             SetCtlMax  (aWin->scrollBar, aWin->lin);
  855.             SetCtlValue(aWin->scrollBar, aWin->scrollPos);
  856.             InvalScrollBar(aWin);
  857.         }
  858.         break ;
  859.     default :
  860.         SetHandleSize ( aWin -> windowText , TEXT_BLOCK ) ;
  861.         aWin -> windowTextLen = 0L ;
  862.         aWin -> lin = 0 ;
  863.         aWin -> wid = 0 ;
  864.         aWin -> scrollPos = 0 ;
  865.         if ( aWin -> scrollBar ) {
  866.             SetCtlMax ( aWin -> scrollBar , 0 ) ;
  867.             InvalScrollBar ( aWin ) ;
  868.         }
  869.         break ;
  870.     }
  871.     SetPt ( & ( aWin -> cursor ) , 0 , 0 ) ;
  872.     aWin -> clear = 1 ;
  873. }
  874.  
  875.  
  876. Boolean
  877. ClosingWindowChar(const int c) {
  878.     return  c == CHAR_ESC || c == CHAR_BLANK || c == CHAR_LF || c == CHAR_CR ||
  879.             c == 'q' ;
  880. }
  881.  
  882.  
  883. #define BTN_IND 2
  884. #define BTN_W    40
  885. #define BTN_H    (SBARHEIGHT-2)
  886.  
  887. static void
  888. topl_resp_rect(int resp_idx, Rect *r)
  889. {
  890.     r->left      = (BTN_IND + BTN_W) * resp_idx + BTN_IND;
  891.     r->right  = r->left + BTN_W;
  892.     r->bottom = theWindows[WIN_MESSAGE].theWindow->portRect.bottom - 1;
  893.     r->top      = r->bottom - BTN_H;
  894. }
  895.  
  896.  
  897. Boolean
  898. in_topl_mode(void)
  899. {
  900.     return top_line &&
  901.            (*top_line)->viewRect.left < theWindows[WIN_MESSAGE].theWindow->portRect.right;
  902. }
  903.  
  904.  
  905. void
  906. enter_topl_mode(char *query)
  907. {
  908.     if (!top_line || in_topl_mode())
  909.         Debugger();
  910.  
  911.     putstr(WIN_MESSAGE, ATR_BOLD, query);
  912.  
  913.     (*top_line)->viewRect.left = 0;
  914.  
  915.     topl_query_len = strlen(query);
  916.     (*top_line)->selStart = topl_query_len;
  917.     (*top_line)->selEnd      = topl_query_len;
  918.     PtrToXHand(query, (*top_line)->hText, topl_query_len);
  919.     TECalText(top_line);
  920.  
  921.     display_nhwindow(WIN_MESSAGE, FALSE);
  922. }
  923.  
  924.  
  925. void
  926. leave_topl_mode(char *answer)
  927. {
  928.     int ans_len = (*top_line)->teLength - topl_query_len;
  929.     NhWindow *aWin = theWindows + WIN_MESSAGE;
  930.  
  931.     if (!in_topl_mode())
  932.         Debugger();
  933.  
  934.     BlockMove(*(*top_line)->hText + topl_query_len, answer, ans_len);
  935.     answer[ans_len] = '\0';
  936.  
  937.     if ( aWin -> windowTextLen > 0 &&
  938.          ( * aWin -> windowText ) [ aWin -> windowTextLen - 1 ] == CHAR_CR ) {
  939.         -- aWin -> windowTextLen ;
  940.         -- aWin -> lin ;
  941.     }
  942.     putstr(WIN_MESSAGE, ATR_BOLD, answer);
  943.  
  944.     (*top_line)->viewRect.left += 10000;
  945. }
  946.  
  947. /*
  948.  * TESetSelect flushes out all the pending key strokes.  I hate it.
  949.  */
  950. static void
  951. topl_set_select(short selStart, short selEnd)
  952. {
  953.     TEDeactivate(top_line);
  954.     (*top_line)->selStart = selStart;
  955.     (*top_line)->selEnd      = selEnd;
  956.     TEActivate(top_line);
  957. }
  958.  
  959.  
  960. static void
  961. topl_replace(char *new_ans)
  962. {
  963.     topl_set_select(topl_query_len, (*top_line)->teLength);
  964.     TEDelete(top_line);
  965.     TEInsert(new_ans, strlen(new_ans), top_line);
  966. }
  967.  
  968.  
  969. Boolean
  970. topl_key(unsigned char ch)
  971. {
  972.     switch (ch) {
  973.         case CHAR_ESC:
  974.             topl_replace("\x1b");
  975.             return false;
  976.         case CHAR_ENTER: case CHAR_CR: case CHAR_LF:
  977.             return false;
  978.  
  979.         case 0x1f & 'P':
  980.             nh_doprev_message();
  981.             return true;
  982.         case '\x1e'/* up arrow */:
  983.             topl_set_select(topl_query_len, topl_query_len);
  984.             return true;
  985.         case CHAR_BS: case '\x1c'/* left arrow */:
  986.             if ((*top_line)->selEnd > topl_query_len)
  987.                 TEKey(ch, top_line);
  988.             return true;
  989.         default:
  990.             TEKey(ch, top_line);
  991.             return true;
  992.     }
  993. }
  994.  
  995.  
  996. Boolean
  997. topl_ext_key(unsigned char ch)
  998. {
  999.     switch (ch) {
  1000.         case CHAR_ESC:
  1001.             topl_replace("\x1b");
  1002.             return false;
  1003.         case CHAR_ENTER: case CHAR_CR: case CHAR_LF:
  1004.             return false;
  1005.  
  1006.         case 0x1f & 'P':
  1007.             nh_doprev_message();
  1008.             return true;
  1009.         case CHAR_BS:
  1010.             topl_replace("");
  1011.             return true;
  1012.         default: {
  1013.             int com_index = -1, oindex = 0;
  1014.             TEInsert(&ch, 1, top_line);
  1015.             while(extcmdlist[oindex].ef_txt != NULL){
  1016.                 if(!strncmpi(*(*top_line)->hText + topl_query_len,
  1017.                              extcmdlist[oindex].ef_txt,
  1018.                              (*top_line)->teLength - topl_query_len))
  1019.                     if(com_index == -1) /* No matches yet*/
  1020.                         com_index = oindex;
  1021.                     else /* More than 1 match */
  1022.                         com_index = -2;
  1023.                 oindex++;
  1024.             }
  1025.             if(com_index >= 0)
  1026.                 topl_replace((char *) extcmdlist[com_index].ef_txt);
  1027.             return true;
  1028.         }
  1029.     }
  1030. }
  1031.  
  1032.  
  1033. void
  1034. topl_flash_resp(int resp_idx)
  1035. {
  1036.     long dont_care;
  1037.     Rect frame;
  1038.     SetPort(theWindows[WIN_MESSAGE].theWindow);
  1039.     topl_resp_rect(resp_idx, &frame);
  1040.     InsetRect(&frame, 1, 1);
  1041.     InvertRect(&frame);
  1042.     Delay(GetDblTime() / 2, &dont_care);
  1043.     InvertRect(&frame);
  1044. }
  1045.  
  1046.  
  1047. void
  1048. topl_set_def(int new_def_idx)
  1049. {
  1050.     Rect frame;
  1051.     SetPort(theWindows[WIN_MESSAGE].theWindow);
  1052.     topl_resp_rect(topl_def_idx, &frame);
  1053.     InvalRect(&frame);
  1054.     topl_def_idx = new_def_idx;
  1055.     topl_resp_rect(new_def_idx, &frame);
  1056.     InvalRect(&frame);
  1057. }
  1058.  
  1059.  
  1060. void
  1061. topl_set_resp(char *resp, char def)
  1062. {
  1063.     char *loc;
  1064.     Rect frame;
  1065.     int r_len, r_len1;
  1066.  
  1067.     if (!resp) {
  1068.         const char any_str[2] = { CHAR_ANY, '\0' };
  1069.         resp = (char *) any_str;
  1070.         def = CHAR_ANY;
  1071.     }
  1072.  
  1073.     SetPort(theWindows[WIN_MESSAGE].theWindow);
  1074.     r_len1 = strlen(resp);
  1075.     r_len  = strlen(topl_resp);
  1076.     if (r_len < r_len1)
  1077.         r_len = r_len1;
  1078.     topl_resp_rect(0, &frame);
  1079.     frame.right = (BTN_IND + BTN_W) * r_len;
  1080.     InvalRect(&frame);
  1081.  
  1082.     strcpy(topl_resp, resp);
  1083.     loc = strchr (resp, def);
  1084.     topl_def_idx = loc ? loc - resp : -1;
  1085. }
  1086.  
  1087.  
  1088. static char
  1089. topl_resp_key(char ch)
  1090. {
  1091.     if (strlen(topl_resp) > 0) {
  1092.         char *loc = strchr(topl_resp, ch);
  1093.  
  1094.         if (!loc)
  1095.             if (ch == '\x9'/* tab */) {
  1096.                 topl_set_def(topl_def_idx <= 0 ? strlen(topl_resp)-1 : topl_def_idx-1);
  1097.                 ch = '\0';
  1098.  
  1099.             } else if (ch == CHAR_ESC) {
  1100.                 loc = strchr(topl_resp, 'q');
  1101.                 if (!loc) {
  1102.                     loc = strchr(topl_resp, 'n');
  1103.                     if (!loc && topl_def_idx >= 0)
  1104.                         loc = topl_resp + topl_def_idx;
  1105.                 }
  1106.  
  1107.             } else if (ch == (0x1f & 'P')) {
  1108.                 nh_doprev_message();
  1109.                 ch = '\0';
  1110.  
  1111.             } else if (topl_def_idx >= 0) {
  1112.                 if ( ch == CHAR_ENTER || ch == CHAR_CR || ch == CHAR_LF ||
  1113.                      ch == CHAR_BLANK || topl_resp[topl_def_idx] == CHAR_ANY )
  1114.                     loc = topl_resp + topl_def_idx;
  1115.  
  1116.                 else if (strchr(topl_resp, '#')) {
  1117.                     if (digit(ch)) {
  1118.                         topl_set_def(strchr(topl_resp, '#') - topl_resp);
  1119.                         TEKey(ch, top_line);
  1120.                         ch = '\0';
  1121.  
  1122.                     } else if (topl_resp[topl_def_idx] == '#')
  1123.                         if (ch == '\x1e'/* up arrow */) {
  1124.                             topl_set_select(topl_query_len, topl_query_len);
  1125.                             ch = '\0';
  1126.                         } else if (ch == '\x1d'/* right arrow */ ||
  1127.                                    ch == '\x1f'/* down arrow */ ||
  1128.                                    (ch == CHAR_BS || ch == '\x1c'/* left arrow */) &&
  1129.                                         (*top_line)->selEnd > topl_query_len) {
  1130.                             TEKey(ch, top_line);
  1131.                             ch = '\0';
  1132.                         }
  1133.                 }
  1134.             }
  1135.  
  1136.         if (loc) {
  1137.             topl_flash_resp(loc - topl_resp);
  1138.             if (*loc != CHAR_ANY)
  1139.                 ch = *loc;
  1140.             TEKey(ch, top_line);
  1141.         }
  1142.     }
  1143.  
  1144.     return ch;
  1145. }
  1146.  
  1147.  
  1148. void
  1149. adjust_window_pos(NhWindow *aWin, WindowPtr theWindow, short w)
  1150. {
  1151. #ifdef THINK_C
  1152.     Rect scr_r   = (*GetGrayRgn())->rgnBBox, win_ind = { 20, 2, 3, 3 };
  1153. #else
  1154.     const Rect scr_r   = (*GetGrayRgn())->rgnBBox, win_ind = { 20, 2, 3, 3 };
  1155. #endif
  1156.     const short    min_w = theWindow->portRect.right - theWindow->portRect.left,
  1157.                 max_w = scr_r.right - scr_r.left - win_ind.left - win_ind.right;
  1158.     Point pos;
  1159.     short h = aWin->lin * aWin->charHeight, max_h;
  1160.  
  1161.     SetPort(theWindow);
  1162.     if (!RetrieveWinPos(theWindow, &pos.v, &pos.h)) {
  1163.         pos.v = theWindow->portRect.top;
  1164.         pos.h = theWindow->portRect.left;
  1165.         LocalToGlobal(&pos);
  1166.     }
  1167.  
  1168.     max_h = full_screen ? scr_r.bottom - win_ind.bottom - scr_r.top - win_ind.top
  1169.                         : scr_r.bottom - win_ind.bottom - pos.v;
  1170.     if (h > max_h      ) h = max_h;
  1171.     if (h < MIN_HEIGHT) h = MIN_HEIGHT;
  1172.     if (w < min_w      ) w = min_w;
  1173.     if (w > max_w      ) w = max_w;
  1174.     SizeWindow(theWindow, w, h, true);
  1175.  
  1176.     if (pos.v + h + win_ind.bottom > scr_r.bottom)
  1177.         pos.v = scr_r.bottom - h - win_ind.bottom;
  1178.     if (pos.h + w + win_ind.right  > scr_r.right)
  1179.         pos.h = scr_r.right     - w - win_ind.right;
  1180.     MoveWindow(theWindow, pos.h, pos.v, false);
  1181. }
  1182.  
  1183.  
  1184. /*
  1185.  * display/select/update the window.
  1186.  * If f is true, this window should be "modal" - don't return
  1187.  * until presumed seen.
  1188.  */
  1189. void
  1190. mac_display_nhwindow ( winid win , BOOLEAN_P f )
  1191. {
  1192.     WindowPtr theWindow ;
  1193.     NhWindow * aWin = & theWindows [ win ] ;
  1194.  
  1195.     if ( win < 0 || win >= NUM_MACWINDOWS ) {
  1196.         error ( "Invalid window %d in display_nhwindow." , win ) ;
  1197.         return ;
  1198.     }
  1199.     theWindow = aWin -> theWindow ;
  1200.     if ( ! theWindow ) {
  1201.         error ( "Unallocated window %d in display_nhwindow." , win ) ;
  1202.         return ;
  1203.     }
  1204.  
  1205.     if (theWindow == _mt_window) {
  1206.         tty_display_nhwindow(win, f);
  1207.         return;
  1208.     }
  1209.  
  1210.     if ( f && inSelect == WIN_ERR && win == WIN_MESSAGE ) {
  1211.         topl_set_resp ( NULL , 0 ) ;
  1212.         if ( aWin -> windowTextLen > 0 &&
  1213.              ( * aWin -> windowText ) [ aWin -> windowTextLen - 1 ] == CHAR_CR ) {
  1214.             -- aWin -> windowTextLen ;
  1215.             -- aWin -> lin ;
  1216.         }
  1217.         putstr ( win , flags . standout ? ATR_INVERSE : ATR_NONE , " --More--" ) ;
  1218.     }
  1219.  
  1220.     if ( ! ( ( WindowPeek ) theWindow ) -> visible || full_screen ) {
  1221.  
  1222.         if ( win != WIN_MESSAGE ) {
  1223.             const char cr = CHAR_CR;
  1224.             short w = 0;
  1225.             long line_start = 0;
  1226.             HLock(aWin->windowText);
  1227.  
  1228.             while (line_start < aWin->windowTextLen) {
  1229.                 long line_end;
  1230.                 short line_w;
  1231.                 line_end = Munger(aWin->windowText, line_start, &cr, 1, nil, 0);
  1232.                 if (line_end < 0)
  1233.                     line_end = aWin->windowTextLen;
  1234.                 line_w = TextWidth(*aWin->windowText, line_start, line_end - line_start);
  1235.                 if (w < line_w)
  1236.                     w = line_w;
  1237.                 line_start = line_end + 1;
  1238.             }
  1239.             HUnlock(aWin->windowText);
  1240.  
  1241.             adjust_window_pos(aWin, theWindow, w + (SBARWIDTH+2));
  1242.         }
  1243.  
  1244.         if ( ! small_screen || win != WIN_MESSAGE || f )
  1245.             SelectWindow ( theWindow ) ;
  1246.         ShowWindow ( theWindow ) ;
  1247.     }
  1248.  
  1249.     SetPort ( theWindow ) ;
  1250.     if ( aWin -> scrollBar ) {
  1251.         InvalScrollBar ( aWin ) ;
  1252.     }
  1253.  
  1254.     if ( f && inSelect == WIN_ERR ) {
  1255.         int ch ;
  1256.  
  1257.         inSelect = win ;
  1258.         do {
  1259.             ch = nhgetch ( ) ;
  1260.         } while ( ! ClosingWindowChar ( ch ) ) ;
  1261.         inSelect = WIN_ERR ;
  1262.  
  1263.         if ( win == WIN_MESSAGE )
  1264.             topl_set_resp ( "" , '\0' ) ;
  1265.         else
  1266.             HideWindow ( theWindow ) ;
  1267.  
  1268.     } else {
  1269.         wait_synch ( ) ;
  1270.     }
  1271. }
  1272.  
  1273.  
  1274. void
  1275. mac_destroy_nhwindow ( winid win )
  1276. {
  1277.     WindowPtr theWindow ;
  1278.     NhWindow * aWin = & theWindows [ win ] ;
  1279.     int kind , visible ;
  1280.  
  1281.     if ( win < 0 || win >= NUM_MACWINDOWS ) {
  1282.         if ( flags . window_inited )
  1283.             error ( "Invalid window number %d (Max %d) in destroy_nhwindow." ,
  1284.                 win , NUM_MACWINDOWS ) ;
  1285.         return ;
  1286.     }
  1287.     theWindow = aWin -> theWindow ;
  1288.     if ( ! theWindow ) {
  1289.         error ( "Not allocated window number %d in destroy_nhwindow." ,
  1290.             win ) ;
  1291.         return ;
  1292.     }
  1293. /*
  1294.  *    if (theWindow == _mt_window) {
  1295.  *        tty_destroy_nhwindow(win);
  1296.  *        return;
  1297.  *    }
  1298.  */
  1299.  
  1300.     /*
  1301.      * Check special windows.
  1302.      * The base window should never go away.
  1303.      * The other "standard" windows should not go away
  1304.      * unless we've exitted nhwindows.
  1305.      */
  1306.     if ( win == BASE_WINDOW ) {
  1307.         return ;
  1308.     }
  1309.     if ( win == WIN_INVEN || win == WIN_MESSAGE ) {
  1310.         if ( flags . window_inited ) {
  1311.             if ( flags . tombstone && killer ) {
  1312.                 /* Prepare for the coming of the tombstone window. */
  1313.                 mono_font ( ) ;
  1314.                 full_screen = TRUE ;
  1315.             }
  1316.             return ;
  1317.         }
  1318.     }
  1319.  
  1320.     kind = ( ( WindowPeek ) theWindow ) -> windowKind - WIN_BASE_KIND ;
  1321.     visible = ( ( WindowPeek ) theWindow ) -> visible ;
  1322.  
  1323.     if ( ( ! visible || ( kind != NHW_MENU && kind != NHW_TEXT ) ) &&
  1324.         theWindow != _mt_window ) {
  1325.         DisposeWindow ( theWindow ) ;
  1326.         if ( aWin -> windowText ) {
  1327.             DisposHandle ( aWin -> windowText ) ;
  1328.         }
  1329.         aWin -> theWindow = (WindowPtr) NULL ;
  1330.         aWin -> windowText = (Handle) NULL ;
  1331.     }
  1332. }
  1333.  
  1334.  
  1335. void
  1336. mac_number_pad ( int pad )
  1337. {
  1338.     macPad = pad ;
  1339. }
  1340.  
  1341.  
  1342. void
  1343. trans_num_keys(EventRecord *theEvent)
  1344. {
  1345.     if (macPad) {
  1346.         Handle h = GetResource('Nump', theEvent->modifiers & shiftKey ? 129 : 128);
  1347.         if (h) {
  1348.             short *ab = (short *)*h;
  1349.             int i = ab[0];
  1350.             while (i) {
  1351.                 if ((theEvent->message & keyCodeMask) == (ab[i] & keyCodeMask)) {
  1352.                     theEvent->message = ab[i];
  1353.                     break;
  1354.                 }
  1355.                 --i;
  1356.             }
  1357.         }
  1358.     }
  1359. }
  1360.  
  1361.  
  1362. /*
  1363.  * Note; theWindow may very well be NULL here, since keyDown may call
  1364.  * it when theres no window !!!
  1365.  */
  1366. void
  1367. GeneralKey ( EventRecord * theEvent , WindowPtr theWindow )
  1368. {
  1369. #if defined(applec)
  1370. # pragma unused(theWindow)
  1371. #endif
  1372.     trans_num_keys ( theEvent ) ;
  1373.     AddToKeyQueue ( topl_resp_key ( theEvent -> message & 0xff ) , 1 ) ;
  1374. }
  1375.  
  1376.  
  1377. static void
  1378. macKeyNull ( EventRecord * theEvent , WindowPtr theWindow )
  1379. {
  1380.     GeneralKey ( theEvent , theWindow ) ;
  1381. }
  1382.  
  1383.  
  1384. static void
  1385. macKeyMessage ( EventRecord * theEvent , WindowPtr theWindow )
  1386. {
  1387.     GeneralKey ( theEvent , theWindow ) ;
  1388. }
  1389.  
  1390.  
  1391. static void
  1392. macKeyTerm ( EventRecord * theEvent , WindowPtr theWindow )
  1393. {
  1394.     GeneralKey ( theEvent , theWindow ) ;
  1395. }
  1396.  
  1397.  
  1398. static void
  1399. macKeyMenu ( EventRecord * theEvent , WindowPtr theWindow )
  1400. {
  1401.     if ( filter_scroll_key ( theEvent -> message & 0xff ,
  1402.         GetNhWin ( theWindow ) ) ) {
  1403.         GeneralKey ( theEvent , theWindow ) ;
  1404.     }
  1405. }
  1406.  
  1407.  
  1408. static void
  1409. macKeyText ( EventRecord * theEvent , WindowPtr theWindow )
  1410. {
  1411.     char c = filter_scroll_key ( theEvent -> message & 0xff ,
  1412.                                  GetNhWin ( theWindow ) ) ;
  1413.     if ( c )
  1414.         if ( inSelect == WIN_ERR && ClosingWindowChar ( c ) ) {
  1415.             HideWindow ( theWindow ) ;
  1416.             destroy_nhwindow ( GetNhWin ( theWindow ) - theWindows ) ;
  1417.         } else {
  1418.             GeneralKey ( theEvent , theWindow ) ;
  1419.         }
  1420. }
  1421.  
  1422.  
  1423. static void
  1424. macClickNull ( EventRecord * theEvent , WindowPtr theWindow )
  1425. {
  1426.     if ( ! theEvent || ! theWindow ) {
  1427.         Debugger ( ) ;
  1428.     }
  1429. }
  1430.  
  1431.  
  1432. static void
  1433. macClickMessage ( EventRecord * theEvent , WindowPtr theWindow )
  1434. {
  1435.     int r_idx = 0;
  1436.     Point mouse = theEvent->where;
  1437.     GlobalToLocal(&mouse);
  1438.     while (topl_resp[r_idx]) {
  1439.         Rect frame;
  1440.         topl_resp_rect(r_idx, &frame);
  1441.         InsetRect(&frame, 1, 1);
  1442.         if (PtInRect(mouse, &frame)) {
  1443.  
  1444.             Boolean in_btn = true;
  1445.             InvertRect(&frame);
  1446.             while (WaitMouseUp()) {
  1447.                 SystemTask();
  1448.                 GetMouse(&mouse);
  1449.                 if (PtInRect(mouse, &frame) != in_btn) {
  1450.                     in_btn = !in_btn;
  1451.                     InvertRect(&frame);
  1452.                 }
  1453.             }
  1454.             if (in_btn) {
  1455.                 InvertRect(&frame);
  1456.                 AddToKeyQueue ( topl_resp [ r_idx ] , 1 ) ;
  1457.             }
  1458.             return;
  1459.  
  1460.         }
  1461.         ++r_idx;
  1462.     }
  1463.  
  1464.     macClickText(theEvent, theWindow);
  1465. }
  1466.  
  1467.  
  1468. static void
  1469. macClickTerm ( EventRecord * theEvent , WindowPtr theWindow )
  1470. {
  1471.     int shift_down = theEvent->modifiers & shiftKey;
  1472.     NhWindow *nhw = GetNhWin(theWindow);
  1473.     Point where = theEvent->where;
  1474.         GlobalToLocal(&where);
  1475.         where.h = where.h / nhw->charWidth + 1;
  1476.         where.v = where.v / nhw->charHeight;
  1477.     clicked_mod = shift_down ? CLICK_2 : CLICK_1;
  1478.  
  1479.     if (strchr(topl_resp, click_to_cmd(where.h, where.v, clicked_mod)))
  1480.         nhbell();
  1481.     else {
  1482.         if (cursor_locked)
  1483.             while (WaitMouseUp())
  1484.                 SystemTask();
  1485.         else if (!shift_down)
  1486.             gNextClickRepeat = TickCount() + *(short *)KeyThresh;
  1487.         gClickedToMove = TRUE;
  1488.         clicked_pos = where;
  1489.     }
  1490. }
  1491.  
  1492. static amtToScroll = 0 ;
  1493. static NhWindow * winToScroll = (NhWindow *) NULL ;
  1494.  
  1495. static pascal void
  1496. Up ( ControlHandle theBar , short part )
  1497. {
  1498.     EventRecord fake ;
  1499.     short now = GetCtlValue ( theBar ) ;
  1500.     short min = GetCtlMin ( theBar ) ;
  1501.     Rect r ;
  1502.     RgnHandle rgn = NewRgn ( ) ;
  1503.  
  1504.     if ( ! part ) {
  1505.         return ;
  1506.     }
  1507.  
  1508.     if ( now - min < amtToScroll ) {
  1509.         amtToScroll = now - min ;
  1510.     }
  1511.     if ( ! amtToScroll ) {
  1512.         return ;
  1513.     }
  1514.     SetCtlValue ( theBar , now - amtToScroll ) ;
  1515.     winToScroll -> scrollPos = now - amtToScroll ;
  1516.     r = winToScroll -> theWindow -> portRect ;
  1517.     r . right -= SBARWIDTH ;
  1518.     if ( winToScroll == theWindows + WIN_MESSAGE )
  1519.         r . bottom -= SBARHEIGHT + 1 ;
  1520.     ScrollRect ( & r , 0 , amtToScroll * winToScroll -> charHeight , rgn ) ;
  1521.     if ( rgn ) {
  1522.         InvalRgn ( rgn ) ;
  1523.         BeginUpdate ( winToScroll -> theWindow ) ;
  1524.     }
  1525.     winToScroll -> updateFunc  ( & fake , winToScroll -> theWindow ) ;
  1526.     if ( rgn ) {
  1527.         EndUpdate ( winToScroll -> theWindow ) ;
  1528.         DisposeRgn ( rgn ) ;
  1529.     }
  1530. }
  1531.  
  1532.  
  1533. static pascal void
  1534. Down ( ControlHandle theBar , short part )
  1535. {
  1536.     EventRecord fake ;
  1537.     short now = GetCtlValue ( theBar ) ;
  1538.     short max = GetCtlMax ( theBar ) ;
  1539.     Rect r ;
  1540.     RgnHandle rgn = NewRgn ( ) ;
  1541.  
  1542.     if ( ! part ) {
  1543.         return ;
  1544.     }
  1545.  
  1546.     if ( max - now < amdow * aWin = GetNhWin ( theWindow ) ;
  1547.  
  1548.     r = theWindow -> portRect ;
  1549.     if ( aWin -> scrollBar && ( * aWin -> scrollBar ) -> contrlVis ) {
  1550.         short code ;
  1551.         Point p = theEvent -> where ;
  1552.         ControlHandle theBar ;
  1553.  
  1554.         r . right -= SBARWIDTH ;
  1555.         GlobalToLocal ( & p ) ;
  1556.         code = FindControl ( p , theWindow , & theBar ) ;
  1557.         if ( code ) {
  1558.             DoScrollBar ( p , code , theBar , aWin , theWindow ) ;
  1559.             return ;
  1560.         }
  1561.     }
  1562. }
  1563.  
  1564.  
  1565. static void
  1566. macUpdateNull ( EventRecord * theEvent , WindowPtr theWindow )
  1567. {
  1568.     if ( ! theEvent || ! theWindow ) {
  1569.         Debugger ( ) ;
  1570.     }
  1571. }
  1572.  
  1573.  
  1574. static void
  1575. draw_growicon_vert_only(WindowPtr wind) {
  1576.     GrafPtr org_port;
  1577.     RgnHandle org_clip = NewRgn();
  1578.     Rect r = wind->portRect;
  1579.     r.left = r.right - SBARWIDTH;
  1580.  
  1581.     GetPort(&org_port);
  1582.     SetPort(wind);
  1583.     GetClip(org_clip);
  1584.     ClipRect(&r);
  1585.     DrawGrowIcon(wind);
  1586.     SetClip(org_clip);
  1587.     DisposeRgn(org_clip);
  1588.     SetPort(org_port);
  1589. }
  1590.  
  1591.  
  1592. static void
  1593. macUpdateMessage ( EventRecord * theEvent , WindowPtr theWindow )
  1594. {
  1595.     RgnHandle org_clip = NewRgn(), clip = NewRgn();
  1596.     Rect r = theWindow -> portRect ;
  1597.     NhWindow * aWin = GetNhWin ( theWindow ) ;
  1598.     int l ;
  1599.  
  1600.     if ( ! theEvent ) {
  1601.         Debugger ( ) ;
  1602.     }
  1603.  
  1604.     GetClip(org_clip);
  1605.  
  1606.     DrawControls(theWindow);
  1607.     DrawGrowIcon(theWindow);
  1608.  
  1609.     l = 0;
  1610.     while (topl_resp[l]) {
  1611.         StringPtr name;
  1612.         unsigned char tmp[2];
  1613.         FontInfo font;
  1614.         Rect frame;
  1615.         topl_resp_rect(l, &frame);
  1616.         switch (topl_resp[l]) {
  1617.             case 'y':
  1618.                 name = "\pyes";
  1619.                 break;
  1620.             case 'n':
  1621.                 name = "\pno";
  1622.                 break;
  1623.             case 'N':
  1624.                 name = "\pNone";
  1625.                 break;
  1626.             case 'a':
  1627.                 name = "\pall";
  1628.                 break;
  1629.             case 'q':
  1630.                 name = "\pquit";
  1631.                 break;
  1632.             case CHAR_ANY:
  1633.                 name = "\pany key";
  1634.                 break;
  1635.             default:
  1636.                 tmp[0] = 1;
  1637.                 tmp[1] = topl_resp[l];
  1638.                 name = tmp;
  1639.                 break;
  1640.         }
  1641.         TextFont(geneva);
  1642.         TextSize(9);
  1643.         GetFontInfo(&font);
  1644.         MoveTo((frame.left + frame.right  - StringWidth(name)) / 2,
  1645.                (frame.top  + frame.bottom + font.ascent-font.descent-font.leading-1) / 2);
  1646.         DrawString(name);
  1647.         PenNormal();
  1648.         if (l == topl_def_idx)
  1649.             PenSize(2, 2);
  1650.         FrameRoundRect(&frame, 4, 4);
  1651.         ++l;
  1652.     }
  1653.  
  1654.     r . right -= SBARWIDTH + 2;
  1655.     r . bottom -= SBARHEIGHT + 1;
  1656.     /* Clip to the portrect - scrollbar/growicon *before* adjusting the rect
  1657.         to be larger than the size of the window (!) */
  1658.     RectRgn(clip, &r);
  1659.     SectRgn(clip, org_clip, clip);
  1660.     if ( r . right < MIN_RIGHT )
  1661.         r . right = MIN_RIGHT ;
  1662.     r . top -= aWin -> scrollPos * aWin -> charHeight ;
  1663.  
  1664. #if 0
  1665.     /* If you enable this band of code (and disable the next band), you will get
  1666.        fewer flickers but a slower performance while drawing the dot line. */
  1667.     {    RgnHandle dotl_rgn = NewRgn();
  1668.         Rect dotl;
  1669.         dotl.left    = r.left;
  1670.         dotl.right    = r.right;
  1671.         dotl.bottom = r.top + aWin->save_lin * aWin->charHeight;
  1672.         dotl.top    = dotl.bottom - 1;
  1673.         FillRect(&dotl, &qd.gray);
  1674.         RectRgn(dotl_rgn, &dotl);
  1675.         DiffRgn(clip, dotl_rgn, clip);
  1676.         DisposeRgn(dotl_rgn);
  1677.         SetClip(clip);
  1678.     }
  1679. #endif
  1680.  
  1681.     if (in_topl_mode()) {
  1682.         RgnHandle topl_rgn = NewRgn();
  1683.         Rect topl_r = r;
  1684.         topl_r.top += (aWin->lin - 1) * aWin->charHeight;
  1685.         l = (*top_line)->destRect.right - (*top_line)->destRect.left;
  1686.         (*top_line)->viewRect = topl_r;
  1687.         (*top_line)->destRect = topl_r;
  1688.         if (l != topl_r.right - topl_r.left)
  1689.             TECalText(top_line);
  1690.         TEUpdate(&topl_r, top_line);
  1691.         RectRgn(topl_rgn, &topl_r);
  1692.         DiffRgn(clip, topl_rgn, clip);
  1693.         DisposeRgn(topl_rgn);
  1694.         SetClip(clip);
  1695.     }
  1696.  
  1697.     DisposeRgn(clip);
  1698.  
  1699.     TextFont ( aWin -> fontNum ) ;
  1700.     TextSize ( aWin -> fontSize ) ;
  1701.     HLock ( aWin -> windowText ) ;
  1702.     TextBox ( * aWin -> windowText , aWin -> windowTextLen , & r , teJustLeft ) ;
  1703.     HUnlock ( aWin -> windowText ) ;
  1704.  
  1705. #if 1
  1706.     r.bottom = r.top + aWin->save_lin * aWin->charHeight;
  1707.     r.top     = r.bottom - 1;
  1708.     FillRect(&r, (void *) &qd.gray);
  1709. #endif
  1710.  
  1711.     SetClip(org_clip);
  1712.     DisposeRgn(org_clip);
  1713. }
  1714.  
  1715.  
  1716. static void
  1717. macUpdateTerm ( EventRecord * theEvent , WindowPtr theWindow )
  1718. {
  1719. #if defined(applec)
  1720. # pragma unused(theEvent)
  1721. #endif
  1722.     tty_environment_changed ( theWindow ) ;
  1723.     image_tty(theWindow);
  1724. }
  1725.  
  1726.  
  1727. static void
  1728. macUpdateMenu ( EventRecord * theEvent , WindowPtr theWindow )
  1729. {
  1730.     Rect r = theWindow -> portRect ;
  1731.     Rect r2 = r ;
  1732.     NhWindow * aWin = GetNhWin ( theWindow ) ;
  1733.     RgnHandle h ;
  1734.     Boolean vis ;
  1735.  
  1736.     if ( ! theEvent ) {
  1737.         Debugger ( ) ;
  1738.     }
  1739.  
  1740.     draw_growicon_vert_only(theWindow);
  1741.  
  1742.     r2 . left = r2 . right - SBARWIDTH ;
  1743.     r2 . right += 1 ;
  1744.     r2 . top -= 1 ;
  1745.     vis = ( r2 . bottom > r2 . top + 50 ) ;
  1746.     DrawControls ( theWindow ) ;
  1747.  
  1748.     h = (RgnHandle) NULL ;
  1749.     if ( vis && ( h = NewRgn ( ) ) ) {
  1750.         RgnHandle tmp = NewRgn ( ) ;
  1751.         if ( ! tmp ) {
  1752.             DisposeRgn ( h ) ;
  1753.             h = (RgnHandle) NULL ;
  1754.         } else {
  1755.             GetClip ( h ) ;
  1756.             RectRgn ( tmp , & r2 ) ;
  1757.             DiffRgn ( h , tmp , tmp ) ;
  1758.             SetClip ( tmp ) ;
  1759.             DisposeRgn ( tmp ) ;
  1760.         }
  1761.     }
  1762.     if ( r . right < MIN_RIGHT )
  1763.         r . right = MIN_RIGHT ;
  1764.     r . top -= aWin -> scrollPos * aWin -> charHeight ;
  1765.     HLock ( aWin -> windowText ) ;
  1766.     TextBox ( * aWin -> windowText , aWin -> windowTextLen , & r , teJustLeft ) ;
  1767.     HUnlock ( aWin -> windowText ) ;
  1768.     if ( h ) {
  1769.         SetClip ( h ) ;
  1770.         DisposeRgn ( h ) ;
  1771.     }
  1772. }
  1773.  
  1774.  
  1775. static void
  1776. macUpdateText ( EventRecord * theEvent , WindowPtr theWindow )
  1777. {
  1778.     Rect r = theWindow -> portRect ;
  1779.     Rect r2 = r ;
  1780.     NhWindow * aWin = GetNhWin ( theWindow ) ;
  1781.     RgnHandle h ;
  1782.     Boolean vis ;
  1783.  
  1784.     if ( ! theEvent ) {
  1785.         Debugger ( ) ;
  1786.     }
  1787.  
  1788.     r2 . left = r2 . right - SBARWIDTH ;
  1789.     r2 . right += 1 ;
  1790.     r2 . top -= 1 ;
  1791.     vis = ( r2 . bottom > r2 . top + 50 ) ;
  1792.     DrawControls ( theWindow ) ;
  1793.  
  1794.     h = (RgnHandle) NULL ;
  1795.     if ( vis && ( h = NewRgn ( ) ) ) {
  1796.         RgnHandle tmp = NewRgn ( ) ;
  1797.         if ( ! tmp ) {
  1798.             DisposeRgn ( h ) ;
  1799.             h = (RgnHandle) NULL ;
  1800.         } else {
  1801.             GetClip ( h ) ;
  1802.             RectRgn ( tmp , & r2 ) ;
  1803.             DiffRgn ( h , tmp , tmp ) ;
  1804.             SetClip ( tmp ) ;
  1805.             DisposeRgn ( tmp ) ;
  1806.         }
  1807.     }
  1808.     if ( r . right < MIN_RIGHT )
  1809.         r . right = MIN_RIGHT ;
  1810.     r . top -= aWin -> scrollPos * aWin -> charHeight ;
  1811.     r . right -= SBARWIDTH;
  1812.     HLock ( aWin -> windowText ) ;
  1813.     TextBox ( * aWin -> windowText , aWin -> windowTextLen , & r , teJustLeft ) ;
  1814.     HUnlock ( aWin -> windowText ) ;
  1815.     draw_growicon_vert_only(theWindow);
  1816.     if ( h ) {
  1817.         SetClip ( h ) ;
  1818.         DisposeRgn ( h ) ;
  1819.     }
  1820. }
  1821.  
  1822.  
  1823. static void
  1824. macCursorNull ( EventRecord * theEvent , WindowPtr theWindow , RgnHandle mouseRgn )
  1825. {
  1826. #if defined(applec)
  1827. # pragma unused(theWindow)
  1828. #endif
  1829.     Rect r = { -1 , -1 , 2 , 2 } ;
  1830.  
  1831.     InitCursor ( ) ;
  1832.     OffsetRect ( & r , theEvent -> where . h , theEvent -> where . v ) ;
  1833.     RectRgn ( mouseRgn , & r ) ;
  1834. }
  1835.  
  1836.  
  1837. static void
  1838. macCursorMessage ( EventRecord * theEvent , WindowPtr theWindow , RgnHandle mouseRgn )
  1839. {
  1840. #if defined(applec)
  1841. # pragma unused(theWindow)
  1842. #endif
  1843.     Rect r = { -1 , -1 , 2 , 2 } ;
  1844.  
  1845.     InitCursor ( ) ;
  1846.     OffsetRect ( & r , theEvent -> where . h , theEvent -> where . v ) ;
  1847.     RectRgn ( mouseRgn , & r ) ;
  1848. }
  1849.  
  1850.  
  1851. static void
  1852. macCursorTerm ( EventRecord * theEvent , WindowPtr theWindow , RgnHandle mouseRgn )
  1853. {
  1854.     Point where ;
  1855.     char * dir_bas , * dir ;
  1856.     CursHandle ch ;
  1857.     GrafPtr gp ;
  1858.     NhWindow * nhw = GetNhWin ( theWindow ) ;
  1859.     Rect r = { 0 , 0 , 1 , 1 } ;
  1860.  
  1861.     GetPort ( & gp ) ;
  1862.     SetPort ( theWindow ) ;
  1863.  
  1864.     where = theEvent -> where ;
  1865.     GlobalToLocal ( & where ) ;
  1866.  
  1867.     if ( cursor_locked )
  1868.         dir = NULL ;
  1869.     else {
  1870.         dir_bas = flags . num_pad ? (char *) ndir : (char *) sdir ;
  1871.         dir = strchr ( dir_bas , click_to_cmd ( where . h / nhw -> charWidth + 1 ,
  1872.                                                 where . v / nhw -> charHeight ,
  1873.                                                 CLICK_1 ) ) ;
  1874.     }
  1875.     ch = GetCursor ( dir ? dir - dir_bas + 513 : 512 ) ;
  1876.     if ( ch ) {
  1877.  
  1878.         HLock ( ( Handle ) ch ) ;
  1879.         SetCursor ( * ch ) ;
  1880.         HUnlock ( ( Handle ) ch ) ;
  1881.  
  1882.     } else {
  1883.  
  1884.         InitCursor ( ) ;
  1885.     }
  1886.     OffsetRect ( & r , theEvent -> where . h , theEvent -> where . v ) ;
  1887.     RectRgn ( mouseRgn , & r ) ;
  1888.  
  1889.     SetPort ( gp ) ;
  1890. }
  1891.  
  1892.  
  1893. static void
  1894. macCursorMenu ( EventRecord * theEvent , WindowPtr theWindow , RgnHandle mouseRgn )
  1895. {
  1896. #if defined(applec)
  1897. # pragma unused(theWindow)
  1898. #endif
  1899.     Rect r = { -1 , -1 , 2 , 2 } ;
  1900.  
  1901.     InitCursor ( ) ;
  1902.     OffsetRect ( & r , theEvent -> where . h , theEvent -> where . v ) ;
  1903.     RectRgn ( mouseRgn , & r ) ;
  1904. }
  1905.  
  1906.  
  1907. static void
  1908. macCursorText ( EventRecord * theEvent , WindowPtr theWindow , RgnHandle mouseRgn )
  1909. {
  1910. #if defined(applec)
  1911. # pragma unused(theWindow)
  1912. #endif
  1913.     Rect r = { -1 , -1 , 2 , 2 } ;
  1914.  
  1915.     InitCursor ( ) ;
  1916.     OffsetRect ( & r , theEvent -> where . h , theEvent -> where . v ) ;
  1917.     RectRgn ( mouseRgn , & r ) ;
  1918. }
  1919.  
  1920.  
  1921. void
  1922. UpdateMeng
  1923.             int ix;
  1924.             for ( ix = 0 ; ix < QUEUE_LEN ; ix ++ ) {
  1925.                 keyQueue [ ix ] = 0 ;
  1926.             }
  1927.             FlushEvents ( keyDownMask , 0 ) ;
  1928.         }
  1929.         break ;
  1930.     }
  1931. }
  1932.  
  1933.  
  1934. long doDawdle = 0L ;
  1935.  
  1936. void
  1937. WindowGoAway ( EventRecord * theEvent, WindowPtr theWindow )
  1938. {
  1939.     NhWindow * aWin = GetNhWin(theWindow);
  1940.  
  1941.     if ( ! theEvent || TrackGoAway ( theWindow , theEvent -> where ) ) {
  1942.         if ( aWin - theWindows == BASE_WINDOW && ! flags . window_inited ) {
  1943.             AddToKeyQueue ( '\033' , 1 ) ;
  1944.             return ;
  1945.         } else {
  1946.             HideWindow ( theWindow ) ;
  1947.         }
  1948.         if ( inSelect == WIN_ERR || aWin - theWindows != inSelect ) {
  1949.             destroy_nhwindow ( aWin - theWindows ) ;
  1950.         } else {
  1951.             AddToKeyQueue ( '\033' , 1 ) ;
  1952.         }
  1953.     }
  1954. }
  1955.  
  1956. void
  1957. DimMenuBar ( void )
  1958. {
  1959.     extern void AdjustMenus(short);
  1960.  
  1961.     AdjustMenus(1);
  1962. }
  1963.  
  1964.  
  1965. void
  1966. UndimMenuBar ( void )
  1967. {
  1968.     extern void AdjustMenus(short);
  1969.  
  1970.     AdjustMenus(0);
  1971. }
  1972.  
  1973. static int mBarDimmed = 0 ;
  1974.  
  1975. void
  1976. mac_get_nh_event( void )
  1977. {
  1978.     EventRecord anEvent ;
  1979.  
  1980.     if ( ( inSelect == WIN_ERR && flags . window_inited && ! in_topl_mode ( ) )
  1981.          == mBarDimmed )
  1982.         if ( mBarDimmed ) {
  1983.             UndimMenuBar ( ) ;
  1984.             mBarDimmed = 0 ;
  1985.         } else {
  1986.             DimMenuBar ( ) ;
  1987.             mBarDimmed = 1 ;
  1988.         }
  1989.     /*
  1990.      * We want to take care of keys in the buffer as fast as
  1991.      * possible
  1992.      */
  1993.     if ( keyQueue [ 0 ] ) {
  1994.         doDawdle = 0L ;
  1995.     }
  1996.     if ( asyDSC ) {
  1997.         SetPort ( asyDSC -> theWindow ) ;
  1998.         DrawScrollbar ( asyDSC , asyDSC -> theWindow ) ;
  1999.     }
  2000.     if ( kApplicInFront ) {
  2001.         AdjustMenus ( 0 ) ;
  2002.     }
  2003.     (void) WaitNextEvent ( -1 , & anEvent , doDawdle , gMouseRgn ) ;
  2004.     doDawdle = 0L ;
  2005. #if 0
  2006.     /* I don't want to make the tty cursor blinking. */
  2007.     if ( handle_tty_event ( _mt_window , & anEvent ) )    
  2008. #endif
  2009.         HandleEvent ( & anEvent ) ;
  2010.  
  2011.     if (top_line && theWindows) {
  2012.         WindowPeek win = (WindowPeek)theWindows[WIN_MESSAGE].theWindow;
  2013.         if (win && win->visible)
  2014.             TEIdle(top_line);
  2015.     }
  2016. }
  2017.  
  2018.  
  2019. int
  2020. GetFromKeyQueue ( void ) {
  2021. int ix , ret ;
  2022.  
  2023.     ret = keyQueue [ 0 ] ;
  2024.     for ( ix = 0 ; ix < QUEUE_LEN - 1 ; ix ++ ) {
  2025.         keyQueue [ ix ] = keyQueue [ ix + 1 ] ;
  2026.     }
  2027.     keyQueue [ ix ] = 0 ;
  2028.  
  2029.     return ret ;
  2030. }
  2031.  
  2032.  
  2033. int
  2034. mac_nhgetch( void ) {
  2035. int ch ;
  2036. NhWindow * nhw = flags . window_inited ? theWindows + WIN_MAP : (NhWindow *) nil ;
  2037.  
  2038.     if ( theWindows ) {
  2039.     NhWindow * aWin = theWindows + WIN_MESSAGE ;
  2040.  
  2041.         if ( WIN_MESSAGE > 0 ) {
  2042.             aWin -> last_more_lin = aWin -> lin ;
  2043.         }
  2044.     }
  2045.  
  2046.     wait_synch ( ) ;
  2047.  
  2048.     if ( ! keyQueue [ 0 ] ) {
  2049.         long total , contig ;
  2050.         static char warn = 0 ;
  2051.  
  2052.         PurgeSpace ( & total , & contig ) ;
  2053.         if ( contig < 25000L || total < 50000L ) {
  2054.             if ( ! warn ) {
  2055.                 pline ( "Low Memory!" ) ;
  2056.                 warn = 1 ;
  2057.             }
  2058.         } else {
  2059.             warn = 0 ;
  2060.         }
  2061.     }
  2062.  
  2063.     do {
  2064.         doDawdle = ( in_topl_mode() ? GetCaretTime ( ) : 120L ) ;
  2065.  
  2066.         if ( nhw ) {
  2067.             SetPort ( nhw -> theWindow ) ;
  2068.             if ( WaitMouseUp ( ) ) {
  2069.             unsigned long tick = TickCount ( ) ;
  2070.  
  2071.                 if ( tick >= gNextClickRepeat ) {
  2072.                 Point where ;
  2073.  
  2074.                     GetMouse ( & where ) ;
  2075.                     SetPt ( & clicked_pos , where . h / nhw -> charWidth ,
  2076.                                             where . v / nhw -> charHeight ) ;
  2077.                     gClickedToMove = TRUE ;
  2078.                     gNextClickRepeat = tick + * ( short * ) KeyRepThresh ;
  2079.                 }
  2080.                 if ( doDawdle > * ( short * ) KeyRepThresh ) {
  2081.                     doDawdle = * ( short * ) KeyRepThresh ;
  2082.                 }
  2083.             } else {
  2084.                 gNextClickRepeat = 0xffffffff ;
  2085.             }
  2086.         }
  2087.  
  2088.         get_nh_event ( ) ;
  2089.         ch = GetFromKeyQueue ( ) ;
  2090.     } while ( ! ch && ! gClickedToMove ) ;
  2091.  
  2092.     if ( ! gClickedToMove ) {
  2093.         ObscureCursor ( ) ;
  2094.     } else {
  2095.         gClickedToMove = 0 ;
  2096.     }
  2097.  
  2098. #ifdef THINK_C
  2099.     if (ch == '\r') ch = '\n';
  2100. #endif
  2101.  
  2102.     return ch ;
  2103. }
  2104.  
  2105.  
  2106. void
  2107. mac_delay_output( void )
  2108. {
  2109.     long destTicks = TickCount ( ) + 1 ;
  2110.  
  2111.     while ( TickCount ( ) < destTicks ) {
  2112.         wait_synch ( ) ;
  2113.     }
  2114. }
  2115.  
  2116.  
  2117. void
  2118. mac_wait_synch( void )
  2119. {
  2120.     get_nh_event ( ) ;
  2121. }
  2122.  
  2123.  
  2124. void
  2125. mac_mark_synch( void )
  2126. {
  2127.     get_nh_event ( ) ;
  2128. }
  2129.  
  2130.  
  2131. void
  2132. mac_cliparound ( int x , int y )
  2133. {
  2134.     /* TODO */
  2135.     if ( ! ( x * ( y + 1 ) ) ) {
  2136.         Debugger ( ) ;
  2137.     }
  2138. }
  2139.  
  2140.  
  2141. void
  2142. mac_raw_print ( const char * str )
  2143. {
  2144.     tty_raw_print(str);
  2145. }
  2146.  
  2147.  
  2148. void
  2149. mac_raw_print_bold ( const char * str )
  2150. {
  2151.     tty_raw_print_bold(str);
  2152. }
  2153.  
  2154.  
  2155. void
  2156. mac_exit_nhwindows ( const char * s )
  2157. {
  2158.     clear_screen ( ) ;
  2159.     tty_exit_nhwindows ( s ) ;
  2160.     destroy_nhwindow ( WIN_MESSAGE ) ;
  2161.     destroy_nhwindow ( WIN_INVEN ) ;
  2162. }
  2163.  
  2164.  
  2165. /*
  2166.  * Don't forget to decrease in_putstr before returning...
  2167.  */
  2168. void
  2169. mac_putstr ( winid win , int attr , const char * str )
  2170. {
  2171.     long len , slen ;
  2172.     NhWindow * aWin = & theWindows [ win ] ;
  2173.     int kind ;
  2174.     static char in_putstr = 0 ;
  2175.     Rect r ;
  2176.  
  2177.     if ( in_putstr > 3 ) {
  2178.         /* DebugStr ( ( ConstStr255Param ) "\pRecursion!" ) ; */
  2179.         return ;
  2180.     }
  2181.     if ( win < 0 || win >= NUM_MACWINDOWS ) {
  2182.         error ( "Invalid window %d (Max %d) in putstr." , win ,
  2183.             NUM_MACWINDOWS , attr ) ;
  2184.         return ;
  2185.     }
  2186.     if ( ! aWin -> theWindow ) {
  2187.         error ( "Unallocated window %d in putstr." , win ) ;
  2188.         return ;
  2189.     }
  2190.  
  2191.     if (aWin->theWindow == _mt_window) {
  2192.         tty_putstr(win, attr, str);
  2193.         return;
  2194.     }
  2195.  
  2196.     in_putstr ++ ;
  2197.     kind = ( ( WindowPeek ) ( aWin -> theWindow ) ) -> windowKind -
  2198.         WIN_BASE_KIND ;
  2199.     slen = strlen ( str ) ;
  2200.  
  2201.     {
  2202.         char * sr , * ds ;
  2203.  
  2204.         r = aWin->theWindow->portRect;
  2205.         if (win && win == WIN_MESSAGE) {
  2206.             r.right  -= SBARWIDTH  + 1;
  2207.             r.bottom -= SBARHEIGHT + 1;
  2208.             if ( aWin->last_more_lin < aWin->scrollPos )
  2209.                 aWin->last_more_lin = aWin->scrollPos;
  2210.             if ( flags.page_wait && aWin->last_more_lin <=
  2211.                  aWin->lin - (r.bottom - r.top) / aWin->charHeight )
  2212.                 display_nhwindow(win, TRUE);
  2213.         }
  2214.  
  2215.         /*
  2216.          * A "default" text window - uses TextBox
  2217.          * We just add the text, without attributes for now
  2218.          */
  2219.         len = GetHandleSize ( aWin -> windowText ) ;
  2220.         while ( aWin -> windowTextLen + slen + 1 > len ) {
  2221.             len = ( len > 2048 ) ? ( len + 2048 ) : ( len * 2 ) ;
  2222.             SetHandleSize ( aWin -> windowText , len ) ;
  2223.             if ( MemError ( ) ) {
  2224.                 error ( "SetHandleSize (putstr)" ) ;
  2225.                 aWin -> windowTextLen = 0L ;
  2226.                 aWin -> save_lin = 0 ;
  2227.                 aWin -> lin = 0 ;
  2228.             }
  2229.         }
  2230.     
  2231.         len = aWin -> windowTextLen ;
  2232.         sr = (char *)str ;
  2233.         ds = * ( aWin -> windowText ) + len ;
  2234.         while ( * sr ) {
  2235.             if ( * sr == CHAR_LF )
  2236.                 * ds = CHAR_CR ;
  2237.             else
  2238.                 * ds = * sr ;
  2239.             if ( * ds == CHAR_CR && kind != NHW_MENU ) {
  2240.                 aWin -> lin ++ ;
  2241.             }
  2242.             sr ++ ;
  2243.             ds ++ ;
  2244.         }
  2245.  
  2246.         ( * ( aWin -> windowText ) ) [ len + slen ] = CHAR_CR ;
  2247.         aWin -> windowTextLen += slen + 1 ;
  2248.         aWin -> lin ++ ;
  2249.     
  2250.         SetPort ( aWin -> theWindow ) ;
  2251.         InvalRect ( & r ) ;
  2252.         aWin -> clear = 0 ;
  2253.         if ( kind == NHW_MESSAGE ) {
  2254.             short min = aWin->lin - (r.bottom - r.top) / aWin->charHeight;
  2255.             if (aWin->scrollPos < min) {
  2256.                 aWin->scrollPos = min;
  2257.                 SetCtlMax  (aWin->scrollBar, aWin->lin);
  2258.                 SetCtlValue(aWin->scrollBar, min);
  2259.             }
  2260.         }
  2261.         if ( aWin -> scrollBar ) {
  2262.             InvalScrollBar ( aWin ) ;
  2263.         }
  2264.     }
  2265.     in_putstr -- ;
  2266. }
  2267.  
  2268.  
  2269. void
  2270. mac_curs ( winid win , int x , int y )
  2271. {
  2272.     NhWindow * aWin = & theWindows [ win ] ;
  2273.     int kind = ( ( WindowPeek ) ( aWin -> theWindow ) ) -> windowKind -
  2274.         WIN_BASE_KIND ;
  2275.  
  2276.     if (aWin->theWindow == _mt_window) {
  2277.         tty_curs(win, x, y);
  2278.         return;
  2279.     }
  2280.  
  2281.     SetPort  ( aWin -> theWindow ) ;
  2282.     MoveTo ( x * aWin -> charWidth , ( y + 1 ) * aWin -> charHeight -
  2283.         aWin -> leading ) ;
  2284.     SetPt ( & ( aWin -> cursor ) , x , y ) ;
  2285. }
  2286.  
  2287.  
  2288. void
  2289. mac_print_glyph ( winid window , XCHAR_P x , XCHAR_P y , int glyph )
  2290. {
  2291.     if (theWindows[window].theWindow != _mt_window)
  2292.         Debugger();
  2293.     tty_print_glyph(window, x, y, glyph);
  2294. }
  2295.  
  2296.  
  2297. int
  2298. mac_nh_poskey ( int * a , int * b , int * c )
  2299. {
  2300.     int ch = nhgetch();
  2301.     *a = clicked_pos.h;
  2302.     *b = clicked_pos.v;
  2303.     *c = clicked_mod;
  2304.     return ch;
  2305. }
  2306.  
  2307.  
  2308. void
  2309. mac_start_menu ( winid win )
  2310. {
  2311.     HideWindow ( theWindows [ win ] . theWindow ) ;
  2312.     clear_nhwindow ( win ) ;
  2313. }
  2314.  
  2315.  
  2316. void
  2317. mac_add_menu ( winid win , CHAR_P menuChar , int attr , const char * str )
  2318. {
  2319.     long addSize ;
  2320.     int newWid ;
  2321.     NhWindow * aWin = & theWindows [ win ] ;
  2322.  
  2323.     if ( ! str || aWin -> lin >= NUM_MENU_ITEMS )
  2324.         return ;
  2325.  
  2326.     SetPort ( aWin -> theWindow ) ;
  2327.     aWin -> itemChars [ aWin -> lin ] = menuChar ;
  2328.  
  2329.     addSize = strlen ( str ) ;
  2330.     newWid = TextWidth ( str , 0 , addSize ) ;
  2331.     if ( newWid > aWin -> wid )
  2332.         aWin -> wid = newWid ;
  2333.     putstr ( win , attr , str ) ;
  2334. }
  2335.  
  2336.  
  2337. /*
  2338.  * End a menu in this window, window must a type NHW_MENU.
  2339.  * ch is the value to return if the menu is canceled,
  2340.  * str is a list of cancel characters (values that may be input)
  2341.  * morestr is a prompt to display, rather than the default.
  2342.  * str and morestr might be ignored by some ports.
  2343.  */
  2344. void
  2345. mac_end_menu ( winid win , CHAR_P ch , const char * str , const char * morestr )
  2346. {
  2347.     unsigned char buf [ 256 ] ;
  2348.     int len ;
  2349.     NhWindow * aWin = & theWindows [ win ] ;
  2350.  
  2351.     strncpy ( aWin -> cancelStr , str , NUM_CANCEL_ITEMS ) ;
  2352.     aWin -> cancelStr [ NUM_CANCEL_ITEMS - 1 ] = 0 ;
  2353.     aWin -> cancelChar = ch ;
  2354.  
  2355.     buf [ 0 ] = 0 ;
  2356.     if ( morestr ) {
  2357.         strncpy ( (char *)& buf [ 1 ] , morestr , 255 ) ;
  2358.         len = strlen ( morestr ) ;
  2359.         if ( len > 255 )
  2360.             buf [ 0 ] = 255 ;
  2361.         else
  2362.             buf [ 0 ] = len ;
  2363.     }
  2364.     SetWTitle ( aWin -> theWindow , buf ) ;
  2365. }
  2366.  
  2367.  
  2368. char
  2369. mac_select_menu ( winid win )
  2370. {
  2371.     int c , l ;
  2372.     NhWindow * aWin = & theWindows [ win ] ;
  2373.     WindowPtr theWin = aWin -> theWindow ;
  2374.  
  2375.     inSelect = win ;
  2376.  
  2377.     adjust_window_pos ( aWin , theWin , aWin -> wid + ( SBARWIDTH + 2 ) ) ;
  2378.     SetPort ( theWin ) ;
  2379.     if ( aWin -> scrollBar ) {
  2380.         InvalScrollBar ( aWin ) ;
  2381.     }
  2382.     SelectWindow ( theWin ) ;
  2383.     ShowWindow ( theWin ) ;
  2384.     InvalRect ( & ( theWin -> portRect ) ) ;
  2385.  
  2386.     do {
  2387.         c = nhgetch ( ) ;
  2388.         for ( l = 0 ; l < aWin -> lin ; l ++ ) {
  2389.             if ( aWin -> itemChars [ l ] == c )
  2390.                 goto done ;
  2391.         }
  2392.         if ( ClosingWindowChar ( c ) ) {
  2393.             c = aWin -> cancelChar ;
  2394.         }
  2395.     } while ( ! strchr ( aWin -> cancelStr , c ) &&
  2396.         c != aWin -> cancelChar ) ;
  2397.  
  2398. done :
  2399.  
  2400.     HideWindow ( theWin ) ;
  2401.  
  2402.     inSelect = WIN_ERR ;
  2403.  
  2404.     return c ;
  2405. }
  2406.  
  2407.  
  2408. void
  2409. mac_display_file ( name, complain )
  2410. const char * name;
  2411. boolean    complain;
  2412. {
  2413.     long l ;
  2414.     short refNum ;
  2415.     Ptr buf ;
  2416.     int win ;
  2417.  
  2418.     if ( 0 > ( refNum = macopen ( name , O_RDONLY , TEXT_TYPE ) ) ) {
  2419.         if (complain) error ( "Cannot open file %s." , name ) ;
  2420.     } else {
  2421.         l = macseek ( refNum , 0 , SEEK_END ) ;
  2422.         ( void ) macseek ( refNum , 0 , 0L ) ;
  2423.         win = create_nhwindow ( NHW_TEXT ) ;
  2424.         if ( win == WIN_ERR ) {
  2425.             if (complain) error ( "Cannot make window." ) ;
  2426.             goto out ;
  2427.         }
  2428.         buf = NewPtr(l+1);
  2429.         if (buf)
  2430.             l = macread(refNum, buf, l);
  2431.         if (buf && l > 0) {
  2432.             buf[l] = '\0';
  2433.             putstr(win, 0, buf);
  2434.             display_nhwindow(win, FALSE);
  2435.         } else {
  2436.             HideWindow(theWindows[win].theWindow);
  2437.             destroy_nhwindow(win);
  2438.         }
  2439.         if (buf)
  2440.             DisposPtr(buf);
  2441. out :
  2442.         macclose ( refNum ) ;
  2443.     }
  2444. }
  2445.  
  2446.  
  2447. void
  2448. port_help ( )
  2449. {
  2450.     display_file ( PORT_HELP , TRUE ) ;
  2451. }
  2452.  
  2453.  
  2454. short frame_corner ;
  2455.  
  2456.  
  2457. static pascal void
  2458. FrameItem ( DialogPtr dlog , short item )
  2459. {
  2460.     short k ;
  2461.     Handle h ;
  2462.     Rect r ;
  2463.  
  2464.     GetDItem ( dlog , item , & k , & h , & r ) ;
  2465.     PenSize ( 3 , 3 ) ;
  2466.     FrameRoundRect ( & r , frame_corner , frame_corner ) ;
  2467.     PenNormal ( ) ;
  2468. }
  2469.  
  2470.  
  2471. void
  2472. SetFrameItem ( DialogPtr dlog , short frame , short item )
  2473. {
  2474.     Rect r , r2 ;
  2475.     short kind ;
  2476.     Handle h ;
  2477.  
  2478.     GetDItem ( dlog , item , & kind , & h , & r ) ;
  2479.     InsetRect ( & r , -4 , -4 ) ;
  2480.     r2 = r ;
  2481.     GetDItem ( dlog , frame , & kind , & h , & r ) ;
  2482.     SetDItem ( dlog , frame , kind , ( Handle ) FrameItem , & r2 ) ;
  2483.     frame_corner = 16 ;
  2484. }
  2485.  
  2486.  
  2487. //    Flash a button (for instance OK if you press enter)
  2488. //
  2489. void
  2490. FlashButton ( DialogPtr dlog , short item )
  2491. {
  2492.     short k ;
  2493.     Handle h ;
  2494.     Rect r ;
  2495.     long l ;
  2496.  
  2497.     GetDItem ( dlog , item , & k , & h , &  r ) ;
  2498.     if ( k == ctrlItem + btnCtrl ) {
  2499.         HiliteControl ( ( ControlHandle ) h , 1 ) ;
  2500.         Delay ( GetDblTime ( ) / 2 , & l ) ;
  2501.         HiliteControl ( ( ControlHandle ) h , 0 ) ;
  2502.     }
  2503. }
  2504.  
  2505.  
  2506. pascal Boolean
  2507. CharacterDialogFilter ( DialogPtr dp , EventRecord * ev , short * item )
  2508. {
  2509.     int ix ;
  2510.     Handle h ;
  2511.     Rect r ;
  2512.     short k ;
  2513.     Str255 s ;
  2514.     unsigned char com [ 2 ] ;
  2515.  
  2516.     if ( ev -> what == mouseDown ) {
  2517.  
  2518.         int code ;
  2519.         WindowPtr wp ;
  2520.         Rect r ;
  2521.  
  2522.         code = FindWindow ( ev -> where , & wp ) ;
  2523.         if ( wp != dp || code != inDrag ) {
  2524.     
  2525.             return 0 ;
  2526.         }
  2527.         r = ( * GetGrayRgn ( ) ) -> rgnBBox ;
  2528.         InsetRect ( & r , 3 , 3 ) ;
  2529.     
  2530.         DragWindow ( wp , ev -> where , & r ) ;
  2531.         SaveWindowPos ( wp ) ;
  2532.  
  2533.         ev -> what = nullEvent ;
  2534.         return 1 ;
  2535.     }
  2536.     if ( ev -> what != keyDown ) {
  2537.  
  2538.         return 0 ;
  2539.     }
  2540.     com [ 0 ] = 1 ;
  2541.     com [ 1 ] = ev -> message & 0xff ;
  2542.  
  2543.     if ( com [ 1 ] == 10 || com [ 1 ] == 13 || com [ 1 ] == 32 ||
  2544.         com [ 1 ] == 3 ) { // various "OK"
  2545.  
  2546.         * item = 1 ;
  2547.         FlashButton ( dp , 1 ) ;
  2548.         return 1 ;
  2549.     }
  2550.     if ( com [ 1 ] == 'Q' || com [ 1 ] == 'q' ||
  2551.          com [ 1 ] == 27 || ( ev -> message & 0xff00 == 0x3500 ) ) { // escape
  2552.  
  2553.         * item = 2 ;
  2554.         FlashButton ( dp , 2 ) ;
  2555.         return 1 ;
  2556.     }
  2557.     for ( ix = 3 ; ix ; ix ++ ) {
  2558.  
  2559.         h = ( Handle ) NULL ;
  2560.         k = 0 ;
  2561.         GetDItem ( dp , ix , & k , & h , & r ) ;
  2562.         if ( ! k || ! h ) {
  2563.  
  2564.             return 0 ;
  2565.         }
  2566.         if ( k == 6 ) { // Radio Button Item
  2567.  
  2568.             GetCTitle ( ( ControlHandle ) h , s ) ;
  2569.             s [ 0 ] = 1 ;
  2570.             if ( ! IUEqualString ( com , s ) ) {
  2571.  
  2572.                 * item = ix ;
  2573.                 return 1 ;
  2574.             }
  2575.         }
  2576.     }
  2577. /*NOTREACHED*/
  2578.     return 0 ;
  2579. }
  2580.  
  2581.  
  2582. void
  2583. mac_player_selection ( void )
  2584. {
  2585. /* see macmain.c:mac_askname() and macmenu.c:DialogAskName() */
  2586. }
  2587.  
  2588. void
  2589. mac_update_inventory ( void )
  2590. {
  2591. }
  2592.  
  2593.  
  2594. void
  2595. mac_suspend_nhwindows ( const char * foo)
  2596. {
  2597.     /*    Can't relly do that :-)        */
  2598. }
  2599.  
  2600.  
  2601. void
  2602. mac_resume_nhwindows ( void )
  2603. {
  2604.     /*    Can't relly do that :-)        */
  2605. }
  2606.  
  2607.  
  2608. int
  2609. try_key_queue ( char * bufp )
  2610. {
  2611.     if ( keyQueue [ 0 ] ) {
  2612.  
  2613.         int ix , flag = 0 ;
  2614.         for ( ix = 0 ; ix < QUEUE_LEN ; ix ++ ) {
  2615.  
  2616.             if ( ! flag ) {
  2617.  
  2618.                 if ( ! ( bufp [ ix ] = keyQueue [ ix ] ) ) {
  2619.  
  2620.                     flag = 1 ;
  2621.                 }
  2622.             }
  2623.             keyQueue [ ix ] = 0 ;
  2624.         }
  2625.         if ( ! flag ) {
  2626.  
  2627.             bufp [ ix ] = 0 ;
  2628.         }
  2629.         return 1 ;
  2630.     }
  2631.  
  2632.     return 0 ;
  2633. }
  2634.  
  2635. /* Interface definition, for windows.c */
  2636. struct window_procs mac_procs = {
  2637.     "mac",
  2638.     mac_init_nhwindows,
  2639.     mac_player_selection,
  2640.     mac_askname,
  2641.     mac_get_nh_event,
  2642.     mac_exit_nhwindows,
  2643.     mac_suspend_nhwindows,
  2644.     mac_resume_nhwindows,
  2645.     mac_create_nhwindow,
  2646.     mac_clear_nhwindow,
  2647.     mac_display_nhwindow,
  2648.     mac_destroy_nhwindow,
  2649.     mac_curs,
  2650.     mac_putstr,
  2651.     mac_display_file,
  2652.     mac_start_menu,
  2653.     mac_add_menu,
  2654.     mac_end_menu,
  2655.     mac_select_menu,
  2656.     mac_update_inventory,
  2657.     mac_mark_synch,
  2658.     mac_wait_synch,
  2659. #ifdef CLIPPING
  2660.     mac_cliparound,
  2661. #endif
  2662.     mac_print_glyph,
  2663.     mac_raw_print,
  2664.     mac_raw_print_bold,
  2665.     mac_nhgetch,
  2666.     mac_nh_poskey,
  2667.     mac_nhbell,
  2668.     mac_doprev_message,
  2669.     mac_yn_function,
  2670.     mac_getlin,
  2671. #ifdef COM_COMPL
  2672.     mac_get_ext_cmd,
  2673. #endif /* COM_COMPL */
  2674.     mac_number_pad,
  2675.     mac_delay_output,
  2676. #ifdef CHANGE_COLOR
  2677.     (void *) donull,
  2678.     (void *) donull,
  2679. #endif
  2680.     /* other defs that really should go away (they're tty specific) */
  2681.     0,    //    mac_start_screen,
  2682.     0, //    mac_end_screen,
  2683.     genl_outrip,
  2684. } ;
  2685.  
  2686. /*macwin.c*/
  2687.