2023-11-16 18:19:54 -05:00

3728 lines
92 KiB
C

/* *** main.c ***************************************************************
*
* File IO Suite -- Example Main
* from Book 1 of the Amiga Programmers' Suite by RJ Mical
*
* Copyright (C) 1986, 1987, Robert J. Mical
* All Rights Reserved.
*
* Created for Amiga developers.
* Any or all of this code can be used in any program as long as this
* entire copyright notice is retained, ok?
*
* The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable.
* All copyright notices and all file headers must be retained intact.
* The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the
* resultant object code may be included in any software product. However, no
* portion of the source listings or documentation of the Amiga Programmer's
* Suite Book 1 may be distributed or sold for profit or in a for-profit
* product without the written authorization of the author, RJ Mical.
*
* HISTORY NAME DESCRIPTION
* ----------- -------------- --------------------------------------------
* 4 Feb 87 RJ Real release
* 12 Aug 86 RJ >:-{)* Prepare (clean house) for release
* 3 May 86 =RJ Mical= Fix prop gadget for both 1.1 and 1.2
* 1 Feb 86 =RJ Mical= Created this file.
*
* *********************************************************************** */
#define FILEIO_SOURCEFILE
#include "fileio.h"
BOOL TestFileIO();
struct NewScreen NewFileIOScreen =
{
0, 0, /* LeftEdge, TopEdge */
320, 200, /* Width, Height */
2, /* Depth */
0, 1, /* Detail/BlockPens */
NULL, /* ViewPort Modes (must set/clear HIRES as needed) */
CUSTOMSCREEN,
&SafeFont, /* Font */
(UBYTE *)"Example FileIO Program's Screen",
NULL, /* Gadgets */
NULL, /* CustomBitMap */
};
struct NewWindow NewFileIOWindow =
{
0, 12, /* LeftEdge, TopEdge */
320, 150, /* Width, Height */
-1, -1, /* Detail/BlockPens */
NEWSIZE | MOUSEBUTTONS | VANILLAKEY | MENUPICK | CLOSEWINDOW
| DISKINSERTED,
/* IDCMP Flags */
WINDOWSIZING | WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE
| SIZEBRIGHT | SMART_REFRESH | RMBTRAP | ACTIVATE | NOCAREREFRESH,
/* Window Specification Flags */
NULL, /* FirstGadget */
NULL, /* Checkmark */
(UBYTE *)"FileIO Requester Window", /* WindowTitle */
NULL, /* Screen */
NULL, /* SuperBitMap */
96, 30, /* MinWidth, MinHeight */
640, 200, /* MaxWidth, MaxHeight */
WBENCHSCREEN,
};
VOID main(argc, argv)
LONG argc;
char **argv;
{
struct Screen *screen;
struct Window *window;
struct FileIOSupport *fileio1, *fileio2;
BOOL mainswitch, ioswitch, mainsuccess;
LONG class;
struct IntuiMessage *message;
SHORT pick;
mainsuccess = FALSE;
screen = NULL;
window = NULL;
fileio1 = fileio2 = NULL;
IntuitionBase = (struct IntuitionBase *)
OpenLibrary("intuition.library", 0);
GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0);
DosBase = (struct DosLibrary *)OpenLibrary("dos.library", 0);
IconBase = (struct IconBase *)OpenLibrary("icon.library", 0);
if ( (IntuitionBase == NULL)
|| (GfxBase == NULL)
|| (DosBase == NULL)
|| (IconBase == NULL) )
goto MAIN_DONE;
if (argv)
{
/* OK, we started from CLI */
if (argc > 1)
{
if (screen = OpenScreen(&NewFileIOScreen))
{
NewFileIOWindow.Screen = screen;
NewFileIOWindow.Type = CUSTOMSCREEN;
}
}
}
window = OpenWindow(&NewFileIOWindow);
fileio1 = GetFileIOSupport();
fileio2 = GetFileIOSupport();
if ((window == NULL) || (fileio1 == NULL) || (fileio2 == NULL))
goto MAIN_DONE;
SetFlag(fileio2->Flags, WBENCH_MATCH | MATCH_OBJECTTYPE);
fileio2->DiskObjectType = WBTOOL;
fileio2->ReqTitle = (UBYTE *)"- Workbench Tools and Drawers -";
SetAPen(window->RPort, 1);
Move(window->RPort, 25, 40);
Text(window->RPort, "= Click for FileIO Requester =", 30);
mainswitch = TRUE;
pick = 0;
while (mainswitch)
{
WaitPort(window->UserPort);
ioswitch = FALSE;
while (message = GetMsg(window->UserPort))
{
class = message->Class;
ReplyMsg(message);
switch (class)
{
case CLOSEWINDOW:
mainswitch = FALSE;
break;
case DISKINSERTED:
/* You should clear the GOOD_FILENAMES flag whenever you
* detect that a new disk was inserted.
*/
ClearFlag(fileio1->Flags, GOOD_FILENAMES);
ClearFlag(fileio2->Flags, GOOD_FILENAMES);
/* While I'm here, I'll demo another feature for you. */
ToggleFlag(fileio1->Flags, USE_VOLUME_NAMES);
ToggleFlag(fileio2->Flags, USE_VOLUME_NAMES);
break;
default:
/* If any other event occurs, bring up that old requester! */
ioswitch = TRUE;
break;
}
}
if (ioswitch)
{
if (pick == 0)
{
if (TestFileIO(fileio1, window))
/* Oops, disk swapped, so restart the other */
ClearFlag(fileio2->Flags, GOOD_FILENAMES);
}
else
{
if (TestFileIO(fileio2, window))
/* Oops, disk swapped, so restart the other */
ClearFlag(fileio1->Flags, GOOD_FILENAMES);
}
pick = 1 - pick;
}
}
mainsuccess = TRUE;
MAIN_DONE:
if (NOT mainsuccess) Alert(ALERT_NO_MEMORY, NULL);
if (fileio1) ReleaseFileIO(fileio1);
if (fileio2) ReleaseFileIO(fileio2);
if (window) CloseWindow(window);
if (screen) CloseScreen(screen);
if (IntuitionBase) CloseLibrary(IntuitionBase);
if (GfxBase) CloseLibrary(GfxBase);
if (DosBase) CloseLibrary(DosBase);
if (IconBase) CloseLibrary(IconBase);
}
BOOL TestFileIO(fileio, window)
struct FileIOSupport *fileio;
struct Window *window;
/* This guy calls GetFileIOName(), displays the file name selected by the
* user, and returns TRUE if the user swapped disks during GetFileIOName()
* (else returns FALSE)
*/
{
UBYTE name[80];
if (GetFileIOName(fileio, window))
{
/* If user was positive, display the name */
CopyString(&name[0], "[");
BuildFileIOPathname(fileio, &name[1]);
ConcatString(&name[0], "]");
AlertGrunt(&name[0], window);
}
if (FlagIsSet(fileio->Flags, DISK_HAS_CHANGED))
{
ClearFlag(fileio->Flags, DISK_HAS_CHANGED);
return(TRUE);
}
else return(FALSE);
}
/* *** fileio.c *************************************************************
*
* File IO Suite -- Primary FileIO Requester Routines
* from Book 1 of the Amiga Programmers' Suite by RJ Mical
*
* Copyright (C) 1986, 1987, Robert J. Mical
* All Rights Reserved.
*
* Created for Amiga developers.
* Any or all of this code can be used in any program as long as this
* entire copyright notice is retained, ok? Thanks.
*
* The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable.
* All copyright notices and all file headers must be retained intact.
* The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the
* resultant object code may be included in any software product. However, no
* portion of the source listings or documentation of the Amiga Programmer's
* Suite Book 1 may be distributed or sold for profit or in a for-profit
* product without the written authorization of the author, RJ Mical.
*
* HISTORY NAME DESCRIPTION
* ----------- -------------- --------------------------------------------
* 20 Oct 87 - RJ Added RENAME_RAMDISK to fix what seems to
* be a bug in either AmigaDOS or Workbench.
* 26 Aug 87 RJ Added test for 0 GadgetID at end of
* GetFileIOName()
* 4 Feb 87 RJ Real release
* 12 Aug 86 RJ >:-{)* Prepare (clean house) for release
* 3 May 86 =RJ Mical= Fix prop gadget for both 1.1 and 1.2
* 1 Feb 86 =RJ Mical= Created this file.
*
* *********************************************************************** */
#define FILEIO_SOURCEFILE
#include "fileio.h"
/* These routines can be found in filesupp.c */
extern HandleGadget();
extern StartOpenRequester();
extern DiskInserted();
extern PropMouseMoves();
/* *** GetFileIOSupport() ***************************************************
*
* NAME
* GetFileIOSupport -- Allocate and initialize a FileIOSupport structure
*
*
* SYNOPSIS
* struct FileIOSupport *GetFileIOSupport();
*
*
* FUNCTION
* Allocates and initializes a FileIOSupport structure for use with
* calls to GetFileIOName().
*
* You may want to further initialize the structure before calling
* GetFileIOName(). Refer to the FileIO documentation for more
* information.
*
* When you're done with the structure, call ReleaseFileIO().
*
*
* INPUTS
* None
*
*
* RESULT
* If all goes well, returns the address of a FileIOSupport structure.
* If anything goes wrong (usually out of memory), returns NULL.
*
*
* EXAMPLE
* struct FileIOSupport *fileio;
* fileio = GetFileIOSupport();
* GetFileIOName(fileio, window);
* ReleaseFileIO(fileio);
*
*
* BUGS
* None known
*
*
* SEE ALSO
* GetFileIOName(), ReleaseFileIO()
*/
struct FileIOSupport *GetFileIOSupport()
{
struct FileIOSupport *fileio;
if (fileio = (struct FileIOSupport *)AllocMem(
sizeof(struct FileIOSupport), MEMF_CLEAR))
{
/* Anything special to initialize? */
SetFlag(fileio->Flags, USE_VOLUME_NAMES | RENAME_RAMDISK);
}
return(fileio);
}
/* *** GetFileIOName() ******************************************************
*
* NAME
* GetFileIOName -- Gets a file name for input/output from the user
*
*
* SYNOPSIS
* BOOL GetFileIOName(FileIO, Window);
*
*
* FUNCTION
* This routine creates a filename requester which allows the user
* to browse through the AmigaDOS filesystem and select one of
* the filenames found there.
*
* The FileIO argument is a pointer to a FileIOSupport structure,
* which is allocated and initialized for you via a call to
* GetFileIOSupport().
* You may preset the FileIO parameters before calling this routine,
* or you may leave them set at their default values. See the FileIO
* documentation for complete details.
*
* The Window argument is the pointer to the window structure returned
* by a call to Intuition's OpenWindow() function. As this routine
* opens a requester and requesters open in windows, you must have
* already opened a window before calling this routine, even if it's
* a window opened for no other purpose than to call this routine.
*
* This routine returns a BOOL value of TRUE or FALSE, depending on
* whether the user chose to accept or cancel the filename selection
* operation. If TRUE, the filename selected by the user can be
* found in the FileIO structure FileName[] field. This filename
* will have all leading and trailing blanks removed (in case the
* user typed in a filename with extraneous spaces). Likewise,
* the pathname to the disk and drawer can be found in the text
* fields DiskName[] and DrawerName[]. You can construct
* the pathname using these text strings. Also, you can call
* BuildFileIOPathname() to build the pathname automatically.
*
* There's a *lot* more to be said about this function. Please
* read the documentation.
*
* NOTE: This routine is not re-entrant. What this means
* is that if you have created a program that has more than one task,
* this routine cannot be called by more than one task at a time.
* This is not a problem for the grand majority of programs.
* But if you have some application that would require calling this
* routine asynchronously from multiple tasks, you'll have to
* implement some quick semaphore arrangement to avoid collisions.
* No big deal, actually. See Exec semaphores for everything you need.
*
*
* INPUTS
* FileIO = pointer to a FileIOSupport structure, as allocated
* via a call to GetFileIOSupport()
* Window = pointer to a Window structure, as created via a call
* to Intuition's OpenWindow()
*
*
* RESULT
* TRUE if the user decided that the filename selection was successful,
* FALSE if the user chose to cancel the operation
*
*
* EXAMPLE
* if (GetFileIOName(fileio, window))
* ProcessFileName(&fileio->FileName[0]);
*
*
* BUGS
* None known, though there could be some, and the disk selection
* subsystem logic is not perfectly polished (though it's believed
* to be bug-free).
*
*
* SEE ALSO
* BuildFileIOPathname(), GetFileIOSupport(), ReleaseFileIO()
*/
BOOL GetFileIOName(fileio, window)
struct FileIOSupport *fileio;
struct Window *window;
{
UBYTE *newtext;
if ((fileio == NULL) || (window == NULL)) return(FALSE);
OpenSaveLock = CurrentDir(NULL);
CurrentDir(OpenSaveLock);
fileio->DOSLock = OpenSaveLock;
/* Get easily-accessible copies of the values that are referenced
* most often
*/
OpenReq = &OpenReqSupport.Requester;
OpenReqWindow = OpenReqSupport.Window = window;
OpenReqFileIO = fileio;
/* Set up the DoRequest() handlers */
OpenReqSupport.GadgetHandler = HandleGadget;
OpenReqSupport.StartRequest = StartOpenRequester;
OpenReqSupport.NewDiskHandler = DiskInserted;
OpenReqSupport.MouseMoveHandler = PropMouseMoves;
/* Init the string gadget buffers */
OpenNameTextInfo.Buffer = &fileio->FileName[0];
OpenDrawerTextInfo.Buffer = &fileio->DrawerName[0];
OpenDiskTextInfo.Buffer = &fileio->DiskName[0];
/* Initialize the requester title */
if ((ReqTitleText.IText = fileio->ReqTitle) == NULL)
ReqTitleText.IText = DefaultReqTitle;
ReqTitleText.LeftEdge
= (OPEN_WIDTH - IntuiTextLength(&ReqTitleText)) >> 1;
/* If this fileio doesn't have valid filenames,
* then refresh the whole thing
*/
if (FlagIsClear(fileio->Flags, GOOD_FILENAMES))
{
ResetNameText(TRUE);
ResetDrawerText(TRUE);
BuildVolumeTable(fileio);
CopyString(&OpenReqFileIO->DiskName[0], CurrentVolumeName());
}
ResetNameText(FALSE);
ResetDrawerText(FALSE);
ResetDiskText(FALSE);
StuffSelectNames(0);
InitOpenProp(TRUE);
/* Reset the double-click time variables */
OpenClickSeconds = OpenClickMicros = 0;
/* And now, do that requester. */
DoRequest(&OpenReqSupport);
/* Back, eh? Wasn't that easy? */
if (FlagIsSet(fileio->Flags, LOCK_GOTTEN))
{
UnLock(fileio->DOSLock);
ClearFlag(fileio->Flags, LOCK_GOTTEN);
}
CurrentDir(OpenSaveLock);
OpenReqFileIO = NULL;
/* Strip any excess leading and trailing blanks off the final name */
newtext = StripOuterSpace(&fileio->FileName[0], " ");
CopyString(&fileio->FileName[0], newtext);
if ((OpenReqSupport.SelectedGadgetID)
&& (OpenReqSupport.SelectedGadgetID != OPENGADGET_CANCEL))
return(TRUE);
return(FALSE);
}
/* *** BuildFileIOPathname() ************************************************
*
* NAME
* BuildFileIOPathname -- Build a file pathname using a FileIO struct
*
*
* SYNOPSIS
* BuildFileIOPathname(FileIOSupport, Buffer);
*
*
* FUNCTION
* Builds the text for a pathname using the FileName[], DrawerName[] and
* DiskName[] fields of the specified FileIOSupport structure
* after the support structure has been used in a successful call
* to GetFileIOName(). Writes the text into the Buffer.
*
*
* INPUTS
* FileIOSupport = the address of a FileIOSupport structure
* Buffer = address of the buffer to receive the file pathname
*
*
* RESULT
* None
*
*
* SEE ALSO
* GetFileIOName()
*/
VOID BuildFileIOPathname(fileio, buffer)
struct FileIOSupport *fileio;
UBYTE *buffer;
{
StripOuterSpace(&fileio->DiskName[0], " ");
StripOuterSpace(&fileio->DrawerName[0], " ");
StripOuterSpace(&fileio->FileName[0], " ");
CopyString(buffer, &fileio->DiskName[0]);
if (StringLength(&fileio->DrawerName[0]))
{
ConcatString(buffer, &fileio->DrawerName[0]);
ConcatString(buffer, "/");
}
ConcatString(buffer, &fileio->FileName[0]);
}
/* *** AddFileIOName() ******************************************************
*
* NAME
* AddFileIOName -- Add a file name to the names in a FileIOSupport
*
*
* SYNOPSIS
* AddFileIOName(FileIOSupport, FileName);
*
*
* FUNCTION
* This routine adds a file name to the list of file names currently
* in the specified FileIOSupport structure. The next time the
* FileIOSupport structure is used for a call to GetFileIOName(), the
* new file name will apppear alphabetized in with the other file names.
*
* This routine will most often be used after a call to GetFileIOName()
* or some other routine where the user is allowed to specify the name
* of a file to be opened for output. If the file is opened
* successfully, this routine will make sure that the name of the file
* is in the FileIOSupport structure. This is important if the output
* file has been newly created; otherwise, without calling this
* routine, the next time the FileIOSupport structure is used the new
* file name would not appear even though the file exists. If the name
* is already in the list when you call AddFileIOName() then nothing
* happens. This allows you to call AddFileIOName() without worrying
* about duplicate name redundancy.
*
* Here's a typical sequence of events leading up to a call to
* AddFileIOName():
*
* First, get a FileIOSupport structure:
* fileio = GetFileIOSupport(...);
*
* When the user wants to write data, use GetFileIOName()
* to provide a convenient and consistent interface to
* the filesystem:
* goodfile = GetFileIOName(...);
*
* If the user has selected a name for output (in this example,
* goodfile will equal TRUE if the user selected a name), then
* open the file (possibly creating it) and then call
* AddFileIOName() to make sure the name is in the FileIOSupport
* structure's list:
* if (goodfile)
* {
* UBYTE filename[80];
*
* BuildFileIOPathname(fileio, &filename[0]);
* ... open filename, write it, close it ...
* if (filename opened successfully)
* AddFileIOName(fileio, &filename[0]);
* }
*
*
* INPUTS
* FileIOSupport = the address of a FileIOSupport structure
* FileName = the address of null-terminated text that is
* either a simple file name or a valid AmigaDOS pathname.
*
*
* RESULT
* None
*
*
* SEE ALSO
* GetFileIOName()
* GetFileIOSupport()
*/
VOID AddFileIOName(fileio, filename)
struct FileIOSupport *fileio;
UBYTE *filename;
{
SHORT index, i, length;
struct Remember *remember, *oldremember;
UBYTE *nextentry;
struct Remember *namekey;
/* Does the filename start with a volume name? If so, skip over it */
index = IndexString(filename, ":");
if (index >= 0) filename += index + 1;
/* Does the filename start with a directory name? If so, skip over it */
do
{
index = IndexString(filename, "/");
if (index >= 0) filename += index + 1;
}
while (index >= 0);
if (*filename == 0) return;
/* Here, filename points to what is presumed to be a valid file name.
* If it's found among the FileIOSupport's names, exit.
* If it's not found in the list, add it.
*
* The current file names are stored in the fileio's Remember list.
*/
remember = fileio->NameKey;
oldremember = NULL;
while (remember)
{
i = CompareUpperStrings(filename, remember->Memory);
if (i < 0) goto ADD_FILENAME;
if (i == 0) return;
oldremember = remember;
remember = remember->NextRemember;
}
ADD_FILENAME:
/* Name not on list, so add it now */
length = StringLength(filename);
namekey = NULL;
if (nextentry = AllocRemember(&namekey, length + 1 + 1, NULL))
{
CopyString(nextentry, filename);
*(nextentry + length + 1) = 0;
if (oldremember) oldremember->NextRemember = namekey;
else fileio->NameKey = namekey;
/* This assignment is valid whether or not remember is NULL */
namekey->NextRemember = remember;
fileio->NameCount++;
}
}
/* *** ReleaseFileIO() ******************************************************
*
* NAME
* ReleaseFileIO -- Release the FileIO structure and all local memory
*
*
* SYNOPSIS
* ReleaseFileIO(FileIO);
*
*
* FUNCTION
* Releases the FileIO structure by freeing all local memory attached
* to the structure and then freeing the structure itself.
*
*
* INPUTS
* FileIO = the address of a FileIO structure
*
*
* RESULT
* None
*
*
* SEE ALSO
* GetFileIOSupport()
*/
VOID ReleaseFileIO(fileio)
struct FileIOSupport *fileio;
{
if (fileio)
{
FreeRemember(&fileio->VolumeKey, TRUE);
FreeRemember(&fileio->NameKey, TRUE);
FreeMem(fileio, sizeof(struct FileIOSupport));
}
}
/* *** filesupp.c ***********************************************************
*
* File IO Suite -- Open Requester Routines
* from Book 1 of the Amiga Programmers' Suite by RJ Mical
*
* Copyright (C) 1986, 1987, Robert J. Mical
* All Rights Reserved.
*
* Created for Amiga developers.
* Any or all of this code can be used in any program as long as this
* entire copyright notice is retained, ok? Thanks.
*
* The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable.
* All copyright notices and all file headers must be retained intact.
* The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the
* resultant object code may be included in any software product. However, no
* portion of the source listings or documentation of the Amiga Programmer's
* Suite Book 1 may be distributed or sold for profit or in a for-profit
* product without the written authorization of the author, RJ Mical.
*
* HISTORY NAME DESCRIPTION
* ----------- -------------- --------------------------------------------
* 20 Oct 87 - RJ Added RENAME_RAMDISK to fix what seems to
* be a bug in either AmigaDOS or Workbench.
* 27 Sep 87 RJ In order to show the correct DiskName during
* WarmStartFileIO(), that routine now
* refreshes the gadgets both before and after
* the BuildNameTable() process.
* 4 Feb 87 RJ Real release
* 12 Aug 86 RJ >:-{)* Prepare (clean house) for release
* 3 May 86 =RJ Mical= Fix prop gadget for both 1.1 and 1.2
* 1 Feb 86 =RJ Mical= Created this file.
*
* *********************************************************************** */
#define FILEIO_SOURCEFILE
#include "fileio.h"
/* I think these are silly, but I put them here anyway to avoid compiler
* warnings.
*/
VOID InitOpenProp();
VOID StuffSelectNames();
/* ======================================================================= */
/* === ResetText Routines ================================================ */
/* ======================================================================= */
VOID ResetTextGrunt(info, resetbuffer)
struct StringInfo *info;
BOOL resetbuffer;
/* Reset the string position variables, and reset the buffer itself if
* resetbuffer is TRUE.
*/
{
info->BufferPos = info->DispPos = 0;
if (resetbuffer) info->Buffer[0] = '\0';
}
VOID ResetNameText(resetbuffer)
BOOL resetbuffer;
{
ResetTextGrunt(&OpenNameTextInfo, resetbuffer);
}
VOID ResetDrawerText(resetbuffer)
BOOL resetbuffer;
{
ResetTextGrunt(&OpenDrawerTextInfo, resetbuffer);
}
VOID ResetDiskText(resetbuffer)
BOOL resetbuffer;
{
ResetTextGrunt(&OpenDiskTextInfo, resetbuffer);
}
/* ======================================================================= */
/* === WarmStart Initializer ============================================= */
/* ======================================================================= */
VOID WarmStartFileIO(fileio)
struct FileIOSupport *fileio;
/* This routine establishes a lock on the current disk and drawer,
* resets all of the subsystem control variables,
* gets the file names for the current disk and drawer,
* initializes the proportional gadget,
* and then refreshes the requester.
*/
{
ULONG lock;
/* If the fileio already had a lock, release it before proceeding */
if (FlagIsSet(fileio->Flags, LOCK_GOTTEN))
{
UnLock(fileio->DOSLock);
ClearFlag(fileio->Flags, LOCK_GOTTEN);
fileio->DOSLock = OpenSaveLock;
CurrentDir(OpenSaveLock);
}
/* Build the lock name using the current disk and drawer names */
if (StringLength(&fileio->DiskName[0]))
CopyString(&OpenLockName[0], &fileio->DiskName[0]);
else
CopyString(&OpenLockName[0], CurrentVolumeName());
/* If the programmer wants us to sidestep the "RAM DISK:" bug,
* then by all means oblige her or him.
*/
if (FlagIsSet(fileio->Flags, RENAME_RAMDISK)
&& CompareUpperStrings(&OpenLockName[0],
"RAM DISK:") == 0)
{
/* Everyone seems suspicious of "RAM Disk:" */
OpenLockName[3] = ':';
OpenLockName[4] = '\0';
}
ConcatString(&OpenLockName[0], &fileio->DrawerName[0]);
/* Can we get a lock on this name? */
if (lock = Lock(&OpenLockName[0], ACCESS_READ))
{
/* Got it! */
SetFlag(fileio->Flags, LOCK_GOTTEN);
fileio->DOSLock = lock;
CurrentDir(lock);
}
else
{
/* Hey, bad break, this name just won't do. But the rest of these
* routines need a valid directory, so go back home.
*/
Alert(ALERT_BAD_DIRECTORY, OpenReqWindow);
CopyString(&fileio->DiskName[0], &CurrentDiskString[0]);
ResetDiskText(FALSE);
ResetDrawerText(TRUE);
}
/* Reset the fileio name selection variables */
fileio->CurrentPick = -1;
fileio->NameStart = 0;
fileio->NameCount = 0;
/* Reset the text and gadgets */
InitOpenProp(TRUE); /* Initialize the prop gadget */
StuffSelectNames(-1); /* Display all of the names */
BuildNameTable(OpenReqFileIO); /* Get the file names */
StuffSelectNames(1); /* Display the file names */
}
/* ======================================================================= */
/* === Select Name Routines ============================================== */
/* ======================================================================= */
VOID BlankSelectText(index)
SHORT index;
/* This routine truns the SelectText at index into blanks */
{
UBYTE *ptr;
SHORT blanklength;
ptr = &OpenSelectBuffers[index][0];
for (blanklength = VISIBLE_SELECT_LENGTH - 1; blanklength; blanklength--)
*ptr++ = ' ';
*ptr = '\0';
OpenSelectText[index].FrontPen = 1;
OpenSelectText[index].BackPen = 0;
}
VOID DrawSelectNames()
{
struct Layer *layer;
Forbid();
if (layer = OpenReq->ReqLayer)
if (layer->rp)
PrintIText(layer->rp,
&OpenSelectText[NAME_ENTRY_COUNT - 1],
OPENSELECT_LEFT, OPENSELECT_TOP);
Permit();
}
VOID StuffSelectNames(refreshcount)
SHORT refreshcount;
/* This routine stuffs the Open Requester's filename gadgets with
* names from the fileio structure, starting from the
* fileio->NameStart name. If the refreshcount is nonzero, the gadgets
* will be refreshed too.
*/
{
SHORT i, end, bufferpos;
SHORT length, blanklength;
UBYTE *ptr, *ptr2;
struct Remember *remember;
struct Layer *layer;
if (OpenReqFileIO->NameCount
> OpenReqFileIO->NameStart + NAME_ENTRY_COUNT)
end = OpenReqFileIO->NameStart + NAME_ENTRY_COUNT;
else end = OpenReqFileIO->NameCount;
bufferpos = 0;
/* The current file names are stored in the fileio's Remember list */
remember = OpenReqFileIO->NameKey;
for (i = 0; i < OpenReqFileIO->NameStart; i++)
remember = remember->NextRemember;
for (i = OpenReqFileIO->NameStart; i < end; i++)
{
ptr = &OpenSelectBuffers[bufferpos][0];
ptr2 = remember->Memory;
length = StringLength(ptr2);
if (length >= VISIBLE_SELECT_LENGTH)
length = VISIBLE_SELECT_LENGTH - 1;
blanklength = (VISIBLE_SELECT_LENGTH - 1) - length;
/* By filling up the IntuiText with blanks after the characters,
* the text, when printed, will overstrike any characters that were
* there before.
*/
for ( ; length; length--) *ptr++ = *ptr2++;
for ( ; blanklength; blanklength--) *ptr++ = ' ';
*ptr = '\0';
/* If this is the selected text, then use "highlight" pens */
if (i == OpenReqFileIO->CurrentPick)
{
OpenSelectText[bufferpos].FrontPen = -2;
OpenSelectText[bufferpos].BackPen = -1;
}
else
{
OpenSelectText[bufferpos].FrontPen = 1;
OpenSelectText[bufferpos].BackPen = 0;
}
bufferpos++;
remember = remember->NextRemember;
}
/* Now, for all lines that have no entries, fill with blanks */
for ( ; bufferpos < NAME_ENTRY_COUNT; bufferpos++)
BlankSelectText(bufferpos);
/* Finally, redraw the lot */
if (refreshcount)
{
Forbid();
if (layer = OpenReq->ReqLayer)
if (layer->rp)
RefreshGList(&OpenSelectNameGadget, OpenReqWindow, OpenReq,
refreshcount);
DrawSelectNames();
Permit();
}
}
VOID SetNameStart()
/* This little guy sets the NameStart based on the current
* prop gadget setting.
*/
{
if (OpenReqFileIO->NameCount <= NAME_ENTRY_COUNT)
OpenReqFileIO->NameStart = 0;
else
OpenReqFileIO->NameStart = (OpenPropInfo.VertPot
* (OpenReqFileIO->NameCount - NAME_ENTRY_COUNT + 1)) >> 16;
}
VOID StripLastDrawer()
/* This guy strips the end drawer reference off of the drawer string,
* which includes nulling out the string if there's only one to strip.
*/
{
UBYTE *ptr;
SHORT index;
ptr = OpenDrawerTextInfo.Buffer;
index = IndexString(ptr, "/");
if (index != -1)
{
/* OK, there's more than one drawer reference, so get the ptr + index
* to the last one.
*/
do
ptr += (index + 1);
while ((index = IndexString(ptr, "/")) != -1);
}
else index = 0;
/* Zammo! */
*(ptr + index) = '\0';
}
BOOL DirectoryName()
/* Returns TRUE if the selected name was a directory-type reference
* (up or down), else returns FALSE for a normal filename.
*/
{
struct Remember *nextentry;
SHORT i;
UBYTE entryflags;
if (OpenReqFileIO->NameCount)
{
/* Find the selected entry in the key list */
nextentry = OpenReqFileIO->NameKey;
for (i = OpenReqFileIO->CurrentPick; i > 0; i--)
nextentry = nextentry->NextRemember;
i = StringLength(nextentry->Memory) + 1;
entryflags = *(nextentry->Memory + i);
if (FlagIsSet(entryflags, NAMED_DIRECTORY | NAMED_PREVIOUS))
return(TRUE);
/* else just a normal file name was selected, so fall out to ... */
}
return(FALSE);
}
VOID StuffFileName()
/* If the selected name is a normal filename, stuffs the filename into the
* Name gadget. If the selected name is a directory reference,
* adjusts the drawer gadget accordingly.
* Returns TRUE if the selected name was a directory-type reference
* (up or down), else returns FALSE for a normal filename.
*/
{
struct Remember *nextentry;
SHORT i;
UBYTE entryflags;
if (OpenReqFileIO->NameCount)
{
/* Find the selected entry in the key list */
nextentry = OpenReqFileIO->NameKey;
for (i = OpenReqFileIO->CurrentPick; i; i--)
nextentry = nextentry->NextRemember;
i = StringLength(nextentry->Memory) + 1;
entryflags = *(nextentry->Memory + i);
if (FlagIsSet(entryflags, NAMED_DIRECTORY))
{
/* If there's already a drawer reference, build a proper
* extension before adding the new to the end.
*/
if (StringLength(OpenDrawerTextInfo.Buffer))
ConcatString(OpenDrawerTextInfo.Buffer, "/");
ConcatString(OpenDrawerTextInfo.Buffer,
nextentry->Memory + DIR_TEXT_SIZE);
ResetDrawerText(FALSE);
ResetNameText(TRUE);
}
else if (FlagIsSet(entryflags, NAMED_PREVIOUS))
{
/* Remove the last drawer reference */
StripLastDrawer();
ResetDrawerText(FALSE);
ResetNameText(TRUE);
}
else
{
/* Just a normal old file name was selected */
CopyString(OpenNameTextInfo.Buffer, nextentry->Memory);
ResetNameText(FALSE);
}
}
}
/* ======================================================================= */
/* === Proportional Gadget Routines ====================================== */
/* ======================================================================= */
VOID SetOpenPropPot(resetpos)
BOOL resetpos;
/* This routine resets the vertical pot of the proportional gadget
* with respect to the current number of displayable file names.
*/
{
LONG slack, result;
slack = OpenReqFileIO->NameCount - NAME_ENTRY_COUNT;
if (slack > 0)
{
result = ((LONG)OpenReqFileIO->NameStart << 16) / slack;
if (result > 0xFFFF) result = 0xFFFF;
OpenPropInfo.VertPot = result;
}
else
OpenPropInfo.VertPot = 0;
if (resetpos) OpenPropImage.TopEdge = 0;
}
VOID InitOpenProp(resetpos)
BOOL resetpos;
/* This routine initializes the variable imagery of the proportional
* gadget and then initializes the gadget's vertical pot.
* The BOOL arg resetpos describes whether you want the call to
* SetOpenPropPot() to reset the prop's knob position.
*/
{
LONG namecount, height;
SHORT i, i2;
namecount = OpenReqFileIO->NameCount;
if (namecount <= NAME_ENTRY_COUNT)
{
OpenPropInfo.VertBody = 0xFFFF;
ClearFlag(OpenPropInfo.Flags, FREEVERT);
height = OPENPROP_MAXHEIGHT;
}
else
{
OpenPropInfo.VertBody = ((LONG)NAME_ENTRY_COUNT << 16) / namecount;
SetFlag(OpenPropInfo.Flags, FREEVERT);
height = (OPENPROP_MAXHEIGHT * NAME_ENTRY_COUNT) / namecount;
if (height < OPENPROP_MINHEIGHT) height = OPENPROP_MINHEIGHT;
}
OpenPropImage.Height = height;
for (i = 0; i < OPENPROP_TOPHEIGHT; i++)
{
OpenPropData[i] = OpenPropTop[i];
OpenPropData[i + height] = OpenPropTop[i + OPENPROP_TOPHEIGHT];
}
for (i = OPENPROP_TOPHEIGHT; i < height - OPENPROP_BOTTOMHEIGHT; i++)
{
OpenPropData[i] = OpenPropBottom[0];
OpenPropData[i + height] = OpenPropBottom[OPENPROP_BOTTOMHEIGHT];
}
i2 = 0;
for (i = height - OPENPROP_BOTTOMHEIGHT; i < height; i++)
{
OpenPropData[i] = OpenPropBottom[i2];
OpenPropData[i + height] = OpenPropBottom[i2 + OPENPROP_BOTTOMHEIGHT];
i2++;
}
SetOpenPropPot(resetpos);
}
/* ======================================================================= */
/* === Requester Handler Routines ======================================== */
/* ======================================================================= */
VOID StartOpenRequester()
/* Called after the requester has been opened. */
{
ActivateGadget(&OpenNameTextGadget, OpenReqWindow, OpenReq);
if (FlagIsClear(OpenReqFileIO->Flags, GOOD_FILENAMES))
WarmStartFileIO(OpenReqFileIO);
else DrawSelectNames();
}
SHORT HandleSelect(y, seconds, micros)
SHORT y;
LONG seconds, micros;
/* This routine accepts that a GADGETDOWN occured at the given
* pointer y offset. This is translated into the ordinal number of the
* filename selected by the user, and this is assigned to the
* CurrentPick variable of the OpenReqFileIO structure.
* Returns:
* 1 = DirectoryName() returned TRUE (selection was directory name)
* 0 = new name selected, DirectoryName() returned FALSE (normal name)
* -1 = same name selected, double-clicked
* -2 = same name selected, not double-clicked
*/
{
SHORT returnvalue, oldy;
LONG oldseconds, oldmicros;
y -= (OpenReq->TopEdge + OPENSELECT_TOP);
y = y / OPEN_LINEHEIGHT;
y += OpenReqFileIO->NameStart;
if (y >= OpenReqFileIO->NameCount)
y = OpenReqFileIO->NameCount - 1;
oldseconds = OpenClickSeconds;
oldmicros = OpenClickMicros;
OpenClickSeconds = seconds;
OpenClickMicros = micros;
oldy = OpenReqFileIO->CurrentPick;
OpenReqFileIO->CurrentPick = y;
if (DirectoryName())
{
returnvalue = 1;
}
else
{
if (y == oldy)
{
/* User has selected the same name again.
* Was it done quickly enough to count as a
* double-click selection?
*/
if (FlagIsClear(OpenReqFileIO->Flags, DOUBLECLICK_OFF)
&& DoubleClick(oldseconds, oldmicros,
OpenClickSeconds, OpenClickMicros))
returnvalue = -1;
else returnvalue = -2;
}
else
{
/* Do this work, what there is of it, only if the user
* hasn't reselected an already-selected name.
*/
returnvalue = 0;
}
}
return(returnvalue);
}
LONG HandleGadget(gadget, x, y, seconds, micros)
struct Gadget *gadget;
SHORT x, y;
LONG seconds, micros;
/* This routine handles one gadget selection */
{
BOOL softbuild, hardbuild;
SHORT count;
LONG returnvalue;
/* softbuild causes the file names to be refreshed.
* hardbuild causes the entire requester to be reestablished.
* either or both can be set.
*/
softbuild = hardbuild = FALSE;
/* count refers to the count that will be sent to StuffSelectNames().
* The default is 2, as you can see.
*/
count = 2;
/* If the selection of any gadget causes us to want the requester to
* go away, set the returnvalue non-zero.
*/
returnvalue = 0;
switch (gadget->GadgetID)
{
case OPENGADGET_SELECTNAME:
if (OpenReqFileIO->NameCount)
{
/* So our big name gadget was selected, eh? Well, which one
* was the user really pointing at?
*/
y = HandleSelect(y, seconds, micros);
if (y < 0)
{
/* The user has reselected the old name */
if (y == -1) returnvalue = -1;
}
else
{
/* The user has selected a new name */
StuffFileName();
softbuild = TRUE;
if (y == 1) hardbuild = TRUE;
count = 5;
}
}
break;
case OPENGADGET_UPGADGET:
if (OpenReqFileIO->NameStart)
{
OpenReqFileIO->NameStart--;
softbuild = TRUE;
}
break;
case OPENGADGET_DOWNGADGET:
if (OpenReqFileIO->NameStart + NAME_ENTRY_COUNT
< OpenReqFileIO->NameCount)
{
OpenReqFileIO->NameStart++;
softbuild = TRUE;
}
break;
case OPENGADGET_PROPGADGET:
if (OpenReqFileIO->NameCount > NAME_ENTRY_COUNT)
{
SetNameStart();
softbuild = TRUE;
}
break;
case OPENGADGET_NEXTDISK:
/* Next disk! Wholly mackerel! First, if no "next" then split */
if (OpenReqFileIO->VolumeCount <= 1) break;
OpenReqFileIO->VolumeIndex++;
if (OpenReqFileIO->VolumeIndex >= OpenReqFileIO->VolumeCount)
OpenReqFileIO->VolumeIndex = 0;
CopyString(&OpenReqFileIO->DiskName[0], CurrentVolumeName());
ResetDiskText(FALSE);
ResetDrawerText(TRUE);
/* Refresh the display so the user can see what's been done, as
* well as having the display refreshed all over again (hardbuild)
* below after the new filenames are retrieved.
*/
softbuild = TRUE;
count = 5;
/* Intentionally fall into DRAWER/DISKTEXT */
case OPENGADGET_DRAWERTEXT:
case OPENGADGET_DISKTEXT:
ResetNameText(TRUE);
hardbuild = TRUE;
break;
default:
break;
}
/* These are split intentionally, because setters of hardbuild might
* want a softbuild done first, to show why a hardbuild is being done!
*/
if (hardbuild) SetWaitPointer(OpenReqWindow);
if (softbuild)
{
SetOpenPropPot();
StuffSelectNames(count);
}
if (hardbuild)
WarmStartFileIO(OpenReqFileIO); /* Restart the lock etc. */
return(returnvalue);
}
VOID DiskInserted()
/* This routine is called by the RequesterSupport code whenever a new disk
* has been inserted. This allows the user to swap disks while the
* requester is displayed. Unfortunately, I have no way of knowing which
* disk swapped, so I have to restart the requester more or less.
* Not too bad, but a little unpleasant.
*/
{
SetWaitPointer(OpenReqWindow);
SetFlag(OpenReqFileIO->Flags, DISK_HAS_CHANGED);
BuildVolumeTable(OpenReqFileIO);
CopyString(&OpenReqFileIO->DiskName[0], CurrentVolumeName());
WarmStartFileIO(OpenReqFileIO);
}
VOID PropMouseMoves()
/* This routine is called by RequesterSupport whenever the mouse moves
* while a FOLLOWMOUSE gadget is set. The only FOLLOWMOUSE gadget is
* the prop gadget, so...
*/
{
/* ... if there's more names than the number of visible names,
* then reset the name start and redisplay the names.
*/
if (OpenReqFileIO->NameCount > NAME_ENTRY_COUNT)
{
SetNameStart();
StuffSelectNames(2);
}
}
/* *** opendata.c ***********************************************************
*
* File IO Suite -- Open Requester Data
* from Book 1 of the Amiga Programmers' Suite by RJ Mical
*
* Copyright (C) 1986, 1987, Robert J. Mical
* All Rights Reserved.
*
* Created for Amiga developers.
* Any or all of this code can be used in any program as long as this
* entire copyright notice is retained, ok? Thanks.
*
* The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable.
* All copyright notices and all file headers must be retained intact.
* The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the
* resultant object code may be included in any software product. However, no
* portion of the source listings or documentation of the Amiga Programmer's
* Suite Book 1 may be distributed or sold for profit or in a for-profit
* product without the written authorization of the author, RJ Mical.
*
* HISTORY NAME DESCRIPTION
* ----------- -------------- --------------------------------------------
* 18 Aug 87 RJ Removed SELECTED from most string gadgets
* 18 Aug 87 RJ Added KeyHandler field to ReqSupport
* 12 Aug 86 RJ >:-{)* Prepare (clean house) for release
* 3 May 86 =RJ Mical= Fix prop gadget for both 1.1 and 1.2
* 1 Feb 86 =RJ Mical= Created this file.
*
* *********************************************************************** */
#define FILEIO_SOURCEFILE
#include "fileio.h"
struct TextAttr SafeFont =
{
(UBYTE *)"topaz.font",
TOPAZ_EIGHTY,
0,
0,
};
/* This is where the Select text is kept! This array of text will be
* redrawn every time we want Intuition to redraw the lowly SelectGadget.
* The strings themselves are kept in OpenSelectBuffers where
* the open routines make sure that the buffers are padded with
* blanks and are always null-terminated. Ha ha! Like madmen
* dancing, like crazy monkeys.
*/
UBYTE OpenSelectBuffers[NAME_ENTRY_COUNT][VISIBLE_SELECT_LENGTH];
struct IntuiText OpenSelectText[NAME_ENTRY_COUNT] =
{
{
1, 0,
JAM2,
1, 1 + (OPEN_LINEHEIGHT * 0),
&SafeFont,
&OpenSelectBuffers[0][0],
NULL,
},
{
1, 0,
JAM2,
1, 1 + (OPEN_LINEHEIGHT * 1),
&SafeFont,
&OpenSelectBuffers[1][0],
&OpenSelectText[0],
},
{
1, 0,
JAM2,
1, 1 + (OPEN_LINEHEIGHT * 2),
&SafeFont,
&OpenSelectBuffers[2][0],
&OpenSelectText[1],
},
{
1, 0,
JAM2,
1, 1 + (OPEN_LINEHEIGHT * 3),
&SafeFont,
&OpenSelectBuffers[3][0],
&OpenSelectText[2],
},
{
1, 0,
JAM2,
1, 1 + (OPEN_LINEHEIGHT * 4),
&SafeFont,
&OpenSelectBuffers[4][0],
&OpenSelectText[3],
},
{
1, 0,
JAM2,
1, 1 + (OPEN_LINEHEIGHT * 5),
&SafeFont,
&OpenSelectBuffers[5][0],
&OpenSelectText[4],
},
};
/* === Backdrop Gadget =================================================== */
/* We shouldn't need this gadget. It's sole purpose is to allow the user
* to cancel the filename building operation by clicking outside any of
* the regular requester gadgets. Why, we may ask, don't we just make
* the requester a NOISYREQ and detect SELECTDOWN. Well, we tried that,
* and either there's something wrong with our brains or 1.2 Intuition has
* a bug that doesn't broadcast SELECTDOWN to requester listeners.
* It broadcasts SELECTUP, MENUDOWN and MENUUP jes' fine, but no DOWN.
* Bummer. So anyway, now we got an imageless, highlightless gadget that
* fills up the entire requester but, being at the back of the list, won't
* be hit unless all other gadgets are missed.
* Having a wonderful time, wish you were here.
*/
struct Gadget BackdropGadget =
{
NULL,
0, 0,
OPEN_WIDTH, OPEN_HEIGHT,
GADGHNONE, /* Flags */
GADGIMMEDIATE, /* Activation */
REQGADGET | BOOLGADGET, /* Type */
NULL, /* GadgetRender */
NULL, /* SelectRender */
NULL,
NULL, NULL,
OPENGADGET_BACKDROP,
NULL,
};
/* === OK, Cancel, and NextDisk Gadgets ================================== */
SHORT BoolCluster3Pairs[] =
{
0, -3,
55, -3,
57, -1,
57, 19,
55, 21,
-1, 21,
-3, 19,
-3, -1,
-1, -3,
};
SHORT BoolCluster2Pairs[] =
{
-2, -1,
56, -1,
56, 19,
-2, 19,
-2, -1,
};
SHORT BoolClusterPairs[] =
{
-1, -2,
55, -2,
55, 20,
-1, 20,
-1, -2,
};
struct Border BoolCluster3Border =
{
1, 1,
2, 0,
JAM1,
9,
&BoolCluster3Pairs[0],
NULL,
};
struct Border BoolCluster2Border =
{
1, 1,
1, 0,
JAM1,
5,
&BoolCluster2Pairs[0],
&BoolCluster3Border,
};
struct Border BoolClusterBorder =
{
1, 1,
1, 0,
JAM1,
5,
&BoolClusterPairs[0],
&BoolCluster2Border,
};
struct IntuiText NextDisk2Text =
{
1, 0,
JAM2,
13, 11,
&SafeFont,
(UBYTE *)"DISK",
NULL,
};
struct IntuiText NextDiskText =
{
1, 0,
JAM2,
13, 3,
&SafeFont,
(UBYTE *)"NEXT",
&NextDisk2Text,
};
struct IntuiText CancelText =
{
1, 0,
JAM2,
5, 7,
&SafeFont,
(UBYTE *)"CANCEL",
NULL,
};
struct IntuiText OK2Text =
{
1, 0,
JAM2,
17, 7,
&SafeFont,
(UBYTE *)"OK!",
NULL,
};
struct Gadget NextDiskGadget =
{
&BackdropGadget,
197, 82 + REQTITLE_HEIGHT,
57, 21,
GADGHCOMP, /* Flags */
RELVERIFY, /* Activation */
REQGADGET | BOOLGADGET, /* Type */
(APTR)&BoolClusterBorder, /* GadgetRender */
NULL, /* SelectRender */
&NextDiskText,
NULL, NULL,
OPENGADGET_NEXTDISK,
NULL,
};
struct Gadget CancelGadget =
{
&NextDiskGadget,
114, 82 + REQTITLE_HEIGHT,
57, 21,
GADGHCOMP, /* Flags */
RELVERIFY | ENDGADGET, /* Activation */
REQGADGET | BOOLGADGET, /* Type */
(APTR)&BoolClusterBorder, /* GadgetRender */
NULL, /* SelectRender */
&CancelText,
NULL, NULL,
OPENGADGET_CANCEL,
NULL,
};
struct Gadget OKGadget =
{
&CancelGadget,
32, 82 + REQTITLE_HEIGHT,
57, 21,
GADGHCOMP, /* Flags */
RELVERIFY | ENDGADGET, /* Activation */
REQGADGET | BOOLGADGET, /* Type */
(APTR)&BoolClusterBorder,
NULL, /* Renders */
&OK2Text,
NULL, NULL,
OPENGADGET_OK,
NULL,
};
/* === OpenUp ============================================================= */
struct Image OpenUpImage =
{
1, -1,
15, 14,
2,
&OpenUpData[0],
0x03, 0x00,
NULL,
};
struct Gadget OpenUpGadget =
{
&OKGadget,
134, 14 + REQTITLE_HEIGHT,
15, 12,
GADGIMAGE | GADGHNONE, /* Flags */
GADGIMMEDIATE, /* Activation */
REQGADGET | BOOLGADGET, /* Type */
(APTR)&OpenUpImage,
NULL, /* Renders */
NULL,
NULL, NULL,
OPENGADGET_UPGADGET,
NULL,
};
/* === OpenDown =========================================================== */
struct Image OpenDownImage =
{
1, -1,
15, 14,
2,
&OpenDownData[0],
0x03, 0x00,
NULL,
};
struct Gadget OpenDownGadget =
{
&OpenUpGadget,
134, 64 + REQTITLE_HEIGHT,
15, 12,
GADGIMAGE | GADGHNONE, /* Flags */
GADGIMMEDIATE, /* Activation */
REQGADGET | BOOLGADGET, /* Type */
(APTR)&OpenDownImage,
NULL, /* Renders */
NULL,
NULL, NULL,
OPENGADGET_DOWNGADGET,
NULL,
};
/* === OpenDrawerText ==================================================== */
struct StringInfo OpenDrawerTextInfo =
{
NULL, /* Must be supplied from the appropriate FileIOSupport structure */
&OpenUndoBuffer[0],
0,
MAX_NAME_LENGTH,
0,
0,0,0,0,0,0,0,0,
};
struct Gadget OpenDrawerTextGadget =
{
&OpenDownGadget,
157, 41 + REQTITLE_HEIGHT,
122, 10,
GADGHCOMP, /* Flags */
RELVERIFY | STRINGCENTER, /* Activation */
REQGADGET | STRGADGET, /* Type */
NULL, NULL, /* Renders */
NULL,
NULL,
(APTR)&OpenDrawerTextInfo,
OPENGADGET_DRAWERTEXT,
NULL,
};
/* === OpenDiskText ====================================================== */
struct StringInfo OpenDiskTextInfo =
{
NULL, /* Must be supplied from the appropriate FileIOSupport structure */
&OpenUndoBuffer[0],
0,
MAX_NAME_LENGTH,
0,
0,0,0,0,0,0,0,0,
};
struct Gadget OpenDiskTextGadget =
{
&OpenDrawerTextGadget,
157, 65 + REQTITLE_HEIGHT,
122, 10,
GADGHCOMP, /* Flags */
RELVERIFY | STRINGCENTER, /* Activation */
REQGADGET | STRGADGET, /* Type */
NULL, NULL, /* Renders */
NULL,
NULL,
(APTR)&OpenDiskTextInfo,
OPENGADGET_DISKTEXT,
NULL,
};
/* === OpenNameText ====================================================== */
struct StringInfo OpenNameTextInfo =
{
NULL, /* Must be supplied from the appropriate FileIOSupport structure */
&OpenUndoBuffer[0],
0,
MAX_NAME_LENGTH,
0,
0,0,0,0,0,0,0,0,
};
struct Gadget OpenNameTextGadget =
{
&OpenDiskTextGadget,
157, 16 + REQTITLE_HEIGHT,
122, 10,
GADGHCOMP | SELECTED, /* Flags */
RELVERIFY | ENDGADGET | STRINGCENTER, /* Activation */
REQGADGET | STRGADGET, /* Type */
NULL, NULL, /* Renders */
NULL,
NULL,
(APTR)&OpenNameTextInfo,
OPENGADGET_NAMETEXT,
NULL,
};
/* === OpenProp =========================================================== */
/* OpenPropData[] is in chipdata.c */
struct Image OpenPropImage =
{
1, 0,
11, 8,
2,
&OpenPropData[0],
0x03, 0x00,
NULL,
};
struct PropInfo OpenPropInfo =
{
FREEVERT | PROPBORDERLESS,
0, 0, /* Pots should be reinitialized on the fly */
0, 0, /* Bodies should be reinitialized on the fly */
0, 0, 0, 0, 0, 0,
};
struct Gadget OpenPropGadget =
{
&OpenNameTextGadget,
136, 30 + REQTITLE_HEIGHT, /* Left, Top */
13, 30, /* Width, Height */
GADGIMAGE | GADGHNONE, /* Flags */
GADGIMMEDIATE | RELVERIFY | FOLLOWMOUSE, /* Activation */
REQGADGET | PROPGADGET, /* Type */
(APTR)&OpenPropImage,
NULL, /* Renders */
NULL,
NULL,
(APTR)&OpenPropInfo,
OPENGADGET_PROPGADGET,
NULL,
};
/* === OpenSelectName ==================================================== */
struct Gadget OpenSelectNameGadget =
{
&OpenPropGadget,
OPENSELECT_LEFT, OPENSELECT_TOP, /* Left, Top */
OPENSELECT_WIDTH, OPENSELECT_HEIGHT, /* Width, Height */
GADGHNONE, /* Flags */
GADGIMMEDIATE, /* Activation */
REQGADGET | BOOLGADGET, /* Type */
NULL, NULL, /* Renders */
NULL, /* Text */
NULL, NULL,
OPENGADGET_SELECTNAME,
NULL,
};
/* === Requester Details ================================================= */
/* This data is used to render the requester more prettily. */
/* === Line Pairs === */
SHORT Req3BorderData[] =
{
1, 0,
OPEN_WIDTH - 2, 0,
OPEN_WIDTH - 2, 1,
OPEN_WIDTH - 1, 1,
OPEN_WIDTH - 1, 108 + REQTITLE_HEIGHT,
OPEN_WIDTH - 2, 108 + REQTITLE_HEIGHT,
OPEN_WIDTH - 2, 109 + REQTITLE_HEIGHT,
1, 109 + REQTITLE_HEIGHT,
1, 108 + REQTITLE_HEIGHT,
0, 108 + REQTITLE_HEIGHT,
0, 1,
1, 1,
1, 0,
};
SHORT Req2BorderData[] =
{
1 + 1, 0 + 1,
OPEN_WIDTH - 2 - 1, 0 + 1,
OPEN_WIDTH - 2 - 1, 1 + 1,
OPEN_WIDTH - 1 - 1, 1 + 1,
OPEN_WIDTH - 1 - 1, 108 - 1 + REQTITLE_HEIGHT,
OPEN_WIDTH - 2 - 1, 108 - 1 + REQTITLE_HEIGHT,
OPEN_WIDTH - 2 - 1, 109 - 1 + REQTITLE_HEIGHT,
1 + 1, 109 - 1 + REQTITLE_HEIGHT,
1 + 1, 108 - 1 + REQTITLE_HEIGHT,
0 + 1, 108 - 1 + REQTITLE_HEIGHT,
0 + 1, 1 + 1,
1 + 1, 1 + 1,
1 + 1, 0 + 1,
};
SHORT ReqBorderData[] =
{
1 + 2, 0 + 2,
OPEN_WIDTH - 2 - 2, 0 + 2,
OPEN_WIDTH - 2 - 2, 1 + 2,
OPEN_WIDTH - 1 - 2, 1 + 2,
OPEN_WIDTH - 1 - 2, 108 - 2 + REQTITLE_HEIGHT,
OPEN_WIDTH - 2 - 2, 108 - 2 + REQTITLE_HEIGHT,
OPEN_WIDTH - 2 - 2, 109 - 2 + REQTITLE_HEIGHT,
1 + 2, 109 - 2 + REQTITLE_HEIGHT,
1 + 2, 108 - 2 + REQTITLE_HEIGHT,
0 + 2, 108 - 2 + REQTITLE_HEIGHT,
0 + 2, 1 + 2,
1 + 2, 1 + 2,
1 + 2, 0 + 2,
};
SHORT SelectBorderData[] =
{
8, 14 + REQTITLE_HEIGHT,
129, 14 + REQTITLE_HEIGHT,
130, 15 + REQTITLE_HEIGHT,
130, 74 + REQTITLE_HEIGHT,
129, 75 + REQTITLE_HEIGHT,
8, 75 + REQTITLE_HEIGHT,
7, 74 + REQTITLE_HEIGHT,
7, 15 + REQTITLE_HEIGHT,
8, 14 + REQTITLE_HEIGHT,
};
SHORT TextBorderData[] =
{
-1, -2,
120, -2,
121, -1,
121, 8,
120, 9,
-1, 9,
-2, 8,
-2, -1,
-1, -2,
};
SHORT PropBorderData[] =
{
0, -3,
16, -3,
16, 32,
0, 32,
0, -2,
15, -2,
15, -1,
17, -1,
17, 30,
15, 30,
15, 31,
1, 31,
1, 30,
-1, 30,
-1, -1,
-1, 1,
};
/* === Borders === */
struct Border Req3Border =
{
0, 0,
1, 0,
JAM1,
13,
&Req3BorderData[0],
NULL,
};
struct Border Req2Border =
{
0, 0,
2, 0,
JAM1,
13,
&Req2BorderData[0],
&Req3Border,
};
struct Border ReqBorder =
{
0, 0,
1, 0,
JAM1,
13,
&ReqBorderData[0],
&Req2Border,
};
struct Border SelectBorder =
{
0, 0,
1, 0,
JAM1,
9,
&SelectBorderData[0],
&ReqBorder,
};
struct Border Text3Border =
{
157, 65 + REQTITLE_HEIGHT,
1, 0,
JAM1,
9,
&TextBorderData[0],
&SelectBorder,
};
struct Border Text2Border =
{
157, 41 + REQTITLE_HEIGHT,
1, 0,
JAM1,
9,
&TextBorderData[0],
&Text3Border,
};
struct Border TextBorder =
{
157, 16 + REQTITLE_HEIGHT,
1, 0,
JAM1,
9,
&TextBorderData[0],
&Text2Border,
};
struct Border PropBorder =
{
134, 30 + REQTITLE_HEIGHT,
1, 0,
JAM1,
16,
&PropBorderData[0],
&TextBorder,
};
/* === RJ wants to know: Some Requester Text For You? === */
UBYTE *DefaultReqTitle = (UBYTE *)"File IO Requester";
struct IntuiText ReqTitleText =
{
1, 0,
JAM2,
0, 5, /* The x-coordinate is initialized to center the title */
&SafeFont,
NULL, /* Points to the title supplied in the FileIOSupport */
NULL,
};
struct IntuiText SelectText =
{
1, 0,
JAM2,
18, 6 + REQTITLE_HEIGHT,
&SafeFont,
(UBYTE *)"Select a Name",
&ReqTitleText,
};
struct IntuiText Type3Text =
{
1, 0,
JAM2,
201, 55 + REQTITLE_HEIGHT,
&SafeFont,
(UBYTE *)"Disk",
&SelectText,
};
struct IntuiText Type2Text =
{
1, 0,
JAM2,
193, 31 + REQTITLE_HEIGHT,
&SafeFont,
(UBYTE *)"Drawer",
&Type3Text,
};
struct IntuiText TypeText =
{
1, 0,
JAM2,
161, 6 + REQTITLE_HEIGHT,
&SafeFont,
(UBYTE *)"Or Type a Name",
&Type2Text,
};
/* === Main Data ======================================================== */
struct ReqSupport OpenReqSupport =
{
/* struct Requester Requester; */
{
/* struct Requester *OlderRequest;*/
NULL,
/* SHORT LeftEdge, TopEdge;*/
OPEN_LEFT, OPEN_TOP,
/* SHORT Width, Height;*/
OPEN_WIDTH, OPEN_HEIGHT,
/* SHORT RelLeft, RelTop;*/
0, 0,
/* struct Gadget *ReqGadget;*/
&OpenSelectNameGadget,
/* struct Border *ReqBorder;*/
&PropBorder,
/* struct IntuiText *ReqText;*/
&TypeText,
/* USHORT Flags;*/
NOISYREQ,
/* UBYTE BackFill;*/
0,
/* struct ClipRect ReqCRect;*/
{ NULL },
/* struct BitMap *ImageBMap;*/
NULL,
/* struct BitMap ReqBMap;*/
{ NULL },
}, /* end of Requester structure */
/* struct Window *Window; */
NULL,
/* LONG (*StartRequest)(); */
NULL,
/* LONG (*ReqHandler)(); */
NULL,
/* LONG (*NewDiskHandler)(); */
NULL,
/* LONG (*KeyHandler)(); */
NULL,
/* LONG (*MouseMoveHandler)(); */
NULL,
/* SHORT SelectedGadgetID; */
0,
};
struct Requester *OpenReq = NULL;
struct Window *OpenReqWindow = NULL;
struct FileIOSupport *OpenReqFileIO = NULL;
UBYTE OpenUndoBuffer[MAX_NAME_LENGTH];
UBYTE OpenLockName[128] = {0};
ULONG OpenSaveLock = NULL;
UBYTE CurrentDiskString[] = ":";
LONG OpenClickSeconds;
LONG OpenClickMicros;
/* *** chipdata.c ***********************************************************
*
* File IO Suite -- Chip Memory Data Declarations
* from Book 1 of the Amiga Programmers' Suite by RJ Mical
*
* Copyright (C) 1986, 1987, Robert J. Mical
* All Rights Reserved.
*
* Created for Amiga developers.
* Any or all of this code can be used in any program as long as this
* entire copyright notice is retained, ok?
*
* The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable.
* All copyright notices and all file headers must be retained intact.
* The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the
* resultant object code may be included in any software product. However, no
* portion of the source listings or documentation of the Amiga Programmer's
* Suite Book 1 may be distributed or sold for profit or in a for-profit
* product without the written authorization of the author, RJ Mical.
*
* HISTORY NAME DESCRIPTION
* ----------- -------------- --------------------------------------------
* 4 Feb 87 RJ Real release
* 12 Aug 86 RJ >:-{)* Prepare (clean house) for release
* 3 May 86 =RJ Mical= Fix prop gadget for both 1.1 and 1.2
* 1 Feb 86 =RJ Mical= Created this file.
*
* *********************************************************************** */
#define FILEIO_SOURCEFILE
/* This prevents eglobfio.c from being included */
#define EGLOBAL_FILEIO_CANCEL
#include "fileio.h"
/* === WaitPointer Imagery =============================================== */
USHORT ElecArtsWaitPointer[(ELECARTSPOINT_HEIGHT * 2) + 4] =
{
0x0000, 0x0000,
0x6700, 0xC000,
0xCFA0, 0xC700,
0xBFF0, 0x0FA0,
0x70F8, 0x3FF0,
0x7DFC, 0x3FF8,
0xFBFC, 0x7FF8,
0x70FC, 0x3FF8,
0x7FFE, 0x3FFC,
0x7F0E, 0x3FFC,
0x3FDF, 0x1FFE,
0x7FBE, 0x3FFC,
0x3F0E, 0x1FFC,
0x1FFC, 0x07F8,
0x07F8, 0x01E0,
0x01E0, 0x0080,
0x07C0, 0x0340,
0x0FE0, 0x07C0,
0x0740, 0x0200,
0x0000, 0x0000,
0x0070, 0x0020,
0x0078, 0x0038,
0x0038, 0x0010,
0x0000, 0x0000,
};
/* === Open Requester Imagery ============================================ */
USHORT OpenPropData[OPENPROP_MAXHEIGHT * 2];
USHORT OpenPropTop[OPENPROP_TOPHEIGHT * 2] =
{
/* plane 0 */
0x7FC0,
0xE0E0,
/* plane 1 */
0x0000,
0x1F00,
};
USHORT OpenPropBottom[OPENPROP_BOTTOMHEIGHT * 2] =
{
/* plane 0 */
0xC060,
0xC060,
0xC060,
0xC060,
0xE0E0,
0x7FC0,
/* plane 1 */
0x3F80,
0x3F80,
0x3F80,
0x3F80,
0x1F00,
0x0000,
};
USHORT OpenUpData[] =
{
/* plane 0 */
0x0100,
0x739C,
0x87C2,
0x8FE2,
0x9FF2,
0xBFFA,
0x8382,
0x8382,
0x8382,
0x8382,
0x8382,
0x7BBC,
0x0380,
0x0380,
/* plane 1 */
0x0000,
0x0000,
0x600C,
0x4004,
0x0000,
0x0000,
0x0000,
0x783C,
0x783C,
0x783C,
0x783C,
0x0000,
0x0000,
0x0000,
};
USHORT OpenDownData[] =
{
/* plane 0 */
0x0380,
0x0380,
0x7BBC,
0x8382,
0x8382,
0x8382,
0x8382,
0x8382,
0xBFFA,
0x9FF2,
0x8FE2,
0x87C2,
0x739C,
0x0100,
/* plane 1 */
0x0000,
0x0000,
0x0000,
0x783C,
0x783C,
0x783C,
0x783C,
0x0000,
0x0000,
0x0000,
0x4004,
0x600C,
0x0000,
0x0000,
};
/* *** volname.c ************************************************************
*
* File IO Suite -- Volume Name Construction Routines
* from Book 1 of the Amiga Programmers' Suite by RJ Mical
*
* Copyright (C) 1986, 1987, Robert J. Mical
* All Rights Reserved.
*
* Created for Amiga developers.
* Any or all of this code can be used in any program as long as this
* entire copyright notice is retained, ok? Thanks.
*
* The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable.
* All copyright notices and all file headers must be retained intact.
* The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the
* resultant object code may be included in any software product. However, no
* portion of the source listings or documentation of the Amiga Programmer's
* Suite Book 1 may be distributed or sold for profit or in a for-profit
* product without the written authorization of the author, RJ Mical.
*
* HISTORY NAME DESCRIPTION
* ----------- -------------- --------------------------------------------
* 27 Sep 87 RJ Leave VolumeIndex alone as much as possible.
* Also, after building a new volume table, try
* to look up the old volume name among the
* new volume entries and set VolumeIndex
* if possible.
* 4 Feb 87 RJ Real release
* 12 Aug 86 RJ >:-{)* Prepare (clean house) for release
* 3 May 86 =RJ Mical= Fix prop gadget for both 1.1 and 1.2
* 1 Feb 86 =RJ Mical= Created this file.
*
* *********************************************************************** */
#define FILEIO_SOURCEFILE
#include "fileio.h"
#include <libraries/dosextens.h>
/* Lattice doesn't accept the ID_DOS_DISK which looks like this:
* #define ID_DOS_DISK ('DOS\0')
* so I make up my own.
*/
#define X_ID_DOS_DISK (((LONG)'D'<<24)|((LONG)'O'<<16)|('S'<<8)|('\0'))
BOOL DOSDisk(device)
struct DeviceList *device;
/* This little routine dips its gnarled toes directly into the
* scary murky depths of AmigaDOS interior.
* If it survives, it returns TRUE or FALSE depending on whether or
* the specified device is a DOS disk.
* Jeez, Look at the structure names in this routine! Whew! You almost
* gotta be a computer scientist to understand this stuff.
*/
{
struct MsgPort *port;
BOOL result;
struct InfoData *info;
struct StandardPacket *packet;
result = FALSE;
/* Allocate the data structures required to communicate with AmigaDOS */
info = (struct InfoData *)AllocMem(sizeof(struct InfoData), MEMF_CLEAR);
packet = (struct StandardPacket *)AllocMem(sizeof(struct StandardPacket),
MEMF_CLEAR);
/* Grab us a message port for the reply from DOS */
port = CreatePort(NULL, 0);
if (port && info && packet)
{
/* OK, everything is set so here we go! */
/* Set up the StandardPacket's Exec message */
packet->sp_Msg.mn_Node.ln_Type = NT_MESSAGE;
packet->sp_Msg.mn_Node.ln_Name = (char *)&packet->sp_Pkt;
packet->sp_Msg.mn_ReplyPort = port;
/* Set up the StandardPacket's DOS data */
packet->sp_Pkt.dp_Link = &packet->sp_Msg;
packet->sp_Pkt.dp_Type = ACTION_DISK_INFO;
packet->sp_Pkt.dp_Arg1 = ((LONG)info >> 2);
packet->sp_Pkt.dp_Port = port;
/* Now, ask the device whether or not it's a DOS disk */
PutMsg(device->dl_Task, &packet->sp_Msg);
/* zzz */
WaitPort(port);
/* Well? */
if (info->id_DiskType == X_ID_DOS_DISK) result = TRUE;
}
if (port) DeletePort(port);
if (info) FreeMem(info, sizeof(struct InfoData));
if (packet) FreeMem(packet, sizeof(struct StandardPacket));
return(result);
}
VOID BuildVolumeTable(fileio)
struct FileIOSupport *fileio;
/* This routine builds an alphabetically-sorted list of all active volumes.
* The names can be either the device names or the volume names, depending
* on whether you set USE_VOLUME_NAMES.
*/
{
struct DosInfo *dosinfo;
struct DeviceList *masterlist, *devlist, *worklist;
struct MsgPort *handler;
LONG yuck;
UBYTE *nameptr, *textptr;
UBYTE len;
SHORT i;
struct Remember **key, *localkey, *keyptr;
if (DosBase == NULL) return;
key = &fileio->VolumeKey;
FreeRemember(key, TRUE);
localkey = NULL;
/* FORMERLY: fileio->VolumeCount = fileio->VolumeIndex = 0;
* Instead, try leaving index where it was, clipping as needed at the end
*/
fileio->VolumeCount = 0;
/* First, feel through from DosBase down to the device list, dancing
* all the while with the bcpl pointers.
*/
yuck = (LONG)((struct RootNode *)DosBase->dl_Root)->rn_Info;
dosinfo = (struct DosInfo *)(yuck << 2); /* reality pointer */
yuck = (LONG)dosinfo->di_DevInfo;
masterlist = (struct DeviceList *)(yuck << 2); /* reality pointer */
devlist = masterlist;
while (devlist)
{
/* First, find each device that's active (dl_Task is not NULL) */
if ((devlist->dl_Type == DLT_DEVICE) && (devlist->dl_Task))
{
/* OK, got a device. Now ask it if it's a DOS disk. */
if (NOT DOSDisk(devlist)) goto NEXT_DEVICE;
/* OK, got a device that's a DOS disk. Now find the name.
* If USE_VOLUME_NAMES is clear, use the device name,
* else look up the volume name.
*/
nameptr = (UBYTE *)devlist->dl_Name;
if (FlagIsSet(fileio->Flags, USE_VOLUME_NAMES))
{
/* Use the handler for this volume to find the matching device */
handler = (struct MsgPort *)devlist->dl_Task;
worklist = masterlist;
while (worklist)
{
if ((worklist->dl_Type == DLT_VOLUME)
&& (worklist->dl_Task == handler))
{
nameptr = (UBYTE *)worklist->dl_Name;
goto GOT_NAME;
}
yuck = worklist->dl_Next;
worklist = (struct DeviceList *)(yuck << 2);
}
/* If we get to the end of this loop and fall out, then what?
* Got an active device but no matching volume? OK.
*/
}
GOT_NAME:
yuck = (LONG)nameptr;
nameptr = (UBYTE *)(yuck << 2);
len = *nameptr++;
if ((textptr = AllocRemember(&localkey, len + 2, NULL)) == NULL)
{
Alert(ALERT_OUTOFMEM, NULL);
goto DEVICES_DONE;
}
fileio->VolumeCount++;
for (i = 0; i < len; i++) *textptr++ = *nameptr++;
*textptr++ = ':';
*textptr = '\0';
MakeEntry(localkey->Memory, key, NULL);
}
NEXT_DEVICE:
yuck = devlist->dl_Next;
devlist = (struct DeviceList *)(yuck << 2);
}
DEVICES_DONE:
FreeRemember(&localkey, TRUE);
/* Safety measure */
if (fileio->VolumeIndex >= fileio->VolumeCount)
fileio->VolumeIndex = fileio->VolumeCount - 1;
keyptr = fileio->VolumeKey;
nameptr = &fileio->DiskName[0];
i = 0;
while (keyptr)
{
if (StringsEqual(keyptr->Memory, nameptr))
{
fileio->VolumeIndex = i;
goto DONE;
}
keyptr = keyptr->NextRemember;
i++;
}
fileio->VolumeIndex = 0;
DONE: ;
}
UBYTE *CurrentVolumeName()
/* This routine returns a pointer the name of the current volume */
{
SHORT i;
struct Remember *remember;
/* If there's no active volumes then return the "safe" volume name */
if (OpenReqFileIO->VolumeCount < 1)
return(&CurrentDiskString[0]);
/* Safety measure */
if (OpenReqFileIO->VolumeIndex >= OpenReqFileIO->VolumeCount)
OpenReqFileIO->VolumeIndex = 0;
/* Finally, look up the name */
remember = OpenReqFileIO->VolumeKey;
for (i = 0; i < OpenReqFileIO->VolumeIndex; i++)
remember = remember->NextRemember;
return(remember->Memory);
}
/* *** filename.c ***********************************************************
*
* File IO Suite -- File Name Construction Routines
* from Book 1 of the Amiga Programmers' Suite by RJ Mical
*
* Copyright (C) 1986, 1987, Robert J. Mical
* All Rights Reserved.
*
* Created for Amiga developers.
* Any or all of this code can be used in any program as long as this
* entire copyright notice is retained, ok? Thanks.
*
* The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable.
* All copyright notices and all file headers must be retained intact.
* The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the
* resultant object code may be included in any software product. However, no
* portion of the source listings or documentation of the Amiga Programmer's
* Suite Book 1 may be distributed or sold for profit or in a for-profit
* product without the written authorization of the author, RJ Mical.
*
* HISTORY NAME DESCRIPTION
* ----------- -------------- --------------------------------------------
* 4 Feb 87 RJ Real release
* 12 Aug 86 RJ >:-{)* Prepare (clean house) for release
* 3 May 86 =RJ Mical= Fix prop gadget for both 1.1 and 1.2
* 1 Feb 86 =RJ Mical= Created this file.
*
* *********************************************************************** */
#define FILEIO_SOURCEFILE
#include "fileio.h"
#include <libraries/dosextens.h>
#define FRIENDLY_NOT 0
#define FRIENDLY_DRAWER 1
#define FRIENDLY_OTHER 2
VOID BuildNameTable(fileio)
struct FileIOSupport *fileio;
/* This routine searches through the fileio lock for all file entries,
* and builds a list of the names found.
* If the user wants Workbench-style pattern matching, filenames are
* passed through a filter before being added to the list.
* All directory entries are added to the list.
*/
{
struct FileInfoBlock *fileinfo;
UBYTE *ptr;
UBYTE workname[MAX_NAME_LENGTH + 5]; /* the extra 5 are for the ".info" */
struct Remember **key;
ULONG lock;
SHORT i, flags, type;
SHORT pick;
fileio->NameCount = 0;
lock = fileio->DOSLock;
key = &fileio->NameKey;
FreeRemember(key, TRUE);
ClearFlag(fileio->Flags, GOOD_FILENAMES);
if ((fileinfo = (struct FileInfoBlock *)AllocMem(
sizeof(struct FileInfoBlock), MEMF_CLEAR)) == NULL)
goto BUILD_EXIT;
SetWaitPointer(OpenReqWindow);
/* Now, first, before we might be interrupted by MessageInterrupt(),
* check whether or not we're looking in a drawer and, if so, add the
* entry that allows the user to ascend one drawer.
*/
if (StringLength(&OpenReqFileIO->DrawerName[0]))
{
MakeEntry("\253\253 PRIOR DRAWER", key, NAMED_PREVIOUS);
/* bump the master count */
fileio->NameCount++;
}
/* starting from Examine() until ExNext() is NULL */
if (Examine(lock, fileinfo))
while (ExNext(lock, fileinfo))
{
/* Default: this entry is a normal file */
flags = NULL;
CopyString(&workname[0], fileinfo->fib_FileName);
#ifdef WBENCH_CODE
/* Now, does the caller want Workbench-style pattern matching? */
if (FlagIsSet(fileio->Flags, WBENCH_MATCH))
{
/* start from location 1 to avoid matching the ".info" file */
if (ptr = FindSuffix(&workname[1], ".info"))
{
*ptr = '\0'; /* strip the suffix off that baby */
/* Get the friendliness quotient of this .info file */
type = FriendlyInfoType(&workname[0], fileio);
/* If just not friendly, forget about it */
if (type == FRIENDLY_NOT) goto NEXT_LOCK;
/* If this was a drawer, set the fileinfo as a directory */
if (type == FRIENDLY_DRAWER)
fileinfo->fib_DirEntryType = 1;
}
else goto NEXT_LOCK;
}
#endif /* ... of WBENCH_CODE conditional */
if (fileinfo->fib_DirEntryType >= 0)
{
/* This entry is a directory */
flags = NAMED_DIRECTORY;
/* If you change the following text, change DIR_TEXT_SIZE too */
for (i = StringLength(&workname[0]); i >= 0; i--)
workname[i + DIR_TEXT_SIZE] = workname[i];
workname[0] = '\273';
workname[1] = '\273';
workname[2] = ' ';
}
pick = MakeEntry(&workname[0], key, flags);
/* bump the master count */
fileio->NameCount++;
if (pick <= fileio->CurrentPick)
fileio->CurrentPick++;
InitOpenProp(FALSE);
StuffSelectNames(2);
NEXT_LOCK:
/* If there's a message pending, split with what we've got */
if (MessageInterrupt()) goto EXAMINE_DONE;
}
SetFlag(fileio->Flags, GOOD_FILENAMES);
EXAMINE_DONE:
if (OpenReqWindow) ClearPointer(OpenReqWindow);
FreeMem(fileinfo, sizeof(struct FileInfoBlock));
BUILD_EXIT: ;
}
VOID PropInterrupt()
/* This routine is called by MessageInterrupt() if the prop gadget
* is played with while the file name table is being built.
* As long as the user is using the proportional gadget, hang around here.
*/
{
struct IntuiMessage *message;
struct Gadget *gadget;
BOOL mousemove;
FOREVER
{
WaitPort(OpenReqWindow->UserPort);
mousemove = FALSE;
while (message = GetMsg(OpenReqWindow->UserPort))
{
switch (message->Class)
{
case GADGETUP:
gadget = (struct Gadget *)message->IAddress;
switch (gadget->GadgetID)
{
case OPENGADGET_PROPGADGET:
ReplyMsg(message);
HandleGadget(gadget, 0, 0, 0, 0);
return;
default:
goto MESSAGE_RETURN;
}
break;
case MOUSEMOVE:
ReplyMsg(message);
mousemove = TRUE;
break;
default:
goto MESSAGE_RETURN;
}
}
if (mousemove) PropMouseMoves();
}
MESSAGE_RETURN:
/* Pretend we didn't see this message */
AddHead(&OpenReqWindow->UserPort->mp_MsgList, message);
}
BOOL MessageInterruptGrunt(message)
struct IntuiMessage *message;
/* Test if there's a gadget type of message at the window port,
* react to it if there is one, and return TRUE if the message is
* one that should interrupt the building of the file name list.
*/
{
ULONG class;
SHORT x, y;
struct Gadget *gadget;
LONG seconds, micros;
class = message->Class;
if ((class == GADGETDOWN) || (class == GADGETUP))
{
gadget = (struct Gadget *)message->IAddress;
x = message->MouseX;
y = message->MouseY;
seconds = message->Seconds;
micros = message->Micros;
OpenReqSupport.SelectedGadgetID = gadget->GadgetID;
switch (gadget->GadgetID)
{
case OPENGADGET_SELECTNAME:
y = HandleSelect(y, seconds, micros);
if ((y == -1) || (y == 1))
{
/* Pretend we didn't see this message */
AddHead(&OpenReqWindow->UserPort->mp_MsgList, message);
return(TRUE);
}
StuffFileName();
StuffSelectNames(5);
goto REPLY_AND_RETURN_FALSE;
case OPENGADGET_UPGADGET:
case OPENGADGET_DOWNGADGET:
goto REPLY_AND_RETURN_FALSE;
case OPENGADGET_PROPGADGET:
HandleGadget(gadget, x, y, seconds, micros);
if (class == GADGETDOWN) PropInterrupt();
goto REPLY_AND_RETURN_FALSE;
default:
/* Do nothing, fall into the message's AddHead() below.
* This includes the gadgets OK, CANCEL, NEXTDISK,
* DISKNAME, DRAWERNAME, FILENAME, and BACKDROP.
*/
break;
}
}
/* Pretend we didn't see this message */
AddHead(&OpenReqWindow->UserPort->mp_MsgList, message);
return(TRUE);
REPLY_AND_RETURN_FALSE:
ReplyMsg(message);
return(FALSE);
}
BOOL MessageInterrupt()
/* Call MessageInterruptGrunt() with each message.
* Return TRUE if the message is one that should interrupt the building
* of the file name list, else return FALSE.
*/
{
struct IntuiMessage *message;
while (message = GetMsg(OpenReqWindow->UserPort))
{
if (MessageInterruptGrunt(message))
return(TRUE);
}
return(FALSE);
}
SHORT MakeEntry(name, startkey, flags)
UBYTE *name;
struct Remember **startkey;
UBYTE flags;
{
SHORT length, pos;
struct Remember *localkey, *nextkey, *oldkey;
UBYTE *ptr;
/* length equals the length of the text plus one for the
* terminating NULL
*/
length = StringLength(name) + 1;
localkey = NULL;
/* Alloc one larger than length to make room for the flag byte */
ptr = AllocRemember(&localkey, length + 1, NULL);
if (ptr == NULL) return(32767);
CopyString(ptr, name);
*(ptr + length) = flags;
nextkey = *startkey;
pos = 0;
oldkey = NULL;
while (nextkey)
{
if (CompareUpperStrings(nextkey->Memory, name) >= 0)
goto DONE;
oldkey = nextkey;
nextkey = nextkey->NextRemember;
pos++;
}
DONE:
if (oldkey) oldkey->NextRemember = localkey;
else *startkey = localkey;
localkey->NextRemember = nextkey;
return(pos);
}
#ifdef WBENCH_CODE
SHORT FriendlyInfoType(infoname, fileio)
UBYTE *infoname;
struct FileIOSupport *fileio;
/* This routine looks at the .info file that's named infoname and
* tests to see if its object type and tool type match the specifications
* in the fileio structure. Returns TRUE if everything matches.
* If the .info file couldn't be opened or if the requirements don't
* match, FALSE is returned.
*/
{
struct DiskObject *object;
SHORT result;
result = FRIENDLY_NOT;
if (object = GetDiskObject(infoname))
{
if ((object->do_Type == WBDRAWER) || (object->do_Type == WBGARBAGE))
result = FRIENDLY_DRAWER;
else if (object->do_Type == WBDISK)
result = FRIENDLY_NOT;
else
{
if (FlagIsSet(fileio->Flags, MATCH_OBJECTTYPE))
if (object->do_Type != fileio->DiskObjectType) goto FRIEND_DONE;
result = FRIENDLY_OTHER;
if (FlagIsSet(fileio->Flags, MATCH_TOOLTYPE))
{
if (NOT MatchToolValue(
FindToolType(object->do_ToolTypes, "FILETYPE"),
&fileio->ToolType[0]))
result = FRIENDLY_NOT;
}
}
}
FRIEND_DONE:
if (object) FreeDiskObject(object);
return(result);
}
#endif /* ... of WBENCH_CODE conditional */
/* *** strings.c ************************************************************
*
* String Manipulation Routines
*
* Copyright (C) 1986, 1987, Robert J. Mical
*
* CONFIDENTIAL and PROPRIETARY
*
* HISTORY NAME DESCRIPTION
* ----------- -------------- --------------------------------------------
* 4 Feb 87 RJ Real release
* 2 Feb 87 RJ Added StripOuterSpace()
* 16 May 86 RJ Just more stuff
* 1 June 1985 =RJ Mical= Created this file from a weird distant echo.
*
* *********************************************************************** */
#include "exec/types.h"
#define FOREVER for(;;)
/* copy these and define them as 'extern' in your global include file
* in order to use these routines in your code.
*/
SHORT CompareUpperStrings();
UBYTE *FindSuffix();
SHORT GetAtom();
SHORT IndexString();
SHORT StringLength();
BOOL StringsEqual();
UBYTE *StripLeadingSpace();
UBYTE *StripOuterSpace();
SHORT CompareUpperStrings(s, t)
UBYTE *s, *t;
/* Compare s to t, making alphabet characters uppercase. Return value:
* s < t -1
* s == t 0
* s > t 1
*/
{
SHORT sc, tc;
FOREVER
{
sc = *s++;
if ((sc >= 'a') && (sc <= 'z')) sc = sc - 'a' + 'A';
tc = *t++;
if ((tc >= 'a') && (tc <= 'z')) tc = tc - 'a' + 'A';
if (sc < tc) return(-1);
if (sc > tc) return(1);
if (sc == '\0') return(0);
}
return(0);
}
VOID CopyString(tostring, fromstring)
UBYTE *tostring, *fromstring;
{
while (*tostring++ = *fromstring++) ;
}
VOID ConcatString(firststring, addstring)
UBYTE *firststring, *addstring;
{
SHORT length1;
length1 = StringLength(firststring);
firststring += length1;
CopyString(firststring, addstring);
}
UBYTE *FindSuffix(string, suffix)
UBYTE *string;
UBYTE *suffix;
{
SHORT stringlength, suffixlength;
if ( (stringlength = StringLength(string))
>= (suffixlength = StringLength(suffix)) )
{
if (StringsEqual(string + stringlength - suffixlength, suffix))
return (string + stringlength - suffixlength);
}
return(NULL);
}
SHORT IndexString(lookin, lookfor)
UBYTE *lookin, *lookfor;
/* This routines looks in the lookin string for the lookfor string.
* Returns the position of the lookfor string in lookin, or
* returns -1 if the lookfor string was not found.
*/
{
SHORT index;
UBYTE *workin, *workfor;
index = 0;
while (*lookin)
{
workin = lookin;
workfor = lookfor;
while ((*workfor) && (*workin) && (*workfor == *workin))
{
workfor++;
workin++;
}
if (*workfor == '\0') return(index);
lookin++;
index++;
}
return(-1);
}
SHORT StringLength(text)
UBYTE *text;
{
SHORT length;
length = 0;
while (*text++) length++;
return(length);
}
BOOL StringsEqual(text1, text2)
UBYTE *text1, *text2;
{
while (*text1 == *text2)
{
if (*text1 == '\0') return(TRUE);
text1++;
text2++;
}
return(FALSE);
}
UBYTE *StripLeadingSpace(text, space)
UBYTE *text, *space;
/* This routine "strips" the leading occurrences of the space string
* characters from the text string by finding the first character
* of the text string that is not contained in the space string.
* The return value is a pointer to the first non-space character in text.
* If text is the null string or if text consists of nothing
* but space characters, NULL is returned.
* If space is the NULL string, text is returned.
*/
{
if (space == NULL) return(text);
if (*space == '\0') return(text);
while (*text && (*text == *space)) text++;
if (*text) return(text);
return(NULL);
}
UBYTE *StripOuterSpace(text, space)
UBYTE *text, *space;
/* This routine "strips" the leading and trailing occurrences of the space
* string characters from the text string.
* The return value is a pointer to the first non-space character in text,
* and a null byte is stored after the text's last non-space character.
*/
{
UBYTE *workspace, *lastspace;
if (text == NULL) return(NULL);
if ((workspace = StripLeadingSpace(text, space)) == NULL)
{
*text = '\0';
return(text);
}
lastspace = workspace + StringLength(workspace) - 1;
while ((lastspace >= workspace) && (*lastspace == *space)) lastspace--;
*(lastspace + 1) = '\0';
return(workspace);
}
/* *** pointers.c ***********************************************************
*
* Intuition Pointers Routines
* from Book 1 of the Amiga Programmers' Suite by RJ Mical
*
* Copyright (C) 1986, 1987, Robert J. Mical
* All Rights Reserved.
*
* Created for Amiga developers.
* Any or all of this code can be used in any program as long as this
* entire copyright notice is retained, ok? Thanks.
*
* The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable.
* All copyright notices and all file headers must be retained intact.
* The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the
* resultant object code may be included in any software product. However, no
* portion of the source listings or documentation of the Amiga Programmer's
* Suite Book 1 may be distributed or sold for profit or in a for-profit
* product without the written authorization of the author, RJ Mical.
*
* HISTORY NAME DESCRIPTION
* ----------- -------------- --------------------------------------------
* 12 Aug 86 RJ >:-{)* Prepare (clean house) for release
* 3 May 86 =RJ Mical= Fix prop gadget for both 1.1 and 1.2
* 1 Feb 86 =RJ Mical= Created this file.
*
* *********************************************************************** */
#define FILEIO_SOURCEFILE
#include "fileio.h"
extern USHORT ElecArtsWaitPointer[];
VOID SetWaitPointer(window)
struct Window *window;
{
/* This one is the default because it's my favorite */
SetPointer(window, &ElecArtsWaitPointer[0], ELECARTSPOINT_HEIGHT,
16, ELECARTSPOINT_XOFF, ELECARTSPOINT_YOFF);
}
/* *** alerts.c *************************************************************
*
* Alert and Abort AutoRequest Routines
* from Book 1 of the Amiga Programmers' Suite by RJ Mical
*
* Copyright (C) 1986, 1987, Robert J. Mical
* All Rights Reserved.
*
* Created for Amiga developers.
* Any or all of this code can be used in any program as long as this
* entire copyright notice is retained, ok?
*
* The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable.
* All copyright notices and all file headers must be retained intact.
* The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the
* resultant object code may be included in any software product. However, no
* portion of the source listings or documentation of the Amiga Programmer's
* Suite Book 1 may be distributed or sold for profit or in a for-profit
* product without the written authorization of the author, RJ Mical.
*
* HISTORY NAME DESCRIPTION
* ----------- -------------- --------------------------------------------
* 27 Sep 87 RJ Removed reference to alerts.h, brought
* declarations into this file
* 4 Feb 87 RJ Real release
* 11 Jul 86 RJ >:-{)* Prepare (clean house) for release
* 1 Feb 86 =RJ Mical= Created this file with fond memories
*
* *********************************************************************** */
#include <prosuite/prosuite.h>
#define ALERT_TEXT_TOP 6
#define ALERT_TEXT_LEFT 6
extern struct TextAttr SafeFont;
UBYTE *AlertStrings[] =
{
/* "Longest allowed string -----------|" */
(UBYTE *)"Really broken. Stop all and reboot",
(UBYTE *)"Out of memory! Sheesh.",
(UBYTE *)"Invalid Disk or Drawer Selection",
};
struct IntuiText AlertText =
{
AUTOFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
AUTOLEFTEDGE + ALERT_TEXT_LEFT, AUTOTOPEDGE + ALERT_TEXT_TOP,
&SafeFont,
NULL, NULL,
};
struct IntuiText AlertOKText =
{
AUTOFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
AUTOLEFTEDGE, AUTOTOPEDGE,
&SafeFont,
(UBYTE *)"OK",
NULL,
};
VOID AlertGrunt(text, window)
UBYTE *text;
struct Window *window;
{
AlertText.IText = text;
AutoRequest(window, &AlertText, NULL,
&AlertOKText, 0, 0, 320, 48 + ALERT_TEXT_TOP);
}
VOID Alert(abortNumber, window)
USHORT abortNumber;
struct Window *window;
{
AlertGrunt(AlertStrings[abortNumber], window);
}
VOID Abort(abortNumber, window)
USHORT abortNumber;
struct Window *window;
{
Alert(abortNumber, window);
/*??? FOREVER Alert(ALERT_ABORT, window);*/
FOREVER Alert(0, window);
}
/* *** reqsupp.c ************************************************************
*
* Requester Support Routine
* from Book 1 of the Amiga Programmers' Suite by RJ Mical
*
* Copyright (C) 1986, 1987, Robert J. Mical
* All Rights Reserved.
*
* Created for Amiga developers.
* Any or all of this code can be used in any program as long as this
* entire copyright notice is retained, ok?
*
* The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable.
* All copyright notices and all file headers must be retained intact.
* The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the
* resultant object code may be included in any software product. However, no
* portion of the source listings or documentation of the Amiga Programmer's
* Suite Book 1 may be distributed or sold for profit or in a for-profit
* product without the written authorization of the author, RJ Mical.
*
* HISTORY NAME DESCRIPTION
* ----------- -------------- --------------------------------------------
* 4 Feb 87 RJ Real release
* 12 Aug 86 RJ >:-{)* Prepare (clean house) for release
* 3 May 86 =RJ Mical= Fix prop gadget for both 1.1 and 1.2
* 1 Feb 86 =RJ Mical= Created this file.
*
* *********************************************************************** */
#include <prosuite/prosuite.h>
#include <prosuite/reqsupp.h>
struct IntuiMessage *GetMsg();
/* *** DoRequest() **********************************************************
*
* NAME
* DoRequest -- Creates and manages a requester
*
*
* SYNOPSIS
* DoRequest(ReqSupport);
*
*
* FUNCTION
* Creates a requester according to the specifications laid out
* by you in a ReqSupport structure, and manages the interaction
* with the requester for you. In the end this routine returns control
* to you with an identifier describing which gadget the user selected
* to terminate the requester; this identifier can be found in the
* SelectedGadgetID field of your ReqSupport structure.
*
* Note that if anything goes wrong while trying to create the
* requester (usually out of memory) this routine returns
* immediately with the SelectedGadgetID field set to zero.
* Because of this, you should either avoid GadgetIDs of zero
* or at least you should have your Cancel Gadget have an
* ID of zero.
*
* You can specify routines that will be called when certain events
* occur while the requester is displayed. For instance, you can
* specify that a particular routine be called every time the
* user selects any of the requester gadgets. See the documentation
* and the ReqSupport structure for details about what
* routine vectors you can supply.
*
*
* INPUTS
* ReqSupport = pointer to a ReqSupport structure
*
*
* RESULT
* Returns the identifier of the gadget that ended the requester
* in the ReqSupport's SelectedGadgetID field.
* If anything goes wrong (usually out of memory) the SelectedGadgetID
* field is set to zero.
*/
VOID DoRequest(reqsupp)
struct ReqSupport *reqsupp;
{
ULONG class;
SHORT x, y;
struct IntuiMessage *message;
struct Gadget *gadget;
ULONG saveidcmp;
BOOL IAintGotNoSatisfaction, mousemoved;
struct Window *window;
LONG seconds, micros;
window = reqsupp->Window;
saveidcmp = window->IDCMPFlags;
/* If you change the list of IDCMP flags, check the effect it has
* on the switch / case statements of MessageInterrupt() in filename.c
*/
ModifyIDCMP(window,
GADGETUP | GADGETDOWN | REQSET | REQCLEAR
| MOUSEMOVE | DISKINSERTED);
if (Request(&reqsupp->Requester, window) == FALSE)
{
reqsupp->SelectedGadgetID = 0;
goto JUMP_SHIP;
}
IAintGotNoSatisfaction = TRUE;
while (IAintGotNoSatisfaction)
{
Wait(1 << window->UserPort->mp_SigBit);
mousemoved = FALSE;
while (message = GetMsg(window->UserPort))
{
gadget = (struct Gadget *)message->IAddress;
class = message->Class;
x = message->MouseX;
y = message->MouseY;
seconds = message->Seconds;
micros = message->Micros;
ReplyMsg(message);
if (IAintGotNoSatisfaction) switch (class)
{
case REQSET:
/* Does the caller have some startup
* stuff to perform now that the
* requester has been opened?
*/
if (reqsupp->StartRequest)
(*reqsupp->StartRequest)();
break;
case DISKINSERTED:
if (reqsupp->NewDiskHandler) (*reqsupp->NewDiskHandler)();
break;
case MOUSEMOVE:
mousemoved = TRUE;
break;
case GADGETDOWN:
case GADGETUP:
reqsupp->SelectedGadgetID = gadget->GadgetID;
if (reqsupp->GadgetHandler)
{
if ((*reqsupp->GadgetHandler)(gadget,
x, y, seconds, micros))
{
EndRequest(&reqsupp->Requester, window);
IAintGotNoSatisfaction = FALSE;
}
}
break;
case REQCLEAR:
IAintGotNoSatisfaction = FALSE;
break;
}
}
if (mousemoved && reqsupp->MouseMoveHandler && IAintGotNoSatisfaction)
(*reqsupp->MouseMoveHandler)();
}
JUMP_SHIP:
ModifyIDCMP(window, saveidcmp);
}
/* *** globfio.c ************************************************************
*
* File IO Suite -- Global Variable Definitions
* from Book 1 of the Amiga Programmers' Suite by RJ Mical
* (available soon if not already)
*
* Copyright (C) 1986, 1987, Robert J. Mical
* All Rights Reserved.
*
* Created for Amiga developers.
* Any or all of this code can be used in any program as long as this
* entire copyright notice is retained, ok?
*
* The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable.
* All copyright notices and all file headers must be retained intact.
* The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the
* resultant object code may be included in any software product. However, no
* portion of the source listings or documentation of the Amiga Programmer's
* Suite Book 1 may be distributed or sold for profit or in a for-profit
* product without the written authorization of the author, RJ Mical.
*
* HISTORY NAME DESCRIPTION
* ----------- -------------- --------------------------------------------
* 27 Sep 87 RJ Changed name of this file from global.c
* 4 Feb 87 RJ Real release
* 12 Aug 86 RJ >:-{)* Prepare (clean house) for release
* 3 May 86 RJ Fix prop gadget for both 1.1 and 1.2
* 1 Feb 86 =RJ Mical= Created this file.
*
* *********************************************************************** */
/* This prevents eglobfio.c from being included */
#define EGLOBAL_FILEIO_CANCEL
#define FILEIO_SOURCEFILE
#include "fileio.h"
/* === System Global Variables ========================================== */
struct IntuitionBase *IntuitionBase = NULL;
struct GfxBase *GfxBase = NULL;
struct DosLibrary *DosBase = NULL;
struct IconBase *IconBase = NULL;
#ifndef EGLOBAL_FILEIO_C
#define EGLOBAL_FILEIO_C
/* *** eglobfio.c ***********************************************************
*
* File IO Suite -- External Global Variable Definitions
* from Book 1 of the Amiga Programmers' Suite by RJ Mical
* (available soon if not already)
*
* Copyright (C) 1986, 1987, Robert J. Mical
* All Rights Reserved.
*
* Created for Amiga developers.
* Any or all of this code can be used in any program as long as this
* entire copyright notice is retained, ok?
*
* The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable.
* All copyright notices and all file headers must be retained intact.
* The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the
* resultant object code may be included in any software product. However, no
* portion of the source listings or documentation of the Amiga Programmer's
* Suite Book 1 may be distributed or sold for profit or in a for-profit
* product without the written authorization of the author, RJ Mical.
*
* HISTORY NAME DESCRIPTION
* ----------- -------------- --------------------------------------------
* 27 Sep 87 RJ Changed name of this file from eglobal.c
* 4 Feb 87 RJ Real release
* 12 Aug 86 RJ >:-{)* Prepare (clean house) for release
* 3 May 86 RJ Fix prop gadget for both 1.1 and 1.2
* 1 Feb 86 =RJ Mical= Created this file.
*
* *********************************************************************** */
/* === System Global Variables ========================================== */
extern struct IntuitionBase *IntuitionBase;
extern struct GfxBase *GfxBase;
extern struct DosLibrary *DosBase;
extern struct IconBase *IconBase;
extern struct TextAttr SafeFont;
extern struct Gadget OKGadget, CancelGadget;
/* === Open Requester Declarations ======================================= */
/* The global declaration of these can be found in opendata.c */
extern struct Requester *OpenReq;
extern struct ReqSupport OpenReqSupport;
extern struct Window *OpenReqWindow;
extern struct FileIOSupport *OpenReqFileIO;
extern struct StringInfo OpenNameTextInfo;
extern struct StringInfo OpenDrawerTextInfo;
extern struct StringInfo OpenDiskTextInfo;
extern struct Gadget OpenNameTextGadget;
extern struct Gadget OpenDiskTextGadget;
extern struct Gadget OpenDrawerTextGadget;
extern struct PropInfo OpenPropInfo;
extern struct Image OpenPropImage;
extern struct Gadget OpenSelectNameGadget;
extern UBYTE OpenUndoBuffer[];
extern UBYTE OpenSelectBuffers[NAME_ENTRY_COUNT][VISIBLE_SELECT_LENGTH];
extern struct IntuiText OpenSelectText[NAME_ENTRY_COUNT];
extern UBYTE OpenLockName[];
extern struct IntuiText ReqTitleText;
extern UBYTE *DefaultReqTitle;
extern ULONG OpenSaveLock;
extern UBYTE CurrentDiskString[];
extern LONG OpenClickSeconds;
extern LONG OpenClickMicros;
/* The global declaration of these can be found in chipdata.c */
extern USHORT OpenUpData[];
extern USHORT OpenDownData[];
extern USHORT OpenPropData[];
extern USHORT OpenPropTop[];
extern USHORT OpenPropBottom[];
#endif /* of EGLOBAL_FILEIO_C */