diff --git a/library/CLIPBOARD b/library/CLIPBOARD
index df4a12fb..ad645445 100644
--- a/library/CLIPBOARD
+++ b/library/CLIPBOARD
@@ -1 +1 @@
-(DEFINE-FILE-INFO READTABLE "INTERLISP" PACKAGE "INTERLISP")
(FILECREATED " 8-Aug-2020 15:48:08" 
{DSK}<Users>kaplan>Local>medley3.5>lispcore>library>CLIPBOARD.;53 7823   

      changes to%:  (VARS CLIPBOARDCOMS)

      previous date%: " 8-Aug-2020 15:25:18" 
{DSK}<Users>kaplan>Local>medley3.5>lispcore>library>CLIPBOARD.;52)


(PRETTYCOMPRINT CLIPBOARDCOMS)

(RPAQQ CLIPBOARDCOMS
       [                                                     (* ; "Enable copy and paste")
        (FNS INSTALL-CLIPBOARD GETCLIPBOARD PUTCLIPBOARD PASTEFROMCLIPBOARD LISPINTERRUPTS.PASTE)
        (FNS TEDIT.COPYTOCLIPBOARD TEDIT.EXTRACTTOCLIPBOARD)
        (FNS SEDIT.COPYTOCLIPBOARD)
        (INITVARS (CLIPBOARD-FORMAT :UTF8))
        (DECLARE%: DONTEVAL@LOAD DOEVAL@COMPILE DOCOPY (FILES (SYSLOAD)
                                                              UNIXCOMM UNICODE)
               (P (INSTALL-CLIPBOARD)))
        (DECLARE%: DONTEVAL@LOAD DOEVAL@COMPILE DONTCOPY COMPILERVARS (ADDVARS (NLAMA)
                                                                             (NLAML)
                                                                             (LAMA])



(* ; "Enable copy and paste")

(DEFINEQ

(INSTALL-CLIPBOARD
  [LAMBDA NIL                                               (* ; "Edited  8-Aug-2020 07:59 by rmk:")
                                                            (* ; "Edited 19-Apr-2020 12:15 by rmk:")
                                                            (* ; "Edited 18-Apr-2018 23:00 by rmk:")
    (CL:WHEN (GETD 'LISPINTERRUPTS.PASTE)
        (MOVD? 'LISPINTERRUPTS 'LISPINTERRUPTS.ORIG)
        (MOVD 'LISPINTERRUPTS.PASTE 'LISPINTERRUPTS))
    (INTERRUPTCHAR (CHARCODE "1,v")
           '(PASTEFROMCLIPBOARD))
    (INTERRUPTCHAR (CHARCODE "1,V")
           '(PASTEFROMCLIPBOARD))
    (CL:WHEN (BOUNDP 'TEDIT.READTABLE)                       (* ; "TEDIT")

        (* ;; "Paste")

        (TEDIT.SETFUNCTION (CHARCODE "1,v")
               (FUNCTION PASTEFROMCLIPBOARD)
               TEDIT.READTABLE)
        (TEDIT.SETFUNCTION (CHARCODE "1,V")
               (FUNCTION PASTEFROMCLIPBOARD)
               TEDIT.READTABLE)

        (* ;; "Copy")

        (TEDIT.SETFUNCTION (CHARCODE "1,c")
               (FUNCTION TEDIT.COPYTOCLIPBOARD)
               TEDIT.READTABLE)
        (TEDIT.SETFUNCTION (CHARCODE "1,C")
               (FUNCTION TEDIT.COPYTOCLIPBOARD)
               TEDIT.READTABLE)

        (* ;; "Extract")

        (TEDIT.SETFUNCTION (CHARCODE "1,X")
               (FUNCTION TEDIT.EXTRACTTOCLIPBOARD)
               TEDIT.READTABLE)
        (TEDIT.SETFUNCTION (CHARCODE "1,x")
               (FUNCTION TEDIT.EXTRACTTOCLIPBOARD)
               TEDIT.READTABLE))
    (CL:WHEN (GETP 'SEDIT 'FILEDATES)                        (* ; 
                                                             "SEDIT copy: INTERRUPTCHAR does paste")
        (SEDIT:ADD-COMMAND "1,c" 'SEDIT.COPYTOCLIPBOARD)
        (SEDIT:ADD-COMMAND "1,C" 'SEDIT.COPYTOCLIPBOARD)
        (SEDIT:RESET-COMMANDS))])

(GETCLIPBOARD
  [LAMBDA NIL                                               (* ; "Edited  8-Aug-2020 07:56 by rmk:")
                                                            (* ; "Edited 25-Apr-2018 16:56 by rmk:")
    (CL:WITH-OPEN-STREAM (s (CREATE-PROCESS-STREAM "pbpaste"))
           (\EXTERNALFORMAT s CLIPBOARD-FORMAT)
           [SETFILEINFO s 'ENDOFSTREAMOP #'(CL:LAMBDA (s)
                                                  (RETFROM (FUNCTION READCCODE)
                                                         NIL]
           (CONCATCODES (BIND C WHILE (SETQ C (READCCODE s)) COLLECT C])

(PUTCLIPBOARD
  [LAMBDA (OBJECT PRINTFN)                                  (* ; "Edited  8-Aug-2020 07:56 by rmk:")
                                                            (* ; "Edited 25-Apr-2018 16:49 by rmk:")

    (* ;; "Clipboard is UNICODE and UTF8")

    (CL:WITH-OPEN-STREAM (s (CREATE-PROCESS-STREAM "pbcopy"))
           (\EXTERNALFORMAT s CLIPBOARD-FORMAT)
           (IF PRINTFN
               THEN (APPLY* PRINTFN OBJECT s)
             ELSE (PRIN3 OBJECT s])

(PASTEFROMCLIPBOARD
  [LAMBDA NIL                                           (* ; "Edited 18-Apr-2018 13:56 by rmk:")
                                                            (* ; "Edited 17-Apr-2018 23:11 by rmk:")

    (* ;; 
  "Should be able to just call COPYINSERT, but the default BKSYSBUF puts in string qujotes ")

    (LET ((STR (GETCLIPBOARD)))
         (IF (WINDOWPROP (PROCESS.WINDOW (TTY.PROCESS))
                        'COPYINSERTFN)
             THEN (COPYINSERT STR)
           ELSE (BIND C WHILE (SETQ C (GNCCODE STR)) DO (BKSYSCHARCODE C])

(LISPINTERRUPTS.PASTE
  [LAMBDA NIL                                           (* ; "Edited 18-Apr-2018 22:59 by rmk:")

    (* ;; "So paste interrupts will be installed in every process")

    (APPEND [LIST (LIST (CHARCODE "1,v")
                        '(PASTEFROMCLIPBOARD))
                  (LIST (CHARCODE "1,V")
                        '(PASTEFROMCLIPBOARD]
           (LISPINTERRUPTS.ORIG])
)
(DEFINEQ

(TEDIT.COPYTOCLIPBOARD
  [LAMBDA NIL                                           (* ; "Edited 18-Apr-2018 00:02 by rmk:")
    (LET [(TEXTSTREAM (TEXTSTREAM (TTY.PROCESS]
         (IF TEXTSTREAM
             THEN (PUTCLIPBOARD (TEDIT.SEL.AS.STRING TEXTSTREAM])

(TEDIT.EXTRACTTOCLIPBOARD
  [LAMBDA NIL                                           (* ; "Edited 19-Apr-2020 12:17 by rmk:")
                                                            (* ; "Edited 18-Apr-2018 00:02 by rmk:")
    (LET [(TEXTSTREAM (TEXTSTREAM (TTY.PROCESS]
         (IF TEXTSTREAM
             THEN (PUTCLIPBOARD (TEDIT.SEL.AS.STRING TEXTSTREAM))
                   (TEDIT.DELETE TEXTSTREAM (TEDIT.GETSEL TEXTSTREAM])
)
(DEFINEQ

(SEDIT.COPYTOCLIPBOARD
  [LAMBDA (CONTEXT)                                     (* ; "Edited  8-Aug-2020 15:25 by rmk:")
                                                            (* ; "Edited 24-Apr-2018 20:39 by rmk:")
                                                            (* ; "Edited 24-Apr-2018 20:33 by rmk:")
                                                            (* ; "Edited 23-Apr-2018 18:19 by rmk:")
    [CL:MULTIPLE-VALUE-BIND (SEL SELTYPE)
           (SEDIT:GET-SELECTION CONTEXT)

           (* ;; "SEL could be a list of several elements, or a structure, depending on SELTYPE.  ")

           (* ;; "SELTYPE=NIL means not a valid selection, and SEL is NIL.  Non-NIL values are :SUB-LIST, :CHARACTERS, and T")

           (CL:WHEN SELTYPE
               [PUTCLIPBOARD (CONS SEL (EQ SELTYPE :SUB-LIST))
                      (FUNCTION (LAMBDA (PAIR STREAM)
                                  (LET ((*PRINT-PRETTY* T)
                                        (PRETTYTABFLG NIL)
                                        (FONTCHANGEFLG NIL)
                                        (%#RPARS NIL))
                                       (DECLARE (SPECVARS *PRINT-PRETTY* %#RPARS PRETTYTABFLG 
                                                           FONTCHANGEFLG))
                                       (PRINTDEF (CAR PAIR)
                                              0 NIL (CDR PAIR)
                                              NIL STREAM])]
    T])
)

(RPAQ? CLIPBOARD-FORMAT :UTF8)
(DECLARE%: DONTEVAL@LOAD DOEVAL@COMPILE DOCOPY 

(FILESLOAD (SYSLOAD)
       UNIXCOMM UNICODE)


(INSTALL-CLIPBOARD)
)
(DECLARE%: DONTEVAL@LOAD DOEVAL@COMPILE DONTCOPY COMPILERVARS 

(ADDTOVAR NLAMA )

(ADDTOVAR NLAML )

(ADDTOVAR LAMA )
)
(PUTPROPS CLIPBOARD COPYRIGHT (NONE))
(DECLARE%: DONTCOPY
  (FILEMAP (NIL (1216 5170 (INSTALL-CLIPBOARD 1226 . 3048) (GETCLIPBOARD 3050 . 3649) (PUTCLIPBOARD 3651
 . 4126) (PASTEFROMCLIPBOARD 4128 . 4745) (LISPINTERRUPTS.PASTE 4747 . 5168)) (5171 5930 (
TEDIT.COPYTOCLIPBOARD 5181 . 5462) (TEDIT.EXTRACTTOCLIPBOARD 5464 . 5928)) (5931 7470 (
SEDIT.COPYTOCLIPBOARD 5941 . 7468)))))
STOP
\ No newline at end of file
+(DEFINE-FILE-INFO READTABLE "INTERLISP" PACKAGE "INTERLISP")
(FILECREATED "22-Feb-2021 14:39:46" 
{DSK}<Users>kaplan>Local>medley3.5>git-medley>library>CLIPBOARD.;48 8988   

      changes to%:  (VARS CLIPBOARDCOMS)
                    (FNS GETCLIPBOARD PUTCLIPBOARD CLIPBOARD-COPY-STREAM CLIPBOARD-PASTE-STREAM)

      previous date%: "15-Feb-2021 23:48:39" 
{DSK}<Users>kaplan>Local>medley3.5>git-medley>library>CLIPBOARD.;47)


(PRETTYCOMPRINT CLIPBOARDCOMS)

(RPAQQ CLIPBOARDCOMS
       [                                                     (* ; "Enable copy and paste")
        (FNS INSTALL-CLIPBOARD GETCLIPBOARD PUTCLIPBOARD PASTEFROMCLIPBOARD LISPINTERRUPTS.PASTE 
             CLIPBOARD-COPY-STREAM CLIPBOARD-PASTE-STREAM)
        (FNS TEDIT.COPYTOCLIPBOARD TEDIT.EXTRACTTOCLIPBOARD)
        (FNS SEDIT.COPYTOCLIPBOARD)
        (INITVARS (CLIPBOARD-FORMAT :UTF8))
        (DECLARE%: DONTEVAL@LOAD DOEVAL@COMPILE DOCOPY (FILES (SYSLOAD)
                                                              UNIXCOMM UNICODE)
               (P (INSTALL-CLIPBOARD)))
        (DECLARE%: DONTEVAL@LOAD DOEVAL@COMPILE DONTCOPY COMPILERVARS (ADDVARS (NLAMA)
                                                                             (NLAML)
                                                                             (LAMA])



(* ; "Enable copy and paste")

(DEFINEQ

(INSTALL-CLIPBOARD
  [LAMBDA NIL                                               (* ; "Edited  8-Aug-2020 07:59 by rmk:")
                                                            (* ; "Edited 19-Apr-2020 12:15 by rmk:")
                                                            (* ; "Edited 18-Apr-2018 23:00 by rmk:")
    (CL:WHEN (GETD 'LISPINTERRUPTS.PASTE)
        (MOVD? 'LISPINTERRUPTS 'LISPINTERRUPTS.ORIG)
        (MOVD 'LISPINTERRUPTS.PASTE 'LISPINTERRUPTS))
    (INTERRUPTCHAR (CHARCODE "1,v")
           '(PASTEFROMCLIPBOARD))
    (INTERRUPTCHAR (CHARCODE "1,V")
           '(PASTEFROMCLIPBOARD))
    (CL:WHEN (BOUNDP 'TEDIT.READTABLE)                       (* ; "TEDIT")

        (* ;; "Paste")

        (TEDIT.SETFUNCTION (CHARCODE "1,v")
               (FUNCTION PASTEFROMCLIPBOARD)
               TEDIT.READTABLE)
        (TEDIT.SETFUNCTION (CHARCODE "1,V")
               (FUNCTION PASTEFROMCLIPBOARD)
               TEDIT.READTABLE)

        (* ;; "Copy")

        (TEDIT.SETFUNCTION (CHARCODE "1,c")
               (FUNCTION TEDIT.COPYTOCLIPBOARD)
               TEDIT.READTABLE)
        (TEDIT.SETFUNCTION (CHARCODE "1,C")
               (FUNCTION TEDIT.COPYTOCLIPBOARD)
               TEDIT.READTABLE)

        (* ;; "Extract")

        (TEDIT.SETFUNCTION (CHARCODE "1,X")
               (FUNCTION TEDIT.EXTRACTTOCLIPBOARD)
               TEDIT.READTABLE)
        (TEDIT.SETFUNCTION (CHARCODE "1,x")
               (FUNCTION TEDIT.EXTRACTTOCLIPBOARD)
               TEDIT.READTABLE))
    (CL:WHEN (GETP 'SEDIT 'FILEDATES)                        (* ; 
                                                             "SEDIT copy: INTERRUPTCHAR does paste")
        (SEDIT:ADD-COMMAND "1,c" 'SEDIT.COPYTOCLIPBOARD)
        (SEDIT:ADD-COMMAND "1,C" 'SEDIT.COPYTOCLIPBOARD)
        (SEDIT:RESET-COMMANDS))])

(GETCLIPBOARD
  [LAMBDA NIL                                           (* ; "Edited 22-Feb-2021 14:23 by rmk:")
                                                            (* ; "Edited 25-Apr-2018 16:56 by rmk:")
    (CL:WITH-OPEN-STREAM (s (CLIPBOARD-PASTE-STREAM))
           (\EXTERNALFORMAT s CLIPBOARD-FORMAT)
           [SETFILEINFO s 'ENDOFSTREAMOP #'(CL:LAMBDA (s)
                                                  (RETFROM (FUNCTION READCCODE)
                                                         NIL]
           (CONCATCODES (BIND C WHILE (SETQ C (READCCODE s)) COLLECT C])

(PUTCLIPBOARD
  [LAMBDA (OBJECT PRINTFN)                              (* ; "Edited 22-Feb-2021 14:38 by rmk:")
                                                            (* ; "Edited 25-Apr-2018 16:49 by rmk:")

    (* ;; "Clipboard is UNICODE and UTF8")

    (CL:WITH-OPEN-STREAM (s (CLIPBOARD-COPY-STREAM))
           (\EXTERNALFORMAT s CLIPBOARD-FORMAT)
           (IF PRINTFN
               THEN (APPLY* PRINTFN OBJECT s)
             ELSE (PRIN3 OBJECT s])

(PASTEFROMCLIPBOARD
  [LAMBDA NIL                                           (* ; "Edited 15-Feb-2021 23:43 by rmk:")
                                                            (* ; "Edited 18-Apr-2018 13:56 by rmk:")
                                                            (* ; "Edited 17-Apr-2018 23:11 by rmk:")

    (* ;; "If for some reason TTY process doesn't have a window (e.g. TEXEC), we can only do the character printing.  Presumably the right thing to do--no image objects in an exec.")

    (* ;; "Should be able to just call COPYINSERT, but the default BKSYSBUF puts in string quotes.")

    (LET [(STR (GETCLIPBOARD))
          (WINDOW (PROCESS.WINDOW (TTY.PROCESS]
         (IF (AND WINDOW (WINDOWPROP WINDOW 'COPYINSERTFN))
             THEN (COPYINSERT STR)
           ELSE (BIND C WHILE (SETQ C (GNCCODE STR)) DO (BKSYSCHARCODE C])

(LISPINTERRUPTS.PASTE
  [LAMBDA NIL                                           (* ; "Edited 18-Apr-2018 22:59 by rmk:")

    (* ;; "So paste interrupts will be installed in every process")

    (APPEND [LIST (LIST (CHARCODE "1,v")
                        '(PASTEFROMCLIPBOARD))
                  (LIST (CHARCODE "1,V")
                        '(PASTEFROMCLIPBOARD]
           (LISPINTERRUPTS.ORIG])

(CLIPBOARD-COPY-STREAM
  [LAMBDA NIL                                           (* ; "Edited 22-Feb-2021 14:38 by rmk:")
    (LET ((OST (UNIX-GETENV "OSTYPE")))
         (CREATE-PROCESS-STREAM (CL:IF (STRPOS "darwin" OST)
                                    "pbcopy"
                                    "xclip")])

(CLIPBOARD-PASTE-STREAM
  [LAMBDA NIL                                           (* ; "Edited 22-Feb-2021 14:23 by rmk:")
    (LET ((OST (UNIX-GETENV "OSTYPE")))
         (CREATE-PROCESS-STREAM (CL:IF (STRPOS "darwin" OST)
                                    "pbpaste"
                                    "xclip")])
)
(DEFINEQ

(TEDIT.COPYTOCLIPBOARD
  [LAMBDA NIL                                           (* ; "Edited 18-Apr-2018 00:02 by rmk:")
    (LET [(TEXTSTREAM (TEXTSTREAM (TTY.PROCESS]
         (IF TEXTSTREAM
             THEN (PUTCLIPBOARD (TEDIT.SEL.AS.STRING TEXTSTREAM])

(TEDIT.EXTRACTTOCLIPBOARD
  [LAMBDA NIL                                           (* ; "Edited 19-Apr-2020 12:17 by rmk:")
                                                            (* ; "Edited 18-Apr-2018 00:02 by rmk:")
    (LET [(TEXTSTREAM (TEXTSTREAM (TTY.PROCESS]
         (IF TEXTSTREAM
             THEN (PUTCLIPBOARD (TEDIT.SEL.AS.STRING TEXTSTREAM))
                   (TEDIT.DELETE TEXTSTREAM (TEDIT.GETSEL TEXTSTREAM])
)
(DEFINEQ

(SEDIT.COPYTOCLIPBOARD
  [LAMBDA (CONTEXT)                                     (* ; "Edited  8-Aug-2020 15:25 by rmk:")
                                                            (* ; "Edited 24-Apr-2018 20:39 by rmk:")
                                                            (* ; "Edited 24-Apr-2018 20:33 by rmk:")
                                                            (* ; "Edited 23-Apr-2018 18:19 by rmk:")
    [CL:MULTIPLE-VALUE-BIND (SEL SELTYPE)
           (SEDIT:GET-SELECTION CONTEXT)

           (* ;; "SEL could be a list of several elements, or a structure, depending on SELTYPE.  ")

           (* ;; "SELTYPE=NIL means not a valid selection, and SEL is NIL.  Non-NIL values are :SUB-LIST, :CHARACTERS, and T")

           (CL:WHEN SELTYPE
               [PUTCLIPBOARD (CONS SEL (EQ SELTYPE :SUB-LIST))
                      (FUNCTION (LAMBDA (PAIR STREAM)
                                  (LET ((*PRINT-PRETTY* T)
                                        (PRETTYTABFLG NIL)
                                        (FONTCHANGEFLG NIL)
                                        (%#RPARS NIL))
                                       (DECLARE (SPECVARS *PRINT-PRETTY* %#RPARS PRETTYTABFLG 
                                                           FONTCHANGEFLG))
                                       (PRINTDEF (CAR PAIR)
                                              0 NIL (CDR PAIR)
                                              NIL STREAM])]
    T])
)

(RPAQ? CLIPBOARD-FORMAT :UTF8)
(DECLARE%: DONTEVAL@LOAD DOEVAL@COMPILE DOCOPY 

(FILESLOAD (SYSLOAD)
       UNIXCOMM UNICODE)


(INSTALL-CLIPBOARD)
)
(DECLARE%: DONTEVAL@LOAD DOEVAL@COMPILE DONTCOPY COMPILERVARS 

(ADDTOVAR NLAMA )

(ADDTOVAR NLAML )

(ADDTOVAR LAMA )
)
(PUTPROPS CLIPBOARD COPYRIGHT (NONE))
(DECLARE%: DONTCOPY
  (FILEMAP (NIL (1376 6335 (INSTALL-CLIPBOARD 1386 . 3208) (GETCLIPBOARD 3210 . 3832) (PUTCLIPBOARD 3834
 . 4336) (PASTEFROMCLIPBOARD 4338 . 5256) (LISPINTERRUPTS.PASTE 5258 . 5679) (CLIPBOARD-COPY-STREAM 
5681 . 6005) (CLIPBOARD-PASTE-STREAM 6007 . 6333)) (6336 7095 (TEDIT.COPYTOCLIPBOARD 6346 . 6627) (
TEDIT.EXTRACTTOCLIPBOARD 6629 . 7093)) (7096 8635 (SEDIT.COPYTOCLIPBOARD 7106 . 8633)))))
STOP
\ No newline at end of file
diff --git a/library/CLIPBOARD.LCOM b/library/CLIPBOARD.LCOM
index 3d96ce94..4fe0bc17 100644
Binary files a/library/CLIPBOARD.LCOM and b/library/CLIPBOARD.LCOM differ
diff --git a/library/CLIPBOARD.TXT b/library/CLIPBOARD.TXT
new file mode 100644
index 00000000..78f0002a
--- /dev/null
+++ b/library/CLIPBOARD.TXT
@@ -0,0 +1,17 @@
+library/CLIPBOARD
+
+Written by Ron Kaplan, 2020-2021
+
+A small package that implements copy and paste to the system clipboard.
+
+It arms meta-C for copy to the clipboard from the current selection of an application that has been armed (Tedit, Sedit), and also meta-X for extraction (copy followed by delete).
+
+Meta-V is defined as an interrupt character that pastes the current clipboard contents into whatever process curent has input focus.
+
+The information in the clipboard can be provided from or provided to external (non-Medley) applications (mail, emacs, etc.) in the usual way.  For example, a form cselected in SEDIT can be copied to the clipboard and pasted into an email message.
+
+It assumes that the clipboard is a utf-8/unicode stream, and uses the UNICODE package to convert to and from the Medley internal character encoding (XCCS).
+
+The name of the clipboard stream may differ from platform to platform.  On the Mac, the paste stream is "pbpaste" and the copy stream is "pbcopy".  Those names are used if "darwin" is a substring of (UNIX-GETENV "ostype").  Otherwise both stream-names default to "xclip".  The functions CLIPBOARD-COPY-STREAM and CLIPBOARD-PASTE-STREAM perform this selection.
+
+
