[BACK]Return to match.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

Annotation of src/usr.bin/mg/match.c, Revision 1.16

1.16    ! kjell       1: /*     $OpenBSD: match.c,v 1.15 2008/06/14 08:46:30 kjell Exp $        */
1.11      kjell       2:
                      3: /* This file is in the public domain. */
1.4       niklas      4:
1.1       deraadt     5: /*
1.3       millert     6:  *     Limited parenthesis matching routines
1.1       deraadt     7:  *
1.7       mickey      8:  * The hacks in this file implement automatic matching * of (), [], {}, and
                      9:  * other characters.  It would be better to have a full-blown syntax table,
1.3       millert    10:  * but there's enough overhead in the editor as it is.
1.1       deraadt    11:  */
                     12:
1.3       millert    13: #include "def.h"
                     14: #include "key.h"
                     15:
1.8       millert    16: static int     balance(void);
1.12      deraadt    17: static void    displaymatch(struct line *, int);
1.1       deraadt    18:
1.2       millert    19: /*
                     20:  * Balance table. When balance() encounters a character that is to be
                     21:  * matched, it first searches this table for a balancing left-side character.
1.3       millert    22:  * If the character is not in the table, the character is balanced by itself.
1.1       deraadt    23:  */
                     24: static struct balance {
1.3       millert    25:        char    left, right;
                     26: } bal[] = {
1.14      kjell      27:        { '(', ')' },
                     28:        { '[', ']' },
                     29:        { '{', '}' },
                     30:        { '<', '>' },
                     31:        { '\0', '\0' }
1.1       deraadt    32: };
                     33:
                     34: /*
1.7       mickey     35:  * Hack to show matching paren.  Self-insert character, then show matching
1.15      kjell      36:  * character, if any.  Bound to "blink-and-insert".
1.1       deraadt    37:  */
1.3       millert    38: int
1.9       cloder     39: showmatch(int f, int n)
1.1       deraadt    40: {
1.3       millert    41:        int     i, s;
1.1       deraadt    42:
                     43:        for (i = 0; i < n; i++) {
                     44:                if ((s = selfinsert(FFRAND, 1)) != TRUE)
1.10      db         45:                        return (s);
1.3       millert    46:                /* unbalanced -- warn user */
                     47:                if (balance() != TRUE)
1.1       deraadt    48:                        ttbeep();
                     49:        }
1.10      db         50:        return (TRUE);
1.1       deraadt    51: }
                     52:
                     53: /*
                     54:  * Search for and display a matching character.
                     55:  *
                     56:  * This routine does the real work of searching backward
                     57:  * for a balancing character.  If such a balancing character
                     58:  * is found, it uses displaymatch() to display the match.
                     59:  */
