/* push_undo_stack: return pointer to initialized undo node */ undo_t * push_undo_stack(int type, long from, long to) { undo_t *t; #if defined(sun) || defined(NO_REALLOC_NULL) if (ustack == NULL && (ustack = (undo_t *) malloc((usize = USIZE) * sizeof(undo_t))) == NULL) { fprintf(stderr, "%s\n", strerror(errno)); seterrmsg("out of memory"); return NULL; } #endif t = ustack; if (u_p < usize || (t = (undo_t *) realloc(ustack, (usize += USIZE) * sizeof(undo_t))) != NULL) { ustack = t; ustack[u_p].type = type; ustack[u_p].t = get_addressed_line_node(to); ustack[u_p].h = get_addressed_line_node(from); return ustack + u_p++; } /* out of memory - release undo stack */ fprintf(stderr, "%s\n", strerror(errno)); seterrmsg("out of memory"); clear_undo_stack(); free(ustack); ustack = NULL; usize = 0; return NULL; }
/* search_and_replace: for each line in a range, change text matching a pattern according to a substitution template; return status */ int search_and_replace(pattern_t *pat, int gflag, int kth) { undo_t *up; const char *txt; const char *eot; long lc; long xa = current_addr; int nsubs = 0; line_t *lp; int len; current_addr = first_addr - 1; for (lc = 0; lc <= second_addr - first_addr; lc++) { lp = get_addressed_line_node(++current_addr); if ((len = substitute_matching_text(pat, lp, gflag, kth)) < 0) return ERR; else if (len) { up = NULL; if (delete_lines(current_addr, current_addr) < 0) return ERR; txt = rbuf; eot = rbuf + len; SPL1(); do { if ((txt = put_sbuf_line(txt)) == NULL) { SPL0(); return ERR; } else if (up) up->t = get_addressed_line_node(current_addr); else if ((up = push_undo_stack(UADD, current_addr, current_addr)) == NULL) { SPL0(); return ERR; } } while (txt != eot); SPL0(); nsubs++; xa = current_addr; } } current_addr = xa; if (nsubs == 0 && !(gflag & GLB)) { errmsg = "no match"; return ERR; } else if ((gflag & (GPR | GLS | GNP)) && display_lines(current_addr, current_addr, gflag) < 0) return ERR; return 0; }
/* build_active_list: add line matching a pattern to the global-active list */ int build_active_list(int isgcmd) { regex_t *pat; line_t *lp; int n; char *s; char delimiter; if ((delimiter = *ibufp) == ' ' || delimiter == '\n') { seterrmsg("invalid pattern delimiter"); return ERR; } else if ((pat = get_compiled_pattern()) == NULL) return ERR; else if (*ibufp == delimiter) ibufp++; clear_active_list(); lp = get_addressed_line_node(first_addr); for (n = first_addr; n <= second_addr; n++, lp = lp->q_forw) { if ((s = get_sbuf_line(lp)) == NULL) return ERR; if (isbinary) NUL_TO_NEWLINE(s, lp->len); if (!regexec(pat, s, 0, NULL, 0) == isgcmd && set_active_node(lp) < 0) return ERR; } return 0; }
/* write_stream: write a range of lines to a stream; return status */ long write_stream(FILE *fp, long n, long m) { line_t *lp = get_addressed_line_node(n); unsigned long size = 0; char *s; int len; if (des) init_des_cipher(); for (; n && n <= m; n++, lp = lp->q_forw) { if ((s = get_sbuf_line(lp)) == NULL) return ERR; len = lp->len; if (n != addr_last || !isbinary || !newline_added) s[len++] = '\n'; if (put_stream_line(fp, s, len) < 0) return ERR; size += len; } if (des) { flush_des_file(fp); /* flush buffer */ size += 8 - size % 8; /* adjust DES size */ } return size; }
/* push_undo_stack: return pointer to initialized undo node */ undo_t * push_undo_stack(int type, int from, int to) { undo_t *t; t = ustack; if (u_p < usize || (t = reallocarray(ustack, (usize += USIZE), sizeof(undo_t))) != NULL) { ustack = t; ustack[u_p].type = type; ustack[u_p].t = get_addressed_line_node(to); ustack[u_p].h = get_addressed_line_node(from); return ustack + u_p++; } /* out of memory - release undo stack */ perror(NULL); seterrmsg("out of memory"); clear_undo_stack(); free(ustack); ustack = NULL; usize = 0; return NULL; }
/* read_stream: read a stream into the editor buffer; return status */ int read_stream(FILE *fp, int n) { line_t *lp = get_addressed_line_node(n); undo_t *up = NULL; unsigned int size = 0; int o_newline_added = newline_added; int o_isbinary = isbinary; int appended = (n == addr_last); int len; isbinary = newline_added = 0; #ifdef DES if (des) init_des_cipher(); #endif for (current_addr = n; (len = get_stream_line(fp)) > 0; size += len) { SPL1(); if (put_sbuf_line(sbuf) == NULL) { SPL0(); return ERR; } lp = lp->q_forw; if (up) up->t = lp; else if ((up = push_undo_stack(UADD, current_addr, current_addr)) == NULL) { SPL0(); return ERR; } SPL0(); } if (len < 0) return ERR; if (appended && size && o_isbinary && o_newline_added) fputs("newline inserted\n", stderr); else if (newline_added && (!appended || (!isbinary && !o_isbinary))) fputs("newline appended\n", stderr); if (isbinary && newline_added && !appended) size += 1; if (!size) newline_added = 1; newline_added = appended ? newline_added : o_newline_added; isbinary = isbinary | o_isbinary; if (des) size += 8 - size % 8; /* adjust DES size */ return size; }
/* pop_undo_stack: undo last change to the editor buffer */ int pop_undo_stack(void) { long n; long o_current_addr = current_addr; long o_addr_last = addr_last; if (u_current_addr == -1 || u_addr_last == -1) { seterrmsg("nothing to undo"); return ERR; } else if (u_p) modified = 1; get_addressed_line_node(0); /* this get_addressed_line_node last! */ SPL1(); for (n = u_p; n-- > 0;) { switch(ustack[n].type) { case UADD: REQUE(ustack[n].h->q_back, ustack[n].t->q_forw); break; case UDEL: REQUE(ustack[n].h->q_back, ustack[n].h); REQUE(ustack[n].t, ustack[n].t->q_forw); break; case UMOV: case VMOV: REQUE(ustack[n - 1].h, ustack[n].h->q_forw); REQUE(ustack[n].t->q_back, ustack[n - 1].t); REQUE(ustack[n].h, ustack[n].t); n--; break; default: /*NOTREACHED*/ ; } ustack[n].type ^= 1; } /* reverse undo stack order */ for (n = u_p; n-- > (u_p + 1)/ 2;) USWAP(ustack[n], ustack[u_p - 1 - n]); if (isglobal) clear_active_list(); current_addr = u_current_addr, u_current_addr = o_current_addr; addr_last = u_addr_last, u_addr_last = o_addr_last; SPL0(); return 0; }