home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / code / microema.sit / src / mactty.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-07-27  |  38.3 KB  |  1,601 lines  |  [TEXT/Earl]

  1. /*
  2.  * The routines in this file provide support for DJB's Macintosh terminal
  3.  * It compiles into nothing if not a MacTTY device.
  4.  *
  5.  * Extensively modified by Earle R. Horton.  Window support is limited to
  6.  * a single Macintosh window for speed.  Routines optimized, and mouse
  7.  * action parser which interfaces directly to microemacs routines
  8.  * installed.
  9.  */
  10. #include <stdio.h>
  11. #include "estruct.h"
  12. #include "edef.h"
  13. #include "epath.h"
  14.  
  15. #if    FINDER
  16. #if MPW
  17. #define __ALLNU__
  18. #include <types.h>
  19. #include <resources.h>
  20. #include <quickdraw.h>
  21. #include <fonts.h>
  22. #include <events.h>
  23. #include <windows.h>
  24. #include <menus.h>
  25. #include <textedit.h>
  26. #include <dialogs.h>
  27. #include <segload.h>
  28. #include <toolutils.h>
  29. #include <osutils.h>
  30. #include <desk.h>
  31. #include <strings.h>
  32. #include <controls.h>
  33. #include <script.h>
  34. #include <Memory.h>
  35. #endif
  36. #if LSC
  37. #include <QuickDraw.h>
  38. #include <FontMgr.h>
  39. #include <EventMgr.h>
  40. #include <WindowMgr.h>
  41. #include <MenuMgr.h>
  42. #include <DialogMgr.h>
  43. #include <DeskMgr.h>
  44. #include <controlmgr.h>
  45. #include <OSUtil.h>
  46. /*
  47.  * This should be in there somewhere.
  48.  */
  49. #define normal 0x00
  50. #define bold 0x01
  51. #define italic 0x02
  52. #define underline 0x04
  53. #define outline 0x08
  54. #define shadow 0x10
  55. #define condense 0x20
  56. #define extend 0x40
  57. #endif
  58. #include "TTY_Windows.h"
  59. #if MPW
  60. #define CtoPstr c2pstr
  61. #endif
  62.  
  63. #if MPW
  64. #ifdef macintosh
  65. pascal void XSTDTEXT(count,textAddr,numer,denom)
  66.     short count;    /* This is until I find out how to cast */
  67.     Ptr textAddr;    /* a constant long to a Point. */
  68.     long numer, denom;    
  69.     extern 0xA882;
  70. #define lmalloc malloc
  71. #else                /* Aztec C, doesn't do prototypes. */
  72. pascal void XSTDTEXT() = 0xA882;
  73. #endif
  74. #undef StdText
  75. #define StdText XSTDTEXT
  76. #endif
  77. #ifndef macintosh
  78. pascal void TTY_W_ScrollAction();
  79. #else
  80. pascal void TTY_W_ScrollAction(ControlHandle, short);
  81. #endif
  82.  
  83. /*
  84.  * Globals.
  85.  */
  86. Rect        cursRect;
  87. Point        pen_pt;
  88.  
  89. static int16    curs_row,curs_column,max_rows,max_columns,
  90.         min_rows,min_columns, act_rows,act_columns,
  91.         top_offset,left_offset,bottom_offset,right_offset,
  92.         window_width,window_height,char_ascent,char_descent,
  93.         curs_width,curs_height,vpos,vmax;
  94.  
  95. int32        lastCursBlink,lastmouseup;
  96. Boolean     cursBlinkFlag,cursVis,cursHid,resizeme;
  97. ControlHandle    vScrollBar;
  98. WindowPeek    uEmacsTTY_W;
  99. MenuHandle    myMenus[lastMenu+1];
  100. extern Pattern *popupPat;
  101. static short     rfile;
  102. #ifdef MPU68000
  103. long (*KeyInterpreter)();
  104. #else
  105. int (*KeyInterpreter)();
  106. #endif
  107. RgnHandle        junkrgn;
  108. SysEnvRec theWorld;
  109.  
  110. int window_is_active = FALSE;
  111. long malloc_safety = 65000L;
  112.  
  113. #define __SEG__ mactty
  114.  
  115. dummy(){}
  116. /*
  117.  *    mac_ttyopen:
  118.  *     Set up the TTY Window for uEmacs...
  119.  */
  120. #define __SEG__ INIT
  121. mac_ttyopen()
  122. {
  123.     WindowPtr        tempTTY_W;
  124.     Point            pt;
  125.     MenuHandle        menuH;
  126.     FontInfo        fontInfo;
  127.     WStateData        **windowstate;
  128.     Rect            scrollRect;
  129.     char            *lmalloc();
  130.     Rect            **windowresource;
  131.     EventRecord        theEvent;
  132.     long mem_to_grab;
  133.     
  134.     mem_to_grab = FreeMem()-malloc_safety;
  135.  
  136.     if(mem_to_grab > 524288L){    /* Don't be greedy! */
  137.         mem_to_grab = 524288L;
  138.     }
  139.  
  140.     if(mem_to_grab > 0L)free(lmalloc(mem_to_grab));
  141.  
  142.     (void)SysEnvirons(1,&theWorld);
  143.  
  144.     uEmacsTTY_W = (WindowPeek) malloc(sizeof(WindowRecord));
  145.     if(uEmacsTTY_W == NIL) return (ERR);
  146.     
  147.     windowresource = (Rect **)GetResource('WIND',128);
  148.     if(windowresource == NULL) exit();
  149.  
  150.     if((*windowresource)->top <= GetMBarHeight()){
  151.         (*windowresource)->top = GetMBarHeight()+4;
  152.     }
  153.     
  154.     tempTTY_W = GetNewWindow(128,uEmacsTTY_W,(WindowPtr)-1);
  155.     ReleaseResource(windowresource);
  156.  
  157.     if(tempTTY_W != (WindowPtr)uEmacsTTY_W)exit();
  158.     SetWTitle(tempTTY_W,ourAppName);
  159.     SetPort(uEmacsTTY_W);
  160.     TextFont(monaco);
  161.     TextFace(NIL);
  162.     TextMode(srcCopy);
  163.     TextSize(9);
  164.     GetFontInfo(&fontInfo);
  165.     char_ascent    = fontInfo.ascent;
  166.     char_descent    = fontInfo.descent;
  167.     curs_width    = fontInfo.widMax;
  168.     curs_height    = fontInfo.ascent + fontInfo.descent + fontInfo.leading;
  169.     
  170.     max_rows        =
  171.         (SCREENBITS.bounds.bottom-SCROLLBARWIDTH)/curs_height;
  172.     max_columns    =
  173.         (SCREENBITS.bounds.right-SCROLLBARWIDTH)/curs_width;
  174.     act_rows    = (tempTTY_W->portRect.bottom 
  175.               - tempTTY_W->portRect.top)
  176.               / curs_height;
  177.     act_columns    = (tempTTY_W->portRect.right
  178.               - tempTTY_W->portRect.left
  179.               - SCROLLBARWIDTH)/curs_width;
  180.     if(act_rows > max_rows) {
  181.         act_rows    = max_rows - 3;
  182.     }
  183.     if(act_columns > max_columns){
  184.         act_columns    = max_columns - 2;
  185.     }
  186.     max_columns    += max_columns/2;
  187.     min_rows    = 5;
  188.     min_columns    = 25;
  189.     top_offset    = 0;
  190.     left_offset    = 2;
  191.     bottom_offset    = 0;
  192.     right_offset    = SCROLLBARWIDTH - 1;
  193.     window_width    = right_offset    + act_columns*curs_width
  194.                     + left_offset;
  195.     window_height    = top_offset    + act_rows*curs_height
  196.                     + bottom_offset;
  197.                                     
  198.     /* Resize the window to the appropriate size */
  199.     SizeWindow(uEmacsTTY_W,window_width,window_height,false);
  200.  
  201.     resizeme    = FALSE;
  202.     cursBlinkFlag    = TRUE;
  203.     
  204.     
  205.     /* Add inactive unhilighted scroll bars as requested */
  206.         
  207.     scrollRect.left     = window_width - SCROLLBARWIDTH + 1;
  208.     scrollRect.top        = - 1;
  209.     scrollRect.right    = window_width + 1;
  210.     scrollRect.bottom    = window_height - SCROLLBARWIDTH + 2;
  211.         
  212.     vScrollBar = NewControl(tempTTY_W, &scrollRect, "", true, 1, 0, 2,
  213.         scrollBarProc, (long) uEmacsTTY_W);
  214.     if(vScrollBar == NIL) exit();
  215.     HiliteControl(vScrollBar, 0);
  216.     /* make the window visible */
  217.     ShowWindow(tempTTY_W);
  218.     DrawGrowIcon(tempTTY_W);
  219.     ShowControl(vScrollBar);
  220.     
  221.     clearleft();
  222.     term.t_mrow = max_rows + 3;
  223.     term.t_nrow = act_rows - 1;
  224.     term.t_mcol = max_columns + 2;
  225.     term.t_ncol = act_columns;
  226.     cursVis = CURS_INVIS;
  227.     cursHid = CURS_SHOW;
  228.     junkrgn = NewRgn();
  229.     if(GetNextEvent((short)app4Mask,&theEvent)){
  230.         theEvent.modifiers = (short)theEvent.message & 1;
  231.         theEvent.what = activateEvt;
  232.         eventparser(&theEvent);
  233.         TTY_WHideCurs();
  234.     }else{
  235.         window_is_active = TRUE;
  236.         SelectWindow(tempTTY_W);
  237.     }
  238.     return (OK);
  239. }
  240. #define __SEG__ mactty
  241. /*
  242.  *  mac_ttymove
  243.  *
  244.  *        Move cursor to indicated row and column in Macintosh window.
  245.  */
  246. mac_ttymove(whichRow, whichColumn)
  247.     int    whichRow, whichColumn;
  248. {
  249.     curs_row = (whichRow>act_rows)
  250.         ? act_rows    : whichRow;
  251.     curs_column = (whichColumn>act_columns)
  252.         ? act_columns : whichColumn;
  253.     
  254.     TTY_WBlinkCurs(CURS_INVIS);
  255.     SetRect(&cursRect, left_offset + (curs_column)*curs_width
  256.         , top_offset    + (curs_row)*curs_height
  257.         , left_offset + (curs_column+1)*curs_width
  258.         , top_offset  + (curs_row+1)*curs_height);
  259.     SetPt(&pen_pt, left_offset+(curs_column*curs_width),
  260.           top_offset+char_ascent+(curs_row*curs_height));
  261.     
  262.     MoveTo(pen_pt.h, pen_pt.v);
  263.     
  264.     TTY_WBlinkCurs(CURS_VIS);
  265. }
  266. /*
  267.  *  mac_ttygetc
  268.  *
  269.  *        Get a character from the keyboard on the Mac.  Or at least
  270.  *    get it from somebody who thinks he knows what it is!
  271.  *
  272.  */
  273. int mac_ttygetc()
  274. {
  275.  
  276.     EventRecord        theEvent;
  277.     /* if Mouse-Down occurs return a CTRL-G to abort */
  278.     while(!EventAvail((short)(keyDownMask+autoKeyMask+app4Mask), &theEvent)) {
  279.         TTY_WBlinkCurs(CURS_IDLE);
  280.         if(EventAvail((short)(mDownMask+app4Mask), &theEvent))  return (0x07);
  281.     }
  282.     /* Next, look in the event queue */
  283.     GetNextEvent((short)(keyDownMask+autoKeyMask), &theEvent);
  284.     return(*KeyInterpreter)(&theEvent);
  285. }
  286. /*
  287.  *  mac_ttyeeol
  288.  *
  289.  *        Erase to end of current line.
  290.  *
  291.  */
  292. mac_ttyeeol()
  293. {
  294.     Rect    temp;
  295.     TTY_WBlinkCurs(CURS_INVIS);
  296.     temp = cursRect;
  297.     temp.right = left_offset+
  298.         ((act_columns)*curs_width);
  299.     EraseRect(&temp);
  300. }
  301. /*
  302.  *  mac_ttyeeop
  303.  *
  304.  *        Erase to end of screen.
  305.  *
  306.  */
  307. mac_ttyeeop()
  308. {
  309.     Rect    temp;
  310.     mac_ttyeeol();
  311.     temp = cursRect;
  312.     temp.right = left_offset+
  313.         ((act_columns)*curs_width);
  314.     temp.top = temp.bottom;
  315.     temp.left = left_offset;
  316.     temp.bottom = left_offset+
  317.         (act_rows*curs_height);
  318.     EraseRect(&temp);
  319. }
  320. /*
  321.  *  mac_ttybeep
  322.  *
  323.  *        Beep.
  324.  *
  325.  */
  326. mac_ttybeep()
  327. {
  328.     SysBeep(1);
  329. }
  330. mac_ttyscroll(toprow,botrow,nrows)
  331. int    toprow,botrow,nrows;
  332. {
  333.     Rect    scrollrect;
  334.     SetRect(&scrollrect,left_offset,
  335.         toprow * curs_height + top_offset,
  336.             window_width - right_offset,
  337.                 botrow * curs_height + top_offset);
  338.     ScrollRect(&scrollrect,0,nrows*curs_height,junkrgn);
  339. }
  340. /*
  341.  *  uEmacs_Refresh
  342.  *
  343.  *        Force an update of the terminal window.  (And some other
  344.  *        black magic, since we have to move the scroll bars, too.)
  345.  */
  346. uEmacs_Refresh()
  347. {
  348.     Rect scrollRect;
  349.     TTY_WRecalcScroll();
  350.     if(resizeme){
  351.         HideControl(vScrollBar);
  352.         scrollRect.left     =
  353.             window_width - SCROLLBARWIDTH + 1;
  354.         scrollRect.top        = -  1;
  355.         scrollRect.right    = window_width + 1;
  356.         scrollRect.bottom    =
  357.             window_height - (SCROLLBARWIDTH - 2);
  358.         MoveControl(vScrollBar,
  359.             scrollRect.left,scrollRect.top);
  360.         SizeControl(vScrollBar,
  361.             scrollRect.right-scrollRect.left,
  362.                 scrollRect.bottom-scrollRect.top);
  363.         ShowControl(vScrollBar);
  364.         newsize(TRUE,act_rows);
  365.         newwidth(TRUE,act_columns);
  366.         resizeme = FALSE;
  367.     }
  368.     DrawGrowIcon(uEmacsTTY_W);
  369.     clearleft();
  370.     refresh(FALSE, 0);
  371.     update(TRUE);
  372.     ValidRect(&((WindowPtr)uEmacsTTY_W)->portRect);
  373. }
  374. clearleft()
  375. {
  376. Rect junkRect;
  377.     junkRect.left        = 0;
  378.     junkRect.top        = -  1;
  379.     junkRect.right    = left_offset;
  380.     junkRect.bottom = window_height;
  381.     EraseRect(&junkRect);
  382. }
  383. /*
  384.  *  uEmacs_Quit
  385.  *
  386.  *        Shut down MicroEMACS.
  387.  */
  388. uEmacs_Quit()
  389. {
  390.     quit(0,0);
  391. }
  392. /*
  393.  *  uEmacs_ScrollLine
  394.  *
  395.  *        Scroll the current MicroEMACS window one line at a time.
  396.  *        The vtscroll() routine takes care of all update.
  397.  */
  398. uEmacs_ScrollLine(n)
  399.     int    n;
  400. {
  401.     register LINE *lp;
  402.     lp = curwp->w_linep;
  403.     TTY_WBlinkCurs(CURS_INVIS);
  404.     mvupwind(0,n);
  405.     if(n==1 && lp != curwp->w_linep)vtscrollup();
  406.     else if(n== -1)vtscrolldown();
  407.     TTY_WBlinkCurs(CURS_VIS);
  408. }
  409. /*
  410.  *    uEmacs_VBufPos()
  411.  *
  412.  *        Return the current positon in the file. Based on the current line
  413.  *        vs. the current number of lines in the buffer.
  414.  */
  415. uEmacs_VBufPos()
  416. {
  417.     register LINE    *lp;        /* current line */
  418.     register int16    numlines;    /* # of lines in file */
  419.     register int16    predlines;    /* # lines preceding point */
  420.     /* starting at the beginning of the buffer */
  421.     lp = lforw(curbp->b_linep);
  422.     /* start counting chars and lines */
  423.     numlines = 0;
  424.     while (lp != curbp->b_linep) {
  425.         /* can we find the top line in the current window */
  426.         if (lp == curwp->w_linep) {
  427.             predlines = numlines;
  428.         }
  429.         /* on to the next line */
  430.         ++numlines;
  431.         lp = lforw(lp);
  432.     }
  433.     /* if at end of file, record it */
  434.     if (curwp->w_linep == curbp->b_linep) {
  435.         predlines = numlines;
  436.     }
  437.     vmax = numlines;
  438.     vpos = predlines;
  439. }
  440. /*
  441.  *  mac_ttyrev
  442.  *
  443.  *        Set reverse video character attribute
  444.  *            (TRUE = reverse, FALSE = normal)
  445.  */
  446. mac_ttyrev(state)
  447.     int    state;
  448. {
  449.     if(state){
  450.         ForeColor(whiteColor);
  451.         BackColor(blackColor);
  452.     }
  453.     else{
  454.         ForeColor(blackColor);
  455.         BackColor(whiteColor);
  456.     }
  457. }
  458. spal(str)char*str;{}
  459. #if    TYPEAH
  460. /* typahead:    Check to see if any characters are already in the
  461.  *                    Event Queue.
  462.  */
  463. typahead()
  464. {
  465.     EventRecord        theEvent;
  466.     
  467.     return (EventAvail(keyDownMask+autoKeyMask, &theEvent));
  468. }
  469. #endif
  470. /*
  471.  *    GrowTTY_Window() -    Let the user drag the specified TTY_Window with the mouse.
  472.  *
  473.  *    wPtr        -    The TTY_Window to be moved.
  474.  *    startPt     -    starting location of the mouse (global coordinates).
  475.  *
  476.  *    returns     -    packed 32 bit int: lower 16 bits = new width
  477.  *                upper 16 bits = new height
  478.  *                takes into account max and min fields of TTY_Window
  479.  */
  480. int32 GrowTTY_Window(startPt)
  481.     Point    *startPt;
  482. {    
  483.     Rect    sizeRect;
  484.     
  485.     sizeRect.left    =
  486.         right_offset + min_columns*curs_width + left_offset;
  487.     sizeRect.top    =
  488.         top_offset + min_rows*curs_height + bottom_offset;
  489.     sizeRect.right    =
  490.         right_offset + max_columns*curs_width + left_offset;
  491.     sizeRect.bottom    =
  492.         top_offset + max_rows*curs_height + bottom_offset;
  493.         
  494.     return (GrowWindow(uEmacsTTY_W,*startPt, &sizeRect));
  495. }
  496. /*
  497.  *    SizeTTY_Window() -    Resize the specified TTY_Window.
  498.  *                New area generates an update event.
  499.  *
  500.  *    wPtr         -    The TTY_Window to be moved.
  501.  *    w, h         -    new width and height for the TTY_Window.
  502.  *
  503.  */
  504. SizeTTY_Window(w, h)
  505.     int16            w, h;
  506. {    
  507.     Rect scrollRect;
  508. /* Assure an even number of rows, columns in the final size */
  509.     w -= (w-left_offset-right_offset) % curs_width;
  510.     h -= (h-top_offset-bottom_offset) % curs_height;
  511.      HideControl(vScrollBar);    /* Size the window. */
  512.     SizeWindow(uEmacsTTY_W, w, h, false);
  513.  
  514.     window_width    = w;        /* Calculate new rows and columns. */
  515.     window_height    = h;
  516.     act_rows    = (h-top_offset-bottom_offset)/curs_height;
  517.     act_columns    = (w-left_offset-right_offset)/curs_width;
  518.     resizeme = TRUE;
  519.     uEmacs_Refresh();
  520. }
  521. /*
  522.  *    eventparser(event) -    Processes events belonging to TTY_Windows.
  523.  *
  524.  *            event            -    Ptr to EventRecord.
  525.  */
  526. eventparser(event)
  527.     EventRecord        *event;
  528. {
  529.     int16            findResult;
  530.     int32            growResult;
  531.     WStateData        **windowstate;
  532.     Point            tempPt;
  533.     Rect            dragRect,userRect;
  534.     WindowPeek          tmppeek;
  535.     
  536.     /* if NULL event idle the cursor. */
  537.     if(event->what == nullEvent) {
  538.         TTY_WBlinkCurs(CURS_IDLE);
  539.         return;
  540.     }
  541.     
  542.     switch(event->what) {
  543.         case mouseDown:
  544.             tempPt = event->where;
  545.             findResult = FindWindow(tempPt,&tmppeek);
  546.             if(tmppeek != uEmacsTTY_W)return;
  547.             /* Handle the mouse-down */
  548.             switch(findResult) {
  549.                 case inContent:
  550.                     if (uEmacsTTY_W != (WindowPeek)FrontWindow()) {
  551.                         SelectWindow(uEmacsTTY_W);
  552.                     } else {
  553.                         GlobalToLocal(&tempPt);
  554.                         /* Check if in scroll-bars */
  555.                         if(!DoTTY_WScroll(&tempPt, event))
  556.                             mouseparser(&tempPt, event);
  557.                         TTY_WRecalcScroll();
  558.                     }
  559.                     break;
  560.                 case inDrag:
  561.                     SetRect(&dragRect, 
  562.                         4, GetMBarHeight()+4,
  563.                         SCREENBITS.bounds.right-4,
  564.                          SCREENBITS.bounds.bottom-4);
  565.                     DragWindow(uEmacsTTY_W,tempPt, &dragRect);
  566.                         /* Application will be notified by an update event */
  567.                     break;
  568.                 case inGrow:
  569.                     growResult = GrowTTY_Window(&tempPt);
  570.                     if(growResult != 0) {
  571.                         SizeTTY_Window(LoWord(growResult),
  572.                            HiWord(growResult), TRUE);
  573.                     }
  574.                     break;
  575.                 case inGoAway:
  576.                     if (TrackGoAway(uEmacsTTY_W,tempPt))    {
  577.                         /* call the owner's close routine */
  578.                         uEmacs_Quit();
  579.                     }
  580.                     break;
  581.                 case inZoomIn:
  582.                     if(TrackBox(uEmacsTTY_W,tempPt, inZoomIn)) {
  583.                         ZoomWindow(uEmacsTTY_W, inZoomIn, FALSE);
  584.                         SizeTTY_Window(((WindowPtr)uEmacsTTY_W)->portRect.right,
  585.                                 ((WindowPtr)uEmacsTTY_W)->portRect.bottom,TRUE);
  586.                     }
  587.                     break;
  588.                 case inZoomOut:
  589.                     if(TrackBox(uEmacsTTY_W,tempPt, inZoomOut)) {
  590. /*
  591.  * ZoomWindow() resizes our window, but not necessarily to an even number
  592.  * of rows and columns.  After correction, the WStateData stored in our
  593.  * WindowRecord.dataHandle must be corrected or the WDEF might become
  594.  * confused about which state we are in.
  595.  */
  596.                         userRect = ((WindowPtr)uEmacsTTY_W)->portRect;
  597.                         LocalToGlobal(&userRect.top);
  598.                         LocalToGlobal(&userRect.bottom);
  599.                         ZoomWindow(uEmacsTTY_W, inZoomOut, FALSE);
  600.                         SizeTTY_Window(((WindowPtr)uEmacsTTY_W)->portRect.right+3,
  601.                                 ((WindowPtr)uEmacsTTY_W)->portRect.bottom+3,TRUE);
  602.                         windowstate = (WStateData **)uEmacsTTY_W->dataHandle;
  603.                         (**windowstate).stdState = ((WindowPtr)uEmacsTTY_W)->portRect;
  604.                         (**windowstate).userState = userRect;
  605.                         HLock(windowstate);
  606.                         LocalToGlobal(&(**windowstate).stdState);
  607.                         LocalToGlobal(&(**windowstate).stdState.bottom);
  608.                         HUnlock(windowstate);
  609.                     }
  610.                     break;
  611.                 default:
  612.                     break;
  613.             }
  614.             break;
  615.             
  616.         case mouseUp:
  617.             lastmouseup = event->when;
  618.             break;
  619.         
  620.         case updateEvt:
  621.             TTY_WHideCurs();
  622.             BeginUpdate(uEmacsTTY_W);
  623.             uEmacs_Refresh();
  624.             EndUpdate(uEmacsTTY_W);
  625.             TTY_WShowCurs();
  626.             break;
  627.         case activateEvt:
  628.             if (event->modifiers & activeFlag) {
  629.                 /* Show cursor/range and show controls */
  630.                 HiliteControl(vScrollBar, 0);
  631.                 window_is_active = TRUE;
  632.                 TTY_WShowCurs(uEmacsTTY_W);
  633.                 InitCursor();
  634.             } else {
  635.                 HiliteControl(vScrollBar, 255);
  636.                 window_is_active = FALSE;
  637.                 TTY_WHideCurs();
  638.             }
  639.             clearleft();
  640.             break;
  641.         
  642.         default:
  643.             break;
  644.         
  645.     }
  646.     return;
  647. }
  648. /*
  649.  *    DoTTY_WScroll() -    Handle mouse-down events in TTY_W scrollbars
  650.  *
  651.  *            pt        -    location of mousedown.
  652.  *            returns:    -    TRUE  - is a scroll-bar event
  653.  *                    -    FALSE - is not a scroll-bar event
  654.  */
  655. DoTTY_WScroll(pt, event)
  656.     Point            *pt;
  657.     EventRecord        *event;
  658. {
  659.     int16            partCode, trackResult;
  660.     ControlHandle    whichControl;
  661.     partCode = FindControl(*pt, uEmacsTTY_W, &whichControl);
  662.     if((partCode == NIL) || (whichControl == NIL)) return FALSE;
  663.     TTY_WHideCurs();
  664.     if(partCode == inThumb) {
  665.         trackResult = TrackControl(whichControl,*pt, NIL);
  666.         if(trackResult == inThumb) {
  667.             gotoline(TRUE,GetCtlValue(vScrollBar)+1);
  668.             update(TRUE);
  669.         }
  670.     } else {
  671.         trackResult = TrackControl(whichControl,*pt, TTY_W_ScrollAction);
  672.     }
  673.     TTY_WShowCurs();
  674. }
  675. /*
  676.  *    TTY_W_ScrollAction()    -    Handle mouse-down events in TTY_W scrollbars
  677.  *
  678.  *            uEmacsTTY_W     -    TTY_WindowPtr.
  679.  *            pt        -    location of mousedown.
  680.  *            returns:    -    TRUE  - is a scroll-bar event
  681.  *                    -    FALSE - is not a scroll-bar event
  682.  */
  683. pascal void TTY_W_ScrollAction(whichControl, partCode)
  684.     ControlHandle    whichControl;
  685.     int16            partCode;
  686. {
  687.     int16    hval,vval;
  688.     switch (partCode) {
  689.         case inUpButton:
  690.             if(vpos > 0){
  691.                 SetCtlValue(vScrollBar,--vpos);
  692.                 uEmacs_ScrollLine(1);
  693.             }
  694.             break;
  695.         case inDownButton:
  696.             if(vpos < vmax){
  697.                 SetCtlValue(vScrollBar,++vpos);
  698.                 uEmacs_ScrollLine(-1);
  699.             }
  700.             break;
  701.         case inPageUp:
  702.             backpage(FALSE,1);
  703.             update(TRUE);
  704.             TTY_WRecalcScroll();
  705.             break;
  706.         case inPageDown:
  707.             forwpage(FALSE,1);
  708.             update(TRUE);
  709.             TTY_WRecalcScroll();
  710.             break;
  711.     }
  712. }
  713. /*
  714.  *    TTY_WRecalcScroll()    -    Handle mouse-down events in TTY_W scrollbars
  715.  *
  716.  */
  717. TTY_WRecalcScroll()
  718. {
  719.     
  720.     /* Get the position in the window displayed in the TTY_W and adjust control*/
  721.     uEmacs_VBufPos();
  722.     SetCtlMax(vScrollBar, vmax);
  723.     SetCtlValue(vScrollBar, vpos);
  724.     Draw1Control(vScrollBar);
  725. }
  726. /*
  727.  * getpos() - Returns row and column corresponding to current mouse point
  728.  *            in terminal emulator.
  729.  */
  730. getpos(row,col)
  731. int16 *row;
  732. int16 *col;
  733. {
  734.     Point pt;
  735.     GetMouse(&pt);
  736.     *row = (pt.v - top_offset)/curs_height;
  737.     *col = (pt.h - left_offset)/curs_width;
  738. }    
  739. /*
  740.  *    mouseparser() -    Handle mouse-down events in ╡Emacs window.
  741.  *
  742.  *    pt        -    location of mousedown.
  743.  *
  744.  *    Make the window in which the mouse down occured current.  If in the
  745.  *    text area, then move the cursor to as close to the Point as possible,
  746.  *    then wait for a drag.  If in a mode line, let the user drag the mode 
  747.  *    line to resize the window.
  748.  *  
  749.  *    Since the bottom mode line does not move, resizing the bottom window
  750.  *    is a little different.  Trying to pull up on the bottom mode line makes
  751.  *    the bottom window smaller by moving the next-to-the-bottom mode line
  752.  *    down.  Trying to pull down on the bottom mode line makes the bottom
  753.  *    window larger by making the next-to-the-bottom window smaller.
  754.  *    Trying to resize when there is only one window causes it to be split,
  755.  *    with the cursor remaining in the bottom window.
  756.  *
  757.  *    A window can be deleted by shrinking it within this routine.  Other
  758.  *    windows cannot, however, be deleted by enlarging the current one.
  759.  *
  760.  *    Double-clicks in a mode line call nextbuffer().
  761.  *
  762.  *    Double-clicks in the text area  move the point to the
  763.  *    character clicked on, then swap the mark.
  764.  *
  765.  *    Drags have a similar effect as in "regular" Macintosh text editors.
  766.  *    A simple drag leaves the mark set to the beginning of the drag, and
  767.  *    the point at the end of the drag.  A shift drag does not move the mark,
  768.  *    only the point.
  769.  *
  770.  *    Moves off the end of extended lines are not handled well.  This requires
  771.  *    tighter coupling with the routines in display.c.
  772.  */
  773. mouseparser( pt, event)
  774.     Point            *pt;
  775.     EventRecord        *event;
  776. {    
  777. #if LSC
  778.     pascal long GetDblTime();
  779. #else
  780.     long GetDblTime();
  781. #endif
  782.     register WINDOW *wp;
  783.     register LINE *lp;
  784.     int16    pt_row,pt_col,new_row,new_col;
  785.     int     i;
  786.     static int16 last_col,last_row;
  787.     Boolean doubleclick;
  788.     Boolean markset = false;
  789.     
  790.     mlerase();
  791.     getpos(&pt_row,&pt_col);
  792.     pt_row = (pt_row<0) ? 0 : pt_row;
  793.     pt_row = (pt_row>act_rows) ? act_rows : pt_row;
  794.     pt_col = (pt_col<0) ? 0 : pt_col;
  795.     pt_col = (pt_col>act_columns) ? act_columns : pt_col;
  796.     
  797.     doubleclick = (pt_col == last_col && pt_row == last_row &&
  798.         (event->when - lastmouseup) <= GetDblTime());
  799.     last_row = pt_row;
  800.     last_col = pt_col;
  801.     
  802. /*
  803.  * Find window where mouse down occured.
  804.  * Make it current, fix up mode lines.
  805.  */
  806.     for(wp=wheadp;wp->w_wndp!=NULL;){
  807.         if(wp->w_toprow <= pt_row && 
  808.             wp->w_toprow+wp->w_ntrows >= pt_row)break;
  809.         wp = wp->w_wndp;
  810.     }
  811.     curwp = wp;
  812.     curbp = wp->w_bufp;
  813.     upmode();
  814. /*
  815.  * Click in a mode line.
  816.  */
  817.     if(wp->w_toprow+wp->w_ntrows == pt_row){
  818.         if(doubleclick){           /* Handle double click. */
  819.             nextbuffer(FALSE);
  820.             update(TRUE);
  821.         }
  822.         while(StillDown()){          /* Check for mode line move. */
  823.             getpos(&new_row,&new_col);
  824.             if(new_row < pt_row){  /* Pull up, shrink current. */
  825.                 if (wheadp->w_wndp == NULL) {
  826.                     if(splitwind(TRUE,2)==FALSE){
  827.                         update(TRUE);
  828.                         return;
  829.                     }
  830.                 }
  831.                 else if(shrinkwind(TRUE,1)==FALSE){
  832.                     delwind();
  833.                     update(TRUE);
  834.                     return;
  835.                 }
  836.             }         /* Pull down, enlarge current window. */
  837.             else if(new_row > pt_row){
  838.                 if (wheadp->w_wndp == NULL) {
  839.                     if(splitwind(TRUE,2)==FALSE){
  840.                         update(TRUE);
  841.                         return;
  842.                     }
  843.                 }
  844.                 else if(enlargewind(TRUE,1)==FALSE){
  845.                     update(TRUE);
  846.                     return;
  847.                 }
  848.             }           /* Update if mode line changed. */
  849.             if(new_row != pt_row){
  850.                 pt_row = wp->w_toprow+wp->w_ntrows;
  851.                 update(TRUE);
  852.             }
  853.         }
  854. /*
  855.  * Click in message line.
  856.  */
  857.     }else if(pt_row == term.t_nrow){
  858.         namedcmd();
  859. /*
  860.  * Click in text.  Drag or move.
  861.  */
  862.     }else{
  863.         cursBlinkFlag = FALSE;  /* Shut off cursor blink during drag. */
  864.         if((event->modifiers & shiftKey) != 0){
  865.             markset = true;
  866.             doubleclick = false;
  867.         }
  868.         do{
  869.             getpos(&new_row,&new_col);
  870.             if(new_col < 0)new_col = 0;
  871.             if(!markset && (new_row != pt_row || new_col != pt_col)){
  872.                 markset = true;
  873.                 doubleclick = false;
  874.                 setmark();
  875.             }
  876.             if(new_row >= wp->w_toprow + wp->w_ntrows){
  877.                 if(vpos < vmax){
  878.                     SetCtlValue(vScrollBar,++vpos);
  879.                     uEmacs_ScrollLine(-1);
  880.                 }
  881.                 new_row = wp->w_toprow + wp->w_ntrows - 1;
  882.                 TTY_WHideCurs();
  883.             }
  884.             else if(new_row < wp->w_toprow){
  885.                 if(vpos > 0){
  886.                     SetCtlValue(vScrollBar,--vpos);
  887.                     uEmacs_ScrollLine(1);
  888.                 }
  889.                 new_row = wp->w_toprow;
  890.                 TTY_WHideCurs();
  891.             }else{
  892.                 TTY_WShowCurs();
  893.             }
  894.             for(i=wp->w_toprow,lp=wp->w_linep;
  895.                 ((i<new_row) && (lp != curbp->b_linep));){
  896.                 lp = lforw(lp);i++;
  897.             }
  898.             wp->w_dotp = lp;
  899.             curgoal = new_col;
  900.             wp->w_doto = getgoal(wp->w_dotp);
  901.             pt_row = new_row;
  902.             pt_col = new_col;
  903.             update(TRUE);
  904.         }while(StillDown());
  905.         if(doubleclick){
  906.             swapmark();
  907.         }
  908.         TTY_WShowCurs();
  909.         cursBlinkFlag    = TRUE;
  910.     }
  911.     update(TRUE);
  912. }
  913. /*
  914.  *  mac_ttyputc
  915.  *
  916.  *        Put a character to the terminal window for the mac.
  917.  *
  918.  */
  919. mac_ttyputc(c)
  920.     int    c;
  921. {
  922.     int16    newcol;
  923.     
  924.     c &= 0xFF;
  925.     
  926.     TTY_WBlinkCurs(CURS_INVIS);
  927.     if( c <= 31 || c == '\177') {
  928.         switch(c) {
  929.             case '\012':
  930.             case '\015':
  931.                 mac_ttymove( curs_row, 0);
  932.                 break;
  933.                 
  934.             case '\177':
  935.                 mac_ttymove( curs_row,
  936.                     (curs_column>0 ? curs_column-1 : 0));
  937.                 mac_ttyputc(' ');
  938.                 mac_ttymove( curs_row,
  939.                     (curs_column>0 ? curs_column-1 : 0));
  940.                 break;
  941.                 
  942.             case '\b':
  943.                 mac_ttymove( curs_row,
  944.                   (curs_column>0 ?
  945.                     curs_column-1 : 0));
  946.                 break;
  947.                 
  948.             default:
  949.                 break;
  950.         }
  951.     } else {
  952.         if(curs_column+1 < act_columns) {
  953.             DrawChar((short)c);
  954.             OffsetRect(&cursRect, curs_width, (short)0);
  955.             TTY_WBlinkCurs(CURS_VIS);
  956.             curs_column += 1;
  957.         } else {
  958.             DrawChar(c);
  959.             TTY_WBlinkCurs(CURS_VIS);
  960.             GetPen(&pen_pt);
  961.             pen_pt.h -= curs_width;
  962.             MoveTo(pen_pt.h, pen_pt.v);
  963.         }
  964.     }
  965.     TTY_WBlinkCurs(CURS_VIS);
  966.     GetPen(&pen_pt);
  967. }
  968. /*
  969.  * TTY_WPutText()    -    Put a character to the given TTY_Window at the
  970.  *                current cursor location, advance the cursor.
  971.  *
  972.  *    arow, acol    -    position of first character to draw.
  973.  *    n        -    number of characters to draw.
  974.  *    buf        -    ptr to buffer containing the characters.
  975.  */
  976. TTY_WPutText(arow, acol, n, buf)
  977.     int            arow, acol, n;
  978.     Ptr            buf;
  979. {
  980.     Point    oldpen_pt;
  981.     if(n <= 0) return;
  982.     
  983.     /* save pen position and move to new point */
  984.     GetPen(&oldpen_pt);
  985.     
  986.     SetPt(&pen_pt,
  987.         left_offset+(acol*curs_width),
  988.         top_offset+char_ascent+
  989.             (arow*curs_height));
  990.     MoveTo(pen_pt.h, pen_pt.v);
  991.     
  992.     TTY_WBlinkCurs(CURS_INVIS);
  993.     StdText(n,buf,0x00010001,0x00010001);
  994.     /* restore pen position */
  995.     MoveTo(oldpen_pt.h, oldpen_pt.v);
  996.     GetPen(&pen_pt);
  997.     
  998. }
  999. /*
  1000.  *  TTY_WBlinkCurs    -     Change the cursor state every GetCaretTime() ticks...
  1001.  *
  1002.  *        flag    -    CURS_IDLE        idle the cursor
  1003.  *                CURS_VIS        make cursor immediately "visible"
  1004.  *                CURS_INVIS        make cursor immediately "invisible"
  1005.  *
  1006.  *                (cursBlinkFlag: ZERO means no blinking)
  1007.  *                (cursVis:    CURS_VIS means cursor is invisible)
  1008.  *                (        CURS_INVIS  means cursor is visible)
  1009.  */
  1010. TTY_WBlinkCurs(flag)
  1011.     int16    flag;
  1012. {    
  1013.     if(!window_is_active){
  1014.         flag = CURS_INVIS;
  1015.     }
  1016.     switch(flag){
  1017.         case CURS_VIS:
  1018.             if((cursVis == CURS_INVIS) && (cursHid == CURS_SHOW)) {
  1019.                 InvertRect(&cursRect);
  1020.                 cursVis = CURS_VIS;
  1021.                 lastCursBlink  = TickCount();
  1022.             }
  1023.             break;
  1024.         case CURS_INVIS:
  1025.             if((cursVis == CURS_VIS) && (cursHid == CURS_SHOW)) {
  1026.                 InvertRect(&cursRect);
  1027.                 cursVis = CURS_INVIS;
  1028.                 lastCursBlink  = TickCount();
  1029.             }
  1030.             break;
  1031.         default:
  1032.             if((cursBlinkFlag) && (cursHid == CURS_SHOW) && 
  1033.                (TickCount() > lastCursBlink + GetCaretTime())) {
  1034.                 InvertRect(&cursRect);
  1035.                 cursVis = (cursVis?CURS_INVIS:CURS_VIS);
  1036.                 lastCursBlink  = TickCount();
  1037.             }
  1038.             break;
  1039.     }
  1040. }
  1041. /*
  1042.  *  TTY_WShowCurs    -     Allow the terminal cursor to be seen
  1043.  *
  1044.  *                (cursHid:    CURS_HIDE means cursor is hidden)
  1045.  *                (        CURS_SHOW means cursor is not hidden)
  1046.  */
  1047. TTY_WShowCurs()
  1048. {
  1049.     if(FrontWindow() == (WindowPtr) uEmacsTTY_W) {
  1050.         cursHid = CURS_SHOW;
  1051.         TTY_WBlinkCurs(CURS_VIS);
  1052.     }
  1053. }
  1054. /*
  1055.  *  TTY_WHideCurs    -     Supress the terminal cursor
  1056.  *
  1057.  *        ttywPtr -    TTY_WindowPtr to be affected.
  1058.  *
  1059.  *                (cursHid:    CURS_HIDE means cursor is hidden)
  1060.  *                (        CURS_SHOW means cursor is not hidden)
  1061.  */
  1062. TTY_WHideCurs()
  1063. {
  1064.     TTY_WBlinkCurs(CURS_INVIS);
  1065.     cursHid = CURS_HIDE;
  1066. }
  1067. /*
  1068.  * Hook for exit.  Perform any post-processing desired, then call
  1069.  * ExitToShell().
  1070.  */
  1071. exit(){
  1072.     Rect **origwindow,**savewindow;
  1073.     char fname[256];
  1074. /*
  1075.  * The next section saves the current window location and size in the
  1076.  * resource fork of the startup file, creating it if necessary.
  1077.  */
  1078.     if(rfile == -1){
  1079.         if(flook(pathname[0]) != NULL){
  1080.             strcpy(fname,pathname[0]);
  1081.             c2pstr(fname);
  1082.             SetVol(nil,_iovrefnum);
  1083.             CreateResFile(fname);
  1084.             rfile = OpenRFPerm(fname,_iovrefnum,fsCurPerm);
  1085.         }
  1086.     }
  1087.     if(rfile != -1){
  1088.         origwindow = (Rect**)GetResource('WIND',128);
  1089.         if(HomeResFile(origwindow) == rfile){
  1090.             savewindow = origwindow;
  1091.         }else{
  1092.             UseResFile(rfile);
  1093.             savewindow = (Rect **)NewHandle(GetHandleSize(origwindow));
  1094.             HLock(origwindow);
  1095.             HLock(savewindow);
  1096.             BlockMove(*origwindow,*savewindow,GetHandleSize(origwindow));
  1097.             AddResource(savewindow,'WIND',128,"\012App Window");
  1098.         }
  1099.         **savewindow = ((WindowPtr)uEmacsTTY_W)->portRect;
  1100.         LocalToGlobal(*savewindow);
  1101.         LocalToGlobal(&((**savewindow).bottom));
  1102.         ChangedResource(savewindow);
  1103.         UpdateResFile(rfile);
  1104.     }
  1105.     ExitToShell();
  1106. }
  1107. maineventloop()        /* Used to be main(). */
  1108. {
  1109.     int32            growResult;
  1110.     int16            windowCode, dialogItemHit;
  1111.     Boolean         GNEResult, dialogResult;
  1112.     WindowPtr        whichWindow;
  1113.     DialogPtr        whichDialog;
  1114.     WindowPeek        tempWPeek;
  1115.     EventRecord        anEvent;
  1116.     GrafPtr         oldPort;
  1117.     int            mine;
  1118.     char            vname[256];
  1119.     Boolean            done = false;
  1120.     char             *flook();
  1121.     char             fname[256];
  1122.     ProcPtr         *GetC_Resource;
  1123.     
  1124.     Handle ourHandle;
  1125.     int i;
  1126.  
  1127. #ifdef macintosh
  1128.     ReleaseResource(GetNamedResource('CODE',"\007%A5Init"));
  1129. #endif    
  1130.  
  1131. /* Load the keyboard Event Record interpreter. */
  1132.     GetC_Resource = (ProcPtr *)GetResource('GetC',606);
  1133.     LoadResource(GetC_Resource);
  1134.     HNoPurge(GetC_Resource);
  1135. #ifdef macintosh    /* MPW╤code at top of heap; Aztec╤code at bottom. */
  1136.     HUnlock(GetC_Resource);
  1137.     MoveHHi(GetC_Resource);
  1138. #endif
  1139.     HLock(GetC_Resource);
  1140.     KeyInterpreter = *GetC_Resource;
  1141.  
  1142.     MoreMasters();
  1143.     MoreMasters();
  1144.     MoreMasters();
  1145.     MoreMasters();
  1146.  
  1147.     GetAppParms(ourAppName,&ourRefNum,&ourHandle);
  1148.  
  1149.     GetVol(vname,&ourVRefNum);
  1150. /*
  1151.  * If we find a startup file in the normal place, we open the resource
  1152.  * fork and use it as the current resource file.
  1153.  */
  1154.     if(flook(pathname[0]) != NULL){
  1155.         strcpy(fname,pathname[0]);
  1156.         c2pstr(fname);
  1157.         rfile = OpenRFPerm(fname,_iovrefnum,fsCurPerm);
  1158.         UseResFile(rfile);
  1159.     }
  1160.  
  1161.     SetUpMenus();
  1162.     InitEmacs();
  1163.  
  1164. #ifdef macintosh
  1165.     UnloadSeg(InitEmacs);
  1166.     ReleaseResource(GetNamedResource('CODE',"\004INIT"));
  1167. #endif
  1168.     
  1169. /*
  1170.  * This was a "for(;;)" but the compiler optimized out the return part of the
  1171.  * function and MacsBug couldn't see the debugger label for main().
  1172.  */
  1173.     do{
  1174.     
  1175.         SystemTask();
  1176.         
  1177.         GetPort(&oldPort);
  1178.         /* Check for keyboard input to TTY_Windows */
  1179.         if((whichWindow=FrontWindow()) == (WindowPtr)uEmacsTTY_W) {
  1180.             /* Keyboard event or non-empty owner char buffer? */
  1181.             if( EventAvail((short)(keyDownMask+autoKeyMask), &anEvent) ) {
  1182.                 SetPort(uEmacsTTY_W);
  1183.                 Do_Emacs_Char();
  1184.                 update(TRUE);
  1185.                 TTY_WRecalcScroll();
  1186.             }
  1187.         } else if(whichWindow != NIL) {
  1188.             if(EventAvail((short)(keyDownMask+autoKeyMask), &anEvent))
  1189.                 GetNextEvent((short)(keyDownMask+autoKeyMask), &anEvent);
  1190.         }
  1191.         GNEResult = GetNextEvent(
  1192.             (short)(everyEvent-keyDownMask-keyUpMask-autoKeyMask), &anEvent);
  1193.         /* Pass NIL ptr to trigger insertion pt updates in TTY_W's and Dialogs */
  1194.         (void)FindWindow(anEvent.where,&tempWPeek);
  1195.         mine = (uEmacsTTY_W == tempWPeek || 
  1196.             uEmacsTTY_W == (WindowPeek)anEvent.message ||
  1197.             anEvent.what == app4Evt);
  1198.         if(!GNEResult) {
  1199.             anEvent.what = nullEvent;
  1200.             SetPort(uEmacsTTY_W);
  1201.             eventparser(&anEvent);
  1202.         } else if(mine) {
  1203.             SetPort(uEmacsTTY_W);
  1204.             if(anEvent.what == app4Evt){    /* Suspend/Resume */
  1205.                 anEvent.what = activateEvt;
  1206.                 anEvent.modifiers = (short)(anEvent.message & 1);
  1207.             }    /* Cast to activateEvt for ╡Emacs window */
  1208.             eventparser(&anEvent);
  1209.         } else {
  1210.             /* Main event processor */
  1211.             switch (anEvent.what) {
  1212.                 case mouseDown:
  1213.                     windowCode = FindWindow(anEvent.where, &whichWindow);
  1214.                     switch (windowCode) {
  1215.                         case inMenuBar:
  1216.                             BuildBufferMenu();/* Fix-up Menus */
  1217.                             SetPort(whichWindow);
  1218.                             menuparser(MenuSelect(anEvent.where));
  1219.                             break;
  1220.                         case inSysWindow:
  1221.                             SetPort(whichWindow);
  1222.                             SystemClick(&anEvent, whichWindow);
  1223.                             break;
  1224.                         default:
  1225.                             break;
  1226.                     }
  1227.                     break;
  1228.                 default:
  1229.                     break;
  1230.             }
  1231.         SetPort(oldPort);
  1232.         }
  1233.     }while(!done);
  1234. }
  1235.  
  1236. /*
  1237.  * menuparser() - Process mouse clicks in menu bar
  1238.  */
  1239.  
  1240. menuparser(mResult)
  1241. long int mResult;
  1242. {
  1243.     char    name[256];
  1244.     char    bufname[256];
  1245.     short    i,j;
  1246.     short    theMenu, theItem;
  1247.     int (*fncmatch())();
  1248.     register int (*kfunc)();    /* ptr to a named menu function */
  1249.     short    length;     /* length of a menu command string */
  1250.     short    extendedcmd;    /* simple command or extended? */
  1251.  
  1252.     SetPort(uEmacsTTY_W);
  1253.  
  1254.     theMenu = HiWord(mResult);            /* This is the RSRC ID */
  1255.     theItem = LoWord(mResult);            /* This is the item number */
  1256.     switch (theMenu-MENUBASE) {
  1257.         case appleMenu:
  1258.             if (theItem == aboutMeItem) {
  1259.                 /* Put up the credits */;
  1260.                 DoAbout();
  1261.             } else {
  1262.                 long driversize;
  1263.                 GetItem(myMenus[appleMenu], theItem, name);
  1264.                 (void) OpenDeskAcc(name);   /* Argh! */
  1265.                 SetPort(uEmacsTTY_W);
  1266.             }
  1267.             break;
  1268.         case editMenu:
  1269.             /*
  1270.              * If this is for a 'standard' edit item,
  1271.              * run it through SystemEdit first.
  1272.              * SystemEdit will return FALSE if it's not a system window.
  1273.              */
  1274.             if ((theItem <= clearItem) && SystemEdit(theItem-1)) {
  1275.                 break;
  1276.             }
  1277.             /*
  1278.              * Otherwise, it's my window.
  1279.              */
  1280.             switch (theItem) {
  1281.                 case undoItem:
  1282.                     /* can't undo */
  1283.                     break;
  1284.                 case cutItem:
  1285.                     emacs_cut();
  1286.                     break;
  1287.                 case copyItem:
  1288.                     emacs_copy();
  1289.                     break;
  1290.                 case pasteItem:
  1291.                     emacs_paste();
  1292.                     break;
  1293.                 case clearItem:
  1294.                     break;
  1295.                 default:
  1296.                     break;
  1297.             } /*endsw theItem*/
  1298.             break;
  1299.  
  1300.         case bufferMenu:
  1301.             GetItem(myMenus[bufferMenu], theItem, name);
  1302.             PtoCstr(name);
  1303.         /* See note below regarding '-' as first character in menu item. */
  1304.             if(SwitchToBuffer(name[0] == '\0' ? &name[1] : name))
  1305.             {
  1306.                 CheckItem(myMenus[bufferMenu], theItem, true);
  1307.                 update(FALSE);
  1308.             }
  1309.             break;
  1310.         case fileMenu:        /* User-configured menus, all. */
  1311.         case commands1Menu:    /* Content is significant. */
  1312.         case commands2Menu:
  1313.         case commands3Menu:
  1314.         case commands4Menu:
  1315.             GetItem(myMenus[theMenu-MENUBASE],theItem,name);
  1316.             length = name[0];
  1317.             PtoCstr(name);
  1318.             extendedcmd = FALSE;
  1319.             for(;--length;){
  1320.                 if(name[length]==' ')extendedcmd = TRUE;
  1321.             }
  1322.             if(extendedcmd) docmd(name);    /* execute a command line */
  1323.             else{
  1324.                 kfunc=fncmatch(name);
  1325.                 if (kfunc == NULL) {
  1326.                     mlwrite("[No such function]");
  1327.                     return(FALSE);
  1328.                 }
  1329.                 (*kfunc)(FALSE, 0);    /* execute a named command */
  1330.             }
  1331.             update(FALSE);
  1332.             break;
  1333.     }
  1334.     HiliteMenu(0);
  1335.     return;
  1336. }
  1337.  
  1338.  
  1339. BuildBufferMenu()
  1340. {
  1341.     BUFFER    *bp;
  1342.     char    bname[256];
  1343.     int16    i,j,buf_items;
  1344.  
  1345.     /* Empty out the menu >128K ROMs only*/
  1346.     buf_items = CountMItems(myMenus[bufferMenu]);
  1347.     for(i=buf_items; i>0; i--) DelMenuItem(myMenus[bufferMenu], i);
  1348.     i=0;
  1349.     
  1350. /*
  1351.  * Cycle through the buffer list.
  1352.  * First time for active buffers, second time for inactive.
  1353.  * This puts the list of active buffers together at the top
  1354.  * of the menu.
  1355.  */
  1356.     bp = bheadp;
  1357.     while (bp != NULL) {
  1358.         /* Don't display internal buffers */
  1359.         /* Don't display inactive buffers */
  1360.         if((bp->b_flag & BFINVS) || (bp->b_active != TRUE)) {
  1361.             bp = bp->b_bufp;
  1362.             continue;
  1363.         }
  1364. /*
  1365.  * The following subterfuge is necessary because any menu item whose title
  1366.  * begins with '-' will appear as a gray line.    In the event of a buffer
  1367.  * name beginning with '-', we put a NUL in front of the name to keep
  1368.  * the MDEF from seeing the '-'.
  1369.  */
  1370.         bname[0] = '\0';
  1371.         strcpy(bp->b_bname[0] == '-' ? &bname[1] : &bname[0], bp->b_bname);
  1372.         CtoPstr(bname[0] == '\0' && bname[1] == '-' ? &bname[1] : &bname[0]);
  1373.         if(bname[0] == '\0' && bname[2] == '-'){
  1374.             bname[0] = bname[1] + 1;
  1375.             bname[1] = '\0';
  1376.         }
  1377. /*
  1378.  * Add/Set menu item to the buffer name.  Try to avoid the effect
  1379.  * of possible Menu Meta-characters in buffer names.
  1380.  */
  1381.         i++;
  1382.  
  1383.         AppendMenu(myMenus[bufferMenu], "\001 ");
  1384.         SetItem(myMenus[bufferMenu], i,bname);
  1385.         /* Check the current buffer */
  1386.         if(bp == curbp) {
  1387.             CheckItem(myMenus[bufferMenu], i, true);
  1388.         }
  1389.         /* Italicize the name if the buffer is modified. */
  1390.         if(bp->b_flag & BFCHG){
  1391.             SetItemStyle(myMenus[bufferMenu], i, italic);
  1392.         }
  1393.         bp = bp->b_bufp;
  1394.     }
  1395. /*
  1396.  * Once again through the list, looking for inactive buffers.
  1397.  */
  1398.     bp = bheadp;
  1399.     while (bp != NULL) {
  1400.         /* Don't display active buffers */
  1401.         if(bp->b_active == TRUE) {
  1402.             bp = bp->b_bufp;
  1403.             continue;
  1404.         }
  1405.         bname[0] = '\0';
  1406.         strcpy(bp->b_bname[0] == '-' ? &bname[1] : &bname[0], bp->b_bname);
  1407.         CtoPstr(bname[0] == '\0' && bname[1] == '-' ? &bname[1] : &bname[0]);
  1408.         if(bname[0] == '\0' && bname[2] == '-'){
  1409.             bname[0] = bname[1] + 1;
  1410.             bname[1] = '\0';
  1411.         }
  1412.         i++;
  1413.  
  1414.         AppendMenu(myMenus[bufferMenu], "\001 ");
  1415.         SetItem(myMenus[bufferMenu], i,bname);
  1416.         /* Display in outline if not in memory. */
  1417.         SetItemStyle(myMenus[bufferMenu], i, outline);
  1418.         bp = bp->b_bufp;
  1419.     }
  1420.     
  1421. }
  1422.  
  1423.  
  1424. /*
  1425.  *    SwitchToBuffer()
  1426.  *
  1427.  *        Change to the named buffer.
  1428.  */
  1429. SwitchToBuffer(name)
  1430.     char    *name;
  1431. {
  1432.     register BUFFER *bp;
  1433.     register int    s;
  1434.  
  1435.     if ((bp=bfind(name, TRUE, 0)) == NULL)
  1436.         return (FALSE);
  1437.     return(swbuffer(bp));
  1438. }
  1439.  
  1440. /*
  1441.  * Set up the user menus.  Called only once.
  1442.  */
  1443. #define __SEG__ INIT
  1444.  
  1445. SetUpMenus()
  1446. {
  1447.     int menu;
  1448.  
  1449.     myMenus[appleMenu] = GetMenu(appleMenu+MENUBASE);
  1450.     AddResMenu(myMenus[appleMenu], (ResType) 'DRVR');
  1451.     myMenus[fileMenu]   = GetMenu(fileMenu+MENUBASE);
  1452.     myMenus[editMenu]   = GetMenu(editMenu+MENUBASE);
  1453.     myMenus[bufferMenu] = GetMenu(bufferMenu+MENUBASE);
  1454.     myMenus[commands1Menu] = GetMenu(commands1Menu+MENUBASE);
  1455.     myMenus[commands2Menu] = GetMenu(commands2Menu+MENUBASE);
  1456.     myMenus[commands3Menu] = GetMenu(commands3Menu+MENUBASE);
  1457.     myMenus[commands4Menu] = GetMenu(commands4Menu+MENUBASE);
  1458.     for (menu=0; menu <= lastMenu; ++menu) InsertMenu(myMenus[menu], 0);
  1459.     DrawMenuBar();
  1460.  
  1461.     return;
  1462. }
  1463. #define __SEG__ mactty
  1464. /*
  1465.  * DoAbout:
  1466.  *
  1467.  *    Dialog box handler for extended about box.  Put up a dialog
  1468.  *    box with help information.  Cycle through a string list
  1469.  *    (STR# ID HLIST) to change the contents of a statText item.
  1470.  *    Help information is updated by changing the contents of the
  1471.  *    STR#, making things easier to localize.
  1472.  */
  1473. #define HDLOG 128
  1474. #define HLIST 957
  1475. #define HITEM 5
  1476. #define MORE 1
  1477. #define BACK 2
  1478. #define ENOUGH 3
  1479. DoAbout()
  1480. {
  1481.     int16        res,i,helptype,nlimit;
  1482.     DialogPtr    helpdialog;
  1483.     WindowPtr    tempport;
  1484.     char        helpstring[256];
  1485.     StringHandle    creatorstring;
  1486.     Handle        helpitem;
  1487.     Rect        helpbox;
  1488.     int16        **stringlist;
  1489.     int16        moretype;
  1490.     Handle        moreitem;
  1491.     Rect        morebox;
  1492.     /* Prepare to use dialog box. */
  1493.     helpdialog = GetNewDialog(HDLOG,(long)0,(WindowPtr) -1);
  1494.     GetDItem(helpdialog,HITEM,&helptype,&helpitem,&helpbox);
  1495.     GetDItem(helpdialog,MORE,&moretype,&moreitem,&morebox);
  1496.     GetPort(&tempport);
  1497.     SetPort(helpdialog);
  1498.     ForeColor(redColor);
  1499.     PenSize(3,3);
  1500.     InsetRect(&morebox,-4,-4);
  1501.     FrameRoundRect(&morebox,16,16);
  1502.     /* How many strings? */
  1503.     stringlist = (int16 **)GetResource('STR#',HLIST);
  1504.     LoadResource(stringlist);
  1505.     if((creatorstring = (StringHandle)GetResource('Earl',0)) != NULL){
  1506.         LoadResource(creatorstring);
  1507.         GetDItem(helpdialog,HITEM - 1,&moretype,&moreitem,&morebox);
  1508.         HLock(creatorstring);
  1509.         SetIText(moreitem,*creatorstring);
  1510.         ReleaseResource(creatorstring);
  1511.     }    
  1512.     nlimit = (int16) **stringlist;
  1513.     i = 0;
  1514.     res = 1;
  1515.     while(res != ENOUGH){        /* Done when quit button selected. */
  1516.         if (res == BACK) i--;                /* Cycle back. */
  1517.         else i++;                /* Cycle forwards. */
  1518.         if (i<1) i=nlimit;       /* Choose < 1, use last string. */
  1519.         GetIndString(helpstring,HLIST,i);    /* Get the string. */
  1520.         if(helpstring[0] == '\0'){   /* Out of range, last string. */
  1521.             i=1;               /* Cycle back to first one. */
  1522.             GetIndString(helpstring,HLIST,i);    /* Get it. */
  1523.         }
  1524.         ForeColor(blueColor);
  1525.         SetIText(helpitem,helpstring);            /* Use it. */
  1526.         ModalDialog(0L,&res);        /* ModalDialog handles events. */
  1527.     }
  1528.     DisposDialog(helpdialog);            /* Done, clean up. */
  1529.     SetPort(tempport);
  1530.     ReleaseResource(GetResource('DLOG',128));
  1531.     ReleaseResource(GetResource('DITL',128));
  1532.     ReleaseResource(stringlist);
  1533. }
  1534. /*
  1535.  * Default item filter for print dialogs.
  1536.  */
  1537. pascal short MyFilter(tp,theEvent,itemhit)
  1538. DialogPtr tp;
  1539. EventRecord *theEvent;
  1540. int16       *itemhit;
  1541. {
  1542. char c;
  1543. GrafPtr port;
  1544. int16 type;
  1545. Handle item;
  1546. Rect box;
  1547.     if(theEvent->what == keyDown){
  1548.         c = (theEvent->message & charCodeMask);
  1549.         if( (c == 'y') || (c == 'Y') || (c == 13) || (c == 3)){ /* Return or Enter. */
  1550.             *itemhit = 1;
  1551.         }
  1552.         if( (c == 'n') || (c == 'N') ){
  1553.             *itemhit = 2;
  1554.         }
  1555.         if(*itemhit == 1 || *itemhit == 2){
  1556.             GetPort(&port);
  1557.             GetDItem(port,*itemhit,&type,&item,&box);
  1558.             HiliteControl(item,1);
  1559.             return 0x0100;
  1560.         }
  1561.     }
  1562.     return  FALSE;
  1563. }
  1564.  
  1565. int mlyesno(prompt)
  1566. char *prompt;
  1567. {
  1568.     DialogPtr dlg;
  1569.     int16 type,itemhit;
  1570.     Handle item;
  1571.     Rect box;
  1572.     GrafPtr tmpport;
  1573.     char name[256];
  1574.     DialogRecord x;
  1575.     
  1576.     dlg = GetNewDialog(129,0L,(WindowPtr)-1);
  1577.     GetDItem(dlg,1,&type,&item,&box);
  1578.     GetPort(&tmpport);
  1579.     SetPort(dlg);
  1580.     ForeColor(redColor);
  1581.     PenSize(3,3);
  1582.     InsetRect(&box,-4,-4);
  1583.     FrameRoundRect(&box,16,16);
  1584.     ForeColor(blackColor);
  1585.     GetDItem(dlg,1,&type,&item,&box);
  1586.     strcpy(name,prompt);
  1587.     strcat(name,"?");
  1588.     c2pstr(name);
  1589.     GetDItem(dlg,3,&type,&item,&box);
  1590.     SetIText(item,name);
  1591.     itemhit = 0;
  1592.     while(itemhit != 1 && itemhit != 2){
  1593.         ModalDialog(MyFilter,&itemhit);
  1594.     }
  1595.     DisposDialog(dlg);
  1596.     SetPort(tmpport);
  1597.     if(itemhit == 1)return TRUE;
  1598.     else return FALSE;
  1599. }
  1600. #endif
  1601.