(size_trunc_len): align to properly use either IEC or SI prefixes with the unit B (byte).

Additionally always put a space between number and unit which is
required by the norms.

It is important to note that really small buffers have to be bigger than it
appears because they store bytes and non-Latin scripts need more than one byte
with UTF-8 to encode them, e.g., the string "1023 МиБ" in Russian requires
11 bytes + null terminator.

Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
This commit is contained in:
Michael Osipov 2016-08-25 15:09:03 +02:00 committed by Andrew Borodin
parent b3867a6e15
commit bae814d0d4
4 changed files with 37 additions and 25 deletions

View File

@ -448,23 +448,26 @@ size_trunc_len (char *buffer, unsigned int len, uintmax_t size, int units, gbool
*/ */
#endif #endif
}; };
/* *INDENT-ON* */
static const char *const suffix[] = { "", "K", "M", "G", "T", "P", "E", "Z", "Y", NULL };
static const char *const suffix_lc[] = { "", "k", "m", "g", "t", "p", "e", "z", "y", NULL };
const char *const *sfx = use_si ? suffix_lc : suffix; static const char *const units_iec[] = { N_("B"), N_("KiB"), N_("MiB"), N_("GiB"), N_("TiB"),
N_("PiB"), N_("EiB"), N_("ZiB"), N_("YiB"), NULL };
static const char *const units_si[] = { N_("B"), N_("kB"), N_("MB"), N_("GB"), N_("TB"),
N_("PB"), N_("EB"), N_("ZB"), N_("YB"), NULL };
/* *INDENT-ON* */
const char *const *sfx = use_si ? units_si : units_iec;
int j = 0; int j = 0;
if (len == 0) if (len == 0)
len = 9; len = 9;
#if SIZEOF_UINTMAX_T == 8 #if SIZEOF_UINTMAX_T == 8
/* 20 decimal digits are required to represent 8 bytes */ /* 20 decimal digits are required to represent 8 bytes */
else if (len > 19) else if (len > 21)
len = 19; len = 21;
#else #else
/* 10 decimal digits are required to represent 4 bytes */ /* 10 decimal digits are required to represent 4 bytes */
else if (len > 9) else if (len > 11)
len = 9; len = 11;
#endif #endif
/* /*
@ -489,20 +492,25 @@ size_trunc_len (char *buffer, unsigned int len, uintmax_t size, int units, gbool
{ {
if (j == units) if (j == units)
{ {
/* Empty files will print "0" even with minimal width. */ /* Empty files will print "0 B" even with minimal width. */
g_snprintf (buffer, len + 1, "%s", "0"); g_snprintf (buffer, len + 1, "0 %s", _("B"));
} }
else else
{ {
/* Use "~K" or just "K" if len is 1. Use "B" for bytes. */ /* Use "~KiB/kB" or just "KiB/kB" if len is 1. Use "B" for bytes. */
g_snprintf (buffer, len + 1, (len > 1) ? "~%s" : "%s", (j > 1) ? sfx[j - 1] : "B"); g_snprintf (buffer, len + 1, (len > 1) ? "~%s" : "%s",
(j > 1) ? _(sfx[j - 1]) : _("B"));
} }
break; break;
} }
if (size < power10[len - (j > 0 ? 1 : 0)]) /*
* Offset calculation: 1 for space + 2*3 bytes for scaled units as multibyte
* encoding with UTF-8 for non-Latin scripts.
*/
if (size < power10[len - (1 + 6)])
{ {
g_snprintf (buffer, len + 1, "%" PRIuMAX "%s", size, sfx[j]); g_snprintf (buffer, len + 1, "%" PRIuMAX " %s", size, _(sfx[j]));
break; break;
} }

View File

