[Contents] [Index] [Help] [Retrace] [Browse <] [Browse >]

/* The following program will create a display with the same attributes
** as the user's Workbench screen.  It does this by first inquiring as
** to those attributes, duplicating them, and then creating a similar
** display.
*/

/**********************************************************************/
/*                                                                    */
/*       WBClone.c: To clone the Workbench using graphics calls       */
/*                                                                    */
/*       Compile : SAS/C 5.10a LC -b1 -cfist -L -v -y                 */
/*                                                                    */
/**********************************************************************/

#include <exec/types.h>
#include <exec/exec.h>
#include <clib/exec_protos.h>
#include <intuition/screens.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <clib/intuition_protos.h>
#include <graphics/gfx.h>
#include <graphics/gfxbase.h>
#include <graphics/view.h>
#include <graphics/gfxnodes.h>
#include <graphics/videocontrol.h>
#include <clib/graphics_protos.h>

#include <stdio.h>
#include <stdlib.h>

#define INTUITIONNAME "intuition.library"

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

/*********************************************************************/
/*                            GLOBAL VARIABLES                       */
/*********************************************************************/

struct IntuitionBase *IntuitionBase = NULL ;
struct GfxBase *GfxBase = NULL ;

/**********************************************************************/
/*                                                                    */
/* VOID Error (char *String)                                          */
/*                                                                    */
/* Print string and exit                                              */
/*                                                                    */
/**********************************************************************/

VOID Error (char *String)
{
	VOID CloseAll (VOID) ;

	printf (String) ;

	CloseAll () ;
	exit(0) ;
}

/**********************************************************************/
/*                                                                    */
/* VOID Init ()                                                       */
/*                                                                    */
/* Opens all the required libraries allocates all memory, etc.        */
/*                                                                    */
/**********************************************************************/

VOID Init ( VOID )
{
	/* Open the intuition library.... */
	if ((IntuitionBase = (struct IntuitionBase *)OpenLibrary (INTUITIONNAME, 37L)) == NULL)
		Error ("Could not open the Intuition.library") ;

	/* Open the graphics library.... */
	if ((GfxBase = (struct GfxBase *)OpenLibrary (GRAPHICSNAME, 36L)) == NULL)
		Error ("Could not open the Graphics.library") ;
}

/**********************************************************************/
/*                                                                    */
/* VOID CloseAll ()                                                   */
/*                                                                    */
/* Closes and tidies up everything that was used.                     */
/*                                                                    */
/**********************************************************************/

VOID CloseAll ( VOID )
{
	/* Close everything in the reverse order in which they were opened */

	/* Close the Graphics Library */
	if (GfxBase)
		CloseLibrary ((struct Library *) GfxBase) ;

	/* Close the Intuition Library */
	if (IntuitionBase)
		CloseLibrary ((struct Library *) IntuitionBase) ;
}

/**********************************************************************/
/*                                                                    */
/* VOID DestroyView(struct View *view)                                */
/*                                                                    */
/* Close and free everything to do with the View                      */
/*                                                                    */
/**********************************************************************/

VOID DestroyView(struct View *view)
{
	struct ViewExtra *ve;

	if (view)
	{
		if (ve = (struct ViewExtra *)GfxLookUp(view))
		{
			if (ve->Monitor)
				CloseMonitor(ve->Monitor);

			GfxFree((struct ExtendedNode *)ve);
		}

		/* Free up the copper lists */
		if (view->LOFCprList)
			FreeCprList(view->LOFCprList);

		if (view->SHFCprList)
			FreeCprList(view->SHFCprList);

		FreeVec(view);
	}
}

/**********************************************************************/
/*                                                                    */
/* struct View *DupView(struct View *v, ULONG ModeID)                 */
/*                                                                    */
/* Duplicate the View.                                                */
/*                                                                    */
/**********************************************************************/

struct View *DupView(struct View *v, ULONG ModeID)
{
	/* Allocate and init a View structure.  Also, get a ViewExtra
	 * structure and attach the monitor type to the View.
	 */

