diff --git a/imconfig.h b/imconfig.h index 0f5357cd..ca552212 100644 --- a/imconfig.h +++ b/imconfig.h @@ -4,6 +4,18 @@ #pragma once +//---- Define your own malloc/free/realloc functions if you want to override internal memory allocations for ImGui +/* + #define IM_MALLOC(_SIZE) MyMalloc(_SIZE) + #define IM_FREE(_PTR) MyFree(_PTR) + #define IM_REALLOC(_PTR, _SIZE) MyRealloc(_PTR, _SIZE) + + #include // size_t + void* MyMalloc(size_t size); + void MyFree(void *ptr); + void* MyRealloc(void *ptr, size_t size); +*/ + //---- Define your own ImVector<> type if you don't want to use the provided implementation defined in imgui.h //#include //#define ImVector std::vector @@ -35,3 +47,4 @@ namespace ImGui void Value(const char* prefix, const MyVec4& v, const char* float_format = NULL); }; */ + diff --git a/imgui.cpp b/imgui.cpp index cc9528a7..683df5ce 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -188,11 +188,13 @@ #include // intptr_t #include // vsnprintf #include // memset +#include // new (ptr) #ifdef _MSC_VER #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen #endif + //------------------------------------------------------------------------- // Forward Declarations //------------------------------------------------------------------------- @@ -373,6 +375,14 @@ static int ImStricmp(const char* str1, const char* str2) return d; } +static char* ImStrdup(const char *str) +{ + char *buff = (char*)IM_MALLOC(strlen(str) + 1); + IM_ASSERT(buff); + strcpy(buff, str); + return buff; +} + static const char* ImStristr(const char* haystack, const char* needle, const char* needle_end) { if (!needle_end) @@ -615,7 +625,7 @@ struct ImGuiIniData bool Collapsed; ImGuiIniData() { memset(this, 0, sizeof(*this)); } - ~ImGuiIniData() { if (Name) { free(Name); Name = NULL; } } + ~ImGuiIniData() { if (Name) { IM_FREE(Name); Name = NULL; } } }; struct ImGuiState @@ -656,7 +666,7 @@ struct ImGuiState // Logging bool LogEnabled; FILE* LogFile; - ImGuiTextBuffer LogClipboard; + ImGuiTextBuffer* LogClipboard; int LogAutoExpandMaxDepth; ImGuiState() @@ -679,6 +689,7 @@ struct ImGuiState LogEnabled = false; LogFile = NULL; LogAutoExpandMaxDepth = 2; + LogClipboard = NULL; } }; @@ -944,7 +955,7 @@ void ImGuiTextBuffer::append(const char* fmt, ...) ImGuiWindow::ImGuiWindow(const char* name, ImVec2 default_pos, ImVec2 default_size) { - Name = strdup(name); + Name = ImStrdup(name); ID = GetID(name); IDStack.push_back(ID); @@ -971,14 +982,16 @@ ImGuiWindow::ImGuiWindow(const char* name, ImVec2 default_pos, ImVec2 default_si FocusIdxRequestCurrent = IM_INT_MAX; FocusIdxRequestNext = IM_INT_MAX; - DrawList = new ImDrawList(); + DrawList = (ImDrawList*)IM_MALLOC(sizeof(ImDrawList)); + new(DrawList) ImDrawList(); } ImGuiWindow::~ImGuiWindow() { - delete DrawList; + DrawList->~ImDrawList(); + IM_FREE(DrawList); DrawList = NULL; - free(Name); + IM_FREE(Name); Name = NULL; } @@ -1058,8 +1071,9 @@ static ImGuiIniData* FindWindowSettings(const char* name) if (ImStricmp(ini->Name, name) == 0) return ini; } - ImGuiIniData* ini = new ImGuiIniData(); - ini->Name = strdup(name); + ImGuiIniData* ini = (ImGuiIniData*)IM_MALLOC(sizeof(ImGuiIniData)); + new(ini) ImGuiIniData(); + ini->Name = ImStrdup(name); ini->Collapsed = false; ini->Pos = ImVec2(FLT_MAX,FLT_MAX); ini->Size = ImVec2(0,0); @@ -1097,12 +1111,12 @@ static void LoadSettings() fclose(f); return; } - char* f_data = new char[f_size+1]; + char* f_data = (char*)IM_MALLOC(f_size+1); f_size = fread(f_data, 1, f_size, f); // Text conversion alter read size so let's not be fussy about return value fclose(f); if (f_size == 0) { - delete[] f_data; + IM_FREE(f_data); return; } f_data[f_size] = 0; @@ -1136,7 +1150,7 @@ static void LoadSettings() line_start = line_end+1; } - delete[] f_data; + IM_FREE(f_data); } static void SaveSettings() @@ -1208,6 +1222,9 @@ void NewFrame() if (!g.Initialized) { // Initialize on first frame + g.LogClipboard = (ImGuiTextBuffer*)IM_MALLOC(sizeof(ImGuiTextBuffer)); + new(g.LogClipboard) ImGuiTextBuffer(); + IM_ASSERT(g.Settings.empty()); LoadSettings(); if (!g.IO.Font) @@ -1216,7 +1233,8 @@ void NewFrame() const void* fnt_data; unsigned int fnt_size; ImGui::GetDefaultFontData(&fnt_data, &fnt_size, NULL, NULL); - g.IO.Font = new ImBitmapFont(); + g.IO.Font = (ImBitmapFont*)IM_MALLOC(sizeof(ImBitmapFont)); + new(g.IO.Font) ImBitmapFont(); g.IO.Font->LoadFromMemory(fnt_data, fnt_size); g.IO.FontYOffset = +1; } @@ -1343,14 +1361,21 @@ void Shutdown() SaveSettings(); for (size_t i = 0; i < g.Windows.size(); i++) - delete g.Windows[i]; + { + g.Windows[i]->~ImGuiWindow(); + IM_FREE(g.Windows[i]); + } g.Windows.clear(); g.CurrentWindowStack.clear(); + g.RenderDrawLists.clear(); g.FocusedWindow = NULL; g.HoveredWindow = NULL; g.HoveredWindowExcludingChilds = NULL; for (size_t i = 0; i < g.Settings.size(); i++) - delete g.Settings[i]; + { + g.Settings[i]->~ImGuiIniData(); + IM_FREE(g.Settings[i]); + } g.Settings.clear(); g.ColorEditModeStorage.Clear(); if (g.LogFile && g.LogFile != stdout) @@ -1360,16 +1385,23 @@ void Shutdown() } if (g.IO.Font) { - delete g.IO.Font; + g.IO.Font->~ImBitmapFont(); + IM_FREE(g.IO.Font); g.IO.Font = NULL; } if (g.PrivateClipboard) { - free(g.PrivateClipboard); + IM_FREE(g.PrivateClipboard); g.PrivateClipboard = NULL; } + if (g.LogClipboard) + { + g.LogClipboard->~ImGuiTextBuffer(); + IM_FREE(g.LogClipboard); + } + g.Initialized = false; } @@ -1534,9 +1566,9 @@ static void LogText(const ImVec2& ref_pos, const char* text, const char* text_en else { if (log_new_line || !is_first_line) - g.LogClipboard.append("\n%*s%.*s", tree_depth*4, "", char_count, text_remaining); + g.LogClipboard->append("\n%*s%.*s", tree_depth*4, "", char_count, text_remaining); else - g.LogClipboard.append(" %.*s", char_count, text_remaining); + g.LogClipboard->append(" %.*s", char_count, text_remaining); } } @@ -1859,7 +1891,8 @@ bool Begin(const char* name, bool* open, ImVec2 size, float fill_alpha, ImGuiWin // Create window the first time, and load settings if (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Tooltip)) { - window = new ImGuiWindow(name, ImVec2(0,0), size); + window = (ImGuiWindow*)IM_MALLOC(sizeof(ImGuiWindow)); + new(window) ImGuiWindow(name, ImVec2(0,0), size); } else { @@ -1867,7 +1900,8 @@ bool Begin(const char* name, bool* open, ImVec2 size, float fill_alpha, ImGuiWin if (settings && ImLength(settings->Size) > 0.0f && !(flags & ImGuiWindowFlags_NoResize))// && ImLengthsize) == 0.0f) size = settings->Size; - window = new ImGuiWindow(name, g.NewWindowDefaultPos, size); + window = (ImGuiWindow*)IM_MALLOC(sizeof(ImGuiWindow)); + new(window) ImGuiWindow(name, g.NewWindowDefaultPos, size); if (settings->Pos.x != FLT_MAX) { @@ -2267,12 +2301,12 @@ void End() fclose(g.LogFile); g.LogFile = NULL; } - if (g.LogClipboard.size() > 1) + if (g.LogClipboard->size() > 1) { - g.LogClipboard.append("\n"); + g.LogClipboard->append("\n"); if (g.IO.SetClipboardTextFn) - g.IO.SetClipboardTextFn(g.LogClipboard.begin(), g.LogClipboard.end()); - g.LogClipboard.clear(); + g.IO.SetClipboardTextFn(g.LogClipboard->begin(), g.LogClipboard->end()); + g.LogClipboard->clear(); } } @@ -3970,7 +4004,7 @@ bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlag { // Remove new-line from pasted buffer size_t clipboard_len = strlen(clipboard); - char* clipboard_filtered = (char*)malloc(clipboard_len+1); + char* clipboard_filtered = (char*)IM_MALLOC(clipboard_len+1); int clipboard_filtered_len = 0; for (int i = 0; clipboard[i]; i++) { @@ -3981,7 +4015,7 @@ bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlag } clipboard_filtered[clipboard_filtered_len] = 0; stb_textedit_paste(&edit_state, &edit_state.StbState, clipboard_filtered, clipboard_filtered_len); - free(clipboard_filtered); + IM_FREE(clipboard_filtered); } } else if (g.IO.InputCharacters[0]) @@ -5100,7 +5134,7 @@ ImBitmapFont::ImBitmapFont() void ImBitmapFont::Clear() { if (Data && DataOwned) - free(Data); + IM_FREE(Data); Data = NULL; DataOwned = false; Info = NULL; @@ -5127,7 +5161,7 @@ bool ImBitmapFont::LoadFromFile(const char* filename) DataSize = (size_t)f_size; if (fseek(f, 0, SEEK_SET)) return false; - if ((Data = (unsigned char*)malloc(DataSize)) == NULL) + if ((Data = (unsigned char*)IM_MALLOC(DataSize)) == NULL) { fclose(f); return false; @@ -5135,7 +5169,7 @@ bool ImBitmapFont::LoadFromFile(const char* filename) if (fread(Data, 1, DataSize, f) != DataSize) { fclose(f); - free(Data); + IM_FREE(Data); return false; } fclose(f); @@ -5378,7 +5412,7 @@ static const char* GetClipboardTextFn_DefaultImpl() static char* buf_local = NULL; if (buf_local) { - free(buf_local); + IM_FREE(buf_local); buf_local = NULL; } if (!OpenClipboard(NULL)) @@ -5387,7 +5421,7 @@ static const char* GetClipboardTextFn_DefaultImpl() if (buf_handle == NULL) return NULL; if (char* buf_global = (char*)GlobalLock(buf_handle)) - buf_local = strdup(buf_global); + buf_local = ImStrdup(buf_global); GlobalUnlock(buf_handle); CloseClipboard(); return buf_local; @@ -5426,12 +5460,12 @@ static void SetClipboardTextFn_DefaultImpl(const char* text, const char* text_en { if (GImGui.PrivateClipboard) { - free(GImGui.PrivateClipboard); + IM_FREE(GImGui.PrivateClipboard); GImGui.PrivateClipboard = NULL; } if (!text_end) text_end = text + strlen(text); - GImGui.PrivateClipboard = (char*)malloc((size_t)(text_end - text) + 1); + GImGui.PrivateClipboard = (char*)IM_MALLOC((size_t)(text_end - text) + 1); memcpy(GImGui.PrivateClipboard, text, (size_t)(text_end - text)); GImGui.PrivateClipboard[(size_t)(text_end - text)] = 0; } @@ -5965,7 +5999,7 @@ void ShowTestWindow(bool* open) /* // Copyright (c) 2004, 2005 Tristan Grimmer -// Permission is hereby granted, free of charge, to any person obtaining a copy +// Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell diff --git a/imgui.h b/imgui.h index c8ffeedb..3675c76d 100644 --- a/imgui.h +++ b/imgui.h @@ -19,6 +19,18 @@ struct ImGuiWindow; #include // va_list #include // NULL +#ifndef IM_MALLOC +#define IM_MALLOC(_SIZE) malloc((_SIZE)) +#endif + +#ifndef IM_FREE +#define IM_FREE(_PTR) free((_PTR)) +#endif + +#ifndef IM_REALLOC +#define IM_REALLOC(_PTR, _SIZE) realloc((_PTR), (_SIZE)) +#endif + #ifndef IM_ASSERT #include #define IM_ASSERT(_EXPR) assert(_EXPR) @@ -58,6 +70,7 @@ struct ImVec4 // std::vector<> like class to avoid dragging dependencies (also: windows implementation of STL with debug enabled is absurdly slow, so let's bypass it so our code runs fast in debug). // this implementation does NOT call c++ constructors! we don't need them! also only provide the minimum functionalities we need. #ifndef ImVector + template class ImVector { @@ -72,7 +85,7 @@ public: typedef const value_type* const_iterator; ImVector() { Size = Capacity = 0; Data = NULL; } - ~ImVector() { if (Data) free(Data); } + ~ImVector() { if (Data) IM_FREE(Data); } inline bool empty() const { return Size == 0; } inline size_t size() const { return Size; } @@ -83,7 +96,7 @@ public: inline value_type& operator[](size_t i) { IM_ASSERT(i < Size); return Data[i]; } inline const value_type& operator[](size_t i) const { IM_ASSERT(i < Size); return Data[i]; } - inline void clear() { if (Data) { Size = Capacity = 0; free(Data); Data = NULL; } } + inline void clear() { if (Data) { Size = Capacity = 0; IM_FREE(Data); Data = NULL; } } inline iterator begin() { return Data; } inline const_iterator begin() const { return Data; } inline iterator end() { return Data + Size; } @@ -94,7 +107,7 @@ public: inline const value_type& back() const { IM_ASSERT(Size > 0); return at(Size-1); } inline void swap(ImVector& rhs) { const size_t rhs_size = rhs.Size; rhs.Size = Size; Size = rhs_size; const size_t rhs_cap = rhs.Capacity; rhs.Capacity = Capacity; Capacity = rhs_cap; value_type* rhs_data = rhs.Data; rhs.Data = Data; Data = rhs_data; } - inline void reserve(size_t new_capacity) { Data = (value_type*)realloc(Data, new_capacity * sizeof(value_type)); Capacity = new_capacity; } + inline void reserve(size_t new_capacity) { Data = (value_type*)IM_REALLOC(Data, new_capacity * sizeof(value_type)); Capacity = new_capacity; } inline void resize(size_t new_size) { if (new_size > Capacity) reserve(new_size); Size = new_size; } inline void push_back(const value_type& v) { if (Size == Capacity) reserve(Capacity ? Capacity * 2 : 4); Data[Size++] = v; }