X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fimgui%2Fimgui_memory_editor.h;h=531bc27326b9d1f9f94e81647a27845ab4518c2b;hb=51076eb87ce3d28b37ffa9606d8692c32c287d75;hp=d1e54f0f4f07040727029de4b3bda71fdc638186;hpb=51047cd2e8a1e834d0345e2eadaeb0da70eb7bfc;p=mesa.git diff --git a/src/imgui/imgui_memory_editor.h b/src/imgui/imgui_memory_editor.h index d1e54f0f4f0..531bc27326b 100644 --- a/src/imgui/imgui_memory_editor.h +++ b/src/imgui/imgui_memory_editor.h @@ -35,6 +35,10 @@ // - 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. @@ -45,10 +49,11 @@ #include // 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