home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 5 / ctrom5b.zip / ctrom5b / OS2 / SPEL / UCHESS / UCHESSRC / BOBS.C < prev    next >
Text File  |  1994-10-31  |  38KB  |  1,131 lines

  1. #include "bobs.h"
  2.  
  3. #define APPLY_PALETTE
  4.  
  5. #include <stdlib.h>
  6. #include <string.h>
  7.  
  8. // *************************************************************
  9. // Raster Object Primitives, for OS/2 PM
  10. // CopyRight (c) 1994 W. Roger Uzun
  11. // Avatar Consulting
  12. // *************************************************************
  13.  
  14.  
  15. // **************************************************
  16. // hab and hwndClient are opened and inited
  17. // by the user before calling any of these calls
  18. // CxClient and CyClient have to be set by outside and declared
  19. // outside as well
  20.  
  21. // hwndClient is the handle to the target PM window
  22. // hab is the HAB from the WinInitialize call
  23. // CxClient is the Client Windows Width
  24. // CyClient is the Client Windows Height
  25. // **************************************************
  26.  
  27. // **************************************************
  28. // Here are external data structures
  29. // the main pgm must fill these in before he calls
  30. // anything out of this C package
  31. extern int cyClient,cxClient;
  32. extern HAB hab;
  33. extern HWND hwndClient;
  34. extern int BOBHEIGHT;
  35. extern int ROW8B;
  36.  
  37. #define SQUAREWIDTH 59
  38. #define ROUNDEDSQUAREWIDTH 64
  39. #define SQUAREHEIGHT BOBHEIGHT
  40. #define COLA (16)
  41. #define COLB (16+SQUAREWIDTH)
  42. #define COLC (16+SQUAREWIDTH*2)
  43. #define COLD (16+SQUAREWIDTH*3)
  44. #define COLE (16+SQUAREWIDTH*4)
  45. #define COLF (16+SQUAREWIDTH*5)
  46. #define COLG (16+SQUAREWIDTH*6)
  47. #define COLH (16+SQUAREWIDTH*7)
  48. //#define ROW7 (ROW8-SQUAREHEIGHT)
  49. #define ROW8 (ROW8B-SQUAREHEIGHT)
  50. #define ROW7 (ROW8B-SQUAREHEIGHT*2)
  51. #define ROW6 (ROW8B-SQUAREHEIGHT*3)
  52. #define ROW5 (ROW8B-SQUAREHEIGHT*4)
  53. #define ROW4 (ROW8B-SQUAREHEIGHT*5)
  54. #define ROW3 (ROW8B-SQUAREHEIGHT*6)
  55. #define ROW2 (ROW8B-SQUAREHEIGHT*7)
  56. #define ROW1 (ROW8B-SQUAREHEIGHT*8)
  57.  
  58.  
  59. void DrawAmigaBoard(void);
  60.  
  61. // **************************************************
  62.  
  63. // **************************************************
  64. // here are internal data structures to this module
  65. HMTX DrawSemaphore; // have WM_PAINT and DrawGels go 1 at a time
  66. HDC hdcMemory,winhdc;
  67. HPS hpsMemory;
  68. HPS hwClientPS=0L; // we need to keep a PS around for the target
  69. SIZEL bobsizl;
  70. HBITMAP BackGndBitmap=NULL;
  71. UCHAR *BackGndImage;
  72. BOB *SystemBobList=NULL;
  73. int SafeBlit=1; // if BM_SRCTRANSPARENT supported, try 0
  74. int GelsInited=0;
  75. // **************************************************
  76.  
  77. // ********************************************
  78. // here are the function Prototypes
  79. // You would first open your client window, and fill in
  80. // the hab, hwndClient, CxClient, and CyClient data items
  81. // You would then call InitGels() to init the system drawing structs
  82. // You would then call CreateBob() for each Raster Object you want
  83. // to create, You then call AddBob() to add each one you want
  84. // to be drawn in the client window...
  85. // you call DrawGList() to actually Draw things
  86. // You can set SafeBlit to 1 for safe 2 part blits
  87. // if the Video supports BM_SRCTRANSPARENT blits set
  88. // SafeBlit to 0 for better blits
  89. // When you want to erase a bob from a screen for a given
  90. // frame, call EraseBob(), to remove a bob from the Drawing List
  91. // call RemBob().  To shut it all down, call RemBob() for anyone
  92. // in the list, then for every Bob created call FreeBob(),
  93. // then call CloseGels() to shut it all down.
  94. //
  95. // As far as redrawing the window when WM_PAINT msgs are
  96. // received, it is assumed that during WM_Paint >>YOU<< will
  97. // have code to Blit the background into the Client Windows
  98. // area...after that is done, You can call RepaintBobs();
  99. // to repaint all of the raster objects...
  100. // Probably a good idea to have your Client Window WM_PAINT
  101. // routine do a DosRequestMutexSem(DrawSemaphore,xxx);
  102. // and a DosReleaseMutexSem(DrawSemaphore); any time
  103. // before it starts to upset the screen, so that only
  104. // one routine at a time is drawing to the client window
  105. // PS_Space
  106. // ******************************************************
  107.  
  108. void DisplayError(char *);
  109.  
  110. BOB *CreateBob(LONG Width,LONG Height,LONG Depth,void *Image,UCHAR *Palette);
  111. int FreeBob(BOB *);
  112. void DrawGList(void);
  113.  
  114. ULONG Mono_Palette[2]={0x00000000L,
  115.                0x00ffffffL};
  116.  
  117. int InitGels(void);
  118. void AddBob(BOB *);
  119. void RemBob(BOB *);
  120. void RemBobNR(BOB *);
  121. void EraseBob(BOB *);
  122. int CloseGels(void);
  123. void TransBlit(BOB *,HPS,HPS,LONG,PPOINTL);
  124. void TransBlit2(BOB *,HPS,HPS,LONG,PPOINTL);
  125. void MakeShadowMask(void *,void *,ULONG,ULONG);
  126. void RepaintBobs(HPS); // for WM_Paint situations
  127.  
  128.  
  129.  
  130. // THIS ROUTINE ONLY WORKS WHEN WID OF IMAGE IS A MULT OF 32!!!
  131. void MakeShadowMask(s,d,wid,ht)
  132. void *s;
  133. void *d;
  134. ULONG wid,ht;
  135. {
  136.  ULONG bytecnt=0;
  137.  UBYTE  *src,*dest;
  138.  UBYTE workbyte;
  139.  ULONG rem,i,j;
  140.  UBYTE srcbyte;
  141.  
  142.  src = (UBYTE *)s;
  143.  dest = (UBYTE *)d;
  144.  
  145.  if (wid & 0x7)
  146.   return;
  147.  j = (wid & 0x1f);
  148.  rem = j >> 3; // need to pad each scanline with rem bytes
  149.  for(j=0;j<((wid*ht)/8);j++)
  150.   {
  151.    workbyte = 0;
  152.    for(i=0;i<8;i++)
  153.     {
  154.      srcbyte = *src++;
  155.      if ((srcbyte))
  156.       { // this is a 1 bit
  157.      workbyte |= 1;
  158.       }
  159.      if (i != 7)
  160.       workbyte <<= 1;
  161.      if (rem)
  162.       {
  163.        bytecnt++;
  164.        if (bytecnt == wid)
  165.     {
  166.      for(bytecnt=0;bytecnt<rem;bytecnt++)
  167.       *dest++ = 0xff;
  168.      bytecnt = 0;
  169.     }
  170.       }
  171.     }
  172.    *dest++ = workbyte;
  173.   }
  174. }
  175.  
  176. void FreeFullBitmap()
  177. {
  178.   GpiSetBitmap(hpsMemory,NULL);
  179.   GpiSetBitmap(hwClientPS,NULL);
  180.   if (BackGndBitmap != (HBITMAP)NULL)
  181.    GpiDeleteBitmap(BackGndBitmap);
  182.   BackGndBitmap = NULL;
  183. }
  184.  
  185. int LoadBMPImage(name,image,wid,ht)
  186. char *name;
  187. void *image;
  188. ULONG wid,ht;
  189. {
  190.  char errstr[48];
  191.  FILESTATUS fileinfo;
  192.  ULONG action,len,bytesread,newptr;
  193.  APIRET rc;
  194.  HFILE file;
  195.  
  196.     rc = DosOpen(name, &file, &action,4L,FILE_NORMAL,FILE_OPEN,
  197.       OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE,NULL);
  198.     if (rc)
  199.      {
  200.       sprintf(errstr,"Could open %s",name);
  201.       DisplayError(errstr);
  202.       return(0);
  203.      }
  204.     rc = DosQueryFileInfo(file,FIL_STANDARD,&fileinfo,sizeof(fileinfo));
  205.     if (rc)
  206.      {
  207.       DosClose(file);
  208.       return(0);
  209.      }
  210.     len = fileinfo.cbFile - (wid*ht);
  211.     rc = DosSetFilePtr(file,len,FILE_BEGIN,&newptr);
  212.     if (rc)
  213.      {
  214.       DisplayError("Could not set file ptr");
  215.       DosClose(file);
  216.       return(0);
  217.      }
  218.     rc = DosRead(file,image,wid*ht,&bytesread);
  219.     if ((rc)||(bytesread != wid*ht))
  220.      {
  221.       DosClose(file);
  222.       return(0);
  223.      }
  224.     DosClose(file);
  225.     return(1);
  226. }
  227.  
  228. int LoadFullBitmap(hps,name,first,Palette)
  229. HPS hps;
  230. char *name;
  231. int first;
  232. UCHAR *Palette;
  233. {
  234. #ifdef APPLY_PALETTE
  235.  static int AppliedPal=0;
  236. #endif
  237.  static int FirstTimeRun=1;
  238.  RECTL rect;
  239.  POINTL apts,apts2[4];
  240.  int i;
  241.  ULONG ImageSize;
  242.  BITMAPINFO2 *bmi2;
  243.  APIRET rc;
  244.  FILESTATUS fileinfo;
  245.  HFILE file;
  246.  ULONG bytesread;
  247.  ULONG action;
  248.  UCHAR type[4];
  249. #ifdef APPLY_PALETTE
  250.  LONG *tmpPalette;
  251. #endif
  252.  ULONG file_len,file_offset,newptr;
  253.  
  254.  if ((first == TRUE)&&(FirstTimeRun))
  255.   {
  256.     if (name == NULL)
  257.      return(0);
  258.     rc = DosOpen(name, &file, &action,4L,FILE_NORMAL,FILE_OPEN,
  259.       OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE,NULL);
  260.     if (rc)
  261.      {
  262.       return(0);
  263.      }
  264.     rc = DosRead(file,type,2L,&bytesread);
  265.     if ((rc)||(bytesread != 2))
  266.      {
  267.       DosClose(file);
  268.       return(0);
  269.      }
  270.     type[2] = 0;
  271.     if (stricmp(type,"BM"))
  272.      {
  273.       DosClose(file);
  274.       return(0);
  275.      }
  276.     rc = DosRead(file,&file_len,4L,&bytesread);
  277.     if ((rc)||(bytesread != 4))
  278.      {
  279.       DosClose(file);
  280.       return(0);
  281.      }
  282.     rc = DosRead(file,&file_offset,4L,&bytesread);
  283.     if ((rc)||(bytesread != 4))
  284.      {
  285.       DosClose(file);
  286.       return(0);
  287.      }
  288.     rc = DosQueryFileInfo(file,FIL_STANDARD,&fileinfo,sizeof(fileinfo));
  289.     if (rc)
  290.      {
  291.       DosClose(file);
  292.       return(0);
  293.      }
  294.     ImageSize = fileinfo.cbFile - file_offset;
  295.     rc = DosAllocMem((PPVOID)&BackGndImage,ImageSize,
  296.      (ULONG)(PAG_READ|PAG_WRITE|PAG_COMMIT));
  297.     if (rc)
  298.      {
  299.       DosClose(file);
  300.       return(0);
  301.      }
  302.     file_offset = fileinfo.cbFile - (640*480);
  303.     rc = DosSetFilePtr(file,file_offset,FILE_BEGIN,&newptr);
  304.     if (rc)
  305.      {
  306.       DosClose(file);
  307.       return(0);
  308.      }
  309.     rc = DosRead(file,BackGndImage,640*480,&bytesread);
  310.     if ((rc)||(bytesread != 640*480))
  311.      {
  312.       DosClose(file);
  313.       return(0);
  314.      }
  315.     DosClose(file);
  316. // now setup the bitmap info for it...
  317.    bmi2 = calloc(sizeof(BITMAPINFOHEADER2)+(sizeof(RGB2)*256),1);
  318.    if (bmi2 == NULL)
  319.     {
  320.      DosFreeMem(BackGndImage);
  321.      return(0);
  322.     }
  323.    for(i=0;i<256;i++)
  324.     {  // each rgb2 entry in the palette is 4 bytes long
  325.       bmi2->argbColor[i].bRed = Palette[i*4];
  326.       bmi2->argbColor[i].bGreen = Palette[i*4+1];
  327.       bmi2->argbColor[i].bBlue = Palette[i*4+2];
  328.     }
  329. #ifdef APPLY_PALETTE
  330.    if (!AppliedPal)
  331.     {
  332.      rc = DosAllocMem((PPVOID)&tmpPalette,256*4,
  333.        (ULONG)(PAG_READ|PAG_WRITE|PAG_COMMIT));
  334.      if (rc)
  335.       {
  336.         DosFreeMem(BackGndImage);
  337.         return(0);
  338.       }
  339.      for(i=0;i<256;i++)
  340.       {  // each rgb2 entry in the palette is 4 bytes long
  341.         tmpPalette[i] = (Palette[i*4] << 16) +
  342.          (Palette[i*4+1]<<8) + Palette[i*4+2];
  343.       }
  344.     }
  345. #endif
  346.    bmi2->cbFix = sizeof(BITMAPINFOHEADER2);
  347.    bmi2->cx = 640;
  348.    bmi2->cy = 480;
  349.    bmi2->cPlanes = 1;
  350.    bmi2->cBitCount = 8;
  351.    bmi2->cbImage = (640*480);
  352.    bmi2->cxResolution = cxClient;
  353.    bmi2->cyResolution = cyClient;
  354.    bmi2->cclrUsed = 256;
  355.    bmi2->cclrImportant = 256;
  356.    bmi2->ulColorEncoding = BCE_RGB;
  357.    if (BackGndBitmap != (HBITMAP)NULL)
  358.     {
  359.      GpiSetBitmap(hpsMemory,NULL);
  360.      GpiSetBitmap(hwClientPS,NULL);
  361.      GpiDeleteBitmap(BackGndBitmap);
  362.      //BackGndBitmap = NULL;
  363.     }
  364.    BackGndBitmap = GpiCreateBitmap(hwClientPS,(PBITMAPINFOHEADER2)bmi2,
  365.         CBM_INIT,(PBYTE)BackGndImage,bmi2);
  366.    if (BackGndBitmap == 0L)
  367.     {
  368.      DosFreeMem(BackGndImage);
  369.      return(0);
  370.     }
  371.    DosFreeMem(BackGndImage);
  372.    DosFreeMem(bmi2);
  373. #ifdef APPLY_PALETTE
  374.    if (!AppliedPal)
  375.     {
  376.      if (!GpiCreateLogColorTable(hwClientPS,LCOL_PURECOLOR,LCOLF_CONSECRGB,0L,256,(PLONG)tmpPalette))
  377.       return(0);
  378.      if (!GpiCreateLogColorTable(hpsMemory,LCOL_PURECOLOR,LCOLF_CONSECRGB,0L,256,(PLONG)tmpPalette))
  379.       return(0);
  380.      DosFreeMem(tmpPalette);
  381.      AppliedPal = 1;
  382.     }
  383. #endif
  384.   }
  385. // now blit this thing into the windows space
  386.   rect.xLeft = 0;
  387.   rect.xRight = 639;
  388.   rect.yTop = 479;
  389.   rect.yBottom = 0;
  390.   apts.x = 0;
  391.   apts.y = 0;
  392.   WinDrawBitmap(hps,BackGndBitmap,&rect,&apts,
  393.          0L,0L,DBM_NORMAL);
  394.   if (!FirstTimeRun)
  395.    {
  396.     DrawAmigaBoard();
  397.    }
  398.   else //if (first == TRUE)
  399.    { // fix the offscreen bitmap
  400.      // A1 is black B1 is white
  401.      // A2 is white B2 is black
  402.      // A7 is black B7 is white
  403.      // A8 is white B8 is black
  404.      // A5 is black
  405.      // B5 is white
  406.    GpiSetBitmap(hpsMemory,BackGndBitmap);
  407.  
  408. // do ROW1 in offscreen bitmap
  409.    apts2[2].x = COLA; // src left bottom
  410.    apts2[2].y = (ROW5); // src left bottom
  411.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  412.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  413.    apts2[0].x = COLA; // tgt left bottom
  414.    apts2[0].y = (ROW1); // tgt left bottom
  415.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  416.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  417.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  418.  
  419.    apts2[2].x = COLA; // src left bottom
  420.    apts2[2].y = (ROW5)  ; // src left bottom
  421.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  422.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  423.    apts2[0].x = COLC; // tgt left bottom
  424.    apts2[0].y = (ROW1); // tgt left bottom
  425.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  426.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  427.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  428.  
  429.    apts2[2].x = COLA; // src left bottom
  430.    apts2[2].y = (ROW5)  ; // src left bottom
  431.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  432.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  433.    apts2[0].x = COLE; // tgt left bottom
  434.    apts2[0].y = (ROW1); // tgt left bottom
  435.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  436.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  437.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  438.  
  439.    apts2[2].x = COLA; // src left bottom
  440.    apts2[2].y = (ROW5)  ; // src left bottom
  441.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  442.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  443.    apts2[0].x = COLG; // tgt left bottom
  444.    apts2[0].y = (ROW1); // tgt left bottom
  445.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  446.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  447.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  448.  
  449.    apts2[2].x = COLB; // src left bottom
  450.    apts2[2].y = (ROW5)  ; // src left bottom
  451.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  452.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  453.    apts2[0].x = COLB; // tgt left bottom
  454.    apts2[0].y = (ROW1); // tgt left bottom
  455.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  456.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  457.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  458.  
  459.    apts2[2].x = COLB; // src left bottom
  460.    apts2[2].y = (ROW5)  ; // src left bottom
  461.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  462.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  463.    apts2[0].x = COLD; // tgt left bottom
  464.    apts2[0].y = (ROW1); // tgt left bottom
  465.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  466.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  467.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  468.  
  469.    apts2[2].x = COLB; // src left bottom
  470.    apts2[2].y = (ROW5)  ; // src left bottom
  471.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  472.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  473.    apts2[0].x = COLF; // tgt left bottom
  474.    apts2[0].y = (ROW1); // tgt left bottom
  475.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  476.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  477.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  478.  
  479.    apts2[2].x = COLB; // src left bottom
  480.    apts2[2].y = (ROW5)  ; // src left bottom
  481.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  482.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  483.    apts2[0].x = COLH; // tgt left bottom
  484.    apts2[0].y = (ROW1); // tgt left bottom
  485.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  486.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  487.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  488.  
  489. // now do row 7 in offscreen bitmap
  490.    apts2[2].x = COLA; // src left bottom
  491.    apts2[2].y = (ROW5) ; // src left bottom
  492.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  493.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  494.    apts2[0].x = COLA; // tgt left bottom
  495.    apts2[0].y = (ROW7) ; // tgt left bottom
  496.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  497.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  498.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  499.  
  500.    apts2[2].x = COLA; // src left bottom
  501.    apts2[2].y = (ROW5) ; // src left bottom
  502.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  503.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  504.    apts2[0].x = COLC; // tgt left bottom
  505.    apts2[0].y = (ROW7) ; // tgt left bottom
  506.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  507.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  508.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  509.  
  510.    apts2[2].x = COLA; // src left bottom
  511.    apts2[2].y = (ROW5) ; // src left bottom
  512.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  513.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  514.    apts2[0].x = COLE; // tgt left bottom
  515.    apts2[0].y = (ROW7) ; // tgt left bottom
  516.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  517.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  518.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  519.  
  520.    apts2[2].x = COLA; // src left bottom
  521.    apts2[2].y = (ROW5) ; // src left bottom
  522.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  523.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  524.    apts2[0].x = COLG; // tgt left bottom
  525.    apts2[0].y = (ROW7) ; // tgt left bottom
  526.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  527.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  528.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  529.  
  530.    apts2[2].x = COLB; // src left bottom
  531.    apts2[2].y = (ROW5) ; // src left bottom
  532.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  533.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  534.    apts2[0].x = COLB; // tgt left bottom
  535.    apts2[0].y = (ROW7) ; // tgt left bottom
  536.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  537.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  538.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  539.  
  540.    apts2[2].x = COLB; // src left bottom
  541.    apts2[2].y = (ROW5) ; // src left bottom
  542.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  543.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  544.    apts2[0].x = COLD; // tgt left bottom
  545.    apts2[0].y = (ROW7) ; // tgt left bottom
  546.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  547.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  548.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  549.  
  550.    apts2[2].x = COLB; // src left bottom
  551.    apts2[2].y = (ROW5) ; // src left bottom
  552.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  553.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  554.    apts2[0].x = COLF; // tgt left bottom
  555.    apts2[0].y = (ROW7) ; // tgt left bottom
  556.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  557.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  558.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  559.  
  560.    apts2[2].x = COLB; // src left bottom
  561.    apts2[2].y = (ROW5) ; // src left bottom
  562.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  563.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  564.    apts2[0].x = COLH; // tgt left bottom
  565.    apts2[0].y = (ROW7) ; // tgt left bottom
  566.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  567.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  568.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  569.  
  570. // now do row 2 in offscreen bitmap
  571.    apts2[2].x = COLB; // src left bottom
  572.    apts2[2].y = (ROW5) ; // src left bottom
  573.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  574.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  575.    apts2[0].x = COLA; // tgt left bottom
  576.    apts2[0].y = (ROW2) ; // tgt left bottom
  577.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  578.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  579.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  580.  
  581.    apts2[2].x = COLB; // src left bottom
  582.    apts2[2].y = (ROW5) ; // src left bottom
  583.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  584.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  585.    apts2[0].x = COLC; // tgt left bottom
  586.    apts2[0].y = (ROW2) ; // tgt left bottom
  587.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  588.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  589.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  590.  
  591.    apts2[2].x = COLB; // src left bottom
  592.    apts2[2].y = (ROW5) ; // src left bottom
  593.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  594.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  595.    apts2[0].x = COLE; // tgt left bottom
  596.    apts2[0].y = (ROW2) ; // tgt left bottom
  597.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  598.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  599.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  600.  
  601.    apts2[2].x = COLB; // src left bottom
  602.    apts2[2].y = (ROW5) ; // src left bottom
  603.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  604.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  605.    apts2[0].x = COLG; // tgt left bottom
  606.    apts2[0].y = (ROW2) ; // tgt left bottom
  607.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  608.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  609.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  610.  
  611.    apts2[2].x = COLA; // src left bottom
  612.    apts2[2].y = (ROW5) ; // src left bottom
  613.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  614.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  615.    apts2[0].x = COLB; // tgt left bottom
  616.    apts2[0].y = (ROW2) ; // tgt left bottom
  617.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  618.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  619.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  620.  
  621.    apts2[2].x = COLA; // src left bottom
  622.    apts2[2].y = (ROW5) ; // src left bottom
  623.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  624.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  625.    apts2[0].x = COLD; // tgt left bottom
  626.    apts2[0].y = (ROW2) ; // tgt left bottom
  627.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  628.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  629.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  630.  
  631.    apts2[2].x = COLA; // src left bottom
  632.    apts2[2].y = (ROW5) ; // src left bottom
  633.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  634.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  635.    apts2[0].x = COLF; // tgt left bottom
  636.    apts2[0].y = (ROW2) ; // tgt left bottom
  637.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  638.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  639.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  640.  
  641.    apts2[2].x = COLA; // src left bottom
  642.    apts2[2].y = (ROW5) ; // src left bottom
  643.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  644.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  645.    apts2[0].x = COLH; // tgt left bottom
  646.    apts2[0].y = (ROW2) ; // tgt left bottom
  647.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  648.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  649.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  650.  
  651. // now do row 8 in offscreen bitmap
  652.    apts2[2].x = COLB; // src left bottom
  653.    apts2[2].y = (ROW5) ; // src left bottom
  654.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  655.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  656.    apts2[0].x = COLA; // tgt left bottom
  657.    apts2[0].y = (ROW8); // tgt left bottom
  658.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  659.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  660.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  661.  
  662.    apts2[2].x = COLB; // src left bottom
  663.    apts2[2].y = (ROW5) ; // src left bottom
  664.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  665.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  666.    apts2[0].x = COLC; // tgt left bottom
  667.    apts2[0].y = (ROW8) ; // tgt left bottom
  668.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  669.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  670.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  671.  
  672.    apts2[2].x = COLB; // src left bottom
  673.    apts2[2].y = (ROW5) ; // src left bottom
  674.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  675.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  676.    apts2[0].x = COLE; // tgt left bottom
  677.    apts2[0].y = (ROW8) ; // tgt left bottom
  678.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  679.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  680.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  681.  
  682.    apts2[2].x = COLB; // src left bottom
  683.    apts2[2].y = (ROW5) ; // src left bottom
  684.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  685.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  686.    apts2[0].x = COLG; // tgt left bottom
  687.    apts2[0].y = (ROW8) ; // tgt left bottom
  688.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  689.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  690.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  691.  
  692.    apts2[2].x = COLA; // src left bottom
  693.    apts2[2].y = (ROW5) ; // src left bottom
  694.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  695.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  696.    apts2[0].x = COLB; // tgt left bottom
  697.    apts2[0].y = (ROW8) ; // tgt left bottom
  698.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  699.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  700.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  701.  
  702.    apts2[2].x = COLA; // src left bottom
  703.    apts2[2].y = (ROW5) ; // src left bottom
  704.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  705.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  706.    apts2[0].x = COLD; // tgt left bottom
  707.    apts2[0].y = (ROW8) ; // tgt left bottom
  708.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  709.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  710.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  711.  
  712.    apts2[2].x = COLA; // src left bottom
  713.    apts2[2].y = (ROW5) ; // src left bottom
  714.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  715.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  716.    apts2[0].x = COLF; // tgt left bottom
  717.    apts2[0].y = (ROW8) ; // tgt left bottom
  718.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  719.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  720.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  721.  
  722.    apts2[2].x = COLA; // src left bottom
  723.    apts2[2].y = (ROW5) ; // src left bottom
  724.    apts2[3].x = apts2[2].x + SQUAREWIDTH - 1; // src rt top
  725.    apts2[3].y = apts2[2].y + SQUAREHEIGHT - 1; // src rt top
  726.    apts2[0].x = COLH; // tgt left bottom
  727.    apts2[0].y = (ROW8) ; // tgt left bottom
  728.    apts2[1].x = apts2[0].x + SQUAREWIDTH - 1; // tgt rt top
  729.    apts2[1].y = apts2[0].y + SQUAREHEIGHT - 1; // tgt rt top
  730.    GpiBitBlt(hpsMemory,hwClientPS,4,(PPOINTL)apts2,ROP_SRCCOPY,BBO_IGNORE);
  731.  
  732.    GpiSetBitmap(hpsMemory,NULL);
  733.    }
  734.  FirstTimeRun = 0;
  735.  return(1);
  736. }
  737.  
  738. void RepaintBobs(hps)
  739. HPS hps; // this routine is for WM_PAINT time...
  740. {// pass in the  HPS from WinBeginPaint,
  741.  // A good idea to request the mutex sem DrawSemaphore
  742.  // in your WM_PAINT routine, before you do any drawing
  743.  // release it there too
  744.  // YOU MUST HAVE RE-BLITTED THE BACKGND BITMAP 1st!!!
  745.  // this just redraws the bob list at  oldx,oldy
  746.  BOB *list;
  747.  POINTL apts[4];
  748.  
  749.  if (!GelsInited) // in case we are called before gels setup
  750.   return;
  751.  //GpiSetDrawMode();
  752.  list = SystemBobList;
  753.  while (list != NULL)
  754.   {
  755.    if ((list->OldX != -1)&&(list->OldY != -1))
  756.     {
  757.      apts[2].x = 0; // src left bottom
  758.      apts[2].y = 0; // src left bottom
  759.      apts[3].x = list->Width - 1; // src rt top
  760.      apts[3].y = list->Height - 1; // src rt top
  761.      apts[0].x = list->OldX; // tgt left bottom
  762.      apts[0].y = list->OldY; // tgt left bottom
  763.      apts[1].x = apts[0].x + list->Width - 1; // tgt rt top
  764.      apts[1].y = apts[0].y + list->Height - 1; // tgt rt top
  765.      TransBlit(list,hps,hpsMemory,4L,(PPOINTL)apts);
  766.     }
  767.    list = list->Next;
  768.   }
  769.  //GpiSetDrawMode();
  770. }
  771.  
  772.  
  773. // BUGS HERE I THINK, The creation of the ShadowImage is not
  774. // correct somehow... !!!!!
  775.  
  776. BOB *CreateBob(Width,Height,Depth,Image,Palette)
  777. LONG Width,Height,Depth;
  778. UCHAR *Palette; // this is a char array 3 bytes per entry for RGB
  779. void *Image; // this is the image data for this Object, in OS/2 format
  780. {
  781.  LONG tmpw;
  782.  APIRET rc;
  783.  LONG i;
  784.  BOB *bob;
  785.  LONG NumColors=(1L<<Depth);
  786.  
  787.  bob = calloc(sizeof(BOB),1);
  788.  if (!bob)
  789.   return(NULL);
  790.  bob->bmi2 = calloc((sizeof(BITMAPINFOHEADER2)+sizeof(RGB2)*NumColors),1);
  791.  bob->sbmi2 = calloc(sizeof(BITMAPINFOHEADER2)+sizeof(RGB2)*2,1);
  792.  if (bob->bmi2 == NULL)
  793.   return(NULL);
  794.  if (bob->sbmi2 == NULL)
  795.   return(NULL);
  796.  if (Width & 0x1f) // not mult of 32 bits in scanline
  797.   {
  798.    tmpw = Width & 0x1f;
  799.    tmpw += 0x20; // now it is
  800.   }
  801.  else
  802.   tmpw = Width;
  803.  rc = DosAllocMem((PPVOID)&bob->ShadowImage,(tmpw*Height)/8,
  804.     PAG_READ|PAG_WRITE|PAG_COMMIT);
  805.  if (rc)
  806.   return(NULL);
  807.  MakeShadowMask(Image,bob->ShadowImage,Width,Height);
  808.  for(i=0;i<NumColors;i++)
  809.   {
  810.     bob->bmi2->argbColor[i].bRed = Palette[i*4];
  811.     bob->bmi2->argbColor[i].bGreen = Palette[i*4+1];
  812.     bob->bmi2->argbColor[i].bBlue = Palette[i*4+2];
  813.   }
  814.  bob->sbmi2->argbColor[1].bRed = 0xff;
  815.  bob->sbmi2->argbColor[1].bGreen = 0xff;
  816.  bob->sbmi2->argbColor[1].bBlue = 0xff;
  817.  bob->bmi2->cbFix = sizeof(BITMAPINFOHEADER2);
  818.  bob->sbmi2->cbFix = sizeof(BITMAPINFOHEADER2);
  819.  bob->bmi2->cx = bob->sbmi2->cx = Width;
  820.  bob->bmi2->cy = bob->sbmi2->cy = Height;
  821.  bob->bmi2->cPlanes = bob->sbmi2->cPlanes = 1;
  822.  bob->bmi2->cBitCount = Depth;
  823.  bob->sbmi2->cBitCount = 1;
  824.  bob->bmi2->cbImage = ((Width*Height*Depth)/8);
  825.  bob->sbmi2->cbImage = (Width*Height)/8;
  826.  bob->bmi2->cxResolution = bob->sbmi2->cxResolution = cxClient;
  827.  bob->bmi2->cyResolution = bob->sbmi2->cyResolution = cyClient;
  828.  bob->bmi2->cclrUsed = NumColors;
  829.  bob->sbmi2->cclrUsed = 2;
  830.  bob->bmi2->cclrImportant = NumColors;
  831.  bob->sbmi2->cclrImportant = 2;
  832.  bob->bmi2->usUnits = bob->sbmi2->usUnits = 0;
  833.  bob->bmi2->ulColorEncoding = bob->sbmi2->ulColorEncoding = BCE_RGB;
  834.  bob->Width = Width;
  835.  bob->Depth = Depth;
  836.  bob->Height = Height;
  837.  bob->XPos = bob->YPos = bob->OldY = bob->OldX = -1;
  838.  bob->SaveBuffer = GpiCreateBitmap(hwClientPS,(PBITMAPINFOHEADER2)bob->bmi2,
  839.         0L,NULL,bob->bmi2);
  840.  if (bob->SaveBuffer == 0L)
  841.   return(NULL);
  842.  bob->Image = GpiCreateBitmap(hwClientPS,(PBITMAPINFOHEADER2)bob->bmi2,
  843.         CBM_INIT,(PBYTE)Image,bob->bmi2);
  844.  if (bob->Image == 0L)
  845.   return(NULL);
  846.  bob->ShadowMask = GpiCreateBitmap(hwClientPS,(PBITMAPINFOHEADER2)bob->sbmi2,
  847.         CBM_INIT,(PBYTE)bob->ShadowImage,bob->sbmi2);
  848.  if (bob->ShadowMask == 0L)
  849.   return(NULL);
  850.  DosFreeMem(bob->ShadowImage);
  851.  bob->ShadowImage = NULL;
  852.  return(bob);
  853. }
  854.  
  855. int FreeBob(bob)
  856. BOB *bob;
  857. {
  858.   GpiSetBitmap(hwClientPS,NULL);
  859.   GpiDeleteBitmap(bob->ShadowMask);
  860.   GpiDeleteBitmap(bob->Image);
  861.   GpiDeleteBitmap(bob->SaveBuffer);
  862.   free(bob->bmi2);
  863.   free(bob->sbmi2);
  864.   free(bob);
  865.   return(1);
  866. }
  867.  
  868. void TransBlit2(bob,hwClientPS,hpsMemory,numpts,rect_bounds)
  869. BOB *bob;
  870. HPS hwClientPS;
  871. HPS hpsMemory;
  872. LONG numpts;
  873. PPOINTL rect_bounds;
  874. {
  875.  APIRET rc;
  876.  
  877.  rc = DosRequestMutexSem(DrawSemaphore,2000);
  878.  if (rc)
  879.   return;
  880.  TransBlit(bob,hwClientPS,hpsMemory,numpts,rect_bounds);
  881.  DosReleaseMutexSem(DrawSemaphore);
  882. }
  883.  
  884. void TransBlit(bob,hwClientPS,hpsMemory,numpts,rect_bounds)
  885. BOB *bob;
  886. HPS hwClientPS;
  887. HPS hpsMemory;
  888. LONG numpts;
  889. PPOINTL rect_bounds;
  890. {
  891.   if (!SafeBlit)
  892.    {
  893.     GpiSetBitmap(hpsMemory,bob->Image);
  894.     GpiSetBackColor(hwClientPS,CLR_FALSE);
  895.     GpiSetBackMix(hwClientPS,BM_SRCTRANSPARENT);
  896.     GpiBitBlt(hwClientPS,hpsMemory,numpts,(PPOINTL)rect_bounds,ROP_SRCCOPY,BBO_IGNORE);
  897.     GpiSetBackMix(hwClientPS,BM_DEFAULT);
  898.    } // !safe
  899.   else
  900.    {
  901.     GpiSetBitmap(hpsMemory,bob->ShadowMask);
  902.     GpiBitBlt(hwClientPS,hpsMemory,numpts,(PPOINTL)rect_bounds,ROP_SRCAND,BBO_IGNORE);
  903.     GpiSetBitmap(hpsMemory,bob->Image);
  904.     GpiBitBlt(hwClientPS,hpsMemory,numpts,(PPOINTL)rect_bounds,ROP_SRCPAINT,BBO_IGNORE);
  905.     } // safe
  906. }
  907.  
  908. void DrawGList()
  909. {
  910.  RECTL rect;
  911.  POINTL apts[4];
  912.  BOB *list=SystemBobList;
  913.  
  914.  if (list != NULL)
  915.   {
  916.    if (DosRequestMutexSem(DrawSemaphore,10000L))
  917.     {
  918.      return;
  919.     }
  920.   }
  921.  //GpiSetDrawMode();
  922.  while (list != NULL)
  923.   { // restore all the backgrounds that were destroyed
  924.    if ((list->OldX != -1)&&(list->OldY != -1))
  925.     {
  926.       rect.xLeft = 0;
  927.       rect.xRight = list->Width - 1;
  928.       rect.yTop = list->Height - 1;
  929.       rect.yBottom = 0;
  930.       apts[0].x = list->OldX;
  931.       apts[0].y = list->OldY;
  932.      // restore the backgn to what it was
  933.      WinDrawBitmap(hwClientPS,list->SaveBuffer,&rect,&apts[0],
  934.          0L,0L,DBM_NORMAL);
  935.     }
  936.    list = list->Next;
  937.   }
  938.  list = SystemBobList;
  939.  while (list != NULL)
  940.   {  // save all the backgnds that are about to be overwritten
  941.    if ((list->XPos != -1)&&(list->YPos != -1))
  942.     {
  943.      apts[0].x = 0; // target left bottom
  944.      apts[0].y = 0; // target left bottom
  945.      apts[1].x = list->Width - 1; // target rt top
  946.      apts[1].y = list->Height - 1; // tgt rt top
  947.      apts[2].x = list->XPos; // src left bottom
  948.      apts[2].y = list->YPos; // src left bottom
  949.      apts[3].x = apts[2].x + list->Width - 1; // src rt top
  950.      apts[3].y = apts[2].y + list->Height - 1; // src rt top
  951.      // now save the backgn area to savebuffer area
  952.      GpiSetBitmap(hpsMemory,list->SaveBuffer);
  953.      GpiBitBlt(hpsMemory,hwClientPS,4L,(PPOINTL)apts,
  954.         ROP_SRCCOPY,BBO_IGNORE);
  955.     }
  956.    list = list->Next;
  957.   }
  958.  list = SystemBobList;
  959.  while (list != NULL)
  960.   { // draw all the Bobs at their new locations
  961.    if ((list->XPos != -1)&&(list->YPos != -1))
  962.     {
  963.      apts[2].x = 0; // src left bottom
  964.      apts[2].y = 0; // src left bottom
  965.      apts[3].x = list->Width - 1; // src rt top
  966.      apts[3].y = list->Height - 1; // src rt top
  967.      apts[0].x = list->XPos; // tgt left bottom
  968.      apts[0].y = list->YPos; // tgt left bottom
  969.      apts[1].x = apts[0].x + list->Width - 1; // tgt rt top
  970.      apts[1].y = apts[0].y + list->Height - 1; // tgt rt top
  971.      TransBlit(list,hwClientPS,hpsMemory,4L,(PPOINTL)apts);
  972.      list->OldX = list->XPos;
  973.      list->OldY = list->YPos;
  974.     }
  975.    list = list->Next;
  976.   }
  977.  //GpiSetDrawMode();
  978.  DosReleaseMutexSem(DrawSemaphore);
  979. }
  980.  
  981. int InitGels()
  982. {
  983.  bobsizl.cx = bobsizl.cy = 0;
  984.  hwClientPS = GpiCreatePS(hab,winhdc,&bobsizl,
  985.    PU_PELS|GPIF_DEFAULT|GPIT_MICRO|GPIA_ASSOC);
  986.  bobsizl.cx = bobsizl.cy = 0;
  987.  hdcMemory = DevOpenDC(hab,OD_MEMORY,"*",0L,NULL,NULLHANDLE);
  988.  hpsMemory = GpiCreatePS(hab,hdcMemory,&bobsizl,
  989.    PU_PELS|GPIF_DEFAULT|GPIT_MICRO|GPIA_ASSOC);
  990.  SystemBobList = NULL; // no bobs on list
  991.  if (DosCreateMutexSem("\\SEM32\\DrawSem",&DrawSemaphore,
  992.      DC_SEM_SHARED,FALSE))
  993.   {
  994.    return(0);
  995.   }
  996.  GelsInited = 1;
  997.  return(1);
  998. }
  999.  
  1000. int CloseGels()
  1001. {
  1002.  //WinCloseWindowDC(winhdc);
  1003.  DosCloseMutexSem(DrawSemaphore);
  1004.  GpiDestroyPS(hwClientPS);
  1005.  hwClientPS = 0L;
  1006.  GpiDestroyPS(hpsMemory);
  1007.  DevCloseDC(hdcMemory);
  1008.  GelsInited = 0;
  1009.  SystemBobList = NULL;
  1010.  return(1);
  1011. }
  1012.  
  1013. void AddBob(bob)
  1014. BOB *bob;
  1015. {
  1016.  BOB *list;
  1017.  
  1018.  if (bob == NULL)
  1019.   return;
  1020.  bob->Next = NULL;
  1021.  if (SystemBobList == NULL)
  1022.   { // first time
  1023.    SystemBobList = bob;
  1024.    return;
  1025.   }
  1026.  list = SystemBobList;
  1027.  while (list->Next != NULL)
  1028.   {
  1029.    list = list->Next;
  1030.   }
  1031.  list->Next = bob;
  1032. }
  1033.  
  1034. void EraseBob(bob)
  1035. BOB *bob;
  1036. {
  1037.  POINTL rcl;
  1038.  RECTL rect;
  1039.  
  1040.  if (bob == NULL)
  1041.   return;
  1042.  if (DosRequestMutexSem(DrawSemaphore,15000L))
  1043.   {
  1044.    return;
  1045.   }
  1046.  if ((bob->OldX != -1)&&(bob->OldY != -1))
  1047.   {
  1048.    rect.xLeft = 0;
  1049.    rect.xRight = bob->Width - 1;
  1050.    rect.yTop = bob->Height - 1;
  1051.    rect.yBottom = 0;
  1052.    rcl.x = bob->OldX;
  1053.    rcl.y = bob->OldY;
  1054.    // restore the backgn to what it was
  1055.    WinDrawBitmap(hwClientPS,bob->SaveBuffer,&rect,&rcl,
  1056.            0L,0L,DBM_NORMAL);
  1057.   }
  1058.  bob->OldX = bob->OldY = -1;
  1059.  DosReleaseMutexSem(DrawSemaphore);
  1060. }
  1061.  
  1062. void RemBob(bob)
  1063. BOB *bob;
  1064. { // we will use the HPS for the main client here..
  1065.  POINTL rcl;
  1066.  BOB *list;
  1067.  RECTL rect;
  1068.  
  1069.  if (bob == NULL)
  1070.   return;
  1071.  if (DosRequestMutexSem(DrawSemaphore,15000L))
  1072.   {
  1073.    return;
  1074.   }
  1075.  if ((bob->OldX != -1)&&(bob->OldY != -1))
  1076.   {
  1077.    rect.xLeft = 0;
  1078.    rect.xRight = bob->Width - 1;
  1079.    rect.yTop = bob->Height - 1;
  1080.    rect.yBottom = 0;
  1081.    rcl.x = bob->OldX;
  1082.    rcl.y = bob->OldY;
  1083.    // restore the backgn to what it was
  1084.    WinDrawBitmap(hwClientPS,bob->SaveBuffer,&rect,&rcl,
  1085.            0L,0L,DBM_NORMAL);
  1086.   }
  1087.  bob->OldX = bob->OldY = -1;
  1088.  DosReleaseMutexSem(DrawSemaphore);
  1089.  if (bob == SystemBobList)
  1090.   {
  1091.    SystemBobList = bob->Next;
  1092.    return;
  1093.   }
  1094.  list = SystemBobList; 
  1095.  while (list != NULL)
  1096.   {
  1097.    if (list->Next == bob)
  1098.     {
  1099.      list->Next = bob->Next;
  1100.      return;
  1101.     }
  1102.    list = list->Next;
  1103.   }
  1104. }
  1105.  
  1106. void RemBobNR(bob)
  1107. BOB *bob;
  1108. { // we will use the HPS for the main client here..
  1109.  BOB *list;
  1110.  
  1111.  if (bob == NULL)
  1112.   return;
  1113.  bob->OldX = bob->OldY = -1;
  1114.  if (bob == SystemBobList)
  1115.   {
  1116.    SystemBobList = bob->Next;
  1117.    return;
  1118.   }
  1119.  list = SystemBobList;
  1120.  while (list != NULL)
  1121.   {
  1122.    if (list->Next == bob)
  1123.     {
  1124.      list->Next = bob->Next;
  1125.      return;
  1126.     }
  1127.    list = list->Next;
  1128.   }
  1129. }
  1130.  
  1131.