1.3       millert    60: static int
1.9       cloder     61: balance(void)
1.1       deraadt    62: {
1.12      deraadt    63:        struct line     *clp;
1.3       millert    64:        int      cbo;
1.10      db         65:        int      c, i, depth;
                     66:        int      rbal, lbal;
1.1       deraadt    67:
1.2       millert    68:        rbal = key.k_chars[key.k_count - 1];
1.1       deraadt    69:
                     70:        /* See if there is a matching character -- default to the same */
                     71:        lbal = rbal;
                     72:        for (i = 0; bal[i].right != '\0'; i++)
                     73:                if (bal[i].right == rbal) {
                     74:                        lbal = bal[i].left;
                     75:                        break;
                     76:                }
                     77:
1.3       millert    78:        /*
                     79:         * Move behind the inserted character.  We are always guaranteed
                     80:         * that there is at least one character on the line, since one was
                     81:         * just self-inserted by blinkparen.
                     82:         */
1.1       deraadt    83:        clp = curwp->w_dotp;
                     84:        cbo = curwp->w_doto - 1;
                     85:
1.3       millert    86:        /* init nesting depth */
                     87:        depth = 0;
1.1       deraadt    88:
                     89:        for (;;) {
1.3       millert    90:                if (cbo == 0) {
                     91:                        clp = lback(clp);       /* beginning of line    */
1.13      kjell      92:                        if (clp == curbp->b_headp)
1.1       deraadt    93:                                return (FALSE);
1.2       millert    94:                        cbo = llength(clp) + 1;
1.1       deraadt    95:                }
1.3       millert    96:                if (--cbo == llength(clp))
                     97:                        c = '\n';               /* end of line          */
1.1       deraadt    98:                else
1.3       millert    99:                        c = lgetc(clp, cbo);    /* somewhere in middle  */
1.1       deraadt   100:
1.3       millert   101:                /*
                    102:                 * Check for a matching character.  If still in a nested
                    103:                 * level, pop out of it and continue search.  This check
                    104:                 * is done before the nesting check so single-character
                    105:                 * matches will work too.
                    106:                 */
1.1       deraadt   107:                if (c == lbal) {
                    108:                        if (depth == 0) {
1.2       millert   109:                                displaymatch(clp, cbo);
1.1       deraadt   110:                                return (TRUE);
1.2       millert   111:                        } else
1.1       deraadt   112:                                depth--;
                    113:                }
1.2       millert   114:                /* Check for another level of nesting.   */
1.1       deraadt   115:                if (c == rbal)
                    116:                        depth++;
                    117:        }
1.2       millert   118:        /* NOTREACHED */
1.1       deraadt   119: }
                    120:
                    121: /*
1.7       mickey    122:  * Display matching character.  Matching characters that are not in the
                    123:  * current window are displayed in the echo line. If in the current window,
1.3       millert   124:  * move dot to the matching character, sit there a while, then move back.
1.1       deraadt   125:  */
1.6       art       126: static void
1.12      deraadt   127: displaymatch(struct line *clp, int cbo)
1.1       deraadt   128: {
1.12      deraadt   129:        struct line     *tlp;
1.3       millert   130:        int      tbo;
                    131:        int      cp;
                    132:        int      bufo;
                    133:        int      c;
                    134:        int      inwindow;
                    135:        char     buf[NLINE];
                    136:
                    137:        /*
                    138:         * Figure out if matching char is in current window by
                    139:         * searching from the top of the window to dot.
                    140:         */
1.1       deraadt   141:        inwindow = FALSE;
1.7       mickey    142:        for (tlp = curwp->w_linep; tlp != lforw(curwp->w_dotp);
1.3       millert   143:            tlp = lforw(tlp))
1.1       deraadt   144:                if (tlp == clp)
                    145:                        inwindow = TRUE;
                    146:
                    147:        if (inwindow == TRUE) {
1.5       art       148:                tlp = curwp->w_dotp;    /* save current position */
1.1       deraadt   149:                tbo = curwp->w_doto;
                    150:
1.5       art       151:                curwp->w_dotp = clp;    /* move to new position */
1.2       millert   152:                curwp->w_doto = cbo;
1.16    ! kjell     153:                curwp->w_rflag |= WFMOVE;
1.1       deraadt   154:
1.5       art       155:                update();               /* show match */
                    156:                ttwait(1000);           /* wait for key or 1 second */
1.1       deraadt   157:
1.5       art       158:                curwp->w_dotp = tlp;    /* return to old position */
1.2       millert   159:                curwp->w_doto = tbo;
1.16    ! kjell     160:                curwp->w_rflag |= WFMOVE;
1.1       deraadt   161:                update();
1.3       millert   162:        } else {
                    163:                /* match is not in this window, so display line in echo area */
1.1       deraadt   164:                bufo = 0;
1.3       millert   165:                for (cp = 0; cp < llength(clp); cp++) {
1.2       millert   166:                        c = lgetc(clp, cp);
1.1       deraadt   167:                        if (c != '\t'
1.3       millert   168: #ifdef NOTAB
1.2       millert   169:                            || (curbp->b_flag & BFNOTAB)
1.1       deraadt   170: #endif
1.2       millert   171:                                )
                    172:                                if (ISCTRL(c)) {
                    173:                                        buf[bufo++] = '^';
                    174:                                        buf[bufo++] = CCHR(c);
                    175:                                } else
                    176:                                        buf[bufo++] = c;
1.1       deraadt   177:                        else
                    178:                                do {
                    179:                                        buf[bufo++] = ' ';
                    180:                                } while (bufo & 7);
                    181:                }
                    182:                buf[bufo++] = '\0';
1.2       millert   183:                ewprintf("Matches %s", buf);
1.1       deraadt   184:        }
                    185: }