/* Program to analyse the file tex:fontdb and produce stats of font usage. */

#include <stdio.h>

FILE    *db, *fp, *fopen();

char	database[] = "fontdb",
        fontname[20];

int     mode;

struct pxl_listst {
         int  times;
         char pxlfile[25];
         struct pxl_listst *next;
       };

/* SPLIT */
/* Split takes a line and splits it into four fields: font number, name, size */
/* and pxl filename */
split(line,fontnum,fntname,fontsize,pxlfile)
char  *line,
      *fntname,
      *pxlfile;
int   *fontnum;
long int *fontsize;
{
int   x=0;

  *fontnum = 0;
  while (*line != '\t') {                    /* Fields are separated by a tab */
    *fontnum = *fontnum*10+(*line-'0');
    ++line;
  }
  ++line;

  while (*line != '\t') {                    /* Get string */
    fntname[x] = *line;
    ++line;
    ++x;
  }
  fntname[x] = '\0';
  ++line;

  *fontsize = 0;
  while (*line != '\t') {                    /* Get size */
    *fontsize = *fontsize*10+(*line-'0');
    ++line;
  }
  ++line;

  x = 0;
  while (*line != '\n') {                    /* Get pxl filename */
    pxlfile[x++] = *line;
    ++line;
  }
  pxlfile[x] = '\0';

} /* split */


/* SORT_PXL_LIST */
/* Returns a pointer to a list of pxlfiles in decreasing order of usage */
struct pxl_listst *sort_pxl_list(list)
struct pxl_listst *list;
{
struct pxl_listst *temp, 
                  *prevrec,
                  *sorted;
int max = 0;

  temp = sorted = NULL;
  while (list != NULL) {
    if ((*list).times > max) {                /* Put at start of list */
      if (sorted == NULL) {                   /* Special case at start */
        sorted = (struct pxl_listst *) calloc(1, sizeof(struct pxl_listst));
        sorted->times = list->times;
        strcpy(sorted->pxlfile, list->pxlfile);
        sorted->next = NULL;
      } else {
        temp = (struct pxl_listst *) calloc(1, sizeof(struct pxl_listst));
        temp->times = list->times;
        strcpy(temp->pxlfile, list->pxlfile);
        temp->next = sorted;
        sorted = temp;
      }
      max = (*list).times;
    } else {                                  /* Insert at correct place */
      prevrec = sorted;
      temp = sorted->next;
      while (((*list).times < (*temp).times) && temp != NULL) {
        prevrec = temp;
        temp = temp->next;
      }
      if (temp == NULL) {                     /* Append to list */
        temp = (struct pxl_listst *) calloc(1, sizeof(struct pxl_listst));
        temp->times = list->times;
        strcpy(temp->pxlfile, list->pxlfile);
        temp->next = NULL;
        prevrec->next = temp;
      } else {
        (*prevrec).next = (struct pxl_listst *) calloc(1, sizeof(struct pxl_listst));
        prevrec = (*prevrec).next;
        prevrec->times = list->times;
        strcpy(prevrec->pxlfile, list->pxlfile);
        prevrec->next = temp;
      }
    }
    list = (*list).next;
  }
  return(sorted);
}  /* sort_pxl_list */


