#include <sys/queue.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "def.h"
#include "funmap.h"
#include "kbd.h"
void dired_init(void);
static int dired(int, int);
static int d_otherwindow(int, int);
static int d_undel(int, int);
static int d_undelbak(int, int);
static int d_findfile(int, int);
static int d_updirectory(int, int);
static int d_ffotherwindow(int, int);
static int d_expunge(int, int);
static int d_copy(int, int);
static int d_del(int, int);
static int d_rename(int, int);
static int d_exec(int, struct buffer *, const char *, const char *, ...);
static int d_shell_command(int, int);
static int d_create_directory(int, int);
static int d_makename(struct line *, char *, size_t);
static int d_warpdot(struct line *, int *);
static int d_forwpage(int, int);
static int d_backpage(int, int);
static int d_forwline(int, int);
static int d_backline(int, int);
static int d_killbuffer_cmd(int, int);
static int d_refreshbuffer(int, int);
static int d_filevisitalt(int, int);
static int d_gotofile(int, int);
static void reaper(int);
static int gotofile(char*);
static struct buffer *refreshbuffer(struct buffer *);
static int createlist(struct buffer *);
static void redelete(struct buffer *);
static char *findfname(struct line *, char *);
extern struct KEYMAPE (2) helpmap;
extern struct KEYMAPE (6) cXmap;
extern struct KEYMAPE (8) metamap;
const char DDELCHAR = 'D';
struct delentry {
SLIST_ENTRY(delentry) entry;
char *fn;
};
SLIST_HEAD(slisthead, delentry) delhead = SLIST_HEAD_INITIALIZER(delhead);
static PF dirednul[] = {
setmark,
gotobol,
backchar,
rescan,
d_del,
gotoeol,
forwchar,
ctrlg,
NULL,
};
static PF diredcl[] = {
reposition,
d_findfile,
d_forwline,
rescan,
d_backline,
rescan,
backisearch,
forwisearch,
rescan,
universal_argument,
d_forwpage,
rescan,
NULL
};
static PF diredcz[] = {
spawncli,
NULL,
rescan,
rescan,
rescan,
rescan,
d_forwline,
d_shell_command,
rescan,
rescan,
rescan,
rescan,
rescan,
rescan,
rescan,
rescan,
rescan,
d_create_directory
};
static PF diredcaret[] = {
d_updirectory
};
static PF direda[] = {
d_filevisitalt,
rescan,
d_copy,
d_del,
d_findfile,
d_findfile,
d_refreshbuffer,
rescan,
rescan,
d_gotofile
};
static PF diredn[] = {
d_forwline,
d_ffotherwindow,
d_backline,
d_killbuffer_cmd,
d_rename,
rescan,
rescan,
d_undel,
rescan,
rescan,
d_expunge
};
static PF direddl[] = {
d_undelbak
};
static PF diredbp[] = {
d_backpage
};
static PF dirednull[] = {
NULL
};
static struct KEYMAPE (1) d_backpagemap = {
1,
1,
rescan,
{
{
'v', 'v', diredbp, NULL
}
}
};
static struct KEYMAPE (8) diredmap = {
8,
8,
rescan,
{
{
CCHR('@'), CCHR('H'), dirednul, (KEYMAP *) & helpmap
},
{
CCHR('L'), CCHR('X'), diredcl, (KEYMAP *) & cXmap
},
{
CCHR('['), CCHR('['), dirednull, (KEYMAP *) &
d_backpagemap
},
{
CCHR('Z'), '+', diredcz, (KEYMAP *) & metamap
},
{
'^', '^', diredcaret, NULL
},
{
'a', 'j', direda, NULL
},
{
'n', 'x', diredn, NULL
},
{
CCHR('?'), CCHR('?'), direddl, NULL
},
}
};
void
dired_init(void)
{
funmap_add(dired, "dired", 1);
funmap_add(d_create_directory, "dired-create-directory", 1);
funmap_add(d_copy, "dired-do-copy", 1);
funmap_add(d_expunge, "dired-do-flagged-delete", 0);
funmap_add(d_rename, "dired-do-rename", 1);
funmap_add(d_findfile, "dired-find-file", 1);
funmap_add(d_ffotherwindow, "dired-find-file-other-window", 1);
funmap_add(d_del, "dired-flag-file-deletion", 0);
funmap_add(d_gotofile, "dired-goto-file", 1);
funmap_add(d_forwline, "dired-next-line", 0);
funmap_add(d_otherwindow, "dired-other-window", 0);
funmap_add(d_backline, "dired-previous-line", 0);
funmap_add(d_refreshbuffer, "dired-revert", 0);
funmap_add(d_backpage, "dired-scroll-down", 0);
funmap_add(d_forwpage, "dired-scroll-up", 0);
funmap_add(d_shell_command, "dired-shell-command", 1);
funmap_add(d_undel, "dired-unmark", 0);
funmap_add(d_undelbak, "dired-unmark-backward", 0);
funmap_add(d_killbuffer_cmd, "quit-window", 0);
funmap_add(d_updirectory, "dired-up-directory", 0);
maps_add((KEYMAP *)&diredmap, "dired");
dobindkey(fundamental_map, "dired", "^Xd");
}
int
dired(int f, int n)
{
char dname[NFILEN], *bufp, *slash;
struct buffer *bp;
if (curbp->b_fname[0] != '\0') {
(void)strlcpy(dname, curbp->b_fname, sizeof(dname));
if ((slash = strrchr(dname, '/')) != NULL) {
*(slash + 1) = '\0';
}
} else {
if (getcwd(dname, sizeof(dname)) == NULL)
dname[0] = '\0';
}
if ((bufp = eread("Dired (directory): ", dname, NFILEN,
EFDEF | EFNEW | EFCR)) == NULL)
return (ABORT);
if (bufp[0] == '\0')
return (FALSE);
if ((bp = dired_(bufp)) == NULL)
return (FALSE);
curbp = bp;
return (showbuffer(bp, curwp, WFFULL | WFMODE));
}
int
d_otherwindow(int f, int n)
{
char dname[NFILEN], *bufp, *slash;
struct buffer *bp;
struct mgwin *wp;
if (curbp->b_fname[0] != '\0') {
(void)strlcpy(dname, curbp->b_fname, sizeof(dname));
if ((slash = strrchr(dname, '/')) != NULL) {
*(slash + 1) = '\0';
}
} else {
if (getcwd(dname, sizeof(dname)) == NULL)
dname[0] = '\0';
}
if ((bufp = eread("Dired other window: ", dname, NFILEN,
EFDEF | EFNEW | EFCR)) == NULL)
return (ABORT);
else if (bufp[0] == '\0')
return (FALSE);
if ((bp = dired_(bufp)) == NULL)
return (FALSE);
if ((wp = popbuf(bp, WNONE)) == NULL)
return (FALSE);
curbp = bp;
curwp = wp;
return (TRUE);
}
int
d_del(int f, int n)
{
if (n < 0)
return (FALSE);
while (n--) {
if (d_warpdot(curwp->w_dotp, &curwp->w_doto) == TRUE) {
lputc(curwp->w_dotp, 0, DDELCHAR);
curbp->b_flag |= BFDIREDDEL;
}
if (lforw(curwp->w_dotp) != curbp->b_headp) {
curwp->w_dotp = lforw(curwp->w_dotp);
curwp->w_dotline++;
}
}
curwp->w_rflag |= WFEDIT | WFMOVE;
return (d_warpdot(curwp->w_dotp, &curwp->w_doto));
}
int
d_undel(int f, int n)
{
if (n < 0)
return (d_undelbak(f, -n));
while (n--) {
if (llength(curwp->w_dotp) > 0)
lputc(curwp->w_dotp, 0, ' ');
if (lforw(curwp->w_dotp) != curbp->b_headp) {
curwp->w_dotp = lforw(curwp->w_dotp);
curwp->w_dotline++;
}
}
curwp->w_rflag |= WFEDIT | WFMOVE;
return (d_warpdot(curwp->w_dotp, &curwp->w_doto));
}
int
d_undelbak(int f, int n)
{
if (n < 0)
return (d_undel(f, -n));
while (n--) {
if (lback(curwp->w_dotp) != curbp->b_headp) {
curwp->w_dotp = lback(curwp->w_dotp);
curwp->w_dotline--;
}
if (llength(curwp->w_dotp) > 0)
lputc(curwp->w_dotp, 0, ' ');
}
curwp->w_rflag |= WFEDIT | WFMOVE;
return (d_warpdot(curwp->w_dotp, &curwp->w_doto));
}
int
d_findfile(int f, int n)
{
struct buffer *bp;
int s;
char fname[NFILEN];
if ((s = d_makename(curwp->w_dotp, fname, sizeof(fname))) == ABORT)
return (FALSE);
if (s == TRUE)
bp = dired_(fname);
else
bp = findbuffer(fname);
if (bp == NULL)
return (FALSE);
curbp = bp;
if (showbuffer(bp, curwp, WFFULL) != TRUE)
return (FALSE);
if (bp->b_fname[0] != 0)
return (TRUE);
return (readin(fname));
}
int
d_updirectory(int f, int n)
{
struct buffer *bp;
int ret;
char fname[NFILEN];
ret = snprintf(fname, sizeof(fname), "%s..", curbp->b_fname);
if (ret < 0 || (size_t)ret >= sizeof(fname))
return (ABORT);
bp = dired_(fname);
if (bp == NULL)
return (FALSE);
curbp = bp;
if (showbuffer(bp, curwp, WFFULL) != TRUE)
return (FALSE);
if (bp->b_fname[0] != 0)
return (TRUE);
return (readin(fname));
}
int
d_ffotherwindow(int f, int n)
{
char fname[NFILEN];
int s;
struct buffer *bp;
struct mgwin *wp;
if ((s = d_makename(curwp->w_dotp, fname, sizeof(fname))) == ABORT)
return (FALSE);
if ((bp = (s ? dired_(fname) : findbuffer(fname))) == NULL)
return (FALSE);
if ((wp = popbuf(bp, WNONE)) == NULL)
return (FALSE);
curbp = bp;
curwp = wp;
if (bp->b_fname[0] != 0)
return (TRUE);
return (readin(fname));
}
int
d_expunge(int f, int n)
{
struct line *lp, *nlp;
char fname[NFILEN], sname[NFILEN];
int tmp;
tmp = curwp->w_dotline;
curwp->w_dotline = 0;
for (lp = bfirstlp(curbp); lp != curbp->b_headp; lp = nlp) {
curwp->w_dotline++;
nlp = lforw(lp);
if (llength(lp) && lgetc(lp, 0) == 'D') {
switch (d_makename(lp, fname, sizeof(fname))) {
case ABORT:
dobeep();
ewprintf("Bad line in dired buffer");
curwp->w_dotline = tmp;
return (FALSE);
case FALSE:
if (unlink(fname) == -1) {
(void)xbasename(sname, fname, NFILEN);
dobeep();
ewprintf("Could not delete '%s'", sname);
curwp->w_dotline = tmp;
return (FALSE);
}
break;
case TRUE:
if (rmdir(fname) == -1) {
(void)xbasename(sname, fname, NFILEN);
dobeep();
ewprintf("Could not delete directory "
"'%s'", sname);
curwp->w_dotline = tmp;
return (FALSE);
}
break;
}
lfree(lp);
curwp->w_bufp->b_lines--;
if (tmp > curwp->w_dotline)
tmp--;
curwp->w_rflag |= WFFULL;
}
}
curwp->w_dotline = tmp;
d_warpdot(curwp->w_dotp, &curwp->w_doto);
curbp->b_flag &= ~BFDIREDDEL;
return (TRUE);
}
int
d_copy(int f, int n)
{
struct stat statbuf;
char frname[NFILEN], toname[NFILEN], sname[NFILEN];
char *topath, *bufp;
int ret;
size_t off;
struct buffer *bp;
if (d_makename(curwp->w_dotp, frname, sizeof(frname)) != FALSE) {
dobeep();
ewprintf("Not a file");
return (FALSE);
}
off = strlcpy(toname, curbp->b_fname, sizeof(toname));
if (off >= sizeof(toname) - 1) {
dobeep();
ewprintf("Directory name too long");
return (FALSE);
}
(void)xbasename(sname, frname, NFILEN);
bufp = eread("Copy %s to: ", toname, sizeof(toname),
EFDEF | EFNEW | EFCR, sname);
if (bufp == NULL)
return (ABORT);
else if (bufp[0] == '\0')
return (FALSE);
topath = adjustname(toname, TRUE);
if (stat(topath, &statbuf) == 0) {
if (S_ISDIR(statbuf.st_mode)) {
ret = snprintf(toname, sizeof(toname), "%s/%s",
topath, sname);
if (ret < 0 || ret >= sizeof(toname) - 1) {
dobeep();
ewprintf("Directory name too long");
return (FALSE);
}
topath = adjustname(toname, TRUE);
}
}
if (topath == NULL)
return (FALSE);
if (strcmp(frname, topath) == 0) {
ewprintf("Cannot copy to same file: %s", frname);
return (TRUE);
}
ret = (copy(frname, topath) >= 0) ? TRUE : FALSE;
if (ret != TRUE)
return (ret);
if ((bp = refreshbuffer(curbp)) == NULL)
return (FALSE);
ewprintf("Copy: 1 file");
return (showbuffer(bp, curwp, WFFULL | WFMODE));
}
int
d_rename(int f, int n)
{
struct stat statbuf;
char frname[NFILEN], toname[NFILEN];
char *topath, *bufp;
int ret;
size_t off;
struct buffer *bp;
char sname[NFILEN];
if (d_makename(curwp->w_dotp, frname, sizeof(frname)) != FALSE) {
dobeep();
ewprintf("Not a file");
return (FALSE);
}
off = strlcpy(toname, curbp->b_fname, sizeof(toname));
if (off >= sizeof(toname) - 1) {
dobeep();
ewprintf("Name too long");
return (FALSE);
}
(void)xbasename(sname, frname, NFILEN);
bufp = eread("Rename %s to: ", toname,
sizeof(toname), EFDEF | EFNEW | EFCR, sname);
if (bufp == NULL)
return (ABORT);
else if (bufp[0] == '\0')
return (FALSE);
topath = adjustname(toname, TRUE);
if (stat(topath, &statbuf) == 0) {
if (S_ISDIR(statbuf.st_mode)) {
ret = snprintf(toname, sizeof(toname), "%s/%s",
topath, sname);
if (ret < 0 || ret >= sizeof(toname) - 1) {
dobeep();
ewprintf("Directory name too long");
return (FALSE);
}
topath = adjustname(toname, TRUE);
}
}
if (topath == NULL)
return (FALSE);
if (strcmp(frname, topath) == 0) {
ewprintf("Cannot move to same file: %s", frname);
return (TRUE);
}
ret = (rename(frname, topath) >= 0) ? TRUE : FALSE;
if (ret != TRUE)
return (ret);
if ((bp = refreshbuffer(curbp)) == NULL)
return (FALSE);
ewprintf("Move: 1 file");
return (showbuffer(bp, curwp, WFFULL | WFMODE));
}
void
reaper(int signo __attribute__((unused)))
{
int save_errno = errno, status;
while (waitpid(-1, &status, WNOHANG) >= 0)
;
errno = save_errno;
}
int
d_shell_command(int f, int n)
{
char command[512], fname[PATH_MAX], *bufp;
struct buffer *bp;
struct mgwin *wp;
char sname[NFILEN];
bp = bfind("*Shell Command Output*", TRUE);
if (bclear(bp) != TRUE)
return (ABORT);
if (d_makename(curwp->w_dotp, fname, sizeof(fname)) != FALSE) {
dobeep();
ewprintf("bad line");
return (ABORT);
}
command[0] = '\0';
(void)xbasename(sname, fname, NFILEN);
bufp = eread("! on %s: ", command, sizeof(command), EFNEW, sname);
if (bufp == NULL)
return (ABORT);
if (d_exec(0, bp, fname, "sh", "-c", command, NULL) != TRUE)
return (ABORT);
if ((wp = popbuf(bp, WNONE)) == NULL)
return (ABORT);
curwp = wp;
curbp = wp->w_bufp;
return (TRUE);
}
static int
d_exec(int space, struct buffer *bp, const char *input, const char *cmd, ...)
{
char buf[BUFSIZ];
va_list ap;
struct sigaction olda, newa;
char **argv = NULL, *cp;
FILE *fin;
int fds[2] = { -1, -1 };
int infd = -1;
int ret = (ABORT), n;
pid_t pid;
if (sigaction(SIGCHLD, NULL, &olda) == -1)
return (ABORT);
va_start(ap, cmd);
for (n = 2; va_arg(ap, char *) != NULL; n++)
;
va_end(ap);
if ((argv = calloc(n, sizeof(*argv))) == NULL) {
dobeep();
ewprintf("Can't allocate argv : %s", strerror(errno));
goto out;
}
n = 1;
argv[0] = (char *)cmd;
va_start(ap, cmd);
while ((argv[n] = va_arg(ap, char *)) != NULL)
n++;
va_end(ap);
if (input == NULL)
input = "/dev/null";
if ((infd = open(input, O_RDONLY)) == -1) {
dobeep();
ewprintf("Can't open input file : %s", strerror(errno));
goto out;
}
if (pipe(fds) == -1) {
dobeep();
ewprintf("Can't create pipe : %s", strerror(errno));
goto out;
}
newa.sa_handler = reaper;
newa.sa_flags = 0;
if (sigaction(SIGCHLD, &newa, NULL) == -1)
goto out;
if ((pid = fork()) == -1) {
dobeep();
ewprintf("Can't fork");
goto out;
}
switch (pid) {
case 0:
close(fds[0]);
dup2(infd, STDIN_FILENO);
dup2(fds[1], STDOUT_FILENO);
dup2(fds[1], STDERR_FILENO);
if (execvp(argv[0], argv) == -1)
ewprintf("Can't exec %s: %s", argv[0], strerror(errno));
exit(1);
break;
default:
close(infd);
close(fds[1]);
infd = fds[1] = -1;
if ((fin = fdopen(fds[0], "r")) == NULL)
goto out;
while (fgets(buf, sizeof(buf), fin) != NULL) {
cp = strrchr(buf, *bp->b_nlchr);
if (cp == NULL && !feof(fin)) {
int c;
addlinef(bp, "%*s%s...", space, "", buf);
while ((c = getc(fin)) != EOF &&
c != *bp->b_nlchr)
;
continue;
} else if (cp)
*cp = '\0';
addlinef(bp, "%*s%s", space, "", buf);
}
fclose(fin);
break;
}
ret = (TRUE);
out:
if (sigaction(SIGCHLD, &olda, NULL) == -1)
ewprintf("Warning, couldn't reset previous signal handler");
if (fds[0] != -1)
close(fds[0]);
if (fds[1] != -1)
close(fds[1]);
if (infd != -1)
close(infd);
free(argv);
return ret;
}
int
d_create_directory(int f, int n)
{
int ret;
struct buffer *bp;
ret = ask_makedir();
if (ret != TRUE)
return(ret);
if ((bp = refreshbuffer(curbp)) == NULL)
return (FALSE);
return (showbuffer(bp, curwp, WFFULL | WFMODE));
}
int
d_killbuffer_cmd(int f, int n)
{
return(killbuffer_cmd(FFRAND, 0));
}
int
d_refreshbuffer(int f, int n)
{
struct buffer *bp;
if ((bp = refreshbuffer(curbp)) == NULL)
return (FALSE);
return (showbuffer(bp, curwp, WFFULL | WFMODE));
}
struct buffer *
refreshbuffer(struct buffer *bp)
{
char *tmp_b_fname;
int i, tmp_w_dotline, ddel = 0;
tmp_b_fname = strdup(bp->b_fname);
if (tmp_b_fname == NULL) {
dobeep();
ewprintf("Out of memory");
return (NULL);
}
tmp_w_dotline = curwp->w_dotline;
if (bp->b_flag & BFDIREDDEL)
ddel = createlist(bp);
killbuffer(bp);
if ((bp = dired_(tmp_b_fname)) == NULL) {
free(tmp_b_fname);
return (NULL);
}
free(tmp_b_fname);
if (ddel)
redelete(bp);
bp->b_dotp = bfirstlp(bp);
if (tmp_w_dotline > bp->b_lines)
tmp_w_dotline = bp->b_lines - 1;
for (i = 1; i < tmp_w_dotline; i++)
bp->b_dotp = lforw(bp->b_dotp);
bp->b_dotline = i;
bp->b_doto = 0;
d_warpdot(bp->b_dotp, &bp->b_doto);
curbp = bp;
return (bp);
}
static int
d_makename(struct line *lp, char *fn, size_t len)
{
int start, nlen, ret;
char *namep;
if (d_warpdot(lp, &start) == FALSE)
return (ABORT);
namep = &lp->l_text[start];
nlen = llength(lp) - start;
ret = snprintf(fn, len, "%s%.*s", curbp->b_fname, nlen, namep);
if (ret < 0 || ret >= (int)len)
return (ABORT);
return ((lgetc(lp, 2) == 'd') ? TRUE : FALSE);
}
#define NAME_FIELD 9
static int
d_warpdot(struct line *dotp, int *doto)
{
char *tp = dotp->l_text;
int off = 0, field = 0, len;
len = llength(dotp);
while (off < len) {
if (tp[off++] == ' ') {
if (++field == NAME_FIELD) {
*doto = off;
return (TRUE);
}
while (off < len && tp[off] == ' ')
off++;
}
}
*doto = 0;
return (FALSE);
}
static int
d_forwpage(int f, int n)
{
forwpage(f | FFRAND, n);
return (d_warpdot(curwp->w_dotp, &curwp->w_doto));
}
static int
d_backpage (int f, int n)
{
backpage(f | FFRAND, n);
return (d_warpdot(curwp->w_dotp, &curwp->w_doto));
}
static int
d_forwline (int f, int n)
{
forwline(f | FFRAND, n);
return (d_warpdot(curwp->w_dotp, &curwp->w_doto));
}
static int
d_backline (int f, int n)
{
backline(f | FFRAND, n);
return (d_warpdot(curwp->w_dotp, &curwp->w_doto));
}
int
d_filevisitalt (int f, int n)
{
char fname[NFILEN];
if (d_makename(curwp->w_dotp, fname, sizeof(fname)) == ABORT)
return (FALSE);
return(do_filevisitalt(fname));
}
struct buffer *
dired_(char *dname)
{
struct buffer *bp;
int i;
size_t len;
if ((dname = adjustname(dname, TRUE)) == NULL) {
dobeep();
ewprintf("Bad directory name");
return (NULL);
}
len = strlen(dname);
if (dname[len - 1] != '/') {
dname[len++] = '/';
dname[len] = '\0';
}
if ((access(dname, R_OK | X_OK)) == -1) {
if (errno == EACCES) {
dobeep();
ewprintf("Permission denied: %s", dname);
} else {
dobeep();
ewprintf("Error opening: %s", dname);
}
return (NULL);
}
for (bp = bheadp; bp != NULL; bp = bp->b_bufp) {
if (strcmp(bp->b_fname, dname) == 0) {
if (fchecktime(bp) != TRUE)
ewprintf("Directory has changed on disk;"
" type g to update Dired");
return (bp);
}
}
bp = bfind(dname, TRUE);
bp->b_flag |= BFREADONLY | BFIGNDIRTY;
if ((d_exec(2, bp, NULL, "ls", "-al", dname, NULL)) != TRUE)
return (NULL);
bp->b_dotp = bfirstlp(bp);
bp->b_dotline = 1;
for (i = 0; i < bp->b_lines; i++) {
bp->b_dotp = lforw(bp->b_dotp);
bp->b_dotline++;
if (d_warpdot(bp->b_dotp, &bp->b_doto) == FALSE)
continue;
if (strcmp(ltext(bp->b_dotp) + bp->b_doto, "..") == 0)
break;
}
if (++i < bp->b_lines - 2) {
bp->b_dotp = lforw(bp->b_dotp);
bp->b_dotline++;
}
d_warpdot(bp->b_dotp, &bp->b_doto);
(void)strlcpy(bp->b_fname, dname, sizeof(bp->b_fname));
(void)strlcpy(bp->b_cwd, dname, sizeof(bp->b_cwd));
if ((bp->b_modes[1] = name_mode("dired")) == NULL) {
bp->b_modes[0] = name_mode("fundamental");
dobeep();
ewprintf("Could not find mode dired");
return (NULL);
}
(void)fupdstat(bp);
bp->b_nmodes = 1;
return (bp);
}
void
redelete(struct buffer *bp)
{
struct delentry *dt, *d1 = NULL;
struct line *lp, *nlp;
char fname[NFILEN];
char *p = fname;
size_t plen, fnlen;
int finished = 0;
bp->b_flag &= ~BFDIREDDEL;
for (lp = bfirstlp(bp); lp != bp->b_headp; lp = nlp) {
bp->b_dotp = lp;
if ((p = findfname(lp, p)) == NULL) {
nlp = lforw(lp);
continue;
}
plen = strlen(p);
SLIST_FOREACH_SAFE(d1, &delhead, entry, dt) {
fnlen = strlen(d1->fn);
if ((plen == fnlen) &&
(strncmp(p, d1->fn, plen) == 0)) {
lputc(bp->b_dotp, 0, DDELCHAR);
bp->b_flag |= BFDIREDDEL;
SLIST_REMOVE(&delhead, d1, delentry, entry);
if (SLIST_EMPTY(&delhead)) {
finished = 1;
break;
}
}
}
if (finished)
break;
nlp = lforw(lp);
}
while (!SLIST_EMPTY(&delhead)) {
d1 = SLIST_FIRST(&delhead);
SLIST_REMOVE_HEAD(&delhead, entry);
free(d1->fn);
free(d1);
}
return;
}
int
createlist(struct buffer *bp)
{
struct delentry *d1 = NULL, *d2;
struct line *lp, *nlp;
char fname[NFILEN];
char *p = fname;
int ret = FALSE;
for (lp = bfirstlp(bp); lp != bp->b_headp; lp = nlp) {
if (((lp->l_text[0] != DDELCHAR)) ||
((p = findfname(lp, p)) == NULL)) {
nlp = lforw(lp);
continue;
}
if (SLIST_EMPTY(&delhead)) {
if ((d1 = malloc(sizeof(struct delentry)))
== NULL)
return (ABORT);
if ((d1->fn = strdup(p)) == NULL) {
free(d1);
return (ABORT);
}
SLIST_INSERT_HEAD(&delhead, d1, entry);
} else {
if ((d2 = malloc(sizeof(struct delentry)))
== NULL) {
free(d1->fn);
free(d1);
return (ABORT);
}
if ((d2->fn = strdup(p)) == NULL) {
free(d1->fn);
free(d1);
free(d2);
return (ABORT);
}
if (!d1)
SLIST_INSERT_HEAD(&delhead, d2, entry);
else
SLIST_INSERT_AFTER(d1, d2, entry);
d1 = d2;
}
ret = TRUE;
nlp = lforw(lp);
}
return (ret);
}
int
dired_jump(int f, int n)
{
struct buffer *bp;
const char *modename;
char dname[NFILEN], *fname;
int ret, i;
for (i = 0; i <= curbp->b_nmodes; i++) {
modename = curbp->b_modes[i]->p_name;
if (strncmp(modename, "dired", 5) == 0)
return (d_updirectory(f, n));
}
if (getbufcwd(dname, sizeof(dname)) != TRUE)
return (FALSE);
fname = curbp->b_fname;
if ((bp = dired_(dname)) == NULL)
return (FALSE);
curbp = bp;
ret = showbuffer(bp, curwp, WFFULL | WFMODE);
if (ret != TRUE)
return ret;
fname = adjustname(fname, TRUE);
if (fname != NULL)
gotofile(fname);
return (TRUE);
}
int
d_gotofile(int f, int n)
{
size_t lenfpath;
char fpath[NFILEN];
char *fpth, *fnp = NULL;
if (getbufcwd(fpath, sizeof(fpath)) != TRUE)
fpath[0] = '\0';
lenfpath = strlen(fpath);
fnp = eread("Goto file: ", fpath, NFILEN,
EFNEW | EFCR | EFFILE | EFDEF);
if (fnp == NULL)
return (ABORT);
else if (fnp[0] == '\0')
return (FALSE);
fpth = adjustname(fpath, TRUE);
if (fpth == NULL || strlen(fpth) == lenfpath - 1) {
ewprintf("No file to find");
return (TRUE);
}
return gotofile(fpth);
}
int
gotofile(char *fpth)
{
struct line *lp, *nlp;
char fname[NFILEN];
char *p;
int tmp;
(void)xbasename(fname, fpth, NFILEN);
tmp = 0;
for (lp = bfirstlp(curbp); lp != curbp->b_headp; lp = nlp) {
tmp++;
if ((p = findfname(lp, p)) == NULL) {
nlp = lforw(lp);
continue;
}
if (strcmp(fname, p) == 0) {
curwp->w_dotp = lp;
curwp->w_dotline = tmp;
(void)d_warpdot(curwp->w_dotp, &curwp->w_doto);
tmp--;
break;
}
nlp = lforw(lp);
}
if (tmp == curbp->b_lines - 1) {
ewprintf("File not found %s", fname);
return (FALSE);
} else {
eerase();
return (TRUE);
}
}
char *
findfname(struct line *lp, char *fn)
{
int start;
(void)d_warpdot(lp, &start);
if (start < 1)
return NULL;
fn = &lp->l_text[start];
return fn;
}