added bookmark support.

Wed, 05 Mar 2003 01:58:36 +0000

author
eric
date
Wed, 05 Mar 2003 01:58:36 +0000
changeset 74
12bc5088172e
parent 73
6e306105c128
child 75
29d7cbc7c251

added bookmark support.

Makefile file | annotate | diff | revisions
TODO file | annotate | diff | revisions
pdf.h file | annotate | diff | revisions
pdf_bookmark.c file | annotate | diff | revisions
pdf_prim.c file | annotate | diff | revisions
pdf_prim.h file | annotate | diff | revisions
pdf_private.h file | annotate | diff | revisions
pdf_util.h file | annotate | diff | revisions
t2p.c file | annotate | diff | revisions
tumble.c file | annotate | diff | revisions
     1.1 --- a/Makefile	Wed Mar 05 01:58:31 2003 +0000
     1.2 +++ b/Makefile	Wed Mar 05 01:58:36 2003 +0000
     1.3 @@ -1,6 +1,6 @@
     1.4  # t2p: build a PDF file out of one or more TIFF Class F Group 4 files
     1.5  # Makefile
     1.6 -# $Id: Makefile,v 1.16 2003/02/22 02:02:06 eric Exp $
     1.7 +# $Id: Makefile,v 1.17 2003/03/04 17:58:36 eric Exp $
     1.8  # Copyright 2001 Eric Smith <eric@brouhaha.com>
     1.9  #
    1.10  # This program is free software; you can redistribute it and/or modify
    1.11 @@ -43,7 +43,7 @@
    1.12  TARGETS = t2p bitblt_test
    1.13  
    1.14  CSRCS = t2p.c semantics.c bitblt.c bitblt_test.c bitblt_table_gen.c \
    1.15 -	pdf.c pdf_util.c pdf_prim.c pdf_g4.c pdf_g4_table_gen.c
    1.16 +	pdf.c pdf_util.c pdf_prim.c pdf_bookmark.c pdf_g4.c pdf_g4_table_gen.c
    1.17  OSRCS = scanner.l parser.y
    1.18  HDRS = t2p.h semantics.h bitblt.h \
    1.19  	pdf.h pdf_private.h pdf_util.h pdf_prim.h
    1.20 @@ -62,7 +62,7 @@
    1.21  
    1.22  
    1.23  t2p: t2p.o scanner.o semantics.o parser.tab.o bitblt.o \
    1.24 -	pdf.o pdf_util.o pdf_prim.o pdf_g4.o
    1.25 +	pdf.o pdf_util.o pdf_prim.o pdf_bookmark.o pdf_g4.o
    1.26  
    1.27  bitblt_tables.h: bitblt_table_gen
    1.28  	./bitblt_table_gen >bitblt_tables.h
     2.1 --- a/TODO	Wed Mar 05 01:58:31 2003 +0000
     2.2 +++ b/TODO	Wed Mar 05 01:58:36 2003 +0000
     2.3 @@ -1,5 +1,5 @@
     2.4  t2p TODO list
     2.5 -$Id: TODO,v 1.9 2003/02/21 01:25:47 eric Exp $
     2.6 +$Id: TODO,v 1.10 2003/03/04 17:58:36 eric Exp $
     2.7  
     2.8  No particular order.
     2.9  
    2.10 @@ -70,6 +70,7 @@
    2.11  * proper output of real numbers - variable precision, no exponent
    2.12  
    2.13  * bookmarks (outline)
    2.14 +    * alternate destination specs (only is /Fit currently supported)
    2.15  
    2.16  * name trees, number trees
    2.17  
     3.1 --- a/pdf.h	Wed Mar 05 01:58:31 2003 +0000
     3.2 +++ b/pdf.h	Wed Mar 05 01:58:36 2003 +0000
     3.3 @@ -4,7 +4,7 @@
     3.4   *      will be compressed using ITU-T T.6 (G4) fax encoding.
     3.5   *
     3.6   * PDF routines
     3.7 - * $Id: pdf.h,v 1.4 2003/02/21 01:25:47 eric Exp $
     3.8 + * $Id: pdf.h,v 1.5 2003/03/04 17:58:36 eric Exp $
     3.9   * Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
    3.10   *
    3.11   * This program is free software; you can redistribute it and/or modify
    3.12 @@ -28,6 +28,8 @@
    3.13  
    3.14  typedef struct pdf_page *pdf_page_handle;
    3.15  
    3.16 +typedef struct pdf_bookmark *pdf_bookmark_handle;
    3.17 +
    3.18  
    3.19  void pdf_init (void);
    3.20  
    3.21 @@ -68,6 +70,11 @@
    3.22  
    3.23  void pdf_set_page_number (pdf_page_handle pdf_page, char *page_number);
    3.24  
    3.25 -void pdf_bookmark (pdf_page_handle pdf_page, int level, char *name);
    3.26 +/* Create a new bookmark, under the specified parent, or at the top
    3.27 +   level if parent is NULL. */
    3.28 +pdf_bookmark_handle pdf_new_bookmark (pdf_bookmark_handle parent,
    3.29 +				      char *title,
    3.30 +				      bool open,
    3.31 +				      pdf_page_handle pdf_page);
    3.32  
    3.33  void pdf_insert_tiff_image (pdf_page_handle pdf_page, char *filename);
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/pdf_bookmark.c	Wed Mar 05 01:58:36 2003 +0000
     4.3 @@ -0,0 +1,132 @@
     4.4 +/*
     4.5 + * t2p: Create a PDF file from the contents of one or more TIFF
     4.6 + *      bilevel image files.  The images in the resulting PDF file
     4.7 + *      will be compressed using ITU-T T.6 (G4) fax encoding.
     4.8 + *
     4.9 + * PDF routines
    4.10 + * $Id: pdf_bookmark.c,v 1.1 2003/03/04 17:58:36 eric Exp $
    4.11 + * Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
    4.12 + *
    4.13 + * This program is free software; you can redistribute it and/or modify
    4.14 + * it under the terms of the GNU General Public License version 2 as
    4.15 + * published by the Free Software Foundation.  Note that permission is
    4.16 + * not granted to redistribute this program under the terms of any
    4.17 + * other version of the General Public License.
    4.18 + *
    4.19 + * This program is distributed in the hope that it will be useful,
    4.20 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.21 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.22 + * GNU General Public License for more details.
    4.23 + *
    4.24 + * You should have received a copy of the GNU General Public License
    4.25 + * along with this program; if not, write to the Free Software
    4.26 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
    4.27 + */
    4.28 +
    4.29 +
    4.30 +#include <stdbool.h>
    4.31 +#include <stdint.h>
    4.32 +#include <stdio.h>
    4.33 +#include <stdlib.h>
    4.34 +#include <string.h>
    4.35 +
    4.36 +
    4.37 +#include "bitblt.h"
    4.38 +#include "pdf.h"
    4.39 +#include "pdf_util.h"
    4.40 +#include "pdf_prim.h"
    4.41 +#include "pdf_private.h"
    4.42 +
    4.43 +
    4.44 +static void pdf_bookmark_update_count (pdf_bookmark_handle entry)
    4.45 +{
    4.46 +  struct pdf_obj *count_obj;
    4.47 +
    4.48 +  while (entry)
    4.49 +    {
    4.50 +      count_obj = pdf_get_dict_entry (entry->dict, "Count");
    4.51 +      if (! count_obj)
    4.52 +	{
    4.53 +	  count_obj = pdf_new_integer (0);
    4.54 +	  pdf_set_dict_entry (entry->dict, "Count", count_obj);
    4.55 +	}
    4.56 +      pdf_set_integer (count_obj,
    4.57 +		       pdf_get_integer (count_obj) +
    4.58 +		       ((entry->open) ? 1 : -1));
    4.59 +      entry = entry->parent;
    4.60 +    }
    4.61 +}
    4.62 +
    4.63 +
    4.64 +/* Create a new bookmark, under the specified parent, or at the top
    4.65 +   level if parent is NULL. */
    4.66 +pdf_bookmark_handle pdf_new_bookmark (pdf_bookmark_handle parent,
    4.67 +				      char *title,
    4.68 +				      bool open,
    4.69 +				      pdf_page_handle pdf_page)
    4.70 +{
    4.71 +  pdf_file_handle pdf_file = pdf_page->pdf_file;
    4.72 +  struct pdf_bookmark *root;
    4.73 +  struct pdf_bookmark *entry;
    4.74 +
    4.75 +  struct pdf_obj *dest_array;
    4.76 +
    4.77 +  root = pdf_file->outline_root;
    4.78 +  if (! root)
    4.79 +    {
    4.80 +      root = pdf_calloc (1, sizeof (struct pdf_bookmark));
    4.81 +      root->dict = pdf_new_ind_ref (pdf_file, pdf_new_obj (PT_DICTIONARY));
    4.82 +      pdf_set_dict_entry (root->dict, "Count", pdf_new_integer (0));
    4.83 +
    4.84 +      pdf_file->outline_root = root;
    4.85 +      pdf_set_dict_entry (pdf_file->catalog, "Outlines", root->dict);
    4.86 +    }
    4.87 +
    4.88 +  entry = pdf_calloc (1, sizeof (struct pdf_bookmark));
    4.89 +  entry->dict = pdf_new_ind_ref (pdf_file, pdf_new_obj (PT_DICTIONARY));
    4.90 +  entry->open = open;
    4.91 +
    4.92 +  pdf_set_dict_entry (entry->dict, "Title", pdf_new_string (title));
    4.93 +
    4.94 +  dest_array = pdf_new_obj (PT_ARRAY);
    4.95 +  pdf_add_array_elem (dest_array, pdf_page->page_dict);
    4.96 +  pdf_add_array_elem (dest_array, pdf_new_name ("Fit"));
    4.97 +  pdf_set_dict_entry (entry->dict, "Dest", dest_array);
    4.98 +
    4.99 +  if (parent)
   4.100 +    {
   4.101 +      entry->parent = parent;
   4.102 +      entry->prev = parent->last;
   4.103 +    }
   4.104 +  else
   4.105 +    {
   4.106 +      parent = root;
   4.107 +      entry->parent = root;
   4.108 +      entry->prev = root->last;
   4.109 +    }
   4.110 +
   4.111 +  pdf_set_dict_entry (entry->dict, "Parent", parent->dict);
   4.112 +
   4.113 +  if (entry->prev)
   4.114 +    {
   4.115 +      pdf_set_dict_entry (entry->dict, "Prev", entry->prev->dict);
   4.116 +
   4.117 +      entry->prev->next = entry;
   4.118 +      pdf_set_dict_entry (entry->prev->dict, "Next", entry->dict);
   4.119 +
   4.120 +      parent->last = entry;
   4.121 +      pdf_set_dict_entry (parent->dict, "Last", entry->dict);
   4.122 +    }
   4.123 +  else
   4.124 +    {
   4.125 +      parent->first = entry;
   4.126 +      pdf_set_dict_entry (parent->dict, "First", entry->dict);
   4.127 +
   4.128 +      parent->last = entry;
   4.129 +      pdf_set_dict_entry (parent->dict, "Last", entry->dict);
   4.130 +    }
   4.131 +
   4.132 +  pdf_bookmark_update_count (parent);
   4.133 +
   4.134 +  return (entry);
   4.135 +}
     5.1 --- a/pdf_prim.c	Wed Mar 05 01:58:31 2003 +0000
     5.2 +++ b/pdf_prim.c	Wed Mar 05 01:58:36 2003 +0000
     5.3 @@ -4,7 +4,7 @@
     5.4   *      will be compressed using ITU-T T.6 (G4) fax encoding.
     5.5   *
     5.6   * PDF routines
     5.7 - * $Id: pdf_prim.c,v 1.5 2003/02/21 02:49:11 eric Exp $
     5.8 + * $Id: pdf_prim.c,v 1.6 2003/03/04 17:58:36 eric Exp $
     5.9   * Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
    5.10   *
    5.11   * This program is free software; you can redistribute it and/or modify
    5.12 @@ -102,7 +102,7 @@
    5.13      bool              boolean;
    5.14      char              *name;
    5.15      char              *string;
    5.16 -    unsigned long     integer;
    5.17 +    long              integer;
    5.18      double            real;
    5.19      struct pdf_obj    *ind_ref;
    5.20      struct pdf_dict   dict;
    5.21 @@ -233,7 +233,7 @@
    5.22  }
    5.23  
    5.24  
    5.25 -struct pdf_obj *pdf_new_integer (unsigned long val)
    5.26 +struct pdf_obj *pdf_new_integer (long val)
    5.27  {
    5.28    struct pdf_obj *obj = pdf_new_obj (PT_INTEGER);
    5.29    obj->val.integer = val;
    5.30 @@ -315,7 +315,7 @@
    5.31  }
    5.32  
    5.33  
    5.34 -unsigned long pdf_get_integer (struct pdf_obj *obj)
    5.35 +long pdf_get_integer (struct pdf_obj *obj)
    5.36  {
    5.37    if (obj->type == PT_IND_REF)
    5.38      obj = pdf_deref_ind_obj (obj);
    5.39 @@ -325,7 +325,7 @@
    5.40    return (obj->val.integer);
    5.41  }
    5.42  
    5.43 -void pdf_set_integer (struct pdf_obj *obj, unsigned long val)
    5.44 +void pdf_set_integer (struct pdf_obj *obj, long val)
    5.45  {
    5.46    if (obj->type == PT_IND_REF)
    5.47      obj = pdf_deref_ind_obj (obj);
     6.1 --- a/pdf_prim.h	Wed Mar 05 01:58:31 2003 +0000
     6.2 +++ b/pdf_prim.h	Wed Mar 05 01:58:36 2003 +0000
     6.3 @@ -4,7 +4,7 @@
     6.4   *      will be compressed using ITU-T T.6 (G4) fax encoding.
     6.5   *
     6.6   * PDF routines
     6.7 - * $Id: pdf_prim.h,v 1.4 2003/02/21 02:49:11 eric Exp $
     6.8 + * $Id: pdf_prim.h,v 1.5 2003/03/04 17:58:36 eric Exp $
     6.9   * Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
    6.10   *
    6.11   * This program is free software; you can redistribute it and/or modify
    6.12 @@ -68,7 +68,7 @@
    6.13  
    6.14  struct pdf_obj *pdf_new_string (char *str);
    6.15  
    6.16 -struct pdf_obj *pdf_new_integer (unsigned long val);
    6.17 +struct pdf_obj *pdf_new_integer (long val);
    6.18  
    6.19  struct pdf_obj *pdf_new_real (double val);
    6.20  
    6.21 @@ -80,8 +80,8 @@
    6.22  struct pdf_obj *pdf_deref_ind_obj (struct pdf_obj *ind_obj);
    6.23  
    6.24  
    6.25 -unsigned long pdf_get_integer (struct pdf_obj *obj);
    6.26 -void pdf_set_integer (struct pdf_obj *obj, unsigned long val);
    6.27 +long pdf_get_integer (struct pdf_obj *obj);
    6.28 +void pdf_set_integer (struct pdf_obj *obj, long val);
    6.29  
    6.30  
    6.31  double pdf_get_real (struct pdf_obj *obj);
     7.1 --- a/pdf_private.h	Wed Mar 05 01:58:31 2003 +0000
     7.2 +++ b/pdf_private.h	Wed Mar 05 01:58:36 2003 +0000
     7.3 @@ -4,7 +4,7 @@
     7.4   *      will be compressed using ITU-T T.6 (G4) fax encoding.
     7.5   *
     7.6   * PDF routines
     7.7 - * $Id: pdf_private.h,v 1.2 2003/02/20 04:44:17 eric Exp $
     7.8 + * $Id: pdf_private.h,v 1.3 2003/03/04 17:58:36 eric Exp $
     7.9   * Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
    7.10   *
    7.11   * This program is free software; you can redistribute it and/or modify
    7.12 @@ -45,14 +45,32 @@
    7.13  };
    7.14  
    7.15  
    7.16 +struct pdf_bookmark
    7.17 +{
    7.18 +  struct pdf_obj *dict;    /* indirect reference */
    7.19 +  bool open;
    7.20 +
    7.21 +  struct pdf_bookmark *first;
    7.22 +  struct pdf_bookmark *last;
    7.23 +
    7.24 +  /* the following fields don't appear in the root */
    7.25 +  /* title and dest are in the dictionary but don't have
    7.26 +     explicit fields in the C structure */
    7.27 +  struct pdf_bookmark *parent;
    7.28 +  struct pdf_bookmark *prev;
    7.29 +  struct pdf_bookmark *next;
    7.30 +};
    7.31 +
    7.32 +
    7.33  struct pdf_file
    7.34  {
    7.35 -  FILE             *f;
    7.36 -  struct pdf_obj   *first_ind_obj;
    7.37 -  struct pdf_obj   *last_ind_obj;
    7.38 -  long int         xref_offset;
    7.39 -  struct pdf_obj   *catalog;
    7.40 -  struct pdf_obj   *info;
    7.41 -  struct pdf_pages *root;
    7.42 -  struct pdf_obj   *trailer_dict;
    7.43 +  FILE                *f;
    7.44 +  struct pdf_obj      *first_ind_obj;
    7.45 +  struct pdf_obj      *last_ind_obj;
    7.46 +  long int             xref_offset;
    7.47 +  struct pdf_obj      *catalog;
    7.48 +  struct pdf_obj      *info;
    7.49 +  struct pdf_pages    *root;
    7.50 +  struct pdf_bookmark *outline_root;
    7.51 +  struct pdf_obj      *trailer_dict;
    7.52  };
     8.1 --- a/pdf_util.h	Wed Mar 05 01:58:31 2003 +0000
     8.2 +++ b/pdf_util.h	Wed Mar 05 01:58:36 2003 +0000
     8.3 @@ -4,7 +4,7 @@
     8.4   *      will be compressed using ITU-T T.6 (G4) fax encoding.
     8.5   *
     8.6   * PDF routines
     8.7 - * $Id: pdf_util.h,v 1.3 2003/02/21 02:49:11 eric Exp $
     8.8 + * $Id: pdf_util.h,v 1.4 2003/03/04 17:58:36 eric Exp $
     8.9   * Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
    8.10   *
    8.11   * This program is free software; you can redistribute it and/or modify
    8.12 @@ -24,14 +24,21 @@
    8.13   */
    8.14  
    8.15  
    8.16 +#include <assert.h>
    8.17 +
    8.18 +
    8.19  void pdf_fatal (char *fmt, ...);
    8.20  
    8.21  void *pdf_calloc (size_t nmemb, size_t size);
    8.22  
    8.23  char *pdf_strdup (char *s);
    8.24  
    8.25 +#if 1
    8.26 +#define pdf_assert(cond) assert(cond)
    8.27 +#else
    8.28  #define pdf_assert(cond) do \
    8.29      { \
    8.30        if (! (cond)) \
    8.31          pdf_fatal ("assert at %s(%d)\n", __FILE__, __LINE__); \
    8.32      } while (0)
    8.33 +#endif
     9.1 --- a/t2p.c	Wed Mar 05 01:58:31 2003 +0000
     9.2 +++ b/t2p.c	Wed Mar 05 01:58:36 2003 +0000
     9.3 @@ -4,7 +4,7 @@
     9.4   *      will be compressed using ITU-T T.6 (G4) fax encoding.
     9.5   *
     9.6   * Main program
     9.7 - * $Id: t2p.c,v 1.24 2003/02/21 01:25:47 eric Exp $
     9.8 + * $Id: t2p.c,v 1.25 2003/03/04 17:58:36 eric Exp $
     9.9   * Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
    9.10   *
    9.11   * This program is free software; you can redistribute it and/or modify
    9.12 @@ -88,7 +88,7 @@
    9.13    fprintf (stderr, "    -v   verbose\n");
    9.14    fprintf (stderr, "    -b fmt  create bookmarks\n");
    9.15    fprintf (stderr, "bookmark format:\n");
    9.16 -  fprintf (stderr, "    %%F  file name\n");
    9.17 +  fprintf (stderr, "    %%F  file name (sans suffix)\n");
    9.18    fprintf (stderr, "    %%p  page number\n");
    9.19  }
    9.20  
    9.21 @@ -311,7 +311,7 @@
    9.22  					  points */
    9.23  
    9.24    Rect rect;
    9.25 -  Bitmap *bitmap;
    9.26 +  Bitmap *bitmap = NULL;
    9.27  
    9.28    int row;
    9.29  
    9.30 @@ -464,6 +464,7 @@
    9.31  
    9.32    page = pdf_new_page (out->pdf, width_points, height_points);
    9.33  
    9.34 +#if 0
    9.35    pdf_write_g4_fax_image (page,
    9.36  			  0, 0,  /* x, y */
    9.37  			  width_points, height_points,
    9.38 @@ -471,21 +472,102 @@
    9.39  			  0, /* ImageMask */
    9.40  			  0, 0, 0,  /* r, g, b */
    9.41  			  0); /* BlackIs1 */
    9.42 +#endif
    9.43  
    9.44 -  free_bitmap (bitmap);
    9.45 +  while (bookmarks)
    9.46 +    {
    9.47 +      /* $$$ need to handle level here */
    9.48 +      pdf_new_bookmark (NULL, bookmarks->name, 0, page);
    9.49 +      bookmarks = bookmarks->next;
    9.50 +    }
    9.51  
    9.52    result = 1;
    9.53  
    9.54   fail:
    9.55 +  if (bitmap)
    9.56 +    free_bitmap (bitmap);
    9.57 +
    9.58    return (result);
    9.59  }
    9.60  
    9.61  
    9.62 -void main_args (char *out_fn, int inf_count, char **in_fn)
    9.63 +#define MAX_BOOKMARK_NAME_LEN 500
    9.64 +
    9.65 +
    9.66 +static int filename_length_without_suffix (char *in_fn)
    9.67 +{
    9.68 +  char *p;
    9.69 +  int len = strlen (in_fn);
    9.70 +
    9.71 +  p = strrchr (in_fn, '.');
    9.72 +  if (p && ((strcasecmp (p, ".tif") == 0) ||
    9.73 +	    (strcasecmp (p, ".tiff") == 0)))
    9.74 +    return (p - in_fn);
    9.75 +  return (len);
    9.76 +}
    9.77 +
    9.78 +
    9.79 +/* $$$ this function should ensure that it doesn't overflow the name string! */
    9.80 +static void generate_bookmark_name (char *name,
    9.81 +				    char *bookmark_fmt, 
    9.82 +				    char *in_fn,
    9.83 +				    int page)
    9.84 +{
    9.85 +  bool meta = 0;
    9.86 +  int len;
    9.87 +
    9.88 +  while (*bookmark_fmt)
    9.89 +    {
    9.90 +      if (meta)
    9.91 +	{
    9.92 +	  meta = 0;
    9.93 +	  switch (*bookmark_fmt)
    9.94 +	    {
    9.95 +	    case '%':
    9.96 +	      *(name++) = '%';
    9.97 +	      break;
    9.98 +	    case 'F':
    9.99 +	      len = filename_length_without_suffix (in_fn);
   9.100 +	      strncpy (name, in_fn, len);
   9.101 +	      name += len;
   9.102 +	      break;
   9.103 +	    case 'p':
   9.104 +	      sprintf (name, "%d", page);
   9.105 +	      name += strlen (name);
   9.106 +	      break;
   9.107 +	    default:
   9.108 +	      break;
   9.109 +	    }
   9.110 +	}
   9.111 +      else
   9.112 +	switch (*bookmark_fmt)
   9.113 +	  {
   9.114 +	  case '%':
   9.115 +	    meta = 1;
   9.116 +	    break;
   9.117 +	  default:
   9.118 +	    *(name++) = *bookmark_fmt;
   9.119 +	  }
   9.120 +      bookmark_fmt++;
   9.121 +    }
   9.122 +  *bookmark_fmt = '\0';
   9.123 +}
   9.124 +
   9.125 +
   9.126 +void main_args (char *out_fn,
   9.127 +		int inf_count,
   9.128 +		char **in_fn,
   9.129 +		char *bookmark_fmt)
   9.130  {
   9.131    int i, ip;
   9.132    input_attributes_t input_attributes;
   9.133    pdf_file_attributes_t output_attributes;
   9.134 +  bookmark_t bookmark;
   9.135 +  char bookmark_name [MAX_BOOKMARK_NAME_LEN];
   9.136 +
   9.137 +  bookmark.next = NULL;
   9.138 +  bookmark.level = 1;
   9.139 +  bookmark.name = & bookmark_name [0];
   9.140  
   9.141    memset (& input_attributes, 0, sizeof (input_attributes));
   9.142    memset (& output_attributes, 0, sizeof (output_attributes));
   9.143 @@ -499,7 +581,13 @@
   9.144        for (ip = 1;; ip++)
   9.145  	{
   9.146  	  fprintf (stderr, "processing page %d of file \"%s\"\r", ip, in_fn [i]);
   9.147 -	  if (! process_page (ip, input_attributes, NULL))
   9.148 +	  if (bookmark_fmt)
   9.149 +	    generate_bookmark_name (& bookmark_name [0],
   9.150 +				    bookmark_fmt, 
   9.151 +				    in_fn [i],
   9.152 +				    ip);
   9.153 +	  if (! process_page (ip, input_attributes,
   9.154 +			      bookmark_fmt ? & bookmark : NULL))
   9.155  	    fatal (3, "error processing page %d of input file \"%s\"\n", ip, in_fn [i]);
   9.156  	  if (last_tiff_page ())
   9.157  	    break;
   9.158 @@ -596,7 +684,7 @@
   9.159    if (spec_fn)
   9.160      main_spec (spec_fn);
   9.161    else
   9.162 -    main_args (out_fn, inf_count, in_fn);
   9.163 +    main_args (out_fn, inf_count, in_fn, bookmark_fmt);
   9.164    
   9.165    close_tiff_input_file ();
   9.166    close_pdf_output_files ();
    10.1 --- a/tumble.c	Wed Mar 05 01:58:31 2003 +0000
    10.2 +++ b/tumble.c	Wed Mar 05 01:58:36 2003 +0000
    10.3 @@ -4,7 +4,7 @@
    10.4   *      will be compressed using ITU-T T.6 (G4) fax encoding.
    10.5   *
    10.6   * Main program
    10.7 - * $Id: tumble.c,v 1.24 2003/02/21 01:25:47 eric Exp $
    10.8 + * $Id: tumble.c,v 1.25 2003/03/04 17:58:36 eric Exp $
    10.9   * Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
   10.10   *
   10.11   * This program is free software; you can redistribute it and/or modify
   10.12 @@ -88,7 +88,7 @@
   10.13    fprintf (stderr, "    -v   verbose\n");
   10.14    fprintf (stderr, "    -b fmt  create bookmarks\n");
   10.15    fprintf (stderr, "bookmark format:\n");
   10.16 -  fprintf (stderr, "    %%F  file name\n");
   10.17 +  fprintf (stderr, "    %%F  file name (sans suffix)\n");
   10.18    fprintf (stderr, "    %%p  page number\n");
   10.19  }
   10.20  
   10.21 @@ -311,7 +311,7 @@
   10.22  					  points */
   10.23  
   10.24    Rect rect;
   10.25 -  Bitmap *bitmap;
   10.26 +  Bitmap *bitmap = NULL;
   10.27  
   10.28    int row;
   10.29  
   10.30 @@ -464,6 +464,7 @@
   10.31  
   10.32    page = pdf_new_page (out->pdf, width_points, height_points);
   10.33  
   10.34 +#if 0
   10.35    pdf_write_g4_fax_image (page,
   10.36  			  0, 0,  /* x, y */
   10.37  			  width_points, height_points,
   10.38 @@ -471,21 +472,102 @@
   10.39  			  0, /* ImageMask */
   10.40  			  0, 0, 0,  /* r, g, b */
   10.41  			  0); /* BlackIs1 */
   10.42 +#endif
   10.43  
   10.44 -  free_bitmap (bitmap);
   10.45 +  while (bookmarks)
   10.46 +    {
   10.47 +      /* $$$ need to handle level here */
   10.48 +      pdf_new_bookmark (NULL, bookmarks->name, 0, page);
   10.49 +      bookmarks = bookmarks->next;
   10.50 +    }
   10.51  
   10.52    result = 1;
   10.53  
   10.54   fail:
   10.55 +  if (bitmap)
   10.56 +    free_bitmap (bitmap);
   10.57 +
   10.58    return (result);
   10.59  }
   10.60  
   10.61  
   10.62 -void main_args (char *out_fn, int inf_count, char **in_fn)
   10.63 +#define MAX_BOOKMARK_NAME_LEN 500
   10.64 +
   10.65 +
   10.66 +static int filename_length_without_suffix (char *in_fn)
   10.67 +{
   10.68 +  char *p;
   10.69 +  int len = strlen (in_fn);
   10.70 +
   10.71 +  p = strrchr (in_fn, '.');
   10.72 +  if (p && ((strcasecmp (p, ".tif") == 0) ||
   10.73 +	    (strcasecmp (p, ".tiff") == 0)))
   10.74 +    return (p - in_fn);
   10.75 +  return (len);
   10.76 +}
   10.77 +
   10.78 +
   10.79 +/* $$$ this function should ensure that it doesn't overflow the name string! */
   10.80 +static void generate_bookmark_name (char *name,
   10.81 +				    char *bookmark_fmt, 
   10.82 +				    char *in_fn,
   10.83 +				    int page)
   10.84 +{
   10.85 +  bool meta = 0;
   10.86 +  int len;
   10.87 +
   10.88 +  while (*bookmark_fmt)
   10.89 +    {
   10.90 +      if (meta)
   10.91 +	{
   10.92 +	  meta = 0;
   10.93 +	  switch (*bookmark_fmt)
   10.94 +	    {
   10.95 +	    case '%':
   10.96 +	      *(name++) = '%';
   10.97 +	      break;
   10.98 +	    case 'F':
   10.99 +	      len = filename_length_without_suffix (in_fn);
  10.100 +	      strncpy (name, in_fn, len);
  10.101 +	      name += len;
  10.102 +	      break;
  10.103 +	    case 'p':
  10.104 +	      sprintf (name, "%d", page);
  10.105 +	      name += strlen (name);
  10.106 +	      break;
  10.107 +	    default:
  10.108 +	      break;
  10.109 +	    }
  10.110 +	}
  10.111 +      else
  10.112 +	switch (*bookmark_fmt)
  10.113 +	  {
  10.114 +	  case '%':
  10.115 +	    meta = 1;
  10.116 +	    break;
  10.117 +	  default:
  10.118 +	    *(name++) = *bookmark_fmt;
  10.119 +	  }
  10.120 +      bookmark_fmt++;
  10.121 +    }
  10.122 +  *bookmark_fmt = '\0';
  10.123 +}
  10.124 +
  10.125 +
  10.126 +void main_args (char *out_fn,
  10.127 +		int inf_count,
  10.128 +		char **in_fn,
  10.129 +		char *bookmark_fmt)
  10.130  {
  10.131    int i, ip;
  10.132    input_attributes_t input_attributes;
  10.133    pdf_file_attributes_t output_attributes;
  10.134 +  bookmark_t bookmark;
  10.135 +  char bookmark_name [MAX_BOOKMARK_NAME_LEN];
  10.136 +
  10.137 +  bookmark.next = NULL;
  10.138 +  bookmark.level = 1;
  10.139 +  bookmark.name = & bookmark_name [0];
  10.140  
  10.141    memset (& input_attributes, 0, sizeof (input_attributes));
  10.142    memset (& output_attributes, 0, sizeof (output_attributes));
  10.143 @@ -499,7 +581,13 @@
  10.144        for (ip = 1;; ip++)
  10.145  	{
  10.146  	  fprintf (stderr, "processing page %d of file \"%s\"\r", ip, in_fn [i]);
  10.147 -	  if (! process_page (ip, input_attributes, NULL))
  10.148 +	  if (bookmark_fmt)
  10.149 +	    generate_bookmark_name (& bookmark_name [0],
  10.150 +				    bookmark_fmt, 
  10.151 +				    in_fn [i],
  10.152 +				    ip);
  10.153 +	  if (! process_page (ip, input_attributes,
  10.154 +			      bookmark_fmt ? & bookmark : NULL))
  10.155  	    fatal (3, "error processing page %d of input file \"%s\"\n", ip, in_fn [i]);
  10.156  	  if (last_tiff_page ())
  10.157  	    break;
  10.158 @@ -596,7 +684,7 @@
  10.159    if (spec_fn)
  10.160      main_spec (spec_fn);
  10.161    else
  10.162 -    main_args (out_fn, inf_count, in_fn);
  10.163 +    main_args (out_fn, inf_count, in_fn, bookmark_fmt);
  10.164    
  10.165    close_tiff_input_file ();
  10.166    close_pdf_output_files ();