(FILECREATED " 7-Dec-87 10:51:53" {QV}<NOTECARDS>1.3KNEXT>PMIPATCH069.;14 44352  

      changes to:  (VARS PMIPATCH069COMS NC.UnknownLinkIconAttachedBitMap)

      previous date: " 5-Nov-87 15:22:44" {QV}<NOTECARDS>1.3KNEXT>PMIPATCH069.;11)


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

(PRETTYCOMPRINT PMIPATCH069COMS)

(RPAQQ PMIPATCH069COMS ((* * pmi 12/7/87: This patch implements a change to link icon bitmaps for 
			     cross-file links. Instead of displaying the arrow cross-file link bitmap 
			     on the left side of the link icon, it has been moved to the right side 
			     of the link icon. The normal bitmap for the card type is now displayed 
			     on the left side, if the card type is known (the card's notefile is 
									      open.))
			  (* * Changed in NCUTILITIES)
			  (FNS NC.DrawInnerBox)
			  (* * Changed in NCCARDS)
			  (FNS NC.FetchLinkIconAttachedBitMap)
			  (* * New in NCCARDS)
			  (GLOBALVARS NC.UnknownLinkIconAttachedBitMap 
				      NC.UnknownLinkIconAttachedBitMaps)
			  (BITMAPS NC.UnknownLinkIconAttachedBitMap)
			  (VARS (NC.UnknownLinkIconAttachedBitMaps NC.UnknownLinkIconAttachedBitMap))
			  (* * Changed in NCLINKS)
			  (FNS NC.DrawLinkOrPointerIcon NC.ComputeLinkOrPointerImageBox 
			       NC.CreateLinkIconStrings)
			  (* * New for NCCROSSFILELINKS)
			  (* * Now a programmer can customize the icon which will appear on the right 
			     side of the link icon for cross-file links. The main hook is the 
			     property "AttachedBitMapFn" which should be placed on the card type's 
			     atom; which in this case is CrossFileLink. This function will be called 
			     in the display code by NC.FetchCrossFileLinkIconAttachedBitMap when a 
			     cross-file link is encountered.)
			  (FNS NC.FetchCrossFileLinkIconAttachedBitMap)
			  (* * An example is provided here which has a notefile-dependent function 
			     for computing the bitmap to be displayed. It stores each notefile with 
			     its list of different sized bitmaps in the hash array 
			     NC.AttachedBitMapsHashArray. Then function 
			     NC.FetchNoteFileAttachedBitmap computes and retrieves these bitmaps.)
			  (GLOBALVARS NC.AttachedBitMapsHashArray NC.NoteFileAttachedBitMap 
				      NC.NoteFileAttachedBitMapMask)
			  (VARS (NC.AttachedBitMapsHashArray))
			  (BITMAPS NC.NoteFileAttachedBitMap NC.NoteFileAttachedBitMapMask)
			  (FNS NC.CrossFileLinkAttachedBitMapFn NC.FetchNoteFileAttachedBitmap)
			  (* * The following expression establishes NC.CrossFileLinkAttachedBitMapFn 
			     as the AttachedBitMapFn for the link type CrossFileLink. 
			     NC.CrossFileLinkAttachedBitMapFn shades the cross-file link bitmap 
			     according to the notefile it points to.)
			  (* * (P (PUTPROP (QUOTE CrossFileLink)
					   (QUOTE AttachedBitMapFn)
					   (FUNCTION NC.CrossFileLinkAttachedBitMapFn))))))
