Document the recently added WITHOUT_SRCS variable.
[dragonfly.git] / contrib / nvi / common / api.c
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.
8  *
9  * See the LICENSE file for redistribution information.
10  */
11
12 #include "config.h"
13
14 #ifndef lint
15 static const char sccsid[] = "@(#)api.c 8.26 (Berkeley) 10/14/96";
16 #endif /* not lint */
17
18 #include <sys/types.h>
19 #include <sys/queue.h>
20 #include <sys/time.h>
21
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>
29
30 #include "../common/common.h"
31
32 extern GS *__global_list;                       /* XXX */
33
34 /*
35  * api_fscreen --
36  *      Return a pointer to the screen specified by the screen id
37  *      or a file name.
38  *
39  * PUBLIC: SCR *api_fscreen __P((int, char *));
40  */
41 SCR *
42 api_fscreen(id, name)
43         int id;
44         char *name;
45 {
46         GS *gp;
47         SCR *tsp;
48
49         gp = __global_list;
50
51         /* Search the displayed list. */
52         for (tsp = gp->dq.cqh_first;
53             tsp != (void *)&gp->dq; tsp = tsp->q.cqe_next)
54                 if (name == NULL) {
55                         if (id == tsp->id)
56                                 return (tsp);
57                 } else if (!strcmp(name, tsp->frp->name))
58                         return (tsp);
59
60         /* Search the hidden list. */
61         for (tsp = gp->hq.cqh_first;
62             tsp != (void *)&gp->hq; tsp = tsp->q.cqe_next)
63                 if (name == NULL) {
64                         if (id == tsp->id)
65                                 return (tsp);
66                 } else if (!strcmp(name, tsp->frp->name))
67                         return (tsp);
68         return (NULL);
69 }
70
71 /*
72  * api_aline --
73  *      Append a line.
74  *
75  * PUBLIC: int api_aline __P((SCR *, recno_t, char *, size_t));
76  */
77 int
78 api_aline(sp, lno, line, len)
79         SCR *sp;
80         recno_t lno;
81         char *line;
82         size_t len;
83 {
84         return (db_append(sp, 1, lno, line, len));
85 }
86
87 /*
88  * api_dline --
89  *      Delete a line.
90  *
91  * PUBLIC: int api_dline __P((SCR *, recno_t));
92  */
93 int
94 api_dline(sp, lno)
95         SCR *sp;
96         recno_t lno;
97 {
98         return (db_delete(sp, lno));
99 }
100
101 /*
102  * api_gline --
103  *      Get a line.
104  *
105  * PUBLIC: int api_gline __P((SCR *, recno_t, char **, size_t *));
106  */
107 int
108 api_gline(sp, lno, linepp, lenp)
109         SCR *sp;
110         recno_t lno;
111         char **linepp;
112         size_t *lenp;
113 {
114         int isempty;
115
116         if (db_eget(sp, lno, linepp, lenp, &isempty)) {
117                 if (isempty)
118                         msgq(sp, M_ERR, "209|The file is empty");
119                 return (1);
120         }
121         return (0);
122 }
123
124 /*
125  * api_iline --
126  *      Insert a line.
127  *
128  * PUBLIC: int api_iline __P((SCR *, recno_t, char *, size_t));
129  */
130 int
131 api_iline(sp, lno, line, len)
132         SCR *sp;
133         recno_t lno;
134         char *line;
135         size_t len;
136 {
137         return (db_insert(sp, lno, line, len));
138 }
139
140 /*
141  * api_lline --
142  *      Return the line number of the last line in the file.
143  *
144  * PUBLIC: int api_lline __P((SCR *, recno_t *));
145  */
146 int
147 api_lline(sp, lnop)
148         SCR *sp;
149         recno_t *lnop;
150 {
151         return (db_last(sp, lnop));
152 }
153
154 /*
155  * api_sline --
156  *      Set a line.
157  *
158  * PUBLIC: int api_sline __P((SCR *, recno_t, char *, size_t));
159  */
160 int
161 api_sline(sp, lno, line, len)
162         SCR *sp;
163         recno_t lno;
164         char *line;
165         size_t len;
166 {
167         return (db_set(sp, lno, line, len));
168 }
169
170 /*
171  * api_getmark --
172  *      Get the mark.
173  *
174  * PUBLIC: int api_getmark __P((SCR *, int, MARK *));
175  */
176 int
177 api_getmark(sp, markname, mp)
178         SCR *sp;
179         int markname;
180         MARK *mp;
181 {
182         return (mark_get(sp, (ARG_CHAR_T)markname, mp, M_ERR));
183 }
184
185 /*
186  * api_setmark --
187  *      Set the mark.
188  *
189  * PUBLIC: int api_setmark __P((SCR *, int, MARK *));
190  */
191 int
192 api_setmark(sp, markname, mp)
193         SCR *sp;
194         int markname;
195         MARK *mp;
196 {
197         return (mark_set(sp, (ARG_CHAR_T)markname, mp, 1));
198 }
199
200 /*
201  * api_nextmark --
202  *      Return the first mark if next not set, otherwise return the
203  *      subsequent mark.
204  *
205  * PUBLIC: int api_nextmark __P((SCR *, int, char *));
206  */
207 int
208 api_nextmark(sp, next, namep)
209         SCR *sp;
210         int next;
211         char *namep;
212 {
213         LMARK *mp;
214
215         mp = sp->ep->marks.lh_first;
216         if (next)
217                 for (; mp != NULL; mp = mp->q.le_next)
218                         if (mp->name == *namep) {
219                                 mp = mp->q.le_next;
220                                 break;
221                         }
222         if (mp == NULL)
223                 return (1);
224         *namep = mp->name;
225         return (0);
226 }
227
228 /*
229  * api_getcursor --
230  *      Get the cursor.
231  *
232  * PUBLIC: int api_getcursor __P((SCR *, MARK *));
233  */
234 int
235 api_getcursor(sp, mp)
236         SCR *sp;
237         MARK *mp;
238 {
239         mp->lno = sp->lno;
240         mp->cno = sp->cno;
241         return (0);
242 }
243
244 /*
245  * api_setcursor --
246  *      Set the cursor.
247  *
248  * PUBLIC: int api_setcursor __P((SCR *, MARK *));
249  */
250 int
251 api_setcursor(sp, mp)
252         SCR *sp;
253         MARK *mp;
254 {
255         size_t len;
256
257         if (db_get(sp, mp->lno, DBG_FATAL, NULL, &len))
258                 return (1);
259         if (mp->cno < 0 || mp->cno > len) {
260                 msgq(sp, M_ERR, "Cursor set to nonexistent column");
261                 return (1);
262         }
263
264         /* Set the cursor. */
265         sp->lno = mp->lno;
266         sp->cno = mp->cno;
267         return (0);
268 }
269
270 /*
271  * api_emessage --
272  *      Print an error message.
273  *
274  * PUBLIC: void api_emessage __P((SCR *, char *));
275  */
276 void
277 api_emessage(sp, text)
278         SCR *sp;
279         char *text;
280 {
281         msgq(sp, M_ERR, "%s", text);
282 }
283
284 /*
285  * api_imessage --
286  *      Print an informational message.
287  *
288  * PUBLIC: void api_imessage __P((SCR *, char *));
289  */
290 void
291 api_imessage(sp, text)
292         SCR *sp;
293         char *text;
294 {
295         msgq(sp, M_INFO, "%s", text);
296 }
297
298 /*
299  * api_edit
300  *      Create a new screen and return its id 
301  *      or edit a new file in the current screen.
302  *
303  * PUBLIC: int api_edit __P((SCR *, char *, SCR **, int));
304  */
305 int
306 api_edit(sp, file, spp, newscreen)
307         SCR *sp;
308         char *file;
309         SCR **spp;
310         int newscreen;
311 {
312         ARGS *ap[2], a;
313         EXCMD cmd;
314
315         if (file) {
316                 ex_cinit(&cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0, ap);
317                 ex_cadd(&cmd, &a, file, strlen(file));
318         } else
319                 ex_cinit(&cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0, NULL);
320         if (newscreen)
321                 cmd.flags |= E_NEWSCREEN;               /* XXX */
322         if (cmd.cmd->fn(sp, &cmd))
323                 return (1);
324         *spp = sp->nextdisp;
325         return (0);
326 }
327
328 /*
329  * api_escreen
330  *      End a screen.
331  *
332  * PUBLIC: int api_escreen __P((SCR *));
333  */
334 int
335 api_escreen(sp)
336         SCR *sp;
337 {
338         EXCMD cmd;
339
340         /*
341          * XXX
342          * If the interpreter exits anything other than the current
343          * screen, vi isn't going to update everything correctly.
344          */
345         ex_cinit(&cmd, C_QUIT, 0, OOBLNO, OOBLNO, 0, NULL);
346         return (cmd.cmd->fn(sp, &cmd));
347 }
348
349 /*
350  * api_swscreen --
351  *    Switch to a new screen.
352  *
353  * PUBLIC: int api_swscreen __P((SCR *, SCR *));
354  */
355 int
356 api_swscreen(sp, new)
357       SCR *sp, *new;
358 {
359         /*
360          * XXX
361          * If the interpreter switches from anything other than the
362          * current screen, vi isn't going to update everything correctly.
363          */
364         sp->nextdisp = new;
365         F_SET(sp, SC_SSWITCH);
366
367         return (0);
368 }
369
370 /*
371  * api_map --
372  *      Map a key.
373  *
374  * PUBLIC: int api_map __P((SCR *, char *, char *, size_t));
375  */
376 int
377 api_map(sp, name, map, len)
378         SCR *sp;
379         char *name, *map;
380         size_t len;
381 {
382         ARGS *ap[3], a, b;
383         EXCMD cmd;
384
385         ex_cinit(&cmd, C_MAP, 0, OOBLNO, OOBLNO, 0, ap);
386         ex_cadd(&cmd, &a, name, strlen(name));
387         ex_cadd(&cmd, &b, map, len);
388         return (cmd.cmd->fn(sp, &cmd));
389 }
390
391 /*
392  * api_unmap --
393  *      Unmap a key.
394  *
395  * PUBLIC: int api_unmap __P((SCR *, char *));
396  */
397 int 
398 api_unmap(sp, name)
399         SCR *sp;
400         char *name;
401 {
402         ARGS *ap[2], a;
403         EXCMD cmd;
404
405         ex_cinit(&cmd, C_UNMAP, 0, OOBLNO, OOBLNO, 0, ap);
406         ex_cadd(&cmd, &a, name, strlen(name));
407         return (cmd.cmd->fn(sp, &cmd));
408 }
409
410 /*
411  * api_opts_get --
412  *      Return a option value as a string, in allocated memory.
413  *      If the option is of type boolean, boolvalue is (un)set
414  *      according to the value; otherwise boolvalue is -1.
415  *
416  * PUBLIC: int api_opts_get __P((SCR *, char *, char **, int *));
417  */
418 int
419 api_opts_get(sp, name, value, boolvalue)
420         SCR *sp;
421         char *name, **value;
422         int *boolvalue;
423 {
424         OPTLIST const *op;
425         int offset;
426
427         if ((op = opts_search(name)) == NULL) {
428                 opts_nomatch(sp, name);
429                 return (1);
430         }
431
432         offset = op - optlist;
433         if (boolvalue != NULL)
434                 *boolvalue = -1;
435         switch (op->type) {
436         case OPT_0BOOL:
437         case OPT_1BOOL:
438                 MALLOC_RET(sp, *value, char *, strlen(op->name) + 2 + 1);
439                 (void)sprintf(*value,
440                     "%s%s", O_ISSET(sp, offset) ? "" : "no", op->name);
441                 if (boolvalue != NULL)
442                         *boolvalue = O_ISSET(sp, offset);
443                 break;
444         case OPT_NUM:
445                 MALLOC_RET(sp, *value, char *, 20);
446                 (void)sprintf(*value, "%lu", (u_long)O_VAL(sp, offset));
447                 break;
448         case OPT_STR:
449                 if (O_STR(sp, offset) == NULL) {
450                         MALLOC_RET(sp, *value, char *, 2);
451                         value[0] = '\0';
452                 } else {
453                         MALLOC_RET(sp,
454                             *value, char *, strlen(O_STR(sp, offset)) + 1);
455                         (void)sprintf(*value, "%s", O_STR(sp, offset));
456                 }
457                 break;
458         }
459         return (0);
460 }
461
462 /*
463  * api_opts_set --
464  *      Set options.
465  *
466  * PUBLIC: int api_opts_set __P((SCR *, char *, char *, u_long, int));
467  */
468 int
469 api_opts_set(sp, name, str_value, num_value, bool_value)
470         SCR *sp;
471         char *name, *str_value;
472         u_long num_value;
473         int bool_value;
474 {
475         ARGS *ap[2], a, b;
476         OPTLIST const *op;
477         int rval;
478         size_t blen;
479         char *bp;
480
481         if ((op = opts_search(name)) == NULL) {
482                 opts_nomatch(sp, name);
483                 return (1);
484         }
485
486         switch (op->type) {
487         case OPT_0BOOL:
488         case OPT_1BOOL:
489                 GET_SPACE_RET(sp, bp, blen, 64);
490                 a.len = snprintf(bp, 64, "%s%s", bool_value ? "" : "no", name);
491                 break;
492         case OPT_NUM:
493                 GET_SPACE_RET(sp, bp, blen, 64);
494                 a.len = snprintf(bp, 64, "%s=%lu", name, num_value);
495                 break;
496         case OPT_STR:
497                 GET_SPACE_RET(sp, bp, blen, 1024);
498                 a.len = snprintf(bp, 1024, "%s=%s", name, str_value);
499                 break;
500         }
501         a.bp = bp;
502         b.len = 0;
503         b.bp = NULL;
504         ap[0] = &a;
505         ap[1] = &b;
506         rval = opts_set(sp, ap, NULL);
507
508         FREE_SPACE(sp, bp, blen);
509
510         return (rval);
511 }
512
513 /*
514  * api_run_str --
515  *      Execute a string as an ex command.
516  *
517  * PUBLIC: int api_run_str __P((SCR *, char *));
518  */
519 int     
520 api_run_str(sp, cmd)
521         SCR *sp;
522         char *cmd;
523 {
524         return (ex_run_str(sp, NULL, cmd, strlen(cmd), 0, 0));
525 }