vi: update the dimensions of a single window when the terminal is resized
[neatvi.git] / tag.c
blobb7f2841ebcf704076ebc2c4b03e634793eca207b
1 #include <fcntl.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <sys/stat.h>
6 #include <unistd.h>
7 #include "vi.h"
9 static char *tagpath;
10 static char *tag;
11 static long taglen;
13 int tag_init(void)
15 return 0;
18 static int tag_load(void)
20 char buf[1 << 10];
21 struct sbuf *sb;
22 long nr;
23 int fd;
24 if (tagpath != NULL)
25 return tag == NULL;
26 tagpath = getenv("TAGPATH") ? getenv("TAGPATH") : "tags";
27 if ((fd = open(tagpath, O_RDONLY)) < 0)
28 return 1;
29 sb = sbuf_make();
30 while ((nr = read(fd, buf, sizeof(buf))) > 0)
31 sbuf_mem(sb, buf, nr);
32 close(fd);
33 taglen = sbuf_len(sb);
34 tag = sbuf_done(sb);
35 return 0;
38 void tag_done(void)
40 free(tag);
41 tag = NULL;
42 tagpath = NULL;
45 static char *copypart(char *dst, int dstlen, char *src)
47 char *end = src;
48 int len = dstlen - 1;
49 while (*end && *end != '\t' && *end != '\n')
50 end++;
51 if (end - src < len)
52 len = end - src;
53 memcpy(dst, src, len);
54 dst[len] = '\0';
55 return *end ? end + 1 : end;
58 static char *tag_next(char *s, int dir)
60 if (dir >= 0 && *s) {
61 if ((s = strchr(s + 1, '\n')) != NULL)
62 return s + 1;
64 if (dir < 0 && s > tag) {
65 s--;
66 while (s > tag && s[-1] != '\n')
67 s--;
68 return s;
70 return NULL;
73 int tag_find(char *name, int *pos, int dir, char *path, int pathlen, char *cmd, int cmdlen)
75 char *s;
76 int len = strlen(name);
77 if (tag_load() != 0)
78 return 1;
79 if (*pos >= taglen)
80 *pos = 0;
81 s = dir != 0 ? tag_next(tag + *pos, dir) : tag + *pos;
82 while (s) {
83 if (!strncmp(name, s, len) && s[len] == '\t') {
84 char *r = copypart(path, pathlen, s + len + 1);
85 copypart(cmd, cmdlen, r);
86 *pos = s - tag;
87 return 0;
89 s = tag_next(s, dir);
91 return 1;