|
|
gramscii.c - gramscii - A simple editor for ASCII box-and-arrow charts |
|
|
 |
Log |
|
|
 |
Files |
|
|
 |
Refs |
|
|
 |
Tags |
|
|
 |
README |
|
|
 |
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 } |
|