home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / ckc095.zip / ckmini.c < prev    next >
C/C++ Source or Header  |  1989-08-22  |  19KB  |  680 lines

  1. /* John A. Oberschelp for Emory University -- vt102 printer support 22 May 1989 */
  2. /*                    Emory contact is Peter W. Day, ospwd@emoryu1.cc.emory.edu */ 
  3. /* Paul Placeway 4/89    - fixed up things for profiling, minor changes */
  4. /* Paul Placeway 3/28/88 - created by moving a bunch of junk out of ckmusr.c */
  5. /*
  6.  * file ckmini.c
  7.  *
  8.  * Module of mackermit containing code for the menus and other MacIntosh
  9.  * things.
  10.  *
  11.  */
  12.  
  13. /*
  14.  Copyright (C) 1985, Trustees of Columbia University in the City of New York.
  15.  Permission is granted to any individual or institution to use, copy, or
  16.  redistribute this software so long as it is not sold for profit, provided this
  17.  copyright notice is retained.
  18. */
  19.  
  20. #include "ckcdeb.h"
  21. #include "ckcker.h"
  22.  
  23. #define    __SEG__ ckmini
  24. #include <desk.h>
  25. #include <files.h>
  26. #include <windows.h>
  27. #include <events.h>
  28. #include <dialogs.h>
  29. #include <fonts.h>
  30. #include <menus.h>
  31. #include <Memory.h>
  32. #include <Resources.h>
  33. #include <Traps.h>
  34. #include <toolutils.h>
  35. #include <devices.h>
  36. #include <serial.h>
  37. #include <textedit.h>
  38. #include <segload.h>
  39. #include <ctype.h>
  40.  
  41. extern    Handle    hPrintBuffer;                    /*JAO*/
  42. #include <printing.h>                        /*JAO*/
  43.  
  44. /* here is what is different */
  45. #ifndef __QUICKDRAW__
  46. #include <QuickDraw.h>
  47. #endif
  48. #include <osutils.h>
  49.  
  50. /* PWP: put the #include for the script manager here! */
  51.  
  52. #ifdef PROFILE
  53. #include <Perf.h>
  54. TP2PerfGlobals ThePGlobals = nil;
  55. #endif /* PROFILE */
  56.  
  57. #include "ckmdef.h"        /* General Mac defs */
  58. #include "ckmres.h"        /* Mac resource equates */
  59. #include "ckmasm.h"        /* new A8 and A9 traps */
  60.  
  61. /* Global Variables */
  62.  
  63. MenuHandle menus[MAX_MENU + 1];    /* handle on our menus */
  64.  
  65. short innum;            /* Input driver refnum */
  66. short outnum;            /* Output driver refnum */
  67. int protocmd;            /* protocol file cmd, or -1 for */
  68.  /* remote cmds, or 0 if not in */
  69.  /* protocol */
  70.  
  71. Cursor *watchcurs;        /* the watch cursor */
  72. Cursor *textcurs, *normcurs;
  73.  
  74. int quit = FALSE;
  75.  
  76. Boolean mcmdactive = TRUE;    /* Enable menu command keys */
  77. Boolean fkeysactive = TRUE;    /* Enable FKEYs */
  78.  
  79. WindowPtr terminalWindow;    /* the terminal window */
  80. extern WindowPtr remoteWindow;    /* the remote command window */
  81.  
  82. extern int dfloc;                       /* Default location: remote/local */
  83. extern int dfprty;                      /* Default parity */
  84. extern int dfflow;                      /* Default flow control */
  85.  
  86. extern int local;            /* running local or remote? */
  87.  
  88. extern Boolean have_multifinder; /* becomes true if we are running MF */
  89. extern Boolean in_background;    /* becomes TRUE if have_multifinder and
  90.                  * we have recieved a "suspend" event */
  91.  
  92. extern long mf_sleep_time;    /* this is the number of (60Hz) ticks to
  93.                  * sleep before getting a nullEvent (to
  94.                  * flash our cursor) (and input chars from
  95.                  * the serial line)
  96.                  */
  97.  
  98. extern Boolean have_128roms;    /* actually, a Mac + or better */
  99.  
  100. /* local variables */
  101.  
  102. Boolean have_fourone = FALSE;    /* true if we are running system 4.1 or
  103.                  * better */
  104. Boolean have_ctrl_key = FALSE; /* true if we have an ADB (SE or II) keyboard */
  105.  
  106. Boolean usingRAMdriver = FALSE;    /* true if using the RAM serial driver */
  107.  
  108. short takeFRefNum;        /* file reference number of the take file */
  109.  
  110. /****************************************************************************/
  111. /****************************************************************************/
  112. cmdini ()
  113. {
  114.     short vRefNum;
  115.     Str255 volName;
  116.     OSErr err;
  117.  
  118.     GetVol (&volName, &vRefNum);
  119.     err = FSOpen ("Kermit Takefile", vRefNum, &takeFRefNum);
  120.     /* try to open the take file */
  121.     if (err == noErr) {
  122.     tlevel = 1;
  123.     getch ();        /* get first character of take file */
  124.     gettoken ();
  125.     };
  126. }                /* cmdini */
  127.  
  128.  
  129.  
  130. /****************************************************************************/
  131. /* return uppercase for a letter */
  132. /****************************************************************************/
  133. char
  134. CAP (c)
  135. char c;
  136. {
  137.     if (islower (c))
  138.     return (_toupper (c));
  139.     else
  140.     return (c);
  141. }                /* CAP */
  142.  
  143.  
  144. #define TAK_SERV    1
  145. #define TAK_QUIT    2
  146. #define TAK_SEND    3
  147. #define TAK_RECV    4
  148. #define TAK_GET        5
  149. #define TAK_INP        6
  150. #define TAK_OUT        7
  151. #define TAK_UNK 255
  152.  
  153. char *takecmdtab[] = {
  154.     "SERVER",
  155.     "QUIT",
  156.     "SEND",
  157.     "RECEIVE",
  158.     "GET",
  159.     "INPUT"
  160.     "OUTPUT",
  161. };
  162.  
  163. int taketoktab[] = {
  164.     TAK_SERV
  165.     TAK_QUIT
  166.     TAK_SEND
  167.     TAK_RECV
  168.     TAK_GET
  169.     TAK_INP
  170.     TAK_OUT
  171. };
  172.  
  173. #define NUMOFCMDS (sizeof (taketoktab)/sizeof(int))
  174.  
  175. /****************************************************************************/
  176. /* return the token number for a specific take command */
  177. /****************************************************************************/
  178. int
  179. findcmd (cmd)
  180. char *cmd;
  181. {
  182.     int k;
  183.  
  184.     for (k = 0; k < NUMOFCMDS; k++)
  185.     if (strcmp (takecmdtab[k], cmd) == 0)
  186.         return (taketoktab[k]);    /* and return ID */
  187.     return (TAK_UNK);        /* else unknown */
  188. }                /* findcmd */
  189.  
  190.  
  191.  
  192. char ch;
  193.  
  194. /****************************************************************************/
  195. /****************************************************************************/
  196. getch ()
  197. {
  198.     long count;
  199.  
  200.     count = 1;
  201.     if (FSRead (takeFRefNum, &count, &ch) != noErr)
  202.     ch = '\0';
  203. }                /* getch */
  204.  
  205.  
  206.  
  207. #define TOK_CMD        1    /* command id in 'theCmd' */
  208. #define TOK_STR        2    /* string in 'theString' */
  209. #define TOK_NUM        3    /* number in 'theNumber' */
  210. #define TOK_ID        4    /* identifier token */
  211. #define TOK_EOF        5    /* end of file token */
  212. #define TOK_SLS        6    /* ',' */
  213. #define TOK_DOT        7    /* '.' */
  214. #define TOK_UNK    255        /* unknown token */
  215.  
  216. int token;
  217. int theCmd;
  218. char theString[256];
  219. long theNumber;
  220.  
  221. /****************************************************************************/
  222. /****************************************************************************/
  223. gettoken ()
  224. {
  225.     int cmdid;
  226.     char *c;
  227.     char buffer[30];
  228.     Boolean comment;
  229.  
  230.     while ((ch <= ' ') || (ch == '/')) {
  231.     if (ch <= ' ')        /* skip all characters <= blank */
  232.         if (ch == '\0') {    /* except eof character */
  233.         token = TOK_EOF;
  234.         return;
  235.         } else
  236.         getch ();
  237.  
  238.     if (ch == '/') {    /* slash / comment */
  239.         getch ();
  240.  
  241.         if (ch != '*') {
  242.         token = TOK_SLS;
  243.         return;
  244.         }
  245.         getch ();
  246.         comment = TRUE;
  247.         while (comment) {
  248.         if (ch == '\0') {
  249.             token = TOK_EOF;
  250.             return;
  251.         }
  252.         if (ch == '*') {
  253.             getch ();
  254.             if (ch == '/') {
  255.             comment = FALSE;
  256.             getch ();
  257.             }
  258.         } else
  259.             getch ();
  260.         }            /* while (comment) */
  261.  
  262.     }            /* if (ch == '/') */
  263.     }                /* while ((ch <= ' ') || (ch == '/')) */
  264.  
  265.     if (ch == '"') {        /* string */
  266.     token = TOK_STR;
  267.     c = theString;
  268.     getch ();
  269.  
  270.     while (TRUE) {
  271.         if (ch == '"')
  272.         ch = '\0';
  273.  
  274.         if (ch == '\\') {
  275.         getch ();
  276.         if (ch == 'n')
  277.             ch = '\n';
  278.         else if (ch == 'b')
  279.             ch = '\b';
  280.         else if (ch == 't')
  281.             ch = '\t';
  282.         }
  283.         if ((c - theString) < (sizeof (theString) - 1))
  284.         *c++ = ch;
  285.  
  286.         if (ch == '\0') {
  287.         *c = '\0';
  288.         getch ();
  289.         return;
  290.         } else
  291.         getch ();
  292.     }
  293.     }                /* TOK_STR */
  294.     if ((ch >= '0') && (ch <= '9')) {    /* number */
  295.     token = TOK_NUM;
  296.     theNumber = 0;
  297.     getch ();
  298.     return;
  299.     }                /* TOK_NUM */
  300.     ch = CAP (ch);
  301.     if ((ch >= 'A') && (ch <= 'Z')) {    /* command / identifier */
  302.     c = buffer;
  303.     while ((((ch >= 'A') && (ch <= 'Z')) ||    /* get the whole string */
  304.         ((ch >= '0') && (ch <= '9'))) &&
  305.            ((c - buffer) < (sizeof (buffer) - 1))) {
  306.         *c++ = ch;
  307.         getch ();
  308.         ch = CAP (ch);
  309.     }
  310.     *c = '\0';        /* end the buffer with \0 */
  311.  
  312.     cmdid = findcmd (buffer);    /* check for command */
  313.     if (cmdid != TAK_UNK) {
  314.         token = TOK_CMD;
  315.         theCmd = cmdid;    /* return the command id if true */
  316.     } else
  317.         token = TOK_ID;    /* return the identifier id if true */
  318.  
  319.     return;
  320.     }                /* TOK_CMD / TOK_ID */
  321.     switch (ch) {
  322.       case '.':        /* dot */
  323.     token = TOK_DOT;
  324.     break;
  325.  
  326.       default:            /* unknown character */
  327.     token = TOK_UNK;
  328.     }
  329. }                /* gettoken */
  330.  
  331.  
  332.  
  333. /****************************************************************************/
  334. /****************************************************************************/
  335. char
  336. nextcmd ()
  337. {
  338.     if (token == TOK_CMD) {
  339.     switch (theCmd) {
  340.         case TAK_SERV:
  341.         displa = TRUE;
  342.         scrcreate ();    /* create the packet display dialog */
  343.         protocmd = SERV_REMO;    /* run the mac as server */
  344.         gettoken ();
  345.         return ('x');
  346.  
  347.       case TAK_QUIT:
  348.         quit = TRUE;
  349.         FSClose (takeFRefNum);
  350.         return (0);
  351.  
  352.       case TAK_SEND:    /* send a file: local, remote files */
  353.         gettoken ();
  354.         if (token != TOK_STR)
  355.         return (0);
  356.  
  357.         strcpy (filargs.fillcl, theString);    /* file to send */
  358.  
  359.         gettoken ();
  360.         if (token == TOK_STR) {    /* send as */
  361.         strcpy (filargs.filrem, theString);
  362.         gettoken ();
  363.         } else
  364.         zltor (filargs.fillcl, filargs.filrem);
  365.  
  366.         cmarg = filargs.fillcl;
  367.         cmarg2 = filargs.filrem;
  368.  
  369.         nfils = -1;        /* Use cmarg, not cmlist */
  370.         protocmd = SEND_FIL;
  371.         scrcreate ();
  372.         return ('s');    /* return with send state */
  373.  
  374.       case TAK_RECV:
  375.         initfilrecv ();    /* init recv flags */
  376.         protocmd = RECV_FIL;
  377.         scrcreate ();
  378.         gettoken ();
  379.         return ('v');    /* return with recv state */
  380.  
  381.       case TAK_GET:    /* Get from server */
  382.         gettoken ();
  383.         if (token != TOK_STR)
  384.         return (0);
  385.  
  386.         strcpy (cmarg, theString);
  387.         protocmd = GETS_FIL;
  388.         scrcreate ();
  389.         gettoken ();
  390.         return ('r');
  391.  
  392.       default:
  393.         return (0);
  394.     }            /* switch (theCmd) */
  395.  
  396.     } else {
  397.     tlevel = -1;        /* no more commands */
  398.     FSClose (takeFRefNum);
  399.     return (0);
  400.     }
  401.  
  402. }                /* nextcmd */
  403.  
  404.  
  405. /****************************************************************************/
  406. /* init_menus - create the menu bar. */
  407. /****************************************************************************/
  408. setup_menus ()
  409. {
  410.     int i;
  411.     static int menus_are_drawn = 0;
  412.     THz curZone;
  413.  
  414.     if (!menus_are_drawn) {    /* if the first time through */
  415.     /*
  416.      * PWP: we do command keys by default ONLY on a keyboard that has a CTRL
  417.      * key
  418.      */
  419.     mcmdactive = have_ctrl_key;
  420.     
  421.     /* setup Apple menu */
  422.     if ((menus[APPL_MENU] = GetMenu (APPL_MENU)) == NIL)
  423.         printerr("Couldn't get MENU", APPL_MENU);
  424.     else
  425.         AddResMenu (menus[APPL_MENU], 'DRVR');
  426.     } else {
  427.         ClearMenuBar();        /* remove all menus from the list */
  428.     }
  429.     
  430.     InsertMenu (menus[APPL_MENU], 0);    /* Put Apple Menu on menu line */
  431.  
  432.     for (i = MIN_MENU; i <= MAX_MENU; i++) {    /* For all menus */
  433.         if (menus_are_drawn && menus[i]) {
  434.         curZone = GetZone();        /* as per John Norstad's (Disinfectant) */
  435.         SetZone(HandleZone(menus[i]));    /* "Toolbox Gotchas" */
  436.         ReleaseResource(menus[i]);        /* free old resource */
  437.         SetZone(curZone);
  438.     }
  439.         if (mcmdactive) {
  440.         if ((menus[i] = GetMenu (i)) == NIL)    /* Fetch it from resource file */
  441.         printerr("Couldn't get MENU", i);
  442.     } else {
  443.         if ((menus[i] = GetMenu (i+32)) == NIL) {    /* try to get w/o clover */
  444.             printerr("Couldn't get MENU", i+32);
  445.         menus[i] = GetMenu (i);    /* Fetch normal from resource file */
  446.         }
  447.     }
  448.     InsertMenu (menus[i], 0);    /* Put it on menu line */
  449.     }
  450.  
  451.     DrawMenuBar ();        /* Finish up by displaying the bar */
  452.  
  453.     CheckItem (menus[SETG_MENU], MCDM_SETG, mcmdactive);
  454.     menus_are_drawn = 1;
  455. }                /* setup_menus */
  456.  
  457. Boolean
  458. IsWNEImplemented ()
  459. {
  460.     int err;
  461.     SysEnvRec theWorld;
  462. #define FOURONEVERSION    1040    /* version == (short) (4.1 * 256.) */
  463.  
  464.     /*
  465.      * (from Mac Tech Note #158) We need ot call SysEnvirons to make sure
  466.      * that WaitNextEvent is implemented.  If we are running on 64K ROMs, and
  467.      * RAM HFS is running (trap 0xA060), then GetTrapAddress(0x60) will
  468.      * return a value different from the unimplemented trap since trap 60 is
  469.      * implemented for HFS and the 64K ROM version of GetTrapAddress doesn't
  470.      * differentiate between OS and Tool traps.
  471.      */
  472.  
  473.     /* These are both toolbox traps, hence the 1 */
  474.     err = SysEnvirons (1, &theWorld);    /* we have the glue, so machineType
  475.                      * will allways be filled in */
  476.  
  477.     /* to see if we can use the script manager */
  478.     have_fourone = (theWorld.systemVersion >= FOURONEVERSION);
  479.  
  480.     /* let's hope that Apple gets sane about the CTRL key... */
  481.     have_ctrl_key = (theWorld.keyBoardType == envAExtendKbd) ||
  482.     (theWorld.keyBoardType == envStandADBKbd);
  483.  
  484.     have_128roms = !((theWorld.machineType == envMac) ||
  485.                  (theWorld.machineType == envXL) ||
  486.                  (theWorld.machineType == envMachUnknown));
  487.     
  488.     /* is WNE implemented? */
  489.     if (theWorld.machineType < 0)
  490.     return FALSE;        /* we don't know what kind of Mac this is. */
  491.  
  492.     /* "..., 1" 'cause these are tooltraps: */
  493.     /* 6.0.2 bug fixed by RWR <CES00661%UDACSVM.BITNET@cunyvm.cuny.edu> */
  494.     
  495.     if ((NGetTrapAddress (num_WaitNextEvent, 1) !=
  496.      NGetTrapAddress (num_UnknownTrap, 1)) &&    /* RWR  */
  497.     (NGetTrapAddress (num_JugglDispatch, 1) !=    /* RWR  */
  498.      NGetTrapAddress (num_UnknownTrap, 1)))        /* RWR  */
  499.     return TRUE;
  500.  
  501.     return FALSE;
  502. }
  503.  
  504. extern hmacrodefs macroshdl;    /* handle to the macro table */
  505. extern modrec modtable[NUMOFMODS];    /* modifier records */
  506. extern RgnHandle dummyRgn;    /* dummy region for ckmcon */
  507. WindowRecord terminalWRec;    /* store window stuff here */
  508. extern char **myclip_h;        /* internal clipboard */
  509. extern int myclip_size;        /* size of above */
  510. extern long MyCaretTime;    /* ticks between flashes for cursor */
  511. extern char **myclip_h;        /* internal terminal clipboard */
  512.  
  513. /****************************************************************************/
  514. /* mac_init - Initialize the macintosh and any window, menu, or other */
  515. /* resources we will be using. */
  516. /****************************************************************************/
  517. mac_init ()
  518. {
  519.     int err;
  520.     int i;
  521.     CursHandle cursh;
  522.  
  523.     MaxApplZone ();        /* Make appl. heap big as can be */
  524.  
  525.     MoreMasters ();        /* Create some more master pointers */
  526.     MoreMasters ();        /* Create some more master pointers */
  527.     err = MemError ();
  528.     if (err != noErr)
  529.     printerr ("Unable to create masters", err);
  530.  
  531.     InitGraf (&qd.thePort);    /* Init the graf port */
  532.     InitFonts ();        /* The fonts */
  533.     InitWindows ();        /* The windows */
  534.  
  535. /* Debugger(); */
  536.     /*
  537.      * PWP: we MUST call IsWNEImplemented() BEFORE using have_fourone, or
  538.      * have_ctrl_key (in InitMenus() )
  539.      */
  540.     have_multifinder = IsWNEImplemented ();    /* See Above. */
  541.  
  542.     InitMenus ();
  543.     TEInit ();            /* Init text edit */
  544.     InitDialogs (NILPROC);    /* The dialog manager */
  545.     InitCursor ();        /* start with a nice cursor */
  546.     SetEventMask (everyEvent - keyUpMask);
  547.  
  548.     dummyRgn = NewRgn ();
  549.  
  550.     normcurs = &qd.arrow;
  551.     if ((cursh = GetCursor (watchCursor)) != NIL) {
  552.     HLock(cursh);
  553.     watchcurs = *cursh;        /* the waiting cursor */
  554.     } else {
  555.         watchcurs = &qd.arrow;
  556.     }
  557.     if ((cursh = GetCursor (iBeamCursor)) != NIL) {
  558.     HLock(cursh);
  559.     textcurs = *cursh;        /* the text body cursor */
  560.     } else {
  561.         textcurs = &qd.arrow;
  562.     }
  563.  
  564.     MyCaretTime = GetCaretTime();
  565.     if (MyCaretTime < 3 || MyCaretTime > 300)
  566.     MyCaretTime = 20L;
  567.     
  568.     setup_menus ();        /* build our menus */
  569.     ScrDmpEnb = scrdmpenabled;    /* enable FKEYs */
  570.  
  571.     inittiobufs();        /* init terminal I/O buffers */
  572.  
  573.     initrcmdw ();        /* init remote cmd window */
  574.     initfilset ();        /* init file settings */
  575.  
  576.     terminalWindow = GetNewWindow (TERMBOXID, &terminalWRec, (WindowPtr) - 1);
  577.     SetPort (terminalWindow);
  578.  
  579.     TextFont (monaco);        /* Monaco font for non-proportional spacing */
  580.     TextSize (9);
  581.  
  582.     FlushEvents (everyEvent, 0);    /* clear click ahead */
  583.  
  584.     port_open(-6);    /* open Modem port by default */
  585.     
  586.     parity = DEFPAR;
  587.     if (!setserial (innum, outnum, DSPEED, DEFPAR))    /* set speed parity */
  588.     fatal("Couldn't set serial port to default speed",0);
  589.     
  590.     ttres();            /* (PWP) set up flow control for interactive use */
  591.     
  592.     consetup ();        /* Set up for connecting */
  593.     displa = TRUE;        /* Make everything goes to screen */
  594.  
  595.     /* init (internal) clipboard */
  596.     myclip_h = (char **) NewHandle (32);
  597.     myclip_size = 0;
  598.     
  599.     /* init the macro table */
  600.     macroshdl = (hmacrodefs) NewHandle (MacroBaseSize);
  601.     (*macroshdl)->numOfMacros = 0;
  602.  
  603.     /* clear the prefix strings */
  604.     for (i = 0; i < NUMOFMODS; i++)
  605.     modtable[i].prefix[0] = '\0';
  606.  
  607.     loadkset ();        /* PWP: get our defaults for these */
  608.     loadmset ();
  609.  
  610.     /* Frank changed main() to call init and then set flow, parity, etc.
  611.        so we make sure they will be set right (again) after we return. */
  612.     dfloc = local;                      /* And whether it's local or remote. */
  613.     dfprty = parity;                    /* Set initial parity, */
  614.     dfflow = flow;                      /* and flow control. */
  615.  
  616.  
  617. #ifdef PROFILE
  618.     if (!INITPERF(&ThePGlobals, 1, 8, FALSE, TRUE, "\pCODE", 0, "\pROMII",
  619.                   FALSE, 0, 0, 0))
  620.     fatal("Could not start profiling", 0);
  621.     (void) PerfControl(ThePGlobals, TRUE);
  622. #endif /* PROFILE */
  623. }                /* mac_init */
  624.  
  625.  
  626. /****************************************************************************/
  627. /* mac_cleanup() - called before leaving this program to clean up any */
  628. /*                     dangling Mac stuff. */
  629. /* Called by doexit, transfer and zkself. */
  630. /****************************************************************************/
  631. mac_cleanup ()
  632. {
  633.     ScrDmpEnb = scrdmpenabled;    /* re-enabled screen dumping */
  634.     
  635.     FutzOptKey(0);        /* reset old Mac key map */
  636.     
  637. #ifdef PROFILE
  638.     if (PERFDUMP(ThePGlobals, "\pPerform.out", true, 80))
  639.     fatal("Could not dump profiling output", 0);
  640.     (void) TermPerf (ThePGlobals);
  641. #endif /* PROFILE */
  642.  
  643.     port_close();        /* close the serial port down */
  644.  
  645. #ifdef TLOG
  646.     if (tralog)            /* close transaction log if necessary */
  647.     closetlog ();
  648. #endif TLOG
  649.  
  650.     if (seslog)            /* close session log if necessary */
  651.     closeslog ();
  652.  
  653.     DisposeMacros ();        /* dipose all macro strings */
  654.     if (macroshdl)
  655.     DisposHandle ((Handle) macroshdl);    /* release the macro table */
  656.     macroshdl = 0L;
  657.     
  658.     if (myclip_h)
  659.     DisposHandle(myclip_h);                                            /*JAO*/
  660.     myclip_h = 0L;                                                    /*JAO*/
  661.  
  662.     if (hPrintBuffer)
  663.     DisposHandle(hPrintBuffer);                                            /*JAO*/
  664.     hPrintBuffer = 0L;                                                    /*JAO*/
  665.  
  666.     DisposeRgn (dummyRgn);
  667. }                /* mac_cleanup */
  668.  
  669.  
  670.  
  671. /****************************************************************************/
  672. /* doexit(status) - exit to shell.  Perhaps we should check for abnormal */
  673. /*                      status codes... */
  674. /****************************************************************************/
  675. doexit (status)
  676. {
  677.     mac_cleanup ();        /* make things tidy */
  678.     ExitToShell ();
  679. }                /* doexit */
  680.