home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
500-599
/
ff597.lzh
/
ShadowMaster
/
docs
/
Programmers
< prev
next >
Wrap
Text File
|
1992-02-01
|
8KB
|
159 lines
How to build a shadowmaster module.
*** Quick Start for SAS C programmers:
Doing a graphics module is relatively easy. Copy the
"source/savers/black.c" source to the name you've chosen, change the
colorspec, Title, Screen and Window tags as appropriate, and then put
your graphics code in the routine "dographics". Dographics is called
with screen and window opened as you specified, and the raster set to
color 0. Build your blanker, and run it from the CLI to test it. Use
CTRL-C to exit.
A utility module is somewhat harder. Use the template
"source/savers/guard.c" as a basis, replacing the template and the
routine "doutility" as needed. If you're going to do a simple utility
that just starts a single blanker and then waits for the CTRL-C, your
routine should just return the command string. If your utility wants
to wait for other things (timeouts, etc) or wants to do something
other than exit on keyboard input, you need to compile with -dLOOPS.
In this case, doutility's argument is TRUE the first time after the
utility is started, and you should just hand back the command string.
After the command is launched, doutility is called with a FALSE
argument. It should then wait for whatever events it wishes, then
return the string for the next command to be run. For either case,
returning a NULL pointer will cause the utility to exit.
NOTE: Your routine (dographics or doutility) must RETURN, and not call
exit.
For more information, see the source files black.c, guard.c,
savermain.h and utillitymain.h in the savers directory.
If you aren't using SAS C, you can try to compile the above templates
without a do routine, and then link in with an appropriate routine
from your favorite language. However, it's probably better to write
the interface code from scratch, using the appropriate main.h files as
a guide.
*** The Interface Specification
A saver module is told to start by being executed normally. It is told
that it should stop by being sent a SIGBREAKF_CTRL_C signal. This
means that doing graphics modules - that only need to do the client
half of the interface - is relatively easy. Almost any command that
can be run from the CLI and stopped with a CTRL-C can be used. The
templates for SAS C are tweaked to be small, but that's all that is
special about them.
On the server side, things are much more complicated. You can't just
launch your client module, and blithely wait for the event that means
they should exit and send them a CTRL-C. If they have exited
beforehand, your signal could cause the system to crash. Further, your
client may (for its own reasons) decide to ignore your signal, and not
exit. You must not start another client until it has exited. Because of
this, you need to find out when the client exits.
Fortunately, 2.0 provides a perfect facility for this. pr_ExitCode has
been added to the process structure, and is run when the process
exits. Unfortunately, I've not been able to get anyone at CBM to state
that it's safe to send a signal at anytime before this code exits, but
testing shows that the code runs with the same Task structure as is
created by CreateNewProc with the tag NP_ExitCode used to set
pr_ExitCode. Depending on this code to signal the exit should not
create any race conditions.
The standard used in the templates is that a global variable holds a
pointer to the client Task structure, and pr_ExitCode sets that
pointer to NULL, then sends a signal to the server task (with a
pointer in a second global) to indicate that it has exited, and the
server should do whatever it feels needs to be done in that case.
Note that the Task structure pointer is accessed by multiple tasks,
and is used to communicate between them. Because of the dangers
inherent in misreading the value of this variable, the changes to it
and the attempts to read it must be locked from mutual access. A
SignalSemaphore is used for this.
*** Configuration
The configuration sytem has two types of objects in it, utility module
preferences editors, and saver module configuration programs.
Configuration programs should open a window at 0,11 with the gadgets
appropriate for that saver module, including a way of aborting with no
exit. After the user indicates they wish to use the selected
configuration, the configuration program should write a line to
standard output that can be used to invoke it. Put in all keywords,
and don't assume that the module will live in a specific directory. If
no changes are made, don't write anything to standard output.
Utility modules all use preferences editors. The only allowable start
switch is "FROM", indicating a preferences file to use other than the
defaults (generally, env:shadowmaster/modulename.prefs). They should
be AUISG compliant and provide appropriate facilities for selecting,
configuring and testing the next module in the chain.
To make this task somewhat easier, the file source/config/prefs.c
provides a "startup" module for building preferences editors. The user
code must provide the following external variables, initialized to
approiate values:
int windowheight ; /* Height to open the window to */
int windowwidth ; /* Width to open the window to */
char *basename ; /* env:basename/appname.prefs */
char *appname ; /* is the default prefs file */
char *errname ; /* error reports look like errname: text */
You must also provide the following functions for prefs to call:
int SaveFile(char *) ; /* Save current preferences to named file */
int LoadFile(char *) ; /* Load preferences from named file */
int Undo(void) ; /* Undo last action */
int Defaults(void) ; /* Reset to defaults */
int UserGadgets(struct Gadget *ng,/* Add user gadgets to window */
struct NewGadget *gad) ;
void CleanUp(int) ; /* Cleans up before exit */
The Undo and Defaults return TRUE to cause an immediate exit, but
should probably always return FALSE.
SaveFile and LoadFile return the success of the operation asked for.
Cleanup is passed a TRUE if the user exited with changes to the env:
or envarc: preferences files, false otherwise.
UserGadets adds the editor-specific gadgets, and returns FALSE if it
fails. ng is the newgadget structure used to set up the bottom row of
gadgets. You can (and should) use ng_TextAttr from it, and can depend
on ng_TopEdge being the top edge of the gadgets for placing your
gadgets. The created gadgets should have ng_UserData set to point at
int (*)(struct Gagdet *, UWORD) functions to handle the gadgets. They
are called when that gadget is selected by the user, with the gadget
pointed to by the first argument, and the IntuiMessage Code field as
the second argument. gad is the last gadget created on ng, for
passing to CreateGadget. These gadgets should return TRUE if the
editor should exit immediately (in which case CleanUp is called from
the startup code), and FALSE otherwise. Always returning FALSE is
probably the correct behavior.
Note that the Defaults, Undo, LoadFile and SaveFile cannot depend on
window being open, and should check to see if it is NULL before trying
to use it. If it is open, the gadgets will be in place, and should be
updated/referenced as needed by all function. In particular,
GT_SetGadgetAttrs should be called to change the values of these
objects, and the value should be read from text/integer gadgets before
saving it, as it is possible for the user to change them without your
function being called.
Prefs.c provides the following externals to your preferences editor:
extern struct Window *window ; /* The editor window */
extern USHORT __far BusyPointerData[] ; /* A 2.0 busy wait pointer */
extern void dowbmessage(char *) ; /* Error reporting routine */
See /source/config/guard.c for an example of using these interface.