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 }