Exemplo n.º 1
0
  @Nullable
  private TextRange findIt(
      @NotNull Editor editor,
      int startOffset,
      int count,
      int dir,
      boolean noSmartCase,
      boolean wrap,
      boolean showMessages,
      boolean wholeFile) {
    TextRange res = null;

    if (lastSearch == null || lastSearch.length() == 0) {
      return res;
    }

    /*
    int pflags = RE.REG_MULTILINE;
    if (shouldIgnoreCase(lastSearch, noSmartCase))
    {
        pflags |= RE.REG_ICASE;
    }
    */
    // RE sp;
    RegExp sp;
    RegExp.regmmatch_T regmatch = new RegExp.regmmatch_T();
    regmatch.rmm_ic = shouldIgnoreCase(lastSearch, noSmartCase);
    sp = new RegExp();
    regmatch.regprog = sp.vim_regcomp(lastSearch, 1);
    if (regmatch == null) {
      if (logger.isDebugEnabled()) logger.debug("bad pattern: " + lastSearch);
      return res;
    }

    /*
    int extra_col = 1;
    int startcol = -1;
    boolean found = false;
    boolean match_ok = true;
    LogicalPosition pos = editor.offsetToLogicalPosition(startOffset);
    LogicalPosition endpos = null;
    //REMatch match = null;
    */

    CharacterPosition lpos = EditorHelper.offsetToCharacterPosition(editor, startOffset);
    RegExp.lpos_T pos = new RegExp.lpos_T();
    pos.lnum = lpos.line;
    pos.col = lpos.column;

    int found;
    int lnum; /* no init to shut up Apollo cc */
    // RegExp.regmmatch_T regmatch;
    CharPointer ptr;
    int matchcol;
    int startcol;
    RegExp.lpos_T endpos = new RegExp.lpos_T();
    int loop;
    RegExp.lpos_T start_pos;
    boolean at_first_line;
    int extra_col = 1;
    boolean match_ok;
    long nmatched;
    // int         submatch = 0;
    int first_lnum;

    int lineCount = EditorHelper.getLineCount(editor);
    int startLine = 0;
    int endLine = lineCount;

    do /* loop for count */ {
      start_pos = new RegExp.lpos_T(pos); /* remember start pos for detecting no match */
      found = 0; /* default: not found */
      at_first_line = true; /* default: start in first line */
      if (pos.lnum == -1) /* correct lnum for when starting in line 0 */ {
        pos.lnum = 0;
        pos.col = 0;
        at_first_line = false; /* not in first line now */
      }

      /*
       * Start searching in current line, unless searching backwards and
       * we're in column 0.
       */
      if (dir == -1 && start_pos.col == 0) {
        lnum = pos.lnum - 1;
        at_first_line = false;
      } else {
        lnum = pos.lnum;
      }

      int lcount = EditorHelper.getLineCount(editor);
      for (loop = 0; loop <= 1; ++loop) /* loop twice if 'wrapscan' set */ {
        if (!wholeFile) {
          startLine = lnum;
          endLine = lnum + 1;
        }
        for (; lnum >= startLine && lnum < endLine; lnum += dir, at_first_line = false) {
          /*
           * Look for a match somewhere in the line.
           */
          first_lnum = lnum;
          nmatched = sp.vim_regexec_multi(regmatch, editor, lcount, lnum, 0);
          if (nmatched > 0) {
            /* match may actually be in another line when using \zs */
            lnum += regmatch.startpos[0].lnum;
            ptr = new CharPointer(EditorHelper.getLineBuffer(editor, lnum));
            startcol = regmatch.startpos[0].col;
            endpos = regmatch.endpos[0];

            /*
             * Forward search in the first line: match should be after
             * the start position. If not, continue at the end of the
             * match (this is vi compatible) or on the next char.
             */
            if (dir == 1 && at_first_line) {
              match_ok = true;
              /*
               * When match lands on a NUL the cursor will be put
               * one back afterwards, compare with that position,
               * otherwise "/$" will get stuck on end of line.
               */
              while ((startcol - (startcol == ptr.strlen() ? 1 : 0))
                  < (start_pos.col + extra_col)) {
                if (nmatched > 1) {
                  /* end is in next line, thus no match in
                   * this line */
                  match_ok = false;
                  break;
                }
                matchcol = endpos.col;
                /* for empty match: advance one char */
                if (matchcol == startcol && ptr.charAt(matchcol) != '\u0000') {
                  ++matchcol;
                }
                if (ptr.charAt(matchcol) == '\u0000'
                    || (nmatched = sp.vim_regexec_multi(regmatch, editor, lcount, lnum, matchcol))
                        == 0) {
                  match_ok = false;
                  break;
                }
                startcol = regmatch.startpos[0].col;
                endpos = regmatch.endpos[0];

                /* Need to get the line pointer again, a
                 * multi-line search may have made it invalid. */
                ptr = new CharPointer(EditorHelper.getLineBuffer(editor, lnum));
              }
              if (!match_ok) {
                continue;
              }
            }
            if (dir == -1) {
              /*
               * Now, if there are multiple matches on this line,
               * we have to get the last one. Or the last one before
               * the cursor, if we're on that line.
               * When putting the new cursor at the end, compare
               * relative to the end of the match.
               */
              match_ok = false;
              for (; ; ) {
                if (!at_first_line || (regmatch.startpos[0].col + extra_col <= start_pos.col)) {
                  /* Remember this position, we use it if it's
                   * the last match in the line. */
                  match_ok = true;
                  startcol = regmatch.startpos[0].col;
                  endpos = regmatch.endpos[0];
                } else {
                  break;
                }

                /*
                 * We found a valid match, now check if there is
                 * another one after it.
                 * If vi-compatible searching, continue at the end
                 * of the match, otherwise continue one position
                 * forward.
                 */
                if (nmatched > 1) {
                  break;
                }
                matchcol = endpos.col;
                /* for empty match: advance one char */
                if (matchcol == startcol && ptr.charAt(matchcol) != '\u0000') {
                  ++matchcol;
                }
                if (ptr.charAt(matchcol) == '\u0000'
                    || (nmatched = sp.vim_regexec_multi(regmatch, editor, lcount, lnum, matchcol))
                        == 0) {
                  break;
                }

                /* Need to get the line pointer again, a
                 * multi-line search may have made it invalid. */
                ptr = new CharPointer(EditorHelper.getLineBuffer(editor, lnum));
              }

              /*
               * If there is only a match after the cursor, skip
               * this match.
               */
              if (!match_ok) {
                continue;
              }
            }

            pos.lnum = lnum;
            pos.col = startcol;
            endpos.lnum += first_lnum;
            found = 1;

            /* Set variables used for 'incsearch' highlighting. */
            // search_match_lines = endpos.lnum - (lnum - first_lnum);
            // search_match_endcol = endpos.col;
            break;
          }
          // line_breakcheck();      /* stop if ctrl-C typed */
          // if (got_int)
          //    break;

          if (loop != 0 && lnum == start_pos.lnum) {
            break; /* if second loop, stop where started */
          }
        }
        at_first_line = false;

        /*
         * stop the search if wrapscan isn't set, after an interrupt and
         * after a match
         */
        if (!wrap || found != 0) {
          break;
        }

        /*
         * If 'wrapscan' is set we continue at the other end of the file.
         * If 'shortmess' does not contain 's', we give a message.
         * This message is also remembered in keep_msg for when the screen
         * is redrawn. The keep_msg is cleared whenever another message is
         * written.
         */
        if (dir == -1) /* start second loop at the other end */ {
          lnum = lineCount - 1;
          // if (!shortmess(SHM_SEARCH) && (options & SEARCH_MSG))
          //    give_warning((char_u *)_(top_bot_msg), TRUE);
        } else {
          lnum = 0;
          // if (!shortmess(SHM_SEARCH) && (options & SEARCH_MSG))
          //    give_warning((char_u *)_(bot_top_msg), TRUE);
        }
      }
      // if (got_int || called_emsg || break_loop)
      //    break;
    } while (--count > 0 && found != 0); /* stop after count matches or no match */

    if (found == 0) /* did not find it */ {
      // if ((options & SEARCH_MSG) == SEARCH_MSG)
      if (showMessages) {
        if (wrap) {
          VimPlugin.showMessage(MessageHelper.message(Msg.e_patnotf2, lastSearch));
        } else if (lnum <= 0) {
          VimPlugin.showMessage(MessageHelper.message(Msg.E384, lastSearch));
        } else {
          VimPlugin.showMessage(MessageHelper.message(Msg.E385, lastSearch));
        }
      }
      return null;
    }

    // return new TextRange(editor.logicalPositionToOffset(new LogicalPosition(pos.lnum, pos.col)),
    //    editor.logicalPositionToOffset(new LogicalPosition(endpos.lnum, endpos.col)));
    // return new TextRange(editor.logicalPositionToOffset(new LogicalPosition(pos.lnum, 0)) +
    // pos.col,
    //    editor.logicalPositionToOffset(new LogicalPosition(endpos.lnum, 0)) + endpos.col);
    return new TextRange(
        EditorHelper.characterPositionToOffset(editor, new CharacterPosition(pos.lnum, pos.col)),
        EditorHelper.characterPositionToOffset(
            editor, new CharacterPosition(endpos.lnum, endpos.col)));
  }