/* -*- Mode:C; Tab-width:4  -*-
/*                                                                       */
/*                                                                       */
/*                      RESTRICTED RIGHTS LEGEND                         */
/*                                                                       */
/* Use, duplication, or disclosure by the Government is subject to       */
/* restrictions as set forth in subdivision (b)(3)(ii) of the Rights in  */
/* Technical Data and Computer Software clause at 52.227-7013.           */
/*                                                                       */
/*                    TEXAS INSTRUMENTS INCORPORATED.                    */
/*                            P.O. BOX 2909                              */
/*                         AUSTIN, TEXAS 78769                           */
/*                              MS 2151                                  */
/*                                                                       */
/*  Copyright (C) 1988, 1987, Texas Instruments Incorporated.            */
/*  All rights reserved.                                                 */
/*                                                                       */



#define __ALLNU__			/* include MacII stuff */
#include <types.h>
#include <quickdraw.h>
#include <toolutils.h>
#include <textedit.h>
#include <menus.h>
#include <events.h>
#include <controls.h>
#include <windows.h>
#include <dialogs.h>
#include <fonts.h>
#include <memory.h>
#include <osutils.h>
#include <traps.h>
#include <retrace.h>

#include "lispm.h"
#include "addincomm.h"
#include "micronet-accessors.h"

/* #define GGGDEBUG	1 */

    /* flags for AdjustScreenSize */
#define FVISIBLE	1
#define FREBUILDING	2
#define FCHECKSIZE	4


typedef union ParmBlk {
	struct {
	    Rect screenRect ;
	    short unused ;
	    short dynamicResize ;
	} r ;
	struct {
	    Pattern LinePenPattern ;
	    Point LineStartPoint ;
	    Point LineEndPoint ;
	    short LinePenHeight ;
	    short LinePenWidth ;
	    short LineExplorerWindowID ;
	    short LinePenMode ;
	    Rect LineClippingRect ;
	} l ;
	struct {
	    short Parm2 ;
	    short Parm1 ;
	    short Parm4 ;
	    short Parm3 ;
	    short Parm6 ;
	    short Parm5 ;
	    short Parm8 ;
	    short Parm7 ;
	    short Parm10 ;
	    short Parm9 ;
	    short Parm12 ;
	    short Parm11 ;
	    short Parm14 ;
	    short Parm13 ;
	    short Parm16 ;
	    short Parm15 ;
	} p ;
	struct {
	    short CharFont ;
	    char CharUnused ;		/* byted swapped crap */
	    char CharASCIICode ;
	    short CharFontSize ;
	    short CharFontStyle ;
	    Point CharBaseline ;
	    short CharExplorerWindowID ;
	    short CharPenMode ;
	    Rect CharClippingRect ;
	} c ;
	struct {
	    short StringFontStyle ;
	    short StringFont ;
	    short StringPenMode ;
	    short StringFontSize ;
	    short StringLength ;
	    short StringStartIndex ;
	    Point StringBaseline ;
	    short StringExplorerWindowID ;
	    short StringXLimit ;
	    Rect StringClippingRect ;
	} s ;
	struct {
	    Pattern RectanglePenPattern ;
	    Rect RectangleRect ;
	    short RectangleExplorerWindowID ;
	    short RectanglePenMode ;
	    Rect RectangleClippingRect ;
	} dr ;
	struct {
	    short FontMetricsStyle ;
	    short FontMetricsFont ;
	    short FontMetricsUnused ;
	    short FontMetricsSize ;
	} fm ;
	struct {
	    short KeyCode ;
	    short KeyModifiers ;
	} key ;
	struct {
	    short SelectVisibility ;
	    short SelectExplorerWindowID ;
	} sel ;
	struct {
	    short CopyMode ;
	    short CopyArrayType ;
	    short CopyHeight ;
	    short CopyWidth ;
	    short CopyDestinationID ;
	    short CopySourceID ;
	    Point CopySource ;
	    Point CopyDestination ;
	    short CopySourceHeight ;
	    short CopySourceWidth ;
		short CopyUnused ;			/* To position the last of an odd # of parms */
	    short CopyScreenUpdatesInhibited;
	} blt ;
	struct {
	    short AdjustBitArrayWidth ;
	    short AdjustBitArrayExplorerWindowID ;
	    short AdjustBitArrayContentsMatter ;
	    short AdjustBitArrayHeight ;
	} aba ;
	struct {
	    short AdjustExplorerWindowID ;
	    short AdjustExplorerScreenID ;
	    short AdjustScreenHeight ;
	    short AdjustScreenWidth ;
	    short AdjustUnused ;
	    short AdjustVisibility ;
	} ass ;
	struct {
	    short ToExplorerWindowID ;
	    short FromExplorerWindowID ;
	    Point ToWindowPosition ;
	} red ;
	struct {
	    Pattern TrianglePenPattern ;
	    Point TriangleVertex0 ;
	    Point TriangleVertex1 ;
	    Point TriangleVertex2 ;
	    short TriangleExplorerWindowID ;
	    short TrianglePenMode ;
	    Rect TriangleClippingRect ;
	} dt ;
	struct {
		Pattern FilledPolyFillPattern ;
	    short FilledPolyExplorerWindowID ;
	    short FilledPolyPenMode ;
		short FillPolyUnused ;
		short FilledPolyLength;
	    Rect FilledPolyClippingRect ;
		Point FilledPolyFirstVertex;		
	} dfp ;
	struct {
	    Pattern FrameRectPenPattern ;
	    Rect FrameRectRect ;
	    short FrameRectPenWidth ;
	    short FrameRectPenMode ;
	    short FrameRectExplorerWindowID ;
	    short FrameRectPenHeight ;
	    Rect FrameRectClippingRect ;
	} dfr ;
	struct {
	    Pattern OvalPenPattern ;
	    Rect OvalRect ;
	    short OvalExplorerWindowID ;
	    short OvalPenMode ;
	    Rect OvalClippingRect ;
	} dov ;
	struct {
	    Pattern FrameOvalPenPattern ;
	    Rect FrameOvalRect ;
	    short FrameOvalPenWidth ;
	    short FrameOvalPenMode ;
	    short FrameOvalExplorerWindowID ;
	    short FrameOvalPenHeight ;
	    Rect FrameOvalClippingRect ;
	} dfo ;
	struct {
	    short DeallocateUnused ;
	    short DeallocateExplorerWindowID ;
	} dea ;
	struct {
	    Point MousePosition ;
	    short MouseExplorerScreenID ;
	    short MouseButtons ;
	} mp ;
	struct {
	    short MouseCursorUnused ;
	    short MouseCursor ;
	} cur ;
} ParmBlk ;

#ifdef GGGDEBUG
#define NonBitArrayHeap 400000
#else
#define NonBitArrayHeap 300000 	/* Bytes of heap space for everything but bitarrays */
#endif

#define MaxResidentBitArrays 128 /* The maximum number of bitarrays which could be on the Mac
				 given sufficient memory */

struct BitArrayRec {
    Ptr start;		/*If NIL means slot in BitArrayPool is not currently unused*/
    long length;		/* If 0 means this slot in BitArrayPool has never been allocated */
} ;

Ptr BitArrayPoolAreaPtr;
long BitArrayPoolAreaSize;
struct BitArrayRec BitArrayPool[MaxResidentBitArrays]; /* For tracking BitArray Allocation */

typedef ParmBlk *PBlkPtr ;

extern EWS_ctrl_struct *EWS_ctrl ;	/* Pointer to heap-allocated structure of sizeable arrays */
extern MenuHandle myMenus[] ;
extern ScreensMenuItem ScreensMenu[] ;
extern int mouseDownNow ;
extern long mouseUpTime ;
extern int vMaxCtlValue, hMaxCtlValue ;
extern int MaxWindowWidth, MaxWindowHeight ;
extern Boolean DirectDrawingEnabled ;
extern WindowPtr gDebugWindowPtr ;

ParmBlk MyParms ;
WindowRecord wRecord ;
extern WindowPtr MouseWindow;
extern Boolean MouseHold;

RgnHandle TempRgn, BRgn, CRgn ;
RgnHandle GrayRgn ;
RgnHandle OldGrayRgn ;
long TTemp ;

GrafPort		miscPort ;

extern Boolean debugFlag ;

typedef struct {
    Boolean 	UpdateP ;
    short 		ScreenUpdatesInhibited ; /* This allows mx to bunch screen updates together. */
    int 		ExplorerWindowID ;
    Rect 		InvalidRect ;
	short		CurrentCommandOpcode ;
} UpdateType ;

int WhoStateSize ;
int MouseDocCount = 2 ;
int MouseDocCharHeight ;
int MaxUsedWid = -1 ;
int MaxUsedSid= -1 ;
int MaxUsedBAid = -1 ;

UpdateType UpdateRec ;

Ptr BitArrayPtr ;
Cursor currentCursor ;


Boolean
ValidateBitMapPtr (BMPtr, CallNumber)
BitMap		*BMPtr ;
short		CallNumber ;
{
	Boolean		AnAllocatedBlockP = FALSE ;
	short		i ;
	for (i = 0; i <= MaxUsedBAid; i++)
		if (BitArrayPool[i].start == (Ptr)BMPtr) {
			AnAllocatedBlockP = i + 1 ;			/* +1 to ensure non-zero */
			break ;
		}
	if (
		AnAllocatedBlockP &&
		(BitArrayPool[AnAllocatedBlockP - 1].length == 
			(long)(((BMPtr->bounds.right+15)/16) * 2 * BMPtr->bounds.bottom)) &&
		BMPtr->baseAddr >= &BitArrayPoolAreaPtr[0] &&
		BMPtr->baseAddr <= &BitArrayPoolAreaPtr[BitArrayPoolAreaSize-1] &&
		(BMPtr->rowBytes * 8) >= BMPtr->bounds.right
		)  { 
		return (TRUE) ;
	} else {
		debugPrint1 ("ValidateBitMapPtr call #%d failed.\n", CallNumber) ;
		if (BMPtr) 
			dumpPortBits ("Input BitMap", BMPtr) ;
		return (FALSE) ;
	}
}


Boolean
ValidateGrafPortPtr (GPPtr, CallNumber)
GrafPtr		GPPtr ;
short		CallNumber ;
{
	if (
		ValidateBitMapPtr (&GPPtr->portBits, CallNumber) &&
		GPPtr->grafProcs == NULL &&
		PtInRect (GPPtr->pnLoc, &GPPtr->portRect)
		) { 
		return (TRUE) ;
	} else {
		debugPrint1 ("ValidateGrafPortPtr call #%d failed.", CallNumber);
		return (FALSE) ;
	}
}


ThisIsOneOfOurWindows(Window)
WindowPtr Window ;
{
    register long RefCon ;

    RefCon = GetWRefCon(Window) ;
    if (RefCon > 0 && RefCon <= MaxUsedWid && EWS_ctrl->MyWindows[RefCon])
	if (EWS_ctrl->MyWindows[RefCon]->myWindow == Window)
	    return(TRUE) ;
    return(FALSE) ;
}


/*										*/
/* Someday try adding the following term to the definition of OnScreenP:	*/
/* !EmptyRgn (EWS_ctrl->MyWindows[abs(EWS_ctrl->
		AssociatedMacWindowID[WindowID])]->myWindow->visRgn))*/

Boolean
OnScreenP(WindowID)
int 		WindowID;
{
	Boolean 	result;
	
	if (WindowID == PRINTER_ID) { /* ab 9/20/88.  Do nothing for printer */
		return (FALSE) ;
	}
		
	EWS_ctrl->MyWindows[abs(EWS_ctrl->AssociatedMacWindowID[WindowID])]->SavedBitMapIsCurrent = 
     	   	(EWS_ctrl->SavedGrafPorts[WindowID]->portBits.baseAddr != qd.screenBits.baseAddr) ;
	result = 
		(EWS_ctrl->AssociatedMacWindowID[WindowID] != 0) && 
    	(EWS_ctrl->MyWindows[abs(EWS_ctrl->AssociatedMacWindowID[WindowID])]->SavedBitMapIsCurrent) ;
			
#ifdef GGGDEBUG
	if (debugFlag && FALSE) {
		debugPrint (8, "OnScreenP: Time= %6d  Op= %d  WID= %d  AMWID= %d  SBMIC= %d  SGP/bA= x%08x/x%08x  R= %d\n",
			TickCount (), UpdateRec.CurrentCommandOpcode, WindowID, 
			EWS_ctrl->AssociatedMacWindowID[WindowID],
			EWS_ctrl->MyWindows[abs(EWS_ctrl->AssociatedMacWindowID[WindowID])]->SavedBitMapIsCurrent,
			EWS_ctrl->SavedGrafPorts[WindowID],
			EWS_ctrl->SavedGrafPorts[WindowID]->portBits.baseAddr,
			result);
	    }
#endif GGGDEBUG

    return (result);
}

Boolean
EligibleForToScreenDrawingP(S)
short 		S;		/* AssociatedMacWindowID of an E-window visible on an E-screen */
{
	Boolean				result = FALSE ;
	GrafPtr				thisWindow ;
	Boolean				ScreenImageIsCurrent ;
    MacWindowRecPtr 	macrec;
	
	if ((S == 0) || (S == PRINTER_ID))				   /* ab 9/20/88 */
		return (result);
	S = abs (S) ;
	macrec = EWS_ctrl->MyWindows[S] ;
	if (macrec && (thisWindow = macrec->myWindow) && (macrec->MacWindowsSavedBitMapsID > -1)) {
		ScreenImageIsCurrent = !macrec->AwaitingAnUpdateEvent ;
		result = DirectDrawingEnabled && (FrontWindow () == thisWindow) && ScreenImageIsCurrent ;
		if (result) {
   			RectRgn (TempRgn, &EWS_ctrl->SavedBitMaps[macrec->MacWindowsSavedBitMapsID].bounds);
			RectRgn (CRgn, &macrec->UsableArea) ;
			SectRgn (thisWindow->visRgn, CRgn, BRgn) ;
			UnionRgn (BRgn, TempRgn, CRgn) ;
			result = result && (EqualRgn (CRgn, BRgn)) ;
		}
	
#ifdef GGGDEBUG
		if (debugFlag) {
			debugPrint(7, "Eligible?  S= %d  DDE= %d  FW=W: %d  SIiC= %d  SBMID= %d  BuV=V: %d  Result= %d\n",
				S,
				DirectDrawingEnabled,
				FrontWindow () == thisWindow,
				ScreenImageIsCurrent,
				macrec->MacWindowsSavedBitMapsID,
				EqualRgn(CRgn, thisWindow->visRgn),
				result);
		}
#endif
	}
	return (result);
}

void
ChangeEWindowFromSBMtoScreen (w, MacWindowID)
short 		w;				/* ID of an E-window currently drawing directly to a SavedBitMap */
short		MacWindowID ;	/* w's associated Mac Window's ID */
{
    GrafPtr    SGP = EWS_ctrl->SavedGrafPorts[w];
	WindowPtr  MacWindow = EWS_ctrl->MyWindows[abs(MacWindowID)]->myWindow;
	
	if (SGP->portBits.baseAddr != qd.screenBits.baseAddr) {		/* NOP if SGP points at screen */
#ifdef GGGDEBUG
		if (debugFlag ) {
			debugPrint2("CEWfSBMtS: wID= %d  SGP[wID]= x%08x\n", w, SGP);
			dumpPort("CEWfSBMtS MacWindow", MacWindow) ;
			dumpPort("CEWfSBMtS SGP before:", SGP);
		}
#endif

		OffsetRect (&SGP->portBits.bounds, 
			MacWindow->portBits.bounds.left, MacWindow->portBits.bounds.top) ;
    	SGP->portBits.baseAddr = MacWindow->portBits.baseAddr;
    	SGP->portBits.rowBytes = MacWindow->portBits.rowBytes;
	
#ifdef GGGDEBUG
		if (debugFlag) {
			dumpPort("CEWfSBMtS SGP after", SGP);
		}
#endif
	}

}

