imgui: update memory editor
authorLionel Landwerlin <lionel.g.landwerlin@intel.com>
Mon, 25 Feb 2019 10:58:40 +0000 (10:58 +0000)
committerLionel Landwerlin <lionel.g.landwerlin@intel.com>
Tue, 26 Feb 2019 12:49:07 +0000 (12:49 +0000)
Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Acked-by: Tapani Pälli <tapani.palli@intel.com>
src/imgui/README
src/imgui/imgui_memory_editor.h

index 6e14927a66b61d86327887522e10762fe561bb9d..01419237553cff5930a83e5c641dad47515da079 100644 (file)
@@ -1,7 +1,8 @@
 Dear ImGui
 ==========
 
 Dear ImGui
 ==========
 
-This directory contains a copy of the Dear ImGui library at the following commit :
+This directory contains a copy of the Dear ImGui library
+(https://github.com/ocornut/imgui) at the following commit :
 
 commit f977871854af941289f2a9090dcc90f7aa3449a8
 Author: omar <omarcornut@gmail.com>
 
 commit f977871854af941289f2a9090dcc90f7aa3449a8
 Author: omar <omarcornut@gmail.com>
@@ -10,6 +11,15 @@ Date:   Fri Feb 15 13:10:22 2019 +0100
     ImFont: Minor adjustment to the structure.
     Examples: Removed unused variable.
 
     ImFont: Minor adjustment to the structure.
     Examples: Removed unused variable.
 
+There is also a copy of the memory editor
+(https://github.com/ocornut/imgui_club) at the following commit :
+
+commit 378e32ac92aa120512ee1aeb90522c9214e9b694
+Author: omar <omarcornut@gmail.com>
+Date:   Wed Oct 10 15:20:32 2018 +0200
+
+    Comments (#9)
+
 Embedding the library into one's project is main way people seems to
 work with ImGui. Since this is just for a debugging tool, we're not
 exposing ourselves too much.
 Embedding the library into one's project is main way people seems to
 work with ImGui. Since this is just for a debugging tool, we're not
 exposing ourselves too much.
index d1e54f0f4f07040727029de4b3bda71fdc638186..5ee6145288c2c7f50d9aac9fb17572906aa81f9f 100644 (file)
@@ -35,6 +35,9 @@
 // - 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.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.
 //
 // 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.
 //
 // 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
 #include <stdint.h>     // uint8_t, etc.
 
 #ifdef _MSC_VER
-#define _PRISizeT   "IX"
+#define _PRISizeT   "I"
 #define snprintf    _snprintf
 #else
 #define snprintf    _snprintf
 #else
-#define _PRISizeT   "zX"
+#define _PRISizeT   "z"
 #endif
 
 struct MemoryEditor
 #endif
 
 struct MemoryEditor
@@ -79,21 +82,23 @@ struct MemoryEditor
     };
 
     // Settings
     };
 
     // 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;
     bool            ContentsWidthChanged;
     size_t          DataPreviewAddr;
     size_t          DataEditingAddr;
@@ -111,10 +116,12 @@ struct MemoryEditor
         Open = true;
         ReadOnly = false;
         Cols = 16;
         Open = true;
         ReadOnly = false;
         Cols = 16;
+        OptShowOptions = true;
         OptShowDataPreview = false;
         OptShowHexII = false;
         OptShowAscii = true;
         OptGreyOutZeroes = true;
         OptShowDataPreview = false;
         OptShowHexII = false;
         OptShowAscii = true;
         OptGreyOutZeroes = true;
+        OptUpperCaseHex = true;
         OptMidColsCount = 8;
         OptAddrDigitsCount = 0;
         HighlightColor = IM_COL32(255, 255, 255, 50);
         OptMidColsCount = 8;
         OptAddrDigitsCount = 0;
         HighlightColor = IM_COL32(255, 255, 255, 50);
@@ -180,7 +187,7 @@ struct MemoryEditor
     }
 
     // Standalone Memory Editor window
     }
 
     // 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);
     {
         Sizes s;
         CalcSizes(s, mem_size, base_display_addr);
@@ -202,8 +209,9 @@ struct MemoryEditor
     }
 
     // Memory Editor contents only
     }
 
     // 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();
         Sizes s;
         CalcSizes(s, mem_size, base_display_addr);
         ImGuiStyle& style = ImGui::GetStyle();
@@ -211,7 +219,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;
         // 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);
         if (OptShowDataPreview)
             footer_height += height_separator + ImGui::GetFrameHeightWithSpacing() * 1 + ImGui::GetTextLineHeightWithSpacing() * 3;
         ImGui::BeginChild("##scrolling", ImVec2(0, -footer_height), false, ImGuiWindowFlags_NoMove);
@@ -261,10 +271,16 @@ struct MemoryEditor
         const ImU32 color_text = ImGui::GetColorU32(ImGuiCol_Text);
         const ImU32 color_disabled = OptGreyOutZeroes ? ImGui::GetColorU32(ImGuiCol_TextDisabled) : color_text;
 
         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);
         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++)
 
             // Draw Hexadecimal
             for (int n = 0; n < Cols && addr < mem_size; n++, addr++)
@@ -301,14 +317,14 @@ struct MemoryEditor
                     {
                         ImGui::SetKeyboardFocusHere();
                         ImGui::CaptureKeyboardFromApp(true);
                     {
                         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.
                     }
                     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())
                         {
                             UserData* user_data = (UserData*)data->UserData;
                             if (!data->HasSelection())
@@ -328,7 +344,7 @@ struct MemoryEditor
                     };
                     UserData user_data;
                     user_data.CursorPos = -1;
                     };
                     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;
                     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;
@@ -364,14 +380,14 @@ struct MemoryEditor
                         else if (b == 0x00)
                             ImGui::Text("   ");
                         else
                         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
                     }
                     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))
                     {
                     }
                     if (!ReadOnly && ImGui::IsItemHovered() && ImGui::IsMouseClicked(0))
                     {
@@ -422,52 +438,56 @@ struct MemoryEditor
             DataEditingAddr = DataPreviewAddr = data_editing_addr_next;
         }
 
             DataEditingAddr = DataPreviewAddr = data_editing_addr_next;
         }
 
-        ImGui::Separator();
-
-        // Options menu
-
         bool next_show_data_preview = OptShowDataPreview;
         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))
+            {
+                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)
             {
             {
-                ImGui::BeginChild("##scrolling");
-                ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + (GotoAddr / Cols) * ImGui::GetTextLineHeight());
-                ImGui::EndChild();
-                DataEditingAddr = DataPreviewAddr = GotoAddr;
-                DataEditingTakeFocus = true;
+                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)
         }
 
         if (OptShowDataPreview)
@@ -599,7 +619,7 @@ struct MemoryEditor
     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];
     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)
         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 +629,7 @@ struct MemoryEditor
 
         if (data_format == DataFormat_Bin)
         {
 
         if (data_format == DataFormat_Bin)
         {
-            snprintf(out_buf, out_buf_size, "%s", FormatBinary(buf, size * 8));
+            snprintf(out_buf, out_buf_size, "%s", FormatBinary(buf, (int)size * 8));
             return;
         }
 
             return;
         }