summaryrefslogtreecommitdiff
path: root/libnautilus-extensions/nautilus-font-manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnautilus-extensions/nautilus-font-manager.c')
-rw-r--r--libnautilus-extensions/nautilus-font-manager.c996
1 files changed, 996 insertions, 0 deletions
diff --git a/libnautilus-extensions/nautilus-font-manager.c b/libnautilus-extensions/nautilus-font-manager.c
new file mode 100644
index 000000000..331f58190
--- /dev/null
+++ b/libnautilus-extensions/nautilus-font-manager.c
@@ -0,0 +1,996 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/* nautilus-font-manager.c - Functions for managing fonts.
+
+ Copyright (C) 2000 Eazel, Inc.
+
+ The Gnome Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Authors: Ramiro Estrugo <ramiro@eazel.com>
+*/
+
+#include <config.h>
+#include "nautilus-font-manager.h"
+#include "nautilus-string.h"
+#include "nautilus-string-list.h"
+#include "nautilus-lib-self-check-functions.h"
+#include "nautilus-file-utilities.h"
+
+#include <libgnome/gnome-util.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <libgnomevfs/gnome-vfs.h>
+
+#define XLFD_INDEX_FOUNDRY 1
+#define XLFD_INDEX_FAMILY 2
+#define XLFD_INDEX_WEIGHT 3
+#define XLFD_INDEX_SLANT 4
+#define XLFD_INDEX_SET_WIDTH 5
+#define XLFD_INDEX_CHAR_SET_REGISTRY 13
+#define XLFD_INDEX_CHAR_SET_ENCODING 14
+#define XLFD_INDEX_MAX XLFD_INDEX_CHAR_SET_ENCODING
+
+#define FONTS_DIR_FILE_NAME "fonts.dir"
+#define FONTS_ALIAS_FILE_NAME "fonts.alias"
+#define FONTS_SCALE_FILE_NAME "fonts.scale"
+
+typedef struct {
+ char *file_name;
+ char *foundry;
+ char *family;
+ char *weight;
+ char *slant;
+ char *set_width;
+ char *char_set_registry;
+ char *char_set_encoding;
+} FontDescription;
+
+typedef struct {
+ char *directory;
+ char *fonts_dir_file;
+ char *fonts_alias_file;
+ char *fonts_scale_file;
+ GList *descriptions;
+ GList *postscript_font_list;
+ GList *true_type_font_list;
+} FontDescriptionTable;
+
+static gboolean string_is_valid (const char *string);
+static char * file_as_string (const char *file_name);
+static gboolean directory_contains_file (const char *directory,
+ const char *file_name);
+static FontDescription * font_description_new (const char *font_file_name,
+ const char *xlfd_string);
+static void font_description_free (FontDescription *description);
+static void font_description_table_for_each (const FontDescriptionTable *description_table,
+ NautilusFontManagerIterationCallback callback,
+ gpointer callback_data);
+static char *font_description_get_file_name (const FontDescription *description);
+static char *font_description_get_foundry (const FontDescription *description);
+static char *font_description_get_family (const FontDescription *description);
+static char *font_description_get_weight (const FontDescription *description);
+static char *font_description_get_slant (const FontDescription *description);
+static char *font_description_get_set_width (const FontDescription *description);
+static char *font_description_get_char_set_registry (const FontDescription *description);
+static char *font_description_get_char_set_encoding (const FontDescription *description);
+static FontDescriptionTable * font_description_table_new (const char *font_directory);
+static void font_description_table_install_font_lists (FontDescriptionTable *table,
+ GList *postscript_font_list,
+ GList *true_type_font_list);
+static void font_description_table_add (FontDescriptionTable *description_table,
+ const char *line);
+static guint font_description_table_get_length (const FontDescriptionTable *description_table);
+static const FontDescription * font_description_table_peek_nth (const FontDescriptionTable *description_table,
+ guint n);
+static char * font_description_table_get_nth_file_name (const FontDescriptionTable *description_table,
+ guint n);
+static void font_description_table_free (FontDescriptionTable *table);
+static void font_description_table_clear (FontDescriptionTable *table);
+
+static gboolean
+string_is_valid (const char *string)
+{
+ return string && string[0] != '\0';
+}
+
+static char *
+file_as_string (const char *file_name)
+{
+ struct stat stat_info;
+ FILE *stream;
+ char *result;
+ size_t num_read;
+
+ g_return_val_if_fail (file_name != NULL, NULL);
+ g_return_val_if_fail (g_file_exists (file_name), NULL);
+
+ if (stat (file_name, &stat_info) != 0) {
+ return NULL;
+ }
+
+ if (stat_info.st_size == 0) {
+ return NULL;
+ }
+
+ stream = fopen (file_name, "r");
+
+ if (!stream) {
+ return NULL;
+ }
+
+ result = g_malloc (sizeof (char) * stat_info.st_size + 1);
+
+ num_read = fread (result, sizeof (char), stat_info.st_size, stream);
+
+ fclose (stream);
+
+ if ((ssize_t)num_read != stat_info.st_size) {
+ g_free (result);
+ return NULL;
+ }
+
+ result[stat_info.st_size] = '\0';
+
+ return result;
+}
+
+static FontDescription *
+font_description_new (const char *font_file_name,
+ const char *xlfd_string)
+{
+ FontDescription *font_description = NULL;
+ NautilusStringList *tokenized_xlfd;
+
+ g_return_val_if_fail (string_is_valid (font_file_name), NULL);
+ g_return_val_if_fail (string_is_valid (xlfd_string), NULL);
+
+ tokenized_xlfd = nautilus_string_list_new_from_tokens (xlfd_string, "-", FALSE);
+
+ if (nautilus_string_list_get_length (tokenized_xlfd) == (XLFD_INDEX_MAX + 1)) {
+ font_description = g_new0 (FontDescription, 1);
+ font_description->file_name = g_strdup (font_file_name);
+ font_description->foundry = nautilus_string_list_nth (tokenized_xlfd, XLFD_INDEX_FOUNDRY);
+ font_description->family = nautilus_string_list_nth (tokenized_xlfd, XLFD_INDEX_FAMILY);
+ font_description->weight = nautilus_string_list_nth (tokenized_xlfd, XLFD_INDEX_WEIGHT);
+ font_description->slant = nautilus_string_list_nth (tokenized_xlfd, XLFD_INDEX_SLANT);
+ font_description->set_width = nautilus_string_list_nth (tokenized_xlfd, XLFD_INDEX_SET_WIDTH);
+ font_description->char_set_registry = nautilus_string_list_nth (tokenized_xlfd, XLFD_INDEX_CHAR_SET_REGISTRY);
+ font_description->char_set_encoding = nautilus_string_list_nth (tokenized_xlfd, XLFD_INDEX_CHAR_SET_ENCODING);
+ } else {
+ g_warning ("'%s' is not a valid XLFD string", xlfd_string);
+ }
+
+ nautilus_string_list_free (tokenized_xlfd);
+
+ return font_description;
+}
+
+static void
+font_description_free (FontDescription *font_description)
+{
+ g_return_if_fail (font_description != NULL);
+
+ g_free (font_description->file_name);
+ g_free (font_description->foundry);
+ g_free (font_description->family);
+ g_free (font_description->weight);
+ g_free (font_description->slant);
+ g_free (font_description->set_width);
+ g_free (font_description->char_set_registry);
+ g_free (font_description->char_set_encoding);
+ g_free (font_description);
+}
+
+static char *
+font_description_get_file_name (const FontDescription *description)
+{
+ g_return_val_if_fail (description != NULL, NULL);
+
+ return g_strdup (description->file_name);
+}
+
+static char *
+font_description_get_foundry (const FontDescription *description)
+{
+ g_return_val_if_fail (description != NULL, NULL);
+
+ return g_strdup (description->foundry);
+}
+
+static char *
+font_description_get_family (const FontDescription *description)
+{
+ g_return_val_if_fail (description != NULL, NULL);
+
+ return g_strdup (description->family);
+}
+
+static char *
+font_description_get_weight (const FontDescription *description)
+{
+ g_return_val_if_fail (description != NULL, NULL);
+
+ return g_strdup (description->weight);
+}
+
+static char *
+font_description_get_slant (const FontDescription *description)
+{
+ g_return_val_if_fail (description != NULL, NULL);
+
+ return g_strdup (description->slant);
+}
+
+static char *
+font_description_get_set_width (const FontDescription *description)
+{
+ g_return_val_if_fail (description != NULL, NULL);
+
+ return g_strdup (description->set_width);
+}
+
+static char *
+font_description_get_char_set_registry (const FontDescription *description)
+{
+ g_return_val_if_fail (description != NULL, NULL);
+
+ return g_strdup (description->char_set_registry);
+}
+
+static char *
+font_description_get_char_set_encoding (const FontDescription *description)
+{
+ g_return_val_if_fail (description != NULL, NULL);
+
+ return g_strdup (description->char_set_encoding);
+}
+
+static void
+font_description_table_add (FontDescriptionTable *description_table,
+ const char *line)
+{
+ char *font_file_name = NULL;
+ FontDescription *description;
+ char *xlfd_delimeter;
+
+ g_return_if_fail (description_table != NULL);
+ g_return_if_fail (string_is_valid (line));
+
+ xlfd_delimeter = strstr (line, " ");
+
+ if (xlfd_delimeter == NULL) {
+ g_warning ("'%s' is not a valid font description line", line);
+ return;
+ }
+
+ font_file_name = g_strndup (line, xlfd_delimeter - line);
+
+ while (isspace ((guchar) *xlfd_delimeter)) {
+ xlfd_delimeter++;
+ }
+
+ description = font_description_new (font_file_name, xlfd_delimeter);
+
+ if (description != NULL) {
+ description_table->descriptions = g_list_append (description_table->descriptions,
+ description);
+ }
+
+ g_free (font_file_name);
+}
+
+static guint
+font_description_table_get_length (const FontDescriptionTable *description_table)
+{
+ g_return_val_if_fail (description_table != NULL, 0);
+
+ return g_list_length (description_table->descriptions);
+}
+
+static const FontDescription *
+font_description_table_peek_nth (const FontDescriptionTable *description_table,
+ guint n)
+{
+ g_return_val_if_fail (description_table != NULL, NULL);
+ g_return_val_if_fail (n < font_description_table_get_length (description_table), NULL);
+
+ return g_list_nth_data (description_table->descriptions, n);
+}
+
+static char *
+font_description_table_get_nth_file_name (const FontDescriptionTable *description_table,
+ guint n)
+{
+ const FontDescription *description;
+
+ g_return_val_if_fail (description_table != NULL, NULL);
+ g_return_val_if_fail (n < font_description_table_get_length (description_table), NULL);
+
+ description = font_description_table_peek_nth (description_table, n);
+
+ return g_strdup (description->file_name);
+}
+
+static void
+font_description_table_free (FontDescriptionTable *table)
+{
+ g_return_if_fail (table != NULL);
+
+ font_description_table_clear (table);
+ g_free (table);
+}
+
+static void
+font_description_table_clear (FontDescriptionTable *table)
+{
+ GList *node;
+
+ g_return_if_fail (table != NULL);
+
+ node = table->descriptions;
+ while (node != NULL) {
+ font_description_free (node->data);
+ node = node->next;
+ }
+
+ g_list_free (table->descriptions);
+ table->descriptions = NULL;
+
+ g_free (table->directory);
+ table->directory = NULL;
+
+ g_free (table->fonts_dir_file);
+ table->fonts_dir_file = NULL;
+
+ g_free (table->fonts_alias_file);
+ table->fonts_alias_file = NULL;
+
+ g_free (table->fonts_scale_file);
+ table->fonts_scale_file = NULL;
+}
+
+static void
+font_description_table_for_each (const FontDescriptionTable *description_table,
+ NautilusFontManagerIterationCallback callback,
+ gpointer callback_data)
+{
+ GList *node;
+ const FontDescription *description;
+
+ g_return_if_fail (description_table != NULL);
+ g_return_if_fail (callback != NULL);
+
+ node = description_table->descriptions;
+ while (node != NULL) {
+ description = node->data;
+ g_assert (node->data != NULL);
+
+ (* callback) (description->foundry,
+ description->family,
+ description->weight,
+ description->slant,
+ description->set_width,
+ description->char_set_registry,
+ description->char_set_encoding,
+ callback_data);
+
+ node = node->next;
+ }
+}
+
+static FontDescriptionTable *
+table_new_from_contents (const char *contents)
+{
+ FontDescriptionTable *description_table;
+ NautilusStringList *tokenized_contents;
+ int i;
+ int count;
+ char *line;
+
+ g_return_val_if_fail (string_is_valid (contents), NULL);
+
+ tokenized_contents = nautilus_string_list_new_from_tokens (contents, "\n", FALSE);
+
+ /* Make sure there is at least one description. Item 0 is the count */
+ if (nautilus_string_list_get_length (tokenized_contents) <= 1) {
+ nautilus_string_list_free (tokenized_contents);
+ return NULL;
+ }
+
+ /* Find out how many font entries are described in this file */
+ if (!nautilus_string_list_nth_as_integer (tokenized_contents, 0, &count)) {
+ nautilus_string_list_free (tokenized_contents);
+ return NULL;
+ }
+
+ description_table = g_new0 (FontDescriptionTable, 1);
+
+ for (i = 0; i < count; i++) {
+ line = nautilus_string_list_nth (tokenized_contents, i + 1);
+
+ if (line != NULL) {
+ font_description_table_add (description_table, line);
+ }
+
+ g_free (line);
+ }
+
+ nautilus_string_list_free (tokenized_contents);
+
+ return description_table;
+}
+
+static FontDescriptionTable *
+font_description_table_new (const char *font_directory)
+{
+ FontDescriptionTable *table;
+ char *description_file;
+ char *description_contents;
+
+ g_return_val_if_fail (string_is_valid (font_directory), NULL);
+ g_return_val_if_fail (g_file_test (font_directory, G_FILE_TEST_ISDIR), NULL);
+
+ description_file = nautilus_make_path (font_directory, FONTS_DIR_FILE_NAME);
+ description_contents = file_as_string (description_file);
+
+ if (description_contents == NULL) {
+ g_free (description_file);
+ return NULL;
+ }
+
+ table = table_new_from_contents (description_contents);
+
+ if (table != NULL) {
+ table->fonts_dir_file = nautilus_make_path (font_directory, FONTS_DIR_FILE_NAME);
+
+ /* Assign the alias file if found */
+ if (directory_contains_file (font_directory, FONTS_ALIAS_FILE_NAME)) {
+ table->fonts_alias_file = nautilus_make_path (font_directory, FONTS_ALIAS_FILE_NAME);
+ }
+
+ /* Assign the alias scale if found */
+ if (directory_contains_file (font_directory, FONTS_SCALE_FILE_NAME)) {
+ table->fonts_scale_file = nautilus_make_path (font_directory, FONTS_SCALE_FILE_NAME);
+ }
+ }
+
+ return table;
+}
+
+static void
+font_description_table_install_font_lists (FontDescriptionTable *table,
+ GList *postscript_font_list,
+ GList *true_type_font_list)
+{
+ g_return_if_fail (table != NULL);
+ g_return_if_fail (table->postscript_font_list == NULL);
+ g_return_if_fail (table->true_type_font_list == NULL);
+
+ table->postscript_font_list = postscript_font_list;
+ table->true_type_font_list = true_type_font_list;
+}
+
+static GnomeVFSResult
+collect_fonts_from_directory (const char *font_directory,
+ GList **postscript_font_list,
+ GList **true_type_font_list)
+{
+ GnomeVFSDirectoryHandle *directory;
+ GnomeVFSResult result;
+ GnomeVFSFileInfo *info;
+ char *directory_uri;
+
+ g_return_val_if_fail (string_is_valid (font_directory), GNOME_VFS_ERROR_BAD_PARAMETERS);
+ g_return_val_if_fail (postscript_font_list != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
+ g_return_val_if_fail (true_type_font_list != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
+
+ directory_uri = g_strconcat ("file://", font_directory, NULL);
+
+ *postscript_font_list = NULL;
+ *true_type_font_list = NULL;
+
+ result = gnome_vfs_directory_open (&directory,
+ directory_uri, GNOME_VFS_FILE_INFO_GET_MIME_TYPE, NULL);
+ g_free (directory_uri);
+
+ if (result != GNOME_VFS_OK) {
+ return result;
+ }
+
+
+ while (TRUE) {
+ info = gnome_vfs_file_info_new ();
+ result = gnome_vfs_directory_read_next (directory, info);
+ if (result == GNOME_VFS_OK) {
+ if (strcasecmp (info->mime_type, "application/x-font-type1") == 0) {
+ *postscript_font_list = g_list_prepend (*postscript_font_list,
+ g_strconcat (font_directory,
+ "/", info->name, NULL));
+ } else if (strcasecmp (info->mime_type, "application/x-font-ttf") == 0) {
+ *true_type_font_list = g_list_prepend (*true_type_font_list,
+ g_strconcat (font_directory,
+ "/", info->name, NULL));
+ }
+ }
+ gnome_vfs_file_info_unref (info);
+
+ if (result == GNOME_VFS_ERROR_EOF) {
+ break;
+ }
+ }
+
+ gnome_vfs_directory_close (directory);
+
+ return GNOME_VFS_OK;
+}
+
+
+static void
+chop_off_comments (char *line)
+{
+
+ /* Terminates a string right at the start of a comment, stripping it from the
+ * string.
+ */
+ gboolean saw_escape;
+ char *scanner;
+
+ saw_escape = FALSE;
+ for (scanner = line; *scanner != '\0'; scanner++) {
+ if (saw_escape) {
+ saw_escape = FALSE;
+ continue;
+ }
+ if (*scanner == '\\') {
+
+
+ saw_escape = TRUE;
+ continue;
+ }
+ if (*scanner == '#') {
+ *scanner = '\0';
+ break;
+ }
+ }
+}
+
+static void
+next_token (const char *buffer, int from, int *token_start, int *token_end)
+{
+ gboolean saw_escape;
+ const char *scanner;
+
+ g_assert ((int) strlen (buffer) >= from);
+
+ *token_start = -1;
+ *token_end = -1;
+
+ /* strip white space */
+ saw_escape = FALSE;
+ for (scanner = buffer + from; *scanner != '\0'; scanner++) {
+ if (saw_escape) {
+ saw_escape = FALSE;
+ continue;
+ }
+ if (*scanner == '\\') {
+ saw_escape = TRUE;
+ continue;
+ }
+ if (!isspace ((guchar) *scanner) && *scanner != '\n') {
+ *token_start = scanner - buffer;
+ break;
+ }
+ }
+
+ if (*scanner == ',') {
+ *token_end = *token_start + 1;
+ return;
+ }
+
+ /* go until token end */
+ saw_escape = FALSE;
+ for (; *scanner != '\0'; scanner++) {
+ if (saw_escape) {
+ saw_escape = FALSE;
+ continue;
+ }
+ if (*scanner == '\\') {
+ saw_escape = TRUE;
+ continue;
+ }
+ if (isspace ((guchar) *scanner) || *scanner == ',') {
+ break;
+ }
+ }
+
+ if (*token_start >= 0) {
+ *token_end = scanner - buffer;
+ }
+}
+
+#define READ_BUFFER_SIZE 2048
+
+static gboolean
+token_matches (const char *buffer, int start, int end, const char *pattern)
+{
+ if (start < 0) {
+ return FALSE;
+ }
+
+ return strncmp (buffer + start, pattern, end - start) == 0;
+}
+
+typedef enum {
+ EXPECT_CATALOGUE,
+ EXPECT_ASSIGNMENT,
+ EXPECT_DIRECTORY,
+ EXPECT_COMMA
+} FontConfigParseState;
+
+static void
+font_server_for_each_font_directory_internal (void (* callback) (const char *font_directory, gpointer callback_data),
+ gpointer callback_data,
+ char *buffer,
+ FILE *file)
+{
+ FontConfigParseState state;
+ int token_start, token_end;
+ char *font_directory;
+
+ g_return_if_fail (callback != NULL);
+ g_return_if_fail (buffer != NULL);
+ g_return_if_fail (file != NULL);
+
+ state = EXPECT_CATALOGUE;
+ while (TRUE) {
+ fgets (buffer, READ_BUFFER_SIZE, file);
+ if (strlen (buffer) == 0) {
+ if (state != EXPECT_COMMA) {
+ g_print ("unexpected file end\n");
+ }
+ break;
+ }
+
+ chop_off_comments (buffer);
+
+ token_start = 0;
+ while (TRUE) {
+ next_token (buffer, token_start, &token_start, &token_end);
+
+ if (token_start < 0) {
+ break;
+ }
+
+ switch (state) {
+ case EXPECT_CATALOGUE:
+ if (token_matches(buffer, token_start, token_end, "catalogue")) {
+ state = EXPECT_ASSIGNMENT;
+ }
+ break;
+
+ case EXPECT_ASSIGNMENT:
+ if (!token_matches(buffer, token_start, token_end, "=")) {
+ g_print (" expected token \"=\" \n");
+ return;
+ }
+ state = EXPECT_DIRECTORY;
+ break;
+
+ case EXPECT_DIRECTORY:
+ if (token_matches(buffer, token_start, token_end, ",")) {
+ g_print (" expected directory name \n");
+ return;
+ }
+ /* found a directory, call an each function on it */
+ font_directory = g_strndup (buffer + token_start, token_end - token_start);
+ (* callback) (font_directory, callback_data);
+ g_free (font_directory);
+ state = EXPECT_COMMA;
+ break;
+
+ case EXPECT_COMMA:
+ if (!token_matches(buffer, token_start, token_end, ",")) {
+ /* we are done, no more directories */
+ return;
+ }
+ state = EXPECT_DIRECTORY;
+ break;
+ }
+
+ token_start = token_end;
+ }
+ }
+}
+
+static void
+font_server_for_each_font_directory (const char *font_config_file_path,
+ void (* callback) (const char *font_directory, gpointer callback_data),
+ gpointer callback_data)
+{
+ /* scan the font config file, finding all the font directory paths */
+ FILE *font_config_file;
+ char *buffer;
+
+ g_return_if_fail (string_is_valid (font_config_file_path));
+ g_return_if_fail (callback != NULL);
+ g_return_if_fail (callback_data != NULL);
+
+ font_config_file = fopen (font_config_file_path, "r");
+
+ if (font_config_file == NULL) {
+ return;
+ }
+
+ buffer = g_malloc (READ_BUFFER_SIZE);
+ font_server_for_each_font_directory_internal (callback,
+ callback_data,
+ buffer,
+ font_config_file);
+
+ g_free (buffer);
+ fclose (font_config_file);
+}
+
+static gboolean
+directory_contains_file (const char *directory,
+ const char *file_name)
+{
+ gboolean result;
+ char *path;
+
+ g_return_val_if_fail (string_is_valid (directory), FALSE);
+ g_return_val_if_fail (string_is_valid (file_name), FALSE);
+
+ path = nautilus_make_path (directory, file_name);
+ result = g_file_exists (path);
+ g_free (path);
+
+ return result;
+}
+
+static void
+font_server_for_each_callback (const char *font_directory,
+ gpointer callback_data)
+{
+ FontDescriptionTable *table;
+
+ GList *postscript_font_list = NULL;
+ GList *true_type_font_list = NULL;
+
+ GList **collected_font_tables;
+
+ g_return_if_fail (font_directory != NULL);
+ g_return_if_fail (callback_data != NULL);
+
+ collected_font_tables = callback_data;
+
+ /* Collect postscript and true type font in this directory */
+ collect_fonts_from_directory (font_directory, &postscript_font_list, &true_type_font_list);
+
+ /* No scalable fonts found; we're done */
+ if (g_list_length (postscript_font_list) == 0
+ && g_list_length (true_type_font_list) == 0) {
+ return;
+ }
+
+ /* If no "fonts.dir" exists, then the user has a missing description file (broken setup) */
+ if (!directory_contains_file (font_directory, FONTS_DIR_FILE_NAME)) {
+ g_free (postscript_font_list);
+ g_free (true_type_font_list);
+ g_warning ("Direcotry '%s' contains scalable fonts but no '%s' description file.",
+ font_directory,
+ FONTS_DIR_FILE_NAME);
+ return;
+ }
+
+ table = font_description_table_new (font_directory);
+ g_assert (table != NULL);
+
+ font_description_table_install_font_lists (table, postscript_font_list, true_type_font_list);
+
+ *collected_font_tables = g_list_prepend (*collected_font_tables, table);
+}
+
+/* Public */
+void
+nautilus_font_manager_for_each_font (NautilusFontManagerIterationCallback callback,
+ gpointer callback_data)
+{
+ GList *collected_font_tables = NULL;
+ GList *node;
+ FontDescriptionTable *table;
+
+ g_return_if_fail (callback != NULL);
+
+ font_server_for_each_font_directory ("/etc/X11/fs/config",
+ font_server_for_each_callback,
+ &collected_font_tables);
+
+ node = collected_font_tables;
+ while (node) {
+ g_assert (node->data != NULL);
+ table = node->data;
+
+ font_description_table_for_each (table, callback, callback_data);
+ font_description_table_free (table);
+
+ node = node->next;
+ }
+
+ g_list_free (collected_font_tables);
+}
+
+
+#if !defined (NAUTILUS_OMIT_SELF_CHECK)
+
+/*
+ * The check strategy here is to create a temporary directory
+ * with a single fonts.dir inside it. We then use that to
+ * exercise the font manager.
+ */
+static const char *test_fonts_dir_content =
+"4\n"
+"n019003l.pfb -URW-Helvetica-medium-r-normal--0-0-0-0-p-0-iso8859-1\n"
+"n019004l.pfb -URW-Helvetica-bold-r-normal--0-0-0-0-p-0-iso8859-1\n"
+"n019023l.pfb -URW-Helvetica-medium-o-normal--0-0-0-0-p-0-iso8859-1\n"
+"n019024l.pfb -URW-Helvetica-bold-o-normal--0-0-0-0-p-0-iso8859-1\n"
+;
+
+static char *
+call_chop_off_comments (const char *input)
+{
+ char *test_copy;
+ test_copy = g_strdup (input);
+ chop_off_comments (test_copy);
+ return test_copy;
+}
+
+static gboolean
+write_temp_font_dot_dir_file (const char *temp_font_dir_file_name)
+{
+ FILE *stream;
+ size_t num;
+ size_t num_written;
+
+ g_return_val_if_fail (string_is_valid (temp_font_dir_file_name), FALSE);
+ g_return_val_if_fail (!g_file_exists (temp_font_dir_file_name), FALSE);
+
+ stream = fopen (temp_font_dir_file_name, "w");
+ g_return_val_if_fail (stream != NULL, FALSE);
+
+ num = strlen (test_fonts_dir_content);
+ num_written = fwrite (test_fonts_dir_content, sizeof (char), num, stream);
+ fclose (stream);
+
+ g_return_val_if_fail (num == num_written, FALSE);
+
+ return TRUE;
+}
+
+static char *
+get_unique_temp_directory (void)
+{
+ char *temp_font_directory;
+
+ temp_font_directory = nautilus_unique_temporary_file_name ();
+
+ if (temp_font_directory == NULL) {
+ return NULL;
+ }
+
+ if (g_file_test (temp_font_directory, G_FILE_TEST_ISDIR)) {
+ g_free (temp_font_directory);
+ return NULL;
+ }
+
+ mkdir (temp_font_directory, 0755);
+
+ if (!g_file_test (temp_font_directory, G_FILE_TEST_ISDIR)) {
+ g_free (temp_font_directory);
+ return NULL;
+ }
+
+ return temp_font_directory;
+}
+
+void
+nautilus_self_check_font_manager (void)
+{
+ FontDescriptionTable *table;
+ const FontDescription *description;
+
+ char *temp_font_directory;
+ char *temp_fonts_dot_dir_file;
+ char *cleanup_command;
+ gboolean temp_font_directory_ok;
+
+ temp_font_directory = get_unique_temp_directory ();
+ g_return_if_fail (string_is_valid (temp_font_directory));
+
+ temp_fonts_dot_dir_file = nautilus_make_path (temp_font_directory, FONTS_DIR_FILE_NAME);
+ temp_font_directory_ok = write_temp_font_dot_dir_file (temp_fonts_dot_dir_file);
+ g_return_if_fail (temp_font_directory_ok == TRUE);
+
+ cleanup_command = g_strdup_printf ("/bin/rm -rf %s", temp_font_directory);
+
+ table = font_description_table_new (temp_font_directory);
+
+ NAUTILUS_CHECK_INTEGER_RESULT (font_description_table_get_length (table), 4);
+ NAUTILUS_CHECK_STRING_RESULT (font_description_table_get_nth_file_name (table, 0), "n019003l.pfb");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_table_get_nth_file_name (table, 1), "n019004l.pfb");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_table_get_nth_file_name (table, 2), "n019023l.pfb");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_table_get_nth_file_name (table, 3), "n019024l.pfb");
+
+ description = font_description_table_peek_nth (table, 0);
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_file_name (description), "n019003l.pfb");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_foundry (description), "URW");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_family (description), "Helvetica");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_weight (description), "medium");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_slant (description), "r");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_set_width (description), "normal");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_char_set_encoding (description), "1");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_char_set_registry (description), "iso8859");
+
+ description = font_description_table_peek_nth (table, 1);
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_file_name (description), "n019004l.pfb");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_foundry (description), "URW");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_family (description), "Helvetica");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_weight (description), "bold");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_slant (description), "r");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_set_width (description), "normal");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_char_set_encoding (description), "1");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_char_set_registry (description), "iso8859");
+
+ description = font_description_table_peek_nth (table, 2);
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_file_name (description), "n019023l.pfb");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_foundry (description), "URW");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_family (description), "Helvetica");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_weight (description), "medium");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_slant (description), "o");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_set_width (description), "normal");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_char_set_encoding (description), "1");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_char_set_registry (description), "iso8859");
+
+ description = font_description_table_peek_nth (table, 3);
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_file_name (description), "n019024l.pfb");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_foundry (description), "URW");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_family (description), "Helvetica");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_weight (description), "bold");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_slant (description), "o");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_set_width (description), "normal");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_char_set_encoding (description), "1");
+ NAUTILUS_CHECK_STRING_RESULT (font_description_get_char_set_registry (description), "iso8859");
+
+ font_description_table_free (table);
+
+ /* chop_off_comments() */
+ NAUTILUS_CHECK_STRING_RESULT (call_chop_off_comments ("foo bar"), "foo bar");
+ NAUTILUS_CHECK_STRING_RESULT (call_chop_off_comments ("foo bar\n"), "foo bar\n");
+ NAUTILUS_CHECK_STRING_RESULT (call_chop_off_comments ("#foo bar"), "");
+ NAUTILUS_CHECK_STRING_RESULT (call_chop_off_comments ("foo bar#"), "foo bar");
+ NAUTILUS_CHECK_STRING_RESULT (call_chop_off_comments ("\\foo bar"), "\\foo bar");
+ NAUTILUS_CHECK_STRING_RESULT (call_chop_off_comments ("\\#foo bar"), "\\#foo bar");
+ NAUTILUS_CHECK_STRING_RESULT (call_chop_off_comments ("\\##foo bar"), "\\#");
+
+ system (cleanup_command);
+
+ g_free (cleanup_command);
+ g_free (temp_font_directory);
+ g_free (temp_fonts_dot_dir_file);
+}
+
+#endif /* !NAUTILUS_OMIT_SELF_CHECK */