void
ChangeEWindowFromScreentoSBM (w, MacWindowID)
short 		w;				/* ID of an E-window currently drawing directly to Mac screen */
short		MacWindowID ;	/* w's associated Mac Window's ID */
{
    WindowPtr  MacWindow = EWS_ctrl->MyWindows[abs(MacWindowID)]->myWindow;
	GrafPtr    SGP = EWS_ctrl->SavedGrafPorts[w];
    short      OSBMid = EWS_ctrl->IDofOriginalSavedBitMapIndirectedTo[w];

	if (SGP->portBits.baseAddr == qd.screenBits.baseAddr) {		/* NOP unless SGP points at screen */
#ifdef GGGDEBUG
		if (debugFlag) {
			debugPrint2("CEWfStSBM: W= %d, OSBMid= %d\n", w, OSBMid);
			dumpPort("CEWfStSBM MacWindow", MacWindow) ;
			dumpPort("CEWfStSBM SGP before", SGP);
		}
#endif

	    OffsetRect (&SGP->portBits.bounds, 
			-MacWindow->portBits.bounds.left, -MacWindow->portBits.bounds.top) ;
	    SGP->portBits.baseAddr = EWS_ctrl->SavedBitMaps[OSBMid].baseAddr ;
	    SGP->portBits.rowBytes = EWS_ctrl->SavedBitMaps[OSBMid].rowBytes ;
	
#ifdef GGGDEBUG
		 if (debugFlag) {
			dumpPort("CEWfStSBM SGP after", SGP);
		}
#endif
	}
}

static void
rFontInfo(Finfo, Font, Size)
FontInfo *Finfo ;
int Font, Size ;
{
    if (Finfo) {
		if (EWS_ctrl->CachedFontInfo[Font].FontSize != Size) {
	   		GetFontInfo(&EWS_ctrl->CachedFontInfo[Font].FontInfo) ;
	    	EWS_ctrl->CachedFontInfo[Font].FontSize = Size ;
		}
		*Finfo = EWS_ctrl->CachedFontInfo[Font].FontInfo ;
    }
}

void
UpdateUsableArea(MacWindowRecord)
register MacWindowRecPtr MacWindowRecord ;
{
    GrafPtr tempPort ;

    if (MacWindowRecord) {
		MacWindowRecord->UsableArea = MacWindowRecord->myWindow->portRect ;
		MacWindowRecord->UsableArea.right -= VSBarWidth ;
		MacWindowRecord->UsableArea.bottom -= HSBarHeight + 
				MouseDocumentHeight(MacWindowRecord->MouseDocCount) ;
		GetPort(&tempPort) ;
		SetPort(MacWindowRecord->myWindow) ;
		ClipRect(&MacWindowRecord->UsableArea) ;
		SetPort(tempPort) ;
    }
}

Ptr
NewBitMap(theBitMap, width, height)
register BitMap *theBitMap;
short width, height;		/* Width & height needed in pixels (bits) */
{
    long 	length;		 	/* Length in Bytes of memory needed for bit array */
    short 	i;
    long 	base = 0;
    GrafPtr oldPort ;

	/* Protect ourselves from bad callers */
    if ((theBitMap == NULL))  {  /* || !ValidateBitMapPtr (theBitMap, 1)) */
		debugPrint0("NewBitMap called with a NULL GrafPtr!\n") ;
		debugDump () ;
		return(NULL) ;
	}
	
    length = ((width+15) / 16) * 2 * (long)height ;

	/*Allocate a new block of memory from the BitArrayPool */

    for (i = 0; i < MaxResidentBitArrays; i++) {
		if (BitArrayPoolAreaSize < (base + length)) 	/* Any room left?*/
	    	break;				 						/* Nope, no use continuing */

		if ((BitArrayPool[i].start == NULL) && 			/* Slot not currently assigned? */
				((BitArrayPool[i].length == 0) ||     	/* Previously unassigned slot? */
 				 (length <= BitArrayPool[i].length))) { /* Previously used slot big enough?*/
			/*Allocate it*/
	    	if (BitArrayPool[i].length == 0)
				BitArrayPool[i].length = length;
			if (i > MaxUsedBAid)
				MaxUsedBAid = i ;
	   		BitArrayPool[i].start = &BitArrayPoolAreaPtr[base];
	    	theBitMap->baseAddr = BitArrayPool[i].start;
	    	theBitMap->rowBytes = ((width+15) / 16) * 2 ;
	    	SetRect(&theBitMap->bounds, 0, 0, width, height) ;
#ifdef GGGDEBUG
	    	if (debugFlag) {
				long	CurrentBlockAdr = 0 ;
				int		j ;
				for (j = 0; j < MaxResidentBitArrays; j++) {
					if (BitArrayPool[j].start == NULL) {
						if (BitArrayPool[j].length == 0) {
							break ;
						} else {
							debugPrint2 ("NewBitMap - %d-byte hole at x%08x.\n",
								BitArrayPool[j].length, &BitArrayPoolAreaPtr[CurrentBlockAdr]) ;
						}
					} else {
						if (j > MaxUsedBAid)
							debugPrint2 ("NewBitMap - slot %d(%d) in use but beyond max.\n",
								j, MaxUsedBAid) ;
					}
					CurrentBlockAdr += BitArrayPool[j].length ;
				}
				debugPrint5("NewBitMap %d  (Max= %d)  PTR = x%08x  LEN = %d  SPACE= %d\n",
					i, MaxUsedBAid, theBitMap->baseAddr, length,
					BitArrayPoolAreaSize - CurrentBlockAdr) ;
	    	}
#endif
	    	return(theBitMap->baseAddr) ;
		}
		base += BitArrayPool[i].length; /*Keep looking*/
    }
#ifdef GGGDEBUG
    if (debugFlag) {
		debugPrint2("NewBitMap Failed  PTR = x%08x  LEN = %d\n", theBitMap->baseAddr, length) ;
    }
#endif
    return(NULL) ;
}

static
ChangeBitArraySize(WindowID, NewWidth, NewHeight, ContentsMatter)
int WindowID, NewWidth, NewHeight, ContentsMatter ;
{
    BitMap oldBitMap ;
    register int i ;
    register BitMap *cBitMap ;
    GrafPtr oldPort ;

    if (WindowID == PRINTER_ID) {
#ifdef ABDEBUG
        printf ("ChangeBitArraySize called on printer--illegal\n");
#endif
        return (TRUE);
    }
    cBitMap = &EWS_ctrl->SavedBitMaps[WindowID] ;
    if (cBitMap->baseAddr != qd.screenBits.baseAddr) {
		oldBitMap = *cBitMap ;
		if (cBitMap->bounds.right >= NewWidth && cBitMap->bounds.bottom >= NewHeight) {
	    	cBitMap->bounds.right = NewWidth ;
	    	cBitMap->bounds.bottom = NewHeight ;
		} else {

	    	if (NewBitMap(cBitMap, NewWidth, NewHeight) == NULL)
				return(FALSE) ;

	    	GetPort(&oldPort) ;
		    SetPort(EWS_ctrl->SavedGrafPorts[WindowID]) ;
	    	if (ContentsMatter) {
				CopyBits(&oldBitMap, cBitMap, &oldBitMap.bounds, &oldBitMap.bounds,
						srcCopy, NULL) ;
	    	}
	    	FreeBitMap(oldBitMap.baseAddr) ;

			/* propagate the change through all the valid grafPorts */
	    	for (i=1; i <= MaxUsedWid; i++) {
				if (EWS_ctrl->SavedGrafPorts[i] && 
						(EWS_ctrl->SavedGrafPorts[i]->portBits.baseAddr == 
							oldBitMap.baseAddr)) {
		    		SetPort(EWS_ctrl->SavedGrafPorts[i]) ;
		    		PortSize(NewWidth, NewHeight) ;
		    		SetPortBits(cBitMap) ;
		    		RectRgn(EWS_ctrl->SavedGrafPorts[i]->visRgn, 
					&EWS_ctrl->SavedGrafPorts[i]->portRect) ;
#ifdef GGGDEBUG
		    		if (debugFlag)
		    			debugPrint1("propagated to %d\n", i) ;
#endif
				}
	    	}
	    	SetPort(oldPort) ;

		}
    } else {
		if (NewBitMap(cBitMap, NewWidth, NewHeight) == NULL) {
	    	*cBitMap = qd.screenBits ;
	    	return(FALSE) ;
		}
    }
    return(TRUE) ;
}


/*																					*/
/*	Debugging Routines for printing the contents of common structures to the debug	*/
/*		window.																		*/
/*																					*/

#ifdef GGGDEBUG

dump1Rect (label1, rect1)
char 	*label1 ;
Rect	*rect1 ;
{
	if (debugFlag)
		debugPrint5 (" %s: %d %d %d %d\n",
			label1, rect1->left, rect1->top, rect1->right, rect1->bottom);
}

dump2Rects(label1, rect1, label2, rect2)
char 	*label1 ;
char	*label2 ;
Rect	*rect1 ;
Rect	*rect2 ;
{
	if (debugFlag)
		debugPrint (10, " %s: %d %d %d %d        %s: %d %d %d %d\n",
			label1, rect1->left, rect1->top, rect1->right, rect1->bottom,
			label2, rect2->left, rect2->top, rect2->right, rect2->bottom);
}

dump3Rects(label1, rect1, label2, rect2, label3, rect3)
char 	*label1 ;
char	*label2 ;
char	*label3 ;
Rect	*rect1 ;
Rect	*rect2 ;
Rect	*rect3 ;
{
	if (debugFlag)
		debugPrint (15, " %s: %d %d %d %d     %s: %d %d %d %d     %s: %d %d %d %d\n",
			label1, rect1->left, rect1->top, rect1->right, rect1->bottom,
			label2, rect2->left, rect2->top, rect2->right, rect2->bottom,
			label3, rect3->left, rect3->top, rect3->right, rect3->bottom);
}

dump4Rects(label1, rect1, label2, rect2, label3, rect3, label4, rect4)
char 	*label1 ;
char	*label2 ;
char	*label3 ;
char	*label4 ;
Rect	*rect1 ;
Rect	*rect2 ;
Rect	*rect3 ;
Rect	*rect4 ;
{
	if (debugFlag)
		debugPrint (20, " %s: %d %d %d %d    %s: %d %d %d %d    %s: %d %d %d %d    %s: %d %d %d %d\n",
			label1, rect1->left, rect1->top, rect1->right, rect1->bottom,
			label2, rect2->left, rect2->top, rect2->right, rect2->bottom,
			label3, rect3->left, rect3->top, rect3->right, rect3->bottom,
			label4, rect4->left, rect4->top, rect4->right, rect4->bottom);
}

dumpPort(label, port)
char *label ;
GrafPtr port ;
{
    if (debugFlag) {
		if (label && *label)
	    	debugPrint3("%s: dump of grafPort x%08x, baseAddr= x%08x\n",
				label, port, port->portBits.baseAddr) ;
		dump4Rects(" clip", &(*port->clipRgn)->rgnBBox,
			"vis", &(*port->visRgn)->rgnBBox,
			"bounds", &port->portBits.bounds,
			"portRect", &port->portRect) ;

    }
}

dumpPortBits(label, bits)
char *label ;
BitMap *bits ;
{
    if (debugFlag) {
		debugPrint(7, " %s:  baseAddr = x%08x  rowbytes = %d  bounds = %d %d %d %d\n",
			label, bits->baseAddr, bits->rowBytes, 
			bits->bounds.left, bits->bounds.top, bits->bounds.right, bits->bounds.bottom) ;
    }
}
#endif

dumpCopyBitsCall(srcBits, dstBits, srcRect, dstRect, mode, maskRgn)
BitMap			*srcBits, *dstBits;
Rect 			*srcRect, *dstRect;
short			mode;
RgnHandle		maskRgn;
{
	if (debugFlag) {
		dumpPortBits ("srcBits", srcBits);
		dumpPortBits ("dstBits", dstBits);
		dump3Rects ("srcRect", srcRect, "dstRect", dstRect,
			"thePort's visRgn", &(*qd.thePort->visRgn)->rgnBBox);
		if (maskRgn != NULL) 
			dump1Rect ("maskRgn", &(*maskRgn)->rgnBBox) ;
	}
}

dumpEvent (EventPtr)
EventRecord		*EventPtr ;
{
	if (EventPtr->what != 0)				/* Don't report a nullEvent */
		debugPrint (6, "** EventRecord: what= %d  message= x%08x  when= %d here= (%d,%d)  modifiers= %04x\n",
			EventPtr->what,
			EventPtr->message,
			EventPtr->when,
			EventPtr->where.h,
			EventPtr->where.v,
			EventPtr->modifiers);
}
	
/* ab 9/20/88 Start new debug routines */

printregion(label, rgnhandle)
char *label ;
register RgnHandle rgnhandle;
{
    printw(" %s: Size = %d.  Rect = %d %d %d %d\n", label,
			(*rgnhandle)->rgnSize, (*rgnhandle)->rgnBBox.left, (*rgnhandle)->rgnBBox.top, 
			(*rgnhandle)->rgnBBox.right, (*rgnhandle)->rgnBBox.bottom);
}


printpoint(label, point)
char *label ;
register Point *point ;
{
    printw(" %s: %d %d\n", label, point->v, point->h);
}

printgrafport(label, grafptr)
char *label ;
register GrafPtr grafptr;
{
    printw("%s:\n", label);
	printw(" portBits = %08x,  grafProcs = %08x\n", grafptr->portBits, grafptr->grafProcs);
	printrect("portRect", &grafptr->portRect);
	printrect("portBits.bounds", &grafptr->portBits.bounds);
	printregion("visRgn", grafptr->visRgn);
	printregion("clipRgn", grafptr->clipRgn);
	printw( " pnMode = %d,  pnVis = %d,  txFont = %d, txMode = %d, txSize = %d\n",
				grafptr->pnMode, grafptr->pnVis, grafptr->txFont, grafptr->txMode, grafptr->txSize);
}

/* ab 9/20/88 End new debug routines */


/* Creates a bitarray for a LispM window or adjusts its size if it already exists.
   Also changes the size of the LispM window's grafPort to agree.
   Parms are windowID, width, height, and contents-matter.
   When width<=0 then the window has no bit map and is not to be given a bit map, just
   adjust the size of the window's graphPort. */

static
AdjustAnyBitArray(winID, width, height, contents_matter)
register int winID ;
int width, height, contents_matter ;
{
    Rect 	bounds ;
    GrafPtr oldPort ;
	
	/* ab 9/20/88 */
	if (winID == PRINTER_ID)  {
#ifdef ABDEBUG
        printw("AdjustAny called on PRINTER\n");
#endif
		return (TRUE);
    }
	if (width < 0)
		width = -width ;
	else if (! ChangeBitArraySize(winID, width, height, contents_matter))
		return (FALSE) ;

	/* Get the window a new grafPort if necessary */
	GetPort (&oldPort) ;
	if (EWS_ctrl->SavedGrafPorts[winID] == NULL) {
		EWS_ctrl->SavedGrafPorts[winID] = (GrafPtr)NewPtr(sizeof(GrafPort)) ;
		if (EWS_ctrl->SavedGrafPorts[winID] == NULL)
			return (FALSE) ;
		OpenPort(EWS_ctrl->SavedGrafPorts[winID]) ;
	} else 
		SetPort(EWS_ctrl->SavedGrafPorts[winID]) ;
	
	/*	thePort is now this E-window's grafPort.  Update its portBits size, visRgn,
		and cliping region.  */
	if (EWS_ctrl->SavedGrafPorts[winID]->portBits.baseAddr != qd.screenBits.baseAddr)
		SetPortBits (&EWS_ctrl->SavedBitMaps[winID]) ;
	else
		PortSize (width, height) ;
	RectRgn(EWS_ctrl->SavedGrafPorts[winID]->visRgn,
		&EWS_ctrl->SavedGrafPorts[winID]->portRect) ;
	SetRect (&bounds, 0, 0, width, height) ;
	ClipRect(&bounds) ;
	
#ifdef GGGDEBUG
	if (debugFlag) {
		debugPrint2 ("ABA  W= %d(%d).\n", winID, MaxUsedWid) ;
		dumpPort("ABA", EWS_ctrl->SavedGrafPorts[winID]) ;
	}
#endif
	/* Update upper bound for array scanning */
	if (winID > MaxUsedWid)
		MaxUsedWid = winID ;
		
	SetPort (oldPort) ;
    return (TRUE) ;
}

static void
AddScreenMenuItem(theWindow, theName)
WindowPtr theWindow ;
char *theName ;
{
    int nitems ;
    char name[255] ;

    strcpy(name, "\265Explorer ") ;
    strcat(name, theName) ;
    AppendMenu(myMenus[scrnM], name) ;
    nitems = CountMItems(myMenus[scrnM]) ;
    ScreensMenu[nitems].window = theWindow ;
    strcpy(ScreensMenu[nitems].name, name) ;
}

void
RemoveScreenMenuItem(theWindow)
WindowPtr theWindow ;
{
    register int nitems, i, j ;
    int deaditem ;

    if (theWindow == NULL)
		return ;

    nitems = CountMItems(myMenus[scrnM]) ;
    i = j = 0 ;
    deaditem = -1 ;
    do {
		i++ ;
		j++ ;
		if (theWindow == ScreensMenu[i].window) {
		    deaditem = i ;
		    j++ ;
		}
		ScreensMenu[i].window = ScreensMenu[j].window ;
		strcpy(ScreensMenu[i].name, ScreensMenu[j].name) ;
    } while (j <= nitems) ;
    if (deaditem != -1) {
		DelMenuItem(myMenus[scrnM], deaditem) ;
    }
}

