diff options
| author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2014-12-02 20:17:04 +0100 | 
|---|---|---|
| committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2014-12-02 20:17:04 +0100 | 
| commit | 7d8191b83e163d76bb05e13b373638e4eeb7da95 (patch) | |
| tree | fe29c36a3cb4ef2267b2253da4dde8ce360b3cb5 /sanei/sanei_load_values.c | |
Initial import of sane-frontends version 1.0.14-9
Diffstat (limited to 'sanei/sanei_load_values.c')
| -rw-r--r-- | sanei/sanei_load_values.c | 207 | 
1 files changed, 207 insertions, 0 deletions
| diff --git a/sanei/sanei_load_values.c b/sanei/sanei_load_values.c new file mode 100644 index 0000000..01c8e42 --- /dev/null +++ b/sanei/sanei_load_values.c @@ -0,0 +1,207 @@ +/* sane - Scanner Access Now Easy. +   Copyright (C) 1997 David Mosberger-Tang +   This file is part of the SANE package. + +   This program is free software; you can redistribute it and/or +   modify it under the terms of the GNU General Public License as +   published by the Free Software Foundation; either version 2 of the +   License, or (at your option) any later version. + +   This program is distributed in the hope that it will be useful, but +   WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   General Public License for more details. + +   You should have received a copy of the GNU General Public License +   along with this program; if not, write to the Free Software +   Foundation, Inc., 59 Temple Place - Suite 330, Boston, +   MA 02111-1307, USA. + +   As a special exception, the authors of SANE give permission for +   additional uses of the libraries contained in this release of SANE. + +   The exception is that, if you link a SANE library with other files +   to produce an executable, this does not by itself cause the +   resulting executable to be covered by the GNU General Public +   License.  Your use of that executable is in no way restricted on +   account of linking the SANE library code into it. + +   This exception does not, however, invalidate any other reasons why +   the executable file might be covered by the GNU General Public +   License. + +   If you submit changes to SANE to the maintainers to be included in +   a subsequent release, you agree by submitting the changes that +   those changes may be distributed with this exception intact. + +   If you write modifications of your own for SANE, it is your choice +   whether to permit this exception to apply to your modifications. +   If you do not wish that, delete this exception notice. + +   This file implements a routine to restore option values saved to a +   file (using sanei_save_values()).  This is a bit tricky since +   setting an option may change the availability of other options. +   The problem is that we don't know the order of the set-value calls +   that resulted in the saved set of option values.  One solution +   might be to simply keep setting all option values until we no +   longer get any changes to the option value set.  However, that has +   the potential for live-lock.  Instead, we keep track of what +   options caused a SANE_INFO_RELOAD_OPTIONS.  For such options, their +   value is set exactly once.  This guarantees convergence after a +   bounded (and usually small) number of iterations.  The resulting +   value set is guaranteed to be the desired (saved) one as long as +   setting an option that affects availability of other options does +   not "lose" its value by setting another option.  I don't think any +   sane backend would do this and since this is SANE, we just proved +   that this algorithm works perfectly.  */ + +#ifdef __TANDEM +#include <floss.h> +#endif + +#ifdef _AIX +# include <lalloca.h>	/* MUST come first for AIX! */ +#endif + +#include "sane/config.h" +#include <lalloca.h> + +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#ifdef HAVE_LIBC_H +# include <libc.h>	/* NeXTStep/OpenStep */ +#endif + +#include <sane/sane.h> +#include "../include/sane/sanei_wire.h" +#include "../include/sane/sanei_codec_ascii.h" + +#define BITS_PER_LONG	(8*sizeof (u_long)) + +#define SET(set, bit) \ +  ((set)[(bit)/BITS_PER_LONG] |= (1UL << (bit)%BITS_PER_LONG)) +#define IS_SET(set, bit) \ +  (((set)[(bit)/BITS_PER_LONG] & (1UL << (bit)%BITS_PER_LONG)) != 0) + +int +sanei_load_values (int fd, SANE_Handle device) +{ +  const SANE_Option_Descriptor *opt; +  SANE_Word *word_array; +  SANE_String name, str; +  u_long *caused_reload; +  SANE_Int num_options; +  SANE_Status status; +  int i, keep_going; +  SANE_Word word; +  SANE_Int info; +  off_t offset; +  size_t size; +  char *buf; +  Wire w; + +  offset = lseek (fd, 0, SEEK_CUR); +  w.io.fd = fd; +#ifdef __TANDEM +  w.io.read = floss_read; +  w.io.write = floss_write; +#else +  w.io.read = read; +  w.io.write = write; +#endif +  sanei_w_init (&w, sanei_codec_ascii_init); +  sanei_w_set_dir (&w, WIRE_DECODE); +  keep_going = 0; + +  sane_control_option (device, 0, SANE_ACTION_GET_VALUE, &num_options, 0); +  size = (num_options + BITS_PER_LONG - 1) / BITS_PER_LONG * sizeof (long); +  caused_reload = alloca (size); +  memset (caused_reload, 0, size); + +  while (1) +    { +      sanei_w_space (&w, 3); + +      if (!w.status) +	sanei_w_string (&w, &name); + +      if (w.status) +	{ +	  if (keep_going) +	    { +	      lseek (fd, offset, SEEK_SET); +	      sanei_w_set_dir (&w, WIRE_DECODE); +	      keep_going = 0; +	      continue; +	    } +	  return 0; +	} + +      status = SANE_STATUS_GOOD; +      info = 0; +      for (i = 1; (opt = sane_get_option_descriptor (device, i)); ++i) +	{ +	  if (!opt->name || strcmp (opt->name, name) != 0) +	    continue; + +	  if (IS_SET(caused_reload, i)) +	    continue; + +	  switch (opt->type) +	    { +	    case SANE_TYPE_BOOL: +	    case SANE_TYPE_INT: +	    case SANE_TYPE_FIXED: +	      if (opt->size == sizeof (SANE_Word)) +		{ +		  sanei_w_word (&w, &word); +		  status = sane_control_option (device, i, +						SANE_ACTION_SET_VALUE, +						&word, &info); +		} +	      else +		{ +		  SANE_Int len; + +		  sanei_w_array (&w, &len, (void **) &word_array, +				 (WireCodecFunc) sanei_w_word, +				 sizeof (SANE_Word)); +		  status = sane_control_option (device, i, +						SANE_ACTION_SET_VALUE, +						word_array, &info); +		  w.direction = WIRE_FREE; +		  sanei_w_array (&w, &len, (void **) &word_array, +				 (WireCodecFunc) sanei_w_word, +				 sizeof (SANE_Word)); +		  w.direction = WIRE_DECODE; +		} +	      break; + +	    case SANE_TYPE_STRING: +	      sanei_w_string (&w, &str); +	      buf = malloc (opt->size); +	      strncpy (buf, str, opt->size); +	      buf[opt->size - 1] = '\0'; +	      sanei_w_free (&w, (WireCodecFunc) sanei_w_string, &str); + +	      status = sane_control_option (device, i, SANE_ACTION_SET_VALUE, +					    buf, &info); +	      break; + +	    case SANE_TYPE_BUTTON: +	    case SANE_TYPE_GROUP: +	      break; +	    } +	  break; +	} +      sanei_w_free (&w, (WireCodecFunc) sanei_w_string, &name); + +      if (status == SANE_STATUS_GOOD && (info & SANE_INFO_RELOAD_OPTIONS)) +	{ +	  SET (caused_reload, i); +	  keep_going = 1; +	} +    } +  return 0; +} | 
