/*
Copyright (c) 2004-2005, Dirk Krause
All rights reserved.

Redistribution and use in source and binary forms,
with or without modification, are permitted provided
that the following conditions are met:

* Redistributions of source code must retain the above
  copyright notice, this list of conditions and the
  following disclaimer.
* Redistributions in binary form must reproduce the above 
  opyright notice, this list of conditions and the following
  disclaimer in the documentation and/or other materials
  provided with the distribution.
* Neither the name of the Dirk Krause nor the names of
  its contributors may be used to endorse or promote
  products derived from this software without specific
  prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/

/* {{{ include files */

#define DKFIGCO_C 1
#include "dkfig.h"


#line 43 "dkfigco.ctr"


/* }}} include files */



/* {{{ static variables */


/* {{{ configuration related */

#ifndef SYSCONFDIR
#if DK_HAVE_FEATURE_BACKSLASH
#define SYSCONFDIR "\\etc"
#else
#define SYSCONFDIR "/etc"
#endif
#endif

static char default_config_filename[] = { SYSCONFDIR "/fig2vect.cfg" };
static char short_config_filename[] = { "fig2vect.cfg" };

/* }}} configuration related */

/* file open modes {{{ */
static char str_r[] = { "r" };
/* }}} */



/* {{{ keys to retrieve and save preferences */

static char pk_language[] = { "/output-language" };
static char pk_make[]     = { "/make" };
static char pk_linelgt[]  = { "/line-length" };
static char pk_utf8[]	  = { "/utf-8" };
static char pv_empty[]	  = { "" };
static char pv_auto[]	  = { "auto" };
static char pv_true[]	  = { "true" };
static char pv_false[]	  = { "false" };
static char pk_shdir[]	  = { "/dir/shared" };
static char str_uc2l[]	  = { "/uc2lat-t" };

/* }}} keys to retrieve and save preferences */



/* {{{ suffixes for different output file types */

static char *output_suffixes[] = {
  ".mp",
  ".eps",
  ".svg",
  ".tex",
  ".bb",
  ".pdf",
  ".ps"
};			/* }}} */


/* {{{ keywords for long options */

static char *longopt_keywords[] = {
  /*  0 */ "v$ersion",
  /*  1 */ "h$elp",
  /*  2 */ "c$onfigure",
  /*  3 */ "u$nconfigure",
  /*  4 */ "sh$ow-configuration",
  /*  5 */ "m$ake",
  /*  6 */ "o$ption",
  /*  7 */ "l$anguage",
  /*  8 */ "r$eset",
  /*  9 */ "si$lently",
  NULL
};

/* }}} keywords for long options */

/* {{{ case insensitive file names */

static int have_fncaseins =
#if DK_HAVE_FNCASEINS
1
#else
0
#endif
;

/* }}} case insensitive file names */



/* {{{ key/value pairs to create the message array */

