home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 17 / CD_ASCQ_17_101194.iso / vrac_os2 / blankr42.zip / BSSDEV.ZIP / bssdev.doc < prev    next >
Text File  |  1994-08-17  |  9KB  |  310 lines

  1. Instructions for writing External Screen Blanker Modules
  2.  
  3. Screen Blanker modules are the 32-Bit counterpart of Deskpic
  4. modules. 
  5.  
  6. What do you need to write an external Screen Blanker module? 
  7. Well, a pretty good working knowledge of Presentation Manager 
  8. wouldn't hurt. These instructions will attempt to tell you how 
  9. to write a module, but they won't tell you how to program
  10. in PM. To help, an example extension is provided and is a good place
  11. to start. When I write a new extension, I usually use 'BOUNCE' as a
  12. framework and go from there.
  13.  
  14. An external Screen Blanker module is a Dynamic Link Library that contains
  15. three functions and has the file extension of '.BBS' instead of '.DLL'.
  16. The three functions must be exported with the following ordinals:
  17.  
  18.    pchStatus       @1
  19.    dpBlanker       @2
  20.    vdBlankerThread @3
  21.  
  22. The three functions are specified by the following function prototypes:
  23.  
  24.    PCHAR pchStatus(PBLANKERBLOCK, PBOOL);
  25.    MRESULT EXPENTRY dpBlanker(HWND, ULONG, MPARAM, MPARAM);
  26.    VOID vdBlankerThread(VOID);
  27.  
  28. And the structure BLANKERBLOCK is defined as follows:
  29.  
  30.    typedef struct {
  31.       HAB habBlanker;
  32.       HWND hwndScreen;
  33.       RECTL rclScreen;
  34.       BOOL fClose;
  35.       HMODULE hmodBlanker;
  36.    } BLANKERBLOCK;
  37.  
  38.    typedef BLANKERBLOCK *PBLANKERBLOCK;
  39.  
  40.  
  41. The BLANKERBLOCK structure is how Screen Blanker provides the module with
  42. information about its environment. The fields have the following meaning:
  43.  
  44. 'habBlanker' is the handle of the Screen Blanker program's Anchor Block. This may
  45.    be needed by some OS/2 functions.
  46. 'hwndScreen' is the handle of the screen saver window. This will be needed
  47.    by 'vdBlankerThread' to get a Presentation Space to draw into.
  48. 'rclScreen' is the coordinates of the screen saver window.
  49. 'fClose' is a flag that is used by 'vdBlankerThread' to
  50.    determine when to stop.
  51. 'hModBlanker' is the module handle of the Screen Blanker module.
  52.    This will be needed to access any local resources.
  53.  
  54. The values of 'habBlanker' and 'hModBlanker' are always valid, but the values
  55. of 'hwndScreen', 'rclScreen', and 'fClose' are only valid during
  56. the execution of 'vdBlankerThread'.
  57.  
  58.  
  59. pchStatus
  60.  
  61. This function is called by Screen Blanker to get the name of the screen saver.
  62. Screen Blanker passes a pointer to a BLANKERBLOCK structure, and a pointer to a
  63. BOOL. The function should save the pointer to the BLANKERBLOCK structure in
  64. global memory so that it can be accessed by the other two functions. The
  65. function should also indicate whether the screen saver is enabled by setting
  66. the BOOL to TRUE if enabled, and FALSE if disabled. When finished, the
  67. function should return a pointer to a zero terminated string which is the
  68. name of the Screen Blanker module, or NULL if the screen saver has
  69. no name. Note that while Screen Blanker will call this function before calling the
  70. other two, it may call this function multiple times. 
  71.  
  72.  
  73. dpBlanker
  74.  
  75. This is a dialog procedure for the dialog that Screen Blanker will invoke when
  76. the user chooses this screen saver module from the list of External modules. 
  77. The dialog should allow the user to modify any parameters that
  78. the screen saver may have. The dialog template should be part of the
  79. resources of the screen saver module and should have a dialog
  80. template ID of 42. If 'pchStatus' returns NULL instead of a screen saver
  81. name, the dialog will never be invoked.
  82.  
  83.  
  84. vdBlankerThread
  85.  
  86. This procedure will be started as a separate thread when Screen Blanker invokes
  87. the screen saver. The procedure should clear the screen and then display
  88. whatever graphics the screen saver employs until 'fClose' in the
  89. BLANKERBLOCK structure becomes non-zero. When 'fClose' becomes
  90. non-zero, the procedure should release any resources it might have, enter
  91. a critical section using 'DosEnterCritSec', set 'fClose' to FALSE, 
  92. and exit (in that order). It is important that the procedure
  93. respond quickly to 'fClose' becoming TRUE so that users will
  94. not be delayed by the screen saver. The procedure should also get its own
  95. Anchor Block, since threads shouldn't make calls to the PM API without one.
  96. Note that stack space is limited, so any sizeable memory needed should be
  97. allocated at run time.
  98.  
  99. That completes the explanation. Where the instructions are a little sketchy,
  100. use the example source code to see at least one way of doing it. 
  101.  
  102. Please avoid statically linking the C library where possible to reduce the
  103. size of the .BSS file. Whenever possible use the following function replacements
  104. (like in BOUNCE.C):
  105.  
  106. /*
  107.   minirtl.c
  108.   mini run time library for use with
  109.   ScreenSaver modules with Borland C++
  110. */
  111. #define INCL_DOS
  112. #define INCL_WIN
  113. #include <os2.h>
  114. #include <string.h>
  115. #include <malloc.h>
  116. #include <memory.h>
  117. #include <process.h>
  118.  
  119. /*
  120.   this part of the file was taken from emx 0.8g
  121.   -- Copyright (c) 1990-1993 by Eberhard Mattes
  122. */
  123.  
  124. void *memcpy (void *s1, const void *s2, size_t n)
  125. {
  126.   size_t i;
  127.  
  128.   for (i = 0; i < n; ++i)
  129.     ((char *)s1)[i] = ((char *)s2)[i];
  130.   return (s1);
  131. }
  132. void *memset (void *s, int c, size_t n)
  133. {
  134.   size_t i;
  135.   for (i = 0; i < n; ++i)
  136.     ((char *)s)[i] = (char)c;
  137.   return (s);
  138. }
  139. char *strcat (char *string1, const char *string2)
  140. {
  141.   char *dst;
  142.   dst = string1;
  143.   while (*dst != 0)
  144.     ++dst;
  145.   while ((*dst = *string2) != 0)
  146.     ++dst, ++string2;
  147.   return (string1);
  148. }
  149. char  *strcpy (char *string1, const char *string2)
  150. {
  151.   char *dst;
  152.   dst = string1;
  153.   while ((*dst = *string2) != 0)
  154.     ++dst, ++string2;
  155.   return (string1);
  156. }
  157. size_t  strlen (const char *string)
  158. {
  159.   size_t i;
  160.   i = 0;
  161.   while (string[i] != 0) ++i;
  162.   return (i);
  163. }
  164.  
  165. static unsigned int __rand = 1;
  166. int  rand()
  167. {
  168.   __rand = __rand * 69069 + 5;
  169.   return ((__rand >> 16) & 0x7fff);
  170. }
  171. void  srand(unsigned int seed)
  172. {
  173.   __rand = seed;
  174. }
  175.  
  176. /*
  177.   the remainder of the file is
  178.   (C) 1993-94 Siegfried Hanisch
  179. */
  180.  
  181. // if 1MB is not enough, increase this value
  182. // the memory is not commited, so it does not use physical memory
  183. // until it is accessed
  184. #define MEMPOOLSIZE    (1024L*1024L)
  185. static  void  *mempool = NULL;
  186.  
  187. void  *calloc(size_t elements, size_t size)
  188. {
  189.   return malloc(elements*size);
  190. }
  191.  
  192. void  *malloc(size_t size)
  193. {
  194.   APIRET  rc;
  195.   size_t  *mem;
  196.   rc = DosSubAllocMem(mempool, (PVOID *)&mem, size+sizeof(size_t));
  197.   if(rc){
  198.     WinAlarm(HWND_DESKTOP, WA_ERROR);
  199.     return NULL;
  200.   }
  201.   mem[0] = size;
  202.   return (void *)(&mem[1]);
  203. }
  204.  
  205. void  free(void *mem)
  206. {
  207.   APIRET  rc;
  208.   size_t  *m;
  209.   m = (size_t *)mem;
  210.   rc = DosSubFreeMem(mempool, &m[-1], m[-1]+sizeof(size_t));
  211.   if(rc){
  212.     WinAlarm(HWND_DESKTOP, WA_ERROR);
  213.   }
  214. }
  215.  
  216. void  *realloc(void *mem, size_t size)
  217. {
  218.   void  *new_mem;
  219.   size_t  *m;
  220.   size_t  old_size;
  221.   m = (size_t *)mem;
  222.   old_size = m[-1];
  223.  
  224.   new_mem = malloc(size);
  225.   memcpy(new_mem, mem, old_size);
  226.   memset(((char *)new_mem)+old_size, 0 , size-old_size);
  227.   free(mem);
  228.   return new_mem;
  229. }
  230.  
  231. char  *strdup(const char *string)
  232. {
  233.   return strcpy(malloc(strlen(string)+1), string);
  234. }
  235.  
  236. BOOL  alloc_heap()
  237. {
  238.   APIRET  rc;
  239.   rc = DosAllocMem((PVOID *)&mempool, MEMPOOLSIZE, PAG_READ|PAG_WRITE);
  240.   if(rc){
  241.     WinAlarm(HWND_DESKTOP, WA_ERROR);
  242.     mempool = NULL;
  243.     return FALSE;
  244.   }
  245.  
  246.   rc = DosSubSetMem(mempool, DOSSUB_INIT|DOSSUB_SPARSE_OBJ, MEMPOOLSIZE);
  247.   if(rc){
  248.     DosFreeMem(mempool);
  249.     WinAlarm(HWND_DESKTOP, WA_ERROR);
  250.     return FALSE;
  251.   }
  252.   return TRUE;
  253. }
  254.  
  255. void  free_heap()
  256. {
  257.   APIRET  rc;
  258.   rc = DosSubUnsetMem(mempool);
  259.   if(rc){
  260.     WinAlarm(HWND_DESKTOP, WA_ERROR);
  261.   }
  262.   rc = DosFreeMem(mempool);
  263.   if(rc){
  264.     WinAlarm(HWND_DESKTOP, WA_ERROR);
  265.   }
  266. }
  267.  
  268. #if defined(__BORLANDC__)
  269. int _beginthread(void (_USERENTRY *__start)(void *), unsigned __stksize, void *__arg)
  270. {
  271.   TID  tid;
  272.   if(DosCreateThread(&tid, (PFNTHREAD)__start, (ULONG)__arg, 2L, __stksize) != 0)
  273.     return -1;
  274.   return tid;
  275. }
  276.  
  277. void  _endthread(void)
  278. {
  279.   DosExit(EXIT_THREAD, 0);
  280. }
  281. #elif defined(__IBMC__)
  282. int  _Optlink beginthread( void(* _Optlink __thread)(void *),
  283.   void *stack, unsigned stack_size, void *arg_list);
  284. {
  285.   TID  tid;
  286.   if(DosCreateThread(&tid, (PFNTHREAD)__thread, (ULONG)arg_list, 2L, stack_size) != 0)
  287.     return -1;
  288.   return tid;
  289. }
  290.  
  291. void  _endthread()
  292. {
  293.   DosExit(EXIT_THREAD, 0);
  294. }
  295. #elif defined(__EMX__)
  296. int  _beginthread(void (*start)(void *arg), void *stack,
  297.   unsigned stack_size, void *arg_list)
  298. {
  299.   TID  tid;
  300.   if(DosCreateThread(&tid, (PFNTHREAD)start, (ULONG)arg_list, 2L, stack_size) != 0)
  301.     return -1;
  302.   return tid;
  303. }
  304.  
  305. void  _endthread()
  306. {
  307.   DosExit(EXIT_THREAD, 0);
  308. }
  309. #endif
  310.