diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 3fb7a132..73e3e5bf 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -35,6 +35,11 @@ HOW TO UPDATE? Breaking Changes: + - TreeNodeEx(): The helper ImGuiTreeNodeFlags_CollapsingHeader flag now include ImGuiTreeNodeFlags_NoTreePushOnOpen. The flag was already set by CollapsingHeader(). + The only difference is if you were using TreeNodeEx() manually with ImGuiTreeNodeFlags_CollapsingHeader and without ImGuiTreeNodeFlags_NoTreePushOnOpen. In which case + you can remove the ImGuiTreeNodeFlags_NoTreePushOnOpen flag from your call (ImGuiTreeNodeFlags_CollapsingHeader & ~ImGuiTreeNodeFlags_NoTreePushOnOpen). (#1864) + - ImFontAtlas: Renamed GetGlyphRangesChinese() to GetGlyphRangesChineseFull() to distinguish other variants and discourage using the full set. (#1859) + Other Changes: - Nav: To keep the navigated item in view we also attempt to scroll the parent window as well as the current window. (#787) @@ -44,7 +49,13 @@ Other Changes: - BeginDragDropSource(): Offset tooltip position so it is off the mouse cursor, but also closer to it than regular tooltips, and not clamped by viewport. (#1739) - BeginDragDropTarget(): Added ImGuiDragDropFlags_AcceptNoPreviewTooltip flag to request hiding the drag source tooltip from the target site. (#143) - BeginCombo(), BeginMainMenuBar(), BeginChildFrame(): Temporary style modification are restored at the end of BeginXXX instead of EndXXX, to not affect tooltips and child windows. + - Popup: Improved handling of (erroneously) repeating calls to OpenPopup() to not fully close/re-open the popup so its child popups won't get closed. (#1497, #1533, #1865). + - InputTextMultiline(): Fixed double navigation highlight when scrollbar is active. (#787) + - InputText(): Fixed Undo after pasting large amount of text (Redo will still fail when undo buffers are exhausted, but text won't be corrupted). + - SliderFloat(): When using keyboard/gamepad and a zero precision format string (e.g. "%.0f"), always step in integer units. (#1866) + - ImFontAtlas: Added GetGlyphRangesChineseSimplifiedCommon() helper that returns a list of ~2500 most common Simplified Chinese characters. (#1859) [@JX-Master, @ocornut] - Examples: GLFW: Made it possible to Shutdown/Init the backend again (by reseting the time storage properly). (#1827) [@ice1000] + - Misc: Updated stb_textedit from 1.09 + patches to 1.12 + minor patches. - Internals: PushItemFlag() flags are inherited by BeginChild(). diff --git a/imgui.cpp b/imgui.cpp index 0f7edbe6..7df80098 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -274,7 +274,10 @@ - 2018/XX/XX (1.XX) - Moved IME support functions from io.ImeSetInputScreenPosFn, io.ImeWindowHandle to the PlatformIO api. - 2018/XX/XX (1.XX) - removed io.DisplayVisibleMin, io.DisplayVisibleMax settings (it was used to clip within the DisplayMin..DisplayMax range, I don't know of anyone using it) - - 2018/05/03 (1.61) - DragInt(): The default compile-time format string has been changed from "%.0f" to "%d", as we are not using integers internally any more. + + - 2018/06/06 (1.62) - renamed GetGlyphRangesChinese() to GetGlyphRangesChineseFull() to distinguish other variants and discourage using the full set. + - 2018/06/06 (1.62) - TreeNodeEx(): the ImGuiTreeNodeFlags_CollapsingHeader helper now include the ImGuiTreeNodeFlags_NoTreePushOnOpen flag. See Changelog for details. + - 2018/05/03 (1.61) - DragInt(): the default compile-time format string has been changed from "%.0f" to "%d", as we are not using integers internally any more. If you used DragInt() with custom format strings, make sure you change them to use %d or an integer-compatible format. To honor backward-compatibility, the DragInt() code will currently parse and modify format strings to replace %*f with %d, giving time to users to upgrade their code. If you have IMGUI_DISABLE_OBSOLETE_FUNCTIONS enabled, the code will instead assert! You may run a reg-exp search on your codebase for e.g. "DragInt.*%f" to help you find them. @@ -715,8 +718,12 @@ (such as CP-923 for Japanese or CP-1251 for Cyrillic) will NOT work! Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8. - Text input: it is up to your application to pass the right character code by calling - io.AddInputCharacter(). The applications in examples/ are doing that. + Text input: it is up to your application to pass the right character code by calling io.AddInputCharacter(). + The applications in examples/ are doing that. + Windows: you can use the WM_CHAR or WM_UNICHAR or WM_IME_CHAR message (depending if your app is built using Unicode or MultiByte mode). + You may also use MultiByteToWideChar() or ToUnicode() to retrieve Unicode codepoints from MultiByte characters or keyboard state. + Windows: if your language is relying on an Input Method Editor (IME), you copy the HWND of your window to io.ImeWindowHandle in order for + the default implementation of io.ImeSetInputScreenPosFn() to set your Microsoft IME position correctly. Q: How can I use the drawing facilities without an ImGui window? (using ImDrawList API) A: - You can create a dummy window. Call SetNextWindowBgAlpha(0.0f), call Begin() with NoTitleBar|NoResize|NoMove|NoScrollbar|NoSavedSettings|NoInputs flags. @@ -2359,9 +2366,9 @@ static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand) const ImRect& curr = g.NavScoringRectScreen; // Current modified source rect (NB: we've applied Max.x = Min.x in NavUpdate() to inhibit the effect of having varied item width) g.NavScoringCount++; - if (window != g.NavWindow) + // When entering through a NavFlattened border, we consider child window items as fully clipped for scoring + if (window->ParentWindow == g.NavWindow) { - // When crossing through a NavFlattened border, we score items on the other windows fully clipped IM_ASSERT((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened); if (!window->ClipRect.Contains(cand)) return false; @@ -3309,9 +3316,11 @@ static void ImGui::NavUpdate() // Set mouse position given our knowledge of the navigated item position from last frame if ((g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) && (g.IO.BackendFlags & ImGuiBackendFlags_HasSetMousePos)) { - IM_ASSERT(!g.NavDisableHighlight && g.NavDisableMouseHover); - g.IO.MousePos = g.IO.MousePosPrev = NavCalcPreferredRefPos(); - g.IO.WantSetMousePos = true; + if (!g.NavDisableHighlight && g.NavDisableMouseHover && g.NavWindow) + { + g.IO.MousePos = g.IO.MousePosPrev = NavCalcPreferredRefPos(); + g.IO.WantSetMousePos = true; + } } g.NavMousePosDirty = false; } @@ -5738,16 +5747,19 @@ void ImGui::OpenPopupEx(ImGuiID id) } else { - // Close child popups if any - g.OpenPopupStack.resize(current_stack_size + 1); - // Gently handle the user mistakenly calling OpenPopup() every frame. It is a programming mistake! However, if we were to run the regular code path, the ui // would become completely unusable because the popup will always be in hidden-while-calculating-size state _while_ claiming focus. Which would be a very confusing // situation for the programmer. Instead, we silently allow the popup to proceed, it will keep reappearing and the programming error will be more obvious to understand. if (g.OpenPopupStack[current_stack_size].PopupId == id && g.OpenPopupStack[current_stack_size].OpenFrameCount == g.FrameCount - 1) + { g.OpenPopupStack[current_stack_size].OpenFrameCount = popup_ref.OpenFrameCount; + } else + { + // Close child popups if any, then flag popup for open/reopen + g.OpenPopupStack.resize(current_stack_size + 1); g.OpenPopupStack[current_stack_size] = popup_ref; + } // When reopening a popup we first refocus its parent, otherwise if its parent is itself a popup it would get closed by ClosePopupsOverWindow(). // This is equivalent to what ClosePopupToLevel() does. @@ -9420,14 +9432,14 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l } // CollapsingHeader returns true when opened but do not indent nor push into the ID stack (because of the ImGuiTreeNodeFlags_NoTreePushOnOpen flag). -// This is basically the same as calling TreeNodeEx(label, ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen). You can remove the _NoTreePushOnOpen flag if you want behavior closer to normal TreeNode(). +// This is basically the same as calling TreeNodeEx(label, ImGuiTreeNodeFlags_CollapsingHeader). You can remove the _NoTreePushOnOpen flag if you want behavior closer to normal TreeNode(). bool ImGui::CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; - return TreeNodeBehavior(window->GetID(label), flags | ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen, label); + return TreeNodeBehavior(window->GetID(label), flags | ImGuiTreeNodeFlags_CollapsingHeader, label); } bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags) @@ -9440,7 +9452,7 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags return false; ImGuiID id = window->GetID(label); - bool is_open = TreeNodeBehavior(id, flags | ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen | (p_open ? ImGuiTreeNodeFlags_AllowItemOverlap : 0), label); + bool is_open = TreeNodeBehavior(id, flags | ImGuiTreeNodeFlags_CollapsingHeader | (p_open ? ImGuiTreeNodeFlags_AllowItemOverlap : 0), label); if (p_open) { // Create a small overlapping close button // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc. @@ -10050,7 +10062,8 @@ static bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType d else if (delta != 0.0f) { clicked_t = SliderBehaviorCalcRatioFromValue(data_type, *v, v_min, v_max, power, linear_zero_pos); - if (is_decimal || is_power) + const int decimal_precision = is_decimal ? ImParseFormatPrecision(format, 3) : 0; + if ((decimal_precision > 0) || is_power) { delta /= 100.0f; // Gamepad/keyboard tweak speeds in % of slider bounds if (IsNavInputDown(ImGuiNavInput_TweakSlow)) @@ -11330,6 +11343,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 return false; } draw_window = GetCurrentWindow(); + draw_window->DC.NavLayerActiveMaskNext |= draw_window->DC.NavLayerCurrentMask; // This is to ensure that EndChild() will display a navigation highlight size.x -= draw_window->ScrollbarSizes.x; } else @@ -11725,9 +11739,11 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 // Select which buffer we are going to display. When ImGuiInputTextFlags_NoLiveEdit is set 'buf' might still be the old value. We set buf to NULL to prevent accidental usage from now on. const char* buf_display = (g.ActiveId == id && is_editable) ? edit_state.TempTextBuffer.Data : buf; buf = NULL; - RenderNavHighlight(frame_bb, id); if (!is_multiline) + { + RenderNavHighlight(frame_bb, id); RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); + } const ImVec4 clip_rect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + size.x, frame_bb.Min.y + size.y); // Not using frame_bb.Max because we have adjusted size ImVec2 render_pos = is_multiline ? draw_window->DC.CursorPos : frame_bb.Min + style.FramePadding; diff --git a/imgui.h b/imgui.h index a953475f..c7e53065 100644 --- a/imgui.h +++ b/imgui.h @@ -668,7 +668,7 @@ enum ImGuiTreeNodeFlags_ //ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 11, // FIXME: TODO: Extend hit box horizontally even if not framed //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 12, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 13, // (WIP) Nav: left direction may move to this TreeNode() from any of its child (items submitted between TreeNode and TreePop) - ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoAutoOpenOnLog + ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog // Obsolete names (will be removed) #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS @@ -1183,10 +1183,10 @@ struct ImGuiIO namespace ImGui { // OBSOLETED in 1.61 (from Apr 2018) - bool InputFloat(const char* label, float* v, float step, float step_fast, int decimal_precision, ImGuiInputTextFlags extra_flags = 0); // Use the 'const char* format' version instead of 'decimal_precision'! - bool InputFloat2(const char* label, float v[2], int decimal_precision, ImGuiInputTextFlags extra_flags = 0); - bool InputFloat3(const char* label, float v[3], int decimal_precision, ImGuiInputTextFlags extra_flags = 0); - bool InputFloat4(const char* label, float v[4], int decimal_precision, ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputFloat(const char* label, float* v, float step, float step_fast, int decimal_precision, ImGuiInputTextFlags extra_flags = 0); // Use the 'const char* format' version instead of 'decimal_precision'! + IMGUI_API bool InputFloat2(const char* label, float v[2], int decimal_precision, ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputFloat3(const char* label, float v[3], int decimal_precision, ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputFloat4(const char* label, float v[4], int decimal_precision, ImGuiInputTextFlags extra_flags = 0); // OBSOLETED in 1.60 (from Dec 2017) static inline bool IsAnyWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_AnyWindow); } static inline bool IsAnyWindowHovered() { return IsWindowHovered(ImGuiHoveredFlags_AnyWindow); } @@ -1198,7 +1198,7 @@ namespace ImGui static inline void SetNextWindowContentWidth(float w) { SetNextWindowContentSize(ImVec2(w, 0.0f)); } static inline float GetItemsLineHeightWithSpacing() { return GetFrameHeightWithSpacing(); } // OBSOLETED in 1.52 (between Aug 2017 and Oct 2017) - bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha_override = -1.0f, ImGuiWindowFlags flags = 0); // Use SetNextWindowSize(size, ImGuiCond_FirstUseEver) + SetNextWindowBgAlpha() instead. + IMGUI_API bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha_override = -1.0f, ImGuiWindowFlags flags = 0); // Use SetNextWindowSize(size, ImGuiCond_FirstUseEver) + SetNextWindowBgAlpha() instead. static inline bool IsRootWindowOrAnyChildHovered() { return IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows); } static inline void AlignFirstTextHeightToWidgets() { AlignTextToFramePadding(); } void SetNextWindowPosCenter(ImGuiCond cond); @@ -1796,19 +1796,21 @@ struct ImFontAtlas // Helpers to retrieve list of common Unicode ranges (2 value per range, values are inclusive, zero-terminated list) // NB: Make sure that your string are UTF-8 and NOT in your local code page. In C++11, you can create UTF-8 string literal using the u8"Hello world" syntax. See FAQ for details. - IMGUI_API const ImWchar* GetGlyphRangesDefault(); // Basic Latin, Extended Latin - IMGUI_API const ImWchar* GetGlyphRangesKorean(); // Default + Korean characters - IMGUI_API const ImWchar* GetGlyphRangesJapanese(); // Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs - IMGUI_API const ImWchar* GetGlyphRangesChinese(); // Default + Japanese + full set of about 21000 CJK Unified Ideographs - IMGUI_API const ImWchar* GetGlyphRangesCyrillic(); // Default + about 400 Cyrillic characters - IMGUI_API const ImWchar* GetGlyphRangesThai(); // Default + Thai characters + // NB: Consider using GlyphRangesBuilder to build glyph ranges from textual data. + IMGUI_API const ImWchar* GetGlyphRangesDefault(); // Basic Latin, Extended Latin + IMGUI_API const ImWchar* GetGlyphRangesKorean(); // Default + Korean characters + IMGUI_API const ImWchar* GetGlyphRangesJapanese(); // Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs + IMGUI_API const ImWchar* GetGlyphRangesChineseFull(); // Default + Half-Width + Japanese Hiragana/Katakana + full set of about 21000 CJK Unified Ideographs + IMGUI_API const ImWchar* GetGlyphRangesChineseSimplifiedCommon();// Default + Half-Width + Japanese Hiragana/Katakana + set of 2500 CJK Unified Ideographs for common simplified Chinese + IMGUI_API const ImWchar* GetGlyphRangesCyrillic(); // Default + about 400 Cyrillic characters + IMGUI_API const ImWchar* GetGlyphRangesThai(); // Default + Thai characters // Helpers to build glyph ranges from text data. Feed your application strings/characters to it then call BuildRanges(). struct GlyphRangesBuilder { ImVector UsedChars; // Store 1-bit per Unicode code point (0=unused, 1=used) GlyphRangesBuilder() { UsedChars.resize(0x10000 / 8); memset(UsedChars.Data, 0, 0x10000 / 8); } - bool GetBit(int n) { return (UsedChars[n >> 3] & (1 << (n & 7))) != 0; } + bool GetBit(int n) const { return (UsedChars[n >> 3] & (1 << (n & 7))) != 0; } void SetBit(int n) { UsedChars[n >> 3] |= 1 << (n & 7); } // Set bit 'c' in the array void AddChar(ImWchar c) { SetBit(c); } // Add character IMGUI_API void AddText(const char* text, const char* text_end = NULL); // Add string (each character of the UTF-8 string are added) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 7419eec4..dc290a20 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2029,7 +2029,7 @@ const ImWchar* ImFontAtlas::GetGlyphRangesKorean() return &ranges[0]; } -const ImWchar* ImFontAtlas::GetGlyphRangesChinese() +const ImWchar* ImFontAtlas::GetGlyphRangesChineseFull() { static const ImWchar ranges[] = { @@ -2043,67 +2043,136 @@ const ImWchar* ImFontAtlas::GetGlyphRangesChinese() return &ranges[0]; } -const ImWchar* ImFontAtlas::GetGlyphRangesJapanese() +static void UnpackAccumulativeOffsetsIntoRanges(int base_codepoint, const short* accumulative_offsets, int accumulative_offsets_count, ImWchar* out_ranges) { - // Store the 1946 ideograms code points as successive offsets from the initial unicode codepoint 0x4E00. Each offset has an implicit +1. - // This encoding is designed to helps us reduce the source code size. - // FIXME: Source a list of the revised 2136 joyo kanji list from 2010 and rebuild this. - // The current list was sourced from http://theinstructionlimit.com/author/renaudbedardrenaudbedard/page/3 - // Note that you may use ImFontAtlas::GlyphRangesBuilder to create your own ranges, by merging existing ranges or adding new characters. - static const short offsets_from_0x4E00[] = + for (int n = 0; n < accumulative_offsets_count; n++, out_ranges += 2) { - -1,0,1,3,0,0,0,0,1,0,5,1,1,0,7,4,6,10,0,1,9,9,7,1,3,19,1,10,7,1,0,1,0,5,1,0,6,4,2,6,0,0,12,6,8,0,3,5,0,1,0,9,0,0,8,1,1,3,4,5,13,0,0,8,2,17, - 4,3,1,1,9,6,0,0,0,2,1,3,2,22,1,9,11,1,13,1,3,12,0,5,9,2,0,6,12,5,3,12,4,1,2,16,1,1,4,6,5,3,0,6,13,15,5,12,8,14,0,0,6,15,3,6,0,18,8,1,6,14,1, - 5,4,12,24,3,13,12,10,24,0,0,0,1,0,1,1,2,9,10,2,2,0,0,3,3,1,0,3,8,0,3,2,4,4,1,6,11,10,14,6,15,3,4,15,1,0,0,5,2,2,0,0,1,6,5,5,6,0,3,6,5,0,0,1,0, - 11,2,2,8,4,7,0,10,0,1,2,17,19,3,0,2,5,0,6,2,4,4,6,1,1,11,2,0,3,1,2,1,2,10,7,6,3,16,0,8,24,0,0,3,1,1,3,0,1,6,0,0,0,2,0,1,5,15,0,1,0,0,2,11,19, - 1,4,19,7,6,5,1,0,0,0,0,5,1,0,1,9,0,0,5,0,2,0,1,0,3,0,11,3,0,2,0,0,0,0,0,9,3,6,4,12,0,14,0,0,29,10,8,0,14,37,13,0,31,16,19,0,8,30,1,20,8,3,48, - 21,1,0,12,0,10,44,34,42,54,11,18,82,0,2,1,2,12,1,0,6,2,17,2,12,7,0,7,17,4,2,6,24,23,8,23,39,2,16,23,1,0,5,1,2,15,14,5,6,2,11,0,8,6,2,2,2,14, - 20,4,15,3,4,11,10,10,2,5,2,1,30,2,1,0,0,22,5,5,0,3,1,5,4,1,0,0,2,2,21,1,5,1,2,16,2,1,3,4,0,8,4,0,0,5,14,11,2,16,1,13,1,7,0,22,15,3,1,22,7,14, - 22,19,11,24,18,46,10,20,64,45,3,2,0,4,5,0,1,4,25,1,0,0,2,10,0,0,0,1,0,1,2,0,0,9,1,2,0,0,0,2,5,2,1,1,5,5,8,1,1,1,5,1,4,9,1,3,0,1,0,1,1,2,0,0, - 2,0,1,8,22,8,1,0,0,0,0,4,2,1,0,9,8,5,0,9,1,30,24,2,6,4,39,0,14,5,16,6,26,179,0,2,1,1,0,0,0,5,2,9,6,0,2,5,16,7,5,1,1,0,2,4,4,7,15,13,14,0,0, - 3,0,1,0,0,0,2,1,6,4,5,1,4,9,0,3,1,8,0,0,10,5,0,43,0,2,6,8,4,0,2,0,0,9,6,0,9,3,1,6,20,14,6,1,4,0,7,2,3,0,2,0,5,0,3,1,0,3,9,7,0,3,4,0,4,9,1,6,0, - 9,0,0,2,3,10,9,28,3,6,2,4,1,2,32,4,1,18,2,0,3,1,5,30,10,0,2,2,2,0,7,9,8,11,10,11,7,2,13,7,5,10,0,3,40,2,0,1,6,12,0,4,5,1,5,11,11,21,4,8,3,7, - 8,8,33,5,23,0,0,19,8,8,2,3,0,6,1,1,1,5,1,27,4,2,5,0,3,5,6,3,1,0,3,1,12,5,3,3,2,0,7,7,2,1,0,4,0,1,1,2,0,10,10,6,2,5,9,7,5,15,15,21,6,11,5,20, - 4,3,5,5,2,5,0,2,1,0,1,7,28,0,9,0,5,12,5,5,18,30,0,12,3,3,21,16,25,32,9,3,14,11,24,5,66,9,1,2,0,5,9,1,5,1,8,0,8,3,3,0,1,15,1,4,8,1,2,7,0,7,2, - 8,3,7,5,3,7,10,2,1,0,0,2,25,0,6,4,0,10,0,4,2,4,1,12,5,38,4,0,4,1,10,5,9,4,0,14,4,2,5,18,20,21,1,3,0,5,0,7,0,3,7,1,3,1,1,8,1,0,0,0,3,2,5,2,11, - 6,0,13,1,3,9,1,12,0,16,6,2,1,0,2,1,12,6,13,11,2,0,28,1,7,8,14,13,8,13,0,2,0,5,4,8,10,2,37,42,19,6,6,7,4,14,11,18,14,80,7,6,0,4,72,12,36,27, - 7,7,0,14,17,19,164,27,0,5,10,7,3,13,6,14,0,2,2,5,3,0,6,13,0,0,10,29,0,4,0,3,13,0,3,1,6,51,1,5,28,2,0,8,0,20,2,4,0,25,2,10,13,10,0,16,4,0,1,0, - 2,1,7,0,1,8,11,0,0,1,2,7,2,23,11,6,6,4,16,2,2,2,0,22,9,3,3,5,2,0,15,16,21,2,9,20,15,15,5,3,9,1,0,0,1,7,7,5,4,2,2,2,38,24,14,0,0,15,5,6,24,14, - 5,5,11,0,21,12,0,3,8,4,11,1,8,0,11,27,7,2,4,9,21,59,0,1,39,3,60,62,3,0,12,11,0,3,30,11,0,13,88,4,15,5,28,13,1,4,48,17,17,4,28,32,46,0,16,0, - 18,11,1,8,6,38,11,2,6,11,38,2,0,45,3,11,2,7,8,4,30,14,17,2,1,1,65,18,12,16,4,2,45,123,12,56,33,1,4,3,4,7,0,0,0,3,2,0,16,4,2,4,2,0,7,4,5,2,26, - 2,25,6,11,6,1,16,2,6,17,77,15,3,35,0,1,0,5,1,0,38,16,6,3,12,3,3,3,0,9,3,1,3,5,2,9,0,18,0,25,1,3,32,1,72,46,6,2,7,1,3,14,17,0,28,1,40,13,0,20, - 15,40,6,38,24,12,43,1,1,9,0,12,6,0,6,2,4,19,3,7,1,48,0,9,5,0,5,6,9,6,10,15,2,11,19,3,9,2,0,1,10,1,27,8,1,3,6,1,14,0,26,0,27,16,3,4,9,6,2,23, - 9,10,5,25,2,1,6,1,1,48,15,9,15,14,3,4,26,60,29,13,37,21,1,6,4,0,2,11,22,23,16,16,2,2,1,3,0,5,1,6,4,0,0,4,0,0,8,3,0,2,5,0,7,1,7,3,13,2,4,10, - 3,0,2,31,0,18,3,0,12,10,4,1,0,7,5,7,0,5,4,12,2,22,10,4,2,15,2,8,9,0,23,2,197,51,3,1,1,4,13,4,3,21,4,19,3,10,5,40,0,4,1,1,10,4,1,27,34,7,21, - 2,17,2,9,6,4,2,3,0,4,2,7,8,2,5,1,15,21,3,4,4,2,2,17,22,1,5,22,4,26,7,0,32,1,11,42,15,4,1,2,5,0,19,3,1,8,6,0,10,1,9,2,13,30,8,2,24,17,19,1,4, - 4,25,13,0,10,16,11,39,18,8,5,30,82,1,6,8,18,77,11,13,20,75,11,112,78,33,3,0,0,60,17,84,9,1,1,12,30,10,49,5,32,158,178,5,5,6,3,3,1,3,1,4,7,6, - 19,31,21,0,2,9,5,6,27,4,9,8,1,76,18,12,1,4,0,3,3,6,3,12,2,8,30,16,2,25,1,5,5,4,3,0,6,10,2,3,1,0,5,1,19,3,0,8,1,5,2,6,0,0,0,19,1,2,0,5,1,2,5, - 1,3,7,0,4,12,7,3,10,22,0,9,5,1,0,2,20,1,1,3,23,30,3,9,9,1,4,191,14,3,15,6,8,50,0,1,0,0,4,0,0,1,0,2,4,2,0,2,3,0,2,0,2,2,8,7,0,1,1,1,3,3,17,11, - 91,1,9,3,2,13,4,24,15,41,3,13,3,1,20,4,125,29,30,1,0,4,12,2,21,4,5,5,19,11,0,13,11,86,2,18,0,7,1,8,8,2,2,22,1,2,6,5,2,0,1,2,8,0,2,0,5,2,1,0, - 2,10,2,0,5,9,2,1,2,0,1,0,4,0,0,10,2,5,3,0,6,1,0,1,4,4,33,3,13,17,3,18,6,4,7,1,5,78,0,4,1,13,7,1,8,1,0,35,27,15,3,0,0,0,1,11,5,41,38,15,22,6, - 14,14,2,1,11,6,20,63,5,8,27,7,11,2,2,40,58,23,50,54,56,293,8,8,1,5,1,14,0,1,12,37,89,8,8,8,2,10,6,0,0,0,4,5,2,1,0,1,1,2,7,0,3,3,0,4,6,0,3,2, - 19,3,8,0,0,0,4,4,16,0,4,1,5,1,3,0,3,4,6,2,17,10,10,31,6,4,3,6,10,126,7,3,2,2,0,9,0,0,5,20,13,0,15,0,6,0,2,5,8,64,50,3,2,12,2,9,0,0,11,8,20, - 109,2,18,23,0,0,9,61,3,0,28,41,77,27,19,17,81,5,2,14,5,83,57,252,14,154,263,14,20,8,13,6,57,39,38, + out_ranges[0] = out_ranges[1] = (ImWchar)(base_codepoint + accumulative_offsets[n]); + base_codepoint += accumulative_offsets[n]; + } + out_ranges[0] = 0; +} + +const ImWchar* ImFontAtlas::GetGlyphRangesChineseSimplifiedCommon() +{ + // Store 2500 regularly used characters for Simplified Chinese. + // Sourced from https://zh.wiktionary.org/wiki/%E9%99%84%E5%BD%95:%E7%8E%B0%E4%BB%A3%E6%B1%89%E8%AF%AD%E5%B8%B8%E7%94%A8%E5%AD%97%E8%A1%A8 + // This table covers 97.97% of all characters used during the month in July, 1987. + // You can use ImFontAtlas::GlyphRangesBuilder to create your own ranges derived from this, by merging existing ranges or adding new characters. + // (Stored as accumulative offsets from the initial unicode codepoint 0x4E00. This encoding is designed to helps us compact the source code size.) + static const short accumulative_offsets_from_0x4E00[] = + { + 0,1,2,4,1,1,1,1,2,1,3,2,1,2,2,1,1,1,1,1,5,2,1,2,3,3,3,2,2,4,1,1,1,2,1,5,2,3,1,2,1,2,1,1,2,1,1,2,2,1,4,1,1,1,1,5,10,1,2,19,2,1,2,1,2,1,2,1,2, + 1,5,1,6,3,2,1,2,2,1,1,1,4,8,5,1,1,4,1,1,3,1,2,1,5,1,2,1,1,1,10,1,1,5,2,4,6,1,4,2,2,2,12,2,1,1,6,1,1,1,4,1,1,4,6,5,1,4,2,2,4,10,7,1,1,4,2,4, + 2,1,4,3,6,10,12,5,7,2,14,2,9,1,1,6,7,10,4,7,13,1,5,4,8,4,1,1,2,28,5,6,1,1,5,2,5,20,2,2,9,8,11,2,9,17,1,8,6,8,27,4,6,9,20,11,27,6,68,2,2,1,1, + 1,2,1,2,2,7,6,11,3,3,1,1,3,1,2,1,1,1,1,1,3,1,1,8,3,4,1,5,7,2,1,4,4,8,4,2,1,2,1,1,4,5,6,3,6,2,12,3,1,3,9,2,4,3,4,1,5,3,3,1,3,7,1,5,1,1,1,1,2, + 3,4,5,2,3,2,6,1,1,2,1,7,1,7,3,4,5,15,2,2,1,5,3,22,19,2,1,1,1,1,2,5,1,1,1,6,1,1,12,8,2,9,18,22,4,1,1,5,1,16,1,2,7,10,15,1,1,6,2,4,1,2,4,1,6, + 1,1,3,2,4,1,6,4,5,1,2,1,1,2,1,10,3,1,3,2,1,9,3,2,5,7,2,19,4,3,6,1,1,1,1,1,4,3,2,1,1,1,2,5,3,1,1,1,2,2,1,1,2,1,1,2,1,3,1,1,1,3,7,1,4,1,1,2,1, + 1,2,1,2,4,4,3,8,1,1,1,2,1,3,5,1,3,1,3,4,6,2,2,14,4,6,6,11,9,1,15,3,1,28,5,2,5,5,3,1,3,4,5,4,6,14,3,2,3,5,21,2,7,20,10,1,2,19,2,4,28,28,2,3, + 2,1,14,4,1,26,28,42,12,40,3,52,79,5,14,17,3,2,2,11,3,4,6,3,1,8,2,23,4,5,8,10,4,2,7,3,5,1,1,6,3,1,2,2,2,5,28,1,1,7,7,20,5,3,29,3,17,26,1,8,4, + 27,3,6,11,23,5,3,4,6,13,24,16,6,5,10,25,35,7,3,2,3,3,14,3,6,2,6,1,4,2,3,8,2,1,1,3,3,3,4,1,1,13,2,2,4,5,2,1,14,14,1,2,2,1,4,5,2,3,1,14,3,12, + 3,17,2,16,5,1,2,1,8,9,3,19,4,2,2,4,17,25,21,20,28,75,1,10,29,103,4,1,2,1,1,4,2,4,1,2,3,24,2,2,2,1,1,2,1,3,8,1,1,1,2,1,1,3,1,1,1,6,1,5,3,1,1, + 1,3,4,1,1,5,2,1,5,6,13,9,16,1,1,1,1,3,2,3,2,4,5,2,5,2,2,3,7,13,7,2,2,1,1,1,1,2,3,3,2,1,6,4,9,2,1,14,2,14,2,1,18,3,4,14,4,11,41,15,23,15,23, + 176,1,3,4,1,1,1,1,5,3,1,2,3,7,3,1,1,2,1,2,4,4,6,2,4,1,9,7,1,10,5,8,16,29,1,1,2,2,3,1,3,5,2,4,5,4,1,1,2,2,3,3,7,1,6,10,1,17,1,44,4,6,2,1,1,6, + 5,4,2,10,1,6,9,2,8,1,24,1,2,13,7,8,8,2,1,4,1,3,1,3,3,5,2,5,10,9,4,9,12,2,1,6,1,10,1,1,7,7,4,10,8,3,1,13,4,3,1,6,1,3,5,2,1,2,17,16,5,2,16,6, + 1,4,2,1,3,3,6,8,5,11,11,1,3,3,2,4,6,10,9,5,7,4,7,4,7,1,1,4,2,1,3,6,8,7,1,6,11,5,5,3,24,9,4,2,7,13,5,1,8,82,16,61,1,1,1,4,2,2,16,10,3,8,1,1, + 6,4,2,1,3,1,1,1,4,3,8,4,2,2,1,1,1,1,1,6,3,5,1,1,4,6,9,2,1,1,1,2,1,7,2,1,6,1,5,4,4,3,1,8,1,3,3,1,3,2,2,2,2,3,1,6,1,2,1,2,1,3,7,1,8,2,1,2,1,5, + 2,5,3,5,10,1,2,1,1,3,2,5,11,3,9,3,5,1,1,5,9,1,2,1,5,7,9,9,8,1,3,3,3,6,8,2,3,2,1,1,32,6,1,2,15,9,3,7,13,1,3,10,13,2,14,1,13,10,2,1,3,10,4,15, + 2,15,15,10,1,3,9,6,9,32,25,26,47,7,3,2,3,1,6,3,4,3,2,8,5,4,1,9,4,2,2,19,10,6,2,3,8,1,2,2,4,2,1,9,4,4,4,6,4,8,9,2,3,1,1,1,1,3,5,5,1,3,8,4,6, + 2,1,4,12,1,5,3,7,13,2,5,8,1,6,1,2,5,14,6,1,5,2,4,8,15,5,1,23,6,62,2,10,1,1,8,1,2,2,10,4,2,2,9,2,1,1,3,2,3,1,5,3,3,2,1,3,8,1,1,1,11,3,1,1,4, + 3,7,1,14,1,2,3,12,5,2,5,1,6,7,5,7,14,11,1,3,1,8,9,12,2,1,11,8,4,4,2,6,10,9,13,1,1,3,1,5,1,3,2,4,4,1,18,2,3,14,11,4,29,4,2,7,1,3,13,9,2,2,5, + 3,5,20,7,16,8,5,72,34,6,4,22,12,12,28,45,36,9,7,39,9,191,1,1,1,4,11,8,4,9,2,3,22,1,1,1,1,4,17,1,7,7,1,11,31,10,2,4,8,2,3,2,1,4,2,16,4,32,2, + 3,19,13,4,9,1,5,2,14,8,1,1,3,6,19,6,5,1,16,6,2,10,8,5,1,2,3,1,5,5,1,11,6,6,1,3,3,2,6,3,8,1,1,4,10,7,5,7,7,5,8,9,2,1,3,4,1,1,3,1,3,3,2,6,16, + 1,4,6,3,1,10,6,1,3,15,2,9,2,10,25,13,9,16,6,2,2,10,11,4,3,9,1,2,6,6,5,4,30,40,1,10,7,12,14,33,6,3,6,7,3,1,3,1,11,14,4,9,5,12,11,49,18,51,31, + 140,31,2,2,1,5,1,8,1,10,1,4,4,3,24,1,10,1,3,6,6,16,3,4,5,2,1,4,2,57,10,6,22,2,22,3,7,22,6,10,11,36,18,16,33,36,2,5,5,1,1,1,4,10,1,4,13,2,7, + 5,2,9,3,4,1,7,43,3,7,3,9,14,7,9,1,11,1,1,3,7,4,18,13,1,14,1,3,6,10,73,2,2,30,6,1,11,18,19,13,22,3,46,42,37,89,7,3,16,34,2,2,3,9,1,7,1,1,1,2, + 2,4,10,7,3,10,3,9,5,28,9,2,6,13,7,3,1,3,10,2,7,2,11,3,6,21,54,85,2,1,4,2,2,1,39,3,21,2,2,5,1,1,1,4,1,1,3,4,15,1,3,2,4,4,2,3,8,2,20,1,8,7,13, + 4,1,26,6,2,9,34,4,21,52,10,4,4,1,5,12,2,11,1,7,2,30,12,44,2,30,1,1,3,6,16,9,17,39,82,2,2,24,7,1,7,3,16,9,14,44,2,1,2,1,2,3,5,2,4,1,6,7,5,3, + 2,6,1,11,5,11,2,1,18,19,8,1,3,24,29,2,1,3,5,2,2,1,13,6,5,1,46,11,3,5,1,1,5,8,2,10,6,12,6,3,7,11,2,4,16,13,2,5,1,1,2,2,5,2,28,5,2,23,10,8,4, + 4,22,39,95,38,8,14,9,5,1,13,5,4,3,13,12,11,1,9,1,27,37,2,5,4,4,63,211,95,2,2,2,1,3,5,2,1,1,2,2,1,1,1,3,2,4,1,2,1,1,5,2,2,1,1,2,3,1,3,1,1,1, + 3,1,4,2,1,3,6,1,1,3,7,15,5,3,2,5,3,9,11,4,2,22,1,6,3,8,7,1,4,28,4,16,3,3,25,4,4,27,27,1,4,1,2,2,7,1,3,5,2,28,8,2,14,1,8,6,16,25,3,3,3,14,3, + 3,1,1,2,1,4,6,3,8,4,1,1,1,2,3,6,10,6,2,3,18,3,2,5,5,4,3,1,5,2,5,4,23,7,6,12,6,4,17,11,9,5,1,1,10,5,12,1,1,11,26,33,7,3,6,1,17,7,1,5,12,1,11, + 2,4,1,8,14,17,23,1,2,1,7,8,16,11,9,6,5,2,6,4,16,2,8,14,1,11,8,9,1,1,1,9,25,4,11,19,7,2,15,2,12,8,52,7,5,19,2,16,4,36,8,1,16,8,24,26,4,6,2,9, + 5,4,36,3,28,12,25,15,37,27,17,12,59,38,5,32,127,1,2,9,17,14,4,1,2,1,1,8,11,50,4,14,2,19,16,4,17,5,4,5,26,12,45,2,23,45,104,30,12,8,3,10,2,2, + 3,3,1,4,20,7,2,9,6,15,2,20,1,3,16,4,11,15,6,134,2,5,59,1,2,2,2,1,9,17,3,26,137,10,211,59,1,2,4,1,4,1,1,1,2,6,2,3,1,1,2,3,2,3,1,3,4,4,2,3,3, + 1,4,3,1,7,2,2,3,1,2,1,3,3,3,2,2,3,2,1,3,14,6,1,3,2,9,6,15,27,9,34,145,1,1,2,1,1,1,1,2,1,1,1,1,2,2,2,3,1,2,1,1,1,2,3,5,8,3,5,2,4,1,3,2,2,2,12, + 4,1,1,1,10,4,5,1,20,4,16,1,15,9,5,12,2,9,2,5,4,2,26,19,7,1,26,4,30,12,15,42,1,6,8,172,1,1,4,2,1,1,11,2,2,4,2,1,2,1,10,8,1,2,1,4,5,1,2,5,1,8, + 4,1,3,4,2,1,6,2,1,3,4,1,2,1,1,1,1,12,5,7,2,4,3,1,1,1,3,3,6,1,2,2,3,3,3,2,1,2,12,14,11,6,6,4,12,2,8,1,7,10,1,35,7,4,13,15,4,3,23,21,28,52,5, + 26,5,6,1,7,10,2,7,53,3,2,1,1,1,2,163,532,1,10,11,1,3,3,4,8,2,8,6,2,2,23,22,4,2,2,4,2,1,3,1,3,3,5,9,8,2,1,2,8,1,10,2,12,21,20,15,105,2,3,1,1, + 3,2,3,1,1,2,5,1,4,15,11,19,1,1,1,1,5,4,5,1,1,2,5,3,5,12,1,2,5,1,11,1,1,15,9,1,4,5,3,26,8,2,1,3,1,1,15,19,2,12,1,2,5,2,7,2,19,2,20,6,26,7,5, + 2,2,7,34,21,13,70,2,128,1,1,2,1,1,2,1,1,3,2,2,2,15,1,4,1,3,4,42,10,6,1,49,85,8,1,2,1,1,4,4,2,3,6,1,5,7,4,3,211,4,1,2,1,2,5,1,2,4,2,2,6,5,6, + 10,3,4,48,100,6,2,16,296,5,27,387,2,2,3,7,16,8,5,38,15,39,21,9,10,3,7,59,13,27,21,47,5,21,6 }; - static ImWchar base_ranges[] = + static ImWchar base_ranges[] = // not zero-terminated { 0x0020, 0x00FF, // Basic Latin + Latin Supplement 0x3000, 0x30FF, // Punctuations, Hiragana, Katakana 0x31F0, 0x31FF, // Katakana Phonetic Extensions 0xFF00, 0xFFEF, // Half-width characters }; - static bool full_ranges_unpacked = false; - static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(offsets_from_0x4E00)*2 + 1]; - if (!full_ranges_unpacked) + static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(accumulative_offsets_from_0x4E00) * 2 + 1] = { 0 }; + if (!full_ranges[0]) { - // Unpack - int codepoint = 0x4e00; memcpy(full_ranges, base_ranges, sizeof(base_ranges)); - ImWchar* dst = full_ranges + IM_ARRAYSIZE(base_ranges); - for (int n = 0; n < IM_ARRAYSIZE(offsets_from_0x4E00); n++, dst += 2) - dst[0] = dst[1] = (ImWchar)(codepoint += (offsets_from_0x4E00[n] + 1)); - dst[0] = 0; - full_ranges_unpacked = true; + UnpackAccumulativeOffsetsIntoRanges(0x4E00, accumulative_offsets_from_0x4E00, IM_ARRAYSIZE(accumulative_offsets_from_0x4E00), full_ranges + IM_ARRAYSIZE(base_ranges)); + } + return &full_ranges[0]; +} + +const ImWchar* ImFontAtlas::GetGlyphRangesJapanese() +{ + // 1946 common ideograms code points for Japanese + // Sourced from http://theinstructionlimit.com/common-kanji-character-ranges-for-xna-spritefont-rendering + // FIXME: Source a list of the revised 2136 Joyo Kanji list from 2010 and rebuild this. + // You can use ImFontAtlas::GlyphRangesBuilder to create your own ranges derived from this, by merging existing ranges or adding new characters. + // (Stored as accumulative offsets from the initial unicode codepoint 0x4E00. This encoding is designed to helps us compact the source code size.) + static const short accumulative_offsets_from_0x4E00[] = + { + 0,1,2,4,1,1,1,1,2,1,6,2,2,1,8,5,7,11,1,2,10,10,8,2,4,20,2,11,8,2,1,2,1,6,2,1,7,5,3,7,1,1,13,7,9,1,4,6,1,2,1,10,1,1,9,2,2,4,5,6,14,1,1,9,3,18, + 5,4,2,2,10,7,1,1,1,3,2,4,3,23,2,10,12,2,14,2,4,13,1,6,10,3,1,7,13,6,4,13,5,2,3,17,2,2,5,7,6,4,1,7,14,16,6,13,9,15,1,1,7,16,4,7,1,19,9,2,7,15, + 2,6,5,13,25,4,14,13,11,25,1,1,1,2,1,2,2,3,10,11,3,3,1,1,4,4,2,1,4,9,1,4,3,5,5,2,7,12,11,15,7,16,4,5,16,2,1,1,6,3,3,1,1,2,7,6,6,7,1,4,7,6,1,1, + 2,1,12,3,3,9,5,8,1,11,1,2,3,18,20,4,1,3,6,1,7,3,5,5,7,2,2,12,3,1,4,2,3,2,3,11,8,7,4,17,1,9,25,1,1,4,2,2,4,1,2,7,1,1,1,3,1,2,6,16,1,2,1,1,3,12, + 20,2,5,20,8,7,6,2,1,1,1,1,6,2,1,2,10,1,1,6,1,3,1,2,1,4,1,12,4,1,3,1,1,1,1,1,10,4,7,5,13,1,15,1,1,30,11,9,1,15,38,14,1,32,17,20,1,9,31,2,21,9, + 4,49,22,2,1,13,1,11,45,35,43,55,12,19,83,1,3,2,3,13,2,1,7,3,18,3,13,8,1,8,18,5,3,7,25,24,9,24,40,3,17,24,2,1,6,2,3,16,15,6,7,3,12,1,9,7,3,3, + 3,15,21,5,16,4,5,12,11,11,3,6,3,2,31,3,2,1,1,23,6,6,1,4,2,6,5,2,1,1,3,3,22,2,6,2,3,17,3,2,4,5,1,9,5,1,1,6,15,12,3,17,2,14,2,8,1,23,16,4,2,23, + 8,15,23,20,12,25,19,47,11,21,65,46,4,3,1,5,6,1,2,5,26,2,1,1,3,11,1,1,1,2,1,2,3,1,1,10,2,3,1,1,1,3,6,3,2,2,6,6,9,2,2,2,6,2,5,10,2,4,1,2,1,2,2, + 3,1,1,3,1,2,9,23,9,2,1,1,1,1,5,3,2,1,10,9,6,1,10,2,31,25,3,7,5,40,1,15,6,17,7,27,180,1,3,2,2,1,1,1,6,3,10,7,1,3,6,17,8,6,2,2,1,3,5,5,8,16,14, + 15,1,1,4,1,2,1,1,1,3,2,7,5,6,2,5,10,1,4,2,9,1,1,11,6,1,44,1,3,7,9,5,1,3,1,1,10,7,1,10,4,2,7,21,15,7,2,5,1,8,3,4,1,3,1,6,1,4,2,1,4,10,8,1,4,5, + 1,5,10,2,7,1,10,1,1,3,4,11,10,29,4,7,3,5,2,3,33,5,2,19,3,1,4,2,6,31,11,1,3,3,3,1,8,10,9,12,11,12,8,3,14,8,6,11,1,4,41,3,1,2,7,13,1,5,6,2,6,12, + 12,22,5,9,4,8,9,9,34,6,24,1,1,20,9,9,3,4,1,7,2,2,2,6,2,28,5,3,6,1,4,6,7,4,2,1,4,2,13,6,4,4,3,1,8,8,3,2,1,5,1,2,2,3,1,11,11,7,3,6,10,8,6,16,16, + 22,7,12,6,21,5,4,6,6,3,6,1,3,2,1,2,8,29,1,10,1,6,13,6,6,19,31,1,13,4,4,22,17,26,33,10,4,15,12,25,6,67,10,2,3,1,6,10,2,6,2,9,1,9,4,4,1,2,16,2, + 5,9,2,3,8,1,8,3,9,4,8,6,4,8,11,3,2,1,1,3,26,1,7,5,1,11,1,5,3,5,2,13,6,39,5,1,5,2,11,6,10,5,1,15,5,3,6,19,21,22,2,4,1,6,1,8,1,4,8,2,4,2,2,9,2, + 1,1,1,4,3,6,3,12,7,1,14,2,4,10,2,13,1,17,7,3,2,1,3,2,13,7,14,12,3,1,29,2,8,9,15,14,9,14,1,3,1,6,5,9,11,3,38,43,20,7,7,8,5,15,12,19,15,81,8,7, + 1,5,73,13,37,28,8,8,1,15,18,20,165,28,1,6,11,8,4,14,7,15,1,3,3,6,4,1,7,14,1,1,11,30,1,5,1,4,14,1,4,2,7,52,2,6,29,3,1,9,1,21,3,5,1,26,3,11,14, + 11,1,17,5,1,2,1,3,2,8,1,2,9,12,1,1,2,3,8,3,24,12,7,7,5,17,3,3,3,1,23,10,4,4,6,3,1,16,17,22,3,10,21,16,16,6,4,10,2,1,1,2,8,8,6,5,3,3,3,39,25, + 15,1,1,16,6,7,25,15,6,6,12,1,22,13,1,4,9,5,12,2,9,1,12,28,8,3,5,10,22,60,1,2,40,4,61,63,4,1,13,12,1,4,31,12,1,14,89,5,16,6,29,14,2,5,49,18,18, + 5,29,33,47,1,17,1,19,12,2,9,7,39,12,3,7,12,39,3,1,46,4,12,3,8,9,5,31,15,18,3,2,2,66,19,13,17,5,3,46,124,13,57,34,2,5,4,5,8,1,1,1,4,3,1,17,5, + 3,5,3,1,8,5,6,3,27,3,26,7,12,7,2,17,3,7,18,78,16,4,36,1,2,1,6,2,1,39,17,7,4,13,4,4,4,1,10,4,2,4,6,3,10,1,19,1,26,2,4,33,2,73,47,7,3,8,2,4,15, + 18,1,29,2,41,14,1,21,16,41,7,39,25,13,44,2,2,10,1,13,7,1,7,3,5,20,4,8,2,49,1,10,6,1,6,7,10,7,11,16,3,12,20,4,10,3,1,2,11,2,28,9,2,4,7,2,15,1, + 27,1,28,17,4,5,10,7,3,24,10,11,6,26,3,2,7,2,2,49,16,10,16,15,4,5,27,61,30,14,38,22,2,7,5,1,3,12,23,24,17,17,3,3,2,4,1,6,2,7,5,1,1,5,1,1,9,4, + 1,3,6,1,8,2,8,4,14,3,5,11,4,1,3,32,1,19,4,1,13,11,5,2,1,8,6,8,1,6,5,13,3,23,11,5,3,16,3,9,10,1,24,3,198,52,4,2,2,5,14,5,4,22,5,20,4,11,6,41, + 1,5,2,2,11,5,2,28,35,8,22,3,18,3,10,7,5,3,4,1,5,3,8,9,3,6,2,16,22,4,5,5,3,3,18,23,2,6,23,5,27,8,1,33,2,12,43,16,5,2,3,6,1,20,4,2,9,7,1,11,2, + 10,3,14,31,9,3,25,18,20,2,5,5,26,14,1,11,17,12,40,19,9,6,31,83,2,7,9,19,78,12,14,21,76,12,113,79,34,4,1,1,61,18,85,10,2,2,13,31,11,50,6,33,159, + 179,6,6,7,4,4,2,4,2,5,8,7,20,32,22,1,3,10,6,7,28,5,10,9,2,77,19,13,2,5,1,4,4,7,4,13,3,9,31,17,3,26,2,6,6,5,4,1,7,11,3,4,2,1,6,2,20,4,1,9,2,6, + 3,7,1,1,1,20,2,3,1,6,2,3,6,2,4,8,1,5,13,8,4,11,23,1,10,6,2,1,3,21,2,2,4,24,31,4,10,10,2,5,192,15,4,16,7,9,51,1,2,1,1,5,1,1,2,1,3,5,3,1,3,4,1, + 3,1,3,3,9,8,1,2,2,2,4,4,18,12,92,2,10,4,3,14,5,25,16,42,4,14,4,2,21,5,126,30,31,2,1,5,13,3,22,5,6,6,20,12,1,14,12,87,3,19,1,8,2,9,9,3,3,23,2, + 3,7,6,3,1,2,3,9,1,3,1,6,3,2,1,3,11,3,1,6,10,3,2,3,1,2,1,5,1,1,11,3,6,4,1,7,2,1,2,5,5,34,4,14,18,4,19,7,5,8,2,6,79,1,5,2,14,8,2,9,2,1,36,28,16, + 4,1,1,1,2,12,6,42,39,16,23,7,15,15,3,2,12,7,21,64,6,9,28,8,12,3,3,41,59,24,51,55,57,294,9,9,2,6,2,15,1,2,13,38,90,9,9,9,3,11,7,1,1,1,5,6,3,2, + 1,2,2,3,8,1,4,4,1,5,7,1,4,3,20,4,9,1,1,1,5,5,17,1,5,2,6,2,4,1,4,5,7,3,18,11,11,32,7,5,4,7,11,127,8,4,3,3,1,10,1,1,6,21,14,1,16,1,7,1,3,6,9,65, + 51,4,3,13,3,10,1,1,12,9,21,110,3,19,24,1,1,10,62,4,1,29,42,78,28,20,18,82,6,3,15,6,84,58,253,15,155,264,15,21,9,14,7,58,40,39, + }; + static ImWchar base_ranges[] = // not zero-terminated + { + 0x0020, 0x00FF, // Basic Latin + Latin Supplement + 0x3000, 0x30FF, // Punctuations, Hiragana, Katakana + 0x31F0, 0x31FF, // Katakana Phonetic Extensions + 0xFF00, 0xFFEF, // Half-width characters + }; + static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(accumulative_offsets_from_0x4E00)*2 + 1] = { 0 }; + if (!full_ranges[0]) + { + memcpy(full_ranges, base_ranges, sizeof(base_ranges)); + UnpackAccumulativeOffsetsIntoRanges(0x4E00, accumulative_offsets_from_0x4E00, IM_ARRAYSIZE(accumulative_offsets_from_0x4E00), full_ranges + IM_ARRAYSIZE(base_ranges)); } return &full_ranges[0]; } diff --git a/misc/fonts/README.txt b/misc/fonts/README.txt index b42a0721..6209fd7e 100644 --- a/misc/fonts/README.txt +++ b/misc/fonts/README.txt @@ -15,7 +15,6 @@ In this document: - Fonts Loading Instructions - FreeType rasterizer, Small font sizes - Building Custom Glyph Ranges -- Remapping Codepoints - Embedding Fonts in Source Code - Credits/Licences for fonts included in this folder - Links, Other fonts @@ -27,7 +26,9 @@ In this document: - You can use the style editor ImGui::ShowStyleEditor() to browse your fonts and understand what's going on if you have an issue. - Make sure your font ranges data are persistent (available during the call to GetTexDataAsAlpha8()/GetTexDataAsRGBA32()/Build(). - - Use C++11 u8"my text" syntax to encode literal strings as UTF-8. + - Use C++11 u8"my text" syntax to encode literal strings as UTF-8. e.g.: + u8"hello" + u8"こんにちは" // this will be encoded as UTF-8 - If you want to include a backslash \ character in your string literal, you need to double them e.g. "folder\\filename". @@ -122,12 +123,13 @@ In this document: // Basic Latin, Extended Latin io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesDefault()); - // Include full set of about 21000 CJK Unified Ideographs - io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesJapanese()); + // Default + Selection of 2500 Ideographs used by Simplified Chinese + io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesChineseSimplifiedCommon()); // Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs - io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesChinese()); + io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesJapanese()); + See "BUILDING CUSTOM GLYPH RANGES" section to create your own ranges. Offset font vertically by altering the io.Font->DisplayOffset value: ImFont* font = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels); @@ -162,18 +164,6 @@ In this document: io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, ranges.Data); ---------------------------------------- - REMAPPING CODEPOINTS ---------------------------------------- - - All your strings needs to use UTF-8 encoding. Specifying literal in your source code using a local code page (such as CP-923 for Japanese, or CP-1251 for Cyrillic) will NOT work! - In C++11 you can encode a string literal in UTF-8 by using the u8"hello" syntax. Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8. - e.g. - u8"hello" - u8"こんにちは" - You may also try to remap your local codepage characters to their Unicode codepoint using font->AddRemapChar(), but international users may have problems reading/editing your source code. - - --------------------------------------- EMBEDDING FONTS IN SOURCE CODE --------------------------------------- diff --git a/stb_textedit.h b/stb_textedit.h index 270153c1..9e12469b 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -1,10 +1,9 @@ -// [ImGui] this is a slightly modified version of stb_textedit.h 1.9. Those changes would need to be pushed into nothings/stb -// [ImGui] - fixed linestart handler when over last character of multi-line buffer + simplified existing code (#588, #815) -// [ImGui] - fixed a state corruption/crash bug in stb_text_redo and stb_textedit_discard_redo (#715) -// [ImGui] - fixed a crash bug in stb_textedit_discard_redo (#681) +// [ImGui] this is a slightly modified version of stb_textedit.h 1.12. Those changes would need to be pushed into nothings/stb +// [ImGui] - 2018-06: fixed undo/redo after pasting large amount of text (over 32 kb). Redo will still fail when undo buffers are exhausted, but text won't be corrupted (see nothings/stb issue #620) +// [ImGui] - 2018-06: fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321) // [ImGui] - fixed some minor warnings -// stb_textedit.h - v1.9 - public domain - Sean Barrett +// stb_textedit.h - v1.12 - public domain - Sean Barrett // Development of this library was sponsored by RAD Game Tools // // This C header file implements the guts of a multi-line text-editing @@ -23,9 +22,7 @@ // // LICENSE // -// This software is dual-licensed to the public domain and under the following -// license: you are granted a perpetual, irrevocable license to copy, modify, -// publish, and distribute this file as you see fit. +// See end of file for license information. // // // DEPENDENCIES @@ -37,6 +34,9 @@ // // VERSION HISTORY // +// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash +// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield +// 1.10 (2016-10-25) supress warnings about casting away const with -Wcast-qual // 1.9 (2016-08-27) customizable move-by-word // 1.8 (2016-04-02) better keyboard handling when mouse button is down // 1.7 (2015-09-13) change y range handling in case baseline is non-0 @@ -55,12 +55,13 @@ // // Ulf Winklemann: move-by-word in 1.1 // Fabian Giesen: secondary key inputs in 1.5 -// Martins Mozeiko: STB_TEXTEDIT_memmove +// Martins Mozeiko: STB_TEXTEDIT_memmove in 1.6 // // Bugfixes: // Scott Graham // Daniel Keller // Omar Cornut +// Dan Thompson // // USAGE // @@ -90,8 +91,8 @@ // moderate sizes. The undo system does no memory allocations, so // it grows STB_TexteditState by the worst-case storage which is (in bytes): // -// [4 + sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATE_COUNT -// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHAR_COUNT +// [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATE_COUNT +// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHAR_COUNT // // // Implementation mode: @@ -114,7 +115,7 @@ // Symbols that must be the same in header-file and implementation mode: // // STB_TEXTEDIT_CHARTYPE the character type -// STB_TEXTEDIT_POSITIONTYPE small type that a valid cursor position +// STB_TEXTEDIT_POSITIONTYPE small type that is a valid cursor position // STB_TEXTEDIT_UNDOSTATECOUNT the number of undo states to allow // STB_TEXTEDIT_UNDOCHARCOUNT the number of characters to store in the undo buffer // @@ -203,7 +204,7 @@ // void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) // int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) // int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len) -// void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int key) +// void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXEDIT_KEYTYPE key) // // Each of these functions potentially updates the string and updates the // state. @@ -237,7 +238,9 @@ // inputs, set a high bit to distinguish the two; then you can define the // various definitions like STB_TEXTEDIT_K_LEFT have the is-key-event bit // set, and make STB_TEXTEDIT_KEYTOCHAR check that the is-key-event bit is -// clear. +// clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to +// anything other type you wante before including. +// // // When rendering, you can read the cursor position and selection state from // the STB_TexteditState. @@ -297,9 +300,9 @@ typedef struct { // private data STB_TEXTEDIT_POSITIONTYPE where; - short insert_length; - short delete_length; - short char_storage; + STB_TEXTEDIT_POSITIONTYPE insert_length; + STB_TEXTEDIT_POSITIONTYPE delete_length; + int char_storage; } StbUndoRecord; typedef struct @@ -308,7 +311,7 @@ typedef struct StbUndoRecord undo_rec [STB_TEXTEDIT_UNDOSTATECOUNT]; STB_TEXTEDIT_CHARTYPE undo_char[STB_TEXTEDIT_UNDOCHARCOUNT]; short undo_point, redo_point; - short undo_char_point, redo_char_point; + int undo_char_point, redo_char_point; } StbUndoState; typedef struct @@ -450,6 +453,15 @@ static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y) // API click: on mouse down, move the cursor to the clicked location, and reset the selection static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) { + // In single-line mode, just always make y = 0. This lets the drag keep working if the mouse + // goes off the top or bottom of the text + if( state->single_line ) + { + StbTexteditRow r; + STB_TEXTEDIT_LAYOUTROW(&r, str, 0); + y = r.ymin; + } + state->cursor = stb_text_locate_coord(str, x, y); state->select_start = state->cursor; state->select_end = state->cursor; @@ -459,9 +471,21 @@ static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *stat // API drag: on mouse drag, move the cursor and selection endpoint to the clicked location static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) { - int p = stb_text_locate_coord(str, x, y); + int p = 0; + + // In single-line mode, just always make y = 0. This lets the drag keep working if the mouse + // goes off the top or bottom of the text + if( state->single_line ) + { + StbTexteditRow r; + STB_TEXTEDIT_LAYOUTROW(&r, str, 0); + y = r.ymin; + } + if (state->select_start == state->select_end) state->select_start = state->cursor; + + p = stb_text_locate_coord(str, x, y); state->cursor = state->select_end = p; } @@ -677,7 +701,7 @@ static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) } // API paste: replace existing selection with passed-in text -static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *text, int len) +static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len) { // if there's a selection, the paste should delete it stb_textedit_clamp(str, state); @@ -695,8 +719,12 @@ static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state return 0; } +#ifndef STB_TEXTEDIT_KEYTYPE +#define STB_TEXTEDIT_KEYTYPE int +#endif + // API key: process a keyboard input -static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int key) +static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key) { retry: switch (key) { @@ -1073,14 +1101,14 @@ static void stb_textedit_discard_undo(StbUndoState *state) if (state->undo_rec[0].char_storage >= 0) { int n = state->undo_rec[0].insert_length, i; // delete n characters from all other records - state->undo_char_point = state->undo_char_point - (short) n; // vsnet05 - STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) ((size_t)state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE))); + state->undo_char_point -= n; + STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE))); for (i=0; i < state->undo_point; ++i) if (state->undo_rec[i].char_storage >= 0) - state->undo_rec[i].char_storage = state->undo_rec[i].char_storage - (short) n; // vsnet05 // @OPTIMIZE: get rid of char_storage and infer it + state->undo_rec[i].char_storage -= n; // @OPTIMIZE: get rid of char_storage and infer it } --state->undo_point; - STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) ((size_t)state->undo_point*sizeof(state->undo_rec[0]))); + STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0]))); } } @@ -1096,14 +1124,17 @@ static void stb_textedit_discard_redo(StbUndoState *state) // if the k'th undo state has characters, clean those up if (state->undo_rec[k].char_storage >= 0) { int n = state->undo_rec[k].insert_length, i; - // delete n characters from all other records - state->redo_char_point = state->redo_char_point + (short) n; // vsnet05 - STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((size_t)(STB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE))); + // move the remaining redo character data to the end of the buffer + state->redo_char_point += n; + STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((STB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE))); + // adjust the position of all the other records to account for above memmove for (i=state->redo_point; i < k; ++i) if (state->undo_rec[i].char_storage >= 0) - state->undo_rec[i].char_storage = state->undo_rec[i].char_storage + (short) n; // vsnet05 + state->undo_rec[i].char_storage += n; } - STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point, state->undo_rec + state->redo_point-1, (size_t) ((size_t)(STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0]))); + // now move all the redo records towards the end of the buffer; the first one is at 'redo_point' + STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, (size_t) ((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0]))); + // now move redo_point to point to the new one ++state->redo_point; } } @@ -1139,15 +1170,15 @@ static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, return NULL; r->where = pos; - r->insert_length = (short) insert_len; - r->delete_length = (short) delete_len; + r->insert_length = (STB_TEXTEDIT_POSITIONTYPE) insert_len; + r->delete_length = (STB_TEXTEDIT_POSITIONTYPE) delete_len; if (insert_len == 0) { r->char_storage = -1; return NULL; } else { r->char_storage = state->undo_char_point; - state->undo_char_point = state->undo_char_point + (short) insert_len; + state->undo_char_point += insert_len; return &state->undo_char[r->char_storage]; } } @@ -1187,16 +1218,16 @@ static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) // there's definitely room to store the characters eventually while (s->undo_char_point + u.delete_length > s->redo_char_point) { - // there's currently not enough room, so discard a redo record - stb_textedit_discard_redo(s); // should never happen: if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT) return; + // there's currently not enough room, so discard a redo record + stb_textedit_discard_redo(s); } r = &s->undo_rec[s->redo_point-1]; r->char_storage = s->redo_char_point - u.delete_length; - s->redo_char_point = s->redo_char_point - (short) u.delete_length; + s->redo_char_point = s->redo_char_point - u.delete_length; // now save the characters for (i=0; i < u.delete_length; ++i) @@ -1318,4 +1349,61 @@ static void stb_textedit_initialize_state(STB_TexteditState *state, int is_singl { stb_textedit_clear_state(state, is_single_line); } + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif + +static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *ctext, int len) +{ + return stb_textedit_paste_internal(str, state, (STB_TEXTEDIT_CHARTYPE *) ctext, len); +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + #endif//STB_TEXTEDIT_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +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 copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/