home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / MPack1_2_1.lha / MPack / src / macmpack.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-05  |  17.7 KB  |  778 lines

  1. /* mac_mpack.c -- Mac user interface to mpack routines
  2.  *
  3.  * (C) Copyright 1993 by Christopher J. Newman
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of Christopher J. Newman not be used in
  11.  * advertising or publicity pertaining to distribution of the software without
  12.  * specific, written prior permission.  Christopher J. Newman makes no
  13.  * representations about the suitability of this software for any purpose.  It
  14.  * is provided "as is" without express or implied warranty.
  15.  *
  16.  * CHRISTOPHER J. NEWMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  17.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
  18.  * SHALL CHRISTOPHER J. NEWMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  19.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  20.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  21.  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  22.  * OF THIS SOFTWARE.
  23.  */
  24.  
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include <ctype.h>
  28. #include "macnapp.h"
  29. #include "macmpack.h"
  30. #include "version.h"
  31.  
  32. /* save watch cursor */
  33. Cursor watch;
  34.  
  35. /* preferences */
  36. struct mpack_preferences **mpack_prefs;
  37.  
  38. /* flag for active help window */
  39. static WindowPtr helpw = NULL;
  40.  
  41. typedef struct filelist {
  42.     int vRefNum;
  43.     PCstr fname[65];
  44. } filelist;
  45.  
  46. typedef struct listwin {
  47.     na_win win;
  48.     int count;
  49.     filelist **hflist;
  50.     ListHandle l;
  51. } listwin;
  52.  
  53. void warn(char *str);
  54. static void do_decodefiles(listwin *);
  55. static void addfile(listwin *, SFReply *);
  56. static void removefile(listwin *);
  57. static short listclose(na_win *);
  58. static short listmouse(na_win *, Point, short, short);
  59. static short listctrl(na_win *, Point, short, short, ControlHandle);
  60. static short listupdate(na_win *, Boolean);
  61. static short listinit(na_win *,long *);
  62. static short textinit(na_win *,long *);
  63. static short prefsctrl(na_win *, Point, short, short, ControlHandle);
  64. static short prefsinit(na_win *, long *);
  65. static void do_decode(SFReply *);
  66. static void do_encode(SFReply *);
  67. static short mainmenu(struct na_win*, WORD, WORD);
  68.  
  69. #define dwin ((listwin *) win)
  70.  
  71. SFTypeList textList = { 'TEXT', 0, 0, 0 };
  72.  
  73. /* warn the user
  74.  */
  75. void warn(char *str)
  76. {
  77.     PCstr wstr[257];
  78.     
  79.     CtoPCstrncpy(wstr, str, 255);
  80.     ParamText(P(wstr), NULL, NULL, NULL);
  81.     NAalert(warnALRT);
  82. }
  83.  
  84. /* yell at the user
  85.  */
  86. void yell(char *str)
  87. {
  88.     PCstr wstr[257];
  89.     
  90.     CtoPCstrncpy(wstr, str, 255);
  91.     ParamText(P(wstr), NULL, NULL, NULL);
  92.     NAalert(errorALRT);
  93. }
  94.  
  95. /* process the files in the file list
  96.  */
  97. static void do_decodefiles(dw)
  98.     listwin *dw;
  99. {
  100.     int count = dw->count;
  101.     filelist *fl;
  102.     FILE *dfile;
  103.     extern long _ftype, _fcreator;
  104.     
  105.     _ftype = 'TEXT';
  106.     _fcreator = 'mPAK';
  107.     SetCursor(&watch);
  108.     MoveHHi((Handle) dw->hflist);
  109.     HLock((Handle) dw->hflist);
  110.     fl = *dw->hflist;
  111.     while (count--) {
  112.         SetVol(NULL, fl->vRefNum);
  113.         if (dfile = fopen(C(fl->fname), "r")) {
  114.             handleMessage(dfile, "text/plain", 0);
  115.             fclose(dfile);
  116.         }
  117.         ++fl;
  118.     }
  119.     HUnlock((Handle) dw->hflist);
  120.     SetCursor(&arrow);
  121. }
  122.  
  123. /* return non-zero if two filenames have the same prefix
  124.  */
  125. static int fprefixMatch(char *base, PCstr *match)
  126. {
  127.     PCstr temp[257];
  128.     char *scan;
  129.     short prefixlen;
  130.     
  131.     PtoPCstrcpy(temp, base);
  132.     scan = C(temp) + PCstrlen(temp) - 1;
  133.     while (isdigit(*scan) && scan > C(temp)) --scan;
  134.     prefixlen = scan - C(temp) + 1;
  135.     if (strncmp(C(temp), C(match), prefixlen)) return (0);
  136.     scan = C(match) + prefixlen;
  137.     while (isdigit(*scan)) ++scan;
  138.     
  139.     return (!*scan);
  140. }
  141.  
  142. /* do the add of a file to a list
  143.  */
  144. static void addit(listwin *dw, short vRefNum, char *fname)
  145. {
  146.     long size = GetHandleSize((Handle) dw->hflist) / sizeof (filelist);
  147.     filelist *fl;
  148.     char *bp;
  149.     Cell c;
  150.     PCstr fbuf[42];
  151.  
  152.     if (size == dw->count) {
  153.         SetHandleSize((Handle) dw->hflist, (++size * sizeof (filelist)));
  154.         if (MemError() != noErr) return;
  155.     }
  156.     MoveHHi((Handle) dw->hflist);
  157.     HLock((Handle) dw->hflist);
  158.     fl = *dw->hflist + dw->count;
  159.     fl->vRefNum = vRefNum;
  160.     PtoPCstrcpy(fl->fname, fname);
  161.     SetPt(&c, 0, dw->count);
  162.     LAddRow(1, ++dw->count, dw->l);
  163.     LSetCell((Ptr) C(fname), (short) Pstrlen(fname), c, dw->l);
  164.     HUnlock((Handle) dw->hflist);
  165. }
  166.  
  167. /* add file set to file list
  168.  */
  169. static void addfile(dw, reply)
  170.     listwin *dw;
  171.     SFReply *reply;
  172. {
  173.     CInfoPBRec cipbr;
  174.     HFileInfo *fpb = (HFileInfo *)&cipbr;
  175.     PCstr fbuf[42];
  176.     short idx, foundone = 0, wrefnum;
  177.     long dirid, procid;
  178.     
  179.     /* find directory where file is */
  180.     procid = 0;
  181.     GetWDInfo(reply->vRefNum, &wrefnum, &dirid, &procid);
  182.     
  183.     /* loop through directory */
  184.     idx = 1;
  185.     for (;;) {
  186.         fpb->ioVRefNum = wrefnum;
  187.         fpb->ioNamePtr = P(fbuf);
  188.         fpb->ioDirID = dirid;
  189.         fpb->ioFDirIndex = idx;
  190.         if (PBGetCatInfo(&cipbr, FALSE)) break;
  191.         SetClen(fbuf);
  192.         
  193.         if (!(fpb->ioFlAttrib & 16) && fprefixMatch((char *)reply->fName, fbuf)) {
  194.             addit(dw, reply->vRefNum, (char *) P(fbuf));
  195.             foundone = 1;
  196.         }
  197.         ++idx;
  198.     }
  199.     if (!foundone) {
  200.         addit(dw, reply->vRefNum, (char *) reply->fName);
  201.     }
  202. }
  203.  
  204. /* remove file from file list
  205.  */
  206. static void removefile(dw)
  207.     listwin *dw;
  208. {
  209.     filelist *fl;
  210.     int count;
  211.     Cell c;
  212.     
  213.     c.h = c.v = 0;
  214.     if (LGetSelect(TRUE, &c, dw->l)) {
  215.         MoveHHi((Handle) dw->hflist);
  216.         HLock((Handle) dw->hflist);
  217.         fl = *dw->hflist + c.v;
  218.         count = dw->count - c.v;
  219.         while (--count) {
  220.             fl[0] = fl[1];
  221.             ++fl;
  222.         }
  223.         HUnlock((Handle) dw->hflist);        
  224.         --dw->count;
  225.         LDelRow(1, c.v, dw->l);
  226.     }
  227. }
  228.  
  229. /* close list window
  230.  */
  231. static short listclose(win)
  232.     na_win *win;
  233. {
  234.     LDispose(dwin->l);
  235.     DisposHandle((Handle) dwin->hflist);
  236.     
  237.     return (NA_CLOSED);
  238. }
  239.  
  240. /* mouse procedure
  241.  */
  242. static short listmouse(na_win *win, Point p, short type, short mods)
  243. {
  244.     Cell c;
  245.     
  246.     if (!(type & 1)) {
  247.         LClick(p, mods, dwin->l);
  248.         c.h = c.v = 0;
  249.         NAhiliteDItem((DialogPtr)win->pwin, iRemove, LGetSelect(TRUE, &c, dwin->l) ? 0 : 255);
  250.     }
  251. }
  252.  
  253. /* control procedure
  254.  */
  255. static short listctrl(na_win *win, Point p, short item, short mods, ControlHandle ctrlh)
  256. {
  257.     SFReply reply;
  258.     Point where;
  259.  
  260.     switch (item) {
  261.         case iAdd:
  262.             where.h = where.v = 0;
  263.             SFGetFile(where, NULL, NULL, 1, textList, NULL, &reply);
  264.             if (reply.good) {
  265.                 if (!dwin->count) {
  266.                     NAhiliteDItem((DialogPtr)win->pwin, iOk, 0);
  267.                 }
  268.                 addfile(dwin, &reply);
  269.             }
  270.             return (NA_PROCESSED);
  271.             
  272.         case iRemove:
  273.             removefile(dwin);
  274.             NAhiliteDItem((DialogPtr)win->pwin, iRemove, 255);
  275.             if (!dwin->count) {
  276.                 NAhiliteDItem((DialogPtr)win->pwin, iOk, 255);
  277.             }
  278.             return (NA_PROCESSED);
  279.  
  280.         case iOk:
  281.             do_decodefiles(dwin);
  282.         case iCancel:
  283.             return (NA_REQCLOSE);
  284.     }
  285.     
  286.     return (NA_NOTPROCESSED);
  287. }
  288.  
  289. /* update the list window
  290.  */
  291. static short listupdate(na_win *win, Boolean resize)
  292. {
  293.     Rect r;
  294.     Handle hand;
  295.     short type;
  296.     
  297.     GetDItem((DialogPtr)win->pwin, iFileList, &type, &hand, &r);
  298.     FrameRect(&r);
  299.     UpdtDialog(win->pwin, win->pwin->visRgn);
  300.     LUpdate(win->pwin->visRgn, dwin->l);
  301.     
  302.     return (NA_NOTPROCESSED);
  303. }
  304.  
  305. /* initialize the list window
  306.  */
  307. static short listinit(win, data)
  308.     na_win *win;
  309.     long *data;
  310. {
  311.     SFReply *reply = (SFReply *) data;
  312.     Rect r, zrect;
  313.     Point p;
  314.     Handle hand;
  315.     short type;
  316.     
  317.     GetDItem((DialogPtr)win->pwin, iFileList, &type, &hand, &r);
  318.     InsetRect(&r, 1, 1);
  319.     zrect.top = zrect.bottom = zrect.left = p.h = p.v = 0;\
  320.     zrect.right = 1;
  321.     dwin->l = LNew(&r, &zrect, p, 0, win->pwin, 0, 0, 0, 1);
  322.     if (!dwin->l) return (NA_CLOSED);
  323.     (*dwin->l)->selFlags = lOnlyOne;
  324.     dwin->hflist = (filelist **) NewHandle(sizeof (filelist));
  325.     if (!dwin->hflist) {
  326.         LDispose(dwin->l);
  327.         return (NA_CLOSED);
  328.     }
  329.     dwin->count = 0;
  330.     addfile(dwin, reply);
  331.     win->closep = listclose;
  332.     win->updatep = listupdate;
  333.     win->ctrlp = listctrl;
  334.     win->mousep = listmouse;
  335.     NAhiliteDItem((DialogPtr)win->pwin, iRemove, 255);
  336.     ShowWindow(win->pwin);
  337.     DrawDialog(win->pwin);
  338.     LDoDraw(TRUE, dwin->l);
  339.     
  340.     return (NA_NOTPROCESSED);
  341. }
  342.  
  343. /* Decode procedure: first get a file, then open decode window
  344.  */
  345. static void do_decode(SFReply *reply)
  346. {
  347.     SFReply infile;
  348.     Point where;
  349.     
  350.     if (!reply) {
  351.         reply = &infile;
  352.         where.h = where.v = 0;
  353.         SFGetFile(where, NULL, NULL, 1, textList, NULL, &infile);
  354.     }
  355.     if (reply->good) {
  356.         NAwindow(0, NA_DIALOGWINDOW | NA_USERESOURCE | NA_RECENTER | NA_DEFBUTTON |
  357.             NA_HASCONTROLS | NA_CLOSEBOX, NULL, decodeDLOG, (long *) reply,
  358.             sizeof (listwin), listinit);
  359.     }
  360. }
  361.  
  362. /* a filter proc which handles Return, Enter, Esc, command-period properly
  363.  */
  364. pascal Boolean mySaveFilterProc(dialog, pevent, item)
  365.     DialogPtr        dialog;
  366.     EventRecord        *pevent;
  367.     short            *item;
  368. {
  369.     int c;
  370.  
  371.     if (pevent->what == autoKey || pevent->what == keyDown) {
  372.         switch (c = (pevent->message & charCodeMask)) {
  373.             case '\r':
  374.             case '\n':
  375.             case 0x03:
  376.                 *item = 1;
  377.                 goto HILITE;
  378.             
  379.             case '.':
  380.                 if (!(pevent->modifiers & cmdKey)) break;
  381.             case '\033':
  382.                 *item = 2;
  383.             HILITE:
  384.                 NAflashButton(dialog, *item);
  385.                 return (true);
  386.             default:
  387.                 if (((DialogPeek)dialog)->editField + 1 == iMaximum
  388.                     && isprint(c) && c != '\t' && !isdigit(c)) {
  389.                     pevent->what = nullEvent;
  390.                 }
  391.                 break;
  392.                     
  393.         }
  394.     }
  395.     
  396.     return (false);
  397. }
  398.  
  399. static long save_max;
  400. static PCstr save_subject[257];
  401. static short save_dflag;
  402.  
  403. /* custom file dialog procedure
  404.  */
  405. pascal short mySaveDialog(short item, DialogPtr theDialog)
  406. {
  407.     Handle etext;
  408.     PCstr tstr[257];
  409.     ControlHandle    ctrl;
  410.     short value;
  411.     
  412.     switch (item) {
  413.         case iDescfile:
  414.             NAgetDHandle(theDialog, iDescfile, &ctrl);
  415.             SetCtlValue(ctrl, !GetCtlValue(ctrl));
  416.             break;
  417.             
  418.         case iSplit:
  419.             NAgetDHandle(theDialog, iSplit, &ctrl);
  420.             value = GetCtlValue(ctrl);
  421.             SetCtlValue(ctrl, !value);
  422.             break;
  423.             
  424.         case iOk:
  425.             NAgetIText(theDialog, iSubject, save_subject);
  426.             NAgetDHandle(theDialog, iSplit, &ctrl);
  427.             save_max = 0;
  428.             if (GetCtlValue(ctrl)) {
  429.                 NAgetIText(theDialog, iMaximum, tstr);
  430.                 save_max = atol(C(tstr));
  431.             }
  432.             NAgetDHandle(theDialog, iDescfile, &ctrl);
  433.             save_dflag = GetCtlValue(ctrl);
  434.             break;
  435.     }
  436.     
  437.     return (item);
  438. }
  439.  
  440. /* Decode procedure: first get a file, then open decode window
  441.  */
  442. static void do_encode(SFReply *reply)
  443. {
  444.     SFReply infile, outfile, descfile;
  445.     Point where;
  446.     PCstr fname[34], mtype[257];
  447.     struct lookupct *ctptr;
  448.     char *scan;
  449.     short mapcount, i;
  450.     Handle h;
  451.     ResType type = 'TyCr';
  452.     extern long _ftype, _fcreator;
  453.     
  454.     where.h = where.v = 0;
  455.     if (!reply) {
  456.         SFGetFile(where, NULL, NULL, -1, NULL, NULL, &infile);
  457.         if (!infile.good) return;
  458.     } else {
  459.         infile = *reply;
  460.     }
  461.     PtoPCstrcpy(fname, (char *) infile.fName);
  462.     if (scan = strrchr(C(fname), '.')) {
  463.         *scan = '\0';
  464.         SetPlen(fname);
  465.     }
  466.     if (PCstrlen(fname) >= 25) {
  467.         *fname = 25;
  468.         SetClen(fname);
  469.     }
  470.     PtoCstr(infile.fName);
  471.   RETRYSFP:
  472.     SFPPutFile(where, "\pMIME part prefix:", P(fname), 
  473.         mySaveDialog, &outfile, encodeDLOG, mySaveFilterProc);
  474.     if (outfile.good) {
  475.         PtoCstr(outfile.fName);
  476.         if (!strcmp((char *)infile.fName, (char *)outfile.fName)) {
  477.             yell("The output filename must be different from the input filename");
  478.             goto RETRYSFP;
  479.         }
  480.         if (save_dflag) {
  481.             SFGetFile(where, NULL, NULL, 1, textList, NULL, &descfile);
  482.             if (!descfile.good) {
  483.                 save_dflag = 0;
  484.             } else {
  485.                 PtoCstr(descfile.fName);
  486.             }
  487.         }
  488.         mapcount = CountResources(type);
  489.         *mtype = '\0';
  490.         for (i = 1; i <= mapcount; ++i) {
  491.             h = GetIndResource(type, i);
  492.             if (h && **(OSType **)h == infile.fType) {
  493.                 GetResInfo(h, &i, &type, P(mtype));
  494.                 if (ResError() == noErr) break;
  495.             }
  496.         }
  497.         SetClen(mtype);
  498.  
  499.         _ftype = 'TEXT';
  500.         _fcreator = 'mPAK';
  501.         SetCursor(&watch);
  502.         encode(infile.fName, save_dflag ? descfile.fName : 0,
  503.             *C(save_subject) ? save_subject : infile.fName, NULL, save_max,
  504.             PCstrlen(mtype) ? C(mtype) : NULL, outfile.fName);
  505.         SetCursor(&arrow);
  506.     }
  507. }
  508.  
  509. /* open a textedit window & load a file into it
  510.  */
  511. static short textinit(na_win *win, long *data)
  512. {
  513.     Handle h = (Handle) data;
  514.     long size;
  515.     
  516.     TextFont(monaco);
  517.     TextSize(9);
  518.     size = GetHandleSize(h);
  519.     MoveHHi(h);
  520.     HLock(h);
  521.     NATEinit(win, NATE_READONLY, 489, *h, size);
  522.     HUnlock(h);
  523.     ShowWindow(win->pwin);
  524.     
  525.     return (NA_NOTPROCESSED);
  526. }
  527.  
  528. /* Open a window for a text file
  529.  */
  530. static short textopen(short message, AppFile *afile, FSSpec *fspec)
  531. {
  532.     SFReply reply;
  533.     Point where;
  534.     Handle data;
  535.     long len, saved;
  536.     short fref;
  537.     OSErr err;
  538.     Rect *sr;
  539.     FInfo finfo;
  540.     PCstr fname[257];
  541.     char emsg[512];
  542.     
  543.     if (message != appOpen) return (-1);
  544.     
  545.     /* find & open file */
  546.     if (!afile && !fspec) {
  547.         where.h = where.v = 0;
  548.         SFGetFile(where, NULL, NULL, 1, textList, NULL, &reply);
  549.         if (!reply.good) return (-1);
  550.         PtoPCstrcpy(fname, (char *) reply.fName);
  551.         err = FSOpen(reply.fName, reply.vRefNum, &fref);
  552.     } else if (afile) {
  553.         PtoPCstrcpy(fname, (char *) afile->fName);
  554.         BlockMove(afile->fName, reply.fName, sizeof (reply.fName));
  555.         reply.fType = afile->fType;
  556.         reply.vRefNum = afile->vRefNum;
  557.         reply.good = 1;
  558.         if (afile->fType == 'TEXT') {
  559.             do_decode(&reply);
  560.         } else {
  561.             do_encode(&reply);
  562.         }
  563.         return (0);
  564.     } else {
  565.         PtoPCstrcpy(fname, (char *) fspec->name);
  566.         if (FSpGetFInfo(fspec, &finfo) == noErr) {
  567.             BlockMove(fspec->name, reply.fName, sizeof (reply.fName));
  568.             reply.fType = finfo.fdType;
  569.             reply.vRefNum = fspec->vRefNum;
  570.             reply.good = 1;
  571.             if (finfo.fdType == 'TEXT') {
  572.                 do_decode(&reply);
  573.             } else {
  574.                 do_encode(&reply);
  575.             }
  576.             return (0);
  577.         }
  578.         err = FSpOpenDF(fspec, fsRdPerm, &fref);
  579.     }
  580.     
  581.     /* read file */
  582.     if (err != noErr) {
  583.         sprintf(emsg, "Could not open file %s\rError %d", C(fname), err);
  584.         yell(emsg);
  585.         return (-1);
  586.     }
  587.     if (GetEOF(fref, &len) < 0 || len >= 32000 || !(data = NewHandle(len))) {
  588.         FSClose(fref);
  589.         sprintf(emsg, "File %s is too long to view.", C(fname));
  590.         yell(emsg);
  591.         return (-1);
  592.     }
  593.     MoveHHi(data);
  594.     HLock(data);
  595.     saved = len;
  596.     err = FSRead(fref, &saved, *data);
  597.     HUnlock(data);
  598.     FSClose(fref);
  599.     if (err != noErr || saved != len) {
  600.         sprintf(emsg, "Could not read file %s\rError %d", C(fname), err);
  601.         yell(emsg);
  602.         return (-1);
  603.     }
  604.     
  605.     /* open NATE window */
  606.     sr = NAscreenrect(NA_TOPSCN | NA_RIGHTSCN | NA_TITLEOFFSET | NA_STACK);
  607.     if (sr->right - sr->left > 512) sr->right = sr->left + 512;
  608.     NAwindow(sr, NA_USERESOURCE | NA_FORCESIZE | NATEflags, C(fname), textWIND,
  609.         (long *) data, sizeof (nate_win), textinit);
  610.     DisposHandle(data);
  611.     
  612.     return (0);
  613. }
  614.  
  615. #define hwinfo ((nate_win *)win)
  616.  
  617. /* help close procedure
  618.  */
  619. static short helpclose(na_win *win)
  620. {
  621.     helpw = NULL;
  622.  
  623.     return (NATEclosep(win));
  624. }
  625.  
  626. /* help window procedure
  627.  */
  628. static short helpwindow(na_win *win, long *data)
  629. {
  630.     Rect        rtemp, vtemp;
  631.     Handle        h, hs;
  632.     long        len;
  633.     TEHandle    hTE;
  634.     
  635.     rtemp = win->pwin->portRect;
  636.     vtemp = rtemp;
  637.     vtemp.right = vtemp.left + (hwinfo->docwidth = 475);
  638.     win->mousep = NATEmousep;
  639.     win->idlep = NATEidlep;
  640.     win->menup = NATEmenup;
  641.     win->activep = NATEactivep;
  642.     win->updatep = NATEupdatep;
  643.     win->ctrlp = NATEctrlp;
  644.     win->closep = helpclose;
  645.     win->cursorRgn = NewRgn();
  646.     hwinfo->vctrl = hwinfo->hctrl = NULL;
  647.     
  648.     TEAutoView(true, hTE = hwinfo->hTE = TEStylNew(&vtemp, &rtemp));
  649.     h = GetResource('TEXT', helpTEXT);
  650.     hs = GetResource('styl', helpSTYL);
  651.     len = GetHandleSize(h);
  652.     HLock(h);
  653.     TEStylInsert(*h, len, (StScrpHandle) hs, hTE);
  654.     HUnlock(h);
  655.     TESetSelect(0, 0, hTE);
  656.     hwinfo->lheight = TEGetHeight((*hTE)->nLines, 0, hTE) / (*hTE)->nLines;
  657.     ShowWindow(helpw = win->pwin);
  658.     
  659.     return (NA_NOTPROCESSED);
  660. }
  661.  
  662. /* control procedure
  663.  */
  664. static short prefsctrl(na_win *win, Point p, short item, short mods, ControlHandle ctrlh)
  665. {
  666.     PCstr tmpstr[256];
  667.     
  668.     if (item == iOk) {
  669.         /* if internet host has changed */
  670.         NAgetIText(win->pwin, iHost, P(tmpstr));
  671.         SetClen(tmpstr);
  672.         HLock((Handle) mpack_prefs);
  673.         if (strcmp(C(tmpstr), (*mpack_prefs)->internet_host)) {
  674.             HUnlock((Handle) mpack_prefs);
  675.             /* update the preferences resource */
  676.             SetHandleSize((Handle) mpack_prefs, sizeof (struct mpack_preferences)
  677.                 + PCstrlen(tmpstr));
  678.             HLock((Handle) mpack_prefs);
  679.             strcpy((*mpack_prefs)->internet_host, C(tmpstr));
  680.             ChangedResource((Handle) mpack_prefs);
  681.         }
  682.         HUnlock((Handle) mpack_prefs);
  683.     }
  684.     
  685.     return (item == iOk || item == iCancel ? NA_REQCLOSE : NA_NOTPROCESSED);
  686. }
  687.  
  688. static short prefsinit(na_win *win, long *data)
  689. {
  690.     PCstr tmpstr[256];
  691.     
  692.     win->ctrlp = prefsctrl;
  693.     HLock((Handle) mpack_prefs);
  694.     strcpy(C(tmpstr), (*mpack_prefs)->internet_host);
  695.     HUnlock((Handle) mpack_prefs);
  696.     SetPlen(tmpstr);
  697.     NAsetIText(win->pwin, iHost, P(tmpstr));
  698.     SelIText(win->pwin, iHost, 0, 32767);
  699.     ShowWindow(win->pwin);
  700.     
  701.     return (NA_NOTPROCESSED);
  702. }
  703.  
  704. /* Main menu procedure
  705.  */
  706. static short mainmenu(na_win *win, WORD menuid, WORD itemno)
  707. {
  708.     short status;
  709.     MenuHandle mh;
  710.     PCstr version[32];
  711.  
  712.     switch (menuid) {
  713.         case mApple:
  714.             if (itemno == iAbout) {
  715.                 CtoPCstrcpy(version, MPACK_VERSION);
  716.                 ParamText(P(version), NULL, NULL, NULL);
  717.                 return (NAwindow(0, NA_DIALOGWINDOW | NA_USERESOURCE | NA_RECENTER
  718.                     | NA_DIALOGUPDATE | NA_MODAL, "About", aboutDLOG, (long *) NULL, 0, NAabout));
  719.             }
  720.             if (!helpw) {
  721.                 NAwindow(0, NA_USERESOURCE | NATEflags | NA_SMARTSIZE, NULL, helpWIND,
  722.                     (long *) NULL, sizeof (nate_win), helpwindow);
  723.             } else {
  724.                 SelectWindow(helpw);
  725.             }
  726.             break;
  727.             
  728.         case mFile:
  729.             switch (itemno) {
  730.                 case iEncode:
  731.                     do_encode(NULL);
  732.                     return (NA_PROCESSED);
  733.                     
  734.                 case iDecode:
  735.                     do_decode(NULL);
  736.                     return (NA_PROCESSED);
  737.                 
  738.                 case iOpen:
  739.                     textopen(appOpen, NULL, NULL);
  740.                     return (NA_PROCESSED);
  741.  
  742.                 case iClose:
  743.                     return (NA_NOTPROCESSED);
  744.                     
  745.                 case iPrefs:
  746.                     return (NAwindow(0, NA_DIALOGWINDOW | NA_USERESOURCE | NA_RECENTER
  747.                         | NA_DIALOGUPDATE | NA_MODAL | NA_DEFBUTTON, "Preferences", prefsDLOG,
  748.                         (long *) NULL, 0, prefsinit));
  749.  
  750.                 case iQuit:
  751.                     return (NA_REQCLOSEALL);
  752.             }
  753.             break;
  754.  
  755.         case mEdit:
  756.             switch (itemno) {
  757.                 case iClipboard:
  758.                     NAclipboardMenu(menuid, itemno, 'TEXT');
  759.                     return (NA_PROCESSED);
  760.             }
  761.             break;
  762.     }
  763.     return (NA_NOTPROCESSED);
  764. }
  765.  
  766.  
  767. main()
  768. {
  769.     CursHandle cursH;
  770.  
  771.     if (NAinit(128, 3, textopen, mainmenu, 2, 0, iClose) == 0) {
  772.         mpack_prefs = (struct mpack_preferences **) GetResource('mPRF', prefsID);
  773.         cursH = GetCursor(watchCursor);
  774.         watch = **cursH;
  775.         NAmainloop();
  776.     }
  777. }
  778.