Disk Files
Volume Number: 3
Issue Number: 10
Column Tag: Basic School
Reading & Writing Disk Files 
By Dave Kelly, MacTutor Editorial Board, Ontario, CA
READING & WRITING “Z” FAST WAY
Reading and writing data is often taken for granted. Yet we read and write data
every time we turn on our computers. Fundamental to the Macintosh is the handling of
graphics, sometimes in MacPaint format, and sometimes in DRAW or PICT format.
Zedcor has some interesting commands that will speed up your data handling no matter
which format you are using.
Fig. 1 Paint scroller program scrolls PICT images
The commands I am referring to are WRITE FILE (E-159) and READ FILE
(E-126). I have used the examples in the manual as a base to set up my demo
programs. Before I discuss this more, let’s review the syntax:
READ FILE [#] filenumber%, desinationAddress&, NumberofBytes&
and
WRITE FILE [#] filenumber%, desinationAddress&, NumberofBytes&
The key is to set up variables that you want to read or write, find the pointer to
the variable ( destinationAddress& ) and read or write the desired NumberofBytes&.
Easy, right? I can just imagine some of the possibilities. How about a communications
program? Or a file transfer program? Or how about writing your own mini finder?
The WRITE FILE example in the ZBasic manual demonstrates a way that variables
may be temporarily stored (quickly) to disk, run another application, then return to
this program and read the variables back via READ FILE. This could always be done
before (with other Basic commands), but not as fast. I’ve taken the WRITE FILE
example and modified slightly to create a Mini Finder type program. Those of you who
have been around the Macintosh for a while will remember the old days when the
minifinder option was not a part of the Finder. Several minifinder type programs
popped up. By replacing the regular finder with a smaller finder, space on the disk
can be preserved. That was really all you could do when disks were limited to 400K.
Now with 800K disks and hard disks, the need is not as great. Still, with all the things
being added to the system file, if you don’t have a hard disk your system disk is
probably pretty full. My system file on my hard disk is over 1M byte (with all the
fonts loaded of course).
HOW IT WORKS
First you must realize that this program will not work properly unless you
compile it into a “full-blown” application. Since the program will launch another
application it will be impossible to return to ZBasic and load you basic source code to
run it again. So just compile as an application first. Also, this application must be
located in the “blessed” folder (i.e. the system folder). The reason for this is that this
application will temporarily take the place of the Finder (which also must remain in
the system folder). In a sense, our ZBasic application becomes a system application.
The program makes use of two global variables (available to all Macintosh
applications) namely, CurApName ($910) and FinderName ($2F0). The variable
FinderName contains the name of the Finder application (usually “Finder”).
CurApName contains the name of your application program. An application has no way
to know if a user has changed its name. If the application needs to no its own name, it
may refer to CurApName. The trick that this application uses is to temporarily change
the name of the Finder application to the current application name. The CurApName and
FinderName variables are stored in Pascal format with length first with the string
following. Be careful to observe the proper length of the strings. CurApName is type
Str31 which means it is a string with length (max) of 32. FinderName can only be 16
characters long because it is of type Str15. (A partial list of global variables is found
on page E-198 in the ZBasic manual).
Dummy first and last variables are set up to determine the block of variables
that you want to read. The variables will be read or write from that block of memory
which is marked by the first and last variables. It is important to realize that ZBasic
determines which variable is last during the compile process not during run time.
This is the reason for the subroutine “Get Last Variable Pointer” at the end of the
program. Notice that the last variable is defined at the very end of the program. If you
only have a few variables to store you may want to position the first and last to include
only those variables. Just remember that space should be reserved for reading
variables back. Just for fun the program records the timer count as one of the
variables to be stored. When the program is re-run after launching another
application, it will check the timer again and display the elapsed time.
An important additional comment is that you should remember to tell the user
what you have in mind when every you display a GetFile dialog box. IF your program
displays a dialog box to load/save a file or as in this case to launch an application, be
sure the the user knows why the dialog is displayed. If the dialog was displayed as the
result of a menu that was selected then the purpose is self explanatory. Occasionally,
I’ve seen programs that start up by displaying a GetFile dialog, without specifying that
the application is looking for a paint type file (for example). Well, I don’t keep my
paint files in the same folder as the applications so I wouldn’t know which type of file
was being requested. My suggested solution is to display another dialog above or below
the GetFile dialog which explains what kind of info is being requested. This is one way
to make the program much more user usable.
The ZBasic Quick “ZFinder” demo may spark some more ideas to help your next
programming project. The listing is included at the end of this column.
MORE FILE READING
The next program was derived from the READ FILE demo on page E-126 of the
ZBasic manual. Actually the only part of the demo that is used here is the method of
reading a paint file. For more information on reading paint files I refer you to my
column in September 1985 (gee, that was 2 years ago). Using READ FILE we read 720
lines with 72 bytes per line. The BLOCKMOVE statement is used to move the paint
picture into a reserved space in memory. Some of the variables used in the 1st
example on page E-126 are:
X%(1),71 -> represents a single line (72 chars) of the paint picture.
X$(719) -> 720 lines of the paint picture.
FL& -> File length (does not include pattern header).
The toolbox routine UNPACKBITS is used to decompress the paint file a line at a
time. The BLOCKMOVE statement moves the unpacked picture for safe keeping until the
entire file is unpacked. Be sure that this routine is not used between Event ON
statements and Event OFF as it will slow down a lot. That is because the Event
statements cause the compiler to put GETNEXTEVENT calls at the beginning of each
basic line. This routine works about 10 times faster without GETNEXTEVENT traps.
The are a few side effects of the Event loop which should be explained. For some
reason the PUT statement didn’t work properly outside of the event loop. Originally, I
had put the initial PUT statement in the subroutine that reads the paint file. This
caused the picture to be erase by some refreshing of the output window. But when
placed in the loop, the refreshing recognized that there was a change. I can’t explain
why this happened. Perhaps, Andy or Michael Gariepy of Zedcor could explain this one
sometime.
Credit for the cursors and scrolling go to Lee Bass of West Covina, CA. (Thanks
Lee). Lee’s original program had no menu and no event loop. Really, the event loop
should be short as possible (this one is kind of long), but since Lee implemented the
mouse functions without an event loop that’s how it stayed. I would prefer that ON
MOUSE be used to detect any mouse movements and remove all the appropriate
statements from the event loop. If you are just learning you may want to try modifying
the program by implementing ON MOUSE GOSUB type structure to the program. Lee’s
cursors were created with ResEdit and converted to RMaker files to make it easier for
you to type in these programs if you are so inclined. The window was divided in to
thirds horizontally and thirds vertically to give 9 sections for the nine different
cursors. During the main event loop the mouse is read to determine its position and
the cursor is modified according to which of the window sections the coordinates fall.
Pretty simple but maybe you have a better way. If you have any suggestions feel free
to send them in.
This program requires that you use RMaker to create the cursor resources.
Since the current version of RMaker doesn’t work well with HFS you should move the
compiled application and RMaker out on to the desktop and run it from there. The
RMaker source file can be in any folder. RMaker appends the cursor resources to the
application file only if you have named the application the same as the name in the first
line of the RMaker source file. If you can’t find RMaker (distributed with ZBasic) or
don’t like it (or just plain don’t understand it) you may want to create your cursors
with ResEdit. The cursor resource ID numbers are :
257 -> up arrow
258 -> down arrow
259 -> left arrow
260 -> right arrow
261 -> top/left arrow
262 -> top/right arrow