| 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 |
} |