branch: externals/hyperbole
commit c86935b4a030d340c62d77e706ceebc56c449453
Author: Bob Weiner <[email protected]>
Commit: Bob Weiner <[email protected]>

    {M-w} and {C-x r s} utilize selectable things when no region active
    
    {C-w} in kotl-mode does the same thing.
---
 ChangeLog         |  54 +++++++++++++++++-
 hbut.el           |  49 ++++++++--------
 hsettings.el      |   4 +-
 hui-select.el     |   6 +-
 hypb.el           | 129 ++++++++++++++++++++++++++++++++++++++++-
 hyperbole.el      |  22 ++++---
 hyrolo-logic.el   |  28 +++++----
 hyrolo.el         |  17 +++---
 kotl/MANIFEST     |   2 +-
 kotl/kimport.el   |   9 ++-
 kotl/klink.el     | 168 +++++++++++++++++++++++++++++++++---------------------
 kotl/kotl-mode.el | 135 +++++++++++++++++++++++++++++--------------
 kotl/kview.el     |  20 ++++---
 13 files changed, 458 insertions(+), 185 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index a337113577..3599ed4bcb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,9 +1,61 @@
+2022-04-12  Bob Weiner  <[email protected]>
+
+* hypb.el (hypb:selectable-thing): Add and use in hypb:kill-ring-save, 
kotl-mode:kill-region,
+          (hypb:selectable-thing-and-bounds): Add and use in 
hypb:copy-to-register.
+  hui-select.el (hui-select-get-region): Rename to hui-select-get-thing.
+
+2022-04-11  Bob Weiner  <[email protected]>
+
+* kotl/kimport.el (kimport:insert-register): Make autoload since could be 
invoked from {C-x r i}
+    when in a Koutline.
+                  (kimport:insert-file): Make autoload since could be invoked 
from {C-x i} when
+    in a Koutline.
+
+2022-04-10  Bob Weiner  <[email protected]>
+
+* kotl/klink.el (klink:absolute): Add.
+                (klink:parse): Allow for '<@' at the start of a klink 
reference.
+
+* hypb.el (hypb:copy-to-register): Add.
+  hyperbole.el (hkey-initialize): Bind {C-x r s} to hypb:copy-to-register in 
hyperbole-mode.
+
+* hypb.el (hypb:kill-ring-save):
+  hyperbole.el (hkey-initialize): Override the {M-w} command from "simple.el" 
when hyperbole-mode is
+    active to allow copying selectable thing at point if no region is active.
+
+* kotl/kotl-mode.el (kotl-mode:kill-region): When called interactively with no 
region active, copy
+    selectable thing at point or reference to kcell at point.  Also show 
copied region to the user
+    if called interactively with copy-p flag.
+
+* kotl/kview.el (require 'klink): Add.
+                (kcell-view:absolute-reference, kcell-view:reference): Return 
nil if not in kotl-mode.
+
+* kotl/kotl-mode.el (kotl-mode:copy-kcell-reference-to-register): Add to save 
a Koutline cell reference
+    at point to a register.
+                    (kotl-mode:copy-absolute-kcell-link-to-kill-ring): Rename 
from
+    kotl-mode:copy-absolute-klink-to-kill-ring.
+                    (kotl-mode:copy-relative-kcell-link-to-kill-ring): Rename 
from
+    kotl-mode:copy-relative-klink-to-kill-ring.
+                    (kotl-mode:copy-absolute-kcell-link-to-register): Rename 
from
+    kotl-mode:copy-absolute-klink-to-register.
+                    (kotl-mode:copy-relative-kcell-link-to-register): Rename 
from
+    kotl-mode:copy-relative-klink-to-register.
+
+* kotl/klink.el (klink:at-p): Make an autoload since klinks may be tested in 
non-Koutline buffers.
+    Also add yank-handler text property used when yanking klink into a buffer.
+                (klink:set-yank-handler):
+                (klink:yank-handler): Add to handle yanks of klinks and adjust 
based on yank location.
+  kotl/kview.el (kcell-view:absolute-reference, kcell-view:reference): Use 
klink:set-yank-handler.
+
+* hsettings.el (hyperbole-web-search-alist): Update value-type property to 
allow for function symbols,
+    e.g. webjump item.
+
 2022-04-09  Mats Lidell  <[email protected]>
 
 * test/hyrolo-tests.el (hyrolo-add-items-at-multiple-levels): Add check
     and remove test temp file.
 
-2022-04-03  Kathy  <[email protected]>
+2022-04-03  Bob Weiner  <[email protected]>
 
 * test/kotl-mode-tests.el (setup-kotl-mode-example-test): Fix so handles 
multiple buffers with same
     buffer name prefix.
diff --git a/hbut.el b/hbut.el
index 1fe3fa4ecd..01191108b5 100644
--- a/hbut.el
+++ b/hbut.el
@@ -3,7 +3,7 @@
 ;; Author:       Bob Weiner
 ;;
 ;; Orig-Date:    18-Sep-91 at 02:57:09
-;; Last-Mod:     20-Feb-22 at 22:08:04 by Bob Weiner
+;; Last-Mod:     10-Apr-22 at 09:45:19 by Bob Weiner
 ;;
 ;; Copyright (C) 1991-2022  Free Software Foundation, Inc.
 ;; See the "HY-COPY" file for license information.
@@ -972,11 +972,11 @@ Ignore email-related buffers."
              nil
            (goto-char start)
            (insert comment-start)
-           (if (not (eq (preceding-char) ?\ ))
-               (insert ?\ ))
+           (unless (eq (preceding-char) ?\ )
+             (insert ?\ ))
            (goto-char (+ (point) (- end start)))
-           (if (not (eq (following-char) ?\ ))
-               (insert ?\ ))
+           (unless (eq (following-char) ?\ )
+             (insert ?\ ))
            (insert comment-end))))))
 
 ;;; Regexps derived in part from "filladapt.el" by Kyle E. Jones under