void
UpdateScreensMenu(theWindow)
WindowPtr theWindow ;
{
    int i, nitems ;

    if (theWindow) {
		nitems = CountMItems(myMenus[scrnM]) ;
		for (i=1 ; i <= nitems; i++)
		    CheckItem(myMenus[scrnM], i, (ScreensMenu[i].window == theWindow)) ;
    }
}

/*	The following routine is the guts of a Redirect Drawing command.  It has been made a
	separate routine so it could be invoked as part of CreateMacWindow, allowing us to
	fake a RedirectDrawing of a newly created Mac Window's E-screen's E-window to itself.
	Doing this handles all the Direct Drawing issues correctly for an E-screen's E-window.
	*/
static void
Direct_a_Windows_Drawing_To (FromEWindowID, ToEWindowID, WhereInToWindow_x, WhereInToWindow_y) 
short		FromEWindowID, ToEWindowID,	WhereInToWindow_x, WhereInToWindow_y ;
{
    Rect 		bounds ;
	short 		OldAssociatedMacWindowID;	/* AMWID prior to this redirection */
	short 		NewAssociatedMacWindowID;	/* AMWID after    this redirection */
	
	/* ab 9-20-88 */
	if (FromEWindowID == PRINTER_ID ||
		MyParms.red.ToExplorerWindowID == PRINTER_ID) {
#ifdef ABDEBUG
        printw("Redirect called on PRINTER\n");
#endif
		return;
	}

#ifdef GGGDEBUG
    if (debugFlag) {
		debugPrint4 ("Redirect: %d to %d  x:%d  y:%d\n",
			FromEWindowID, ToEWindowID,
			WhereInToWindow_x, WhereInToWindow_y);
	}	
	if ((EWS_ctrl->SavedBitMaps[ToEWindowID].baseAddr ==
				qd.screenBits.baseAddr) &&
			(FromEWindowID != ToEWindowID)) {
		debugPrint4 ("Redirect: %d to %d  x:%d  y:%d  DESTINATION = SCREENBITS!\n", 
			FromEWindowID, ToEWindowID,
			WhereInToWindow_x, WhereInToWindow_y);
		debugDump () ;
	}
#endif
    if (EWS_ctrl->SavedGrafPorts[FromEWindowID] == NULL) {
#ifdef GGGDEBUG
		debugPrint1("Redirect: CREATING GRAFPORT FOR WID %d!\n",
			FromEWindowID) ;
		debugDump () ;
#endif
		EWS_ctrl->SavedGrafPorts[FromEWindowID] =
			(GrafPtr)NewPtr(sizeof(GrafPort)) ;
		if (EWS_ctrl->SavedGrafPorts[FromEWindowID] == NULL)  {
			PrtErrorMsg(215) ;
  			CloseDriver(DriverData->refnum);
			exit(-1);
		}
		OpenPort(EWS_ctrl->SavedGrafPorts[FromEWindowID]) ;
		bounds = EWS_ctrl->SavedBitMaps[ToEWindowID].bounds ;
		bounds.right -= bounds.left ;
		bounds.bottom -= bounds.top ;
		bounds.left = bounds.top = 0 ;
		PortSize(bounds.right - bounds.left, bounds.bottom - bounds.top) ;
		RectRgn(EWS_ctrl->SavedGrafPorts[FromEWindowID]->visRgn, &bounds) ;
		ClipRect(&bounds) ;
    }

    SetPort(EWS_ctrl->SavedGrafPorts[FromEWindowID]) ;
    SetOrigin(0, 0) ;
    SetPortBits(&EWS_ctrl->SavedBitMaps[ToEWindowID]) ;
    bounds = EWS_ctrl->SavedGrafPorts[FromEWindowID]->portBits.bounds ;
    PortSize(bounds.right - bounds.left, bounds.bottom - bounds.top) ; 
    RectRgn(EWS_ctrl->SavedGrafPorts[FromEWindowID]->visRgn, &bounds) ;

	/* Position this window within its ultimate superior */
    SetOrigin(-WhereInToWindow_x, -WhereInToWindow_y) ;

	/* Remember this window's previous AMWID, set its new one, handle possible	*/
	/* change in the window's direct-drawing state.  This code works because	*/
	/* (1) the initial value for AssociatedMacWindowID[W] is 0, signifying that	*/
	/* E-window W is not visible on any E-screen, and (2) this code is never 	*/
	/* executed for the	E-window directly associated with an E-screen.			*/
	
	OldAssociatedMacWindowID = 
		EWS_ctrl->AssociatedMacWindowID[FromEWindowID];
	NewAssociatedMacWindowID = OldAssociatedMacWindowID ;
    if (OldAssociatedMacWindowID <= 0)  /* A window, not a screen */
		if (EWS_ctrl->AssociatedMacWindowID[ToEWindowID] > 0)
			NewAssociatedMacWindowID =
				-EWS_ctrl->AssociatedMacWindowID[ToEWindowID] ;
		else
			NewAssociatedMacWindowID = 0 ;
		
    {
	short S, w;

	S = NewAssociatedMacWindowID;
	w = FromEWindowID;

#ifdef GGGDEBUG
    if (debugFlag) {
		debugPrint4 ("Redirect: OldAMWI= %d/%d  AMWI = %d/%d\n",
			OldAssociatedMacWindowID, EligibleForToScreenDrawingP (OldAssociatedMacWindowID),
			S, EligibleForToScreenDrawingP (S));
		dumpPort(NULL, EWS_ctrl->SavedGrafPorts[FromEWindowID]) ;
    }
#endif

	EWS_ctrl->IDofOriginalSavedBitMapIndirectedTo[w] = abs(ToEWindowID);
	if ((S != 0 && ((OldAssociatedMacWindowID == 0) 
					|| (S > 0 && S == OldAssociatedMacWindowID)
					)) &&
			EligibleForToScreenDrawingP (NewAssociatedMacWindowID)) {
	    ChangeEWindowFromSBMtoScreen (w, NewAssociatedMacWindowID);
	} else
		if (S == 0 && OldAssociatedMacWindowID !=0 && 
				EligibleForToScreenDrawingP (OldAssociatedMacWindowID))
			ChangeEWindowFromScreentoSBM (w, OldAssociatedMacWindowID);
    }
	
	EWS_ctrl->AssociatedMacWindowID[FromEWindowID] = NewAssociatedMacWindowID ;

}


static
CreateMacWindow(MacWindowID, ExpWindowID, width, height, flags)
int MacWindowID, ExpWindowID, width, height;
int flags;
{
    extern WindowPtr gDebugWindowPtr ;
    Boolean AllocationFailure = FALSE ;
    Rect drawRect;
    Rect vScrollArea;
    Rect hScrollArea;
    char MacWindowIDStr[255];
    register MacWindowRecPtr macrec;
    int center;
    FontInfo finfo ;
    Boolean createNew ;
    static char firsttime = TRUE ;
    short useablewidth ;
    short useableheight ;

    macrec = EWS_ctrl->MyWindows[MacWindowID] ;
    createNew = (macrec == NULL) ;

	if (ExpWindowID == PRINTER_ID) {						/* ab 9/20/88 */
		return(0);
	}
	
    if (createNew) {
		macrec = EWS_ctrl->MyWindows[MacWindowID] = 
				(MacWindowRecPtr)NewPtr(sizeof(MacWindowRec));
		if (macrec == NULL)
	    	return(-1) ;
		if (MacWindowID > MaxUsedSid)
			MaxUsedSid = MacWindowID ;
		if (ExpWindowID > MaxUsedWid)
			MaxUsedWid = ExpWindowID ;

#ifdef GGGDEBUG
		if (debugFlag)
	   		debugPrint5("Screen .. Mac: %d(%d)  Exp: %d(%d)  WRPtr: %d\n",
				MacWindowID, MaxUsedSid, ExpWindowID, MaxUsedWid,
				macrec);
#endif
#ifdef NOTYET			/* full screen width stuff */
	SetRect(&drawRect, qd.screenBits.bounds.left, qd.screenBits.bounds.top + 40,
			min(width, qd.screenBits.bounds.right) + VSBarWidth,
			min(height + HSBarHeight + MouseDocumentHeight(MouseDocCount) + 40,
			qd.screenBits.bounds.bottom - 1)) ;
#else
		useablewidth = ((qd.screenBits.bounds.right - qd.screenBits.bounds.left) -
				VSBarWidth) & ~31 ;
		useablewidth = min(width, useablewidth) ;
		useableheight = (qd.screenBits.bounds.bottom - qd.screenBits.bounds.top) -
				40 - HSBarHeight - 1 - MouseDocumentHeight(MouseDocCount) ;
		useableheight = min(height, useableheight) ;
/*		center = ((qd.screenBits.bounds.right - qd.screenBits.bounds.left) -
			useablewidth - VSBarWidth) / 2; */
		SetRect(&drawRect, qd.screenBits.bounds.left, qd.screenBits.bounds.top + 40,
			qd.screenBits.bounds.left + useablewidth + VSBarWidth, 
			qd.screenBits.bounds.top + useableheight + 40 +
				MouseDocumentHeight(MouseDocCount) + HSBarHeight) ;
		OffsetRect(&drawRect, 4, 0) ;	
#endif

#ifdef GGGDEBUG
		sprintf(MacWindowIDStr, "microExplorer-%03d/%03d", MacWindowID, ExpWindowID);
#else
		sprintf(MacWindowIDStr, "microExplorer-%03d", MacWindowID, ExpWindowID);
#endif

		macrec->myWindow = NewWindow(NULL, &drawRect, MacWindowIDStr, flags & FVISIBLE,
				       zoomDocProc, (Ptr)-1, TRUE, 0);
		if (macrec->myWindow == NULL)
		    return(-1) ;

		macrec->MouseDocCount = MouseDocCount ;

		SetPort(macrec->myWindow);

		(*((WStateData **)((WindowPeek)macrec->myWindow)->dataHandle))->stdState = drawRect ;

		UpdateUsableArea(macrec);
		macrec->ScrollOffset.h = macrec->ScrollOffset.v = 0;		

	    /* set up the scroll bar controls for this window */
		SetRect(&vScrollArea, macrec->myWindow->portRect.right - VSBarWidth + 1,
			macrec->myWindow->portRect.top - 1,
			macrec->myWindow->portRect.right + 1,
			macrec->myWindow->portRect.bottom - HSBarHeight + 1) ;
		SetRect(&hScrollArea, macrec->myWindow->portRect.right - HSBarSize,
			macrec->myWindow->portRect.bottom - HSBarHeight,
			macrec->myWindow->portRect.right - VSBarWidth + 1,
			macrec->myWindow->portRect.bottom + 1) ;

		GetClip(TempRgn);
		ClipRect(&qd.thePort->portRect);

#ifdef XXDEBUG
		if (debugFlag) {
		    dump2Rects("UsableArea", &macrec->UsableArea, "ClipRect", &(*TempRgn)->rgnBBox);
		    dump2Rects("vScrollArea", &vScrollArea, "hScrollArea", &hScrollArea);
		}
#endif

		macrec->vScroll = NewControl(macrec->myWindow, &vScrollArea, "", TRUE, 0, 0,
				       0, scrollBarProc, VertScrollBar);
		macrec->hScroll = NewControl(macrec->myWindow, &hScrollArea, "", TRUE, 0, 0,
				       0, scrollBarProc, HorzScrollBar);
	
		SetClip(TempRgn);

	    /*	The M-window's current scroll origin will be saved in 
			EWS_ctrl->MyWindows[M-WID]^.CurrentOrigin... */
		macrec->CurrentOrigin.v = macrec->CurrentOrigin.h = 0;

		sprintf(MacWindowIDStr, "%03d", MacWindowID);
		AddScreenMenuItem(macrec->myWindow, MacWindowIDStr);
		UpdateScreensMenu(macrec->myWindow);

		vMaxCtlValue = height - (macrec->UsableArea.bottom - macrec->UsableArea.top) ;
		hMaxCtlValue = width - (macrec->UsableArea.right - macrec->UsableArea.left) ;
		SetCtlMax(macrec->hScroll, hMaxCtlValue) ;
		SetCtlMax(macrec->vScroll, vMaxCtlValue) ;
    
    }

	/* Create the SavedBitMap and SavedGrafPort for the E-Screen. */
    AllocationFailure = ! AdjustAnyBitArray(ExpWindowID, width, height, 0) ;

    macrec->MacWindowsSavedBitMapsID = ExpWindowID;
	EWS_ctrl->AssociatedMacWindowID[ExpWindowID] = MacWindowID;

	/* if we are not rebuilding, must be creating/resizing */
    if (!AllocationFailure && !(flags & FREBUILDING)) {
	    /* Link the SavedBitMap/SavedGrafPort of the E-Screen to this M-window */
		SetWRefCon(macrec->myWindow, MacWindowID);	
		SetPort(macrec->myWindow) ;
		if (!createNew) {
	   		SizeWindow(macrec->myWindow, width + VSBarWidth,
				height + HSBarHeight + MouseDocumentHeight(macrec->MouseDocCount),
				TRUE) ;
	   		UpdateWinSize(macrec->myWindow) ;
		}
		drawRect = macrec->myWindow->portRect ;
		LocalToGlobal(&drawRect.top) ;
		LocalToGlobal(&drawRect.bottom) ;
		(*((WStateData **)((WindowPeek)macrec->myWindow)->dataHandle))->stdState = drawRect ;
    }

    MouseHold = FALSE;
    MouseWindow = macrec->myWindow;
    DriverData->lockedMouse.validp = FALSE;
    DriverData->lockedMouse.Pos.h = 0;
    DriverData->lockedMouse.Pos.v = 0;
    DriverData->lockedMouse.button = 0;
    DriverData->lockedMouse.ScreenID = swap_16b(MacWindowID);

    if (AllocationFailure)
		return(-1);

    if (firsttime) {
		HideWindow(gDebugWindowPtr) ;
		firsttime = FALSE ;
    }

    macrec->ignoreActivate = TRUE ;

	/* Set the E-window for Direct Drawing if not already and it's E-screen is Eligible */
	Direct_a_Windows_Drawing_To (ExpWindowID, ExpWindowID, 0, 0) ;
	/* EWS_ctrl->IDofOriginalSavedBitMapIndirectedTo[ExpWindowID] = ExpWindowID;
	if ((EWS_ctrl->SavedGrafPorts[ExpWindowID]->portBits.baseAddr != qd.screenBits.baseAddr) &&
			EligibleForToScreenDrawingP (MacWindowID))
	    ChangeEWindowFromSBMtoScreen (ExpWindowID, MacWindowID);
	*/

    return(MacWindowID);
}

static void
SelectExplorerWindow(cmd)
acb *cmd ;
{
    MacWindowRecPtr macrec ;

    copy_parms_32b(cmd, &MyParms, 0, 1, TO_ARRAY) ;
    set_input_complete(cmd, 1) ;
    if (MyParms.sel.SelectExplorerWindowID < 1 ||
					MyParms.sel.SelectExplorerWindowID > 255)
		return ;

    macrec = EWS_ctrl->MyWindows[abs(EWS_ctrl->
		AssociatedMacWindowID[MyParms.sel.SelectExplorerWindowID])] ;
    if (macrec == NULL || macrec->myWindow == NULL) {
#ifdef GGGDEBUG
		debugPrint2("Select: ATTEMPT TO SELECT BOGUS WINDOW %d AMWI=%d\n",
			MyParms.sel.SelectExplorerWindowID,
			EWS_ctrl->AssociatedMacWindowID[MyParms.sel.SelectExplorerWindowID]) ;
		debugDump () ;
#endif
		return ;
    }
#ifdef GGGDEBUG
    if (debugFlag) {
		debugPrint2 ("Select [%d] == %s\n", MyParms.sel.SelectExplorerWindowID,
			MyParms.sel.SelectVisibility ? "hide" : "show") ;
    }
#endif
    ShowHide(macrec->myWindow, MyParms.sel.SelectVisibility == 0) ;
    if (MyParms.sel.SelectVisibility == 0) {
		if (macrec->myWindow != FrontWindow ()) {
			UpdateSavedBitMapsFromScreen ();
			macrec->AwaitingAnUpdateEvent = TRUE ;
			SelectWindow(macrec->myWindow) ;
			ReestablishToScreenDrawing();
		}
		MouseHold = FALSE;
		MouseWindow = macrec->myWindow ;
    }
}