	struct View *view = NULL;
	struct ViewExtra *ve = NULL;
	struct MonitorSpec *mspc = NULL;

	if (view = AllocVec(sizeof(struct View), MEMF_PUBLIC | MEMF_CLEAR))
	{
		if (ve = GfxNew(VIEW_EXTRA_TYPE))
		{
			if (mspc = OpenMonitor(NULL, ModeID))
			{
				InitView(view);
				view->DyOffset = v->DyOffset;
				view->DxOffset = v->DxOffset;
				view->Modes = v->Modes;
				GfxAssociate(view, (struct ExtendedNode *)ve);
				ve->Monitor = mspc;
			}
			else printf("Could not open monitor\n");
		}
		else printf("Could not get ViewExtra\n");
	}
	else printf("Could not create View\n");

	if (view && ve && mspc)
		return(view);
	else
	{
		DestroyView(view);
		return(NULL);
	}
}

/**********************************************************************/
/*                                                                    */
/* VOID DestroyViewPort(struct ViewPort *vp)                          */
/*                                                                    */
/* Close and free everything to do with the ViewPort.                 */
/*                                                                    */
/**********************************************************************/

VOID DestroyViewPort(struct ViewPort *vp)
{
	if (vp)
	{
		/* Find the ViewPort's ColorMap. From that use VideoControl
		 *  to get the ViewPortExtra, and free it.
		 * Then free the ColorMap, and finally the ViewPort itself.
		 */
		struct ColorMap *cm = vp->ColorMap;
		struct TagItem ti[] =
		{
			{VTAG_VIEWPORTEXTRA_GET, NULL},	/* <-- This field will be filled in */
			{VTAG_END_CM, NULL}
		};

		if (cm)
		{
			if (VideoControl(cm, ti) == NULL)
				GfxFree((struct ExtendedNode *)ti[0].ti_Data);
			else
				printf("VideoControl error in DestroyViewPort()\n");

			FreeColorMap(cm);
		}
		else
		{
			printf("Could not free the ColorMap\n");
		}

		FreeVPortCopLists(vp);

		FreeVec(vp);
	}
}

/**********************************************************************/
/*                                                                    */
/* struct ViewPort *DupViewPort(struct ViewPort *vp, ULONG ModeID)    */
/*                                                                    */
/* Duplicate the ViewPort.                                            */
/*                                                                    */
/**********************************************************************/

struct ViewPort *DupViewPort(struct ViewPort *vp, ULONG ModeID)
{
	/* Allocate and initialise a ViewPort. Copy the ViewPort width and
	 * heights, offsets, and modes values.  Allocate and initialize a
	 * ColorMap.
	 *
	 * Also, allocate a ViewPortExtra, and copy the TextOScan values of the
	 * ModeID from the database into the ViewPortExtra.
	 */

	#define COLOURS 32
	struct ViewPort *Myvp;
	struct ViewPortExtra *vpe;
	struct ColorMap *cm;
	struct TagItem ti[] = 			/* to attach everything */
	{
		{VTAG_ATTACH_CM_SET, NULL},	/* these NULLs will be replaced in the code */
		{VTAG_VIEWPORTEXTRA_SET, NULL},
		{VTAG_NORMAL_DISP_SET, NULL},
		{VTAG_END_CM, NULL}
	};
	struct DimensionInfo query = {0};
	UWORD colour;
	int c;
	ULONG gotinfo = NULL;

