(FILECREATED "29-JUN-83 11:28:50" {PHYLUM}<LISPCORE>SOURCES>RS232CHAT.;61 37921  

      changes to:  (FNS \RS232CHAT.DUPLEX \RS232CHAT.GETMENUS)

      previous date: "29-JUN-83 07:17:48" {PHYLUM}<JONL>LISP>RS232CHAT.;1)


(* Copyright (c) 1982, 1983 by Xerox Corporation)

(PRETTYCOMPRINT RS232CHATCOMS)

(RPAQQ RS232CHATCOMS ((FILES (SYSLOAD)
			     RS232 RS232LOGIN)
		      (DECLARE: EVAL@COMPILE DONTEVAL@LOAD DONTCOPY
				(P (OR (GETMACROPROP (QUOTE RS232INITIALIZECHECK)
						     COMPILERMACROPROPS)
				       (LOADFROM (QUOTE RS232)))))
		      (LOCALVARS . T)
		      (* CHAT and similar tools)
		      (DECLARE: EVAL@COMPILE DONTCOPY (RECORDS RS232CHATEXITSTATE SAVEDTERMENV))
		      (INITVARS (RS232CHATEXITSTATE NIL)
				(\RS232CHAT.PERMITTED.INTERRUPTS NIL)
				(\RS232CHATSTATE.GLOBALVARS (QUOTE (\RCHATS \RS232CHATTTBL 
									    RS232XON\XOFF? 
									    RS232CHATBINHOOK 
								       \RS232CHAT.LocalEchoStream))))
		      (GLOBALVARS RS232CHATEXITSTATE \RS232CHAT.GLOBALVARS \RS232CHAT.SPECVARS)
		      (INITVARS * (MAPCAR \RS232CHATSTATE.GLOBALVARS (FUNCTION (LAMBDA (X)
										       (LIST X NIL))))
				)
		      (INITVARS * \RS232CHATSTATE.SPECVARS.ALIST)
		      (INITVARS (\RS232CHATSTATE.SPECVARS (MAPCAR \RS232CHATSTATE.SPECVARS.ALIST
								  (FUNCTION CAR))))
		      (GLOBALVARS * (EVAL (QUOTE \RS232CHATSTATE.GLOBALVARS)))
		      (SPECVARS * (EVAL (QUOTE \RS232CHATSTATE.SPECVARS)))
		      (FNS RS232CHAT \RS232CHAT.REENTER \RS232CHAT.SWITCHSTATE 
			   \RS232CHAT.MODIFY.TERMENV \RS232CHAT.DUPLEX \RS232CHAT.DOCOMMAND 
			   \RS232CHAT.GETKEY \RS232CHAT.DO↑B)
		      (COMS (* Byte I/O for RS232CHAT)
			    (RECORDS RS232CHATBINHOOK)
			    (INITVARS (\RS232CHAT7? T)
				      (RS232REMOTEXOFF? NIL)
				      (\RS232FTPSLOW.BaudRate 1200))
			    (FNS \RS232CHAT.BIN \RS232CHAT.NEWLINE \RS232CHAT.NEWLINE.AUX 
				 \RS232CHAT.*APPLY2* \RS232CHAT.GAGHIM)
			    (GLOBALVARS \RS232CHAT7? RS232REMOTEXOFF? \RS232FTPSLOW.BaudRate))
		      (COMS (* Menu, window, process, and blinker functions)
			    (FNS \RS232CHAT.GETMENUS \RCHATD.SETUP \RCHATW.SETUP \RS232CHAT.RESHAPEFN 
				 \RS232CHAT.BUTTONFN \RS232CHAT.DOMENU)
			    (GLOBALVARS \RCHATD \RCHATD.FONTDESCENT \RCHATD.BTMY \RCHATD.TOPY)
			    (FNS \RS232CHAT.PROCESS.EXIT)
			    (DECLARE: EVAL@COMPILE DONTCOPY (RECORDS RS232CHATBLINKER))
			    (FNS \RS232CHATBLINKWINK \RS232CHATBLINKOFF)
			    (INITVARS (\RS232CHATWINDOW NIL)
				      (\RS232CHATMENU NIL)
				      (\RS232CHATSPEEDMENU NIL)
				      (\RS232CHAT.MENUSIGNAL NIL)
				      (\RS232CHATBLINKER NIL))
			    (GLOBALVARS \RS232CHATWINDOW \RS232CHATMENU \RS232CHATSPEEDMENU 
					\RS232CHAT.MENUSIGNAL \RS232CHATBLINKER))))
(FILESLOAD (SYSLOAD)
	   RS232 RS232LOGIN)
(DECLARE: EVAL@COMPILE DONTEVAL@LOAD DONTCOPY 
(OR (GETMACROPROP (QUOTE RS232INITIALIZECHECK)
		  COMPILERMACROPROPS)
    (LOADFROM (QUOTE RS232)))
)
(DECLARE: DOEVAL@COMPILE DONTCOPY

(LOCALVARS . T)
)



(* CHAT and similar tools)

(DECLARE: EVAL@COMPILE DONTCOPY 
[DECLARE: EVAL@COMPILE 

(TYPERECORD RS232CHATEXITSTATE (GLOBALVARS SPECVARS SAVEDTERMENV)
			       GLOBALVARS ←(MAPCAR \RS232CHATSTATE.GLOBALVARS (FUNCTION EVALV))
			       SPECVARS ←(MAPCAR \RS232CHATSTATE.SPECVARS (FUNCTION EVALV))
			       (RECORD GLOBALVARS (\RCHATS \RS232CHATTTBL RS232XON\XOFF?)))

(RECORD SAVEDTERMENV (SAVEDTTBL SAVEDINTERRUPTS SAVEDKEYACTIONS))
]
)

(RPAQ? RS232CHATEXITSTATE NIL)

(RPAQ? \RS232CHAT.PERMITTED.INTERRUPTS NIL)

(RPAQ? \RS232CHATSTATE.GLOBALVARS (QUOTE (\RCHATS \RS232CHATTTBL RS232XON\XOFF? RS232CHATBINHOOK 
						  \RS232CHAT.LocalEchoStream)))
(DECLARE: DOEVAL@COMPILE DONTCOPY

(ADDTOVAR GLOBALVARS RS232CHATEXITSTATE \RS232CHAT.GLOBALVARS \RS232CHAT.SPECVARS)
)

(RPAQ? \RCHATS NIL)

(RPAQ? \RS232CHATTTBL NIL)

(RPAQ? RS232XON\XOFF? NIL)

(RPAQ? RS232CHATBINHOOK NIL)