static dk_key_value_t kv[] = {
  /*  0 */
  {
  (char *)"/m/01",
  (char *)"on" 
  },
  /*  1 */
  {
  (char *)"/m/02", 
  (char *)"off" 
  },
  /*  2 */
  {
  (char *)"/m/03", 
  (char *)"behave like make when running on directories" 
  },
  /*  3 */
  {
  (char *)"/m/04", 
  (char *)"output language" 
  },
  /*  4 */
  {
  (char *)"/m/05", 
  (char *)"<undefined>" 
  },
  /*  5 */
  { 
  (char *)"/m/06", 
  (char *)"Current configuration:" 
  },
  /*  6 */
  { 
  (char *)"/m/07", 
  (char *)"No gzip decompression available." 
  },
  /*  7 */
  { 
  (char *)"/m/08", 
  (char *)"No bzip2 decompression available." 
  },
  /*  8 */
  { 
  (char *)"/m/09", 
  (char *)"Failed to save configuration!" 
  },
  /*  9 */
  { 
  (char *)"/m/10", 
  (char *)"Configuration file: " 
  },
  /* 10 */
  { 
  (char *)"/m/11", 
  (char *)"." 
  },
  /* 11 */
  { 
  (char *)"/m/12", 
  (char *)"Not enough memory!" 
  },
  /* 12 */
  { 
  (char *)"/m/13", 
  (char *)"Syntax error!" 
  },
  /* 13 */
  { 
  (char *)"/m/14", 
  (char *)"Mathematical error!" 
  },
  /* 14 */
  { 
  (char *)"/m/15", 
  (char *)"Unknown base driver: " 
  },
  /* 15 */
  { 
  (char *)"/m/16", 
  (char *)"!"
  },
  /* 16 */
  { 
  (char *)"/m/17", 
  (char *)"Reading input file \"" 
  },
  /* 17 */
  { 
  (char *)"/m/18", 
  (char *)"\"." 
  },
  /* 18 */
  { 
  (char *)"/m/19", 
  (char *)"The input file was read successfully." 
  },
  /* 19 */
  { 
  (char *)"/m/20", 
  (char *)"Error while reading input file." 
  },
  /* 20 */
  { 
  (char *)"/m/21", 
  (char *)"Writing output file \"" 
  },
  /* 21 */
  { 
  (char *)"/m/22", 
  (char *)"\"." 
  },
  /* 22 */
  { 
  (char *)"/m/23", 
  (char *)"Output file finished." 
  },
  /* 23 */
  { 
  (char *)"/m/24", 
  (char *)"Failed to open stream for standard input!" 
  },
  /* 24 */
  { 
  (char *)"/m/25", 
  (char *)"Failed to open stream for standard output!" 
  },
  /* 25 */
  { 
  (char *)"/m/26", 
  (char *)"Base driver name \"" 
  },
  /* 26 */
  { 
  (char *)"/m/27", 
  (char *)"\" unknown!"
  },
  /* 27 */
  { 
  (char *)"/m/28", 
  (char *)"Missing base driver name!" 
  },
  /* 28 */
  { 
  (char *)"/m/29", 
  (char *)"Skipping \"" 
  },
  /* 29 */
  { 
  (char *)"/m/30", 
  (char *)"\"." 
  },
  /* 30 */
  { 
  (char *)"/m/31", 
  (char *)"Output file name \"" 
  },
  /* 31 */
  { 
  (char *)"/m/32", 
  (char *)"\" too long!" 
  },
  /* 32 */
  { 
  (char *)"/m/33", 
  (char *)"Invalid text handling \"" 
  },
  /* 33 */
  { 
  (char *)"/m/34", 
  (char *)"\"!" 
  },
  /* 34 */
  { 
  (char *)"/m/35", 
  (char *)"Invalid font chooser \"" 
  },
  /* 35 */
  { 
  (char *)"/m/36", 
  (char *)"\"!" 
  },
  /* 36 */
  { 
  (char *)"/m/37", 
  (char *)"Invalid size keyword \"" 
  },
  /* 37 */
  { 
  (char *)"/m/38", 
  (char *)"\"!" 
  },
  /* 38 */
  { 
  (char *)"/m/39", 
  (char *)"Invalid mbox specification!"
  },
  /* 39 */
  { 
  (char *)"/m/40", 
  (char *)"Invalid keyword \"" 
  },
  /* 40 */
  { 
  (char *)"/m/41", 
  (char *)"\" in text handling!" 
  },
  /* 41 */
  { 
  (char *)"/m/42", 
  (char *)"Option \"" 
  },
  /* 42 */
  { 
  (char *)"/m/43", 
  (char *)"\" too long!" 
  },
  /* 43 */
  { 
  (char *)"/m/44", 
  (char *)"Too many points!" 
  },
  /* 44 */
  { 
  (char *)"/m/45", 
  (char *)"Internal setup error!" 
  },
  /* 45 */
  { 
  (char *)"/m/46", 
  (char *)"Preamble file \"" 
  },
  /* 46 */
  { 
  (char *)"/m/47", 
  (char *)"\" not found!" 
  },
  /* 47 */
  { 
  (char *)"/m/48", 
  (char *)"Preamble file name \"" 
  },
  /* 48 */
  { 
  (char *)"/m/49", 
  (char *)"\" too long!" 
  },
  /* 49 */
  { 
  (char *)"/m/50", 
  (char *)"Failed to insert preamble file \"" 
  },
  /* 50 */
  { 
  (char *)"/m/51", 
  (char *)"\"!" 
  },
  /* 51 */
  { 
  (char *)"/m/52", 
  (char *)"Forward arrowhead removed." 
  },
  /* 52 */
  { 
  (char *)"/m/53", 
  (char *)"Backward arrowhead removed." 
  },
  /* 53 */
  { 
  (char *)"/m/54", 
  (char *)"Skipping included image." 
  },
  /* 54 */
  { 
  (char *)"/m/55", 
  (char *)"Start of new output figure." 
  },
  /* 55 */
  { 
  (char *)"/m/56", 
  (char *)"Gathering font information." 
  },
  /* 56 */
  { 
  (char *)"/m/57", 
  (char *)"Starting output." 
  },
  /* 57 */
  { 
  (char *)"/m/58", 
  (char *)"Output finished." 
  },
  /* 58 */
  { 
  (char *)"/m/59", 
  (char *)"Very long line, possibly truncated."
  },
  /* 59 */
  { 
  (char *)"/m/60", 
  (char *)"Failed to create stream for output file!" 
  },
  /* 60 */
  { 
  (char *)"/m/61", 
  (char *)"Error while executing \"" 
  },
  /* 61 */
  { 
  (char *)"/m/62", 
  (char *)"\"!" 
  },
  /* 62 */
  { 
  (char *)"/m/63", 
  (char *)"Processing included image \"" 
  },
  /* 63 */
  { 
  (char *)"/m/64", 
  (char *)"\"." 
  },
  /* 64 */
  { 
  (char *)"/m/65", 
  (char *)"Image finished." 
  },
  /* 65 */
  { 
  (char *)"/m/66", 
  (char *)"Bitmap-to-EPS conversion failed for \"" 
  },
  /* 66 */
  { 
  (char *)"/m/67", 
  (char *)"Unknown or unsupported file type!" 
  },
  /* 67 */
  { 
  (char *)"/m/68", 
  (char *)"Failed to create temporary file name!" 
  },
  /* 68 */
  { 
  (char *)"/m/69", 
  (char *)"NetPBM format not supported!" 
  },
  /* 69 */
  { 
  (char *)"/m/70", 
  (char *)"JPEG format not supported!" 
  },
  /* 70 */
  { 
  (char *)"/m/71", 
  (char *)"PNG format not supported!" 
  },
  /* 71 */
  { 
  (char *)"/m/72", 
  (char *)"Problem while reading image file!"
  },
  /* 72 */
  { 
  (char *)"/m/73", 
  (char *)"Failed to create output streams!" 
  },
  /* 73 */
  { 
  (char *)"/m/74", 
  (char *)"Failed to initialize encoded chunk!" 
  },
  /* 74 */
  { 
  (char *)"/m/75", 
  (char *)"Failed to finish encoded chunk!" 
  },
  /* 75 */
  { 
  (char *)"/m/76", 
  (char *)"Error while writing encoded data!" 
  },
  /* 76 */
  { 
  (char *)"/m/77", 
  (char *)"Failed to create JPEG decompressor!" 
  },
  /* 77 */
  { 
  (char *)"/m/78", 
  (char *)"Failed to assign file to JPEG decompressor!" 
  },
  /* 78 */
  { 
  (char *)"/m/79", 
  (char *)"Failed to read JPEG header from file!" 
  },
  /* 79 */
  { 
  (char *)"/m/80", 
  (char *)"Failed to start JPEG decompression!" 
  },
  /* 80 */
  { 
  (char *)"/m/81", 
  (char *)"Error while reading JPEG file!" 
  },
  /* 81 */
  {
  (char *)"/m/82", 
  (char *)"Failed to allocate memory for image! (Not enough RAM/swap space)"
  },
  /* 82 */
  { 
  (char *)"/m/83", 
  (char *)"Failed to create PNG read structure!" 
  },
  /* 83 */
  { 
  (char *)"/m/84", 
  (char *)"Failed to create PNG info structure!"
  },
  /* 84 */
  { 
  (char *)"/m/85", 
  (char *)"Missing bounding box for \"" 
  },
  /* 85 */
  { 
  (char *)"/m/86", 
  (char *)"Driver does not support special text!" 
  },
  /* 86 */
  { 
  (char *)"/m/87", 
  (char *)"Unknown key in special comment \"" 
  },
  /* 87 */
  { 
  (char *)"/m/88", 
  (char *)"Special comment unused by this driver \""
  },
  /* 88 */
  { 
  (char *)"/m/89", 
  (char *)"Option not configurable by special comments \"" 
  },
  /* 89 */
  { 
  (char *)"/m/90", 
  (char *)"Error while processing special comment \"" 
  },
  /* 90 */
  { 
  (char *)"/m/91", 
  (char *)"Unused command line option \""
  },
  /* 91 */
  { 
  (char *)"/m/92", 
  (char *)"Unused configuration file option \"" 
  },
  /* 92 */
  { 
  (char *)"/m/93", 
  (char *)"\"!"
  },
  /* 93 */
  { 
  (char *)"/m/94", 
  (char *)"Redefinition of \""
  },
  /* 94 */
  { 
  (char *)"/m/95", 
  (char *)"JS libraries must be specfied at document level!" 
  },
  /* 95 */
  { 
  (char *)"/m/96", 
  (char *)"Failed to obtain image dimensions for \""
  },
  /* 96 */
  { 
  (char *)"/m/97", 
  (char *)"Error while reading PNG file \"" 
  },
  /* 97 */
  { 
  (char *)"/m/98", 
  (char *)"\"!"
  },
  /* 98 */
  { 
  (char *)"/m/99", 
  (char *)"Gathering font, pattern and image information." 
  },
  /* 99 */
  { 
  (char *)"/m/100", 
  (char *)"Starting PDF output."
  },
  /* 100 */
  { 
  (char *)"/m/101", 
  (char *)"Creating graphics stream." 
  },
  /* 101 */
  { 
  (char *)"/m/102", 
  (char *)"Writing font objects." 
  },
  /* 102 */
  { 
  (char *)"/m/103", 
  (char *)"Writing pattern objects." 
  },
  /* 103 */
  { 
  (char *)"/m/104", 
  (char *)"Writing image objects." 
  },
  /* 104 */
  { 
  (char *)"/m/105", 
  (char *)"Unknown object type in FIG file!"
  },
  /* 105 */
  { 
  (char *)"/m/106", 
  (char *)"Too few bytes in file!"
  },
  /* 106 */
  { 
  (char *)"/m/107", 
  (char *)"Failed to write pattern object!"
  },
  /* 107 */
  { 
  (char *)"/m/108", 
  (char *)"Failed to write image data for \""
  },
  /* 108 */
  { 
  (char *)"/m/109", 
  (char *)"\"!"
  },
  /* 109 */
  { 
  (char *)"/m/110", 
  (char *)"Font number out of range!"
  },
  /* 110 */
  { 
  (char *)"/m/111", 
  (char *)"This driver can only handle left-aligned text!"
  },
  /* 111 */
  { 
  (char *)"/m/112", 
  (char *)"File type of included image is not supported!" 
  },
  /* 112 */
  { 
  (char *)"/m/113", 
  (char *)"Bitmap-to-PDF conversion failed for \"" 
  },
  /* 113 */
  { 
  (char *)"/m/114", 
  (char *)"Conversion failed, errors occured!" 
  },
  /* 114 */
  { 
  (char *)"/m/115", 
  (char *)"Only PS allows the setpagedevice operator, EPS doesn't!"
  },
  /* 115 */
  { 
  (char *)"/m/116", 
  (char *)"Only PS allows the showpage operator, EPS doesn't!"
  },
  /* 116 */
  {
    (char *)"/m/117",
    (char *)"Failed to find shared directory name!"
  },
  /* 117 */
  {
    (char *)"/m/118",
    (char *)"Shared directory name too long!"
  },
  /* 118 */
  {
    (char *)"/m/119",
    (char *)"Failed to create converter from UTF-8 to LaTeX!"
  }
  ,
  /* 119 */
  {
    (char *)"/m/120",
    (char *)"Character out of range (must be 0x00 ... 0xFF)!"
  },
  /* 120 */
  {
    (char *)"/m/121",
    (char *)"Suggestion: Use combination of this driver and LaTeX driver."
  },
  /* 121 */
  {
    (char *)"/m/122",
    (char *)"Gathering infomation about fonts, images and fill patterns."
  },
  /* 122 */
  {
    (char *)"/m/123",
    (char *)"<standard output>"
  },
  /* 123 */
  {
    (char *)"/m/124",
    (char *)"Failed to load LaTeX encoding table for "
  },
  /* 124 */
  {
    (char *)"/m/125",
    (char *)"!"
  },
  /* 125 */
  {
    (char *)"/m/126",
    (char *)"Failed to find LaTeX encoding for "
  },
  /* 126 */
  {
    (char *)"/m/127",
    (char *)"!"
  },
  /* 127 */
  {
    (char *)"/m/128",
    (char *)"Writing to output file \""
  },
  /* 128 */
  {
    (char *)"/m/129",
    (char *)"\"."
  },
};
static size_t szkv = sizeof(kv)/sizeof(dk_key_value_t);

/* }}} key/value pairs to create the message array */



/* {{{ suffixes for XFig files we are willing to read */

static char *figsuffixes[] = {
  ".fig", ".fig.gz", ".fig.bz2",
  NULL
};

/* }}} suffixes for XFig files we are willing to read */



/* {{{ compression suffixes we can possibly handle */

static char *suffixes[] = {
  ".gz", ".bz2", ".svgz", NULL
};

/* }}} compression suffixes we can possibly handle */



/* {{{ suffixes for TeX and dvi file */
#if VERSION_BEFORE_2006_03_10
static char suffix_tex[] = { ".tex" };
static char suffix_dvi[] = { ".dvi" };
static char suffix_ps[]  = { ".ps" };
static char suffix_log[] = { ".log" };
#endif

/* }}} suffixes for TeX and dvi file */



/* {{{ the driver base names */

static char *base_driver_names[] = {
  /*   0 */	"mp",
  /*   1 */	"mmp",
  /*   2 */	"eps",
  /*   3 */	"svg",
  /*   4 */	"tex",
  /*   5 */	"bb",
  /*   6 */	"pdf",
  /*   7 */	"ps",
  NULL
};

/* }}} the driver base names */



/* {{{ file name standard input */

static char string_stdin[]  = { "<<<stdin>>>" };
static char string_stdout[] = { "<<<stdout>>>" };
static char string_dot[] = { "." };

/* }}} file name standard input */



/* {{{ maximum input line length */

static size_t max_line_length =
#ifdef DKFIG_MAX_LINE_LENGTH
  (size_t)(DKFIG_MAX_LINE_LENGTH)
#else
  (size_t)0
#endif
;
/* }}} */



/* {{{ builtin default options */
static unsigned long builtin_default_options1 = 
DKFIG_OPT_METAPOST_ARROWHEADS
| DKFIG_OPT_FILL_PATTERNS
| DKFIG_OPT_FILL_CONTIGOUS
| DKFIG_OPT_ALLOW_PSRL
| DKFIG_OPT_REMOVE_BITMAP_BORDER
| DKFIG_OPT_KEEP_BITMAP_WH_RATIO
| DKFIG_OPT_USE_CSS
| DKFIG_OPT_IGNORE_UNKNOWN_PAPER
| DKFIG_OPT_DP_DOT_LW
;
static unsigned long builtin_default_options2 =
DKFIG_OPT_FLIP_DIAGONAL
| DKFIG_OPT_INTERPOLATE_IMAGES
| DKFIG_OPT_SVG_FONTSIZE_UNIT
;
/* }}} */



