home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
500-599
/
ff502.lzh
/
CELLS
/
CELLSSource.lzh
/
cView.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-04-20
|
11KB
|
470 lines
/*
* CELLS An Implementation of the WireWorld cellular automata
* as described in Scientific American, Jan 1990.
*
* Copyright 1990 by Davide P. Cervone.
* You may use this code, provided this copyright notice is kept intact.
* See the CELLS.HELP file for complete information on distribution conditions.
*/
/*
* File: cView.c Handles the VIEW mode of the Load PArt requester.
*/
#include "cGadget.h"
#include "cRequest.h"
#include "cReqLP.h"
#include "cParts.h"
#define IMAGEW (LP_PNAMEW-2)
#define IMAGEH (LP_PNAMEH-2)
#define BOXSIZE 4
#define BOXW ((IMAGEW-3)/BOXSIZE)
#define BOXH ((IMAGEH-3)/BOXSIZE)
#define SCROLLDELAY 6
#define SLIDERINFO ((struct PropInfo *)(theList->Slider->SpecialInfo))
/*
* Image structure used to draw the small picture of the parts
*/
static struct Image ViewImage =
{1,1, IMAGEW,IMAGEH,SCREEND, NULL, 0xFF, 0x00, NULL};
int Viewing; /* TRUE if in VIEW mode */
static LISTINFO *ActiveList; /* which list's slider is active */
extern void LPGadgetUp(),LPGadgetDown(),DoListMouse();
/*
* PartToImage()
*
* Clear the image to the background color
* If the part fits within the image, center it, otherwise, clip it
* Set the drawing mode
* for each cell in the part
* if the cell is within the visible area of the part within the image
* if the cell is non-zero
* fill in the cell in the image
*/
static void PartToImage(rp,thePart)
struct RastPort *rp;
PART *thePart;
{
register short X,Y;
register UBYTE *theByte = thePart->Data;
short x,y,w,h;
short dx,dy;
short Bx,By;
SetRast(rp,BACKGROUND);
if (thePart->w > BOXW)
{
x = (thePart->w - BOXW) / 2;
w = BOXW + x;
dx = 2;
} else {
x = 0;
w = thePart->w;
dx = (BOXW - w) / 2 * BOXSIZE + 2;
}
if (thePart->h > BOXH)
{
y = (thePart->h - BOXH) / 2;
h = BOXH + y;
dy = 2;
} else {
y = 0;
h = thePart->h;
dy = (BOXH - h) / 2 * BOXSIZE + 2;
}
SetDrMd(rp,JAM1);
for (Y=0; Y<thePart->h; Y++)
{
for (X=0; X<thePart->w; X++,theByte++)
{
if (X >= x && X < w && Y >= y && Y < h)
{
if (*theByte)
{
Bx = dx + BOXSIZE * (X - x);
By = dy + BOXSIZE * (Y - y);
SetAPen(rp,(int)(*theByte));
RectFill(rp,Bx,By,Bx+BOXSIZE-2,By+BOXSIZE-2);
}
}
}
}
}
/*
* SetViewImage()
*
* Set up the list to point to this item
* If the item exists
* set the list to select this item
* get the part's image
* show the part's name
* otherwise
* clear the image area and name
* If the Load Part requester is up, refresh the gadgets
*/
static void SetViewImage(theList,theItem)
LISTINFO *theList;
LISTITEM *theItem;
{
theList->ItemTop = theItem;
if (theItem)
{
theList->ItemSelect = theItem;
theList->SelectedItem = theList->TopItem;
PartToImage(irp,theItem);
SetStringInfo(theList->Name,theItem->Name);
} else {
SetRast(irp,FOREGROUND);
SetStringInfo(theList->Name,"");
}
if (ActiveRequest)
{
RefreshGList(theList->Gadget,myWindow,theList->Request,1);
RefreshGList(theList->Name,myWindow,theList->Request,1);
}
}
/*
* UpdateViewSlider()
*
* Calculate the new body and pot values for the current list position
* If the Load Part requester is up,
* if the values are not the current ones, update the slider gadget
* otherwise
* set the slider values to the new values
*/
void UpdateViewSlider(theList)
LISTINFO *theList;
{
int Pot,Body;
if (theList->ListLen > 1)
{
Body = 0xFFFF / theList->ListLen;
Pot = 0xFFFF * theList->TopItem / (theList->ListLen - 1);
} else {
Body = 0xFFFF;
Pot = 0;
}
if (ActiveRequest)
{
if (Body != SLIDERINFO->VertBody || Pot != SLIDERINFO->VertPot)
NewModifyProp(theList->Slider,myWindow,theList->Request,
SLIDERINFO->Flags,0,Pot,0,Body,1);
} else {
SLIDERINFO->VertBody = Body;
SLIDERINFO->VertPot = Pot;
}
}
/*
* RemoveViewItem()
*
* Decrease the list length
* If the deleted item is the head of the list, set the head to the next one
* if the deleted item is the displayed item,
* select the next item in the list, if possible, and the previous
* item if not, and NULL, if no previous or next item.
* otherwise, if the deleted item is before the top item in the list,
* decrement the top item counter to reflect the deletion
* Unselect the item, if it was selected
* Show the new selected item
* Update the sliders to the new position and length
*/
void RemoveViewItem(theList,theItem)
LISTINFO *theList;
LISTITEM *theItem;
{
LISTITEM *ItemTop = theList->ItemTop;
theList->ListLen--;
if (theItem == theList->Item) theList->Item = theItem->Prev;
if (theItem == ItemTop)
{
if (ItemTop->Prev)
{
ItemTop = ItemTop->Prev;
} else {
ItemTop = ItemTop->Next;
if (theList->TopItem) theList->TopItem--;
}
} else if (ItemBeforeTop(theItem,ItemTop)) {
theList->TopItem--;
}
if (theList->ItemSelect) theList->ItemSelect->Flags &= ~LI_SELECTED;
theList->ItemSelect = NULL;
SetViewImage(theList,ItemTop);
UpdateViewSlider(theList);
}
/*
* SetView()
*
* Initialise the list manager to use the given list
* setup the image of the current item
* update the sliders to their new position and size
*/
void SetView(theGadget,theItem,SelectItem)
struct Gadget *theGadget;
LISTITEM *theItem,*SelectItem;
{
LISTINFO *theList = (LISTINFO *)theGadget->UserData;
theItem = InitList(theList,theItem,SelectItem);
SetViewImage(theList,theItem);
UpdateViewSlider(theList);
}
/*
* DoScrollUp()
*
* while the arrow is being held down
* if there are more parts to scroll
* move to the next part and display it
* update the sliders
* delay (if necessary)
*/
void DoViewScrollUp(theList,theGadget,theMessage)
LISTINFO *theList;
struct Gadget *theGadget;
struct IntuiMessage *theMessage;
{
while (theGadget->Flags & SELECTED)
{
if (theList->TopItem)
{
theList->TopItem--;
SetViewImage(theList,theList->ItemTop->Next);
RefreshGList(theList->Gadget,myWindow,theList->Request,1);
UpdateViewSlider(theList);
#if SCROLLDELAY > 0
Delay(SCROLLDELAY);
#endif
}
}
}
/*
* DoScrollDown()
*
* while the arrow is being held down
* if there are more parts to scroll
* move to the next part and display it
* update the sliders
* delay (if necessary)
*/
void DoViewScrollDown(theList,theGadget,theMessage)
LISTINFO *theList;
struct Gadget *theGadget;
struct IntuiMessage *theMessage;
{
while (theGadget->Flags & SELECTED)
{
if (theList->TopItem + 1 < theList->ListLen)
{
theList->TopItem++;
SetViewImage(theList,theList->ItemTop->Prev);
RefreshGList(theList->Gadget,myWindow,theList->Request,1);
UpdateViewSlider(theList);
#if SCROLLDELAY > 0
Delay(SCROLLDELAY);
#endif
}
}
}
/*
* DoViewSlider()
*
* Find the position in the list of the new slider location
* If the position has changed
* Look through the list until we get to the specified position
* display the proper part image
*/
void DoViewSlider(theList)
LISTINFO *theList;
{
LISTITEM *theItem = theList->Item;
short Top;
short Size = theList->ListLen - 1;
if (Size < 0) Size = 0;
Top = Size * SLIDERINFO->VertPot / 0xFFFF;
if (Top > Size) Top = Size; else if (Top < 0) Top = 0;
if (Top != theList->TopItem)
{
theList->TopItem = Top;
while (Top-- && theItem) theItem = theItem->Prev;
SetViewImage(theList,theItem);
}
}
/*
* ViewGadgetUp()
*
* Do the right thing for gadget up events in VIEW mode:
*
* Parts slider:
* stop getting mouse moves and make no slider as active
* update the slider position
*
* Everything else:
* do the regular gadget up routine
*/
void ViewGadgetUp(theGadget,theMessage)
struct Gadget *theGadget;
struct IntuiMessage *theMessage;
{
switch(theGadget->GadgetID)
{
case LP_PSLIDE:
StopMouseMoves(); ActiveList = NULL;
DoViewSlider(theGadget->UserData);
break;
default:
LPGadgetUp(theGadget,theMessage);
break;
}
}
/*
* ViewGadgetDown()
*
* Do the right thing for gadget down events in VIEW mode:
*
* Ignore hits in the name and parts list gadgets
* Arrows: scroll the parts list in VIEW mode
* Slider: if the knob is hit, start dragging poperations
* Everything else: do the regular gadget down routine
*/
void ViewGadgetDown(theGadget,theMessage)
struct Gadget *theGadget;
struct IntuiMessage *theMessage;
{
LISTINFO *theList;
switch(theGadget->GadgetID)
{
case LP_PNAMES:
case LP_NAME:
break;
case LP_PUARROW:
DoViewScrollUp(theGadget->UserData,theGadget,theMessage);
break;
case LP_PDARROW:
DoViewScrollDown(theGadget->UserData,theGadget,theMessage);
break;
case LP_PSLIDE:
theList = (LISTINFO *)theGadget->UserData;
if (SLIDERINFO->Flags & KNOBHIT)
{
DoViewSlider(theList);
StartMouseMoves();
ActiveList = theList;
}
break;
default:
LPGadgetDown(theGadget,theMessage);
break;
}
}
/*
* DoViewMouse()
*
* if a list is active, do the slider operation in VIEW mode
*/
void DoViewMouse(MouseX,MouseY,theMessage)
short MouseX,MouseY;
struct IntuiMessage *theMessage;
{
if (ActiveList) DoViewSlider(ActiveList);
}
/*
* SetViewMode()
*
* If already in VIEW mode
* clear the image bitmap
* set things up for a text list again
* call the list manager to initialize the list
* change the gadget routines back to normal
* cancel VIEW mode
* Otherwise
* set up the image to use the bitmap data area
* set up the list gadget to use the image
* display the selected part
* set the gadget routines to the VIEW mode routines
* set VIEW mode to TRUE
*/
void SetViewMode(theList,theItem,SelectItem)
LISTINFO *theList;
LISTITEM *theItem;
LISTITEM *SelectItem;
{
if (Viewing)
{
SetRast(irp,FOREGROUND);
RefreshGList(theList->Gadget,myWindow,theList->Request,1);
theList->Gadget->GadgetText = theList->IText;
theList->Gadget->GadgetRender = (APTR)theList->Image;
SetList(theList->Gadget,theItem,SelectItem);
theList->Request->er_GadgetDown = &LPGadgetDown;
theList->Request->er_GadgetUp = &LPGadgetUp;
theList->Request->er_MouseMove = &DoListMouse;
Viewing = FALSE;
} else {
ViewImage.ImageData = (USHORT *)irp->BitMap->Planes[0];
theList->Gadget->GadgetText = NULL;
theList->Gadget->GadgetRender = (APTR)&ViewImage;
SetView(theList->Gadget,theItem,SelectItem);
theList->Request->er_GadgetDown = &ViewGadgetDown;
theList->Request->er_GadgetUp = &ViewGadgetUp;
theList->Request->er_MouseMove = &DoViewMouse;
Viewing = TRUE;
}
}