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