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

  1. /***************************************************************************\
  2. * BOUNCE.C - An example Desktop Screen Saver extension by John Ridges
  3. *            Converted to a 32-Bit Screen Blanker module by Peter Wansch
  4. \***************************************************************************/
  5.  
  6. #define MAXBITMAPS 25   /* How many happy faces can be on the screen */
  7.  
  8. #define INCL_DOSMEMMGR
  9. #define INCL_DOSPROCESS
  10. #define INCL_GPIBITMAPS
  11. #define INCL_WINBUTTONS
  12. #define INCL_WINDIALOGS
  13. #define INCL_WINENTRYFIELDS
  14. #define INCL_WININPUT
  15. #define INCL_WINMESSAGEMGR
  16. #define INCL_WINTIMER
  17. #define INCL_WINWINDOWMGR
  18. #define INCL_WINSHELLDATA
  19.  
  20. #include <os2.h>
  21.  
  22. typedef struct {
  23.   HAB habBlanker;
  24.   HWND hwndScreen;
  25.   RECTL rclScreen;
  26.   BOOL fClose;
  27.   HMODULE hmodBlanker;
  28. } BLANKERBLOCK;
  29.  
  30. typedef BLANKERBLOCK *PBLANKERBLOCK;
  31.  
  32. int rand();
  33. void srand(unsigned int seed);
  34. PCHAR pchStatus(PBLANKERBLOCK, PBOOL);
  35. MRESULT EXPENTRY dpBlanker(HWND, ULONG, MPARAM, MPARAM);
  36. VOID vdBlankerThread(VOID);
  37.  
  38. static PBLANKERBLOCK pBlankerBlock;
  39.  
  40. /*
  41.    This is the record that describes the position and velocity of
  42.    a happy face
  43. */
  44.  
  45. typedef struct {
  46.   FIXED xvelocity,yvelocity;
  47.   FIXED xposition,yposition;
  48. } BITMAPREC;
  49.  
  50. /*
  51.   This is the record that contains the options of the screen saver.
  52.   These options are kept in the OS2.INI profile file.
  53. */
  54.  
  55. typedef struct {
  56.   BOOL enabled;   /* The screen saver enabled status */
  57.   int numbitmaps;   /* The number of happy faces on the screen */
  58. } PROFILEREC;
  59.  
  60. static char name[] = "Bounce";  /* The name of this screen saver */
  61. static BOOL gotprofile = FALSE;  /* Indicates that we've read the profile */
  62. static PROFILEREC profile = {TRUE, 4};   /* Default values */
  63.  
  64. static unsigned int __rand = 1;
  65. int rand()
  66. {
  67.   __rand = __rand * 69069 + 5;
  68.   return ((__rand >> 16) & 0x7fff);
  69. }
  70. void srand(unsigned int seed)
  71. {
  72.   __rand = seed;
  73. }
  74.  
  75. PCHAR pchStatus(PBLANKERBLOCK initptr, PBOOL enabledptr)
  76. {
  77.   ULONG i;
  78.  
  79.   /* Save the SAVERBLOCK address locally */
  80.   pBlankerBlock = initptr;
  81.  
  82.   /* Read the profile (but only once!) */
  83.   if (!gotprofile) {
  84.     i = sizeof(PROFILEREC);
  85.     PrfQueryProfileData(HINI_PROFILE,"Blanker",name,&profile,&i);
  86.     gotprofile = TRUE;
  87.   }
  88.   /* Return the enabled status */
  89.   *enabledptr = profile.enabled;
  90.  
  91.   /* Return the screen saver name */
  92.   return name;
  93. }
  94.  
  95. MRESULT EXPENTRY dpBlanker(HWND hwnd, ULONG message, MPARAM mp1, MPARAM mp2)
  96. {
  97.   SHORT i;
  98.  
  99.   switch(message) {
  100.   case WM_INITDLG:
  101.     /* Check the enabled button if enabled */
  102.     if (profile.enabled)
  103.       WinSendDlgItemMsg(hwnd,3,BM_SETCHECK,MPFROMSHORT(1),0);
  104.  
  105.     /* Set the Quantity field */
  106.     WinSetDlgItemShort(hwnd,4,profile.numbitmaps,TRUE);
  107.  
  108.     /* Bring up the dialog */
  109.     WinShowWindow(hwnd,TRUE);
  110.     return FALSE;
  111.  
  112.   case WM_COMMAND:
  113.     /* If OK is pushed */
  114.     if (SHORT1FROMMP(mp1) == 1) {
  115.       /* Get the value of the Quantity field */
  116.       WinQueryDlgItemShort(hwnd,4,&i,TRUE);
  117.  
  118.       /* Check to see if the Quantity is in bounds */
  119.       if (i < 1 || i > MAXBITMAPS) {
  120.         /* Bring up an error message box */
  121.         WinMessageBox(HWND_DESKTOP,hwnd,"The number of happy faces must "
  122.           "be between 1 and 25",NULL,0,MB_OK|MB_ICONHAND);
  123.  
  124.         /* Hilight the Quantity field */
  125.         WinSendDlgItemMsg(hwnd,4,EM_SETSEL,MPFROM2SHORT(0,
  126.           WinQueryDlgItemTextLength(hwnd,4)),0);
  127.  
  128.         /* Give the Quantity field the focus */
  129.         WinSetFocus(HWND_DESKTOP,WinWindowFromID(hwnd,4));
  130.  
  131.         /* Don't exit the dialog */
  132.         return FALSE;
  133.       }
  134.       /* Save the number of happy faces */
  135.       profile.numbitmaps = i;
  136.  
  137.       /* Get the enabled status */
  138.       profile.enabled =
  139.         SHORT1FROMMR(WinSendDlgItemMsg(hwnd,3,BM_QUERYCHECK,0,0));
  140.  
  141.       /* Write the profile data */
  142.       PrfWriteProfileData(HINI_PROFILE,"Blanker",name,&profile,
  143.         sizeof(PROFILEREC));
  144.     }
  145.   }
  146.   return WinDefDlgProc(hwnd,message,mp1,mp2);
  147. }
  148.  
  149. VOID vdBlankerThread(VOID)
  150. {
  151.   HAB hab;
  152.   HPS hps;
  153.   int i;
  154.   FIXED tempx,tempy;
  155.   ULONG sqrt;
  156.   POINTL aptl[4];
  157.   BITMAPREC *bitmaps;
  158.   HBITMAP hbmp;
  159.  
  160.   /* Get an HAB for this thread (since we make PM calls) */
  161.   hab = WinInitialize(0);
  162.  
  163.   /* Get an HPS of the screen */
  164.   hps = WinGetPS(pBlankerBlock->hwndScreen);
  165.  
  166.   /* Paint the screen black */
  167.   WinFillRect(hps,&pBlankerBlock->rclScreen,CLR_BLACK);
  168.  
  169.   /* Get memory for the array of BITMAPRECs */
  170.         bitmaps = NULL;
  171.         DosAllocMem((PPVOID)&bitmaps, sizeof(BITMAPREC)*profile.numbitmaps, PAG_READ | PAG_WRITE | PAG_COMMIT);
  172.  
  173.   /* Flag all the happy faces as 'position unknown' */
  174.   for (i = 0; i < profile.numbitmaps; i++) 
  175.           bitmaps[i].xposition = -1L;
  176.  
  177.   /* Get the handle to the happy face and its dimensions */
  178.   hbmp = GpiLoadBitmap(hps,pBlankerBlock->hmodBlanker,1,0L,0L);
  179.   aptl[2].x = aptl[2].y = 0;
  180.   aptl[3].x = aptl[3].y = 34;
  181.  
  182.   /* Randomize RAND using the time */
  183.   srand((unsigned int)WinGetCurrentTime(hab));
  184.  
  185.   /* Loop until Screen Blanker tells us to stop */
  186.   while (!pBlankerBlock->fClose)
  187.  
  188.     /* Process for each happy face */
  189.     for (i = 0; i < profile.numbitmaps; i++) {
  190.  
  191.     /* If the happy face's position is unknown, initialize it */
  192.     if (bitmaps[i].xposition < 0) {
  193.  
  194.       /* Pick a random x velocity between -1 and 1 (fixed) */
  195.       tempx = (long)rand()<<1;
  196.       bitmaps[i].xvelocity = rand()&1 ? tempx : -tempx;
  197.  
  198.       /*
  199.         Make the total velocity 1 by computing:
  200.         yvelocity = sqrt(1 - xvelocity * xvelocity)
  201.       */
  202.       tempy = MAKEFIXED(0,65535)-((ULONG)tempx*(ULONG)tempx>>16);
  203.  
  204.       /* Cheesy sqrt routine to avoid linking in floating point */
  205.       sqrt = 0;
  206.       tempx = 1L<<15;
  207.       do {
  208.         sqrt ^= tempx;
  209.         if (sqrt*sqrt>>16 > (ULONG)tempy) sqrt ^= tempx;
  210.         tempx >>= 1;
  211.       } while (tempx);
  212.  
  213.       /* Randomly set y velocity sign */
  214.       bitmaps[i].yvelocity = rand()&1 ? sqrt : -sqrt;
  215.  
  216.       /* Randomly choose the x and y position of the happy face */
  217.       tempx = MAKEFIXED(pBlankerBlock->rclScreen.xLeft,0)+(rand()*
  218.         (pBlankerBlock->rclScreen.xRight-pBlankerBlock->rclScreen.xLeft-32)<<1);
  219.       tempy = MAKEFIXED(pBlankerBlock->rclScreen.yBottom,0)+(rand()*
  220.         (pBlankerBlock->rclScreen.yTop-pBlankerBlock->rclScreen.yBottom-32)<<1);
  221.     }
  222.     else {
  223.       /* Find the new position of the happy face */
  224.       tempx = bitmaps[i].xposition+bitmaps[i].xvelocity;
  225.       tempy = bitmaps[i].yposition+bitmaps[i].yvelocity;
  226.  
  227.       /* See if the happy face has hit an edge of the screen */
  228.       if (FIXEDINT(tempx) < (int)pBlankerBlock->rclScreen.xLeft) {
  229.  
  230.         /* Bounced off the left edge */
  231.         tempx = (pBlankerBlock->rclScreen.xLeft<<17)-tempx;
  232.         bitmaps[i].xvelocity = -bitmaps[i].xvelocity;
  233.       }
  234.       else if (FIXEDINT(tempx) >= (int)pBlankerBlock->rclScreen.xRight-32) {
  235.  
  236.         /* Bounced off the right edge */
  237.         tempx = (pBlankerBlock->rclScreen.xRight-32<<17)-tempx;
  238.         bitmaps[i].xvelocity = -bitmaps[i].xvelocity;
  239.       }
  240.       if (FIXEDINT(tempy) < (int)pBlankerBlock->rclScreen.yBottom) {
  241.  
  242.         /* Bounced off the bottom edge */
  243.         tempy = (pBlankerBlock->rclScreen.yBottom<<17)-tempy;
  244.         bitmaps[i].yvelocity = -bitmaps[i].yvelocity;
  245.       }
  246.       else if (FIXEDINT(tempy) >= (int)pBlankerBlock->rclScreen.yTop-32) {
  247.  
  248.         /* Bounced off the top edge */
  249.         tempy = (pBlankerBlock->rclScreen.yTop-32<<17)-tempy;
  250.         bitmaps[i].yvelocity = -bitmaps[i].yvelocity;
  251.       }
  252.     }
  253.     /* Draw the happy face in the new position */
  254.     aptl[0].x = FIXEDINT(tempx)-1;
  255.     aptl[0].y = FIXEDINT(tempy)-1;
  256.     aptl[1].x = FIXEDINT(tempx)+32;
  257.     aptl[1].y = FIXEDINT(tempy)+32;
  258.     GpiWCBitBlt(hps,hbmp,4L,aptl,ROP_SRCCOPY,BBO_IGNORE);
  259.  
  260.     /* Save the position of the happy face */
  261.     bitmaps[i].xposition = tempx;
  262.     bitmaps[i].yposition = tempy;
  263.   }
  264.   /* Release the happy face bitmap */
  265.   GpiDeleteBitmap(hbmp);
  266.  
  267.   /* Release the memory for the array of BITMAPRECs */
  268.   DosFreeMem(bitmaps);
  269.  
  270.   /* Release the HPS of the screen */
  271.   WinReleasePS(hps);
  272.  
  273.   /* Get rid of the HAB */
  274.   WinTerminate(hab);
  275.  
  276.   /* Make sure the stack doesn't vanish before we're completely gone */
  277.   DosEnterCritSec();
  278.  
  279.   /* Tell Screen Blanker that we're gone */
  280.  
  281.   pBlankerBlock->fClose = FALSE;
  282. }
  283.