|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T m
Length: 4920 (0x1338) Types: TextFile Names: »match.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─⟦this⟧ »EUUGD11/euug-87hel/sec1/micrognu/match.c«
/* * Name: MicroEMACS * Limited parenthesis matching routines * Version: Gnu30 * Last edit: 13-Jul-86 * Created: 19-May-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic * * The hacks in this file implement automatic matching * of (), [], {}, and other characters. It would be * better to have a full-blown syntax table, but there's * enough overhead in the editor as it is. * * Since I often edit Scribe code, I've made it possible to * blink arbitrary characters -- just bind delimiter characters * to "blink-matching-paren-hack" */ #include "def.h" /* Balance table. When balance() encounters a character * that is to be matched, it first searches this table * for a balancing left-side character. If the character * is not in the table, the character is balanced by itself. * This is to allow delimiters in Scribe documents to be matched. */ static struct balance { char left, right; } bal[] = { { '(', ')' }, { '[', ']' }, { '{', '}' }, { '<', '>' }, { '\0','\0'} }; /* * Fake the GNU "blink-matching-paren" variable. * If the argument exists, nonzero means show, * zero means don't. If it doesn't exist, * pretend it's nonzero. */ blinkparen(f, n, k) { register char *command; register SYMBOL *sp; if (f == FALSE) n = 1; command = (n == 0) ? "self-insert-command" : "blink-matching-paren-hack"; if ((sp=symlookup(command)) == NULL) { ewprintf("blinkparen: no binding for %s",command); return (FALSE); } binding[(KEY) ')'] = sp; /* rebind paren */ return (TRUE); } /* * Self-insert character, then show matching character, * if any. Bound to "blink-matching-paren-command". */ showmatch(f, n, k) { register int i, s; if (k == KRANDOM) return(FALSE); for (i = 0; i < n; i++) { if ((s = selfinsert(f, 1, k)) != TRUE) return(s); if (balance(k) != TRUE) /* unbalanced -- warn user */ ttbeep(); } return (TRUE); } /* * Search for and display a matching character. * * This routine does the real work of searching backward * for a balancing character. If such a balancing character * is found, it uses displaymatch() to display the match. */ static balance(k) int k; { register LINE *clp; register int cbo; int c; int i; int rbal, lbal; int depth; rbal = k & KCHAR; if ((k&KCTRL)!=0 && rbal>='@' && rbal<='_') /* ASCII-ify. */ rbal -= '@'; /* See if there is a matching character -- default to the same */ lbal = rbal; for (i = 0; bal[i].right != '\0'; i++) if (bal[i].right == rbal) { lbal = bal[i].left; break; } /* Move behind the inserted character. We are always guaranteed */ /* that there is at least one character on the line, since one was */ /* just self-inserted by blinkparen. */ clp = curwp->w_dotp; cbo = curwp->w_doto - 1; depth = 0; /* init nesting depth */ for (;;) { if (cbo == 0) { /* beginning of line */ clp = lback(clp); if (clp == curbp->b_linep) return (FALSE); cbo = llength(clp)+1; } if (--cbo == llength(clp)) /* end of line */ c = '\n'; else c = lgetc(clp,cbo); /* somewhere in middle */ /* Check for a matching character. If still in a nested */ /* level, pop out of it and continue search. This check */ /* is done before the nesting check so single-character */ /* matches will work too. */ if (c == lbal) { if (depth == 0) { displaymatch(clp,cbo); return (TRUE); } else depth--; } /* Check for another level of nesting. */ if (c == rbal) depth++; } } /* * Display matching character. * Matching characters that are not in the current window * are displayed in the echo line. If in the current * window, move dot to the matching character, * sit there a while, then move back. */ static displaymatch(clp, cbo) register LINE *clp; register int cbo; { register LINE *tlp; register int tbo; register int cp; register int bufo; register int c; int inwindow; char buf[NLINE]; /* Figure out if matching char is in current window by */ /* searching from the top of the window to dot. */ inwindow = FALSE; for (tlp = curwp->w_linep; tlp != lforw(curwp->w_dotp); tlp = lforw(tlp)) if (tlp == clp) inwindow = TRUE; if (inwindow == TRUE) { tlp = curwp->w_dotp; /* save current position */ tbo = curwp->w_doto; curwp->w_dotp = clp; /* move to new position */ curwp->w_doto = cbo; curwp->w_flag |= WFMOVE; update(); /* show match */ sleep(1); /* wait a bit */ curwp->w_dotp = tlp; /* return to old position */ curwp->w_doto = tbo; curwp->w_flag |= WFMOVE; update(); } else { /* match not in this window so display line in echo area */ bufo = 0; for (cp = 0; cp < llength(clp); cp++) { /* expand tabs */ c = lgetc(clp,cp); if (c != '\t') buf[bufo++] = c; else do { buf[bufo++] = ' '; } while (bufo & 7); } buf[bufo++] = '\0'; ewprintf("Matches %s",buf); } return (TRUE); }