(RPAQ? \RS232CHAT.LocalEchoStream NIL)

(RPAQQ \RS232CHATSTATE.SPECVARS.ALIST ((\RS232PERMITTED.INTERRUPTS NIL)
				       (\RS232ESCAPE.CHARCODE (CHARCODE #B))
				       (\RS232CHAT.EOLsequence "
")
				       (\RS232CHAT.NEWLINECHAR (CHARCODE LF))
				       (\RS232CHAT.BellSequence "↑<Bell>")
				       (\RS232CHAT.IgnoreCharcodes (LIST (CHARCODE NULL)))))

(RPAQ? \RS232PERMITTED.INTERRUPTS NIL)

(RPAQ? \RS232ESCAPE.CHARCODE (CHARCODE #B))

(RPAQ? \RS232CHAT.EOLsequence "
")

(RPAQ? \RS232CHAT.NEWLINECHAR (CHARCODE LF))

(RPAQ? \RS232CHAT.BellSequence "↑<Bell>")

(RPAQ? \RS232CHAT.IgnoreCharcodes (LIST (CHARCODE NULL)))

(RPAQ? \RS232CHATSTATE.SPECVARS (MAPCAR \RS232CHATSTATE.SPECVARS.ALIST (FUNCTION CAR)))
(DECLARE: DOEVAL@COMPILE DONTCOPY

(ADDTOVAR GLOBALVARS \RCHATS \RS232CHATTTBL RS232XON\XOFF? RS232CHATBINHOOK 
	  \RS232CHAT.LocalEchoStream)
)
(DECLARE: DOEVAL@COMPILE DONTCOPY

(SPECVARS \RS232PERMITTED.INTERRUPTS \RS232ESCAPE.CHARCODE \RS232CHAT.EOLsequence 
	  \RS232CHAT.NEWLINECHAR \RS232CHAT.BellSequence \RS232CHAT.IgnoreCharcodes)
)
(DEFINEQ

(RS232CHAT
  (LAMBDA (TypeScriptStream XON\XOFF? LocalEchoStream BINHOOK)
    (DECLARE (GLOBALVARS \ORIGKEYACTIONS))                   (* JonL " 8-APR-83 19:43")
    (RS232INITIALIZECHECK)                                   (* Sets up the GLOBALVARS relevant to RS232CHAT)
    (SETQ RS232CHATEXITSTATE)
    (OR (TERMTABLEP \RS232CHATTTBL)
	(for I (TTBL ←(COPYTERMTABLE (QUOTE ORIG))) from 0 to 31
	   do (ECHOCONTROL I (if (FMEMB I (CHARCODE (TAB EOL BELL)))
				 then (QUOTE SIMULATE)
			       else (QUOTE INDICATE))
			   TTBL)
	   finally (PROGN (ECHOMODE NIL TTBL)
			  (CONTROL T TTBL)
			  (SETQ \RS232CHATTTBL TTBL))))
    (OR (type? MENU \RS232CHATMENU)
	(\RS232CHAT.GETMENUS))
    (SETQ \RCHATS (GETSTREAM (OR (OR TypeScriptStream \RS232CHATWINDOW)
				 (CREATEW NIL (QUOTE RS232ChatConnection)))
			     (QUOTE OUTPUT)))
    (SETQ RS232CHATBINHOOK (AND (type? RS232CHATBINHOOK BINHOOK)
				BINHOOK))
    (SETQ \RS232CHAT.XON\XOFF? XON\XOFF?)
    (SETQ \RS232CHAT.LocalEchoStream (if (NULL LocalEchoStream)
					 then NIL
				       elseif (EQ T LocalEchoStream)
					 then \RCHATS
				       else (GETSTREAM LocalEchoStream (QUOTE OUTPUT))))
    (EVAL.AS.PROCESS (QUOTE (\RS232CHAT.REENTER)))))

(\RS232CHAT.REENTER
  (LAMBDA (STATE)                                            (* JonL "23-JUN-83 20:42")
    (\CHECKCARET (TTYDISPLAYSTREAM))                         (* Since we're becoming the TTY process, then flush the 
							     caret in the previous window)
    (RESETLST (RESETSAVE (\RS232CHAT.SWITCHSTATE STATE T))
	      (\RCHATD.SETUP)
	      (if (THIS.PROCESS)
		  then (if \RCHATD
			   then (PROCESS.WINDOW (THIS.PROCESS)
						\RS232CHATWINDOW)
				(PROCESS.SWITCH.TO.WINDOW \RS232CHATWINDOW)
				(WINDOWPROP \RS232CHATWINDOW (QUOTE BUTTONEVENTFN)
					    (QUOTE \RS232CHAT.BUTTONFN))
                                                             (* Foo, patch up for bug in PROCESS.SWITCH.TO.WINDOW)
				
			 else (RESETSAVE (TTY.PROCESS (THIS.PROCESS)))))
	      (if RS232XON\XOFF?
		  then                                       (* If we're playing the XON\XOFF? game, then be sure he 
							     isn't gagged)
		       (PROG NIL
			     (\RS232DECODE.LINESTATUS (OR (\RS232CHAT.GAGHIM)
							  (RETURN)))))
	      (\RS232CHAT.DUPLEX)                            (* This call is mainly to provide a frame name from 
							     which to RETFROM)
	      (SETQ \LastInWindow)                           (* Foo, Terrible Kludges in WINDOW.MOUSE.HANDLER will 
							     cause the chat window to flicker if the mouse stays in 
							     it when quitting this function.)
	      NIL)))

(\RS232CHAT.SWITCHSTATE
  (LAMBDA (STATE ENTERING?)                                  (* JonL " 8-MAY-83 00:29")
    (SETQ \RS232CHAT.MENUSIGNAL)                             (* This FLG is only for coordination between the mouse 
							     and \RS232CHAT.DUPLEX)
    (\RS232CHATBLINKOFF)                                     (* Regardless of whether we are coming or going, the 
							     "cursor" wants to be off.)
    (PROG ((CURRENTSTATE (create RS232CHATEXITSTATE)))
          (UNINTERRUPTABLY
              (if STATE
		  then (MAP2C \RS232CHATSTATE.GLOBALVARS (fetch GLOBALVARS of STATE)
			      (FUNCTION SET))
		       (MAP2C \RS232CHATSTATE.SPECVARS (fetch SPECVARS of STATE)
			      (FUNCTION SET))
		else                                         (* The random variable \RS232CHAT.XON\XOFF? is merely to
							     transfer the 2nd argument of RS232CHAT into here, 
							     knowing that upon exiting RS232XON\XOFF? will be 
							     restored.)
		     (SETQ RS232XON\XOFF? \RS232CHAT.XON\XOFF?))
	      (if ENTERING?
		  then                                       (* Save initial terminal environment while installing 
							     the one appropriate for RS232CHAT NIL)
		       (replace SAVEDTERMENV of CURRENTSTATE
			  with (\RS232CHAT.MODIFY.TERMENV (create SAVEDTERMENV
								  SAVEDTTBL ← \RS232CHATTTBL
								  SAVEDINTERRUPTS ← 
								  \RS232CHAT.PERMITTED.INTERRUPTS
								  SAVEDKEYACTIONS ←(DEFERREDCONSTANT
								    (LIST (ASSOC (QUOTE BLANK-TOP)
										 \ORIGKEYACTIONS)
									  (ASSOC (QUOTE BLANK-MIDDLE)
										 \ORIGKEYACTIONS)
									  (QUOTE (BLANK-BOTTOM 
											 METADOWN . 
											   METAUP)))))
							  T))
		       (RS232MODEMCONTROL (QUOTE (DTR RTS)))
		elseif (NULL STATE)
		  then (SHOULDNT (QUOTE \RS232CHAT.SWITCHSTATE))
		else (\RS232CHAT.MODIFY.TERMENV (fetch SAVEDTERMENV of STATE))
		     (RS232MODEMCONTROL (QUOTE (DTR))))
	      (SETQ RS232CHATEXITSTATE (AND (NOT ENTERING?)
					    CURRENTSTATE)))
          (RETURN CURRENTSTATE))))

(\RS232CHAT.MODIFY.TERMENV
  (LAMBDA (ENV SAVECURRENT?)                                 (* JonL " 5-MAY-83 23:05")
    (PROG ((TTBL (fetch SAVEDTTBL of ENV))
	   (INTS (fetch SAVEDINTERRUPTS of ENV))
	   (ACTS (fetch SAVEDKEYACTIONS of ENV)))
          (if SAVECURRENT?
	      then                                           (* Note how the returned TERMENV record has the previous
							     settings of these states.)
		   (RETURN (create SAVEDTERMENV
				   SAVEDTTBL ←(SETTERMTABLE TTBL)
				   SAVEDINTERRUPTS ←(RESET.INTERRUPTS INTS T)
				   SAVEDKEYACTIONS ←(MODIFY.KEYACTIONS ACTS T)))
	    else (SETTERMTABLE TTBL)
		 (RESET.INTERRUPTS INTS)
		 (MODIFY.KEYACTIONS ACTS)))))

(\RS232CHAT.DUPLEX
  (LAMBDA NIL                                                (* JonL "29-JUN-83 10:09")
    (PROG ((BLOCKINTERVAL (SETUPTIMER 0 NIL (QUOTE TICKS)))
	   (PROMPTSTREAM (GETSTREAM PROMPTWINDOW))
	   ECHOSTREAM ECHO=OUT? ECHOING.NOW? C)
          (DECLARE (SPECVARS ECHO=OUT? ECHOING.NOW? PROMPTSTREAM)
		   (GLOBALVARS \RS232CHATBLINKER))           (* Just to be sure that these SPECVARS are "looked up")
          (SETQ ECHO=OUT? (EQ \RCHATS \RS232CHAT.LocalEchoStream))
          (SETQ ECHOSTREAM (OR \RS232CHAT.LocalEchoStream \RCHATS))
      A                                                      (* Just printout chars from remote host, while waiting 
							     for keyboard input.)
          (repeatuntil (\SYSBUFP)
	     do (\RS232CHATBLINKWINK)
		(if (RS232PEEKBYTE)
		    then (\RS232CHAT.BIN ECHOING.NOW?)
		  elseif (TIMEREXPIRED? BLOCKINTERVAL (QUOTE TICKS))
		    then (PROG NIL                           (* Every so often, we must permit the background 
							     processes to run, so that we can still have a mouse.)
			   B   (if (AND (PROG1 \RS232BACKGROUNDSTATE 
                                                             (* Comment PPLossage))
					(ILESSP (fetch (RS232CHARACTERISTICS BAUDRATE) of RS232INIT)
						\RS232FTPSLOW.BaudRate))
				   then (BLOCK)
				 else (\RS232CHECK.BLOCK))
			       (if (PROG1 (SETQ C \RS232CHAT.MENUSIGNAL)
					  (SETQ \RS232CHAT.MENUSIGNAL))
				   then (\RS232CHATBLINKOFF)
					(SELECTQ C
						 (BREAK (\RS232CHAT.DO↑B))
						 (MENU (MENU \RS232CHATMENU)
                                                             (* Go around again, since the menu may communicate to us
							     via \RS232CHAT.MENUSIGNAL)
						       (GO B))
						 (QUIT (RETFROM (QUOTE \RS232CHAT.DUPLEX)))
						 (Bye (RS232MODEMHANGUP)
						      (RETFROM (QUOTE \RS232CHAT.DUPLEX)))
						 (RS232LOGIN (RS232.PROMPT&LOGIN \RCHATS T))
						 (HELP "Unrecognized \RS23CHAT.MENUSIGNAL" C))))
			 (if (AND \RCHATD (IGREATERP \RCHATD.BTMY (DSPYPOSITION NIL \RCHATD)))
			     then 

          (* When control gets out of our hands, it may print to the chat window without scrolling; so bring the cursor back
	  up to top.)


				  (\RS232CHAT.NEWLINE (CHARCODE EOL)))
			 (SETQ BLOCKINTERVAL (SETUPTIMER \RS232.BLOCKINTERVAL.tics BLOCKINTERVAL
							 (QUOTE TICKS))))
		(SERVICEIRING))                              (* Send typed-in byte to remote host 
							     (unless it is the escape char))
          (if (NOT (SMALLP (SETQ C (\GETSYSBUF))))
	      then (SHOULDNT (QUOTE \GETSYSBUF)))
          (SERVICEIRING)
          (if (EQ C \RS232ESCAPE.CHARCODE)
	      then (ERSETQ (\RS232CHAT.DOCOMMAND))
	    else                                             (* Send out the typed-in byte, but check for extra stuff
							     on EOL)
		 (if (EQ C (CHARCODE EOL))
		     then (RS232WRITECHARS \RS232CHAT.EOLsequence T)
		   else (RS232WRITEBYTE C T))                (* Perhaps local echoing for the keyboard is wanted?)
		 (if \RS232CHAT.LocalEchoStream
		     then (if ECHO=OUT?
			      then (\RS232CHATBLINKOFF))
			  (if (NOT ECHOING.NOW?)
			      then (SETQ ECHOING.NOW? T)
				   (if ECHO=OUT?
				       then (SERVICEIRING)
					    (BOUT \RS232CHAT.LocalEchoStream (CHARCODE %[))))
			  (SERVICEIRING)
			  (BOUT \RS232CHAT.LocalEchoStream C)))
          (GO A))))

(\RS232CHAT.DOCOMMAND
  (LAMBDA NIL                                                (* JonL "27-JUN-83 20:31")
    (DECLARE (SPECVARS PROMPTSTREAM))
    (PROG (C S)
          (\RS232CHATBLINKOFF)
      B   (SERVICEIRING)
          (\RS232BOUTSTRING PROMPTSTREAM "
RS232Chat Command: ")
          (SETQ S
	    (SELCHARQ
	      (SETQ C (\RS232CHAT.GETKEY))
	      ((Q K q k)
		(\RS232BOUTSTRING PROMPTSTREAM "Quit.")
		(RETFROM (QUOTE \RS232CHAT.DUPLEX)))
	      (? (DSPRESET PROMPTWINDOW)
		 

"? - print this help;  7 - truncate to 7-bits;  8 - to 8-bits;
 E - change Escape char; O - XON (use ↑Q/↑S protocol);  F - XOFF; 
 S - Change Speed; <CR> - set EOL to CR;  <LF> - set EOL to CR/LF;
↑B - BREAK Interrupt;  L - LOGIN;  C - Clear RS232CHAT Window;
 R - Call RAID;  B - send Break signal;  Q - Quit (or exit); ")
	      ((B b)
		(RS232SENDBREAK)
		"BREAK sent!")
	      ((L l)
		(RS232.PROMPT&LOGIN \RCHATS)
		NIL)
	      ((C c)
		(AND \RCHATD (DSPRESET \RCHATD))
		"Clear.")
	      ((↑B R r)
		(if (EQ C (CHARCODE ↑B))
		    then (\RS232CHAT.DO↑B)
		  else (RAID))
		NIL)
	      ((O o)
		(SETQ RS232XON\XOFF? T)
		"XON")
	      ((F f)
		(SETQ RS232XON\XOFF?)
		"XOFF")
	      ((S s)                                         (* Note that the interrupts are set as for RS232CHAT, so
							     PROMPTFORWORD doesn't have to fiddle with them)
		(FRESHLINE PROMPTSTREAM)
		(if (NLSETQ (APPLY (QUOTE RS232INIT)
				   (CONS (READ (OR (STRINGP (PROMPTFORWORD
							      "LineSpeed = " "1200"
							      (QUOTE (LAMBDA NIL
									     (QUOTE (110 150 300 600 
											 1200 2400 
											 4800 9600 
											 19200))))
							      PROMPTSTREAM))
						   "FOOBAR"))
					 (CDR RS232INIT))))
		    then NIL
		  else (CONCAT "Unacceptable value; Speed still = " (MKSTRING (fetch (
RS232CHARACTERISTICS BAUDRATE) of RS232INIT)))))
	      ((E e)
		(\RS232BOUTSTRING PROMPTSTREAM "Escape/Command character = ")
		(SETQ \RS232ESCAPE.CHARCODE (\RS232CHAT.GETKEY))
		(CONCAT (CHARACTER \RS232ESCAPE.CHARCODE)
			(CONSTANT (CHARACTER (CHARCODE EOL)))))
	      ((CR LF)
		(SETQ \RS232CHAT.EOLsequence (if (EQ C (CHARCODE CR))
						 then (CONSTANT (CONCAT (CHARACTER (CHARCODE CR))))
					       else (SETQ \RS232CHAT.EOLsequence
						      (CONSTANT (CONCAT (CHARACTER (CHARCODE CR))
									(CHARACTER (CHARCODE LF)))))))
		)
	      ((7 8)
		(SETQ \RS232CHAT7? (EQ C (CHARCODE 7)))
		(if \RS232CHAT7?
		    then "7bit"
		  else "8bit"))
	      (GO B)))
          (AND S (\RS232BOUTSTRING PROMPTSTREAM S))
          (SERVICEIRING))))

(\RS232CHAT.GETKEY
  (LAMBDA NIL                                                (* JonL "22-NOV-82 23:12")
    (eachtime (SERVICEIRING) until (\SYSBUFP) finally (RETURN (PROG1 (\GETSYSBUF)
								     (SERVICEIRING))))))

(\RS232CHAT.DO↑B
  (LAMBDA NIL                                                (* JonL " 9-MAY-83 14:49")
    (RESETFORM (\RS232CHAT.MODIFY.TERMENV (fetch SAVEDTERMENV of RS232CHATEXITSTATE)
					  T)
	       (NLSETQ (BREAK1 NIL T RS232CHAT)))))
)



(* Byte I/O for RS232CHAT)

[DECLARE: EVAL@COMPILE 

(TYPERECORD RS232CHATBINHOOK (HOOKCHARTABLE HOOKFN))
]

(RPAQ? \RS232CHAT7? T)

(RPAQ? RS232REMOTEXOFF? NIL)

(RPAQ? \RS232FTPSLOW.BaudRate 1200)
(DEFINEQ

(\RS232CHAT.BIN
  (LAMBDA (LOCALECHOINGNOW?)                                 (* JonL "27-JUN-83 20:54")
    (DECLARE (SPECVARS ECHO=OUT? ECHOING.NOW? \RS232CHAT.BellSequence))
    (PROG ((C (RS232READBYTE)))
          (if (NULL C)
	      then 

          (* Well, we're only supposed to come to \RS232CHAT.BIN when there is a byte in the input ring buffer, but you know
	  how those things go ...)


		   (RETURN)
	    elseif (AND (EQ C (CHARCODE ↑G))
			RS232XON\XOFF?)
	      then                                           (* Can this really be right? TOPS-20 seems to do it -- 
							     JonL May 1983)
		   (SETQ RS232REMOTEXOFF? T)
		   (RETURN))
          (\RS232CHATBLINKOFF)                               (* Even though the blinker is taken down here, it will 
							     come back on again due to the call to \BLINKWINK in 
							     \RS232CHAT.DUPLEX)
          (if (AND RS232CHATBINHOOK (\SYNCODE (fetch HOOKCHARTABLE of RS232CHATBINHOOK)
					      C))
	      then (APPLY* (fetch HOOKFN of RS232CHATBINHOOK)
			   C)
	    elseif (NOT (FMEMB C \RS232CHAT.IgnoreCharcodes))
	      then (if \RS232CHAT7?
		       then (SETQ C (LOADBYTE C 0 7)))
		   (if LOCALECHOINGNOW?
		       then (SETQ ECHOING.NOW?)
			    (if ECHO=OUT?
				then (BOUT \RS232CHAT.LocalEchoStream (CHARCODE %]))
				     (SERVICEIRING)))
		   (if (NULL \RCHATD)
		       then (BOUT \RCHATS C)
		     elseif (EQ C \RS232CHAT.NEWLINECHAR)
		       then 

          (* Normally, this would be (CHARCODE LF) which works both for systems that send both CR/LF and those that send 
	  only LF. If the remote host sends only CR, then \RS232CHAT.NEWLINECHAR has to be reset.)


			    (\RS232CHAT.NEWLINE)
		     else                                    (* Special hacks for Display code.)
			  (SELCHARQ C
				    ((CR)                    (* This is so we don't get extra LF's on display stream 
							     when a CR/LF is sent from remote host)
				      (DSPXPOSITION (DSPLEFTMARGIN NIL \RCHATD)
						    \RCHATD))
				    ((LF)                    (* Phooey! We'd just like to have \RS232CHAT.NEWLINE be 
							     the EOLFN for \RCHATD)
				      (\RS232CHAT.NEWLINE))
				    ((BELL)                  (* Glaaag, the display code for BELL takes mannnny 
							     milliseconds -- it "flashes" the DisplayStream window.)
				      (if (\RS232CHAT.*APPLY2* (FUNCTION BOUT)
							       \RCHATS C 0)
					elseif \RS232CHAT.BellSequence
					  then (\RS232BOUTSTRING \RCHATS \RS232CHAT.BellSequence)
					else (SERVICEIRING)
					     (RESETFORM (VIDEOCOLOR (SETQ C T))
							(FRPTQ BELLCNT (\RS232CHECK.BLOCK BELLRATE)
							       (VIDEOCOLOR (SETQ C (NOT C))))
							(SERVICEIRING))))
				    (BOUT \RCHATS C))))
          (SERVICEIRING))))

(\RS232CHAT.NEWLINE
  (LAMBDA (C)                                                (* JonL "23-JUN-83 18:49")
    (OR (\RS232CHAT.*APPLY2* (FUNCTION \RS232CHAT.NEWLINE.AUX)
			     C T \RS232FTPSLOW.BaudRate)
	(\RS232CHAT.NEWLINE.AUX C))))

(\RS232CHAT.NEWLINE.AUX
  (LAMBDA (C NO.RINGB.SERVICE.FLG)                           (* JonL "28-JUN-83 05:11")
    (OR NO.RINGB.SERVICE.FLG (SERVICEIRING))
    (PROG ((LFSIZE (IMINUS (ffetch \SFLINEFEED of \RCHATD)))
	   (LEFTMARGIN (ffetch \SFLeftMargin of \RCHATD))
	   (SCROLL? (ffetch \SFScroll of \RCHATD))
	   (OLDY (DSPYPOSITION NIL \RCHATD))
	   NEWY)
          (OR NO.RINGB.SERVICE.FLG (SERVICEIRING))
          (DSPXPOSITION LEFTMARGIN \RCHATD)
          (OR NO.RINGB.SERVICE.FLG (SERVICEIRING))
          (SETQ NEWY (IDIFFERENCE OLDY LFSIZE))
          (if (ILESSP NEWY \RCHATD.BTMY)
	      then (PROG ((DIFFERENTIAL (IDIFFERENCE OLDY \RCHATD.BTMY)))
		         (if (IGREATERP DIFFERENTIAL 0)
			     then                            (* Clean out a few garbage lines at the bottom of the 
							     window)
				  (DSPCLEOL \RCHATD LEFTMARGIN (fetch (REGION BOTTOM)
								  of (ffetch \SFClippingRegion
									of \RCHATD))
					    DIFFERENTIAL))
		         (OR NO.RINGB.SERVICE.FLG (SERVICEIRING))
		         (if SCROLL?
			     then 

          (* Well, foo, as of June 83 we'll just let the system display code handle this case, not worrying about all the 
	  time it will surely take.)


				  (DSPSCROLLUP \RCHATD (IDIFFERENCE OLDY \RCHATD.FONTDESCENT)
					       NIL
					       (IDIFFERENCE LFSIZE DIFFERENTIAL))
				  (SETQ NEWY \RCHATD.BTMY)
				  (GO XIT)
			   else                              (* Wrap, wrap, wrap, wrap, Wrap-around Sue -- to the 
							     tune of the Beach Boys "Run Around Sue")
				(SETQ NEWY \RCHATD.TOPY))))
          (DSPCLEOL \RCHATD LEFTMARGIN (IDIFFERENCE NEWY \RCHATD.FONTDESCENT)
		    LFSIZE)                                  (* Clean out the tubes on the new line)
      XIT (OR NO.RINGB.SERVICE.FLG (SERVICEIRING))
          (DSPYPOSITION NEWY \RCHATD)
          (OR NO.RINGB.SERVICE.FLG (SERVICEIRING)))))

(\RS232CHAT.*APPLY2*
  (LAMBDA (FUN A1 A2 BaudRateLimit)                          (* JonL "28-JUN-83 05:02")
    (SERVICEIRING)
    (PROG ((SLOWENOUGH (ILESSP (fetch (RS232CHARACTERISTICS BAUDRATE) of RS232INIT)
			       BaudRateLimit)))
          (if SLOWENOUGH
	      then (SPREADAPPLY* FUN A1 A2)
	    elseif (NULL RS232XON\XOFF?)
	      then (RETURN)
	    elseif (NOT RS232REMOTEXOFF?)
	      then (PROG (STATUS1 STATUS2)
		         (UNINTERRUPTABLY
                             (SETQ STATUS1 (\RS232CHAT.GAGHIM T))
			     (SPREADAPPLY* FUN A1 A2)
			     (SETQ STATUS2 (\RS232CHAT.GAGHIM)))
		         (if (OR STATUS1 STATUS2)
			     then (\RS232DECODE.LINESTATUS (LOGOR (OR (FIXP STATUS1)
								      0)
								  (OR (FIXP STATUS2)
								      0)))))
	    else                                             (* Here, either the remote host is gagged 
							     (XOFF) or the speed is so slow that it doesn't matter)
		 (SPREADAPPLY* FUN A1 A2))
          (SERVICEIRING)
          (RETURN T))))

(\RS232CHAT.GAGHIM
  (LAMBDA (OFF?)                                             (* JonL " 5-MAY-83 19:28")
    (PROG ((FIRST.STATUS (FIXP (\RS232CHECK.THRE)))
	   OLDHI STATUS)                                     (* Wait until Transmitter holding register **should** be
							     off.)
          (RS232DATAO (if OFF?
			  then (CHARCODE ↑S)
			else (CHARCODE ↑Q)))
          (if (NOT OFF?)
	      then (SETQ RS232REMOTEXOFF?)
		   (RETURN FIRST.STATUS)
	    else (SETQ RS232REMOTEXOFF? T))                  (* Wait until 8 byte-intervals have passed "quietly" 
							     before proceeding -- it may take him a while to hear the
							     XOFF)
      A   (SETQ OLDHI \RS232ORING.WRITE)
          (during \RS232.Tovh&BIC8.tics timerUnits (QUOTE TICKS) usingTimer \RS232.THRE.BOX
	     do (if (RS232INTERRUPT?)
		    then (SETQ STATUS (\RS232.PROCESSINTERRUPT (QUOTE NOERROR)))
			 (if (NULL STATUS)
			     then (if (NEQ OLDHI \RS232ORING.WRITE)
				      then                   (* Foo, some character just walked in, so start the 
							     waiting all over again.)
					   (GO A))
			   else                              (* Foo, there is some sort of error, so exit now)
				(if (NOT (FIXP STATUS))
				    then (SHOULDNT))
				(RETURN))))
          (RETURN (OR (FIXP STATUS)
		      FIRST.STATUS)))))
)
(DECLARE: DOEVAL@COMPILE DONTCOPY

(ADDTOVAR GLOBALVARS \RS232CHAT7? RS232REMOTEXOFF? \RS232FTPSLOW.BaudRate)
)



(* Menu, window, process, and blinker functions)

(DEFINEQ

(\RS232CHAT.GETMENUS
  (LAMBDA NIL                                                (* JonL "29-JUN-83 10:22")
    (RESETFORM (RADIX 10)
	       (SETQ \RS232CHATSPEEDMENU
		 (create MENU
			 ITEMS ←(QUOTE (75 110 150 300 600 1200 2400 4800 9600 19200))
			 TITLE ← "Line Speed"
			 MENUCOLUMNS ← 2
			 MENUFONT ←(DSPFONT NIL WindowTitleDisplayStream)
			 CHANGEOFFSETFLG ← T
			 CENTERFLG ← T))
	       (SETQ \RS232CHATMENU (create MENU
					    ITEMS ←(QUOTE
					      ((7 (SETQ \RS232CHAT7? T)
						  "Trim incoming bytes to 7-bits")
						(8 (SETQ \RS232CHAT7?)
						   "Don't trim incoming bytes to 7-bits")
						(NewLine:LF (SETQ \RS232CHAT.NEWLINECHAR
							      (CHARCODE LF))
							    "Remote sends LF for 'NewLine'")
						(NewLine:CR (SETQ \RS232CHAT.NEWLINECHAR
							      (CHARCODE CR))
							    "Remote sends CR for 'NewLine'")
						(CR->CR/LF (SETQ \RS232CHAT.EOLsequence
							     (CONSTANT (CONCAT (CHARACTER
										 (CHARCODE CR))
									       (CHARACTER
										 (CHARCODE LF)))))
							   "'Return' key sends CR/LF")
						(CR->CR (SETQ \RS232CHAT.EOLsequence
							  (CONSTANT (CONCAT (CHARACTER (CHARCODE
											 CR)))))
							"'Return' key sends CR")
						(Bye (SETQ \RS232CHAT.MENUSIGNAL (QUOTE Bye))
						     "'Hangs up' modem and exits")
						(Quit (SETQ \RS232CHAT.MENUSIGNAL (QUOTE QUIT))
						      "Exits from RS232CHAT.")
						(XON (SETQ RS232XON\OFF? T)
						     "Enable XON/XOFF protocol.")
						(XOFF (SETQ RS232XON\OFF?)
						      "Disable XON/XOFF protocol.")
						(ChangeSpeed (ERSETQ (APPLY (QUOTE RS232INIT)
									    (CONS (MENU 
									      \RS232CHATSPEEDMENU)
										  (CDR RS232INIT))))
							     "Pop-Up menu for line speed selection")
						(RAID (RAID)
						      "Calls RAID")
						(Login (SETQ \RS232CHAT.MENUSIGNAL (QUOTE RS232LOGIN))
						       "Prompt for LOGIN to corresponding Host.")
						(StopLogin (SETQ \RS232LOGIN.STOP? T)
							   
				"If RS232LOGIN is in process, then stops at a 'convenient' time.")
						(SendBreak (RS232SENDBREAK)
							   "Sends 'Break' signal (0.25secs).")
						(LongBreak (RS232SENDBREAK T)
							   "Sends 'Break' signal (3.5secs).")
						(Exit (SETQ \RS232CHAT.MENUSIGNAL (QUOTE QUIT))
						      "Exits from RS232CHAT.")
						(PageSize (if \RS232LOGIN.LASTHOSTSYSTEMTYPE
							      then (\RS232LOGIN.SENDPAGESIZE
								     \RS232CHATWINDOW 
								   \RS232LOGIN.LASTHOSTSYSTEMTYPE
								     (ITIMES 3 \RCLKSECOND)))
							  
			  "Send Page size parameters to logged-in host (which must be at 'exec')")
						(Clear (DSPRESET \RS232CHATWINDOW)
						       "Clears this RS232CHAT window.")
						(↑B (SETQ \RS232CHAT.MENUSIGNAL (QUOTE BREAK))
						    "Enters a Lisp-level HELP/BREAK loop")))
					    MENUCOLUMNS ← 2
					    MENUFONT ←(DSPFONT NIL WindowTitleDisplayStream)
					    TITLE ← "RS232Chat Coms"
					    MENUBORDERSIZE ← 1
					    CENTERFLG ← T)))
                                                             (* Must wait until after MENU is created to set the 
							     MENUOFFSET since we don't know the exact IMAGEWIDTH 
							     beforehand.)
    (replace MENUOFFSET of (PROG1 \RS232CHATMENU             (* Comment PPLossage))
       with (create POSITION
		    XCOORD ←(IQUOTIENT (IDIFFERENCE (fetch (MENU IMAGEWIDTH) of \RS232CHATMENU)
						    6)
				       2)
		    YCOORD ← 20))))

(\RCHATD.SETUP
  (LAMBDA NIL                                                (* JonL " 8-APR-83 20:00")
    (if (type? DISPLAYSTREAM (ffetch (STREAMOFDISPLAYSTREAM DISPLAYSTREAM) of \RCHATS))
	then                                                 (* Makes sure that \RCHATD has its OFD pointer back to 
							     \RCHATS)
	     (SETQ \RCHATD (\GETDISPLAYSTREAMFROMSTREAM \RCHATS))
	     ((LAMBDA (DFONT CREG)                           (* Caches a few important values)
		 (SETQ \RCHATD.FONTDESCENT (FONTDESCENT DFONT))
		 (SETQ \RCHATD.TOPY (ADD1 (IDIFFERENCE (fetch TOP of CREG)
						       (FONTASCENT DFONT))))
		 (SETQ \RCHATD.BTMY (IPLUS (fetch BOTTOM of CREG)
					   \RCHATD.FONTDESCENT)))
	       (DSPFONT NIL \RCHATD)
	       (DSPCLIPPINGREGION NIL \RCHATD))
	     (SETQ \RS232CHATWINDOW (WFROMDS \RCHATD))
	     (replace \SFEOLFN of \RCHATD with (FUNCTION \RS232CHAT.NEWLINE))
	     (MAPC (QUOTE ((RESHAPEFN \RS232CHAT.RESHAPEFN)
			    (BUTTONEVENTFN \RS232CHAT.BUTTONFN)
			    (PROCESS.IDLEFN \RS232CHAT.BUTTONFN)
			    (PROCESS.EXITFN \RS232CHAT.PROCESS.EXIT)))
		   (FUNCTION (LAMBDA (X)
		       (WINDOWPROP \RS232CHATWINDOW (CAR X)
				   (CADR X)))))
	     (\RCHATW.SETUP \RS232CHATWINDOW)
	     (if (NULL (SETQ \RS232CHATBLINKER (WINDOWPROP \RS232CHATWINDOW (QUOTE RS232CHATBLINKER)))
		       )
		 then                                        (* Be sure that there is a "caret" for it.)
		      (SETQ \RS232CHATBLINKER (create RS232CHATBLINKER))
		      (WINDOWPROP \RS232CHATWINDOW (QUOTE RS232CHATBLINKER)
				  \RS232CHATBLINKER))
      else (SETQ \RS232CHATBLINKER (SETQ \RCHATD (SETQ \RS232CHATWINDOW))))))

(\RCHATW.SETUP
  (LAMBDA (W)                                                (* JonL "15-DEC-82 21:22")
    (PROG (PAGEHEIGHT LINELENGTH OLDTITLE)
          (if (SETQ OLDTITLE (WINDOWPROP W (QUOTE TITLE)))
	      then (if (STRPOS (QUOTE :% % PageLength% =% )
			       OLDTITLE)
		       then (SETQ OLDTITLE (SUBSTRING OLDTITLE 1 (SUB1 (STRPOS (QUOTE 
									     :% % PageLength% =% )
									       OLDTITLE)))))
	    else                                             (* Be sure there is a TITLE before calculating 
							     pagelength parameter.)
		 (WINDOWPROP W (QUOTE TITLE)
			     (SETQ OLDTITLE (QUOTE RS232ChatConnection))))
                                                             (* Be sure window is open, and fix up the Title)
          (TOTOPW W)                                         (* Also, clip the PAGEHEIGHT and LINELENGTH at 127, 
							     since TENEX only has a 7-bit field for these 
							     quantities.)
          (SETQ PAGEHEIGHT (IMIN (IQUOTIENT (WINDOWPROP W (QUOTE HEIGHT))
					    (IABS (DSPLINEFEED NIL \RCHATD)))
				 127))
          (SETQ LINELENGTH (IMIN 127 (LINELENGTH NIL W)))
          (WINDOWPROP W (QUOTE TITLE)
		      (CONCAT OLDTITLE (QUOTE :% % PageLength% =% )
			      PAGEHEIGHT ", LineLength = " LINELENGTH))
          (WINDOWPROP W (QUOTE PAGESIZE)
		      (LIST PAGEHEIGHT LINELENGTH)))))

(\RS232CHAT.RESHAPEFN
  (LAMBDA (W IMG REG)                                        (* JonL "18-DEC-82 03:55")
    (RESHAPEBYREPAINTFN W IMG REG)
    (if (EQ W \RS232CHATWINDOW)
	then                                                 (* A moby setup of cached parameters.
							     How can it happen that some window which isn't 
							     \RS232CHATWINDOW gets passed in here?)
	     (SETQ \RCHATS (GETSTREAM \RS232CHATWINDOW))
	     (\RCHATD.SETUP)
      else                                                   (* Just re-calculates the linelength and pagelength 
							     parameters.)
	   (\RCHATW.SETUP W))
    T))

(\RS232CHAT.BUTTONFN
  (LAMBDA (WINDOW)                                           (* JonL "22-APR-83 16:40")
    (if (AND (PROG1 RS232CHATEXITSTATE                       (* RS232CHATEXITSTATE is NIL when we are already within 
							     an RS232CHAT))
	     (LASTMOUSESTATE (OR LEFT MIDDLE)))
	then (if (NOT (WINDOWP WINDOW))
		 then (SHOULDNT (QUOTE WINDOW))
	       elseif (NOT (type? RS232CHATEXITSTATE RS232CHATEXITSTATE))
		 then (SHOULDNT (QUOTE RS232CHATEXITSTATE))
	       elseif (OR (NEQ WINDOW \RS232CHATWINDOW)
			  ((LAMBDA (S D)
			      (SETQ D (fetch (STREAMOFDISPLAYSTREAM DISPLAYSTREAM) of S))
			      (OR (NOT (type? DISPLAYSTREAM D))
				  (NOT (EQ (fetch (DISPLAYSTREAM XWINDOWHINT) of D)
					   \RS232CHATWINDOW))))
			    (fetch (RS232CHATEXITSTATE GLOBALVARS \RCHATS) of RS232CHATEXITSTATE)))
		 then                                        (* Foo, window still active even though someone has 
							     reset \RS232CHATWINDOW variable.)
		      (replace (RS232CHATEXITSTATE GLOBALVARS \RCHATS) of RS232CHATEXITSTATE
			 with (GETSTREAM WINDOW (QUOTE OUTPUT))))
	     (EVAL.AS.PROCESS (LIST (QUOTE \RS232CHAT.REENTER)
				    (KWOTE RS232CHATEXITSTATE)))
      elseif (LASTMOUSESTATE MIDDLE)
	then (SETQ \RS232CHAT.MENUSIGNAL (QUOTE MENU)))))

(\RS232CHAT.DOMENU
  (LAMBDA (WINDOW)                                           (* JonL " 8-APR-83 20:12")
                                                             (* As of 4/8/83 this function is no longer needed;
							     it used to be the RIGHTBUTTONFN for the 
							     \RS232CHATWINDOW)
    (OR (WINDOWP WINDOW)
	(SHOULDNT (QUOTE WINDOW)))
    (if (AND (NULL RS232CHATEXITSTATE)
	     (EQ WINDOW \RS232CHATWINDOW)
	     (type? MENU \RS232CHATMENU)
	     (IGEQ (ffetch \SFClippingTop of (WINDOWPROP WINDOW (QUOTE DSP)))
		   LASTMOUSEY))
	then (MENU \RS232CHATMENU)
      else                                                   (* Standard RIGHTBUTTONFN when not running in RS232CHAT 
							     or if mouse was clicked in title region)
	   (DOWINDOWCOM WINDOW))))
)
(DECLARE: DOEVAL@COMPILE DONTCOPY

(ADDTOVAR GLOBALVARS \RCHATD \RCHATD.FONTDESCENT \RCHATD.BTMY \RCHATD.TOPY)
)
(DEFINEQ

(\RS232CHAT.PROCESS.EXIT
  (LAMBDA (MYWINDOW)                                         (* JonL " 8-APR-83 19:45")
    (\RS232CHATBLINKOFF)
    ((LAMBDA (PROC)
	(if (AND (PROCESSP PROC)
		 (WINDOWPROP MYWINDOW (QUOTE PROCESS.EXITFN)
			     NIL))
	    then (DEL.PROCESS PROC)))
      (WINDOWPROP MYWINDOW (QUOTE PROCESS)))))
)
(DECLARE: EVAL@COMPILE DONTCOPY 
[DECLARE: EVAL@COMPILE 

(RECORD RS232CHATBLINKER (NEXTBLINKTIME BLINKUP? BLINKINTERVAL)
			 NEXTBLINKTIME ←(\RCLOCK0 (NCREATE (QUOTE FIXP)))
			 BLINKINTERVAL ←(ITIMES \CARETRATE \RCLKMILLISECOND))
]
)
(DEFINEQ

(\RS232CHATBLINKWINK
  (LAMBDA (FORCETIMEOUT?)                                    (* JonL "28-DEC-82 05:29")
    (if (NULL \RS232CHATBLINKER)
	then NIL
      elseif (OR FORCETIMEOUT? (TIMEREXPIRED? (fetch NEXTBLINKTIME of \RS232CHATBLINKER)
					      (QUOTE TICS)))
	then (replace NEXTBLINKTIME of \RS232CHATBLINKER with (SETUPTIMER (fetch BLINKINTERVAL
									     of \RS232CHATBLINKER)
									  (fetch NEXTBLINKTIME
									     of \RS232CHATBLINKER)
									  (QUOTE TICS)))
	     (replace BLINKUP? of \RS232CHATBLINKER with (NOT (fetch BLINKUP? of \RS232CHATBLINKER)))
	     (SERVICEIRING)
	     (UNINTERRUPTABLY
                 (TOTOPW \RCHATD)
		 (BITBLT (fetch (CURSOR CURSORBITMAP) of \CARET)
			 0 0 (PROG1 \RCHATD                  (* Comment PPLossage))
			 (IDIFFERENCE (DSPXPOSITION NIL \RCHATD)
				      (fetch CURSORHOTSPOTX of \CARET))
			 (IDIFFERENCE (DSPYPOSITION NIL \RCHATD)
				      (fetch CURSORHOTSPOTY of \CARET))
			 CURSORWIDTH CURSORHEIGHT (QUOTE INPUT)
			 (QUOTE INVERT))))
    (SERVICEIRING)))

(\RS232CHATBLINKOFF
  (LAMBDA NIL                                                (* JonL "28-DEC-82 04:55")
    (if \RS232CHATBLINKER
	then (SERVICEIRING)
	     (if (fetch BLINKUP? of \RS232CHATBLINKER)
		 then (\RS232CHATBLINKWINK T))               (* Either he's already off, or we turn him off)
	     (replace NEXTBLINKTIME of (PROG1 \RS232CHATBLINKER 
                                                             (* Comment PPLossage))
		with (SETUPTIMER 0 (fetch NEXTBLINKTIME of \RS232CHATBLINKER)
				 (QUOTE TICS))))             (* And set his timer now so that any subsequent calls to
							     \BLINKWINK will turn him on)
    (SERVICEIRING)))
)

(RPAQ? \RS232CHATWINDOW NIL)

(RPAQ? \RS232CHATMENU NIL)

(RPAQ? \RS232CHATSPEEDMENU NIL)

(RPAQ? \RS232CHAT.MENUSIGNAL NIL)

(RPAQ? \RS232CHATBLINKER NIL)
(DECLARE: DOEVAL@COMPILE DONTCOPY

(ADDTOVAR GLOBALVARS \RS232CHATWINDOW \RS232CHATMENU \RS232CHATSPEEDMENU \RS232CHAT.MENUSIGNAL 
	  \RS232CHATBLINKER)
)
(PUTPROPS RS232CHAT COPYRIGHT ("Xerox Corporation" 1982 1983))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (4983 17378 (RS232CHAT 4993 . 6281) (\RS232CHAT.REENTER 6283 . 7777) (
\RS232CHAT.SWITCHSTATE 7779 . 9935) (\RS232CHAT.MODIFY.TERMENV 9937 . 10676) (\RS232CHAT.DUPLEX 10678
 . 14234) (\RS232CHAT.DOCOMMAND 14236 . 16867) (\RS232CHAT.GETKEY 16869 . 17110) (\RS232CHAT.DO↑B 
17112 . 17376)) (17601 25274 (\RS232CHAT.BIN 17611 . 20539) (\RS232CHAT.NEWLINE 20541 . 20794) (
\RS232CHAT.NEWLINE.AUX 20796 . 22769) (\RS232CHAT.*APPLY2* 22771 . 23845) (\RS232CHAT.GAGHIM 23847 . 
25272)) (25444 34913 (\RS232CHAT.GETMENUS 25454 . 28892) (\RCHATD.SETUP 28894 . 30618) (\RCHATW.SETUP 
30620 . 32028) (\RS232CHAT.RESHAPEFN 32030 . 32699) (\RS232CHAT.BUTTONFN 32701 . 34079) (
\RS232CHAT.DOMENU 34081 . 34911)) (35027 35381 (\RS232CHAT.PROCESS.EXIT 35037 . 35379)) (35622 37504 (
\RS232CHATBLINKWINK 35632 . 36773) (\RS232CHATBLINKOFF 36775 . 37502)))))
STOP