
/****************************************************************************
 *
 * MODULE:       g.mkfontcap
 * AUTHOR(S):    Paul Kelly
 * PURPOSE:      Generates the font configuration file by scanning various
 *               directories for GRASS stroke and Freetype-compatible fonts.
 *              
 * COPYRIGHT:    (C) 2007 by the GRASS Development Team
 *
 *               This program is free software under the GNU General Public
 *               License (>=v2). Read the file COPYING that comes with GRASS
 *               for details.
 *
 *****************************************************************************/

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

#include <grass/gis.h>
#include <grass/fontcap.h>

#include "local_proto.h"

struct font_desc
{

    char *filename;   /**< Filename in fonts directory */

    char *description;/**< Descriptive name of font contained in this file */
};

static struct font_desc *font_descriptions = NULL;
static int num_descriptions = 0;

static int load_font_descriptions(const char *);
static void free_font_descriptions(void);
static const char *get_desc(const char *);

/**
 * \brief Find Stroke fonts and store them in a global GFONT_CAP struct
 * 
 * The directory $GISBASE/fonts is listed to find all stroke fonts (i.e.
 * files with a .hmp extension).
 * Information on each font is stored in the global GFONT_CAP struct, 
 * fontcap, to be used by the main program.
 **/

void find_stroke_fonts(void)
{
    char *dirpath, *fonttable;
    char **dirlisting;
    int numfiles, i;

    G_asprintf(&dirpath, "%s/fonts", G_gisbase());

    dirlisting = G__ls(dirpath, &numfiles);

    G_asprintf(&fonttable, "%s/fonts.table", dirpath);
    if (access(fonttable, R_OK) == 0)
	load_font_descriptions(fonttable);

    for (i = 0; i < numfiles; i++) {
	if (!strstr(dirlisting[i], ".hmp"))
	    continue;

	if (totalfonts >= maxfonts) {
	    maxfonts += 20;
	    fontcap = G_realloc(fontcap, maxfonts * sizeof(struct GFONT_CAP));
	}

	/* Path */
	G_asprintf(&fontcap[totalfonts].path, "%s%c%s", dirpath,
		   HOST_DIRSEP, dirlisting[i]);
	G_convert_dirseps_to_host(fontcap[totalfonts].path);
	/* Description & Name */
	fontcap[totalfonts].longname = G_store(get_desc(dirlisting[i]));
	*(strstr(dirlisting[i], ".hmp")) = '\0';
	fontcap[totalfonts].name = G_store(dirlisting[i]);
	/* Font Type */
	fontcap[totalfonts].type = GFONT_STROKE;
	/* These two probably not relevant */
	fontcap[totalfonts].index = 0;
	fontcap[totalfonts].encoding = G_store("utf-8");
	totalfonts++;

	G_free(dirlisting[i]);
    }
    G_free(dirlisting);

    if (font_descriptions)
	free_font_descriptions();

    return;

}

/**
 * \brief Loads description file for stroke fonts into memory
 *
 * Parses the font description file and loads an array of filenames
 * and corresponding descriptions pointed at by the static variable
 * font_descriptions. After calling, num_descriptions will contain
 * the number of font descriptions that were loaded.
 * 
 * \param descfile Filename to be loaded
 *
 * \return 1 if at least one font description was loaded; 0 otherwise
 **/

static int load_font_descriptions(const char *descfile)
{
    size_t memsize = 0;
    FILE *fp;
    char buff[500];

    fp = fopen(descfile, "r");
    if (fp == NULL) {
	G_warning("Unable to open font description file %s for reading: %s",
		  descfile, strerror(errno));
	return 0;
    }

    while (G_getl2(buff, sizeof(buff), fp)) {
	char name[100], description[256];

	if (buff[0] == '#')
	    continue;

	if (sscanf(buff, "%99[^|]|%255[^\n]", name, description) != 2)
	    continue;

	if (num_descriptions >= memsize) {
	    memsize += 20;
	    font_descriptions = G_realloc(font_descriptions,
					  memsize * sizeof(struct font_desc));
	}

	font_descriptions[num_descriptions].filename = G_store(name);
	font_descriptions[num_descriptions].description =
	    G_store(description);
	num_descriptions++;
    }

    fclose(fp);

    return (num_descriptions > 0);
}

/**
 * \brief Returns the descriptive name corresponding to a stroke font
 *
 * Searches through the static font_descriptions name for a descriptive
 * name matching the filename passed to the function. If a match is found,
 * the descriptive name is returned; otherwise the filename that was 
 * originally passed is returned.
 * 
 * \param filename Filename of stroke font
 * 
 * \return Const string containing descriptive name for the font
 **/

static const char *get_desc(const char *filename)
{
    int i;

    for (i = 0; i < num_descriptions; i++)
	if (G_strcasecmp(filename, font_descriptions[i].filename) == 0)
	    return font_descriptions[i].description;

    /* If there was no font descriptions file, or the filename wasn't found
     * in it, we'll end up here and simply return the filename for the
     * description */

    return filename;
}

/**
 * \brief Frees the memory used by the table of font descriptive names
 **/

static void free_font_descriptions(void)
{
    int i;

    for (i = 0; i < num_descriptions; i++) {
	G_free(font_descriptions[i].filename);
	G_free(font_descriptions[i].description);
    }

    return;
}
