;/* lines.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 lines.c
Blink FROM LIB:c.o,lines.o TO lines LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
**
** This example shows how to implement a superbitmap, and uses a host of
** Intuition facilities. Further reading of other Intuition and graphics
** chapters may be required for a complete understanding of this example.
**
** lines.c -- implements a superbitmap with scroll gadgets
** This program requires V37, as it uses calls to OpenWindowTags(),
** LockPubScreen().
*/
/* Enforces use of new prefixed Intuition flag names */
#define INTUI_V36_NAMES_ONLY
#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <clib/exec_protos.h>
#include <clib/layers_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
/* Random number function in amiga.lib (see amiga.lib.doc) */
UWORD RangeRand( unsigned long maxValue );
#ifdef LATTICE
int CXBRK(void) { return(0); } /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); } /* really */
#endif
#define WIDTH_SUPER (800)
#define HEIGHT_SUPER (600)
#define UP_DOWN_GADGET (0)
#define LEFT_RIGHT_GADGET (1)
#define NO_GADGET (2)
#define MAXPROPVAL (0xFFFFL)
#define GADGETID(x) (((struct Gadget *)(msg->IAddress))->GadgetID)
#define LAYERXOFFSET(x) (x->RPort->Layer->Scroll_X)
#define LAYERYOFFSET(x) (x->RPort->Layer->Scroll_Y)
/* A string with this format will be found by the version command
** supplied by Amiga, Inc. This will allow users to give version
** numbers with error reports.
*/
UBYTE vers[] = "$VER: lines 37.2";
struct Library *GfxBase;
struct Library *IntuitionBase;
struct Library *LayersBase;
struct Window *Win = NULL; /* window pointer */
struct PropInfo BotGadInfo = {0};
struct Image BotGadImage = {0};
struct Gadget BotGad = {0};
struct PropInfo SideGadInfo = {0};
struct Image SideGadImage = {0};
struct Gadget SideGad = {0};
/* Prototypes for our functions */
VOID initBorderProps(struct Screen *myscreen);
VOID doNewSize(void);
VOID doDrawStuff(void);
VOID doMsgLoop(void);
VOID superWindow(struct Screen *myscreen);
/*
** main
** Open all required libraries and get a pointer to the default public screen.
** Cleanup when done or on error.
*/
VOID main(int argc, char **argv)
{
struct Screen *myscreen;
/* open all of the required libraries for the program.
**
** require version 37 of the Intuition library.
*/
if (IntuitionBase = OpenLibrary("intuition.library",37L))
{
if (GfxBase = OpenLibrary("graphics.library",33L))
{
if (LayersBase = OpenLibrary("layers.library",33L))
{
/* LockPubScreen()/UnlockPubScreen is only available under V36
** and later... Use GetScreenData() under V34 systems to get a
** copy of the screen structure...
*/
if (NULL != (myscreen = LockPubScreen(NULL)))
{
superWindow(myscreen);
UnlockPubScreen(NULL,myscreen);
}
CloseLibrary(LayersBase);
}
CloseLibrary(GfxBase);
}
CloseLibrary(IntuitionBase);
}
}
/*
** Create, initialize and process the super bitmap window.
** Cleanup if any error.
*/
VOID superWindow(struct Screen *myscreen)
{
struct BitMap *bigBitMap;
WORD planeNum;
WORD allocatedBitMaps;
/* set-up the border prop gadgets for the OpenWindow() call. */
initBorderProps(myscreen);
/* The code relies on the allocation of the BitMap structure with
** the MEMF_CLEAR flag. This allows the assumption that all of the
** bitmap pointers are NULL, except those successfully allocated
** by the program.
*/
if (bigBitMap = AllocMem(sizeof(struct BitMap), MEMF_PUBLIC | MEMF_CLEAR))
{
InitBitMap(bigBitMap, myscreen->BitMap.Depth, WIDTH_SUPER, HEIGHT_SUPER);
allocatedBitMaps = TRUE;
for (planeNum = 0;
(planeNum < myscreen->BitMap.Depth) && (allocatedBitMaps == TRUE);
planeNum++)
{
bigBitMap->Planes[planeNum] = AllocRaster(WIDTH_SUPER, HEIGHT_SUPER);
if (NULL == bigBitMap->Planes[planeNum])
allocatedBitMaps = FALSE;
}
/* Only open the window if the bitplanes were successfully
** allocated. Fail silently if they were not.
*/
if (TRUE == allocatedBitMaps)
{
/* OpenWindowTags() and OpenWindowTagList() are only available
** when the library version is at least V36. Under earlier
** versions of Intuition, use OpenWindow() with a NewWindow
** structure.
*/
if (NULL != (Win = OpenWindowTags(NULL,
WA_Width, 150,
WA_Height, 4 * (myscreen->WBorTop + myscreen->Font->ta_YSize + 1),
WA_MaxWidth, WIDTH_SUPER,
WA_MaxHeight, HEIGHT_SUPER,
WA_IDCMP, IDCMP_GADGETUP | IDCMP_GADGETDOWN |
IDCMP_NEWSIZE | IDCMP_INTUITICKS | IDCMP_CLOSEWINDOW,
WA_Flags, WFLG_SIZEGADGET | WFLG_SIZEBRIGHT | WFLG_SIZEBBOTTOM |
WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET |
WFLG_SUPER_BITMAP | WFLG_GIMMEZEROZERO | WFLG_NOCAREREFRESH,
WA_Gadgets, &(SideGad),
WA_Title, &vers[6], /* take title from version string */
WA_PubScreen, myscreen,
WA_SuperBitMap, bigBitMap,
TAG_DONE)))
{
/* set-up the window display */
SetRast(Win->RPort,0); /* clear the bitplanes */
SetDrMd(Win->RPort,JAM1);
doNewSize(); /* adjust props to represent portion visible */
doDrawStuff();
/* process the window, return on IDCMP_CLOSEWINDOW */
doMsgLoop();
CloseWindow(Win);
}
}
for (planeNum = 0; planeNum < myscreen->BitMap.Depth; planeNum++)
{
/* free only the bitplanes actually allocated... */
if (NULL != bigBitMap->Planes[planeNum])
FreeRaster(bigBitMap->Planes[planeNum], WIDTH_SUPER, HEIGHT_SUPER);
}
FreeMem(bigBitMap,sizeof(struct BitMap));
}
}
/*
** Set-up the prop gadgets--initialize them to values that fit
** into the window border. The height of the prop gadget on the side
** of the window takes the height of the title bar into account in its
** set-up. note the initialization assumes a fixed size "sizing" gadget.
**
** Note also, that the size of the sizing gadget is dependent on the
** screen resolution. The numbers given here are only valid if the
** screen is NOT lo-res. These values must be re-worked slightly
** for lo-res screens.
**
** The PROPNEWLOOK flag is ignored by 1.3.
*/
VOID initBorderProps(struct Screen *myscreen)
{
/* initializes the two prop gadgets.
**
** Note where the PROPNEWLOOK flag goes. Adding this flag requires
** no extra storage, but tells the system that our program is
** expecting the new-look prop gadgets under 2.0.
*/
BotGadInfo.Flags = AUTOKNOB | FREEHORIZ | PROPNEWLOOK;
BotGadInfo.HorizPot = 0;
BotGadInfo.VertPot = 0;
BotGadInfo.HorizBody = -1;
BotGadInfo.VertBody = -1;
BotGad.LeftEdge = 3;
BotGad.TopEdge = -7;
BotGad.Width = -23;
BotGad.Height = 6;
BotGad.Flags = GFLG_RELBOTTOM | GFLG_RELWIDTH;
BotGad.Activation = GACT_RELVERIFY | GACT_IMMEDIATE | GACT_BOTTOMBORDER;
BotGad.GadgetType = GTYP_PROPGADGET | GTYP_GZZGADGET;
BotGad.GadgetRender = (APTR)&(BotGadImage);
BotGad.SpecialInfo = (APTR)&(BotGadInfo);
BotGad.GadgetID = LEFT_RIGHT_GADGET;
SideGadInfo.Flags = AUTOKNOB | FREEVERT | PROPNEWLOOK;
SideGadInfo.HorizPot = 0;
SideGadInfo.VertPot = 0;
SideGadInfo.HorizBody = -1;
SideGadInfo.VertBody = -1;
/* NOTE the TopEdge adjustment for the border and the font for V36.
*/
SideGad.LeftEdge = -14;
SideGad.TopEdge = myscreen->WBorTop + myscreen->Font->ta_YSize + 2;
SideGad.Width = 12;
SideGad.Height = -SideGad.TopEdge - 11;
SideGad.Flags = GFLG_RELRIGHT | GFLG_RELHEIGHT;
SideGad.Activation = GACT_RELVERIFY | GACT_IMMEDIATE | GACT_RIGHTBORDER;
SideGad.GadgetType = GTYP_PROPGADGET | GTYP_GZZGADGET;
SideGad.GadgetRender = (APTR)&(SideGadImage);
SideGad.SpecialInfo = (APTR)&(SideGadInfo);
SideGad.GadgetID = UP_DOWN_GADGET;
SideGad.NextGadget = &(BotGad);
}
/*
** This function does all the work of drawing the lines
*/
VOID doDrawStuff()
{
WORD x1,y1,x2,y2;
WORD pen,ncolors,deltx,delty;
ncolors = 1 << Win->WScreen->BitMap.Depth;
deltx = RangeRand(6)+2;
delty = RangeRand(6)+2;
pen = RangeRand(ncolors-1) + 1;
SetAPen(Win->RPort,pen);
for(x1=0, y1=0, x2=WIDTH_SUPER-1, y2=HEIGHT_SUPER-1;
x1 < WIDTH_SUPER;
x1 += deltx, x2 -= deltx)
{
Move(Win->RPort,x1,y1);
Draw(Win->RPort,x2,y2);
}
pen = RangeRand(ncolors-1) + 1;
SetAPen(Win->RPort,pen);
for(x1=0, y1=0, x2=WIDTH_SUPER-1, y2=HEIGHT_SUPER-1;
y1 < HEIGHT_SUPER;
y1 += delty, y2 -= delty)
{
Move(Win->RPort,x1,y1);
Draw(Win->RPort,x2,y2);
}
}
/*
** This function provides a simple interface to ScrollLayer
*/
VOID slideBitMap(WORD Dx,WORD Dy)
{
ScrollLayer(0,Win->RPort->Layer,Dx,Dy);
}
/*
** Update the prop gadgets and bitmap positioning when the size changes.
*/
VOID doNewSize()
{
ULONG tmp;
tmp = LAYERXOFFSET(Win) + Win->GZZWidth;
if (tmp >= WIDTH_SUPER)
slideBitMap(WIDTH_SUPER-tmp,0);
NewModifyProp(&(BotGad),Win,NULL,AUTOKNOB | FREEHORIZ,
((LAYERXOFFSET(Win) * MAXPROPVAL) /
(WIDTH_SUPER - Win->GZZWidth)),
NULL,
((Win->GZZWidth * MAXPROPVAL) / WIDTH_SUPER),
MAXPROPVAL,
1);
tmp = LAYERYOFFSET(Win) + Win->GZZHeight;
if (tmp >= HEIGHT_SUPER)
slideBitMap(0,HEIGHT_SUPER-tmp);
NewModifyProp(&(SideGad),Win,NULL,AUTOKNOB | FREEVERT,
NULL,
((LAYERYOFFSET(Win) * MAXPROPVAL) /
(HEIGHT_SUPER - Win->GZZHeight)),
MAXPROPVAL,
((Win->GZZHeight * MAXPROPVAL) / HEIGHT_SUPER),
1);
}
/*
** Process the currently selected gadget.
** This is called from IDCMP_INTUITICKS and when the gadget is released
** IDCMP_GADGETUP.
*/
VOID checkGadget(UWORD gadgetID)
{
ULONG tmp;
WORD dX = 0;
WORD dY = 0;
switch (gadgetID)
{
case UP_DOWN_GADGET:
tmp = HEIGHT_SUPER - Win->GZZHeight;
tmp = tmp * SideGadInfo.VertPot;
tmp = tmp / MAXPROPVAL;
dY = tmp - LAYERYOFFSET(Win);
break;
case LEFT_RIGHT_GADGET:
tmp = WIDTH_SUPER - Win->GZZWidth;
tmp = tmp * BotGadInfo.HorizPot;
tmp = tmp / MAXPROPVAL;
dX = tmp - LAYERXOFFSET(Win);
break;
}
if (dX || dY)
slideBitMap(dX,dY);
}
/*
** Main message loop for the window.
*/
VOID doMsgLoop()
{
struct IntuiMessage *msg;
WORD flag = TRUE;
UWORD currentGadget = NO_GADGET;
while (flag)
{
/* Whenever you want to wait on just one message port */
/* you can use WaitPort(). WaitPort() doesn't require */
/* the setting of a signal bit. The only argument it */
/* requires is the pointer to the window's UserPort */
WaitPort(Win->UserPort);
while (msg = (struct IntuiMessage *)GetMsg(Win->UserPort))
{
switch (msg->Class)
{
case IDCMP_CLOSEWINDOW:
flag = FALSE;
break;
case IDCMP_NEWSIZE:
doNewSize();
doDrawStuff();
break;
case IDCMP_GADGETDOWN:
currentGadget = GADGETID(msg);
break;
case IDCMP_GADGETUP:
checkGadget(currentGadget);
currentGadget = NO_GADGET;
break;
case IDCMP_INTUITICKS:
checkGadget(currentGadget);
break;
}
ReplyMsg((struct Message *)msg);
}
}
}