Search in sources :

Example 6 with LogicalPosition

use of com.intellij.openapi.editor.LogicalPosition in project ideavim by JetBrains.

the class RegExp method regmatch.

/*
     * regmatch - main matching routine
     *
     * Conceptually the strategy is simple: Check to see whether the current
     * node matches, call self recursively to see whether the rest matches,
     * and then act accordingly.  In practice we make some effort to avoid
     * recursion, in particular by going through "ordinary" nodes (that don't
     * need to know whether the rest of the match failed) by a loop instead of
     * by recursion.
     *
     * Returns true when there is a match.  Leaves reginput and reglnum just after
     * the last matched character.
     * Returns false when there is no match.  Leaves reginput and reglnum in an
     * undefined state!
     */
private boolean regmatch(@Nullable CharPointer scan) {
    CharPointer next;
    /* Next node. */
    int op;
    char c;
    while (scan != null) {
        if (got_int || out_of_stack) {
            return false;
        }
        next = regnext(scan);
        op = scan.OP();
        /* Check for character class with NL added. */
        if (WITH_NL(op) && reginput.isNul() && reglnum < reg_maxline) {
            reg_nextline();
        } else {
            if (WITH_NL(op)) {
                op -= ADD_NL;
            }
            c = reginput.charAt();
            switch(op) {
                case BOL:
                    if (!reginput.equals(regline)) {
                        return false;
                    }
                    break;
                case EOL:
                    if (c != '') {
                        return false;
                    }
                    break;
                case RE_BOF:
                    /* Passing -1 to the getline() function provided for the search
                         * should always return null if the current line is the first
                         * line of the file. */
                    if (reglnum != 0 || !reginput.equals(regline) || (reg_match == null && reg_getline(-1) != null)) {
                        return false;
                    }
                    break;
                case RE_EOF:
                    if (reglnum != reg_maxline || c != '') {
                        return false;
                    }
                    break;
                case CURSOR:
                    /* Check if the buffer is in a window and compare the
                         * reg_win->w_cursor position to the match position. */
                    LogicalPosition curpos = reg_buf.getCaretModel().getLogicalPosition();
                    if (reglnum + reg_firstlnum != curpos.line || reginput.pointer() - regline.pointer() != curpos.column) {
                        return false;
                    }
                    break;
                case RE_LNUM:
                    if (reg_match != null || !re_num_cmp((reglnum + reg_firstlnum), scan)) {
                        return false;
                    }
                    break;
                case RE_COL:
                    if (!re_num_cmp((reginput.pointer() - regline.pointer()) + 1, scan)) {
                        return false;
                    }
                    break;
                case RE_VCOL:
                    /* TODO
                        if (!re_num_cmp(win_linetabsize(reg_win == null ? curwin : reg_win,
                            regline, (int)(reginput - regline)) + 1, scan))
                        {
                            return false;
                        }
                        */
                    break;
                case BOW:
                    /* \<word; reginput points to w */
                    if (c == '') /* Can't match at end of line */
                    {
                        return false;
                    } else {
                        if (!CharacterClasses.isWord(c) || (reginput.pointer() > regline.pointer() && CharacterClasses.isWord(reginput.charAt(-1)))) {
                            return false;
                        }
                    }
                    break;
                case EOW:
                    /* word\>; reginput points after d */
                    if (reginput.equals(regline)) /* Can't match at start of line */
                    {
                        return false;
                    }
                    if (!CharacterClasses.isWord(reginput.charAt(-1))) {
                        return false;
                    }
                    if (!reginput.isNul() && CharacterClasses.isWord(c)) {
                        return false;
                    }
                    break;
                case ANY:
                    if (c == '') {
                        return false;
                    }
                    reginput.inc();
                    break;
                case IDENT:
                    if (!Character.isJavaIdentifierPart(c)) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case SIDENT:
                    if (CharacterClasses.isDigit(reginput.charAt()) || !Character.isJavaIdentifierPart(c)) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case KWORD:
                    if (!CharacterClasses.isWord(reginput.charAt())) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case SKWORD:
                    if (CharacterClasses.isDigit(reginput.charAt()) || !CharacterClasses.isWord(reginput.charAt())) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case FNAME:
                    if (!CharacterClasses.isFile(c)) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case SFNAME:
                    if (CharacterClasses.isDigit(reginput.charAt()) || !CharacterClasses.isFile(c)) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case PRINT:
                    if (!CharacterClasses.isPrint(reginput.charAt())) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case SPRINT:
                    if (CharacterClasses.isDigit(reginput.charAt()) || !CharacterClasses.isPrint(reginput.charAt())) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case WHITE:
                    if (!CharacterClasses.isWhite(c)) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case NWHITE:
                    if (c == '' || CharacterClasses.isWhite(c)) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case DIGIT:
                    if (!CharacterClasses.isDigit(c)) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case NDIGIT:
                    if (c == '' || CharacterClasses.isDigit(c)) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case HEX:
                    if (!CharacterClasses.isHex(c)) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case NHEX:
                    if (c == '' || CharacterClasses.isHex(c)) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case OCTAL:
                    if (!CharacterClasses.isOctal(c)) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case NOCTAL:
                    if (c == '' || CharacterClasses.isOctal(c)) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case WORD:
                    if (!CharacterClasses.isWord(c)) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case NWORD:
                    if (c == '' || CharacterClasses.isWord(c)) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case HEAD:
                    if (!CharacterClasses.isHead(c)) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case NHEAD:
                    if (c == '' || CharacterClasses.isHead(c)) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case ALPHA:
                    if (!CharacterClasses.isAlpha(c)) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case NALPHA:
                    if (c == '' || CharacterClasses.isAlpha(c)) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case LOWER:
                    if (!CharacterClasses.isLower(c)) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case NLOWER:
                    if (c == '' || CharacterClasses.isLower(c)) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case UPPER:
                    if (!CharacterClasses.isUpper(c)) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case NUPPER:
                    if (c == '' || CharacterClasses.isUpper(c)) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case EXACTLY:
                    {
                        int len;
                        CharPointer opnd;
                        opnd = scan.OPERAND();
                        /* Inline the first byte, for speed. */
                        if (opnd.charAt() != reginput.charAt() && (!ireg_ic || Character.toLowerCase(opnd.charAt()) != Character.toLowerCase(reginput.charAt()))) {
                            return false;
                        }
                        if (opnd.charAt(1) == '') {
                            reginput.inc();
                        /* matched a single char */
                        } else {
                            len = opnd.strlen();
                            /* Need to match first byte again for multi-byte. */
                            if (cstrncmp(opnd, reginput, len) != 0) {
                                return false;
                            }
                            reginput.inc(len);
                        }
                    }
                    break;
                case ANYOF:
                case ANYBUT:
                    if (c == '') {
                        return false;
                    }
                    if ((cstrchr(scan.OPERAND(), c) == null) == (op == ANYOF)) {
                        return false;
                    }
                    reginput.inc();
                    break;
                case NOTHING:
                    break;
                case BACK:
                    break;
                case MOPEN:
                /* Match start: \zs */
                case MOPEN + 1:
                /* \( */
                case MOPEN + 2:
                case MOPEN + 3:
                case MOPEN + 4:
                case MOPEN + 5:
                case MOPEN + 6:
                case MOPEN + 7:
                case MOPEN + 8:
                case MOPEN + 9:
                    {
                        int no;
                        save_se_T save = new save_se_T();
                        no = op - MOPEN;
                        cleanup_subexpr();
                        save_se(save, reg_startpos[no], reg_startp[no]);
                        if (regmatch(next)) {
                            return true;
                        }
                        restore_se(save, reg_startpos[no], reg_startp[no]);
                        return false;
                    }
                case NOPEN:
                /* \%( */
                case NCLOSE:
                    /* \) after \%( */
                    return regmatch(next);
                case ZOPEN + 1:
                case ZOPEN + 2:
                case ZOPEN + 3:
                case ZOPEN + 4:
                case ZOPEN + 5:
                case ZOPEN + 6:
                case ZOPEN + 7:
                case ZOPEN + 8:
                case ZOPEN + 9:
                    {
                        int no;
                        save_se_T save = new save_se_T();
                        no = op - ZOPEN;
                        cleanup_zsubexpr();
                        save_se(save, reg_startzpos[no], reg_startzp[no]);
                        if (regmatch(next)) {
                            return true;
                        }
                        restore_se(save, reg_startzpos[no], reg_startzp[no]);
                        return false;
                    }
                case MCLOSE:
                /* Match end: \ze */
                case MCLOSE + 1:
                /* \) */
                case MCLOSE + 2:
                case MCLOSE + 3:
                case MCLOSE + 4:
                case MCLOSE + 5:
                case MCLOSE + 6:
                case MCLOSE + 7:
                case MCLOSE + 8:
                case MCLOSE + 9:
                    {
                        int no;
                        save_se_T save = new save_se_T();
                        no = op - MCLOSE;
                        cleanup_subexpr();
                        save_se(save, reg_endpos[no], reg_endp[no]);
                        if (regmatch(next)) {
                            return true;
                        }
                        restore_se(save, reg_endpos[no], reg_endp[no]);
                        return false;
                    }
                case ZCLOSE + 1:
                /* \) after \z( */
                case ZCLOSE + 2:
                case ZCLOSE + 3:
                case ZCLOSE + 4:
                case ZCLOSE + 5:
                case ZCLOSE + 6:
                case ZCLOSE + 7:
                case ZCLOSE + 8:
                case ZCLOSE + 9:
                    {
                        int no;
                        save_se_T save = new save_se_T();
                        no = op - ZCLOSE;
                        cleanup_zsubexpr();
                        save_se(save, reg_endzpos[no], reg_endzp[no]);
                        if (regmatch(next)) {
                            return true;
                        }
                        restore_se(save, reg_endzpos[no], reg_endzp[no]);
                        return false;
                    }
                case BACKREF + 1:
                case BACKREF + 2:
                case BACKREF + 3:
                case BACKREF + 4:
                case BACKREF + 5:
                case BACKREF + 6:
                case BACKREF + 7:
                case BACKREF + 8:
                case BACKREF + 9:
                    {
                        int no;
                        int len;
                        int clnum;
                        int ccol;
                        CharPointer p;
                        no = op - BACKREF;
                        cleanup_subexpr();
                        if (reg_match != null) /* Single-line regexp */
                        {
                            if (reg_endp[no] == null) {
                                /* Backref was not set: Match an empty string. */
                                len = 0;
                            } else {
                                /* Compare current input with back-ref in the same
                                     * line. */
                                len = reg_endp[no].pointer() - reg_startp[no].pointer();
                                if (cstrncmp(reg_startp[no], reginput, len) != 0) {
                                    return false;
                                }
                            }
                        } else /* Multi-line regexp */
                        {
                            if (reg_endpos[no].lnum < 0) {
                                /* Backref was not set: Match an empty string. */
                                len = 0;
                            } else {
                                if (reg_startpos[no].lnum == reglnum && reg_endpos[no].lnum == reglnum) {
                                    /* Compare back-ref within the current line. */
                                    len = reg_endpos[no].col - reg_startpos[no].col;
                                    if (cstrncmp(regline.ref(reg_startpos[no].col), reginput, len) != 0) {
                                        return false;
                                    }
                                } else {
                                    /* Messy situation: Need to compare between two
                                         * lines. */
                                    ccol = reg_startpos[no].col;
                                    clnum = reg_startpos[no].lnum;
                                    for (; ; ) {
                                        /* Since getting one line may invalidate
                                             * the other, need to make copy.  Slow! */
                                        if (!regline.equals(reg_tofree)) {
                                            reg_tofree = regline.ref(0);
                                            reginput = reg_tofree.ref(reginput.pointer() - regline.pointer());
                                            regline = reg_tofree.ref(0);
                                        }
                                        /* Get the line to compare with. */
                                        p = reg_getline(clnum);
                                        if (clnum == reg_endpos[no].lnum) {
                                            len = reg_endpos[no].col - ccol;
                                        } else {
                                            len = p.ref(ccol).strlen();
                                        }
                                        if (cstrncmp(p.ref(ccol), reginput, len) != 0) {
                                            return false;
                                        /* doesn't match */
                                        }
                                        if (clnum == reg_endpos[no].lnum) {
                                            break;
                                        /* match and at end! */
                                        }
                                        if (reglnum == reg_maxline) {
                                            return false;
                                        /* text too short */
                                        }
                                        /* Advance to next line. */
                                        reg_nextline();
                                        ++clnum;
                                        ccol = 0;
                                        if (got_int || out_of_stack) {
                                            return false;
                                        }
                                    }
                                /* found a match!  Note that regline may now point
                                         * to a copy of the line, that should not matter. */
                                }
                            }
                        }
                        /* Matched the backref, skip over it. */
                        reginput.inc(len);
                    }
                    break;
                case ZREF + 1:
                case ZREF + 2:
                case ZREF + 3:
                case ZREF + 4:
                case ZREF + 5:
                case ZREF + 6:
                case ZREF + 7:
                case ZREF + 8:
                case ZREF + 9:
                    {
                        int no;
                        int len;
                        cleanup_zsubexpr();
                        no = op - ZREF;
                        if (re_extmatch_in != null && re_extmatch_in.matches[no] != null) {
                            len = re_extmatch_in.matches[no].length();
                            if (cstrncmp(new CharPointer(re_extmatch_in.matches[no]), reginput, len) != 0) {
                                return false;
                            }
                            reginput.inc(len);
                        } else {
                        /* Backref was not set: Match an empty string. */
                        }
                    }
                    break;
                case BRANCH:
                    {
                        if (next.OP() != BRANCH) /* No choice. */
                        {
                            next = scan.OPERAND();
                        /* Avoid recursion. */
                        } else {
                            regsave_T save = new regsave_T();
                            do {
                                reg_save(save);
                                if (regmatch(scan.OPERAND())) {
                                    return true;
                                }
                                reg_restore(save);
                                scan = regnext(scan);
                            } while (scan != null && scan.OP() == BRANCH);
                            return false;
                        /* NOTREACHED */
                        }
                    }
                    break;
                case BRACE_LIMITS:
                    {
                        int no;
                        if (next.OP() == BRACE_SIMPLE) {
                            bl_minval = scan.OPERAND_MIN();
                            bl_maxval = scan.OPERAND_MAX();
                        } else if (next.OP() >= BRACE_COMPLEX && next.OP() < BRACE_COMPLEX + 10) {
                            no = next.OP() - BRACE_COMPLEX;
                            brace_min[no] = scan.OPERAND_MIN();
                            brace_max[no] = scan.OPERAND_MAX();
                            brace_count[no] = 0;
                        } else {
                            VimPlugin.showMessage(MessageHelper.message(Msg.e_internal));
                            return false;
                        }
                    }
                    break;
                case BRACE_COMPLEX:
                case BRACE_COMPLEX + 1:
                case BRACE_COMPLEX + 2:
                case BRACE_COMPLEX + 3:
                case BRACE_COMPLEX + 4:
                case BRACE_COMPLEX + 5:
                case BRACE_COMPLEX + 6:
                case BRACE_COMPLEX + 7:
                case BRACE_COMPLEX + 8:
                case BRACE_COMPLEX + 9:
                    {
                        int no;
                        regsave_T save = new regsave_T();
                        no = op - BRACE_COMPLEX;
                        ++brace_count[no];
                        /* If not matched enough times yet, try one more */
                        if (brace_count[no] <= (brace_min[no] <= brace_max[no] ? brace_min[no] : brace_max[no])) {
                            reg_save(save);
                            if (regmatch(scan.OPERAND())) {
                                return true;
                            }
                            reg_restore(save);
                            --brace_count[no];
                            /* failed, decrement match count */
                            return false;
                        }
                        /* If matched enough times, may try matching some more */
                        if (brace_min[no] <= brace_max[no]) {
                            /* Range is the normal way around, use longest match */
                            if (brace_count[no] <= brace_max[no]) {
                                reg_save(save);
                                if (regmatch(scan.OPERAND())) {
                                    return true;
                                /* matched some more times */
                                }
                                reg_restore(save);
                                --brace_count[no];
                            /* matched just enough times */
                            /* continue with the items after \{} */
                            }
                        } else {
                            /* Range is backwards, use shortest match first */
                            if (brace_count[no] <= brace_min[no]) {
                                reg_save(save);
                                if (regmatch(next)) {
                                    return true;
                                }
                                reg_restore(save);
                                next = scan.OPERAND();
                            /* must try to match one more item */
                            }
                        }
                    }
                    break;
                case BRACE_SIMPLE:
                case STAR:
                case PLUS:
                    {
                        char nextb;
                        /* next byte */
                        char nextb_ic;
                        /* next byte reverse case */
                        int count;
                        regsave_T save = new regsave_T();
                        int minval;
                        int maxval;
                        /*
                             * Lookahead to avoid useless match attempts when we know
                             * what character comes next.
                             */
                        if (next.OP() == EXACTLY) {
                            nextb = next.OPERAND().charAt();
                            if (ireg_ic) {
                                if (Character.isUpperCase(nextb)) {
                                    nextb_ic = Character.toLowerCase(nextb);
                                } else {
                                    nextb_ic = Character.toUpperCase(nextb);
                                }
                            } else {
                                nextb_ic = nextb;
                            }
                        } else {
                            nextb = '';
                            nextb_ic = '';
                        }
                        if (op != BRACE_SIMPLE) {
                            minval = (op == STAR) ? 0 : 1;
                            maxval = MAX_LIMIT;
                        } else {
                            minval = bl_minval;
                            maxval = bl_maxval;
                        }
                        /*
                             * When maxval > minval, try matching as much as possible, up
                             * to maxval.  When maxval < minval, try matching at least the
                             * minimal number (since the range is backwards, that's also
                             * maxval!).
                             */
                        count = regrepeat(scan.OPERAND(), maxval);
                        if (got_int) {
                            return false;
                        }
                        if (minval <= maxval) {
                            /* Range is the normal way around, use longest match */
                            while (count >= minval) {
                                /* If it could match, try it. */
                                if (nextb == '' || reginput.charAt() == nextb || reginput.charAt() == nextb_ic) {
                                    reg_save(save);
                                    if (regmatch(next)) {
                                        return true;
                                    }
                                    reg_restore(save);
                                }
                                /* Couldn't or didn't match -- back up one char. */
                                if (--count < minval) {
                                    break;
                                }
                                if (reginput.equals(regline)) {
                                    /* backup to last char of previous line */
                                    --reglnum;
                                    regline = reg_getline(reglnum);
                                    /* Just in case regrepeat() didn't count right. */
                                    if (regline == null) {
                                        return false;
                                    }
                                    reginput = regline.ref(regline.strlen());
                                    // fast_breakcheck(); - TOOD
                                    if (got_int || out_of_stack) {
                                        return false;
                                    }
                                } else {
                                    reginput.dec();
                                }
                            }
                        } else {
                            /* Range is backwards, use shortest match first.
                                 * Careful: maxval and minval are exchanged! */
                            if (count < maxval) {
                                return false;
                            }
                            for (; ; ) {
                                /* If it could work, try it. */
                                if (nextb == '' || reginput.charAt() == nextb || reginput.charAt() == nextb_ic) {
                                    reg_save(save);
                                    if (regmatch(next)) {
                                        return true;
                                    }
                                    reg_restore(save);
                                }
                                /* Couldn't or didn't match: try advancing one char. */
                                if (count == minval || regrepeat(scan.OPERAND(), 1) == 0) {
                                    break;
                                }
                                ++count;
                                if (got_int || out_of_stack) {
                                    return false;
                                }
                            }
                        }
                        return false;
                    }
                case NOMATCH:
                    {
                        regsave_T save = new regsave_T();
                        /* If the operand matches, we fail.  Otherwise backup and
                             * continue with the next item. */
                        reg_save(save);
                        if (regmatch(scan.OPERAND())) {
                            return false;
                        }
                        reg_restore(save);
                    }
                    break;
                case MATCH:
                case SUBPAT:
                    {
                        regsave_T save = new regsave_T();
                        /* If the operand doesn't match, we fail.  Otherwise backup
                             * and continue with the next item. */
                        reg_save(save);
                        if (!regmatch(scan.OPERAND())) {
                            return false;
                        }
                        if (op == MATCH) /* zero-width */
                        {
                            reg_restore(save);
                        }
                    }
                    break;
                case BEHIND:
                case NOBEHIND:
                    {
                        regsave_T save_after = new regsave_T(), save_start = new regsave_T();
                        regsave_T save_behind_pos;
                        boolean needmatch = (op == BEHIND);
                        /*
                             * Look back in the input of the operand matches or not. This
                             * must be done at every position in the input and checking if
                             * the match ends at the current position.
                             * First check if the next item matches, that's probably
                             * faster.
                             */
                        reg_save(save_start);
                        if (regmatch(next)) {
                            /* save the position after the found match for next */
                            reg_save(save_after);
                            /* start looking for a match with operand at the current
                                 * postion.  Go back one character until we find the
                                 * result, hitting the start of the line or the previous
                                 * line (for multi-line matching).
                                 * Set behind_pos to where the match should end, BHPOS
                                 * will match it. */
                            save_behind_pos = behind_pos == null ? null : new regsave_T(behind_pos);
                            behind_pos = new regsave_T(save_start);
                            while (true) {
                                reg_restore(save_start);
                                if (regmatch(scan.OPERAND()) && reg_save_equal(behind_pos)) {
                                    behind_pos = save_behind_pos;
                                    /* found a match that ends where "next" started */
                                    if (needmatch) {
                                        reg_restore(save_after);
                                        return true;
                                    }
                                    return false;
                                }
                                /*
                                     * No match: Go back one character.  May go to
                                     * previous line once.
                                     */
                                if (reg_match == null) {
                                    if (save_start.pos.col == 0) {
                                        if (save_start.pos.lnum < behind_pos.pos.lnum || reg_getline(--save_start.pos.lnum) == null) {
                                            break;
                                        }
                                        reg_restore(save_start);
                                        save_start.pos.col = regline.strlen();
                                    } else {
                                        --save_start.pos.col;
                                    }
                                } else {
                                    if (save_start.ptr == regline) {
                                        break;
                                    }
                                    save_start.ptr.dec();
                                }
                            }
                            /* NOBEHIND succeeds when no match was found */
                            behind_pos = save_behind_pos;
                            if (!needmatch) {
                                reg_restore(save_after);
                                return true;
                            }
                        }
                        return false;
                    }
                case BHPOS:
                    if (reg_match == null) {
                        if (behind_pos.pos.col != reginput.pointer() - regline.pointer() || behind_pos.pos.lnum != reglnum) {
                            return false;
                        }
                    } else if (behind_pos.ptr != reginput) {
                        return false;
                    }
                    break;
                case NEWL:
                    if (c != '' || reglnum == reg_maxline) {
                        return false;
                    }
                    reg_nextline();
                    break;
                case END:
                    return true;
                default:
                    VimPlugin.showMessage(MessageHelper.message(Msg.e_re_corr));
                    return false;
            }
        }
        scan = next;
    }
    /*
         * We get here only if there's trouble -- normally "case END" is the
         * terminating point.
         */
    VimPlugin.showMessage(MessageHelper.message(Msg.e_re_corr));
    return false;
}
Also used : LogicalPosition(com.intellij.openapi.editor.LogicalPosition)

