#define SYM_ORPHAN 0x04
#define FILE_MISSING 0x08
#define FILE_SELECTED 0x10
+#define FILE_SCANNED 0x20
/* Macros to define process spawn behaviour as flags */
#define F_NONE 0x00 /* no flag set */
static int spawn(char *file, char *arg1, char *arg2, char *arg3, ushort_t flag);
static void move_cursor(int target, int ignore_scrolloff);
static char *load_input(int fd, const char *path);
-static int editselection(void);
static int set_sort_flags(int r);
#ifndef NOFIFO
static void notify_fifo(bool force);
printwarn(NULL);
}
-static void appendfpath(const char *path, const size_t len)
+static bool appendfpath(const char *path, const size_t len)
{
+ bool ret = FALSE;
+
if ((selbufpos >= selbuflen) || ((len + 3) > (selbuflen - selbufpos))) {
selbuflen += PATH_MAX;
pselbuf = xrealloc(pselbuf, selbuflen);
+ ret = TRUE;
if (!pselbuf)
errexit();
}
selbufpos += xstrsncpy(pselbuf + selbufpos, path, len);
+ return ret;
}
/* Write selected file paths to fd, linefeed separated */
found = memmem(found, buflen - (found - startpos), g_buf, len);
if (!found)
return NULL;
-
if (found == startpos || *(found - 1) == '\0')
return found;
-
/* We found g_buf as a substring of a path, move forward */
found += len;
if (found >= startpos + buflen)
return ma->startpos - mb->startpos;
}
+static void findmarkentry(char *path, struct entry *dentp)
+{
+ if (!(dentp->flags & FILE_SCANNED)) {
+ if (findinsel(findselpos, mkpath(path, dentp->name, g_buf)))
+ dentp->flags |= FILE_SELECTED;
+ dentp->flags |= FILE_SCANNED;
+ }
+}
+
static void invertselbuf(char *path)
{
size_t len, endpos, offset = 0;
char *found;
int nmarked = 0, prev = 0;
+ struct entry *dentp;
selmark *marked = malloc(nselected * sizeof(selmark));
if (nselected > LARGESEL) {
/* First pass: inversion */
for (int i = 0; i < ndents; ++i) {
- /* Toggle selection status */
- pdents[i].flags ^= FILE_SELECTED;
+ dentp = &pdents[i];
+ findmarkentry(path, dentp);
+
+ /* Toggle selection status */
+ dentp->flags ^= FILE_SELECTED;
/* Find where the files marked for deselection are in selection buffer */
- if (!(pdents[i].flags & FILE_SELECTED)) {
- len = mkpath(path, pdents[i].name, g_buf);
+ if (!(dentp->flags & FILE_SELECTED)) {
+ len = mkpath(path, dentp->name, g_buf);
found = findinsel(findselpos, len);
marked[nmarked].startpos = found;
nselected ? writesel(pselbuf, selbufpos - 1) : clearselection();
}
-/* removes g_buf from selbuf */
+/* Removes g_buf from selbuf */
static void rmfromselbuf(size_t len)
{
char *found = findinsel(findselpos, len);
nselected ? writesel(pselbuf, selbufpos - 1) : clearselection();
}
+static bool scanselforpath(const char *path)
+{
+ if (!path[1]) { /* path should always be at least two bytes (including NULL) */
+ findselpos = pselbuf;
+ return TRUE;
+ }
+
+ size_t off = xstrsncpy(g_buf, path, PATH_MAX);
+
+ g_buf[off - 1] = '/';
+ /*
+ * We set findselpos only here. Directories can be listed in arbitrary order.
+ * This is the best best we can do for remembering position.
+ */
+ findselpos = findinsel(NULL, off);
+ return (findselpos != NULL);
+}
+
static void addtoselbuf(char *path, int startid, int endid)
{
size_t len = appendslash(path);
+ struct entry *dentp;
/* Remember current selection buffer position */
for (int i = startid; i <= endid; ++i) {
- if (!(pdents[i].flags & FILE_SELECTED)) {
- /* Write the path to selection file to avoid flush */
- appendfpath(path, len + xstrsncpy(path + len, pdents[i].name, PATH_MAX - len));
+ dentp = &pdents[i];
+ if (findselpos)
+ findmarkentry(path, dentp);
+ else
+ dentp->flags |= FILE_SCANNED;
- pdents[i].flags |= FILE_SELECTED;
+ if (!(dentp->flags & FILE_SELECTED)) {
+ /* Write the path to selection file to avoid flush */
+ if (appendfpath(path, len + xstrsncpy(path + len, dentp->name, PATH_MAX - len)))
+ scanselforpath(path);
+ dentp->flags |= FILE_SELECTED;
++nselected;
}
}
uchar_t entflags = 0;
int flags = 0;
struct dirent *dp;
- bool found;
- char *namep, *pnb, *buf = g_buf;
+ char *namep, *pnb, *buf;
struct entry *dentp;
- size_t off, namebuflen = NAMEBUF_INCR;
+ size_t off = 0, namebuflen = NAMEBUF_INCR;
struct stat sb_path, sb;
DIR *dirp = opendir(path);
if (cfg.blkorder) {
num_files = 0;
dir_blocks = 0;
+ buf = g_buf;
if (fstatat(fd, path, &sb_path, 0) == -1)
goto exit;
}
#endif
- if (path[1]) { /* path should always be at least two bytes (including NULL) */
- off = xstrsncpy(buf, path, PATH_MAX);
- buf[off - 1] = '/';
- /*
- * We set findselpos only here. Directories can be listed in arbitrary order.
- * This is the best best we can do for remembering position.
- */
- found = (findselpos = findinsel(NULL, off)) != NULL;
- } else {
- findselpos = NULL;
- found = TRUE;
- }
-
- off = 0;
-
do {
namep = dp->d_name;
if (S_ISDIR(sb.st_mode)) {
if (sb_path.st_dev == sb.st_dev) { // NOLINT
- mkpath(path, namep, buf);
+ mkpath(path, namep, buf); // NOLINT
dirwalk(path, buf, -1, FALSE);
if (g_state.interrupt)
entflags = 0;
}
- if (found && findinsel(findselpos, mkpath(path, dentp->name, buf)) != NULL)
- dentp->flags |= FILE_SELECTED;
-
if (cfg.blkorder) {
if (S_ISDIR(sb.st_mode)) {
- mkpath(path, namep, buf);
+ mkpath(path, namep, buf); // NOLINT
/* Need to show the disk usage of this dir */
dirwalk(path, buf, ndents, (sb_path.st_dev != sb.st_dev)); // NOLINT
ncols = adjust_cols(ncols);
+ bool found = scanselforpath(path);
+
/* Print listing */
for (i = curscroll; i < onscreen; ++i) {
move(++j, 0);
+
+ if (found)
+ findmarkentry(path, &pdents[i]);
+
printent(&pdents[i], ncols, i == cur);
}
selstartid = 0;
selendid = ndents - 1;
+
+ scanselforpath(path);
}
- (sel == SEL_SELINV)
+ ((sel == SEL_SELINV) && findselpos)
? invertselbuf(path) : addtoselbuf(path, selstartid, selendid);
#ifndef NOX11