Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / nvi / common / api.c
blobe6f43505c38605061b4c6fb4b9b152c0948ee95f
1 /* $NetBSD: api.c,v 1.1.1.2 2008/05/18 14:29:40 aymeric Exp $ */
3 /*-
4 * Copyright (c) 1992, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
6 * Copyright (c) 1992, 1993, 1994, 1995, 1996
7 * Keith Bostic. All rights reserved.
8 * Copyright (c) 1995
9 * George V. Neville-Neil. All rights reserved.
11 * See the LICENSE file for redistribution information.
14 #include "config.h"
16 #ifndef lint
17 static const char sccsid[] = "Id: api.c,v 8.40 2002/06/08 19:30:33 skimo Exp (Berkeley) Date: 2002/06/08 19:30:33";
18 #endif /* not lint */
20 #include <sys/types.h>
21 #include <sys/queue.h>
22 #include <sys/time.h>
24 #include <bitstring.h>
25 #include <limits.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <termios.h>
30 #include <unistd.h>
32 #include "../common/common.h"
33 #include "../ex/tag.h"
35 extern GS *__global_list; /* XXX */
38 * api_fscreen --
39 * Return a pointer to the screen specified by the screen id
40 * or a file name.
42 * PUBLIC: SCR *api_fscreen __P((int, char *));
44 SCR *
45 api_fscreen(int id, 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(SCR *sp, db_recno_t lno, char *line, size_t len)
84 size_t wblen;
85 const CHAR_T *wbp;
87 CHAR2INT(sp, line, len, wbp, wblen);
89 return (db_append(sp, 1, lno, wbp, wblen));
93 * api_extend --
94 * Extend file.
96 * PUBLIC: int api_extend __P((SCR *, db_recno_t));
98 int
99 api_extend(SCR *sp, db_recno_t lno)
101 db_recno_t lastlno;
102 if (db_last(sp, &lastlno))
103 return 1;
104 while(lastlno < lno)
105 if (db_append(sp, 1, lastlno++, NULL, 0))
106 return 1;
107 return 0;
111 * api_dline --
112 * Delete a line.
114 * PUBLIC: int api_dline __P((SCR *, db_recno_t));
117 api_dline(SCR *sp, db_recno_t lno)
119 if (db_delete(sp, lno))
120 return 1;
121 /* change current line if deleted line is that one
122 * or one berfore that
124 if (sp->lno >= lno && sp->lno > 1)
125 sp->lno--;
126 return 0;
130 * api_gline --
131 * Get a line.
133 * PUBLIC: int api_gline __P((SCR *, db_recno_t, CHAR_T **, size_t *));
136 api_gline(SCR *sp, db_recno_t lno, CHAR_T **linepp, size_t *lenp)
138 int isempty;
140 if (db_eget(sp, lno, linepp, lenp, &isempty)) {
141 if (isempty)
142 msgq(sp, M_ERR, "209|The file is empty");
143 return (1);
145 return (0);
149 * api_iline --
150 * Insert a line.
152 * PUBLIC: int api_iline __P((SCR *, db_recno_t, CHAR_T *, size_t));
155 api_iline(SCR *sp, db_recno_t lno, CHAR_T *line, size_t len)
157 return (db_insert(sp, lno, line, len));
161 * api_lline --
162 * Return the line number of the last line in the file.
164 * PUBLIC: int api_lline __P((SCR *, db_recno_t *));
167 api_lline(SCR *sp, db_recno_t *lnop)
169 return (db_last(sp, lnop));
173 * api_sline --
174 * Set a line.
176 * PUBLIC: int api_sline __P((SCR *, db_recno_t, CHAR_T *, size_t));
179 api_sline(SCR *sp, db_recno_t lno, CHAR_T *line, size_t len)
181 return (db_set(sp, lno, line, len));
185 * api_getmark --
186 * Get the mark.
188 * PUBLIC: int api_getmark __P((SCR *, int, MARK *));
191 api_getmark(SCR *sp, int markname, MARK *mp)
193 return (mark_get(sp, (ARG_CHAR_T)markname, mp, M_ERR));
197 * api_setmark --
198 * Set the mark.
200 * PUBLIC: int api_setmark __P((SCR *, int, MARK *));
203 api_setmark(SCR *sp, int markname, MARK *mp)
205 return (mark_set(sp, (ARG_CHAR_T)markname, mp, 1));
209 * api_nextmark --
210 * Return the first mark if next not set, otherwise return the
211 * subsequent mark.
213 * PUBLIC: int api_nextmark __P((SCR *, int, char *));
216 api_nextmark(SCR *sp, int next, char *namep)
218 LMARK *mp;
220 mp = sp->ep->marks.lh_first;
221 if (next)
222 for (; mp != NULL; mp = mp->q.le_next)
223 if (mp->name == *namep) {
224 mp = mp->q.le_next;
225 break;
227 if (mp == NULL)
228 return (1);
229 *namep = mp->name;
230 return (0);
234 * api_getcursor --
235 * Get the cursor.
237 * PUBLIC: int api_getcursor __P((SCR *, MARK *));
240 api_getcursor(SCR *sp, MARK *mp)
242 mp->lno = sp->lno;
243 mp->cno = sp->cno;
244 return (0);
248 * api_setcursor --
249 * Set the cursor.
251 * PUBLIC: int api_setcursor __P((SCR *, MARK *));
254 api_setcursor(SCR *sp, MARK *mp)
256 size_t len;
258 if (db_get(sp, mp->lno, DBG_FATAL, NULL, &len))
259 return (1);
260 if (mp->cno > len) {
261 msgq(sp, M_ERR, "Cursor set to nonexistent column");
262 return (1);
265 /* Set the cursor. */
266 sp->lno = mp->lno;
267 sp->cno = mp->cno;
268 return (0);
272 * api_emessage --
273 * Print an error message.
275 * PUBLIC: void api_emessage __P((SCR *, char *));
277 void
278 api_emessage(SCR *sp, char *text)
280 msgq(sp, M_ERR, "%s", text);
284 * api_imessage --
285 * Print an informational message.
287 * PUBLIC: void api_imessage __P((SCR *, char *));
289 void
290 api_imessage(SCR *sp, char *text)
292 msgq(sp, M_INFO, "%s", text);
296 * api_edit
297 * Create a new screen and return its id
298 * or edit a new file in the current screen.
300 * PUBLIC: int api_edit __P((SCR *, char *, SCR **, int));
303 api_edit(SCR *sp, char *file, SCR **spp, int newscreen)
305 EXCMD cmd;
306 size_t wlen;
307 const CHAR_T *wp;
309 if (file) {
310 ex_cinit(sp, &cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0);
311 CHAR2INT(sp, file, strlen(file) + 1, wp, wlen);
312 argv_exp0(sp, &cmd, wp, wlen - 1 /* terminating 0 */);
313 } else
314 ex_cinit(sp, &cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0);
315 if (newscreen)
316 cmd.flags |= E_NEWSCREEN; /* XXX */
317 if (cmd.cmd->fn(sp, &cmd))
318 return (1);
319 *spp = sp->nextdisp;
320 return (0);
324 * api_escreen
325 * End a screen.
327 * PUBLIC: int api_escreen __P((SCR *));
330 api_escreen(SCR *sp)
332 EXCMD cmd;
335 * XXX
336 * If the interpreter exits anything other than the current
337 * screen, vi isn't going to update everything correctly.
339 ex_cinit(sp, &cmd, C_QUIT, 0, OOBLNO, OOBLNO, 0);
340 return (cmd.cmd->fn(sp, &cmd));
344 * api_swscreen --
345 * Switch to a new screen.
347 * PUBLIC: int api_swscreen __P((SCR *, SCR *));
350 api_swscreen(SCR *sp, SCR *new)
353 * XXX
354 * If the interpreter switches from anything other than the
355 * current screen, vi isn't going to update everything correctly.
357 sp->nextdisp = new;
358 F_SET(sp, SC_SSWITCH);
360 return (0);
364 * api_map --
365 * Map a key.
367 * PUBLIC: int api_map __P((SCR *, char *, char *, size_t));
370 api_map(SCR *sp, char *name, char *map, size_t len)
372 EXCMD cmd;
373 size_t wlen;
374 const CHAR_T *wp;
376 ex_cinit(sp, &cmd, C_MAP, 0, OOBLNO, OOBLNO, 0);
377 CHAR2INT(sp, name, strlen(name) + 1, wp, wlen);
378 argv_exp0(sp, &cmd, wp, wlen - 1);
379 CHAR2INT(sp, map, len, wp, wlen);
380 argv_exp0(sp, &cmd, wp, wlen);
381 return (cmd.cmd->fn(sp, &cmd));
385 * api_unmap --
386 * Unmap a key.
388 * PUBLIC: int api_unmap __P((SCR *, char *));
390 int
391 api_unmap(SCR *sp, char *name)
393 EXCMD cmd;
394 size_t wlen;
395 const CHAR_T *wp;
397 ex_cinit(sp, &cmd, C_UNMAP, 0, OOBLNO, OOBLNO, 0);
398 CHAR2INT(sp, name, strlen(name) + 1, wp, wlen);
399 argv_exp0(sp, &cmd, wp, wlen - 1);
400 return (cmd.cmd->fn(sp, &cmd));
404 * api_opts_get --
405 * Return a option value as a string, in allocated memory.
406 * If the option is of type boolean, boolvalue is (un)set
407 * according to the value; otherwise boolvalue is -1.
409 * PUBLIC: int api_opts_get __P((SCR *, CHAR_T *, char **, int *));
412 api_opts_get(SCR *sp, const CHAR_T *name, char **value, int *boolvalue)
414 OPTLIST const *op;
415 int offset;
417 if ((op = opts_search(name)) == NULL) {
418 opts_nomatch(sp, name);
419 return (1);
422 offset = op - optlist;
423 if (boolvalue != NULL)
424 *boolvalue = -1;
425 switch (op->type) {
426 case OPT_0BOOL:
427 case OPT_1BOOL:
428 MALLOC_RET(sp, *value, char *, STRLEN(op->name) + 2 + 1);
429 (void)sprintf(*value,
430 "%s"WS, O_ISSET(sp, offset) ? "" : "no", op->name);
431 if (boolvalue != NULL)
432 *boolvalue = O_ISSET(sp, offset);
433 break;
434 case OPT_NUM:
435 MALLOC_RET(sp, *value, char *, 20);
436 (void)sprintf(*value, "%lu", (u_long)O_VAL(sp, offset));
437 break;
438 case OPT_STR:
439 if (O_STR(sp, offset) == NULL) {
440 MALLOC_RET(sp, *value, char *, 2);
441 value[0] = '\0';
442 } else {
443 MALLOC_RET(sp,
444 *value, char *, strlen(O_STR(sp, offset)) + 1);
445 (void)sprintf(*value, "%s", O_STR(sp, offset));
447 break;
449 return (0);
453 * api_opts_set --
454 * Set options.
456 * PUBLIC: int api_opts_set __P((SCR *, CHAR_T *, char *, u_long, int));
459 api_opts_set(SCR *sp, const CHAR_T *name,
460 const char *str_value, u_long num_value, int bool_value)
462 ARGS *ap[2], a, b;
463 OPTLIST const *op;
464 int rval;
465 size_t blen;
466 CHAR_T *bp;
468 if ((op = opts_search(name)) == NULL) {
469 opts_nomatch(sp, name);
470 return (1);
473 switch (op->type) {
474 case OPT_0BOOL:
475 case OPT_1BOOL:
476 GET_SPACE_RETW(sp, bp, blen, 64);
477 a.len = SPRINTF(bp, 64, L("%s"WS), bool_value ? "" : "no", name);
478 break;
479 case OPT_NUM:
480 GET_SPACE_RETW(sp, bp, blen, 64);
481 a.len = SPRINTF(bp, 64, L(""WS"=%lu"), name, num_value);
482 break;
483 case OPT_STR:
484 GET_SPACE_RETW(sp, bp, blen, 1024);
485 a.len = SPRINTF(bp, 1024, L(""WS"=%s"), name, str_value);
486 break;
487 default:
488 bp = NULL;
489 break;
492 a.bp = bp;
493 b.len = 0;
494 b.bp = NULL;
495 ap[0] = &a;
496 ap[1] = &b;
497 rval = opts_set(sp, ap, NULL);
499 FREE_SPACEW(sp, bp, blen);
501 return (rval);
505 * api_run_str --
506 * Execute a string as an ex command.
508 * PUBLIC: int api_run_str __P((SCR *, char *));
510 int
511 api_run_str(SCR *sp, char *cmd)
513 size_t wlen;
514 const CHAR_T *wp;
516 CHAR2INT(sp, cmd, strlen(cmd)+1, wp, wlen);
517 return (ex_run_str(sp, NULL, wp, wlen - 1, 0, 0));
521 * PUBLIC: TAGQ * api_tagq_new __P((SCR*, char*));
523 TAGQ *
524 api_tagq_new(SCR *sp, char *tag)
526 TAGQ *tqp;
527 size_t len;
529 /* Allocate and initialize the tag queue structure. */
530 len = strlen(tag);
531 CALLOC_GOTO(sp, tqp, TAGQ *, 1, sizeof(TAGQ) + len + 1);
532 CIRCLEQ_INIT(&tqp->tagq);
533 tqp->tag = tqp->buf;
534 memcpy(tqp->tag, tag, (tqp->tlen = len) + 1);
536 return tqp;
538 alloc_err:
539 return (NULL);
543 * PUBLIC: void api_tagq_add __P((SCR*, TAGQ*, char*, char *, char *));
545 void
546 api_tagq_add(SCR *sp, TAGQ *tqp, char *filename, char *search, char *msg)
548 TAG *tp;
549 const CHAR_T *wp;
550 size_t wlen;
551 size_t flen = strlen(filename);
552 size_t slen = strlen(search);
553 size_t mlen = strlen(msg);
555 CALLOC_GOTO(sp, tp, TAG *, 1,
556 sizeof(TAG) - 1 + flen + 1 +
557 (slen + 1 + mlen + 1) * sizeof(CHAR_T));
558 tp->fname = (char *)tp->buf;
559 memcpy(tp->fname, filename, flen + 1);
560 tp->fnlen = flen;
561 tp->search = (CHAR_T *)((char *)tp->fname + flen + 1);
562 CHAR2INT(sp, search, slen + 1, wp, wlen);
563 MEMCPYW(tp->search, wp, wlen);
564 tp->slen = slen;
565 tp->msg = tp->search + slen + 1;
566 CHAR2INT(sp, msg, mlen + 1, wp, wlen);
567 MEMCPYW(tp->msg, wp, wlen);
568 tp->mlen = mlen;
569 CIRCLEQ_INSERT_TAIL(&tqp->tagq, tp, q);
571 alloc_err:
572 return;
576 * PUBLIC: int api_tagq_push __P((SCR*, TAGQ**));
579 api_tagq_push(SCR *sp, TAGQ **tqpp)
581 TAGQ *tqp;
583 tqp = *tqpp;
585 *tqpp = 0;
587 /* Check to see if we found anything. */
588 if (tqp->tagq.cqh_first == (void *)&tqp->tagq) {
589 free(tqp);
590 return 0;
593 tqp->current = tqp->tagq.cqh_first;
595 if (tagq_push(sp, tqp, 0, 0))
596 return 1;
598 return (0);
602 * PUBLIC: void api_tagq_free __P((SCR*, TAGQ*));
604 void
605 api_tagq_free(SCR *sp, TAGQ *tqp)
607 if (tqp)
608 tagq_free(sp, tqp);