Example 7 with LogicalPosition

use of com.intellij.openapi.editor.LogicalPosition in project ideavim by JetBrains.

the class CopyGroup method putText.

/**
   * This performs the actual insert of the paste
   *
   * @param editor      The editor to paste into
   * @param context     The data context
   * @param offset      The location within the file to paste the text
   * @param text        The text to paste
   * @param type        The type of paste
   * @param count       The number of times to paste the text
   * @param indent      True if pasted lines should be autoindented, false if not
   * @param cursorAfter If true move cursor to just after pasted text
   * @param mode        The type of hightlight prior to the put.
   */
public void putText(@NotNull Editor editor, @NotNull DataContext context, int offset, @NotNull String text, @NotNull SelectionType type, int count, boolean indent, boolean cursorAfter, @NotNull CommandState.SubMode mode) {
    if (logger.isDebugEnabled()) {
        logger.debug("offset=" + offset);
        logger.debug("type=" + type);
        logger.debug("mode=" + mode);
    }
    if (mode == CommandState.SubMode.VISUAL_LINE && editor.isOneLineMode()) {
        return;
    }
    // Don't indent if this there isn't anything about a linewise selection or register
    if (indent && type != SelectionType.LINE_WISE && mode != CommandState.SubMode.VISUAL_LINE) {
        indent = false;
    }
    if (type == SelectionType.LINE_WISE && text.length() > 0 && text.charAt(text.length() - 1) != '\n') {
        text = text + '\n';
    }
    int insertCnt = 0;
    int endOffset = offset;
    if (type != SelectionType.BLOCK_WISE) {
        for (int i = 0; i < count; i++) {
            VimPlugin.getChange().insertText(editor, offset, text);
            insertCnt += text.length();
            endOffset += text.length();
        }
    } else {
        LogicalPosition start = editor.offsetToLogicalPosition(offset);
        int col = mode == CommandState.SubMode.VISUAL_LINE ? 0 : start.column;
        int line = start.line;
        if (logger.isDebugEnabled()) {
            logger.debug("col=" + col + ", line=" + line);
        }
        int lines = 1;
        for (int i = 0; i < text.length(); i++) {
            if (text.charAt(i) == '\n') {
                lines++;
            }
        }
        if (line + lines >= EditorHelper.getLineCount(editor)) {
            for (int i = 0; i < line + lines - EditorHelper.getLineCount(editor); i++) {
                VimPlugin.getChange().insertText(editor, EditorHelper.getFileSize(editor, true), "\n");
                insertCnt++;
            }
        }
        StringTokenizer parser = new StringTokenizer(text, "\n");
        int maxlen = 0;
        while (parser.hasMoreTokens()) {
            String segment = parser.nextToken();
            maxlen = Math.max(maxlen, segment.length());
        }
        parser = new StringTokenizer(text, "\n");
        while (parser.hasMoreTokens()) {
            String segment = parser.nextToken();
            String origSegment = segment;
            if (segment.length() < maxlen) {
                logger.debug("short line");
                StringBuilder extra = new StringBuilder(maxlen - segment.length());
                for (int i = segment.length(); i < maxlen; i++) {
                    extra.append(' ');
                }
                segment = segment + extra.toString();
                if (col != 0 && col < EditorHelper.getLineLength(editor, line)) {
                    origSegment = segment;
                }
            }
            String pad = EditorHelper.pad(editor, line, col);
            int insoff = editor.logicalPositionToOffset(new LogicalPosition(line, col));
            endOffset = insoff;
            if (logger.isDebugEnabled()) {
                logger.debug("segment='" + segment + "'");
                logger.debug("origSegment='" + origSegment + "'");
                logger.debug("insoff=" + insoff);
            }
            for (int i = 0; i < count; i++) {
                String txt = i == 0 ? origSegment : segment;
                VimPlugin.getChange().insertText(editor, insoff, txt);
                insertCnt += txt.length();
                endOffset += txt.length();
            }
            if (mode == CommandState.SubMode.VISUAL_LINE) {
                VimPlugin.getChange().insertText(editor, endOffset, "\n");
                insertCnt++;
                endOffset++;
            } else {
                if (pad.length() > 0) {
                    VimPlugin.getChange().insertText(editor, insoff, pad);
                    insertCnt += pad.length();
                    endOffset += pad.length();
                }
            }
            line++;
        }
    }
    LogicalPosition slp = editor.offsetToLogicalPosition(offset);
    /*
    int adjust = 0;
    if ((type & Command.FLAG_MOT_LINEWISE) != 0)
    {
        adjust = -1;
    }
    */
    LogicalPosition elp = editor.offsetToLogicalPosition(endOffset - 1);
    if (logger.isDebugEnabled()) {
        logger.debug("slp.line=" + slp.line);
        logger.debug("elp.line=" + elp.line);
    }
    if (indent) {
        int startOff = editor.getDocument().getLineStartOffset(slp.line);
        int endOff = editor.getDocument().getLineEndOffset(elp.line);
        VimPlugin.getChange().autoIndentRange(editor, context, new TextRange(startOff, endOff));
    }
    /*
    boolean indented = false;
    for (int i = slp.line; indent && i <= elp.line; i++)
    {
        MotionGroup.moveCaret(editor, context, editor.logicalPositionToOffset(new LogicalPosition(i, 0)));
        KeyHandler.executeAction("OrigAutoIndentLines", context);
        indented = true;
    }
    */
    if (logger.isDebugEnabled()) {
        logger.debug("insertCnt=" + insertCnt);
    }
    if (indent) {
        endOffset = EditorHelper.getLineEndOffset(editor, elp.line, true);
        insertCnt = endOffset - offset;
        if (logger.isDebugEnabled()) {
            logger.debug("insertCnt=" + insertCnt);
        }
    }
    int cursorMode;
    if (type == SelectionType.BLOCK_WISE) {
        if (mode == CommandState.SubMode.VISUAL_LINE) {
            cursorMode = cursorAfter ? 4 : 1;
        } else {
            cursorMode = cursorAfter ? 5 : 1;
        }
    } else if (type == SelectionType.LINE_WISE) {
        if (mode == CommandState.SubMode.VISUAL_LINE) {
            cursorMode = cursorAfter ? 4 : 3;
        } else {
            cursorMode = cursorAfter ? 4 : 3;
        }
    } else /* Characterwise */
    {
        if (mode == CommandState.SubMode.VISUAL_LINE) {
            cursorMode = cursorAfter ? 4 : 1;
        } else {
            cursorMode = cursorAfter ? 5 : 2;
        }
    }
    switch(cursorMode) {
        case 1:
            MotionGroup.moveCaret(editor, offset);
            break;
        case 2:
            MotionGroup.moveCaret(editor, endOffset - 1);
            break;
        case 3:
            MotionGroup.moveCaret(editor, offset);
            MotionGroup.moveCaret(editor, VimPlugin.getMotion().moveCaretToLineStartSkipLeading(editor));
            break;
        case 4:
            MotionGroup.moveCaret(editor, endOffset + 1);
            break;
        case 5:
            int pos = Math.min(endOffset, EditorHelper.getLineEndForOffset(editor, endOffset - 1) - 1);
            MotionGroup.moveCaret(editor, pos);
            break;
    }
    VimPlugin.getMark().setChangeMarks(editor, new TextRange(offset, endOffset));
}
Also used : LogicalPosition(com.intellij.openapi.editor.LogicalPosition) StringTokenizer(java.util.StringTokenizer) TextRange(com.maddyhome.idea.vim.common.TextRange)

