;;; -*- Mode: Common-Lisp; Package: User; Base: 10.; Patch-File: T -*-

;;; Reason: Prevent error in FILL-RECTANGLE when rectangle is invisible due to clipping.

;;;                           RESTRICTED RIGHTS LEGEND
;;;
;;; Use, duplication, or disclosure by the Government is subject to
;;; restrictions as set forth in subdivision (c)(1)(ii) of the Rights in
;;; Technical Data and Computer Software clause at 52.227-7013.
;;;
;;;   TEXAS INSTRUMENTS INCORPORATED      
;;;   P.O. BOX 2909, M/S 2151             
;;;   AUSTIN, TEXAS 78769                 
;;;
;;; Copyright (C) 1989 Texas Instruments Incorporated.
;;; All rights reserved.

;;; Patch file for X11M version 6.12
;;; Written 07/07/89 22:16:55 by buehring,
;;; while running on Spud from band LOD4
;;; With SYSTEM 6.10, VIRTUAL-MEMORY 6.1, EH 6.3, MAKE-SYSTEM 6.0, MICRONET 6.0, LOCAL-FILE 6.0,
;;;  BASIC-PATHNAME 6.1, NETWORK-SUPPORT-COLD 6.0, BASIC-NAMESPACE 6.1, NETWORK-NAMESPACE 6.0,
;;;  DISK-IO 6.0, DISK-LABEL 6.0, BASIC-FILE 6.2, MAC-PATHNAME 6.0, NETWORK-PATHNAME 6.0,
;;;  COMPILER 6.7, TV 6.12, DATALINK 6.0, CHAOSNET 6.0, GC 6.3, MEMORY-AUX 6.0, NVRAM 6.1,
;;;  SYSLOG 6.1, STREAMER-TAPE 6.4, UCL 6.0, INPUT-EDITOR 6.0, METER 6.1, ZWEI 6.3,
;;;  DEBUG-TOOLS 6.3, NETWORK-SUPPORT 6.0, NETWORK-SERVICE 6.1, DATALINK-DISPLAYS 6.0,
;;;  FONT-EDITOR 6.1, SERIAL 6.0, PRINTER 6.3, MAC-PRINTER-TYPES 6.1, PRINTER-TYPES 6.1,
;;;  IMAGEN 6.0, SUGGESTIONS 6.0, MAIL-DAEMON 6.2, MAIL-READER 6.1, TELNET 6.0, VT100 6.0,
;;;  NAMESPACE-EDITOR 6.0, PROFILE 6.1, VISIDOC 6.2, TI-CLOS 6.11, CLEH 6.4, IP 3.47,
;;;  Experimental BUG 11.10, Experimental CLX 6.2, CLUE 6.5, X11M 6.11,  microcode 429,
;;;  Band Name: Release 6.0 + SLE  6/26