(* * pmi 12/7/87: This patch implements a change to link icon bitmaps for cross-file links. 
Instead of displaying the arrow cross-file link bitmap on the left side of the link icon, it 
has been moved to the right side of the link icon. The normal bitmap for the card type is now 
displayed on the left side, if the card type is known (the card's notefile is open.))

(* * Changed in NCUTILITIES)

(DEFINEQ

(NC.DrawInnerBox
  (LAMBDA (Left Bottom Width Height LineWidth Operation ImageStream Dashing SkipLeftEdgeFlg 
		SkipRightEdgeFlg ScaledIconWidth ScaledIconHeight)
                                                             (* pmi: " 5-Nov-87 12:32")

          (* * Draw a box that fits exactly inside the region given. Omit the left edge if SkipLeftEdgeFlg non-nil.)



          (* * pmi & rht 2/10/87: Changed to not overwrite corners of the box.)



          (* * pmi 2/11/87: Updated for Multi-line link icons. If multi-line, does not draw box edge in upper left corner 
	  where bitmap is placed.)



          (* * rht 10/28/87: Added Dashing argument and passed to calls to DRAWLINE.)



          (* * pmi 11/3/87: Added SkipRightEdgeFlg for new cross-file link icons (with additional attached bitmap on right 
	  side of link icons.))


    (if (AND (GREATERP Width 0)
		 (GREATERP Height 0))
	then (LET ((TrueWidth (SUB1 Width))
		     (TrueHeight (SUB1 Height))
		     (HalfBorderWidth (FIX (TIMES LineWidth .5)))
		     (Offset (if (EVENP LineWidth)
				 then -1
			       else 0))
		     Right Top)
		    (SETQ Right (PLUS Left TrueWidth))
		    (SETQ Top (PLUS Bottom TrueHeight))
		    (LET ((CenterLeft (PLUS Left HalfBorderWidth Offset))
			  (CenterBottom (PLUS Bottom HalfBorderWidth))
			  (CenterRight (DIFFERENCE Right HalfBorderWidth))
			  (CenterTop (DIFFERENCE Top HalfBorderWidth))
			  (InnerBottom (PLUS Bottom LineWidth))
			  (InnerTop (DIFFERENCE Top LineWidth)))
		         (if (EVENP LineWidth)
			     then (SETQ CenterBottom (SUB1 CenterBottom)))

          (* * Draw the bottom line)


		         (DRAWLINE Left CenterBottom Right CenterBottom LineWidth Operation 
				     ImageStream NIL Dashing)

          (* * Draw the right line)


		         (if SkipRightEdgeFlg
			     then (if ScaledIconWidth
					then               (* Leave a break for the attached bitmap)
					       (DRAWLINE CenterRight InnerBottom CenterRight
							   (DIFFERENCE Top ScaledIconHeight)
							   LineWidth Operation ImageStream NIL 
							   Dashing)
					       (SETQ Right (DIFFERENCE Right ScaledIconWidth)))
			   else (DRAWLINE CenterRight InnerBottom CenterRight Top LineWidth 
					      Operation ImageStream NIL Dashing))

          (* * Draw the left line)


		         (if SkipLeftEdgeFlg
			     then (if ScaledIconWidth
					then               (* Leave a break for the attached bitmap)
					       (DRAWLINE CenterLeft (DIFFERENCE Top 
										 ScaledIconHeight)
							   CenterLeft InnerBottom LineWidth Operation 
							   ImageStream NIL Dashing)
					       (SETQ Left (PLUS Left ScaledIconWidth)))
			   else (DRAWLINE CenterLeft Top CenterLeft InnerBottom LineWidth 
					      Operation ImageStream NIL Dashing))

          (* * Draw the top line)


		         (DRAWLINE Left CenterTop Right CenterTop LineWidth Operation ImageStream 
				     NIL Dashing))))))
)
(* * Changed in NCCARDS)

(DEFINEQ

(NC.FetchLinkIconAttachedBitMap
  (LAMBDA (Card ScaledHeightToMatch Scale)                   (* pmi: " 5-Nov-87 12:56")

          (* * Return the default link icon attached bit map corresponding to Card)



          (* * fgh 2/5/86 First created.)



          (* * rht 5/10/86: Now takes special action if BitMapVal is a list. In that case, it should be an ordered prop list 
	  of heights and bitmaps. We take the one closest in height to HeightToMatch.)



          (* * rht 8/7/86: Now converts single bitmap to list of bitmaps of different heights if necessary.
	  Also now takes Scale argument.)



          (* * pmi 11/3/87: Now uses a default bitmap (?) if Card is NIL or its card type is undefined.)


    (DECLARE (GLOBALVARS NC.DefaultLinkIconAttachedBitMapHeights 
			     NC.UnknownLinkIconAttachedBitMaps))
    (LET (BitMapVal)
         (if (AND Card (SETQ BitMapVal (fetch (Card LinkIconAttachedBitMap) of Card)))
	     then (if (BITMAPP BitMapVal)
			then (replace (NoteCardType LinkIconAttachedBitMap)
				  of (NC.CardTypeRecord (NC.FetchType Card))
				  with (SETQ BitMapVal (NC.MakeTypeIconBitMapSet BitMapVal 
							  NC.DefaultLinkIconAttachedBitMapHeights))))
	   elseif (BITMAPP NC.UnknownLinkIconAttachedBitMaps)
	     then (SETQ NC.UnknownLinkIconAttachedBitMaps (SETQ BitMapVal (
			  NC.MakeTypeIconBitMapSet NC.UnknownLinkIconAttachedBitMaps 
						     NC.DefaultLinkIconAttachedBitMapHeights)))
	   else (SETQ BitMapVal NC.UnknownLinkIconAttachedBitMaps))
         (if (LISTP BitMapVal)
	     then (OR ScaledHeightToMatch (SETQ ScaledHeightToMatch 0))
		    (OR Scale (SETQ Scale 1))
		    (LET (BitMap)
		         (for X on BitMapVal by (CDDR X)
			    do (LET ((ScaledHeight (TIMES Scale (CAR X))))
				      (if (OR (NULL BitMap)
						  (LEQ ScaledHeight ScaledHeightToMatch))
					  then (SETQ BitMap (CADR X))
					elseif (GREATERP ScaledHeight ScaledHeightToMatch)
					  then (RETURN))))
		     BitMap)))))
)
(* * New in NCCARDS)

(DECLARE: DOEVAL@COMPILE DONTCOPY

(GLOBALVARS NC.UnknownLinkIconAttachedBitMap NC.UnknownLinkIconAttachedBitMaps)
)

(RPAQ NC.UnknownLinkIconAttachedBitMap (READBITMAP))
(21 18
"OOOOOH@@"
"H@@@@H@@"
"H@@@@H@@"
"H@OH@H@@"
"HAOL@H@@"
"HAHL@H@@"
"HAHL@H@@"
"H@AL@H@@"
"H@CH@H@@"
"H@G@@H@@"
"H@F@@H@@"
"H@F@@H@@"
"H@@@@H@@"
"H@F@@H@@"
"H@F@@H@@"
"H@@@@H@@"
"H@@@@H@@"
"OOOOOH@@")

(RPAQ NC.UnknownLinkIconAttachedBitMaps NC.UnknownLinkIconAttachedBitMap)
(* * Changed in NCLINKS)

(DEFINEQ

(NC.DrawLinkOrPointerIcon
  (LAMBDA (ImageStream ImageBox LinkIconString AttachBitmapFlg Card PointerStyleFlg)
                                                             (* pmi: " 5-Nov-87 12:27")

          (* * Draw the icon representing either a link or a pointer object.)



          (* * pmi 11/3/87: Added ability to print new cross-file link icon, with bitmap attached to right side of link 
	  icon.)


    (DECLARE (GLOBALVARS NC.LinkIconMultiLineMode NC.LinkIconMaxWidth NC.LinkIconSpaceInnerX 
			     NC.LinkIconSpaceOuterX NC.LinkIconSpaceInnerY NC.LinkIconSpaceOuterY 
			     NC.LinkIconSpaceInterLine NC.LinkIconBorderWidth 
			     NC.PointerIconDashingStyle))
    (PROG ((Scale (DSPSCALE NIL ImageStream))
	     (Font (DSPFONT NIL ImageStream))
	     Dashing FontHeight FontAscent FontDescent Left Bottom Top CrossFileLinkFlg 
	     CrossFileLinkDestCard ActualCard Icon SavedIcon CrossFileLinkIcon LinkIconStrings 
	     ApproxBoxWidth ApproxBoxHeight BoxWidth BoxHeight ScaledIconHeight ScaledIconWidth 
	     XPosition ScaledLinkIconMaxWidth ScaledBorderWidth ScaledSpaceInnerX ScaledSpaceOuterX 
	     ScaledSpaceInnerY ScaledSpaceOuterY ScaledSpaceInterLine HalfScaledSpaceInterLine 
	     BottomOfLine)

          (* * Make temporaries of scaled variables)


	    (SETQ ScaledLinkIconMaxWidth (TIMES Scale NC.LinkIconMaxWidth))
	    (SETQ ScaledBorderWidth (TIMES Scale NC.LinkIconBorderWidth))
	    (SETQ ScaledSpaceInnerX (TIMES Scale NC.LinkIconSpaceInnerX))
	    (SETQ ScaledSpaceOuterX (TIMES Scale NC.LinkIconSpaceOuterX))
	    (SETQ ScaledSpaceInnerY (TIMES Scale NC.LinkIconSpaceInnerY))
	    (SETQ ScaledSpaceOuterY (TIMES Scale NC.LinkIconSpaceOuterY))
	    (SETQ ScaledSpaceInterLine (TIMES Scale NC.LinkIconSpaceInterLine))
	    (SETQ HalfScaledSpaceInterLine (IQUOTIENT ScaledSpaceInterLine 2))
	    (SETQ FontHeight (FONTHEIGHT Font))

          (* * Indicate Pointer vs Link using dashing style.)


	    (if PointerStyleFlg
		then (SETQ Dashing NC.PointerIconDashingStyle))

          (* * Set up the icon, if displayed)


	    (if AttachBitmapFlg
		then 

          (* * Attached icon)



          (* * Check to see if this link points to a card in another notefile.)


		       (if (EQ (NCP.CardType Card)
				   (QUOTE CrossFileLink))
			   then (SETQ CrossFileLinkFlg T)
				  (if (SETQ CrossFileLinkDestCard (NCP.GetCrossFileLinkDestCard
					    Card NIL T))
				      then (SETQ ActualCard CrossFileLinkDestCard)
				    else (SETQ ActualCard NIL))
			 else (SETQ CrossFileLinkFlg NIL)
				(SETQ ActualCard Card))

          (* * Use an estimate of the width and height to tell if the box contains more than one line of text)


		       (if NC.LinkIconMultiLineMode
			   then 

          (* * Multi-line link icons are enabled)


				  (SETQ ApproxBoxWidth (PLUS ScaledSpaceOuterX ScaledBorderWidth 
								 ScaledSpaceInnerX (STRINGWIDTH
								   LinkIconString Font)
								 ScaledSpaceInnerX ScaledBorderWidth 
								 ScaledSpaceOuterX))
				  (SETQ ApproxBoxHeight (PLUS ScaledSpaceOuterY ScaledBorderWidth 
								  ScaledSpaceInnerY FontHeight 
								  ScaledSpaceInnerY ScaledBorderWidth 
								  ScaledSpaceOuterY))

          (* * Use the box height to determine if Multi-line or Single line. Calculate the correct bitmap.)


				  (SETQ BoxHeight (fetch (IMAGEBOX YSIZE) of ImageBox))
				  (if (GREATERP BoxHeight ApproxBoxHeight)
				      then                 (* Calculate height for Multi-line icon)
					     (SETQ ScaledIconHeight (PLUS ScaledBorderWidth 
									      ScaledSpaceInnerY 
									      FontHeight 
									 HalfScaledSpaceInterLine))
					     (SETQ Icon (NC.FetchLinkIconAttachedBitMap 
										       ActualCard 
										 ScaledIconHeight 
											    Scale))
					     (SETQ SavedIcon
					       (NC.FetchLinkIconAttachedBitMap ActualCard
										 (PLUS 
										ScaledBorderWidth 
										ScaledSpaceInnerY 
										       FontHeight 
										ScaledSpaceInnerY 
										ScaledBorderWidth)
										 Scale))
				    else                   (* Calculate height for Single line icon)
					   (SETQ ScaledIconHeight (PLUS ScaledBorderWidth 
									    ScaledSpaceInnerY 
									    FontHeight 
									    ScaledSpaceInnerY 
									    ScaledBorderWidth))
					   (SETQ Icon (NC.FetchLinkIconAttachedBitMap ActualCard 
										 ScaledIconHeight 
											  Scale))
					   (SETQ SavedIcon Icon))
				  (SETQ ScaledIconHeight (TIMES Scale (BITMAPHEIGHT Icon)))
				  (SETQ ScaledIconWidth (TIMES Scale (BITMAPWIDTH Icon)))
			 else 

          (* * Multi-line link icons are disabled)


				(SETQ ScaledIconHeight (PLUS ScaledBorderWidth ScaledSpaceInnerY 
								 FontHeight ScaledSpaceInnerY 
								 ScaledBorderWidth))
				(SETQ Icon (NC.FetchLinkIconAttachedBitMap ActualCard 
									       ScaledIconHeight Scale)
				  )
				(SETQ SavedIcon Icon)
				(SETQ ScaledIconHeight (TIMES Scale (BITMAPHEIGHT Icon)))
				(SETQ ScaledIconWidth (TIMES Scale (BITMAPWIDTH Icon))))
		       (SETQ CrossFileLinkIcon (if CrossFileLinkFlg
						     then (NC.FetchCrossFileLinkIconAttachedBitMap
							      Card CrossFileLinkDestCard 
							      ScaledIconHeight Scale)
						   else NIL))
	      else 

          (* * No attached icon)


		     (SETQ Icon NIL)
		     (SETQ SavedIcon Icon)
		     (SETQ CrossFileLinkIcon NIL)
		     (SETQ ScaledIconHeight 0)
		     (SETQ ScaledIconWidth 0))

          (* * Now determine the text to be printed)


	    (if (AND Icon (GREATERP (PLUS ScaledSpaceInnerX ScaledSpaceInnerX ScaledIconWidth
						  (if CrossFileLinkIcon
						      then ScaledIconWidth
						    else 0))
					  ScaledLinkIconMaxWidth))
		then 

          (* If the width of the icon plus the inner x's is greater than the ScaledLinkIconMaxWidth set by the user, set the 
	  icons and text to NIL)


		       (SETQ Icon NIL)
		       (SETQ SavedIcon Icon)
		       (SETQ CrossFileLinkIcon NIL)
		       (SETQ ScaledIconHeight 0)
		       (SETQ ScaledIconWidth 0)
		       (SETQ LinkIconStrings (LIST ""))
	      elseif (STREQUAL LinkIconString "")
		then                                       (* There is no text to print, so set it to the null 
							     string)
		       (SETQ LinkIconStrings (LIST ""))
	      else 

          (* * Have the text parsed into separate lines)


		     (SETQ LinkIconStrings (NC.CreateLinkIconStrings LinkIconString SavedIcon 
									 CrossFileLinkIcon 
									 ImageStream)))

          (* * Compute all the size values.)


	    (SETQ Bottom (PLUS (DIFFERENCE (DSPYPOSITION NIL ImageStream)
						 (fetch (IMAGEBOX YDESC) of ImageBox))
				   ScaledSpaceOuterY))
	    (SETQ BoxHeight (DIFFERENCE (fetch (IMAGEBOX YSIZE) of ImageBox)
					    (PLUS ScaledSpaceOuterY ScaledSpaceOuterY)))
	    (SETQ Top (PLUS Bottom BoxHeight))
	    (SETQ Left (PLUS (DSPXPOSITION NIL ImageStream)
				 ScaledSpaceOuterX))
	    (SETQ BoxWidth (DIFFERENCE (fetch (IMAGEBOX XSIZE) of ImageBox)
					   (PLUS ScaledSpaceOuterX ScaledSpaceOuterX)))

          (* * Display the icon, if possible)


	    (if (AND Icon (LEQ (PLUS ScaledIconWidth ScaledSpaceInnerX ScaledSpaceInnerX)
				     ScaledLinkIconMaxWidth))
		then 

          (* Put out the icon bitmap, but only if the width of the icon plus the inner x's does not exceed the 
	  LinkIconMaxWidth set by the user.)


		       (BITBLT Icon 0 0 ImageStream Left (DIFFERENCE Top ScaledIconHeight)) 

          (* DSPFONT is a kludge to get around bug in PRESS BITBLT which sets the width of a space char to NIL.
	  Bug reported as AR %#5630.0)


		       (DSPFONT Font ImageStream)
		       (if (ZEROP (NCHARS LinkIconString))
			   then                            (* Display the cross-file link icon, if necessary)
				  (if CrossFileLinkIcon
				      then (BITBLT CrossFileLinkIcon 0 0 ImageStream
						       (DIFFERENCE (PLUS Left BoxWidth)
								     ScaledIconWidth)
						       (DIFFERENCE Top ScaledIconHeight)))
                                                             (* Quit because just a typeicon)
				  (RETURN))
	      else                                         (* There isn't enough space for the icon, so set it to
							     NIL)
		     (SETQ Icon NIL)
		     (SETQ ScaledIconWidth 0))

          (* * Enter the appropriate text.)


	    (SETQ XPosition (PLUS Left (if Icon
					       then ScaledIconWidth
					     else ScaledBorderWidth)
				      ScaledSpaceInnerX))
	    (DSPXPOSITION XPosition ImageStream)
	    (SETQ FontDescent (FONTDESCENT Font))
	    (if LinkIconStrings
		then (if (GREATERP (LENGTH LinkIconStrings)
					 1)
			   then (SETQ FontAscent (FONTASCENT Font))
				  (SETQ BottomOfLine (DIFFERENCE Top (PLUS ScaledBorderWidth 
										ScaledSpaceInnerY 
										 FontAscent)))
				  (SETQ XPosition (PLUS Left ScaledSpaceInnerX ScaledBorderWidth))
				  (for String in LinkIconStrings
				     do (DSPYPOSITION BottomOfLine ImageStream)
					  (PRIN1 String ImageStream)
					  (SETQ BottomOfLine (DIFFERENCE BottomOfLine
									     (PLUS FontDescent 
									     ScaledSpaceInterLine 
										     FontAscent)))
					  (DSPXPOSITION XPosition ImageStream))

          (* * Draw the box for multiple lines of text.)


				  (NC.DrawInnerBox Left Bottom BoxWidth BoxHeight ScaledBorderWidth 
						     NIL ImageStream Dashing Icon CrossFileLinkIcon 
						     ScaledIconWidth ScaledIconHeight)
			 else (DSPYPOSITION (PLUS Bottom ScaledBorderWidth ScaledSpaceInnerY 
							FontDescent)
						ImageStream)
				(PRIN1 (CAR LinkIconStrings)
					 ImageStream)

          (* * Draw the box for a single line of text.)


				(NC.DrawInnerBox (PLUS Left ScaledIconWidth)
						   Bottom
						   (DIFFERENCE BoxWidth (if CrossFileLinkIcon
									      then (PLUS 
										  ScaledIconWidth 
										  ScaledIconWidth)
									    else ScaledIconWidth))
						   BoxHeight ScaledBorderWidth NIL ImageStream 
						   Dashing Icon CrossFileLinkIcon)))

          (* * Display the cross-file link icon, if necessary)


	    (if CrossFileLinkIcon
		then (BITBLT CrossFileLinkIcon 0 0 ImageStream (DIFFERENCE (PLUS Left 
											 BoxWidth)
										 ScaledIconWidth)
				 (DIFFERENCE Top ScaledIconHeight))))))

(NC.ComputeLinkOrPointerImageBox
  (LAMBDA (ImageStream LinkIconString AttachBitmapFlg Card RightMargin)
                                                             (* pmi: " 4-Nov-87 13:25")

          (* * Compute the size of the image box needed to print a link or pointer icon.)



          (* * pmi 11/3/87: Added ability to print new cross-file link icon, with bitmap attached to right side of link 
	  icon.)


    (DECLARE (GLOBALVARS NC.LinkIconMultiLineMode NC.LinkIconMaxWidth NC.LinkIconBorderWidth 
			     NC.LinkIconSpaceInnerX NC.LinkIconSpaceOuterX NC.LinkIconSpaceInnerY 
			     NC.LinkIconSpaceOuterY NC.LinkIconSpaceInterLine))
    (LET ((Scale (DSPSCALE NIL ImageStream))
	  (StringWidth 0)
	  (Font (DSPFONT NIL ImageStream))
	  CrossFileLinkFlg CrossFileLinkDestCard ActualCard Icon SavedIcon CrossFileLinkIcon 
	  FontHeight ApproxBoxWidth LinkIconStrings ScaledIconHeight ScaledIconWidth NumberOfLines 
	  XSize YSize ScaledLinkIconMaxWidth ScaledBorderWidth ScaledSpaceInnerX ScaledSpaceOuterX 
	  ScaledSpaceInnerY ScaledSpaceOuterY ScaledSpaceInterLine HalfScaledSpaceInterLine 
	  TotalEdgeSpaceY)
         (SETQ FontHeight (FONTHEIGHT Font))

          (* * Make temporaries of scaled vars.)


         (SETQ ScaledLinkIconMaxWidth (TIMES Scale NC.LinkIconMaxWidth))
         (SETQ ScaledBorderWidth (TIMES Scale NC.LinkIconBorderWidth))
         (SETQ ScaledSpaceInnerX (TIMES Scale NC.LinkIconSpaceInnerX))
         (SETQ ScaledSpaceOuterX (TIMES Scale NC.LinkIconSpaceOuterX))
         (SETQ ScaledSpaceInnerY (TIMES Scale NC.LinkIconSpaceInnerY))
         (SETQ ScaledSpaceOuterY (TIMES Scale NC.LinkIconSpaceOuterY))
         (SETQ ScaledSpaceInterLine (TIMES Scale NC.LinkIconSpaceInterLine))
         (SETQ HalfScaledSpaceInterLine (IQUOTIENT ScaledSpaceInterLine 2))

          (* *)


         (SETQ TotalEdgeSpaceY (PLUS ScaledBorderWidth ScaledSpaceOuterY ScaledSpaceInnerY))
         (SETQ YSize (PLUS TotalEdgeSpaceY TotalEdgeSpaceY FontHeight))

          (* * Set up the icon, if displayed)


         (if AttachBitmapFlg
	     then 

          (* * Attached icon)



          (* * Check to see if this link points to a card in another notefile.)


		    (if (EQ (NCP.CardType Card)
				(QUOTE CrossFileLink))
			then (SETQ CrossFileLinkFlg T)
			       (if (SETQ CrossFileLinkDestCard (NCP.GetCrossFileLinkDestCard
					 Card NIL T))
				   then (SETQ ActualCard CrossFileLinkDestCard)
				 else (SETQ ActualCard NIL))
		      else (SETQ CrossFileLinkFlg NIL)
			     (SETQ ActualCard Card))

          (* * Use an estimate of the width to tell if the box contains more than one line of text)


		    (if NC.LinkIconMultiLineMode
			then 

          (* * Multi-line link icons are enabled)


			       (SETQ ApproxBoxWidth (PLUS ScaledBorderWidth ScaledSpaceInnerX
							      (STRINGWIDTH LinkIconString Font)
							      ScaledSpaceInnerX ScaledBorderWidth))

          (* * The image box must be calculated)


			       (if (GREATERP ApproxBoxWidth ScaledLinkIconMaxWidth)
				   then                    (* Calculate Multi-line icon)
					  (SETQ ScaledIconHeight (PLUS ScaledBorderWidth 
									   ScaledSpaceInnerY 
									   FontHeight 
									 HalfScaledSpaceInterLine))
					  (SETQ Icon (NC.FetchLinkIconAttachedBitMap ActualCard 
										 ScaledIconHeight 
											 Scale))
					  (SETQ SavedIcon Icon)
					  (SETQ ScaledIconHeight (TIMES Scale (BITMAPHEIGHT
									      Icon)))
					  (SETQ ScaledIconWidth (TIMES Scale (BITMAPWIDTH
									     Icon)))
				 else                      (* Calculate Single line icon)
					(SETQ ScaledIconHeight (PLUS ScaledBorderWidth 
									 ScaledSpaceInnerY FontHeight 
									 ScaledSpaceInnerY 
									 ScaledBorderWidth))
					(SETQ Icon (NC.FetchLinkIconAttachedBitMap ActualCard 
										 ScaledIconHeight 
										       Scale))
					(SETQ SavedIcon Icon)
					(SETQ ScaledIconHeight (TIMES Scale (BITMAPHEIGHT
									    Icon)))
					(SETQ ScaledIconWidth (TIMES Scale (BITMAPWIDTH Icon))) 

          (* * Now see if total width, including the icon, will still fit if this is a Single line)


					(if (AND (NOT (STREQUAL LinkIconString ""))
						     (GREATERP (PLUS ApproxBoxWidth 
									 ScaledIconWidth
									 (if CrossFileLinkFlg
									     then ScaledIconWidth
									   else 0))
								 ScaledLinkIconMaxWidth))
					    then           (* Now it doesn't fit. Calculate Multi-line icon)
						   (SETQ ScaledIconHeight
						     (PLUS ScaledBorderWidth ScaledSpaceInnerY 
							     FontHeight HalfScaledSpaceInterLine))
						   (SETQ Icon (NC.FetchLinkIconAttachedBitMap
						       ActualCard ScaledIconHeight Scale))
						   (SETQ ScaledIconHeight (TIMES Scale
										     (BITMAPHEIGHT
										       Icon)))
						   (SETQ ScaledIconWidth (TIMES Scale
										    (BITMAPWIDTH
										      Icon)))))
		      else 

          (* * Multi-line link icons are disabled)


			     (SETQ ScaledIconHeight (PLUS ScaledBorderWidth ScaledSpaceInnerY 
							      FontHeight ScaledSpaceInnerY 
							      ScaledBorderWidth))
			     (SETQ Icon (NC.FetchLinkIconAttachedBitMap ActualCard 
									    ScaledIconHeight Scale))
			     (SETQ SavedIcon Icon)
			     (SETQ ScaledIconHeight (TIMES Scale (BITMAPHEIGHT Icon)))
			     (SETQ ScaledIconWidth (TIMES Scale (BITMAPWIDTH Icon))))
		    (SETQ CrossFileLinkIcon (if CrossFileLinkFlg
						  then (NC.FetchCrossFileLinkIconAttachedBitMap
							   Card CrossFileLinkDestCard 
							   ScaledIconHeight Scale)
						else NIL))
	   else 

          (* * No attached icon)


		  (SETQ Icon NIL)
		  (SETQ SavedIcon Icon)
		  (SETQ CrossFileLinkIcon NIL)
		  (SETQ ScaledIconHeight 0)
		  (SETQ ScaledIconWidth 0))

          (* * Now determine the actual size of the image box)


         (if (AND Icon (GREATERP (PLUS ScaledSpaceInnerX ScaledSpaceInnerX ScaledIconWidth
					       (if CrossFileLinkIcon
						   then ScaledIconWidth
						 else ScaledBorderWidth))
				       ScaledLinkIconMaxWidth))
	     then 

          (* If the width of the icon plus the width of the cross-file link icon (if any) plus the inner x's is greater than 
	  the ScaledLinkIconMaxWidth set by the user, set the box width to ScaledLinkIconMaxWidth plus the outer x's.)


		    (SETQ XSize (PLUS ScaledLinkIconMaxWidth ScaledSpaceOuterX ScaledSpaceOuterX))
	   elseif (ZEROP (NCHARS LinkIconString))
	     then (if Icon
			then 

          (* There is no text to print, so the box width is just the icon width plus the width of the cross-file link icon 
	  (if any) plus the outer x on each side)


			       (SETQ XSize (PLUS ScaledSpaceOuterX ScaledSpaceOuterX 
						     ScaledIconWidth (if CrossFileLinkIcon
									 then ScaledIconWidth
								       else ScaledBorderWidth)))
		      else 

          (* There is no text or Icon to print, so the box width is just the inner x, border width, and outer x on each side)


			     (SETQ XSize (PLUS ScaledSpaceInnerX ScaledSpaceInnerX 
						   ScaledBorderWidth ScaledBorderWidth 
						   ScaledSpaceOuterX ScaledSpaceOuterX)))
	   else                                            (* Have the text parsed into separate lines)
		  (SETQ LinkIconStrings (NC.CreateLinkIconStrings LinkIconString SavedIcon 
								      CrossFileLinkIcon ImageStream))
		  (if LinkIconStrings
		      then (SETQ NumberOfLines (LENGTH LinkIconStrings))
			     (if (GREATERP NumberOfLines 1)
				 then (SETQ StringWidth (PLUS (STRINGWIDTH (CAR 
										  LinkIconStrings)
										   Font)
								    ScaledIconWidth
								    (if CrossFileLinkIcon
									then ScaledIconWidth
								      else 0)))
                                                             (* Find the longest string for the width of the box)
					(for String in (CDR LinkIconStrings) bind 
										  PartStringWidth
					   when (GREATERP (SETQ PartStringWidth
								(STRINGWIDTH String Font))
							      StringWidth)
					   do (SETQ StringWidth PartStringWidth))
					(SETQ YSize (PLUS TotalEdgeSpaceY TotalEdgeSpaceY
							      (TIMES NumberOfLines FontHeight)
							      (TIMES (SUB1 NumberOfLines)
								       ScaledSpaceInterLine)))
			       else (SETQ StringWidth (PLUS (STRINGWIDTH (CAR 
										  LinkIconStrings)
										 Font)
								  ScaledIconWidth
								  (if CrossFileLinkIcon
								      then ScaledIconWidth
								    else 0))))
			     (SETQ XSize (MIN (PLUS StringWidth ScaledSpaceOuterX 
							  ScaledSpaceOuterX ScaledSpaceInnerX 
							  ScaledSpaceInnerX
							  (if Icon
							      then (if CrossFileLinkIcon
									 then 0
								       else ScaledBorderWidth)
							    else (PLUS ScaledBorderWidth 
									   ScaledBorderWidth)))
						  (PLUS ScaledLinkIconMaxWidth ScaledSpaceOuterX 
							  ScaledSpaceOuterX)))))
         (create IMAGEBOX
		   XSIZE ← XSize
		   YSIZE ← YSize
		   YDESC ←(COND
		     (RightMargin                            (* This is in a TEdittextstream)
				  (PLUS (FONTDESCENT Font)
					  TotalEdgeSpaceY))
		     (T 0))
		   XKERN ← 0))))

(NC.CreateLinkIconStrings
  (LAMBDA (LinkIconString Icon CrossFileLinkIcon ImageStream)
                                                             (* pmi: " 4-Nov-87 13:26")

          (* * pmi 2/9/87: First written to parse the text for a link icon into multiple lines)



          (* * rht 10/24/87: Removed initial "Link" arg. It was not being used.)



          (* * pmi 11/3/87: Added CrossFileLinkIcon argument for change to cross-file link icons (adding attached bitmap to 
	  right of link icon).)


    (DECLARE (GLOBALVARS NC.LinkIconMaxWidth NC.LinkIconMultiLineMode NC.LinkIconBorderWidth 
			     NC.LinkIconSpaceInnerX))
    (PROG ((Scale (DSPSCALE NIL ImageStream))
	     (LinkIconLines NIL)
	     (ThisString "")
	     RemainingLineWidth Font ScaledBorderWidth ScaledSpaceInnerX LineWidth StringLength 
	     CharsPtr NumberOfLines StringList String StringWidth Char CharWidth CurrentWidth EndPtr)
	    (SETQ Font (DSPFONT NIL ImageStream))

          (* * Make temporaries of scaled vars.)


	    (SETQ ScaledBorderWidth (TIMES Scale NC.LinkIconBorderWidth))
	    (SETQ ScaledSpaceInnerX (TIMES Scale NC.LinkIconSpaceInnerX))

          (* * Width of text in link icon)


	    (SETQ LineWidth (DIFFERENCE (TIMES Scale NC.LinkIconMaxWidth)
					    (PLUS ScaledSpaceInnerX ScaledSpaceInnerX 
						    ScaledBorderWidth ScaledBorderWidth)))

          (* * If there isn't even enough room for the bitmap, give up.)


	    (if Icon
		then (SETQ RemainingLineWidth (DIFFERENCE LineWidth
								(PLUS (if Icon
									    then
									     (DIFFERENCE
									       (BITMAPWIDTH Icon)
									       ScaledBorderWidth)
									  else 0)
									(if CrossFileLinkIcon
									    then
									     (DIFFERENCE
									       (BITMAPWIDTH Icon)
									       ScaledBorderWidth)
									  else 0))))
	      else (SETQ RemainingLineWidth LineWidth))

          (* * Turn the text into a string list of words and spaces)


	    (if NC.LinkIconMultiLineMode
		then 

          (* * Calculate multiple lines of text)


		       (SETQ StringList (NC.ParseString LinkIconString))
		       (SETQ String (CAR StringList))
		       (SETQ NumberOfLines 0) 

          (* * Determine the line breaks)


		       (while StringList
			  do (if (AND (STREQUAL (SUBSTRING String 1 1)
							(QUOTE " "))
					    (STREQUAL ThisString ""))
				   then 

          (* * The "word" is a space or spaces and we are at the beginning of the line. In this case we want to throw away 
	  the spaces.)


					  (SETQ StringList (CDR StringList))
					  (if StringList
					      then (SETQ String (CAR StringList)))
				 else (SETQ StringWidth (STRINGWIDTH String Font))
					(if (LESSP StringWidth RemainingLineWidth)
					    then 

          (* * The word or spaces will fit on the remainder of the line)


						   (SETQ ThisString (CONCAT ThisString String))
						   (SETQ RemainingLineWidth (DIFFERENCE 
									       RemainingLineWidth 
										      StringWidth))
						   (SETQ StringList (CDR StringList))
						   (if StringList
						       then (SETQ String (CAR StringList))
						     else (SETQ LinkIconLines (NCONC1 
										    LinkIconLines 
										       ThisString)))
					  elseif (EQ StringWidth RemainingLineWidth)
					    then 

          (* * The word or spaces will exactly fit on the remainder of the line)


						   (SETQ ThisString (CONCAT ThisString String))
						   (SETQ LinkIconLines (NCONC1 LinkIconLines 
										   ThisString))
						   (SETQ ThisString "")
						   (SETQ RemainingLineWidth LineWidth)
						   (SETQ NumberOfLines (ADD1 NumberOfLines))
						   (SETQ StringList (CDR StringList))
						   (if StringList
						       then (SETQ String (CAR StringList)))
					  elseif (STREQUAL ThisString "")
					    then 

          (* * We have a word that is too long for the line, and we are at the beginning of the line)


						   (SETQ CurrentWidth 0)
						   (SETQ EndPtr (for I from 1
								     to (NCHARS String)
								     do (SETQ Char
									    (SUBSTRING String I I))
									  (SETQ CurrentWidth
									    (PLUS CurrentWidth
										    (STRINGWIDTH
										      Char Font)))
									  (if (GREATERP 
										     CurrentWidth 
									       RemainingLineWidth)
									      then
									       (RETURN
										 (SUB1 I)))))
						   (if (EQ EndPtr 0)
						       then 

          (* * This character won't fit on this line, so give up)


							      (OR LinkIconLines (SETQ 
								      LinkIconLines (LIST "")))
							      (RETURN)
						     else (SETQ ThisString
							      (CONCAT ThisString
									(SUBSTRING String 1 EndPtr))
							      ))
						   (SETQ LinkIconLines (NCONC1 LinkIconLines 
										   ThisString))
						   (SETQ String (SUBSTRING String (ADD1 EndPtr))
						     )
						   (SETQ ThisString "")
						   (SETQ RemainingLineWidth LineWidth)
						   (SETQ NumberOfLines (ADD1 NumberOfLines))
					  elseif (STREQUAL (SUBSTRING String 1 1)
							       (QUOTE " "))
					    then 

          (* * We have spaces at the end of the line which can be thrown away)


						   (SETQ LinkIconLines (NCONC1 LinkIconLines 
										   ThisString))
						   (SETQ ThisString "")
						   (SETQ RemainingLineWidth LineWidth)
						   (SETQ NumberOfLines (ADD1 NumberOfLines))
						   (SETQ StringList (CDR StringList))
						   (if StringList
						       then (SETQ String (CAR StringList)))
					  else 

          (* * We have a word that won't fit on the remainder of the line, so we must start it on the next line)


						 (SETQ LinkIconLines (NCONC1 LinkIconLines 
										 ThisString))
						 (SETQ ThisString "")
						 (SETQ RemainingLineWidth LineWidth)
						 (SETQ NumberOfLines (ADD1 NumberOfLines)))))
	      elseif (LESSP (STRINGWIDTH LinkIconString Font)
				RemainingLineWidth)
		then 

          (* * Calculate single line of text. The string will fit as is)


		       (SETQ LinkIconLines (LIST LinkIconString))
	      else 

          (* * Calculate single line of text. We have to chop the string down to fit in one line)


		     (SETQ StringLength (NCHARS LinkIconString))
		     (SETQ CharsPtr 1)
		     (SETQ LinkIconLines (LIST (while (ILEQ CharsPtr StringLength)
						      do (if (LESSP (SETQ CharWidth
									    (STRINGWIDTH
									      (NTHCHAR 
										   LinkIconString 
											 CharsPtr)
									      Font))
									  RemainingLineWidth)
							       then (SETQ RemainingLineWidth
									(DIFFERENCE 
									       RemainingLineWidth 
										      CharWidth))
								      (SETQ CharsPtr (ADD1 
											 CharsPtr))
							     elseif (EQ CharsPtr 1)
							       then (RETURN "")
							     else (RETURN (SUBSTRING
										LinkIconString 1
										(SUB1 CharsPtr))))
						      finally (RETURN (SUBSTRING LinkIconString 
										       1
										       (SUB1 
											 CharsPtr)))))
		       ))
	    (RETURN LinkIconLines))))
)
(* * New for NCCROSSFILELINKS)

(* * Now a programmer can customize the icon which will appear on the right side of the link 
icon for cross-file links. The main hook is the property "AttachedBitMapFn" which should be 
placed on the card type's atom; which in this case is CrossFileLink. This function will be 
called in the display code by NC.FetchCrossFileLinkIconAttachedBitMap when a cross-file link is
 encountered.)

(DEFINEQ

(NC.FetchCrossFileLinkIconAttachedBitMap
  (LAMBDA (Card CrossFileLinkDestCard ScaledHeightToMatch Scale)
                                                             (* pmi: " 4-Nov-87 19:14")

          (* * Hook for user to calculate the bitmap to be displayed on the right side of a link icon if it is a cross-file 
	  link and it's attached bitmap is being displayed.)


    (LET ((AttachedBitMapFn (GETPROP (QUOTE CrossFileLink)
				       (QUOTE AttachedBitMapFn)))
	  BitMap)

          (* * If a special bitmap has been defined, return it. Otherwise, just return the standard cross-file link bitmap.)


         (if (AND AttachedBitMapFn (SETQ BitMap (APPLY* AttachedBitMapFn Card 
								CrossFileLinkDestCard 
								ScaledHeightToMatch Scale)))
	     then BitMap
	   else (NC.FetchLinkIconAttachedBitMap Card ScaledHeightToMatch Scale)))))
)
(* * An example is provided here which has a notefile-dependent function for computing the 
bitmap to be displayed. It stores each notefile with its list of different sized bitmaps in the
 hash array NC.AttachedBitMapsHashArray. Then function NC.FetchNoteFileAttachedBitmap computes 
and retrieves these bitmaps.)

(DECLARE: DOEVAL@COMPILE DONTCOPY

(GLOBALVARS NC.AttachedBitMapsHashArray NC.NoteFileAttachedBitMap NC.NoteFileAttachedBitMapMask)
)

(RPAQQ NC.AttachedBitMapsHashArray NIL)

(RPAQ NC.NoteFileAttachedBitMap (READBITMAP))
(21 18
"OOO@@@@@"
"@@AH@@@@"
"@@@L@@@@"
"@@@F@@@@"
"@@@C@@@@"
"@@@AH@@@"
"@@@@L@@@"
"@@@@F@@@"
"@@@@C@@@"
"@@@@C@@@"
"@@@@F@@@"
"@@@@L@@@"
"@@@AH@@@"
"@@@C@@@@"
"@@@F@@@@"
"@@@L@@@@"
"@@AH@@@@"
"OOO@@@@@")

(RPAQ NC.NoteFileAttachedBitMapMask (READBITMAP))
(21 18
"@@@OOH@@"
"@@@GOH@@"
"@@@COH@@"
"@@@AOH@@"
"@@@@OH@@"
"@@@@GH@@"
"@@@@CH@@"
"@@@@AH@@"
"@@@@@H@@"
"@@@@@H@@"
"@@@@AH@@"
"@@@@CH@@"
"@@@@GH@@"
"@@@@OH@@"
"@@@AOH@@"
"@@@COH@@"
"@@@GOH@@"
"@@@OOH@@")
(DEFINEQ

(NC.CrossFileLinkAttachedBitMapFn
  (LAMBDA (Card CrossFileLinkDestCard ScaledHeightToMatch Scale)
                                                             (* pmi: " 5-Nov-87 14:09")

          (* * Compute the proper bitmap for the cross-file link card Card. The bitmaps are stored in a hash array using 
	  notefile objects for the keys.)


    (DECLARE (GLOBALVARS NC.DefaultLinkIconAttachedBitMapHeights NC.AttachedBitMapsHashArray))
    (LET (NoteFile BitMapSample BitMapList BitMap ScaledHeight)
         (SETQ NoteFile (NC.NoteFileFromNoteFileUID (fetch (CrossFileLinkSubstance 
								     CrossFileLinkDestNoteFileUID)
							   of (NCP.CardSubstance Card))))

          (* * If we have not yet defined the hash array to hold the possible bitmaps, do so now.)


         (if (NOT (HARRAYP NC.AttachedBitMapsHashArray))
	     then (SETQ NC.AttachedBitMapsHashArray (HASHARRAY 100)))

          (* * If the bitmaps for this notefile have not already been defined, get a sample bitmap and create an array of 
	  bitmaps of different sizes.)


         (if (NOT (LISTP (SETQ BitMapList (GETHASH NoteFile NC.AttachedBitMapsHashArray))))
	     then (SETQ BitMapSample (NC.FetchNoteFileAttachedBitmap NoteFile (
								      NC.CoerceToInterestedWindow
									     Card)))
		    (SETQ BitMapList (NC.MakeTypeIconBitMapSet BitMapSample 
							  NC.DefaultLinkIconAttachedBitMapHeights))
		    (PUTHASH NoteFile BitMapList NC.AttachedBitMapsHashArray))

          (* * Pick the proper size bitmap from the list as determined by ScaledHeightToMatch.)


         (OR ScaledHeightToMatch (SETQ ScaledHeightToMatch 0))
         (OR Scale (SETQ Scale 1))
         (for X on BitMapList by (CDDR X)
	    do (SETQ ScaledHeight (TIMES Scale (CAR X)))
		 (if (OR (NULL BitMap)
			     (LEQ ScaledHeight ScaledHeightToMatch))
		     then (SETQ BitMap (CADR X))
		   elseif (GREATERP ScaledHeight ScaledHeightToMatch)
		     then (RETURN)))
     BitMap)))

(NC.FetchNoteFileAttachedBitmap
  (LAMBDA (NoteFile InterestedWindow)                        (* pmi: " 5-Nov-87 14:11")

          (* * One way to define the bitmaps for these cross-file link attached bitmaps -
	  let the user make up a shade.)


    (DECLARE (GLOBALVARS NC.NoteFileAttachedBitMap NC.NoteFileAttachedBitMapMask))
    (LET (NoteFileName BitMap BitMapShade)
         (SETQ NoteFileName (NCP.FileNameFromNoteFile NoteFile))
         (NCP.PrintMsg InterestedWindow T "Create a shade for notefile " NoteFileName)
         (SETQ BitMapShade (EDITSHADE))
         (NCP.ClearMsg InterestedWindow T)
         (SETQ BitMap (BITMAPCREATE (BITMAPWIDTH NC.NoteFileAttachedBitMap)
					(BITMAPHEIGHT NC.NoteFileAttachedBitMap)))
         (BITBLT NC.NoteFileAttachedBitMap NIL NIL BitMap NIL NIL NIL NIL (QUOTE INPUT)
		   (QUOTE PAINT))
         (BLTSHADE BitMapShade BitMap NIL NIL NIL NIL (QUOTE PAINT))
         (BITBLT NC.NoteFileAttachedBitMapMask NIL NIL BitMap NIL NIL NIL NIL (QUOTE INPUT)
		   (QUOTE ERASE))
     BitMap)))
)
(* * The following expression establishes NC.CrossFileLinkAttachedBitMapFn as the 
AttachedBitMapFn for the link type CrossFileLink. NC.CrossFileLinkAttachedBitMapFn shades the 
cross-file link bitmap according to the notefile it points to.)

(* * (P (PUTPROP (QUOTE CrossFileLink) (QUOTE AttachedBitMapFn) (FUNCTION 
NC.CrossFileLinkAttachedBitMapFn))))

(PUTPROPS PMIPATCH069 COPYRIGHT ("Xerox Corporation" 1987))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (3305 6488 (NC.DrawInnerBox 3315 . 6486)) (6520 8727 (NC.FetchLinkIconAttachedBitMap 
6530 . 8725)) (9242 38210 (NC.DrawLinkOrPointerIcon 9252 . 20462) (NC.ComputeLinkOrPointerImageBox 
20464 . 30418) (NC.CreateLinkIconStrings 30420 . 38208)) (38644 39569 (
NC.FetchCrossFileLinkIconAttachedBitMap 38654 . 39567)) (40579 43904 (NC.CrossFileLinkAttachedBitMapFn
 40589 . 42769) (NC.FetchNoteFileAttachedBitmap 42771 . 43902)))))
STOP