1 /*	SC	A Spreadsheet Calculator
2  *		Abbreviations
3  *
4  *		Chuck Martin <nrocinu@myrealbox.com>
5  *		Originally created:  November, 2001
6  *
7  *		$Revision: 7.16 $
8  */
9 
10 #include <sys/types.h>
11 #ifdef BSD42
12 #include <strings.h>
13 #else
14 #ifndef SYSIII
15 #include <string.h>
16 #endif
17 #endif
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <ctype.h>
22 #include "sc.h"
23 
24 static	struct abbrev *abbr_base;
25 
26 void
add_abbr(char * string)27 add_abbr(char *string)
28 {
29     struct abbrev *a;
30     register char *p;
31     struct abbrev *prev = NULL;
32     char *expansion;
33 
34     if (!string || *string == '\0') {
35 	if (!are_abbrevs()) {
36 	    error("No abbreviations defined");
37 	    return;
38 	} else {
39 	    FILE *f;
40 	    int pid;
41 	    char px[MAXCMD];
42 	    char *pager;
43 	    struct abbrev *a;
44 	    struct abbrev *nexta;
45 
46 	    (void) strcpy(px, "| ");
47 	    if (!(pager = getenv("PAGER")))
48 		pager = DFLT_PAGER;
49 	    (void) strcat(px, pager);
50 	    f = openfile(px, &pid, NULL);
51 	    if (!f) {
52 		error("Can't open pipe to %s", pager);
53 		return;
54 	    }
55 	    (void) fprintf(f, "\n%-15s %s\n","Abbreviation","Expanded");
56 	    if (!brokenpipe) (void) fprintf(f, "%-15s %s\n", "------------",
57 		    "--------");
58 
59 	    for (a = nexta = abbr_base; nexta; a = nexta, nexta = a->a_next)
60 		;
61 	    while (a) {
62 		(void) fprintf(f, "%-15s %s\n", a->abbr, a->exp);
63 		if (brokenpipe) return;
64 		a = a->a_prev;
65 	    }
66 	    closefile(f, pid, 0);
67 	    return;
68 	}
69     }
70 
71     if ((expansion = strchr(string, ' ')))
72 	*expansion++ = '\0';
73 
74     if (isalpha(*string) || isdigit(*string) || *string == '_') {
75 	for (p = string; *p; p++)
76 	    if (!(isalpha(*p) || isdigit(*p) || *p == '_')) {
77 		error("Invalid abbreviation: %s", string);
78 		scxfree(string);
79 		return;
80 	    }
81     } else {
82 	for (p = string; *p; p++)
83 	    if ((isalpha(*p) || isdigit(*p) || *p == '_') && *(p+1)) {
84 		error("Invalid abbreviation: %s", string);
85 		scxfree(string);
86 		return;
87 	    }
88     }
89 
90     if (expansion == NULL)
91 	if ((a = find_abbr(string, strlen(string), &prev))) {
92 	    error("abbrev \"%s %s\"", a->abbr, a->exp);
93 	    return;
94 	} else {
95 	    error("abreviation \"%s\" doesn't exist", string);
96 	    return;
97 	}
98 
99     if (find_abbr(string, strlen(string), &prev))
100 	del_abbr(string);
101 
102     a = (struct abbrev *)scxmalloc((unsigned)sizeof(struct abbrev));
103     a->abbr = string;
104     a->exp = expansion;
105 
106     if (prev) {
107 	a->a_next = prev->a_next;
108 	a->a_prev = prev;
109 	prev->a_next = a;
110 	if (a->a_next)
111 	    a->a_next->a_prev = a;
112     } else {
113 	a->a_next = abbr_base;
114 	a->a_prev = NULL;
115 	if (abbr_base)
116 	    abbr_base->a_prev = a;
117 	abbr_base = a;
118     }
119 }
120 
121 void
del_abbr(char * abbrev)122 del_abbr(char *abbrev)
123 {
124     struct abbrev *a;
125     struct abbrev **prev;
126 
127     if (!(a = find_abbr(abbrev, strlen(abbrev), prev)))
128 	return;
129 
130     if (a->a_next)
131         a->a_next->a_prev = a->a_prev;
132     if (a->a_prev)
133         a->a_prev->a_next = a->a_next;
134     else
135 	abbr_base = a->a_next;
136     scxfree((char *)(a->abbr));
137     scxfree((char *)a);
138 }
139 
140 struct abbrev *
find_abbr(char * abbrev,int len,struct abbrev ** prev)141 find_abbr(char *abbrev, int len, struct abbrev **prev)
142 {
143     struct abbrev *a;
144     int cmp;
145     int exact = TRUE;
146 
147     if (len < 0) {
148 	exact = FALSE;
149 	len = -len;
150     }
151 
152     for (a = abbr_base; a; a = a->a_next) {
153 	if ((cmp = strncmp(abbrev, a->abbr, len)) > 0)
154 	    return (NULL);
155 	*prev = a;
156 	if (cmp == 0)
157 	    if (!exact || strlen(a->abbr) == len)
158 		return (a);
159     }
160     return NULL;
161 }
162 
163 void
write_abbrevs(FILE * f)164 write_abbrevs(FILE *f)
165 {
166     register struct abbrev *a;
167     register struct abbrev *nexta;
168 
169     for (a = nexta = abbr_base; nexta; a = nexta, nexta = a->a_next) /* */ ;
170     while (a) {
171 	(void) fprintf(f, "abbrev \"%s\" \"%s\"\n", a->abbr, a->exp);
172 	a = a->a_prev;
173     }
174 }
175 
176 int
are_abbrevs()177 are_abbrevs()
178 {
179     return (abbr_base != 0);
180 }
181