BSD 4_3 development
[unix-history] / usr / contrib / jove / abbrev.c
CommitLineData
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
19struct 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
28static struct abbrev *A_tables[NMAJORS + 1][HASHSIZE] = {0};
29
30int AutoCaseAbbrev = 1;
31
32static unsigned int
33hash(a)
34register 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
45static
46def_abbrev(table)
47struct 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
57static struct abbrev *
58lookup(table, abbrev)
59register struct abbrev *table[HASHSIZE];
60register 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
72static
73define(table, abbrev, phrase)
74register struct abbrev *table[HASHSIZE];
75char *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
96AbbrevExpand()
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
147static 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
157static
158save_abbrevs(file)
159char *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
183static
184rest_abbrevs(file)
185char *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)
205fmterr: 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
216DefGAbbrev()
217{
218 def_abbrev(A_tables[GLOBAL]);
219}
220
221DefMAbbrev()
222{
223 def_abbrev(A_tables[curbuf->b_major]);
224}
225
226SaveAbbrevs()
227{
228 char filebuf[FILESIZE];
229
230 save_abbrevs(ask_file((char *) 0, filebuf));
231}
232
233RestAbbrevs()
234{
235 char filebuf[FILESIZE];
236
237 rest_abbrevs(ask_file((char *) 0, filebuf));
238}
239
240EditAbbrevs()
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
272BindMtoW()
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