	if (Myvp = AllocVec(sizeof(struct ViewPort), MEMF_CLEAR | MEMF_PUBLIC))
	{
		if (vpe = (struct ViewPortExtra *)GfxNew(VIEWPORT_EXTRA_TYPE))
		{
			if (cm = GetColorMap(32))
			{
				if (gotinfo = GetDisplayInfoData(NULL, (APTR)&query,
                                                                 sizeof(query), DTAG_DIMS, ModeID))
				{
					InitVPort(Myvp);

					/* duplicate the ViewPort structure */
					Myvp->DWidth = vp->DWidth;
					Myvp->DHeight = vp->DHeight;
					Myvp->DxOffset = vp->DxOffset;
					Myvp->DyOffset = vp->DyOffset;
					Myvp->Modes = vp->Modes;
					Myvp->SpritePriorities = vp->SpritePriorities;
					Myvp->ExtendedModes = vp->ExtendedModes;

					/* duplicate the Overscan values */
					vpe->DisplayClip = query.TxtOScan;

					/* attach everything together */
					ti[0].ti_Data = (ULONG)Myvp;
					ti[1].ti_Data = (ULONG)vpe;
					ti[2].ti_Data = (ULONG)FindDisplayInfo(ModeID);
					if (VideoControl(cm, ti) != NULL)
					{
						printf("VideoControl error in CreateViewPort()\n");
					}

					/* copy the colours from the workbench */
					for (c = 0; c < COLOURS; c++)
					{
						if ((colour = GetRGB4(vp->ColorMap, c)) != -1)
						{
						SetRGB4CM(cm, c, (colour >> 8),
							  ((colour >> 4) & 0xf), (colour & 0xf));
						}
					}
				}
				else printf("Database error\n");
			}
			else printf("Could not get the ColorMap\n");
		}
		else printf("Could not get the ViewPortExtra\n");
	}
	else printf("Could not get the ViewPort\n");

	if (Myvp && vpe && cm && gotinfo)
		return(Myvp);
	else
	{
		DestroyViewPort(vp);
		return(NULL);
	}
}

/***********************************************************************************/
/*                                                                                 */
/* VOID DestroyBitMap(struct BitMap *Mybm, SHORT width, SHORT height, SHORT depth) */
/*                                                                                 */
/* Close and free everything to do with the BitMap                                 */
/*                                                                                 */
/***********************************************************************************/

VOID DestroyBitMap(struct BitMap *Mybm, SHORT width, SHORT height, SHORT depth)
{
	int i;

	if (Mybm)
	{
		for (i = 0; (i < depth); i++)
		{
			if (Mybm->Planes[i])
				FreeRaster(Mybm->Planes[i], width, height);
		}
		FreeVec(Mybm);
	}
}

/***********************************************************************/
/*                                                                     */
/* struct BitMap *CreateBitMap(SHORT width, SHORT height, SHORT depth) */
/*                                                                     */
/* Create the BitMap.                                                  */
/*                                                                     */
/***********************************************************************/

struct BitMap *CreateBitMap(SHORT width, SHORT height, SHORT depth)
{
	/* Allocate a BitMap structure, initialise it, and allocate each plane. */

	struct BitMap *Mybm;
	PLANEPTR allocated = (PLANEPTR) 1;
	int i;

	if (Mybm = AllocVec(sizeof(struct BitMap), MEMF_CLEAR | MEMF_PUBLIC))
	{
		InitBitMap(Mybm, depth, width, height);
		for (i = 0; ((i < depth) && (allocated)); i++)
			allocated = (Mybm->Planes[i] = AllocRaster(width, height));

		if (allocated == NULL)
		{
			printf("Could not allocate all the planes\n");
			DestroyBitMap(Mybm, width, height, depth);
			Mybm = NULL;
		}
	}
	else printf("Could not get BitMap\n");

	return(Mybm);
}

/********************************************************************************/
/*                                                                              */
/* VOID ShowView(struct View *view, struct ViewPort *vp, struct BitMap *bm,    */
/*                                                SHORT width, SHORT height)    */
/*                                                                              */
/* Assemble and display the View.                                               */
/*                                                                              */
/********************************************************************************/

