(FILECREATED "24-May-84 17:31:31" {DSK}TEDIT.;8 96547  

      changes to:  (FNS \TEDIT.COPY.PIECEMAPFN TEDIT.EDIT.OBJECT)

      previous date: "24-May-84 11:49:23" {DSK}TEDIT.;7)


(PRETTYCOMPRINT TEDITCOMS)

(RPAQQ TEDITCOMS [(FILES TEXTOFD TEDITCOMMAND TEDITSCREEN TEDITABBREV TEDITLOOKS)
	(CONSTANTS (\SCRATCHLEN 64))
	[INITVARS (TEDIT.TERMSA.FONTS NIL)
		  (TEDIT.TENTATIVE NIL)
		  (TEDIT.DEFAULT.PROPS NIL)
		  (TEDIT.STARTUP.MONITORLOCK (CREATE.MONITORLOCK (QUOTE TEDIT.STARTUP]
	[VARS (TEDIT.RESTART.MENU (CREATE MENU ITEMS← (QUOTE (NewEditProcess]
	(GLOBALVARS TEDIT.TENTATIVE TEDIT.DEFAULT.PROPS)
	(FNS \TEDIT2 COERCETEXTOBJ TEDIT TEDIT.CHARWIDTH TEDIT.COPY TEDIT.DELETE 
	     TEDIT.DO.BLUEPENDINGDELETE TEDIT.INSERT TEDIT.KILL TEDIT.MAPLINES TEDIT.MAPPIECES 
	     TEDIT.MOVE TEDIT.QUIT TEDIT.STRINGWIDTH TEDIT.\INSERT TEXTOBJ TEXTSTREAM \TEDIT.INCLUDE 
	     \TEDIT.INSERT.PIECES \TEDIT.MOVE.PIECEMAPFN \TEDIT.OBJECT.SHOWSEL \TEDIT.CHARDELETE 
	     \TEDIT.COPY.PIECEMAPFN \TEDIT.DELETE \TEDIT.FOREIGN.COPY? \TEDIT.QUIT \TEDIT.WORDDELETE 
	     \TEDIT1)
	(COMS (* Debugging functions)
	      (FNS PLCHAIN PRINTLINE SEEFILE))
	(COMS (* Object-oriented editing)
	      (FNS TEDIT.INSERT.OBJECT TEDIT.EDIT.OBJECT TEDIT.FIND.OBJECT TEDIT.PUT.OBJECT 
		   TEDIT.GET.OBJECT TEDIT.OBJECT.CHANGED))
	(FILES TEDITHCPY TEDITFIND TEDITHISTORY TEDITFILE TEDITWINDOW TEDITSELECTION IMAGEOBJ TFBRAVO 
	       TEDITMENU)
	(COMS (* TEDIT Support information)
	      (E (SETQ TEDITSYSTEMDATE (DATE)))
	      (VARS TEDITSYSTEMDATE)
	      (FNS MAKETEDITFORM)
	      (P (ADDTOVAR LAFITESPECIALFORMS ("TEdit Report" (QUOTE MAKETEDITFORM)
							      "Report a problem with TEdit"))
		 (SETQ LAFITEFORMSMENU NIL)))
	(COMS (* LISTFILES Interface, so the system can decide if a file is a TEdit file.)
	      (ADDVARS (PRINTFILETYPES (TEDIT (TEST \TEDIT.FORMATTEDP1)
					      (EXTENSION (TEDIT])
(FILESLOAD TEXTOFD TEDITCOMMAND TEDITSCREEN TEDITABBREV TEDITLOOKS)
(DECLARE: EVAL@COMPILE 

(RPAQQ \SCRATCHLEN 64)

(CONSTANTS (\SCRATCHLEN 64))
)

(RPAQ? TEDIT.TERMSA.FONTS NIL)

(RPAQ? TEDIT.TENTATIVE NIL)

(RPAQ? TEDIT.DEFAULT.PROPS NIL)

(RPAQ? TEDIT.STARTUP.MONITORLOCK (CREATE.MONITORLOCK (QUOTE TEDIT.STARTUP)))

(RPAQ TEDIT.RESTART.MENU (CREATE MENU ITEMS← (QUOTE (NewEditProcess))))
(DECLARE: DOEVAL@COMPILE DONTCOPY

(ADDTOVAR GLOBALVARS TEDIT.TENTATIVE TEDIT.DEFAULT.PROPS)
)
(DEFINEQ

(\TEDIT2
  [LAMBDA (TEXT WINDOW UNSPAWNED)                            (* jds "25-Apr-84 15:05")
                                                             (* Does the actual editing work, once TEDIT has 
							     OPENTEXTSTREAMed the thing to be edited.)
    (\TEDIT.COMMAND.LOOP (fetch (TEXTSTREAM TEXTOBJ) of TEXT))
                                                             (* Run the editing engine)
    (CLOSEW WINDOW)                                          (* Close the edit window)
    (\TEXTCLOSEF TEXT)                                       (* Close the underlying files)
    (replace ACCESSBITS of TEXT with BothBits)               (* But leave the stream itself accessible)
    (replace \WINDOW of (fetch (TEXTSTREAM TEXTOBJ) of TEXT) with NIL)
                                                             (* And disconnect it from the TEXTOBJ)
    (AND (WINDOWPROP WINDOW (QUOTE TEDIT.AFTERQUITFN))
	 (APPLY* (WINDOWPROP WINDOW (QUOTE TEDIT.AFTERQUITFN))
		 WINDOW TEXT))                               (* Apply any post-window-close 
							     (and post-QUIT) function)
    (COND
      (UNSPAWNED                                             (* We're not a distinct process: Send back the edited 
							     text in some suitable form)
		 (COND
		   ((NEQ (fetch EDITFINISHEDFLG of (fetch (TEXTSTREAM TEXTOBJ) of TEXT))
			 T)
		     (PROG1 (fetch EDITFINISHEDFLG of (fetch (TEXTSTREAM TEXTOBJ) of TEXT))
			    (replace EDITFINISHEDFLG of (fetch (TEXTSTREAM TEXTOBJ) of TEXT)
			       with NIL)))
		   ((STRINGP (fetch TXTFILE of (fetch (TEXTSTREAM TEXTOBJ) of TEXT)))
		     (COERCETEXTOBJ (fetch (TEXTSTREAM TEXTOBJ) of TEXT)
				    (QUOTE STRINGP)))
		   (T TEXT)))
      (T                                                     (* We're a distinct process. Just die)
	 (KILL.ME])

(COERCETEXTOBJ
  [LAMBDA (STREAM TYPE)                                      (* gbn " 7-May-84 22:26")
                                                             (* Coerce the contents of the TEXOTBJ to be of the given
							     type. This is for making a string from a textobj, e.g.)
    (PROG ((TEXTOBJ (COND
		      ((type? STREAM STREAM)
			(fetch (TEXTSTREAM TEXTOBJ) of STREAM))
		      (T STREAM)))
	   OFILE FMTFILE)
          (OR (type? TEXTOBJ TEXTOBJ)
	      (\ILLEGAL.ARG TEXTOBJ))                        (* If we haven't got a TEXTOBJ, something is wrong.)
          (RETURN (SELECTQ TYPE
			   (STRINGP (PROG ((STR (ALLOCSTRING (fetch TEXTLEN of TEXTOBJ)))
					   PC
					   (CH# 1)
					   (PCTB (fetch PCTB of TEXTOBJ))
					   PFILE)
				          [for I from (ADD1 \FirstPieceOffset)
					     to (IDIFFERENCE (\EDITELT PCTB \PCTBLastPieceOffset)
							     2)
					     by \EltsPerPiece
					     do (SETQ PC (\EDITELT PCTB I))
						(COND
						  ((ATOM PC)
                                                             (* It's the lastpiece atom -- do nothing.)
						    )
						  [(fetch PSTR of PC)
						    [OR (ZEROP (fetch PLEN of PC))
							(RPLSTRING STR CH#
								   (SUBSTRING (fetch PSTR
										 of PC)
									      1
									      (fetch PLEN
										 of PC]
						    (SETQ CH# (IPLUS CH# (fetch PLEN of PC]
						  [(SETQ PFILE (fetch PFILE of PC))
						    [COND
						      ((NOT (OPENP PFILE))
							(REPLACE PFILE OF PC
							   WITH (SETQ PFILE (OPENSTREAM PFILE
											(QUOTE INPUT]
						    (SETFILEPTR PFILE (fetch PFPOS of PC))
						    (for C from CH# as I from 1
						       to (fetch PLEN of PC)
						       do (RPLCHARCODE STR C (BIN PFILE)))
						    (SETQ CH# (IPLUS CH# (fetch PLEN of PC]
						  [(fetch POBJ of PC)
                                                             (* DO NOTHING FOR OBJECTS)
						    (SETQ CH# (IPLUS CH# (fetch PLEN of PC]
						  (T (ERROR "CANNOT GET TEXT FROM A 'PIECE.'" PC]
				          (RETURN STR)))
			   (STREAM (COND
				     ((type? STREAM (fetch TXTFILE of TEXTOBJ))
				       (OPENFILE (fetch FULLNAME of (fetch TXTFILE of TEXTOBJ))
						 (QUOTE INPUT))
				       (replace ACCESSBITS of (fetch TXTFILE of TEXTOBJ)
					  with ReadBit)))
				   (\SETUPGETCH 1 TEXTOBJ)
				   STREAM)
			   (FILE (SETQ OFILE (OPENFILE (QUOTE {CORE}TEDITOUTPUT.TMP)
						       (QUOTE BOTH)
						       (QUOTE NEW)))
				 (TEDIT.PUT.PCTB TEXTOBJ OFILE)
				 (CLOSEF OFILE)
				 OFILE)
			   (SPLIT                            (* I.e., Return 2 files, one with plain text, one with 
							     formatting info, such that concatenating them will do 
							     the right thing.)
				  (SETQ OFILE (OPENFILE (QUOTE {NODIRCORE})
							(QUOTE BOTH)
							(QUOTE NEW)))
				  (SETQ FMTFILE (TEDIT.PUT.PCTB TEXTOBJ OFILE NIL T))
				  (CLOSEF OFILE)
				  (CONS OFILE FMTFILE))
			   NIL])

(TEDIT
  [LAMBDA (TEXT WINDOW DONTSPAWN PROPS)                      (* jds "16-May-84 17:09")
                                                             (* User entry to the text editor.
							     Takes an optional window to be used for editing)
                                                             (* DONTSPAWN => Don't try to create a new process for 
							     this edit.)
    (PROG ((TPROPS (APPEND PROPS (COPY TEDIT.DEFAULT.PROPS)))
	   PROC)                                             (* Inlcude the default properties in the list.)
          [COND
	    ((AND TEXT (ATOM TEXT))                          (* Make sure the file exists before trying to open the 
							     window.)
	      (SETQ TEXT (OPENFILE TEXT (QUOTE INPUT)
				   (QUOTE OLD]
          (WITH.MONITOR TEDIT.STARTUP.MONITORLOCK [OR WINDOW (SETQ WINDOW
							(COND
							  ((OR (NOT TEDIT.DEFAULT.WINDOW)
							       (\TEDIT.ACTIVE.WINDOWP 
									     TEDIT.DEFAULT.WINDOW))
							    (TEDIT.CREATEW 
						"Please specify a REGION for the editing window."
									   TEXT))
							  (T (CLEARW TEDIT.DEFAULT.WINDOW)
							     (WINDOWPROP TEDIT.DEFAULT.WINDOW
									 (QUOTE TITLE)
									 (\TEDIT.ORIGINAL.WINDOW.TITLE
									   TEXT))
							     (WINDOWPROP TEDIT.DEFAULT.WINDOW
									 (QUOTE TEDITCREATED)
									 T)
                                                             (* Replace the old title)
							     TEDIT.DEFAULT.WINDOW]
			(SETQ TEXT (OPENTEXTSTREAM TEXT WINDOW NIL NIL PROPS)))
          (COND
	    (DONTSPAWN                                       (* Either no processes running, or specifically not to 
							     spawn one.)
		       (RETURN (\TEDIT2 TEXT WINDOW T)))
	    (T                                               (* Spawn a process to do the edit.)
	       (SETQ PROC (ADD.PROCESS (LIST (QUOTE \TEDIT2)
					     (KWOTE TEXT)
					     WINDOW NIL)
				       (QUOTE NAME)
				       (QUOTE TEdit)
				       (QUOTE RESTARTABLE)
				       (QUOTE HARDRESET)))
	       (PROCESSPROP PROC (QUOTE WINDOW)
			    WINDOW)
	       (COND
		 ((NOT (LISTGET TPROPS (QUOTE LEAVETTY)))    (* Unless he asked us to leave the tty where it is, 
							     TEdit should get it.)
		   (TTY.PROCESS PROC)))
	       (RETURN PROC])

(TEDIT.CHARWIDTH
  [LAMBDA (CH FONT TERMSA)                                   (* jds "22-OCT-83 19:32")
                                                             (* Returns the width of CH in FONT printed according to 
							     any special printing instructions in CHARTABLE TERMSA)
    (COND
      (TERMSA                                                (* There IS a TERMTABLE to account for)
	      (SELECTC (fetch CCECHO of (\SYNCODE TERMSA CH))
		       (INDICATE.CCE (IPLUS (COND
					      ((IGREATERP CH 127)
                                                             (* META character)
						(SETQ CH (LOGAND CH 127))
						(CHARWIDTH (CHARCODE #)
							   FONT))
					      (T 0))
					    (COND
					      ((ILESSP CH 32)
                                                             (* CONTROL character)
						(SETQ CH (LOGOR CH 64))
						(CHARWIDTH (CHARCODE ↑)
							   FONT))
					      (T 0))
					    (CHARWIDTH CH FONT)))
		       (SIMULATE.CCE (SELCHARQ CH
					       ((EOL CR LF)
						 (IMAX 6 (CHARWIDTH CH FONT)))
					       (ESCAPE (CHARWIDTH (CHARCODE $)
								  FONT))
					       (BELL 0)
					       (TAB 36)
					       (CHARWIDTH CH FONT)))
		       (REAL.CCE (CHARWIDTH CH FONT))
		       (IGNORE.CCE 0)
		       (SHOULDNT)))
      (T                                                     (* The usual case is to treat every character as a 
							     graphic.)
	 (SELCHARQ CH
		   (CR (IMAX 6 (CHARWIDTH CH FONT)))
		   (TAB 36)
		   (CHARWIDTH CH FONT])

(TEDIT.COPY
  [LAMBDA (FROM TO)                                          (* jds "21-May-84 16:43")
    (SETQ TEDIT.COPY.PENDING NIL)                            (* First, Turn off the global flag that got us here.)
    (COND
      ((NOT (AND FROM (fetch SET of FROM)))                  (* There MUST be a source selected first.)
	(TEDIT.PROMPTPRINT (fetch \TEXTOBJ of TO)
			   "Copy source selection hasn't been set yet." T))
      (T (\SHOWSEL FROM NIL NIL)                             (* Before all else, make sure the copy source selection 
							     is turned off)
	 (replace SET of FROM with NIL)
	 (COND
	   ((AND TO (fetch SET of TO))                       (* Can only do copy if there's a target selection)
	     (PROG ((TOOBJ (fetch \TEXTOBJ of TO))
		    (FROMOBJ (fetch \TEXTOBJ of FROM))
		    (CROSSCOPY (NEQ (fetch \TEXTOBJ of FROM)
				    (fetch \TEXTOBJ of TO)))
		    TOLEN LEN INSPC INSPC# PC NPC PCCH NPCCH OPLEN EVENT REPLACING INSERTCH# PCLST 
		    OBJ COPYFN UNDOCHAIN)
	           (SETQ PCLST (TEDIT.SELECTED.PIECES FROMOBJ FROM CROSSCOPY (FUNCTION 
							\TEDIT.COPY.PIECEMAPFN)
						      FROMOBJ TOOBJ))
                                                             (* Get the list of pieces to be copied)
	           (TEDIT.DO.BLUEPENDINGDELETE TO TOOBJ)     (* Do any blue-pending-delete)
	           (SETQ TOLEN (fetch TEXTLEN of TOOBJ))
	           (\SHOWSEL TO NIL NIL)                     (* NOW turn off the target selection.)
	           [COND
		     ((EQ (fetch POINT of TO)
			  (QUOTE LEFT))
		       (SETQ INSERTCH# (fetch CH# of TO)))
		     (T (SETQ INSERTCH# (ADD1 (IMIN (fetch CHLIM of TO)
						    TOLEN]   (* Figure out where to do the insertion.)
	           (SETQ UNDOCHAIN (\TEDIT.INSERT.PIECES TOOBJ INSERTCH# PCLST
							 [SETQ LEN
							   (ADD1 (IDIFFERENCE (fetch CHLIM
										 of FROM)
									      (fetch CH#
										 of FROM]
							 NIL NIL CROSSCOPY))
	           (SETQ EVENT (fetch TXTHISTORY of TOOBJ))
	           [SETQ REPLACING (AND (EQ (fetch THACTION of EVENT)
					    (QUOTE Delete))
					(IEQP INSERTCH# (fetch THCH# of EVENT]
	           (\TEDIT.HISTORYADD TOOBJ (create TEDITHISTORYEVENT
						    THACTION ←(COND
						      (REPLACING (QUOTE Replace))
						      (T (QUOTE Copy)))
						    THLEN ← LEN
						    THCH# ← INSERTCH#
						    THFIRSTPIECE ← UNDOCHAIN
						    THOLDINFO ←(AND REPLACING EVENT)))
                                                             (* Make a history-list entry for the COPY.)
	           (replace \DIRTY of TOOBJ with T)          (* Mark the document changed)
	           (replace TEXTLEN of TOOBJ with (IPLUS LEN TOLEN))
                                                             (* Set the new length)
                                                             (* Do the actual copy)
	           (\FIXILINES TOOBJ TO INSERTCH# LEN TOLEN)
                                                             (* Fix LINES and SELs)
	           (COND
		     ((EQ (fetch FORMATTEDP of TOOBJ)
			  (fetch FORMATTEDP of FROMOBJ))     (* Either both of the files are formatted or neither is.
							     This case is OK)
		       )
		     ((fetch FORMATTEDP of TOOBJ)            (* The source wasn't formatted, but the target is.
							     Go convert the copied text.)
		       (\TEDIT.CONVERT.TO.FORMATTED TOOBJ INSERTCH# (IPLUS INSERTCH# LEN)))
		     (T                                      (* The source is formatted and the target isn't.
							     Give the guy a choice.)
                                                             (* For now, convert the target file to formatted.)
			(\TEDIT.CONVERT.TO.FORMATTED TOOBJ)))
	           (TEDIT.UPDATE.SCREEN TOOBJ)               (* Refresh the display)
	           (replace CH# of TO with INSERTCH#)        (* Correct the target selection)
	           (replace CHLIM of TO with (IPLUS INSERTCH# LEN -1))
	           (replace DCH of TO with LEN)
	           (replace DX of TO with 0)
	           (replace POINT of TO with (QUOTE RIGHT))
	           (\FIXSEL TO TOOBJ)
	           (\SHOWSEL TO NIL T)))
	   (T                                                (* There is no target selection -- complain)
	      (TEDIT.PROMPTPRINT (fetch \TEXTOBJ of FROM)
				 "Please select a destination for the copy first." T])

(TEDIT.DELETE
  [LAMBDA (STREAM SEL LEN)                                   (* jds "15-Feb-84 16:16")
                                                             (* DELETE THE CHARACTERS SPECIFIED FROM THE MAIN TEXT.)
    (PROG ((TEXTOBJ (TEXTOBJ STREAM)))
          [COND
	    ((FIXP SEL)
	      (TEDIT.SETSEL STREAM SEL LEN)
	      (SETQ SEL (fetch SEL of TEXTOBJ]
          (OR SEL (SETQ SEL (fetch SEL of TEXTOBJ)))
          (\TEDIT.DELETE SEL TEXTOBJ])

(TEDIT.DO.BLUEPENDINGDELETE
  [LAMBDA (SEL TEXTOBJ)                                      (* jds " 6-Jan-84 16:00")
                                                             (* Check for blue-pending-delete, and do it if it's 
							     there.)
    (COND
      ((fetch BLUEPENDINGDELETE of TEXTOBJ)                  (* If he's in a Blue-pending-delete state, delete the 
							     selection.)
	(\TEDIT.DELETE SEL (fetch \TEXTOBJ of SEL))
	(\SHOWSEL SEL NIL NIL)
	(TEDIT.RESET.EXTEND.PENDING.DELETE SEL)
	(\SHOWSEL SEL NIL T])

(TEDIT.INSERT
  [LAMBDA (STREAM TEXT CH#ORSEL LOOKS DONTSCROLL)            (* jds "21-May-84 16:44")
                                                             (* Insert TEXT (character, litatom or string) at the 
							     appropriate spot in the text.)
    (SETQ STREAM (TEXTSTREAM STREAM))
    [COND
      ((FIXP CH#ORSEL)                                       (* He gave us a ch# to insert before)
	(TEDIT.SETSEL STREAM CH#ORSEL 1 (QUOTE LEFT]
    [COND
      ((LITATOM TEXT)
	(SETQ TEXT (MKSTRING TEXT]
    [OR (type? SELECTION CH#ORSEL)
	(SETQ CH#ORSEL (fetch SEL of (fetch (TEXTSTREAM TEXTOBJ) of STREAM]
    (COND
      ((AND CH#ORSEL (fetch SET of CH#ORSEL))
	(PROG ((TEXTOBJ (fetch (TEXTSTREAM TEXTOBJ) of STREAM))
	       CH# LINE XPOINT OTEXTLEN DS LINES CHARS BLANKSEEN CRSEEN)
	      (COND
		(LOOKS                                       (* If looks for this insertion were specified, set them 
							     up.)
		       (TEDIT.CARETLOOKS STREAM LOOKS)))
	      (SETQ DS (fetch DS of TEXTOBJ))
	      (SETQ OTEXTLEN (fetch TEXTLEN of TEXTOBJ))     (* The PRE-INSERT text length, for starting the screen 
							     update process)
	      (COND
		((fetch \WINDOW of TEXTOBJ)                  (* If this text is in a window, move it so the insertion
							     point is on-screen, then turn off the selection 
							     highlight)
		  (COND
		    ((NOT DONTSCROLL)                        (* If DONTSCROLL is T, then don't bother scrolling the 
							     window to show the change.)
		      (TEDIT.NORMALIZECARET TEXTOBJ CH#ORSEL)))
		  (\SHOWSEL CH#ORSEL NIL NIL)))
	      (SETQ CH# (IMAX 1 (SELECTQ (fetch POINT of CH#ORSEL)
					 (LEFT (fetch CH# of CH#ORSEL))
					 [RIGHT (ADD1 (IMIN (fetch TEXTLEN of TEXTOBJ)
							    (fetch CHLIM of CH#ORSEL]
					 NIL)))
	      (SETQ LINE (SELECTQ (fetch POINT of CH#ORSEL)
				  (LEFT (fetch L1 of CH#ORSEL))
				  (RIGHT (fetch LN of CH#ORSEL))
				  NIL))
	      (SETQ XPOINT (SELECTQ (fetch POINT of CH#ORSEL)
				    (LEFT (fetch X0 of CH#ORSEL))
				    (RIGHT (fetch XLIM of CH#ORSEL))
				    NIL))
	      [COND
		[(type? STRINGP TEXT)                        (* It's a string: Count the characters and Insert them 
							     one by one into the text stream)
		  (SETQ CHARS (NCHARS TEXT))
		  (for ACHAR instring TEXT as NCH# from CH# by 1
		     do (SELCHARQ ACHAR
				  (CR (SETQ CRSEEN T)
				      (\INSERTCR ACHAR NCH# TEXTOBJ))
				  (SPACE (SETQ BLANKSEEN T)
					 (\INSERTCH ACHAR NCH# TEXTOBJ))
				  (\INSERTCH ACHAR NCH# TEXTOBJ]
		(T                                           (* It's a singe character. Just insert it.)
		   (SETQ CHARS 1)
		   (SELCHARQ TEXT
			     (CR (SETQ CRSEEN T)
				 (\INSERTCR TEXT CH# TEXTOBJ))
			     (SPACE (SETQ BLANKSEEN T)
				    (\INSERTCH TEXT CH# TEXTOBJ))
			     (\INSERTCH TEXT CH# TEXTOBJ]
	      (\FIXILINES TEXTOBJ CH#ORSEL CH# CHARS OTEXTLEN)
                                                             (* Fix up the line descriptors and the Selection.)
	      (AND LINE (TEDIT.INSERT.UPDATESCREEN TEXT CH# CHARS XPOINT TEXTOBJ CH#ORSEL LINE 
						   OTEXTLEN BLANKSEEN CRSEEN DS))
                                                             (* Update the edit window.)
	  ))
      (T (TEDIT.PROMPTPRINT TEXTOBJ "Please select a place for the insertion." T])

(TEDIT.KILL
  [LAMBDA (STREAM)                                           (* jds "14-Feb-84 16:29")
                                                             (* Force the edit session supported by STREAM to 
							     terminate, and to return VALUE)
    (COND
      ((type? STREAM STREAM)                                 (* If he gave us a textofd, get the textobj)
	(SETQ STREAM (fetch (TEXTSTREAM TEXTOBJ) of STREAM)))
      [(WINDOWP STREAM)                                      (* Take a window, and do the obvious with it.)
	(SETQ STREAM (WINDOWPROP STREAM (QUOTE TEXTOBJ]
      ((type? TEXTOBJ STREAM)                                (* A Textobj is just fine)
	)
      (T                                                     (* Anything else is ungood, double-plus)
	 (\ILLEGAL.ARG STREAM)))
    (replace EDITFINISHEDFLG of STREAM with T)
    (PROG (TEDW TEDPROC)
          (AND (SETQ TEDW (fetch \WINDOW of STREAM))
	       [PROCESSP (SETQ TEDPROC (WINDOWPROP TEDW (QUOTE PROCESS]
	       (NEQ TEDPROC (THIS.PROCESS))
	       (DEL.PROCESS TEDPROC)
	       (TEDIT.DEACTIVATE.WINDOW TEDW])

(TEDIT.MAPLINES
  [LAMBDA (TEXTOBJ FN)                                       (* jds "18-Jan-84 14:30")
                                                             (* Go thru the visible lines in a textobj and call a 
							     mapping fn on them)
                                                             (* FN has 2 args: the LINEDESCRIPTOR, and a VISIBLEFLG 
							     to say if the line is visible on the screen.)
    (bind (LINE ←(fetch NEXTLINE of (fetch LINES of TEXTOBJ)))
	  (BOT ← 0)
	  [TOP ←(fetch HEIGHT of (DSPCLIPPINGREGION (\TEDIT.MAINW TEXTOBJ] while LINE
       do (COND
	    ((EQ (APPLY* FN LINE (AND (ILESSP (fetch YBOT of LINE)
					      TOP)
				      (IGREATERP (fetch YBOT of LINE)
						 BOT)))
		 (QUOTE STOP))
	      (RETURN)))
	  (SETQ LINE (fetch NEXTLINE of LINE])

(TEDIT.MAPPIECES
  [LAMBDA (TEXTOBJ FN FNARG)                                 (* jds "28-Mar-84 17:58")
                                                             (* Go thru all the pieces in a document, applying a 
							     function to them serially)
                                                             (* FN is a function of 3 args 
							     (PIECE CH#-of-1st-char-in-piece PIECE# in table FNARG))
    (PROG ((PCTB (fetch PCTB of TEXTOBJ)))
          (RETURN (bind (BASE ←(\ADDBASE2 (fetch (ARRAYP BASE) of PCTB)
					  \FirstPieceOffset))
		     for I from \FirstPieceOffset to (IDIFFERENCE (ELT PCTB \PCTBLastPieceOffset)
								  \EltsPerPiece)
		     by \EltsPerPiece
		     do [COND
			  ((EQ (APPLY* FN (\GETBASEPTR BASE 0)
				       (\GETBASEPTR BASE 2)
				       I FNARG)
			       (QUOTE STOP))
			    (RETURN (LIST (\GETBASEPTR BASE 0)
					  (\GETBASEPTR BASE 2)
					  I]
			(SETQ BASE (\ADDBASE BASE (CONSTANT (IPLUS \EltsPerPiece \EltsPerPiece])

(TEDIT.MOVE
  [LAMBDA (FROM TO)                                          (* jds "21-May-84 16:44")
    (SETQ TEDIT.MOVE.PENDING NIL)                            (* First, Turn off the global flag that got us here.)
    (COND
      ((NOT (AND FROM (fetch SET of FROM)))                  (* There MUST be a source selected first.)
	(TEDIT.PROMPTPRINT (fetch \TEXTOBJ of TO)
			   "Copy source selection hasn't been set yet." T))
      (T (\SHOWSEL FROM NIL NIL)                             (* Before all else, make sure the copy source selection 
							     is turned off)
	 (COND
	   ((AND TO (fetch SET of TO))                       (* Can only do copy if there's a target selection)
	     (PROG ((FROMCH1 (fetch CH# of FROM))
		    (FROMCHLIM (fetch CHLIM of FROM))
		    (TOOBJ (fetch \TEXTOBJ of TO))
		    (FROMOBJ (fetch \TEXTOBJ of FROM))
		    (TOLEN (fetch TEXTLEN of (fetch \TEXTOBJ of TO)))
		    (TOPCTB (fetch PCTB of (fetch \TEXTOBJ of TO)))
		    (FROMPCTB (fetch PCTB of (fetch \TEXTOBJ of FROM)))
		    (CROSSCOPY (NEQ (fetch \TEXTOBJ of FROM)
				    (fetch \TEXTOBJ of TO)))
		    LEN INSPC INSPC# PC NPC PCCH NPCCH OPLEN EVENT REPLACING INSERTCH# PCLST OBJ 
		    COPYFN UNDOCHAIN)                        (* Find the insertion point)
	           (SETQ PCLST (TEDIT.SELECTED.PIECES FROMOBJ FROM CROSSCOPY (FUNCTION 
							\TEDIT.MOVE.PIECEMAPFN)
						      FROMOBJ TOOBJ))
	           (TEDIT.DO.BLUEPENDINGDELETE TO TOOBJ)     (* Do any blue-pending-delete)
	           (SETQ TOPCTB (fetch PCTB of TOOBJ))       (* Get the new PCTB and text length)
	           (SETQ EVENT (fetch TXTHISTORY of TOOBJ))
	           [SETQ LEN (ADD1 (IDIFFERENCE (fetch CHLIM of FROM)
						(fetch CH# of FROM]
	           (\TEDIT.DELETE FROM FROMOBJ T)            (* Now delete the text from its old place)
	           (SETQ TOLEN (fetch TEXTLEN of TOOBJ))
	           (\SHOWSEL TO NIL NIL)                     (* NOW turn off the target selection.)
	           (replace SET of FROM with NIL)
	           [COND
		     ((EQ (fetch POINT of TO)
			  (QUOTE LEFT))
		       (SETQ INSERTCH# (fetch CH# of TO)))
		     (T (SETQ INSERTCH# (ADD1 (IMIN (fetch CHLIM of TO)
						    TOLEN]   (* Figure out where to do the insertion.)
	           (SETQ UNDOCHAIN (\TEDIT.INSERT.PIECES TOOBJ INSERTCH# PCLST LEN NIL NIL CROSSCOPY))
	           [SETQ REPLACING (AND (EQ (fetch THACTION of EVENT)
					    (QUOTE Delete))
					(IEQP INSERTCH# (fetch THCH# of EVENT]
	           (\TEDIT.HISTORYADD TOOBJ (create TEDITHISTORYEVENT
						    THACTION ←(COND
						      (REPLACING (QUOTE ReplaceMove))
						      (T (QUOTE Move)))
						    THLEN ← LEN
						    THCH# ← INSERTCH#
						    THFIRSTPIECE ← UNDOCHAIN
						    THAUXINFO ← FROMOBJ
						    THOLDINFO ←(fetch CH# of FROM)))
                                                             (* Make a history-list entry for the COPY.)
	           (replace \DIRTY of TOOBJ with T)          (* Mark the document changed)
	           (replace TEXTLEN of TOOBJ with (IPLUS LEN TOLEN))
                                                             (* Set the new length)
                                                             (* Do the actual copy)
	           (\FIXILINES TOOBJ TO INSERTCH# LEN TOLEN)
                                                             (* Fix LINES and SELs)
	           (COND
		     ((EQ (fetch FORMATTEDP of TOOBJ)
			  (fetch FORMATTEDP of FROMOBJ))     (* Either both of the files are formatted or neither is.
							     This case is OK)
		       )
		     ((fetch FORMATTEDP of TOOBJ)            (* The source wasn't formatted, but the target is.
							     Go convert the copied text.)
		       (\TEDIT.CONVERT.TO.FORMATTED TOOBJ INSERTCH# (IPLUS INSERTCH# LEN)))
		     (T                                      (* The source is formatted and the target isn't.
							     Give the guy a choice.)
                                                             (* For now, convert the target file to formatted.)
			(\TEDIT.CONVERT.TO.FORMATTED TOOBJ)))
	           (TEDIT.UPDATE.SCREEN TOOBJ)               (* Refresh the display)
	           (replace CH# of TO with INSERTCH#)        (* Correct the target selection)
	           (replace CHLIM of TO with (IPLUS INSERTCH# LEN -1))
	           (replace DCH of TO with LEN)
	           (replace DX of TO with 0)
	           (replace POINT of TO with (QUOTE RIGHT))
	           (\FIXSEL TO TOOBJ)
	           (\SHOWSEL TO NIL T)))
	   (T                                                (* There is no target selection -- complain)
	      (TEDIT.PROMPTPRINT (fetch \TEXTOBJ of FROM)
				 "Please select a destination for the copy first." T])

(TEDIT.QUIT
  [LAMBDA (STREAM VALUE)                                     (* gbn "18-Apr-84 15:02")
                                                             (* Force the edit session supported by STREAM to 
							     terminate, and to return VALUE)
    (COND
      ((type? STREAM STREAM)                                 (* If he gave us a textofd, get the textobj)
	(SETQ STREAM (fetch (TEXTSTREAM TEXTOBJ) of STREAM)))
      ((type? TEXTOBJ STREAM)                                (* A Textobj is just fine)
	)
      (T                                                     (* Anything else is ungood, double-plus)
	 (\ILLEGAL.ARG STREAM)))
    (replace EDITFINISHEDFLG of STREAM with (OR VALUE T))    (* tell the command loop to stop next time through)
    (PROG (MAINW)
          (COND
	    ([AND (fetch \WINDOW of STREAM)
		  (NEQ (SETQ MAINW (\TEDIT.MAINW STREAM))
		       (PROCESSPROP (TTY.PROCESS)
				    (QUOTE WINDOW]           (* there is a main window of the stream, and it is not 
							     the window of the tty process, so give it the tty)
	      (TTY.PROCESS (WINDOWPROP MAINW (QUOTE PROCESS])

(TEDIT.STRINGWIDTH
  [LAMBDA (STR FONT TERMSA)                                  (* jds "19-AUG-83 14:40")
    (COND
      (TERMSA                                                (* We have a terminal table to take account of.
							     Do so.)
	      (for CH instring STR sum (TEDIT.CHARWIDTH CH FONT TERMSA)))
      (T                                                     (* Just use the native character widths)
	 (for CH instring STR sum (SELCHARQ CH
					    (TAB 36)
					    (CHARWIDTH CH FONT])

(TEDIT.\INSERT
  [LAMBDA (CH SEL STREAM BLANKSEEN CRSEEN SKIPINSERT)        (* jds "21-May-84 16:45")
                                                             (* Insert the character CH at the appropriate spot in 
							     the text.)
    (DECLARE (LOCALVARS . T))
    (PROG [(TEXTOBJ (COND
		      ((type? STREAM STREAM)                 (* If we got a STREAM, change it into a textobj)
			(fetch (TEXTSTREAM TEXTOBJ) of STREAM))
		      (T STREAM]
          (COND
	    ((NOT (AND SEL (fetch SET of SEL)))
	      (TEDIT.PROMPTPRINT TEXTOBJ "Please select a place for the insertion." T)
	      (RETURN)))
          (COND
	    ((fetch \WINDOW of TEXTOBJ)                      (* There is a window; make sure the insert point is 
							     on-screen, and turn off any highlighted selection)
	      (TEDIT.NORMALIZECARET TEXTOBJ SEL)
	      (\SHOWSEL SEL NIL NIL)))
          (PROG [(CH# (IMAX 1 (SELECTQ (fetch POINT of SEL)
				       (LEFT (fetch CH# of SEL))
				       (RIGHT (ADD1 (fetch CHLIM of SEL)))
				       NIL)))
		 (LINE (SELECTQ (fetch POINT of SEL)
				(LEFT (fetch L1 of SEL))
				(RIGHT (fetch LN of SEL))
				NIL))
		 (XPOINT (SELECTQ (fetch POINT of SEL)
				  (LEFT (fetch X0 of SEL))
				  (RIGHT (fetch XLIM of SEL))
				  NIL))
		 (OTEXTLEN (fetch TEXTLEN of TEXTOBJ))
		 (DS (fetch DS of TEXTOBJ))
		 (CHARS (COND
			  ((type? STRINGP CH)
			    (NCHARS CH))
			  (T 1]
	        [OR SKIPINSERT (COND
		      (CRSEEN                                (* This was a CR. Go do the para breaking as needed)
			      (\INSERTCR CH CH# TEXTOBJ))
		      (T                                     (* No para breaks. Just insert the character)
			 (\INSERTCH CH CH# TEXTOBJ]
	        (\FIXILINES TEXTOBJ SEL CH# CHARS OTEXTLEN)
	        (TEDIT.INSERT.UPDATESCREEN CH CH# CHARS XPOINT TEXTOBJ SEL LINE OTEXTLEN BLANKSEEN 
					   CRSEEN DS])

(TEXTOBJ
  [LAMBDA (STREAM)                                           (* jds "20-Apr-84 15:29")
                                                             (* Convert from a text stream to the associated textobj)
    (COND
      ((type? TEXTOBJ STREAM)
	STREAM)
      ((AND (type? STREAM STREAM)
	    (fetch (TEXTSTREAM TEXTOBJ) of STREAM)
	    (type? TEXTOBJ (fetch (TEXTSTREAM TEXTOBJ) of STREAM)))
	(fetch (TEXTSTREAM TEXTOBJ) of STREAM))
      [(AND (WINDOWP STREAM)
	    (WINDOWPROP STREAM (QUOTE TEXTOBJ]
      [(AND (DISPLAYSTREAMP STREAM)
	    (WINDOWPROP STREAM (QUOTE TEXTOBJ]
      ((\ILLEGAL.ARG STREAM])

(TEXTSTREAM
  [LAMBDA (STREAM)                                           (* jds "20-Apr-84 15:29")
                                                             (* Force a textobj or stream to be a stream)
    (COND
      ((AND (type? STREAM STREAM)
	    (fetch (TEXTSTREAM TEXTOBJ) of STREAM)
	    (type? TEXTOBJ (fetch (TEXTSTREAM TEXTOBJ) of STREAM)))
	STREAM)
      ((type? TEXTOBJ STREAM)
	(fetch STREAMHINT of STREAM))
      [(AND (WINDOWP STREAM)
	    (WINDOWPROP STREAM (QUOTE TEXTSTREAM]
      [(AND (DISPLAYSTREAMP STREAM)
	    (WINDOWPROP STREAM (QUOTE TEXTSTREAM]
      ((\ILLEGAL.ARG STREAM])

(\TEDIT.INCLUDE
  [LAMBDA (TEXTOBJ FILE START END)                           (* jds "10-May-84 14:30")
                                                             (* A NATIVE text includer: Includes part of a file, 
							     without checking to see if it's a bravo file, a TEdit 
							     file or whatever.)
    (PROG ((LEN (IDIFFERENCE (OR END (GETEOFPTR FILE))
			     (OR START 0)))
	   (SEL (fetch SEL of TEXTOBJ))
	   NPC)
          (SETQ NPC (create PIECE
			    PFILE ←(\GETOFD FILE (QUOTE INPUT))
			    PFPOS ←(OR START 0)
			    PLEN ← LEN
			    PLOOKS ←(\TEDIT.GET.INSERT.CHARLOOKS TEXTOBJ SEL)
			    PPARALOOKS ← NIL))               (* Create a PIECE to describe the text)
          (\TEDIT.INSERT.PIECES TEXTOBJ (fetch CH# of SEL)
				NPC LEN)                     (* Insert it in the document)
          (add (fetch TEXTLEN of TEXTOBJ)
	       LEN)                                          (* And update the document's length)
          (\TEDIT.MARK.LINES.DIRTY TEXTOBJ (fetch CH# of SEL)
				   (IPLUS (fetch CH# of SEL)
					  LEN))              (* Mark the screen dirty, so updating it will find 
							     something to do)
          (replace CHLIM of SEL with (SUB1 (IPLUS (fetch CH# of SEL)
						  LEN)))
          (replace DCH of SEL with LEN)
          (replace DX of SEL with 0)
          (replace POINT of SEL with (QUOTE RIGHT))
          (replace SELKIND of SEL with (QUOTE CHAR))
          (replace SELOBJ of SEL with NIL)
          (COND
	    ((fetch \WINDOW of TEXTOBJ)
	      (\SHOWSEL SEL NIL NIL)
	      (TEDIT.UPDATE.SCREEN TEXTOBJ)
	      (\FIXSEL SEL TEXTOBJ)
	      (\SHOWSEL SEL NIL T)))                         (* Update the screen)
          (replace \DIRTY of TEXTOBJ with T)
          (\SETUPGETCH (fetch CH# of SEL)
		       TEXTOBJ])

(\TEDIT.INSERT.PIECES
  [LAMBDA (TEXTOBJ CH# FIRSTPIECE #CHARS INSPC INSPC# CROSSCOPY)
                                                             (* gbn " 7-May-84 22:27")

          (* Inserts a series of pieces into TEXTOBJ in front of character CH#. If FIRSTPIECE is a PIECE, this will follow 
	  the next-piece pointer chain; if FIRSTPIECE is a list, it is a list of pieces to insert. If CROSSCOPY is non-NIL, 
	  the pieces' contents will be copied, to preserve text in case the original is deleted. INSPC and INSPC# are 
	  accelerators for where in the PCTB the new pieces should go.)



          (* It is the CALLER'S RESPONSIBILITY to make sure the pieces to be inserted are "safe" --that they are, if 
	  necessary, copies of the originals, and can safely be modified.)


    (PROG ((TOLEN (fetch TEXTLEN of TEXTOBJ))
	   (TOPCTB (fetch PCTB of TEXTOBJ))
	   LEN PC PREVPC NPC UNDOCHAIN PSTR PFILE)
          [SETQ INSPC# (OR INSPC# (\CHTOPCNO CH# TOPCTB)
			   (SUB1 (\EDITELT TOPCTB \PCTBLastPieceOffset]
                                                             (* Get a handle on the piece we're to insert within or 
							     in front of)
          [SETQ INSPC (OR INSPC (\EDITELT TOPCTB (ADD1 INSPC#]
                                                             (* And the piece, itself.)
          (replace \INSERTNEXTCH of TEXTOBJ with -1)         (* Force later insertions to make new pieces.)
          (replace \INSERTFIRSTCH of TEXTOBJ with -1)
          (COND
	    ((IGEQ CH# TOLEN)                                (* We're inserting at end of file;
							     leave the piece to insert before as LASTPIECE)
	      )
	    ((IEQP CH# (\EDITELT TOPCTB INSPC#))             (* The insertion is IN FRONT of this piece;
							     just continue on)
	      )
	    (T (SETQ INSPC (\SPLITPIECE INSPC CH# TEXTOBJ INSPC#))
	       (add INSPC# \EltsPerPiece)))                  (* Nope, we're inserting INSIDE this piece.
							     Split it in two.)
          (COND
	    ((NEQ INSPC (QUOTE LASTPIECE))                   (* Not the last piece, so back up using the pointer.)
	      (SETQ PREVPC (fetch PREVPIECE of INSPC)))
	    [(NOT (ZEROP (fetch TEXTLEN of TEXTOBJ)))        (* If we are at the end, AND there is text before us, 
							     find it thru the pctb.)
	      (SETQ PREVPC (\EDITELT TOPCTB (IDIFFERENCE (\EDITELT TOPCTB \PCTBLastPieceOffset)
							 \EltsPerPiece]
	    (T                                               (* Otherwise, there is no piece before where we're 
							     inserting.)
	       (SETQ PREVPC NIL)))                           (* For pushing para looks in)
          (bind (PC ←(COND
		      ((LISTP FIRSTPIECE)
			(pop FIRSTPIECE))
		      (T FIRSTPIECE)))
		(LEN ← 0)
		(PCCOUNT ← 0) first (SETQ UNDOCHAIN PC) while (AND PC (ILESSP LEN #CHARS))
	     do                                              (* Now insert the copied pieces into the new place)
                                                             (* REPLACED THE CREATE USING HERE WITH PC ITSELF SINCE 
							     WHEN THINGS REACH HERE THEY HAVE ALREADY BEEN COPIED 
							     (GBN DEC 21))
		(COND
		  ((AND CROSSCOPY (SETQ PFILE (fetch PFILE of PC)))

          (* If this is a cross-document copy, and the text comes from a file, we must REALLY make a copy of the text, lest 
	  the source file be deleted.)


		    [replace PSTR of PC with (SETQ PSTR (ALLOCSTRING (fetch PLEN of PC]
		    [COND
		      ((NOT (OPENP PFILE))                   (* The source file was CLOSED -- reopen it, for our us)
			(REPLACE PFILE OF PC WITH (SETQ PFILE (OPENSTREAM PFILE (QUOTE INPUT)
									  (QUOTE OLD]
		    (SETFILEPTR PFILE (fetch PFPOS of PC))
		    (bind (BASE ←(fetch (STRINGP BASE) of PSTR))
			  (OFFST ←(fetch (STRINGP OFFST) of PSTR)) for I from 0
		       to (SUB1 (fetch PLEN of PC))
		       do                                    (* Copy the characters to the string)
			  (PUTBASEBYTE BASE (IPLUS OFFST I)
				       (\BIN PFILE)))
		    (replace PFILE of PC with NIL)           (* And the piece no longer has a file attached.)
		    ))
		[COND
		  ((LISTP FIRSTPIECE)                        (* If the piece list really IS a list, grab the next 
							     piece from the front)
		    (SETQ NPC (pop FIRSTPIECE)))
		  (T                                         (* Otherwise, follow the NEXTPIECE chain among pieces)
		     (SETQ NPC (fetch NEXTPIECE of PC]
		(\INSERTPIECE PC INSPC TEXTOBJ NIL INSPC#) 
                                                             (* Insert the piece into the new document)
		(add INSPC# \EltsPerPiece)
		(add LEN (fetch PLEN of PC))
		(SETQ PC NPC))
          [COND
	    ((AND PREVPC (NOT (fetch PPARALAST of PREVPC)))
                                                             (* We're inserting inside a paragraph--must copy para 
							     looks forward into the text.)
	      (bind (PPLOOKS ←(fetch PPARALOOKS of PREVPC))
		    (PC ←(fetch NEXTPIECE of PREVPC)) while (AND PC (NEQ INSPC PC))
		 do                                          (* Copy para looks info in from the left, up the the 
							     first para break.)
		    (replace PPARALOOKS of PC with PPLOOKS)
		    (COND
		      ((fetch PPARALAST of PC)               (* If this piece ends a paragraph, we're done.)
			(RETURN)))
		    (SETQ PC (fetch NEXTPIECE of PC]
          [COND
	    ((NEQ INSPC (QUOTE LASTPIECE))                   (* Only copy para looks in from the right if there is 
							     text to the right.)
	      (bind (PPLOOKS ←(fetch PPARALOOKS of INSPC))
		    (PC ←(fetch PREVPIECE of INSPC)) while (NEQ PC PREVPC)
		 do                                          (* Copy para looks in from the right, up to the first 
							     para break)
		    (COND
		      ((fetch PPARALAST of PC)               (* If this piece ends a paragraph, we're done.)
			(RETURN)))
		    (replace PPARALOOKS of PC with PPLOOKS)
		    (SETQ PC (fetch PREVPIECE of PC]
          (RETURN UNDOCHAIN])

(\TEDIT.MOVE.PIECEMAPFN
  [LAMBDA (PC TEXTOBJ FROMOBJ TOOBJ)                         (* jds "12-Apr-84 15:34")
                                                             (* Called by TEDIT.MOVE via TEDIT.SELECTED.PIECES, to do
							     the move-operation processing on the candidate pieces.)
    (PROG (OBJ MOVEFN)
          (SETQ PC (create PIECE using PC PNEW ← T))         (* No matter what, we need a fresh copy.)
          [COND
	    ((fetch POBJ of PC)                              (* This piece describes an object)
	      (SETQ OBJ (fetch POBJ of PC))
	      (COND
		((SETQ MOVEFN (IMAGEOBJPROP OBJ (QUOTE WHENMOVEDFN)))
                                                             (* If there's an eventfn for moving, use it.)
		  (APPLY* MOVEFN OBJ (fetch DS of TOOBJ)
			  (fetch STREAMHINT of FROMOBJ)
			  (fetch STREAMHINT of TOOBJ]
          (RETURN PC])

(\TEDIT.OBJECT.SHOWSEL
  [LAMBDA (TEXTOBJ SEL ON SELWINDOW)                         (* jds "11-Apr-84 16:44")
                                                             (* We are hilighting (or dehilighting) a selected 
							     object. Let it know.)
    (PROG ((X (fetch X0 of SEL))
	   (Y (fetch Y0 of SEL))
	   (OBJ (fetch SELOBJ of SEL))
	   (WIDTH (fetch DX of SEL))
	   (XOFFSET (DSPXOFFSET NIL SELWINDOW))
	   (YOFFSET (DSPYOFFSET NIL SELWINDOW))
	   (IMAGEFN (IMAGEOBJPROP (fetch SELOBJ of SEL)
				  (QUOTE WHENOPERATEDONFN)))
	   IMAGEBOX)
          (SETQ IMAGEBOX (OR (IMAGEOBJPROP OBJ (QUOTE BOUNDBOX))
			     (APPLY* (IMAGEOBJPROP OBJ (QUOTE IMAGEBOXFN))
				     OBJ SELWINDOW)))
          (RESETLST (RESETSAVE (DSPXOFFSET (IDIFFERENCE (IPLUS X XOFFSET)
							(fetch XKERN of IMAGEBOX))
					   SELWINDOW)
			       (LIST (FUNCTION DSPXOFFSET)
				     XOFFSET
				     (fetch DS of TEXTOBJ)))
		    (RESETSAVE (DSPYOFFSET (IPLUS Y YOFFSET)
					   SELWINDOW)
			       (LIST (FUNCTION DSPYOFFSET)
				     YOFFSET SELWINDOW))
		    (RESETSAVE (DSPCLIPPINGREGION (create REGION
							  LEFT ← 0
							  BOTTOM ← 0
							  WIDTH ←(IMIN WIDTH
								       (IDIFFERENCE (fetch WRIGHT
										       of TEXTOBJ)
										    X))
							  HEIGHT ←(fetch YSIZE of IMAGEBOX))
						  SELWINDOW)
			       (LIST (FUNCTION DSPCLIPPINGREGION)
				     (DSPCLIPPINGREGION NIL SELWINDOW)
				     SELWINDOW))
		    (AND IMAGEFN (ERSETQ (APPLY* IMAGEFN OBJ SELWINDOW (COND
						   (ON (QUOTE HIGHLIGHTED))
						   (T (QUOTE UNHIGHLIGHTED)))
						 SEL])

(\TEDIT.CHARDELETE
  [LAMBDA (TEXTOBJ SCRATCHSTRING SEL)                        (* jds " 2-May-84 11:14")
                                                             (* Do character-backspace deletion for TEDIT)
    (SETQ TEXTOBJ (TEXTOBJ TEXTOBJ))
    (PROG ((PCTB (fetch PCTB of TEXTOBJ))
	   TLEN INSCH# INSPC INSPC# TLOOKS)
          (COND
	    [[NOT (ZEROP (SETQ TLEN (fetch (STRINGP OFFST) of SCRATCHSTRING]
                                                             (* If we didn't really insert the text yet, just remove 
							     from the text to be inserted)
	      (replace (STRINGP OFFST) of SCRATCHSTRING with (SUB1 TLEN))
	      (replace (STRINGP LENGTH) of SCRATCHSTRING with (ADD1 (fetch (STRINGP LENGTH)
								       of SCRATCHSTRING]
	    (T                                               (* Delete the character just before the current 
							     insertpoint.)
	       (SELECTQ (fetch POINT of SEL)
			[LEFT (SETQ INSCH# (SUB1 (fetch CH# of SEL]
			(RIGHT (SETQ INSCH# (fetch CHLIM of SEL)))
			NIL)
	       (COND
		 ((ILEQ INSCH# 0)                            (* Can't backspace past start of document)
		   (RETURN)))
	       [SETQ INSPC (\EDITELT PCTB (ADD1 (SETQ INSPC# (\CHTOPCNO INSCH# PCTB]
	       (SETQ TLOOKS (\TEDIT.APPLY.STYLES (fetch PLOOKS of INSPC)
						 INSPC TEXTOBJ))
	       [while (AND INSPC (fetch CLINVISIBLE of TLOOKS))
		  do                                         (* Back over any invisible text, which we're no allowed 
							     to delete.)
		     (SETQ INSPC (fetch PREVPIECE of INSPC))
		     (SETQ INSCH# (SUB1 (\EDITELT PCTB INSPC#)))
		     (SETQ INSPC# (IDIFFERENCE INSPC# \EltsPerPiece))
		     (COND
		       (INSPC (SETQ TLOOKS (\TEDIT.APPLY.STYLES (fetch PLOOKS of INSPC)
								INSPC TEXTOBJ]
	       (COND
		 ((ILEQ INSCH# 0)                            (* We backed up to the start of the document.
							     Can't go no further.)
		   (RETURN))
		 ((NOT (fetch CLPROTECTED of TLOOKS))        (* Can only backspace if the char to go isn't 
							     protected.)
		   (replace CH# of SEL with (replace CHLIM of SEL with INSCH#))
                                                             (* Set up the selection to point to the character which 
							     is to be deleted.)
		   (replace DCH of SEL with 1)
		   (\SHOWSEL SEL NIL NIL)                    (* Turn off the underlining, if any, so there's no 
							     garbage.)
		   (\FIXSEL SEL TEXTOBJ)                     (* Fix the selection up so it points to the right line 
							     and all)
		   (\TEDIT.DELETE SEL TEXTOBJ T)             (* And delete it.)
		   ])

(\TEDIT.COPY.PIECEMAPFN
  [LAMBDA (PC TEXTOBJ FROMOBJ TOOBJ)                         (* jds "24-May-84 17:04")
                                                             (* Called by TEDIT.COPY via TEDIT.SELECTED.PIECES, to do
							     the copy-operation processing on the candidate pieces.)
    (PROG (OBJ NEWOBJ COPYFN)
          (SETQ PC (create PIECE using PC PNEW ← T))         (* No matter what, we need a fresh copy.)
          [COND
	    ((fetch POBJ of PC)                              (* This piece describes an object)
	      (SETQ OBJ (fetch POBJ of PC))
	      [COND
		[(SETQ COPYFN (IMAGEOBJPROP OBJ (QUOTE COPYFN)))
		  (SETQ NEWOBJ (APPLY* COPYFN OBJ (fetch STREAMHINT of FROMOBJ)
				       (fetch STREAMHINT of TOOBJ)))
		  (COND
		    ((EQ NEWOBJ (QUOTE DON'T))               (* He said not to copy this piece -- abort the whole 
							     copy.)
		      (TEDIT.PROMPTPRINT TEXTOBJ "COPY of this object not allowed." T)
		      (RETFROM (QUOTE TEDIT.COPY)))
		    (NEWOBJ (replace POBJ of PC with NEWOBJ))
		    (T (replace POBJ of PC with (COPYALL OBJ]
		(OBJ                                         (* No copy fn; just strike off a copy of our own)
		     (replace POBJ of PC with (COPYALL OBJ]
	      (COND
		((SETQ COPYFN (IMAGEOBJPROP OBJ (QUOTE WHENCOPIEDFN)))
                                                             (* If there's an eventfn for copying, use it.)
		  (APPLY* COPYFN OBJ (fetch DS of TOOBJ)
			  (fetch STREAMHINT of FROMOBJ)
			  (fetch STREAMHINT of TOOBJ]
          [COND
	    ((fetch CLPROTECTED of (fetch PLOOKS of PC))     (* The source text was protected;
							     unprotect the copy.)
	      (replace PLOOKS of PC with (create CHARLOOKS using (fetch PLOOKS of PC)
								 CLPROTECTED ← NIL CLSELHERE ← NIL]
          (RETURN PC])

(\TEDIT.DELETE
  [LAMBDA (SEL STREAM SELOFF)                                (* jds "18-May-84 10:55")
                                                             (* DELETE THE CHARACTERS SPECIFIED FROM THE MAIN TEXT.)
                                                             (* SELOFF => The selection is already turned off.)
    (PROG [(TEXTOBJ (COND
		      ((type? STREAM STREAM)                 (* If we got a STREAM, change it into a textobj)
			(fetch (TEXTSTREAM TEXTOBJ) of STREAM))
		      (T STREAM]
          (PROG ((CH# (fetch CH# of SEL))
		 (CHLIM (fetch CHLIM of SEL))
		 (LINES (fetch LINES of TEXTOBJ))
		 (DS (fetch DS of TEXTOBJ))
		 (WINDOW (fetch \WINDOW of TEXTOBJ))
		 (HEIGHTCHANGED NIL)
		 (NLINE1 NIL)
		 (CRFLAG NIL)
		 (LINES\DELETED NIL)
		 OLINE1 OLINEN LEN NEXTLINE NL OLINE DX OCHLIM OXLIM OLHEIGHT OLASCENT OLDESCENT DY 
		 PREVLINE TEXTLEN OCR\END SAVEWIDTH IMAGECACHE)
	        [SETQ LEN (COND
		    ((IGREATERP CH# (fetch TEXTLEN of TEXTOBJ))
                                                             (* Past end of text, so don't delete any)
		      0)
		    ((IGREATERP CH# CHLIM)                   (* Start is past end, so don't delete any.)
		      0)
		    ((ZEROP (fetch DCH of SEL))              (* Just a caret--no text really selected--so don't 
							     delete any)
		      0)
		    ((ZEROP CHLIM)                           (* CHLIM is before start of text, so don't delete any)
		      0)
		    (T                                       (* The normal case.)
		       (ADD1 (IDIFFERENCE CHLIM CH#]         (* # of characters to be deleted)
	        (COND
		  ((OR (NOT (fetch SET of SEL))
		       (ZEROP LEN))                          (* If the selection isn't set, don't do anything.)
		    (RETURN)))
	        (AND WINDOW (TEDIT.NORMALIZECARET TEXTOBJ SEL))
                                                             (* If the text appears in a window, move the deletion 
							     point on-screen)
	        (SETQ OLINE1 (fetch L1 of SEL))
	        (SETQ OLINEN (fetch LN of SEL))
	        (\TEDIT.SHOWSELS TEXTOBJ NIL NIL)            (* Turn off the selection's highlighting)
	        (AND LINES (\FIXDLINES LINES SEL CH# CHLIM TEXTOBJ))
                                                             (* Update the line descriptors to account for the 
							     deletion)
	        (\DELETECH CH# CHLIM LEN TEXTOBJ)            (* Do the actual deletion of characters)
	        (replace THPOINT of (fetch TXTHISTORY of TEXTOBJ) with (fetch POINT of SEL))
                                                             (* Remember which side of the selection we were on, in 
							     case it gets undone.)
	        (replace CH# of SEL with (IMAX 1 CH#))
	        (replace CHLIM of SEL with (fetch CH# of SEL))
	        (replace POINT of SEL with (QUOTE LEFT))
	        (replace DCH of SEL with 0)
	        (COND
		  ((NOT WINDOW)                              (* If there's no window to update, don't bother)
		    (RETURN)))
	        (SETQ TEXTLEN (fetch TEXTLEN of TEXTOBJ))    (* The new text length)
	        [SETQ LINES\DELETED (\TEDIT.CLOSEUPLINES TEXTOBJ (AND OLINE1
								      (COND
									((fetch DELETED of OLINE1)
									  (fetch PREVLINE
									     of OLINE1))
									(T OLINE1)))
							 (AND OLINEN (COND
								((fetch DELETED of OLINEN)
								  (fetch NEXTLINE of OLINEN))
								(T OLINEN]
                                                             (* Remove any lines which were completely deleted.)
	        (COND
		  ((OR (LISTP WINDOW)
		       (NOT OLINE1)
		       (NOT OLINEN)
		       (OR (NEQ (fetch QUAD of (fetch LFMTSPEC of OLINE1))
				(QUOTE LEFT))
			   (IGREATERP (fetch RIGHTMAR of (fetch LFMTSPEC of OLINE1))
				      (fetch WRIGHT of TEXTOBJ)))
		       (fetch LHASTABS of OLINE1)
		       (fetch LHASTABS of OLINEN))           (* This line must needs be reformatted the hard way--it 
							     isn't a left ragged line or one of the lines is 
							     off-screen.)
		    (replace DX of SEL with 0)
		    (TEDIT.UPDATE.SCREEN TEXTOBJ)            (* Correct the text that's displayed already)
		    (\FIXSEL SEL TEXTOBJ)                    (* Then fix up the selection as needed.)
		    (\TEDIT.SHOWSELS TEXTOBJ NIL T)
		    (RETURN)))
	        (replace DESC of (fetch THISLINE of TEXTOBJ) with NIL)
	        [COND
		  [(EQ OLINE1 OLINEN)                        (* The deletion was within a single line.)
		    (COND
		      [(NOT (fetch DELETED of OLINE1))       (* Remove the deleted text, closing up the gap.
							     Fix LXLIM & Spaceleft)
			(replace SPACELEFT of OLINE1
			   with (IPLUS (IMIN (fetch SPACELEFT of OLINE1)
					     (IDIFFERENCE (fetch RIGHTMARGIN of OLINE1)
							  (fetch XLIM of SEL)))
				       (fetch DX of SEL)))   (* This handles the case where you delete a trailing 
							     space on the line (not counted in SPACELEFT).)
			(replace LXLIM of OLINE1 with (IDIFFERENCE (fetch LXLIM of OLINE1)
								   (fetch DX of SEL)))
			(BITBLT DS (fetch XLIM of SEL)
				(fetch YBOT of OLINE1)
				DS
				(fetch X0 of SEL)
				(fetch YBOT of OLINE1)
				(IDIFFERENCE (fetch RIGHTMARGIN of OLINE1)
					     (fetch XLIM of SEL))
				(fetch LHEIGHT of OLINE1)
				(QUOTE INPUT)
				(QUOTE REPLACE))             (* Move the rest of the line to the left over the 
							     deleted part)
			(BITBLT NIL 0 0 DS (IDIFFERENCE (fetch RIGHTMARGIN of OLINE1)
							(fetch SPACELEFT of OLINE1))
				(fetch YBOT of OLINE1)
				(fetch SPACELEFT of OLINE1)
				(fetch LHEIGHT of OLINE1)
				(QUOTE TEXTURE)
				(QUOTE REPLACE)
				WHITESHADE)                  (* And blank out to the right margin)
			(SETQ NLINE1 OLINE1)
			(COND
			  ((IGEQ CHLIM (IPLUS (fetch CHARLIM of OLINE1)
					      LEN))
			    (SETQ CRFLAG T]
		      (T (SETQ NLINE1 (fetch PREVLINE of OLINE1))
			 (COND
			   ((IGREATERP (fetch CHARLIM of NLINE1)
				       0)                    (* We'll only re-format this line if it isn't the dummy 
							     header line.)
			     (replace DIRTY of NLINE1 with T]
		  (T                                         (* The deletion spans a line boundary.)
		     (SETQ LINES\DELETED T)                  (* Remember that fact.)

          (* We can't tell whether there are any spaces to the left of us on the line; Hence, in the future, we must assume 
	  the worst and try to move text upward)


		     (COND
		       ((NOT (fetch DELETED of OLINE1))      (* WIPE OUT TAIL WHICH WAS DELETED, CHANGE LXLIM, SAVE 
							     PTR TO IT.)
			 (replace SPACELEFT of OLINE1 with (IDIFFERENCE (fetch RIGHTMARGIN
									   of OLINE1)
									(fetch X0 of SEL)))
			 (replace LXLIM of OLINE1 with (fetch X0 of SEL))
                                                             (* New limit of line's length is same as start of del.)
			 (BITBLT NIL 0 0 DS (IDIFFERENCE (fetch RIGHTMARGIN of OLINE1)
							 (fetch SPACELEFT of OLINE1))
				 (fetch YBOT of OLINE1)
				 (fetch SPACELEFT of OLINE1)
				 (fetch LHEIGHT of OLINE1)
				 (QUOTE TEXTURE)
				 (QUOTE REPLACE)
				 WHITESHADE)                 (* Blank out the deleted part)
			 (SETQ NLINE1 OLINE1)))
		     [COND
		       ((NOT (fetch DELETED of OLINEN))

          (* Wipe out the front part of the line, and move the rest over. Then fix its LXLIM, SPACELEFT, and FIRSTSPACE.
	  Then save a pointer to it if none was saved for the first line of the deletion.)


			 (BITBLT DS (fetch XLIM of SEL)
				 (fetch YBOT of OLINEN)
				 DS
				 (fetch LEFTMARGIN of OLINEN)
				 (fetch YBOT of OLINEN)
				 (IDIFFERENCE (fetch RIGHTMARGIN of OLINEN)
					      (fetch XLIM of SEL))
				 (fetch LHEIGHT of OLINEN)
				 (QUOTE INPUT)
				 (QUOTE REPLACE))            (* Wipe out the deleted part)
			 [replace LXLIM of OLINEN with (IDIFFERENCE (fetch LXLIM of OLINEN)
								    (IDIFFERENCE (fetch XLIM
										    of SEL)
										 (fetch LEFTMARGIN
										    of OLINEN]
                                                             (* Fix the right limit of the line's extent)
			 [replace SPACELEFT of OLINEN with (IPLUS (fetch SPACELEFT of OLINEN)
								  (IDIFFERENCE (fetch XLIM
										  of SEL)
									       (fetch LEFTMARGIN
										  of OLINEN]
                                                             (* And SPACELEFT on the line)
			 (BITBLT NIL 0 0 DS (IDIFFERENCE (fetch RIGHTMARGIN of OLINEN)
							 (fetch SPACELEFT of OLINEN))
				 (fetch YBOT of OLINEN)
				 (fetch SPACELEFT of OLINEN)
				 (fetch LHEIGHT of OLINEN)
				 (QUOTE TEXTURE)
				 (QUOTE REPLACE)
				 WHITESHADE)                 (* Clear to the right margin)
			 (OR NLINE1 (SETQ NLINE1 OLINEN]
		     (COND
		       ((NOT NLINE1)
			 (SETQ NLINE1 (fetch PREVLINE of OLINE1))
			 (COND
			   ((IGREATERP (fetch CHARLIM of NLINE1)
				       0)                    (* We'll only re-format this line if it isn't the dummy 
							     header line.)
			     (replace DIRTY of NLINE1 with T]
	        [COND
		  (NLINE1 (AND (SETQ PREVLINE (fetch PREVLINE of NLINE1))
			       (IGREATERP (fetch CHAR1 of PREVLINE)
					  0)
			       (NOT (fetch CR\END of PREVLINE))
			       (ILEQ CH# (fetch CHARTOP of PREVLINE))
			       (SETQ NLINE1 PREVLINE)
			       (replace DIRTY of NLINE1 with T))
                                                             (* If it looks like we may need to look at the previous 
							     line to do this right, move back and look at it.)
			  (while NLINE1
			     do                              (* Propagate the changes downward...)
				(COND
				  [(AND (fetch DIRTY of NLINE1)
					(SETQ NEXTLINE (fetch NEXTLINE of NLINE1)))
                                                             (* The known fast cases)

          (* This line needs to be checked AND there's a line after it to steal text from AND we think we can snatch a word 
	  or more from that next line)


				    (SETQ OXLIM (fetch LXLIM of NLINE1))
                                                             (* Old values for checking after re-format)
				    (SETQ OCHLIM (fetch CHARLIM of NLINE1))
				    (SETQ OCR\END (fetch CR\END of NLINE1))
				    (SETQ OLHEIGHT (fetch LHEIGHT of NLINE1))
				    (SETQ OLASCENT (fetch ASCENT of NLINE1))
				    (SETQ OLDESCENT (fetch DESCENT of NLINE1))
				    (\FORMATLINE TEXTOBJ NIL (fetch CHAR1 of NLINE1)
						 NLINE1)     (* Compute the new line break)
				    (\TEDIT.ADJUST.LINES TEXTOBJ NLINE1 WINDOW
							 (IPLUS (fetch YBOT of NLINE1)
								(fetch LHEIGHT of NLINE1))
							 (IDIFFERENCE OLASCENT (fetch ASCENT
										  of NLINE1)))
                                                             (* Allow for differences in ascent of the line)
				    (\TEDIT.ADJUST.LINES TEXTOBJ NEXTLINE WINDOW
							 (fetch YBOT of NLINE1)
							 (IDIFFERENCE OLDESCENT
								      (fetch DESCENT of NLINE1)))
                                                             (* Allow for differences in descent)
                                                             (* The YBOT here is right, because the line hasn't moved
							     yet.)
				    (add (fetch YBOT of NLINE1)
					 (IDIFFERENCE OLDESCENT (fetch DESCENT of NLINE1)))
                                                             (* NB that in this case, the line has a new bottom as 
							     well.)
				    [COND
				      ([OR (NOT (IEQP OXLIM (fetch LXLIM of NLINE1)))
					   (NOT (IEQP OCHLIM (fetch CHARLIM of NLINE1]
                                                             (* We got some text from the next line.
							     Go move the screen images as needed)
					(SETQ DX (IDIFFERENCE (fetch LXLIM of NLINE1)
							      OXLIM))
                                                             (* Width of the text to be moved up)
					(SETQ OLHEIGHT (fetch LHEIGHT of NLINE1))
					(COND
					  [(IGREATERP DX 0)
                                                             (* We're only interested if there IS text to move.)
					    (while (IGREATERP DX 0)
					       do            (* Keep grabbing text until we've got it all)
						  (COND
						    ((NOT NEXTLINE)
                                                             (* There is no succeeding line to take text from.
							     Resort to the slow way, then stop the process bu setting
							     DX to 0)
						      (\DISPLAYLINE TEXTOBJ NLINE1)
						      (SETQ DX 0))
						    ((OR (fetch LHASTABS of NLINE1)
							 (fetch LHASTABS of NEXTLINE))
                                                             (* There are TABS in the system.
							     Their width can change, so do this the slow way.)
						      (\DISPLAYLINE TEXTOBJ NLINE1)
						      (SETQ DX 0)
						      (replace CHAR1 of NEXTLINE
							 with (ADD1 (fetch CHARLIM of NLINE1)))
						      (replace DIRTY of NEXTLINE with T)
						      (TEDIT.UPDATE.SCREEN TEXTOBJ NEXTLINE))
						    ((ILEQ (fetch YBOT of NEXTLINE)
							   (fetch WBOTTOM of TEXTOBJ))
                                                             (* The next line lies below bottom of window--just 
							     Displayline, and blast the next line to hell.)
						      (\DISPLAYLINE TEXTOBJ NLINE1)
						      (replace NEXTLINE of NLINE1 with NIL)
						      (replace PREVLINE of NEXTLINE with NIL)
						      (SETQ DX 0))
						    ((IGREATERP (IDIFFERENCE (fetch LXLIM
										of NEXTLINE)
									     (fetch LEFTMARGIN
										of NEXTLINE))
								DX)
                                                             (* The next line is on-screen, and has enough text to 
							     fill our needs.)
						      (BITBLT DS (fetch LEFTMARGIN of NEXTLINE)
							      (fetch YBOT of NEXTLINE)
							      DS OXLIM
							      (IPLUS (fetch YBOT of NLINE1)
								     (IDIFFERENCE (fetch DESCENT
										     of NLINE1)
										  (fetch DESCENT
										     of NEXTLINE)))
							      DX
							      (IMIN (fetch LHEIGHT of NLINE1)
								    (fetch LHEIGHT of NEXTLINE))
							      (QUOTE INPUT)
							      (QUOTE REPLACE))
                                                             (* Move the front of the next line up to the end of this
							     line, satisfying our need.)
						      (SETQ LINES\DELETED
							(OR (\PULLTEXT NEXTLINE DX
								       (ADD1 (fetch CHARLIM
										of NLINE1))
								       TEXTOBJ)
							    LINES\DELETED))
                                                             (* Now propogate the text grabbing on downward.)
						      (SETQ DX 0)
                                                             (* We've satisfied the need; tell the main loop so.)
						      )
						    (T       (* NEXT NLINE1 WON'T FILL THIS ONE: GRAB IT, DECREMENT 
							     DX, BUMP LXLIM, MOVE ANY LOWER LINES UP OVER IT, AND TRY
							     AGAIN.)
						       (BITBLT DS (fetch LEFTMARGIN of NEXTLINE)
							       (fetch YBOT of NEXTLINE)
							       DS OXLIM
							       (IPLUS (fetch YBOT of NLINE1)
								      (IDIFFERENCE (fetch DESCENT
										      of NLINE1)
										   (fetch DESCENT
										      of NEXTLINE)))
							       (fetch LXLIM of NEXTLINE)
							       (IMIN (fetch LHEIGHT of NEXTLINE)
								     (fetch LHEIGHT of NLINE1))
							       (QUOTE INPUT)
							       (QUOTE REPLACE))
						       [SETQ DX (IDIFFERENCE DX
									     (IDIFFERENCE
									       (fetch LXLIM
										  of NEXTLINE)
									       (fetch LEFTMARGIN
										  of NEXTLINE]
                                                             (* Find out how much more text we need.)
						       [SETQ OXLIM
							 (IPLUS OXLIM (IDIFFERENCE (fetch LXLIM
										      of NEXTLINE)
										   (fetch LEFTMARGIN
										      of NEXTLINE]
                                                             (* And fix the "old" values for the next shor thru the 
							     loop)
						       (SETQ NL (fetch NEXTLINE of NEXTLINE))
						       (TEDIT.DELETELINE NEXTLINE TEXTOBJ)
                                                             (* Really delete the line we used up, and move lower 
							     lines up to fill.)
						       (SETQ NEXTLINE NL)
						       (SETQ LINES\DELETED T]
					  ((ILESSP DX 0)     (* For whatever reason, we have to push text downward 
							     (deleting a blank at EOL can do this).)
					    (SETQ DX (IMINUS DX))
					    [COND
					      ((fetch NEXTLINE of NLINE1)
                                                             (* There's a next line to push onto)
						[SETQ SAVEWIDTH
						  (IMIN DX
							(IMAX 0 (IDIFFERENCE (fetch RIGHTMARGIN
										of NLINE1)
									     (IDIFFERENCE
									       (fetch LXLIM
										  of NLINE1)
									       DX]
                                                             (* Save the text to be pushed down)
						(SETQ IMAGECACHE (\TEDIT.LINECACHE (fetch LINECACHE
										      of TEXTOBJ)
										   DX
										   (fetch LHEIGHT
										      of NLINE1)))
						(\TEDIT.CHECK (fetch TCUP
								 of (fetch CARET of TEXTOBJ)))
                                                             (* The caret must be invisible when the line cache is 
							     updated)
						(BITBLT WINDOW (IDIFFERENCE OXLIM DX)
							(fetch YBOT of NLINE1)
							IMAGECACHE 0 0 DX (fetch LHEIGHT
									     of NLINE1)
							(QUOTE INPUT)
							(QUOTE REPLACE))
						(\PUSHTEXT (fetch NEXTLINE of NLINE1)
							   (IDIFFERENCE OXLIM DX)
							   (fetch YBOT of NLINE1)
							   DX
							   (ADD1 (fetch CHARLIM of NLINE1))
							   TEXTOBJ OCR\END (fetch LINECACHE
									      of TEXTOBJ)
							   SAVEWIDTH)
                                                             (* And push the next guy along.)
						)
					      (T             (* No next line to push text onto.
							     Make a new one.)
						 [SETQ NEXTLINE
						   (replace NEXTLINE of NLINE1
						      with (\FORMATLINE TEXTOBJ NIL
									(ADD1 (fetch CHARLIM
										 of NLINE1]
                                                             (* Create the new line)
						 (replace PREVLINE of NEXTLINE with NLINE1)
                                                             (* Plug it into the chain of lines)
						 (COND
						   ((IGREATERP (fetch YBOT of NLINE1)
							       (IPLUS (fetch LHEIGHT of NEXTLINE)
								      (fetch WBOTTOM of TEXTOBJ)))
                                                             (* There's room for this new line.
							     Go ahead and display it)
						     (replace YBOT of NEXTLINE
							with (IDIFFERENCE (fetch YBOT of NLINE1)
									  (fetch LHEIGHT
									     of NEXTLINE)))
						     (replace YBASE of NEXTLINE
							with (IPLUS (fetch YBOT of NEXTLINE)
								    (fetch DESCENT of NEXTLINE)))
						     (\DISPLAYLINE TEXTOBJ (fetch NEXTLINE
									      of NLINE1]
					    (BITBLT NIL 0 0 DS (fetch LXLIM of NLINE1)
						    (fetch YBOT of NLINE1)
						    (fetch WRIGHT of TEXTOBJ)
						    (fetch LHEIGHT of NLINE1)
						    (QUOTE TEXTURE)
						    (QUOTE REPLACE)
						    WHITESHADE)
                                                             (* Blank out the line beyond its new end)
					    ]
				    (COND
				      ((AND (IGEQ (fetch CHARLIM of NLINE1)
						  TEXTLEN)
					    (NOT (fetch CR\END of NLINE1)))
                                                             (* If this line is at end of text, and it has no 
							     trailing CR, make sure there's no dummy line below it.)
					(replace NEXTLINE of NLINE1 with NIL]
				  ((AND (IEQP (fetch LXLIM of NLINE1)
					      (IDIFFERENCE (fetch RIGHTMARGIN of NLINE1)
							   (fetch SPACELEFT of NLINE1)))
					(ILESSP (fetch CHARLIM of NLINE1)
						TEXTLEN))    (* The general case)
				    (TEDIT.UPDATE.SCREEN TEXTOBJ)
				    (RETURN))
				  ((fetch DIRTY of NLINE1)   (* Nothing much changed, but there may have been a 
							     change in line height. Best to fix it up.)
				    (SETQ OLHEIGHT (fetch LHEIGHT of NLINE1))
				    (SETQ OLASCENT (fetch ASCENT of NLINE1))
				    (SETQ OLDESCENT (fetch DESCENT of NLINE1))
				    (\FORMATLINE TEXTOBJ NIL (fetch CHAR1 of NLINE1)
						 NLINE1)     (* Compute the new line break)
				    (\TEDIT.ADJUST.LINES TEXTOBJ NLINE1 WINDOW
							 (IPLUS (fetch YBASE of NLINE1)
								(fetch ASCENT of NLINE1))
							 (IDIFFERENCE OLASCENT (fetch ASCENT
										  of NLINE1)))
                                                             (* Allow for differences in ascent of the line)
				    (\TEDIT.ADJUST.LINES TEXTOBJ NEXTLINE WINDOW
							 (fetch YBOT of NLINE1)
							 (IDIFFERENCE OLDESCENT
								      (fetch DESCENT of NLINE1)))
                                                             (* Allow for differences in descent)
				    (add (fetch YBOT of NLINE1)
					 (IDIFFERENCE OLDESCENT (fetch DESCENT of NLINE1)))
                                                             (* NB that in this case, the line has a new bottom as 
							     well.)
				    ))
				(SETQ NLINE1 (fetch NEXTLINE of NLINE1]
	        (COND
		  (LINES\DELETED                             (* Lines were deleted; fill the bottom of the window as 
							     possible)
				 (SETQ OLINE (\TEDIT.FIND.LAST.LINE TEXTOBJ LINES))
                                                             (* OLINE is now the last line displayed on the screen.)
				 (\FILLWINDOW (fetch YBOT of OLINE)
					      OLINE TEXTOBJ)))
	        (replace CH# of SEL with (IMAX 1 CH#))
	        (replace CHLIM of SEL with (fetch CH# of SEL))
	        (replace POINT of SEL with (QUOTE LEFT))
	        (replace DX of SEL with 0)
	        (replace DCH of SEL with 0)
	        (TEDIT.SET.SEL.LOOKS SEL (QUOTE NORMAL))
	        (COND
		  ((ZEROP TEXTLEN)                           (* There are no characters; set the SEL to be at top of 
							     screen, left edge.)
		    (replace NEXTLINE of LINES with (\FORMATLINE TEXTOBJ NIL 1 NIL))
		    (replace PREVLINE of (fetch NEXTLINE of LINES) with LINES)
		    [replace YBOT of (fetch NEXTLINE of LINES)
		       with (IDIFFERENCE (fetch WTOP of TEXTOBJ)
					 (FONTPROP (FONTCREATE (QUOTE GACHA)
							       10)
						   (QUOTE HEIGHT]
		    (replace DESCENT of (fetch NEXTLINE of LINES) with (FONTPROP (FONTCREATE
										   (QUOTE GACHA)
										   10)
										 (QUOTE DESCENT)))
		    [replace YBASE of (fetch NEXTLINE of LINES)
		       with (IPLUS (fetch YBOT of (fetch NEXTLINE of LINES))
				   (fetch DESCENT of (fetch NEXTLINE of LINES]
		    [replace YBASE of (fetch NEXTLINE of LINES)
		       with (IPLUS (fetch YBOT of (fetch NEXTLINE of LINES))
				   (fetch DESCENT of (fetch NEXTLINE of LINES]
		    [replace Y0 of SEL with (IDIFFERENCE (fetch WTOP of TEXTOBJ)
							 (COND
							   ((fetch L1 of SEL)
							     (fetch LHEIGHT
								of (fetch L1 of SEL)))
							   (T 12]
		    (replace YLIM of SEL with (fetch Y0 of SEL))
		    (replace POINT of SEL with (QUOTE LEFT))
		    [replace X0 of SEL with (replace XLIM of SEL
					       with (COND
						      ((fetch L1 of SEL)
							(fetch LEFTMARGIN
							   of (fetch L1 of SEL)))
						      (T 8]
		    (replace L1 of SEL with (fetch NEXTLINE of LINES))
		    (replace LN of SEL with (fetch NEXTLINE of LINES)))
		  (T (\FIXSEL SEL TEXTOBJ)
		     (\TEDIT.FIXSELS TEXTOBJ SEL)))
	        (\SHOWSEL SEL NIL T)
	        (TEDIT.NORMALIZECARET TEXTOBJ SEL)
	        (\TEDIT.SHOWSELS TEXTOBJ NIL T])

(\TEDIT.FOREIGN.COPY?
  [LAMBDA (SEL)                                              (* jds "22-May-84 14:47")

          (* IF the current process's window isn't a TEdit window, do a "Copy" by BKSYSBUFing the selected text.
	  Then turn off all the various indicators.)


    (PROG (PROCW (SOURCE.TEXTOBJ (fetch \TEXTOBJ of SEL))
		 CH STREAM DEST.TEDIT? DEST.TEXTOBJ)
          [SETQ DEST.TEDIT? (AND (SETQ PROCW (PROCESSPROP (TTY.PROCESS)
							  (QUOTE WINDOW)))
				 (SETQ DEST.TEXTOBJ (WINDOWPROP PROCW (QUOTE TEXTOBJ]
          (COND
	    ((OR (NOT DEST.TEDIT?)
		 (AND PROCW DEST.TEXTOBJ (NEQ SOURCE.TEXTOBJ DEST.TEXTOBJ)
		      (fetch EDITOPACTIVE of DEST.TEXTOBJ)))
                                                             (* OK -- receiver isn't TEdit.
							     Do it the hard way.)
	      (\SETUPGETCH (fetch CH# of SEL)
			   SOURCE.TEXTOBJ)
	      (SETQ STREAM (fetch STREAMHINT of SOURCE.TEXTOBJ))
	      (for I from 1 to (fetch DCH of SEL) when (FIXP (SETQ CH (\BIN STREAM)))
		 do (BKSYSBUF (CHARACTER CH)))
	      (\SHOWSEL SEL NIL NIL)
	      (SETQ TEDIT.COPY.PENDING NIL])

(\TEDIT.QUIT
  [LAMBDA (W NOFORCE)                                        (* gbn "18-Apr-84 11:51")
                                                             (* Called by the default TEDIT.DEFAULT.MENUFN to perform
							     the QUIT command.)
    (PROG ((TEXTOBJ (WINDOWPROP W (QUOTE TEXTOBJ)))
	   (QUITFNS (WINDOWPROP W (QUOTE TEDIT.QUITFN)))
	   QUITFLG RESP)
          [for QUITFN inside QUITFNS while (AND (NEQ QUITFLG (QUOTE DON'T))
						(NEQ QUITFLG T))
	     do (COND
		  ((EQ QUITFN T)
		    (SETQ QUITFLG T))
		  (T (AND QUITFN (NEQ QUITFN T)
			  (SETQ QUITFLG (APPLY* QUITFN W (fetch STREAMHINT of TEXTOBJ)
						TEXTOBJ
						(fetch EDITPROPS of TEXTOBJ]
          (COND
	    ((EQ QUITFLG (QUOTE DON'T))                      (* The user supplied a QUITFN, and it returned "DON'T", 
							     so just ignore all this Fooferaw and keep editing.)
	      (RETURN))
	    [(AND (fetch \DIRTY of TEXTOBJ)
		  (NEQ QUITFNS T)
		  (NEQ QUITFLG T))                           (* If this document has changed, check with the user to 
							     make sure he really wants to do it.)
	      (replace EDITFINISHEDFLG of TEXTOBJ with (MOUSECONFIRM "Not Saved Yet... " 
								     "LEFT to Quit anyway."
								     (fetch PROMPTWINDOW
									of TEXTOBJ]
	    (T                                               (* Go ahead and quit the next time we see the main 
							     command loop.)
	       (replace EDITFINISHEDFLG of TEXTOBJ with T)))
          [AND (fetch \WINDOW of TEXTOBJ)
	       (NOT NOFORCE)
	       (NEQ (\TEDIT.MAINW TEXTOBJ)
		    (PROCESSPROP (TTY.PROCESS)
				 (QUOTE WINDOW)))
	       (TTY.PROCESS (WINDOWPROP (\TEDIT.MAINW TEXTOBJ)
					(QUOTE PROCESS]
          (RETURN (fetch EDITFINISHEDFLG of TEXTOBJ])

(\TEDIT.WORDDELETE
  [LAMBDA (TEXTOBJ)                                          (* jds "12-Apr-84 15:49")
                                                             (* Delete the word to the left of the caret.)
    (PROG ((SEL (fetch SEL of TEXTOBJ))
	   (STREAM (fetch STREAMHINT of TEXTOBJ))
	   (READSA (fetch READSA of (OR (fetch TXTWTBL of TEXTOBJ)
					TEDIT.WORDBOUND.READTABLE)))
	   INSCH# CH CHNO)                                   (* Back word.)
          (SETQ INSCH# (SELECTQ (fetch POINT of SEL)
				(LEFT (SUB1 (fetch CH# of SEL)))
				(RIGHT (fetch CHLIM of SEL))
				NIL))                        (* Find the place to delete backward from)
          (COND
	    ((IGREATERP INSCH# 0)                            (* Don't try to back up past start of file.)
	      (\SETUPGETCH INSCH# TEXTOBJ)
	      (SETQ CH (\BIN STREAM))
	      (for old CHNO from INSCH# to 1 by -1
		 while [AND (SELECTC (COND
				       ((FIXP CH)
					 (\SYNCODE READSA CH))
				       (T                    (* It's an object!)
					  TEXT.TTC))
				     (TEXT.TTC NIL)
				     T)
			    (NOT (fetch CLPROTECTED of (fetch PLOOKS of (fetch (TEXTSTREAM PIECE)
									   of STREAM]
		 do (SETQ CH (\GETCHB TEXTOBJ)))             (* Skip over any initial separator characters)
	      (for old CHNO from CHNO to 1 by -1
		 while [AND (SELECTC (COND
				       ((FIXP CH)
					 (\SYNCODE READSA CH))
				       (T                    (* It's an object!)
					  TEXT.TTC))
				     (TEXT.TTC T)
				     NIL)
			    (NOT (fetch CLPROTECTED of (fetch PLOOKS of (fetch (TEXTSTREAM PIECE)
									   of STREAM]
		 do (SETQ CH (\GETCHB TEXTOBJ)))             (* Skip over the next group of non-separators 
							     (= a "word"))
	      (\SHOWSEL SEL NIL NIL)
	      [replace CH# of SEL with (COND
					 ((ILEQ CHNO 1)
					   1)
					 (T (IPLUS 2 CHNO]   (* First character to delete)
	      (replace CHLIM of SEL with INSCH#)
	      (replace DCH of SEL with (IDIFFERENCE INSCH# CHNO))
	      (\FIXSEL SEL TEXTOBJ)
	      (\SHOWSEL SEL NIL T)
	      (\TEDIT.DELETE SEL TEXTOBJ])

(\TEDIT1
  [LAMBDA (TEXT WINDOW UNSPAWNED PROPS)                      (* gbn "19-Apr-84 13:56")
                                                             (* Does the actual editing work, and re-coercion or 
							     process kill when done. Called by TEDIT directly, or 
							     ADD.PROCESSed by it.)
    (SETQ TEXT (OPENTEXTSTREAM TEXT WINDOW NIL NIL PROPS))   (* Open the text for editing)
    (\TEDIT.COMMAND.LOOP (fetch (TEXTSTREAM TEXTOBJ) of TEXT))
                                                             (* Run the editing engine)
    (CLOSEW WINDOW)
    (replace \WINDOW of (fetch (TEXTSTREAM TEXTOBJ) of TEXT) with NIL)
    (AND (WINDOWPROP WINDOW (QUOTE TEDIT.AFTERQUITFN))
	 (APPLY* (WINDOWPROP WINDOW (QUOTE TEDIT.AFTERQUITFN))
		 WINDOW TEXT))                               (* Apply any post-window-close 
							     (and post-QUIT) function)
    (COND
      (UNSPAWNED                                             (* We're not a distinct process: Send back the edited 
							     text in some suitable form)
		 (COND
		   ((NEQ (fetch EDITFINISHEDFLG of (fetch (TEXTSTREAM TEXTOBJ) of TEXT))
			 T)
		     (PROG1 (fetch EDITFINISHEDFLG of (fetch (TEXTSTREAM TEXTOBJ) of TEXT))
			    (replace EDITFINISHEDFLG of (fetch (TEXTSTREAM TEXTOBJ) of TEXT)
			       with NIL)))
		   ((STRINGP (fetch TXTFILE of (fetch (TEXTSTREAM TEXTOBJ) of TEXT)))
		     (COERCETEXTOBJ (fetch (TEXTSTREAM TEXTOBJ) of TEXT)
				    (QUOTE STRINGP)))
		   (T TEXT)))
      (T                                                     (* We're a distinct process. Just die)
	 (KILL.ME])
)



(* Debugging functions)

(DEFINEQ

(PLCHAIN
  [LAMBDA (LN)                                               (* jds "21-JAN-82 09:57")
    (PRINTLINE LN)
    (COND
      ((fetch NEXTLINE of LN)
	(PLCHAIN (fetch NEXTLINE of LN])

(PRINTLINE
  [LAMBDA (LN)                                               (* jds "21-Apr-84 15:04")
    (printout T "-----" T LN "  Bot: " (fetch YBOT of LN)
	      "  Base: "
	      (fetch YBASE of LN)
	      "  Height: "
	      (fetch LHEIGHT of LN)
	      "  Ascent: "
	      (fetch ASCENT of LN)
	      "  Descent: "
	      (fetch DESCENT of LN)
	      T "Char1: " (fetch CHAR1 of LN)
	      "  Lim: "
	      (fetch CHARLIM of LN)
	      "  Top: "
	      (fetch CHARTOP of LN))
    (COND
      ((fetch DIRTY of LN)
	(PRIN1 "  DIRTY")))
    (COND
      ((fetch NEW of LN)
	(PRIN1 "  NEW")))
    (COND
      ((fetch CR\END of LN)
	(PRIN1 "  CR-at-end")))
    (COND
      ((fetch DELETED of LN)
	(PRIN1 "  DELETED")))
    (PRIN1 ".
")
    (printout T "RMar: " (fetch RIGHTMARGIN of LN)
	      "  XLim: "
	      (fetch LXLIM of LN)
	      "  Left: "
	      (fetch SPACELEFT of LN)
	      T "Prev:  " (fetch PREVLINE of LN)
	      T "Next:  " (fetch NEXTLINE of LN)
	      T)
    (COND
      ((AND (IGEQ (fetch CHAR1 of LN)
		  1)
	    (ILEQ (fetch CHAR1 of LN)
		  (fetch TEXTLEN of TEXTOBJ)))               (* The line is real -- print it.)
	(\SETUPGETCH (fetch CHAR1 of LN)
		     TEXTOBJ)
	(PRIN1 "|")
	[bind CH for CHNO from (fetch CHAR1 of LN) to (IMIN (fetch TEXTLEN of TEXTOBJ)
							    (fetch CHARLIM of LN))
	   do (SETQ CH (\GETCH TEXTOBJ))
	      (COND
		((SMALLP CH)
		  (PRIN1 (CHARACTER CH)))
		(T (PRINT CH]
	(PRIN1 "|
"])

(SEEFILE
  [LAMBDA (FILE ST ND)                                       (* jds " 4-NOV-83 20:21")
    (PROG (CH)
          [SETQ FILE (OR (OPENP FILE)
			 (OPENSTREAM FILE (QUOTE INPUT]
          (SETFILEPTR FILE (OR ST 0))
          (for I from (OR ST 0) to (OR ND (SUB1 (GETEOFPTR FILE)))
	     do (printout T I 5 (SETQ CH (BIN FILE))
			  9
			  (COND
			    [(ILEQ CH (CHARCODE ↑Z))
			      (CONCAT "↑" (CHARACTER (IPLUS CH (CHARCODE @]
			    (T (CHARACTER CH)))
			  T])
)



(* Object-oriented editing)

(DEFINEQ

(TEDIT.INSERT.OBJECT
  [LAMBDA (OBJECT STREAM CH#)                                (* jds "10-May-84 15:46")
                                                             (* Inserts the annotation OBJECT into text STREAM in 
							     front of character CH.)
    (PROG ((TEXTOBJ (TEXTOBJ STREAM))
	   SEL)
          (SETQ SEL (fetch SEL of TEXTOBJ))
          (PROG ([PC (COND
		       ((ILEQ CH# (fetch TEXTLEN of TEXTOBJ))
			 (\CHTOPC CH# (fetch PCTB of TEXTOBJ)))
		       (T (QUOTE LASTPIECE]
		 (PCTB (ffetch PCTB of TEXTOBJ))
		 (TEXTLEN (fetch TEXTLEN of TEXTOBJ))
		 PCNO CHNO NEWPC PREVPC INSERTFN)
	        (TEDIT.DO.BLUEPENDINGDELETE SEL TEXTOBJ)     (* Do the pending delete, if there is one.)
	        (\SHOWSEL SEL NIL NIL)                       (* Turn off the selection for now)
	        (SETQ CH# (IMIN CH# (ADD1 TEXTLEN)))         (* CH# we're to insert these characters in front of)
	        (freplace \INSERTFIRSTCH of TEXTOBJ with -1)
	        (SETQ PCNO (\FINDPIECE PC PCTB))             (* Piece we're to insert in front of or inside)
	        (SETQ NEWPC (create PIECE
				    PSTR ← NIL
				    PFILE ← NIL
				    POBJ ← OBJECT
				    PLEN ← 1))               (* The new piece we're inserting)
	        (COND
		  ((OR (IGREATERP CH# TEXTLEN)
		       (IEQP CH# (\EDITELT PCTB PCNO)))      (* We're inserting on a piece boundary;
							     do it, then remember the prior piece.)
		    (\INSERTPIECE NEWPC PC TEXTOBJ))
		  (T                                         (* Not on a piece boundary; split the piece we're inside
							     of, then insert.)
		     (\INSERTPIECE NEWPC (\SPLITPIECE PC CH# TEXTOBJ)
				   TEXTOBJ)))
	        (COND
		  ((SETQ INSERTFN (IMAGEOBJPROP OBJECT (QUOTE WHENINSERTEDFN)))
                                                             (* If there is a WHENINSERTEDFN, apply it.)
		    (APPLY* INSERTFN OBJECT (fetch DS of TEXTOBJ)
			    NIL STREAM)))
	        (SETQ PCTB (fetch PCTB of TEXTOBJ))
	        (SETQ PREVPC (fetch PREVPIECE of NEWPC))     (* Fill in the para looks)
	        [COND
		  [PREVPC (COND
			    [(AND (fetch PPARALAST of PREVPC)
				  (fetch NEXTPIECE of NEWPC))
			      (replace PPARALOOKS of NEWPC with (fetch PPARALOOKS
								   of (fetch NEXTPIECE of NEWPC]
			    (T (replace PPARALOOKS of NEWPC with (fetch PPARALOOKS of PREVPC]
		  (T (COND
		       ((SETQ PREVPC (fetch NEXTPIECE of NEWPC))
			 (replace PPARALOOKS of NEWPC with (fetch PPARALOOKS of PREVPC)))
		       (T (replace PPARALOOKS of NEWPC with (fetch FMTSPEC of TEXTOBJ]
	        (replace PLOOKS of NEWPC with (fetch CARETLOOKS of TEXTOBJ))
	        (\TEDIT.HISTORYADD TEXTOBJ (create TEDITHISTORYEVENT
						   THACTION ←(QUOTE Insert)
						   THCH# ← CH#
						   THLEN ← 1
						   THFIRSTPIECE ← NEWPC))
	        (SETQ TEXTLEN (freplace TEXTLEN of TEXTOBJ with (IPLUS 1 TEXTLEN)))
	        (replace \INSERTNEXTCH of TEXTOBJ with -1)
	        (replace \DIRTY of TEXTOBJ with T)
	        (replace DESC of (fetch THISLINE of TEXTOBJ) with NIL)
	        (replace CH# of SEL with (replace CHLIM of SEL with (ADD1 CH#)))
	        (replace DCH of SEL with 0)
	        (replace DX of SEL with 0)
	        (replace POINT of SEL with (QUOTE LEFT))
	        (replace SELKIND of SEL with (QUOTE CHAR))
	        (replace DESC of (fetch THISLINE of TEXTOBJ) with NIL)
	        (COND
		  ((fetch \WINDOW of TEXTOBJ)
		    (\FIXILINES TEXTOBJ SEL CH# 1 (SUB1 TEXTLEN))
		    (TEDIT.UPDATE.SCREEN TEXTOBJ)
		    (\FIXSEL SEL TEXTOBJ)
		    (\SHOWSEL SEL NIL T)))
	        (\COPYSEL SEL TEDIT.SELECTION])

(TEDIT.EDIT.OBJECT
  [LAMBDA (STREAM OBJ)                                       (* jds "24-May-84 17:05")
    (PROG ([TEXTOBJ (COND
		      ((type? TEXTOBJ STREAM)
			STREAM)
		      ((type? STREAM STREAM)
			(fetch (TEXTSTREAM TEXTOBJ) of STREAM))
		      ((SHOULDNT]
	   SEL LL CH# SELOBJ EDITFN)
          [COND
	    [(AND OBJ (IMAGEOBJP OBJ))
	      (SETQ CH# (TEDIT.FIND.OBJECT TEXTOBJ OBJ))
	      (COND
		(CH# (SETQ SEL (fetch SCRATCHSEL of TEXTOBJ))
		     (replace CH# of SEL with CH#)
		     (replace CHLIM of SEL with CH#)
		     (SETQ SELOBJ OBJ)
		     (replace DCH of SEL with 1)
		     (replace \TEXTOBJ of SEL with TEXTOBJ)
		     (\FIXSEL SEL TEXTOBJ))
		(T (TEDIT.PROMPTPRINT TEXTOBJ "Can't find specified object." T]
	    (T (SETQ SEL (fetch SEL of TEXTOBJ))
	       (SETQ OBJ (fetch SELOBJ of SEL]
          (COND
	    [OBJ                                             (* OK There's an object selected.
							     Edit it.)
		 (SETQ EDITFN (IMAGEOBJPROP OBJ (QUOTE EDITFN)))
		 (COND
		   ((AND EDITFN (APPLY* EDITFN OBJ))         (* If the editfn makes a change, update the screen.)
		     (replace DIRTY of (fetch L1 of SEL) with T)
		     (TEDIT.UPDATE.SCREEN TEXTOBJ]
	    (T                                               (* No object selected.)
	       (TEDIT.PROMPTPRINT TEXTOBJ "Please select an editable object first." T])

(TEDIT.FIND.OBJECT
  [LAMBDA (TEXTOBJ OBJ)                                      (* jds "22-OCT-83 17:36")
                                                             (* Find OBJ, if it's in TEXTOBJ, and return CH#.
							     Else return nil)
    (SETQ TEXTOBJ (TEXTOBJ TEXTOBJ))
    (PROG ((PCTB (fetch PCTB of TEXTOBJ))
	   PC)
          (RETURN (for PCNO from (ADD1 \FirstPieceOffset) to (\EDITELT PCTB \PCTBLastPieceOffset)
		     by \EltsPerPiece
		     do (SETQ PC (\EDITELT PCTB PCNO))
			(COND
			  ((EQ (fetch POBJ of PC)
			       OBJ)
			    (RETURN (\EDITELT PCTB (SUB1 PCNO])

(TEDIT.PUT.OBJECT
  [LAMBDA (PIECE OFILE FONTFILE CURCH#)                      (* jds " 1-May-84 11:58")
                                                             (* Given a piece which describes an object, put the 
							     object out there.)
    (PROG ((OBJECT (fetch POBJ of PIECE))
	   (FONTCH# (GETFILEPTR FONTFILE))
	   LEN)
          (\DWOUT FONTFILE 0)                                (* Placeholder for length of the object's description)
          (\SMALLPOUT FONTFILE \PieceDescriptorOBJECT)       (* Mark this as setting the piece's looks)
          (\ATMOUT FONTFILE (IMAGEOBJPROP OBJECT (QUOTE GETFN)))
                                                             (* The FN to apply to reconstruct the object)
          (APPLY* (IMAGEOBJPROP OBJECT (QUOTE PUTFN))
		  OBJECT OFILE)
          (SETFILEPTR FONTFILE FONTCH#)                      (* Now go back and fill in the length of the text 
							     description of the object.)
          [\DWOUT FONTFILE (SETQ LEN (ADD1 (IDIFFERENCE (GETEOFPTR OFILE)
							CURCH#]
          (SETFILEPTR FONTFILE -1)                           (* Make sure we're at the end of the font file)
          (SETFILEPTR OFILE -1)                              (* And the text part of the file)
          (RETURN LEN])

(TEDIT.GET.OBJECT
  [LAMBDA (STREAM PIECE FILE CURCH#)                         (* jds " 3-Apr-84 10:42")
                                                             (* Get an object from the file)
                                                             (* CURCH# = fileptr within the text section of the file 
							     where the object's text starts.)
    (PROG (FILEPTRSAVE NAMELEN NAME OBJ)
          (SETQ NAMELEN (\SMALLPIN FILE))                    (* The length of the description which follows)
          [SETQ NAME (PACK (for I from 1 to NAMELEN collect (CHARACTER (\BIN FILE]
                                                             (* The re-load function name)
          (SETQ FILEPTRSAVE (GETFILEPTR FILE))               (* Save our file location thru the building of the 
							     object)
          (SETFILEPTR FILE CURCH#)
          (SETQ OBJ (APPLY* NAME FILE STREAM PIECE CURCH#))
          (SETFILEPTR FILE FILEPTRSAVE)
          (replace POBJ of PIECE with OBJ)
          (replace PFILE of PIECE with NIL)
          (replace PSTR of PIECE with NIL)
          [replace PLOOKS of PIECE with (COND
					  ((fetch PREVPIECE of PIECE)
					    (fetch PLOOKS of (fetch PREVPIECE of PIECE)))
					  (T (OR (fetch DEFAULTCHARLOOKS of (fetch (TEXTSTREAM 
											  TEXTOBJ)
									       of STREAM))
						 (CHARLOOKS.FROM.FONT TEDIT.DEFAULT.FONT]
          (RETURN (fetch POBJ of PIECE])

(TEDIT.OBJECT.CHANGED
  [LAMBDA (TEXTOBJ OBJECT)                                   (* jds "10-May-84 14:05")
                                                             (* Notify TEdit that an object has changed, and the 
							     display may need to be updated.)
    (PROG ((LINES (fetch LINES of TEXTOBJ))
	   PCINFO CHANGED CHANGEDCH#)
          (SETQ PCINFO (TEDIT.MAPPIECES TEXTOBJ [FUNCTION (LAMBDA (CH# PC PCNO OBJ)
					    (AND (EQ OBJ (fetch POBJ of PC))
						 (QUOTE STOP]
					OBJECT))             (* Find the piece containing this object)
          (OR PCINFO (HELP "Changed OBJECT not found!?"))
          (SETQ CHANGEDCH# (CAR PCINFO))                     (* Get the CH# of the changed object)
          (\TEDIT.MARK.LINES.DIRTY TEXTOBJ CHANGEDCH# CHANGEDCH#)
                                                             (* Mark affected lines)
          (\SHOWSEL (fetch SEL of TEXTOBJ)
		    NIL NIL)
          (TEDIT.UPDATE.SCREEN TEXTOBJ LINES)
          (\FIXSEL (fetch SEL of TEXTOBJ)
		   TEXTOBJ)
          (\SHOWSEL (fetch SEL of TEXTOBJ)
		    NIL T])
)
(FILESLOAD TEDITHCPY TEDITFIND TEDITHISTORY TEDITFILE TEDITWINDOW TEDITSELECTION IMAGEOBJ TFBRAVO 
	   TEDITMENU)



(* TEDIT Support information)


(RPAQQ TEDITSYSTEMDATE "24-May-84 17:31:57")
(DEFINEQ

(MAKETEDITFORM
  [LAMBDA NIL                                                (* jds "16-Mar-84 09:43")
    (MAKEXXXSUPPORTFORM "TEdit" "TEditSupport.pa" TEDITSYSTEMDATE])
)
(ADDTOVAR LAFITESPECIALFORMS ("TEdit Report" (QUOTE MAKETEDITFORM)
					     "Report a problem with TEdit"))
(SETQ LAFITEFORMSMENU NIL)



(* LISTFILES Interface, so the system can decide if a file is a TEdit file.)


(ADDTOVAR PRINTFILETYPES (TEDIT (TEST \TEDIT.FORMATTEDP1)
				(EXTENSION (TEDIT))))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (2410 83138 (\TEDIT2 2420 . 4431) (COERCETEXTOBJ 4433 . 7601) (TEDIT 7603 . 9923) (
TEDIT.CHARWIDTH 9925 . 11468) (TEDIT.COPY 11470 . 16136) (TEDIT.DELETE 16138 . 16636) (
TEDIT.DO.BLUEPENDINGDELETE 16638 . 17213) (TEDIT.INSERT 17215 . 20768) (TEDIT.KILL 20770 . 21939) (
TEDIT.MAPLINES 21941 . 22831) (TEDIT.MAPPIECES 22833 . 23882) (TEDIT.MOVE 23884 . 29020) (TEDIT.QUIT 
29022 . 30216) (TEDIT.STRINGWIDTH 30218 . 30767) (TEDIT.\INSERT 30769 . 32794) (TEXTOBJ 32796 . 33473)
 (TEXTSTREAM 33475 . 34135) (\TEDIT.INCLUDE 34137 . 36131) (\TEDIT.INSERT.PIECES 36133 . 42601) (
\TEDIT.MOVE.PIECEMAPFN 42603 . 43553) (\TEDIT.OBJECT.SHOWSEL 43555 . 45222) (\TEDIT.CHARDELETE 45224
 . 48080) (\TEDIT.COPY.PIECEMAPFN 48082 . 50072) (\TEDIT.DELETE 50074 . 75977) (\TEDIT.FOREIGN.COPY? 
75979 . 77162) (\TEDIT.QUIT 77164 . 79042) (\TEDIT.WORDDELETE 79044 . 81365) (\TEDIT1 81367 . 83136)) 
(83171 85579 (PLCHAIN 83181 . 83401) (PRINTLINE 83403 . 85072) (SEEFILE 85074 . 85577)) (85616 95823 (
TEDIT.INSERT.OBJECT 85626 . 89619) (TEDIT.EDIT.OBJECT 89621 . 91115) (TEDIT.FIND.OBJECT 91117 . 91767)
 (TEDIT.PUT.OBJECT 91769 . 93090) (TEDIT.GET.OBJECT 93092 . 94662) (TEDIT.OBJECT.CHANGED 94664 . 95821
)) (96026 96215 (MAKETEDITFORM 96036 . 96213)))))
STOP