Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!utgpu!water!watnot!watmath!clyde!cuae2!ihnp4!ptsfa!lll-lcc!pyramid!hplabs!felix!macintosh From: macintosh@felix.UUCP Newsgroups: mod.mac.sources Subject: Unpit version 0.3.1 Source (part 3 of 3) Message-ID: <2279@felix.UUCP> Date: Fri, 13-Feb-87 02:42:05 EST Article-I.D.: felix.2279 Posted: Fri Feb 13 02:42:05 1987 Date-Received: Sat, 14-Feb-87 15:21:22 EST References: <2277@felix.UUCP> <2278@felix.UUCP> Sender: macintosh@felix.UUCP Reply-To: macintosh@felix.UUCP (The Moderator) Organization: FileNet Corp., Costa Mesa, Ca. Lines: 576 Approved: bytebug@felix.UUCP (Roger L. Long) [Unpit version 0.3.1 Source - part 3 of 3] --- if (root->flag) { if (errno = putbit (1, file)) return errno; if (errno = putbyte (root->byte, file)) return errno; } else { if (errno = putbit (0, file)) return errno; if (errno = write_tree(root->zero, file)) return errno; if (errno = write_tree(root->one , file)) return errno; } return noErr; } /* Walk the minimum-total-cost tree to associate bit sequences with each byte. ############################# Build_Sequences ######################### */ Boolean build_sequences(nd, bits, bitcount) nodeptr nd; long bits; int bitcount; { if (nd->flag) { byte_code[nd->byte].bcount = bitcount; byte_code[nd->byte].bits = bits; } else { if ((bitcount == 32) || (! build_sequences(nd->zero, bits, bitcount+1)) || (! build_sequences(nd->one , bits | (1 << bitcount), bitcount+1))) return FALSE; } return TRUE; } /* Write the contents of a buffer using precomputed Huffman compression strings. ############################### PackWrite ############################## */ int pack_write(pit_ref_num, Count, Buffer) int pit_ref_num; long *Count; unsigned char *Buffer; { long theBits, MyCount = *Count; int i, e; while (MyCount--) { theBits = byte_code[*Buffer].bits; for (i = byte_code[*Buffer++].bcount; i; i--) { if (e = putbit((int) (theBits & 1), pit_ref_num)) return e; theBits = theBits >> 1; } } return noErr; } /* Copy files into the file denoted by pit_ref_num until error or user done. ############################## Pack_Files ############################# */ Boolean pack_files(pit_ref_num) int pit_ref_num; { SFReply InpRecord; ParamBlockRec ParamB; Point where; unsigned char fileHeader[HDRBYTES+2]; long Count; int i, j, errno, argCount, msg; register crctype crc; DialogPtr theDialog = 0L; nodeptr root; AppFile argFile; if(optkeyDown) { CountAppFiles(&msg, &argCount); for(j=1; j<=argCount; j++) { GetAppFiles(j, &argFile); ParamText(0L, 0L, "\PPack", argFile.fName); theDialog = GetNewDialog(statusid, 0L, -1L); DrawDialog(theDialog); ParamB.fileParam.ioCompletion = 0L; ParamB.fileParam.ioNamePtr = argFile.fName; ParamB.fileParam.ioVRefNum = argFile.vRefNum; ParamB.fileParam.ioFVersNum = 0; ParamB.fileParam.ioFDirIndex = 0; /* NamePtr/VRefNum */ if (Err(PBGetFInfo(&ParamB,0),errGetFInfo)) goto error; for (i = 0; i < 64; i++) { fileHeader[i] = argFile.fName[i]; InpRecord.fName[i] = argFile.fName[i]; } InpRecord.fType = argFile.fType; InpRecord.vRefNum = argFile.vRefNum; InpRecord.version = argFile.versNum; put4(&fileHeader[H_TYPEOFF], ParamB.fileParam.ioFlFndrInfo.fdType); put4(&fileHeader[H_AUTHOFF], ParamB.fileParam.ioFlFndrInfo.fdCreator); fileHeader[H_FLAGOFF ] = (ParamB.fileParam.ioFlFndrInfo.fdFlags >> 8) & 0xff; fileHeader[H_FLAGOFF+1] = (ParamB.fileParam.ioFlFndrInfo.fdFlags & 0xff); fileHeader[H_LOCKOFF ] = 0; fileHeader[H_LOCKOFF+1] = (ParamB.fileParam.ioFlAttrib & FLOCK) ? 1 : 0; put4(&fileHeader[H_DLENOFF], ParamB.fileParam.ioFlLgLen); put4(&fileHeader[H_RLENOFF], ParamB.fileParam.ioFlRLgLen); put4(&fileHeader[H_CTIMOFF], ParamB.fileParam.ioFlCrDat); put4(&fileHeader[H_MTIMOFF], ParamB.fileParam.ioFlMdDat); crc = upd_crc(0, fileHeader, (long) HDRBYTES); fileHeader[HDRBYTES ] = (crc >> 8) & 0xff; fileHeader[HDRBYTES+1] = (crc & 0xff); if (Compress) { Count = 4L; if (Err(FSWrite(pit_ref_num,&Count,"PMa4"), errWriting)) goto error; init_count(); init_output(); if (run_through_file(freq_count, pit_ref_num, fileHeader, &InpRecord, ParamB.fileParam.ioFlLgLen, ParamB.fileParam.ioFlRLgLen)) goto error; root = build_tree(); if (Err(write_tree(root, pit_ref_num), errWriting)) goto error; if (! build_sequences(root,0L,0)) { Err2(errCompress); goto error; } if (run_through_file(pack_write, pit_ref_num, fileHeader, &InpRecord, ParamB.fileParam.ioFlLgLen, ParamB.fileParam.ioFlRLgLen)) goto error; if (Err(flush_output(pit_ref_num), errWriting)) goto error; } /* if compress */ else { Count = 4L; if (Err(FSWrite(pit_ref_num, &Count, "PMag"), errWriting) || run_through_file(C_FSWrite, pit_ref_num, fileHeader, &InpRecord, ParamB.fileParam.ioFlLgLen, ParamB.fileParam.ioFlRLgLen)) goto error; } /* if compress */ DisposDialog(theDialog); theDialog = 0L; ClrAppFiles(j); } /* for j in argCount */ Count = 4; return (! Err(FSWrite(pit_ref_num, &Count, "PEnd"), errWriting)); } /* if Args != 0L */ else { /* Loop as long as the user is willing to supply files */ while (TRUE) { where.h = GET_FILE_X; where.v = GET_FILE_Y; SFGetFile(where, "", 0L, -1, 0L, 0L, &InpRecord); if (! InpRecord.good) { Count = 4; return (! Err(FSWrite(pit_ref_num, &Count, "PEnd"), errWriting)); } ParamText(0L, 0L, "\PPack", InpRecord.fName); theDialog = GetNewDialog(statusid, 0L, -1L); DrawDialog(theDialog); ParamB.fileParam.ioCompletion = 0L; ParamB.fileParam.ioNamePtr = InpRecord.fName; ParamB.fileParam.ioVRefNum = InpRecord.vRefNum; ParamB.fileParam.ioFVersNum = 0; ParamB.fileParam.ioFDirIndex = 0; if (Err(PBGetFInfo(&ParamB,0),errGetFInfo)) goto error; for (i = 0; i < 64; i++) fileHeader[i] = InpRecord.fName[i]; put4(&fileHeader[H_TYPEOFF], ParamB.fileParam.ioFlFndrInfo.fdType); put4(&fileHeader[H_AUTHOFF], ParamB.fileParam.ioFlFndrInfo.fdCreator); fileHeader[H_FLAGOFF ] = (ParamB.fileParam.ioFlFndrInfo.fdFlags >> 8) & 0xff; fileHeader[H_FLAGOFF+1] = (ParamB.fileParam.ioFlFndrInfo.fdFlags & 0xff); fileHeader[H_LOCKOFF ] = 0; fileHeader[H_LOCKOFF+1] = (ParamB.fileParam.ioFlAttrib & FLOCK) ? 1 : 0; put4(&fileHeader[H_DLENOFF], ParamB.fileParam.ioFlLgLen); put4(&fileHeader[H_RLENOFF], ParamB.fileParam.ioFlRLgLen); put4(&fileHeader[H_CTIMOFF], ParamB.fileParam.ioFlCrDat); put4(&fileHeader[H_MTIMOFF], ParamB.fileParam.ioFlMdDat); crc = upd_crc(0, fileHeader, (long) HDRBYTES); fileHeader[HDRBYTES ] = (crc >> 8) & 0xff; fileHeader[HDRBYTES+1] = (crc & 0xff); if (Compress) { Count = 4L; if (Err(FSWrite(pit_ref_num,&Count,"PMa4"), errWriting)) goto error; init_count(); init_output(); if (run_through_file(freq_count, pit_ref_num, fileHeader, &InpRecord, ParamB.fileParam.ioFlLgLen, ParamB.fileParam.ioFlRLgLen)) goto error; root = build_tree(); if (Err(write_tree(root, pit_ref_num), errWriting)) goto error; if (! build_sequences(root,0L,0)) { Err2(errCompress); goto error; } if (run_through_file(pack_write, pit_ref_num, fileHeader, &InpRecord, ParamB.fileParam.ioFlLgLen, ParamB.fileParam.ioFlRLgLen)) goto error; if (Err(flush_output(pit_ref_num), errWriting)) goto error; } else { Count = 4L; if (Err(FSWrite(pit_ref_num, &Count, "PMag"), errWriting) || run_through_file(C_FSWrite, pit_ref_num, fileHeader, &InpRecord, ParamB.fileParam.ioFlLgLen, ParamB.fileParam.ioFlRLgLen)) goto error; } /* Remove status dialog from screen */ DisposDialog(theDialog); theDialog = 0L; } /* while */ } /* if optkeyDown */ error: /* should not be reached except by "goto" */ if (theDialog != 0L) DisposDialog(theDialog); return FALSE; } /* Turn a long value into four characters. ################################# Put4 ################################ */ put4(str, data) unsigned char *str; long data; { int i; for (i = 3; i >= 0; i--) { str[i] = data & BYTEMASK; data >>= 8; } } /***************************************************************************/ /* Scaffolding to support the Mac user interface, DAs, etc. */ /***************************************************************************/ #define charcodemask 255 #define lastmenu 3 /* number of menus */ #define applemenu 1 /* menu ID for desk accessory menu */ #define filemenu 2 /* menu ID for File menu */ #define editmenu 3 /* menu ID for Edit menu */ #define iunpack 1 /* items in the File menu */ #define ifilter 2 /*-------*/ #define idelete 4 /*-------*/ #define ipack 6 #define icompress 7 /*-------*/ #define ihelp 9 /*-------*/ #define iquit 11 MenuHandle mymenus[lastmenu+1]; EventRecord myevent; WindowPtr whichwindow; int windowcode; Boolean userdone; #define maxStackSize 8192 setup() { int i; /* Do various magical things to set up memory (this is all from SKEL) */ typedef long *lomemptr; /* a pointer to low memory locations */ lomemptr nilptr; /* will have value NIL */ lomemptr stackbaseptr; /* points to current stack base */ EventRecord anEvent; nilptr = 0L; *nilptr = (long)'Blee';/* for ID=02 bomb on dereferencing 0 */ stackbaseptr = (lomemptr) 0x908; /* CurStackBase */ SetApplLimit ((Ptr) (*stackbaseptr - maxStackSize)); MaxApplZone(); MoreMasters(); MoreMasters(); MoreMasters(); InitGraf(&thePort); InitFonts(); FlushEvents(everyEvent, 0); InitWindows(); InitMenus(); TEInit(); InitDialogs(0L); InitCursor(); SetEventMask(everyEvent - keyUpMask); /* Check to see if the user is holding down the option key for a */ /* mass packing */ GetNextEvent(everyEvent, &anEvent); if(anEvent.modifiers & optionKey) optkeyDown = TRUE; else optkeyDown = FALSE; /* I can think of no reason why calling GetMenu() in a loop should */ /* have different results than unrolling the loop, but if MENU_BUG */ /* is defined, Unpit will bomb (or drop into Macsbug) when run. I */ /* suspect that the bombs are a result of a bug in LightSpeed C... */ /* Update: October 1, 1986. As suggested by Steve Stein of THINK, */ /* the problem is caused by SetEventMask in the LSC 1.0.2 MacTraps */ /* library. The fix is to search for hexadecimal 225f21df01444ed1 */ /* using FEdit/equivalent and change the third byte from 21 to 31. */ #ifdef MENU_BUG for (i = applemenu; i <= editmenu; i++) mymenus[i] = GetMenu(i); #else mymenus[applemenu] = GetMenu(applemenu); mymenus[filemenu] = GetMenu(filemenu); mymenus[editmenu] = GetMenu(editmenu); #endif AddResMenu(mymenus[applemenu],'DRVR'); Filter = TRUE; CheckItem(mymenus[filemenu],ifilter,/* Filter ? */ 255 /* :0 */); Compress = TRUE; CheckItem(mymenus[filemenu],icompress,/* Compress ? */ 255 /* :0 */); for (i = applemenu; i <= editmenu; i++) InsertMenu(mymenus[i],0); DrawMenuBar(); } /* Handle a command given through a menu selection ############################ DoCommand ############################## We carry out the command indicated by mResult. If it was Quit, we return true, else false. Since the menu was highlighted by MenuSelect, we must finish by unhighlighting it to indicate we're done. */ Boolean docommand (mresult) long mresult; { int refnum; int themenu, theitem; char name[255]; GrafPtr saveport; /* for saving current port in when opening a desk accessory */ Boolean returns; #define aboutboxid 257 #define aboutraeid 258 #define helponeid 261 #define helptwoid 262 #define okButton 1 #define moreButton 2 DialogPtr theDialog, moreDialog; int itemhit; returns = FALSE; /* assume Quit not selected */ themenu = HiWord (mresult); /* get the menu selected */ theitem = LoWord (mresult); /* ... and the Item of that menu */ switch (themenu) { case 0: break; /* user made no selection; do nothing */ case applemenu: if (theitem == 1) /* tell about the program */ { for(itemhit=0; itemhit!=okButton;) { theDialog = GetNewDialog(aboutboxid, 0L, -1L); ModalDialog(0L, &itemhit); DisposDialog(theDialog); if(itemhit == moreButton) { moreDialog = GetNewDialog(aboutraeid, 0L, -1L); ModalDialog(0L, &itemhit); DisposDialog(moreDialog); } } /* for */ } /* if */ else /* run a desk accessory; make sure port is preserved */ { GetPort (&saveport); GetItem (mymenus[applemenu], theitem, name); /* get name */ refnum = OpenDeskAcc (name);/* run the desk accessory */ SetPort (saveport); } break; case filemenu: switch (theitem) { case iunpack: unpack(); break; case ifilter: Filter = (Filter ? FALSE : TRUE); CheckItem(mymenus[filemenu],ifilter,(Filter) ? 255 : 0); break; case idelete: delete(); break; case ipack: pack(); break; case icompress: Compress = (Compress ? FALSE : TRUE); CheckItem(mymenus[filemenu],icompress,(Compress) ? 255 : 0); break; case ihelp: /* tell how to use the program */ theDialog = GetNewDialog(helponeid, 0L, -1L); ModalDialog(0L, &itemhit); DisposDialog(theDialog); theDialog = GetNewDialog(helptwoid, 0L, -1L); ModalDialog(0L, &itemhit); DisposDialog(theDialog); break; case iquit: returns = TRUE; break; } /* fileMenu case */ break; case editmenu: SystemEdit(theitem-1); break; } /* menu case */ HiliteMenu (0); /* turn off hilighting on the menu just used */ return (returns); } /* DoCommand */ maineventloop () { /* body of MainEventLoop */ FlushEvents (everyEvent, 0); /* discard leftover events */ /* get next event, and Handle it appropriately, until user QUITs */ userdone = FALSE; do { SystemTask (); /* Handle desk accessories */ if (GetNextEvent (everyEvent, &myevent)) { /* get event; if for us... */ switch (myevent.what) {/* Handle each kind of event */ case mouseDown: /* find out what window the mouse went down in, and where in it */ windowcode = FindWindow (myevent.where, &whichwindow); switch (windowcode) { /* Handle mouse-down for each place */ case inSysWindow: /* Handle the desk accessories */ SystemClick (&myevent, whichwindow); break;/* inSysWindow */ case inMenuBar: /* Handle the command */ userdone = docommand (MenuSelect (myevent.where)); break;/* inMenuBar */ } break; /* switch */ case keyDown: case autoKey: /* if command key, pass the char to MenuKey */ if ((myevent.modifiers & cmdKey) != 0) userdone = docommand (MenuKey ((char) (myevent.message & charcodemask))); break; /* switch */ case diskEvt: if (HiWord(myevent.message) != noErr) { Point where; where.h = INIT_X; where.v = INIT_Y; DIBadMount(where, myevent.message); } break; /* switch */ } } } while (userdone == FALSE); } main() { Handle Args; char OurName[64]; int OurRefNum, ArgCount, ArgType; AppFile *ArgFile; ParamBlockRec ParamB; Boolean even; setup(); DILoad(); GetAppParms(OurName, &OurRefNum, &Args); ArgType = **((int **) Args); ArgCount = *(((int *) (*Args)) + 1); if (ArgCount == 0) { maineventloop(); } else { if (ArgType != appOpen) { Err2(errBadPrint); } else { if(!optkeyDown) { HLock(Args); ArgFile = (AppFile *) (*Args + 4); while (ArgCount-- > 0) { ParamB.fileParam.ioCompletion = 0L; ParamB.fileParam.ioNamePtr = ArgFile->fName; ParamB.fileParam.ioVRefNum = ArgFile->vRefNum; ParamB.fileParam.ioFVersNum = 0; ParamB.fileParam.ioFDirIndex = 0; /* NamePtr/VRefNum */ PBGetFInfo(&ParamB,0); pit_bytes_left = ParamB.fileParam.ioFlLgLen; if (pit_bytes_left < 4L) { /* this is more meaningful than "I/O error", */ /* but we should also print the filename ... */ Err2(errNotPackit); } else { pit_index = 0; pit_max_index = -1; FSOpen(ArgFile->fName,ArgFile->vRefNum,&pit_ref_num); unpit(); FSClose(pit_ref_num); } even = ((ArgFile->fName[0] >> 1) * 2) == ArgFile->fName[0]; ArgFile = (AppFile *) (9 + ArgFile->fName[0] + (even ? 1 : 0) + (char *) ArgFile); } HUnlock(Args); } else { pack(); } } } DIUnload(); } --- end of part 3 ---