/***** **** E d F o n t Font Editor for Bradford Text Processing Program *** ** Written by F. W. Hogan, 03/30/87 */ /* General constants */ #define BEL 0x07 /* ASCII Bell */ #define BS 0x08 /* ASCII Backspace */ #define CR 0x0d /* ASCII Carriage Return */ #define ESC 0x1b /* ASCII Escape */ #define SP 0x20 /* ASCII Space */ #define DEL 0x7f /* ASCII Rubout */ #define NULL 0 /* General null value */ #define EOF -1 /* End-Of-File value from I/O functions */ #define ERR -1 /* General "on error" return value */ #define OK 0 /* General purpose "no error" return value */ #define YES 1 /* General purpose true truth value */ #define NO 0 /* General purpose false truth value */ #define Ctrl_ 0x1f & /* Prefix macro to generate control chars */ #define repeat while (1) /* Infinite loop construct */ /* CRT control strings (8 bytes allowed for each, except for biases) */ /* These set for Televideo 912/920/92, Liberty, Qume, new Sorocs, etc. */ #define CLEARS "\032\0\0\0\0\0\0\0" /* Clear Screen */ #define CURPOS "\033=\0\0\0\0\0\0" /* Cursor Positioning prefix */ #define CLREOL "\033T\0\0\0\0\0\0" /* Clear to End of Line */ #define RVSON "\033)\0\0\0\0\0\0" /* Reverse Video On */ #define RVSOFF "\033(\0\0\0\0\0\0" /* Reverse Video Off */ #define RBIAS "\040" /* Cursor Positioning Row bias */ #define CBIAS "\040" /* Cursor Positioning Column bias */ /* Display symbol strings (8 bytes allowed) */ #define DOT "()\0\0\0\0\0\0" /* Display symbol string for dot */ #define NODOT ". \0\0\0\0\0\0" /* Display symbol string for no dot */ /* Redefinable cursor key characters */ #define UPKEY 'E' /* Cursor up */ #define LTKEY 'S' /* Cursor left */ #define RTKEY 'D' /* Cursor right */ #define DNKEY 'X' /* Cursor down */ /* Editor parameters and constants */ #define VERS 16 /* Version number */ #define MAXDEFS 95 /* Maximum number of char font defs */ #define DEFLDEF 21 /* Default definition length */ #define MAXROWS 16 /* Maximum no. of rows in char face */ #define MAXCOLS 9 /* Maximum no. of columns in char face */ #define MAXLINE 80 /* Maximum work line length */ #define MENUSIZ 19 /* Maximum rows in menus */ #define CROW 22 /* Command input row */ #define CCOL 45 /* Command input column */ #define EROW 23 /* Error report row */ #define ECOL 45 /* Error report column */ #define FROW 4 /* Face grid row */ #define FCOL 27 /* Face grid column */ #define IROW 23 /* General information row */ #define ICOL 0 /* General information column */ #define MROW 3 /* Menu row */ #define MCOL 52 /* Menu column */ #define SROW 22 /* Status line row */ #define SCOL 0 /* Status line column */ #define TROW 2 /* Ascii table row */ #define TCOL 3 /* Ascii table column */ /* Global variables */ char clears[8]; /* Clear Screen */ char curpos[8]; /* Cursor Positioning prefix */ char rbias; /* Cursor Positioning Row bias */ char cbias; /* Cursor Positioning Column bias */ char clreol[8]; /* Clear to End of Line */ char rvson[8]; /* Reverse Video On */ char rvsoff[8]; /* Reverse Video Off */ char dot[8]; /* Display symbol string for dot */ char nodot[8]; /* Display symbol string for no dot */ char FontModified; /* Font Modified semaphore */ char fname[15]; /* Font File Name */ int fd; /* File Descriptor */ struct facedef { /* Char face definition structure */ char dots[2][MAXCOLS]; char width; char begcol; char endcol; }; struct facedef face[MAXDEFS]; /* Table of char face definitions */ int ndefs, ldef; /* No. of face defns. and length of each */ int maxc; /* Maximum character value */ char edbuf[MAXROWS][MAXCOLS]; /* Edit buffer array */ char svbuf[MAXROWS][MAXCOLS]; /* Scratchpad save buffer array */ int curchr; /* Current edit character */ int scrchr; /* Saved scratchpad character */ int oldchr; /* Previous edit character */ int cwid; /* Current char face width */ int cbeg, cend; /* Current char face start & end columns */ char cflg[MAXDEFS]; /* Flags indicating chars modified */ char line[MAXLINE]; /* work line buffer */ /* BDS-C file I/O variables */ char iobuf[134]; /* buffered-i/o buffer */ /*** ** EdFont MAIN Function */ main(argc, argv) int argc; char *argv[]; { int i, j, n; int c; struct facedef *p; /* initialize crt control strings, etc. */ movmem(CLEARS, clears, 8); movmem(CURPOS, curpos, 8); movmem(CLREOL, clreol, 8); movmem(RVSON, rvson, 8); movmem(RVSOFF, rvsoff, 8); movmem(RBIAS, &rbias, 1); movmem(CBIAS, &cbias, 1); movmem(DOT, dot, 8); movmem(NODOT, nodot, 8); /* Process command line */ switch (argc) { case 1: strcpy(fname, "DELETE.ME"); break; case 2: strcpy(line, argv[1]); if (line[0] == '?') usage(); line[14] = '\0'; dftype(fname, ".BIN", line); break; default: usage(); } /* Clear screen and sign on */ puts(clears); display(0, 18, "EdFont - Bradford Font Editor"); printf(" - Version %d.%0d", VERS/10, VERS%10); showmenu(MROW, MCOL); /* display command menu */ showtable(TROW, TCOL); /* display ascii table */ readfont(); /* get font file definitions */ oldchr = curchr = SP; /* default start char */ getface(svbuf); /* initialize save buffer */ /* Command processing loop */ repeat { display(SROW, SCOL, clreol); /* display font file name */ printf("Font:%s %s %s", rvson, fname, rvsoff); gotodefn(); /* goto current char defn */ display(CROW, CCOL, clreol); /* get command */ puts("Command? "); c = toupper(getch()); infomsg(clreol); /* clear message line */ display(CROW, CCOL, clreol); /* clear command input field */ switch (c) { case 'C': /* Copy to buffer */ getface(svbuf); infomsg("Face copied to save buffer"); break; case 'E': /* Edit character face */ editface(); display(FROW-2, FCOL, clreol); showmenu(MROW, MCOL); break; case 'H': /* Hex-select character */ puts("Enter character code: "); if (accept(line, 5) == ERR) break; sscanf(line, "%x", &c); if (c >= SP && c <= maxc) curchr = c; else errmsg("\7Character codes are 20h to 7Eh"); break; case 'K': /* Key-select character */ puts("Press key of character: "); c = getch(); if (c >= SP && c <= maxc) curchr = c; else errmsg("\7Illegal character key"); break; case 'N': /* Next character face */ case ' ': if (++curchr > maxc) curchr = SP; break; case 'P': /* Previous character face */ if (--curchr < SP) curchr = maxc; break; case 'R': /* Read font file */ if (FontModified) if (ask("Clobber modified font? ") == 'N') break; else display(CROW, CCOL, clreol); if (getname("File to Read : ", fname) == OK) { readfont(); showtable(TROW, TCOL); } break; case 'S': /* Scan characters */ puts("[Keys 0-9 set speed; others stop]"); n = 0; repeat { if (kbhit()) if (isdigit(c = getch())) n = 3640 * (0x39 - c); else break; if (++curchr > maxc) curchr = SP; gotodefn(); for (i=0; i: ", fname) == OK) { writefont(); if (! FontModified) showtable(TROW, TCOL); } break; case 'X': /* Exit EdFont */ if (FontModified) if (ask("Abandon modified font? ") == 'N') break; infomsg("Exiting EdFont..."); exit(); break; default: putch(BEL); break; } } } /*** ** Get face definition and display */ gotodefn() { /* Display current character */ display(SROW, SCOL+24, 0); printf("Char:%s '%c' = (%02xh) %s", rvson, curchr, curchr, rvsoff); /* Turn off highlight of previous char in ascii table */ display(TROW+(oldchr & 15)+2, TCOL+2*(oldchr>>4)-3, 0); putch(' '); if (cflg[oldchr-SP]) { puts(rvson); putch(oldchr); puts(rvsoff); } else putch(oldchr); putch(' '); /* Highlight current character in table */ display(TROW+(curchr & 15)+2, TCOL+2*(curchr>>4)-3, 0); puts(rvson); putch('>'); putch(curchr); putch('<'); puts(rvsoff); getface(edbuf); showface(FROW, FCOL); oldchr = curchr; /* update old char */ } /*** ** Edit character face definition */ editface() { int i, j, key, row, col; char cell, c; showecmds(MROW, MCOL); /* show edit cmds */ row = col = 0; /* init row, col */ cell = 1; /* init plot mode */ display(FROW-2, FCOL, "Mode:"); printf("%s PLOT %s", rvson, rvsoff); repeat { showcurs(row, col, YES); /* show cursor */ key = toupper(getch()); /* get edit command */ showcurs(row, col, NO); /* turn off cursor */ switch (key) { case SP: /* toggle dot */ edbuf[row][col] ^= 1; break; CursRt: case Ctrl_(RTKEY): case Ctrl_'L': /* cursor right */ if (++col < MAXCOLS) break; else col = 0; CursDn: case Ctrl_(DNKEY):case Ctrl_'J': /* cursor down */ if (++row >= MAXROWS) row = 0; break; CursLt: case Ctrl_(LTKEY): case Ctrl_'H': /* cursor left */ if (col-- > 0) break; else col = MAXCOLS - 1; CursUp: case Ctrl_(UPKEY): case Ctrl_'K': /* cursor up */ if (row-- <= 0) row = MAXROWS - 1; break; case RTKEY: case 'L': /* edit move right */ edbuf[row][col] = cell; showcurs(row, col, NO); goto CursRt; break; case DNKEY: case 'J': /* edit move down */ edbuf[row][col] = cell; showcurs(row, col, NO); goto CursDn; break; case LTKEY: case 'H': /* edit move left */ edbuf[row][col] = cell; showcurs(row, col, NO); goto CursLt; break; case UPKEY: case 'K': /* edit move up */ edbuf[row][col] = cell; showcurs(row, col, NO); goto CursUp; break; case Ctrl_'V': /* plot/erase toggle */ cell ^= 1; display(FROW-2, FCOL+5, 0); printf("%s %s %s ", rvson, cell ? "PLOT" : "ERASE", rvsoff); break; case Ctrl_'W': /* move face up */ for (j=0; j0; j--) edbuf[i][j] = edbuf[i][j-1]; edbuf[i][0] = c; } showface(FROW, FCOL); break; case Ctrl_'Z': /* move face down */ for (j=0; j0; i--) edbuf[i][j] = edbuf[i-1][j]; edbuf[0][j] = c; } showface(FROW, FCOL); break; case Ctrl_'Y': /* erase face */ for (i=0; idots[i][j] = 0; p->width = 9; p->begcol = 1; p->endcol = 9; } } /*** ** Load character definitions from font file */ loaddefs() { int c, i, j; struct facedef *p; /* Read header info */ if ((c = getbyte()) == EOF) return ERR; if ((ndefs = c) > MAXDEFS) { /* number of definitions */ errmsg("\7Too many definitions in font file"); return ERR; } if (getbyte() == EOF) return ERR; /* filler */ if ((c = getbyte()) == EOF) return ERR; ldef = c; /* length of definition */ if (getbyte() == EOF) return ERR; /* filler */ /* Read character face definitions */ for (p = face; p < face + ndefs; p++) { for (i = 0; i < 2; i++) for (j = 0; j < MAXCOLS; j++) { if ((c = getbyte()) == EOF) return ERR; p->dots[i][j] = c; } if ((c = getbyte()) == EOF) return ERR; p->width = c; if ((c = getbyte()) == EOF) return ERR; p->begcol = c; if ((c = getbyte()) == EOF) return ERR; p->endcol = c; } return OK; } /*** ** Save character definitions to font file */ savedefs() { char c; int i, j; struct facedef *p; /* Write header info */ c = ndefs; if (putbyte(c) == ERR) return ERR; /* no. of defns */ if (putbyte(0) == ERR) return ERR; /* filler */ c = ldef; if (putbyte(c) == ERR) return ERR; /* length of defn */ if (putbyte(0) == ERR) return ERR; /* filler */ /* Write character face definitions */ for (p = face; p < face + ndefs; p++) { for (i = 0; i < 2; i++) for (j = 0; j < MAXCOLS; j++) if (putbyte(p->dots[i][j]) == ERR) return ERR; if (putbyte(p->width) == ERR) return ERR; if (putbyte(p->begcol) == ERR) return ERR; if (putbyte(p->endcol) == ERR) return ERR; } return OK; } /*** ** Get a byte from file */ getbyte() { int c; if ((c = getc(iobuf)) == EOF) { errmsg("\7Premature EOF in file"); } return c; } /*** ** Put a byte to file */ putbyte(c) char c; { int i; if ((i = putc(c, iobuf)) == ERR) errmsg("\7Error in writing file"); return i; } /*** ** Get character face definition into face buffer */ getface(buf) char buf[][MAXCOLS]; { int i, j, k; struct facedef *p; p = &face[curchr - SP]; /* char defns start at */ for (i=0; i> (i/2); for (j=0; jdots[i%2][j] & k)==0) ? 0 : 1; } cwid = p->width; cbeg = p->begcol; cend = p->endcol; } /*** ** Calculate column limits of character face */ sizeface() { int i, j; for (cbeg=MAXCOLS-1, j=0; j<=cbeg; j++) /* left limit */ for (i=0; i=cend; j--) /* right limit */ for (i=0; i cend++) { /* adjust limits */ cbeg = 1; cend = MAXCOLS; } cwid = cend - cbeg + 1; /* calculate width */ } /*** ** Put character in face buffer to face definition */ putface(buf) char buf[][MAXCOLS]; { int i, j, k, n; struct facedef *p; p = &face[curchr - SP]; /* char defns start at */ for (i=0; i<2; i++) for (j=0; jdots[i][j] = n; } p->width = cwid; p->begcol = cbeg; p->endcol = cend; } /*** ** Show character face edit buffer on screen at (r, c) */ showface(r, c) int r, c; { int i, j; char s[5]; for (i=0; i N ^ n ~ | E"); display(r++, c, "| / ? O _ o | F"); display(r++, c, " -------------"); } /*** ** Display command menu at (r, c) */ showmenu(r, c) int r, c; { int i; for (i = r; i < r+MENUSIZ; i++) /* erase edit menu */ display(i, c, clreol); display(r++, c, " --------Commands---------"); display(r++, c, "| C Copy to save buffer |"); display(r++, c, "| E Edit character |"); display(r++, c, "| H Hex-select character |"); display(r++, c, "| K Key-select character |"); display(r++, c, "| N Next character |"); display(r++, c, "| P Previous character |"); display(r++, c, "| R Read font file |"); display(r++, c, "| S Scan characters |"); display(r++, c, "| T Transfer char/buffer |"); display(r++, c, "| W Write font file |"); display(r++, c, "| X Exit EdFont |"); display(r++, c, " -------------------------"); } /*** ** Display edit commands at (r, c) */ showecmds(r, c) int r, c; { int i; for (i = r; i < r+MENUSIZ; i++) /* erase cmd menu */ display(i, c, clreol); display(r++, c, " -----Edit Cmds-----"); display(r++, c, "| ^E Cursor Up |"); display(r++, c, "| ^S Cursor Left |"); display(r++, c, "| ^D Cursor Right |"); display(r++, c, "| ^X Cursor Down |"); display(r++, c, "| Toggle Dot |"); display(r++, c, "| E Edit & Up |"); display(r++, c, "| S Edit & Left |"); display(r++, c, "| D Edit & Right |"); display(r++, c, "| X Edit & Down |"); display(r++, c, "| ^V Change Mode |"); display(r++, c, "| ^W Shift Up |"); display(r++, c, "| ^A Shift Left |"); display(r++, c, "| ^F Shift Right |"); display(r++, c, "| ^Z Shift Down |"); display(r++, c, "| ^Y Erase Face |"); display(r++, c, "| ^Q Undo Changes |"); display(r++, c, "| Edit Done |"); display(r++, c, " -------------------"); } /*** ** Display usage message */ usage() { puts("usage: EDFONT {}"); exit(); } /*** ** Display information message string */ infomsg(s) char *s; { display(IROW, ICOL, s); } /*** ** Display error message string */ errmsg(s) char *s; { display(EROW, ECOL, s); } /*** ** Prompt with string and return with 'Y' or 'N' answer */ ask(s) char *s; { int c; if (s) puts(s); repeat { c = toupper(getch()); if (c == 'Y' || c == 'N') return c; putch('\7'); } } /*** ** Prompt with message s and accept file name (default type .BIN). * If entered alone, name is unchanged and is echoed on screen. */ getname(s, name) char *s, *name; { puts(s); if ((accept(line, 14)) == ERR) return ERR; dftype(name, ".BIN", line); if (line[0] == '\0') puts(name); return OK; } /*** ** Copy file name "src" to "name", add default type "typ" if none. * If "src" is null, "name" is not affected. */ dftype(name, typ, src) char *name, *typ, *src; { if (*src) { while (*src) if ((*name++ = toupper(*src++)) == '.') upcase(name, src); strcpy(name, typ); } } /*** ** Create file name "name" with type "typ" using file name "fn" */ makenam(name, typ, fn) char *name, *typ, *fn; { while (*fn != '.' && *fn != 0) *name++ = *fn++; strcpy(name, typ); } /*** ** Set attributes of file specified by array fcb */ setattr(fcb) char *fcb; { bdos(30, fcb); /* CP/M Set File Attributes */ } /*** ** Convert string t to upper case and copy to string s (returned) */ upcase(s, t) char *s, *t; { while (*s++ = toupper(*t++)) ; return s; } /*** ** Place cursor at screen coordinate (r, c) and display string s */ display(r, c, s) char *s; int r, c; { puts(curpos); putch(r + rbias); putch(c + cbias); if (s) puts(s); } /*** ** Accept string of max length m from console * ESC or CTRL-G keys cause ERR return, else OK */ accept(s, m) char *s; int m; { int n; char c; n = m; while ((c = getch()) != CR) { if (c >= SP && c < DEL) { if (n > 0) { putch (*s++ = c); n--; } else putch(BEL); } else switch (c) { case BS: case DEL: if (n < m) { s--; puts("\8 \8"); n++; } break; case ESC: case Ctrl_'G': while (n < m) { s--; puts("\8 \8"); n++; } return ERR; break; case Ctrl_'X': case Ctrl_'U': while (n < m) { s--; puts("\8 \8"); n++; } break; default: putch(BEL); break; } } *s = '\0'; return OK; } /*** ** Get character from console without echo */ getch() { int c; while ((c = bdos(6, 0xff)) == 0); /* CP/M Direct Console I/O */ return (c & 0x7f); } /*** ** Display string s without interrogating console */ puts(s) char *s; { while (*s) putch(*s++); } /* End of EdFont */