Commit | Line | Data |
---|---|---|
b346cbec C |
1 | /************************************************************************* |
2 | * This program is copyright (C) 1985, 1986 by Jonathan Payne. It is * | |
3 | * provided to you without charge for use only on a licensed Unix * | |
4 | * system. You may copy JOVE provided that this notice is included with * | |
5 | * the copy. You may not sell copies of this program or versions * | |
6 | * modified for use on microcomputer systems, unless the copies are * | |
7 | * included with a Unix system distribution and the source is provided. * | |
8 | *************************************************************************/ | |
9 | ||
10 | #include "jove.h" | |
11 | ||
12 | #ifdef ABBREV | |
13 | ||
14 | #include "io.h" | |
15 | #include "ctype.h" | |
16 | ||
17 | #define HASHSIZE 20 | |
18 | ||
19 | struct abbrev { | |
20 | unsigned int a_hash; | |
21 | char *a_abbrev, | |
22 | *a_phrase; | |
23 | struct abbrev *a_next; | |
24 | data_obj *a_cmdhook; | |
25 | }; | |
26 | ||
27 | #define GLOBAL NMAJORS | |
28 | static struct abbrev *A_tables[NMAJORS + 1][HASHSIZE] = {0}; | |
29 | ||
30 | int AutoCaseAbbrev = 1; | |
31 | ||
32 | static unsigned int | |
33 | hash(a) | |
34 | register char *a; | |
35 | { | |
36 | register unsigned int hashval = 0; | |
37 | register int c; | |
38 | ||
39 | while (c = *a++) | |
40 | hashval = (hashval << 2) + c; | |
41 | ||
42 | return hashval; | |
43 | } | |
44 | ||
45 | static | |
46 | def_abbrev(table) | |
47 | struct abbrev *table[HASHSIZE]; | |
48 | { | |
49 | char abbrev[100], | |
50 | phrase[100]; | |
51 | ||
52 | strcpy(abbrev, ask((char *) 0, "abbrev: ")); | |
53 | strcpy(phrase, ask((char *) 0, "abbrev: %s phrase: ", abbrev)); | |
54 | define(table, abbrev, phrase); | |
55 | } | |
56 | ||
57 | static struct abbrev * | |
58 | lookup(table, abbrev) | |
59 | register struct abbrev *table[HASHSIZE]; | |
60 | register char *abbrev; | |
61 | { | |
62 | register struct abbrev *ap; | |
63 | unsigned int h; | |
64 | ||
65 | h = hash(abbrev); | |
66 | for (ap = table[h % HASHSIZE]; ap; ap = ap->a_next) | |
67 | if (ap->a_hash == h && strcmp(ap->a_abbrev, abbrev) == 0) | |
68 | break; | |
69 | return ap; | |
70 | } | |
71 | ||
72 | static | |
73 | define(table, abbrev, phrase) | |
74 | register struct abbrev *table[HASHSIZE]; | |
75 | char *abbrev, | |
76 | *phrase; | |
77 | { | |
78 | register struct abbrev *ap; | |
79 | ||
80 | ap = lookup(table, abbrev); | |
81 | if (ap == 0) { | |
82 | register unsigned int h = hash(abbrev); | |
83 | ||
84 | ap = (struct abbrev *) emalloc(sizeof *ap); | |
85 | ap->a_hash = h; | |
86 | ap->a_abbrev = copystr(abbrev); | |
87 | h %= HASHSIZE; | |
88 | ap->a_next = table[h]; | |
89 | ap->a_cmdhook = 0; | |
90 | table[h] = ap; | |
91 | } else | |
92 | free(ap->a_phrase); | |
93 | ap->a_phrase = copystr(phrase); | |
94 | } | |
95 | ||
96 | AbbrevExpand() | |
97 | { | |
98 | Bufpos point; | |
99 | char wordbuf[100]; | |
100 | register char *wp = wordbuf, | |
101 | *cp; | |
102 | register int c; | |
103 | int UC_count = 0; | |
104 | struct abbrev *ap; | |
105 | ||
106 | DOTsave(&point); | |
107 | exp = 1; | |
108 | WITH_TABLE(curbuf->b_major) | |
109 | BackWord(); | |
110 | while (curchar < point.p_char && ismword(c = linebuf[curchar])) { | |
111 | if (AutoCaseAbbrev) { | |
112 | if (isupper(c)) { | |
113 | UC_count++; | |
114 | c = tolower(c); | |
115 | } | |
116 | } | |
117 | ||
118 | *wp++ = c; | |
119 | curchar++; | |
120 | } | |
121 | *wp = '\0'; | |
122 | END_TABLE(); | |
123 | ||
124 | if ((ap = lookup(A_tables[curbuf->b_major], wordbuf)) == 0 && | |
125 | (ap = lookup(A_tables[GLOBAL], wordbuf)) == 0) { | |
126 | SetDot(&point); | |
127 | return; | |
128 | } | |
129 | DoTimes(DelPChar(), (wp - wordbuf)); | |
130 | ||
131 | for (cp = ap->a_phrase; c = *cp; ) { | |
132 | if (AutoCaseAbbrev) { | |
133 | Insert(islower(c) && UC_count && | |
134 | (cp == ap->a_phrase || (UC_count > 1 && (*(cp - 1) == ' '))) ? | |
135 | toupper(c) : c); | |
136 | } | |
137 | else { | |
138 | Insert(c); | |
139 | } | |
140 | cp++; | |
141 | } | |
142 | ||
143 | if (ap->a_cmdhook != 0) | |
144 | ExecCmd(ap->a_cmdhook); | |
145 | } | |
146 | ||
147 | static char *mode_names[NMAJORS + 1] = { | |
148 | "Fundamental", | |
149 | "Text Mode", | |
150 | "C Mode", | |
151 | #ifdef LISP | |
152 | "Lisp Mode", | |
153 | #endif | |
154 | "Global" | |
155 | }; | |
156 | ||
157 | static | |
158 | save_abbrevs(file) | |
159 | char *file; | |
160 | { | |
161 | File *fp; | |
162 | struct abbrev *ap, | |
163 | **tp; | |
164 | char buf[LBSIZE]; | |
165 | int i, | |
166 | count = 0; | |
167 | ||
168 | fp = open_file(file, buf, F_WRITE, COMPLAIN, QUIET); | |
169 | for (i = 0; i <= GLOBAL; i++) { | |
170 | fprintf(fp, "------%s abbrevs------\n", mode_names[i]); | |
171 | for (tp = A_tables[i]; tp < &A_tables[i][HASHSIZE]; tp++) | |
172 | for (ap = *tp; ap; ap = ap->a_next) { | |
173 | fprintf(fp, "%s:%s\n", | |
174 | ap->a_abbrev, | |
175 | ap->a_phrase); | |
176 | count++; | |
177 | } | |
178 | } | |
179 | f_close(fp); | |
180 | add_mess(" %d written.", count); | |
181 | } | |
182 | ||
183 | static | |
184 | rest_abbrevs(file) | |
185 | char *file; | |
186 | { | |
187 | int eof = 0, | |
188 | mode = -1, /* Will be ++'d immediately */ | |
189 | lnum = 0; | |
190 | char *phrase_p; | |
191 | File *fp; | |
192 | char buf[LBSIZE]; | |
193 | ||
194 | fp = open_file(file, buf, F_READ, COMPLAIN, QUIET); | |
195 | while (mode <= GLOBAL) { | |
196 | eof = f_gets(fp, genbuf, LBSIZE); | |
197 | if (eof || genbuf[0] == '\0') | |
198 | break; | |
199 | lnum++; | |
200 | if (strncmp(genbuf, "------", 6) == 0) { | |
201 | mode++; | |
202 | continue; | |
203 | } | |
204 | if (mode == -1) | |
205 | fmterr: complain("Abbrev. format error, line %d.", file, lnum); | |
206 | phrase_p = index(genbuf, ':'); | |
207 | if (phrase_p == 0) | |
208 | goto fmterr; | |
209 | *phrase_p++ = '\0'; /* Null terminate the abbrev. */ | |
210 | define(A_tables[mode], genbuf, phrase_p); | |
211 | } | |
212 | f_close(fp); | |
213 | message(NullStr); | |
214 | } | |
215 | ||
216 | DefGAbbrev() | |
217 | { | |
218 | def_abbrev(A_tables[GLOBAL]); | |
219 | } | |
220 | ||
221 | DefMAbbrev() | |
222 | { | |
223 | def_abbrev(A_tables[curbuf->b_major]); | |
224 | } | |
225 | ||
226 | SaveAbbrevs() | |
227 | { | |
228 | char filebuf[FILESIZE]; | |
229 | ||
230 | save_abbrevs(ask_file((char *) 0, filebuf)); | |
231 | } | |
232 | ||
233 | RestAbbrevs() | |
234 | { | |
235 | char filebuf[FILESIZE]; | |
236 | ||
237 | rest_abbrevs(ask_file((char *) 0, filebuf)); | |
238 | } | |
239 | ||
240 | EditAbbrevs() | |
241 | { | |
242 | char *tname = "jove_wam.$$$", | |
243 | *EditName = "Abbreviation Edit"; | |
244 | Buffer *obuf = curbuf, | |
245 | *ebuf; | |
246 | ||
247 | if (ebuf = buf_exists(EditName)) { | |
248 | if (ebuf->b_type != B_SCRATCH) | |
249 | confirm("Over-write buffer %b?", ebuf); | |
250 | } | |
251 | SetBuf(ebuf = do_select(curwind, EditName)); | |
252 | ebuf->b_type = B_SCRATCH; | |
253 | initlist(ebuf); | |
254 | /* Empty buffer. Save the definitions to a tmp file | |
255 | and read them into this buffer so we can edit them. */ | |
256 | save_abbrevs(tname); | |
257 | read_file(tname, NO); | |
258 | message("[Edit definitions and then type C-X C-C]"); | |
259 | Recur(); /* We edit them ... now */ | |
260 | /* RESetBuf in case we deleted the buffer while we were editing. */ | |
261 | SetBuf(ebuf = do_select(curwind, EditName)); | |
262 | if (IsModified(ebuf)) { | |
263 | SetBuf(ebuf); | |
264 | file_write(tname, 0); | |
265 | rest_abbrevs(tname); | |
266 | unmodify(); | |
267 | } | |
268 | (void) unlink(tname); | |
269 | SetBuf(do_select(curwind, obuf->b_name)); | |
270 | } | |
271 | ||
272 | BindMtoW() | |
273 | { | |
274 | struct abbrev *ap; | |
275 | char *word; | |
276 | data_obj *hook; | |
277 | ||
278 | word = ask((char *) 0, "Word: "); | |
279 | ||
280 | if ((ap = lookup(A_tables[curbuf->b_major], word)) == 0 && | |
281 | (ap = lookup(A_tables[GLOBAL], word)) == 0) | |
282 | complain("%s: unknown abbrev.", word); | |
283 | ||
284 | hook = findmac("Macro: "); | |
285 | if (hook == 0) | |
286 | complain("[Undefined macro]"); | |
287 | ap->a_cmdhook = hook; | |
288 | } | |
289 | ||
290 | #endif ABBREV |