#include #include #include #include #include "gui.h" #include "editor.h" #include "keys.h" struct s_edit_buf edit_buf; int edit_buf_init( struct s_edit_buf * buf ) { memset( (char*)buf, 0, sizeof(struct s_edit_buf) ); buf->blocksize = EDIT_BUF_DEFAULT_BLOCKSIZE; edit_buf_destroy( buf ); buf->data = malloc( buf->blocksize ); if( buf->data == NULL ) return( 1 ); buf->size = buf->blocksize; buf->data[0] = 0; buf->used = 1; return( 0 ); } void edit_buf_destroy( struct s_edit_buf * buf ) { if( buf->data ) free( buf->data ); buf->data = NULL; } void edit_buf_alloc( struct s_edit_buf * buf, int amount ) { int blocks = 1; if( buf->size < (buf->used + amount)+1 ){ if( amount > buf->blocksize) blocks = (amount / buf->blocksize)+1; buf->data = realloc( buf->data, buf->size+(buf->blocksize*blocks)); buf->size += (buf->blocksize*blocks); } } long edit_buf_find_linestart( struct s_edit_buf * buf, long curpos, long skip, long direction ) { long i; if( direction == 0 ) return( -1 ); if( buf == NULL) return( -1 ); if( curpos > buf->used-1 ) return( buf->used-1 ); if( skip > 0 ) { curpos = edit_buf_find_linestart( buf, curpos, 0, direction ); skip--; if( curpos > 0 && skip >0 ){ return( edit_buf_find_linestart( buf, curpos, skip, direction ) ); } return( curpos ); } curpos += direction; if( direction > 0 && curpos <= 0 ) { return( 0 ); } for( i=curpos; i>=1; i=i+direction){ if(buf->data[i] == 10 || buf->data[i] == 13 || buf->data[i] == 0 ){ return( i ) ; } } return( -1 ); } void edit_buf_redraw( struct s_edit_buf * buf ) { char * out = " "; int cury = 1; int curx = 0; int curline = 1; int i=0; int len; long lines_limit; long lines_done=0; short inv=0; len = strlen( buf->data ); lines_limit = c_rows-2; #ifndef WITHOUT_GFX cury = 4; lines_limit -= 3; #endif if( i >= buf->redraw_start_at_char ) fillspace(0, cury, c_cols, 0); for( i = 0; i<=len; i++ ) { if( buf->data[i] == 13 || buf->data[i] == 10 ) { if( i >= buf->redraw_start_at_char ){ fillspace(curx, cury, c_cols, 0); if( buf->cursor == i ) textxy( curx, cury, 1, " " ); lines_done++; if( lines_done >= lines_limit ) break; } curx = 0; cury++; if( cury > c_rows-2 ) break; continue; } else { if( buf->scroll_y < cury && curx < c_cols-1 ) { *out = buf->data[i]; if( *out == 0 ) *out = ' '; if( i == buf->cursor ) inv = 1; if( i >= buf->redraw_start_at_char ){ textxy( curx, cury, inv, out ); } if( inv == 1 ) inv = 0; if( buf->data[i] == 0 ){ break; } } curx++; } } } void edit_buf_insert( struct s_edit_buf * buf, unsigned char * c ) { int i, pos; int len = strlen( c ); edit_buf_alloc( buf, len ); memmove( &buf->data[buf->cursor+len], &buf->data[buf->cursor], strlen(&buf->data[buf->cursor]) ); for( i=0; icursor+i; if( c[i] == 13 || c[i] == 10 ) { buf->lines++; } buf->data[pos] = c[i]; buf->used++; } buf->data[buf->used-1] = 0; buf->redraw_start_at_char = (buf->cursor>0 ) ? buf->cursor-1 : 0; buf->redraw_limit_lines = -1; /* newline may cause reflow */ buf->cursor += len; edit_buf_redraw( buf ); } void edit_buf_remove( struct s_edit_buf * buf ) { buf->used--; } char * edit_text( char * title, char * text ) { short code, key; char ascii, sh; char exit = 0; int i=0, x=0, z=0; char ig=0; char tmp[3]=""; char * result=NULL; long nextbest; long maybest; draw_info("ESC=Exit without save, F2=Save"); for( i=1; i 0 ) { edit_buf.cursor--; edit_buf.redraw_limit_lines = 2; edit_buf.redraw_start_at_char = edit_buf.cursor; edit_buf_redraw( &edit_buf ); edit_buf.cursor++; memmove( &edit_buf.data[edit_buf.cursor-1], &edit_buf.data[edit_buf.cursor], strlen(&edit_buf.data[edit_buf.cursor])+1 ); edit_buf.cursor--; edit_buf.redraw_start_at_char = (edit_buf.cursor>0 ) ? edit_buf.cursor-1 : 0; edit_buf.redraw_limit_lines = -1; edit_buf.used--; edit_buf.data[edit_buf.used-1] = 0; edit_buf_redraw( &edit_buf ); } break; case CURS_UP: ig = 1; nextbest = edit_buf_find_linestart( &edit_buf, edit_buf.cursor, 0, -1); maybest = edit_buf_find_linestart( &edit_buf, nextbest-1, 0, -1); if( nextbest != -1 && maybest < nextbest && maybest >= 0 ) { if( maybest+(edit_buf.cursor-nextbest) < nextbest ){ nextbest = maybest+(edit_buf.cursor-nextbest); } } if( nextbest > -1 ) { edit_buf.redraw_start_at_char = nextbest; edit_buf.redraw_limit_lines = 4; edit_buf.cursor = nextbest; edit_buf_redraw( &edit_buf ); } break; case CURS_DOWN: ig = 1; z = edit_buf_find_linestart( &edit_buf, edit_buf.cursor, 0, -1); if( z>=0 ){ z = edit_buf.cursor-z; } else { z = 0; } nextbest = edit_buf_find_linestart( &edit_buf, edit_buf.cursor-1, 0, +1); if( nextbest != -1 ) { maybest = edit_buf_find_linestart( &edit_buf, nextbest+1, 0, +1); nextbest += z; if( nextbest > maybest ) { nextbest = maybest; } if( nextbest > -1 ) { edit_buf.redraw_start_at_char = edit_buf.cursor; edit_buf.redraw_limit_lines = 4; edit_buf.cursor = nextbest; edit_buf_redraw( &edit_buf ); } } break; case CURS_LEFT: if( edit_buf.cursor > 0 ){ edit_buf.cursor--; edit_buf.redraw_limit_lines = 2; edit_buf.redraw_start_at_char = edit_buf.cursor; edit_buf_redraw( &edit_buf ); } ig = 1; break; case CURS_RIGHT: if( edit_buf.cursor < edit_buf.used-1 ){ edit_buf.redraw_start_at_char = edit_buf.cursor; edit_buf.cursor++; edit_buf.redraw_limit_lines = 2; edit_buf_redraw( &edit_buf ); } ig = 1; break; default: break; } if( ig == 1 || exit == 1 ) continue; if( (char)key == 0 ) continue; if( key == 13 ) key = 10; *tmp = (char)key; edit_buf_insert( &edit_buf, tmp ); } while( exit != 1 ); return( result ); } void end_edit_text( ) { edit_buf_destroy( &edit_buf ); }