home *** CD-ROM | disk | FTP | other *** search
-
-
-
-
-
- "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
-
-
-
-
-
-
-