/* }}} static variables */




/* {{{ functions */



/* {{{ cleanup_options_iterator 

  Cleanup on option storage and iterator.
  Release memory for options, storage and iterator.
  Invoked by dkfig_co_cleanup().

*/

static void
cleanup_options_iterator DK_P2(dk_storage_t *,s,dk_storage_iterator_t *,i)
{
  dk_fig_opt *o;
  
  if((s) && (i)) {
    dksto_it_reset(i);
    while((o = (dk_fig_opt *)dksto_it_next(i)) != NULL) {
      dkfig_opt_delete(o);
    }
    dksto_it_close(i);
  }
  if(s) {
    dksto_close(s);
  }
  
}
/* }}} cleanup_options_iterator */



/* {{{ dkfig_co_cleanup

  Clean up before releasing the memory.
  Invoked by dkfig_co_delete() or dkfig_co_new().

*/

void
dkfig_co_cleanup DK_P1(dk_fig_conversion *,c)
{
  char *cp;
  
  if(c) {
    c->app = NULL;
    if(c->uc2lat) {
      dkle_close(c->uc2lat); c->uc2lat = NULL;
    }
    if(c->uc2ldir) {
      cp = c->uc2ldir; dk_delete(cp);
      c->uc2ldir = NULL;
    }
    cleanup_options_iterator(c->opt, c->opti);
    c->opt = NULL; c->opti = NULL;
    cleanup_options_iterator(c->optg, c->optgi);
    c->optg = NULL; c->optgi = NULL;
    cleanup_options_iterator(c->optb, c->optbi);
    c->optb = NULL; c->optbi = NULL;
    cleanup_options_iterator(c->optd, c->optdi);
    c->optd = NULL; c->optdi = NULL;
    c->optn = c->opt1 = c->opt2 = 0UL;
    if(c->tpfn) {	
      cp = c->tpfn; dk_delete(cp);
    }
    c->tpfn = NULL;
    if(c->texn) {
      cp = c->texn; dk_delete(cp);
    }
    c->texn = NULL;
    if(c->dvin) {
      cp = c->dvin; dk_delete(cp);
    }
    c->dvin = NULL;
    if(c->psn) {
      cp = c->psn; dk_delete(cp);
    }
    c->psn = NULL;
    if(c->logn) {
      cp = c->logn; dk_delete(cp);
    }
    c->logn = NULL;
    if(c->auxn) {
      cp = c->auxn; dk_delete(cp);
    }
    c->auxn = NULL;
    if(c->fcfg) {	
      cp = c->fcfg; dk_delete(cp);
    } c->fcfg = NULL;
    if(c->cfgfn) {
      
      cp = c->cfgfn; dk_delete(cp);
    } c->cfgfn = NULL;
    if(c->drn) {
      
      cp = c->drn; dk_delete(cp);
    }
    c->drn = NULL;
    if(c->defdr) {
      
      cp = c->defdr; dk_delete(cp);
    }
    c->defdr = NULL;
    if(c->basdr) {
      cp = c->basdr; dk_delete(cp);
    }
    c->basdr = NULL;
    c->ifn1 = c->ofn1 = c->ifn2 = c->ofn2 = NULL;
    c->normal_text = c->special_text = 0;
    if(c->msg1) { char **xp; xp = c->msg1; dk_delete(xp); }
    c->msg1 = NULL;
    c->istrm = NULL; c->ostrm = NULL;
    c->bdnum = 0;
    c->svgv = 0;
    c->svgs = 0;
  }
  
}
/* }}} dkfig_co_cleanup */



/* {{{ dkfig_co_delete

  Clean up and release memory.

*/

void
dkfig_co_delete DK_P1(dk_fig_conversion *,c)
{
  
  if(c) {
    dkfig_co_cleanup(c);
    dk_delete(c);
  }
  
}
/* }}} dkfig_co_delete */



/* {{{ initialize_options_storage

  Initialize option storage and iterator.
  Invoked by dkfig_co_init().

*/

static
void
initialize_options_storage DK_P2(dk_fig_conversion *,c,int,what)
{
  dk_storage_t *mys = NULL;
  dk_storage_iterator_t *myi = NULL;
  
  if((what >= 0) && (what <= 3)) {
    mys = dksto_open(3);
    if(mys) {
      dksto_set_comp(mys, dkfig_opt_compare, 0);
      myi = dksto_it_open(mys);
      if(!(myi)) {
        if(c->app) {
	  dkapp_err_memory(c->app, sizeof(dk_storage_iterator_t), 1);  
	}
      }
    } else {
      if(c->app) {
        dkapp_err_memory(c->app, sizeof(dk_storage_t), 1);
      }
    }
    switch(what) {
      case 0: c->opt  = mys; c->opti  = myi; break;
      case 1: c->optg = mys; c->optgi = myi; break;
      case 2: c->optb = mys; c->optbi = myi; break;
      case 3: c->optd = mys; c->optdi = myi; break;
    }
  }
  
}
/* }}} initialize_options_storage */



/* {{{ set_tex_filenames

  Create temporary file names for a *.tex and a *.dvi file.

*/


static char str_conv_format[] = { "f2v_%lu.tex" };
static char str_conv_dvi[]  = { "f2v_%lu.dvi" };
static char str_conv_ps[]  = { "f2v_%lu.ps" };
static char str_conv_log[]  = { "f2v_%lu.log" };
static char str_conv_aux[]  = { "f2v_%lu.aux" };

static
int
set_tex_filenames DK_P1(dk_fig_conversion *,c)
{
/*
  As TeX produces *.dvi files in the current directory
  (there is no option to change this) we keep both
  *.tex and *.dvi in the current directory. The *.ps
  file is created here too.
*/
  int back = 0;
  unsigned long mypid = 0UL;
  char buffer[64];
  
  mypid = (unsigned long)dksf_getpid();
#if DK_HAVE_SNPRINTF
   snprintf(buffer, sizeof(buffer), str_conv_format, mypid);
   buffer[sizeof(buffer)-1] = '\0';
#else
  sprintf(buffer, str_conv_format,  mypid);
#endif
  c->texn = dkstr_dup(buffer);
#if DK_HAVE_SNPRINTF
  snprintf(buffer, sizeof(buffer), str_conv_dvi, mypid);
  buffer[sizeof(buffer)-1] = '\0';
#else
  sprintf(buffer, str_conv_dvi, mypid);
#endif
  c->dvin = dkstr_dup(buffer);
#if DK_HAVE_SNPRINTF
  snprintf(buffer, sizeof(buffer), str_conv_ps, mypid);
  buffer[sizeof(buffer)-1] = '\0';
#else
  sprintf(buffer, str_conv_ps, mypid);
#endif
  c->psn  = dkstr_dup(buffer);
#if DK_HAVE_SNPRINTF
  snprintf(buffer, sizeof(buffer), str_conv_log, mypid);
  buffer[sizeof(buffer)-1] = '\0';
#else
  sprintf(buffer, str_conv_log, mypid);
#endif
  c->logn = dkstr_dup(buffer);
#if DK_HAVE_SNPRINTF
  snprintf(buffer, sizeof(buffer), str_conv_aux, mypid);
  buffer[sizeof(buffer)-1] = '\0';
#else
  sprintf(buffer, str_conv_aux, mypid);
#endif
  c->auxn = dkstr_dup(buffer);
  if((c->texn) && (c->dvin) && (c->psn) && (c->logn) && (c->auxn)) {
    back = 1;
  }
  
  
  
  
  
  
  return back;
}
/* }}} set_tex_filenames */



/* {{{ dkfig_co_init

  Intialize a dk_fig_conversion.
  Return 0 on error (not enough memory).
  Non-zero on success.

*/

static char string_table_name[] = { "fig2vect" };

