/[MITgcm]/MITgcm/tools/mpack-1.6/macmpack.c
ViewVC logotype

Annotation of /MITgcm/tools/mpack-1.6/macmpack.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1 - (hide annotations) (download)
Tue Aug 26 20:45:25 2003 UTC (20 years, 8 months ago) by edhill
Branch: MAIN
CVS Tags: checkpoint64y, checkpoint64x, checkpoint58l_post, checkpoint64z, checkpoint51k_post, checkpoint57t_post, checkpoint64q, checkpoint64p, checkpoint64s, checkpoint64r, checkpoint64u, checkpoint64t, checkpoint64w, checkpoint64v, checkpoint64i, checkpoint64h, checkpoint64k, checkpoint64j, checkpoint64m, checkpoint64l, checkpoint64o, checkpoint64n, checkpoint64a, checkpoint57o_post, checkpoint64c, checkpoint64b, checkpoint64e, checkpoint64d, checkpoint64g, checkpoint64f, checkpoint52l_pre, checkpoint52e_pre, hrcube4, checkpoint58e_post, mitgcm_mapl_00, checkpoint52n_post, checkpoint52j_post, checkpoint53d_post, checkpoint58u_post, checkpoint58w_post, checkpoint54a_pre, checkpoint51o_pre, checkpoint57m_post, checkpoint55c_post, checkpoint54e_post, checkpoint52e_post, checkpoint57s_post, checkpoint51n_pre, checkpoint54a_post, checkpoint63p, checkpoint63q, checkpoint63r, checkpoint63s, checkpoint63l, checkpoint63m, checkpoint63n, checkpoint63o, checkpoint63h, checkpoint63i, checkpoint63j, checkpoint63k, checkpoint63d, checkpoint63e, checkpoint63f, checkpoint63g, checkpoint53c_post, checkpoint63a, checkpoint63b, checkpoint63c, checkpoint57k_post, checkpoint55d_pre, checkpoint57d_post, checkpoint51l_post, checkpoint57g_post, checkpoint51q_post, checkpoint64, checkpoint65, checkpoint60, checkpoint61, checkpoint62, checkpoint63, checkpoint57b_post, checkpoint57c_pre, checkpoint51j_post, checkpoint58r_post, checkpoint55j_post, checkpoint56b_post, checkpoint57i_post, checkpoint57y_post, hrcube_1, checkpoint57e_post, checkpoint66g, checkpoint66f, checkpoint66e, checkpoint66d, checkpoint66c, checkpoint66b, checkpoint66a, checkpoint66o, checkpoint66n, checkpoint66m, checkpoint66l, checkpoint66k, checkpoint66j, checkpoint66i, checkpoint66h, branch-netcdf, checkpoint52d_pre, checkpoint52l_post, checkpoint55h_post, checkpoint58n_post, checkpoint53b_post, checkpoint58x_post, checkpoint52k_post, checkpoint52b_pre, checkpoint57g_pre, checkpoint54b_post, checkpoint53b_pre, checkpoint55b_post, checkpoint58t_post, checkpoint58h_post, checkpoint65z, checkpoint65x, checkpoint65y, checkpoint54d_post, checkpoint65r, checkpoint65s, checkpoint65p, checkpoint65q, checkpoint65v, checkpoint65w, checkpoint65t, checkpoint65u, checkpoint65j, checkpoint65k, checkpoint65h, checkpoint65i, checkpoint65n, checkpoint65o, checkpoint65l, checkpoint65m, checkpoint65b, checkpoint65c, checkpoint65a, checkpoint65f, checkpoint65g, checkpoint65d, checkpoint65e, checkpoint56c_post, checkpoint52m_post, checkpoint57y_pre, checkpoint55, checkpoint53a_post, checkpoint57f_pre, checkpoint57a_post, checkpoint54, checkpoint58q_post, checkpoint54f_post, checkpoint57v_post, checkpoint59q, checkpoint59p, checkpoint55g_post, checkpoint59r, checkpoint51o_post, checkpoint51p_post, checkpoint58j_post, checkpoint52a_pre, checkpoint59e, checkpoint59d, checkpoint59g, checkpoint59f, checkpoint59a, checkpoint55f_post, checkpoint59c, checkpoint59b, checkpoint59m, checkpoint59l, checkpoint59o, checkpoint59n, checkpoint59i, checkpoint59h, checkpoint59k, checkpoint59j, checkpoint57r_post, checkpoint59, checkpoint58, checkpoint57a_pre, checkpoint55i_post, checkpoint57, checkpoint56, checkpoint51i_post, checkpoint53, checkpoint52, checkpoint51f_post, checkpoint52d_post, eckpoint57e_pre, checkpoint51r_post, checkpoint52a_post, checkpoint57h_done, checkpoint58f_post, checkpoint52b_post, checkpoint53g_post, checkpoint52f_post, branchpoint-genmake2, checkpoint57x_post, checkpoint57n_post, checkpoint52c_post, checkpoint58d_post, checkpoint58c_post, checkpoint57w_post, checkpoint57p_post, checkpint57u_post, checkpoint57f_post, checkpoint58a_post, checkpoint51h_pre, checkpoint51l_pre, checkpoint58i_post, checkpoint57q_post, checkpoint51g_post, checkpoint58g_post, ecco_c52_e35, hrcube5, checkpoint58o_post, checkpoint57z_post, checkpoint62c, checkpoint62b, checkpoint62a, checkpoint62g, checkpoint62f, checkpoint62e, checkpoint62d, checkpoint62k, checkpoint62j, checkpoint62i, checkpoint62h, checkpoint62o, checkpoint62n, checkpoint62m, checkpoint62l, checkpoint62s, checkpoint62r, checkpoint62q, checkpoint62p, checkpoint62w, checkpoint62v, checkpoint62u, checkpoint62t, checkpoint57c_post, checkpoint62z, checkpoint62y, checkpoint62x, checkpoint58y_post, checkpoint55e_post, checkpoint58k_post, checkpoint52i_post, checkpoint52j_pre, checkpoint58v_post, checkpoint53f_post, checkpoint55a_post, checkpoint51t_post, checkpoint53d_pre, checkpoint54c_post, checkpoint58s_post, checkpoint61f, checkpoint61g, checkpoint61d, checkpoint61e, checkpoint61b, checkpoint61c, checkpoint58p_post, checkpoint61a, checkpoint61n, checkpoint61o, checkpoint61l, checkpoint61m, checkpoint61j, checkpoint61k, checkpoint61h, checkpoint61i, checkpoint61v, checkpoint61w, checkpoint61t, checkpoint61u, checkpoint61r, checkpoint61s, checkpoint61p, checkpoint61q, checkpoint51n_post, checkpoint57j_post, checkpoint61z, checkpoint61x, checkpoint61y, checkpoint58b_post, checkpoint57h_pre, checkpoint51i_pre, checkpoint58m_post, checkpoint57l_post, checkpoint52i_pre, checkpoint51u_post, checkpoint52h_pre, checkpoint52f_pre, checkpoint57h_post, hrcube_2, hrcube_3, checkpoint56a_post, checkpoint51m_post, checkpoint51s_post, checkpoint55d_post, HEAD
Branch point for: branch-nonh, branch-genmake2, tg2-branch, checkpoint51n_branch, netcdf-sm0
File MIME type: text/plain
Initial check-in of the CMU "mpack" utility.  This allows us to (portably)
send MITgcm output as MIME-encoded email messages and will be used by the
"testreport" script.  The CMU license is basically an "AS-IS" statement.

