/*
	WARNING: This file was generated by dkct.
	Changes you make here will be lost if dkct is run again!
	You should modify the original source and run dkct on it.
	Original source: dk3paper.ctr
*/

/*
Copyright (C) 2011-2013, Dirk Krause

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 author nor the names of 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.
*/

/**	@file dk3paper.c The dk3paper module.
*/


#line 57 "dk3paper.ctr"

#include "dk3all.h"
#include "dk3paper.h"





#line 64 "dk3paper.ctr"



/**	Built-in named paper sizes, may be overwritten in configuration files.
*/
static dkChar const * const	dk3paper_default_sizes[] = {
dkT("A4\t\t=\t595\t842"),
dkT("Letter\t\t=\t612\t792"),
dkT("a4\t\t=\t595\t842\t56\t28\t14\t14"),
dkT("letter\t\t=\t612\t792\t56\t28\t14\t14"),
NULL


#line 76 "dk3paper.ctr"
};



/**	File name for configuration file.
*/
static dkChar const dk3paper_config_file_name[] = { dkT("dk3paper.conf") };



/**	Delete named paper size, release memory.
	@param	nps	Data to delete.
*/
static
void
dk3paper_nps_delete(dk3_named_paper_size_t	*nps)
{
  

#line 94 "dk3paper.ctr"
  if(nps->name) {
    dk3_release(nps->name)
  }
  dk3_delete(nps)
  

#line 99 "dk3paper.ctr"
}



/**	Create named paper size structure, allocate memory.
	@param	app	Application structure for diagnostics.
	@param	name	Paper size name.
	@return	Pointer to new paper size on success, NULL on error.
*/
static
dk3_named_paper_size_t *
dk3paper_nps_new(dk3_app_t *app, dkChar const *name)
{
 dk3_named_paper_size_t	*back	= NULL;
 

#line 114 "dk3paper.ctr"
 if((app) && (name)) {
   back = dk3_new_app(dk3_named_paper_size_t,1,app);
   if(back) {
     back->name = NULL;
     (back->size).w = (back->size).h = 0.0;
     (back->size).i = (back->size).o = (back->size).t = (back->size).b = 0.0;
     back->name = dk3str_dup_app(name, app);
     if(!(back->name)) {
       dk3paper_nps_delete(back); back = NULL;
     }
   }
 } 

#line 126 "dk3paper.ctr"
 return back;
}



/**	Compare two named paper sizes by name.
	@param	l	Left structure.
	@param	r	Right structure.
	@param	cr	Comparison criteria (0=size/size, 1=size/name).
	@return	Comparison result.
*/
static
int
dk3paper_nps_compare(void *l, void *r, int cr)
{
  int back = 0;
  dk3_named_paper_size_t	*pl;	/* Pointer to left structure. */
  dk3_named_paper_size_t	*pr;	/* Pointer to right structure. */
  if(l) {
    if(r) {
      pl = (dk3_named_paper_size_t *)l;
      switch(cr) {
        case 1: {
	  /*
	  	Compare structure against a name string.
	  */
	  if(pl->name) {
	    back = dk3str_cmp(pl->name, (dkChar const *)r);
	  } else {
	    back = -1;
	  }
	} break;
	default: {
	  /*
	  	Compare two structures by name.
	  */
	  pr = (dk3_named_paper_size_t *)r;
	  if(pl->name) {
	    if(pr->name) {
	      back = dk3str_cmp(pl->name, pr->name);
	    } else {
	      back = 1;
	    }
	  } else {
	    if(pr->name) {
	      back = -1;
	    }
	  }
	} break;
      }
    } else {
      back = 1;
    }
  } else {
    if(r) {
      back = -1;
    }
  }
  if(back < -1) back = -1;
  if(back >  1) back =  1;
  return back;
}