Example 8 with LogicalPosition

use of com.intellij.openapi.editor.LogicalPosition in project ideavim by JetBrains.

the class FileGroup method displayLocationInfo.

public void displayLocationInfo(@NotNull Editor editor) {
    StringBuilder msg = new StringBuilder();
    Document doc = editor.getDocument();
    if (CommandState.getInstance(editor).getMode() != CommandState.Mode.VISUAL) {
        LogicalPosition lp = editor.getCaretModel().getLogicalPosition();
        int col = editor.getCaretModel().getOffset() - doc.getLineStartOffset(lp.line);
        int endoff = doc.getLineEndOffset(lp.line);
        if (doc.getCharsSequence().charAt(endoff) == '\n') {
            endoff--;
        }
        int ecol = endoff - doc.getLineStartOffset(lp.line);
        LogicalPosition elp = editor.offsetToLogicalPosition(endoff);
        msg.append("Col ").append(col + 1);
        if (col != lp.column) {
            msg.append("-").append(lp.column + 1);
        }
        msg.append(" of ").append(ecol + 1);
        if (ecol != elp.column) {
            msg.append("-").append(elp.column + 1);
        }
        int lline = editor.getCaretModel().getLogicalPosition().line;
        int total = EditorHelper.getLineCount(editor);
        msg.append("; Line ").append(lline + 1).append(" of ").append(total);
        SearchHelper.CountPosition cp = SearchHelper.countWords(editor);
        msg.append("; Word ").append(cp.getPosition()).append(" of ").append(cp.getCount());
        int offset = editor.getCaretModel().getOffset();
        int size = EditorHelper.getFileSize(editor);
        msg.append("; Character ").append(offset + 1).append(" of ").append(size);
    } else {
        msg.append("Selected ");
        TextRange vr = VimPlugin.getMotion().getVisualRange(editor);
        vr.normalize();
        int lines;
        SearchHelper.CountPosition cp = SearchHelper.countWords(editor);
        int words = cp.getCount();
        int word = 0;
        if (vr.isMultiple()) {
            lines = vr.size();
            int cols = vr.getMaxLength();
            msg.append(cols).append(" Cols; ");
            for (int i = 0; i < vr.size(); i++) {
                cp = SearchHelper.countWords(editor, vr.getStartOffsets()[i], vr.getEndOffsets()[i] - 1);
                word += cp.getCount();
            }
        } else {
            LogicalPosition slp = editor.offsetToLogicalPosition(vr.getStartOffset());
            LogicalPosition elp = editor.offsetToLogicalPosition(vr.getEndOffset());
            lines = elp.line - slp.line + 1;
            cp = SearchHelper.countWords(editor, vr.getStartOffset(), vr.getEndOffset() - 1);
            word = cp.getCount();
        }
        int total = EditorHelper.getLineCount(editor);
        msg.append(lines).append(" of ").append(total).append(" Lines");
        msg.append("; ").append(word).append(" of ").append(words).append(" Words");
        int chars = vr.getSelectionCount();
        int size = EditorHelper.getFileSize(editor);
        msg.append("; ").append(chars).append(" of ").append(size).append(" Characters");
    }
    VimPlugin.showMessage(msg.toString());
}
Also used : LogicalPosition(com.intellij.openapi.editor.LogicalPosition) TextRange(com.maddyhome.idea.vim.common.TextRange) Document(com.intellij.openapi.editor.Document) SearchHelper(com.maddyhome.idea.vim.helper.SearchHelper)