1 edhill 1.1 /* macmpack.c -- Mac user interface to mpack routines
2     *
3     * (C) Copyright 1993-1995 by Carnegie Mellon University
4     * All Rights Reserved.
5     *
6     * Permission to use, copy, modify, distribute, and sell this software
7     * and its documentation for any purpose is hereby granted without fee,
8     * provided that the above copyright notice appear in all copies and
9     * that both that copyright notice and this permission notice appear in
10     * supporting documentation, and that the name of Carnegie Mellon University
11     * not be used in advertising or publicity pertaining to distribution of the
12     * software without specific, written prior permission. Carnegie
13     * Mellon University makes no representations about the suitability of
14     * this software for any purpose. It is provided "as is" without
15     * express or implied warranty.
16     *
17     * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
18     * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
19     * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
20     * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21     * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
22     * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
23     * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
24     * SOFTWARE.
25     *
26     * NOTE: a good GUI requires a lot of work... This needs more.
27     */
28    
29     #include <Folders.h>
30     #include <Script.h>
31     #include <GestaltEqu.h>
32    
33     #include <stdio.h>
34     #include <time.h>
35     #include <string.h>
36     #include <ctype.h>
37     #include "version.h"
38     #include "part.h"
39     #include "macnapp.h"
40     #include "macmpack.h"
41     #include "macICTypes.h"
42     #include "macICAPI.h"
43     #include "macICKeys.h"
44    
45     /* ThinkC's internal stdio functions: */
46     #include <ansi_private.h>
47    
48     /* window types: */
49     #define DECODELIST 1
50     #define PREFWIN 2
51    
52     /* save watch cursor */
53     Cursor watch;
54    
55     /* preferences */
56     struct pref_folder *pfolder = NULL;
57     struct mpack_preferences **mpack_prefs = NULL;
58     static ICInstance icinst = NULL;
59    
60     /* flag for active help window */
61     static WindowPtr helpw = NULL;
62    
63     /* active decode status window */
64     static na_win *curstatwin = NULL;
65     short didchat;
66    
67     /* MacTCP started: -1 = error, 1 = active, 0 = unknown */
68     static short tcpstart = 0;
69    
70     /* this is used for opening TEXT files */
71     SFTypeList textList = { 'TEXT', 0, 0, 0 };
72    
73     /* next two types are used in the dialog used to select files to decode
74     */
75     typedef struct filelist {
76     short vRefNum;
77     long dirID;
78     PCstr fname[65];
79     } filelist;
80     typedef struct listwin {
81     na_win win;
82     int count;
83     filelist **hflist;
84     ListHandle l;
85     } listwin;
86    
87     /* this is the status window for decoding
88     */
89     typedef struct statuswin {
90     na_win win;
91     RgnHandle urgn; /* user region */
92     Rect urect; /* user rectangle */
93     Rect frect; /* frame rectangle */
94     short row; /* row at top of scroll area */
95     short nrow; /* rows of status text */
96     long size, used; /* bytes of status text & amount used */
97     Handle text; /* status text */
98     ControlHandle sb; /* scroll bar control */
99     short height, ascent; /* font height and ascent */
100     } statuswin;
101    
102     /* this is for the encode window
103     */
104     typedef struct encodewin {
105     nate_win w;
106     Boolean nateon; /* cursor in Desc edit field */
107     Boolean useemail; /* sending email */
108     long partsize; /* max part size (0 = no limit) */
109     OSType ftype; /* type of file to encode */
110     FSSpec fspec; /* file to encode */
111     FSSpec ofile; /* output file */
112     } encodewin;
113    
114     /* show progress
115     */
116     typedef struct progresswin {
117     natcp_win w;
118     short percent;
119     } progresswin;
120    
121     /* send mail
122     */
123     typedef struct mailwin {
124     progresswin w;
125     Handle headers; /* email headers */
126     Handle envelope; /* envelope */
127     short state; /* state */
128     short remaining; /* messages remaining */
129     Boolean sending; /* flag for active SMTP task */
130     Boolean useemail; /* sending email */
131     Boolean gothost; /* got the hostname */
132     long partsize; /* max part size (0 = no limit) */
133     long dirID; /* ID for temp dir */
134     OSType ftype; /* type of file to encode */
135     FSSpec fspec; /* file to be encoded */
136     FSSpec ofile; /* output file */
137     FILE *dfile; /* desc file */
138     PCstr server[257]; /* SMTP server */
139     PCstr subj[257]; /* subject */
140     CInfoPBRec cpb;
141     } mailwin;
142    
143     /* mailwin states */
144     #define MS_MACTCP 0 /* Starting MacTCP */
145     #define MS_GETHOST 1 /* Getting hostname */
146     #define MS_ENCODE 2 /* Do encoding */
147     #define MS_SENDING 3 /* Sending email */
148    
149     /* some prototypes */
150     void warn(char *str);
151     void stattext(Str255, unsigned char);
152     static void do_decodefiles(na_win *);
153     static void addfile(listwin *, FSSpec *);
154     static void removefile(listwin *);
155     static short listclose(na_win *);
156     static short listmouse(na_win *, Point, short, short);
157     static short listctrl(na_win *, Point, short, short, ControlHandle);
158     static short listupdate(na_win *, Boolean);
159     static short listinit(na_win *,long *);
160     static short prefsctrl(na_win *, Point, short, short, ControlHandle);
161     static short prefsinit(na_win *, long *);
162     static void do_decode(FSSpec *);
163     static void do_encode(FSSpec *, OSType);
164     static short mainmenu(struct na_win*, WORD, WORD);
165    
166     #define dwin ((listwin *) win)
167     #define swin ((statuswin *) win)
168     #define ewin ((encodewin *) win)
169     #define twin ((nate_win *) win)
170     #define prwin ((progresswin *) win)
171     #define mwin ((mailwin *) win)
172    
173     /* Get a FILE* to a Macintosh file
174     ******************************* ###############################
175     * KLUDGE ALERT! KLUDGE ALERT! * # KLUDGE ALERT! KLUDGE ALERT! #
176     ******************************* ###############################
177     * Mac files are specified by name/vRefNum/dirID combo, but the portable
178     * portions of mpack use FILE* to do I/O. We need a way to get an open FILE*
179     * from a file specified by name/vRefNum/dirID. Here we use the proper Macintosh
180     * routines to open a file, then hack together a FILE* using ThinkC's internal
181     * routines. The major trouble is that we have no way to get at the FILE action
182     * procedure (fp->proc), so we need a sample FILE* to be passed in. Bleargh!
183     ******************************* ###############################
184     * KLUDGE ALERT! KLUDGE ALERT! * # KLUDGE ALERT! KLUDGE ALERT! #
185     ******************************* ###############################
186     */
187     FILE *Macopen(FILE *sample, Str255 name, short vRefNum, long dirID,
188     short binary_flag, short res_fork, SignedByte permission)
189     {
190     FILE *fp = NULL;
191     short refnum;
192     long curEOF;
193     OSErr err;
194    
195     if ((!res_fork && (err = HOpen(vRefNum, dirID, name, permission, &refnum)) == noErr)
196     || (res_fork && (err = HOpenRF(vRefNum, dirID, name, permission, &refnum)) == noErr)) {
197     if ((fp = __getfile()) == NULL) {
198     FSClose(refnum);
199     } else {
200     if (permission == fsWrPerm) {
201     /* if we're writing to the file, truncate it */
202     SetEOF(refnum, curEOF = 0);
203     } else {
204     GetEOF(refnum, &curEOF);
205     }
206     fp->refnum = refnum;
207     fp->len = (fpos_t) curEOF;
208     fp->binary = binary_flag;
209     setvbuf(fp, NULL, _IOFBF, BUFSIZ);
210     fp->proc = sample->proc;
211     }
212     }
213    
214     return (fp);
215     }
216    
217    
218     /* warn the user
219     */
220     void warn(char *str)
221     {
222     PCstr wstr[257];
223    
224     CtoPCstrncpy(wstr, str, 255);
225     ParamText(P(wstr), NULL, NULL, NULL);
226     NAalert(warnALRT);
227     }
228    
229     /* yell at the user
230     */
231     void yell(char *str)
232     {
233     PCstr wstr[257];
234    
235     CtoPCstrncpy(wstr, str, 255);
236     ParamText(P(wstr), NULL, NULL, NULL);
237     NAalert(errorALRT);
238     }
239    
240     /* chat with user
241     */
242     chat(char *str)
243     {
244     PCstr tmpstr[257];
245    
246     CtoPCstrcpy(tmpstr, str);
247     stattext(P(tmpstr), 0);
248     }
249    
250     /* returns NA_ALLCLOSED if appropriate, else NA_CLOSED
251     */
252     static short alldone(na_win *win)
253     {
254     if (win->next == NULL && win->afterp == NULL && (*mpack_prefs)->quit_finished
255     && RecoverHandle((Ptr) win) == (Handle) NAhead) {
256     return (NA_ALLCLOSED);
257     }
258    
259     return (NA_CLOSED);
260     }
261    
262     /* update procedure for status dialog box
263     */
264     static short statupdate(na_win *win, Boolean newsize)
265     {
266     RgnHandle savergn;
267     unsigned char *s;
268     short row, top;
269     Rect tmpr;
270    
271     FrameRect(&swin->frect);
272     savergn = NewRgn();
273     if (savergn) {
274     GetClip(savergn);
275     SetClip(swin->urgn);
276     }
277    
278     /* redraw text area */
279     HLock(swin->text);
280     s = * (unsigned char **) swin->text;
281     top = swin->urect.top;
282     for (row = 0; row < swin->row; ++row) {
283     s += s[1] + 2;
284     }
285     for (; row < swin->nrow && top + swin->height <= swin->urect.bottom; ++row) {
286     MoveTo(swin->urect.left, top + swin->ascent);
287     if (*s) TextFace(1);
288     DrawString(s + 1);
289     if (*s) TextFace(0);
290     /* advance to next string */
291     top += swin->height;
292     s += s[1] + 2;
293     }
294     HUnlock(swin->text);
295    
296     if (savergn) {
297     SetClip(savergn);
298     DisposeRgn(savergn);
299     }
300    
301     return (NA_NOTPROCESSED);
302     }
303    
304     /* refresh status window
305     */
306     void statrefresh()
307     {
308     na_win *win = curstatwin;
309    
310     Draw1Control(swin->sb);
311     statupdate(win, false);
312     }
313    
314     /* add text to the status window
315     */
316     void stattext(Str255 str, unsigned char bold)
317     {
318     na_win *win = curstatwin;
319     short i, len;
320     unsigned char *s, *start;
321     RgnHandle rgn;
322     Rect tmpr;
323    
324     if (!win) return;
325     didchat = 1;
326    
327     /* advance to next row */
328     if (swin->height * (swin->nrow++ - swin->row)
329     >= swin->urect.bottom - swin->urect.top) {
330     SetCtlMax(swin->sb, ++swin->row);
331     SetCtlValue(swin->sb, swin->row);
332     if ((rgn = NewRgn()) != NULL) {
333     tmpr = swin->urect;
334     ScrollRect(&tmpr, 0, -swin->height, rgn);
335     DisposeRgn(rgn);
336     }
337     }
338    
339     /* add the text */
340     len = * (unsigned char *) str;
341     if (swin->size - swin->used < len + 1) {
342     SetHandleSize(swin->text, swin->size * 2);
343     if (MemError() == 0) swin->size *= 2;
344     }
345     HLock(swin->text);
346     s = start = * (unsigned char **) swin->text;
347     for (i = 1; i < swin->nrow; ++i) {
348     s += s[1] + 2;
349     }
350     if (len + 2 + s < start + swin->size) {
351     *s = bold;
352     memcpy(s + 1, str, len + 1);
353     swin->used = s + len + 2 - start;
354     }
355     HUnlock(swin->text);
356     statupdate(win, false);
357     }
358    
359     /* scroll the status dialog
360     */
361     static void statscroll(na_win *win, short rows)
362     {
363     RgnHandle rgn;
364    
365     if ((rgn = NewRgn()) != NULL) {
366     SetCtlValue(swin->sb, swin->row += rows);
367     ScrollRect(&swin->urect, 0, - swin->height * rows, rgn);
368     EraseRgn(rgn);
369     DisposeRgn(rgn);
370     }
371     statupdate(win, false);
372     }
373    
374     /* scroll bar procedure
375     */
376     static pascal void statscollbar(ControlHandle ctrlh, short part)
377     {
378     na_win *win = (na_win *) GetCRefCon(ctrlh);
379     short max, new, page;
380    
381     max = GetCtlMax(ctrlh);
382     page = (swin->urect.bottom - swin->urect.top) / swin->height - 1;
383     switch (part) {
384     case inUpButton:
385     page = 1;
386     /* fall through */
387     case inPageUp:
388     if (swin->row > 0) {
389     statscroll(win, - (swin->row < page ? swin->row : page));
390     }
391     break;
392     case inDownButton:
393     page = 1;
394     /* fall through */
395     case inPageDown:
396     if (swin->row < max) {
397     statscroll(win, max - swin->row < page ? max - swin->row : page);
398     }
399     break;
400     case inThumb:
401     break;
402     }
403     }
404    
405     /* control procedure for status dialog box
406     */
407     static short statctrl(na_win *win, Point p, short item, short mods, ControlHandle ctrlh)
408     {
409     short value;
410    
411     if (ctrlh == swin->sb) {
412     ctrlh = swin->sb;
413     if (item != inThumb) {
414     SetCRefCon(ctrlh, (long) win);
415     TrackControl(ctrlh, p, statscollbar);
416     } else {
417     TrackControl(ctrlh, p, nil);
418     value = GetCtlValue(ctrlh);
419     if (value != swin->row) statscroll(win, value - swin->row);
420     }
421     } else if (item == iOk) {
422     return (NA_REQCLOSE);
423     }
424    
425     return (NA_NOTPROCESSED);
426     }
427    
428     /* close procedure for status dialog box
429     */
430     static short statclose(na_win *win)
431     {
432     DisposeRgn(swin->urgn);
433     DisposHandle(swin->text);
434     DisposeControl(swin->sb);
435    
436     return (alldone(win));
437     }
438    
439     /* init procedure for status dialog box
440     */
441     static short statinit(na_win *win, long *data)
442     {
443     Rect tmpr;
444     FontInfo finfo;
445    
446     /* disable OK button while working */
447     NAhiliteDItem(win->pwin, iOk, 255);
448    
449     /* set up status text area & font */
450     if ((swin->urgn = NewRgn()) == NULL) return (NA_CLOSED);
451     TextFont(geneva);
452     TextSize(9);
453     GetFontInfo(&finfo);
454     swin->ascent = finfo.ascent;
455     swin->height = finfo.ascent + finfo.descent + finfo.leading;
456     NAgetDRect(win->pwin, iStatus, &swin->frect);
457     swin->urect = swin->frect;
458     InsetRect(&swin->urect, 2,
459     2 + ((swin->urect.bottom - swin->urect.top - 4) % swin->height) / 2);
460     RectRgn(swin->urgn, &swin->urect);
461    
462     /* set up text storage */
463     if ((swin->text = NewHandle(swin->size = 1024)) == NULL) {
464     DisposeRgn(swin->urgn);
465     return (NA_CLOSED);
466     }
467     **(char **)swin->text = '\0';
468    
469     /* set up scrollbar */
470     NAgetDRect(win->pwin, iStatScroll, &tmpr);
471     swin->sb = NewControl(win->pwin, &tmpr, "\p", true, 0, 0, 0, scrollBarProc, 0);
472     if (!swin->sb) {
473     DisposeRgn(swin->urgn);
474     DisposHandle(swin->text);
475     return (NA_CLOSED);
476     }
477    
478     /* set up procedures */
479     win->closep = statclose;
480     win->ctrlp = statctrl;
481     win->updatep = statupdate;
482    
483     /* keep window locked until decoding is done */
484     ++win->locks;
485     curstatwin = win;
486    
487     return (NA_NOTPROCESSED);
488     }
489    
490     /* process the files in the file list
491     */
492     static void do_decodefiles(na_win *win)
493     {
494     int count = dwin->count;
495     filelist *fl;
496     FILE *dfile, *tmpf;
497     extern long _ftype, _fcreator;
498     long ticks;
499     int result;
500    
501     MapTypeCreator("text/plain", 0);
502     SetCursor(&watch);
503     if (NAwindow(0, NA_DIALOGWINDOW | NA_TITLEBAR | NA_DEFBUTTON | NA_USERESOURCE
504     | NA_CLOSEBOX | NA_HASCONTROLS,
505     0, dstatDLOG, 0, sizeof (statuswin), statinit) == NA_CLOSED) {
506     warn("Not enough memory to decode");
507     return;
508     }
509     MoveHHi((Handle) dwin->hflist);
510     HLock((Handle) dwin->hflist);
511     fl = *dwin->hflist;
512     tmpf = tmpfile();
513     while (count--) {
514     stattext(fl->fname, 1);
515     didchat = 0;
516     if (dfile = Macopen(tmpf, fl->fname, fl->vRefNum, fl->dirID, 0, 0, 1)) {
517     result = handleMessage(part_init(dfile), "text/plain",
518     0, (*mpack_prefs)->extract_text);
519     if (result != 0 || didchat <= 0) {
520     if (didchat < 0) {
521     chat("Decoding cancelled");
522     } else {
523     chat("Found nothing to decode");
524     }
525     }
526     fclose(dfile);
527     } else {
528     chat("Couldn't find source file");
529     }
530     ++fl;
531     }
532     fclose(tmpf);
533     HUnlock((Handle) dwin->hflist);
534     NAhiliteDItem(curstatwin->pwin, iOk, 0);
535     NAunlockWindow(curstatwin);
536     curstatwin = NULL;
537     SetCursor(&arrow);
538     DisposHandle((Handle) dwin->hflist);
539     }
540    
541     /* return non-zero if two filenames have the same prefix
542     */
543     static int fprefixMatch(char *base, PCstr *match)
544     {
545     PCstr temp[257];
546     char *scan;
547     short prefixlen;
548    
549     PtoPCstrcpy(temp, base);
550     scan = C(temp) + PCstrlen(temp) - 1;
551     while (isdigit(*scan) && scan > C(temp)) --scan;
552     prefixlen = scan - C(temp) + 1;
553     if (strncmp(C(temp), C(match), prefixlen)) return (0);
554     scan = C(match) + prefixlen;
555     while (isdigit(*scan)) ++scan;
556    
557     return (!*scan);
558     }
559    
560     /* do the add of a file to a list
561     */
562     static void addit(listwin *dw, short vRefNum, long dirID, char *fname)
563     {
564     long size = GetHandleSize((Handle) dw->hflist) / sizeof (filelist);
565     filelist *fl;
566     char *bp;
567     Cell c;
568     int i;
569     PCstr fbuf[42];
570    
571     if (size == dw->count) {
572     SetHandleSize((Handle) dw->hflist, (++size * sizeof (filelist)));
573     if (MemError() != noErr) return;
574     }
575     MoveHHi((Handle) dw->hflist);
576     HLock((Handle) dw->hflist);
577     fl = *dw->hflist;
578     for (i = dw->count; i; --i, ++fl) {
579     if (fl->vRefNum == vRefNum && fl->dirID == dirID &&
580     *fl->fname == *fname && !strncmp(C(fl->fname), C(fname), *fl->fname)) {
581     break;
582     }
583     }
584     if (!i) {
585     fl->vRefNum = vRefNum;
586     fl->dirID = dirID;
587     PtoPCstrcpy(fl->fname, fname);
588     SetPt(&c, 0, dw->count);
589     LAddRow(1, ++dw->count, dw->l);
590     LSetCell((Ptr) C(fname), (short) Pstrlen(fname), c, dw->l);
591     }
592     HUnlock((Handle) dw->hflist);
593     }
594    
595     /* add file set to file list
596     */
597     static void addfile(dw, fspec)
598     listwin *dw;
599     FSSpec *fspec;
600     {
601     CInfoPBRec cipbr;
602     HFileInfo *fpb = (HFileInfo *)&cipbr;
603     PCstr fbuf[42];
604     short idx, foundone = 0;
605     long procid;
606    
607     /* remove working directory stuff */
608     if (fspec->parID == 0) {
609     GetWDInfo(fspec->vRefNum, &fspec->vRefNum, &fspec->parID, &procid);
610     }
611    
612     /* loop through directory */
613     for (idx = 1; ; ++idx) {
614     fpb->ioVRefNum = fspec->vRefNum;
615     fpb->ioNamePtr = P(fbuf);
616     fpb->ioDirID = fspec->parID;
617     fpb->ioFDirIndex = idx;
618     if (PBGetCatInfoSync(&cipbr)) break;
619     SetClen(fbuf);
620    
621     if (!(fpb->ioFlAttrib & 16) && fprefixMatch((char *)fspec->name, fbuf)) {
622     addit(dw, fspec->vRefNum, fspec->parID, (char *) P(fbuf));
623     foundone = 1;
624     }
625     }
626     if (!foundone) {
627     addit(dw, fspec->vRefNum, fspec->parID, (char *) fspec->name);
628     }
629     }
630    
631     /* remove file from file list
632     */
633     static void removefile(dw)
634     listwin *dw;
635     {
636     filelist *fl;
637     int count;
638     Cell c;
639    
640     c.h = c.v = 0;
641     if (LGetSelect(TRUE, &c, dw->l)) {
642     MoveHHi((Handle) dw->hflist);
643     HLock((Handle) dw->hflist);
644     fl = *dw->hflist + c.v;
645     count = dw->count - c.v;
646     while (--count) {
647     fl[0] = fl[1];
648     ++fl;
649     }
650     HUnlock((Handle) dw->hflist);
651     --dw->count;
652     LDelRow(1, c.v, dw->l);
653     }
654     }
655    
656     /* close list window
657     */
658     static short listclose(win)
659     na_win *win;
660     {
661     LDispose(dwin->l);
662    
663     return (alldone(win));
664     }
665    
666     /* mouse procedure
667     */
668     static short listmouse(na_win *win, Point p, short type, short mods)
669     {
670     Cell c;
671    
672     if (!(type & 1)) {
673     LClick(p, mods, dwin->l);
674     c.h = c.v = 0;
675     NAhiliteDItem((DialogPtr)win->pwin, iRemove, LGetSelect(TRUE, &c, dwin->l) ? 0 : 255);
676     }
677    
678     return (NA_NOTPROCESSED);
679     }
680    
681     /* control procedure
682     */
683     static short listctrl(na_win *win, Point p, short item, short mods, ControlHandle ctrlh)
684     {
685     StandardFileReply reply;
686    
687     switch (item) {
688     case iAdd:
689     NAgetFile(NULL, 1, textList, &reply);
690     if (reply.sfGood) {
691     if (!dwin->count) {
692     NAhiliteDItem((DialogPtr)win->pwin, iOk, 0);
693     }
694     addfile(dwin, &reply.sfFile);
695     }
696     return (NA_PROCESSED);
697    
698     case iRemove:
699     removefile(dwin);
700     NAhiliteDItem((DialogPtr)win->pwin, iRemove, 255);
701     if (!dwin->count) {
702     NAhiliteDItem((DialogPtr)win->pwin, iOk, 255);
703     }
704     return (NA_PROCESSED);
705    
706     case iOk:
707     win->afterp = do_decodefiles;
708     case iCancel:
709     return (NA_REQCLOSE);
710     }
711    
712     return (NA_NOTPROCESSED);
713     }
714    
715     /* update the list window
716     */
717     static short listupdate(na_win *win, Boolean resize)
718     {
719     Rect r;
720    
721     NAgetDRect(win->pwin, iFileList, &r);
722     FrameRect(&r);
723     LUpdate(win->pwin->visRgn, dwin->l);
724    
725     return (NA_NOTPROCESSED);
726     }
727    
728     /* initialize the list window
729     */
730     static short listinit(win, data)
731     na_win *win;
732     long *data;
733     {
734     FSSpec *fspec = (FSSpec *) data;
735     Rect r, zrect;
736     Point p;
737     Handle hand;
738     short type;
739    
740     GetDItem((DialogPtr)win->pwin, iFileList, &type, &hand, &r);
741     InsetRect(&r, 1, 1);
742     zrect.top = zrect.bottom = zrect.left = p.h = p.v = 0;\
743     zrect.right = 1;
744     dwin->l = LNew(&r, &zrect, p, 0, win->pwin, 0, 0, 0, 1);
745     if (!dwin->l) return (NA_CLOSED);
746     (*dwin->l)->selFlags = lOnlyOne;
747     dwin->hflist = (filelist **) NewHandle(sizeof (filelist));
748     if (!dwin->hflist) {
749     LDispose(dwin->l);
750     return (NA_CLOSED);
751     }
752     dwin->count = 0;
753     addfile(dwin, fspec);
754     win->closep = listclose;
755     win->updatep = listupdate;
756     win->ctrlp = listctrl;
757     win->mousep = listmouse;
758     win->type = DECODELIST;
759     NAhiliteDItem((DialogPtr)win->pwin, iRemove, 255);
760     ShowWindow(win->pwin);
761     LDoDraw(TRUE, dwin->l);
762    
763     return (NA_NOTPROCESSED);
764     }
765    
766     /* Decode procedure: first get a file, then open decode window
767     */
768     static void do_decode(FSSpec *fspec)
769     {
770     StandardFileReply infile;
771     na_win **wh, *wp;
772    
773     if (!fspec) {
774     NAgetFile(NULL, 1, textList, &infile);
775     if (!infile.sfGood) return;
776     fspec = &infile.sfFile;
777     } else {
778     /* file supplied by drag & drop, look for existing decode window: */
779     for (wh = NAhead; wh && (*wh)->type != DECODELIST; wh = (*wh)->next);
780     if (wh && (wp = NAlockWindow(wh)) != NULL) {
781     addfile((listwin *) wp, fspec);
782     NAunlockWindow(wp);
783     return;
784     }
785     }
786     NAwindow(0, NA_DIALOGWINDOW | NA_USERESOURCE | NA_DEFBUTTON |
787     NA_HASCONTROLS | NA_CLOSEBOX, NULL, decodeDLOG, (long *) fspec,
788     sizeof (listwin), listinit);
789     }
790    
791     /* Map MIME type to/from Macintosh file types
792     */
793     void MapTypeCreator(char *contenttype, OSType type)
794     {
795     extern long _ftype, _fcreator;
796     PCstr tstr[257];
797     Handle h;
798     ICAttr attr;
799     long size = 0;
800     Ptr map;
801     ICMapEntry *ment;
802     unsigned char *scan, *end, *pstr;
803     short mapcount, i, foundit = 0;
804     OSType temp;
805    
806     if (!type) CtoPCstrncpy(tstr, contenttype, 255);
807    
808     /* first try a lookup via Internet Config */
809     if (icinst && ICBegin(icinst, icReadOnlyPerm) == noErr) {
810     if (ICGetPref(icinst, kICMapping, &attr, nil, &size) == noErr
811     && size > 0 && (map = NewPtr(size)) != nil) {
812     if (ICGetPref(icinst, kICMapping, &attr, map, &size) == noErr) {
813     scan = (unsigned char *) map;
814     end = scan + size;
815     while (scan < end) {
816     ment = (ICMapEntry *) scan;
817     pstr = scan + ment->fixed_length;
818     scan += ment->total_length;
819     if (type && ment->file_type != type) continue;
820     pstr += *pstr + 1; /* skip over extension */
821     pstr += *pstr + 1; /* skip over creator app name */
822     pstr += *pstr + 1; /* skip over post app name */
823     if (type) {
824     PtoPCstrcpy((PCstr *) contenttype, (char *) pstr);
825     foundit = 1;
826     break;
827     } else if (EqualString(P(tstr), pstr, false, true)) {
828     _ftype = ment->file_type;
829     _fcreator = ment->file_creator;
830     foundit = 1;
831     break;
832     }
833     }
834     }
835     DisposPtr(map);
836     }
837     ICEnd(icinst);
838     }
839    
840     /* if we didn't find it, try our quick&dirty mappings */
841     if (!foundit) {
842     if (type) {
843     mapcount = CountResources('TyCr');
844     for (i = 1; i <= mapcount; ++i) {
845     h = GetIndResource('TyCr', i);
846     if (h && **(OSType **)h == type) {
847     GetResInfo(h, &i, &temp, P(contenttype));
848     if (ResError() == noErr) break;
849     }
850     }
851     SetClen((PCstr *) contenttype);
852     } else {
853     h = GetNamedResource('TyCr', P(tstr));
854     if (h) {
855     _ftype = (*(OSType **)h)[0];
856     _fcreator = (*(OSType **)h)[1];
857     } else {
858     _ftype = '????';
859     _fcreator = 'mPAK';
860     }
861     }
862     }
863     }
864    
865     /* get internet config string prefs
866     */
867     static short getICprefs(na_win *win, PCstr *eaddr, PCstr *smtphost)
868     {
869     char *scan, *end;
870     ICAttr attr;
871     long size;
872     ICError err = noErr;
873    
874     *C(eaddr) = '\0';
875     SetPlen(eaddr);
876     *C(smtphost) = '\0';
877     SetPlen(smtphost);
878     if (icinst && ICBegin(icinst, icReadOnlyPerm) == noErr) {
879     size = 256;
880     if (ICGetPref(icinst, kICEmail, &attr, (Ptr) eaddr, &size) == noErr
881     && win && (attr & ICattr_locked_mask)) {
882     NAenableDItem(win->pwin, iEmailAddr, 0);
883     }
884     SetClen(eaddr);
885     size = 256;
886     if (ICGetPref(icinst, kICSMTPHost, &attr, (Ptr) smtphost, &size) == noErr
887     && win && (attr & ICattr_locked_mask)) {
888     NAenableDItem(win->pwin, iMailServer, 0);
889     }
890     SetClen(smtphost);
891     ICEnd(icinst);
892     } else {
893     HLock((Handle) mpack_prefs);
894     end = (char *) (*mpack_prefs) + GetHandleSize((Handle) mpack_prefs);
895     scan = (*mpack_prefs)->internet_host;
896     while (scan < end && *scan++);
897     if (scan < end) CtoPCstrcpy(eaddr, scan);
898     while (scan < end && *scan++);
899     if (scan < end) CtoPCstrcpy(smtphost, scan);
900     HUnlock((Handle) mpack_prefs);
901     }
902     }
903    
904     /* copy desc file, with word-wrap
905     */
906     static short copydesc(FILE *out, TEHandle hTE)
907     {
908     char c;
909     short i, count, word, col, reset;
910     char **htxt;
911    
912     count = (*hTE)->teLength;
913     htxt = (char **) (*hTE)->hText;
914     for (i = word = col = 0; i < count; ++i) {
915     c = (*htxt)[i];
916     reset = i - word == 80 || c == '\r';
917     if (reset || c == ' ') {
918     while (word < i) putc((*htxt)[word], out), ++word;
919     }
920     if (reset || ++col == 80) {
921     putc('\r', out);
922     c = (*htxt)[word];
923     if (c == ' ' || c == '\r') ++word;
924     col = 0;
925     }
926     }
927     while (word < i) putc((*htxt)[word], out), ++word;
928     rewind(out);
929     }
930    
931     /* start up MacTCP callback
932     */
933     static void mytcpinit(short status)
934     {
935     static DialogPtr dialog = NULL;
936     GrafPtr save;
937     Rect box;
938    
939     if (status < 0) {
940     tcpstart = -1;
941     } else if (status == 0) {
942     tcpstart = 1;
943     } else {
944     if (!dialog && status < 100) {
945     dialog = GetNewDialog(progDLOG, nil, (WindowPtr) -1);
946     NAsetIText(dialog, iWorkText, "\pWaiting for MacTCP to finish. Press \021. to stop.");
947     }
948     if (dialog) {
949     GetPort(&save);
950     SetPort(dialog);
951     NAgetDRect(dialog, iProgress, &box);
952     FrameRect(&box);
953     InsetRect(&box, 1, 1);
954     box.right = box.left + (box.right - box.left) * status / 100;
955     FillRect(&box, qd.dkGray);
956     SetPort(save);
957     if (status == 100) {
958     DisposDialog(dialog);
959     dialog = NULL;
960     }
961     }
962     }
963     }
964    
965     /* update the progress bar
966     */
967     static short progressupdate(na_win *win, Boolean newsize)
968     {
969     Rect box;
970    
971     if (prwin->percent >= 0) {
972     NAgetDRect(win->pwin, iProgress, &box);
973     FrameRect(&box);
974     InsetRect(&box, 1, 1);
975     if (prwin->percent) {
976     box.right = box.left + (box.right - box.left) * prwin->percent / 100;
977     FillRect(&box, qd.dkGray);
978     } else {
979     EraseRect(&box);
980     }
981     }
982    
983     return (NA_NOTPROCESSED);
984     }
985    
986     /* handle the cancel button
987     */
988     static short progressctrl(na_win *win, Point p, short item, short mods,
989     ControlHandle ctrlh)
990     {
991     return (item == iCancel ? NA_REQCLOSE : NA_NOTPROCESSED);
992     }
993    
994     /* close progress window
995     */
996     static short progressclose(na_win *win)
997     {
998     NAmodalMenus(0);
999    
1000     return (NA_CLOSED);
1001     }
1002    
1003     /* make/go directory under prefs and return directory number
1004     */
1005     static OSErr prefsubdir(PCstr *name, long *dirID)
1006     {
1007     CInfoPBRec cipbr;
1008     DirInfo *dpb = &cipbr.dirInfo;
1009     long subdir, dir;
1010     short vref = pfolder->fspec.vRefNum;
1011     OSErr err;
1012    
1013     err = DirCreate(vref, dir = pfolder->fspec.parID, P(name), &subdir);
1014     if (err == dupFNErr) {
1015     dpb->ioVRefNum = vref;
1016     dpb->ioNamePtr = P(name);
1017     dpb->ioDrDirID = dir;
1018     dpb->ioFDirIndex = 0;
1019     if ((err = PBGetCatInfoSync(&cipbr)) != noErr) return (err);
1020     subdir = dpb->ioDrDirID;
1021     } else if (err != noErr) {
1022     return (err);
1023     }
1024     *dirID = subdir;
1025    
1026     return (noErr);
1027     }
1028    
1029     /* smtp status task
1030     */
1031     static void smtpstat(void *wh, short code, short err, long num, char *errstr)
1032     {
1033     na_win *win, **winh;
1034     char msg[256];
1035     OSErr oserr = noErr;
1036    
1037     /* verify win is valid */
1038     for (winh = NAhead; winh && winh != wh; winh = (*winh)->next);
1039     if (!winh) return;
1040    
1041     /* handle SMTP callback */
1042     win = NAlockWindow((na_win **) wh);
1043     if (code == NASMTP_progress) {
1044     prwin->percent = err;
1045     progressupdate(win, false);
1046     } else if (code == NASMTP_badaddr) {
1047     sprintf(msg, "Invalid address: <%s>. Email will be sent to valid recipients.",
1048     errstr);
1049     yell(msg);
1050     } else {
1051     switch (code) {
1052     case NASMTP_nomem:
1053     yell("Not enough memory to send email");
1054     break;
1055     case NASMTP_tcpfail:
1056     yell("Failed to connect to mail host");
1057     break;
1058     case NASMTP_temperr:
1059     case NASMTP_permerr:
1060     sprintf(msg, "Delivery failed: %s", errstr);
1061     yell(msg);
1062     break;
1063     default:
1064     yell("Mail delivery failed.");
1065     case NASMTP_completed:
1066     break;
1067     }
1068     mwin->sending = false;
1069     oserr = HDelete(mwin->fspec.vRefNum, mwin->fspec.parID, mwin->fspec.name);
1070     }
1071     if (oserr != noErr && oserr != fnfErr) {
1072     if (mwin->remaining) ++mwin->cpb.hFileInfo.ioFDirIndex;
1073     yell("Unable to remove temporary email file.");
1074     }
1075     NAunlockWindowh((na_win **) wh, win);
1076     }
1077    
1078     /* Get the email hostname
1079     */
1080     static void mailhost(void *user, na_tcp s, short status, long size, char *data)
1081     {
1082     struct mpack_preferences *mp;
1083     char *ihost;
1084     na_win *win, **winh;
1085     long len, oldsize;
1086    
1087     /* first make sure our window still exists */
1088     for (winh = NAhead; winh && winh != user; winh = (*winh)->next);
1089     if (!winh) return;
1090     win = NAlockWindow(winh);
1091    
1092     /* check for errors */
1093     if (status != NATCP_connect) {
1094     warn("Failed to get hostname from MacTCP");
1095     } else {
1096     mwin->gothost = true;
1097     if (data[size - 1] == '.') --size;
1098    
1099     /* update internet_host preference */
1100     len = strlen((*mpack_prefs)->internet_host);
1101     oldsize = GetHandleSize((Handle) mpack_prefs);
1102     if (len < size) {
1103     SetHandleSize((Handle) mpack_prefs, oldsize + (size - len));
1104     if (MemError() != noErr) return;
1105     }
1106     HLock((Handle) mpack_prefs);
1107     mp = *mpack_prefs;
1108     ihost = mp->internet_host;
1109     memmove(ihost + size + 1, ihost + len + 1,
1110     oldsize - len - 1 - ((char *) ihost - (char *) mp));
1111     memcpy(ihost, data, size);
1112     ihost[size] = '\0';
1113     HUnlock((Handle) mpack_prefs);
1114     }
1115     NAunlockWindowh(winh, win);
1116     }
1117    
1118     /* clean up mail task
1119     */
1120     static short mailclose(na_win *win)
1121     {
1122     if (mwin->dfile != NULL) fclose(mwin->dfile);
1123     if (mwin->envelope) DisposeHandle(mwin->envelope);
1124     if (mwin->headers) DisposeHandle(mwin->headers);
1125     NAmodalMenus(0);
1126    
1127     return (alldone(win));
1128     }
1129    
1130     /* send email
1131     */
1132     static short mailtask(na_win *win)
1133     {
1134     short vrefnum, encoding, refnum, result;
1135     long procid;
1136     FILE *tmpf, *fp, *resfork;
1137     OSErr err;
1138     CInfoPBRec cipbr;
1139     HFileInfo *fpb = (HFileInfo *)&cipbr;
1140     PCstr tstr[257], mtype[257], fname[257];
1141     extern long _ftype, _fcreator;
1142    
1143     switch (mwin->state) {
1144     case MS_MACTCP:
1145     if (tcpstart < 0) {
1146     yell("Couldn't find MacTCP");
1147     return (NA_REQCLOSE);
1148     }
1149     if (tcpstart == 0) break;
1150     ++mwin->state;
1151     NAsetIText(win->pwin, iWorkText, "\pGetting Hostname");
1152     mwin->gothost = false;
1153     NATCPgethost(mailhost, (void *) GetWRefCon(win->pwin));
1154     /* fall through */
1155     case MS_GETHOST:
1156     if (!mwin->gothost) break;
1157     ++mwin->state;
1158     /* fall through */
1159     case MS_ENCODE:
1160     NAsetIText(win->pwin, iWorkText, "\pEncoding file");
1161    
1162     /* get temp output filename for email */
1163     if (mwin->useemail) {
1164     mwin->ofile.vRefNum = pfolder->fspec.vRefNum;
1165     memcpy(mwin->ofile.name, "\pemail", 6);
1166     if (prefsubdir("\poutgoing-email", &mwin->ofile.parID) != noErr) {
1167     yell("Failed to write encoded file");
1168     return (NA_REQCLOSE);
1169     }
1170     }
1171    
1172     /* set file type */
1173     SetCursor(&watch);
1174     MapTypeCreator((char *) mtype, mwin->ftype);
1175    
1176     /* Determine the correct encoding */
1177     encoding = (*mpack_prefs)->encoding;
1178     fpb->ioVRefNum = mwin->fspec.vRefNum;
1179     fpb->ioNamePtr = mwin->fspec.name;
1180     fpb->ioDirID = mwin->fspec.parID;
1181     fpb->ioFDirIndex = 0;
1182     if (PBGetCatInfoSync(&cipbr) != noErr) {
1183     SetCursor(&arrow);
1184     yell("File disappeared before being encoded!");
1185     return (NA_REQCLOSE);
1186     }
1187     if (encoding == EN_AUTO) {
1188     encoding = EN_DOUBLE;
1189     if (!fpb->ioFlRLgLen && *mtype != '\0') encoding = EN_DATA;
1190     }
1191     if (!fpb->ioFlLgLen) encoding = EN_SINGLE;
1192    
1193     /* do applesingle/appledouble encoding */
1194     tmpf = tmpfile();
1195     fp = Macopen(tmpf, mwin->fspec.name, mwin->fspec.vRefNum, mwin->fspec.parID,
1196     strcmp(C(mtype), "text/plain") ? 1 : 0, 0, fsRdPerm);
1197     if (!fp) {
1198     fclose(tmpf);
1199     SetCursor(&arrow);
1200     yell("Couldn't save encoded file");
1201     return (NA_REQCLOSE);
1202     }
1203     if (encoding == EN_DATA) {
1204     fclose(tmpf);
1205     tmpf = NULL;
1206     } else {
1207     /* open resource fork & output file for applesingle/double encoding */
1208     resfork = Macopen(tmpf, mwin->fspec.name, mwin->fspec.vRefNum,
1209     mwin->fspec.parID, 1, 1, 1);
1210     if (encode_applefile(tmpf, fpb, resfork, encoding == EN_SINGLE ? fp : NULL) < 0) {
1211     SetCursor(&arrow);
1212     yell("Couldn't save encoded file");
1213     return (NA_REQCLOSE);
1214     }
1215     rewind(tmpf);
1216     if (encoding == EN_SINGLE) {
1217     fp = tmpf;
1218     tmpf = NULL;
1219     strcpy(C(mtype), "application/applefile");
1220     SetPlen(mtype);
1221     }
1222     }
1223    
1224     /* generate output files */
1225     _fcreator = 'mPAK';
1226     _ftype = 'TEXT';
1227     GetVol(0, &vrefnum);
1228     err = OpenWD(mwin->ofile.vRefNum, mwin->ofile.parID, 0, &refnum);
1229     SetVol(0, err == noErr ? refnum : mwin->ofile.vRefNum);
1230     PtoPCstrcpy(tstr, (char *) mwin->ofile.name);
1231     PtoPCstrcpy(fname, (char *) mwin->fspec.name);
1232     result = encode(fp, tmpf, C(fname), mwin->dfile, C(mwin->subj), NULL,
1233     mwin->partsize, PCstrlen(mtype) ? C(mtype) : NULL, C(tstr));
1234     if (err == noErr) CloseWD(refnum);
1235     SetVol(0, vrefnum);
1236     if (tmpf) fclose(tmpf);
1237     fclose(fp);
1238     if (mwin->dfile) {
1239     fclose(mwin->dfile);
1240     mwin->dfile = NULL;
1241     }
1242     SetCursor(&arrow);
1243     if (!mwin->useemail) return (NA_REQCLOSE);
1244     prwin->percent = 0;
1245     progressupdate(win, false);
1246     ++mwin->state;
1247    
1248     /* count files */
1249     mwin->cpb.dirInfo.ioVRefNum = mwin->ofile.vRefNum;
1250     mwin->cpb.dirInfo.ioDrDirID = mwin->dirID = mwin->ofile.parID;
1251     mwin->cpb.dirInfo.ioFDirIndex = -1;
1252     if (PBGetCatInfoSync(&mwin->cpb) != noErr) {
1253     return (NA_CLOSED);
1254     }
1255     mwin->remaining = mwin->cpb.dirInfo.ioDrNmFls;
1256     mwin->cpb.dirInfo.ioFDirIndex = 1;
1257     /* fall through */
1258     case MS_SENDING:
1259     if (mwin->sending) break;
1260     if (!mwin->remaining) return (NA_REQCLOSE);
1261     sprintf(C(tstr), "Email parts remaining to submit: %d", mwin->remaining--);
1262     SetPlen(tstr);
1263     NAsetIText(win->pwin, iWorkText, tstr);
1264     prwin->percent = 0;
1265     progressupdate(win, false);
1266     mwin->cpb.hFileInfo.ioDirID = mwin->dirID;
1267     mwin->cpb.hFileInfo.ioNamePtr = (StringPtr) &mwin->fspec.name;
1268     if (PBGetCatInfoSync(&mwin->cpb) != noErr) {
1269     yell("Email disappeared before submission!");
1270     return (NA_REQCLOSE);
1271     }
1272     mwin->sending = true;
1273     mwin->fspec.vRefNum = mwin->cpb.hFileInfo.ioVRefNum;
1274     mwin->fspec.parID = mwin->dirID;
1275     NASMTPsubmit(smtpstat, C(mwin->server), &mwin->fspec,
1276     mwin->headers, mwin->envelope,
1277     NASMTP_crtrans, (void *) GetWRefCon(win->pwin));
1278     break;
1279     }
1280    
1281     return (NA_NOTPROCESSED);
1282     }
1283    
1284     /* Following routine stolen from Mark Crispin's c-client library:
1285     *
1286     * Write current time in RFC 822 format
1287     * Accepts: destination string
1288     *
1289     * This depends upon the ReadLocation() call in System 7 and the
1290     * user properly setting his location/timezone in the Map control
1291     * panel.
1292     * 2/95 - I added support for dlsDelta & compatibility checking
1293     */
1294     void rfc822_date(char *string)
1295     {
1296     long tz, tzm;
1297     time_t ti = time (0);
1298     struct tm *t = localtime (&ti);
1299     MachineLocation loc;
1300    
1301     /* output date */
1302     strcpy(string, "Date: ");
1303     string += 6;
1304     strftime (string,1024,"%a, %d %b %Y %H:%M:%S ",t);
1305     /* now output time zone, if we can get it */
1306     tz = 0;
1307     if (Gestalt(gestaltScriptMgrVersion, &tz) == noErr && tz >= 200) {
1308     ReadLocation(&loc); /* get location/timezone */
1309     /* get sign-extended time zone */
1310     tz = (loc.gmtFlags.gmtDelta & 0x00ffffff) |
1311     ((loc.gmtFlags.gmtDelta & 0x00800000) ? 0xff000000 : 0);
1312     tz /= 60; /* get timezone in minutes */
1313     tzm = tz % 60; /* get minutes from the hour */
1314     sprintf (string += strlen(string),"%+03ld%02ld",
1315     tz/60,tzm >= 0 ? tzm : -tzm);
1316     if (!tzm && tz <= -240 && tz >= -660) {
1317     string += strlen(string);
1318     if (loc.gmtFlags.dlsDelta & 0x80) {
1319     sprintf(string, " (%cDT)", "AECMPYHB"[- (tz / 60) - 3]);
1320     } else {
1321     sprintf(string, " (%cST)", "AECMPYHB"[- (tz / 60) - 4]);
1322     }
1323     }
1324     } else {
1325     sprintf(string + strlen(string), "+0000 (Local Time Zone Unknown)");
1326     }
1327     }
1328    
1329     /* init mail sending
1330     */
1331     static short mailinit(na_win *win, long *data)
1332     {
1333     encodewin *ew = (encodewin *) data;
1334     WindowPtr pwin = ew->w.winp.pwin;
1335     ControlHandle ctrlh;
1336     PCstr tstr[257], email[257];
1337    
1338     /* copy values from encode window */
1339     NAgetIText(pwin, iSubj, mwin->subj);
1340     NAgetIText(pwin, iEmailto, email);
1341     mwin->partsize = ew->partsize;
1342     mwin->useemail = ew->useemail;
1343     mwin->fspec = ew->fspec;
1344     mwin->ftype = ew->ftype;
1345     mwin->ofile = ew->ofile;
1346    
1347     /* copy desc file */
1348     mwin->dfile = NULL;
1349     if ((*ew->w.hTE)->teLength && (mwin->dfile = tmpfile()) != NULL) {
1350     copydesc(mwin->dfile, ew->w.hTE);
1351     }
1352    
1353     /* set procedures */
1354     win->taskp = mailtask;
1355     win->updatep = progressupdate;
1356     win->ctrlp = progressctrl;
1357     win->closep = mailclose;
1358    
1359     /* Customize Progress window, set up envelope & headers for email */
1360     prwin->percent = -1;
1361     NAgetDHandle(win->pwin, iCancel, &ctrlh);
1362     SetCTitle(ctrlh, "\pStop");
1363     NAmodalMenus(1);
1364     if (!mwin->useemail) {
1365     mwin->state = MS_ENCODE;
1366     } else {
1367     if (!tcpstart) NATCPinit(mytcpinit);
1368     NAsetIText(win->pwin, iWorkText, "\pLooking for MacTCP");
1369     mwin->state = MS_MACTCP;
1370    
1371     /* create envelope, get server */
1372     getICprefs(NULL, tstr, mwin->server);
1373     if (PtrToHand(C(tstr), &mwin->envelope, PCstrlen(tstr) + 1) != noErr
1374     || PtrAndHand(C(email), mwin->envelope, PCstrlen(email) + 1) != noErr) {
1375     if (mwin->envelope) DisposeHandle(mwin->envelope);
1376     return (NA_CLOSED);
1377     }
1378    
1379     /* create headers */
1380     if ((mwin->headers = NewHandle(1024)) == NULL) {
1381     DisposeHandle(mwin->envelope);
1382     return (NA_CLOSED);
1383     }
1384     HLock(mwin->headers);
1385     rfc822_date((char *) *mwin->headers);
1386     sprintf((char *) (*mwin->headers) + strlen((char *) (*mwin->headers)),
1387     "\r\nFrom: %s\r\nTo: %s\r\n", C(tstr), C(email));
1388     HUnlock(mwin->headers);
1389     SetHandleSize(mwin->headers, strlen((char *) (*mwin->headers)));
1390     }
1391    
1392     return (NA_NOTPROCESSED);
1393     }
1394    
1395     /* update the encode window
1396     */
1397     static short encodeupdate(na_win *win, Boolean newsize)
1398     {
1399     Rect btmp;
1400     ControlHandle ctrlh;
1401    
1402     /* draw double-line */
1403     NAgetDRect(win->pwin, iBar, &btmp);
1404     FrameRect(&btmp);
1405    
1406     /* draw disabled edittext boxes */
1407     NAgetDHandle(win->pwin, iLimit, &ctrlh);
1408     if (!GetCtlValue(ctrlh)) {
1409     NAhiliteDItem(win->pwin, iPartLimit, 255);
1410     }
1411     if (NAradioGet(win->pwin, iEmail, iSavefile) == iSavefile) {
1412     NAhiliteDItem(win->pwin, iEmailto, 255);
1413     }
1414    
1415     return (NATEupdatep(win, newsize));
1416     }
1417    
1418     /* select desc text
1419     */
1420     static short seldesctext(na_win *win)
1421     {
1422     win->activep = NATEactivep;
1423     win->idlep = NATEidlep;
1424     NATEactivep(win, true);
1425     ewin->nateon = true;
1426     SelIText(win->pwin, iDescEdit, 0, 0);
1427     TESetSelect(32767, 32767, twin->hTE);
1428     }
1429    
1430     /* encode control proc
1431     */
1432     static short encodectrl(na_win *win, Point p, short item,
1433     short mods, ControlHandle ctrlh)
1434     {
1435     short value;
1436     DialogPeek dpeek = (DialogPeek) win->pwin;
1437     char *scan;
1438     Boolean good;
1439     StandardFileReply reply;
1440     PCstr tstr[257];
1441    
1442     if (ctrlh == twin->vctrl) {
1443     return (NATEctrlp(win, p, item, mods, ctrlh));
1444     }
1445     switch (item) {
1446     case iOk:
1447     /* get part size */
1448     ewin->partsize = 0;
1449     NAgetDHandle(win->pwin, iLimit, &ctrlh);
1450     if (GetCtlValue(ctrlh)) {
1451     NAgetIText(win->pwin, iPartLimit, tstr);
1452     ewin->partsize = atol(C(tstr)) * 1000;
1453     }
1454     NAgetIText(win->pwin, iEmailto, tstr);
1455     ewin->useemail = NAradioGet(win->pwin, iEmail, iSavefile) == iEmail;
1456     if (ewin->useemail) {
1457     /* verify email address */
1458     if (!strchr(C(tstr), '@')) {
1459     yell("Invalid Email address, please re-enter");
1460     SelIText(win->pwin, iEmailto, 0, 32767);
1461     break;
1462     }
1463     } else {
1464     /* get output filename */
1465     PtoPCstrcpy(tstr, (char *) ewin->fspec.name);
1466     if (PCstrlen(tstr) > 23) {
1467     PCstrlen(tstr) = 23;
1468     SetClen(tstr);
1469     }
1470     strcat(C(tstr), ".mime");
1471     SetPlen(tstr);
1472     do {
1473     NAputFile(ewin->partsize ? "\pPart prefix" : "\pEmail file:",
1474     tstr, &reply);
1475     good = true;
1476     if (reply.sfGood
1477     && EqualString(reply.sfFile.name,
1478     ewin->fspec.name, true, false)) {
1479     good = false;
1480     yell("The output filename must be different from the input filename");
1481     }
1482     } while (!good);
1483     if (!reply.sfGood) break;
1484     ewin->ofile = reply.sfFile;
1485     }
1486     if (NAwindow(0, NA_DIALOGWINDOW | NA_TITLEBAR | NA_HASTASK
1487     | NA_USERESOURCE | NA_MODAL, NULL, progDLOG,
1488     (long *) win, sizeof (mailwin), mailinit) == NA_CLOSED) {
1489     warn("Not enough memory to proceed");
1490     break;
1491     }
1492     case iCancel:
1493     return (NA_REQCLOSE);
1494     case iEmail:
1495     case iSavefile:
1496     NAradioSet(win->pwin, iEmail, iSavefile, item);
1497     NAenableDItem(win->pwin, iEmailto, item == iEmail ? 1 : 0);
1498     NAhiliteDItem(win->pwin, iEmailto, item == iEmail ? 0 : 255);
1499     if (item == iEmail || dpeek->editField == iEmailto - 1) {
1500     SelIText(win->pwin, item == iEmail ? iEmailto : iSubj, 0, 32767);
1501     }
1502     break;
1503     case iLimit:
1504     SetCtlValue(ctrlh, value = !GetCtlValue(ctrlh));
1505     NAenableDItem(win->pwin, iPartLimit, value ? 1 : 0);
1506     NAhiliteDItem(win->pwin, iPartLimit, value ? 0 : 255);
1507     if (value || dpeek->editField == iPartLimit - 1) {
1508     SelIText(win->pwin, value ? iPartLimit : iSubj, 0, 32767);
1509     }
1510     break;
1511     case iDescEdit:
1512     case iSubj:
1513     case iEmailto:
1514     case iPartLimit:
1515     if (!ewin->nateon && dpeek->editField == iDescEdit - 1) {
1516     seldesctext(win);
1517     }
1518     break;
1519     }
1520     if (ewin->nateon && dpeek->editField != iDescEdit - 1) {
1521     win->activep = NULL;
1522     win->idlep = NULL;
1523     NATEactivep(win, false);
1524     ewin->nateon = false;
1525     }
1526    
1527     return (NA_NOTPROCESSED);
1528     }
1529    
1530     /* encode key proc
1531     */
1532     static short encodekey(na_win *win, long c, short mods)
1533     {
1534     if (!(mods & cmdKey)) {
1535     if (ewin->nateon && c != '\t' && c != '\n' && c != '\3' && c != '\033') {
1536     return (NATEkeyp(win, c, mods));
1537     }
1538     }
1539    
1540     return (NA_NOTPROCESSED);
1541     }
1542    
1543     /* menu proc for encode window
1544     */
1545     static short encodemenu(na_win *win, WORD menu, WORD item)
1546     {
1547     StandardFileReply descfile;
1548     MenuHandle mf = NAmenuh(mFile);
1549     short result = NA_NOTPROCESSED;
1550     short refnum;
1551     long size;
1552     Ptr text;
1553     Boolean success;
1554    
1555     switch (menu) {
1556     case 0:
1557     EnableItem(mf, iInsert);
1558     /* fall through */
1559     case mEdit:
1560     result = ewin->nateon ? NATEmenup(win, menu, item)
1561     : NAdialogMenu(win, menu, item);
1562     break;
1563     case mFile:
1564     if (item != iInsert) break;
1565     result = NA_PROCESSED;
1566     NAgetFile(NULL, 1, textList, &descfile);
1567     if (!descfile.sfGood) break;
1568     if (HOpen(descfile.sfFile.vRefNum, descfile.sfFile.parID,
1569     descfile.sfFile.name, fsRdPerm, &refnum) != noErr) {
1570     warn("Failed to open file");
1571     break;
1572     }
1573     text = NULL;
1574     success = GetEOF(refnum, &size) == noErr && (text = NewPtr(size)) != NULL
1575     && FSRead(refnum, &size, text) == noErr;
1576     if (success) {
1577     TEInsert(text, size, twin->hTE);
1578     TESelView(twin->hTE);
1579     NATEsetscroll(win, false, (Rect*) NULL, (Rect*) NULL);
1580     } else {
1581     warn("Failed to read file");
1582     }
1583     if (text) DisposPtr(text);
1584     FSClose(refnum);
1585     break;
1586     }
1587     if (menu != 0) DisableItem(mf, iInsert);
1588    
1589     return (result);
1590     }
1591    
1592     /* mouse proc for encode window
1593     */
1594     static short encodemouse(na_win *win, Point p, short type, short mods)
1595     {
1596     if (p.v >= twin->topoff && !ewin->nateon) seldesctext(win);
1597    
1598     return (NATEmousep(win, p, type, mods));
1599     }
1600    
1601     /* close the encode window
1602     */
1603     static short encodeclose(na_win *win)
1604     {
1605     NATEclosep(win);
1606    
1607     return (NA_CLOSED);
1608     }
1609    
1610     /* init the encode window
1611     */
1612     static short encodeinit(na_win *win, long *data)
1613     {
1614     StandardFileReply *sf = (StandardFileReply *) data;
1615     Rect rtmp, btmp;
1616     FontInfo finfo;
1617    
1618     /* copy data */
1619     ewin->fspec = sf->sfFile;
1620     ewin->ftype = sf->sfType;
1621    
1622     /* set sizing limits */
1623     NAgetDRect(win->pwin, iBar, &btmp);
1624     rtmp = win->pwin->portRect;
1625     win->minw = win->maxw = rtmp.right - rtmp.left;
1626     win->minh = btmp.bottom + 64;
1627     twin->topoff = btmp.bottom;
1628    
1629     /* init text area */
1630     TextFont(monaco);
1631     TextSize(9);
1632     GetFontInfo(&finfo);
1633     NATEinit(win, NATE_NOHSCROLL, 80 * finfo.widMax + 2, NULL, 0);
1634     ewin->nateon = 0;
1635     TextFont(0);
1636     TextSize(0);
1637    
1638     /* set control values */
1639     NAradioSet(win->pwin, iEmail, iSavefile, iSavefile);
1640     if (tcpstart < 0) NAhiliteDItem(win->pwin, iEmail, 255);
1641     NAenableDItem(win->pwin, iEmailto, 0);
1642     NAenableDItem(win->pwin, iPartLimit, 0);
1643     NAsetIText(win->pwin, iSubj, ewin->fspec.name);
1644     SelIText(win->pwin, iSubj, 0, 32767);
1645     SetWTitle(win->pwin, ewin->fspec.name);
1646     ShowWindow(win->pwin);
1647    
1648     /* set window procedures */
1649     win->updatep = encodeupdate;
1650     win->closep = encodeclose;
1651     win->keyp = encodekey;
1652     win->ctrlp = encodectrl;
1653     win->mousep = encodemouse;
1654     win->menup = encodemenu;
1655     win->idlep = NULL;
1656     win->activep = NULL;
1657    
1658     return (NA_NOTPROCESSED);
1659     }
1660    
1661     /* Encode procedure: first get a file, then open encode save window
1662     */
1663     static void do_encode(FSSpec *fspec, OSType ftype)
1664     {
1665     StandardFileReply infile;
1666    
1667     if (!fspec) {
1668     NAgetFile(NULL, -1, NULL, &infile);
1669     if (!infile.sfGood) return;
1670     } else {
1671     infile.sfFile = *fspec;
1672     infile.sfType = ftype;
1673     }
1674     NAwindow(NULL, NA_DIALOGWINDOW | NA_TITLEBAR | NA_GROWBOX | NA_USERESOURCE
1675     | NA_DEFBUTTON | NA_HASCONTROLS,
1676     NULL, sendDLOG, (long *) &infile, sizeof (encodewin), encodeinit);
1677     }
1678    
1679     /* Open a file via drag&drop
1680     */
1681     static short openfile(short message, FSSpec *fspec, FInfo *finfo)
1682     {
1683     if (message != appOpen) return (-1);
1684    
1685     /* open file */
1686     if (finfo->fdType == 'TEXT') {
1687     do_decode(fspec);
1688     } else {
1689     do_encode(fspec, finfo->fdType);
1690     }
1691    
1692     return (0);
1693     }
1694    
1695     #define hwinfo ((nate_win *)win)
1696    
1697     /* help close procedure
1698     */
1699     static short helpclose(na_win *win)
1700     {
1701     helpw = NULL;
1702    
1703     return (NATEclosep(win));
1704     }
1705    
1706     /* help window procedure
1707     */
1708     static short helpwindow(na_win *win, long *data)
1709     {
1710     Rect rtemp, vtemp;
1711     Handle h, hs;
1712     long len;
1713     TEHandle hTE;
1714    
1715     rtemp = win->pwin->portRect;
1716     vtemp = rtemp;
1717     vtemp.right = vtemp.left + (hwinfo->docwidth = 475);
1718     win->mousep = NATEmousep;
1719     win->idlep = NATEidlep;
1720     win->menup = NATEmenup;
1721     win->activep = NATEactivep;
1722     win->updatep = NATEupdatep;
1723     win->ctrlp = NATEctrlp;
1724     win->closep = helpclose;
1725     win->cursorRgn = NewRgn();
1726     hwinfo->vctrl = hwinfo->hctrl = NULL;
1727    
1728     TEAutoView(true, hTE = hwinfo->hTE = TEStylNew(&vtemp, &rtemp));
1729     h = GetResource('TEXT', helpTEXT);
1730     hs = GetResource('styl', helpSTYL);
1731     len = GetHandleSize(h);
1732     HLock(h);
1733     TEStylInsert(*h, len, (StScrpHandle) hs, hTE);
1734     HUnlock(h);
1735     TESetSelect(0, 0, hTE);
1736     hwinfo->lheight = TEGetHeight((*hTE)->nLines, 0, hTE) / (*hTE)->nLines;
1737     ShowWindow(helpw = win->pwin);
1738    
1739     return (NA_NOTPROCESSED);
1740     }
1741    
1742     /* Set the hostname: TCP callback
1743     */
1744     static void sethost(void *user, na_tcp s, short status, long size, char *data)
1745     {
1746     PCstr host[65];
1747     Rect box;
1748     na_win *win, **winh;
1749    
1750     /* first make sure our window still exists */
1751     for (winh = NAhead; winh && (*winh)->type != PREFWIN; winh = (*winh)->next);
1752     if (!winh || (*winh)->child != user) return;
1753     win = NAlockWindow((na_win **) user);
1754    
1755     /* check for errors */
1756     if (status != NATCP_connect) {
1757     warn("Failed to get hostname from MacTCP");
1758     } else {
1759     if (data[size - 1] == '.') --size;
1760     PCstrlen(host) = size;
1761     memcpy(C(host), data, size);
1762     NAsetIText((*winh)->pwin, iHost, host);
1763     SelIText((*winh)->pwin, iHost, 0, 32767);
1764     }
1765     prwin->percent = 100;
1766     progressupdate(win, false);
1767     NAunlockWindowh(winh, win);
1768     }
1769    
1770     /* if TCP is active, get hostname
1771     */
1772     static short settask(na_win *win)
1773     {
1774     if (tcpstart == 0 && !prwin->percent) {
1775     NAsetIText(win->pwin, iWorkText, "\pLooking for MacTCP");
1776     prwin->percent = 1;
1777     progressupdate(win, false);
1778     NATCPinit(mytcpinit);
1779     } else if (tcpstart == 1 && prwin->percent < 50) {
1780     NAsetIText(win->pwin, iWorkText, "\pLooking up Internet hostname");
1781     prwin->percent = 50;
1782     progressupdate(win, false);
1783     NATCPgethost(sethost, (void *) GetWRefCon(win->pwin));
1784     }
1785     progressupdate(win, false);
1786     if (tcpstart == -1) {
1787     warn("MacTCP not available");
1788     NAhiliteDItem((*win->parent)->pwin, iSet, 255);
1789     }
1790    
1791     return (tcpstart == -1 || prwin->percent == 100 ? NA_CLOSED : NA_NOTPROCESSED);
1792     }
1793    
1794     /* set the Internet host via MacTCP
1795     */
1796     static short setinit(na_win *win, long *data)
1797     {
1798     win->taskp = settask;
1799     win->updatep = progressupdate;
1800     win->closep = progressclose;
1801     NAmodalMenus(1);
1802    
1803     return (NA_NOTPROCESSED);
1804     }
1805    
1806     /* preference control procedure
1807     */
1808     static short prefsctrl(na_win *win, Point p, short item, short mods, ControlHandle ctrlh)
1809     {
1810     PCstr tmpstr[257];
1811     short encoding, extract_text, quit_finished, result = NA_NOTPROCESSED;
1812     ControlHandle ctrl;
1813     char *scan, *end;
1814     short changed, len, i, useic;
1815     static short prefitem[3] = { iHost, iEmailAddr, iMailServer };
1816    
1817     switch (item) {
1818     case iOk:
1819     HLock((Handle) mpack_prefs);
1820     changed = 0;
1821     encoding = NAradioGet(win->pwin, iAuto, iDouble) - iAuto;
1822     NAgetDHandle(win->pwin, iTextEncode, &ctrl);
1823     extract_text = GetCtlValue(ctrl);
1824     NAgetDHandle(win->pwin, iQuitFinish, &ctrl);
1825     quit_finished = GetCtlValue(ctrl);
1826     if (encoding != (*mpack_prefs)->encoding
1827     || extract_text != (*mpack_prefs)->extract_text
1828     || quit_finished != (*mpack_prefs)->quit_finished) {
1829     changed = 1;
1830     }
1831     if (changed) {
1832     (*mpack_prefs)->encoding = encoding;
1833     (*mpack_prefs)->extract_text = extract_text;
1834     (*mpack_prefs)->quit_finished = quit_finished;
1835     ChangedResource((Handle) mpack_prefs);
1836     changed = 0;
1837     }
1838     len = 1;
1839     scan = (*mpack_prefs)->internet_host;
1840     end = (char *) *mpack_prefs + GetHandleSize((Handle) mpack_prefs);
1841     for (i = 0; i < 3; ++i) {
1842     NAgetIText(win->pwin, prefitem[i], P(tmpstr));
1843     SetClen(tmpstr);
1844     len += PCstrlen(tmpstr);
1845     if (scan == end || strcmp(C(tmpstr), scan)) {
1846     changed = 1;
1847     }
1848     while (scan < end && *scan++);
1849     }
1850     if (changed) {
1851     HUnlock((Handle) mpack_prefs);
1852     /* update the preferences resource */
1853     SetHandleSize((Handle) mpack_prefs, sizeof (struct mpack_preferences)
1854     + len);
1855     HLock((Handle) mpack_prefs);
1856     scan = (*mpack_prefs)->internet_host;
1857     useic = icinst && ICBegin(icinst, icReadWritePerm) == noErr;
1858     for (i = 0; i < 3; ++i) {
1859     NAgetIText(win->pwin, prefitem[i], P(tmpstr));
1860     SetClen(tmpstr);
1861     strcpy(scan, C(tmpstr));
1862     scan += PCstrlen(tmpstr) + 1;
1863     if (i && useic) {
1864     ICSetPref(icinst, i == 1 ? kICEmail : kICSMTPHost,
1865     ICattr_no_change, (Ptr) P(tmpstr), PCstrlen(tmpstr) + 1);
1866     }
1867     }
1868     if (useic) ICEnd(icinst);
1869     ChangedResource((Handle) mpack_prefs);
1870     }
1871     HUnlock((Handle) mpack_prefs);
1872     case iCancel:
1873     result = NA_REQCLOSE;
1874     NAmodalMenus(0);
1875     break;
1876     case iAuto:
1877     case iData:
1878     case iSingle:
1879     case iDouble:
1880     NAradioSet(win->pwin, iAuto, iDouble, item);
1881     break;
1882     case iTextEncode:
1883     case iQuitFinish:
1884     SetCtlValue(ctrlh, !GetCtlValue(ctrlh));
1885     break;
1886     case iSet:
1887     NAwindow(0, NA_DIALOGWINDOW | NA_TITLEBAR | NA_HASTASK | NA_USERESOURCE
1888     | NA_MODAL | NA_CHILDWINDOW,
1889     NULL, progDLOG, NULL, sizeof (progresswin), setinit);
1890     break;
1891     }
1892    
1893     return (result);
1894     }
1895    
1896     /* update preferences dialog
1897     */
1898     static short prefsupdate(na_win *win, Boolean newsize)
1899     {
1900     Handle hn;
1901     Rect box;
1902     short type;
1903    
1904     /* draw disabled items */
1905     GetDItem(win->pwin, iEmailAddr, &type, &hn, &box);
1906     if (type == statText) NAhiliteDItem(win->pwin, iEmailAddr, 255);
1907     GetDItem(win->pwin, iMailServer, &type, &hn, &box);
1908     if (type == statText) NAhiliteDItem(win->pwin, iMailServer, 255);
1909    
1910     return (NA_NOTPROCESSED);
1911     }
1912    
1913     /* initialize preferences dialog
1914     */
1915     static short prefsinit(na_win *win, long *data)
1916     {
1917     PCstr tmpstr[257], eaddr[257];
1918     ControlHandle ctrl;
1919    
1920     win->type = PREFWIN;
1921     win->ctrlp = prefsctrl;
1922     win->menup = NAdialogMenu;
1923     win->updatep = prefsupdate;
1924     HLock((Handle) mpack_prefs);
1925     strcpy(C(tmpstr), (*mpack_prefs)->internet_host);
1926     HUnlock((Handle) mpack_prefs);
1927     SetPlen(tmpstr);
1928     NAsetIText(win->pwin, iHost, P(tmpstr));
1929     SelIText(win->pwin, iHost, 0, 32767);
1930     getICprefs(win, eaddr, tmpstr);
1931     NAsetIText(win->pwin, iEmailAddr, P(eaddr));
1932     NAsetIText(win->pwin, iMailServer, P(tmpstr));
1933     NAradioSet(win->pwin, iAuto, iDouble, (*mpack_prefs)->encoding + iAuto);
1934     NAsetIval(win->pwin, iTextEncode, (*mpack_prefs)->extract_text);
1935     NAsetIval(win->pwin, iQuitFinish, (*mpack_prefs)->quit_finished);
1936     if (tcpstart == -1) NAhiliteDItem(win->pwin, iSet, 255);
1937     NAmodalMenus(1);
1938     ShowWindow(win->pwin);
1939    
1940     return (NA_NOTPROCESSED);
1941     }
1942    
1943     /* Main menu procedure
1944     */
1945     static short mainmenu(na_win *win, WORD menuid, WORD itemno)
1946     {
1947     short status = NA_NOTPROCESSED;
1948     MenuHandle mh;
1949     PCstr version[32];
1950    
1951     switch (menuid) {
1952     case 0:
1953     NAenableMItem(mApple, iAbout);
1954     return (status);
1955     case mApple:
1956     if (itemno == iAbout) {
1957     CtoPCstrcpy(version, MPACK_VERSION);
1958     ParamText(P(version), NULL, NULL, NULL);
1959     return (NA_NOTPROCESSED);
1960     }
1961     break;
1962    
1963     case mFile:
1964     switch (itemno) {
1965     case iEncode:
1966     do_encode(NULL, 0);
1967     status = NA_PROCESSED;
1968     break;
1969    
1970     case iDecode:
1971     do_decode(NULL);
1972     status = NA_PROCESSED;
1973     break;
1974    
1975     case iClose:
1976     break;
1977    
1978     case iPrefs:
1979     status = NAwindow(0, NA_DIALOGWINDOW | NA_USERESOURCE
1980     | NA_MODAL | NA_DEFBUTTON | NA_TITLEBAR,
1981     NULL, prefsDLOG, (long *) NULL, 0, prefsinit);
1982     break;
1983    
1984     case iQuit:
1985     status = NA_REQCLOSEALL;
1986     break;
1987     }
1988     break;
1989    
1990     case mEdit:
1991     break;
1992    
1993     case mHelp:
1994     if (!helpw) {
1995     NAwindow(0, NA_USERESOURCE | NATEflags | NATE_READONLY | NA_SMARTSIZE,
1996     NULL, helpWIND, (long *) NULL, sizeof (nate_win), helpwindow);
1997     } else {
1998     SelectWindow(helpw);
1999     }
2000     break;
2001     }
2002     NAdisableMItem(mApple, iAbout);
2003    
2004     return (status);
2005     }
2006    
2007     /* make preferences folder/file
2008     * returns -1 on failure.
2009     */
2010     static short makepref()
2011     {
2012     Handle hpref = NULL, htmpl;
2013     long dirID;
2014     short vRefNum;
2015     char *scan, *end;
2016     PCstr dname[257];
2017     CInfoPBRec cpb;
2018     DirInfo *dp = &cpb.dirInfo;
2019     ParamBlockRec pb;
2020     VolumeParam *vp = &pb.volumeParam;
2021     FInfo finfo;
2022     static unsigned char pname[] = "\pprefs";
2023    
2024     /* set up pref folder storage */
2025     pfolder = (struct pref_folder *) NewPtr(sizeof (struct pref_folder));
2026     if (!pfolder) return (-1);
2027     end = scan = (char *) pfolder->prefs + sizeof (pfolder->prefs) - 1;
2028     *scan = '\0';
2029    
2030     /* get pref folder */
2031     if (FindFolder(kOnSystemDisk, kPreferencesFolderType,
2032     kCreateFolder, &vRefNum, &pfolder->fspec.parID) != noErr) {
2033     return (-1);
2034     }
2035    
2036     /* create subfolder, if needed */
2037     PtoPCstrcpy(dname, (char *) "\pMpack");
2038     (void) DirCreate(vRefNum, pfolder->fspec.parID, P(dname), &dirID);
2039    
2040     /* get mpack prefs folder info */
2041     dp->ioNamePtr = P(dname);
2042     dp->ioVRefNum = vRefNum;
2043     dp->ioFDirIndex = 0;
2044     dp->ioDrDirID = pfolder->fspec.parID;
2045     if (PBGetCatInfoSync(&cpb) != noErr) return (-1);
2046     pfolder->fspec.parID = dirID = dp->ioDrDirID;
2047     pfolder->fspec.vRefNum = vRefNum;
2048    
2049     /* generate pathname */
2050     dp->ioFDirIndex = -1;
2051     for (;;) {
2052     *--scan = ':';
2053     if (scan - (char *) pfolder->prefs < 1 + PCstrlen(dname)) return (-1);
2054     scan -= PCstrlen(dname);
2055     memcpy(scan, C(dname), PCstrlen(dname));
2056     if ((dp->ioDrDirID = dp->ioDrParID) == 2) break;
2057     if (PBGetCatInfoSync(&cpb) != noErr) return (-1);
2058     }
2059     vp->ioVolIndex = 0;
2060     vp->ioNamePtr = P(dname);
2061     vp->ioVRefNum = vRefNum;
2062     if (PBGetVInfoSync(&pb) != noErr) return (-1);
2063     *--scan = ':';
2064     if (scan - (char *) pfolder->prefs < 16 + PCstrlen(dname)) return (-1);
2065     PtoPCstrcpy(pfolder->prefs, (char *) P(dname));
2066     CtoPCstrcat(pfolder->prefs, scan);
2067    
2068     /* Get/Create preferences file */
2069     HCreateResFile(vRefNum, dirID, pname);
2070     if (ResError() == noErr) {
2071     HGetFInfo(vRefNum, dirID, pname, &finfo);
2072     finfo.fdType = 'pref';
2073     finfo.fdCreator = 'mPAK';
2074     HSetFInfo(vRefNum, dirID, pname, &finfo);
2075     hpref = GetResource('mPRF', prefsID);
2076     DetachResource(hpref);
2077     htmpl = GetResource('TMPL', IDnaID);
2078     DetachResource(htmpl);
2079     }
2080     pfolder->refnum = HOpenResFile(vRefNum, dirID, pname, fsRdWrPerm);
2081     if (pfolder->refnum < 0) return (-1);
2082     if (hpref) {
2083     AddResource(hpref, 'mPRF', prefsID, "\p");
2084     AddResource(htmpl, 'TMPL', IDnaID, "\pIDna");
2085     ReleaseResource(htmpl);
2086     } else {
2087     hpref = GetResource('mPRF', prefsID);
2088     }
2089     if (!hpref) return (-1);
2090     mpack_prefs = (struct mpack_preferences **) hpref;
2091    
2092     return (0);
2093     }
2094    
2095     /* cleanup shared resources
2096     */
2097     void maccleanup()
2098     {
2099     if (pfolder) {
2100     CloseResFile(pfolder->refnum);
2101     DisposPtr((Ptr) pfolder);
2102     }
2103     if (icinst) ICStop(icinst);
2104     if (tcpstart == 1) NATCPdone(120); /* give 2 seconds to go away */
2105     }
2106    
2107     main()
2108     {
2109     CursHandle cursH;
2110    
2111     if (NAinit(128, 2, openfile, mainmenu, 3, 1, 0, iClose) == 0) {
2112     /* set up preferences */
2113     if (makepref() < 0) {
2114     yell("Couldn't create preferences file");
2115     } else {
2116     /* set up internet config */
2117     if (ICStart(&icinst, 'mPAK') == noErr) {
2118     (void) ICFindConfigFile(icinst, 0, NULL);
2119     }
2120     /* save watch cursor */
2121     cursH = GetCursor(watchCursor);
2122     watch = **cursH;
2123     /* enter main loop, cleanup on exit */
2124     NAmainloop();
2125     maccleanup();
2126     }
2127     }
2128     }

  ViewVC Help
Powered by ViewVC 1.1.22