gramscii.c - gramscii - A simple editor for ASCII box-and-arrow charts DIR Log DIR Files DIR Refs DIR Tags DIR README DIR LICENSE --- gramscii.c (4678B) --- 1 /* 2 * 3 * gramscii: a simple editor for ASCII box-and-arrow charts 4 * 5 * Copyright (c) 2019 Vincenzo "KatolaZ" Nicosia <katolaz@freaknet.org> 6 * 7 * This program is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program. Please see the attached file COPYING. 19 * Otherwise, please visit <https://www.gnu.org/licenses/>. 20 * 21 */ 22 23 #define _POSIX_C_SOURCE 200112L 24 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <signal.h> 28 29 #include "arg.h" 30 #include "gramscii.h" 31 32 /** global variables **/ 33 34 lineset_t screen; /* what is visualised */ 35 lineset_t cutbuf; /* cut/paste buffer */ 36 lineset_t *undo; /* undo list */ 37 38 pos_t marks[26]; /* position marks */ 39 char mark_map[26]; /* marks map */ 40 41 int undo_sz;/* allocated size of undo list*/ 42 int undo_cur;/* undo position */ 43 int undo_lst;/* last valid undo position */ 44 45 int WIDTH, HEIGHT; 46 47 int mode;/* mode */ 48 int dir;/* line direction */ 49 int x; 50 int y; 51 int step;/* current step */ 52 int mult;/* current multiplier */ 53 int force_new; 54 char corner; 55 56 /* number of available markers for each type */ 57 int hlines_sz; 58 int vlines_sz; 59 int corners_sz; 60 int stmarks_sz; 61 int endmarks_sz; 62 /**/ 63 64 /* line and arrow markers */ 65 int cur_hl, cur_vl, cur_corn, cur_start, cur_end; 66 char line_h; 67 char line_v; 68 char mark_st; 69 char mark_end; 70 /**/ 71 72 char modified; /* set to 1 if screen modified since last save */ 73 char fname[256]; 74 75 76 char script; /* set to 1 in script-mode */ 77 char autoend; /* set to 1 in auto-arrow mode */ 78 79 /* Used by draw_arrow to identify the bounding box */ 80 int a_miny; 81 int a_maxy; 82 /**/ 83 84 struct termios t1, t2, t3; 85 86 /** End of global variables **/ 87 88 char *argv0; 89 90 91 void cleanup(int s){ 92 93 if (!script){ 94 printf("\033[;H\033[2J"); 95 tcsetattr(0, TCSANOW, &t1); 96 } 97 else 98 dump_lines(screen, stdout); 99 fflush(stdout); 100 exit(s); 101 } 102 103 /*** Initialisation ***/ 104 105 void init(){ 106 107 signal(SIGHUP, cleanup); 108 signal(SIGINT, cleanup); 109 signal(SIGTERM, cleanup); 110 signal(SIGQUIT, cleanup); 111 112 if (!script){ 113 tcgetattr(0, &t1); 114 t2 = t1; 115 t2.c_lflag &= ~(ICANON | ECHO); 116 tcsetattr(0, TCSANOW, &t2); 117 } 118 init_screen(); 119 x = 0; 120 y = 0; 121 step = 1; 122 modified = 0; 123 fname[0] = '\0'; 124 redraw(); 125 } 126 127 128 /*** Commands ***/ 129 130 void commands(FILE *fc){ 131 132 int c; 133 while((c=fgetc(fc))!=EOF){ 134 if (!change_style(c) && !move_around(c, fc, 1)){ 135 #ifdef DEBUG 136 fprintf(stderr, "got command: %c\n", c); 137 #endif 138 switch(c){ 139 case 'i': 140 mode = TEXT; 141 get_text(fc); 142 break; 143 case 'R': 144 redraw(); 145 break; 146 case 'b': 147 mode = BOX; 148 get_box(fc, BOX_RECT); 149 break; 150 case 'A': autoend=1; 151 case 'a': 152 mode = ARROW; 153 get_arrow(fc); 154 autoend = 0; 155 break; 156 case 'W': 157 force_new = 1;/** FALLTHROUGH **/ 158 case 'w': 159 write_file(fc); 160 break; 161 case 'e': 162 check_modified(fc);/** FALLTHROUGH **/ 163 case 'E': 164 load_file(fc); 165 break; 166 case 'N': 167 new_file(fc); 168 break; 169 case 'x': 170 mode = DEL; 171 erase(fc); 172 break; 173 case 'v': 174 mode = VIS; 175 visual_box(fc); 176 break; 177 case 'C': 178 crop_to_nonblank(); 179 break; 180 case 'p': 181 paste(); 182 break; 183 case 'u': 184 undo_change(); 185 break; 186 case 'U': 187 redo_change(); 188 break; 189 case 'r': 190 read_file_at(fc, x, y); 191 break; 192 case 't': 193 mode = TRP; 194 get_box(fc, BOX_TRAP_UC); 195 break; 196 case 'z': 197 mode = PAR; 198 get_box(fc, BOX_PARR); 199 break; 200 case '#': 201 mode = REM; 202 get_comment(fc); 203 break; 204 case 'M': 205 mark_pos(fc); 206 break; 207 case 'q': 208 check_modified(fc);/** FALLTHROUGH **/ 209 case 'Q': 210 cleanup(0); 211 break; 212 } 213 } 214 check_bound(&x, &y); 215 status_bar(); 216 show_cursor(); 217 step = 1; 218 force_new = 0; 219 } 220 221 } 222 223 void usage(){ 224 fprintf(stderr, "Usage: %s [-s] [-h] [file ...]\n", argv0); 225 exit(1); 226 } 227 228 229 int main(int argc, char *argv[]){ 230 FILE *fc; 231 232 ARGBEGIN { 233 case 's': 234 script = 1; 235 break; 236 case 'h': /* FALLTHROUGH */ 237 default: 238 usage(); 239 } ARGEND; 240 241 init(); 242 while (argc){ 243 fc = fopen(argv[0], "r"); 244 if (fc == NULL){ 245 fprintf(stderr, "Error opening file %s\n", argv[0]); 246 } 247 else { 248 commands(fc); 249 fflush(fc); 250 fclose(fc); 251 redraw(); 252 } 253 argv++; 254 argc--; 255 } 256 commands(stdin); 257 cleanup(0); 258 }