(FILECREATED "12-Mar-85 05:49:32" {IVY}<TEDIT>TEDITSCREEN.;51 127085 

      changes to:  (FNS \TEDIT.COPY.LINEDESCRIPTOR \TEDIT.FIXCHANGEDLINE)

      previous date: " 6-Mar-85 23:30:45" {IVY}<TEDIT>TEDITSCREEN.;50)


(* Copyright (c) 1983, 1984, 1985 by John Sybalsky & Xerox Corporation. All rights reserved.)

(PRETTYCOMPRINT TEDITSCREENCOMS)

(RPAQQ TEDITSCREENCOMS ((RECORDS THISLINE LINEDESCRIPTOR LINECACHE)
	(CONSTANTS (LMInvisibleRun 401)
		   (LMLooksChange 400))
	(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.CLEAR.SCREEN.BELOW.LINE \TEDIT.CLOSEUPLINES 
	     \TEDIT.COPY.LINEDESCRIPTOR \TEDIT.CREATE.LINECACHE \TEDIT.FIXCHANGEDLINE 
	     \TEDIT.FIXCHANGEDPART \TEDIT.INSERTLINE \TEDIT.LINE.LIST \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 FULLXPOINTER)                      (* 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.)
			       LHEIGHT                       (* Total height of hte line, Ascent+Descent.)
			       ASCENT                        (* Ascent of the line above YBASE)
			       DESCENT                       (* How far line descends below YBASE)
			       LTRUEDESCENT                  (* The TRUE DESCENT for this line, unadjusted for line 
							     leading.)
			       LTRUEASCENT                   (* The TRUE ASCENT for this line, unadjusted for 
							     pre-paragraph leading.)
			       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))
			       NEXTLINE                      (* Next line chain pointer)
			       (PREVLINE FULLXPOINTER)       (* Previous line chain pointer)
			       LMARK

          (* One of SOLID, GREY, NIL. Tells what kind of special-line marker should be put in the left margin for this 
	  paragraph. (For hardcopy, can also be an indicator for special processing?))


			       LTEXTOBJ                      (* A cached TEXTOBJ that this line took its text from.
							     Used in hardcopy to disambiguate when chno's should be 
							     updated...)
			       CACHE                         (* A cached THISLINE, for keeping hardcopy info around 
							     while we crunch with the line descriptors to make 
							     things fit.)
			       LDOBJ                         (* The object which lies behind this line of text, for 
							     updating, etc.)
			       LFMTSPEC                      (* The format spec for this line's paragraph 
							     (eventually))
			       (DIRTY FLAG)                  (* T if this line has changed since it was last 
							     formatted.)
			       (CR\END FLAG)                 (* T if this line ends with a CR.)
			       (DELETED FLAG)

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


			       (LHASPROT FLAG)               (* This line contains protected text.)
			       (LHASTABS FLAG)

          (* 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.)


			       (1STLN FLAG)                  (* This line is the first line in a paragraph)
			       (LSTLN FLAG)                  (* This is the last line in a paragraph)
			       )
	  CHARLIM ← 1000000 NEXTLINE ← NIL PREVLINE ← NIL 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 (FULLXPOINTER POINTER POINTER POINTER POINTER)))
(/DECLAREDATATYPE (QUOTE LINEDESCRIPTOR)
		  (QUOTE (POINTER POINTER POINTER POINTER POINTER POINTER POINTER POINTER POINTER 
				  POINTER POINTER POINTER POINTER POINTER POINTER FULLXPOINTER 
				  POINTER POINTER POINTER POINTER POINTER FLAG FLAG FLAG FLAG FLAG 
				  FLAG FLAG)))
(/DECLAREDATATYPE (QUOTE LINECACHE)
		  (QUOTE (POINTER FULLXPOINTER)))
