/* $Id: ckmutl.c,v 1.8 91/12/27 21:51:04 fdc Exp $ * $Source: /uw/mackermit/RCS/ckmutl.c,v $ *------------------------------------------------------------------ * $Log: ckmutl.c,v $ * Revision 1.8 91/12/27 21:51:04 fdc * Change fatal to macfatal, make all lines shorter than 80. * * Revision 1.7 91/12/15 23:18:03 rick * ut9 * * Revision 1.6 91/10/13 13:43:46 rick * UT(7) * * Revision 1.5 91/10/01 12:17:19 rick * UT(5) * * Revision 1.4 91/09/25 12:17:46 rick * Command window in TE. Multiple vt100 windows for command window. * * Revision 1.3 91/09/12 21:50:58 rick * UT(3). Install on watsun * * Revision 1.2 1991/09/10 22:21:51 rick * Update to UTexas(2) * * Revision 1.1 1991/09/10 19:18:10 rick * Initial revision * *------------------------------------------------------------------ * $Endlog$ */ /* Version 0.8(35) - Jim Noble at Planning Research Corporation, June 1987. */ /* Ported to Megamax native Macintosh C compiler. */ /* Edit by Frank on 20 Jun 5:25pm */ /* In commdialog(), don't set parity on sio chip. */ /* Edit by Bill on Apr 30 00:11 */ /* use mygetitem instead of getitem, it doesn't convert from pascal to c */ /* Redo handapple */ /* Edit by Bill on Apr 21 17:27 */ /* Try to fix meaning of TURN and TURNCH in dialog box */ /* Remove version from dofiledialog dialog box */ /* * file ckmutl.c * * Module of mackermit containing code for the menus and other MacIntosh * things. * */ /* Copyright (C) 1985, 1994, 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. */ #include /* For isdigit */ #include #include #include #include "ckcdeb.h" #include "ckcasc.h" #include "ckcker.h" #include "ckmdef.h" /* General Mac defs */ #include "ckmres.h" /* Resource file defs */ #include "ckmasm.h" /* Assembler code */ #include "ckmcon.h" /* defines, etc. for terminal emulator */ #include "ckmptp.h" /* ckm* Prototypes */ extern MenuHandle menus[]; #ifdef COMMENT /* Now found in ckuusx.c */ /****************************************************************************/ /* B L D L E N -- Make length-encoded copy of string */ /****************************************************************************/ char * bldlen (str, dest) char *str; char *dest; { int len; len = strlen (str); *dest = tochar (len); strcpy (dest + 1, str); return (dest + len + 1); } /* bldlen */ #endif /* COMMENT */ /****************************************************************************/ /* S S E T G E N -- Construct a generic command into a target string */ /****************************************************************************/ void ssetgen (char *stor, char type, char *arg1, char *arg2, char *arg3) { char *upstr, *cp; cp = stor; *cp++ = type; *cp = '\0'; if (*arg1 != '\0') { upstr = bldlen (arg1, cp); if (*arg2 != '\0') { upstr = bldlen (arg2, upstr); if (*arg3 != '\0') bldlen (arg3, upstr); } } debug (F110, "setgen", stor, 0); } /* ssetgen */ #ifdef COMMENT /* S E T G E N -- Construct a generic command */ /* in ckuusx.c */ CHAR #ifdef CK_ANSIC setgen(char type,char * arg1, char * arg2, char * arg3) #else setgen(type,arg1,arg2,arg3) char type, *arg1, *arg2, *arg3; #endif /* CK_ANSIC */ /* setgen */ { char *upstr, *cp; static char sg_cmdstr[256]; /* Place to build generic command */ cp = sg_cmdstr; *cp++ = type; *cp = NUL; if (*arg1 != NUL) { upstr = bldlen(arg1,cp); if (*arg2 != NUL) { upstr = bldlen(arg2,upstr); if (*arg3 != NUL) bldlen(arg3,upstr); } } cmarg = sg_cmdstr; debug(F110,"setgen",cmarg,0); return('g'); } #endif /* COMMENT */ /****************************************************************************/ /* printerr - display error message and number in standard error box. */ /****************************************************************************/ printerr (str, err) char *str; int err; { int i; char error[10]; if (str == NULL) str = ""; if (str[0] == 0) str = "Unspecified Kermit application error"; debug (F111,"ERROR: ", str, err); /* put error in debug log */ if (err) { /* Err=0 signals message only */ for (i = 0; i < 10; error[i++] = '\0'); /* Make string null * terminated */ NumToString ((long) err, error); /* Convert err number */ ParamText (c2p_tmp(str), error, "", ""); /* Insert strings into error box */ } else { ParamText (c2p_tmp(str), "", "", ""); } if (!server) /* Display alert only if not server mode */ NoteAlert (ALERT_ERROR, (ModalFilterProcPtr) NILPROC); } /* printerr */ /* * printfalert * Printf to an alert box. */ void printfalert (char *format, ...) { char string[512]; va_list ap; va_start(ap, format); vsprintf(string, format, ap); va_end(ap); printerr(string, 0); } /****************************************************************************/ /* macfatal - close file, and exit to shell. */ /****************************************************************************/ VOID macfatal (str, err) char *str; int err; { int i; char error[10]; if (err) { /* Err=0 signals message only */ for (i = 0; i < 10; error[i++] = '\0'); /* Make string null * terminated */ NumToString ((long) err, error); /* Convert err number */ ParamText ("\pFatal error:", c2p_tmp(str), error, ""); /* Insert strings into * error box */ } else ParamText ("\pFatal error:", c2p_tmp(str), "", ""); if (!server) /* Display alert only if not server mode */ StopAlert (ALERT_ERROR, (ModalFilterProcPtr) NILPROC); /* * terminate NOW! The heap might be scrambled, so don't try to clean * anything up. */ ExitToShell (); } /* macfatal */ /****************************************************************************/ /* SetStrText - Set the string value in the dialog's edit or static text item. */ /****************************************************************************/ SetStrText (item, s, dlg) int item; StringPtr s; /* a Pascal string */ DialogPtr dlg; { short itemtype; Rect itemrect; Handle itemhdl; GetDItem (dlg, item, &itemtype, &itemhdl, &itemrect); if ((itemtype & editText) || (itemtype & statText)) SetIText (itemhdl, s); else printerr ("Bad item in SetStrText: ", item); } /* SetStrText */ /****************************************************************************/ /* SetNumText - Set the numeric value in the dialog's edit or static text item. */ /****************************************************************************/ SetNumText (item, val, dlg) int item; int val; DialogPtr dlg; { unsigned char itembuf[10]; NumToString ((long) val, itembuf); SetStrText (item, itembuf, dlg); } /* SetNumText */ /*PWP************************************************************************/ /* circleOK - Circle the default button for a dialog (since the dialog manager * doesn't do this for us. * * cleaned up as per USENET suggestion by Keith Rollin, Apple */ /****************************************************************************/ circleOK(dlg) DialogPtr dlg; { short itemtype; Rect itemrect; Handle itemhdl; GrafPtr oldport; PenState oldpen; int i; GetDItem (dlg, 1, &itemtype, &itemhdl, &itemrect); if (itemtype != (ctrlItem | btnCtrl)) return; /* it wasn't a button */ GetPort(&oldport); SetPort(dlg); GetPenState(&oldpen); PenNormal(); InsetRect(&itemrect,-4,-4); i = (itemrect.bottom - itemrect.top) / 2; PenSize(3,3); /* see IM 1, page 407 (dialog manager) */ FrameRoundRect(&itemrect,i,i); SetPenState(&oldpen); SetPort(oldport); } /* SetStrText */ /*PWP************************************************************************ * c2p_tmp - copy s to static temporary storage and convert it to a Pascal * string. Used for passing strings to many toolbox routines. ****************************************************************************/ StringPtr c2p_tmp(char *s) { static char foo[256]; strncpy (foo, s, 256); foo[255] = '\0'; /* just in case */ c2pstr(foo); return ((StringPtr) foo); } StringPtr c2p_tmp2(char *s) { static char foo[256]; strncpy (foo, s, 256); foo[255] = '\0'; /* just in case */ c2pstr(foo); return ((StringPtr) foo); } char * p2c_tmp (StringPtr s) { static char foo[256]; pstring_copy ((StringPtr) foo, (StringPtr) s); p2cstr(foo); foo[255] = '\0'; /* just in case */ return (foo); } char * p2c_tmp2 (StringPtr s) { static char foo[256]; pstring_copy ((StringPtr) foo, (StringPtr) s); p2cstr(foo); foo[255] = '\0'; /* just in case */ return (foo); } void pstring_copy (StringPtr d, StringPtr s) { register int i; register char *sp, *dp; i = Length(s); sp = (char *) s; dp = (char *) d; *dp++ = *sp++; /* copy length */ while (i-- > 0) *dp++ = *sp++; /* copy the characters */ } void enable_fkeys(enable) int enable; { /* unsigned char *sde_addr = (unsigned char *) ScrDmpEnb; */ /* I don't know why this is needed, but ScrDmpEnb is 0x2f8 */ if (enable) *((unsigned char *) 0x2f8) = scrdmpenabled; /* enable FKEYs */ else *((unsigned char *) 0x2f8) = scrdmpdisabled; /* disable FKEYs */ } extern char *protv; /* protocol version number */ extern char *versio; /* C-Kermit version number */ extern int tsecs; /* Seconds for transaction */ extern long filcnt, /* Number of files in transaction */ flci, /* Characters from line, current file */ flco, /* Chars to line, current file */ tlci, /* Chars from line in transaction */ tlco, /* Chars to line in transaction */ ffc, /* Chars to/from current file */ tfc; /* Chars to/from files in transaction */ extern char *dftty; extern char default_port_name[]; /****************************************************************************/ /* aboutKermit - Display the about kermit dialog box, and some transaction */ /* statistics */ /****************************************************************************/ aboutKermit () { Handle kversion; short itemhit; DialogPtr aboutDlg; THz curZone; aboutDlg = GetNewDialog (ABOUTID, NILPTR, (WindowPtr) - 1); circleOK(aboutDlg); kversion = GetResource (ApplCreator, 0); /* get version information */ HLock (kversion); /* prevent movement */ /* p2cstr (*kversion); /* convert to C string */ SetStrText (AB_VERS, (StringPtr) *kversion, aboutDlg); SetStrText (AB_PROV, c2p_tmp(versio), aboutDlg); /* was protv */ /* #ifdef COMMENT */ /* take these out for the real version */ SetStrText (AB_COPY, "\pThis is a DEVELOPMENT Test copy of Kermit.", aboutDlg); SetStrText (AB_CPY2, "\p", aboutDlg); SetStrText (AB_CPY3, "\p", aboutDlg); SetStrText (AB_BUGS, "\pSend bug reports to: kermit@columbia.edu", aboutDlg); /* #endif *//* COMMENT */ ModalDialog ((ModalFilterProcPtr) NILPROC, &itemhit); DisposDialog (aboutDlg); /* c2pstr (*kversion); /* convert back to Pascal string */ HUnlock (kversion); /* undo previous HLock */ curZone = GetZone(); /* as per John Norstad's (Disinfectant) */ SetZone(HandleZone(kversion)); /* "Toolbox Gotchas" */ ReleaseResource(kversion); /* no longer needed */ SetZone(curZone); } /* aboutKermit */ /****************************************************************************/ /* show_stats -- show some statistics about the file transfer speed */ /****************************************************************************/ show_stats () { short itemhit; DialogPtr statDlg; long lx; statDlg = GetNewDialog (STATBOXID, NILPTR, (WindowPtr) - 1); circleOK(statDlg); SetNumText (ST_TSEC, tsecs, statDlg); SetNumText (ST_TLCI, tlci, statDlg); SetNumText (ST_TLCO, tlco, statDlg); SetNumText (ST_TFC, tfc, statDlg); if (tsecs > 0) SetNumText (ST_EBAUD, ((tfc*10)/tsecs), statDlg); else SetStrText (ST_EBAUD, (StringPtr) "n/a", statDlg); if (tsecs > 0) { lx = (tfc * 10l) / tsecs; SetNumText (ST_EBAUD, lx, statDlg); if (speed > 0) { lx = (lx * 100l) / speed; SetNumText (ST_EEFF, lx, statDlg); } else { SetStrText (ST_EEFF, (StringPtr) "n/a", statDlg); } } else { SetStrText (ST_EBAUD, (StringPtr) "n/a", statDlg); SetStrText (ST_EEFF, (StringPtr) "n/a", statDlg); } ModalDialog ((ModalFilterProcPtr) NILPROC, &itemhit); DisposDialog (statDlg); } /* aboutKermit */ /****************************************************************************/ /* handapple - Handle the apple menu, either running a desk accessory */ /* or calling a routine to display information about our */ /* program. Use the practice of */ /* checking for available memory, and saving the GrafPort */ /* described in the DA Manager's Guide. */ /****************************************************************************/ handapple (accitem) int accitem; { GrafPtr savePort; /* Where to save current port */ Handle acchdl; /* holds ptr to accessory resource */ Str255 accname; /* string holds accessory name */ long accsize; /* holds size of the acc + stack */ if (accitem == 1) { /* tell about Kermit? */ aboutKermit (); /* yes, "about kermit" please */ return; /* and return */ } GetItem (menus[APPL_MENU], accitem, accname); /* get the pascal name */ SetResLoad (FALSE); /* don't load into memory */ /* figure out acc size + heap */ accsize = SizeResource (GetNamedResource ((ResType) 'DRVR', accname)); acchdl = NewHandle (accsize); /* try for a block this size */ SetResLoad (TRUE); /* reset flag for rsrc mgr */ if (acchdl == NIL) { /* able to get a chunk? */ printerr ("Not enough memory for accessory. Requires: ", (int) accsize); return; /* failed */ } DisposHandle (acchdl); /* get rid of this handle */ GetPort (&savePort); /* save the current port */ OpenDeskAcc (accname); /* run desk accessory */ SetPort (savePort); /* and put back our port */ } /* handapple */ /******************************************************************** * Stuff to handle and update the Font menu */ setup_font_menu() { int i, nmitems; long m_sz; char m_item_buf[256]; char cur_font_name[256]; struct termw *termw = ttermw; GetFontName (termw->current_font, cur_font_name); /* First, the font sizes */ for (i = 0; i < BIGSZ_FONT; i++) { /* get the size number */ GetItem(menus[FONT_MENU], i, m_item_buf); StringToNum(m_item_buf, &m_sz); /* if this is an availiable size, outline font it, else normal */ SetItemStyle (menus[FONT_MENU], i, (RealFont(termw->current_font, m_sz) ? outline : normal)); CheckItem (menus[FONT_MENU], i, (m_sz == ttermw->current_size)); } /* Now the font names */ nmitems = CountMItems(menus[FONT_MENU]); for (i = BIGSZ_FONT+2; i <= nmitems; i++) { GetItem(menus[FONT_MENU], i, m_item_buf); /* if the font number corrisponding to this menu entry is the current font, check it, else don't */ CheckItem(menus[FONT_MENU], i, EqualString(m_item_buf, cur_font_name, FALSE, TRUE)); } } change_current_size (struct termw *termw, int item) { char m_item_buf[256]; long m_sz; GetItem(menus[FONT_MENU], item, m_item_buf); StringToNum(m_item_buf, &m_sz); if ((m_sz > 4) && (m_sz < 72)) { termw->current_size = m_sz; /* change the current size */ term_new_font(termw); /* doesn't change #lines, but size of a line has changed */ grow_term_to(termw,termw->screensize); } } change_current_font (struct termw *termw, int item) { char m_item_buf[256]; short fn; GetItem(menus[FONT_MENU], item, m_item_buf); GetFNum(m_item_buf, &fn); if (fn != 0) { termw->current_font = fn; term_new_font(termw); /* doesn't change #lines, but size of a line has changed */ grow_term_to(termw,termw->screensize); } } typedef struct { unsigned kerval; unsigned int macval; } KMTBL; KMTBL kerbaudtbl[] = { {300, baud300}, {600, baud600}, {1200, baud1200}, {1800, baud1800}, {2400, baud2400}, {4800, baud4800}, {7200, baud7200}, {9600, baud9600}, {19200, baud19200}, {38400, 2}, /* this is a guess */ {57600, baud57600} }; #define kerbaudlen ((sizeof (kerbaudtbl))/(sizeof (KMTBL))) #define PARITY_ETC (noParity+stop10+data8) int setserial (irefnum, orefnum, b, p) int irefnum, orefnum, b, p; #pragma unused (p) { int err, mb, i; ParamBlockRec cpb; if ((b < 300) || (b > 57600)) return (0); /* was a garbage value */ if (!irefnum) /* port not open */ return (1); /* pretend that we succeeded */ mb = baud9600; found_speed: /* * PWP: if the Mac does parity in hardware, then Even parity seems to * not work correctly, so we have Kermit do parity in * software. */ /* * Apple Q&A says that I should reset the output side first, then input, then * do handshake and set buffer */ err = SerReset (orefnum, mb + PARITY_ETC); /* reset serial output port */ if (err != noErr) { printerr ("setserial couldn't set port (output): ", err); return (0); } err = SerReset (irefnum, mb + PARITY_ETC); /* reset serial input port */ if (err != noErr) { printerr ("setserial couldn't set port (input): ", err); return (0); } cpb.cntrlParam.csCode = 13; /* set baud rate */ cpb.cntrlParam.csParam[0] = (unsigned short) b; cpb.cntrlParam.ioCRefNum = orefnum; err = PBControl (&cpb, FALSE); if (err != noErr) { printerr ("setserial couldn't set port (input): ", err); return (0); } cpb.cntrlParam.csCode = 13; /* set baud rate */ cpb.cntrlParam.csParam[0] = (unsigned short) b; cpb.cntrlParam.ioCRefNum = irefnum; err = PBControl (&cpb, FALSE); if (err != noErr) { printerr ("setserial couldn't set port (input): ", err); return (0); } speed = b; /* set global kermit value */ return (1); /* we did it */ } /* setserial */ RESSERTBL commbaudtbl[] = { {CR_BAUD300, 300}, {CR_BAUD600, 600}, {CR_BAUD1200, 1200}, {CR_BAUD1800, 1800}, {CR_BAUD2400, 2400}, {CR_BAUD3600, 3600}, {CR_BAUD4800, 4800}, {CR_BAUD7200, 7200}, {CR_BAUD9600, 9600}, {CR_BAUD14400, 14400}, {CR_BAUD19200, 19200}, {CR_BAUD28800, 28800}, {CR_BAUD38400, 38400}, {CR_BAUD57600, 57600}, #ifdef NOT_YET {CR_BAUD76800, 76800}, {CR_BAUD115200, 115200}, #endif {0, 0} }; RESSERTBL commparitytbl[] = { {CR_PARODD, KPARITY_ODD}, {CR_PAREVEN, KPARITY_EVEN}, {CR_PARMARK, KPARITY_MARK}, {CR_PARSPACE, KPARITY_SPACE}, {CR_PARNONE, KPARITY_NONE}, {0, 0} }; /****************************************************************************/ /* rshilite - hilite the radio control item matching the given */ /* serial value, and disable all other control items in the */ /* resource-serial table. */ /****************************************************************************/ rshilite (servalue, rstbl, dlg) int servalue; RESSERTBL rstbl[]; DialogPtr dlg; { int i; short itemtype; Rect itembox; Handle itemhdl; for (i = 0; rstbl[i].resval != 0; i++) { GetDItem (dlg, rstbl[i].resval, &itemtype, &itemhdl, &itembox); if (itemtype != ctrlItem + radCtrl) printerr ("rshilite called with non radio control: ", rstbl[i].resval); if (rstbl[i].serval == servalue) SetCtlValue ((ControlHandle) itemhdl, btnOn); else SetCtlValue ((ControlHandle) itemhdl, btnOff); } } /* rshilite */ /****************************************************************************/ /****************************************************************************/ rsreference (rstbl, value, dlg) RESSERTBL rstbl[]; DialogPtr dlg; int value; { int i; short itemtype; Rect itembox; Handle itemhdl; for (i = 0; rstbl[i].resval != 0; i++) { GetDItem (dlg, rstbl[i].resval, &itemtype, &itemhdl, &itembox); SetCRefCon ((ControlHandle) itemhdl, (long) value); } } /* rsreference */ /****************************************************************************/ /* rsserval - given a resource ID for a control and a resource-serial */ /* table, return the serial value. */ /****************************************************************************/ int rsserval (resvalue, rstbl) int resvalue; RESSERTBL rstbl[]; { int i; for (i = 0; rstbl[i].resval != 0; i++) if (rstbl[i].resval == resvalue) return (rstbl[i].serval); macfatal ("rsserval didn't find: ", resvalue); return (0); /* never get here */ } /* rsserval */ #define CREF_BAUD 1 #define CREF_PARITY 2 extern int drop_dtr; /****************************************************************************/ /* commdialog - enter communications setup dialog. */ /****************************************************************************/ commdialog () { DialogPtr commdlg; long i; short itemhit; short itemtype; int dlgspeed; int dlgparity; int dlgflow; int dlgdtr; int dlgdtrin, dlgctsout; Handle itemhdl; Rect itembox; char new_port_name[256]; extern int fCTS, fDTR; GrafPtr save_port; GetPort(&save_port); if ((commdlg = GetNewDialog (COMMBOXID, NILPTR, (WindowPtr) - 1)) == 0) return; SetPort(commdlg); circleOK(commdlg); dlgspeed = speed; /* initialize to current global */ dlgparity = parity; /* values of baud and parity */ dlgflow = flow; dlgctsout = fCTS; dlgdtrin = fDTR; dlgdtr = drop_dtr; rshilite (dlgspeed, commbaudtbl, commdlg); /* hilite our baud */ rshilite (dlgparity, commparitytbl, commdlg); /* hilite our parity */ SetCtlValue (getctlhdl (CR_XONXOFF, commdlg), /* hilite our flow */ dlgflow ? btnOn : btnOff); SetCtlValue (getctlhdl (CR_DROPDTR, commdlg), /* hilite our DTR */ dlgdtr ? btnOn : btnOff); SetCtlValue (getctlhdl (CR_DTRIN, commdlg), dlgdtrin ? btnOn : btnOff); SetCtlValue (getctlhdl (CR_CTSOUT, commdlg), dlgctsout ? btnOn : btnOff); /* for all baud and parity controls set the reference value for each * control to the resource-serial table address so we can manipulate * these controls easily during the dialog processing. */ rsreference (commbaudtbl, CREF_BAUD, commdlg); /* setup control ref's */ rsreference (commparitytbl, CREF_PARITY, commdlg); /* * Set dialog refcon so that drawPortPopup can find the string to draw. * Set drawing routine for popup menu. */ strcpy(new_port_name, dftty); SetWRefCon(commdlg, (long)new_port_name); /* Stash the csp */ GetDItem(commdlg, CR_PORT, &itemtype, &itemhdl, &itembox); SetDItem(commdlg, CR_PORT, itemtype, (Handle)drawPortPopup, &itembox); for (;;) { ModalDialog ((ModalFilterProcPtr) NILPROC, &itemhit); switch (itemhit) { case OKBtn: drop_dtr = dlgdtr; /* if port changed */ if ((innum == 0) || (strcmp(new_port_name, dftty) != 0)) { Boolean old_port_was_open = (innum != 0); dlgdtr = drop_dtr; drop_dtr = 1; /* so we don't confuse AppleTalk */ port_close(); drop_dtr = dlgdtr; port_open(new_port_name); if (innum == 0) { /* if open failed */ if (old_port_was_open) port_open(dftty); /* re-open old port */ strcpy(new_port_name, dftty); GetDItem(commdlg, CR_PORT, &itemtype, &itemhdl, &itembox); InvalRect(&itembox); break; /* keep doing dialog */ } strcpy(default_port_name, new_port_name); dftty = default_port_name; } parity = dlgparity; flow = dlgflow; fDTR = dlgdtrin; fCTS = dlgctsout; if (!setserial (innum, outnum, dlgspeed, KPARITY_NONE)) break; /* keep doing dialog */ if (sershake(flow)) break; /* else fall thru */ case QuitBtn: DisposDialog (commdlg); /* finished with the dialog */ SetPort(save_port); return; /* so return */ case CR_XONXOFF: /* do flow control */ dlgflow = !dlgflow; SetCtlValue (getctlhdl (CR_XONXOFF, commdlg), dlgflow ? btnOn : btnOff); break; case CR_DROPDTR: /* drop DTR on exit */ dlgdtr = !dlgdtr; SetCtlValue (getctlhdl (CR_DROPDTR, commdlg), dlgdtr ? btnOn : btnOff); break; case CR_PORT: GetDItem(commdlg, CR_PORT, &itemtype, &itemhdl, &itembox); popSerialPorts(&itembox, new_port_name); break; case CR_DTRIN: dlgdtrin = !dlgdtrin; SetCtlValue (getctlhdl (CR_DTRIN, commdlg), dlgdtrin ? btnOn : btnOff); break; case CR_CTSOUT: dlgctsout = !dlgctsout; SetCtlValue (getctlhdl (CR_CTSOUT, commdlg), dlgctsout ? btnOn : btnOff); break; default: /* default is radio button */ GetDItem (commdlg, itemhit, &itemtype, &itemhdl, &itembox); i = GetCRefCon ((ControlHandle) itemhdl); switch (i) { case CREF_BAUD: dlgspeed = rsserval (itemhit, commbaudtbl); rshilite (dlgspeed, commbaudtbl, commdlg); break; case CREF_PARITY: dlgparity = rsserval (itemhit, commparitytbl); rshilite (dlgparity, commparitytbl, commdlg); break; default: printerr ("Item has no refcon: ", itemhit); } } } } /* commdialog */ RESSERTBL protoblktbl[] = { /* block check: */ {PR_BLK1, 1}, /* type 1 */ {PR_BLK2, 2}, /* type 2 */ {PR_BLK3, 3}, /* type 3 */ {0, 0} }; #define KTURN_NONE 128 /* indicate no handshake */ RESSERTBL protohstbl[] = { /* hand shake: */ {PR_HSBELL, 7}, /* bell = 7 */ {PR_HSCR, 15}, /* cr = 15 */ {PR_HSESC, 33}, /* esc = 33 */ {PR_HSLF, 12}, /* lf = 12 */ {PR_HSNONE, KTURN_NONE}, /* none = 128 */ {PR_HSXON, XON}, /* xon = 21 */ {PR_HSXOFF, 23}, /* xoff = 23 */ {0, 0} }; RESSERTBL protointtbl[] = { /* edit text integer items: */ {PR_INPADN, 0}, /* inbound pad count edit text */ {PR_OUTPADN, 1}, /* outbound pad count edit text */ {PR_INTIMEO, 2}, /* inbound secs timeout edit text */ {PR_OUTTIMEO, 3}, /* outbound secs timeout edit text */ {PR_INPKTLEN, 4}, /* inbound packet length edit text */ {PR_OUTPKTLEN, 5}, /* outbound packet length edit text */ {PR_WINSIZ, 6}, /* sliding window size */ {0, 0} }; int *protointcells[] = { /* parallel to above table! */ &mypadn, /* inbound pad count */ &npad, /* outbound pad count */ &timint, /* inbound timeout in secs */ &rtimo, /* outbound timeout in secs */ &urpsiz, /* user requested inbound pkt length */ &spsiz, /* inbound pkt length */ &wslotr /* sliding window size requested */ }; RESSERTBL protochrtbl[] = { /* edit text character items: */ {PR_INPADC, 0}, /* inbound pad chr edit text */ {PR_OUTPADC, 1}, /* outbound pad chr */ {PR_INEOP, 2}, /* inbound end of packet edit text */ {PR_OUTEOP, 3}, /* outbound end of packet edit text */ {PR_INSOP, 4}, /* inbound start of pkt edit text */ {PR_OUTSOP, 5}, /* outbound start of pkt edit text */ {0, 0} }; char *protochrcells[] = { /* parallel to above table! */ &mypadc, /* inbound pad char */ &padch, /* outbound pad char */ &eol, /* inbound end of packet char */ &seol, /* outbound end of pkt char */ &stchr, /* inbound start of pkt char */ &mystch /* outbound start of packet char */ }; /****************************************************************************/ /* etgetcc - Set edit text paramter from dialog window to an ASCII */ /* control character value. Returns FALSE if value is */ /* illegal, warning has been displayed. */ /****************************************************************************/ int etgetcc (item, dlg, chrcell) DialogPtr dlg; int item; char *chrcell; { short itemtype; int i; long rslt; Rect itemrect; Handle itemhdl; char itembuf[256]; char c; GetDItem (dlg, item, &itemtype, &itemhdl, &itemrect); if (itemtype != editText) { printerr ("etsetcc item not editText: ", item); return (FALSE); } GetIText (itemhdl, itembuf); /* p2cstr(itembuf); /* convert to c string */ for (i = 1; i < Length(itembuf); i++) { /* check for digits */ c = itembuf[i]; if (!isdigit (c)) { printerr ("Field contains a non numeric, code ", c); return (FALSE); } } StringToNum (itembuf, &rslt); if ((rslt > 037) && (rslt != 0177)) { printerr ("Not in ASCII control range: ", (int) rslt); return (FALSE); } *chrcell = (char) rslt; return (TRUE); } /* etgetcc */ /****************************************************************************/ /* etgetnum - Set edit text paramet from dialog to numeric cell. */ /* Returns FALSE if value is non numeric or not in range */ /* in which case an error message is printed. */ /****************************************************************************/ int etgetnum (item, dlg, intcell) DialogPtr dlg; int item; int *intcell; { short itemtype; int i; long rslt; Rect itemrect; Handle itemhdl; char itembuf[256]; char c; GetDItem (dlg, item, &itemtype, &itemhdl, &itemrect); if (itemtype != editText) { printerr ("etsetnum item not editText: ", item); return (FALSE); } GetIText (itemhdl, itembuf); for (i = 1; i < Length(itembuf); i++) { /* check for digits */ c = itembuf[i]; if (!isdigit (c)) { printerr ("Field contains a non numeric, code ", c); return (FALSE); } } StringToNum (itembuf, &rslt); /* check inbound packet length */ /* MAXRP-8 is for the rest of the header (MARK, SEQ, TYPE, etc.) */ if ((item == PR_INPKTLEN) && (rslt > MAXRP-8)) { printerr ("Sorry, the maximum receive packet length is ", MAXRP-8); return (FALSE); } /* check outbound packet length */ if ((item == PR_OUTPKTLEN) && (rslt > MAXSP)) { printerr ("Sorry, the maximum send packet length is ", MAXSP); return (FALSE); } *intcell = (int) rslt; return (TRUE); } /* etgetnum */ #define PREF_BLKCHK 1 #define PREF_HNDSHK 2 /****************************************************************************/ /* protodialog - enter protocol setup dialog. */ /****************************************************************************/ protodialog () { DialogPtr protoDialog; long i; short itemhit; short itemtype; int dlgval; int dlgint; int dlgbctr; int dlgturnch; Handle itemhdl; Rect itembox; char dlgchr; protoDialog = GetNewDialog (PROTOBOXID, NILPTR, (WindowPtr) - 1); circleOK(protoDialog); dlgbctr = bctr; /* init local block check */ dlgturnch = turnch; /* handshake */ if (!turn) /* no turn character? */ dlgturnch = KTURN_NONE; /* indicate none */ /* for all button controls set the reference value */ rsreference (protohstbl, PREF_HNDSHK, protoDialog); rsreference (protoblktbl, PREF_BLKCHK, protoDialog); /* for each button controls, hilite the current setting */ rshilite (dlgturnch, protohstbl, protoDialog); /* hilite our hand shake */ rshilite (dlgbctr, protoblktbl, protoDialog); /* hilite our block check */ /* for each edit text item, set current value in edit text */ for (i = 0; protochrtbl[i].resval != 0; i++) SetNumText (protochrtbl[i].resval, (int) *protochrcells[i], protoDialog); for (i = 0; protointtbl[i].resval != 0; i++) SetNumText (protointtbl[i].resval, *protointcells[i], protoDialog); for (;;) { ModalDialog ((ModalFilterProcPtr) NILPROC, &itemhit); switch (itemhit) { case OKBtn: /* finish up */ turnch = dlgturnch; /* set global handshake */ turn = (turnch == KTURN_NONE) ? FALSE : TRUE; /* set turn */ bctr = dlgbctr; /* set block type check */ for (i = 0; protochrtbl[i].resval != 0; i++) /* set chr vals */ if (!etgetcc (protochrtbl[i].resval, protoDialog, protochrcells[i])) macfatal ("During OKBtn etgetcc failed!", (int) i); for (i = 0; protointtbl[i].resval != 0; i++) /* set int vals */ if (!etgetnum (protointtbl[i].resval, protoDialog, protointcells[i])) macfatal ("During OKBtn etgetnum failed!", (int) i); if (wslotr < 1) wslotr = 1; if (wslotr > 1) { swcapr = 1; #ifdef COMMENT if ((urpsiz * wslotr) > BIGRBUFSIZ) { urpsiz = BIGRBUFSIZ / wslotr - 1; printerr (\ "Window size * packet length too big, packet length reset to ", urpsiz); } #endif /* COMMENT */ } else { swcapr = 0; } /* fall through... */ case QuitBtn: /* fall in from above */ DisposDialog (protoDialog); /* finished with the dialog */ return; /* return */ case PR_INPADC: case PR_OUTPADC: case PR_INEOP: case PR_OUTEOP: case PR_INSOP: case PR_OUTSOP: if (!etgetcc (itemhit, protoDialog, &dlgchr)) { /* get back tbl idx */ dlgval = rsserval (itemhit, protochrtbl); dlgval = (int) *protochrcells[dlgval]; /* now cell value */ SetNumText (itemhit, dlgval, protoDialog); /* and reset it */ SelIText(protoDialog, itemhit, 0, 32767); } break; case PR_INPADN: case PR_OUTPADN: case PR_INTIMEO: case PR_OUTTIMEO: case PR_INPKTLEN: case PR_OUTPKTLEN: case PR_WINSIZ: if (!etgetnum (itemhit, protoDialog, &dlgint)) { /* get back tbl idx */ dlgval = rsserval (itemhit, protointtbl); dlgval = *protointcells[dlgval]; /* now cell value */ SetNumText (itemhit, dlgval, protoDialog); /* and reset it */ SelIText(protoDialog, itemhit, 0, 32767); } break; default: GetDItem (protoDialog, itemhit, &itemtype, &itemhdl, &itembox); if (itemtype != ctrlItem + radCtrl) /* must be radio button */ macfatal ("Not radio button", itemhit); i = GetCRefCon ((ControlHandle) itemhdl); if (i == PREF_BLKCHK) { dlgbctr = rsserval (itemhit, protoblktbl); rshilite (dlgbctr, protoblktbl, protoDialog); } else if (i == PREF_HNDSHK) { dlgturnch = rsserval (itemhit, protohstbl); rshilite (dlgturnch, protohstbl, protoDialog); } else printerr ("radio item has bad refcon: ", itemhit); break; /* all done with radio buttons */ } } } /* protodialog */ #define TR_FIRST TR_AUTOWRAP #define TR_LAST TR_BLINKC /****************************************************************************/ /****************************************************************************/ termsetdialog (struct termw *termw) { DialogPtr termdlg; short itemhit; short i; int dlgint, t_numlines; Boolean ts[TR_LAST + 1]; termdlg = GetNewDialog (TERMINALBOXID, NILPTR, (WindowPtr) - 1); circleOK(termdlg); ts[TR_AUTOWRAP] = termw->autowrap; ts[TR_AUTOREPT] = termw->autorepeat; ts[TR_INVERT] = termw->screeninvert; ts[TR_SMOOTH] = termw->smoothscroll; ts[TR_AUTOLF] = termw->newline; ts[TR_LOCLECHO] = duplex; ts[TR_TRANSP] = !termw->dispcontchar; /* PWP */ ts[TR_BLOCKC] = termw->blockcursor; ts[TR_MOUSE] = termw->mouse_arrows; ts[TR_VISBELL] = termw->visible_bell; ts[TR_EIGHTBIT] = termw->eightbit_disp; ts[TR_BLINKC] = termw->blinkcursor; t_numlines = termw->screensize; /* set the ctl values according to the flags */ for (i = TR_FIRST; i <= TR_LAST; i++) SetCtlValue (getctlhdl(i, termdlg), (ts[i]) ? btnOn : btnOff); SetNumText(TR_NUMLINES,t_numlines,termdlg); SelIText(termdlg, TR_NUMLINES, 0, 32767); for (;;) { ModalDialog ((ModalFilterProcPtr) NILPROC, &itemhit); switch (itemhit) { case OKBtn: /* finish up */ termw->autowrap = ts[TR_AUTOWRAP]; termw->autorepeat = ts[TR_AUTOREPT]; termw->smoothscroll = ts[TR_SMOOTH]; termw->newline = ts[TR_AUTOLF]; duplex = ts[TR_LOCLECHO]; termw->dispcontchar = !ts[TR_TRANSP]; termw->visible_bell = ts[TR_VISBELL]; termw->eightbit_disp = ts[TR_EIGHTBIT]; if ((termw->blockcursor != ts[TR_BLOCKC]) || (termw->blinkcursor != ts[TR_BLINKC]) || (ts[TR_MOUSE])) { cursor_erase (termw); termw->blockcursor = ts[TR_BLOCKC]; termw->blinkcursor = ts[TR_BLINKC]; termw->mouse_arrows = ts[TR_MOUSE]; cursor_draw(termw); } if (termw->screeninvert != ts[TR_INVERT]) invert_term (termw); grow_term_to(termw, t_numlines); case QuitBtn: /* fall in from above */ DisposDialog (termdlg); /* finished with the dialog */ return; /* return */ case TR_RESETBTN: term_reset(termw); /* reset the terminal emulator */ break; case TR_AUTOWRAP: case TR_AUTOREPT: case TR_INVERT: case TR_SMOOTH: case TR_AUTOLF: case TR_LOCLECHO: case TR_TRANSP: case TR_BLOCKC: case TR_MOUSE: case TR_VISBELL: case TR_EIGHTBIT: case TR_BLINKC: ts[itemhit] = !ts[itemhit]; SetCtlValue (getctlhdl (itemhit, termdlg), (ts[itemhit]) ? btnOn : btnOff); break; case TR_NUMLINES: if (!etgetnum (TR_NUMLINES, termdlg, &dlgint)) { SetNumText (TR_NUMLINES, t_numlines, termdlg); SelIText(termdlg, TR_NUMLINES, 0, 32767); } else { if (dlgint > MAX_SCREENSIZE) { printerr ("Sorry, the maximum screen length is", MAX_SCREENSIZE); SetNumText (TR_NUMLINES, t_numlines, termdlg); SelIText(termdlg, TR_NUMLINES, 0, 32767); } else { t_numlines = dlgint; } } break; } } } /* termsetdialog */ #define CS_AFIRST CS_USA #define CS_ALAST CS_SWISS #define CS_BFIRST CS_ISOLATIN1 #define CS_BLAST CS_ISOLATIN5 /****************************************************************************/ /****************************************************************************/ charsetdialog (struct termw *termw) { DialogPtr chardlg; short itemhit; short i; int dlg_g0 = CS_USA, dlg_g1 = CS_VTGRAPH; chardlg = GetNewDialog (CHARBOXID, NILPTR, (WindowPtr) - 1); circleOK(chardlg); if (termw->nat_char_mode) dlg_g0 = termw->nat_set + CS_USA - USA_NAT; else dlg_g0 = CS_USA; /* Should handle GRAF_SET here too */ switch (termw->graphicsinset[1]) { case LAT1_SET: case DECINTL_SET: dlg_g1 = CS_ISOLATIN1; break; case LAT2_SET: dlg_g1 = CS_ISOLATIN2; break; case LAT3_SET: dlg_g1 = CS_ISOLATIN3; break; case LAT4_SET: dlg_g1 = CS_ISOLATIN4; break; case LATCYR_SET: dlg_g1 = CS_ISOCYRILLIC; break; case LATARAB_SET: dlg_g1 = CS_ISOARABIC; break; case LATGREEK_SET: dlg_g1 = CS_ISOGREEK; break; case LATHEBREW_SET: dlg_g1 = CS_ISOHEBREW; break; case LAT5_SET: dlg_g1 = CS_ISOLATIN5; break; case GRAF_SET: dlg_g1 = CS_VTGRAPH; break; case TECH_SET: dlg_g1 = CS_VTTECH; break; } for (i = CS_AFIRST; i <= CS_ALAST; i++) SetCtlValue (getctlhdl (i, chardlg), btnOff); SetCtlValue (getctlhdl (dlg_g0, chardlg), btnOn); for (i = CS_BFIRST; i <= CS_BLAST; i++) SetCtlValue (getctlhdl (i, chardlg), btnOff); SetCtlValue (getctlhdl (dlg_g1, chardlg), btnOn); for (;;) { ModalDialog ((ModalFilterProcPtr) NILPROC, &itemhit); switch (itemhit) { case OKBtn: /* finish up */ switch (dlg_g0) { case CS_USA: termw->nat_set = USA_NAT; termw->graphicsinset[0] = ASCII_SET; /* but we leave the setting of termw->nat_char_mode as is */ break; case CS_UK: case CS_DUTCH: case CS_FINNISH: case CS_FRENCH: case CS_FRCAN: case CS_GERMAN: case CS_ITALIAN: case CS_NORDAN: case CS_PORTUGUESE: case CS_SPANISH: case CS_SWEDISH: case CS_SWISS: termw->graphicsinset[0] = ASCII_SET; termw->nat_set = dlg_g0 - CS_USA + USA_NAT; termw->nat_char_mode = TRUE; break; } switch (dlg_g1) { case CS_ISOLATIN1: termw->graphicsinset[1] = LAT1_SET; termw->nat_char_mode = FALSE; break; case CS_ISOLATIN2: termw->graphicsinset[1] = LAT2_SET; termw->nat_char_mode = FALSE; break; case CS_ISOLATIN3: termw->graphicsinset[1] = LAT3_SET; termw->nat_char_mode = FALSE; break; case CS_ISOLATIN4: termw->graphicsinset[1] = LAT4_SET; termw->nat_char_mode = FALSE; break; case CS_ISOCYRILLIC: termw->graphicsinset[1] = LATCYR_SET; termw->nat_char_mode = FALSE; break; case CS_ISOARABIC: termw->graphicsinset[1] = LATARAB_SET; termw->nat_char_mode = FALSE; break; case CS_ISOGREEK: termw->graphicsinset[1] = LATGREEK_SET; termw->nat_char_mode = FALSE; break; case CS_ISOHEBREW: termw->graphicsinset[1] = LATHEBREW_SET; termw->nat_char_mode = FALSE; break; case CS_ISOLATIN5: termw->graphicsinset[1] = LAT5_SET; termw->nat_char_mode = FALSE; break; case CS_VTGRAPH: termw->graphicsinset[1] = GRAF_SET; break; case CS_VTTECH: termw->graphicsinset[1] = TECH_SET; break; } set_char_map(termw); /* change the display translate table */ /* fall through */ case QuitBtn: /* fall in from above */ DisposDialog (chardlg); /* finished with the dialog */ return; /* return */ case CS_UK: case CS_DUTCH: case CS_FINNISH: case CS_FRENCH: case CS_FRCAN: case CS_GERMAN: case CS_ITALIAN: case CS_NORDAN: case CS_PORTUGUESE: case CS_SPANISH: case CS_SWEDISH: case CS_SWISS: /* national char mode implies not ISO 8859 */ SetCtlValue (getctlhdl (dlg_g1, chardlg), btnOff); dlg_g1 = CS_VTGRAPH; SetCtlValue (getctlhdl (dlg_g1, chardlg), btnOn); /* fall through */ case CS_USA: SetCtlValue (getctlhdl (dlg_g0, chardlg), btnOff); dlg_g0 = itemhit; SetCtlValue (getctlhdl (dlg_g0, chardlg), btnOn); break; case CS_ISOLATIN1: case CS_ISOLATIN2: case CS_ISOLATIN3: case CS_ISOLATIN4: case CS_ISOCYRILLIC: case CS_ISOARABIC: case CS_ISOGREEK: case CS_ISOHEBREW: case CS_ISOLATIN5: /* 8859 says that the lower half (G0) is straight ASCII */ SetCtlValue (getctlhdl (dlg_g0, chardlg), btnOff); dlg_g0 = CS_USA; SetCtlValue (getctlhdl (dlg_g0, chardlg), btnOn); /* fall through */ case CS_VTGRAPH: case CS_VTTECH: SetCtlValue (getctlhdl (dlg_g1, chardlg), btnOff); dlg_g1 = itemhit; SetCtlValue (getctlhdl (dlg_g1, chardlg), btnOn); break; } } } /* charsetdialog */ /****************************************************************************/ /****************************************************************************/ setradpair (rid1, rid2, bool, dlg) DialogPtr dlg; { SetCtlValue (getctlhdl (rid1, dlg), bool ? btnOn : btnOff); SetCtlValue (getctlhdl (rid2, dlg), bool ? btnOff : btnOn); } /* setradpair */ /****************************************************************************/ /* setfiledialog - enter file settings dialog. */ /****************************************************************************/ setfiledialog() { DialogPtr setfdlg; short item = RADITM_FIRST - 1; setfdlg = GetNewDialog (FILEBOXID, NILPTR, (WindowPtr) - 1); circleOK(setfdlg); filargs.filflg = filargs.fildflg; /* Use current defaults */ for (;;) { setfilflgs (item, setfdlg); /* Keep flags up to date */ setradpair (FSET_ATTEND, FSET_UNATTEND, (filargs.filflg & FIL_DODLG), setfdlg); setradpair (FSET_SUPERSEDE, FSET_NEWNAMES, (filargs.filflg & FIL_OKILL), setfdlg); SetCtlValue (getctlhdl (FSET_KEEP, setfdlg), (keep) ? btnOn : btnOff); SetCtlValue (getctlhdl (FSET_XMITTOO, setfdlg), (sendusercvdef) ? btnOn : btnOff); ModalDialog ((ModalFilterProcPtr) NILPROC, &item); switch (item) { case ok: filargs.fildflg = filargs.filflg; /* set default flags */ case cancel: DisposDialog (setfdlg); /* all done with dialog */ return; /* can go home... */ case FSET_ATTEND: case FSET_UNATTEND: filargs.filflg ^= FIL_DODLG; /* toggle flag */ break; case FSET_SUPERSEDE: case FSET_NEWNAMES: filargs.filflg ^= FIL_OKILL; /* toggle flag */ break; case FSET_KEEP: keep = !keep; break; case FSET_XMITTOO: sendusercvdef = !sendusercvdef; break; } } } /* setfiledialog */ struct launchparams { char *lnamep; short config; } lparams; char lfile[64]; /****************************************************************************/ /* handlelaunch - Handle transfer to another application. */ /* Called when "launch" selected from menu bar. */ /****************************************************************************/ handlelaunch () { OSType appltype = 'APPL'; Point where; SFReply sfr; SetPt (&where, 75, 115); SFGetFile (where, "", (FileFilterProcPtr) NILPROC, 1, &appltype, (DlgHookProcPtr) NILPROC, &sfr); if (!sfr.good) /* hit cancel, return now */ return; p2cstr (&sfr.fName); doclean (); /* about to leave, leave clean! */ strcpy (lfile, (char *) &sfr.fName); lparams.lnamep = lfile; lparams.config = 0; SetVol ((char *) 0, sfr.vRefNum); /* allow any drive */ c2pstr (lparams.lnamep); loadA0 ((char *) &lparams); Launch (); } /* handlelaunch */ #ifdef COMMENT /* These are in ckcfn2.c */ /****************************************************************************/ /****************************************************************************/ VOID fstats () { tfc += ffc; tlog(F100," end of file","",0l); tlog(F101," file characters ","",ffc); tlog(F101," communication line in ","",flci); tlog(F101," communication line out ","",flco); } /* fstats */ /****************************************************************************/ /****************************************************************************/ VOID tstats () { } /* tstats */ /* And These are in ckuusx.c */ /****************************************************************************/ /****************************************************************************/ VOID rdebu (c, i) CHAR *c; int i; { } /* rdebu */ /****************************************************************************/ /****************************************************************************/ VOID sdebu (l) int l; { } /* sdebu */ #endif /* COMMENT */ void popSerialPorts (Rect *rect, char *ret_port_name) { int n, itsID; MenuHandle theMenu; long theChoice; Point pt; CRMRecPtr crmp; CRMRec dummycrmrec; CRMSerialPtr serp; unsigned char *sp; Str255 p_port_name; int selected = 0; /* * get an id for the menu and create it. */ itsID = 0; while (itsID < 128) itsID = UniqueID('MENU'); theMenu = NewMenu(itsID,"\pxxx"); /* create the menu */ InsertMenu(theMenu,-1); /* add it to the menu list */ strcpy((char *)p_port_name, ret_port_name); c2pstr(p_port_name); /* * add the items */ crmp = &dummycrmrec; dummycrmrec.crmDeviceType = crmSerialDevice; dummycrmrec.crmDeviceID = 0; n = 1; if (NGetTrapAddress(0x8b, OSTrap) != NGetTrapAddress(0x9f,OSTrap)) { /* if ctb */ while (crmp = (CRMRecPtr)CRMSearch((QElemPtr)crmp)) { if (serp = (CRMSerialPtr)crmp->crmAttributes) { if (sp = (unsigned char *)*serp->name) { /* if current port */ if (EqualString(p_port_name, sp, false, false)) selected = n; AppendMenu(theMenu, "\p "); SetItem(theMenu, n++, sp); } } } } else { /* no ctb */ AppendMenu(theMenu, "\pPhone"); if (EqualString(p_port_name, "\pPhone", false, false)) selected = n; n++; AppendMenu(theMenu, "\pPrinter"); if (EqualString(p_port_name, "\pPrinter", false, false)) selected = n; n++; } if (selected) SetItemMark(theMenu, selected, checkMark); fixmenuwidth(theMenu, rect->right - rect->left); /* *pop it up */ pt.h = rect->left+1; pt.v = rect->top; LocalToGlobal(&pt); theChoice = PopUpMenuSelect(theMenu, pt.v, pt.h, selected); theChoice = theChoice & 0xffff; if (theChoice) { GetItem(theMenu, theChoice, p_port_name); p2cstr(p_port_name); trimstring(p_port_name); strcpy(ret_port_name, (char *)p_port_name); InvalRect(rect); /* force redraw */ } DeleteMenu(itsID); DisposeMenu(theMenu); } /* * fixmenuwidth * set minimum menu width by widening item */ void fixmenuwidth (MenuHandle themenu, int minwidth) { Str255 scratch; minwidth -= 27; GetItem(themenu, 1, scratch); if (StringWidth(scratch) >= minwidth) return; while (StringWidth(scratch) < minwidth) scratch[scratch[0]++ + 1] = ' '; SetItem(themenu, 1, scratch); } /* * doshadow * Draw shadowed frame * Also in sldef.c */ void doshadow (Rect *rect) { FrameRect(rect); MoveTo(rect->left+2, rect->bottom); /* shadow */ LineTo(rect->right, rect->bottom); LineTo(rect->right, rect->top+2); } /* modern definition of Pattern */ typedef struct { unsigned char pat[8]; } new_Pattern; /* * dotriangle * Also in sldef.c */ void dotriangle (Rect *rect) { int i; PolyHandle poly; new_Pattern black; for (i = 0; i < sizeof(black); i++) black.pat[i] = 0xff; /* ... should use qd-> */ poly = OpenPoly(); MoveTo(rect->right - 16, rect->top + 5); LineTo(rect->right - 5, rect->top + 5); LineTo(rect->right - 10, rect->top + 10); LineTo(rect->right - 16, rect->top + 5); ClosePoly(); #ifdef MPW FillPoly(poly, (ConstPatternParam)&black); #else FillPoly(poly, (Pattern *)&black); #endif KillPoly(poly); } /* * drawPortPopup * Called during ModalDialog to draw the serial port user item. */ pascal void drawPortPopup (DialogPtr dialog, short item) { char *port_string; short itemtype; Handle itemhdl; Rect itembox; GetDItem(dialog, item, &itemtype, &itemhdl, &itembox); port_string = (char *)GetWRefCon(dialog); /* get stashed string */ EraseRect(&itembox); doshadow(&itembox); dotriangle(&itembox); itembox.right -= 18; /* room for triangle */ centertext(port_string, &itembox, 12); } void centertext (char *text, Rect *rect, int texth) { int l, i, n, nlines, yoff, y, xoff, pixels, rectw; unsigned char *ss, *e, *lim; unsigned char scratch[256]; Rect copy; if (!text) return; /* copy the text */ n = strlen(text); if (n > sizeof(scratch)-1) n = sizeof(scratch)-1; bcopy(text, (char *)scratch, n); scratch[n] = '\0'; /* Find out how many lines of text we have */ ss = scratch; nlines = 1; /* account for last line */ while (*ss) if (*ss++ == '\015') nlines++; yoff = (rect->bottom - rect->top - 1 - (nlines * (texth+2))) / 2; /* -1 */ y = rect->top + yoff + texth + 2; rectw = rect->right - rect->left; ss = e = scratch; lim = &scratch[strlen((char *)scratch)]; while (e < lim) { while (*e && (*e != '\015')) e++; *e = '\0'; l = strlen((char *)ss); pixels = TextWidth(ss, 0, l); xoff = 10; /* * Truncate string if too wide for space */ if ((pixels + xoff) > rectw) { for (i = l-1; i > 0; i--) { ss[i] = 'É'; pixels = TextWidth(ss, 0, i+1); if ((pixels + xoff) < rectw) break; } l = i + 1; } MoveTo(rect->left + xoff, y-2); DrawText(ss, 0, l); ss = ++e; y += texth + 2; } } /* * trimstring * Trim trailing blanks from a string */ void trimstring (unsigned char *cp) { int n; if (*cp == ' ') return; if ((n = strlen((char *)cp)) == 0) return; cp += n - 1; while (*cp == ' ') cp--; *++cp = '\0'; } /* * Junk so Emacs will set local variables to be compatible with Mac/MPW. * Should be at end of file. * This file uses 8 * * Local Variables: * tab-width: 8 * End: */