CalcMaxSize(bounds, maxwidth, maxheight)
Rect *bounds ;
int *maxwidth, *maxheight ;
{
#ifdef NOTYET		/* for full screen width windows */
    *maxwidth = (bounds->right - bounds->left) ;
#else
	/* round to 32 pixel boundary */
    *maxwidth = ((bounds->right - bounds->left) - 8) & ~31 ;
#endif
    *maxheight = (bounds->bottom - bounds->top) - 20 - 20 - HSBarHeight - 1 ;
}

InitTVStuff()
{
    register int i ;
    register MacWindowRecPtr macrec ;
    extern Rect dragRect;
    extern VBLTask TvVblTask;
    extern TvVbl();
    FontInfo finfo ;
    GrafPtr oldPort ;
    GrafPort tempPort ;
	
    TvVblTask.qType = vType;
    TvVblTask.vblAddr = TvVbl;
    TvVblTask.vblCount = 2;
    TvVblTask.vblPhase = 0;
    setupTvVbl(&TvVblTask);

	/* init current cursor to the arrow */
    currentCursor = qd.arrow ;

	/* Initialize the Circular Buffer for debug history if enabled */
	InitializeDebugBuffer () ;

	/*Initialize the BitArrayPool. This is an array used to keep track of how bitArrays
	 are allocated in the BitArray area. The bitArray area is a section of the heap which we
	 manage ourselves to prevent the heap from becoming too fragmented. */

    BitArrayPoolAreaSize = (long)GetApplLimit() - (long)ApplicZone() - NonBitArrayHeap;
    BitArrayPoolAreaPtr = (struct BitArrayRec *)NewPtr(BitArrayPoolAreaSize);
#ifdef GGGDEBUG
    debugPrint2 ("BitArrayPool  Base = x%08x  Size = %d\n", BitArrayPoolAreaPtr, BitArrayPoolAreaSize) ;
#endif
    if (BitArrayPoolAreaPtr == NULL || MemError() != noErr) {
		PrtErrorMsg(211) ;	/* BitArrayPool allocation failed. */
		return(-1) ;
    }
	
	for (i = 0; i < BitArrayPoolAreaSize; i++) {
		BitArrayPoolAreaPtr[i] = (Ptr)0 ;
	}

    for (i = 0; i < MaxResidentBitArrays; i++) {
		BitArrayPool[i].start = NULL;
		BitArrayPool[i].length = 0;
    }

    SetFScaleDisable(FALSE) ;


    SetRect(&dragRect, 2, 20,
		 qd.screenBits.bounds.right - 2, qd.screenBits.bounds.bottom - 2) ;


	/* a bogus port that we can do things with, like offscreen copybits. keeps black screen bug away */
    OpenPort(&miscPort) ;


    CalcMaxSize(&qd.screenBits.bounds, &MaxWindowWidth, &MaxWindowHeight) ;

#ifndef MAC
	/* reserve room for bitblts */
    BitArrayPtr = NewPtr(0x18000) ;
    if (BitArrayPtr == NULL) {
		PrtErrorMsg(212) ;	/* Memory allocation failed in TV initializations */
	return -1;
    	}
#endif

    if ((TempRgn = NewRgn()) == NULL) {
		PrtErrorMsg(212) ;	/* Memory allocation failed in TV initializations */
		return(-1) ;
    }
    if ((CRgn = NewRgn()) == NULL)  {
		PrtErrorMsg(212) ;	/* Memory allocation failed in TV initializations */
		return(-1) ;
    }
    if ((BRgn = NewRgn()) == NULL)  {
		PrtErrorMsg(212) ;	/* Memory allocation failed in TV initializations */
		return(-1) ;
    }
	
	/* Initialize arrays indexed by font ID, by E-window ID, or by E-screen ID. */
	/*		The initial values are mostly safe.  One is not.  Giving each 		*/
	/*		E-window a save-array of the entire screen makes indirection to or	*/
	/*		use of an uninitialized E-window a very obvious bug -- the menu bar	*/
	/*		either gets destroyed by an E-window's image or it gets copied into	*/
	/*		an E-window's image.												*/
	
	EWS_ctrl = (EWS_ctrl_struct *)NewPtr(sizeof(EWS_ctrl_struct));
	if (EWS_ctrl == NULL)  {
		PrtErrorMsg(212) ;	/* Memory allocation failed in TV initializations */
		return(-1) ;
    }
		
    for (i=0; i < 256; i++) {
		EWS_ctrl->CachedFontInfo[i].FontSize = 0 ;	/* Ith font has no cached image */
		EWS_ctrl->MyWindows[i+1] = NULL ;			/* Ith E-screen has no Mac window */
		EWS_ctrl->SavedBitMaps[i] = qd.screenBits ;	/* Ith E-window save-array = Mac screen */
		EWS_ctrl->SavedGrafPorts[i] = NULL ;		/* Ith E-window has no grafPort */
		EWS_ctrl->AssociatedMacWindowID[i] = 0 ;	/* Ith E-window is not visible */
		EWS_ctrl->IDofOriginalSavedBitMapIndirectedTo[i] = i;	
													/* Ith E-window indirects to itself */
    }

    for (i=0; i <= MaxScreenMenuItems; i++)
		ScreensMenu[i].window = NULL ;
		
	/*	Manually put a pointer to the debug window into ScreensMenu[1].window so all
		these items will have pointers to the windows they name.  */
	ScreensMenu[1].window = gDebugWindowPtr ;


	/* determine size of mouse documentation area */
    GetPort(&oldPort) ;
    SetPort(&miscPort) ;
    TextFont(MouseDocFont) ;
    TextSize(MouseDocFontSize) ;

    GetFontInfo(&finfo) ;
    MouseDocCharHeight = (finfo.leading + finfo.ascent + finfo.descent) ;

    TextFont(monaco) ;
    TextSize(9) ;
    GetFontInfo(&finfo) ;
    WhoStateSize = finfo.widMax * 20 + 4 ;

    SetPort(oldPort) ;

	/* create a "safe" M-window descriptor for M-Window-ID zero */
    macrec = EWS_ctrl->MyWindows[0] = (MacWindowRecPtr)NewPtr(sizeof(MacWindowRec)) ;
    if (macrec == NULL)  {
	PrtErrorMsg(212) ;	/* Memory allocation failed in TV initializations */
	return(-1) ;
    }

    macrec->myWindow = NULL ;
    macrec->UsableArea.left = macrec->UsableArea.right = 0 ;
    macrec->UsableArea.top = macrec->UsableArea.bottom = 0 ;
    macrec->ScrollOffset.v = macrec->ScrollOffset.h = 0 ;
    macrec->vScroll = macrec->hScroll = NULL ;
    macrec->MacWindowsSavedBitMapsID = -1 ;
    macrec->CurrentOrigin.v = macrec->CurrentOrigin.h = 0 ;
    return(noErr) ;
}

/*
    AdjustScreenSize:
	Parm1 = Mac Window ID / Explorer Screen ID
  	Parm2 = Explorer Window ID
	Parm3 = width
	Parm4 = height
	...if width == height == 0 then destroy the /E-window data structures
	returns: success in Parm1, success is positive if successful and -1 if not
*/

static void
AdjustScreenSize(cmd)
acb *cmd ;
{
    short success ;
    MacWindowRecPtr macrecp ;

    copy_parms_32b(cmd, &MyParms, 0, 3, TO_ARRAY) ;
    set_input_complete(cmd, 1) ;

#ifdef GGGDEBUG
    if (debugFlag) {
		debugPrint5 ("AdjScrSize: [%d]  Wid=%d  w=%d  h=%d  vis=x%x\n",
			MyParms.ass.AdjustExplorerScreenID,
			MyParms.ass.AdjustExplorerWindowID,
			MyParms.ass.AdjustScreenWidth,
			MyParms.ass.AdjustScreenHeight,
			MyParms.ass.AdjustVisibility) ;
	}
#endif

	/* this little kludge allows us to do all sorts of nifty things on the
	   explorer side to guard against creating too many screens / windows */
    if (MyParms.ass.AdjustVisibility & FCHECKSIZE) {
		set_parm_32b(cmd, 0, BitArrayPoolAreaSize) ;
		return ;
    }

	/* Because either destroying or creating a new E-screen/M-window may
	   change the eligibility of existing M-windows for Direct Drawing, we
	   must save/restore all M-windows' screen images before/after the 
	   following code */
    UpdateSavedBitMapsFromScreen ();

	/* 0,0 is a special case sent to destroy the mac window */
    if (MyParms.ass.AdjustExplorerScreenID != 0 &&
    	MyParms.ass.AdjustScreenWidth == 0 &&
		MyParms.ass.AdjustScreenHeight == 0) {
#ifdef GGGDEBUG
		debugPrint2("Destroying Screen %d/%d\n", 
			MyParms.ass.AdjustExplorerScreenID, MyParms.ass.AdjustExplorerWindowID) ;
#endif
		SetPort(&miscPort) ;
		/* Destroy E-window's SavedGrafPort, if it has one */
		if (EWS_ctrl->SavedGrafPorts[MyParms.ass.AdjustExplorerWindowID] != NULL) {
		    ClosePort(EWS_ctrl->SavedGrafPorts[MyParms.ass.AdjustExplorerWindowID]) ;
		    DisposPtr((Ptr)EWS_ctrl->SavedGrafPorts[MyParms.ass.AdjustExplorerWindowID]) ;
		    EWS_ctrl->SavedGrafPorts[MyParms.ass.AdjustExplorerWindowID] = NULL ;
		}
		/* Destroy the E-window's SavedBitMap */
		FreeBitMap(EWS_ctrl->SavedBitMaps[MyParms.ass.AdjustExplorerWindowID].baseAddr) ;
		EWS_ctrl->SavedBitMaps[MyParms.ass.AdjustExplorerWindowID] = qd.screenBits ;
		EWS_ctrl->AssociatedMacWindowID[MyParms.ass.AdjustExplorerWindowID] = 0 ;
		success = 1 ;
		if (UpdateRec.UpdateP) {
		    if (MyParms.ass.AdjustExplorerWindowID == UpdateRec.ExplorerWindowID)
				UpdateRec.UpdateP = FALSE ;
		}
		macrecp = EWS_ctrl->MyWindows[MyParms.ass.AdjustExplorerScreenID] ;
		if (macrecp) {
		    EWS_ctrl->MyWindows[MyParms.ass.AdjustExplorerScreenID] = NULL ;
		    if (macrecp->myWindow) {
				if (macrecp->myWindow == MouseWindow)
			    	MouseWindow = NULL ;
				RemoveScreenMenuItem(macrecp->myWindow);
				DisposeWindow(macrecp->myWindow);
	 	  	}
	   		DisposPtr(macrecp) ;
		}
#ifdef GGGDEBUG
		debugPrint1("Screen %d Dead\n", MyParms.ass.AdjustExplorerScreenID) ;
#endif
    } else {
		if (MyParms.ass.AdjustExplorerScreenID == PRINTER_ID) {
			/* ab 9/20/88.  Special case for printer -- no associated mac window */
			EWS_ctrl->AssociatedMacWindowID[MyParms.ass.AdjustExplorerScreenID] = 0; 
			success =  0;
		} else {
			success = CreateMacWindow(MyParms.ass.AdjustExplorerScreenID,
				MyParms.ass.AdjustExplorerWindowID, MyParms.ass.AdjustScreenWidth,
				MyParms.ass.AdjustScreenHeight, MyParms.ass.AdjustVisibility) ;
		}
    }
	ReestablishToScreenDrawing();
    set_parm_16b(cmd, 0, success) ;
}

/*
   {Creates a bitarray for a LispM window or adjusts its size if it already exists.
    Also changes the size of the LispM window's grafPort to agree.}
   {returns: success in Parm1, success is 1 if successful and -1 if not}
   {When width<=0 then the window has no bit map and is not to be given a bit map, just
    adjust the size of the window's graphPort.} */
static void
AdjustBitArray(cmd)
acb *cmd ;
{
    short success ;

    copy_parms_32b(cmd, &MyParms, 0, 2, TO_ARRAY) ;
    set_input_complete(cmd, 1) ;

#ifdef GGGDEBUG
    if (debugFlag) {
	debugPrint4 ("AdjustBitArray: [%d]  w=%d  h=%d  save=%d\n",
		MyParms.aba.AdjustBitArrayExplorerWindowID,
		MyParms.aba.AdjustBitArrayWidth, MyParms.aba.AdjustBitArrayHeight,
		MyParms.aba.AdjustBitArrayContentsMatter) ;
    }
#endif

    if (AdjustAnyBitArray(MyParms.aba.AdjustBitArrayExplorerWindowID,
						  MyParms.aba.AdjustBitArrayWidth, 
						  MyParms.aba.AdjustBitArrayHeight,
						  MyParms.aba.AdjustBitArrayContentsMatter))
		success = 1 ;
    else
		success = 0 ;

    set_parm_16b(cmd, 0, success) ;
}


/*
  {Parm1 = Explorer window ID of window being indirected, never an E-screen's Wid}
  {Parm2 = Explorer window ID of window being redirected to}
  {Parm3 = x position of where 1st window is within the recipient window}
  {Parm4 = y position of where 1st window is within the recipient window}
*/
static void
RedirectDrawing(cmd)
acb *cmd ;
{

    copy_parms_32b(cmd, &MyParms, 0, 2, TO_ARRAY) ;
    set_input_complete(cmd, 1) ;
	
	Direct_a_Windows_Drawing_To (MyParms.red.FromExplorerWindowID, MyParms.red.ToExplorerWindowID,
			MyParms.red.ToWindowPosition.h, MyParms.red.ToWindowPosition.v) ;
}


/* Parm1 = Explorer window ID to be deallocated */
static void
DeallocateBitArray(cmd)
acb *cmd ;
{
    register 	ExplorerWindowID ;
    int 		i, S;

    copy_parms_32b(cmd, &MyParms, 0, 2, TO_ARRAY) ;
    set_input_complete(cmd, 1) ;

    ExplorerWindowID = MyParms.dea.DeallocateExplorerWindowID ;
	S = EWS_ctrl->AssociatedMacWindowID[ExplorerWindowID] ;

	/* ab 9-20-88 */
	if (ExplorerWindowID == PRINTER_ID) {
#ifdef ABDEBUG
        printw("Redirect called on PRINTER\n");
#endif
		return ;
	}
	
    SetPort(&miscPort) ;
	
	if (MaxUsedWid == ExplorerWindowID)
		MaxUsedWid -= 1 ;

#ifdef GGGDEBUG
    if (debugFlag) {
		debugPrint4 ("Deallocate: wID= %d(%d)  SGP= x%08x  SGPbA= x%08x\n", 
			ExplorerWindowID, MaxUsedWid,
			EWS_ctrl->SavedGrafPorts[ExplorerWindowID],
			EWS_ctrl->SavedBitMaps[ExplorerWindowID].baseAddr) ;
    }
#endif
    if (EWS_ctrl->SavedGrafPorts[ExplorerWindowID] != NULL) {
		ClosePort(EWS_ctrl->SavedGrafPorts[ExplorerWindowID]) ;
		DisposPtr((Ptr)EWS_ctrl->SavedGrafPorts[ExplorerWindowID]) ;
    }

    FreeBitMap(EWS_ctrl->SavedBitMaps[ExplorerWindowID].baseAddr) ;

    EWS_ctrl->SavedGrafPorts[ExplorerWindowID] = NULL ;
    EWS_ctrl->SavedBitMaps[ExplorerWindowID] = qd.screenBits ;
    EWS_ctrl->AssociatedMacWindowID[ExplorerWindowID] = 0 ;
	EWS_ctrl->IDofOriginalSavedBitMapIndirectedTo[ExplorerWindowID] = ExplorerWindowID;
	
	/*  If this is a screen's window, mark the screen as unusable */
	if (S > 0) {
		EWS_ctrl->MyWindows[S]->SavedBitMapIsCurrent = FALSE ;
		EWS_ctrl->MyWindows[S]->MacWindowsSavedBitMapsID = -1 ;
	}
	
}

