(FILECREATED "23-SEP-83 18:24:58" {PHYLUM}<LISPUSERS>MENUEDWINDOW.;6 20020  

      changes to:  (FNS MENUEDWINDOWCLOSEFN)

      previous date: "12-APR-83 14:46:51" {PHYLUM}<LISPUSERS>MENUEDWINDOW.;5)


(* Copyright (c) 1983 by Xerox Corporation)

(PRETTYCOMPRINT MENUEDWINDOWCOMS)

(RPAQQ MENUEDWINDOWCOMS ((* This file contains a set of functions that allow the user to treate a 
			    main window and an associated menu as a single unit. The pair can be 
			    MOVED RESHAPED CLOSED etc. as if it was a single entity. The menu can be 
			    position above, below or on either side of the main window. The user has 
			    the option of specifying the location and size of the main window. 
			    Various heuristics are applied to make sure that the result is large 
			    enoght to display the menu and window titles)
			 (FNS MAKEMENUEDWINDOW MOVEMENUWINDOW RESHAPEMENUEDWINDOW 
			      GETREGIONFORMENUEDWINDOW MAKEMENUWINDOW MENUEDWINDOWTOTOPFN 
			      MENUEDWINDOWCLOSEFN MENUEDWINDOWOPENFN)))



(* This file contains a set of functions that allow the user to treate a main window and an 
associated menu as a single unit. The pair can be MOVED RESHAPED CLOSED etc. as if it was a 
single entity. The menu can be position above, below or on either side of the main window. The 
user has the option of specifying the location and size of the main window. Various heuristics 
are applied to make sure that the result is large enoght to display the menu and window titles)