VOID ShowView(struct View *view, struct ViewPort *vp, struct BitMap *bm,
                                               SHORT width, SHORT height)
{
	/* Attach the BitMap to the ViewPort via a RasInfo.  Attach the ViewPort
	 * to the View.  Clear the BitMap, and draw into it by attaching the BitMap
	 * to a RastPort.  Then MakeVPort(), MrgCop() and LoadView().
	 * Just wait for the user to press <RETURN> before returning.
	 */

	struct RastPort *rp;
	struct RasInfo *ri;

	if (rp = AllocVec(sizeof(struct RastPort), MEMF_CLEAR | MEMF_PUBLIC))
	{
		if (ri = AllocVec(sizeof(struct RasInfo), MEMF_CLEAR | MEMF_PUBLIC))
		{
			InitRastPort(rp);
			ri->BitMap = rp->BitMap = bm;
			vp->RasInfo = ri;
			view->ViewPort = vp;

			/* render */
			SetRast(rp, 0);		/* clear the background */
			SetAPen(rp, ((1 << bm->Depth) - 1));	/* use the last pen */
			Move(rp, 0, 0);
			Draw(rp, width, 0);
			Draw(rp, width, height);
			Draw(rp, 0, height);
			Draw(rp, 0, 0);

			/* display it */
			MakeVPort(view, vp);
			MrgCop(view);
			LoadView(view);

			getchar();

			/* bring back the system */
			RethinkDisplay();

			FreeVec(ri);
		}
		else printf("Could not get RasInfo\n");

		FreeVec(rp);
	}
	else printf("Could not get RastPort\n");

}

/**********************************************************************/
/*                                                                    */
/* VOID main (int argc, char *argv[])                                 */
/*                                                                    */
/* Clone the Workbench View using Graphics Library calls.             */
/*                                                                    */
/**********************************************************************/

VOID main (int argc, char *argv[])
{
	struct Screen *wb;
	struct View *Myview;
	struct ViewPort *Myvp;
	struct BitMap *Mybm;
	ULONG ModeID;
	ULONG IbaseLock;

	Init () ;		/* to open the libraries */

	/* To clone the Workbench using graphics calls involves duplicating
	 * the Workbench ViewPort, ViewPort mode, and Intuition's View.
	 * This also involves duplicating the DisplayClip for the overscan
	 * value, the colours, and the View position.
	 *
	 * When this is all done, the View, ViewPort, ColorMap and BitMap
	 * (and ViewPortExtra, ViewExtra and RasInfo) all have to be linked
	 * together, and the copperlists made to create the display.
	 *
	 * This is not as difficult as it sounds (trust me!)
	 */

	/* First, lock the Workbench screen, so no changes can be made to it
	 * while we are duplicating it.
	 */
	if (wb = LockPubScreen("Workbench"))
	{
		/* Find the Workbench's ModeID. This is a 32-bit number that
		 * identifies the monitor type, and the display mode of that monitor.
		 */
		ModeID = GetVPModeID(&wb->ViewPort);

		/* We need to duplicate Intuition's View structure, so lock IntuitionBase
		 * to prevent the View changing under our feet.
		 */
		IbaseLock = LockIBase(0);
		if (Myview = DupView(&IntuitionBase->ViewLord, ModeID))
		{
			/* The View has been cloned, so we don't need to keep it locked. */
			UnlockIBase(IbaseLock);

			/* Now duplicate the Workbench's ViewPort. Remember, we still have
			 * the Workbench locked.
			 */
			if (Myvp = DupViewPort(&wb->ViewPort, ModeID))
			{
				/* Create a BitMap to render into. This will be of the
				 * same dimensions as the Workbench.
				 */
				if (Mybm = CreateBitMap(wb->Width, wb->Height, wb->BitMap.Depth))
				{
					/* Now we have everything copied, show something */
					ShowView(Myview, Myvp, Mybm, wb->Width-1, wb->Height-1);

					/* Now free up everything we have allocated */
					DestroyBitMap(Mybm, wb->Width, wb->Height, wb->BitMap.Depth);
				}
				DestroyViewPort(Myvp);
			}
			DestroyView(Myview);
		}
		else
		{
			UnlockIBase(IbaseLock);
		}
		UnlockPubScreen(NULL, wb);
	}
	CloseAll () ;
}