home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / EXTANI.ZIP / HAPPY.C < prev    next >
C/C++ Source or Header  |  1990-04-22  |  8KB  |  260 lines

  1. /***************************************************************************\
  2. * HAPPY.C - An example animated desktop extension by John Ridges
  3. \***************************************************************************/
  4.  
  5. #define NUMBEROFPOINTERS 5   /* How many happy faces on the screen */
  6. #define SPEED 3              /* How many pels a happy face moves each turn */
  7.  
  8. #define INCL_DOSMEMMGR
  9. #define INCL_DOSPROCESS
  10. #define INCL_DOSSEMAPHORES
  11. #define INCL_WINDIALOGS
  12. #define INCL_WINMESSAGEMGR
  13. #define INCL_WINPOINTERS
  14. #define INCL_WINSYS
  15. #define INCL_WINTIMER
  16. #define INCL_WINWINDOWMGR
  17.  
  18. #include <os2.h>
  19. #include <stdlib.h>   /* Needed because SRAND and RAND are called */
  20.  
  21. typedef struct {
  22.     HAB animatehab;
  23.     HPS shadowhps;
  24.     HWND screenhwnd;
  25.     RECTL screenrectl;
  26.     ULONG hpssemaphore;
  27.     ULONG volatile closesemaphore;
  28.     HMODULE thismodule;
  29.     BOOL (far pascal *screenvisible)(void);
  30. } INITBLOCK;
  31.  
  32. char far pascal _loadds animatename(void);
  33. BOOL far pascal _loadds animateinit(INITBLOCK far *);
  34. void far pascal _loadds animatechar(char);
  35. void far pascal _loadds animatedblclk(MPARAM);
  36. void far pascal _loadds animatepaint(HPS, RECTL far *);
  37. void far pascal _loadds animateclose(void);
  38. void far pascal _loadds animatethread(void);
  39.  
  40. static INITBLOCK far *init;
  41.  
  42. /*
  43.    This is the record that describes the position and velocity of
  44.    a happy face
  45. */
  46. typedef struct {
  47.     FIXED xvelocity,yvelocity;
  48.     FIXED xposition,yposition;
  49.     BOOL invert;
  50. } POINTERREC;
  51.  
  52. static SEL pointersel;                     /* Selector for the array of POINTERRECs */
  53. static HPOINTER hptr;                      /* Handle of the happy face pointer */
  54. static POINTERREC volatile far *pointers;  /* Address of the array of POINTERRECs */
  55. static BOOL volatile invert = FALSE;       /* The 'invert the faces' flag */
  56.  
  57. char far pascal _loadds animatename()
  58. {
  59.     return 'H';   /* Tell ANIMATE that we are H for Happy face */
  60. }
  61.  
  62. BOOL far pascal _loadds animateinit(initptr)
  63. INITBLOCK far *initptr;
  64. {
  65.     int i;
  66.  
  67.     init = initptr;   /* Save the INITBLOCK address locally */
  68.  
  69.     /* Get memory for the array of POINTERRECs */
  70.     DosAllocSeg(sizeof(POINTERREC)*NUMBEROFPOINTERS,&pointersel,SEG_NONSHARED);
  71.     pointers = MAKEP(pointersel,0);
  72.  
  73.     /* Flag all the happy faces as 'position unknown' */
  74.     for (i = 0; i < NUMBEROFPOINTERS; i++) pointers[i].xposition = -1L;
  75.  
  76.     /* Get the handle to the happy face */
  77.     hptr = WinLoadPointer(HWND_DESKTOP,init->thismodule,1);
  78.  
  79.     /* Tell ANIMATE that we won't be using the shadow hps */
  80.     return FALSE;
  81. }
  82.  
  83. void far pascal _loadds animatechar(c)
  84. char c;
  85. {
  86.     int i;
  87.     
  88.     switch (c) {
  89.     case 'i':
  90.     case 'I':
  91.         invert = !invert;   /* Change the 'invert the faces' flag */
  92.         break;
  93.     case 'r':
  94.     case 'R':
  95.         /* Reverse direction of all the happy faces */
  96.         for (i = 0; i < NUMBEROFPOINTERS; i++) {
  97.             pointers[i].xvelocity = -pointers[i].xvelocity;
  98.             pointers[i].yvelocity = -pointers[i].yvelocity;
  99.         }
  100.         break;
  101.     }
  102. }
  103.     
  104. void far pascal _loadds animatedblclk(mp1)
  105. MPARAM mp1;
  106. {
  107.     mp1;   /* Reference the argument so we don't get compiler warnings */
  108.  
  109.     WinMessageBox(HWND_DESKTOP,HWND_DESKTOP,
  110.         "Happy faces example animated desktop extension.\n\n"
  111.         "When the desktop has the focus, use 'I' to invert the happy faces "
  112.         "and 'R' to reverse their direction.\n\nBy John Ridges",
  113.         "ANIMATE",0,MB_OK|MB_NOICON);
  114. }
  115.  
  116. void far pascal _loadds animatepaint(hps,prclpaint)
  117. HPS hps;
  118. RECTL far *prclpaint;
  119. {
  120.     int i;
  121.  
  122.     /* Paint the screen with the background color */
  123.     WinFillRect(hps,prclpaint,SYSCLR_BACKGROUND);
  124.  
  125.     /* Redraw all the happy faces with known positions */
  126.     for (i = 0; i < NUMBEROFPOINTERS; i++) if (pointers[i].xposition >= 0)
  127.         WinDrawPointer(hps,FIXEDINT(pointers[i].xposition),
  128.             FIXEDINT(pointers[i].yposition),hptr,
  129.             pointers[i].invert ? DP_INVERTED : DP_NORMAL);
  130. }
  131.  
  132. void far pascal _loadds animateclose()
  133. {
  134.     /* Release the memory for the array of POINTERRECs */
  135.     DosFreeSeg(pointersel);
  136. }
  137.  
  138. void far pascal _loadds animatethread()
  139. {
  140.     HAB hab;
  141.     HPS hps;
  142.     int i;
  143.     FIXED tempx,tempy;
  144.     ULONG sqrt;
  145.  
  146.     /* Get an HAB for this thread (since we make PM calls) */
  147.     hab = WinInitialize(0);
  148.  
  149.     /* Randomize RAND using the time */
  150.     srand((unsigned int)WinGetCurrentTime(hab));
  151.  
  152.     /* Tell ANIMATE that we are done initializing and painting may proceed */
  153.     WinPostMsg(init->screenhwnd,WM_USER,0,0);
  154.  
  155.     /* Loop until ANIMATE tells us to stop */
  156.     while (!init->closesemaphore)
  157.  
  158.         /* Don't do anything if the screen is not visible */
  159.         if ((init->screenvisible)()) {
  160.  
  161.         /* Enter the critical section so we can get an HPS of the screen */
  162.         DosSemRequest(&init->hpssemaphore,SEM_INDEFINITE_WAIT);
  163.         hps = WinGetPS(init->screenhwnd);
  164.  
  165.         /* Process for each happy face */
  166.         for (i = 0; i < NUMBEROFPOINTERS; i++) {
  167.  
  168.             /* If the happy face's position is unknown, initialize it */
  169.             if (pointers[i].xposition < 0) {
  170.  
  171.                 /* Pick a random x velocity between -1 and 1 (fixed) */
  172.                 tempx = (long)rand()<<1;
  173.                 pointers[i].xvelocity = rand()&1 ? tempx : -tempx;
  174.  
  175.                 /*
  176.                    Make the total velocity 1 by computing:
  177.                    yvelocity = sqrt(1 - xvelocity * xvelocity)
  178.                 */
  179.                 tempy = MAKEFIXED(0,65535)-((ULONG)tempx*(ULONG)tempx>>16);
  180.  
  181.                 /* Cheesy sqrt routine to avoid linking in floating point */
  182.                 sqrt = 0;
  183.                 tempx = 1L<<15;
  184.                 do {
  185.                     sqrt ^= tempx;
  186.                     if (sqrt*sqrt>>16 > (ULONG)tempy) sqrt ^= tempx;
  187.                     tempx >>= 1;
  188.                 } while (tempx);
  189.  
  190.                 /* Randomly set y velocity sign */
  191.                 pointers[i].yvelocity = rand()&1 ? sqrt : -sqrt;
  192.  
  193.                 /* Multiply the velocities by the requested speed */
  194.                 pointers[i].xvelocity *= SPEED;
  195.                 pointers[i].yvelocity *= SPEED;
  196.  
  197.                 /* Randomly choose the x and y position of the happy face */
  198.                 tempx = MAKEFIXED(init->screenrectl.xLeft,0)+(rand()*
  199.                     (init->screenrectl.xRight-init->screenrectl.xLeft-32)<<1);
  200.                 tempy = MAKEFIXED(init->screenrectl.yBottom,0)+(rand()*
  201.                     (init->screenrectl.yTop-init->screenrectl.yBottom-32)<<1);
  202.             }
  203.             else {
  204.                 /* Find the new position of the happy face */
  205.                 tempx = pointers[i].xposition+pointers[i].xvelocity;
  206.                 tempy = pointers[i].yposition+pointers[i].yvelocity;
  207.  
  208.                 /* See if the happy face has hit an edge of the screen */
  209.                 if (FIXEDINT(tempx) < (int)init->screenrectl.xLeft) {
  210.  
  211.                     /* Bounced off the left edge */
  212.                     tempx = (init->screenrectl.xLeft<<17)-tempx;
  213.                     pointers[i].xvelocity = -pointers[i].xvelocity;
  214.                 }
  215.                 else if (FIXEDINT(tempx) > (int)init->screenrectl.xRight-32) {
  216.  
  217.                     /* Bounced off the right edge */
  218.                     tempx = (init->screenrectl.xRight-32<<17)-tempx;
  219.                     pointers[i].xvelocity = -pointers[i].xvelocity;
  220.                 }
  221.                 if (FIXEDINT(tempy) < (int)init->screenrectl.yBottom) {
  222.  
  223.                     /* Bounced off the bottom edge */
  224.                     tempy = (init->screenrectl.yBottom<<17)-tempy;
  225.                     pointers[i].yvelocity = -pointers[i].yvelocity;
  226.                 }
  227.                 else if (FIXEDINT(tempy) >= (int)init->screenrectl.yTop-32) {
  228.  
  229.                     /* Bounced off the top edge */
  230.                     tempy = (init->screenrectl.yTop-32<<17)-tempy;
  231.                     pointers[i].yvelocity = -pointers[i].yvelocity;
  232.                 }
  233.                 /* Undraw the happy face in the old position */
  234.                 WinDrawPointer(hps,FIXEDINT(pointers[i].xposition),
  235.                     FIXEDINT(pointers[i].yposition),hptr,
  236.                     pointers[i].invert ? DP_INVERTED : DP_NORMAL);
  237.             }
  238.             /* Draw the happy face in the new position */
  239.             WinDrawPointer(hps,FIXEDINT(tempx),FIXEDINT(tempy),hptr,
  240.                 invert ? DP_INVERTED : DP_NORMAL);
  241.  
  242.             /* Save the position and invert value of the happy face */
  243.             pointers[i].xposition = tempx;
  244.             pointers[i].yposition = tempy;
  245.             pointers[i].invert = invert;
  246.         }
  247.         /* Release the HPS of the screen and leave the critical section */
  248.         WinReleasePS(hps);
  249.         DosSemClear(&init->hpssemaphore);
  250.     }
  251.     /* We've been told to close, so get rid of the HAB */
  252.     WinTerminate(hab);
  253.  
  254.     /* Make sure the stack doesn't vanish before we're completely gone */
  255.     DosEnterCritSec();
  256.  
  257.     /* Tell ANIMATE that we're gone */
  258.     DosSemClear((HSEM)&init->closesemaphore);
  259. }
  260.