@@ -1009,12 +1009,11 @@ Ignore email-related buffers."
 (defun    hbut:fill-prefix-remove (label)
   "Remove any recognized fill prefix from within LABEL.
 `hbut:fill-prefix-regexps' is a list of fill prefixes to recognize."
-  (if (string-match "\n" label)
-      (mapc (lambda (fill-prefix)
-             (and (string-match "\n" label)
-                  (setq label
-                        (hypb:replace-match-string fill-prefix label " " t))))
-           hbut:fill-prefix-regexps))
+  (when (string-match "\n" label)
+    (mapc (lambda (prefix)
+           (when (string-match "\n" label)
+             (setq label (hypb:replace-match-string prefix label " " t))))
+         hbut:fill-prefix-regexps))
   label)
 
 (defun    hbut:delete (&optional lbl-key buffer key-src)
@@ -1070,7 +1069,8 @@ nil.  BUFFER defaults to the current buffer."
 
 (defun    hbut:is-p (object)
   "Return non-nil if OBJECT is a symbol representing a Hyperbole button."
- (and (symbolp object) (hattr:get object 'categ)))
+ (when (symbolp object)
+   (hattr:get object 'categ)))
 
 (defun    hbut:key (hbut)
   "Return the key for Hyperbole button symbol HBUT."
@@ -1131,17 +1131,17 @@ With optional FULL when source is a pathname, return 
the full pathname."
   "Return unformatted filename associated with formatted current buffer.
 This is used to obtain the source of Hyperbole buttons for buffers that
 represent the output of particular document formatters."
-  (and (or (eq major-mode 'Info-mode)
-          (string-match "\\.info\\(-[0-9]+\\)?$" (buffer-name)))
-       (let ((src (and buffer-file-name
-                      (substring
-                       buffer-file-name
-                       0 (string-match "\\.[^.]+$" buffer-file-name)))))
-        (cond ((file-exists-p (concat src ".texi"))
-               (concat src ".texi"))
-              ((file-exists-p (concat src ".texinfo"))
-               (concat src ".texinfo"))
-              ((current-buffer))))))
+  (when (or (eq major-mode 'Info-mode)
+           (string-match "\\.info\\(-[0-9]+\\)?$" (buffer-name)))
+    (let ((src (and buffer-file-name
+                   (substring
+                    buffer-file-name
+                    0 (string-match "\\.[^.]+$" buffer-file-name)))))
+      (cond ((file-exists-p (concat src ".texi"))
+            (concat src ".texi"))
+           ((file-exists-p (concat src ".texinfo"))
+            (concat src ".texinfo"))
+           ((current-buffer))))))
 
 (defun    hbut:key-src-set-buffer (src)
   "Set buffer to SRC, a buffer, buffer name, file, directory or symlink and 
return SRC or nil if invalid."
@@ -1570,8 +1570,7 @@ Return symbol for button deleted or nil."
   (unless but-sym
     (setq but-sym 'hbut:current))
   (when (ibut:is-p but-sym)
-    (let ((but-key (hattr:get but-sym 'lbl-key))
-         (loc     (hattr:get but-sym 'loc))
+    (let ((loc     (hattr:get but-sym 'loc))
          (start   (hattr:get but-sym 'lbl-start))
          (end     (hattr:get but-sym 'lbl-end)))
       (when (and start end)
diff --git a/hsettings.el b/hsettings.el
index 6aec0e694b..c79b616c43 100644
--- a/hsettings.el
+++ b/hsettings.el
@@ -3,7 +3,7 @@
 ;; Author:       Bob Weiner
 ;;
 ;; Orig-Date:    15-Apr-91 at 00:48:49
-;; Last-Mod:     26-Feb-22 at 16:29:33 by Bob Weiner
+;; Last-Mod:     10-Apr-22 at 10:55:06 by Bob Weiner
 ;;
 ;; Copyright (C) 1991-2021  Free Software Foundation, Inc.
 ;; See the "HY-COPY" file for license information.
@@ -251,7 +251,7 @@ obtained search string."
   :set (lambda (_option value)
         (set _option value)
         (hyperbole-update-menus))
-  :type '(alist :key-type string :value-type string)
+  :type '(alist :key-type string :value-type (choice string symbol))
   :group 'hyperbole-commands)
 
 ;;; ************************************************************************
diff --git a/hui-select.el b/hui-select.el
index 303d43699e..8801fb5d00 100644
--- a/hui-select.el
+++ b/hui-select.el
@@ -3,7 +3,7 @@
 ;; Author:       Bob Weiner
 ;;
 ;; Orig-Date:    19-Oct-96 at 02:25:27
-;; Last-Mod:     20-Feb-22 at 14:50:54 by Bob Weiner
+;; Last-Mod:     12-Apr-22 at 00:43:21 by Bob Weiner
 ;;
 ;; Copyright (C) 1996-2021  Free Software Foundation, Inc.
 ;; See the "HY-COPY" file for license information.
@@ -391,8 +391,8 @@ Also, add language-specific syntax setups to aid in thing 
selection."
        (hui-select-word (point)))))
 
 ;;;###autoload
-(defun hui-select-get-region ()
-  "Return the region that `hui-select-thing' would select."
+(defun hui-select-get-thing ()
+  "Return the thing at point that `hui-select-thing' would select."
   (let ((region-bounds (hui-select-get-region-boundaries)))
     (when region-bounds
       (buffer-substring-no-properties (car region-bounds) (cdr 
region-bounds)))))
diff --git a/hypb.el b/hypb.el
index f3329631fc..a779344b0e 100644
--- a/hypb.el
+++ b/hypb.el
@@ -3,7 +3,7 @@
 ;; Author:       Bob Weiner
 ;;
 ;; Orig-Date:     6-Oct-91 at 03:42:38
-;; Last-Mod:     20-Feb-22 at 22:12:33 by Bob Weiner
+;; Last-Mod:     12-Apr-22 at 01:40:32 by Bob Weiner
 ;;
 ;; Copyright (C) 1991-2022  Free Software Foundation, Inc.
 ;; See the "HY-COPY" file for license information.
@@ -217,6 +217,53 @@ If no matching installation type is found, return a list 
of (\"unknown\" hyperb:
          (keep-lines "^(HyDebug)" opoint (point))))
       (untabify start (point)))))
 
+;; Derived from copy-to-register of "register.el"
+;;;###autoload
+(defun hypb:copy-to-register (register start end &optional delete-flag region)
+  "Copy region or thing into register REGISTER.
+With prefix arg, delete as well.
+Called from program, takes five args: REGISTER, START, END, DELETE-FLAG,
+and REGION.  START and END are buffer positions indicating what to copy.
+The optional argument REGION if non-nil, indicates that we're not just
+copying some text between START and END, but we're copying the region.
+
+Interactively, reads the register using `register-read-with-preview'.
+
+If called interactively and there is no active region, copy any selectable
+thing at point; see `hypb:selectable-thing'."
+  (interactive (list (register-read-with-preview "Copy to register: ")
+                    (region-beginning)
+                    (region-end)
+                    current-prefix-arg
+                    t))
+  (let (thing-and-bounds
+       thing
+       start
+       end
+       str)
+    (prog1 (setq str
+                ;; If called interactively and no region is active, copy thing 
at
+                ;; point or current kcell ref when in kotl-mode
+                (cond ((and (called-interactively-p 'interactive)
+                            (not (use-region-p))
+                            (prog1 (setq thing-and-bounds 
(hypb:selectable-thing-and-bounds)
+                                         start (nth 1 thing-and-bounds)
+                                         end   (nth 2 thing-and-bounds)
+                                         thing (nth 0 thing-and-bounds))
+                              (when (and delete-flag start end)
+                                (delete-region start end))))
+                       thing)
+                      (region
+                       (funcall region-extract-function delete-flag))
+                      (t (filter-buffer-substring start end delete-flag))))
+      (set-register register str)
+      (setq deactivate-mark t)
+      (cond (delete-flag)
+           ((called-interactively-p 'interactive)
+            (if thing
+                (message "Saved selectable thing: %s" thing)
+              (indicate-copied-region)))))))
+
 (defun hypb:debug ()
   "Load Hyperbole hbut.el source file and set debugging traceback flag."
   (interactive)
@@ -546,6 +593,52 @@ copied, otherwise, it is omitted."
       (or (kview:char-invisible-p start) (append-to-buffer buffer start (1+ 
start)))
       (setq start (1+ start)))))
        