(DECLARE: EVAL@COMPILE 

(RPAQQ LMInvisibleRun 401)

(RPAQQ LMLooksChange 400)

(CONSTANTS (LMInvisibleRun 401)
	   (LMLooksChange 400))
)
(FILESLOAD TEXTOFD TEDITLOOKS IMAGEOBJ)
(DEFINEQ

(TEDIT.CR.UPDATESCREEN
  [LAMBDA (CH# XPOINT TEXTOBJ SEL LINE BLANKSEEN CRSEEN DS CHWIDTH DONTSCROLL)
                                                             (* jds "19-Jan-85 15:06")

          (* 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 ((WINDOW (fetch \WINDOW of TEXTOBJ))
	   (PREVLINE (fetch PREVLINE of LINE)))
          (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)
	      (replace TXTNEEDSUPDATE of TEXTOBJ with T)))
          (TEDIT.UPDATE.SCREEN TEXTOBJ PREVLINE T)
          (\FIXSEL SEL TEXTOBJ)
          (\SHOWSEL SEL NIL T)
          (COND
	    (DONTSCROLL                                      (* SO DO NOTHING))
	    ([OR (NOT (fetch NEXTLINE of LINE))
		 (ILEQ (fetch YBOT of (fetch NEXTLINE of LINE))
		       (fetch BOTTOM of (DSPCLIPPINGREGION NIL WINDOW]
                                                             (* This pushed the caret off-screen.
							     Move it up.)
	      (replace EDITOPACTIVE of TEXTOBJ with NIL)
	      (SCROLLW WINDOW 0 (LLSH (fetch LHEIGHT of (COND
							  ((fetch NEXTLINE of LINE))
							  (LINE)))
				      1])

(TEDIT.DELETELINE
  [LAMBDA (LINE TEXTOBJ WINDOW)                              (* jds " 8-Feb-85 18:26")
                                                             (* 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 NIL WINDOW)
                                                             (* And fix up the screen to cover the blank space.)
      ])

(TEDIT.INSERT.DISPLAYTEXT
  [LAMBDA (TEXTOBJ CH CHWIDTH LINE XPOINT DS SEL)            (* jds "13-Dec-84 09:29")
                                                             (* 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)                                       (* Change the font)
          [COND
	    ((IGREATERP (FONTPROP (fetch CLFONT of LOOKS)
				  (QUOTE ASCENT))
			(fetch LTRUEASCENT of LINE))         (* The font this character is in is taller than the 
							     existing line. Adjust the LINEDESCRIPTOR's ascent.)
	      [\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]
                                                             (* Move other text to allow for the new height)
	      (add (fetch (LINEDESCRIPTOR ASCENT) of LINE)
		   (IDIFFERENCE (FONTPROP (fetch CLFONT of LOOKS)
					  (QUOTE ASCENT))
				(fetch LTRUEASCENT of LINE)))
	      (replace (LINEDESCRIPTOR LTRUEASCENT) of LINE with (FONTPROP (fetch CLFONT
									      of LOOKS)
									   (QUOTE ASCENT]
          (COND
	    ((IGREATERP (FONTPROP (fetch CLFONT of LOOKS)
				  (QUOTE DESCENT))
			(fetch LTRUEDESCENT 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 LTRUEDESCENT of LINE)
						(FONTPROP (fetch CLFONT of LOOKS)
							  (QUOTE DESCENT]
	      (add (fetch (LINEDESCRIPTOR DESCENT) of LINE)
		   (IDIFFERENCE (FONTPROP (fetch CLFONT of LOOKS)
					  (QUOTE DESCENT))
				(fetch LTRUEDESCENT of LINE)))
                                                             (* Fix the line's leading-adjusted descent to account 
							     for this change)
	      (replace LTRUEDESCENT of LINE with (FONTPROP (fetch CLFONT of LOOKS)
							   (QUOTE DESCENT)))
                                                             (* Also the unadjusted descent)
	      (replace YBOT of LINE with (IDIFFERENCE (fetch YBASE of LINE)
						      (fetch DESCENT of LINE)))
                                                             (* And note our new location.)
	      ))
          (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 (DSPXPOSITION NIL DS)
								   (fetch YBOT of LINE)
								   36
								   (fetch LHEIGHT of LINE)
								   (QUOTE TEXTURE)
								   (QUOTE REPLACE)
								   WHITESHADE)
							   (RELMOVETO 36 0 DS))
						      (CR (BITBLT NIL 0 0 DS (DSPXPOSITION NIL DS)
								  (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 (DSPXPOSITION NIL DS)
					   (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 (DSPXPOSITION NIL DS)
					  (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 OTEXTLEN BLANKSEEN CRSEEN DONTSCROLL INCREMENTAL)
                                                             (* jds " 5-Mar-85 16:57")
                                                             (* 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
	    ((AND INCREMENTAL (\SYSBUFP))                    (* We're doing incremental updates, and there's type-in
							     waiting. Bail out, now that we have fixed up the 
							     selection.)
	      (RETURN))
	    ((NOT WINDOW)                                    (* If this textobj has no window to update, don't 
							     bother)
	      (RETURN))
	    ((OR T (LISTP WINDOW)
		 (TEXTPROP TEXTOBJ (QUOTE SLOWUPDATE)))      (* FOR NOW, ALWAYS UPDATE THE SCREEN THE HARD WAY)
	      (TEDIT.UPDATE.SCREEN TEXTOBJ NIL T (fetch CH# of SEL))
	      (\FIXSEL SEL TEXTOBJ)
	      (\SHOWSEL SEL NIL T))
	    [LINES                                           (* 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 (SELECTION 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 DONTSCROLL)) ((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) (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.ADJUST.LINES TEXTOBJ 
	  (fetch NEXTLINE of LINE) WINDOW (fetch YBOT of LINE) (IDIFFERENCE OLHEIGHT (fetch LHEIGHT of LINE))) 
	  (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 OLHEIGHT)) (\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 OLHEIGHT 
	  (QUOTE INPUT) (QUOTE REPLACE)) (\TEDIT.ADJUST.LINES TEXTOBJ LINE DS (IPLUS (fetch YBOT of LINE) 
	  (IMIN OLHEIGHT (fetch LHEIGHT of LINE))) (IDIFFERENCE OLASCENT (fetch ASCENT of LINE))) (\TEDIT.ADJUST.LINES TEXTOBJ
	  NEXTLINE WINDOW (fetch YBOT of LINE) (IDIFFERENCE OLDESCENT (fetch DESCENT of LINE))) (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 
	  OLDESCENT)) (T (\TEDIT.ADJUST.LINES TEXTOBJ LINE DS (IPLUS (fetch YBOT of LINE) (IMIN OLHEIGHT 
	  (fetch LHEIGHT of LINE))) (IDIFFERENCE OLASCENT (fetch ASCENT of LINE))) (\TEDIT.ADJUST.LINES TEXTOBJ NEXTLINE 
	  WINDOW (fetch YBOT of LINE) (IDIFFERENCE OLDESCENT (fetch DESCENT of LINE))) (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 ((IGEQ (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 
	  (TEXTPROP TEXTOBJ (QUOTE 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)))


		   ]
	    (NIL 

          (* (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)
          [for WW inside WINDOW as L1 inside (fetch L1 of SEL) as LN inside (fetch LN of SEL)
	     do (COND
		  (DONTSCROLL                                (* If scrolling is suppressed, don't bother with the 
							     next check:)
			      (\TEDIT.SET.WINDOW.EXTENT TEXTOBJ WW))
		  [(EQ WW (fetch SELWINDOW of TEXTOBJ))
		    (COND
		      ([OR (NULL (SELECTQ (fetch POINT of SEL)
					  (LEFT L1)
					  (RIGHT LN)
					  NIL))
			   (ILEQ (SELECTQ (fetch POINT of SEL)
					  (LEFT (fetch YBOT of L1))
					  (RIGHT (fetch YBOT of LN))
					  0)
				 (fetch BOTTOM of (DSPCLIPPINGREGION NIL WW]
                                                             (* The caret is off-window in the selection window.
							     Need to scroll it up so the caret is visible.)
			(while (OR (ILESSP (fetch Y0 of SEL)
					   (fetch WBOTTOM of TEXTOBJ))
				   (IGEQ (fetch Y0 of SEL)
					 (fetch WTOP of TEXTOBJ)))
			   do                                (* The caret just went off-screen.
							     Move it up some.)
			      (replace EDITOPACTIVE of TEXTOBJ with NIL)
			      (SCROLLW WW 0 (LLSH (COND
						    [(SELECTQ (fetch POINT of SEL)
							      (LEFT L1)
							      (RIGHT LN)
							      NIL)
						      (fetch LHEIGHT
							 of (SELECTQ (fetch POINT of SEL)
								     (LEFT L1)
								     (RIGHT LN)
								     (SHOULDNT]
						    (T 12))
						  1]
		  (T (\TEDIT.SET.WINDOW.EXTENT TEXTOBJ WW]
          (\COPYSEL SEL TEDIT.SELECTION])

(TEDIT.UPDATE.SCREEN
  [LAMBDA (TEXTOBJ STARTINGLINE INCREMENTAL? NEXTCARETCH#)   (* jds "22-Feb-85 16:35")
                                                             (* Update the screen, as needed to fix up "dirty" 
							     lines.)
    (SETQ TEXTOBJ (TEXTOBJ TEXTOBJ))
    (bind NLINE for WW inside (fetch \WINDOW of TEXTOBJ) as LINE inside (OR STARTINGLINE
									    (fetch LINES
									       of TEXTOBJ))
       do (SETQ NLINE (\TEDIT.FIXCHANGEDPART TEXTOBJ LINE WW INCREMENTAL? NEXTCARETCH#)) 
                                                             (* The last line in the edit window)
	  (AND NLINE (\FILLWINDOW (fetch YBOT of NLINE)
				  NLINE TEXTOBJ NIL WW])

(\BACKFORMAT
  [LAMBDA (LINES TEXTOBJ)                                    (* jds " 1-Mar-85 15:02")
                                                             (* Move back to the next preceding CR 
							     (to guarantee a line break), then format lines to reach
							     where we are now.)
                                                             (* LINES is the dummy first line for this window in 
							     TEXTOBJ)

          (* Returns a pointer to the last of the back-formatted lines (i.e., the one that comes latest in the document), or 
	  to LINES if no lines are formatted)


    (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                                         (* Back up until we find a CR)
		     (SETQ CH (\GETCHB TEXTOBJ))
		     (COND
		       ((EQ CH (CHARCODE CR))
			 (RETURN]
	       (SETQ CHNO (IMAX (ADD1 CHNO)
				1))                          (* But never further than the front of the document)
	       (while (ILEQ CHNO (SUB1 CH1))
		  do                                         (* Now move forward, formatting lines until we catch up
							     with where we were.)
		     (SETQ NLINE (\FORMATLINE TEXTOBJ NIL CHNO)) 
                                                             (* Format the next line)
		     (replace YBOT of NLINE with WHEIGHT)    (* Make sure it thinks it's off-window)
		     (replace YBASE of NLINE with WHEIGHT)
		     (replace PREVLINE of NLINE with LINES) 
                                                             (* Hook it onto the end of the chain)
		     (replace NEXTLINE of LINES with NLINE)
		     (SETQ LINES NLINE)
		     (SETQ CHNO (ADD1 (fetch CHARLIM of NLINE))) 
                                                             (* And find the start of the next line))
	       (replace NEXTLINE of NLINE with LINE1)        (* Now, with the final line we formatted, hook the rest
							     of the line chain onto it.)
	       (AND LINE1 (replace PREVLINE of LINE1 with NLINE))
	       (RETURN NLINE])

(\DISPLAYLINE
  [LAMBDA (TEXTOBJ LINE WINDOW)                              (* jds " 6-Mar-85 23:00")
                                                             (* 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 (CAR (fetch \WINDOW 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)
	      (DSPCLIPPINGREGION (create REGION
					 LEFT ← 0
					 BOTTOM ← 0
					 WIDTH ←(fetch BITMAPWIDTH of CACHE)
					 HEIGHT ←(fetch BITMAPHEIGHT of CACHE))
				 DS)))
          (BITBLT NIL 0 0 CACHE 0 0 NIL NIL (QUOTE TEXTURE)
		  (QUOTE REPLACE)
		  WHITESHADE)                                (* Clear the line cache)
          [COND
	    ((AND (NOT (ZEROP (fetch CHAR1 of LINE)))
		  (ILEQ (fetch CHAR1 of LINE)
			TEXTLEN)
		  (IGEQ (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)
		      (IPLUS (fetch YBASE of LINE)
			     (fetch WBOTTOM of TEXTOBJ))
		      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))
	      (SETQ OFONT (DSPFONT (fetch CLFONT of (SETQ OLOOKS (\EDITELT LOOKS 0)))
				   DS))                      (* The starting font)
	      (SETQ DDWIDTHCACHE (ffetch DDWIDTHSCACHE of DISPLAYDATA))
                                                             (* Cache the character-image widths)
	      (SETQ DDOFFSETCACHE (ffetch DDOFFSETSCACHE of DISPLAYDATA))
                                                             (* And the offset-into-strike-bitmap array)
	      (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))                           (* Any sub- or superscripting at start of line)
	      (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))            (* Grab the character (or IMAGEOBJ) to display)
		    (SETQ DX (\WORDELT WLIST I))             (* And its width)
		    [SELECTC CH
			     (LMInvisibleRun                 (* An INVISIBLE run -- skip it, and skip over the char 
							     count)
					     (add LOOKNO 1))
			     (LMLooksChange                  (* 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))
                                                             (* Cache the new widths and offsets from the new font)
					    (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.)
				  (DSPFONT (fetch CLFONT of OLOOKS)
					   DS)
				  (MOVETO (IDIFFERENCE TX XOFFSET)
					  CURY DS)           (* Move to after the object's image)
				  ]
		    (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))                           (* Paint the cached image on the screen 
							     (this lessens flicker during update))
          (SELECTQ (fetch LMARK of LINE)
		   (GREY                                     (* This line has some property that isn't visible to 
							     the user. Tell him to be careful)
			 (BITBLT NIL 0 0 WINDOWDS 0 (fetch YBASE of LINE)
				 4 4 (QUOTE TEXTURE)
				 (QUOTE PAINT)
				 42405))
		   (SOLID                                    (* This line has some property that isn't visible to 
							     the user. Tell him to be careful)
			  (BITBLT NIL 0 0 WINDOWDS 0 (fetch YBASE of LINE)
				  4 4 (QUOTE TEXTURE)
				  (QUOTE PAINT)
				  BLACKSHADE))
		   (BITBLT NIL 0 0 WINDOWDS 0 (fetch YBASE of LINE)
			   4 4 (QUOTE TEXTURE)
			   (QUOTE REPLACE)
			   WHITESHADE])

(\DOFORMATTING
  [LAMBDA (TEXTOBJ LINE FMTSPEC THISLINE #BLANKS PREVSP 1STLN)
                                                             (* jds "16-Jan-85 14:18")
                                                             (* 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 LTRUEDESCENT of LINE with (fetch DESCENT of LINE))
          (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
		(T (add (fetch LHEIGHT of LINE)
			(fetch LINELEAD of FMTSPEC))         (* And adjust the line's descent accordingly)
		   (add (fetch DESCENT of LINE)
			(fetch LINELEAD of FMTSPEC]
          [COND
	    ((AND 1STLN (fetch LEADBEFORE of FMTSPEC))       (* If paragraph pre-leading was specified, set it)
	      (add (fetch LHEIGHT of LINE)
		   (fetch LEADBEFORE of FMTSPEC))            (* And adjust the line's ascent accordingly.)
	      (add (fetch ASCENT of LINE)
		   (fetch LEADBEFORE of FMTSPEC]
          (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))
			  (COND
			    ((OR (ILESSP (fetch LEN of THISLINE)
					 0)
				 (ZEROP #BLANKS)
				 (ZEROP PREVSP))             (* For empty lines, and lines with no spaces, don't 
							     bother fixing blank widths.)
			      (RETURN]
		   [CENTERED                                 (* Split the difference for centering)
			     (add (fetch LEFTMARGIN of LINE)
				  (LRSH SPACELEFT 6))
			     (add (fetch LXLIM of LINE)
				  (LRSH SPACELEFT 6))
			     (COND
			       ((OR (ILESSP (fetch LEN of THISLINE)
					    0)
				    (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 (ILESSP (fetch LEN of THISLINE)
					     0)
				     (ZEROP #BLANKS)
				     (ZEROP PREVSP))         (* For empty lines, and lines with no spaces, don't 
							     bother fixing blank widths.)
				  (RETURN)))
			      (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))
				((IEQP PREVSP (ADD1 (fetch LEN of THISLINE)))
                                                             (* Only if the last character on the line is a space 
							     should we remove trailing spaces from the list)
				  (bind (OPREVSP ←(SUB1 PREVSP)) while (AND (IGREATERP PREVSP 0)
									    (ILEQ OPREVSP PREVSP))
				     do 

          (* Back up over all trailing white space on the line. So that those blanks don't get counted when computing the 
	  space to be added to each REAL space on the line, when it is justified.)


					(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.)
				  )
				(T (SETQ EXTRASP 0)))
			      [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)                (* Change all the spaces--chained for 
							     justification--back into regular spaces, for the 
							     display code.)
      ])

(\FILLWINDOW
  [LAMBDA (YBOT CURLINE TEXTOBJ DONTFILLFLG WINDOW)          (* jds "22-Feb-85 17:08")
                                                             (* 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)))
	   NEXTLINE OFLOWFN)
          (SETQ WHEIGHT (fetch WTOP of TEXTOBJ))
          (replace TXTNEEDSUPDATE of TEXTOBJ with NIL)
          (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 (IGEQ (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 (TEXTPROP TEXTOBJ (QUOTE 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)
		       (AND (IEQP CHARLIM TEXTLEN)
			    (fetch CR\END of CURLINE))
		       (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 (SETQ NEXTLINE (fetch NEXTLINE of PREVLINE)))
		    (replace NEXTLINE of PREVLINE with LINE)
		    (AND NEXTLINE (replace PREVLINE of NEXTLINE with LINE))
		    (COND
		      ((IGEQ (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 (TEXTPROP TEXTOBJ (QUOTE 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                                         (* Otherwise, note that we ran off the end of the 
							     file.)
		     (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 (SUB1 (fetch WBOTTOM of TEXTOBJ]
		(SETQ LINE (fetch NEXTLINE of LINE)))
          (COND
	    ((IGEQ YBOT (fetch WBOTTOM of TEXTOBJ))          (* If there is space left at the bottom of the window, 
							     blank it out.)
	      (BITBLT NIL 0 0 WINDOW 0 (fetch WBOTTOM of TEXTOBJ)
		      (fetch WRIGHT of TEXTOBJ)
		      (IDIFFERENCE YBOT (fetch WBOTTOM of TEXTOBJ))
		      (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))                            (* If the last line ends in a CR, put a dummy line 
							     below it.)
	      [SETQ LINE (replace NEXTLINE of PREVLINE with (\FORMATLINE TEXTOBJ NIL (ADD1 TEXTLEN]
	      (replace PREVLINE of LINE with PREVLINE)
	      (replace YBOT of LINE with (IDIFFERENCE (fetch YBOT of PREVLINE)
						      (fetch LHEIGHT of LINE)))
	      (replace YBASE of LINE with (IDIFFERENCE (fetch YBOT of PREVLINE)
						       (fetch ASCENT of LINE)))
	      (replace CHARLIM of LINE with (ADD1 TEXTLEN))
	      (SETQ PREVLINE LINE)))
          (COND
	    ((AND (IGEQ (fetch CHARLIM of PREVLINE)
			TEXTLEN)
		  (NOT (fetch CR\END of PREVLINE)))          (* 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 " 6-Mar-85 21:24")
                                                             (* 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 (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)
			      (replace TXTNEEDSUPDATE of TEXTOBJ 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)
			      (replace TXTNEEDSUPDATE of TEXTOBJ with T]
			((IGEQ 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)
			     (IGEQ 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 TXTNEEDSUPDATE of TEXTOBJ with T)
			  (replace CHAR1 of LINE with (IMAX 1 (IMIN CHAR1 CH#1)))
			  (COND
			    [(IGEQ CHARLIM CH#LIM)
			      (replace CHARLIM of LINE with (IDIFFERENCE CHARLIM
									 (IMIN DCH (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 "19-Jan-85 16:51")
                                                             (* 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.)
          [for WW inside (ffetch \WINDOW of TEXTOBJ) as LINES inside (fetch LINES of TEXTOBJ)
	     as L1 in (fetch L1 of SEL)
	     do                                              (* For each pane in the editing window, examine the 
							     pane's list of 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 L1))                 (* 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)
			  (replace TXTNEEDSUPDATE of TEXTOBJ with T))
			((IGEQ (ffetch CHARTOP of LINE)
			       CH#1)                         (* This line spans the insert point.
							     Mark it DIRTY.)
			  (freplace DIRTY of LINE with T)
			  (replace TXTNEEDSUPDATE of TEXTOBJ 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)
			  (replace TXTNEEDSUPDATE of TEXTOBJ 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]
          (\TEDIT.FIXINSSEL (fetch MOVESEL of TEXTOBJ)
			    TEXTOBJ CH#1 DCH)
          (\TEDIT.FIXINSSEL (fetch SHIFTEDSEL of TEXTOBJ)
			    TEXTOBJ CH#1 DCH)
          (\TEDIT.FIXINSSEL SEL TEXTOBJ CH#1 DCH])

(\FORMATLINE
  [LAMBDA (TEXTOBJ FMTSPEC CH#1 OLINE 1STLN)                 (* jds " 8-Feb-85 18:19")
                                                             (* Given a starting place, format the next line of 
							     text. Return the LINEDESCRIPTOR;
							     reusing OLINE if it's given.)

          (* If CH#1 is past end of document, \FORMATLINE returns an empty line descriptor that is set up right wrt leading 
	  and font. This is used by \FILLWINDOW to create the dummy line at end of document when you hit a CR there.)


    (PROG (TX [LINE (OR OLINE (create LINEDESCRIPTOR
				      RIGHTMARGIN ←(fetch WRIGHT of TEXTOBJ)
				      YBOT ←(SUB1 (fetch WBOTTOM 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)
	      (DS (WINDOWPROP (CAR (fetch \WINDOW of TEXTOBJ))
			      (QUOTE DSP)))
	      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 LOOKSUPDATEFN of TEXTSTREAM with (FUNCTION \TEDIT.LOOKS.UPDATE))
          (freplace CHARLIM of LINE with TEXTLEN)            (* Force each new line to find its true CHARLIM.)
          (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)))
	      (replace LHASPROT of LINE with (fetch CLPROTECTED of CLOOKS))
                                                             (* Remember if the first character on the line is 
							     protected.)
	      (SETQ FONT (FONTCOPY (fetch CLFONT of CLOOKS)
				   (QUOTE DEVICE)
				   (QUOTE DISPLAY)))         (* Grab the initial font for this line)
	      [SETQ ASCENTB (SETQ ASCENT (IMAX ASCENT (IPLUS (fetch \SFAscent of FONT)
							     (OR (fetch CLOFFSET of CLOOKS)
								 0]
                                                             (* The initial ascent, per the initial font)
	      [SETQ DESCENTB (SETQ DESCENT (IMAX DESCENT (IDIFFERENCE (fetch \SFDescent of FONT)
								      (OR (fetch CLOFFSET
									     of CLOOKS)
									  0]
                                                             (* Initial descent, per the initial font.)
	      [SETQ FONTWIDTHS (COND
		  (TERMSA (\TEDIT.GET.TERMSA.WIDTHS TERMSA FONT))
		  (T (fetch \SFWidths of FONT]               (* Cache the character width table for use in finding 
							     the line break)
	      (\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]
                                                             (* If this is the start of a paragraph, mark it so.)
	      (replace LMARK of LINE with NIL)               (* Start by assuming that we don't want a margin marker
							     for this line.)
	      (replace 1STLN of LINE with 1STLN)             (* Are we on the first line of a paragraph?)
	      [COND
		(1STLN                                       (* This is the first line of a paragraph.
							     Check for special paragraph types, like headings, that 
							     get marked in the margin.)
		       (COND
			 ((EQ (fetch FMTPARATYPE of FMTSPEC)
			      (QUOTE PAGEHEADING))
			   (replace LMARK of LINE with (QUOTE GREY)))
			 ((OR (fetch FMTNEWPAGEBEFORE of FMTSPEC)
			      (fetch FMTNEWPAGEAFTER of FMTSPEC))
			   (replace LMARK of LINE with (QUOTE GREY)))
			 ([AND (fetch FMTSPECIALX of FMTSPEC)
			       (NOT (ZEROP (fetch FMTSPECIALX of FMTSPEC]
			   (replace LMARK of LINE with (QUOTE GREY)))
			 ([AND (fetch FMTSPECIALY of FMTSPEC)
			       (NOT (ZEROP (fetch FMTSPECIALY of FMTSPEC]
			   (replace LMARK of LINE with (QUOTE GREY]
	      [SETQ TX (replace LEFTMARGIN of LINE with (IPLUS 8 (fetch WLEFT of TEXTOBJ)
							       (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 when (SETQ CH
										     (\BIN TEXTSTREAM)
										     )
		 do                                          (* The character loop)
                                                             (* 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 DS 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)
			   (COND
			     ([NEQ 1 (fetch PLEN of (SETQ PC (fetch (TEXTSTREAM PIECE) of TEXTSTREAM]

          (* The object is several chars wide, but doesn't have a subsidiary stream to pull those chars from.
	  Build an invisible run to fill the space.)


			       (add LOOKNO 1)                (* Fix the counter of charlooks changes)
			       (\EDITSETA LOOKS LOOKNO (SUB1 (fetch PLEN of PC)))
			       (\RPLPTR CHLIST 0 LMInvisibleRun)
                                                             (* Note the existence of an invisible run of characters
							     here.)
			       (\PUTBASE WLIST 0 0)
			       (add TLEN 1)
			       (SETQ CHLIST (\ADDBASE CHLIST 2))
			       (SETQ WLIST (\ADDBASE WLIST 1))
			       (add CHNO (SUB1 (fetch PLEN of PC)))
			       (add INVISIBLERUNS (\EDITELT LOOKS LOOKNO))
                                                             (* Keep track of how much invisible text we cross over)
			       ))
			   (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))
				  (replace LSTLN of LINE with T)
                                                             (* This has to be done better when we get non-para 
							     breaking CRs.)
				  (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 NIL))
                                                             (* 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 (IMAX (SUB1 CHNO)
										  CH#1))
					     (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 T))
                                                             (* Finish up processing the outstanding TAB.
							     We get back the new X position, with that taken into 
							     account.)
			    (SETQ TX TABPENDING)
			    (SETQ TABPENDING NIL)
			    (\TEDIT.PURGE.SPACES (fetch CHARS of THISLINE)
						 PREVSP)     (* Don't use the spaces before the TAB in 
							     justification.)
			    (SETQ PREVSP 0]
	    (T                                               (* No text to go in this line;
							     set Ascent/Descent to the default font from the 
							     window.)
	       [SETQ PC (AND (IGREATERP TEXTLEN 0)
			     (\CHTOPC TEXTLEN (fetch PCTB of TEXTOBJ]
                                                             (* Grab the last real part of the document, to get 
							     paragraph looks)
	       (SETQ FONT (OR (AND (fetch CARETLOOKS of TEXTOBJ)
				   (fetch CLFONT of (fetch CARETLOOKS of TEXTOBJ)))
			      (AND (fetch DEFAULTCHARLOOKS of TEXTOBJ)
				   (fetch CLFONT of (fetch DEFAULTCHARLOOKS of TEXTOBJ)))
			      DEFAULTFONT))                  (* The font we use is preferably the caret looks, else 
							     the default for this edit, else the system default)
	       (SETQ ASCENT (FONTPROP FONT (QUOTE ASCENT)))
	       (SETQ DESCENT (FONTPROP FONT (QUOTE DESCENT)))
	       (SETQ FMTSPEC (OR FMTSPEC (AND PC (fetch PPARALOOKS of PC))
				 (fetch FMTSPEC of TEXTOBJ)))
                                                             (* Use the preceding paragraph's looks)
	       (SETQ 1STLN (OR (NOT PC)
			       (fetch PPARALAST of PC)))
	       (replace 1STLN of LINE with 1STLN)
	       [SETQ TX (COND
		   [1STLN (replace LEFTMARGIN of LINE with (IPLUS 8 (fetch WLEFT of TEXTOBJ)
								  (fetch 1STLEFTMAR of FMTSPEC]
		   (T (replace LEFTMARGIN of LINE with (IPLUS 8 (fetch WLEFT of TEXTOBJ)
							      (fetch LEFTMAR 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)))
							  DEFAULTFONT)
						      (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 LOOKSUPDATEFN of TEXTSTREAM with NIL)
          (RETURN LINE])

(\PULLTEXT
  [LAMBDA (LINE DX CH1 TEXTOBJ)                              (* jds "18-Jan-85 08: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)) (OLEFTMAR (fetch LEFTMARGIN of LINE)) 
	  (OLHEIGHT (fetch LHEIGHT of LINE)) (OLASCENT (fetch ASCENT of LINE)) (OLDESCENT (fetch DESCENT 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) (\TEDIT.ADJUST.LINES TEXTOBJ LINE DS (IPLUS (fetch YBOT of LINE) 
	  (IMIN OLHEIGHT (fetch LHEIGHT of LINE))) (IDIFFERENCE OLASCENT (fetch ASCENT of LINE))) (* Allow for differences in 
	  ascent of the line) (\TEDIT.ADJUST.LINES TEXTOBJ NEXTLINE WINDOW (fetch YBOT of LINE) (IDIFFERENCE OLDESCENT 
	  (fetch DESCENT of LINE))) (COND ((NOT (ZEROP (SETQ NDX (IDIFFERENCE (IDIFFERENCE (fetch LXLIM of LINE) 
	  (fetch LEFTMARGIN of LINE)) (IDIFFERENCE OXLIM OLEFTMAR))))) (* The line length changed from what we'd expected.
	  Some text got moved up from below.) (COND ((ILESSP NDX 0) (ERROR "Moving Text down after DEL."
	  NDX)) (T (COND ((AND (SETQ NLINE (fetch NEXTLINE of LINE)) (IGEQ (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 (IPLUS (fetch YBOT of LINE) (IDIFFERENCE (fetch DESCENT of LINE) 
	  (fetch DESCENT of NLINE))) NDX (IMIN (fetch LHEIGHT of LINE) (fetch LHEIGHT of NLINE)) (QUOTE INPUT) 
	  (QUOTE PAINT)) (* 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 
	  (fetch WBOTTOM of TEXTOBJ) (fetch WRIGHT of TEXTOBJ) (IDIFFERENCE (SUB1 (fetch YBOT of LINE)) 
	  (fetch WBOTTOM of TEXTOBJ)) (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 PREVDESCENT)
                                                             (* jds "18-Jan-85 08:36")
                                                             (* 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)) (OLASCENT (fetch ASCENT of LINE)) (OLDESCENT (fetch DESCENT 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) (\TEDIT.ADJUST.LINES TEXTOBJ 
	  LINE DS (IPLUS (fetch YBOT of LINE) (IMIN OLHEIGHT (fetch LHEIGHT of LINE))) (IDIFFERENCE OLASCENT 
	  (fetch ASCENT of LINE))) (\TEDIT.ADJUST.LINES TEXTOBJ NEXTLINE WINDOW (fetch YBOT of LINE) (IDIFFERENCE OLDESCENT 
	  (fetch DESCENT of 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 (TEXTPROP TEXTOBJ (QUOTE 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 ((IGEQ (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 
	  (TEXTPROP TEXTOBJ (QUOTE 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 ((IGEQ (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.) 
	  (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) (IPLUS (fetch YBOT of LINE) (IDIFFERENCE PREVDESCENT 
	  (fetch DESCENT of LINE))) SAVEWIDTH (fetch LHEIGHT of LINE) (QUOTE INPUT) (QUOTE PAINT)) (* 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 
	  (fetch DESCENT of LINE))) (* Now propogate the change to the next line.))) (replace DIRTY of LINE with NIL) 
	  (RETURN T)))


    ])

(\SHOWTEXT
  [LAMBDA (TEXTOBJ LINES WINDOW)                             (* jds "21-Dec-84 16:07")
                                                             (* 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.PRIMARYW TEXTOBJ)))
	      (DSPFILL (CREATEREGION (fetch WLEFT of TEXTOBJ)
				     (fetch WBOTTOM of TEXTOBJ)
				     (IDIFFERENCE (fetch WRIGHT of TEXTOBJ)
						  (fetch WLEFT of TEXTOBJ))
				     (IDIFFERENCE (fetch WTOP of TEXTOBJ)
						  (fetch WBOTTOM of TEXTOBJ)))
		       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 WTOP of TEXTOBJ)
						    CHAR1 ← 0
						    CHARLIM ← 0
						    SPACELEFT ← -1
						    RIGHTMARGIN ←(SUB1 (fetch WRIGHT of TEXTOBJ))
						    NEXTLINE ← NIL
						    CHARTOP ← -1
						    LHEIGHT ← 0
						    LXLIM ←(fetch WRIGHT of TEXTOBJ)
						    CR\END ← T
						    ASCENT ← 0
						    DESCENT ← 0
						    LTRUEASCENT ← 0))
                                                             (* Make sure we have the anchor pseudo-line)
				(WINDOWPROP WINDOW (QUOTE LINES)
					    LINES)
				(\FILLWINDOW (fetch WTOP of TEXTOBJ)
					     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 " 5-Feb-85 10:28")

          (* 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
	    ((ZEROP DY)                                      (* This line's total height HAS NOT CHANGED.
							     Don't make any adjustments.)
	      )
	    ((ILESSP LINETOP (fetch WBOTTOM of TEXTOBJ))     (* This line is off the screen.
							     Don't bother adjusting it.)
	      )
	    (T                                               (* This line's total height changed -- must move the 
							     rest of the window, and adjust YBOT/BASEs.)
	       (bind (LL ← FIRSTLINE) while (AND LL (IGEQ (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
		       ((ILESSP (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 (TEXTPROP TEXTOBJ (QUOTE OVERFLOWFN)))
				 (SETQ OFLOW T)
				 (APPLY* OFLOWFN WINDOW TEXTOBJ)
				 (RETURN NIL))               (* We walked off the bottom, and the user gave us an 
							     OFLOWFN to handle it. Give it a try.)
			     ]
		     (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 (fetch WBOTTOM of TEXTOBJ)
			   WINDOW 0 (IPLUS DY (fetch WBOTTOM of TEXTOBJ))
			   (fetch WRIGHT of TEXTOBJ)
			   LINETOP
			   (QUOTE INPUT)
			   (QUOTE REPLACE))                  (* Move the text up)
		   (BITBLT NIL 0 0 WINDOW 0 (fetch WBOTTOM of TEXTOBJ)
			   (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 (IGEQ (fetch YBOT of PREVLINE)
					  (fetch WBOTTOM of TEXTOBJ)))
                                                             (* 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 (IPLUS (fetch WBOTTOM of TEXTOBJ)
					    (IMINUS DY))
			    WINDOW 0 (fetch WBOTTOM of TEXTOBJ)
			    (fetch WRIGHT of TEXTOBJ)
			    (IDIFFERENCE LINETOP (fetch WBOTTOM of TEXTOBJ))
			    (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.CLEAR.SCREEN.BELOW.LINE
  [LAMBDA (TEXTOBJ WINDOW LINE)                              (* jds "17-Jan-85 12:38")
                                                             (* Clears the edit window to white, clearing only the 
							     sapce below the line given.)
    (BITBLT NIL 0 0 WINDOW 0 (fetch WBOTTOM of TEXTOBJ)
	    (fetch WRIGHT of TEXTOBJ)
	    (IDIFFERENCE (fetch YBOT of LINE)
			 (fetch WBOTTOM of TEXTOBJ))
	    (QUOTE TEXTURE)
	    (QUOTE REPLACE)
	    WHITESHADE])

(\TEDIT.CLOSEUPLINES
  [LAMBDA (TEXTOBJ PREVLINE NEXTLINE DONTFILLFLG WINDOW)     (* jds "10-Feb-85 17:17")

          (* 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 (WWIDTH (IDIFFERENCE (fetch WRIGHT of TEXTOBJ)
				   (fetch WLEFT of TEXTOBJ)))
	      (LOWESTY (COND
			 (PREVLINE (fetch YBOT of PREVLINE))
			 (T (ADD1 (fetch WTOP of 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 WINDOW (fetch WLEFT of TEXTOBJ)
			      (fetch WBOTTOM of TEXTOBJ)
			      WINDOW
			      (fetch WLEFT of TEXTOBJ)
			      (IPLUS DY (fetch WBOTTOM of TEXTOBJ))
			      WWIDTH
			      (IPLUS (IDIFFERENCE (fetch YBOT of NEXTLINE)
						  (fetch WBOTTOM of TEXTOBJ))
				     (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
			      ((IGEQ NYBOT (fetch WBOTTOM of TEXTOBJ))
				(SETQ LOWESTY NYBOT)))
			    [COND
			      [(ILESSP (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 WINDOW)
				(COND
				  ((fetch NEXTLINE of LINE)
                                                             (* There's a next line after the current one.
							     Use it)
				    )
				  ((IGEQ (fetch CHARLIM of LINE)
					 (fetch TEXTLEN of TEXTOBJ))
                                                             (* We're at the end of the text;
							     don't bother trying to add more lines)
				    )
				  (T                         (* There's more; try adding another line.)
				     [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 LINE (fetch NEXTLINE of LINE))
			 until (ILESSP NYBOT (fetch WBOTTOM of TEXTOBJ]
          (BITBLT NIL 0 0 WINDOW (fetch WLEFT of TEXTOBJ)
		  (fetch WBOTTOM of TEXTOBJ)
		  WWIDTH
		  (IDIFFERENCE LOWESTY (fetch WBOTTOM of TEXTOBJ))
		  (QUOTE TEXTURE)
		  (QUOTE REPLACE)
		  WHITESHADE)                                (* Clear the part of the screen below the lowest line 
							     now displayed)
          (RETURN T])

(\TEDIT.COPY.LINEDESCRIPTOR
  [LAMBDA (FROMLINE TOLINE)                                  (* jds "12-Mar-85 04:23")
                                                             (* Copy the contents of one line descriptor into 
							     another -- except for chaining and Y-location info.)
    (freplace LEFTMARGIN of TOLINE with (ffetch LEFTMARGIN of FROMLINE))
    (freplace RIGHTMARGIN of TOLINE with (ffetch RIGHTMARGIN of FROMLINE))
    (freplace LXLIM of TOLINE with (ffetch LXLIM of FROMLINE))
    (freplace SPACELEFT of TOLINE with (ffetch SPACELEFT of FROMLINE))
    (freplace LHEIGHT of TOLINE with (ffetch LHEIGHT of FROMLINE))
    (freplace CHAR1 of TOLINE with (ffetch CHAR1 of FROMLINE))
    (freplace CHARLIM of TOLINE with (ffetch CHARLIM of FROMLINE))
    (freplace CHARTOP of TOLINE with (ffetch CHARTOP of FROMLINE))
    (freplace DIRTY of TOLINE with NIL)
    (freplace CR\END of TOLINE with (ffetch CR\END of FROMLINE))
    (freplace LDOBJ of TOLINE with (ffetch LDOBJ of FROMLINE))
    (freplace LHASPROT of TOLINE with (ffetch LHASPROT of FROMLINE))
    (freplace LFMTSPEC of TOLINE with (ffetch LFMTSPEC of FROMLINE))
    (freplace LTRUEDESCENT of TOLINE with (ffetch LTRUEDESCENT of FROMLINE))
    (freplace LTRUEASCENT of TOLINE with (ffetch LTRUEASCENT of FROMLINE))
    (freplace ASCENT of TOLINE with (ffetch ASCENT of FROMLINE))
    (freplace DESCENT of TOLINE with (ffetch DESCENT of FROMLINE))
    (freplace LHASTABS of TOLINE with (ffetch LHASTABS of FROMLINE))
    (freplace LMARK of TOLINE with (ffetch LMARK of FROMLINE))
    (freplace 1STLN of TOLINE with (ffetch 1STLN of FROMLINE))
    (freplace LSTLN of TOLINE with (ffetch LSTLN of FROMLINE])

(\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.FIXCHANGEDLINE
  [LAMBDA (TEXTOBJ PREVYBOT LINES WINDOW TEXTLEN THISLINE WHEIGHT CHARLIM NEXTCARETCH#)
                                                             (* jds "12-Mar-85 04:20")
                                                             (* Reformat a single line, if need be.
							     Returns the changed line)
    (PROG ((YBOT PREVYBOT)
	   (FORMATDONE NIL)
	   LIMITCHANGED WASDIRTY OCHLIM OLHEIGHT (PREVLINE NIL)
	   (FOUND NIL)
	   DY OFLOWFN NEWLINE)
          [COND
	    ((IEQP CHARLIM 1)
	      (SETQ CHARLIM (fetch CHAR1 of LINES]
          (COND
	    ([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 prior one)
	      (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)
	      (\TEDIT.COPY.LINEDESCRIPTOR NEWLINE LINES)     (* Move it into place in the chain)
	      (replace DESC of THISLINE with LINES)          (* And pretend that LINES is the line we just 
							     formatted--since it effectively IS.)
	      (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 (IGEQ (SETQ YBOT (IDIFFERENCE YBOT (fetch LHEIGHT of NEWLINE)))
			    (fetch WBOTTOM of TEXTOBJ))
		      (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)
		  )
		((IGEQ YBOT (fetch WBOTTOM of TEXTOBJ))      (* 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 (TEXTPROP TEXTOBJ (QUOTE OVERFLOWFN)))
			(APPLY* OFLOWFN WINDOW TEXTOBJ)
			(RETFROM (FUNCTION \TEDIT.FIXCHANGEDLINE)))
		   [replace YBOT of LINES with (replace YBASE of LINES
						  with (SUB1 (fetch WBOTTOM of TEXTOBJ]
                                                             (* Mark this line as being off-screen)
		   (COND
		     ((IGREATERP (fetch CHARLIM of LINES)
				 NEXTCARETCH#)
		       (replace NEXTLINE of LINES with NIL)))
                                                             (* Chop off any lines below it, to preserve changes 
							     that may propogate off the bottom of the window)
		   (\TEDIT.CLEAR.SCREEN.BELOW.LINE TEXTOBJ WINDOW (fetch PREVLINE of LINES))
                                                             (* And clear the space below the bottom line on the 
							     screen)
		   (RETURN)))
	      (SETQ LINES NEWLINE)                           (* So that if we inserted a line, we start by moving up
							     to the pre-existing line)
	      ))
          (RETURN LINES])

(\TEDIT.FIXCHANGEDPART
  [LAMBDA (TEXTOBJ STARTINGLINE WINDOW INCREMENTAL? NEXTCARETCH#)
                                                             (* jds "22-Feb-85 16:32")
                                                             (* 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.PRIMARYW TEXTOBJ))
						 (QUOTE LINES]
	   (YBOT (fetch WTOP of TEXTOBJ))
	   (FORMATDONE NIL)
	   LIMITCHANGED WASDIRTY CHARLIM OCHLIM OLHEIGHT (PREVLINE NIL)
	   (TPREVLINE NIL)
	   (TEXTLEN (fetch TEXTLEN of TEXTOBJ))
	   (THISLINE (fetch THISLINE of TEXTOBJ))
	   (WHEIGHT (fetch WTOP of TEXTOBJ))
	   (WBOTTOM (fetch WBOTTOM of TEXTOBJ))
	   (CLEARBOTTOM T)
	   [NEXTCARETCH# (OR NEXTCARETCH# (fetch CH# of (fetch SEL of TEXTOBJ]
	   DY OFLOWFN NEWLINE)
          [COND
	    [NIL (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)))
			       (SETQ YBOT (fetch YBOT of LINES]
	    (T                                               (* Otherwise, go looking for work)
	       (AND LINES (SETQ TPREVLINE (fetch PREVLINE of LINES)))
	       [while LINES
		  do                                         (* Find the first line descriptor of a DIRTY line.)
		     (SETQ YBOT (fetch YBOT of LINES))
		     (COND
		       ((ILESSP 0 (SETQ DY (IDIFFERENCE (IDIFFERENCE (fetch YBOT of TPREVLINE)
								     (fetch LHEIGHT of LINES))
							YBOT)))
                                                             (* There used to be another line above this one.
							     Move this up to cover it.)
			 (\TEDIT.ADJUST.LINES TEXTOBJ LINES (OR WINDOW (\TEDIT.PRIMARYW TEXTOBJ))
					      (IPLUS YBOT (fetch LHEIGHT of LINES))
					      DY)))
		     (COND
		       ((AND (ILESSP YBOT (fetch WBOTTOM of TEXTOBJ))
			     (IGREATERP (fetch CHAR1 of LINES)
					NEXTCARETCH#))       (* We've run off the bottom of the screen.)
			 (replace NEXTLINE of TPREVLINE with NIL)
                                                             (* There may be unfixed changes there, so chop off any 
							     further lines.)
			 (SETQ LINES NIL))
		       ((fetch DIRTY of LINES)
			 (RETURN))
		       ([AND [NOT (IEQP (fetch CHAR1 of LINES)
					(ADD1 (fetch CHARLIM of TPREVLINE]
			     (NOT (ZEROP (fetch CHARLIM of TPREVLINE]
                                                             (* This line doesn't match up with the previous line;
							     we should start updating here.
							     But don't worry about the dummy first line)
			 (RETURN))
		       (T (SETQ TPREVLINE LINES)
			  (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 (fetch WBOTTOM of TEXTOBJ)
		      (fetch WIDTH of (DSPCLIPPINGREGION NIL WINDOW))
		      (IDIFFERENCE YBOT (fetch WBOTTOM of TEXTOBJ))
		      (QUOTE TEXTURE)
		      (QUOTE REPLACE)
		      WHITESHADE)
	      (COND
		([OR (ZEROP TEXTLEN)
		     (NOT (fetch NEXTLINE of (WINDOWPROP (OR WINDOW (\TEDIT.PRIMARYW TEXTOBJ))
							 (QUOTE LINES]

          (* If there is no text, or no image, force a call to \FILLWINDOW, to provide a dummy empty line descriptor for the 
	  guy to type at.)


		  (RETURN (fetch LINES of TEXTOBJ)))
		(T                                           (* We found no changes; return a NIL last-line-changed)
		   (RETURN NIL]
          [SETQ YBOT (fetch YBOT of (SETQ PREVLINE (fetch PREVLINE of LINES]
                                                             (* Y bottom of the first line to reformat.)
          (SETQ CHARLIM (ADD1 (fetch CHARLIM of PREVLINE)))
                                                             (* char to start formatting with)
          (while (AND LINES (OR (IGEQ YBOT (fetch WBOTTOM of TEXTOBJ))
				(ILEQ CHARLIM NEXTCARETCH#)))
	     do 

          (* Run thru lines, cleaning them up. Start with the first dirty line, and only stop if we're both past the place the
	  caret will be AND off the bottom of the screen.)


		(COND
		  ([ILESSP 0 (SETQ DY (IDIFFERENCE (IDIFFERENCE YBOT (fetch LHEIGHT of LINES))
						   (fetch YBOT of LINES]
                                                             (* There used to be another line above this one.
							     Move this up to cover it.)
		    (\TEDIT.ADJUST.LINES TEXTOBJ LINES (OR WINDOW (\TEDIT.PRIMARYW TEXTOBJ))
					 (IPLUS (fetch YBOT of LINES)
						(fetch LHEIGHT of LINES))
					 DY)))
		[COND
		  ((IGREATERP CHARLIM (IMIN (IMAX 1 (fetch CHARLIM of LINES))
					    TEXTLEN))        (* This line has been rendered superfluous -- Delete 
							     it.)
		    (TEDIT.DELETELINE LINES TEXTOBJ WINDOW))
		  (T                                         (* Try updating the line. If the updater returns NIL, 
							     it ran off the bottom of the screen, and we should give
							     up.)
		     (COND
		       ((\TEDIT.FIXCHANGEDLINE TEXTOBJ YBOT LINES WINDOW TEXTLEN THISLINE WHEIGHT 
					       CHARLIM NEXTCARETCH#)
                                                             (* We're still on screen; update the character and 
							     Y-position counters for the next loop)
			 (SETQ CHARLIM (ADD1 (fetch CHARLIM of LINES)))
			 (SETQ YBOT (fetch YBOT of LINES)))
		       (T                                    (* Ran off the bottom of the window;
							     the bottom has already been cleared, so avoid doing it 
							     here.)
			  (SETQ CLEARBOTTOM NIL)
			  (RETURN]
		(COND
		  ((IGEQ CHARLIM TEXTLEN)                    (* If we've run out of text, chop off any remaining 
							     line descriptors, since we won't be needing them.)
		    (replace NEXTLINE of LINES with NIL)
		    (replace TXTNEEDSUPDATE of TEXTOBJ with NIL)
                                                             (* And there's no more screen updating to do, either.)
		    )
		  ((AND INCREMENTAL? (fetch NEXTLINE of LINES)
			(IGREATERP CHARLIM NEXTCARETCH#)
			(\SYSBUFP))                          (* This is an incremental update, and he hit a key.
							     Stop updating and listen to him)
                                                             (* HOWEVER, NEVER STOP ON THE LAST LINE -- IF THERE ARE
							     NEW LINES TO ADD, ADD ONE.)
		    (SETQ PREVLINE NIL)
		    (SETQ CLEARBOTTOM NIL)
		    (RETURN)))
		(SETQ PREVLINE LINES)                        (* Remember the last line we really formatted.)
		(SETQ LINES (fetch NEXTLINE of LINES))       (* Move to the next line))
          (COND
	    (CLEARBOTTOM                                     (* There had been lines yet to be formatted, so there 
							     may be garbage below the end of the screen.)
			 (\TEDIT.CLEAR.SCREEN.BELOW.LINE TEXTOBJ WINDOW PREVLINE)))
          (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.LINE.LIST
  [LAMBDA (TEXTOBJ WINDOW)                                   (* jds " 7-Feb-85 14:13")
    (for WW inside (fetch \WINDOW of TEXTOBJ) as LINES inside (fetch LINES of TEXTOBJ)
       when (EQ WW WINDOW) do (RETURN LINES])

(\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 " 6-Mar-85 21:29")
                                                             (* 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)
		      (ADD1 (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 (ILESSP (fetch CHAR1 of LL)
									 CHLIM#)
								 (IGEQ (fetch CHARTOP of LL)
								       CH#))

          (* The dirty range overlaps with this line -- it is between the 1st char on the line, and the last char examined 
	  when deciding where to break the line.)


							     (replace DIRTY of LL with T)))
							 (SETQ LL (fetch NEXTLINE of LL)))
       finally (replace TXTNEEDSUPDATE of TEXTOBJ with T])

(\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])
)
(PUTPROPS TEDITSCREEN COPYRIGHT ("John Sybalsky & Xerox Corporation" 1983 1984 1985))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (6475 126977 (TEDIT.CR.UPDATESCREEN 6485 . 8225) (TEDIT.DELETELINE 8227 . 9069) (
TEDIT.INSERT.DISPLAYTEXT 9071 . 16763) (TEDIT.INSERT.UPDATESCREEN 16765 . 27385) (TEDIT.UPDATE.SCREEN 
27387 . 28173) (\BACKFORMAT 28175 . 31031) (\DISPLAYLINE 31033 . 40415) (\DOFORMATTING 40417 . 46443) 
(\FILLWINDOW 46445 . 53552) (\FIXDLINES 53554 . 57600) (\FIXILINES 57602 . 60943) (\FORMATLINE 60945
 . 82616) (\PULLTEXT 82618 . 86752) (\PUSHTEXT 86754 . 92998) (\SHOWTEXT 93000 . 94971) (
\TEDIT.ADJUST.LINES 94973 . 99993) (\TEDIT.BLTCHAR 99995 . 101784) (\TEDIT.CLEAR.SCREEN.BELOW.LINE 
101786 . 102347) (\TEDIT.CLOSEUPLINES 102349 . 106650) (\TEDIT.COPY.LINEDESCRIPTOR 106652 . 108764) (
\TEDIT.CREATE.LINECACHE 108766 . 109427) (\TEDIT.FIXCHANGEDLINE 109429 . 115257) (
\TEDIT.FIXCHANGEDPART 115259 . 123839) (\TEDIT.INSERTLINE 123841 . 124465) (\TEDIT.LINE.LIST 124467 . 
124764) (\TEDIT.LINECACHE 124766 . 125452) (\TEDIT.MARK.LINES.DIRTY 125454 . 126662) (
\TEDIT.PURGE.SPACES 126664 . 126975)))))
STOP