source: branches/1.11-appstore/source/cocoa-ide/hemlock/unused/archive/highlight.lisp

Last change on this file was 6569, checked in by Gary Byers, 18 years ago

Move more (currently unused, often unlikely to ever be used) stuff to an
archive directory.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.7 KB
Line 
1;;; -*- Log: hemlock.log; Package: Hemlock -*-
2;;;
3;;; **********************************************************************
4;;; This code was written as part of the CMU Common Lisp project at
5;;; Carnegie Mellon University, and has been placed in the public domain.
6;;;
7#+CMU (ext:file-comment
8 "$Header$")
9;;;
10;;; **********************************************************************
11;;;
12;;; Highlighting paren and some other good stuff.
13;;;
14;;; Written by Bill Chiles and Jim Healy.
15;;;
16
17(in-package :hemlock)
18
19
20
21
22;;;; Open parens.
23
24(defhvar "Highlight Open Parens"
25 "When non-nil, causes open parens to be displayed in a different font when
26 the cursor is directly to the right of the corresponding close paren."
27 :value nil)
28
29(defhvar "Open Paren Finder Function"
30 "Should be a function that takes a mark for input and returns either NIL
31 if the mark is not after a close paren, or two (temporary) marks
32 surrounding the corresponding open paren."
33 :value 'lisp-open-paren-finder-function)
34
35
36(defvar *open-paren-font-marks* nil
37 "The pair of font-marks surrounding the currently highlighted open-
38 paren or nil if there isn't one.")
39
40(defvar *open-paren-highlight-font* 2
41 "The index into the font-map for the open paren highlighting font.")
42
43
44;;; MAYBE-HIGHLIGHT-OPEN-PARENS is a redisplay hook that matches parens by
45;;; highlighting the corresponding open-paren after a close-paren is
46;;; typed.
47;;;
48(defun maybe-highlight-open-parens (window)
49 (declare (ignore window))
50 (when (value highlight-open-parens)
51 (if (and (value highlight-active-region) (region-active-p))
52 (kill-open-paren-font-marks)
53 (multiple-value-bind
54 (start end)
55 (funcall (value open-paren-finder-function)
56 (current-point))
57 (if (and start end)
58 (set-open-paren-font-marks start end)
59 (kill-open-paren-font-marks))))))
60;;;
61(add-hook redisplay-hook 'maybe-highlight-open-parens)
62
63(defun set-open-paren-font-marks (start end)
64 (if *open-paren-font-marks*
65 (flet ((maybe-move (dst src)
66 (unless (mark= dst src)
67 (move-font-mark dst src))))
68 (declare (inline maybe-move))
69 (maybe-move (region-start *open-paren-font-marks*) start)
70 (maybe-move (region-end *open-paren-font-marks*) end))
71 (let ((line (mark-line start)))
72 (setf *open-paren-font-marks*
73 (region
74 (font-mark line (mark-charpos start)
75 *open-paren-highlight-font*)
76 (font-mark line (mark-charpos end) 0))))))
77
78(defun kill-open-paren-font-marks ()
79 (when *open-paren-font-marks*
80 (delete-font-mark (region-start *open-paren-font-marks*))
81 (delete-font-mark (region-end *open-paren-font-marks*))
82 (setf *open-paren-font-marks* nil)))
83
84
85
86
87
88;;;; Active regions.
89
90(defvar *active-region-font-marks* nil)
91(defvar *active-region-highlight-font* 3
92 "The index into the font-map for the active region highlighting font.")
93
94
95;;; HIGHLIGHT-ACTIVE-REGION is a redisplay hook for active regions.
96;;; Since it is too hard to know how the region may have changed when it is
97;;; active and already highlighted, if it does not check out to being exactly
98;;; the same, we just delete all the font marks and make new ones. When
99;;; the current window is the echo area window, just pretend everything is
100;;; okay; this keeps the region highlighted while we're in there.
101;;;
102(defun highlight-active-region (window)
103 (unless (eq window *echo-area-window*)
104 (when (value highlight-active-region)
105 (cond ((region-active-p)
106 (cond ((not *active-region-font-marks*)
107 (set-active-region-font-marks))
108 ((check-active-region-font-marks))
109 (t (kill-active-region-font-marks)
110 (set-active-region-font-marks))))
111 (*active-region-font-marks*
112 (kill-active-region-font-marks))))))
113;;;
114(add-hook redisplay-hook 'highlight-active-region)
115
116(defun set-active-region-font-marks ()
117 (flet ((stash-a-mark (m &optional (font *active-region-highlight-font*))
118 (push (font-mark (mark-line m) (mark-charpos m) font)
119 *active-region-font-marks*)))
120 (let* ((region (current-region nil nil))
121 (start (region-start region))
122 (end (region-end region)))
123 (with-mark ((mark start))
124 (unless (mark= mark end)
125 (loop
126 (stash-a-mark mark)
127 (unless (line-offset mark 1 0) (return))
128 (when (mark>= mark end) (return)))
129 (unless (start-line-p end) (stash-a-mark end 0))))))
130 (setf *active-region-font-marks* (nreverse *active-region-font-marks*)))
131
132(defun kill-active-region-font-marks ()
133 (dolist (m *active-region-font-marks*)
134 (delete-font-mark m))
135 (setf *active-region-font-marks* nil))
136
137;;; CHECK-ACTIVE-REGION-FONT-MARKS returns t if the current region is the same
138;;; as that what is highlighted on the screen. This assumes
139;;; *active-region-font-marks* is non-nil. At the very beginning, our start
140;;; mark must not be at the end; it must be at the first font mark; and the
141;;; font marks must be in the current buffer. We don't make font marks if the
142;;; start is at the end, so if this is the case, then they just moved together.
143;;; We return nil in this case to kill all the font marks and make new ones, but
144;;; no new ones will be made.
145;;;
146;;; Sometimes we hack the font marks list and return t because we can easily
147;;; adjust the highlighting to be correct. This keeps all the font marks from
148;;; being killed and re-established. In the loop, if there are no more font
149;;; marks, we either ended a region already highlighted on the next line down,
150;;; or we have to revamp the font marks. Before returning here, we see if the
151;;; region ends one more line down at the beginning of the line. If this is
152;;; true, then the user is simply doing "Next Line" at the beginning of the
153;;; line.
154;;;
155;;; Each time through the loop we look at the top font mark, move our roving
156;;; mark down one line, and see if they compare. If they are not equal, the
157;;; region may still be the same as that highlighted on the screen. If this
158;;; is the last font mark, not at the beginning of the line, and it is at the
159;;; region's end, then this last font mark is in the middle of a line somewhere
160;;; changing the font from the highlighting font to the default font. Return
161;;; t.
162;;;
163;;; If our roving mark is not at the current font mark, but it is at or after
164;;; the end of the active region, then the end of the active region has moved
165;;; before its previous location.
166;;;
167;;; Otherwise, move on to the next font mark.
168;;;
169;;; If our roving mark never moved onto a next line, then the buffer ends on the
170;;; previous line, and the last font mark changes from the highlighting font to
171;;; the default font.
172;;;
173(defun check-active-region-font-marks ()
174 (let* ((region (current-region nil nil))
175 (end (region-end region)))
176 (with-mark ((mark (region-start region)))
177 (let ((first-active-mark (car *active-region-font-marks*))
178 (last-active-mark (last *active-region-font-marks*)))
179 (if (and (mark/= mark end)
180 (eq (current-buffer)
181 (line-buffer (mark-line first-active-mark)))
182 (mark= first-active-mark mark))
183 (let ((marks (cdr *active-region-font-marks*)))
184 (loop
185 (unless marks
186 (let ((res (and (line-offset mark 1 0)
187 (mark= mark end))))
188 (when (and (not res)
189 (line-offset mark 1 0)
190 (mark= mark end)
191 (start-line-p (car last-active-mark)))
192 (setf (cdr last-active-mark)
193 (list (font-mark (line-previous (mark-line mark))
194 0
195 *active-region-highlight-font*)))
196 (return t))
197 (return res)))
198 (let ((fmark (car marks)))
199 (if (line-offset mark 1 0)
200 (cond ((mark/= mark fmark)
201 (return (and (not (cdr marks))
202 (not (start-line-p fmark))
203 (mark= fmark end))))
204 ((mark>= mark end)
205 (return nil))
206 (t (setf marks (cdr marks))))
207
208 (return (and (not (cdr marks))
209 (not (start-line-p fmark))
210 (mark= fmark end))))))))))))
211
Note: See TracBrowser for help on using the repository browser.