diff --git a/include/eepp/core/string.hpp b/include/eepp/core/string.hpp index 082edeb20..15e1675f7 100644 --- a/include/eepp/core/string.hpp +++ b/include/eepp/core/string.hpp @@ -307,6 +307,9 @@ class EE_API String { **/ static String fromUtf8( const std::string& utf8String ); + /** @return The number of codepoints of the utf8 string. */ + static size_t utf8StringLength( const std::string& utf8String ); + /** @brief Default constructor ** This constructor creates an empty string. **/ diff --git a/src/eepp/core/string.cpp b/src/eepp/core/string.cpp index 36fc8a2f5..2e3e71d0d 100644 --- a/src/eepp/core/string.cpp +++ b/src/eepp/core/string.cpp @@ -879,6 +879,25 @@ String String::fromUtf8( const std::string& utf8String ) { return String( utf32 ); } +#define iscont( p ) ( ( *(p)&0xC0 ) == 0x80 ) + +static inline const char* utf8_next( const char* s, const char* e ) { + while ( s < e && iscont( s + 1 ) ) + ++s; + return s < e ? s + 1 : e; +} + +static inline size_t utf8_length( const char* s, const char* e ) { + size_t i = 0; + for ( i = 0; s < e; ++i ) + s = utf8_next( s, e ); + return i; +} + +size_t String::utf8StringLength( const std::string& utf8String ) { + return utf8_length( utf8String.c_str(), utf8String.c_str() + utf8String.length() ); +} + String::operator std::string() const { return toUtf8(); } diff --git a/src/tools/ecode/plugins/linter/linterplugin.cpp b/src/tools/ecode/plugins/linter/linterplugin.cpp index 59eb8ec06..aa1743d56 100644 --- a/src/tools/ecode/plugins/linter/linterplugin.cpp +++ b/src/tools/ecode/plugins/linter/linterplugin.cpp @@ -452,7 +452,7 @@ void LinterPlugin::drawAfterLineText( UICodeEditor* editor, const Int64& index, String string( str ); line.setString( string ); Rectf box( pos - editor->getScreenPos(), { editor->getTextWidth( string ), lineHeight } ); - match.box = box; + match.box[editor] = box; line.draw( pos.x, pos.y + lineHeight * 0.5f ); } } @@ -462,10 +462,10 @@ bool LinterPlugin::onMouseMove( UICodeEditor* editor, const Vector2i& pos, const auto it = mMatches.find( editor->getDocumentRef().get() ); if ( it != mMatches.end() ) { Vector2f localPos( editor->convertToNodeSpace( pos.asFloat() ) ); - for ( const auto& matchIt : it->second ) { + for ( auto& matchIt : it->second ) { auto& matches = matchIt.second; - for ( const auto& match : matches ) { - if ( match.box.contains( localPos ) ) { + for ( auto& match : matches ) { + if ( match.box[editor].contains( localPos ) ) { editor->setTooltipText( match.text ); editor->getTooltip()->setDontAutoHideOnMouseMove( true ); editor->getTooltip()->setPixelsPosition( Vector2f( pos.x, pos.y ) ); diff --git a/src/tools/ecode/plugins/linter/linterplugin.hpp b/src/tools/ecode/plugins/linter/linterplugin.hpp index 0c2fa1cf7..0a406e446 100644 --- a/src/tools/ecode/plugins/linter/linterplugin.hpp +++ b/src/tools/ecode/plugins/linter/linterplugin.hpp @@ -37,7 +37,7 @@ struct LinterMatch { std::string text; TextPosition pos; String::HashType lineCache; - Rectf box; + std::map box; LinterType type{ LinterType::Error }; }; diff --git a/src/tools/ecode/projectsearch.cpp b/src/tools/ecode/projectsearch.cpp index ac095c3cc..baa7f31f8 100644 --- a/src/tools/ecode/projectsearch.cpp +++ b/src/tools/ecode/projectsearch.cpp @@ -35,7 +35,7 @@ static String textLine( const std::string& fileText, const size_t& fromPos, size while ( ++ptr && *ptr != '\0' && *ptr != '\n' ) { } end = ptr - stringStartPtr; - relCol = String( fileText.substr( start, startPtr - nlStartPtr ) ).size(); + relCol = String::utf8StringLength( fileText.substr( start, startPtr - nlStartPtr ) ); // if the line to substract is massive we only get the fist kilobyte of that line, since the // line is only shared for visual aid. return fileText.substr( start, end - start > EE_1KB ? EE_1KB : end - start ); @@ -69,11 +69,12 @@ searchInFileHorspool( const std::string& file, const std::string& text, const bo totNl += countNewLines( fileText, lSearchRes, searchRes ); String str( textLine( caseSensitive ? fileText : fileTextOriginal, searchRes, relCol ) ); - res.push_back( { str, - { { (Int64)totNl, (Int64)relCol }, - { (Int64)totNl, (Int64)( relCol + text.size() ) } }, - searchRes, - static_cast( searchRes + text.size() ) } ); + res.push_back( + { str, + { { (Int64)totNl, (Int64)relCol }, + { (Int64)totNl, (Int64)( relCol + String::utf8StringLength( text ) ) } }, + searchRes, + static_cast( searchRes + text.size() ) } ); lSearchRes = searchRes; searchRes += text.size(); } @@ -188,4 +189,4 @@ void ProjectSearch::find( const std::vector files, std::string stri } } -} +} // namespace ecode diff --git a/src/tools/ecode/uitreeviewglobalsearch.cpp b/src/tools/ecode/uitreeviewglobalsearch.cpp index 39366e7ba..82739b2ab 100644 --- a/src/tools/ecode/uitreeviewglobalsearch.cpp +++ b/src/tools/ecode/uitreeviewglobalsearch.cpp @@ -11,10 +11,11 @@ namespace ecode { UITreeViewGlobalSearch::UITreeViewGlobalSearch( const SyntaxColorScheme& colorScheme, bool searchReplace ) : - UITreeView(), mColorScheme( colorScheme ), mSearchReplace( searchReplace ) { - mLineNumColor = Color::fromString( - mUISceneNode->getRoot()->getUIStyle()->getVariable( "--font-hint" ).getValue() ); -} + UITreeView(), + mLineNumColor( Color::fromString( + mUISceneNode->getRoot()->getUIStyle()->getVariable( "--font-hint" ).getValue() ) ), + mColorScheme( colorScheme ), + mSearchReplace( searchReplace ) {} UIWidget* UITreeViewGlobalSearch::createCell( UIWidget* rowWidget, const ModelIndex& index ) { UITableCell* widget = index.column() == (Int64)getModel()->treeColumn()