(DEFINEQ

(MAKEMENUEDWINDOW
  [LAMBDA (MENU WINDOWTITLE LOCATION WINDOWSPEC MENUWINDOWTITLE FONT)
                                                             (* rrb " 8-APR-83 17:10")

          (* This function is used to create a MAIN window MENU pair. MENU specifty the menu content and may be a menu, a 
	  simple list or in A-list format. WINDOWTITLE is a string specifying a title for the main window.
	  LOCATION specifies the placement of the window.. (TOP BOTTOM LEFT RIGHT) WINDOWSPECT may be a REGION or an 
	  EXISTING WINDOW. If it is NIL, a new window will be created. MENUWINDOWTITLE is a string specifying a title for 
	  the menu window. FONT specifies the font to be used in the menu.)


    (PROG (WINDOW ITEMS REGION #OFITEMS/ROW MINWIDTH MINHEIGHT MINITEMWIDTH ROWS COLUMNS)
          [COND
	    ((NULL LOCATION)                                 (* Default LOCATION is TOP)
	      (SETQ LOCATION (QUOTE TOP]
          [COND
	    ((NULL FONT)                                     (* Default font is HEVETICA10 in BOLD)
	      (SETQ FONT (FONTCREATE (QUOTE (HELVETICA 10 BOLD]
          [COND
	    [(LISTP MENU)
	      (SETQ ITEMS MENU)
	      (SETQ ROWS (if (FMEMB LOCATION (QUOTE (TOP BOTTOM)))
			     then 1
			   else (LENGTH ITEMS]
	    (T (SETQ MENU (create MENU copying MENU))
	       (SETQ ITEMS (fetch ITEMS of MENU))
	       (SETQ MENUWINDOWTITLE (fetch TITLE of MENU))
	       (SETQ ROWS (if (fetch MENUROWS of MENU)
			    else (replace MENUROWS of MENU with (if (FMEMB LOCATION
									   (QUOTE (TOP BOTTOM)))
								    then 1
								  else (LENGTH ITEMS]
          (CLRPROMPT)                                        (* The minimum item width is the width of the longest 
							     element of the menu)
          (SETQ #OFITEMS/ROW (IQUOTIENT (IPLUS (SUB1 ROWS)
					       (LENGTH ITEMS))
					ROWS))
          (SETQ MINITEMWIDTH (IPLUS (APPLY (QUOTE IMAX)
					   (for X in ITEMS collect (STRINGWIDTH (COND
										  ((LISTP X)
										    (CAR X))
										  (T X))
										FONT)))
				    (STRINGWIDTH " " FONT)))
                                                             (* The minimum width of the window takes into account 
							     the contents of the menu an titles)
          (SETQ MINWIDTH (IPLUS (STRINGWIDTH WINDOWTITLE (DSPFONT NIL WindowTitleDisplayStream))
				(STRINGWIDTH " " WindowTitleDisplayStream)))
          [if (FMEMB LOCATION (QUOTE (TOP BOTTOM)))
	      then (SETQ MINWIDTH (IMAX (ITIMES MINITEMWIDTH #OFITEMS/ROW)
					MINWIDTH
					(IPLUS (STRINGWIDTH MENUWINDOWTITLE (DSPFONT NIL 
									 WindowTitleDisplayStream))
					       (STRINGWIDTH " " WindowTitleDisplayStream]
                                                             (* The window must be tall enough to hold the title)
          [SETQ MINHEIGHT (IPLUS 4 (ITIMES ROWS (FONTHEIGHT (DSPFONT NIL WindowTitleDisplayStream]
                                                             (* Columns and rowas are set depending on the location 
							     of the window)

          (* The window may be specified by the user. A region or an existing window may be supplied by the caller.
	  In any case the size may have to be adjusted so that titles and and menu fit)


          [SETQ WINDOW (COND
	      ((NULL WINDOWSPEC)
		(printout PROMPTWINDOW "Specify a region for " (if WINDOWTITLE
								 else "the window"))
		(SETQ REGION (GETREGION MINWIDTH MINHEIGHT NIL (FUNCTION GETREGIONFORMENUEDWINDOW)
					(LIST #OFITEMS/ROW MINWIDTH)))
		(CREATEW REGION WINDOWTITLE))
	      ((REGIONP WINDOWSPEC)
		(SETQ REGION WINDOWSPEC)
		(COND
		  ((LESSP (fetch HEIGHT of REGION)
			  MINHEIGHT)
		    (REPLACE HEIGHT OF REGION WITH MINHEIGHT)))
		(COND
		  ((LESSP (fetch WIDTH of REGION)
			  MINWIDTH)
		    (REPLACE WIDTH OF REGION WITH MINWIDTH)))
		(replace WIDTH of REGION with (IPLUS (ITIMES (IQUOTIENT (fetch WIDTH of REGION)
									#OFITEMS/ROW)
							     #OFITEMS/ROW)
						     2))
		(CREATEW REGION WINDOWTITLE))
	      ((WINDOWP WINDOWSPEC)
		(CLOSEW WINDOWSPEC)
		(SETQ REGION (WINDOWPROP WINDOWSPEC (QUOTE REGION)))
		(COND
		  ((LESSP (fetch HEIGHT of REGION)
			  MINHEIGHT)
		    (REPLACE HEIGHT OF REGION WITH MINHEIGHT)))
		(COND
		  ((LESSP (fetch WIDTH of REGION)
			  MINWIDTH)
		    (replace WIDTH of REGION with MINWIDTH)))
		(replace WIDTH of REGION with (IPLUS (ITIMES (IQUOTIENT (fetch WIDTH of REGION)
									#OFITEMS/ROW)
							     #OFITEMS/ROW)
						     2))
		(SHAPEW WINDOWSPEC REGION)
		(COND
		  (WINDOWTITLE (WINDOWPROP WINDOWSPEC (QUOTE TITLE)
					   WINDOWTITLE)))
		(OPENW WINDOWSPEC)
		WINDOWSPEC)
	      ((SHOULDNT]                                    (* If the menu is on the side continue the title bar 
							     even if the menu has no title)
          (COND
	    ((AND (NULL MENUWINDOWTITLE)
		  (MEMBER LOCATION (QUOTE (LEFT RIGHT)))
		  (WINDOWPROP WINDOW (QUOTE TITLE)))
	      (SETQ MENUWINDOWTITLE " ")))                   (* Now set up the menu)
          (COND
	    ((LISTP MENU)
	      (SELECTQ LOCATION
		       ((TOP BOTTOM)
			 (SETQ COLUMNS #OFITEMS/ROW)
			 (SETQ ROWS 1))
		       ((RIGHT LEFT)
			 (SETQ COLUMNS 1)
			 (SETQ ROWS #OFITEMS/ROW))
		       (SHOULDNT))
	      (SETQ MENU
		(create MENU
			MENUFONT ← FONT
			ITEMS ← ITEMS
			MENUCOLUMNS ← COLUMNS
			MENUROWS ← ROWS
			CENTERFLG ← T
			TITLE ← MENUWINDOWTITLE)))
	    (T (if MENUWINDOWTITLE
		   then (replace TITLE of MENU with MENUWINDOWTITLE))
	       (UPDATE/MENU/IMAGE MENU)))
          (CLRPROMPT)                                        (* if the menu is horizontal adjuest the ITEMWIDTH parm 
							     of the menu)
          (COND
	    ((MEMBER LOCATION (QUOTE (TOP BOTTOM)))
	      (replace ITEMWIDTH of MENU with (IQUOTIENT (fetch (REGION WIDTH)
							    of (WINDOWPROP WINDOW (QUOTE REGION)))
							 #OFITEMS/ROW))
	      (UPDATE/MENU/IMAGE MENU)))                     (* Now build the menu window)
          (MAKEMENUWINDOW WINDOW MENU LOCATION)              (* Window properties are added to the main window so 
							     that operations like MOVE and RESHAPE can take the menu 
							     window into account)
          (WINDOWPROP WINDOW (QUOTE NEWREGIONFN)
		      (FUNCTION GETREGIONFORMENUEDWINDOW))
          (WINDOWPROP WINDOW (QUOTE MINWIDTH)
		      MINWIDTH)
          (WINDOWPROP WINDOW (QUOTE MENUPOSITION)
		      LOCATION)
          (WINDOWPROP WINDOW (QUOTE AFTERMOVEFN)
		      (FUNCTION MOVEMENUWINDOW))
          (WINDOWPROP WINDOW (QUOTE RESHAPEFN)
		      (FUNCTION RESHAPEMENUEDWINDOW))
          (WINDOWPROP WINDOW (QUOTE TOTOPFN)
		      (FUNCTION MENUEDWINDOWTOTOPFN))
          (WINDOWPROP WINDOW (QUOTE CLOSEFN)
		      (FUNCTION MENUEDWINDOWCLOSEFN))
          (WINDOWPROP WINDOW (QUOTE OPENFN)
		      (FUNCTION MENUEDWINDOWOPENFN))
          [WINDOWPROP WINDOW (QUOTE SHRINKFN)
		      (FUNCTION (LAMBDA (W)
			  (SETQ W (WINDOWPROP W (QUOTE MENUWINDOW)))
			  (WINDOWPROP W (QUOTE CLOSEFN)
				      NIL)
			  (CLOSEW W)
			  (WINDOWPROP W (QUOTE CLOSEFN)
				      (QUOTE DON'T]
          [WINDOWPROP WINDOW (QUOTE EXPANDFN)
		      (FUNCTION (LAMBDA (W)
			  (SETQ W (WINDOWPROP W (QUOTE MENUWINDOW)))
			  (WINDOWPROP W (QUOTE OPENFN)
				      NIL)
			  (OPENW W)
			  (WINDOWPROP W (QUOTE OPENFN)
				      (QUOTE DON'T]
      NIL (RETURN WINDOW])

(MOVEMENUWINDOW
  [LAMBDA (WINDOW)                                           (* SDG " 4-FEB-83 09:52")
                                                             (* This function is called whenever the main window is 
							     moved. It repositions the associated menuwindow)
    (PROG (MENUWINDOW LOCATIONFORMENU MENUFORWINDOW)
          (SETQ MENUWINDOW (WINDOWPROP WINDOW (QUOTE MENUWINDOW)))
          (SETQ MENUFORWINDOW (WINDOWPROP WINDOW (QUOTE WINDOWMENU)))
                                                             (* The location of the menu depends on its position with
							     respect to the main window)
          (SETQ LOCATIONFORMENU (SELECTQ (WINDOWPROP WINDOW (QUOTE MENUPOSITION))
					 [TOP (create POSITION
						      XCOORD ←(fetch LEFT of (WINDOWPROP
									       WINDOW
									       (QUOTE REGION)))
						      YCOORD ←(fetch PTOP of (WINDOWPROP
									       WINDOW
									       (QUOTE REGION]
					 [BOTTOM (create POSITION
							 XCOORD ←(fetch LEFT
								    of (WINDOWPROP WINDOW
										   (QUOTE REGION)))
							 YCOORD ←(IDIFFERENCE
							   (fetch BOTTOM of (WINDOWPROP WINDOW
											(QUOTE REGION)
											))
							   (fetch IMAGEHEIGHT of MENUFORWINDOW]
					 [LEFT (create POSITION
						       XCOORD ←(IDIFFERENCE
							 (fetch LEFT of (WINDOWPROP WINDOW
										    (QUOTE REGION)))
							 (fetch IMAGEWIDTH of MENUFORWINDOW))
						       YCOORD ←(IDIFFERENCE
							 (fetch TOP of (WINDOWPROP WINDOW
										   (QUOTE REGION)))
							 (fetch IMAGEHEIGHT of MENUFORWINDOW]
					 [RIGHT (create POSITION
							XCOORD ←(fetch RIGHT
								   of (WINDOWPROP WINDOW
										  (QUOTE REGION)))
							YCOORD ←(IDIFFERENCE
							  (fetch TOP of (WINDOWPROP WINDOW
										    (QUOTE REGION)))
							  (fetch IMAGEHEIGHT of MENUFORWINDOW]
					 (SHOULDNT)))
          (WINDOWPROP MENUWINDOW (QUOTE MOVEFN)
		      NIL)                                   (* Now the menu can be moved into the correct position)
          (MOVEW MENUWINDOW LOCATIONFORMENU)
          (WINDOWPROP MENUWINDOW (QUOTE MOVEFN)
		      (QUOTE DON'T])

(RESHAPEMENUEDWINDOW
  [LAMBDA (WINDOW)                                           (* rrb " 8-APR-83 16:36")

          (* This function takes care of size adjustments whenever the main window is reshaped. The size of the window is 
	  constrained so that the menu and titles will fit properly)


    (PROG (MENUWINDOW MENU POSITION WINDOWMENU)
          (SETQ WINDOWMENU (WINDOWPROP WINDOW (QUOTE WINDOWMENU)))
          (SETQ MENUWINDOW (WINDOWPROP WINDOW (QUOTE MENUWINDOW)))
          (WINDOWPROP MENUWINDOW (QUOTE CLOSEFN)
		      NIL)
          (SETQ POSITION (WINDOWPROP WINDOW (QUOTE MENUPOSITION)))
          (CLOSEW MENUWINDOW)                                (* Since the size of the window has changed it will be 
							     necessary to adjust the menu image if the menu is 
							     horizontal)
          (COND
	    ((MEMBER POSITION (QUOTE (TOP BOTTOM)))
	      (replace ITEMWIDTH of WINDOWMENU with (IQUOTIENT (fetch (REGION WIDTH)
								  of (WINDOWPROP WINDOW (QUOTE REGION)
										 ))
							       (fetch MENUCOLUMNS of WINDOWMENU)))
	      (UPDATE/MENU/IMAGE WINDOWMENU)))               (* Now the ne menu window can be constructed)
          (MAKEMENUWINDOW WINDOW (WINDOWPROP WINDOW (QUOTE WINDOWMENU))
			  POSITION])

(GETREGIONFORMENUEDWINDOW
  [LAMBDA (FIXEDPOINT MOVINGPOINT NEWREGIONFNARG)            (* SDG " 4-FEB-83 12:28")

          (* This function is called whenever a new region for the window is needed. It constrains the size of the window so
	  that the menu and/or titles will fit)


    (COND
      ((NULL MOVINGPOINT)                                    (* This is true only the first time the function is 
							     called)
	FIXEDPOINT)
      (T (PROG (#OFMENUITEMS MENUWIDTH XDELTA XADJ)

          (* The NEWREGIONFNARG can be either a window or a list consisting of the number of items in the menu and the 
	  minimum width of the window neede to hold the menu an titles)


	       (COND
		 [(WINDOWP NEWREGIONFNARG)
		   [SETQ #OFMENUITEMS (LENGTH (fetch ITEMS of (WINDOWPROP NEWREGIONFNARG
									  (QUOTE WINDOWMENU]
		   (SETQ MENUWIDTH (WINDOWPROP NEWREGIONFNARG (QUOTE MINWIDTH]
		 ((LISTP NEWREGIONFNARG)
		   (SETQ #OFMENUITEMS (CAR NEWREGIONFNARG))
		   (SETQ MENUWIDTH (CADR NEWREGIONFNARG)))
		 (T (SHOULDNT)))
	       (SETQ XDELTA (IDIFFERENCE (fetch (POSITION XCOORD) of MOVINGPOINT)
					 (fetch (POSITION XCOORD) of FIXEDPOINT)))
	       [SETQ MENUWIDTH (COND
		   ((LESSP XDELTA 0)
		     (SETQ XADJ -2)
		     (COND
		       ((LESSP (MINUS XDELTA)
			       MENUWIDTH)
			 (MINUS MENUWIDTH))
		       (T XDELTA)))
		   (T (SETQ XADJ 2)
		      (COND
			((LESSP XDELTA MENUWIDTH)
			  MENUWIDTH)
			(T XDELTA]
	       (SETQ MENUWIDTH (IPLUS (ITIMES (IQUOTIENT MENUWIDTH #OFMENUITEMS)
					      #OFMENUITEMS)
				      XADJ))                 (* The adjusted XCOORD can now be inserted)
	       (replace (POSITION XCOORD) of MOVINGPOINT with (IPLUS MENUWIDTH (fetch (POSITION
											XCOORD)
										  of FIXEDPOINT)))
	       (RETURN MOVINGPOINT])

(MAKEMENUWINDOW
  [LAMBDA (MAINWINDOW MENUFORWINDOW LOCATION)                (* SDG " 4-FEB-83 11:31")
                                                             (* edited: "26-JAN-83 12:09")
                                                             (* This function is called to create the menu window)
    (PROG (MENUWINDOW MENUPOSITION)                          (* First set up a position for the window based on the 
							     position of the main window and the relative location of
							     the menu)
          (SETQ MENUPOSITION (SELECTQ LOCATION
				      [TOP (create POSITION
						   XCOORD ←(fetch LEFT of (WINDOWPROP MAINWINDOW
										      (QUOTE REGION)))
						   YCOORD ←(fetch PTOP of (WINDOWPROP MAINWINDOW
										      (QUOTE REGION]
				      [BOTTOM (create POSITION
						      XCOORD ←(fetch LEFT of (WINDOWPROP
									       MAINWINDOW
									       (QUOTE REGION)))
						      YCOORD ←(IDIFFERENCE
							(fetch BOTTOM of (WINDOWPROP MAINWINDOW
										     (QUOTE REGION)))
							(fetch IMAGEHEIGHT of MENUFORWINDOW]
				      (RIGHT (create POSITION
						     XCOORD ←(fetch RIGHT of (WINDOWPROP
									       MAINWINDOW
									       (QUOTE REGION)))
						     YCOORD ←(IPLUS
						       (IDIFFERENCE (fetch TOP
								       of (WINDOWPROP MAINWINDOW
										      (QUOTE REGION)))
								    (fetch IMAGEHEIGHT of 
										    MENUFORWINDOW))
						       1)))
				      (LEFT (create POSITION
						    XCOORD ←(IDIFFERENCE (fetch LEFT
									    of (WINDOWPROP
										 MAINWINDOW
										 (QUOTE REGION)))
									 (fetch IMAGEWIDTH
									    of MENUFORWINDOW))
						    YCOORD ←(IPLUS (IDIFFERENCE
								     (fetch TOP
									of (WINDOWPROP MAINWINDOW
										       (QUOTE REGION))
									    )
								     (fetch IMAGEHEIGHT of 
										    MENUFORWINDOW))
								   1)))
				      (SHOULDNT)))           (* Now make the menu window)
          (SETQ MENUWINDOW (ADDMENU MENUFORWINDOW NIL MENUPOSITION))
                                                             (* Now save each other's window *)
          (WINDOWPROP MAINWINDOW (QUOTE WINDOWMENU)
		      MENUFORWINDOW)                         (* Other window properties are added so that operation 
							     selectable with the mouse like MOVE and RESHAPE will 
							     happen as expected)
          (WINDOWPROP MENUWINDOW (QUOTE MAINWINDOW)
		      MAINWINDOW)
          (WINDOWPROP MAINWINDOW (QUOTE MENUWINDOW)
		      MENUWINDOW)
          (WINDOWPROP MENUWINDOW (QUOTE TOTOPFN)
		      (FUNCTION MENUEDWINDOWTOTOPFN))
          (WINDOWPROP MENUWINDOW (QUOTE CLOSEFN)
		      (QUOTE DON'T))
          (WINDOWPROP MENUWINDOW (QUOTE OPENFN)
		      (QUOTE DON'T))
          (WINDOWPROP MENUWINDOW (QUOTE MOVEFN)
		      (QUOTE DON'T))

          (* This hack caues a right mouse button hit on this window to do what a right button hit on the main window would 
	  do)


          [WINDOWPROP MENUWINDOW (QUOTE RIGHTBUTTONFN)
		      (FUNCTION (LAMBDA (W)
			  (DOWINDOWCOM (WINDOWPROP W (QUOTE MAINWINDOW]
          (WINDOWPROP MAINWINDOW (QUOTE MENULENGTH)
		      (LENGTH (fetch (MENU ITEMS) of MENUFORWINDOW)))
          (WINDOWPROP MENUWINDOW (QUOTE RESHAPEFN)
		      (QUOTE DON'T))
          (RETURN MENUWINDOW])

(MENUEDWINDOWTOTOPFN
  [LAMBDA (WINDOW)                                           (* SDG " 4-FEB-83 10:14")
                                                             (* This function causes both the main and menu window to
							     be visible when either is selected)
    (PROG (W)
          [SETQ W (OR (WINDOWPROP WINDOW (QUOTE MAINWINDOW))
		      (WINDOWPROP WINDOW (QUOTE MENUWINDOW]
          (COND
	    ((WINDOWP W)
	      (TOTOPW W T])

(MENUEDWINDOWCLOSEFN
  [LAMBDA (MAINW)                                            (* rrb "23-SEP-83 16:14")
                                                             (* closefn for a menued window.
							     Closes the menu window and sets its own openfn to 
							     reestablish the link and open the menu.)
    (PROG [(MENUWINDOW (WINDOWPROP MAINW (QUOTE MENUWINDOW]

          (* remove the DON'T from the menu window so it will close. I'm not sure why the DON'T was there in the first 
	  place- rrb.)


          (WINDOWPROP MENUWINDOW (QUOTE CLOSEFN)
		      NIL)                                   (* break link back to this window.)
          (WINDOWPROP MENUWINDOW (QUOTE MAINWINDOW)
		      NIL)
          (CLOSEW MENUWINDOW])

(MENUEDWINDOWOPENFN
  [LAMBDA (MAINW)                                            (* M.Yonke "12-APR-83 14:44")
                                                             (* open function for menued windows.
							     Opens and reestablishes the link from the menu window to
							     the main window.)
    (PROG [(MENUWINDOW (WINDOWPROP MAINW (QUOTE MENUWINDOW]
          (WINDOWPROP MENUWINDOW (QUOTE OPENFN)
		      NIL)
          (OPENW MENUWINDOW)
          (WINDOWPROP MENUWINDOW (QUOTE OPENFN)
		      (QUOTE DON'T))
          (WINDOWPROP MENUWINDOW (QUOTE MAINWINDOW)
		      MAINW])
)
(PUTPROPS MENUEDWINDOW COPYRIGHT ("Xerox Corporation" 1983))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (1500 19937 (MAKEMENUEDWINDOW 1510 . 9167) (MOVEMENUWINDOW 9169 . 11424) (
RESHAPEMENUEDWINDOW 11426 . 12738) (GETREGIONFORMENUEDWINDOW 12740 . 14595) (MAKEMENUWINDOW 14597 . 
18069) (MENUEDWINDOWTOTOPFN 18071 . 18536) (MENUEDWINDOWCLOSEFN 18538 . 19313) (MENUEDWINDOWOPENFN 
19315 . 19935)))))
STOP