summaryrefslogtreecommitdiff
path: root/liba2ps/dsc.c
diff options
context:
space:
mode:
Diffstat (limited to 'liba2ps/dsc.c')
-rw-r--r--liba2ps/dsc.c358
1 files changed, 358 insertions, 0 deletions
diff --git a/liba2ps/dsc.c b/liba2ps/dsc.c
new file mode 100644
index 0000000..8338ce6
--- /dev/null
+++ b/liba2ps/dsc.c
@@ -0,0 +1,358 @@
+/* dsc.c - recording information about the PostScript resources
+ Copyright 1988-2017 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#include <config.h>
+
+#include "a2ps.h"
+#include "dsc.h"
+#include "jobs.h"
+#include "routines.h"
+#include "str_ht.h"
+
+/************************************************************************
+ * Multivalued hash tables *
+ ************************************************************************/
+typedef struct multivalued_entry {
+ char * key; /* E.g., "font", "color" */
+ struct string_htable * entries; /* E.g., "Courier", "Helvetica-Bold" */
+} multivalued_entry;
+
+static unsigned long
+mv_key_hash_1 (struct multivalued_entry *key)
+{
+ return_STRING_HASH_1 (key->key);
+}
+
+static unsigned long
+mv_key_hash_2 (struct multivalued_entry *key)
+{
+ return_STRING_HASH_2 (key->key);
+}
+
+static int
+mv_key_hash_cmp (struct multivalued_entry *x, struct multivalued_entry *y)
+{
+ return_STRING_COMPARE (x->key, y->key);
+}
+
+/*
+ * Create and return a new multivaluated_entry, with key TYPE.
+ */
+static struct multivalued_entry *
+multivalued_entry_new (const char * type)
+{
+ struct multivalued_entry * res = XMALLOC (struct multivalued_entry);
+ res->key = xstrdup (type);
+ res->entries = string_htable_new ();
+ return res;
+}
+
+/*
+ * Return the multivalued_entry related to TYPE in TABLE
+ * if there is, NULL otherwise.
+ */
+static struct multivalued_entry *
+multivalued_entry_get (struct hash_table_s * table, const char * type)
+{
+ static struct multivalued_entry token, * res;
+
+ token.key = (char *) type;
+ res = (struct multivalued_entry *) hash_find_item (table, &token);
+ return res;
+}
+
+/*
+ * Add a new multivalued_entry with TYPE, if necessary
+ */
+static void
+multivalued_entry_add (struct hash_table_s * table,
+ struct multivalued_entry * item)
+{
+ hash_insert (table, item);
+}
+
+/*
+ * In the macro table TABLE, get the sub_table having TYPE (create
+ * if necessary), and in this sub table, store a malloc'd copy of VALUE
+ */
+static void
+multivalued_entry_add_couple (hash_table * table,
+ const char * type, const char * value)
+{
+ struct multivalued_entry * sub_table;
+
+ sub_table = multivalued_entry_get (table, type);
+ if (sub_table == NULL) {
+ sub_table = multivalued_entry_new (type);
+ multivalued_entry_add (table, sub_table);
+ }
+
+ string_htable_add (sub_table->entries, value);
+}
+
+/*
+ * Return the sub hash_table corresponding to TYPE in TABLE
+ * NULL if none
+ */
+static struct string_htable *
+multivalued_entry_get_sub_table (struct hash_table_s * table,
+ const char * type)
+{
+ struct multivalued_entry * item;
+ item = multivalued_entry_get (table, type);
+ if (!item)
+ return NULL;
+ return item->entries;
+}
+
+/*
+ * Return the entries of type TYPE and value VALUE in TABLE
+ * if there is. NULL otherwise
+ */
+static const char *
+multivalued_entry_get_sub_item (struct hash_table_s * table,
+ const char * type,
+ const char * value)
+{
+ struct string_htable * sub_table;
+
+ sub_table = multivalued_entry_get_sub_table (table, type);
+ if (!sub_table)
+ return NULL;
+ return string_htable_get (sub_table, value);
+}
+
+struct hash_table_s *
+multivalued_table_new (void)
+{
+ static struct hash_table_s * res;
+
+ res = XMALLOC (hash_table);
+ hash_init (res, 8,
+ (hash_func_t) mv_key_hash_1,
+ (hash_func_t) mv_key_hash_2,
+ (hash_cmp_func_t) mv_key_hash_cmp);
+ return res;
+}
+
+/************************************************************************
+ * Multivalued hash tables *
+ ************************************************************************/
+/*
+ * Is this resource already recorded?
+ */
+int
+exist_resource (a2ps_job * job, const char * key, const char * value)
+{
+ return (multivalued_entry_get_sub_item (job->status->needed_resources,
+ key, value)
+ != NULL);
+}
+
+/*
+ * Used to record the requirements needed
+ */
+void
+add_supplied_resource (a2ps_job * job, const char * key, const char * value)
+{
+ multivalued_entry_add_couple (job->status->supplied_resources, key, value);
+}
+
+static void
+multivalued_entry_dump (FILE * stream, int first,
+ const char * fmt_first, const char * fmt_others,
+ struct multivalued_entry * entry)
+{
+ char ** values;
+ int i;
+
+ /* Get all the values in a malloc'd storage.
+ * We sort them because:
+ * 1. it looks better,
+ * 2. fewer sources of differences in regression tests */
+ values = (char **) string_htable_dump_sorted (entry->entries);
+ for (i = 0 ; values[i] ; i++) {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+ fprintf (stream, first ? fmt_first : fmt_others, entry->key, values[i]);
+#pragma GCC diagnostic pop
+ first = false;
+ }
+}
+
+/*
+ * Specify the needed resources to the PS prologue
+ */
+void
+dump_supplied_resources (FILE * stream, a2ps_job * job)
+{
+ int i;
+
+ multivalued_entry ** list;
+ list = ((multivalued_entry **)
+ hash_dump (job->status->supplied_resources, NULL, NULL));
+
+ for (i = 0 ; list [i] ; i ++)
+ /* i is used as a clue that it is the first */
+ multivalued_entry_dump (stream, i == 0,
+ "%%%%DocumentSuppliedResources: %s %s\n",
+ "%%%%+ %s %s\n",
+ list [i]);
+}
+
+/*
+ * Used to record the requirements needed
+ */
+void
+add_needed_resource (a2ps_job * job, const char * key, const char * value)
+{
+ multivalued_entry_add_couple (job->status->needed_resources, key, value);
+}
+
+/*
+ * Returned the needed resource if it is known,
+ * NULL otherwise
+ */
+static const char *
+needed_resource_get (a2ps_job * job, const char * key, const char * value)
+{
+ return multivalued_entry_get_sub_item (job->status->needed_resources,
+ key, value);
+}
+
+/*
+ * Dump the needed resources _BUT_ the colors
+ */
+void
+dump_needed_resources (FILE * stream, a2ps_job * job)
+{
+ int i;
+ int first = 1;
+
+ multivalued_entry ** list;
+ list = ((multivalued_entry **)
+ hash_dump (job->status->needed_resources, NULL, NULL));
+
+ for (i = 0 ; list [i] ; i ++)
+ {
+ /* Don't print the colors, because they have another section */
+ if (STREQ (list [i]-> key, "color")
+ /* nor files, since they are yet included */
+ || STREQ (list [i]-> key, "file"))
+ continue;
+
+ multivalued_entry_dump (stream, first,
+ "%%%%DocumentNeededResources: %s %s\n",
+ "%%%%+ %s %s\n",
+ list [i]);
+ first = false;
+ }
+}
+
+/*
+ * Colors used by the document
+ */
+void
+add_process_color (a2ps_job * job, const char * value)
+{
+ multivalued_entry_add_couple (job->status->needed_resources,
+ "color", value);
+}
+
+/*
+ * Dump the needed colors
+ */
+void
+dump_process_color (FILE * stream, a2ps_job * job)
+{
+ struct string_htable * color_table;
+
+ color_table = multivalued_entry_get_sub_table (job->status->needed_resources,
+ "color");
+
+ if (color_table)
+ {
+ int i;
+ char ** colors = (char **) string_htable_dump_sorted (color_table);
+
+ if (*colors != NULL) {
+ fputs ("%%DocumentProcessColors: ", stream);
+ for (i = 0 ; colors [i] ; i++)
+ fprintf (stream, "%s ", colors [i]);
+ putc ('\n', stream);
+ }
+ }
+}
+
+/************************************************************************/
+/* Handling the fonts */
+/************************************************************************/
+/*
+ * We will need this fonts.
+ * Depending whether it is part of the 13 standard fonts, consider
+ * it to be a Needed or an IncludedResource.
+ */
+void
+add_required_font (a2ps_job * job, const char * name)
+{
+ if (a2ps_printers_font_known_p (job->printers, name))
+ {
+ /* This is a regular ps fonts.
+ * `Needed' it, and `Include" it.
+ * We do it only if not yet done to avoid multiple %%Include */
+ if (!needed_resource_get (job, "font", name)) {
+ add_needed_resource (job, "font", name);
+ output (job->divertion, "%%%%IncludeResource: font %s\n", name);
+ }
+ } else {
+ /* This is not a known font.
+ * `Supplie' it, and include it */
+ add_supplied_resource (job, "font", name);
+ }
+}
+
+/*
+ * Return a malloc'd char ** in which are stored
+ * the required_fonts (if there are, NULL otherwise)
+ */
+char **
+required_fonts_get (a2ps_job * job)
+{
+ struct string_htable * font_table;
+ font_table =
+ multivalued_entry_get_sub_table (job->status->supplied_resources,
+ "font");
+
+ if (font_table)
+ return (char **) string_htable_dump_sorted (font_table);
+ return NULL;
+}
+
+/*
+ * Dump the setup code read in the various prologue (.pro and .ps)
+ * files. The hard part is that we don't want to dump too
+ * many definitions of fonts, to avoid running out of memory on
+ * too old PS level 1 printers.
+ * Nevertheless, I still wait for somebody to tell me if this is
+ * really needed (useful is sure, needed is not)
+ */
+void
+dump_setup (FILE * stream, a2ps_job * job)
+{
+ output_dump (job->status->setup, stream);
+}