diff --git a/src/intf.c b/src/intf.c index 4f3e1e1..010c01e 100644 --- a/src/intf.c +++ b/src/intf.c @@ -70,11 +70,13 @@ struct argument { #define MAXFMTSPECS 16 // Maximum number of conversion specifiers struct convspec { - int len; // Length of conversion specifier, 0 = unused + char spec; // Conversion specifier: c d f N s int arg_num; // Which variable argument to use - char spec; // Conversion specifier: c d N s + int len; // Length of conversion specifier, 0 = unused + int precision; // Precision value bool flag_group; // Flag "'" (thousands grouping) bool flag_nosym; // Flag "!" (omit currency symbol) + bool flag_prec; // Flag "." (precision) bool flag_long; // Length modifier "l" (long) }; @@ -835,6 +837,17 @@ int mkchstr_parse (const char *restrict format, flag_other = true; break; + case '.': + // Precision flag + if (format_spec->flag_prec || count != 0) { + errno = EINVAL; + return -1; + } + + format_spec->flag_prec = true; + flag_other = true; + break; + case 'l': // Long length modifier if (format_spec->flag_long) { @@ -850,7 +863,8 @@ int mkchstr_parse (const char *restrict format, case 'c': // Insert a character (char) if (format_spec->flag_group || format_spec->flag_nosym - || format_spec->flag_long || count != 0) { + || format_spec->flag_prec || format_spec->flag_long + || count != 0) { errno = EINVAL; return -1; } @@ -860,7 +874,8 @@ int mkchstr_parse (const char *restrict format, case 'd': // Insert an integer (int or long int) - if (count != 0) { + if (format_spec->flag_nosym || format_spec->flag_prec + || count != 0) { errno = EINVAL; return -1; } @@ -869,10 +884,23 @@ int mkchstr_parse (const char *restrict format, TYPE_LONGINT : TYPE_INT; goto handlefmt; + case 'f': + // Insert a floating-point number (double) + if (format_spec->flag_nosym || format_spec->flag_long || + (! format_spec->flag_prec && count != 0)) { + errno = EINVAL; + return -1; + } + + format_spec->precision = count; + + arg_type = TYPE_DOUBLE; + goto handlefmt; + case 'N': // Insert a monetary amount (double) - if (format_spec->flag_group || format_spec->flag_long - || count != 0) { + if (format_spec->flag_group || format_spec->flag_prec + || format_spec->flag_long || count != 0) { errno = EINVAL; return -1; } @@ -883,7 +911,8 @@ int mkchstr_parse (const char *restrict format, case 's': // Insert a string (const char *) if (format_spec->flag_group || format_spec->flag_nosym - || format_spec->flag_long || count != 0) { + || format_spec->flag_prec || format_spec->flag_long + || count != 0) { errno = EINVAL; return -1; } @@ -1102,6 +1131,31 @@ int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, str = buf; goto insertstr; + case 'f': + // Insert a floating-point number (double) into the output + if (spec->flag_prec) { + if (snprintf(buf, BUFSIZE, spec->flag_group ? + "%'.*f" : "%.*f", spec->precision, + format_arg[spec->arg_num].a.a_double) < 0) { + saved_errno = errno; + free(buf); + errno = saved_errno; + goto error; + } + } else { + if (snprintf(buf, BUFSIZE, spec->flag_group ? + "%'f" : "%f", + format_arg[spec->arg_num].a.a_double) < 0) { + saved_errno = errno; + free(buf); + errno = saved_errno; + goto error; + } + } + + str = buf; + goto insertstr; + case 'N': // Insert a monetary amount (double) into the output if (l_strfmon(buf, BUFSIZE, spec->flag_nosym ? "%!n" : "%n", diff --git a/src/intf.h b/src/intf.h index 4541bc4..46f86dc 100644 --- a/src/intf.h +++ b/src/intf.h @@ -317,14 +317,16 @@ extern int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, %c - Insert the next parameter as a character (type char) %s - Insert the next parameter as a string (type char *) %d - Insert the next parameter as an integer (type int) - %'d - Insert as an int, using the locale's thousands separator + %'d - As above, using the locale's thousands group separator %ld - Insert the next parameter as a long int - %'ld - Insert as a long int, using the locale's thousands separator + %'ld - As above, using the locale's thousands group separator + %f - Insert the next parameter as a floating point number (double) + %.mf - As above, with precision "m" (a positive integer > 0) + %'.mf - As above, using the locale's thousands group separator %N - Insert the next parameter as a double, using the locale's national currency format (extension to printf()) - %!N - Insert the next parameter as a double, using the locale's - national currency format without the actual currency symbol - (extension to printf()) + %!N - As above, using the locale's national currency format without + the actual currency symbol (extension to printf()) Instead of using "%" to convert the next parameter, "%m$" can be used to indicate fixed parameter m (where m is an integer from 1 to 8). For