home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fish 'n' More 2
/
fishmore-publicdomainlibraryvol.ii1991xetec.iso
/
fish
/
libraries
/
fileio_463
/
fileio.doc
< prev
next >
Wrap
Text File
|
1991-03-09
|
105KB
|
2,321 lines
Set your editor's TAB width to 3
FileIO Requester
User and Programmer Manual
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 document describes the FileIO Requester library, both for users of
the requester and for programmers who will utilize the library.
The main sections of this document are:
o FROM THE USER'S POINT OF VIEW
o PROGRAMMER'S REFERENCE
o DEMO PROGRAM NOTES
o TECHNICAL REFERENCE
o USING THE AMIGA PROGRAMMER'S SUITE
o APPENDIX A: FileIO Library Function Calls
============================================================================
=== FROM THE USER'S POINT OF VIEW ==========================================
============================================================================
This section presents the FileIO Requester from the user's point of view.
This is a example of the sort of documentation that might be supplied to the
end user of this FileIO Requester. Simply clip from here to the Programmer's
section, and include this as a chapter in the user manual.
=== The FileIO Requester ========================================
This program employs a file requester based upon R.J. Mical's ProSuite unit,
though this library implementation has been modified extensively.
The FileIO Requester allows you an easy way to select which file you want to
use for input or output. The following describes how you go about using the
FileIO Requester.
The FileIO Requester consists of several parts:
o the "Select a Name" list which allows you to choose a file name simply by
scrolling through a list of names until you find the one you want, point-
ing at the name and clicking the left mouse button
o the OK! gadget which you use to acknowledge that the name you've chosen
is the one that you wanted
o 3 string gadgets which allow you to type in the name directly rather than
using the "Select a Name" list to choose the file that you want
o a NEXT DISK gadget which allows you to examine one disk after another
o the CANCEL gadget, which you use when you've decided that you don't want
to select a file after all
The "Select a Name" list presents you with a list of file names in the current
drawer. You use the mouse to scan easily through the list and select one of the
filenames simply by pointing at it and clicking.
The "Select a Name" feature consists of:
o a box of where some of the list of file names are displayed
o a slider (to the right of the box) which lets you quickly scan through
the list of files
o an up arrow gadget and a down arrow gadget (above and below the slider)
which allow you to move through the list one filename at a time
There are 3 types of entries in the list of file names.
At the top of the list are the file names that you can choose. These names are
listed in alphabetical order (case insensitive).
At the bottom of the list there are special entries which allow you to move
around through the drawers of a disk, much like you move around through drawers
on the Workbench display.
The entries that start with the ">>>>" characters allow you to "open" a drawer
and examine the names of the files in that drawer. For example, when examining
a Workbench disk, at the bottom of the list you would find an entry that looked
like ">>>> Devs" which means that you can go into the drawer named "Devs". If
you selected ">>>> Devs" you would see, after a short pause, a new list of file
names: the names of the files that are in the "Devs" drawer.
In the "Devs" drawer you would also find a special entry, "<<<< PRIOR DRAWER".
If you select this entry, you will move back to the drawer that contained your
current drawer.
An alternate way to change drawers is to type the name of the drawer you want
in the string gadget labeled "Drawer". It is located beneath the filename list.
You select the gadget, type in the name, and hit return. If you type the name
of a drawer which does not exist, the FileIO will send you back to the root
directory of that disk. The length of the string that you type into the drawer
gadget is limited to 132 characters. Since AmigaDOS limits the length of all
file, drawer, and disk names to 30 characters, this means that you can safely
nest drawers (one inside of another) up to four drawers deep. Beyond that, you
should make sure that you name your drawers less than 30 characters each. The
FileIO will not allow you to go any deeper after the drawer gadget has 132
chars in it.
Once you have a list of file names to choose from in the file name box, there's
a slider gadget to help you scroll around through the names. The slider is to
the right of the file names. It has a knob which you move to scroll through the
names. The knob will be different sizes depending on the number of names in the
file list. If the knob is small, this means that you can see only a small
number of the total file names. The smaller the knob, the more names there are
to see. On the other hand, if you can see all the names in the list, the knob
will fill up the entire slider and you won't be able to move it.
To view the file names, you "grab" the slider's knob and move it up and down.
You grab the knob by pointing at it and pressing and HOLDING the left mouse
button. When you have grabbed the knob, you can move the pointer and scan
quickly through the list of file names.
Also, you can view the list of names one page at a time by clicking to either
side (but not on) the slider's knob. If you want fine control of your movement
through the file list, the up and down arrows let you adjust the list of names
one name at a time. If you hold the mouse button down while on top of either
arrow, the filenames will scroll in that direction. When you release the
button, scrolling stops, but if instead you move off the arrow before releas-
ing, the scrolling continues. Auto-scroll will continue until you click on a
scrolling filename, or until the end of the list is reached.
Once you have found the file name that you want to choose, you select it by
pointing at it and clicking. When you do this, the name will be highlighted
and it will appear in a box labeled "Name" beneath the list. When you've
decided that this is really the name you wanted to choose, click on the OK!
gadget. Another way to tell the program that you're sure you want to select
a certain file name is by double-clicking on the file name in the same way
that you double-click on a Workbench icon. Double-clicking is exactly the
same as selecting a name and then OK!
If you don't want to use the "Select a Name" feature, you can select a name
by clicking on the string gadget labeled "Name", typing the desired filename,
and then hitting return or clicking on the OK! gadget. Hitting return after
typing the name you want is the same as selecting OK! You can select and type
into the string gadgets at any time. You don't have to wait for the wait
pointer to change before you hit return! If you type in the name of a disk that
is not mounted, and then refuse to insert it into the drive when AmigaDOS asks
you for it, the FileIO switches to another disk that is mounted (if another
floppy exists).
To view the files of a different disk, select the NEXT DISK gadget. When you
do, the name of the next disk is displayed in the Disk string gadget and the
disk is then searched. If this disk isn't the one you wanted, you can press
NEXT DISK again even though you may be seeing the wait pointer. You can press
NEXT DISK quickly as many times as you want until you see the name of the disk
you want in the Disk gadget. If you prefer, you can also type the name of the
disk you want directly into the Disk string gadget. If the disk you want to
examine is not in the drive, you may remove the disk that the requester has
last examined (after the light goes out of course), and insert the desired disk
in that drive. Now wait for the requester to automatically update its display.
After inserting a disk, the requester will automatically redraw the list.
Alternately, you may select a new disk by clicking the RIGHT MOUSE button.
The filenames will be replaced by a list of all the mounted volumes (or
devices). The name of the disk that you are currently examining will be
highlighted. You can scroll through this list of disk names using the slider.
When you see the disk name that you would like to examine, click the LEFT
MOUSE button on it. The FileIO will then display the contents of that disk.
Note that all of your logical assigns are also displayed (i.e. LIBS, FONTS,
etc.) If you wish to only see the actual disk names, press function key #5
while the requester is open.
You might notice that the ZZZ-cloud wait pointer looks a little different
from the ones you're used to on the Amiga. The FileIO Requester's ZZZ-cloud
pointer has a small tab at the top left which allows you to continue pointing
and making selections even though the ZZZ-cloud is displayed. The FileIO
Requester's ZZZ-cloud tells you that it's working, but it doesn't make you
wait.
You might notice also that the file names start appearing one by one
alphabetically in the list. You can select one of these names even before all
of the names have been added to the list, although this can be a bit tricky as
they move around a lot. While the list is being built, you can use the slider
to look at what names have already been added. If you see the name that you
want to select, you can stop the building of the file name list by clicking on
a spot inside the requester but outside of all of the gadgets. For instance, if
you click above (but not on) the OK! gadget, this will stop the list from being
constructed. Then you can select the name you want as usual. To restart the
building of the file name list, click on either the Drawer or Disk string
gadget and hit return. You can also stop the display of filenames temporarily
by grabbing and holding the scroll gadget. When you release, the display will
continue.
For some reason, the requester may not be able to open. Maybe another
program is already displaying it. Only one program can be displaying it at a
time. Or perhaps you have used up too much memory. In either case, instead
of a requester, you will see this prompt in the title bar of the window.
Filename >
This will be followed by a cursor and whatever filename you last chose with
the requester. You must now type in the complete name (including the drive and
drawer names) as you would in the CLI. For example,
Extras:BasicDemos/ConvertFD
If the window is not full size, you should move it to the upper left corner
of the monitor display, and resize it to fully open. Then press any cursor key
to redisplay the cursor. If there was no previous filename, then you will see
the ":" current directory sign. Move the cursor past this and type in the
filename that you wish to save or load if it is on the current disk. Otherwise,
you need to type the name of the disk upon which the file can be found. The
disk name goes in front of the ":", and the drawers and filename go after the
":". (If the file is on the current disk, and in the current drawer, you only
need to type the filename. Otherwise, you must specify which disk and drawer
you really want.) If the filename that is initially displayed is the one that
you want, simply press RETURN.
You can use the cursor keys to move about in the filename, deleting charac-
ters with the delete or backspace keys. If there is any text extending beyond
the border of the window, you can scroll to it using the cursor keys.
Holding the ALT key while pressing the cursor keys will move to the
beginning and end of the typed filename.
When you are satisfied with your choice, hit RETURN. Otherwise, hit the
escape key to cancel.
You have the facility to "customize" the requester for each application.
After the requester comes up, the function keys have the following purposes:
F1 - Operates the same as selecting the Next Disk gadget.
F2 - Toggles between using the volume name or the device name of the floppy.
For example, if you place your WorkBench disk in the internal drive
and you are using volume names, "WorkBench 1.3:" will appear for the
Disk name. If using device names, "DF0:" will appear instead.
F3 - Any filename that ends in ".info" will not be displayed. To disable
this feature, select F3 again.
F4 - Only displays filenames that end with a phrase that you provide.
You will be prompted to enter a string in the title bar of the window.
If for example, you typed .library, then the requester would display
all drawers, but only those files that end with .library. The word
need not be an extension. You could also specify that only files that
end with the word, picture, be displayed. To disable this feature,
select F4 again. The program that you are using must support this
feature for it to work. If the program doesn't support it, F4 will do
nothing. When you type any string into the NAME gadget, the extention
will automatically be added.
F5 - This toggles ON/OFF the facility for displaying the logical assigns
in your system. A logical assign is the C: directory for example. This
directory might be on your hard drive DH0:. If you toggle the assigns
OFF, then you'll just see DH0: in the list of devices when you click
the right mouse button. If you toggle assigns ON, then you'll see both
C: and DH0: in the list. Remember that you can also choose to use the
volume or device names (as toggled by F2).
F6 - This will cause the requester not to initially reconstruct the filename
list on subsequent uses. The advantage is that the next time the req-
uester comes up, the names will appear immediately. The disadvantage is
that if you save a file, it will not appear in the list until you turn
this feature back on (momentarily anyway). Turn it on/off by pressing F6.
F7 - WorkBench matching ON/OFF. If ON, this only displays those names that
end in .info (just like WorkBench does). Also, a prompt asks you whether
you want only those names that are TOOLS, PROJECTS, or any kind. An example
of a TOOL is a program that you can run, like NotePad. An example of a
PROJECT is a data file, like a note you might write using NotePad. The
names of disks are never displayed in the filename list.
F8 - Alphabetize feature ON/OFF. When ON, the filenames are alphabetized in
the display. When OFF, newer files are listed at the top of the display.
F9 - Same as the CANCEL gadget.
F10 - Same as the OK! gadget.
When you customize the requester, it only affects that one application, so
different programs can have different "customized" requesters.
============================================================================
=== PROGRAMMER'S REFERENCE =================================================
============================================================================
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 DoFileIO() is non-reentrant
o Interpreting the return values of DoFileIO()
o Internal Error Handling
o Quick Display (NO_CARE_REDRAW)
o Workbench-style Filename Operations
o .Info File Suppression
o Filtering by Extension
o No Icon (.info) files
o FileIO Flags
o RAM Disk Bug
o Free Disk Space
o Procedure for Opening and Using the FileIO Requester library
o Using the requester to display lists of strings
o Filename and Custom Lists
o Multiple Filenames
o Installing Custom Handlers
========================== 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. If you use multiple FileIOs,
when you go to free them, free the FileIO that you first used for disk IO last.
(ie The first FileIO to be used with DoFileIO, DoFileIOWindow, ParseString,
ParentPath, or ParentLock, without the SPECIAL_REQ flag set).
====================== 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, although 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, alt-right and alt-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 alternative to having a string
gadget (which takes up window space and also requires allocating several
structures), plus allows for displaying custom prompts. The user can scroll to
any text 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 values 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 deter-
mine 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 file-
name, 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, via DoFileIO perhaps).
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 I 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, you'll
need to install a custom handler for DISKINSERTED events (see the section
on Custom Handlers), and within this function you should clear the
NO_CARE_REDRAW flag in all of your 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, etc).
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.
====================== .Info File Suppression =========================
Setting the INFO_SUPPRESS flag is exactly the opposite of Workbench
matching. All files that end in .info will be ignored, and are 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
Setting this means that the filename data is NOT to be reconstructed before
initially drawing the requester. The previous list is instead redrawn.
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.
EXCLUDE_ASSIGNS
If set, then when the list of device or volume names is displayed, no
logical assigns appear in the list. Only the actual disk device names
appear. The default is to allow logical assignments. Note that when you
pre-initialize the fileIO's DiskName[], you should set the USE_DEVICE_NAMES
and EXCLUDE_ASSIGNS to the desired values before calling DoFileIO(). For
example, if you wish the file requester to open up displaying all of the
files on DF0:, then set USE_DEVICE_NAMES, copy the string "df0:" into
the DiskName[] buffer, clear the Drawer and FileName[], and call DoFileIO.
If you want to display all the files in the LIBS: drawer, make sure that
EXCLUDE_ASSIGNS is clear, copy "libs:" into the DiskName[], clear the
Drawer and Filenames, and call DoFileIO. (USE_DEVICE_NAMES won't matter
since logical assigns are added whether device or volumes names are
displayed.)
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. The WBENCH_MATCH flag must also be set.
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.
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) /* the class field from an Intui Message */
{
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) if you intend
to use DoFileIO().
Initially, you might want to set the FileIO to open in the directory from
where your application was invoked. You do this by passing a 0 to ParentLock().
Alternately, if you expect to receive an argument filename from the user (via
Workbench or the CLI), you would use ParentPath() to set up the FileIO to that
filename and complete path.
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 those 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 = JAM2;
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 */
}
/* Else tell the user that he's about to overwrite */
}
/* Error in entering filename (i.e. did not enter a 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 constructing 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 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 inter-
action, 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 removed 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 alpha-
betical 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).
NOTE: Your strings must be limited to 192 bytes (counting the final null).
The file requester only displays the first 29 bytes of the string. Furthermore,
when the string is copied to the FileIO's Filename buffer, the size of that
buffer is 192 bytes (ie Filename[192]) instead of 30 as with normal disk I/O.
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.
Once you setup a FileIO's list, it remains this way until you perform
NewEntryList, or use that FileIO for disk IO. You do not have to remake the
same list everytime that you call DoFileIO.
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 Entry-
String does not contain the full path, only the filename. (The path can be
constructed with the FileIO's Disk and Drawer buffers. The best approach is to
copy the filename to the FileIO's FileName buffer and then call GetFullPathname
to add the FileIO's Disk and Drawers.)
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, or for when 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
choises.
Consult the examples for how to use MULTIPLE_FILES.
========================== 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 */
};
In assembly:
HandlerBlock
dc.l AddrOfStartCode
dc.l AddrOfDiskInsertCode
dc.l AddrOfGadgetCode
dc.l AddrOfRawkeyCode
dc.l AddrOfMouseMoveCode
=============================================================================
=== DEMO PROGRAM NOTES ======================================================
=============================================================================
This section briefly describes the demo programs that drive some of the FileIO
Requester library's features. There are C, assembly, and AmigaBasic demos (no
joke).
If you invoke some of the C or asm demos without a second argument on the CLI,
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, TestFileIO.c, uses two FileIO structures to demonstrate the tech-
niques that you should use when managing multiple FileIOs. The first FileIO
structure, fileio1, is used in its default state as created by GetFileIO(). The
other one, 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). CustomList.c demos setting up a custom list of strings.
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 Prompt-
UserEntry() 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 that 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, BasicFileIO 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. BasicList
demos how to use the FileIO to display a list of your own strings. MultipleList
and MultipleFile demo how to handle multiple selections for both filename and
custom lists in BASIC.
=============================================================================
=== TECHNICAL REFERENCE =====================================================
=============================================================================
The FileIO files include:
requester.library the actual library (slightly < 11K 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
FileIO.i assembly programmer's include file
TestFileIO.c a C example of filename selection
CustomList.c a C example using SPECIAL_REQ
TestFileIO.asm an assembly example of filename selection
CustomList.asm an assembly example using SPECIAL_REQ
StartUp.asm the startup code for the assembly examples
TestFileIO an executable of the assembly filename example
CustomList an executable of the assembly SPECIAL_REQ example
BasicFileIO an AmigaBasic application of single filename selection
BasicList an AmigaBasic demo of SPECIAL_REQ
MultipleFileIO an AmigaBasic application of multiple filenames
MultipleList an AmigaBasic demo of SPECIAL_REQ with multiple select
requester.bmap the bmap file for AmigaBasic
requester_lib.fd the fd file used to make the bmap file
================= 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()
DoFileIO() ;only 1 task at a time
DoFileIOWindow() ;only 1 task at a time
FindName()
GetFullPathname()
GetFileIO()
GetRawkey()
IsEntryThere()
NewEntryList()
ParentLock()
ParentPath()
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.
********************* FindName() ************************
NAME
FindName -- Isolate the filename part from a complete pathname
SYNOPSIS
pathend = FindName(buffer,pathname);
d0 a0 a1
FUNCTION
Separates the filename part from the passed, complete pathname string. The
pathname may contain drawer and disk names (i.e. df0:someDrawer/filename).
The filename part is then copied to the passed buffer, and this is stripped
from the pathname.
INPUTS
FileIO
pathname - a pointer to a null-terminated path string
RESULT
Returns the address of the terminating null byte of pathname so that you
can quickly append a new filename to this path (dir)
********************* 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.
*********************** ParentLock(), ParentPath() *************************
NAME
ParentPath, ParentLock - Create an entire path from a filename or lock
and parse it into the FileIO
SYNOPSIS
ParentPath(FileIO,Name)
a0 a1
ParentLock(FileIO,Lock)
a0 a1
INPUTS
The FileIO structure
The address of the NULL-terminated filename (for ParentPath)
An amigaDOS lock (for ParentLock)
FUNCTION
These 2 functions recreate an entire path from just a filename or a lock.
They are very useful for interpreting the args from Workbench or the CLI
when your program is started. They create the entire path in the FileIO's
Buffer, then call ParseString() to separate the components into the FileIO
Filename, Drawername, and Diskname buffers, and set the FILEIO_FILESIZE and
FREEBYTES. For example, assume that your program takes the following file-
name arg from the CLI:
1> MyProg <some data filename>
Let's assume that the user's current directory is a drawer in RAM: called
"Blort". He runs your program as so:
1> MyProg MyName
Now, how do you know where MyName is if the user didn't specify the entire
path of RAM:blort/MyName? Well, you can pass the string that he did type to
ParentPath() and your fileio buffer will be returned with that complete path
(and the FILESIZE and FREEBYTES set accordingly). The fileIO FileName will
contain "MyName", the DrawerName will be "blort", and the DiskName will be
"RAM:". When the user calls up the file requester, this is how it will open.
ParentLock() creates the entire path based upon a Lock. For example, some
program sends you a lock on a file. You can create the entire path and parse
it into the FileIO with this function.
From WB, the user may click on the icon for the data file. You simply
get the wa_Name from the arg for the data file and call ParentPath().
As a third example, you may wish to obtain the complete pathname for
your program (ie tool name) since the user may have renamed it. You'll want
to save icons with this tool name string. This is done with ParentPath in
the same manner as with the data file examples.
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.
Note that for non-existant paths or filenames, this will NULL out the
path buffer. In such a case, it may be necessary to strip off the filename
part using FindName, and call ParentPath with this new path. Then, you
can reappend the filename part by copying it back to the FileIO FILENAME
buffer, and calling GetFullPathname to finally recreate the complete path.
All of this hassle is due to the fact that AmigaDOS, a very inadequate DOS,
has no facility to easily obtain the complete working path of a CLI's
current directory. (When is CBM going to fix this???)
*********************** 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 can be used in place of the slower ParentPath() as long as you're
sure that the complete path (including all dir levels) is part of the
string. Otherwise, the FileIO is set up to default to the current directory.
For example, if you wanted to check for the existance of a file without
bringing up the requester, and you know the complete path, use this.
************************* 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
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 »»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
************************* AddFileGadgs() ****************************
NAME
AddFileGadgs - Adds file gadgets to the requester (while opened)
SYNOPSIS
AddFileGadgs(Gadgets, window, requester);
a0 a2 a5
FUNCTION
This is used to add gadgets to the requester after it has opened. The most
logical place to do this would be in a call to your custom StartHandler. To
remove those gadgets later (while the requester is still open), pass a null
(0) for Gadgets. The requester and window parameters are the same as the
library passes to your custom vectors.
NOTE: The library automatically removes any gadgets that you added when
the requester disappears.
************************* 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 - Changes the window's colors 0 and 1 to black and white
SYNOPSIS
oldColors = Window_BW(window)
d0 a0
SYNOPSIS
If you present the file requester (or any of the auto-requesters) in a
window where color #0 and #1 are very similiar, the text and graphics for
the requester will be very difficult to distinguish from the background.
This scenario is quite possible when loading an ILBM picture into a window
and then bringing up the requester. Calling this function before DoFileIO()
will result in your window colors #0 and #1 being changed to black and
white. When the requester appears, it will be rendered in a satisfactory
manner. Upon return from DoFileIO, you can then call BW_Restore to restore
those colors to the original state. Basic users note that these functions
are called Window.BW and BW.Restore for your use.
RESULTS
ULONG oldColors - the previous colors as a ULONG
************************** BW_Restore() *************************
NAME
BW_Restore - Restores the window's colors 0 and 1 to oldColors
SYNOPSIS
BW_Restore(oldColors, window)
d0 a0