qemacs-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemacs-commit] qemacs dired.c


From: Charlie Gordon
Subject: [Qemacs-commit] qemacs dired.c
Date: Sun, 30 Aug 2015 15:30:59 +0000

CVSROOT:        /sources/qemacs
Module name:    qemacs
Changes by:     Charlie Gordon <chqrlie>        15/08/30 15:30:59

Modified files:
        .              : dired.c 

Log message:
        dired: code cleanup, better layout control
        - refactored dired_sort_list() as dired_update_buffer():
          better detection of formating changes and less useless sorting
        - make sort-mode, hflag, nflag... remanent and global for all dired 
buffers
        - fix and simplify handling of current entry in dired popleft window.
        - compute and display numbers of hidden files and directories
        - total byte count only accounts for visible entries
        - control dired-hflag with 'H': human readable sizes
        - control dired-nflag with 'N': alpha/numeric/hidden uid/gid columns
        - use variable setter function for dired-sort-mode and dired-time-format

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/qemacs/dired.c?cvsroot=qemacs&r1=1.60&r2=1.61

Patches:
Index: dired.c
===================================================================
RCS file: /sources/qemacs/qemacs/dired.c,v
retrieving revision 1.60
retrieving revision 1.61
diff -u -b -r1.60 -r1.61
--- dired.c     27 Aug 2015 23:03:39 -0000      1.60
+++ dired.c     30 Aug 2015 15:30:58 -0000      1.61
@@ -2,7 +2,7 @@
  * Directory editor mode for QEmacs.
  *
  * Copyright (c) 2001-2002 Fabrice Bellard.
- * Copyright (c) 2002-2014 Charlie Gordon.
+ * Copyright (c) 2002-2015 Charlie Gordon.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -44,6 +44,14 @@
     DIRED_SORT_DESCENDING = 32,
 };
 
+enum {
+    DIRED_UPDATE_SORT = 1,
+    DIRED_UPDATE_FILTER = 2,
+    DIRED_UPDATE_COLUMNS = 4,
+    DIRED_UPDATE_REBUILD = 8,
+    DIRED_UPDATE_ALL = 15,
+};
+
 enum time_format {
     TF_COMPACT,
     TF_DOS,
@@ -55,34 +63,30 @@
     TF_MAX = TF_SECONDS,
 };
 
-static ModeDef dired_mode;
+typedef struct DiredState DiredState;
+typedef struct DiredItem DiredItem;
 
-static time_t curtime;
-
-/* XXX: need a function to set these variables and trigger refresh */
-static enum time_format dired_time_format;
-static int dired_show_dot_files = 1;
-#ifdef CONFIG_DARWIN
-static int dired_show_ds_store = 0;
-#endif
-
-typedef struct DiredState {
+struct DiredState {
     QEModeData base;    /* derived from QEModeData */
-    StringArray items;
-    int sort_mode; /* DIRED_SORT_GROUP | DIRED_SORT_NAME */
-    int last_index;
+    StringArray items;  /* XXX: should just use a generic array */
+    enum time_format time_format;
+    int show_dot_files;
+    int show_ds_store;
+    int hflag, nflag;
+    int sort_mode;
+    DiredItem *last_cur;
     long long total_bytes;
-    int ndirs, nfiles;
+    int ndirs, nfiles, ndirs_hidden, nfiles_hidden;
     int blocksize;
-    int hflag, nflag, last_width;
+    int last_width;
     int no_blocks, no_mode, no_link, no_uid, no_gid, no_size, no_date;
     int blockslen, modelen, linklen, uidlen, gidlen, sizelen, datelen, namelen;
     int fnamecol;
     char path[MAX_FILENAME_SIZE]; /* current path */
-} DiredState;
+};
 
 /* opaque structure for sorting DiredState.items StringArray */