int
dkfig_co_init DK_P2(dk_fig_conversion *,c,dk_app_t *,a)
{
  int back = 0;
  char buffer[32];
  
  if(c) {
    c->app = a;
    c->opt = NULL;  c->opti = NULL;
    c->optg = NULL; c->optgi = NULL;
    c->optb = NULL; c->optbi = NULL;
    c->optd = NULL; c->optdi = NULL;
    c->optn = 0UL;
    c->opt1 = builtin_default_options1;
    c->opt2 = builtin_default_options2;
    c->uc2lat = NULL;
    c->uc2ldir = NULL;
    c->af = 0x00;
    
    if(c->app) {
      long mpl;
      mpl = dksf_get_maxpathlen();
      c->uc2ldir = dk_new(char,(size_t)mpl);
      if(c->uc2ldir) {		
        (c->uc2ldir)[0] = '\0';
        if(dkapp_get_pref(c->app, pk_shdir, c->uc2ldir, (size_t)mpl, 0)) {
	  
	  if((strlen(c->uc2ldir) + strlen(str_uc2l)) < mpl) {	
	    strcat(c->uc2ldir, str_uc2l);	
	    c->uc2lat = dkle_open(c->uc2ldir);
	    if(!(c->uc2lat)) {
	      dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 118);
	    }
	  } else {		
	    /* ERROR: Shared directory name too large */
	    dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 117);
	  }
	} else {		
	  /* ERROR: Failed to find shared directory */
	  dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 116);
	}
      } else {			
        /* ERROR: Memory */
	dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 12);
      }
    }
    c->nodcoord = 2; c->nodtrigo = 3; c->nodcolor = 3;
    c->circlesteps = 4;
    c->psl  = 0; c->dscl = 0;
    c->istrm = NULL; c->ostrm = NULL;
    c->latfs = -1;
    c->drn = c->defdr = c->basdr = NULL;
    c->ifn1 = c->ofn1 = NULL;
    c->ifn2 = c->ofn2 = NULL;
    c->normal_text = c->special_text = 0;
    c->fsf  = 1.0;
    c->msg1 = NULL;
    c->cfgfn = NULL;
    c->bdnum = -1;
    c->spseg = 8;
    c->texn  = NULL;
    c->dvin  = NULL;
    c->psn   = NULL;
    c->logn  = NULL;
    c->auxn  = NULL;
    c->tpfn  = NULL;
    c->incg  = NULL;
    c->fcfg  = NULL;
    c->patlw = 1L;
    c->patrp = 8L;
    c->ahlj  = 0;
    c->minitsteps = 8UL;
    c->maxitsteps = 2048UL;
    c->svgv  = DKFIG_SVG_VERS_11;	/* SVG 1.1 by default */
    initialize_options_storage(c,0);	/* opt  (command line) */
    initialize_options_storage(c,1);	/* optg (global options) */
    initialize_options_storage(c,2);	/* optb (base options) */
    initialize_options_storage(c,3);	/* optd (driver options) */
    c->msg1 = dkapp_find_key_value(a, kv, szkv, string_table_name);
    if((c->opt) && (c->opti) && (c->msg1) && (c->optg) && (c->optgi)
       && (c->optb) && (c->optbi) && (c->optd) && (c->optdi)
       && (c->uc2ldir) && (c->uc2lat))
    {
      back = set_tex_filenames(c);
      if(back) {
        if(c->app) {
	  int utf8configured = 0;
	  int utf8auto = 1;
          c->defdr = dkapp_get_str_pref(c->app, pk_language);
	  switch(dkapp_get_bool_pref(c->app, pk_make)) {
	    case 0: {
	      c->opt1 &= (~DKFIG_OPT_MAKE);
	    } break;
	    case 1: {
	      c->opt1 |= DKFIG_OPT_MAKE;
	    } break;
	  }
	  if(dkapp_get_pref(c->app, pk_utf8, buffer,sizeof(buffer), 0)) {
	    (void)dkfig_tool2_set_utf8(c, buffer, 1);
	  } else {
	    (void)dkfig_tool2_utf8_auto(c);
	  }
        }
      }
    }
  }
  
  return back;
}
/* }}} dkfig_co_init */



/* {{{ dkfig_co_new

  Allocate new dk_fig_conversion conversion structure
  and initialize it.

*/

dk_fig_conversion *
dkfig_co_new DK_P1(dk_app_t *,a)
{
  dk_fig_conversion *back = NULL;
  
  back = dk_new(dk_fig_conversion,1);
  if(back) {
    if(!dkfig_co_init(back, a)) {
      dkfig_co_delete(back); back = NULL;
    }
  }
  if(!back) {
    if(a) {
      dkapp_err_memory(a, sizeof(dk_fig_conversion), 1);
    }
  }
  
  return back;
}
/* }}} dk_fig_conversion */



/* {{{ check_bool_opts

  Set/reset one bit in an unsigned long depending
  on the string p retrieved from the preference
  system.
  c->opt1 = check_bool_opts(c->opt1, ptr, DKFIG_OPT_MAKE, 1);

*/

static
unsigned long
check_bool_opts DK_P4(unsigned long,a,char *,p,unsigned long,f,int,d)
{
  unsigned long back;
  int what;
  
  back = a;
  what = d;
  if(dkstr_is_bool(p)) {
    what = dkstr_is_on(p);
  }
  if(what) {
    back |= f;
  } else {
    back &= (~f);
  }
  
  return back;
}
/* }}} check_bool_opts */



/* {{{ get_base_driver

  Get base driver number.

*/

static
int
get_base_driver DK_P1(char *,n)
{
  int back = -1;
  
  if(n) {
    back = dkstr_array_index(base_driver_names, n, 1);
  }
  
  return back;
}
/* }}} get_base_driver */



/* {{{ add_opt

  Add an option.

*/

static void
add_opt DK_P4(dk_fig_conversion *,c,unsigned long,on,char *,p,int *,bck)
{
  dk_fig_opt *opt;
  
  if(c->opt) {
    opt = dkfig_opt_new(on,p);
    if(opt) {
      if(!dksto_add(c->opt, (void *)opt)) {
        dkfig_opt_delete(opt);
        *bck = ((*bck) | DKFIG_WHAT_ERROR);
	if(c->app) {
	  dkapp_err_memory(c->app, sizeof(dk_storage_node_t), 1);
	}
      }
    } else {
      *bck = ((*bck) | DKFIG_WHAT_ERROR);
      if(c->app) {
        dkapp_err_memory(c->app, sizeof(dk_fig_opt), 1);
      }
    }
  } else {
    *bck = ((*bck) | DKFIG_WHAT_ERROR);
  }
  
}
/* }}} add_opt */



/* {{{ set_driver

  Set the driver name.

*/

static void
set_driver DK_P3(dk_fig_conversion *,c,char *,drn,int *,bck)
{
  
  if(c->drn) {
    *bck = ((*bck) | DKFIG_WHAT_ERROR);
  } else {
    c->drn = dkstr_dup(drn);
    if(!(c->drn)) {
      *bck = ((*bck) | DKFIG_WHAT_ERROR);
      if(c->app) {
        dkapp_err_memory(c->app, 1, (1+strlen(drn)));
      }
    }
  }
  
}
/* }}} set_driver */



/* {{{ dkfig_co_apply_args

  Process the command line args.
  Return DKFIG_WHAT_... value indicating what to do.

*/

int
dkfig_co_apply_args DK_P3(dk_fig_conversion *,c,int,argc,char **,argv)
{
  int back = 0;
  int i, found; char *ptr, *xptr, **lfdptr;
  unsigned long onum;
  
  if(c) {
  if(argc > 0) {
  if(argv) {	
    lfdptr = argv; lfdptr++; i=1;
    found = 0; onum = 0UL;
    while(i < argc) {
      ptr = *lfdptr;
      if(*ptr == '-') {		
        ptr++;
	switch(*ptr) {
	  case '-' : {
	    
	    ptr++;
	    xptr = strchr(ptr, '=');
	    if(xptr) { *(xptr++) = '\0'; }
	    found = dkstr_array_abbr(longopt_keywords, ptr, (char)'$', 1);
	    switch(found) {
	      case 0: {		
	        back |= DKFIG_WHAT_VERSION;
	      } break;
	      case 1: {		
	        back |= DKFIG_WHAT_HELP;
	      } break;
	      case 2: {		
	        back |= DKFIG_WHAT_CONFIGURE;
	      } break;
	      case 3: {		
	        back |= DKFIG_WHAT_UNCONFIGURE;
	      } break;
	      case 4: {		
	        back |= DKFIG_WHAT_SHOWCONF;
	      } break;
	      case 5: {		
	        if(xptr) {
		  c->opt1 = check_bool_opts(c->opt1, xptr, DKFIG_OPT_MAKE, 1);
		} else {
		  c->opt1 = c->opt1 | DKFIG_OPT_MAKE;
		}
	      } break;
	      case 6: {		
	        if(xptr) {
		  add_opt(c, onum++, xptr, &back);
		} else {
		  back = DKFIG_WHAT_ERROR;
		}
	      } break;
	      case 7: {		
	        if(xptr) {
		  set_driver(c, xptr, &back);
		} else {
		  back = DKFIG_WHAT_ERROR;
		}
	      } break;
	      case 8: {		
	        c->opt1 = (c->opt1) | DKFIG_OPT_RESET | DKFIG_OPT_MAKE;
	        if(c->drn) {
	          char *mycptr;
	          mycptr = c->drn;
	          dk_delete(mycptr);
	          c->drn = NULL;
	        }
	      } break;
	      case 9: {} break;
	      default: {
	        back |= DKFIG_WHAT_ERROR;
	      } break;
	    }
	  } break;
	  case 'C' : {
	    
	    back |= DKFIG_WHAT_SHOWCONF;
	  } break;
	  case 'c' : {
	    
	    back |= DKFIG_WHAT_CONFIGURE;
	  } break;
	  case 'u' : {
	    
	    back |= DKFIG_WHAT_UNCONFIGURE;
	  } break;
	  case 'h' : {
	    
	    back |= DKFIG_WHAT_HELP;
	  } break;
	  case 'v' : {
	    
	    back |= DKFIG_WHAT_VERSION;
	  } break;
	  case 'a' : {
	    c->af = 0x01;
	  } break;
	  case 'm' : {
	    
	    ptr++;
	    if(*ptr) {
	      c->opt1 = check_bool_opts(c->opt1, ptr, DKFIG_OPT_MAKE, 1);
	    } else {
	      c->opt1 |= DKFIG_OPT_MAKE;
	    }
	    
	  } break;
	  case 'r' : {
	    c->opt1 = (c->opt1) | DKFIG_OPT_RESET | DKFIG_OPT_MAKE;
	    if(c->drn) {
	      char *mycptr;
	      mycptr = c->drn;
	      dk_delete(mycptr);
	      c->drn = NULL;
	    }
	  } break;
	  case 'l' : {
	    ptr++;
	    if(!(*ptr)) {
	      ptr = NULL;
	      lfdptr++; i++;
	      if(i < argc) {
	        ptr = *lfdptr;
	      }
	    }
	    if(ptr) {
	      set_driver(c, ptr, &back);
	    } else {
	      back |= DKFIG_WHAT_ERROR;
	    }
	  } break;
	  case 'o' : {
	    ptr++;
	    if(!(*ptr)) {
	      ptr = NULL;
	      lfdptr++; i++;
	      if(i < argc) {
	        ptr = *lfdptr;
	      }
	    }
	    if(ptr) {
	      add_opt(c, onum++, ptr, &back);
	    } else {
	      back |= DKFIG_WHAT_ERROR;
	    }
	  } break;
	  case 's' : { } break;
	  case 'i': {
	    ptr++; 
	    if(!(*ptr)) {
	      ptr = NULL;
	      lfdptr++; i++;
	      if(i < argc) {
	        ptr = *lfdptr;
	      }
	    }
	    if(ptr) {
	      c->incg = ptr;
	      
	    } else {
	      back |= DKFIG_WHAT_ERROR;
	    }
	  } break;
	  default: {
	    back |= DKFIG_WHAT_ERROR;
	  } break;
	}
      } else {			
        if(c->ifn1) {
	  if(c->ofn1) {
	    back |= DKFIG_WHAT_ERROR;
	  } else {
	    c->ofn1 = ptr;
	  }
	} else {
	  c->ifn1 = ptr;
	}
      }
      lfdptr++; i++;
    }
  }
  }
  }
  
  return back;
}
/* }}} dkfig_co_apply_args */



