home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / c-kermit / ckmusr.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  48KB  |  1,903 lines

  1. /* File ckmusr.c */
  2.  
  3. /*
  4.   Copyright (C) 1984, 1995, Trustees of Columbia University in the City of New
  5.   York.  The C-Kermit software may not be, in whole or in part, licensed or
  6.   sold for profit as a software product itself, nor may it be included in or
  7.   distributed with commercial products or otherwise distributed by commercial
  8.   concerns to their clients or customers without written permission of the
  9.   Office of Kermit Development and Distribution, Columbia University.  This
  10.   copyright notice must not be removed, altered, or obscured.
  11. */
  12.  
  13. /* fdc - edits for 0.991(190), 17 Aug 94 */
  14. /*
  15.  edit by John A. Oberschelp for Emory University --
  16.  vt102 printer support 22 May 1989
  17.  */
  18. /* Emory contact is Peter W. Day, ospwd@emoryu1.cc.emory.edu */ 
  19. /* various edits by PWP 8/88 -- 5/89: much rearangement, new menus 'n stuff */
  20. /* edit by PWP 3/27/88 -- Make the log session and transaction stuff a   */
  21. /*  separate menu. */
  22. /* edits by PWP -- Nov. 87..Mar. 88  Fixed several oversights, bugs, etc., */
  23. /* added MultiFinder support */
  24. /* Version 0.9(36) - Matthias Aebi, ECOFIN Research and Consulting, Ltd., */
  25. /*  Oct 1987 ported to MPW C */
  26. /* Version 0.8(35) - Jim Noble at Planning Research Corporation, June 1987. */
  27. /* Ported to Megamax native Macintosh C compiler. */
  28. /* DPVC at U of R, on Oct 1, to do blinking cursor and mouse cursor movement */
  29. /* Edit by Bill, Jeff, and Howie on Jun 13 */
  30. /* Add select window, drag */
  31. /* Edit by WBC3 on Apr 29 */
  32. /* Don't supply a second name for send as, otherwise file name translation */
  33. /* will not occur.  Let user type it if they want. */
  34. /* Edit by WBC3 on Apr 23 */
  35. /* Make typein to the emulator only take effect when it's the "front window" */
  36. /* Edit by WBC3 on Apr 23 */
  37. /* Make only Command-. stop protocol rather then anything but Command-. */
  38. /* Edit by WBC3 on Apr 22 */
  39. /* Make debug and tlog only show up if DEBUG is defined */
  40. /* Edit by Bill on Apr 21 17:51 */
  41. /* In Screen depelete event queue instead of handling one event at */
  42. /* a time, also don't loose events */
  43.  
  44. /*
  45.  * file ckmusr.c
  46.  *
  47.  * Module of mackermit containing code for the menus and other MacIntosh
  48.  * things.
  49.  *
  50.  */
  51. #include <DiskInit.h>
  52. #include "ckcdeb.h"
  53. #include "ckcker.h"
  54.  
  55. #include "ckmdef.h"        /* General Mac defs */
  56. #include "ckmres.h"        /* Mac resource equates */
  57. #include "ckmasm.h"        /* new A8 and A9 traps */
  58. #include "ckmwin.h"        /* common window routines */
  59. #include "ckmcon.h"
  60. #include "ckmptp.h"        /* ckm* Prototypes */
  61. #ifdef MPW33
  62. #include <Signal.h>
  63. #endif /* MPW33 */
  64.  
  65. /* Global Variables */
  66.  
  67. #ifdef COMMENT
  68. /* these are now found in ckuusx.c */
  69. int success = 1;        /* C-Kermit command succeeded flag */
  70. int cmdlvl = 0;            /* macro nesting depth (currently unused) */
  71. #endif /* COMMENT */
  72.  
  73. #ifdef CK5A
  74. /* file wierdness (used for VAX/VMS C-Kermit */
  75. int fblksiz = DBLKSIZ;        /* file block size */
  76. int frecl = DLRECL;        /* file record length */
  77. int frecfm = XYFF_S;        /* file record format */
  78. int forg = XYFO_S;        /* file orginization (sequential) */
  79. int fcctrl = XYFP_N;        /* file carriage control (control chars) */
  80. #endif /* CK5A */
  81.  
  82. MenuHandle menus[LAST_MENU + 1];    /* Handle on our menus */
  83.  
  84. short innum;                /* Input driver refnum */
  85. short outnum;                /* Output driver refnum */
  86. int protocmd;                /* protocol file cmd, or -1 for */
  87.                     /* remote cmds, or 0 if not in */
  88.                     /* protocol */
  89.  
  90. char *mybuff;                /* Serial drivers new buffer */
  91.  
  92. SerShk controlparam;            /* Change serial driver parameters */
  93.  
  94. int quit = FALSE;
  95.  
  96. Boolean mcmdactive = TRUE;        /* Enable menu command keys */
  97. Boolean fkeysactive = TRUE;        /* Enable FKEYs */
  98.  
  99. #ifdef notdef
  100. extern WindowPtr remoteWindow;        /* The remote command window */
  101. #endif
  102.  
  103. extern int deblog;            /* If true, do debugging */
  104. extern int what;
  105. extern int connected;
  106. extern OSType texttype;
  107. extern OSType kermtype;
  108. extern Cursor *lastCursor, *watchcurs;
  109.  
  110. /* 
  111.  * local variables 
  112.  */
  113. static int titlen = 1;
  114. Boolean have_multifinder = FALSE; /* becomes true if we are running MF */
  115. Boolean in_background = FALSE;    /* becomes TRUE if have_multifinder and
  116.                  * we have recieved a "suspend" event */
  117.  
  118. long mf_sleep_time = 5L;    /* this is the number of (60Hz) ticks to
  119.                  * sleep before getting a nullEvent (to
  120.                  * flash our cursor) (and input chars from
  121.                  * the serial line)
  122.                  */
  123. long pr_mf_sleep_time = 2L;    /* Same as above for during transfers */
  124.  
  125. Boolean have_128roms = FALSE;    /* actually, a Mac + or better */
  126. #define switchEvt     1 /* Switching event (suspend/resume )  for app4evt */
  127.  
  128. /*
  129.  * Stuff for alarm() and friends.
  130.  */
  131. SIGTYP (*msignal(int type, SIGTYP (*func)(int)))(int);
  132. SIGTYP (*alarmfunc)() = SIG_IGN;
  133. SIGTYP (*intfunc)() = SIG_IGN;
  134. typedef unsigned long ulong;
  135. ulong alarmtime = 0;          /* global alarm time */
  136.  
  137. /*
  138.  * Forward reference
  139.  */
  140. void closecmdw (struct cmdw *cmdw);
  141. Boolean checksave (struct cmdw *cmdw);
  142. void setwname (struct cmdw *cmdw, StringPtr name);
  143. void savefile (struct cmdw *cmdw, Boolean as);
  144. StringPtr malloc_pstring (StringPtr src);
  145. void redo_window_menu(void);
  146. void insertbuf (char *buf, int len, TEHandle teh, int *eol);
  147. void openfile (void);
  148. static void newfile (Handle h, int len);
  149. void dopagesetup (void);
  150. void doprinter (WindowPtr window);
  151.  
  152. /*
  153.  * Externals
  154.  */
  155. #ifdef COMMENT
  156. extern Handle hPrintBuffer;            /*JAO*/
  157. extern long lPrintBufferChars;
  158. extern long lPrintBufferAt;
  159. #endif /* COMMENT */
  160.  
  161. extern struct cmdw *activecmdw;
  162. extern struct cmdw *cmdwl;
  163. extern int to_printer;
  164.  
  165. /****************************************************************************/
  166. /* miniparser - called during protocol to handle events.  Handles dialog, */
  167. /*                  update, and keydown (the abort key) events.  Ignores */
  168. /*                  all other events.  The dialog events are assumed to */
  169. /*                  be for screen (status) display. */
  170. /****************************************************************************/
  171. miniparser (deplete)        /* deplete pending events */
  172. {
  173.     EventRecord ev;
  174.     DialogPtr mydlg;
  175.     short item;
  176.     
  177.     do {
  178.     if (have_multifinder) {
  179.         /* task, task */
  180.         /*
  181.          * NOTE: pr_mf_sleep_time MUST be < 50 to work right, due to
  182.          * a bug in MultiFinder 1.0.  See TN 177.
  183.          */
  184.         if (pr_mf_sleep_time > 30L)
  185.             pr_mf_sleep_time = 30L;
  186.         WaitNextEvent (everyEvent, &ev, pr_mf_sleep_time, NULL);
  187.     } else {
  188.         SystemTask ();    /* let the system move */
  189.         GetNextEvent (everyEvent, &ev);    /* get an event */
  190.     }
  191.  
  192.     /*
  193.      * Be paranoid: check for all the events that IsDialogEvent might trap
  194.      * but we want to do something with anyway FIRST.
  195.      */
  196.     switch (ev.what) {    /* we may need to do something */
  197.       case nullEvent:
  198.         return;        /* we have depleted all pending events */
  199.  
  200.       case keyDown:
  201.         if ((ev.modifiers & cmdKey) && ((ev.message & 0x7f) == '.')) {
  202.         if (CautionAlert (ALERT_ABORT, 
  203.                   (ModalFilterProcPtr) NILPROC) == OKBtn) {
  204.             sstate = 'a';    /* move into abort state */
  205.             return;
  206.         }
  207.         }
  208.         break;
  209.  
  210.       case app4Evt:    /* really a suspend/resume event */
  211.         if ((have_multifinder) &&
  212.             (((ev.message >> 24) & 0xff) == switchEvt)) {
  213.         in_background = ((ev.message & 0x1) == 0);
  214.         /* PWP: do stuff for disabling the status window here */
  215.         }
  216.         updateCursor(ttermw, 1, (WindowPeek) ev.message);
  217.         break;
  218.     }
  219.  
  220.     /*
  221.      * now try handing any remaining events to the dialog manager
  222.      */
  223.     if (IsDialogEvent (&ev)) {    /* meant for dialog manager? */
  224.     
  225.         /* must be for screen */
  226.         if (DialogSelect (&ev, &mydlg, &item))
  227.         scrmydlg (item);    /* let him handle it */
  228.  
  229.     } else switch (ev.what) {    /* we may need to do something */
  230.       /*
  231.        * Dialog manager didn't want it -- deal with remainders.
  232.        */
  233.       case updateEvt:
  234.         doupdate ((WindowPtr) ev.message);    /* handle updates */
  235.         break;
  236.  
  237.       case mouseDown:    /* Mouse event */
  238.         domouse (&ev, TRUE);
  239.         break;
  240.     }
  241.     } while (deplete);        /* return now, or loop */
  242. }                /* miniparser */
  243.  
  244.  
  245. /*
  246.  * Handle events.
  247.  */
  248. char newparser (deplete, menuok, time)
  249.     int deplete;            /* deplete pending events */
  250.     int menuok;                /* true if menus ok */
  251.     long time;                /* max delay in seconds */
  252. {
  253.     int sconnected;
  254.     char menu_event();
  255.     char nextcmd ();
  256.     char rstate = 0;
  257.     long limitticks;
  258.     EventRecord ev;
  259.     DialogPtr mydlg;
  260.     WindowPtr w;
  261.     short item;
  262.     struct cmdw *cmdw;
  263.     
  264.     limitticks = TickCount() + 60L * time; /* set max time */
  265.  
  266.     /*
  267.      * Save state of connected.  If it changes, exit the parser.
  268.      */
  269.     sconnected = connected;
  270.  
  271.     /*
  272.      * Update the vt100 windows.
  273.      */
  274.     updatecommand(ctermw);
  275.     updatecommand(ttermw);
  276.  
  277.     protocmd = 0;            /* not in protocol mode */
  278.     do {
  279.     /*
  280.      * Update the cursor.
  281.      */
  282.     w = FrontWindow();
  283.     if (w == ttermw->window)
  284.         updateCursor(ttermw, 0, (WindowPeek) w);
  285.     else if (w == ctermw->window)
  286.         updateCursor(ctermw, 0, (WindowPeek) w);
  287.     else if (cmdw = cmdwbywindow(w))
  288.         cmdwUpdateCursor(cmdw);
  289.  
  290. #ifdef notdef /* ??? */
  291.     else updateCursor(ttermw, 0, (WindowPeek) w);
  292. #endif
  293.  
  294.     if (sconnected != connected)
  295.         return (rstate);
  296.  
  297.     if (have_multifinder) {
  298.         /* task, task */
  299.         /*
  300.          * NOTE: mf_sleep_time MUST be < 50 to work right, due to
  301.          * a bug in MultiFinder 1.0.  See TN 177.
  302.          */
  303.         if (mf_sleep_time > 30L)
  304.             mf_sleep_time = 30L;
  305.         WaitNextEvent (everyEvent, &ev, mf_sleep_time, NULL);
  306.     } else {
  307.         SystemTask ();        /* let the system move */
  308.         GetNextEvent (everyEvent, &ev); /* get an event */
  309.     }
  310.  
  311.     /* 
  312.      * See if time has expired 
  313.      */
  314.     if (time && (TickCount() > limitticks))
  315.         return '\0';
  316.     if (alarmtime && alarmfunc && (((ulong)TickCount() - alarmtime) > 0))
  317.         (*alarmfunc)(0);
  318.  
  319.     /* Handle all the pending port chars */
  320.     inpchars(ttermw);
  321.  
  322.     /*
  323.      * Be paranoid: check for all the events that IsDialogEvent might trap
  324.      * but we want to do something with anyway FIRST.
  325.      */
  326.     switch (ev.what) {        /* we may need to do something */
  327.     case keyDown:
  328.     case autoKey:
  329.         if ((ev.modifiers & cmdKey) && ((ev.message & 0x7f) == '.')) {
  330.         if (CautionAlert (ALERT_ABORT, 
  331.                   (ModalFilterProcPtr) NILPROC) == OKBtn)
  332.             return('a');    /* move into abort state */
  333.         } else if ((ev.modifiers & cmdKey) && (mcmdactive)) {
  334.         if (menuok)
  335.             rstate = menu_event(MenuKey(ev.message&charCodeMask));
  336.         if (rstate)
  337.             return rstate;
  338.         } else if (FrontWindow() == ttermw->window) {
  339.         if (!connected) {
  340.             if (console_char(ctermw, &ev)) {
  341.             updateCursor(ctermw, 1, NIL); /* set the watch */
  342.             return (rstate); /* and return with state */
  343.             }
  344.         } else {
  345.             handle_char (ttermw, &ev);
  346.             if (sconnected != connected)
  347.             return (rstate);
  348.         }
  349.         } else if (cmdw = cmdwbywindow(FrontWindow())) {
  350.         rcdkey (cmdw, &ev);
  351.         } else if (FrontWindow () == ctermw->window) {
  352.         /* always a command in this window */
  353.         if (console_char(ctermw, &ev)) {
  354.             cursor_erase(ctermw);
  355.             updateCursor(ctermw, 1, NIL); /* set the watch */
  356.             return (rstate); /* and return with state */
  357.         }
  358.         }
  359.         break;
  360.  
  361.     case app4Evt:            /* really a suspend/resume event */
  362.         if (!have_multifinder) {
  363.         updateCursor(ctermw, 1, (WindowPeek) ev.message);
  364.         break;
  365.         }
  366.  
  367.         switch ((ev.message>>24) & 0xff) {
  368.         case switchEvt:
  369.         /* Treat switch events as activate events too */
  370.         if (ev.message & 0x01) { /* Resume Event */
  371.             in_background = FALSE;
  372.             doactivate(FrontWindow(), activeFlag);
  373.         } else {        /* Suspend Event */
  374.             in_background = TRUE;
  375.             doactivate(FrontWindow(), 0);
  376.             /* PWP: do stuff for disabling the status window here */
  377.         }
  378.         }
  379.         updateCursor(ctermw, 1, (WindowPeek) ev.message);
  380.         break;
  381.     } /* switch */
  382.     
  383.     /*
  384.      * Dialog manager didn't want it -- deal with remainders.
  385.      */
  386.     switch (ev.what) {
  387.     case updateEvt:
  388.         doupdate ((WindowPtr) ev.message); /* handle updates */
  389.         break;
  390.  
  391.     case mouseDown:            /* Mouse event */
  392.         if (rstate = domouse (&ev, FALSE))
  393.         return(rstate);
  394.         break;
  395.  
  396.     case activateEvt:        /* (de)active a window */
  397.         doactivate ((WindowPtr) ev.message, ev.modifiers);
  398.         break;
  399.  
  400.     case diskEvt:            /* disk inserted */
  401.         if (((ev.message >> 16) & 0xFFFF) != noErr) {
  402.         DILoad();
  403.         DIBadMount(ev.where, ev.message);
  404.         DIUnload();
  405.         }
  406.         break;
  407.  
  408.     } /* switch */
  409.  
  410.     /*
  411.      * now try handing any remaining events to the dialog manager
  412.      */
  413.     if (IsDialogEvent (&ev)) {
  414.         if (DialogSelect (&ev, &mydlg, &item))
  415.         scrmydlg (item);    /* let him handle it */
  416.         continue;
  417.     } 
  418.  
  419.     /*
  420.      * Flash the cursors.
  421.      */
  422.     if ((FrontWindow() == ttermw->window) && (ttermw->blinkcursor))
  423.         flash_cursor(ttermw);
  424.     else if ((FrontWindow() == ctermw->window) && (ctermw->blinkcursor))
  425.         flash_cursor(ctermw);
  426.     else if (activecmdw)
  427.         TEIdle(activecmdw->teh);
  428.  
  429.     } while (deplete);            /* return now, or loop */
  430.  
  431.     return rstate;
  432. }
  433.  
  434.  
  435. /****************************************************************************/
  436. /* domouse  - handle mouse down events for different windows. */
  437. /****************************************************************************/
  438. char
  439. domouse (evt, mini)
  440. EventRecord *evt;
  441.     int mini;                /* TRUE if miniparser */
  442. {
  443.     char state = 0;
  444.     WindowPtr window;
  445.     int evtwcode;
  446.     struct cmdw *cmdw;
  447.  
  448.     evtwcode = FindWindow (evt->where, &window);
  449.  
  450.     switch (evtwcode) {        /* Tell us where */
  451.       case inMenuBar:        /* Looking at the menus? */
  452.     if (mini)
  453.         break;
  454.     updateCursor(ttermw, 1, NIL); /* (UoR) mouse cursor off */
  455.     state = menu_event (MenuSelect (evt->where));
  456.     break;            /* All done */
  457.  
  458.       case inSysWindow:    /* Looking at system, like */
  459.     SystemClick (evt, window);    /* a desk accessary */
  460.     break;            /* Let the system handle it */
  461.  
  462.       case inContent:
  463.     if (window != FrontWindow ()) {
  464.         if (cmdw = cmdwbywindow(window))
  465.         cmdwSelectWindow(cmdw);
  466.         else
  467.         kSelectWindow (window);    /* make window current */
  468.     } else if (window == ttermw->window)
  469.         termmouse (ttermw, evt);
  470.     else if (cmdw = cmdwbywindow(window))
  471.         rcdmouse (cmdw, evt);
  472.     else if (window == ctermw->window)
  473.         termmouse(ctermw, evt);
  474.     break;
  475.  
  476.       case inDrag:        /* Wanna drag? */
  477.     kSelectWindow(window);
  478.     DragWindow (window, evt->where, &qd.screenBits.bounds);
  479.     break;
  480.  
  481.       case inGoAway:
  482.     if (cmdw = cmdwbywindow(window)) {
  483.         if (TrackGoAway (cmdw->window, evt->where)) {
  484.         closecmdw(cmdw);
  485.         /* !!!!!!!!!! if was a file window, destroy it */
  486.         }
  487.     } else if (window == ctermw->window) {
  488.         if (TrackGoAway (ctermw->window, evt->where))
  489.         closetermw(ctermw);
  490.     } else if (window == ttermw->window) {
  491.         if (TrackGoAway (ttermw->window, evt->where))
  492.         closetermw(ttermw);
  493.     }
  494.     break;
  495.  
  496.       case inGrow:
  497.     if (window != FrontWindow ()) {
  498.         if (cmdw = cmdwbywindow(window))
  499.         cmdwSelectWindow(cmdw);
  500.         else
  501.         kSelectWindow (window);    /* make window current */
  502.     } else if (window == ttermw->window)
  503.         growterm(ttermw, &evt->where);
  504.     else if (cmdw = cmdwbywindow(window))
  505.         growremwindow(cmdw, evt->where);
  506.     else if (window == ctermw->window)
  507.         growterm(ctermw, &evt->where);
  508.     break;
  509.     }
  510.     
  511.     ttermw->last_flash = TickCount ();    /* reset timer for flashes */
  512.     return (state);            /* return with new state or 0 */
  513. }                /* domouse */
  514.  
  515.  
  516.  
  517. /****************************************************************************/
  518. /* doupdate - handle update event on different windows, dispatch to */
  519. /*              redraw routines */
  520. /****************************************************************************/
  521. doupdate (window)
  522. WindowPtr window;
  523. {
  524.     GrafPtr savePort;
  525.     struct cmdw *cmdw;
  526.  
  527.     GetPort (&savePort);
  528.     SetPort (window);
  529.     BeginUpdate (window);
  530.  
  531.     if (window == ttermw->window) {
  532.     term_redraw(ttermw);        /* terminal window */
  533.     } else if (cmdw = cmdwbywindow(window)) {
  534.     rcdupdate (cmdw);        /* Redraw  window */
  535.     } else if (window == ctermw->window) {
  536.     term_redraw(ctermw);
  537.     }
  538.  
  539.     EndUpdate (window);
  540.     SetPort (savePort);
  541. }                /* doupdate */
  542.  
  543.  
  544.  
  545. #define NNN 20                /* for debugging */
  546. static WindowPtr wqueue[NNN];
  547. static int mqueue[NNN];
  548. static int qindex = 0;
  549.  
  550. /****************************************************************************/
  551. /* doactivate - activate a window */
  552. /****************************************************************************/
  553. doactivate (window, mod)
  554. WindowPtr window;
  555. int mod;
  556. { /* doactivate */
  557.     GrafPtr savePort;
  558.     struct cmdw *cmdw;
  559.  
  560. /*
  561.   The following if () {...} wrapper added by fdc at the suggestion of Edward
  562.   Huff, NYU Medical Center, to fix the problem in which Mac Kermit crashes if
  563.   all its windows are closed, and then it is selected from the application
  564.   menu of another application.
  565. */
  566.     if (window != (WindowPtr)0) {
  567.  
  568.     GetPort (&savePort);
  569.     SetPort (window);
  570.  
  571.     /*  Save last action in circular queue for debugging. */
  572.  
  573.     wqueue[qindex] = window;
  574.     mqueue[qindex] = mod;
  575.     if (++qindex == NNN)
  576.       qindex = 0;
  577.  
  578.     HiliteWindow (window, ((mod & activeFlag) != 0));
  579.     if (!(mod & activeFlag))
  580.       activecmdw = NULL;
  581.     if (cmdw = cmdwbywindow(window))
  582.       rcdactivate (cmdw, mod);
  583.     else if (window == ctermw->window) {
  584.         term_activate(ctermw, mod);
  585.         updateCursor(ctermw, 1, (WindowPeek) ctermw->window);
  586.     } else if (window == ttermw->window) {
  587.         term_activate(ttermw, mod);
  588.         updateCursor(ttermw, 1, (WindowPeek) ttermw->window);
  589.     }
  590.  
  591. #ifdef COMMENT
  592.     if (!EmptyRgn(((WindowPeek)terminalWindow)->updateRgn))
  593.       doupdate (terminalWindow);    /* Fake an update event */
  594. #endif
  595.  
  596.     SetPort (savePort);
  597.     }
  598. }                    /* doactivate */
  599.  
  600. show_queue ()
  601. {
  602.     int i;
  603.  
  604.     i = qindex + 1;
  605.     while (i != qindex) {
  606.     if (i >= NNN)
  607.         i = 0;
  608.     printf("%3d: window=0x%x mod=0x%x\n", i, wqueue[i], mqueue[i]);
  609.     
  610.     i++;
  611.     }
  612. }
  613.  
  614. char genstr[100];
  615.  
  616. /****************************************************************************/
  617. /****************************************************************************/
  618. char menu_event (menu_item)
  619.     long menu_item;
  620. {
  621.     int r;
  622.     Boolean saveas = FALSE;
  623.     short menu = HiWord (menu_item);    /* decompose arg */
  624.     short item = LoWord (menu_item);
  625.     char state = '\0';
  626.     int remotedialog ();    /* returns boolean */
  627.     WindowPtr window;
  628.     struct cmdw *cmdw;
  629.     struct termw *termw;
  630.     char scratch[255];
  631.  
  632.     switch (menu) {
  633.       case APPL_MENU:        /* Mac system menu item */
  634.     handapple (item);
  635.     break;            /* all done */
  636.  
  637.       case FILE_MENU:
  638.       case FILE_MEN2:
  639.     switch (item) {        /* Find out which was selected */
  640.       case QUIT_FIL:    /* Want to quit program? */
  641.         doexit(GOOD_EXIT,-1);        /* should never return */
  642.         macfatal("menu_event: doexit didn't exit", 0);
  643.  
  644.  
  645.       case XFER_FIL:
  646.         handlelaunch ();    /* Handle x-fer to application */
  647.         break;
  648.  
  649.       case SAVE_FIL:    /* save settings */
  650.         savevals();
  651.         break;
  652.  
  653.       case LOAD_FIL:    /* load settings */
  654.         loadvals ();
  655.         HiliteMenu (0);    /* Done doing menu, so un-hilite */
  656.         return 'n';        /* null command to force parser return */
  657.  
  658.       case PGSTUP_FIL:    /* Page Setup... */
  659.         dopagesetup();
  660.         break;
  661.  
  662.       case PRINT_FIL:    /* Print... */
  663.         doprinter(FrontWindow());
  664.         break;
  665.  
  666.       case PBUF_FIL:    /* Print the Buffer */
  667.         now_print();
  668.         break;
  669.         
  670.       case PSTAT_FIL:    /* Print Buffer Status Dialog Box */
  671.         pr_stat();
  672.         break;
  673.  
  674. #ifdef COMMENT
  675.       case PDISC_FIL:    /* Discard the Print Buffer */
  676.         if (hPrintBuffer)
  677.         DisposHandle(hPrintBuffer);
  678.         hPrintBuffer = 0L;
  679.         lPrintBufferChars = 0L;
  680.         updatepstat();
  681.         break;
  682.  
  683.       case POPEN_FIL:       /* Open Captured Text */
  684.         if (hPrintBuffer && lPrintBufferChars) {
  685.         newfile(hPrintBuffer, lPrintBufferChars);
  686.         lPrintBufferChars = lPrintBufferAt = 0L; /* flush buffer */
  687.         updatepstat();
  688.         } else
  689.         SysBeep(3);
  690.         break;
  691. #endif /* COMMENT */
  692.  
  693.       case TAKE_FIL:    /* Take Command File... */
  694.         takedialog();
  695.         HiliteMenu (0);    /* Done doing menu, so un-hilite */
  696.         return 'n';        /* null command to force parser return */
  697.  
  698.       case TAKEW_FIL:    /* Take Command from Window */
  699.         if ((cmdw = cmdwbywindow(FrontWindow())) == NULL) {
  700.         SysBeep(3);
  701.         break;
  702.         }
  703.         if ((cmdw->flags & CMDWF_FOPEN) || (!(cmdw->flags & CMDWF_FILE))) {
  704.         SysBeep(3);
  705.         break;
  706.         }
  707.         sprintf(scratch, "%%%%%%%d", cmdw->id);
  708.         kShowWindow(ctermw);    /* force command window */
  709.         kSelectWindow(ctermw->window);
  710.         getlfile(scratch, 0);    /* queue the take file */
  711.         HiliteMenu (0);        /* Done doing menu, so un-hilite */
  712.         return 'n';              /* null command to force parser return */
  713.  
  714.       case NEW_FIL:
  715.         newfile(0L, 0);
  716.         break;
  717.  
  718.       case OPEN_FIL:
  719.         openfile();
  720.         break;
  721.  
  722.       case CLOSE_FIL:
  723.         if (cmdw = cmdwbywindow(FrontWindow())) {
  724.         closecmdw(cmdw);
  725.             /* !!!!! Need to destroy window, unlink and free cmdw, etc */
  726.         } else if (termw = termwbywindow(FrontWindow()))
  727.         closetermw(termw);
  728.         break;
  729.         
  730.       case SAVEAS_FIL:
  731.         saveas = TRUE;
  732.       case SAVEF_FIL:
  733.         if (cmdw = cmdwbywindow(FrontWindow())) {
  734.         if (cmdw->flags & CMDWF_FILE) {
  735.             savefile(cmdw, saveas);
  736.             break;
  737.         }
  738.         }
  739.         SysBeep(1);
  740.         break;
  741.     }
  742.     break;
  743.  
  744.       case EDIT_MENU:        /* PWP: good for DA editors */
  745.       case EDIT_MEN2:        /* PWP: good for DA editors */
  746.         window = FrontWindow();    /* we do different things based on this */
  747.     
  748.         switch(item) {
  749.       case UNDO_EDIT:    /* undo */
  750.         if (window == ttermw->window) {
  751.         SysBeep(3);
  752.         } else if (cmdw = cmdwbywindow(window)) {
  753.         SysBeep (3);
  754.         } else if (window == ctermw->window) {
  755.         SysBeep (3);
  756.         } else {
  757.         if (!SystemEdit (item - 1))
  758.             SysBeep (3);
  759.         }
  760.         break;
  761.  
  762.       case CUT_EDIT:    /* cut */
  763.         if (window == ttermw->window) {
  764.         scr_copy(ttermw);
  765.         } else if (cmdw = cmdwbywindow(window)) {
  766.         rcd_cut(cmdw);
  767.         cmdw->flags |= CMDWF_MODIFIED;
  768.         } else if (window == ctermw->window) {
  769.         scr_copy(ctermw);
  770.         } else {
  771.         if (!SystemEdit (item - 1))
  772.             SysBeep (3);
  773.         }
  774.         break;
  775.  
  776.       case COPY_EDIT:    /* copy */
  777.         if (window == ttermw->window) {
  778.         scr_copy(ttermw);
  779.         } else if (cmdw = cmdwbywindow(window)) {
  780.         rcd_copy(cmdw);
  781.         } else if (window == ctermw->window) {
  782.         scr_copy(ctermw);
  783.         } else {
  784.         if (!SystemEdit (item - 1))
  785.             SysBeep (3);
  786.         }
  787.         break;
  788.  
  789.       case PASTE_EDIT:    /* paste */
  790.         if (window == ttermw->window) {
  791.         scr_paste(ttermw);
  792.         } else if (cmdw = cmdwbywindow(window)) {
  793.         rcd_paste(cmdw);
  794.         cmdw->flags |= CMDWF_MODIFIED;
  795.         } else if (window == ctermw->window) {
  796.         cmd_paste(ttermw);
  797.         state = 'p';        /* wake up getchar() */
  798.         } else {
  799.         if (!SystemEdit (item - 1))
  800.             SysBeep (3);
  801.         }
  802.         break;
  803.  
  804.       case CLEAR_EDIT:    /* clear */
  805.         if (window == ttermw->window) {
  806.         SysBeep(3);
  807.         } else if (cmdw = cmdwbywindow(window)) {
  808.         rcd_clear(cmdw);
  809.         cmdw->flags |= CMDWF_MODIFIED;
  810.         } else if (window == ctermw->window) {
  811.         SysBeep(3);
  812.         } else {
  813.         if (!SystemEdit (item - 1))
  814.             SysBeep (3);
  815.         }
  816.         break;
  817.       
  818.     }
  819.     break;
  820.  
  821.       case SETG_MENU:
  822.       case SETG_MEN2:
  823.     switch (item) {
  824.       case PROT_SETG:
  825.         protodialog ();
  826.         break;
  827.  
  828.       case COMM_SETG:
  829.         commdialog ();    /* communications dialog */
  830.         break;
  831.  
  832.       case FILE_SETG:
  833.         setfiledialog ();    /* do default file settings */
  834.         break;
  835.  
  836.       case TERM_SETG:    /* do terminal emulation settings */
  837.         termsetdialog (ttermw);
  838.         break;
  839.  
  840.       case CHARS_SETG:    /* do terminal emulation settings */
  841.         charsetdialog (ttermw);
  842.         break;
  843.  
  844.       case SCRD_SETG:    /* fkeys  active / not active */
  845.         CheckItem (menus[SETG_MENU], SCRD_SETG,
  846.                (fkeysactive = !fkeysactive));
  847.         enable_fkeys (fkeysactive);
  848.         break;
  849.  
  850.       case MCDM_SETG:    /* menu command keys active / not active */
  851.         CheckItem (menus[SETG_MENU], MCDM_SETG,
  852.                (mcmdactive = !mcmdactive));
  853.         setup_menus();        /* redo menus */
  854.         redo_window_menu();        /* reenter dynamic window menu entries */
  855.         break;
  856.  
  857.       case KEYM_SETG:
  858.         keymacros ();
  859.         break;
  860.  
  861.       case MODF_SETG:
  862.         keymoddialog ();
  863.         break;
  864.     }
  865.     break;
  866.  
  867.     /*
  868.      * return either 'g' for generic or 'c' for host with cmarg holding
  869.      * cmd
  870.      */
  871.  
  872.       case REMO_MENU:
  873.       case REMO_MEN2:
  874.     cmarg = genstr;            /* indicate cmd ok to proceed */
  875.     switch (item) {
  876.       case SEND_REMO:        /* send a file: local, remote files */
  877.         if (!dosenddialog (&cmarg, &cmarg2))
  878.           break;
  879.         r = zxpand(cmarg);    /* must call this now since sinit() doesn't */
  880.         if (r <= 0)
  881.           printerr("zxpand returned ", r);
  882.         nfils = -1;            /* Use cmarg, not cmlist */
  883.         state = 's';        /* return with send state */
  884.         protocmd = item;
  885.         what = W_SEND;
  886.         scrcreate ();        /* create the status screen */
  887.         break;
  888.  
  889.       case RECV_REMO:        /* Ask for recv info -- */
  890.         initfilrecv ();        /* init recv flags */
  891.         state = 'v';        /* return with recv state */
  892.         protocmd = item;
  893.         what = W_RECV;
  894.         scrcreate ();        /* create the status screen */
  895.         break;
  896.  
  897.       case GETS_REMO:        /* Get from server */
  898.         if (dogetfdialog (&cmarg)) {
  899.         state = 'r';        /* Say we want to get */
  900.         protocmd = item;
  901.         what = W_RECV;
  902.         scrcreate ();        /* create the status screen */
  903.         }
  904.         break;
  905.         
  906.       case STATS_REMO:        /* show transfer stats */
  907.         show_stats();
  908.         cmarg = NILPTR;
  909.         break;
  910.         
  911.       case LCD_REMO:        /* set transfer directory */
  912.         set_cwd();
  913.         cmarg = NILPTR;
  914.         break;
  915.  
  916.       case FIN_REMO:
  917.         state = 'g';
  918.         protocmd = -1;        /* hey we're going to protocol! */
  919.         what = W_REMO;
  920.         ssetgen (genstr, 'F', "", "", "");    /* Finish */
  921.         break;
  922.  
  923.       case BYE_REMO:
  924.         state = 'g';
  925.         protocmd = -1;        /* Ditto.. */
  926.         what = W_REMO;
  927.         ssetgen (genstr, 'L', "", "", "");    /* Bye, logout */
  928.         break;
  929.  
  930.       case SERV_REMO:
  931.         displa = 1;
  932.         what = W_RECV;
  933.         protocmd = item;
  934.         scrcreate ();        /* Create the status screen */
  935.         return ('x');
  936.  
  937.       default:
  938.         if (!remotedialog (item, genstr))
  939.         cmarg = NILPTR;        /* cancel issued, prevent it */
  940.         else {
  941.         protocmd = -1;        /* hey we're going to protocol! */
  942.         what = W_REMO;
  943.         if (item == HOST_REMO)
  944.           state = 'c';        /* REMOTE HOST */
  945.         else
  946.           state = 'g';        /* REMOTE other */
  947.         }
  948.         break;
  949.     } /* switch item */
  950.     if (protocmd) {
  951.         lastCursor = 0L;
  952.         SetCursor(watchcurs);
  953.     }
  954.     break;
  955.     
  956.       case WIND_MENU:
  957.       case WIND_MENU2:
  958.     cmarg = genstr;            /* indicate cmd ok to proceed */
  959.     switch (item) {
  960.       case TERM_WIND:        /* Show terminal window */
  961.         kShowWindow(ttermw);
  962.         kSelectWindow(ttermw->window); /* make window current */
  963.         cmarg = NILPTR;        /* Don't do anything else */
  964.         break;
  965.  
  966.       case CMDW_WIND:        /* Show command window */
  967.         kShowWindow(ctermw);
  968.         kSelectWindow(ctermw->window);
  969.         cmarg = NILPTR;        /* Don't do anything else */
  970.         break;
  971.  
  972.       case RESP_WIND:
  973.         rcmdwshow(rcmdw);
  974.         cmarg = NILPTR;        /* Don't do anything else */
  975.         break;
  976.  
  977.       case PRNT_WIND:
  978.         rcmdwshow(prntw);
  979.         cmarg = NILPTR;        /* Don't do anything else */
  980.         break;
  981.  
  982.       default:
  983.         for (cmdw = cmdwl; cmdw; cmdw = cmdw->next) {
  984.         if (item == cmdw->menuitem) {
  985.             cmdwSelectWindow(cmdw);
  986.             break;
  987.         }
  988.         }
  989.         break;
  990.     }
  991.     break;
  992.     
  993.       case LOG_MENU:
  994.       case LOG_MEN2:
  995.     switch(item) {
  996.       case SLOG_LOG:        /* session logging */
  997.         if (seslog) {
  998.             scrlasttolog(ttermw);    /* save the last line on the screen */
  999.         closeslog ();
  1000.         seslog = 0;
  1001.         } else {
  1002.         seslog = openslog ();
  1003.         scrtolog(ttermw);   /* if the file is open, just do the dump */
  1004.         }
  1005.         CheckItem (menus[LOG_MENU], SLOG_LOG, seslog);
  1006.         if (seslog) {
  1007.             EnableItem(menus[LOG_MENU], SDMP_LOG);
  1008.         } else {
  1009.             DisableItem(menus[LOG_MENU], SDMP_LOG);
  1010.         }
  1011.         break;
  1012.  
  1013.       case SDMP_LOG:        /* dump screen to session log */
  1014.         if (seslog)    {        /* session logging active? */
  1015.         scrtolog(ttermw);   /* if the file is open, just do the dump */
  1016.         } else {
  1017.         SysBeep(3);    /* can't dump screen without a log file. */
  1018.             DisableItem(menus[LOG_MENU], SDMP_LOG);
  1019.         }
  1020.         break;
  1021.  
  1022.       case TLOG_LOG:        /* transaction logging */
  1023.         if (tralog) {
  1024.         closetlog ();
  1025.         tralog = 0;
  1026.         } else {
  1027.         tralog = opentlog ();
  1028.         }
  1029.         CheckItem (menus[LOG_MENU], TLOG_LOG, tralog);
  1030.         break;
  1031.  
  1032.       case PLOG_LOG:        /* packet logging */
  1033.         if (pktlog) {
  1034.         closetlog ();
  1035.         pktlog = 0;
  1036.         } else {
  1037.         pktlog = openplog ();
  1038.         }
  1039.         CheckItem (menus[LOG_MENU], PLOG_LOG, pktlog);
  1040.         break;
  1041.  
  1042.       case DLOG_LOG:        /* log debugging */
  1043.         if (deblog) {
  1044.         (void) closedlog ();
  1045.         deblog = 0;
  1046.         } else {
  1047.         deblog = opendlog ();
  1048.         rcmdwshow (rcmdw);    /* display the remote cmd window */
  1049.         /* Debugger(); */
  1050.         }
  1051.         CheckItem (menus[LOG_MENU], DLOG_LOG, deblog);
  1052.         break;
  1053.  
  1054.       case DBGR_LOG:        /* call debugger */
  1055.         Debugger();
  1056.         break;
  1057.  
  1058.     }
  1059.     break;
  1060.  
  1061.     case FONT_MENU:
  1062.     if (item <= BIGSZ_FONT) {    /* handle a font size request */
  1063.         change_current_size (ttermw, item);
  1064.     } else {        /* handle a font request */
  1065.         change_current_font(ttermw,item);
  1066.     }
  1067.     setup_font_menu();    /* update font and sizes */
  1068.     break;
  1069.  
  1070.     case SPCL_MENU:            /* Special */
  1071.     case SPCL_MENU2:
  1072.         window = FrontWindow();    /* we do different things based on this */
  1073.     switch (item) {
  1074.       case BREAK_SPCL:        /* send break */
  1075.         if (window == ttermw->window)
  1076.         sendbreak(5);
  1077.         else
  1078.         SysBeep(3);
  1079.         break;
  1080.  
  1081.       case LBREAK_SPCL:        /* send break */
  1082.         if (window == ttermw->window)
  1083.         sendbreak(70);
  1084.         else
  1085.         SysBeep(3);
  1086.         break;
  1087.  
  1088.       case XON_SPCL:        /* send XON */
  1089.         if (window == ttermw->window)
  1090.         do_xon();
  1091.         else
  1092.         SysBeep(3);
  1093.         break;
  1094.  
  1095.       case DTR_SPCL:        /* toggle DTR */
  1096.         if (window == ttermw->window)
  1097.         toggle_dtr(70);
  1098.         else
  1099.         SysBeep(3);
  1100.         break;
  1101.  
  1102.       case RESET_SPCL:    /* Reset terminal */
  1103.         if (window == ttermw->window)
  1104.         term_reset(ttermw);    /* reset the terminal emulator */
  1105.         else
  1106.         SysBeep(3);
  1107.         break;
  1108.     }
  1109.     break;
  1110.     }
  1111.  
  1112.     HiliteMenu (0);            /* Done doing menu, so un-hilite */
  1113.  
  1114.     return (state);            /* Don't go into Kermit protocol */
  1115. }                /* menu_event */
  1116.  
  1117. #ifdef COMMENT
  1118. /****************************************************************************/
  1119. /* herald() prints out the version number (but we arn't on a TTY, so don't) */
  1120. /****************************************************************************/
  1121. VOID herald ()
  1122. {
  1123. }                /* herald */
  1124. #endif /* COMMENT */
  1125.  
  1126.  
  1127. /****************************************************************************/
  1128. /****************************************************************************/
  1129. /*
  1130.  * conect
  1131.  * This MAC routine duplicates a routine in ckucon.c
  1132.  */
  1133. conect ()
  1134. {
  1135.     connected = 1;            /* put mac into connected mode */
  1136.     sstate = 'c';
  1137.     if (ttermw->window != FrontWindow()) {
  1138.     kShowWindow(ttermw);
  1139.     kSelectWindow(ttermw->window);
  1140.     }
  1141.     return 0;
  1142. }
  1143.  
  1144.  
  1145. /****************************************************************************/
  1146. /****************************************************************************/
  1147. cmdlin ()
  1148. {
  1149.     return (0);            /* nothing parsed */
  1150. }                /* cmdlin */
  1151.  
  1152.  
  1153.  
  1154. /****************************************************************************/
  1155. /****************************************************************************/
  1156. chkint ()
  1157. {
  1158. }                /* chkint */
  1159.  
  1160. /****************************************************************************/
  1161. #ifdef DEBUG
  1162. /*  D E B U G  --  Enter a record in the debugging log  */
  1163.  
  1164. /*
  1165.  Call with a format, two strings, and a number:
  1166.    f  - Format, a bit string in range 0-7.
  1167.         If bit x is on, then argument number x is printed.
  1168.    s1 - String, argument number 1.  If selected, printed as is.
  1169.    s2 - String, argument number 2.  If selected, printed in brackets.
  1170.    n  - Int, argument 3.  If selected, printed preceded by equals sign.
  1171.  
  1172.    f=0 is special: print s1,s2, and interpret n as a char.
  1173. */
  1174. #define DBUFL 2300
  1175. int
  1176. dodebug(f,s1,s2,n) int f; char *s1, *s2; long n; {
  1177.     static char *s = 0;
  1178.     char *sp;
  1179.  
  1180.     /*
  1181.      * Allocate s if not done already
  1182.      */
  1183.     if (!s && !(s = malloc(DBUFL)))
  1184.     macfatal("dodebug: no room for s", 0);
  1185.     sp = s;
  1186.  
  1187.     if (!deblog) return (0);        /* If no debug log, don't */
  1188.     switch (f) {
  1189.         case F000:            /* 0, print both strings, */
  1190.         if (strlen(s1) + strlen(s2) + 5 > DBUFL) { /* and n as a char */
  1191.         sprintf(sp,"DEBUG string too long\n");
  1192.         } else {
  1193.         if (n > 31 && n < 127)
  1194.           sprintf(sp,"%s%s:%c\n",s1,s2,n);
  1195.         else if (n < 32 || n == 127)
  1196.           sprintf(sp,"%s%s:^%c\n",s1,s2,(n+64) & 0x7F);
  1197.         else if (n > 127 && n < 160)
  1198.           sprintf(sp,"%s%s:~^%c\n",s1,s2,(n-64) & 0x7F);
  1199.         else if (n > 159 && n < 256)
  1200.           sprintf(sp,"%s%s:~%c\n",s1,s2,n & 0x7F);
  1201.         else sprintf(sp,"%s%s:%d\n",s1,s2,n);
  1202.         }
  1203.         if (zsout(ZDFILE,s) < 0) deblog = 0;
  1204.         break;
  1205.         case F001:            /* 1, "=n" */
  1206.         sprintf(sp,"=%d\n",n);
  1207.         if (zsout(ZDFILE,s) < 0) deblog = 0;
  1208.         break;
  1209.         case F010:            /* 2, "[s2]" */
  1210.         if (strlen(s2) + 4 > DBUFL)
  1211.           sprintf(sp,"DEBUG string too long\n");
  1212.         else sprintf(sp,"[%s]\n",s2);
  1213.         if (zsout(ZDFILE,"") < 0) deblog = 0;
  1214.         break;
  1215.         case F011:            /* 3, "[s2]=n" */
  1216.         if (strlen(s2) + 15 > DBUFL)
  1217.           sprintf(sp,"DEBUG string too long\n");
  1218.         else sprintf(sp,"[%s]=%d\n",s2,n);
  1219.         if (zsout(ZDFILE,s) < 0) deblog = 0;
  1220.         break;
  1221.         case F100:            /* 4, "s1" */
  1222.         if (zsoutl(ZDFILE,s1) < 0) deblog = 0;
  1223.         break;
  1224.         case F101:            /* 5, "s1=n" */
  1225.         if (strlen(s1) + 15 > DBUFL)
  1226.           sprintf(sp,"DEBUG string too long\n");
  1227.         else sprintf(sp,"%s=%d\n",s1,n);
  1228.         if (zsout(ZDFILE,s) < 0) deblog = 0;
  1229.         break;
  1230.         case F110:            /* 6, "s1[s2]" */
  1231.         if (strlen(s1) + strlen(s2) + 4 > DBUFL)
  1232.           sprintf(sp,"DEBUG string too long\n");
  1233.         else sprintf(sp,"%s[%s]\n",s1,s2);
  1234.         if (zsout(ZDFILE,s) < 0) deblog = 0;
  1235.         break;
  1236.         case F111:            /* 7, "s1[s2]=n" */
  1237.         if (strlen(s1) + strlen(s2) + 15 > DBUFL)
  1238.           sprintf(sp,"DEBUG string too long\n");
  1239.         else sprintf(sp,"%s[%s]=%d\n",s1,s2,n);
  1240.         if (zsout(ZDFILE,s) < 0) deblog = 0;
  1241.         break;
  1242.     default:
  1243.         sprintf(sp,"\n?Invalid format for debug() - %d\n",n);
  1244.         if (zsout(ZDFILE,s) < 0) deblog = 0;
  1245.     }
  1246.     return (0);
  1247. }
  1248. #endif
  1249.  
  1250.  
  1251.  
  1252. /****************************************************************************/
  1253. /* sleep - called during protocol for a dismiss.  Keep machine running */
  1254. /*           with calls to the miniparser during this period. */
  1255. /****************************************************************************/
  1256. sleep (secs)
  1257. {
  1258.     long finalticks;        /* tickscount for exit */
  1259.  
  1260.     finalticks = TickCount () + (60 * secs);    /* TickCount for exit  */
  1261.     while (finalticks > TickCount ()) {    /* keep the machine running by */
  1262.     miniparser (TRUE);    /* deplete the Q */
  1263.     if (sstate == 'a')    /* if in abort state, forget */
  1264.         return;        /* this wait */
  1265.     }
  1266. }                /* sleep */
  1267.  
  1268.  
  1269.  
  1270. /****************************************************************************/
  1271. /****************************************************************************/
  1272. VOID ermsg (msg)            /* Print error message */
  1273. char *msg;
  1274. {
  1275.     screen (SCR_EM, 0, 0l, msg);/* Put the error on the screen */
  1276.     tlog (F110, "Error -", msg, 0l);
  1277. }                /* ermsg */
  1278.  
  1279.  
  1280.  
  1281. /****************************************************************************/
  1282. /****************************************************************************/
  1283. VOID intmsg (n)
  1284. long n;
  1285. #pragma unused (n)
  1286. {
  1287.     return;
  1288. }                /* intmsg */
  1289.  
  1290.  
  1291. /*
  1292.  * Insert buffer into window, processing characters.
  1293.  */
  1294. void
  1295. insertbuf (char *buf, int len, TEHandle teh, int *eol)
  1296. {
  1297.     int n;
  1298.     char *cp, *cp2;
  1299.     static char cr[1] = { 0x0d };
  1300.  
  1301.     cp = cp2 = buf;
  1302.     while (cp < buf+len) {
  1303.     switch (*cp) {
  1304.     case 0x0a:            /* linefeed */
  1305.     case 0x0d:            /* return */
  1306.         if (n = (cp - cp2)) {        /* flush buffer */
  1307.         TEInsert(cp2, n, teh);
  1308.         }
  1309.         cp++;            /* skip char */
  1310.         cp2 = cp;
  1311.         *eol = 1;
  1312.         break;
  1313.  
  1314.     default:
  1315.         if (*eol) {
  1316.             *eol = 0;
  1317.             TEInsert(cr, 1, teh);
  1318.         }
  1319.         cp++;
  1320.         break;
  1321.     }
  1322.     }
  1323.     if (n = (cp - cp2)) {            /* flush end of buffer */
  1324.     TEInsert(cp2, n, teh);
  1325.     }
  1326. }
  1327.  
  1328.  
  1329. /*
  1330.  * openfile
  1331.  * Open an existing TEXT file.
  1332.  */
  1333. void
  1334. openfile ()
  1335. {
  1336.     SFReply savr;
  1337.     Point where;
  1338.     struct cmdw *cmdw = NULL, *tmp;
  1339.     int err;
  1340.     short refNum;
  1341.     long len;
  1342.     char buf[1024];
  1343.     int eol = 0;
  1344.  
  1345.     SetPt (&where, 75, 115);
  1346.     SFGetFile (where, "\pOpen:", (FileFilterProcPtr) NILPROC,
  1347.                1, &texttype, (DlgHookProcPtr) NILPROC, &savr);
  1348.  
  1349.     if (!savr.good)        /* did they hit cancel? */
  1350.     return;            /* yes, so return now */
  1351.  
  1352.     /*
  1353.      * Loop checking to see if this file is already open.  If it
  1354.      * is, just pop up the window.
  1355.      */
  1356.     for (tmp = cmdwl; tmp; tmp = tmp->next) {
  1357.     if ((tmp->vRefNum == savr.vRefNum) && 
  1358.         (strcmp(p2c_tmp(savr.fName), p2c_tmp2((StringPtr) tmp->fName)) == 0)) {
  1359.         cmdwSelectWindow(tmp);
  1360.         return;
  1361.     }
  1362.     }
  1363.  
  1364.     err = FSOpen(savr.fName, savr.vRefNum, &refNum);
  1365.     if (err != noErr) {
  1366.     printfalert("Could not open %s: %d", p2c_tmp(savr.fName), err);
  1367.     return;
  1368.     }
  1369.  
  1370.     /*
  1371.      * Build the window.
  1372.      */
  1373.     cmdw = initcmdw(RCMDBOXID, RCMDVSCROLL, RCMDHSCROLL);
  1374.     cmdw->refNum = refNum;
  1375.     cmdw->vRefNum = savr.vRefNum;    /* save file stuff */
  1376.     cmdw->fName = malloc_pstring(savr.fName);
  1377.     cmdw->flags |= CMDWF_FILE;
  1378.     setwname(cmdw, savr.fName);
  1379.  
  1380.     /*
  1381.      * Read in the file.
  1382.      */
  1383.     for (;;) {
  1384.     len = sizeof(buf);
  1385.     err = FSRead(refNum, &len, buf);
  1386.     if ((err == eofErr) && (len == 0))
  1387.         break;
  1388.     if ((err != noErr) && (err != eofErr)) {
  1389.         printfalert("Error reading file: %d", err);
  1390.         /* !!!! DESTROY THINGS HERE !!!!!!!!!! */
  1391.         return;
  1392.     }
  1393.     
  1394.     /* !!!!! make sure we don't overflow the TE record ? !!!!!!!!! */
  1395.  
  1396.     insertbuf(buf, len, cmdw->teh, &eol);
  1397.     }
  1398.     TESetSelect(0L, 0L, cmdw->teh);    /* select beginning */
  1399.     setscrollmax(cmdw);            /* set the max */
  1400.     rcmdwshow(cmdw);
  1401. }
  1402.  
  1403.  
  1404. /*
  1405.  * newfile
  1406.  * Create a new window either empty or given a handle to text.
  1407.  */
  1408. static void
  1409. newfile (Handle h, int len)
  1410. {
  1411.     char scratch[255];
  1412.     struct cmdw *cmdw;
  1413.  
  1414.     cmdw = initcmdw(RCMDBOXID, RCMDVSCROLL, RCMDHSCROLL);
  1415.     cmdw->flags |= CMDWF_FILE;
  1416.     sprintf(scratch, "Untitled-%d", titlen++);
  1417.     c2pstr(scratch);
  1418.     setwname(cmdw, (StringPtr) scratch);
  1419.  
  1420.     if (h) {
  1421.     TEInsert((Ptr)*h, len, cmdw->teh);
  1422.     TESetSelect(0L, 0L, cmdw->teh);    /* select beginning */
  1423.     setscrollmax(cmdw);        /* set the max */
  1424.     cmdw->flags |= CMDWF_MODIFIED;
  1425.     }
  1426.  
  1427.     rcmdwshow(cmdw);
  1428. }
  1429.  
  1430.  
  1431. /*
  1432.  * closefile
  1433.  * Close a file associated with a cmdw.
  1434.  */
  1435. closefile (struct cmdw *cmdw)
  1436. {
  1437.     int err;
  1438.  
  1439.     if (!(cmdw->flags & CMDWF_FILE))
  1440.     return;
  1441.  
  1442.     if (cmdw->refNum == 0)
  1443.     return;
  1444.  
  1445.     err = FSClose((short) cmdw->refNum);
  1446.     if (err != noErr)
  1447.     printfalert("Error closing: %d", err);
  1448.     cmdw->refNum = 0;
  1449. }
  1450.  
  1451.  
  1452. /*
  1453.  * closecmdw
  1454.  * Close a window associated with a cmdw.
  1455.  */
  1456. void closecmdw (struct cmdw *cmdw)
  1457. {
  1458.     struct cmdw *tmp;
  1459.  
  1460.     if (!checksave(cmdw))
  1461.     return;
  1462.  
  1463.     /*
  1464.      * Delete windows menu item, adjust item numbers for
  1465.      * rest of items in the menu.
  1466.      */
  1467.     if (cmdw->menuitem) {
  1468.     DelMenuItem(menus[WIND_MENU], cmdw->menuitem);
  1469.  
  1470.     for (tmp = cmdwl; tmp; tmp = tmp->next)
  1471.         if (tmp->menuitem > cmdw->menuitem)
  1472.         tmp->menuitem--;
  1473.     }
  1474.     cmdw->menuitem = 0;
  1475.  
  1476.     closefile(cmdw);
  1477.  
  1478.     if (!(cmdw->flags & CMDWF_FILE)) {    /* If not a file window (prob rcmdw) */
  1479.     rcmdwhide(cmdw);
  1480.     return;
  1481.     }
  1482.  
  1483.     /*
  1484.      * Unlink and Destroy the cmdw.
  1485.      */
  1486.     if (cmdwl == cmdw) {
  1487.     cmdwl = cmdw->next;
  1488.     } else {
  1489.     for (tmp = cmdwl; tmp; tmp = tmp->next) {
  1490.         if (tmp->next == cmdw) {
  1491.         tmp->next = cmdw->next;
  1492.         break;
  1493.         }
  1494.     }
  1495.     if (tmp == NULL) {
  1496.         printfalert("closecmdw: cmdw not in list");
  1497.         return;
  1498.     }
  1499.     }
  1500.     if (cmdw == activecmdw)
  1501.     activecmdw = NULL;
  1502.  
  1503.     DisposeWindow(cmdw->window);
  1504.     if (cmdw->fName)
  1505.     free(cmdw->fName);
  1506.     if (cmdw->wname)
  1507.     free(cmdw->wname);
  1508.     free(cmdw);
  1509. }
  1510.  
  1511.  
  1512. /*
  1513.  * savefile
  1514.  * Save a file associated with a cmdw.
  1515.  * If as then force a new file name dialog.
  1516.  */
  1517. void
  1518. savefile (struct cmdw *cmdw, Boolean as)
  1519. {
  1520.     int err;
  1521.     long len;
  1522.     short refNum;
  1523.     Point where;
  1524.     SFReply reply;
  1525.     CharsHandle h;
  1526.     StringPtr oldfName = NULL;
  1527.     short oldvRefNum;
  1528.     static StringPtr tmpfile = "\pTMPxyzzy";
  1529.  
  1530.     if (cmdw->refNum)            /* if existing file open */
  1531.     closefile(cmdw);
  1532.  
  1533.     if (cmdw->fName) {            /* if existing name */
  1534.     oldfName = cmdw->fName;
  1535.     oldvRefNum = cmdw->vRefNum;
  1536.     } else
  1537.     as = TRUE;            /* always treat as Save As */
  1538.  
  1539.     if (as || !oldfName) {        /* if forced or none previous */
  1540.     SetPt (&where, 75, 115);
  1541.     SFPutFile(where, "\pSave As", cmdw->wname,
  1542.             0L, &reply);
  1543.     if (!reply.good)        /* if Cancel */
  1544.         return;
  1545.         /* !!!!! hmmm, we may have closed the file */
  1546.  
  1547.     cmdw->vRefNum = reply.vRefNum;
  1548.     cmdw->fName = malloc_pstring(reply.fName);
  1549.     }
  1550.  
  1551.     /*
  1552.      * Open a temporary file and write our text to it.  Possibly
  1553.      * delete an old tmp file.
  1554.      */
  1555.     FSDelete(tmpfile, cmdw->vRefNum);
  1556.  
  1557.     /* !!!!! should generate unique name here */
  1558.     err = Create(tmpfile, cmdw->vRefNum, kermtype ,texttype);
  1559.     if (err != noErr) {
  1560.     printfalert("Could not create %s: %d", p2c_tmp(tmpfile), err);
  1561.     return;
  1562.     }
  1563.     err = FSOpen(tmpfile, cmdw->vRefNum, &refNum);
  1564.     if (err != noErr) {
  1565.     printfalert("Could not open %s: %d", p2c_tmp(tmpfile), err);
  1566.     return;
  1567.     }
  1568.     cmdw->refNum = refNum;
  1569.  
  1570.     h = TEGetText(cmdw->teh);
  1571.  
  1572.     len = (*cmdw->teh)->teLength;
  1573.     err = FSWrite(cmdw->refNum, &len, (Ptr)*h);
  1574.     if (err != noErr) {
  1575.     printfalert("savefile err writing: %d", err);
  1576.     }
  1577.  
  1578.     err = FSClose(cmdw->refNum);
  1579.     if (err != noErr) {
  1580.     printfalert("Error closing file: %d", err);
  1581.     cmdw->refNum = 0;        /* lose this file */
  1582.     return;
  1583.     }
  1584.  
  1585.     /*
  1586.      * If there was an old file, delete it now unless we're doing
  1587.      * a save as and the new file name is different.
  1588.      */
  1589.     if (oldfName && 
  1590.     (!as || ((oldvRefNum == cmdw->vRefNum) && 
  1591.          strcmp(p2c_tmp((StringPtr) oldfName),
  1592.              p2c_tmp2((StringPtr) cmdw->fName)) == 0))) {
  1593.     err = FSDelete(oldfName, oldvRefNum);
  1594.     if (err != noErr) {
  1595.         printfalert("Error deleting old file %s: %d", 
  1596.             p2c_tmp((StringPtr) oldfName), err);
  1597.         return;
  1598.     }
  1599.     if (oldfName != cmdw->fName)
  1600.         free(oldfName);
  1601.     oldfName = NULL;
  1602.     }
  1603.     /*
  1604.      * Possibly delete the file name we're about to use.
  1605.      * This happens if we are replacing a file.  Hopefully,
  1606.      * the dialog already check to see if this was ok.
  1607.      */
  1608.     FSDelete(cmdw->fName, cmdw->vRefNum);
  1609.  
  1610.     /*
  1611.      * rename our tmp file to be the new file.
  1612.      */
  1613.     err = Rename(tmpfile, cmdw->vRefNum, cmdw->fName);
  1614.     if (err != noErr) {
  1615.     printfalert("Error renaming %s to %s: %d", 
  1616.             p2c_tmp(tmpfile), p2c_tmp2((StringPtr) cmdw->fName), err);
  1617.     return;
  1618.     }
  1619.  
  1620.     /*
  1621.      * Open our new file to keep it locked.
  1622.      */
  1623.     err = FSOpen(cmdw->fName, cmdw->vRefNum, &cmdw->refNum);
  1624.     if (err != noErr) {
  1625.     printfalert("savefile: error re-opening %s: %d",
  1626.             p2c_tmp((StringPtr) cmdw->fName), err);
  1627.     }
  1628.  
  1629.     setwname(cmdw, cmdw->fName);
  1630.     cmdw->flags &= ~CMDWF_MODIFIED;    /* not modified any more */
  1631. }
  1632.  
  1633.  
  1634. /*
  1635.  * checksave
  1636.  * Check to see if we should save a modified buffer.
  1637.  * Return FALSE if cancelled.
  1638.  */
  1639. Boolean checksave (struct cmdw *cmdw)
  1640. {
  1641.     DialogPtr dlg;
  1642.     short itemhit;
  1643.     char scratch[255];
  1644.  
  1645.     if (!(cmdw->flags & CMDWF_MODIFIED) || !(cmdw->flags & CMDWF_FILE))
  1646.     return TRUE;
  1647.  
  1648.     sprintf(scratch, "Save changes to %s", p2c_tmp(cmdw->wname));
  1649.     c2pstr(scratch);
  1650.     ParamText(scratch, "", "", "");
  1651.     dlg = GetNewDialog (SAVEBOXID, NILPTR, (WindowPtr) - 1);
  1652.     circleOK(dlg);
  1653.     
  1654.     for (;;) {
  1655.     ModalDialog ((ModalFilterProcPtr) NILPROC, &itemhit);
  1656.  
  1657.     switch (itemhit) {
  1658.     case SV_YES:
  1659.         DisposDialog(dlg);
  1660.         savefile(cmdw, FALSE);
  1661.         return TRUE;
  1662.  
  1663.     case SV_NO:
  1664.         DisposDialog(dlg);
  1665.         return TRUE;
  1666.  
  1667.     case SV_CANCEL:
  1668.         DisposDialog(dlg);
  1669.         return FALSE;
  1670.     }
  1671.     }
  1672. }
  1673.  
  1674.  
  1675. /*
  1676.  * closetermw
  1677.  * What to do when a termw window is closed
  1678.  */
  1679. closetermw (struct termw *termw)
  1680. {
  1681.     kHideWindow(termw);
  1682.  
  1683.     if (termw == ttermw)
  1684.     kSelectWindow(ctermw->window); /* force command window */
  1685.     else if (termw == ctermw)
  1686.     kSelectWindow(ttermw->window); /* force terminal window */
  1687. }
  1688.  
  1689.  
  1690. /*
  1691.  * setwname
  1692.  * Set window name
  1693.  * name is a pascal string
  1694.  */
  1695. void
  1696. setwname (struct cmdw *cmdw, StringPtr name)
  1697. {
  1698.     struct cmdw *tmp;
  1699.  
  1700.     if (cmdw->wname)
  1701.     free(cmdw->wname);
  1702.     cmdw->wname = malloc_pstring(name);
  1703.     SetWTitle (cmdw->window, cmdw->wname);
  1704.  
  1705.     /*
  1706.      * Don't try to update the Windows menu if we have old roms.
  1707.      */
  1708.     if (!have_128roms)
  1709.     return;
  1710.  
  1711.     /*
  1712.      * Delete old item in Windows menu if it exists and 
  1713.      * renumber following items.
  1714.      */
  1715.     if (cmdw->menuitem) {
  1716.     DelMenuItem(menus[WIND_MENU], cmdw->menuitem);
  1717.  
  1718.     for (tmp = cmdwl; tmp; tmp = tmp->next)
  1719.         if (tmp->menuitem > cmdw->menuitem)
  1720.         tmp->menuitem--;
  1721.     }
  1722.  
  1723.     /*
  1724.      * Insert new window name after the fixed entries.
  1725.      * Renumber other items.
  1726.      */
  1727.     InsMenuItem(menus[WIND_MENU], cmdw->wname, WIND_MENU_DIVIDER);
  1728.     for (tmp = cmdwl; tmp; tmp = tmp->next)    
  1729.     if (tmp->menuitem)
  1730.         tmp->menuitem++;
  1731.     cmdw->menuitem = WIND_MENU_DIVIDER + 1;
  1732. }
  1733.  
  1734. /*
  1735.  * Remove and reenter all dynamic window entries in windows menu.
  1736.  * For switching command-keys on and off, so that dynamic entries
  1737.  * are not lost.
  1738.  */
  1739. void
  1740. redo_window_menu()
  1741. {
  1742.     int min_n, max_n, i;
  1743.     struct cmdw *tmp;
  1744.  
  1745.     /*
  1746.      * Don't try to update the Windows menu if we have old roms.
  1747.      */
  1748.     if (!have_128roms)
  1749.     return;
  1750.  
  1751.     max_n = 0;
  1752.     min_n = 32766;    /* hopefully we will never have 32766 entries */
  1753.     for (tmp = cmdwl; tmp; tmp = tmp->next) {
  1754.     if (tmp->menuitem) {
  1755.         DelMenuItem(menus[WIND_MENU], tmp->menuitem);
  1756.         if (min_n > tmp->menuitem)
  1757.         min_n = tmp->menuitem;
  1758.         if (max_n < tmp->menuitem)
  1759.         max_n = tmp->menuitem;
  1760.     }
  1761.     }
  1762.  
  1763.     /*
  1764.      * Now for the hard part: we have a linked-list of windows, that we
  1765.      * wish to insert into the Windows menu in the same order that they
  1766.      * were in.  For the moment, we will do this the stupid O(n^2) way,
  1767.      * because it is easy to figure out.  Note since we are inserting
  1768.      * after WIND_MENU_DIVIDER, we go from last to first.
  1769.      */
  1770.     for (i = max_n; i >= min_n; i--) {
  1771.     for (tmp = cmdwl; tmp; tmp = tmp->next) {
  1772.         if (i == tmp->menuitem) {
  1773.             InsMenuItem(menus[WIND_MENU], tmp->wname, WIND_MENU_DIVIDER);
  1774.         }
  1775.     }
  1776.     }
  1777. }
  1778.  
  1779. /*
  1780.  * malloc_pstring
  1781.  * Return a malloced copy of a pascal string.
  1782.  */
  1783. StringPtr malloc_pstring (StringPtr src)
  1784. {
  1785.     StringPtr dst;
  1786.  
  1787.     dst = malloc(src[0]+1);
  1788.     if (!dst)
  1789.     macfatal("malloc_pstring: no memory", 0);
  1790.     bcopy((char *) src, (char *) dst, src[0]+1);
  1791.     return dst;
  1792. }
  1793.  
  1794.  
  1795. /*
  1796.  * msignal
  1797.  * signal() replacement function.
  1798.  */
  1799. SIGTYP (*msignal (int type, SIGTYP (*func)(int)))(int) {
  1800.     SIGTYP (*old)();
  1801.  
  1802.     if (type == SIGALRM) {
  1803.     old = alarmfunc;
  1804.     alarmfunc = func;
  1805.     } else if (type == SIGINT) {
  1806.     old = intfunc;
  1807.     intfunc = func;
  1808.     } else {
  1809.     macfatal("msignal unknown type", type);
  1810.     }
  1811.     return old;
  1812. }
  1813.  
  1814. /*
  1815.  * malarm
  1816.  * alarm() replacement function
  1817.  */
  1818. void
  1819. malarm (int value) {
  1820.     /*
  1821.      * Save global alarm time
  1822.      */
  1823.     if (value == 0)            /* If clearing the alarms */
  1824.       alarmtime = 0L;
  1825.     else
  1826.       alarmtime = TickCount() + 60L * value;
  1827. }
  1828.  
  1829.  
  1830. /*
  1831.  * msleep
  1832.  * sleep for milliseconds
  1833.  */
  1834. msleep (int delay)
  1835. {
  1836.     ulong ticks;
  1837.  
  1838.     ticks = (delay + 15) / 16;        /* approximate number of ticks */
  1839.     ticks += TickCount();
  1840.  
  1841.     while (((ulong)TickCount() - ticks) < 0)
  1842.     ;
  1843. }
  1844.  
  1845.  
  1846. /*
  1847.  * updatepstat
  1848.  * Update status of various print menus.
  1849.  */
  1850. updatepstat ()
  1851. {
  1852.     /* if (!hPrintBuffer || !lPrintBufferChars || to_printer) { */
  1853.     
  1854.     if (to_printer) {
  1855.     DisableItem(menus[FILE_MENU], PBUF_FIL);
  1856.     DisableItem(menus[FILE_MENU], PSTAT_FIL);
  1857.     /* DisableItem(menus[FILE_MENU], PDISC_FIL); */
  1858.     } else {
  1859.     EnableItem(menus[FILE_MENU], PBUF_FIL);
  1860.     EnableItem(menus[FILE_MENU], PSTAT_FIL);
  1861.     /* EnableItem(menus[FILE_MENU], PDISC_FIL); */
  1862.     }
  1863. #ifdef COMMENT
  1864.     if (lPrintBufferChars)
  1865.     EnableItem(menus[FILE_MENU], POPEN_FIL);
  1866.     else
  1867.     DisableItem(menus[FILE_MENU], POPEN_FIL);
  1868. #endif /* COMMENT */
  1869. }
  1870.  
  1871. /*
  1872.  * doprinter
  1873.  * Print the current window.
  1874.  */
  1875. void
  1876. doprinter (WindowPtr window)
  1877. {
  1878.     long length;
  1879.     CharsHandle h;
  1880.     struct cmdw *cmdw;
  1881.  
  1882.     if (!(cmdw = cmdwbywindow(window))) {
  1883.     SysBeep(3);
  1884.     return;
  1885.     }
  1886.  
  1887.     length = (*cmdw->teh)->teLength;
  1888.     h = TEGetText(cmdw->teh);
  1889.  
  1890.     printer((Handle) h, length, 0L, 0x7FFFFFFFL);
  1891. }
  1892.  
  1893.  
  1894. /*
  1895.  * Junk so Emacs will set local variables to be compatible with Mac/MPW.
  1896.  * Should be at end of file.
  1897.  * This routine is formatted for 8 char tabs.
  1898.  * 
  1899.  * Local Variables:
  1900.  * tab-width: 8
  1901.  * End:
  1902.  */
  1903.