/* 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; }
/* append lines from the yank buffer */ bool put_lines( const int addr ) { undo_t * up = 0; line_t *p, *lp = yank_buffer_head.q_forw; if( lp == &yank_buffer_head ) { set_error_msg( "Nothing to put" ); return false; } current_addr_ = addr; while( lp != &yank_buffer_head ) { disable_interrupts(); p = dup_line_node( lp ); if( !p ) { enable_interrupts(); return false; } add_line_node( p, current_addr_++ ); if( up ) up->tail = p; else { up = push_undo_atom( UADD, current_addr_, current_addr_ ); if( !up ) { enable_interrupts(); return false; } } modified_ = true; lp = lp->q_forw; enable_interrupts(); } return true; }
/* copy a range of lines; return false if error */ bool copy_lines( const int first_addr, const int second_addr, const int addr ) { line_t *lp, *np = search_line_node( first_addr ); undo_t * up = 0; int n = second_addr - first_addr + 1; int m = 0; current_addr_ = addr; if( addr >= first_addr && addr < second_addr ) { n = addr - first_addr + 1; m = second_addr - addr; } for( ; n > 0; n = m, m = 0, np = search_line_node( current_addr_ + 1 ) ) for( ; n-- > 0; np = np->q_forw ) { disable_interrupts(); lp = dup_line_node( np ); if( !lp ) { enable_interrupts(); return false; } add_line_node( lp, current_addr_++ ); if( up ) up->tail = lp; else { up = push_undo_atom( UADD, current_addr_, current_addr_ ); if( !up ) { enable_interrupts(); return false; } } modified_ = true; enable_interrupts(); } return true; }
/* for each line in a range, change text matching a pattern according to a substitution template; return false if error */ char search_and_replace( const int first_addr, const int second_addr, const int gflags, const int snum, const char isglobal ) { int lc; char match_found = 0; set_current_addr( first_addr - 1 ); for( lc = 0; lc <= second_addr - first_addr; ++lc ) { line_t *lp = search_line_node( inc_current_addr() ); int len = replace_matching_text( lp, gflags, snum ); if( len < 0 ) return 0; if( len ) { const char *txt = rbuf; const char *eot = rbuf + len; undo_t *up = 0; disable_interrupts(); if( !delete_lines( current_addr(), current_addr(), isglobal ) ) return 0; do { txt = put_sbuf_line( txt, current_addr() ); if( !txt ) { enable_interrupts(); return 0; } if( up ) up->tail = search_line_node( current_addr() ); else if( !( up = push_undo_atom( UADD, -1, -1 ) ) ) { enable_interrupts(); return 0; } } while( txt != eot ); enable_interrupts(); match_found = 1; } } if( !match_found && !( gflags & GLB ) ) { set_error_msg( "No match" ); return 0; } return 1; }
/* move a range of lines */ bool move_lines( const int first_addr, const int second_addr, const int addr, const bool isglobal ) { line_t *b1, *a1, *b2, *a2; int n = inc_addr( second_addr ); int p = first_addr - 1; disable_interrupts(); if( addr == first_addr - 1 || addr == second_addr ) { a2 = search_line_node( n ); b2 = search_line_node( p ); current_addr_ = second_addr; } else if( !push_undo_atom( UMOV, p, n ) || !push_undo_atom( UMOV, addr, inc_addr( addr ) ) ) { enable_interrupts(); return false; } else { a1 = search_line_node( n ); if( addr < first_addr ) { b1 = search_line_node( p ); b2 = search_line_node( addr ); /* this search_line_node last! */ } else { b2 = search_line_node( addr ); b1 = search_line_node( p ); /* this search_line_node last! */ } a2 = b2->q_forw; link_nodes( b2, b1->q_forw ); link_nodes( a1->q_back, a2 ); link_nodes( b1, a1 ); current_addr_ = addr + ( ( addr < first_addr ) ? second_addr - first_addr + 1 : 0 ); } if( isglobal ) unset_active_nodes( b2->q_forw, a2 ); modified_ = true; enable_interrupts(); return true; }
/* delete a range of lines */ bool delete_lines( const int from, const int to, const bool isglobal ) { line_t *n, *p; if( !yank_lines( from, to ) ) return false; disable_interrupts(); if( !push_undo_atom( UDEL, from, to ) ) { enable_interrupts(); return false; } n = search_line_node( inc_addr( to ) ); p = search_line_node( from - 1 ); /* this search_line_node last! */ if( isglobal ) unset_active_nodes( p->q_forw, n ); link_nodes( p, n ); last_addr_ -= to - from + 1; current_addr_ = from - 1; modified_ = true; enable_interrupts(); return true; }
/* Insert text from stdin (or from command buffer if global) to after line n; stop when either a single period is read or EOF. Return false if insertion fails. */ bool append_lines( const char ** const ibufpp, const int addr, const bool isglobal ) { int size = 0; undo_t * up = 0; current_addr_ = addr; while( true ) { if( !isglobal ) { *ibufpp = get_tty_line( &size ); if( !*ibufpp ) return false; if( size == 0 || (*ibufpp)[size-1] != '\n' ) { clearerr( stdin ); return ( size == 0 ); } } else { if( !**ibufpp ) return true; for( size = 0; (*ibufpp)[size++] != '\n'; ) ; } if( size == 2 && **ibufpp == '.' ) { *ibufpp += size; return true; } disable_interrupts(); if( !put_sbuf_line( *ibufpp, size, current_addr_ ) ) { enable_interrupts(); return false; } if( up ) up->tail = search_line_node( current_addr_ ); else { up = push_undo_atom( UADD, current_addr_, current_addr_ ); if( !up ) { enable_interrupts(); return false; } } *ibufpp += size; modified_ = true; enable_interrupts(); } }