1 /* $MirOS: contrib/code/jupp/tab.c,v 1.6 2017/01/10 19:16:28 tg Exp $ */
5 * (C) 1992 Joseph H. Allen
7 * This file is part of JOE (Joe's Own Editor)
12 #ifdef HAVE_SYS_TYPES_H
13 #include <sys/types.h>
15 #ifdef HAVE_SYS_STAT_H
30 typedef struct tab TAB;
32 extern int smode; /* ??? */
34 int menu_explorer = 0; /* Stay in menu system when directory selected */
37 int first_len; /* Original size of path */
38 int ofst; /* Starting offset to path */
39 unsigned char *path; /* current directory */
40 unsigned char *pattern; /* search pattern */
41 int len; /* no. entries in files */
42 unsigned char **files; /* array of file names */
44 unsigned char *type; /* file type array */
46 unsigned char *orgpath;
47 unsigned char *orgnam;
50 #define F_DIR 1 /* type codes for file type array */
54 /* Read matching files from a directory
55 * Directory is given in tab.path
56 * Pattern is given in tab.pattern
58 * Returns with -1 if there was an error
59 * Otherwise returns index to file with inode given in prv
60 * len and files are set with the file names
61 * type is set with the file types
64 static int get_entries(TAB *tab, int prv)
68 unsigned char *oldpwd = pwd();
69 unsigned char **files;
73 files = rexpnd(tab->pattern);
82 tab->len = aLEN(files);
85 vasort(files, tab->len);
88 tab->type = (unsigned char *) joe_malloc(tab->len);
89 for (a = 0; a != tab->len; a++) {
91 mset(&buf, 0, sizeof(struct stat));
93 stat((char *)(files[a]), &buf);
94 if ((int)buf.st_ino == prv)
96 if ((buf.st_mode & S_IFMT) == S_IFDIR)
98 else if (buf.st_mode & (0100 | 0010 | 0001))
99 tab->type[a] = F_EXEC;
101 tab->type[a] = F_NORMAL;
107 static void insnam(BW *bw, unsigned char *path, unsigned char *nam, int dir, int ofst)
109 P *p = pdup(bw->cursor);
112 p_goto_eol(bw->cursor);
115 binsm(bw->cursor, sv(path));
116 p_goto_eol(bw->cursor);
117 if (path[sLEN(path) - 1] != '/') {
118 binsm(bw->cursor, sc("/"));
119 p_goto_eol(bw->cursor);
122 binsm(bw->cursor, sv(nam));
123 p_goto_eol(bw->cursor);
125 binsm(bw->cursor, sc("/"));
126 p_goto_eol(bw->cursor);
129 bw->cursor->xcol = piscol(bw->cursor);
132 /* Given a menu structure with a tab structure as its object,
133 * a pattern and path set in the tab structure:
135 * Load the menu with a list of file names and set the file name in
136 * the prompt window to the directory the menu was read in from.
137 * If flg is set, treload attempts to position to the previous directory
140 * Returns with -1 if there was an error
141 * Returns with 0 for success
144 static unsigned char **treload(TAB *tab,MENU *m, BW *bw, int flg,int *defer)
150 if ((which = get_entries(tab, tab->prv)) < 0)
152 if (tab->path && tab->path[0])
153 stat((char *)tab->path, &buf);
156 tab->prv = buf.st_ino;
160 tab->list = vatrunc(tab->list, aLEN(tab->files));
162 for (x = 0; tab->files[x]; ++x) {
163 unsigned char *s = vsncpy(NULL, 0, sv(tab->files[x]));
165 tab->list = vaset(tab->list, x, s);
166 if (tab->type[x] == F_DIR)
167 tab->list[x] = vsadd(tab->list[x], '/');
168 else if (tab->type[x] == F_EXEC)
169 tab->list[x] = vsadd(tab->list[x], '*');
173 insnam(bw, tab->path, tab->pattern, 0, tab->ofst);
176 ldmenu(m, tab->list, which);
177 insnam(bw, tab->path, tab->pattern, 0, tab->ofst);
182 static void rmtab(TAB *tab)
194 /*****************************************************************************/
195 /****************** The user hit return **************************************/
196 /*****************************************************************************/
197 static int tabrtn(MENU *m, int cursor, TAB *tab)
199 if (menu_explorer && tab->type[cursor] == F_DIR) { /* Switch directories */
200 unsigned char *orgpath = tab->path;
201 unsigned char *orgpattern = tab->pattern;
202 unsigned char *e = endprt(tab->path);
204 /* if (!strcmp(tab->files[cursor], "..") && sLEN(e)
205 && !(e[0] == '.' && e[1] == '.' && (!e[2] || e[2] == '/')))
206 tab->path = begprt(tab->path);
208 tab->path = vsncpy(NULL, 0, sv(tab->path));
209 tab->path = vsncpy(sv(tab->path), sv(m->list[cursor]));
212 tab->pattern = vsncpy(NULL, 0, sc("*"));
213 if (!treload(m->object, m, m->parent->win->object, 0, NULL)) {
214 msgnw(m->parent, US "Couldn't read directory ");
216 tab->pattern = orgpattern;
225 } else { /* Select name */
226 BW *bw = m->parent->win->object;
228 insnam(bw, tab->path, tab->files[cursor], (tab->type[cursor]==F_DIR), tab->ofst);
237 /* Like above, but treats directories as files (adds them to path instead of
238 * traverse hierarchy) */
240 static int tabrtn1(MENU *m, int cursor, TAB *tab)
242 /* New way: just add directory to path */
243 BW *bw = m->parent->win->object;
245 insnam(bw, tab->path, tab->files[cursor], (tab->type[cursor]==F_DIR ? 1 : 0), tab->ofst);
254 /*****************************************************************************/
255 /****************** The user hit backspace ***********************************/
256 /*****************************************************************************/
257 static int tabbacks(MENU *m, int cursor, TAB *tab)
259 unsigned char *orgpath = tab->path;
260 unsigned char *orgpattern = tab->pattern;
261 unsigned char *e = endprt(tab->path);
263 if (sLEN(e) && sLEN(tab->path)!=tab->first_len)
264 tab->path = begprt(tab->path);
270 tab->pattern = vsncpy(NULL, 0, sc("*"));
272 if (!treload(m->object, m, m->parent->win->object, 1, NULL)) {
273 msgnw(m->parent, US "Couldn't read directory ");
275 tab->pattern = orgpattern;
285 /*****************************************************************************/
286 static int tababrt(BW *bw, int cursor, TAB *tab)
288 insnam(bw, tab->orgpath, tab->orgnam, 0, tab->ofst);
293 static void p_goto_start_of_path(P *p)
295 while (/* CONSTCOND */ 1)
305 /*****************************************************************************/
306 /****************** Create a tab window **************************************/
307 /*****************************************************************************/
313 unsigned char *cline, *tmp;
319 tab = (TAB *) joe_malloc(sizeof(TAB));
326 q = pdup(bw->cursor);
329 p_goto_start_of_path(p);
332 tmp = brvs(p, (int) (q->byte - p->byte));
333 cline = parsens(tmp, &a, &b);
339 tab->pattern = namprt(cline);
340 tab->path = dirprt(cline);
341 tab->first_len = sLEN(tab->path);
342 tab->orgnam = vsncpy(NULL, 0, sv(tab->pattern));
343 tab->orgpath = vsncpy(NULL, 0, sv(tab->path));
344 tab->pattern = vsadd(tab->pattern, '*');
347 l = treload(tab, 0, bw, 0, &which);
349 if (l && (new = mkmenu(bw->parent, l, tabrtn, tababrt, tabbacks, which, tab, NULL))) {
350 if (sLEN(tab->files) == 1)
351 return tabrtn1(new, 0, tab);
352 else if (smode || isreg(tab->orgnam))
355 unsigned char *com = mcomplete(new);