/* ANAL ALL */
/* Produces list of pxl files against number of times used */
anal_all()
{

char     line[80],
         fontname[20],
         no_of_fonts[10],
         pxlfile[25];

int     fontnum,
        total = 0,
        x, y;

long int fontsize;

struct pxl_listst *pxl_list, *temp;

  pxl_list = NULL;
  while (fgets(line, 80, fp) != 0) {
    fgets(no_of_fonts, 10, fp);
    y = atoi(no_of_fonts);
    total = total+y;
    for (x=0; x<y; x++) {
      fgets(line, 80, fp);
      split(line, &fontnum, fontname, &fontsize, pxlfile);
      if (pxl_list == NULL) {
        pxl_list = (struct pxl_listst *) calloc(1,sizeof(struct pxl_listst));
        pxl_list->times = 1;
        strcpy(pxl_list->pxlfile, pxlfile);
        pxl_list->next = NULL;
      } else {
        temp = pxl_list;
        while ((strcmp((*temp).pxlfile, pxlfile) != 0) && (*temp).next != NULL) 
                                                               temp = temp->next;
        if (strcmp((*temp).pxlfile, pxlfile) == 0) {
          (*temp).times++;
        } else {
          temp->next = (struct pxl_listst *) calloc(1,sizeof(struct pxl_listst));
          temp = temp->next;
          strcpy(temp->pxlfile, pxlfile);
          temp->times = 1;
          temp->next = NULL;
        } 
      }
    }
  }

  temp = sort_pxl_list(pxl_list);
  pxl_list = temp;

  /* Print out results */
  printf("Total Number of Pxl files = %d\n", total);
  printf("Pxl file\t\tTimes\t%%\n");
  while (pxl_list != NULL) {
    printf("%s\t", (*pxl_list).pxlfile);
    if (strlen((*pxl_list).pxlfile) < 16) printf(" \t");
    printf("%d\t%d%%\n", (*pxl_list).times, (*pxl_list).times*100/total);
    pxl_list = (*pxl_list).next;
  }
}  /* anal_all */


/* ANAL FONT */
/* print out number of times a certain font was used. */
anal_font(font)
char    *font;
{
int	y,
 	x,
        total=0,
	fontnum;

long int fontsize;

struct  fontlist {
          int      times;
          char     pxlfile[25];
          struct fontlist *next;
        };

char	line[80],
	fontname[20],
        pxlfile[25],
	no_of_fonts[10];

struct fontlist *fontinfo, *temp;

  fontinfo = NULL;
  while (fgets(line, 80, fp) != 0) {
    fgets(no_of_fonts, 10, fp);
    y = atoi(no_of_fonts);
    for (x=0; x<y; x++) {
      fgets(line, 80, fp);
      split(line, &fontnum, fontname, &fontsize, pxlfile);
      if (strcmp(fontname, font) == 0) {
        ++total;
        if (fontinfo == NULL) {
          fontinfo = (struct fontlist *) calloc(1,sizeof(struct fontlist));
          fontinfo->times = 1;
          strcpy(fontinfo->pxlfile, pxlfile);
          fontinfo->next = NULL;
        } else {
          temp = fontinfo;
          while ((strcmp((*temp).pxlfile, pxlfile) != 0) && (*temp).next != NULL) 
                                                                temp = temp->next;
          if (strcmp((*temp).pxlfile, pxlfile) == 0) {
            temp->times++;
          } else {
            temp->next = (struct fontlist *) calloc(1,sizeof(struct fontlist));
            temp = temp->next;
            temp->times = 1;
            strcpy(temp->pxlfile, pxlfile);
            temp->next = NULL;
          };
        }
      }
    }
  }
  
  /* Print out results */
  printf("Font %s was used a total number of %d times\n", font, total);
  printf("Times\tPxlfile\n");
  while (fontinfo != NULL) {
    printf("%d\t%s\n", (*fontinfo).times,
                       (*fontinfo).pxlfile);
    fontinfo = (*fontinfo).next;
  }
}   /* anal_font */



main()
{
  printf("Font usage analyser\n");
  printf("-------------------\n");
  printf("Mode 1 produces a list of pxl files and the number of times they\n");
  printf("       appear in the database\n");
  printf("Mode 2 produces a list of different pxl files for a particular font\n");
  printf("Mode 3 to exit\n");

  for (;;) {
    if ((db = fopen(database,"r")) == NULL) {           /* Check database exists */
      printf("Can't open %s for input\n", database);
      return(0);
    }
    fp = db;

    printf("\nMode: ");
    scanf("%d", &mode);
    switch (mode) {
      case 1: anal_all();
              break;
      case 2: printf("Which font: ");
              scanf("%s", fontname);
              anal_font(fontname);
              break;
      case 3: return(0);
      default : printf("\nMode must be in range 1-3\n");
   }

  }
}
