(FILECREATED " 9-Jan-85 20:49:01" {PHYLUM}<LFG>PARSER>MENUPATCH.;1 9002   )


(* Copyright (c) 1985 by Xerox Corporation. All rights reserved.)

(PRETTYCOMPRINT MENUPATCHCOMS)

(RPAQQ MENUPATCHCOMS ((FNS MENU.HANDLER)))
(DEFINEQ

(MENU.HANDLER
  [LAMBDA (MENU DSP KEEPCONTROLIFOUTFLG CHANGEOFFSETFLG NESTEDFLG)
                                                             (* rrb " 9-Jan-85 19:08")
                                                             (* handles details of watching mouse for menus.)
    (RESETLST (RESETSAVE NIL (LIST (QUOTE \SMASHMENUIMAGEONRESET)
				   MENU))
	      (PROG (ITEM SUBITEMS SUBMENURESULT OLDBOXX OLDBOXY BOXX BOXY HELDSTATE
			  (MOUSEDOWN (LASTMOUSESTATE (NOT UP)))
			  (MOVEDLEFT "NESTED")
			  (LASTBUTTONSTATE LASTMOUSEBUTTONS)
			  (MGRIDSPEC (fetch (MENU MENUGRID) of MENU))
			  (HOLDTIMER (SETUPTIMER MENUHELDWAIT))
			  (HELDFN (fetch (MENU WHENHELDFN) of MENU))
			  (NROWS (fetch (MENU MENUROWS) of MENU))
			  (NCOLUMNS (fetch (MENU MENUCOLUMNS) of MENU)))
		    (COND
		      ((AND MOUSEDOWN (STRICTLY/BETWEEN (SETQ BOXY (GRIDYCOORD (LASTMOUSEY DSP)
									       MGRIDSPEC))
							-1 NROWS)
			    (STRICTLY/BETWEEN (SETQ BOXX (GRIDXCOORD (LASTMOUSEX DSP)
								     MGRIDSPEC))
					      -1 NCOLUMNS))
                                                             (* make a special check for when the last state was 
							     down and save the information about which item that was
							     over.)
			(\INVERTITEM (SETQ OLDBOXX BOXX)
				     (SETQ OLDBOXY BOXY)
				     MENU DSP)))
		    (RETURN (COND
			      ([SETQ ITEM
				  (ERSETQ (until (COND
						   (MOUSEDOWN 
                                                             (* if mouse has been down, process it)
							      (MOUSESTATE UP))
						   ((MOUSESTATE (NOT UP))
                                                             (* mouse hasn't been down but just went down.)
						     [COND
						       ((AND (NULL KEEPCONTROLIFOUTFLG)
							     (LASTMOUSESTATE RIGHT))
							 (DOWINDOWCOM (WHICHW LASTMOUSEX LASTMOUSEY)))
						       (T (SETQ MOUSEDOWN T)
							  (COND
							    (OLDBOXX 
                                                             (* switch between boxing to flipping items.)
								     (\BOXITEM OLDBOXX OLDBOXY MENU 
									       DSP)
								     (\INVERTITEM OLDBOXX OLDBOXY 
										  MENU DSP]
						     NIL))
					     do (COND
						  [(AND (STRICTLY/BETWEEN (SETQ BOXY
									    (GRIDYCOORD (LASTMOUSEY
											  DSP)
											MGRIDSPEC))
									  -1 NROWS)
							(STRICTLY/BETWEEN (SETQ BOXX
									    (GRIDXCOORD (LASTMOUSEX
											  DSP)
											MGRIDSPEC))
									  -1 NCOLUMNS))
                                                             (* BOXX and BOXY hold the number of the box pointed 
							     at.)
						    (COND
						      ((OR (NEQ BOXX OLDBOXX)
							   (NEQ BOXY OLDBOXY))
                                                             (* selected item has changed.)
                                                             (* uninvert old item if there was one.)
							[COND
							  (OLDBOXX (COND
								     (MOUSEDOWN (\INVERTITEM OLDBOXX 
											  OLDBOXY 
											     MENU DSP)
										)
								     (T (\BOXITEM OLDBOXX OLDBOXY 
										  MENU DSP)))
								   (MENU.HELDSTATE.RESET OLDBOXX 
											 OLDBOXY))
							  (T (SETQ HOLDTIMER (SETUPTIMER MENUHELDWAIT 
											HOLDTIMER]
                                                             (* invert new item)
							(COND
							  (MOUSEDOWN (\INVERTITEM BOXX BOXY MENU DSP))
							  (T (\BOXITEM BOXX BOXY MENU DSP)))
							(SETQ OLDBOXX BOXX)
							(SETQ OLDBOXY BOXY))
						      ((AND HELDFN (NULL HELDSTATE)
							    (TIMEREXPIRED? HOLDTIMER))
                                                             (* same button in same region for MENUHELDWAIT 
							     milliseconds.)
							(APPLY* HELDFN (GETMENUITEM MENU OLDBOXX 
										    OLDBOXY)
								MENU
								(\FDECODE/BUTTON LASTBUTTONSTATE))
							(SETQ HELDSTATE T]
						  (T         (* cursor moved outside of the menu.)
						     (COND
						       (OLDBOXX (COND
								  ((AND (IGREATERP BOXX 0)
									(SETQ ITEM
									  (GETMENUITEM MENU OLDBOXX 
										       OLDBOXY))
									(SETQ SUBITEMS
									  (\MENUSUBITEMS MENU ITEM)))
                                                             (* There are subitems to be displayed)
								    (SETQ SUBMENURESULT
								      (MENU (NESTED.SUBMENU MENU 
											 SUBITEMS)
									    (NESTED.SUBMENU.POS
									      MENU ITEM DSP)
									    NIL T))
								    (COND
								      ((NEQ SUBMENURESULT MOVEDLEFT)
                                                             (* selected something from submenu)
									(COND
									  (MOUSEDOWN (\INVERTITEM
										       OLDBOXX 
										       OLDBOXY MENU 
										       DSP))
									  (T (\BOXITEM OLDBOXX 
										       OLDBOXY MENU 
										       DSP)))
									(MENU.HELDSTATE.RESET OLDBOXX 
											  OLDBOXY)
									(SETQ OLDBOXX)
									(GO OUT)))
								    (SETQ SUBMENURESULT NIL)))
								(COND
								  (MOUSEDOWN (\INVERTITEM OLDBOXX 
											  OLDBOXY 
											  MENU DSP))
								  (T (\BOXITEM OLDBOXX OLDBOXY MENU 
									       DSP)))
								(MENU.HELDSTATE.RESET OLDBOXX OLDBOXY)
								(SETQ OLDBOXX)))
                                                             (* OLDBOXX denotes item inverted.)
						     (COND
						       ((AND NESTEDFLG BOXX (IGREATERP 0 BOXX)
							     (ILESSP (LASTMOUSEX DSP)
								     0))

          (* make sure the mouse has moved all the way out past the left including its border and outline size.
	  We know it has to be a pop up menu that will have 0 as its left edge.)

                                                             (* if this is a nested call and the user moved to the 
							     left, return indication of this.)
							 (RETURN MOVEDLEFT))
						       ((NOT KEEPCONTROLIFOUTFLG)
							 (RETURN)))
						     (SETQ OLDBOXX)))
						(COND
						  ((NEQ LASTBUTTONSTATE (SETQ LASTBUTTONSTATE 
							  LASTMOUSEBUTTONS))
                                                             (* reset held timer)
						    (MENU.HELDSTATE.RESET OLDBOXX OLDBOXX)))
					     finally         (* turn off inverse image. and call whenunheldfn is 
							     necessary.)
						     OUT
						     (COND
						       (OLDBOXX (COND
								  (MOUSEDOWN (\INVERTITEM OLDBOXX 
											  OLDBOXY 
											  MENU DSP))
								  (T (\BOXITEM OLDBOXX OLDBOXY MENU 
									       DSP)))
								(MENU.HELDSTATE.RESET OLDBOXX OLDBOXY)
								))
                                                             (* if called for, change the menu offset so the menu 
							     will come up in the same place relative to the cursor 
							     next time.)
						     [COND
						       ((AND CHANGEOFFSETFLG OLDBOXX)
							 (SELECTQ (fetch (MENU CHANGEOFFSETFLG)
								     of MENU)
								  ((Y NIL))
								  (replace (POSITION XCOORD)
								     of (fetch (MENU MENUOFFSET)
									   of MENU)
								     with (LASTMOUSEX DSP)))
							 (SELECTQ (fetch (MENU CHANGEOFFSETFLG)
								     of MENU)
								  ((X NIL))
								  (replace (POSITION YCOORD)
								     of (fetch (MENU MENUOFFSET)
									   of MENU)
								     with (LASTMOUSEY DSP]
						     (RETURN (COND
							       (SUBMENURESULT)
							       (OLDBOXX (CONS (GETMENUITEM MENU 
											  OLDBOXX 
											  OLDBOXY)
									      (\FDECODE/BUTTON 
										  LASTBUTTONSTATE]
                                                             (* no error)
				(RETURN (CAR ITEM)))
			      (T                             (* user ↑E -
							     reset the menu selection.)

          (* note -
	  this doesn't protect against ↑D. I would suggest that something be put on the reset list to clear the menu image in 
	  the case of a ↑D.)


				 [COND
				   (OLDBOXX (COND
					      (MOUSEDOWN (\INVERTITEM OLDBOXX OLDBOXY MENU DSP))
					      (T (\BOXITEM OLDBOXX OLDBOXY MENU DSP]
				 (ERROR!])
)
(PUTPROPS MENUPATCH COPYRIGHT ("Xerox Corporation" 1985))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (230 8922 (MENU.HANDLER 240 . 8920)))))
STOP