home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / cpm / list / banner03.lbr / XBFONT.CZ / XBFONT.C
Text File  |  1988-01-08  |  12KB  |  385 lines

  1. /* this is bfont.c, by Burt Solomon, roughly 1984 or 1985:
  2.  
  3. SET YOUR EDITOR TO EXPAND TABS TO 4 SPACES!!!
  4.  
  5. RELEASE 0.3 NOTES:
  6. Defining a character with "^a  >" instead of "<a  >" makes it a control 
  7. character.
  8. ----------------------------------
  9.  
  10. BS doesn't comment very well, but he sure is clever.
  11. It compiles to a program which:
  12. (1) inputs a file like font.1, and
  13. (2) outputs a file like font1.d;
  14.  
  15. 1987: porting to CP/M, AZTEC C: first tried changing some ints to longs 
  16. (character size wider than 16 won't work with int); then discovered that 
  17. no manipulations of longs work correctly in AZTEC C.
  18. Please note that my version of AZTEC C dates from 1982, and they may 
  19. have improved things since then.
  20. However, severe compiler braindamage requires extensive rewriting.
  21.  
  22. FORMAT OF (1) input file:
  23.  <X     >
  24.  #      #
  25.   #    #
  26.    #  #
  27.     ##
  28.    #  #
  29.   #    #
  30.  #      #
  31.  %
  32.     #
  33.  <Y et cetera
  34. ,where the lines heve the following meanings
  35. <x  > says "this is the letter x and its width is as specified by the <>"
  36.  ##   lines make a picture of the letter; the number of lines defines the 
  37.       height of the letter.
  38. %     the ## lines that follow describe desenders (sic), as spelled by the
  39.       author.
  40.  ##   lines describe the descender.
  41. <     start of a new i.d. line ends the letter.
  42. NOTE: allowing more than one letter definition on the same line complicates 
  43. the program.  
  44.  
  45. FORMAT OF (2) output:
  46. 'C' program source -- declarations for static initializers to be used by 
  47. newfont.c -- to be #included there.
  48.  
  49.  #ifdef DEBUG lines added while porting to aztec C 1987
  50. */
  51. /* #define DEBUG */
  52.  
  53. #include "stdio.h"
  54.  
  55. #define nchars 128    /* number of chars in char set*/
  56.     /* changed for release 0.3: in a new font, ^A (for example) might
  57.     ** be used for a special effect: to print some pretty picture...
  58.     */
  59. #define nlines 16    /*number of lines above base line in a banner character*/
  60. #define dlines  3    /*number of lines desending in a banner character*/
  61. #define mxl    19    /*number of lines max. in a banner character*/
  62.  
  63. #define mxw    32    /*max width of a banner character. */
  64. #define wbytes  4    /* bytes used in a bitmask for this width. */
  65.  
  66. /*    define the states for input to be in */
  67. #define def_next 0
  68. #define def_char 1
  69. #define def_end  2
  70. #define fil_char 3
  71. #define desend   4
  72.  
  73. int inputchar;            /* current character */
  74. int line;        /* current line being worked on */
  75. int col;        /* column on current line */
  76. char curmap[wbytes];    /* working bitmap. */
  77. char ctrlflag = 0;
  78.  
  79. struct chr
  80. {
  81.     int tablechar;        /* this character */
  82.     int startcol;        /* starting column for this character */
  83.     int width;        /* width of this character */
  84.     int height;        /* height of this character */
  85.     int descent;        /* decesending amount for this character */
  86.     char bitmap[mxl*wbytes];    /* one mask for each line */
  87. }
  88. ch[nchars];
  89.  
  90. main(argc,argp)
  91. char **argp;int argc;
  92. {
  93.     int bitnumber;    /* number of bit in current scan. */
  94.     register int curchar;    /* current character being worded on */
  95.     int first;        /* first character current line */
  96.     int last;        /* last character current line */
  97.     int dflag;            /* desender flag */
  98.     int state;        /* current state of affairs */
  99.     int workheight;    /* working height of character. */
  100.     int bb, findflag;
  101.  
  102.     for (curchar = 0; curchar < nchars; curchar++)
  103.     {
  104.          ch[curchar].tablechar = -1;
  105.          ch[curchar].startcol = ch[curchar].width = ch[curchar].height =
  106.               ch[curchar].descent = 0;
  107.     }
  108.  
  109.     line = curchar = first = last = 
  110.         col = dflag = 0;    /* guarantee initial values. */
  111.     clrcmap();                /* clear working bitmap */
  112.     state = def_next;        /* current working state */
  113.  
  114.     while ((inputchar = getchar()) != EOF)    /* till end of file */
  115.     {   if (inputchar == 13) continue;    /* don't trust CP/M I/O */
  116.         if (inputchar == '!' && col == 0)    /* comment in any state. */
  117.             while ((inputchar = getchar()) != EOF
  118.                 && inputchar != '\n');    /* do nothing. */
  119.         switch (state)
  120.         {
  121.         case def_next:        /* start of a new character */
  122.             if (inputchar == '<' || inputchar == '^')
  123.             {    /* yes it starts a definition. */
  124.                 ch[curchar].startcol = col;    /* curchar starts at column */
  125.                 state = def_char;    /* next get characters name */
  126.                 ctrlflag = (inputchar == '^');
  127.             }
  128.             else if (inputchar == '\n' || inputchar == '!')
  129.             {    /* end of "start definitions" line. */
  130.                 if  (curchar != first)
  131.                 {    /* we had at least one full definition. */
  132.                     state = fil_char;    /* get contents of char. */
  133.                     curchar = first;    /* point to first on line. */
  134.                 }    /* else it is a blank line. */
  135.                 if (inputchar == '!')
  136.                 {    /* comment. */
  137.                     while ((inputchar = getchar()) != EOF
  138.                     && inputchar != '\n');    /* do nothing. */
  139.                 }
  140.             }
  141.             else if (inputchar != ' ') err ("Invalid define character");
  142.             break;
  143.  
  144.         case def_char:        /* name this character now */
  145.             if (inputchar < 0 || inputchar > 128)
  146.             {    err ("Invalid character name");
  147.             }    /* changed release 0.3: allow definitions of funny
  148.                 ** characters. \n and \r will not work of course!
  149.                 */
  150.             if (ctrlflag) inputchar &= 0x1f;
  151.             ctrlflag = 0;
  152.             ch[curchar].tablechar = inputchar;
  153.             state = def_end;
  154.             break;
  155.  
  156.         case def_end:        /* mark the size of this character */
  157.             if (inputchar == '>')
  158.             {    /* found the end. */
  159.                 ch[curchar].width = col - ch[curchar].startcol + 1;
  160.                 if (ch[curchar].width > mxw)
  161.                     err ( "character too wide!" );
  162.                 dflag = ch[curchar].height = ch[curchar].descent = 0;
  163.                 clrOmap(curchar);    /* clear out its map. */
  164.                 clrcmap();            /* clear working bitmap */
  165.                 state = def_next;    /* look for another on same line. */
  166.                 curchar = ++last;    /* point to next char. */
  167.             }
  168.             else if (inputchar != ' ') err ("Invalid define character");
  169.             break;
  170.  
  171.         case desend:        /* processing the start of desending */
  172.             if (dflag < 0)
  173.             {    /* waiting for end of "%" line. */
  174.                 if (inputchar != '\n') err ("Invalid desending character");
  175.                 dflag = 0;
  176.                 break;
  177.             }    /* else fall through to case fil_char */
  178.  
  179.         case fil_char:        /* fill in this characters mask now */
  180.             if (ch[curchar].startcol == col)
  181.             {    /* begin working on curchar. */
  182.                 clrcmap();        /* clear working bitmap */
  183.                 bitnumber = ch[curchar].width;
  184. #ifdef DEBUG
  185. printf("start curchar=%d dflag=%d workheight=%d bitnumber=%d\n",
  186. curchar, dflag, workheight, bitnumber);
  187. #endif
  188.             }
  189.             bitnumber--;    /* proceed to next bit in final mask. */
  190. #ifdef DEBUG
  191. printf("curchar=%d dflag=%d workheight=%d bitnumber=%d\n",
  192. curchar, dflag, workheight, bitnumber);
  193. #endif
  194.             if (inputchar == '#')
  195.             {    /* specifies a position to be set. */
  196.                 if (bitnumber < 0)
  197.                     err("unexpected '#', check space between characters\n");
  198.                 setcmap(bitnumber);    /* set bit in curmap. */
  199.             }
  200.             if (bitnumber == 0)
  201.             {    /* width of curchar was used up. */
  202. #ifdef DEBUG
  203. printf("end of curchar=%d dflag=%d workheight=%d\n",
  204. curchar, dflag, workheight);
  205. #endif
  206.                 if (col != (ch[curchar].startcol + ch[curchar].width -1))
  207.                     err("Internal error 1!");
  208.                 bitnumber = -1;     /* yes this is a kludge */
  209.                 workheight = ch[curchar].height + dflag;
  210.                 cpycmap(curchar, workheight);
  211.                 curchar++;    /* point to next character. */
  212.                 clrcmap();    /* clear working bitmap */
  213.                 if (inputchar == ' ' || inputchar == '#') break;
  214.             }
  215.             if (inputchar == ' ') break;
  216.             if (inputchar == '#' && bitnumber >= 0) break;
  217.             if (inputchar == '\n')
  218.             {    /* end-of-line may be "premature" */
  219.                 workheight = ch[curchar].height + dflag;
  220.                 if (tstcmap()) cpycmap(curchar, workheight);
  221.                 if (state == desend)
  222.                 {    /* we are processing descenders. */
  223.                     for (curchar = first; curchar < last; curchar++)
  224.                     {    /* check all characters defined on these lines. */
  225.                         workheight = ch[curchar].height + dflag;
  226.                         if (tstOmap(curchar, workheight))
  227.                             ch[curchar].descent = dflag + 1;
  228.                     }
  229.                     dflag++;
  230.                 }
  231.                 else
  232.                 {    /* not descenders. workheight == ch[].height */
  233.                     for (curchar = first; curchar < last; curchar++)
  234.                         if (tstOmap(curchar, 0))
  235.                             ch[curchar].height++;
  236.                 }
  237.                 clrcmap();    /* clear working bitmap */
  238.             }
  239.             else if (col == 0 && (inputchar == '<' || inputchar == '^'))
  240.             {    /* a new set of definitions. */
  241.                 ctrlflag = (inputchar == '^');
  242.                 state = def_char;
  243.                 first = curchar = last;
  244.                 ch[curchar].startcol = 0;
  245.             }
  246.             else if (col == 0 && inputchar == '%')
  247.             {    /* next line starts descenders. */
  248.                 dflag = -1;
  249.                 state = desend;
  250.             }
  251.             else
  252.             {    printf("curchar=%d workheight=%d state=%d\n",
  253.                     curchar, workheight, state);
  254.                 printf("first=%d last=%d dflag=%d\n",
  255.                     first,last,dflag);
  256.                 printf("ch[curchar].startcol=%d bitnumber=%d\n",
  257.                     ch[curchar].startcol, bitnumber);
  258.                 for (bb = 0; bb < curchar; bb++)
  259.                 {    printf(
  260. "ch[%d].tablechar=%x startcol=%d width=%d height=%d descent=%d\n",
  261.                     bb, ch[bb].tablechar, ch[bb].startcol,
  262.                     ch[bb].width, ch[bb].height, ch[bb].descent);
  263.                 }
  264.                 err ("Invalid fill character");
  265.             }
  266.             break;
  267.  
  268.         default:
  269.             break;
  270.         }
  271.  
  272.         col++;
  273.         if (inputchar == '\n')
  274.         {
  275.             curchar = first;
  276.             col = 0;
  277.             line++;
  278.         }
  279.     }
  280.  
  281.     /* write out the table now */
  282.  
  283.     for (inputchar = 0; inputchar < 128; inputchar++)
  284.     {    /* scan all possible banner characters in order. */
  285.         findflag = 0;
  286.  
  287.         for (curchar = 0; curchar < nchars; curchar++)
  288.             if (ch[curchar].tablechar == inputchar)
  289.             {    /* curchar was defined. */
  290.                 findflag = 1;
  291.                 break;
  292.             }
  293.  
  294.         if (findflag)
  295.         {    /* character was defined. */
  296. #ifdef DEBUG
  297. printf (" /* character 0x%x was defined: */\n", inputchar);
  298. #endif
  299.             printf ("{%d,%d,%d", ch[curchar].width, ch[curchar].height,
  300.                 ch[curchar].descent);
  301.             findflag = (ch[curchar].descent + ch[curchar].height) * wbytes;
  302.             for (bb = 0; bb < findflag; bb++)
  303.             {
  304.                 printf(",0x%x%s",ch[curchar].bitmap[bb],
  305.                     ( ( bb % 8 ) == 7 ) ? "\n\t" : " " );
  306.             }
  307.             if (inputchar == 127 || inputchar <= ' ')
  308.                 printf("}%s  \/* 0x%x */\n",
  309.                     ((inputchar == 127) ? "" : ","),
  310.                     inputchar);
  311.             else
  312.                 printf("}%s  \/* %c *\/\n",
  313.                     ((inputchar == 127) ? "" : ","),
  314.                     inputchar);
  315.         }
  316.         else
  317.         {    /* undefined character. */
  318.             printf ("{0,0,0}%s  \/* 0x%x *\/\n",
  319.                 ((inputchar == 127) ? "" : ","),
  320.                 inputchar);
  321.         }
  322.     }
  323. }
  324.  
  325. err(str)
  326. char *str;
  327. {
  328.     printf ("%s, inputchar=%x, line=%d, col=%d\n", str, inputchar, line,
  329. col);
  330.     exit (1);
  331. }
  332.  
  333. clrcmap()
  334. {    int i;
  335.     for (i = 0; i < wbytes; i++)
  336.         curmap[i] = 0;
  337. }
  338.  
  339. clrOmap(index)
  340. {    int i;
  341.     for (i = 0; i < (mxl*wbytes); i++)
  342.         ch[index].bitmap[i] = 0;
  343. }
  344.  
  345. cpycmap(index, entry)
  346. {    int i, base;
  347.     base = entry * wbytes;
  348.     for (i = 0; i < wbytes; i++)
  349.         ch[index].bitmap[base+i] = curmap[i];
  350. }
  351.  
  352. tstcmap()
  353. {    /* is the working bitmap not all zeroes? */
  354.     int i;
  355.     for (i = 0; i < wbytes; i++)
  356.         if (curmap[i] != 0) return (1);
  357.     return (0);
  358. }
  359.  
  360. tstOmap(index, entry)
  361. {    /* see if a "long" in ch[index].bitmap[] is not all zeroes. */
  362.     int i, base;
  363.     base = entry * wbytes;
  364.     for (i = 0; i < wbytes; i++)
  365.         if (ch[index].bitmap[base + i] != 0) return (1);
  366.     return (0);
  367. }
  368.  
  369. setcmap(bitno)
  370. {    /* set a bit in curmap: 0 is curmap[wbytes-1]&1, max curmap[0]&0x80 */
  371.     int index;
  372.     char localmask;
  373.  
  374.     index = wbytes - 1 - ( bitno / 8 );
  375. /*    bitno        result (wbytes==4)
  376.     0 to 7        (4 - 1 - (0/8)) == 3
  377.     8 to 15        (3 - (15/8) == 2
  378. and so forth.
  379. */
  380.     localmask = 1 << ( bitno % 8 );
  381.     curmap[index] |= localmask;
  382. }
  383.  
  384.  
  385.