the script used to extract a release
[nvi.git] / common / api.c
blobf931f4a211cfba91372b097361d391d5728cf0b2
1 /*-
2 * Copyright (c) 1992, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1992, 1993, 1994, 1995, 1996
5 * Keith Bostic. All rights reserved.
6 * Copyright (c) 1995
7 * George V. Neville-Neil. All rights reserved.
9 * See the LICENSE file for redistribution information.
12 #include "config.h"
14 #ifndef lint
15 static const char sccsid[] = "$Id: api.c,v 8.33 2000/09/03 18:58:25 skimo Exp $ (Berkeley) $Date: 2000/09/03 18:58:25 $";
16 #endif /* not lint */
18 #include <sys/types.h>
19 #include <sys/queue.h>
20 #include <sys/time.h>
22 #include <bitstring.h>
23 #include <limits.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <termios.h>
28 #include <unistd.h>
30 #include "../common/common.h"
31 #include "../ex/tag.h"
33 extern GS *__global_list; /* XXX */
36 * api_fscreen --
37 * Return a pointer to the screen specified by the screen id
38 * or a file name.
40 * PUBLIC: SCR *api_fscreen __P((int, char *));
42 SCR *
43 api_fscreen(id, name)
44 int id;
45 char *name;
47 GS *gp;
48 SCR *tsp;
49 WIN *wp;
51 gp = __global_list;
53 /* Search the displayed lists. */
54 for (wp = gp->dq.cqh_first;
55 wp != (void *)&gp->dq; wp = wp->q.cqe_next)
56 for (tsp = wp->scrq.cqh_first;
57 tsp != (void *)&wp->scrq; tsp = tsp->q.cqe_next)
58 if (name == NULL) {
59 if (id == tsp->id)
60 return (tsp);
61 } else if (!strcmp(name, tsp->frp->name))
62 return (tsp);
64 /* Search the hidden list. */
65 for (tsp = gp->hq.cqh_first;
66 tsp != (void *)&gp->hq; tsp = tsp->q.cqe_next)
67 if (name == NULL) {
68 if (id == tsp->id)
69 return (tsp);
70 } else if (!strcmp(name, tsp->frp->name))
71 return (tsp);
72 return (NULL);
76 * api_aline --
77 * Append a line.
79 * PUBLIC: int api_aline __P((SCR *, db_recno_t, char *, size_t));
81 int
82 api_aline(sp, lno, line, len)
83 SCR *sp;
84 db_recno_t lno;
85 char *line;
86 size_t len;
88 size_t wblen;
89 CHAR_T *wbp;
91 CHAR2INT(sp, line, len, wbp, wblen);
93 return (db_append(sp, 1, lno, wbp, wblen));
97 * api_extend --
98 * Extend file.
100 * PUBLIC: int api_extend __P((SCR *, db_recno_t));
102 int
103 api_extend(sp, lno)
104 SCR *sp;
105 db_recno_t lno;
107 db_recno_t lastlno;
108 if (db_last(sp, &lastlno))
109 return 1;
110 while(lastlno < lno)
111 if (db_append(sp, 1, lastlno++, NULL, 0))
112 return 1;
113 return 0;
117 * api_dline --
118 * Delete a line.
120 * PUBLIC: int api_dline __P((SCR *, db_recno_t));
123 api_dline(sp, lno)
124 SCR *sp;
125 db_recno_t lno;
127 if (db_delete(sp, lno))
128 return 1;
129 /* change current line if deleted line is that one
130 * or one berfore that
132 if (sp->lno >= lno && sp->lno > 1)
133 sp->lno--;
134 return 0;
138 * api_gline --
139 * Get a line.
141 * PUBLIC: int api_gline __P((SCR *, db_recno_t, CHAR_T **, size_t *));
144 api_gline(sp, lno, linepp, lenp)
145 SCR *sp;
146 db_recno_t lno;
147 CHAR_T **linepp;
148 size_t *lenp;
150 int isempty;
152 if (db_eget(sp, lno, linepp, lenp, &isempty)) {
153 if (isempty)
154 msgq(sp, M_ERR, "209|The file is empty");
155 return (1);
157 return (0);
161 * api_iline --
162 * Insert a line.
164 * PUBLIC: int api_iline __P((SCR *, db_recno_t, char *, size_t));
167 api_iline(sp, lno, line, len)
168 SCR *sp;
169 db_recno_t lno;
170 char *line;
171 size_t len;
173 size_t wblen;
174 CHAR_T *wbp;
176 CHAR2INT(sp, line, len, wbp, wblen);
178 return (db_insert(sp, lno, wbp, wblen));
182 * api_lline --
183 * Return the line number of the last line in the file.
185 * PUBLIC: int api_lline __P((SCR *, db_recno_t *));
188 api_lline(sp, lnop)
189 SCR *sp;
190 db_recno_t *lnop;
192 return (db_last(sp, lnop));
196 * api_sline --
197 * Set a line.
199 * PUBLIC: int api_sline __P((SCR *, db_recno_t, char *, size_t));
202 api_sline(sp, lno, line, len)
203 SCR *sp;
204 db_recno_t lno;
205 char *line;
206 size_t len;
208 size_t wblen;
209 CHAR_T *wbp;
211 CHAR2INT(sp, line, len, wbp, wblen);
213 return (db_set(sp, lno, wbp, wblen));
217 * api_getmark --
218 * Get the mark.
220 * PUBLIC: int api_getmark __P((SCR *, int, MARK *));
223 api_getmark(sp, markname, mp)
224 SCR *sp;
225 int markname;
226 MARK *mp;
228 return (mark_get(sp, (ARG_CHAR_T)markname, mp, M_ERR));
232 * api_setmark --
233 * Set the mark.
235 * PUBLIC: int api_setmark __P((SCR *, int, MARK *));
238 api_setmark(sp, markname, mp)
239 SCR *sp;
240 int markname;
241 MARK *mp;
243 return (mark_set(sp, (ARG_CHAR_T)markname, mp, 1));
247 * api_nextmark --
248 * Return the first mark if next not set, otherwise return the
249 * subsequent mark.
251 * PUBLIC: int api_nextmark __P((SCR *, int, char *));
254 api_nextmark(sp, next, namep)
255 SCR *sp;
256 int next;
257 char *namep;
259 LMARK *mp;
261 mp = sp->ep->marks.lh_first;
262 if (next)
263 for (; mp != NULL; mp = mp->q.le_next)
264 if (mp->name == *namep) {
265 mp = mp->q.le_next;
266 break;
268 if (mp == NULL)
269 return (1);
270 *namep = mp->name;
271 return (0);
275 * api_getcursor --
276 * Get the cursor.
278 * PUBLIC: int api_getcursor __P((SCR *, MARK *));
281 api_getcursor(sp, mp)
282 SCR *sp;
283 MARK *mp;
285 mp->lno = sp->lno;
286 mp->cno = sp->cno;
287 return (0);
291 * api_setcursor --
292 * Set the cursor.
294 * PUBLIC: int api_setcursor __P((SCR *, MARK *));
297 api_setcursor(sp, mp)
298 SCR *sp;
299 MARK *mp;
301 size_t len;
303 if (db_get(sp, mp->lno, DBG_FATAL, NULL, &len))
304 return (1);
305 if (mp->cno < 0 || mp->cno > len) {
306 msgq(sp, M_ERR, "Cursor set to nonexistent column");
307 return (1);
310 /* Set the cursor. */
311 sp->lno = mp->lno;
312 sp->cno = mp->cno;
313 return (0);
317 * api_emessage --
318 * Print an error message.
320 * PUBLIC: void api_emessage __P((SCR *, char *));
322 void
323 api_emessage(sp, text)
324 SCR *sp;
325 char *text;
327 msgq(sp, M_ERR, "%s", text);
331 * api_imessage --
332 * Print an informational message.
334 * PUBLIC: void api_imessage __P((SCR *, char *));
336 void
337 api_imessage(sp, text)
338 SCR *sp;
339 char *text;
341 msgq(sp, M_INFO, "%s", text);
345 * api_edit
346 * Create a new screen and return its id
347 * or edit a new file in the current screen.
349 * PUBLIC: int api_edit __P((SCR *, char *, SCR **, int));
352 api_edit(sp, file, spp, newscreen)
353 SCR *sp;
354 char *file;
355 SCR **spp;
356 int newscreen;
358 EXCMD cmd;
359 size_t wlen;
360 CHAR_T *wp;
362 if (file) {
363 ex_cinit(sp, &cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0);
364 CHAR2INT(sp, file, strlen(file) + 1, wp, wlen);
365 argv_exp0(sp, &cmd, wp, wlen - 1 /* terminating 0 */);
366 } else
367 ex_cinit(sp, &cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0);
368 if (newscreen)
369 cmd.flags |= E_NEWSCREEN; /* XXX */
370 if (cmd.cmd->fn(sp, &cmd))
371 return (1);
372 *spp = sp->nextdisp;
373 return (0);
377 * api_escreen
378 * End a screen.
380 * PUBLIC: int api_escreen __P((SCR *));
383 api_escreen(sp)
384 SCR *sp;
386 EXCMD cmd;
389 * XXX
390 * If the interpreter exits anything other than the current
391 * screen, vi isn't going to update everything correctly.
393 ex_cinit(sp, &cmd, C_QUIT, 0, OOBLNO, OOBLNO, 0);
394 return (cmd.cmd->fn(sp, &cmd));
398 * api_swscreen --
399 * Switch to a new screen.
401 * PUBLIC: int api_swscreen __P((SCR *, SCR *));
404 api_swscreen(sp, new)
405 SCR *sp, *new;
408 * XXX
409 * If the interpreter switches from anything other than the
410 * current screen, vi isn't going to update everything correctly.
412 sp->nextdisp = new;
413 F_SET(sp, SC_SSWITCH);
415 return (0);
419 * api_map --
420 * Map a key.
422 * PUBLIC: int api_map __P((SCR *, char *, char *, size_t));
425 api_map(sp, name, map, len)
426 SCR *sp;
427 char *name, *map;
428 size_t len;
430 EXCMD cmd;
431 size_t wlen;
432 CHAR_T *wp;
434 ex_cinit(sp, &cmd, C_MAP, 0, OOBLNO, OOBLNO, 0);
435 CHAR2INT(sp, name, strlen(name) + 1, wp, wlen);
436 argv_exp0(sp, &cmd, wp, wlen - 1);
437 CHAR2INT(sp, map, len, wp, wlen);
438 argv_exp0(sp, &cmd, wp, wlen);
439 return (cmd.cmd->fn(sp, &cmd));
443 * api_unmap --
444 * Unmap a key.
446 * PUBLIC: int api_unmap __P((SCR *, char *));
448 int
449 api_unmap(sp, name)
450 SCR *sp;
451 char *name;
453 EXCMD cmd;
454 size_t wlen;
455 CHAR_T *wp;
457 ex_cinit(sp, &cmd, C_UNMAP, 0, OOBLNO, OOBLNO, 0);
458 CHAR2INT(sp, name, strlen(name) + 1, wp, wlen);
459 argv_exp0(sp, &cmd, wp, wlen - 1);
460 return (cmd.cmd->fn(sp, &cmd));
464 * api_opts_get --
465 * Return a option value as a string, in allocated memory.
466 * If the option is of type boolean, boolvalue is (un)set
467 * according to the value; otherwise boolvalue is -1.
469 * PUBLIC: int api_opts_get __P((SCR *, char *, char **, int *));
472 api_opts_get(sp, name, value, boolvalue)
473 SCR *sp;
474 char *name, **value;
475 int *boolvalue;
477 OPTLIST const *op;
478 int offset;
480 if ((op = opts_search(name)) == NULL) {
481 opts_nomatch(sp, name);
482 return (1);
485 offset = op - optlist;
486 if (boolvalue != NULL)
487 *boolvalue = -1;
488 switch (op->type) {
489 case OPT_0BOOL:
490 case OPT_1BOOL:
491 MALLOC_RET(sp, *value, char *, strlen(op->name) + 2 + 1);
492 (void)sprintf(*value,
493 "%s%s", O_ISSET(sp, offset) ? "" : "no", op->name);
494 if (boolvalue != NULL)
495 *boolvalue = O_ISSET(sp, offset);
496 break;
497 case OPT_NUM:
498 MALLOC_RET(sp, *value, char *, 20);
499 (void)sprintf(*value, "%lu", (u_long)O_VAL(sp, offset));
500 break;
501 case OPT_STR:
502 if (O_STR(sp, offset) == NULL) {
503 MALLOC_RET(sp, *value, char *, 2);
504 value[0] = '\0';
505 } else {
506 MALLOC_RET(sp,
507 *value, char *, strlen(O_STR(sp, offset)) + 1);
508 (void)sprintf(*value, "%s", O_STR(sp, offset));
510 break;
512 return (0);
516 * api_opts_set --
517 * Set options.
519 * PUBLIC: int api_opts_set __P((SCR *, char *, char *, u_long, int));
522 api_opts_set(sp, name, str_value, num_value, bool_value)
523 SCR *sp;
524 char *name, *str_value;
525 u_long num_value;
526 int bool_value;
528 ARGS *ap[2], a, b;
529 OPTLIST const *op;
530 int rval;
531 size_t blen;
532 char *bp;
533 size_t wblen;
534 CHAR_T *wbp;
536 if ((op = opts_search(name)) == NULL) {
537 opts_nomatch(sp, name);
538 return (1);
541 switch (op->type) {
542 case OPT_0BOOL:
543 case OPT_1BOOL:
544 GET_SPACE_RET(sp, bp, blen, 64);
545 a.len = snprintf(bp, 64, "%s%s", bool_value ? "" : "no", name);
546 break;
547 case OPT_NUM:
548 GET_SPACE_RET(sp, bp, blen, 64);
549 a.len = snprintf(bp, 64, "%s=%lu", name, num_value);
550 break;
551 case OPT_STR:
552 GET_SPACE_RET(sp, bp, blen, 1024);
553 a.len = snprintf(bp, 1024, "%s=%s", name, str_value);
554 break;
557 CHAR2INT(sp, bp, a.len, wbp, wblen);
558 a.len = wblen;
559 wbp = v_wstrdup(sp, wbp, wblen);
561 a.bp = wbp;
562 b.len = 0;
563 b.bp = NULL;
564 ap[0] = &a;
565 ap[1] = &b;
566 rval = opts_set(sp, ap, NULL);
568 free(wbp);
569 FREE_SPACE(sp, bp, blen);
571 return (rval);
575 * api_run_str --
576 * Execute a string as an ex command.
578 * PUBLIC: int api_run_str __P((SCR *, char *));
580 int
581 api_run_str(sp, cmd)
582 SCR *sp;
583 char *cmd;
585 size_t wlen;
586 CHAR_T *wp;
588 CHAR2INT(sp, cmd, strlen(cmd)+1, wp, wlen);
589 return (ex_run_str(sp, NULL, wp, wlen - 1, 0, 0));
593 * PUBLIC: TAGQ * api_tagq_new __P((SCR*, char*));
595 TAGQ *
596 api_tagq_new(sp, tag)
597 SCR *sp;
598 char *tag;
600 TAGQ *tqp;
601 size_t len;
603 /* Allocate and initialize the tag queue structure. */
604 len = strlen(tag);
605 CALLOC_GOTO(sp, tqp, TAGQ *, 1, sizeof(TAGQ) + len + 1);
606 CIRCLEQ_INIT(&tqp->tagq);
607 tqp->tag = tqp->buf;
608 memcpy(tqp->tag, tag, (tqp->tlen = len) + 1);
610 return tqp;
612 alloc_err:
613 return (NULL);
617 * PUBLIC: void api_tagq_add __P((SCR*, TAGQ*, char*, char *, char *));
619 void
620 api_tagq_add(sp, tqp, filename, search, msg)
621 SCR *sp;
622 TAGQ *tqp;
623 char *filename, *search, *msg;
625 TAG *tp;
626 CHAR_T *wp;
627 size_t wlen;
628 size_t flen = strlen(filename);
629 size_t slen = strlen(search);
630 size_t mlen = strlen(msg);
632 CALLOC_GOTO(sp, tp, TAG *, 1,
633 sizeof(TAG) - 1 + flen + 1 + slen + 1 + mlen + 1);
634 tp->fname = (char *)tp->buf;
635 memcpy(tp->fname, filename, flen + 1);
636 tp->fnlen = flen;
637 tp->search = (CHAR_T *)((char *)tp->fname + flen + 1);
638 CHAR2INT(sp, search, slen + 1, wp, wlen);
639 MEMCPYW(tp->search, wp, wlen);
640 tp->slen = slen;
641 tp->msg = tp->search + slen + 1;
642 CHAR2INT(sp, msg, mlen + 1, wp, wlen);
643 MEMCPYW(tp->msg, wp, wlen);
644 tp->mlen = mlen;
645 CIRCLEQ_INSERT_TAIL(&tqp->tagq, tp, q);
647 alloc_err:
648 return;
652 * PUBLIC: int api_tagq_push __P((SCR*, TAGQ**));
655 api_tagq_push(sp, tqpp)
656 SCR *sp;
657 TAGQ **tqpp;
659 FREF *frp;
660 db_recno_t lno;
661 size_t cno;
662 int istmp;
663 TAGQ *tqp;
665 tqp = *tqpp;
667 *tqpp = 0;
669 /* Check to see if we found anything. */
670 if (tqp->tagq.cqh_first == (void *)&tqp->tagq) {
671 free(tqp);
672 return 0;
675 tqp->current = tqp->tagq.cqh_first;
677 if (tagq_push(sp, tqp, 0, 0))
678 return 1;
680 return (0);
684 * PUBLIC: void api_tagq_free __P((SCR*, TAGQ*));
686 void
687 api_tagq_free(sp, tqp)
688 SCR *sp;
689 TAGQ *tqp;
691 if (tqp)
692 tagq_free(sp, tqp);