/* {{{ dkfig_co_showconf_app

  Show the current configuration.

*/

void
dkfig_co_showconf_app DK_P1(dk_fig_conversion *,c)
{
  char *valptr1, *valptr2;
  size_t sz1, sz2, szx, i;
  
  if(c->msg1) {
    fputs((c->msg1)[5], stdout); fputc('\n', stdout);
    valptr1 = (c->opt1 & DKFIG_OPT_MAKE) ?
              ((c->msg1)[0]) : ((c->msg1)[1]);
    valptr2 = (c->msg1)[4];
    if(c->drn) {
      valptr2 = c->drn;
    } else {
      if(!(c->opt1 & DKFIG_OPT_RESET)) {
        if(c->defdr) { valptr2 = c->defdr; }
      }
    }
    sz1 = strlen(valptr1); sz2 = strlen(valptr2);
    if(sz1 > sz2) szx = sz1;
    else          szx = sz2;
    fputs("-l   ", stdout); fputs(valptr2, stdout);
    for(i = sz2; i < szx; i++) fputc(' ', stdout);
    fputs("   ", stdout);
    fputs((c->msg1)[3], stdout); fputc('\n', stdout);
    fputs("-m   ", stdout); fputs(valptr1, stdout);
    for(i = sz1; i < szx; i++) fputc(' ', stdout);
    fputs("   ", stdout);
    fputs((c->msg1)[2], stdout); fputc('\n', stdout);
  }
  
}
/* }}} dkfig_co_showconf_app */



/* {{{ dkfig_co_configure_app

  Save the current configuration, return non-zero value
  on success.

*/

int
dkfig_co_configure_app DK_P1(dk_fig_conversion *,c)
{
  int back = 0; char *valptr;
  
  if((c->app) && (c->msg1)) {
    back = 1;
    valptr = ((c->opt1) & DKFIG_OPT_MAKE) ?
             (c->msg1)[0] : (c->msg1)[1];
    if(!dkapp_set_pref(c->app, pk_make, valptr)) {
      back = 0;
    }
    valptr = pv_empty;
    if(c->drn) {
      valptr = c->drn;
    } else {
      if((c->defdr) && (!(c->opt1 & DKFIG_OPT_RESET))) {
        valptr = c->defdr;
      }
    }
    if(!dkapp_set_pref(c->app, pk_language, valptr)) {
      back = 0;
    }
    dkfig_co_showconf_app(c);
  }
  if(!back) {
    /* ERROR: Failed to save new configuration! */
    dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 8);
  }
  
  return back;
}
/* }}} dkfig_co_configure_app */




/* {{{ establish_base_driver_name

  Find base driver name.

*/

static
void
establish_base_driver_name DK_P1(dk_fig_conversion *,c)
{
  char *cp = NULL;
  
  if(!(c->basdr)) {
    if(c->drn) {
      c->basdr = dkstr_dup(c->drn);
      if(!(c->basdr)) {
        if(c->app) {
	  dkapp_err_memory(c->app, sizeof(char), (1+strlen(c->drn)));
	}
      }
    } else {
      if(c->defdr) {
        c->basdr = dkstr_dup(c->defdr);
	if(!(c->basdr)) {
	  if(c->app) {
	    dkapp_err_memory(c->app, sizeof(char), (1+strlen(c->defdr)));
	  }
	}
      }
    }
  }
  if(c->basdr) {
    cp = dkstr_chr(c->basdr, '.');
    if(cp) {
      *cp = '\0';
    }
  }
  
}
/* }}} establish_base_driver_name */



/* {{{ add_option_line

  Process one configuration file line.

*/

static int
add_option_line DK_P4(dk_fig_conversion *,c,char *,l,unsigned long,ln,int,st)
{
  int back = 0;
  dk_storage_t *sto = NULL;
  dk_fig_opt *opt;
  
  switch(st) {
    case 0: sto = c->optg; break;
    case 1: sto = c->optb; break;
    case 2: sto = c->optd; break;
  }
  if(sto) {
    opt = dkfig_opt_new(ln,l);
    if(opt) {
      if(dksto_add(sto, (void *)opt)) {
        back = 1;
      } else {
        dkapp_err_memory(c->app, sizeof(dk_storage_node_t), 1);
      }
    } else {
      if(c->app) {
        dkapp_err_memory(c->app, sizeof(dk_fig_opt), 1);
      }
    }
  }
  
  return back;
}
/* }}} add_option_line */



/* {{{ dkfig_co_load_configuration

  Read configuration file and load contents to
  the storages.

*/


static int
dkfig_co_load_configuration DK_P1(dk_fig_conversion *,c)
{
  int back = 0;
  int state;
  char *buffer, *cp, *cp2;
  dk_stream_t *cfgstr;
  long l; size_t sz;
  unsigned long lineno;
  
  establish_base_driver_name(c);
  if(c->app) {
    c->cfgfn = dkapp_find_file_dup(c->app, short_config_filename);
  } else {
    c->cfgfn = dkstr_dup(default_config_filename);
  }
  if(c->cfgfn) {
    
    /* DEBUG: Configuration file ... is used */
    dkfig_tool2_msg3(c, DK_LOG_LEVEL_DEBUG, 9, 10, c->cfgfn);
    cp = dksf_get_file_type_dot(c->cfgfn);
    if(cp) {
      state = dkstr_array_index(suffixes, cp, have_fncaseins);
    }
    cfgstr = NULL;
    switch(state) {
      case 0: {
#if DK_HAVE_ZLIB_H
        cfgstr = dkstream_opengz(c->cfgfn, str_r, 0, NULL);
#else
	dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 6);
#endif
      } break;
      case 1: {
#if DK_HAVE_BZLIB_H
        cfgstr = dkstream_openbz2(c->cfgfn, str_r, 0, NULL);
#else
	dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 7);
#endif
      } break;
      default: {
        cfgstr = dkstream_openfile(c->cfgfn, str_r, 0, NULL);
      } break;
    }
    if(cfgstr) {
      l = 256L + dksf_get_maxpathlen();
      sz = (size_t)l;
      buffer = dk_new(char,sz);
      if(buffer) {
        back = 1;
        state = -1;
        lineno = 0UL;
        while(dkstream_gets(cfgstr, buffer, sz)) {
	  dkstr_delcomm(buffer, (char)'#');
	  lineno++;
	  cp = dkstr_start(buffer, NULL);
	  if(cp) {
	    dkstr_chomp(cp, NULL);
	    if(*cp == '[') {
	      state = -1;
	      cp2 = dkstr_rchr(cp, ']');
	      if(cp2) {
	        *cp2 = '\0';
	      }
	      cp++;
	      cp = dkstr_start(cp, NULL);
	      if(cp) {
	        dkstr_chomp(cp, NULL);
		if(strcmp(cp, "*") == 0) {
		  state = 0;
		} else {
		  if(c->drn) {
		    if(strcmp(cp, c->drn) == 0) {
		      state = 2;
		    }
		  } else {
		    if(c->defdr) {
		      if(strcmp(cp, c->defdr) == 0) {
		        state = 2;
		      }
		    }
		  }
		  if(state == -1) {
		    if(c->basdr) {
		      if(strcmp(cp, c->basdr) == 0) {
		        state = 1;
		      }
		    }
		  }
		}
	      }
	    } else {
	      switch(state) {
	        case 0: {	/* general option */
		  if(!add_option_line(c,cp,lineno,state)) { back = 0; }
		} break;
		case 1: {	/* base driver option */
		  if(!add_option_line(c,cp,lineno,state)) { back = 0; }
		} break;
		case 2: {	/* driver option */
		  if(!add_option_line(c,cp,lineno,state)) { back = 0; }
		} break;
	      }
	    }
	  }
        }
        dk_delete(buffer); buffer = NULL;
      } else {
        if(c->app) dkapp_err_memory(c->app, sizeof(char), sz);
      }
      dkstream_close(cfgstr); cfgstr = NULL;
    } else {
      if(c->app) dkapp_err_fopenr(c->app, c->cfgfn);
    }
    /* cp = c->cfgfn; dk_delete(c->cfgfn); c->cfgfn = NULL; */
  }
  
  return back;
}
/* }}} dkfig_co_load_configuration */



/* {{{ largest_of

  Find line size of largest line in storage.

*/

