1 /* Code to handle Abbreviation Expansions
2 for MicroEMACS 4.00
3 (C)Copyright 1995 by Daniel M. Lawrence
4 */
5
6 #include <stdio.h>
7 #include "estruct.h"
8 #include "eproto.h"
9 #include "edef.h"
10 #include "elang.h"
11
ab_save(c)12 VOID PASCAL NEAR ab_save(c)
13
14 char c; /* character to add to current word buffer */
15
16 {
17 char *s; /* ptr to cycle chars */
18
19 /* only in ABBREV mode */
20 if ((curbp->b_mode & MDABBR) == 0)
21 return;
22
23 /* is the buffer full? */
24 if (ab_pos == ab_end) {
25 /* shift all the letters down one */
26 s = ab_word;
27 while (s < ab_end) {
28 *s = *(s+1);
29 ++s;
30 }
31 ab_pos--;
32 }
33
34 /* add the character */
35 *ab_pos++ = c;
36 *ab_pos = 0;
37 }
38
ab_expand()39 VOID PASCAL NEAR ab_expand()
40
41 {
42 char *exp; /* expansion of current symbol */
43 char c; /* current character to insert */
44
45 /* only in ABBREV mode, never in VIEW mode */
46 if ((curbp->b_mode & MDABBR) == 0 ||
47 (curbp->b_mode & MDVIEW) == MDVIEW)
48 return;
49
50 /* is the current buffer a symbol in the abbreviation table? */
51 if ((exp = ab_lookup(ab_word)) != NULL) {
52
53 /* backwards delete the symbol */
54 ldelete(-((long)strlen(ab_word)), FALSE);
55
56 /* and insert its expansion */
57 while (*exp) {
58
59 c = *exp++;
60
61 /*
62 * If a space was typed, fill column is defined, the
63 * argument is non-negative, wrap mode is enabled, and
64 * we are now past fill column, perform word wrap.
65 */
66 if (c == ' ' && (curwp->w_bufp->b_mode & MDWRAP) &&
67 fillcol > 0 &&
68 getccol(FALSE) > fillcol)
69 execkey(&wraphook, FALSE, 1);
70
71 linsert(1, c);
72 }
73
74 /* ring the bell */
75 if (ab_bell)
76 TTbeep();
77 }
78
79 /* reset the word buffer */
80 ab_pos = ab_word;
81 *ab_pos = 0;
82 }
83
84 /* add a new abbreviation */
85
add_abbrev(f,n)86 int PASCAL NEAR add_abbrev(f, n)
87
88 int f, n; /* numeric flag and argument */
89
90 {
91 register int status; /* status return */
92 char sym_name[MAXSYM+1];/* name of symbol to fetch */
93 char value[NSTRING]; /* value to set symbol to */
94
95 /* first get the symbol name */
96 status = mlreply(TEXT231, sym_name, MAXSYM + 1);
97 /* "Abbreviation to set: " */
98 if (status != TRUE)
99 return(status);
100
101 /* get the value for that expansion */
102 if (f == TRUE)
103 strcpy(value, int_asc(n));
104 else {
105 status = mlreply(TEXT53, &value[0], NSTRING);
106 /* "Value: " */
107 if (status == ABORT)
108 return(status);
109 }
110
111 /* and add the abbreviation to the list */
112 return(ab_insert(sym_name, value));
113 }
114
115 /* Delete a single abbreviation */
116
del_abbrev(f,n)117 int PASCAL NEAR del_abbrev(f, n)
118
119 int f, n; /* numeric flag and argument */
120
121 {
122 register int status; /* status return */
123 char sym_name[MAXSYM+1];/* name of symbol to fetch */
124
125 /* first get the symbol name */
126 status = mlreply(TEXT232, sym_name, MAXSYM + 1);
127 /* "Abbreviation to delete: " */
128 if (status != TRUE)
129 return(status);
130
131 /* and yank the abbreviation to the list */
132 return(ab_delete(sym_name));
133 }
134
135 /* Kill all abbreviations */
136
kill_abbrevs(f,n)137 int PASCAL NEAR kill_abbrevs(f, n)
138
139 int f, n; /* numeric flag and argument */
140
141 {
142 /* kill them! */
143 return(ab_clean());
144 }
145
desc_abbrevs(f,n)146 int PASCAL NEAR desc_abbrevs(f, n)
147
148 int f, n; /* numeric flag and argument */
149
150 {
151 register BUFFER *abbbuf;/* buffer to put abbreviation list into */
152 register ABBREV *cur_node;/* ptr to current abbreviation */
153 char outseq[NSTRING]; /* output buffer for keystroke sequence */
154
155 /* and get a buffer for it */
156 abbbuf = bfind(TEXT234, TRUE, BFINVS);
157 /* "Abbreviation list" */
158 if (abbbuf == NULL || bclear(abbbuf) == FALSE) {
159 mlwrite(TEXT235);
160 /* "Can not display abbreviation list" */
161 return(FALSE);
162 }
163
164 /* let us know this is in progress */
165 mlwrite(TEXT233);
166 /* "[Building Abbreviation list]" */
167
168 /* build the abbreviation list */
169 cur_node = ab_head;
170 while (cur_node != (ABBREV *)NULL) {
171
172 /* add in the abbreviation symbol name */
173 strcpy(outseq, cur_node->ab_sym);
174 pad(outseq, 20);
175
176 /* add it's expansion */
177 strncat(outseq, cur_node->ab_exp, NSTRING - 20);
178 outseq[NSTRING - 1] = 0;
179
180 /* and add it as a line into the buffer */
181 if (addline(abbbuf, outseq) != TRUE)
182 return(FALSE);
183
184 cur_node = cur_node->ab_next;
185 }
186
187 /* display the list */
188 wpopup(abbbuf);
189 mlerase(); /* clear the mode line */
190 return(TRUE);
191 }
192
193 /* insert a list of all the current abbreviations into the current buffer */
194
ins_abbrevs(f,n)195 int PASCAL NEAR ins_abbrevs(f, n)
196
197 int f, n; /* numeric flag and argument */
198
199 {
200 register ABBREV *cur_node;/* ptr to current abbreviation */
201
202 /* insert the abbreviation list in the current buffer */
203 cur_node = ab_head;
204 while (cur_node != (ABBREV *)NULL) {
205
206 /* insert the abbreviation symbol as a line */
207 if (addline(curbp, cur_node->ab_sym) != TRUE)
208 return(FALSE);
209
210 /* now a line with the expansion */
211 if (addline(curbp, cur_node->ab_exp) != TRUE)
212 return(FALSE);
213
214 cur_node = cur_node->ab_next;
215 }
216
217 return(TRUE);
218 }
219
def_abbrevs(f,n)220 int PASCAL NEAR def_abbrevs(f, n)
221
222 int f,n; /* prefix flag and argument */
223
224 {
225 register BUFFER *bp; /* ptr to buffer to dump */
226 register LINE *lp; /* ptr to current line in our buffer */
227 register llength; /* length of the current line being examined */
228 char cur_sym[MAXSYM+1]; /* current symbol being defined */
229 char cur_exp[NSTRING]; /* current expansion */
230
231 /* get the buffer to load abbreviations from */
232 bp = getdefb();
233 bp = getcbuf(TEXT236, bp ? bp->b_bname : mainbuf, TRUE);
234 /* "Define Abbreviations in buffer" */
235 if (bp == NULL)
236 return(ABORT);
237
238 /* step throught the buffer */
239 lp = lforw(bp->b_linep);
240 while (lp != bp->b_linep) {
241
242 /* get a symbol name */
243 llength = lused(lp);
244 if (llength > MAXSYM)
245 llength = MAXSYM;
246 strncpy(cur_sym, ltext(lp), llength);
247 cur_sym[llength] = 0;
248
249 /* advance to the next line in the buffer */
250 lp = lforw(lp);
251 if (lp == bp->b_linep)
252 break;
253
254 /* and an expansion for that symbol */
255 llength = lused(lp);
256 if (llength > MAXSYM)
257 llength = MAXSYM;
258 strncpy(cur_exp, ltext(lp), llength);
259 cur_exp[llength] = 0;
260
261 /* add it to the current abbreviation list */
262 ab_insert(cur_sym, cur_exp);
263
264 /* on to the next pair */
265 lp = lforw(lp);
266 }
267 }
268
ab_init()269 VOID PASCAL NEAR ab_init()
270
271 {
272 ab_head = (ABBREV *)NULL; /* abbreviation list empty */
273 ab_bell = FALSE; /* no ringing please! */
274 ab_cap = FALSE; /* don't match capatilization on expansion */
275 ab_quick = FALSE; /* no aggressive expansion */
276 ab_pos = ab_word; /* no word accumulated yet */
277 ab_end = &ab_word[NSTRING - 1]; /* ptr to detect end of this buffer */
278 }
279
280 /* ab_insert: Insert a <sym> in the abbreviation list defined as
281 <expansion>
282 */
283
ab_insert(sym,expansion)284 int PASCAL NEAR ab_insert(sym, expansion)
285
286 char *sym; /* symbol to expand */
287 char *expansion; /* string to expand to */
288
289 {
290 ABBREV *new_node; /* pointer to the newly allocated node */
291 ABBREV *cur_node; /* pointer to travel down list */
292
293 /* nothing longer than MAXSYM please */
294 if (strlen(sym) > MAXSYM)
295 sym[MAXSYM + 1] = 0;
296
297 /* is this already defined? */
298 if (ab_lookup(sym) != NULL)
299 ab_delete(sym);
300
301 /* allocate a new node to hold abbreviation */
302 new_node = (ABBREV *)room(sizeof(ABBREV)+strlen(expansion)+1);
303 if (new_node == NULL)
304 return(FALSE);
305
306 /* copy data to that node */
307 strcpy(new_node->ab_sym, sym);
308 strcpy(new_node->ab_exp, expansion);
309
310 /* do we have an empty list */
311 if (ab_head == NULL) {
312
313 ab_head = new_node;
314 new_node->ab_next = NULL;
315
316 } else {
317
318 /* does our new node go before the first */
319 if (strcmp(sym, ab_head->ab_sym) < 0) {
320
321 /* insert the node before the first node */
322 new_node->ab_next = ab_head;
323 ab_head = new_node;
324
325 } else {
326
327 /* search for the right place to insert */
328 cur_node = ab_head;
329 while (cur_node->ab_next != NULL) {
330
331 if (strcmp(sym, cur_node->ab_next->ab_sym) > 0) {
332
333 /* insert after cur_node */
334 new_node->ab_next = cur_node->ab_next;
335 cur_node->ab_next = new_node;
336 return(TRUE);
337 }
338
339 /* step to the next node */
340 cur_node = cur_node->ab_next;
341 }
342
343 /* insert after the last node */
344 cur_node->ab_next = new_node;
345 new_node->ab_next = NULL;
346 }
347 }
348
349 return(TRUE);
350 }
351
352 /* ab_lookup: look up and return the expansion of <sym>.
353 Return a NULL if it is not in the list
354 */
355
ab_lookup(sym)356 char *PASCAL NEAR ab_lookup(sym)
357
358 char *sym; /* name of the symbol to look up */
359
360 {
361
362 ABBREV *cur_node; /* ptr to look through list */
363
364 /* starting at the head, step through the list */
365 cur_node = ab_head;
366 while (cur_node != NULL) {
367
368 /* if there is a match, return the expansion */
369 if (strcmp(sym,cur_node->ab_sym) == 0) {
370 return(cur_node->ab_exp);
371 }
372 cur_node=cur_node->ab_next;
373 }
374
375 /* at the end, return NULL */
376 return(NULL);
377 }
378
379 /* ab_delete: Delete <sym> from the abbreviation list */
380
ab_delete(sym)381 int PASCAL NEAR ab_delete(sym)
382
383 char *sym;
384
385 {
386
387 ABBREV *cur_node,*previous; /* ptr to look through list */
388
389 /* start at beginning */
390 previous=NULL;
391 cur_node=ab_head;
392
393 /* step through the list */
394 while(cur_node!=NULL) {
395
396 /* if there is a match, delete the node */
397 if (previous == NULL && strcmp(sym,cur_node->ab_sym) == 0) {
398
399 /*important: resets our head pointer*/
400 ab_head=cur_node->ab_next;
401 free(cur_node);
402 return(TRUE);
403
404 } else if (strcmp(sym,cur_node->ab_sym) == 0
405 && cur_node != NULL) {
406 previous->ab_next=NULL;
407 free(cur_node);
408 return(TRUE);
409 }
410
411 /*makes sure our previous pointer steps with cur_node*/
412 previous = cur_node;
413 cur_node = cur_node->ab_next;
414 }
415
416 /* at the end, no match to delete */
417 return(FALSE);
418 }
419
ab_clean()420 int PASCAL NEAR ab_clean()
421
422 {
423
424 ABBREV *cur_node; /* ptr to look through list */
425 ABBREV *next; /* ptr to next abbreviation */
426
427 /* start at the beginning, */
428 cur_node = ab_head;
429
430 /* cycle through the list */
431 while (cur_node != (ABBREV *)NULL) {
432 next = cur_node->ab_next;
433 free(cur_node);
434 cur_node = next;
435 }
436
437 /* and re-init the list */
438 ab_head = (ABBREV *)NULL;
439 return(TRUE);
440 }
441