-typedef struct DiredItem {
+struct DiredItem {
     DiredState *state;
     mode_t  mode;   /* inode protection mode */
     nlink_t nlink;  /* number of hard links to the file */
@@ -92,17 +96,38 @@
     time_t  mtime;
     off_t   size;
     int     offset;
+    char    hidden;
     char    mark;
     char    name[1];
-} DiredItem;
+};
+
+static ModeDef dired_mode;
+
+static time_t dired_curtime;
+
+static enum time_format dired_time_format;
+static int dired_show_dot_files = 1;
+static int dired_show_ds_store = 0;
+static int dired_nflag = 0; /* 0=name, 1=numeric, 2=hidden */
+static int dired_hflag = 0; /* 0=exact, 1=human-decimal, 2=human-binary */
+static int dired_sort_mode = DIRED_SORT_GROUP | DIRED_SORT_NAME;
 
 static inline DiredState *dired_get_state(EditState *e, int status)
 {
     return qe_get_buffer_mode_data(e->b, &dired_mode, status ? e : NULL);
 }
 
-static inline int dired_get_index(EditState *s) {
-    return list_get_pos(s) - DIRED_HEADER;
+static DiredItem *dired_get_cur_item(DiredState *ds, EditState *s) {
+    int i, index = list_get_pos(s) - DIRED_HEADER;
+
+    if (index >= 0) {
+        for (i = 0; i < ds->items.nb_items; i++) {
+            DiredItem *dip = ds->items.items[i]->opaque;
+            if (!dip->hidden && index-- == 0)
+                return dip;
+        }
+    }
+    return NULL;
 }
 
 static void dired_free(DiredState *ds)
@@ -116,25 +141,19 @@
 
         free_strings(&ds->items);
 
-        ds->last_index = -1;
+        ds->last_cur = NULL;
     }
 }
 