Example 9 with LogicalPosition

use of com.intellij.openapi.editor.LogicalPosition in project intellij-community by JetBrains.

the class EditorFragmentComponent method doInit.

private void doInit(Component anchorComponent, EditorEx editor, int startLine, int endLine, boolean showFolding, boolean showGutter) {
    Document doc = editor.getDocument();
    final int endOffset = endLine < doc.getLineCount() ? doc.getLineEndOffset(endLine) : doc.getTextLength();
    boolean newRendering = editor instanceof EditorImpl;
    int widthAdjustment = newRendering ? EditorUtil.getSpaceWidth(Font.PLAIN, editor) : 0;
    final int textImageWidth = Math.min(editor.getMaxWidthInRange(doc.getLineStartOffset(startLine), endOffset) + widthAdjustment, getWidthLimit(editor));
    FoldingModelEx foldingModel = editor.getFoldingModel();
    boolean isFoldingEnabled = foldingModel.isFoldingEnabled();
    if (!showFolding) {
        foldingModel.setFoldingEnabled(false);
    }
    Point p1 = editor.logicalPositionToXY(new LogicalPosition(startLine, 0));
    Point p2 = editor.logicalPositionToXY(new LogicalPosition(Math.max(endLine, startLine + 1), 0));
    int y1 = p1.y;
    int y2 = p2.y;
    final int textImageHeight = y2 - y1 == 0 ? editor.getLineHeight() : y2 - y1;
    LOG.assertTrue(textImageHeight > 0, "Height: " + textImageHeight + "; startLine:" + startLine + "; endLine:" + endLine + "; p1:" + p1 + "; p2:" + p2);
    int savedScrollOffset = newRendering ? 0 : editor.getScrollingModel().getHorizontalScrollOffset();
    if (savedScrollOffset > 0) {
        editor.getScrollingModel().scrollHorizontally(0);
    }
    final BufferedImage textImage = UIUtil.createImage(anchorComponent == null ? editor.getContentComponent() : anchorComponent, textImageWidth, textImageHeight, BufferedImage.TYPE_INT_RGB);
    Graphics textGraphics = textImage.getGraphics();
    EditorUIUtil.setupAntialiasing(textGraphics);
    final JComponent rowHeader;
    final BufferedImage markersImage;
    final int markersImageWidth;
    if (showGutter) {
        rowHeader = editor.getGutterComponentEx();
        markersImageWidth = Math.max(1, rowHeader.getWidth());
        markersImage = UIUtil.createImage(editor.getComponent(), markersImageWidth, textImageHeight, BufferedImage.TYPE_INT_RGB);
        Graphics markerGraphics = markersImage.getGraphics();
        EditorUIUtil.setupAntialiasing(markerGraphics);
        markerGraphics.translate(0, -y1);
        markerGraphics.setClip(0, y1, rowHeader.getWidth(), textImageHeight);
        markerGraphics.setColor(getBackgroundColor(editor));
        markerGraphics.fillRect(0, y1, rowHeader.getWidth(), textImageHeight);
        rowHeader.paint(markerGraphics);
    } else {
        markersImageWidth = 0;
        rowHeader = null;
        markersImage = null;
    }
    textGraphics.translate(0, -y1);
    textGraphics.setClip(0, y1, textImageWidth, textImageHeight);
    final boolean wasVisible = editor.setCaretVisible(false);
    editor.getContentComponent().paint(textGraphics);
    if (wasVisible) {
        editor.setCaretVisible(true);
    }
    if (!showFolding) {
        foldingModel.setFoldingEnabled(isFoldingEnabled);
    }
    if (savedScrollOffset > 0) {
        editor.getScrollingModel().scrollHorizontally(savedScrollOffset);
    }
    JComponent component = new JComponent() {

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(textImageWidth + markersImageWidth, textImageHeight);
        }

        @Override
        protected void paintComponent(Graphics graphics) {
            if (markersImage != null) {
                UIUtil.drawImage(graphics, markersImage, 0, 0, null);
                UIUtil.drawImage(graphics, textImage, rowHeader.getWidth(), 0, null);
            } else {
                UIUtil.drawImage(graphics, textImage, 0, 0, null);
            }
        }
    };
    setLayout(new BorderLayout());
    add(component);
    final Color borderColor = editor.getColorsScheme().getColor(EditorColors.SELECTED_TEARLINE_COLOR);
    Border outsideBorder = JBUI.Borders.customLine(borderColor, LINE_BORDER_THICKNESS);
    Border insideBorder = JBUI.Borders.empty(EMPTY_BORDER_THICKNESS, EMPTY_BORDER_THICKNESS);
    setBorder(BorderFactory.createCompoundBorder(outsideBorder, insideBorder));
}
Also used : LogicalPosition(com.intellij.openapi.editor.LogicalPosition) EditorImpl(com.intellij.openapi.editor.impl.EditorImpl) Document(com.intellij.openapi.editor.Document) FoldingModelEx(com.intellij.openapi.editor.ex.FoldingModelEx) HintHint(com.intellij.ui.HintHint) LightweightHint(com.intellij.ui.LightweightHint) BufferedImage(java.awt.image.BufferedImage) Border(javax.swing.border.Border)

