
(DEFUN REMOVE-WINDOW (WINDOW STATE VULTURE-RECTANGLE &OPTIONAL (STILL-MAPPED T))
  "Visually remove WINDOW from its position in the hierarchy.
STILL-MAPPED is non-NIL if WINDOW remains mapped, NIL if it becomes unmapped."
  ;; This function is used for the unmap-window request and the `bury' case
  ;; of the configure-window request.  We don't affect data structures to really
  ;; remove this window from the window hierarchy.
  ;; The idea of this is to place WINDOW at the bottom of the hierarchy if
  ;; STILL-MAPPED is non-NIL or to remove WINDOW completely if STILL-MAPPED is
  ;; NIL.  We start with a rectangle representing WINDOW and check for
  ;; intersecting windows below WINDOW in the occlusion stack.  When we get to
  ;; the last window in the occlusion stack, we will either give the rest to
  ;; the parent of WINDOW (if STILL-MAPPED is NIL) or to WINDOW (if
  ;; STILL-MAPPED is non-NIL).  (The term vulture-rectangle is used to signify
  ;; that other windows are picking away at WINDOW, only leaving what they
  ;; don't need.
  (UNLESS (EQL (window.class window) input-only)
    (LET* ((SIBLING      (WINDOW.NEXT-SIB WINDOW))
           SIBLING-BOX
           (PARENT       (WINDOW.PARENT   WINDOW))
           (LAST-SIBLING (WINDOW.LAST-CHILD PARENT)))
      (SAVE-AREAS WINDOW)
      (WHEN (AND (NOT (EQ LAST-SIBLING WINDOW))
                 VULTURE-RECTANGLE)
        ;; WINDOW is not at the bottom of the occlusion stack.
        (LOOP
          (WHEN (AND (WINDOW.MAPPED-P SIBLING)
                     (NOT (EQL (window.class sibling) input-only))
                     (WINDOWS-INTERSECT-P WINDOW SIBLING))
            (SETQ SIBLING-BOX (MAKE-WINDOW-BOX SIBLING))
            (EXPOSE-WINDOW-PORTION SIBLING STATE VULTURE-RECTANGLE T)
            (SETQ VULTURE-RECTANGLE (SUBTRACT-BOX VULTURE-RECTANGLE SIBLING-BOX)))
          (WHEN (EQ SIBLING LAST-SIBLING)
            (RETURN NIL))
          (SETQ SIBLING (WINDOW.NEXT-SIB SIBLING))))
      ;; If STILL-MAPPED is T then we are all done with the drawing part
      ;; since the only part of WINDOW which remains is that part which its
      ;; lower level siblings left alone.
      (WHEN (NULL STILL-MAPPED)
        (EXPOSE-WINDOW-PORTION PARENT STATE VULTURE-RECTANGLE T)))))



(DEFUN UNMAP-WINDOW (STATE WINDOW)
  ;; If the window is already unmapped then we are done.
  (WHEN (WINDOW.MAPPED-P WINDOW)
    (LET* ((PARENT (WINDOW.PARENT WINDOW))
           (ANCESTERS-MAPPED T)
           (ANCESTER PARENT))
      (LOOP
        (WHEN (NOT (WINDOW.MAPPED-P ANCESTER))
          (SETQ ANCESTERS-MAPPED NIL)
          (RETURN NIL))
        (SETQ ANCESTER (WINDOW.PARENT ANCESTER))
        (WHEN (NULL ANCESTER)
          (RETURN NIL)))
      (progn ;; WITH-TREE-LOCKED (PARENT) ;; lock moved to unmap-window-request - LGO
        (SETF (WINDOW.MAPPED-P WINDOW) NIL)
	(WHEN ANCESTERS-MAPPED
	  (LET ((OLD-OCCLUSION-STACK (OCCLUSION-STACK-TO-LIST WINDOW (WINDOW.OCCLUSION-STACK WINDOW))))
	    (GENERATE-ALL-INFERIORS-OCCLUSION-STACKS PARENT)
	    ;; Visually remove the window.
	    (REMOVE-WINDOW WINDOW STATE OLD-OCCLUSION-STACK NIL))
	  (UNMAP-NOTIFY-EVENT STATE WINDOW NIL))))
    ;; A window is realized if it and its ancestors are mapped.
    (SETF (WINDOW.REALIZED-P WINDOW) NIL)
    ;; Need to do the same for children.
    (LABELS ((CHECK-INFERIORS (WINDOW)
               "Check inferiors of WINDOW to make then unrealized."
               (LET ((CHILD      (WINDOW.FIRST-CHILD WINDOW))
                     (LAST-CHILD (WINDOW.LAST-CHILD  WINDOW)))
                 (WHEN CHILD
                   (LOOP
                     (SETF (WINDOW.REALIZED-P CHILD) NIL)
                     (CHECK-INFERIORS CHILD)
                     (WHEN (EQ CHILD LAST-CHILD)
                       (RETURN NIL))
                     (SETQ CHILD (WINDOW.NEXT-SIB CHILD)))))))
      (CHECK-INFERIORS WINDOW))))




(DEFUN EXPOSE-WINDOW-PORTION (WINDOW STATE BOXES &OPTIONAL (OCCLUSION-STACKS-UPDATED T))
  "Try to expose the portion of WINDOW indicated by BOXES."
  ;; We will either draw the portion of the WINDOW from the backing store, or tell
  ;; the application that part of WINDOW needs to be updated.
  ;; We are guaranteed that WINDOW is mapped.  Note that it could be that WINDOW
  ;; has children which need to be exposed.  We will look at the children to see
  ;; if any of them overlap BOXES and call ourselves recursively.
  
  (server-trace "~%EXPOSE-WINDOW-PORTION; window=~S boxes=~S" window boxes)
  (WHEN (AND BOXES (WINDOW.MAPPED-P WINDOW) (WINDOW.REALIZED-P WINDOW)
	     (NOT (EQL (WINDOW.CLASS WINDOW) INPUT-ONLY)))
    (VALIDATE-BACKING-STORE WINDOW)
    (LET* ((INTERIOR-BOX (MAKE-WINDOW-BOX-INTERIOR WINDOW))
           (BACKING-STORE (AND (WINDOW.BACKING-STORE-VALID WINDOW)
			       (WINDOW.BACKING-STORE     WINDOW)))
           (ABSOLUTE-X    (WINDOW.ABSOLUTE-INSIDE-X WINDOW))
           (ABSOLUTE-Y    (WINDOW.ABSOLUTE-INSIDE-Y WINDOW))
           (FRAME-BUFFER (DEVICE-PRIVATE-WINDOW-ARRAY WINDOW))
	   (BOXES-TO-DRAW (SET-INTERSECT-BOXES BOXES INTERIOR-BOX))
	   (OCCLUSION-STACK (WINDOW.OCCLUSION-STACK WINDOW))
	   INTERSECT-BOXES)
      ;; Output the borders before we do anything else.
      ;; If we don't have anything to draw with, then we can't draw.
      ;; We need to obtain boxes for the interior part of the window.
      (IF OCCLUSION-STACKS-UPDATED
	  ;; O.S. are up to date - only expose parts of window that
	  ;; are visible *now* and intersect boxes-to-draw
	  (SETQ INTERSECT-BOXES
		(SET-INTERSECT-BOX-SETS BOXES-TO-DRAW (OCCLUSION-STACK-TO-LIST WINDOW OCCLUSION-STACK)))
	;; O.S. are old - just expose anything that intersects with window interior
	(SETQ INTERSECT-BOXES BOXES-TO-DRAW))
      #+comment
      (loop
	while intersect-boxes
	for child being the xwindow-children of window
	when (and (WINDOW.MAPPED-P child) (WINDOW.REALIZED-P child)
	     (NOT (EQL (WINDOW.CLASS child) INPUT-ONLY)))
	do
	(setq intersect-boxes (subtract-box intersect-boxes (make-window-box child))))
      (WHEN INTERSECT-BOXES
	(WITH-CURSOR-LOCKED (:SERVER)
	  (MAYBE-REMOVE-CURSOR WINDOW)
	  (DRAW-BORDERS WINDOW)
	  (LOOP FOR BOX IN INTERSECT-BOXES
		;; Count is the number of boxes remaining after this one.
		FOR COUNT DOWNFROM (1- (LENGTH INTERSECT-BOXES))
		FOR BOX-LEFT   = (BOX.LEFT   BOX)
		FOR BOX-TOP    = (BOX.TOP    BOX)
		FOR BOX-WIDTH  = (BOX.WIDTH  BOX)
		FOR BOX-HEIGHT = (BOX.HEIGHT BOX)
		DO
		(IF BACKING-STORE
		    ;; We have enough data to generate the parts of the window which
		    ;; are now visible.
		    (X-BITBLT GX-COPY BOX-WIDTH BOX-HEIGHT
			      (PIXMAP.ARRAY BACKING-STORE)
			      (- BOX-LEFT ABSOLUTE-X) (- BOX-TOP ABSOLUTE-Y)
			      FRAME-BUFFER BOX-LEFT BOX-TOP)
		  ;;ELSE
		  ;; We didn't have anything on the window, so it is up to the
		  ;; application to update itself.  
		  (EXPOSE-EVENT STATE WINDOW BOX-LEFT BOX-TOP BOX-WIDTH BOX-HEIGHT COUNT T)
		  ))))
      (when boxes-to-draw
	(LOOP
	  FOR CHILD BEING THE XWINDOW-CHILDREN OF WINDOW
	  DO
	  (EXPOSE-WINDOW-PORTION CHILD STATE BOXES OCCLUSION-STACKS-UPDATED)))
      )))
