*** empty log message ***
[nvi.git] / common / api.c
blob8edaf226d35cf13b5a24bbdb0a53e2bb8ab7daa2
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.30 2000/06/25 17:34:37 skimo Exp $ (Berkeley) $Date: 2000/06/25 17:34:37 $";
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 return (db_append(sp, 1, lno, line, len));
92 * api_extend --
93 * Extend file.
95 * PUBLIC: int api_extend __P((SCR *, db_recno_t));
97 int
98 api_extend(sp, lno)
99 SCR *sp;
100 db_recno_t lno;
102 db_recno_t lastlno;
103 if (db_last(sp, &lastlno))
104 return 1;
105 while(lastlno < lno)
106 if (db_append(sp, 1, lastlno++, "", 0))
107 return 1;
108 return 0;
112 * api_dline --
113 * Delete a line.
115 * PUBLIC: int api_dline __P((SCR *, db_recno_t));
118 api_dline(sp, lno)
119 SCR *sp;
120 db_recno_t lno;
122 if (db_delete(sp, lno))
123 return 1;
124 /* change current line if deleted line is that one
125 * or one berfore that
127 if (sp->lno >= lno && sp->lno > 1)
128 sp->lno--;
129 return 0;
133 * api_gline --
134 * Get a line.
136 * PUBLIC: int api_gline __P((SCR *, db_recno_t, CHAR_T **, size_t *));
139 api_gline(sp, lno, linepp, lenp)
140 SCR *sp;
141 db_recno_t lno;
142 CHAR_T **linepp;
143 size_t *lenp;
145 int isempty;
147 if (db_eget(sp, lno, linepp, lenp, &isempty)) {
148 if (isempty)
149 msgq(sp, M_ERR, "209|The file is empty");
150 return (1);
152 return (0);
156 * api_iline --
157 * Insert a line.
159 * PUBLIC: int api_iline __P((SCR *, db_recno_t, char *, size_t));
162 api_iline(sp, lno, line, len)
163 SCR *sp;
164 db_recno_t lno;
165 char *line;
166 size_t len;
168 return (db_insert(sp, lno, line, len));
172 * api_lline --
173 * Return the line number of the last line in the file.
175 * PUBLIC: int api_lline __P((SCR *, db_recno_t *));
178 api_lline(sp, lnop)
179 SCR *sp;
180 db_recno_t *lnop;
182 return (db_last(sp, lnop));
186 * api_sline --
187 * Set a line.
189 * PUBLIC: int api_sline __P((SCR *, db_recno_t, char *, size_t));
192 api_sline(sp, lno, line, len)
193 SCR *sp;
194 db_recno_t lno;
195 char *line;
196 size_t len;
198 return (db_set(sp, lno, line, len));
202 * api_getmark --
203 * Get the mark.
205 * PUBLIC: int api_getmark __P((SCR *, int, MARK *));
208 api_getmark(sp, markname, mp)
209 SCR *sp;
210 int markname;
211 MARK *mp;
213 return (mark_get(sp, (ARG_CHAR_T)markname, mp, M_ERR));
217 * api_setmark --
218 * Set the mark.
220 * PUBLIC: int api_setmark __P((SCR *, int, MARK *));
223 api_setmark(sp, markname, mp)
224 SCR *sp;
225 int markname;
226 MARK *mp;
228 return (mark_set(sp, (ARG_CHAR_T)markname, mp, 1));
232 * api_nextmark --
233 * Return the first mark if next not set, otherwise return the
234 * subsequent mark.
236 * PUBLIC: int api_nextmark __P((SCR *, int, char *));
239 api_nextmark(sp, next, namep)
240 SCR *sp;
241 int next;
242 char *namep;
244 LMARK *mp;
246 mp = sp->ep->marks.lh_first;
247 if (next)
248 for (; mp != NULL; mp = mp->q.le_next)
249 if (mp->name == *namep) {
250 mp = mp->q.le_next;
251 break;
253 if (mp == NULL)
254 return (1);
255 *namep = mp->name;
256 return (0);
260 * api_getcursor --
261 * Get the cursor.
263 * PUBLIC: int api_getcursor __P((SCR *, MARK *));
266 api_getcursor(sp, mp)
267 SCR *sp;
268 MARK *mp;
270 mp->lno = sp->lno;
271 mp->cno = sp->cno;
272 return (0);
276 * api_setcursor --
277 * Set the cursor.
279 * PUBLIC: int api_setcursor __P((SCR *, MARK *));
282 api_setcursor(sp, mp)
283 SCR *sp;
284 MARK *mp;
286 size_t len;
288 if (db_get(sp, mp->lno, DBG_FATAL, NULL, &len))
289 return (1);
290 if (mp->cno < 0 || mp->cno > len) {
291 msgq(sp, M_ERR, "Cursor set to nonexistent column");
292 return (1);
295 /* Set the cursor. */
296 sp->lno = mp->lno;
297 sp->cno = mp->cno;
298 return (0);
302 * api_emessage --
303 * Print an error message.
305 * PUBLIC: void api_emessage __P((SCR *, char *));
307 void
308 api_emessage(sp, text)
309 SCR *sp;
310 char *text;
312 msgq(sp, M_ERR, "%s", text);
316 * api_imessage --
317 * Print an informational message.
319 * PUBLIC: void api_imessage __P((SCR *, char *));
321 void
322 api_imessage(sp, text)
323 SCR *sp;
324 char *text;
326 msgq(sp, M_INFO, "%s", text);
330 * api_edit
331 * Create a new screen and return its id
332 * or edit a new file in the current screen.
334 * PUBLIC: int api_edit __P((SCR *, char *, SCR **, int));
337 api_edit(sp, file, spp, newscreen)
338 SCR *sp;
339 char *file;
340 SCR **spp;
341 int newscreen;
343 EXCMD cmd;
345 if (file) {
346 ex_cinit(sp, &cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0);
347 argv_exp0(sp, &cmd, file, strlen(file));
348 } else
349 ex_cinit(sp, &cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0);
350 if (newscreen)
351 cmd.flags |= E_NEWSCREEN; /* XXX */
352 if (cmd.cmd->fn(sp, &cmd))
353 return (1);
354 *spp = sp->nextdisp;
355 return (0);
359 * api_escreen
360 * End a screen.
362 * PUBLIC: int api_escreen __P((SCR *));
365 api_escreen(sp)
366 SCR *sp;
368 EXCMD cmd;
371 * XXX
372 * If the interpreter exits anything other than the current
373 * screen, vi isn't going to update everything correctly.
375 ex_cinit(sp, &cmd, C_QUIT, 0, OOBLNO, OOBLNO, 0);
376 return (cmd.cmd->fn(sp, &cmd));
380 * api_swscreen --
381 * Switch to a new screen.
383 * PUBLIC: int api_swscreen __P((SCR *, SCR *));
386 api_swscreen(sp, new)
387 SCR *sp, *new;
390 * XXX
391 * If the interpreter switches from anything other than the
392 * current screen, vi isn't going to update everything correctly.
394 sp->nextdisp = new;
395 F_SET(sp, SC_SSWITCH);
397 return (0);
401 * api_map --
402 * Map a key.
404 * PUBLIC: int api_map __P((SCR *, char *, char *, size_t));
407 api_map(sp, name, map, len)
408 SCR *sp;
409 char *name, *map;
410 size_t len;
412 EXCMD cmd;
414 ex_cinit(sp, &cmd, C_MAP, 0, OOBLNO, OOBLNO, 0);
415 argv_exp0(sp, &cmd, name, strlen(name));
416 argv_exp0(sp, &cmd, map, len);
417 return (cmd.cmd->fn(sp, &cmd));
421 * api_unmap --
422 * Unmap a key.
424 * PUBLIC: int api_unmap __P((SCR *, char *));
426 int
427 api_unmap(sp, name)
428 SCR *sp;
429 char *name;
431 EXCMD cmd;
433 ex_cinit(sp, &cmd, C_UNMAP, 0, OOBLNO, OOBLNO, 0);
434 argv_exp0(sp, &cmd, name, strlen(name));
435 return (cmd.cmd->fn(sp, &cmd));
439 * api_opts_get --
440 * Return a option value as a string, in allocated memory.
441 * If the option is of type boolean, boolvalue is (un)set
442 * according to the value; otherwise boolvalue is -1.
444 * PUBLIC: int api_opts_get __P((SCR *, char *, char **, int *));
447 api_opts_get(sp, name, value, boolvalue)
448 SCR *sp;
449 char *name, **value;
450 int *boolvalue;
452 OPTLIST const *op;
453 int offset;
455 if ((op = opts_search(name)) == NULL) {
456 opts_nomatch(sp, name);
457 return (1);
460 offset = op - optlist;
461 if (boolvalue != NULL)
462 *boolvalue = -1;
463 switch (op->type) {
464 case OPT_0BOOL:
465 case OPT_1BOOL:
466 MALLOC_RET(sp, *value, char *, strlen(op->name) + 2 + 1);
467 (void)sprintf(*value,
468 "%s%s", O_ISSET(sp, offset) ? "" : "no", op->name);
469 if (boolvalue != NULL)
470 *boolvalue = O_ISSET(sp, offset);
471 break;
472 case OPT_NUM:
473 MALLOC_RET(sp, *value, char *, 20);
474 (void)sprintf(*value, "%lu", (u_long)O_VAL(sp, offset));
475 break;
476 case OPT_STR:
477 if (O_STR(sp, offset) == NULL) {
478 MALLOC_RET(sp, *value, char *, 2);
479 value[0] = '\0';
480 } else {
481 MALLOC_RET(sp,
482 *value, char *, strlen(O_STR(sp, offset)) + 1);
483 (void)sprintf(*value, "%s", O_STR(sp, offset));
485 break;
487 return (0);
491 * api_opts_set --
492 * Set options.
494 * PUBLIC: int api_opts_set __P((SCR *, char *, char *, u_long, int));
497 api_opts_set(sp, name, str_value, num_value, bool_value)
498 SCR *sp;
499 char *name, *str_value;
500 u_long num_value;
501 int bool_value;
503 ARGS *ap[2], a, b;
504 OPTLIST const *op;
505 int rval;
506 size_t blen;
507 char *bp;
509 if ((op = opts_search(name)) == NULL) {
510 opts_nomatch(sp, name);
511 return (1);
514 switch (op->type) {
515 case OPT_0BOOL:
516 case OPT_1BOOL:
517 GET_SPACE_RET(sp, bp, blen, 64);
518 a.len = snprintf(bp, 64, "%s%s", bool_value ? "" : "no", name);
519 break;
520 case OPT_NUM:
521 GET_SPACE_RET(sp, bp, blen, 64);
522 a.len = snprintf(bp, 64, "%s=%lu", name, num_value);
523 break;
524 case OPT_STR:
525 GET_SPACE_RET(sp, bp, blen, 1024);
526 a.len = snprintf(bp, 1024, "%s=%s", name, str_value);
527 break;
529 a.bp = bp;
530 b.len = 0;
531 b.bp = NULL;
532 ap[0] = &a;
533 ap[1] = &b;
534 rval = opts_set(sp, ap, NULL);
536 FREE_SPACE(sp, bp, blen);
538 return (rval);
542 * api_run_str --
543 * Execute a string as an ex command.
545 * PUBLIC: int api_run_str __P((SCR *, char *));
547 int
548 api_run_str(sp, cmd)
549 SCR *sp;
550 char *cmd;
552 return (ex_run_str(sp, NULL, cmd, strlen(cmd), 0, 0));
556 * PUBLIC: TAGQ * api_tagq_new __P((SCR*, char*));
558 TAGQ *
559 api_tagq_new(sp, tag)
560 SCR *sp;
561 char *tag;
563 TAGQ *tqp;
564 size_t len;
566 /* Allocate and initialize the tag queue structure. */
567 len = strlen(tag);
568 CALLOC_GOTO(sp, tqp, TAGQ *, 1, sizeof(TAGQ) + len + 1);
569 CIRCLEQ_INIT(&tqp->tagq);
570 tqp->tag = tqp->buf;
571 memcpy(tqp->tag, tag, (tqp->tlen = len) + 1);
573 return tqp;
575 alloc_err:
576 return (NULL);
580 * PUBLIC: void api_tagq_add __P((SCR*, TAGQ*, char*, char *, char *));
582 void
583 api_tagq_add(sp, tqp, filename, search, msg)
584 SCR *sp;
585 TAGQ *tqp;
586 char *filename, *search, *msg;
588 TAG *tp;
589 size_t flen = strlen(filename);
590 size_t slen = strlen(search);
592 CALLOC_GOTO(sp, tp, TAG *, 1, sizeof(TAG) - 1 + flen + 1 + slen + 1);
593 tp->fname = tp->buf;
594 memcpy(tp->fname, filename, flen + 1);
595 tp->fnlen = flen;
596 tp->search = tp->fname + flen + 1;
597 memcpy(tp->search, search, slen + 1);
598 tp->slen = slen;
599 CIRCLEQ_INSERT_TAIL(&tqp->tagq, tp, q);
601 alloc_err:
602 return;
606 * PUBLIC: int api_tagq_push __P((SCR*, TAGQ**));
609 api_tagq_push(sp, tqpp)
610 SCR *sp;
611 TAGQ **tqpp;
613 FREF *frp;
614 db_recno_t lno;
615 size_t cno;
616 int istmp;
617 TAGQ *tqp;
619 tqp = *tqpp;
621 *tqpp = 0;
623 /* Check to see if we found anything. */
624 if (tqp->tagq.cqh_first == (void *)&tqp->tagq) {
625 free(tqp);
626 return 0;
629 tqp->current = tqp->tagq.cqh_first;
631 if (tagq_push(sp, tqp, 0, 0))
632 return 1;
634 return (0);
638 * PUBLIC: void api_tagq_free __P((SCR*, TAGQ*));
640 void
641 api_tagq_free(sp, tqp)
642 SCR *sp;
643 TAGQ *tqp;
645 if (tqp)
646 tagq_free(sp, tqp);