|
|
1.1 ! root 1: /* ! 2: * This routine gets a bracket character from where the dot lies ! 3: * and searches for the corresponding bracket. ! 4: */ ! 5: #include <stdio.h> ! 6: #include "ed.h" ! 7: ! 8: static int o_col, o_row, r_col, r_char, r_row = -1; ! 9: ! 10: /* ! 11: * This is called before each comand is executed. ! 12: */ ! 13: bracketoff() ! 14: { ! 15: if (bind.bracket && (r_row >= 0)) { ! 16: tmove(r_row, r_col); ! 17: tputc(r_char); ! 18: r_row = -1; ! 19: tmove(o_row, o_col); ! 20: return (TRUE); ! 21: } ! 22: return (FALSE); ! 23: } ! 24: ! 25: /* ! 26: * toggle bracket mode. ! 27: */ ! 28: bracketsw() ! 29: { ! 30: bind.bracket ^= 1; ! 31: } ! 32: ! 33: bracketsearch() ! 34: { ! 35: bstart(0); /* do full search */ ! 36: } ! 37: ! 38: /* ! 39: * This is called after each screen update. ! 40: */ ! 41: bracketmode(row, col) ! 42: { ! 43: r_row = -1; ! 44: if (bind.bracket) ! 45: bstart(1); ! 46: movecursor(row, col); ! 47: tmove(o_row = row, o_col = col); ! 48: } ! 49: ! 50: static ! 51: bstart(modesw) ! 52: { ! 53: register LINE *clp; ! 54: int cbo; ! 55: ! 56: if (((o_col = cbo = curwp->w_doto) == llength(clp = curwp->w_dotp))) ! 57: if (modesw) ! 58: --cbo; ! 59: else ! 60: return (FALSE); ! 61: ! 62: switch (lgetc(clp, cbo)) { ! 63: case '/': ! 64: if ((++cbo == llength(clp)) || ('*' != lgetc(clp, cbo--))) ! 65: break; ! 66: case '[': ! 67: case '{': ! 68: case '(': ! 69: return (brksearch(1, modesw, clp, cbo)); ! 70: case '*': ! 71: if ((++cbo == llength(clp)) || ('/' != lgetc(clp, cbo))) ! 72: break; ! 73: case ']': ! 74: case '}': ! 75: case ')': ! 76: return (brksearch(-1, modesw, clp, cbo)); ! 77: case '"': ! 78: case '\'': ! 79: if (modesw) ! 80: break; ! 81: if (mlyesno("Forward search")) ! 82: return (brksearch(1, modesw, clp, cbo)); ! 83: return (brksearch(-1, modesw, clp, cbo)); ! 84: } ! 85: if (!modesw) ! 86: mlwrite("Place dot on \"'(){}[] /* or */"); ! 87: return (FALSE); ! 88: } ! 89: ! 90: /* defines for states of forward and backward searches */ ! 91: #define NORMAL 0 /* normal state */ ! 92: #define SLASH 1 /* slash maybe comment */ ! 93: #define COMMENT 2 /* comment */ ! 94: #define STAR 3 /* star in comment */ ! 95: #define DQUOTE 4 /* in string */ ! 96: #define SQUOTE 5 /* in single quote */ ! 97: #define BSL 6 /* backslash */ ! 98: #define BADEXPR 7 /* bad expression encountered */ ! 99: #define STARTB 8 /* starting search */ ! 100: ! 101: /* ! 102: * scan for end of balanced c expression forward or backward. ! 103: */ ! 104: static ! 105: brksearch(dir, mode, clp, cbo) ! 106: int dir; /* 1 forward -1 backward */ ! 107: int mode; /* 1 paren mode, 0 match paren command */ ! 108: LINE *clp; /* line to start search */ ! 109: int cbo; /* char to start search */ ! 110: { ! 111: register int c, state; ! 112: LINE *end; ! 113: int prev, pstate, bcnt, pcnt, ccnt, bscnt, ctrs; ! 114: ! 115: bcnt = ccnt = pcnt = bscnt = 0; ! 116: state = STARTB; ! 117: if (mode) { /* end is top or bottom of window */ ! 118: if (dir < 0) ! 119: end = lback(curwp->w_linep); ! 120: else ! 121: for (end = curwp->w_linep, c = curwp->w_ntrows; ! 122: (c-- > 0) && (curbp->b_linep != end); ! 123: end = lforw(end)) ; ! 124: } else /* end is buffer end */ ! 125: end = curbp->b_linep; ! 126: ! 127: while (clp != end) { ! 128: if (dir > 0) { /* get next char */ ! 129: if (cbo == llength(clp)) { ! 130: clp = lforw(clp); ! 131: cbo = 0; ! 132: c = '\n'; ! 133: } else ! 134: c = lgetc(clp, cbo++); ! 135: } else { /* get prev char. watch \ here. */ ! 136: c = prev; ! 137: if (cbo < 0) { ! 138: clp = lback(clp); ! 139: cbo = llength(clp) - 1; ! 140: prev = '\n'; ! 141: } ! 142: else if (('\\' == (prev = lgetc(clp, cbo--))) && ! 143: (state != COMMENT) && (state != SLASH)) { ! 144: bscnt ^= 1; /* count \ */ ! 145: prev = c; /* don't discard char */ ! 146: continue; ! 147: } ! 148: if (bscnt) { /* odd \ discard c */ ! 149: bscnt = 0; ! 150: continue; ! 151: } ! 152: } ! 153: ! 154: switch (state) { /* do state processing */ ! 155: case SLASH: /* / encountered */ ! 156: if (c == '*') { ! 157: state = COMMENT; ! 158: continue; ! 159: } ! 160: state = NORMAL; ! 161: case NORMAL: /* not in anything */ ! 162: break; ! 163: case STAR: /* * in comment */ ! 164: if (c == '/') { ! 165: state = NORMAL; ! 166: goto processed; ! 167: } ! 168: state = COMMENT; ! 169: case COMMENT: /* in comment */ ! 170: if (c == '*') ! 171: state = STAR; ! 172: continue; ! 173: case SQUOTE: /* in ' string */ ! 174: case DQUOTE: /* in " string */ ! 175: switch (c) { ! 176: case '\n': ! 177: state = BADEXPR; ! 178: goto processed; ! 179: case '\\': /* can't get here if dir < 0 */ ! 180: pstate = state; ! 181: state = BSL; ! 182: continue; ! 183: case '"': ! 184: if (state != DQUOTE) ! 185: continue; ! 186: state = NORMAL; ! 187: goto processed; ! 188: case '\'': ! 189: if (state != SQUOTE) ! 190: continue; ! 191: state = NORMAL; ! 192: goto processed; ! 193: default: ! 194: continue; ! 195: } ! 196: case BSL: /* can't get here if dir < 0 */ ! 197: state = pstate; ! 198: continue; ! 199: case STARTB: ! 200: state = NORMAL; ! 201: if (dir < 0) ! 202: continue; ! 203: } ! 204: ! 205: switch (c) { /* process chars in NORMAL state */ ! 206: case '[': ! 207: bcnt += dir; ! 208: break; ! 209: case '{': ! 210: ccnt += dir; ! 211: if (pcnt | bcnt) ! 212: state = BADEXPR; ! 213: break; ! 214: case ';': ! 215: if (bcnt) ! 216: state = BADEXPR; ! 217: break; ! 218: case '(': ! 219: pcnt += dir; ! 220: break; ! 221: case '"': ! 222: state = DQUOTE; ! 223: continue; ! 224: case '\'': ! 225: state = SQUOTE; ! 226: continue; ! 227: case '\\': /* can't get here if dir < 0 */ ! 228: pstate = state; ! 229: state = BSL; ! 230: continue; ! 231: case '/': ! 232: state = SLASH; ! 233: continue; ! 234: case ']': ! 235: bcnt -= dir; ! 236: break; ! 237: case '}': ! 238: ccnt -= dir; ! 239: if (pcnt | bcnt) ! 240: state = BADEXPR; ! 241: break; ! 242: case ')': ! 243: pcnt -= dir; ! 244: } ! 245: ! 246: /* done if BADEXPR or balanced expr or ) with no ( etc */ ! 247: processed: if (((ctrs = bcnt | ccnt | pcnt) <= 0) || (state == BADEXPR)) { ! 248: if (dir > 0) { ! 249: if (--cbo < 0) { ! 250: clp = lback(clp); ! 251: cbo = llength(clp); ! 252: } ! 253: } else { /* we are on prev so back up 2 */ ! 254: for (bscnt = 0; bscnt < 2; bscnt++) { ! 255: if (++cbo > llength(clp)) { ! 256: clp = lforw(clp); ! 257: cbo = 0; ! 258: break; ! 259: } ! 260: } ! 261: } ! 262: if (mode) { /* paren mode */ ! 263: if ((ctrs < 0) || (state == BADEXPR) || ! 264: (0 > (r_row = locatecursor(clp)))) ! 265: return (FALSE); ! 266: tmove(r_row, (r_col = truecol(clp, cbo))); ! 267: tstand(1); ! 268: tputc(r_char = c); ! 269: tstand(0); ! 270: } else { /* match paren command */ ! 271: curwp->w_dotp = clp; ! 272: curwp->w_doto = cbo; ! 273: curwp->w_flag |= WFMOVE; ! 274: if ((ctrs < 0) || (state == BADEXPR)) { ! 275: mlwrite("Bad expression"); ! 276: return (FALSE); ! 277: } ! 278: } ! 279: return (TRUE); ! 280: } ! 281: } ! 282: if (!mode) ! 283: mlwrite("End not found"); ! 284: return (FALSE); ! 285: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.