static
size_t
largest_of DK_P2(dk_storage_t *,sto,dk_storage_iterator_t *,it)
{
  size_t sz = 0, back = 0;
  dk_fig_opt *o;
  
  if(sto && it) {
    dksto_it_reset(it);
    while((o = (dk_fig_opt *)dksto_it_next(it)) != NULL) {
      if(o->name) {
        sz = strlen(o->name);
	if(sz > back) {
	  back = sz;
	}
      }
    }
  }
  
  return back;
}
/* }}} largest_of */



/* {{{ set_lcfge

  To process options later we need the largest
  line size to allocate a line buffer.

*/

static
void
set_lcfge DK_P1(dk_fig_conversion *,c)
{
  size_t back = 0;
  
  c->lcfge = 0;
  back = largest_of(c->opt, c->opti);
  if(back > c->lcfge) c->lcfge = back;
  back = largest_of(c->optg, c->optgi);
  if(back > c->lcfge) c->lcfge = back;
  back = largest_of(c->optb, c->optbi);
  if(back > c->lcfge) c->lcfge = back;
  back = largest_of(c->optd, c->optdi);
  if(back > c->lcfge) c->lcfge = back;
  
}
/* }}} set_lcfge */



/* {{{ dkfig_co_add_stream

  Input stream is open, now read line by line
  and add the lines to the drawing.

*/

int
dkfig_co_add_stream DK_P1(dk_fig_conversion *,c)
{
  int back = 0;
  size_t sz = 512;
  char *buffer = NULL, *ptr;
  int cc;
  
  if(c->app) {
    sz = (size_t)dkapp_get_ul_pref(c->app, pk_linelgt);
    if(!sz) { sz = 512; }
    
    if(sz <  128) sz =  128;
    if(max_line_length) {
      if(sz > max_line_length) sz = max_line_length;
    }
  }
  buffer = dk_new(char,sz);
  if(buffer) {			
    back = cc = 1;
    while(cc) {
      if(dkstream_gets(c->istrm, buffer, sz)) {
        
	if(strlen(buffer) == (sz - 1)) {
	  if((c->app) && (c->msg1)) {
	    dkapp_set_source_lineno(
	      c->app,
	      (1 + dkfig_rd_get_errl(c->drwng))
	    );
	    dkfig_tool2_msg1(c, DK_LOG_LEVEL_WARNING, 58);
	  }
	}
        ptr = dkstr_start(buffer, NULL);
	if(ptr) {
	  dkstr_chomp(ptr, NULL);
          if(!dkfig_read_add_line(c->drwng, ptr, c)) {
	    back = cc = 0;
	    if(c->app) {
	      dkapp_set_source_lineno(c->app, dkfig_rd_get_errl(c->drwng));
	    }
	  }
	}
      } else {
        cc = 0;
      }
    }
    if(back) {
      if(!dkfig_read_input_finished(c->drwng,c->normal_text,c->special_text,c)) 
      {
        back = 0;
	if(c->app) {
	  dkapp_set_source_lineno(c->app, dkfig_rd_get_errl(c->drwng));
	}
      }
    } else {
      switch(dkfig_rd_get_errc(c->drwng)) {
        case DKFIG_ERROR_MEMORY: {
	  /* ERROR: Memory allocation failed */
	  dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 11);
	} break;
	case DKFIG_ERROR_SYNTAX: {
	  dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 12);
	} break;
	case DKFIG_ERROR_MATH: {
	  /* ERROR: Math error in calculations */
	  dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 13);
	} break;
      }
    }
    dk_delete(buffer); buffer = NULL;
  } else {
    /* ERROR: Memory */
    dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 11);
  }
  
  return back;
}
/* }}} dkfig_co_add_stream */



/* {{{ dkfig_co_out_to_stream

  Input was read, now write output.

*/

static
int
dkfig_co_out_to_stream DK_P1(dk_fig_conversion *,c)
{
  int back = 0;
  
  switch(c->bdnum) {
    case 0: {
      back = dkfig_output_mp(c);
    } break;
    case 1: {
      back = dkfig_output_mmp(c);
    } break;
    case 2: {
      back = dkfig_output_eps(c);
    } break;
    case 3: {
      back = dkfig_output_svg(c);
    } break;
    case 4: {
      back = dkfig_output_tex(c);
    } break;
    case 5: {
      back = dkfig_output_bb(c);
    } break;
    case 6: {
      back = dkfig_output_pdf(c);
    } break;
    case 7: {
      back = dkfig_output_ps(c);
    } break;
    default: {
      /* ERROR: Unknown base driver ... */
      if(c->app && c->msg1) {
        char buffer[32];
#if DK_HAVE_SNPRINTF
	snprintf(buffer, sizeof(buffer), "%d", c->bdnum);
	buffer[sizeof(buffer)-1] = '\0';
#else
	sprintf(buffer, "%d", c->bdnum);
#endif
        dkfig_tool2_msg3(c, DK_LOG_LEVEL_ERROR, 14, 15, buffer);
      }
    } break;
  }
  
  return back;
}
/* }}} dkfig_co_out_to_stream */



/* {{{ run_for_streams

  Input and output stream usable, read input
  and write output.

*/

static
int
run_for_streams DK_P1(dk_fig_conversion *,c)
{
  int back = 0;
  int use_web_palette = 0;
  
  if((c->opt1) & DKFIG_OPT_WEB_PALETTE) {
    use_web_palette = 1;
  }
  c->drwng = dkfig_new(use_web_palette);
  if(c->drwng) {
    if(c->ifn2) {
      dkfig_set_input_filename(c->drwng, c->ifn2);
      if(c->app) {
        dkapp_set_source_filename(c->app, c->ifn2);
      }
    } else {
      if(c->app) {
        dkapp_set_source_filename(c->app, string_stdin);
      }
    }
    if(c->app) { dkapp_set_source_lineno(c->app, 0UL); }
    dkfig_set_spline_segments(c->drwng, c->spseg);
    dkfig_rd_set_opts((dk_fig_drawing *)((c->drwng)->data), c->opt1);
    dkfig_rd_set_ahlj((dk_fig_drawing *)((c->drwng)->data), c->ahlj);
    dkfig_rd_set_it_steps(
      (dk_fig_drawing *)((c->drwng)->data),
      c->minitsteps, c->maxitsteps
    );
    /* PROGRESS: Reading input file ... */
    dkfig_tool2_msg3(
      c, DK_LOG_LEVEL_PROGRESS, 16, 17, ((c->ifn2) ? c->ifn2 : string_stdin)
    );
    if(dkfig_co_add_stream(c)) {
      /* PROGRESS: Input file was read successfully */
      dkfig_tool2_msg1(c, DK_LOG_LEVEL_PROGRESS, 18);
      dkfig_tool_correct_for_plain_tex(c);
      /* PROGRESS: Writing output file ... */
      dkfig_tool2_msg3(
        c, DK_LOG_LEVEL_PROGRESS, 20, 21, ((c->ofn2) ? c->ofn2 : string_stdout)
      );
      back = dkfig_co_out_to_stream(c);
      if(c->app) { dkapp_set_source_lineno(c->app, 0UL); }
      /* PROGRESS: Finished writing output file */
      dkfig_tool2_msg1(c, DK_LOG_LEVEL_PROGRESS, 22);
      if(!back) {
        dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 113);
      }
    } else {	
      /* PROGRESS: Finished reading input file, failure! */
      dkfig_tool2_msg1(c, DK_LOG_LEVEL_PROGRESS, 19);
    }
    if(c->app) { dkapp_set_source_filename(c->app, NULL); }
    dkfig_delete(c->drwng); c->drwng = NULL;
  } else {
    /* ERROR: Memory */
    dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 11);
  }
  
  return back;
}
/* }}} run_for_streams */



/* {{{ run_for_stdio

  Run as a filter. Process standard input
  to standard output.

*/

static
int
run_for_stdio DK_P1(dk_fig_conversion *,c)
{
  int back = 0;
  
  c->istrm = dkstream_for_file(stdin);
  if(c->istrm) {
    dksf_set_file_binary(stdout);
    c->ostrm = dkstream_for_file(stdout);
    if(c->ostrm) {
      c->ifn2 = NULL; c->ofn2 = NULL;
      back = run_for_streams(c);
      dkstream_close(c->ostrm); c->ostrm = NULL;
    } else {
      /* ERROR: No stream */
      dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 24);
    }
    dkstream_close(c->istrm); c->istrm = NULL;
  } else {
    /* ERROR: No stream */
    dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 23);
  }
  
  return back;
}
/* }}} run_for_stdio */



/* {{{ find_fig_suffix

  Find suffix of input file to check whether the
  file is plain or compressed.

*/

static
char *
find_fig_suffix DK_P1(char *,n)
{
  char *back = NULL;
  char **xptr;
  size_t l1, l2, l3;
  int i;
  
  xptr = figsuffixes;
  l1 = strlen(n);
  while((!back) && (*xptr)) {
    l2 = strlen(*xptr);
    if(l1 > l2) {
      l3 = l1 - l2;
      if(have_fncaseins) {
        i = dkstr_casecmp(&(n[l3]), *xptr);
      } else {
        i = strcmp(&(n[l3]), *xptr);
      }
      if(i == 0) {
        back = &(n[l3]);
      }
    }
    xptr++;
  }
  
  return back;
}
/* }}} find_fig_suffix */



/* {{{ check_must_run

  When traversing a directory we have found a pair
  of input and output file name. Here we check
  whether we must run for that pair (make style
  ignored or input file newer than output file).

*/

static
int
check_must_run DK_P2(char *,i,char *,o)
{
  int back = 1;
  dk_stat_t sti, sto;
  char *ti, *to;
  
  ti = to = NULL;
  if(dkstat_get(&sti, i)) {
    ti = dkstat_mtime(&sti);
  }
  if(dkstat_get(&sto, o)) {
    to = dkstat_mtime(&sto);
  }
  if(ti && to) {
    if(strcmp(to,ti) > 0) {
      back = 0;
    }
  }
  
  return back;
}
/* }}} check_must_run */



