Mercurial > hg > xemacs-beta
comparison lisp/hyperbole/kotl/kview.el @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | c53a95d3c46d |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
1 ;;!emacs | |
2 ;; | |
3 ;; FILE: kview.el | |
4 ;; SUMMARY: Display handling of koutlines. | |
5 ;; USAGE: GNU Emacs Lisp Library | |
6 ;; KEYWORDS: outlines, wp | |
7 ;; | |
8 ;; AUTHOR: Bob Weiner & Kellie Clark | |
9 ;; | |
10 ;; ORIG-DATE: 6/30/93 | |
11 ;; LAST-MOD: 2-Nov-95 at 00:52:52 by Bob Weiner | |
12 ;;; ************************************************************************ | |
13 ;;; Other required Lisp Libraries | |
14 ;;; ************************************************************************ | |
15 (mapcar 'require '(klabel kfill hypb)) | |
16 | |
17 ;;; ************************************************************************ | |
18 ;;; Public variables | |
19 ;;; ************************************************************************ | |
20 | |
21 (set-default 'kview nil) | |
22 | |
23 (defvar kview:default-blank-lines t | |
24 "*Default setting of whether to show blank lines between koutline cells. | |
25 T means show them, nil means don't show them.") | |
26 | |
27 (defvar kview:default-levels-to-show 0 | |
28 "*Default number of cell levels to show. 0 means all levels.") | |
29 | |
30 (defvar kview:default-lines-to-show 0 | |
31 "*Default number of lines per cell to show. 0 means all lines.") | |
32 | |
33 | |
34 (defvar kview:default-label-min-width 4 | |
35 "*Minimum width to which to pad labels in a kotl view. | |
36 Labels are padded with spaces on the left.") | |
37 | |
38 (defvar kview:default-label-separator " " | |
39 "*Default string of characters to insert between label and contents of a koutline cell.") | |
40 | |
41 (defvar kview:default-label-type 'alpha | |
42 "*Default label-type to use for new koutlines. | |
43 It must be one of the following symbols: | |
44 no for no labels | |
45 id for permanent idstamp labels, e.g. 001, 002, etc. | |
46 alpha for '1a2' full alphanumeric labels | |
47 legal for '1.1.2' labels | |
48 partial-alpha for partial alphanumeric labels, e.g. '2' for node '1a2' | |
49 star for multi-star labeling, e.g. '***'.") | |
50 | |
51 (defvar kview:default-level-indent 3 | |
52 "*Default number of spaces to indent each succeeding level in koutlines.") | |
53 | |
54 ;;; ************************************************************************ | |
55 ;;; Public functions | |
56 ;;; ************************************************************************ | |
57 | |
58 ;;; | |
59 ;;; kcell-view | |
60 ;;; | |
61 | |
62 (defun kcell-view:backward (&optional visible-p label-sep-len) | |
63 "Move to start of the prior cell at the same level as the current cell. | |
64 With optional VISIBLE-P, consider only visible cells. | |
65 Return t unless no such cell." | |
66 (or label-sep-len (setq label-sep-len | |
67 (kview:label-separator-length kview))) | |
68 (let ((opoint (point)) | |
69 (found) (done) | |
70 (curr-indent 0) | |
71 (start-indent (kcell-view:indent nil label-sep-len))) | |
72 (while (and (not (or found done)) | |
73 (kcell-view:previous visible-p label-sep-len)) | |
74 (if (bobp) | |
75 (progn (setq done t) | |
76 (goto-char opoint)) | |
77 (setq curr-indent (kcell-view:indent nil label-sep-len)) | |
78 (cond ((= curr-indent start-indent) | |
79 (goto-char (kcell-view:start nil label-sep-len)) | |
80 (setq found t)) | |
81 ((< curr-indent start-indent) | |
82 ;; Went past start of this tree without a match. | |
83 (setq done t) | |
84 (goto-char opoint)) | |
85 ;; else go to prior node | |
86 ))) | |
87 found)) | |
88 | |
89 (defun kview:beginning-of-actual-line () | |
90 "Go to the beginning of the current line whether collapsed or not." | |
91 (if (re-search-backward "[\n\r]" nil 'move) | |
92 (forward-char 1))) | |
93 | |
94 (defun kcell-view:cell (&optional pos) | |
95 "Return kcell at optional POS or point." | |
96 (kproperty:get (kcell-view:plist-point pos) 'kcell)) | |
97 | |
98 (defun kcell-view:child (&optional visible-p label-sep-len) | |
99 "Move to start of current cell's child. | |
100 With optional VISIBLE-P, consider only visible children. | |
101 Return t unless cell has no matching child. | |
102 Optional LABEL-SEP-LEN is the length of the separation between | |
103 a cell's label and the start of its contents." | |
104 (let* ((opoint (point)) | |
105 (prev-indent (kcell-view:indent nil label-sep-len)) | |
106 (next (kcell-view:next visible-p label-sep-len))) | |
107 (or label-sep-len (setq label-sep-len | |
108 (kview:label-separator-length kview))) | |
109 ;; Since kcell-view:next leaves point at the start of a cell, the cell's | |
110 ;; indent is just the current-column of point. | |
111 (if (and next (> (current-column) prev-indent)) | |
112 t | |
113 ;; Move back to previous point and return nil. | |
114 (goto-char opoint) | |
115 nil))) | |
116 | |
117 (defun kcell-view:child-p (&optional pos visible-p label-sep-len) | |
118 "Return t if cell at optional POS or point has a child. | |
119 With optional VISIBLE-P, consider only visible children. | |
120 Optional LABEL-SEP-LEN is the length of the separation between | |
121 a cell's label and the start of its contents." | |
122 (save-excursion | |
123 (if pos (goto-char pos)) | |
124 (kcell-view:child visible-p label-sep-len))) | |
125 | |
126 (defun kcell-view:collapse (&optional pos label-sep-len) | |
127 "Collapse cell at optional POS or point within the current view." | |
128 (save-excursion | |
129 (goto-char (kcell-view:start pos label-sep-len)) | |
130 (subst-char-in-region (point) (kcell-view:end-contents) ?\n ?\r t))) | |
131 | |
132 (defun kcell-view:collapsed-p (&optional pos label-sep-len) | |
133 "Return t if cell at optional POS or point is collapsed within the current view." | |
134 (save-excursion | |
135 (goto-char (kcell-view:start pos label-sep-len)) | |
136 (if (search-forward "\r" (kcell-view:end-contents) t) | |
137 t))) | |
138 | |
139 (defun kcell-view:contents (&optional pos) | |
140 "Return contents of cell at optional POS or point." | |
141 (save-excursion | |
142 (if pos (goto-char pos)) | |
143 (let ((indent (kcell-view:indent)) | |
144 (start (kcell-view:start)) | |
145 (end (kcell-view:end-contents))) | |
146 ;; Remove indentation from all but first line. | |
147 (hypb:replace-match-string | |
148 (concat "\\([\n\r]\\)" (make-string indent ?\ )) | |
149 (buffer-substring start end) "\\1")))) | |
150 | |
151 (defun kcell-view:create (kview cell level klabel &optional no-fill) | |
152 "Insert into KVIEW at point, CELL at LEVEL (1 = first level) with KLABEL. | |
153 Optional NO-FILL non-nil suppresses filling of cell's contents upon insertion | |
154 or movement." | |
155 (if (= (kcell:idstamp cell) 0) | |
156 nil | |
157 (or no-fill (setq no-fill (kcell:get-attr cell 'no-fill))) | |
158 (let* ((label-min-width (kview:label-min-width kview)) | |
159 (label-fmt (format "%%%ds" label-min-width)) | |
160 (label (if (string= klabel "") "" (format label-fmt klabel))) | |
161 (label-separator (if (string= klabel "") " " | |
162 (kview:label-separator kview))) | |
163 (mult-line-indent (* (1- level) (kview:level-indent kview))) | |
164 (thru-label (+ mult-line-indent label-min-width | |
165 (length label-separator))) | |
166 (old-point (point)) | |
167 (fill-prefix (make-string thru-label ?\ )) | |
168 contents | |
169 new-point) | |
170 (if no-fill (kcell:set-attr cell 'no-fill t)) | |
171 (insert fill-prefix) | |
172 (setq contents (kview:insert-contents cell nil no-fill fill-prefix)) | |
173 ;; Insert lines to separate cell from next. | |
174 (insert (if (or no-fill (equal contents "")) | |
175 "\n\n" "\n")) | |
176 (if (kview:get-attr kview 'blank-lines) | |
177 nil | |
178 ;; Make blank lines invisible. | |
179 (kproperty:put (1- (point)) (min (point) (point-max)) | |
180 '(invisible t))) | |
181 (kfile:narrow-to-kcells) | |
182 (setq new-point (point)) | |
183 (goto-char old-point) | |
184 ;; Delete leading spaces used to get fill right in first cell | |
185 ;; line. Replace it with label. | |
186 (delete-char thru-label) | |
187 (insert (format | |
188 (format "%%%ds" (- thru-label (length label-separator))) | |
189 label)) | |
190 (setq old-point (point)) | |
191 (insert label-separator) | |
192 (goto-char old-point) | |
193 ;; Add cell's attributes to the text property list at point. | |
194 (kproperty:set 'kcell cell) | |
195 (goto-char new-point)))) | |
196 | |
197 (defun kcell-view:end (&optional pos) | |
198 "Return end position of cell from optional POS or point. | |
199 Includes blank lines following cell contents." | |
200 (or pos (setq pos (point))) | |
201 (save-excursion | |
202 (or (re-search-forward "[\n\r][\n\r]" nil t) | |
203 (point-max)))) | |
204 | |
205 (defun kcell-view:end-contents (&optional pos) | |
206 "Return end position of cell contents from optional POS or point. | |
207 Excludes blank lines following cell contents." | |
208 (save-excursion | |
209 (if pos (goto-char pos)) | |
210 (goto-char (kcell-view:end)) | |
211 (skip-chars-backward "\n\r") | |
212 (point))) | |
213 | |
214 (defun kcell-view:expand (&optional pos label-sep-len) | |
215 "Expand cell at optional POS or point within the current view." | |
216 (save-excursion | |
217 (goto-char (kcell-view:start pos label-sep-len)) | |
218 (subst-char-in-region (point) (kcell-view:end-contents) ?\r ?\n t))) | |
219 | |
220 (defun kcell-view:forward (&optional visible-p label-sep-len) | |
221 "Move to start of the following cell at the same level as the current cell. | |
222 With optional VISIBLE-P, consider only visible cells. | |
223 Return t unless no such cell." | |
224 (or label-sep-len (setq label-sep-len | |
225 (kview:label-separator-length kview))) | |
226 (let ((opoint (point)) | |
227 (found) (done) | |
228 (curr-indent 0) | |
229 (start-indent (kcell-view:indent nil label-sep-len))) | |
230 (while (and (not (or found done)) | |
231 (kcell-view:next visible-p label-sep-len)) | |
232 (setq curr-indent (kcell-view:indent nil label-sep-len)) | |
233 (cond ((= curr-indent start-indent) | |
234 (goto-char (kcell-view:start nil label-sep-len)) | |
235 (setq found t)) | |
236 ((< curr-indent start-indent) | |
237 ;; Went past end of this tree without a match. | |
238 (setq done t) | |
239 (goto-char opoint)) | |
240 ;; else go to following node | |
241 )) | |
242 ;; If didn't find a match, return to original point. | |
243 (or found (goto-char opoint)) | |
244 found)) | |
245 | |
246 (defun kcell-view:get-attr (attribute &optional pos) | |
247 "Return ATTRIBUTE's value for current cell or cell at optional POS." | |
248 (save-excursion | |
249 (if pos (goto-char pos)) | |
250 (kcell:get-attr (kcell-view:cell) attribute))) | |
251 | |
252 (defun kcell-view:idstamp (&optional pos) | |
253 "Return idstamp string of cell at optional POS or point." | |
254 (save-excursion | |
255 (if pos (goto-char pos)) | |
256 (format "0%d" (kcell:idstamp (kcell-view:cell))))) | |
257 | |
258 (defun kcell-view:indent (&optional pos label-sep-len) | |
259 "Return indentation of cell at optional POS or point. | |
260 Optional LABEL-SEP-LEN is the view-specific length of the separator between a | |
261 cell's label and the start of its contents." | |
262 (+ (save-excursion | |
263 (kcell-view:to-label-end pos) | |
264 (current-column)) | |
265 (or label-sep-len (kview:label-separator-length kview)))) | |
266 | |
267 (defun kcell-view:label (&optional pos) | |
268 "Return displayed label string of cell at optional POS or point. | |
269 If labels are off, return cell's idstamp as a string." | |
270 (save-excursion | |
271 (if pos (goto-char pos)) | |
272 (let ((label-type (kview:label-type kview))) | |
273 (if (eq label-type 'no) | |
274 (kcell-view:idstamp) | |
275 (kcell-view:to-label-end) | |
276 (buffer-substring (point) (progn (skip-chars-backward "^ \t\n\r") | |
277 (point))))))) | |
278 | |
279 (defun kcell-view:level (&optional pos label-sep-len indent) | |
280 "Return cell level relative to top cell of the outline for current cell or one at optional POS. | |
281 0 = top cell level, 1 = 1st level in outline. | |
282 Optional LABEL-SEP-LEN is length of spaces between a cell label and its the | |
283 start of its body in the current view. Optional INDENT is the indentation in | |
284 characters of the cell whose level is desired." | |
285 (or label-sep-len (setq label-sep-len (kview:label-separator-length kview))) | |
286 (save-excursion | |
287 (if pos (goto-char pos)) | |
288 (/ (- (or indent (kcell-view:indent nil label-sep-len)) label-sep-len) | |
289 (kview:level-indent kview)))) | |
290 | |
291 (defun kcell-view:line (&optional pos) | |
292 "Return contents of cell line at point or optional POS as a string." | |
293 (save-excursion | |
294 (if pos (goto-char pos)) | |
295 (if (kview:valid-position-p) | |
296 (buffer-substring | |
297 (kotl-mode:beginning-of-line) | |
298 (kotl-mode:end-of-line)) | |
299 (error "(kcell-view:line): Invalid position, '%d'" (point))))) | |
300 | |
301 (defun kcell-view:next (&optional visible-p label-sep-len) | |
302 "Move to start of next cell within current view. | |
303 With optional VISIBLE-P, consider only visible cells. | |
304 Return t unless no next cell." | |
305 (let ((opoint (point)) | |
306 pos) | |
307 ;; | |
308 ;; If a subtree is collapsed, be sure we end up at the start of a visible | |
309 ;; cell rather than within an invisible one. | |
310 (if visible-p | |
311 (progn (goto-char (kcell-view:end-contents)) (end-of-line))) | |
312 (setq pos (kproperty:next-single-change (point) 'kcell)) | |
313 (if (or (null pos) | |
314 (if (goto-char pos) (kotl-mode:eobp))) | |
315 (progn (goto-char opoint) | |
316 nil) | |
317 (goto-char (kcell-view:start nil label-sep-len)) | |
318 (not (eq opoint (point)))))) | |
319 | |
320 (defun kcell-view:operate (function &optional start end) | |
321 "Invoke FUNCTION with view restricted to current cell contents. | |
322 Optional START and END are start and endpoints of cell to use." | |
323 (save-restriction | |
324 (narrow-to-region (or start (kcell-view:start)) | |
325 (or end (kcell-view:end-contents))) | |
326 (funcall function))) | |
327 | |
328 (defun kcell-view:parent (&optional visible-p label-sep-len) | |
329 "Move to start of current cell's parent within current view. | |
330 If parent is top cell, move to first cell within view and return 0. | |
331 Otherwise, return t unless optional VISIBLE-P is non-nil and the parent cell | |
332 is not part of the current view." | |
333 (or label-sep-len (setq label-sep-len (kview:label-separator-length kview))) | |
334 (let ((opoint (point)) | |
335 (parent-level (1- (kcell-view:level nil label-sep-len)))) | |
336 (if (= parent-level 0) ;; top cell | |
337 (progn (goto-char (point-min)) | |
338 (goto-char (kcell-view:start nil label-sep-len)) | |
339 0) | |
340 ;; Skip from point back past any siblings | |
341 (while (kcell-view:backward visible-p label-sep-len)) | |
342 ;; Move back to parent. | |
343 (if (kcell-view:previous visible-p label-sep-len) | |
344 t | |
345 ;; Move back to previous point and return nil. | |
346 (goto-char opoint) | |
347 nil)))) | |
348 | |
349 (defun kcell-view:previous (&optional visible-p label-sep-len) | |
350 "Move to start of previous cell within current view. | |
351 With optional VISIBLE-P, consider only visible cells. | |
352 Return t unless no previous cell." | |
353 (let ((opoint (point)) | |
354 (pos (point))) | |
355 (goto-char (kcell-view:start nil label-sep-len)) | |
356 ;; | |
357 ;; If a subtree is collapsed, be sure we end up at the start of a visible | |
358 ;; cell rather than within an invisible one. | |
359 (if visible-p | |
360 (beginning-of-line) | |
361 (if (setq pos (kproperty:previous-single-change (point) 'kcell)) | |
362 (goto-char pos))) | |
363 (if (and pos (not (kotl-mode:bobp)) | |
364 (setq pos (kproperty:previous-single-change (point) 'kcell))) | |
365 (progn (goto-char pos) | |
366 (skip-chars-backward "\n\r") | |
367 (if visible-p (beginning-of-line)) | |
368 (goto-char (kcell-view:start nil label-sep-len)) | |
369 (not (eq opoint (point)))) | |
370 ;; No previous cell exists | |
371 (goto-char opoint) | |
372 nil))) | |
373 | |
374 (defun kcell-view:plist (&optional pos) | |
375 "Return attributes associated with cell at optional POS or point." | |
376 (kcell:plist (kcell-view:cell pos))) | |
377 | |
378 (defun kcell-view:plist-point (&optional pos) | |
379 "Return buffer position of attributes associated with cell at optional POS or point." | |
380 (save-excursion (1+ (kcell-view:to-label-end pos)))) | |
381 | |
382 (defun kcell-view:to-label-end (&optional pos) | |
383 "Move point after end of current cell's label and return point." | |
384 (if pos (goto-char pos)) | |
385 (kview:end-of-actual-line) | |
386 (cond ((null kview) | |
387 (error "(kcell-view:to-label-end): Invalid kview; try {M-x kotl-mode RET} to fix it.")) | |
388 (klabel-type:changing-flag | |
389 ;; When changing from one label type to another, e.g. alpha to | |
390 ;; legal, we can't depend on the label being of the type given by | |
391 ;; the kview, so use kcell properties to find label end. | |
392 (if (kproperty:get (1- (point)) 'kcell) | |
393 nil | |
394 ;; If not at beginning of cell contents, move there. | |
395 (goto-char (kproperty:previous-single-change (point) 'kcell))) | |
396 ;; Then move to end of label via embedded kcell property. | |
397 (goto-char (kproperty:previous-single-change (point) 'kcell))) | |
398 ((funcall (kview:get-attr kview 'to-label-end)) | |
399 (point)) | |
400 (t (error "(kcell-view:to-label-end): Can't find end of current cell's label")))) | |
401 | |
402 (defun kcell-view:reference (&optional pos relative-dir) | |
403 "Return a reference to the kcell at optional POS or point for use in a link. | |
404 The reference is a string of the form, \"<kcell-file, cell-ref>\" where | |
405 cell-ref is as described in the documentation for 'kcell:ref-to-id'. | |
406 Kcell-file is made relative to optional RELATIVE-DIR before it is returned." | |
407 (format "<%s, %s=%s>" (hpath:relative-to buffer-file-name relative-dir) | |
408 (kcell-view:label pos) (kcell-view:idstamp pos))) | |
409 | |
410 (defun kcell-view:remove-attr (attribute &optional pos) | |
411 "Remove ATTRIBUTE, if any, for current cell or cell at optional POS." | |
412 (interactive "*SAttribute to remove: ") | |
413 (save-excursion | |
414 (if pos (goto-char pos)) | |
415 (let ((kcell (kcell:remove-attr (kcell-view:cell) attribute))) | |
416 (if (interactive-p) | |
417 (message "Cell <%s> now has no %s attribute." | |
418 (kcell-view:label) attribute)) | |
419 kcell))) | |
420 | |
421 (defun kcell-view:set-attr (attribute value &optional pos) | |
422 "Set ATTRIBUTE's VALUE for current cell or cell at optional POS and return the cell." | |
423 (save-excursion | |
424 (if pos (goto-char pos)) | |
425 ;; Returns kcell. | |
426 (kcell:set-attr (kcell-view:cell) attribute value))) | |
427 | |
428 (defun kcell-view:set-cell (kcell) | |
429 "Attach KCELL property to cell at point." | |
430 (save-excursion | |
431 (kcell-view:to-label-end) | |
432 (kproperty:set 'kcell kcell))) | |
433 | |
434 (defun kcell-view:sibling-p (&optional pos visible-p label-sep-len) | |
435 "Return t if cell at optional POS or point has a successor. | |
436 With optional VISIBLE-P, consider only visible siblings." | |
437 (save-excursion | |
438 (if pos (goto-char pos)) | |
439 (kcell-view:forward visible-p label-sep-len))) | |
440 | |
441 (defun kcell-view:start (&optional pos label-sep-len) | |
442 "Return start position of cell contents from optional POS or point." | |
443 (save-excursion | |
444 (+ (kcell-view:to-label-end pos) | |
445 (or label-sep-len (kview:label-separator-length kview))))) | |
446 | |
447 ;;; | |
448 ;;; kview - one view per buffer, multiple views per kotl | |
449 ;;; | |
450 | |
451 (defun kview:add-cell (klabel level &optional contents prop-list no-fill) | |
452 "Create a new cell with full KLABEL and add it at point at LEVEL within outline. | |
453 1 = first level. Optional cell CONTENTS and PROP-LIST may also be given, as | |
454 well as NO-FILL which skips filling of any CONTENTS. | |
455 Return new cell. This function does not renumber any other cells." | |
456 (let ((new-cell (kcell:create contents (kview:id-increment kview) | |
457 prop-list))) | |
458 (kcell-view:create kview new-cell level klabel no-fill) | |
459 new-cell)) | |
460 | |
461 (defun kview:buffer (kview) | |
462 "Return kview's buffer or nil if argument is not a kview." | |
463 (if (kview:is-p kview) | |
464 (get-buffer (kview:get-attr kview 'view-buffer-name)))) | |
465 | |
466 (defun kview:create (buffer-name | |
467 &optional id-counter label-type level-indent | |
468 label-separator label-min-width blank-lines | |
469 levels-to-show lines-to-show) | |
470 "Return a new kview for BUFFER-NAME. | |
471 Optional ID-COUNTER is the maximum permanent id previously given out in this | |
472 outline. Optional LABEL-TYPE, LEVEL-INDENT, LABEL-SEPARATOR, LABEL-MIN-WIDTH, | |
473 BLANK-LINES, LEVELS-TO-SHOW, and LINES-TO-SHOW may also be given, otherwise default values are used. | |
474 | |
475 See documentation of: | |
476 'kview:default-label-type' for LABEL-TYPE, | |
477 'kview:default-level-indent' for LEVEL-INDENT, | |
478 'kview:default-label-separator' for LABEL-SEPARATOR, | |
479 'kview:default-label-min-width' for LABEL-MIN-WIDTH, | |
480 'kview:default-blank-lines' for BLANK-LINES, | |
481 'kview:default-levels-to-show' for LEVELS-TO-SHOW, | |
482 'kview:default-lines-to-show' for LINES-TO-SHOW." | |
483 | |
484 (let ((buf (get-buffer buffer-name))) | |
485 (cond ((null buf) | |
486 (error "(kview:create): No such buffer, '%s'." buffer-name)) | |
487 ((or (null id-counter) (= id-counter 0)) | |
488 (setq id-counter 0)) | |
489 ((not (integerp id-counter)) | |
490 (error "(kview:create): 2nd arg, '%s', must be an integer." id-counter))) | |
491 (set-buffer buf) | |
492 (if (and (boundp 'kview) (eq (kview:buffer kview) buf)) | |
493 ;; Don't recreate view if it exists. | |
494 nil | |
495 (make-local-variable 'kview) | |
496 (setq kview | |
497 (list 'kview 'plist | |
498 (list 'view-buffer-name buffer-name | |
499 'top-cell | |
500 (kcell:create-top buffer-file-name id-counter) | |
501 'label-type (or label-type kview:default-label-type) | |
502 'label-min-width (or label-min-width | |
503 kview:default-label-min-width) | |
504 'label-separator (or label-separator | |
505 kview:default-label-separator) | |
506 'label-separator-length | |
507 (length (or label-separator | |
508 kview:default-label-separator)) | |
509 'level-indent (or level-indent | |
510 kview:default-level-indent) | |
511 'blank-lines | |
512 (or blank-lines kview:default-blank-lines) | |
513 'levels-to-show | |
514 (or levels-to-show kview:default-levels-to-show) | |
515 'lines-to-show | |
516 (or lines-to-show kview:default-lines-to-show) | |
517 ))) | |
518 (kview:set-functions (or label-type kview:default-label-type))) | |
519 kview)) | |
520 | |
521 ;;; Using this stimulates an GNU Emacs V19.19 bug in text-property handling, | |
522 ;; visible when one deletes a sibling cell and then deletes the prior cell, | |
523 ;; the following cell is left with a different idstamp and its label | |
524 ;; displays as "0". Using delete-char here would solve the problem but we | |
525 ;; suggest you upgrade to a newer version of GNU Emacs in which the bug is | |
526 ;; fixed. | |
527 (defun kview:delete-region (start end) | |
528 "Delete cells between START and END points from current view." | |
529 (delete-region start end)) | |
530 | |
531 (defun kview:end-of-actual-line () | |
532 "Go to the end of the current line whether collapsed or not." | |
533 (if (re-search-forward "[\n\r]" nil 'move) | |
534 (backward-char 1))) | |
535 | |
536 (defun kview:fill-region (start end &optional kcell justify) | |
537 "Fill region between START and END within current view. | |
538 With optional KCELL, assume START and END delimit that cell's contents. | |
539 With optional JUSTIFY, justify region as well. | |
540 Fill-prefix must be a string of spaces the length of this cell's indent, when | |
541 this function is called." | |
542 (let ((opoint (set-marker (make-marker) (point))) | |
543 (label-sep-len (kview:label-separator-length kview)) | |
544 (continue t) | |
545 prev-point) | |
546 (goto-char start) | |
547 (while continue | |
548 (if (kcell:get-attr (or kcell (kcell-view:cell)) 'no-fill) | |
549 (setq continue (kcell-view:next nil label-sep-len)) | |
550 (fill-paragraph justify t) | |
551 (setq prev-point (point)) | |
552 (forward-paragraph) | |
553 (re-search-forward "[^ \t\n\r]" nil t)) | |
554 (setq continue (and continue | |
555 (/= (point) prev-point) | |
556 (< (point) (min end (point-max)))))) | |
557 ;; Return to original point. | |
558 (goto-char opoint) | |
559 (set-marker opoint nil))) | |
560 | |
561 (cond ((and hyperb:xemacs-p (or (>= emacs-minor-version 12) | |
562 (> emacs-major-version 19))) | |
563 (defun kview:goto-cell-id (id-string) | |
564 "Move point to start of cell with idstamp ID-STRING and return t, else nil." | |
565 (let ((cell-id (string-to-int id-string)) | |
566 label-end kcell) | |
567 (setq label-end | |
568 (map-extents | |
569 (function (lambda (extent unused) | |
570 (setq kcell (extent-property extent 'kcell)) | |
571 (if (= (kcell:idstamp kcell) cell-id) | |
572 (extent-end-position extent)))) | |
573 nil nil nil nil nil 'kcell)) | |
574 (if (null label-end) | |
575 nil | |
576 (goto-char label-end) | |
577 t)))) | |
578 (hyperb:lemacs-p | |
579 (defun kview:goto-cell-id (id-string) | |
580 "Move point to start of cell with idstamp ID-STRING and return t, else nil." | |
581 (let ((cell-id (string-to-int id-string)) | |
582 label-end kcell) | |
583 (setq label-end | |
584 (map-extents | |
585 (function (lambda (extent unused) | |
586 (setq kcell (extent-property extent 'kcell)) | |
587 (and kcell (= (kcell:idstamp kcell) cell-id) | |
588 (extent-end-position extent)))))) | |
589 (if (null label-end) | |
590 nil | |
591 (goto-char label-end) | |
592 t)))) | |
593 ;; Emacs 19 | |
594 (t (defun kview:goto-cell-id (id-string) | |
595 "Move point to start of cell with idstamp ID-STRING and return t, else nil." | |
596 (let ((cell-id (string-to-int id-string)) | |
597 (opoint (point)) | |
598 pos kcell) | |
599 (goto-char (point-min)) | |
600 (while (and (setq pos | |
601 (kproperty:next-single-change (point) 'kcell)) | |
602 (goto-char pos) | |
603 (or (null (setq kcell (kproperty:get pos 'kcell))) | |
604 (/= (kcell:idstamp kcell) cell-id)))) | |
605 (if pos | |
606 (progn | |
607 (forward-char (kview:label-separator-length kview)) | |
608 t) | |
609 (goto-char opoint) | |
610 nil)))) | |
611 ) | |
612 | |
613 (defun kview:id-increment (kview) | |
614 "Return next idstamp (an integer) for KVIEW." | |
615 (let* ((top-cell (kview:get-attr kview 'top-cell)) | |
616 (counter (1+ (kcell:get-attr top-cell 'id-counter)))) | |
617 (kcell:set-attr top-cell 'id-counter counter) | |
618 counter)) | |
619 | |
620 (defun kview:idstamp-to-label (permanent-id) | |
621 "Return relative label for cell with PERMANENT-ID within current kview." | |
622 (save-excursion | |
623 (if (kotl-mode:goto-cell permanent-id) | |
624 (kcell-view:label)))) | |
625 | |
626 (defun kview:insert-contents (kcell contents no-fill fill-prefix) | |
627 "Insert KCELL's CONTENTS into view at point and fill resulting paragraphs, unless NO-FILL is non-nil. | |
628 FILL-PREFIX is the indentation string for the current cell. | |
629 If CONTENTS is nil, get contents from KCELL. Return contents inserted (this | |
630 value may differ from the value passed in.)" | |
631 (let ((start (point)) | |
632 end) | |
633 (setq contents (or contents (kcell:contents kcell) "")) | |
634 (insert contents) | |
635 ;; | |
636 ;; Delete any extra newlines at end of cell contents. | |
637 (setq end (point)) | |
638 (skip-chars-backward "\n\r") | |
639 (delete-region (point) end) | |
640 (setq end (point)) | |
641 ;; | |
642 (save-restriction | |
643 (if no-fill | |
644 ;; Insert proper indent in all but the first line which has | |
645 ;; already been indented. | |
646 (progn | |
647 (narrow-to-region start end) | |
648 (goto-char (point-min)) | |
649 (while (re-search-forward "[\n\r]" nil t) | |
650 (insert fill-prefix)) | |
651 (goto-char (point-max))) | |
652 ;; | |
653 ;; Filling cell will insert proper indent on all lines. | |
654 (if (equal contents "") | |
655 nil | |
656 (goto-char start) | |
657 (beginning-of-line) | |
658 (narrow-to-region (point) end) | |
659 ;; Add fill-prefix to all but paragraph separator lines, so | |
660 ;; filling is done properly. | |
661 (while (re-search-forward "[\n\r][^\n\r]" nil t) | |
662 (forward-char -1) (insert fill-prefix)) | |
663 (kview:fill-region start end kcell) | |
664 (goto-char (point-min)) | |
665 ;; Now add fill-prefix to paragraph separator lines. | |
666 (while (re-search-forward "[\n\r][\n\r]" nil t) | |
667 (forward-char -1) (insert fill-prefix)) | |
668 ;; | |
669 (goto-char (point-max)))))) | |
670 contents) | |
671 | |
672 (defun kview:is-p (object) | |
673 "Is OBJECT a kview?" | |
674 (if (listp object) (eq (car object) 'kview))) | |
675 | |
676 (defun kview:kotl (kview) | |
677 "Return kview's kotl object or nil if argument is not a kview." | |
678 (if (kview:is-p kview) | |
679 (kview:get-attr kview 'kotl))) | |
680 | |
681 (defun kview:label (klabel-function prev-label child-p) | |
682 "Return label string to display for current cell computed from KLABEL-FUNCTION, PREV-LABEL and CHILD-P." | |
683 (funcall klabel-function prev-label child-p)) | |
684 | |
685 (defun kview:label-function (kview) | |
686 "Return function which will return display label for current cell in KVIEW. | |
687 Function signature is: (func prev-label &optional child-p), where prev-label | |
688 is the display label of the cell preceding the current one and child-p is | |
689 non-nil if cell is to be the child of the preceding cell." | |
690 (kview:get-attr kview 'label-function)) | |
691 | |
692 (defun kview:label-min-width (kview) | |
693 "Return kview's label-min-width setting or nil if argument is not a kview. | |
694 See documentation for kview:default-label-min-width." | |
695 (if (kview:is-p kview) | |
696 (kview:get-attr kview 'label-min-width))) | |
697 | |
698 (defun kview:label-separator (kview) | |
699 "Return kview's label-separator setting or nil if argument is not a kview. | |
700 See documentation for kview:default-label-separator." | |
701 (if (kview:is-p kview) | |
702 (kview:get-attr kview 'label-separator))) | |
703 | |
704 (defun kview:label-separator-length (kview) | |
705 "Return kview's label-separator length or nil if argument is not a kview. | |
706 See documentation for kview:default-label-separator." | |
707 (kview:get-attr kview 'label-separator-length)) | |
708 | |
709 (defun kview:label-type (kview) | |
710 "Return kview's label-type setting or nil if argument is not a kview. | |
711 See documentation for kview:default-label-type." | |
712 (if (kview:is-p kview) | |
713 (kview:get-attr kview 'label-type))) | |
714 | |
715 (defun kview:level-indent (kview) | |
716 "Return kview's level-indent setting or nil if argument is not a kview. | |
717 See documentation for kview:default-level-indent." | |
718 (if (kview:is-p kview) | |
719 (kview:get-attr kview 'level-indent))) | |
720 | |
721 (defun kview:map-branch (func kview &optional first-p visible-p) | |
722 "Applies FUNC to the sibling trees from point forward within KVIEW and returns results as a list. | |
723 With optional FIRST-P non-nil, begins with first sibling in current branch. | |
724 With optional VISIBLE-P, considers only those sibling cells that are visible | |
725 in the view. | |
726 | |
727 FUNC should take one argument, the kview local variable of the current | |
728 buffer or some other kview, and should operate upon the cell at point. | |
729 | |
730 `Cell-indent' contains the indentation value of the first cell mapped when | |
731 FUNC is called so that it may test against this value. `Label-sep-len' | |
732 contains the label separator length. | |
733 | |
734 See also 'kview:map-siblings' and 'kview:map-tree'." | |
735 (save-excursion | |
736 (set-buffer (kview:buffer kview)) | |
737 (let ((results) | |
738 (label-sep-len (kview:label-separator-length kview))) | |
739 (if first-p | |
740 ;; Move back to first predecessor at same level. | |
741 (while (kcell-view:backward t label-sep-len))) | |
742 (let ((cell-indent (kcell-view:indent nil label-sep-len))) | |
743 ;; Terminate when no further cells or when reach a cell at an equal | |
744 ;; or higher level in the kotl than the first cell that we processed. | |
745 (while (and (progn (setq results (cons (funcall func kview) results)) | |
746 (kcell-view:next visible-p label-sep-len)) | |
747 (> (kcell-view:indent nil label-sep-len) cell-indent)))) | |
748 (nreverse results)))) | |
749 | |
750 (defun kview:map-siblings (func kview &optional first-p visible-p) | |
751 "Applies FUNC to the sibling cells from point forward within KVIEW and returns results as a list. | |
752 With optional FIRST-P non-nil, begins with first sibling in current branch. | |
753 With optional VISIBLE-P, considers only those sibling cells that are visible | |
754 in the view. | |
755 | |
756 FUNC should take one argument, the kview local variable of the current | |
757 buffer or some other kview, and should operate upon the cell at point. | |
758 | |
759 `Cell-indent' contains the indentation value of the first cell mapped when | |
760 FUNC is called so that it may test against this value. `Label-sep-len' | |
761 contains the label separator length. | |
762 | |
763 See also 'kview:map-branch' and 'kview:map-tree'." | |
764 (save-excursion | |
765 (set-buffer (kview:buffer kview)) | |
766 (let ((results) | |
767 (label-sep-len (kview:label-separator-length kview))) | |
768 (if first-p | |
769 ;; Move back to first predecessor at same level. | |
770 (while (kcell-view:backward t label-sep-len))) | |
771 (let ((cell-indent (kcell-view:indent nil label-sep-len))) | |
772 ;; Terminate when no further cells at same level. | |
773 (while (progn (setq results (cons (funcall func kview) results)) | |
774 (kcell-view:forward visible-p label-sep-len)))) | |
775 (nreverse results)))) | |
776 | |
777 (defun kview:map-tree (func kview &optional top-p visible-p) | |
778 "Applies FUNC to the tree starting at point within KVIEW and returns results as a list. | |
779 With optional TOP-P non-nil, maps over all of kview's cells. | |
780 With optional VISIBLE-P, considers only those cells that are visible in the | |
781 view. | |
782 | |
783 FUNC should take one argument, the kview local variable of the current | |
784 buffer or some other kview, and should operate upon the cell at point. | |
785 | |
786 `Cell-indent' contains the indentation value of the first cell mapped when | |
787 FUNC is called so that it may test against this value. `Label-sep-len' | |
788 contains the label separator length. | |
789 | |
790 See also 'kview:map-branch' and 'kview:map-siblings'." | |
791 (let ((results) | |
792 (label-sep-len (kview:label-separator-length kview))) | |
793 (save-excursion | |
794 (set-buffer (kview:buffer kview)) | |
795 (if top-p | |
796 (progn (goto-char (point-min)) | |
797 (kview:end-of-actual-line) | |
798 ;; Terminate when no further cells to process. | |
799 (while (progn | |
800 (setq results (cons (funcall func kview) results)) | |
801 (kcell-view:next visible-p label-sep-len)))) | |
802 (let ((cell-indent (kcell-view:indent nil label-sep-len))) | |
803 ;; Terminate when no further cells or when reach a cell at an equal | |
804 ;; or higher level in the kotl than the first cell that we processed. | |
805 (while (and (progn (setq results (cons (funcall func kview) results)) | |
806 (kcell-view:next visible-p label-sep-len)) | |
807 (> (kcell-view:indent nil label-sep-len) | |
808 cell-indent)))))) | |
809 (nreverse results))) | |
810 | |
811 (defun kview:move (from-start from-end to-start from-indent to-indent | |
812 &optional copy-p fill-p) | |
813 "Move tree between FROM-START and FROM-END to TO-START, changing FROM-INDENT to TO-INDENT. | |
814 Copy tree if optional COPY-P is non-nil. Refill cells if optional | |
815 FILL-P is non-nil. Leave point at TO-START." | |
816 (let ((region (buffer-substring from-start from-end)) | |
817 (new-start (set-marker (make-marker) to-start)) | |
818 collapsed-cells expr new-end space) | |
819 ;; | |
820 ;; Move or copy tree region to new location. | |
821 (or copy-p (delete-region from-start from-end)) | |
822 (goto-char new-start) | |
823 (insert region) | |
824 (setq new-end (point)) | |
825 ;; | |
826 ;; Change indentation of tree cells. | |
827 (if (/= from-indent to-indent) | |
828 (save-restriction | |
829 (narrow-to-region new-start new-end) | |
830 ;; Store list of which cells are presently collapsed. | |
831 (setq collapsed-cells | |
832 (kview:map-tree | |
833 (function (lambda (view) | |
834 ;; Use free variable label-sep-len bound in | |
835 ;; kview:map-tree for speed. | |
836 (kcell-view:collapsed-p nil label-sep-len))) | |
837 kview t)) | |
838 ;; Expand all cells. | |
839 (subst-char-in-region new-start new-end ?\r ?\n t) | |
840 ;; | |
841 (goto-char (point-min)) | |
842 (if (< from-indent to-indent) | |
843 ;; Add indent | |
844 (progn | |
845 (setq expr (make-string (1+ (- to-indent from-indent)) ?\ )) | |
846 (while (re-search-forward "^ " nil t) | |
847 (replace-match expr t t) | |
848 (forward-line 1))) | |
849 ;; Reduce indent in all but first cell lines. | |
850 (setq expr (concat "^" (make-string | |
851 (- from-indent to-indent) ?\ ))) | |
852 (while (re-search-forward expr nil t) | |
853 (replace-match "" t t) | |
854 (forward-line 1)) | |
855 ;; Reduce indent in first cell lines which may have an | |
856 ;; autonumber or other cell delimiter. | |
857 (setq space (- from-indent to-indent | |
858 (kview:label-separator-length kview) | |
859 1)) | |
860 (if (zerop space) | |
861 nil | |
862 (setq expr (concat "^" (make-string | |
863 (- from-indent to-indent | |
864 (kview:label-separator-length kview) | |
865 1) | |
866 ?\ ))) | |
867 (kview:map-tree | |
868 (function (lambda (view) | |
869 (save-excursion | |
870 (beginning-of-line) | |
871 (if (looking-at expr) | |
872 (replace-match "" t t))))) | |
873 kview t))) | |
874 ;; | |
875 (if fill-p | |
876 ;; Refill cells without no-fill attribute. | |
877 (kview:map-tree (function (lambda (view) | |
878 (kotl-mode:fill-cell nil t))) | |
879 kview t)) | |
880 ;; | |
881 ;; Collapse temporarily expanded cells. | |
882 (if (delq nil collapsed-cells) | |
883 (kview:map-tree | |
884 (function | |
885 (lambda (view) | |
886 (if (car collapsed-cells) | |
887 ;; Use free variable label-sep-len bound in | |
888 ;; kview:map-tree for speed. | |
889 (kcell-view:collapse nil label-sep-len)) | |
890 (setq collapsed-cells (cdr collapsed-cells)))) | |
891 kview t)))) | |
892 ;; | |
893 (goto-char new-start) | |
894 ;; | |
895 ;; Delete temporary markers. | |
896 (set-marker new-start nil))) | |
897 | |
898 (defun kview:set-buffer-name (kview new-name) | |
899 "Set kview's buffer name to NEW-NAME." | |
900 (if (kview:is-p kview) | |
901 (save-excursion | |
902 (let ((buf (kview:buffer kview))) | |
903 (if buf (set-buffer buf))) | |
904 (kview:set-attr kview 'view-buffer-name new-name)) | |
905 (error "(kview:set-buffer-name): Invalid kview argument"))) | |
906 | |
907 (defun kview:set-label-type (kview new-type) | |
908 "Change kview's label display type to NEW-TYPE, updating all displayed labels. | |
909 See documentation for variable, kview:default-label-type, for | |
910 valid values of NEW-TYPE." | |
911 (interactive (list kview | |
912 (let ((completion-ignore-case) | |
913 (label-type (kview:label-type kview)) | |
914 new-type-str) | |
915 (if (string= | |
916 "" | |
917 (setq new-type-str | |
918 (completing-read | |
919 (format "View label type (current = %s): " | |
920 label-type) | |
921 '(("alpha") ("legal") ("id") ("no") | |
922 ("partial-alpha") ("star")) | |
923 nil t))) | |
924 label-type | |
925 (intern new-type-str))))) | |
926 (if (not (memq new-type '(alpha legal id no partial-alpha star))) | |
927 (error "(kview:set-label-type): Invalid label type, '%s'." new-type)) | |
928 ;; Disable use of partial-alpha for now since it is broken. | |
929 (if (eq new-type 'partial-alpha) | |
930 (error "(kview:set-label-type): Partial-alpha labels don't work, choose another type")) | |
931 (let ((old-label-type (kview:label-type kview))) | |
932 (if (eq old-label-type new-type) | |
933 nil | |
934 (klabel-type:set-labels new-type) | |
935 (kview:set-attr kview 'label-type new-type) | |
936 (kview:set-functions new-type) | |
937 (kvspec:update t)))) | |
938 | |
939 (defun kview:top-cell (kview) | |
940 "Return kview's invisible top cell with idstamp 0 or nil if argument is not a kview." | |
941 (if (kview:is-p kview) | |
942 (kview:get-attr kview 'top-cell))) | |
943 | |
944 (defun kview:valid-position-p (&optional pos) | |
945 "Return non-nil iff point or optional POS is at a position where editing may occur. | |
946 The read-only positions between cells and within cell indentations are invalid." | |
947 (cond ((null pos) | |
948 (>= (current-column) (kcell-view:indent))) | |
949 ((not (integer-or-marker-p pos)) | |
950 (error "(kview:valid-position-p): Argument POS not an integer | |
951 or marker, '%s'" pos)) | |
952 ((or (< pos (point-min)) (> pos (point-max))) | |
953 (error "(kview:valid-position-p): Invalid POS argument, '%d'" | |
954 pos)) | |
955 (t (save-excursion | |
956 (goto-char pos) | |
957 (>= (current-column) (kcell-view:indent)))))) | |
958 | |
959 ;;; ************************************************************************ | |
960 ;;; Private functions | |
961 ;;; ************************************************************************ | |
962 | |
963 (defun kview:get-attr (obj attribute) | |
964 "Return the value of OBJECT's ATTRIBUTE." | |
965 (car (cdr (memq attribute (car (cdr (memq 'plist obj))))))) | |
966 | |
967 (defun kview:set-attr (obj attribute value) | |
968 "Set OBJECT's ATTRIBUTE to VALUE and return VALUE." | |
969 (let* ((plist-ptr (cdr (memq 'plist obj))) | |
970 (plist (car plist-ptr)) | |
971 (attr (memq attribute plist))) | |
972 (if attr | |
973 (setcar (cdr attr) value) | |
974 (setcar plist-ptr | |
975 (nconc (list attribute value) plist))) | |
976 value)) | |
977 | |
978 (defun kview:set-functions (label-type) | |
979 "Setup functions which handle labels of LABEL-TYPE for current view." | |
980 (kview:set-attr kview 'label-function (klabel-type:function label-type)) | |
981 (kview:set-attr kview 'label-child (klabel-type:child label-type)) | |
982 (kview:set-attr kview 'label-increment (klabel-type:increment label-type)) | |
983 (kview:set-attr kview 'label-parent (klabel-type:parent label-type)) | |
984 (kview:set-attr kview 'to-label-end (klabel-type:to-label-end label-type))) | |
985 | |
986 (defun kview:set-label-separator (label-separator &optional set-default-p) | |
987 "Set the LABEL-SEPARATOR (a string) between labels and cell contents for the current kview. | |
988 With optional prefix arg SET-DEFAULT-P, the default separator value used for | |
989 new outlines is also set to this new value." | |
990 (interactive | |
991 (progn (barf-if-buffer-read-only) | |
992 (list (if (kview:is-p kview) | |
993 (read-string | |
994 (format | |
995 "Change current%s label separator from \"%s\" to: " | |
996 (if current-prefix-arg " and default" "") | |
997 (kview:label-separator kview)))) | |
998 current-prefix-arg))) | |
999 | |
1000 (barf-if-buffer-read-only) | |
1001 (cond ((not (kview:is-p kview)) | |
1002 (error "(kview:set-label-separator): This is not a koutline")) | |
1003 ((not (stringp label-separator)) | |
1004 (error "(kview:set-label-separator): Invalid separator, \"%s\"" | |
1005 label-separator)) | |
1006 ((< (length label-separator) 2) | |
1007 (error "(kview:set-label-separator): Separator must be two or more characters, \"%s\"" | |
1008 label-separator))) | |
1009 | |
1010 (let* ((old-sep-len (kview:label-separator-length kview)) | |
1011 (sep-len (length label-separator)) | |
1012 (sep-len-increase (- sep-len old-sep-len)) | |
1013 (indent) | |
1014 (reindent-function | |
1015 (cond ((zerop sep-len-increase) | |
1016 (function (lambda ()))) | |
1017 ((> sep-len-increase 0) | |
1018 ;; Increase indent in each cell line. | |
1019 (function (lambda () | |
1020 (goto-char (point-min)) | |
1021 (setq indent (make-string | |
1022 sep-len-increase ?\ )) | |
1023 (while (re-search-forward "[^\n\r][\n\r] " nil t) | |
1024 (insert indent))))) | |
1025 (t | |
1026 ;; Decrease indent in each cell line. | |
1027 (function (lambda () | |
1028 (goto-char (point-min)) | |
1029 (setq indent | |
1030 (concat "[^\n\r][\n\r]" | |
1031 (make-string | |
1032 (- sep-len-increase) ?\ ))) | |
1033 (while (re-search-forward indent nil t) | |
1034 (delete-region | |
1035 (+ (match-beginning 0) 2) (match-end 0)))))))) | |
1036 pos) | |
1037 (save-excursion | |
1038 (goto-char (point-min)) | |
1039 (kproperty:replace-separator pos label-separator old-sep-len) | |
1040 ;; Reindent all lines in cells except the first line which has already | |
1041 ;; been done. | |
1042 (funcall reindent-function)) | |
1043 (kview:set-attr kview 'label-separator label-separator) | |
1044 (kview:set-attr kview 'label-separator-length sep-len) | |
1045 (if set-default-p | |
1046 (setq kview:default-label-separator label-separator)))) | |
1047 | |
1048 (provide 'kview) |