FreeBitMap(baseAddr)
Ptr baseAddr ;
{
    register int i ;
	register Ptr j ;
    Boolean NotEmpty = FALSE ;
	Boolean Success = FALSE ;

    if (baseAddr == qd.screenBits.baseAddr)
		return ;

    for (i = 0; i<= MaxUsedBAid; i++) {
		if (BitArrayPool[i].start == baseAddr) {
			/* Clear it */
			for (j = baseAddr; j < baseAddr + BitArrayPool[i].length; j++) {
				*j = 0 ;
			}
	    	BitArrayPool[i].start = NULL;	/* Deallocate it */
			/* if we are releasing the one on the end, just make it contiguous */
	    	if (i + 1 < MaxResidentBitArrays) {
				if (BitArrayPool[i+1].length == 0) {
		   			BitArrayPool[i].length = 0 ;
					MaxUsedBAid -= 1 ;
				}
	    	} else {
				BitArrayPool[i].length = 0 ;
			}
#ifdef GGGDEBUG
	    	if (debugFlag) {
				debugPrint3 ("FreeBitMap %d(%d)  x%08x\n", i, MaxUsedBAid, baseAddr) ;
				Success = TRUE ;
	    	}
		} else {
			if (debugFlag && !Success  && (BitArrayPool[i].start > baseAddr))
				debugPrint4 ("FreeBitMap failed.  Slot %d(%d)'s startadr %08x > inputadr %08x.\n",
					i, MaxUsedBAid, BitArrayPool[i].start, baseAddr) ;
#endif GGGDEBUG
		}
		NotEmpty = (NotEmpty || (BitArrayPool[i].start != NULL));
    }
			
    if (!NotEmpty) {		 /* If BitArrayPool is empty then reinitialize it */
		for (i = 0; i <= MaxUsedBAid; i++) {
	    	BitArrayPool[i].start = NULL;
	    	BitArrayPool[i].length = 0;
		}
#ifdef GGGDEBUG
		if (debugFlag) {
	    	debugPrint1("BitArrayPool flushed (Max =%d)\n", MaxUsedBAid) ;
		}
#endif GGGDEBUG
		MaxUsedBAid = -1 ;
    }
}
  
/*
	{Retreives the font width table.}
  	{Parm1 = font}
	{Parm2 = font style}
	{Parm3 = font size} */

static void
rFontMetrics(cmd)
acb *cmd ;
{
    FMetricRec aFMrec ;
    Handle tHandle ;
    Style newFace ;
    GrafPtr oldPort ;
    GrafPort tempPort ;
    FMInput FMInputRec ;


    copy_parms_32b(cmd, &MyParms, 0, 2, TO_ARRAY) ;
#ifdef XXDEBUG
    if (debugFlag) {
		debugPrint3("rFontMetrics %d %d %d\n", MyParms.fm.FontMetricsStyle,
		 	MyParms.fm.FontMetricsFont, MyParms.fm.FontMetricsSize) ;
    }
#endif

    GetPort(&oldPort) ;
    SetPort(&miscPort) ;
    TextFont(MyParms.fm.FontMetricsFont) ;
    TextFace((Style)MyParms.fm.FontMetricsStyle) ;
    TextSize(MyParms.fm.FontMetricsSize) ;

    FMInputRec.family = MyParms.fm.FontMetricsFont ;
    FMInputRec.size = MyParms.fm.FontMetricsSize ;
    FMInputRec.face = (Style)MyParms.fm.FontMetricsStyle ;
    FMInputRec.needBits = FALSE ;
    FMInputRec.device = 0 ;
    FMInputRec.numer.v = 1 ;
    FMInputRec.numer.h = 1 ;
    FMInputRec.denom.v = 1 ;
    FMInputRec.denom.h = 1 ;
    FMSwapFont(&FMInputRec) ;

    FontMetrics(&aFMrec) ;
    copy_parms_16b(cmd, &aFMrec, 0, 8, TO_ACB) ;
    tHandle = (Handle)aFMrec.wTabHandle ;
    copy_parms_16b(cmd, *tHandle, 8, 512, TO_ACB) ;
    copy_parms_16b(cmd, (char *)*tHandle + 1060, 520, 5, TO_ACB) ;

    SetPort(oldPort) ;
}

/* ab 9/20/88 Remove STATIC declaration */
void
setPortFonts(port, Font, FontStyle, FontSize)
GrafPtr port ;
int Font, FontStyle, FontSize ;
{
    if (Font != port->txFont)
		TextFont(Font) ;
    if ((Style)FontStyle != port->txFace)
		TextFace((Style)FontStyle) ;
    if (FontSize != port->txSize)
		TextSize(FontSize) ;
}


static void
InvalidateScreenRect(WindowID, modRect)
int WindowID ;
Rect *modRect ;
{
#ifdef GGGDEBUG
	if (debugFlag) {
		debugPrint1("Invalidate W= %d\n", WindowID);
		if ((modRect->right - modRect->left) != 7)
			dump1Rect("modRect", modRect);
	}
#endif GGGDEBUG
    if (UpdateRec.UpdateP) {
		if (UpdateRec.ExplorerWindowID == WindowID) {
	    	UnionRect(&UpdateRec.InvalidRect, modRect, &UpdateRec.InvalidRect) ;
#ifdef GGGDEBUG
			if (debugFlag) {
				dump1Rect ("UnionRect", &UpdateRec.InvalidRect);
			}
#endif GGGDEBUG
		} else {
	    	short oldInhibit = UpdateRec.ScreenUpdatesInhibited;
			UpdateRec.ScreenUpdatesInhibited = FALSE;
	    	UpdateScreen() ;
			UpdateRec.ScreenUpdatesInhibited = oldInhibit;
	    	UpdateRec.InvalidRect = *modRect ;
	    	UpdateRec.ExplorerWindowID = WindowID ;
	    	UpdateRec.UpdateP = TRUE ;
		}
    } else {
		UpdateRec.InvalidRect = *modRect ;
		UpdateRec.ExplorerWindowID = WindowID ;
		UpdateRec.UpdateP = TRUE ;
    }
}

UpdateScreen()
{
    Rect dstRect ;
    MacWindowRecPtr macrec ;

    if (UpdateRec.ExplorerWindowID == PRINTER_ID) {
#ifdef ABDEBUG
        printf("UpdateScreen called on printer window: illegal\n");
#endif
        return (FALSE);
    }
    if (UpdateRec.UpdateP && !UpdateRec.ScreenUpdatesInhibited) {
	macrec = EWS_ctrl->MyWindows[abs(EWS_ctrl->AssociatedMacWindowID
			[UpdateRec.ExplorerWindowID])] ;
	if (macrec && macrec->myWindow) {
		/* Convert from E-window's coords to E-screen's coords.  The 		*/
		/* E-screen's (0,0) point aligns with the M-window's (0,0) point, 	*/
		/* so no conversion	is needed to go from the E-screen's coordinate 	*/
		/* system to the M-window's coordinate system.						*/
	     OffsetRect(&UpdateRec.InvalidRect,
			-EWS_ctrl->SavedGrafPorts[UpdateRec.ExplorerWindowID]->portBits.bounds.left,
			-EWS_ctrl->SavedGrafPorts[UpdateRec.ExplorerWindowID]->portBits.bounds.top) ;
		/* Adjust destination rectangle for any scrolling of the M-window. 	*/
	    dstRect = UpdateRec.InvalidRect ;
	    OffsetRect(&dstRect, -macrec->ScrollOffset.h, -macrec->ScrollOffset.v) ;
		/* Copy from the E-screen's SBM to the M-window's portBits.			*/
	    SetPort(macrec->myWindow) ;
		RectRgn (TempRgn, &macrec->UsableArea) ;
	    CopyBits(&EWS_ctrl->SavedBitMaps[macrec->MacWindowsSavedBitMapsID],
			&macrec->myWindow->portBits, &UpdateRec.InvalidRect, &dstRect,
			srcCopy, TempRgn) ;
			
#ifdef GGGDEBUG
		if (debugFlag) {
			debugPrint2 ("UpdateScreen: wID/sID= %d/%d\n", 
				UpdateRec.ExplorerWindowID,
				EWS_ctrl->AssociatedMacWindowID[UpdateRec.ExplorerWindowID]);
			if ((dstRect.right - dstRect.left) != 7) {
				dumpPort("UpdateScreen - SGP", 
					EWS_ctrl->SavedGrafPorts[UpdateRec.ExplorerWindowID]);
				dumpCopyBitsCall(&EWS_ctrl->SavedBitMaps[macrec->MacWindowsSavedBitMapsID],
					&macrec->myWindow->portBits, &UpdateRec.InvalidRect, &dstRect,
					srcCopy, TempRgn) ;
			}
		}
#endif GGGDEBUG

	    UpdateRec.UpdateP = FALSE ;
	}
    }
}


/*
  {Three kinds of bitblts are handled here - Mac to Mac, Explorer to Mac, Mac to Explorer} 
  	{Parm1 = type of array}
	{Parm2 = transfer mode}
	{Parm3 = width in bits}
	{Parm4 = height}
	{Parm5 = -1 if from Explorer, else ExpWindowID of source SavedBitMap.}
	{Parm6 = -1 if to Explorer, else ExpWindowID of destination SavedBitMap.}
	{Parm7,Parm8 = (x,y) of first source pixel.}
	{Parm9,Parm10 = (x,y) of first destination pixel.}
*/

static void
rCopyBits(cmd)		/* This code is never used anymore. */
acb *cmd ;
{
#ifdef GGGDEBUG
	debugPrint0("rCopyBits called...this is an error\n") ;
#endif GGGDEBUG
}

