/* get a line of text from the scratch file; return pointer to the text */ char * get_sbuf_line( const line_t * const lp ) { static char * buf = 0; static int bufsz = 0; int len; if( lp == &buffer_head ) return 0; seek_write = true; /* force seek on write */ /* out of position */ if( sfpos != lp->pos ) { sfpos = lp->pos; if( fseek( sfp, sfpos, SEEK_SET ) != 0 ) { show_strerror( 0, errno ); set_error_msg( "Cannot seek temp file" ); return 0; } } len = lp->len; if( !resize_buffer( &buf, &bufsz, len + 1 ) ) return 0; if( (int)fread( buf, 1, len, sfp ) != len ) { show_strerror( 0, errno ); set_error_msg( "Cannot read temp file" ); return 0; } sfpos += len; /* update file position */ buf[len] = 0; return buf; }
/* write a line of text to the scratch file and add a line node to the editor buffer; return a pointer to the end of the text */ const char * put_sbuf_line( const char * const buf, const int size, const int addr ) { line_t * const lp = dup_line_node( 0 ); const char * const p = (const char *) memchr( buf, '\n', size ); int len; if( !lp ) return 0; if( !p ) { set_error_msg( "Line too long" ); return 0; } len = p - buf; /* out of position */ if( seek_write ) { if( fseek( sfp, 0L, SEEK_END ) != 0 ) { show_strerror( 0, errno ); set_error_msg( "Cannot seek temp file" ); return 0; } sfpos = ftell( sfp ); seek_write = false; } if( (int)fwrite( buf, 1, len, sfp ) != len ) /* assert: interrupts disabled */ { sfpos = -1; show_strerror( 0, errno ); set_error_msg( "Cannot write temp file" ); return 0; } lp->pos = sfpos; lp->len = len; add_line_node( lp, addr ); ++current_addr_; sfpos += len; /* update file position */ return p + 1; }
/* return pointer to compiled pattern from command buffer */ static regex_t *get_compiled_pattern( const char **ibufpp ) { static regex_t *exp = 0; char *exps; const char delimiter = **ibufpp; int n; if( delimiter == ' ' ) { set_error_msg( "Invalid pattern delimiter" ); return 0; } if( delimiter == '\n' || *++(*ibufpp) == '\n' || **ibufpp == delimiter ) { if( !exp ) set_error_msg( "No previous pattern" ); return exp; } if( !( exps = extract_pattern( ibufpp, delimiter ) ) ) return 0; /* buffer alloc'd && not reserved */ if( exp && !patlock ) regfree( exp ); else if( !( exp = ( regex_t *) malloc( sizeof( regex_t ) ) ) ) { show_strerror( 0, errno ); set_error_msg( "Memory exhausted" ); return 0; } patlock = 0; n = regcomp( exp, exps, 0 ); if( n ) { char buf[80]; regerror( n, exp, buf, sizeof( buf ) ); set_error_msg( buf ); free( exp ); exp = 0; } return exp; }
/* return a pointer to a copy of a line node, or to a new node if lp == 0 */ static line_t * dup_line_node( line_t * const lp ) { line_t * const p = (line_t *) malloc( sizeof (line_t) ); if( !p ) { show_strerror( 0, errno ); set_error_msg( "Memory exhausted" ); return 0; } if( lp ) { p->pos = lp->pos; p->len = lp->len; } return p; }
/* open scratch file */ bool open_sbuf( void ) { isbinary_ = newline_added_ = false; sfp = tmpfile(); if( !sfp ) { show_strerror( 0, errno ); set_error_msg( "Cannot open temp file" ); return false; } return true; }
/* add a line node to the global-active list */ bool set_active_node( const line_t * const lp ) { disable_interrupts(); if( !resize_line_buffer( &active_list, &active_size, ( active_len + 1 ) * sizeof (line_t **) ) ) { show_strerror( 0, errno ); set_error_msg( "Memory exhausted" ); enable_interrupts(); return false; } enable_interrupts(); active_list[active_len++] = lp; return true; }
/* close scratch file */ bool close_sbuf( void ) { clear_yank_buffer(); clear_undo_stack(); if( sfp ) { if( fclose( sfp ) != 0 ) { show_strerror( 0, errno ); set_error_msg( "Cannot close temp file" ); return false; } sfp = 0; } sfpos = 0; seek_write = false; return true; }
/* assure at least a minimum size for buffer 'buf' */ bool resize_buffer( char ** const buf, int * const size, const int min_size ) { if( *size < min_size ) { const int new_size = ( min_size < 512 ? 512 : ( min_size / 512 ) * 1024 ); void * new_buf = 0; disable_interrupts(); if( *buf ) new_buf = realloc( *buf, new_size ); else new_buf = malloc( new_size ); if( !new_buf ) { show_strerror( 0, errno ); set_error_msg( "Memory exhausted" ); enable_interrupts(); return false; } *size = new_size; *buf = (char *)new_buf; enable_interrupts(); } return true; }
/* return pointer to intialized undo node */ undo_t * push_undo_atom( const int type, const int from, const int to ) { disable_interrupts(); if( !resize_undo_buffer( &ustack, &usize, ( u_ptr + 1 ) * sizeof (undo_t) ) ) { show_strerror( 0, errno ); set_error_msg( "Memory exhausted" ); if( ustack ) { clear_undo_stack(); free( ustack ); ustack = 0; usize = u_ptr = 0; u_current_addr = u_last_addr = -1; } enable_interrupts(); return 0; } enable_interrupts(); ustack[u_ptr].type = type; ustack[u_ptr].tail = search_line_node( to ); ustack[u_ptr].head = search_line_node( from ); return ustack + u_ptr++; }