mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-11-04 07:01:04 +01:00 
			
		
		
		
	InputScalar: Fixed manual input when using %03d style width in display format string. (amended once)
This commit is contained in:
		@@ -2007,23 +2007,20 @@ bool ImGui::DataTypeApplyFromText(const char* buf, ImGuiDataType data_type, void
 | 
			
		||||
    ImGuiDataTypeTempStorage data_backup;
 | 
			
		||||
    memcpy(&data_backup, p_data, type_info->Size);
 | 
			
		||||
 | 
			
		||||
    if (format == NULL)
 | 
			
		||||
    // Sanitize format
 | 
			
		||||
    // For float/double we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in, so force them into %f and %lf
 | 
			
		||||
    char format_sanitized[32];
 | 
			
		||||
    if (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double)
 | 
			
		||||
        format = type_info->ScanFmt;
 | 
			
		||||
 | 
			
		||||
    if (data_type == ImGuiDataType_S32 || data_type == ImGuiDataType_U32 || data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64 || data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double)
 | 
			
		||||
    {
 | 
			
		||||
        // For float/double we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in, so force them into %f and %lf
 | 
			
		||||
        if (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double)
 | 
			
		||||
            format = type_info->ScanFmt;
 | 
			
		||||
        if (sscanf(buf, format, p_data) < 1)
 | 
			
		||||
            return false;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
        format = ImParseFormatSanitizeForScanning(format, format_sanitized, IM_ARRAYSIZE(format_sanitized));
 | 
			
		||||
 | 
			
		||||
    // Small types need a 32-bit buffer to receive the result from scanf()
 | 
			
		||||
    int v32 = 0;
 | 
			
		||||
    if (sscanf(buf, format, type_info->Size >= 4 ? p_data : &v32) < 1)
 | 
			
		||||
        return false;
 | 
			
		||||
    if (type_info->Size < 4)
 | 
			
		||||
    {
 | 
			
		||||
        // Small types need a 32-bit buffer to receive the result from scanf()
 | 
			
		||||
        int v32;
 | 
			
		||||
        if (sscanf(buf, format, &v32) < 1)
 | 
			
		||||
            return false;
 | 
			
		||||
        if (data_type == ImGuiDataType_S8)
 | 
			
		||||
            *(ImS8*)p_data = (ImS8)ImClamp(v32, (int)IM_S8_MIN, (int)IM_S8_MAX);
 | 
			
		||||
        else if (data_type == ImGuiDataType_U8)
 | 
			
		||||
@@ -2104,26 +2101,10 @@ static float GetMinimumStepAtDecimalPrecision(int decimal_precision)
 | 
			
		||||
    return (decimal_precision < IM_ARRAYSIZE(min_steps)) ? min_steps[decimal_precision] : ImPow(10.0f, (float)-decimal_precision);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Sanitize format
 | 
			
		||||
// - Zero terminate so extra characters after format (e.g. "%f123") don't confuse atof/atoi
 | 
			
		||||
// - stb_sprintf.h supports several new modifiers which format numbers in a way that also makes them incompatible atof/atoi.
 | 
			
		||||
static void SanitizeFormatString(const char* fmt, char* fmt_out, size_t fmt_out_size)
 | 
			
		||||
{
 | 
			
		||||
    IM_UNUSED(fmt_out_size);
 | 
			
		||||
    const char* fmt_end = ImParseFormatFindEnd(fmt);
 | 
			
		||||
    IM_ASSERT((size_t)(fmt_end - fmt + 1) < fmt_out_size); // Format is too long, let us know if this happens to you!
 | 
			
		||||
    while (fmt < fmt_end)
 | 
			
		||||
    {
 | 
			
		||||
        char c = *(fmt++);
 | 
			
		||||
        if (c != '\'' && c != '$' && c != '_') // Custom flags provided by stb_sprintf.h. POSIX 2008 also supports '.
 | 
			
		||||
            *(fmt_out++) = c;
 | 
			
		||||
    }
 | 
			
		||||
    *fmt_out = 0; // Zero-terminate
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename TYPE>
 | 
			
		||||
TYPE ImGui::RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, TYPE v)
 | 
			
		||||
{
 | 
			
		||||
    IM_UNUSED(data_type);
 | 
			
		||||
    IM_ASSERT(data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double);
 | 
			
		||||
    const char* fmt_start = ImParseFormatFindStart(format);
 | 
			
		||||
    if (fmt_start[0] != '%' || fmt_start[1] == '%') // Don't apply if the value is not visible in the format string
 | 
			
		||||
@@ -2131,7 +2112,7 @@ TYPE ImGui::RoundScalarWithFormatT(const char* format, ImGuiDataType data_type,
 | 
			
		||||
 | 
			
		||||
    // Sanitize format
 | 
			
		||||
    char fmt_sanitized[32];
 | 
			
		||||
    SanitizeFormatString(fmt_start, fmt_sanitized, IM_ARRAYSIZE(fmt_sanitized));
 | 
			
		||||
    ImParseFormatSanitizeForPrinting(fmt_start, fmt_sanitized, IM_ARRAYSIZE(fmt_sanitized));
 | 
			
		||||
    fmt_start = fmt_sanitized;
 | 
			
		||||
 | 
			
		||||
    // Format value with our rounding, and read back
 | 
			
		||||
@@ -3205,6 +3186,8 @@ bool ImGui::SliderScalarN(const char* label, ImGuiDataType data_type, void* v, i
 | 
			
		||||
// - ImParseFormatFindStart() [Internal]
 | 
			
		||||
// - ImParseFormatFindEnd() [Internal]
 | 
			
		||||
// - ImParseFormatTrimDecorations() [Internal]
 | 
			
		||||
// - ImParseFormatSanitizeForPrinting() [Internal]
 | 
			
		||||
// - ImParseFormatSanitizeForScanning() [Internal]
 | 
			
		||||
// - ImParseFormatPrecision() [Internal]
 | 
			
		||||
// - TempInputTextScalar() [Internal]
 | 
			
		||||
// - InputScalar()
 | 
			
		||||
@@ -3268,6 +3251,44 @@ const char* ImParseFormatTrimDecorations(const char* fmt, char* buf, size_t buf_
 | 
			
		||||
    return buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Sanitize format
 | 
			
		||||
// - Zero terminate so extra characters after format (e.g. "%f123") don't confuse atof/atoi
 | 
			
		||||
// - stb_sprintf.h supports several new modifiers which format numbers in a way that also makes them incompatible atof/atoi.
 | 
			
		||||
void ImParseFormatSanitizeForPrinting(const char* fmt_in, char* fmt_out, size_t fmt_out_size)
 | 
			
		||||
{
 | 
			
		||||
    const char* fmt_end = ImParseFormatFindEnd(fmt_in);
 | 
			
		||||
    IM_UNUSED(fmt_out_size);
 | 
			
		||||
    IM_ASSERT((size_t)(fmt_end - fmt_in + 1) < fmt_out_size); // Format is too long, let us know if this happens to you!
 | 
			
		||||
    while (fmt_in < fmt_end)
 | 
			
		||||
    {
 | 
			
		||||
        char c = *fmt_in++;
 | 
			
		||||
        if (c != '\'' && c != '$' && c != '_') // Custom flags provided by stb_sprintf.h. POSIX 2008 also supports '.
 | 
			
		||||
            *(fmt_out++) = c;
 | 
			
		||||
    }
 | 
			
		||||
    *fmt_out = 0; // Zero-terminate
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// - For scanning we need to remove all width and precision fields "%3.7f" -> "%f". BUT don't strip types like "%I64d" which includes digits. ! "%07I64d" -> "%I64d"
 | 
			
		||||
const char* ImParseFormatSanitizeForScanning(const char* fmt_in, char* fmt_out, size_t fmt_out_size)
 | 
			
		||||
{
 | 
			
		||||
    const char* fmt_end = ImParseFormatFindEnd(fmt_in);
 | 
			
		||||
    const char* fmt_out_begin = fmt_out;
 | 
			
		||||
    IM_UNUSED(fmt_out_size);
 | 
			
		||||
    IM_ASSERT((size_t)(fmt_end - fmt_in + 1) < fmt_out_size); // Format is too long, let us know if this happens to you!
 | 
			
		||||
    bool has_type = false;
 | 
			
		||||
    while (fmt_in < fmt_end)
 | 
			
		||||
    {
 | 
			
		||||
        char c = *fmt_in++;
 | 
			
		||||
        if (!has_type && ((c >= '0' && c <= '9') || c == '.'))
 | 
			
		||||
            continue;
 | 
			
		||||
        has_type |= ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); // Stop skipping digits
 | 
			
		||||
        if (c != '\'' && c != '$' && c != '_') // Custom flags provided by stb_sprintf.h. POSIX 2008 also supports '.
 | 
			
		||||
            *(fmt_out++) = c;
 | 
			
		||||
    }
 | 
			
		||||
    *fmt_out = 0; // Zero-terminate
 | 
			
		||||
    return fmt_out_begin;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename TYPE>
 | 
			
		||||
static const char* ImAtoi(const char* src, TYPE* output)
 | 
			
		||||
{
 | 
			
		||||
@@ -3337,9 +3358,11 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
 | 
			
		||||
    format = ImParseFormatTrimDecorations(format, fmt_buf, IM_ARRAYSIZE(fmt_buf));
 | 
			
		||||
    DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, p_data, format);
 | 
			
		||||
    ImStrTrimBlanks(data_buf);
 | 
			
		||||
    const bool is_floating_point = (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double);
 | 
			
		||||
    const bool is_hexadecimal = !is_floating_point && format[0] && toupper(format[strlen(format) - 1]) == 'X';
 | 
			
		||||
 | 
			
		||||
    ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_NoMarkEdited;
 | 
			
		||||
    flags |= ((data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) ? ImGuiInputTextFlags_CharsScientific : ImGuiInputTextFlags_CharsDecimal);
 | 
			
		||||
    flags |= is_floating_point ? ImGuiInputTextFlags_CharsScientific : is_hexadecimal ? ImGuiInputTextFlags_CharsHexadecimal : ImGuiInputTextFlags_CharsDecimal;
 | 
			
		||||
    bool value_changed = false;
 | 
			
		||||
    if (TempInputText(bb, id, label, data_buf, IM_ARRAYSIZE(data_buf), flags))
 | 
			
		||||
    {
 | 
			
		||||
@@ -3349,7 +3372,7 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
 | 
			
		||||
        memcpy(&data_backup, p_data, data_type_size);
 | 
			
		||||
 | 
			
		||||
        // Apply new value (or operations) then clamp
 | 
			
		||||
        DataTypeApplyFromText(data_buf, data_type, p_data, NULL);
 | 
			
		||||
        DataTypeApplyFromText(data_buf, data_type, p_data, format);
 | 
			
		||||
        if (p_clamp_min || p_clamp_max)
 | 
			
		||||
        {
 | 
			
		||||
            if (p_clamp_min && p_clamp_max && DataTypeCompare(data_type, p_clamp_min, p_clamp_max) > 0)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user