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