imgui: bump imgui memory editor copy
[mesa.git] / src / imgui / imgui_memory_editor.h
index d1e54f0f4f07040727029de4b3bda71fdc638186..531bc27326b9d1f9f94e81647a27845ab4518c2b 100644 (file)
 // - v0.25: fixed wording: all occurrences of "Rows" renamed to "Columns".
 // - v0.26: fixed clicking on hex region
 // - v0.30: added data preview for common data types
+// - v0.31: added OptUpperCaseHex option to select lower/upper casing display [@samhocevar]
+// - v0.32: changed signatures to use void* instead of unsigned char*
+// - v0.33: added OptShowOptions option to hide all the interactive option setting.
+// - v0.34: binary preview now applies endianess setting [@nicolasnoble]
 //
 // Todo/Bugs:
 // - Arrows are being sent to the InputText() about to disappear which for LeftArrow makes the text cursor appear at position 1 for one frame.
 #include <stdint.h>     // uint8_t, etc.
 
 #ifdef _MSC_VER
-#define _PRISizeT   "IX"
-#define snprintf    _snprintf
+#define _PRISizeT   "I"
+#define ImSnprintf  _snprintf
 #else
-#define _PRISizeT   "zX"
+#define _PRISizeT   "z"
+#define ImSnprintf  snprintf
 #endif
 
 struct MemoryEditor
@@ -79,21 +84,23 @@ struct MemoryEditor
     };
 
     // Settings
-    bool            Open;                                   // = true   // set to false when DrawWindow() was closed. ignore if not using DrawWindow
-    bool            ReadOnly;                               // = false  // set to true to disable any editing
-    int             Cols;                                   // = 16     //
-    bool            OptShowDataPreview;                     // = false  //
-    bool            OptShowHexII;                           // = false  //
-    bool            OptShowAscii;                           // = true   //
-    bool            OptGreyOutZeroes;                       // = true   //
-    int             OptMidColsCount;                        // = 8      // set to 0 to disable extra spacing between every mid-cols
-    int             OptAddrDigitsCount;                     // = 0      // number of addr digits to display (default calculated based on maximum displayed addr)
-    ImU32           HighlightColor;                         //          // color of highlight
-    u8              (*ReadFn)(const u8* data, size_t off);  // = NULL   // optional handler to read bytes
-    void            (*WriteFn)(u8* data, size_t off, u8 d); // = NULL   // optional handler to write bytes
-    bool            (*HighlightFn)(const u8* data, size_t off);//NULL   // optional handler to return Highlight property (to support non-contiguous highlighting)
-
-    // State/Internals
+    bool            Open;                                   // = true   // set to false when DrawWindow() was closed. ignore if not using DrawWindow().
+    bool            ReadOnly;                               // = false  // disable any editing.
+    int             Cols;                                   // = 16     // number of columns to display.
+    bool            OptShowOptions;                         // = true   // display options button/context menu. when disabled, options will be locked unless you provide your own UI for them.
+    bool            OptShowDataPreview;                     // = false  // display a footer previewing the decimal/binary/hex/float representation of the currently selected bytes.
+    bool            OptShowHexII;                           // = false  // display values in HexII representation instead of regular hexadecimal: hide null/zero bytes, ascii values as ".X".
+    bool            OptShowAscii;                           // = true   // display ASCII representation on the right side.
+    bool            OptGreyOutZeroes;                       // = true   // display null/zero bytes using the TextDisabled color.
+    bool            OptUpperCaseHex;                        // = true   // display hexadecimal values as "FF" instead of "ff".
+    int             OptMidColsCount;                        // = 8      // set to 0 to disable extra spacing between every mid-cols.
+    int             OptAddrDigitsCount;                     // = 0      // number of addr digits to display (default calculated based on maximum displayed addr).
+    ImU32           HighlightColor;                         //          // background color of highlighted bytes.
+    u8              (*ReadFn)(const u8* data, size_t off);  // = NULL   // optional handler to read bytes.
+    void            (*WriteFn)(u8* data, size_t off, u8 d); // = NULL   // optional handler to write bytes.
+    bool            (*HighlightFn)(const u8* data, size_t off);//NULL   // optional handler to return Highlight property (to support non-contiguous highlighting).
+
+    // [Internal State]
     bool            ContentsWidthChanged;
     size_t          DataPreviewAddr;
     size_t          DataEditingAddr;
