(FILECREATED "24-May-84 20:12:52" {DSK}TEDITSCREEN.;9 118165 

      changes to:  (FNS \DISPLAYLINE)

      previous date: "24-May-84 14:00:21" {DSK}TEDITSCREEN.;8)


(PRETTYCOMPRINT TEDITSCREENCOMS)

(RPAQQ TEDITSCREENCOMS ((RECORDS THISLINE LINEDESCRIPTOR LINECACHE)
	(FILES TEXTOFD TEDITLOOKS IMAGEOBJ)
	(FNS TEDIT.CR.UPDATESCREEN TEDIT.DELETELINE TEDIT.INSERT.DISPLAYTEXT 
	     TEDIT.INSERT.UPDATESCREEN TEDIT.UPDATE.SCREEN \BACKFORMAT \DISPLAYLINE \DOFORMATTING 
	     \FILLWINDOW \FIXDLINES \FIXILINES \FORMATLINE \PULLTEXT \PUSHTEXT \SHOWTEXT 
	     \TEDIT.ADJUST.LINES \TEDIT.BLTCHAR \TEDIT.CLOSEUPLINES \TEDIT.CREATE.LINECACHE 
	     \TEDIT.FIXCHANGEDPART \TEDIT.INSERTLINE \TEDIT.LINECACHE \TEDIT.MARK.LINES.DIRTY 
	     \TEDIT.PURGE.SPACES)))
