/* replace a range of lines with the joined text of those lines */ bool join_lines( const int from, const int to, const bool isglobal ) { static char * buf = 0; static int bufsz = 0; int size = 0; line_t * const ep = search_line_node( inc_addr( to ) ); line_t * bp = search_line_node( from ); while( bp != ep ) { const char * const s = get_sbuf_line( bp ); if( !s || !resize_buffer( &buf, &bufsz, size + bp->len ) ) return false; memcpy( buf + size, s, bp->len ); size += bp->len; bp = bp->q_forw; } if( !resize_buffer( &buf, &bufsz, size + 2 ) ) return false; memcpy( buf + size, "\n", 2 ); size += 2; if( !delete_lines( from, to, isglobal ) ) return false; current_addr_ = from - 1; disable_interrupts(); if( !put_sbuf_line( buf, size, current_addr_ ) || !push_undo_atom( UADD, current_addr_, current_addr_ ) ) { enable_interrupts(); return false; } modified_ = true; enable_interrupts(); return true; }
/* 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; }
/* substitute_matching_text: replace text matched by a pattern according to a substitution template; return pointer to the modified text */ int substitute_matching_text(pattern_t *pat, line_t *lp, int gflag, int kth) { int off = 0; int changed = 0; int matchno = 0; int i = 0; regmatch_t rm[SE_MAX]; char *txt; char *eot; if ((txt = get_sbuf_line(lp)) == NULL) return ERR; if (isbinary) NUL_TO_NEWLINE(txt, lp->len); eot = txt + lp->len; if (!regexec(pat, txt, SE_MAX, rm, 0)) { do { if (!kth || kth == ++matchno) { changed++; i = rm[0].rm_so; REALLOC(rbuf, rbufsz, off + i, ERR); if (isbinary) NEWLINE_TO_NUL(txt, rm[0].rm_eo); memcpy(rbuf + off, txt, i); off += i; if ((off = apply_subst_template(txt, rm, off, pat->re_nsub)) < 0) return ERR; } else { i = rm[0].rm_eo; REALLOC(rbuf, rbufsz, off + i, ERR); if (isbinary) NEWLINE_TO_NUL(txt, i); memcpy(rbuf + off, txt, i); off += i; } txt += rm[0].rm_eo; } while (*txt && (!changed || ((gflag & GSG) && rm[0].rm_eo)) && !regexec(pat, txt, SE_MAX, rm, REG_NOTBOL)); i = eot - txt; REALLOC(rbuf, rbufsz, off + i + 2, ERR); if (i > 0 && !rm[0].rm_eo && (gflag & GSG)) { errmsg = "infinite substitution loop"; return ERR; } if (isbinary) NEWLINE_TO_NUL(txt, i); memcpy(rbuf + off, txt, i); memcpy(rbuf + off + i, "\n", 2); } return changed ? off + i + 1 : 0; }
/* replace text matched by a pattern according to a substitution template; return pointer to the modified text */ static int replace_matching_text( const line_t *lp, const int gflags, const int snum ) { const int se_max = 30; /* max subexpressions in a regular expression */ regmatch_t rm[se_max]; char *txt = get_sbuf_line( lp ); char *eot; int i = 0, off = 0; char changed = 0; if( !txt ) return -1; if( isbinary() ) nul_to_newline( txt, lp->len ); eot = txt + lp->len; if( !regexec( global_pat, txt, se_max, rm, 0 ) ) { int matchno = 0; do { if( !snum || snum == ++matchno ) { changed = 1; i = rm[0].rm_so; if( !resize_buffer( &rbuf, &rbufsz, off + i ) ) return -1; if( isbinary() ) newline_to_nul( txt, rm[0].rm_eo ); memcpy( rbuf + off, txt, i ); off += i; off = apply_subst_template( txt, rm, off, global_pat->re_nsub ); if( off < 0 ) return -1; } else { i = rm[0].rm_eo; if( !resize_buffer( &rbuf, &rbufsz, off + i ) ) return -1; if( isbinary() ) newline_to_nul( txt, i ); memcpy( rbuf + off, txt, i ); off += i; } txt += rm[0].rm_eo; } while( *txt && ( !changed || ( ( gflags & GSG ) && rm[0].rm_eo ) ) && !regexec( global_pat, txt, se_max, rm, REG_NOTBOL ) ); i = eot - txt; if( !resize_buffer( &rbuf, &rbufsz, off + i + 2 ) ) return -1; if( i > 0 && !rm[0].rm_eo && ( gflags & GSG ) ) { set_error_msg( "Infinite substitution loop" ); return -1; } if( isbinary() ) newline_to_nul( txt, i ); memcpy( rbuf + off, txt, i ); memcpy( rbuf + off + i, "\n", 2 ); } return ( changed ? off + i + 1 : 0 ); }
/* return the address of the next line matching a pattern in a given direction. wrap around begin/end of editor buffer if necessary */ int get_matching_node_addr( const char **ibufpp, const char forward ) { regex_t *pat = get_compiled_pattern( ibufpp ); int addr = current_addr(); if( !pat ) return -1; do { addr = ( forward ? inc_addr( addr ) : dec_addr( addr ) ); if( addr ) { line_t *lp = search_line_node( addr ); char *s = get_sbuf_line( lp ); if( !s ) return -1; if( isbinary() ) nul_to_newline( s, lp->len ); if( !regexec( pat, s, 0, 0, 0 ) ) return addr; } } while( addr != current_addr() ); set_error_msg( "No match" ); return -1; }
/* add line matching a pattern to the global-active list */ char build_active_list( const char **ibufpp, const int first_addr, const int second_addr, const char match ) { regex_t *pat; line_t *lp; int addr; const char delimiter = **ibufpp; if( delimiter == ' ' || delimiter == '\n' ) { set_error_msg( "Invalid pattern delimiter" ); return 0; } if( !( pat = get_compiled_pattern( ibufpp ) ) ) return 0; if( **ibufpp == delimiter ) ++(*ibufpp); clear_active_list(); lp = search_line_node( first_addr ); for( addr = first_addr; addr <= second_addr; ++addr, lp = lp->q_forw ) { char *s = get_sbuf_line( lp ); if( !s ) return 0; if( isbinary() ) nul_to_newline( s, lp->len ); if( !regexec( pat, s, 0, 0, 0 ) == match && !set_active_node( lp ) ) return 0; } return 1; }