/* 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 () ; }