home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fish 'n' More 2
/
fishmore-publicdomainlibraryvol.ii1991xetec.iso
/
dirs
/
fileio_393.lzh
/
FileIO
/
FileIO.doc
< prev
next >
Wrap
Text File
|
1990-10-28
|
85KB
|
1,965 lines
Set your editor's TAB width to 3
FileIO Requester
Programmer Manual
Adapted from the Amiga Programmer's Suite Book 1, by RJ Mical
Copyright (C) 1987, Robert J. Mical
Additional notes concerning the requester library have been added by
Jeff Glatt who converted the original C into an assembly language library.
This section is for the programmer who wants to use the FileIO Requester
library routines in her or his program.
The Workbench names for DOS objects have been used in the FileIO Requester,
and are used throughout this document for simplicity. For your reference,
a directory is referred to as a "drawer" and volumes, or DOS filesystem
devices, are referred to as "disks".
These are the subsections of this section:
o Basic Operation
o Multiple FileIO Structures
o Workbench-style Filename Operations
o Filtering by Extension
o No Icon (.info) files
o FileIO Flags
o DoFileIO() and DoFileIOWindow() are non-reentrant
o Procedure for Opening and Using the FileIO Requester library
o Displaying Lists of Strings (non-disk operation)
========================== Basic Operation ============================
The FileIO routines base all of their work on a data structure called
the FileIO structure. You are allocated one of these structures when you
call the GetFileIO() routine. The structure is initialized with reasonable
default values for you. Conversely, you can declare and pre-initialize a
FileIO structure as long as all fields are set to zero or an appropriate
value. At the very least, you must set the FileIO's Buffer field to point to
where you want string input stored, and initialize the DrawMode, PenA, and
PenB fields to desired values. The buffer size should be > = 202 bytes.
The FileIO structure is used when calling the DoFileIO() and DoFileIOWindow()
routines, which are the routines that actually present the requester to
the user and get the user's filename selection. DoFileIOWindow() is the same
as DoFileIO() except that the former opens a window for the requester. With
DoFileIO(), you must already have a window open.
There are several flags and data fields in the FileIO structure that you
may choose to initialize before calling DoFileIO(). By setting or clearing
these flags, you define how information is to be presented to the user.
These flags are described below in "FileIO Flags". Also, the user can
change these flags for each FileIO via the function keys.
The DoFileIO() function returns one of 2 values:
1). The address of the buffer where the complete pathname (disk, drawer,
and filename as one, NULL-terminated string) has been stored. This
buffer will be the one that you supply in the FileIO's buffer field.
2). A -1 if the user selected the cancel gadget.
The DoFileIOWindow() function may return this additional value:
3). A zero if the window didn't open.
You can call these routines any number of times with the same FileIO
structure. Also, your program can have more than one FileIO structure at a
time. An example of why you would want more than one FileIO structure: you
might want to have separate structures for getting input filenames and
output filenames from the user. Another example: you might have one
structure for letting the user select text files and another for the
selection of graphics files each with different options/features. Also,
there are some lib routines that do not deal with disk file IO, but use the
FileIO structure nonetheless and you might want a FileIO with a special
string buffer for these routines.
Finally, when you're finished with your FileIO structure (usually not until
your program is terminating) then you call ReleaseFileIO() to deallocate all
the resources that it's accumulated. If the FileIO was obtained via
GetFileIO(), this routine also frees it for you.
====================== DoFileIO() is non-reentrant ========================
The DoFileIO() routine is non-reentrant. For the sake of memory efficiency,
it uses global data and variables rather than creating local copies of these
for each caller. What this means is that only 1 task can use the library
functions DoFileIO() or DoFileIOWindow() at a time, though all other lib
functions are re-entrant. If you attempt to call DoFileIO() or DoFileIOWindow()
while another task is using it, the library will automatically prompt the
user to type in the complete filename, instead of displaying the requester.
The area where the user types in the filename is in the title bar of the
window where the requester opened. The prompt
Filename >
will be displayed in the window's titlebar, along with a cursor. Several
line editing features are supported including cursor key movement (with the
ability to insert characters), backspace, delete, shift-right and shift-left
cursor to the start and end of the string, and escape. The window's title is
later restored. In fact, this feature of being able to use the title bar for
getting user input can be used with your own prompts. It is a handy alterna-
tive to having a string gadget (which takes up window space and also requires
allocating several structures), plus allows for displaying custom prompts.
The newest version of the lib lets the user scroll to any test beyond the
boundaries of the window title bar borders.
Note that many tasks can open the library simultaneously, but only 1 can be
displaying the FileIO requester at a given moment.
This redirection to entering the filename via the title bar is completely
invisible to your application. Upon return from DoFileIO() or DoFileIOWindow()
you will receive one of the 2 (or 3), previously described return values.
========== Interpreting the return value of DoFileIO() ================
As mentioned before, there are 3 possible return values from DoFileIOWindow
and 2 returns from DoFileIO(). If there is not enough memory for the window
to open with DoFileIOWindow(), then the return value is 0 and the FileIO's
Errno field = ERR_WINDOW. If this happens, you will have to find another way
to get the filename. If you already have a window open, use DoFileIO(). This
routine will never fail. Alternately, you might have the user type the path
as he would from the CLI, and call ParseString() to put it in the FileIO.
If the user selects the CANCEL gadget, (or hits ESCAPE when entering the
filename in the titlebar, or RETURN with no chars input), both routines will
return -1.
In all other cases, the address of the FileIO's Buffer will be returned.
This indicates that the user selected OK, or typed something in the string
gadgets or title bar. This does not mean that the filename is valid for
your purpose though. Let's assume that you called DoFileIO() from a load
routine. Naturally, you want the user to select an existing file to load,
but let's say that he types a non-existant file in the Name gadget or just
selects a disk or drawer without eventually choosing a file before selecting
OK. You can determine what the user did by examining 2 FileIO fields. The
FileIO's Filename buffer contains just the filename portion of the complete
path (separated from all the drawer and disk names). If this buffer is NULL,
then the user did not select a filename. If the buffer is not NULL, then he
either selected a filename, or typed one in. If he typed one in, how do
you know if the filename exists? The FileIO's FileSize field will be 0 if
the filename doesn't exist (or couldn't be examined because the user refused
to mount the file's disk). In this case, you would abort the load. If the
FileSize is not 0, then the file exists and this is how large it is in bytes.
In conclusion, here are the steps you should take for a load routine:
1). Call DoFileIO() with the FileIO's Buffer set to the address of your
path buffer, and the DrawMode, PenA, and PenB fields initialized.
2). Examine the return. If -1, then CANCEL. (If 0 for DoFileIOWindow, then
get the filename another way).
3). Check the FileIO's filename buffer for NULL. If NULL, then abort load
posting "This is not a loadable file."
4). Check the FileIO's FileSize field. If zero, post "File doesn't exist."
5). Otherwise, use the path buffer to open the file for reading.
Here are the steps you should take for a save routine:
1). Same as load routine step 1
2). Same as load routine step 2
3). Check the filename buffer for NULL. If NULL, then abort posting
"Did not supply a filename."
4). Check the FileSize field. If it's not 0, then the user must have selected
a filename that already exists on the chosen disk and in the specified
drawer. Post "File exists. Should we overwrite it?" Get a yes or no
response from the user to continue or abort.
5). Otherwise, use the path buffer to open the file for writing.
======================== Internal Error Handling ==========================
The requester is set up so that if the user types in a non-existant disk
name or refuses to mount the chosen disk, the req will default to any other
mounted disk. If no disks mounted, then the default FILEIO_DISKNAME is ":".
For example, assume that the user types "Leroy:" in the disk string gadget,
but the disk is not in any drive. AmigaDOS will prompt for that disk. If
the user then CANCELs the system prompt, the FileIO req will display the
contents of some other disk that is mounted, adjusting the string gadgets
accordingly. In the case where no disks are mounted, the pathname buffer
that is returned will not contain any disk name.
If the user types a drawer name that is not in the current dir level, the
req will knock him back to the root of the current dir. For example, assume
that the user is looking inside of a drawer called "TireBiter". There is no
drawer called "George" inside here, but the user types this in the drawer
string gadget nonetheless. The requester will clear ALL the drawer names,
defaulting to the root of the disk.
The library will not return non-existant disk or drawer names. If you needed
the requester to do this though (maybe you want to pass the path buffer to
CreateDir) then the user should type the "new" drawer name by itself in the
Name gadget. Conversely he could enter the string via the titlebar like so:
WorkBench:Demos/Blort
where you simply treat Blort as a dir name instead of a filename. The lib
will copy Blort to the FileIO's Filename field nonetheless. Just check the
FileSize field to make sure that there isn't a file already named this.
If there is some error in obtaining the disk name and it defaults to ":",
then the returned pathname will not have a drawer name prepended to it.
For example, say the user typed "df0:" in the drawer string gadget, but the
drive was empty. The requester will automatically default to another mounted
disk/device, etc, until one can be examined, or finally ":" is used. If the
user then types "Papoon" in the Filename Gadget, the returned path will be:
Papoon
which will be stored in the FileIO's Filename buffer if its a Filename, or
the FileIO's Drawername buffer if it's a drawer. If it is a Filename that
exists in the current dir, the FileSize will be its size in bytes.
================= Quick Display (NO_CARE_REDRAW) ================
The data in the FileIO structure often remains valid between calls to
DoFileIO(), so with subsequent calls a flag has been provided to avoid
reconstructing the filename list. This allows the requester to appear very
quickly because the usually-lengthy process of accessing the disk is avoided.
Other times, it may be necessary to have the requester reconstruct its list
of filenames (i.e. when a disk is changed or a file created/deleted by an
application which does not communicate with the FileIO requester). Perhaps,
as in a save routine, it may not be important to show the user what other
recent files are on the disk as long as proper file protection is provided.
The library uses the NO_CARE_REDRAW flag to discern whether to reconstruct
the list, or simply to use the FileIO's previous names. If you set this flag,
the old list is simply redrawn. Once you set this flag, the list will not
be reconstructed on subsequent calls until you explicitly clear NO_CARE_REDRAW.
(i.e. you always get the same, non-updated list unless the user changes dirs
or disables the feature himself via the Function keys).
When GetFileIO() creates a FileIO structure for you, this flag is cleared
to specify that the structure doesn't contain an updated list of filenames.
Thus the first call to DoFileIO() causes the filename list to be constructed.
After the call to DoFileIO() is the time to set the flag. You must do a bit
of work if you wish to make use of this feature. You are obliged to watch
for IDCMP events of class DISKINSERTED and to clear the NO_CARE_REDRAW flag
in any of your FileIO structures whenever you see this event. The
DISKINSERTED event occurs when the user has switched around the disks. When
the user has changed disks, you can't be sure that your FileIO's filename
list is still valid, so as a courtesy to the user you must cause the filename
list to be reconstructed. In the case that some disk activity occurs in a
program that doesn't use the FileIO library, you will never know about this
activity. Also, if the disk is changed or files are created/deleted by some
other task using the library, you will have no way to determine this. For
these reasons, you may elect to forgo this feature entirely. If you don't use
this feature, you need not bother looking for DISKINSERTED events. Because
the library has been completely rewritten in optimized assembly, it doesn't
take too long for the requester to construct its list anew. Also, the user
can toggle this feature ON/OFF using function key 6 if he wants. The example
applications don't use this feature. You can use the FileIO Requester library
to get the name of a file to be used for output. If you do, and the
specified file doesn't currently exist, AmigaDOS will create it anew when
you open it (mode NEWFILE). From the FileIO Requester point of view, this
means that a file now exists that isn't in your FileIO list. To get the name
in the list, clear the NO_CARE_REDRAW (if it was SET). The next time that
the FileIO structure is used for a call to DoFileIO() or DoFileIOWindow(),
the new file name will appear alphabetized in with the other file names.
Once again, this is not applicable if you don't ever set NO_CARE_REDRAW.
If you have more than one FileIO structure, remember that you must clear
the NO_CARE_REDRAW flag in all of them whenever you see Intuition's
DISKINSERTED IDCMP event class (if you're using the NO_CARE_REDRAW feature).
Also, regarding new disks, there's an extra procedure that you must follow.
If the user changes the disk while you've called DoFileIO() or DoFileIOWindow(),
you won't actually see a DISKINSERTED event (as the event will have been
processed by the library before control is returned to you). So how will you
know to clear the NO_CARE_REDRAW flag in your other structures? Well, the
library records the fact that a DISKINSERTED event was handled by setting
the DISK_HAS_CHANGED flag in your FileIO structure. So on return from a call
to DoFileIO() or DoFileIOWindow you should check to see whether your FileIO
structure has the DISK_HAS_CHANGED flag set. If it does, you should clear
the DISK_HAS_CHANGED flag in the structure and then clear the NO_CARE_REDRAW
flag in all of your other FileIO structures. This assures that when you
call DoFileIO() with any of your other support structures, the filename lists
will be reconstructed, as they should. Please note that all this needs to be
done ONLY IF YOU'RE SETTING NO_CARE_REDRAW.
=============== Workbench-style Filename Operations ====================
You can have file names appear in the FileIO Requester using the same rules
that govern how files appear on the Workbench display, by using the Workbench
.info file mechanism.
To attempt to match Workbench patterns, you must set the WBENCH_MATCH flag
in your FileIO structure, as described below.
The Workbench .info file mechanism is a detailed topic that will not be
delved into here. Please read the Amiga ROM Kernel Manual for a description
of the Workbench operation and data types. What follows is a cursory
description of the Workbench technique, which is described only well enough
to explain how you can interact with it via your FileIO structure.
The Workbench program examines the directory of a disk and displays icons
for the files it finds that end with a ".info" suffix (hereafter referred to
as .info files). The file names displayed beneath the icons have the
".info" suffix removed. The Workbench .info files contain information
regarding what type of data is contained in the file (executable program,
project data, et cetera).
You can choose to have only .info files displayed to the user (with the
".info" removed) in the same way that the Workbench does. You get this
by setting the WBENCH_MATCH flag. Any executables without icons (.info files
) will not be displayed. The same is true of drawers.
If you wish, you can further filter the names that appear. There are two
techniques that you can employ for filtering which file names will be added
to the list: you can ask for only those files that match a particular
Workbench object type and only those files that match a particular tool type.
You elect to match the object type by setting the MATCH_OBJECTTYPE flag in
your FileIO structure. The object types typically of interest are WBTOOL
and WBPROJECT. By selecting one of these 2 types, your filename list will
consist only of executable files or data files respectively (except that all
.info drawer names are always displayed). If this is confusing, refer to the
ROM Kernel manual for a discussion of object types.
You can also request to match a Workbench tool type. By matching tool types,
you can, for instance, have your file list display only those data files
that were created by a specific application. See the section entitled
"The ToolTypes Array" in the Workbench chapter of the ROM Kernel manual for
a description of how tool types work. You elect to match tool types by
placing a pointer to the ToolTypes text in the ToolTypes field of your FileIO
structure. If this field is left zero, then the TOOLTYPES will be ignored.
=========================== No Info Files ============================
Setting the INFO_SUPPRESS flag is exactly the opposite of Workbench
matching. All files that end in .info will be ignored, and not displayed.
This is handy if the user doesn't have a .info file to go with every file
that he wishes to peruse. With WB MATCH, those files would not be displayed.
With INFO_SUPPRESS set, they would be displayed but no .info files would
clutter the display. This gives the impression of WB MATCH while enabling
files without icons to also be seen. On the down side, that means that the
user will see ALL files without icons including those that are best left
alone (i.e. translator.library). All drawers are displayed regardless.
When the user makes his selection, the .info is not added to the pathname.
==================== Filtering by Extension =====================
Sometimes, you may have an application that only wants to see filenames
that end with a certain string (i.e. ".iff"). You can specify an extension
by storing the address of this string in the Extension field of the
FileIO. Also, you need to specify the length (don't count the terminating
NULL byte) and store this value in the ExtSize field. For the preceding
example, the length would be 4 (counting the .). Finally, you must set the
EXTENSION_MATCH flag. If the EXTENSION_MATCH flag is clear, the extension
fields will be ignored. In this way, you can quickly enable and disable the
feature with the one flag. Only the files that END with this extension (case
insensitive) will be displayed. Incidentally, this need not be a real exten-
sion. You can match any ending at all. For example, you could only display
those files that end with the string "picture". In this case, the length
would be 7. If you set the EXTENSION_MATCH flag, then clear the INFO_SUPPRESS
flag. Because only those files that end in your specified extension are seen,
.info files won't be displayed anyway (unless your specified extension is
".info" in which case you'll get nothing but .info files. An icon editor,
maybe?) All drawers will be displayed regardless. Please note that the
extension string that you supply MUST HAVE ALL LETTERS IN LOWER CASE.
In order for the user to take advantage of this feature via the F4 key,
you must set up the FileIO for it. First you must supply a buffer for the
user's typed extension. Place the address in the FileIO's Extension field.
The buffer must be at least 20 bytes long. Don't enable the EXTENSION_MATCH
flag.
If you don't want the user to take advantage of extension match, then
clear the EXTENSION_MATCH flag AND zero the Extension pointer field. There
is the possibility that you may have supplied an Extension to be matched
and while the requester was displayed, the user changed the match string.
For this reason, the buffer should always be at least 20 bytes if you use
this feature. Also, don't assume that the returned filename is definitely
ending with the extension you initially passed. If the user changed the
match string, it won't be the same extension. Also, you should re-initialize
your extension buffer string each time before you call DoFileIO(). The
returned pathname and FILEIO_FILENAME buffer have the extension added.
For SPECIAL_REQ, the extention is ignored.
========================== FileIO Flags ===========================
Remember that the user can always adjust these himself with the function
keys. For this reason, you might simply go with the defaults.
NO_CARE_REDRAW
This flag designates whether the filename data contained in the
FileIO is to be reconstructed before initially drawing the requester.
USE_DEVICE_NAMES
When you leave this flag CLEAR, the AmigaDOS volume names will
be used for the disk names in the requester. If you SET
this flag, the device names will be used instead. The default is to
follow the Workbench convention and use volume names.
DISK_HAS_CHANGED
If the user changes the disk while the FileIO Requester is being
displayed, this flag is set in the FileIO structure. The only time you
must pay attention to this flag is when you have set the NO_CARE_REDRAW
flag. If you find that DISK_HAS_CHANGED has been set, you must clear
that flag in this FileIO structure and then clear the NO_CARE_REDRAW
flag in all of your FileIO structures.
DOUBLECLICK_OFF
Normally, the user can double-click on a filename to select it.
You may choose to disable this feature, for instance, when you want the
user to be very certain about the filename selection (perhaps if the
file is about to be destroyed, or something equally drastic). To disable
double-clicking, set the DOUBLECLICK_OFF flag. Then the user will have
to explicitly select OK! or type the filename and hit return for the
selection to be made. Affects SPECIAL_REQ
WBENCH_MATCH
You set this flag to specify that you want Workbench-style .info file
logic to be used when constructing the filename list. This flag is
cleared when your FileIO structure is first created.
MATCH_OBJECTTYPE
When you set this flag (and the WBENCH_MATCH flag), the MatchType field
of your FileIO structure will be compared with the do_Type field of the
.info file's DiskObject structure. If they match, the file will be
displayed. Both the MATCH_TOOLTYPE and the MATCH_OBJECTTYPE flags can
be set at the same time.
MULTIPLE_FILES
Set this flag for multiple filename selection. All selections must be in
the same directory. You must examine the EntryFlags (selected bit) of
each Entry structure to determine which files were selected. This flag
cannot be changed by the user unless an application allows him to do so.
Affects SPECIAL_REQ
INFO_SUPPRESS
All .info files are suppressed from the display if you SET this.
EXTENSION_MATCH
Filters filenames that end with a certain string if you SET this.
CUSTOM_HANDLERS
Allows adding custom handlers to the internal library
handlers of GADGETUP, GADGETDOWN, MOUSEMOVE, RAWKEY, DISKINSERTED,
and initial REQSET. You can supply an additional handler for any and all of
these events that will be invoked along with the internal library handler
(or in place of it). Once you call DoFileIO(), the handlers will be installed
and active until the requester ends. Set or Clear this flag before calling
DoFileIO(). If the requester can't open or is being used by another task,
the user will get titlebar entry, and your handlers will be ignored.
Cannot be changed by the user. Affects SPECIAL_REQ
NO_ALPHA
When clear, the filenames are alphabetized in the display. When SET,
newer files are listed at the top of the display. Affects SPECIAL_REQ
SPECIAL_REQ
Allows using the FileIO requester to display lists of strings not
relating to disk drive operations. Cannot be changed by the user.
======================= RAM DISK bug ============================
There seems to be a bug in 1.2 AmigaDOS. For some reason, whenever one
attempts to get an AmigaDOS Lock on the volume named "RAM DISK:" a
software error occurs. The problem doesn't necessarily lie in AmigaDOS,
but the truth is that the error occurs with little provocation
of AmigaDOS (for instance:
dir "RAM DISK:"
can and does crash the Amiga). Though 1.3 resolves this bug, the FileIO
code provides a work-around for 1.2 by changing "RAM DISK:" to "RAM:"
which locks successfully and does not crash the machine. This solution
has a problem: if the user has given the name "RAM DISK:" to some
non-RAM: disk (such as a floppy) then this fix will fail and the floppy
named "RAM DISK:" wouldn't be seen. This isn't too bad of a problem,
because if the user has been silly enough to name a floppy "RAM DISK:"
the user is probably experiencing lots of other problems already and this
will provide just one more reason why one shouldn't name a floppy
"RAM DISK:" don'cha know.
======================= Free Disk Space ================================
The FileIO's FREEBYTES field indicates how many free bytes remain on the
disk that the user has chosen. This is useful for a save routine. After all,
you wouldn't want to start saving a 230K file to a disc that only has 229K
free. Unfortunately, AmigaDOG always says that the RAM DISK: has 0 bytes
free. Actually, it has as many bytes free as mem that is available. Whenever
the user selects RAM: or RAM DISK:, the FileIO's FREEBYTES is set to
0xFFFFFFFF (the largest size possible). If you encounter this condition, you
may wish to use Exec's AvailMem to determine if you can do the save.
========== Procedure for Using the FileIO Requester library ===========
This section presents a step-by-step procedure for utilizing the FileIO
Requester library with your own program.
Copy the requester.library into the libs directory of your boot disk. For
workbench users, double-click on the inclosed program "CopyLib" and place
your Workbench disk in the drive when you see the DOS requester. CopyLib
will display the FileIO requester if all went well. Select the requester's
CANCEL and exit the program by closing the window.
You have to include FileIO.h in every C module that refers to your FileIO
structure.
#include "FileIO.h"
For assembly language users, (WOW! We hardly ever get real support for
programming on the Amiga), include FileIO.i
Open the library via a call to exec's OpenLibrary and store the pointer at
a variable called RequesterBase (MUST BE CALLED THIS FOR C PROGRAMMERS).
if (!(RequesterBase = (APTR) OpenLibrary("requester.library", 1L)))
exit(0);
Declare a pointer to a FileIO structure (initialized to 0), and then fill
that pointer with the address of one of the structures.
struct FileIO *myFileIO = 0;
myFileIO = GetFileIO();
<<<< IF USING NO_CARE_REDRAW >>>>>
Your NewWindow structure should have the DISKINSERTED flag set along with
your other IDCMP flags. Whenever you receive a DISKINSERTED event, you
should clear the NO_CARE_REDRAW flag (if SET) in every FileIO structure you
control. The following code could be added to the case switch where you
handle IDCMP events.
switch (imessageclass)
{
case DISKINSERTED:
/* You should clear the NO_CARE_REDRAW flag
* whenever you detect that a new disk was
* inserted.
*/
if (myFileIO)
ClearFlag(myFileIO->Flags, NO_CARE_REDRAW);
break;
}
Alternately, you may elect to leave NO_CARE_REDRAW clear in which case the
requester display will be updated every time it is used and you won't need
to bother with receiving DISKINSERTED events.
Set the FileIO's Buffer field to the address of a buffer that you have
allocated. This is where the complete path will be constructed for you.
(i.e Disk:drawer1/drawer2...etc/filename ) Also initialize the FileIO's
DrawMode, PenA, and PenB. You might also want to set the FileIO's X and Y
fields where the requester will open within your window (relative upper left).
When you want to present the FileIO Requester to the user, call DoFileIO() or
DoFileIOWindow(). If these routines return the address of the passed buffer
where you want the full path name to be stored, the user did not cancel the
operation, nor was there an error in opening the window (for DoFileIOWindow
only). A -1 and 0 will be returned respectively for the two error conditions.
The following code is an example of presenting the FileIO Requester to the
user and then reacting to the result.
/* This set-up need only be done once, though you can change them later */
UBYTE buffer[204];
myFileIO->Buffer = buffer;
myFileIO->DrawMode = JAM1;
myFileIO->PenA = 1;
myFileIO->PenB = 0;
/* ================================================================ */
if (myFileIO)
{
result = (DoFileIO(myFileIO, window));
if (result==&buffer[0])
{
/* Here, do something like read or write the file.
*/
if (writefile)
{
if (myFileIO->FileName[0])
{
if (!myFileIO->FileSize)
{
/* Open the file (MODE_NEWFILE) */
/* Write the file */
/* Close the file */
}
/* Otherwise, tell the user that he's about to overwrite */
}
/* Error in entering filename */
}
if (readfile)
{
if (myFileIO->FileName[0])
{
if (myFileIO->FileSize)
{
/* Open the file (MODE_OLDFILE) */
/* Read the file */
/* Close the file */
}
/* Otherwise, tell the user that the file doesn't exist */
}
/* Not a loadable file */
}
}
if (result==0)
{
/* This only happens if DoFileIOWindow() bombs. Call DoFileIO() */
}
/* Otherwise, CANCEL must have been selected. Never mind. */
}
Finally, when you're done with your FileIO structure (usually when
your program is exiting), you can free up the structure and its resources
with a simple call to ReleaseFileIO(), like this:
if( RequesterBase ) ReleaseFileIO(myFileIO);
Also, you need to close the library upon exit.
if( RequesterBase ) CloseLibrary( RequesterBase );
When you link your C program, you'll need to assemble and link with
FileInterface.asm. This is the usual assembly poot needed by C programs in
order to call assembly language libraries. You want efficiency, write in
assembly. Assembly programmers can simply use the _LVO library offsets as
provided in FileIO.i. See the example applications for details.
ONE FINAL NOTE: The lib needs to trap RIGHT MOUSE buttons for displaying
the list of disk names. When exiting, the lib clears the RMBTRAP bit of
your window's flags, so if you had it set before calling DoFileIO(), then
you'll have to set it again upon return by going to the Flags field of
your window structure and setting bit #16.
============ USING THE REQUESTER TO DISPLAY LISTS OF STRINGS =============
There may be times when you need to display a list of strings in a
requester so that a user can scroll around the list via the mouse and
choose an item in the list. The amount of code and IDCMP hassle of construct-
ing such a requester can certainly be considerable, especially if you want to
include a Prop scroll bar, scroll arrows, a string gadget, CANCEL and OK
gadgets, etc.
The latest version of the FileIO requester library has a feature whereby
you can use the lib's requester to display your list of strings. The lib
handles all user interaction, list display, and IDCMP. You simply set the
SPECIAL_REQ flag of the FileIO before calling DoFileIO() or DoFileIOWindow()
and the requester will display your list of strings. The requester is no
longer a disk I/O tool. In fact, the Disk and Drawer string gadgets are re-
moved from the display, and the NextDisk gadget no longer has anything to do
with switching dirs.
The user can employ the Prop and Arrow gadgets (with auto-scroll) to scroll
through the list of strings. The size of the Prop's knob reflects the per-
centage of visible strings just like in the disk I/O version.
The user can click on any string to make it the currently selected one,
and it will be highlighted and copied to a string gadget below. Or the user
can type his selection directly into the string gadget. A double-click on
a string will end the requester with that string as the chosen one.
The chosen string will be copied to the FileIO's Filename buffer. Note
that with SPECIAL_REQ, you do not need a Pathname buffer. (In fact, the
FileIO's BUFFER field will be overwritten.)
With SPECIAL_REQ, DoFileIO() or DoFileIOWindow will return the following:
1). A -1 if the user selected the CANCEL gadget.
2). A -2 if the library was being used by another task (i.e. the same
note about non-reentrant code applies here).
3). A 0 if there is a problem opening the FileIO window (if DoFileIOWindow
doesn't open, or the requester doesn't open).
4). The address of the FileIO's Filename buffer (i.e. where the selected
string is copied) if all went well and the user selected OK, or double-
clicked on a string, or typed in his selection in the Name gadget.
So how do you give your list of strings to the lib? There are 2 functions,
NewEntryList() and AddEntry() that you use to make the list.
Here are the passed parameters.
EntryNum = AddEntry(ID_num, StringAddress, FileIO);
d0 d1 a0 a1
NewEntryList(FileIO);
a1
Each FileIO can have its own list attached to it. NewEntryList frees
any previous list (if one exists) that was made for the passed FileIO. For
this reason, you should call NewEntryList first before using AddEntry to
add strings. You can then add strings to the list by subsequent calls
to AddEntry. (AddEntry adds the one passed string into the list. The list is
alphabetized as each string is added to it so that the strings are always
displayed in alphabetical order, unless you set the NO_ALPHA flag. With
NO_ALPHA, each entry is added to the tail of the list.) ID_num is some value
that you want associated with the string. When the user selects that string,
it is copied into the FileIO's Filename buffer and the ID is copied into the
FileIO's FileSize field. This ID is a LONG, and can be any value you desire
(i.e. maybe even a pointer to some data structure associated with that string). The only restriction is that ID cannot be -1 (i.e. 0xFFFFFFFF).
The returned EntryNum is where the string has been alphabetically placed
in the list (i.e. the first string in the list returns 0). If you receive
a negative number from AddEntry(), this means that there wasn't enough memory
to add the string to the list. Actually, AddEntry copies the string, and
adds the copy to the list, so you need not keep the original string after it
is added to the list.
When you finally call ReleaseFileIO(), any list associated with the FileIO
is freed.
Here is how you might create a list with the following 3 items and display
it in the FileIO requester:
/* You should have opened the requester lib and allocated a FileIO */
if (myFileIO)
{
NewEntryList(myFileIO);
error = AddEntry(1L, "This is One", myFileIO);
if (error<0) break;
error = AddEntry(2L, "Two", myFileIO);
if (error<0) break;
error = AddEntry(3L, "Three", myFileIO);
if (error<0) break;
result = (DoFileIO(myFileIO, window));
if (result==myFileIO->FileName)
{
/* FileName buffer contains the string, and FileSize the ID
*/
}
if (result==0)
{
/* This only happens if DoFileIOWindow() bombs. Call DoFileIO() */
}
if (result==-2)
{
/* This happens if someone is using the library. Come back later */
}
/* Otherwise, CANCEL must have been selected. Never mind. */
}
There is a possibility that the user may type a string that is not in the
list, directly into the Name gadget. Before exiting, the requester lib will
check if the string is in the list. If not, the string is copied to the
FileIO FileName buffer as before, but the FileSize field is set to -1. A
FileSize of -1 means "this string isn't in the list". That is why you should
not assign an ID of -1 to any string. The lib ignores the case of the string
when comparing items in the list (i.e. "Amiga" and "amIGA" are the same),
but it does not trim away any leading or trailing spaces.
With SPECIAL_REQ, the "Next Disk" gadget can be a custom gadget for your
use. You place into the FileIO's FileIOText field a pointer to the string
that you want displayed in the gadget. This string should be no more than 11
characters (not counting the end NULL). You should pad the head of the
string with spaces to properly center inside the gadget. You should also
store in the FileIO's FileIORoutine field a pointer to a routine that is to
be executed everytime the user releases the mouse over the custom gadget.
The library calls this routine passing the FileIO and Window (that the
requester opened in), and the Requester Structure.
BOOL yourRoutine(Requester, Window, FileIO)
a5 a3 a2
This function should return TRUE to end the requester, or FALSE to continue.
If FALSE, the FileIO display will be refreshed when your function returns. (In
case your custom routine added/removed something from the list, or changed
lists). If you return TRUE, the requester will end with the FileIO's Errno
field set to ERR_APPGADG.
If your FileIO's FileIORoutine field is set to NULL when you call DoFileIO,
the custom gadget is removed from the display.
Finally, there is a routine that you can use to determine if a certain
string is in the list.
entryNum = IsEntryThere(String, FileIO)
d0 a0 a1
where String is the address of the string you wish to check for.
This returns the entryNum (like AddEntry) of the string if it is found
in the list, or a -1 if it is not in the list. For assembly programmers,
if found, the address of the Remember structure is returned in a0.
====================== Filename and Custom Lists =====================
The list of filenames (or custom list created via AddEntry) is created using
the Intuition function, AllocRemember. The "anchor" of the list is the
FileIO's FileList field. So each string has its own Remember structure. The
Remember's rm_Memory points to my own Entry structure. An Entry structure
looks like this:
struct Entry {
LONG EntryID;
UBYTE EntryFlags; /* Don't alter this! */
UBYTE EntryString[size of the string not counting end NULL];
};
In asm,
EntryID dc.l 0
EntryFlags dc.b 6
EntryString dc.b [the bytes comprising the NULL-terminated string]
I have redefined the Remember structure as a FileEntry structure since
that is easier to reference:
struct FileEntry {
struct FileEntry *nextEntry;
ULONG EntrySize;
struct Entry *filePart;
};
Don't use sizeof on these structures. The library makes them for you. The 3rd
field of the Entry structure is a variable length, NULL-terminated string.
This structure has been defined simply so that you can get access to the
EntryID, EntryFlags, and EntryString. These structures are used for both
custom lists and the list of filenames. For filenames, each filename has a
FileEntry structure. Its EntryID is the filesize. Bit #7 of the EntryFlags
is set if the filename was selected by the user. The EntryString is the
NULL-terminated filename (separated from its dir). When the SPECIAL_REQ
flag is set, the Entry's EntryID is your passed ID to AddEntry().
All the FileEntry structures are linked together, and the FileIO's
FileList field points to the first FileEntry in the list.
You can use one FileIO to alternately display several custom lists. The key
is to properly set the FileIO's NameCount, NameStart, CurrentPick, and FileList
fields before calling DoFileIO(). You should make a list as in the above
example, and then copy the FileList field to some global. Then zero out the
FileList field. Do this for all your lists. Now when you want to display one
list, pass the appropriate global to a routine that does the following:
1). Clear the FileList field.
2). Call NewEntryList() (to initialize the NameStart and CurrentPick)
3). Set the FileIO's NameCount to the number of items in the list
4). Set the FileIO's FileList to the passed global.
5). Set the SPECIAL_REQ flag. (If it wasn't set previously.)
6). Call DoFileIO()
7). Clear the FileList field.
Here's a C function to implement the above. It returns TRUE if all went
well, and FALSE if error or user cancel.
BOOL ShowList(ListAddr,NumOfItems,window,fileio)
struct Remember *ListAddr; /* the contents of the FileIO's FileList field
after you made the list with AddEntry(). */
SHORT NumOfItems; /* number of entries in Remember List */
struct Window *window;
struct FileIO *fileio;
{
UBYTE *address;
fileio->FileList = 0; /* you stored the original value in the global ListAddr
after making the list */
NewEntryList(fileio);
fileio->NameCount = NumOfItems;
fileio->FileList = ListAddr;
SetFlag(fileio->Flags, SPECIAL_REQ);
address = DoFileIO(fileio, window);
fileio->FileList = 0;
if( address <= 0 )
return( FALSE );
else
return( TRUE );
}
When exiting your program, you must de-Allocate all the lists. For each,
1). Set the FileIO's FileList to the passed global.
2). Call NewEntryList()
void FreeProgList(fileio, filelist)
struct FileIO *fileio;
struct Remember *filelist;
{
fileio->FileList = filelist; /* original value you previously stored in global
after making the list */
NewEntryList(fileio);
fileio->FileList = 0;
}
Consult the examples, CustomList, for how to use SPECIAL_REQ.
========================= Multiple Selections ===========================
You can allow the user to make multiple selections from a custom list or the
filename list by setting the FileIO's MULTIPLE_FILES flag. When the user
clicks on a name, it will be highlighted. The user can then select more
filenames, with all of them simultaneously selected. The library sets bit
#7 of each selected file's Entry structure's EntryFlags. If a user clicks on
a filename that is already selected, then the filename is de-selected. Note
that double-clicking on a filename still can terminate the requester. The
last selected name is the one that appears in the FileIO's FileName buffer.
When the user double-clicks, or selects CANCEL or OK, the requester ends.
At this point, you must go through the FileIO's FileList, examining each
Entry structure's EntryFlags for bit #7 set to determine which files were
selected. The caveat is that all files must be in the same directory because
the EntryString does not contain the full path, only the filename. (The path
can be constructed with the FileIO's Disk and Drawer buffers.)
There is a library function to aid in locating the selected files:
FileEntry = RetrieveEntry( FileEntryPtr, FileIO );
d0 a0 a1
FileEntryPtr should point to a FileEntry structure in the FileIO's FileList
or be set to 0. If 0, this routine locates the first selected FileEntry
structure in the FileList, updates the passed FileEntryPtr to point to that
structure, and returns that address. The next time that this function is
called, FileEntryPtr will not be 0, and so this function will return the next
selected FileEntry structure, etc. When there are no more selected files, a 0
is returned and the FileEntryPtr is cleared.
Another function:
ClearEntries(FileIO);
a1
clears the selected bit of all EntryFlags in the FileIO's FileList. This is
useful for clearing selections after a custom list has been presented to the
user (especially if the user has set NO_CARE_REDRAW).
If the user types a filename directly into the Filename gadget, the library
will NOT check if the filename is in the current list and set its selected
bit if so. You can determine whether the filename exists in the current dir
by the value of the FILEIO_FILESIZE field as before. For SPECIAL_REQ, the
library DOES set the selected bit if the entered text is one of the displayed
choices.
Consult the examples for how to use MULTIPLE_FILES.
=============================================================================
=== DEMO PROGRAM NOTES ======================================================
=============================================================================
This section briefly describes the demo programs that drive some of the
FileIO Requester library's features. There is a C demo, an assembly demo,
and an AmigaBasic demo (no joke).
If you invoke the C or asm demos without a second argument, a window will be
opened in the Workbench screen. If you invoke these demos with any second
argument, a hi-res screen will be opened for the requester window.
The C demo uses two FileIO structures to demonstrate the techniques that you
should use when managing multiple FileIOs. These techniques include processing
DISKINSERTED events and discovering on return from DoFileIO() that the
DISK_HAS_CHANGED flag is set. (As long as you're using the NO_CARE_REDRAW
feature). The first support structure, fileio1, is used in its vanilla state
as created by GetFileIO(). The other support structure, fileio2, is
initialized to do Workbench-style .info file handling where the filename
list will consist of only .info objects of type WBPROJECT. Also, fileio1
uses volume names and the other uses device names. You activate fileio1 when
you click the right mouse button. You activate fileio2 when you press any
key. Finally, when you do any of the selection techniques where you accept
your selection, the pathname to your selection is displayed in a FileIO
autorequester. If you choose CANCEL to end the FileIO process, nothing happens.
To stop the program, click on the window close gadget (when the requester
is not displayed).
The assembly demo only uses 1 FileIO structure. There is a menu to
demonstrate various features. You should manually deselect the features
you want disabled, and select those that you want enabled. For example,
select CUSTOM to see how a custom handler is installed for the REQSET event.
Also, this program can look for files that only end in certain strings if
you select the EXTENSION menu item. When you enable the extension feature,
the application uses the PromptUserEntry() function. Notice how the prompt
appears in the window titlebar with a cursor. You can type in the string
that you want to match, and hit return. Now when you call up the requester,
only those filenames that end in that extension will be displayed (along
with any dirs). This works just like the F4 Function key option.
Also of interest is the Multiple menu item which toggles MULTIPLE_FILES.
With this on, note how several files can be clicked and selected. When you
select OK, the asm example then prints out the pathbuffer, followed by all
files selected. Note that the selected files do not contain the full path.
The amigabasic demo asks the user if he wants to display only those files
with a certain extension, and inputs the extension. Otherwise, it suppresses
all .info files. It then copies the pathname to a string variable which can
be better utilized for basic manipulation. Also this demos a few of the
library's autorequester functions. When running this program, the included
bmap for the FileIO requester library must be in the same directory.
Additionally, there are examples to demonstrate using the requester to dis-
play custom lists of strings.
========================================================================
INSTALLING CUSTOM HANDLERS
You can install custom handlers for any of several events that might occur
in the requester. You need to set the CUSTOM_HANDLERS flag of the FileIO, and
fill the FileIO's HandlerBlockPtr field with the address of a HandlerBlock
structure. The HandlerBlock structure (defined in FileIO.h) holds the
addresses of the handlers for REQSET, DISKINSERTED, GADGETDOWN (and UP),
RAWKEY, and MOUSEMOVE. If you have no handler for a particular event, NULL
its HandlerBlock field. Each FileIO can have its own custom handlers.
For REQSET, and DISKINSERTED, if your handler returns a 1, then the
library's internal handler will be skipped. Otherwise, the library routine
will be executed if you return a 0.
For GADGETDOWN and GADGETUP, your handler will be called only if the Gadget
ID is not one of the requester's gadgets. Your handler will be passed the ID
in d0 (as well as other parameters). Your handler should return a 0 in order
to continue, or a 1 if you wish to end the requester. (You can check that
your custom handler ended the requester if the FileIO's Errno = ERR_APPGADG).
The only two requester gadgets that the library no longer controls are the CANCEL
and OK gadgets. Control of these two is passed to your custom handler. These
two gadgets have IDs of 32672 and 32673 respectively. If you receive either
of these IDs, you should return a 1. On the other hand, you could simply
cause these gadgets to be ignored by returning a 0. In any event, your
handler will have to return a 1 eventually in order to exit the requester,
or the user would have to type the Filename in the Filename string Gadget.
Do not use gadget IDs between 32672 to 32682 as these are reserved by the
library.
For MOUSEMOVE, the events are "collected" (i.e. you only receive one event
when the user stops moving the mouse). Also, you won't receive MOUSEMOVE when
the user is operating the requester's scroll (prop) gadget. Your handler
doesn't need a return value.
For RAWKEY, you won't receive any function keys. No return value is needed.
The requester calls your handler with the following items in these
registers:
a2 - the address of your FileIO
a3 - the address of the window in which the requester is open
a4 - the IAddress of the event (not valid for REQSET or DISKINSERTED)
d6 - MouseX position (for RAWKEY handler, this is the Code instead)
d7 - MouseY position (for RAWKEY handler, this is the Qualifier)
d2 - Seconds
d5 - Micros
d0 - (need not be saved) For GADGETUP and DOWN, the gadgetID
For RAWKEY handler, the ascii value as returned from DecodeRawkey()
You MUST save these registers if you plan on altering them.
If your handler is written in C (yech!), I've provided a mechanism for
receiving these parameters passed on the stack like all good, inefficient C
programs should. Let's face it, C just doesn't have enough power to do the
sophisticated, efficient things that we do in assembly. But if you'd like to
fool yourself into thinking otherwise, I've tried to accomodate your
delusions. After filling in the HandlerBlock's pointers to the desired
routines, you must call SetFileIOHandlers(HandlerBlock). This routine
will see to it that your handler receives the following parameters except
where previously noted.
BOOL yourHandler(IAddress,Window,FileIO,MouseY,MouseX,Micros,Seconds,GadgID);
Note that GadgID is the ascii value (UWORD) for the RAWKEY handler.
Unfortunately, unlike the assembly implementation, if you want to have
different FileIO's with unique custom handler routines, you'll have to
call SetFileIOHandlers() before each call to DoFileIO(). Hey, you're writing
in C, so you should be used to giving up some flexibility.
If you're using Manx small data model, you'll probably have to call geta4
or savea4 (whatever). a4 will definitely not have the base of your program's
data section. These are the types of problems you should expect if you allow
a C compiler to determine 68000 register usage. Also, since register a6 is
"reserved" for library base vectoring on the Amiga, the C interface to the
library does not save this register. If your compiled program crashes because
of this, its time to buy a better compiler, or perhaps solve these headaches
once and for all with an assembler.
struct HandlerBlock {
APTR StartUpCode; /* Called when the requester first opens */
APTR DiskInsertedCode; /* Called whenever a disk is inserted */
APTR GadgetCode; /* Called whenever a gadget UP or DOWN */
APTR KeyCode; /* Called whenever a rawkey occurs */
APTR MouseMoveCode; /* Called when the mouse is moved */
};
assembly:
dc.l AddrOfStartCode
dc.l AddrOfDiskInsertCode
dc.l AddrOfGadgetCode
dc.l AddrOfRawkeyCode
dc.l AddrOfMouseMoveCode
=============================================================================
=== TECHNICAL REFERENCE =====================================================
=============================================================================
The FileIO files include:
requester.library the actual library (slightly < 10K in size)
FileIO.doc The documentation. You've obviously found it.
FileIO.h includes for an C application using the library
FileInterface.asm glue routines for a C application to use the
library. (poot) Expects all integers passed 32bit
FileInterface.lobj A BLink-able object for Lattice C users
FileIO.i assembly programmer's include file
main.c an application in C
CustomList.c an C demo using SPECIAL_REQ
Test.asm an application in assembly
CustomList.asm an asm application using SPECIAL_REQ
StartUp.asm the startup code for the assembly examples
TestFileIO an executable of the assembly application
MakeTest execute this script file to make the asm example
BasicFileIO an AmigaBasic application (do you believe me now?)
BasicString an AmigaBasic demo of SPECIAL_REQ
requester.bmap the bmap file for AmigaBasic
requester_lib.fd the fd file used to make the bmap file
CopyLib a utility to copy libraries to a boot disk
Not all of these files are included with this update. Only those files
which have changed since an earlier PD release have been included.
================= USING THE AMIGA PROGRAMMER'S SUITE =======================
The following is the message that appeared with RJ Mical's ProSuite code
on Fred Fish Disc #107. That version of FileIO was not a library. It was a
C code module that needed to be compiled and linked with your application.
At this point, the code for this library is significantly different than
the original, and quite incompatible with R.J's Includes and Defines. Also,
there are differences in both functionality and features. But R.J. started
the ball rolling so....
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.
If you use the Amiga Programmer's Suite, I wouldn't mind if you gave me
some mention somewhere.
Good luck! Program hard, program well. -RJ Mical
Make lots of money and become a arrogant, self-serving pain-in-the-ass.
-Jeff Glatt (my personal philosophy is a bit more philanthropic than RJ's)
=== APPENDIX A: FileIO Function Calls ======================================
CONTENTS:
AddEntry()
AddFileGadgs()
AutoMessage()
AutoMessageLen()
AutoPrompt3()
AutoFileMessage()
BW_Restore()
ClearEntries()
DecodeRawkey()
DeleteEntry()
DoFileIO() ;only 1 task at a time
DoFileIOWindow() ;only 1 task at a time
FindDeleteEntry()
GetFullPathname()
GetFileIO()
GetRawkey()
IsEntryThere()
NewEntryList()
ParseString()
PromptUserEntry()
PutProjIcon()
ReleaseFileIO()
ResetBuffer()
RetrieveEntry()
SetWaitPointer()
TypeFilename()
UserEntry()
Window_BW()
««««««««««««««««««««««««««« FILENAME FUNCTIONS »»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
*********************** DoFileIO(), DoFileIOWindow() **********************
NAME
DoFileIO -- Gets a file name for input/output from the user
DoFileIOWindow() -- The same, but opens a window for the requester.
SYNOPSIS
ULONG address = DoFileIO(fileio, window);
d0 a0 a1
ULONG address = DoFileIOWindow(fileio, screen);
d0 a0 a1
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 FileIO structure, which is allo-
cated and initialized via a call to GetFileIO(), or declared in your
application.
You may preset the FileIO parameters before calling this routine,
or you may leave them set at their default values. See the FileIO
documentation and include files 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.
DoFileIOWindow() is provided to circumvent this problem. It simply opens
a window on the passed screen before calling DoFileIO, and closes it
upon exit. By setting screen to NULL, the window opens on the WorkBench
screen. Also, you might use DoFileIOWindow if you wanted a requester
that could be moved or depth arranged by the user in an existing screen.
The title that appears in the window will be gotten from the address in
the FileIO's Title field.
You must initialize the FileIO's Buffer field to hold the address of a
buffer where the full pathname string (i.e. disk:drawer.../filename) will
be constructed. The size should be no less than 202 bytes. Also, the
FileIO's DrawMode, PenA, and PenB fields should be set to the values
you want restored when the requester closes.
This routine returns a 0 if DoFileIOWindow's window couldn't open, a -1
if the user selected CANCEL, or the address of the FileIO's Buffer if
all went well and the user selected a filename. The full path name will
have been constructed in the buffer. The filename itself will have
all leading and trailing blanks removed (in case the user typed in a
filename with extraneous spaces) and stored in the FileIO's FileName[].
Likewise, the disk and drawer names can be found in the text
fields DiskName[] and DrawerName[] of the FileIO. You can always call
GetFullPathname() to build the pathname from the separate fields of the
FileIO.
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 some
other task is calling DoFileIO() or DoFileIOWindow(), this routine
will automatically call TypeFilename() for the 2nd application.
INPUTS (for DoFileIO)
fileio = pointer to a FileIO structure, as allocated
via a call to GetFileIO()
window = pointer to a Window structure, as created via a call
to Intuition's OpenWindow()
RESULT
0 if an error in opening DoFileIOWindow() window. You will not get this
error for DoFileIO()
-1 if the user selected CANCEL
the address of the Buffer if all went well and a file was selected. Also
for assembly programmers the end of the string is in a1 like GetFullPathname.
BUGS
Clears the RMBTRAP bit of Window's Flags.
********************* GetFileIO() ************************
NAME
GetFileIO -- Allocate and initialize a FileIO structure
SYNOPSIS
struct FileIO *GetFileIO();
FUNCTION
Allocates and initializes a FileIO structure for use with
calls to DoFileIO(), DoFileIOWindow(), TypeFileName(), PromptUserEntry().
You may want to further initialize the structure before calling these
routines. At least the FileIO's Buffer, DrawMode, PenA, and PenB fields
should be initialized. Instead of allocating a FileIO via this routine,
you may declare one globally or statically as long as all fields are
initialized to zero or an approprite value.
When you're done with the structure, call ReleaseFileIO() regardless of
whether it was allocated or declared to free up resources.
INPUTS
None
RESULT
If all goes well, returns the address of a FileIO structure.
If anything goes wrong (out of memory), returns NULL.
*********************** GetFullPathname() *********************
NAME
GetFullPathname -- Build a file pathname using a FileIO struct
SYNOPSIS
Buffer = GetFullPathname(FileIO, Buffer);
d0 a0 a1
FUNCTION
Builds the text for a pathname using the FileName[], DrawerName[] and
DiskName[] fields of the specified FileIO structure after the structure
has been used in a successful call to DoFileIO(), DoFileIOWindow(), or
TypeFilename(). Writes the text into the Buffer.
INPUTS
FileIO = the address of a FileIO structure
Buffer = address of the buffer to receive the file pathname
RESULT
The address of the passed buffer. Also, for assembly programmers the
address of the terminating NULL is in a1 so you can quickly determine
the string length by subtracting d0 from a1 with the result in a1.
*********************** ParseString() *******************************
NAME
ParseString - Separate a path string into separate components
SYNOPSIS
ParseString(FileIO,String)
a0 a1
INPUTS
The FileIO structure
The address of the NULL-terminated path
FUNCTION
This takes the NULL-terminated path as it would be typed on a CLI line
Diskname:TopDrawer/....etc.../BottomDrawer/Filename
and parses it for "weird" typos or non-existant disk or drawer names.
Of course, there may not be any Disk or Drawer names. It then copies the
individual components of the Disk, drawer, and filename to the FileIO's
respective buffers, and sets the FILEIO_FILESIZE and FILEIO_FREEBYTES
fields accordingly. (i.e. If the path turns out to be a drawer or disk
only, then FileIO's Filename is NULLED and FileSize = 0. If a non-existant
file, it copies the Filename to FileIO, but FileSize = 0. If it is a
loadable file, it copies the Filename and sets FileSize accordingly.)
The parsed result is placed into the FileIO's Buffer (cannot be the same
buffer as the passed string).
This is useful for processing the initial argv argument passed to
_main for the StartUp code. It will initialize the FileIO buffers to
this passed name, and set-up the FileSize and Filename buffer so that
it can be determined what kind of object this is. Also, it makes it
possible to use the same load routine for the initial passed argv as
you would for DoFileIO() or TypeFilename(). For Basic programmer's this
can be used to set up the FileIO based upon a string gotten via an Input
statement.
************************* ReleaseFileIO() **************************
NAME
ReleaseFileIO -- Release the FileIO structure and all local memory
SYNOPSIS
ReleaseFileIO(fileio);
a1
FUNCTION
Releases the FileIO structure by freeing all local memory attached
to the structure and then freeing the structure itself if it is an
ALLOCATED_FILEIO (i.e. not pre-initialized in your application).
Restores the directory that was established when the FileIO was first
sent to DoFileIO() or DoFileIOWindow(). (You should not unlock the
initial dir that is contained in the FileIO's originalLock field.)
INPUTS
fileio = the address of a FileIO structure
RESULT
None
;********************* TypeFilename() ***************************
NAME
TypeFilename - Uses the window's titlebar to obtain the path name instead
of the file requester (an alternative). Displays the prompt
"Filename >"
SYNOPSIS
buffer =TypeFilename(FileIO, Window);
a0 a1
FUNCTION
If you really don't like the requester, and would prefer to have the
user type in the full path via the window's title bar, then use this.
Also, you might use this within a save routine so that the user has to
deliberately type his choice. The pathname contained within the FileIO's
Disk, Drawer, and Filename fields is what is initially presented to the
user. This routine is automatically called if an application tries to
call DoFileIO() or DoFileIOWindow() when another task is displaying the
FileIO requester. Also called if there is not enough mem to open/display
the requester. This routine sets up the FileIO's Disk, Drawer, Filename,
FileSize, and FreeBytes fields in the same manner as DoFileIO so that
you can interpret the results in exactly the same manner.
INPUTS
Window = the address of a window
FileIO = the FileIO structure
RESULT
Returns the address of the FileIO's Buffer or a -1 if the user bailed
out without entering anything. An ESC will return -1, but will store an
ESC char ($1B) and then NULL char in the buffer.
«««««««««««««««««««««««««« RAWKEY STRING INPUT »»»»»»»»»»»»»»»»»»»»»»»»»»»»
;*************************** DecodeRawkey() ***************************
NAME
DecodeRawkey() - Takes the passed RAWKEY Code and Qualifier and returns
an ascii value based on the System KeyMap.
SYNOPSIS
value = DecodeRawkey(Qualifier, Code);
d0 a1
FUNCTION
Because there exists different Amiga keyboard configurations and alternate
keymaps, there are only 2 proper methods for your program to translate user
keystrokes into ascii chars:
1). Use the console device.
2). Use VANILLA_KEY IDCMP.
The problem with #1 is that you have to deal with the console.device,
IO blocks, and Function, cursor, and other keys being translated as character
strings. Very UGLY!!!! The problem with #2 is that you don't receive Function,
cursor, or Help keystrokes. Very unfriendly!!! This routine solves both pro-
blems by managing the console device for you, and by "extending" the ascii
char set, it defines single ascii values for each Function, cursor, and Help
key.
INPUTS
Code - the code field of a RAWKEY IntuiMessage
Qualifier - the qualifier field of a RAWKEY IntuiMessage
RESULT
The return is a UWORD (not a byte as is usually the case with ascii chars).
This is because I have "extended" the ascii char set beyond hex FF in order
to define values for the Function, cursor, and Help keys. A zero is returned
if the key is undefined or if it is a KEYUP event.
Plain Function keys return hex 100 to 109 for the 10 keys.
The 4 cursor keys are hex 10A to 10D for UP, DOWN, RIGHT, and LEFT
respectively.
The Help key returns hex 10e.
Shifted Function keys return hex 200 to 209.
Shifted cursor keys are hex 20A to 20D.
Shifted Help key is 20E.
Alt Function keys are hex 400 to 409.
All other keys (and combos) return whatever value the System KeyMap contains
(except that all char strings are ignored and return 0).
;*************************** UserEntry() ***************************
NAME
UserEntry - Uses the window's titlebar to obtain user input.
SYNOPSIS
buffer = UserEntry(charlimit, initBuffer, FileIO, Window);
d0 a1 a2 a3
FUNCTION
This clears the window's titlebar, displays a cursor, and allows the user
to type in chars up to the limit, or until CR or ESC is pressed. The NULL
terminated result is placed in the FileIO's Buffer. When the charlimit is
reached, the routine automatically terminates. You must set the FileIO's
PenA, PenB, and DrawMode fields so that these may be restored by the lib
when the function is finished.
The initBuffer string is what is presented to the user (and what he may
edit). The passed window must have RAWKEY IDCMP set, and the FileIO's
RawCode field set to 0 in order to use the default decoding routine,
GetRawkey(). Otherwise, decoding will be redirected to the routine specified
in the FileIO's RawCode field. (Maybe you want VANILLAKEY instead. Or
maybe you also want to handle other IDCMP events while "inside" of UserEntry.
GetRawkey disposes of all but RAWKEY events. Or maybe you've set up your
own custom IDCMP port and RAW handling routine.) Regardless, your RawCode
routine must go to the window's IDCMP port to get a message or wait if
there is no message. It should handle all IDCMP messages except RAWKEY or
VANILLAKEY. If one of these messages, exit with an UWORD representing the
character as follows:
$20 to $7F for ascii chars, $7F for delete, $08 for BACKSPACE, $0D for
RETURN, $1B for ESCAPE, $010C for LEFT Cursor, $010D for Right Cursor,
$020C for SHIFT-LEFT Cursor, and $020D for SHIFT-RIGHT Cursor.
UserEntry will continue calling your RawCode for each char, and terminate
upon receiving an $0D or $1B, or reaching the charlimit.
Since the titlebar can hold approx 70 chars between the CLOSEGADGET and
FRONT/BACK, the FileIO's Buffer might be set to 70 bytes. It must be at
least as big as charlimit. Upon return, your window's title is restored.
INPUTS
Window = the address of a window
FileIO = the FileIO structure
charlimit = the number of characters to accept from the user
initBuffer = the NULL-terminated string to initialize the FileIO's
buffer to, or NULL if no initialization desired
RESULT
Returns the address of the FileIO's Buffer or a 0 if the user bailed
out without entering anything. An ESC will return 0, but will store an
ESC char ($1B) and then NULL char in the buffer.
;******************** PromptUserEntry() ***************************
NAME
PromptUserEntry - Uses the window's titlebar to obtain user input.
SYNOPSIS
buffer = PromptUserEntry(charlimit,prompt,initBuffer,FileIO,Window);
d0 a0 a1 a2 a3
FUNCTION
This works just like UserEntry except that it first displays the
passed prompt string in the titlebar. The FileIO's Buffer should always
be greater than the number of chars in the prompt plus charlimit.
INPUTS
Window = the address of a window
FileIO = the FileIO structure
charlimit = the number of characters to accept from the user
buffer = the buffer where the user's input is placed
prompt = NULL-terminated prompt to display
initBuffer = the NULL-terminated string to initialize the FileIO's
buffer to, or 0 if no initialization desired
RESULT
Returns the address of the FileIO's Buffer or a 0 if the user bailed
out without entering anything. An ESC will return 0, but will store an
ESC char ($1B) and NULL char in the buffer.
******************* SetTitle() ********************************
NAME
SetTitle - Uses the window's titlebar to display 1 or 2 strings.
SYNOPSIS
SetTitle(String1,String2,FileIO,Window);
a0 a1 a2 a3
INPUTS
Window = the address of a window
FileIO = the FileIO structure
String1 = the NULL-terminated string to the left
String2 = NULL-terminated string placed to the right of String1. If you
pass a zero instead, no 2nd string displayed.
FUNCTION
This will display the 2 strings in the window's titlebar (saving the
initial title to the FileIO's Title field), and return immediately with
the strings still displayed. Subsequent calls can be made to display
different strings, but when ResetTitle() is finally called, the initial
titlebar is restored. This routine is useful for displaying error msgs to
the user without halting program execution (like a requester does), and
allows the msg to remain visible for as long as it is needed. Furthermore,
it doesn't require that the user respond to it. This function makes temp-
orary use of the FileIO's Buffer, so you must supply a buffer whose address
is stored at the FileIO Buffer field. This buffer must be large enough to
contain both Strings.
******************* ResetTitle() ********************************
NAME
ResetTitle - Restores the window's titlebar after calls to SetTitle
(if any calls were made at all)
SYNOPSIS
ResetTitle(FileIO,Window);
a2 a3
INPUTS
Window = the address of a window
FileIO = the FileIO structure
FUNCTION
Resets the initial title (stored in FileIO's Title field) if it detects
that any calls were made to SetTitle. Otherwise, it does nothing.
««««««««««««««««««««««««««««««« CUSTOM LISTS »»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
******************* AddEntry() ***********************
NAME
AddEntry - For adding a string to be displayed in the FileIO's FileList
SYNOPSIS
ID_num = AddEntry(ID_num, String, FileIO);
d0 d1 a0 a1
INPUTS
The FileIO structure
The address of a NULL-terminated string to become the EntryString.
A ULONG (or LONG if you define it that way) that is associated with the
string.
FUNCTION
When the SPECIAL_REQ flag of the FileIO is set, then DoFileIO() and DoFile-
IOWindow() no longer do disk operations. Instead, the FileIO's FileList is
list of FileEntry structures which you create via AddEntry(). The passed
string becomes the EntryString and the passed ID_num is the EntryID.
RETURN
This returns the passed ID_num if the string was added to the FileIO's
FileList, or a -2 if no mem to add the string.
******************* ClearEntries() ***********************
NAME
ClearEntries - For de-selecting all of the FileIO FileList's FileEntries
SYNOPSIS
ClearEntries(FileIO);
a1
INPUTS
The FileIO structure
FUNCTION
This clears bit #7 of EntryFlags for all the FileEntry structures in the
FileIO's FileList. This may be useful for clearing selections after you
have processed MULTIPLE_FILES within a custom list (SPECIAL_REQ).
RETURN
NONE
************************ DeleteEntry() **************************
SYNOPSIS
DeleteEntry( PrevEntry, DeleteEntry, FileIO)
d1 a0 a1
INPUTS
The FileIO structure
Pointer to the entry (Remember structure) to remove
Pointer to the entry before the entry to remove (Previous entry)
FUNCTION
Removes DeleteEntry from the list. Needs the PrevEntry which is the
Remember struct preceding the one to be deleted from the linked list. This
is used mostly in conjunction with RetrieveEntry() or IsEntryThere().
RETURN
NONE
************************ FindDeleteEntry() **************************
SYNOPSIS
FindDeleteEntry(String, FileIO)
a0 a1
INPUTS
The FileIO structure
Pointer to the null-terminated string to find in the list and remove
FUNCTION
Searches the FileIO's list for the first instance of the string. Case-
insensitive match. If found, it removes that Remember structure.
RETURN
NONE
******************* IsEntryThere() **********************
SYNOPSIS
entrynum = IsEntryThere(String, FileIO)
d0 a0 a1
INPUTS
The FileIO structure
Pointer to null-terminated string to find in the list
RETURN
Returns the FileEntry number whose string matches the passed string. (Case-
insensitive). The numbers start from 0 with the first FileEntry structure
in the FileList being 0. For example, if your string matches the third
entry in the list, a 2 will be returned. A -1 is returned if the string is
not in the list. Also, the address of the matching Remember structure is
stored at the variable ThisEntry (in FileInterface.asm), and the previous
Remember struct in the list is stored at the variable PrevEntry (or 0 if
this is the head of the list). These two variables are used with
DeleteEntry(). For asm programmers, these 2 are returned in a0 and d1.
******************* NewEntryList() ***********************
NAME
NewEntryList - For freeing any previous FileIO FileList and resetting the
FileIO variables.
SYNOPSIS
NewEntryList(FileIO);
a1
INPUTS
The FileIO structure
FUNCTION
This deletes the FileIO's FileList (i.e. all of the FileEntry and Remember
structures created with AddEntry).
RETURN
NONE
******************* RetrieveEntry() ***********************
NAME
RetrieveEntry - For locating the next selected FileEntry structure within
the FileIO's FileList. (Used with MULTIPLE_FILES selection).
SYNOPSIS
FileEntry = RetrieveEntry(FileEntryPtr, FileIO);
d0 a0 a1
INPUTS
The FileIO structure
A PTR (the address) to a FileEntry structure within the FileIO's FileList
or a cleared PTR.
FUNCTION
When the MULTIPLE_FILES flag of the FileIO is set, then the library sets
bit #7 of the EntryFlags of every FileEntry that the user selected. This
routine helps you locate which files were selected, one at a time. The first
time that you call this function, FileEntryPtr should be cleared so that the
function will start at the first FileEntry in the FileIO's FileList.
RETURN
This routine updates FileEntryPtr to point to the next selected FileEntry
structure, and returns this address. If there is no next selected file, a 0 is
returned, and FileEntryPtr is cleared. If a FileEntryPtr not equal to 0 is
returned, you can access the FileEntry's Entry structure to get the EntryID and
EntryString. This are the FileSize and Filename, respectively. If SPECIAL_REQ
set, these are the ID and string, respectively. Also, if the returned FileEntry
is not the first in the list, the variable PrevEntry (in the module FileInter-
face.asm which you link with your C code) is the address of the previous
FileEntry. This may be used for DeleteEntry(). If the returned FileEntry is
the head of the list, PrevEntry will be 0. For asm programmers, the PrevEntry
address is returned in d1.
«««««««««««««««««««««««««««««« MISC ROUTINES »»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
************************* AutoFileMessage() ****************************
NAME
AutoFilemessage - AutoMessage with preset strings to choose from
SYNOPSIS
BOOL AutoFileMessage(messagenumber, window);
d1 a0
FUNCTION
The requester library has several messages it uses for internal use.
You can have one of these messages displayed just by passing the number
of the message you want. See Include file for available messages.
Some of the messages have two responses "YES" and "OK". Others have just
the "OK".
INPUTS
window = the address of a window structure
messagenumber = number of the string to be displayed
RESULT
Returns FALSE (d0 = 0) if the user selects "NO" or TRUE (d0 = 1) if the
user selects "OK".
******************** AutoMessage(), AutoMessageLen() ********************
NAME
Automessage - an easy implementation of an AutoRequester
SYNOPSIS
AutoMessage(message, window);
d0 a0
AutoMessageLen(message, window, length);
d0 a0 d1
FUNCTION
This displays the passed string (whose address is in d0) in a simple
AutoRequester. It manages the dimensions (automatically sizes to the
passed message) and the IntuiText structure for you. Use AutoMessageLen
if you know the length of the string to be displayed.
INPUTS
window = the address of a window structure
message = address of the string to be displayed
RESULT
None
************************ AutoPrompt3() **************************
NAME
AutoPrompt3 - AutoRequester with up to 3 lines of Text
SYNOPSIS
BOOL AutoPrompt3(message1, message2, message3, window);
a1 a2 a3 a0
FUNCTION
Displays up to 3 passed strings in an autorequester. Automatically
dimensions the requester to the size of the longest string, and
positions the other strings for a symmetrical display. Returns with
user's response to "YES" or "NO". You can also display only 2 or even
1 string if you pass NULL for the other messages.
INPUTS
window = the address of a window structure
message1 = address of the top string to be displayed
message2 = address of the 2nd string to be displayed or NULL if none
message3 = address of the 3nd string to be displayed or NULL if none
RESULT
Returns FALSE (d0 = 0) if the user selects "NO" or TRUE (d0 = 1) if the
user selects "YES".
************************ PutProjIcon() **************************
NAME
PutProjIcon - Like icon lib's PutIcon, but for image PROJECT icons only
SYNOPSIS
error = PutProjIcon(name, DiskObject);
a0 a1
FUNCTION
Most applications only need to save PROJECT icons as opposed to TOOL, or
DRAWER icons. Furthermore, most programs save image as opposed to border icons.
This routine is meant to replace the icon.library's PutIcon or PutDiskObject
for those icons. If the only function in the icon library you use is PutIcon
or PutDiskObject, you'll definitely want to get rid of your calls to an ugly,
6K C library and use this. You need to declare a DiskObject structure.
Set the GADGHIMAGE bit of the imbedded Gadget's Flags field. The GadgetRender
and SelectRender should point to initialized Image structs that point to
the icon data and define its Width, Height, and Depth. Set do_DefaultTool to
point to your NULL-terminated tool name, or NULL if no default tool. The
do_ToolTypes and do_DrawerData must be 0.
INPUTS
name - the name of the icon file to create (the .info will be added later)
DiskObject - an amigaDOS DiskObject structure
RESULT
Returns zero if successful. -1 if the icon couldn't be created. -2 if
a write error (i.e. ran out of space on the disk).
If an error occurs, the icon file is deleted.
************************ ResetBuffer() *********************************
NAME
ResetBuffer - Resets the cursor within a StringInfo's buffer to the
first position. Also, can NULL out the buffer itself and
reset the number of chars to 0.
SYNOPSIS
ResetBuffer(stringinfo, resetFlag);
a0 d0
FUNCTION
If you have a String gadget whose cursor you'd like to set back at the
first position, you can use this function. Also, if resetFlag is TRUE
(1) then the gadget's buffer will be NULLED. You must refresh the gadget
yourself after this call.
INPUTS
stringinfo = the address of a StringInfo structure
resetFlag = whether to NULL or not
RESULT
NONE
************************** SetWaitPointer() *************************
NAME
SetWaitPointer - Sets the zzz cloud pointer in the passed window.
SYNOPSIS
SetWaitPointer(window);
a0
FUNCTION
If you want to have a wait pointer appear in a window, you can use this
function which already has set up the pointer data in CHIP mem. Then
when you want to restore the pointer, call Intuition's ClearPointer().
INPUTS
window = the address of a window structure
RESULT
None
************************** Window_BW() *************************
NAME
Window_BW - Sets colors 0 and 1 to black and white
SYNOPSIS
origColors = Window_BW(window);
d0 a0
FUNCTION
Sometimes, as in loading an IFF picture that has colors 0 and 1 of similiar
intensities, it will be difficult to distinguish the text in a requester
from the background. Whenever you have an application where this may occur,
you should call this routine before DoFileIO() or DoFileIOWindow, or before
using any of the auto requester routines. This will set the screen's colors
0 and 1 to black and white so that the requester text will be readily visi-
ble. This function returns the original colors 0 and 1 as a ULONG. This will
be used to restore the original colors later with BW_Restore().
INPUTS
window = the address of a window structure
RESULT
None
************************** BW_Restore() *************************
NAME
BW_Restore - Resets colors 0 and 1 to original values
SYNOPSIS
BW_Restore(origColors, window);
d0 a0
FUNCTION
This function restores the original colors altered by Window_BW().
INPUTS
origColors = the return of Window_BW()
window = the address of a window structure
RESULT
None
************************** AddFileGadgs() *************************
NAME
AddFileGadgs - Allows adding more gadgets to the file/list requester
SYNOPSIS
AddFileGadgs(gadgetPtr, window, req);
a0 a3 a5
FUNCTION
This function allows you to add (or change) gadgets to the file requester
once it is open. This is intended to be used from within a CUSTOM_HANDLERS
routine, usually the StartHandler. The args window and req are the same
args that are passed to your custom handler by the lib. The gadgetPtr is
a pointer to the first gadget of the list to be added. When gadget msgs
are received by these gadgets (don't use the same ID #'s that the lib gadgs
use - see FileIO.h), your custom GadgetHandler will receive that gadget ID
#.
INPUTS
gadgetPtr = ptr to the first gadget
window = the address of a window structure
req = the fileio req structure
RESULT
None