+;; Override the {M-w} command from "simple.el" when hyperbole-mode is active
+;; to allow copying kcell references or regions.
+;;;###autoload
+(defun hypb:kill-ring-save (beg end &optional region)
+  "Save the active region as if killed, but don't kill it.
+In Transient Mark mode, deactivate the mark.
+If `interprogram-cut-function' is non-nil, also save the text for a window
+system cut and paste.
+
+If called interactively and there is no active region, copy any selectable
+thing at point; see `hypb:selectable-thing'.
+
+If you want to append the killed region to the last killed text,
+use \\[append-next-kill] before \\[kill-ring-save].
+
+The copied text is filtered by `filter-buffer-substring' before it is
+saved in the kill ring, so the actual saved text might be different
+from what was in the buffer.
+
+When called from Lisp, save in the kill ring the stretch of text
+between BEG and END, unless the optional argument REGION is
+non-nil, in which case ignore BEG and END, and save the current
+region instead.
+
+This command is similar to `copy-region-as-kill', except that it gives
+visual feedback indicating the extent of the region being copied."
+  ;; Pass mark first, then point, because the order matters when
+  ;; calling `kill-append'.
+  (interactive (list (mark) (point)
+                    (prefix-numeric-value current-prefix-arg)))
+  (let (thing)
+    (if (or (use-region-p)
+           (not (called-interactively-p 'interactive)))
+       (copy-region-as-kill beg end region)
+      (setq thing (hypb:selectable-thing))
+      (if (stringp thing)
+         (progn (kill-new thing)
+                (setq deactivate-mark t))
+       (copy-region-as-kill beg end region)))
+    ;; This use of called-interactively-p is correct because the code it
+    ;; controls just gives the user visual feedback.
+    (when (called-interactively-p 'interactive)
+      (if thing
+         (message "Saved selectable thing: %s" thing)
+       (indicate-copied-region)))))
+
 ;;;###autoload
 (defun hypb:locate (search-string &optional filter arg)
   "Find file name match anywhere, calling the value of `locate-command', and 
putting results in the `*Locate*' buffer.
@@ -744,6 +837,40 @@ The value returned is the value of the last form in BODY."
             (select-frame-set-input-focus (window-frame window)))
     (error "(hypb:select-window-frame): Argument must be a live window, not 
'%s'" window)))
 
+(defun hypb:selectable-thing ()
+  "Return any selectable thing at point as a string or nil if none."
+  (cond ((klink:absolute (klink:at-p)))
+       ((derived-mode-p 'kotl-mode)
+        (kcell-view:absolute-reference))
+       ((let* ((hbut (hbut:at-p))
+               (start (when hbut (hattr:get hbut 'lbl-start)))
+               (end (when hbut (hattr:get hbut 'lbl-end))))
+          (and start end
+               (buffer-substring-no-properties start end))))
+       ((hui-select-at-delimited-thing-p)
+        (hui-select-get-thing))))
+
+(defun hypb:selectable-thing-and-bounds ()
+  "Return a list of any selectable thing at point as a string, start position 
of thing, end position of thing, or nil if none.
+Start and end may be nil if thing was generated rather than extracted from a 
region."
+  (let (thing-and-bounds thing start end)
+    (cond ((setq thing-and-bounds (klink-at-p))
+          (when thing-and-bounds
+            (setcar (klink:absolute thing-and-bounds) thing-and-bounds)
+            thing-and-bounds))
+         ((derived-mode-p 'kotl-mode)
+          (list (kcell-view:absolute-reference)))
+         ((setq thing (hbut:at-p)
+                start (when thing (hattr:get thing 'lbl-start))
+                end (when thing (hattr:get thing 'lbl-end)))
+          (and start end
+               (list (buffer-substring-no-properties start end) start end)))
+         ((hui-select-at-delimited-thing-p)
+          (when (setq thing-and-bounds (hui-select-get-region-boundaries))
+            (buffer-substring-no-properties (car thing-and-bounds) (cdr 
thing-and-bounds))
+            (car thing-and-bounds)
+            (cdr thing-and-bounds))))))
+
 (defun hypb:set-raw-syntax-descriptor (char raw-descriptor &optional 
syntax-table)
   "Set the syntax of CHAR to RAW-DESCRIPTOR (syntax table value) in the 
current syntax table or optional SYNTAX-TABLE.
 Return the RAW-DESCRIPTOR.  Use the `syntax-after' function to
diff --git a/hyperbole.el b/hyperbole.el
index 577c69e188..966f19e1e4 100644
--- a/hyperbole.el
+++ b/hyperbole.el
@@ -5,7 +5,7 @@
 ;; Author:           Bob Weiner
 ;; Maintainer:       Bob Weiner <[email protected]>, Mats Lidell <[email protected]>
 ;; Created:          06-Oct-92 at 11:52:51
-;; Last-Mod:     20-Feb-22 at 12:15:16 by Bob Weiner
+;; Last-Mod:     10-Apr-22 at 21:12:50 by Bob Weiner
 ;; Released:         03-May-21
 ;; Version:          8.0.0pre
 ;; Keywords:         comm, convenience, files, frames, hypermedia, languages, 
mail, matching, mouse, multimedia, outlines, tools, wp
@@ -260,12 +260,6 @@ of the commands."
          (hkey-set-key "\M-o" #'hkey-operate)
        (hkey-maybe-set-key "\M-o" #'hkey-operate)))
     ;;
-    ;; Bind {C-c @} to create a user-specified sized grid of windows
-    ;; displaying different buffers.
-    ;;
-    ;; Don't override prior bindings of this key.
-    (hkey-maybe-set-key "\C-c@" #'hycontrol-windows-grid)
-    ;;
     ;; Explicit button renames without invoking the Hyperbole menu.
     ;; No binding by default.
     ;; Don't override prior bindings of this key.
@@ -276,6 +270,20 @@ of the commands."
     ;; of unit selected each time.
     (hkey-maybe-set-key "\C-c\C-m" #'hui-select-thing)
     ;;
+    ;; Override the {M-w} command from "simple.el" when hyperbole-mode is 
active
+    ;; to allow copying kcell references or regions to the kill ring.
+    (hkey-set-key [remap kill-ring-save] #'hypb:kill-ring-save)
+    ;;
+    ;; Override the {C-x r s} command from "register.el" when hyperbole-mode 
is active
+    ;; to allow saving kcell references or regions to a register.
+    (hkey-set-key "\C-xrs" #'hypb:copy-to-register)
+    ;;
+    ;; Bind {C-c @} to create a user-specified sized grid of windows
+    ;; displaying different buffers.
+    ;;
+    ;; Don't override prior bindings of this key.
+    (hkey-maybe-set-key "\C-c@" #'hycontrol-windows-grid)
+    ;;
     ;; Bind {C-c \} to interactively manage windows and frames.
     (hkey-maybe-set-key "\C-c\\" #'hycontrol-enable-windows-mode)
     ;;
diff --git a/hyrolo-logic.el b/hyrolo-logic.el
index 854773a359..da7823ac35 100644
--- a/hyrolo-logic.el
+++ b/hyrolo-logic.el
@@ -3,7 +3,7 @@
 ;; Author:       Bob Weiner
 ;;
 ;; Orig-Date:    13-Jun-89 at 22:57:33
-;; Last-Mod:     24-Jan-22 at 00:23:35 by Bob Weiner
+;; Last-Mod:     10-Apr-22 at 09:53:39 by Bob Weiner
 ;;
 ;; Copyright (C) 1989-2021  Free Software Foundation, Inc.
 ;; See the "HY-COPY" file for license information.
@@ -136,13 +136,12 @@ single argument."
   "Apply SEXP to all entries in optional IN-BUFS, display entries where SEXP 
is non-nil.
 If IN-BUFS is nil, `hyrolo-file-list' is used.  If optional COUNT-ONLY is
 non-nil, don't display entries, return count of matching entries only.  If
-optional INCLUDE-SUB-ENTRIES flag is non-nil, SEXP will be applied across all
-sub-entries at once.  Default is to apply SEXP to each entry and sub-entry
-separately.  Entries are displayed with all of their sub-entries unless
-INCLUDE-SUB-ENTRIES is nil and optional NO-SUB-ENTRIES-OUT flag is non-nil.
-SEXP should use the free variables `start' and `end' which contain the limits
-of the region on which it should operate.  Returns number of evaluations of
-SEXP that matched entries."
+optional INCLUDE-SUB-ENTRIES flag is non-nil, apply SEXP across all sub-entries
+at once.  Default is to apply SEXP to each entry and sub-entry separately.
+Entries are displayed with all of their sub-entries unless INCLUDE-SUB-ENTRIES
+is nil and optional NO-SUB-ENTRIES-OUT flag is non-nil.  SEXP should utilize 
the
+free variables `start' and `end' as the region on which to operate.
+Return the number of evaluations of SEXP that match entries."
   (let* ((display-buf (unless count-only
                       (prog1 (set-buffer (get-buffer-create 
hyrolo-display-buffer))
                         (setq buffer-read-only nil)
@@ -164,13 +163,12 @@ SEXP that matched entries."
                         include-sub-entries _no-sub-entries-out)
   "Apply logical SEXP to each entry in HYROLO-BUF and write out matching 
entries to `hyrolo-display-buffer'.
 If optional COUNT-ONLY is non-nil, don't display entries, return count of
-matching entries only.  If optional INCLUDE-SUB-ENTRIES flag is non-nil, SEXP
-will be applied across all sub-entries at once.  Default is to apply SEXP to
-each entry and sub-entry separately.  Entries are displayed with all of their
-sub-entries unless INCLUDE-SUB-ENTRIES is nil and optional NO-SUB-ENTRIES-OUT
-flag is non-nil.  SEXP should use the free variables `start' and `end' which
-contain the limits of the region on which it should operate.  Returns number
-of applications of SEXP that matched entries."
+matching entries only.  If optional INCLUDE-SUB-ENTRIES flag is non-nil, apply
+SEXP across all sub-entries at once.  Default is to apply SEXP to each entry
+and sub-entry separately.  Entries are displayed with all of their sub-entries
+unless INCLUDE-SUB-ENTRIES is nil and optional NO-SUB-ENTRIES-OUT flag is 
non-nil.
+SEXP should utilize the free variables `start' and `end' as the region on which
+to operate.  Return the number of evaluations of SEXP that match entries."
   (setq hyrolo-buf (or (get-buffer hyrolo-buf) hyrolo-buf))
   (if (or (bufferp hyrolo-buf)
          (if (file-exists-p hyrolo-buf)
diff --git a/hyrolo.el b/hyrolo.el
index 3869ce73a0..e0b768bd33 100644
--- a/hyrolo.el
+++ b/hyrolo.el
@@ -3,7 +3,7 @@
 ;; Author:       Bob Weiner
 ;;
 ;; Orig-Date:     7-Jun-89 at 22:08:29
-;; Last-Mod:     26-Mar-22 at 14:57:44 by Bob Weiner
+;; Last-Mod:     10-Apr-22 at 23:46:44 by Bob Weiner
 ;;
 ;; Copyright (C) 1991-2021  Free Software Foundation, Inc.
 ;; See the "HY-COPY" file for license information.
@@ -224,8 +224,7 @@ entry which begins with the parent string."
        (error "(hyrolo-add): Insertion failed, `%s' parent entry not found in 
\"%s\""
               parent file)))
     (narrow-to-region (point) (progn (hyrolo-to-entry-end t (length level)) 
(point)))
-    (let* ((len (length name))
-          (name-level (concat level "*"))
+    (let* ((name-level (concat level "*"))
           (level-len (length name-level))
           (first-char (aref name 0))
           (entry "")
@@ -980,8 +979,7 @@ Return number of matching entries found."
       (insert "No result.")
     (print contacts (get-buffer-create "*contacts-data*"))
     (dolist (contact contacts)
-      (let* (child
-            (name-value (nth 0 (xml-get-children contact 'gd:name)))
+      (let* ((name-value (nth 0 (xml-get-children contact 'gd:name)))
              (fullname (xml-node-child-string (nth 0 (xml-get-children 
name-value 'gd:fullName))))
              (givenname (xml-node-child-string (nth 0 (xml-get-children 
name-value 'gd:givenName))))
              (familyname (xml-node-child-string (nth 0 (xml-get-children 
name-value 'gd:familyName))))
@@ -995,7 +993,7 @@ Return number of matching entries found."
 
              (notes (xml-node-child-string (nth 0 (xml-get-children contact 
'content))))
              ;; Links
-             (links (xml-get-children contact 'link))
+             ;; (links (xml-get-children contact 'link))
 
              ;; Multiple values
              ;; Format is ((rel-type . data) (rel-type . data) … )
@@ -1229,12 +1227,13 @@ Return number of groupings matched."
        ;; Caller may have adjusted entry visibility, so don't do this: 
(outline-show-all)
        total-found))))
 
-(defun hyrolo-map-single-subtree (func exact-level-regexp level-len 
buffer-read-only)
+(defun hyrolo-map-single-subtree (func exact-level-regexp level-len 
read-only-flag)
   "See doc for `hyrolo-map-level'.  Return number of groupings matched."
   (let* ((start (point))
         (end 0)
         (num-found 0)
-        (higher-level-entry-regexp))
+        (higher-level-entry-regexp)
+        (buffer-read-only read-only-flag))
     ;; Move to the next instance of 'level-regexp'.
     ;; Although subtrees are hidden, searches will still see them.
     (when (re-search-forward exact-level-regexp nil t)
@@ -1498,7 +1497,7 @@ Return point where matching entry begins or nil if not 
found."
 CURR-ENTRY-LEVEL-LEN is the integer length of the last entry
 header found.  If INCLUDE-SUB-ENTRIES is nil, CURR-ENTRY-LEVEL-LEN is not 
needed.
 Return current point."
-  ;; Sets free variable, next-entry-exists, for speed.
+  ;; Set free variable, next-entry-exists, for speed.
   (while (and (setq next-entry-exists
                    (re-search-forward hyrolo-entry-regexp nil t))
              include-sub-entries
diff --git a/kotl/MANIFEST b/kotl/MANIFEST
index 473ef2b987..f551ffa1da 100644
--- a/kotl/MANIFEST
+++ b/kotl/MANIFEST
@@ -6,7 +6,7 @@ kfile.el                  - Save and restore koutlines from 
files
 kfill.el                 - Fill and justify koutline cells
 kimport.el               - Convert and insert other outline file formats into 
koutlines
 klabel.el                 - Display label handling for koutlines
-klink.el                  - Implicit reference to a kcell action type, for use 
in koutlines
+klink.el                  - Implicit reference to a Koutline kcell
 kmenu.el                  - Pulldown and popup menus for kotl-mode, the 
Koutliner mode
 kotl-mode.el              - Major mode for editing koutlines and associated 
commands
 kotl-orgtbl.el            - Allow use of Org minor-mode table editing in 
koutlines
diff --git a/kotl/kimport.el b/kotl/kimport.el
index 765aa24ad7..7cf0d171d8 100644
--- a/kotl/kimport.el
+++ b/kotl/kimport.el
@@ -3,7 +3,7 @@
 ;; Author:       Bob Weiner
 ;;
 ;; Orig-Date:    15-Nov-93 at 11:57:05
-;; Last-Mod:     12-Feb-22 at 10:42:20 by Mats Lidell
+;; Last-Mod:     11-Apr-22 at 23:51:03 by Bob Weiner
 ;;
 ;; Copyright (C) 1993-2021  Free Software Foundation, Inc.
 ;; See the "../HY-COPY" file for license information.
@@ -120,6 +120,7 @@ BUFFER may be a buffer or a buffer name."
   (insert-buffer-substring buffer)
   (kotl-mode:add-indent-to-region))
 
+;;;###autoload
 (defun kimport:insert-file (import-from children-p)
   "Insert each element in IMPORT-FROM as a separate cell in the current view.
 Insert as sibling cells following the current cell unless prefix arg,
@@ -147,6 +148,7 @@ Set mark after the inserted text."
     (push-mark (+ (point) (car (cdr tem)))))
   (kotl-mode:add-indent-to-region))
 
+;;;###autoload
 (defun kimport:insert-register (register &optional arg)
   "Insert contents of register REGISTER at point in current cell.
 REGISTER is a character naming the register to insert.
@@ -167,8 +169,9 @@ Interactively, second arg is non-nil if prefix ARG is 
supplied."
            (princ (marker-position val) (current-buffer)))
           (t
            (error "Register `%c' does not contain text" register))))
-  ;; Do want to activate the mark here.
-  (if (not arg) (exchange-point-and-mark)))
+  (unless arg
+    ;; Do want to activate the mark here.
+    (exchange-point-and-mark)))
 
 ;;; Augment right-side numbered files, blank line between cells
 ;;;
diff --git a/kotl/klink.el b/kotl/klink.el
index f3dec16efe..95f7b1d927 100644
--- a/kotl/klink.el
+++ b/kotl/klink.el
@@ -1,9 +1,9 @@
-;;; klink.el --- Implicit reference to a kcell action type, for use in 
koutlines  -*- lexical-binding: t; -*-
+;;; klink.el --- Implicit reference to a Koutline kcell  -*- lexical-binding: 
t; -*-
 ;;
 ;; Author:       Bob Weiner
 ;;
 ;; Orig-Date:    15-Nov-93 at 12:15:16
-;; Last-Mod:     12-Feb-22 at 18:50:58 by Bob Weiner
+;; Last-Mod:     10-Apr-22 at 23:11:46 by Bob Weiner
 ;;
 ;; Copyright (C) 1993-2021  Free Software Foundation, Inc.
 ;; See the "../HY-COPY" file for license information.
@@ -84,6 +84,17 @@
 ;;; Public functions
 ;;; ************************************************************************
 
+(defun klink:absolute (label-and-pos)
+  "With point in a klink's source buffer and LABEL-AND-POS a list of 
(klink-label, klink-start, klink-end) including delimiters, return an absolute 
klink string.
+Klink is of the form: \"<absolute-file-name, cell-ref>\".
+See documentation for `kcell:ref-to-id' for valid cell-ref formats."
+  (when (and (derived-mode-p 'kotl-mode) label-and-pos (listp label-and-pos))
+    (let* ((file-and-cell-ref (klink:parse (car label-and-pos)))
+          (file (or (car file-and-cell-ref) buffer-file-name))
+          (cell-ref (nth 1 file-and-cell-ref)))
+      (klink:set-yank-handler
+       (format "<%s, %s>" (expand-file-name file) cell-ref)))))
+
 ;;;###autoload
 (defun klink:create (reference)
   "Insert at point an implicit link to REFERENCE.
@@ -108,11 +119,11 @@ See documentation for `kcell:ref-to-id' for valid 
cell-ref formats."
        file-ref cell-ref)
     (setq reference (klink:parse reference)
          file-ref  (car reference)
-         cell-ref  (car (cdr reference)))
+         cell-ref  (nth 1 reference))
     ;; Don't need filename if link is to a cell in current buffer.
-    (if (and file-ref (equal buffer-file-name
-                            (expand-file-name file-ref default-directory)))
-       (setq file-ref nil))
+    (when (and file-ref (equal buffer-file-name
+                              (expand-file-name file-ref default-directory)))
+      (setq file-ref nil))
     (cond (file-ref
           (setq file-ref (hpath:relative-to file-ref))
                 ;; "./" prefix, if any.
@@ -124,67 +135,77 @@ See documentation for `kcell:ref-to-id' for valid 
cell-ref formats."
          (cell-ref (insert "<@ " cell-ref ">"))
          (t  (error "(klink:create) Invalid reference, `%s'" reference)))))
 
+;;;###autoload
 (defun klink:at-p ()
   "Return non-nil iff point is within a klink.
 See documentation for the `actypes::link-to-kotl' function for valid klink
 formats.  Value returned is a list of: link-label, link-start-position, and
 link-end-position, (including delimiters)."
-  (let (bol klink referent path)
-    (if (and
-        ;; Avoid false matches in certain modes.
-        (not (memq major-mode klink:ignore-modes))
-        ;; If this is an OO-Browser listing buffer, ignore anything that
-        ;; looks like a klink, e.g. a C++ <template> class.
-        (if (fboundp 'br-browser-buffer-p)
-            (not (br-browser-buffer-p))
-          t)
-        ;; If in a programming mode, Klinks can occur only within comments.
-        (if (derived-mode-p 'prog-mode)
-            ;; Next line means point is within a comment
-            (nth 4 (syntax-ppss))
-          t)
-        ;; If in a C-based mode, Klinks can only occur within comments.
-        (if (and (memq major-mode klink:c-style-modes)
-                 (fboundp 'c-within-comment-p))
-            (or (c-within-comment-p)
-                (save-excursion
-                  (and (re-search-backward "//\\|\n" nil t) (looking-at 
"//"))))
-          t)
-        ;; Don't match to C-style lines like:  #include < path >
-        ;; even if inside a comment.
-        (if (memq major-mode klink:c-style-modes)
-            (save-excursion
-              (beginning-of-line)
-              (setq bol (point))
-              (require 'hmouse-tag)
-              (not (looking-at smart-c-include-regexp)))
-          t)
-        (save-excursion
-          ;; Don't match Elisp print objects such as #<buffer>
-          ;; even if inside a comment
-          (and (search-backward "<" bol t)
-               (not (eq (preceding-char) ?#))
-               ;; Don't match to \<(explicit)> Hyperbole buttons
-               (not (eq (char-after (1+ (point))) ?\())))
-        (setq klink (hbut:label-p t "<" ">" t))
-        (stringp (setq referent (car klink)))
-        (setq referent (string-trim referent))
-        ;; Ensure it conforms to some klink specification.
-        (or (string-match "^ *[-@|!&]" referent)
-            (if (string-match "\\s-*," referent)
-                (progn (setq path (substring referent 0 (match-beginning 0)))
-                       (hpath:is-p path))
-              (hpath:is-p referent)))
-        ;; Eliminate matches to e-mail addresses like, <user@domain>
-        (not (string-match "[^<> \t\n\r\f][!&@]" referent))
-        ;; Eliminate matches to URLs
-        (not (string-match "\\`[a-zA-Z]+:" referent))
-        ;; Don't match to <HTML> and </SGML> type tags
-        (not (and (memq major-mode hui-select-markup-modes)
-                  ;; Assume , followed by a number is a klink.
-                  (not (string-match ",\\s-*[0-9]" referent))
-                  (string-match "\\`[a-zA-Z!/]" referent))))
-       klink)))
+  (let (bol label-and-pos referent path)
+    (when (and
+          ;; Avoid false matches in certain modes.
+          (not (memq major-mode klink:ignore-modes))
+          ;; If this is an OO-Browser listing buffer, ignore anything that
+          ;; looks like a klink, e.g. a C++ <template> class.
+          (if (fboundp 'br-browser-buffer-p)
+              (not (br-browser-buffer-p))
+            t)
+          ;; If in a programming mode, Klinks can occur only within comments.
+          (if (derived-mode-p 'prog-mode)
+              ;; Next line means point is within a comment
+              (nth 4 (syntax-ppss))
+            t)
+          ;; If in a C-based mode, Klinks can only occur within comments.
+          (if (and (memq major-mode klink:c-style-modes)
+                   (fboundp 'c-within-comment-p))
+              (or (c-within-comment-p)
+                  (save-excursion
+                    (and (re-search-backward "//\\|\n" nil t) (looking-at 
"//"))))
+            t)
+          ;; Don't match to C-style lines like:  #include < path >
+          ;; even if inside a comment.
+          (if (memq major-mode klink:c-style-modes)
+              (save-excursion
+                (beginning-of-line)
+                (setq bol (point))
+                (require 'hmouse-tag)
+                (not (looking-at smart-c-include-regexp)))
+            t)
+          (save-excursion
+            ;; Don't match Elisp print objects such as #<buffer>
+            ;; even if inside a comment
+            (and (search-backward "<" bol t)
+                 (not (eq (preceding-char) ?#))
+                 ;; Don't match to \<(explicit)> Hyperbole buttons
+                 (not (eq (char-after (1+ (point))) ?\())))
+          (setq label-and-pos (hbut:label-p t "<" ">" t))
+          (stringp (setq referent (car label-and-pos)))
+          (setq referent (string-trim referent))
+          ;; Ensure it conforms to some klink specification.
+          (or (string-match "^ *[-@|!&]" referent)
+              (if (string-match "\\s-*," referent)
+                  (progn (setq path (substring referent 0 (match-beginning 0)))
+                         (hpath:is-p path))
+                (hpath:is-p referent)))
+          ;; Eliminate matches to e-mail addresses like, <user@domain>
+          (not (string-match "[^<> \t\n\r\f][!&@]" referent))
+          ;; Eliminate matches to URLs
+          (not (string-match "\\`[a-zA-Z]+:" referent))
+          ;; Don't match to <HTML> and </SGML> type tags
+          (not (and (memq major-mode hui-select-markup-modes)
+                    ;; Assume , followed by a number is a klink.
+                    (not (string-match ",\\s-*[0-9]" referent))
+                    (string-match "\\`[a-zA-Z!/]" referent))))
+      label-and-pos)))
+
+(defun klink:set-yank-handler (klink)
+  "Add yank-handler to KLINK so link is made relative when yanked into the 
same koutline or the same directory.
+Return the modified KLINK."
+  (add-text-properties 0 (length klink)
+                      (list 'yank-handler 'klink:yank-handler
+                            'yank-excluded-properties (cons 'yank-handler 
(get-text-property 0 'yank-excluded-properties klink)))
+                      klink)
+  klink)
 
 ;;; ************************************************************************
 ;;; Hyperbole type definitions
@@ -196,7 +217,7 @@ link-end-position, (including delimiters)."
 See documentation for the `link-to-kotl' function for valid klink formats."
   (let* ((link-and-pos (klink:at-p))
         (link (car link-and-pos))
-        (start-pos (car (cdr link-and-pos))))
+        (start-pos (nth 1 link-and-pos)))
     (when link
       (ibut:label-set link-and-pos)
       (hact 'klink:act link start-pos))))
@@ -253,8 +274,8 @@ See documentation for `kcell:ref-to-id' for valid cell-ref 
formats."
 (defun klink:parse (reference)
   "Return (file-ref cell-ref) list parsed from REFERENCE string.
 Either element of the list may be nil if REFERENCE does not contain that
-element.  REFERENCE should be one of the following forms (and may include an
-optional pair of <> delimiters:
+element.  REFERENCE must be one of the following forms (and may include an
+optional pair of <> delimiters) or an error is triggered:
   (pathname, cell-ref)
   pathname, cell-ref
   cell-ref
@@ -274,7 +295,7 @@ See documentation for `kcell:ref-to-id' for valid cell-ref 
formats."
      reference)
     ;; pathname cell-ref
     (list (match-string 1 reference) (match-string 2 reference)))
-   ((string-match (format "\\`\\s-*<?\\s-*\\(%s\\)\\s-*>?\\s-*\\'"
+   ((string-match (format "\\`\\s-*<?@?\\s-*\\(%s\\)\\s-*>?\\s-*\\'"
                          klink:cell-ref-regexp)
                  reference)
     ;; cell-ref
@@ -308,6 +329,21 @@ Assume point is in klink referent buffer, where the klink 
points."
          (if (and new-label (not (equal label new-label)))
              (klink:replace-label klink link-buf start new-label)))))
 
+(defun klink:yank-handler (klink)
+  (if (string-match "<\\([^,]+\\), \\(.+\\)" klink)
+      (let* ((file (match-string 1 klink))
+            (rest (match-string 2 klink))
+            (dir (file-name-directory file)))
+       (cond ((equal file buffer-file-name)
+              ;; Remove the klink filename since yanking into the
+              ;; same file
+              (insert (format "<@ %s" rest)))
+             ((and buffer-file-name (equal dir (file-name-directory 
buffer-file-name)))
+              ;; Use filename without dir since yanking into same directory
+              (insert (format "<%s, %s" (file-name-nondirectory file) rest)))
+             (t (insert klink))))
+    (insert klink)))
+                                
 ;;; ************************************************************************
 ;;; Private variables
 ;;; ************************************************************************
diff --git a/kotl/kotl-mode.el b/kotl/kotl-mode.el
index 33b8aa04ad..ed6514b923 100644
--- a/kotl/kotl-mode.el
+++ b/kotl/kotl-mode.el
@@ -3,7 +3,7 @@
 ;; Author:       Bob Weiner
 ;;
 ;; Orig-Date:    6/30/93
-;; Last-Mod:      3-Apr-22 at 23:08:47 by Bob Weiner
+;; Last-Mod:     12-Apr-22 at 01:39:17 by Bob Weiner
 ;;
 ;; Copyright (C) 1993-2021  Free Software Foundation, Inc.
 ;; See the "../HY-COPY" file for license information.
@@ -325,24 +325,42 @@ See `center-line' for more info."
     ;; Move to editable point if need be.
     (kotl-mode:to-valid-position)))
 
-(defun kotl-mode:copy-absolute-klink-to-kill-ring (&optional pos)
+(defun kotl-mode:copy-kcell-reference-to-register (klink register)
+  "Copy a KLINK at point or if in a kcell, a klink to that kcell, to a 
REGISTER named by a single character."
+  (interactive
+   (let ((klink (klink:absolute (klink:at-p))))
+     (list
+      (cond (klink)
+           ((derived-mode-p 'kotl-mode)
+            (setq klink (kcell-view:absolute-reference))))
+      (when klink
+       (register-read-with-preview (format "Copy %s to register: " klink))))))
+  (if (and (stringp klink) register)
+      (set-register register klink)
+    (user-error "(kotl-mode:copy-kcell-reference-to-register): Point is not 
within a Koutliner klink or kcell")))
+
+(defun kotl-mode:copy-absolute-kcell-link-to-kill-ring (&optional pos)
   "Add an absolute kcell reference (from optional POS or point) for use 
outside the outline as a new kill ring entry."
   (interactive "d")
   (kill-new (kcell-view:absolute-reference pos)))
 
-(defun kotl-mode:copy-relative-klink-to-kill-ring (&optional pos)
+(defun kotl-mode:copy-relative-kcell-link-to-kill-ring (&optional pos)
   "Add a relative kcell reference (from optional POS or point) as a new kill 
ring entry."
   (interactive "d")
   (kill-new (kcell-view:reference pos)))
 
-(defun kotl-mode:copy-absolute-klink-to-register (register pos)
+(defun kotl-mode:copy-absolute-kcell-link-to-register (register pos)
   "Copy into REGISTER an absolute kcell reference (from optional POS or 
point)."
-  (interactive "cCopy to register: \nd")
+  (interactive
+   (list (register-read-with-preview "Copy absolute link to current cell to 
register: ")
+        (point)))
   (set-register register (kcell-view:absolute-reference pos)))
 
-(defun kotl-mode:copy-relative-klink-to-register (register pos)
+(defun kotl-mode:copy-relative-kcell-link-to-register (register pos)
   "Copy into REGISTER a relative kcell reference (from optional POS or point)."
-  (interactive "cCopy to register: \nd")
+  (interactive
+   (list (register-read-with-preview "Copy relative link to current cell to 
register: ")
+        (point)))
   (set-register register (kcell-view:reference pos)))
 
 (defun kotl-mode:copy-region-as-kill (start end)
@@ -670,45 +688,74 @@ With optional COPY-P equal to 't, copy region to kill 
ring but does not
 kill it.  With COPY-P any other non-nil value, return region as a
 string without affecting kill ring.
 
+If called interactively and there is no active region, copy any selectable
+thing at point; see `hypb:selectable-thing'.
+
 If the buffer is read-only and COPY-P is nil, the region will not be deleted
-but it will be copied to the kill ring and then an error will be signaled."
+but it will be copied to the kill ring and then an error will be signaled.
+
+If a completion is active, this aborts the completion only."
   (interactive "*r")
-  (let ((read-only (and (not copy-p) buffer-read-only)))
-    (if read-only (setq copy-p t))
-    (if (and (number-or-marker-p start)
-            (number-or-marker-p end)
-            (eq (kcell-view:cell start)
-                (kcell-view:cell end)))
-       (save-excursion
-         (goto-char start)
-         (let ((indent (kcell-view:indent))
-               killed subst-str)
-           ;; Convert region to string
-           ;; Convert all occurrences of newline + indent
-           ;; to just newline, eliminating indent.
-           ;; Then save to kill ring.
-           (setq subst-str (concat "\\([\n\r]\\)" (make-string indent ?\ ))
-                 killed
-                 (hypb:replace-match-string
-                  subst-str (buffer-substring start end) "\\1"))
-           (unless copy-p
-             ;; If last char of region is a newline, then delete indent in
-             ;; following line.
-             (delete-region
-              start (+ end (if (memq (char-after (1- (max start end)))
-                                     '(?\n ?\r))
-                               indent
-                             0))))
-           (if (and copy-p (not (eq copy-p t)))
-               ;; Return killed region as a string.
-               killed
-             (if (eq last-command 'kill-region)
-                 (kill-append killed (< end start))
-               (kill-new killed))
-             (setq this-command 'kill-region)
-             (when read-only (barf-if-buffer-read-only)))))
-      (error
-       "(kotl-mode:kill-region): Bad region or not within a single Koutline 
cell"))))
+  (let ((read-only (and (not copy-p) buffer-read-only))
+       thing)
+    (when read-only
+      (setq copy-p t))
+    (prog1 (cond
+           ((eq last-command 'complete)
+            (delete-region (point) cmpl-last-insert-location)
+            (insert cmpl-original-string)
+            (setq completion-to-accept nil))
+           ;; If called interactively and no region is active, copy thing at 
point
+           ((and (memq this-command '(kotl-mode:kill-region 
kotl-mode:copy-region-as-kill))
+                 (not (use-region-p))
+                 (setq thing (hypb:selectable-thing)))
+            (if (and copy-p (not (eq copy-p t)))
+                ;; Return thing as a string
+                thing
+              (if (eq last-command 'kill-region)
+                  (kill-append thing (< end start))
+                (kill-new thing))
+              (setq deactivate-mark t)))
+           ;; If no thing to process, copy region whether active or not
+           ((and (number-or-marker-p start)
+                 (number-or-marker-p end)
+                 (eq (kcell-view:cell start)
+                     (kcell-view:cell end)))
+            (save-excursion
+              (goto-char start)
+              (let ((indent (kcell-view:indent))
+                    killed subst-str)
+                ;; Convert region to string
+                ;; Convert all occurrences of newline + indent
+                ;; to just newline, eliminating indent.
+                ;; Then save to kill ring.
+                (setq subst-str (concat "\\([\n\r]\\)" (make-string indent ?\ 
))
+                      killed
+                      (hypb:replace-match-string
+                       subst-str (buffer-substring start end) "\\1"))
+                (unless copy-p
+                  ;; If last char of region is a newline, then delete indent in
+                  ;; following line.
+                  (delete-region
+                   start (+ end (if (memq (char-after (1- (max start end)))
+                                          '(?\n ?\r))
+                                    indent
+                                  0))))
+                (if (and copy-p (not (eq copy-p t)))
+                    ;; Return killed region as a string.
+                    killed
+                  (if (eq last-command 'kill-region)
+                      (kill-append killed (< end start))
+                    (kill-new killed))
+                  (setq this-command 'kill-region)
+                  (setq deactivate-mark t)
+                  (when read-only (barf-if-buffer-read-only))
+                  nil))))
+           (t (error "(kotl-mode:kill-region): Bad region or not within a 
single Koutline cell")))
+      (when (and copy-p (memq this-command '(kill-region kotl-mode:kill-region 
kotl-mode:copy-region-as-kill)))
+       (if thing
+           (message "Saved selectable thing: %s" thing)
+         (indicate-copied-region))))))
 
 ;; Bound to {C-w} when completion.el library is loaded.
 (defalias 'kotl-mode:completion-kill-region 'kotl-mode:kill-region)
diff --git a/kotl/kview.el b/kotl/kview.el
index 8b665acea5..df3f5c4b7f 100644
--- a/kotl/kview.el
+++ b/kotl/kview.el
@@ -3,7 +3,7 @@
 ;; Author:       Bob Weiner
 ;;
 ;; Orig-Date:    6/30/93
-;; Last-Mod:      3-Apr-22 at 19:00:16 by Bob Weiner
+;; Last-Mod:     10-Apr-22 at 22:31:58 by Bob Weiner
 ;;
 ;; Copyright (C) 1993-2021  Free Software Foundation, Inc.
 ;; See the "../HY-COPY" file for license information.
@@ -17,7 +17,7 @@
 ;;; Other required Lisp Libraries
 ;;; ************************************************************************
 
-(eval-and-compile (mapc #'require '(klabel kfill hypb)))
+(eval-and-compile (mapc #'require '(klabel kfill klink hypb)))
 ;; Quiet byte compiler warnings for this free variable.
 (eval-when-compile
   (defvar label-sep-len nil))
@@ -481,23 +481,27 @@ If between kcells, move to the previous one.  The current 
cell may be hidden."
             (error "(kcell-view:to-label-end): Can't find end of current 
cell's label"))))))
 
 (defun kcell-view:absolute-reference (&optional pos)
-  "Return a reference to the kcell at optional POS or point for use in a link.
+  "Return a klink to the kcell at optional POS or point; return nil if not in 
a kcell.
 The reference is a string of the form, \"<kcell-file, cell-ref>\"
 where cell-ref is as described in the documentation for
 `kcell:ref-to-id'.  Kcell-file is an absolute path to the current
 Koutline file."
-  (format "<%s, %s=%s>" buffer-file-name
-         (kcell-view:label pos) (kcell-view:idstamp pos)))
+  (when (derived-mode-p 'kotl-mode)
+    (klink:set-yank-handler
+     (format "<%s, %s=%s>" buffer-file-name
+            (kcell-view:label pos) (kcell-view:idstamp pos)))))
 
 (defun kcell-view:reference (&optional pos relative-dir)
-  "Return a reference to the kcell at optional POS or point for use in a link.
+  "Return a klink to the kcell at optional POS or point; return nil if not in 
a kcell.
 The reference is a string of the form, \"<kcell-file, cell-ref>\"
 where cell-ref is as described in the documentation for
 `kcell:ref-to-id'.  Kcell-file is made relative to optional
 RELATIVE-DIR (or `default-directory' if RELATIVE-DIR is not given
 or is nil), before it is returned."
-  (format "<%s, %s=%s>" (hpath:relative-to buffer-file-name relative-dir)
-         (kcell-view:label pos) (kcell-view:idstamp pos)))
+  (when (derived-mode-p 'kotl-mode)
+    (klink:set-yank-handler
+     (format "<%s, %s=%s>" (hpath:relative-to buffer-file-name relative-dir)
+            (kcell-view:label pos) (kcell-view:idstamp pos)))))
 
 (defun kcell-view:remove-attr (attribute &optional pos)
   "Remove ATTRIBUTE, if any, for current cell or cell at optional POS.  Return 
the modified cell."

Reply via email to