@@ -111,10 +118,12 @@ struct MemoryEditor
         Open = true;
         ReadOnly = false;
         Cols = 16;
+        OptShowOptions = true;
         OptShowDataPreview = false;
         OptShowHexII = false;
         OptShowAscii = true;
         OptGreyOutZeroes = true;
+        OptUpperCaseHex = true;
         OptMidColsCount = 8;
         OptAddrDigitsCount = 0;
         HighlightColor = IM_COL32(255, 255, 255, 50);
@@ -173,14 +182,14 @@ struct MemoryEditor
         {
             s.PosAsciiStart = s.PosHexEnd + s.GlyphWidth * 1;
             if (OptMidColsCount > 0)
-                s.PosAsciiStart += ((Cols + OptMidColsCount - 1) / OptMidColsCount) * s.SpacingBetweenMidCols;
+                s.PosAsciiStart += (float)((Cols + OptMidColsCount - 1) / OptMidColsCount) * s.SpacingBetweenMidCols;
             s.PosAsciiEnd = s.PosAsciiStart + Cols * s.GlyphWidth;
         }
         s.WindowWidth = s.PosAsciiEnd + style.ScrollbarSize + style.WindowPadding.x * 2 + s.GlyphWidth;
     }
 
     // Standalone Memory Editor window
-    void DrawWindow(const char* title, u8* mem_data, size_t mem_size, size_t base_display_addr = 0x0000)
+    void DrawWindow(const char* title, void* mem_data, size_t mem_size, size_t base_display_addr = 0x0000)
     {
         Sizes s;
         CalcSizes(s, mem_size, base_display_addr);
@@ -202,8 +211,9 @@ struct MemoryEditor
     }
 
     // Memory Editor contents only
