Article View: comp.sources.mac
Article #47Tar 1.1 Source (part 3 of 3)
From: Craig Ruff
Date: Sat, 14 May 1988 06:57
Date: Sat, 14 May 1988 06:57
1393 lines
31868 bytes
31868 bytes
[Tar 1.1 Source - part 3 of 3]
---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# extract.c
# list.c
# menu.c
# window.c
# This archive created: Wed May 11 07:24:07 1988
# By: Roger L. Long (bytebug@dhw68k.cts.com)
export PATH; PATH=/bin:$PATH
echo shar: extracting "'extract.c'" '(7771 characters)'
if test -f 'extract.c'
then
echo shar: will not over-write existing file "'extract.c'"
else
sed 's/^X//' << \SHAR_EOF > 'extract.c'
X/*
X * Macintosh Tar
X *
X * Modified by Craig Ruff for use on the Macintosh.
X */
X/*
X * Extract files from a tar archive.
X *
X * Written 19 Nov 1985 by John Gilmore, ihnp4!hoptoad!gnu.
X *
X * @(#) extract.c 1.17 86/10/29 Public Domain - gnu
X */
X#include "tar.h"
X
Xextern union record *head; /* Points to current tape header */
Xextern struct stat {
X long st_size;
X long st_mtime;
X} hstat; /* Fake stat struct for compat. */
X
Xvoid ExtractArchive();
Xextern void PrintHeader();
Xextern void SkipFile();
X
Xint MakeDirs(); /* Makes required directories */
X
X/*
X * Extract - extract the entire archive
X */
XExtract() {
X Point where;
X SFReply reply;
X WDPBRec wdpb;
X
X /*
X * Use the standard file dialog to select the archive.
X */
X where.h = where.v = 75;
X SFGetFile(pass(where), "\PSelect TAR file", NIL, 0, NIL, NIL, &reply);
X if (!reply.good)
X return;
X
X /*
X * Remember the VRefNum and Name for OpenArchive.
X * Find out where to put the extracted files.
X */
X arVRefNum = reply.vRefNum;
X arName = reply.fName;
X if (GetDir("\Pto put extracted files") == FALSE)
X return;
X
X /*
X * Open the target directory as a base to put everything.
X */
X wdpb.ioCompletion = NIL;
X wdpb.ioNamePtr = NIL;
X wdpb.ioVRefNum = dirVRefNum;
X wdpb.ioWDProcID = 'TAR ';
X wdpb.ioWDDirID = dirDirID;
X if (PBOpenWD(&wdpb, FALSE) != noErr) {
X OSAlert("\PExtract", "\PPBOpenWD", NIL, wdpb.ioResult);
X return;
X }
X
X /*
X * Extract and print the files as found in the archive.
X */
X dirVRefNum = wdpb.ioVRefNum;
X if (WindInit())
X goto done;
X
X TextFace(underlineStyle);
X WPrintf(header);
X TextFace(0);
X
X if (setjmp(errJmp) == 0)
X ReadAnd(ExtractArchive);
X else
X CloseArchive();
X
X WindEnd(autoPage);
Xdone:
X (void) PBCloseWD(&wdpb, FALSE);
X}
X
X/*
X * Extract a file from the archive.
X */
Xvoid
XExtractArchive()
X{
X register char *data;
X register char *p;
X CInfoPBRec pb;
X HPrmBlkRec dpb;
X HPrmBlkRec fpb;
X int fd, i, namelen;
X long check, written;
X long size;
X OSErr err;
X char macName[256];
X char *routine = "\PExtractArchive";
X
X SaveRec(&head); /* Make sure it sticks around */
X UseRec(head); /* And go past it in the archive */
X DecodeHeader(head, &hstat, 1); /* Snarf fields */
X
X /* Print the record from 'head' and 'hstat' */
X PrintHeader();
X
X switch (head->header.linkflag) {
X default:
X WPrintf("Unknown file type %d for %s",
X head->header.linkflag, head->header.name);
X break;
X
X case LF_OLDNORMAL:
X case LF_NORMAL:
X /*
X * Appears to be a file.
X * See if it's really a directory.
X */
X namelen = strlen(head->header.name) - 1;
X if (head->header.name[namelen] == '/')
X goto really_dir;
X
X FixName(head->header.name, macName);
X again_file:
X fpb.ioCompletion = NIL;
X fpb.ioNamePtr = macName;
X fpb.ioVRefNum = dirVRefNum;
X fpb.u.hfp.ioDirID = 0;
X err = PBHCreate(&fpb, FALSE);
X if (err == noErr) {
X fpb.ioCompletion = NIL;
X fpb.ioNamePtr = macName;
X fpb.ioVRefNum = dirVRefNum;
X fpb.u.hfp.ioDirID = 0;
X fpb.u.hfp.ioFDirIndex = 0;
X if (PBHGetFInfo(&fpb, FALSE)) {
X OSAlert(routine, "\PPBHGetFInfo", NIL, fpb.ioResult);
X goto doNext;
X }
X
X strncpy(&fpb.u.hfp.ioFlFndrInfo.fdCreator, fdCreator, 4);
X strncpy(&fpb.u.hfp.ioFlFndrInfo.fdType, fdType, 4);
X fpb.ioCompletion = NIL;
X fpb.ioNamePtr = macName;
X fpb.ioVRefNum = dirVRefNum;
X fpb.u.hfp.ioDirID = 0;
X if (PBHSetFInfo(&fpb, FALSE)) {
X OSAlert(routine, "\PPBHSetFInfo", NIL, fpb.ioResult);
X goto doNext;
X }
X
X fpb.u.iop.ioPermssn = fsWrPerm;
X fpb.u.iop.ioMisc = NIL;
X err = PBHOpen(&fpb, FALSE);
X }
X
X if (err != noErr) {
X if (MakeDirs(macName))
X goto again_file;
X
X PgmAlert(routine, "\PCould not make file", macName, NIL);
X SkipFile((long)hstat.st_size);
X break;
X }
X
X /*
X * Note that this only extracts data forks!
X */
X for (size = hstat.st_size;
X size > 0;
X size -= written) {
X /*
X * Locate data, determine max length
X * writeable, write it, record that
X * we have used the data, then check
X * if the write worked.
X */
X data = FindRec()->charptr;
X written = EndOfRecs()->charptr - data;
X if (written > size)
X written = size;
X
X /*
X * Convert newlines to return for Mac compatability.
X */
X if (cvtNl) {
X for (i = written, p = data; --i >= 0; p++)
X if (*p == '\n')
X *p = '\r';
X }
X
X check = written;
X fpb.u.iop.ioBuffer = data;
X fpb.u.iop.ioReqCount = check;
X fpb.u.iop.ioPosMode = fsAtMark;
X fpb.u.iop.ioPosOffset = 0;
X err = PBWrite(&fpb, FALSE);
X if (err != noErr) {
X OSAlert(routine, "\PPBWrite", NIL, err);
X goto doNext;
X }
X
X check = fpb.u.iop.ioActCount;
X /*
X * The following is in violation of strict
X * typing, since the arg to userec
X * should be a struct rec *. FIXME.
X */
X UseRec(data + written - 1);
X if (check == written) continue;
X /*
X * Error in writing to file.
X * Print it, skip to next file in archive.
X */
X PgmAlert(routine, "\PWrite short", NIL, NIL);
X doNext:
X PBClose(&fpb, FALSE);
X SkipFile((long)(size - written));
X goto quit;
X }
X
X PBClose(&fpb, FALSE);
X quit:
X break;
X
X case LF_DIR:
X /* Check for trailing / */
X namelen = strlen(head->header.name)-1;
X really_dir:
X while (namelen && head->header.name[namelen] == '/')
X head->header.name[namelen--] = '\0'; /* Zap / */
X
X FixName(head->header.name, macName);
X /* FALL THROUGH */
X again_dir:
X dpb.ioCompletion = NIL;
X dpb.ioNamePtr = macName;
X dpb.ioVRefNum = dirVRefNum;
X dpb.u.hfp.ioDirID = 0;
X err = PBDirCreate(&dpb, FALSE);
X if ((err != noErr) && (err != dupFNErr)) {
X if (MakeDirs(macName))
X goto again_dir;
X
X PgmAlert(routine, "\PCould not make directory",
X macName, NIL);
X }
X break;
X
X }
X
X /* We don't need to save it any longer. */
X SaveRec((union record **) 0); /* Unsave it */
X}
X
X/*
X * After a file/link/symlink/dir creation has failed, see if
X * it's because some required directory was not present, and if
X * so, create all required dirs.
X */
Xint
XMakeDirs(pathname)
Xchar *pathname;
X{
X int madeone = 0; /* Did we do anything yet? */
X int i, savedLen;
X OSErr err;
X HPrmBlkRec pb;
X
X savedLen = pathname[0] & 0xff;
X /*
X * skip initial ':'
X *
X * Note that the directory name has already been converted to Mac style.
X */
X for (i = 2; i < savedLen; i++) {
X while ((i < savedLen) && (pathname[i] != ':'))
X i++;
X
X if (i == savedLen)
X break;
X
X pathname[0] = i++ - 1;
X pb.ioCompletion = NIL;
X pb.ioNamePtr = pathname;
X pb.ioVRefNum = dirVRefNum;
X pb.u.hfp.ioDirID = 0;
X err = PBDirCreate(&pb, FALSE);
X if (err == dupFNErr) {
X continue;
X
X } else if (err != noErr) {
X OSAlert("\PMakeDirs", "\PPBDirCreate", pathname,
X pb.ioResult);
X return(0);
X
X } else {
X madeone++; /* Remember if we made one */
X continue;
X }
X }
X
X pathname[0] = savedLen;
X return(madeone); /* Tell them to retry if we made one */
X}
X
X/*
X * FixName - convert to a Mac style pathname
X *
X * Conversions:
X * . -> (Stay at this directory level)
X * .. -> :: (Up a directory level)
X * .xxxx -> _xxxx (Don't get in trouble with device names)
X * xx:xx -> xx/xx (Don't get in trouble with directory delims)
X */
XFixName(tar, mac)
Xregister char *tar;
Xchar *mac;
X{
X char *end = tar + strlen(tar);
X register char *p = mac + 1;
X register char *next;
X
X for (next = tar; tar < end; next++) {
X /*
X * Swallow up all contiguous '/' characters.
X */
X while (*next && (*next == '/'))
X next++;
X
X /*
X * Find the entire name up until the next '/'.
X */
X tar = next;
X while (*next && (*next != '/'))
X next++;
X
X *next = 0;
X *p++ = ':';
X if (*tar == '.')
X switch (*(tar + 1)) {
X case '\0':
X p--;
X continue;
X
X case '.':
X if (*(tar + 2) == 0)
X continue;
X /* else FALL THROUGH */
X
X default:
X *tar = '_';
X }
X
X while (tar < next) {
X if (*tar == ':')
X *tar = '/';
X *p++ = *tar++;
X }
X }
X
X *mac = p - mac - 1;
X}
SHAR_EOF
if test 7771 -ne "`wc -c < 'extract.c'`"
then
echo shar: error transmitting "'extract.c'" '(should have been 7771 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'list.c'" '(7209 characters)'
if test -f 'list.c'
then
echo shar: will not over-write existing file "'list.c'"
else
sed 's/^X//' << \SHAR_EOF > 'list.c'
X/*
X * Macintosh Tar
X *
X * Modified by Craig Ruff for use on the Macintosh.
X */
X/*
X * List a tar archive.
X *
X * Also includes support routines for reading a tar archive.
X *
X * Pubic Domain version written 26 Aug 1985 by John Gilmore (ihnp4!hoptoad!gnu).
X *
X * @(#)list.c 1.18 9/23/86 Public Domain - gnu
X */
X#include "tar.h"
X
Xchar *ctime(); /* From libc.a */
X
X#define isodigit(c) ( ((c) >= '0') && ((c) <= '7') )
X#define isspace(c) ((c) == ' ')
X
Xlong FromOct(); /* Decode octal number */
X
Xunion record *head; /* Points to current archive header */
Xstruct stat {
X long st_size;
X long st_mtime;
X} hstat; /* Fake stat struct for compat. */
X
Xvoid ListArchive();
Xvoid PrintHeader();
Xvoid ReadAnd();
Xvoid SkipFile();
X
X/*
X * List - list an archive file
X */
XList() {
X Point where;
X SFReply reply;
X Boolean oldAutoPage = autoPage;
X
X /*
X * Use standard file to get the archive file.
X * Always do a screen at a time if to the screen.
X */
X where.h = where.v = 75;
X SFGetFile(pass(where), "\PName of TAR file:", NIL, -1, NIL, NIL, &reply);
X if (!reply.good)
X return;
X
X arVRefNum = reply.vRefNum;
X arName = reply.fName;
X if (WindInit())
X return;
X
X autoPage = TRUE;
X TextFace(underlineStyle);
X WPrintf(header);
X TextFace(0);
X
X if (setjmp(errJmp) == 0)
X ReadAnd(ListArchive);
X else
X CloseArchive();
X
X WindEnd(TRUE);
X autoPage = oldAutoPage;
X}
X
X/*
X * Main loop for reading an archive.
X */
Xvoid
XReadAnd(doSomething)
Xvoid (*doSomething)();
X{
X int status = 1;
X int prevStatus;
X EventRecord e;
X CursHandle cursor;
X
X if ((cursor = GetCursor(watchCursor)) != NIL)
X SetCursor(*cursor);
X
X OpenArchive(1); /* Open for reading */
X
X for(;;) {
X SystemTask();
X if (EventAvail(keyDownMask, &e) && (e.what != nullEvent)) {
X if (
X (e.modifiers & cmdKey) &&
X ((e.message & charCodeMask) == '.')
X ) {
X GetNextEvent(keyDownMask, &e);
X break;
X }
X }
X
X prevStatus = status;
X status = ReadHeader();
X switch (status) {
X case 1: /* Valid header */
X /* We should decode next field (mode) first... */
X /* Ensure incoming names are null terminated. */
X head->header.name[NAMSIZ-1] = '\0';
X (*doSomething)();
X continue;
X
X /*
X * If the previous header was good, tell them
X * that we are skipping bad ones.
X */
X case 0: /* Invalid header */
X case0:
X UseRec(head);
X if (prevStatus == 1) {
X PgmAlert("\PReadAnd",
X "\PSkipping to next file header...",
X NIL, NIL);
X }
X continue;
X
X case 2: /* Block of zeroes */
X if (ignorez)
X goto case0; /* Just skip if asked */
X /* FALL THRU */
X case (int) EOF: /* End of archive */
X break;
X }
X break;
X }
X
X CloseArchive();
X SetCursor(&arrow);
X}
X
X
X/*
X * Print a header record, based on tar options.
X */
Xvoid
XListArchive()
X{
X long t;
X
X /* Save the record */
X SaveRec(&head);
X
X /*
X * Print the header record.
X * Don't sling the names too fast!
X */
X PrintHeader();
X if (!autoPage)
X Delay(60L, &t);
X
X /* Skip past it in the archive */
X SaveRec((union record **) 0); /* Unsave it */
X UseRec(head);
X
X /* Skip to the next header on the archive */
X SkipFile((long)hstat.st_size);
X}
X
X
X/*
X * Read a record that's supposed to be a header record.
X * Return its address in "head", and if it is good, the file's
X * size in hstat.st_size.
X *
X * Return 1 for success, 0 if the checksum is bad, EOF on eof,
X * 2 for a block full of zeros (EOF marker).
X *
X * You must always userec(head) to skip past the header which this
X * routine reads.
X */
Xint
XReadHeader()
X{
X register int i;
X register long sum, recsum;
X register char *p;
X register union record *header;
X
X header = FindRec();
X head = header; /* This is our current header */
X if (NIL == header)
X return(EOF);
X
X recsum = FromOct(8, header->header.chksum);
X sum = 0;
X p = header->charptr;
X for (i = sizeof(*header); --i >= 0;) {
X /*
X * We can't use unsigned char here because of old compilers,
X * e.g. V7.
X */
X sum += 0xFF & *p++;
X }
X
X /* Adjust checksum to count the "chksum" field as blanks. */
X for (i = sizeof(header->header.chksum); --i >= 0;)
X sum -= 0xFF & header->header.chksum[i];
X sum += ' ' * sizeof(header->header.chksum);
X
X if (sum == recsum) {
X /*
X * Good record. Decode file size and return.
X */
X hstat.st_size = FromOct(1+12, header->header.size);
X return(1);
X }
X
X if (sum == 8 * ' ') {
X /*
X * This is a zeroed block...whole block is 0's except
X * for the 8 blanks we faked for the checksum field.
X */
X return(2);
X }
X
X return(0);
X}
X
X/*
X * Decode things from a file header record into a "struct stat".
X *
X * read_header() has already decoded the checksum and length, so we don't.
X *
X * If wantug != 0, we want the uid/group info decoded from Unix Standard
X * tapes (for extraction). If == 0, we are just printing anyway, so save time.
X */
XDecodeHeader(header, st, wantug)
Xregister union record *header;
Xregister struct stat *st;
Xint wantug;
X{
X st->st_mtime = FromOct(1+12, header->header.mtime);
X}
X
X/*
X * Quick and dirty octal conversion.
X *
X * Result is -1 if the field is invalid (all blank, or nonoctal).
X */
Xlong
XFromOct(digs, where)
Xregister int digs;
Xregister char *where;
X{
X register long value;
X
X while (isspace(*where)) { /* Skip spaces */
X where++;
X if (--digs <= 0)
X return(-1); /* All blank field */
X }
X
X value = 0;
X while (digs > 0 && isodigit(*where)) { /* Scan til nonoctal */
X value = (value << 3) | (*where++ - '0');
X --digs;
X }
X
X if (digs > 0 && *where && !isspace(*where))
X return(-1); /* Ended on non-space/nul */
X
X return(value);
X}
X
X/*
X * Actually print it.
X */
X#define UGSWIDTH 9 /* min width of User, group, size */
X#define DATEWIDTH 19 /* Last mod date */
Xstatic int ugswidth = UGSWIDTH; /* Max width encountered so far */
X
Xvoid
XPrintHeader()
X{
X char mode;
X char *timestamp;
X char *user, *group;
X char size[12]; /* Holds a formatted long */
X long longie; /* To make ctime() call portable */
X int pad;
X
X DecodeHeader(head, &hstat, 0);
X /* File type and mode */
X mode = '?';
X switch (head->header.linkflag) {
X case LF_NORMAL:
X case LF_OLDNORMAL:
X mode = 'F';
X if ('/' == head->header.name[strlen(head->header.name)-1])
X mode = 'D';
X break;
X
X case LF_DIR:
X mode = 'D';
X break;
X }
X
X /*
X * Convert to Mac based time from Unix based time.
X */
X longie = hstat.st_mtime + TIMEDIFF;
X
X timestamp = ctime(&longie);
X timestamp[16] = '\0';
X timestamp[24] = '\0';
X
X /* Format the file size or major/minor device numbers */
X switch (head->header.linkflag) {
X default:
X (void) sprintf(size, "?????");
X break;
X
X case LF_DIR:
X (void) sprintf(size, "%.*s", UGSWIDTH, "");
X break;
X
X case LF_OLDNORMAL:
X case LF_NORMAL:
X (void) sprintf(size, "%ld", hstat.st_size);
X break;
X }
X
X
X /* Figure out padding and print the whole line. */
X pad = strlen(size) + 1;
X if (pad > ugswidth)
X ugswidth = pad;
X
X WPrintf("%c %*s%s %s %s %.*s", mode, ugswidth - pad, "", size,
X timestamp+4, timestamp+20, sizeof(head->header.name),
X head->header.name);
X}
X
X/*
X * Skip over <size> bytes of data in records in the archive.
X */
Xvoid
XSkipFile(size)
Xregister long size;
X{
X union record *x;
X
X while (size > 0) {
X x = FindRec();
X if (x == NIL) { /* Check it... */
X PgmAlert("\PSkipFile", "\PUnexpected EOF on archive file",
X NIL, NIL);
X longjmp(errJmp, 1);
X }
X UseRec(x);
X size -= RECORDSIZE;
X }
X}
SHAR_EOF
if test 7209 -ne "`wc -c < 'list.c'`"
then
echo shar: error transmitting "'list.c'" '(should have been 7209 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'menu.c'" '(4610 characters)'
if test -f 'menu.c'
then
echo shar: will not over-write existing file "'menu.c'"
else
sed 's/^X//' << \SHAR_EOF > 'menu.c'
X/*
X * Macintosh Tar
X *
X * Written by Craig Ruff.
X *
X * Menu handling routines.
X */
X
X#include "tar.h"
X#include <resource.h>
X
X/*
X * Resource IDs for menus
X */
X#define appleID 128
X#define fileID 129
X#define editID 130
X#define optionID 131
X
X/*
X * Index for each menu
X */
X#define appleMenu 0
X#define fileMenu 1
X#define editMenu 2
X#define optionMenu 3
X#define menuCount 4
X
X/*
X * Item in Apple Menu
X */
X#define aboutItem 1
X
X/*
X * Items in File Menu
X */
X#define createItem 1 /* Create archive */
X#define extractItem 2 /* Extract archive */
X#define listItem 3 /* List archive */
X#define closeItem 5 /* Close (only for Desk Acc) */
X#define pgsetItem 6 /* Page setup */
X#define quitItem 8
X
X/*
X * Items in Edit Menu
X *
X * For use by Desk Accessories.
X */
X#define undoItem 1
X#define cutItem 3
X#define copyItem 4
X#define pasteItem 5
X#define clearItem 6
X
X/*
X * Items in Options Menu
X */
X#define convertItem 1 /* Convert newlines */
X#define oldArchItem 2 /* Old tar compatible archive creation */
X#define blockItem 3 /* Set block size */
X#define pageItem 5 /* Control paging of screen listing */
X#define printItem 6 /* Use printer instead of screen */
X#define typeItem 8 /* Creator/Type dialog */
X
X
X/*
X * Menu related variables
X */
X
XMenuHandle menus[menuCount];
XBoolean menusOK;
X
X/*
X * MenuInit - set up menu bar
X *
X * Reads non-apple menus from resource file.
X */
XBoolean
XMenuInit() {
X int i;
X char *routine = "\PMenuInit";
X
X if ((menus[appleMenu] = GetMenu(appleID)) == NIL) {
X OSAlert(routine, "\PGetMenu Apple Menu", NIL, ResError());
X return(TRUE);
X }
X
X AddResMenu(menus[appleMenu], 'DRVR');
X if ((menus[fileMenu] = GetMenu(fileID)) == NIL) {
X OSAlert(routine, "\PGetMenu File Menu", NIL, ResError());
X return(TRUE);
X }
X
X if ((menus[editMenu] = GetMenu(editID)) == NIL) {
X OSAlert(routine, "\PGetMenu Edit Menu", NIL, ResError());
X return(TRUE);
X }
X
X if ((menus[optionMenu] = GetMenu(optionID)) == NIL) {
X OSAlert(routine, "\PGetMenu Option Menu", NIL, ResError());
X return(TRUE);
X }
X
X
X CheckItem(menus[optionMenu], pageItem, autoPage);
X for (i = appleMenu; i < menuCount; i++)
X InsertMenu(menus[i], 0);
X
X DDaMenus();
X DrawMenuBar();
X return(FALSE);
X}
X
X/*
X * MenuCmd - handle a menu pick or keyboard equivalent
X */
XMenuCmd(result)
Xlong result;
X{
X WindowPeek wp;
X short theItem = result & 0xffff;
X short theMenu = (result >> 16) & 0xffff;
X char name[256];
X OSErr err;
X char *routine = "\PMenuCmd";
X GrafPtr savedPort;
X
X switch (theMenu) {
X case appleID:
X if (theItem == aboutItem)
X DoAboutBox();
X else {
X /*
X * Oh boy, set up for a desk accessory.
X */
X GetItem(menus[appleMenu], theItem, name);
X GetPort(&savedPort);
X if ((err = ZeroScrap()) != noErr) {
X OSAlert(routine, "\PZeroScrap", NIL, err);
X break;
X }
X
X if ((err = TEToScrap()) != noErr) {
X OSAlert(routine, "\PTEToScrap", NIL, err);
X break;
X }
X
X (void) OpenDeskAcc(name);
X SetPort(savedPort);
X if (FrontWindow() != NIL) {
X EDaMenus();
X }
X }
X break;
X
X case fileID:
X switch (theItem) {
X case createItem:
X ArCreate();
X break;
X
X case extractItem:
X Extract();
X break;
X
X case listItem:
X List();
X break;
X
X case closeItem:
X /*
X * If the front window belongs to a Desk Acc, close it!
X */
X if ((wp = (WindowPeek) FrontWindow()) == NIL)
X break;
X
X if (wp->windowKind < 0) {
X CloseDeskAcc(wp->windowKind);
X DDaMenus();
X }
X break;
X
X case pgsetItem:
X if (!PrSetup())
X (void) PrStlDialog(prRecHdl);
X break;
X
X case quitItem:
X doneFlag = TRUE;
X break;
X }
X break;
X
X case editID:
X /*
X * Send to a Desk Acc.
X */
X (void) SystemEdit(theItem - 1);
X break;
X
X case optionID:
X switch (theItem) {
X case convertItem:
X cvtNl ^= TRUE;
X CheckItem(menus[optionMenu], convertItem, cvtNl);
X break;
X
X case oldArchItem:
X oldArch ^= TRUE;
X CheckItem(menus[optionMenu], oldArchItem, oldArch);
X break;
X
X case blockItem:
X DoBlockSize();
X break;
X
X case pageItem:
X autoPage ^= TRUE;
X CheckItem(menus[optionMenu], pageItem, autoPage);
X break;
X
X case printItem:
X doPrint ^= TRUE;
X CheckItem(menus[optionMenu], printItem, doPrint);
X break;
X
X case typeItem:
X DoCreatorType();
X break;
X }
X break;
X }
X
X HiliteMenu(0);
X FlushEvents(everyEvent, 0);
X}
X
X/*
X * DDaMenus - disable Desk Acc specific menu and menu item
X */
XDDaMenus() {
X DisableItem(menus[editMenu], 0);
X DisableItem(menus[fileMenu], closeItem);
X DrawMenuBar();
X menusOK = TRUE;
X}
X
X/*
X * EDaMenus - enable Desk Acc specific menu and menu item
X */
XEDaMenus() {
X EnableItem(menus[editMenu], 0);
X EnableItem(menus[fileMenu], closeItem);
X DrawMenuBar();
X menusOK = FALSE;
X}
SHAR_EOF
if test 4610 -ne "`wc -c < 'menu.c'`"
then
echo shar: error transmitting "'menu.c'" '(should have been 4610 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'window.c'" '(7222 characters)'
if test -f 'window.c'
then
echo shar: will not over-write existing file "'window.c'"
else
sed 's/^X//' << \SHAR_EOF > 'window.c'
X/*
X * Macintosh Tar
X *
X * Written by Craig Ruff
X *
X * Window manipulation routines for display (and printer) listings of archives.
X */
X
X#include "tar.h"
X#include <resource.h>
X
X#define dispID 129 /* Display window ID (in resource file) */
X#define LEFTMAR 5
X#define TOPMAR 5
X
XWindowPtr dispWind;
XBoolean windOpen = FALSE;
Xshort fontHeight;
Xshort bottomMargin;
Xshort bottomLine;
Xshort topLine;
Xshort curLine;
Xshort wLines;
Xshort wCurLine = 0;
XRgnHandle update;
XTPPrPort prPort;
XGrafPtr savedPort;
X
X/*
X * WindInit - either open the window or printer port
X *
X * Returns TRUE if an error is found, FALSE otherwise.
X *
X * Separate routines for screen and printer are not really needed.
X */
XBoolean
XWindInit() {
X FontInfo fInfo;
X char *routine = "\PWindInit";
X
X if (doPrint) {
X /*
X * We are listing to the printer.
X * Make sure we have opened the printer driver.
X */
X if (!pOpen && PrSetup())
X return(TRUE);
X
X /*
X * Ask about this listings specifics.
X */
X if (PrJobDialog(prRecHdl) == FALSE)
X return(TRUE);
X
X if (PrError() != noErr) {
X OSAlert(routine, "\PPrJobDialog", NIL, PrError());
X return(TRUE);
X }
X
X /*
X * Open the printer document (once per listing).
X */
X prPort = PrOpenDoc(prRecHdl, NIL, NIL);
X if (PrError() != noErr) {
X OSAlert(routine, "\PPrOpenDoc", NIL, PrError());
X return(TRUE);
X }
X
X /*
X * Open the page (once per physical page).
X */
X PrOpenPage(prPort, NIL);
X if (PrError() != noErr) {
X OSAlert(routine, "\PPrOpenPage", NIL, PrError());
X return(TRUE);
X }
X
X /*
X * Use monaco 9 so our listing lines up properly.
X * (Lazy)
X */
X GetPort(&savedPort);
X SetPort(prPort);
X TextFont(monaco);
X TextSize(9);
X
X /*
X * Figure out how many lines fit on a page.
X */
X GetFontInfo(&fInfo);
X fontHeight = fInfo.ascent + fInfo.descent + fInfo.leading;
X MoveTo(LEFTMAR, curLine = fontHeight);
X bottomLine = (((**prRecHdl).prInfo.rPage.bottom / fontHeight) - 1)
X * fontHeight;
X
X return(FALSE);
X }
X
X /*
X * Listing to screen.
X * Get a temporary region for scrolling bits.
X * Get the window template from the resource file.
X */
X if ((update = NewRgn()) == NIL) {
X OSAlert(routine, "\PNewRgn", NIL, MemError());
X return(TRUE);
X }
X
X if ((dispWind = GetNewWindow(dispID, NIL, (WindowPtr) -1)) == NIL) {
X OSAlert(routine, "\PGetNewWindow", NIL, ResError());
X return(TRUE);
X }
X
X /*
X * Use monaco 9 so our listing lines up.
X */
X SetPort(dispWind);
X TextFont(monaco);
X TextSize(9);
X
X /*
X * Figure out how many lines fit on a page, save this as margin info.
X */
X GetFontInfo(&fInfo);
X fontHeight = fInfo.ascent + fInfo.descent + fInfo.leading;
X
X MoveTo(LEFTMAR, curLine = fontHeight);
X topLine = curLine + fInfo.descent + fInfo.leading;
X bottomLine = (wLines = dispWind->portRect.bottom / fontHeight) * fontHeight;
X bottomMargin = bottomLine + fInfo.descent + fInfo.leading;
X
X wCurLine = 0;
X windOpen = TRUE;
X return(FALSE);
X}
X
X/*
X * WindEnd - clean up after a listing to screen or printer
X */
XWindEnd(keyWait)
XBoolean keyWait;
X{
X if (doPrint) {
X TPrStatus prSt;
X char *routine = "\PWindEnd";
X short err;
X
X /*
X * Printing, close page and document.
X */
X PrClosePage(prPort);
X if ((err = PrError()) != noErr) {
X if (err != iPrAbort)
X OSAlert(routine, "\PPrClosePage", NIL, PrError());
X goto done;
X }
X
X PrCloseDoc(prPort);
X if ((err = PrError()) != noErr) {
X if (err != iPrAbort)
X OSAlert(routine, "\PPrCloseDoc", NIL, PrError());
X goto done;
X }
X
X /*
X * If the printing involved spooling, spool it now.
X */
X if ((**prRecHdl).prJob.bJDocLoop == bSpoolLoop)
X PrPicFile(prRecHdl, NIL, NIL, NIL, &prSt);
X
X done: SetPort(savedPort);
X return;
X }
X
X /*
X * Listing to screen. See if we should wait for a key press to continue.
X */
X if (keyWait) {
X EventRecord e;
X Boolean oldAutoPage = autoPage;
X
X autoPage = FALSE; /* So we don't get two messages */
X if (!doPrint)
X WPrintf("Press any key to continue");
X
X do {
X SystemTask();
X if (GetNextEvent(keyDownMask, &e) == FALSE)
X e.what = nullEvent;
X } while (e.what != keyDown);
X
X autoPage = oldAutoPage;
X }
X
X DisposeWindow(dispWind);
X DisposeRgn(update);
X windOpen = FALSE;
X}
X
X/*
X * WPrintf - printf to the screen or printer
X *
X * Used like you'd expect, but does NOT handle paper motion
X * characters like newline, etc.
X */
XWPrintf(fmt, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)
Xchar *fmt;
Xlong a0, a1, a2, a3, a4, a5, a6, a7, a8, a9;
X{
X Rect r;
X char buf[256];
X EventRecord e;
X char *routine = "\PWPrintf";
X short err;
X
X if (!windOpen && !doPrint)
X return;
X
X sprintf(buf, fmt, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
X if (strlen(buf) >= sizeof(buf))
X StkErrAlert(); /* Sanity check, stack overrun */
X
X if (doPrint) {
X /*
X * Printing.
X */
X if (curLine > bottomLine) {
X /*
X * At end of page, start a new one.
X */
X PrClosePage(prPort);
X if ((err = PrError()) != noErr) {
X if (err != iPrAbort)
X OSAlert(routine, "\PPrClosePage", NIL,
X PrError());
X longjmp(errJmp, 1);
X }
X
X PrOpenPage(prPort, NIL);
X if (PrError() != noErr) {
X if (err != iPrAbort)
X OSAlert(routine, "\PPrClosePage", NIL,
X PrError());
X longjmp(errJmp, 1);
X }
X
X /*
X * Yes, we really must reset the font.
X */
X MoveTo(LEFTMAR, curLine = fontHeight);
X TextFace(underlineStyle);
X DrawText(header, 0, strlen(header));
X TextFace(0);
X MoveTo(LEFTMAR, curLine += fontHeight);
X }
X
X DrawText(buf, 0, strlen(buf));
X MoveTo(LEFTMAR, curLine += fontHeight);
X return;
X }
X
X /*
X * On screen.
X */
X SetPort(dispWind);
X if (autoPage && (++wCurLine == wLines)) {
X /*
X * At end of screen, wait for key press.
X */
X wCurLine = 0;
X DrawText("Press any key to continue", 0, 25);
X do {
X SystemTask();
X if (GetNextEvent(keyDownMask, &e) == FALSE)
X e.what = nullEvent;
X } while (e.what != keyDown);
X
X SetRect(&r, dispWind->portRect.left, bottomMargin - fontHeight,
X dispWind->portRect.right, bottomMargin);
X EraseRect(&r);
X MoveTo(LEFTMAR, curLine);
X
X } else {
X /*
X * No auto page, only stop if command S is pressed.
X */
X if (GetNextEvent(keyDownMask, &e)) {
X if (((e.message & charCodeMask & ~0x20) == 'S')
X && (e.modifiers & cmdKey)) {
X do {
X /*
X * Start again after command Q.
X */
X SystemTask();
X if (GetNextEvent(keyDownMask, &e) == FALSE)
X e.message = 0;
X
X e.message &= charCodeMask & ~0x20;
X } while (e.message != 'Q');
X }
X }
X }
X
X if (curLine > bottomLine) {
X /*
X * At end of screen, scroll up.
X */
X SetRect(&r, dispWind->portRect.left, topLine,
X dispWind->portRect.right, bottomMargin);
X ScrollRect(&r, 0, -fontHeight, update);
X SetEmptyRgn(update);
X MoveTo(LEFTMAR, curLine = bottomLine);
X }
X
X DrawText(buf, 0, strlen(buf));
X MoveTo(LEFTMAR, curLine += fontHeight);
X}
X
X/*
X * PrSetup - make sure the printer driver has been opened.
X *
X * Returns TRUE if an error is found, FALSE otherwise.
X */
XBoolean
XPrSetup() {
X char *routine = "\PPrSetup";
X
X if (!pOpen) {
X PrOpen();
X if (PrError() != noErr) {
X OSAlert(routine, "\PPrOpen", NIL, PrError());
X return(TRUE);
X }
X
X pOpen = TRUE;
X PrintDefault(prRecHdl);
X if (PrError() != noErr) {
X OSAlert(routine, "\PPrintDefault", NIL, PrError());
X return(TRUE);
X }
X }
X
X return(FALSE);
X}
SHAR_EOF
if test 7222 -ne "`wc -c < 'window.c'`"
then
echo shar: error transmitting "'window.c'" '(should have been 7222 characters)'
fi
fi # end of overwriting check
# End of shell archive
exit 0
--- end of part 3 ---
Technical Details
Message-ID:
<7964@dhw68k.cts.com>Path:
arc1-ca.pugleaf.net!utzoo!attcan!uunet!lll-winken!lll-tis!ames!oliveb!pyramid!hplabs!felix!dhw68k!macintoshReferences:
<7889@dhw68k.cts.com> <7925@dhw68k.cts.com>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!attcan!uunet!lll-winken!lll-tis!ames!oliveb!pyramid!hplabs!felix!dhw68k!macintosh From: cruff@ncar.ucar.edu (Craig Ruff) Newsgroups: comp.sources.mac Subject: Tar 1.1 Source (part 3 of 3) Message-ID: <7964@dhw68k.cts.com> Date: 14 May 88 06:57:18 GMT References: <7889@dhw68k.cts.com> <7925@dhw68k.cts.com> Sender: macintosh@dhw68k.cts.com Organization: Scientific Computing Division/NCAR, Boulder CO Lines: 1392 Approved: bytebug@dhw68k.cts.com (Roger L. Long)