home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d5xx
/
d502
/
cells.lha
/
CELLS
/
CELLSSource.lzh
/
cDoFile.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-04-20
|
19KB
|
715 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: cDoFile.c Handles the file requester
*/
#include "cGadget.h"
#include "cRequest.h"
#include "cReqLS.h"
#include "cDos.h"
#include "cParts.h"
extern char FileName[]; /* The current circuit file name */
extern char LSNameBuf[]; /* The name gadget buffer area */
extern int RequestID; /* The type of file requester in use */
extern FILEINFO FirstFile; /* The list of names in the current directory */
extern FILEINFO FindFile();
char DirName[MAXFNAME]; /* The current directory name */
#define LSGADGET LSRequest.er_Request.ReqGadget
/*
* NewDirectory()
*
* If the directory name is not empty, then get a lock on the current
* directory; if successful, change directories to that directory, otherwise
* set the lookup flag (change the name of the current directory instead
* of changing the current directory to the named one).
*
* If we are looking up the name (e.g., an error occured or DirName only
* contains a relative path), the get the complete path name. Set the
* gadgets in the requester to reflect the new name and contents.
*
* If no directory name is present, look up the device list instead.
*
* Since directory look-ups can take long, record the mounted drives so
* that disk insert events will not cause an update before the user has
* had a chance to look at the current directory.
*/
void NewDirectory(Flag)
int Flag;
{
LOCK lock;
int Last = strlen(DirName) - 1;
if (Last >= 0)
{
if (DosLock(&lock,DirName,TYPE_DIR))
UnLock(CurrentDir(lock)); else Flag = LOOKUPDIR;
if (Flag == LOOKUPDIR) GetProcessDir(DirName);
SetLSDirectory(DirName);
} else {
SetLSDevices();
}
Mounted = MountedDrives();
}
/*
* AttemptOpen()
*
* If a file name was given, then
* If the file can not be locked for reading, then
* If the operation is SAVE and the file does not exist, then were done,
* Otherwise, report the failure to open the file;
* Otherwise, (the file exists and can be read)
* Get the FIB of the file.
* If it is not a directory, then
* If the operation is SAVE warn about re-writing,
* Otherwise we've found the file to open.
* Otherwise, (it IS a directory)
* re-activate the name gadget (bug in Intuition makes this fail)
* CD to the selected directory and get its name
* look up the directory contents, etc.
* Unlock the lock.
*/
static int AttemptOpen(Name,ID)
char *Name;
int ID;
{
FIB theFib;
LOCK lock;
int status = FALSE;
if (Name && Name[0])
{
if ((lock = Lock(Name,ACCESS_READ)) == 0)
{
if (RequestID == LS_SAVE && IoErr() == ERROR_OBJECT_NOT_FOUND)
status = TRUE;
else
DosError("Open","File");
} else {
if (DosExamine(lock,&theFib,TYPE_FILE))
{
if (theFib->fib_DirEntryType < 0)
{
if (RequestID == LS_SAVE && ID != LS_REWRITE)
SetReWrite(); else status = TRUE;
} else {
ActivateLSName();
lock = CurrentDir(lock);
GetProcessDir(DirName);
NewDirectory(NOLOOKUP);
}
}
UnLock(lock);
}
} else {
LSMessage("Can't Open File: No File Specified");
}
return(status);
}
/*
* DoOpen()
*
* Try to open the file specified in the name gadget.
* If successful,
* If the operation will save a new file to the current directory,
* disable the directory list (so that it will be looked up fresh
* the next time - we don't actually know what directory the file
* will go into, since the name could include a path)
* Remove the requester and clean up
* Read or write the curcuit as necessary (include PARTS gadget status)
*/
static void DoOpen(theGadget)
struct Gadget *theGadget;
{
if (AttemptOpen(LSNameBuf,theGadget->GadgetID))
{
if (RequestID == LS_SAVE && theGadget->GadgetID != LS_REWRITE)
DisableLSList(&LSGADGET[LS_NLIST]);
RemoveRequest(&LSRequest);
SetPointerColor(PenInUse);
if (RequestID == LS_LOAD)
ReadFile(LSNameBuf,LSGADGET[LS_CHECK].Flags & SELECTED);
else
WriteFile(LSNameBuf,LSGADGET[LS_CHECK].Flags & SELECTED);
}
}
/*
* DoDirUpPressed()
*
* If SHIFT is held down (meaning go to the root directory)
* get the directory name if necessary
* find the ':' in the name
* If found and it is not the last character in the name,
* remove the rest of the name and look up the new directory
* Otherwiese (no SHIFT)
* If there is a directory named, get its length
* look backward for the first '/' or ':'
* truncate the directory name and look up the new directory
*/
static void DoDirUpPressed(Shifted)
int Shifted;
{
int len;
short i;
if (Shifted)
{
if ((len = strlen(DirName)) == 0) GetProcessDir(DirName);
for (i=0; DirName[i] && DirName[i] != ':'; i++);
if ((DirName[i] == ':' && DirName[i+1]) || len == 0)
{
DirName[i+1] = 0;
NewDirectory(NOLOOKUP);
}
} else {
if ((i = strlen(DirName)) > 0)
{
for (i-=2; i>=0 && DirName[i] != '/' && DirName[i] != ':'; i--);
if (i < 0 || DirName[i] == ':') i++;
DirName[MAX(i,0)] = 0;
NewDirectory(NOLOOKUP);
}
}
}
/*
* DoDirPressed()
*
* Look up the current directory.
* If SHIFT pressed, then disable the directory listing
* otherwise refresh the directory listing.
*/
static void DoDirPressed(Shifted)
int Shifted;
{
GetProcessDir(DirName);
if (Shifted)
{
DisableLSList(&LSGADGET[LS_NLIST]);
ClearDirectoryList();
} else {
EnableLSList(&LSGADGET[LS_NLIST]);
SetLSDirectory(DirName);
}
}
/*
* DoDrive()
*
* Get the name of the next mounted disk drive
* If no error, then look up the directory contents
* otherwise give an appropriate message.
*/
static void DoDrive()
{
switch(DosNextDisk(DirName))
{
case NOERROR:
NewDirectory(NOLOOKUP);
break;
case NOVOLMOUNT:
LSMessage("No Volumes Mounted");
DirName[0] = 0;
NewDirectory(NOLOOKUP);
break;
case NOVOLOTHER:
LSMessage("No Other Volumes Mounted");
GetProcessDir(DirName);
break;
}
}
/*
* DoInfo()
*
* If the specified file name can be locked, then
* If the ALT key is pressed
* If we can get an Info Block for the current disk,
* display its information
* Otherwise
* If we can get an FIB for the specified file
* If SHIFT is pressed
* display its comment field
* Otherwise
* get the file's creation date and its protection
* display the appropriate message for a file or directory
* Unlock the lock
*/
static void DoInfo(Shifted,ALTed)
int Shifted,ALTed;
{
LOCK lock;
FIB Fib;
INFODATA theInfo;
char time[16],prot[9];
int i;
if (DosLock(&lock,LSNameBuf,TYPE_FILE))
{
if (ALTed)
{
if (DosInfo(lock,&theInfo,TYPE_FILE))
LSMessage("Disk: %ld Free %ld Used (%ld%%) %s",
theInfo->id_NumBlocks - theInfo->id_NumBlocksUsed,
theInfo->id_NumBlocksUsed,
theInfo->id_NumBlocksUsed * 100 / theInfo->id_NumBlocks,
(theInfo->id_DiskState == ID_WRITE_PROTECTED)? "Locked": "");
} else {
if (DosExamine(lock,&Fib,TYPE_FILE))
{
if (Shifted)
{
if (Fib->fib_Comment[0])
LSMessage(Fib->fib_Comment);
else
LSMessage("No FileNote for this File");
} else {
GetStrTime(&time,&(Fib->fib_Date));
strcpy(prot,"hsparwed");
for (i=3; i>=0; i--)
if (Fib->fib_Protection & (1<<i)) prot[7-i] = '-';
for (i=7; i>3; i--)
if ((Fib->fib_Protection & (1<<i)) == 0) prot[7-i] = '-';
if (Fib->fib_DirEntryType < 0)
LSMessage("%ld Byte%s (%ld Block%s) [%s] %s",
Fib->fib_Size, (Fib->fib_Size != 1)? "s": "",
Fib->fib_NumBlocks, (Fib->fib_NumBlocks != 1)? "s": "",
prot, time);
else
LSMessage("Dir: [%s] %s",prot,time);
}
}
}
UnLock(lock);
}
}
/*
* DoDelete()
*
* If no file is named, give an error message,
* Otherwise if the file can be deleted,
* display the deletion message
* find the file in the directory listing (if any)
* remove the file entry from the list
* clear the name string
* Otherwise, give an error message
*/
static void DoDelete()
{
FILEINFO theFile;
if (LSNameBuf[0] == 0)
{
LSMessage("Can't Delete File: None Specified");
} else if (DeleteFile(LSNameBuf)) {
LSMessage("'%s' Deleted",LSNameBuf);
theFile = FindFile(LSNameBuf);
if (theFile) RemoveFile(theFile);
SetStringInfo(&LSGADGET[LS_NAME],"");
RefreshRequest(&LSRequest,LS_NAME,NULL);
} else DosError("Delete","File");
}
/*
* DoMakeDir()
*
* If no name was given, display an error
* Otherwise,
* If the new directory can not be created, display a message
* Otherwise,
* CD to the new directory
* get its complete path name,
* clear the name gadget
* look up the new directory contents
*/
static void DoMakeDir()
{
LOCK lock;
if (LSNameBuf[0] == 0)
{
LSMessage("Can't Create Directory: No Name Specified");
} else {
if ((lock = CreateDir(LSNameBuf)) == 0)
{
DosError("Create","Directory");
} else {
UnLock(lock);
if (DosLock(&lock,LSNameBuf,TYPE_DIR))
{
UnLock(CurrentDir(lock));
GetProcessDir(DirName);
SetStringInfo(&LSGADGET[LS_NAME],"");
RefreshRequest(&LSRequest,LS_NAME,NULL);
NewDirectory(LOOKUPDIR);
}
}
}
}
/*
* LSGadgetUp()
*
* Handles GadgetUp events for the LoadSave file requester:
* Clear any message in the message box
* Clear the RE-WRITE button name if appropriate
* For each gadget, do the right thing (try to make sure the name gadget
* remains active):
*
* LOAD, SAVE, REWRITE and NAME: Open the specified file
* DRIVE: Get the next drive's information
* INFO: Get the file's information
* DELETE: Delete the file
* MAKEDIR: Make the new directory
* CANCEL: Cancel the requester and put things back in order
*
* The Directory Name: lookup directory list
* Left Arrow: Go to parent directory
* The Slider: update the list position
*/
static void LSGadgetUp(theGadget,theMessage)
struct Gadget *theGadget;
struct IntuiMessage *theMessage;
{
LSMessage(NULL);
if (theGadget->GadgetID != LS_REWRITE) UnsetReWrite();
switch(theGadget->GadgetID)
{
case LS_LOAD:
case LS_SAVE:
case LS_REWRITE:
case LS_NAME:
DoOpen(theGadget);
break;
case LS_DRIVE:
DoDrive();
ActivateLSName();
break;
case LS_INFO:
DoInfo(theMessage->Qualifier & SHIFTKEYS,
theMessage->Qualifier & ALTKEYS);
ActivateLSName();
break;
case LS_DELETE:
DoDelete();
ActivateLSName();
break;
case LS_MAKEDIR:
DoMakeDir();
ActivateLSName();
break;
case LS_DIR:
DoDirPressed(theMessage->Qualifier & SHIFTKEYS);
ActivateLSName();
break;
case LS_DLARROW:
DoDirUpPressed(theMessage->Qualifier & SHIFTKEYS);
ActivateLSName();
break;
case LS_CANCEL:
QuitInProgress = FALSE;
RemoveRequest(&LSRequest);
if (RequestID == LS_LOAD)
InvertGadget(&cGadget[ID_LOAD]);
else
InvertGadget(&cGadget[ID_SAVE]);
SetPointerColor(PenInUse);
break;
case LS_SLIDE:
EndListSlider(theGadget->UserData);
break;
}
}
/*
* LSGadgetDown()
*
* Handles GadgetDown message for the LoadSave File Requester
* Clear the message box if appropriate
* Clear the RE-WRITE gadget name
* For each gadget, do the right thing (try to make the name gadget active
* as often as possible):
*
* A File Name in the List: if double clicked, try to open it
* Up Arrow: Scroll the list Up
* Down Arrow: Scroll the List Down
* Slider: Let the list manager know that the slider is active
* Name Gadget: Unselect any selected names in the list
* Message: Get back the last message displayed
*/
static void LSGadgetDown(theGadget,theMessage)
struct Gadget *theGadget;
struct IntuiMessage *theMessage;
{
if (theGadget->GadgetID != LS_MESSAGE &&
theGadget->GadgetID != LS_NAME) LSMessage(NULL);
UnsetReWrite();
switch(theGadget->GadgetID)
{
case LS_NLIST:
if (DoListHit(theGadget->UserData,theMessage)) DoOpen(theGadget);
break;
case LS_UARROW:
DoListScrollUp(theGadget->UserData,theGadget,theMessage);
break;
case LS_DARROW:
DoListScrollDown(theGadget->UserData,theGadget,theMessage);
break;
case LS_SLIDE:
StartListSlider(theGadget->UserData);
break;
case LS_NAME:
if ((LSGADGET[LS_NLIST].Flags & GADGDISABLED) == 0)
UnsetListSelect(theGadget->UserData,TRUE);
break;
case LS_CHECK:
ActivateLSName();
break;
case LS_MESSAGE:
RecallLSMessage(theGadget);
ActivateLSName();
break;
}
}
/*
* DoLoad()
*
* If the requester is not already up
* Clear the name buffer
* Invert the LOAD gadget and set the pointer to its normal colors
* Set up the requester title and gadget names
* Open the requester
* If unsuccessful, put the pointer and LOAD gadgets back the way they were
*/
void DoLoad()
{
extern void DoListMouse();
if (ActiveRequest != &LSRequest)
{
LSNameBuf[0] = 0;
InvertGadget(&cGadget[ID_LOAD]);
RestorePointerColor();
SetLSTexts("Load Circuit from File:","Load",
"Load Library as Parts",LS_LOAD);
LSListInfo.Image->NextImage = NULL;
LSGADGET[LS_CHECK].Flags &= ~GADGDISABLED;
AddRequest(&LSRequest,LSGadgetDown,LSGadgetUp,DoListMouse);
if (ActiveRequest == NULL)
{
InvertGadget(&cGadget[ID_LOAD]);
SetPointerColor(PenInUse);
}
}
}
/*
* DoSaveAs()
*
* If the requester is not already active
* Copy the current circuit file name to the name gadget
* Invert the SAVE gadget and set the pointer to its normal colors
* Set the requester title and gadget names
* Disable PARTS gadget if necessary
* Open the requester
* If unsuccessful, put things back as they were
*/
void DoSaveAs()
{
extern void DoListMouse();
if (ActiveRequest != &LSRequest)
{
strcpy(LSNameBuf,FileName);
InvertGadget(&cGadget[ID_SAVE]);
RestorePointerColor();
SetLSTexts((SelectType)? "Save Selection to File:":
"Save Circuit to File:","Save","Save as Library (Parts Only)",LS_SAVE);
if (SelectType || PartsList.FirstPart == NULL)
LSGADGET[LS_CHECK].Flags |= GADGDISABLED;
else
LSGADGET[LS_CHECK].Flags &= ~GADGDISABLED;
LSListInfo.Image->NextImage = NULL;
AddRequest(&LSRequest,LSGadgetDown,LSGadgetUp,DoListMouse);
if (ActiveRequest == NULL)
{
InvertGadget(&cGadget[ID_SAVE]);
SetPointerColor(PenInUse);
}
}
}
/*
* DoSave()
*
* If cells are selected, request a file for them to be saved into
* Otherwise,
* If changes have been made to the current circuit
* If the circuit has no name yet
* get a file name for the circuit
* Otherwise
* Invert the SAVE button during the save operation
* and put the pointer colors back to normal
* save the circuit to its file
* Otherwise give a message that no saving is required
*/
void DoSave()
{
if (SelectType)
{
DoSaveAs();
} else {
if (Changed)
{
if (FileName[0] == 0)
{
DoSaveAs();
} else {
InvertGadget(&cGadget[ID_SAVE]);
RestorePointerColor();
WriteFile(FileName,0);
}
} else {
DoError("Circuit has not been Modified");
}
}
}
/*
* DoNew()
*
* Cancel any selection
* If changes have been made
* Ask whether changes should be discarded
* If still going on with the NEW command,
* Clear the library list
* Clear the grid
* Clear the UNDO and RESET grids
* Clear the file name and the Changed flag
*/
void DoNew()
{
int OKtoDoNew = TRUE;
if (SelectType) CancelSelect();
if (Changed)
{
InvertGadget(&cGadget[ID_LOAD]);
RestorePointerColor();
OKtoDoNew =
DoQuestion(" Changes have not been Saved. Discard Changes? ");
SetPointerColor(PenInUse);
InvertGadget(&cGadget[ID_LOAD]);
}
if (OKtoDoNew)
{
ClearLibs();
DoClear();
ClearGrid(UndoArray);
ClearGrid(ResetArray);
Changed = FALSE;
FileName[0] = 0;
}
}
/*
* DoDiskInseted()
*
* If the file requester is active
* Look up the currently mounted floppy drives
* If a new disk was inserted, go to the root of that disk
*/
void DoDiskInserted(theMessage)
struct IntuiMessage *theMessage;
{
int OldMounted = Mounted;
if (ActiveRequest == &LSRequest)
{
Mounted = MountedDrives();
if (DosInsertedDrive(OldMounted,DirName))
NewDirectory(LOOKUPDIR);
}
}
/*
* DoDiskRemoved()
*
* Get the currently mounted disks, so we can tell what new disks
* are inserted later.
*/
void DoDiskRemoved(theMessage)
struct IntuiMessage *theMessage;
{
Mounted = MountedDrives();
}