/* {{{ run_with_ofn2

  The output file name is now fully known too.
  Open output stream and continue.

*/

static char default_write_mode[] = { "wb" };
static char text_write_mode[] = { "w" };

static
int
run_with_ofn2 DK_P1(dk_fig_conversion *,c)
{
  int back = 0; int ft = -1; int reason = 0;
  char *sp; char *sp2;
  char *write_mode;
  
  write_mode= default_write_mode;
  ft = -1;
  sp = dksf_get_file_type_dot(c->ofn2);
  if(sp) {
    ft = dkstr_array_index(suffixes, sp, have_fncaseins);
    if(c->bdnum < 1) {
      if(!(c->basdr)) {
        
        sp2 = NULL;
        if(ft >= 0) {		
	  *sp = '\0';
          sp2 = dksf_get_file_type_dot(c->ofn2);
	  if(sp2) {
	    sp2++;
	    c->basdr = dkstr_dup(sp2);
	    if(!(c->basdr)) {
	      /* ERROR: Memory */
	      dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 11);
	    }
	  }
	  *sp = '.';
	} else {		
	  sp2 = sp; sp2++;
	  c->basdr = dkstr_dup(sp2);
	  if(!(c->basdr)) {
	    /* ERROR: Memory */
	    dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 11);
	  }
	}
      }
      if(c->basdr) {
        
        c->bdnum = get_base_driver(c->basdr);
      }
    }
  } else {	
  }
  if(c->basdr) {
    if(c->bdnum < 0) {
      c->bdnum = get_base_driver(c->basdr);
    }
    if(c->bdnum > -1) {
    switch(c->bdnum) {
      case 0: case 1: case 4: {
        write_mode = text_write_mode;
      } break;
    }
    switch(ft) {
      case 0: case 2: {
#if DK_HAVE_ZLIB_H
        if(c->app) {
          c->ostrm = dkapp_stream_opengz(c->app, c->ofn2, write_mode);
        } else {
          c->ostrm = dkstream_opengz(c->ofn2, write_mode, 0, &reason);
        }
        if(c->ostrm) {
          back = run_for_streams(c);
          dkstream_close(c->ostrm); c->ostrm = NULL;
        } else {
          /* ERROR: Failed to write */
	  if(c->app) {
	    dkapp_err_fopenw(c->app, c->ofn2);
	  }
        }
#else
	dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 6);
#endif
      } break;
      case 1: {
#if DK_HAVE_BZLIB_H
        if(c->app) {
          c->ostrm = dkapp_stream_openbz2(c->app, c->ofn2, write_mode);
        } else {
          c->ostrm = dkstream_openbz2(c->ofn2, write_mode, 0, &reason);
        }
        if(c->ostrm) {
          back = run_for_streams(c);
          dkstream_close(c->ostrm); c->ostrm = NULL;
        } else {
          /* ERROR: Failed to write */
	  if(c->app) { dkapp_err_fopenw(c->app, c->ofn2); }
        }
#else
	dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 7);
#endif
      } break;
      default: {
        
        if(c->app) {
          c->ostrm = dkapp_stream_openfile(c->app, c->ofn2, write_mode);
        } else {
          c->ostrm = dkstream_openfile(c->ofn2, write_mode, 0, &reason);
        }
        if(c->ostrm) {
          back = run_for_streams(c);
          dkstream_close(c->ostrm); c->ostrm = NULL;
        } else {
          /* ERROR: Failed to write file */
	  if(c->app) { dkapp_err_fopenw(c->app, c->ofn2); }
        }
      } break;
    }
  } else {
    /* ERROR: Unknown base driver */
    dkfig_tool2_msg3(c, DK_LOG_LEVEL_ERROR, 25, 26, c->basdr);
  }
  } else {
    /* No base driver specified */
    dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 27);
  }
  
  return back;
}
/* }}} run_with_ofn2 */



/* {{{ run_with_istream

  The input stream was created successfully, now
  use it.

*/

static
int
run_with_istream DK_P1(dk_fig_conversion *,c)
{
  int back = 0;
  dk_fne_t *fne = NULL;
  char *tc = NULL;
  
  if(c->ofn1) {
    if(dksf_must_expand_filename(c->ofn1)) {
      fne = dkfne_open(c->ofn1, 1, 0);
      if(fne) {
        if(dkfne_next(fne)) {
	  tc = dkstr_dup(dkfne_get_fullname(fne));
	  if(tc) {
	    if(dkfne_next(fne)) {
	      /* ERROR: Too many file names */
	      if(c->app) {
	        dkapp_err_multiple_files(c->app, c->ofn1);
	      }
	    } else {
	      c->ofn2 = tc;
	      back = run_with_ofn2(c);
	      c->ofn2 = NULL;
	    }
	    dk_delete(tc); tc = NULL;
	  } else {
	    /* ERROR: Memory */
	    dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 11);
	  }
	} else {
	  /* ERROR: No such file */
	  if(c->app) {
	    dkapp_err_no_such_file(c->app, c->ofn1);
	  }
	}
        dkfne_close(fne); fne = NULL;
      } else {
        /* ERROR: No filename expander */
	dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 11);
      }
    } else {
      c->ofn2 = c->ofn1;
      back = run_with_ofn2(c);
    }
  } else {
    if(c->basdr) {
      c->bdnum = get_base_driver(c->basdr);
      if(c->bdnum > -1) {
        c->ofn2 = NULL;
        dksf_set_file_binary(stdout);
        c->ostrm = dkstream_for_file(stdout);
        if(c->ostrm) {
          back = run_for_streams(c);
          dkstream_close(c->ostrm); c->ostrm = NULL;
        } else {
          /* ERROR: No stream */
	  dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 24);
        }
      } else {
        /* ERROR: Unknown base driver */
	dkfig_tool2_msg3(c, DK_LOG_LEVEL_ERROR, 25, 26, c->basdr);
      }
    } else {
      /* ERROR: No base driver */
      dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 27);
    }
  }
  
  return back;
}
/* }}} run_with_istream */



/* {{{ run_with_ifn2

  Wildcards in input file name are resolved, ifn2
  contains a real file name (or NULL).

*/

static
int
run_with_ifn2 DK_P1(dk_fig_conversion *,c)
{
  int back = 0; int ft = -1; int reason = 0;
  char *sp;
  
  sp = dksf_get_file_type_dot(c->ifn2);
  if(sp) {
    ft = dkstr_array_index(suffixes, sp, have_fncaseins);
  }
    switch(ft) {
      case 0: {
#if DK_HAVE_ZLIB_H
        if(c->app) {
	  c->istrm = dkapp_stream_opengz(c->app, c->ifn2, str_r);
	} else {
	  c->istrm = dkstream_opengz(c->ifn2, str_r, 0, &reason);
	}
	if(c->istrm) {
	  back = run_with_istream(c);
	  dkstream_close(c->istrm); c->istrm = NULL;
	} else {
	  /* ERROR: Failed to read */
	  if(c->app) { dkapp_err_fopenr(c->app, c->ifn2); }
	}
#else
        /* ERROR: No zlib support */
	dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 6);
#endif
      } break;
      case 1: {
#if DK_HAVE_BZLIB_H
        if(c->app) {
	  c->istrm = dkapp_stream_openbz2(c->app, c->ifn2, str_r);
	} else {
	  c->istrm = dkstream_openbz2(c->ifn2, str_r, 0, &reason);
	}
	if(c->istrm) {
	  back = run_with_istream(c);
	  dkstream_close(c->istrm); c->istrm = NULL;
	} else {
	  /* ERROR: Failed to read */
	  if(c->app) { dkapp_err_fopenr(c->app, c->ifn2); }
	}
#else
        /* ERROR: No bzip2 support */
	dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 7);
#endif
      } break;
      default: {
        if(c->app) {
	  c->istrm = dkapp_stream_openfile(c->app, c->ifn2, str_r);
	} else {
	  c->istrm = dkstream_openfile(c->ifn2, str_r, 0, &reason);
	}
	if(c->istrm) {
	  back = run_with_istream(c);
	  dkstream_close(c->istrm); c->istrm = NULL;
	} else {
	  /* ERROR: No stream */
	  if(c->app) { dkapp_err_fopenr(c->app, c->ifn2); }
	}
      } break;
    }
  
  return back;
}
/* }}} run_with_ifn2 */



/* {{{ run_for_filenames

  The file names specified for input and output
  may still contain wildcards. Resolve if
  necessary.

*/

static
int
run_for_filenames DK_P1(dk_fig_conversion *,c)
{
  int back = 0;
  dk_fne_t *fne = NULL;
  char *tc = NULL;
  
  c->ifn2 = NULL;
  if(c->ifn1) {
    if(dksf_must_expand_filename(c->ifn1)) {
      fne = dkfne_open(c->ifn1, 1, 0);
      if(fne) {
        if(dkfne_next(fne)) {
	  tc = dkstr_dup(dkfne_get_fullname(fne));
	  if(tc) {
	    if(dkfne_next(fne)) {
	      /* ERROR: Too many file names match pattern */
	      if(c->app) {
	        dkapp_err_multiple_files(c->app, c->ifn1);
	      }
	    } else {
	      c->ifn2 = tc;
	      back = run_with_ifn2(c);
	      c->ifn2 = NULL;
	    }
	    dk_delete(tc); tc = NULL;
	  } else {
	    /* ERROR: Memory */
	    dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 11);
	  }
	} else {
	  /* ERROR: No matching file name */
	  if(c->app) {
	    dkapp_err_no_such_file(c->app, c->ifn1);
	  }
	}
        dkfne_close(fne); fne = NULL;
      } else {
        /* ERROR: No file name expander */
	dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 11);
      }
    } else {
      c->ifn2 = c->ifn1;
      back = run_with_ifn2(c);
      c->ifn2 = NULL;
    }
  } else {
    if(c->basdr) {
      c->bdnum = get_base_driver(c->basdr);
      if(c->bdnum > -1) {
        back = run_for_stdio(c);	
      } else {
        /* ERROR: Unknown base driver */
	dkfig_tool2_msg3(c, DK_LOG_LEVEL_ERROR, 25, 26, c->basdr);
      }
    } else {
      /* ERROR: No base driver */
      dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 27);
    }
  }
  c->ifn2 = NULL;
  
  return back;
}
/* }}} run_for_filenames */



