home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.004 / xemacs-1 / xemacs-19.13 / lisp / hyperbole / kotl / kotl-mode.el < prev    next >
Encoding:
Text File  |  1995-08-26  |  98.8 KB  |  2,735 lines

  1. ;;!emacs
  2. ;;
  3. ;; FILE:         kotl-mode.el
  4. ;; SUMMARY:      Major mode for editing koutlines and associated commands.
  5. ;; USAGE:        GNU Emacs Lisp Library
  6. ;; KEYWORDS:     data, hypermedia, outlines, wp
  7. ;;
  8. ;; AUTHOR:       Bob Weiner & Kellie Clark
  9. ;;
  10. ;; ORIG-DATE:    6/30/93
  11. ;; LAST-MOD:     25-Aug-95 at 01:36:17 by Bob Weiner
  12. ;;
  13. ;; This file is part of Hyperbole.
  14. ;; Available for use and distribution under the same terms as GNU Emacs.
  15. ;;
  16. ;; Copyright (C) 1993-1995, Free Software Foundation, Inc.
  17. ;; Developed with support from Motorola Inc.
  18. ;;
  19. ;; DESCRIPTION:  
  20. ;; DESCRIP-END.
  21.  
  22. ;;; ************************************************************************
  23. ;;; Other required Lisp Libraries
  24. ;;; ************************************************************************
  25.  
  26. (mapcar 'require '(hsite hmail kview kotl))
  27.  
  28. ;;; ************************************************************************
  29. ;;; Public variables
  30. ;;; ************************************************************************
  31.  
  32. (defvar kotl-mode:refill-flag nil
  33.   "*Automatically refill cells during move, copy, promotion and demotion operations when non-nil.
  34. Default value is nil.  Cells with a `no-fill' attribute are never refilled
  35. during such operations, regardless of the value of this flag.")
  36.  
  37. ;;; ************************************************************************
  38. ;;; Public functions
  39. ;;; ************************************************************************
  40.  
  41. (defun kotl-mode ()
  42.   "The major mode used to edit and view koutlines.
  43. It provides the following keys:
  44. \\{kotl-mode-map}"
  45.   (interactive)
  46.   (use-local-map kotl-mode-map)
  47.   (setq major-mode 'kotl-mode
  48.     mode-name "Kotl"
  49.     indent-tabs-mode nil)
  50.   (set-syntax-table text-mode-syntax-table)
  51.   (make-local-variable 'selective-display-ellipses)
  52.   (make-local-variable 'minor-mode-alist)
  53.   ;; Ensure that outline structure data is saved when save-buffer is called
  54.   ;; from save-some-buffers, {C-x s}.
  55.   (add-hook 'local-write-file-hooks 'kotl-mode:update-buffer)
  56.   (setq local-abbrev-table text-mode-abbrev-table
  57.     ;; Remove outline indication due to selective-display.
  58.     minor-mode-alist (set:remove '(selective-display " Outline")
  59.                      minor-mode-alist)
  60.     minor-mode-alist (set:remove '(selective-display " Otl")
  61.                      minor-mode-alist)
  62.     ;; Remove indication that buffer is ;; narrowed.
  63.     mode-line-format (set:remove "%n" mode-line-format)
  64.     selective-display t
  65.     selective-display-ellipses t
  66.     paragraph-start "^[ \t]*$\\|^\^L"
  67.     paragraph-separate "^[ \t]*$\\|^\^L")
  68.   ;; If buffer has not yet been formatted for editing, format it.
  69.   (widen) ;; Ensures that narrowed but unformatted kotl file is recognized.
  70.   (cond
  71.    ;; Unformatted kotl file
  72.    ((kfile:is-p)
  73.     (kfile:read
  74.      (current-buffer)
  75.      (and buffer-file-name (file-exists-p buffer-file-name))))
  76.    ;; Formatted kotl file
  77.    ((kview:is-p kview)
  78.     nil)
  79.    ;; New kotl file
  80.    (t (kfile:create (current-buffer))))
  81.   (run-hooks 'kotl-mode-hook))
  82.  
  83. (defun kotl-mode:find-file-hook ()
  84.   (if (kview:is-p kview)
  85.       (kotl-mode:to-valid-position))
  86.   nil)
  87.  
  88. ;;; Ensure that point ends up at a valid position whenever a find-file
  89. ;;; is done on a kotl-file.
  90. (add-hook 'find-file-hooks 'kotl-mode:find-file-hook)
  91.  
  92. ;;; Ensure that outline structure data is hidden from view after a file save.
  93. (add-hook 'after-save-hook 'kfile:narrow-to-kcells)
  94.  
  95. ;;; Restore blank line separator settings after saving an outline.
  96. (add-hook 'after-save-hook 'kfile:shorten-after-saving)
  97.  
  98. ;;; ------------------------------------------------------------------------
  99. ;;; Editing within a single kotl
  100. ;;; ------------------------------------------------------------------------
  101.  
  102. (fset 'kotl-mode:backward-delete-char-untabify
  103.       'kotl-mode:delete-backward-char)
  104. (fset 'kotl-mode:backward-delete-char
  105.       'kotl-mode:delete-backward-char)
  106.  
  107. (defun kotl-mode:backward-kill-word (arg)
  108.   "Kill up to prefix ARG words preceding point within a single cell."
  109.   (interactive "*p")
  110.   (or arg (setq arg 1))
  111.   (cond ((< arg 0)
  112.      (if (kotl-mode:eocp)
  113.          (error "(kotl-mode:backward-kill-word): End of cell")))
  114.     ((> arg 0)
  115.      (if (kotl-mode:bocp)
  116.          (error "(kotl-mode:backward-kill-word): Beginning of cell"))))
  117.   (if (= arg 0)
  118.       nil
  119.     (save-restriction
  120.       (narrow-to-region (kcell-view:start) (kcell-view:end-contents))
  121.       (backward-kill-word arg))))
  122.  
  123. (defun kotl-mode:center-line ()
  124.   "Center the line point is on, within the width specified by `fill-column'.
  125. This means adjusting the indentation so that it equals the distance between
  126. the end of the text and `fill-column'."
  127.   (interactive "*")
  128.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  129.   (let ((indent (kcell-view:indent))
  130.     (opoint (point-marker))
  131.     (bocp)
  132.     start)
  133.     (setq start (kotl-mode:beginning-of-line))
  134.     (if (setq bocp (kotl-mode:bocp))
  135.     (progn
  136.       ;; Add a temporary fill-prefix since this is the 1st line of the cell
  137.       ;; where label could interfere with centering.
  138.       (insert "\n\n") (insert-char ?\  indent)))
  139.     (center-line)
  140.     (if bocp
  141.     ;; Delete temporary fill prefix.
  142.     (delete-region start (+ start indent 2)))
  143.     (goto-char opoint)
  144.     ;; Move to editable point if need be.
  145.     (kotl-mode:to-valid-position)))
  146.  
  147. (defun kotl-mode:center-paragraph ()
  148.   "Center each nonblank line in the paragraph at or after point.
  149. See `center-line' for more info."
  150.   (interactive "*")
  151.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  152.   (let ((indent (kcell-view:indent))
  153.     (opoint (point-marker))
  154.     start)
  155.     (backward-paragraph)
  156.     (kotl-mode:to-valid-position)
  157.     (setq start (point))
  158.     ;; Add a temporary fill-prefix for 1st line in cell which contains a
  159.     ;; label, so is centered properly.
  160.     (insert "\n\n") (insert-char ?\  indent)
  161.     (kcell-view:operate 'center-paragraph)
  162.     ;; Delete temporary fill prefix.
  163.     (delete-region start (+ start indent 2))
  164.     ;; Return to original point.
  165.     (goto-char (min opoint (kcell-view:end-contents)))
  166.     ;; Move to editable point if need be.
  167.     (kotl-mode:to-valid-position)))
  168.  
  169. (defun kotl-mode:copy-region-as-kill (start end)
  170.   "Copy region between START and END within a single kcell to kill ring."
  171.   (interactive "*r")
  172.   (kotl-mode:kill-region start end t))
  173.  
  174. (defun kotl-mode:copy-to-register (register start end &optional delete-flag)
  175.   "Copy into REGISTER the region START to END.
  176. With optional prefix arg DELETE-FLAG, delete region."
  177.   (interactive "cCopy to register: \nr\nP")
  178.   (let ((indent (kcell-view:indent)))
  179.     (set-register register
  180.           (hypb:replace-match-string
  181.            (concat "^" (make-string indent ?\ ))
  182.            (buffer-substring start end)
  183.            "")))
  184.   (if delete-flag (delete-region start end)))
  185.  
  186. (defun kotl-mode:delete-backward-char (arg &optional kill-flag)
  187.   "Delete up to the preceding prefix ARG characters.
  188. Return number of characters deleted.
  189. Optional KILL-FLAG non-nil means save in kill ring instead of deleting.
  190. Does not delete across cell boundaries."
  191.   (interactive "*P")
  192.   (if (interactive-p)
  193.       (if current-prefix-arg
  194.       (setq kill-flag t
  195.         arg (prefix-numeric-value current-prefix-arg))))
  196.   (or arg (setq arg 1))
  197.   (kotl-mode:delete-char (- arg) kill-flag))
  198.  
  199. (defun kotl-mode:delete-blank-lines ()
  200.   "On blank line within a cell, delete all surrounding blank lines, leaving just one.
  201. On isolated blank line, delete that one.
  202. On nonblank line, delete all blank lines that follow it.
  203.  
  204. If nothing but whitespace follows point until the end of a cell, delete all
  205. whitespace at the end of the cell."
  206.   (interactive "*")
  207.   ;; If nothing but whitespace from point until the end of cell, remove all
  208.   ;; cell trailing whitespace.
  209.   (let ((end (kcell-view:end-contents))
  210.     start)
  211.     (if (save-excursion
  212.       (skip-chars-forward " \t\n\^M" end)
  213.       (not (kotl-mode:eocp)))
  214.     (kcell-view:operate (function (lambda () (delete-blank-lines))))
  215.       (setq start (kcell-view:start))
  216.       (goto-char end)
  217.       ;; delete any preceding whitespace
  218.       (skip-chars-backward " \t\n\^M" start)
  219.       (delete-region (max start (point)) end)))
  220.   (kotl-mode:to-valid-position))
  221.  
  222. (defun kotl-mode:delete-char (arg &optional kill-flag)
  223.   "Delete up to prefix ARG characters following point.
  224. Return number of characters deleted.
  225. Optional KILL-FLAG non-nil means save in kill ring instead of deleting.
  226. Does not delete across cell boundaries."
  227.   (interactive "*P")
  228.   (if (interactive-p)
  229.       (if current-prefix-arg
  230.       (setq kill-flag t
  231.         arg (prefix-numeric-value current-prefix-arg))))
  232.   (or arg (setq arg 1))
  233.   (let ((del-count 0)
  234.     (indent (kcell-view:indent))
  235.     count start end)
  236.     (cond ((> arg 0)
  237.        (if (kotl-mode:eocp)
  238.            (error "(kotl-mode:delete-char): End of cell")
  239.          (setq end (kcell-view:end)
  240.            arg (min arg (- end (point))))
  241.          (while (> arg 0)
  242.            (if (kotl-mode:eolp)
  243.            (if (/= ?\ (char-syntax (following-char)))
  244.                (setq arg 0
  245.                  del-count (1- del-count))
  246.              (delete-char 1 kill-flag)
  247.              ;; There may be non-whitespace characters in the
  248.              ;; indent area.  Don't delete them.
  249.              (setq count indent)
  250.              (while (and (> count 0)
  251.                  (= ?\ (char-syntax (following-char))))
  252.                (delete-char 1)
  253.                (setq count (1- count))))
  254.          (delete-char 1 kill-flag))
  255.            (setq arg (1- arg)
  256.              del-count (1+ del-count)))
  257.          ))
  258.       ((< arg 0)
  259.        (if (kotl-mode:bocp)
  260.            (error "(kotl-mode:delete-char): Beginning of cell")
  261.          (setq start (kcell-view:start)
  262.            arg (max arg (- start (point))))
  263.          (while (< arg 0)
  264.            (if (kotl-mode:bolp)
  265.            (if (/= ?\ (char-syntax (preceding-char)))
  266.                (setq arg 0
  267.                  del-count (1- del-count))
  268.              ;; There may be non-whitespace characters in the
  269.              ;; indent area.  Don't delete them.
  270.              (setq count indent)
  271.              (while (and (> count 0)
  272.                  (= ?\ (char-syntax (preceding-char))))
  273.                (delete-char -1)
  274.                (setq count (1- count)))
  275.              (if (zerop count)
  276.              (delete-char -1 kill-flag)))
  277.          (delete-char -1 kill-flag))
  278.            (setq arg (1+ arg)
  279.              del-count (1+ del-count))))))
  280.     del-count))
  281.  
  282. (defun kotl-mode:delete-horizontal-space ()
  283.   "Delete all spaces and tabs around point."
  284.   (interactive "*")
  285.   (save-restriction
  286.     (narrow-to-region
  287.      (save-excursion
  288.        (kotl-mode:start-of-line))
  289.      (save-excursion
  290.        (kotl-mode:finish-of-line)))
  291.     (delete-horizontal-space)))
  292.  
  293. (defun kotl-mode:delete-indentation (&optional arg)
  294.   "Join this line to previous and fix up whitespace at join.
  295. If there is a fill prefix, delete it from the beginning of this line.
  296. With argument, join this line to following line."
  297.   (interactive "*P")
  298.   (kcell-view:operate
  299.    (function
  300.     (lambda ()
  301.       (let ((opoint (point)))
  302.     (beginning-of-line)
  303.     (if arg (forward-line 1))
  304.     (if (eq (preceding-char) ?\n)
  305.         (progn
  306.           (delete-region (point) (1- (point)))
  307.           ;; If the second line started with the fill prefix,
  308.           ;; delete the prefix.
  309.           (if (and fill-prefix
  310.                (<= (+ (point) (length fill-prefix)) (point-max))
  311.                (string= fill-prefix
  312.                 (buffer-substring
  313.                  (point) (+ (point) (length fill-prefix)))))
  314.           (delete-region (point) (+ (point) (length fill-prefix))))
  315.           (fixup-whitespace))
  316.       (goto-char opoint)))))))
  317.  
  318. (defun kotl-mode:fill-cell (&optional justify ignore-collapsed-p)
  319.   "Fill current cell within current view if it does not have a non-nil `no-fill' attribute.
  320. With optional JUSTIFY, justify cell as well.
  321. IGNORE-COLLAPSED-P is used when caller has already expanded cell, indicating
  322. it is not collapsed."
  323.   (interactive "*P")
  324.   (cond ((kcell-view:get-attr 'no-fill)
  325.      (if (interactive-p)
  326.          (progn (beep)
  327.             (message "Current cell has a `do not fill' attribute.")
  328.             nil)))
  329.     ((string-match "\\`[ \t\n\^M]*\\'" (kcell-view:contents))
  330.       ;; Cell content is all whitespace.
  331.      nil)
  332.     (t (let* ((indent (kcell-view:indent))
  333.           (opoint (set-marker (make-marker) (point)))
  334.           (start  (kcell-view:start))
  335.           (collapsed-p)
  336.           (end (kcell-view:end-contents))
  337.           temp-prefix prev-point)
  338.          (goto-char start)
  339.          ;; Expand cell if collapsed so that filling is done properly.
  340.          (if (and (not ignore-collapsed-p)
  341.               (setq collapsed-p (search-forward "\^M" end t)))
  342.          (subst-char-in-region start end ?\^M ?\n t))
  343.          (goto-char start)
  344.          ;; Add a temporary fill-prefix for 1st labeled line, so is filled properly.
  345.          (insert (setq temp-prefix (concat "\n\n" (make-string indent ?\ ))))
  346.          (while (progn (fill-paragraph justify)
  347.                (setq prev-point (point))
  348.                (forward-paragraph)
  349.                (and (/= (point) prev-point)
  350.                 (< (point) (kcell-view:end-contents))
  351.                 (if (memq (preceding-char) '(?\n ?\^M))
  352.                     (not (looking-at "[\n\^M]"))
  353.                   t))))
  354.          ;; Delete temporary fill prefix.
  355.          (goto-char start)
  356.          (if (looking-at temp-prefix)
  357.          (replace-match "" t t))
  358.          ;; Return to original point.
  359.          (setq end (kcell-view:end-contents))
  360.          (goto-char (min opoint end))
  361.          ;;
  362.          ;; If cell was collapsed before filling, collapse it again.
  363.          (if collapsed-p
  364.          (subst-char-in-region start end ?\n ?\^M t))
  365.          ;;
  366.          ;; Remove markers
  367.          (set-marker opoint nil))
  368.        ;; Move to editable point if need be.
  369.        (kotl-mode:to-valid-position))))
  370.  
  371. (defun kotl-mode:fill-paragraph (&optional justify)
  372.   "Fill the current paragraph within the cell.
  373. With optional JUSTIFY, justify the paragraph as well.
  374. Ignore any non-nil no-fill attribute attached to the cell."
  375.   (interactive "*P")
  376.   (let ((indent (kcell-view:indent))
  377.     (opoint (point-marker))
  378.     start)
  379.     (backward-paragraph)
  380.     (kotl-mode:to-valid-position)
  381.     (setq start (point))
  382.     ;; Add a temporary fill-prefix for 1st line in cell which contains a
  383.     ;; label, so is filled properly.
  384.     (insert "\n\n") (insert-char ?\  indent)
  385.     (fill-paragraph justify)
  386.     ;; Delete temporary fill prefix.
  387.     (delete-region start (+ start indent 2))
  388.     ;; Return to original point.
  389.     (goto-char (min opoint (kcell-view:end-contents)))
  390.     ;; Move to editable point if need be.
  391.     (kotl-mode:to-valid-position)))
  392.  
  393. ;; XEmacs binds this to {M-q}.
  394. (fset 'kotl-mode:fill-paragraph-or-region 'kotl-mode:fill-paragraph)
  395.  
  396. (defun kotl-mode:fill-tree (&optional top-p)
  397.   "Refill each cell within the tree whose root is at point.
  398. Skip cells with a non-nil no-fill attribute.
  399. With optional prefix argument TOP-P non-nil, refill all cells in the outline."
  400.   (interactive "P")
  401.   ;; Store list of which cells are presently collapsed.
  402.   (let ((collapsed-cells
  403.      (kview:map-tree
  404.       (function (lambda (view)
  405.               ;; Use free variable label-sep-len bound in
  406.               ;; kview:map-tree for speed.
  407.               (kcell-view:collapsed-p nil label-sep-len)))
  408.       kview top-p)))
  409.     ;;
  410.     ;; Expand all cells in tree.
  411.     (if top-p
  412.     (subst-char-in-region (point-min) (point-max) ?\^M ?\n t)
  413.       (save-excursion
  414.     (let ((start (kcell-view:start)))
  415.       (kotl-mode:end-of-tree)
  416.       (subst-char-in-region
  417.        (point) (kcell-view:end-contents) ?\^M ?\n t))))
  418.     ;;
  419.     ;; Refill cells without no-fill property.
  420.     (kview:map-tree (function (lambda (view) (kotl-mode:fill-cell)))
  421.             kview top-p)
  422.     ;;
  423.     ;; Collapse temporarily expanded cells.
  424.     (if (delq nil collapsed-cells)
  425.     (kview:map-tree
  426.      (function
  427.       (lambda (view)
  428.         (if (car collapsed-cells)
  429.         ;; Use free variable label-sep-len bound in
  430.         ;; kview:map-tree for speed.
  431.         (kcell-view:collapse nil label-sep-len))
  432.         (setq collapsed-cells (cdr collapsed-cells))))
  433.      kview top-p))))
  434.  
  435. (defun kotl-mode:insert-buffer (buffer)
  436.   "Insert after point the contents of BUFFER.
  437. Puts mark after the inserted text.
  438. BUFFER may be a buffer or a buffer name."
  439.   (interactive "*bInsert buffer: ")
  440.   (insert-buffer buffer)
  441.   (kotl-mode:add-indent-to-region))
  442.  
  443. (defun kotl-mode:insert-file (filename)
  444.   "Insert contents of file FILENAME into current cell after point.
  445. Set mark after the inserted text."
  446.   (interactive "*fInsert file: ")
  447.   (let ((tem (insert-file-contents filename)))
  448.     (push-mark (+ (point) (car (cdr tem)))))
  449.   (kotl-mode:add-indent-to-region))
  450.  
  451. (defun kotl-mode:insert-register (register &optional arg)
  452.   "Insert contents of register REGISTER at point in current cell.
  453. REGISTER is a character naming the register to insert.
  454. Normally puts point before and mark after the inserted text.
  455. If optional second arg is non-nil, puts mark before and point after.
  456. Interactively, second arg is non-nil if prefix arg is supplied."
  457.   (interactive "*cInsert register: \nP")
  458.   (push-mark)
  459.   (let ((val (get-register register)))
  460.     (cond ((consp val)
  461.            (insert-rectangle val))
  462.           ((stringp val)
  463.        (insert val)
  464.        (kotl-mode:add-indent-to-region))
  465.           ((integerp val)
  466.            (princ val (current-buffer)))
  467.           ((and (markerp val) (marker-position val))
  468.            (princ (marker-position val) (current-buffer)))
  469.           (t
  470.            (error "Register '%c' does not contain text" register))))
  471.   (if (not arg) (exchange-point-and-mark)))
  472.  
  473. (defun kotl-mode:just-one-space ()
  474.   "Delete all spaces and tabs around point and leave one space."
  475.   (interactive "*")
  476.   (save-restriction
  477.     (narrow-to-region
  478.      (save-excursion
  479.        (kotl-mode:start-of-line))
  480.      (save-excursion
  481.        (kotl-mode:finish-of-line)))
  482.     (just-one-space)))
  483.  
  484. (defun kotl-mode:kill-line (&optional arg)
  485.   "Kill ARG lines from point."
  486.   (interactive "*P")
  487.   (if (and (null arg)
  488.        (kotl-mode:bolp)
  489.        (boundp 'kill-whole-line) kill-whole-line)
  490.       (let ((indent (kcell-view:indent)))
  491.     ;; Kill whole line including newline, if any.
  492.     (kcell-view:operate
  493.      (function
  494.       (lambda ()
  495.         (let ((no-newline))
  496.           (kill-region (point)
  497.                (progn (setq no-newline
  498.                     (not (search-forward "\n" nil 'stay)))
  499.                   (point)))
  500.           (or no-newline (delete-char indent)))))))
  501.     ;; Kill part of a line or multiple lines.
  502.     (let ((num-arg (prefix-numeric-value arg)))
  503.       (cond
  504.        ((and (null arg) (not (kotl-mode:eolp)))
  505.     ;; kill to eol but not newline
  506.     (kill-region (point) (setq arg (kotl-mode:finish-of-line))))
  507.        ((= num-arg 0)
  508.     ;; kill to bol
  509.     (kill-region (point) (setq arg (kotl-mode:start-of-line))))
  510.        (t;; (/= num-arg 0)
  511.     ;; Find start and end of region to kill
  512.     (let ((start (point))
  513.           (end (min (kcell-view:end-contents)
  514.             (save-excursion (forward-line num-arg) (point)))))
  515.       (kotl-mode:kill-region start end))))))
  516.   (setq last-command 'kill-region))
  517.  
  518. (defun kotl-mode:kill-region (start end &optional copy-p)
  519.   "Kill region between START and END within a single kcell.
  520. With optional COPY-P equal to 't, copy region to kill ring but does not
  521. kill it.  With COPY-P any other non-nil value, return region as a
  522. string without affecting kill ring.
  523.  
  524. If the buffer is read-only and COPY-P is nil, the region will not be deleted
  525. but it will be copied to the kill ring and then an error will be signaled."
  526.   (interactive "*r")
  527.   (let ((read-only (and (not copy-p) buffer-read-only)))
  528.     (if read-only (setq copy-p t))
  529.     (if (and (number-or-marker-p start)
  530.          (number-or-marker-p end)
  531.          (eq (kcell-view:cell start)
  532.          (kcell-view:cell end)))
  533.     (save-excursion
  534.       (goto-char start)
  535.       (let ((indent (kcell-view:indent))
  536.         killed subst-str)
  537.         ;; Convert region to string
  538.         ;; Convert all occurrences of newline + indent
  539.         ;; to just newline, eliminating indent.
  540.         ;; Then save to kill ring.
  541.         (setq subst-str (concat "\\([\n\^M]\\)" (make-string indent ?\ ))
  542.           killed
  543.           (hypb:replace-match-string
  544.            subst-str (buffer-substring start end) "\\1"))
  545.         (if copy-p
  546.         nil
  547.           ;; If last char of region is a newline, then delete indent in
  548.           ;; following line.
  549.           (delete-region
  550.            start (+ end (if (memq (char-after (1- (max start end)))
  551.                       '(?\n ?\^M))
  552.                 indent
  553.                   0))))
  554.         (if (and copy-p (not (eq copy-p t)))
  555.         ;; Return killed region as a string.
  556.         killed
  557.           (if (eq last-command 'kill-region)
  558.           (kill-append killed (< end start))
  559.         (kill-new killed))
  560.           (setq this-command 'kill-region)
  561.           (if read-only (barf-if-buffer-read-only))
  562.           )))
  563.       (error
  564.        "(kotl-mode:kill-region): Bad region or not within a single kcell."))))
  565.  
  566. (fset 'kotl-mode:kill-ring-save 'kotl-mode:copy-region-as-kill)
  567.  
  568. (defun kotl-mode:kill-sentence (&optional arg)
  569.   "Kill up to prefix ARG (or 1) sentences following point within a single cell."
  570.   (interactive "*p")
  571.   (or arg (setq arg 1))
  572.   (cond ((> arg 0)
  573.      (if (kotl-mode:eocp)
  574.          (error "(kotl-mode:kill-sentence): End of cell")))
  575.     ((< arg 0)
  576.      (if (kotl-mode:bocp)
  577.          (error "(kotl-mode:kill-sentence): Beginning of cell"))))
  578.   (if (= arg 0)
  579.       nil
  580.     (kotl-mode:kill-region (point)
  581.                (save-excursion
  582.                  (kotl-mode:forward-sentence arg)))))
  583.  
  584. (defun kotl-mode:kill-word (arg)
  585.   "Kill up to prefix ARG words following point within a single cell."
  586.   (interactive "*p")
  587.   (or arg (setq arg 1))
  588.   (cond ((> arg 0)
  589.      (if (kotl-mode:eocp)
  590.          (error "(kotl-mode:kill-word): End of cell")))
  591.     ((< arg 0)
  592.      (if (kotl-mode:bocp)
  593.          (error "(kotl-mode:kill-word): Beginning of cell"))))
  594.   (if (= arg 0)
  595.       nil
  596.     (save-restriction
  597.       (narrow-to-region (kcell-view:start) (kcell-view:end-contents))
  598.       (kill-word arg))))
  599.  
  600. (defun kotl-mode:newline (arg)
  601.   "Insert a newline.  With ARG, insert ARG newlines.
  602. In Auto Fill mode, if no numeric arg, break the preceding line if it is
  603. too long."
  604.   (interactive "*p")
  605.   (let ((indent (kcell-view:indent)))
  606.     (if (equal arg 1)
  607.     (progn
  608.       (save-excursion
  609.         (insert ?\n)
  610.         (insert-char ?\  indent))
  611.       (do-auto-fill)
  612.       (forward-line 1)
  613.       (kotl-mode:start-of-line)
  614.       )
  615.       (while (> arg 0)
  616.     (insert ?\n)
  617.     (insert-char ?\  indent)
  618.     (setq arg (1- arg))))))
  619.  
  620. (fset 'kotl-mode:newline-and-indent 'kotl-mode:newline)
  621.  
  622. (defun kotl-mode:open-line (arg)
  623.   "Insert a newline and leave point before it.
  624. With arg N, insert N newlines."
  625.   (interactive "*p")
  626.   (let* ((bolp (and (kotl-mode:bolp) (not (kotl-mode:bocp))))
  627.      (indent (kcell-view:indent)))
  628.     (while (> arg 0)
  629.       (save-excursion
  630.         (insert ?\n)
  631.     (if (and (not bolp) fill-prefix)
  632.         (insert fill-prefix)
  633.       (insert-char ?\  indent)))
  634.       (setq arg (1- arg)))
  635.     (if (and bolp fill-prefix)
  636.     (progn (delete-horizontal-space)
  637.            (insert fill-prefix)))
  638.     ))
  639.  
  640. (defun kotl-mode:set-fill-prefix (turn-off)
  641.   "Sets fill prefix to line up to point.
  642. With prefix arg TURN-OFF or at begin of line, turns fill prefix off."
  643.   (interactive "P")
  644.   (set-fill-prefix (or turn-off (kotl-mode:bolp))))
  645.  
  646. (defun kotl-mode:transpose-chars (arg)
  647.   "Interchange characters around point, moving forward one character.
  648. With prefix ARG, take character before point and drag it forward past ARG
  649. other characters (backward if ARG negative).
  650. If no prefix ARG and at end of line, the previous two characters are
  651. exchanged."
  652.   (interactive "*P")
  653.   (and (null arg) (kotl-mode:eolp) (kotl-mode:forward-char -1))
  654.   (transpose-subr 'kotl-mode:forward-char (prefix-numeric-value arg)))
  655.  
  656. (defun kotl-mode:transpose-lines (arg)
  657.   "Exchange current line and previous line, leaving point after both.
  658. If no previous line, exchange current with next line.
  659. With prefix ARG, take previous line and move it past ARG lines.
  660. With prefix ARG = 0, interchange the line that contains point with the line
  661. that contains mark."
  662.   (interactive "*p")
  663.   (cond
  664.    ((and (kotl-mode:first-line-p) (kotl-mode:last-line-p))
  665.     (error "(kotl-mode:transpose-lines): Only one line in outline"))
  666.    ;;
  667.    ;; Transpose current and previous lines or current and next lines, if no
  668.    ;; previous line.  Leave point after both exchanged lines.
  669.    ((= arg 1)
  670.     (let* ((point (point-marker))
  671.        (mark (set-marker (make-marker)
  672.                  (if (kotl-mode:first-line-p)
  673.                  (kotl-mode:next-line 1)
  674.                    (kotl-mode:previous-line 1)))))
  675.       (kotl-mode:transpose-lines-internal point mark)
  676.       (goto-char (max point mark))
  677.       (kotl-mode:next-line 1)
  678.       (set-marker mark nil)))
  679.    ;;
  680.    ;; Transpose point and mark lines, leaving point on the line of text that
  681.    ;; originally contained point.
  682.    ((= arg 0)
  683.     (kotl-mode:transpose-lines-internal (point-marker) (hypb:mark-marker t))
  684.     ;; This is like exchange-point-and-mark, but doesn't activate the
  685.     ;; mark.
  686.     (goto-char (prog1 (hypb:mark t)
  687.          (set-marker (hypb:mark-marker t) (point)))))
  688.    ;;
  689.    ;; Move previous line past ARG next lines and leave point after previous
  690.    ;; line text.
  691.    (t
  692.     (if (kotl-mode:first-line-p)
  693.     (error "(kotl-mode:transpose-lines): No previous line to transpose"))
  694.     (kotl-mode:previous-line 1)
  695.     (let* ((mark (set-marker (make-marker)
  696.                  (save-excursion (kotl-mode:next-line arg))))
  697.        (line-to-move (kotl-mode:delete-line)))
  698.       (condition-case ()
  699.       ;; Delete trailing newline if any, ignoring error.
  700.       (kotl-mode:delete-char 1)
  701.     (error nil))
  702.       (goto-char mark)
  703.       (set-marker mark nil)
  704.       (kotl-mode:finish-of-line)
  705.       (insert "\n")
  706.       (insert-char ?\  (kcell-view:indent))
  707.       (insert line-to-move)
  708.       (kotl-mode:start-of-line)))))
  709.  
  710. (defun kotl-mode:transpose-paragraphs (arg)
  711.   "Interchange this (or next) paragraph with previous one."
  712.   (interactive "*p")
  713.   (transpose-subr 'kotl-mode:forward-paragraph (prefix-numeric-value arg)))
  714.  
  715. (defun kotl-mode:transpose-sentences (arg)
  716.   "Interchange this (next) and previous sentence."
  717.   (interactive "*p")
  718.   (transpose-subr 'kotl-mode:forward-sentence (prefix-numeric-value arg)))
  719.  
  720. (defun kotl-mode:transpose-words (arg)
  721.   "Interchange words around point, leaving point after both words.
  722. With prefix ARG, take word before or around point and drag it forward past
  723. ARG other words (backward if ARG negative).  If ARG is zero, the words around
  724. or after point and around or after mark are interchanged."
  725.   (interactive "*p")
  726.   (transpose-subr 'kotl-mode:forward-word (prefix-numeric-value arg)))
  727.  
  728. (defun kotl-mode:zap-to-char (arg char)
  729.   "Kill up to and including prefix ARG'th occurrence of CHAR.
  730. Goes backward if ARG is negative; error if CHAR not found."
  731.   (interactive "*p\ncZap to char within current cell: ")
  732.   (kcell-view:operate 
  733.    (function (lambda () (zap-to-char arg char)))))
  734.  
  735. ;;; ------------------------------------------------------------------------
  736. ;;; Editing across kotls
  737. ;;; ------------------------------------------------------------------------
  738.  
  739. (defun kotl-mode:copy-after (from-cell-ref to-cell-ref child-p)
  740.   "Copy tree rooted at FROM-CELL-REF to follow tree rooted at TO-CELL-REF.
  741. If prefix arg CHILD-P is non-nil, make FROM-CELL-REF the first child of
  742. TO-CELL-REF, otherwise make it the sibling following TO-CELL-REF.
  743.  
  744. Leave point at the start of the root cell of the new tree."
  745.   (interactive
  746.    (let* ((label (kcell-view:label))
  747.       (hargs:defaults (list label label)))
  748.      (append
  749.       (hargs:iform-read
  750.        (list
  751.     'interactive
  752.     (format "*+KCopy tree: \n+KCopy tree <%%s> to follow as %s of cell: "
  753.         (if current-prefix-arg "child" "sibling"))))
  754.       (list current-prefix-arg))))
  755.   ;;
  756.   ;; Copy tree in current view and leave point at the start of the copy.
  757.   (goto-char (kotl-mode:move-after from-cell-ref to-cell-ref child-p t))
  758.   ;; Alter the copied tree so each cell appears to be newly created.
  759.   (kview:map-tree
  760.    (function
  761.     (lambda (view)
  762.       (kcell-view:set-cell
  763.        (kcell:create nil (kview:id-increment view)))))
  764.    kview))
  765.  
  766. (defun kotl-mode:copy-before (from-cell-ref to-cell-ref parent-p)
  767.   "Copy tree rooted at FROM-CELL-REF to precede tree rooted at TO-CELL-REF.
  768. If prefix arg PARENT-P is non-nil, make FROM-CELL-REF the first child of
  769. TO-CELL-REF's parent, otherwise make it the preceding sibling of TO-CELL-REF.
  770.  
  771. Leave point at the start of the root cell of the new tree."
  772.   (interactive
  773.    (let* ((label (kcell-view:label))
  774.       (hargs:defaults (list label label)))
  775.      (append
  776.       (hargs:iform-read
  777.        (list 'interactive
  778.          (format "*+KCopy tree: \n+KCopy tree <%%s> to be %s of cell: "
  779.              (if current-prefix-arg "first child of parent"
  780.                "preceding sibling"))))
  781.       (list current-prefix-arg))))
  782.   ;;
  783.   ;; Copy tree in current view and leave point at the start of the copy.
  784.   (goto-char (kotl-mode:move-before from-cell-ref to-cell-ref parent-p t))
  785.   ;; Alter the copied tree so each cell appears to be newly created.
  786.   (kview:map-tree
  787.    (function
  788.     (lambda (view)
  789.       (kcell-view:set-cell
  790.        (kcell:create nil (kview:id-increment view)))))
  791.    kview))
  792.  
  793. (defun kotl-mode:copy-to-buffer (cell-ref buffer)
  794.   "Copy outline tree rooted at CELL-REF to a non-koutline BUFFER.
  795. The tree is inserted before point in BUFFER.  Use \"0\" to copy the whole
  796. outline buffer."
  797.   (interactive
  798.    (let* ((label (kcell-view:label))
  799.       (hargs:defaults (list label)))
  800.      (hargs:iform-read
  801.       '(interactive "+KCopy tree without attributes: (0 for whole outline) \nBTo buffer: "))))
  802.   (if (equal cell-ref "0")
  803.       (append-to-buffer (get-buffer-create buffer) (point-min) (point-max))
  804.     (let (start end)
  805.       (save-excursion
  806.     (kotl-mode:goto-cell cell-ref t)
  807.     (beginning-of-line)
  808.     (setq start (point))
  809.     (or (= (kotl-mode:forward-cell 1) 0) (goto-char (point-max)))
  810.     (forward-line -1)
  811.     (setq end (point)))
  812.       (append-to-buffer (get-buffer-create buffer) start end))))
  813.  
  814. (defun kotl-mode:move-after (from-cell-ref to-cell-ref child-p
  815.                  &optional copy-p fill-p)
  816.   "Move tree rooted at FROM-CELL-REF to follow tree rooted at TO-CELL-REF.
  817. If prefix arg CHILD-P is non-nil, make FROM-CELL-REF the first child of
  818. TO-CELL-REF, otherwise make it the sibling following TO-CELL-REF.
  819. With optional COPY-P, copies tree rather than moving it.
  820.  
  821. Leave point at original location but return the tree's new start point."
  822.   (interactive
  823.    (let* ((label (kcell-view:label))
  824.       (hargs:defaults (list label label)))
  825.      (append
  826.       (hargs:iform-read
  827.        (list
  828.     'interactive
  829.     (format "*+KMove tree: \n+KMove tree <%%s> to follow as %s of cell: "
  830.         (if current-prefix-arg "child" "sibling"))))
  831.       (list current-prefix-arg))))
  832.   (if (and (not copy-p) (equal from-cell-ref to-cell-ref))
  833.       (error "(kotl-mode:move-after): Can't move tree after itself"))
  834.   (let* ((orig (set-marker (make-marker) (point)))
  835.      (label-sep-len (kview:label-separator-length kview))
  836.      (move-to-point (set-marker
  837.              (make-marker)
  838.              (kotl-mode:goto-cell to-cell-ref t)))
  839.      (to-label (kcell-view:label))
  840.      (to-indent (kcell-view:indent nil label-sep-len))
  841.      (from-label (progn (kotl-mode:goto-cell from-cell-ref t)
  842.                 (kcell-view:label)))
  843.      (from-indent (kcell-view:indent nil label-sep-len))
  844.      (start (kotl-mode:tree-start))
  845.      (end   (kotl-mode:tree-end))
  846.      (sib-id (if (= 0 (kotl-mode:forward-cell 1))
  847.              (kcell-view:idstamp)))
  848.      new-tree-start)
  849.     ;;
  850.     ;; We can't move a tree to a point within itself, so if that is the case
  851.     ;; and this is not a copy operation, signal an error.
  852.     (if (and (not copy-p) (>= move-to-point start) (<= move-to-point end))
  853.     (error "(kotl-mode:move-after): Can't move tree <%s> to within itself"
  854.            from-label))
  855.     ;;
  856.     ;; If tree to move has a sibling, point is now at the start of the
  857.     ;; sibling cell.  Mark its label with a property which will be deleted
  858.     ;; whenever the cell label is renumbered.  This tells us whether or not
  859.     ;; to renumber the sibling separately from the tree to move.
  860.     (if sib-id
  861.     ;; Move to middle of label and insert klabel-original temp property.
  862.     (progn (goto-char (- (point) label-sep-len 3))
  863.            (kproperty:set 'klabel-original t)))
  864.     ;;
  865.     ;; Position for insertion before deletion of tree-to-move from old
  866.     ;; position, in case old position precedes new one.
  867.     ;; Skip past either cell or tree at move-to-point.
  868.     (goto-char move-to-point)
  869.     (if child-p
  870.     ;; Move to insert position for first child of to-cell-ref.
  871.     (progn (goto-char (kcell-view:end))
  872.            (setq to-label (klabel:child to-label)
  873.              to-indent (+ to-indent (kview:level-indent kview))))
  874.       ;; Move to after to-cell-ref's tree for insertion as following sibling.
  875.       (goto-char (kotl-mode:tree-end))
  876.       (setq to-label (klabel:increment to-label)))
  877.     ;;
  878.     ;; Insert tree-to-move at new location
  879.     ;;
  880.     (kview:move start end (point) from-indent to-indent copy-p
  881.         (or fill-p kotl-mode:refill-flag))
  882.     ;;
  883.     ;; Ensure that point is within editable region of cell with to-label.
  884.     (kotl-mode:to-valid-position)
  885.     (setq new-tree-start (point))
  886.     ;;
  887.     ;; Update current cell and new siblings' labels within view.
  888.     (klabel-type:update-labels to-label)
  889.     ;;
  890.     (if copy-p
  891.     nil
  892.       ;;
  893.       ;; Move to sibling of tree-to-move within view and update labels within
  894.       ;; view of tree-to-move's original siblings.
  895.       (if sib-id
  896.       (progn (kotl-mode:goto-cell sib-id t)
  897.          ;; Sibling labels may have already been updated if tree was
  898.          ;; moved somewhere preceding its siblings.
  899.          (let ((label-middle (- (point) label-sep-len 2)))
  900.            (if (kproperty:get label-middle 'klabel-original)
  901.                (klabel-type:update-labels from-label))))))
  902.     ;;
  903.     (goto-char orig)
  904.     ;;
  905.     ;; Ensure that point is within editable region of a cell.
  906.     (kotl-mode:to-valid-position)
  907.     ;;
  908.     (set-marker orig nil)
  909.     (set-marker move-to-point nil)
  910.     new-tree-start))
  911.  
  912. (defun kotl-mode:move-before (from-cell-ref to-cell-ref parent-p
  913.                   &optional copy-p fill-p)
  914.   "Move tree rooted at FROM-CELL-REF to precede tree rooted at TO-CELL-REF.
  915. If prefix arg PARENT-P is non-nil, make FROM-CELL-REF the first child of
  916. TO-CELL-REF's parent, otherwise make it the preceding sibling of TO-CELL-REF.
  917. With optional COPY-P, copies tree rather than moving it.
  918.  
  919. Leave point at original location but return the tree's new start point."
  920.   (interactive
  921.    (let* ((label (kcell-view:label))
  922.       (hargs:defaults (list label label)))
  923.      (append
  924.       (hargs:iform-read
  925.        (list 'interactive
  926.          (format "*+KMove tree: \n+KMove tree <%%s> to be %s of cell: "
  927.              (if current-prefix-arg "first child of parent"
  928.                "preceding sibling"))))
  929.       (list current-prefix-arg))))
  930.   (if (and (not copy-p) (equal from-cell-ref to-cell-ref))
  931.       (error "(kotl-mode:move-before): Can't move tree before itself"))
  932.   (let* ((orig (set-marker (make-marker) (point)))
  933.      (label-sep-len (kview:label-separator-length kview))
  934.      (move-to-point (set-marker
  935.              (make-marker)
  936.              (kotl-mode:goto-cell to-cell-ref t)))
  937.      (to-label (kcell-view:label))
  938.      (to-indent (kcell-view:indent nil label-sep-len))
  939.      (from-label (progn (kotl-mode:goto-cell from-cell-ref t)
  940.                 (kcell-view:label)))
  941.      (from-indent (kcell-view:indent nil label-sep-len))
  942.      (start (kotl-mode:tree-start))
  943.      (end   (kotl-mode:tree-end))
  944.      (sib-id (if (= 0 (kotl-mode:forward-cell 1))
  945.              (kcell-view:idstamp)))
  946.      new-tree-start)
  947.     ;;
  948.     ;; We can't move a tree to a point within itself, so if that is the case
  949.     ;; and this is not a copy operation, signal an error.
  950.     (if (and (not copy-p) (>= move-to-point start) (<= move-to-point end))
  951.     (error "(kotl-mode:move-before): Can't move tree <%s> to within itself"
  952.            from-label))
  953.     ;;
  954.     ;; If tree to move has a sibling, point is now at the start of the
  955.     ;; sibling cell.  Mark its label with a property which will be deleted
  956.     ;; whenever the cell label is renumbered.  This tells us whether or not
  957.     ;; to renumber the sibling separately from the tree to move.
  958.     (if sib-id
  959.     ;; Move to middle of label and insert klabel-original temp property.
  960.     (progn (goto-char (- (point) label-sep-len 3))
  961.            (kproperty:set 'klabel-original t)))
  962.     ;;
  963.     ;; Position for insertion at succeeding-tree, before deletion of
  964.     ;; tree-to-move from old position, in case old position precedes new one.
  965.     (goto-char move-to-point)
  966.     (if parent-p
  967.     ;; Move to insert position for first child of to-cell-ref's parent.
  968.     (if (kcell-view:parent nil label-sep-len)
  969.         (progn (setq to-label (klabel:child (kcell-view:label)))
  970.            (goto-char (kcell-view:end)))
  971.       (error "(kotl-mode:move-before): to-cell-ref's parent not in current view"))
  972.       ;; Move to before to-cell-ref for insertion as preceding sibling.
  973.       (goto-char (kotl-mode:tree-start)))
  974.     ;;
  975.     ;; Insert tree-to-move at new location
  976.     ;;
  977.     (kview:move start end (point) from-indent to-indent copy-p
  978.         (or fill-p kotl-mode:refill-flag))
  979.     ;;
  980.     ;; Ensure that point is within editable region of root of tree just moved.
  981.     (kotl-mode:to-valid-position)
  982.     (setq new-tree-start (point))
  983.     ;;
  984.     ;; Update current cell and new siblings' labels within view.
  985.     (klabel-type:update-labels to-label)
  986.     ;;
  987.     (if copy-p
  988.     nil
  989.       ;;
  990.       ;; Move to sibling of tree-to-move within view and update labels within
  991.       ;; view of tree-to-move's original siblings.
  992.       (if sib-id
  993.       (progn
  994.         (kotl-mode:goto-cell sib-id t)
  995.         ;; Sibling labels may have already been updated if tree was
  996.         ;; moved somewhere preceding its siblings.
  997.         (let ((label-middle (- (point) label-sep-len 2)))
  998.           (if (kproperty:get label-middle 'klabel-original)
  999.           (klabel-type:update-labels from-label))))))
  1000.     ;;
  1001.     (goto-char orig)
  1002.     ;;
  1003.     ;; Ensure that point is within editable region of a cell.
  1004.     (kotl-mode:to-valid-position)
  1005.     ;;
  1006.     (set-marker orig nil)
  1007.     (set-marker move-to-point nil)
  1008.     new-tree-start))
  1009.  
  1010. (defun kotl-mode:yank (&optional arg)
  1011.   "Reinsert the last stretch of killed text.
  1012. More precisely, reinsert the stretch of killed text most recently
  1013. killed OR yanked.  Put point at end, and set mark at beginning.
  1014. With just C-u as argument, same but put point at beginning (and mark at end).
  1015. With argument N, reinsert the Nth most recently killed stretch of killed
  1016. text.
  1017. See also the command \\[kotl-mode:yank-pop]."
  1018.   (interactive "*P")
  1019.   (push-mark (point))
  1020.   (let* ((yank-text (current-kill (cond
  1021.                    ((listp arg) 0)
  1022.                    ((eq arg '-) -1)
  1023.                    (t (1- arg)))))
  1024.      (indent (kcell-view:indent))
  1025.      (indent-str (make-string indent ?\ )))
  1026.     ;; Convert all occurrences of newline to newline + cell indent.
  1027.     ;; Then insert into buffer.
  1028.     (insert (hypb:replace-match-string
  1029.          "[\n\^M]" yank-text (concat "\\0" indent-str))))
  1030.   (if (consp arg)
  1031.       ;; This is like exchange-point-and-mark, but doesn't activate the mark.
  1032.       ;; It is cleaner to avoid activation, even though the command
  1033.       ;; loop would deactivate the mark because we inserted text.
  1034.       (goto-char (prog1 (mark t)
  1035.            (set-marker (hypb:mark-marker t) (point)))))
  1036.   nil)
  1037.  
  1038. (defun kotl-mode:yank-pop (arg)
  1039.   "Replace just-yanked stretch of killed text with a different stretch.
  1040. This command is allowed only immediately after a `yank' or a `yank-pop'.
  1041. At such a time, the region contains a stretch of reinserted
  1042. previously-killed text.  `yank-pop' deletes that text and inserts in its
  1043. place a different stretch of killed text.
  1044.  
  1045. With no argument, the previous kill is inserted.
  1046. With argument N, insert the Nth previous kill.
  1047. If N is negative, this is a more recent kill.
  1048.  
  1049. The sequence of kills wraps around, so that after the oldest one
  1050. comes the newest one."
  1051.   (interactive "*p")
  1052.   (if (not (eq last-command 'kotl-mode:yank))
  1053.       (error "Previous command was not a yank"))
  1054.   (setq this-command 'kotl-mode:yank)
  1055.   (let ((before (< (point) (mark t))))
  1056.     (delete-region (point) (mark t))
  1057.     (set-marker (hypb:mark-marker t) (point) (current-buffer))
  1058.     (let* ((yank-text (current-kill arg))
  1059.        (indent (kcell-view:indent))
  1060.        (indent-str (make-string indent ?\ )))
  1061.       ;; Convert all occurrences of newline to newline + cell indent.
  1062.       ;; Then insert into buffer.
  1063.       (insert (hypb:replace-match-string
  1064.            "[\n\^M]" yank-text (concat "\\0" indent-str))))
  1065.     (if before
  1066.     ;; This is like exchange-point-and-mark, but doesn't activate the mark.
  1067.     ;; It is cleaner to avoid activation, even though the command
  1068.     ;; loop would deactivate the mark because we inserted text.
  1069.     (goto-char (prog1 (mark t)
  1070.              (set-marker (hypb:mark-marker t) (point) (current-buffer))))))
  1071.   nil)
  1072.  
  1073. ;;; ------------------------------------------------------------------------
  1074. ;;; Movement
  1075. ;;; ------------------------------------------------------------------------
  1076.  
  1077. ;;; Cursor and keypad key functions aliases for XEmacs.
  1078. (if (not (string-match "XEmacs\\|Lucid" emacs-version))
  1079.     nil
  1080.   (fset 'kotl-mode:fkey-backward-char 'kotl-mode:backward-char)
  1081.   (fset 'kotl-mode:fkey-forward-char  'kotl-mode:forward-char)
  1082.   (fset 'kotl-mode:fkey-next-line     'kotl-mode:next-line)
  1083.   (fset 'kotl-mode:fkey-previous-line 'kotl-mode:previous-line)
  1084.   (fset 'kotl-mode:deprecated-scroll-down 'kotl-mode:scroll-down)
  1085.   (fset 'kotl-mode:deprecated-scroll-up 'kotl-mode:scroll-up)
  1086.   (fset 'kotl-mode:deprecated-bob     'kotl-mode:beginning-of-buffer)
  1087.   (fset 'kotl-mode:deprecated-eob     'kotl-mode:end-of-buffer))
  1088.  
  1089. (defun kotl-mode:back-to-indentation ()
  1090.   "Move point to the first non-read-only non-whitespace character on this line."
  1091.   (interactive)
  1092.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1093.   (back-to-indentation)
  1094.   (kotl-mode:to-valid-position))
  1095.  
  1096. (defun kotl-mode:backward-cell (arg)
  1097.   "Move to prefix ARGth prior visible cell (same level) within current view.
  1098. Return number of cells left to move."
  1099.   (interactive "p")
  1100.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1101.   (if (< arg 0)
  1102.       (kotl-mode:forward-cell (- arg))
  1103.     (let ((prior (= arg 0))
  1104.       (label-sep-len (kview:label-separator-length kview)))
  1105.       (while (and (> arg 0) (setq prior (kcell-view:backward t label-sep-len)))
  1106.     (setq arg (1- arg)))
  1107.       (if (or prior (not (interactive-p)))
  1108.       arg
  1109.     (error "(kotl-mode:backward-cell): No prior cell at same level")))))
  1110.  
  1111. (defun kotl-mode:backward-char (&optional arg)
  1112.   "Move point backward ARG (or 1) characters and return point."
  1113.   (interactive "p")
  1114.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1115.   (or arg (setq arg 1))
  1116.   (if (>= arg 0)
  1117.       (while (> arg 0)
  1118.     (cond ((kotl-mode:bobp)
  1119.            (error "(kotl-mode:backward-char): Beginning of buffer"))
  1120.           ((kotl-mode:bocp)
  1121.            (if (kcell-view:previous)
  1122.            (kotl-mode:end-of-cell)))
  1123.           ((kotl-mode:bolp)
  1124.            (if (re-search-backward "[\n\^M]" nil t)
  1125.            (kotl-mode:to-valid-position t)))
  1126.           (t (backward-char)))
  1127.     (setq arg (1- arg)))
  1128.     (kotl-mode:forward-char (- arg)))
  1129.   (point))
  1130.  
  1131. (defun kotl-mode:backward-paragraph (&optional arg)
  1132.   "Move backward to start of paragraph.
  1133. With arg N, do it N times; negative arg -N means move forward N paragraphs.
  1134. Return point.
  1135.  
  1136. A paragraph start is the beginning of a line which is a
  1137. `first-line-of-paragraph' or which is ordinary text and follows a
  1138. paragraph-separating line.
  1139.  
  1140. See `forward-paragraph' for more information."
  1141.   (interactive "p")
  1142.   (setq arg (prefix-numeric-value arg)
  1143.     zmacs-region-stays t);; Maintain region highlight for XEmacs.
  1144.   (kotl-mode:forward-paragraph (- arg)))
  1145.  
  1146. (fset 'kotl-mode:backward-para 'kotl-mode:backward-paragraph)
  1147.  
  1148. (defun kotl-mode:backward-sentence (&optional arg)
  1149.   "Move point backward ARG (or 1) sentences and return point."
  1150.   (interactive "p")
  1151.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1152.   (let* ((label-sep-len (kview:label-separator-length kview))
  1153.      ;; Setting fill prefix makes sentence commands properly recognize
  1154.      ;; indented paragraphs.
  1155.      (fill-prefix (make-string (kcell-view:indent nil label-sep-len) ?\ )))
  1156.     (if (kotl-mode:bobp)
  1157.     (error "(kotl-mode:backward-sentence): First sentence")
  1158.       (if (and (kotl-mode:bocp) (kcell-view:previous nil label-sep-len))
  1159.       (goto-char (kcell-view:end-contents)))
  1160.       (or arg (setq arg 1))
  1161.       (save-restriction
  1162.     (if (= arg 1)
  1163.         (narrow-to-region
  1164.          (- (kcell-view:start nil label-sep-len)
  1165.         (kcell-view:indent nil label-sep-len))
  1166.          (kcell-view:end-contents)))
  1167.     (unwind-protect
  1168.         (let ((opoint (point)))
  1169.           (backward-sentence arg)
  1170.           (if (= opoint (point))
  1171.           (progn (kcell-view:previous nil label-sep-len)
  1172.              (backward-sentence arg))))
  1173.       (kotl-mode:to-valid-position t)))))
  1174.   (point))
  1175.  
  1176. (defun kotl-mode:backward-word (&optional arg)
  1177.   "Move point backward ARG (or 1) words and return point."
  1178.   (interactive "p")
  1179.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1180.   (or arg (setq arg 1))
  1181.   (if (>= arg 0)
  1182.       (while (> arg 0)
  1183.     (cond ((kotl-mode:bobp) (setq arg 0))
  1184.           ((kotl-mode:bocp)
  1185.            (beginning-of-line)
  1186.            (kotl-mode:to-valid-position t)))
  1187.     (unwind-protect
  1188.         (backward-word 1)
  1189.       (kotl-mode:to-valid-position t))
  1190.     (setq arg (1- arg)))
  1191.     (kotl-mode:forward-word (- arg)))
  1192.   (point))
  1193.  
  1194. (defun kotl-mode:beginning-of-buffer ()
  1195.   "Move point to beginning of buffer and return point."
  1196.   (interactive)
  1197.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1198.   (goto-char (point-min))
  1199.   ;; To move to cell start.
  1200.   (goto-char (kcell-view:start)))
  1201.  
  1202. (defun kotl-mode:beginning-of-cell (&optional arg)
  1203.   "Move point to beginning of current or ARGth - 1 prior cell and return point."
  1204.   (interactive "p")
  1205.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1206.   (or arg (setq arg 1))
  1207.   (or (integer-or-marker-p arg)
  1208.       (error "(kotl-mode:beginning-of-cell): Wrong type arg, integer-or-marker, '%s'" arg))
  1209.   (if (= arg 1)
  1210.       (goto-char (kcell-view:start))
  1211.     (kotl-mode:backward-cell (1- arg)))
  1212.   (point))
  1213.  
  1214. ;;; Avoid XEmacs byte-compiler bug which inserts nil for calls to this
  1215. ;;; function if named kotl-mode:beginning-of-line.
  1216. ;;;
  1217. (defun kotl-mode:start-of-line (&optional arg)
  1218.   "Move point to beginning of current or ARGth - 1 line and return point."
  1219.   (interactive "p")
  1220.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1221.   (or arg (setq arg 1))
  1222.   (or (integer-or-marker-p arg)
  1223.       (error "(kotl-mode:start-of-line): Wrong type arg, integer-or-marker, '%s'" arg))
  1224.   (forward-line (1- arg))
  1225.   (if (eolp)
  1226.       nil
  1227.     (forward-char (prog1 (kcell-view:indent)
  1228.             (beginning-of-line))))
  1229.   (point))
  1230.  
  1231. (defalias 'kotl-mode:beginning-of-line 'kotl-mode:start-of-line)
  1232.  
  1233. (defun kotl-mode:beginning-of-tree ()
  1234.   "Move point to the level 1 root of the current cell's tree.
  1235. Leave point at the start of the cell."
  1236.   (interactive)
  1237.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1238.   (let ((label-sep-len (kview:label-separator-length kview)))
  1239.     (if (/= (kcell-view:level nil label-sep-len) 1)
  1240.     ;; Enable user to return to this previous position if desired.
  1241.     (push-mark nil 'no-msg))
  1242.     (while (and (/= (kcell-view:level nil label-sep-len) 1)
  1243.         (kcell-view:parent nil label-sep-len)))
  1244.     (kotl-mode:beginning-of-cell)))
  1245.  
  1246. (defun kotl-mode:down-level (arg)
  1247.   "Move down prefix ARG levels lower within current tree."
  1248.   (interactive "p")
  1249.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1250.   (if (< arg 0)
  1251.       (kotl-mode:up-level (- arg))
  1252.     ;; Enable user to return to this previous position if desired.
  1253.     (push-mark nil 'no-msg)
  1254.     (let ((child))
  1255.       (while (and (> arg 0) (kcell-view:child))
  1256.     (or child (setq child t))
  1257.     (setq arg (1- arg)))
  1258.       ;; Signal an error if couldn't move down at least 1 child level.
  1259.       (or child
  1260.       (progn
  1261.         (goto-char (hypb:mark t))
  1262.         (pop-mark)
  1263.         (error "(kotl-mode:down-level): No child level to which to move")
  1264.         )))))
  1265.  
  1266. (defun kotl-mode:end-of-buffer ()
  1267.   "Move point to end of buffer and return point."
  1268.   (interactive)
  1269.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1270.   (goto-char (point-max))
  1271.   ;; To move to cell end.
  1272.   (kotl-mode:to-valid-position t)
  1273.   (point))
  1274.  
  1275. (defun kotl-mode:end-of-cell (&optional arg)
  1276.   "Move point to end of current or ARGth - 1 succeeding cell and return point."
  1277.   (interactive "p")
  1278.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1279.   (or arg (setq arg 1))
  1280.   (or (integer-or-marker-p arg)
  1281.       (error "(kotl-mode:end-of-cell): Wrong type arg, integer-or-marker, '%s'" arg))
  1282.   (if (= arg 1)
  1283.       (goto-char (kcell-view:end-contents))
  1284.     (kotl-mode:forward-cell (1- arg)))
  1285.   (point))
  1286.  
  1287. ;;; Avoid XEmacs byte-compiler bug which inserts nil for calls to this
  1288. ;;; function if named kotl-mode:end-of-line.
  1289. ;;;
  1290. (defun kotl-mode:finish-of-line (&optional arg)
  1291.   "Move point to end of current or ARGth - 1 line and return point."
  1292.   (interactive "p")
  1293.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1294.   (or arg (setq arg 1))
  1295.   (or (integer-or-marker-p arg)
  1296.       (error "(kotl-mode:finish-of-line): Wrong type arg, integer-or-marker, '%s'" arg))
  1297.   (forward-line (1- arg))
  1298.   (end-of-line)
  1299.   ;; May have to move backwards to before label if support labels
  1300.   ;; at end of cells.
  1301.   (point))
  1302.  
  1303. (defalias 'kotl-mode:end-of-line 'kotl-mode:finish-of-line)
  1304.  
  1305. (defun kotl-mode:end-of-tree ()
  1306.   "Move point to the last cell in tree rooted at the current cell.
  1307. Leave point at the start of the cell."
  1308.   (interactive)
  1309.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1310.   ;; Enable user to return to this previous position if desired.
  1311.   (push-mark nil 'no-msg)
  1312.   (let ((label-sep-len (kview:label-separator-length kview)))
  1313.     (if (kcell-view:forward nil label-sep-len)
  1314.     ;; Move to cell preceding start of next tree.
  1315.     (kcell-view:previous nil label-sep-len)
  1316.       ;; Otherwise, no next tree, so move until find last cell in tree.
  1317.       (let ((cell-indent (kcell-view:indent nil label-sep-len))
  1318.         (end-point (point)))
  1319.     ;; Terminate when no further cells or when reach a cell at an equal
  1320.     ;; or higher level in the outline than the first cell that we
  1321.     ;; processed.
  1322.     (while (and (kcell-view:next nil label-sep-len)
  1323.             (> (kcell-view:indent nil label-sep-len) cell-indent))
  1324.       (setq end-point (point)))
  1325.     (goto-char end-point)))
  1326.     (kotl-mode:beginning-of-cell)))
  1327.  
  1328. (defun kotl-mode:first-sibling ()
  1329.   "Move point to the first sibling of the present cell.
  1330. Leave point at the start of the cell or at its present position if it is
  1331. already within the first sibling cell."
  1332.   (interactive)
  1333.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1334.   (let ((label-sep-len (kview:label-separator-length kview)))
  1335.     (if (save-excursion (kcell-view:backward nil label-sep-len))
  1336.     ;; Enable user to return to this previous position if desired.
  1337.     (push-mark nil 'no-msg))
  1338.     (while (kcell-view:backward nil label-sep-len))))
  1339.  
  1340. (defun kotl-mode:forward-cell (arg)
  1341.   "Move to prefix ARGth following cell (same level) within current view.
  1342. Return number of cells left to move."
  1343.   (interactive "p")
  1344.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1345.   (if (< arg 0)
  1346.       (kotl-mode:backward-cell (- arg))
  1347.     (let ((next (= arg 0))
  1348.       (label-sep-len (kview:label-separator-length kview)))
  1349.       (while (and (> arg 0) (setq next (kcell-view:forward t label-sep-len)))
  1350.     (setq arg (1- arg)))
  1351.       (if (or next (not (interactive-p)))
  1352.       arg
  1353.     (error "(kotl-mode:forward-cell): No following cell at same level")))))
  1354.  
  1355. (defun kotl-mode:forward-char (&optional arg)
  1356.   "Move point forward ARG (or 1) characters and return point."
  1357.   (interactive "p")
  1358.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1359.   (or arg (setq arg 1))
  1360.   (if (>= arg 0)
  1361.       (while (> arg 0)
  1362.     (cond ((and (kotl-mode:eolp) (kotl-mode:last-line-p))
  1363.            (error "(kotl-mode:forward-char): End of buffer"))
  1364.           ((kotl-mode:eocp)
  1365.            (skip-chars-forward "\n\^M")
  1366.            (kotl-mode:start-of-line))
  1367.           ((kotl-mode:eolp)
  1368.            (forward-char)
  1369.            (kotl-mode:start-of-line))
  1370.           (t (forward-char)))
  1371.     (setq arg (1- arg)))
  1372.     (kotl-mode:backward-char (- arg)))
  1373.   (point))
  1374.  
  1375. (defun kotl-mode:forward-paragraph (&optional arg)
  1376.   "Move point forward until after the last character of the current paragraph.
  1377. With arg N, do it N times; negative arg -N means move backward N paragraphs.
  1378. Return point.
  1379.  
  1380. A line which `paragraph-start' matches either separates paragraphs
  1381. \(if `paragraph-separate' matches it also) or is the first line of a paragraph.
  1382. A paragraph end is one character before the beginning of a line which is not
  1383. part of the paragraph, or the end of the buffer."
  1384.   (interactive "p")
  1385.   (setq arg (prefix-numeric-value arg)
  1386.     zmacs-region-stays t);; Maintain region highlight for XEmacs.
  1387.   (if (< arg 0)
  1388.       (progn
  1389.     (if (kotl-mode:bocp) (setq arg (1- arg)))
  1390.     (while (< arg 0)
  1391.       (start-of-paragraph-text)
  1392.       (setq arg (1+ arg))))
  1393.     (while (> arg 0) 
  1394.       (end-of-paragraph-text)
  1395.       (setq arg (1- arg))))
  1396.   (kotl-mode:to-valid-position)
  1397.   (point))
  1398.  
  1399. (fset 'kotl-mode:forward-para 'kotl-mode:forward-paragraph)
  1400.  
  1401. (defun kotl-mode:forward-sentence (&optional arg)
  1402.   "Move point forward ARG (or 1) sentences and return point."
  1403.   (interactive "P")
  1404.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1405.   (let* ((label-sep-len (kview:label-separator-length kview))
  1406.      ;; Setting fill prefix makes sentence commands properly recognize
  1407.      ;; indented paragraphs.
  1408.      (fill-prefix (make-string (kcell-view:indent nil label-sep-len) ?\ )))
  1409.     (if (kotl-mode:eobp)
  1410.     (error "(kotl-mode:forward-sentence): Last sentence")
  1411.       (if (kotl-mode:eocp) (kcell-view:next nil label-sep-len))
  1412.       (or arg (setq arg 1))
  1413.       (save-restriction
  1414.     (if (= arg 1)
  1415.         (narrow-to-region
  1416.          (- (kcell-view:start nil label-sep-len)
  1417.         (kcell-view:indent nil label-sep-len))
  1418.          (kcell-view:end-contents)))
  1419.     (unwind-protect
  1420.         (let ((opoint (point)))
  1421.           (forward-sentence arg)
  1422.           (if (= opoint (point))
  1423.           (progn (kcell-view:next nil label-sep-len)
  1424.              (forward-sentence arg))))
  1425.       (kotl-mode:to-valid-position)))))
  1426.   (point))
  1427.  
  1428. (defun kotl-mode:forward-word (&optional arg)
  1429.   "Move point forward ARG (or 1) words and return point."
  1430.   (interactive "p")
  1431.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1432.   (or arg (setq arg 1))
  1433.   (if (>= arg 0)
  1434.       (while (> arg 0)
  1435.     (cond ((kotl-mode:eobp) (setq arg 0))
  1436.           ((kotl-mode:eocp)
  1437.            (skip-chars-forward "\n\^M")
  1438.            (kotl-mode:start-of-line)))
  1439.     (unwind-protect
  1440.         (forward-word 1)
  1441.       (kotl-mode:to-valid-position))
  1442.     ;; If point is at beginning of a cell after moving forward a word,
  1443.     ;; then we moved over something other than a word (some
  1444.     ;; punctuation or an outline autonumber); therefore, leave counter as
  1445.     ;; is in order to move forward over next word.
  1446.     (or (kotl-mode:bocp)
  1447.         (setq arg (1- arg))))
  1448.     (kotl-mode:backward-word (- arg)))
  1449.   (point))
  1450.  
  1451. (defun kotl-mode:goto-cell (cell-ref &optional error-p)
  1452.   "Move point to start of cell given by CELL-REF.  (See 'kcell:ref-to-id'.)
  1453. Return point iff CELL-REF is found within current view.
  1454. With a prefix argument, CELL-REF is assigned the argument value for use
  1455. as an idstamp.
  1456.  
  1457. Optional second arg, ERROR-P, non-nil means signal an error if CELL-REF is
  1458. not found within current view.  Will signal same error if called
  1459. interactively when CELL-REF is not found."
  1460.   (interactive
  1461.    (list (if current-prefix-arg
  1462.          (format "0%d" (prefix-numeric-value current-prefix-arg))
  1463.        (read-string "Goto cell label or id: "))))
  1464.   (setq cell-ref
  1465.     (or (kcell:ref-to-id cell-ref)
  1466.         (error "(kotl-mode:goto-cell): Invalid cell reference, '%s'" cell-ref)))
  1467.   (let* ((opoint (point))
  1468.      (found))
  1469.     (goto-char (point-min))
  1470.     (cond ((= ?0 (aref cell-ref 0))
  1471.        ;; is an idstamp
  1472.        (if (kview:goto-cell-id cell-ref)
  1473.            (setq found (point))))
  1474.        ;; is a label
  1475.       ((re-search-forward
  1476.         (format "\\([\n\^M][\n\^M]\\|\\`\\)[ ]*%s%s"
  1477.             (regexp-quote cell-ref)
  1478.             (regexp-quote (kview:label-separator kview)))
  1479.         nil t)
  1480.        (setq found (point)))
  1481.       ;; no match
  1482.       (t (goto-char opoint)
  1483.          nil))
  1484.     (if (and (not found) (or error-p (interactive-p)))
  1485.     (error "(kotl-mode:goto-cell): No '%s' cell in this view" cell-ref)
  1486.       found)))
  1487.  
  1488. (defun kotl-mode:head-cell ()
  1489.   "Move point to the start of the first visible cell at the same level as current cell.
  1490. If at head cell already, do nothing and return nil."
  1491.   (interactive "p")
  1492.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1493.   (let ((moved)
  1494.     (label-sep-len (kview:label-separator-length kview)))
  1495.     (while (kcell-view:backward t label-sep-len)
  1496.       (setq moved t))
  1497.     moved))
  1498.  
  1499. (defun kotl-mode:last-sibling ()
  1500.   "Move point to the last sibling of the present cell.
  1501. Leave point at the start of the cell or at its present position if it is
  1502. already within the last sibling cell."
  1503.   (interactive)
  1504.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1505.   (let ((label-sep-len (kview:label-separator-length kview)))
  1506.     (if (save-excursion (kcell-view:forward nil label-sep-len))
  1507.     ;; Enable user to return to this previous position if desired.
  1508.     (push-mark nil 'no-msg))
  1509.     (while (kcell-view:forward nil label-sep-len))))
  1510.  
  1511. (defun kotl-mode:mark-paragraph ()
  1512.   "Put point at beginning of this paragraph, mark at end.
  1513. The paragraph marked is the one that contains point or follows point."
  1514.   (interactive)
  1515.   (forward-paragraph 1)
  1516.   (kotl-mode:to-valid-position t)
  1517.   (hypb:push-mark nil t t)
  1518.   (backward-paragraph 1)
  1519.   (kotl-mode:to-valid-position))
  1520.  
  1521. (defun kotl-mode:mark-whole-buffer ()
  1522.   "Put point at first editable character in buffer and mark at the last such character."
  1523.   (interactive)
  1524.   (hypb:push-mark (point))
  1525.   (kotl-mode:end-of-buffer)
  1526.   (hypb:push-mark (point) nil t)
  1527.   (kotl-mode:beginning-of-buffer))
  1528.  
  1529. (defun kotl-mode:next-cell (arg)
  1530.   "Move to prefix ARGth next cell (any level) within current view."
  1531.   (interactive "p")
  1532.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1533.   (if (< arg 0)
  1534.       (kotl-mode:previous-cell (- arg))
  1535.     (let ((next (= arg 0))
  1536.       (label-sep-len (kview:label-separator-length kview)))
  1537.       (while (and (> arg 0) (setq next (kcell-view:next t label-sep-len)))
  1538.     (setq arg (1- arg)))
  1539.       (if next
  1540.       arg
  1541.     (error "(kotl-mode:next-cell): Last cell")))))
  1542.  
  1543. (defun kotl-mode:next-line (arg)
  1544.   "Move point to ARGth next line and return point."
  1545.   (interactive "p")
  1546.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1547.   (kotl-mode:set-temp-goal-column)
  1548.   (let ((orig-arg arg))
  1549.     (cond ((> arg 0)
  1550.        (while (and (> arg 0) (= 0 (forward-line 1)))
  1551.          (cond ((kotl-mode:eobp)
  1552.             (forward-line -1)
  1553.             (goto-char (kcell-view:end-contents))
  1554.             (and (interactive-p) (= orig-arg arg)
  1555.              (message "(kotl-mode:next-line): Last line") (beep))
  1556.             (setq arg 0)
  1557.             )
  1558.            ((looking-at "^$");; blank line between cells
  1559.             nil);; Don't count this line.
  1560.            (t (setq arg (1- arg)))))
  1561.        (kotl-mode:line-move 0)
  1562.        (kotl-mode:to-valid-position)
  1563.        )
  1564.       ((< arg 0)
  1565.        (kotl-mode:previous-line (- arg)))
  1566.       (t)))
  1567.   (setq this-command 'next-line)
  1568.   (point))
  1569.  
  1570. (defun kotl-mode:next-tree ()
  1571.   "Move past current tree to next tree, or to last cell in tree if no next tree.
  1572. Return non-nil iff there is a next tree within this koutline."
  1573.   (let ((start-indent (kcell-view:indent))
  1574.     (label-sep-len (kview:label-separator-length kview))
  1575.     (same-tree t))
  1576.       (while (and (kcell-view:next nil label-sep-len)
  1577.           (setq same-tree (< start-indent
  1578.                      (kcell-view:indent nil label-sep-len)))))
  1579.       (not same-tree)))
  1580.  
  1581. (defun kotl-mode:previous-line (arg)
  1582.   "Move point to ARGth previous line and return point."
  1583.   (interactive "p")
  1584.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1585.   (kotl-mode:set-temp-goal-column)
  1586.   (cond ((> arg 0)
  1587.          (while (and (> arg 0) (= 0 (forward-line -1)))
  1588.            (cond ((kotl-mode:bobp)
  1589.                   (kotl-mode:beginning-of-cell)
  1590.                   (setq arg 0))
  1591.                  ((looking-at "^$") ;; blank line between cells
  1592.                   nil) ;; Don't count this line.
  1593.                  (t (setq arg (1- arg)))))
  1594.      (kotl-mode:line-move 0)
  1595.      (kotl-mode:to-valid-position)
  1596.      )
  1597.         ((< arg 0)
  1598.          (kotl-mode:next-line (- arg)))
  1599.         (t))
  1600.   (setq this-command 'previous-line)
  1601.   (point))
  1602.  
  1603. (defun kotl-mode:previous-cell (arg)
  1604.   "Move to prefix ARGth previous cell (any level) within current view."
  1605.   (interactive "p")
  1606.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1607.   (if (< arg 0)
  1608.       (kotl-mode:next-cell (- arg))
  1609.     (let ((previous (= arg 0))
  1610.       (label-sep-len (kview:label-separator-length kview)))
  1611.       (while (and (> arg 0) (setq previous
  1612.                   (kcell-view:previous t label-sep-len)))
  1613.     (setq arg (1- arg)))
  1614.       (if previous
  1615.       arg
  1616.     (error "(kotl-mode:previous-cell): First cell")))))
  1617.  
  1618. (defun kotl-mode:scroll-down (arg)
  1619.   "Scroll text of current window downward ARG lines; or a windowful if no ARG."
  1620.   (interactive "P")
  1621.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1622.   (scroll-down arg)
  1623.   (kotl-mode:to-valid-position t))
  1624.  
  1625. (defun kotl-mode:scroll-up (arg)
  1626.   "Scroll text of current window upward ARG lines; or a windowful if no ARG."
  1627.   (interactive "P")
  1628.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1629.   (scroll-up arg)
  1630.   (kotl-mode:to-valid-position))
  1631.  
  1632. (defun kotl-mode:tail-cell ()
  1633.   "Move point to the start of the last visible cell at the same level as current cell and return t.
  1634. If at tail cell already, do nothing and return nil."
  1635.   (interactive "p")
  1636.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1637.   (let ((moved)
  1638.     (label-sep-len (kview:label-separator-length kview)))
  1639.     (while (kcell-view:forward t label-sep-len)
  1640.       (setq moved t))
  1641.     moved))
  1642.  
  1643. (defun kotl-mode:up-level (arg)
  1644.   "Move up prefix ARG levels higher in current outline view."
  1645.   (interactive "p")
  1646.   (setq zmacs-region-stays t) ;; Maintain region highlight for XEmacs.
  1647.   (if (< arg 0)
  1648.       (kotl-mode:down-level (- arg))
  1649.     ;; Enable user to return to this previous position if desired.
  1650.     (push-mark nil 'no-msg)
  1651.     (let ((parent)
  1652.       (label-sep-len (kview:label-separator-length kview))
  1653.       result)
  1654.       (while (and (> arg 0) (setq result (kcell-view:parent t label-sep-len)))
  1655.     (or parent (setq parent result))
  1656.     (setq arg (if (eq result 0) 0 (1- arg))))
  1657.       ;; Signal an error if couldn't move up at least 1 parent level.
  1658.       (or (and parent (not (eq parent 0)))
  1659.       (progn
  1660.         (goto-char (hypb:mark t))
  1661.         (pop-mark)
  1662.         (error "(kotl-mode:up-level): No parent level to which to move")
  1663.         )))))
  1664.  
  1665. ;;; ------------------------------------------------------------------------
  1666. ;;; Predicates
  1667. ;;; ------------------------------------------------------------------------
  1668.  
  1669. (defun kotl-mode:bobp ()
  1670.   "Return point if at the start of the first cell in kview, else nil."
  1671.   (interactive)
  1672.   (or (bobp)
  1673.       (and (not (save-excursion (re-search-backward "[\n\^M]" nil t)))
  1674.        (kotl-mode:bolp))))
  1675.  
  1676. (defun kotl-mode:bocp ()
  1677.   "Return point if at beginning of a kcell, else nil."
  1678.   (and (kotl-mode:bolp)
  1679.        (let ((begin-point (kcell-view:plist-point))
  1680.          (bol))
  1681.      (and begin-point
  1682.           (save-excursion
  1683.         ;; If first line-begin is less than cell begin point,
  1684.         ;; then we know we are on the first line of the cell.
  1685.         (if (setq bol (re-search-backward "^" nil t))
  1686.             (<= bol begin-point)))))
  1687.        (point)))
  1688.  
  1689. (defun kotl-mode:bolp ()
  1690.   "Return point if at beginning of a kview line, else nil."
  1691.   (if (= (current-column) (kcell-view:indent))
  1692.       (point)))
  1693.  
  1694. (defun kotl-mode:buffer-empty-p ()
  1695.   "Return non-nil iff there are no outline cells within current buffer."
  1696.   (save-excursion
  1697.     (goto-char (point-min))
  1698.     (looking-at "[\n\^M]*\\'")))
  1699.  
  1700. (defun kotl-mode:eobp ()
  1701.   "Return point if after the end of the last cell in kview, else nil."
  1702.   (interactive)
  1703.   (if (looking-at "^[\n\^M]*\\'") (point)))
  1704.  
  1705. (defun kotl-mode:eocp ()
  1706.   "Return point if at the end of a kview cell, else nil."
  1707.   (or (eobp)
  1708.       (looking-at "[\n\^M]+\\'")
  1709.       (and (eolp)
  1710.        (save-excursion
  1711.          (skip-chars-forward "\n\^M")
  1712.          (kotl-mode:start-of-line)
  1713.          (kotl-mode:bocp)))))
  1714.  
  1715. (fset 'kotl-mode:eolp 'eolp)
  1716.  
  1717. (defun kotl-mode:first-cell-p ()
  1718.   "Return t iff point is on the first cell of the outline."
  1719.   (save-excursion (not (kcell-view:previous))))
  1720.  
  1721. (fset 'kotl-mode:first-line-p 'first-line-p)
  1722.  
  1723. (defun kotl-mode:last-cell-p ()
  1724.   "Return t iff point is on the last cell of the outline."
  1725.   (save-excursion (not (kcell-view:next))))
  1726.  
  1727. (defun kotl-mode:last-line-p ()
  1728.   "Return t iff point is on the last line of the outline."
  1729.   (save-excursion
  1730.     (kotl-mode:finish-of-line)
  1731.     (looking-at "\n*\\'")))
  1732.  
  1733. ;;; ------------------------------------------------------------------------
  1734. ;;; Smart Key Support
  1735. ;;; ------------------------------------------------------------------------
  1736.  
  1737.  
  1738. (defun kotl-mode:action-key ()
  1739.   "Collapses, expands, links to, and scrolls through koutline cells.
  1740. Invoked via a key press when in kotl-mode.  It assumes that its caller has
  1741. already checked that the key was pressed in an appropriate buffer and has
  1742. moved the cursor to the selected buffer.
  1743.  
  1744. If key is pressed:
  1745.  (1) at the end of buffer, uncollapse and unhide all cells in view;
  1746.  (2) within a cell, if its subtree is hidden then show it,
  1747.      otherwise hide it;
  1748.  (3) between cells or within the read-only indentation region to the left of
  1749.      a cell, then move point to prior location and begin creation of a
  1750.      klink to some other outline cell; hit the Action Key twice to select the
  1751.      link referent cell;
  1752.  (4) anywhere else, scroll up a windowful."
  1753.   (interactive)
  1754.   (cond    ((kotl-mode:eobp) (kotl-mode:show-all))
  1755.     ((kotl-mode:eolp) (scroll-up-eol))
  1756.     ((not (kview:valid-position-p))
  1757.      (if (markerp action-key-depress-prev-point)
  1758.          (progn (select-window
  1759.              (get-buffer-window
  1760.               (marker-buffer action-key-depress-prev-point)))
  1761.             (goto-char (marker-position action-key-depress-prev-point))
  1762.             (call-interactively 'klink:create))
  1763.        (kotl-mode:to-valid-position)
  1764.        (error "(kotl-mode:action-key): Action Key released at invalid position")))
  1765.     (t ;; On a cell line (not at the end of line).
  1766.      (if (smart-outline-subtree-hidden-p)
  1767.          (kotl-mode:show-tree (kcell-view:label))
  1768.        (kotl-mode:hide-tree (kcell-view:label)))))
  1769.   (kotl-mode:to-valid-position))
  1770.  
  1771. (defun kotl-mode:help-key ()
  1772.   "Displays properties of koutline cells, collapses all cells, and scrolls back.
  1773. Invoked via an assist-key press when in kotl-mode.  It assumes that its caller
  1774. has already checked that the assist-key was pressed in an appropriate buffer
  1775. and has moved the cursor to the selected buffer.
  1776.  
  1777. If assist-key is pressed:
  1778.  (1) at the end of buffer, collapse all cells and hide all non-level-one
  1779.      cells;
  1780.  (2) on a header line but not at the beginning or end, display properties of
  1781.      each cell in tree beginning at point;
  1782.  (3) between cells or within the read-only indentation region to the left of
  1783.      a cell, then move point to prior location and prompt to move one tree to
  1784.      a new location in the outline; hit the Action Key twice to select the
  1785.      tree to move and where to move it;
  1786.  (4) anywhere else, scroll down a windowful."
  1787.   (interactive)
  1788.   (cond ((kotl-mode:eobp) (kotl-mode:overview))
  1789.     ((kotl-mode:eolp) (scroll-down-eol))
  1790.     ((not (kview:valid-position-p))
  1791.      (if (markerp assist-key-depress-prev-point)
  1792.          (progn (select-window
  1793.              (get-buffer-window
  1794.               (marker-buffer assist-key-depress-prev-point)))
  1795.             (goto-char (marker-position
  1796.                 assist-key-depress-prev-point))
  1797.             (call-interactively 'kotl-mode:move-after))
  1798.        (kotl-mode:to-valid-position)
  1799.        (error "(kotl-mode:help-key): Help Key released at invalid position")))
  1800.     ((not (bolp))
  1801.      ;; On an outline header line but not at the start/end of line,
  1802.      ;; show properties for tree at point.
  1803.      (kotl-mode:kcell-help (kcell-view:label) (or current-prefix-arg 2)))
  1804.     ((scroll-down-eol)))
  1805.   (kotl-mode:to-valid-position))
  1806.  
  1807. ;;; ------------------------------------------------------------------------
  1808. ;;; Structure Editing
  1809. ;;; ------------------------------------------------------------------------
  1810.  
  1811. (defun kotl-mode:add-child ()
  1812.   "Add a new cell to current kview as first child of current cell."
  1813.   (interactive "*")
  1814.   (kotl-mode:add-cell '(4)))
  1815.  
  1816. (defun kotl-mode:add-parent ()
  1817.   "Add a new cell to current kview as sibling of current cell's parent."
  1818.   (interactive "*")
  1819.   (kotl-mode:add-cell -1))
  1820.  
  1821. (defun kotl-mode:add-cell (&optional relative-level contents no-fill)
  1822.   "Add a cell following current cell at optional RELATIVE-LEVEL with CONTENTS string.
  1823. Optional prefix arg RELATIVE-LEVEL means add as sibling if nil or >= 0, as
  1824. child if equal to universal argument, {C-u}, and as sibling of current cell's
  1825. parent, otherwise.  If added as sibling of current level, RELATIVE-LEVEL is
  1826. used as a repeat count for the number of cells to add.
  1827.  
  1828. Optional NO-FILL prevents any filling of CONTENTS.
  1829.  
  1830. Return last newly added cell."
  1831.   (interactive "*P")
  1832.   (or (stringp contents) (setq contents nil))
  1833.   (let ((klabel (kcell-view:label))
  1834.     (label-sep-len (kview:label-separator-length kview))
  1835.     cell-level new-cell sibling-p child-p start parent
  1836.     cells-to-add)
  1837.     (setq cell-level (kcell-view:level nil label-sep-len)
  1838.       child-p (equal relative-level '(4))
  1839.       sibling-p (and (not child-p)
  1840.              (cond ((not relative-level) 1)
  1841.                    ((>= (prefix-numeric-value relative-level) 0)
  1842.                 (prefix-numeric-value relative-level))))
  1843.       cells-to-add (or sibling-p 1))
  1844.     (if child-p
  1845.     (setq cell-level (1+ cell-level))
  1846.       (if sibling-p
  1847.       nil
  1848.     ;; Add as following sibling of current cell's parent.
  1849.     ;; Move to parent.
  1850.     (setq cell-level (1- cell-level)
  1851.           start (point)
  1852.           parent (kcell-view:parent nil label-sep-len))
  1853.     (if (not (eq parent t))
  1854.         (progn
  1855.           (goto-char start)
  1856.           (error
  1857.            "(kotl-mode:add-cell): No higher level at which to add cell.")
  1858.           )))
  1859.       ;; Skip from point past any children to next cell.
  1860.       (if (kotl-mode:next-tree)
  1861.       ;; If found a new tree, then move back to prior cell so can add
  1862.       ;; new cell after it.
  1863.       (kcell-view:previous nil label-sep-len)))
  1864.     (goto-char (kcell-view:end))
  1865.     ;;
  1866.     ;; Insert new cells into view.
  1867.     (if (= cells-to-add 1)
  1868.     (setq klabel
  1869.           (cond (sibling-p
  1870.              (klabel:increment klabel))
  1871.             (child-p (klabel:child klabel))
  1872.             ;; add as sibling of parent of current cell
  1873.             (t (klabel:increment (klabel:parent klabel))))
  1874.           new-cell (kview:add-cell klabel cell-level contents nil
  1875.                        (or no-fill sibling-p
  1876.                        (not kotl-mode:refill-flag))))
  1877.       ;;
  1878.       ;; sibling-p must be true if we are looping here so there is no need to
  1879.       ;; conditionalize how to increment the labels.
  1880.       (while (>= (setq cells-to-add (1- cells-to-add)) 0)
  1881.     (setq klabel (klabel:increment klabel)
  1882.           ;; Since new cells are at the same level as old one, don't fill
  1883.           ;; any of their intial contents.
  1884.           new-cell (kview:add-cell klabel cell-level contents nil t))))
  1885.     ;;
  1886.     ;; Move back to last inserted cell and then move to its following
  1887.     ;; sibling if any.
  1888.     (kotl-mode:to-valid-position t)
  1889.     (save-excursion
  1890.       (if (kcell-view:forward t label-sep-len)
  1891.       ;; Update the labels of these siblings and their subtrees.
  1892.       (klabel-type:update-labels (klabel:increment klabel))))
  1893.     ;;
  1894.     ;; Leave point within last newly added cell and return this cell.
  1895.     (kotl-mode:beginning-of-cell)
  1896.     new-cell))
  1897.  
  1898. (defun kotl-mode:demote-tree (arg)
  1899.   "Move current tree a maximum of prefix ARG levels lower in current view.
  1900. Each cell is refilled iff its `no-fill' attribute is nil and
  1901. kotl-mode:refill-flag is non-nil.  With prefix ARG = 0, cells are demoted up
  1902. to one level and kotl-mode:refill-flag is treated as true."
  1903.   (interactive "*p")
  1904.   (cond ((< arg 0)
  1905.          (kotl-mode:promote-tree (- arg)))
  1906.         (t (let* ((label-sep-len (kview:label-separator-length kview))
  1907.           (orig-level (kcell-view:level nil label-sep-len))
  1908.           (orig-point (point))
  1909.           (orig-id (kcell-view:idstamp))
  1910.           (fill-p (= arg 0))
  1911.           (orig-pos-in-cell
  1912.            (- (point) (kcell-view:start nil label-sep-len)))
  1913.           prev prev-level)
  1914.          (if fill-p (setq arg 1))
  1915.          (unwind-protect
  1916.          (progn
  1917.            (backward-char 1)
  1918.            (while (and (> arg 0)
  1919.                    (setq prev
  1920.                      (kcell-view:previous nil label-sep-len)))
  1921.              (if prev
  1922.              (progn (setq prev-level
  1923.                       (kcell-view:level nil label-sep-len))
  1924.                 (cond ((> prev-level (+ orig-level arg))
  1925.                        ;; Don't want to demote this far
  1926.                        ;; so keep looking at prior nodes.
  1927.                        nil)
  1928.                       ((= arg (- prev-level orig-level))
  1929.                        ;; Demote to be sibling of this kcell.
  1930.                        (setq arg -1))
  1931.                       ((< prev-level orig-level)
  1932.                       ;; prev is at higher level then
  1933.                       ;; orig, so can't demote
  1934.                        (setq prev nil
  1935.                          arg 0))
  1936.                       (t
  1937.                        ;; Demote below this kcell.  This is
  1938.                        ;; as far we can demote, though it may
  1939.                        ;; not be the full amount of arg.
  1940.                        (setq arg 0))))))
  1941.            (if prev
  1942.                (kotl-mode:move-after
  1943.             (kcell-view:label orig-point)
  1944.             (kcell-view:label) (= arg 0)
  1945.             nil fill-p)))
  1946.            ;; Move to start of original cell
  1947.            (kotl-mode:goto-cell orig-id)
  1948.            ;; Move to original pos within cell
  1949.            (forward-char orig-pos-in-cell)
  1950.            )
  1951.          (if (not prev)
  1952.          (error "(kotl-mode:demote-tree): Cannot demote any further"))))))
  1953.  
  1954. (defun kotl-mode:exchange-cells (cell-ref-1 cell-ref-2)
  1955.   "Exchange CELL-REF-1 with CELL-REF-2 in current view.  Don't move point."
  1956.   (interactive
  1957.    (let ((hargs:defaults
  1958.       (save-excursion
  1959.         (list (kcell-view:label)
  1960.           (cond
  1961.            ((kcell-view:previous t)
  1962.             (kcell-view:label))
  1963.            ((kcell-view:next t)
  1964.             (kcell-view:label))
  1965.            (t (error
  1966.                "(kotl-mode:exchange-cells): No 2 visible cells")))))))
  1967.      (hargs:iform-read
  1968.       '(interactive "*+KExchange cell: \n+KExchange cell <%s> with cell: "))))
  1969.   (save-excursion
  1970.     (let (kcell-1 contents-1
  1971.       kcell-2 contents-2)
  1972.       ;;
  1973.       ;; Save cell-1 attributes
  1974.       (kotl-mode:goto-cell cell-ref-1 t)
  1975.       (setq kcell-1 (kcell-view:cell)
  1976.         contents-1 (kcell-view:contents))
  1977.       ;;
  1978.       ;; Save cell-2 attributes
  1979.       (kotl-mode:goto-cell cell-ref-2 t)
  1980.       (setq kcell-2 (kcell-view:cell)
  1981.         contents-2 (kcell-view:contents))
  1982.       ;;
  1983.       ;; Substitute cell-1 attributes into cell-2 location.
  1984.       ;;
  1985.       ;; Set kcell properties.
  1986.       (kcell-view:set-cell kcell-1)
  1987.       ;; If idstamp labels are on, then must exchange labels in view.
  1988.       (if (eq (kview:label-type kview) 'id)
  1989.       (klabel:set (kcell-view:idstamp)))
  1990.       ;; Exchange cell contents.
  1991.       (delete-region (kcell-view:start) (kcell-view:end-contents))
  1992.       (insert
  1993.        (hypb:replace-match-string
  1994.     "\\([\n\^M]\\)"
  1995.     contents-1 (concat "\\1" (make-string (kcell-view:indent) ?\ ))))
  1996.       (if kotl-mode:refill-flag (kotl-mode:fill-cell))
  1997.       ;;
  1998.       ;; Substitute cell-2 attributes into cell-1 location.
  1999.       ;;
  2000.       ;; Set kcell properties.
  2001.       (kotl-mode:goto-cell cell-ref-1 t)
  2002.       (kcell-view:set-cell kcell-2)
  2003.       ;; If idstamp labels are on, then must exchange labels in view.
  2004.       (if (eq (kview:label-type kview) 'id)
  2005.       (klabel:set (kcell-view:idstamp)))
  2006.       ;; Exchange cell contents.
  2007.       (delete-region (kcell-view:start) (kcell-view:end-contents))
  2008.       ;; Add indentation to all but first line.
  2009.       (insert
  2010.        (hypb:replace-match-string
  2011.     "\\([\n\^M]\\)"
  2012.     contents-2 (concat "\\1" (make-string (kcell-view:indent) ?\ ))))
  2013.       (if kotl-mode:refill-flag (kotl-mode:fill-cell)))))
  2014.  
  2015. (defun kotl-mode:kill-contents (arg)
  2016.   "Kill contents of cell from point to cell end.
  2017. With prefix ARG, kill entire cell contents."
  2018.   (interactive "*P")
  2019.   (kotl-mode:kill-region
  2020.    (if arg (kcell-view:start) (point))
  2021.    (kcell-view:end-contents)))
  2022.  
  2023. (defun kotl-mode:kill-tree (&optional arg)
  2024.   "Kill ARG following trees starting with tree rooted at point.
  2025. If ARG is not a non-positive number, nothing is done."
  2026.   (interactive "*p")
  2027.   (or (integerp arg) (setq arg 1))
  2028.   (let ((killed) (label (kcell-view:label))
  2029.     (label-sep-len (kview:label-separator-length kview))
  2030.     start end sib)
  2031.     (while (> arg 0)
  2032.       (setq start (kotl-mode:tree-start)
  2033.         end   (kotl-mode:tree-end)
  2034.         sib   (kcell-view:sibling-p nil label-sep-len)
  2035.         arg (1- arg)
  2036.         killed t)
  2037.       ;; Don't want to delete any prior cells, so if on last cell, ensure
  2038.       ;; this is the last one killed.
  2039.       (if (kotl-mode:last-cell-p)
  2040.       (progn (setq arg 0)
  2041.          (kview:delete-region start end))
  2042.     (kview:delete-region start end)
  2043.     (kotl-mode:to-valid-position)))
  2044.     (if killed
  2045.     (progn
  2046.       (cond (sib (klabel-type:update-labels label))
  2047.         ((kotl-mode:buffer-empty-p)
  2048.          ;; Always leave at least 1 visible cell within a view.
  2049.          (kview:add-cell "1" 1)))
  2050.       (kotl-mode:to-valid-position)))))
  2051.  
  2052. (defun kotl-mode:mail-tree (cell-ref)
  2053.   "Mail outline tree rooted at CELL-REF.  Use \"0\" for whole outline buffer."
  2054.   (interactive
  2055.    (let* ((label (kcell-view:label))
  2056.       (hargs:defaults (list label)))
  2057.      (hargs:iform-read
  2058.       '(interactive "+KMail tree: (0 for whole outline) "))))
  2059.   (if (equal cell-ref "0")
  2060.       (hmail:buffer (current-buffer))
  2061.     (let (start end)
  2062.       (save-excursion
  2063.     (kotl-mode:goto-cell cell-ref t)
  2064.     (beginning-of-line)
  2065.     (setq start (point))
  2066.     (or (= (kotl-mode:forward-cell 1) 0) (goto-char (point-max)))
  2067.     (forward-line -1)
  2068.     (setq end (point)))
  2069.       (hmail:region start end))))
  2070.  
  2071. (defun kotl-mode:promote-tree (arg)
  2072.   "Move current tree a maximum of prefix ARG levels higher in current view.
  2073. Each cell is refilled iff its `no-fill' attribute is nil and
  2074. kotl-mode:refill-flag is non-nil.  With prefix ARG = 0, cells are promoted up
  2075. to one level and kotl-mode:refill-flag is treated as true."
  2076.   (interactive "*p")
  2077.   (cond ((< arg 0)
  2078.          (kotl-mode:demote-tree (- arg)))
  2079.         (t (let* ((parent) (result)
  2080.           (label-sep-len (kview:label-separator-length kview))
  2081.           (orig-point (point))
  2082.           (orig-id (kcell-view:idstamp))
  2083.           (fill-p (= arg 0))
  2084.           (orig-pos-in-cell
  2085.            (- (point) (kcell-view:start nil label-sep-len))))
  2086.          (if fill-p (setq arg 1))
  2087.          (unwind-protect
  2088.          (progn
  2089.            (backward-char 1)
  2090.            (while (and (> arg 0)
  2091.                    (setq result (kcell-view:parent
  2092.                          nil label-sep-len))
  2093.                    (not (eq result 0)))
  2094.              (setq parent result
  2095.                arg (1- arg)))
  2096.            (if parent
  2097.                (kotl-mode:move-after
  2098.             (kcell-view:label orig-point)
  2099.             (kcell-view:label) nil
  2100.             nil fill-p)))
  2101.            ;; Move to start of original cell
  2102.            (kotl-mode:goto-cell orig-id)
  2103.            ;; Move to original pos within cell
  2104.            (forward-char orig-pos-in-cell))
  2105.          (if (not parent)
  2106.          (error "(kotl-mode:promote-tree): Cannot promote any further"))))))
  2107.  
  2108. (defun kotl-mode:split-cell (&optional arg)
  2109.   "Split current cell into two cells and move to new cell.
  2110. Cell contents after point become part of the newly created cell.
  2111. The default is to create the new cell as a sibling of the current cell.
  2112. With optional universal ARG, {C-u}, the new cell is added as the child of
  2113. the current cell."
  2114.   (interactive "*P")
  2115.   (let ((new-cell-contents (kotl-mode:kill-region
  2116.                 (point) (kcell-view:end-contents) 'string))
  2117.     (start (kcell-view:start)))
  2118.     ;; delete any preceding whitespace
  2119.     (skip-chars-backward " \t\n\^M" start)
  2120.     (delete-region (max start (point)) (kcell-view:end-contents))
  2121.     (kotl-mode:add-cell arg new-cell-contents
  2122.             (kcell-view:get-attr 'no-fill))))
  2123.  
  2124.  
  2125. (defun kotl-mode:transpose-cells (arg)
  2126.   "Exchange current and previous visible cells, leaving point after both.
  2127. If no previous cell, exchange current with next cell.
  2128. With prefix ARG, take current tree and move it past ARG visible cells.
  2129. With prefix ARG = 0, interchange the cell that contains point with the cell
  2130. that contains mark."
  2131.   (interactive "*p")
  2132.   (let ((label-sep-len (kview:label-separator-length kview)))
  2133.     (cond
  2134.      ((save-excursion (not (or (kcell-view:next t label-sep-len)
  2135.                    (kcell-view:previous t label-sep-len))))
  2136.       (error "(kotl-mode:transpose-cells): Only one visible cell in outline"))
  2137.      ;;
  2138.      ;; Transpose current and previous cells or current and next cells, if no
  2139.      ;; previous cell.  Leave point after both exchanged cells or within last
  2140.      ;; visible cell.
  2141.      ((= arg 1)
  2142.       (let ((label-1 (kcell-view:label))
  2143.         (prev (kcell-view:previous t label-sep-len))
  2144.         label-2)
  2145.     (or prev (kcell-view:next t label-sep-len))
  2146.     (setq label-2 (kcell-view:label))
  2147.     (kotl-mode:exchange-cells label-1 label-2)
  2148.     (kcell-view:next t label-sep-len)
  2149.     (if prev (kcell-view:next t label-sep-len))))
  2150.      ;;
  2151.      ;; Transpose point and mark cells, moving point to the new location of the
  2152.      ;; cell which originally contained point.
  2153.      ((= arg 0)
  2154.       (let ((label-1 (kcell-view:label))
  2155.         label-2)
  2156.     ;; This is like exchange-point-and-mark, but doesn't activate the
  2157.     ;; mark.
  2158.     (goto-char (prog1 (hypb:mark t)
  2159.              (set-marker (hypb:mark-marker t) (point))))
  2160.     (setq label-2 (kcell-view:label))
  2161.     (kotl-mode:exchange-cells label-1 label-2)))
  2162.      ;;
  2163.      ;; Move current tree past ARG next visible cells and leave point after
  2164.      ;; original cell text.
  2165.      (t
  2166.       (let ((mark (set-marker (make-marker)
  2167.                   (save-excursion (kotl-mode:next-line arg)))))
  2168.     (kotl-mode:move-after
  2169.      (kcell-view:label)
  2170.      (progn (while (and (> arg 0) (kcell-view:next t label-sep-len))
  2171.           (setq arg (1- arg)))
  2172.         (kcell-view:label))
  2173.      nil)
  2174.     (goto-char mark)
  2175.     (set-marker mark nil))))))
  2176.  
  2177. ;;; ------------------------------------------------------------------------
  2178. ;;; Structure Viewing
  2179. ;;; ------------------------------------------------------------------------
  2180.  
  2181. (defun kotl-mode:collapse-tree (&optional all-flag)
  2182.   "Collapse each visible cell of tree rooted at point.
  2183. With optional ALL-FLAG non-nil, collapse all cells visible within the current
  2184. view."
  2185.   (interactive "P")
  2186.   (kotl-mode:is-p)
  2187.   (let (buffer-read-only)
  2188.     (kview:map-tree
  2189.      (function
  2190.       (lambda (kview)
  2191.     ;; Use free variable label-sep-len bound in kview:map-tree for speed.
  2192.     (goto-char (kcell-view:start nil label-sep-len))
  2193.     (subst-char-in-region (point) (kcell-view:end-contents) ?\n ?\^M t)))
  2194.      kview all-flag t)))
  2195.  
  2196. (defun kotl-mode:expand-tree (&optional all-flag)
  2197.   "Expand each visible cell of tree rooted at point.
  2198. With optional ALL-FLAG non-nil, expand all cells visible within the current
  2199. view."
  2200.   (interactive "P")
  2201.   (kotl-mode:is-p)
  2202.   (let (buffer-read-only)
  2203.     (kview:map-tree
  2204.      (function
  2205.       (lambda (kview)
  2206.     ;; Use free variable label-sep-len bound in kview:map-tree for speed.
  2207.     (goto-char (kcell-view:start nil label-sep-len))
  2208.     (subst-char-in-region (point) (kcell-view:end-contents) ?\^M ?\n t)))
  2209.      kview all-flag t)))
  2210.  
  2211. (defun kotl-mode:toggle-tree-expansion (&optional all-flag)
  2212.   "Collapse or expand each cell of tree rooted at point or all visible cells if optional prefix arg ALL-FLAG is given.
  2213. If current cell is collapsed, cells will be expanded, otherwise they will be
  2214. collapsed."
  2215.   (interactive "P")
  2216.   (if (kcell-view:collapsed-p)
  2217.        ;; expand cells
  2218.       (kotl-mode:expand-tree all-flag)
  2219.     (kotl-mode:collapse-tree all-flag)))
  2220.  
  2221. ;;; 
  2222. (defun kotl-mode:extend-all ()
  2223.   "Add blank lines between all visible and invisible cells in current kview."
  2224.   (interactive "*")
  2225.   (kotl-mode:is-p)
  2226.   (let ((modified-p (buffer-modified-p))
  2227.     end)
  2228.     (save-excursion
  2229.       (goto-char (point-min))
  2230.       (while (and (setq end (kproperty:next-single-change (point) 'kcell-end))
  2231.           (progn
  2232.             (goto-char end)
  2233.             (kproperty:remove (point) (+ (point) 2) '(kcell-end t))
  2234.             (insert (following-char))
  2235.             (if (= (point) (point-max))
  2236.             nil
  2237.               (forward-char 2)
  2238.               t))))
  2239.       (set-buffer-modified-p modified-p))))
  2240.  
  2241. (defun kotl-mode:shorten-all ()
  2242.   "Remove blank lines between all visible and invisible cells in current kview."
  2243.   (interactive "*")
  2244.   (kotl-mode:is-p)
  2245.   (let ((modified-p (buffer-modified-p)))
  2246.     (save-excursion
  2247.       (goto-char (point-min))
  2248.       (while (search-forward "\n\n" nil t)
  2249.     (replace-match "\n" t t)
  2250.     (goto-char (match-beginning 0))
  2251.     (kproperty:set 'kcell-end t))
  2252.       (goto-char (point-min))
  2253.       (while (re-search-forward "\^M[\n\^M]" nil t)
  2254.     (replace-match "\^M" t t)
  2255.     (goto-char (match-beginning 0))
  2256.     (kproperty:set 'kcell-end t)))
  2257.     (set-buffer-modified-p modified-p)))
  2258.  
  2259. ;;; 
  2260. (defun kotl-mode:overview ()
  2261.   "Show only the first line of each cell in the current outline."
  2262.   (interactive)
  2263.   (kotl-mode:collapse-tree t))
  2264.  
  2265. (defun kotl-mode:show-all ()
  2266.   "Show (expand) all cells in current view."
  2267.   (interactive)
  2268.   (if (kotl-mode:is-p)
  2269.       (let (buffer-read-only)
  2270.     (show-all))))
  2271.  
  2272. (defun kotl-mode:top-cells ()
  2273.   "Collapse all level 1 cells in view, thereby hiding any sublevels."
  2274.   (interactive)
  2275.   (kotl-mode:is-p)
  2276.   (save-excursion
  2277.     (let ((modified-p (buffer-modified-p))
  2278.       (buffer-read-only))
  2279.       ;; Make each cell display as a single line.
  2280.       (subst-char-in-region (point-min) (kotl-mode:end-of-buffer) ?\n ?\^M t)
  2281.       (goto-char (point-min))
  2282.       (while (search-forward "\^M\^M" nil t)
  2283.     (replace-match "\n\n" t t))
  2284.       (goto-char (point-min))
  2285.       ;; Hide all non-level-1 cells.
  2286.       ;; !! Won't work if labels are turned off.
  2287.       (while (re-search-forward
  2288.           "^[ ]*\\([0-9]+\\.?[a-z.A-Z]\\|\\*\\*+\\)" nil t)
  2289.     (save-excursion
  2290.       (beginning-of-line)
  2291.       (subst-char-in-region (- (point) 2) (point) ?\n ?\^M t)))
  2292.       ;; Restore buffer modification status
  2293.       (set-buffer-modified-p modified-p))))
  2294.  
  2295. ;;; 
  2296. (defun kotl-mode:hide-sublevels (levels-to-keep)
  2297.   "Hide all cells in outline at levels deeper than LEVELS-TO-KEEP (a number).
  2298. Shows any hidden cells within LEVELS-TO-KEEP.  1 is the first level."
  2299.   (interactive "P")
  2300.   (if (null levels-to-keep)
  2301.       (setq levels-to-keep
  2302.         (read-from-minibuffer "Hide cells deeper than level: "
  2303.                   nil nil t)))
  2304.   (setq levels-to-keep (prefix-numeric-value levels-to-keep))
  2305.   (if (< levels-to-keep 1)
  2306.       (error "(kotl-mode:hide-sublevels): Must display at least one level."))
  2307.   (kview:map-tree
  2308.    (function (lambda (kview) 
  2309.            (if (/= (kcell-view:level) levels-to-keep)
  2310.            (kotl-mode:show-tree)
  2311.          (kotl-mode:hide-subtree)
  2312.          ;; Move to last cell in hidden subtree, to skip further
  2313.          ;; processing of these cells.
  2314.          (if (kcell-view:next t)
  2315.              (kcell-view:previous)
  2316.            (goto-char (point-max))))))
  2317.    kview t))
  2318.  
  2319. (defun kotl-mode:hide-subtree (&optional cell-ref show-flag)
  2320.   "Hide subtree, ignoring root, at optional CELL-REF (defaults to cell at point)."
  2321.   (interactive)
  2322.   (kotl-mode:is-p)
  2323.   (save-excursion
  2324.     (if cell-ref
  2325.     (kotl-mode:goto-cell cell-ref t)
  2326.       (kotl-mode:beginning-of-cell))
  2327.     (let ((start (kcell-view:end-contents))
  2328.       (end (kotl-mode:tree-end t))
  2329.       (buffer-read-only))
  2330.       (if show-flag
  2331.       (subst-char-in-region start end ?\^M ?\n t)
  2332.     (subst-char-in-region start end ?\n ?\^M t)))))
  2333.  
  2334. (defun kotl-mode:show-subtree (&optional cell-ref)
  2335.   "Show subtree, ignoring root, at optional CELL-REF (defaults to cell at point)."
  2336.   (interactive)
  2337.   (kotl-mode:hide-subtree cell-ref t))
  2338.  
  2339. (defun kotl-mode:hide-tree (&optional cell-ref show-flag)
  2340.   "Collapse tree rooted at optional CELL-REF (defaults to cell at point)."
  2341.   (interactive)
  2342.   (kotl-mode:is-p)
  2343.   (save-excursion
  2344.     (let ((start (if cell-ref
  2345.              (kotl-mode:goto-cell cell-ref t)
  2346.            (kotl-mode:beginning-of-cell)))
  2347.       (end (kotl-mode:tree-end t))
  2348.       (buffer-read-only))
  2349.       (if show-flag
  2350.       (subst-char-in-region start end ?\^M ?\n t)
  2351.     (subst-char-in-region start end ?\n ?\^M t)))))
  2352.  
  2353. (defun kotl-mode:show-tree (&optional cell-ref)
  2354.   "Display fully expanded tree rooted at CELL-REF."
  2355.   (interactive)
  2356.   (kotl-mode:hide-tree cell-ref t))
  2357.  
  2358. ;;; 
  2359. (defun kotl-mode:kcell-help (&optional cell-ref cells-flag)
  2360.   "Display a temporary buffer with CELL-REF's properties.
  2361. CELL-REF defaults to current cell.
  2362. Optional prefix arg CELLS-FLAG selects the cells to print:
  2363.   If = 1, print CELL-REF's cell only;
  2364.   If > 1, print CELL-REF's visible tree (the tree rooted at CELL-REF);
  2365.   If < 1, print all visible cells in current view (CELL-REF is not used).
  2366.  
  2367. See also the documentation for `kotl-mode:properties'."
  2368.   (interactive
  2369.    (let* ((label (kcell-view:label))
  2370.       (hargs:defaults (list label label)))
  2371.      (append
  2372.       (let ((arg (prefix-numeric-value current-prefix-arg)))
  2373.     (if (< arg 1)
  2374.         0
  2375.       (hargs:iform-read
  2376.        (list 'interactive
  2377.          (format "+KDisplay properties of %s: "
  2378.              (if (= arg 1) "kcell" "kotl"))))))
  2379.       (list current-prefix-arg))))
  2380.   (or (integerp cells-flag)
  2381.       (setq cells-flag (prefix-numeric-value cells-flag)))
  2382.   (or (stringp cell-ref) (setq cell-ref (kcell-view:label)))
  2383.   (with-output-to-temp-buffer
  2384.       (hypb:help-buf-name "Kotl")
  2385.     (save-excursion
  2386.       (cond ((= cells-flag 1)
  2387.          (kotl-mode:goto-cell cell-ref)
  2388.          (kotl-mode:print-properties kview))
  2389.         ((> cells-flag 1)
  2390.          (kotl-mode:goto-cell cell-ref)
  2391.          (kview:map-tree 'kotl-mode:print-properties kview nil t))
  2392.         ;; (< cells-flag 1)
  2393.         (t (kotl-mode:properties t))))))
  2394.  
  2395. (defun kotl-mode:properties (all-flag)
  2396.   "Display a temporary buffer with current kcell's properties.
  2397. With prefix arg ALL-FLAG non-nil, display properties for all visible
  2398. kcells in the current buffer.
  2399.  
  2400. See also the documentation for `kotl-mode:kcell-help'."
  2401.   (interactive "P")
  2402.   (with-output-to-temp-buffer
  2403.       (hypb:help-buf-name "Kotl")
  2404.     (save-excursion
  2405.       (if (not all-flag)
  2406.       (kotl-mode:print-properties kview)
  2407.     (let ((label-sep-len (kview:label-separator-length kview)))
  2408.       (kotl-mode:beginning-of-buffer)
  2409.       (while (progn (kotl-mode:print-properties kview)
  2410.             (kcell-view:next t label-sep-len))))))))
  2411.  
  2412. ;;; ************************************************************************
  2413. ;;; Private functions
  2414. ;;; ************************************************************************
  2415.  
  2416. (defun kotl-mode:add-indent-to-region (&optional indent start end)
  2417.   "Add current cell's indent to current region.
  2418. Optionally, INDENT and region START and END may be given."
  2419.   (or (integerp indent) (setq indent (kcell-view:indent)))
  2420.   (save-excursion
  2421.     (save-restriction
  2422.       (narrow-to-region (or start (point)) (or end (hypb:mark t)))
  2423.       (goto-char (point-min))
  2424.       (replace-regexp "\n" (concat "\n" (make-string indent ?\ ))))))
  2425.  
  2426. (defun kotl-mode:delete-line (&optional pos)
  2427.   "Delete and return contents of cell line at point or optional POS as a string.
  2428. Does not delete newline at end of line."
  2429.   (save-excursion
  2430.     (if pos (goto-char pos))
  2431.     (if (kview:valid-position-p)
  2432.     (let ((bol (kotl-mode:start-of-line))
  2433.           (eol (kotl-mode:finish-of-line)))
  2434.       (prog1
  2435.           (buffer-substring bol eol)
  2436.         (delete-region bol eol)))
  2437.       (error "(kotl-mode:delete-line): Invalid position, '%d'" (point)))))
  2438.  
  2439. (defun kotl-mode:is-p ()
  2440.   "Signal an error if current buffer is not a Hyperbole outline, else return t."
  2441.   (or (and (fboundp 'kview:is-p) (kview:is-p kview))
  2442.       (hypb:error
  2443.        "(kotl-mode:is-p): Command requires a current Hyperbole outline.")))
  2444.  
  2445. (defun kotl-mode:tree-end (&optional omit-end-newlines)
  2446.   "Return end point of current cell's tree within this view.
  2447. If optional OMIT-END-NEWLINES is non-nil, point returned precedes any
  2448. newlines at end of tree."
  2449.   (let* ((label-sep-len (kview:label-separator-length kview))
  2450.      (start-indent (kcell-view:indent nil label-sep-len))
  2451.      (next))
  2452.     (save-excursion
  2453.       (while (and (setq next (kcell-view:next nil label-sep-len))
  2454.           (< start-indent (kcell-view:indent nil label-sep-len))))
  2455.       (cond (next
  2456.          (goto-char (progn (kcell-view:previous nil label-sep-len)
  2457.                    (kcell-view:end))))
  2458.         ;; Avoid skipping too far at end of file.
  2459.         ((re-search-forward "[\n\^M][\n\^M]" nil t))
  2460.         (t (goto-char (point-max))))
  2461.       (if omit-end-newlines (skip-chars-backward "\n\^M"))
  2462.       (point))))
  2463.  
  2464. (defun kotl-mode:tree-start ()
  2465.   "Return beginning of line position preceding current cell's start point."
  2466.   (save-excursion (goto-char (kcell-view:start)) (beginning-of-line)
  2467.           (point)))
  2468.  
  2469. (defun kotl-mode:line-move (arg)
  2470.   "Move point ARG visible lines forward within an outline."
  2471.   (if (not (integerp selective-display))
  2472.       (forward-line arg)
  2473.     ;; Move by arg lines, but ignore invisible ones.
  2474.     (while (> arg 0)
  2475.       (vertical-motion 1)
  2476.       (forward-char -1)
  2477.       (forward-line 1)
  2478.       (setq arg (1- arg)))
  2479.     (while (< arg 0)
  2480.       (vertical-motion -1)
  2481.       (beginning-of-line)
  2482.       (setq arg (1+ arg))))
  2483.   (move-to-column (or goal-column temporary-goal-column))
  2484.   nil)
  2485.  
  2486. (defun kotl-mode:print-properties (kview)
  2487.   "Print to the `standard-output' stream the properties of the current visible kcell. 
  2488. Takes argument KVIEW (so it can be used with 'kview:map-tree' and so that
  2489. KVIEW is bound correctly) but always operates upon the current view."
  2490.   ;; Move to start of visible cell to avoid printing properties for an
  2491.   ;; invisible kcell which point may be over.
  2492.   ;; Print first line of cell for reference.
  2493.   (princ
  2494.    (save-excursion
  2495.      (buffer-substring (progn (beginning-of-line) (point))
  2496.                (progn (kview:end-of-actual-line)
  2497.                   (point)))))
  2498.   (terpri)
  2499.   (hattr:report (kcell:plist (kcell-view:cell)))
  2500.   (terpri))
  2501.  
  2502. (defun kotl-mode:set-temp-goal-column ()
  2503.   (if (not (or (eq last-command 'next-line)
  2504.            (eq last-command 'previous-line)))
  2505.       (setq temporary-goal-column
  2506.         (if (and track-eol (eolp)
  2507.              ;; Don't count beg of empty line as end of line
  2508.              ;; unless we just did explicit end-of-line.
  2509.              (or (not (bolp)) (eq last-command 'end-of-line)))
  2510.         9999
  2511.           (current-column)))))
  2512.  
  2513. (defun kotl-mode:to-valid-position (&optional backward-p)
  2514.   "Move point to the nearest non-read-only position within current koutline view.
  2515. With optional BACKWARD-P, move backward if possible to get to valid position."
  2516.   (let ((label-sep-len (kview:label-separator-length kview)))
  2517.     (cond ((kotl-mode:bobp)
  2518.        (goto-char (kcell-view:start nil label-sep-len)))
  2519.       ((kotl-mode:eobp)
  2520.        (skip-chars-backward "\n\^M"))
  2521.       (t (let ((indent (kcell-view:indent nil label-sep-len)))
  2522.            (if (>= (current-column) indent)
  2523.            nil
  2524.          (if (bolp)
  2525.              (if backward-p
  2526.              (skip-chars-backward "\n\^M")
  2527.                (skip-chars-forward "\n\^M")))
  2528.          (setq indent (kcell-view:indent nil label-sep-len))
  2529.          (if (< (current-column) indent)
  2530.              (move-to-column indent))))))))
  2531.  
  2532. (defun kotl-mode:transpose-lines-internal (start end)
  2533.   "Transpose lines at START and END markers within an outline.
  2534. Leave point at end of line now residing at START."
  2535.   (if (and start end
  2536.        (kview:valid-position-p start)
  2537.        (kview:valid-position-p end))
  2538.       (let* ((pline (kotl-mode:delete-line start))
  2539.          mline)
  2540.     (goto-char end)
  2541.     (setq mline (kotl-mode:delete-line))
  2542.     (insert pline)
  2543.     (goto-char start)
  2544.     (insert mline))
  2545.     ;; Set non-point and non-mark markers to point nowhere before signalling
  2546.     ;; an error.
  2547.     (or (eq start (point-marker))
  2548.     (eq start (hypb:mark-marker t))
  2549.     (set-marker start nil))
  2550.     (or (eq end (point-marker))
  2551.     (eq end (hypb:mark-marker t))
  2552.     (set-marker start nil))
  2553.     (error "(kotl-mode:transpose-lines): Point or mark is at an invalid position")))
  2554.  
  2555. (defun kotl-mode:update-buffer ()
  2556.   "Update current view buffer in preparation for saving."
  2557.   (if (kview:is-p kview)
  2558.       (let ((mod-p (buffer-modified-p))
  2559.         (start (window-start)))
  2560.     (save-excursion
  2561.       (kfile:update)
  2562.       (set-buffer-modified-p mod-p))
  2563.     (set-window-start nil (max (point-min) start) t)
  2564.     nil)))
  2565.  
  2566. ;;; ------------------------------------------------------------------------
  2567.  
  2568. (defvar kotl-mode-map nil
  2569.   "Keymap containing koutliner editing and viewing commands.")
  2570. (if kotl-mode-map
  2571.     nil
  2572.   (setq kotl-mode-map
  2573.     (if (string-match "XEmacs\\|Lucid" emacs-version)
  2574.         (make-keymap)
  2575.       (copy-keymap indented-text-mode-map)))
  2576.   ;; Overload edit keys to deal with structure and labels.
  2577.   (let (local-cmd)
  2578.     (mapcar 
  2579.      (if (string-match "XEmacs\\|Lucid" emacs-version)
  2580.      ;; XEmacs
  2581.      (function
  2582.       (lambda (cmd)
  2583.         (setq local-cmd (intern-soft
  2584.                  (concat "kotl-mode:" (symbol-name cmd))))
  2585.         ;; Only bind key locally if kotl-mode local-cmd has already
  2586.         ;; been defined and cmd is a valid function.
  2587.         (if (and local-cmd (fboundp cmd))
  2588.         (progn
  2589.           ;; Make local-cmd have the same property list as cmd,
  2590.           ;; e.g. so pending-delete property is the same.
  2591.           (setplist local-cmd (symbol-plist cmd)) 
  2592.           (mapcar
  2593.            (function
  2594.             (lambda (key) (define-key kotl-mode-map key local-cmd)))
  2595.            (where-is-internal cmd))))))
  2596.        ;; GNU Emacs 19
  2597.        (function
  2598.     (lambda (cmd)
  2599.       (setq local-cmd (intern-soft
  2600.                (concat "kotl-mode:" (symbol-name cmd))))
  2601.       ;; Only bind key locally if kotl-mode local-cmd has already
  2602.       ;; been defined and cmd is a valid function.
  2603.       (if (and local-cmd (fboundp cmd))
  2604.           (progn
  2605.         ;; Make local-cmd have the same property list as cmd,
  2606.         ;; e.g. so pending-delete property is the same.
  2607.         (setplist local-cmd (symbol-plist cmd)) 
  2608.         (substitute-key-definition
  2609.          cmd local-cmd kotl-mode-map global-map))))))
  2610.      '(
  2611.        back-to-indentation
  2612.        backward-char
  2613.        backward-delete-char
  2614.        backward-delete-char-untabify
  2615.        backward-kill-word
  2616.        backward-para
  2617.        backward-paragraph
  2618.        backward-sentence
  2619.        backward-word
  2620.        beginning-of-buffer
  2621.        beginning-of-line
  2622.        copy-region-as-kill
  2623.        copy-to-register
  2624.        delete-blank-lines
  2625.        delete-backward-char
  2626.        delete-char
  2627.        delete-horizontal-space
  2628.        delete-indentation
  2629.        end-of-buffer
  2630.        end-of-line
  2631.        fill-paragraph
  2632.        fill-paragraph-or-region
  2633.        ;; cursor keys
  2634.        fkey-backward-char
  2635.        fkey-forward-char
  2636.        fkey-next-line
  2637.        fkey-previous-line
  2638.        ;;
  2639.        forward-char
  2640.        forward-word
  2641.        forward-para
  2642.        forward-paragraph
  2643.        forward-sentence
  2644.        insert-buffer
  2645.        insert-file
  2646.        insert-register
  2647.        just-one-space
  2648.        kill-word
  2649.        kill-line
  2650.        kill-region
  2651.        kill-ring-save
  2652.        kill-sentence
  2653.        mark-paragraph
  2654.        mark-whole-buffer
  2655.        newline
  2656.        newline-and-indent
  2657.        next-line
  2658.        open-line
  2659.        previous-line
  2660.        scroll-down
  2661.        scroll-up
  2662.        transpose-chars
  2663.        transpose-lines
  2664.        transpose-paragraphs
  2665.        transpose-sentences
  2666.        transpose-words
  2667.        yank
  2668.        yank-pop
  2669.        zap-to-char
  2670.        )))
  2671.  
  2672.  
  2673.   ;; kotl-mode keys
  2674.   (define-key kotl-mode-map "\C-c@"     'kotl-mode:mail-tree)
  2675.   (define-key kotl-mode-map "\C-c,"     'kotl-mode:beginning-of-cell)
  2676.   (define-key kotl-mode-map "\C-c."     'kotl-mode:end-of-cell)
  2677.   (define-key kotl-mode-map "\C-c<"     'kotl-mode:first-sibling)
  2678.   (define-key kotl-mode-map "\C-c>"     'kotl-mode:last-sibling)
  2679.   (define-key kotl-mode-map "\C-c^"     'kotl-mode:beginning-of-tree)
  2680.   (define-key kotl-mode-map "\C-c$"     'kotl-mode:end-of-tree)
  2681.   (define-key kotl-mode-map "\C-ca"     'kotl-mode:add-child)
  2682.   (define-key kotl-mode-map "\C-c\C-a"  'kotl-mode:show-all)
  2683.   (define-key kotl-mode-map "\C-c\C-b"  'kotl-mode:backward-cell)
  2684.   (define-key kotl-mode-map "\C-cc"     'kotl-mode:copy-after)
  2685.   (define-key kotl-mode-map "\C-c\C-c"  'kotl-mode:copy-before)
  2686.   (define-key kotl-mode-map "\C-c\M-c"  'kotl-mode:copy-to-buffer)
  2687.   (define-key kotl-mode-map "\C-cd"     'kotl-mode:down-level)
  2688.   (define-key kotl-mode-map "\C-c\C-d"  'kotl-mode:down-level)
  2689.   (define-key kotl-mode-map "\C-ce"     'kotl-mode:exchange-cells)
  2690.   (define-key kotl-mode-map "\C-c\C-f"  'kotl-mode:forward-cell)
  2691.   (define-key kotl-mode-map "\C-cg"     'kotl-mode:goto-cell)
  2692.   (define-key kotl-mode-map "\C-ch"     'kotl-mode:kcell-help)
  2693.   (define-key kotl-mode-map "\C-c\C-h"  'kotl-mode:hide-tree)
  2694.   (define-key kotl-mode-map "\M-\C-h"   'kotl-mode:hide-subtree)
  2695.   ;; Override this global binding for set-selective-display with a similar
  2696.   ;; function appropriate for kotl-mode.
  2697.   (define-key kotl-mode-map "\C-x$"     'kotl-mode:hide-sublevels)
  2698.   (define-key kotl-mode-map "\C-i"      'kotl-mode:demote-tree)
  2699.   (define-key kotl-mode-map "\M-\C-i"   'kotl-mode:promote-tree)
  2700.   (define-key kotl-mode-map "\C-j"      'kotl-mode:add-cell)
  2701.   (define-key kotl-mode-map "\M-j"      'kotl-mode:fill-paragraph)
  2702.   (define-key kotl-mode-map "\C-c\M-j"  'kotl-mode:fill-cell)
  2703.   (define-key kotl-mode-map "\M-\C-j"   'kotl-mode:fill-tree)
  2704.   (define-key kotl-mode-map "\C-c\C-k"  'kotl-mode:kill-tree)
  2705.   (define-key kotl-mode-map "\C-ck"     'kotl-mode:kill-contents)
  2706.   (define-key kotl-mode-map "\C-cl"     'klink:create)
  2707.   (if (eq (global-key-binding "\C-xl") 'set-fill-prefix)
  2708.       (define-key kotl-mode-map "\C-xl"     'kotl-mode:set-fill-prefix))
  2709.   (define-key kotl-mode-map "\C-c\C-l"     'kview:set-label-type)
  2710.   (define-key kotl-mode-map "\C-x."     'kotl-mode:set-fill-prefix)
  2711.   (define-key kotl-mode-map "\C-m"      'kotl-mode:newline)
  2712.   (define-key kotl-mode-map "\C-cm"     'kotl-mode:move-after)
  2713.   (define-key kotl-mode-map "\C-c\C-m"  'kotl-mode:move-before)
  2714.   (define-key kotl-mode-map "\C-c\C-n"  'kotl-mode:next-cell)
  2715.   (define-key kotl-mode-map "\C-c\C-o"  'kotl-mode:overview)
  2716.   (define-key kotl-mode-map "\C-c\C-p"  'kotl-mode:previous-cell)
  2717.   (define-key kotl-mode-map "\C-cp"     'kotl-mode:add-parent)
  2718.   (if (memq (global-key-binding "\M-q") '(fill-paragraph
  2719.                       fill-paragraph-or-region))
  2720.       (progn
  2721.     (define-key kotl-mode-map "\C-c\M-q" 'kotl-mode:fill-cell)
  2722.     (define-key kotl-mode-map "\M-\C-q"  'kotl-mode:fill-tree)))
  2723.   (define-key kotl-mode-map "\C-cs"     'kotl-mode:split-cell)
  2724.   (define-key kotl-mode-map "\C-c\C-s"  'kotl-mode:show-tree)
  2725.   (define-key kotl-mode-map "\C-c\C-\\" 'kotl-mode:show-tree)
  2726.   (define-key kotl-mode-map "\M-s"      'kotl-mode:center-line)
  2727.   (define-key kotl-mode-map "\M-S"      'kotl-mode:center-paragraph)
  2728.   (define-key kotl-mode-map "\C-ct"     'kotl-mode:transpose-cells)
  2729.   (define-key kotl-mode-map "\C-c\C-t"  'kotl-mode:top-cells)
  2730.   (define-key kotl-mode-map "\C-cu"     'kotl-mode:up-level)
  2731.   (define-key kotl-mode-map "\C-c\C-u"  'kotl-mode:up-level)
  2732.   (define-key kotl-mode-map "\C-x\C-w"  'kfile:write))
  2733.  
  2734. (provide 'kotl-mode)
  2735.