it's LINES, not ROWS!
[nvi.git] / common / seq.c
blob627f6dc6c5dc078c284fb8fb7b6b3801b96b859b
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.21 1993/12/09 19:42:15 bostic Exp $ (Berkeley) $Date: 1993/12/09 19:42:15 $";
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 "seq.h"
21 #include "excmd.h"
24 * seq_set --
25 * Internal version to enter a sequence.
27 int
28 seq_set(sp, name, nlen, input, ilen, output, olen, stype, userdef)
29 SCR *sp;
30 char *name, *input, *output;
31 size_t nlen, ilen, olen;
32 enum seqtype stype;
33 int userdef;
35 SEQ *lastqp, *qp;
36 CHAR_T *p;
38 #if defined(DEBUG) && 0
39 TRACE(sp, "seq_set: name {%s} input {%s} output {%s}\n",
40 name ? name : "", input, output);
41 #endif
42 /* Just replace the output field in any previous occurrence. */
43 if ((qp = seq_find(sp, &lastqp, input, ilen, stype, NULL)) != NULL) {
44 if ((p = v_strdup(sp, output, olen)) == NULL)
45 goto mem1;
46 FREE(qp->output, qp->olen);
47 qp->olen = olen;
48 qp->output = p;
49 return (0);
52 /* Allocate and initialize space. */
53 CALLOC(sp, qp, SEQ *, 1, sizeof(SEQ));
54 if (qp == NULL)
55 goto mem1;
56 if (name == NULL)
57 qp->name = NULL;
58 else if ((qp->name = v_strdup(sp, name, nlen)) == NULL)
59 goto mem2;
60 if ((qp->input = v_strdup(sp, input, ilen)) == NULL)
61 goto mem3;
62 if ((qp->output = v_strdup(sp, output, olen)) == NULL) {
63 FREE(qp->input, ilen);
64 mem3: if (qp->name != NULL)
65 FREE(qp->name, nlen);
66 mem2: FREE(qp, sizeof(SEQ));
67 mem1: msgq(sp, M_SYSERR, NULL);
68 return (1);
71 qp->stype = stype;
72 qp->nlen = nlen;
73 qp->ilen = ilen;
74 qp->olen = olen;
75 qp->flags = userdef ? S_USERDEF : 0;
77 /* Link into the chain. */
78 if (lastqp == NULL) {
79 LIST_INSERT_HEAD(&sp->gp->seqq, qp, q);
80 } else {
81 LIST_INSERT_AFTER(lastqp, qp, q);
84 /* Set the fast lookup bit. */
85 bit_set(sp->gp->seqb, qp->input[0]);
87 return (0);
91 * seq_delete --
92 * Delete a sequence.
94 int
95 seq_delete(sp, input, ilen, stype)
96 SCR *sp;
97 char *input;
98 size_t ilen;
99 enum seqtype stype;
101 SEQ *qp;
103 if ((qp = seq_find(sp, NULL, input, ilen, stype, NULL)) == NULL)
104 return (1);
106 LIST_REMOVE(qp, q);
107 if (qp->name != NULL)
108 FREE(qp->name, qp->nlen);
109 FREE(qp->input, qp->ilen);
110 FREE(qp->output, qp->olen);
111 FREE(qp, sizeof(SEQ));
112 return (0);
116 * seq_find --
117 * Search the sequence list for a match to a buffer, if ispartial
118 * isn't NULL, partial matches count.
120 SEQ *
121 seq_find(sp, lastqp, input, ilen, stype, ispartialp)
122 SCR *sp;
123 SEQ **lastqp;
124 char *input;
125 size_t ilen;
126 enum seqtype stype;
127 int *ispartialp;
129 SEQ *lqp, *qp;
130 int diff;
133 * Ispartialp is a location where we return if there was a
134 * partial match, i.e. if the string were extended it might
135 * match something.
137 * XXX
138 * Overload the meaning of ispartialp; only the terminal key
139 * search doesn't want the search limited to complete matches,
140 * i.e. ilen may be longer than the match.
142 if (ispartialp != NULL)
143 *ispartialp = 0;
144 for (lqp = NULL, qp = sp->gp->seqq.lh_first;
145 qp != NULL; lqp = qp, qp = qp->q.le_next) {
146 /* Fast checks on the first character and type. */
147 if (qp->input[0] > input[0])
148 break;
149 if (qp->input[0] < input[0] || qp->stype != stype)
150 continue;
152 /* Check on the real comparison. */
153 diff = memcmp(qp->input, input, MIN(qp->ilen, ilen));
154 if (diff > 0)
155 break;
156 if (diff < 0)
157 continue;
159 * If the entry is the same length as the string, return a
160 * match. If the entry is shorter than the string, return a
161 * match if called from the terminal key routine. Otherwise,
162 * keep searching for a complete match.
164 if (qp->ilen <= ilen) {
165 if (qp->ilen == ilen || ispartialp != NULL) {
166 if (lastqp != NULL)
167 *lastqp = lqp;
168 return (qp);
170 continue;
173 * If the entry longer than the string, return partial match
174 * if called from the terminal key routine. Otherwise, no
175 * match.
177 if (ispartialp != NULL)
178 *ispartialp = 1;
179 break;
181 if (lastqp != NULL)
182 *lastqp = lqp;
183 return (NULL);
187 * seq_dump --
188 * Display the sequence entries of a specified type.
191 seq_dump(sp, stype, isname)
192 SCR *sp;
193 enum seqtype stype;
194 int isname;
196 CHNAME const *cname;
197 SEQ *qp;
198 int cnt, len, olen, tablen;
199 char *p;
201 cnt = 0;
202 cname = sp->gp->cname;
203 tablen = O_VAL(sp, O_TABSTOP);
204 for (qp = sp->gp->seqq.lh_first; qp != NULL; qp = qp->q.le_next) {
205 if (stype != qp->stype)
206 continue;
207 ++cnt;
208 for (p = qp->input,
209 olen = qp->ilen, len = 0; olen > 0; --olen, ++len)
210 (void)ex_printf(EXCOOKIE, "%s", cname[*p++].name);
211 for (len = tablen - len % tablen; len; --len)
212 (void)ex_printf(EXCOOKIE, " ");
214 for (p = qp->output, olen = qp->olen; olen > 0; --olen)
215 (void)ex_printf(EXCOOKIE, "%s", cname[*p++].name);
217 if (isname && qp->name != NULL) {
218 for (len = tablen - len % tablen; len; --len)
219 (void)ex_printf(EXCOOKIE, " ");
220 for (p = qp->name, olen = qp->nlen; olen > 0; --olen)
221 (void)ex_printf(EXCOOKIE,
222 "%s", cname[*p++].name);
224 (void)ex_printf(EXCOOKIE, "\n");
226 return (cnt);
230 * seq_save --
231 * Save the sequence entries to a file.
234 seq_save(sp, fp, prefix, stype)
235 SCR *sp;
236 FILE *fp;
237 char *prefix;
238 enum seqtype stype;
240 CHAR_T esc;
241 SEQ *qp;
242 size_t olen;
243 int ch;
244 char *p;
246 /* Write a sequence command for all keys the user defined. */
247 (void)term_key_ch(sp, K_VLNEXT, &esc);
248 for (qp = sp->gp->seqq.lh_first; qp != NULL; qp = qp->q.le_next) {
249 if (!F_ISSET(qp, S_USERDEF))
250 continue;
251 if (stype != qp->stype)
252 continue;
253 if (prefix)
254 (void)fprintf(fp, "%s", prefix);
255 for (p = qp->input, olen = qp->ilen; olen > 0; --olen) {
256 ch = *p++;
257 if (ch == esc || ch == '|' ||
258 isblank(ch) || term_key_val(sp, ch) == K_NL)
259 (void)putc(esc, fp);
260 (void)putc(ch, fp);
262 (void)putc(' ', fp);
263 for (p = qp->output, olen = qp->olen; olen > 0; --olen) {
264 ch = *p++;
265 if (ch == esc || ch == '|' ||
266 term_key_val(sp, ch) == K_NL)
267 (void)putc(esc, fp);
268 (void)putc(ch, fp);
270 (void)putc('\n', fp);
272 return (0);