home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / screen / shdwmstr.lha / docs / Programmers < prev    next >
Text File  |  1992-01-20  |  8KB  |  159 lines

  1. How to build a shadowmaster module.
  2.  
  3.  
  4. *** Quick Start for SAS C programmers:
  5.  
  6. Doing a graphics module is relatively easy. Copy the
  7. "source/savers/black.c" source to the name you've chosen, change the
  8. colorspec, Title, Screen and Window tags as appropriate, and then put
  9. your graphics code in the routine "dographics". Dographics is called
  10. with screen and window opened as you specified, and the raster set to
  11. color 0. Build your blanker, and run it from the CLI to test it. Use
  12. CTRL-C to exit.
  13.  
  14.  
  15. A utility module is somewhat harder. Use the template
  16. "source/savers/guard.c" as a basis, replacing the template and the
  17. routine "doutility" as needed.  If you're going to do a simple utility
  18. that just starts a single blanker and then waits for the CTRL-C, your
  19. routine should just return the command string. If your utility wants
  20. to wait for other things (timeouts, etc) or wants to do something
  21. other than exit on keyboard input, you need to compile with -dLOOPS.
  22. In this case, doutility's argument is TRUE the first time after the
  23. utility is started, and you should just hand back the command string.
  24. After the command is launched, doutility is called with a FALSE
  25. argument.  It should then wait for whatever events it wishes, then
  26. return the string for the next command to be run. For either case,
  27. returning a NULL pointer will cause the utility to exit.
  28.  
  29. NOTE: Your routine (dographics or doutility) must RETURN, and not call
  30. exit.
  31.  
  32. For more information, see the source files black.c, guard.c,
  33. savermain.h and utillitymain.h in the savers directory.
  34.  
  35. If you aren't using SAS C, you can try to compile the above templates
  36. without a do routine, and then link in with an appropriate routine
  37. from your favorite language. However, it's probably better to write
  38. the interface code from scratch, using the appropriate main.h files as
  39. a guide.
  40.  
  41.  
  42. *** The Interface Specification
  43.  
  44. A saver module is told to start by being executed normally. It is told
  45. that it should stop by being sent a SIGBREAKF_CTRL_C signal. This
  46. means that doing graphics modules - that only need to do the client
  47. half of the interface - is relatively easy. Almost any command that
  48. can be run from the CLI and stopped with a CTRL-C can be used. The
  49. templates for SAS C are tweaked to be small, but that's all that is
  50. special about them.
  51.  
  52. On the server side, things are much more complicated. You can't just
  53. launch your client module, and blithely wait for the event that means
  54. they should exit and send them a CTRL-C. If they have exited
  55. beforehand, your signal could cause the system to crash. Further, your
  56. client may (for its own reasons) decide to ignore your signal, and not
  57. exit. You must not start another client until it has exited. Because of
  58. this, you need to find out when the client exits.
  59.  
  60. Fortunately, 2.0 provides a perfect facility for this. pr_ExitCode has
  61. been added to the process structure, and is run when the process
  62. exits. Unfortunately, I've not been able to get anyone at CBM to state
  63. that it's safe to send a signal at anytime before this code exits, but
  64. testing shows that the code runs with the same Task structure as is
  65. created by CreateNewProc with the tag NP_ExitCode used to set
  66. pr_ExitCode. Depending on this code to signal the exit should not
  67. create any race conditions.
  68.  
  69. The standard used in the templates is that a global variable holds a
  70. pointer to the client Task structure, and pr_ExitCode sets that
  71. pointer to NULL, then sends a signal to the server task (with a
  72. pointer in a second global) to indicate that it has exited, and the
  73. server should do whatever it feels needs to be done in that case.
  74.  
  75. Note that the Task structure pointer is accessed by multiple tasks,
  76. and is used to communicate between them. Because of the dangers
  77. inherent in misreading the value of this variable, the changes to it
  78. and the attempts to read it must be locked from mutual access. A
  79. SignalSemaphore is used for this.
  80.  
  81.  
  82. *** Configuration
  83.  
  84. The configuration sytem has two types of objects in it, utility module
  85. preferences editors, and saver module configuration programs.
  86. Configuration programs should open a window at 0,11 with the gadgets
  87. appropriate for that saver module, including a way of aborting with no
  88. exit. After the user indicates they wish to use the selected
  89. configuration, the configuration program should write a line to
  90. standard output that can be used to invoke it. Put in all keywords,
  91. and don't assume that the module will live in a specific directory. If
  92. no changes are made, don't write anything to standard output.
  93.  
  94. Utility modules all use preferences editors. The only allowable start
  95. switch is "FROM", indicating a preferences file to use other than the
  96. defaults (generally, env:shadowmaster/modulename.prefs). They should
  97. be AUISG compliant and provide appropriate facilities for selecting,
  98. configuring and testing the next module in the chain.
  99.  
  100. To make this task somewhat easier, the file source/config/prefs.c
  101. provides a "startup" module for building preferences editors. The user
  102. code must provide the following external variables, initialized to
  103. approiate values:
  104.  
  105. int windowheight ;        /* Height to open the window to */
  106. int windowwidth ;        /* Width to open the window to */
  107. char *basename ;        /* env:basename/appname.prefs */
  108. char *appname ;            /* is the default prefs file */
  109. char *errname ;            /* error reports look like errname: text */
  110.  
  111. You must also provide the following functions for prefs to call:
  112.  
  113. int SaveFile(char *) ;        /* Save current preferences to named file */
  114. int LoadFile(char *) ;        /* Load preferences from named file */
  115. int Undo(void) ;        /* Undo last action */
  116. int Defaults(void) ;        /* Reset to defaults */
  117. int UserGadgets(struct Gadget *ng,/* Add user gadgets to window */
  118.         struct NewGadget *gad) ;
  119. void CleanUp(int) ;        /* Cleans up before exit */
  120.  
  121. The Undo and Defaults return TRUE to cause an immediate exit, but
  122. should probably always return FALSE.
  123.  
  124. SaveFile and LoadFile return the success of the operation asked for.
  125.  
  126. Cleanup is passed a TRUE if the user exited with changes to the env:
  127. or envarc: preferences files, false otherwise.
  128.  
  129. UserGadets adds the editor-specific gadgets, and returns FALSE if it
  130. fails. ng is the newgadget structure used to set up the bottom row of
  131. gadgets. You can (and should) use ng_TextAttr from it, and can depend
  132. on ng_TopEdge being the top edge of the gadgets for placing your
  133. gadgets. The created gadgets should have ng_UserData set to point at
  134. int (*)(struct Gagdet *, UWORD) functions to handle the gadgets. They
  135. are called when that gadget is selected by the user, with the gadget
  136. pointed to by the first argument, and the IntuiMessage Code field as
  137. the second argument.  gad is the last gadget created on ng, for
  138. passing to CreateGadget.  These gadgets should return TRUE if the
  139. editor should exit immediately (in which case CleanUp is called from
  140. the startup code), and FALSE otherwise.  Always returning FALSE is
  141. probably the correct behavior.
  142.  
  143. Note that the Defaults, Undo, LoadFile and SaveFile cannot depend on
  144. window being open, and should check to see if it is NULL before trying
  145. to use it. If it is open, the gadgets will be in place, and should be
  146. updated/referenced as needed by all function. In particular,
  147. GT_SetGadgetAttrs should be called to change the values of these
  148. objects, and the value should be read from text/integer gadgets before
  149. saving it, as it is possible for the user to change them without your
  150. function being called.
  151.  
  152. Prefs.c provides the following externals to your preferences editor:
  153.  
  154. extern struct Window *window ;            /* The editor window */
  155. extern USHORT __far BusyPointerData[] ;        /* A 2.0 busy wait pointer */
  156. extern void dowbmessage(char *) ;        /* Error reporting routine */
  157.  
  158. See /source/config/guard.c for an example of using these interface.
  159.