static void
rNewCopyBits(cmd)
acb *cmd ;
{
    BitMap tBitMap ;
    long rowlength ;
    Rect tRect ;
    Rect aRect ;
    long arraylength ;
    BitMap SourceBM ;
    BitMap DestBM ;
    GrafPtr oldPort ;
    register short x, y ;

    copy_parms_32b(cmd, &MyParms, 0, 7, TO_ARRAY) ;
	UpdateRec.ScreenUpdatesInhibited = FALSE;
	
	/* CopyBits seems to have some severe dependencies on what the curent port is 		*/
	/*  In order for CopyBits to clip to the visRgn we must make sure thePort is our	*/
	/*  destination GrafPort.															*/
    GetPort(&oldPort) ;
	if (MyParms.blt.CopyDestinationID < 0)
		SetPort (&miscPort) ;
	else
	    SetPort(EWS_ctrl->SavedGrafPorts[MyParms.blt.CopyDestinationID]) ;

#ifdef GGGDEBUG
	if (debugFlag) {
	    debugPrint(8, "CopyBits %s[%d/%d]->%s[%d/%d]  UpDatesInhibited= %d  thePort= x%08x\n", 
			MyParms.blt.CopySourceID < 0 ? "exp" : "mac",
			MyParms.blt.CopySourceID,
			MyParms.blt.CopySourceID < 0 ? 0 : 
				EWS_ctrl->AssociatedMacWindowID[MyParms.blt.CopySourceID],
			MyParms.blt.CopyDestinationID < 0 ? "exp" : "mac",
			MyParms.blt.CopyDestinationID,
			MyParms.blt.CopyDestinationID < 0 ? 0 : 
				EWS_ctrl->AssociatedMacWindowID[MyParms.blt.CopyDestinationID],
			MyParms.blt.CopyScreenUpdatesInhibited,
			qd.thePort) ;
			
	}
#endif

    if (MyParms.blt.CopySourceID < 0) {		
	
	/* >>>>>>>>>>   From explorer to Mac    <<<<<<<<<< */
	
	rowlength = (MyParms.blt.CopySourceWidth + 31) >> 5 ;	/* / 32 */
	arraylength = 4 * rowlength * MyParms.blt.CopySourceHeight ;
	tBitMap.rowBytes = 4 * rowlength ;
#ifdef MAC
	tBitMap.baseAddr = (Ptr)((char *)cmd + sizeof(struct acb_header) + 28); 
	  /*sizeof(struct acbheader)+sizeof(MyParms.blt)) ;*/
#else
	copy_parms_8b(cmd, BitArrayPtr, sizeof(MyParms.blt), arraylength, TO_ARRAY) ;
	tBitMap.baseAddr = BitArrayPtr ;
#endif
	SetRect(&tBitMap.bounds, 0, 0, MyParms.blt.CopySourceWidth, MyParms.blt.CopySourceHeight) ;
	BitSwap(tBitMap.baseAddr, tBitMap.baseAddr, arraylength) ;
	SetRect(&tRect, MyParms.blt.CopyDestination.h, MyParms.blt.CopyDestination.v, 
			MyParms.blt.CopyWidth + MyParms.blt.CopyDestination.h,
			MyParms.blt.CopyHeight + MyParms.blt.CopyDestination.v) ;

	/* ab 9/2/88 */
	if ( MyParms.blt.CopyDestinationID == PRINTER_ID && EWS_ctrl->SavedGrafPorts[PRINTER_ID] ) {
	    SetPort(EWS_ctrl->SavedGrafPorts[PRINTER_ID]);
	    DestBM = EWS_ctrl->SavedGrafPorts[PRINTER_ID]->portBits;
#ifdef ABDEBUG
        debugPrint(5, "CopyBits Exp to MAC %s[%d]->%s[%d]  UpDatesInhibited= %d\n", 
            MyParms.blt.CopySourceID < 0 ? "exp" : "mac",
            MyParms.blt.CopySourceID,
            MyParms.blt.CopyDestinationID < 0 ? "exp" : "mac",
            MyParms.blt.CopyDestinationID,
            MyParms.blt.CopyScreenUpdatesInhibited) ;
#endif
	} else {
		if (EWS_ctrl->AssociatedMacWindowID[MyParms.blt.CopyDestinationID] > 0)
			DestBM = EWS_ctrl->SavedGrafPorts[MyParms.blt.CopyDestinationID]->portBits ;
		else {
			DestBM = EWS_ctrl->SavedBitMaps[MyParms.blt.CopyDestinationID] ;
#ifdef GGGDEBUG
			if (DestBM == qd.screenBits) {
			   	debugPrint (6, "CopyBits %s[%d/%d]->%s[%d/%d] TO SBM == SCREENBITS!!!\n", 
					MyParms.blt.CopySourceID < 0 ? "exp" : "mac",
					MyParms.blt.CopySourceID,
					MyParms.blt.CopySourceID < 0 ? 0 : 
						EWS_ctrl->AssociatedMacWindowID[MyParms.blt.CopySourceID],
					MyParms.blt.CopyDestinationID < 0 ? "exp" : "mac",
					MyParms.blt.CopyDestinationID,
					MyParms.blt.CopyDestinationID < 0 ? 0 : 
						EWS_ctrl->AssociatedMacWindowID[MyParms.blt.CopyDestinationID]) ;
				debugDump () ;
			}
#endif GGGDEBUG
		}
	}

#ifdef GGGDEBUG
	if (debugFlag) {
	    debugPrint (7, " src = Exp[%dx%d]  w=%d  h=%d  dest=x%08x(%d,%d)\n",
	    	MyParms.blt.CopySourceWidth, MyParms.blt.CopySourceHeight,
			MyParms.blt.CopyWidth, MyParms.blt.CopyHeight, 
			DestBM.baseAddr, MyParms.blt.CopyDestination.h, MyParms.blt.CopyDestination.v) ;
	}
#endif

	if (MyParms.blt.CopySourceWidth < MyParms.blt.CopyWidth ||
						MyParms.blt.CopySourceHeight < MyParms.blt.CopyHeight) {
	    SetRect(&aRect, MyParms.blt.CopySource.h, MyParms.blt.CopySource.v,
			MyParms.blt.CopySource.h + MyParms.blt.CopySourceWidth,
			MyParms.blt.CopySource.v + MyParms.blt.CopySourceHeight) ;
	    rPatternFill(&tBitMap, &DestBM, &aRect, &tRect, MyParms.blt.CopyMode) ;
	} else {
	    SetRect(&aRect, 0, 0, MyParms.blt.CopyWidth, MyParms.blt.CopyHeight) ;
	    CopyBits(&tBitMap, &DestBM, &aRect, &tRect, MyParms.blt.CopyMode, NULL) ;
#ifdef GGGDEBUG
		if (debugFlag) {
			dumpCopyBitsCall (&tBitMap, &DestBM, &aRect, &tRect, MyParms.blt.CopyMode, NULL) ;
		}
#endif
	}
	set_input_complete(cmd, 1) ;
	if ((EWS_ctrl->AssociatedMacWindowID[MyParms.blt.CopyDestinationID] > 0 ) &&
			OnScreenP(MyParms.blt.CopyDestinationID)) {
		UpdateRec.ScreenUpdatesInhibited = MyParms.blt.CopyScreenUpdatesInhibited;
	    InvalidateScreenRect(MyParms.blt.CopyDestinationID, &tRect) ;
	}
    } else if (MyParms.blt.CopyDestinationID < 0) {	
	
	/* >>>>>>>>>>   from mac to explorer   <<<<<<<<<< */
	
	rowlength = (MyParms.blt.CopyWidth + 31) >> 5 ;	/* / 32 */
	arraylength = 4 * rowlength * MyParms.blt.CopyHeight ;
	tBitMap.rowBytes = 4 * rowlength ;

	SetRect(&tRect, MyParms.blt.CopySource.h, MyParms.blt.CopySource.v,
		MyParms.blt.CopySourceWidth + MyParms.blt.CopySource.h,
		MyParms.blt.CopySourceHeight + MyParms.blt.CopySource.v) ;

	/* ab 9/20/88 */
	if ((EWS_ctrl->AssociatedMacWindowID[MyParms.blt.CopySourceID] > 0) ||
			(MyParms.blt.CopySourceID == PRINTER_ID)) {
		SourceBM = EWS_ctrl->SavedGrafPorts[MyParms.blt.CopySourceID]->portBits ;
#ifdef ABDEBUG
        if (MyParms.blt.CopySourceID == PRINTER_ID) {
            printw("CopyBits MAC to Exp %s[%d]->%s[%d]  UpDatesInhibited= %d\n", 
                MyParms.blt.CopySourceID < 0 ? "exp" : "mac",
                MyParms.blt.CopySourceID,
                MyParms.blt.CopyDestinationID < 0 ? "exp" : "mac",
                MyParms.blt.CopyDestinationID,
                MyParms.blt.CopyScreenUpdatesInhibited) ; }
#endif
 	} else {
		SourceBM = EWS_ctrl->SavedBitMaps[MyParms.blt.CopySourceID] ;
#ifdef GGGDEBUG
		if (SourceBM == qd.screenBits) {
		   	debugPrint (6, "CopyBits %s[%d/%d]->%s[%d/%d] FROM SBM == SCREENBITS!!!\n", 
				MyParms.blt.CopySourceID < 0 ? "exp" : "mac",
				MyParms.blt.CopySourceID,
				MyParms.blt.CopySourceID < 0 ? 0 : 
					EWS_ctrl->AssociatedMacWindowID[MyParms.blt.CopySourceID],
				MyParms.blt.CopyDestinationID < 0 ? "exp" : "mac",
				MyParms.blt.CopyDestinationID,
				MyParms.blt.CopyDestinationID < 0 ? 0 : 
					EWS_ctrl->AssociatedMacWindowID[MyParms.blt.CopyDestinationID]) ;
			debugDump () ;
		}
#endif GGGDEBUG
	}
		
#ifdef GGGDEBUG
	if (debugFlag) {
	    debugPrint5 (" w=%d  h=%d  src=x%08x[%d,%d]\n",
			MyParms.blt.CopyWidth, MyParms.blt.CopyHeight, 
			SourceBM.baseAddr, MyParms.blt.CopySource.h, MyParms.blt.CopySource.v) ;
	}
#endif

#ifdef MAC
	tBitMap.baseAddr = (Ptr)((char *)cmd + sizeof(struct acb_header) + 28);
	/*sizeof(struct acbheader) + sizeof(MyParms.blt)) ;*/
#else
	tBitMap.baseAddr = BitArrayPtr ;
#endif
	SetRect(&tBitMap.bounds, 0, 0, MyParms.blt.CopyWidth, MyParms.blt.CopyHeight) ;
	CopyBits(&SourceBM, &tBitMap, &tRect, &tBitMap.bounds, MyParms.blt.CopyMode, NULL) ;
#ifdef GGGDEBUG
	if (debugFlag) {
		dumpCopyBitsCall(&SourceBM, &tBitMap, &tRect, &tBitMap.bounds, 
			MyParms.blt.CopyMode, NULL) ;
	}
#endif GGGDEBUG
	BitSwap(tBitMap.baseAddr, tBitMap.baseAddr, arraylength) ;
#ifndef MAC
	copy_parms_8b(cmd, BitArrayPtr, sizeof(MyParms.blt), arraylength, TO_ACB) ;
#endif
    } else {		
	
	/* >>>>>>>>>>   from mac to mac   <<<<<<<<<< */
	
	set_input_complete(cmd, 1) ;
	SetRect(&tRect, MyParms.blt.CopySource.h, MyParms.blt.CopySource.v,
		MyParms.blt.CopySourceWidth + MyParms.blt.CopySource.h,
		MyParms.blt.CopySourceHeight + MyParms.blt.CopySource.v) ;
	SetRect(&aRect, MyParms.blt.CopyDestination.h,
		MyParms.blt.CopyDestination.v, MyParms.blt.CopyWidth +
		MyParms.blt.CopyDestination.h, MyParms.blt.CopyHeight +
		MyParms.blt.CopyDestination.v) ;
		
	if ((EWS_ctrl->AssociatedMacWindowID[MyParms.blt.CopySourceID] > 0) ||
			(MyParms.blt.CopySourceID == PRINTER_ID)) {
		SourceBM = EWS_ctrl->SavedGrafPorts[MyParms.blt.CopySourceID]->portBits ;
#ifdef ABDEBUG
        if (MyParms.blt.CopySourceID == PRINTER_ID) {
            printw("CopyBits MAC to MAC %s[%d]->%s[%d]  UpDatesInhibited= %d\n", 
                MyParms.blt.CopySourceID < 0 ? "exp" : "mac",
                MyParms.blt.CopySourceID,
                MyParms.blt.CopyDestinationID < 0 ? "exp" : "mac",
                MyParms.blt.CopyDestinationID,
                MyParms.blt.CopyScreenUpdatesInhibited) ; }
#endif
	} else {
		SourceBM = EWS_ctrl->SavedBitMaps[MyParms.blt.CopySourceID] ;
#ifdef GGGDEBUG
		if (SourceBM == qd.screenBits) {
		   	debugPrint(6, "CopyBits %s[%d/%d]->%s[%d/%d] FROM SBM == SCREENBITS!!!\n", 
				MyParms.blt.CopySourceID < 0 ? "exp" : "mac",
				MyParms.blt.CopySourceID,
				MyParms.blt.CopySourceID < 0 ? 0 : 
					EWS_ctrl->AssociatedMacWindowID[MyParms.blt.CopySourceID],
				MyParms.blt.CopyDestinationID < 0 ? "exp" : "mac",
				MyParms.blt.CopyDestinationID,
				MyParms.blt.CopyDestinationID < 0 ? 0 : 
					EWS_ctrl->AssociatedMacWindowID[MyParms.blt.CopyDestinationID]) ;
			debugDump () ;
		}
#endif GGGDEBUG
	}
		
	if ( MyParms.blt.CopyDestinationID == PRINTER_ID && EWS_ctrl->SavedGrafPorts[PRINTER_ID] ) {
	    SetPort(EWS_ctrl->SavedGrafPorts[PRINTER_ID]);
	    DestBM = EWS_ctrl->SavedGrafPorts[PRINTER_ID]->portBits;
#ifdef ABDEBUG
        printw("CopyBits %s[%d]->%s[%d]  UpDatesInhibited= %d\n", 
            MyParms.blt.CopySourceID < 0 ? "exp" : "mac",
            MyParms.blt.CopySourceID,
            MyParms.blt.CopyDestinationID < 0 ? "exp" : "mac",
            MyParms.blt.CopyDestinationID,
            MyParms.blt.CopyScreenUpdatesInhibited) ;
#endif
 	} else {
		if (EWS_ctrl->AssociatedMacWindowID[MyParms.blt.CopyDestinationID] > 0)
			DestBM = EWS_ctrl->SavedGrafPorts[MyParms.blt.CopyDestinationID]->portBits ;
		else {
			DestBM = EWS_ctrl->SavedBitMaps[MyParms.blt.CopyDestinationID] ;
#ifdef GGGDEBUG
			if (DestBM == qd.screenBits) {
		   		debugPrint(6, "CopyBits %s[%d/%d]->%s[%d/%d] TO SBM == SCREENBITS!!!\n", 
					MyParms.blt.CopySourceID < 0 ? "exp" : "mac",
					MyParms.blt.CopySourceID,
					MyParms.blt.CopySourceID < 0 ? 0 : 
						EWS_ctrl->AssociatedMacWindowID[MyParms.blt.CopySourceID],
					MyParms.blt.CopyDestinationID < 0 ? "exp" : "mac",
					MyParms.blt.CopyDestinationID,
					MyParms.blt.CopyDestinationID < 0 ? 0 : 
						EWS_ctrl->AssociatedMacWindowID[MyParms.blt.CopyDestinationID]) ;
				debugDump () ;
			}
#endif GGGDEBUG
		}
	}
		
#ifdef GGGDEBUG
	if (debugFlag) {
	    debugPrint(8, " w=%d  h=%d  src=x%08x[%d,%d]  dest=x%08x[%d,%d]\n", 
			MyParms.blt.CopyWidth, MyParms.blt.CopyHeight, 
			SourceBM.baseAddr, MyParms.blt.CopySource.h, MyParms.blt.CopySource.v, 
			DestBM.baseAddr, MyParms.blt.CopyDestination.h, MyParms.blt.CopyDestination.v) ;
	}
#endif GGGDEBUG
	
	if (MyParms.blt.CopySourceWidth < MyParms.blt.CopySource.h + MyParms.blt.CopyWidth ||
		MyParms.blt.CopySourceHeight < MyParms.blt.CopySource.v + MyParms.blt.CopyHeight) {
	    rPatternFill(&SourceBM, &DestBM, &tRect, &aRect, MyParms.blt.CopyMode) ;
	} else {
	    SetRect(&tRect, MyParms.blt.CopySource.h, MyParms.blt.CopySource.v,
			MyParms.blt.CopyWidth + MyParms.blt.CopySource.h,
			MyParms.blt.CopyHeight + MyParms.blt.CopySource.v) ;
	    CopyBits(&SourceBM, &DestBM, &tRect, &aRect, MyParms.blt.CopyMode, NULL) ;
#ifdef GGGDEBUG
		if (debugFlag) {
			dumpCopyBitsCall(&SourceBM, &DestBM, &tRect, &aRect, MyParms.blt.CopyMode, NULL) ;
		}
#endif GGGDEBUG
	}
	if ((EWS_ctrl->AssociatedMacWindowID[MyParms.blt.CopyDestinationID] > 0 ) &&
			OnScreenP(MyParms.blt.CopyDestinationID)) {
		UpdateRec.ScreenUpdatesInhibited = MyParms.blt.CopyScreenUpdatesInhibited;
	    InvalidateScreenRect(MyParms.blt.CopyDestinationID, &aRect) ;
	}
    }
    SetPort(oldPort) ;
}


rPatternFill(src, dest, srcrect, destrect, copymode)
BitMap *src ;
BitMap *dest ;
register Rect *srcrect ;
register Rect *destrect ;
short copymode ;
{
    short width, height ;
    Rect srect, drect, trect ;
    short x, y ;

    RectRgn(TempRgn, destrect) ;


	/*
		+-----+-----+
		|     |     |
		|  0  |  1  |
		+-----+------
		|     |     |
		|  2  |  3  |
		+-----+-----+
	*/

    width = src->bounds.right - src->bounds.left ;
    height = src->bounds.bottom - src->bounds.top ;


    if (copymode != srcCopy && copymode != notSrcCopy) {
	drect.left = destrect->left ;
	drect.right = destrect->left + width ;
	drect.top = destrect->top ;
	drect.bottom = destrect->top + height ;
	for (y = 0 ; y < destrect->bottom - destrect->top ; y += height) {
	    for (x = 0 ; x < destrect->right - destrect->left ; x += width) {
		CopyBits(src, dest, srcrect, &drect, copymode, TempRgn) ;
#ifdef GGGDEBUG
		if (debugFlag) {
			dumpCopyBitsCall(src, dest, srcrect, &drect, copymode, TempRgn) ;
		}
#endif GGGDEBUG
		OffsetRect(&drect, width, 0) ;
	    }
	    drect.left = destrect->left ;
	    drect.right = destrect->left + width ;
	    OffsetRect(&drect, 0, height) ;
	}

	return ;
    }

	/* 0 */
    srect.left = destrect->left ;
    srect.top = destrect->top ;
    srect.right = srect.left + width ;
    srect.bottom = srect.top + height ;
    if (srcrect->left == 0 && srcrect->top == 0) {
		SetRect (&trect, 0, 0, width, height) ;
		CopyBits(src, dest, &trect, &srect, copymode, TempRgn) ;
#ifdef GGGDEBUG
		if (debugFlag) {
			dumpCopyBitsCall(src, dest, &trect, &srect, copymode, TempRgn) ;
		}
#endif GGGDEBUG
    } else {
	    /* we have a problem with pattern alignment here... we must normalize */
	    /* the seed for replication area 0 to be the full width and height of */
	    /* the pattern for it to replicate properly, otherwise it ends up as  */
	    /* a moire pattern or worse */

	trect.left = srcrect->left ;
	trect.top = srcrect->top ;
	trect.right = width ;
	trect.bottom = height ;
	drect.left = destrect->left ;
	drect.right = destrect->left + width - srcrect->left ;
	drect.top = destrect->top ;
	drect.bottom = destrect->top + height - srcrect->top ;
	CopyBits(src, dest, &trect, &drect, copymode, TempRgn) ;
#ifdef GGGDEBUG
		if (debugFlag) {
			dumpCopyBitsCall(src, dest, &trect, &drect, copymode, TempRgn) ;
		}
#endif GGGDEBUG

	if (srcrect->left) {
	    trect.left = 0 ;
	    trect.right = srcrect->left ;
	    trect.top = srcrect->top ;
	    trect.bottom = height ;
	    drect.left += width - srcrect->left ;
	    drect.right = drect.left + srcrect->left ;	
	    CopyBits(src, dest, &trect, &drect, copymode, TempRgn) ;
#ifdef GGGDEBUG
		if (debugFlag) {
			dumpCopyBitsCall(src, dest, &trect, &drect, copymode, TempRgn) ;
		}
#endif GGGDEBUG
	}
	if (srcrect->top) {

	    trect.left = srcrect->left ;
	    trect.top = 0 ;
	    trect.right = width ;
	    trect.bottom = srcrect->top ;
	    drect.left = destrect->left ;
	    drect.right = destrect->left + width - srcrect->left ;
	    drect.top = destrect->top + height - srcrect->top ;
	    drect.bottom = drect.top + srcrect->top ;
	    CopyBits(src, dest, &trect, &drect, copymode, TempRgn) ;
#ifdef GGGDEBUG
		if (debugFlag) {
			dumpCopyBitsCall(src, dest, &trect, &drect, copymode, TempRgn) ;
		}
#endif GGGDEBUG

	    if (srcrect->left) {
		trect.left = 0 ;
		trect.right = srcrect->left ;
		trect.top = 0 ;
		trect.bottom = srcrect->top ;
		drect.left += width - srcrect->left ;
		drect.right = drect.left + srcrect->left ;	
		CopyBits(src, dest, &trect, &drect, copymode, TempRgn) ;
#ifdef GGGDEBUG
		if (debugFlag) {
			dumpCopyBitsCall(src, dest, &trect, &drect, copymode, TempRgn) ;
		}
#endif GGGDEBUG
	    }
	}
    }
	
    for (;;) {

	    /* 1 */
	if (srect.right < destrect->right) {
	    drect.left = srect.right ;
	    drect.top = srect.top ;
	    drect.right = drect.left + width ;
	    drect.bottom = drect.top + height ;	
	    CopyBits(dest, dest, &srect, &drect, copymode, TempRgn) ;
#ifdef GGGDEBUG
		if (debugFlag) {
			dumpCopyBitsCall(src, dest, &srect, &drect, copymode, TempRgn) ;
		}
#endif GGGDEBUG
	}

	    /* 2 */
	if (srect.bottom < destrect->bottom) {
	    drect.left = srect.left ;
	    drect.top = srect.bottom ;
	    drect.right = drect.left + width ;
	    drect.bottom = drect.top + height ;	
	    CopyBits(dest, dest, &srect, &drect, copymode, TempRgn) ;
#ifdef GGGDEBUG
		if (debugFlag) {
			dumpCopyBitsCall(src, dest, &srect, &drect, copymode, TempRgn) ;
		}
#endif GGGDEBUG
	}

	    /* 3 */
	drect.left = srect.right ;
	drect.top = srect.bottom ;
	drect.right = drect.left + width ;
	drect.bottom = drect.top + height ;	
	CopyBits(dest, dest, &srect, &drect, copymode, TempRgn) ;
#ifdef GGGDEBUG
		if (debugFlag) {
			dumpCopyBitsCall(src, dest, &srect, &drect, copymode, TempRgn) ;
		}
#endif GGGDEBUG
	if (drect.right > destrect->right && drect.bottom > destrect->bottom)
	    break ;

	    /* update 0 */
	srect.right += width ;
	srect.right = min(srect.right, destrect->right) ;
	srect.bottom += height ;
	srect.bottom = min(srect.bottom, destrect->bottom) ;
	width = srect.right - srect.left ;
	height = srect.bottom - srect.top ;
    }
}


/*
	{Parm1 = Pen Transfer Mode}
	{Parm2,3,4,5 = X1,Y1,X2,Y2}
	{Parm6 = Explorer window ID being drawn to}
	{Parm7,8,9,10 = left,top,right,bottom of the clipping rectangle}
*/

