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

  1. /* $Id: ckmutl.c,v 1.8 91/12/27 21:51:04 fdc Exp $
  2.  * $Source: /uw/mackermit/RCS/ckmutl.c,v $
  3.  *------------------------------------------------------------------
  4.  * $Log:    ckmutl.c,v $
  5.  * Revision 1.8  91/12/27  21:51:04  fdc
  6.  * Change fatal to macfatal, make all lines shorter than 80.
  7.  * 
  8.  * Revision 1.7  91/12/15  23:18:03  rick
  9.  * ut9
  10.  * 
  11.  * Revision 1.6  91/10/13  13:43:46  rick
  12.  * UT(7)
  13.  * 
  14.  * Revision 1.5  91/10/01  12:17:19  rick
  15.  * UT(5)
  16.  * 
  17.  * Revision 1.4  91/09/25  12:17:46  rick
  18.  * Command window in TE. Multiple vt100 windows for command window.
  19.  * 
  20.  * Revision 1.3  91/09/12  21:50:58  rick
  21.  * UT(3). Install on watsun
  22.  * 
  23.  * Revision 1.2  1991/09/10  22:21:51  rick
  24.  * Update to UTexas(2)
  25.  *
  26.  * Revision 1.1  1991/09/10  19:18:10  rick
  27.  * Initial revision
  28.  *
  29.  *------------------------------------------------------------------
  30.  * $Endlog$
  31.  */
  32.  
  33. /* Version 0.8(35) - Jim Noble at Planning Research Corporation, June 1987. */
  34. /* Ported to Megamax native Macintosh C compiler. */
  35. /* Edit by Frank on 20 Jun 5:25pm */
  36. /* In commdialog(), don't set parity on sio chip. */
  37. /* Edit by Bill on Apr 30 00:11 */
  38. /* use mygetitem instead of getitem, it doesn't convert from pascal to c */
  39. /* Redo handapple */
  40. /* Edit by Bill on Apr 21 17:27 */
  41. /* Try to fix meaning of TURN and TURNCH in dialog box */
  42. /* Remove version from dofiledialog dialog box */
  43.  
  44. /*
  45.  * file ckmutl.c
  46.  *
  47.  * Module of mackermit containing code for the menus and other MacIntosh
  48.  * things.
  49.  *
  50.  */
  51.  
  52. /*
  53.   Copyright (C) 1985, 1994, Trustees of Columbia University in the City of New
  54.   York.  The C-Kermit software may not be, in whole or in part, licensed or
  55.   sold for profit as a software product itself, nor may it be included in or
  56.   distributed with commercial products or otherwise distributed by commercial
  57.   concerns to their clients or customers without written permission of the
  58.   Office of Kermit Development and Distribution, Columbia University.  This
  59.   copyright notice must not be removed, altered, or obscured.
  60. */
  61.  
  62. #include <ctype.h>        /* For isdigit */
  63. #include <StdArg.h>
  64. #include <CRMSerialDevices.h>
  65. #include <CommResources.h>
  66. #include "ckcdeb.h"
  67. #include "ckcasc.h"
  68. #include "ckcker.h"
  69. #include "ckmdef.h"        /* General Mac defs */
  70. #include "ckmres.h"        /* Resource file defs */
  71. #include "ckmasm.h"        /* Assembler code */
  72. #include "ckmcon.h"        /* defines, etc. for terminal emulator */
  73. #include "ckmptp.h"        /* ckm* Prototypes */
  74.  
  75. extern MenuHandle menus[];
  76.  
  77. #ifdef COMMENT
  78. /* Now found in ckuusx.c */
  79. /****************************************************************************/
  80. /*  B L D L E N  --  Make length-encoded copy of string  */
  81. /****************************************************************************/
  82. char *
  83. bldlen (str, dest)
  84. char *str;
  85. char *dest;
  86. {
  87.     int len;
  88.  
  89.     len = strlen (str);
  90.     *dest = tochar (len);
  91.     strcpy (dest + 1, str);
  92.     return (dest + len + 1);
  93. }                /* bldlen */
  94. #endif /* COMMENT */
  95.  
  96.  
  97. /****************************************************************************/
  98. /*  S S E T G E N  --  Construct a generic command into a target string  */
  99. /****************************************************************************/
  100. void
  101. ssetgen (char *stor, char type, char *arg1, char *arg2, char *arg3)
  102. {
  103.     char *upstr, *cp;
  104.  
  105.     cp = stor;
  106.     *cp++ = type;
  107.     *cp = '\0';
  108.     if (*arg1 != '\0') {
  109.     upstr = bldlen (arg1, cp);
  110.     if (*arg2 != '\0') {
  111.         upstr = bldlen (arg2, upstr);
  112.         if (*arg3 != '\0')
  113.         bldlen (arg3, upstr);
  114.     }
  115.     }
  116.     debug (F110, "setgen", stor, 0);
  117. }                /* ssetgen */
  118.  
  119.  
  120. #ifdef COMMENT
  121. /*  S E T G E N  --  Construct a generic command  */
  122. /* in ckuusx.c */
  123.  
  124. CHAR
  125. #ifdef CK_ANSIC
  126. setgen(char type,char * arg1, char * arg2, char * arg3)
  127. #else
  128. setgen(type,arg1,arg2,arg3) char type, *arg1, *arg2, *arg3;
  129. #endif /* CK_ANSIC */
  130. /* setgen */ {
  131.     char *upstr, *cp;
  132.     static char sg_cmdstr[256];            /* Place to build generic command */
  133.  
  134.     cp = sg_cmdstr;
  135.     *cp++ = type;
  136.     *cp = NUL;
  137.     if (*arg1 != NUL) {
  138.     upstr = bldlen(arg1,cp);
  139.     if (*arg2 != NUL) {
  140.         upstr = bldlen(arg2,upstr);
  141.         if (*arg3 != NUL) bldlen(arg3,upstr);
  142.     }
  143.     }
  144.     cmarg = sg_cmdstr;
  145.     debug(F110,"setgen",cmarg,0);
  146.  
  147.     return('g');
  148. }
  149. #endif /* COMMENT */
  150.  
  151.  
  152. /****************************************************************************/
  153. /* printerr - display error message and number in standard error box. */
  154. /****************************************************************************/
  155. printerr (str, err)
  156. char *str;
  157. int err;
  158. {
  159.     int i;
  160.     char error[10];
  161.  
  162.     if (str == NULL) str = "";
  163.     if (str[0] == 0)
  164.       str = "Unspecified Kermit application error";
  165.     debug (F111,"ERROR: ", str, err);    /* put error in debug log */
  166.     if (err) {            /* Err=0 signals message only */
  167.     for (i = 0; i < 10; error[i++] = '\0');    /* Make string null
  168.                          * terminated */
  169.     NumToString ((long) err, error);    /* Convert err number */
  170.     ParamText (c2p_tmp(str), error, "", "");
  171.                 /* Insert strings into error box */
  172.     } else {
  173.     ParamText (c2p_tmp(str), "", "", "");
  174.     }
  175.     
  176.     if (!server)        /* Display alert only if not server mode */
  177.       NoteAlert (ALERT_ERROR, (ModalFilterProcPtr) NILPROC);
  178. } /* printerr */
  179.  
  180.  
  181. /*
  182.  * printfalert
  183.  * Printf to an alert box.
  184.  */
  185. void printfalert (char *format, ...)
  186. {
  187.     char string[512];
  188.     va_list ap;
  189.  
  190.     va_start(ap, format);
  191.     vsprintf(string, format, ap);
  192.     va_end(ap);
  193.  
  194.     printerr(string, 0);
  195. }
  196.  
  197.  
  198.  
  199.  
  200.  
  201. /****************************************************************************/
  202. /* macfatal - close file, and exit to shell.    */
  203. /****************************************************************************/
  204. VOID macfatal (str, err)
  205. char *str;
  206. int err;
  207. {
  208.     int i;
  209.     char error[10];
  210.  
  211.     if (err) {            /* Err=0 signals message only */
  212.     for (i = 0; i < 10; error[i++] = '\0');    /* Make string null
  213.                          * terminated */
  214.     NumToString ((long) err, error);    /* Convert err number */
  215.     ParamText ("\pFatal error:", c2p_tmp(str), error, "");
  216.                 /* Insert strings into
  217.                              * error box */
  218.     } else
  219.     ParamText ("\pFatal error:", c2p_tmp(str), "", "");
  220.  
  221.     if (!server)        /* Display alert only if not server mode */
  222.     StopAlert (ALERT_ERROR, (ModalFilterProcPtr) NILPROC);
  223.  
  224.     /*
  225.      * terminate NOW!  The heap might be scrambled, so don't try to clean
  226.      * anything up.
  227.      */
  228.     ExitToShell ();
  229. }                /* macfatal */
  230.  
  231.  
  232.  
  233. /****************************************************************************/
  234. /* SetStrText - Set the string value in the dialog's edit or static text
  235.    item.    */
  236. /****************************************************************************/
  237. SetStrText (item, s, dlg)
  238. int item;
  239. StringPtr s;        /* a Pascal string */
  240. DialogPtr dlg;
  241. {
  242.     short itemtype;
  243.     Rect itemrect;
  244.     Handle itemhdl;
  245.  
  246.     GetDItem (dlg, item, &itemtype, &itemhdl, &itemrect);
  247.     if ((itemtype & editText) || (itemtype & statText))
  248.     SetIText (itemhdl, s);
  249.     else
  250.     printerr ("Bad item in SetStrText: ", item);
  251. }                /* SetStrText */
  252.  
  253.  
  254.  
  255. /****************************************************************************/
  256. /* SetNumText - Set the numeric value in the dialog's edit or static text
  257.    item.    */
  258. /****************************************************************************/
  259. SetNumText (item, val, dlg)
  260. int item;
  261. int val;
  262. DialogPtr dlg;
  263. {
  264.     unsigned char itembuf[10];
  265.  
  266.     NumToString ((long) val, itembuf);
  267.     SetStrText (item, itembuf, dlg);
  268. }                /* SetNumText */
  269.  
  270. /*PWP************************************************************************/
  271. /* circleOK - Circle the default button for a dialog (since the dialog manager
  272.  * doesn't do this for us.
  273.  *
  274.  * cleaned up as per USENET suggestion by Keith Rollin, Apple
  275.  */
  276. /****************************************************************************/
  277. circleOK(dlg)
  278. DialogPtr dlg;
  279. {
  280.     short itemtype;
  281.     Rect itemrect;
  282.     Handle itemhdl;
  283.     GrafPtr oldport;
  284.     PenState oldpen;
  285.     int i;
  286.  
  287.     GetDItem (dlg, 1, &itemtype, &itemhdl, &itemrect);
  288.     if (itemtype != (ctrlItem | btnCtrl))
  289.     return;        /* it wasn't a button */
  290.  
  291.     GetPort(&oldport);
  292.     SetPort(dlg);
  293.     GetPenState(&oldpen);
  294.     PenNormal();
  295.     
  296.     InsetRect(&itemrect,-4,-4);
  297.     i = (itemrect.bottom - itemrect.top) / 2;
  298.     PenSize(3,3);    /* see IM 1, page 407 (dialog manager) */
  299.     FrameRoundRect(&itemrect,i,i);
  300.     SetPenState(&oldpen);
  301.     SetPort(oldport);
  302. }                /* SetStrText */
  303.  
  304. /*PWP************************************************************************
  305.  * c2p_tmp - copy s to static temporary storage and convert it to a Pascal
  306.  * string.  Used for passing strings to many toolbox routines.
  307.  ****************************************************************************/
  308.  
  309. StringPtr
  310. c2p_tmp(char *s)
  311. {
  312.     static char foo[256];
  313.     
  314.     strncpy (foo, s, 256);
  315.     foo[255] = '\0';    /* just in case */
  316.     c2pstr(foo);
  317.     return ((StringPtr) foo);
  318. }
  319.  
  320. StringPtr
  321. c2p_tmp2(char *s)
  322. {
  323.     static char foo[256];
  324.     
  325.     strncpy (foo, s, 256);
  326.     foo[255] = '\0';    /* just in case */
  327.     c2pstr(foo);
  328.     return ((StringPtr) foo);
  329. }
  330.  
  331. char *
  332. p2c_tmp (StringPtr s)
  333. {
  334.     static char foo[256];
  335.     
  336.     pstring_copy ((StringPtr) foo, (StringPtr) s);
  337.     p2cstr(foo);
  338.     foo[255] = '\0';    /* just in case */
  339.     return (foo);
  340. }
  341.  
  342. char *
  343. p2c_tmp2 (StringPtr s)
  344. {
  345.     static char foo[256];
  346.     
  347.     pstring_copy ((StringPtr) foo, (StringPtr) s);
  348.     p2cstr(foo);
  349.     foo[255] = '\0';    /* just in case */
  350.     return (foo);
  351. }
  352.  
  353. void
  354. pstring_copy (StringPtr d, StringPtr s)
  355. {
  356.     register int i;
  357.     register char *sp, *dp;
  358.     
  359.     i = Length(s);
  360.     sp = (char *) s;
  361.     dp = (char *) d;
  362.     
  363.     *dp++ = *sp++;            /* copy length */
  364.     while (i-- > 0)
  365.         *dp++ = *sp++;            /* copy the characters */
  366. }
  367.  
  368. void
  369. enable_fkeys(enable)
  370. int enable;
  371. {
  372.     /* unsigned char *sde_addr = (unsigned char *) ScrDmpEnb; */
  373.     /* I don't know why this is needed, but ScrDmpEnb is 0x2f8 */
  374.     
  375.     if (enable)
  376.         *((unsigned char *) 0x2f8) = scrdmpenabled;    /* enable FKEYs */
  377.     else
  378.         *((unsigned char *) 0x2f8) = scrdmpdisabled; /* disable FKEYs */
  379. }
  380.  
  381.  
  382. extern char *protv;        /* protocol version number */
  383. extern char *versio;        /* C-Kermit version number */
  384.  
  385. extern int tsecs;        /* Seconds for transaction */
  386. extern long filcnt,        /* Number of files in transaction */
  387.     flci,            /* Characters from line, current file */
  388.     flco,            /* Chars to line, current file  */
  389.     tlci,            /* Chars from line in transaction */
  390.     tlco,            /* Chars to line in transaction */
  391.     ffc,            /* Chars to/from current file */
  392.     tfc;            /* Chars to/from files in transaction */
  393.  
  394. extern char *dftty;
  395. extern char default_port_name[];
  396.  
  397. /****************************************************************************/
  398. /* aboutKermit - Display the about kermit dialog box, and some transaction */
  399. /*                    statistics */
  400. /****************************************************************************/
  401. aboutKermit ()
  402. {
  403.     Handle kversion;
  404.     short itemhit;
  405.     DialogPtr aboutDlg;
  406.     THz curZone;
  407.  
  408.     aboutDlg = GetNewDialog (ABOUTID, NILPTR, (WindowPtr) - 1);
  409.     circleOK(aboutDlg);
  410.     
  411.     kversion = GetResource (ApplCreator, 0);    /* get version information */
  412.     HLock (kversion);        /* prevent movement */
  413.     /* p2cstr (*kversion);        /* convert to C string */
  414.  
  415.     SetStrText (AB_VERS, (StringPtr) *kversion, aboutDlg);
  416.     SetStrText (AB_PROV, c2p_tmp(versio), aboutDlg);    /* was protv */
  417.     
  418. /* #ifdef COMMENT */
  419. /* take these out for the real version */
  420. SetStrText (AB_COPY, "\pThis is a DEVELOPMENT Test copy of Kermit.", aboutDlg);
  421. SetStrText (AB_CPY2, "\p", aboutDlg);
  422. SetStrText (AB_CPY3, "\p", aboutDlg);
  423. SetStrText (AB_BUGS, "\pSend bug reports to: kermit@columbia.edu", 
  424.         aboutDlg);
  425. /* #endif *//* COMMENT */
  426.  
  427.     ModalDialog ((ModalFilterProcPtr) NILPROC, &itemhit);
  428.     DisposDialog (aboutDlg);
  429.  
  430.     /* c2pstr (*kversion);    /* convert back to Pascal string */
  431.     HUnlock (kversion);        /* undo previous HLock */
  432.     curZone = GetZone();    /* as per John Norstad's (Disinfectant) */
  433.     SetZone(HandleZone(kversion));    /* "Toolbox Gotchas" */
  434.     ReleaseResource(kversion);    /* no longer needed */
  435.     SetZone(curZone);
  436. }                /* aboutKermit */
  437.  
  438. /****************************************************************************/
  439. /* show_stats -- show some statistics about the file transfer speed */
  440. /****************************************************************************/
  441. show_stats ()
  442. {
  443.     short itemhit;
  444.     DialogPtr statDlg;
  445.     long lx;
  446.  
  447.     statDlg = GetNewDialog (STATBOXID, NILPTR, (WindowPtr) - 1);
  448.     circleOK(statDlg);
  449.     
  450.     SetNumText (ST_TSEC, tsecs, statDlg);
  451.     SetNumText (ST_TLCI, tlci, statDlg);
  452.     SetNumText (ST_TLCO, tlco, statDlg);
  453.     SetNumText (ST_TFC, tfc, statDlg);
  454.     if (tsecs > 0)
  455.     SetNumText (ST_EBAUD, ((tfc*10)/tsecs), statDlg);
  456.     else
  457.     SetStrText (ST_EBAUD, (StringPtr) "n/a", statDlg);
  458.  
  459.     if (tsecs > 0) {
  460.     lx = (tfc * 10l) / tsecs;
  461.     SetNumText (ST_EBAUD, lx, statDlg);
  462.     if (speed > 0) {
  463.         lx = (lx * 100l) / speed;
  464.         SetNumText (ST_EEFF, lx, statDlg);
  465.     } else {
  466.         SetStrText (ST_EEFF, (StringPtr) "n/a", statDlg);
  467.     }
  468.     } else {
  469.     SetStrText (ST_EBAUD, (StringPtr) "n/a", statDlg);
  470.     SetStrText (ST_EEFF, (StringPtr) "n/a", statDlg);
  471.     }
  472.  
  473.  
  474.     ModalDialog ((ModalFilterProcPtr) NILPROC, &itemhit);
  475.     DisposDialog (statDlg);
  476. }                /* aboutKermit */
  477.  
  478.  
  479. /****************************************************************************/
  480. /* handapple - Handle the apple menu, either running a desk accessory */
  481. /*               or calling a routine to display information about our */
  482. /*               program.  Use the practice of */
  483. /*               checking for available memory, and saving the GrafPort */
  484. /*               described in the DA Manager's Guide. */
  485. /****************************************************************************/
  486. handapple (accitem)
  487. int accitem;
  488. {
  489.     GrafPtr savePort;        /* Where to save current port */
  490.     Handle acchdl;        /* holds ptr to accessory resource */
  491.     Str255 accname;        /* string holds accessory name */
  492.     long accsize;        /* holds size of the acc + stack */
  493.  
  494.     if (accitem == 1) {        /* tell about Kermit? */
  495.     aboutKermit ();        /* yes, "about kermit" please */
  496.     return;            /* and return */
  497.     }
  498.     GetItem (menus[APPL_MENU], accitem, accname); /* get the pascal name */
  499.     SetResLoad (FALSE);        /* don't load into memory */
  500.  
  501.     /* figure out acc size + heap */
  502.     accsize = SizeResource (GetNamedResource ((ResType) 'DRVR', accname));
  503.     acchdl = NewHandle (accsize);    /* try for a block this size */
  504.     SetResLoad (TRUE);        /* reset flag for rsrc mgr */
  505.     if (acchdl == NIL) {    /* able to get a chunk? */
  506.     printerr ("Not enough memory for accessory. Requires: ",
  507.           (int) accsize);
  508.     return;            /* failed */
  509.     }
  510.     DisposHandle (acchdl);    /* get rid of this handle */
  511.     GetPort (&savePort);    /* save the current port */
  512.     OpenDeskAcc (accname);    /* run desk accessory */
  513.     SetPort (savePort);        /* and put back our port */
  514. }                /* handapple */
  515.  
  516. /********************************************************************
  517.  * Stuff to handle and update the Font menu
  518.  */
  519.  
  520. setup_font_menu()
  521. {
  522.     int i, nmitems;
  523.     long m_sz;
  524.     char m_item_buf[256];
  525.     char cur_font_name[256];
  526.     struct termw *termw = ttermw;
  527.     
  528.     GetFontName (termw->current_font, cur_font_name);
  529.  
  530.     /* First, the font sizes */
  531.     for (i = 0; i < BIGSZ_FONT; i++) {
  532.         /* get the size number */
  533.     GetItem(menus[FONT_MENU], i, m_item_buf);
  534.         StringToNum(m_item_buf, &m_sz);
  535.     
  536.     /* if this is an availiable size, outline font it, else normal */
  537.     SetItemStyle (menus[FONT_MENU], i,
  538.               (RealFont(termw->current_font, m_sz)
  539.                ? outline : normal));
  540.     CheckItem (menus[FONT_MENU], i, (m_sz == ttermw->current_size));
  541.     }
  542.     
  543.     /* Now the font names */
  544.     nmitems = CountMItems(menus[FONT_MENU]);
  545.     for (i = BIGSZ_FONT+2; i <= nmitems; i++) {
  546.     GetItem(menus[FONT_MENU], i, m_item_buf);
  547.  
  548.     /* if the font number corrisponding to this menu entry is the
  549.        current font, check it, else don't */
  550.     CheckItem(menus[FONT_MENU], i,
  551.         EqualString(m_item_buf, cur_font_name, FALSE, TRUE));
  552.     }
  553. }
  554.  
  555. change_current_size (struct termw *termw, int item)
  556. {
  557.     char m_item_buf[256];
  558.     long m_sz;
  559.  
  560.     GetItem(menus[FONT_MENU], item, m_item_buf);
  561.     StringToNum(m_item_buf, &m_sz);
  562.  
  563.     if ((m_sz > 4) && (m_sz < 72)) {
  564.         termw->current_size = m_sz;    /* change the current size */
  565.     term_new_font(termw);
  566.     
  567.     /* doesn't change #lines, but size of a line has changed */
  568.     grow_term_to(termw,termw->screensize);
  569.     }    
  570. }
  571.  
  572. change_current_font (struct termw *termw, int item)
  573. {
  574.     char m_item_buf[256];
  575.     short fn;
  576.  
  577.     GetItem(menus[FONT_MENU], item, m_item_buf);
  578.  
  579.     GetFNum(m_item_buf, &fn);
  580.     
  581.     if (fn != 0) {
  582.     termw->current_font = fn;
  583.     term_new_font(termw);
  584.  
  585.     /* doesn't change #lines, but size of a line has changed */
  586.     grow_term_to(termw,termw->screensize);
  587.     }
  588. }
  589.  
  590.  
  591.  
  592. typedef struct {
  593.     unsigned kerval;
  594.     unsigned int macval;
  595. }   KMTBL;
  596.  
  597. KMTBL kerbaudtbl[] = {
  598.     {300, baud300},
  599.     {600, baud600},
  600.     {1200, baud1200},
  601.     {1800, baud1800},
  602.     {2400, baud2400},
  603.     {4800, baud4800},
  604.     {7200, baud7200},
  605.     {9600, baud9600},
  606.     {19200, baud19200},    
  607.     {38400, 2},        /* this is a guess */
  608.     {57600, baud57600}
  609. };
  610.  
  611. #define kerbaudlen ((sizeof (kerbaudtbl))/(sizeof (KMTBL)))
  612.  
  613. #define PARITY_ETC    (noParity+stop10+data8)
  614.  
  615. int
  616. setserial (irefnum, orefnum, b, p)
  617. int irefnum, orefnum, b, p;
  618. #pragma unused (p)
  619. {
  620.     int err, mb, i;
  621.     ParamBlockRec cpb;
  622.     
  623.     if ((b < 300) || (b > 57600))
  624.         return (0);        /* was a garbage value */
  625.  
  626.     if (!irefnum)        /* port not open */
  627.         return (1);        /* pretend that we succeeded */
  628.     mb = baud9600;
  629.  
  630.   found_speed:
  631.  
  632. /*
  633.  * PWP: if the Mac does parity in hardware, then Even parity seems to
  634.  * not work correctly, so we have Kermit do parity in
  635.  * software.
  636.  */
  637.  
  638. /*
  639.  * Apple Q&A says that I should reset the output side first, then input, then
  640.  * do handshake and set buffer
  641.  */
  642.     err = SerReset (orefnum, mb + PARITY_ETC);    /* reset serial output port */
  643.     if (err != noErr) {
  644.     printerr ("setserial couldn't set port (output): ", err);
  645.     return (0);
  646.     }
  647.  
  648.     err = SerReset (irefnum, mb + PARITY_ETC);    /* reset serial input port */
  649.     if (err != noErr) {
  650.     printerr ("setserial couldn't set port (input): ", err);
  651.     return (0);
  652.     }
  653.  
  654.     cpb.cntrlParam.csCode = 13;            /* set baud rate */
  655.     cpb.cntrlParam.csParam[0] = (unsigned short) b;
  656.     cpb.cntrlParam.ioCRefNum = orefnum;
  657.     err = PBControl (&cpb, FALSE);
  658.     if (err != noErr) {
  659.     printerr ("setserial couldn't set port (input): ", err);
  660.     return (0);
  661.     }
  662.     cpb.cntrlParam.csCode = 13;            /* set baud rate */
  663.     cpb.cntrlParam.csParam[0] = (unsigned short) b;
  664.     cpb.cntrlParam.ioCRefNum = irefnum;
  665.     err = PBControl (&cpb, FALSE);
  666.     if (err != noErr) {
  667.     printerr ("setserial couldn't set port (input): ", err);
  668.     return (0);
  669.     }
  670.     speed = b;            /* set global kermit value */
  671.     
  672.     return (1);    /* we did it */
  673. }                /* setserial */
  674.  
  675. RESSERTBL commbaudtbl[] = {
  676.     {CR_BAUD300, 300},
  677.     {CR_BAUD600, 600},
  678.     {CR_BAUD1200, 1200},
  679.     {CR_BAUD1800, 1800},
  680.     {CR_BAUD2400, 2400},
  681.     {CR_BAUD3600, 3600},
  682.     {CR_BAUD4800, 4800},
  683.     {CR_BAUD7200, 7200},
  684.     {CR_BAUD9600, 9600},
  685.     {CR_BAUD14400, 14400},
  686.     {CR_BAUD19200, 19200},
  687.     {CR_BAUD28800, 28800},
  688.     {CR_BAUD38400, 38400},
  689.     {CR_BAUD57600, 57600},
  690. #ifdef NOT_YET
  691.     {CR_BAUD76800, 76800},
  692.     {CR_BAUD115200, 115200},
  693. #endif
  694.     {0, 0}
  695. };
  696.  
  697. RESSERTBL commparitytbl[] = {
  698.     {CR_PARODD, KPARITY_ODD},
  699.     {CR_PAREVEN, KPARITY_EVEN},
  700.     {CR_PARMARK, KPARITY_MARK},
  701.     {CR_PARSPACE, KPARITY_SPACE},
  702.     {CR_PARNONE, KPARITY_NONE},
  703.     {0, 0}
  704. };
  705.  
  706.  
  707.  
  708. /****************************************************************************/
  709. /* rshilite - hilite the radio control item matching the given */
  710. /*          serial value, and disable all other control items in the */
  711. /*          resource-serial table. */
  712. /****************************************************************************/
  713. rshilite (servalue, rstbl, dlg)
  714. int servalue;
  715. RESSERTBL rstbl[];
  716. DialogPtr dlg;
  717. {
  718.     int i;
  719.     short itemtype;
  720.     Rect itembox;
  721.     Handle itemhdl;
  722.  
  723.     for (i = 0; rstbl[i].resval != 0; i++) {
  724.     GetDItem (dlg, rstbl[i].resval, &itemtype, &itemhdl, &itembox);
  725.  
  726.     if (itemtype != ctrlItem + radCtrl)
  727.         printerr ("rshilite called with non radio control: ",
  728.               rstbl[i].resval);
  729.  
  730.     if (rstbl[i].serval == servalue)
  731.         SetCtlValue ((ControlHandle) itemhdl, btnOn);
  732.     else
  733.         SetCtlValue ((ControlHandle) itemhdl, btnOff);
  734.     }
  735. }                /* rshilite */
  736.  
  737.  
  738.  
  739. /****************************************************************************/
  740. /****************************************************************************/
  741. rsreference (rstbl, value, dlg)
  742. RESSERTBL rstbl[];
  743. DialogPtr dlg;
  744. int value;
  745. {
  746.     int i;
  747.     short itemtype;
  748.     Rect itembox;
  749.     Handle itemhdl;
  750.  
  751.     for (i = 0; rstbl[i].resval != 0; i++) {
  752.     GetDItem (dlg, rstbl[i].resval, &itemtype, &itemhdl, &itembox);
  753.     SetCRefCon ((ControlHandle) itemhdl, (long) value);
  754.     }
  755. }                /* rsreference */
  756.  
  757.  
  758.  
  759. /****************************************************************************/
  760. /* rsserval - given a resource ID for a control and a resource-serial */
  761. /*              table, return the serial value. */
  762. /****************************************************************************/
  763. int
  764. rsserval (resvalue, rstbl)
  765. int resvalue;
  766. RESSERTBL rstbl[];
  767. {
  768.     int i;
  769.  
  770.     for (i = 0; rstbl[i].resval != 0; i++)
  771.     if (rstbl[i].resval == resvalue)
  772.         return (rstbl[i].serval);
  773.  
  774.     macfatal ("rsserval didn't find: ", resvalue);
  775.     return (0);            /* never get here */
  776. }                /* rsserval */
  777.  
  778.  
  779.  
  780. #define CREF_BAUD 1
  781. #define CREF_PARITY 2
  782.  
  783. extern int drop_dtr;
  784.  
  785. /****************************************************************************/
  786. /* commdialog - enter communications setup dialog. */
  787. /****************************************************************************/
  788. commdialog ()
  789. {
  790.     DialogPtr commdlg;
  791.     long i;
  792.     short itemhit;
  793.     short itemtype;
  794.     int dlgspeed;
  795.     int dlgparity;
  796.     int dlgflow;
  797.     int dlgdtr;
  798.     int dlgdtrin, dlgctsout;
  799.     Handle itemhdl;
  800.     Rect itembox;
  801.     char new_port_name[256];
  802.     extern int fCTS, fDTR;
  803.     GrafPtr save_port;
  804.  
  805.     GetPort(&save_port);
  806.     if ((commdlg = GetNewDialog (COMMBOXID, NILPTR, (WindowPtr) - 1)) == 0)
  807.     return;
  808.     SetPort(commdlg);
  809.     circleOK(commdlg);
  810.     
  811.     dlgspeed = speed;        /* initialize to current global */
  812.     dlgparity = parity;        /* values of baud and parity */
  813.     dlgflow = flow;
  814.     dlgctsout = fCTS;
  815.     dlgdtrin = fDTR;
  816.     dlgdtr = drop_dtr;
  817.  
  818.     rshilite (dlgspeed, commbaudtbl, commdlg);    /* hilite our baud */
  819.     rshilite (dlgparity, commparitytbl, commdlg); /* hilite our parity */
  820.     SetCtlValue (getctlhdl (CR_XONXOFF, commdlg), /* hilite our flow */
  821.          dlgflow ? btnOn : btnOff);
  822.  
  823.     SetCtlValue (getctlhdl (CR_DROPDTR, commdlg), /* hilite our DTR */
  824.          dlgdtr ? btnOn : btnOff);
  825.     SetCtlValue (getctlhdl (CR_DTRIN, commdlg), dlgdtrin ? btnOn : btnOff);
  826.     SetCtlValue (getctlhdl (CR_CTSOUT, commdlg), dlgctsout ? btnOn : btnOff);
  827.  
  828. /* for all baud and parity controls set the reference value for each
  829.  * control to the resource-serial table address so we can manipulate
  830.  * these controls easily during the dialog processing.
  831.  */
  832.  
  833.     rsreference (commbaudtbl, CREF_BAUD, commdlg); /* setup control ref's */
  834.     rsreference (commparitytbl, CREF_PARITY, commdlg);
  835.  
  836.     /*
  837.      * Set dialog refcon so that drawPortPopup can find the string to draw.
  838.      * Set drawing routine for popup menu.
  839.      */
  840.     strcpy(new_port_name, dftty);
  841.     SetWRefCon(commdlg, (long)new_port_name); /* Stash the csp */
  842.     GetDItem(commdlg, CR_PORT, &itemtype, &itemhdl, &itembox);
  843.     SetDItem(commdlg, CR_PORT, itemtype, (Handle)drawPortPopup, &itembox);
  844.  
  845.     for (;;) {
  846.     ModalDialog ((ModalFilterProcPtr) NILPROC, &itemhit);
  847.  
  848.     switch (itemhit) {
  849.       case OKBtn:
  850.         drop_dtr = dlgdtr;
  851.         /* if port changed */
  852.         if ((innum == 0) || (strcmp(new_port_name, dftty) != 0)) {
  853.         Boolean old_port_was_open = (innum != 0);
  854.         dlgdtr = drop_dtr;
  855.         drop_dtr = 1;    /* so we don't confuse AppleTalk */
  856.         port_close();
  857.         drop_dtr = dlgdtr;
  858.         port_open(new_port_name);
  859.         if (innum == 0)    {    /* if open failed */
  860.             if (old_port_was_open)
  861.               port_open(dftty);    /* re-open old port */
  862.             strcpy(new_port_name, dftty);
  863.             GetDItem(commdlg, CR_PORT, &itemtype, &itemhdl, &itembox);
  864.             InvalRect(&itembox);
  865.             break;        /* keep doing dialog */
  866.         }
  867.         strcpy(default_port_name, new_port_name);
  868.         dftty = default_port_name;
  869.         }
  870.         parity = dlgparity;
  871.         flow = dlgflow;
  872.         fDTR = dlgdtrin;
  873.         fCTS = dlgctsout;
  874.         if (!setserial (innum, outnum, dlgspeed, KPARITY_NONE))
  875.         break;    /* keep doing dialog */
  876.         if (sershake(flow))
  877.         break;
  878.         /* else fall thru */
  879.  
  880.       case QuitBtn:
  881.         DisposDialog (commdlg);    /* finished with the dialog */
  882.         SetPort(save_port);
  883.         return;        /* so return */
  884.  
  885.       case CR_XONXOFF:    /* do flow control */
  886.         dlgflow = !dlgflow;
  887.         SetCtlValue (getctlhdl (CR_XONXOFF, commdlg),
  888.              dlgflow ? btnOn : btnOff);
  889.         break;
  890.  
  891.       case CR_DROPDTR:    /* drop DTR on exit */
  892.         dlgdtr = !dlgdtr;
  893.         SetCtlValue (getctlhdl (CR_DROPDTR, commdlg),
  894.              dlgdtr ? btnOn : btnOff);
  895.         break;
  896.  
  897.  
  898.       case CR_PORT:
  899.         GetDItem(commdlg, CR_PORT, &itemtype, &itemhdl, &itembox);
  900.         popSerialPorts(&itembox, new_port_name);
  901.         break;
  902.  
  903.       case CR_DTRIN:
  904.         dlgdtrin = !dlgdtrin;
  905.         SetCtlValue (getctlhdl (CR_DTRIN, commdlg), 
  906.              dlgdtrin ? btnOn : btnOff);
  907.         break;
  908.  
  909.       case CR_CTSOUT:
  910.         dlgctsout = !dlgctsout;
  911.         SetCtlValue (getctlhdl (CR_CTSOUT, commdlg), 
  912.              dlgctsout ? btnOn : btnOff);
  913.         break;
  914.  
  915.       default:        /* default is radio button */
  916.         GetDItem (commdlg, itemhit, &itemtype, &itemhdl, &itembox);
  917.         i = GetCRefCon ((ControlHandle) itemhdl);
  918.  
  919.         switch (i) {
  920.           case CREF_BAUD:
  921.         dlgspeed = rsserval (itemhit, commbaudtbl);
  922.         rshilite (dlgspeed, commbaudtbl, commdlg);
  923.         break;
  924.  
  925.           case CREF_PARITY:
  926.         dlgparity = rsserval (itemhit, commparitytbl);
  927.         rshilite (dlgparity, commparitytbl, commdlg);
  928.         break;
  929.  
  930.           default:
  931.         printerr ("Item has no refcon: ", itemhit);
  932.         }
  933.     }
  934.     }
  935. }                /* commdialog */
  936.  
  937. RESSERTBL protoblktbl[] = {    /* block check:  */
  938.     {PR_BLK1, 1},        /* type 1 */
  939.     {PR_BLK2, 2},        /* type 2 */
  940.     {PR_BLK3, 3},        /* type 3 */
  941.     {0, 0}
  942. };
  943.  
  944. #define KTURN_NONE 128        /* indicate no handshake */
  945.  
  946. RESSERTBL protohstbl[] = {    /* hand shake: */
  947.     {PR_HSBELL, 7},        /* bell = 7 */
  948.     {PR_HSCR, 15},        /* cr = 15 */
  949.     {PR_HSESC, 33},        /* esc = 33  */
  950.     {PR_HSLF, 12},        /* lf = 12 */
  951.     {PR_HSNONE, KTURN_NONE},    /* none = 128 */
  952.     {PR_HSXON, XON},        /* xon = 21 */
  953.     {PR_HSXOFF, 23},        /* xoff = 23 */
  954.     {0, 0}
  955. };
  956.  
  957. RESSERTBL protointtbl[] = {    /* edit text integer items: */
  958.     {PR_INPADN, 0},        /* inbound pad count edit text */
  959.     {PR_OUTPADN, 1},        /* outbound pad count edit text */
  960.     {PR_INTIMEO, 2},        /* inbound secs timeout edit text */
  961.     {PR_OUTTIMEO, 3},        /* outbound secs timeout edit text */
  962.     {PR_INPKTLEN, 4},        /* inbound packet length edit text */
  963.     {PR_OUTPKTLEN, 5},        /* outbound packet length edit text */
  964.     {PR_WINSIZ, 6},        /* sliding window size */
  965.     {0, 0}
  966. };
  967.  
  968. int *protointcells[] = {    /* parallel to above table! */
  969.     &mypadn,            /* inbound pad count */
  970.     &npad,            /* outbound pad count */
  971.     &timint,            /* inbound timeout in secs */
  972.     &rtimo,            /* outbound timeout in secs */
  973.     &urpsiz,            /* user requested inbound pkt length */
  974.     &spsiz,            /* inbound pkt length */
  975.     &wslotr            /* sliding window size requested */
  976. };
  977.  
  978. RESSERTBL protochrtbl[] = {    /* edit text character items: */
  979.     {PR_INPADC, 0},        /* inbound pad chr edit text */
  980.     {PR_OUTPADC, 1},        /* outbound pad chr */
  981.     {PR_INEOP, 2},        /* inbound end of packet edit text */
  982.     {PR_OUTEOP, 3},        /* outbound end of packet edit text */
  983.     {PR_INSOP, 4},        /* inbound start of pkt edit text */
  984.     {PR_OUTSOP, 5},        /* outbound start of pkt edit text */
  985.     {0, 0}
  986. };
  987.  
  988. char *protochrcells[] = {    /* parallel to above table! */
  989.     &mypadc,            /* inbound pad char */
  990.     &padch,            /* outbound pad char */
  991.     &eol,            /* inbound end of packet char */
  992.     &seol,            /* outbound end of pkt char */
  993.     &stchr,            /* inbound start of pkt char */
  994.     &mystch            /* outbound start of packet char */
  995. };
  996.  
  997. /****************************************************************************/
  998. /* etgetcc - Set edit text paramter from dialog window to an ASCII */
  999. /*             control character value.  Returns FALSE if value is */
  1000. /*             illegal, warning has been displayed. */
  1001. /****************************************************************************/
  1002. int
  1003. etgetcc (item, dlg, chrcell)
  1004. DialogPtr dlg;
  1005. int item;
  1006. char *chrcell;
  1007. {
  1008.     short itemtype;
  1009.     int i;
  1010.     long rslt;
  1011.     Rect itemrect;
  1012.     Handle itemhdl;
  1013.     char itembuf[256];
  1014.     char c;
  1015.  
  1016.     GetDItem (dlg, item, &itemtype, &itemhdl, &itemrect);
  1017.     if (itemtype != editText) {
  1018.     printerr ("etsetcc item not editText: ", item);
  1019.     return (FALSE);
  1020.     }
  1021.     GetIText (itemhdl, itembuf);
  1022.     /* p2cstr(itembuf);            /* convert to c string */
  1023.     for (i = 1; i < Length(itembuf); i++) {    /* check for digits */
  1024.     c = itembuf[i];
  1025.     if (!isdigit (c)) {
  1026.         printerr ("Field contains a non numeric, code ", c);
  1027.         return (FALSE);
  1028.     }
  1029.     }
  1030.     StringToNum (itembuf, &rslt);
  1031.     if ((rslt > 037) && (rslt != 0177)) {
  1032.     printerr ("Not in ASCII control range: ", (int) rslt);
  1033.     return (FALSE);
  1034.     }
  1035.     *chrcell = (char) rslt;
  1036.     return (TRUE);
  1037. }                /* etgetcc */
  1038.  
  1039.  
  1040.  
  1041. /****************************************************************************/
  1042. /* etgetnum - Set edit text paramet from dialog to numeric cell. */
  1043. /*              Returns FALSE if value is non numeric or not in range */
  1044. /*              in which case an error message is printed. */
  1045. /****************************************************************************/
  1046. int
  1047. etgetnum (item, dlg, intcell)
  1048. DialogPtr dlg;
  1049. int item;
  1050. int *intcell;
  1051. {
  1052.     short itemtype;
  1053.     int i;
  1054.     long rslt;
  1055.     Rect itemrect;
  1056.     Handle itemhdl;
  1057.     char itembuf[256];
  1058.     char c;
  1059.  
  1060.     GetDItem (dlg, item, &itemtype, &itemhdl, &itemrect);
  1061.     if (itemtype != editText) {
  1062.     printerr ("etsetnum item not editText: ", item);
  1063.     return (FALSE);
  1064.     }
  1065.     GetIText (itemhdl, itembuf);
  1066.  
  1067.     for (i = 1; i < Length(itembuf); i++) {    /* check for digits */
  1068.     c = itembuf[i];
  1069.     if (!isdigit (c)) {
  1070.         printerr ("Field contains a non numeric, code ", c);
  1071.         return (FALSE);
  1072.     }
  1073.     }
  1074.     StringToNum (itembuf, &rslt);
  1075.  
  1076.     /* check inbound packet length */
  1077.     /* MAXRP-8 is for the rest of the header (MARK, SEQ, TYPE, etc.) */
  1078.     if ((item == PR_INPKTLEN) && (rslt > MAXRP-8)) {
  1079.     printerr ("Sorry, the maximum receive packet length is ", MAXRP-8);
  1080.     return (FALSE);
  1081.     }
  1082.     /* check outbound packet length */
  1083.     if ((item == PR_OUTPKTLEN) && (rslt > MAXSP)) {
  1084.     printerr ("Sorry, the maximum send packet length is ", MAXSP);
  1085.     return (FALSE);
  1086.     }
  1087.     *intcell = (int) rslt;
  1088.     return (TRUE);
  1089. }                /* etgetnum */
  1090.  
  1091.  
  1092.  
  1093. #define PREF_BLKCHK 1
  1094. #define PREF_HNDSHK 2
  1095.  
  1096. /****************************************************************************/
  1097. /* protodialog - enter protocol setup dialog. */
  1098. /****************************************************************************/
  1099. protodialog ()
  1100. {
  1101.     DialogPtr protoDialog;
  1102.     long i;
  1103.     short itemhit;
  1104.     short itemtype;
  1105.     int dlgval;
  1106.     int dlgint;
  1107.     int dlgbctr;
  1108.     int dlgturnch;
  1109.     Handle itemhdl;
  1110.     Rect itembox;
  1111.     char dlgchr;
  1112.  
  1113.     protoDialog = GetNewDialog (PROTOBOXID, NILPTR, (WindowPtr) - 1);
  1114.     circleOK(protoDialog);
  1115.     
  1116.     dlgbctr = bctr;        /* init local block check */
  1117.     dlgturnch = turnch;        /* handshake */
  1118.     if (!turn)            /* no turn character? */
  1119.     dlgturnch = KTURN_NONE;    /* indicate none */
  1120.  
  1121.     /* for all button controls set the reference value */
  1122.     rsreference (protohstbl, PREF_HNDSHK, protoDialog);
  1123.     rsreference (protoblktbl, PREF_BLKCHK, protoDialog);
  1124.  
  1125.     /* for each button controls, hilite the current setting */
  1126.     rshilite (dlgturnch, protohstbl, protoDialog); /* hilite our hand shake */
  1127.     rshilite (dlgbctr, protoblktbl, protoDialog); /* hilite our block check */
  1128.  
  1129.     /* for each edit text item, set current value in edit text */
  1130.     for (i = 0; protochrtbl[i].resval != 0; i++)
  1131.     SetNumText (protochrtbl[i].resval,
  1132.             (int) *protochrcells[i], protoDialog);
  1133.  
  1134.     for (i = 0; protointtbl[i].resval != 0; i++)
  1135.     SetNumText (protointtbl[i].resval,
  1136.             *protointcells[i], protoDialog);
  1137.  
  1138.     for (;;) {
  1139.     ModalDialog ((ModalFilterProcPtr) NILPROC, &itemhit);
  1140.  
  1141.     switch (itemhit) {
  1142.       case OKBtn:        /* finish up */
  1143.         turnch = dlgturnch;    /* set global handshake */
  1144.         turn = (turnch == KTURN_NONE) ? FALSE : TRUE; /* set turn */
  1145.         bctr = dlgbctr;    /* set block type check */
  1146.  
  1147.         for (i = 0; protochrtbl[i].resval != 0; i++) /* set chr vals */
  1148.         if (!etgetcc (protochrtbl[i].resval, protoDialog,
  1149.                   protochrcells[i]))
  1150.             macfatal ("During OKBtn etgetcc failed!", (int) i);
  1151.  
  1152.         for (i = 0; protointtbl[i].resval != 0; i++) /* set int vals */
  1153.         if (!etgetnum (protointtbl[i].resval, protoDialog,
  1154.                    protointcells[i]))
  1155.             macfatal ("During OKBtn etgetnum failed!", (int) i);
  1156.  
  1157.         if (wslotr < 1) wslotr = 1;
  1158.         if (wslotr > 1) {
  1159.             swcapr = 1;
  1160. #ifdef COMMENT
  1161.             if ((urpsiz * wslotr) > BIGRBUFSIZ) {
  1162.             urpsiz = BIGRBUFSIZ / wslotr - 1;
  1163.             printerr (\
  1164. "Window size * packet length too big, packet length reset to ", urpsiz);
  1165.             }
  1166. #endif /* COMMENT */
  1167.         } else {
  1168.             swcapr = 0;
  1169.         }
  1170.         /* fall through... */
  1171.         
  1172.       case QuitBtn:    /* fall in from above */
  1173.         DisposDialog (protoDialog);    /* finished with the dialog */
  1174.         return;        /* return */
  1175.  
  1176.       case PR_INPADC:
  1177.       case PR_OUTPADC:
  1178.       case PR_INEOP:
  1179.       case PR_OUTEOP:
  1180.       case PR_INSOP:
  1181.       case PR_OUTSOP:
  1182.         if (!etgetcc (itemhit, protoDialog, &dlgchr)) {
  1183.         /* get back tbl idx */
  1184.         dlgval = rsserval (itemhit, protochrtbl);
  1185.         dlgval = (int) *protochrcells[dlgval];    /* now cell value */
  1186.         SetNumText (itemhit, dlgval, protoDialog); /* and reset it */
  1187.         SelIText(protoDialog, itemhit, 0, 32767);
  1188.         }
  1189.         break;
  1190.  
  1191.       case PR_INPADN:
  1192.       case PR_OUTPADN:
  1193.       case PR_INTIMEO:
  1194.       case PR_OUTTIMEO:
  1195.       case PR_INPKTLEN:
  1196.       case PR_OUTPKTLEN:
  1197.       case PR_WINSIZ:
  1198.         if (!etgetnum (itemhit, protoDialog, &dlgint)) {
  1199.         /* get back tbl idx */
  1200.         dlgval = rsserval (itemhit, protointtbl);
  1201.         dlgval = *protointcells[dlgval];    /* now cell value */
  1202.         SetNumText (itemhit, dlgval, protoDialog); /* and reset it */
  1203.         SelIText(protoDialog, itemhit, 0, 32767);
  1204.         }
  1205.         break;
  1206.  
  1207.       default:
  1208.         GetDItem (protoDialog, itemhit, &itemtype, &itemhdl, &itembox);
  1209.  
  1210.         if (itemtype != ctrlItem + radCtrl)    /* must be radio button */
  1211.         macfatal ("Not radio button", itemhit);
  1212.  
  1213.         i = GetCRefCon ((ControlHandle) itemhdl);
  1214.  
  1215.         if (i == PREF_BLKCHK) {
  1216.         dlgbctr = rsserval (itemhit, protoblktbl);
  1217.         rshilite (dlgbctr, protoblktbl, protoDialog);
  1218.  
  1219.         } else if (i == PREF_HNDSHK) {
  1220.         dlgturnch = rsserval (itemhit, protohstbl);
  1221.         rshilite (dlgturnch, protohstbl, protoDialog);
  1222.  
  1223.         } else
  1224.         printerr ("radio item has bad refcon: ", itemhit);
  1225.  
  1226.         break;        /* all done with radio buttons */
  1227.     }
  1228.     }
  1229. }                /* protodialog */
  1230.  
  1231.  
  1232.  
  1233. #define TR_FIRST TR_AUTOWRAP
  1234. #define TR_LAST TR_BLINKC
  1235.  
  1236. /****************************************************************************/
  1237. /****************************************************************************/
  1238. termsetdialog (struct termw *termw)
  1239. {
  1240.     DialogPtr termdlg;
  1241.     short itemhit;
  1242.     short i;
  1243.     int dlgint, t_numlines;
  1244.     Boolean ts[TR_LAST + 1];
  1245.  
  1246.     termdlg = GetNewDialog (TERMINALBOXID, NILPTR, (WindowPtr) - 1);
  1247.     circleOK(termdlg);
  1248.     
  1249.     ts[TR_AUTOWRAP] = termw->autowrap;
  1250.     ts[TR_AUTOREPT] = termw->autorepeat;
  1251.     ts[TR_INVERT] = termw->screeninvert;
  1252.     ts[TR_SMOOTH] = termw->smoothscroll;
  1253.     ts[TR_AUTOLF] = termw->newline;
  1254.     ts[TR_LOCLECHO] = duplex;
  1255.     ts[TR_TRANSP] = !termw->dispcontchar;    /* PWP */
  1256.     ts[TR_BLOCKC] = termw->blockcursor;
  1257.     ts[TR_MOUSE] = termw->mouse_arrows;
  1258.     ts[TR_VISBELL] = termw->visible_bell;
  1259.     ts[TR_EIGHTBIT] = termw->eightbit_disp;
  1260.     ts[TR_BLINKC] = termw->blinkcursor;
  1261.     t_numlines = termw->screensize;
  1262.  
  1263.     /* set the ctl values according to the flags */
  1264.     for (i = TR_FIRST; i <= TR_LAST; i++)
  1265.     SetCtlValue (getctlhdl(i, termdlg), (ts[i]) ? btnOn : btnOff);
  1266.  
  1267.     SetNumText(TR_NUMLINES,t_numlines,termdlg);
  1268.     SelIText(termdlg, TR_NUMLINES, 0, 32767);
  1269.     
  1270.     for (;;) {
  1271.     ModalDialog ((ModalFilterProcPtr) NILPROC, &itemhit);
  1272.  
  1273.     switch (itemhit) {
  1274.       case OKBtn:        /* finish up */
  1275.         termw->autowrap = ts[TR_AUTOWRAP];
  1276.         termw->autorepeat = ts[TR_AUTOREPT];
  1277.         termw->smoothscroll = ts[TR_SMOOTH];
  1278.         termw->newline = ts[TR_AUTOLF];
  1279.         duplex = ts[TR_LOCLECHO];
  1280.         termw->dispcontchar = !ts[TR_TRANSP];
  1281.         termw->visible_bell = ts[TR_VISBELL];
  1282.         termw->eightbit_disp = ts[TR_EIGHTBIT];
  1283.         if ((termw->blockcursor != ts[TR_BLOCKC]) ||
  1284.         (termw->blinkcursor != ts[TR_BLINKC]) ||
  1285.         (ts[TR_MOUSE])) {
  1286.         cursor_erase (termw);
  1287.         termw->blockcursor = ts[TR_BLOCKC];
  1288.         termw->blinkcursor = ts[TR_BLINKC];
  1289.         termw->mouse_arrows = ts[TR_MOUSE];
  1290.         cursor_draw(termw);
  1291.     }
  1292.         if (termw->screeninvert != ts[TR_INVERT])
  1293.         invert_term (termw);
  1294.         grow_term_to(termw, t_numlines);
  1295.  
  1296.       case QuitBtn:    /* fall in from above */
  1297.         DisposDialog (termdlg);    /* finished with the dialog */
  1298.         return;        /* return */
  1299.  
  1300.       case TR_RESETBTN:
  1301.         term_reset(termw);        /* reset the terminal emulator */
  1302.         break;
  1303.         
  1304.       case TR_AUTOWRAP:
  1305.       case TR_AUTOREPT:
  1306.       case TR_INVERT:
  1307.       case TR_SMOOTH:
  1308.       case TR_AUTOLF:
  1309.       case TR_LOCLECHO:
  1310.       case TR_TRANSP:
  1311.       case TR_BLOCKC:
  1312.       case TR_MOUSE:
  1313.       case TR_VISBELL:
  1314.       case TR_EIGHTBIT:
  1315.       case TR_BLINKC:
  1316.         ts[itemhit] = !ts[itemhit];
  1317.         SetCtlValue (getctlhdl (itemhit, termdlg),
  1318.                  (ts[itemhit]) ? btnOn : btnOff);
  1319.         break;
  1320.  
  1321.       case TR_NUMLINES:
  1322.         if (!etgetnum (TR_NUMLINES, termdlg, &dlgint)) {
  1323.         SetNumText (TR_NUMLINES, t_numlines, termdlg);
  1324.         SelIText(termdlg, TR_NUMLINES, 0, 32767);
  1325.         } else {
  1326.         if (dlgint > MAX_SCREENSIZE) {
  1327.             printerr ("Sorry, the maximum screen length is",
  1328.               MAX_SCREENSIZE);
  1329.             SetNumText (TR_NUMLINES, t_numlines, termdlg);
  1330.             SelIText(termdlg, TR_NUMLINES, 0, 32767);
  1331.         } else {
  1332.             t_numlines = dlgint;
  1333.         }
  1334.         }
  1335.         break;
  1336.     }
  1337.     }
  1338. }                /* termsetdialog */
  1339.  
  1340. #define CS_AFIRST    CS_USA
  1341. #define CS_ALAST    CS_SWISS
  1342. #define CS_BFIRST    CS_ISOLATIN1
  1343. #define CS_BLAST    CS_ISOLATIN5
  1344.  
  1345. /****************************************************************************/
  1346. /****************************************************************************/
  1347. charsetdialog (struct termw *termw)
  1348. {
  1349.     DialogPtr chardlg;
  1350.     short itemhit;
  1351.     short i;
  1352.     int dlg_g0 = CS_USA, dlg_g1 = CS_VTGRAPH;
  1353.  
  1354.     chardlg = GetNewDialog (CHARBOXID, NILPTR, (WindowPtr) - 1);
  1355.     circleOK(chardlg);
  1356.     
  1357.     if (termw->nat_char_mode)
  1358.         dlg_g0 = termw->nat_set + CS_USA - USA_NAT;
  1359.     else
  1360.     dlg_g0 = CS_USA;    /* Should handle GRAF_SET here too */
  1361.  
  1362.     switch (termw->graphicsinset[1]) {
  1363.       case LAT1_SET:
  1364.       case DECINTL_SET:
  1365.     dlg_g1 = CS_ISOLATIN1;
  1366.     break;
  1367.  
  1368.       case LAT2_SET:
  1369.     dlg_g1 = CS_ISOLATIN2;
  1370.     break;
  1371.  
  1372.       case LAT3_SET:
  1373.     dlg_g1 = CS_ISOLATIN3;
  1374.     break;
  1375.  
  1376.       case LAT4_SET:
  1377.     dlg_g1 = CS_ISOLATIN4;
  1378.     break;
  1379.  
  1380.       case LATCYR_SET:
  1381.     dlg_g1 = CS_ISOCYRILLIC;
  1382.     break;
  1383.  
  1384.       case LATARAB_SET:
  1385.     dlg_g1 = CS_ISOARABIC;
  1386.     break;
  1387.  
  1388.       case LATGREEK_SET:
  1389.     dlg_g1 = CS_ISOGREEK;
  1390.     break;
  1391.  
  1392.       case LATHEBREW_SET:
  1393.     dlg_g1 = CS_ISOHEBREW;
  1394.     break;
  1395.  
  1396.       case LAT5_SET:
  1397.     dlg_g1 = CS_ISOLATIN5;
  1398.     break;
  1399.  
  1400.       case GRAF_SET:
  1401.     dlg_g1 = CS_VTGRAPH;
  1402.     break;
  1403.  
  1404.       case TECH_SET:
  1405.     dlg_g1 = CS_VTTECH;
  1406.     break;
  1407.  
  1408.     }
  1409.  
  1410.     for (i = CS_AFIRST; i <= CS_ALAST; i++)
  1411.     SetCtlValue (getctlhdl (i, chardlg), btnOff);
  1412.     SetCtlValue (getctlhdl (dlg_g0, chardlg), btnOn);
  1413.     for (i = CS_BFIRST; i <= CS_BLAST; i++)
  1414.     SetCtlValue (getctlhdl (i, chardlg), btnOff);
  1415.     SetCtlValue (getctlhdl (dlg_g1, chardlg), btnOn);
  1416.     
  1417.     for (;;) {
  1418.  
  1419.     ModalDialog ((ModalFilterProcPtr) NILPROC, &itemhit);
  1420.  
  1421.     switch (itemhit) {
  1422.       case OKBtn:        /* finish up */
  1423.         switch (dlg_g0) {
  1424.           case CS_USA:
  1425.         termw->nat_set = USA_NAT;
  1426.         termw->graphicsinset[0] = ASCII_SET;
  1427.         /* but we leave the setting of termw->nat_char_mode as is */
  1428.         break;
  1429.  
  1430.           case CS_UK:
  1431.           case CS_DUTCH:
  1432.           case CS_FINNISH:
  1433.           case CS_FRENCH:
  1434.           case CS_FRCAN:
  1435.           case CS_GERMAN:
  1436.           case CS_ITALIAN:
  1437.           case CS_NORDAN:
  1438.           case CS_PORTUGUESE:
  1439.           case CS_SPANISH:
  1440.           case CS_SWEDISH:
  1441.           case CS_SWISS:
  1442.         termw->graphicsinset[0] = ASCII_SET;
  1443.         termw->nat_set = dlg_g0 - CS_USA + USA_NAT;
  1444.         termw->nat_char_mode = TRUE;
  1445.         break;
  1446.         }
  1447.         switch (dlg_g1) {
  1448.           case CS_ISOLATIN1:
  1449.         termw->graphicsinset[1] = LAT1_SET;
  1450.         termw->nat_char_mode = FALSE;
  1451.         break;
  1452.  
  1453.           case CS_ISOLATIN2:
  1454.         termw->graphicsinset[1] = LAT2_SET;
  1455.         termw->nat_char_mode = FALSE;
  1456.         break;
  1457.  
  1458.           case CS_ISOLATIN3:
  1459.         termw->graphicsinset[1] = LAT3_SET;
  1460.         termw->nat_char_mode = FALSE;
  1461.         break;
  1462.  
  1463.           case CS_ISOLATIN4:
  1464.         termw->graphicsinset[1] = LAT4_SET;
  1465.         termw->nat_char_mode = FALSE;
  1466.         break;
  1467.  
  1468.           case CS_ISOCYRILLIC:
  1469.         termw->graphicsinset[1] = LATCYR_SET;
  1470.         termw->nat_char_mode = FALSE;
  1471.         break;
  1472.  
  1473.           case CS_ISOARABIC:
  1474.         termw->graphicsinset[1] = LATARAB_SET;
  1475.         termw->nat_char_mode = FALSE;
  1476.         break;
  1477.  
  1478.           case CS_ISOGREEK:
  1479.         termw->graphicsinset[1] = LATGREEK_SET;
  1480.         termw->nat_char_mode = FALSE;
  1481.         break;
  1482.  
  1483.           case CS_ISOHEBREW:
  1484.         termw->graphicsinset[1] = LATHEBREW_SET;
  1485.         termw->nat_char_mode = FALSE;
  1486.         break;
  1487.  
  1488.           case CS_ISOLATIN5:
  1489.         termw->graphicsinset[1] = LAT5_SET;
  1490.         termw->nat_char_mode = FALSE;
  1491.         break;
  1492.  
  1493.           case CS_VTGRAPH:
  1494.         termw->graphicsinset[1] = GRAF_SET;
  1495.         break;
  1496.  
  1497.           case CS_VTTECH:
  1498.         termw->graphicsinset[1] = TECH_SET;
  1499.         break;
  1500.         }
  1501.         set_char_map(termw);    /* change the display translate table */
  1502.         /* fall through */
  1503.         
  1504.       case QuitBtn:    /* fall in from above */
  1505.         DisposDialog (chardlg);    /* finished with the dialog */
  1506.         return;        /* return */
  1507.  
  1508.       case CS_UK:
  1509.       case CS_DUTCH:
  1510.       case CS_FINNISH:
  1511.       case CS_FRENCH:
  1512.       case CS_FRCAN:
  1513.       case CS_GERMAN:
  1514.       case CS_ITALIAN:
  1515.       case CS_NORDAN:
  1516.       case CS_PORTUGUESE:
  1517.       case CS_SPANISH:
  1518.       case CS_SWEDISH:
  1519.       case CS_SWISS:
  1520.         /* national char mode implies not ISO 8859 */
  1521.         SetCtlValue (getctlhdl (dlg_g1, chardlg), btnOff);
  1522.         dlg_g1 = CS_VTGRAPH;
  1523.         SetCtlValue (getctlhdl (dlg_g1, chardlg), btnOn);
  1524.         /* fall through */
  1525.       case CS_USA:
  1526.         SetCtlValue (getctlhdl (dlg_g0, chardlg), btnOff);
  1527.         dlg_g0 = itemhit;
  1528.         SetCtlValue (getctlhdl (dlg_g0, chardlg), btnOn);
  1529.         break;
  1530.         
  1531.       case CS_ISOLATIN1:
  1532.       case CS_ISOLATIN2:
  1533.       case CS_ISOLATIN3:
  1534.       case CS_ISOLATIN4:
  1535.       case CS_ISOCYRILLIC:
  1536.       case CS_ISOARABIC:
  1537.       case CS_ISOGREEK:
  1538.       case CS_ISOHEBREW:
  1539.       case CS_ISOLATIN5:
  1540.         /* 8859 says that the lower half (G0) is straight ASCII */
  1541.         SetCtlValue (getctlhdl (dlg_g0, chardlg), btnOff);
  1542.         dlg_g0 = CS_USA;
  1543.         SetCtlValue (getctlhdl (dlg_g0, chardlg), btnOn);
  1544.         /* fall through */
  1545.       case CS_VTGRAPH:
  1546.       case CS_VTTECH:
  1547.         SetCtlValue (getctlhdl (dlg_g1, chardlg), btnOff);
  1548.         dlg_g1 = itemhit;
  1549.         SetCtlValue (getctlhdl (dlg_g1, chardlg), btnOn);
  1550.         break;
  1551.  
  1552.     }
  1553.     }
  1554. }                /* charsetdialog */
  1555.  
  1556.  
  1557.  
  1558. /****************************************************************************/
  1559. /****************************************************************************/
  1560. setradpair (rid1, rid2, bool, dlg)
  1561. DialogPtr dlg;
  1562. {
  1563.     SetCtlValue (getctlhdl (rid1, dlg), bool ? btnOn : btnOff);
  1564.     SetCtlValue (getctlhdl (rid2, dlg), bool ? btnOff : btnOn);
  1565. }                /* setradpair */
  1566.  
  1567.  
  1568.  
  1569. /****************************************************************************/
  1570. /* setfiledialog - enter file settings dialog. */
  1571. /****************************************************************************/
  1572. setfiledialog() {
  1573.     DialogPtr setfdlg;
  1574.     short item = RADITM_FIRST - 1;
  1575.  
  1576.     setfdlg = GetNewDialog (FILEBOXID, NILPTR, (WindowPtr) - 1);
  1577.     circleOK(setfdlg);
  1578.     filargs.filflg = filargs.fildflg;    /* Use current defaults */
  1579.  
  1580.     for (;;) {
  1581.     setfilflgs (item, setfdlg);    /* Keep flags up to date */
  1582.  
  1583.     setradpair (FSET_ATTEND, FSET_UNATTEND,
  1584.             (filargs.filflg & FIL_DODLG), setfdlg);
  1585.     setradpair (FSET_SUPERSEDE, FSET_NEWNAMES,
  1586.             (filargs.filflg & FIL_OKILL), setfdlg);
  1587.     SetCtlValue (getctlhdl (FSET_KEEP, setfdlg),
  1588.              (keep) ? btnOn : btnOff);
  1589.     SetCtlValue (getctlhdl (FSET_XMITTOO, setfdlg),
  1590.              (sendusercvdef) ? btnOn : btnOff);
  1591.  
  1592.     ModalDialog ((ModalFilterProcPtr) NILPROC, &item);
  1593.     switch (item) {
  1594.       case ok:
  1595.         filargs.fildflg = filargs.filflg; /* set default flags */
  1596.  
  1597.       case cancel:
  1598.         DisposDialog (setfdlg);    /* all done with dialog */
  1599.         return;            /* can go home... */
  1600.  
  1601.       case FSET_ATTEND:
  1602.       case FSET_UNATTEND:
  1603.         filargs.filflg ^= FIL_DODLG; /* toggle flag */
  1604.         break;
  1605.  
  1606.       case FSET_SUPERSEDE:
  1607.       case FSET_NEWNAMES:
  1608.         filargs.filflg ^= FIL_OKILL; /* toggle flag */
  1609.         break;
  1610.  
  1611.       case FSET_KEEP:
  1612.         keep = !keep;
  1613.         break;
  1614.         
  1615.       case FSET_XMITTOO:
  1616.         sendusercvdef = !sendusercvdef;
  1617.         break;
  1618.     }
  1619.     }
  1620. } /* setfiledialog */
  1621.  
  1622.  
  1623.  
  1624. struct launchparams {
  1625.     char *lnamep;
  1626.     short config;
  1627. }   lparams;
  1628. char lfile[64];
  1629.  
  1630.  
  1631.  
  1632. /****************************************************************************/
  1633. /* handlelaunch - Handle transfer to another application. */
  1634. /*                Called when "launch" selected from menu bar. */
  1635. /****************************************************************************/
  1636. handlelaunch ()
  1637. {
  1638.     OSType appltype = 'APPL';
  1639.     Point where;
  1640.     SFReply sfr;
  1641.  
  1642.     SetPt (&where, 75, 115);
  1643.     SFGetFile (where, "", (FileFilterProcPtr) NILPROC, 1, &appltype,
  1644.            (DlgHookProcPtr) NILPROC, &sfr);
  1645.  
  1646.     if (!sfr.good)        /* hit cancel, return now */
  1647.     return;
  1648.  
  1649.     p2cstr (&sfr.fName);
  1650.  
  1651.     doclean ();        /* about to leave, leave clean! */
  1652.  
  1653.     strcpy (lfile, (char *) &sfr.fName);
  1654.     lparams.lnamep = lfile;
  1655.     lparams.config = 0;
  1656.     SetVol ((char *) 0, sfr.vRefNum);    /* allow any drive */
  1657.     c2pstr (lparams.lnamep);
  1658.  
  1659.     loadA0 ((char *) &lparams);
  1660.     Launch ();
  1661. }                /* handlelaunch */
  1662.  
  1663.  
  1664. #ifdef COMMENT
  1665. /* These are in ckcfn2.c */
  1666. /****************************************************************************/
  1667. /****************************************************************************/
  1668. VOID fstats ()
  1669. {
  1670.     tfc += ffc;
  1671.     tlog(F100," end of file","",0l);
  1672.     tlog(F101,"  file characters        ","",ffc);
  1673.     tlog(F101,"  communication line in  ","",flci);
  1674.     tlog(F101,"  communication line out ","",flco);
  1675. }                /* fstats */
  1676.  
  1677.  
  1678.  
  1679. /****************************************************************************/
  1680. /****************************************************************************/
  1681. VOID tstats ()
  1682. {
  1683. }                /* tstats */
  1684.  
  1685. /* And These are in ckuusx.c */
  1686. /****************************************************************************/
  1687. /****************************************************************************/
  1688. VOID rdebu (c, i)
  1689.     CHAR *c;
  1690.     int i;
  1691. {
  1692. }                /* rdebu */
  1693.  
  1694.  
  1695.  
  1696. /****************************************************************************/
  1697. /****************************************************************************/
  1698. VOID sdebu (l)
  1699. int l;
  1700. {
  1701. }                /* sdebu */
  1702. #endif /* COMMENT */
  1703.  
  1704. void popSerialPorts (Rect *rect, char *ret_port_name) {   
  1705.     int n, itsID;
  1706.     MenuHandle theMenu;
  1707.     long theChoice;
  1708.     Point pt;
  1709.     CRMRecPtr crmp;
  1710.     CRMRec dummycrmrec;
  1711.     CRMSerialPtr serp;
  1712.     unsigned char *sp;
  1713.     Str255 p_port_name;
  1714.     int selected = 0;
  1715.     /* 
  1716.      * get an id for the menu and create it. 
  1717.      */
  1718.     itsID = 0;
  1719.     while (itsID < 128)
  1720.       itsID = UniqueID('MENU');
  1721.     theMenu = NewMenu(itsID,"\pxxx");    /* create the menu */
  1722.     InsertMenu(theMenu,-1);        /* add it to the menu list */
  1723.     
  1724.     strcpy((char *)p_port_name, ret_port_name);
  1725.     c2pstr(p_port_name);
  1726.     /* 
  1727.      * add the items 
  1728.      */
  1729.     crmp = &dummycrmrec;
  1730.     dummycrmrec.crmDeviceType = crmSerialDevice;
  1731.     dummycrmrec.crmDeviceID = 0;
  1732.     n = 1;
  1733.  
  1734.     if (NGetTrapAddress(0x8b, OSTrap) != NGetTrapAddress(0x9f,OSTrap)) {
  1735.     /* if ctb */
  1736.     while (crmp = (CRMRecPtr)CRMSearch((QElemPtr)crmp)) {
  1737.         if (serp = (CRMSerialPtr)crmp->crmAttributes) {
  1738.         if (sp = (unsigned char *)*serp->name) {
  1739.             /* if current port */
  1740.             if (EqualString(p_port_name, sp, false, false))
  1741.               selected = n;
  1742.             AppendMenu(theMenu, "\p ");
  1743.             SetItem(theMenu, n++, sp);
  1744.         }
  1745.         }
  1746.     }
  1747.     } else {                /* no ctb */
  1748.     AppendMenu(theMenu, "\pPhone");
  1749.     if (EqualString(p_port_name, "\pPhone", false, false))
  1750.       selected = n;
  1751.     n++;
  1752.     AppendMenu(theMenu, "\pPrinter");
  1753.     if (EqualString(p_port_name, "\pPrinter", false, false))
  1754.       selected = n;
  1755.     n++;
  1756.     }
  1757.     if (selected)
  1758.       SetItemMark(theMenu, selected, checkMark);
  1759.     
  1760.     fixmenuwidth(theMenu, rect->right - rect->left);
  1761.     /* 
  1762.      *pop it up 
  1763.      */
  1764.     pt.h = rect->left+1;
  1765.     pt.v = rect->top;
  1766.     LocalToGlobal(&pt);
  1767.     theChoice = PopUpMenuSelect(theMenu, pt.v, pt.h, selected);
  1768.     theChoice = theChoice & 0xffff;
  1769.     if (theChoice) {
  1770.     GetItem(theMenu, theChoice, p_port_name);
  1771.     p2cstr(p_port_name);
  1772.     trimstring(p_port_name);
  1773.     strcpy(ret_port_name, (char *)p_port_name);
  1774.     InvalRect(rect);        /* force redraw */
  1775.     }
  1776.     DeleteMenu(itsID);
  1777.     DisposeMenu(theMenu);
  1778. }
  1779.  
  1780. /*
  1781.  * fixmenuwidth
  1782.  * set minimum menu width by widening item
  1783.  */
  1784. void fixmenuwidth (MenuHandle themenu, int minwidth) {
  1785.     Str255 scratch;
  1786.     
  1787.     minwidth -= 27;
  1788.     GetItem(themenu, 1, scratch);
  1789.     if (StringWidth(scratch) >= minwidth)
  1790.       return;
  1791.     while (StringWidth(scratch) < minwidth)
  1792.       scratch[scratch[0]++ + 1] = ' ';
  1793.     SetItem(themenu, 1, scratch);
  1794. }
  1795.  
  1796. /*
  1797.  * doshadow
  1798.  * Draw shadowed frame
  1799.  * Also in sldef.c
  1800.  */
  1801. void doshadow (Rect *rect) {
  1802.     FrameRect(rect);
  1803.     MoveTo(rect->left+2, rect->bottom);    /* shadow */
  1804.     LineTo(rect->right, rect->bottom);
  1805.     LineTo(rect->right, rect->top+2);
  1806. }
  1807.  
  1808. /* modern definition of Pattern */
  1809. typedef struct {
  1810.     unsigned char pat[8];
  1811. } new_Pattern;
  1812.  
  1813. /*
  1814.  * dotriangle
  1815.  * Also in sldef.c
  1816.  */
  1817. void dotriangle (Rect *rect) {
  1818.     int i;
  1819.     PolyHandle poly;
  1820.     new_Pattern black;
  1821.     
  1822.     for (i = 0; i < sizeof(black); i++)
  1823.     black.pat[i] = 0xff;        /* ... should use qd-> */
  1824.  
  1825.     poly = OpenPoly();
  1826.     MoveTo(rect->right - 16, rect->top + 5);
  1827.     LineTo(rect->right - 5, rect->top + 5);
  1828.     LineTo(rect->right - 10, rect->top + 10);
  1829.     LineTo(rect->right - 16, rect->top + 5);
  1830.     ClosePoly();
  1831. #ifdef MPW
  1832.     FillPoly(poly, (ConstPatternParam)&black);
  1833. #else
  1834.     FillPoly(poly, (Pattern *)&black);
  1835. #endif
  1836.     KillPoly(poly);
  1837. }
  1838.     
  1839. /*
  1840.  * drawPortPopup
  1841.  * Called during ModalDialog to draw the serial port user item.
  1842.  */
  1843. pascal void drawPortPopup (DialogPtr dialog, short item) {
  1844.     char *port_string;
  1845.     short itemtype;
  1846.     Handle itemhdl;
  1847.     Rect itembox;
  1848.  
  1849.     GetDItem(dialog, item, &itemtype, &itemhdl, &itembox);
  1850.     port_string = (char *)GetWRefCon(dialog); /* get stashed string */
  1851.  
  1852.     EraseRect(&itembox);
  1853.     doshadow(&itembox);
  1854.     dotriangle(&itembox);
  1855.     itembox.right -= 18;        /* room for triangle */
  1856.  
  1857.     centertext(port_string, &itembox, 12);
  1858. }
  1859.  
  1860. void centertext (char *text, Rect *rect, int texth) {
  1861.     int l, i, n, nlines, yoff, y, xoff, pixels, rectw;
  1862.     unsigned char *ss, *e, *lim;
  1863.     unsigned char scratch[256];
  1864.     Rect copy;
  1865.     
  1866.     if (!text)
  1867.       return;
  1868.     
  1869.     /* copy the text */
  1870.     n = strlen(text);
  1871.     if (n > sizeof(scratch)-1)
  1872.       n = sizeof(scratch)-1;
  1873.     bcopy(text, (char *)scratch, n);
  1874.     scratch[n] = '\0';
  1875.  
  1876.     /* Find out how many lines of text we have */
  1877.     ss = scratch;
  1878.     nlines = 1;                /* account for last line */
  1879.     while (*ss)
  1880.       if (*ss++ == '\015')
  1881.     nlines++;
  1882.  
  1883.     yoff = (rect->bottom - rect->top - 1 - (nlines * (texth+2))) / 2; /* -1 */
  1884.     y = rect->top + yoff + texth + 2;
  1885.     rectw = rect->right - rect->left;
  1886.     
  1887.     ss = e = scratch;
  1888.     lim = &scratch[strlen((char *)scratch)];
  1889.     while (e < lim) {
  1890.     while (*e && (*e != '\015'))
  1891.       e++;
  1892.     *e = '\0';
  1893.     l = strlen((char *)ss);
  1894.     pixels = TextWidth(ss, 0, l);
  1895.     xoff = 10;
  1896.     /*
  1897.      * Truncate string if too wide for space
  1898.      */
  1899.     if ((pixels + xoff) > rectw) {
  1900.         for (i = l-1; i > 0; i--) {
  1901.         ss[i] = '╔';
  1902.         pixels = TextWidth(ss, 0, i+1);
  1903.         if ((pixels + xoff) < rectw)
  1904.           break;
  1905.         }
  1906.         l = i + 1;
  1907.     }
  1908.     MoveTo(rect->left + xoff, y-2);
  1909.     DrawText(ss, 0, l);
  1910.     ss = ++e;
  1911.     y += texth + 2;
  1912.     }
  1913. }
  1914.  
  1915. /*
  1916.  * trimstring
  1917.  * Trim trailing blanks from a string
  1918.  */
  1919. void trimstring (unsigned char *cp) {
  1920.     int n;
  1921.     
  1922.     if (*cp == ' ')
  1923.       return;
  1924.     if ((n = strlen((char *)cp)) == 0)
  1925.       return;
  1926.     cp += n - 1;
  1927.     while (*cp == ' ')
  1928.       cp--;
  1929.     *++cp = '\0';
  1930. }
  1931. /*
  1932.  * Junk so Emacs will set local variables to be compatible with Mac/MPW.
  1933.  * Should be at end of file.
  1934.  * This file uses 8
  1935.  * 
  1936.  * Local Variables:
  1937.  * tab-width: 8
  1938.  * End:
  1939.  */
  1940.