]> git.lyx.org Git - features.git/blobdiff - src/lyxfind.cpp
InsetIndex: hide printTree behind a LYX_INSET_INDEX_DEBUG flag
[features.git] / src / lyxfind.cpp
index 3963c9633164c0efe42ff94b8077514cc1d82702..c8fc40947e75643cb281589fc41b62b30508858c 100644 (file)
@@ -14,6 +14,7 @@
  */
 
 #include <config.h>
+#include <iterator>
 
 #include "lyxfind.h"
 
@@ -1110,7 +1111,7 @@ private:
         ** @todo Normalization should also expand macros, if the corresponding
         ** search option was checked.
         **/
-       string normalize(docstring const & s, bool ignore_fomat) const;
+       string convertLF2Space(docstring const & s, bool ignore_fomat) const;
        // normalized string to search
        string par_as_string;
        // regular expression to use for searching
@@ -2423,7 +2424,7 @@ void LatexInfo::buildEntries(bool isPatternString)
        }
        // Ignore language if there is math somewhere in pattern-string
        if (isPatternString) {
-               for (auto s: usedText) {
+               for (auto const & s: usedText) {
                        // Remove entries created in previous search runs
                        keys.erase(s);
                }
@@ -3668,7 +3669,7 @@ MatchStringAdv::MatchStringAdv(lyx::Buffer & buf, FindAndReplaceOptions & opt)
                previous_single_replace = true;
        }
        // When using regexp, braces are hacked already by escape_for_regex()
-       par_as_string = normalize(ds, opt.ignoreformat);
+       par_as_string = convertLF2Space(ds, opt.ignoreformat);
        open_braces = 0;
        close_wildcards = 0;
 
@@ -3774,7 +3775,7 @@ MatchStringAdv::MatchStringAdv(lyx::Buffer & buf, FindAndReplaceOptions & opt)
                        }
                        if (opt.matchword) {
                                modifyRegexForMatchWord(par_as_string);
-                               opt.matchword = false;
+                               // opt.matchword = false;
                        }
                        regexp_str = "(" + lead_as_regexp + ")()" + par_as_string;
                        regexp2_str = "(" + lead_as_regexp + ")(.*?)" + par_as_string;