#!C
; From file GRAPHICS-PRIMITIVES.LISP#> X11M.SERVER; MR-X:
#10R X11#:
(COMPILER-LET ((*PACKAGE* (FIND-PACKAGE "X11"))
                          (SI:*LISP-MODE* :COMMON-LISP)
                          (*READTABLE* SYS:COMMON-LISP-READTABLE)
                          (SI:*READER-SYMBOL-SUBSTITUTIONS* SYS::*COMMON-LISP-SYMBOL-SUBSTITUTIONS*))
  (COMPILER#:PATCH-SOURCE-FILE "SYS: X11M.SERVER; GRAPHICS-PRIMITIVES.#"


(DEFUN FILL-RECTANGLE (DRAWABLE GCONTEXT X Y WIDTH HEIGHT PIXEL)
  "Fill a rectangle, taking into account any children in the drawable."
  (LET ((OCCLUSION-STACK (AND (TYPEP DRAWABLE 'WINDOW) (WINDOW.OCCLUSION-STACK DRAWABLE))))
    (LABELS ((DRAW-WINDOW-RECTANGLE (DRAWABLE X Y WIDTH HEIGHT)
               "Draw a rectangle onto drawable taking into account the clip-mask of the gcontext."
	       (COND ((not (GCONTEXT.CLIP-P GCONTEXT))       ; Normal, simple case, no clip mask
		      (DRAW-RECTANGLE DRAWABLE X Y WIDTH HEIGHT PIXEL))
		     ((gcontext.clip-mask gcontext)
		      ;; We have a clip-mask, which is the most general case.  We need to
		      ;; combine the clip-mask with the rectangle we are trying to draw
		      ;; to obtain the pixels on the drawable that are to be filled.
		      (using-resource (TEMP-RECTANGLE pixmap DRAWABLE WIDTH HEIGHT 1 0)
			;; Copy only those bits of the clip mask that are inside
			;; of the rectangle we are trying to draw.
			(COPY-ARRAY-CLIPPED WIDTH HEIGHT NIL
					    (GCONTEXT.CLIP-MASK GCONTEXT)
					    (- (POINT.X (GCONTEXT.CLIP-ORIGIN GCONTEXT)))
					    (- (POINT.Y (GCONTEXT.CLIP-ORIGIN GCONTEXT)))
					    TEMP-RECTANGLE 0 0)
			(x-BITBLT (if (zerop pixel) gx-and-inverted gx-or)
				  WIDTH HEIGHT
				  TEMP-RECTANGLE 0 0
				  (DEVICE-PRIVATE-DRAWABLE DRAWABLE) X Y)))
		     ;; Clip to a single clipping rectangle
		     ((GCONTEXT.clip-rectangle GCONTEXT)
		      (LET ((BOX-TO-DRAW
			      (nintersect-boxes
				(MAKE-BOX :LEFT X :TOP Y :WIDTH WIDTH :HEIGHT HEIGHT)
				(GCONTEXT.clip-rectangle GCONTEXT))))
			(WHEN BOX-TO-DRAW
			  (DRAW-RECTANGLE DRAWABLE (BOX.LEFT BOX-TO-DRAW) (BOX.TOP BOX-TO-DRAW)
					  (BOX.WIDTH BOX-TO-DRAW) (BOX.HEIGHT BOX-TO-DRAW)
					PIXEL))))
		     ;; Else no clip-rectangle, nothing to draw
		     ))

             (DRAW-OCCLUDED-RECTANGLE (X-OR-BOX &OPTIONAL Y WIDTH HEIGHT)
             "Draw a rectangle through the occlusion stack.  The argument X-OR-BOX
              is either an X coordinate, or is a box object."
             ;; This added complexity is trying to avoid creating a box object when
             ;; we already have one.
             (LET* ((BOX-P (TYPEP X-OR-BOX 'BOX))
                    (X X-OR-BOX))
               (WHEN BOX-P
                 ;; We have a box.  Initialize the other arguments from the parts of the box.
                 (SETQ X      (BOX.LEFT   X-OR-BOX)
                       Y      (BOX.TOP    X-OR-BOX)
                       WIDTH  (BOX.WIDTH  X-OR-BOX)
                       HEIGHT (BOX.HEIGHT X-OR-BOX)))
               (IF (EQ OCCLUSION-STACK T)
                   ;; Simple case.  The window is fully visible, so we just draw the rectangle.
                   (DRAW-WINDOW-RECTANGLE DRAWABLE X Y WIDTH HEIGHT)
                   ;;ELSE
                   (LET* ((window-x (window.absolute-inside-x drawable))
			  (window-y (window.absolute-inside-y drawable))
			  ;; Translate the box to draw to absolute coordinates
			  (RECTANGLE-BOX (MAKE-BOX :LEFT (+ X window-x) :TOP  (+ Y window-y)
						   :WIDTH WIDTH :HEIGHT HEIGHT)))
                     ;; Go through the occlusion stack to find a box which overlaps the rectangle
                     ;; we are trying to draw.
                     (DOLIST (BOX OCCLUSION-STACK)
                       (WHEN (BOX-INTERSECT-P BOX RECTANGLE-BOX)
                         ;; Draw part of our rectangle where the two boxes intersect.
                         (LET ((COMMON-BOX (INTERSECT-BOXES BOX RECTANGLE-BOX)))
			   (when common-box
			     (DRAW-WINDOW-RECTANGLE
			       DRAWABLE ;; get window-relative x/y coordinates
			       (- (BOX.LEFT COMMON-BOX) window-x)
			       (- (BOX.top COMMON-BOX) window-y)
			       (BOX.WIDTH COMMON-BOX) (BOX.HEIGHT COMMON-BOX)))))))))))
      (IF (TYPEP DRAWABLE 'WINDOW)
          (PROGN
            ;; If this window has a backing store, then we need to draw the rectangle there too.
	    (WHEN (window.backing-store-valid drawable)
	      (DRAW-WINDOW-RECTANGLE (window.backing-store drawable) X Y WIDTH HEIGHT))
            ;; If the window isn't mapped then all we needed to do is to update the backing
            ;; store.  If the window is mapped then we need to update the window too.
            (WHEN (AND (WINDOW.MAPPED-P DRAWABLE)
                       (NOT (EQL (window.class drawable) input-only)))
              (IF (OR (= (GCONTEXT.SUBWINDOW-MODE GCONTEXT) SUBWINDOW-MODE-INCLUDE-INFERIORS)
                      (TYPEP DRAWABLE 'PIXMAP)
                      (NULL (LOCATE-FIRST-CHILD DRAWABLE)))
                  ;; Simple case: include-inferiors subwindow mode, or there are no children.
                  (DRAW-OCCLUDED-RECTANGLE X Y WIDTH HEIGHT)
                  ;;ELSE
                  ;; The subwindow mode is clip-by-children and we have children.  Only
                  ;; fill the part of the window that is not in the children.
                  (LET ((CHILD-INTERSECTS-RECTANGLE NIL))
                    ;; First, see if we need to deal with the children at all.
		    (loop for child being the xwindow-children of drawable
			  when (AND (WINDOW.MAPPED-P child)
                                    (NOT (EQL (window.class child) input-only))) do
			  (unless (OR
				    ;; Window below the rectangle?
				    (> (WINDOW.Y CHILD) (+ Y HEIGHT -1))
				    ;; Window above the rectangle?
				    (< (+ (WINDOW.Y CHILD) (WINDOW.OUTSIDE-HEIGHT CHILD) -1)
				       Y)
				    ;; Window to the left of the rectangle?
				    (< (+ (WINDOW.X CHILD) (WINDOW.OUTSIDE-WIDTH  CHILD) -1)
				       X)
				    ;; Window to the right of the rectangle?
				    (> (WINDOW.X CHILD) (+ X WIDTH -1)))
                            (SETQ CHILD-INTERSECTS-RECTANGLE T)
                            (RETURN NIL)))
                    (IF CHILD-INTERSECTS-RECTANGLE
                          ;; Create boxes which are those parts of the rectangle which can be
                          ;; drawn.  Note that the (X,Y) coordinates are relative to the
                          ;; inside of the drawable.
                        (let ((RECTANGLE-BOX (INTERSECT-BOXES
					       ;; Box for the rectangle.
					       (MAKE-BOX :LEFT X :TOP Y
							 :WIDTH WIDTH :HEIGHT HEIGHT)
					       ;; Box for the drawable.
					       (MAKE-BOX :LEFT   0
							 :TOP    0
							 :WIDTH  (WINDOW.WIDTH    DRAWABLE)
							 :HEIGHT (WINDOW.HEIGHT   DRAWABLE)))))
                          (LOOP for child being the xwindow-children of drawable
				when (AND (WINDOW.MAPPED-P child)
                                          (NOT (EQL (window.class child) input-only))) do
				(SETQ RECTANGLE-BOX (SUBTRACT-BOX
						      RECTANGLE-BOX
						      (MAKE-BOX
							:LEFT   (WINDOW.X              CHILD)
							:TOP    (WINDOW.Y              CHILD)
							:WIDTH  (WINDOW.OUTSIDE-WIDTH  CHILD)
							:HEIGHT (WINDOW.OUTSIDE-HEIGHT CHILD)))))
                          (LOOP FOR RECTANGLE IN RECTANGLE-BOX
                                DO (DRAW-OCCLUDED-RECTANGLE RECTANGLE)))
                        ;;ELSE
                        ;; None of the children overlap this rectangle, so we can just draw
                        ;; it since there will be no interference.
                        (DRAW-OCCLUDED-RECTANGLE X Y WIDTH HEIGHT))))))
          ;;ELSE
          ;; Simple case: a pixmap, which can't have inferiors.
          (DRAW-RECTANGLE DRAWABLE X Y WIDTH HEIGHT PIXEL)))))

))
