diff --git a/include/eepp/ui/doc/syntaxtokenizer.hpp b/include/eepp/ui/doc/syntaxtokenizer.hpp index 4e01fc6b2..30c543676 100644 --- a/include/eepp/ui/doc/syntaxtokenizer.hpp +++ b/include/eepp/ui/doc/syntaxtokenizer.hpp @@ -20,7 +20,7 @@ struct EE_API SyntaxToken { struct EE_API SyntaxTokenPosition { // TODO: type should be the hash of the name of the type. Using std::string takes at least - // 40 bytes per token vs 4 bytes. It's much easier to debug a string than a hash and that's + // 32 bytes per token vs 4 bytes. It's much easier to debug a string than a hash and that's // the reason why we keep it for the moment. std::string type; Int64 pos{ 0 }; diff --git a/include/eepp/ui/uicodeeditor.hpp b/include/eepp/ui/uicodeeditor.hpp index d50411ba5..33d1e2510 100644 --- a/include/eepp/ui/uicodeeditor.hpp +++ b/include/eepp/ui/uicodeeditor.hpp @@ -504,8 +504,11 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { void scrollToCursor( bool centered = true ); - void scrollTo( const TextPosition& position, bool centered = false, - bool forceExactPosition = false, bool scrollX = true ); + void scrollTo( TextRange position, bool centered = false, bool forceExactPosition = false, + bool scrollX = true ); + + void scrollTo( TextPosition position, bool centered = false, bool forceExactPosition = false, + bool scrollX = true ); const MinimapConfig& getMinimapConfig() const; @@ -615,9 +618,9 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { size_t getJumpLinesLength() const; - void setJumpLinesLength(size_t jumpLinesLength); + void setJumpLinesLength( size_t jumpLinesLength ); - protected: + protected: struct LastXOffset { TextPosition position{ 0, 0 }; Float offset{ 0.f }; diff --git a/projects/linux/ee.config b/projects/linux/ee.config index 9358a2eb0..f43f359f8 100644 --- a/projects/linux/ee.config +++ b/projects/linux/ee.config @@ -13,3 +13,4 @@ #define DR_MP3_IMPLEMENTATION #define DR_FLAC_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION +#define ECODE_USE_BACKWARD diff --git a/projects/linux/ee.creator.user b/projects/linux/ee.creator.user index 91225aca3..5a45c8017 100644 --- a/projects/linux/ee.creator.user +++ b/projects/linux/ee.creator.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -236,6 +236,7 @@ -e config=release -e verbose=true + make true GenericProjectManager.GenericMakeStep diff --git a/projects/linux/ee.includes b/projects/linux/ee.includes index 98e9eee8b..0be1d9fbd 100644 --- a/projects/linux/ee.includes +++ b/projects/linux/ee.includes @@ -6,8 +6,6 @@ ../../src/thirdparty/efsw/src ../../src/thirdparty/libvorbis/include ../../src/thirdparty/mbedtls/include -/usr/include/freetype2/ -/usr/lib64/gcc/x86_64-suse-linux/10/include ../../src/modules/eterm/src/ ../../src/modules/eterm/include/ ../../src/modules/maps/include/ @@ -15,3 +13,4 @@ ../../src/modules/physics/include/ ../../src/modules/physics/src/ ../../src/tools/ecode +/usr/include/freetype2/ diff --git a/src/eepp/ui/css/stylesheetparser.cpp b/src/eepp/ui/css/stylesheetparser.cpp index 0803d53b1..133e558f1 100644 --- a/src/eepp/ui/css/stylesheetparser.cpp +++ b/src/eepp/ui/css/stylesheetparser.cpp @@ -100,6 +100,10 @@ bool StyleSheetParser::parse( std::string& css, std::vector& import std::size_t pos = 0; std::string buffer; + // Check UTF-8 BOM header + if ( css.size() >= 3 && (char)0xef == css[0] && (char)0xbb == css[1] && (char)0xbf == css[2] ) + pos = 3; // skip BOM header + while ( pos < css.size() ) { switch ( rs ) { case ReadingSelector: { diff --git a/src/eepp/ui/tools/uicodeeditorsplitter.cpp b/src/eepp/ui/tools/uicodeeditorsplitter.cpp index 2df1fe5f1..516a9ed77 100644 --- a/src/eepp/ui/tools/uicodeeditorsplitter.cpp +++ b/src/eepp/ui/tools/uicodeeditorsplitter.cpp @@ -647,8 +647,10 @@ UITabWidget* UICodeEditorSplitter::createEditorWithTabWidget( Node* parent, bool mAboutToAddEditor = editorData.second; // Open same document in the new split if ( openCurEditor && prevCurEditor && prevCurEditor != editorData.second && - !prevCurEditor->getDocument().isEmpty() ) + !prevCurEditor->getDocument().isEmpty() ) { editorData.second->setDocument( prevCurEditor->getDocumentRef() ); + editorData.second->goToLine( prevCurEditor->getDocument().getSelection().start() ); + } mAboutToAddEditor = nullptr; Lock l( mTabWidgetMutex ); mTabWidgets.push_back( tabWidget ); diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index 86a0f84c4..a814fde6b 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -1496,7 +1496,7 @@ void UICodeEditor::updateScrollBar() { void UICodeEditor::goToLine( const TextPosition& position, bool centered, bool forceExactPosition, bool scrollX ) { mDoc->setSelection( position ); - scrollTo( mDoc->getSelection().start(), centered, forceExactPosition, scrollX ); + scrollTo( mDoc->getSelection(), centered, forceExactPosition, scrollX ); } bool UICodeEditor::getAutoCloseBrackets() const { @@ -1568,13 +1568,13 @@ void UICodeEditor::copyFilePath( bool copyPosition ) { } void UICodeEditor::scrollToCursor( bool centered ) { - scrollTo( mDoc->getSelection().start(), centered ); + scrollTo( mDoc->getSelection(), centered ); } void UICodeEditor::updateEditor() { mDoc->setPageSize( getVisibleLinesCount() ); if ( mDirtyScroll && mDoc->getActiveClient() == this ) - scrollTo( mDoc->getSelection().start() ); + scrollTo( mDoc->getSelection() ); updateScrollBar(); mDirtyEditor = false; mDirtyScroll = false; @@ -1682,34 +1682,42 @@ void UICodeEditor::setLineSpacing( const StyleSheetLength& lineSpace ) { } } -void UICodeEditor::scrollTo( const TextPosition& position, bool centered, bool forceExactPosition, +void UICodeEditor::scrollTo( TextPosition position, bool centered, bool forceExactPosition, bool scrollX ) { + scrollTo( { position, position }, centered, forceExactPosition, scrollX ); +} + +void UICodeEditor::scrollTo( TextRange position, bool centered, bool forceExactPosition, + bool scrollX ) { + position.normalize(); auto lineRange = getVisibleLineRange(); Int64 minDistance = mHScrollBar->isVisible() ? 3 : 2; - if ( forceExactPosition || position.line() <= (Int64)lineRange.first || - position.line() >= (Int64)lineRange.second - minDistance ) { + if ( forceExactPosition || position.start().line() <= (Int64)lineRange.first || + position.start().line() >= (Int64)lineRange.second - minDistance ) { // Vertical Scroll Float lineHeight = getLineHeight(); - Float min = eefloor( lineHeight * ( eemax( 0, position.line() - 1 ) ) ); - Float max = eefloor( lineHeight * ( position.line() + minDistance ) - mSize.getHeight() ); + Float min = eefloor( lineHeight * ( eemax( 0, position.start().line() - 1 ) ) ); + Float max = + eefloor( lineHeight * ( position.start().line() + minDistance ) - mSize.getHeight() ); Float halfScreenLines = eefloor( mSize.getHeight() / lineHeight * 0.5f ); if ( forceExactPosition ) { - setScrollY( - lineHeight * - ( eemax( 0, position.line() - 1 - ( centered ? halfScreenLines : 0 ) ) ) ); + setScrollY( lineHeight * + ( eemax( 0, position.start().line() - 1 - + ( centered ? halfScreenLines : 0 ) ) ) ); } else if ( min < mScroll.y ) { if ( centered ) { - if ( position.line() - 1 - halfScreenLines >= 0 ) - min = eefloor( lineHeight * - ( eemax( 0, position.line() - 1 - halfScreenLines ) ) ); + if ( position.start().line() - 1 - halfScreenLines >= 0 ) + min = eefloor( lineHeight * ( eemax( 0, position.start().line() - 1 - + halfScreenLines ) ) ); } setScrollY( min ); } else if ( max > mScroll.y ) { if ( centered ) { - max = eefloor( lineHeight * ( position.line() + minDistance + halfScreenLines ) - + max = eefloor( lineHeight * + ( position.start().line() + minDistance + halfScreenLines ) - mSize.getHeight() ); max = eemin( max, getMaxScroll().y ); } @@ -1720,14 +1728,18 @@ void UICodeEditor::scrollTo( const TextPosition& position, bool centered, bool f // Horizontal Scroll if ( !scrollX ) return; - Float offsetX = getXOffsetCol( position ); - Float glyphSize = getGlyphWidth(); - Float minVisibility = glyphSize; + Float offsetXEnd = getXOffsetCol( position.end() ); + Float minVisibility = getGlyphWidth(); Float viewPortWidth = getViewportWidth(); - if ( offsetX + minVisibility > mScroll.x + viewPortWidth ) { - setScrollX( eefloor( eemax( 0.f, offsetX + minVisibility - viewPortWidth ) ) ); - } else if ( offsetX < mScroll.x ) { - setScrollX( eefloor( eemax( 0.f, offsetX - minVisibility ) ) ); + if ( offsetXEnd + minVisibility > mScroll.x + viewPortWidth ) { + setScrollX( eefloor( eemax( 0.f, offsetXEnd + minVisibility - viewPortWidth ) ) ); + } else if ( offsetXEnd < mScroll.x ) { + if ( offsetXEnd - minVisibility < viewPortWidth ) + setScrollX( 0.f ); + else { + Float offsetXStart = getXOffsetCol( position.start() ); + setScrollX( eefloor( eemax( 0.f, offsetXStart - minVisibility ) ) ); + } } } diff --git a/src/thirdparty/backward-cpp/backward.hpp b/src/thirdparty/backward-cpp/backward.hpp index 9e0c4369f..670aa4585 100644 --- a/src/thirdparty/backward-cpp/backward.hpp +++ b/src/thirdparty/backward-cpp/backward.hpp @@ -221,6 +221,13 @@ #include #include #include +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#include +#undef _GNU_SOURCE +#else +#include +#endif #if BACKWARD_HAS_BFD == 1 // NOTE: defining PACKAGE{,_VERSION} is required before including @@ -233,13 +240,6 @@ #define PACKAGE_VERSION #endif #include -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#include -#undef _GNU_SOURCE -#else -#include -#endif #endif #if BACKWARD_HAS_DW == 1 @@ -254,13 +254,6 @@ #include #include #include -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#include -#undef _GNU_SOURCE -#else -#include -#endif #endif #if (BACKWARD_HAS_BACKTRACE == 1) || (BACKWARD_HAS_BACKTRACE_SYMBOL == 1) @@ -734,6 +727,7 @@ public: } size_t thread_id() const { return 0; } void skip_n_firsts(size_t) {} + void *const *begin() const { return nullptr; } }; class StackTraceImplBase { @@ -817,7 +811,12 @@ public: _index = -1; _depth = depth; _Unwind_Backtrace(&this->backtrace_trampoline, this); - return static_cast(_index); + if (_index == -1) { + // _Unwind_Backtrace has failed to obtain any backtraces + return 0; + } else { + return static_cast(_index); + } } private: @@ -3621,10 +3620,12 @@ public: symOptions |= SYMOPT_LOAD_LINES | SYMOPT_UNDNAME; SymSetOptions(symOptions); EnumProcessModules(process, &module_handles[0], - module_handles.size() * sizeof(HMODULE), &cbNeeded); + static_cast(module_handles.size() * sizeof(HMODULE)), + &cbNeeded); module_handles.resize(cbNeeded / sizeof(HMODULE)); EnumProcessModules(process, &module_handles[0], - module_handles.size() * sizeof(HMODULE), &cbNeeded); + static_cast(module_handles.size() * sizeof(HMODULE)), + &cbNeeded); std::transform(module_handles.begin(), module_handles.end(), std::back_inserter(modules), get_mod_info(process)); void *base = modules[0].base_address; @@ -3808,11 +3809,18 @@ public: } #endif + // Allow adding to paths gotten from BACKWARD_CXX_SOURCE_PREFIXES after loading the + // library; this can be useful when the library is loaded when the locations are unknown + // Warning: Because this edits the static paths variable, it is *not* intrinsiclly thread safe + static void add_paths_to_env_variable_impl(const std::string & to_add) { + get_mutable_paths_from_env_variable().push_back(to_add); + } + private: details::handle > _file; - std::vector get_paths_from_env_variable_impl() { + static std::vector get_paths_from_env_variable_impl() { std::vector paths; const char *prefixes_str = std::getenv("BACKWARD_CXX_SOURCE_PREFIXES"); if (prefixes_str && prefixes_str[0]) { @@ -3821,9 +3829,13 @@ private: return paths; } - const std::vector &get_paths_from_env_variable() { - static std::vector paths = get_paths_from_env_variable_impl(); - return paths; + static std::vector &get_mutable_paths_from_env_variable() { + static volatile std::vector paths = get_paths_from_env_variable_impl(); + return const_cast&>(paths); + } + + static const std::vector &get_paths_from_env_variable() { + return get_mutable_paths_from_env_variable(); } #ifdef BACKWARD_ATLEAST_CXX11 @@ -3991,10 +4003,12 @@ public: bool object; int inliner_context_size; int trace_context_size; + bool reverse; Printer() : snippet(true), color_mode(ColorMode::automatic), address(false), - object(false), inliner_context_size(5), trace_context_size(7) {} + object(false), inliner_context_size(5), trace_context_size(7), + reverse(true) {} template FILE *print(ST &st, FILE *fp = stderr) { cfile_streambuf obuf(fp); @@ -4041,8 +4055,14 @@ private: void print_stacktrace(ST &st, std::ostream &os, Colorize &colorize) { print_header(os, st.thread_id()); _resolver.load_stacktrace(st); - for (size_t trace_idx = st.size(); trace_idx > 0; --trace_idx) { - print_trace(os, _resolver.resolve(st[trace_idx - 1]), colorize); + if ( reverse ) { + for (size_t trace_idx = st.size(); trace_idx > 0; --trace_idx) { + print_trace(os, _resolver.resolve(st[trace_idx - 1]), colorize); + } + } else { + for (size_t trace_idx = 0; trace_idx < st.size(); ++trace_idx) { + print_trace(os, _resolver.resolve(st[trace_idx]), colorize); + } } } diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index 3758e2756..766dd316d 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -748,7 +748,7 @@ void App::showStatusBar( bool show ) { } ProjectBuildManager* App::getProjectBuildManager() const { - return mProjectBuildManager.get(); + return mProjectBuildManager ? mProjectBuildManager.get() : nullptr; } UITabWidget* App::getSidePanel() const { diff --git a/src/tools/ecode/statusbuildoutputcontroller.cpp b/src/tools/ecode/statusbuildoutputcontroller.cpp index dc1dcf796..28e1c1596 100644 --- a/src/tools/ecode/statusbuildoutputcontroller.cpp +++ b/src/tools/ecode/statusbuildoutputcontroller.cpp @@ -149,7 +149,7 @@ bool StatusBuildOutputController::searchFindAndAddStatusResult( void StatusBuildOutputController::runBuild( const std::string& buildName, const std::string& buildType, const ProjectBuildOutputParser& outputParser ) { - if ( !mApp->getProjectBuildManager() ) + if ( nullptr == mApp->getProjectBuildManager() ) return; auto pbm = mApp->getProjectBuildManager(); @@ -272,7 +272,7 @@ void StatusBuildOutputController::runBuild( const std::string& buildName, void StatusBuildOutputController::runClean( const std::string& buildName, const std::string& buildType, const ProjectBuildOutputParser& outputParser ) { - if ( !mApp->getProjectBuildManager() ) + if ( nullptr == mApp->getProjectBuildManager() ) return; auto pbm = mApp->getProjectBuildManager(); diff --git a/src/tools/ecode/universallocator.cpp b/src/tools/ecode/universallocator.cpp index e5dcecde9..32fed19f7 100644 --- a/src/tools/ecode/universallocator.cpp +++ b/src/tools/ecode/universallocator.cpp @@ -336,6 +336,7 @@ void UniversalLocator::initLocateBar( UILocateBar* locateBar, UITextInput* locat if ( String::startsWith( mLocateInput->getText(), "sb " ) ) { auto pbm = mApp->getProjectBuildManager(); + if ( nullptr == pbm ) return; auto cfg = pbm->getConfig(); std::string buildName = vName.toString(); if ( pbm->hasBuild( buildName ) ) { @@ -346,6 +347,7 @@ void UniversalLocator::initLocateBar( UILocateBar* locateBar, UITextInput* locat return; } else if ( String::startsWith( mLocateInput->getText(), "sbt " ) ) { auto pbm = mApp->getProjectBuildManager(); + if ( nullptr == pbm ) return; auto cfg = pbm->getConfig(); auto build = pbm->getBuild( cfg.buildName ); if ( build != nullptr ) { @@ -410,7 +412,7 @@ void UniversalLocator::updateLocateBarSync() { mLocateTable->setPixelsSize( width, mLocateTable->getRowHeight() * LOCATEBAR_MAX_VISIBLE_ITEMS ); width -= mLocateTable->getVerticalScrollBar()->getPixelsSize().getWidth(); - if ( mLocateTable->getModel()->columnCount() == 2 ) { + if ( mLocateTable->getModel()->columnCount() >= 2 ) { mLocateTable->setColumnsVisible( { 0, 1 } ); mLocateTable->setColumnWidth( 0, eeceil( width * 0.5 ) ); mLocateTable->setColumnWidth( 1, width - mLocateTable->getColumnWidth( 0 ) ); @@ -610,6 +612,8 @@ void UniversalLocator::showSwitchBuild() { std::shared_ptr> UniversalLocator::openBuildModel( const std::string& match ) { + if ( nullptr == mApp->getProjectBuildManager() ) + return ItemListOwnerModel::create( {} ); const auto& builds = mApp->getProjectBuildManager()->getBuilds(); std::vector buildNames; if ( builds.empty() ) @@ -649,6 +653,8 @@ void UniversalLocator::showSwitchBuildType() { std::shared_ptr> UniversalLocator::openBuildTypeModel( const std::string& match ) { + if ( nullptr == mApp->getProjectBuildManager() ) + return ItemListOwnerModel::create( {} ); const auto& builds = mApp->getProjectBuildManager()->getBuilds(); const auto& cfg = mApp->getProjectBuildManager()->getConfig(); @@ -674,7 +680,7 @@ UniversalLocator::openBuildTypeModel( const std::string& match ) { void UniversalLocator::updateSwitchBuildTypeTable() { mLocateTable->setModel( openBuildTypeModel( mLocateInput->getText().substr( 4 ).trim().toUtf8() ) ); - if ( mLocateTable->getModel()->rowCount() > 0 ) { + if ( mLocateTable->getModel()->rowCount() > 0 && nullptr != mApp->getProjectBuildManager() ) { ModelIndex idx = mLocateTable->findRowWithText( mApp->getProjectBuildManager()->getConfig().buildType ); mLocateTable->getSelection().set( idx.isValid() ? idx