/**	Set values in a named paper size.
	@param	np	Named paper size.
	@param	v	Values array.
	@param	num	Number of values (2 or 6).
	Width and height are mandatory, borders are
	optional.
	@return	1 on success, 0 on error.
*/
static
int
dk3paper_set_values(dk3_named_paper_size_t *np, double const *v, size_t num)
{
  int			back	= 0;
  

#line 205 "dk3paper.ctr"
  (np->size).i = (np->size).o = (np->size).t = (np->size).b = 0.0;
  (np->size).w = v[0]; (np->size).h = v[1];
  if(num > 2) {
    (np->size).i = v[2]; (np->size).o = v[3];
    (np->size).t = v[4]; (np->size).b = v[5];
  }
  /*
  	Indicate success only if all values are reasonable.
  */
  if((np->size).w > 0.0) {
    if((np->size).h > 0.0) {
      if((np->size).i >= 0.0) {
        if((np->size).o >= 0.0) {
	  if((np->size).t >= 0.0) {
	    if((np->size).b >= 0.0) {
	      back = 1;
	    }
	  }
	}
      }
    }
  } 

#line 227 "dk3paper.ctr"
  return back;
}



/**	Handler function for one configuration file line.
	@param	obj	Paper size collection.
	@param	il	Input line to process.
	@return	1 for OK, 0 for recoverable error, -1 for abort.
*/
static
int
dk3paper_const_line_handler(void *obj, dkChar const *il)
{
  dkChar bu[DK3_PAPER_CONFIG_LINE_SIZE];	/* Private copy. */
  dkChar			*parts[16];	/* Split number sequence. */
  double			 v[8];		/* Values from text line. */
  dk3_paper_size_collection_t	*psc;		/* Paper size collection. */
  dk3_named_paper_size_t	*np;		/* Paper size to edit. */
  dkChar			*p1;		/* Paper size name. */
  dkChar			*p2;		/* Values for that size. */
  size_t			 nparts;	/* Number of values. */
  size_t			 i;		/* Traverse all values. */
  int			 back	= 1;
  int			 res	= 0;	/* Flag: No reporting necessary. */
  

#line 253 "dk3paper.ctr"
  if((obj) && (il)) {	

#line 254 "dk3paper.ctr"
    psc = (dk3_paper_size_collection_t *)obj;
    if(dk3str_len(il) < DK3_SIZEOF(bu,dkChar)) {
      dk3str_cpy(bu, il);
      p1 = dk3str_start(bu, NULL);
      if(p1) {
        if(*p1 != dkT('#')) {
	  p2 = dk3str_chr(p1, dkT('='));
	  if(p2) {
	    *(p2++) = dkT('\0');
	    p2 = dk3str_start(p2, NULL);
	    if(p2) {
	      dk3str_chomp(p1, NULL);
	      nparts = dk3str_explode(parts, 15, p2, NULL);
	      if((nparts == 2) || (nparts == 6)) {
	        /*
			Line syntax ok so far.
		*/
	        res = 1;
		/*
			Read double value from all text words.
		*/
	        for(i = 0; i < nparts; i++) {
		  if(dk3sf_sscanf3(parts[i], dkT("%lg"), &(v[i])) != 1) {
		    res = 0;
		  }
		}
		if(res) {
		  if(dk3str_len(p1) > 0) {
		    /*
		    	Attempt to find existing size for that name.
		    */
		    np = (dk3_named_paper_size_t *)dk3sto_it_find_like(
		      psc->i_sizes, (void *)p1, 1
		    );
		    if(np) {
		      /*
		      	Entry exists, reconfigure entry.
		      */
		      res = dk3paper_set_values(np, v, nparts);
		    } else {
		      /*
		      	Create new entry.
		      */
		      np = dk3paper_nps_new(psc->app, p1);
		      if(np) {
		        if(dk3sto_add(psc->s_sizes, (void *)np)) {
			  res = dk3paper_set_values(np, v, nparts);
			} else {
			  /* ERROR: Memory */
			  dk3paper_nps_delete(np); np = NULL;
			  back = 0;
			}
		      } else {
		        /* ERROR: Memory */
			back = 0;
		      }
		    }
		  } else { res = 0; }
		}
	      }
	    }
	  }
	} else { res = 1; }
      } else { res = 1; }
      if(!(res)) {
        /* ERROR: Syntax */
	dk3str_cpy(bu, il);
	dk3str_normalize(bu, NULL, dkT(' '));
	dk3app_log_i3(psc->app, DK3_LL_ERROR, 211, 212, bu);
      }
    }
  } 

#line 326 "dk3paper.ctr"
  return back;
}



/**	Handler function for one configuration file line.
	@param	obj	Paper size collection.
	@param	il	Input line to process.
	@return	1 for OK, 0 for recoverable error, -1 for abort.
*/
static
int
dk3paper_line_handler(void *obj, dkChar *il)
{
  int back;
  back = dk3paper_const_line_handler(obj, il);
  return back;
}



