(FILECREATED " 7-Oct-86 14:39:22" {ERIS}<TEDIT>TEDITSCREEN.;41 129728 

      changes to:  (FNS \TEDIT.CLOSEUPLINES)

      previous date: " 6-Oct-86 13:03:26" {ERIS}<TEDIT>TEDITSCREEN.;40)


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

(PRETTYCOMPRINT TEDITSCREENCOMS)

(RPAQQ TEDITSCREENCOMS 
       ((FILES TEDITDECLS)
        (DECLARE: EVAL@COMPILE DONTCOPY (CONSTANTS (\SCRATCHLEN 64))
               (FILES (LOADCOMP)
                      TEDITDECLS))
        (FNS TEDIT.CR.UPDATESCREEN TEDIT.DELETELINE TEDIT.INSERT.DISPLAYTEXT 
             TEDIT.INSERT.UPDATESCREEN TEDIT.UPDATE.SCREEN \BACKFORMAT \DISPLAYLINE \DOFORMATTING 
             \FILLWINDOW \FIXDLINES \FIXILINES \FORMATLINE \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.NEXT.LINE.BOTTOM \TEDIT.PURGE.SPACES)))
(FILESLOAD TEDITDECLS)
(DECLARE: EVAL@COMPILE DONTCOPY 
(DECLARE: EVAL@COMPILE 

(RPAQQ \SCRATCHLEN 64)

(CONSTANTS (\SCRATCHLEN 64))
)

(FILESLOAD (LOADCOMP)
       TEDITDECLS)
)
(DEFINEQ

(TEDIT.CR.UPDATESCREEN
  [LAMBDA (CH# XPOINT TEXTOBJ SEL LINE BLANKSEEN CRSEEN DS CHWIDTH DONTSCROLL)
                                                                           (* jds 
                                                                           " 9-Feb-86 15:24")
            
            (* 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.)

    (HELP)  
            (* (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 
                                                                           " 9-Feb-86 15:26")
                                                                           (* This function does 
                                                                           the actual displaying 
                                                                           of typed-in text on the 
                                                                           edit window.)
    (HELP)  
            (* (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 "24-Sep-86 01:13")
                                                             (* 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))
             ((fetch TXTDON'TUPDATE of TEXTOBJ)              (* ; 
                                            "Don't update the screen if updates are being inhibited.")
              (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)))
          (\COPYSEL SEL TEDIT.SELECTION)
          [for WW inside WINDOW as L1 inside (fetch L1 of SEL) as LN
             inside (fetch LN of SEL) as L1LIST on (fetch L1 of SEL) as LNLIST
             on (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 [COND
                                      ((SETQ SELINE (SELECTQ (fetch POINT of SEL)
                                                        (LEFT (CAR L1LIST))
                                                        (RIGHT (CAR LNLIST))
                                                        NIL))
                                       (ILESSP (fetch YBOT of SELINE)
                                              (fetch WBOTTOM of TEXTOBJ)))
                                      (T (ILESSP (fetch Y0 of SEL)
                                                (fetch WBOTTOM of TEXTOBJ]
                                   (AND (IGEQ (fetch Y0 of SEL)
                                              (fetch WTOP of TEXTOBJ))
                                        (NULL SELINE)))
                           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 (CAR L1LIST))
                                                          (RIGHT (CAR LNLIST))
                                                          NIL)
                                                      (fetch LHEIGHT
                                                         of (SELECTQ (fetch POINT of SEL)
                                                                (LEFT (CAR L1LIST))
                                                                (RIGHT (CAR LNLIST))
                                                                (SHOULDNT]
                                                     (T 12))
                                                  1]
                   (T (\TEDIT.SET.WINDOW.EXTENT TEXTOBJ WW]
          (\COPYSEL SEL TEDIT.SELECTION])

(TEDIT.UPDATE.SCREEN
  [LAMBDA (TEXTOBJ STARTINGLINE INCREMENTAL? NEXTCARETCH#)   (* jds "24-Sep-86 01:21")
                                                             (* Update the screen, as needed to fix 
                                                             up "dirty" lines.)
    (SETQ TEXTOBJ (TEXTOBJ TEXTOBJ))
    (COND
       ((NOT (fetch TXTDON'TUPDATE of TEXTOBJ))              (* ; 
                                          "Only update the screen if we aren't suppressing updating.")
        (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 NEXTCARETCH#])

(\BACKFORMAT
  [LAMBDA (LINES TEXTOBJ WHEIGHT)                            (* jds " 7-May-85 00:48")
                                                             (* 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))
	   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 "23-Oct-85 12:19")
                                                             (* Display the line of text LINE in the edit window 
							     where it belongs.)
    (PROG ((CH 0)
	     (CHLIST (fetch (THISLINE CHARS) of (fetch THISLINE of TEXTOBJ)))
	     (WLIST (fetch (THISLINE WIDTHS) of (fetch THISLINE of TEXTOBJ)))
	     (LOOKS (fetch (THISLINE LOOKS) of (fetch THISLINE of TEXTOBJ)))
	     (WINDOWDS (WINDOWPROP (OR WINDOW (CAR (fetch (TEXTOBJ \WINDOW) of TEXTOBJ)))
				     (QUOTE DSP)))
	     (TEXTLEN (fetch (TEXTOBJ TEXTLEN) of TEXTOBJ))
	     (THISLINE (fetch (TEXTOBJ THISLINE) of TEXTOBJ))
	     (TERMSA (fetch (TEXTOBJ TXTTERMSA) of TEXTOBJ))
	     (STREAM (fetch (TEXTOBJ STREAMHINT) of TEXTOBJ))
	     (OLDCACHE (fetch LCBITMAP of (fetch (TEXTOBJ DISPLAYCACHE) of TEXTOBJ)))
	     (DS (fetch (TEXTOBJ DISPLAYCACHEDS) of TEXTOBJ))
	     (HCPYDS (fetch (TEXTOBJ DISPLAYHCPYDS) of TEXTOBJ))
	     (HARDCOPYMODE (fetch (FMTSPEC FMTHARDCOPY) of (fetch (LINEDESCRIPTOR LFMTSPEC)
								  of LINE)))
	     LOOKSTARTX CACHE \PCHARSLEFT \PSTRING \PFILE FONT OFONT OLOOKS XOFFSET CLIPLEFT 
	     CLIPRIGHT DISPLAYDATA DDPILOTBBT DDWIDTHCACHE DDOFFSETCACHE CURY LHEIGHT SCALE)
	    [SETQ LHEIGHT (COND
		((fetch (LINEDESCRIPTOR PREVLINE) of LINE)
                                                             (* So if theres a base-to-base measure, we clear 
							     everything right.)
		  (IMAX (IDIFFERENCE (fetch YBOT of (fetch (LINEDESCRIPTOR PREVLINE)
							       of LINE))
					 (fetch (LINEDESCRIPTOR YBOT) of LINE))
			  (fetch (LINEDESCRIPTOR LHEIGHT) of LINE)))
		(T (fetch (LINEDESCRIPTOR LHEIGHT) of LINE]
	    (COND
	      (HARDCOPYMODE                                  (* This is a hardcopy-mode line.
							     Scale things.)
                                                             (* (SETQ DS HCPYDS))
			    (SETQ SCALE (DSPSCALE NIL HCPYDS)))
	      (T (SETQ SCALE 1)))
	    (SETQ CACHE (\TEDIT.LINECACHE (fetch (TEXTOBJ DISPLAYCACHE) of TEXTOBJ)
					      (COND
						(HARDCOPYMODE (FIXR (FQUOTIENT (fetch 
										      RIGHTMARGIN
										      of LINE)
										   SCALE)))
						(T (fetch RIGHTMARGIN of LINE)))
					      LHEIGHT))
	    (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
	      (HARDCOPYMODE                                  (* This is a hardcopy-mode line.
							     Scale things.)
                                                             (* (SETQ DS HCPYDS))
			    (SETQ SCALE (DSPSCALE NIL HCPYDS)))
	      (T (SETQ SCALE 1)))
	    [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)
		(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 (FIXR (FTIMES SCALE (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)
						  (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)
						  )
				   [(CHARCODE (TAB #↑I))
                                                             (* TAB: use the width from the cache to decide the 
							     right formatting.)
				     (COND
				       ((OR (IEQP CH (CHARCODE #↑I))
					      (fetch CLLEADER of OLOOKS)
					      (EQ (fetch CLUSERINFO of OLOOKS)
						    (QUOTE DOTTEDLEADER)))
					 (LET* [[LEADERFONT (COND
							      (HARDCOPYMODE (FONTCOPY (fetch
											  CLFONT
											   of
											    OLOOKS)
											(QUOTE
											  DEVICE)
											HCPYDS))
							      (T (fetch CLFONT of OLOOKS]
						(DOTWIDTH (CHARWIDTH (CHARCODE %.)
								       LEADERFONT))
						(TTX (IPLUS TX DOTWIDTH (IDIFFERENCE
								DOTWIDTH
								(IREMAINDER TX DOTWIDTH]
					       (while (ILEQ TTX (IPLUS TX DX))
						  do (COND
							 (HARDCOPYMODE
							   (\TEDIT.BLTCHAR
							     (CHARCODE %.)
							     DS
							     (FIXR (FQUOTIENT (IDIFFERENCE
										    TTX DOTWIDTH)
										  SCALE))
							     DISPLAYDATA DDPILOTBBT CLIPRIGHT))
							 ((OR TERMSA HARDCOPYMODE)
                                                             (* Using special instrns from TERMSA)
							   (\DSPPRINTCHAR DS (CHARCODE %.)))
							 (T 
                                                             (* Native charcodes)
							    (\TEDIT.BLTCHAR (CHARCODE %.)
									      DS
									      (IDIFFERENCE TTX 
											 DOTWIDTH)
									      DISPLAYDATA DDPILOTBBT 
									      CLIPRIGHT)))
						       (add TTX DOTWIDTH]
				   (13                       (* It's a CR)
				       NIL)
				   (COND
				     [(SMALLP CH)          (* Normal character -- just display it.)
				       (COND
					 (HARDCOPYMODE (\TEDIT.BLTCHAR CH DS
									 (FIXR (FQUOTIENT TX 
											    SCALE))
									 DISPLAYDATA DDPILOTBBT 
									 CLIPRIGHT))
					 ((OR TERMSA HARDCOPYMODE)
                                                             (* Using special instrns from TERMSA)
					   (\DSPPRINTCHAR DS CH))
					 (T                  (* Native charcodes)
					    (\TEDIT.BLTCHAR CH DS TX DISPLAYDATA DDPILOTBBT 
							      CLIPRIGHT]
				     (T                      (* CH is an object.)
					(MOVETO (IDIFFERENCE (FIXR (FQUOTIENT TX SCALE))
								 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 (FIXR (FQUOTIENT TX SCALE))
								 XOFFSET)
						  CURY DS)   (* Move to after the object's image)
					]
			(add TX DX)                        (* Update our X position)
		   finally (replace DDXPOSITION of DISPLAYDATA
				with (IDIFFERENCE (FIXR (FQUOTIENT TX SCALE))
						      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)
		      LHEIGHT
		      (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)
				       6 6 (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)
					6 6 (QUOTE TEXTURE)
					(QUOTE PAINT)
					BLACKSHADE))
		       (BITBLT NIL 0 0 WINDOWDS 0 (fetch YBASE of LINE)
				 6 6 (QUOTE TEXTURE)
				 (QUOTE REPLACE)
				 WHITESHADE])

(\DOFORMATTING
  [LAMBDA (TEXTOBJ LINE FMTSPEC THISLINE #BLANKS PREVSP 1STLN)             (* jds 
                                                                           "20-Mar-86 17:22")
                                                                           (* Do the formatting 
                                                                           work for justified, 
                                                                           centered, etc.
                                                                           lines)
    (PROG ((QUAD (fetch QUAD of FMTSPEC))
           (SPACELEFT (LLSH (fetch SPACELEFT of LINE)
                            5))
           (EXISTINGSPACE 0)
           (CHLIST (fetch (THISLINE CHARS) of THISLINE))
           (WLIST (fetch (THISLINE 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)
          (replace (THISLINE TLSPACEFACTOR) of THISLINE with 1)            (* Start by assuming 
                                                                           that we want a space 
                                                                           factor of 1.0)
          [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]
          [COND
             ((AND (fetch LSTLN of LINE)
                   (fetch LEADAFTER of FMTSPEC))                           (* If paragraph 
                                                                           pre-leading was 
                                                                           specified, set it)
              (add (fetch LHEIGHT of LINE)
                   (fetch LEADAFTER of FMTSPEC))                           (* And adjust the 
                                                                           line's ascent 
                                                                           accordingly.)
              (add (fetch DESCENT of LINE)
                   (fetch LEADAFTER 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))
                               (add EXISTINGSPACE (\WORDELT WLIST 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]
                         (COND
                            ((NOT (ZEROP EXTRASP))                         (* Only if we really 
                                                                           expanded the line --)
                             (replace (THISLINE TLSPACEFACTOR) of THISLINE
                                with (FQUOTIENT (IPLUS EXISTINGSPACE (fetch (LINEDESCRIPTOR SPACELEFT
                                                                                   ) of LINE))
                                            EXISTINGSPACE))                (* And set the space 
                                                                           factor for display)
                             ))
                         (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 NEXTCARETCH#)
                                                             (* jds " 5-Oct-85 11:50")
                                                             (* 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.)
                                                             (* NEXTCARETCH# => always format to at least this CH#, 
							     to assure that we know where the caret will next be.)
    (PROG* ((LINE (fetch NEXTLINE of CURLINE))
	    (CHARLIM (fetch CHARLIM of CURLINE))
	    (PREVLINE CURLINE)
	    (TEXTLEN (fetch TEXTLEN of TEXTOBJ))
	    (LINES\DELETED NIL)
	    (WINDOW (OR WINDOW (fetch \WINDOW of TEXTOBJ)))
	    (WHEIGHT (WINDOWPROP WINDOW (QUOTE HEIGHT)))
	    NEXTLINE OFLOWFN)
           (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 (\TEDIT.NEXT.LINE.BOTTOM YBOT LINE PREVLINE))
				    (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))
		   [(AND LINE NEXTCARETCH# (ILEQ (fetch CHAR1 of LINE)
						 NEXTCARETCH#))
                                                             (* There's a line, and it's earlier than the next caret
							     location. Keep going.)
		     (replace YBOT of LINE with YBOT)
		     (replace YBASE of LINE with (IPLUS YBOT (fetch DESCENT of LINE]
		   (LINE                                     (* There is a line, but it won't fit.)
			 [COND
			   ((fetch FMTBASETOBASE of (fetch LFMTSPEC of LINE))
			     (SETQ YBOT (fetch YBOT of PREVLINE)))
			   (T (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 [COND
				[(fetch FMTBASETOBASE of (fetch LFMTSPEC of LINE))
				  (SETQ YBOT (IDIFFERENCE (IPLUS YBOT (fetch DESCENT of PREVLINE))
							  (IPLUS (fetch FMTBASETOBASE
								    of (fetch LFMTSPEC of LINE))
								 (fetch DESCENT of LINE]
				(T (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))
		       [(AND NEXTCARETCH# (ILEQ (fetch CHAR1 of LINE)
						NEXTCARETCH#))
                                                             (* This line is needed to find the next caret location,
							     even tho it won't fit on the screen)
			 (replace YBOT of LINE with YBOT)
			 (replace YBASE of LINE with (IPLUS YBOT (fetch DESCENT of LINE]
		       (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 "21-Sep-85 09:20")
                                                             (* 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.)
			   (AND NL (replace DIRTY of NL with T))
                                                             (* This may well force a reformatting of the next line.
							     Mark it dirty just in case.)
			   ))
		      (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 "17-Oct-85 11:57")
                                                             (* 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.)


    (DECLARE (SPECVARS LOOKS CHLIST WLIST FONTWIDTHS CHNO ASCENT DESCENT LOOKNO LINE FONT 
			   INVISIBLERUNS DEVICE SCALE NEWASCENT NEWDESCENT))
    (PROG ([LINE (OR OLINE (create LINEDESCRIPTOR
					 RIGHTMARGIN ←(fetch WRIGHT of TEXTOBJ)
					 YBOT ←(SUB1 (fetch WBOTTOM of TEXTOBJ]
	     (CH#B CH#1)
	     (GATHERBLANK T)
	     (TLEN 0)
	     (TEXTLEN (fetch TEXTLEN of TEXTOBJ))
	     (THISLINE (ffetch THISLINE of TEXTOBJ))
	     (CHNO CH#1)
	     (LOOKNO 0)
	     (INVISIBLERUNS 0)
	     (ASCENT 0)
	     (DESCENT 0)
	     (PREVSP 0)
	     (#BLANKS 0)
	     (DEFAULTTAB 36)
	     (DS (WINDOWPROP (CAR (fetch \WINDOW of TEXTOBJ))
			       (QUOTE DSP)))
	     LEFTEDGE TX DX TXB CH FORCEEND T1SPACE TXB1 DXB WIDTH LOOK#B FONT FONTWIDTHS TERMSA 
	     CLOOKS TEXTSTREAM CHLIST WLIST LOOKS ASCENTB DESCENTB INVISIBLERUNSB TABPENDING BOX PC 
	     PCNO DEVICE SCALE NEWASCENT NEWDESCENT TABSPEC HARDCOPYMODE ORIGFMTSPEC)

          (* * 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 (THISLINE 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 LMInvisibleRun)
			(\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)))
			(AND PC (SETQ CLOOKS (\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))
				(AND PC (SETQ CLOOKS (\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 ORIGFMTSPEC (OR FMTSPEC (SETQ FMTSPEC (OR (fetch PPARALOOKS
									   of (fetch
										  (TEXTSTREAM
										    PIECE)
										   of TEXTSTREAM))
									(fetch FMTSPEC
									   of TEXTOBJ]
                                                             (* Get the paragraph looks)
		(COND
		  [(SETQ HARDCOPYMODE (fetch FMTHARDCOPY of FMTSPEC))
                                                             (* This line is a hardcopy line.
							     Scale things for it.)
		    [SETQ DEVICE (OR (fetch DISPLAYHCPYDS of TEXTOBJ)
					 (replace DISPLAYHCPYDS of TEXTOBJ
					    with (OPENIMAGESTREAM (QUOTE {NODIRCORE})
								      (QUOTE INTERPRESS]
		    (SETQ SCALE (DSPSCALE NIL DEVICE))
		    (SETQ FMTSPEC (\TEDIT.HCPYFMTSPEC FMTSPEC DEVICE))
		    (SETQ DEFAULTTAB (FIXR (FTIMES 36 SCALE)))
		    (SETQ LEFTEDGE (FIXR (FTIMES 8 SCALE]
		  (T                                         (* Regular line. Format at display resolutions)
		     (SETQ DEVICE (fetch DISPLAYCACHEDS of TEXTOBJ))
		     (SETQ SCALE 1)
		     (SETQ LEFTEDGE 8)))
		(SETQ TABSPEC (fetch TABSPEC of FMTSPEC))
		[COND
		  ((type? FONTCLASS (SETQ FONT (fetch CLFONT of CLOOKS)))
		    (SETQ FONT (FONTCOPY (fetch CLFONT of CLOOKS)
					     (QUOTE DEVICE)
					     (QUOTE DISPLAY]
                                                             (* Grab the initial font for this line)
		[SETQ ASCENTB (SETQ NEWASCENT (IPLUS (fetch \SFAscent of FONT)
							   (OR (fetch CLOFFSET of CLOOKS)
								 0]
                                                             (* The initial ascent, per the initial font)
		[SETQ DESCENTB (SETQ NEWDESCENT (IDIFFERENCE (fetch \SFDescent of FONT)
								   (OR (fetch CLOFFSET
									    of CLOOKS)
									 0]
                                                             (* Initial descent, per the initial font.)
		[COND
		  (HARDCOPYMODE                              (* If this is a hardcopy line, fetch the hardcopy 
							     version of the font)
				(SETQ FONT (FONTCOPY (fetch CLFONT of CLOOKS)
							 (QUOTE DEVICE)
							 DEVICE]
		(\EDITSETA LOOKS 0 CLOOKS)                   (* Save looks in the line cache)
		[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 [FIXR (FTIMES SCALE (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 LEFTEDGE (fetch RIGHTMAR of FMTSPEC)))
			      (T (FIXR (FTIMES SCALE (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)
			      (\FGETCHARWIDTH FONT CH))
			    (T                               (* CH is an object)
			       (SETQ BOX (APPLY* (IMAGEOBJPROP CH (QUOTE IMAGEBOXFN))
						     CH DS TX WIDTH))
                                                             (* Get its size)
			       (SETQ NEWASCENT (IDIFFERENCE (fetch YSIZE of BOX)
								(fetch YDESC of BOX)))
			       (SETQ NEWDESCENT (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)
				   ))
			       (COND
				 [HARDCOPYMODE (FIXR (FTIMES SCALE (fetch XSIZE of BOX]
				 (T (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)
					 (COND
					   (NEWASCENT        (* The ascent has changed; catch it)
						      (SETQ ASCENT (IMAX ASCENT NEWASCENT))
						      (SETQ DESCENT (IMAX DESCENT NEWDESCENT))
						      (SETQ NEWASCENT NIL)))
					 (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)
				      (COND
					((AND NEWASCENT (ZEROP ASCENT)
						(ZEROP DESCENT))
                                                             (* The ascent has changed; catch it)
					  (SETQ ASCENT NEWASCENT)
					  (SETQ DESCENT NEWDESCENT)))
				      (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)
					 (COND
					   (NEWASCENT        (* The ascent has changed; catch it)
						      (SETQ ASCENT (IMAX ASCENT NEWASCENT))
						      (SETQ DESCENT (IMAX DESCENT NEWDESCENT))
						      (SETQ NEWASCENT NIL)))
					 (\RPLPTR CHLIST 0 CH)
					 (SETQ TABPENDING
					   (\TEDIT.FORMATTABS TEXTOBJ TABSPEC THISLINE CHLIST WLIST 
								TX DEFAULTTAB LEFTEDGE 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))
					 (\TEDIT.PURGE.SPACES (fetch CHARS of THISLINE)
								PREVSP)
                                                             (* All the spaces before a tab don't take part in 
							     justification from here on.)
					 (SETQ #BLANKS 0)
                                                             (* Also reset the count of spaces on this line, so we 
							     widen later spaces enough.)
					 (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
					     ((AND (SMALLP CH)
						     (IGEQ CH 192)
						     (ILEQ CH 207))
                                                             (* This is an NS accent character.
							     Space it 0.0)
					       (SETQ DX 0)))
					   (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)
						    (COND
						      (NEWASCENT 
                                                             (* The ascent has changed; catch it)
								 (SETQ ASCENT (IMAX ASCENT 
											NEWASCENT))
								 (SETQ DESCENT (IMAX DESCENT 
										       NEWDESCENT))
								 (SETQ NEWASCENT NIL]
					       (RETURN))
					     (T              (* Not past the rightmargin yet...)
						(COND
						  (NEWASCENT 
                                                             (* The ascent has changed; catch it)
							     (SETQ ASCENT (IMAX ASCENT NEWASCENT))
							     (SETQ DESCENT (IMAX DESCENT 
										     NEWDESCENT))
							     (SETQ NEWASCENT NIL)))
						(\RPLPTR CHLIST 0 CH)
						(\PUTBASE WLIST 0 DX)
                                                             (* Check for decimal tabs)
						(COND
						  ((AND (SMALLP CH)
							  (EQ CH (CHARCODE %.))
							  TABPENDING
							  (NOT (FIXP TABPENDING))
							  (EQ (fetch PTTYPE of TABPENDING)
								(QUOTE DECIMAL)))
                                                             (* Figure out which tab stop to use, and what we need 
							     to do to get there.)
						    (SETQ TABPENDING
						      (\TEDIT.FORMATTABS TEXTOBJ TABSPEC THISLINE 
									   CHLIST WLIST TX DEFAULTTAB 
									   LEFTEDGE TABPENDING T))
						    [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)
						    (\TEDIT.PURGE.SPACES (fetch CHARS
									      of THISLINE)
									   PREVSP)
                                                             (* All the spaces before a tab don't take part in 
							     justification from here on.)
						    (SETQ #BLANKS 0)
                                                             (* Also reset the count of spaces on this line, so we 
							     widen later spaces enough.)
						    (SETQ PREVSP 0)
						    (SETQ T1SPACE T)
						    (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]
			(SETQ CHLIST (\ADDBASE CHLIST 2)) 
                                                             (* Move the pointers forward for the next character.)
			(SETQ WLIST (\ADDBASE WLIST 1)))
                                                             (* End of char loop)
		(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 TABSPEC THISLINE CHLIST WLIST TX 
						     DEFAULTTAB LEFTEDGE 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)
		 (\EDITSETA LOOKS 0 CLOOKS)                  (* Set up the initial looks so that \DISPLAYLINE 
							     doesn't complain)
		 (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 (OR ORIGFMTSPEC FMTSPEC)
			     THISLINE #BLANKS PREVSP 1STLN)
	    (replace LFMTSPEC of LINE with FMTSPEC)
	    (replace LOOKSUPDATEFN of TEXTSTREAM with NIL)
	    (RETURN LINE])

(\SHOWTEXT
  [LAMBDA (TEXTOBJ LINES WINDOW)                             (* jds "14-Jun-85 09:57")
                                                             (* 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 [PROG1 (DSPCLIPPINGREGION NIL WINDOW)
                                                             (* For region within a window:)

          (* (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 ←(WINDOWPROP WINDOW (QUOTE HEIGHT))
						    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
						    LFMTSPEC ← TEDIT.DEFAULT.FMTSPEC))
                                                             (* Make sure we have the anchor pseudo-line)
				(WINDOWPROP WINDOW (QUOTE LINES)
					    LINES)
				(\FILLWINDOW (WINDOWPROP WINDOW (QUOTE HEIGHT))
					     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 "17-May-85 15:19")

          (* 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.)
	      )
	    (FIRSTLINE                                       (* 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 CURX DISPLAYDATA DDPILOTBBT CLIPRIGHT)
                                                             (* jds " 9-Jan-86 17:14")
                                                             (* 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 IMAGEWIDTH (CHAR8CODE (\CHAR8CODE CHARCODE)))
	    [COND
	      ((NEQ (ffetch DDCHARSET of DISPLAYDATA)
		      (\CHARSET CHARCODE))
		(\CHANGECHARSET.DISPLAY DISPLAYDATA (\CHARSET CHARCODE]
	    (SETQ IMAGEWIDTH (\GETBASE (fetch DDCHARIMAGEWIDTHS of DISPLAYDATA)
					   (\CHAR8CODE CHARCODE)))
	    (SETQ NEWX (IPLUS CURX IMAGEWIDTH))
	    (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 IMAGEWIDTH (IDIFFERENCE
									  RIGHT LEFT)))
		    (freplace PBTSOURCEBIT of DDPILOTBBT with (\GETBASE (fetch 
										   DDOFFSETSCACHE
										   of DISPLAYDATA)
										(\CHAR8CODE 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 " 7-Oct-86 14:38")
          
          (* 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)
                                                             (* NEXTLINE = NIL => remove all lower 
                                                             lines.)
    (COND
       (PREVLINE                                             (* PREVLINE = NIL => DON'T close up 
                                                             anything.)
              (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# PREVDESCENT)
                                                             (* jds " 5-Oct-85 11:53")
                                                             (* 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)
	      (COND
		((AND (ILESSP CHARLIM (fetch CHAR1 of LINES))
		      (IEQP (ADD1 (fetch CHARLIM of NEWLINE))
			    (fetch CHAR1 of LINES)))         (* If this is a space-filling line, just move the other
							     lines down.)
		  (\TEDIT.INSERTLINE NEWLINE LINES))
		(T                                           (* Otherwise, write over existing lines)
		   (\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)
		   ))
	      (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 (\TEDIT.NEXT.LINE.BOTTOM YBOT NEWLINE (fetch PREVLINE
										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))
				       (COND
					 ((fetch FMTBASETOBASE of (fetch LFMTSPEC of LINES))
					   (IDIFFERENCE (fetch YBOT of LINES)
							YBOT))
					 (T (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)
		  )
		((AND NEXTCARETCH# (ILEQ (fetch CHAR1 of LINES)
					 NEXTCARETCH#))      (* This line is off-screen, but is needed for finding 
							     the caret's new location)
		  (replace YBOT of LINES with YBOT)
		  (replace YBASE of LINES with YBOT))
		(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 " 5-Oct-85 11:55")
                                                             (* Reformat lines as needed after a change.
							     Return the last line changed, or NIL if there's no need
							     for a \FILLWINDOW.)
    (PROG* ((THISW (OR WINDOW (\TEDIT.PRIMARYW TEXTOBJ)))
	    [LINES (fetch NEXTLINE of (WINDOWPROP THISW (QUOTE LINES]
	    (REGION (DSPCLIPPINGREGION NIL THISW))
	    (YBOT (fetch PTOP of REGION))
	    (FORMATDONE NIL)
	    LIMITCHANGED WASDIRTY CHARLIM OCHLIM OLHEIGHT (PREVLINE NIL)
	    (TPREVLINE NIL)
	    (TEXTLEN (fetch TEXTLEN of TEXTOBJ))
	    (THISLINE (fetch THISLINE of TEXTOBJ))
	    (WHEIGHT (fetch PTOP of REGION))
	    (WBOTTOM (fetch BOTTOM of REGION))
	    (CLEARBOTTOM T)
	    [NEXTCARETCH# (OR NEXTCARETCH# (fetch CH# of (fetch SEL of TEXTOBJ]
	    DY OFLOWFN NEWLINE TYBOT)
           [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 (\TEDIT.NEXT.LINE.BOTTOM
							   YBOT LINES (fetch (LINEDESCRIPTOR PREVLINE)
									 of LINES))
							 YBOT)))
                                                             (* There used to be another line above this one.
							     Move this up to cover it.)
			  (\TEDIT.CLOSEUPLINES TEXTOBJ (fetch PREVLINE of LINES)
					       LINES NIL (OR WINDOW (\TEDIT.PRIMARYW TEXTOBJ)))
                                                             (* This HAS to fill the window, or we may wind up with 
							     missing lines at the bottom of the screen)
			  ))
		      (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 (WINDOWPROP WINDOW (QUOTE LINES]
		 (T                                          (* We found no changes; return a NIL last-line-changed)
		    (replace TXTNEEDSUPDATE of TEXTOBJ with NIL)
                                                             (* Reset the "needs-update" flag so we don't come back 
							     looking for work again.)
		    (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 (\TEDIT.NEXT.LINE.BOTTOM YBOT LINES
									     (fetch (LINEDESCRIPTOR
										      PREVLINE)
										of LINES))
						    (fetch YBOT of LINES]
                                                             (* There used to be another line above this one.
							     Move this up to cover it.)
		     (\TEDIT.CLOSEUPLINES TEXTOBJ (fetch PREVLINE of LINES)
					  LINES T (OR WINDOW (\TEDIT.PRIMARYW TEXTOBJ]
		 [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
			((SETQ LINES (\TEDIT.FIXCHANGEDLINE TEXTOBJ YBOT LINES WINDOW TEXTLEN 
							    THISLINE WHEIGHT CHARLIM NEXTCARETCH#
							    (fetch DESCENT of PREVLINE)))
                                                             (* 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)                                (* gbn "10-May-85 21:21")
                                                             (* 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 (ILEQ (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.NEXT.LINE.BOTTOM
  [LAMBDA (CURYBOT LINE PREVLINE)                            (* jds " 5-Oct-85 11:50")

          (* * Given a current Y-bottom for PREVLINE, and a LINE to follow it, compute the new line's YBOT value.
	  Takes into account Base-to-base leasing, as well as paragraph leadings.)


    (PROG (NEWYBOT PARALEADING PARALOOKS BASETOBASE)
          [COND
	    [[SETQ BASETOBASE (fetch (FMTSPEC FMTBASETOBASE) of (SETQ PARALOOKS (fetch (LINEDESCRIPTOR
											 LFMTSPEC)
										   of LINE]

          (* If base-to-base spacing is specified, we have to do this in two parts: First, compute the proper spacing between 
	  the lines; then add in any paragraph leading.)


	      [SETQ NEWYBOT (IDIFFERENCE (IPLUS YBOT (fetch (LINEDESCRIPTOR DESCENT) of PREVLINE))
					 (IPLUS BASETOBASE (fetch (LINEDESCRIPTOR DESCENT)
							      of LINE]
	      (COND
		((fetch (LINEDESCRIPTOR 1STLN) of LINE)      (* This is the first line of a new paragraph.
							     Add in any paragraph leading.)
		  [SETQ PARALEADING (IPLUS (fetch (FMTSPEC LEADBEFORE) of PARALOOKS)
					   (fetch (FMTSPEC LEADAFTER) of (fetch (LINEDESCRIPTOR
										  LFMTSPEC)
									    of PREVLINE]
                                                             (* The inter-paragraph space is the sum of the previous
							     para's post-leading and this para's pre-leading.)
		  (SETQ NEWYBOT (IDIFFERENCE NEWYBOT PARALEADING]
	    (T                                               (* If there's no base-to-base spacing, then paragraph 
							     leading was taken into account in the line formatter, 
							     and is already part of LHEIGHT.)
	       (SETQ NEWYBOT (IDIFFERENCE YBOT (fetch (LINEDESCRIPTOR LHEIGHT) of LINE]
          (RETURN NEWYBOT])

(\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 1986))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (1320 129615 (TEDIT.CR.UPDATESCREEN 1330 . 2869) (TEDIT.DELETELINE 2871 . 3713) (
TEDIT.INSERT.DISPLAYTEXT 3715 . 9765) (TEDIT.INSERT.UPDATESCREEN 9767 . 15807) (TEDIT.UPDATE.SCREEN 
15809 . 16860) (\BACKFORMAT 16862 . 19672) (\DISPLAYLINE 19674 . 32167) (\DOFORMATTING 32169 . 45223) 
(\FILLWINDOW 45225 . 53894) (\FIXDLINES 53896 . 58168) (\FIXILINES 58170 . 61511) (\FORMATLINE 61513
 . 89117) (\SHOWTEXT 89119 . 91235) (\TEDIT.ADJUST.LINES 91237 . 96275) (\TEDIT.BLTCHAR 96277 . 98487)
 (\TEDIT.CLEAR.SCREEN.BELOW.LINE 98489 . 99050) (\TEDIT.CLOSEUPLINES 99052 . 105974) (
\TEDIT.COPY.LINEDESCRIPTOR 105976 . 108088) (\TEDIT.CREATE.LINECACHE 108090 . 108751) (
\TEDIT.FIXCHANGEDLINE 108753 . 115402) (\TEDIT.FIXCHANGEDPART 115404 . 124531) (\TEDIT.INSERTLINE 
124533 . 125157) (\TEDIT.LINE.LIST 125159 . 125456) (\TEDIT.LINECACHE 125458 . 126144) (
\TEDIT.MARK.LINES.DIRTY 126146 . 127357) (\TEDIT.NEXT.LINE.BOTTOM 127359 . 129300) (
\TEDIT.PURGE.SPACES 129302 . 129613)))))
STOP