Mercurial > hg > Applications > mh
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 } |