From 7ea3149c2dde5b14aff7201b50c96ceb91eab675 Mon Sep 17 00:00:00 2001 From: zufuliu Date: Sun, 10 Dec 2023 20:49:10 +0800 Subject: [PATCH] Sync Scintilla section changes. --- scintilla/call/ScintillaCall.cxx | 12 ++ scintilla/include/Scintilla.h | 5 +- scintilla/include/Scintilla.iface | 12 +- scintilla/include/ScintillaCall.h | 3 + scintilla/include/ScintillaMessages.h | 5 +- scintilla/src/CellBuffer.cxx | 4 + scintilla/src/Editor.cxx | 164 +++++++++++++++++--------- scintilla/src/Editor.h | 4 + scintilla/src/Selection.cxx | 7 ++ scintilla/src/Selection.h | 1 + version.txt | 6 +- 11 files changed, 162 insertions(+), 61 deletions(-) diff --git a/scintilla/call/ScintillaCall.cxx b/scintilla/call/ScintillaCall.cxx index 0305368455..fc589435b5 100644 --- a/scintilla/call/ScintillaCall.cxx +++ b/scintilla/call/ScintillaCall.cxx @@ -2286,10 +2286,18 @@ void ScintillaCall::SetSelectionMode(Scintilla::SelectionMode selectionMode) { Call(Message::SetSelectionMode, static_cast(selectionMode)); } +void ScintillaCall::ChangeSelectionMode(Scintilla::SelectionMode selectionMode) { + Call(Message::ChangeSelectionMode, static_cast(selectionMode)); +} + SelectionMode ScintillaCall::SelectionMode() { return static_cast(Call(Message::GetSelectionMode)); } +void ScintillaCall::SetMoveExtendsSelection(bool moveExtendsSelection) { + Call(Message::SetMoveExtendsSelection, moveExtendsSelection); +} + bool ScintillaCall::MoveExtendsSelection() { return Call(Message::GetMoveExtendsSelection); } @@ -2786,6 +2794,10 @@ void ScintillaCall::AddSelection(Position caret, Position anchor) { Call(Message::AddSelection, caret, anchor); } +int ScintillaCall::SelectionFromPoint(int x, int y) { + return static_cast(Call(Message::SelectionFromPoint, x, y)); +} + void ScintillaCall::DropSelectionN(int selection) { Call(Message::DropSelectionN, selection); } diff --git a/scintilla/include/Scintilla.h b/scintilla/include/Scintilla.h index 6c34877db6..956467dff6 100644 --- a/scintilla/include/Scintilla.h +++ b/scintilla/include/Scintilla.h @@ -426,7 +426,7 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP #define SCI_AUTOCGETOPTIONS 2639 #define SCI_AUTOCSETDROPRESTOFWORD 2270 #define SCI_AUTOCGETDROPRESTOFWORD 2271 -#define SCI_SETAUTOINSERTMASK 2474 +#define SCI_SETAUTOINSERTMASK 2109 #define SCI_REGISTERIMAGE 2405 #define SCI_CLEARREGISTEREDIMAGES 2408 #define SCI_AUTOCGETTYPESEPARATOR 2285 @@ -869,7 +869,9 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP #define SC_SEL_LINES 2 #define SC_SEL_THIN 3 #define SCI_SETSELECTIONMODE 2422 +#define SCI_CHANGESELECTIONMODE 2659 #define SCI_GETSELECTIONMODE 2423 +#define SCI_SETMOVEEXTENDSSELECTION 2719 #define SCI_GETMOVEEXTENDSSELECTION 2706 #define SCI_GETLINESELSTARTPOSITION 2424 #define SCI_GETLINESELENDPOSITION 2425 @@ -1011,6 +1013,7 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP #define SCI_CLEARSELECTIONS 2571 #define SCI_SETSELECTION 2572 #define SCI_ADDSELECTION 2573 +#define SCI_SELECTIONFROMPOINT 2474 #define SCI_DROPSELECTIONN 2671 #define SCI_SETMAINSELECTION 2574 #define SCI_GETMAINSELECTION 2575 diff --git a/scintilla/include/Scintilla.iface b/scintilla/include/Scintilla.iface index ba05a55e6d..3b2659fada 100644 --- a/scintilla/include/Scintilla.iface +++ b/scintilla/include/Scintilla.iface @@ -1101,7 +1101,7 @@ set void AutoCSetDropRestOfWord=2270(bool dropRestOfWord,) get bool AutoCGetDropRestOfWord=2271(,) # Set auto insert mask -set void SetAutoInsertMask=2474(int mask,) +set void SetAutoInsertMask=2109(int mask,) # Register an XPM image for use in autocompletion lists. fun void RegisterImage=2405(int type, string xpmData) @@ -2426,9 +2426,16 @@ val SC_SEL_THIN=3 # by lines (SC_SEL_LINES). set void SetSelectionMode=2422(SelectionMode selectionMode,) +# Set the selection mode to stream (SC_SEL_STREAM) or rectangular (SC_SEL_RECTANGLE/SC_SEL_THIN) or +# by lines (SC_SEL_LINES) without changing MoveExtendsSelection. +fun void ChangeSelectionMode=2659(SelectionMode selectionMode,) + # Get the mode of the current selection. get SelectionMode GetSelectionMode=2423(,) +# Set whether or not regular caret moves will extend or reduce the selection. +set void SetMoveExtendsSelection=2719(bool moveExtendsSelection,) + # Get whether or not regular caret moves will extend or reduce the selection. get bool GetMoveExtendsSelection=2706(,) @@ -2857,6 +2864,9 @@ fun void SetSelection=2572(position caret, position anchor) # Add a selection fun void AddSelection=2573(position caret, position anchor) +# Find the selection index for a point. -1 when not at a selection. +fun int SelectionFromPoint=2474(int x, int y) + # Drop one selection fun void DropSelectionN=2671(int selection,) diff --git a/scintilla/include/ScintillaCall.h b/scintilla/include/ScintillaCall.h index de3fc06b62..d62c643dd1 100644 --- a/scintilla/include/ScintillaCall.h +++ b/scintilla/include/ScintillaCall.h @@ -616,7 +616,9 @@ class ScintillaCall { void CopyRange(Position start, Position end); void CopyText(Position length, const char *text); void SetSelectionMode(Scintilla::SelectionMode selectionMode); + void ChangeSelectionMode(Scintilla::SelectionMode selectionMode); Scintilla::SelectionMode SelectionMode(); + void SetMoveExtendsSelection(bool moveExtendsSelection); bool MoveExtendsSelection(); Position GetLineSelStartPosition(Line line); Position GetLineSelEndPosition(Line line); @@ -741,6 +743,7 @@ class ScintillaCall { void ClearSelections(); void SetSelection(Position caret, Position anchor); void AddSelection(Position caret, Position anchor); + int SelectionFromPoint(int x, int y); void DropSelectionN(int selection); void SetMainSelection(int selection); int MainSelection(); diff --git a/scintilla/include/ScintillaMessages.h b/scintilla/include/ScintillaMessages.h index 81adaf6869..3b0e4f76e8 100644 --- a/scintilla/include/ScintillaMessages.h +++ b/scintilla/include/ScintillaMessages.h @@ -210,7 +210,7 @@ enum class Message { AutoCGetOptions = 2639, AutoCSetDropRestOfWord = 2270, AutoCGetDropRestOfWord = 2271, - SetAutoInsertMask = 2474, + SetAutoInsertMask = 2109, RegisterImage = 2405, ClearRegisteredImages = 2408, AutoCGetTypeSeparator = 2285, @@ -539,7 +539,9 @@ enum class Message { CopyRange = 2419, CopyText = 2420, SetSelectionMode = 2422, + ChangeSelectionMode = 2659, GetSelectionMode = 2423, + SetMoveExtendsSelection = 2719, GetMoveExtendsSelection = 2706, GetLineSelStartPosition = 2424, GetLineSelEndPosition = 2425, @@ -655,6 +657,7 @@ enum class Message { ClearSelections = 2571, SetSelection = 2572, AddSelection = 2573, + SelectionFromPoint = 2474, DropSelectionN = 2671, SetMainSelection = 2574, GetMainSelection = 2575, diff --git a/scintilla/src/CellBuffer.cxx b/scintilla/src/CellBuffer.cxx index 7a92c9a59e..c6173d5e53 100644 --- a/scintilla/src/CellBuffer.cxx +++ b/scintilla/src/CellBuffer.cxx @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -758,6 +759,9 @@ const char *CellBuffer::DeleteChars(Sci::Position position, Sci::Position delete } void CellBuffer::Allocate(Sci::Position newSize) { + //if (!largeDocument && (newSize > INT32_MAX)) { + // throw std::runtime_error("CellBuffer::Allocate: size of standard document limited to 2G."); + //} substance.ReAllocate(newSize); if (hasStyles) { style.ReAllocate(newSize); diff --git a/scintilla/src/Editor.cxx b/scintilla/src/Editor.cxx index d910bfe721..6f89295acd 100644 --- a/scintilla/src/Editor.cxx +++ b/scintilla/src/Editor.cxx @@ -4414,8 +4414,6 @@ bool Editor::DragThreshold(Point ptStart, Point ptNow) noexcept { void Editor::StartDrag() { // Always handled by subclasses - //SetMouseCapture(true); - //DisplayCursor(Window::Cursor::::arrow); } void Editor::DropAt(SelectionPosition position, const char *value, size_t lengthValue, bool moving, bool rectangular) { @@ -4522,6 +4520,28 @@ bool Editor::PointInSelection(Point pt) { return false; } +ptrdiff_t Editor::SelectionFromPoint(Point pt) { + // Prioritize checking inside non-empty selections since each character will be inside only 1 + const SelectionPosition posChar = SPositionFromLocation(pt, true, true); + for (size_t r = 0; r < sel.Count(); r++) { + if (sel.Range(r).ContainsCharacter(posChar)) { + return r; + } + } + + // Then check if near empty selections as may be near more than 1 + const SelectionPosition pos = SPositionFromLocation(pt, true, false); + for (size_t r = 0; r < sel.Count(); r++) { + const SelectionRange &range = sel.Range(r); + if ((range.Empty()) && (pos == range.caret)) { + return r; + } + } + + // No selection at point + return -1; +} + bool Editor::PointInSelMargin(Point pt) const noexcept { // Really means: "Point in a margin" if (vs.fixedColumnWidth > 0) { // There is a margin @@ -4546,6 +4566,12 @@ Window::Cursor Editor::GetMarginCursor(Point pt) const noexcept { return Window::Cursor::reverseArrow; } +void Editor::DropSelection(size_t part) noexcept { + sel.DropSelection(part); + ContainerNeedsUpdate(Update::Selection); + Redraw(); +} + void Editor::TrimAndSetSelection(Sci::Position currentPos_, Sci::Position anchor_) { sel.TrimSelection(SelectionRange(currentPos_, anchor_)); SetSelection(currentPos_, anchor_); @@ -4641,10 +4667,10 @@ void Editor::ButtonDownWithModifiers(Point pt, unsigned int curTime, KeyMod modi const bool ctrl = FlagSet(modifiers, KeyMod::Ctrl); const bool shift = FlagSet(modifiers, KeyMod::Shift); const bool alt = FlagSet(modifiers, KeyMod::Alt); - SelectionPosition newPos = SPositionFromLocation(pt, false, false, AllowVirtualSpace(virtualSpaceOptions, alt)); - newPos = MovePositionOutsideChar(newPos, sel.MainCaret() - newPos.Position()); - SelectionPosition newCharPos = SPositionFromLocation(pt, false, true, false); - newCharPos = MovePositionOutsideChar(newCharPos, -1); + const SelectionPosition clickPos = SPositionFromLocation(pt, false, false, AllowVirtualSpace(virtualSpaceOptions, alt)); + const SelectionPosition newPos = MovePositionOutsideChar(clickPos, sel.MainCaret() - clickPos.Position()); + const SelectionPosition newCharPos = MovePositionOutsideChar( + SPositionFromLocation(pt, false, true, false), -1); inDragDrop = DragDrop::none; sel.SetMoveExtends(false); @@ -4653,21 +4679,22 @@ void Editor::ButtonDownWithModifiers(Point pt, unsigned int curTime, KeyMod modi NotifyIndicatorClick(true, newPos.Position(), modifiers); + const bool multiClick = (curTime < (lastClickTime + Platform::DoubleClickTime())) && Close(pt, lastClick, doubleClickCloseThreshold); + lastClickTime = curTime; + lastClick = pt; + const bool inSelMargin = PointInSelMargin(pt); // In margin ctrl+(double)click should always select everything if (ctrl && inSelMargin) { SelectAll(); - lastClickTime = curTime; - lastClick = pt; return; } if (shift && !inSelMargin) { SetSelection(newPos); } - if ((curTime < (lastClickTime + Platform::DoubleClickTime())) && Close(pt, lastClick, doubleClickCloseThreshold)) { + if (multiClick) { //Platform::DebugPrintf("Double click %d %d = %d\n", curTime, lastClickTime, curTime - lastClickTime); - SetMouseCapture(true); - FineTickerStart(TickReason::scroll, 100, 10); + ChangeMouseCapture(true); if (!ctrl || !multipleSelection || (selectionUnit != TextUnit::character && selectionUnit != TextUnit::word)) SetEmptySelection(newPos.Position()); bool doubleClick = false; @@ -4765,21 +4792,32 @@ void Editor::ButtonDownWithModifiers(Point pt, unsigned int curTime, KeyMod modi } SetDragPosition(SelectionPosition(Sci::invalidPosition)); - SetMouseCapture(true); - FineTickerStart(TickReason::scroll, 100, 10); + ChangeMouseCapture(true); } else { if (PointIsHotspot(pt)) { NotifyHotSpotClicked(newCharPos.Position(), modifiers); hotSpotClickPos = newCharPos.Position(); } if (!shift) { - if (PointInSelection(pt) && !SelectionEmpty()) - inDragDrop = DragDrop::initial; - else - inDragDrop = DragDrop::none; + const ptrdiff_t selectionPart = SelectionFromPoint(pt); + if (selectionPart >= 0) { + if (multipleSelection && ctrl) { + // Deselect + if (sel.Count() > 1) { + DropSelection(selectionPart); + // Completed: don't want any more processing of this click + return; + } else { + // Switch to just the click position + SetSelection(newPos, newPos); + } + } + if (!sel.Range(selectionPart).Empty()) { + inDragDrop = DragDrop::initial; + } + } } - SetMouseCapture(true); - FineTickerStart(TickReason::scroll, 100, 10); + ChangeMouseCapture(true); if (inDragDrop != DragDrop::initial) { SetDragPosition(SelectionPosition(Sci::invalidPosition)); if (!shift) { @@ -4809,8 +4847,6 @@ void Editor::ButtonDownWithModifiers(Point pt, unsigned int curTime, KeyMod modi } } } - lastClickTime = curTime; - lastClick = pt; lastXChosen = static_cast(pt.x) + xOffset; ShowCaretAtCurrentPosition(); } @@ -4896,8 +4932,7 @@ void Editor::ButtonMoveWithModifiers(Point pt, unsigned int, KeyMod modifiers) { if (inDragDrop == DragDrop::initial) { if (DragThreshold(ptMouseLast, pt)) { - SetMouseCapture(false); - FineTickerCancel(TickReason::scroll); + ChangeMouseCapture(false); SetDragPosition(movePos); CopySelectionRange(drag); StartDrag(); @@ -5039,8 +5074,7 @@ void Editor::ButtonUpWithModifiers(Point pt, unsigned int curTime, KeyMod modifi SetHotSpotRange(nullptr); } ptMouseLast = pt; - SetMouseCapture(false); - FineTickerCancel(TickReason::scroll); + ChangeMouseCapture(false); NotifyIndicatorClick(false, newPos.Position(), modifiers); if (inDragDrop == DragDrop::dragging) { const SelectionPosition selStart = SelectionStart(); @@ -5173,6 +5207,16 @@ void Editor::FineTickerCancel(TickReason) noexcept { assert(false); } +void Editor::ChangeMouseCapture(bool on) noexcept { + SetMouseCapture(on); + // While mouse captured want timer to scroll automatically + if (on) { + FineTickerStart(TickReason::scroll, 100, 10); + } else { + FineTickerCancel(TickReason::scroll); + } +} + void Editor::SetFocusState(bool focusState) { const bool changing = hasFocus != focusState; hasFocus = focusState; @@ -6034,6 +6078,33 @@ void Editor::SetSelectionNMessage(Message iMessage, uptr_t wParam, sptr_t lParam ContainerNeedsUpdate(Update::Selection); } +namespace { + +constexpr Selection::SelTypes SelTypeFromMode(SelectionMode mode) noexcept { + return static_cast(static_cast(mode) + 1); +} + +} + +void Editor::SetSelectionMode(uptr_t wParam, bool setMoveExtends) { + const Selection::SelTypes newSelType = SelTypeFromMode(static_cast(wParam)); + if (setMoveExtends) { + sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != newSelType)); + } + sel.selType = newSelType; + switch (sel.selType) { + case Selection::SelTypes::rectangle: + sel.Rectangular() = sel.RangeMain(); // adjust current selection + break; + case Selection::SelTypes::lines: + SetSelection(sel.RangeMain().caret, sel.RangeMain().anchor); // adjust current selection + break; + default: + break; + } + InvalidateWholeSelection(); +} + sptr_t Editor::StringResult(sptr_t lParam, const char *val) noexcept { const size_t len = val ? strlen(val) : 0; if (lParam) { @@ -8069,33 +8140,12 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) { case Message::SelectionIsRectangle: return sel.selType == Selection::SelTypes::rectangle ? 1 : 0; - case Message::SetSelectionMode: { - switch (static_cast(wParam)) { - case SelectionMode::Stream: - sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::SelTypes::stream)); - sel.selType = Selection::SelTypes::stream; - break; - case SelectionMode::Rectangle: - sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::SelTypes::rectangle)); - sel.selType = Selection::SelTypes::rectangle; - sel.Rectangular() = sel.RangeMain(); // adjust current selection - break; - case SelectionMode::Lines: - sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::SelTypes::lines)); - sel.selType = Selection::SelTypes::lines; - SetSelection(sel.RangeMain().caret, sel.RangeMain().anchor); // adjust current selection - break; - case SelectionMode::Thin: - sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::SelTypes::thin)); - sel.selType = Selection::SelTypes::thin; - break; - default: - sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::SelTypes::stream)); - sel.selType = Selection::SelTypes::stream; - } - InvalidateWholeSelection(); - break; - } + case Message::SetSelectionMode: + SetSelectionMode(wParam, true); + break; + case Message::ChangeSelectionMode: + SetSelectionMode(wParam, false); + break; case Message::GetSelectionMode: switch (sel.selType) { case Selection::SelTypes::stream: @@ -8109,6 +8159,9 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) { default: // ?! return static_cast(SelectionMode::Stream); } + case Message::SetMoveExtendsSelection: + sel.SetMoveExtends(wParam != 0); + break; case Message::GetMoveExtendsSelection: return sel.MoveExtends(); case Message::GetLineSelStartPosition: @@ -8519,10 +8572,11 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) { Redraw(); break; + case Message::SelectionFromPoint: + return SelectionFromPoint(PointFromParameters(wParam, lParam)); + case Message::DropSelectionN: - sel.DropSelection(PositionFromUPtr(wParam)); - ContainerNeedsUpdate(Update::Selection); - Redraw(); + DropSelection(wParam); break; case Message::SetMainSelection: diff --git a/scintilla/src/Editor.h b/scintilla/src/Editor.h index 27c24a070e..09afad8ea6 100644 --- a/scintilla/src/Editor.h +++ b/scintilla/src/Editor.h @@ -542,8 +542,10 @@ class Editor : public EditModel, public DocWatcher { /** PositionInSelection returns true if position in selection. */ bool PositionInSelection(Sci::Position pos) const noexcept; bool SCICALL PointInSelection(Point pt); + ptrdiff_t SCICALL SelectionFromPoint(Point pt); bool SCICALL PointInSelMargin(Point pt) const noexcept; Window::Cursor GetMarginCursor(Point pt) const noexcept; + void DropSelection(size_t part) noexcept; void TrimAndSetSelection(Sci::Position currentPos_, Sci::Position anchor_); void LineSelection(Sci::Position lineCurrentPos_, Sci::Position lineAnchorPos_, bool wholeLine); void WordSelection(Sci::Position pos); @@ -565,6 +567,7 @@ class Editor : public EditModel, public DocWatcher { virtual bool SetIdle(bool) noexcept { return false; } + void ChangeMouseCapture(bool on) noexcept; virtual void SetMouseCapture(bool on) noexcept = 0; virtual bool HaveMouseCapture() const noexcept = 0; void SetFocusState(bool focusState); @@ -630,6 +633,7 @@ class Editor : public EditModel, public DocWatcher { void StyleSetMessage(Scintilla::Message iMessage, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam); Scintilla::sptr_t StyleGetMessage(Scintilla::Message iMessage, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam); void SetSelectionNMessage(Scintilla::Message iMessage, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam) noexcept; + void SetSelectionMode(uptr_t wParam, bool setMoveExtends); // Coercion functions for transforming WndProc parameters into pointers static void *PtrFromSPtr(Scintilla::sptr_t lParam) noexcept { diff --git a/scintilla/src/Selection.cxx b/scintilla/src/Selection.cxx index d4a5e8f881..9bf1605fcd 100644 --- a/scintilla/src/Selection.cxx +++ b/scintilla/src/Selection.cxx @@ -124,6 +124,13 @@ bool SelectionRange::ContainsCharacter(Sci::Position posCharacter) const noexcep return (posCharacter >= anchor.Position()) && (posCharacter < caret.Position()); } +bool SelectionRange::ContainsCharacter(SelectionPosition spCharacter) const noexcept { + if (anchor > caret) + return (spCharacter >= caret) && (spCharacter < anchor); + else + return (spCharacter >= anchor) && (spCharacter < caret); +} + SelectionSegment SelectionRange::Intersect(SelectionSegment check) const noexcept { const SelectionSegment inOrder(caret, anchor); if ((inOrder.start <= check.end) || (inOrder.end >= check.start)) { diff --git a/scintilla/src/Selection.h b/scintilla/src/Selection.h index 0358bd9f43..7cc4296f2b 100644 --- a/scintilla/src/Selection.h +++ b/scintilla/src/Selection.h @@ -121,6 +121,7 @@ struct SelectionRange { bool Contains(Sci::Position pos) const noexcept; bool Contains(SelectionPosition sp) const noexcept; bool ContainsCharacter(Sci::Position posCharacter) const noexcept; + bool ContainsCharacter(SelectionPosition spCharacter) const noexcept; SelectionSegment Intersect(SelectionSegment check) const noexcept; SelectionPosition Start() const noexcept { return (anchor < caret) ? anchor : caret; diff --git a/version.txt b/version.txt index 1d9363f8ec..8326e56351 100644 --- a/version.txt +++ b/version.txt @@ -5,17 +5,17 @@ git clone https://github.com/XhmikosR/notepad2-mod.git Scintilla (upstream) hg clone http://hg.code.sf.net/p/scintilla/code scintilla 5.4.0 -2023-11-18 9428:f634641a8c10 +2023-12-09 9455:dad186dd18a5 Lexilla (upstream) git clone https://github.com/ScintillaOrg/lexilla.git 5.2.9 -2023-11-18 cf7b44e3a2689179918cc28567bbc21d23c55173 +2023-12-04 3f1121ed1af3dfeef75e751ec28af7200c5310b6 SciTE (upstream) hg clone http://hg.code.sf.net/p/scintilla/scite 5.4.0 -2023-11-18 6215:b401c42098d6 +2023-12-04 6230:43295c7effc2 init submodule: git submodule init