@@ -3793,7 +3794,7 @@ MatchResult MatchStringAdv::findAux(DocIterator const & cur, int len, MatchStrin
 
        docstring docstr = stringifyFromForSearch(opt, cur, len);
        string str;
-       str = normalize(docstr, opt.ignoreformat);
+       str = convertLF2Space(docstr, opt.ignoreformat);
        if (!opt.ignoreformat) {
                str = correctlanguagesetting(str, false, !opt.ignoreformat);
                // remove closing '}' and '\n' to allow for use of '$' in regex
@@ -3949,20 +3950,17 @@ MatchResult MatchStringAdv::findAux(DocIterator const & cur, int len, MatchStrin
 MatchResult MatchStringAdv::operator()(DocIterator const & cur, int len, MatchStringAdv::matchType at_begin) const
 {
        MatchResult mres = findAux(cur, len, at_begin);
-       int res = mres.match_len;
        LYXERR(Debug::FINDVERBOSE,
-              "res=" << res << ", at_begin=" << matchTypeAsString(at_begin)
+              "res=" << mres.match_len << ", at_begin=" << matchTypeAsString(at_begin)
               << ", matchAtStart=" << opt.matchAtStart
               << ", inTexted=" << cur.inTexted());
-       if (opt.matchAtStart) {
-               if (cur.pos() != 0)
-                       mres.match_len = 0;
-               else if (mres.match_prefix > 0)
-                       mres.match_len = 0;
-               return mres;
+       if (mres.match_len > 0) {
+               if (opt.matchAtStart) {
+                       if (cur.pos() > 0 || mres.match_prefix > 0)
+                               mres.match_len = 0;
+               }
        }
-       else
-               return mres;
+       return mres;
 }
 
 #if 0
@@ -3990,8 +3988,7 @@ static bool simple_replace(string &t, string from, string to)
 }
 #endif
 
-#if 1
-static string convertLF2Space(docstring const &s, bool ignore_format)
+string MatchStringAdv::convertLF2Space(docstring const &s, bool ignore_format) const
 {
        // Using original docstring to handle '\n'
 
@@ -4058,77 +4055,6 @@ static string convertLF2Space(docstring const &s, bool ignore_format)
        return(t.str());
 }
 
-#else
-static string convertLF2Space(docstring const & s, bool ignore_format)
-{
-       // Using utf8-converted string to handle '\n'
-
-       string t;
-       t = lyx::to_utf8(s);
-       // Remove \n at begin
-       while (!t.empty() && t[0] == '\n')
-               t = t.substr(1);
-       // Remove \n* at end
-       while (!t.empty() && t[t.size() - 1] == '\n') {
-               t = t.substr(0, t.size() - 1);
-       }
-       size_t pos;
-       // Handle all other '\n'
-       while ((pos = t.find("\n")) != string::npos) {
-               if (pos > 1 && t[pos-1] == '\\' && t[pos-2] == '\\' ) {
-                       // Handle '\\\n'
-                       if (isPrintableNonspace(t[pos+1]) && ((pos < 3) || isPrintableNonspace(t[pos-3]))) {
-                               t.replace(pos-2, 3, " ");
-                       }
-                       else {
-                               // Already a space there
-                               t.replace(pos-2, 3, "");
-                       }
-               }
-               else {
-                       if (!isAlnumASCII(t[pos+1]) || !isAlnumASCII(t[pos-1])) {
-                               // '\n' adjacent to non-alpha-numerics, discard
-                               t.replace(pos, 1, "");
-                       }
-                       else {
-                               // Replace all other \n with spaces
-                               t.replace(pos, 1, " ");
-                       }
-                       if (!ignore_format) {
-                               size_t count = 0;
-                               while ((pos > count + 1) && (t[pos - 1 -count] == '%')) {
-                                       count++;
-                               }
-                               if (count > 0) {
-                                       t.replace(pos - count, count, "");
-                               }
-                       }
-               }
-       }
-       return(t);
-
-}
-#endif
-
-string MatchStringAdv::normalize(docstring const & s, bool ignore_format) const
-{
-       string t = convertLF2Space(s, ignore_format);
-
-       // The following replaces are not appropriate in non-format-search mode
-       if (!ignore_format) {
-               // Remove stale empty \emph{}, \textbf{} and similar blocks from latexify
-               // Kornel: Added textsl, textsf, textit, texttt and noun
-               // + allow to seach for colored text too
-               LYXERR(Debug::FINDVERBOSE, "Removing stale empty macros from: " << t);
-               while (regex_replace(t, t, "\\\\(emph|noun|text(bf|sl|sf|it|tt)|(u|uu)line|(s|x)out|uwave)(\\{(\\{\\})?\\})+", ""))
-                       LYXERR(Debug::FINDVERBOSE, "  further removing stale empty \\emph{}, \\textbf{} macros from: " << t);
-               while (regex_replace(t, t, "\\\\((sub)?(((sub)?section)|paragraph)|part)\\*?(\\{(\\{\\})?\\})+", ""))
-                       LYXERR(Debug::FINDVERBOSE, "  further removing stale empty \\section{}, \\part{}, \\paragraph{} macros from: " << t);
-               while (regex_replace(t, t, "\\\\(foreignlanguage|textcolor|item)\\{[a-z]+\\}(\\{(\\{\\})?\\})+", ""));
-       }
-       return t;
-}
-
 docstring stringifyFromCursor(DocIterator const & cur, int len)
 {
        LYXERR(Debug::FINDVERBOSE, "Stringifying with len=" << len << " from cursor at pos: " << cur);
@@ -4513,7 +4439,7 @@ int findForwardAdv(DocIterator & cur, MatchStringAdv & match)
                                        default:
                                                // Todo@
                                                // Handle not like MatchResult::newIsTooFar
-                                               LYXERR0( "Probably too far: Increment = " << increment << " match_prefix = " << mres.match_prefix);
+                                               LYXERR(Debug::FINDVERBOSE, "Probably too far: Increment = " << increment << " match_prefix = " << mres.match_prefix);
                                                firstInvalid--;
                                                increment = increment*3/4;
                                                cur = old_cur;
@@ -4566,7 +4492,8 @@ MatchResult findMostBackwards(DocIterator & cur, MatchStringAdv const & match, M
                LYXERR(Debug::FINDVERBOSE, "findMostBackwards(): cur=" << cur);
                DocIterator new_cur = cur;
                new_cur.backwardPos();
-               if (new_cur == cur || &new_cur.inset() != &inset || !match(new_cur, -1, MatchStringAdv::MatchFromStart).match_len)
+               if (new_cur == cur || &new_cur.inset() != &inset
+                   || match(new_cur, -1, MatchStringAdv::MatchFromStart).match_len <= 0)
                        break;
                MatchResult new_mr = findAdvFinalize(new_cur, match, expected);
                if (new_mr.match_len == mr.match_len)
@@ -4764,7 +4691,7 @@ static int findAdvReplace(BufferView * bv, FindAndReplaceOptions const & opt, Ma
                return 0;
        LASSERT(sel_len > 0, return 0);
 
-       if (!matchAdv(sel_beg, sel_len, MatchStringAdv::MatchFromStart).match_len)
+       if (matchAdv(sel_beg, sel_len, MatchStringAdv::MatchFromStart).match_len <= 0)
                return 0;
 
        // Build a copy of the replace buffer, adapted to the KeepCase option
@@ -4832,6 +4759,10 @@ static int findAdvReplace(BufferView * bv, FindAndReplaceOptions const & opt, Ma
        return 1;
 }
 
+static bool isWordChar(char_type c)
+{
+       return isLetterChar(c) || isNumberChar(c);
+}
 
 /// Perform a FindAdv operation.
 bool findAdv(BufferView * bv, FindAndReplaceOptions & opt)
@@ -4857,8 +4788,52 @@ bool findAdv(BufferView * bv, FindAndReplaceOptions & opt)
                        bv->putSelectionAt(bv->cursor().selectionBegin(), length, !opt.forward);
                num_replaced += findAdvReplace(bv, opt, matchAdv);
                cur = bv->cursor();
-               if (opt.forward)
+               if (opt.forward) {
+                       if (opt.matchword && cur.pos() > 0) {  // Skip word-characters if we are in the mid of a word
+                               if (cur.inTexted()) {
+                                       Paragraph const & par = cur.paragraph();
+                                       int len_limit, new_pos;
+                                       if (cur.lastpos() < par.size())
+                                               len_limit = cur.lastpos();
+                                       else
+                                               len_limit = par.size();
+                                       for (new_pos = cur.pos() - 1; new_pos < len_limit; new_pos++) {
+                                               if (!isWordChar(par.getChar(new_pos)))
+                                                       break;
+                                       }
+                                       if (new_pos > cur.pos())
+                                               cur.pos() = new_pos;
+                               }
+                               else if (cur.inMathed()) {
+                                       // Check if 'cur.pos()-1' and 'cur.pos()' both point to a letter,
+                                       // I am not sure, we should consider the selection
+                                       bool sel = bv->cursor().selection();
+                                       if (!sel && cur.pos() < cur.lastpos()) {
+                                               CursorSlice const & cs = cur.top();
+                                               MathData md = cs.cell();
+                                               int len = -1;
+                                               MathData::const_iterator it_end = md.end();
+                                               MathData md2;
+                                               // Start the check with one character before actual cursor position
+                                               for (MathData::const_iterator it = md.begin() + cs.pos() - 1;
+                                                   it != it_end; ++it)
+                                                       md2.push_back(*it);
+                                               docstring inp = asString(md2);
+                                               for (len = 0; (unsigned) len < inp.size() && len + cur.pos() <= cur.lastpos(); len++) {
+                                                       if (!isWordChar(inp[len]))
+                                                               break;
+                                               }
+                                               // len == 0 means previous char was a word separator
+                                               // len == 1       search starts with a word separator
+                                               // len == 2 ...   we have to skip len -1 chars
+                                               if (len > 1)
+                                                       cur.pos() = cur.pos() + len - 1;
+                                       }
+                               }
+                               opt.matchword = false;
+                       }
                        pos_len = findForwardAdv(cur, matchAdv);
+               }
                else
                        pos_len = findBackwardsAdv(cur, matchAdv);
        } catch (exception & ex) {