🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: mod.mac.sources
Article #43

Unpit version 0.3.1 Source (part 3 of 3)

#43
From: macintosh
Date: Fri, 13 Feb 1987 07:42
576 lines
18876 bytes
[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 ---
Technical Details
Message-ID: <2279@felix.UUCP>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!water!watnot!watmath!clyde!cuae2!ihnp4!ptsfa!lll-lcc!pyramid!hplabs!felix!macintosh
References: <2277@felix.UUCP> <2278@felix.UUCP>

Show Full Headers
Complete Article Headers
Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: arc1-ca.pugleaf.net!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)