home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_progs
/
prog_c
/
skel.lzh
/
SKEL
/
SKEL.DOC
< prev
next >
Wrap
Text File
|
1991-08-16
|
12KB
|
242 lines
"z
Skeleton Workbench Application
by Joel Swank
January 9, 1989
The Skeleton Workbench Application is my attempt to make
writing workbench applications (almost) as easy as writing CLI
applications. When I began adding Intuition interfaces to some
of my CLI utilities I found that I needed esentially the same
routines in each. So I decided to make a skeleton program that
provides all the basic routines needed by most applications. I
now have a 'Skel' directory that I copy to start a new
application. Then I rename and modify each of the files to suit
the new application.
The Skel directory contains the following files:
* makefile: File to compile Skeleton using Aztec C.
* skel.c: Mainline, initialization/termination,
Gadget and Menu handling.
* skwindow.h: Data structures for main window.
* doargs.c: Agrument processing for Workbench and CLI.
* abouthelp.c: Help window and About Requester processing.
* helpwin.h: Data structures for help window.
* skel.info: Tool icon for workbench startup.
Following is a description of the Skeleton and how I
customize it for a new application.
I rename skel.c and edit it to be the new main routine. The
main() routine first sets up any defaults needed. Then it opens
any libraries that are needed. Next it calls either the
Workbench or CLI argument routine. Next it sets up the gadgets,
opens the main window, and attaches the menu. Finally, it
writes the window text and waits for a message from Intuition.
The done() subroutine is the termination routine. It closes
or frees everything opened or allocated by the program. Whenever
I add something to the initialization, I add a coresponding
entry to done(). This is very important since AmigaDOS has no
resource tracking. If a program allocates a resource and doesn't
free it, that resource is gone until next boot. The done
routine is called from wherever program exit is required. It
accepts a return code that is passed to the exit routine to
become the error code for the program. Notice that done() checks
to see if a resource is allocated before closing or freeing it.
This allows it to be called at any time and it will only close
that which has been opened. For this to work, all resource
pointers must be set to NULL before initialization, and set to
NULL if they are closed anywhere else in the program.
The main loop waits for an IDCMP message to arrive at the
main window message port. When one does, it uses the Class field
of the message to determine what type of message was received.
It only reacts to CLOSEWINDOW, GADGETUP, and MENUPICK messages.
There are lots of other types that might be used. I can add
cases for these here and add the corresponding bit to the
IDCMPFlags of the NewWindow structure before opening the window,
or use the ModifyIDCMP() subroutine to change the IDCMPFlags
after the window is open.
The CLOSEWINDOW message just causes done(0) to be called.
This message is the result of the user clicking the Close
Gadget. Of course, the WINDOWCLOSE bit must be set in the
NewWindow Flags field for this gadget to be created.
A GADGETUP message indicates that user has selected one of
the gadgets in my gadget list. I use the RELVERIFY flag in my
boolean gadgets so that the user must click and release over the
gadget to activate it. The IAddress field of the message
contains the address of the Gadget structure of the gadget that
was selected. I compare this to a list of my gadget addresses(
a list of 1 in skel) to see which was selected. The only active
gadget in Skel is the 'GO' gadget which causes the do_it()
routine to be executed. I can add checks for more gadgets here.
Another type of boolean gadget I can use is a TOGGLESELECT
gadget. These gadgets are toggled on and off each time the user
clicks them. The current state is kept by intuition and can be
read any time by testing the SELECTED bit of the Flags field of
the Gadget structure. No message is generated when these
gadgets are clicked.
A MENUPICK message arrives each time the user brings up the
menus for my window. The message Code field contains a number
indicating which menu was picked. The processing of a menu pick
is handled in the do_pick() subroutine.
The do_pick() subroutine determines which menu has been
selected. It uses the standard macros to break the message code
into the menu number, item number, and subitem number. The
proper routine is selected with a series of nested switch
statements. Menus and items are numbered from zero starting in
the upper left. The Project menu has 4 items, each of which
cause the execution of a routine. The Options menu has only one
item that is an example of using MUTUALEXCLUDE subitems. I can
ignore the messages for these items because Intuition totally
handles turning on and off the check marks as the user selects
options. All I have to do is test the CHECKED bit in the SubItem
Flags field to see which item is selected. The only time I
might want to do something in response to a message for one of
these items is if the option being selected needs an
initialization routine to be run. After processing the
selection, I use the ItemAddress() subroutine to get the actual
address of the menuitem structure and get its NextSelect field.
This is either the number of another selection to be processed,
or MENUNULL. Selection processing repeats until all selections
in the chain have been processed.
The do_it() subroutine is the main action routine and it is
activated by the GO gadget. It first checks the options and then
calls off_gads(). off_gads() disables all gadgets except the
STOP gadget. In order to do this properly I must first use
RemoveGList() to remove all the gadgets from the window. Then I
can make any changes to the gadgets. I have made a couple of
macros (OffGad & OnGad) to set and clear the GADDISABLED bit in
the Gadget structure. There are Intuition subroutines to do this
(OffGadget() and OnGadget()), but these routines also refresh
the image of each gadget. It is more efficient and more visually
pleasing, when changing several gadgets, to to make all the
changes and refresh all the gadgets at the same time. I use
AddGList to put them back in the window, and then RefreshGlist()
to refresh the image of all gadgets. Some gadgets are not
redrawn properly unless they are drawn on background color, so I
use RectFill() to clear the window first. Notice that thr
redraw_scr() subroutine is actually part of on_gadds() and
off_gads() and should not be called elsewhere. Off_gads() also
removes the menus from the window so that the user cannot select
them while do_it() is running.
After adjusting the gadgets do_it() enters a loop of drawing a
graphic and checking for a message at the window port. Notice
that I cannot wait on the port this time because I have things
to do. So I have to call GetMsg() until I get a non-NULL pointer
back. I only recognize the CLOSEWINDOW and Stop gadgets.
CLOSEWINDOW executes done(). On Stop I exit the loop and finish
do_it() with the off_gads() subroutine. It swaps the gadgets
back and attaches the menu.
The Open menu item executes the do_open subroutine. This is
where I normally would have my interface to a File Requester and
the open of the returned filename. Instead Skel has just a test
of my standard 'Open Fail' error Requester.
I have included an _abort() routine. This routine is called by
the Aztec Chk_Abort routine. Chk_Abort is called by the Aztec
I/O routines to check for the cancel signal. It calls abort to
clean up and exit when it detects cancel. If the program uses
none of the Aztec I/O routines and doesn't call Chk_Abort,
_abort() is not needed. The only other use for _abort() is with
Manx's source level debugger (SDB). SDB calls _abort() when I
use the q command to exit the program early. If I put a call to
done() in _abort() the q command will release all my resources.
The doargs.c file contains a subroutine to get workbench
arguments and a subroutine to get CLI arguments. getWBargs()
finds the Workbench startup message and reads in the icon of the
first argument in the argument list. This is the icon used to
start the program. It should be a Tool icon. It may have
parameters set in the ToolTypes array. I use the FindToolType()
subroutine to check for my 3 possible tooltypes. FindToolType()
is case sensitive, so to change the DELAY argument 'DELAY=20'
must be entered, 'delay=20' won't work. I could also use the
MatchToolValue() subroutine to check for specific values of a
ToolType. The user can use Workbench Info tool to edit the
ToolTypes array. In order to read the arguments the
icon.library is needed. Since getWBargs() is the only place it
is needed, I open and close it here and it is not closed in
done(). getCLIargs() scans the C argument array for the same 3
arguments. There is also an empty subroutine called _wb_parse()
in this file. It is a dummy to keep the Aztec subroutine of the
same name from being included from the library. _wb_parse()
scans the ToolTypes array for a Window specification and opens a
window if it finds one. Since I am handling the ToolTypes array,
and opening my own window, I don't need the Aztec routine.
The files abouthelp.c and helpwin.h contain everything needed
for two items I always have on my Project menu, About and Help.
about() displays a requester with program name, version, author
and date. help() Opens its own full sized window and pages
through an array of text lines. The text is stored as an array
of pointers to lines of text. A NULL pointer ends the array. A
line with only a formfeed is a signal to stop and wait for the
user to click the 'MORE' gadget. This file also contains the
text structures for my AutoRequest() error requesters. I use
single and multi-line requesters to inform the user of errors
and other important information.
The skel.info file is a tool icon that can be used to start
skel. I edit this file using the icon editor to make an icon for
the new application. I use the Workbench Info menu selection to
edit the ToolTypes array and add any entrys needed by the new
application. I then rename it to match the name of the new
command.
The remaining file, skwindow.h, contains all the data
structures defining my main window, all its gadgets and all its
menus. This code was generated with PowerWindows 2.0. I use
PowerWindows to create all my window definitions. PowerWindows
makes designing and editing Screens and windows and all the
trimmings very easy. I always keep my PowerWindows generated
source unedited, so that it is easy to alter the definition and
generate new source. If you don't have PowerWindows, you can use
skwindow.h as a guide for creating your own window.
There are a lot of other things needed to flesh out an
application. One of the most common is a file Requester.
Fortunately there are several of these available in the public
domain. There is FileReq by Peter da Silva on Fish Disk #85, amd
Getfile by Charlie Heath on Fish Disk #41. I have been using
FileIO by RJ Mical from the prosuite package on Fish Disk #107.
Prosuite also has several other good utilities. There is a
ColorWindow for editing the palette of any screen. There is a
requester handler to help with more elegant requesters than the
AutoRequest() requesters I use.
Skel doesn't begin to exercise all the features of
Intuition, but it provides me with a good starting point for
getting my application up and running quickly. It should also be
a good way for a novice to learn Intuition a step at a time. "z