/* File ckmusr.c */ /* Copyright (C) 1984, 1995, Trustees of Columbia University in the City of New York. The C-Kermit software may not be, in whole or in part, licensed or sold for profit as a software product itself, nor may it be included in or distributed with commercial products or otherwise distributed by commercial concerns to their clients or customers without written permission of the Office of Kermit Development and Distribution, Columbia University. This copyright notice must not be removed, altered, or obscured. */ /* fdc - edits for 0.991(190), 17 Aug 94 */ /* edit by John A. Oberschelp for Emory University -- vt102 printer support 22 May 1989 */ /* Emory contact is Peter W. Day, ospwd@emoryu1.cc.emory.edu */ /* various edits by PWP 8/88 -- 5/89: much rearangement, new menus 'n stuff */ /* edit by PWP 3/27/88 -- Make the log session and transaction stuff a */ /* separate menu. */ /* edits by PWP -- Nov. 87..Mar. 88 Fixed several oversights, bugs, etc., */ /* added MultiFinder support */ /* Version 0.9(36) - Matthias Aebi, ECOFIN Research and Consulting, Ltd., */ /* Oct 1987 ported to MPW C */ /* Version 0.8(35) - Jim Noble at Planning Research Corporation, June 1987. */ /* Ported to Megamax native Macintosh C compiler. */ /* DPVC at U of R, on Oct 1, to do blinking cursor and mouse cursor movement */ /* Edit by Bill, Jeff, and Howie on Jun 13 */ /* Add select window, drag */ /* Edit by WBC3 on Apr 29 */ /* Don't supply a second name for send as, otherwise file name translation */ /* will not occur. Let user type it if they want. */ /* Edit by WBC3 on Apr 23 */ /* Make typein to the emulator only take effect when it's the "front window" */ /* Edit by WBC3 on Apr 23 */ /* Make only Command-. stop protocol rather then anything but Command-. */ /* Edit by WBC3 on Apr 22 */ /* Make debug and tlog only show up if DEBUG is defined */ /* Edit by Bill on Apr 21 17:51 */ /* In Screen depelete event queue instead of handling one event at */ /* a time, also don't loose events */ /* * file ckmusr.c * * Module of mackermit containing code for the menus and other MacIntosh * things. * */ #include #include "ckcdeb.h" #include "ckcker.h" #include "ckmdef.h" /* General Mac defs */ #include "ckmres.h" /* Mac resource equates */ #include "ckmasm.h" /* new A8 and A9 traps */ #include "ckmwin.h" /* common window routines */ #include "ckmcon.h" #include "ckmptp.h" /* ckm* Prototypes */ #ifdef MPW33 #include #endif /* MPW33 */ /* Global Variables */ #ifdef COMMENT /* these are now found in ckuusx.c */ int success = 1; /* C-Kermit command succeeded flag */ int cmdlvl = 0; /* macro nesting depth (currently unused) */ #endif /* COMMENT */ #ifdef CK5A /* file wierdness (used for VAX/VMS C-Kermit */ int fblksiz = DBLKSIZ; /* file block size */ int frecl = DLRECL; /* file record length */ int frecfm = XYFF_S; /* file record format */ int forg = XYFO_S; /* file orginization (sequential) */ int fcctrl = XYFP_N; /* file carriage control (control chars) */ #endif /* CK5A */ MenuHandle menus[LAST_MENU + 1]; /* Handle on our menus */ short innum; /* Input driver refnum */ short outnum; /* Output driver refnum */ int protocmd; /* protocol file cmd, or -1 for */ /* remote cmds, or 0 if not in */ /* protocol */ char *mybuff; /* Serial drivers new buffer */ SerShk controlparam; /* Change serial driver parameters */ int quit = FALSE; Boolean mcmdactive = TRUE; /* Enable menu command keys */ Boolean fkeysactive = TRUE; /* Enable FKEYs */ #ifdef notdef extern WindowPtr remoteWindow; /* The remote command window */ #endif extern int deblog; /* If true, do debugging */ extern int what; extern int connected; extern OSType texttype; extern OSType kermtype; extern Cursor *lastCursor, *watchcurs; /* * local variables */ static int titlen = 1; Boolean have_multifinder = FALSE; /* becomes true if we are running MF */ Boolean in_background = FALSE; /* becomes TRUE if have_multifinder and * we have recieved a "suspend" event */ long mf_sleep_time = 5L; /* this is the number of (60Hz) ticks to * sleep before getting a nullEvent (to * flash our cursor) (and input chars from * the serial line) */ long pr_mf_sleep_time = 2L; /* Same as above for during transfers */ Boolean have_128roms = FALSE; /* actually, a Mac + or better */ #define switchEvt 1 /* Switching event (suspend/resume ) for app4evt */ /* * Stuff for alarm() and friends. */ SIGTYP (*msignal(int type, SIGTYP (*func)(int)))(int); SIGTYP (*alarmfunc)() = SIG_IGN; SIGTYP (*intfunc)() = SIG_IGN; typedef unsigned long ulong; ulong alarmtime = 0; /* global alarm time */ /* * Forward reference */ void closecmdw (struct cmdw *cmdw); Boolean checksave (struct cmdw *cmdw); void setwname (struct cmdw *cmdw, StringPtr name); void savefile (struct cmdw *cmdw, Boolean as); StringPtr malloc_pstring (StringPtr src); void redo_window_menu(void); void insertbuf (char *buf, int len, TEHandle teh, int *eol); void openfile (void); static void newfile (Handle h, int len); void dopagesetup (void); void doprinter (WindowPtr window); /* * Externals */ #ifdef COMMENT extern Handle hPrintBuffer; /*JAO*/ extern long lPrintBufferChars; extern long lPrintBufferAt; #endif /* COMMENT */ extern struct cmdw *activecmdw; extern struct cmdw *cmdwl; extern int to_printer; /****************************************************************************/ /* miniparser - called during protocol to handle events. Handles dialog, */ /* update, and keydown (the abort key) events. Ignores */ /* all other events. The dialog events are assumed to */ /* be for screen (status) display. */ /****************************************************************************/ miniparser (deplete) /* deplete pending events */ { EventRecord ev; DialogPtr mydlg; short item; do { if (have_multifinder) { /* task, task */ /* * NOTE: pr_mf_sleep_time MUST be < 50 to work right, due to * a bug in MultiFinder 1.0. See TN 177. */ if (pr_mf_sleep_time > 30L) pr_mf_sleep_time = 30L; WaitNextEvent (everyEvent, &ev, pr_mf_sleep_time, NULL); } else { SystemTask (); /* let the system move */ GetNextEvent (everyEvent, &ev); /* get an event */ } /* * Be paranoid: check for all the events that IsDialogEvent might trap * but we want to do something with anyway FIRST. */ switch (ev.what) { /* we may need to do something */ case nullEvent: return; /* we have depleted all pending events */ case keyDown: if ((ev.modifiers & cmdKey) && ((ev.message & 0x7f) == '.')) { if (CautionAlert (ALERT_ABORT, (ModalFilterProcPtr) NILPROC) == OKBtn) { sstate = 'a'; /* move into abort state */ return; } } break; case app4Evt: /* really a suspend/resume event */ if ((have_multifinder) && (((ev.message >> 24) & 0xff) == switchEvt)) { in_background = ((ev.message & 0x1) == 0); /* PWP: do stuff for disabling the status window here */ } updateCursor(ttermw, 1, (WindowPeek) ev.message); break; } /* * now try handing any remaining events to the dialog manager */ if (IsDialogEvent (&ev)) { /* meant for dialog manager? */ /* must be for screen */ if (DialogSelect (&ev, &mydlg, &item)) scrmydlg (item); /* let him handle it */ } else switch (ev.what) { /* we may need to do something */ /* * Dialog manager didn't want it -- deal with remainders. */ case updateEvt: doupdate ((WindowPtr) ev.message); /* handle updates */ break; case mouseDown: /* Mouse event */ domouse (&ev, TRUE); break; } } while (deplete); /* return now, or loop */ } /* miniparser */ /* * Handle events. */ char newparser (deplete, menuok, time) int deplete; /* deplete pending events */ int menuok; /* true if menus ok */ long time; /* max delay in seconds */ { int sconnected; char menu_event(); char nextcmd (); char rstate = 0; long limitticks; EventRecord ev; DialogPtr mydlg; WindowPtr w; short item; struct cmdw *cmdw; limitticks = TickCount() + 60L * time; /* set max time */ /* * Save state of connected. If it changes, exit the parser. */ sconnected = connected; /* * Update the vt100 windows. */ updatecommand(ctermw); updatecommand(ttermw); protocmd = 0; /* not in protocol mode */ do { /* * Update the cursor. */ w = FrontWindow(); if (w == ttermw->window) updateCursor(ttermw, 0, (WindowPeek) w); else if (w == ctermw->window) updateCursor(ctermw, 0, (WindowPeek) w); else if (cmdw = cmdwbywindow(w)) cmdwUpdateCursor(cmdw); #ifdef notdef /* ??? */ else updateCursor(ttermw, 0, (WindowPeek) w); #endif if (sconnected != connected) return (rstate); if (have_multifinder) { /* task, task */ /* * NOTE: mf_sleep_time MUST be < 50 to work right, due to * a bug in MultiFinder 1.0. See TN 177. */ if (mf_sleep_time > 30L) mf_sleep_time = 30L; WaitNextEvent (everyEvent, &ev, mf_sleep_time, NULL); } else { SystemTask (); /* let the system move */ GetNextEvent (everyEvent, &ev); /* get an event */ } /* * See if time has expired */ if (time && (TickCount() > limitticks)) return '\0'; if (alarmtime && alarmfunc && (((ulong)TickCount() - alarmtime) > 0)) (*alarmfunc)(0); /* Handle all the pending port chars */ inpchars(ttermw); /* * Be paranoid: check for all the events that IsDialogEvent might trap * but we want to do something with anyway FIRST. */ switch (ev.what) { /* we may need to do something */ case keyDown: case autoKey: if ((ev.modifiers & cmdKey) && ((ev.message & 0x7f) == '.')) { if (CautionAlert (ALERT_ABORT, (ModalFilterProcPtr) NILPROC) == OKBtn) return('a'); /* move into abort state */ } else if ((ev.modifiers & cmdKey) && (mcmdactive)) { if (menuok) rstate = menu_event(MenuKey(ev.message&charCodeMask)); if (rstate) return rstate; } else if (FrontWindow() == ttermw->window) { if (!connected) { if (console_char(ctermw, &ev)) { updateCursor(ctermw, 1, NIL); /* set the watch */ return (rstate); /* and return with state */ } } else { handle_char (ttermw, &ev); if (sconnected != connected) return (rstate); } } else if (cmdw = cmdwbywindow(FrontWindow())) { rcdkey (cmdw, &ev); } else if (FrontWindow () == ctermw->window) { /* always a command in this window */ if (console_char(ctermw, &ev)) { cursor_erase(ctermw); updateCursor(ctermw, 1, NIL); /* set the watch */ return (rstate); /* and return with state */ } } break; case app4Evt: /* really a suspend/resume event */ if (!have_multifinder) { updateCursor(ctermw, 1, (WindowPeek) ev.message); break; } switch ((ev.message>>24) & 0xff) { case switchEvt: /* Treat switch events as activate events too */ if (ev.message & 0x01) { /* Resume Event */ in_background = FALSE; doactivate(FrontWindow(), activeFlag); } else { /* Suspend Event */ in_background = TRUE; doactivate(FrontWindow(), 0); /* PWP: do stuff for disabling the status window here */ } } updateCursor(ctermw, 1, (WindowPeek) ev.message); break; } /* switch */ /* * Dialog manager didn't want it -- deal with remainders. */ switch (ev.what) { case updateEvt: doupdate ((WindowPtr) ev.message); /* handle updates */ break; case mouseDown: /* Mouse event */ if (rstate = domouse (&ev, FALSE)) return(rstate); break; case activateEvt: /* (de)active a window */ doactivate ((WindowPtr) ev.message, ev.modifiers); break; case diskEvt: /* disk inserted */ if (((ev.message >> 16) & 0xFFFF) != noErr) { DILoad(); DIBadMount(ev.where, ev.message); DIUnload(); } break; } /* switch */ /* * now try handing any remaining events to the dialog manager */ if (IsDialogEvent (&ev)) { if (DialogSelect (&ev, &mydlg, &item)) scrmydlg (item); /* let him handle it */ continue; } /* * Flash the cursors. */ if ((FrontWindow() == ttermw->window) && (ttermw->blinkcursor)) flash_cursor(ttermw); else if ((FrontWindow() == ctermw->window) && (ctermw->blinkcursor)) flash_cursor(ctermw); else if (activecmdw) TEIdle(activecmdw->teh); } while (deplete); /* return now, or loop */ return rstate; } /****************************************************************************/ /* domouse - handle mouse down events for different windows. */ /****************************************************************************/ char domouse (evt, mini) EventRecord *evt; int mini; /* TRUE if miniparser */ { char state = 0; WindowPtr window; int evtwcode; struct cmdw *cmdw; evtwcode = FindWindow (evt->where, &window); switch (evtwcode) { /* Tell us where */ case inMenuBar: /* Looking at the menus? */ if (mini) break; updateCursor(ttermw, 1, NIL); /* (UoR) mouse cursor off */ state = menu_event (MenuSelect (evt->where)); break; /* All done */ case inSysWindow: /* Looking at system, like */ SystemClick (evt, window); /* a desk accessary */ break; /* Let the system handle it */ case inContent: if (window != FrontWindow ()) { if (cmdw = cmdwbywindow(window)) cmdwSelectWindow(cmdw); else kSelectWindow (window); /* make window current */ } else if (window == ttermw->window) termmouse (ttermw, evt); else if (cmdw = cmdwbywindow(window)) rcdmouse (cmdw, evt); else if (window == ctermw->window) termmouse(ctermw, evt); break; case inDrag: /* Wanna drag? */ kSelectWindow(window); DragWindow (window, evt->where, &qd.screenBits.bounds); break; case inGoAway: if (cmdw = cmdwbywindow(window)) { if (TrackGoAway (cmdw->window, evt->where)) { closecmdw(cmdw); /* !!!!!!!!!! if was a file window, destroy it */ } } else if (window == ctermw->window) { if (TrackGoAway (ctermw->window, evt->where)) closetermw(ctermw); } else if (window == ttermw->window) { if (TrackGoAway (ttermw->window, evt->where)) closetermw(ttermw); } break; case inGrow: if (window != FrontWindow ()) { if (cmdw = cmdwbywindow(window)) cmdwSelectWindow(cmdw); else kSelectWindow (window); /* make window current */ } else if (window == ttermw->window) growterm(ttermw, &evt->where); else if (cmdw = cmdwbywindow(window)) growremwindow(cmdw, evt->where); else if (window == ctermw->window) growterm(ctermw, &evt->where); break; } ttermw->last_flash = TickCount (); /* reset timer for flashes */ return (state); /* return with new state or 0 */ } /* domouse */ /****************************************************************************/ /* doupdate - handle update event on different windows, dispatch to */ /* redraw routines */ /****************************************************************************/ doupdate (window) WindowPtr window; { GrafPtr savePort; struct cmdw *cmdw; GetPort (&savePort); SetPort (window); BeginUpdate (window); if (window == ttermw->window) { term_redraw(ttermw); /* terminal window */ } else if (cmdw = cmdwbywindow(window)) { rcdupdate (cmdw); /* Redraw window */ } else if (window == ctermw->window) { term_redraw(ctermw); } EndUpdate (window); SetPort (savePort); } /* doupdate */ #define NNN 20 /* for debugging */ static WindowPtr wqueue[NNN]; static int mqueue[NNN]; static int qindex = 0; /****************************************************************************/ /* doactivate - activate a window */ /****************************************************************************/ doactivate (window, mod) WindowPtr window; int mod; { /* doactivate */ GrafPtr savePort; struct cmdw *cmdw; /* The following if () {...} wrapper added by fdc at the suggestion of Edward Huff, NYU Medical Center, to fix the problem in which Mac Kermit crashes if all its windows are closed, and then it is selected from the application menu of another application. */ if (window != (WindowPtr)0) { GetPort (&savePort); SetPort (window); /* Save last action in circular queue for debugging. */ wqueue[qindex] = window; mqueue[qindex] = mod; if (++qindex == NNN) qindex = 0; HiliteWindow (window, ((mod & activeFlag) != 0)); if (!(mod & activeFlag)) activecmdw = NULL; if (cmdw = cmdwbywindow(window)) rcdactivate (cmdw, mod); else if (window == ctermw->window) { term_activate(ctermw, mod); updateCursor(ctermw, 1, (WindowPeek) ctermw->window); } else if (window == ttermw->window) { term_activate(ttermw, mod); updateCursor(ttermw, 1, (WindowPeek) ttermw->window); } #ifdef COMMENT if (!EmptyRgn(((WindowPeek)terminalWindow)->updateRgn)) doupdate (terminalWindow); /* Fake an update event */ #endif SetPort (savePort); } } /* doactivate */ show_queue () { int i; i = qindex + 1; while (i != qindex) { if (i >= NNN) i = 0; printf("%3d: window=0x%x mod=0x%x\n", i, wqueue[i], mqueue[i]); i++; } } char genstr[100]; /****************************************************************************/ /****************************************************************************/ char menu_event (menu_item) long menu_item; { int r; Boolean saveas = FALSE; short menu = HiWord (menu_item); /* decompose arg */ short item = LoWord (menu_item); char state = '\0'; int remotedialog (); /* returns boolean */ WindowPtr window; struct cmdw *cmdw; struct termw *termw; char scratch[255]; switch (menu) { case APPL_MENU: /* Mac system menu item */ handapple (item); break; /* all done */ case FILE_MENU: case FILE_MEN2: switch (item) { /* Find out which was selected */ case QUIT_FIL: /* Want to quit program? */ doexit(GOOD_EXIT,-1); /* should never return */ macfatal("menu_event: doexit didn't exit", 0); case XFER_FIL: handlelaunch (); /* Handle x-fer to application */ break; case SAVE_FIL: /* save settings */ savevals(); break; case LOAD_FIL: /* load settings */ loadvals (); HiliteMenu (0); /* Done doing menu, so un-hilite */ return 'n'; /* null command to force parser return */ case PGSTUP_FIL: /* Page Setup... */ dopagesetup(); break; case PRINT_FIL: /* Print... */ doprinter(FrontWindow()); break; case PBUF_FIL: /* Print the Buffer */ now_print(); break; case PSTAT_FIL: /* Print Buffer Status Dialog Box */ pr_stat(); break; #ifdef COMMENT case PDISC_FIL: /* Discard the Print Buffer */ if (hPrintBuffer) DisposHandle(hPrintBuffer); hPrintBuffer = 0L; lPrintBufferChars = 0L; updatepstat(); break; case POPEN_FIL: /* Open Captured Text */ if (hPrintBuffer && lPrintBufferChars) { newfile(hPrintBuffer, lPrintBufferChars); lPrintBufferChars = lPrintBufferAt = 0L; /* flush buffer */ updatepstat(); } else SysBeep(3); break; #endif /* COMMENT */ case TAKE_FIL: /* Take Command File... */ takedialog(); HiliteMenu (0); /* Done doing menu, so un-hilite */ return 'n'; /* null command to force parser return */ case TAKEW_FIL: /* Take Command from Window */ if ((cmdw = cmdwbywindow(FrontWindow())) == NULL) { SysBeep(3); break; } if ((cmdw->flags & CMDWF_FOPEN) || (!(cmdw->flags & CMDWF_FILE))) { SysBeep(3); break; } sprintf(scratch, "%%%%%%%d", cmdw->id); kShowWindow(ctermw); /* force command window */ kSelectWindow(ctermw->window); getlfile(scratch, 0); /* queue the take file */ HiliteMenu (0); /* Done doing menu, so un-hilite */ return 'n'; /* null command to force parser return */ case NEW_FIL: newfile(0L, 0); break; case OPEN_FIL: openfile(); break; case CLOSE_FIL: if (cmdw = cmdwbywindow(FrontWindow())) { closecmdw(cmdw); /* !!!!! Need to destroy window, unlink and free cmdw, etc */ } else if (termw = termwbywindow(FrontWindow())) closetermw(termw); break; case SAVEAS_FIL: saveas = TRUE; case SAVEF_FIL: if (cmdw = cmdwbywindow(FrontWindow())) { if (cmdw->flags & CMDWF_FILE) { savefile(cmdw, saveas); break; } } SysBeep(1); break; } break; case EDIT_MENU: /* PWP: good for DA editors */ case EDIT_MEN2: /* PWP: good for DA editors */ window = FrontWindow(); /* we do different things based on this */ switch(item) { case UNDO_EDIT: /* undo */ if (window == ttermw->window) { SysBeep(3); } else if (cmdw = cmdwbywindow(window)) { SysBeep (3); } else if (window == ctermw->window) { SysBeep (3); } else { if (!SystemEdit (item - 1)) SysBeep (3); } break; case CUT_EDIT: /* cut */ if (window == ttermw->window) { scr_copy(ttermw); } else if (cmdw = cmdwbywindow(window)) { rcd_cut(cmdw); cmdw->flags |= CMDWF_MODIFIED; } else if (window == ctermw->window) { scr_copy(ctermw); } else { if (!SystemEdit (item - 1)) SysBeep (3); } break; case COPY_EDIT: /* copy */ if (window == ttermw->window) { scr_copy(ttermw); } else if (cmdw = cmdwbywindow(window)) { rcd_copy(cmdw); } else if (window == ctermw->window) { scr_copy(ctermw); } else { if (!SystemEdit (item - 1)) SysBeep (3); } break; case PASTE_EDIT: /* paste */ if (window == ttermw->window) { scr_paste(ttermw); } else if (cmdw = cmdwbywindow(window)) { rcd_paste(cmdw); cmdw->flags |= CMDWF_MODIFIED; } else if (window == ctermw->window) { cmd_paste(ttermw); state = 'p'; /* wake up getchar() */ } else { if (!SystemEdit (item - 1)) SysBeep (3); } break; case CLEAR_EDIT: /* clear */ if (window == ttermw->window) { SysBeep(3); } else if (cmdw = cmdwbywindow(window)) { rcd_clear(cmdw); cmdw->flags |= CMDWF_MODIFIED; } else if (window == ctermw->window) { SysBeep(3); } else { if (!SystemEdit (item - 1)) SysBeep (3); } break; } break; case SETG_MENU: case SETG_MEN2: switch (item) { case PROT_SETG: protodialog (); break; case COMM_SETG: commdialog (); /* communications dialog */ break; case FILE_SETG: setfiledialog (); /* do default file settings */ break; case TERM_SETG: /* do terminal emulation settings */ termsetdialog (ttermw); break; case CHARS_SETG: /* do terminal emulation settings */ charsetdialog (ttermw); break; case SCRD_SETG: /* fkeys active / not active */ CheckItem (menus[SETG_MENU], SCRD_SETG, (fkeysactive = !fkeysactive)); enable_fkeys (fkeysactive); break; case MCDM_SETG: /* menu command keys active / not active */ CheckItem (menus[SETG_MENU], MCDM_SETG, (mcmdactive = !mcmdactive)); setup_menus(); /* redo menus */ redo_window_menu(); /* reenter dynamic window menu entries */ break; case KEYM_SETG: keymacros (); break; case MODF_SETG: keymoddialog (); break; } break; /* * return either 'g' for generic or 'c' for host with cmarg holding * cmd */ case REMO_MENU: case REMO_MEN2: cmarg = genstr; /* indicate cmd ok to proceed */ switch (item) { case SEND_REMO: /* send a file: local, remote files */ if (!dosenddialog (&cmarg, &cmarg2)) break; r = zxpand(cmarg); /* must call this now since sinit() doesn't */ if (r <= 0) printerr("zxpand returned ", r); nfils = -1; /* Use cmarg, not cmlist */ state = 's'; /* return with send state */ protocmd = item; what = W_SEND; scrcreate (); /* create the status screen */ break; case RECV_REMO: /* Ask for recv info -- */ initfilrecv (); /* init recv flags */ state = 'v'; /* return with recv state */ protocmd = item; what = W_RECV; scrcreate (); /* create the status screen */ break; case GETS_REMO: /* Get from server */ if (dogetfdialog (&cmarg)) { state = 'r'; /* Say we want to get */ protocmd = item; what = W_RECV; scrcreate (); /* create the status screen */ } break; case STATS_REMO: /* show transfer stats */ show_stats(); cmarg = NILPTR; break; case LCD_REMO: /* set transfer directory */ set_cwd(); cmarg = NILPTR; break; case FIN_REMO: state = 'g'; protocmd = -1; /* hey we're going to protocol! */ what = W_REMO; ssetgen (genstr, 'F', "", "", ""); /* Finish */ break; case BYE_REMO: state = 'g'; protocmd = -1; /* Ditto.. */ what = W_REMO; ssetgen (genstr, 'L', "", "", ""); /* Bye, logout */ break; case SERV_REMO: displa = 1; what = W_RECV; protocmd = item; scrcreate (); /* Create the status screen */ return ('x'); default: if (!remotedialog (item, genstr)) cmarg = NILPTR; /* cancel issued, prevent it */ else { protocmd = -1; /* hey we're going to protocol! */ what = W_REMO; if (item == HOST_REMO) state = 'c'; /* REMOTE HOST */ else state = 'g'; /* REMOTE other */ } break; } /* switch item */ if (protocmd) { lastCursor = 0L; SetCursor(watchcurs); } break; case WIND_MENU: case WIND_MENU2: cmarg = genstr; /* indicate cmd ok to proceed */ switch (item) { case TERM_WIND: /* Show terminal window */ kShowWindow(ttermw); kSelectWindow(ttermw->window); /* make window current */ cmarg = NILPTR; /* Don't do anything else */ break; case CMDW_WIND: /* Show command window */ kShowWindow(ctermw); kSelectWindow(ctermw->window); cmarg = NILPTR; /* Don't do anything else */ break; case RESP_WIND: rcmdwshow(rcmdw); cmarg = NILPTR; /* Don't do anything else */ break; case PRNT_WIND: rcmdwshow(prntw); cmarg = NILPTR; /* Don't do anything else */ break; default: for (cmdw = cmdwl; cmdw; cmdw = cmdw->next) { if (item == cmdw->menuitem) { cmdwSelectWindow(cmdw); break; } } break; } break; case LOG_MENU: case LOG_MEN2: switch(item) { case SLOG_LOG: /* session logging */ if (seslog) { scrlasttolog(ttermw); /* save the last line on the screen */ closeslog (); seslog = 0; } else { seslog = openslog (); scrtolog(ttermw); /* if the file is open, just do the dump */ } CheckItem (menus[LOG_MENU], SLOG_LOG, seslog); if (seslog) { EnableItem(menus[LOG_MENU], SDMP_LOG); } else { DisableItem(menus[LOG_MENU], SDMP_LOG); } break; case SDMP_LOG: /* dump screen to session log */ if (seslog) { /* session logging active? */ scrtolog(ttermw); /* if the file is open, just do the dump */ } else { SysBeep(3); /* can't dump screen without a log file. */ DisableItem(menus[LOG_MENU], SDMP_LOG); } break; case TLOG_LOG: /* transaction logging */ if (tralog) { closetlog (); tralog = 0; } else { tralog = opentlog (); } CheckItem (menus[LOG_MENU], TLOG_LOG, tralog); break; case PLOG_LOG: /* packet logging */ if (pktlog) { closetlog (); pktlog = 0; } else { pktlog = openplog (); } CheckItem (menus[LOG_MENU], PLOG_LOG, pktlog); break; case DLOG_LOG: /* log debugging */ if (deblog) { (void) closedlog (); deblog = 0; } else { deblog = opendlog (); rcmdwshow (rcmdw); /* display the remote cmd window */ /* Debugger(); */ } CheckItem (menus[LOG_MENU], DLOG_LOG, deblog); break; case DBGR_LOG: /* call debugger */ Debugger(); break; } break; case FONT_MENU: if (item <= BIGSZ_FONT) { /* handle a font size request */ change_current_size (ttermw, item); } else { /* handle a font request */ change_current_font(ttermw,item); } setup_font_menu(); /* update font and sizes */ break; case SPCL_MENU: /* Special */ case SPCL_MENU2: window = FrontWindow(); /* we do different things based on this */ switch (item) { case BREAK_SPCL: /* send break */ if (window == ttermw->window) sendbreak(5); else SysBeep(3); break; case LBREAK_SPCL: /* send break */ if (window == ttermw->window) sendbreak(70); else SysBeep(3); break; case XON_SPCL: /* send XON */ if (window == ttermw->window) do_xon(); else SysBeep(3); break; case DTR_SPCL: /* toggle DTR */ if (window == ttermw->window) toggle_dtr(70); else SysBeep(3); break; case RESET_SPCL: /* Reset terminal */ if (window == ttermw->window) term_reset(ttermw); /* reset the terminal emulator */ else SysBeep(3); break; } break; } HiliteMenu (0); /* Done doing menu, so un-hilite */ return (state); /* Don't go into Kermit protocol */ } /* menu_event */ #ifdef COMMENT /****************************************************************************/ /* herald() prints out the version number (but we arn't on a TTY, so don't) */ /****************************************************************************/ VOID herald () { } /* herald */ #endif /* COMMENT */ /****************************************************************************/ /****************************************************************************/ /* * conect * This MAC routine duplicates a routine in ckucon.c */ conect () { connected = 1; /* put mac into connected mode */ sstate = 'c'; if (ttermw->window != FrontWindow()) { kShowWindow(ttermw); kSelectWindow(ttermw->window); } return 0; } /****************************************************************************/ /****************************************************************************/ cmdlin () { return (0); /* nothing parsed */ } /* cmdlin */ /****************************************************************************/ /****************************************************************************/ chkint () { } /* chkint */ /****************************************************************************/ #ifdef DEBUG /* D E B U G -- Enter a record in the debugging log */ /* Call with a format, two strings, and a number: f - Format, a bit string in range 0-7. If bit x is on, then argument number x is printed. s1 - String, argument number 1. If selected, printed as is. s2 - String, argument number 2. If selected, printed in brackets. n - Int, argument 3. If selected, printed preceded by equals sign. f=0 is special: print s1,s2, and interpret n as a char. */ #define DBUFL 2300 int dodebug(f,s1,s2,n) int f; char *s1, *s2; long n; { static char *s = 0; char *sp; /* * Allocate s if not done already */ if (!s && !(s = malloc(DBUFL))) macfatal("dodebug: no room for s", 0); sp = s; if (!deblog) return (0); /* If no debug log, don't */ switch (f) { case F000: /* 0, print both strings, */ if (strlen(s1) + strlen(s2) + 5 > DBUFL) { /* and n as a char */ sprintf(sp,"DEBUG string too long\n"); } else { if (n > 31 && n < 127) sprintf(sp,"%s%s:%c\n",s1,s2,n); else if (n < 32 || n == 127) sprintf(sp,"%s%s:^%c\n",s1,s2,(n+64) & 0x7F); else if (n > 127 && n < 160) sprintf(sp,"%s%s:~^%c\n",s1,s2,(n-64) & 0x7F); else if (n > 159 && n < 256) sprintf(sp,"%s%s:~%c\n",s1,s2,n & 0x7F); else sprintf(sp,"%s%s:%d\n",s1,s2,n); } if (zsout(ZDFILE,s) < 0) deblog = 0; break; case F001: /* 1, "=n" */ sprintf(sp,"=%d\n",n); if (zsout(ZDFILE,s) < 0) deblog = 0; break; case F010: /* 2, "[s2]" */ if (strlen(s2) + 4 > DBUFL) sprintf(sp,"DEBUG string too long\n"); else sprintf(sp,"[%s]\n",s2); if (zsout(ZDFILE,"") < 0) deblog = 0; break; case F011: /* 3, "[s2]=n" */ if (strlen(s2) + 15 > DBUFL) sprintf(sp,"DEBUG string too long\n"); else sprintf(sp,"[%s]=%d\n",s2,n); if (zsout(ZDFILE,s) < 0) deblog = 0; break; case F100: /* 4, "s1" */ if (zsoutl(ZDFILE,s1) < 0) deblog = 0; break; case F101: /* 5, "s1=n" */ if (strlen(s1) + 15 > DBUFL) sprintf(sp,"DEBUG string too long\n"); else sprintf(sp,"%s=%d\n",s1,n); if (zsout(ZDFILE,s) < 0) deblog = 0; break; case F110: /* 6, "s1[s2]" */ if (strlen(s1) + strlen(s2) + 4 > DBUFL) sprintf(sp,"DEBUG string too long\n"); else sprintf(sp,"%s[%s]\n",s1,s2); if (zsout(ZDFILE,s) < 0) deblog = 0; break; case F111: /* 7, "s1[s2]=n" */ if (strlen(s1) + strlen(s2) + 15 > DBUFL) sprintf(sp,"DEBUG string too long\n"); else sprintf(sp,"%s[%s]=%d\n",s1,s2,n); if (zsout(ZDFILE,s) < 0) deblog = 0; break; default: sprintf(sp,"\n?Invalid format for debug() - %d\n",n); if (zsout(ZDFILE,s) < 0) deblog = 0; } return (0); } #endif /****************************************************************************/ /* sleep - called during protocol for a dismiss. Keep machine running */ /* with calls to the miniparser during this period. */ /****************************************************************************/ sleep (secs) { long finalticks; /* tickscount for exit */ finalticks = TickCount () + (60 * secs); /* TickCount for exit */ while (finalticks > TickCount ()) { /* keep the machine running by */ miniparser (TRUE); /* deplete the Q */ if (sstate == 'a') /* if in abort state, forget */ return; /* this wait */ } } /* sleep */ /****************************************************************************/ /****************************************************************************/ VOID ermsg (msg) /* Print error message */ char *msg; { screen (SCR_EM, 0, 0l, msg);/* Put the error on the screen */ tlog (F110, "Error -", msg, 0l); } /* ermsg */ /****************************************************************************/ /****************************************************************************/ VOID intmsg (n) long n; #pragma unused (n) { return; } /* intmsg */ /* * Insert buffer into window, processing characters. */ void insertbuf (char *buf, int len, TEHandle teh, int *eol) { int n; char *cp, *cp2; static char cr[1] = { 0x0d }; cp = cp2 = buf; while (cp < buf+len) { switch (*cp) { case 0x0a: /* linefeed */ case 0x0d: /* return */ if (n = (cp - cp2)) { /* flush buffer */ TEInsert(cp2, n, teh); } cp++; /* skip char */ cp2 = cp; *eol = 1; break; default: if (*eol) { *eol = 0; TEInsert(cr, 1, teh); } cp++; break; } } if (n = (cp - cp2)) { /* flush end of buffer */ TEInsert(cp2, n, teh); } } /* * openfile * Open an existing TEXT file. */ void openfile () { SFReply savr; Point where; struct cmdw *cmdw = NULL, *tmp; int err; short refNum; long len; char buf[1024]; int eol = 0; SetPt (&where, 75, 115); SFGetFile (where, "\pOpen:", (FileFilterProcPtr) NILPROC, 1, &texttype, (DlgHookProcPtr) NILPROC, &savr); if (!savr.good) /* did they hit cancel? */ return; /* yes, so return now */ /* * Loop checking to see if this file is already open. If it * is, just pop up the window. */ for (tmp = cmdwl; tmp; tmp = tmp->next) { if ((tmp->vRefNum == savr.vRefNum) && (strcmp(p2c_tmp(savr.fName), p2c_tmp2((StringPtr) tmp->fName)) == 0)) { cmdwSelectWindow(tmp); return; } } err = FSOpen(savr.fName, savr.vRefNum, &refNum); if (err != noErr) { printfalert("Could not open %s: %d", p2c_tmp(savr.fName), err); return; } /* * Build the window. */ cmdw = initcmdw(RCMDBOXID, RCMDVSCROLL, RCMDHSCROLL); cmdw->refNum = refNum; cmdw->vRefNum = savr.vRefNum; /* save file stuff */ cmdw->fName = malloc_pstring(savr.fName); cmdw->flags |= CMDWF_FILE; setwname(cmdw, savr.fName); /* * Read in the file. */ for (;;) { len = sizeof(buf); err = FSRead(refNum, &len, buf); if ((err == eofErr) && (len == 0)) break; if ((err != noErr) && (err != eofErr)) { printfalert("Error reading file: %d", err); /* !!!! DESTROY THINGS HERE !!!!!!!!!! */ return; } /* !!!!! make sure we don't overflow the TE record ? !!!!!!!!! */ insertbuf(buf, len, cmdw->teh, &eol); } TESetSelect(0L, 0L, cmdw->teh); /* select beginning */ setscrollmax(cmdw); /* set the max */ rcmdwshow(cmdw); } /* * newfile * Create a new window either empty or given a handle to text. */ static void newfile (Handle h, int len) { char scratch[255]; struct cmdw *cmdw; cmdw = initcmdw(RCMDBOXID, RCMDVSCROLL, RCMDHSCROLL); cmdw->flags |= CMDWF_FILE; sprintf(scratch, "Untitled-%d", titlen++); c2pstr(scratch); setwname(cmdw, (StringPtr) scratch); if (h) { TEInsert((Ptr)*h, len, cmdw->teh); TESetSelect(0L, 0L, cmdw->teh); /* select beginning */ setscrollmax(cmdw); /* set the max */ cmdw->flags |= CMDWF_MODIFIED; } rcmdwshow(cmdw); } /* * closefile * Close a file associated with a cmdw. */ closefile (struct cmdw *cmdw) { int err; if (!(cmdw->flags & CMDWF_FILE)) return; if (cmdw->refNum == 0) return; err = FSClose((short) cmdw->refNum); if (err != noErr) printfalert("Error closing: %d", err); cmdw->refNum = 0; } /* * closecmdw * Close a window associated with a cmdw. */ void closecmdw (struct cmdw *cmdw) { struct cmdw *tmp; if (!checksave(cmdw)) return; /* * Delete windows menu item, adjust item numbers for * rest of items in the menu. */ if (cmdw->menuitem) { DelMenuItem(menus[WIND_MENU], cmdw->menuitem); for (tmp = cmdwl; tmp; tmp = tmp->next) if (tmp->menuitem > cmdw->menuitem) tmp->menuitem--; } cmdw->menuitem = 0; closefile(cmdw); if (!(cmdw->flags & CMDWF_FILE)) { /* If not a file window (prob rcmdw) */ rcmdwhide(cmdw); return; } /* * Unlink and Destroy the cmdw. */ if (cmdwl == cmdw) { cmdwl = cmdw->next; } else { for (tmp = cmdwl; tmp; tmp = tmp->next) { if (tmp->next == cmdw) { tmp->next = cmdw->next; break; } } if (tmp == NULL) { printfalert("closecmdw: cmdw not in list"); return; } } if (cmdw == activecmdw) activecmdw = NULL; DisposeWindow(cmdw->window); if (cmdw->fName) free(cmdw->fName); if (cmdw->wname) free(cmdw->wname); free(cmdw); } /* * savefile * Save a file associated with a cmdw. * If as then force a new file name dialog. */ void savefile (struct cmdw *cmdw, Boolean as) { int err; long len; short refNum; Point where; SFReply reply; CharsHandle h; StringPtr oldfName = NULL; short oldvRefNum; static StringPtr tmpfile = "\pTMPxyzzy"; if (cmdw->refNum) /* if existing file open */ closefile(cmdw); if (cmdw->fName) { /* if existing name */ oldfName = cmdw->fName; oldvRefNum = cmdw->vRefNum; } else as = TRUE; /* always treat as Save As */ if (as || !oldfName) { /* if forced or none previous */ SetPt (&where, 75, 115); SFPutFile(where, "\pSave As", cmdw->wname, 0L, &reply); if (!reply.good) /* if Cancel */ return; /* !!!!! hmmm, we may have closed the file */ cmdw->vRefNum = reply.vRefNum; cmdw->fName = malloc_pstring(reply.fName); } /* * Open a temporary file and write our text to it. Possibly * delete an old tmp file. */ FSDelete(tmpfile, cmdw->vRefNum); /* !!!!! should generate unique name here */ err = Create(tmpfile, cmdw->vRefNum, kermtype ,texttype); if (err != noErr) { printfalert("Could not create %s: %d", p2c_tmp(tmpfile), err); return; } err = FSOpen(tmpfile, cmdw->vRefNum, &refNum); if (err != noErr) { printfalert("Could not open %s: %d", p2c_tmp(tmpfile), err); return; } cmdw->refNum = refNum; h = TEGetText(cmdw->teh); len = (*cmdw->teh)->teLength; err = FSWrite(cmdw->refNum, &len, (Ptr)*h); if (err != noErr) { printfalert("savefile err writing: %d", err); } err = FSClose(cmdw->refNum); if (err != noErr) { printfalert("Error closing file: %d", err); cmdw->refNum = 0; /* lose this file */ return; } /* * If there was an old file, delete it now unless we're doing * a save as and the new file name is different. */ if (oldfName && (!as || ((oldvRefNum == cmdw->vRefNum) && strcmp(p2c_tmp((StringPtr) oldfName), p2c_tmp2((StringPtr) cmdw->fName)) == 0))) { err = FSDelete(oldfName, oldvRefNum); if (err != noErr) { printfalert("Error deleting old file %s: %d", p2c_tmp((StringPtr) oldfName), err); return; } if (oldfName != cmdw->fName) free(oldfName); oldfName = NULL; } /* * Possibly delete the file name we're about to use. * This happens if we are replacing a file. Hopefully, * the dialog already check to see if this was ok. */ FSDelete(cmdw->fName, cmdw->vRefNum); /* * rename our tmp file to be the new file. */ err = Rename(tmpfile, cmdw->vRefNum, cmdw->fName); if (err != noErr) { printfalert("Error renaming %s to %s: %d", p2c_tmp(tmpfile), p2c_tmp2((StringPtr) cmdw->fName), err); return; } /* * Open our new file to keep it locked. */ err = FSOpen(cmdw->fName, cmdw->vRefNum, &cmdw->refNum); if (err != noErr) { printfalert("savefile: error re-opening %s: %d", p2c_tmp((StringPtr) cmdw->fName), err); } setwname(cmdw, cmdw->fName); cmdw->flags &= ~CMDWF_MODIFIED; /* not modified any more */ } /* * checksave * Check to see if we should save a modified buffer. * Return FALSE if cancelled. */ Boolean checksave (struct cmdw *cmdw) { DialogPtr dlg; short itemhit; char scratch[255]; if (!(cmdw->flags & CMDWF_MODIFIED) || !(cmdw->flags & CMDWF_FILE)) return TRUE; sprintf(scratch, "Save changes to %s", p2c_tmp(cmdw->wname)); c2pstr(scratch); ParamText(scratch, "", "", ""); dlg = GetNewDialog (SAVEBOXID, NILPTR, (WindowPtr) - 1); circleOK(dlg); for (;;) { ModalDialog ((ModalFilterProcPtr) NILPROC, &itemhit); switch (itemhit) { case SV_YES: DisposDialog(dlg); savefile(cmdw, FALSE); return TRUE; case SV_NO: DisposDialog(dlg); return TRUE; case SV_CANCEL: DisposDialog(dlg); return FALSE; } } } /* * closetermw * What to do when a termw window is closed */ closetermw (struct termw *termw) { kHideWindow(termw); if (termw == ttermw) kSelectWindow(ctermw->window); /* force command window */ else if (termw == ctermw) kSelectWindow(ttermw->window); /* force terminal window */ } /* * setwname * Set window name * name is a pascal string */ void setwname (struct cmdw *cmdw, StringPtr name) { struct cmdw *tmp; if (cmdw->wname) free(cmdw->wname); cmdw->wname = malloc_pstring(name); SetWTitle (cmdw->window, cmdw->wname); /* * Don't try to update the Windows menu if we have old roms. */ if (!have_128roms) return; /* * Delete old item in Windows menu if it exists and * renumber following items. */ if (cmdw->menuitem) { DelMenuItem(menus[WIND_MENU], cmdw->menuitem); for (tmp = cmdwl; tmp; tmp = tmp->next) if (tmp->menuitem > cmdw->menuitem) tmp->menuitem--; } /* * Insert new window name after the fixed entries. * Renumber other items. */ InsMenuItem(menus[WIND_MENU], cmdw->wname, WIND_MENU_DIVIDER); for (tmp = cmdwl; tmp; tmp = tmp->next) if (tmp->menuitem) tmp->menuitem++; cmdw->menuitem = WIND_MENU_DIVIDER + 1; } /* * Remove and reenter all dynamic window entries in windows menu. * For switching command-keys on and off, so that dynamic entries * are not lost. */ void redo_window_menu() { int min_n, max_n, i; struct cmdw *tmp; /* * Don't try to update the Windows menu if we have old roms. */ if (!have_128roms) return; max_n = 0; min_n = 32766; /* hopefully we will never have 32766 entries */ for (tmp = cmdwl; tmp; tmp = tmp->next) { if (tmp->menuitem) { DelMenuItem(menus[WIND_MENU], tmp->menuitem); if (min_n > tmp->menuitem) min_n = tmp->menuitem; if (max_n < tmp->menuitem) max_n = tmp->menuitem; } } /* * Now for the hard part: we have a linked-list of windows, that we * wish to insert into the Windows menu in the same order that they * were in. For the moment, we will do this the stupid O(n^2) way, * because it is easy to figure out. Note since we are inserting * after WIND_MENU_DIVIDER, we go from last to first. */ for (i = max_n; i >= min_n; i--) { for (tmp = cmdwl; tmp; tmp = tmp->next) { if (i == tmp->menuitem) { InsMenuItem(menus[WIND_MENU], tmp->wname, WIND_MENU_DIVIDER); } } } } /* * malloc_pstring * Return a malloced copy of a pascal string. */ StringPtr malloc_pstring (StringPtr src) { StringPtr dst; dst = malloc(src[0]+1); if (!dst) macfatal("malloc_pstring: no memory", 0); bcopy((char *) src, (char *) dst, src[0]+1); return dst; } /* * msignal * signal() replacement function. */ SIGTYP (*msignal (int type, SIGTYP (*func)(int)))(int) { SIGTYP (*old)(); if (type == SIGALRM) { old = alarmfunc; alarmfunc = func; } else if (type == SIGINT) { old = intfunc; intfunc = func; } else { macfatal("msignal unknown type", type); } return old; } /* * malarm * alarm() replacement function */ void malarm (int value) { /* * Save global alarm time */ if (value == 0) /* If clearing the alarms */ alarmtime = 0L; else alarmtime = TickCount() + 60L * value; } /* * msleep * sleep for milliseconds */ msleep (int delay) { ulong ticks; ticks = (delay + 15) / 16; /* approximate number of ticks */ ticks += TickCount(); while (((ulong)TickCount() - ticks) < 0) ; } /* * updatepstat * Update status of various print menus. */ updatepstat () { /* if (!hPrintBuffer || !lPrintBufferChars || to_printer) { */ if (to_printer) { DisableItem(menus[FILE_MENU], PBUF_FIL); DisableItem(menus[FILE_MENU], PSTAT_FIL); /* DisableItem(menus[FILE_MENU], PDISC_FIL); */ } else { EnableItem(menus[FILE_MENU], PBUF_FIL); EnableItem(menus[FILE_MENU], PSTAT_FIL); /* EnableItem(menus[FILE_MENU], PDISC_FIL); */ } #ifdef COMMENT if (lPrintBufferChars) EnableItem(menus[FILE_MENU], POPEN_FIL); else DisableItem(menus[FILE_MENU], POPEN_FIL); #endif /* COMMENT */ } /* * doprinter * Print the current window. */ void doprinter (WindowPtr window) { long length; CharsHandle h; struct cmdw *cmdw; if (!(cmdw = cmdwbywindow(window))) { SysBeep(3); return; } length = (*cmdw->teh)->teLength; h = TEGetText(cmdw->teh); printer((Handle) h, length, 0L, 0x7FFFFFFFL); } /* * Junk so Emacs will set local variables to be compatible with Mac/MPW. * Should be at end of file. * This routine is formatted for 8 char tabs. * * Local Variables: * tab-width: 8 * End: */