Example 10 with LogicalPosition

use of com.intellij.openapi.editor.LogicalPosition in project intellij-community by JetBrains.

the class HintManagerImpl method showErrorHint.

@Override
public void showErrorHint(@NotNull Editor editor, @NotNull String hintText, int offset1, int offset2, short constraint, int flags, int timeout) {
    JComponent label = HintUtil.createErrorLabel(hintText);
    LightweightHint hint = new LightweightHint(label);
    final LogicalPosition pos1 = editor.offsetToLogicalPosition(offset1);
    final LogicalPosition pos2 = editor.offsetToLogicalPosition(offset2);
    final Point p = getHintPosition(hint, editor, pos1, pos2, constraint);
    showEditorHint(hint, editor, p, flags, timeout, false);
}
Also used : LogicalPosition(com.intellij.openapi.editor.LogicalPosition) RelativePoint(com.intellij.ui.awt.RelativePoint)

Aggregations

LogicalPosition (com.intellij.openapi.editor.LogicalPosition)106 Document (com.intellij.openapi.editor.Document)16 PsiElement (com.intellij.psi.PsiElement)14 Editor (com.intellij.openapi.editor.Editor)12 TextRange (com.intellij.openapi.util.TextRange)11 VirtualFile (com.intellij.openapi.vfs.VirtualFile)10 EditorEx (com.intellij.openapi.editor.ex.EditorEx)7 CaretModel (com.intellij.openapi.editor.CaretModel)6 NotNull (org.jetbrains.annotations.NotNull)6 RelativePoint (com.intellij.ui.awt.RelativePoint)5 JSFile (com.intellij.lang.javascript.psi.JSFile)4 EditorColorsManager (com.intellij.openapi.editor.colors.EditorColorsManager)4 TextAttributes (com.intellij.openapi.editor.markup.TextAttributes)4 Project (com.intellij.openapi.project.Project)4 PsiFile (com.intellij.psi.PsiFile)4 PsiReference (com.intellij.psi.PsiReference)4 PsiMultiReference (com.intellij.psi.impl.source.resolve.reference.impl.PsiMultiReference)4 Mark (com.maddyhome.idea.vim.common.Mark)4 HighlightManager (com.intellij.codeInsight.highlighting.HighlightManager)3 EditorWindow (com.intellij.injected.editor.EditorWindow)3