home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / server / ddx / mi / misprite.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-19  |  50.9 KB  |  2,043 lines

  1. /*
  2.  * misprite.c
  3.  *
  4.  * machine independent software sprite routines
  5.  */
  6.  
  7. /* $XConsortium: misprite.c,v 5.38 91/07/19 23:19:31 keith Exp $ */
  8.  
  9. /*
  10. Copyright 1989 by the Massachusetts Institute of Technology
  11.  
  12. Permission to use, copy, modify, and distribute this software and its
  13. documentation for any purpose and without fee is hereby granted,
  14. provided that the above copyright notice appear in all copies and that
  15. both that copyright notice and this permission notice appear in
  16. supporting documentation, and that the name of M.I.T. not be used in
  17. advertising or publicity pertaining to distribution of the software
  18. without specific, written prior permission.  M.I.T. makes no
  19. representations about the suitability of this software for any
  20. purpose.  It is provided "as is" without express or implied warranty.
  21. */
  22.  
  23. # include   "X.h"
  24. # include   "Xproto.h"
  25. # include   "misc.h"
  26. # include   "pixmapstr.h"
  27. # include   "input.h"
  28. # include   "mi.h"
  29. # include   "cursorstr.h"
  30. # include   "font.h"
  31. # include   "scrnintstr.h"
  32. # include   "colormapst.h"
  33. # include   "windowstr.h"
  34. # include   "gcstruct.h"
  35. # include   "mipointer.h"
  36. # include   "mispritest.h"
  37. # include   "dixfontstr.h"
  38. # include   "fontstruct.h"
  39.  
  40. /*
  41.  * screen wrappers
  42.  */
  43.  
  44. static int  miSpriteScreenIndex;
  45. static unsigned long miSpriteGeneration = 0;
  46.  
  47. static Bool        miSpriteCloseScreen();
  48. static void        miSpriteGetImage();
  49. static void        miSpriteGetSpans();
  50. static void        miSpriteSourceValidate();
  51. static Bool        miSpriteCreateGC();
  52. static void        miSpriteBlockHandler();
  53. static void        miSpriteInstallColormap();
  54. static void        miSpriteStoreColors();
  55.  
  56. static void        miSpritePaintWindowBackground();
  57. static void        miSpritePaintWindowBorder();
  58. static void        miSpriteCopyWindow();
  59. static void        miSpriteClearToBackground();
  60.  
  61. static void        miSpriteSaveDoomedAreas();
  62. static RegionPtr    miSpriteRestoreAreas();
  63. static void        miSpriteComputeSaved();
  64.  
  65. #define SCREEN_PROLOGUE(pScreen, field)\
  66.   ((pScreen)->field = \
  67.    ((miSpriteScreenPtr) (pScreen)->devPrivates[miSpriteScreenIndex].ptr)->field)
  68.  
  69. #define SCREEN_EPILOGUE(pScreen, field, wrapper)\
  70.     ((pScreen)->field = wrapper)
  71.  
  72. /*
  73.  * GC func wrappers
  74.  */
  75.  
  76. static int  miSpriteGCIndex;
  77.  
  78. static void miSpriteValidateGC (),  miSpriteCopyGC ();
  79. static void miSpriteDestroyGC(),    miSpriteChangeGC();
  80. static void miSpriteChangeClip(),   miSpriteDestroyClip();
  81. static void miSpriteCopyClip();
  82.  
  83. static GCFuncs    miSpriteGCFuncs = {
  84.     miSpriteValidateGC,
  85.     miSpriteChangeGC,
  86.     miSpriteCopyGC,
  87.     miSpriteDestroyGC,
  88.     miSpriteChangeClip,
  89.     miSpriteDestroyClip,
  90.     miSpriteCopyClip,
  91. };
  92.  
  93. #define GC_FUNC_PROLOGUE(pGC)                    \
  94.     miSpriteGCPtr   pGCPriv =                    \
  95.     (miSpriteGCPtr) (pGC)->devPrivates[miSpriteGCIndex].ptr;\
  96.     (pGC)->funcs = pGCPriv->wrapFuncs;                \
  97.     if (pGCPriv->wrapOps)                    \
  98.     (pGC)->ops = pGCPriv->wrapOps;
  99.  
  100. #define GC_FUNC_EPILOGUE(pGC)                    \
  101.     pGCPriv->wrapFuncs = (pGC)->funcs;                \
  102.     (pGC)->funcs = &miSpriteGCFuncs;                \
  103.     if (pGCPriv->wrapOps)                    \
  104.     {                                \
  105.     pGCPriv->wrapOps = (pGC)->ops;                \
  106.     (pGC)->ops = &miSpriteGCOps;                \
  107.     }
  108.  
  109. /*
  110.  * GC op wrappers
  111.  */
  112.  
  113. static void        miSpriteFillSpans(),    miSpriteSetSpans();
  114. static void        miSpritePutImage();
  115. static RegionPtr    miSpriteCopyArea(),        miSpriteCopyPlane();
  116. static void        miSpritePolyPoint(),    miSpritePolylines();
  117. static void        miSpritePolySegment(),    miSpritePolyRectangle();
  118. static void        miSpritePolyArc(),        miSpriteFillPolygon();
  119. static void        miSpritePolyFillRect(),    miSpritePolyFillArc();
  120. static int        miSpritePolyText8(),    miSpritePolyText16();
  121. static void        miSpriteImageText8(),    miSpriteImageText16();
  122. static void        miSpriteImageGlyphBlt(),    miSpritePolyGlyphBlt();
  123. static void        miSpritePushPixels(),    miSpriteLineHelper();
  124. static void        miSpriteChangeClip(),    miSpriteDestroyClip();
  125. static void        miSpriteCopyClip();
  126.  
  127. static GCOps miSpriteGCOps = {
  128.     miSpriteFillSpans,        miSpriteSetSpans,        miSpritePutImage,    
  129.     miSpriteCopyArea,        miSpriteCopyPlane,        miSpritePolyPoint,
  130.     miSpritePolylines,        miSpritePolySegment,    miSpritePolyRectangle,
  131.     miSpritePolyArc,        miSpriteFillPolygon,    miSpritePolyFillRect,
  132.     miSpritePolyFillArc,    miSpritePolyText8,        miSpritePolyText16,
  133.     miSpriteImageText8,        miSpriteImageText16,    miSpriteImageGlyphBlt,
  134.     miSpritePolyGlyphBlt,   miSpritePushPixels,        miSpriteLineHelper,
  135. };
  136.  
  137. /*
  138.  * testing only -- remove cursor for every draw.  Eventually,
  139.  * each draw operation will perform a bounding box check against
  140.  * the saved cursor area
  141.  */
  142.  
  143. #define GC_SETUP_CHEAP(pDrawable)                    \
  144.     miSpriteScreenPtr    pScreenPriv = (miSpriteScreenPtr)        \
  145.     (pDrawable)->pScreen->devPrivates[miSpriteScreenIndex].ptr; \
  146.  
  147. #define GC_SETUP(pDrawable, pGC)                    \
  148.     GC_SETUP_CHEAP(pDrawable)                        \
  149.     miSpriteGCPtr    pGCPrivate = (miSpriteGCPtr)            \
  150.     (pGC)->devPrivates[miSpriteGCIndex].ptr;            \
  151.     GCFuncs *oldFuncs = pGC->funcs;
  152.  
  153. #define GC_SETUP_AND_CHECK(pDrawable, pGC)                \
  154.     GC_SETUP(pDrawable, pGC);                        \
  155.     if (GC_CHECK((WindowPtr)pDrawable))                    \
  156.     miSpriteRemoveCursor (pDrawable->pScreen);
  157.     
  158. #define GC_CHECK(pWin)                            \
  159.     (pScreenPriv->isUp &&                        \
  160.         (pScreenPriv->pCacheWin == pWin ?                \
  161.         pScreenPriv->isInCacheWin : (                \
  162.         ((int) (pScreenPriv->pCacheWin = (pWin))) ,            \
  163.         (pScreenPriv->isInCacheWin =                \
  164.         (pWin)->drawable.x < pScreenPriv->saved.x2 &&        \
  165.         pScreenPriv->saved.x1 < (pWin)->drawable.x +        \
  166.                     (int) (pWin)->drawable.width && \
  167.         (pWin)->drawable.y < pScreenPriv->saved.y2 &&        \
  168.         pScreenPriv->saved.y1 < (pWin)->drawable.y +        \
  169.                     (int) (pWin)->drawable.height &&\
  170.         (pWin)->drawable.pScreen->RectIn (&(pWin)->borderClip, \
  171.             &pScreenPriv->saved) != rgnOUT))))
  172.  
  173. #define GC_OP_PROLOGUE(pGC) { \
  174.     (pGC)->funcs = pGCPrivate->wrapFuncs; \
  175.     (pGC)->ops = pGCPrivate->wrapOps; \
  176.     }
  177.  
  178. #define GC_OP_EPILOGUE(pGC) { \
  179.     pGCPrivate->wrapOps = (pGC)->ops; \
  180.     (pGC)->funcs = oldFuncs; \
  181.     (pGC)->ops = &miSpriteGCOps; \
  182.     }
  183.  
  184. /*
  185.  * pointer-sprite method table
  186.  */
  187.  
  188. static Bool miSpriteRealizeCursor (),    miSpriteUnrealizeCursor ();
  189. static void miSpriteSetCursor (),    miSpriteMoveCursor ();
  190.  
  191. miPointerSpriteFuncRec miSpritePointerFuncs = {
  192.     miSpriteRealizeCursor,
  193.     miSpriteUnrealizeCursor,
  194.     miSpriteSetCursor,
  195.     miSpriteMoveCursor,
  196. };
  197.  
  198. /*
  199.  * other misc functions
  200.  */
  201.  
  202. static void miSpriteRemoveCursor (),    miSpriteRestoreCursor();
  203.  
  204. /*
  205.  * miSpriteInitialize -- called from device-dependent screen
  206.  * initialization proc after all of the function pointers have
  207.  * been stored in the screen structure.
  208.  */
  209.  
  210. Bool
  211. miSpriteInitialize (pScreen, cursorFuncs, screenFuncs)
  212.     ScreenPtr            pScreen;
  213.     miSpriteCursorFuncPtr   cursorFuncs;
  214.     miPointerScreenFuncPtr  screenFuncs;
  215. {
  216.     miSpriteScreenPtr    pPriv;
  217.     VisualPtr        pVisual;
  218.     
  219.     if (miSpriteGeneration != serverGeneration)
  220.     {
  221.     miSpriteScreenIndex = AllocateScreenPrivateIndex ();
  222.     if (miSpriteScreenIndex < 0)
  223.         return FALSE;
  224.     miSpriteGeneration = serverGeneration;
  225.     miSpriteGCIndex = AllocateGCPrivateIndex ();
  226.     }
  227.     if (!AllocateGCPrivate(pScreen, miSpriteGCIndex, sizeof(miSpriteGCRec)))
  228.     return FALSE;
  229.     pPriv = (miSpriteScreenPtr) xalloc (sizeof (miSpriteScreenRec));
  230.     if (!pPriv)
  231.     return FALSE;
  232.     if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, screenFuncs,TRUE))
  233.     {
  234.     xfree ((pointer) pPriv);
  235.     return FALSE;
  236.     }
  237.     for (pVisual = pScreen->visuals;
  238.      pVisual->vid != pScreen->rootVisual;
  239.      pVisual++)
  240.     ;
  241.     pPriv->pVisual = pVisual;
  242.     pPriv->CloseScreen = pScreen->CloseScreen;
  243.     pPriv->GetImage = pScreen->GetImage;
  244.     pPriv->GetSpans = pScreen->GetSpans;
  245.     pPriv->SourceValidate = pScreen->SourceValidate;
  246.     pPriv->CreateGC = pScreen->CreateGC;
  247.     pPriv->BlockHandler = pScreen->BlockHandler;
  248.     pPriv->InstallColormap = pScreen->InstallColormap;
  249.     pPriv->StoreColors = pScreen->StoreColors;
  250.  
  251.     pPriv->PaintWindowBackground = pScreen->PaintWindowBackground;
  252.     pPriv->PaintWindowBorder = pScreen->PaintWindowBorder;
  253.     pPriv->CopyWindow = pScreen->CopyWindow;
  254.     pPriv->ClearToBackground = pScreen->ClearToBackground;
  255.  
  256.     pPriv->SaveDoomedAreas = pScreen->SaveDoomedAreas;
  257.     pPriv->RestoreAreas = pScreen->RestoreAreas;
  258.  
  259.     pPriv->pCursor = NULL;
  260.     pPriv->x = 0;
  261.     pPriv->y = 0;
  262.     pPriv->isUp = FALSE;
  263.     pPriv->shouldBeUp = FALSE;
  264.     pPriv->pCacheWin = NullWindow;
  265.     pPriv->isInCacheWin = FALSE;
  266.     pPriv->checkPixels = TRUE;
  267.     pPriv->pInstalledMap = NULL;
  268.     pPriv->pColormap = NULL;
  269.     pPriv->funcs = cursorFuncs;
  270.     pScreen->devPrivates[miSpriteScreenIndex].ptr = (pointer) pPriv;
  271.     pScreen->CloseScreen = miSpriteCloseScreen;
  272.     pScreen->GetImage = miSpriteGetImage;
  273.     pScreen->GetSpans = miSpriteGetSpans;
  274.     pScreen->SourceValidate = miSpriteSourceValidate;
  275.     pScreen->CreateGC = miSpriteCreateGC;
  276.     pScreen->BlockHandler = miSpriteBlockHandler;
  277.     pScreen->InstallColormap = miSpriteInstallColormap;
  278.     pScreen->StoreColors = miSpriteStoreColors;
  279.  
  280.     pScreen->PaintWindowBackground = miSpritePaintWindowBackground;
  281.     pScreen->PaintWindowBorder = miSpritePaintWindowBorder;
  282.     pScreen->CopyWindow = miSpriteCopyWindow;
  283.     pScreen->ClearToBackground = miSpriteClearToBackground;
  284.  
  285.     pScreen->SaveDoomedAreas = miSpriteSaveDoomedAreas;
  286.     pScreen->RestoreAreas = miSpriteRestoreAreas;
  287.  
  288.     return TRUE;
  289. }
  290.  
  291. /*
  292.  * Screen wrappers
  293.  */
  294.  
  295. /*
  296.  * CloseScreen wrapper -- unwrap everything, free the private data
  297.  * and call the wrapped function
  298.  */
  299.  
  300. static Bool
  301. miSpriteCloseScreen (i, pScreen)
  302.     ScreenPtr    pScreen;
  303. {
  304.     miSpriteScreenPtr   pScreenPriv;
  305.  
  306.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  307.  
  308.     pScreen->CloseScreen = pScreenPriv->CloseScreen;
  309.     pScreen->GetImage = pScreenPriv->GetImage;
  310.     pScreen->GetSpans = pScreenPriv->GetSpans;
  311.     pScreen->SourceValidate = pScreenPriv->SourceValidate;
  312.     pScreen->CreateGC = pScreenPriv->CreateGC;
  313.     pScreen->BlockHandler = pScreenPriv->BlockHandler;
  314.     pScreen->InstallColormap = pScreenPriv->InstallColormap;
  315.     pScreen->StoreColors = pScreenPriv->StoreColors;
  316.  
  317.     pScreen->PaintWindowBackground = pScreenPriv->PaintWindowBackground;
  318.     pScreen->PaintWindowBorder = pScreenPriv->PaintWindowBorder;
  319.     pScreen->CopyWindow = pScreenPriv->CopyWindow;
  320.     pScreen->ClearToBackground = pScreenPriv->ClearToBackground;
  321.  
  322.     pScreen->SaveDoomedAreas = pScreenPriv->SaveDoomedAreas;
  323.     pScreen->RestoreAreas = pScreenPriv->RestoreAreas;
  324.  
  325.     xfree ((pointer) pScreenPriv);
  326.  
  327.     return (*pScreen->CloseScreen) (i, pScreen);
  328. }
  329.  
  330. static void
  331. miSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine)
  332.     DrawablePtr        pDrawable;
  333.     int            sx, sy, w, h;
  334.     unsigned int    format;
  335.     unsigned long   planemask;
  336.     pointer        pdstLine;
  337. {
  338.     ScreenPtr        pScreen = pDrawable->pScreen;
  339.     miSpriteScreenPtr    pScreenPriv;
  340.     
  341.     SCREEN_PROLOGUE (pScreen, GetImage);
  342.  
  343.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  344.  
  345.     if (pDrawable->type == DRAWABLE_WINDOW &&
  346.         pScreenPriv->isUp &&
  347.     ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y, sx, sy, w, h))
  348.     {
  349.     miSpriteRemoveCursor (pScreen);
  350.     }
  351.  
  352.     (*pScreen->GetImage) (pDrawable, sx, sy, w, h,
  353.               format, planemask, pdstLine);
  354.  
  355.     SCREEN_EPILOGUE (pScreen, GetImage, miSpriteGetImage);
  356. }
  357.  
  358. static void
  359. miSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart)
  360.     DrawablePtr    pDrawable;
  361.     int        wMax;
  362.     DDXPointPtr    ppt;
  363.     int        *pwidth;
  364.     int        nspans;
  365.     unsigned int *pdstStart;
  366. {
  367.     ScreenPtr            pScreen = pDrawable->pScreen;
  368.     miSpriteScreenPtr        pScreenPriv;
  369.     
  370.     SCREEN_PROLOGUE (pScreen, GetSpans);
  371.  
  372.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  373.  
  374.     if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp)
  375.     {
  376.     register DDXPointPtr    pts;
  377.     register int        *widths;
  378.     register int        nPts;
  379.     register int        xorg,
  380.                 yorg;
  381.  
  382.     xorg = pDrawable->x;
  383.     yorg = pDrawable->y;
  384.  
  385.     for (pts = ppt, widths = pwidth, nPts = nspans;
  386.          nPts--;
  387.          pts++, widths++)
  388.      {
  389.         if (SPN_OVERLAP(&pScreenPriv->saved,pts->y+yorg,
  390.                  pts->x+xorg,*widths))
  391.         {
  392.         miSpriteRemoveCursor (pScreen);
  393.         break;
  394.         }
  395.     }
  396.     }
  397.  
  398.     (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
  399.  
  400.     SCREEN_EPILOGUE (pScreen, GetSpans, miSpriteGetSpans);
  401. }
  402.  
  403. static void
  404. miSpriteSourceValidate (pDrawable, x, y, width, height)
  405.     DrawablePtr    pDrawable;
  406.     int        x, y, width, height;
  407. {
  408.     ScreenPtr            pScreen = pDrawable->pScreen;
  409.     miSpriteScreenPtr        pScreenPriv;
  410.     
  411.     SCREEN_PROLOGUE (pScreen, SourceValidate);
  412.  
  413.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  414.  
  415.     if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp &&
  416.     ORG_OVERLAP(&pScreenPriv->saved, pDrawable->x, pDrawable->y,
  417.             x, y, width, height))
  418.     {
  419.     miSpriteRemoveCursor (pScreen);
  420.     }
  421.  
  422.     if (pScreen->SourceValidate)
  423.     (*pScreen->SourceValidate) (pDrawable, x, y, width, height);
  424.  
  425.     SCREEN_EPILOGUE (pScreen, SourceValidate, miSpriteSourceValidate);
  426. }
  427.  
  428. static Bool
  429. miSpriteCreateGC (pGC)
  430.     GCPtr   pGC;
  431. {
  432.     ScreenPtr        pScreen = pGC->pScreen;
  433.     Bool        ret;
  434.     miSpriteGCPtr   pPriv;
  435.  
  436.     SCREEN_PROLOGUE (pScreen, CreateGC);
  437.     
  438.     pPriv = (miSpriteGCPtr)pGC->devPrivates[miSpriteGCIndex].ptr;
  439.  
  440.     ret = (*pScreen->CreateGC) (pGC);
  441.  
  442.     pPriv->wrapOps = NULL;
  443.     pPriv->wrapFuncs = pGC->funcs;
  444.     pGC->funcs = &miSpriteGCFuncs;
  445.  
  446.     SCREEN_EPILOGUE (pScreen, CreateGC, miSpriteCreateGC);
  447.  
  448.     return ret;
  449. }
  450.  
  451. static void
  452. miSpriteBlockHandler (i, blockData, pTimeout, pReadmask)
  453.     int    i;
  454.     pointer    blockData;
  455.     pointer    pTimeout;
  456.     pointer    pReadmask;
  457. {
  458.     ScreenPtr        pScreen = screenInfo.screens[i];
  459.     miSpriteScreenPtr    pPriv;
  460.  
  461.     pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  462.  
  463.     SCREEN_PROLOGUE(pScreen, BlockHandler);
  464.     
  465.     (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
  466.  
  467.     SCREEN_EPILOGUE(pScreen, BlockHandler, miSpriteBlockHandler);
  468.  
  469.     if (!pPriv->isUp && pPriv->shouldBeUp)
  470.     miSpriteRestoreCursor (pScreen);
  471. }
  472.  
  473. static void
  474. miSpriteInstallColormap (pMap)
  475.     ColormapPtr    pMap;
  476. {
  477.     ScreenPtr        pScreen = pMap->pScreen;
  478.     miSpriteScreenPtr    pPriv;
  479.  
  480.     pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  481.  
  482.     SCREEN_PROLOGUE(pScreen, InstallColormap);
  483.     
  484.     (*pScreen->InstallColormap) (pMap);
  485.  
  486.     SCREEN_EPILOGUE(pScreen, InstallColormap, miSpriteInstallColormap);
  487.  
  488.     pPriv->pInstalledMap = pMap;
  489.     if (pPriv->pColormap != pMap)
  490.     {
  491.         pPriv->checkPixels = TRUE;
  492.     if (pPriv->isUp)
  493.         miSpriteRemoveCursor (pScreen);
  494.     }
  495. }
  496.  
  497. static void
  498. miSpriteStoreColors (pMap, ndef, pdef)
  499.     ColormapPtr    pMap;
  500.     int        ndef;
  501.     xColorItem    *pdef;
  502. {
  503.     ScreenPtr        pScreen = pMap->pScreen;
  504.     miSpriteScreenPtr    pPriv;
  505.     int            i;
  506.     int            updated;
  507.     VisualPtr        pVisual;
  508.  
  509.     pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  510.  
  511.     SCREEN_PROLOGUE(pScreen, StoreColors);
  512.     
  513.     (*pScreen->StoreColors) (pMap, ndef, pdef);
  514.  
  515.     SCREEN_EPILOGUE(pScreen, StoreColors, miSpriteStoreColors);
  516.  
  517.     if (pPriv->pColormap == pMap)
  518.     {
  519.     updated = 0;
  520.     pVisual = pMap->pVisual;
  521.     if (pVisual->class == DirectColor)
  522.     {
  523.         /* Direct color - match on any of the subfields */
  524.  
  525. #define MaskMatch(a,b,mask) ((a) & (pVisual->mask) == (b) & (pVisual->mask))
  526.  
  527. #define UpdateDAC(plane,dac,mask) {\
  528.     if (MaskMatch (pPriv->colors[plane].pixel,pdef[i].pixel,mask)) {\
  529.     pPriv->colors[plane].dac = pdef[i].dac; \
  530.     updated = 1; \
  531.     } \
  532. }
  533.  
  534. #define CheckDirect(plane) \
  535.         UpdateDAC(plane,red,redMask) \
  536.         UpdateDAC(plane,green,greenMask) \
  537.         UpdateDAC(plane,blue,blueMask)
  538.  
  539.         for (i = 0; i < ndef; i++)
  540.         {
  541.         CheckDirect (SOURCE_COLOR)
  542.         CheckDirect (MASK_COLOR)
  543.         }
  544.     }
  545.     else
  546.     {
  547.         /* PseudoColor/GrayScale - match on exact pixel */
  548.         for (i = 0; i < ndef; i++)
  549.         {
  550.             if (pdef[i].pixel == pPriv->colors[SOURCE_COLOR].pixel)
  551.             {
  552.             pPriv->colors[SOURCE_COLOR] = pdef[i];
  553.             if (++updated == 2)
  554.                 break;
  555.             }
  556.             if (pdef[i].pixel == pPriv->colors[MASK_COLOR].pixel)
  557.             {
  558.             pPriv->colors[MASK_COLOR] = pdef[i];
  559.             if (++updated == 2)
  560.                 break;
  561.             }
  562.         }
  563.     }
  564.         if (updated)
  565.         {
  566.         pPriv->checkPixels = TRUE;
  567.         if (pPriv->isUp)
  568.             miSpriteRemoveCursor (pScreen);
  569.         }
  570.     }
  571. }
  572.  
  573. static void
  574. miSpriteFindColors (pScreen)
  575.     ScreenPtr    pScreen;
  576. {
  577.     miSpriteScreenPtr    pScreenPriv = (miSpriteScreenPtr)
  578.                 pScreen->devPrivates[miSpriteScreenIndex].ptr;
  579.     CursorPtr        pCursor;
  580.     xColorItem        *sourceColor, *maskColor;
  581.  
  582.     pCursor = pScreenPriv->pCursor;
  583.     sourceColor = &pScreenPriv->colors[SOURCE_COLOR];
  584.     maskColor = &pScreenPriv->colors[MASK_COLOR];
  585.     if (!(pCursor->foreRed == sourceColor->red &&
  586.       pCursor->foreGreen == sourceColor->green &&
  587.           pCursor->foreBlue == sourceColor->blue &&
  588.       pCursor->backRed == maskColor->red &&
  589.       pCursor->backGreen == maskColor->green &&
  590.       pCursor->backBlue == maskColor->blue) ||
  591.      pScreenPriv->pColormap != pScreenPriv->pInstalledMap)
  592.     {
  593.     pScreenPriv->pColormap = pScreenPriv->pInstalledMap;
  594.     sourceColor->red = pCursor->foreRed;
  595.     sourceColor->green = pCursor->foreGreen;
  596.     sourceColor->blue = pCursor->foreBlue;
  597.     FakeAllocColor (pScreenPriv->pColormap, sourceColor);
  598.     maskColor->red = pCursor->backRed;
  599.     maskColor->green = pCursor->backGreen;
  600.     maskColor->blue = pCursor->backBlue;
  601.     FakeAllocColor (pScreenPriv->pColormap, maskColor);
  602.     /* "free" the pixels right away, don't let this confuse you */
  603.     FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel);
  604.     FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel);
  605.     }
  606.     pScreenPriv->checkPixels = FALSE;
  607. }
  608.  
  609. /*
  610.  * BackingStore wrappers
  611.  */
  612.  
  613. static void
  614. miSpriteSaveDoomedAreas (pWin, pObscured, dx, dy)
  615.     WindowPtr    pWin;
  616.     RegionPtr    pObscured;
  617.     int        dx, dy;
  618. {
  619.     ScreenPtr        pScreen;
  620.     miSpriteScreenPtr   pScreenPriv;
  621.     BoxRec        cursorBox;
  622.  
  623.     pScreen = pWin->drawable.pScreen;
  624.     
  625.     SCREEN_PROLOGUE (pScreen, SaveDoomedAreas);
  626.  
  627.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  628.     if (pScreenPriv->isUp)
  629.     {
  630.     cursorBox = pScreenPriv->saved;
  631.  
  632.     if (dx || dy)
  633.      {
  634.         cursorBox.x1 += dx;
  635.         cursorBox.y1 += dy;
  636.         cursorBox.x2 += dx;
  637.         cursorBox.y2 += dy;
  638.     }
  639.     if ((* pScreen->RectIn) (pObscured, &cursorBox) != rgnOUT)
  640.         miSpriteRemoveCursor (pScreen);
  641.     }
  642.  
  643.     (*pScreen->SaveDoomedAreas) (pWin, pObscured, dx, dy);
  644.  
  645.     SCREEN_EPILOGUE (pScreen, SaveDoomedAreas, miSpriteSaveDoomedAreas);
  646. }
  647.  
  648. static RegionPtr
  649. miSpriteRestoreAreas (pWin, prgnExposed)
  650.     WindowPtr    pWin;
  651.     RegionPtr    prgnExposed;
  652. {
  653.     ScreenPtr        pScreen;
  654.     miSpriteScreenPtr   pScreenPriv;
  655.     RegionPtr        result;
  656.  
  657.     pScreen = pWin->drawable.pScreen;
  658.     
  659.     SCREEN_PROLOGUE (pScreen, RestoreAreas);
  660.  
  661.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  662.     if (pScreenPriv->isUp)
  663.     {
  664.     if ((* pScreen->RectIn) (prgnExposed, &pScreenPriv->saved) != rgnOUT)
  665.         miSpriteRemoveCursor (pScreen);
  666.     }
  667.  
  668.     result = (*pScreen->RestoreAreas) (pWin, prgnExposed);
  669.  
  670.     SCREEN_EPILOGUE (pScreen, RestoreAreas, miSpriteRestoreAreas);
  671.  
  672.     return result;
  673. }
  674.  
  675. /*
  676.  * Window wrappers
  677.  */
  678.  
  679. static void
  680. miSpritePaintWindowBackground (pWin, pRegion, what)
  681.     WindowPtr    pWin;
  682.     RegionPtr    pRegion;
  683.     int        what;
  684. {
  685.     ScreenPtr        pScreen;
  686.     miSpriteScreenPtr    pScreenPriv;
  687.  
  688.     pScreen = pWin->drawable.pScreen;
  689.  
  690.     SCREEN_PROLOGUE (pScreen, PaintWindowBackground);
  691.  
  692.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  693.     if (pScreenPriv->isUp)
  694.     {
  695.     /*
  696.      * If the cursor is on the same screen as the window, check the
  697.      * region to paint for the cursor and remove it as necessary
  698.      */
  699.     if ((* pScreen->RectIn) (pRegion, &pScreenPriv->saved) != rgnOUT)
  700.         miSpriteRemoveCursor (pScreen);
  701.     }
  702.  
  703.     (*pScreen->PaintWindowBackground) (pWin, pRegion, what);
  704.  
  705.     SCREEN_EPILOGUE (pScreen, PaintWindowBackground, miSpritePaintWindowBackground);
  706. }
  707.  
  708. static void
  709. miSpritePaintWindowBorder (pWin, pRegion, what)
  710.     WindowPtr    pWin;
  711.     RegionPtr    pRegion;
  712.     int        what;
  713. {
  714.     ScreenPtr        pScreen;
  715.     miSpriteScreenPtr    pScreenPriv;
  716.  
  717.     pScreen = pWin->drawable.pScreen;
  718.  
  719.     SCREEN_PROLOGUE (pScreen, PaintWindowBorder);
  720.  
  721.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  722.     if (pScreenPriv->isUp)
  723.     {
  724.     /*
  725.      * If the cursor is on the same screen as the window, check the
  726.      * region to paint for the cursor and remove it as necessary
  727.      */
  728.     if ((* pScreen->RectIn) (pRegion, &pScreenPriv->saved) != rgnOUT)
  729.         miSpriteRemoveCursor (pScreen);
  730.     }
  731.  
  732.     (*pScreen->PaintWindowBorder) (pWin, pRegion, what);
  733.  
  734.     SCREEN_EPILOGUE (pScreen, PaintWindowBorder, miSpritePaintWindowBorder);
  735. }
  736.  
  737. static void
  738. miSpriteCopyWindow (pWin, ptOldOrg, pRegion)
  739.     WindowPtr    pWin;
  740.     DDXPointRec    ptOldOrg;
  741.     RegionPtr    pRegion;
  742. {
  743.     ScreenPtr        pScreen;
  744.     miSpriteScreenPtr    pScreenPriv;
  745.     BoxRec        cursorBox;
  746.     int            dx, dy;
  747.  
  748.     pScreen = pWin->drawable.pScreen;
  749.  
  750.     SCREEN_PROLOGUE (pScreen, CopyWindow);
  751.  
  752.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  753.     if (pScreenPriv->isUp)
  754.     {
  755.     /*
  756.      * check both the source and the destination areas.  The given
  757.      * region is source relative, so offset the cursor box by
  758.      * the delta position
  759.      */
  760.     cursorBox = pScreenPriv->saved;
  761.     dx = pWin->drawable.x - ptOldOrg.x;
  762.     dy = pWin->drawable.y - ptOldOrg.y;
  763.     cursorBox.x1 -= dx;
  764.     cursorBox.x2 -= dx;
  765.     cursorBox.y1 -= dy;
  766.     cursorBox.y2 -= dy;
  767.     if ((* pScreen->RectIn) (pRegion, &pScreenPriv->saved) != rgnOUT ||
  768.         (* pScreen->RectIn) (pRegion, &cursorBox) != rgnOUT)
  769.         miSpriteRemoveCursor (pScreen);
  770.     }
  771.  
  772.     (*pScreen->CopyWindow) (pWin, ptOldOrg, pRegion);
  773.  
  774.     SCREEN_EPILOGUE (pScreen, CopyWindow, miSpriteCopyWindow);
  775. }
  776.  
  777. static void
  778. miSpriteClearToBackground (pWin, x, y, w, h, generateExposures)
  779.     WindowPtr pWin;
  780.     short x,y;
  781.     unsigned short w,h;
  782.     Bool generateExposures;
  783. {
  784.     ScreenPtr        pScreen;
  785.     miSpriteScreenPtr    pScreenPriv;
  786.     int            realw, realh;
  787.  
  788.     pScreen = pWin->drawable.pScreen;
  789.  
  790.     SCREEN_PROLOGUE (pScreen, ClearToBackground);
  791.  
  792.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  793.     if (GC_CHECK(pWin))
  794.     {
  795.     if (!(realw = w))
  796.         realw = (int) pWin->drawable.width - x;
  797.     if (!(realh = h))
  798.         realh = (int) pWin->drawable.height - y;
  799.     if (ORG_OVERLAP(&pScreenPriv->saved, pWin->drawable.x, pWin->drawable.y,
  800.             x, y, realw, realh))
  801.     {
  802.         miSpriteRemoveCursor (pScreen);
  803.     }
  804.     }
  805.  
  806.     (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures);
  807.  
  808.     SCREEN_EPILOGUE (pScreen, ClearToBackground, miSpriteClearToBackground);
  809. }
  810.  
  811. /*
  812.  * GC Func wrappers
  813.  */
  814.  
  815. static void
  816. miSpriteValidateGC (pGC, changes, pDrawable)
  817.     GCPtr    pGC;
  818.     Mask    changes;
  819.     DrawablePtr    pDrawable;
  820. {
  821.     GC_FUNC_PROLOGUE (pGC);
  822.  
  823.     (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);
  824.     
  825.     pGCPriv->wrapOps = NULL;
  826.     if (pDrawable->type == DRAWABLE_WINDOW && ((WindowPtr) pDrawable)->viewable)
  827.     {
  828.     WindowPtr   pWin;
  829.     RegionPtr   pRegion;
  830.  
  831.     pWin = (WindowPtr) pDrawable;
  832.     pRegion = &pWin->clipList;
  833.     if (pGC->subWindowMode == IncludeInferiors)
  834.         pRegion = &pWin->borderClip;
  835.     if ((*pDrawable->pScreen->RegionNotEmpty) (pRegion))
  836.         pGCPriv->wrapOps = pGC->ops;
  837.     }
  838.  
  839.     GC_FUNC_EPILOGUE (pGC);
  840. }
  841.  
  842. static void
  843. miSpriteChangeGC (pGC, mask)
  844.     GCPtr        pGC;
  845.     unsigned long   mask;
  846. {
  847.     GC_FUNC_PROLOGUE (pGC);
  848.  
  849.     (*pGC->funcs->ChangeGC) (pGC, mask);
  850.     
  851.     GC_FUNC_EPILOGUE (pGC);
  852. }
  853.  
  854. static void
  855. miSpriteCopyGC (pGCSrc, mask, pGCDst)
  856.     GCPtr        pGCSrc, pGCDst;
  857.     unsigned long   mask;
  858. {
  859.     GC_FUNC_PROLOGUE (pGCDst);
  860.  
  861.     (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
  862.     
  863.     GC_FUNC_EPILOGUE (pGCDst);
  864. }
  865.  
  866. static void
  867. miSpriteDestroyGC (pGC)
  868.     GCPtr   pGC;
  869. {
  870.     GC_FUNC_PROLOGUE (pGC);
  871.  
  872.     (*pGC->funcs->DestroyGC) (pGC);
  873.     
  874.     GC_FUNC_EPILOGUE (pGC);
  875. }
  876.  
  877. static void
  878. miSpriteChangeClip (pGC, type, pvalue, nrects)
  879.     GCPtr   pGC;
  880.     int        type;
  881.     pointer    pvalue;
  882.     int        nrects;
  883. {
  884.     GC_FUNC_PROLOGUE (pGC);
  885.  
  886.     (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
  887.  
  888.     GC_FUNC_EPILOGUE (pGC);
  889. }
  890.  
  891. static void
  892. miSpriteCopyClip(pgcDst, pgcSrc)
  893.     GCPtr pgcDst, pgcSrc;
  894. {
  895.     GC_FUNC_PROLOGUE (pgcDst);
  896.  
  897.     (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
  898.  
  899.     GC_FUNC_EPILOGUE (pgcDst);
  900. }
  901.  
  902. static void
  903. miSpriteDestroyClip(pGC)
  904.     GCPtr    pGC;
  905. {
  906.     GC_FUNC_PROLOGUE (pGC);
  907.  
  908.     (* pGC->funcs->DestroyClip)(pGC);
  909.  
  910.     GC_FUNC_EPILOGUE (pGC);
  911. }
  912.  
  913. /*
  914.  * GC Op wrappers
  915.  */
  916.  
  917. static void
  918. miSpriteFillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted)
  919.     DrawablePtr pDrawable;
  920.     GCPtr    pGC;
  921.     int        nInit;            /* number of spans to fill */
  922.     DDXPointPtr pptInit;        /* pointer to list of start points */
  923.     int        *pwidthInit;        /* pointer to list of n widths */
  924.     int     fSorted;
  925. {
  926.     GC_SETUP(pDrawable, pGC);
  927.  
  928.     if (GC_CHECK((WindowPtr) pDrawable))
  929.     {
  930.     register DDXPointPtr    pts;
  931.     register int        *widths;
  932.     register int        nPts;
  933.  
  934.     for (pts = pptInit, widths = pwidthInit, nPts = nInit;
  935.          nPts--;
  936.          pts++, widths++)
  937.      {
  938.          if (SPN_OVERLAP(&pScreenPriv->saved,pts->y,pts->x,*widths))
  939.          {
  940.          miSpriteRemoveCursor (pDrawable->pScreen);
  941.          break;
  942.          }
  943.     }
  944.     }
  945.  
  946.     GC_OP_PROLOGUE (pGC);
  947.  
  948.     (*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
  949.  
  950.     GC_OP_EPILOGUE (pGC);
  951. }
  952.  
  953. static void
  954. miSpriteSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted)
  955.     DrawablePtr        pDrawable;
  956.     GCPtr        pGC;
  957.     int            *psrc;
  958.     register DDXPointPtr ppt;
  959.     int            *pwidth;
  960.     int            nspans;
  961.     int            fSorted;
  962. {
  963.     GC_SETUP(pDrawable, pGC);
  964.  
  965.     if (GC_CHECK((WindowPtr) pDrawable))
  966.     {
  967.     register DDXPointPtr    pts;
  968.     register int        *widths;
  969.     register int        nPts;
  970.  
  971.     for (pts = ppt, widths = pwidth, nPts = nspans;
  972.          nPts--;
  973.          pts++, widths++)
  974.      {
  975.          if (SPN_OVERLAP(&pScreenPriv->saved,pts->y,pts->x,*widths))
  976.          {
  977.          miSpriteRemoveCursor(pDrawable->pScreen);
  978.          break;
  979.          }
  980.     }
  981.     }
  982.  
  983.     GC_OP_PROLOGUE (pGC);
  984.  
  985.     (*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
  986.  
  987.     GC_OP_EPILOGUE (pGC);
  988. }
  989.  
  990. static void
  991. miSpritePutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits)
  992.     DrawablePtr      pDrawable;
  993.     GCPtr         pGC;
  994.     int          depth;
  995.     int              x;
  996.     int              y;
  997.     int              w;
  998.     int              h;
  999.     int              format;
  1000.     char          *pBits;
  1001. {
  1002.     GC_SETUP(pDrawable, pGC);
  1003.  
  1004.     if (GC_CHECK((WindowPtr) pDrawable))
  1005.     {
  1006.     if (ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y,
  1007.             x,y,w,h))
  1008.      {
  1009.         miSpriteRemoveCursor (pDrawable->pScreen);
  1010.     }
  1011.     }
  1012.  
  1013.     GC_OP_PROLOGUE (pGC);
  1014.  
  1015.     (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits);
  1016.  
  1017.     GC_OP_EPILOGUE (pGC);
  1018. }
  1019.  
  1020. static RegionPtr
  1021. miSpriteCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty)
  1022.     DrawablePtr      pSrc;
  1023.     DrawablePtr      pDst;
  1024.     GCPtr         pGC;
  1025.     int              srcx;
  1026.     int              srcy;
  1027.     int              w;
  1028.     int              h;
  1029.     int              dstx;
  1030.     int              dsty;
  1031. {
  1032.     RegionPtr rgn;
  1033.  
  1034.     GC_SETUP(pDst, pGC);
  1035.  
  1036.     /* check destination/source overlap. */
  1037.     if (GC_CHECK((WindowPtr) pDst) &&
  1038.      (ORG_OVERLAP(&pScreenPriv->saved,pDst->x,pDst->y,dstx,dsty,w,h) ||
  1039.       ((pDst == pSrc) &&
  1040.        ORG_OVERLAP(&pScreenPriv->saved,pSrc->x,pSrc->y,srcx,srcy,w,h))))
  1041.     {
  1042.     miSpriteRemoveCursor (pDst->pScreen);
  1043.     }
  1044.  
  1045.     GC_OP_PROLOGUE (pGC);
  1046.  
  1047.     rgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h,
  1048.                  dstx, dsty);
  1049.  
  1050.     GC_OP_EPILOGUE (pGC);
  1051.  
  1052.     return rgn;
  1053. }
  1054.  
  1055. static RegionPtr
  1056. miSpriteCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane)
  1057.     DrawablePtr      pSrc;
  1058.     DrawablePtr      pDst;
  1059.     register GC   *pGC;
  1060.     int           srcx,
  1061.           srcy;
  1062.     int           w,
  1063.           h;
  1064.     int           dstx,
  1065.           dsty;
  1066.     unsigned long  plane;
  1067. {
  1068.     RegionPtr rgn;
  1069.  
  1070.     GC_SETUP(pDst, pGC);
  1071.  
  1072.     /*
  1073.      * check destination/source for overlap.
  1074.      */
  1075.     if (GC_CHECK((WindowPtr) pDst) &&
  1076.     (ORG_OVERLAP(&pScreenPriv->saved,pDst->x,pDst->y,dstx,dsty,w,h) ||
  1077.      ((pDst == pSrc) &&
  1078.       ORG_OVERLAP(&pScreenPriv->saved,pSrc->x,pSrc->y,srcx,srcy,w,h))))
  1079.     {
  1080.     miSpriteRemoveCursor (pDst->pScreen);
  1081.     }
  1082.  
  1083.     GC_OP_PROLOGUE (pGC);
  1084.  
  1085.     rgn = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h,
  1086.                   dstx, dsty, plane);
  1087.  
  1088.     GC_OP_EPILOGUE (pGC);
  1089.  
  1090.     return rgn;
  1091. }
  1092.  
  1093. static void
  1094. miSpritePolyPoint (pDrawable, pGC, mode, npt, pptInit)
  1095.     DrawablePtr pDrawable;
  1096.     GCPtr    pGC;
  1097.     int        mode;        /* Origin or Previous */
  1098.     int        npt;
  1099.     xPoint     *pptInit;
  1100. {
  1101.     xPoint    t;
  1102.     int        n;
  1103.     BoxRec    cursor;
  1104.     register xPoint *pts;
  1105.  
  1106.     GC_SETUP (pDrawable, pGC);
  1107.  
  1108.     if (npt && GC_CHECK((WindowPtr) pDrawable))
  1109.     {
  1110.     cursor.x1 = pScreenPriv->saved.x1 - pDrawable->x;
  1111.     cursor.y1 = pScreenPriv->saved.y1 - pDrawable->y;
  1112.     cursor.x2 = pScreenPriv->saved.x2 - pDrawable->x;
  1113.     cursor.y2 = pScreenPriv->saved.y2 - pDrawable->y;
  1114.  
  1115.     if (mode == CoordModePrevious)
  1116.     {
  1117.         t.x = 0;
  1118.         t.y = 0;
  1119.         for (pts = pptInit, n = npt; n--; pts++)
  1120.         {
  1121.         t.x += pts->x;
  1122.         t.y += pts->y;
  1123.         if (cursor.x1 <= t.x && t.x <= cursor.x2 &&
  1124.             cursor.y1 <= t.y && t.y <= cursor.y2)
  1125.         {
  1126.             miSpriteRemoveCursor (pDrawable->pScreen);
  1127.             break;
  1128.         }
  1129.         }
  1130.     }
  1131.     else
  1132.     {
  1133.         for (pts = pptInit, n = npt; n--; pts++)
  1134.         {
  1135.         if (cursor.x1 <= pts->x && pts->x <= cursor.x2 &&
  1136.             cursor.y1 <= pts->y && pts->y <= cursor.y2)
  1137.         {
  1138.             miSpriteRemoveCursor (pDrawable->pScreen);
  1139.             break;
  1140.         }
  1141.         }
  1142.     }
  1143.     }
  1144.  
  1145.     GC_OP_PROLOGUE (pGC);
  1146.  
  1147.     (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pptInit);
  1148.  
  1149.     GC_OP_EPILOGUE (pGC);
  1150. }
  1151.  
  1152. static void
  1153. miSpritePolylines (pDrawable, pGC, mode, npt, pptInit)
  1154.     DrawablePtr      pDrawable;
  1155.     GCPtr         pGC;
  1156.     int              mode;
  1157.     int              npt;
  1158.     DDXPointPtr      pptInit;
  1159. {
  1160.     BoxPtr  cursor;
  1161.     register DDXPointPtr pts;
  1162.     int        n;
  1163.     int        x, y, x1, y1, x2, y2;
  1164.     int        lw;
  1165.     int        extra;
  1166.  
  1167.     GC_SETUP (pDrawable, pGC);
  1168.  
  1169.     if (npt && GC_CHECK((WindowPtr) pDrawable))
  1170.     {
  1171.     cursor = &pScreenPriv->saved;
  1172.     lw = pGC->lineWidth;
  1173.     x = pptInit->x + pDrawable->x;
  1174.     y = pptInit->y + pDrawable->y;
  1175.  
  1176.     if (npt == 1)
  1177.     {
  1178.         extra = lw >> 1;
  1179.         if (LINE_OVERLAP(cursor, x, y, x, y, extra))
  1180.         miSpriteRemoveCursor (pDrawable->pScreen);
  1181.     }
  1182.     else
  1183.     {
  1184.         extra = lw >> 1;
  1185.         /*
  1186.          * mitered joins can project quite a way from
  1187.          * the line end; the 11 degree miter limit limits
  1188.          * this extension to 10.43 * lw / 2, rounded up
  1189.          * and converted to int yields 6 * lw
  1190.          */
  1191.         if (pGC->joinStyle == JoinMiter)
  1192.         extra = 6 * lw;
  1193.         else if (pGC->capStyle == CapProjecting)
  1194.         extra = lw;
  1195.         for (pts = pptInit + 1, n = npt - 1; n--; pts++)
  1196.         {
  1197.         x1 = x;
  1198.         y1 = y;
  1199.         if (mode == CoordModeOrigin)
  1200.         {
  1201.             x2 = pDrawable->x + pts->x;
  1202.             y2 = pDrawable->y + pts->y;
  1203.         }
  1204.         else
  1205.         {
  1206.             x2 = x + pts->x;
  1207.             y2 = y + pts->y;
  1208.         }
  1209.         x = x2;
  1210.         y = y2;
  1211.         LINE_SORT(x1, y1, x2, y2);
  1212.         if (LINE_OVERLAP(cursor, x1, y1, x2, y2, extra))
  1213.         {
  1214.             miSpriteRemoveCursor (pDrawable->pScreen);
  1215.             break;
  1216.         }
  1217.         }
  1218.     }
  1219.     }
  1220.     GC_OP_PROLOGUE (pGC);
  1221.  
  1222.     (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, pptInit);
  1223.  
  1224.     GC_OP_EPILOGUE (pGC);
  1225. }
  1226.  
  1227. static void
  1228. miSpritePolySegment(pDrawable, pGC, nseg, pSegs)
  1229.     DrawablePtr pDrawable;
  1230.     GCPtr     pGC;
  1231.     int        nseg;
  1232.     xSegment    *pSegs;
  1233. {
  1234.     int        n;
  1235.     register xSegment *segs;
  1236.     BoxPtr  cursor;
  1237.     int        x1, y1, x2, y2;
  1238.     int        extra;
  1239.  
  1240.     GC_SETUP(pDrawable, pGC);
  1241.  
  1242.     if (nseg && GC_CHECK((WindowPtr) pDrawable))
  1243.     {
  1244.     cursor = &pScreenPriv->saved;
  1245.     extra = pGC->lineWidth >> 1;
  1246.     if (pGC->capStyle == CapProjecting)
  1247.         extra = pGC->lineWidth;
  1248.     for (segs = pSegs, n = nseg; n--; segs++)
  1249.     {
  1250.         x1 = segs->x1 + pDrawable->x;
  1251.         y1 = segs->y1 + pDrawable->y;
  1252.         x2 = segs->x2 + pDrawable->x;
  1253.         y2 = segs->y2 + pDrawable->y;
  1254.         LINE_SORT(x1, y1, x2, y2);
  1255.         if (LINE_OVERLAP(cursor, x1, y1, x2, y2, extra))
  1256.         {
  1257.         miSpriteRemoveCursor (pDrawable->pScreen);
  1258.         break;
  1259.         }
  1260.     }
  1261.     }
  1262.  
  1263.     GC_OP_PROLOGUE (pGC);
  1264.  
  1265.     (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, pSegs);
  1266.  
  1267.     GC_OP_EPILOGUE (pGC);
  1268. }
  1269.  
  1270. static void
  1271. miSpritePolyRectangle(pDrawable, pGC, nrects, pRects)
  1272.     DrawablePtr    pDrawable;
  1273.     GCPtr    pGC;
  1274.     int        nrects;
  1275.     xRectangle    *pRects;
  1276. {
  1277.     register xRectangle *rects;
  1278.     BoxPtr  cursor;
  1279.     int        lw;
  1280.     int        n;
  1281.     int     x1, y1, x2, y2;
  1282.     
  1283.     GC_SETUP (pDrawable, pGC);
  1284.  
  1285.     if (GC_CHECK((WindowPtr) pDrawable))
  1286.     {
  1287.     lw = pGC->lineWidth >> 1;
  1288.     cursor = &pScreenPriv->saved;
  1289.     for (rects = pRects, n = nrects; n--; rects++)
  1290.     {
  1291.         x1 = rects->x + pDrawable->x;
  1292.         y1 = rects->y + pDrawable->y;
  1293.         x2 = x1 + (int)rects->width;
  1294.         y2 = y1 + (int)rects->height;
  1295.         if (LINE_OVERLAP(cursor, x1, y1, x2, y1, lw) ||
  1296.         LINE_OVERLAP(cursor, x2, y1, x2, y2, lw) ||
  1297.         LINE_OVERLAP(cursor, x1, y2, x2, y2, lw) ||
  1298.         LINE_OVERLAP(cursor, x1, y1, x1, y2, lw))
  1299.         {
  1300.         miSpriteRemoveCursor (pDrawable->pScreen);
  1301.         break;
  1302.         }
  1303.     }
  1304.     }
  1305.  
  1306.     GC_OP_PROLOGUE (pGC);
  1307.  
  1308.     (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, pRects);
  1309.  
  1310.     GC_OP_EPILOGUE (pGC);
  1311. }
  1312.  
  1313. static void
  1314. miSpritePolyArc(pDrawable, pGC, narcs, parcs)
  1315.     DrawablePtr    pDrawable;
  1316.     register GCPtr    pGC;
  1317.     int        narcs;
  1318.     xArc    *parcs;
  1319. {
  1320.     BoxPtr  cursor;
  1321.     int        lw;
  1322.     int        n;
  1323.     register xArc *arcs;
  1324.     
  1325.     GC_SETUP (pDrawable, pGC);
  1326.  
  1327.     if (GC_CHECK((WindowPtr) pDrawable))
  1328.     {
  1329.     lw = pGC->lineWidth >> 1;
  1330.     cursor = &pScreenPriv->saved;
  1331.     for (arcs = parcs, n = narcs; n--; arcs++)
  1332.     {
  1333.         if (ORG_OVERLAP (cursor, pDrawable->x, pDrawable->y,
  1334.                  arcs->x - lw, arcs->y - lw,
  1335.                  (int) arcs->width + pGC->lineWidth,
  1336.                   (int) arcs->height + pGC->lineWidth))
  1337.         {
  1338.         miSpriteRemoveCursor (pDrawable->pScreen);
  1339.         break;
  1340.         }
  1341.     }
  1342.     }
  1343.  
  1344.     GC_OP_PROLOGUE (pGC);
  1345.  
  1346.     (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, parcs);
  1347.  
  1348.     GC_OP_EPILOGUE (pGC);
  1349. }
  1350.  
  1351. static void
  1352. miSpriteFillPolygon(pDrawable, pGC, shape, mode, count, pPts)
  1353.     register DrawablePtr pDrawable;
  1354.     register GCPtr    pGC;
  1355.     int            shape, mode;
  1356.     int            count;
  1357.     DDXPointPtr        pPts;
  1358. {
  1359.     int x, y, minx, miny, maxx, maxy;
  1360.     register DDXPointPtr pts;
  1361.     int n;
  1362.  
  1363.     GC_SETUP (pDrawable, pGC);
  1364.  
  1365.     if (count && GC_CHECK((WindowPtr) pDrawable))
  1366.     {
  1367.     x = pDrawable->x;
  1368.     y = pDrawable->y;
  1369.     pts = pPts;
  1370.     minx = maxx = pts->x;
  1371.     miny = maxy = pts->y;
  1372.     pts++;
  1373.     n = count - 1;
  1374.  
  1375.     if (mode == CoordModeOrigin)
  1376.     {
  1377.         for (; n--; pts++)
  1378.         {
  1379.         if (pts->x < minx)
  1380.             minx = pts->x;
  1381.         else if (pts->x > maxx)
  1382.             maxx = pts->x;
  1383.         if (pts->y < miny)
  1384.             miny = pts->y;
  1385.         else if (pts->y > maxy)
  1386.             maxy = pts->y;
  1387.         }
  1388.         minx += x;
  1389.         miny += y;
  1390.         maxx += x;
  1391.         maxy += y;
  1392.     }
  1393.     else
  1394.     {
  1395.         x += minx;
  1396.         y += miny;
  1397.         minx = maxx = x;
  1398.         miny = maxy = y;
  1399.         for (; n--; pts++)
  1400.         {
  1401.         x += pts->x;
  1402.         y += pts->y;
  1403.         if (x < minx)
  1404.             minx = x;
  1405.         else if (x > maxx)
  1406.             maxx = x;
  1407.         if (y < miny)
  1408.             miny = y;
  1409.         else if (y > maxy)
  1410.             maxy = y;
  1411.         }
  1412.     }
  1413.     if (BOX_OVERLAP(&pScreenPriv->saved,minx,miny,maxx,maxy))
  1414.         miSpriteRemoveCursor (pDrawable->pScreen);
  1415.     }
  1416.  
  1417.     GC_OP_PROLOGUE (pGC);
  1418.  
  1419.     (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pPts);
  1420.  
  1421.     GC_OP_EPILOGUE (pGC);
  1422. }
  1423.  
  1424. static void
  1425. miSpritePolyFillRect(pDrawable, pGC, nrectFill, prectInit)
  1426.     DrawablePtr pDrawable;
  1427.     GCPtr    pGC;
  1428.     int        nrectFill;     /* number of rectangles to fill */
  1429.     xRectangle    *prectInit;      /* Pointer to first rectangle to fill */
  1430. {
  1431.     GC_SETUP(pDrawable, pGC);
  1432.  
  1433.     if (GC_CHECK((WindowPtr) pDrawable))
  1434.     {
  1435.     register int        nRect;
  1436.     register xRectangle *pRect;
  1437.     register int        xorg, yorg;
  1438.  
  1439.     xorg = pDrawable->x;
  1440.     yorg = pDrawable->y;
  1441.  
  1442.     for (nRect = nrectFill, pRect = prectInit; nRect--; pRect++) {
  1443.         if (ORGRECT_OVERLAP(&pScreenPriv->saved,xorg,yorg,pRect)){
  1444.         miSpriteRemoveCursor(pDrawable->pScreen);
  1445.         break;
  1446.         }
  1447.     }
  1448.     }
  1449.  
  1450.     GC_OP_PROLOGUE (pGC);
  1451.  
  1452.     (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrectFill, prectInit);
  1453.  
  1454.     GC_OP_EPILOGUE (pGC);
  1455. }
  1456.  
  1457. static void
  1458. miSpritePolyFillArc(pDrawable, pGC, narcs, parcs)
  1459.     DrawablePtr    pDrawable;
  1460.     GCPtr    pGC;
  1461.     int        narcs;
  1462.     xArc    *parcs;
  1463. {
  1464.     GC_SETUP(pDrawable, pGC);
  1465.  
  1466.     if (GC_CHECK((WindowPtr) pDrawable))
  1467.     {
  1468.     register int    n;
  1469.     BoxPtr        cursor;
  1470.     register xArc *arcs;
  1471.  
  1472.     cursor = &pScreenPriv->saved;
  1473.  
  1474.     for (arcs = parcs, n = narcs; n--; arcs++)
  1475.     {
  1476.         if (ORG_OVERLAP(cursor, pDrawable->x, pDrawable->y,
  1477.                 arcs->x, arcs->y,
  1478.                  (int) arcs->width, (int) arcs->height))
  1479.         {
  1480.         miSpriteRemoveCursor (pDrawable->pScreen);
  1481.         break;
  1482.         }
  1483.     }
  1484.     }
  1485.  
  1486.     GC_OP_PROLOGUE (pGC);
  1487.  
  1488.     (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, parcs);
  1489.  
  1490.     GC_OP_EPILOGUE (pGC);
  1491. }
  1492.  
  1493. /*
  1494.  * general Poly/Image text function.  Extract glyph information,
  1495.  * compute bounding box and remove cursor if it is overlapped.
  1496.  */
  1497.  
  1498. static Bool
  1499. miSpriteTextOverlap (pDraw, font, x, y, n, charinfo, imageblt, w, cursorBox)
  1500.     DrawablePtr   pDraw;
  1501.     FontPtr      font;
  1502.     int          x, y;
  1503.     unsigned long n;
  1504.     CharInfoPtr   *charinfo;
  1505.     Bool      imageblt;
  1506.     unsigned int  w;
  1507.     BoxPtr      cursorBox;
  1508. {
  1509.     ExtentInfoRec extents;
  1510.  
  1511.     x += pDraw->x;
  1512.     y += pDraw->y;
  1513.  
  1514.     if (FONTMINBOUNDS(font,characterWidth) >= 0)
  1515.     {
  1516.     /* compute an approximate (but covering) bounding box */
  1517.     if (!imageblt || (charinfo[0]->metrics.leftSideBearing < 0))
  1518.         extents.overallLeft = charinfo[0]->metrics.leftSideBearing;
  1519.     else
  1520.         extents.overallLeft = 0;
  1521.     if (w)
  1522.         extents.overallRight = w - charinfo[n-1]->metrics.characterWidth;
  1523.     else
  1524.         extents.overallRight = FONTMAXBOUNDS(font,characterWidth)
  1525.                     * (n - 1);
  1526.     if (imageblt && (charinfo[n-1]->metrics.characterWidth >
  1527.              charinfo[n-1]->metrics.rightSideBearing))
  1528.         extents.overallRight += charinfo[n-1]->metrics.characterWidth;
  1529.     else
  1530.         extents.overallRight += charinfo[n-1]->metrics.rightSideBearing;
  1531.     if (imageblt && FONTASCENT(font) > FONTMAXBOUNDS(font,ascent))
  1532.         extents.overallAscent = FONTASCENT(font);
  1533.     else
  1534.         extents.overallAscent = FONTMAXBOUNDS(font, ascent);
  1535.     if (imageblt && FONTDESCENT(font) > FONTMAXBOUNDS(font,descent))
  1536.         extents.overallDescent = FONTDESCENT(font);
  1537.     else
  1538.         extents.overallDescent = FONTMAXBOUNDS(font,descent);
  1539.     if (!BOX_OVERLAP(cursorBox,
  1540.              x + extents.overallLeft,
  1541.              y - extents.overallAscent,
  1542.              x + extents.overallRight,
  1543.              y + extents.overallDescent))
  1544.         return FALSE;
  1545.     else if (imageblt && w)
  1546.         return TRUE;
  1547.     /* if it does overlap, fall through and compute exactly, because
  1548.      * taking down the cursor is expensive enough to make this worth it
  1549.      */
  1550.     }
  1551.     QueryGlyphExtents(font, charinfo, n, &extents);
  1552.     if (imageblt)
  1553.     {
  1554.     if (extents.overallWidth > extents.overallRight)
  1555.         extents.overallRight = extents.overallWidth;
  1556.     if (extents.overallWidth < extents.overallLeft)
  1557.         extents.overallLeft = extents.overallWidth;
  1558.     if (extents.overallLeft > 0)
  1559.         extents.overallLeft = 0;
  1560.     if (extents.fontAscent > extents.overallAscent)
  1561.         extents.overallAscent = extents.fontAscent;
  1562.     if (extents.fontDescent > extents.overallDescent)
  1563.         extents.overallDescent = extents.fontDescent;
  1564.     }
  1565.     return (BOX_OVERLAP(cursorBox,
  1566.             x + extents.overallLeft,
  1567.             y - extents.overallAscent,
  1568.             x + extents.overallRight,
  1569.             y + extents.overallDescent));
  1570. }
  1571.  
  1572. /*
  1573.  * values for textType:
  1574.  */
  1575. #define TT_POLY8   0
  1576. #define TT_IMAGE8  1
  1577. #define TT_POLY16  2
  1578. #define TT_IMAGE16 3
  1579.  
  1580. static int 
  1581. miSpriteText (pDraw, pGC, x, y, count, chars, fontEncoding, textType, cursorBox)
  1582.     DrawablePtr        pDraw;
  1583.     GCPtr        pGC;
  1584.     int            x,
  1585.             y;
  1586.     unsigned long    count;
  1587.     char        *chars;
  1588.     FontEncoding    fontEncoding;
  1589.     Bool        textType;
  1590.     BoxPtr        cursorBox;
  1591. {
  1592.     CharInfoPtr *charinfo;
  1593.     register CharInfoPtr *info;
  1594.     unsigned long n, i;
  1595.     int          w;
  1596.     void          (*drawFunc)();
  1597.  
  1598.     Bool imageblt;
  1599.  
  1600.     imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16);
  1601.  
  1602.     charinfo = (CharInfoPtr *) ALLOCATE_LOCAL(count * sizeof(CharInfoPtr));
  1603.     if (!charinfo)
  1604.     return x;
  1605.  
  1606.     GetGlyphs(pGC->font, count, (unsigned char *)chars,
  1607.           fontEncoding, &n, charinfo);
  1608.     w = 0;
  1609.     if (!imageblt)
  1610.     for (info = charinfo, i = n; i--; info++)
  1611.         w += (*info)->metrics.characterWidth;
  1612.  
  1613.     if (n != 0) {
  1614.     if (miSpriteTextOverlap(pDraw, pGC->font, x, y, n, charinfo, imageblt, w, cursorBox))
  1615.         miSpriteRemoveCursor(pDraw->pScreen);
  1616.  
  1617. #ifdef AVOID_GLYPHBLT
  1618.     /*
  1619.      * On displays like Apollos, which do not optimize the GlyphBlt functions because they
  1620.      * convert fonts to their internal form in RealizeFont and optimize text directly, we
  1621.      * want to invoke the text functions here, not the GlyphBlt functions.
  1622.      */
  1623.     switch (textType)
  1624.     {
  1625.     case TT_POLY8:
  1626.         drawFunc = pGC->ops->PolyText8;
  1627.         break;
  1628.     case TT_IMAGE8:
  1629.         drawFunc = pGC->ops->ImageText8;
  1630.         break;
  1631.     case TT_POLY16:
  1632.         drawFunc = pGC->ops->PolyText16;
  1633.         break;
  1634.     case TT_IMAGE16:
  1635.         drawFunc = pGC->ops->ImageText16;
  1636.         break;
  1637.     }
  1638.     (*drawFunc) (pDraw, pGC, x, y, (int) count, chars);
  1639. #else /* don't AVOID_GLYPHBLT */
  1640.     /*
  1641.      * On the other hand, if the device does use GlyphBlt ultimately to do text, we
  1642.      * don't want to slow it down by invoking the text functions and having them call
  1643.      * GetGlyphs all over again, so we go directly to the GlyphBlt functions here.
  1644.      */
  1645.     drawFunc = imageblt ? pGC->ops->ImageGlyphBlt : pGC->ops->PolyGlyphBlt;
  1646.     (*drawFunc) (pDraw, pGC, x, y, n, charinfo, FONTGLYPHS(pGC->font));
  1647. #endif /* AVOID_GLYPHBLT */
  1648.     }
  1649.     DEALLOCATE_LOCAL(charinfo);
  1650.     return x + w;
  1651. }
  1652.  
  1653. static int
  1654. miSpritePolyText8(pDrawable, pGC, x, y, count, chars)
  1655.     DrawablePtr pDrawable;
  1656.     GCPtr    pGC;
  1657.     int        x, y;
  1658.     int     count;
  1659.     char    *chars;
  1660. {
  1661.     int    ret;
  1662.  
  1663.     GC_SETUP (pDrawable, pGC);
  1664.  
  1665.     GC_OP_PROLOGUE (pGC);
  1666.  
  1667.     if (GC_CHECK((WindowPtr) pDrawable))
  1668.     ret = miSpriteText (pDrawable, pGC, x, y, (unsigned long)count, chars,
  1669.                 Linear8Bit, TT_POLY8, &pScreenPriv->saved);
  1670.     else
  1671.     ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);
  1672.  
  1673.     GC_OP_EPILOGUE (pGC);
  1674.     return ret;
  1675. }
  1676.  
  1677. static int
  1678. miSpritePolyText16(pDrawable, pGC, x, y, count, chars)
  1679.     DrawablePtr pDrawable;
  1680.     GCPtr    pGC;
  1681.     int        x, y;
  1682.     int        count;
  1683.     unsigned short *chars;
  1684. {
  1685.     int    ret;
  1686.  
  1687.     GC_SETUP(pDrawable, pGC);
  1688.  
  1689.     GC_OP_PROLOGUE (pGC);
  1690.  
  1691.     if (GC_CHECK((WindowPtr) pDrawable))
  1692.     ret = miSpriteText (pDrawable, pGC, x, y, (unsigned long)count,
  1693.                 (char *)chars,
  1694.                 FONTLASTROW(pGC->font) == 0 ?
  1695.                 Linear16Bit : TwoD16Bit, TT_POLY16, &pScreenPriv->saved);
  1696.     else
  1697.     ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);
  1698.  
  1699.     GC_OP_EPILOGUE (pGC);
  1700.     return ret;
  1701. }
  1702.  
  1703. static void
  1704. miSpriteImageText8(pDrawable, pGC, x, y, count, chars)
  1705.     DrawablePtr pDrawable;
  1706.     GCPtr    pGC;
  1707.     int        x, y;
  1708.     int        count;
  1709.     char    *chars;
  1710. {
  1711.     GC_SETUP(pDrawable, pGC);
  1712.  
  1713.     GC_OP_PROLOGUE (pGC);
  1714.  
  1715.     if (GC_CHECK((WindowPtr) pDrawable))
  1716.     (void) miSpriteText (pDrawable, pGC, x, y, (unsigned long)count,
  1717.                  chars, Linear8Bit, TT_IMAGE8, &pScreenPriv->saved);
  1718.     else
  1719.     (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);
  1720.  
  1721.     GC_OP_EPILOGUE (pGC);
  1722. }
  1723.  
  1724. static void
  1725. miSpriteImageText16(pDrawable, pGC, x, y, count, chars)
  1726.     DrawablePtr pDrawable;
  1727.     GCPtr    pGC;
  1728.     int        x, y;
  1729.     int        count;
  1730.     unsigned short *chars;
  1731. {
  1732.     GC_SETUP(pDrawable, pGC);
  1733.  
  1734.     GC_OP_PROLOGUE (pGC);
  1735.  
  1736.     if (GC_CHECK((WindowPtr) pDrawable))
  1737.     (void) miSpriteText (pDrawable, pGC, x, y, (unsigned long)count,
  1738.                  (char *)chars,
  1739.                 FONTLASTROW(pGC->font) == 0 ?
  1740.                 Linear16Bit : TwoD16Bit, TT_IMAGE16, &pScreenPriv->saved);
  1741.     else
  1742.     (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);
  1743.  
  1744.     GC_OP_EPILOGUE (pGC);
  1745. }
  1746.  
  1747. static void
  1748. miSpriteImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
  1749.     DrawablePtr pDrawable;
  1750.     GC         *pGC;
  1751.     int     x, y;
  1752.     unsigned long nglyph;
  1753.     CharInfoPtr *ppci;        /* array of character info */
  1754.     pointer     pglyphBase;    /* start of array of glyphs */
  1755. {
  1756.     GC_SETUP(pDrawable, pGC);
  1757.  
  1758.     GC_OP_PROLOGUE (pGC);
  1759.  
  1760.     if (GC_CHECK((WindowPtr) pDrawable) &&
  1761.     miSpriteTextOverlap (pDrawable, pGC->font, x, y, nglyph, ppci, TRUE, 0, &pScreenPriv->saved))
  1762.     {
  1763.     miSpriteRemoveCursor(pDrawable->pScreen);
  1764.     }
  1765.     (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
  1766.  
  1767.     GC_OP_EPILOGUE (pGC);
  1768. }
  1769.  
  1770. static void
  1771. miSpritePolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
  1772.     DrawablePtr pDrawable;
  1773.     GCPtr    pGC;
  1774.     int     x, y;
  1775.     unsigned long nglyph;
  1776.     CharInfoPtr *ppci;        /* array of character info */
  1777.     char     *pglyphBase;    /* start of array of glyphs */
  1778. {
  1779.     GC_SETUP (pDrawable, pGC);
  1780.  
  1781.     GC_OP_PROLOGUE (pGC);
  1782.  
  1783.     if (GC_CHECK((WindowPtr) pDrawable) &&
  1784.     miSpriteTextOverlap (pDrawable, pGC->font, x, y, nglyph, ppci, FALSE, 0, &pScreenPriv->saved))
  1785.     {
  1786.     miSpriteRemoveCursor(pDrawable->pScreen);
  1787.     }
  1788.     (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
  1789.  
  1790.     GC_OP_EPILOGUE (pGC);
  1791. }
  1792.  
  1793. static void
  1794. miSpritePushPixels(pGC, pBitMap, pDrawable, w, h, x, y)
  1795.     GCPtr    pGC;
  1796.     PixmapPtr    pBitMap;
  1797.     DrawablePtr pDrawable;
  1798.     int        w, h, x, y;
  1799. {
  1800.     GC_SETUP(pDrawable, pGC);
  1801.  
  1802.     if (GC_CHECK((WindowPtr) pDrawable) &&
  1803.     ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y,x,y,w,h))
  1804.     {
  1805.     miSpriteRemoveCursor (pDrawable->pScreen);
  1806.     }
  1807.  
  1808.     GC_OP_PROLOGUE (pGC);
  1809.  
  1810.     (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y);
  1811.  
  1812.     GC_OP_EPILOGUE (pGC);
  1813. }
  1814.  
  1815. /*
  1816.  * I don't expect this routine will ever be called, as the GC
  1817.  * will have been unwrapped for the line drawing
  1818.  */
  1819.  
  1820. static void
  1821. miSpriteLineHelper()
  1822. {
  1823.     FatalError("miSpriteLineHelper called\n");
  1824. }
  1825.  
  1826. /*
  1827.  * miPointer interface routines
  1828.  */
  1829.  
  1830. #define SPRITE_PAD  8
  1831.  
  1832. static Bool
  1833. miSpriteRealizeCursor (pScreen, pCursor)
  1834.     ScreenPtr    pScreen;
  1835.     CursorPtr    pCursor;
  1836. {
  1837.     miSpriteScreenPtr    pScreenPriv;
  1838.  
  1839.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  1840.     if (pCursor == pScreenPriv->pCursor)
  1841.     pScreenPriv->checkPixels = TRUE;
  1842.     return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor);
  1843. }
  1844.  
  1845. static Bool
  1846. miSpriteUnrealizeCursor (pScreen, pCursor)
  1847.     ScreenPtr    pScreen;
  1848.     CursorPtr    pCursor;
  1849. {
  1850.     miSpriteScreenPtr    pScreenPriv;
  1851.  
  1852.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  1853.     return (*pScreenPriv->funcs->UnrealizeCursor) (pScreen, pCursor);
  1854. }
  1855.  
  1856. static void
  1857. miSpriteSetCursor (pScreen, pCursor, x, y)
  1858.     ScreenPtr    pScreen;
  1859.     CursorPtr    pCursor;
  1860. {
  1861.     miSpriteScreenPtr    pScreenPriv;
  1862.  
  1863.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  1864.     pScreenPriv->shouldBeUp = TRUE;
  1865.     if (pScreenPriv->x == x &&
  1866.     pScreenPriv->y == y &&
  1867.     pScreenPriv->pCursor == pCursor &&
  1868.     !pScreenPriv->checkPixels)
  1869.     {
  1870.     return;
  1871.     }
  1872.     if (!pCursor)
  1873.     {
  1874.         pScreenPriv->shouldBeUp = FALSE;
  1875.         if (pScreenPriv->isUp)
  1876.         miSpriteRemoveCursor (pScreen);
  1877.     pScreenPriv->pCursor = 0;
  1878.     return;
  1879.     }
  1880.     pScreenPriv->x = x;
  1881.     pScreenPriv->y = y;
  1882.     pScreenPriv->pCacheWin = NullWindow;
  1883.     if (pScreenPriv->checkPixels || pScreenPriv->pCursor != pCursor)
  1884.     {
  1885.     pScreenPriv->pCursor = pCursor;
  1886.     miSpriteFindColors (pScreen);
  1887.     }
  1888.     if (pScreenPriv->isUp) {
  1889.     int    sx, sy;
  1890.     /*
  1891.      * check to see if the old saved region
  1892.      * encloses the new sprite, in which case we use
  1893.      * the flicker-free MoveCursor primitive.
  1894.      */
  1895.     sx = pScreenPriv->x - (int)pCursor->bits->xhot;
  1896.     sy = pScreenPriv->y - (int)pCursor->bits->yhot;
  1897.     if (sx + (int) pCursor->bits->width >= pScreenPriv->saved.x1 &&
  1898.         sx < pScreenPriv->saved.x2 &&
  1899.         sy + (int) pCursor->bits->height >= pScreenPriv->saved.y1 &&
  1900.         sy < pScreenPriv->saved.y2 &&
  1901.         (int) pCursor->bits->width + (2 * SPRITE_PAD) ==
  1902.         pScreenPriv->saved.x2 - pScreenPriv->saved.x1 &&
  1903.         (int) pCursor->bits->height + (2 * SPRITE_PAD) ==
  1904.         pScreenPriv->saved.y2 - pScreenPriv->saved.y1
  1905.         )
  1906.     {
  1907.         pScreenPriv->isUp = FALSE;
  1908.         if (!(sx >= pScreenPriv->saved.x1 &&
  1909.                 sx + (int)pCursor->bits->width < pScreenPriv->saved.x2 &&
  1910.                 sy >= pScreenPriv->saved.y1 &&
  1911.                 sy + (int)pCursor->bits->height < pScreenPriv->saved.y2))
  1912.         {
  1913.         int oldx1, oldy1, dx, dy;
  1914.  
  1915.         oldx1 = pScreenPriv->saved.x1;
  1916.         oldy1 = pScreenPriv->saved.y1;
  1917.         dx = oldx1 - (sx - SPRITE_PAD);
  1918.         dy = oldy1 - (sy - SPRITE_PAD);
  1919.         pScreenPriv->saved.x1 -= dx;
  1920.         pScreenPriv->saved.y1 -= dy;
  1921.         pScreenPriv->saved.x2 -= dx;
  1922.         pScreenPriv->saved.y2 -= dy;
  1923.         (void) (*pScreenPriv->funcs->ChangeSave) (pScreen,
  1924.                 pScreenPriv->saved.x1,
  1925.                  pScreenPriv->saved.y1,
  1926.                 pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
  1927.                 pScreenPriv->saved.y2 - pScreenPriv->saved.y1,
  1928.                 dx, dy);
  1929.         }
  1930.         (void) (*pScreenPriv->funcs->MoveCursor) (pScreen, pCursor,
  1931.                   pScreenPriv->saved.x1,
  1932.                    pScreenPriv->saved.y1,
  1933.                   pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
  1934.                   pScreenPriv->saved.y2 - pScreenPriv->saved.y1,
  1935.                   sx - pScreenPriv->saved.x1,
  1936.                   sy - pScreenPriv->saved.y1,
  1937.                   pScreenPriv->colors[SOURCE_COLOR].pixel,
  1938.                   pScreenPriv->colors[MASK_COLOR].pixel);
  1939.         pScreenPriv->isUp = TRUE;
  1940.     }
  1941.     else
  1942.     {
  1943.         miSpriteRemoveCursor (pScreen);
  1944.     }
  1945.     }
  1946.     if (!pScreenPriv->isUp && pScreenPriv->pCursor)
  1947.     miSpriteRestoreCursor (pScreen);
  1948. }
  1949.  
  1950. static void
  1951. miSpriteMoveCursor (pScreen, x, y)
  1952.     ScreenPtr    pScreen;
  1953.     int        x, y;
  1954. {
  1955.     miSpriteScreenPtr    pScreenPriv;
  1956.  
  1957.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  1958.     miSpriteSetCursor (pScreen, pScreenPriv->pCursor, x, y);
  1959. }
  1960.  
  1961. /*
  1962.  * undraw/draw cursor
  1963.  */
  1964.  
  1965. static void
  1966. miSpriteRemoveCursor (pScreen)
  1967.     ScreenPtr    pScreen;
  1968. {
  1969.     miSpriteScreenPtr   pScreenPriv;
  1970.  
  1971.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  1972.     pScreenPriv->isUp = FALSE;
  1973.     pScreenPriv->pCacheWin = NullWindow;
  1974.     if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pScreen,
  1975.                      pScreenPriv->saved.x1,
  1976.                      pScreenPriv->saved.y1,
  1977.                      pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
  1978.                      pScreenPriv->saved.y2 - pScreenPriv->saved.y1))
  1979.     {
  1980.     pScreenPriv->isUp = TRUE;
  1981.     }
  1982. }
  1983.  
  1984. /*
  1985.  * Called from the block handler, restores the cursor
  1986.  * before waiting for something to do.
  1987.  */
  1988.  
  1989. static void
  1990. miSpriteRestoreCursor (pScreen)
  1991.     ScreenPtr    pScreen;
  1992. {
  1993.     miSpriteScreenPtr   pScreenPriv;
  1994.     int            x, y;
  1995.     CursorPtr        pCursor;
  1996.  
  1997.     miSpriteComputeSaved (pScreen);
  1998.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  1999.     pCursor = pScreenPriv->pCursor;
  2000.     x = pScreenPriv->x - (int)pCursor->bits->xhot;
  2001.     y = pScreenPriv->y - (int)pCursor->bits->yhot;
  2002.     if ((*pScreenPriv->funcs->SaveUnderCursor) (pScreen,
  2003.                       pScreenPriv->saved.x1,
  2004.                       pScreenPriv->saved.y1,
  2005.                       pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
  2006.                       pScreenPriv->saved.y2 - pScreenPriv->saved.y1))
  2007.     {
  2008.     if (pScreenPriv->checkPixels)
  2009.         miSpriteFindColors (pScreen);
  2010.     if ((*pScreenPriv->funcs->PutUpCursor) (pScreen, pCursor, x, y,
  2011.                   pScreenPriv->colors[SOURCE_COLOR].pixel,
  2012.                   pScreenPriv->colors[MASK_COLOR].pixel))
  2013.         pScreenPriv->isUp = TRUE;
  2014.     }
  2015. }
  2016.  
  2017. /*
  2018.  * compute the desired area of the screen to save
  2019.  */
  2020.  
  2021. static void
  2022. miSpriteComputeSaved (pScreen)
  2023.     ScreenPtr    pScreen;
  2024. {
  2025.     miSpriteScreenPtr   pScreenPriv;
  2026.     int            x, y, w, h;
  2027.     int            wpad, hpad;
  2028.     CursorPtr        pCursor;
  2029.  
  2030.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  2031.     pCursor = pScreenPriv->pCursor;
  2032.     x = pScreenPriv->x - (int)pCursor->bits->xhot;
  2033.     y = pScreenPriv->y - (int)pCursor->bits->yhot;
  2034.     w = pCursor->bits->width;
  2035.     h = pCursor->bits->height;
  2036.     wpad = SPRITE_PAD;
  2037.     hpad = SPRITE_PAD;
  2038.     pScreenPriv->saved.x1 = x - wpad;
  2039.     pScreenPriv->saved.y1 = y - hpad;
  2040.     pScreenPriv->saved.x2 = pScreenPriv->saved.x1 + w + wpad * 2;
  2041.     pScreenPriv->saved.y2 = pScreenPriv->saved.y1 + h + hpad * 2;
  2042. }
  2043.