#include #include #include "gramscii.h" #include "config.h" /*** drawing-related functions ***/ /*** 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]; } int change_style(char c){ switch(c){ case '-': toggle_hline(); break; case '|': toggle_vline(); break; case '+': toggle_corner(); break; case '<': toggle_st_mark(); break; case '>': toggle_end_mark(); break; case '.': reset_styles(); break; default: return 0; } return c; } /***** text, box, arrows *****/ void get_text(FILE *fc){ char c; int orig_x = x; redraw(); copy_lines_to_ring(y, y, PRV_STATE); while((c=fgetc(fc))!=EOF && c != 27){ if(c=='\n'){ set_cur(BG); copy_lines_to_ring(y,y, NEW_STATE); y += 1; copy_lines_to_ring(y, y, PRV_STATE); x = orig_x; } else { set_cur(c); update_current(); modified = 1; x += 1; if (x >= WIDTH) x = orig_x; } check_bound(); status_bar(); show_cursor(); } if (modified) copy_lines_to_ring(y, y, NEW_STATE); mode=MOVE; } void draw_box(int x1, int y1, int fix){ int xmin, ymin, xmax, ymax; int i; void (*f)(int, int, char); xmin = MIN(x, x1); xmax = MAX(x, x1); ymin = MIN(y, y1); ymax = MAX(y, y1); if (fix == FIX){ f = set_xy; copy_lines_to_ring(ymin, ymax, PRV_STATE); } else f = draw_xy; for(i=xmin+1; i<=xmax; i++){ f(i, ymin, line_h); f(i, ymax, line_h); } for(i=ymin+1; i<=ymax; i++){ f(xmin, i, line_v); f(xmax, i, line_v); } f(xmin, ymin, corner); f(xmin, ymax, corner); f(xmax, ymin, corner); f(xmax, ymax, corner); if (fix == FIX) copy_lines_to_ring(ymin, ymax, NEW_STATE); show_cursor(); } void get_box(FILE *fc){ char c; int orig_x=x, orig_y=y; redraw(); step = 1; draw_box(x,y,NOFIX); while((c=fgetc(fc))!=EOF && c != 27 && c!= 'b' && c != '\n'){ if (change_style(c)) goto update_box; if (!move_around(c, fc)) continue; check_bound(); redraw(); step = 1; update_box: draw_box(orig_x, orig_y, NOFIX); status_bar(); show_cursor(); } if (c == 'b' || c == '\n'){ draw_box(orig_x, orig_y, FIX); modified = 1; } redraw(); mode = MOVE; } void draw_arrow(int x, int y, char *a, int a_len, int fix){ /* FIXME: copy affected lines to undo */ int i, j, cur_dir; char line; void (*f)(int, int, char); if (fix == FIX) f = set_xy; else f = draw_xy; f(x,y,mark_st); if (!a_len){ show_cursor(); return; } cur_dir=DIR_N; for (i=0; i0) { /* If we are switching between horizontal and vertical, put a "corner" */ if (((cur_dir & DIR_HOR) && (a[i] & DIR_VER)) || ((cur_dir & DIR_VER) && (a[i] & DIR_HOR))){ f(x,y,corner); show_cursor(); } } for(j=0; j=x; i--) set_xy(i,y,BG); break; case DIR_U: for(i=y1; i>=y; i--) set_xy(x,i,BG); break; case DIR_D: for(i=y1; i<=y; i++) set_xy(x,i,BG); break; } } void erase(FILE *fc){ /*FIXME: add affected lines to undo */ char c; int orig_x = x, orig_y = y; status_bar(); show_cursor(); invalidate_undo(); while((c=fgetc(fc))!=EOF && c!=27 && c!= 'x' && c != '\n'){ if (!move_around(c, fc)) continue; check_bound(); do_erase(orig_x, orig_y); step = 1; modified = 1; orig_x = x; orig_y = y; redraw(); status_bar(); show_cursor(); } mode = MOVE; } /*** Visual ***/ void visual_box(FILE *fc){ int orig_x =x, orig_y = y; char c, f = BG; redraw(); step = 1; set_video(VIDEO_REV); draw_box(x,y,NOFIX); while((c=fgetc(fc))!=EOF && c != 27 && c!= 'v' && c != '\n'){ if (!move_around(c, fc)) switch(c){ case 'y': /* yank (copy) */ yank_region(MIN(orig_x,x), MIN(orig_y,y), MAX(orig_x, x), MAX(orig_y, y)); goto vis_exit; break; case 'f':/* fill */ f = get_key(fc, "fill char: "); /** FALLTHROUGH **/ case 'x':/* erase */ if (c == 'x') yank_region(MIN(orig_x,x), MIN(orig_y,y), MAX(orig_x, x), MAX(orig_y, y)); copy_lines_to_ring(MIN(orig_y, y), MAX(orig_y, y), PRV_STATE); erase_box(orig_x, orig_y, f); erase_blank_lines(MIN(y,orig_y), MAX(y, orig_y)); copy_lines_to_ring(MIN(orig_y, y), MAX(orig_y, y), NEW_STATE); modified = 1; goto vis_exit; break; } check_bound(); set_video(VIDEO_NRM); redraw(); step = 1; f = BG; set_video(VIDEO_REV); draw_box(orig_x, orig_y, NOFIX); status_bar(); show_cursor(); } vis_exit: set_video(VIDEO_NRM); redraw(); mode = MOVE; } void paste(){ int y2; y2 = y + cutbuf.num - 1; copy_lines_to_ring(y, y2, PRV_STATE); paste_region(x, y); copy_lines_to_ring(y, y2, NEW_STATE); redraw(); } void put_lines(lineset_t *u){ int i, n; for (i=0; i< u->num; i++){ n = u->l[i].n; ensure_line_length(&(screen.l[i]), strlen(u->l[i].s)); strcpy(screen.l[n].s, u->l[i].s); screen.l[n].lst = strlen(u->l[i].s)-1; } } void undo_change(){ if (undo_cur >= 0){ if (undo_cur > undo_lst) undo_cur = undo_lst; put_lines(& (undo[undo_cur])); undo_cur -= 2; modified = 1; } redraw(); } void redo_change(){ if (undo_cur <= undo_lst-2){ if (undo_cur > 0) put_lines(& (undo[undo_cur+1])); undo_cur +=2; put_lines(& (undo[undo_cur+1])); modified = 1; } redraw(); }