dk3_paper_size_collection_t *
dk3paper_open_app(dk3_app_t *app)
{
  dkChar			 bu[DK3_PAPER_CONFIG_LINE_SIZE]; /* Buffer. */
  dk3_paper_size_collection_t	*back	= NULL;
  dk3_search_t			*sr;
  dkChar const			*fn;
  dkChar const * const		*lfdptr;
  int				 ok	= 0;
  int				 res;
  int				 de;
  int				 se;
  

#line 360 "dk3paper.ctr"
  if(app) {
    back = dk3_new_app(dk3_paper_size_collection_t,1,app);
    if(back) {
      back->app = app;
      back->s_sizes = NULL; back->i_sizes = NULL;
      back->s_sizes = dk3sto_open_app(app);
      if(back->s_sizes) {
        dk3sto_set_comp(back->s_sizes, dk3paper_nps_compare, 0);
        back->i_sizes = dk3sto_it_open(back->s_sizes);
	if(back->i_sizes) {
	  ok = 1;
	  /*
	  	Read built-in lines.
	  */
	  lfdptr = dk3paper_default_sizes;
	  while(*lfdptr) {
	    if(!dk3paper_const_line_handler((void *)back, *lfdptr)) {
	      ok = 0;
	    }
	    lfdptr++;
	  }
	  /*
	  	Read configuration files.
	  */
	  sr = dk3app_find_config_file(app, dk3paper_config_file_name, 0);
	  if(sr) {
	    dk3search_reset(sr);
	    se = dk3app_get_encoding(app);
	    de = dk3app_get_input_file_encoding(app);
	    while((fn = dk3search_next(sr)) != NULL) {
	      res = dk3stream_process_filename_lines_app(
	        (void *)back, dk3paper_line_handler, fn,
		bu, DK3_SIZEOF(bu,dkChar), se, de, app
	      );
	      if(!(res)) {
	        ok = 0;
	      }
	    }
	    dk3search_close(sr);
	  }
	}
      }
      if(!(ok)) {
        dk3paper_close(back); back = NULL;
      }
    }
  } 

#line 407 "dk3paper.ctr"
  return back;
}



void
dk3paper_close(dk3_paper_size_collection_t *psc)
{
  dk3_named_paper_size_t	*nps;	/* Current size to release. */
  

#line 417 "dk3paper.ctr"
  if(psc) {
    if(psc->s_sizes) {
      if(psc->i_sizes) {
        dk3sto_it_reset(psc->i_sizes);
	while((nps = (dk3_named_paper_size_t *)dk3sto_it_next(psc->i_sizes))
	      != NULL
	)
	{
	  dk3paper_nps_delete(nps);
	}
        dk3sto_it_close(psc->i_sizes);
      }
      dk3sto_close(psc->s_sizes);
    }
    psc->s_sizes = NULL;
    psc->app = NULL;
    dk3_delete(psc);
  } 

#line 435 "dk3paper.ctr"
}


dk3_paper_size_t *
dk3paper_find(dk3_paper_size_collection_t *psc, dkChar const *psn)
{
  dk3_paper_size_t		*back	= NULL;
  dk3_named_paper_size_t	*nps;		/* Named size. */
  

#line 444 "dk3paper.ctr"
  if((psc) && (psn)) {
    nps = (dk3_named_paper_size_t *)dk3sto_it_find_like(
      psc->i_sizes, (void *)psn, 1
    );
    if(nps) {	

#line 449 "dk3paper.ctr"
      back = &(nps->size);
    }
  } 

#line 452 "dk3paper.ctr"
  return back;
}



void
dk3paper_reset(dk3_paper_size_collection_t *psc)
{
  if(psc) {
    if(psc->i_sizes) {
      dk3sto_it_reset(psc->i_sizes);
    }
  }
}




dk3_named_paper_size_t *
dk3paper_next(dk3_paper_size_collection_t *psc)
{
  dk3_named_paper_size_t	*back	= NULL;
  if(psc) {
    if(psc->i_sizes) {
      back = (dk3_named_paper_size_t *)dk3sto_it_next(psc->i_sizes);
    }
  }
  return back;
}



