root/trunk/lisp/nzwei/coma.lisp @ 258

Revision 258, 31.5 KB (checked in by rjs, 3 years ago)

Update.

Line 
1;;; Some simple ZWEI command functions.     -*- Mode:LISP; Package:ZWEI -*-
2;;; ** (c) Copyright 1980 Massachusetts Institute of Technology **
3
4;;; DEFS contains a list of all free variables used by these commands.
5;;; Any editor that wishes to use these commands must bind all of them.
6;;; When adding any to this file, or to primitives called by functions
7;;; in this file, update the list in DEFS.
8
9;;; The caller of these functions should also provide a function
10;;; called BARF, to report errors.  It should take arguments like
11;;; the &REST to FORMAT.
12
13;;; Commands in this file also use the PROMPT and TYPEIN lines
14;;; to interact with the user.  In order to keep the implementation
15;;; of these lines as flexible as possible, a very minimal interface
16;;; is defined herein.  The following functions may be used to access
17;;; these lines:
18
19;;; (PROMPT-LINE <ctl-string> . <args>)
20;;;    Do formatted output to the prompt line.  The line is cleared and homed first.
21
22;;; (PROMPT-LINE-MORE <ctl-string> . <args>)
23;;;    Do formatted output to the prompt line, without clearing and homeing.
24
25;;; (TYPEIN-LINE <ctl-string> . <args>)
26;;;    Do formatted output to the typein line.  The line is cleared and homed first.
27
28;;; (TYPEIN-LINE-MORE <ctl-string> . <args>)
29;;;    Do formatted output to the typein line, without clearing and homeing.
30
31;;; (TYPEIN-LINE-Y-OR-N-P <ctl-string> . <args>)
32;;;    Do formatted output to the typein line, and ask for a Y or N answer (see Y-OR-N-P).
33
34;;; (TYPEIN-LINE-ACTIVATE . <body>)
35;;;    This is a SPECIAL FORM.  Within the body, the blinker for the typein line
36;;;    will be on, and input from the typein line is allowed by using the
37;;;    value of TYPEIN-LINE-STREAM, on which regular stream input operations will
38;;;    work.  None of the other TYPEIN line or PROMPT line functions should
39;;;    be called while in the scope of a TYPEIN-LINE-ACTIVATE; all you may
40;;;    do is read from the stream.
41
42;;; (TYPEIN-LINE-READLINE <ctl-string> . <args>)
43;;;    Read in a line from the typein line, with editting.  The arguments
44;;;    are passed along to the prompt line.
45
46;;; (TYPEIN-LINE-READ <ctl-string> . <args>)
47;;;    Like the above, but does a READ instead of a READLINE.
48
49;;; *TYPEOUT-WINDOW*
50;;;    A larger, menu-like window for random stream output.
51
52(ENDF HEAD)
53
54(DEFCOM COM-SELF-INSERT "Inserts itself." (NM)
55  (LET ((CHAR (IN-CURRENT-FONT *LAST-COMMAND-CHAR*))
56        (POINT (POINT)))
57    (LET ((LINE (BP-LINE POINT)) (INDEX (BP-INDEX POINT)))
58         (DOTIMES (I *NUMERIC-ARG*)
59           (INSERT-MOVING POINT CHAR))
60         (SETQ *CURRENT-COMMAND-TYPE* 'SELF-INSERT)
61         (MVRETURN DIS-LINE LINE INDEX))))
62
63(DEFCOM COM-QUOTED-INSERT "Insert a quoted character" (NM)
64  (TYPEIN-LINE "~:[~*~;~A ~]~:@C: "
65               *NUMERIC-ARG-P*
66               (FORMAT-ARGUMENT *NUMERIC-ARG-P* *NUMERIC-ARG*)
67               *LAST-COMMAND-CHAR*)
68  (TYPEIN-LINE-ACTIVATE
69    (SETQ *LAST-COMMAND-CHAR* (FUNCALL STANDARD-INPUT ':TYI)))
70  (TYPEIN-LINE-MORE "~:@C" *LAST-COMMAND-CHAR*)
71  (AND (LDB-TEST %%KBD-CONTROL-META *LAST-COMMAND-CHAR*) (BARF))
72  (COM-SELF-INSERT))
73
74(DEFCOM COM-FORWARD "Move one or more characters forward.
75Move point one character forward.  With a numeric argument,
76move point that many characters forward." (KM R)
77  (LET ((POINT (POINT)))
78    (MOVE-BP POINT (OR (FORWARD-CHAR POINT *NUMERIC-ARG*) (BARF))))
79  (SET-CENTERING-FRACTION *NUMERIC-ARG*)
80  DIS-BPS)
81
82(DEFCOM COM-BACKWARD "Move one or more characters backward.
83Move point one character backward.  With a numeric argument,
84move point that many characters backward." (KM -R)
85  (LET ((POINT (POINT)))
86    (MOVE-BP POINT (OR (FORWARD-CHAR POINT (- *NUMERIC-ARG*)) (BARF))))
87  (SET-CENTERING-FRACTION (- *NUMERIC-ARG*))
88  DIS-BPS)
89
90(DEFCOM COM-GOTO-CHARACTER "Move point to the nth character in the buffer.
91With a negative argument, use the absolute value of the argument, and
92count the characters the way ITS would count them, namely,
93count newlines as two characters rather than one.  This is useful for interpreting
94character counts returned by R and BOLIO." (KM)
95  (LET ((DEST (FUNCALL (IF (MINUSP *NUMERIC-ARG*) #'FORWARD-ITS-CHAR #'FORWARD-CHAR)
96                       (INTERVAL-FIRST-BP *INTERVAL*) (ABS *NUMERIC-ARG*))))
97    (IF (NULL DEST)
98        (BARF "There are fewer than ~D. characters in the buffer." *NUMERIC-ARG*)
99        (MOVE-BP (POINT) DEST)))
100  DIS-BPS)
101
102(DEFCOM COM-DOWN-REAL-LINE "Move down vertically to next real line.
103Moves as far as possible horizontally toward the goal column for successive
104commands." (KM R)
105  (DOWN-REAL-LINE *NUMERIC-ARG*))
106
107(DEFCOM COM-UP-REAL-LINE "Move up vertically to previous real line.
108Moves as far as possible horizontally toward the goal column for successive
109commands." (KM -R)
110  (DOWN-REAL-LINE (- *NUMERIC-ARG*)))
111
112(DEFUN DOWN-REAL-LINE (N-LINES)
113  (SETQ *CURRENT-COMMAND-TYPE* 'REAL-MOVE)
114  (SET-CENTERING-FRACTION N-LINES)
115  (LET ((POINT (POINT))
116        (RET DIS-BPS))
117    (LET ((DEST (FORWARD-LINE POINT N-LINES)))
118      (COND ((NULL DEST)
119             ;; He overshot.
120             (COND ((MINUSP N-LINES)
121                    ;; He was going backwards, go to beginnning.
122                    (MOVE-BP POINT (INTERVAL-FIRST-BP *INTERVAL*))
123                    (SETQ *REAL-LINE-GOAL-XPOS* 0))
124                   ((NOT *NUMERIC-ARG-P*)
125                    ;; No argument give, going down.  Create a line.
126                    (SETQ RET DIS-TEXT)
127                    (MOVE-BP POINT (INSERT (INTERVAL-LAST-BP *INTERVAL*) #\CR))
128                    (SETQ *REAL-LINE-GOAL-XPOS* 0))
129                   (T
130                    ;; He was going forwards, go to end.
131                    (MOVE-BP POINT (INTERVAL-LAST-BP *INTERVAL*))
132                    (SETQ *REAL-LINE-GOAL-XPOS* (BP-INDENTATION POINT)))))
133            (T
134             (SETQ DEST (BP-LINE DEST))
135             (SETQ *REAL-LINE-GOAL-XPOS*
136                   (COND (*PERMANENT-REAL-LINE-GOAL-XPOS*)
137                         ((EQ *LAST-COMMAND-TYPE* 'REAL-MOVE)
138                          *REAL-LINE-GOAL-XPOS*)
139                         (T (BP-INDENTATION POINT))))
140             (LET ((INDEX (INDENTATION-INDEX DEST *REAL-LINE-GOAL-XPOS*)))
141               (MOVE-BP POINT DEST (OR INDEX (LINE-LENGTH DEST)))))))
142    RET))
143
144(DEFCOM COM-SET-GOAL-COLUMN "Sets the goal column for Up Real Line and Down Real Line." (KM)
145  (SETQ *PERMANENT-REAL-LINE-GOAL-XPOS*
146        (COND ((> *NUMERIC-ARG* 1) NIL)
147              (T (BP-INDENTATION (POINT)))))
148  DIS-NONE)
149
150(DEFCOM COM-RECENTER-WINDOW "Choose a new point in buffer to begin redisplay.
151With no argument, center point on the screen.  An argument is the
152line of the window to put point on.  Negative arguments count
153up from the bottom." (KM)
154  (OR *NUMERIC-ARG-P* (MUST-REDISPLAY *WINDOW* DIS-ALL))
155  (LET ((N-PLINES (WINDOW-N-PLINES *WINDOW*)))
156    (RECENTER-WINDOW *WINDOW*
157               ':ABSOLUTE
158               (IF *NUMERIC-ARG-P*
159                   (// (RANGE (+ *NUMERIC-ARG*
160                                 (IF (MINUSP *NUMERIC-ARG*) N-PLINES 0))
161                              0 (1- N-PLINES))
162                       (SMALL-FLOAT N-PLINES))
163                   *CENTER-FRACTION*)))
164  DIS-NONE)
165
166(DEFCOM COM-COMPLETE-REDISPLAY "Redisplay all windows." (KM)
167  (FUNCALL *TYPEOUT-WINDOW* ':DEACTIVATE)
168  (FUNCALL *MODE-LINE-WINDOW* ':REFRESH)
169  (SELECT-WINDOW *WINDOW*)
170  (DOLIST (WINDOW *WINDOW-LIST*)
171    (AND (WINDOW-READY-P WINDOW)
172         (FUNCALL (WINDOW-SHEET WINDOW) ':REFRESH)))
173  DIS-NONE)
174
175(DEFCOM COM-NEXT-SCREEN "Move down to display next screenful of text.
176With argument, move window down <arg> lines." (KM)
177  (RECENTER-WINDOW-RELATIVE *WINDOW* (IF *NUMERIC-ARG-P*
178                                         *NUMERIC-ARG*
179                                         (- (WINDOW-N-PLINES *WINDOW*) 1)))
180  DIS-NONE)
181
182(DEFCOM COM-PREVIOUS-SCREEN "Move up to display previous screenful of text.
183With argument, move window up <arg> lines." (KM)
184  (RECENTER-WINDOW-RELATIVE *WINDOW* (IF *NUMERIC-ARG-P*
185                                         (- *NUMERIC-ARG*)
186                                         (- 1 (WINDOW-N-PLINES *WINDOW*))))
187  DIS-NONE)
188
189(DEFCOM COM-NEXT-SEVERAL-SCREENS "Move down argument screenfuls of text" (KM)
190  (RECENTER-WINDOW-RELATIVE *WINDOW* (* *NUMERIC-ARG* (1- (WINDOW-N-PLINES *WINDOW*))))
191  DIS-NONE)
192
193(DEFCOM COM-PREVIOUS-SEVERAL-SCREENS "Move down argument screenfuls of text" (KM)
194  (RECENTER-WINDOW-RELATIVE *WINDOW* (* *NUMERIC-ARG* (- 1 (WINDOW-N-PLINES *WINDOW*))))
195  DIS-NONE)
196
197(DEFCOM COM-BEGINNING-OF-LINE "Move to the beginning of the line." (KM)
198  (MOVE-BP (POINT) (BEG-LINE (POINT) (1- *NUMERIC-ARG*)))
199  DIS-BPS)
200
201(DEFCOM COM-END-OF-LINE "Move to the end of the line." (KM)
202  (MOVE-BP (POINT) (END-LINE (POINT) (1- *NUMERIC-ARG*)))
203  DIS-BPS)
204
205(DEFCOM COM-MOVE-TO-SCREEN-EDGE "Jump to top or bottom of screen.
206A numeric argument specifies the screen line to go to, negative arguments count
207up from the bottom." (KM)
208  (REDISPLAY *WINDOW* ':POINT NIL NIL T)        ;Force redisplay to completion first
209  (LET ((N-PLINES (WINDOW-N-PLINES *WINDOW*)))
210    (LET ((PLINE (RANGE (IF *NUMERIC-ARG-P*
211                            (+ *NUMERIC-ARG*
212                               (IF (MINUSP *NUMERIC-ARG*) N-PLINES 0))
213                            (FIX (* *CENTER-FRACTION* N-PLINES)))
214                        0 N-PLINES)))
215      (LET ((LINE (PLINE-LINE *WINDOW* PLINE)))
216        (COND ((NOT (NULL LINE))
217               (MOVE-BP (POINT) LINE (PLINE-FROM-INDEX *WINDOW* PLINE)))
218              ((OR (NOT *NUMERIC-ARG-P*) (MINUSP *NUMERIC-ARG*))
219               (MOVE-BP (POINT) (INTERVAL-LAST-BP *INTERVAL*)))
220              (T (MOVE-BP (POINT) (INTERVAL-FIRST-BP *INTERVAL*)))))))
221  DIS-BPS)
222
223(DEFCOM COM-GOTO-BEGINNING "Go to beginning of buffer.
224With an argument from 0 to 10, goes that many tenths of the length of the buffer
225down from the beginning." (KM PUSH)
226  (COND ((NOT *NUMERIC-ARG-P*)
227         (MOVE-BP (POINT) (INTERVAL-FIRST-BP *INTERVAL*)))
228        (T (MOVE-FRACTIONALLY *NUMERIC-ARG*)))
229  DIS-BPS)
230
231(DEFCOM COM-GOTO-END "Go to the end of the buffer.
232With an argument from 0 to 10, goes that many tenths of the length of the buffer
233from the end." (KM PUSH)
234  (COND ((NOT *NUMERIC-ARG-P*)
235         (MOVE-BP (POINT) (INTERVAL-LAST-BP *INTERVAL*)))
236        (T (MOVE-FRACTIONALLY (- 10. *NUMERIC-ARG*))))
237  DIS-BPS)
238
239(DEFUN MOVE-FRACTIONALLY (TENTHS)
240  (COND ((OR (> TENTHS 10.)
241             (< TENTHS 0))
242         (BARF "The argument must be between 0 and 10."))
243        (T
244         (MOVE-BP (POINT)
245          (FORWARD-LINE
246           (INTERVAL-FIRST-BP *INTERVAL*)
247           (// (* (COUNT-LINES *INTERVAL*) TENTHS) 10.)
248           T)))))
249
250(DEFCOM COM-MARK-BEGINNING "Put the mark at the beginning of the buffer." (SM)
251  (MOVE-BP (MARK) (INTERVAL-FIRST-BP *INTERVAL*))
252  DIS-BPS)
253
254(DEFCOM COM-MARK-END "Put the mark at the end of the buffer." (SM)
255  (MOVE-BP (MARK) (INTERVAL-LAST-BP *INTERVAL*))
256  DIS-BPS)
257
258(DEFCOM COM-SWAP-POINT-AND-MARK "Exchange point and the mark." (SM)
259  (OR (EQ (BP-INTERVAL (POINT)) (BP-INTERVAL (MARK)))
260      (BARF "Point and mark not in same buffer"))
261  (SWAP-BPS (POINT) (MARK))
262  DIS-BPS)
263
264(DEFCOM COM-SET-POP-MARK "Sets or pops the mark.
265With no U's, sets the mark at the point, and pushes point onto the point pdl.
266With one U, pops the point pdl.
267With two U's, pops the point pdl and throws it away" (KM)
268  (COND (( *NUMERIC-ARG* 3)
269         (POINT-PDL-PUSH (POINT) *WINDOW* NIL NIL)
270         (MOVE-BP (MARK) (POINT))
271         (SETF (WINDOW-MARK-P *WINDOW*) T)
272         DIS-BPS)
273        (( *NUMERIC-ARG* 17)
274         (MULTIPLE-VALUE-BIND (BP PLINE)
275             (POINT-PDL-POP *WINDOW*)
276           (POINT-PDL-MOVE BP PLINE))
277         DIS-BPS)
278        (T
279         (POINT-PDL-POP *WINDOW*)
280         DIS-NONE)))
281
282(DEFCOM COM-PUSH-POP-POINT-EXPLICIT "Push or pop point onto the point pdl.
283With no argument, push point onto the point pdl.
284With an argument, exchanges point with the nth position on the stack." (KM)
285  (COND ((NOT *NUMERIC-ARG-P*)
286         (POINT-PDL-PUSH (POINT) *WINDOW* T NIL)
287         DIS-NONE)
288        (T
289         (MULTIPLE-VALUE-BIND (BP PLINE)
290              (POINT-PDL-EXCH (POINT) *WINDOW* *NUMERIC-ARG-P* *NUMERIC-ARG*)
291           (POINT-PDL-MOVE BP PLINE))
292         DIS-BPS)))
293
294(DEFCOM COM-MOVE-TO-PREVIOUS-POINT "Exchange point and top of point pdl.
295A numeric argument rotates top arg entries of the point pdl (the default
296numeric argument is 2).  An argument of 1 rotates the whole point pdl
297and a negative argument rotates the other way." ()
298  (ROTATE-POINT-PDL *WINDOW* (IF *NUMERIC-ARG-P* *NUMERIC-ARG* 2)))
299
300(DEFVAR *DEFAULT-PREVIOUS-POINT-ARG* 3)
301(DEFCOM COM-MOVE-TO-DEFAULT-PREVIOUS-POINT "Rotate the point pdl.
302A numeric argument specifies the number of entries to rotate, and sets the new default." ()
303  (AND *NUMERIC-ARG-P*
304       (SETQ *DEFAULT-PREVIOUS-POINT-ARG* *NUMERIC-ARG*))
305  (ROTATE-POINT-PDL *WINDOW* *DEFAULT-PREVIOUS-POINT-ARG*))
306
307(DEFCOM COM-INSERT-CRS "Insert one or more newlines into the buffer." ()
308  (LET ((POINT (POINT)))
309    (LET ((NEXT-LINE (LINE-NEXT (BP-LINE POINT))))
310       (COND ((AND (= (BP-INDEX POINT) (LINE-LENGTH (BP-LINE POINT)))
311                   (NOT *NUMERIC-ARG-P*)
312                   (NEQ (BP-LINE POINT) (BP-LINE (INTERVAL-LAST-BP *INTERVAL*)))
313                   (LINE-BLANK-P NEXT-LINE)
314                   (OR (EQ NEXT-LINE (BP-LINE (INTERVAL-LAST-BP *INTERVAL*)))
315                       (LINE-BLANK-P (LINE-NEXT NEXT-LINE))))
316              (DELETE-INTERVAL (BEG-OF-LINE NEXT-LINE) (END-OF-LINE NEXT-LINE))
317              (MOVE-BP POINT (BEG-OF-LINE NEXT-LINE)))
318             (T
319              (SETQ *CURRENT-COMMAND-TYPE* 'INSERT-CR)
320              (DOTIMES (I *NUMERIC-ARG*)
321                (INSERT-MOVING POINT #\CR))))))
322  DIS-TEXT)
323
324(DEFCOM COM-MAKE-ROOM "Insert one or more blank lines after point." ()
325  (DOTIMES (I *NUMERIC-ARG*)
326     (INSERT (POINT) #\CR))
327  DIS-TEXT)
328
329(DEFCOM COM-SPLIT-LINE "Move rest of current line down vertically.
330Inserts a carriage-return and updates indentation of the new line to be below the
331old position." ()
332  (LET ((POINT (POINT)))
333    (MOVE-BP POINT (FORWARD-OVER *BLANKS* POINT))
334    (LET ((IND (BP-INDENTATION POINT))
335          (BP (COPY-BP POINT)))
336      (DOTIMES (I (MAX *NUMERIC-ARG* 1))
337        (INSERT-MOVING BP #\CR))
338      (INDENT-LINE BP IND)))
339  DIS-TEXT)
340
341(DEFCOM COM-THIS-INDENTATION "Indent a new line to this point.
342With arg of 0, indent this line to here.
343With positive arg, make a new line indented like this one." ()
344  (LET ((BP1 (FORWARD-OVER *BLANKS* (IF (OR (NOT *NUMERIC-ARG-P*) (ZEROP *NUMERIC-ARG*))
345                                        (POINT) (BEG-LINE (POINT)))))
346        (BP2 (IF (ZEROP *NUMERIC-ARG*) (POINT) (INSERT-MOVING (END-LINE (POINT)) #\CR))))
347    (MOVE-BP (POINT) (INDENT-LINE BP2 (BP-INDENTATION BP1))))
348  DIS-TEXT)
349
350(DEFCOM COM-DELETE-INDENTATION "Delete CRLF and any indentation at front of line.
351Leaves a space in place of them where appropriate.  A numeric argument means move
352down a line first (killing the end of the current line)." ()
353  (LET ((POINT (POINT)))
354    (LET ((LINE (BP-LINE POINT)))
355       (COND ((AND *NUMERIC-ARG-P*
356                   (NOT (EQ LINE (BP-LINE (INTERVAL-LAST-BP *INTERVAL*)))))
357              (SETQ LINE (LINE-NEXT LINE))))
358       (MOVE-BP POINT LINE 0)
359       (COND ((NOT (EQ LINE (BP-LINE (INTERVAL-FIRST-BP *INTERVAL*))))
360              (DELETE-INTERVAL (END-OF-LINE (LINE-PREVIOUS LINE)) POINT)))
361       (DELETE-AROUND *BLANKS* POINT)
362       (LET ((SYNTAX-BEFORE (LIST-SYNTAX (BP-CHAR-BEFORE POINT))))
363         (OR (= (LIST-SYNTAX (BP-CHAR POINT)) LIST-CLOSE)
364             (= SYNTAX-BEFORE LIST-OPEN)
365             (= SYNTAX-BEFORE LIST-SINGLE-QUOTE)
366             (INSERT-MOVING POINT (IN-CURRENT-FONT #\SP))))))
367  DIS-TEXT)
368
369(DEFCOM COM-DELETE-FORWARD "Delete one or more characters forward." ()
370  (LET ((POINT (POINT)))
371    (LET ((BP (FORWARD-CHAR POINT *NUMERIC-ARG* T)))
372      (COND ((EQ (BP-LINE POINT) (BP-LINE BP))
373             (MUST-REDISPLAY *WINDOW*
374                             DIS-LINE
375                             (BP-LINE BP)
376                             (MIN (BP-INDEX BP) (BP-INDEX POINT))))
377            (T (MUST-REDISPLAY *WINDOW* DIS-TEXT)))
378      (DELETE-INTERVAL BP POINT)))
379  DIS-NONE)
380
381(DEFCOM COM-RUBOUT "Delete one or more characters backward." ()
382  (LET ((POINT (POINT)))
383    (LET ((BP (FORWARD-CHAR POINT (- *NUMERIC-ARG*) T)))
384      (COND ((EQ (BP-LINE POINT) (BP-LINE BP))
385             (MUST-REDISPLAY *WINDOW*
386                             DIS-LINE
387                             (BP-LINE BP)
388                             (MIN (BP-INDEX BP) (BP-INDEX POINT))))
389            (T (MUST-REDISPLAY *WINDOW* DIS-TEXT)))
390      (DELETE-INTERVAL BP POINT)))
391  DIS-NONE)
392
393(DEFCOM COM-KILL-LINE "Kill to end of line, or kill an end of line.
394Before a CRLF, delete the blank line, otherwise clear the line.
395With a numeric argument, always kills the specified number of lines." ()
396  (LET ((POINT (POINT)))
397    (COND ((AND (BP-= POINT (INTERVAL-LAST-BP *INTERVAL*)) (PLUSP *NUMERIC-ARG*))
398           (BARF "Attempt to kill past the end of the buffer."))
399          (T
400           (SETQ *CURRENT-COMMAND-TYPE* 'KILL)
401           (COND (*NUMERIC-ARG-P*
402                  (KILL-INTERVAL-ARG POINT
403                                     (BEG-LINE POINT *NUMERIC-ARG* T)
404                                     *NUMERIC-ARG*)
405                  DIS-TEXT)
406                 ((END-LINE-P (FORWARD-OVER *BLANKS* POINT))
407                  (KILL-INTERVAL POINT (BEG-LINE POINT 1 T) T T)
408                  DIS-TEXT)
409                 (T
410                  (KILL-INTERVAL POINT (END-LINE POINT) T T)
411                  (MVRETURN DIS-LINE (BP-LINE POINT) (BP-INDEX POINT))))))))
412
413(DEFCOM COM-CLEAR "Kill to the start of the current line." ()
414  (SETQ *CURRENT-COMMAND-TYPE* 'KILL)
415  (LET ((POINT (POINT)))
416    (LET ((BP (BEG-LINE POINT (COND (*NUMERIC-ARG-P* (- *NUMERIC-ARG*))
417                                    ((BEG-LINE-P POINT) -1)
418                                    (T 0)) T)))
419      (KILL-INTERVAL BP POINT NIL NIL)))
420  DIS-TEXT)
421
422(DEFCOM COM-SAVE-REGION "Put region on kill-ring without deleting it." ()
423  (REGION (BP1 BP2)
424    (KILL-RING-SAVE-INTERVAL BP1 BP2 T))
425  DIS-NONE)
426
427(DEFCOM COM-KILL-REGION "Kill from point to mark.
428Killed text is placed on the kill-ring for retrieval" ()
429  (AND (EQ *LAST-COMMAND-TYPE* 'YANK)                   ;By special case.
430       (SETF (WINDOW-MARK-P *WINDOW*) T))
431  (SETQ *CURRENT-COMMAND-TYPE* 'KILL)
432  (REGION (BP1 BP2)
433     (KILL-INTERVAL BP1 BP2 T T))
434  (CLEAN-POINT-PDL *WINDOW*)
435  (LET ((PDL (WINDOW-POINT-PDL *WINDOW*)))
436    (AND PDL (MOVE-BP (MARK) (CAAR PDL))))
437  DIS-TEXT)
438
439(DEFCOM COM-APPEND-NEXT-KILL "Make next kill command append text to previous one." (KM)
440  (SETQ *CURRENT-COMMAND-TYPE* 'KILL)
441  DIS-NONE)
442
443(DEFCOM COM-YANK "Re-insert the last stuff killed.
444Leaves point and mark around what is inserted.  A numeric argument means use the
445n'th most recent kill from the ring." ()
446  (OR *KILL-RING* (BARF))
447  (LET ((ARG (IF (EQ *NUMERIC-ARG-P* ':CONTROL-U) 0 (1- *NUMERIC-ARG*))))
448    (AND ( ARG (LENGTH *KILL-RING*)) (BARF))
449    (SETQ *CURRENT-COMMAND-TYPE* 'YANK)
450    (POINT-PDL-PUSH (POINT) *WINDOW* NIL NIL)
451    (LET ((BP (INSERT-THING (POINT) (NTH ARG *KILL-RING*))))
452      (COND ((EQ *NUMERIC-ARG-P* ':CONTROL-U)
453             (MOVE-BP (MARK) BP))
454            (T
455             (MOVE-BP (MARK) (POINT))
456             (MOVE-BP (POINT) BP)))))
457  DIS-TEXT)
458
459(DEFCOM COM-YANK-POP "Correct a Yank to use a previous kill.
460Deletes between point and the mark and then inserts the previous kill from the
461kill-ring, which is pulled to the top, so that successive attempts cycle through
462the whole ring." ()
463  ;; Need not check for MARK-P, by special case.
464  (OR (EQ *LAST-COMMAND-TYPE* 'YANK) (BARF))
465  (SETQ *CURRENT-COMMAND-TYPE* 'YANK)
466  (DELETE-INTERVAL (POINT) (MARK))
467  (OR (ZEROP *NUMERIC-ARG*)
468      (MOVE-BP (POINT) (INSERT-THING (POINT) (KILL-RING-POP (1- *NUMERIC-ARG*)))))
469  DIS-TEXT)
470
471;;; If there was no arg at all, *NUMERIC-ARG-P* is NIL and *NUMERIC-ARG* is 1.
472;;; If user just typed -, then *NUMERIC-ARG-P* is :SIGN and *NUMERIC-ARG* is -1.
473;;; If numeric arg commands were typed, *NUMERIC-ARG-P* is :DIGITS and
474;;; *NUMERIC-ARG* is the number.
475;;; Note that - does not toggle negativeness, it turns it on.
476
477(DEFCOM COM-QUADRUPLE-NUMERIC-ARG "Multiply the next command's numeric argument by 4." ()
478  (SETQ *NUMERIC-ARG* (* *NUMERIC-ARG* 4)
479        *NUMERIC-ARG-P* ':CONTROL-U)
480  ':ARGUMENT)
481
482(DEFCOM COM-NUMBERS "part of the next command's numeric argument." ()
483  (LET ((FLAG NIL)
484        (DIGIT (- (LDB %%KBD-CHAR *LAST-COMMAND-CHAR*) #/0)))
485    (COND ((< *NUMERIC-ARG* 0)
486           (SETQ FLAG T)
487           (SETQ *NUMERIC-ARG* (MINUS *NUMERIC-ARG*))))
488    (SETQ *NUMERIC-ARG*
489          (IF (EQ *NUMERIC-ARG-P* ':DIGITS)
490              (+ (* 10. *NUMERIC-ARG*) DIGIT)
491              DIGIT))
492    (AND FLAG (SETQ *NUMERIC-ARG* (MINUS *NUMERIC-ARG*))))
493  (SETQ *NUMERIC-ARG-P* ':DIGITS)
494  ':ARGUMENT)
495
496(DEFCOM COM-NEGATE-NUMERIC-ARG "Negate the next command's numeric argument." ()
497  (SETQ *NUMERIC-ARG* (MINUS (ABS *NUMERIC-ARG*))
498        *NUMERIC-ARG-P* ':SIGN)
499  ':ARGUMENT)
500
501(DEFCOM COM-SIMPLE-EXCHANGE-CHARACTERS
502        "Interchange the characters before and after the cursor.
503With a positive argument it interchanges the characters before and
504after the cursor, moves right, and repeats the specified number of
505times, dragging the character to the left of the cursor right.  With a
506negative argument, it interchanges the two characters to the left of
507the cursor, moves between them, and repeats the specified number of
508times, exactly undoing the positive argument form.  With a zero
509argument, it interchanges the characters at point and mark." ()
510  (EXCHANGE-SUBR 'FORWARD-CHAR *NUMERIC-ARG*)
511  DIS-TEXT)
512
513(DEFCOM COM-EXCHANGE-CHARACTERS "Interchange the characters before and after the cursor.
514With a positive argument it interchanges the characters before and
515after the cursor, moves right, and repeats the specified number of
516times, dragging the character to the left of the cursor right.  With a
517negative argument, it interchanges the two characters to the left of
518the cursor, moves between them, and repeats the specified number of
519times, exactly undoing the positive argument form.  With a zero
520argument, it interchanges the characters at point and mark.
521No argument is like an argument of 1, except at the end of a line
522the previous two characters are interchanged." ()
523  (COND ((AND (NOT *NUMERIC-ARG-P*)
524              (= (BP-CHAR (POINT)) #\CR))
525         (MOVE-BP (POINT) (OR (FORWARD-CHAR (POINT) -1) (BARF)))))
526  (EXCHANGE-SUBR 'FORWARD-CHAR *NUMERIC-ARG*)
527  DIS-TEXT)
528
529(DEFCOM COM-EXCHANGE-WORDS "Interchange the words before and after the cursor.
530With a positive argument it interchanges the words before and
531after the cursor, moves right, and repeats the specified number of
532times, dragging the word to the left of the cursor right.  With a
533negative argument, it interchanges the two words to the left of
534the cursor, moves between them, and repeats the specified number of
535times, exactly undoing the positive argument form.  With a zero
536argument, it interchanges the words at point and mark." ()
537  (EXCHANGE-SUBR 'FORWARD-WORD *NUMERIC-ARG*)
538  DIS-TEXT)
539
540(DEFCOM COM-EXCHANGE-LINES "Interchange the lines before and after the cursor.
541With a positive argument it interchanges the lines before and
542after the cursor, moves right, and repeats the specified number of
543times, dragging the word to the left of the cursor right.  With a
544negative argument, it interchanges the two lines to the left of
545the cursor, moves between them, and repeats the specified number of
546times, exactly undoing the positive argument form.  With a zero
547argument, it interchanges the lines at point and mark." ()
548  (EXCHANGE-SUBR 'FORWARD-LINE *NUMERIC-ARG*)
549  DIS-TEXT)
550
551(DEFCOM COM-EXCHANGE-SEXPS "Interchange the S-expressions before and after the cursor.
552With a positive argument it interchanges the S-expressions before and
553after the cursor, moves right, and repeats the specified number of
554times, dragging the S-expression to the left of the cursor right.  With a
555negative argument, it interchanges the two S-expressions to the left of
556the cursor, moves between them, and repeats the specified number of
557times, exactly undoing the positive argument form.  With a zero
558argument, it interchanges the S-expressions at point and mark." ()
559  (EXCHANGE-SUBR 'FORWARD-SEXP *NUMERIC-ARG*)
560  DIS-TEXT)
561
562;;;This is arranged so weirdly because it runs out of local variables as just one function.
563(DEFUN EXCHANGE-SUBR (FN N &AUX BUF1 BUF2)
564  (COND ((PLUSP N)
565         (EXCHANGE-SUBR-1 FN N))
566        ((MINUSP N)
567         (EXCHANGE-SUBR-2 FN N))
568        (T
569         (REGION (BP1 BP2)
570           (WITH-BP (BP1 (OR (FUNCALL FN BP1 1) (BARF)) ':NORMAL)
571             (OR (SETQ BP1 (FUNCALL FN BP1 -1)) (BARF))
572             (WITH-BP (BP2 (OR (FUNCALL FN BP2 1) (BARF)) ':NORMAL)
573               (WITH-BP (BP3 (OR (FUNCALL FN BP2 -1) (BARF)) ':NORMAL)
574                 (WITH-BP (BP4 (OR (FUNCALL FN BP1 1) (BARF)) ':NORMAL)
575                          (SETQ BUF1 (COPY-INTERVAL BP3 BP2 T)
576                                BUF2 (COPY-INTERVAL BP1 BP4 T))
577                          (DELETE-INTERVAL BP3 BP2 T)
578                          (MOVE-BP (POINT) (INSERT-INTERVAL BP3 BUF2))
579                          (MOVE-BP (MARK) (INSERT-INTERVAL BP4 BUF1))
580                          (DELETE-INTERVAL BP1 BP4 T))))))
581           (SETQ *MARK-STAYS* T))))
582
583(DEFUN EXCHANGE-SUBR-1 (FN N &AUX BP1 BUF1 BUF2)
584  (OR (SETQ BP1 (FUNCALL FN (POINT) 1)) (BARF))
585  (OR (SETQ BP1 (FUNCALL FN BP1 -2)) (BARF))
586  (OR (SETQ BP1 (FUNCALL FN BP1 1)) (BARF))
587  (MOVE-BP (POINT) BP1)
588  (DOTIMES (I N)
589    (WITH-BP (BP1 (POINT) ':NORMAL)
590      (WITH-BP (BP2 (OR (FUNCALL FN BP1 1) (BARF)) ':NORMAL)
591        (WITH-BP (BP3 (OR (FUNCALL FN BP2 -1) (BARF)) ':NORMAL)
592          (WITH-BP (BP4 (OR (FUNCALL FN BP1 -1) (BARF)) ':NORMAL)
593                   (SETQ BUF1 (COPY-INTERVAL BP3 BP2 T)
594                         BUF2 (COPY-INTERVAL BP4 BP1 T))
595                   (DELETE-INTERVAL BP3 BP2 T)
596                   (MOVE-BP (POINT) (INSERT-INTERVAL BP3 BUF2))
597                   (INSERT-INTERVAL BP1 BUF1)
598                   (DELETE-INTERVAL BP4 BP1 T)))))))
599
600(DEFUN EXCHANGE-SUBR-2 (FN N &AUX BP1 BUF1 BUF2)
601  (OR (SETQ BP1 (FUNCALL FN (POINT) -1)) (BARF))
602  (OR (SETQ BP1 (FUNCALL FN BP1 1)) (BARF))
603  (MOVE-BP (POINT) BP1)
604  (DO I 0 (1- I) ( I N)
605      (WITH-BP (BP1 (POINT) ':NORMAL)
606        (WITH-BP (BP2 (OR (FUNCALL FN BP1 -2) (BARF)) ':NORMAL)
607          (WITH-BP (BP3 (OR (FUNCALL FN BP2 1) (BARF)) ':NORMAL)
608            (WITH-BP (BP4 (OR (FUNCALL FN BP1 -1) (BARF)) ':NORMAL)
609              (SETQ BUF1 (COPY-INTERVAL BP2 BP3 T)
610                    BUF2 (COPY-INTERVAL BP4 BP1 T))
611              (DELETE-INTERVAL BP4 BP1 T)
612              (INSERT-INTERVAL BP4 BUF1)
613              (MOVE-BP (POINT) (INSERT-INTERVAL BP3 BUF2))
614              (DELETE-INTERVAL BP2 BP3 T)))))))
615
616(DEFCOM COM-EXCHANGE-REGIONS "Exchange region delimited by point and last three marks." (KM)
617  (OR (WINDOW-MARK-P *WINDOW*) (BARF "There is no region"))     ;Avoid accidental lossage
618  (LET ((POINT (POINT)) (MARK (MARK))
619        BP1 BP2 BP3 BP4)
620    (OR (BP-= MARK (CAAR (WINDOW-POINT-PDL *WINDOW*)))
621        (BARF "Mark not at the same place as top of point pdl"))
622    (SETQ BP1 POINT
623          BP2 (POINT-PDL-POP *WINDOW*)
624          BP3 (POINT-PDL-POP *WINDOW*)
625          BP4 (POINT-PDL-POP *WINDOW*))
626    (LET ((LIST (LIST BP1 BP2 BP3 BP4)))
627      (SETQ LIST (SORT LIST #'(LAMBDA (BP1 BP2)
628                                (AND (EQ (BP-INTERVAL BP1) (BP-INTERVAL BP2))
629                                     (BP-< BP1 BP2)))))
630      (SETQ BP1 (FIRST LIST)
631            BP2 (SECOND LIST)
632            BP3 (THIRD LIST)
633            BP4 (FOURTH LIST)))
634    (OR (AND (EQ (BP-INTERVAL BP1) (BP-INTERVAL BP2))
635             (EQ (BP-INTERVAL BP3) (BP-INTERVAL BP4)))
636        (BARF "Regions are not both within single buffers"))
637    (WITH-BP (NBP2 (INSERT-INTERVAL BP2 BP3 BP4 T) ':NORMAL)
638      (WITH-BP (NBP4 (INSERT-INTERVAL BP4 BP1 BP2 T) ':NORMAL)
639        (DELETE-INTERVAL BP1 BP2 T)
640        (DELETE-INTERVAL BP3 BP4 T)
641        (POINT-PDL-PUSH BP1 *WINDOW*)   
642        (POINT-PDL-PUSH NBP2 *WINDOW*)
643        (POINT-PDL-PUSH BP3 *WINDOW*)
644        (MOVE-BP MARK BP3)
645        (MOVE-BP POINT NBP4))))
646  DIS-TEXT)
647
648(DEFUN REVERSE-SUBR (FN N &AUX (POINT (POINT)) BP-LIST)
649  (AND (MINUSP N)
650       (SETQ POINT (FUNCALL FN POINT N)
651             N (- N)))
652  (UNWIND-PROTECT
653    (PROGN
654      (DO ((I 0 (1+ I))
655           (START-BP POINT END-BP)
656           (END-BP))
657          (( I N)
658           (UNDO-SAVE POINT END-BP T "Reverse"))
659        (SETQ END-BP (OR (FUNCALL FN START-BP 1) (BARF))
660              START-BP (OR (FUNCALL FN END-BP -1) (BARF)))
661        (PUSH (LIST (COPY-BP START-BP ':MOVES) (COPY-BP END-BP ':NORMAL)) BP-LIST))
662      (DO ((I 0 (1+ I))
663           (N (// N 2))
664           (LIST-FROM-THE-RIGHT BP-LIST (CDR LIST-FROM-THE-RIGHT))
665           (LIST-FROM-THE-LEFT (REVERSE BP-LIST) (CDR LIST-FROM-THE-LEFT))
666           (RIGHT-START-BP) (RIGHT-END-BP)
667           (LEFT-START-BP) (LEFT-END-BP))
668          (( I N))
669        (SETQ LEFT-START-BP (CAAR LIST-FROM-THE-LEFT)
670              LEFT-END-BP (CADAR LIST-FROM-THE-LEFT))
671        (SETQ RIGHT-START-BP (CAAR LIST-FROM-THE-RIGHT)
672              RIGHT-END-BP (CADAR LIST-FROM-THE-RIGHT))
673        (INSERT-INTERVAL LEFT-START-BP RIGHT-START-BP RIGHT-END-BP T)
674        (DELETE-INTERVAL RIGHT-START-BP RIGHT-END-BP T)
675        (INSERT-INTERVAL RIGHT-START-BP LEFT-START-BP LEFT-END-BP T)
676        (DELETE-INTERVAL LEFT-START-BP LEFT-END-BP T)))
677    (DO ((BPS BP-LIST (CDR BPS)))
678        ((NULL BPS))
679      (FLUSH-BP (CAAR BPS))
680      (FLUSH-BP (CADAR BPS)))))
681
682(DEFCOM COM-REVERSE-LINES "Reverse the order of the specified number of lines" ()
683  (REVERSE-SUBR 'FORWARD-LINE *NUMERIC-ARG*)
684  DIS-TEXT)
685
686(DEFUN KILL-COMMAND-INTERNAL (FUNCTION ARG &AUX (POINT (POINT)))
687  (KILL-INTERVAL-ARG POINT
688                     (OR (FUNCALL FUNCTION POINT ARG) (BARF))
689                     ARG)
690  (SETQ *CURRENT-COMMAND-TYPE* 'KILL)
691  (MOVE-BP (MARK) POINT)
692  DIS-TEXT)
693
694(DEFCOM COM-FORWARD-WORD "Move one or more words forward." (KM)
695  (MOVE-BP (POINT)
696           (OR (FORWARD-WORD (POINT) *NUMERIC-ARG*) (BARF)))
697  DIS-BPS)
698
699(DEFCOM COM-BACKWARD-WORD "Move one or more words backward." (KM)
700  (MOVE-BP (POINT)
701           (OR (FORWARD-WORD (POINT) (- *NUMERIC-ARG*)) (BARF)))
702  DIS-BPS)
703
704(DEFCOM COM-KILL-WORD "Kill one or more words forward." ()
705  (KILL-COMMAND-INTERNAL #'FORWARD-WORD *NUMERIC-ARG*))
706
707(DEFCOM COM-BACKWARD-KILL-WORD "Kill one or more words backward." ()
708  (KILL-COMMAND-INTERNAL #'FORWARD-WORD (- *NUMERIC-ARG*)))
709
710(DEFCOM COM-MARK-WORD "Set mark one or more words from point." (SM)
711  (MOVE-BP (MARK) (OR (FORWARD-WORD (POINT) *NUMERIC-ARG*) (BARF)))
712  DIS-BPS)
713
714(DEFCOM COM-FORWARD-SEXP "Move one or more s-expressions forward." (KM)
715  (MOVE-BP (POINT)
716           (OR (FORWARD-SEXP (POINT) *NUMERIC-ARG*) (BARF)))
717  DIS-BPS)
718
719(DEFCOM COM-FORWARD-SEXP-NO-UP "Move forward one or more s-expressions,
720but never over an unbalanced ).  Useful in keyboard macros, e.g." (KM)
721  (MOVE-BP (POINT)
722           (OR (FORWARD-SEXP (POINT) *NUMERIC-ARG* NIL 0 NIL T T) (BARF)))
723  DIS-BPS)
724
725(DEFCOM COM-BACKWARD-SEXP-NO-UP "Move backward one or more s-expressions,
726but never over an unbalanced (.  Useful in keyboard macros, e.g." (KM)
727  (MOVE-BP (POINT)
728           (OR (FORWARD-SEXP (POINT) (- *NUMERIC-ARG*) NIL 0 NIL T T) (BARF)))
729  DIS-BPS)
730
731(DEFCOM COM-FORWARD-LIST "Move one or more lists forward." (KM)
732  (MOVE-BP (POINT)
733           (OR (FORWARD-LIST (POINT) *NUMERIC-ARG*) (BARF)))
734  DIS-BPS)
735
736(DEFCOM COM-BACKWARD-SEXP "Move one or more s-expressions backward." (KM)
737  (MOVE-BP (POINT)
738           (OR (FORWARD-SEXP (POINT) (- *NUMERIC-ARG*)) (BARF)))
739  DIS-BPS)
740
741(DEFCOM COM-BACKWARD-LIST "Move one or more lists backwards." (KM)
742  (MOVE-BP (POINT)
743           (OR (FORWARD-LIST (POINT) (- *NUMERIC-ARG*)) (BARF)))
744  DIS-BPS)
745
746(DEFCOM COM-KILL-SEXP "Kill one or more s-expressions forward." ()
747  (KILL-COMMAND-INTERNAL #'FORWARD-SEXP *NUMERIC-ARG*))
748
749(DEFCOM COM-KILL-SEXP-NO-UP "Kill one or more s-expressions forward." ()
750  (KILL-COMMAND-INTERNAL #'FORWARD-SEXP-NO-UP *NUMERIC-ARG*))
751
752(DEFCOM COM-BACKWARD-KILL-SEXP "Kill one or more s-expressions backward." ()
753  (KILL-COMMAND-INTERNAL #'FORWARD-SEXP (- *NUMERIC-ARG*)))
754
755(DEFCOM COM-BACKWARD-KILL-SEXP-NO-UP "Kill one or more s-expressions backward." ()
756  (KILL-COMMAND-INTERNAL #'FORWARD-SEXP-NO-UP (- *NUMERIC-ARG*)))
757
758(DEFCOM COM-MARK-SEXP "Set mark one or more s-expressions from point." (SM)
759  (MOVE-BP (MARK) (OR (FORWARD-SEXP (POINT) *NUMERIC-ARG*) (BARF)))
760  DIS-BPS)
761
762(DEFCOM COM-FORWARD-UP-LIST "Move up one level of list structure, forward.
763Also, if called inside of a string, moves up out of that string." (KM)
764  (LET ((BP (IF (LISP-BP-SYNTACTIC-CONTEXT (POINT))
765                (FORWARD-UP-STRING (POINT) (MINUSP *NUMERIC-ARG*))
766                (FORWARD-SEXP (POINT) *NUMERIC-ARG* NIL 1))))
767    (OR BP (BARF))
768    (MOVE-BP (POINT) BP))
769  DIS-BPS)
770
771(DEFCOM COM-BACKWARD-UP-LIST "Move up one level of list structure, backward.
772Also, if called inside of a string, moves back up out of that string." (KM)
773  (LET ((BP (IF (LISP-BP-SYNTACTIC-CONTEXT (POINT))
774                (FORWARD-UP-STRING (POINT) (NOT (MINUSP *NUMERIC-ARG*)))
775                (FORWARD-SEXP (POINT) (- *NUMERIC-ARG*) NIL 1))))
776    (OR BP (BARF))
777    (MOVE-BP (POINT) BP))
778  DIS-BPS)
779
780(DEFCOM COM-BEGINNING-OF-DEFUN "Go to the beginning of the current defun." (KM)
781  (LET ((BP (OR (FORWARD-DEFUN (POINT) (- *NUMERIC-ARG*)) (BARF))))
782    (POINT-PDL-PUSH (POINT) *WINDOW*)
783    (MOVE-BP (POINT) BP))
784  DIS-BPS)
785
786(DEFCOM COM-END-OF-DEFUN "Go to the end of the current defun." (KM)
787  (LET ((BP (FORWARD-DEFUN (POINT) -1 T)))              ;Go to front of defun.
788    (OR (SETQ BP (FORWARD-LIST BP)) (BARF))             ; and forward over it.
789    (SETQ BP (BEG-LINE BP 1 T))
790    (COND ((OR (BP-< BP (POINT))                      ;If we were between defuns,
791               (AND (PLUSP *NUMERIC-ARG*) (BP-= BP (POINT))))
792           (SETQ BP (END-LINE BP -1 T))
793           (OR (SETQ BP (FORWARD-LIST (FORWARD-DEFUN BP 1 T)))
794               (BARF))
795           (SETQ BP (BEG-LINE BP 1 T))))              ; then move ahead another.
796    (POINT-PDL-PUSH (POINT) *WINDOW*)
797    (OR (= *NUMERIC-ARG* 1)
798        (SETQ BP (BEG-LINE (FORWARD-LIST (FORWARD-DEFUN BP (1- *NUMERIC-ARG*) T) 1 T) 1 T)))
799    (MOVE-BP (POINT) BP))
800  DIS-BPS)
801
802(DEFCOM COM-DOWN-LIST "Move down one or more levels of list structure." (KM)
803  (MOVE-BP (POINT)
804           (OR (FORWARD-LIST (POINT) 1 NIL (- *NUMERIC-ARG*) T) (BARF)))
805  DIS-BPS)
806
807(DEFCOM COM-BACKWARD-DOWN-LIST
808        "Move down one or more levels of list structure, backward." (KM)
809  (MOVE-BP (POINT)
810           (OR (FORWARD-LIST (POINT) -1 NIL (- *NUMERIC-ARG*) T T) (BARF)))
811  DIS-BPS)
Note: See TracBrowser for help on using the browser.