Commit | Line | Data |
---|---|---|
524aa063 SL |
1 | #ifndef lint |
2 | static char sccsid[] = "@(#)fed.c 4.2 (Berkeley) %G%"; | |
3 | #endif | |
4 | ||
f2523db4 RC |
5 | /* |
6 | * Font editor for the HP 2648. | |
7 | * | |
8 | * Mark Horton, 1/80 | |
9 | */ | |
10 | ||
11 | #include "fed.h" | |
12 | ||
13 | main(argc,argv) | |
14 | int argc; | |
15 | char **argv; | |
16 | { | |
17 | ||
18 | signal(SIGINT, onintr); | |
19 | signal(SIGQUIT, onsig); | |
20 | signal(SIGILL, onsig); | |
21 | signal(SIGBUS, onsig); | |
22 | signal(SIGSEGV, onsig); | |
23 | signal(SIGSYS, onsig); | |
24 | ||
25 | while (argc > 1 && argv[1][0] == '-') { | |
26 | switch(argv[1][1]) { | |
27 | case 'T': | |
28 | trace = fopen("trace", "w"); | |
29 | setbuf(trace, tracebuf); | |
30 | break; | |
31 | case 'i': | |
32 | case 'v': | |
33 | vidinv(); | |
34 | break; | |
35 | case 'q': | |
36 | QUIET = 1; | |
37 | break; | |
38 | default: | |
39 | printf("Bad flag: %s\n", argv[1]); | |
40 | } | |
41 | argc--; argv++; | |
42 | } | |
43 | if (argc < 2) { | |
44 | fprintf(stderr,"Usage: %s filename\n", argv[0]); | |
45 | exit(1); | |
46 | } | |
47 | ||
48 | if (setjmp(env) == 0) { | |
49 | initialize(); | |
50 | editfont(argv[1]); | |
51 | } | |
52 | ||
53 | cmdloop(); | |
54 | } | |
55 | ||
56 | cmdloop() | |
57 | { | |
58 | char cmd; | |
59 | ||
60 | setjmp(env); | |
61 | for (;;) { | |
62 | cmd = inchar(); | |
63 | if (cmd == ESC) | |
64 | cmd = esccmd(); | |
65 | switch (cmd) { | |
66 | ||
67 | /* ^L: redraw munged up screen */ | |
68 | case '\14': | |
69 | redraw(); | |
70 | break; | |
71 | ||
72 | /* b: move cursor to base point of window */ | |
73 | case 'b': | |
74 | cch(); | |
75 | curs_r = cht[curchar].rcent; | |
76 | curs_c = cht[curchar].ccent; | |
77 | turnoncurs(); | |
78 | break; | |
79 | ||
80 | /* c: toggle whether cursor is on */ | |
81 | case 'c': | |
82 | if (curcurs) | |
83 | turnofcurs(); | |
84 | else | |
85 | turnoncurs(); | |
86 | break; | |
87 | ||
88 | /* d: draw line of current flavor from pen to cursor */ | |
89 | case 'd': | |
90 | cch(); | |
91 | bufmod(); | |
92 | drawline(pen_r, pen_c, curs_r, curs_c); | |
93 | turnofcurs(); | |
94 | turnofrb(); | |
95 | pen_r = curs_r; pen_c = curs_c; | |
96 | syncwind(curwind); | |
97 | break; | |
98 | ||
99 | /* f: fill in the current hole around the cursor */ | |
100 | case 'f': | |
101 | cch(); | |
102 | bufmod(); | |
103 | if (trace) | |
104 | fprintf(trace, "fillin(%d, %d)\n", curs_r, curs_c); | |
105 | if (mat(wind[curwind].val, GLROW, GLCOL, curs_r, curs_c)) | |
106 | error("Not in a hole"); | |
107 | fillin(curs_r, curs_c); | |
108 | curoff(); | |
109 | syncwind(curwind); | |
110 | break; | |
111 | ||
112 | /* g <x>: get glyph "x" as current. */ | |
113 | case 'g': | |
114 | if (fontdes == NULL) | |
115 | error("No current font file"); | |
116 | message("get glyph <char>"); | |
117 | curchar = inchar(); | |
118 | sprintf(msgbuf, "get glyph %s", rdchar(curchar)); | |
119 | message(msgbuf); | |
120 | getglyph(curchar); | |
121 | break; | |
122 | ||
123 | /* h, left arrow: move cursor left */ | |
124 | case 'h': | |
125 | cch(); | |
126 | if (curs_c <= 0) | |
127 | error("Off edge"); | |
128 | else | |
129 | curs_c--; | |
130 | turnoncurs(); | |
131 | break; | |
132 | ||
133 | /* j, down arrow: move cursor down */ | |
134 | case 'j': | |
135 | cch(); | |
136 | if (curs_r >= GLROW-1) | |
137 | error("Off edge"); | |
138 | else | |
139 | curs_r++; | |
140 | turnoncurs(); | |
141 | break; | |
142 | ||
143 | /* k, up arrow: move cursor up */ | |
144 | case 'k': | |
145 | cch(); | |
146 | if (curs_r <= 0) | |
147 | error("Off edge"); | |
148 | else | |
149 | curs_r--; | |
150 | turnoncurs(); | |
151 | break; | |
152 | ||
153 | /* l, right arrow: move cursor down */ | |
154 | case 'l': | |
155 | cch(); | |
156 | if (curs_c >= GLCOL-1) | |
157 | error("Off edge"); | |
158 | else | |
159 | curs_c++; | |
160 | turnoncurs(); | |
161 | break; | |
162 | ||
163 | /* m: move the pen to where the cursor is */ | |
164 | case 'm': | |
165 | cch(); | |
166 | pen_r = curs_r; pen_c = curs_c; | |
167 | turnoncurs(); | |
168 | move(base[curwind].c+curs_c, base[curwind].r+GLROW-1-curs_r); | |
169 | turnonrb(); | |
170 | break; | |
171 | ||
172 | /* n <x>: make a new glyph with char x */ | |
173 | case 'n': | |
174 | newglyph(); | |
175 | break; | |
176 | ||
177 | /* p: print a hard copy on the printer of the screen */ | |
178 | case 'p': | |
179 | printg(); | |
180 | break; | |
181 | ||
182 | /* r: toggle rubber band line */ | |
183 | case 'r': | |
184 | if (currb) | |
185 | turnofrb(); | |
186 | else | |
187 | turnonrb(); | |
188 | break; | |
189 | ||
190 | /* s <what> <where>: set <what> to <where> */ | |
191 | case 's': | |
192 | setcmd(); | |
193 | break; | |
194 | ||
195 | /* u: undo previous buffer modifying command */ | |
196 | case 'u': | |
197 | cch(); | |
198 | undo(); | |
199 | break; | |
200 | ||
201 | /* z <n>: set zoom to n. */ | |
202 | case 'z': | |
203 | message("zoom to <level>"); | |
204 | curzoom = inchar(); | |
205 | if (curzoom == '\r' || curzoom == '\n') | |
206 | curzoom = oldzoom; | |
207 | else { | |
208 | curzoom -= '0'; | |
209 | oldzoom = curzoom; | |
210 | } | |
211 | zoomn(curzoom); | |
212 | break; | |
213 | ||
214 | /* space: reset zoom to last thing user asked for */ | |
215 | case ' ': | |
216 | zoomn(curzoom = oldzoom); | |
217 | break; | |
218 | ||
219 | /* A: artificially embolden/italicize <range> by heavy pen size */ | |
220 | case 'A': | |
221 | bufmod(); | |
222 | artificial(); | |
223 | break; | |
224 | ||
225 | /* B: move base point of window to cursor */ | |
226 | case 'B': | |
227 | cch(); | |
228 | cht[curchar].rcent = curs_r; | |
229 | cht[curchar].ccent = curs_c; | |
230 | turnoncurs(); | |
231 | break; | |
232 | ||
233 | /* | |
234 | * C <from> <to>: copy glyph <from> to <to>. | |
235 | * M <from> <to>: move glyph <from> to <to>. | |
236 | */ | |
237 | case 'C': | |
238 | case 'M': | |
239 | copymove(cmd); | |
240 | break; | |
241 | ||
242 | /* D <char1> <char2>: delete range from font */ | |
243 | case 'D': | |
244 | delchar(); | |
245 | break; | |
246 | ||
247 | /* F: display the entire font on the screen. */ | |
248 | case 'F': | |
249 | showfont(); | |
250 | break; | |
251 | ||
252 | /* I: invert the current glyph */ | |
253 | case 'I': | |
254 | cch(); | |
255 | bufmod(); | |
256 | invert(); | |
257 | break; | |
258 | ||
259 | /* K: kill (wipe clean) current glyph. */ | |
260 | case 'K': | |
261 | cch(); | |
262 | bufmod(); | |
263 | zermat(wind[curwind].val, GLROW, GLCOL); | |
264 | syncwind(curwind); | |
265 | if (trace) | |
266 | fprintf(trace, "kill: curs_r = %d, curs_c = %d\n", curs_r, curs_c); | |
267 | break; | |
268 | ||
269 | /* P <first> <last> <file>: read partial font */ | |
270 | case 'P': | |
271 | readchars(); | |
272 | break; | |
273 | ||
274 | /* Q: quit the editor, not saving work. */ | |
275 | case 'Q': | |
276 | confirm(); | |
277 | done(); | |
278 | exit(0); | |
279 | ||
280 | /* T: typeset a line of input text */ | |
281 | case 'T': | |
282 | typein(); | |
283 | break; | |
284 | ||
285 | /* V: toggle video between inverse and normal */ | |
286 | case 'V': | |
287 | togvid(); | |
288 | break; | |
289 | ||
290 | /* | |
291 | * E <file>: edit new font file <file>. | |
292 | * N <file>: write, then edit <file> | |
293 | * R <file>: read <file> on top of buffer. | |
294 | * W <file>: write out on <file> without quitting | |
295 | */ | |
296 | case 'E': | |
297 | case 'N': | |
298 | case 'R': | |
299 | case 'W': | |
300 | fileiocmd(cmd); | |
301 | break; | |
302 | ||
303 | /* Z: exit, writing out work */ | |
304 | case 'Z': | |
305 | message("Z"); | |
306 | if (inchar() != 'Z') { | |
307 | error("No second Z"); | |
308 | } | |
309 | if (changes) | |
310 | writeback(); | |
311 | done(); | |
312 | exit(0); | |
313 | ||
314 | /* | |
315 | * ".", ">". Set and clear the bit under the cursor. | |
316 | */ | |
317 | case '.': | |
318 | case '>': | |
319 | bufmod(); | |
320 | setmat(wind[curwind].val, GLROW, GLCOL, curs_r, curs_c, cmd=='.' ? 1 : 0); | |
321 | turnofcurs(); | |
322 | syncwind(curwind); | |
323 | break; | |
324 | ||
325 | /* | |
326 | * "#": edit the numerical parameters | |
327 | */ | |
328 | case '#': | |
329 | numedit(); | |
330 | break; | |
331 | ||
332 | default: | |
333 | sprintf(msgbuf, "No such command as %s", rdchar(cmd)); | |
334 | message(msgbuf); | |
335 | } | |
336 | ||
337 | } | |
338 | } | |
339 | ||
340 | /* | |
341 | * esccmd: a command beginning with an escape. | |
342 | * Map it into the corresponding regular command. | |
343 | */ | |
344 | char | |
345 | esccmd() | |
346 | { | |
347 | char cmd; | |
348 | char *p; | |
349 | char escseqbuf[20]; | |
350 | ||
351 | cmd = inchar(); | |
352 | switch(cmd) { | |
353 | case 'A': return ('k'); /* up arrow */ | |
354 | case 'B': return ('j'); /* down arrow */ | |
355 | case 'C': return ('l'); /* right arrow */ | |
356 | case 'D': return ('h'); /* left arrow */ | |
357 | case 'h': return ('b'); /* home */ | |
358 | case '2': return ('u'); /* clear tab = undo */ | |
359 | case '1': return (' '); /* set tab = rezoom */ | |
360 | case 'J': return ('f'); /* clear display = fill area */ | |
361 | case 'S': return ('m'); /* roll up = move */ | |
362 | case 'U': return ('d'); /* next page = draw */ | |
363 | case 'T': return ('.'); /* roll down = set bit */ | |
364 | case 'V': return ('>'); /* prev page = clear bit */ | |
365 | default: | |
366 | /* | |
367 | * Eat up rest of (possibly long) escape sequence. | |
368 | * They all end in an upper case letter, with | |
369 | * a few exceptions. | |
370 | */ | |
371 | p = escseqbuf; | |
372 | *p++ = '$'; | |
373 | *p++ = cmd; | |
374 | while (!isupper(cmd) && cmd != 'h' && cmd != '\n') | |
375 | *p++ = cmd = inchar(); | |
376 | *p++ = 0; | |
377 | sprintf(msgbuf, "Bad escape sequence: %s\n", escseqbuf); | |
378 | error(msgbuf); | |
379 | } | |
380 | } | |
381 | ||
382 | onsig(signo) | |
383 | int signo; | |
384 | { | |
385 | char *mes; | |
386 | ||
387 | switch(signo) { | |
388 | case SIGQUIT: mes = "quit"; break; | |
389 | case SIGILL: mes = "illegal instruction"; break; | |
390 | case SIGBUS: mes = "bus error"; break; | |
391 | case SIGSEGV: mes = "segmentation violation"; break; | |
392 | case SIGSYS: mes = "bad system call"; break; | |
393 | default: mes = "random signal"; break; | |
394 | } | |
395 | if (trace) { | |
396 | fprintf(trace, "%s: core dumped\n", mes); | |
397 | fflush(trace); | |
398 | } | |
399 | signal(SIGILL, SIG_DFL); | |
400 | done(); | |
401 | printf("fed: %s: core dumped\n", mes); | |
402 | fflush(stdout); | |
403 | abort(); | |
404 | } | |
405 | ||
406 | onintr() | |
407 | { | |
408 | signal(SIGINT, onintr); | |
409 | error("Interrupted"); | |
410 | longjmp(env); | |
411 | } |