/* $NetBSD: api.c,v 1.4 2014/01/26 21:43:45 christos Exp $ */ /*- * Copyright (c) 1992, 1993, 1994 * The Regents of the University of California. All rights reserved. * Copyright (c) 1992, 1993, 1994, 1995, 1996 * Keith Bostic. All rights reserved. * Copyright (c) 1995 * George V. Neville-Neil. All rights reserved. * * See the LICENSE file for redistribution information. */ #include "config.h" #include #if 0 #ifndef lint 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 "; #endif /* not lint */ #else __RCSID("$NetBSD: api.c,v 1.4 2014/01/26 21:43:45 christos Exp $"); #endif #include #include #include #include #include #include #include #include #include #include #include "../common/common.h" #include "../ex/tag.h" extern GS *__global_list; /* XXX */ /* * api_fscreen -- * Return a pointer to the screen specified by the screen id * or a file name. * * PUBLIC: SCR *api_fscreen __P((int, char *)); */ SCR * api_fscreen(int id, char *name) { GS *gp; SCR *tsp; WIN *wp; gp = __global_list; /* Search the displayed lists. */ TAILQ_FOREACH(wp, &gp->dq, q) TAILQ_FOREACH(tsp, &wp->scrq, q) if (name == NULL) { if (id == tsp->id) return (tsp); } else if (!strcmp(name, tsp->frp->name)) return (tsp); /* Search the hidden list. */ TAILQ_FOREACH (tsp, &gp->hq, q) if (name == NULL) { if (id == tsp->id) return (tsp); } else if (!strcmp(name, tsp->frp->name)) return (tsp); return (NULL); } /* * api_aline -- * Append a line. * * PUBLIC: int api_aline __P((SCR *, db_recno_t, char *, size_t)); */ int api_aline(SCR *sp, db_recno_t lno, char *line, size_t len) { size_t wblen; const CHAR_T *wbp; CHAR2INT(sp, line, len, wbp, wblen); return (db_append(sp, 1, lno, wbp, wblen)); } /* * api_extend -- * Extend file. * * PUBLIC: int api_extend __P((SCR *, db_recno_t)); */ int api_extend(SCR *sp, db_recno_t lno) { db_recno_t lastlno; if (db_last(sp, &lastlno)) return 1; while(lastlno < lno) if (db_append(sp, 1, lastlno++, NULL, 0)) return 1; return 0; } /* * api_dline -- * Delete a line. * * PUBLIC: int api_dline __P((SCR *, db_recno_t)); */ int api_dline(SCR *sp, db_recno_t lno) { if (db_delete(sp, lno)) return 1; /* change current line if deleted line is that one * or one berfore that */ if (sp->lno >= lno && sp->lno > 1) sp->lno--; return 0; } /* * api_gline -- * Get a line. * * PUBLIC: int api_gline __P((SCR *, db_recno_t, CHAR_T **, size_t *)); */ int api_gline(SCR *sp, db_recno_t lno, CHAR_T **linepp, size_t *lenp) { int isempty; if (db_eget(sp, lno, linepp, lenp, &isempty)) { if (isempty) msgq(sp, M_ERR, "209|The file is empty"); return (1); } return (0); } /* * api_iline -- * Insert a line. * * PUBLIC: int api_iline __P((SCR *, db_recno_t, CHAR_T *, size_t)); */ int api_iline(SCR *sp, db_recno_t lno, CHAR_T *line, size_t len) { return (db_insert(sp, lno, line, len)); } /* * api_lline -- * Return the line number of the last line in the file. * * PUBLIC: int api_lline __P((SCR *, db_recno_t *)); */ int api_lline(SCR *sp, db_recno_t *lnop) { return (db_last(sp, lnop)); } /* * api_sline -- * Set a line. * * PUBLIC: int api_sline __P((SCR *, db_recno_t, CHAR_T *, size_t)); */ int api_sline(SCR *sp, db_recno_t lno, CHAR_T *line, size_t len) { return (db_set(sp, lno, line, len)); } /* * api_getmark -- * Get the mark. * * PUBLIC: int api_getmark __P((SCR *, int, MARK *)); */ int api_getmark(SCR *sp, int markname, MARK *mp) { return (mark_get(sp, (ARG_CHAR_T)markname, mp, M_ERR)); } /* * api_setmark -- * Set the mark. * * PUBLIC: int api_setmark __P((SCR *, int, MARK *)); */ int api_setmark(SCR *sp, int markname, MARK *mp) { return (mark_set(sp, (ARG_CHAR_T)markname, mp, 1)); } /* * api_nextmark -- * Return the first mark if next not set, otherwise return the * subsequent mark. * * PUBLIC: int api_nextmark __P((SCR *, int, char *)); */ int api_nextmark(SCR *sp, int next, char *namep) { LMARK *mp; mp = LIST_FIRST(&sp->ep->marks); if (next) for (; mp != NULL; mp = LIST_NEXT(mp, q)) if (mp->name == *namep) { mp = LIST_NEXT(mp, q); break; } if (mp == NULL) return (1); *namep = mp->name; return (0); } /* * api_getcursor -- * Get the cursor. * * PUBLIC: int api_getcursor __P((SCR *, MARK *)); */ int api_getcursor(SCR *sp, MARK *mp) { mp->lno = sp->lno; mp->cno = sp->cno; return (0); } /* * api_setcursor -- * Set the cursor. * * PUBLIC: int api_setcursor __P((SCR *, MARK *)); */ int api_setcursor(SCR *sp, MARK *mp) { size_t len; if (db_get(sp, mp->lno, DBG_FATAL, NULL, &len)) return (1); if (mp->cno > len) { msgq(sp, M_ERR, "Cursor set to nonexistent column"); return (1); } /* Set the cursor. */ sp->lno = mp->lno; sp->cno = mp->cno; return (0); } /* * api_emessage -- * Print an error message. * * PUBLIC: void api_emessage __P((SCR *, char *)); */ void api_emessage(SCR *sp, char *text) { msgq(sp, M_ERR, "%s", text); } /* * api_imessage -- * Print an informational message. * * PUBLIC: void api_imessage __P((SCR *, char *)); */ void api_imessage(SCR *sp, char *text) { msgq(sp, M_INFO, "%s", text); } /* * api_edit * Create a new screen and return its id * or edit a new file in the current screen. * * PUBLIC: int api_edit __P((SCR *, char *, SCR **, int)); */ int api_edit(SCR *sp, char *file, SCR **spp, int newscreen) { EXCMD cmd; size_t wlen; const CHAR_T *wp; if (file) { ex_cinit(sp, &cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0); CHAR2INT(sp, file, strlen(file) + 1, wp, wlen); argv_exp0(sp, &cmd, wp, wlen - 1 /* terminating 0 */); } else ex_cinit(sp, &cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0); if (newscreen) cmd.flags |= E_NEWSCREEN; /* XXX */ if (cmd.cmd->fn(sp, &cmd)) return (1); *spp = sp->nextdisp; return (0); } /* * api_escreen * End a screen. * * PUBLIC: int api_escreen __P((SCR *)); */ int api_escreen(SCR *sp) { EXCMD cmd; /* * XXX * If the interpreter exits anything other than the current * screen, vi isn't going to update everything correctly. */ ex_cinit(sp, &cmd, C_QUIT, 0, OOBLNO, OOBLNO, 0); return (cmd.cmd->fn(sp, &cmd)); } /* * api_swscreen -- * Switch to a new screen. * * PUBLIC: int api_swscreen __P((SCR *, SCR *)); */ int api_swscreen(SCR *sp, SCR *new) { /* * XXX * If the interpreter switches from anything other than the * current screen, vi isn't going to update everything correctly. */ sp->nextdisp = new; F_SET(sp, SC_SSWITCH); return (0); } /* * api_map -- * Map a key. * * PUBLIC: int api_map __P((SCR *, char *, char *, size_t)); */ int api_map(SCR *sp, char *name, char *map, size_t len) { EXCMD cmd; size_t wlen; const CHAR_T *wp; ex_cinit(sp, &cmd, C_MAP, 0, OOBLNO, OOBLNO, 0); CHAR2INT(sp, name, strlen(name) + 1, wp, wlen); argv_exp0(sp, &cmd, wp, wlen - 1); CHAR2INT(sp, map, len, wp, wlen); argv_exp0(sp, &cmd, wp, wlen); return (cmd.cmd->fn(sp, &cmd)); } /* * api_unmap -- * Unmap a key. * * PUBLIC: int api_unmap __P((SCR *, char *)); */ int api_unmap(SCR *sp, char *name) { EXCMD cmd; size_t wlen; const CHAR_T *wp; ex_cinit(sp, &cmd, C_UNMAP, 0, OOBLNO, OOBLNO, 0); CHAR2INT(sp, name, strlen(name) + 1, wp, wlen); argv_exp0(sp, &cmd, wp, wlen - 1); return (cmd.cmd->fn(sp, &cmd)); } /* * api_opts_get -- * Return a option value as a string, in allocated memory. * If the option is of type boolean, boolvalue is (un)set * according to the value; otherwise boolvalue is -1. * * PUBLIC: int api_opts_get __P((SCR *, const CHAR_T *, char **, int *)); */ int api_opts_get(SCR *sp, const CHAR_T *name, char **value, int *boolvalue) { OPTLIST const *op; int offset; if ((op = opts_search(name)) == NULL) { opts_nomatch(sp, name); return (1); } offset = op - optlist; if (boolvalue != NULL) *boolvalue = -1; switch (op->type) { case OPT_0BOOL: case OPT_1BOOL: MALLOC_RET(sp, *value, char *, STRLEN(op->name) + 2 + 1); (void)sprintf(*value, "%s"WS, O_ISSET(sp, offset) ? "" : "no", op->name); if (boolvalue != NULL) *boolvalue = O_ISSET(sp, offset); break; case OPT_NUM: MALLOC_RET(sp, *value, char *, 20); (void)sprintf(*value, "%lu", (u_long)O_VAL(sp, offset)); break; case OPT_STR: if (O_STR(sp, offset) == NULL) { MALLOC_RET(sp, *value, char *, 2); value[0][0] = '\0'; } else { MALLOC_RET(sp, *value, char *, strlen(O_STR(sp, offset)) + 1); (void)sprintf(*value, "%s", O_STR(sp, offset)); } break; } return (0); } /* * api_opts_set -- * Set options. * * PUBLIC: int api_opts_set __P((SCR *, const CHAR_T *, const char *, u_long, int)); */ int api_opts_set(SCR *sp, const CHAR_T *name, const char *str_value, u_long num_value, int bool_value) { ARGS *ap[2], a, b; OPTLIST const *op; int rval; size_t blen; CHAR_T *bp; if ((op = opts_search(name)) == NULL) { opts_nomatch(sp, name); return (1); } switch (op->type) { case OPT_0BOOL: case OPT_1BOOL: GET_SPACE_RETW(sp, bp, blen, 64); a.len = SPRINTF(bp, 64, L("%s"WS), bool_value ? "" : "no", name); break; case OPT_NUM: GET_SPACE_RETW(sp, bp, blen, 64); a.len = SPRINTF(bp, 64, L(""WS"=%lu"), name, num_value); break; case OPT_STR: GET_SPACE_RETW(sp, bp, blen, 1024); a.len = SPRINTF(bp, 1024, L(""WS"=%s"), name, str_value); break; default: bp = NULL; break; } a.bp = bp; b.len = 0; b.bp = NULL; ap[0] = &a; ap[1] = &b; rval = opts_set(sp, ap, NULL); FREE_SPACEW(sp, bp, blen); return (rval); } /* * api_run_str -- * Execute a string as an ex command. * * PUBLIC: int api_run_str __P((SCR *, char *)); */ int api_run_str(SCR *sp, char *cmd) { size_t wlen; const CHAR_T *wp; CHAR2INT(sp, cmd, strlen(cmd)+1, wp, wlen); return (ex_run_str(sp, NULL, wp, wlen - 1, 0, 0)); } /* * PUBLIC: TAGQ * api_tagq_new __P((SCR*, char*)); */ TAGQ * api_tagq_new(SCR *sp, char *tag) { TAGQ *tqp; size_t len; /* Allocate and initialize the tag queue structure. */ len = strlen(tag); CALLOC_GOTO(sp, tqp, TAGQ *, 1, sizeof(TAGQ) + len + 1); TAILQ_INIT(&tqp->tagq); tqp->tag = tqp->buf; memcpy(tqp->tag, tag, (tqp->tlen = len) + 1); return tqp; alloc_err: return (NULL); } /* * PUBLIC: void api_tagq_add __P((SCR*, TAGQ*, char*, char *, char *)); */ void api_tagq_add(SCR *sp, TAGQ *tqp, char *filename, char *search, char *msg) { TAG *tp; const CHAR_T *wp; size_t wlen; size_t flen = strlen(filename); size_t slen = strlen(search); size_t mlen = strlen(msg); CALLOC_GOTO(sp, tp, TAG *, 1, sizeof(TAG) - 1 + flen + 1 + (slen + 1 + mlen + 1) * sizeof(CHAR_T)); tp->fname = (char *)tp->buf; memcpy(tp->fname, filename, flen + 1); tp->fnlen = flen; tp->search = (CHAR_T *)((char *)tp->fname + flen + 1); CHAR2INT(sp, search, slen + 1, wp, wlen); MEMCPYW(tp->search, wp, wlen); tp->slen = slen; tp->msg = tp->search + slen + 1; CHAR2INT(sp, msg, mlen + 1, wp, wlen); MEMCPYW(tp->msg, wp, wlen); tp->mlen = mlen; TAILQ_INSERT_TAIL(&tqp->tagq, tp, q); alloc_err: return; } /* * PUBLIC: int api_tagq_push __P((SCR*, TAGQ**)); */ int api_tagq_push(SCR *sp, TAGQ **tqpp) { TAGQ *tqp; tqp = *tqpp; *tqpp = 0; /* Check to see if we found anything. */ if (TAILQ_EMPTY(&tqp->tagq)) { free(tqp); return 0; } tqp->current = TAILQ_FIRST(&tqp->tagq); if (tagq_push(sp, tqp, 0, 0)) return 1; return (0); } /* * PUBLIC: void api_tagq_free __P((SCR*, TAGQ*)); */ void api_tagq_free(SCR *sp, TAGQ *tqp) { if (tqp) tagq_free(sp, tqp); }