home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / server / dix / window.c.orig < prev    next >
Encoding:
Text File  |  1993-07-21  |  112.1 KB  |  4,465 lines

  1. /***********************************************************
  2. Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
  3. and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its 
  8. documentation for any purpose and without fee is hereby granted, 
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in 
  11. supporting documentation, and that the names of Digital or MIT not be
  12. used in advertising or publicity pertaining to distribution of the
  13. software without specific, written prior permission.  
  14.  
  15. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  16. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  17. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  18. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  19. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  20. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  21. SOFTWARE.
  22.  
  23. ******************************************************************/
  24.  
  25. /* $XConsortium: window.c,v 5.77 91/09/17 11:02:41 keith Exp $ */
  26.  
  27. #include "X.h"
  28. #define NEED_REPLIES
  29. #define NEED_EVENTS
  30. #include "Xproto.h"
  31. #include "misc.h"
  32. #include "scrnintstr.h"
  33. #include "os.h"
  34. #include "regionstr.h"
  35. #include "validate.h"
  36. #include "windowstr.h"
  37. #include "input.h"
  38. #include "resource.h"
  39. #include "colormapst.h"
  40. #include "cursorstr.h"
  41. #include "dixstruct.h"
  42. #include "gcstruct.h"
  43. #include "servermd.h"
  44.  
  45. extern Bool permitOldBugs;
  46.  
  47. /******
  48.  * Window stuff for server 
  49.  *
  50.  *    CreateRootWindow, CreateWindow, ChangeWindowAttributes,
  51.  *    GetWindowAttributes, DeleteWindow, DestroySubWindows,
  52.  *    HandleSaveSet, ReparentWindow, MapWindow, MapSubWindows,
  53.  *    UnmapWindow, UnmapSubWindows, ConfigureWindow, CirculateWindow,
  54.  *
  55.  ******/
  56.  
  57. static unsigned char _back_lsb[4] = {0x88, 0x22, 0x44, 0x11};
  58. static unsigned char _back_msb[4] = {0x11, 0x44, 0x22, 0x88};
  59.  
  60. typedef struct _ScreenSaverStuff {
  61.     WindowPtr pWindow;
  62.     XID       wid;
  63.     BYTE      blanked;
  64. } ScreenSaverStuffRec;
  65.  
  66. #define SCREEN_IS_BLANKED   0
  67. #define SCREEN_ISNT_SAVED   1
  68. #define SCREEN_IS_TILED     2
  69. #define SCREEN_IS_BLACK        3
  70.  
  71. #define HasSaverWindow(i)   (savedScreenInfo[i].pWindow != NullWindow)
  72.  
  73. extern int ScreenSaverBlanking, ScreenSaverAllowExposures;
  74. int screenIsSaved = SCREEN_SAVER_OFF;
  75.  
  76. static ScreenSaverStuffRec savedScreenInfo[MAXSCREENS];
  77.  
  78. extern WindowPtr *WindowTable;
  79. extern void (* ReplySwapVector[256]) ();
  80.  
  81. static void ResizeChildrenWinSize();
  82. extern void CheckCursorConfinement();
  83. extern void DeleteWindowFromAnySelections();
  84. extern void DeleteWindowFromAnyEvents();
  85. extern Mask EventMaskForClient();
  86. extern void WindowHasNewCursor();
  87. extern void RecalculateDeliverableEvents();
  88. extern int rand();
  89. static Bool MarkOverlappedWindows();
  90. static void SetWinSize(), SetBorderSize();
  91. static Bool TileScreenSaver();
  92.  
  93. #define INPUTONLY_LEGAL_MASK (CWWinGravity | CWEventMask | \
  94.                   CWDontPropagate | CWOverrideRedirect | CWCursor )
  95.  
  96. #define BOXES_OVERLAP(b1, b2) \
  97.       (!( ((b1)->x2 <= (b2)->x1)  || \
  98.         ( ((b1)->x1 >= (b2)->x2)) || \
  99.         ( ((b1)->y2 <= (b2)->y1)) || \
  100.         ( ((b1)->y1 >= (b2)->y2)) ) )
  101.  
  102. #define RedirectSend(pWin) \
  103.     ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureRedirectMask)
  104.  
  105. #define SubSend(pWin) \
  106.     ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureNotifyMask)
  107.  
  108. #define StrSend(pWin) \
  109.     ((pWin->eventMask|wOtherEventMasks(pWin)) & StructureNotifyMask)
  110.  
  111. #define SubStrSend(pWin,pParent) (StrSend(pWin) || SubSend(pParent))
  112.  
  113. /*
  114.  * For SaveUnders using backing-store. The idea is that when a window is mapped
  115.  * with saveUnder set TRUE, any windows it obscures will have its backing
  116.  * store turned on setting the DIXsaveUnder bit,
  117.  * The backing-store code must be written to allow for this
  118.  */
  119.  
  120. /*
  121.  * this is the configuration parameter "NO_BACK_SAVE"
  122.  * it means that any existant backing store should not 
  123.  * be used to implement save unders.
  124.  */
  125.  
  126. #ifndef NO_BACK_SAVE
  127.  
  128. #define DO_SAVE_UNDERS(pWin)    ((pWin)->drawable.pScreen->saveUnderSupport ==\
  129.                  USE_DIX_SAVE_UNDERS)
  130.  
  131. /*
  132.  * saveUnderSupport is set to this magic value when using DIXsaveUnders
  133.  */
  134.  
  135. #define USE_DIX_SAVE_UNDERS    0x40
  136.  
  137. static int numSaveUndersViewable = 0;
  138. static int deltaSaveUndersViewable = 0;
  139.  
  140. /*-
  141.  *-----------------------------------------------------------------------
  142.  * CheckSubSaveUnder --
  143.  *    Check all the inferiors of a window for coverage by saveUnder
  144.  *    windows. Called from ChangeSaveUnder and CheckSaveUnder.
  145.  *    This code is very inefficient.
  146.  *
  147.  * Results:
  148.  *    TRUE if any windows need to have backing-store removed.
  149.  *
  150.  * Side Effects:
  151.  *    Windows may have backing-store turned on or off.
  152.  *
  153.  *-----------------------------------------------------------------------
  154.  */
  155. Bool
  156. CheckSubSaveUnder(pParent, pFirst, pRegion)
  157.     register WindowPtr     pParent;        /* Parent to check */
  158.     WindowPtr        pFirst;        /* first reconfigured window */
  159.     RegionPtr          pRegion;        /* Initial area obscured by saveUnder */
  160. {
  161.     register WindowPtr    pChild;            /* Current child */
  162.     register ScreenPtr     pScreen;        /* Screen to use */
  163.     RegionRec          SubRegion;     /* Area of children obscured */
  164.     Bool        res = FALSE;    /* result */
  165.     Bool        subInited=FALSE;/* SubRegion initialized */
  166.  
  167.     pScreen = pParent->drawable.pScreen;
  168.     if (pChild = pParent->firstChild)
  169.     {
  170.     /*
  171.      * build region above first changed window
  172.      */
  173.  
  174.     for (; pChild != pFirst; pChild = pChild->nextSib)
  175.         if (pChild->viewable && pChild->saveUnder)
  176.         (* pScreen->Union) (pRegion, pRegion, &pChild->borderSize);
  177.     
  178.     /*
  179.      * check region below and including first changed window
  180.      */
  181.  
  182.     for (; pChild; pChild = pChild->nextSib)
  183.     {
  184.         if (pChild->viewable)
  185.         {
  186.         /*
  187.          * don't save under nephew/niece windows;
  188.          * use a separate region
  189.          */
  190.  
  191.         if (pChild->firstChild)
  192.         {
  193.             if (!subInited)
  194.             {
  195.             (*pScreen->RegionInit)(&SubRegion, NullBox, 0);
  196.             subInited = TRUE;
  197.             }
  198.             (* pScreen->RegionCopy) (&SubRegion, pRegion);
  199.             res |= CheckSubSaveUnder(pChild, pChild->firstChild,
  200.                          &SubRegion);
  201.         }
  202.         else
  203.         {
  204.             res |= CheckSubSaveUnder(pChild, pChild->firstChild,
  205.                          pRegion);
  206.         }
  207.  
  208.         if (pChild->saveUnder)
  209.             (* pScreen->Union) (pRegion, pRegion, &pChild->borderSize);
  210.         }
  211.     }
  212.  
  213.     if (subInited)
  214.         (* pScreen->RegionUninit) (&SubRegion);
  215.     }
  216.  
  217.     /*
  218.      * Check the state of this window.  DIX save unders are
  219.      * enabled for viewable windows with some client expressing
  220.      * exposure interest and which intersect the save under region
  221.      */
  222.  
  223.     if (pParent->viewable && 
  224.     ((pParent->eventMask | wOtherEventMasks(pParent)) & ExposureMask) &&
  225.     (*pScreen->RectIn) (pRegion, (*pScreen->RegionExtents)
  226.                     (&pParent->borderSize)) != rgnOUT)
  227.     {
  228.     if (!pParent->DIXsaveUnder)
  229.     {
  230.         pParent->DIXsaveUnder = TRUE;
  231.         (* pScreen->ChangeWindowAttributes) (pParent, CWBackingStore);
  232.     }
  233.     }
  234.     else
  235.     {
  236.     if (pParent->DIXsaveUnder)
  237.     {
  238.         res = TRUE;
  239.         pParent->DIXsaveUnder = FALSE;
  240.     }
  241.     }
  242.     return res;
  243. }
  244.  
  245. /*-
  246.  *-----------------------------------------------------------------------
  247.  * CheckSaveUnder --
  248.  *    See if a window's backing-store state should be changed because
  249.  *    it is or is not obscured by a sibling or child window with saveUnder.
  250.  *
  251.  * Results:
  252.  *    TRUE if any windows need to have backing-store removed.
  253.  *
  254.  * Side Effects:
  255.  *    If the window's state should be changed, it is.
  256.  *
  257.  *-----------------------------------------------------------------------
  258.  */
  259. Bool
  260. CheckSaveUnder (pWin)
  261.     register WindowPtr pWin;       /* Window to check */
  262. {
  263.     RegionRec    rgn;        /* Extent of siblings with saveUnder */
  264.     Bool    res;
  265.  
  266.     if (!deltaSaveUndersViewable && !numSaveUndersViewable)
  267.     return FALSE;
  268.     numSaveUndersViewable += deltaSaveUndersViewable;
  269.     deltaSaveUndersViewable = 0;
  270.     (* pWin->drawable.pScreen->RegionInit) (&rgn, NullBox, 1);
  271.     res = CheckSubSaveUnder (pWin->parent, pWin->nextSib, &rgn);
  272.     (*pWin->drawable.pScreen->RegionUninit) (&rgn);
  273.     return res;
  274. }
  275.  
  276.  
  277. /*-
  278.  *-----------------------------------------------------------------------
  279.  * ChangeSaveUnder --
  280.  *    Change the save-under state of a tree of windows. Called when
  281.  *    a window with saveUnder TRUE is mapped/unmapped/reconfigured.
  282.  *    
  283.  * Results:
  284.  *    TRUE if any windows need to have backing-store removed.
  285.  *
  286.  * Side Effects:
  287.  *    Windows may have backing-store turned on or off.
  288.  *
  289.  *-----------------------------------------------------------------------
  290.  */
  291. Bool
  292. ChangeSaveUnder(pWin, first)
  293.     register WindowPtr     pWin;
  294.     WindowPtr            first;             /* First window to check.
  295.                      * Used when pWin was restacked */
  296. {
  297.     RegionRec    rgn;      /* Area obscured by saveUnder windows */
  298.     register ScreenPtr pScreen;
  299.     Bool    res;
  300.  
  301.     if (!deltaSaveUndersViewable && !numSaveUndersViewable)
  302.     return FALSE;
  303.     numSaveUndersViewable += deltaSaveUndersViewable;
  304.     deltaSaveUndersViewable = 0;
  305.     pScreen = pWin->drawable.pScreen;
  306.     (* pScreen->RegionInit) (&rgn, NullBox, 1);
  307.     res = CheckSubSaveUnder (pWin->parent, first, &rgn);
  308.     (* pScreen->RegionUninit) (&rgn);
  309.     return res;
  310. }
  311.  
  312. /*-
  313.  *-----------------------------------------------------------------------
  314.  * DoChangeSaveUnder --
  315.  *    Actually turn backing-store off for those windows that no longer
  316.  *    need to have it on.
  317.  *
  318.  * Results:
  319.  *    None.
  320.  *
  321.  * Side Effects:
  322.  *    Backing-store and SAVE_UNDER_CHANGE_BIT are turned off for those
  323.  *    windows affected.
  324.  *
  325.  *-----------------------------------------------------------------------
  326.  */
  327. void
  328. DoChangeSaveUnder(pWin, pFirst)
  329.     WindowPtr          pWin;
  330.     WindowPtr        pFirst;
  331. {
  332.     register WindowPtr pChild;
  333.     Bool (* ChangeWindowAttributes)();
  334.  
  335.     ChangeWindowAttributes = pWin->drawable.pScreen->ChangeWindowAttributes;
  336.     if (!pWin->DIXsaveUnder &&
  337.     (pWin->backingStore == NotUseful) && pWin->backStorage)
  338.     (*ChangeWindowAttributes)(pWin, CWBackingStore);
  339.     if (!(pChild = pFirst))
  340.     return;
  341.     while (1)
  342.     {
  343.     if (!pChild->DIXsaveUnder &&
  344.         (pChild->backingStore == NotUseful) && pChild->backStorage)
  345.         (*ChangeWindowAttributes)(pChild, CWBackingStore);
  346.     if (pChild->firstChild)
  347.     {
  348.         pChild = pChild->firstChild;
  349.         continue;
  350.     }
  351.     while (!pChild->nextSib)
  352.     {
  353.         pChild = pChild->parent;
  354.         if (pChild == pWin)
  355.         return;
  356.     }
  357.     pChild = pChild->nextSib;
  358.     }
  359. }
  360. #endif /* DO_SAVE_UNDER */
  361.  
  362. #ifdef DEBUG
  363. /******
  364.  * PrintWindowTree
  365.  *    For debugging only
  366.  ******/
  367.  
  368. int
  369. PrintChildren(p1, indent)
  370.     WindowPtr p1;
  371.     int indent;
  372. {
  373.     WindowPtr p2;
  374.     int i;
  375.  
  376.     while (p1)
  377.     {
  378.         p2 = p1->firstChild;
  379.         for (i=0; i<indent; i++) ErrorF( " ");
  380.     ErrorF( "%x\n", p1->drawable.id);
  381.         miPrintRegion(&p1->clipList);
  382.     PrintChildren(p2, indent+4);
  383.     p1 = p1->nextSib;
  384.     }
  385. }
  386.  
  387. PrintWindowTree()
  388. {
  389.     int i;
  390.     WindowPtr pWin, p1;
  391.  
  392.     for (i=0; i<screenInfo.numScreens; i++)
  393.     {
  394.     ErrorF( "WINDOW %d\n", i);
  395.     pWin = WindowTable[i];
  396.         miPrintRegion(&pWin->clipList);
  397.     p1 = pWin->firstChild;
  398.     PrintChildren(p1, 4);
  399.     }
  400. }
  401. #endif
  402.  
  403. /*
  404.  * allocate an entry in the per-window private data structures
  405.  */
  406.  
  407. static int  windowPrivateCount;
  408.  
  409. void
  410. ResetWindowPrivates()
  411. {
  412.     windowPrivateCount = 0;
  413. }
  414.  
  415. int
  416. AllocateWindowPrivateIndex()
  417. {
  418.     return windowPrivateCount++;
  419. }
  420.  
  421. int
  422. TraverseTree(pWin, func, data)
  423.     register WindowPtr pWin;
  424.     int (*func)();
  425.     pointer data;
  426. {
  427.     register int result;
  428.     register WindowPtr pChild;
  429.  
  430.     if (!(pChild = pWin))
  431.        return(WT_NOMATCH);
  432.     while (1)
  433.     {
  434.     result = (* func)(pChild, data);
  435.     if (result == WT_STOPWALKING)
  436.         return(WT_STOPWALKING);
  437.     if ((result == WT_WALKCHILDREN) && pChild->firstChild)
  438.     {
  439.         pChild = pChild->firstChild;
  440.         continue;
  441.     }
  442.     while (!pChild->nextSib && (pChild != pWin))
  443.         pChild = pChild->parent;
  444.     if (pChild == pWin)
  445.         break;
  446.     pChild = pChild->nextSib;
  447.     }
  448.     return(WT_NOMATCH);
  449. }
  450.  
  451. /*****
  452.  * WalkTree
  453.  *   Walk the window tree, for SCREEN, preforming FUNC(pWin, data) on
  454.  *   each window.  If FUNC returns WT_WALKCHILDREN, traverse the children,
  455.  *   if it returns WT_DONTWALKCHILDREN, dont.  If it returns WT_STOPWALKING
  456.  *   exit WalkTree.  Does depth-first traverse.
  457.  *****/
  458.  
  459. int
  460. WalkTree(pScreen, func, data)
  461.     ScreenPtr pScreen;
  462.     int (* func)();
  463.     pointer data;
  464. {
  465.     return(TraverseTree(WindowTable[pScreen->myNum], func, data));
  466. }
  467.  
  468. /*****
  469.  *  HandleExposures(pWin)
  470.  *    starting at pWin, draw background in any windows that have exposure
  471.  *    regions, translate the regions, restore any backing store,
  472.  *    and then send any regions stille xposed to the client
  473.  *****/
  474.  
  475. static void
  476. HandleExposures(pWin)
  477.     WindowPtr pWin;
  478. {
  479.     register WindowPtr pChild;
  480.     register ValidatePtr val;
  481.     Bool (* RegionNotEmpty)();
  482.     void (* RegionUninit)();
  483.     void (* WindowExposures)();
  484.  
  485.     pChild = pWin;
  486.     RegionNotEmpty = pChild->drawable.pScreen->RegionNotEmpty;
  487.     RegionUninit = pChild->drawable.pScreen->RegionUninit;
  488.     WindowExposures = pChild->drawable.pScreen->WindowExposures;
  489.     while (1)
  490.     {
  491.     if (val = pChild->valdata)
  492.     {
  493.         if ((*RegionNotEmpty)(&val->after.borderExposed))
  494.         (*pChild->drawable.pScreen->PaintWindowBorder)(pChild,
  495.                             &val->after.borderExposed,
  496.                             PW_BORDER);
  497.         (*RegionUninit)(&val->after.borderExposed);
  498.         (*WindowExposures)(pChild, &val->after.exposed, NullRegion);
  499.         (*RegionUninit)(&val->after.exposed);
  500.         xfree(val);
  501.         pChild->valdata = (ValidatePtr)NULL;
  502.         if (pChild->firstChild)
  503.         {
  504.         pChild = pChild->firstChild;
  505.         continue;
  506.         }
  507.     }
  508.     while (!pChild->nextSib && (pChild != pWin))
  509.         pChild = pChild->parent;
  510.     if (pChild == pWin)
  511.         break;
  512.     pChild = pChild->nextSib;
  513.     }
  514. }
  515.  
  516. /* hack for forcing backing store on all windows */
  517. int    defaultBackingStore = NotUseful;
  518. /* hack to force no backing store */
  519. Bool    disableBackingStore = FALSE;
  520. /* hack to force no save unders */
  521. Bool    disableSaveUnders = FALSE;
  522.  
  523. static void
  524. SetWindowToDefaults(pWin)
  525.     register WindowPtr pWin;
  526. {
  527.     pWin->prevSib = NullWindow;
  528.     pWin->firstChild = NullWindow;
  529.     pWin->lastChild = NullWindow;
  530.  
  531.     pWin->valdata = (ValidatePtr)NULL;
  532.     pWin->optional = (WindowOptPtr)NULL;
  533.     pWin->cursorIsNone = TRUE;
  534.  
  535.     pWin->backingStore = NotUseful;
  536.     pWin->DIXsaveUnder = FALSE;
  537.     pWin->backStorage = (pointer) NULL;
  538.  
  539.     pWin->mapped = FALSE;           /* off */
  540.     pWin->realized = FALSE;     /* off */
  541.     pWin->viewable = FALSE;
  542.     pWin->visibility = VisibilityNotViewable;
  543.     pWin->overrideRedirect = FALSE;
  544.     pWin->saveUnder = FALSE;
  545.  
  546.     pWin->bitGravity = ForgetGravity;
  547.     pWin->winGravity = NorthWestGravity;
  548.  
  549.     pWin->eventMask = 0;
  550.     pWin->deliverableEvents = 0;
  551.     pWin->dontPropagate = 0;
  552. }
  553.  
  554. static void
  555. MakeRootTile(pWin)
  556.     WindowPtr pWin;
  557. {
  558.     ScreenPtr pScreen = pWin->drawable.pScreen;
  559.     GCPtr pGC;
  560.     unsigned char back[128];
  561.     int len = PixmapBytePad(4, 1);
  562.     register unsigned char *from, *to;
  563.     register int i, j;
  564.  
  565.     pWin->background.pixmap = (*pScreen->CreatePixmap)(pScreen, 4, 4,
  566.                             pScreen->rootDepth);
  567.  
  568.     pWin->backgroundState = BackgroundPixmap;
  569.     pGC = GetScratchGC(pScreen->rootDepth, pScreen);
  570.     if (!pWin->background.pixmap || !pGC)
  571.     FatalError("cound not create root tile");
  572.  
  573.     {
  574.     CARD32 attributes[2];
  575.  
  576.     attributes[0] = pScreen->whitePixel;
  577.     attributes[1] = pScreen->blackPixel;
  578.  
  579.     (void)ChangeGC(pGC, GCForeground | GCBackground, attributes);
  580.     }
  581.  
  582.    ValidateGC((DrawablePtr)pWin->background.pixmap, pGC);
  583.  
  584.    from = (screenInfo.bitmapBitOrder == LSBFirst) ? _back_lsb : _back_msb;
  585.    to = back;
  586.  
  587.    for (i = 4; i > 0; i--, from++)
  588.     for (j = len; j > 0; j--)
  589.         *to++ = *from;
  590.  
  591.    (*pGC->ops->PutImage)(pWin->background.pixmap, pGC, 1,
  592.                 0, 0, 4, 4, 0, XYBitmap, back);
  593.  
  594.    FreeScratchGC(pGC);
  595.  
  596. }
  597.  
  598. static WindowPtr
  599. AllocateWindow(pScreen)
  600.     ScreenPtr pScreen;
  601. {
  602.     WindowPtr pWin;
  603.     register char *ptr;
  604.     register DevUnion *ppriv;
  605.     register unsigned *sizes;
  606.     register unsigned size;
  607.     register int i;
  608.  
  609.     pWin = (WindowPtr)xalloc(pScreen->totalWindowSize);
  610.     if (pWin)
  611.     {
  612.     ppriv = (DevUnion *)(pWin + 1);
  613.     pWin->devPrivates = ppriv;
  614.     sizes = pScreen->WindowPrivateSizes;
  615.     ptr = (char *)(ppriv + pScreen->WindowPrivateLen);
  616.     for (i = pScreen->WindowPrivateLen; --i >= 0; ppriv++, sizes++)
  617.     {
  618.         if (size = *sizes)
  619.         {
  620.         ppriv->ptr = (pointer)ptr;
  621.         ptr += size;
  622.         }
  623.         else
  624.         ppriv->ptr = (pointer)NULL;
  625.     }
  626.     }
  627.     return pWin;
  628. }
  629.  
  630. /*****
  631.  * CreateRootWindow
  632.  *    Makes a window at initialization time for specified screen
  633.  *****/
  634.  
  635. Bool
  636. CreateRootWindow(pScreen)
  637.     ScreenPtr    pScreen;
  638. {
  639.     WindowPtr    pWin;
  640.     BoxRec    box;
  641.     PixmapFormatRec *format;
  642.  
  643.     pWin = AllocateWindow(pScreen);
  644.     if (!pWin)
  645.     return FALSE;
  646.  
  647.     savedScreenInfo[pScreen->myNum].pWindow = NULL;
  648.     savedScreenInfo[pScreen->myNum].wid = FakeClientID(0);
  649.     screenIsSaved = SCREEN_SAVER_OFF;
  650.  
  651.     WindowTable[pScreen->myNum] = pWin;
  652.  
  653.     pWin->drawable.pScreen = pScreen;
  654.     pWin->drawable.type = DRAWABLE_WINDOW;
  655.  
  656.     pWin->drawable.depth = pScreen->rootDepth;
  657.     for (format = screenInfo.formats;
  658.      format->depth != pScreen->rootDepth;
  659.      format++)
  660.     ;
  661.     pWin->drawable.bitsPerPixel = format->bitsPerPixel;
  662.  
  663.     pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
  664.  
  665.     pWin->parent = NullWindow;
  666.     SetWindowToDefaults(pWin);
  667.  
  668.     pWin->optional = (WindowOptRec *) xalloc (sizeof (WindowOptRec));
  669.  
  670.     pWin->optional->dontPropagateMask = 0;
  671.     pWin->optional->otherEventMasks = 0;
  672.     pWin->optional->otherClients = NULL;
  673.     pWin->optional->passiveGrabs = NULL;
  674.     pWin->optional->userProps = NULL;
  675.     pWin->optional->backingBitPlanes = ~0L;
  676.     pWin->optional->backingPixel = 0;
  677. #ifdef SHAPE
  678.     pWin->optional->boundingShape = NULL;
  679.     pWin->optional->clipShape = NULL;
  680. #endif
  681. #ifdef XINPUT
  682.     pWin->optional->inputMasks = NULL;
  683. #endif
  684.     pWin->optional->colormap = pScreen->defColormap;
  685.     pWin->optional->visual = pScreen->rootVisual;
  686.  
  687.     pWin->nextSib = NullWindow;
  688.  
  689.     pWin->drawable.id = FakeClientID(0);
  690.  
  691.     pWin->origin.x = pWin->origin.y = 0;
  692.     pWin->drawable.height = pScreen->height;
  693.     pWin->drawable.width = pScreen->width;
  694.     pWin->drawable.x = pWin->drawable.y = 0;
  695.  
  696.     box.x1 = 0;
  697.     box.y1 = 0;
  698.     box.x2 = pScreen->width;
  699.     box.y2 = pScreen->height;
  700.     (* pScreen->RegionInit)(&pWin->clipList, &box, 1);
  701.     (* pScreen->RegionInit)(&pWin->winSize, &box, 1);
  702.     (* pScreen->RegionInit)(&pWin->borderSize, &box, 1);
  703.     (* pScreen->RegionInit)(&pWin->borderClip, &box, 1);
  704.  
  705.     pWin->drawable.class = InputOutput;
  706.     pWin->optional->visual = pScreen->rootVisual;
  707.  
  708.     pWin->backgroundState = BackgroundPixel;
  709.     pWin->background.pixel = pScreen->whitePixel;
  710.  
  711.     pWin->borderIsPixel = TRUE;
  712.     pWin->border.pixel = pScreen->blackPixel;
  713.     pWin->borderWidth = 0;
  714.  
  715.     if (!AddResource(pWin->drawable.id, RT_WINDOW, (pointer)pWin))
  716.     return FALSE;
  717.  
  718.     if (disableBackingStore)
  719.     pScreen->backingStoreSupport = NotUseful;
  720.  
  721. #ifdef DO_SAVE_UNDERS
  722.     if ((pScreen->backingStoreSupport != NotUseful) &&
  723.     (pScreen->saveUnderSupport == NotUseful))
  724.     {
  725.     /*
  726.      * If the screen has backing-store but no save-unders, let the
  727.      * clients know we can support save-unders using backing-store.
  728.      */
  729.     pScreen->saveUnderSupport = USE_DIX_SAVE_UNDERS;
  730.     }
  731. #endif /* DO_SAVE_UNDERS */
  732.         
  733.     if (disableSaveUnders)
  734.     pScreen->saveUnderSupport = NotUseful;
  735.  
  736.     return TRUE;
  737. }
  738.  
  739. InitRootWindow(pWin)
  740.     WindowPtr pWin;
  741. {
  742.     ScreenPtr pScreen;
  743.  
  744.     pScreen = pWin->drawable.pScreen;
  745.     if (!(*pScreen->CreateWindow)(pWin))
  746.     return; /* XXX */
  747.     (*pScreen->PositionWindow)(pWin, 0, 0);
  748.  
  749.     pWin->cursorIsNone = FALSE;
  750.     pWin->optional->cursor = rootCursor;
  751.     rootCursor->refcnt++;
  752.     MakeRootTile(pWin);
  753.     pWin->backingStore = defaultBackingStore;
  754.     /* We SHOULD check for an error value here XXX */
  755.     (*pScreen->ChangeWindowAttributes)(pWin,
  756.                CWBackPixmap|CWBorderPixel|CWCursor|CWBackingStore);
  757.  
  758.     MapWindow(pWin, serverClient);
  759. }
  760.  
  761. /* Set the region to the intersection of the rectangle and the
  762.  * window's winSize.  The window is typically the parent of the
  763.  * window from which the region came.
  764.  */
  765.  
  766. ClippedRegionFromBox(pWin, Rgn, x, y, w, h)
  767.     register WindowPtr pWin;
  768.     RegionPtr Rgn;
  769.     register int x, y;
  770.     int w, h;
  771. {
  772.     register ScreenPtr pScreen = pWin->drawable.pScreen;
  773.     BoxRec box;
  774.  
  775.     box = *((* pScreen->RegionExtents)(&pWin->winSize));
  776.     /* we do these calculations to avoid overflows */
  777.     if (x > box.x1)
  778.     box.x1 = x;
  779.     if (y > box.y1)
  780.     box.y1 = y;
  781.     x += w;
  782.     if (x < box.x2)
  783.     box.x2 = x;
  784.     y += h;
  785.     if (y < box.y2)
  786.     box.y2 = y;
  787.     if (box.x1 > box.x2)
  788.     box.x2 = box.x1;
  789.     if (box.y1 > box.y2)
  790.     box.y2 = box.y1;
  791.     (* pScreen->RegionReset)(Rgn, &box);
  792.     (* pScreen->Intersect)(Rgn, Rgn, &pWin->winSize);
  793. }
  794.  
  795. WindowPtr
  796. RealChildHead(pWin)
  797.     register WindowPtr pWin;
  798. {
  799.     if (!pWin->parent &&
  800.     (screenIsSaved == SCREEN_SAVER_ON) &&
  801.     (HasSaverWindow (pWin->drawable.pScreen->myNum)))
  802.     return (pWin->firstChild);
  803.     else
  804.     return (NullWindow);
  805. }
  806.  
  807. /*****
  808.  * CreateWindow
  809.  *    Makes a window in response to client request 
  810.  *****/
  811.  
  812. WindowPtr
  813. CreateWindow(wid, pParent, x, y, w, h, bw, class, vmask, vlist,
  814.          depth, client, visual, error)
  815.     Window wid;
  816.     register WindowPtr pParent;
  817.     short x,y;
  818.     unsigned short w, h, bw;
  819.     unsigned short class;
  820.     register Mask vmask;
  821.     XID *vlist;
  822.     int depth;
  823.     ClientPtr client;
  824.     VisualID visual;
  825.     int *error;
  826. {
  827.     register WindowPtr pWin;
  828.     WindowPtr pHead;
  829.     register ScreenPtr pScreen;
  830.     xEvent event;
  831.     int idepth, ivisual;
  832.     Bool fOK;
  833.     DepthPtr pDepth;
  834.     PixmapFormatRec *format;
  835.     register WindowOptPtr ancwopt;
  836.  
  837.     if (class == CopyFromParent)
  838.     class = pParent->drawable.class;
  839.  
  840.     if ((class != InputOutput) && (class != InputOnly))
  841.     {
  842.     *error = BadValue;
  843.     client->errorValue = class;
  844.     return NullWindow;
  845.     }
  846.  
  847.     if ((class != InputOnly) && (pParent->drawable.class == InputOnly))
  848.     {
  849.         *error = BadMatch;
  850.     return NullWindow;
  851.     }
  852.  
  853.     if ((class == InputOnly) && ((bw != 0) || (depth != 0)))
  854.     {
  855.         *error = BadMatch;
  856.     return NullWindow;
  857.     }
  858.  
  859.     pScreen = pParent->drawable.pScreen;
  860.  
  861.     if ((class == InputOutput) && (depth == 0))
  862.         depth = pParent->drawable.depth;
  863.     ancwopt = pParent->optional;
  864.     if (!ancwopt)
  865.     ancwopt = FindWindowWithOptional(pParent)->optional;
  866.     if (visual == CopyFromParent)
  867.     visual = ancwopt->visual;
  868.  
  869.     /* Find out if the depth and visual are acceptable for this Screen */
  870.     if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth))
  871.     {
  872.     fOK = FALSE;
  873.     for(idepth = 0; idepth < pScreen->numDepths; idepth++)
  874.     {
  875.         pDepth = (DepthPtr) &pScreen->allowedDepths[idepth];
  876.         if ((depth == pDepth->depth) || (depth == 0))
  877.         {
  878.         for (ivisual = 0; ivisual < pDepth->numVids; ivisual++)
  879.         {
  880.             if (visual == pDepth->vids[ivisual])
  881.             {
  882.             fOK = TRUE;
  883.             break;
  884.             }
  885.         }
  886.         }
  887.     }
  888.     if (fOK == FALSE)
  889.     {
  890.         *error = BadMatch;
  891.         return NullWindow;
  892.     }
  893.     }
  894.  
  895.     if (((vmask & (CWBorderPixmap | CWBorderPixel)) == 0) &&
  896.     (class != InputOnly) &&
  897.     (depth != pParent->drawable.depth))
  898.     {
  899.         *error = BadMatch;
  900.         return NullWindow;
  901.     }
  902.  
  903.     if (((vmask & CWColormap) == 0) &&
  904.     (class != InputOnly) &&
  905.     ((visual != ancwopt->visual) || (ancwopt->colormap == None)))
  906.     {
  907.     *error = BadMatch;
  908.         return NullWindow;
  909.     }
  910.  
  911.     pWin = AllocateWindow(pScreen);
  912.     if (!pWin)
  913.     {
  914.     *error = BadAlloc;
  915.         return NullWindow;
  916.     }
  917.     pWin->drawable = pParent->drawable;
  918.     pWin->drawable.depth = depth;
  919.     if (depth == pParent->drawable.depth)
  920.     pWin->drawable.bitsPerPixel = pParent->drawable.bitsPerPixel;
  921.     else
  922.     {
  923.     for (format = screenInfo.formats; format->depth != depth; format++)
  924.         ;
  925.     pWin->drawable.bitsPerPixel = format->bitsPerPixel;
  926.     }
  927.     if (class == InputOnly)
  928.         pWin->drawable.type = (short) UNDRAWABLE_WINDOW;
  929.     pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
  930.  
  931.     pWin->drawable.id = wid;
  932.     pWin->drawable.class = class;
  933.  
  934.     pWin->parent = pParent;
  935.     SetWindowToDefaults(pWin);
  936.  
  937.     if (visual != ancwopt->visual)
  938.     {
  939.     if (!MakeWindowOptional (pWin))
  940.     {
  941.         xfree (pWin);
  942.         *error = BadAlloc;
  943.         return NullWindow;
  944.     }
  945.     pWin->optional->visual = visual;
  946.     pWin->optional->colormap = None;
  947.     }
  948.  
  949.     pWin->borderWidth = bw;
  950.     pWin->backgroundState = None;
  951.  
  952.     pWin->borderIsPixel = pParent->borderIsPixel;
  953.     pWin->border = pParent->border;
  954.     if (pWin->borderIsPixel == FALSE)
  955.     pWin->border.pixmap->refcnt++;
  956.         
  957.     pWin->origin.x = x + (int)bw;
  958.     pWin->origin.y = y + (int)bw;
  959.     pWin->drawable.width = w;
  960.     pWin->drawable.height = h;
  961.     pWin->drawable.x = pParent->drawable.x + x + (int)bw;
  962.     pWin->drawable.y = pParent->drawable.y + y + (int)bw;
  963.  
  964.         /* set up clip list correctly for unobscured WindowPtr */
  965.     (* pScreen->RegionInit)(&pWin->clipList, NullBox, 1);
  966.     (* pScreen->RegionInit)(&pWin->borderClip, NullBox, 1);
  967.     (* pScreen->RegionInit)(&pWin->winSize, NullBox, 1);
  968.     (* pScreen->RegionInit)(&pWin->borderSize, NullBox, 1);
  969.  
  970.     pHead = RealChildHead(pParent);
  971.     if (pHead)
  972.     {
  973.     pWin->nextSib = pHead->nextSib;
  974.         if (pHead->nextSib)
  975.             pHead->nextSib->prevSib = pWin;
  976.     else
  977.         pParent->lastChild = pWin;
  978.         pHead->nextSib = pWin;
  979.     pWin->prevSib = pHead;
  980.     }
  981.     else
  982.     {
  983.         pWin->nextSib = pParent->firstChild;
  984.         if (pParent->firstChild)
  985.         pParent->firstChild->prevSib = pWin;
  986.         else
  987.             pParent->lastChild = pWin;
  988.     pParent->firstChild = pWin;
  989.     }
  990.  
  991.     SetWinSize (pWin);
  992.     SetBorderSize (pWin);
  993.  
  994.     /* We SHOULD check for an error value here XXX */
  995.     if (!(*pScreen->CreateWindow)(pWin))
  996.     {
  997.     *error = BadAlloc;
  998.     DeleteWindow(pWin, wid);
  999.     return NullWindow;
  1000.     }
  1001.     /* We SHOULD check for an error value here XXX */
  1002.     (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y);
  1003.  
  1004.     if (!(vmask & CWEventMask))
  1005.     RecalculateDeliverableEvents(pWin);
  1006.  
  1007.     if (vmask)
  1008.         *error = ChangeWindowAttributes(pWin, vmask, vlist, wClient (pWin));
  1009.     else
  1010.     *error = Success;
  1011.  
  1012.     if (*error != Success)
  1013.     {
  1014.         (void)EventSelectForWindow(pWin, client, (Mask)0); /* can't fail */
  1015.     DeleteWindow(pWin, wid);
  1016.     return NullWindow;
  1017.     }
  1018.     if (!(vmask & CWBackingStore) && (defaultBackingStore != NotUseful))
  1019.     {
  1020.         XID value = defaultBackingStore;
  1021.     (void)ChangeWindowAttributes(pWin, CWBackingStore, &value, wClient (pWin));
  1022.     }
  1023.  
  1024.     if (SubSend(pParent))
  1025.     {
  1026.     event.u.u.type = CreateNotify;
  1027.     event.u.createNotify.window = wid;
  1028.     event.u.createNotify.parent = pParent->drawable.id;
  1029.     event.u.createNotify.x = x;
  1030.     event.u.createNotify.y = y;
  1031.     event.u.createNotify.width = w;
  1032.     event.u.createNotify.height = h;
  1033.     event.u.createNotify.borderWidth = bw;
  1034.     event.u.createNotify.override = pWin->overrideRedirect;
  1035.     DeliverEvents(pParent, &event, 1, NullWindow);        
  1036.     }
  1037.  
  1038.     return pWin;
  1039. }
  1040.  
  1041. static void
  1042. FreeWindowResources(pWin)
  1043.     register WindowPtr pWin;
  1044. {
  1045.     register ScreenPtr pScreen;
  1046.     void (* proc)();
  1047.  
  1048.     pScreen = pWin->drawable.pScreen;
  1049.  
  1050.     DeleteWindowFromAnySaveSet(pWin);
  1051.     DeleteWindowFromAnySelections(pWin);
  1052.     DeleteWindowFromAnyEvents(pWin, TRUE);
  1053.     proc = pScreen->RegionUninit;
  1054.     (* proc)(&pWin->clipList);
  1055.     (* proc)(&pWin->winSize);
  1056.     (* proc)(&pWin->borderClip);
  1057.     (* proc)(&pWin->borderSize);
  1058. #ifdef SHAPE
  1059.     if (wBoundingShape (pWin))
  1060.     (* pScreen->RegionDestroy)(wBoundingShape (pWin));
  1061.     if (wClipShape (pWin))
  1062.     (* pScreen->RegionDestroy)(wClipShape (pWin));
  1063. #endif
  1064.     if (pWin->borderIsPixel == FALSE)
  1065.     (* pScreen->DestroyPixmap)(pWin->border.pixmap);
  1066.     if (pWin->backgroundState == BackgroundPixmap)
  1067.     (* pScreen->DestroyPixmap)(pWin->background.pixmap);
  1068.  
  1069.     DeleteAllWindowProperties(pWin);
  1070.     /* We SHOULD check for an error value here XXX */
  1071.     (* pScreen->DestroyWindow)(pWin);
  1072.     DisposeWindowOptional (pWin);
  1073. }
  1074.  
  1075. static void
  1076. CrushTree(pWin)
  1077.     WindowPtr pWin;
  1078. {
  1079.     register WindowPtr pChild, pSib, pParent;
  1080.     Bool (* UnrealizeWindow)();
  1081.     xEvent event;
  1082.  
  1083.     if (!(pChild = pWin->firstChild))
  1084.         return;
  1085.     UnrealizeWindow = pWin->drawable.pScreen->UnrealizeWindow;
  1086.     while (1)
  1087.     {
  1088.     if (pChild->firstChild)
  1089.     {
  1090.         pChild = pChild->firstChild;
  1091.         continue;
  1092.     }
  1093.     while (1)
  1094.     {
  1095.         pParent = pChild->parent;
  1096.         if (SubStrSend(pChild, pParent))
  1097.         {
  1098.         event.u.u.type = DestroyNotify;
  1099.         event.u.destroyNotify.window = pChild->drawable.id;
  1100.         DeliverEvents(pChild, &event, 1, NullWindow);        
  1101.         }
  1102.         FreeResource(pChild->drawable.id, RT_WINDOW);
  1103.         pSib = pChild->nextSib;
  1104. #ifdef DO_SAVE_UNDERS
  1105.         if (pChild->saveUnder && pChild->viewable)
  1106.         deltaSaveUndersViewable--;
  1107. #endif
  1108.         pChild->viewable = FALSE;
  1109.         if (pChild->realized)
  1110.         {
  1111.         pChild->realized = FALSE;
  1112.         (*UnrealizeWindow)(pChild);
  1113.         }
  1114.         FreeWindowResources(pChild);
  1115.         xfree(pChild);
  1116.         if (pChild = pSib)
  1117.         break;
  1118.         pChild = pParent;
  1119.         pChild->firstChild = NullWindow;
  1120.         pChild->lastChild = NullWindow;
  1121.         if (pChild == pWin)
  1122.         return;
  1123.     }
  1124.     }
  1125. }
  1126.     
  1127. /*****
  1128.  *  DeleteWindow
  1129.  *       Deletes child of window then window itself
  1130.  *****/
  1131.  
  1132. /*ARGSUSED*/
  1133. DeleteWindow(pWin, wid)
  1134.     register WindowPtr pWin;
  1135.     Window wid;
  1136. {
  1137.     register WindowPtr pParent;
  1138.     xEvent event;
  1139.  
  1140.     UnmapWindow(pWin, FALSE);
  1141.  
  1142.     CrushTree(pWin);
  1143.  
  1144.     pParent = pWin->parent;
  1145.     if (pParent && SubStrSend(pWin, pParent))
  1146.     {
  1147.     event.u.u.type = DestroyNotify;
  1148.     event.u.destroyNotify.window = pWin->drawable.id;
  1149.     DeliverEvents(pWin, &event, 1, NullWindow);        
  1150.     }
  1151.  
  1152.     FreeWindowResources(pWin);
  1153.     if (pParent)
  1154.     {
  1155.     if (pParent->firstChild == pWin)
  1156.             pParent->firstChild = pWin->nextSib;
  1157.     if (pParent->lastChild == pWin)
  1158.             pParent->lastChild = pWin->prevSib;
  1159.         if (pWin->nextSib)
  1160.             pWin->nextSib->prevSib = pWin->prevSib;
  1161.         if (pWin->prevSib)
  1162.             pWin->prevSib->nextSib = pWin->nextSib;
  1163.     }
  1164.     xfree(pWin);
  1165. }
  1166.  
  1167. /*ARGSUSED*/
  1168. DestroySubwindows(pWin, client)
  1169.     register WindowPtr pWin;
  1170.     ClientPtr client;
  1171. {
  1172.     /* XXX
  1173.      * The protocol is quite clear that each window should be
  1174.      * destroyed in turn, however, unmapping all of the first
  1175.      * eliminates most of the calls to ValidateTree.  So,
  1176.      * this implementation is incorrect in that all of the
  1177.      * UnmapNotifies occur before all of the DestroyNotifies.
  1178.      * If you care, simply delete the call to UnmapSubwindows.
  1179.      */
  1180.     UnmapSubwindows(pWin);
  1181.     while (pWin->lastChild)
  1182.     FreeResource(pWin->lastChild->drawable.id, RT_NONE);
  1183. }
  1184.  
  1185. /*****
  1186.  *  ChangeWindowAttributes
  1187.  *   
  1188.  *  The value-mask specifies which attributes are to be changed; the
  1189.  *  value-list contains one value for each one bit in the mask, from least
  1190.  *  to most significant bit in the mask.  
  1191.  *****/
  1192.  
  1193. int
  1194. ChangeWindowAttributes(pWin, vmask, vlist, client)
  1195.     register WindowPtr pWin;
  1196.     Mask vmask;
  1197.     XID *vlist;
  1198.     ClientPtr client;
  1199. {
  1200.     register Mask index;
  1201.     register XID *pVlist;
  1202.     PixmapPtr pPixmap;
  1203.     Pixmap pixID;
  1204.     CursorPtr pCursor, pOldCursor;
  1205.     Cursor cursorID;
  1206.     WindowPtr pChild;
  1207.     Colormap cmap;
  1208.     ColormapPtr    pCmap;
  1209.     xEvent xE;
  1210.     int result;
  1211.     register ScreenPtr pScreen;
  1212.     Mask vmaskCopy = 0;
  1213.     register Mask tmask;
  1214.     unsigned int val;
  1215.     int error;
  1216.     Bool checkOptional = FALSE;
  1217.  
  1218.     if ((pWin->drawable.class == InputOnly) && (vmask & (~INPUTONLY_LEGAL_MASK)))
  1219.         return BadMatch;
  1220.  
  1221.     error = Success;
  1222.     pScreen = pWin->drawable.pScreen;
  1223.     pVlist = vlist;
  1224.     tmask = vmask;
  1225.     while (tmask)
  1226.     {
  1227.     index = (Mask) lowbit (tmask);
  1228.     tmask &= ~index;
  1229.     switch (index)
  1230.         {
  1231.       case CWBackPixmap:
  1232.         pixID = (Pixmap )*pVlist;
  1233.         pVlist++;
  1234.         if (pixID == None)
  1235.         {
  1236.         if (pWin->backgroundState == BackgroundPixmap)
  1237.             (* pScreen->DestroyPixmap)(pWin->background.pixmap);
  1238.         if (!pWin->parent)
  1239.                     MakeRootTile(pWin);
  1240.                 else
  1241.                     pWin->backgroundState = None;
  1242.         }
  1243.         else if (pixID == ParentRelative)
  1244.         {
  1245.         if (pWin->parent &&
  1246.             pWin->drawable.depth != pWin->parent->drawable.depth)
  1247.         {
  1248.             error = BadMatch;
  1249.             goto PatchUp;
  1250.         }
  1251.         if (pWin->backgroundState == BackgroundPixmap)
  1252.             (* pScreen->DestroyPixmap)(pWin->background.pixmap);
  1253.         if (!pWin->parent)
  1254.             MakeRootTile(pWin);
  1255.         else
  1256.                 pWin->backgroundState = ParentRelative;
  1257.         /* Note that the parent's backgroundTile's refcnt is NOT
  1258.          * incremented. */
  1259.         }
  1260.             else
  1261.         {    
  1262.                 pPixmap = (PixmapPtr)LookupIDByType(pixID, RT_PIXMAP);
  1263.                 if (pPixmap != (PixmapPtr) NULL)
  1264.         {
  1265.                     if  ((pPixmap->drawable.depth != pWin->drawable.depth) ||
  1266.              (pPixmap->drawable.pScreen != pScreen))
  1267.             {
  1268.                         error = BadMatch;
  1269.             goto PatchUp;
  1270.             }
  1271.             if (pWin->backgroundState == BackgroundPixmap)
  1272.             (* pScreen->DestroyPixmap)(pWin->background.pixmap);
  1273.             pWin->backgroundState = BackgroundPixmap;
  1274.             pWin->background.pixmap = pPixmap;
  1275.             pPixmap->refcnt++;
  1276.         }
  1277.             else
  1278.         {
  1279.             error = BadPixmap;
  1280.             client->errorValue = pixID;
  1281.             goto PatchUp;
  1282.         }
  1283.         }
  1284.         break;
  1285.       case CWBackPixel:
  1286.         if (pWin->backgroundState == BackgroundPixmap)
  1287.         (* pScreen->DestroyPixmap)(pWin->background.pixmap);
  1288.         pWin->backgroundState = BackgroundPixel;
  1289.         pWin->background.pixel = (CARD32 ) *pVlist;
  1290.                /* background pixel overrides background pixmap,
  1291.               so don't let the ddx layer see both bits */
  1292.             vmaskCopy &= ~CWBackPixmap;
  1293.         pVlist++;
  1294.         break;
  1295.       case CWBorderPixmap:
  1296.         pixID = (Pixmap ) *pVlist;
  1297.         pVlist++;
  1298.         if (pixID == CopyFromParent)
  1299.         {
  1300.         if (!pWin->parent ||
  1301.             (pWin->drawable.depth != pWin->parent->drawable.depth))
  1302.         {
  1303.             error = BadMatch;
  1304.             goto PatchUp;
  1305.         }
  1306.         if (pWin->borderIsPixel == FALSE)
  1307.             (* pScreen->DestroyPixmap)(pWin->border.pixmap);
  1308.         pWin->border = pWin->parent->border;
  1309.         if ((pWin->borderIsPixel = pWin->parent->borderIsPixel) == TRUE)
  1310.         {
  1311.             index = CWBorderPixel;
  1312.         }
  1313.                 else
  1314.         {
  1315.             pWin->parent->border.pixmap->refcnt++;
  1316.         }
  1317.         }
  1318.         else
  1319.         {    
  1320.         pPixmap = (PixmapPtr)LookupIDByType(pixID, RT_PIXMAP);
  1321.         if (pPixmap)
  1322.         {
  1323.                     if  ((pPixmap->drawable.depth != pWin->drawable.depth) ||
  1324.              (pPixmap->drawable.pScreen != pScreen))
  1325.             {
  1326.             error = BadMatch;
  1327.             goto PatchUp;
  1328.             }
  1329.             if (pWin->borderIsPixel == FALSE)
  1330.             (* pScreen->DestroyPixmap)(pWin->border.pixmap);
  1331.             pWin->borderIsPixel = FALSE;
  1332.             pWin->border.pixmap = pPixmap;
  1333.             pPixmap->refcnt++;
  1334.         }
  1335.                 else
  1336.         {
  1337.             error = BadPixmap;
  1338.             client->errorValue = pixID;
  1339.             goto PatchUp;
  1340.         }
  1341.         }
  1342.         break;
  1343.       case CWBorderPixel:
  1344.         if (pWin->borderIsPixel == FALSE)
  1345.         (* pScreen->DestroyPixmap)(pWin->border.pixmap);
  1346.         pWin->borderIsPixel = TRUE;
  1347.             pWin->border.pixel = (CARD32) *pVlist;
  1348.             /* border pixel overrides border pixmap,
  1349.                so don't let the ddx layer see both bits */
  1350.         vmaskCopy &= ~CWBorderPixmap;
  1351.         pVlist++;
  1352.             break;
  1353.       case CWBitGravity:
  1354.         val = (CARD8 )*pVlist;
  1355.         pVlist++;
  1356.         if (val > StaticGravity)
  1357.         {
  1358.         error = BadValue;
  1359.         client->errorValue = val;
  1360.         goto PatchUp;
  1361.         }
  1362.         pWin->bitGravity = val;
  1363.         break;
  1364.       case CWWinGravity:
  1365.         val = (CARD8 )*pVlist;
  1366.         pVlist++;
  1367.         if (val > StaticGravity)
  1368.         {
  1369.         error = BadValue;
  1370.         client->errorValue = val;
  1371.         goto PatchUp;
  1372.         }
  1373.         pWin->winGravity = val;
  1374.         break;
  1375.       case CWBackingStore:
  1376.         val = (CARD8 )*pVlist;
  1377.         pVlist++;
  1378.         if ((val != NotUseful) && (val != WhenMapped) && (val != Always))
  1379.         {
  1380.         error = BadValue;
  1381.         client->errorValue = val;
  1382.         goto PatchUp;
  1383.         }
  1384.         pWin->backingStore = val;
  1385.         break;
  1386.       case CWBackingPlanes:
  1387.         if (pWin->optional || ((CARD32)*pVlist != ~0L)) {
  1388.         if (!pWin->optional && !MakeWindowOptional (pWin))
  1389.         {
  1390.             error = BadAlloc;
  1391.             goto PatchUp;
  1392.         }
  1393.         pWin->optional->backingBitPlanes = (CARD32) *pVlist;
  1394.         if ((CARD32)*pVlist == ~0L)
  1395.             checkOptional = TRUE;
  1396.         }
  1397.         pVlist++;
  1398.         break;
  1399.       case CWBackingPixel:
  1400.         if (pWin->optional || (CARD32) *pVlist) {
  1401.         if (!pWin->optional && !MakeWindowOptional (pWin))
  1402.         {
  1403.             error = BadAlloc;
  1404.             goto PatchUp;
  1405.         }
  1406.         pWin->optional->backingPixel = (CARD32) *pVlist;
  1407.         if (!*pVlist)
  1408.             checkOptional = TRUE;
  1409.         }
  1410.         pVlist++;
  1411.         break;
  1412.       case CWSaveUnder:
  1413.         val = (BOOL) *pVlist;
  1414.         pVlist++;
  1415.         if ((val != xTrue) && (val != xFalse))
  1416.         {
  1417.         error = BadValue;
  1418.         client->errorValue = val;
  1419.         goto PatchUp;
  1420.         }
  1421. #ifdef DO_SAVE_UNDERS
  1422.         if ((pWin->saveUnder != val) && (pWin->viewable) &&
  1423.         DO_SAVE_UNDERS(pWin))
  1424.         {
  1425.         /*
  1426.          * Re-check all siblings and inferiors for obscurity or
  1427.          * exposition (hee hee).
  1428.          */
  1429.         if (pWin->saveUnder)
  1430.             deltaSaveUndersViewable--;
  1431.         else
  1432.             deltaSaveUndersViewable++;
  1433.         pWin->saveUnder = val;
  1434.         if (ChangeSaveUnder(pWin, pWin->nextSib))
  1435.             DoChangeSaveUnder(pWin->parent, pWin->nextSib);
  1436.         }
  1437.         else
  1438.         {
  1439.         pWin->saveUnder = val;
  1440.         }
  1441. #else
  1442.         pWin->saveUnder = val;
  1443. #endif /* DO_SAVE_UNDERS */
  1444.         break;
  1445.       case CWEventMask:
  1446.         result = EventSelectForWindow(pWin, client, (Mask )*pVlist);
  1447.         if (result)
  1448.         {
  1449.         error = result;
  1450.         goto PatchUp;
  1451.         }
  1452.         pVlist++;
  1453.         break;
  1454.       case CWDontPropagate:
  1455.         result = EventSuppressForWindow(pWin, client, (Mask )*pVlist,
  1456.                         &checkOptional);
  1457.         if (result)
  1458.         {
  1459.         error = result;
  1460.         goto PatchUp;
  1461.         }
  1462.         pVlist++;
  1463.         break;
  1464.       case CWOverrideRedirect:
  1465.         val = (BOOL ) *pVlist;
  1466.         pVlist++;
  1467.         if ((val != xTrue) && (val != xFalse))
  1468.         {
  1469.         error = BadValue;
  1470.         client->errorValue = val;
  1471.         goto PatchUp;
  1472.         }
  1473.         pWin->overrideRedirect = val;
  1474.         break;
  1475.       case CWColormap:
  1476.         cmap = (Colormap) *pVlist;
  1477.         pVlist++;
  1478.         if (cmap == CopyFromParent)
  1479.         {
  1480.         if (pWin->parent &&
  1481.             (!pWin->optional ||
  1482.               pWin->optional->visual == wVisual (pWin->parent)))
  1483.         {
  1484.             cmap = wColormap (pWin->parent);
  1485.         }
  1486.         else
  1487.             cmap = None;
  1488.         }
  1489.         if (cmap == None)
  1490.         {
  1491.         error = BadMatch;
  1492.         goto PatchUp;
  1493.         }
  1494.         pCmap = (ColormapPtr)LookupIDByType(cmap, RT_COLORMAP);
  1495.         if (!pCmap)
  1496.         {
  1497.         error = BadColor;
  1498.         client->errorValue = cmap;
  1499.         goto PatchUp;
  1500.         }
  1501.         if (pCmap->pVisual->vid != wVisual (pWin) ||
  1502.         pCmap->pScreen != pScreen)
  1503.         {
  1504.         error = BadMatch;
  1505.         goto PatchUp;
  1506.         }
  1507.         if (cmap != wColormap (pWin))
  1508.         {
  1509.         if (!pWin->optional)
  1510.         {
  1511.             if (!MakeWindowOptional (pWin))
  1512.             {
  1513.             error = BadAlloc;
  1514.             goto PatchUp;
  1515.             }
  1516.         }
  1517.         else if (pWin->parent && cmap == wColormap (pWin->parent))
  1518.             checkOptional = TRUE;
  1519.  
  1520.         /*
  1521.          * propagate the original colormap to any children
  1522.          * inheriting it
  1523.          */
  1524.  
  1525.         for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib)
  1526.         {
  1527.             if (!pChild->optional && !MakeWindowOptional (pChild))
  1528.             {
  1529.             error = BadAlloc;
  1530.             goto PatchUp;
  1531.             }
  1532.         }
  1533.  
  1534.         pWin->optional->colormap = cmap;
  1535.  
  1536.         /*
  1537.          * check on any children now matching the new colormap
  1538.          */
  1539.  
  1540.         for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib)
  1541.         {
  1542.             if (pChild->optional->colormap == cmap)
  1543.             CheckWindowOptionalNeed (pChild);
  1544.         }
  1545.  
  1546.         xE.u.u.type = ColormapNotify;
  1547.         xE.u.colormap.window = pWin->drawable.id;
  1548.         xE.u.colormap.colormap = cmap;
  1549.         xE.u.colormap.new = xTrue;
  1550.         xE.u.colormap.state = IsMapInstalled(cmap, pWin);
  1551.         DeliverEvents(pWin, &xE, 1, NullWindow);
  1552.         }
  1553.         break;
  1554.       case CWCursor:
  1555.         cursorID = (Cursor ) *pVlist;
  1556.         pVlist++;
  1557.         /*
  1558.          * install the new
  1559.          */
  1560.         if ( cursorID == None)
  1561.         {
  1562.             if (pWin == WindowTable[pWin->drawable.pScreen->myNum])
  1563.             pCursor = rootCursor;
  1564.             else
  1565.             pCursor = (CursorPtr) None;
  1566.         }
  1567.         else
  1568.         {
  1569.             pCursor = (CursorPtr)LookupIDByType(cursorID, RT_CURSOR);
  1570.             if (!pCursor)
  1571.             {
  1572.             error = BadCursor;
  1573.             client->errorValue = cursorID;
  1574.             goto PatchUp;
  1575.             }
  1576.         }
  1577.  
  1578.         if (pCursor != wCursor (pWin))
  1579.         {
  1580.             /*
  1581.               * patch up child windows so they don't lose cursors.
  1582.               */
  1583.  
  1584.             for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib)
  1585.         {
  1586.             if (!pChild->optional && !pChild->cursorIsNone &&
  1587.             !MakeWindowOptional (pChild))
  1588.             {
  1589.             error = BadAlloc;
  1590.             goto PatchUp;
  1591.             }
  1592.             }
  1593.  
  1594.         pOldCursor = 0;
  1595.         if (pCursor == (CursorPtr) None)
  1596.         {
  1597.             pWin->cursorIsNone = TRUE;
  1598.             if (pWin->optional)
  1599.             {
  1600.             pOldCursor = pWin->optional->cursor;
  1601.             pWin->optional->cursor = (CursorPtr) None;
  1602.             checkOptional = TRUE;
  1603.             }
  1604.         } else {
  1605.             if (!pWin->optional)
  1606.             {
  1607.             if (!MakeWindowOptional (pWin))
  1608.             {
  1609.                 error = BadAlloc;
  1610.                 goto PatchUp;
  1611.             }
  1612.             }
  1613.             else if (pWin->parent && pCursor == wCursor (pWin->parent))
  1614.             checkOptional = TRUE;
  1615.             pOldCursor = pWin->optional->cursor;
  1616.             pWin->optional->cursor = pCursor;
  1617.             pCursor->refcnt++;
  1618.             pWin->cursorIsNone = FALSE;
  1619.             /*
  1620.              * check on any children now matching the new cursor
  1621.              */
  1622.  
  1623.             for (pChild=pWin->firstChild; pChild; pChild=pChild->nextSib)
  1624.             {
  1625.             if (pChild->optional &&
  1626.                 (pChild->optional->cursor == pCursor))
  1627.                 CheckWindowOptionalNeed (pChild);
  1628.             }
  1629.         }
  1630.  
  1631.         if (pWin->realized)
  1632.             WindowHasNewCursor( pWin);
  1633.  
  1634.         /* Can't free cursor until here - old cursor
  1635.          * is needed in WindowHasNewCursor
  1636.          */
  1637.         if (pOldCursor)
  1638.             FreeCursor (pOldCursor, (Cursor)0);
  1639.         }
  1640.         break;
  1641.           default:
  1642.         error = BadValue;
  1643.         client->errorValue = vmask;
  1644.         goto PatchUp;
  1645.       }
  1646.       vmaskCopy |= index;
  1647.     }
  1648. PatchUp:
  1649.     if (checkOptional)
  1650.     CheckWindowOptionalNeed (pWin);
  1651.  
  1652.         /* We SHOULD check for an error value here XXX */
  1653.     (*pScreen->ChangeWindowAttributes)(pWin, vmaskCopy);
  1654.  
  1655.     /* 
  1656.         If the border contents have changed, redraw the border. 
  1657.     Note that this has to be done AFTER pScreen->ChangeWindowAttributes
  1658.         for the tile to be rotated, and the correct function selected.
  1659.     */
  1660.     if ((vmaskCopy & (CWBorderPixel | CWBorderPixmap))
  1661.     && pWin->viewable && HasBorder (pWin))
  1662.     {
  1663.     RegionRec exposed;
  1664.  
  1665.     (* pScreen->RegionInit)(&exposed, NullBox, 0);
  1666.         (* pScreen->Subtract)(&exposed, &pWin->borderClip, &pWin->winSize);
  1667.     (*pWin->drawable.pScreen->PaintWindowBorder)(pWin, &exposed, PW_BORDER);
  1668.         (* pScreen->RegionUninit)(&exposed);
  1669.     }
  1670.     return error;
  1671. }
  1672.  
  1673.  
  1674. /*****
  1675.  * GetWindowAttributes
  1676.  *    Notice that this is different than ChangeWindowAttributes
  1677.  *****/
  1678.  
  1679. GetWindowAttributes(pWin, client)
  1680.     register WindowPtr pWin;
  1681.     ClientPtr client;
  1682. {
  1683.     xGetWindowAttributesReply wa;
  1684.  
  1685.     wa.type = X_Reply;
  1686.     wa.bitGravity = pWin->bitGravity;
  1687.     wa.winGravity = pWin->winGravity;
  1688.     wa.backingStore  = pWin->backingStore;
  1689.     wa.length = (sizeof(xGetWindowAttributesReply) -
  1690.          sizeof(xGenericReply)) >> 2;
  1691.     wa.sequenceNumber = client->sequence;
  1692.     wa.backingBitPlanes =  wBackingBitPlanes (pWin);
  1693.     wa.backingPixel =  wBackingPixel (pWin);
  1694.     wa.saveUnder = (BOOL)pWin->saveUnder;
  1695.     wa.override = pWin->overrideRedirect;
  1696.     if (!pWin->mapped)
  1697.         wa.mapState = IsUnmapped;
  1698.     else if (pWin->realized)
  1699.         wa.mapState = IsViewable;
  1700.     else
  1701.         wa.mapState = IsUnviewable;
  1702.  
  1703.     wa.colormap =  wColormap (pWin);
  1704.     wa.mapInstalled = (wa.colormap == None) ? xFalse
  1705.                         : IsMapInstalled(wa.colormap, pWin);
  1706.  
  1707.     wa.yourEventMask = EventMaskForClient(pWin, client);
  1708.     wa.allEventMasks = pWin->eventMask | wOtherEventMasks (pWin);
  1709.     wa.doNotPropagateMask = wDontPropagateMask (pWin);
  1710.     wa.class = pWin->drawable.class;
  1711.     wa.visualID = wVisual (pWin);
  1712.  
  1713.     WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa);
  1714. }
  1715.  
  1716.  
  1717. static WindowPtr
  1718. MoveWindowInStack(pWin, pNextSib)
  1719.     register WindowPtr pWin, pNextSib;
  1720. {
  1721.     register WindowPtr pParent = pWin->parent;
  1722.     WindowPtr pFirstChange = pWin; /* highest window where list changes */
  1723.  
  1724.     if (pWin->nextSib != pNextSib)
  1725.     {
  1726.         if (!pNextSib)        /* move to bottom */
  1727.     {
  1728.             if (pParent->firstChild == pWin)
  1729.                 pParent->firstChild = pWin->nextSib;
  1730.         /* if (pWin->nextSib) */     /* is always True: pNextSib == NULL
  1731.                           * and pWin->nextSib != pNextSib
  1732.                       * therefore pWin->nextSib != NULL */
  1733.         pFirstChange = pWin->nextSib;
  1734.         pWin->nextSib->prevSib = pWin->prevSib;
  1735.         if (pWin->prevSib)
  1736.                 pWin->prevSib->nextSib = pWin->nextSib;
  1737.             pParent->lastChild->nextSib = pWin;
  1738.             pWin->prevSib = pParent->lastChild;
  1739.             pWin->nextSib = NullWindow;
  1740.             pParent->lastChild = pWin;
  1741.     }
  1742.         else if (pParent->firstChild == pNextSib) /* move to top */
  1743.         {
  1744.         pFirstChange = pWin;
  1745.         if (pParent->lastChild == pWin)
  1746.                pParent->lastChild = pWin->prevSib;
  1747.         if (pWin->nextSib)
  1748.         pWin->nextSib->prevSib = pWin->prevSib;
  1749.         if (pWin->prevSib)
  1750.                 pWin->prevSib->nextSib = pWin->nextSib;
  1751.         pWin->nextSib = pParent->firstChild;
  1752.         pWin->prevSib = (WindowPtr ) NULL;
  1753.         pNextSib->prevSib = pWin;
  1754.         pParent->firstChild = pWin;
  1755.     }
  1756.         else            /* move in middle of list */
  1757.         {
  1758.         WindowPtr pOldNext = pWin->nextSib;
  1759.  
  1760.         pFirstChange = NullWindow;
  1761.             if (pParent->firstChild == pWin)
  1762.                 pFirstChange = pParent->firstChild = pWin->nextSib;
  1763.         if (pParent->lastChild == pWin) {
  1764.            pFirstChange = pWin;
  1765.                pParent->lastChild = pWin->prevSib;
  1766.         }
  1767.         if (pWin->nextSib)
  1768.         pWin->nextSib->prevSib = pWin->prevSib;
  1769.         if (pWin->prevSib)
  1770.                 pWin->prevSib->nextSib = pWin->nextSib;
  1771.             pWin->nextSib = pNextSib;
  1772.             pWin->prevSib = pNextSib->prevSib;
  1773.         if (pNextSib->prevSib)
  1774.                 pNextSib->prevSib->nextSib = pWin;
  1775.             pNextSib->prevSib = pWin;
  1776.         if (!pFirstChange) {             /* do we know it yet? */
  1777.             pFirstChange = pParent->firstChild;  /* no, search from top */
  1778.             while ((pFirstChange != pWin) && (pFirstChange != pOldNext))
  1779.              pFirstChange = pFirstChange->nextSib;
  1780.         }
  1781.     }
  1782.     }
  1783.  
  1784.     return( pFirstChange );
  1785. }
  1786.  
  1787. RegionPtr
  1788. CreateUnclippedWinSize (pWin)
  1789.     register WindowPtr   pWin;
  1790. {
  1791.     RegionPtr    pRgn;
  1792.     BoxRec    box;
  1793.  
  1794.     box.x1 = pWin->drawable.x;
  1795.     box.y1 = pWin->drawable.y;
  1796.     box.x2 = pWin->drawable.x + (int) pWin->drawable.width;
  1797.     box.y2 = pWin->drawable.y + (int) pWin->drawable.height;
  1798.     pRgn = (*pWin->drawable.pScreen->RegionCreate) (&box, 1);
  1799. #ifdef SHAPE
  1800.     if (wBoundingShape (pWin) || wClipShape (pWin)) {
  1801.         ScreenPtr    pScreen = pWin->drawable.pScreen;
  1802.  
  1803.     (*pScreen->TranslateRegion)
  1804.         (pRgn, - pWin->drawable.x, - pWin->drawable.y);
  1805.     if (wBoundingShape (pWin))
  1806.         (*pScreen->Intersect)
  1807.         (pRgn, pRgn, wBoundingShape (pWin));
  1808.     if (wClipShape (pWin))
  1809.         (*pScreen->Intersect)
  1810.         (pRgn, pRgn, wClipShape (pWin));
  1811.     (*pScreen->TranslateRegion)
  1812.         (pRgn, pWin->drawable.x, pWin->drawable.y);
  1813.     }
  1814. #endif
  1815.     return pRgn;
  1816. }
  1817.  
  1818. static void
  1819. SetWinSize (pWin)
  1820.     register WindowPtr pWin;
  1821. {
  1822.     ClippedRegionFromBox(pWin->parent, &pWin->winSize,
  1823.              pWin->drawable.x, pWin->drawable.y,
  1824.               (int)pWin->drawable.width,
  1825.               (int)pWin->drawable.height);
  1826. #ifdef SHAPE
  1827.     if (wBoundingShape (pWin) || wClipShape (pWin)) {
  1828.         ScreenPtr    pScreen = pWin->drawable.pScreen;
  1829.  
  1830.     (*pScreen->TranslateRegion)
  1831.         (&pWin->winSize, - pWin->drawable.x, - pWin->drawable.y);
  1832.     if (wBoundingShape (pWin))
  1833.         (*pScreen->Intersect)
  1834.         (&pWin->winSize, &pWin->winSize, wBoundingShape (pWin));
  1835.     if (wClipShape (pWin))
  1836.         (*pScreen->Intersect)
  1837.         (&pWin->winSize, &pWin->winSize, wClipShape (pWin));
  1838.     (*pScreen->TranslateRegion)
  1839.         (&pWin->winSize, pWin->drawable.x, pWin->drawable.y);
  1840.     }
  1841. #endif
  1842. }
  1843.  
  1844. static void
  1845. SetBorderSize (pWin)
  1846.     register WindowPtr pWin;
  1847. {
  1848.     int    bw;
  1849.  
  1850.     if (HasBorder (pWin)) {
  1851.     bw = wBorderWidth (pWin);
  1852.     ClippedRegionFromBox(pWin->parent, &pWin->borderSize,
  1853.         pWin->drawable.x - bw, pWin->drawable.y - bw,
  1854.         (int)(pWin->drawable.width + (bw<<1)),
  1855.          (int)(pWin->drawable.height + (bw<<1)));
  1856. #ifdef SHAPE
  1857.         if (wBoundingShape (pWin)) {
  1858.             ScreenPtr    pScreen = pWin->drawable.pScreen;
  1859.  
  1860.         (*pScreen->TranslateRegion)
  1861.             (&pWin->borderSize, - pWin->drawable.x, - pWin->drawable.y);
  1862.         (*pScreen->Intersect)
  1863.             (&pWin->borderSize, &pWin->borderSize, wBoundingShape (pWin));
  1864.         (*pScreen->TranslateRegion)
  1865.             (&pWin->borderSize, pWin->drawable.x, pWin->drawable.y);
  1866.         (*pScreen->Union) (&pWin->borderSize,
  1867.                    &pWin->borderSize, &pWin->winSize);
  1868.         }
  1869. #endif
  1870.     } else {
  1871.     (* pWin->drawable.pScreen->RegionCopy)(&pWin->borderSize,
  1872.                            &pWin->winSize);
  1873.     }
  1874. }
  1875.  
  1876. static void
  1877. MoveWindow(pWin, x, y, pNextSib, kind)
  1878.     register WindowPtr pWin;
  1879.     short x,y;
  1880.     WindowPtr pNextSib;
  1881.     VTKind kind;
  1882. {
  1883.     WindowPtr pParent;
  1884.     Bool WasViewable = (Bool)(pWin->viewable);
  1885.     short bw;
  1886.     RegionPtr oldRegion;
  1887.     DDXPointRec oldpt;
  1888.     Bool anyMarked;
  1889.     register ScreenPtr pScreen;
  1890.     WindowPtr windowToValidate;
  1891. #ifdef DO_SAVE_UNDERS
  1892.     Bool dosave = FALSE;
  1893. #endif
  1894.  
  1895.     /* if this is a root window, can't be moved */
  1896.     if (!(pParent = pWin->parent))
  1897.        return ;
  1898.     pScreen = pWin->drawable.pScreen;
  1899.     bw = wBorderWidth (pWin);
  1900.  
  1901.     oldpt.x = pWin->drawable.x;
  1902.     oldpt.y = pWin->drawable.y;
  1903.     if (WasViewable)
  1904.     {
  1905.         oldRegion = (* pScreen->RegionCreate)(NullBox, 1);
  1906.         (* pScreen->RegionCopy)(oldRegion, &pWin->borderClip);
  1907.     anyMarked = MarkOverlappedWindows(pWin, pWin);
  1908.     }
  1909.     pWin->origin.x = x + (int)bw;
  1910.     pWin->origin.y = y + (int)bw;
  1911.     x = pWin->drawable.x = pParent->drawable.x + x + (int)bw;
  1912.     y = pWin->drawable.y = pParent->drawable.y + y + (int)bw;
  1913.  
  1914.     SetWinSize (pWin);
  1915.     SetBorderSize (pWin);
  1916.  
  1917.     (* pScreen->PositionWindow)(pWin, x, y);
  1918.  
  1919.     windowToValidate = MoveWindowInStack(pWin, pNextSib);
  1920.  
  1921.     ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0);
  1922.  
  1923.     if (WasViewable)
  1924.     {
  1925.  
  1926.         anyMarked |= MarkOverlappedWindows(pWin, windowToValidate);
  1927. #ifdef DO_SAVE_UNDERS
  1928.     if (DO_SAVE_UNDERS(pWin))
  1929.     {
  1930.         if (pWin->saveUnder)
  1931.         dosave = ChangeSaveUnder(pWin, windowToValidate);
  1932.         else
  1933.         dosave = CheckSaveUnder(pWin);
  1934.     }
  1935. #endif /* DO_SAVE_UNDERS */
  1936.  
  1937.     if (anyMarked)
  1938.     {
  1939.         (* pScreen->ValidateTree)(pParent, NullWindow, kind);
  1940.         (* pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, oldRegion);
  1941.         (* pScreen->RegionDestroy)(oldRegion);
  1942.         /* XXX need to retile border if ParentRelative origin */
  1943.         HandleExposures(pParent);
  1944.     }
  1945. #ifdef DO_SAVE_UNDERS
  1946.     if (dosave)
  1947.         DoChangeSaveUnder(pWin->parent, windowToValidate);
  1948. #endif /* DO_SAVE_UNDERS */
  1949.     if (anyMarked && pScreen->PostValidateTree)
  1950.         (* pScreen->PostValidateTree)(pParent, NullWindow, kind);
  1951.     }
  1952.     if (pWin->realized)
  1953.     WindowsRestructured ();
  1954. }
  1955.  
  1956. void
  1957. GravityTranslate (x, y, oldx, oldy, dw, dh, gravity, destx, desty)
  1958.     register int x, y;        /* new window position */
  1959.     int        oldx, oldy;    /* old window position */
  1960.     int        dw, dh;
  1961.     unsigned    gravity;
  1962.     register int *destx, *desty;    /* position relative to gravity */
  1963. {
  1964.     switch (gravity) {
  1965.     case NorthGravity:
  1966.     *destx = x + dw / 2;
  1967.     *desty = y;
  1968.     break;
  1969.     case NorthEastGravity:
  1970.     *destx = x + dw;
  1971.     *desty = y;
  1972.     break;
  1973.     case WestGravity:
  1974.     *destx = x;
  1975.     *desty = y + dh / 2;
  1976.     break;
  1977.     case CenterGravity:
  1978.     *destx = x + dw / 2;
  1979.     *desty = y + dh / 2;
  1980.     break;
  1981.     case EastGravity:
  1982.     *destx = x + dw;
  1983.     *desty = y + dh / 2;
  1984.     break;
  1985.     case SouthWestGravity:
  1986.     *destx = x;
  1987.     *desty = y + dh;
  1988.     break;
  1989.     case SouthGravity:
  1990.     *destx = x + dw / 2;
  1991.     *desty = y + dh;
  1992.     break;
  1993.     case SouthEastGravity:
  1994.     *destx = x + dw;
  1995.     *desty = y + dh;
  1996.     break;
  1997.     case StaticGravity:
  1998.     *destx = oldx;
  1999.     *desty = oldy;
  2000.     break;
  2001.     default:
  2002.     *destx = x;
  2003.     *desty = y;
  2004.     break;
  2005.     }
  2006. }
  2007.  
  2008. /* XXX need to retile border on each window with ParentRelative origin */
  2009. static void
  2010. ResizeChildrenWinSize(pWin, dx, dy, dw, dh)
  2011.     register WindowPtr pWin;
  2012.     int dx, dy, dw, dh;
  2013. {
  2014.     register ScreenPtr pScreen;
  2015.     register WindowPtr pSib, pChild;
  2016.     Bool resized = (dw || dh);
  2017.  
  2018.     pScreen = pWin->drawable.pScreen;
  2019.  
  2020.     for (pSib = pWin->firstChild; pSib; pSib = pSib->nextSib)
  2021.     {
  2022.     if (resized && (pSib->winGravity > NorthWestGravity))
  2023.     {
  2024.         int cwsx, cwsy;
  2025.  
  2026.         cwsx = pSib->origin.x;
  2027.         cwsy = pSib->origin.y;
  2028.         GravityTranslate (cwsx, cwsy, cwsx - dx, cwsy - dy, dw, dh,
  2029.             pSib->winGravity, &cwsx, &cwsy);
  2030.         if (cwsx != pSib->origin.x || cwsy != pSib->origin.y)
  2031.         {
  2032.         xEvent event;
  2033.  
  2034.         event.u.u.type = GravityNotify;
  2035.         event.u.gravity.window = pSib->drawable.id;
  2036.         event.u.gravity.x = cwsx - wBorderWidth (pSib);
  2037.         event.u.gravity.y = cwsy - wBorderWidth (pSib);
  2038.         DeliverEvents (pSib, &event, 1, NullWindow);
  2039.         pSib->origin.x = cwsx;
  2040.         pSib->origin.y = cwsy;
  2041.         }
  2042.     }
  2043.     pSib->drawable.x = pWin->drawable.x + pSib->origin.x;
  2044.     pSib->drawable.y = pWin->drawable.y + pSib->origin.y;
  2045.     SetWinSize (pSib);
  2046.     SetBorderSize (pSib);
  2047.     (* pScreen->PositionWindow)(pSib, pSib->drawable.x, pSib->drawable.y);
  2048.     if (pChild = pSib->firstChild)
  2049.     {
  2050.         while (1)
  2051.         {
  2052.         pChild->drawable.x = pChild->parent->drawable.x +
  2053.                      pChild->origin.x;
  2054.         pChild->drawable.y = pChild->parent->drawable.y +
  2055.                      pChild->origin.y;
  2056.         SetWinSize (pChild);
  2057.         SetBorderSize (pChild);
  2058.         (* pScreen->PositionWindow)(pChild,
  2059.                     pChild->drawable.x, pChild->drawable.y);
  2060.         if (pChild->firstChild)
  2061.         {
  2062.             pChild = pChild->firstChild;
  2063.             continue;
  2064.         }
  2065.         while (!pChild->nextSib && (pChild != pSib))
  2066.             pChild = pChild->parent;
  2067.         if (pChild == pSib)
  2068.             break;
  2069.         pChild = pChild->nextSib;
  2070.         }
  2071.     }
  2072.     }
  2073. }
  2074.  
  2075. /*
  2076.  * pValid is a region of the screen which has been
  2077.  * successfully copied -- recomputed exposed regions for affected windows
  2078.  */
  2079.  
  2080. static int
  2081. RecomputeExposures (pWin, pValid)
  2082.     register WindowPtr    pWin;
  2083.     RegionPtr    pValid;
  2084. {
  2085.     register ScreenPtr    pScreen;
  2086.  
  2087.     if (pWin->valdata)
  2088.     {
  2089.     pScreen = pWin->drawable.pScreen;
  2090.     /*
  2091.      * compute exposed regions of this window
  2092.      */
  2093.     (*pScreen->Subtract)(&pWin->valdata->after.exposed, &pWin->clipList, pValid);
  2094.     /*
  2095.      * compute exposed regions of the border
  2096.      */
  2097.     (*pScreen->Subtract)(&pWin->valdata->after.borderExposed,
  2098.                  &pWin->borderClip, &pWin->winSize);
  2099.     (*pScreen->Subtract)(&pWin->valdata->after.borderExposed,
  2100.                  &pWin->valdata->after.borderExposed, pValid);
  2101.     return WT_WALKCHILDREN;
  2102.     }
  2103.     return WT_NOMATCH;
  2104. }
  2105.  
  2106.  
  2107. static void
  2108. SlideAndSizeWindow(pWin, x, y, w, h, pSib)
  2109.     register WindowPtr pWin;
  2110.     short x,y;
  2111.     unsigned short w, h;
  2112.     WindowPtr pSib;
  2113. {
  2114.     WindowPtr pParent;
  2115.     Bool WasViewable = (Bool)(pWin->viewable);
  2116.     unsigned short width = pWin->drawable.width,
  2117.                    height = pWin->drawable.height;
  2118.     short oldx = pWin->drawable.x,
  2119.           oldy = pWin->drawable.y;
  2120.     int bw = wBorderWidth (pWin);
  2121.     short dw, dh;
  2122.     DDXPointRec oldpt;
  2123.     RegionPtr oldRegion;
  2124.     Bool anyMarked;
  2125.     register ScreenPtr pScreen;
  2126.     WindowPtr pFirstChange;
  2127.     register WindowPtr pChild;
  2128.     RegionPtr    gravitate[StaticGravity + 1];
  2129.     register unsigned g;
  2130.     int        nx, ny;        /* destination x,y */
  2131.     int        newx, newy;    /* new inner window position */
  2132.     RegionPtr    pRegion;
  2133.     RegionPtr    destClip;    /* portions of destination already written */
  2134.     RegionPtr    oldWinClip;    /* old clip list for window */
  2135.     RegionPtr    borderVisible = NullRegion; /* visible area of the border */
  2136.     RegionPtr    bsExposed = NullRegion;        /* backing store exposures */
  2137.     Bool    shrunk = FALSE; /* shrunk in an inner dimension */
  2138.     Bool    moved = FALSE;    /* window position changed */
  2139. #ifdef DO_SAVE_UNDERS
  2140.     Bool    dosave = FALSE;
  2141. #endif
  2142.  
  2143.     /* if this is a root window, can't be resized */
  2144.     if (!(pParent = pWin->parent))
  2145.         return ;
  2146.  
  2147.     pScreen = pWin->drawable.pScreen;
  2148.     newx = pParent->drawable.x + x + bw;
  2149.     newy = pParent->drawable.y + y + bw;
  2150.     if (WasViewable)
  2151.     {
  2152.     anyMarked = FALSE;
  2153.     /*
  2154.      * save the visible region of the window
  2155.      */
  2156.     oldRegion = (*pScreen->RegionCreate) (NullBox, 1);
  2157.     (*pScreen->RegionCopy) (oldRegion, &pWin->winSize);
  2158.  
  2159.     /*
  2160.      * catagorize child windows into regions to be moved
  2161.      */
  2162.     for (g = 0; g <= StaticGravity; g++)
  2163.         gravitate[g] = (RegionPtr) NULL;
  2164.     for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
  2165.     {
  2166.         g = pChild->winGravity;
  2167.         if (g != UnmapGravity)
  2168.         {
  2169.         if (!gravitate[g])
  2170.             gravitate[g] = (*pScreen->RegionCreate) (NullBox, 1);
  2171.         (*pScreen->Union) (gravitate[g],
  2172.                    gravitate[g], &pChild->borderClip);
  2173.         }
  2174.         else
  2175.         {
  2176.         UnmapWindow(pChild, TRUE);
  2177.         anyMarked = TRUE;
  2178.         }
  2179.     }
  2180.     anyMarked |= MarkOverlappedWindows(pWin, pWin);
  2181.  
  2182.     oldWinClip = NULL;
  2183.     if (pWin->bitGravity != ForgetGravity)
  2184.     {
  2185.         oldWinClip = (*pScreen->RegionCreate) (NullBox, 1);
  2186.         (*pScreen->RegionCopy) (oldWinClip, &pWin->clipList);
  2187.     }
  2188.         /*
  2189.           * if the window is changing size, borderExposed
  2190.           * can't be computed correctly without some help.
  2191.           */
  2192.         if (pWin->drawable.height > h || pWin->drawable.width > w)
  2193.         shrunk = TRUE;
  2194.  
  2195.     if (newx != oldx || newy != oldy)
  2196.         moved = TRUE;
  2197.  
  2198.     if ((pWin->drawable.height != h || pWin->drawable.width != w) &&
  2199.         HasBorder (pWin))
  2200.     {
  2201.         borderVisible = (*pScreen->RegionCreate) (NullBox, 1);
  2202.         /* for tiled borders, we punt and draw the whole thing */
  2203.         if (pWin->borderIsPixel || !moved)
  2204.         {
  2205.             if (shrunk || moved)
  2206.             (*pScreen->Subtract) (borderVisible,
  2207.                       &pWin->borderClip,
  2208.                             &pWin->winSize);
  2209.             else
  2210.             (*pScreen->RegionCopy) (borderVisible,
  2211.                         &pWin->borderClip);
  2212.         }
  2213.     }
  2214.     }
  2215.     pWin->origin.x = x + bw;
  2216.     pWin->origin.y = y + bw;
  2217.     pWin->drawable.height = h;
  2218.     pWin->drawable.width = w;
  2219.  
  2220.     x = pWin->drawable.x = newx;
  2221.     y = pWin->drawable.y = newy;
  2222.  
  2223.     SetWinSize (pWin);
  2224.     SetBorderSize (pWin);
  2225.  
  2226.     dw = (int)w - (int)width;
  2227.     dh = (int)h - (int)height;
  2228.     ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh);
  2229.  
  2230.     /* let the hardware adjust background and border pixmaps, if any */
  2231.     (* pScreen->PositionWindow)(pWin, x, y);
  2232.  
  2233.     pFirstChange = MoveWindowInStack(pWin, pSib);
  2234.  
  2235.     if (WasViewable)
  2236.     {
  2237.     pRegion = (*pScreen->RegionCreate) (NullBox, 1);
  2238.     if (pWin->backStorage)
  2239.         (*pScreen->RegionCopy) (pRegion, &pWin->clipList);
  2240.  
  2241.     anyMarked |= MarkOverlappedWindows(pWin, pFirstChange);
  2242.  
  2243.     if (pWin->valdata)
  2244.      {
  2245.         pWin->valdata->before.resized = TRUE;
  2246.         pWin->valdata->before.borderVisible = borderVisible;
  2247.     }
  2248.  
  2249. #ifdef DO_SAVE_UNDERS
  2250.     if (DO_SAVE_UNDERS(pWin))
  2251.     {
  2252.         if (pWin->saveUnder)
  2253.         dosave = ChangeSaveUnder(pWin, pFirstChange);
  2254.         else
  2255.         dosave = CheckSaveUnder(pWin);
  2256.     }
  2257. #endif /* DO_SAVE_UNDERS */
  2258.  
  2259.     if (anyMarked)
  2260.         (* pScreen->ValidateTree)(pParent, pFirstChange, VTOther);
  2261.     /*
  2262.      * the entire window is trashed unless bitGravity
  2263.      * recovers portions of it
  2264.      */
  2265.     (*pScreen->RegionCopy) (&pWin->valdata->after.exposed, &pWin->clipList);
  2266.     }
  2267.  
  2268.     GravityTranslate (x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny);
  2269.  
  2270.     if (pWin->backStorage &&
  2271.     ((pWin->backingStore == Always) || WasViewable))
  2272.     {
  2273.     if (!WasViewable)
  2274.         pRegion = &pWin->clipList; /* a convenient empty region */
  2275.     if (pWin->bitGravity == ForgetGravity)
  2276.         bsExposed = (* pScreen->TranslateBackingStore)
  2277.                 (pWin, 0, 0, NullRegion, oldx, oldy);
  2278.     else
  2279.     {
  2280.         bsExposed = (* pScreen->TranslateBackingStore)
  2281.                  (pWin, nx - x, ny - y, pRegion, oldx, oldy);
  2282.     }
  2283.     }
  2284.  
  2285.     if (WasViewable)
  2286.     {
  2287.     /* avoid the border */
  2288.     if (HasBorder (pWin))
  2289.     {
  2290.         int    offx, offy, dx, dy;
  2291.         offx = 0;
  2292.         offy = 0;
  2293.         for (g = 0; g <= StaticGravity; g++)
  2294.         {
  2295.         if (!gravitate[g])
  2296.             continue;
  2297.  
  2298.         /* align winSize to gravitate[g] */
  2299.         GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny);
  2300.         
  2301.         dx = (nx - oldx) - offx;
  2302.         dy = (ny - oldy) - offy;
  2303.         if (dx || dy)
  2304.         {
  2305.             (*pScreen->TranslateRegion) (&pWin->winSize, dx, dy);
  2306.             offx += dx;
  2307.             offy += dy;
  2308.         }
  2309.         (*pScreen->Intersect) (gravitate[g], gravitate[g], &pWin->winSize);
  2310.         }
  2311.         /* get winSize back where it belongs */
  2312.         if (offx || offy)
  2313.         (*pScreen->TranslateRegion) (&pWin->winSize, -offx, -offy);
  2314.     }
  2315.     /*
  2316.      * add screen bits to the appropriate bucket
  2317.      */
  2318.  
  2319.     if (oldWinClip)
  2320.     {
  2321.         /*
  2322.          * clip to new clipList
  2323.          */
  2324.         (*pScreen->RegionCopy) (pRegion, oldWinClip);
  2325.         (*pScreen->TranslateRegion) (pRegion, nx - oldx, ny - oldy);
  2326.         (*pScreen->Intersect) (oldWinClip, pRegion, &pWin->clipList);
  2327.         /*
  2328.          * don't step on any gravity bits which will be copied after this
  2329.          * region.  Note -- this assumes that the regions will be copied
  2330.          * in gravity order.
  2331.          */
  2332.         for (g = pWin->bitGravity + 1; g <= StaticGravity; g++)
  2333.         {
  2334.         if (gravitate[g])
  2335.             (*pScreen->Subtract) (oldWinClip, oldWinClip, gravitate[g]);
  2336.         }
  2337.         (*pScreen->TranslateRegion) (oldWinClip, oldx - nx, oldy - ny);
  2338.         g = pWin->bitGravity;
  2339.         if (!gravitate[g])
  2340.         gravitate[g] = oldWinClip;
  2341.         else
  2342.         {
  2343.         (*pScreen->Union) (gravitate[g], gravitate[g], oldWinClip);
  2344.         (*pScreen->RegionDestroy) (oldWinClip);
  2345.         }
  2346.     }
  2347.  
  2348.     /*
  2349.      * move the bits on the screen
  2350.      */
  2351.  
  2352.     destClip = NULL;
  2353.  
  2354.     for (g = 0; g <= StaticGravity; g++)
  2355.     {
  2356.         if (!gravitate[g])
  2357.             continue;
  2358.  
  2359.         GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny);
  2360.  
  2361.             oldpt.x = oldx + (x - nx);
  2362.         oldpt.y = oldy + (y - ny);
  2363.  
  2364.         /* Note that gravitate[g] is *translated* by CopyWindow */
  2365.  
  2366.         /* only copy the remaining useful bits */
  2367.  
  2368.         (*pScreen->Intersect) (gravitate[g], gravitate[g], oldRegion);
  2369.  
  2370.         /* clip to not overwrite already copied areas */
  2371.  
  2372.         if (destClip) {
  2373.         (*pScreen->TranslateRegion) (destClip, oldpt.x - x, oldpt.y - y);
  2374.         (*pScreen->Subtract) (gravitate[g], gravitate[g], destClip);
  2375.         (*pScreen->TranslateRegion) (destClip, x - oldpt.x, y - oldpt.y);
  2376.         }
  2377.  
  2378.         /* and move those bits */
  2379.  
  2380.         if (oldpt.x != x || oldpt.y != y)
  2381.         (*pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, gravitate[g]);
  2382.  
  2383.         /* remove any overwritten bits from the remaining useful bits */
  2384.  
  2385.         (*pScreen->Subtract) (oldRegion, oldRegion, gravitate[g]);
  2386.  
  2387.         /*
  2388.          * recompute exposed regions of child windows
  2389.          */
  2390.     
  2391.         for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
  2392.         {
  2393.         if (pChild->winGravity != g)
  2394.             continue;
  2395.         (*pScreen->Intersect) (pRegion,
  2396.                        &pChild->borderClip, gravitate[g]);
  2397.         TraverseTree (pChild, RecomputeExposures, (pointer)pRegion);
  2398.         }
  2399.  
  2400.         /*
  2401.          * remove the successfully copied regions of the
  2402.          * window from its exposed region
  2403.          */
  2404.  
  2405.         if (g == pWin->bitGravity)
  2406.         (*pScreen->Subtract)(&pWin->valdata->after.exposed,
  2407.                      &pWin->valdata->after.exposed, gravitate[g]);
  2408.         if (!destClip)
  2409.             destClip = gravitate[g];
  2410.         else
  2411.         {
  2412.         (*pScreen->Union) (destClip, destClip, gravitate[g]);
  2413.         (*pScreen->RegionDestroy) (gravitate[g]);
  2414.         }
  2415.     }
  2416.  
  2417.     (*pScreen->RegionDestroy) (oldRegion);
  2418.     (*pScreen->RegionDestroy) (pRegion);
  2419.     if (destClip)
  2420.         (*pScreen->RegionDestroy) (destClip);
  2421.     if (bsExposed)
  2422.     {
  2423.         RegionPtr    valExposed = NullRegion;
  2424.  
  2425.         if (pWin->valdata)
  2426.         valExposed = &pWin->valdata->after.exposed;
  2427.         (*pScreen->WindowExposures) (pWin, valExposed, bsExposed);
  2428.         if (valExposed)
  2429.         (*pScreen->RegionEmpty) (valExposed);
  2430.         (*pScreen->RegionDestroy) (bsExposed);
  2431.     }
  2432.     if (anyMarked)
  2433.         HandleExposures(pParent);
  2434. #ifdef DO_SAVE_UNDERS
  2435.     if (dosave)
  2436.         DoChangeSaveUnder(pParent, pFirstChange);
  2437. #endif /* DO_SAVE_UNDERS */
  2438.     if (anyMarked && pScreen->PostValidateTree)
  2439.         (* pScreen->PostValidateTree)(pParent, pFirstChange, VTOther);
  2440.     }
  2441.     else if (bsExposed)
  2442.     {
  2443.     (*pScreen->WindowExposures) (pWin, NullRegion, bsExposed);
  2444.     (*pScreen->RegionDestroy) (bsExposed);
  2445.     }
  2446.     if (pWin->realized)
  2447.     WindowsRestructured ();
  2448. }
  2449.  
  2450. /* Keeps the same inside(!) origin */
  2451.  
  2452. static void
  2453. ChangeBorderWidth(pWin, width)
  2454.     register WindowPtr pWin;
  2455.     unsigned short width;
  2456. {
  2457.     WindowPtr pParent;
  2458.     int oldwidth;
  2459.     Bool anyMarked;
  2460.     register ScreenPtr pScreen;
  2461.     Bool WasViewable = (Bool)(pWin->viewable);
  2462.     Bool HadBorder;
  2463. #ifdef DO_SAVE_UNDERS
  2464.     Bool    dosave = FALSE;
  2465. #endif
  2466.  
  2467.     oldwidth = wBorderWidth (pWin);
  2468.     if (oldwidth == width)
  2469.         return;
  2470.     HadBorder = HasBorder(pWin);
  2471.     pScreen = pWin->drawable.pScreen;
  2472.     pParent = pWin->parent;
  2473.     if (WasViewable && width < oldwidth)
  2474.     anyMarked = MarkOverlappedWindows(pWin, pWin);
  2475.  
  2476.     pWin->borderWidth = width;
  2477.     SetBorderSize (pWin);
  2478.  
  2479.     if (WasViewable)
  2480.     {
  2481.         if (width > oldwidth)
  2482.     {
  2483.         anyMarked = MarkOverlappedWindows(pWin, pWin);
  2484.             /*
  2485.               * save the old border visible region to correctly compute
  2486.               * borderExposed.
  2487.               */
  2488.         if (pWin->valdata && HadBorder)
  2489.         {
  2490.             RegionPtr   borderVisible;
  2491.             borderVisible = (*pScreen->RegionCreate) (NULL, 1);
  2492.             (*pScreen->Subtract) (borderVisible,
  2493.                       &pWin->borderClip, &pWin->winSize);
  2494.             pWin->valdata->before.borderVisible = borderVisible;
  2495.         }
  2496.     }
  2497. #ifdef DO_SAVE_UNDERS
  2498.     if (DO_SAVE_UNDERS(pWin))
  2499.     {
  2500.         if (pWin->saveUnder)
  2501.         dosave = ChangeSaveUnder(pWin, pWin->nextSib);
  2502.         else
  2503.         dosave = CheckSaveUnder(pWin);
  2504.     }
  2505. #endif /* DO_SAVE_UNDERS */
  2506.  
  2507.     if (anyMarked)
  2508.     {
  2509.         (* pScreen->ValidateTree)(pParent, pWin, VTOther);
  2510.         HandleExposures(pParent);
  2511.     }
  2512. #ifdef DO_SAVE_UNDERS
  2513.     if (dosave)
  2514.         DoChangeSaveUnder(pParent, pWin->nextSib);
  2515. #endif /* DO_SAVE_UNDERS */
  2516.     if (anyMarked && pScreen->PostValidateTree)
  2517.         (* pScreen->PostValidateTree)(pParent, pWin, VTOther);
  2518.     }
  2519.     if (pWin->realized)
  2520.     WindowsRestructured ();
  2521. }
  2522.  
  2523.  
  2524. #define GET_INT16(m, f) \
  2525.       if (m & mask) \
  2526.           { \
  2527.              f = (INT16) *pVlist;\
  2528.          pVlist++; \
  2529.          }
  2530. #define GET_CARD16(m, f) \
  2531.      if (m & mask) \
  2532.          { \
  2533.             f = (CARD16) *pVlist;\
  2534.          pVlist++;\
  2535.          }
  2536.  
  2537. #define GET_CARD8(m, f) \
  2538.      if (m & mask) \
  2539.          { \
  2540.             f = (CARD8) *pVlist;\
  2541.          pVlist++;\
  2542.          }
  2543.  
  2544. #define ChangeMask ((Mask)(CWX | CWY | CWWidth | CWHeight))
  2545.  
  2546. #define IllegalInputOnlyConfigureMask (CWBorderWidth)
  2547.  
  2548. /*
  2549.  * IsSiblingAboveMe
  2550.  *     returns Above if pSib above pMe in stack or Below otherwise 
  2551.  */
  2552.  
  2553. static int
  2554. IsSiblingAboveMe(pMe, pSib)
  2555.     register WindowPtr pMe, pSib;
  2556. {
  2557.     register WindowPtr pWin;
  2558.  
  2559.     pWin = pMe->parent->firstChild;
  2560.     while (pWin)
  2561.     {
  2562.         if (pWin == pSib)
  2563.             return(Above);
  2564.         else if (pWin == pMe)
  2565.             return(Below);
  2566.         pWin = pWin->nextSib;
  2567.     }
  2568.     return(Below);
  2569. }
  2570.  
  2571. static BoxPtr
  2572. WindowExtents(pWin, pBox)
  2573.     register WindowPtr pWin;
  2574.     register BoxPtr pBox;
  2575. {
  2576.     pBox->x1 = pWin->origin.x - wBorderWidth (pWin);
  2577.     pBox->y1 = pWin->origin.y - wBorderWidth (pWin);
  2578.     pBox->x2 = pWin->origin.x + (int)pWin->drawable.width
  2579.            + wBorderWidth (pWin);
  2580.     pBox->y2 = pWin->origin.y + (int)pWin->drawable.height
  2581.            + wBorderWidth (pWin);
  2582.     return(pBox);
  2583. }
  2584.  
  2585. #ifdef SHAPE
  2586. #define IS_SHAPED(pWin)    (wBoundingShape (pWin) != (RegionPtr) NULL)
  2587.  
  2588. static RegionPtr
  2589. MakeBoundingRegion (pWin, pBox)
  2590.     register WindowPtr    pWin;
  2591.     BoxPtr    pBox;
  2592. {
  2593.     RegionPtr    pRgn;
  2594.     register ScreenPtr pScreen = pWin->drawable.pScreen;
  2595.  
  2596.     pRgn = (*pScreen->RegionCreate) (pBox, 1);
  2597.     if (wBoundingShape (pWin)) {
  2598.         (*pScreen->TranslateRegion) (pRgn, -pWin->origin.x,
  2599.                               -pWin->origin.y);
  2600.         (*pScreen->Intersect) (pRgn, pRgn, wBoundingShape (pWin));
  2601.         (*pScreen->TranslateRegion) (pRgn, pWin->origin.x,
  2602.                               pWin->origin.y);
  2603.     }
  2604.     return pRgn;
  2605. }
  2606.  
  2607. static Bool
  2608. ShapeOverlap (pWin, pWinBox, pSib, pSibBox)
  2609.     WindowPtr    pWin, pSib;
  2610.     BoxPtr    pWinBox, pSibBox;
  2611. {
  2612.     RegionPtr    pWinRgn, pSibRgn;
  2613.     register ScreenPtr    pScreen;
  2614.     Bool    ret;
  2615.  
  2616.     if (!IS_SHAPED(pWin) && !IS_SHAPED(pSib))
  2617.     return TRUE;
  2618.     pScreen = pWin->drawable.pScreen;
  2619.     pWinRgn = MakeBoundingRegion (pWin, pWinBox);
  2620.     pSibRgn = MakeBoundingRegion (pSib, pSibBox);
  2621.     (*pScreen->Intersect) (pWinRgn, pWinRgn, pSibRgn);
  2622.     ret = (*pScreen->RegionNotEmpty) (pWinRgn);
  2623.     (*pScreen->RegionDestroy) (pWinRgn);
  2624.     (*pScreen->RegionDestroy) (pSibRgn);
  2625.     return ret;
  2626. }
  2627. #endif
  2628.  
  2629. static Bool
  2630. AnyWindowOverlapsMe(pWin, pHead, box)
  2631.     WindowPtr pWin, pHead;
  2632.     register BoxPtr box;
  2633. {
  2634.     register WindowPtr pSib;
  2635.     BoxRec sboxrec;
  2636.     register BoxPtr sbox;
  2637.  
  2638.     for (pSib = pWin->prevSib; pSib != pHead; pSib = pSib->prevSib)
  2639.     {
  2640.     if (pSib->mapped)
  2641.     {
  2642.         sbox = WindowExtents(pSib, &sboxrec);
  2643.         if (BOXES_OVERLAP(sbox, box)
  2644. #ifdef SHAPE
  2645.         && ShapeOverlap (pWin, box, pSib, sbox)
  2646. #endif
  2647.         )
  2648.         return(TRUE);
  2649.     }
  2650.     }
  2651.     return(FALSE);
  2652. }
  2653.  
  2654. static Bool
  2655. IOverlapAnyWindow(pWin, box)
  2656.     WindowPtr pWin;
  2657.     register BoxPtr box;
  2658. {
  2659.     register WindowPtr pSib;
  2660.     BoxRec sboxrec;
  2661.     register BoxPtr sbox;
  2662.  
  2663.     for (pSib = pWin->nextSib; pSib; pSib = pSib->nextSib)
  2664.     {
  2665.     if (pSib->mapped)
  2666.     {
  2667.         sbox = WindowExtents(pSib, &sboxrec);
  2668.         if (BOXES_OVERLAP(sbox, box)
  2669. #ifdef SHAPE
  2670.         && ShapeOverlap (pWin, box, pSib, sbox)
  2671. #endif
  2672.         )
  2673.         return(TRUE);
  2674.     }
  2675.     }
  2676.     return(FALSE);
  2677. }
  2678.  
  2679. /*
  2680.  *   WhereDoIGoInTheStack() 
  2681.  *        Given pWin and pSib and the relationshipe smode, return
  2682.  *        the window that pWin should go ABOVE.
  2683.  *        If a pSib is specified:
  2684.  *            Above:  pWin is placed just above pSib
  2685.  *            Below:  pWin is placed just below pSib
  2686.  *            TopIf:  if pSib occludes pWin, then pWin is placed
  2687.  *                    at the top of the stack
  2688.  *            BottomIf:  if pWin occludes pSib, then pWin is 
  2689.  *                       placed at the bottom of the stack
  2690.  *            Opposite: if pSib occludes pWin, then pWin is placed at the
  2691.  *                      top of the stack, else if pWin occludes pSib, then
  2692.  *                      pWin is placed at the bottom of the stack
  2693.  *
  2694.  *        If pSib is NULL:
  2695.  *            Above:  pWin is placed at the top of the stack
  2696.  *            Below:  pWin is placed at the bottom of the stack
  2697.  *            TopIf:  if any sibling occludes pWin, then pWin is placed at
  2698.  *                    the top of the stack
  2699.  *            BottomIf: if pWin occludes any sibline, then pWin is placed at
  2700.  *                      the bottom of the stack
  2701.  *            Opposite: if any sibling occludes pWin, then pWin is placed at
  2702.  *                      the top of the stack, else if pWin occludes any
  2703.  *                      sibling, then pWin is placed at the bottom of the stack
  2704.  *
  2705.  */
  2706.  
  2707. static WindowPtr
  2708. WhereDoIGoInTheStack(pWin, pSib, x, y, w, h, smode)
  2709.     register WindowPtr pWin, pSib;
  2710.     short x, y;
  2711.     unsigned short w, h;
  2712.     int smode;
  2713. {
  2714.     BoxRec box;
  2715.     register ScreenPtr pScreen;
  2716.     WindowPtr pHead, pFirst;
  2717.  
  2718.     if ((pWin == pWin->parent->firstChild) &&
  2719.     (pWin == pWin->parent->lastChild))
  2720.         return((WindowPtr ) NULL);
  2721.     pHead = RealChildHead(pWin->parent);
  2722.     pFirst = pHead ? pHead->nextSib : pWin->parent->firstChild;
  2723.     pScreen = pWin->drawable.pScreen;
  2724.     box.x1 = x;
  2725.     box.y1 = y;
  2726.     box.x2 = x + (int)w;
  2727.     box.y2 = y + (int)h;
  2728.     switch (smode)
  2729.     {
  2730.       case Above:
  2731.         if (pSib)
  2732.            return(pSib);
  2733.         else if (pWin == pFirst)
  2734.             return(pWin->nextSib);
  2735.         else
  2736.             return(pFirst);
  2737.       case Below:
  2738.         if (pSib)
  2739.         if (pSib->nextSib != pWin)
  2740.             return(pSib->nextSib);
  2741.         else
  2742.             return(pWin->nextSib);
  2743.         else
  2744.             return NullWindow;
  2745.       case TopIf:
  2746.     if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs)
  2747.         return(pWin->nextSib);
  2748.     else if (pSib)
  2749.     {
  2750.             if ((IsSiblingAboveMe(pWin, pSib) == Above) &&
  2751.                 ((* pScreen->RectIn)(&pSib->borderSize, &box) != rgnOUT))
  2752.                 return(pFirst);
  2753.             else
  2754.                 return(pWin->nextSib);
  2755.     }
  2756.         else if (AnyWindowOverlapsMe(pWin, pHead, &box))
  2757.             return(pFirst);
  2758.         else
  2759.             return(pWin->nextSib);
  2760.       case BottomIf:
  2761.     if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs)
  2762.         return(pWin->nextSib);
  2763.     else if (pSib)
  2764.     {
  2765.             if ((IsSiblingAboveMe(pWin, pSib) == Below) &&
  2766.                 ((* pScreen->RectIn)(&pSib->borderSize, &box) != rgnOUT))
  2767.                 return NullWindow;
  2768.             else
  2769.                 return(pWin->nextSib);
  2770.     }
  2771.         else if (IOverlapAnyWindow(pWin, &box))
  2772.             return NullWindow;
  2773.         else
  2774.             return(pWin->nextSib);
  2775.       case Opposite:
  2776.     if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs)
  2777.         return(pWin->nextSib);
  2778.     else if (pSib)
  2779.     {
  2780.         if ((* pScreen->RectIn)(&pSib->borderSize, &box) != rgnOUT)
  2781.             {
  2782.                 if (IsSiblingAboveMe(pWin, pSib) == Above)
  2783.                     return(pFirst);
  2784.                 else
  2785.                     return NullWindow;
  2786.             }
  2787.             else
  2788.                 return(pWin->nextSib);
  2789.     }
  2790.         else if (AnyWindowOverlapsMe(pWin, pHead, &box))
  2791.     {
  2792.         /* If I'm occluded, I can't possibly be the first child
  2793.              * if (pWin == pWin->parent->firstChild)
  2794.              *    return pWin->nextSib;
  2795.          */
  2796.             return(pFirst);
  2797.     }
  2798.         else if (IOverlapAnyWindow(pWin, &box))
  2799.             return NullWindow;
  2800.         else
  2801.             return pWin->nextSib;
  2802.       default:
  2803.       {
  2804.         ErrorF("Internal error in ConfigureWindow, smode == %d\n",smode );
  2805.         return pWin->nextSib;
  2806.       }
  2807.     }
  2808. }
  2809.  
  2810. static void
  2811. ReflectStackChange(pWin, pSib, kind)
  2812.     register WindowPtr pWin, pSib;
  2813.     VTKind  kind;
  2814. {
  2815. /* Note that pSib might be NULL */
  2816.  
  2817.     Bool WasViewable = (Bool)pWin->viewable;
  2818.     WindowPtr pParent;
  2819.     Bool anyMarked;
  2820.     WindowPtr pFirstChange;
  2821. #ifdef DO_SAVE_UNDERS
  2822.     Bool    dosave = FALSE;
  2823. #endif
  2824.  
  2825.     /* if this is a root window, can't be restacked */
  2826.     if (!(pParent = pWin->parent))
  2827.         return ;
  2828.  
  2829.     pFirstChange = MoveWindowInStack(pWin, pSib);
  2830.  
  2831.     if (WasViewable)
  2832.     {
  2833.     anyMarked = MarkOverlappedWindows(pWin, pFirstChange);
  2834. #ifdef DO_SAVE_UNDERS
  2835.     if (DO_SAVE_UNDERS(pWin))
  2836.     {
  2837.         if (pWin->saveUnder)
  2838.         dosave = ChangeSaveUnder(pWin, pFirstChange);
  2839.         else
  2840.         dosave = CheckSaveUnder(pWin);
  2841.     }
  2842. #endif /* DO_SAVE_UNDERS */
  2843.     if (anyMarked)
  2844.     {
  2845.         (* pWin->drawable.pScreen->ValidateTree)(pParent, pFirstChange,
  2846.                              kind);
  2847.         HandleExposures(pParent);
  2848.     }
  2849. #ifdef DO_SAVE_UNDERS
  2850.     if (dosave)
  2851.         DoChangeSaveUnder(pParent, pFirstChange);
  2852. #endif /* DO_SAVE_UNDERS */
  2853.     if (anyMarked && pWin->drawable.pScreen->PostValidateTree)
  2854.         (* pWin->drawable.pScreen->PostValidateTree)(pParent,
  2855.                              pFirstChange, kind);
  2856.     }
  2857.     if (pWin->realized)
  2858.     WindowsRestructured ();
  2859. }
  2860.  
  2861. /*****
  2862.  * ConfigureWindow
  2863.  *****/
  2864.  
  2865.  
  2866. int
  2867. ConfigureWindow(pWin, mask, vlist, client)
  2868.     register WindowPtr pWin;
  2869.     register Mask mask;
  2870.     XID *vlist;
  2871.     ClientPtr client;
  2872. {
  2873. #define RESTACK_WIN    0
  2874. #define MOVE_WIN       1
  2875. #define RESIZE_WIN     2
  2876. #define REBORDER_WIN   3
  2877.     register WindowPtr pSib = NullWindow;
  2878.     register WindowPtr pParent = pWin->parent;
  2879.     Window sibwid;
  2880.     Mask index, tmask;
  2881.     register XID *pVlist;
  2882.     short x,   y, beforeX, beforeY;
  2883.     unsigned short w = pWin->drawable.width,
  2884.                    h = pWin->drawable.height,
  2885.                bw = pWin->borderWidth;
  2886.     int action,
  2887.         smode = Above;
  2888.     xEvent event;
  2889.  
  2890.     if ((pWin->drawable.class == InputOnly) && (mask & IllegalInputOnlyConfigureMask))
  2891.         return(BadMatch);
  2892.  
  2893.     if ((mask & CWSibling) && !(mask & CWStackMode))
  2894.         return(BadMatch);
  2895.  
  2896.     pVlist = vlist;
  2897.  
  2898.     if (pParent)
  2899.     {
  2900.         x = pWin->drawable.x - pParent->drawable.x - (int)bw;
  2901.         y = pWin->drawable.y - pParent->drawable.y - (int)bw;
  2902.     }
  2903.     else
  2904.     {
  2905.         x = pWin->drawable.x;
  2906.         y = pWin->drawable.y;
  2907.     }
  2908.     beforeX = x;
  2909.     beforeY = y;
  2910.     action = RESTACK_WIN;    
  2911.     if ((mask & (CWX | CWY)) && (!(mask & (CWHeight | CWWidth))))
  2912.     {
  2913.     GET_INT16(CWX, x);
  2914.      GET_INT16(CWY, y);
  2915.     action = MOVE_WIN;
  2916.     }
  2917.     /* or should be resized */
  2918.     else if (mask & (CWX |  CWY | CWWidth | CWHeight))
  2919.     {
  2920.     GET_INT16(CWX, x);
  2921.     GET_INT16(CWY, y);
  2922.     GET_CARD16(CWWidth, w);
  2923.     GET_CARD16 (CWHeight, h);
  2924.     if (!w || !h)
  2925.     {
  2926.         client->errorValue = 0;
  2927.             return BadValue;
  2928.     }
  2929.         action = RESIZE_WIN;
  2930.     }
  2931.     tmask = mask & ~ChangeMask;
  2932.     while (tmask)
  2933.     {
  2934.     index = (Mask)lowbit (tmask);
  2935.     tmask &= ~index;
  2936.     switch (index)
  2937.         {
  2938.           case CWBorderWidth:
  2939.         GET_CARD16(CWBorderWidth, bw);
  2940.         break;
  2941.           case CWSibling:
  2942.         sibwid = (Window ) *pVlist;
  2943.         pVlist++;
  2944.             pSib = (WindowPtr )LookupIDByType(sibwid, RT_WINDOW);
  2945.             if (!pSib)
  2946.         {
  2947.         client->errorValue = sibwid;
  2948.                 return(BadWindow);
  2949.         }
  2950.             if (pSib->parent != pParent)
  2951.         return(BadMatch);
  2952.         if (pSib == pWin)
  2953.             return(BadMatch);
  2954.         break;
  2955.           case CWStackMode:
  2956.         GET_CARD8(CWStackMode, smode);
  2957.         if ((smode != TopIf) && (smode != BottomIf) &&
  2958.          (smode != Opposite) && (smode != Above) && (smode != Below))
  2959.                    return(BadMatch);
  2960.         break;
  2961.       default:
  2962.         client->errorValue = mask;
  2963.         return(BadValue);
  2964.     }
  2965.     }
  2966.     /* root really can't be reconfigured, so just return */
  2967.     if (!pParent)
  2968.     return Success;
  2969.  
  2970.         /* Figure out if the window should be moved.  Doesnt
  2971.            make the changes to the window if event sent */
  2972.  
  2973.     if (mask & CWStackMode)
  2974.         pSib = WhereDoIGoInTheStack(pWin, pSib, pParent->drawable.x + x,
  2975.                     pParent->drawable.y + y,
  2976.                     w + (bw << 1), h + (bw << 1), smode);
  2977.     else
  2978.         pSib = pWin->nextSib;
  2979.  
  2980.     if ((!pWin->overrideRedirect) && RedirectSend(pParent))
  2981.     {
  2982.     event.u.u.type = ConfigureRequest;
  2983.     event.u.configureRequest.window = pWin->drawable.id;
  2984.     event.u.configureRequest.parent = pParent->drawable.id;
  2985.         if (mask & CWSibling)
  2986.        event.u.configureRequest.sibling = sibwid;
  2987.         else
  2988.                event.u.configureRequest.sibling = None;
  2989.         if (mask & CWStackMode)
  2990.        event.u.u.detail = smode;
  2991.         else
  2992.                event.u.u.detail = Above;
  2993.     event.u.configureRequest.x = x;
  2994.     event.u.configureRequest.y = y;
  2995.     event.u.configureRequest.width = w;
  2996.     event.u.configureRequest.height = h;
  2997.     event.u.configureRequest.borderWidth = bw;
  2998.     event.u.configureRequest.valueMask = mask;
  2999.     if (MaybeDeliverEventsToClient(pParent, &event, 1,
  3000.             SubstructureRedirectMask, client) == 1)
  3001.             return(Success);
  3002.     }
  3003.     if (action == RESIZE_WIN)
  3004.     {
  3005.         Bool size_change = (w != pWin->drawable.width)
  3006.                         || (h != pWin->drawable.height);
  3007.     if (size_change && ((pWin->eventMask|wOtherEventMasks(pWin)) & ResizeRedirectMask))
  3008.     {
  3009.         xEvent eventT;
  3010.             eventT.u.u.type = ResizeRequest;
  3011.             eventT.u.resizeRequest.window = pWin->drawable.id;
  3012.         eventT.u.resizeRequest.width = w;
  3013.         eventT.u.resizeRequest.height = h;
  3014.         if (MaybeDeliverEventsToClient(pWin, &eventT, 1,
  3015.                        ResizeRedirectMask, client) == 1)
  3016.         {
  3017.                 /* if event is delivered, leave the actual size alone. */
  3018.             w = pWin->drawable.width;
  3019.             h = pWin->drawable.height;
  3020.                 size_change = FALSE;
  3021.         }
  3022.     }
  3023.         if (!size_change)
  3024.     {
  3025.         if (mask & (CWX | CWY))
  3026.                 action = MOVE_WIN;
  3027.         else if (mask & (CWStackMode | CWBorderWidth))
  3028.             action = RESTACK_WIN;
  3029.             else   /* really nothing to do */
  3030.                 return(Success) ;
  3031.     }
  3032.     }
  3033.  
  3034.     if (action == RESIZE_WIN)
  3035.             /* we've already checked whether there's really a size change */
  3036.             goto ActuallyDoSomething;
  3037.     if ((mask & CWX) && (x != beforeX))
  3038.             goto ActuallyDoSomething;
  3039.     if ((mask & CWY) && (y != beforeY))
  3040.             goto ActuallyDoSomething;
  3041.     if ((mask & CWBorderWidth) && (bw != wBorderWidth (pWin)))
  3042.             goto ActuallyDoSomething;
  3043.     if (mask & CWStackMode)
  3044.     {
  3045.         if (pWin->nextSib != pSib)
  3046.             goto ActuallyDoSomething;
  3047.     }
  3048.     return(Success);
  3049.  
  3050. ActuallyDoSomething:
  3051.     if (SubStrSend(pWin, pParent))
  3052.     {
  3053.     event.u.u.type = ConfigureNotify;
  3054.     event.u.configureNotify.window = pWin->drawable.id;
  3055.     if (pSib)
  3056.         event.u.configureNotify.aboveSibling = pSib->drawable.id;
  3057.     else
  3058.         event.u.configureNotify.aboveSibling = None;
  3059.     event.u.configureNotify.x = x;
  3060.     event.u.configureNotify.y = y;
  3061.     event.u.configureNotify.width = w;
  3062.     event.u.configureNotify.height = h;
  3063.     event.u.configureNotify.borderWidth = bw;
  3064.     event.u.configureNotify.override = pWin->overrideRedirect;
  3065.     DeliverEvents(pWin, &event, 1, NullWindow);
  3066.     }
  3067.     if (mask & CWBorderWidth)
  3068.     {
  3069.     if (action == RESTACK_WIN)
  3070.     {
  3071.         action = MOVE_WIN;
  3072.         pWin->borderWidth = bw;
  3073.     }
  3074.     else if ((action == MOVE_WIN) &&
  3075.          (beforeX + wBorderWidth (pWin) == x + (int)bw) &&
  3076.          (beforeY + wBorderWidth (pWin) == y + (int)bw))
  3077.     {
  3078.         action = REBORDER_WIN;
  3079.             ChangeBorderWidth(pWin, bw);
  3080.     }
  3081.         else
  3082.         pWin->borderWidth = bw;
  3083.     }
  3084.     if (action == MOVE_WIN)
  3085.         MoveWindow(pWin, x, y, pSib,
  3086.            (mask & CWBorderWidth) ? VTOther : VTMove);
  3087.     else if (action == RESIZE_WIN)
  3088.         SlideAndSizeWindow(pWin, x, y, w, h, pSib);
  3089.     else if (mask & CWStackMode)
  3090.         ReflectStackChange(pWin, pSib, VTOther);
  3091.  
  3092.     if (action != RESTACK_WIN)
  3093.     CheckCursorConfinement(pWin);
  3094.  
  3095.     return(Success);
  3096. #undef RESTACK_WIN
  3097. #undef MOVE_WIN
  3098. #undef RESIZE_WIN
  3099. #undef REBORDER_WIN
  3100. }
  3101.  
  3102. #ifdef SHAPE
  3103. /******
  3104.  *
  3105.  * SetShape
  3106.  *    The border/window shape has changed.  Recompute winSize/borderSize
  3107.  *    and send appropriate exposure events
  3108.  */
  3109.  
  3110. SetShape(pWin)
  3111.     register WindowPtr    pWin;
  3112. {
  3113.     Bool    WasViewable = (Bool)(pWin->viewable);
  3114.     register ScreenPtr pScreen = pWin->drawable.pScreen;
  3115.     Bool    anyMarked;
  3116.     WindowPtr    pParent = pWin->parent;
  3117.     RegionPtr    pOldClip, bsExposed;
  3118. #ifdef DO_SAVE_UNDERS
  3119.     Bool    dosave = FALSE;
  3120. #endif
  3121.  
  3122.     if (WasViewable)
  3123.     {
  3124.     anyMarked = MarkOverlappedWindows(pWin, pWin);
  3125.     if (pWin->valdata)
  3126.     {
  3127.         if (HasBorder (pWin))
  3128.         {
  3129.         RegionPtr    borderVisible;
  3130.  
  3131.             borderVisible = (*pScreen->RegionCreate) (NullBox, 1);
  3132.             (*pScreen->Subtract) (borderVisible,
  3133.                       &pWin->borderClip, &pWin->winSize);
  3134.             pWin->valdata->before.borderVisible = borderVisible;
  3135.         }
  3136.         pWin->valdata->before.resized = TRUE;
  3137.     }
  3138.     }
  3139.  
  3140.     SetWinSize (pWin);
  3141.     SetBorderSize (pWin);
  3142.  
  3143.     ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
  3144.  
  3145.     if (WasViewable)
  3146.     {
  3147.     if (pWin->backStorage)
  3148.     {
  3149.         pOldClip = (*pScreen->RegionCreate) (NullBox, 1);
  3150.         (*pScreen->RegionCopy) (pOldClip, &pWin->clipList);
  3151.     }
  3152.  
  3153.     anyMarked |= MarkOverlappedWindows(pWin, pWin);
  3154.  
  3155. #ifdef DO_SAVE_UNDERS
  3156.     if (DO_SAVE_UNDERS(pWin))
  3157.     {
  3158.         if (pWin->saveUnder)
  3159.         dosave = ChangeSaveUnder(pWin, pWin);
  3160.         else
  3161.         dosave = CheckSaveUnder(pWin);
  3162.     }
  3163. #endif /* DO_SAVE_UNDERS */
  3164.  
  3165.     if (anyMarked)
  3166.         (* pScreen->ValidateTree)(pParent, NullWindow, VTOther);
  3167.     }
  3168.  
  3169.     if (pWin->backStorage &&
  3170.     ((pWin->backingStore == Always) || WasViewable))
  3171.     {
  3172.     if (!WasViewable)
  3173.         pOldClip = &pWin->clipList; /* a convenient empty region */
  3174.     bsExposed = (* pScreen->TranslateBackingStore)
  3175.                  (pWin, 0, 0, pOldClip,
  3176.                    pWin->drawable.x, pWin->drawable.y);
  3177.         if (bsExposed)
  3178.         {
  3179.         RegionPtr    valExposed = NullRegion;
  3180.     
  3181.         if (pWin->valdata)
  3182.             valExposed = &pWin->valdata->after.exposed;
  3183.         (*pScreen->WindowExposures) (pWin, valExposed, bsExposed);
  3184.         if (valExposed)
  3185.             (*pScreen->RegionEmpty) (valExposed);
  3186.         (*pScreen->RegionDestroy) (bsExposed);
  3187.         }
  3188.     }
  3189.     if (WasViewable)
  3190.     {
  3191.     if (anyMarked)
  3192.         HandleExposures(pParent);
  3193. #ifdef DO_SAVE_UNDERS
  3194.     if (dosave)
  3195.         DoChangeSaveUnder(pParent, pWin);
  3196. #endif /* DO_SAVE_UNDERS */
  3197.     if (anyMarked && pScreen->PostValidateTree)
  3198.         (* pScreen->PostValidateTree)(pParent, NullWindow, VTOther);
  3199.     }
  3200.     if (pWin->realized)
  3201.     WindowsRestructured ();
  3202.     CheckCursorConfinement(pWin);
  3203. }
  3204. #endif
  3205.  
  3206. /******
  3207.  *
  3208.  * CirculateWindow
  3209.  *    For RaiseLowest, raises the lowest mapped child (if any) that is
  3210.  *    obscured by another child to the top of the stack.  For LowerHighest,
  3211.  *    lowers the highest mapped child (if any) that is obscuring another
  3212.  *    child to the bottom of the stack.  Exposure processing is performed 
  3213.  *
  3214.  ******/
  3215.  
  3216. int
  3217. CirculateWindow(pParent, direction, client)
  3218.     WindowPtr pParent;
  3219.     int direction;
  3220.     ClientPtr client;
  3221. {
  3222.     register WindowPtr pWin, pHead, pFirst;
  3223.     xEvent event;
  3224.     BoxRec box;
  3225.  
  3226.     pHead = RealChildHead(pParent);
  3227.     pFirst = pHead ? pHead->nextSib : pParent->firstChild;
  3228.     if (direction == RaiseLowest)
  3229.     {
  3230.     for (pWin = pParent->lastChild;
  3231.          (pWin != pHead) &&
  3232.          !(pWin->mapped &&
  3233.            AnyWindowOverlapsMe(pWin, pHead, WindowExtents(pWin, &box)));
  3234.          pWin = pWin->prevSib) ;
  3235.     if (pWin == pHead)
  3236.         return Success;
  3237.     }
  3238.     else
  3239.     {
  3240.     for (pWin = pFirst;
  3241.          pWin &&
  3242.          !(pWin->mapped &&
  3243.            IOverlapAnyWindow(pWin, WindowExtents(pWin, &box)));
  3244.          pWin = pWin->nextSib) ;
  3245.     if (!pWin)
  3246.         return Success;
  3247.     }
  3248.  
  3249.     event.u.circulate.window = pWin->drawable.id;
  3250.     event.u.circulate.parent = pParent->drawable.id;
  3251.     event.u.circulate.event = pParent->drawable.id;
  3252.     if (direction == RaiseLowest)
  3253.     event.u.circulate.place = PlaceOnTop;
  3254.     else
  3255.         event.u.circulate.place = PlaceOnBottom;
  3256.  
  3257.     if (RedirectSend(pParent))
  3258.     {
  3259.     event.u.u.type = CirculateRequest;
  3260.     if (MaybeDeliverEventsToClient(pParent, &event, 1,
  3261.             SubstructureRedirectMask, client) == 1)
  3262.             return(Success);
  3263.     }
  3264.  
  3265.     event.u.u.type = CirculateNotify;
  3266.     DeliverEvents(pWin, &event, 1, NullWindow);
  3267.     ReflectStackChange(pWin,
  3268.                (direction == RaiseLowest) ? pFirst : NullWindow,
  3269.                VTStack);
  3270.  
  3271.     return(Success);
  3272. }
  3273.  
  3274. static int
  3275. CompareWIDs(pWin, wid)
  3276.     WindowPtr pWin;
  3277.     Window *wid;
  3278. {
  3279.     if (pWin->drawable.id == *wid)
  3280.        return(WT_STOPWALKING);
  3281.     else
  3282.        return(WT_WALKCHILDREN);
  3283. }
  3284.  
  3285. /*****
  3286.  *  ReparentWindow
  3287.  *****/
  3288.  
  3289. int
  3290. ReparentWindow(pWin, pParent, x, y, client)
  3291.     register WindowPtr pWin, pParent;
  3292.     short x,y;
  3293.     ClientPtr client;
  3294. {
  3295.     WindowPtr pPrev;
  3296.     Bool WasMapped = (Bool)(pWin->mapped);
  3297.     xEvent event;
  3298.     int bw = wBorderWidth (pWin);
  3299.     register ScreenPtr pScreen;
  3300.  
  3301.     pScreen = pWin->drawable.pScreen;
  3302.     if (TraverseTree(pWin, CompareWIDs, (pointer)&pParent->drawable.id) == WT_STOPWALKING)
  3303.         return(BadMatch);        
  3304.     if (!MakeWindowOptional(pWin))
  3305.     return(BadAlloc);
  3306.  
  3307.     if (WasMapped)
  3308.        UnmapWindow(pWin, FALSE);
  3309.  
  3310.     event.u.u.type = ReparentNotify;
  3311.     event.u.reparent.window = pWin->drawable.id;
  3312.     event.u.reparent.parent = pParent->drawable.id;
  3313.     event.u.reparent.x = x;
  3314.     event.u.reparent.y = y;
  3315.     event.u.reparent.override = pWin->overrideRedirect;
  3316.     DeliverEvents(pWin, &event, 1, pParent);
  3317.  
  3318.     /* take out of sibling chain */
  3319.  
  3320.     pPrev = pWin->parent;
  3321.     if (pPrev->firstChild == pWin)
  3322.         pPrev->firstChild = pWin->nextSib;
  3323.     if (pPrev->lastChild == pWin)
  3324.         pPrev->lastChild = pWin->prevSib;
  3325.  
  3326.     if (pWin->nextSib)
  3327.         pWin->nextSib->prevSib = pWin->prevSib;
  3328.     if (pWin->prevSib)
  3329.         pWin->prevSib->nextSib = pWin->nextSib;
  3330.  
  3331.     /* insert at begining of pParent */
  3332.     pWin->parent = pParent;
  3333.     pPrev = RealChildHead(pParent);
  3334.     if (pPrev)
  3335.     {
  3336.     pWin->nextSib = pPrev->nextSib;
  3337.         if (pPrev->nextSib)
  3338.             pPrev->nextSib->prevSib = pWin;
  3339.     else
  3340.         pParent->lastChild = pWin;
  3341.         pPrev->nextSib = pWin;
  3342.     pWin->prevSib = pPrev;
  3343.     }
  3344.     else
  3345.     {
  3346.         pWin->nextSib = pParent->firstChild;
  3347.     pWin->prevSib = NullWindow;
  3348.         if (pParent->firstChild)
  3349.         pParent->firstChild->prevSib = pWin;
  3350.         else
  3351.             pParent->lastChild = pWin;
  3352.     pParent->firstChild = pWin;
  3353.     }
  3354.  
  3355.     pWin->origin.x = x + bw;
  3356.     pWin->origin.y = y + bw;
  3357.     pWin->drawable.x = x + bw + pParent->drawable.x;
  3358.     pWin->drawable.y = y + bw + pParent->drawable.y;
  3359.  
  3360.     /* clip to parent */
  3361.     SetWinSize (pWin);
  3362.     SetBorderSize (pWin);
  3363.  
  3364.     (* pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y);
  3365.     ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
  3366.  
  3367.     CheckWindowOptionalNeed(pWin);
  3368.  
  3369.     if (WasMapped)
  3370.         MapWindow(pWin, client);
  3371.     RecalculateDeliverableEvents(pWin);
  3372.     return(Success);
  3373. }
  3374.  
  3375. static void
  3376. MarkWindow(pWin)
  3377.     register WindowPtr pWin;
  3378. {
  3379.     register ValidatePtr val;
  3380.     extern Bool Must_have_memory;
  3381.  
  3382.     if (pWin->valdata)
  3383.     return;
  3384.     Must_have_memory = TRUE; /* XXX */
  3385.     val = (ValidatePtr)xalloc(sizeof(ValidateRec));
  3386.     Must_have_memory = FALSE; /* XXX */
  3387.     val->before.oldAbsCorner.x = pWin->drawable.x;
  3388.     val->before.oldAbsCorner.y = pWin->drawable.y;
  3389.     val->before.borderVisible = NullRegion;
  3390.     val->before.resized = FALSE;
  3391.     pWin->valdata = val;
  3392. }
  3393.  
  3394. static Bool
  3395. MarkOverlappedWindows(pWin, pFirst)
  3396.     WindowPtr pWin;
  3397.     WindowPtr pFirst;
  3398. {
  3399.     register BoxPtr box;
  3400.     register WindowPtr pChild, pLast;
  3401.     int (* RectIn)();
  3402.     Bool anyMarked = FALSE;
  3403.  
  3404.     if (pWin == pFirst)
  3405.     {
  3406.     /* Blindly mark pWin and all of it's inferiors.  This is a slight
  3407.      * overkill if there are mapped windows that outside pWin's border,
  3408.      * but it's better than wasting time on RectIn checks.
  3409.      */
  3410.     pChild = pWin;
  3411.     while (1)
  3412.     {
  3413.         if (pChild->viewable)
  3414.         {
  3415.         MarkWindow(pChild);
  3416.         if (pChild->firstChild)
  3417.         {
  3418.             pChild = pChild->firstChild;
  3419.             continue;
  3420.         }
  3421.         }
  3422.         while (!pChild->nextSib && (pChild != pWin))
  3423.         pChild = pChild->parent;
  3424.         if (pChild == pWin)
  3425.         break;
  3426.         pChild = pChild->nextSib;
  3427.     }
  3428.     anyMarked = TRUE;
  3429.     pFirst = pFirst->nextSib;
  3430.     }
  3431.     if (pChild = pFirst)
  3432.     {
  3433.     box = (* pChild->drawable.pScreen->RegionExtents)(&pWin->borderSize);
  3434.     RectIn = pChild->drawable.pScreen->RectIn;
  3435.     pLast = pChild->parent->lastChild;
  3436.     while (1)
  3437.     {
  3438.         if (pChild->viewable && (*RectIn)(&pChild->borderSize, box))
  3439.         {
  3440.         MarkWindow(pChild);
  3441.         anyMarked = TRUE;
  3442.         if (pChild->firstChild)
  3443.         {
  3444.             pChild = pChild->firstChild;
  3445.             continue;
  3446.         }
  3447.         }
  3448.         while (!pChild->nextSib && (pChild != pLast))
  3449.         pChild = pChild->parent;
  3450.         if (pChild == pLast)
  3451.         break;
  3452.         pChild = pChild->nextSib;
  3453.     }
  3454.     }
  3455.     if (anyMarked)
  3456.     MarkWindow(pWin->parent);
  3457.     return anyMarked;
  3458. }
  3459.  
  3460. static void
  3461. RealizeTree(pWin)
  3462.     WindowPtr pWin;
  3463. {
  3464.     register WindowPtr pChild;
  3465.     Bool (* Realize)();
  3466.  
  3467.     Realize = pWin->drawable.pScreen->RealizeWindow;
  3468.     pChild = pWin;
  3469.     while (1)
  3470.     {
  3471.     if (pChild->mapped)
  3472.     {
  3473.         pChild->realized = TRUE;
  3474. #ifdef DO_SAVE_UNDERS
  3475.         if (pChild->saveUnder)
  3476.         deltaSaveUndersViewable++;
  3477. #endif
  3478.         pChild->viewable = (pChild->drawable.class == InputOutput);
  3479.         (* Realize)(pChild);
  3480.         if (pChild->firstChild)
  3481.         {
  3482.         pChild = pChild->firstChild;
  3483.         continue;
  3484.         }
  3485.     }
  3486.     while (!pChild->nextSib && (pChild != pWin))
  3487.         pChild = pChild->parent;
  3488.     if (pChild == pWin)
  3489.         return;
  3490.     pChild = pChild->nextSib;
  3491.     }
  3492. }
  3493.  
  3494. /*****
  3495.  * MapWindow
  3496.  *    If some other client has selected SubStructureReDirect on the parent
  3497.  *    and override-redirect is xFalse, then a MapRequest event is generated,
  3498.  *    but the window remains unmapped.  Otherwise, the window is mapped and a
  3499.  *    MapNotify event is generated.
  3500.  *****/
  3501.  
  3502. int
  3503. MapWindow(pWin, client)
  3504.     register WindowPtr pWin;
  3505.     ClientPtr client;
  3506. {
  3507.     register ScreenPtr pScreen;
  3508.  
  3509.     register WindowPtr pParent;
  3510. #ifdef DO_SAVE_UNDERS
  3511.     Bool    dosave = FALSE;
  3512. #endif
  3513.  
  3514.     if (pWin->mapped)
  3515.         return(Success);
  3516.     pScreen = pWin->drawable.pScreen;
  3517.     if (pParent = pWin->parent)
  3518.     {
  3519.         xEvent event;
  3520.     Bool anyMarked;
  3521.  
  3522.         if ((!pWin->overrideRedirect) && RedirectSend(pParent))
  3523.     {
  3524.         event.u.u.type = MapRequest;
  3525.         event.u.mapRequest.window = pWin->drawable.id;
  3526.         event.u.mapRequest.parent = pParent->drawable.id;
  3527.  
  3528.         if (MaybeDeliverEventsToClient(pParent, &event, 1,
  3529.             SubstructureRedirectMask, client) == 1)
  3530.                 return(Success);
  3531.     }
  3532.  
  3533.     pWin->mapped = TRUE;
  3534.     if (SubStrSend(pWin, pParent))
  3535.     {
  3536.         event.u.u.type = MapNotify;
  3537.         event.u.mapNotify.window = pWin->drawable.id;
  3538.         event.u.mapNotify.override = pWin->overrideRedirect;
  3539.         DeliverEvents(pWin, &event, 1, NullWindow);
  3540.     }
  3541.  
  3542.         if (!pParent->realized)
  3543.             return(Success);
  3544.     RealizeTree(pWin);
  3545.     if (pWin->viewable)
  3546.     {
  3547.         anyMarked = MarkOverlappedWindows(pWin, pWin);
  3548. #ifdef DO_SAVE_UNDERS
  3549.         if (DO_SAVE_UNDERS(pWin))
  3550.         {
  3551.         if (pWin->saveUnder)
  3552.             dosave = ChangeSaveUnder(pWin, pWin->nextSib);
  3553.         else
  3554.             dosave = CheckSaveUnder(pWin);
  3555.         }
  3556. #endif /* DO_SAVE_UNDERS */
  3557.         if (anyMarked)
  3558.         {
  3559.         (* pScreen->ValidateTree)(pParent, pWin, VTMap);
  3560.         HandleExposures(pParent);
  3561.         }
  3562. #ifdef DO_SAVE_UNDERS
  3563.         if (dosave)
  3564.         DoChangeSaveUnder(pParent, pWin->nextSib);
  3565. #endif /* DO_SAVE_UNDERS */
  3566.     if (anyMarked && pScreen->PostValidateTree)
  3567.         (* pScreen->PostValidateTree)(pParent, pWin, VTMap);
  3568.     }
  3569.     WindowsRestructured ();
  3570.     }
  3571.     else
  3572.     {
  3573.     RegionRec   temp;
  3574.  
  3575.     pWin->mapped = TRUE;
  3576.         pWin->realized = TRUE;     /* for roots */
  3577.         pWin->viewable = pWin->drawable.class == InputOutput;
  3578.         /* We SHOULD check for an error value here XXX */
  3579.         (* pScreen->RealizeWindow)(pWin);
  3580.     (* pScreen->RegionInit) (&temp, NullBox, 0);
  3581.     (* pScreen->RegionCopy) (&temp, &pWin->clipList);
  3582.     (*pScreen->WindowExposures) (pWin, &temp, NullRegion);
  3583.     (* pScreen->RegionUninit) (&temp);
  3584.     }
  3585.  
  3586.     return(Success);
  3587. }
  3588.  
  3589.  
  3590. /*****
  3591.  * MapSubwindows
  3592.  *    Performs a MapWindow all unmapped children of the window, in top
  3593.  *    to bottom stacking order.
  3594.  *****/
  3595.  
  3596. MapSubwindows(pParent, client)
  3597.     register WindowPtr pParent;
  3598.     ClientPtr client;
  3599. {
  3600.     register WindowPtr    pWin;
  3601.     WindowPtr        pFirstMapped = NullWindow;
  3602. #ifdef DO_SAVE_UNDERS
  3603.     WindowPtr        pFirstSaveUndered = NullWindow;
  3604. #endif
  3605.     register ScreenPtr    pScreen;
  3606.     register Mask    parentRedirect;
  3607.     register Mask    parentNotify;
  3608.     xEvent        event;
  3609.     Bool        anyMarked;
  3610. #ifdef DO_SAVE_UNDERS
  3611.     Bool    dosave = FALSE;
  3612. #endif
  3613.  
  3614.     pScreen = pParent->drawable.pScreen;
  3615.     parentRedirect = RedirectSend(pParent);
  3616.     parentNotify = SubSend(pParent);
  3617.     anyMarked = FALSE;
  3618.     for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib)
  3619.     {
  3620.     if (!pWin->mapped)
  3621.     {
  3622.             if (parentRedirect && !pWin->overrideRedirect)
  3623.         {
  3624.             event.u.u.type = MapRequest;
  3625.             event.u.mapRequest.window = pWin->drawable.id;
  3626.             event.u.mapRequest.parent = pParent->drawable.id;
  3627.     
  3628.             if (MaybeDeliverEventsToClient(pParent, &event, 1,
  3629.                 SubstructureRedirectMask, client) == 1)
  3630.                     continue;
  3631.         }
  3632.     
  3633.         pWin->mapped = TRUE;
  3634.         if (parentNotify || StrSend(pWin))
  3635.         {
  3636.         event.u.u.type = MapNotify;
  3637.         event.u.mapNotify.window = pWin->drawable.id;
  3638.         event.u.mapNotify.override = pWin->overrideRedirect;
  3639.         DeliverEvents(pWin, &event, 1, NullWindow);
  3640.         }
  3641.     
  3642.         if (!pFirstMapped)
  3643.         pFirstMapped = pWin;
  3644.             if (pParent->realized)
  3645.         {
  3646.             RealizeTree(pWin);
  3647.             if (pWin->viewable)
  3648.             {
  3649.                 anyMarked |= MarkOverlappedWindows(pWin, pWin);
  3650. #ifdef DO_SAVE_UNDERS
  3651.                 if (DO_SAVE_UNDERS(pWin))
  3652.                 {
  3653.                 if (pWin->saveUnder)
  3654.                     dosave |= ChangeSaveUnder(pWin, pWin->nextSib);
  3655.                 else
  3656.                     dosave |= CheckSaveUnder(pWin);
  3657.                 if (dosave && !pFirstSaveUndered)
  3658.                 pFirstSaveUndered = pWin;
  3659.                 }
  3660. #endif /* DO_SAVE_UNDERS */
  3661.             }
  3662.         }
  3663.     }
  3664.     }
  3665.  
  3666.     if (pFirstMapped)
  3667.     {
  3668.         if (anyMarked)
  3669.         {
  3670.         (* pScreen->ValidateTree)(pParent, pFirstMapped, VTMap);
  3671.         HandleExposures(pParent);
  3672.         }
  3673. #ifdef DO_SAVE_UNDERS
  3674.     if (dosave)
  3675.         DoChangeSaveUnder(pParent, pFirstSaveUndered->nextSib);
  3676. #endif /* DO_SAVE_UNDERS */
  3677.     if (anyMarked && pScreen->PostValidateTree)
  3678.         (* pScreen->PostValidateTree)(pParent, pFirstMapped, VTMap);
  3679.         WindowsRestructured ();
  3680.     }
  3681. }
  3682.  
  3683. static void
  3684. UnrealizeTree(pWin, fromConfigure)
  3685.     WindowPtr pWin;
  3686.     Bool fromConfigure;
  3687. {
  3688.     register WindowPtr pChild;
  3689.     void (*RegionEmpty)();
  3690.     Bool (*Unrealize)();
  3691.     void (*ClipNotify)();
  3692.  
  3693.     RegionEmpty = pWin->drawable.pScreen->RegionEmpty;
  3694.     Unrealize = pWin->drawable.pScreen->UnrealizeWindow;
  3695.     ClipNotify = pWin->drawable.pScreen->ClipNotify;
  3696.     pChild = pWin;
  3697.     while (1)
  3698.     {
  3699.     if (pChild->realized)
  3700.     {
  3701.         pChild->realized = FALSE;
  3702.         pChild->visibility = VisibilityNotViewable;
  3703.         (* Unrealize)(pChild);
  3704.         DeleteWindowFromAnyEvents(pChild, FALSE);
  3705.         if (pChild->viewable)
  3706.         {
  3707. #ifdef DO_SAVE_UNDERS
  3708.         if (pChild->saveUnder)
  3709.             deltaSaveUndersViewable--;
  3710. #endif
  3711.         pChild->viewable = FALSE;
  3712.         if (pChild->backStorage)
  3713.             (*pChild->drawable.pScreen->SaveDoomedAreas)(
  3714.                         pChild, &pChild->clipList, 0, 0);
  3715.         if ((pChild != pWin) || fromConfigure)
  3716.         {
  3717.             (* RegionEmpty)(&pChild->clipList);
  3718.             if (ClipNotify)
  3719.             (* ClipNotify)(pChild, 0, 0);
  3720.             (* RegionEmpty)(&pChild->borderClip);
  3721.         }
  3722.         pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
  3723.         }
  3724.         if (pChild->firstChild)
  3725.         {
  3726.         pChild = pChild->firstChild;
  3727.         continue;
  3728.         }
  3729.     }
  3730.     while (!pChild->nextSib && (pChild != pWin))
  3731.         pChild = pChild->parent;
  3732.     if (pChild == pWin)
  3733.         return;
  3734.     pChild = pChild->nextSib;
  3735.     }
  3736. }
  3737.  
  3738. /*****
  3739.  * UnmapWindow
  3740.  *    If the window is already unmapped, this request has no effect.
  3741.  *    Otherwise, the window is unmapped and an UnMapNotify event is
  3742.  *    generated.  Cannot unmap a root window.
  3743.  *****/
  3744.  
  3745. UnmapWindow(pWin, fromConfigure)
  3746.     register WindowPtr pWin;
  3747.     Bool fromConfigure;
  3748. {
  3749.     register WindowPtr pParent;
  3750.     xEvent event;
  3751.     Bool wasRealized = (Bool)pWin->realized;
  3752.     Bool wasViewable = (Bool)pWin->viewable;
  3753.  
  3754.     if ((!pWin->mapped) || (!(pParent = pWin->parent)))
  3755.         return(Success);
  3756.     if (SubStrSend(pWin, pParent))
  3757.     {
  3758.     event.u.u.type = UnmapNotify;
  3759.     event.u.unmapNotify.window = pWin->drawable.id;
  3760.     event.u.unmapNotify.fromConfigure = fromConfigure;
  3761.     DeliverEvents(pWin, &event, 1, NullWindow);
  3762.     }
  3763.     if (wasViewable && !fromConfigure)
  3764.     {
  3765.     pWin->valdata = UnmapValData;
  3766.     MarkOverlappedWindows(pWin, pWin->nextSib);
  3767.     MarkWindow(pWin->parent);
  3768.     }
  3769.     pWin->mapped = FALSE;
  3770.     if (wasRealized)
  3771.     UnrealizeTree(pWin, fromConfigure);
  3772.     if (wasViewable)
  3773.     {
  3774.     if (!fromConfigure)
  3775.     {
  3776.         (* pWin->drawable.pScreen->ValidateTree)(pParent, pWin, VTUnmap);
  3777.         HandleExposures(pParent);
  3778.     }
  3779. #ifdef DO_SAVE_UNDERS
  3780.     if (DO_SAVE_UNDERS(pWin))
  3781.     {
  3782.         if (pWin->saveUnder ? ChangeSaveUnder(pWin, pWin->nextSib) :
  3783.                   CheckSaveUnder(pWin))
  3784.         {
  3785.         DoChangeSaveUnder(pParent, pWin->nextSib);
  3786.         }
  3787.     }
  3788.     pWin->DIXsaveUnder = FALSE;
  3789. #endif /* DO_SAVE_UNDERS */
  3790.     if (!fromConfigure && pWin->drawable.pScreen->PostValidateTree)
  3791.         (* pWin->drawable.pScreen->PostValidateTree)(pParent,
  3792.                              pWin, VTUnmap);
  3793.     }
  3794.     if (wasRealized && !fromConfigure)
  3795.     WindowsRestructured ();
  3796.     return(Success);
  3797. }
  3798.  
  3799. /*****
  3800.  * UnmapSubwindows
  3801.  *    Performs an UnmapWindow request with the specified mode on all mapped
  3802.  *    children of the window, in bottom to top stacking order.
  3803.  *****/
  3804.  
  3805. UnmapSubwindows(pWin)
  3806.     register WindowPtr pWin;
  3807. {
  3808.     register WindowPtr pChild, pHead;
  3809.     xEvent event;
  3810.     Bool wasRealized = (Bool)pWin->realized;
  3811.     Bool wasViewable = (Bool)pWin->viewable;
  3812.     Bool anyMarked = FALSE;
  3813.     Mask parentNotify;
  3814.  
  3815.     if (!pWin->firstChild)
  3816.     return;
  3817.     parentNotify = SubSend(pWin);
  3818.     pHead = RealChildHead(pWin);
  3819.     for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
  3820.     {
  3821.     if (pChild->mapped)
  3822.         {
  3823.         if (parentNotify || StrSend(pChild))
  3824.         {
  3825.         event.u.u.type = UnmapNotify;
  3826.         event.u.unmapNotify.window = pChild->drawable.id;
  3827.         event.u.unmapNotify.fromConfigure = xFalse;
  3828.         DeliverEvents(pChild, &event, 1, NullWindow);
  3829.         }
  3830.         if (pChild->viewable)
  3831.         {
  3832.         pChild->valdata = UnmapValData;
  3833.         anyMarked = TRUE;
  3834.         }
  3835.         pChild->mapped = FALSE;
  3836.             if (pChild->realized)
  3837.         UnrealizeTree(pChild, FALSE);
  3838.         if (wasViewable)
  3839.         {
  3840. #ifdef DO_SAVE_UNDERS
  3841.         pChild->DIXsaveUnder = FALSE;
  3842. #endif /* DO_SAVE_UNDERS */
  3843.         if (pChild->backStorage)
  3844.             (*pChild->drawable.pScreen->SaveDoomedAreas)(
  3845.                         pChild, &pChild->clipList, 0, 0);
  3846.         }
  3847.     }
  3848.     }
  3849.     if (wasViewable)
  3850.     {
  3851.     if (anyMarked)
  3852.     {
  3853.         MarkWindow(pWin);
  3854.         (* pWin->drawable.pScreen->ValidateTree)(pWin, pHead, VTUnmap);
  3855.         HandleExposures(pWin);
  3856.     }
  3857. #ifdef DO_SAVE_UNDERS
  3858.     if (DO_SAVE_UNDERS(pWin))
  3859.     {
  3860.         if (CheckSaveUnder(pWin->firstChild))
  3861.         DoChangeSaveUnder(pWin, pWin->firstChild);
  3862.     }
  3863. #endif /* DO_SAVE_UNDERS */
  3864.     if (anyMarked && pWin->drawable.pScreen->PostValidateTree)
  3865.         (* pWin->drawable.pScreen->PostValidateTree)(pWin, pHead, VTUnmap);
  3866.     }
  3867.     if (wasRealized)
  3868.     WindowsRestructured ();
  3869. }
  3870.  
  3871.  
  3872. void
  3873. HandleSaveSet(client)
  3874.     register ClientPtr client;
  3875. {
  3876.     register WindowPtr pParent, pWin;
  3877.     register int j;
  3878.  
  3879.     for (j=0; j<client->numSaved; j++)
  3880.     {
  3881.         pWin = (WindowPtr)client->saveSet[j];
  3882.         pParent = pWin->parent;
  3883.         while (pParent && (wClient (pParent) == client))
  3884.             pParent = pParent->parent;
  3885.         if (pParent)
  3886.     {
  3887.             ReparentWindow(pWin, pParent, pWin->drawable.x - wBorderWidth (pWin),
  3888.                pWin->drawable.y - wBorderWidth (pWin), client);
  3889.         if(!pWin->realized && pWin->mapped)
  3890.         pWin->mapped = FALSE;
  3891.             MapWindow(pWin, client);
  3892.     }
  3893.     }
  3894.     xfree(client->saveSet);
  3895.     client->numSaved = 0;
  3896.     client->saveSet = (pointer *)NULL;
  3897. }
  3898.  
  3899. Bool
  3900. VisibleBoundingBoxFromPoint(pWin, x, y, box)
  3901.     register WindowPtr pWin;
  3902.     int x, y;   /* in root */
  3903.     BoxPtr box;   /* "return" value */
  3904. {
  3905.     if (!pWin->realized)
  3906.     return (FALSE);
  3907.     if ((* pWin->drawable.pScreen->PointInRegion)(&pWin->clipList, x, y, box))
  3908.         return(TRUE);
  3909.     return(FALSE);
  3910. }
  3911.  
  3912. Bool
  3913. PointInWindowIsVisible(pWin, x, y)
  3914.     register WindowPtr pWin;
  3915.     int x, y;    /* in root */
  3916. {
  3917.     BoxRec box;
  3918.  
  3919.     if (!pWin->realized)
  3920.     return (FALSE);
  3921.     if ((* pWin->drawable.pScreen->PointInRegion)(&pWin->borderClip,
  3922.                           x, y, &box))
  3923.         return(TRUE);
  3924.     return(FALSE);
  3925. }
  3926.  
  3927.  
  3928. RegionPtr
  3929. NotClippedByChildren(pWin)
  3930.     register WindowPtr pWin;
  3931. {
  3932.     register ScreenPtr pScreen;
  3933.     RegionPtr pReg;
  3934.  
  3935.     pScreen = pWin->drawable.pScreen;
  3936.     pReg = (* pScreen->RegionCreate)(NullBox, 1);
  3937.     if (pWin->parent ||
  3938.     screenIsSaved != SCREEN_SAVER_ON ||
  3939.     !HasSaverWindow (pWin->drawable.pScreen->myNum))
  3940.     {
  3941.     (* pScreen->Intersect) (pReg, &pWin->borderClip, &pWin->winSize);
  3942.     }
  3943.     return(pReg);
  3944. }
  3945.  
  3946.  
  3947. void
  3948. SendVisibilityNotify(pWin)
  3949.     WindowPtr pWin;
  3950. {
  3951.     xEvent event;
  3952.     event.u.u.type = VisibilityNotify;
  3953.     event.u.visibility.window = pWin->drawable.id;
  3954.     event.u.visibility.state = pWin->visibility;
  3955.     DeliverEvents(pWin, &event, 1, NullWindow);
  3956. }
  3957.  
  3958.  
  3959. #define RANDOM_WIDTH 32
  3960.  
  3961. #ifndef NOLOGOHACK
  3962. extern int logoScreenSaver;
  3963. static DrawLogo();
  3964. #endif
  3965.  
  3966. void
  3967. SaveScreens(on, mode)
  3968.     int on;
  3969.     int mode;
  3970. {
  3971.     int i;
  3972.     int what;
  3973.  
  3974.     if (on == SCREEN_SAVER_FORCER)
  3975.     {
  3976.         if (mode == ScreenSaverReset)
  3977.             what = SCREEN_SAVER_OFF;
  3978.         else
  3979.            what = SCREEN_SAVER_ON;
  3980.     if (what == screenIsSaved)
  3981.             return ;
  3982.     }
  3983.     else
  3984.         what = on;
  3985.     for (i = 0; i < screenInfo.numScreens; i++)
  3986.     {
  3987.         if (on == SCREEN_SAVER_FORCER)
  3988.         {
  3989.            (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], on);
  3990.         }
  3991.         if (what == SCREEN_SAVER_OFF)
  3992.         {
  3993.         if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED)
  3994.         {
  3995.            (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i],
  3996.                               what);
  3997.         }
  3998.             else if (HasSaverWindow (i))
  3999.         {
  4000.                 savedScreenInfo[i].pWindow = NullWindow;
  4001.                 FreeResource(savedScreenInfo[i].wid, RT_NONE);
  4002.         }
  4003.         continue;
  4004.         }
  4005.         else if (what == SCREEN_SAVER_ON)
  4006.         {
  4007.             if (screenIsSaved == SCREEN_SAVER_ON)  /* rotate pattern */
  4008.             {
  4009.         if (savedScreenInfo[i].blanked == SCREEN_IS_TILED)
  4010.             {
  4011.             WindowPtr pWin = savedScreenInfo[i].pWindow;
  4012. #ifndef NOLOGOHACK
  4013.             if (logoScreenSaver)
  4014.             (*pWin->drawable.pScreen->ClearToBackground)(pWin, 0, 0, 0, 0, FALSE);
  4015. #endif
  4016.                 MoveWindow(pWin,
  4017.                    (short)(-(rand() % RANDOM_WIDTH)),
  4018.                    (short)(-(rand() % RANDOM_WIDTH)),
  4019.                        pWin->nextSib, VTMove);
  4020. #ifndef NOLOGOHACK
  4021.             if (logoScreenSaver)
  4022.             DrawLogo(pWin);
  4023. #endif
  4024.         }
  4025.         continue;
  4026.         }
  4027.             if (ScreenSaverBlanking != DontPreferBlanking)
  4028.         {
  4029.                 if ((* screenInfo.screens[i]->SaveScreen)
  4030.                          (screenInfo.screens[i], what))
  4031.                 {
  4032.                          savedScreenInfo[i].blanked = SCREEN_IS_BLANKED;
  4033.                          continue;
  4034.                 }
  4035.                 if ((ScreenSaverAllowExposures != DontAllowExposures) &&
  4036.             TileScreenSaver(i, SCREEN_IS_BLACK))
  4037.         {
  4038.             savedScreenInfo[i].blanked = SCREEN_IS_BLACK;
  4039.             continue;
  4040.                 }
  4041.         }
  4042.         if ((ScreenSaverAllowExposures != DontAllowExposures) &&
  4043.         TileScreenSaver(i, SCREEN_IS_TILED))
  4044.             {
  4045.             savedScreenInfo[i].blanked = SCREEN_IS_TILED;
  4046.         }
  4047.             else
  4048.             savedScreenInfo[i].blanked = SCREEN_ISNT_SAVED;
  4049.     }
  4050.     }
  4051.     screenIsSaved = what;
  4052. }
  4053.  
  4054. static Bool
  4055. TileScreenSaver(i, kind)
  4056.     int i;
  4057.     int    kind;
  4058. {
  4059.     int j;
  4060.     int result;
  4061.     XID attributes[3];
  4062.     Mask mask;
  4063.     WindowPtr pWin;        
  4064.     CursorMetricRec cm;
  4065.     unsigned char *srcbits, *mskbits;
  4066.     CursorPtr cursor;
  4067.     XID        cursorID;
  4068.     int    attri;
  4069.  
  4070.     mask = 0;
  4071.     attri = 0;
  4072.     switch (kind) {
  4073.     case SCREEN_IS_TILED:
  4074.         switch (WindowTable[i]->backgroundState) {
  4075.         case BackgroundPixel:
  4076.         attributes[attri++] = WindowTable[i]->background.pixel;
  4077.         mask |= CWBackPixel;
  4078.         break;
  4079.         case BackgroundPixmap:
  4080.         attributes[attri++] = None;
  4081.         mask |= CWBackPixmap;
  4082.         break;
  4083.         default:
  4084.         break;
  4085.         }
  4086.     break;
  4087.     case SCREEN_IS_BLACK:
  4088.     attributes[attri++] = WindowTable[i]->drawable.pScreen->blackPixel;
  4089.     mask |= CWBackPixel;
  4090.     break;
  4091.     }
  4092.     mask |= CWOverrideRedirect;
  4093.     attributes[attri++] = xTrue;
  4094.  
  4095.     /*
  4096.      * create a blank cursor
  4097.      */
  4098.  
  4099.     cm.width=16;
  4100.     cm.height=16;
  4101.     cm.xhot=8;
  4102.     cm.yhot=8;
  4103.     srcbits = (unsigned char *)xalloc( PixmapBytePad(32, 1)*16);
  4104.     mskbits = (unsigned char *)xalloc( PixmapBytePad(32, 1)*16);
  4105.     if (!srcbits || !mskbits)
  4106.     {
  4107.     xfree(srcbits);
  4108.     xfree(mskbits);
  4109.     cursor = 0;
  4110.     }
  4111.     else
  4112.     {
  4113.     for (j=0; j<PixmapBytePad(32, 1)*16; j++)
  4114.         srcbits[j] = mskbits[j] = 0x0;
  4115.     cursor = AllocCursor(srcbits, mskbits, &cm, 0, 0, 0, 0, 0, 0);
  4116.     if (cursor)
  4117.     {
  4118.         cursorID = FakeClientID(0);
  4119.         if (AddResource (cursorID, RT_CURSOR, (pointer) cursor))
  4120.         {
  4121.             attributes[attri] = cursorID;
  4122.             mask |= CWCursor;
  4123.         }
  4124.         else
  4125.         cursor = 0;
  4126.     }
  4127.     else
  4128.     {
  4129.         xfree (srcbits);
  4130.         xfree (mskbits);
  4131.     }
  4132.     }
  4133.  
  4134.     pWin = savedScreenInfo[i].pWindow =
  4135.      CreateWindow(savedScreenInfo[i].wid,
  4136.           WindowTable[i],
  4137.           -RANDOM_WIDTH, -RANDOM_WIDTH,
  4138.           (unsigned short)screenInfo.screens[i]->width + RANDOM_WIDTH,
  4139.           (unsigned short)screenInfo.screens[i]->height + RANDOM_WIDTH,
  4140.           0, InputOutput, mask, attributes, 0, serverClient,
  4141.           wVisual (WindowTable[i]), &result);
  4142.  
  4143.     if (cursor)
  4144.     FreeResource (cursorID, RT_NONE);
  4145.  
  4146.     if (!pWin)
  4147.     return FALSE;
  4148.  
  4149.     if (!AddResource(pWin->drawable.id, RT_WINDOW,
  4150.              (pointer)savedScreenInfo[i].pWindow))
  4151.     return FALSE;
  4152.  
  4153.     if (mask & CWBackPixmap)
  4154.     {
  4155.     pWin->backgroundState = BackgroundPixmap;
  4156.     pWin->background.pixmap = pWin->parent->background.pixmap;
  4157.     pWin->background.pixmap->refcnt++;
  4158.     (*pWin->drawable.pScreen->ChangeWindowAttributes)(pWin, CWBackPixmap);
  4159.     }
  4160.  
  4161.     MapWindow(pWin, serverClient);
  4162. #ifndef NOLOGOHACK
  4163.     if (kind == SCREEN_IS_TILED && logoScreenSaver)
  4164.     DrawLogo(pWin);
  4165. #endif
  4166.     return TRUE;
  4167. }
  4168.  
  4169. /*
  4170.  * FindWindowWithOptional
  4171.  *
  4172.  * search ancestors of the given window for an entry containing
  4173.  * a WindowOpt structure.  Assumptions:  some parent will
  4174.  * contain the structure.
  4175.  */
  4176.  
  4177. WindowPtr
  4178. FindWindowWithOptional (w)
  4179.     register WindowPtr w;
  4180. {
  4181.     do
  4182.     w = w->parent;
  4183.     while (!w->optional);
  4184.     return w;
  4185. }
  4186.  
  4187. /*
  4188.  * CheckWindowOptionalNeed
  4189.  *
  4190.  * check each optional entry in the given window to see if
  4191.  * the value is satisfied by the default rules.  If so,
  4192.  * release the optional record
  4193.  */
  4194.  
  4195. CheckWindowOptionalNeed (w)
  4196.     register WindowPtr w;
  4197. {
  4198.     register WindowOptPtr optional;
  4199.     register WindowOptPtr parentOptional;
  4200.  
  4201.     if (!w->parent)
  4202.     return;
  4203.     optional = w->optional;
  4204.     if (optional->dontPropagateMask != DontPropagateMasks[w->dontPropagate])
  4205.     return;
  4206.     if (optional->otherEventMasks != 0)
  4207.     return;
  4208.     if (optional->otherClients != NULL)
  4209.     return;
  4210.     if (optional->passiveGrabs != NULL)
  4211.     return;
  4212.     if (optional->userProps != NULL)
  4213.     return;
  4214.     if (optional->backingBitPlanes != ~0L)
  4215.     return;
  4216.     if (optional->backingPixel != 0)
  4217.     return;
  4218. #ifdef SHAPE
  4219.     if (optional->boundingShape != NULL)
  4220.     return;
  4221.     if (optional->clipShape != NULL)
  4222.     return;
  4223. #endif
  4224. #ifdef XINPUT
  4225.     if (optional->inputMasks != NULL)
  4226.     return;
  4227. #endif
  4228.     parentOptional = FindWindowWithOptional(w)->optional;
  4229.     if (optional->visual != parentOptional->visual)
  4230.     return;
  4231.     if (optional->cursor != None && optional->cursor != parentOptional->cursor)
  4232.     return;
  4233.     if (optional->colormap != parentOptional->colormap)
  4234.     return;
  4235.     DisposeWindowOptional (w);
  4236. }
  4237.  
  4238. /*
  4239.  * MakeWindowOptional
  4240.  *
  4241.  * create an optional record and initialize it with the default
  4242.  * values.
  4243.  */
  4244.  
  4245. Bool
  4246. MakeWindowOptional (pWin)
  4247.     register WindowPtr pWin;
  4248. {
  4249.     register WindowOptPtr optional;
  4250.     register WindowOptPtr parentOptional;
  4251.  
  4252.     if (pWin->optional)
  4253.     return TRUE;
  4254.     optional = (WindowOptPtr) xalloc (sizeof (WindowOptRec));
  4255.     if (!optional)
  4256.     return FALSE;
  4257.     optional->dontPropagateMask = DontPropagateMasks[pWin->dontPropagate];
  4258.     optional->otherEventMasks = 0;
  4259.     optional->otherClients = NULL;
  4260.     optional->passiveGrabs = NULL;
  4261.     optional->userProps = NULL;
  4262.     optional->backingBitPlanes = ~0L;
  4263.     optional->backingPixel = 0;
  4264. #ifdef SHAPE
  4265.     optional->boundingShape = NULL;
  4266.     optional->clipShape = NULL;
  4267. #endif
  4268. #ifdef XINPUT
  4269.     optional->inputMasks = NULL;
  4270. #endif
  4271.     parentOptional = FindWindowWithOptional(pWin)->optional;
  4272.     optional->visual = parentOptional->visual;
  4273.     if (!pWin->cursorIsNone)
  4274.     {
  4275.     optional->cursor = parentOptional->cursor;
  4276.     optional->cursor->refcnt++;
  4277.     }
  4278.     else
  4279.     {
  4280.     optional->cursor = None;
  4281.     }
  4282.     optional->colormap = parentOptional->colormap;
  4283.     pWin->optional = optional;
  4284.     return TRUE;
  4285. }
  4286.  
  4287. DisposeWindowOptional (pWin)
  4288.     register WindowPtr pWin;
  4289. {
  4290.     if (!pWin->optional)
  4291.     return;
  4292.     /*
  4293.      * everything is peachy.  Delete the optional record
  4294.      * and clean up
  4295.      */
  4296.     if (pWin->optional->cursor)
  4297.     {
  4298.     FreeCursor (pWin->optional->cursor, (Cursor)0);
  4299.     pWin->cursorIsNone = FALSE;
  4300.     }
  4301.     else
  4302.     pWin->cursorIsNone = TRUE;
  4303.     xfree (pWin->optional);
  4304.     pWin->optional = NULL;
  4305. }
  4306.  
  4307. #ifndef NOLOGOHACK
  4308. static
  4309. DrawLogo(pWin)
  4310.     WindowPtr pWin;
  4311. {
  4312.     DrawablePtr pDraw;
  4313.     ScreenPtr pScreen;
  4314.     int x, y;
  4315.     unsigned int width, height, size;
  4316.     GC *pGC;
  4317.     int d11, d21, d31;
  4318.     xPoint poly[4];
  4319.     XID fore[2], back[2];
  4320.     xrgb rgb[2];
  4321.     BITS32 fmask, bmask;
  4322.     ColormapPtr cmap;
  4323.  
  4324.     pDraw = (DrawablePtr)pWin;
  4325.     pScreen = pDraw->pScreen;
  4326.     x = -pWin->origin.x;
  4327.     y = -pWin->origin.y;
  4328.     width = pScreen->width;
  4329.     height = pScreen->height;
  4330.     pGC = GetScratchGC(pScreen->rootDepth, pScreen);
  4331.     if (!pGC)
  4332.     return;
  4333.  
  4334.     if ((rand() % 100) <= 17) /* make the probability for white fairly low */
  4335.     fore[0] = pScreen->whitePixel;
  4336.     else
  4337.     fore[0] = pScreen->blackPixel;
  4338.     if ((pWin->backgroundState == BackgroundPixel) &&
  4339.     (cmap = (ColormapPtr)LookupIDByType(wColormap (pWin), RT_COLORMAP))) {
  4340.     fore[1] = pWin->background.pixel;
  4341.     QueryColors(cmap, 2, fore, rgb);
  4342.     if ((rgb[0].red == rgb[1].red) &&
  4343.         (rgb[0].green == rgb[1].green) &&
  4344.         (rgb[0].blue == rgb[1].blue)) {
  4345.         if (fore[0] == pScreen->blackPixel)
  4346.         fore[0] = pScreen->whitePixel;
  4347.         else
  4348.         fore[0] = pScreen->blackPixel;
  4349.     }
  4350.     }
  4351.     fore[1] = FillSolid;
  4352.     fmask = GCForeground|GCFillStyle;
  4353.     if (pWin->backgroundState == BackgroundPixel) {
  4354.     back[0] = pWin->background.pixel;
  4355.     back[1] = FillSolid;
  4356.     bmask = GCForeground|GCFillStyle;
  4357.     } else {
  4358.     back[0] = 0;
  4359.     back[1] = 0;
  4360.     (void)DoChangeGC(pGC, GCTileStipXOrigin|GCTileStipYOrigin, back, 0);
  4361.     back[0] = FillTiled;
  4362.     back[1] = (XID)pWin->background.pixmap;
  4363.     bmask = GCFillStyle|GCTile;
  4364.     }
  4365.  
  4366.     size = width;
  4367.     if (height < width)
  4368.      size = height;
  4369.     size = RANDOM_WIDTH + rand() % (size - RANDOM_WIDTH);
  4370.     size &= ~1;
  4371.     x += rand() % (width - size);
  4372.     y += rand() % (height - size);
  4373.  
  4374. /*
  4375.  *           -----
  4376.  *          /    /
  4377.  *         /    /
  4378.  *        /    /
  4379.  *       /    /
  4380.  *      /____/
  4381.  */
  4382.  
  4383.     d11 = (size / 11);
  4384.     if (d11 < 1) d11 = 1;
  4385.     d21 = (d11+3) / 4;
  4386.     d31 = d11 + d11 + d21;
  4387.     poly[0].x = x + size;              poly[0].y = y;
  4388.     poly[1].x = x + size-d31;          poly[1].y = y;
  4389.     poly[2].x = x + 0;                 poly[2].y = y + size;
  4390.     poly[3].x = x + d31;               poly[3].y = y + size;
  4391.     (void)DoChangeGC(pGC, fmask, fore, 1);
  4392.     ValidateGC(pDraw, pGC);
  4393.     (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly);
  4394.  
  4395. /*
  4396.  *           ------
  4397.  *          /     /
  4398.  *         /  __ /
  4399.  *        /  /  /
  4400.  *       /  /  /
  4401.  *      /__/__/
  4402.  */
  4403.  
  4404.     poly[0].x = x + d31/2;                       poly[0].y = y + size;
  4405.     poly[1].x = x + size / 2;                    poly[1].y = y + size/2;
  4406.     poly[2].x = x + (size/2)+(d31-(d31/2));      poly[2].y = y + size/2;
  4407.     poly[3].x = x + d31;                         poly[3].y = y + size;
  4408.     (void)DoChangeGC(pGC, bmask, back, 1);
  4409.     ValidateGC(pDraw, pGC);
  4410.     (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly);
  4411.  
  4412. /*
  4413.  *           ------
  4414.  *          /  /  /
  4415.  *         /--/  /
  4416.  *        /     /
  4417.  *       /     /
  4418.  *      /_____/
  4419.  */
  4420.  
  4421.     poly[0].x = x + size - d31/2;                poly[0].y = y;
  4422.     poly[1].x = x + size / 2;                    poly[1].y = y + size/2;
  4423.     poly[2].x = x + (size/2)-(d31-(d31/2));      poly[2].y = y + size/2;
  4424.     poly[3].x = x + size - d31;                  poly[3].y = y;
  4425.     ValidateGC(pDraw, pGC);
  4426.     (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly);
  4427.  
  4428. /*
  4429.  * -----
  4430.  * \    \
  4431.  *  \    \
  4432.  *   \    \
  4433.  *    \    \
  4434.  *     \____\
  4435.  */
  4436.  
  4437.     poly[0].x = x;                     poly[0].y = y;
  4438.     poly[1].x = x + size/4;            poly[1].y = y;
  4439.     poly[2].x = x + size;              poly[2].y = y + size;
  4440.     poly[3].x = x + size - size/4;     poly[3].y = y + size;
  4441.     (void)DoChangeGC(pGC, fmask, fore, 1);
  4442.     ValidateGC(pDraw, pGC);
  4443.     (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly);
  4444.  
  4445. /*
  4446.  *          /
  4447.  *         /
  4448.  *        /
  4449.  *       /
  4450.  *      /
  4451.  */
  4452.  
  4453.     poly[0].x = x + size- d11;        poly[0].y = y;
  4454.     poly[1].x = x + size-( d11+d21);  poly[1].y = y;
  4455.     poly[2].x = x + d11;              poly[2].y = y + size;
  4456.     poly[3].x = x + d11 + d21;        poly[3].y = y + size;
  4457.     (void)DoChangeGC(pGC, bmask, back, 1);
  4458.     ValidateGC(pDraw, pGC);
  4459.     (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly);
  4460.  
  4461.     FreeScratchGC(pGC);
  4462. }
  4463.  
  4464. #endif
  4465.