static void
rDrawLine(cmd)
acb *cmd ;
{
    Rect 		modRect, TempRect ;

    copy_parms_32b(cmd, &MyParms, 0, 8, TO_ARRAY) ;
    set_input_complete(cmd, 1) ;

#ifdef XXDEBUG
    if (debugFlag) {
		debugPrint (9, "DrawLine [%d] %d,%d->%d,%d clipped to %d %d %d %d\n", 
			MyParms.l.LineExplorerWindowID,
			MyParms.l.LineStartPoint.h, MyParms.l.LineStartPoint.v,
			MyParms.l.LineEndPoint.h, MyParms.l.LineEndPoint.v,
			MyParms.l.LineClippingRect.left,
			MyParms.l.LineClippingRect.top,
			MyParms.l.LineClippingRect.right,
			MyParms.l.LineClippingRect.bottom) ;
    }
#endif XXDEBUG

    if (EWS_ctrl->SavedGrafPorts[MyParms.l.LineExplorerWindowID] == NULL) {
#ifdef GGGDEBUG
		debugPrint1 ("DrawLine to NULL GrafPort, WID= %d!\n", MyParms.l.LineExplorerWindowID) ;
		debugDump () ;
#endif GGGDEBUG
		return ;
    }

    SetPort(EWS_ctrl->SavedGrafPorts[MyParms.l.LineExplorerWindowID]) ;
    ClipRect(&MyParms.l.LineClippingRect) ;
    PenMode(8 + MyParms.l.LinePenMode) ;
    PenPat(MyParms.l.LinePenPattern) ;
    PenSize(MyParms.l.LinePenWidth, MyParms.l.LinePenHeight) ;

    MoveTo(MyParms.l.LineStartPoint.h, MyParms.l.LineStartPoint.v) ;
    LineTo(MyParms.l.LineEndPoint.h, MyParms.l.LineEndPoint.v) ;

    if (OnScreenP(MyParms.l.LineExplorerWindowID)) {
		/*  Watch out!  quickdraw.h claims the first two arguments to Pt2Rect are of type Point
			when in fact (proved by experimentation!) they are of type (Point *)!!! */
		Pt2Rect(&MyParms.l.LineStartPoint, &MyParms.l.LineEndPoint, &modRect) ;
		/*  Expand the bounding rectangle to include the bottom "pixel" and the right-most "pixel"
			of the line drawn by the hanging-down-and-to-the-right pen.  Usually we draw one-pixel-wide
			lines, so "pixel" is correct.  In case we don't, this code actually catches the bottom-most
			and right-most pen-image.  */
		modRect.right = modRect.right + MyParms.l.LinePenWidth ;
		modRect.bottom = modRect.bottom + MyParms.l.LinePenHeight ;
		SectRect (&modRect, &MyParms.l.LineClippingRect, &TempRect) ;
		InvalidateScreenRect(MyParms.l.LineExplorerWindowID, &TempRect) ;
    }
}

/*
  {Parm1,2,3,4 = penPattern = pattern specification (pixel definition)}
  {Parm5,6,7,8 = X0,Y0,X1,Y1 = boundingRect of upper left and lower right corner
    of rectangle}
  {Parm9 = pen transfer mode}
  {Parm10 = Explorer Window ID being drawn to}
  {Parm11,12,13,14 = left,top,right,bottom of clipping rectangle to use}
*/
static void
rDrawRectangle(cmd)
acb *cmd ;
{
	Rect		TempRect ;
	
    copy_parms_32b(cmd, &MyParms, 0, 7, TO_ARRAY) ;
    set_input_complete(cmd, 1) ;

#ifdef XXDEBUG
    if (debugFlag) {
		debugPrint4 ("DrawRect [%d] SGP= x%08x  SGPpBbA= x%08x  PenMode = %d\n", 
			MyParms.dr.RectangleExplorerWindowID,
			EWS_ctrl->SavedGrafPorts[MyParms.dr.RectangleExplorerWindowID],
			EWS_ctrl->SavedGrafPorts[MyParms.dr.RectangleExplorerWindowID]->portBits.baseAddr,
			MyParms.dr.RectanglePenMode) ;
		dump2Rects("  Rect", &MyParms.dr.RectangleRect, 
			"ClipRect", &MyParms.dr.RectangleClippingRect) ;
    }
#endif
    if (EWS_ctrl->SavedGrafPorts[MyParms.dr.RectangleExplorerWindowID] == NULL) {
#ifdef GGGDEBUG
		debugPrint1 ("DrawRectangle to NULL GrafPort, WID= %d!\n", MyParms.dr.RectangleExplorerWindowID) ;
		debugDump () ;
#endif
		return ;
    }

    SetPort(EWS_ctrl->SavedGrafPorts[MyParms.dr.RectangleExplorerWindowID]) ;
    ClipRect(&MyParms.dr.RectangleClippingRect) ;
    PenPat(MyParms.dr.RectanglePenPattern) ;
    PenMode(8 + MyParms.dr.RectanglePenMode) ;
    PaintRect(&MyParms.dr.RectangleRect) ;
    if (OnScreenP(MyParms.dr.RectangleExplorerWindowID)) {
		SectRect (&MyParms.dr.RectangleRect, &MyParms.dr.RectangleClippingRect, &TempRect) ;
		InvalidateScreenRect(MyParms.dr.RectangleExplorerWindowID, &TempRect);
	}
}

/* Draws a hollow rectangle
  	{Parm1,2,3,4 = penPattern = pattern specification (pixel definition)}
	{Parm5,6 = X,Y of upper left hand corner of rectangle}
	{Parm7,8 = X,Y of lower right hand corner of rectangle}
	{Parm9 = pen transfer mode}
	{Parm10,11 = widht,height of pen}
	{Parm12 = Explorer Window ID being drawn to}
	{Parm13,14,15,16 = left,top,right,bottom of clipping rectangle to use}
*/

static void
rDrawFrameRectangle(cmd)
acb *cmd ;
{
	Rect		InvalRect, TempRect ;
#ifdef XXDEBUG
    if (debugFlag) {
		debugPrint0 ("rDrawFrameRectangle\n") ;
    }
#endif
    copy_parms_32b(cmd, &MyParms, 0, 8, TO_ARRAY) ;
    set_input_complete(cmd, 1) ;

    if (EWS_ctrl->SavedGrafPorts[MyParms.dfr.FrameRectExplorerWindowID] == NULL) {
#ifdef GGGDEBUG
		debugPrint1 ("DrawFrameRect to NULL GrafPort, WID= %d!\n", MyParms.dfr.FrameRectExplorerWindowID) ;
		debugDump () ;
#endif
		return ;
    }


    SetPort(EWS_ctrl->SavedGrafPorts[MyParms.dfr.FrameRectExplorerWindowID]) ;
    ClipRect(&MyParms.dfr.FrameRectClippingRect) ;
    PenPat(MyParms.dfr.FrameRectPenPattern) ;
    PenMode(8 + MyParms.dfr.FrameRectPenMode) ;
    PenSize(MyParms.dfr.FrameRectPenWidth, MyParms.dfr.FrameRectPenHeight) ;
	/*	Expand the bottom and right edges of the rectangle to be framed by the width
		of the pen so the frame, which is drawn entirely within the rectangle given 
		to FrameRect, will hang "down and to the right" of the original
		rectangle to be consistent with the Explorer.  */
	MyParms.dfr.FrameRectRect.right += MyParms.dfr.FrameRectPenWidth ;
	MyParms.dfr.FrameRectRect.bottom += MyParms.dfr.FrameRectPenHeight ;
    FrameRect(&MyParms.dfr.FrameRectRect) ;

#ifdef XXDEBUG
    if (debugFlag) {
		dump1Rect("FrameRect", &MyParms.dfr.FrameRectRect) ;
    }
#endif

    if (OnScreenP(MyParms.dfr.FrameRectExplorerWindowID)) {

		/*	Invalidate the top horizontal line.  */
		SetRect (&TempRect, MyParms.dfr.FrameRectRect.left,
							MyParms.dfr.FrameRectRect.top,
							MyParms.dfr.FrameRectRect.right,
							MyParms.dfr.FrameRectRect.top + MyParms.dfr.FrameRectPenHeight) ;
		SectRect (&TempRect, &MyParms.dfr.FrameRectClippingRect, &InvalRect) ;
		InvalidateScreenRect(MyParms.dfr.FrameRectExplorerWindowID, &InvalRect) ;
		UpdateScreen();
		/*	Invalidate the right vertical line.  */
		SetRect (&TempRect, MyParms.dfr.FrameRectRect.right - MyParms.dfr.FrameRectPenWidth,
							MyParms.dfr.FrameRectRect.top,
							MyParms.dfr.FrameRectRect.right,
							MyParms.dfr.FrameRectRect.bottom) ;
		SectRect (&TempRect, &MyParms.dfr.FrameRectClippingRect, &InvalRect) ;
		InvalidateScreenRect(MyParms.dfr.FrameRectExplorerWindowID, &InvalRect) ;
		UpdateScreen();
		/*	Invalidate the bottom horizontal line.  */
		SetRect (&TempRect, MyParms.dfr.FrameRectRect.left,
							MyParms.dfr.FrameRectRect.bottom - MyParms.dfr.FrameRectPenHeight,
							MyParms.dfr.FrameRectRect.right,
							MyParms.dfr.FrameRectRect.bottom) ;
		SectRect (&TempRect, &MyParms.dfr.FrameRectClippingRect, &InvalRect) ;
		InvalidateScreenRect(MyParms.dfr.FrameRectExplorerWindowID, &InvalRect) ;
		UpdateScreen();
		/*	Invalidate the left vertical line.  */
		SetRect (&TempRect, MyParms.dfr.FrameRectRect.left,
							MyParms.dfr.FrameRectRect.top,
							MyParms.dfr.FrameRectRect.left + MyParms.dfr.FrameRectPenWidth,
							MyParms.dfr.FrameRectRect.bottom) ;
		SectRect (&TempRect, &MyParms.dfr.FrameRectClippingRect, &InvalRect) ;
		InvalidateScreenRect(MyParms.dfr.FrameRectExplorerWindowID, &InvalRect) ;
		UpdateScreen();
	}
}


/* rDrawOval:	{Draws a filled in oval}
  	{Parm1,2,3,4 = penPattern = pattern specification (pixel definition)}
	{Parm5,6 = X,Y of upper left hand corner of bounding rectangle}
	{Parm7,8 = X,Y of lower right hand corner of bounding rectangle}
	{Parm9 = pen transfer mode}
	{Parm10 = Explorer Window ID being drawn to}
	{Parm11,12,13,14 = left,top,right,bottom of clipping rectangle to use}
*/

static void
rDrawOval(cmd)
acb *cmd ;
{
	Rect		TempRect ;
	
#ifdef XXDEBUG
    if (debugFlag) {
		debugPrint0 ("rDrawOval\n") ;
    }
#endif
    copy_parms_32b(cmd, &MyParms, 0, 7, TO_ARRAY) ;
    set_input_complete(cmd, 1) ;

    if (EWS_ctrl->SavedGrafPorts[MyParms.dov.OvalExplorerWindowID] == NULL) {
#ifdef GGGDEBUG
		debugPrint1 ("DrawOval to NULL GrafPort, WID= %d!\n", MyParms.dov.OvalExplorerWindowID) ;
		debugDump () ;
#endif
		return ;
    }

    SetPort(EWS_ctrl->SavedGrafPorts[MyParms.dov.OvalExplorerWindowID]) ;
    ClipRect(&MyParms.dov.OvalClippingRect) ;
    PenPat(MyParms.dov.OvalPenPattern) ;
    PenMode(8 + MyParms.dov.OvalPenMode) ;
    PaintOval(&MyParms.dov.OvalRect) ;
    if (OnScreenP(MyParms.dov.OvalExplorerWindowID)) {
		SectRect (&MyParms.dov.OvalRect, &MyParms.dov.OvalClippingRect, &TempRect) ;
		InvalidateScreenRect (MyParms.dov.OvalExplorerWindowID, &TempRect) ;
	}
}

/* rDrawFrameOval: {Draw a hollow oval}
  	{Parm1,2,3,4 = penPattern = pattern specification (pixel definition)}
	{Parm5,6 = X,Y of upper left hand corner of bounding rectangle}
	{Parm7,8 = X,Y of lower right hand corner of bounding rectangle}
	{Parm9 = pen transfer mode}
	{Parm10,11 = widht,height of pen}
	{Parm12 = Explorer Window ID being drawn to}
	{Parm13,14,15,16 = left,top,right,bottom of clipping rectangle to use}
*/
static void
rDrawFrameOval(cmd)
acb *cmd ;
{
	Rect		TempRect ;
	
#ifdef XXDEBUG
    if (debugFlag) {
		debugPrint0 ("rDrawFrameOval\n") ;
    }
#endif

    copy_parms_32b(cmd, &MyParms, 0, 8, TO_ARRAY) ;
    set_input_complete(cmd, 1) ;

    if (EWS_ctrl->SavedGrafPorts[MyParms.dfo.FrameOvalExplorerWindowID] == NULL) {
#ifdef GGGDEBUG
		debugPrint1 ("DrawFrameOval to NULL GrafPort, WID= %d!\n", MyParms.dfo.FrameOvalExplorerWindowID) ;
		debugDump () ;
#endif
		return ;
    }

    SetPort(EWS_ctrl->SavedGrafPorts[MyParms.dfo.FrameOvalExplorerWindowID]) ;
    ClipRect(&MyParms.dfo.FrameOvalClippingRect) ;
    PenPat(MyParms.dfo.FrameOvalPenPattern) ;
    PenMode(8 + MyParms.dfo.FrameOvalPenMode) ;
    PenSize(MyParms.dfo.FrameOvalPenWidth, MyParms.dfo.FrameOvalPenHeight) ;
	/*	Expand the bottom and right edges of the rectangle circumscribing the oval to be
		framed by the width of the pen so the frame, which is drawn entirely within the
		rectangle given to FrameOval, will hang "down and to the right" of the original
		rectangle to be consistent with the Explorer.  */
	MyParms.dfo.FrameOvalRect.right += MyParms.dfo.FrameOvalPenWidth ;
	MyParms.dfo.FrameOvalRect.bottom += MyParms.dfo.FrameOvalPenHeight ;
    FrameOval(&MyParms.dfo.FrameOvalRect) ;
    if (OnScreenP(MyParms.dfo.FrameOvalExplorerWindowID)) {
		SectRect (&MyParms.dfo.FrameOvalRect, &MyParms.dfo.FrameOvalClippingRect, 
				  &TempRect) ;
		InvalidateScreenRect(MyParms.dfo.FrameOvalExplorerWindowID, &TempRect) ;
	}
}

/* rDrawTriangle: {Draws a filled in triangle}
  	{Parm1,2,3,4 = penPattern = pattern specification (pixel definition)}
  	{Parm5,6 = X0,Y0}
	{Parm7,8 = X1,Y1}
	{Parm9,10 = X2,Y2}
	{Parm11 = pen transfer mode}
	{Parm12 = Explorer Window ID being drawn to}
	{Parm13,14,15,16 = left,top,right,bottom of clipping rectangle}
*/
static void
rDrawTriangle(cmd)
acb *cmd ;
{
    RgnHandle 	TriPoly ;
    Rect 		modRect, TempRect ;

    copy_parms_32b(cmd, &MyParms, 0, 8, TO_ARRAY) ;
    set_input_complete(cmd, 1) ;

    if (EWS_ctrl->SavedGrafPorts[MyParms.dt.TriangleExplorerWindowID] == NULL) {
#ifdef GGGDEBUG
		debugPrint1 ("DrawTriangle to NULL GrafPort, WID= %d!\n", MyParms.dt.TriangleExplorerWindowID) ;
		debugDump () ;
#endif
		return ;
    }

    SetPort(EWS_ctrl->SavedGrafPorts[MyParms.dt.TriangleExplorerWindowID]) ;
    TriPoly = NewRgn() ;
	OpenRgn() ;
		MoveTo(MyParms.dt.TriangleVertex0.h, MyParms.dt.TriangleVertex0.v) ;
		LineTo(MyParms.dt.TriangleVertex1.h, MyParms.dt.TriangleVertex1.v) ;
		LineTo(MyParms.dt.TriangleVertex2.h, MyParms.dt.TriangleVertex2.v) ;
		LineTo(MyParms.dt.TriangleVertex0.h, MyParms.dt.TriangleVertex0.v) ;
    CloseRgn(TriPoly) ;
#ifdef XXDEBUG
    if (debugFlag) {
		Rect	*rect1 = &MyParms.dt.TriangleClippingRect ;
		debugPrint (12, "Tri:%d/%d (%d,%d) to (%d,%d) to (%d,%d) clipped to (%d,%d) (%d,%d)\n",
			StackSpace (), GetHandleSize(TriPoly),
			MyParms.dt.TriangleVertex0.h, MyParms.dt.TriangleVertex0.v,
			MyParms.dt.TriangleVertex1.h, MyParms.dt.TriangleVertex1.v,
			MyParms.dt.TriangleVertex2.h, MyParms.dt.TriangleVertex2.v,
			rect1->left, rect1->top, rect1->right, rect1->bottom) ;
    }
#endif
    ClipRect(&MyParms.dt.TriangleClippingRect) ;
    PenPat(MyParms.dt.TrianglePenPattern) ;
    PenMode(8 + MyParms.dt.TrianglePenMode) ;
    PaintRgn(TriPoly) ;

    if (OnScreenP(MyParms.dt.TriangleExplorerWindowID)) {
	    modRect = (*TriPoly)->rgnBBox ;
		SectRect (&modRect, &MyParms.dt.TriangleClippingRect, &TempRect) ;
		if (debugFlag)
			dump2Rects ("modRect", &modRect, "TempRect", &TempRect) ;
		InvalidateScreenRect (MyParms.dt.TriangleExplorerWindowID, &TempRect) ;
	}
    DisposeRgn(TriPoly) ;
}