-    void DrawContents(u8* mem_data, size_t mem_size, size_t base_display_addr = 0x0000)
+    void DrawContents(void* mem_data_void_ptr, size_t mem_size, size_t base_display_addr = 0x0000)
     {
+        u8* mem_data = (u8*)mem_data_void_ptr;
         Sizes s;
         CalcSizes(s, mem_size, base_display_addr);
         ImGuiStyle& style = ImGui::GetStyle();
@@ -211,7 +221,9 @@ struct MemoryEditor
         // We begin into our scrolling region with the 'ImGuiWindowFlags_NoMove' in order to prevent click from moving the window.
         // This is used as a facility since our main click detection code doesn't assign an ActiveId so the click would normally be caught as a window-move.
         const float height_separator = style.ItemSpacing.y;
-        float footer_height = height_separator + ImGui::GetFrameHeightWithSpacing() * 1;
+        float footer_height = 0;
+        if (OptShowOptions)
+            footer_height += height_separator + ImGui::GetFrameHeightWithSpacing() * 1;
         if (OptShowDataPreview)
             footer_height += height_separator + ImGui::GetFrameHeightWithSpacing() * 1 + ImGui::GetTextLineHeightWithSpacing() * 3;
         ImGui::BeginChild("##scrolling", ImVec2(0, -footer_height), false, ImGuiWindowFlags_NoMove);
@@ -261,17 +273,23 @@ struct MemoryEditor
         const ImU32 color_text = ImGui::GetColorU32(ImGuiCol_Text);
         const ImU32 color_disabled = OptGreyOutZeroes ? ImGui::GetColorU32(ImGuiCol_TextDisabled) : color_text;
 
+        const char* format_address = OptUpperCaseHex ? "%0*" _PRISizeT "X: " : "%0*" _PRISizeT "x: ";
+        const char* format_data = OptUpperCaseHex ? "%0*" _PRISizeT "X" : "%0*" _PRISizeT "x";
+        const char* format_range = OptUpperCaseHex ? "Range %0*" _PRISizeT "X..%0*" _PRISizeT "X" : "Range %0*" _PRISizeT "x..%0*" _PRISizeT "x";
+        const char* format_byte = OptUpperCaseHex ? "%02X" : "%02x";
+        const char* format_byte_space = OptUpperCaseHex ? "%02X " : "%02x ";
+
         for (int line_i = clipper.DisplayStart; line_i < clipper.DisplayEnd; line_i++) // display only visible lines
         {
             size_t addr = (size_t)(line_i * Cols);
-            ImGui::Text("%0*" _PRISizeT ": ", s.AddrDigitsCount, base_display_addr + addr);
+            ImGui::Text(format_address, s.AddrDigitsCount, base_display_addr + addr);
 
             // Draw Hexadecimal
             for (int n = 0; n < Cols && addr < mem_size; n++, addr++)
             {
                 float byte_pos_x = s.PosHexStart + s.HexCellWidth * n;
                 if (OptMidColsCount > 0)
-                    byte_pos_x += (n / OptMidColsCount) * s.SpacingBetweenMidCols;
+                    byte_pos_x += (float)(n / OptMidColsCount) * s.SpacingBetweenMidCols;
                 ImGui::SameLine(byte_pos_x);
 
                 // Draw highlight
@@ -301,14 +319,14 @@ struct MemoryEditor
                     {
                         ImGui::SetKeyboardFocusHere();
                         ImGui::CaptureKeyboardFromApp(true);
-                        sprintf(AddrInputBuf, "%0*" _PRISizeT, s.AddrDigitsCount, base_display_addr + addr);
-                        sprintf(DataInputBuf, "%02X", ReadFn ? ReadFn(mem_data, addr) : mem_data[addr]);
+                        sprintf(AddrInputBuf, format_data, s.AddrDigitsCount, base_display_addr + addr);
+                        sprintf(DataInputBuf, format_byte, ReadFn ? ReadFn(mem_data, addr) : mem_data[addr]);
                     }
                     ImGui::PushItemWidth(s.GlyphWidth * 2);
                     struct UserData
                     {
                         // FIXME: We should have a way to retrieve the text edit cursor position more easily in the API, this is rather tedious. This is such a ugly mess we may be better off not using InputText() at all here.
-                        static int Callback(ImGuiTextEditCallbackData* data)
+                        static int Callback(ImGuiInputTextCallbackData* data)
                         {
                             UserData* user_data = (UserData*)data->UserData;
                             if (!data->HasSelection())
@@ -328,7 +346,7 @@ struct MemoryEditor
                     };
                     UserData user_data;
                     user_data.CursorPos = -1;
-                    sprintf(user_data.CurrentBufOverwrite, "%02X", ReadFn ? ReadFn(mem_data, addr) : mem_data[addr]);
+                    sprintf(user_data.CurrentBufOverwrite, format_byte, ReadFn ? ReadFn(mem_data, addr) : mem_data[addr]);
                     ImGuiInputTextFlags flags = ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_NoHorizontalScroll | ImGuiInputTextFlags_AlwaysInsertMode | ImGuiInputTextFlags_CallbackAlways;
                     if (ImGui::InputText("##data", DataInputBuf, 32, flags, UserData::Callback, &user_data))
                         data_write = data_next = true;
@@ -340,7 +358,7 @@ struct MemoryEditor
                         data_write = data_next = true;
                     if (data_editing_addr_next != (size_t)-1)
                         data_write = data_next = false;
-                    int data_input_value;
+                    unsigned int data_input_value = 0;
                     if (data_write && sscanf(DataInputBuf, "%X", &data_input_value) == 1)
                     {
                         if (WriteFn)
@@ -364,14 +382,14 @@ struct MemoryEditor
                         else if (b == 0x00)
                             ImGui::Text("   ");
                         else
-                            ImGui::Text("%02X ", b);
+                            ImGui::Text(format_byte_space, b);
                     }
                     else
                     {
                         if (b == 0 && OptGreyOutZeroes)
                             ImGui::TextDisabled("00 ");
                         else
-                            ImGui::Text("%02X ", b);
+                            ImGui::Text(format_byte_space, b);
                     }
                     if (!ReadOnly && ImGui::IsItemHovered() && ImGui::IsMouseClicked(0))
                     {
@@ -422,52 +440,56 @@ struct MemoryEditor
             DataEditingAddr = DataPreviewAddr = data_editing_addr_next;
         }
 
-        ImGui::Separator();
-
-        // Options menu
-
         bool next_show_data_preview = OptShowDataPreview;
-        if (ImGui::Button("Options"))
-            ImGui::OpenPopup("context");
-        if (ImGui::BeginPopup("context"))
+        if (OptShowOptions)
         {
-            ImGui::PushItemWidth(56);
-            if (ImGui::DragInt("##cols", &Cols, 0.2f, 4, 32, "%d cols")) { ContentsWidthChanged = true; }
-            ImGui::PopItemWidth();
-            ImGui::Checkbox("Show Data Preview", &next_show_data_preview);
-            ImGui::Checkbox("Show HexII", &OptShowHexII);
-            if (ImGui::Checkbox("Show Ascii", &OptShowAscii)) { ContentsWidthChanged = true; }
-            ImGui::Checkbox("Grey out zeroes", &OptGreyOutZeroes);
+            ImGui::Separator();
 
-            ImGui::EndPopup();
-        }
+            // Options menu
 
-        ImGui::SameLine();
-        ImGui::Text("Range %0*" _PRISizeT "..%0*" _PRISizeT, s.AddrDigitsCount, base_display_addr, s.AddrDigitsCount, base_display_addr + mem_size - 1);
-        ImGui::SameLine();
-        ImGui::PushItemWidth((s.AddrDigitsCount + 1) * s.GlyphWidth + style.FramePadding.x * 2.0f);
-        if (ImGui::InputText("##addr", AddrInputBuf, 32, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_EnterReturnsTrue))
-        {
-            size_t goto_addr;
-            if (sscanf(AddrInputBuf, "%" _PRISizeT, &goto_addr) == 1)
+            if (ImGui::Button("Options"))
+                ImGui::OpenPopup("context");
+            if (ImGui::BeginPopup("context"))
             {
-                GotoAddr = goto_addr - base_display_addr;
-                HighlightMin = HighlightMax = (size_t)-1;
+                ImGui::PushItemWidth(56);
+                if (ImGui::DragInt("##cols", &Cols, 0.2f, 4, 32, "%d cols")) { ContentsWidthChanged = true; }
+                ImGui::PopItemWidth();
+                ImGui::Checkbox("Show Data Preview", &next_show_data_preview);
+                ImGui::Checkbox("Show HexII", &OptShowHexII);
+                if (ImGui::Checkbox("Show Ascii", &OptShowAscii)) { ContentsWidthChanged = true; }
+                ImGui::Checkbox("Grey out zeroes", &OptGreyOutZeroes);
+                ImGui::Checkbox("Uppercase Hex", &OptUpperCaseHex);
+
+                ImGui::EndPopup();
             }
-        }
-        ImGui::PopItemWidth();
 
-        if (GotoAddr != (size_t)-1)
-        {
-            if (GotoAddr < mem_size)
+            ImGui::SameLine();
+            ImGui::Text(format_range, s.AddrDigitsCount, base_display_addr, s.AddrDigitsCount, base_display_addr + mem_size - 1);
+            ImGui::SameLine();
+            ImGui::PushItemWidth((s.AddrDigitsCount + 1) * s.GlyphWidth + style.FramePadding.x * 2.0f);
+            if (ImGui::InputText("##addr", AddrInputBuf, 32, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_EnterReturnsTrue))
             {
-                ImGui::BeginChild("##scrolling");
-                ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + (GotoAddr / Cols) * ImGui::GetTextLineHeight());
-                ImGui::EndChild();
-                DataEditingAddr = DataPreviewAddr = GotoAddr;
-                DataEditingTakeFocus = true;
+                size_t goto_addr;
+                if (sscanf(AddrInputBuf, "%" _PRISizeT "X", &goto_addr) == 1)
+                {
+                    GotoAddr = goto_addr - base_display_addr;
+                    HighlightMin = HighlightMax = (size_t)-1;
+                }
+            }
+            ImGui::PopItemWidth();
+
+            if (GotoAddr != (size_t)-1)
+            {
+                if (GotoAddr < mem_size)
+                {
+                    ImGui::BeginChild("##scrolling");
+                    ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + (GotoAddr / Cols) * ImGui::GetTextLineHeight());
+                    ImGui::EndChild();
+                    DataEditingAddr = DataPreviewAddr = GotoAddr;
+                    DataEditingTakeFocus = true;
+                }
+                GotoAddr = (size_t)-1;
             }
-            GotoAddr = (size_t)-1;
         }
 
         if (OptShowDataPreview)
@@ -585,21 +607,22 @@ struct MemoryEditor
         IM_ASSERT(width <= 64);
         size_t out_n = 0;
         static char out_buf[64 + 8 + 1];
-        for (int j = 0, n = width / 8; j < n; ++j)
+        int n = width / 8;
+        for (int j = n - 1; j >= 0; --j)
         {
             for (int i = 0; i < 8; ++i)
                 out_buf[out_n++] = (buf[j] & (1 << (7 - i))) ? '1' : '0';
             out_buf[out_n++] = ' ';
         }
-        out_buf[out_n] = 0;
         IM_ASSERT(out_n < IM_ARRAYSIZE(out_buf));
+        out_buf[out_n] = 0;
         return out_buf;
     }
 
     void DisplayPreviewData(size_t addr, const u8* mem_data, size_t mem_size, DataType data_type, DataFormat data_format, char* out_buf, size_t out_buf_size) const
     {
         uint8_t buf[8];
-        int elem_size = DataTypeGetSize(data_type);
+        size_t elem_size = DataTypeGetSize(data_type);
         size_t size = addr + elem_size > mem_size ? mem_size - addr : elem_size;
         if (ReadFn)
             for (int i = 0, n = (int)size; i < n; ++i)
@@ -609,7 +632,9 @@ struct MemoryEditor
 
         if (data_format == DataFormat_Bin)
         {
-            snprintf(out_buf, out_buf_size, "%s", FormatBinary(buf, size * 8));
+            uint8_t binbuf[8];
+            EndianessCopy(binbuf, buf, size);
+            ImSnprintf(out_buf, out_buf_size, "%s", FormatBinary(binbuf, (int)size * 8));
             return;
         }
 
@@ -620,85 +645,88 @@ struct MemoryEditor
         {
             int8_t int8 = 0;
             EndianessCopy(&int8, buf, size);
-            if (data_format == DataFormat_Dec) { snprintf(out_buf, out_buf_size, "%hhd", int8); return; }
-            if (data_format == DataFormat_Hex) { snprintf(out_buf, out_buf_size, "0x%02x", int8 & 0xFF); return; }
+            if (data_format == DataFormat_Dec) { ImSnprintf(out_buf, out_buf_size, "%hhd", int8); return; }
+            if (data_format == DataFormat_Hex) { ImSnprintf(out_buf, out_buf_size, "0x%02x", int8 & 0xFF); return; }
             break;
         }
         case DataType_U8:
         {
             uint8_t uint8 = 0;
             EndianessCopy(&uint8, buf, size);
-            if (data_format == DataFormat_Dec) { snprintf(out_buf, out_buf_size, "%hhu", uint8); return; }
-            if (data_format == DataFormat_Hex) { snprintf(out_buf, out_buf_size, "0x%02x", uint8 & 0XFF); return; }
+            if (data_format == DataFormat_Dec) { ImSnprintf(out_buf, out_buf_size, "%hhu", uint8); return; }
+            if (data_format == DataFormat_Hex) { ImSnprintf(out_buf, out_buf_size, "0x%02x", uint8 & 0XFF); return; }
             break;
         }
         case DataType_S16:
         {
             int16_t int16 = 0;
             EndianessCopy(&int16, buf, size);
-            if (data_format == DataFormat_Dec) { snprintf(out_buf, out_buf_size, "%hd", int16); return; }
-            if (data_format == DataFormat_Hex) { snprintf(out_buf, out_buf_size, "0x%04x", int16 & 0xFFFF); return; }
+            if (data_format == DataFormat_Dec) { ImSnprintf(out_buf, out_buf_size, "%hd", int16); return; }
+            if (data_format == DataFormat_Hex) { ImSnprintf(out_buf, out_buf_size, "0x%04x", int16 & 0xFFFF); return; }
             break;
         }
         case DataType_U16:
         {
             uint16_t uint16 = 0;
             EndianessCopy(&uint16, buf, size);
-            if (data_format == DataFormat_Dec) { snprintf(out_buf, out_buf_size, "%hu", uint16); return; }
-            if (data_format == DataFormat_Hex) { snprintf(out_buf, out_buf_size, "0x%04x", uint16 & 0xFFFF); return; }
+            if (data_format == DataFormat_Dec) { ImSnprintf(out_buf, out_buf_size, "%hu", uint16); return; }
+            if (data_format == DataFormat_Hex) { ImSnprintf(out_buf, out_buf_size, "0x%04x", uint16 & 0xFFFF); return; }
             break;
         }
         case DataType_S32:
         {
             int32_t int32 = 0;
             EndianessCopy(&int32, buf, size);
-            if (data_format == DataFormat_Dec) { snprintf(out_buf, out_buf_size, "%d", int32); return; }
-            if (data_format == DataFormat_Hex) { snprintf(out_buf, out_buf_size, "0x%08x", int32); return; }
+            if (data_format == DataFormat_Dec) { ImSnprintf(out_buf, out_buf_size, "%d", int32); return; }
+            if (data_format == DataFormat_Hex) { ImSnprintf(out_buf, out_buf_size, "0x%08x", int32); return; }
             break;
         }
         case DataType_U32:
         {
             uint32_t uint32 = 0;
             EndianessCopy(&uint32, buf, size);
-            if (data_format == DataFormat_Dec) { snprintf(out_buf, out_buf_size, "%u", uint32); return; }
-            if (data_format == DataFormat_Hex) { snprintf(out_buf, out_buf_size, "0x%08x", uint32); return; }
+            if (data_format == DataFormat_Dec) { ImSnprintf(out_buf, out_buf_size, "%u", uint32); return; }
+            if (data_format == DataFormat_Hex) { ImSnprintf(out_buf, out_buf_size, "0x%08x", uint32); return; }
             break;
         }
         case DataType_S64:
         {
             int64_t int64 = 0;
             EndianessCopy(&int64, buf, size);
-            if (data_format == DataFormat_Dec) { snprintf(out_buf, out_buf_size, "%lld", (long long)int64); return; }
-            if (data_format == DataFormat_Hex) { snprintf(out_buf, out_buf_size, "0x%016llx", (long long)int64); return; }
+            if (data_format == DataFormat_Dec) { ImSnprintf(out_buf, out_buf_size, "%lld", (long long)int64); return; }
+            if (data_format == DataFormat_Hex) { ImSnprintf(out_buf, out_buf_size, "0x%016llx", (long long)int64); return; }
             break;
         }
         case DataType_U64:
         {
             uint64_t uint64 = 0;
             EndianessCopy(&uint64, buf, size);
-            if (data_format == DataFormat_Dec) { snprintf(out_buf, out_buf_size, "%llu", (long long)uint64); return; }
-            if (data_format == DataFormat_Hex) { snprintf(out_buf, out_buf_size, "0x%016llx", (long long)uint64); return; }
+            if (data_format == DataFormat_Dec) { ImSnprintf(out_buf, out_buf_size, "%llu", (long long)uint64); return; }
+            if (data_format == DataFormat_Hex) { ImSnprintf(out_buf, out_buf_size, "0x%016llx", (long long)uint64); return; }
             break;
         }
         case DataType_Float:
         {
             float float32 = 0.0f;
             EndianessCopy(&float32, buf, size);
-            if (data_format == DataFormat_Dec) { snprintf(out_buf, out_buf_size, "%f", float32); return; }
-            if (data_format == DataFormat_Hex) { snprintf(out_buf, out_buf_size, "%a", float32); return; }
+            if (data_format == DataFormat_Dec) { ImSnprintf(out_buf, out_buf_size, "%f", float32); return; }
+            if (data_format == DataFormat_Hex) { ImSnprintf(out_buf, out_buf_size, "%a", float32); return; }
             break;
         }
         case DataType_Double:
         {
             double float64 = 0.0;
             EndianessCopy(&float64, buf, size);
-            if (data_format == DataFormat_Dec) { snprintf(out_buf, out_buf_size, "%f", float64); return; }
-            if (data_format == DataFormat_Hex) { snprintf(out_buf, out_buf_size, "%a", float64); return; }
+            if (data_format == DataFormat_Dec) { ImSnprintf(out_buf, out_buf_size, "%f", float64); return; }
+            if (data_format == DataFormat_Hex) { ImSnprintf(out_buf, out_buf_size, "%a", float64); return; }
             break;
         }
+        case DataType_COUNT:
+            break;
         } // Switch
         IM_ASSERT(0); // Shouldn't reach
     }
 };
 
 #undef _PRISizeT
+#undef ImSnprintf