Ticket #3165: 0001-Display-human-readable-sizes-in-panels.patch

File 0001-Display-human-readable-sizes-in-panels.patch, 14.3 KB (added by wentasah, 7 years ago)

Patch

  • lib/util.c

    From 27ab0a7b65e79fc64a65f947f115ba6f8c370bac Mon Sep 17 00:00:00 2001
    From: Michal Sojka <sojkam1@fel.cvut.cz>
    Date: Sun, 2 Feb 2014 22:44:57 +0100
    Subject: [PATCH] Display human readable sizes in panels
    
    When midnight commander displays the size of a file, it tries to
    display as much digits as fits into the size column (7 characters
    wide). The result is that for a 3 MB file it shows, for example,
    3010050. In many cases, it is not important to know the exact number
    of bytes in a file, but only an approximate size (3 MB). Short numbers
    are more "human friendly".
    
    This patch adds a configuration option that enables displaying such
    human readable sizes in panels. The "human readable" means that at
    most three digits are displayed for each file size. This is
    accomplished by modifying function size_trunc_len(). Since the comment
    of this function says that floating point should be avoided by any
    means, the implementation is not as trivial as it could be. It
    displays floating point numbers by displaying integer and fractional
    parts separately as integers.
    
    The effect of this patch is shown in the following table. "si" and
    "hr" denote the values use_si and human_readable parameters of the
    size_trunc_len() function. The table shows the results of the function
    for different sizes.
    
                     CURRENT        THIS PATCH
          size |  !si!hr   si!hr  !si hr   si hr
    -----------|--------------------------------
           950 |     950     950     950     950
          1001 |    1001    1001   0.97K   1.00k
          1005 |    1005    1005   0.98K   1.01k
          1023 |    1023    1023   0.99K   1.02k
          1024 |    1024    1024   0.99K   1.02k
          9849 |    9849    9849   9.61K   9.85k
         12050 |   12050   12050   11.8K   12.1k
         99940 |   99940   99940   97.5K   99.9k
        100000 |  100000  100000   97.6K    100k
        102399 |  102399  102399    100K    102k
        102400 |  102400  102400    100K    102k
        210050 |  210050  210050    205K    210k
       3010050 | 3010050 3010050   2.87M   3.01m
      43010050 |  42002K  43010k   41.0M   43.0m
    1072693248 |   1023M   1073m   0.99G   1.07g
    
    Currently, the decimal separator (".") is hardcoded and independent of
    user's locale.
    
    If anyone wants to test the patch, the table was created with the code
    below.
    
    void print(uintmax_t size)
    {
    	char buffer[50];
    	int units = 0;
    	gboolean use_si = TRUE;
    	gboolean human_readable = TRUE;
    	int len = 7;
    
    	printf("%10ld", size);
    	size_trunc_len (buffer, len, size, units, !use_si, !human_readable);
    	printf("%8s", buffer);
    	size_trunc_len (buffer, len, size, units,  use_si, !human_readable);
    	printf("%8s", buffer);
    	size_trunc_len (buffer, len, size, units, !use_si,  human_readable);
    	printf("%8s", buffer);
    	size_trunc_len (buffer, len, size, units,  use_si,  human_readable);
    	printf("%8s", buffer);
    	printf("\n");
    }
    
    int main(int argc, char *argv[])
    {
    	print(950);
    	print(1001);
    	// ...
    }
    ---
     lib/util.c                | 27 +++++++++++++++++++++++++--
     lib/util.h                |  2 +-
     src/filemanager/boxes.c   |  1 +
     src/filemanager/chown.c   |  2 +-
     src/filemanager/filegui.c |  8 ++++----
     src/filemanager/info.c    |  6 +++---
     src/filemanager/panel.c   |  6 +++---
     src/setup.c               |  2 ++
     src/setup.h               |  1 +
     src/viewer/display.c      |  2 +-
     10 files changed, 42 insertions(+), 15 deletions(-)
    
    diff --git a/lib/util.c b/lib/util.c
    index a34d1b8..093d947 100644
    a b size_trunc_sep (uintmax_t size, gboolean use_si) 
    413413 */ 
    414414 
    415415void 
    416 size_trunc_len (char *buffer, unsigned int len, uintmax_t size, int units, gboolean use_si) 
     416size_trunc_len (char *buffer, unsigned int len, uintmax_t size, int units, gboolean use_si, 
     417                gboolean human_readable) 
    417418{ 
    418419    /* Avoid taking power for every file.  */ 
    419420    /* *INDENT-OFF* */ 
    size_trunc_len (char *buffer, unsigned int len, uintmax_t size, int units, gbool 
    454455    static const char *const suffix_lc[] = { "", "k", "m", "g", "t", "p", "e", "z", "y", NULL }; 
    455456 
    456457    const char *const *sfx = use_si ? suffix_lc : suffix; 
     458    unsigned base = use_si ? 1000 : 1024; 
     459    unsigned human_digits; 
    457460    int j = 0; 
    458461 
    459462    if (len == 0) 
    size_trunc_len (char *buffer, unsigned int len, uintmax_t size, int units, gbool 
    484487            size += size_remain;        /* Re-add remainder lost by division/multiplication */ 
    485488        } 
    486489 
     490    if (human_readable && len < 5) 
     491        human_readable = FALSE; /* Human readable form needs 5 characters */ 
     492 
    487493    for (j = units; sfx[j] != NULL; j++) 
    488494    { 
    489495        if (size == 0) 
    size_trunc_len (char *buffer, unsigned int len, uintmax_t size, int units, gbool 
    501507            break; 
    502508        } 
    503509 
    504         if (size < power10[len - (j > 0 ? 1 : 0)]) 
     510#define DIV_ROUND(a, b) (((a) + ((b)/2))/(b)) 
     511        if ((!human_readable && size < power10[len - (j > 0 ? 1 : 0)]) || 
     512            (human_readable && size < 1000)) 
    505513        { 
    506514            g_snprintf (buffer, len + 1, "%" PRIuMAX "%s", size, sfx[j]); 
    507515            break; 
    508516        } 
     517        else if (human_readable && DIV_ROUND (size, 10) < base && sfx[j + 1]) 
     518        { 
     519            human_digits = DIV_ROUND (size, 10) * 1000 / base;  /* 0 - 999 */ 
     520            g_snprintf (buffer, len + 1, "%u.%02u%s", 
     521                        human_digits / 100, human_digits % 100, sfx[j + 1]); 
     522            break; 
     523        } 
     524        else if (human_readable && DIV_ROUND (size, 100) < base && sfx[j + 1]) 
     525        { 
     526            human_digits = DIV_ROUND (size, 100) * 1000 / base; /* 0 - 999 */ 
     527            g_snprintf (buffer, len + 1, "%u.%01u%s", 
     528                        human_digits / 10, human_digits % 10, sfx[j + 1]); 
     529            break; 
     530        } 
     531#undef DIV_ROUND 
    509532 
    510533        /* Powers of 1000 or 1024, with rounding.  */ 
    511534        if (use_si) 
  • lib/util.h

    diff --git a/lib/util.h b/lib/util.h
    index 24f55c1..49e6530 100644
    a b const char *size_trunc_sep (uintmax_t size, gboolean use_si); 
    106106 * not including trailing 0. BUFFER should be at least LEN+1 long. 
    107107 * 
    108108 * Units: size units (0=bytes, 1=Kbytes, 2=Mbytes, etc.) */ 
    109 void size_trunc_len (char *buffer, unsigned int len, uintmax_t size, int units, gboolean use_si); 
     109void size_trunc_len (char *buffer, unsigned int len, uintmax_t size, int units, gboolean use_si, gboolean human_readable); 
    110110const char *string_perm (mode_t mode_bits); 
    111111 
    112112const char *extension (const char *); 
  • src/filemanager/boxes.c

    diff --git a/src/filemanager/boxes.c b/src/filemanager/boxes.c
    index bd15ae9..7ae3fde 100644
    a b panel_options_box (void) 
    536536                QUICK_START_GROUPBOX (N_("Main options")), 
    537537                    QUICK_CHECKBOX (N_("Show mi&ni-status"), &panels_options.show_mini_info, NULL), 
    538538                    QUICK_CHECKBOX (N_("Use SI si&ze units"), &panels_options.kilobyte_si, NULL), 
     539                    QUICK_CHECKBOX (N_("Human readable &size"), &panels_options.human_readable, NULL), 
    539540                    QUICK_CHECKBOX (N_("Mi&x all files"), &panels_options.mix_all_files, NULL), 
    540541                    QUICK_CHECKBOX (N_("Show &backup files"), &panels_options.show_backups, NULL), 
    541542                    QUICK_CHECKBOX (N_("Show &hidden files"), &panels_options.show_dot_files, NULL), 
  • src/filemanager/chown.c

    diff --git a/src/filemanager/chown.c b/src/filemanager/chown.c
    index 5040b16..bd56c61 100644
    a b chown_cmd (void) 
    367367        chown_label (0, str_trunc (fname, GW - 4)); 
    368368        chown_label (1, str_trunc (get_owner (sf_stat.st_uid), GW - 4)); 
    369369        chown_label (2, str_trunc (get_group (sf_stat.st_gid), GW - 4)); 
    370         size_trunc_len (buffer, GW - 4, sf_stat.st_size, 0, panels_options.kilobyte_si); 
     370        size_trunc_len (buffer, GW - 4, sf_stat.st_size, 0, panels_options.kilobyte_si, panels_options.human_readable); 
    371371        chown_label (3, buffer); 
    372372        chown_label (4, string_perm (sf_stat.st_mode)); 
    373373 
  • src/filemanager/filegui.c

    diff --git a/src/filemanager/filegui.c b/src/filemanager/filegui.c
    index b75fa24..82ed527 100644
    a b overwrite_query_dialog (file_op_context_t * ctx, enum OperationMode mode) 
    557557 
    558558    /* source date and size */ 
    559559    size_trunc_len (fsize_buffer, sizeof (fsize_buffer), ui->s_stat->st_size, 0, 
    560                     panels_options.kilobyte_si); 
     560                    panels_options.kilobyte_si, panels_options.human_readable); 
    561561    ADD_RD_LABEL (2, file_date (ui->s_stat->st_mtime), fsize_buffer, y++); 
    562562    rd_xlen = max (rd_xlen, label2->cols + 8); 
    563563    /* destination date and size */ 
    564564    size_trunc_len (fsize_buffer, sizeof (fsize_buffer), ui->d_stat->st_size, 0, 
    565                     panels_options.kilobyte_si); 
     565                    panels_options.kilobyte_si, panels_options.human_readable); 
    566566    ADD_RD_LABEL (3, file_date (ui->d_stat->st_mtime), fsize_buffer, y++); 
    567567    rd_xlen = max (rd_xlen, label2->cols + 8); 
    568568 
    file_progress_show_total (FileOpTotalContext * tctx, file_op_context_t * ctx, 
    10091009 
    10101010    if (ui->total_bytes_label != NULL) 
    10111011    { 
    1012         size_trunc_len (buffer2, 5, tctx->copied_bytes, 0, panels_options.kilobyte_si); 
     1012            size_trunc_len (buffer2, 5, tctx->copied_bytes, 0, panels_options.kilobyte_si, panels_options.human_readable); 
    10131013        if (!ctx->progress_totals_computed) 
    10141014            g_snprintf (buffer, BUF_TINY, _(" Total: %s "), buffer2); 
    10151015        else 
    10161016        { 
    1017             size_trunc_len (buffer3, 5, ctx->progress_bytes, 0, panels_options.kilobyte_si); 
     1017            size_trunc_len (buffer3, 5, ctx->progress_bytes, 0, panels_options.kilobyte_si, panels_options.human_readable); 
    10181018            g_snprintf (buffer, BUF_TINY, _(" Total: %s/%s "), buffer2, buffer3); 
    10191019        } 
    10201020 
  • src/filemanager/info.c

    diff --git a/src/filemanager/info.c b/src/filemanager/info.c
    index 6397723..335a984 100644
    a b info_show_info (WInfo * info) 
    167167        { 
    168168            char buffer1[6], buffer2[6]; 
    169169 
    170             size_trunc_len (buffer1, 5, myfs_stats.avail, 1, panels_options.kilobyte_si); 
    171             size_trunc_len (buffer2, 5, myfs_stats.total, 1, panels_options.kilobyte_si); 
     170            size_trunc_len (buffer1, 5, myfs_stats.avail, 1, panels_options.kilobyte_si, panels_options.human_readable); 
     171            size_trunc_len (buffer2, 5, myfs_stats.total, 1, panels_options.kilobyte_si, panels_options.human_readable); 
    172172            tty_printf (_("Free space: %s/%s (%d%%)"), buffer1, buffer2, 
    173173                        myfs_stats.total == 0 ? 0 : 
    174174                        (int) (100 * (long double) myfs_stats.avail / myfs_stats.total)); 
    info_show_info (WInfo * info) 
    221221#endif 
    222222        { 
    223223            char buffer[10]; 
    224             size_trunc_len (buffer, 9, st.st_size, 0, panels_options.kilobyte_si); 
     224            size_trunc_len (buffer, 9, st.st_size, 0, panels_options.kilobyte_si, panels_options.human_readable); 
    225225            tty_printf (_("Size:      %s"), buffer); 
    226226#ifdef HAVE_STRUCT_STAT_ST_BLOCKS 
    227227            tty_printf (ngettext (" (%ld block)", " (%ld blocks)", 
  • src/filemanager/panel.c

    diff --git a/src/filemanager/panel.c b/src/filemanager/panel.c
    index 45e4759..b21f14e 100644
    a b string_file_size (file_entry_t * fe, int len) 
    510510    else 
    511511#endif 
    512512    { 
    513         size_trunc_len (buffer, (unsigned int) len, fe->st.st_size, 0, panels_options.kilobyte_si); 
     513        size_trunc_len (buffer, (unsigned int) len, fe->st.st_size, 0, panels_options.kilobyte_si, panels_options.human_readable); 
    514514    } 
    515515    return buffer; 
    516516} 
    show_free_space (WPanel * panel) 
    11411141        char buffer1[6], buffer2[6], tmp[BUF_SMALL]; 
    11421142 
    11431143        size_trunc_len (buffer1, sizeof (buffer1) - 1, myfs_stats.avail, 1, 
    1144                         panels_options.kilobyte_si); 
     1144                        panels_options.kilobyte_si, panels_options.human_readable); 
    11451145        size_trunc_len (buffer2, sizeof (buffer2) - 1, myfs_stats.total, 1, 
    1146                         panels_options.kilobyte_si); 
     1146                        panels_options.kilobyte_si, panels_options.human_readable); 
    11471147        g_snprintf (tmp, sizeof (tmp), " %s/%s (%d%%) ", buffer1, buffer2, 
    11481148                    myfs_stats.total == 0 ? 0 : 
    11491149                    (int) (100 * (long double) myfs_stats.avail / myfs_stats.total)); 
  • src/setup.c

    diff --git a/src/setup.c b/src/setup.c
    index 20c7145..8c46278 100644
    a b int saving_setup; 
    130130panels_options_t panels_options = { 
    131131    .show_mini_info = TRUE, 
    132132    .kilobyte_si = FALSE, 
     133    .human_readable = FALSE, 
    133134    .mix_all_files = FALSE, 
    134135    .show_backups = TRUE, 
    135136    .show_dot_files = TRUE, 
    static const struct 
    389390} panels_ini_options[] = { 
    390391    { "show_mini_info", &panels_options.show_mini_info }, 
    391392    { "kilobyte_si", &panels_options.kilobyte_si }, 
     393    { "human_readable", &panels_options.human_readable }, 
    392394    { "mix_all_files", &panels_options.mix_all_files }, 
    393395    { "show_backups", &panels_options.show_backups }, 
    394396    { "show_dot_files", &panels_options.show_dot_files }, 
  • src/setup.h

    diff --git a/src/setup.h b/src/setup.h
    index 4d43117..e7e9378 100644
    a b typedef struct 
    3737    gboolean show_mini_info;    /* If true, show the mini-info on the panel */ 
    3838    gboolean kilobyte_si;       /* If TRUE, SI units (1000 based) will be used for larger units 
    3939                                 * (kilobyte, megabyte, ...). If FALSE, binary units (1024 based) will be used */ 
     40    gboolean human_readable;    /* If TRUE, at most three digits are used to display the size of the files. */ 
    4041    gboolean mix_all_files;     /* If FALSE then directories are shown separately from files */ 
    4142    gboolean show_backups;      /* If TRUE, show files ending in ~ */ 
    4243    gboolean show_dot_files;    /* If TRUE, show files starting with a dot */ 
  • src/viewer/display.c

    diff --git a/src/viewer/display.c b/src/viewer/display.c
    index ed3ed2a..9849a33 100644
    a b mcview_display_status (mcview_t * view) 
    156156            char buffer[BUF_TRUNC_LEN + 1]; 
    157157 
    158158            size_trunc_len (buffer, BUF_TRUNC_LEN, mcview_get_filesize (view), 0, 
    159                             panels_options.kilobyte_si); 
     159                            panels_options.kilobyte_si, panels_options.human_readable); 
    160160            tty_printf ("%9" PRIuMAX "/%s%s %s", (uintmax_t) view->dpy_end, 
    161161                        buffer, mcview_may_still_grow (view) ? "+" : " ", 
    162162#ifdef HAVE_CHARSET