-static char *dired_get_filename(DiredState *ds, int index,
+static char *dired_get_filename(DiredState *ds, const DiredItem *dip,
                                 char *buf, int buf_size)
 {
-    const StringItem *item;
-    const DiredItem *dip;
-
     if (buf_size > 0)
         buf[0] = '\0';
 
-    if (index < 0 || index >= ds->items.nb_items)
+    if (!dip)
         return NULL;
 
-    item = ds->items.items[index];
-    dip = item->opaque;
-
     /* build filename */
     /* CG: Should canonicalize path */
     return makepath(buf, buf_size, ds->path, dip->name);
@@ -143,17 +162,22 @@
 static int dired_find_target(DiredState *ds, const char *target)
 {
     char filename[MAX_FILENAME_SIZE];
-    int i;
+    int i, row = 0;
 
     if (target) {
+        row = DIRED_HEADER;
         for (i = 0; i < ds->items.nb_items; i++) {
-            if (dired_get_filename(ds, i, filename, sizeof(filename))
+            DiredItem *dip = ds->items.items[i]->opaque;
+    
+            if (dired_get_filename(ds, dip, filename, sizeof(filename))
             &&  strequal(filename, target)) {
-                return i;
+                return row;
             }
+            if (!dip->hidden)
+                row++;
         }
     }
-    return -1;
+    return row;
 }
 
 /* sort alphabetically with directories first */
@@ -334,8 +358,8 @@
         break;
     default:
     case TF_COMPACT:
-        if (systime > curtime - 182 * 86400
-        &&  systime < curtime + 182 * 86400) {
+        if (systime > dired_curtime - 182 * 86400
+        &&  systime < dired_curtime + 182 * 86400) {
             buf_printf(out,     "%s %2d %02d:%02d",
                        month[fmonth],        /* month */
                        systm.tm_mday,        /* day */
@@ -466,74 +490,226 @@
     return atts;
 }
 
-/* `ds` and `b` are valid, `s` may be NULL */
-static void dired_sort_list(DiredState *ds, EditBuffer *b, EditState *s)
+static void dired_filter_files(DiredState *ds)
+{
+    int i;
+
+    ds->show_dot_files = dired_show_dot_files;
+    ds->show_ds_store = dired_show_ds_store;
+    ds->total_bytes = 0;
+    ds->ndirs = ds->nfiles = 0;
+    ds->ndirs_hidden = ds->nfiles_hidden = 0;
+
+    for (i = 0; i < ds->items.nb_items; i++) {
+        DiredItem *dip = ds->items.items[i]->opaque;
+        const char *p = ds->items.items[i]->str;
+        int hidden = 0;
+
+        if (*p == '.') {
+            if ((!dired_show_dot_files)
+            ||  (!dired_show_ds_store && strequal(p, ".DS_Store")))
+                hidden = 1;
+        }
+        /* XXX: should apply other filters? */
+        dip->hidden = hidden;
+        if (hidden) {
+            if (S_ISDIR(dip->mode)) {
+                ds->ndirs_hidden++;
+            } else {
+                ds->nfiles_hidden++;
+            }
+        } else {
+            if (S_ISDIR(dip->mode)) {
+                ds->ndirs++;
+            } else {
+                ds->nfiles++;
+                ds->total_bytes += dip->size;
+            }
+        }
+    }
+}
+
+static void dired_compute_columns(DiredState *ds)
+{
+    char buf[32];
+    int i, len;
+
+    dired_curtime = time(NULL);
+    ds->time_format = dired_time_format;
+    ds->hflag = dired_hflag;
+    ds->nflag = dired_nflag;
+    ds->blockslen = ds->modelen = ds->linklen = 0;
+    ds->uidlen = ds->gidlen = 0;
+    ds->sizelen = ds->datelen = ds->namelen = 0;
+
+    for (i = 0; i < ds->items.nb_items; i++) {
+        DiredItem *dip = ds->items.items[i]->opaque;
+    
+        len = strlen(dip->name);
+        if (ds->namelen < len)
+            ds->namelen = len;
+
+        len = snprintf(buf, sizeof(buf), "%ld",
+                       (long)(((long long)dip->size + ds->blocksize - 1) /
+                              ds->blocksize));
+        if (ds->blockslen < len)
+            ds->blockslen = len;
+
+        ds->modelen = 10;
+
+        len = snprintf(buf, sizeof(buf), "%d", (int)dip->nlink);
+        if (ds->linklen < len)
+            ds->linklen = len;
+
+        len = format_uid(buf, sizeof(buf), ds->nflag, dip->uid);
+        if (ds->uidlen < len)
+            ds->uidlen = len;
+
+        len = format_gid(buf, sizeof(buf), ds->nflag, dip->gid);
+        if (ds->gidlen < len)
+            ds->gidlen = len;
+
+        len = format_size(buf, sizeof(buf), ds->hflag, dip);
+        if (ds->sizelen < len)
+            ds->sizelen = len;
+
+        len = format_date(buf, sizeof(buf), dip->mtime, dired_time_format);
+        if (ds->datelen < len)
+            ds->datelen = len;
+    }
+}
+
+#define inflect(n, singular, plural)  ((n) == 1 ? (singular) : (plural))
+
+/* `b` is valid, `ds` and `s` may be NULL */
+static void dired_update_buffer(DiredState *ds, EditBuffer *b, EditState *s,
+                                int flags)
 {
     char buf[MAX_FILENAME_SIZE];
-    StringItem *item, *cur_item;
-    DiredItem *dip;
-    int index, i, col, width, top_line;
+    DiredItem *dip, *cur_item;
+    int i, col, width, top_line;
+
+    if (!ds)
+        return;
 
     /* Try and preserve scroll position */
     if (s) {
         eb_get_pos(s->b, &top_line, &col, s->offset_top);
-        index = dired_get_index(s);
+        /* XXX: should use dip->offset and delay to rebuild phase */
+        cur_item = dired_get_cur_item(ds, s);
         width = s->width;
     } else {
-        index = col = top_line = 0;
+        col = top_line = 0;
+        cur_item = NULL;
         width = 80;
     }
 
-    cur_item = NULL;
-    if (index >= 0 && index < ds->items.nb_items)
-        cur_item = ds->items.items[index];
+    if (ds->sort_mode != dired_sort_mode)
+        flags |= DIRED_UPDATE_SORT;
 
+    if (flags & DIRED_UPDATE_SORT) {
+        flags |= DIRED_UPDATE_REBUILD;
+        ds->sort_mode = dired_sort_mode;
     qsort(ds->items.items, ds->items.nb_items,
           sizeof(StringItem *), dired_sort_func);
+    }
 
-    /* construct list buffer */
-    /* deleting buffer contents resets s->offset and s->offset_top */
-    eb_clear(b);
+    if (ds->show_dot_files != dired_show_dot_files
+    ||  ds->show_ds_store != dired_show_ds_store) {
+        flags |= DIRED_UPDATE_FILTER;
+    }
 
-    if (DIRED_HEADER) {
-        b->cur_style = DIRED_STYLE_HEADER;
-        eb_printf(b, "  Directory of ");
-        b->cur_style = DIRED_STYLE_DIRECTORY;
-        eb_printf(b, "%s", ds->path);
-        b->cur_style = DIRED_STYLE_HEADER;
-        eb_printf(b, "\n    %d director%s, %d file%s, %lld byte%s\n",
-                  ds->ndirs, ds->ndirs == 1 ? "y" : "ies",
-                  ds->nfiles, &"s"[ds->nfiles == 1],
-                  (long long)ds->total_bytes, &"s"[ds->total_bytes == 1]);
+    if (flags & DIRED_UPDATE_FILTER) {
+        flags |= DIRED_UPDATE_REBUILD;
+        dired_filter_files(ds);
+    }
+
+    if (ds->time_format != dired_time_format
+    ||  ds->nflag != dired_nflag
+    ||  ds->hflag != dired_hflag) {
+        flags |= DIRED_UPDATE_COLUMNS;
     }
-    b->cur_style = DIRED_STYLE_NORMAL;
+
+    if (flags & DIRED_UPDATE_COLUMNS) {
+        flags |= DIRED_UPDATE_REBUILD;
+        dired_compute_columns(ds);
+    }
+
+    if (!(flags & DIRED_UPDATE_REBUILD))
+        return;
 
     /* XXX: should use screen specific space_width, separator_width or 
em_width */
     ds->last_width = width;
+    ds->last_cur = NULL;
     width -= clamp(ds->namelen, 16, 40);
     ds->no_size = ((width -= ds->sizelen + 2) < 0);
     ds->no_date = ((width -= ds->datelen + 2) < 0);
     ds->no_mode = ((width -= ds->modelen + 1) < 0);
-    ds->no_uid = ((width -= ds->uidlen + 1) < 0);
-    ds->no_gid = ((width -= ds->gidlen + 1) < 0);
+    ds->no_uid = (ds->nflag == 2) || ((width -= ds->uidlen + 1) < 0);
+    ds->no_gid = (ds->nflag == 2) || ((width -= ds->gidlen + 1) < 0);
     ds->no_link = ((width -= ds->linklen + 1) < 0);
     ds->no_blocks = ((width -= ds->blockslen + 1) < 0);
     ds->no_blocks = 1;  // disable blocks display to avoid confusing output
 
+    /* construct list buffer */
+    /* deleting buffer contents resets s->offset and s->offset_top */
+    eb_clear(b);
+
+    if (DIRED_HEADER) {
+        int seq = ' ';
+        b->cur_style = DIRED_STYLE_HEADER;
+        eb_printf(b, "  Directory of ");
+        b->cur_style = DIRED_STYLE_DIRECTORY;
+        eb_printf(b, "%s", ds->path);
+        b->cur_style = DIRED_STYLE_HEADER;
+        eb_printf(b, "\n  ");
+        if (ds->ndirs) {
+            eb_printf(b, "%c %d %s", seq, ds->ndirs,
+                      inflect(ds->ndirs, "directory", "directories"));
+            seq = ',';
+        }
+        if (ds->ndirs_hidden) {
+            eb_printf(b, "%c %d %s", seq, ds->ndirs_hidden,
+                      inflect(ds->ndirs_hidden, "hidden directory", "hidden 
directories"));
+            seq = ',';
+        }
+        if (ds->nfiles) {
+            eb_printf(b, "%c %d %s", seq, ds->nfiles,
+                      inflect(ds->nfiles, "file", "files"));
+            seq = ',';
+        }
+        if (ds->nfiles_hidden) {
+            eb_printf(b, "%c %d %s", seq, ds->nfiles_hidden,
+                      inflect(ds->nfiles_hidden, "hidden file", "hidden 
files"));
+            seq = ',';
+        }
+        if (ds->total_bytes) {
+            format_number(buf, sizeof(buf), ds->hflag, ds->total_bytes);
+            eb_printf(b, "%c %s %s", seq, buf,
+                      inflect(ds->total_bytes, "byte", "bytes"));
+            seq = ',';
+        }
+        if (ds->ndirs + ds->ndirs_hidden + ds->nfiles + ds->nfiles_hidden == 
0) {
+            eb_printf(b, "%c empty", seq);
+        }
+        eb_printf(b, "\n");
+    }
+    b->cur_style = DIRED_STYLE_NORMAL;
+
     for (i = 0; i < ds->items.nb_items; i++) {
-        item = ds->items.items[i];
-        dip = item->opaque;
+        dip = ds->items.items[i]->opaque;
         dip->offset = b->total_size;
-        if (item == cur_item) {
-            if (ds->last_index == index)
-                ds->last_index = i;
+        if (dip == cur_item) {
+            ds->last_cur = dip;
             if (s)
                 s->offset = b->total_size;
         }
+        if (dip->hidden)
+            continue;
         col = eb_printf(b, "%c ", dip->mark);
         if (!ds->no_blocks) {
-            col += eb_printf(b, "%*lu ", ds->blockslen,
-                             (long)((dip->size + ds->blocksize - 1) /
+            col += eb_printf(b, "%*ld ", ds->blockslen,
+                             (long)(((long long)dip->size + ds->blocksize - 1) 
/
                                     ds->blocksize));
         }
         if (!ds->no_mode) {
@@ -611,9 +787,8 @@
 static void dired_mark(EditState *s, int mark)
 {
     DiredState *ds;
-    const StringItem *item;
     DiredItem *dip;
-    int ch, index, dir = 1, flags;
+    int ch, dir = 1, flags;
 
     if (!(ds = dired_get_state(s, 1)))
         return;
@@ -625,12 +800,8 @@
     if (dir < 0)
         dired_up_down(s, -1);
 
-    index = dired_get_index(s);
-    if (index < 0 || index >= ds->items.nb_items)
-        return;
-    item = ds->items.items[index];
-    dip = item->opaque;
-
+    dip = dired_get_cur_item(ds, s);
+    if (dip) {
     ch = dip->mark = mark;
     do_bol(s);
     flags = s->b->flags & BF_READONLY;
@@ -638,81 +809,90 @@
     eb_delete_uchar(s->b, s->offset);
     eb_insert_uchar(s->b, s->offset, ch);
     s->b->flags ^= flags;
-
+    }
     if (dir > 0)
         dired_up_down(s, 1);
 }
 
-static void dired_sort(EditState *s, const char *sort_order)
+static QVarType dired_sort_mode_set_value(EditState *s, VarDef *vp,
+    void *ptr, const char *str, int sort_mode)
 {
-    DiredState *ds;
     const char *p;
 
-    if (!(ds = dired_get_state(s, 1)))
-        return;
-
-    for (p = sort_order; *p; p++) {
+    for (p = str; p && *p; p++) {
         switch (qe_tolower((unsigned char)*p)) {
         case 'n':       /* name */
-            ds->sort_mode &= ~DIRED_SORT_MASK;
-            ds->sort_mode |= DIRED_SORT_NAME;
+            sort_mode &= ~DIRED_SORT_MASK;
+            sort_mode |= DIRED_SORT_NAME;
             break;
         case 'e':       /* extension */
-            ds->sort_mode &= ~DIRED_SORT_MASK;
-            ds->sort_mode |= DIRED_SORT_EXTENSION;
+            sort_mode &= ~DIRED_SORT_MASK;
+            sort_mode |= DIRED_SORT_EXTENSION;
             break;
         case 's':       /* size */
-            ds->sort_mode &= ~DIRED_SORT_MASK;
-            ds->sort_mode |= DIRED_SORT_SIZE;
+            sort_mode &= ~DIRED_SORT_MASK;
+            sort_mode |= DIRED_SORT_SIZE;
             break;
         case 'd':       /* direct */
-            ds->sort_mode &= ~DIRED_SORT_MASK;
-            ds->sort_mode |= DIRED_SORT_DATE;
+            sort_mode &= ~DIRED_SORT_MASK;
+            sort_mode |= DIRED_SORT_DATE;
             break;
         case 'u':       /* ungroup */
-            ds->sort_mode &= ~DIRED_SORT_GROUP;
+            sort_mode &= ~DIRED_SORT_GROUP;
             break;
         case 'g':       /* group */
-            ds->sort_mode |= DIRED_SORT_GROUP;
+            sort_mode |= DIRED_SORT_GROUP;
             break;
         case '+':       /* ascending */
-            ds->sort_mode &= ~DIRED_SORT_DESCENDING;
+            sort_mode &= ~DIRED_SORT_DESCENDING;
             break;
         case '-':       /* descending */
-            ds->sort_mode |= DIRED_SORT_DESCENDING;
+            sort_mode |= DIRED_SORT_DESCENDING;
             break;
         case 'r':       /* reverse */
-            ds->sort_mode ^= DIRED_SORT_DESCENDING;
+            sort_mode ^= DIRED_SORT_DESCENDING;
             break;
         }
     }
-    dired_sort_list(ds, s->b, s);
+    dired_sort_mode = sort_mode;
+    return VAR_NUMBER;
 }
 
-static void dired_set_time_format(EditState *s, int format)
+static void dired_sort(EditState *s, const char *sort_order)
 {
-    char buf[32];
-    DiredState *ds;
-    int i, len;
+    int sort_mode = dired_sort_mode;
 
-    if (!(ds = dired_get_state(s, 1)))
-        return;
+    dired_sort_mode_set_value(s, NULL, &dired_sort_mode, sort_order, 
sort_mode);
+
+    if (sort_mode != dired_sort_mode)
+        dired_update_buffer(dired_get_state(s, 0), s->b, s, DIRED_UPDATE_SORT);
+}
 
+static QVarType dired_time_format_set_value(EditState *s, VarDef *vp,
+    void *ptr, const char *str, int format)
+{
+    if (str) {
+        if (!strxcmp(str, "default"))    format = TF_COMPACT;    else
+        if (!strxcmp(str, "compact"))    format = TF_COMPACT;    else
+        if (!strxcmp(str, "dos"))        format = TF_DOS;        else
+        if (!strxcmp(str, "dos-long"))   format = TF_DOS_LONG;   else
+        if (!strxcmp(str, "touch"))      format = TF_TOUCH;      else
+        if (!strxcmp(str, "touch-long")) format = TF_TOUCH_LONG; else
+        if (!strxcmp(str, "full"))       format = TF_FULL;       else
+        if (!strxcmp(str, "seconds"))    format = TF_SECONDS;    else
+            return VAR_UNKNOWN;
+    }
     if (format < 0 || format > TF_MAX)
-        return;
+       return VAR_UNKNOWN;
 
     dired_time_format = format;
 
-    ds->datelen = 0;
-    for (i = 0; i < ds->items.nb_items; i++) {
-        const StringItem *item = ds->items.items[i];
-        const DiredItem *dip = item->opaque;
+    return VAR_NUMBER;
+}
 
-        len = format_date(buf, sizeof(buf), dip->mtime, format);
-        if (ds->datelen < len)
-            ds->datelen = len;
-    }
-    dired_sort_list(ds, s->b, s);
+static void dired_set_time_format(EditState *s, int format)
+{
+    dired_time_format_set_value(s, NULL, &dired_time_format, NULL, format);
 }
 
 /* `ds` and `b` are valid, `s` and `target` may be NULL */
@@ -721,23 +901,16 @@
 {
     FindFileState *ffst;
     char filename[MAX_FILENAME_SIZE];
-    char line[1024], buf[1024];
+    char line[1024];
     const char *p;
     struct stat st;
-    int len, index;
     StringItem *item;
 
     /* free previous list, if any */
     dired_free(ds);
 
-    curtime = time(NULL);
     ds->blocksize = 1024;
-    ds->ndirs = ds->nfiles = 0;
-    ds->total_bytes = 0;
     ds->last_width = 0;
-    ds->blockslen = ds->modelen = ds->linklen = 0;
-    ds->uidlen = ds->gidlen = 0;
-    ds->sizelen = ds->datelen = ds->namelen = 0;
 
     /* CG: should make absolute ? */
     canonicalize_path(ds->path, sizeof(ds->path), path);
@@ -760,20 +933,7 @@
         if (strequal(p, ".") || strequal(p, ".."))
             continue;
 #endif
-        if (!dired_show_dot_files && *p == '.')
-            continue;
-
-#ifdef CONFIG_DARWIN
-        if (!dired_show_ds_store && strequal(p, ".DS_Store"))
-            continue;
-#endif
         pstrcpy(line, sizeof(line), p);
-        if (S_ISDIR(st.st_mode)) {
-            ds->ndirs++;
-        } else {
-            ds->nfiles++;
-            ds->total_bytes += st.st_size;
-        }
         item = add_string(&ds->items, line, 0);
         if (item) {
             DiredItem *dip;
@@ -788,64 +948,35 @@
             dip->rdev = st.st_rdev;
             dip->mtime = st.st_mtime;
             dip->size = st.st_size;
+            dip->hidden = 0;
             dip->mark = ' ';
             memcpy(dip->name, p, plen + 1);
             item->opaque = dip;
-
-            if (ds->namelen < plen)
-                ds->namelen = plen;
-
-            len = snprintf(buf, sizeof(buf), "%lu",
-                           ((unsigned long)st.st_size + ds->blocksize - 1) /
-                           ds->blocksize);
-            if (ds->blockslen < len)
-                ds->blockslen = len;
-
-            ds->modelen = 10;
-
-            len = snprintf(buf, sizeof(buf), "%d", (int)st.st_nlink);
-            if (ds->linklen < len)
-                ds->linklen = len;
-
-            len = format_uid(buf, sizeof(buf), ds->nflag, st.st_uid);
-            if (ds->uidlen < len)
-                ds->uidlen = len;
-
-            len = format_gid(buf, sizeof(buf), ds->nflag, st.st_gid);
-            if (ds->gidlen < len)
-                ds->gidlen = len;
-
-            len = format_size(buf, sizeof(buf), ds->hflag, dip);
-            if (ds->sizelen < len)
-                ds->sizelen = len;
-
-            len = format_date(buf, sizeof(buf), dip->mtime, dired_time_format);
-            if (ds->datelen < len)
-                ds->datelen = len;
         }
     }
     find_file_close(&ffst);
 
-    dired_sort_list(ds, b, s);
+    dired_update_buffer(ds, b, s, DIRED_UPDATE_ALL);
     if (s) {
-        index = dired_find_target(ds, target);
-        s->offset = eb_goto_pos(b, max(index, 0) + DIRED_HEADER, ds->fnamecol);
+        s->offset = eb_goto_pos(b, dired_find_target(ds, target), 
ds->fnamecol);
     }
 }
 
 /* select current item */
 static void dired_select(EditState *s)
 {
+    char filename[MAX_FILENAME_SIZE];
     DiredState *ds;
     struct stat st;
-    char filename[MAX_FILENAME_SIZE];
     EditState *e;
 
     if (!(ds = dired_get_state(s, 1)))
         return;
 
-    if (!dired_get_filename(ds, dired_get_index(s), filename, 
sizeof(filename)))
+    if (!dired_get_filename(ds, dired_get_cur_item(ds, s),
+                            filename, sizeof(filename))) {
         return;
+    }
 
     /* Check if path leads somewhere */
     if (stat(filename, &st) < 0)
@@ -936,6 +1067,16 @@
     dired_build_list(ds, filename, target, s->b, s);
 }
 
+static void dired_toggle_human(EditState *s)
+{
+    dired_hflag = (dired_hflag + 1) % 3;
+}
+
+static void dired_toggle_nflag(EditState *s)
+{
+    dired_nflag = (dired_nflag + 1) % 3;
+}
+
 static void dired_refresh(EditState *s)
 {
     DiredState *ds;
@@ -945,7 +1086,8 @@
     if (!(ds = dired_get_state(s, 1)))
         return;
 
-    dired_get_filename(ds, dired_get_index(s), target, sizeof(target));
+    dired_get_filename(ds, dired_get_cur_item(ds, s),
+                       target, sizeof(target));
     pstrcpy(dirname, sizeof(dirname), ds->path);
     dired_build_list(ds, dirname, target, s->b, s);
 }
@@ -957,16 +1099,17 @@
 
     if (dired_show_dot_files != val) {
         dired_show_dot_files = val;
-        dired_refresh(s);
+        dired_update_buffer(dired_get_state(s, 0), s->b, s, 
DIRED_UPDATE_FILTER);
         put_status(s, "dot files are %s", val ? "visible" : "hidden");
     }
 }
 
 static void dired_display_hook(EditState *s)
 {
-    DiredState *ds;
     char filename[MAX_FILENAME_SIZE];
-    int index;
+    DiredState *ds;
+    DiredItem *dip;
+    int flags = 0;
 
     if (!(ds = dired_get_state(s, 0)))
         return;
@@ -975,23 +1118,23 @@
     if (s->offset && s->offset == s->b->total_size)
         dired_up_down(s, -1);
 
-    if (s->x1 == 0) {
-        if (s->y1 == 0 && ds->last_width != s->width) {
+    if (s->x1 == 0 && s->y1 == 0 && ds->last_width != s->width) {
             /* rebuild buffer contents according to new window width */
             /* XXX: this may cause problems if buffer is displayed in
              * multiple windows, hence the test on s->y1.
              * Should test for current window */
-            dired_sort_list(ds, s->b, s);
+        flags |= DIRED_UPDATE_REBUILD;
         }
+
+    dired_update_buffer(ds, s->b, s, flags);
+
+    if (s->x1 == 0) {
         /* open file so that user can see it before it is selected */
         /* XXX: find a better solution (callback) */
-        index = dired_get_index(s);
-        if (index < 0 || index >= ds->items.nb_items)
-            return;
-        /* Should not rely on last_index! */
-        if (index != ds->last_index) {
-            ds->last_index = index;
-            if (dired_get_filename(ds, index, filename, sizeof(filename))) {
+        dip = dired_get_cur_item(ds, s);
+        if (dip != ds->last_cur) {
+            ds->last_cur = dip;
+            if (dired_get_filename(ds, dip, filename, sizeof(filename))) {
                 dired_view_file(s, filename);
             }
         }
@@ -1008,10 +1151,6 @@
     list_mode.mode_init(s, b, flags);
 
     if (flags & MODEF_NEWINSTANCE) {
-        /* XXX: Should use last sort mode, a global variable */
-        ds->sort_mode = DIRED_SORT_GROUP | DIRED_SORT_NAME;
-        ds->last_index = -1;
-
         eb_create_style_buffer(b, BF_STYLE1);
         /* XXX: should be built by buffer_load API */
         dired_build_list(ds, b->filename, NULL, b, s);
@@ -1052,7 +1191,7 @@
     EditBuffer *b;
     EditState *e;
     DiredState *ds;
-    int width, index;
+    int width;
     char filename[MAX_FILENAME_SIZE], *p;
     char target[MAX_FILENAME_SIZE];
 
@@ -1084,8 +1223,7 @@
 
     ds = dired_get_state(e, 0);
     if (ds) {
-        index = dired_find_target(ds, target);
-        e->offset = eb_goto_pos(e->b, max(index, 0) + DIRED_HEADER,
+        e->offset = eb_goto_pos(e->b, dired_find_target(ds, target),
                                 ds->fnamecol);
     }
     /* modify active window */
@@ -1142,6 +1280,10 @@
     /* R -> rename a file or move selection to another directory */
     /* C -> copy files */
     /* mark files globally */
+    CMD0( 'H', KEY_NONE,
+          "dired-toggle-human", dired_toggle_human)
+    CMD0( 'N', KEY_NONE,
+          "dired-toggle-nflag", dired_toggle_nflag)
     CMD_DEF_END,
 };
 
@@ -1152,11 +1294,12 @@
 };
 
 static VarDef dired_variables[] = {
-    G_VAR( "dired-time-format", dired_time_format, VAR_NUMBER, VAR_RW_SAVE )
+    G_VAR_F( "dired-time-format", dired_time_format, VAR_NUMBER, VAR_RW_SAVE,
+            dired_time_format_set_value )
     G_VAR( "dired-show-dot-files", dired_show_dot_files, VAR_NUMBER, 
VAR_RW_SAVE )
-#ifdef CONFIG_DARWIN
     G_VAR( "dired-show-ds-store", dired_show_ds_store, VAR_NUMBER, VAR_RW_SAVE 
)
-#endif
+    G_VAR_F( "dired-sort-mode", dired_sort_mode, VAR_NUMBER, VAR_RW_SAVE,
+            dired_sort_mode_set_value )
 };
 
 static int dired_init(void)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]