include seq.h in each file, now, only included in a few places
[nvi.git] / common / seq.c
blobce6ef826d7902911b8ff67498a77fef1a63e7849
1 /*-
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
5 * %sccs.include.redist.c%
6 */
8 #ifndef lint
9 static char sccsid[] = "$Id: seq.c,v 8.14 1993/11/18 08:17:20 bostic Exp $ (Berkeley) $Date: 1993/11/18 08:17:20 $";
10 #endif /* not lint */
12 #include <sys/types.h>
14 #include <ctype.h>
15 #include <errno.h>
16 #include <stdlib.h>
17 #include <string.h>
19 #include "vi.h"
20 #include "excmd.h"
23 * seq_set --
24 * Internal version to enter a sequence.
26 int
27 seq_set(sp, name, input, output, stype, userdef)
28 SCR *sp;
29 char *name, *input, *output;
30 enum seqtype stype;
31 int userdef;
33 SEQ *lastqp, *qp;
34 int ilen;
35 char *p;
37 #if defined(DEBUG) && 0
38 TRACE(sp, "seq_set: name {%s} input {%s} output {%s}\n",
39 name ? name : "", input, output);
40 #endif
42 * Find any previous occurrence, and replace the output field.
43 * Q's are sorted by character and length within that character.
45 ilen = strlen(input);
46 for (lastqp = NULL, qp = sp->gp->seqq.lh_first;
47 qp != NULL; lastqp = qp, qp = qp->q.le_next) {
48 if (qp->input[0] < input[0])
49 continue;
50 if (qp->input[0] > input[0] || qp->ilen > ilen)
51 break;
52 if (qp->ilen == ilen &&
53 stype == qp->stype && !strcmp(qp->input, input)) {
54 if ((p = strdup(output)) == NULL)
55 goto mem1;
56 FREE(qp->output, qp->olen);
57 qp->olen = strlen(output);
58 qp->output = p;
59 return (0);
63 /* Allocate and initialize space. */
64 if ((qp = malloc(sizeof(SEQ))) == NULL)
65 goto mem1;
66 if (name == NULL)
67 qp->name = NULL;
68 else if ((qp->name = strdup(name)) == NULL)
69 goto mem2;
70 if ((qp->input = strdup(input)) == NULL)
71 goto mem3;
72 if ((qp->output = strdup(output)) == NULL) {
73 FREE(qp->input, ilen);
74 mem3: if (qp->name != NULL)
75 FREE(qp->name, strlen(qp->name) + 1);
76 mem2: FREE(qp, sizeof(SEQ));
77 mem1: msgq(sp, M_SYSERR, NULL);
78 return (1);
81 qp->stype = stype;
82 qp->ilen = ilen;
83 qp->olen = strlen(output);
84 qp->flags = userdef ? S_USERDEF : 0;
86 /* Link into the chain. */
87 if (lastqp == NULL) {
88 LIST_INSERT_HEAD(&sp->gp->seqq, qp, q);
89 } else {
90 LIST_INSERT_AFTER(lastqp, qp, q);
93 /* Set the fast lookup bit. */
94 bit_set(sp->gp->seqb, qp->input[0]);
96 return (0);
100 * seq_delete --
101 * Delete a sequence.
104 seq_delete(sp, input, stype)
105 SCR *sp;
106 char *input;
107 enum seqtype stype;
109 SEQ *qp;
111 if ((qp = seq_find(sp, input, strlen(input), stype, NULL)) == NULL)
112 return (1);
114 LIST_REMOVE(qp, q);
115 if (qp->name != NULL)
116 FREE(qp->name, strlen(qp->name) + 1);
117 FREE(qp->input, qp->ilen);
118 FREE(qp->output, qp->olen);
119 FREE(qp, sizeof(SEQ));
120 return (0);
124 * seq_find --
125 * Search the sequence list for a match to a buffer, if ispartial
126 * isn't NULL, partial matches count.
128 SEQ *
129 seq_find(sp, input, ilen, stype, ispartialp)
130 SCR *sp;
131 char *input;
132 size_t ilen;
133 enum seqtype stype;
134 int *ispartialp;
136 SEQ *qp;
138 if (ispartialp)
139 *ispartialp = 0;
141 if (ispartialp)
142 for (qp = sp->gp->seqq.lh_first;
143 qp != NULL; qp = qp->q.le_next) {
144 if (qp->input[0] < input[0])
145 continue;
146 if (qp->input[0] > input[0])
147 break;
148 if (stype != qp->stype)
149 continue;
151 * If sequence is shorter or the same length as the
152 * input, can only find an exact match. If input is
153 * shorter than the sequence, can only find a partial.
155 if (qp->ilen <= ilen) {
156 if (!strncmp(qp->input, input, qp->ilen))
157 return (qp);
158 } else {
159 if (!strncmp(qp->input, input, ilen))
160 *ispartialp = 1;
163 else
164 for (qp = sp->gp->seqq.lh_first;
165 qp != NULL; qp = qp->q.le_next) {
166 if (qp->input[0] < input[0])
167 continue;
168 if (qp->input[0] > input[0] || qp->ilen > ilen)
169 break;
170 if (stype == qp->stype && qp->ilen == ilen &&
171 !strncmp(qp->input, input, ilen))
172 return (qp);
174 return (NULL);
178 * seq_dump --
179 * Display the sequence entries of a specified type.
182 seq_dump(sp, stype, isname)
183 SCR *sp;
184 enum seqtype stype;
185 int isname;
187 CHNAME const *cname;
188 SEQ *qp;
189 int ch, cnt, len, tablen;
190 char *p;
192 cnt = 0;
193 cname = sp->cname;
194 tablen = O_VAL(sp, O_TABSTOP);
195 for (qp = sp->gp->seqq.lh_first; qp != NULL; qp = qp->q.le_next) {
196 if (stype != qp->stype)
197 continue;
198 ++cnt;
199 for (p = qp->input, len = 0; (ch = *p); ++p, ++len)
200 (void)ex_printf(EXCOOKIE, "%s", cname[ch].name);
201 for (len = tablen - len % tablen; len; --len)
202 (void)ex_printf(EXCOOKIE, " ");
204 for (p = qp->output; (ch = *p); ++p)
205 (void)ex_printf(EXCOOKIE, "%s", cname[ch].name);
207 if (isname && qp->name) {
208 for (len = tablen - len % tablen; len; --len)
209 (void)ex_printf(EXCOOKIE, " ");
210 for (p = qp->name, len = 0; (ch = *p); ++p, ++len)
211 (void)ex_printf(EXCOOKIE, "%s", cname[ch].name);
213 (void)ex_printf(EXCOOKIE, "\n");
215 return (cnt);
219 * seq_save --
220 * Save the sequence entries to a file.
223 seq_save(sp, fp, prefix, stype)
224 SCR *sp;
225 FILE *fp;
226 char *prefix;
227 enum seqtype stype;
229 SEQ *qp;
230 int ch, esc;
231 char *p;
233 esc = sp->gp->original_termios.c_cc[VLNEXT];
235 /* Write a sequence command for all keys the user defined. */
236 for (qp = sp->gp->seqq.lh_first; qp != NULL; qp = qp->q.le_next) {
237 if (!F_ISSET(qp, S_USERDEF))
238 continue;
239 if (stype != qp->stype)
240 continue;
241 if (prefix)
242 (void)fprintf(fp, "%s", prefix);
243 for (p = qp->input; (ch = *p) != '\0'; ++p) {
244 if (ch == esc || ch == '|' || isblank(ch) ||
245 sp->special[ch] == K_NL)
246 (void)putc(esc, fp);
247 (void)putc(ch, fp);
249 (void)putc(' ', fp);
250 for (p = qp->output; (ch = *p) != '\0'; ++p) {
251 if (ch == esc || ch == '|' || sp->special[ch] == K_NL)
252 (void)putc(esc, fp);
253 (void)putc(ch, fp);
255 (void)putc('\n', fp);
257 return (0);