[DECLARE: EVAL@COMPILE 

(DATATYPE THISLINE (                                         (* Cache for line-related character location info, for 
							     selection code to use)
		    DESC                                     (* Line descriptor for the line this describes now)
		    LEN                                      (* Length of the line in characters)
		    CHARS

          (* Array of character codes (or objects) on the line (charcode of 400 => dummy entry for looks change--go get next
	  entry in LOOKS))


		    WIDTHS                                   (* Array of each character's width in points)
		    LOOKS                                    (* Array of any looks changes within the line.
							     LOOKS (0) = starting character looks for the line)
		    )
		   LEN ← 0 CHARS ←(ARRAY 256 (QUOTE POINTER)
					 0 0)
		   WIDTHS ←(ARRAY 256 (QUOTE SMALLP)
				  0 0)
		   LOOKS ←(ARRAY 256 (QUOTE POINTER)
				 NIL 0))

(DATATYPE LINEDESCRIPTOR (YBOT                               (* Y value for the bottom of the line 
							     (below the descent))
			       YBASE                         (* Yvalue for the base line the characters sit on)
			       LEFTMARGIN                    (* Left margin, in screen points)
			       RIGHTMARGIN                   (* Right margin, in screen points)
			       LXLIM                         (* X value of right edge of rightmost character on the 
							     line (may exceed right margin, if char is a space.))
			       SPACELEFT                     (* Space left on the line, ignoring trailing blanks & 
							     CRs.)
			       FIRSTSPACE                    (* X offset of left edge of first space on the line 
							     (for line updating))
			       LHEIGHT                       (* Total height of hte line, Ascent+Descent.)
			       CHAR1                         (* CH# of the first character on the line.)
			       CHARLIM                       (* CH# of the last character on the line)
			       CHARTOP                       (* CH# of the character which forced the line break 
							     (may exceed CHARLIM))
			       DIRTY                         (* T if this line has changed since it was last 
							     formatted.)
			       NEW                           (* T if this line has not been displayed since being 
							     formatted last)
			       CR\END                        (* T if this line ends with a CR.)
			       ASCENT                        (* Ascent of the line above YBASE)
			       DESCENT                       (* How far line descends below YBASE)
			       NEXTLINE                      (* Next line chain pointer)
			       (PREVLINE FULLXPOINTER)       (* Previous line chain pointer)
			       DELETED

          (* T if this line has been completely deleted since it was last formatted or displayed. (Used by deletion routines
	  to detect garbage lines))


			       CACHE                         (* Bitmap cache for the line's image.)
			       LDOBJ                         (* The object which lies behind this line of text, for 
							     updating, etc.)
			       LHASPROT                      (* This line contains protected text.)
			       LFMTSPEC                      (* The format spec for this line's paragraph 
							     (eventually))
			       LTRUEASCENT                   (* The TRUE ascent for this line, unadjusted for line 
							     leading.)
			       LHASTABS

          (* If this line has a tab in it, this is the line-relative ch# of the final tab. This is to let us punt properly 
	  with tabs in a line.)


			       )
	  CHARLIM ← 1000000 NEXTLINE ← NIL PREVLINE ← NIL NEW ← T DIRTY ← NIL YBOT ← 0 YBASE ← 0 
	  LEFTMARGIN ← 0 DELETED ← NIL)

(DATATYPE LINECACHE (LCBITMAP                                (* The bitmap that will be used by this instance of the 
							     cache)
			      (LCNEXTCACHE FULLXPOINTER)     (* The next cache in the chain, for screen updates.)
			      ))
]
(/DECLAREDATATYPE (QUOTE THISLINE)
		  (QUOTE (POINTER POINTER POINTER POINTER POINTER)))
(/DECLAREDATATYPE (QUOTE LINEDESCRIPTOR)
		  (QUOTE (POINTER POINTER POINTER POINTER POINTER POINTER POINTER POINTER POINTER 
				  POINTER POINTER POINTER POINTER POINTER POINTER POINTER POINTER 
				  FULLXPOINTER POINTER POINTER POINTER POINTER POINTER POINTER 
				  POINTER)))
(/DECLAREDATATYPE (QUOTE LINECACHE)
		  (QUOTE (POINTER FULLXPOINTER)))
(FILESLOAD TEXTOFD TEDITLOOKS IMAGEOBJ)
(DEFINEQ

(TEDIT.CR.UPDATESCREEN
  [LAMBDA (CH# XPOINT TEXTOBJ SEL LINE BLANKSEEN CRSEEN DS CHWIDTH)
                                                             (* jds " 3-May-84 13:11")

          (* Update the edit window image after a CR is typed. Move any text after the CR to a new line, and push or pull 
	  text as needed.)


    (PROG ((LINES\DELETED NIL)
	   (LINES (fetch LINES of TEXTOBJ))
	   (DS (fetch DS of TEXTOBJ))
	   (WINDOW (fetch \WINDOW of TEXTOBJ))
	   (NEXTLINE (fetch NEXTLINE of LINE))
	   (PREVLINE (fetch PREVLINE of LINE))
	   (WWIDTH (fetch WRIGHT of TEXTOBJ))
	   NLINE1 LEN NL OLINE DX DY OCHLIM OXLIM OCR\END OLHEIGHT OLASCENT OLDESCENT NYBOT OFLOWFN)
          (COND
	    ([AND (NOT (fetch CR\END of PREVLINE))
		  (ILEQ (IDIFFERENCE XPOINT (fetch LEFTMARGIN of LINE))
			(IDIFFERENCE (fetch RIGHTMARGIN of PREVLINE)
				     (fetch LXLIM of PREVLINE]
                                                             (* This CR should push the start of the line back 
							     upward.)
	      (replace DIRTY of PREVLINE with T)
	      (TEDIT.UPDATE.SCREEN TEXTOBJ)
	      (\FIXSEL SEL TEXTOBJ)
	      (RETURN)))
          (SETQ NLINE1 (create LINEDESCRIPTOR using LINE))
          [replace ASCENT of NLINE1 with (IPLUS (fetch LTRUEASCENT of NLINE1)
						(fetch LINELEAD of (fetch LFMTSPEC of NLINE1))
						(fetch LEADBEFORE of (fetch LFMTSPEC of NLINE1]
          (replace LHEIGHT of NLINE1 with (IPLUS (fetch ASCENT of NLINE1)
						 (fetch DESCENT of NLINE1)))
          [replace LEFTMARGIN of NLINE1 with (IPLUS 8 (fetch 1STLEFTMAR of (fetch LFMTSPEC
									      of LINE]
          (SETQ CH# (IMIN CH# (fetch TEXTLEN of TEXTOBJ)))   (* Limit CH# to pre-existing text length)
          [SETQ NYBOT (replace YBOT of NLINE1 with (IDIFFERENCE (fetch YBOT of NLINE1)
								(fetch LHEIGHT of NLINE1]
                                                             (* New line's location)
          (COND
	    ((AND (ILEQ NYBOT (fetch WBOTTOM of TEXTOBJ))
		  (SETQ OFLOWFN (WINDOWPROP WINDOW (QUOTE TEDIT.OVERFLOWFN)))
		  (APPLY* OFLOWFN WINDOW TEXTOBJ))           (* This pushed a line off-screen, and there was an 
							     overflow function, and it handled the problem.
							     Just bail out of the update.)
	      (RETURN)))
          (SETQ OLHEIGHT (fetch LHEIGHT of LINE))

          (* SAVE THE VARIOUS COMPONENTS OF A LINE'S HEIGHT, SO WE CAN MOVE LINES UP AND DOWN IF THEY'VE CHANGED AS A RESULT
	  OF THE CR.)


          (SETQ OLASCENT (fetch ASCENT of LINE))
          (SETQ OLDESCENT (fetch DESCENT of LINE))
          (\FORMATLINE TEXTOBJ NIL (fetch CHAR1 of LINE)
		       LINE)
          (SETQ OXLIM (IPLUS (fetch LEFTMARGIN of NLINE1)
			     (IDIFFERENCE (fetch LXLIM of NLINE1)
					  XPOINT)))          (* XLIM of the new line, as just moved down -- not 
							     counting any text which may move upward to fill it out.)
          (SETQ OCHLIM (fetch CHARLIM of NLINE1))
          (SETQ OCR\END (fetch CR\END of NLINE1))
          (\FORMATLINE TEXTOBJ NIL (ADD1 CH#)
		       NLINE1)
          [AND NEXTLINE (\TEDIT.ADJUST.LINES TEXTOBJ NEXTLINE DS (fetch YBOT of LINE)
					     (IMINUS (fetch LHEIGHT of NLINE1]
                                                             (* Move the rest of the text down, to make room for the 
							     new line)
          (replace NEXTLINE of LINE with NLINE1)
          (replace PREVLINE of NLINE1 with LINE)
          (AND NEXTLINE (replace PREVLINE of NEXTLINE with NLINE1))
          (replace YBASE of NLINE1 with (IDIFFERENCE (fetch YBOT of LINE)
						     (fetch ASCENT of NLINE1)))
          (replace YBOT of NLINE1 with (IDIFFERENCE (fetch YBOT of LINE)
						    (fetch LHEIGHT of NLINE1)))
          (BITBLT DS XPOINT [IPLUS (fetch YBOT of LINE)
				   (IMAX 0 (IDIFFERENCE OLDESCENT (fetch DESCENT of NLINE1]
		  DS
		  (fetch LEFTMARGIN of NLINE1)
		  (IPLUS (fetch YBOT of NLINE1)
			 (IMAX 0 (IDIFFERENCE (fetch DESCENT of NLINE1)
					      OLDESCENT)))
		  (IDIFFERENCE (fetch RIGHTMARGIN of LINE)
			       XPOINT)
		  (IMIN (fetch LHEIGHT of NLINE1)
			OLHEIGHT)
		  (QUOTE INPUT)
		  (QUOTE REPLACE))                           (* Copy text after the CR to the new line)
          (BITBLT NIL 0 0 DS XPOINT (fetch YBOT of LINE)
		  (IDIFFERENCE (fetch RIGHTMARGIN of LINE)
			       XPOINT)
		  OLHEIGHT
		  (QUOTE TEXTURE)
		  (QUOTE REPLACE)
		  WHITESHADE)                                (* Blank the pre-existing line from where the CR went 
							     in)
          (BITBLT NIL 0 0 DS (IDIFFERENCE WWIDTH (fetch SPACELEFT of NLINE1))
		  (fetch YBOT of NLINE1)
		  (fetch WRIGHT of TEXTOBJ)
		  (fetch LHEIGHT of NLINE1)
		  (QUOTE TEXTURE)
		  (QUOTE REPLACE)
		  WHITESHADE)                                (* Blank the newly-created line to the right of the new 
							     text.)
          (\TEDIT.ADJUST.LINES TEXTOBJ LINE DS (fetch YBOT of (fetch PREVLINE of LINE))
			       (IDIFFERENCE OLASCENT (fetch ASCENT of LINE)))
                                                             (* Allow for changes in the height-above-baseline of the
							     line we just split)
          (\TEDIT.ADJUST.LINES TEXTOBJ NLINE1 DS (fetch YBOT of LINE)
			       (IDIFFERENCE OLDESCENT (fetch DESCENT of LINE)))
                                                             (* IF the original line's descent, or the new line's 
							     ascent changed, allow for them.)
          (replace YBOT of LINE with (IDIFFERENCE (fetch YBASE of LINE)
						  (fetch DESCENT of LINE)))
                                                             (* The first line never got its YBASE/YBOT fixed in 
							     sync, tho the others did by the line adjustment)
          (replace YBOT of NLINE1 with (IDIFFERENCE (fetch YBASE of NLINE1)
						    (fetch DESCENT of NLINE1)))
          [COND
	    ([OR (NOT (IEQP OXLIM (fetch LXLIM of NLINE1)))
		 (NOT (IEQP OCHLIM (fetch CHARLIM of NLINE1]
	      (SETQ DX (IDIFFERENCE (fetch LXLIM of NLINE1)
				    OXLIM))
	      (COND
		[(IGREATERP DX 0)
		  (while (IGREATERP DX 0)
		     do (COND
			  ((NOT NEXTLINE)
			    (\DISPLAYLINE TEXTOBJ NLINE1)
			    (SETQ DX 0))
			  ((fetch LHASTABS of NEXTLINE)
			    (TEDIT.UPDATE.SCREEN TEXTOBJ LINE)
			    (RETURN))
			  (T (COND
			       ((AND (IGREATERP (IDIFFERENCE (fetch LXLIM of NEXTLINE)
							     (fetch LEFTMARGIN of NEXTLINE))
						DX)
				     (IGREATERP (fetch YBOT of NEXTLINE)
						(fetch WBOTTOM of TEXTOBJ)))
                                                             (* Text moved up to fill the line out.
							     Make the change on-screen, too)
				 (BITBLT DS (fetch LEFTMARGIN of NEXTLINE)
					 (fetch YBOT of NEXTLINE)
					 DS OXLIM (fetch YBOT of NLINE1)
					 DX
					 (fetch LHEIGHT of NLINE1)
					 (QUOTE INPUT)
					 (QUOTE REPLACE))    (* Move the text image up)
                                                             (* Now cache the new line image for later use.)
				 (SETQ LINES\DELETED (OR (\PULLTEXT NEXTLINE DX
								    (ADD1 (fetch CHARLIM
									     of NLINE1))
								    TEXTOBJ)
							 LINES\DELETED))
                                                             (* Then propogate the text movement)
				 (SETQ DX 0))
			       ((ILEQ (fetch YBOT of NEXTLINE)
				      (fetch WBOTTOM of TEXTOBJ))
                                                             (* The next line lies below bottom of window--just 
							     Displayline, and blast the next line to hell.)
				 (\DISPLAYLINE TEXTOBJ NLINE1)
				 (replace NEXTLINE of NLINE1 with NIL)
				 (replace PREVLINE of NEXTLINE with NIL)
				 (SETQ DX 0))
			       (T                            (* NEXT NLINE1 WON'T FILL THIS ONE: GRAB IT, DECREMENT 
							     DX, BUMP LXLIM, MOVE ANY LOWER LINES UP OVER IT, AND TRY
							     AGAIN.)
				  (BITBLT DS (fetch LEFTMARGIN of NEXTLINE)
					  (fetch YBOT of NEXTLINE)
					  DS OXLIM (fetch YBOT of NLINE1)
					  (fetch LXLIM of NEXTLINE)
					  (fetch LHEIGHT of NEXTLINE)
					  (QUOTE INPUT)
					  (QUOTE REPLACE))
				  [SETQ DX (IDIFFERENCE DX (IDIFFERENCE (fetch LXLIM of NEXTLINE)
									(fetch LEFTMARGIN
									   of NEXTLINE]
				  [SETQ OXLIM (IPLUS OXLIM (IDIFFERENCE (fetch LXLIM of NEXTLINE)
									(fetch LEFTMARGIN
									   of NEXTLINE]
				  (SETQ NL (fetch NEXTLINE of NEXTLINE))
				  (TEDIT.DELETELINE NEXTLINE TEXTOBJ)
				  (SETQ NEXTLINE NL)
				  (SETQ LINES\DELETED T]
		((ILESSP DX 0)                               (* Not a problem if the CR overflew the line length 
							     limits)
		  ]
          (COND
	    (LINES\DELETED                                   (* A complete text line was deleted.
							     Fill the screen with more lines, to fit.)
			   (SETQ OLINE (\TEDIT.FIND.LAST.LINE TEXTOBJ LINES))
                                                             (* OLINE is now the last line displayed on the screen.)
			   (\FILLWINDOW (fetch YBOT of OLINE)
					OLINE TEXTOBJ)))
          (TEDIT.SET.SEL.LOOKS SEL (QUOTE NORMAL))
          (replace CHLIM of SEL with (fetch CH# of SEL))
          (replace L1 of SEL with NLINE1)
          (replace LN of SEL with NLINE1)
          (replace DCH of SEL with 0)
          (replace DX of SEL with 0)
          (replace POINT of SEL with (QUOTE LEFT))
          (replace SELKIND of SEL with (QUOTE CHAR))
          (replace X0 of SEL with (replace XLIM of SEL with (fetch LEFTMARGIN of NLINE1)))
          [SETQ NYBOT (replace Y0 of SEL with (replace YLIM of SEL with (fetch YBOT of NLINE1]
          (\SHOWSEL SEL NIL T)
          (COND
	    ((ILEQ NYBOT (fetch WBOTTOM of TEXTOBJ))         (* This pushed the caret off-screen.
							     Move it up.)
	      (replace EDITOPACTIVE of TEXTOBJ with NIL)
	      (SCROLLW WINDOW 0 (LLSH (fetch LHEIGHT of NLINE1)
				      1])

(TEDIT.DELETELINE
  [LAMBDA (LINE TEXTOBJ)                                     (* jds "18-MAR-83 15:53")
                                                             (* Remove a complete text line descriptor from the edit 
							     window, then move lower lines up over it.)
    (PROG ((PREV (fetch PREVLINE of LINE))
	   (NEXT (fetch NEXTLINE of LINE)))                  (* Fix up the line-descriptor chain to dis-include line)
          (COND
	    (PREV (replace NEXTLINE of PREV with NEXT)))
          (COND
	    (NEXT (replace PREVLINE of NEXT with PREV)))
          (\TEDIT.CLOSEUPLINES TEXTOBJ PREV NEXT)            (* And fix up the screen to cover the blank space.)
      ])

(TEDIT.INSERT.DISPLAYTEXT
  [LAMBDA (TEXTOBJ CH CHWIDTH LINE XPOINT DS SEL)            (* jds " 9-May-84 18:02")
                                                             (* This function does the actual displaying of typed-in 
							     text on the edit window.)
    (PROG ((LOOKS (\TEDIT.APPLY.STYLES (fetch CARETLOOKS of TEXTOBJ)
				       (fetch \INSERTPC of TEXTOBJ)
				       TEXTOBJ))
	   (TERMSA (fetch TXTTERMSA of TEXTOBJ))
	   DY FONT)
          (DSPFONT (SETQ FONT (fetch CLFONT of LOOKS))
		   DS)
          [COND
	    ((IGREATERP (FONTPROP (fetch CLFONT of LOOKS)
				  (QUOTE ASCENT))
			(fetch LTRUEASCENT of LINE))
	      [\TEDIT.ADJUST.LINES TEXTOBJ LINE DS (fetch YBOT of (fetch PREVLINE of LINE))
				   (IDIFFERENCE (fetch LTRUEASCENT of LINE)
						(FONTPROP (fetch CLFONT of LOOKS)
							  (QUOTE ASCENT]
	      (replace LTRUEASCENT of LINE with (FONTPROP (fetch CLFONT of LOOKS)
							  (QUOTE ASCENT]
          [COND
	    ((IGREATERP (FONTPROP (fetch CLFONT of LOOKS)
				  (QUOTE DESCENT))
			(fetch DESCENT of LINE))             (* If the caret's font will change the line's descent, 
							     adjust lower lines downward)
	      [\TEDIT.ADJUST.LINES TEXTOBJ (fetch NEXTLINE of LINE)
				   DS
				   (fetch YBOT of LINE)
				   (IDIFFERENCE (fetch DESCENT of LINE)
						(FONTPROP (fetch CLFONT of LOOKS)
							  (QUOTE DESCENT]
	      (replace DESCENT of LINE with (FONTPROP (fetch CLFONT of LOOKS)
						      (QUOTE DESCENT)))
	      (replace YBOT of LINE with (IDIFFERENCE (fetch YBASE of LINE)
						      (fetch DESCENT of LINE]
          (BITBLT DS XPOINT (fetch YBOT of LINE)
		  DS
		  (IPLUS XPOINT CHWIDTH)
		  (fetch YBOT of LINE)
		  (IDIFFERENCE (fetch RIGHTMARGIN of LINE)
			       XPOINT)
		  (fetch LHEIGHT of LINE)
		  (QUOTE INPUT)
		  (QUOTE REPLACE))                           (* Move the old text over)
          (BITBLT NIL 0 0 DS XPOINT (fetch YBOT of LINE)
		  CHWIDTH
		  (fetch LHEIGHT of LINE)
		  (QUOTE TEXTURE)
		  (QUOTE REPLACE)
		  WHITESHADE)                                (* Blank out the area we're going to write into)
          (MOVETO XPOINT (IPLUS (fetch YBASE of LINE)
				(OR (fetch CLOFFSET of LOOKS)
				    0))
		  DS)                                        (* Set the display stream position)
          [COND
	    [TERMSA                                          (* Special terminal table for controlling character 
							     display. Use it.)
		    (RESETLST (RESETSAVE \PRIMTERMSA TERMSA)
			      (replace (TEXTSTREAM REALFILE) of (fetch STREAMHINT of TEXTOBJ)
				 with DS)
			      (COND
				[(STRINGP CH)
				  (for CHAR instring CH
				     do (SELCHARQ CHAR
						  (TAB       (* Put down white)
						       (BITBLT NIL 0 0 DS XPOINT
							       (fetch YBOT of LINE)
							       36
							       (fetch LHEIGHT of LINE)
							       (QUOTE TEXTURE)
							       (QUOTE REPLACE)
							       WHITESHADE)
						       (RELMOVETO 36 0 DS))
						  (CR (BITBLT NIL 0 0 DS XPOINT
							      (fetch YBOT of LINE)
							      (IMAX 6 (CHARWIDTH CHAR FONT))
							      (fetch LHEIGHT of LINE)
							      (QUOTE TEXTURE)
							      (QUOTE REPLACE)
							      WHITESHADE))
						  (\DSPPRINTCHAR (fetch STREAMHINT of TEXTOBJ)
								 CHAR]
				(T (SELCHARQ CH
					     (TAB            (* Put down white)
						  (BITBLT NIL 0 0 DS XPOINT (fetch YBOT of LINE)
							  36
							  (fetch LHEIGHT of LINE)
							  (QUOTE TEXTURE)
							  (QUOTE REPLACE)
							  WHITESHADE)
						  (RELMOVETO 36 0 DS))
					     (CR (BITBLT NIL 0 0 DS XPOINT (fetch YBOT of LINE)
							 (IMAX 6 (CHARWIDTH CH FONT))
							 (fetch LHEIGHT of LINE)
							 (QUOTE TEXTURE)
							 (QUOTE REPLACE)
							 WHITESHADE))
					     (\DSPPRINTCHAR (fetch STREAMHINT of TEXTOBJ)
							    CH]
	    (T                                               (* No special handling; just use native character codes)
	       (COND
		 [(STRINGP CH)
		   (for CHAR instring CH do (SELCHARQ CHAR
						      (TAB 
                                                             (* Put down white)
							   (BITBLT NIL 0 0 DS XPOINT
								   (fetch YBOT of LINE)
								   36
								   (fetch LHEIGHT of LINE)
								   (QUOTE TEXTURE)
								   (QUOTE REPLACE)
								   WHITESHADE)
							   (RELMOVETO 36 0 DS))
						      (CR (BITBLT NIL 0 0 DS XPOINT
								  (fetch YBOT of LINE)
								  (IMAX 6 (CHARWIDTH CHAR FONT))
								  (fetch LHEIGHT of LINE)
								  (QUOTE TEXTURE)
								  (QUOTE REPLACE)
								  WHITESHADE))
						      (BLTCHAR CHAR DS]
		 (T (SELCHARQ CH
			      (TAB                           (* Put down white)
				   (BITBLT NIL 0 0 DS XPOINT (fetch YBOT of LINE)
					   36
					   (fetch LHEIGHT of LINE)
					   (QUOTE TEXTURE)
					   (QUOTE REPLACE)
					   WHITESHADE)
				   (RELMOVETO 36 0 DS))
			      (CR                            (* Blank out the CR's width.)
				  (BITBLT NIL 0 0 DS XPOINT (fetch YBOT of LINE)
					  (IMAX 6 (CHARWIDTH CH FONT))
					  (fetch LHEIGHT of LINE)
					  (QUOTE TEXTURE)
					  (QUOTE REPLACE)
					  WHITESHADE))
			      (BLTCHAR CH DS]
          (BITBLT NIL 0 0 DS (fetch LXLIM of LINE)
		  (fetch YBOT of LINE)
		  (fetch WRIGHT of TEXTOBJ)
		  (fetch LHEIGHT of LINE)
		  (QUOTE TEXTURE)
		  (QUOTE REPLACE)
		  WHITESHADE)                                (* Clear after EOL)
          (TEDIT.MODIFYLOOKS LINE XPOINT DS LOOKS (fetch YBASE of LINE))
                                                             (* Do underlining, strike-out, etc.)
      ])

(TEDIT.INSERT.UPDATESCREEN
  [LAMBDA (CH CH# CHARS XPOINT TEXTOBJ SEL LINE OTEXTLEN BLANKSEEN CRSEEN DS)
                                                             (* jds "21-Apr-84 15:08")
                                                             (* Update the edit window after an insertion)
    (PROG ((THISLINE (fetch THISLINE of TEXTOBJ))
	   (WINDOW (fetch \WINDOW of TEXTOBJ))
	   EOLFLAG CHORIG CHWIDTH OXLIM OCHLIM OCR\END PREVSPACE FIXEDLINE NEXTLINE LINES NEWLINEFLG 
	   DX PREVLINE SAVEWIDTH OFLOWFN OLHEIGHT DY TABSEEN IMAGECACHE)
          (replace CH# of SEL with (IPLUS CHARS CH#))        (* These must be here, since SELs are valid even without
							     a window.)
          (replace CHLIM of SEL with (fetch CH# of SEL))
          (replace POINT of SEL with (QUOTE LEFT))
          (replace DCH of SEL with 0)
          (replace SELKIND of SEL with (QUOTE CHAR))
          (COND
	    ((NOT WINDOW)                                    (* If this textobj has no window to update, don't 
							     bother)
	      (RETURN))
	    ((LISTP WINDOW)                                  (* If there are multiple panes, do it the hard way for 
							     now.)
	      (TEDIT.UPDATE.SCREEN TEXTOBJ)
	      (\FIXSEL SEL TEXTOBJ))
	    (LINE                                            (* We're typing into a pre-existing line)
		  [COND
		    [(STRINGP CH)                            (* Width of the inserted text, if it's > 1 character 
							     long)
		      (SETQ CHWIDTH (TEDIT.STRINGWIDTH CH (fetch CLFONT
							     of (\TEDIT.APPLY.STYLES (fetch 
										       CARETLOOKS
											of TEXTOBJ)
										     (fetch \INSERTPC
											of TEXTOBJ)
										     TEXTOBJ))
						       (fetch TXTTERMSA of TEXTOBJ)))
		      (for CHAR instring CH do (COND
						 ((EQP CHAR (CHARCODE TAB))
						   (SETQ TABSEEN T)
						   (RETURN]
		    (T                                       (* Width for a single character)
		       (SETQ CHWIDTH (SELCHARQ CH
					       (TAB          (* Make all tabs 1/2 inch for the time being.)
						    (SETQ TABSEEN T)
						    36)
					       (TEDIT.CHARWIDTH CH
								(fetch CLFONT
								   of (\TEDIT.APPLY.STYLES
									(fetch CARETLOOKS
									   of TEXTOBJ)
									(fetch \INSERTPC
									   of TEXTOBJ)
									TEXTOBJ))
								(fetch TXTTERMSA of TEXTOBJ]
		  [SETQ EOLFLAG (OR (IGREATERP CH# OTEXTLEN)
				    (IGREATERP CH# (fetch CHARLIM of LINE]
                                                             (* We're inserting at the end of a line.)
		  (replace DX of SEL with 0)
		  (replace X0 of SEL with (IPLUS CHWIDTH XPOINT))
		  (replace XLIM of SEL with (IPLUS CHWIDTH XPOINT))
		  (replace L1 of SEL with LINE)
		  (replace LN of SEL with LINE)
		  (replace Y0 of SEL with (fetch YBOT of LINE))
		  (replace YLIM of SEL with (fetch YBOT of LINE))
		  (SETQ OXLIM (fetch LXLIM of LINE))         (* Where the line used to end.)
		  (SETQ OCHLIM (fetch CHARLIM of LINE))
		  (SETQ OLHEIGHT (fetch LHEIGHT of LINE))
		  (SETQ OCR\END (AND (fetch CR\END of LINE)
				     (NOT EOLFLAG)))         (* Remember whether or not this line used to end with a 
							     CR)
		  [SETQ BLANKSEEN (AND BLANKSEEN (SETQ PREVLINE (fetch PREVLINE of LINE))
				       (NOT (fetch CR\END of PREVLINE))
				       (ILEQ CH# (fetch CHARTOP of PREVLINE]
		  (COND
		    ((OR TABSEEN (fetch LHASTABS of LINE)
			 (NEQ (fetch QUAD of (fetch LFMTSPEC of LINE))
			      (QUOTE LEFT))
			 (LISTP WINDOW))                     (* It's anything other than left-ragged formatting.
							     Must do redisplay the hard way.)
		      (TEDIT.UPDATE.SCREEN TEXTOBJ)
		      (\FIXSEL SEL TEXTOBJ))
		    ((AND CRSEEN (NOT BLANKSEEN)
			  (OR (NOT (STRINGP CH))
			      (IEQP 1 CHARS)))               (* Only a CR in this stash.)
		      (TEDIT.CR.UPDATESCREEN CH# XPOINT TEXTOBJ SEL LINE BLANKSEEN CRSEEN DS CHWIDTH))
		    [[OR BLANKSEEN CRSEEN (AND EOLFLAG (OR (ILEQ CH# OTEXTLEN)
							   (fetch CR\END of LINE)))
			 (IGREATERP CHWIDTH (IMIN (IDIFFERENCE (fetch RIGHTMARGIN of LINE)
							       XPOINT)
						  (fetch SPACELEFT of LINE]
                                                             (* MOVE SOME TEXT TO THE NEXT LINE, CREATING IT IF NEED 
							     BE.)
		      (COND
			(BLANKSEEN                           (* BlankSeen => back up to previous line, and try a pull
							     of text.)
				   (TEDIT.UPDATE.SCREEN TEXTOBJ)
				   (SETQ BLANKSEEN T)
				   (\FIXSEL SEL TEXTOBJ)
				   (\SHOWSEL SEL NIL T))
			(T (\FORMATLINE TEXTOBJ NIL (fetch CHAR1 of LINE)
					LINE)
			   (\TEDIT.ADJUST.LINES TEXTOBJ (fetch NEXTLINE of LINE)
						WINDOW
						(fetch YBOT of LINE)
						(IDIFFERENCE OLHEIGHT (fetch LHEIGHT of LINE)))
			   (COND
			     ([OR (NOT (IEQP (IPLUS CHWIDTH OXLIM)
					     (fetch LXLIM of LINE)))
				  (NOT (IEQP (IPLUS CHARS OCHLIM)
					     (fetch CHARLIM of LINE]
                                                             (* The length of the line changed;
							     we have to move some text.)
                                                             (* THIS USED TO REQUIRE THAT CHARLIM OF LINE BE < 
							     TEXTLEN. 9/27/83. WHY?)
			       (COND
				 ((OR (IGREATERP XPOINT (fetch LXLIM of LINE))
				      (IGREATERP (IPLUS XPOINT CHWIDTH)
						 (fetch LXLIM of LINE)))
                                                             (* The insertion point moved to the next line.)
				   (replace DIRTY of LINE with T)
				   (replace CHARLIM of LINE with OCHLIM)
				   (TEDIT.UPDATE.SCREEN TEXTOBJ)
				   (SETQ BLANKSEEN T)
				   (\FIXSEL SEL TEXTOBJ))
				 (T (SETQ DX (IDIFFERENCE (IPLUS OXLIM CHWIDTH)
							  (fetch LXLIM of LINE)))
				    (replace DIRTY of LINE with NIL)
				    (COND
				      ((fetch NEXTLINE of LINE)
					[SETQ SAVEWIDTH (IMIN DX (IMAX 0
								       (IDIFFERENCE (fetch 
										      RIGHTMARGIN
										       of LINE)
										    (IDIFFERENCE
										      OXLIM DX]
                                                             (* Remember how much was REALLY saved in the SAVEBM)
					(SETQ IMAGECACHE (\TEDIT.LINECACHE (fetch LINECACHE
									      of TEXTOBJ)
									   SAVEWIDTH
									   (fetch LHEIGHT
									      of LINE)))
					(\TEDIT.CHECK (fetch TCUP of (fetch CARET of TEXTOBJ)))
                                                             (* The caret must be up when the line cache is updated.)
					(BITBLT WINDOW (IDIFFERENCE OXLIM DX)
						(fetch YBOT of LINE)
						IMAGECACHE 0 0 DX (fetch LHEIGHT of LINE)
						(QUOTE INPUT)
						(QUOTE REPLACE))
					(TEDIT.INSERT.DISPLAYTEXT TEXTOBJ CH CHWIDTH LINE XPOINT DS 
								  SEL)
					(\PUSHTEXT (fetch NEXTLINE of LINE)
						   (IDIFFERENCE OXLIM DX)
						   (fetch YBOT of LINE)
						   DX
						   (ADD1 (fetch CHARLIM of LINE))
						   TEXTOBJ OCR\END (fetch LINECACHE of TEXTOBJ)
						   SAVEWIDTH))
				      (T (TEDIT.INSERT.DISPLAYTEXT TEXTOBJ CH CHWIDTH LINE XPOINT DS 
								   SEL)
					 [replace NEXTLINE of LINE
					    with (\FORMATLINE TEXTOBJ NIL
							      (ADD1 (fetch CHARLIM of LINE]
					 (SETQ NEWLINEFLG T)
					 (replace PREVLINE of (fetch NEXTLINE of LINE) with LINE)
					 (COND
					   ((IGREATERP (fetch YBOT of LINE)
						       (IPLUS (fetch LHEIGHT
								 of (fetch NEXTLINE of LINE))
							      (fetch WBOTTOM of TEXTOBJ)))
					     [replace YBOT of (fetch NEXTLINE of LINE)
						with (IDIFFERENCE (fetch YBOT of LINE)
								  (fetch LHEIGHT
								     of (fetch NEXTLINE of LINE]
					     [replace YBASE of (fetch NEXTLINE of LINE)
						with (IPLUS (fetch YBOT of (fetch NEXTLINE
									      of LINE))
							    (fetch DESCENT
							       of (fetch NEXTLINE of LINE]
					     (\DISPLAYLINE TEXTOBJ (fetch NEXTLINE of LINE)))
					   (T                (* A Line fell off the bottom.
							     Remember for potential later handling)
					      (AND (SETQ OFLOWFN (WINDOWPROP WINDOW (QUOTE 
										 TEDIT.OVERFLOWFN)))
						   (APPLY* OFLOWFN WINDOW TEXTOBJ]
		    (T                                       (* This character didn't cause any line overflow.
							     Adjust the line length and display the character)
		       (replace SPACELEFT of LINE with (IDIFFERENCE (fetch SPACELEFT of LINE)
								    CHWIDTH))

          (* This is conservative--since SPACELEFT isn't really reduced by spaces at the end of the line, this may cause 
	  line reformatting before it's really needed.)


		       (replace LXLIM of LINE with (IPLUS (fetch LXLIM of LINE)
							  CHWIDTH))
		       (replace DESC of THISLINE with NIL)
		       (TEDIT.INSERT.DISPLAYTEXT TEXTOBJ CH CHWIDTH LINE XPOINT DS SEL)))
		  (\SHOWSEL SEL NIL T))
	    (T                                               (* There isn't really a line to type into yet.
							     Let's create it.)
	       (SETQ LINE LINES)
	       (replace NEXTLINE of LINE with (SETQ NEXTLINE (\FORMATLINE TEXTOBJ NIL 1)))
                                                             (* Create the new line)
	       (replace PREVLINE of NEXTLINE with LINE)
	       (replace YBOT of NEXTLINE with (IDIFFERENCE (fetch YBOT of LINE)
							   (fetch LHEIGHT of NEXTLINE)))
                                                             (* Find where it goes on the screen)
	       (replace YBASE of NEXTLINE with (IPLUS (fetch YBOT of NEXTLINE)
						      (fetch DESCENT of NEXTLINE)))
	       (\DISPLAYLINE TEXTOBJ NEXTLINE)               (* Display it and cache the image)
	       (replace L1 of SEL with (replace LN of SEL with NEXTLINE))
	       (\FIXSEL SEL TEXTOBJ)
	       (\SHOWSEL SEL NIL T)))
          (\COPYSEL SEL TEDIT.SELECTION)
          (COND
	    ((ILEQ (SELECTQ (fetch POINT of SEL)
			    (LEFT (fetch Y0 of SEL))
			    (RIGHT (fetch YLIM of SEL))
			    0)
		   (fetch WBOTTOM of TEXTOBJ))               (* The caret just went off-screen.
							     Move it up some.)
	      (replace EDITOPACTIVE of TEXTOBJ with NIL)
	      (\TEDIT.SCROLLFN (fetch SELWINDOW of TEXTOBJ)
			       0
			       (LLSH (fetch LHEIGHT of (SELECTQ (fetch POINT of SEL)
								(LEFT (fetch L1 of SEL))
								(RIGHT (fetch LN of SEL))
								(SHOULDNT)))
				     1)))
	    (T (\TEDIT.SET.WINDOW.EXTENT TEXTOBJ WINDOW])

(TEDIT.UPDATE.SCREEN
  [LAMBDA (TEXTOBJ STARTINGLINE)                             (* jds "15-Mar-84 13:59")
                                                             (* Update the screen, as needed to fix up "dirty" 
							     lines.)
    (SETQ TEXTOBJ (TEXTOBJ TEXTOBJ))
    (for WW inside (fetch \WINDOW of TEXTOBJ) do (PROG ((NLINE (\TEDIT.FIXCHANGEDPART TEXTOBJ 
										     STARTINGLINE WW))
							)
						       (AND NLINE (\FILLWINDOW (fetch YBOT
										  of NLINE)
									       NLINE TEXTOBJ NIL WW])

(\BACKFORMAT
  [LAMBDA (LINES TEXTOBJ)                                    (* jds "22-OCT-83 17:27")
                                                             (* Move back to the next preceding CR 
							     (to guarantee a line break), then format lines to reach 
							     where we are now.)
    (PROG ((LINE1 (fetch NEXTLINE of LINES))
	   (WHEIGHT (fetch WTOP of TEXTOBJ))
	   CH1 CHNO CH NLINE)
          [SETQ CH1 (COND
	      (LINE1 (fetch CHAR1 of LINE1))
	      (T (fetch TEXTLEN of TEXTOBJ]
          (COND
	    ((ILEQ CH1 1)                                    (* No more lines can be formatted -- we're at the front 
							     of the file.)
	      (RETURN LINES))
	    (T                                               (* There is more to do.)
	       (\SETUPGETCH (IDIFFERENCE CH1 1)
			    TEXTOBJ)
	       [for old CHNO from (IDIFFERENCE CH1 2) to 1 by -1
		  do (SETQ CH (\GETCHB TEXTOBJ))
		     (COND
		       ((EQ CH (CHARCODE CR))
			 (RETURN]
	       (SETQ CHNO (IMAX (ADD1 CHNO)
				1))
	       [while (ILEQ CHNO (SUB1 CH1))
		  do (SETQ NLINE (\FORMATLINE TEXTOBJ NIL CHNO))
		     (replace YBOT of NLINE with WHEIGHT)
		     (replace YBASE of NLINE with WHEIGHT)
		     (replace PREVLINE of NLINE with LINES)
		     (replace NEXTLINE of LINES with NLINE)
		     (SETQ LINES NLINE)
		     (SETQ CHNO (ADD1 (fetch CHARLIM of NLINE]
	       (replace NEXTLINE of NLINE with LINE1)
	       (AND LINE1 (replace PREVLINE of LINE1 with NLINE))
	       (RETURN NLINE])

(\DISPLAYLINE
  [LAMBDA (TEXTOBJ LINE WINDOW IMAGECACHE)                   (* jds "24-May-84 20:10")
                                                             (* Display the line of text LINE in the edit window 
							     where it belongs.)
    (PROG ((CH 0)
	   (CHLIST (fetch CHARS of (fetch THISLINE of TEXTOBJ)))
	   (WLIST (fetch WIDTHS of (fetch THISLINE of TEXTOBJ)))
	   (LOOKS (fetch LOOKS of (fetch THISLINE of TEXTOBJ)))
	   (WINDOWDS (OR (AND WINDOW (WINDOWPROP WINDOW (QUOTE DSP)))
			 (fetch DS of TEXTOBJ)))
	   (TEXTLEN (fetch TEXTLEN of TEXTOBJ))
	   (THISLINE (fetch THISLINE of TEXTOBJ))
	   (TERMSA (fetch TXTTERMSA of TEXTOBJ))
	   (STREAM (fetch STREAMHINT of TEXTOBJ))
	   (OLDCACHE (fetch LCBITMAP of (fetch DISPLAYCACHE of TEXTOBJ)))
	   CACHE
	   (DS (fetch DISPLAYCACHEDS of TEXTOBJ))
	   LOOKSTARTX \PCHARSLEFT \PSTRING \PFILE FONT OFONT OLOOKS XOFFSET CLIPLEFT CLIPRIGHT 
	   DISPLAYDATA DDPILOTBBT DDWIDTHCACHE DDOFFSETCACHE CURY)
          (SETQ CACHE (\TEDIT.LINECACHE (fetch DISPLAYCACHE of TEXTOBJ)
					(fetch RIGHTMARGIN of LINE)
					(fetch LHEIGHT of LINE)))
          (COND
	    ((NEQ CACHE OLDCACHE)                            (* We changed the bitmaps because this line was 
							     bigger--update the displaystream, too)
	      (DSPDESTINATION CACHE DS)))
          (COND
	    ((AND (NOT (ZEROP (fetch CHAR1 of LINE)))
		  (ILEQ (fetch CHAR1 of LINE)
			TEXTLEN)
		  (IGREATERP (fetch YBOT of LINE)
			     (fetch WBOTTOM of TEXTOBJ)))    (* Only display the line of it contains text 
							     (CHAR1 > 0), appears before the end of the test, and is 
							     on-screen.)
	      (COND
		((NEQ (fetch DESC of THISLINE)
		      LINE)                                  (* No image cache -- re-format and display)
		  (\FORMATLINE TEXTOBJ NIL (fetch CHAR1 of LINE)
			       LINE)))
	      (MOVETO (fetch LEFTMARGIN of LINE)
		      (fetch DESCENT of LINE)
		      DS)
	      (MOVETO (fetch LEFTMARGIN of LINE)
		      (fetch YBASE of LINE)
		      WINDOWDS)                              (* Move to the left margin, on the base line for this 
							     line. ..)
	      (SETQ DISPLAYDATA (fetch IMAGEDATA of DS))
	      (SETQ DDPILOTBBT (ffetch DDPILOTBBT of DISPLAYDATA))
	      (SETQ XOFFSET (fetch DDXOFFSET of DISPLAYDATA))
                                                             (* The X position of the left edge of the window, since 
							     \TEDIT.BLTCHAR works on the screen bitmap itself.)
	      (SETQ CLIPLEFT (fetch DDClippingLeft of DISPLAYDATA))
                                                             (* The left and right edges of the clipping region for 
							     the text display window.)
	      (SETQ CLIPRIGHT (fetch DDClippingRight of DISPLAYDATA))
	      (BITBLT NIL 0 0 DS 0 0 (IDIFFERENCE CLIPRIGHT CLIPLEFT)
		      (fetch LHEIGHT of LINE)
		      (QUOTE TEXTURE)
		      (QUOTE REPLACE)
		      WHITESHADE)                            (* Clear the space the line will occupy)
	      (replace NEW of LINE with NIL)
	      (SETQ OFONT (DSPFONT (fetch CLFONT of (SETQ OLOOKS (\EDITELT LOOKS 0)))
				   DS))
	      (SETQ DDWIDTHCACHE (ffetch DDWIDTHSCACHE of DISPLAYDATA))
	      (SETQ DDOFFSETCACHE (ffetch DDOFFSETSCACHE of DISPLAYDATA))
	      (SETQ LOOKSTARTX (fetch LEFTMARGIN of LINE))   (* Starting X position for the current-looks text.)
	      (AND (fetch CLOFFSET of OLOOKS)
		   (RELMOVETO 0 (fetch CLOFFSET of OLOOKS)
			      DS))
	      (bind (LOOKNO ← 1)
		    DX
		    (TX ←(IPLUS XOFFSET (fetch LEFTMARGIN of LINE))) for I from 0
		 to (fetch LEN of THISLINE)
		 do 

          (* * Display the line character by character)


		    (SETQ CH (\EDITELT CHLIST I))
		    (SETQ DX (\WORDELT WLIST I))
		    [SELECTC CH
			     (401                            (* An INVISIBLE run -- skip it, and skip over the char 
							     count)
				  (add LOOKNO 1))
			     (400                            (* A LOOKS change)
				  (replace DDXPOSITION of DISPLAYDATA with (IDIFFERENCE TX XOFFSET))
                                                             (* Make the displaystream reflect our current X 
							     position)
				  (TEDIT.MODIFYLOOKS LINE LOOKSTARTX DS OLOOKS (fetch DESCENT
										  of LINE))
                                                             (* Make any necessary changes to the preceding 
							     characters (underline, strike-out &c))
				  (DSPFONT (fetch CLFONT of (SETQ OLOOKS (\EDITELT LOOKS LOOKNO)))
					   DS)               (* Set the new font)
				  (SETQ DDWIDTHCACHE (ffetch DDWIDTHSCACHE of DISPLAYDATA))
				  (SETQ DDOFFSETCACHE (ffetch DDOFFSETSCACHE of DISPLAYDATA))
				  (add LOOKNO 1)             (* Grab the next set of char looks)
				  (AND (fetch CLOFFSET of OLOOKS)
				       (RELMOVETO 0 (fetch CLOFFSET of OLOOKS)
						  DS))       (* Account for super/subscripting)
				  (SETQ LOOKSTARTX (IDIFFERENCE TX XOFFSET))
                                                             (* Remember the starting Xpos for possible later 
							     underlining &c)
				  )
			     (9                              (* TAB: use the width from the cache to decide the right
							     formatting.))
			     (13                             (* It's a CR)
				 NIL)
			     (COND
			       [(SMALLP CH)                  (* Normal character -- just display it.)
				 (COND
				   (TERMSA                   (* Using special instrns from TERMSA)
					   (\DSPPRINTCHAR STREAM CH))
				   (T                        (* Native charcodes)
				      (\TEDIT.BLTCHAR CH DS DX TX DISPLAYDATA DDPILOTBBT DDWIDTHCACHE 
						      DDOFFSETCACHE CLIPRIGHT]
			       (T                            (* CH is an object.)
				  (MOVETO (IDIFFERENCE TX XOFFSET)
					  (SETQ CURY (DSPYPOSITION NIL DS))
					  DS)                (* Go to the base line, left edge of the image region.)
				  (APPLY* (IMAGEOBJPROP CH (QUOTE DISPLAYFN))
					  CH DS (QUOTE DISPLAY)
					  (fetch STREAMHINT of TEXTOBJ))
                                                             (* Tell him to display himself here.)
				  (MOVETO (IDIFFERENCE TX XOFFSET)
					  CURY DS]
		    (add TX DX)                              (* Update our X position)
		 finally (replace DDXPOSITION of DISPLAYDATA with (IDIFFERENCE TX XOFFSET)) 
                                                             (* Make any necessary looks mods to the last run of 
							     characters)
			 (TEDIT.MODIFYLOOKS LINE LOOKSTARTX DS OLOOKS (fetch DESCENT of LINE)))
	      (BITBLT CACHE 0 0 WINDOWDS 0 (fetch YBOT of LINE)
		      (fetch WRIGHT of TEXTOBJ)
		      (fetch LHEIGHT of LINE)
		      (QUOTE INPUT)
		      (QUOTE REPLACE])

(\DOFORMATTING
  [LAMBDA (TEXTOBJ LINE FMTSPEC THISLINE #BLANKS PREVSP 1STLN)
                                                             (* jds "16-May-84 16:48")
                                                             (* Do the formatting work for justified, centered, etc. 
							     lines)
    (PROG ((QUAD (fetch QUAD of FMTSPEC))
	   (SPACELEFT (LLSH (fetch SPACELEFT of LINE)
			    5))
	   (CHLIST (fetch CHARS of THISLINE))
	   (WLIST (fetch WIDTHS of THISLINE))
	   (SPACEOFLOW 0)
	   EXTRASP OPREVSP LINELEAD)                         (* NB that SPACELEFT, OFLOW, etc. are kept in 32 x value
							     form, for rounding ease.)
          (replace LTRUEASCENT of LINE with (fetch ASCENT of LINE))
                                                             (* Save the true ascent value for display purposes)
          [COND
	    ((SETQ LINELEAD (fetch LINELEAD of FMTSPEC))     (* If line leading was specified, set it)
	      (COND
		((ILESSP LINELEAD 0)
		  (replace LHEIGHT of LINE with LINELEAD))
		(T (add (fetch LHEIGHT of LINE)
			(fetch LINELEAD of FMTSPEC))         (* And adjust the line's ascent accordingly)
		   (add (fetch ASCENT of LINE)
			(fetch LINELEAD of FMTSPEC]
          [COND
	    ((AND 1STLN (fetch LEADBEFORE of FMTSPEC))       (* If line leading was specified, set it)
	      (add (fetch LHEIGHT of LINE)
		   (fetch LEADBEFORE of FMTSPEC))
	      (add (fetch ASCENT of LINE)
		   (fetch LEADBEFORE of FMTSPEC]
          (COND
	    ((EQ QUAD (QUOTE CENTERED))                      (* Keep going if this is centering!)
	      NIL)
	    ((OR (ZEROP (fetch LEN of THISLINE))
		 (ZEROP #BLANKS)
		 (ZEROP PREVSP))                             (* For empty lines, and lines with no spaces, don't 
							     bother fixing blank widths.)
	      (RETURN)))
          (SELECTQ QUAD
		   (LEFT                                     (* Do nothing for left-justified lines except replace 
							     the character codes))
		   (RIGHT                                    (* Just move the right margin over)
			  (replace LEFTMARGIN of LINE with (IPLUS (fetch LEFTMARGIN of LINE)
								  (fetch SPACELEFT of LINE)))
			  (replace LXLIM of LINE with (fetch RIGHTMARGIN of LINE)))
		   [CENTERED                                 (* Split the difference for centering)
			     (add (fetch LEFTMARGIN of LINE)
				  (LRSH SPACELEFT 6))
			     (add (fetch LXLIM of LINE)
				  (LRSH SPACELEFT 6))
			     (COND
			       ((OR (ZEROP (fetch LEN of THISLINE))
				    (ZEROP #BLANKS)
				    (ZEROP PREVSP))          (* For empty lines, and lines with no spaces, don't 
							     bother fixing blank widths.)
				 (RETURN]
		   (JUSTIFIED                                (* For justified lines, stretch each space so line 
							     reaches the right margin)
			      (COND
				((OR (fetch CR\END of LINE)
				     (IGEQ (fetch CHARLIM of LINE)
					   (fetch TEXTLEN of TEXTOBJ)))
                                                             (* This is the last line in the paragraph;
							     don't stretch it out.)
				  (SETQ EXTRASP 0))
				(T (bind (OPREVSP ← PREVSP) while (AND (IGREATERP PREVSP 0)
								       (ILEQ OPREVSP
									     (IPLUS PREVSP 2)))
				      do                     (* Back up over all trailing white space on the line.)
					 (SETQ OPREVSP (SUB1 PREVSP))
					 (SETQ PREVSP (\EDITELT CHLIST OPREVSP))
					 (\EDITSETA CHLIST OPREVSP (CONSTANT (CHARCODE SPACE)))
					 (add #BLANKS -1)
					 %%%%)
				   (AND (ZEROP #BLANKS)
					(RETURN))            (* If there aren't any blanks except at end-of-line, 
							     don't bother going further.)
				   (replace LXLIM of LINE with (fetch RIGHTMARGIN of LINE))
                                                             (* Fix the right margin for showing selections &c)
				   (SETQ EXTRASP (IQUOTIENT SPACELEFT #BLANKS))
                                                             (* Now apportion the extra space evenly among blanks.)
				   ))
			      [while (IGREATERP PREVSP 0)
				 do                          (* Fix up the widths of spaces in the line)
				    (SETQ OPREVSP (SUB1 PREVSP))
				    (SETQ PREVSP (\EDITELT CHLIST OPREVSP))
				    (\EDITSETA CHLIST OPREVSP (CONSTANT (CHARCODE SPACE)))
				    [OR (fetch CR\END of LINE)
					(\WORDSETA WLIST OPREVSP (IPLUS (LRSH (IPLUS EXTRASP 
										     SPACEOFLOW)
									      5)
									(\WORDELT WLIST OPREVSP]
				    (SETQ SPACEOFLOW (LOGAND 31 (IPLUS EXTRASP SPACEOFLOW]
			      (RETURN))
		   NIL)
          (\TEDIT.PURGE.SPACES CHLIST PREVSP])

(\FILLWINDOW
  [LAMBDA (YBOT CURLINE TEXTOBJ DONTFILLFLG WINDOW)          (* jds "21-Apr-84 15:33")
                                                             (* Fill out TEXTOBJ's window, starting with the line 
							     after CURLINE, whose ybottom is YBOT)
                                                             (* Return T if any lines are moved up.)
                                                             (* DONTFILLFLG => Don't bother printing any new lines at
							     the bottom of the screen.)
    (PROG ((LINE (fetch NEXTLINE of CURLINE))
	   (CHARLIM (fetch CHARLIM of CURLINE))
	   (PREVLINE CURLINE)
	   WHEIGHT
	   (TEXTLEN (fetch TEXTLEN of TEXTOBJ))
	   (LINES\DELETED NIL)
	   (WINDOW (OR WINDOW (fetch \WINDOW of TEXTOBJ)))
	   OFLOWFN)
          (SETQ WHEIGHT (fetch HEIGHT of (DSPCLIPPINGREGION NIL WINDOW)))
          (while (AND LINE (IGEQ (fetch YBOT of LINE)
				 WHEIGHT))
	     do                                              (* Do not start with a line which is above the top of 
							     the screen.)
		(SETQ PREVLINE LINE)
		(SETQ CHARLIM (fetch CHARLIM of LINE))
		(SETQ LINE (fetch NEXTLINE of LINE)))
          [repeatwhile (ILESSP CHARLIM TEXTLEN)
	     do                                              (* Walk thru the lines below the starting line.)
		[COND
		  ((AND LINE (IGREATERP (SETQ YBOT (IDIFFERENCE YBOT (fetch LHEIGHT of LINE)))
					(fetch WBOTTOM of TEXTOBJ)))
                                                             (* If there is a line to display, and space to display 
							     it, go ahead.)
		    (replace YBOT of LINE with YBOT)
		    (replace YBASE of LINE with (IPLUS YBOT (fetch DESCENT of LINE)))
		    (\DISPLAYLINE TEXTOBJ LINE WINDOW))
		  (LINE                                      (* There is a line, but it won't fit.)
			(SETQ YBOT (IPLUS YBOT (fetch LHEIGHT of LINE)))
                                                             (* This existing line won't fit.
							     Punt out of this, setting YBOT so the screen gets 
							     cleared right.)
			[COND
			  ((SETQ OFLOWFN (WINDOWPROP WINDOW (QUOTE TEDIT.OVERFLOWFN)))
                                                             (* Try calling any user-supplied overflow fn, to handle 
							     the space overflow)
			    (AND (APPLY* OFLOWFN WINDOW TEXTOBJ)
				 (RETFROM (QUOTE \FILLWINDOW)
					  NIL]
			(RETURN))
		  (DONTFILLFLG                               (* We are instructed NOT to try filling the screen, so 
							     punt out.)
			       (RETURN))
		  ((OR (ILESSP CHARLIM TEXTLEN)
		       (ZEROP TEXTLEN))                      (* No existing lines to display, but there's text left 
							     (or the doc is empty and we need a dummy first line))
		    (SETQ LINE (\FORMATLINE TEXTOBJ NIL (ADD1 CHARLIM)))
                                                             (* Format the next line)
		    (replace PREVLINE of LINE with PREVLINE)
                                                             (* Hook it into the chain of line descriptors)
		    (replace NEXTLINE of LINE with (fetch NEXTLINE of PREVLINE))
		    (replace NEXTLINE of PREVLINE with LINE)
		    (COND
		      ((IGREATERP (SETQ YBOT (IDIFFERENCE YBOT (fetch LHEIGHT of LINE)))
				  (fetch WBOTTOM of TEXTOBJ))
                                                             (* If there's room, display the new line)
			(replace YBOT of LINE with YBOT)
			(replace YBASE of LINE with (IPLUS YBOT (fetch DESCENT of LINE)))
			(\DISPLAYLINE TEXTOBJ LINE WINDOW))
		      (T                                     (* Otherwise, we've overflown the window again)
			 (SETQ YBOT (IPLUS YBOT (fetch LHEIGHT of LINE)))
			 [COND
			   ((SETQ OFLOWFN (WINDOWPROP WINDOW (QUOTE TEDIT.OVERFLOWFN)))
			     (AND (APPLY* OFLOWFN WINDOW TEXTOBJ)
				  (RETFROM (QUOTE \FILLWINDOW)
					   NIL]
			 (RETURN]
		(COND
		  (LINE                                      (* Move forward to the next line in the chain, if any)
			(SETQ CHARLIM (fetch CHARLIM of LINE))
			(SETQ PREVLINE LINE)
			(SETQ LINE (fetch NEXTLINE of LINE)))
		  (T (SETQ CHARLIM (ADD1 TEXTLEN]
          (while LINE
	     do                                              (* If there are any existing lines which didn't fit, set
							     their YBOTs to 0 so they don't show)
		(AND (ILEQ (fetch CHAR1 of LINE)
			   TEXTLEN)
		     (replace YBOT of LINE with 0))
		(SETQ LINE (fetch NEXTLINE of LINE)))
          [COND
	    ((IGREATERP YBOT (fetch WBOTTOM of TEXTOBJ))     (* If there is space left at the bottom of the window, 
							     blank it out.)
	      (BITBLT NIL 0 0 WINDOW (fetch WBOTTOM of TEXTOBJ)
		      0
		      (fetch WRIGHT of TEXTOBJ)
		      YBOT
		      (QUOTE TEXTURE)
		      (QUOTE REPLACE)
		      WHITESHADE)
	      [COND
		((AND PREVLINE (fetch CR\END of PREVLINE)
		      (OR (ILESSP (fetch YBOT of PREVLINE)
				  WHEIGHT)
			  (ILEQ (fetch CHARTOP of PREVLINE)
				0))
		      (IGEQ (fetch CHARLIM of PREVLINE)
			    TEXTLEN)
		      (IGEQ (fetch YBOT of PREVLINE)
			    (fetch LHEIGHT of PREVLINE)))    (* If the last line ends in a CR, put a dummy line below
							     it.)
		  (SETQ PREVLINE (replace NEXTLINE of PREVLINE
				    with (create LINEDESCRIPTOR
						 CHAR1 ←(ADD1 TEXTLEN)
						 CHARLIM ←(ADD1 TEXTLEN)
						 RIGHTMARGIN ←(fetch RIGHTMARGIN of PREVLINE)
						 LEFTMARGIN ←(IPLUS 8 (fetch WLEFT of TEXTOBJ))
						 LXLIM ← 8
						 SPACELEFT ←(IDIFFERENCE (fetch RIGHTMARGIN
									    of PREVLINE)
									 8)
						 LHEIGHT ←(fetch LHEIGHT of PREVLINE)
						 ASCENT ←(fetch ASCENT of PREVLINE)
						 DESCENT ←(fetch DESCENT of PREVLINE)
						 YBOT ←(IDIFFERENCE (fetch YBOT of PREVLINE)
								    (fetch LHEIGHT of PREVLINE))
						 YBASE ←(IDIFFERENCE (fetch YBOT of PREVLINE)
								     (fetch ASCENT of PREVLINE))
						 PREVLINE ← PREVLINE
						 NEXTLINE ←(fetch NEXTLINE of PREVLINE)
						 CHARTOP ←(ADD1 TEXTLEN)
						 LFMTSPEC ←(fetch LFMTSPEC of PREVLINE)
						 LTRUEASCENT ←(fetch LTRUEASCENT of PREVLINE]
	      (COND
		((IGEQ (fetch CHARLIM of PREVLINE)
		       TEXTLEN)                              (* This line lies at end of text, so chop off any 
							     following lines.)
		  (replace NEXTLINE of PREVLINE with NIL]
          (RETURN LINES\DELETED])

(\FIXDLINES
  [LAMBDA (LINES SEL CH#1 CH#LIM TEXTOBJ)                    (* jds "17-Jan-84 14:59")
                                                             (* Fix up the list LINES of line descriptors, given that
							     characters CH#1 thru CH#LIM were deleted.)
                                                             (* Change CHAR1 and CHARLIM entries in each descriptor, 
							     and remove any descriptors for lines which disappeared 
							     entirely.)
    (for WW inside (fetch \WINDOW of TEXTOBJ)
       do (SETQ LINES (WINDOWPROP WW (QUOTE LINES)))
	  (PROG ((NLINES LINES)
		 (DCH (ADD1 (IDIFFERENCE CH#LIM CH#1)))
		 (CH#1L (SUB1 CH#1))
		 PL NL CHARLIM)
	        (bind (LINE ←(fetch NEXTLINE of LINES))
		      CHARLIM CHAR1 while LINE
		   do (SETQ CHARLIM (fetch CHARLIM of LINE))
		      (SETQ CHAR1 (fetch CHAR1 of LINE))
		      (COND
			[(ILESSP CHARLIM CH#1)
			  (COND
			    ((AND (IGEQ CH#1 CHAR1)
				  (ILEQ CH#1 (fetch CHARTOP of LINE)))
                                                             (* This change happened in a place where it may affect 
							     this line's break decision. Better reformat to be safe.)
			      (replace DIRTY of LINE with T))
			    ((AND (fetch CR\END of LINE)
				  (IEQP CHARLIM CH#1L))      (* This line ends in CR, and the deletion starts 
							     immediately thereafter. Best to reformat, for safety.)
			      (replace DIRTY of LINE with T]
			((IGREATERP CHAR1 CH#LIM)            (* This line contains none of the deleted text but is 
							     after it. Update CHAR1, CHARLIM and CHARTOP)
			  (replace CHAR1 of LINE with (IMAX 1 (IDIFFERENCE CHAR1 DCH)))
			  (replace CHARLIM of LINE with (IDIFFERENCE CHARLIM DCH))
			  (replace CHARTOP of LINE with (IDIFFERENCE (fetch CHARTOP of LINE)
								     DCH)))
			[(OR (ILESSP CHAR1 CH#1)
			     (IGREATERP CHARLIM CH#LIM))     (* This line contains some of the deleted text, mark it 
							     as dirty and update CHAR1 and CHARLIM)
			  (replace DIRTY of LINE with T)
			  (replace CHAR1 of LINE with (IMAX 1 (IMIN CHAR1 CH#1)))
			  (COND
			    [(IGREATERP CHARLIM CH#LIM)
			      (replace CHARLIM of LINE with (IDIFFERENCE CHARLIM
									 (IMIN DCH
									       (ADD1 (IDIFFERENCE
										       CH#LIM CHAR1]
			    (T (replace CHARLIM of LINE with CH#1L]
			(T                                   (* This line is totally within the deleted text, remove 
							     it)
			   (SETQ NL (fetch NEXTLINE of LINE))
			   (SETQ PL (fetch PREVLINE of LINE))
			   (COND
			     (PL (replace NEXTLINE of PL with NL)))
			   (COND
			     (NL (replace PREVLINE of NL with PL)))
			   (COND
			     ((EQ NLINES LINE)
			       (SETQ NLINES NL)))
			   (replace DELETED of LINE with T)
                                                             (* Mark this line deleted, so DELETETEXTCHARS know to 
							     ignore it.)
			   ))
		      (SETQ LINE (fetch NEXTLINE of LINE)))
	        (\TEDIT.FIXDELSEL (fetch SEL of TEXTOBJ)
				  TEXTOBJ CH#1 CH#LIM DCH)   (* Fix up the selections in this textobj)
	        (\TEDIT.FIXDELSEL (fetch SHIFTEDSEL of TEXTOBJ)
				  TEXTOBJ CH#1 CH#LIM DCH)
	        (\TEDIT.FIXDELSEL (fetch MOVESEL of TEXTOBJ)
				  TEXTOBJ CH#1 CH#LIM DCH)
	        (\TEDIT.FIXDELSEL (fetch DELETESEL of TEXTOBJ)
				  TEXTOBJ CH#1 CH#LIM DCH)
	        (RETURN NLINES])

(\FIXILINES
  [LAMBDA (TEXTOBJ SEL CH#1 DCH OTEXTLEN)                    (* jds "14-Mar-84 15:10")
                                                             (* Fix the list LINES of line descriptors to account for
							     DCH characters inserted before CH#1)
    (PROG (LINES CH# CHLIM CHAR1 CHARLIM)
          (SETQ CH#1 (IMAX CH#1 1))                          (* Make sure we're inserting in a legit spot.)
          [bind LINES for WW inside (ffetch \WINDOW of TEXTOBJ)
	     do                                              (* For each pane in the editing window, examine the 
							     pane's list of lines)
		(SETQ LINES (WINDOWPROP WW (QUOTE LINES)))
		(bind [LINE ←(COND
			      ((IGEQ (ffetch CHARTOP of LINES)
				     0)                      (* Make sure to skip the initial dummy line)
				LINES)
			      (T (ffetch NEXTLINE of LINES]
		   while LINE
		   do (\DTEST LINE (QUOTE LINEDESCRIPTOR))
		      (COND
			((IGREATERP (SETQ CHAR1 (ffetch CHAR1 of LINE))
				    CH#1)                    (* This line starts after the insertion point.
							     Update it's CHAR1)
			  (freplace CHAR1 of LINE with (IPLUS CHAR1 DCH)))
			((AND (IEQP CH#1 CHAR1)
			      (NEQ LINE (ffetch L1 of SEL)))
                                                             (* The insertion is at the end of the PRIOR line--so go 
							     ahead and update this CHAR1)
			  (freplace CHAR1 of LINE with (IPLUS CHAR1 DCH))
			  (COND
			    ((ffetch PREVLINE of LINE)
			      (freplace DIRTY of (ffetch PREVLINE of LINE) with T)))
			  (freplace DIRTY of LINE with T))
			((IGEQ (ffetch CHARTOP of LINE)
			       CH#1)                         (* This line spans the insert point.
							     Mark it DIRTY.)
			  (freplace DIRTY of LINE with T))
			((AND (IGEQ (SETQ CHARLIM (ffetch CHARLIM of LINE))
				    OTEXTLEN)
			      (NOT (ffetch CR\END of LINE)))

          (* This line is the last in the file, and its CHAR1 is <= the insert point, and it doesn't end in a CR.
	  Therefore, move the line's end upward to accomodate the insertion.)


			  (freplace DIRTY of LINE with T)))
		      [COND
			([OR (IGEQ (SETQ CHARLIM (ffetch CHARLIM of LINE))
				   CH#1)
			     (AND (IGEQ CHARLIM OTEXTLEN)
				  (NOT (ffetch CR\END of LINE]
			  (freplace CHARLIM of LINE with (IPLUS CHARLIM DCH))
			  (COND
			    ((IGEQ (ffetch CHARTOP of LINE)
				   CH#1)
			      (freplace CHARTOP of LINE with (IPLUS (ffetch CHARTOP of LINE)
								    DCH]
		      (SETQ LINE (ffetch NEXTLINE of LINE]
          [COND
	    ((IGEQ (SETQ CH# (ffetch CH# of SEL))
		   CH#1)                                     (* Fix up the selection; if we're beyond the insert 
							     point, move the whole sel forward)
	      (freplace CH# of SEL with (IPLUS CH# DCH]
          (COND
	    ((IGEQ (SETQ CHLIM (ffetch CHLIM of SEL))
		   CH#1)                                     (* And the tail end of the sel, too.)
	      (freplace CHLIM of SEL with (IPLUS CHLIM DCH])

(\FORMATLINE
  [LAMBDA (TEXTOBJ FMTSPEC CH#1 OLINE 1STLN)                 (* jds "21-May-84 16:55")
                                                             (* Given a starting place, format the next line of text.
							     Return the LINEDESCRIPTOR; reusing OLINE if it's given.)
    (PROG (TX [LINE (OR OLINE (create LINEDESCRIPTOR
				      RIGHTMARGIN ←(fetch WRIGHT of TEXTOBJ]
	      DX
	      (CH#B CH#1)
	      TXB CH (FORCEEND NIL)
	      (GATHERBLANK T)
	      (T1SPACE NIL)
	      TXB1 DXB WIDTH LOOK#B FONT (TLEN 0)
	      (TEXTLEN (fetch TEXTLEN of TEXTOBJ))
	      (THISLINE (ffetch THISLINE of TEXTOBJ))
	      FONTWIDTHS
	      (CHNO CH#1)
	      (LOOKNO 0)
	      (INVISIBLERUNS 0)
	      (ASCENT 0)
	      (DESCENT 0)
	      (PREVSP 0)
	      (#BLANKS 0)
	      TERMSA CLOOKS TEXTSTREAM CHLIST WLIST LOOKS ASCENTB DESCENTB INVISIBLERUNSB TABPENDING 
	      BOX PC PCNO)
      %  

          (* * Variables % (TLEN = Current character count on the line) (CHNO = Current character # in the %text) 
	  (DX = width of current char/object) (TX = current right margin) % (TXB1 = right margin of the first space/tab/CR 
	  in a row of space/tab/CR) % (CH#B = The CHNO of most recent space/tab) (TXB = right margin of most recent 
	  %space/tab) (DXB = width of most recent space/tab) (PREVSP = location on the line %of the previous space/tab to 
	  this space/tab + 1) (T1SPACE = a space/CR/TAB has been seen) (#BLANKS = # of spaces/tabs seen) % 
	  (LOOKNO = Current index into the LOOKS array. Updated by \TEDIT.LOOKS.UPDATE as %characters are read in) 
	  (LOOK#B = The LOOKNO of the most recent space/tab) (ASCENTB = Ascent at most recent potential line break point) 
	  (DESCENTB = Descent at most recent potential line break point))


          (SETQ CHLIST (fetch (ARRAYP BASE) of (fetch CHARS of THISLINE)))
          (SETQ WLIST (fetch (ARRAYP BASE) of (fetch WIDTHS of THISLINE)))
          (SETQ LOOKS (fetch LOOKS of THISLINE))
          (SETQ TEXTSTREAM (fetch STREAMHINT of TEXTOBJ))
          (SETQ TERMSA (fetch TXTTERMSA of TEXTOBJ))
          (replace EXTRASTREAMOP of TEXTSTREAM with (QUOTE \TEDIT.LOOKS.UPDATE))
          (freplace CHARLIM of LINE with TEXTLEN)            (* Force each new line to find its true CHARLIM.)
          (freplace NEW of LINE with T)                      (* Mark this line as not yet displayed)
          (freplace DIRTY of LINE with NIL)                  (* And as unchanged since the last formatting.)
          (freplace CHAR1 of LINE with CH#1)
          (freplace CR\END of LINE with NIL)                 (* Assume we won't see a CR.)
          (replace LHASTABS of LINE with NIL)                (* And has no TABs.)
          [COND
	    [(COND
		((AND (ILEQ CH#1 TEXTLEN)
		      (NOT (ZEROP TEXTLEN)))                 (* Only continue if there's really text we can format.)
		  (\SETUPGETCH CH#1 TEXTOBJ)                 (* Starting place)
                                                             (* And starting character looks)
		  (SETQ CLOOKS (fetch (TEXTSTREAM CURRENTLOOKS) of TEXTSTREAM))
		  (COND
		    ((fetch CLINVISIBLE of CLOOKS)           (* We've hit a run of invisible characters.
							     Skip them, and insert a marker in the line cache)
		      (add LOOKNO 1)                         (* Fix the counter of charlooks changes)
		      (SETQ PC (fetch (TEXTSTREAM PIECE) of TEXTSTREAM))
		      (\EDITSETA LOOKS LOOKNO (SETQ INVISIBLERUNS (fetch PLEN of PC)))
		      (\RPLPTR CHLIST 0 401)
		      (\PUTBASE WLIST 0 0)
		      (add TLEN 1)
		      (SETQ CHLIST (\ADDBASE CHLIST 2))
		      (SETQ WLIST (\ADDBASE WLIST 1))
		      (SETQ PC (fetch NEXTPIECE of PC))
		      (SETQ PCNO (ADD1 (fetch (TEXTSTREAM PCNO) of TEXTSTREAM)))
		      (SETQ CLOOKS (AND PC (\TEDIT.APPLY.STYLES (ffetch PLOOKS of PC)
								PC TEXTOBJ)))
		      (while (AND PC (fetch CLINVISIBLE of CLOOKS))
			 do (\EDITSETA LOOKS LOOKNO (add INVISIBLERUNS (fetch PLEN of PC)))
			    (SETQ PC (fetch NEXTPIECE of PC))
			    (SETQ CLOOKS (AND PC (\TEDIT.APPLY.STYLES (ffetch PLOOKS of PC)
								      PC TEXTOBJ)))
			    (add PCNO 1))
		      (add CHNO (\EDITELT LOOKS LOOKNO))
		      (\SETUPGETCH (create EDITMARK
					   PC ←(OR PC (QUOTE LASTPIECE))
					   PCOFF ← 0
					   PCNO ← PCNO)
				   TEXTOBJ)))
		  (ILEQ CHNO TEXTLEN)))
	      (SETQ FONT (fetch CLFONT of CLOOKS))
	      [SETQ ASCENTB (SETQ ASCENT (IMAX ASCENT (IPLUS (fetch \SFAscent of FONT)
							     (OR (fetch CLOFFSET of CLOOKS)
								 0]
	      [SETQ DESCENTB (SETQ DESCENT (IMAX DESCENT (IDIFFERENCE (fetch \SFDescent of FONT)
								      (OR (fetch CLOFFSET
									     of CLOOKS)
									  0]
	      [SETQ FONTWIDTHS (COND
		  (TERMSA (\TEDIT.GET.TERMSA.WIDTHS TERMSA FONT))
		  (T (fetch \SFWidths of FONT]
	      (\EDITSETA LOOKS 0 CLOOKS)                     (* Save looks in the line cache)
	      [OR FMTSPEC (SETQ FMTSPEC (OR (fetch PPARALOOKS of (fetch (TEXTSTREAM PIECE)
								    of TEXTSTREAM))
					    (fetch FMTSPEC of TEXTOBJ]
                                                             (* Get the paragraph looks)
	      [SETQ 1STLN (OR (IEQP CH#1 1)
			      (AND (fetch (TEXTSTREAM PIECE) of TEXTSTREAM)
				   (fetch PREVPIECE of (fetch (TEXTSTREAM PIECE) of TEXTSTREAM))
				   (fetch PPARALAST of (fetch PREVPIECE of (fetch (TEXTSTREAM PIECE)
									      of TEXTSTREAM)))
				   (IEQP (fetch (TEXTSTREAM PCSTARTCH) of TEXTSTREAM)
					 (fetch COFFSET of TEXTSTREAM))
				   (IEQP (fetch (TEXTSTREAM PCSTARTPG) of TEXTSTREAM)
					 (fetch CPAGE of TEXTSTREAM]
                                                             (* Are we on the first line of a paragraph?)
	      [SETQ TX (replace LEFTMARGIN of LINE with (IPLUS 8 (COND
								 (1STLN (fetch 1STLEFTMAR
									   of FMTSPEC))
								 (T (fetch LEFTMAR of FMTSPEC]
                                                             (* Set the left margin accordingly)
	      [replace RIGHTMARGIN of LINE with (SETQ WIDTH (COND
						    ((NOT (ZEROP (fetch RIGHTMAR of FMTSPEC)))
						      (IPLUS 8 (fetch RIGHTMAR of FMTSPEC)))
						    (T (IDIFFERENCE (fetch WRIGHT of TEXTOBJ)
								    8]
                                                             (* RIGHTMAR = 0 => follow the window's width.)
	      (SETQ TXB1 WIDTH)
	      (for old TLEN from TLEN to 254 as old CHNO from CHNO to TEXTLEN
		 do                                          (* The character loop)
		    (SETQ CH (\BIN TEXTSTREAM))              (* Get the next character for the line.)
		    [SETQ DX (COND
			((SMALLP CH)                         (* CH is really a character)
			  (\GETWIDTH FONTWIDTHS CH))
			(T                                   (* CH is an object)
			   (SETQ BOX (APPLY* (IMAGEOBJPROP CH (QUOTE IMAGEBOXFN))
					     CH
					     (fetch DS of TEXTOBJ)
					     TX WIDTH))      (* Get its size)
			   [SETQ ASCENT (IMAX ASCENT (IDIFFERENCE (fetch YSIZE of BOX)
								  (fetch YDESC of BOX]
			   (SETQ DESCENT (IMAX DESCENT (fetch YDESC of BOX)))
			   (IMAGEOBJPROP CH (QUOTE BOUNDBOX)
					 BOX)
			   (fetch XSIZE of BOX]              (* Get CH's X width.)
		    [SELCHARQ CH
			      (SPACE                         (* CH is a <Space>. Remember it, in case we need to 
							     break the line.)
				     (COND
				       (GATHERBLANK (SETQ TXB1 TX)
						    (SETQ GATHERBLANK NIL)))
				     (SETQ CH#B CHNO)        (* put the location # of the previous space/tab in the 
							     character array instead of the space itself)
				     (\RPLPTR CHLIST 0 PREVSP)
				     (\PUTBASE WLIST 0 DX)
				     (SETQ PREVSP (ADD1 TLEN))
				     (SETQ T1SPACE T)
				     (add TX DX)
				     (SETQ TXB TX)
				     (SETQ DXB DX)
				     (SETQ LOOK#B LOOKNO)
				     (SETQ ASCENTB ASCENT)
				     (SETQ DESCENTB DESCENT)
				     (SETQ INVISIBLERUNSB INVISIBLERUNS)
				     (add #BLANKS 1))
			      (CR                            (* Ch is a <Return>. Force an end to the line.)
				  (freplace CHARLIM of LINE with CHNO)
				  (SETQ FORCEEND T)
				  (\RPLPTR CHLIST 0 (CHARCODE CR))
				  (\PUTBASE WLIST 0 (SETQ DX (IMAX DX 6)))
				  (COND
				    (GATHERBLANK (SETQ TXB1 TX)
						 (SETQ GATHERBLANK NIL)))
				  (SETQ T1SPACE T)
				  (freplace CR\END of LINE with T)
				  (SETQ TX (IPLUS TX DX))
				  (RETURN))
			      (TAB                           (* Try to be reasonable with tabs.
							     This will create trouble when doing fast-case 
							     insert/delete, but Pah! for now.)
				   (replace LHASTABS of LINE with T)
                                                             (* To disable smart screen update)
				   (SETQ TABPENDING
				     (\TEDIT.FORMATTABS TEXTOBJ FMTSPEC THISLINE CHLIST WLIST TX 36 8 
							TABPENDING))
                                                             (* Figure out which tab stop to use, and what we need to
							     do to get there.)
				   [COND
				     ((FIXP TABPENDING)      (* If it returns a number, that is the new TX, adjusted 
							     for any prior tabs)
				       (SETQ TX TABPENDING)
				       (SETQ TABPENDING NIL))
				     (TABPENDING             (* Otherwise, look in the PENDINGTAB for the new TX)
						 (SETQ TX (fetch PTNEWTX of TABPENDING]
				   (COND
				     (GATHERBLANK (SETQ TXB1 TX)
						  (SETQ GATHERBLANK NIL)))
				   (SETQ CH#B CHNO)
				   (SETQ DX (\GETBASE WLIST 0))
				   (\RPLPTR CHLIST 0 CH)
				   (\TEDIT.PURGE.SPACES (fetch CHARS of THISLINE)
							PREVSP)
                                                             (* All the spaces before a tab don't take part in 
							     justification from here on.)
				   (SETQ PREVSP 0)
				   (SETQ T1SPACE T)
				   (SETQ TX (IPLUS TX DX))
				   (SETQ TXB TX)             (* Remember the world in case this is the "space" before
							     the line breaks)
				   (SETQ DXB DX)
				   (SETQ LOOK#B LOOKNO)
				   (SETQ ASCENTB ASCENT)
				   (SETQ DESCENTB DESCENT)
				   (SETQ INVISIBLERUNSB INVISIBLERUNS))
			      (PROGN (SETQ GATHERBLANK T)
				     (COND
				       ((IGREATERP (SETQ TX (IPLUS TX DX))
						   WIDTH)    (* We're past the right margin;
							     stop formatting at the last blank.)
					 (SETQ FORCEEND T)
					 (COND
					   (T1SPACE          (* There's a breaking point on this line.
							     Go back there and break the line.)
						    (freplace CHARLIM of LINE with CH#B)
						    (SETQ TX TXB)
						    (SETQ DX DXB)
						    (SETQ ASCENT ASCENTB)
						    (SETQ DESCENT DESCENTB)
						    (SETQ LOOKNO LOOK#B)
						    (SETQ INVISIBLERUNS INVISIBLERUNSB))
					   ((IGREATERP TLEN 0)
					     (freplace CHARLIM of LINE with (SUB1 CHNO))
					     (SETQ TX (IDIFFERENCE TX DX))
                                                             (* No spaces on this line; break it before this 
							     character.)
					     )
					   (T                (* Can't split BEFORE the first thing on the line!)
					      (freplace CHARLIM of LINE with CHNO)
					      (\RPLPTR CHLIST 0 CH)
					      (\PUTBASE WLIST 0 DX)))
					 (RETURN))
				       (T                    (* Not past the rightmargin yet...)
					  (\RPLPTR CHLIST 0 CH)
					  (\PUTBASE WLIST 0 DX]
		    (SETQ CHLIST (\ADDBASE CHLIST 2))        (* Move the pointers forward for the next character.)
		    (SETQ WLIST (\ADDBASE WLIST 1)))
	      (COND
		((AND (IEQP TLEN 255)
		      (ILESSP CHNO TEXTLEN))                 (* This line is too long for us to format??)
		  (TEDIT.PROMPTPRINT TEXTOBJ "Line too long to format." T)))
	      (COND
		(TABPENDING                                  (* There is a TAB outstanding.
							     Go handle it.)
			    (SETQ TABPENDING (\TEDIT.FORMATTABS TEXTOBJ FMTSPEC THISLINE CHLIST WLIST 
								TX 36 8 TABPENDING))
			    [COND
			      ((FIXP TABPENDING)             (* If it returns a number, that is the new TX, adjusted 
							     for any prior tabs)
				(SETQ TX TABPENDING)
				(SETQ TABPENDING NIL))
			      (TABPENDING                    (* Otherwise, look in the PENDINGTAB for the new TX)
					  (SETQ TX (fetch PTNEWTX of TABPENDING]
			    (\TEDIT.PURGE.SPACES (fetch CHARS of THISLINE)
						 PREVSP)
			    (SETQ PREVSP 0]
	    (T                                               (* No text to go in this line;
							     set Ascent/Descent to the default font from the window.)
	       (SETQ ASCENT (FONTPROP (OR (AND (fetch DEFAULTCHARLOOKS of TEXTOBJ)
					       (fetch CLFONT of (fetch DEFAULTCHARLOOKS of TEXTOBJ)))
					  TEDIT.DEFAULT.FONT)
				      (QUOTE ASCENT))
		 (SETQ DESCENT (FONTPROP (OR (AND (fetch DEFAULTCHARLOOKS of TEXTOBJ)
						  (fetch CLFONT of (fetch DEFAULTCHARLOOKS
								      of TEXTOBJ)))
					     TEDIT.DEFAULT.FONT)
					 (QUOTE DESCENT)))
		 (SETQ FMTSPEC (OR FMTSPEC (fetch FMTSPEC of TEXTOBJ)))
		 (SETQ 1STLN T)
		 [SETQ TX (replace LEFTMARGIN of LINE with (IPLUS 8 (fetch 1STLEFTMAR of FMTSPEC]
		 [replace RIGHTMARGIN of LINE with (SETQ WIDTH
						     (COND
						       ((NOT (ZEROP (fetch RIGHTMAR of FMTSPEC)))
							 (fetch RIGHTMAR of FMTSPEC))
						       (T (IDIFFERENCE (fetch WRIGHT of TEXTOBJ)
								       8]
		 (SETQ TXB1 WIDTH]
          [COND
	    ((ZEROP (freplace LHEIGHT of LINE with (IPLUS ASCENT DESCENT)))
	      (replace LHEIGHT of LINE with (FONTPROP (OR (AND (fetch DEFAULTCHARLOOKS of TEXTOBJ)
							       (fetch CLFONT
								  of (fetch DEFAULTCHARLOOKS
									of TEXTOBJ)))
							  TEDIT.DEFAULT.FONT)
						      (QUOTE HEIGHT]
                                                             (* Line's height (or 12 for an empty line))
          (replace ASCENT of LINE with ASCENT)
          (replace DESCENT of LINE with DESCENT)
          (freplace CHARTOP of LINE with CHNO)
          [COND
	    (FORCEEND NIL)
	    (T (SETQ CHNO (SUB1 CHNO))
	       (SETQ TLEN (SUB1 TLEN]                        (* If we ran off the end of the text, then keep true 
							     space left on the line.)
          (freplace LXLIM of LINE with TX)
          [freplace SPACELEFT of LINE with (COND
					     (FORCEEND       (* The line was forced to end.
							     Back up to start of last blank section)
						       (IDIFFERENCE WIDTH TXB1))
					     (GATHERBLANK    (* Otherwise, use the rightmost character on the line.)
							  (IDIFFERENCE WIDTH TX))
					     (T 

          (* The line ended with a run of white space. Ignore it for purposes of deciding how much more we can fit on the 
	  line.)


						(IDIFFERENCE WIDTH TXB1]
          (freplace DESC of THISLINE with LINE)
          [freplace LEN of THISLINE
	     with (IMIN 254 (COND
			  ((ILESSP TEXTLEN CH#1)
			    -1)
			  (T (IPLUS LOOKNO (IDIFFERENCE (IMIN (fetch CHARLIM of LINE)
							      TEXTLEN)
							(IPLUS INVISIBLERUNS (fetch CHAR1
										of LINE]
          (\DOFORMATTING TEXTOBJ LINE FMTSPEC THISLINE #BLANKS PREVSP 1STLN)
          (replace LFMTSPEC of LINE with FMTSPEC)
          (replace EXTRASTREAMOP of TEXTSTREAM with NIL)
          (RETURN LINE])

(\PULLTEXT
  [LAMBDA (LINE DX CH1 TEXTOBJ)                              (* jds "21-Apr-84 15:35")
                                                             (* Reset start of line to ch1, and pull dx off the 
							     front.)
    (COND
      ((ILESSP DX 0)
	(ERROR "MOVING TEXT DOWN AFTER A DELETE??!" DX)))
    (PROG ((OXLIM (fetch LXLIM of LINE))
	   (OCHLIM (fetch CHARLIM of LINE))
	   (OSPACE (IPLUS (fetch SPACELEFT of LINE)
			  DX))
	   NLINE NDX NL (DEL NIL)
	   (DS (fetch DS of TEXTOBJ))
	   (OCH1 (fetch CHAR1 of LINE)))
          (replace DIRTY of LINE with NIL)
          (replace SPACELEFT of LINE with OSPACE)            (* There's going to be more space on this line when 
							     we're done.)
          (replace CHAR1 of LINE with CH1)
          (BITBLT DS (IPLUS (fetch LEFTMARGIN of LINE)
			    DX)
		  (fetch YBOT of LINE)
		  DS
		  (fetch LEFTMARGIN of LINE)
		  (fetch YBOT of LINE)
		  (fetch RIGHTMARGIN of LINE)
		  (fetch LHEIGHT of LINE)
		  (QUOTE INPUT)
		  (QUOTE REPLACE))                           (* Move remaining text over)
          (SETQ OXLIM (IDIFFERENCE OXLIM DX))                (* And shorten the line accordingly)
          (BITBLT NIL 0 0 DS (IDIFFERENCE (fetch RIGHTMARGIN of LINE)
					  OSPACE)
		  (fetch YBOT of LINE)
		  (fetch RIGHTMARGIN of LINE)
		  (fetch LHEIGHT of LINE)
		  (QUOTE TEXTURE)
		  (QUOTE REPLACE)
		  WHITESHADE)                                (* Blank the newly-cleared section of the line's image)
          (COND
	    ((IEQP OXLIM (fetch LEFTMARGIN of LINE))
	      (TEDIT.DELETELINE LINE TEXTOBJ)                (* The call to \PULLTEXT emptied this line completely.
							     Throw it away.)
	      (SETQ DEL T))
	    [T                                               (* Need to check for flow-in from the next line.)
	       (\FORMATLINE TEXTOBJ NIL CH1 LINE)
	       (COND
		 ((NOT (IEQP OXLIM (fetch LXLIM of LINE)))   (* The line length changed from what we'd expected.
							     Some text got moved up from below.)
		   (SETQ NDX (IDIFFERENCE (fetch LXLIM of LINE)
					  OXLIM))
		   (COND
		     ((ILESSP NDX 0)
		       (ERROR "Moving Text down after DEL." NDX))
		     (T (COND
			  [(AND (SETQ NLINE (fetch NEXTLINE of LINE))
				(IGREATERP (fetch YBOT of NLINE)
					   (fetch WBOTTOM of TEXTOBJ)))
			    (COND
			      ((OR (fetch LHASTABS of LINE)
				   (fetch LHASTABS of NLINE))
                                                             (* There are TABS involved. punt out.)
				(\DISPLAYLINE TEXTOBJ LINE)
				(replace CHAR1 of NLINE with (ADD1 (fetch CHARLIM of LINE)))
				(replace DIRTY of NLINE with T)
				(TEDIT.UPDATE.SCREEN TEXTOBJ NLINE)
				(RETURN NIL))
			      [(IGEQ (IDIFFERENCE (fetch LXLIM of NLINE)
						  (fetch LEFTMARGIN of NLINE))
				     NDX)                    (* There's enough on the next line to grab)
				(BITBLT DS (fetch LEFTMARGIN of NLINE)
					(fetch YBOT of NLINE)
					DS OXLIM (fetch YBOT of LINE)
					NDX
					(fetch LHEIGHT of LINE)
					(QUOTE INPUT)
					(QUOTE REPLACE))     (* Move the text up from the next line)
				(COND
				  ((ILESSP (fetch CHARLIM of LINE)
					   (fetch TEXTLEN of TEXTOBJ))
                                                             (* There are more characters to go on the next line.)
				    (SETQ DEL (\PULLTEXT NLINE NDX (ADD1 (fetch CHARLIM of LINE))
							 TEXTOBJ)))
				  (T                         (* This line is the last. Delete all the others)
				     (SETQ DEL T)
				     (replace NEXTLINE of LINE with NIL)
				     (replace PREVLINE of NLINE with NIL)
				     (BITBLT NIL 0 0 DS 0 0 (fetch WRIGHT of TEXTOBJ)
					     (SUB1 (fetch YBOT of LINE))
					     (QUOTE TEXTURE)
					     (QUOTE REPLACE)
					     WHITESHADE]
			      (T                             (* Not enough on next line;; grab it and loop)
				 (ERROR "PULLING TEXT FROM TOO SHORT A LINE"]
			  (T (\DISPLAYLINE TEXTOBJ LINE)
			     (replace NEXTLINE of LINE with NIL)
			     (AND NLINE (replace PREVLINE of NLINE with NIL]
	    (T (replace LXLIM of LINE with OXLIM)))
          (RETURN DEL])

(\PUSHTEXT
  [LAMBDA (LINE X Y DX CH TEXTOBJ FORCEFORMAT IMAGECACHE SAVEWIDTH)
                                                             (* jds "21-Apr-84 15:29")
                                                             (* MOVE TEXT FROM THE LINE ABOVE ONTO THIS LINE)
    (PROG ((NDX 0)
	   (OXLIM (fetch LXLIM of LINE))
	   (OCHLIM (fetch CHARLIM of LINE))
	   (OSPACE (fetch SPACELEFT of LINE))
	   (OLHEIGHT (fetch LHEIGHT of LINE))
	   (OTABS (fetch LHASTABS of LINE))
	   (DS (ffetch DS of TEXTOBJ))
	   (NEXTCACHE (fetch LCNEXTCACHE of IMAGECACHE))
	   NEXTLINE OCR\END NEWLINE NSAVEWIDTH OFLOWFN DY IMAGE)
          (replace CHAR1 of LINE with CH)                    (* Fix up this line to start just after old line ends)
          (SETQ OCR\END (fetch CR\END of LINE))
          (\FORMATLINE TEXTOBJ NIL CH LINE)
          (COND
	    ((OR (fetch LHASTABS of LINE)
		 OTABS)                                      (* Punt if this line has tabs in it.)
	      (replace DIRTY of LINE with T)
	      (TEDIT.UPDATE.SCREEN TEXTOBJ LINE)
	      (RETURN)))
          [COND
	    [(OR FORCEFORMAT (IGREATERP DX OSPACE))          (* May need to move some text to yet another line...)
	      (SETQ NDX (IDIFFERENCE (IPLUS OXLIM DX)
				     (fetch LXLIM of LINE)))
                                                             (* NDX ← Amount of text to be moved to the next line)
	      (COND
		((IGREATERP NDX 0)                           (* There is excess on this line--move it to the next 
							     line)
		  (COND
		    (OCR\END                                 (* This line ends in a CR -- just create a new line with
							     the overflow on it)
			     [SETQ NEWLINE (\FORMATLINE TEXTOBJ NIL (ADD1 (fetch CHARLIM
									     of LINE]
			     (replace YBOT of NEWLINE with (IDIFFERENCE (fetch YBOT of LINE)
									(fetch LHEIGHT of NEWLINE)))
			     (replace YBASE of NEWLINE with (IPLUS (fetch YBOT of NEWLINE)
								   (fetch DESCENT of NEWLINE)))
			     (COND
			       ((AND (SETQ OFLOWFN (WINDOWPROP DS (QUOTE TEDIT.OVERFLOWFN)))
				     (APPLY* OFLOWFN DS TEXTOBJ))
				 (RETURN NIL))
			       ((SETQ NEXTLINE (fetch NEXTLINE of LINE))
                                                             (* There's another line to push onto.)
				 (OR (\TEDIT.ADJUST.LINES TEXTOBJ NEXTLINE DS (fetch YBOT
										 of LINE)
							  (IMINUS (fetch LHEIGHT of NEWLINE)))
				     (RETURN NIL))           (* If pushing overflowed the window, punt here and now.)
				 (BITBLT NIL 0 0 DS 0 (IDIFFERENCE (fetch YBOT of LINE)
								   (fetch LHEIGHT of NEWLINE))
					 (fetch WRIGHT of TEXTOBJ)
					 (fetch LHEIGHT of NEWLINE)
					 (QUOTE TEXTURE)
					 (QUOTE REPLACE)
					 WHITESHADE)
				 (replace PREVLINE of NEXTLINE with NEWLINE)))
			     (replace NEXTLINE of NEWLINE with NEXTLINE)
			     (replace PREVLINE of NEWLINE with LINE)
			     (replace NEXTLINE of LINE with NEWLINE)
			     (\TEDIT.CHECK (fetch TCUP of (fetch CARET of TEXTOBJ))
					   "Caret visible during pushtext move down.")
			     (BITBLT DS (IDIFFERENCE OXLIM NDX)
				     (fetch YBOT of LINE)
				     DS
				     (fetch LEFTMARGIN of NEWLINE)
				     (fetch YBOT of NEWLINE)
				     NDX
				     (fetch LHEIGHT of NEWLINE)
				     (QUOTE INPUT)
				     (QUOTE REPLACE))        (* Move the text onto the newly-built line)
			     (SETQ NDX 0))
		    ((fetch NEXTLINE of LINE)                (* There is text to be moved onto the next line;
							     save its image for the move which happens later)
		      [SETQ NSAVEWIDTH (IMIN NDX (IMAX 0 (IDIFFERENCE (fetch RIGHTMARGIN
									 of LINE)
								      (IDIFFERENCE OXLIM NDX]
		      (\TEDIT.CHECK (fetch TCUP of (fetch CARET of TEXTOBJ)))
                                                             (* THE CARET MUST BE INVISIBLE)
		      (SETQ IMAGE (\TEDIT.LINECACHE NEXTCACHE NSAVEWIDTH (fetch LHEIGHT of LINE)))
		      (BITBLT DS (IDIFFERENCE OXLIM NDX)
			      (fetch YBOT of LINE)
			      IMAGE 0 0 NDX (fetch LHEIGHT of LINE)
			      (QUOTE INPUT)
			      (QUOTE REPLACE))               (* Save the text that will be moved down later on)
		      )
		    (T                                       (* No succeeding line, so create one.)
		       [SETQ NEXTLINE (\FORMATLINE TEXTOBJ NIL (ADD1 (fetch CHARLIM of LINE]
		       (COND
			 ((IGREATERP (fetch YBOT of LINE)
				     (IPLUS (fetch LHEIGHT of NEXTLINE)
					    (fetch WBOTTOM of TEXTOBJ)))
			   (replace YBOT of NEXTLINE with (IDIFFERENCE (fetch YBOT of LINE)
								       (fetch LHEIGHT of NEXTLINE)))
			   (replace YBASE of NEXTLINE with (IPLUS (fetch YBOT of NEXTLINE)
								  (fetch DESCENT of NEXTLINE)))
			   (\DISPLAYLINE TEXTOBJ NEXTLINE NIL NEXTCACHE))
			 ((AND (SETQ OFLOWFN (WINDOWPROP DS (QUOTE TEDIT.OVERFLOWFN)))
			       (APPLY* OFLOWFN DS TEXTOBJ))
                                                             (* This line overflowed the window.
							     If it gets handled by user handler, just punt out.)
			   (RETURN NIL)))
		       (replace NEXTLINE of LINE with NEXTLINE)
		       (replace PREVLINE of NEXTLINE with LINE)
		       (SETQ NDX 0]
	    (T                                               (* There is enough room on this line, so not to worry 
							     about moving text down.)
	       (replace SPACELEFT of LINE with (IDIFFERENCE (fetch SPACELEFT of LINE)
							    DX))
	       (replace LXLIM of LINE with (IPLUS OXLIM DX]
          (COND
	    ((IGREATERP (fetch YBOT of LINE)
			(fetch WBOTTOM of TEXTOBJ))          (* This line is fully on-screen.
							     Move it over to make room for text, then move the text 
							     in from above.)
	      (\TEDIT.ADJUST.LINES TEXTOBJ LINE DS (fetch YBOT of (fetch PREVLINE of LINE))
				   (IDIFFERENCE OLHEIGHT (fetch LHEIGHT of LINE)))
	      (BITBLT DS (fetch LEFTMARGIN of LINE)
		      (fetch YBOT of LINE)
		      DS
		      (IPLUS (fetch LEFTMARGIN of LINE)
			     DX)
		      (fetch YBOT of LINE)
		      OXLIM
		      (fetch LHEIGHT of LINE)
		      (QUOTE INPUT)
		      (QUOTE REPLACE))                       (* Move this line over to make room.)
	      (BITBLT NIL 0 0 DS (fetch LEFTMARGIN of LINE)
		      (fetch YBOT of LINE)
		      DX
		      (fetch LHEIGHT of LINE)
		      (QUOTE TEXTURE)
		      (QUOTE REPLACE)
		      WHITESHADE)                            (* Blank out the space just cleared.)
	      (BITBLT (fetch LCBITMAP of IMAGECACHE)
		      0 0 DS (fetch LEFTMARGIN of LINE)
		      (fetch YBOT of LINE)
		      SAVEWIDTH
		      (fetch LHEIGHT of LINE)
		      (QUOTE INPUT)
		      (QUOTE REPLACE))                       (* Move the text in from above.)
	      (BITBLT NIL 0 0 DS (fetch LXLIM of LINE)
		      (fetch YBOT of LINE)
		      (fetch WRIGHT of TEXTOBJ)
		      (fetch LHEIGHT of LINE)
		      (QUOTE TEXTURE)
		      (QUOTE REPLACE)
		      WHITESHADE)                            (* Blank out the area beyond the end of this line)
                                                             (* Cache the new image)
	      (OR (ILEQ NDX 0)
		  (\PUSHTEXT (fetch NEXTLINE of LINE)
			     (IDIFFERENCE OXLIM NDX)
			     (fetch YBOT of LINE)
			     NDX
			     (ADD1 (fetch CHARLIM of LINE))
			     TEXTOBJ OCR\END NEXTCACHE NSAVEWIDTH))
                                                             (* Now propogate the change to the next line.)
	      ))
          (replace DIRTY of LINE with NIL)
          (RETURN T])

(\SHOWTEXT
  [LAMBDA (TEXTOBJ LINES WINDOW)                             (* jds " 5-Apr-84 10:01")
                                                             (* Fill the editor window with text, starting from the 
							     top of the file.)
    (COND
      ((fetch \WINDOW of TEXTOBJ)                            (* If there is no edit window, just return.)
	(PROG (WREG)
	      (SETQ WINDOW (OR WINDOW (\TEDIT.MAINW TEXTOBJ)))
	      (SETQ WREG (DSPCLIPPINGREGION NIL WINDOW))
	      (DSPFILL NIL WHITESHADE (QUOTE REPLACE)
		       WINDOW)                               (* Clear the window.)
	      (RETURN (RESETLST (RESETSAVE (CURSOR WAITINGCURSOR))
                                                             (* Display the hourglass cursor as we work)
				(SETQ LINES (create LINEDESCRIPTOR
						    YBOT ←(fetch HEIGHT of WREG)
						    CHAR1 ← 0
						    CHARLIM ← 0
						    SPACELEFT ← -1
						    RIGHTMARGIN ←(SUB1 (fetch WIDTH of WREG))
						    NEXTLINE ← NIL
						    CHARTOP ← -1
						    LHEIGHT ← 0
						    LXLIM ←(fetch WIDTH of WREG)
						    CR\END ← T
						    ASCENT ← 0
						    DESCENT ← 0
						    LTRUEASCENT ← 0))
                                                             (* Make sure we have the anchor pseudo-line)
				(\FILLWINDOW (fetch HEIGHT of WREG)
					     LINES TEXTOBJ NIL WINDOW)
                                                             (* Fill the window as usual)
				(\TEDIT.SET.WINDOW.EXTENT TEXTOBJ WINDOW)
				LINES])

(\TEDIT.ADJUST.LINES
  [LAMBDA (TEXTOBJ FIRSTLINE WINDOW LINETOP DY)              (* jds "18-May-84 10:48")

          (* Move all lines from FIRSTLINE (inclusive) on up or down. Fill in a line or drop one off, accordingly.
	  Positive DY means move UP.)

                                                             (* LINETOP is the top of the region to be moved as the 
							     adjustment is made. It corresponds to the TOP of 
							     FIRSTLINE.)
    (PROG ((OFLOW NIL)
	   OFLOWFN OYBOT PREVLINE)
          [COND
	    ((NOT (ZEROP DY))                                (* This line's total height changed -- must move the 
							     rest of the window, and adjust YBOT/BASEs.)
	      (bind (LL ← FIRSTLINE) while (AND LL (IGREATERP (fetch YBOT of LL)
							      (fetch WBOTTOM of TEXTOBJ)))
		 do                                          (* Loop thru the line descriptors that are affected by 
							     the change (i.e., those below it), and adjust their Y 
							     locations.)
		    (SETQ OYBOT (fetch YBOT of LL))
		    [COND
		      ((ILEQ (replace YBOT of LL with (IPLUS OYBOT DY))
			     (fetch WBOTTOM of TEXTOBJ))     (* This line moved below the bottom of the screen)
			(BITBLT NIL 0 0 WINDOW 0 OYBOT (fetch WRIGHT of TEXTOBJ)
				(fetch LHEIGHT of LL)
				(QUOTE TEXTURE)
				(QUOTE REPLACE)
				WHITESHADE)                  (* So clear the space it used to occupy.)
			(COND
			  ((AND (SETQ OFLOWFN (WINDOWPROP WINDOW (QUOTE TEDIT.OVERFLOWFN)))
				(APPLY* OFLOWFN WINDOW TEXTOBJ))
                                                             (* We walked off the bottom, and the user gave us an 
							     OFLOWFN to handle it. Give it a try.)
			    (SETQ OFLOW T)
			    (RETURN NIL]
		    (add (fetch YBASE of LL)
			 DY)                                 (* Adjust the baseline of the line, as well as its 
							     physical bottom.)
		    (replace YBOT of LL with (IDIFFERENCE (fetch YBASE of LL)
							  (fetch DESCENT of LL)))
                                                             (* I realize this looks redundant, but the line's 
							     descent may have changed, too.)
		    (SETQ PREVLINE LL)                       (* Remember the prior line, since we'll need it if we 
							     later try to fill out the window with more text.)
		    (SETQ LL (fetch NEXTLINE of LL))         (* Move to the next line.))
	      (AND OFLOW (RETURN NIL))                       (* If there was an overflow, and it got handled by the 
							     user's OFLOWFN, don't bother trying anything further.)
	      (COND
		[(IGREATERP DY 0)                            (* The line is shorter; move the rest up.)
		  (BITBLT WINDOW 0 0 WINDOW 0 DY (fetch WRIGHT of TEXTOBJ)
			  LINETOP
			  (QUOTE INPUT)
			  (QUOTE REPLACE))                   (* Move the text up)
		  (BITBLT NIL 0 0 WINDOW 0 0 (fetch WRIGHT of TEXTOBJ)
			  DY
			  (QUOTE TEXTURE)
			  (QUOTE REPLACE)
			  WHITESHADE)                        (* Now clear the bottom part of the window, which got 
							     vacated by the adjustment)
		  (COND
		    ((AND PREVLINE (IGREATERP (fetch YBOT of PREVLINE)
					      0))            (* If there is space left on the screen, try to fill it 
							     with new text.)
		      (\FILLWINDOW (fetch YBOT of PREVLINE)
				   PREVLINE TEXTOBJ NIL WINDOW]
		(T                                           (* The line is taller; move the rest down.)
		   (BITBLT WINDOW 0 (IMINUS DY)
			   WINDOW 0 0 (fetch WRIGHT of TEXTOBJ)
			   LINETOP
			   (QUOTE INPUT)
			   (QUOTE REPLACE))                  (* Move the text down)
		   (BITBLT NIL 0 0 WINDOW 0 (IPLUS LINETOP DY)
			   (fetch WRIGHT of TEXTOBJ)
			   (IMINUS DY)
			   (QUOTE TEXTURE)
			   (QUOTE REPLACE)
			   WHITESHADE)                       (* Now clear the region we moved it out of.)
		   ]
          (RETURN T])

(\TEDIT.BLTCHAR
  [LAMBDA (CHARCODE DISPLAYSTREAM WIDTH CURX DISPLAYDATA DDPILOTBBT DDWIDTHCACHE DDOFFSETCACHE 
		    CLIPRIGHT)                               (* jds "15-Mar-84 16:26")
                                                             (* Version of BLTCHAR peculiar to TEdit -- relies on 
							     \DISPLAYLINE to make sure things keep working right.)

          (* puts a character on a guaranteed display stream. Much of the information needed by the BitBlt microcode is 
	  prestored by the routines that change it. This is kept in the BitBltTable.)

                                                             (* knows about the representation of display stream 
							     image data)
                                                             (* MUST NOT POINT AT A WINDOW'S DISPLAYSTREAM!!!)

          (* ASSUMES THAT WE NEVER WANT TO PRINT TO THE LEFT OF ORIGIN 0 ON THE LINE CACHE BITMAP, OR THAT IF WE DO, ALL 
	  BETS ARE OFF)


    (DECLARE (LOCALVARS . T))
    (PROG (NEWX LEFT RIGHT)
          (SETQ NEWX (IPLUS CURX WIDTH))
          (SETQ LEFT (IMAX 0 CURX))
          (SETQ RIGHT (IMIN CLIPRIGHT NEWX))
          (COND
	    ((ILESSP LEFT RIGHT)                             (* Only print anything if there is a place to put it)
	      (UNINTERRUPTABLY
                  (freplace PBTDESTBIT of DDPILOTBBT with LEFT)
                                                             (* Set up the bitblt-table source left)
		  (freplace PBTWIDTH of DDPILOTBBT with (IMIN (\GETBASE DDWIDTHCACHE CHARCODE)
							      (IDIFFERENCE RIGHT LEFT)))
		  (freplace PBTSOURCEBIT of DDPILOTBBT with (\GETBASE DDOFFSETCACHE CHARCODE))
		  (\PILOTBITBLT DDPILOTBBT 0))
	      T])

(\TEDIT.CLOSEUPLINES
  [LAMBDA (TEXTOBJ PREVLINE NEXTLINE DONTFILLFLG)            (* jds "12-Apr-84 19:34")

          (* Given a gap between PREVLINE and NEXTLINE, move NEXTLINE et seq up to coverthe gap, and adjust the YBOTs.
	  If DONTFILLFLG is T then we're not filling the screen)

                                                             (* PREVLINE = NIL => close it up to the top of the 
							     screen)
                                                             (* NEXTLINE = NIL => remove all lower lines.)
    (SETQ PREVLINE (OR PREVLINE (fetch LINES of TEXTOBJ)))
    (PROG [DY (DS (fetch DS of TEXTOBJ))
	      (WWIDTH (fetch WRIGHT of TEXTOBJ))
	      (LOWESTY (COND
			 (PREVLINE (fetch YBOT of PREVLINE))
			 (T (fetch HEIGHT of (DSPCLIPPINGREGION NIL (\TEDIT.MAINW TEXTOBJ]
          [COND
	    (NEXTLINE                                        (* If the gap isn't at the end, move whatever else up 
							     over it.)
		      [SETQ DY (IDIFFERENCE LOWESTY (IPLUS (fetch YBOT of NEXTLINE)
							   (fetch LHEIGHT of NEXTLINE]
		      (AND (ILEQ DY 0)
			   (RETURN))                         (* If there's no gap, don't bother with anything else.)
		      (BITBLT DS 0 0 DS 0 DY WWIDTH (IPLUS (fetch YBOT of NEXTLINE)
							   (fetch LHEIGHT of NEXTLINE))
			      (QUOTE INPUT)
			      (QUOTE REPLACE))               (* Move the remaining lines upward.)
		      (bind ((LINE ← NEXTLINE)
			     (NYBOT ← LOWESTY))
			 while LINE
			 do                                  (* Scan the remaining lines, fixing up the vertical 
							     spacing information)
			    (SETQ NYBOT (IDIFFERENCE NYBOT (fetch LHEIGHT of LINE)))
			    [COND
			      [(ILEQ (fetch YBOT of LINE)
				     (fetch WBOTTOM of TEXTOBJ))
                                                             (* Line is off screen. Display it at the right spot.)
				(AND DONTFILLFLG (RETURN))   (* If we're not filling the screen, then stop here.)
				(replace YBOT of LINE with NYBOT)
				(replace YBASE of LINE with (IPLUS NYBOT (fetch DESCENT of LINE)))
				(\DISPLAYLINE TEXTOBJ LINE)
				(OR (fetch NEXTLINE of LINE)
				    (IGEQ (fetch CHARLIM of LINE)
					  (fetch TEXTLEN of TEXTOBJ))
				    (PROGN [replace NEXTLINE of LINE
					      with (\FORMATLINE TEXTOBJ NIL
								(ADD1 (fetch CHARLIM of LINE]
					   (replace PREVLINE of (fetch NEXTLINE of LINE)
					      with LINE]
			      (T                             (* Line is visible; just update YBOT/YBASE)
				 (replace YBOT of LINE with NYBOT)
				 (replace YBASE of LINE with (IPLUS (fetch YBOT of LINE)
								    (fetch DESCENT of LINE]
			    (SETQ LOWESTY NYBOT)
			    (SETQ LINE (fetch NEXTLINE of LINE))
			 until (ILEQ NYBOT (fetch WBOTTOM of TEXTOBJ]
          (BITBLT NIL 0 0 DS 0 0 WWIDTH (SUB1 LOWESTY)
		  (QUOTE TEXTURE)
		  (QUOTE REPLACE)
		  WHITESHADE)                                (* Clear the part of the screen below the lowest line 
							     now displayed)
          (RETURN T])

(\TEDIT.CREATE.LINECACHE
  [LAMBDA (#CACHES)                                          (* jds "21-Apr-84 00:58")
                                                             (* Create a linked-together set of LINECACHEs, for 
							     saving line images.)
    (PROG [(CACHES (for I from 1 to #CACHES collect (create LINECACHE
							    LCBITMAP ←(BITMAPCREATE 100 15]
          [for CACHE on CACHES
	     do                                              (* Link the caches together.)
		(replace LCNEXTCACHE of (CAR CACHE) with (OR (CADR CACHE)
							     (CAR CACHES]
          (RETURN CACHES])

(\TEDIT.FIXCHANGEDPART
  [LAMBDA (TEXTOBJ STARTINGLINE WINDOW)                      (* jds " 9-May-84 15:42")
                                                             (* Reformat lines as needed after a change.
							     Return the last line changed, or NIL if there's no need 
							     for a \FILLWINDOW.)
    (PROG ([LINES (fetch NEXTLINE of (WINDOWPROP (OR WINDOW (\TEDIT.MAINW TEXTOBJ))
						 (QUOTE LINES]
	   YBOT
	   (FORMATDONE NIL)
	   [WREG (DSPCLIPPINGREGION NIL (OR WINDOW (\TEDIT.MAINW TEXTOBJ]
	   LIMITCHANGED WASDIRTY CHARLIM OCHLIM OLHEIGHT (PREVLINE NIL)
	   (FOUND NIL)
	   (TEXTLEN (fetch TEXTLEN of TEXTOBJ))
	   WHEIGHT DY OFLOWFN NEWLINE)
          (SETQ WHEIGHT (fetch HEIGHT of WREG))
          [COND
	    [STARTINGLINE                                    (* If we were handed a starting line, use it.)
			  (COND
			    ((ZEROP (fetch CHARLIM of STARTINGLINE))
                                                             (* This is the dummy first line.
							     Skip it.)
			      (replace DIRTY of STARTINGLINE with NIL)
			      (SETQ LINES (fetch NEXTLINE of STARTINGLINE)))
			    (T                               (* Normally, whatever line he says to start with, we 
							     start with)
			       (SETQ LINES STARTINGLINE]
	    (T                                               (* Otherwise, go looking for work)
	       [while LINES
		  do                                         (* Find the first line descriptor of a DIRTY line.)
		     (SETQ YBOT (fetch YBOT of LINES))
		     (COND
		       ((ILEQ YBOT 0)                        (* We've run off the bottom of the screen.)
			 (replace NEXTLINE of (fetch PREVLINE of LINES) with NIL)
                                                             (* There may be unfixed changes there, so chop off any 
							     further lines.)
			 (SETQ LINES NIL))
		       ((fetch DIRTY of LINES)
			 (RETURN))
		       (T (SETQ LINES (fetch NEXTLINE of LINES]
	       (COND
		 ((AND LINES (ILESSP (fetch CHARTOP of LINES)
				     0))                     (* If we hit on the dummy first line, skip over it -- 
							     never try to reformat it.)
		   (SETQ LINES (fetch NEXTLINE of LINES]
          [COND
	    ((NOT LINES)                                     (* No changed lines found -- clear below last line on 
							     screen)
	      (BITBLT NIL 0 0 WINDOW 0 0 (fetch WIDTH of (DSPCLIPPINGREGION NIL WINDOW))
		      YBOT
		      (QUOTE TEXTURE)
		      (QUOTE REPLACE)
		      WHITESHADE)
	      (RETURN (AND (ZEROP TEXTLEN)
			   (fetch LINES of TEXTOBJ]          (* We found no changes; return a NIL last-line-changed)
          (SETQ YBOT (fetch YBOT of (fetch PREVLINE of LINES)))
                                                             (* Y bottom of the first line to reformat.)
          (SETQ CHARLIM (fetch CHAR1 of LINES))              (* SUB1 of char to start formatting with)
          (while (AND LINES (IGREATERP YBOT 0))
	     do                                              (* Fix things up)
		[COND
		  ((IGREATERP CHARLIM (IMIN (fetch CHARLIM of LINES)
					    TEXTLEN))        (* This line has been rendered superfluous -- Delete 
							     it.)
		    (TEDIT.DELETELINE LINES TEXTOBJ))
		  [[OR (fetch DIRTY of LINES)
		       (NOT (IEQP CHARLIM (fetch CHAR1 of LINES]
                                                             (* Only act if this line has changed, or if there is a 
							     gap or overlap between this line and the next.)
		    (SETQ OCHLIM (fetch CHARLIM of LINES))   (* This line's old CHLIM, for seeing if it changes)
		    (SETQ OLHEIGHT (fetch LHEIGHT of LINES))
                                                             (* This line's old height, for seeing if it changes.)
		    (SETQ NEWLINE (\FORMATLINE TEXTOBJ NIL CHARLIM))
                                                             (* Create the fresh line)
		    (COND
		      ((AND (ILESSP (fetch CHAR1 of NEWLINE)
				    (fetch CHAR1 of LINES))
			    (ILESSP (fetch CHARLIM of NEWLINE)
				    (fetch CHARLIM of LINES)))
                                                             (* There is a gap to be filled;
							     insert the new line)
                                                             (* NOTE: The fresh line is inserted only if it isn't 
							     likely to overlay the existing line.
							     This minimizes hiccups and screen movement.)
			(replace YBASE of NEWLINE with (IDIFFERENCE YBOT (fetch ASCENT of NEWLINE)))
                                                             (* Put it in place vertically)
			(replace YBOT of NEWLINE with (IDIFFERENCE YBOT (fetch LHEIGHT of NEWLINE)))
			(\TEDIT.INSERTLINE NEWLINE LINES)    (* And insert it in the chain of line descriptors)
			)
		      (T                                     (* We're starting beyond where this line started;
							     over-write it.)
			 (freplace LEFTMARGIN of LINES with (ffetch LEFTMARGIN of NEWLINE))
			 (freplace RIGHTMARGIN of LINES with (ffetch RIGHTMARGIN of NEWLINE))
			 (freplace LXLIM of LINES with (ffetch LXLIM of NEWLINE))
			 (freplace SPACELEFT of LINES with (ffetch SPACELEFT of NEWLINE))
			 (freplace LHEIGHT of LINES with (ffetch LHEIGHT of NEWLINE))
			 (freplace CHAR1 of LINES with (ffetch CHAR1 of NEWLINE))
			 (freplace CHARLIM of LINES with (ffetch CHARLIM of NEWLINE))
			 (freplace CHARTOP of LINES with (ffetch CHARTOP of NEWLINE))
			 (freplace DIRTY of LINES with NIL)
			 (freplace NEW of LINES with T)
			 (freplace CR\END of LINES with (ffetch CR\END of NEWLINE))
			 (freplace LDOBJ of LINES with (ffetch LDOBJ of NEWLINE))
			 (freplace LHASPROT of LINES with (ffetch LHASPROT of NEWLINE))
			 (freplace LFMTSPEC of LINES with (ffetch LFMTSPEC of NEWLINE))
			 (freplace LTRUEASCENT of LINES with (ffetch LTRUEASCENT of NEWLINE))
			 (freplace LHASTABS of LINES with (ffetch LHASTABS of NEWLINE))
			 (SETQ NEWLINE LINES)                (* And copy it back over the original)
			 ))                                  (* Format a line, starting 1 past the end of the prior 
							     line)
		    (SETQ CHARLIM (ADD1 (fetch CHARLIM of NEWLINE)))
                                                             (* Find the end of the new line 
							     (this MUST be before this COND, because LINES is set to 
							     NIL inside it.))
		    (COND
		      ((IGEQ (fetch YBOT of LINES)
			     WHEIGHT)                        (* Do nothing until we see a change to a line which is 
							     on-screen.)
			(replace YBOT of NEWLINE with (fetch YBOT of LINES))
                                                             (* Except to make sure that the fresh line also thinks 
							     it is off screen)
			)
		      ((AND (IGREATERP (SETQ YBOT (IDIFFERENCE YBOT (fetch LHEIGHT of NEWLINE)))
				       0)
			    (NEQ LINES NEWLINE))             (* If there's space left on the screen for this line, 
							     (and it is a new line))
			(\TEDIT.ADJUST.LINES TEXTOBJ (fetch NEXTLINE of NEWLINE)
					     WINDOW
					     (fetch YBOT of (fetch PREVLINE of NEWLINE))
					     (IMINUS (fetch LHEIGHT of NEWLINE)))
                                                             (* Move the existing lines down to fit it in)
			(replace YBOT of NEWLINE with YBOT)
                                                             (* Display it where we are now)
			(replace YBASE of NEWLINE with (IPLUS YBOT (fetch DESCENT of NEWLINE)))
                                                             (* Base line for the characters to sit on)
			(\DISPLAYLINE TEXTOBJ NEWLINE WINDOW)
                                                             (* Display it)
			)
		      ((IGREATERP YBOT 0)                    (* If there's space left on the screen for this line, 
							     and we're overlaying an existing line.)
			(\TEDIT.ADJUST.LINES TEXTOBJ (fetch NEXTLINE of LINES)
					     WINDOW
					     (IPLUS YBOT (fetch LHEIGHT of LINES)
						    (IMINUS OLHEIGHT))
					     (IDIFFERENCE OLHEIGHT (fetch LHEIGHT of LINES)))
                                                             (* Adjust for the possible difference in heights between
							     old and new line)
			(replace YBOT of LINES with YBOT)    (* Display it where we are now)
			(replace YBASE of LINES with (IPLUS YBOT (fetch DESCENT of LINES)))
                                                             (* Base line for the characters to sit on)
			(\DISPLAYLINE TEXTOBJ LINES WINDOW)
                                                             (* Display it)
			)
		      (T                                     (* We have walked off the bottom of the screen.
							     Chop off the lines from here.)
			 (SETQ LINES NEWLINE)
			 (AND (SETQ OFLOWFN (WINDOWPROP WINDOW (QUOTE TEDIT.OVERFLOWFN)))
			      (APPLY* OFLOWFN WINDOW TEXTOBJ)
			      (RETFROM (QUOTE \TEDIT.FIXCHANGEDPART)))
			 (replace YBOT of LINES with (replace YBASE of LINES with 0))
			 (SETQ YBOT (IPLUS YBOT (fetch LHEIGHT of LINES)))
			 (SETQ PREVLINE LINES)
			 (replace NEXTLINE of PREVLINE with NIL)
			 (SETQ LINES NIL)
			 (RETURN)))
		    (SETQ LINES NEWLINE)                     (* So that if we inserted a line, we start by moving up 
							     to the pre-existing line)
		    (COND
		      ((IGEQ CHARLIM TEXTLEN)                (* We've run off the end of the text.)
			(SETQ PREVLINE LINES)
			(replace NEXTLINE of PREVLINE with NIL)
			(RETURN]
		  (T                                         (* Nothing to do on this line;
							     move the counter up to the next line)
		     (SETQ CHARLIM (ADD1 (fetch CHARLIM of LINES)))
		     (SETQ YBOT (fetch YBOT of LINES]
		(SETQ PREVLINE LINES)                        (* Move to the next line)
		(SETQ LINES (fetch NEXTLINE of LINES)))
          (COND
	    ((ILEQ YBOT 0)                                   (* If we made changes all the way to the bottom of the 
							     screen,)
	      (COND
		(PREVLINE (replace NEXTLINE of PREVLINE with NIL)
			  (BITBLT NIL 0 0 WINDOW 0 0 (fetch WIDTH of (DSPCLIPPINGREGION NIL WINDOW))
				  (fetch YBOT of (fetch PREVLINE of PREVLINE))
				  (QUOTE TEXTURE)
				  (QUOTE REPLACE)
				  WHITESHADE)))              (* Discard any remaining lines below that, to force 
							     reformatting.)
	      (RETURN)                                       (* This prevents loss of changes which go past end of 
							     screen.)
	      )
	    (T                                               (* We didn't go off-screen, but we MAY have lost a line,
							     so clear below the last thing we know of.)
	       (BITBLT NIL 0 0 WINDOW 0 0 (fetch WIDTH of (DSPCLIPPINGREGION NIL WINDOW))
		       YBOT
		       (QUOTE TEXTURE)
		       (QUOTE REPLACE)
		       WHITESHADE)
	       (RETURN PREVLINE])

(\TEDIT.INSERTLINE
  [LAMBDA (NEWLINE BEFORELINE)                               (* jds "15-Mar-84 13:58")
                                                             (* Inserts NEWLINE in front of BEFORELINE in the 
							     line-descriptor chain)
    (PROG ((PREVLINE (fetch PREVLINE of BEFORELINE)))
          (replace PREVLINE of NEWLINE with PREVLINE)
          (replace NEXTLINE of NEWLINE with BEFORELINE)
          (replace PREVLINE of BEFORELINE with NEWLINE)
          (AND PREVLINE (replace NEXTLINE of PREVLINE with NEWLINE])

(\TEDIT.LINECACHE
  [LAMBDA (CACHE WIDTH HEIGHT)                               (* jds "21-Apr-84 00:52")
                                                             (* Given a candidate line cache, return the bitmap, 
							     making sure it's at least WIDTH by HEIGHT big.)
    (PROG ((BITMAP (fetch LCBITMAP of CACHE))
	   CW CH)
          (SETQ CW (fetch BITMAPWIDTH of BITMAP))
          (SETQ CH (fetch BITMAPHEIGHT of BITMAP))
          (COND
	    ((AND (IGEQ CW WIDTH)
		  (IGEQ CH HEIGHT))
	      (RETURN BITMAP))
	    (T (RETURN (replace LCBITMAP of CACHE with (BITMAPCREATE (IMAX CW WIDTH)
								     (IMAX CH HEIGHT])

(\TEDIT.MARK.LINES.DIRTY
  [LAMBDA (TEXTOBJ CH1 CHLIM)                                (* jds "23-Apr-84 16:05")
                                                             (* Mark dirty the lines that intersect the range ch1 t 
							     chlim inclusive)
    (bind (CH# ←(IMIN CH1 (fetch TEXTLEN of TEXTOBJ)))
	  (CHLIM# ←(COND
		    ((IEQP CHLIM -1)
		      (fetch TEXTLEN of TEXTOBJ))
		    (T CHLIM)))
       for WW inside (fetch \WINDOW of TEXTOBJ) do (bind (LL ←(WINDOWPROP WW (QUOTE LINES)))
						      while LL
						      do     (* Mark changed lines as DIRTY.)
							 (COND
							   ((AND (ILEQ (fetch CHAR1 of LL)
								       CHLIM#)
								 (IGEQ (fetch CHARLIM of LL)
								       CH#))
							     (replace DIRTY of LL with T)))
							 (SETQ LL (fetch NEXTLINE of LL])

(\TEDIT.PURGE.SPACES
  [LAMBDA (CHLIST PREVSP)                                    (* jds " 9-NOV-83 17:12")
    (bind OPREVSP while (IGREATERP PREVSP 0)
       do (SETQ OPREVSP (SUB1 PREVSP))
	  (SETQ PREVSP (\EDITELT CHLIST OPREVSP))
	  (\EDITSETA CHLIST OPREVSP (CONSTANT (CHARCODE SPACE])
)
(DECLARE: DONTCOPY
  (FILEMAP (NIL (5387 118143 (TEDIT.CR.UPDATESCREEN 5397 . 16421) (TEDIT.DELETELINE 16423 . 17176) (
TEDIT.INSERT.DISPLAYTEXT 17178 . 23269) (TEDIT.INSERT.UPDATESCREEN 23271 . 34696) (TEDIT.UPDATE.SCREEN
 34698 . 35273) (\BACKFORMAT 35275 . 36944) (\DISPLAYLINE 36946 . 44242) (\DOFORMATTING 44244 . 49235)
 (\FILLWINDOW 49237 . 56131) (\FIXDLINES 56133 . 59840) (\FIXILINES 59842 . 63157) (\FORMATLINE 63159
 . 79356) (\PULLTEXT 79358 . 83928) (\PUSHTEXT 83930 . 92216) (\SHOWTEXT 92218 . 93791) (
\TEDIT.ADJUST.LINES 93793 . 97926) (\TEDIT.BLTCHAR 97928 . 99717) (\TEDIT.CLOSEUPLINES 99719 . 103031)
 (\TEDIT.CREATE.LINECACHE 103033 . 103694) (\TEDIT.FIXCHANGEDPART 103696 . 115622) (\TEDIT.INSERTLINE 
115624 . 116236) (\TEDIT.LINECACHE 116238 . 116924) (\TEDIT.MARK.LINES.DIRTY 116926 . 117828) (
\TEDIT.PURGE.SPACES 117830 . 118141)))))
STOP