/* * NAME: cmdbuf->append() * DESCRIPTION: append a block of lines, read from user, to edit buffer */ int cb_append(cmdbuf *cb) { not_in_global(cb); cb_do(cb, cb->first); startblock(cb); cb->flags |= CB_INSERT; return 0; }
/* Put a relocated word into REL block */ void putword(word w, int reloc) { item[itemp++] = w; blockreloc = blockreloc<<2 | reloc; blocksz++; itemsz++; if(blocksz == 18) startblock(); }
/* * NAME: cmdbuf->shift() * DESCRIPTION: shift a range of lines left or right */ static int cb_shift(cmdbuf *cb) { cb_do(cb, cb->first); startblock(cb); cb->lineno = cb->first - 1; cb->flags |= CB_CHANGE; eb_range(cb->edbuf, cb->first, cb->last, shift, FALSE); endblock(cb); return RET_FLAGS; }
/* Start a REL item and write out the last one */ void startitem(hword it) { startblock(); if(itemsz){ item[0] = fw(itemtype, itemsz); writeout(); } itemtype = it; itemsz = 0; itemp = 1; relocp = itemp++; }
/* * NAME: cmdbuf->change() * DESCRIPTION: change a subrange of lines in the edit buffer */ int cb_change(cmdbuf *cb) { Int *m; not_in_global(cb); cb_do(cb, cb->first); /* erase marks of changed lines */ for (m = cb->mark; m < &cb->mark[26]; m++) { if (*m >= cb->first && *m <= cb->last) { *m = 0; } } startblock(cb); cb->flags |= CB_INSERT | CB_CHANGE; return 0; }
/* * NAME: cmdbuf->indent() * DESCRIPTION: indent a range of lines */ int cb_indent(cmdbuf *cb) { char s[STACKSZ]; int i[STACKSZ]; /* setup stacks */ cb->stackbot = s; cb->stack = s + STACKSZ - 1; cb->stack[0] = EOT; cb->ind = i + STACKSZ - 1; cb->ind[0] = 0; cb->quote = '\0'; cb_do(cb, cb->first); startblock(cb); cb->lineno = cb->first - 1; cb->flags |= CB_CHANGE; cb->flags &= ~(CB_PPCONTROL | CB_COMMENT | CB_JSKEYWORD); eb_range(cb->edbuf, cb->first, cb->last, indent, FALSE); endblock(cb); return 0; }
/* * NAME: cmdbuf->join() * DESCRIPTION: join a range of lines in the edit buffer */ int cb_join(cmdbuf *cb) { char buf[MAX_LINE_SIZE + 1]; Int *m; if (cb->edbuf->lines == 0) { error("No lines in buffer"); } if (cb->first < 0) { cb->first = cb->cthis; } if (cb->last < 0) { cb->last = (cb->first == cb->edbuf->lines) ? cb->first : cb->first + 1; } cb_do(cb, cb->first); cb->cthis = cb->othis = cb->first; buf[0] = '\0'; cb->buffer = buf; cb->buflen = 0; eb_range(cb->edbuf, cb->first, cb->last, join, FALSE); /* erase marks for joined lines */ for (m = cb->mark; m < &cb->mark[26]; m++) { if (*m > cb->first && *m <= cb->last) { *m = 0; } } cb->flags |= CB_CHANGE; startblock(cb); addblock(cb, buf); endblock(cb); return RET_FLAGS; }
/* * NAME: subst() * DESCRIPTION: do substitutions in a line. If something is substituted on line * N, and the next substitution happens on line N + 2, line N + 1 * is joined in the new block also. */ static void subst(const char *text) { char line[MAX_LINE_SIZE]; cmdbuf *cb; int idx, size; char *p; Int *k, *l; Int newlines; bool found; cb = ccb; found = FALSE; newlines = 0; idx = 0; /* * Because the write buffer might be flushed, and the text would * not remain in memory, use a local copy. */ text = strcpy(line, text); while (rx_exec(cb->regexp, text, idx, IGNORECASE(cb->vars)) > 0) { if (cb->flags & CB_SKIPPED) { /* * add the previous line, in which nothing was substituted, to * the block. Has to be done here, before the contents of the buffer * are changed. */ addblock(cb, cb->buffer); cb->flags &= ~CB_SKIPPED; /* * check if there were newlines in the last substitution. If there * are, marks on the previous line (without substitutions) will * also have to be changed. */ if (cb->offset > 0) { for (k = cb->mark, l = cb->moffset; k < &cb->mark[26]; k++, l++) { if (*k == cb->lineno - 1 && *l == 0) { *l = *k + cb->offset; } } } } found = TRUE; cb->flags &= ~(CB_UPPER | CB_LOWER | CB_TUPPER | CB_TLOWER); size = cb->regexp->start - text - idx; if (size > 0) { /* copy first unchanged part of line to buffer */ sub(cb, text + idx, size); } p = cb->replace; while (*p != '\0') { switch (*p) { case '&': /* insert matching string */ sub(cb, cb->regexp->start, cb->regexp->size); break; case '\\': /* special substitute characters */ switch (*++p) { case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* insert subexpression between \( \) */ if (cb->regexp->se[*p - '1'].start != (char*) NULL) { sub(cb, cb->regexp->se[*p - '1'].start, cb->regexp->se[*p - '1'].size); break; } /* if no subexpression, fall though */ default: sub(cb, p, 1); /* ignore preceding backslash */ break; case 'n': cb->buffer[cb->buflen++] = '\0'; newlines++; /* insert newline */ break; case 'U': /* convert string to uppercase */ cb->flags |= CB_UPPER; cb->flags &= ~(CB_LOWER | CB_TUPPER | CB_TLOWER); break; case 'L': /* convert string to lowercase */ cb->flags |= CB_LOWER; cb->flags &= ~(CB_UPPER | CB_TUPPER | CB_TLOWER); break; case 'e': case 'E': /* end case conversion */ cb->flags &= ~(CB_UPPER | CB_LOWER | CB_TUPPER | CB_TLOWER); break; case 'u': /* convert char to uppercase */ cb->flags |= CB_TUPPER; cb->flags &= ~CB_TLOWER; break; case 'l': /* convert char to lowercase */ cb->flags &= ~CB_TUPPER; cb->flags |= CB_TLOWER; break; case '\0': /* sigh */ continue; } break; default: /* normal char */ sub(cb, p, 1); break; } p++; } idx = cb->regexp->start + cb->regexp->size - text; if (!(cb->flags & CB_GLOBSUBST) || text[idx] == '\0' || (cb->regexp->size == 0 && text[++idx] == '\0')) { break; } } if (found) { if (text[idx] != '\0') { /* concatenate unchanged part of line after found pattern */ cb->flags &= ~(CB_UPPER | CB_LOWER | CB_TUPPER | CB_TLOWER); sub(cb, text + idx, strlen(text + idx)); } if (!(cb->flags & CB_CURRENTBLK)) { /* start a new block of lines with substitutions in them */ cb->flags |= CB_CHANGE; cb->first = cb->lineno; startblock(cb); cb->flags |= CB_CURRENTBLK; } /* add this changed line to block */ cb->buffer[cb->buflen] = '\0'; if (newlines == 0) { addblock(cb, cb->buffer); } else { /* * There were newlines in the substituted string. Add all * lines to the current block, and save the marks in range. */ p = cb->buffer; do { addblock(cb, p); p += strlen(p) + 1; } while (p <= cb->buffer + cb->buflen); for (k = cb->mark, l = cb->moffset; k < &cb->mark[26]; k++, l++) { if (*k == cb->lineno && *l == 0) { *l = *k + cb->offset; } } cb->offset += newlines; } cb->buflen = 0; cb->last = cb->lineno; } else { if (cb->flags & CB_SKIPPED) { /* two lines without substitutions now. Finish previous block. */ endblock(cb); cb->lineno += cb->offset; cb->offset = 0; cb->flags &= ~(CB_CURRENTBLK | CB_SKIPPED); } else if (cb->flags & CB_CURRENTBLK) { /* * no substitution on this line, but there was one on the previous * line. mark this line as skipped, so it can still be added to * the block of changed lines if the next line has substitutions. */ strcpy(cb->buffer, text); cb->flags |= CB_SKIPPED; } } cb->lineno++; }