/* newfont.c: super banner program. */ /* This program was my idea in 1984; the current UNIX version was created by Burt Solomon; Dan Fisher designed font.1; Changed 1986 (Betza): added comments; added upside-down and backwards and reverse video output. Added slanty (italics) output. Changed 1987 (Betza): port to CP/M, AZTEC C. making bitmap into array instead of long allows (1) increase array size greatly; (2) define a vertical font that will print 1 char per line; (3) therefore we have a BIGBANNER print program! Porting involves: (a) rename variables like 'w' so that less-powerful CP/M editors can find them; (b) fix dependencies on sizeof(int)==4 (c) simplify expressions (in my code, not Burt's) so the puny compiler can handle them correctly. (d) NOTE: this was NOT checked for sign-extension problems! Neither Z80s nor 3Bs sign-extend; if you port this to a VAX, watch out! (for a start, change all declarations of "char" to "unsigned char") Enhancements required for the ported (CP/M) environment: (1) The "build font" program should write a binary file instead of writing declaractions for a 'C' program: of course it must do this as an option! (see next item) nlines, dlines, nxl, csp should come from the file. (2) The "use font" program (this file) should contain only one built-in font; a command-line option to load a new font from a binary file must be added. The net effect of these two changes will be: (a) Users can define new fonts WITHOUT having access to the compiler. (b) We can define one BIG font instead of two small ones: so we can print big sideways letters, one per line. (3) We will be better off if we split this program into several pieces: the compiler takes a long time. Also, the .ASM files produced by the compiler are potentially of interest; the .ASM file produced when you compile the whole thing as one is too large to edit with VDE. (4) Unless you are using ZCPR or DOS25+ or something like that, you cannot get lower-case letters from the command line. (a) -f and -F must have the same meaning. (DONE!!) (b) "\A" in a sting will mean "a"; of course, "\\" means "\". (4.1) -C option toggles case, so 'A' is read as 'a' and vice-versa: with toggle in effect, "\A" means "A" (because "A" means "a"!) (5) A more useful usage message, (DONE!). (6) A way to get blanks into the thing to be bannered: \_ will be taken as a blank (DONE!) (7) A way to get control chars into the banner so that special characters can be used. To do: improve command-line parsing add another font more comments specifiable replacement character (with font2.d and character '#', results are equal to standard UNIX "banner" program). DONE 12/87! option -K# produces the above effect. -K\_ turns this off. -0 option turns off -I -U -B -S -SS -K and -C. (12/87) */ #include "stdio.h" #include "fontdefs.h" extern int csp1, csp2; extern struct chr ch1[nchars], ch2[nchars]; #define left 0 #define right 1 #define center 2 struct chr *ch; int Rflag = 0; /* (Rflag & 1) is true when upside-down printing is requested. */ /* (Rflag & 2) is true when backwards printing is requested. */ /* (Rflag & 4) is true when reverse video is requested. */ /* (Rflag & 8) is true when slanted print is requested. */ /* (Rflag & 16) is true when reverse slant is requested. */ /* (Rflag == 0) is true when normal printing is requested. */ char spacechar = ' '; char ufillc = 0; char casemask = 0; main(argc,argp) char *argp[];int argc; { int i, f, l_width, j, c, n; int pp, px, cpp, cpx; char * ap; /*if invoked with no arguments, prints error comment; if invoked with an argument, prints it in banner form. */ if(argc<2){ xpfhelp(); exit(1); } f = 0; j = center; l_width = 79; for (i = 1; i= '0') && (c <= '9')) l_width = 10*l_width + c - '0'; if (l_width > 128) l_width = 128; if ((l_width == 80) || (l_width < 10)) l_width = 79; break; } case 'I': case 'i': { /* inverse video. */ Rflag ^= 4; break; } case 'B': case 'b': { /* backwards. */ Rflag ^= 2; break; } case 'U': case 'u': { /* upside down. */ Rflag ^= 1; break; } case 'S': case 's': { /* slanted. */ Rflag ^= 8; if (ap[2] == 'S' || ap[2] == 's') Rflag ^= 16; break; } } } else { for (pp = 0; ap[pp]; pp++) { if ( ( cpp = ap[pp]) == '\\' /* '\\' escapes: */ || cpp == '^') { /* if backslash curpos, check next character. */ cpx = ap[pp+1]; if (cpp == '^') ap[pp] = (cpx == '?') ? 0x7f : cpx & 0x1f; else if ( ( cpx >= 'A' && cpx <= 'Z' ) || ( cpx >= 'a' && cpx <= 'z') ) ap[pp] = cpx ^ 0x20; else if ( cpx == '_') ap[pp] = ' '; else ap[pp] = cpx; for (px = pp+1; /* copy the rest left one. */ ap[px] = ap[px+1]; px++) ; /* do nothing. */ } if ( (ap[pp] >= 'A' && ap[pp] <= 'Z') || (ap[pp] >= 'a' && ap[pp] <= 'z') ) ap[pp] |= casemask; } banner(f, l_width, ap, j); } } exit(0); } banner (font, width, str, just) int font, width, just; char *str; /* the command-line string to be bannered.. */ { char *a; /* current character pointer */ char *a1; /* pointer to last blank found */ int d; /* current line's max. desender */ int d1; /* max. desender to last blank */ int l_height; /* current line max. height */ int h1; /* max. height to last blank */ int linewidth; /* current line width accumulated */ int w1; /* size of line to last blank */ int i, j, j1, c, csp; int adjust; /* per-line loop increment. */ char line [140]; char enil [140]; int slant = 0; int rslant = 0; int height; /* final calculated height of line. */ int bb, lw, whichline; /* local variables for output routine. */ ch = ch1; csp = csp1; if (font == 1) { ch = ch2; csp = csp2; } spacechar = ( (Rflag & 4) ? ((ufillc) ? ufillc : '#') : ' '); while (*str) { /* process the input string. */ while (*str == ' ') str++; /* remove leading blanks */ recalc: d = d1 = l_height = h1 = linewidth = w1 =0; for (a = str; c = *a; a++) { /* extract the portion of str that fits one line.. */ if (c == ' ') { /* save location of space (possible wordwrap). */ a1 = a; d1 = d; h1 = l_height; w1 = linewidth - csp; } if ((ch[c].c_width) && (linewidth + ch[c].c_width > (width-slant))) break; /* next character would overflow the line. */ if (ch[c].c_width) { /* the character has a width. */ d = (d < -ch[c].c_descend) ? d : -ch[c].c_descend; l_height = (l_height > ch[c].c_height) ? l_height : ch[c].c_height; /* max height of this line. */ linewidth += (csp + ch[c].c_width); } } if ((c == 0) || (w1 == 0)) { /* no overflow. */ a1 = a; d1 = d; h1 = l_height; /* reset max height. */ w1 = linewidth - csp; } adjust = ( (Rflag & 1) ? 1 : -1 ); height = slant = ( (Rflag & 8) ? (h1 - d1 - 1) : 0); if ( (slant + w1 + (slant != 0) + ( (Rflag & 4) != 0)) > width) { /* slant causes overflow. */ goto recalc; } if (Rflag & 4) { /* reverse video. */ for (j = 0; j < width; line[j++] = spacechar); line[j] = 0; printf("%s\n",line); } if (Rflag & 8) { /* slant requested. */ i = ( (Rflag & 1) != 0) /* + ( (Rflag & 2) != 0) */ + ( (Rflag & 16) != 0); if ( i & 1 ) { /* reverse polarity of slant. */ slant = 0; rslant = 1; } } /* (Rflag&1)for (i = d1+1; i <= h1; i++) */ /* (!(Rflag&1))for (i = h1; i > d1; i--) */ for ( whichline = ( (Rflag & 1) ? (d1 + 1) : h1); ( (Rflag & 1) ? (whichline <= h1) : (whichline > d1) ); whichline += adjust ) { /* process one output line. */ for (j = 0; j < width; line[j++] = spacechar); line[j] = 0; j = jj(just, width, w1, Rflag, slant, height) ; j1 = 0; for (a = str; a < a1; a++) { /* for each character. */ c = *a; if ( lw = ch[c].c_width ) { /* character is not undefined. */ j += lw; if ((whichline <= ch[c].c_height) && (whichline > -ch[c].c_descend)) { /* if whichline is in range for character. */ l_height = ch[c].c_height - whichline; while (lw) { /* for each bit of its width. */ lw--; if (tstOmap(c, l_height, lw)) { /* bit for this column is set. */ j1 = j - lw; if (Rflag & 4) /* reverse vid. */ line[j1] = ' '; else /* normal video. */ line[j1] = (c < ' ' || c == 127 || ufillc) ? ((ufillc)?ufillc:'#') : c; } } } j += csp; } } if ( ! (Rflag & 4)) line[j1+1] = '\0'; if (Rflag & 2) { /* backwards. */ int i; for (i = 0; i < width; i++) { enil[i] = line[(width-1)-i]; if (enil[i] == 0) enil[i] = spacechar; } enil[width] = 0; printf("%s\n", enil); } else printf ("%s\n", line); if (Rflag & 8) { /* slant. */ if (rslant) slant++; else slant--; } } if (Rflag & 4) { /* reverse video. */ int i; for (i = 0; i < width; i++) { line[i] = spacechar; } printf("%s\n", line); } else printf ("\n\n"); str = a1; } } jj(just, width, w1, r, slant, height) { /* get justification value. */ int j; if (r & 2) { /* backwards. */ if (just == left) j = width - height - w1 -1 - ( (r&4) != 0) + slant; else if (just == right) j = -1 + ( (r & 4) != 0) + slant; else j = (width - w1 - height) / 2 - 1 + slant; } else { /* normal. */ if (just == left) j = -1 + ( (r & 4) != 0) + slant; else if (just == right) j = width - height - w1 -1 - ( (r&4) != 0) + slant; else j = (width - w1 - height) / 2 - 1 + slant; } return (j); } tstOmap( index, entry, bitno) { int base, shiftamt, retval, idisp; base = ( entry * wbytes ); idisp = wbytes - 1 - ( bitno >> 3 ); /* / 8 ); */ shiftamt = bitno & 7; /* % 8; */ retval = ch[index].c_bitmap[base + idisp] & ( 1 << shiftamt ); /* fprintf(stderr, "tstOmap(index=%d<%c>, entry=%d<%x>, bitno=%d): base=%d, idisp=%d,\n", index, index, entry, entry, bitno, base, idisp); fprintf(stderr, " shiftamt=%d, retval=%d, ch[index].c_width=%d,\n", shiftamt, retval, ch[index].c_width); fprintf(stderr, " ch[index].c_height=%d, ch[index].descend=%d,\n", ch[index].c_height, ch[index].c_descend); fprintf(stderr, " ch[index].c_bitmap= 0x%x, 0x%x, 0x%x, 0x%x\n\n", ch[index].c_bitmap[0], ch[index].c_bitmap[1], ch[index].c_bitmap[2], ch[index].c_bitmap[3]); */ return ( retval != 0 ); } /* end newfont.c . */