main.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /****************************************************************************
  2. *
  3. * MODULE: g.mkfontcap
  4. * AUTHOR(S): Paul Kelly
  5. * PURPOSE: Generates the font configuration file by scanning various
  6. * directories for GRASS stroke and Freetype-compatible fonts.
  7. *
  8. * COPYRIGHT: (C) 2007-2015 by the GRASS Development Team
  9. *
  10. * This program is free software under the GNU General Public
  11. * License (>=v2). Read the file COPYING that comes with GRASS
  12. * for details.
  13. *
  14. *****************************************************************************/
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <sys/types.h>
  19. #include <sys/stat.h>
  20. #include <unistd.h>
  21. #include <errno.h>
  22. #include <grass/gis.h>
  23. #include <grass/fontcap.h>
  24. #include <grass/glocale.h>
  25. #include "local_proto.h"
  26. char **searchdirs;
  27. int numsearchdirs;
  28. struct GFONT_CAP *fontcap;
  29. int totalfonts;
  30. int maxfonts;
  31. static const char *standarddirs[] = {
  32. /* These are the directories that are searched for Freetype-compatible
  33. * font files by default. They may contain an environment variable
  34. * *at the start* of the string, if enclosed in ${xxx} syntax. */
  35. "/usr/lib/X11/fonts",
  36. "/usr/share/X11/fonts",
  37. "/usr/share/fonts",
  38. "/usr/local/share/fonts",
  39. "${HOME}/Library/Fonts",
  40. "/Library/Fonts",
  41. "/System/Library/Fonts",
  42. "${WINDIR}\\Fonts",
  43. NULL
  44. };
  45. static void add_search_dir(const char *);
  46. static int compare_fonts(const void *, const void *);
  47. int main(int argc, char *argv[])
  48. {
  49. struct Flag *tostdout, *overwrite;
  50. struct Option *extradirs;
  51. struct GModule *module;
  52. FILE *outstream;
  53. char *fontcapfile;
  54. int i;
  55. G_set_program_name(argv[0]);
  56. G_no_gisinit();
  57. G_set_gisrc_mode(G_GISRC_MODE_MEMORY);
  58. module = G_define_module();
  59. G_add_keyword(_("general"));
  60. module->description =
  61. _("Generates the font configuration file by scanning various directories "
  62. "for fonts.");
  63. overwrite = G_define_flag();
  64. overwrite->key = 'o';
  65. overwrite->description =
  66. _("Overwrite font configuration file if already existing");
  67. tostdout = G_define_flag();
  68. tostdout->key = 's';
  69. tostdout->description =
  70. _("Write font configuration file to standard output instead of "
  71. "$GISBASE/etc");
  72. extradirs = G_define_option();
  73. extradirs->key = "extradirs";
  74. extradirs->type = TYPE_STRING;
  75. extradirs->required = NO;
  76. extradirs->label = _("List of extra directories to scan");
  77. extradirs->description =
  78. _("Comma-separated list of extra directories to scan for "
  79. "Freetype-compatible fonts as well as the defaults (see documentation)");
  80. if (G_parser(argc, argv))
  81. exit(EXIT_FAILURE);
  82. if (!tostdout->answer) {
  83. const char *gisbase = G_gisbase();
  84. const char *alt_file = getenv("GRASS_FONT_CAP");
  85. if (alt_file)
  86. fontcapfile = G_store(alt_file);
  87. else
  88. G_asprintf(&fontcapfile, "%s/etc/fontcap", gisbase);
  89. if (!access(fontcapfile, F_OK)) { /* File exists? */
  90. if (!overwrite->answer)
  91. G_fatal_error(_("Fontcap file %s already exists; use -%c flag if you "
  92. "wish to overwrite it"),
  93. fontcapfile, overwrite->key);
  94. }
  95. }
  96. searchdirs = NULL;
  97. numsearchdirs = 0;
  98. /* Prepare list of directories to search */
  99. if (extradirs->answer) {
  100. #ifndef HAVE_FT2BUILD_H
  101. G_warning(_("This GRASS installation was compiled without "
  102. "Freetype support, extradirs parameter ignored"));
  103. #endif
  104. char *str = G_store(extradirs->answer);
  105. while ((str = strtok(str, ","))) {
  106. add_search_dir(str);
  107. str = NULL;
  108. }
  109. }
  110. i = -1;
  111. while (standarddirs[++i])
  112. add_search_dir(standarddirs[i]);
  113. totalfonts = maxfonts = 0;
  114. fontcap = NULL;
  115. find_stroke_fonts();
  116. find_freetype_fonts();
  117. qsort(fontcap, totalfonts, sizeof(struct GFONT_CAP), compare_fonts);
  118. if (tostdout->answer)
  119. outstream = stdout;
  120. else {
  121. outstream = fopen(fontcapfile, "w");
  122. if (outstream == NULL)
  123. G_fatal_error(_("Cannot open %s for writing: %s"), fontcapfile,
  124. strerror(errno));
  125. }
  126. for (i = 0; i < totalfonts; i++)
  127. fprintf(outstream, "%s|%s|%d|%s|%d|%s|\n", fontcap[i].name,
  128. fontcap[i].longname, fontcap[i].type, fontcap[i].path,
  129. fontcap[i].index, fontcap[i].encoding);
  130. fclose(outstream);
  131. exit(EXIT_SUCCESS);
  132. }
  133. static void add_search_dir(const char *name)
  134. {
  135. char envvar_name[256];
  136. char *fullname = NULL;
  137. if (sscanf(name, "${%255[^}]}", envvar_name) == 1) {
  138. char *envvar_value = getenv(envvar_name);
  139. /* N.B. If the envvar isn't set, directory is skipped completely */
  140. if (envvar_value)
  141. G_asprintf(&fullname, "%s%s", envvar_value,
  142. (name + strlen(envvar_name) + 3));
  143. }
  144. else
  145. fullname = G_store(name);
  146. if (fullname) {
  147. searchdirs = (char **)G_realloc(searchdirs,
  148. (numsearchdirs + 1) * sizeof(char *));
  149. searchdirs[numsearchdirs] = fullname;
  150. G_convert_dirseps_to_host(searchdirs[numsearchdirs]);
  151. numsearchdirs++;
  152. }
  153. return;
  154. }
  155. static int compare_fonts(const void *a, const void *b)
  156. {
  157. struct GFONT_CAP *aa = (struct GFONT_CAP *)a;
  158. struct GFONT_CAP *bb = (struct GFONT_CAP *)b;
  159. /* Sort first by type, then by name */
  160. if (aa->type != bb->type)
  161. return (aa->type > bb->type ? 1 : -1);
  162. else {
  163. const char *na = aa->name;
  164. const char *nb = bb->name;
  165. return G_strcasecmp(na, nb);
  166. }
  167. }