@ -1013,12 +1013,12 @@ file_progress_show_total (file_op_total_context_t * tctx, file_op_context_t * ct
if (ui->total_bytes_label != NULL) if (ui->total_bytes_label != NULL)
{ {
size_trunc_len (buffer2, 5, tctx->copied_bytes, 0, panels_options.kilobyte_si); size_trunc_len (buffer2, 11, tctx->copied_bytes, 0, panels_options.kilobyte_si);
if (!ctx->progress_totals_computed) if (!ctx->progress_totals_computed)
g_snprintf (buffer, sizeof (buffer), _(" Total: %s "), buffer2); g_snprintf (buffer, sizeof (buffer), _(" Total: %s "), buffer2);
else else
{ {
size_trunc_len (buffer3, 5, ctx->progress_bytes, 0, panels_options.kilobyte_si); size_trunc_len (buffer3, 11, ctx->progress_bytes, 0, panels_options.kilobyte_si);
g_snprintf (buffer, sizeof (buffer), _(" Total: %s/%s "), buffer2, buffer3); g_snprintf (buffer, sizeof (buffer), _(" Total: %s/%s "), buffer2, buffer3);
} }

View File

@ -176,10 +176,12 @@ info_show_info (WInfo * info)
tty_print_string (_("No space information")); tty_print_string (_("No space information"));
else else
{ {
char buffer1[6], buffer2[6]; char buffer1[12], buffer2[12];
size_trunc_len (buffer1, 5, myfs_stats.avail, 1, panels_options.kilobyte_si); size_trunc_len (buffer1, sizeof (buffer1) - 1, myfs_stats.avail, 1,
size_trunc_len (buffer2, 5, myfs_stats.total, 1, panels_options.kilobyte_si); panels_options.kilobyte_si);
size_trunc_len (buffer2, sizeof (buffer2) - 1, myfs_stats.total, 1,
panels_options.kilobyte_si);
tty_printf (_("Free space: %s/%s (%d%%)"), buffer1, buffer2, tty_printf (_("Free space: %s/%s (%d%%)"), buffer1, buffer2,
myfs_stats.total == 0 ? 0 : myfs_stats.total == 0 ? 0 :
(int) (100 * (long double) myfs_stats.avail / myfs_stats.total)); (int) (100 * (long double) myfs_stats.avail / myfs_stats.total));
@ -232,8 +234,9 @@ info_show_info (WInfo * info)
else else
#endif #endif
{ {
char buffer[10]; char buffer[12];
size_trunc_len (buffer, 9, st.st_size, 0, panels_options.kilobyte_si);
size_trunc_len (buffer, sizeof (buffer) - 1, st.st_size, 0, panels_options.kilobyte_si);
tty_printf (_("Size: %s"), buffer); tty_printf (_("Size: %s"), buffer);
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
tty_printf (ngettext (" (%ld block)", " (%ld blocks)", tty_printf (ngettext (" (%ld block)", " (%ld blocks)",

View File

@ -195,7 +195,7 @@ static panel_field_t panel_fields[] = {
} }
, ,
{ {
"size", 7, FALSE, J_RIGHT, "size", 8, FALSE, J_RIGHT,
/* TRANSLATORS: one single character to represent 'size' sort mode */ /* TRANSLATORS: one single character to represent 'size' sort mode */
/* TRANSLATORS: no need to translate 'sort', it's just a context prefix */ /* TRANSLATORS: no need to translate 'sort', it's just a context prefix */
N_("sort|s"), N_("sort|s"),
@ -205,7 +205,7 @@ static panel_field_t panel_fields[] = {
} }
, ,
{ {
"bsize", 7, FALSE, J_RIGHT, "bsize", 8, FALSE, J_RIGHT,
"", "",
N_("Block Size"), FALSE, FALSE, N_("Block Size"), FALSE, FALSE,
string_file_size_brief, string_file_size_brief,
@ -515,7 +515,8 @@ string_file_size (file_entry_t * fe, int len)
format_device_number (buffer, len + 1, fe->st.st_rdev); format_device_number (buffer, len + 1, fe->st.st_rdev);
else else
#endif #endif
size_trunc_len (buffer, (unsigned int) len, fe->st.st_size, 0, panels_options.kilobyte_si); size_trunc_len (buffer, (unsigned int) (len + 3), fe->st.st_size, 0,
panels_options.kilobyte_si);
return buffer; return buffer;
} }
@ -1154,7 +1155,7 @@ show_free_space (const WPanel * panel)
if (myfs_stats.avail != 0 || myfs_stats.total != 0) if (myfs_stats.avail != 0 || myfs_stats.total != 0)
{ {
const Widget *w = CONST_WIDGET (panel); const Widget *w = CONST_WIDGET (panel);
char buffer1[6], buffer2[6], tmp[BUF_SMALL]; char buffer1[12], buffer2[12], tmp[BUF_SMALL];
size_trunc_len (buffer1, sizeof (buffer1) - 1, myfs_stats.avail, 1, size_trunc_len (buffer1, sizeof (buffer1) - 1, myfs_stats.avail, 1,
panels_options.kilobyte_si); panels_options.kilobyte_si);