Code: Select all
/* clipping.c */
/* Force use of new variable names to help prevent errors */
#define INTUI_V36_NAMES_ONLY
#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <graphics/displayinfo.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/layers.h>
#define MY_WIN_WIDTH (300)
#define MY_WIN_HEIGHT (100)
struct IntuitionIFace *IIntuition;
struct GraphicsIFace *IGraphics;
struct LayersIFace *ILayers;
/*
** unclipWindow()
**
** Used to remove a clipping region installed by clipWindow() or
** clipWindowToBorders(), disposing of the installed region and
** reinstalling the region removed.
*/
void unclipWindow(struct Window *win)
{
struct Region *old_region;
/* Remove any old region by installing a NULL region,
** then dispose of the old region if one was installed.
*/
if (NULL != (old_region = ILayers->InstallClipRegion(win->WLayer, NULL)))
IGraphics->DisposeRegion(old_region);
}
/*
** clipWindow()
** Clip a window to a specified rectangle (given by upper left and
** lower right corner.) the removed region is returned so that it
** may be re-installed later.
*/
struct Region *clipWindow(struct Window *win,
LONG minX, LONG minY, LONG maxX, LONG maxY)
{
struct Region *new_region;
struct Rectangle my_rectangle;
/* set up the limits for the clip */
my_rectangle.MinX = minX;
my_rectangle.MinY = minY;
my_rectangle.MaxX = maxX;
my_rectangle.MaxY = maxY;
/* get a new region and OR in the limits. */
if (NULL != (new_region = IGraphics->NewRegion()))
{
if (FALSE == IGraphics->OrRectRegion(new_region, &my_rectangle))
{
IGraphics->DisposeRegion(new_region);
new_region = NULL;
}
}
/* Install the new region, and return any existing region.
** If the above allocation and region processing failed, then
** new_region will be NULL and no clip region will be installed.
*/
return(ILayers->InstallClipRegion(win->WLayer, new_region));
}
/*
** clipWindowToBorders()
** clip a window to its borders.
** The removed region is returned so that it may be re-installed later.
*/
struct Region *clipWindowToBorders(struct Window *win)
{
return(clipWindow(win, win->BorderLeft, win->BorderTop,
win->Width - win->BorderRight - 1, win->Height - win->BorderBottom - 1));
}
/*
** Wait for the user to select the close gadget.
*/
VOID wait_for_close(struct Window *win)
{
struct IntuiMessage *msg;
SHORT done;
done = FALSE;
while (FALSE == done)
{
/* we only have one signal bit, so we do not have to check which
** bit broke the Wait().
*/
IExec->Wait(1L << win->UserPort->mp_SigBit);
while ( (FALSE == done) &&
(NULL != (msg = (struct IntuiMessage *)IExec->GetMsg(win->UserPort))))
{
/* use a switch statement if looking for multiple event types */
if (msg->Class == IDCMP_CLOSEWINDOW)
done = TRUE;
IExec->ReplyMsg((struct Message *)msg);
}
}
}
/*
** Simple routine to blast all bits in a window with color three to show
** where the window is clipped. After a delay, flush back to color zero
** and refresh the window borders.
*/
VOID draw_in_window(struct Window *win, UBYTE *message)
{
IDOS->Printf("%s...", message);
IGraphics->SetRast(win->RPort, 3);
IDOS->Delay(200);
IGraphics->SetRast(win->RPort, 0);
IIntuition->RefreshWindowFrame(win);
IDOS->Printf("done\n");
}
/*
** Show drawing into an unclipped window, a window clipped to the
** borders and a window clipped to a random rectangle. It is possible
** to clip more complex shapes by AND'ing, OR'ing and exclusive-OR'ing
** regions and rectangles to build a user clip region.
**
** This example assumes that old regions are not going to be re-used,
** so it simply throws them away.
*/
VOID clip_test(struct Window *win)
{
struct Region *old_region;
draw_in_window(win,"Window with no clipping");
/* if the application has never installed a user clip region,
** then old_region will be NULL here. Otherwise, delete the
** old region (you could save it and re-install it later...)
*/
if (NULL != (old_region = clipWindowToBorders(win)))
IGraphics->DisposeRegion(old_region);
draw_in_window(win,"Window clipped to window borders");
unclipWindow(win);
/* here we know old_region will be NULL, as that is what we
** installed with unclipWindow()...
*/
if (NULL != (old_region = clipWindow(win,20,20,100,50)))
IGraphics->DisposeRegion(old_region);
draw_in_window(win,"Window clipped from (20,20) to (100,50)");
unclipWindow(win);
wait_for_close(win);
}
/*
** Open and close resources, call the test routine when ready.
*/
int main(int argc, char **argv)
{
struct Window *win;
struct Library *IntuitionBase = IExec->OpenLibrary("intuition.library", 50);
IIntuition = (struct IntuitionIFace*)IExec->GetInterface(IntuitionBase, "main", 1, NULL);
struct Library *GfxBase = IExec->OpenLibrary("graphics.library", 50);
IGraphics = (struct GraphicsIFace*)IExec->GetInterface(GfxBase, "main", 1, NULL);
struct Library *LayersBase = IExec->OpenLibrary("layers.library", 50);
ILayers = (struct LayersIFace*)IExec->GetInterface(LayersBase, "main", 1, NULL);
if (IIntuition != NULL && IGraphics != NULL && ILayers != NULL)
{
if (NULL != (win =IIntuition->OpenWindowTags(NULL,
WA_Width, MY_WIN_WIDTH,
WA_Height, MY_WIN_HEIGHT,
WA_IDCMP, IDCMP_CLOSEWINDOW,
WA_CloseGadget, TRUE,
WA_DragBar, TRUE,
WA_Activate, TRUE,
TAG_END)))
{
clip_test(win);
IIntuition->CloseWindow(win);
}
}
IExec->DropInterface((struct Interface*)ILayers);
IExec->CloseLibrary(LayersBase);
IExec->DropInterface((struct Interface*)IGraphics);
IExec->CloseLibrary(GfxBase);
IExec->DropInterface((struct Interface*)IIntuition);
IExec->CloseLibrary(IntuitionBase);
return 0;
}