comparison miscellany/less-177/mark.c @ 0:bce86c4163a3

Initial revision
author kono
date Mon, 18 Apr 2005 23:46:02 +0900
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:bce86c4163a3
1 #include "less.h"
2 #include "position.h"
3
4 extern IFILE curr_ifile;
5 extern int sc_height;
6 extern int jump_sline;
7
8 /*
9 * A mark is an ifile (input file) plus a position within the file.
10 */
11 struct mark {
12 IFILE m_ifile;
13 struct scrpos m_scrpos;
14 };
15
16 /*
17 * The table of marks.
18 * Each mark is identified by a lowercase or uppercase letter.
19 */
20 #define NMARKS (2*26) /* a-z, A-Z */
21 static struct mark marks[NMARKS];
22
23 /*
24 * Special mark for the "last mark"; addressed by the apostrophe.
25 */
26 static struct mark lmark;
27
28 /*
29 * Initialize the mark table to show no marks are set.
30 */
31 public void
32 init_mark()
33 {
34 int i;
35
36 for (i = 0; i < NMARKS; i++)
37 marks[i].m_scrpos.pos = NULL_POSITION;
38 lmark.m_scrpos.pos = NULL_POSITION;
39 }
40
41 /*
42 * See if a mark letter is valid (between a and z).
43 */
44 static struct mark *
45 getumark(c)
46 int c;
47 {
48 if (c >= 'a' && c <= 'z')
49 return (&marks[c-'a']);
50
51 if (c >= 'A' && c <= 'Z')
52 return (&marks[c-'A'+26]);
53
54 error("Invalid mark letter", NULL_PARG);
55 return (NULL);
56 }
57
58 /*
59 * Get the mark structure identified by a character.
60 * The mark struct may come either from the mark table
61 * or may be constructed on the fly for certain characters like ^, $.
62 */
63 static struct mark *
64 getmark(c)
65 int c;
66 {
67 register struct mark *m;
68 static struct mark sm;
69
70 switch (c)
71 {
72 case '^':
73 /*
74 * Beginning of the current file.
75 */
76 m = &sm;
77 m->m_scrpos.pos = ch_zero();
78 m->m_scrpos.ln = 0;
79 m->m_ifile = curr_ifile;
80 break;
81 case '$':
82 /*
83 * End of the current file.
84 */
85 if (ch_end_seek())
86 {
87 error("Cannot seek to end of file", NULL_PARG);
88 return (NULL);
89 }
90 m = &sm;
91 m->m_scrpos.pos = ch_tell();
92 m->m_scrpos.ln = sc_height-1;
93 m->m_ifile = curr_ifile;
94 break;
95 case '.':
96 /*
97 * Current position in the current file.
98 */
99 m = &sm;
100 m->m_scrpos.pos = ch_tell();
101 m->m_scrpos.ln = 0;
102 m->m_ifile = curr_ifile;
103 break;
104 case '\'':
105 /*
106 * The "last mark".
107 */
108 m = &lmark;
109 break;
110 default:
111 /*
112 * Must be a user-defined mark.
113 */
114 m = getumark(c);
115 if (m == NULL)
116 break;
117 if (m->m_scrpos.pos == NULL_POSITION)
118 {
119 error("Mark not set", NULL_PARG);
120 return (NULL);
121 }
122 break;
123 }
124 return (m);
125 }
126
127 /*
128 * Is a mark letter is invalid?
129 */
130 public int
131 badmark(c)
132 int c;
133 {
134 return (getmark(c) == NULL);
135 }
136
137 /*
138 * Set a user-defined mark.
139 */
140 public void
141 setmark(c)
142 int c;
143 {
144 register struct mark *m;
145 struct scrpos scrpos;
146
147 m = getumark(c);
148 if (m == NULL)
149 return;
150 get_scrpos(&scrpos);
151 m->m_scrpos = scrpos;
152 m->m_ifile = curr_ifile;
153 }
154
155 /*
156 * Set lmark (the mark named by the apostrophe).
157 */
158 public void
159 lastmark()
160 {
161 struct scrpos scrpos;
162
163 get_scrpos(&scrpos);
164 if (scrpos.pos == NULL_POSITION)
165 return;
166 lmark.m_scrpos = scrpos;
167 lmark.m_ifile = curr_ifile;
168 }
169
170 /*
171 * Go to a mark.
172 */
173 public void
174 gomark(c)
175 int c;
176 {
177 register struct mark *m;
178 struct scrpos scrpos;
179
180 m = getmark(c);
181 if (m == NULL)
182 return;
183
184 /*
185 * If we're trying to go to the lastmark and
186 * it has not been set to anything yet,
187 * set it to the beginning of the current file.
188 */
189 if (m == &lmark && m->m_scrpos.pos == NULL_POSITION)
190 {
191 m->m_ifile = curr_ifile;
192 m->m_scrpos.pos = ch_zero();
193 m->m_scrpos.ln = jump_sline;
194 }
195
196 /*
197 * If we're using lmark, we must save the screen position now,
198 * because if we call edit() below, lmark will change.
199 * (We save the screen position even if we're not using lmark.)
200 */
201 scrpos = m->m_scrpos;
202 if (m->m_ifile != curr_ifile)
203 {
204 /*
205 * Not in the current file; edit the correct file.
206 */
207 if (edit(get_filename(m->m_ifile), 0))
208 return;
209 }
210
211 jump_loc(scrpos.pos, scrpos.ln);
212 }
213
214 /*
215 * Return the position associated with a given mark letter.
216 *
217 * We don't return which screen line the position
218 * is associated with, but this doesn't matter much,
219 * because it's always the first non-blank line on the screen.
220 */
221 public POSITION
222 markpos(c)
223 int c;
224 {
225 register struct mark *m;
226
227 m = getmark(c);
228 if (m == NULL)
229 return (NULL_POSITION);
230
231 if (m->m_ifile != curr_ifile)
232 {
233 error("Mark not in current file", NULL_PARG);
234 return (NULL_POSITION);
235 }
236 return (m->m_scrpos.pos);
237 }