diff options
| -rw-r--r-- | TODO | 2 | ||||
| -rw-r--r-- | gramscii.c | 461 | 
2 files changed, 249 insertions, 214 deletions
| @@ -1,7 +1,6 @@  + optimize redraws (i.e., avoid to redraw if possible)  - (?) change cursor shape according to action  - auto-arrow 'A' (automatic end-char) -- load from file  - read file at point  - visual selection    - crop @@ -13,6 +12,7 @@    (also do not print unmanaged chars!)  - get screen geometry  - allow scrolling (both vertical and horizontal) +* load from file  * check if modified on exit  * write to new file / default file  * delete -- 'x'  @@ -89,6 +89,70 @@ void cleanup(int s){  	exit(0);  } +/*** Status bar ***/ + +char* state_str(){ +	switch(state){ +		case MOVE: +			return "mov"; +		case TEXT: +			return "txt"; +		case BOX: +			return "box"; +		case ARROW: +			return "arr"; +		case DEL: +			return "del"; +		default: +			return "ERR"; +	} +	return "ERR";	 +} + + +void status_bar(){ +	 +	printf("\033[%d;1f\033[7m", HEIGHT+1); +	printf("%100s", " "); +	printf("\033[%d;1f\033[7m", HEIGHT+1); +	printf(" x: %3d y: %3d -- mode: %4s hl: %c vl: %c cn: %c <: %c >: %c %10s",  +		x, y, state_str(), line_h, line_v, corner, mark_st, mark_end, ""); +	printf(" [%s]", fname ); +	printf("\033[0m"); +} + +char get_key(char *s){ + +	printf("\033[%d;1f\033[7m", HEIGHT+1); +	printf("%100s", " "); +	printf("\033[%d;1f\033[7m", HEIGHT+1); +	printf("%s ", s); +	printf("\033[0m"); +	return getchar(); +} + +void get_string(char *msg, char *s, int sz){ + +	printf("\033[%d;1f\033[7m", HEIGHT+1); +	printf("%100s", " "); +	printf("\033[%d;1f\033[7m", HEIGHT+1); +	/* We must activate echo now */ +	t3 = t2; +	t3.c_lflag |= (ECHO | ICANON); +	tcsetattr(0, TCSANOW, &t3); +	printf("%s", msg); +	printf("\033[0m"); +	fgets(s, sz, stdin); +	s[strlen(s)-1] = '\0'; +	tcsetattr(0, TCSANOW, &t2); +} + +int is_yes(char c){ +	return c=='y' ? 1 : c == 'Y'? 1 : 0; +} + +/*** Screen management ***/ +  void show_cursor(){  	printf("\033[%d;%df", y+1, x+1);  } @@ -108,6 +172,31 @@ void draw_xy(int x, int y, char c){  	putchar(c);	  } +void update_current(){ +	printf("\033[%d'%df",y+1,x+1); +	putchar(screen[y][x]); +} + +void erase_line(char *s){ +	while(*s){ +		*s++ = BG; +	} +} + +void erase_screen(){ +	int i; +	for(i=0;i<HEIGHT; i++) +		erase_line(screen[i]); +} + + +void check_bound(){ +	if (x<0) x=0; +	else if (x>=WIDTH) x = WIDTH-1; +	if (y<0) y=0; +	else if (y>=HEIGHT) y = HEIGHT -1;  +} +  void init_screen(){  	int i;  	for(i=0; i<HEIGHT; i++){ @@ -124,36 +213,6 @@ void init_screen(){  	mark_end = end_marks[cur_end];  } -char* state_str(){ -	switch(state){ -		case MOVE: -			return "mov"; -		case TEXT: -			return "txt"; -		case BOX: -			return "box"; -		case ARROW: -			return "arr"; -		case DEL: -			return "del"; -		default: -			return "ERR"; -	} -	return "ERR";	 -} - - -void status_bar(){ -	 -	printf("\033[%d;1f\033[7m", HEIGHT+1); -	printf("%100s", " "); -	printf("\033[%d;1f\033[7m", HEIGHT+1); -	printf(" x: %3d y: %3d -- mode: %4s hl: %c vl: %c cn: %c <: %c >: %c %10s",  -		x, y, state_str(), line_h, line_v, corner, mark_st, mark_end, ""); -	printf(" [%s]", fname ); -	printf("\033[0m"); -} -  void redraw(){  	int i; @@ -165,12 +224,99 @@ void redraw(){  	show_cursor();  } -void update_current(){ -	printf("\033[%d'%df",y+1,x+1); -	putchar(screen[y][x]); +int move_around(char c){ + +	switch(c){ +		case 'H': step = 5; +		case 'h':  +			dir = DIR_L; +			x -= step; +			break;	 +		case 'J': step = 5; +		case 'j': +			dir = DIR_D; +			y += step; +			break; +		case 'K': step = 5; +		case 'k': +			dir = DIR_U; +			y -= step; +			break; +		case 'L': step = 5; +		case 'l': +			dir = DIR_R; +			x += step; +			break; +		default: +			return 0; +	} +	return 1; +} + +void go_to(int where){ +	switch(where){ +		case HOME: +			x = y = 0; +			break; +		case END: +			x = WIDTH-1; +			y = HEIGHT-1; +			break; +		case MIDDLE: +			x = WIDTH/2; +			y = HEIGHT/2; +			break; +	} +	check_bound(); +	show_cursor(); +} + +int progr_x(int dir){ +	return dir == DIR_L ? -1 : dir == DIR_R ? 1: 0;  } +int progr_y(int dir){ +	return dir == DIR_U ? -1 : dir == DIR_D ? 1: 0; +} + +/*** Lines and markers ***/ + +void toggle_hline(){ + +	cur_hl = (cur_hl + 1) % hlines_sz; +	line_h = hlines[cur_hl]; +	 +} + +void toggle_corner(){ +	 +	cur_corn = (cur_corn + 1 ) % corners_sz; +	corner = corners[cur_corn]; + +} + +void toggle_vline(){ + +	cur_vl = (cur_vl + 1) % vlines_sz; +	line_v = vlines[cur_vl]; + +} + +void toggle_st_mark(){ +	 +	cur_start = (cur_start + 1 ) % stmarks_sz; +	mark_st = st_marks[cur_start]; +} + +void toggle_end_mark(){ +	 +	cur_end = (cur_end+ 1 ) % endmarks_sz; +	mark_end = end_marks[cur_end]; +} + + +  void init(){  	signal(SIGHUP, cleanup); @@ -191,13 +337,6 @@ void init(){  	redraw();  } -void check_bound(){ -	if (x<0) x=0; -	else if (x>=WIDTH) x = WIDTH-1; -	if (y<0) y=0; -	else if (y>=HEIGHT) y = HEIGHT -1;  -} -  /*****  text, box, arrows  *****/ @@ -215,6 +354,7 @@ void get_text(){  		else {  			set(c);  			update_current(); +			modified = 1;  			x += 1;  			if (x >= WIDTH)  				x = orig_x; @@ -259,35 +399,6 @@ void draw_box(int x1, int y1, int fix){  } -int move_around(char c){ - -	switch(c){ -		case 'H': step = 5; -		case 'h':  -			dir = DIR_L; -			x -= step; -			break;	 -		case 'J': step = 5; -		case 'j': -			dir = DIR_D; -			y += step; -			break; -		case 'K': step = 5; -		case 'k': -			dir = DIR_U; -			y -= step; -			break; -		case 'L': step = 5; -		case 'l': -			dir = DIR_R; -			x += step; -			break; -		default: -			return 1; -	} -	return 0; -} -  void get_box(){  	char c; @@ -296,7 +407,7 @@ void get_box(){  	step = 1;  	draw_box(x,y,NOFIX);  	while((c=getchar())!=EOF && c != 27 && c!= 'b'){ -		if (move_around(c)) continue; +		if (!move_around(c)) continue;  		check_bound();  		redraw();  		step = 1; @@ -312,17 +423,6 @@ void get_box(){  	state = MOVE;  } - -int progr_x(int dir){ -	return dir == DIR_L ? -1 : dir == DIR_R ? 1: 0; -} - - -int progr_y(int dir){ -	return dir == DIR_U ? -1 : dir == DIR_D ? 1: 0; -} - -  void draw_arrow(int x, int y, char *a, int a_len, int fix){  	int i, j, cur_dir; @@ -381,7 +481,7 @@ void get_arrow(){  	step = 1;  	draw_arrow(x,y, arrow, 0, NOFIX);  	while((c=getchar())!=EOF && c != 27 && c!= 'a'){ -		if (move_around(c)) continue; +		if (!move_around(c)) continue;  		check_bound();  		/* FIXME: if we are out of bound, do nothing? */  		if (arrow_len == arrow_sz){ @@ -404,112 +504,6 @@ void get_arrow(){  	state = MOVE;  } -char get_key(char *s){ - -	printf("\033[%d;1f\033[7m", HEIGHT+1); -	printf("%100s", " "); -	printf("\033[%d;1f\033[7m", HEIGHT+1); -	printf("%s ", s); -	printf("\033[0m"); -	return getchar(); -} - -void get_string(char *s, int sz){ - -	printf("\033[%d;1f\033[7m", HEIGHT+1); -	printf("%100s", " "); -	printf("\033[%d;1f\033[7m", HEIGHT+1); -	/* We must activate echo now */ -	t3 = t2; -	t3.c_lflag |= (ECHO | ICANON); -	tcsetattr(0, TCSANOW, &t3); -	printf("Write to: "); -	printf("\033[0m"); -	fgets(s, sz, stdin); -	s[strlen(s)-1] = '\0'; -	tcsetattr(0, TCSANOW, &t2); -} - -int is_yes(char c){ -	return c=='y' ? 1 : c == 'Y'? 1 : 0; -} - -void write_file(){ -	FILE *f; -	int i; -	 -	if (!fname[0] || force_new){ -		get_string(fname, 255); -		if (f=fopen(fname, "r")){ -			if (!is_yes(get_key("File exists. Overwrite [y/n]?")) ){ -				fclose(f); -				return; -			} -			fclose(f); -		} -	} -	if((f=fopen(fname, "w"))==NULL){ -		get_key("Error opening file."); -		return; -	} -	for (i=0; i<HEIGHT; i++){ -		fprintf(f, "%s\n", screen[i]); -	} -	fclose(f); -	modified = 0; -	get_key("File saved."); -} - -void toggle_hline(){ - -	cur_hl = (cur_hl + 1) % hlines_sz; -	line_h = hlines[cur_hl]; -	 -} - -void toggle_corner(){ -	 -	cur_corn = (cur_corn + 1 ) % corners_sz; -	corner = corners[cur_corn]; - -} - -void toggle_vline(){ - -	cur_vl = (cur_vl + 1) % vlines_sz; -	line_v = vlines[cur_vl]; - -} - -void toggle_st_mark(){ -	 -	cur_start = (cur_start + 1 ) % stmarks_sz; -	mark_st = st_marks[cur_start]; -} - -void toggle_end_mark(){ -	 -	cur_end = (cur_end+ 1 ) % endmarks_sz; -	mark_end = end_marks[cur_end]; -} - -void go_to(int where){ -	switch(where){ -		case HOME: -			x = y = 0; -			break; -		case END: -			x = WIDTH-1; -			y = HEIGHT-1; -			break; -		case MIDDLE: -			x = WIDTH/2; -			y = HEIGHT/2; -			break; -	} -	check_bound(); -	show_cursor(); -}  void do_delete(int x1, int y1){  	int i; @@ -536,7 +530,7 @@ void delete(){  	status_bar();  	show_cursor();  	while((c=getchar())!=EOF && c!=27 && c!= 'x'){ -		if (move_around(c)) continue; +		if (!move_around(c)) continue;  		check_bound();  		step = 1;  		do_delete(orig_x, orig_y); @@ -550,6 +544,34 @@ void delete(){  	state = MOVE;  } +/*** File management ***/ + +void write_file(){ +	FILE *f; +	int i; +	 +	if (!fname[0] || force_new){ +		get_string("Write to: ", fname, 255); +		if (f=fopen(fname, "r")){ +			if (!is_yes(get_key("File exists. Overwrite [y/n]?")) ){ +				fclose(f); +				return; +			} +			fclose(f); +		} +	} +	if((f=fopen(fname, "w"))==NULL){ +		get_key("Error opening file."); +		return; +	} +	for (i=0; i<HEIGHT; i++){ +		fprintf(f, "%s\n", screen[i]); +	} +	fclose(f); +	modified = 0; +	get_key("File saved."); +} +  void check_modified(){  	if (modified){ @@ -560,34 +582,41 @@ void check_modified(){  	}  } +void load_file(){ + +	char newfname[256]; +	FILE *f; +	int i; + +	get_string("Load file: ", newfname, 255); +	if ((f=fopen(newfname, "r")) != NULL){ +		i = 0; +		while((fgets(screen[i], WIDTH+2, f)) != NULL && i<HEIGHT) +			screen[i++][WIDTH-1]='\0'; +		for(;i<HEIGHT; i++){ +			erase_line(screen[i]); +		} +		fclose(f); +	} +	strcpy(fname, newfname); +	modified=0; +	redraw(); +} +void new_file(){ +	check_modified(); +	erase_screen(); +	go_to(MIDDLE); +	redraw(); +	fname[0] = '\0'; +	modified=0; +}  void commands(){  	char c;  	while((c=getchar())!=EOF){ -		//screen[y][x]=BG; -		switch(c){ -			case 'H': -				step=5; -			case 'h': -				x-=step; -				break; -			case 'J': -				step=5; -			case 'j': -				y+=step; -				break; -			case 'K': -				step=5; -			case 'k': -				y-=step; -				break; -			case 'L': -				step=5; -			case 'l': -				x+=step; -				break; +		if (!move_around(c)) switch(c){  			case 'i':  				state = TEXT;  				get_text(); @@ -608,6 +637,14 @@ void commands(){  			case 'w':  				write_file();  				break; +			case 'e': +				check_modified(); +			case 'E': +				load_file(); +				break; +			case 'N': +				new_file(); +				break;  			case 'g':  				go_to(HOME);  				break; @@ -642,8 +679,6 @@ void commands(){  				cleanup(0);  				exit(0);  				break; -			default:; -				//statu("got: %d\n", c);  		}  		check_bound();  		status_bar(); | 
