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
/
cLSList.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-04-20
|
16KB
|
639 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: cLSList.c Handles maintenance of File Requester lists
* and miscellaneous gadgets.
*/
#include "Cells.h"
#include "cRequest.h"
#include "cReqLS.h"
#include "cBoxes.h"
#include "cMemory.h"
#include "cDos.h"
extern char LSDirName[];
extern char LSNameBuf[];
extern char DirName[];
static char Message[MAXBUFFER]; /* message box buffer */
static FILEINFO FirstFile; /* list of files for display */
int RequestID; /* type or file requester (save,load) */
extern FILEINFO mSort();
#define LSGADGET LSRequest.er_Request.ReqGadget
/*
* LSMessage()
*
* If a messageis to be displayed
* copy the message into the buffer area and get its length
* set up the gadget to use the new message text
* split the message into two lines if necessary
* center the messages within the message box
* otherwise (no message)
* clear the message area
* Refresh the gadget if the requester is already active
*/
void LSMessage(s,x1,x2,x3,x4,x5,x6)
char *s,*x1,*x2,*x3,*x4,*x5,*x6;
{
struct Gadget *theGadget = &LSGADGET[LS_MESSAGE];
struct IntuiText *theText = (struct IntuiText *)theGadget->UserData;
short Len,i;
Forbid();
if (s)
{
sprintf(Message,s,x1,x2,x3,x4,x5,x6);
Len = strlen(Message);
theGadget->GadgetText = theText;
theGadget->GadgetText->IText = Message;
if (Len > 33)
{
theText[0].NextText = &theText[1];
theText[0].TopEdge = 2;
theText[1].TopEdge = 11;
for (i=33; i>0 && Message[i] != ' '; i--);
if (i == 0) i = 33;
Message[i] = 0;
theText[0].LeftEdge = (LS_MESSAGEW - CHAR_WIDTH*i++) / 2;
theText[1].LeftEdge = (LS_MESSAGEW - CHAR_WIDTH*(Len-i)) / 2;
theText[1].IText = &Message[i];
} else {
theText[0].LeftEdge = (LS_MESSAGEW - CHAR_WIDTH*Len) / 2;
theText[0].TopEdge = 1 + LNAMEH/2;
theText[0].NextText = NULL;
}
} else {
theGadget->GadgetText = NULL;
}
Permit();
if (ActiveRequest == &LSRequest)
RefreshGList(theGadget,myWindow,ActiveRequest,1);
}
/*
* RecallLSMessage()
*
* If the message box has no message being displayed,
* put the gadget text pointer back to the last message shown
* and refresh the gadget
*/
void RecallLSMessage(theGadget)
struct Gadget *theGadget;
{
if (theGadget->GadgetText == NULL)
{
Forbid();
theGadget->GadgetText = (struct IntuiText *)theGadget->UserData;
RefreshGList(theGadget,myWindow,&LSRequest,1);
Permit();
}
}
/*
* SetLSDirName()
*
* If the directory name is too long, copy only the last part, otherwise
* copy the entire name into the directory name gadget and center it
* If the requester is active
* refresh the directory name (twice if it is currently selected, since
* it is a GADGHCOMP gadget)
*/
static void SetLSDirName(Name)
char *Name;
{
struct IntuiText *theText = LSGADGET[LS_DIR].GadgetText;
short Len = strlen(Name);
if (Len > 20) strcpy(LSDirName,&Name[Len-20]); else strcpy(LSDirName,Name);
theText->LeftEdge = (LS_DIRW - CHAR_WIDTH * strlen(Name) - SLIDEWH) / 2;
if (theText->LeftEdge < 3) theText->LeftEdge = 3;
if (ActiveRequest == &LSRequest)
{
if (LSGADGET[LS_DIR].Flags & SELECTED)
RefreshRequest(&LSRequest,LS_DIR,NULL);
RefreshRequest(&LSRequest,LS_DIR,NULL);
}
}
/*
* SetLSTexts()
*
* Get the directory name and set the directory gadget to it
* Set the requester title to the give title and center it
* Set the name and ID of the LOAD/SAVE button
* Set the title of the check gadget and make sure it is not checked
* Set the initial message, if any
* Save the type of requester (SAVE or LOAD) for future reference
*/
void SetLSTexts(Title,Button,Check,ID)
char *Title,*Button,*Check;
int ID;
{
GetProcessDir(DirName);
SetLSDirName(DirName);
LSRequest.er_Request.ReqText->IText = Title;
LSRequest.er_Request.ReqText->LeftEdge =
(LS_PANELW - CHAR_WIDTH * strlen(Title)) / 2;
LSGADGET[LS_LOAD].GadgetText->IText = Button;
LSGADGET[LS_LOAD].GadgetText->LeftEdge = 15;
LSGADGET[LS_LOAD].GadgetID = ID;
LSGADGET[LS_CHECK].GadgetText->IText = Check;
LSGADGET[LS_CHECK].Flags &= ~SELECTED;
if (LSGADGET[LS_NLIST].Flags & GADGDISABLED)
{
LSMessage("Click on Directory Name for a List of Files");
} else {
LSMessage(NULL);
LSGADGET[LS_NLIST].GadgetText = LSListInfo.IText;
UnsetListSelect(&LSListInfo,FALSE);
}
RequestID = ID;
}
/*
* DisableLSList()
*
* If the list is not already disabled
* clear any selection and set the list to a NULL list
* remove the IntuiTexts from the gadget
* make the background gadget full sized
* disable the gadget and its slider and arrows
* refresh the disabled gadgets
*/
void DisableLSList(theGadget)
struct Gadget *theGadget;
{
short i;
if ((theGadget->Flags & GADGDISABLED) == 0)
{
UnsetListSelect(theGadget->UserData,TRUE);
SetList(theGadget,NULL,NULL);
Forbid();
theGadget->GadgetText = NULL;
LSListInfo.Image->PlaneOnOff = BACKGROUND;
LSListInfo.Image->Height = LS_NLISTH-2;
LSListInfo.Image->TopEdge = 1;
for (i=0; i<4; theGadget[i++].Flags |= GADGDISABLED);
RefreshGList(theGadget,myWindow,&LSRequest,4);
Permit();
}
}
/*
* EnableLSList()
*
* If the list is disabled
* Set the list gadget's text to the list's text array
* Reset the gadget's background color (the image is still full size)
* enable the list, its slider and its arrows
* refresh the list and its sliders
* refresh the list border (kludge: the list gadget really should be smaller)
* Now reset the gadget image to its normal height
*/
void EnableLSList(theGadget)
struct Gadget *theGadget;
{
short i;
if (theGadget->Flags & GADGDISABLED);
{
Forbid();
theGadget->GadgetText = LSListInfo.IText;
LSListInfo.Image->PlaneOnOff = FOREGROUND;
for (i=0; i<4; theGadget[i++].Flags &= ~GADGDISABLED);
RefreshGList(theGadget,myWindow,&LSRequest,4);
RefreshRequest(&LSRequest,LS_BRDRGADG,NULL);
LSListInfo.Image->Height = LNAMEH;
Permit();
}
}
/*
* CompareFiles()
*
* Compare two file names to see if they are equal, or which one is
* first alphabetically (NOFIRST is a kludge to ignore the leading '/' in
* directory names). The list is to be sorted in reverse order, so the
* file names are reversed inthe stricmp() call
*/
static CompareFiles(File1,File2)
FILEINFO File1,File2;
{
char *s1 = File1->Name;
char *s2 = File2->Name;
if (File1->Flags & LI_NOFIRST) s1++;
if (File2->Flags & LI_NOFIRST) s2++;
return(stricmp(s2,s1));
}
/*
* FreeFile()
*
* Frees the memory associated with a file name in the directory list
*/
static void FreeFile(theFile)
FILEINFO theFile;
{
if (theFile->Name) FREECHAR(theFile->Name,theFile->NameLen);
FREESTRUCT(FileInfo,theFile);
}
/*
* ClearDirectoryList()
*
* For each file in the list, clear the memory for the file
*/
void ClearDirectoryList()
{
FILEINFO theFile;
while (FirstFile)
{
theFile = FirstFile;
FirstFile = FirstFile->Next;
FreeFile(theFile);
}
}
/*
* FindFile()
*
* Look through the directory list for the given file name (put it into
* a fake file item so that CompareFiles can be used). Returns NULL if
* the file is not in the list.
*/
FILEINFO FindFile(Name)
char *Name;
{
FILEINFO theFile = FirstFile;
int NotFound = TRUE;
struct FileInfo CmpFile;
CmpFile.Name = Name;
while (theFile && NotFound)
{
if (CompareFiles(theFile,&CmpFile) == 0) NotFound = FALSE;
else theFile = theFile->Next;
}
return(theFile);
}
/*
* RemoveFile()
*
* Unlink the file from the directory list, remove the item from the
* list gadget, and free the file's memory
*/
void RemoveFile(theFile)
FILEINFO theFile;
{
if (theFile->Next) theFile->Next->Prev = theFile->Prev;
if (theFile->Prev) theFile->Prev->Next = theFile->Next;
if (theFile == FirstFile) FirstFile = theFile->Next;
RemoveListItem(&LSListInfo,theFile);
FreeFile(theFile);
}
/*
* MakeFile()
*
* If a new FileInfo structure can be allocated
* get the length of the file name
* if the file is a directory, increase the length (for the '/')
* if we can allocate a character string of the given size
* if the file is a directory
* set the file's flags and copy the name preceeeded by a '/'
* otherwise
* just copy the name
* otherwise
* free the structure and return NULL
*/
static FILEINFO MakeFile(Fib)
FIB Fib;
{
FILEINFO theFile = NULL;
if (NEWSTRUCT(FileInfo,theFile))
{
theFile->NameLen = strlen(Fib->fib_FileName);
if (Fib->fib_DirEntryType > 0) theFile->NameLen++;
if (NEWCHAR(theFile->Name,theFile->NameLen))
{
if (Fib->fib_DirEntryType > 0)
{
theFile->Flags = FI_DIRECTORY | LI_NOFIRST;
theFile->Name[0] = '/';
strcpy(&theFile->Name[1],Fib->fib_FileName);
} else {
strcpy(theFile->Name,Fib->fib_FileName);
}
} else {
FREESTRUCT(FileInfo,theFile);
theFile = NULL;
}
}
return(theFile);
}
/*
* MakeDevice()
*
* If a new FileInfo structure can be allocated
* get the device name length plus one (for ':')
* if we can get a characgter string that long
* get the device's name string
* mark the device as a directory (for purposes or openning)
* otherwise
* free the structure and return NULL
*/
static FILEINFO MakeDevice(theDevice)
struct DeviceList *theDevice;
{
FILEINFO theFile = NULL;
if (NEWSTRUCT(FileInfo,theFile))
{
theFile->NameLen = BCPL_TO_SIZE(theDevice->dl_Name)+1;
if (NEWCHAR(theFile->Name,theFile->NameLen))
{
GetDevName(theFile->Name,theDevice);
theFile->Flags = FI_DIRECTORY;
} else {
FREESTRUCT(FileInfo,theFile);
theFile = NULL;
}
}
return(theFile);
}
/*
* AddFile()
*
* If a file was given
* link it into the directory list and increment the length of the list
* otherwise
* give an error message
*/
static int AddFile(theFile,Count)
FILEINFO theFile;
int Count;
{
if (theFile)
{
theFile->Prev = NULL;
theFile->Next = FirstFile;
if (FirstFile) FirstFile->Prev = theFile;
FirstFile = theFile;
Count++;
} else {
LSMessage("Can't Get Memory for File Info");
}
return(Count);
}
/*
* GetDirectoryList()
*
* If the directory can be locked,
* and it can be examined
* Clear the list gadget's contents
* put up a message about reading the directory
* clear the old list
* while there are more files in the directory, add them to the list
* if there was some error while reading the directory
* give the message, otherwise tell how many were read
* sort the list alphabetically
* Unlock the directory
*/
static void GetDirectoryList()
{
short Count = 0;
LOCK lock;
FIB Fib;
if (DosLock(&lock,DirName,TYPE_DIR))
{
if (DosExamine(lock,&Fib,TYPE_DIR))
{
SetList(&LSGADGET[LS_NLIST],NULL,NULL);
LSMessage("Reading Directory...");
ClearDirectoryList();
while (ExNext(lock,Fib))
Count = AddFile(MakeFile(Fib),Count);
if (IoErr() != ERROR_NO_MORE_ENTRIES)
DosError("Read","Directory");
else
LSMessage("%d File%s",Count,(Count == 1)? "": "s");
FirstFile = mSort(FirstFile,&CompareFiles,NULL);
}
UnLock(lock);
}
}
/*
* GetDeviceList()
*
* Put up the message about the device list
* Clear the old list
* Starting at the first device, while ther are more devices in the list
* add the device to the list, and go on to the next item
* (only the MOUNTED devices are listed; i.e., only ones with active tasks)
* Sort the list, and tell how many devices were listed
*/
static void GetDeviceList()
{
short Count = 0;
struct DeviceList *theDevice;
LSMessage("Reading Device List...");
ClearDirectoryList();
Forbid();
theDevice = FIRSTDEV;
while (theDevice)
{
if (theDevice->dl_Task) Count = AddFile(MakeDevice(theDevice),Count);
theDevice = DEVLIST(theDevice->dl_Next);
}
Permit();
FirstFile = mSort(FirstFile,&CompareFiles,NULL);
LSMessage("%d Device%s",Count,(Count == 1)? "": "s");
}
/*
* SetLSDirectory()
*
* Set the directory gadget to the given name
* Clear the file name gadget and refresh it
* If the directory list is active
* get the list of files in the current directory
* remove any selected item, and show the new list
*/
void SetLSDirectory(Name)
char *Name;
{
Forbid();
SetLSDirName(Name);
SetStringInfo(&LSGADGET[LS_NAME],"");
RefreshRequest(&LSRequest,LS_NAME,NULL);
Permit();
if ((LSGADGET[LS_NLIST].Flags & GADGDISABLED) == 0)
{
UnsetListSelect(&LSListInfo,TRUE);
GetDirectoryList();
SetList(&LSGADGET[LS_NLIST],FirstFile,NULL);
}
}
/*
* SetLSDevices()
*
* Set the directory name to blank
* Clear the file name gadget
* If the directory list is active
* get the list of devices
* clear any old selection and show the new list
*/
void SetLSDevices()
{
Forbid();
SetLSDirName("");
SetStringInfo(&LSGADGET[LS_NAME],"");
RefreshRequest(&LSRequest,LS_NAME,NULL);
Permit();
if ((LSGADGET[LS_NLIST].Flags & GADGDISABLED) == 0)
{
GetDeviceList();
UnsetListSelect(&LSListInfo,TRUE);
SetList(&LSGADGET[LS_NLIST],FirstFile,NULL);
}
}
static char *OldButton; /* button name before it became "REWRITE" */
/*
* SetReWrite()
*
* Display the warning message
* Save the old button name (LOAD or SAVE)
* Set the button name and ID to REWRITE and refresh the button
*/
void SetReWrite()
{
struct Gadget *theGadget = &LSGADGET[LS_LOAD];
LSMessage("File Exists: Press REWRITE to Over-Write it");
Forbid();
OldButton = theGadget->GadgetText->IText;
theGadget->GadgetText->IText = "ReWrite";
theGadget->GadgetText->LeftEdge = 7;
theGadget->GadgetID = LS_REWRITE;
RefreshGList(theGadget,myWindow,&LSRequest,1);
Permit();
}
/*
* UnsetReWrite()
*
* If there is a button name being saved
* Clear the REWRITE name
* Set the name and ID back to what it was, and refresh the button
* Clear the old button name and the message box
*/
void UnsetReWrite()
{
struct Gadget *theGadget = &LSGADGET[LS_LOAD];
if (OldButton)
{
Forbid();
theGadget->GadgetText->IText = " ";
RefreshGList(theGadget,myWindow,&LSRequest,1);
theGadget->GadgetText->IText = OldButton;
theGadget->GadgetText->LeftEdge = 15;
theGadget->GadgetID = RequestID;
RefreshGList(theGadget,myWindow,&LSRequest,1);
Permit();
OldButton = NULL;
LSMessage(NULL);
}
}
/*
* ActivateLSName()
*
* If the list is disabled,
* activate the name gadget
* otherwise
* ask the list manager to activate the name (and deselect any
* selected items, etc)
* [there is a bug in Intuition that causes this to fail if the string gadget
* was the previously active gadget; i.e., when you press RETURN in the file
* name gadget]
*/
void ActivateLSName()
{
if (LSGADGET[LS_NLIST].Flags & GADGDISABLED)
ActivateGadget(&LSGADGET[LS_NAME],myWindow,&LSRequest);
else
ActivateName(&LSListInfo);
}