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