home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 215.lha / FTS / fts.c < prev    next >
C/C++ Source or Header  |  1996-02-15  |  8KB  |  363 lines

  1. /*
  2.  *    list fonts, print info about them
  3.  */
  4.  
  5. /* Two versions:  
  6.  *    large, with select/sort/help options    -DFTS_LARGE
  7.  *    small, bare-bones             (default)
  8.  */
  9.  
  10. #include    <proto/exec.h>
  11. #include    <proto/diskfont.h>
  12.  
  13. #include    <string.h>
  14. #include    <exec/types.h>
  15. #include    <exec/memory.h>
  16. #include    <libraries/diskfont.h>
  17. #include    <graphics/text.h>
  18.  
  19. #define    AFSIZE    2000L
  20.  
  21. long    brkclean();
  22. short    fontcmpname();
  23. void    mkflags(), combine(), fixname(), cleanup(), shortbits();
  24.  
  25. #ifdef FTS_LARGE
  26. void    showhelp(), doargs();
  27. short    fontcmpsize(), select(), mksel();
  28. #endif
  29.  
  30. /* if you don't use 'proto/diskfont.h', then you'll need this:
  31. extern long DiskfontBase;
  32.  */
  33.  
  34. struct    AvailFontsHeader    *afh;
  35.  
  36. #ifdef FTS_LARGE
  37. struct    selinfo {        /* place to keep select options */
  38.     short    valid, type, style, flags, ysize, sort;
  39.     char    *name;
  40. };
  41. /* flag bits for 'valid' selections (things that the user set) */
  42. #define    SEL_TYPE    0x01
  43. #define    SEL_STYLE    0x02
  44. #define    SEL_FLAGS    0x04
  45. #define    SEL_YSIZE    0x08
  46. #define    SEL_NAME    0x10
  47. #define    SEL_SORT    0x20
  48. #endif
  49.  
  50. #define    FBUFSZ    24        /* length of flags string in the listing */
  51.  
  52. void main(ac, av)
  53. int    ac;
  54. char    *av[];
  55. {
  56.     register struct    AvailFonts        *af;
  57.     register struct    TextAttr        *ta;
  58.     unsigned short    num ,i, cnt;
  59.     char    flagbuf[FBUFSZ];
  60. #ifdef FTS_LARGE
  61.     struct    selinfo    selinfo;
  62. #endif
  63.  
  64.     afh = NULL;            /* init for cleanup */
  65.     onbreak(&brkclean);        /* clean-up on ^C/^D */
  66.  
  67. #ifdef FTS_LARGE
  68.     selinfo.sort = 0;        /* sort by name */
  69.     selinfo.valid = 0;        /* no others have been selected */
  70.     selinfo.type = selinfo.style = selinfo.flags = 0;
  71. #endif
  72.     afh = (struct AvailFontsHeader *) AllocMem(AFSIZE, MEMF_CLEAR);
  73.     if ( afh == NULL ) {
  74.         exit(10L);
  75.     }
  76.     if ( (DiskfontBase = OpenLibrary("diskfont.library",0L)) == (long)NULL ) {
  77.         cleanup();
  78.         exit(15L);
  79.     }
  80. #ifdef FTS_LARGE
  81.     doargs(ac, av, &selinfo);    /* find out what they asked for */
  82. #endif
  83.     if ( AvailFonts((char *)afh, AFSIZE, 0xffL) != 0 )
  84.         printf("Some fonts not gotten...\n"); /* really should try again */
  85.     num = afh->afh_NumEntries;
  86.     af = (struct AvailFonts *) &afh[1];        /* trick from RKM */
  87.  
  88.     qsort(af, num, sizeof (struct AvailFonts),    /* sort names/sizes */
  89. #ifdef FTS_LARGE
  90.          (selinfo.sort == 0) ? fontcmpname : fontcmpsize );
  91. #else
  92.          fontcmpname);
  93. #endif
  94.     printf("Font Name          Size Type Style  Flags\n");
  95.     cnt = 0;
  96.     for ( i = 0; i < num; i++, af++ ) {
  97.         ta = &af->af_Attr;
  98.         if ( ta->ta_Name == NULL ) {    /* when "combined" */
  99.             continue;
  100.         }
  101.         if ( i < (num-1) ) {        /* see if we can combine */
  102.             combine(af);
  103.         }
  104.         fixname(ta->ta_Name);        /* get rid of ".font" */
  105. #ifdef FTS_LARGE
  106.         if ( !select(af, &selinfo) ) {    /* if no match, skip it */
  107.             continue;
  108.         }
  109. #endif
  110.         mkflags(flagbuf, af->af_Type, ta->ta_Style, ta->ta_Flags);
  111.         printf("%-20s  %3d  %s\n", ta->ta_Name, ta->ta_YSize, flagbuf);
  112.         cnt++;
  113.     }
  114.     printf("%d / %d fonts.\n", cnt, num);
  115.     cleanup();
  116.     exit(0L);
  117. }
  118.  
  119. void cleanup()
  120. {
  121.     if ( DiskfontBase != NULL )
  122.         CloseLibrary(DiskfontBase);
  123.     if ( afh != NULL ) 
  124.         FreeMem((char *)afh, AFSIZE);
  125. }
  126.  
  127. long brkclean()
  128. {
  129.     cleanup();
  130.     return 1L;
  131. }
  132.  
  133. #ifdef FTS_LARGE
  134. /*
  135.  *    read command line args, fill in selinfo struct
  136.  */
  137. void doargs(ac, av, sp)
  138. register int    ac;
  139. register char    **av;
  140. register struct selinfo *sp;
  141. {
  142.     register char *p;
  143.  
  144.     while ( --ac > 0 ) {
  145.         p = *++av;
  146.         if ( *p != '-' )
  147.             continue;
  148.         ++p;
  149.         switch ( (*p++) ) {
  150.         case 't':        /* set type */
  151.             sp->type |= mksel(p, "dm", 0x2);
  152.             sp->valid |= SEL_TYPE;
  153.             break;
  154.         case 's':        /* set style */
  155.             sp->style |= mksel(p, "eibu", 0x8);
  156.             sp->valid |= SEL_STYLE;
  157.             break;
  158.         case 'f':        /* set flags */
  159.             sp->flags |= mksel(p, "xspwtbdr", 0x80);
  160.             sp->valid |= SEL_FLAGS;
  161.             break;
  162.         case 'y':        /* set ysize (only one!) */
  163.             sp->ysize = atoi(p);
  164.             sp->valid |= SEL_YSIZE;
  165.             break;
  166.         case 'n':        /* set name (only one!) */
  167.             sp->name = p;
  168.             sp->valid |= SEL_NAME;
  169.             break;
  170.         case 'S':        /* set sort by Size */
  171.             sp->sort = 1;
  172.             sp->valid |= SEL_SORT;
  173.             break;
  174.         default:
  175.             showhelp();
  176.         }
  177.     }
  178. }
  179. #endif
  180.  
  181. #ifdef FTS_LARGE
  182. /*
  183.  *    print help message, and cleanup and exit 
  184.  */
  185. void showhelp()
  186. {
  187. printf("Use:  fts  -t[dm] -s[eibu] -f[xspwtbdr] -y# -n(name) -S\n");
  188. printf("    Type:    -t    d = disk        m = memory\n");
  189. printf("    Style:    -s    e = extended        i = italics\n");
  190. printf("            b = bold        u = underline\n");
  191. printf("    Flags:    -f    x = removed        s = designed\n");
  192. printf("            p = proportional    w = wide dot\n");
  193. printf("            t = tall dot        b = backwards\n");
  194. printf("            d = disk font        r = rom\n");
  195. printf("    Size:    -y#    where `#' is YSize of the font\n");
  196. printf("    Name:    -n...    where `...' is the font name\n");
  197. printf("    Sort:    -S = sort by size instead of name\n");
  198.     cleanup();    /* clean up and exit */
  199.     exit(0);
  200. }
  201. #endif
  202.  
  203. /*
  204.  *    compare two AvailFonts structs, to sort by name/ysize
  205.  */
  206. short fontcmpname(f1, f2)
  207. struct AvailFonts *f1, *f2;
  208. {
  209.     int    stricmp();
  210.     short    r;
  211.     register struct    TextAttr *t1, *t2;
  212.  
  213.     t1 = &f1->af_Attr;
  214.     t2 = &f2->af_Attr;
  215.     if ( (r = stricmp(t1->ta_Name, t2->ta_Name)) == 0 ) {
  216.         r = t1->ta_YSize - t2->ta_YSize;
  217.     }
  218.     return r;
  219. }
  220.  
  221. #ifdef FTS_LARGE
  222. /*
  223.  *    compare two AvailFonts structs, to sort by ysize/name
  224.  */
  225. short fontcmpsize(f1, f2)
  226. struct AvailFonts *f1, *f2;
  227. {
  228.     int    stricmp();
  229.     short    r;
  230.     register struct    TextAttr *t1, *t2;
  231.  
  232.     t1 = &f1->af_Attr;
  233.     t2 = &f2->af_Attr;
  234.     if ( (r = t1->ta_YSize - t2->ta_YSize) == 0 ) {
  235.         r = stricmp(t1->ta_Name, t2->ta_Name);
  236.     }
  237.     return r;
  238. }
  239. #endif
  240.  
  241. /*
  242.  *    see if the next (sorted) font has the same characteristics;
  243.  *    if so, combine that one's type with this one; mark it "empty"
  244.  */
  245. void    combine(ap)
  246. struct AvailFonts *ap;
  247. {
  248.     struct AvailFonts *ap2;
  249.     register struct    TextAttr *t1, *t2;
  250.  
  251.     ap2 = ap + 1;
  252.     t1 = &ap->af_Attr;
  253.     t2 = &ap2->af_Attr;
  254.     if ( (strcmp(t1->ta_Name, t2->ta_Name) == 0)
  255.         && t1->ta_YSize == t2->ta_YSize
  256.         && t1->ta_Style == t2->ta_Style
  257.         && t1->ta_Flags == t2->ta_Flags ) {    /* if TextAttr's are same, then combine avail-font types */
  258.         ap->af_Type |= ap2->af_Type;
  259.         t2->ta_Name = NULL;        /* mark it "combined" */
  260.     }
  261. }
  262.  
  263. /*
  264.  *    fix up the font name to print - get rid of the training ".font"
  265.  */
  266. void fixname(p)
  267. char    *p;
  268. {
  269.     register char    *s, *d;
  270.  
  271.     /* if Lattice's "strrchr" did what UNIX's "strrchr" did, we wouldn't have to do this... */
  272.     d = NULL;
  273.     for ( s = p; *s; s++ ) {
  274.         if ( *s == '.' )
  275.             d = s;
  276.     }
  277.     if ( d != NULL )
  278.         *d = '\0';        /* end the name at the last dot */
  279. }
  280.  
  281. /*
  282.  *    fill a print buffer with some flags: mem/style/attributes 
  283.  */
  284. void mkflags(p, t, s, f)
  285. char    *p;            /* destination buffer */
  286. short    t, s, f;        /* type, style, flags */
  287. {
  288.     /*        Type Style  Flags    */
  289.     strcpy (p, " --  ----  --------");    
  290.     shortbits(&p[1], t, "dm", '-', 0x2);
  291.     shortbits(&p[5], s, "eibu", '-', 0x8);
  292.     shortbits(&p[11], f, "xspwtbdr", '-', 0x80);
  293. }
  294.  
  295. /* turn flag bits into series of characters */
  296. void shortbits(p, v, t, fc, b)
  297. char    *p;        /* output string */
  298. short    v;        /* value to be decoded */
  299. char    *t;        /* true char string */
  300. short    fc;        /* false char */
  301. short    b;        /* top (start) bit */
  302. {
  303.     while ( b ) {                /* for each bit */
  304.         *p++ = ( b & v ) ? *t : fc;    /* accum chars if bit is set */
  305.         t++;                /* next char, next bit */
  306.         b >>= 1;
  307.     } 
  308. }
  309.  
  310. #ifdef FTS_LARGE
  311. /* turn characters into flag bits */
  312. short mksel(p, r, b0)
  313. register char    *p;        /* input char string */
  314. char    *r;            /* reference flag characters */
  315. short    b0;            /* top (start) bit */
  316. {
  317.     register short    v;    /* output value */
  318.     register char    *f;    /* current flag char */
  319.     register short    b;    /* current bit */
  320.  
  321.     v = 0;
  322.     while ( *p ) {        /* for each char in input */
  323.         f = r;
  324.         b = b0;
  325.         while ( *f ) {        /* for each char in reference */
  326.             if ( *p == *f )    /* if char's match, set the bit */
  327.                 v |= b;
  328.             f++;        /* next char, next bit */
  329.             b >>= 1;
  330.         } 
  331.         p++;        /* next input char */
  332.     }
  333.     return v;
  334. }
  335. #endif
  336.  
  337. #ifdef FTS_LARGE
  338. /*
  339.  *    see if the given font structure matches what was asked for 
  340.  */
  341. short select(af, ps)
  342. register struct AvailFonts *af;        /* what we're looking at */
  343. register struct selinfo *ps;        /* what they want to see */
  344. {
  345.     register short len;
  346.  
  347.     if ( (ps->valid & SEL_YSIZE) && (af->af_Attr.ta_YSize != ps->ysize) ) 
  348.             return 0;
  349.     len = strlen(ps->name);
  350.     if ( (ps->valid & SEL_NAME)
  351.         && (strnicmp(af->af_Attr.ta_Name, ps->name, len) != 0) )
  352.             return 0;
  353.     if ( (ps->valid & SEL_TYPE)  && !(af->af_Type & ps->type) )
  354.             return 0;
  355.     if ( (ps->valid & SEL_STYLE) && !(af->af_Attr.ta_Style & ps->style) )
  356.             return 0;
  357.     if ( (ps->valid & SEL_FLAGS) && !(af->af_Attr.ta_Flags & ps->flags) )
  358.             return 0;
  359.     return 1;
  360. }
  361. #endif
  362.  
  363.