/* rDrawFilledPolygon: {Draws a filled in polygon}
  	{Parm1,2,3,4 = fillPattern = pattern specification (pixel definition)}
	{Parm5 = pen transfer mode}
	{Parm6 = Explorer Window ID being drawn to}
	{Parm7 = n = Number of points in polygon}
	{Parm9,10,11,12 = left,top,right,bottom of clipping rectangle}
	{Parm13+2j, Parm13+2j, j=0,1,2,...n-1 = n vertices of polygon}
*/
static void
rDrawFilledPolygon(cmd)
acb *cmd ;
{
    RgnHandle 	TriPoly ;
    Rect 		modRect, TempRect ;
    Point 		vertex ;
	unsigned int	TempI ;
	Point		*vertexAddr ;
    short 		i ;	

    copy_parms_32b(cmd, &MyParms, 0, 7, TO_ARRAY) ;

#ifdef XXDEBUG
    if (debugFlag) {
		debugPrint5 ("rDrawFilledPolygon.  %d vertices clipped to %d %d %d %d\n",
			MyParms.dfp.FilledPolyLength,
			MyParms.dfp.FilledPolyClippingRect.left,
			MyParms.dfp.FilledPolyClippingRect.top,
			MyParms.dfp.FilledPolyClippingRect.right,
			MyParms.dfp.FilledPolyClippingRect.bottom) ;
    }
#endif

    if (EWS_ctrl->SavedGrafPorts[MyParms.dfp.FilledPolyExplorerWindowID] == NULL) {
#ifdef GGGDEBUG
		debugPrint1 ("DrawFilledPolygon to NULL GrafPort, WID= %d!\n", 
			MyParms.dfp.FilledPolyExplorerWindowID) ;
		debugDump () ;
#endif
		set_input_complete(cmd, 1) ;
		return ;
    }


    SetPort(EWS_ctrl->SavedGrafPorts[MyParms.dfp.FilledPolyExplorerWindowID]) ;
    TriPoly = NewRgn() ;
	OpenRgn() ;
    	vertex = MyParms.dfp.FilledPolyFirstVertex ;
    	MoveTo(vertex.h, vertex.v) ;
    	for (i=7; i < (MyParms.dfp.FilledPolyLength + 6); i++) {
			TempI = parm_32b (cmd, i) ;
			vertexAddr = (Point *)&TempI ; 
			LineTo(vertexAddr->h, vertexAddr->v) ;
    	}
    	LineTo(vertex.h, vertex.v) ;
    CloseRgn(TriPoly) ;
   	set_input_complete(cmd, 1) ;

    ClipRect(&MyParms.dfp.FilledPolyClippingRect) ;
    PenMode(8 + MyParms.dfp.FilledPolyPenMode) ;
    PenPat(MyParms.dfp.FilledPolyFillPattern) ;
    PaintRgn(TriPoly) ;

    if (OnScreenP(MyParms.dfp.FilledPolyExplorerWindowID)) {
	    modRect = (*TriPoly)->rgnBBox ;
		SectRect (&modRect, &MyParms.dfp.FilledPolyClippingRect, &TempRect) ;
		InvalidateScreenRect(MyParms.dfp.FilledPolyExplorerWindowID, &TempRect) ;
	}
    DisposeRgn(TriPoly) ;
}

/*
  	{Parm1 = ASCII character code}
	{Parm2 = font}
	{Parm3 = font style (bold,italic)}
	{Parm4 = font size}
	{Parm5 = pen transfer mode}
	{Parm6,7 = X,Y of baseline}
	{Parm8 = Explorer Window ID being drawn to}
	{Parm9,10,11,12 = left,top,right,bottom of clipping rectangle to use}
*/

static void
rDrawChar(cmd)
acb *cmd ;
{
    Style 		newFace ;
    Rect 		r ;
    FontInfo 	FInfo ;
    Rect 		modRect, TempRect ;
	
#ifdef XXXXDEBUG
    if (debugFlag && FALSE) {
		debugPrint0 ("rDrawChar\n") ;
    }
#endif
    copy_parms_32b(cmd, &MyParms, 0, 6, TO_ARRAY) ;
    set_input_complete(cmd, 1) ;

    if (EWS_ctrl->SavedGrafPorts[MyParms.c.CharExplorerWindowID] == NULL) {
#ifdef GGGDEBUG
		debugPrint1 ("DrawChar to NULL GrafPort, WID= %d!\n", MyParms.c.CharExplorerWindowID) ;
		debugDump () ;
#endif
		return ;
    }

    SetPort(EWS_ctrl->SavedGrafPorts[MyParms.c.CharExplorerWindowID]) ;
    ClipRect(&MyParms.c.CharClippingRect) ;

    setPortFonts(qd.thePort, MyParms.c.CharFont, MyParms.c.CharFontStyle,
		MyParms.c.CharFontSize) ;
    if (MyParms.c.CharPenMode != qd.thePort->txMode)
		TextMode(MyParms.c.CharPenMode) ;
    MoveTo(MyParms.c.CharBaseline.h, MyParms.c.CharBaseline.v) ;
    DrawChar(MyParms.c.CharASCIICode) ;

#ifdef XXDEBUG
    if (debugFlag && FALSE) {
		debugPrint3 ("DrawChar: '%c' %d %d\n", MyParms.c.CharASCIICode,
			MyParms.c.CharExplorerWindowID, 
			OnScreenP(MyParms.c.CharExplorerWindowID)) ;
		dump1Rect("SGPClip",
		 	&(*EWS_ctrl->SavedGrafPorts[MyParms.c.CharExplorerWindowID]->clipRgn)->rgnBBox) ;
    }
#endif

    if (OnScreenP(MyParms.c.CharExplorerWindowID)) {
		rFontInfo(&FInfo, MyParms.c.CharFont, MyParms.c.CharFontSize) ;
		SetRect(&modRect, MyParms.c.CharBaseline.h,
			MyParms.c.CharBaseline.v - FInfo.ascent,
			MyParms.c.CharBaseline.h + FInfo.widMax + (FInfo.widMax >> 1),
			MyParms.c.CharBaseline.v + FInfo.descent) ;
		SectRect (&modRect, &MyParms.c.CharClippingRect, &TempRect) ;
		InvalidateScreenRect (MyParms.c.CharExplorerWindowID, &TempRect) ;
    }
}


#define GraphicCharP(ch) (!((unsigned)ch >= 0x80) && ((unsigned)ch <= 0x9f))
 
/*
  	{Parm1 = font}
	{Parm2 = font style (bold,italic)}
	{Parm3 = font size}
	{Parm4 = pen transfer mode}
	{Parm5 = 0}
	{Parm6 = number of characters to draw}
	{Parm7,8 = X,Y of font baseline}
	{Parm9 = X limit (pixel at which to stop}
	{Parm10 = Explorer Window ID being drawn to}
	{Parm11,12,13,14 = left,top,right,bottom of clipping rectangle to use}
*/
static void
rDrawString(cmd)
acb *cmd ;
{
    int 		i ;
    char 		text[256] ;
    Rect 		modRect, TempRect ;
    FontInfo 	FInfo ;

    copy_parms_32b(cmd, &MyParms, 0, 7, TO_ARRAY) ;
    copy_parms_8b(cmd, text, 28, MyParms.s.StringLength, TO_ARRAY) ;
    text[MyParms.s.StringLength] = '\0' ;
    set_input_complete(cmd, 1) ;

    if (EWS_ctrl->SavedGrafPorts[MyParms.s.StringExplorerWindowID] == NULL) {
#ifdef GGGDEBUG
		debugPrint1 ("DrawString to NULL GrafPort, WID= %d!\n", MyParms.s.StringExplorerWindowID) ;
		debugDump () ;
#endif
		return ;
    }

    SetPort(EWS_ctrl->SavedGrafPorts[MyParms.s.StringExplorerWindowID]) ;
    ClipRect(&MyParms.s.StringClippingRect) ;
    setPortFonts(qd.thePort, MyParms.s.StringFont, MyParms.s.StringFontStyle,
		MyParms.s.StringFontSize) ;
    if (MyParms.s.StringPenMode != qd.thePort->txMode)
		TextMode(MyParms.s.StringPenMode) ;
    MoveTo(MyParms.s.StringBaseline.h, MyParms.s.StringBaseline.v);
    DrawText(text, MyParms.s.StringStartIndex, MyParms.s.StringLength -
		MyParms.s.StringStartIndex) ;

    if (OnScreenP(MyParms.s.StringExplorerWindowID)) {
		rFontInfo(&FInfo, MyParms.s.StringFont, MyParms.s.StringFontSize) ;
		SetRect(&modRect, MyParms.s.StringBaseline.h,
			MyParms.s.StringBaseline.v - FInfo.ascent,
			MyParms.s.StringXLimit + (FInfo.widMax >> 1),
			MyParms.s.StringBaseline.v + FInfo.descent) ;
		SectRect (&modRect, &MyParms.s.StringClippingRect, &TempRect) ;
		InvalidateScreenRect(MyParms.s.StringExplorerWindowID, &TempRect) ;
    }

#ifdef XXDEBUG
	if (debugFlag) {
		debugPrint5 ("DrawString [%d] SGP= x%08x  SGPpBbA= x%08x  X,Y = %d,%d\n", 
			MyParms.s.StringExplorerWindowID,
			EWS_ctrl->SavedGrafPorts[MyParms.s.StringExplorerWindowID],
			EWS_ctrl->SavedGrafPorts[MyParms.s.StringExplorerWindowID]->portBits.baseAddr,
			MyParms.s.StringBaseline.h, MyParms.s.StringBaseline.v);
		dumpPort (NULL, EWS_ctrl->SavedGrafPorts[MyParms.s.StringExplorerWindowID]) ;
		}
    if (debugFlag && FALSE) {
		MacWindowRecPtr macrec ;

		debugPrint4 ("String: [%d] '%s'  L = %d,%d\n", MyParms.s.StringExplorerWindowID,
			text, MyParms.s.StringLength, MyParms.s.StringStartIndex) ;
		debugPrint2 ("X,Y = %d, %d\n", MyParms.s.StringBaseline.h, MyParms.s.StringBaseline.v);
		dump2Rects("  ModRect", &modRect, "SGP Clip",
			&(*EWS_ctrl->SavedGrafPorts[MyParms.s.StringExplorerWindowID]->clipRgn)->rgnBBox) ;
		dump2Rects ("SGP bounds", 
			&EWS_ctrl->SavedGrafPorts[MyParms.s.StringExplorerWindowID]->portBits.bounds,
			"SGP portRect", 
			&EWS_ctrl->SavedGrafPorts[MyParms.s.StringExplorerWindowID]->portRect) ;

		/* ab 9/20/88 */
		if (MyParms.s.StringExplorerWindowID != PRINTER_ID) {
			macrec = EWS_ctrl->MyWindows[abs(EWS_ctrl->
					AssociatedMacWindowID[MyParms.s.StringExplorerWindowID])];
			dump2Rects("My Clip", &(*macrec->myWindow->clipRgn)->rgnBBox,
				"SBM bounds", &EWS_ctrl->SavedBitMaps[macrec->MacWindowsSavedBitMapsID].bounds) ;
			dump2Rects("WBM bounds", &macrec->myWindow->portBits.bounds,
				"W portrect", &macrec->myWindow->portRect) ;
			debugPrint2 ("Scroll X=%d Y=%d\n", macrec->ScrollOffset.h, macrec->ScrollOffset.v) ;
		}
    }
#endif
}

/*	{Parm1 = mouse cursor ID}  */
static void
ChangeMouseCursor(cmd)
acb *cmd ;
{
    CursHandle NewMouse ;
	Cursor CursorImage ;

    copy_parms_32b(cmd, &MyParms, 0, 1, TO_ARRAY) ;
    if (MyParms.cur.MouseCursor != 0) {		/* use cursor from resource file */
    	set_input_complete(cmd, 1) ;
	NewMouse = GetCursor(MyParms.cur.MouseCursor) ;
	if (NewMouse != NULL) {
	    SetCursor(*NewMouse) ;
	    currentCursor = **NewMouse ;
	}
    } else {			/* use bitmap provided by LISPM */
	copy_parms_8b(cmd, &CursorImage, 4, 64, TO_ARRAY); 			/* get the data and mask */
	copy_parms_32b(cmd, (char *)&CursorImage + 64, 17, 1, TO_ARRAY); 	/* get the hotspot */ 
    	set_input_complete(cmd, 1) ;
	BitSwap(&CursorImage, &CursorImage, 64) ;
	SetCursor(&CursorImage);
	currentCursor = CursorImage ;
    }
		
#ifdef XXDEBUG
    if (debugFlag && FALSE) {
	debugPrint1 ("ChangeCursor %d\n", MyParms.cur.MouseCursor) ;
    }
#endif

}

/*
  {returns: Parm1 := left edge of screen}
  {returns: Parm2 := top edge of screen}
  {returns: Parm3 := right edge of screen}
  {returns: Parm4 := bottom edge of screen} */

static void
GetScreenSize(cmd)
acb *cmd ;
{
    extern Boolean dynamicResize ;

    SetRect(&MyParms.r.screenRect, 0, 0,
		MaxWindowWidth, MaxWindowHeight - MouseDocumentHeight(MouseDocCount)) ;
    MyParms.r.dynamicResize = dynamicResize ;
    copy_parms_32b(cmd, &MyParms, 0, 3, TO_ACB) ;
}

/**************************************************************************/
/*                                                                        */
/*                     TV handler                                         */
/*                                                                        */
/**************************************************************************/

#define MAX_TV_OPCODE 22						/* ab 8/22/88 */

extern void printer_command () ;				/* ab 8/22/88 */

static void
nulltvcmd()
{
}

static void 
(*tv_handlers[])(cmd) =
{
  rNewCopyBits,			/*  0 */
  rDrawChar,			/*  1 */
  nulltvcmd,			/*  2 */       /*MousePosition,	    2  */
  rDrawString,			/*  3 */
  rDrawLine, 			/*  4 */
  rDrawTriangle,		/*  5 */
  nulltvcmd,			/*  6 */
  ChangeMouseCursor,	/*  7 */
  nulltvcmd,			/*  8 */
  rDrawRectangle,		/*  9 */
  rDrawFrameRectangle,	/* 10 */
  rDrawOval,			/* 11 */
  rDrawFrameOval,		/* 12 */
  rFontMetrics,			/* 13 */
  rDrawFilledPolygon,	/* 14 */
  GetScreenSize,		/* 15 */
  AdjustBitArray,		/* 16 */
  RedirectDrawing,		/* 17 */
  DeallocateBitArray,	/* 18 */
  AdjustScreenSize,     /* 19 */
  SelectExplorerWindow,	/* 20 */
  rCopyBits,			/* 21 */
  printer_command		/* 22 */				/* ab 8/22/88 */
  
  };
acb *cmd;

tv_command(cmd)
acb *cmd;
{		
    unsigned char op = opcode(cmd);
	Size	Grow ;
	
	UpdateRec.ScreenUpdatesInhibited = FALSE;
	UpdateRec.CurrentCommandOpcode = op ;
  
#ifdef GGGDEBUG
	if (debugFlag) {
		debugPrint3 ("CommandOp= %d at Time= %d.  Heap= %d.\n",
			op, TickCount (), FreeMem());
	}
#endif GGGDEBUG
    if(op <= MAX_TV_OPCODE) 
      (*tv_handlers[op])(cmd);
  
    return_acb_server(cmd);
	UpdateScreen();
}