/* {{{ save_co_settings
*/
static
void save_co_settings DK_P2(dk_fig_conversion *,cd, dk_fig_conversion *,cs)
{
  cd->normal_text = cs->normal_text;
  cd->special_text = cs->special_text;
  cd->ahlj = cs->ahlj;
  cd->latfs = cs->latfs;
  cd->svgv = cs->svgv;
  cd->psl = cs->psl;
  cd->dscl = cs->dscl;
  cd->spseg = cs->spseg;
  cd->lcfge = cs->lcfge;
  cd->patlw = cs->patlw;
  cd->patrp = cs->patrp;
  cd->nodcoord = cs->nodcoord;
  cd->nodtrigo = cs->nodtrigo;
  cd->nodcolor = cs->nodcolor;
  cd->circlesteps = cs->circlesteps;
  cd->maxitsteps = cs->maxitsteps;
  cd->minitsteps = cs->minitsteps;
  cd->fsf = cs->fsf;
} /* }}} */



/* {{{ run_for_directory

  Traverse directory, process all Fig files found.

*/

static
int
run_for_directory DK_P1(dk_fig_conversion *,c)
{
  int back = 0; int ft = 0; int doit = 0;
  dk_dir_t *dir = NULL;
  long l; size_t sz;	/* size for buffers */
  char *iname = NULL;	/* input file name */
  char *oname = NULL;	/* output file name */
  char *nname = NULL;	/* next full name obtained from directory */
  char *sp = NULL;	/* pointer to the file name suffix */
  char *bck_tpfn;
  dk_fig_conversion backupco;
  
  if((c->basdr) && (c->bdnum > -1)) {
  l = dksf_get_maxpathlen(); sz = (size_t)l;
  iname = dk_new(char,sz);
  oname = dk_new(char,sz);
  if(iname && oname) {
    dir = dkdir_open(c->ifn1);
    if(dir) {
      bck_tpfn = NULL;
      while(dkdir_next(dir)) {
        nname = dkdir_get_fullname(dir);
	if(nname) {
	  if(!(dksf_is_directory(nname))) {
	  if(strlen(nname) < sz) {
	    strcpy(iname, nname); strcpy(oname, nname);
	    sp = find_fig_suffix(oname);
	    if(sp) {
	      ft = dkstr_array_index(figsuffixes,sp,have_fncaseins);
	      if(ft >= 0) {
	        sp++;
		*sp = '\0';
		if(strlen(oname)+strlen(c->basdr) < sz) {
		  strcpy(sp, c->basdr);
		  doit = 1;
		  if((c->opt1) & DKFIG_OPT_MAKE) {
		    doit = check_must_run(iname, oname);
		  }
		  if(doit) {
		    c->ifn2 = iname; c->ofn1 = oname;
		    bck_tpfn = NULL;
		    if(c->tpfn) {
		      bck_tpfn = dkstr_dup(c->tpfn);
		      if(!bck_tpfn) {
		        /* ERROR: Memory */
			dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 11);
		      }
		    }
		    save_co_settings(&backupco, c);
		    back = run_with_ifn2(c);
		    save_co_settings(c, &backupco);
		    if(bck_tpfn) {
		      if(c->tpfn) {
		        char *x; x = c->tpfn;
			dk_delete(x); c->tpfn = NULL;
		      } c->tpfn = NULL;
		      c->tpfn = bck_tpfn;
		      bck_tpfn = NULL;
		    } bck_tpfn = NULL;
		    c->ifn2 = NULL; c->ofn1 = NULL;
		  } else {	/* not necessary to run */
		    /* PROGRESS: No need to run for ... -> ... */
		    dkfig_tool2_msg3(c, DK_LOG_LEVEL_PROGRESS, 28, 29, iname);
		  }
		} else {
		  /* ERROR: Output file name too long */
		  if(c->app && c->msg1) {
		    char *msg[5];
		    msg[0] = (c->msg1)[30];
		    msg[1] = oname;
                    msg[2] = string_dot;
		    msg[3] = c->basdr;
		    msg[4] = (c->msg1)[31];
		    dkapp_log_msg(c->app, DK_LOG_LEVEL_ERROR, msg, 5);
		  }
		}
	      } else {	
	      }
	    }
	  } else {	
	  }
	  }
	} else {	
	}
      }
      dkdir_close(dir); dir = NULL;
    } else {
      /* ERROR: Failed to open directory */
      if(c->app) { dkapp_err_traverse_dir(c->app, c->ifn1 ); }
    }
  } else {
    /* ERROR: Memory */
    dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 11);
  }
  if(oname) { dk_delete(oname); oname = NULL; }
  if(iname) { dk_delete(iname); iname = NULL; }
  }
  
  return back;
}
/* }}} run_for_directory */



/* {{{ lets_go_now

  Run the conversions. Check whether a file or
  a directory was given. If necessary traverse
  the directory.

*/

static
int
lets_go_now DK_P1(dk_fig_conversion *,c)
{
  int back = 0;
  char *auto_file_name = NULL, *ptr = NULL;
  size_t lgt;
  
  c->bdnum = -1;
  if(c->ofn1) {		
    back = run_for_filenames(c);
  } else {		
    if(c->ifn1) {	
      if(dksf_must_expand_filename(c->ifn1)) {	
        back = run_for_filenames(c);
      } else {
        if(dksf_is_directory(c->ifn1)) {	
	  if(c->basdr) {
	    c->bdnum = get_base_driver(c->basdr);
	    if(c->bdnum >= 0) {
	      back = run_for_directory(c);
	    } else {
	      /* ERROR: No such base driver */
	      dkfig_tool2_msg3(c, DK_LOG_LEVEL_ERROR, 25, 26, c->basdr);
	    }
	  } else {
	    /* ERROR: No base driver specified */
	    dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 27);
	  }
	} else {				
	  if(c->basdr) { c->bdnum = get_base_driver(c->basdr); }
	  if(c->af) {				
	    if(c->bdnum >= 0) {
	      lgt = 5 + strlen(c->ifn1);
	      auto_file_name = dk_new(char,lgt);
	      if(auto_file_name) {
	        strcpy(auto_file_name, c->ifn1);
	        ptr = dksf_get_file_type_dot(auto_file_name);
	        if(ptr) { *ptr = '\0'; }
		switch(c->bdnum) {
		  case DKFIG_DRIVER_MP: {
		    strcat(auto_file_name, output_suffixes[0]);
		  } break;
		  case DKFIG_DRIVER_MMP: {
		    strcat(auto_file_name, output_suffixes[0]);
		  } break;
		  case DKFIG_DRIVER_EPS: {
		    strcat(auto_file_name, output_suffixes[1]);
		  } break;
		  case DKFIG_DRIVER_SVG: {
		    strcat(auto_file_name, output_suffixes[2]);
		  } break;
		  case DKFIG_DRIVER_TEX: {
		    strcat(auto_file_name, output_suffixes[3]);
		  } break;
		  case DKFIG_DRIVER_BB: {
		    strcat(auto_file_name, output_suffixes[4]);
		  } break;
		  case DKFIG_DRIVER_PDF: {
		    strcat(auto_file_name, output_suffixes[5]);
		  } break;
		  case DKFIG_DRIVER_PS: {
		    strcat(auto_file_name, output_suffixes[6]);
		  } break;
		}
	        c->ofn1 = auto_file_name;
		dkfig_tool2_msg3(c, DK_LOG_LEVEL_INFO, 127, 128, auto_file_name);
	        back = run_for_filenames(c);
	        c->ofn1 = NULL;
	        dk_delete(auto_file_name);
	        auto_file_name = NULL;
	      } else {
	        /* ERROR: Memory */
		dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 11);
	      }
	    } else {
	      /* ERROR: Internal error, bdnum not yet known */
	    }
	  } else {
	    back = run_for_filenames(c);
	  }
	}
      }
    } else {		
      if(c->basdr) {
        c->bdnum = get_base_driver(c->basdr);
	if(c->bdnum > -1) {
          back = run_for_stdio(c);
	} else {
	  /* ERROR: Unknown base driver */
	  dkfig_tool2_msg3(c, DK_LOG_LEVEL_ERROR, 25, 26, c->basdr);
	}
      } else {
        /* ERROR: No base driver */
	dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 27);
      }
    }
  }
  
  return back;
}
/* }}} lets_go_now */



/* {{{ dkfig_co_run

  Load configuration file, process options
  and run the conversions.

*/

int
dkfig_co_run DK_P1(dk_fig_conversion *,c)
{
  int back = 0;
  
  if(c) {
    establish_base_driver_name(c);
    if(dkfig_co_load_configuration(c)) {
      set_lcfge(c);
      if(dkfig_opt_process_all(c)) {
        back = lets_go_now(c); /* Hey ho, let's go */
      }
    }
  }
  
  return back;
}
/* }}} dkfig_co_run */



/* }}} functions */




/* {{{ SCCS ID */
#ifndef LINT
static char sccs_id[] = {
"@(#)dkfigco.ctr 1.122 05/29/07\t(krause) - fig2vect"
};
#endif
/* }}} */

