/* * Copyright 2009 Jeremy White for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include "config.h" #include #include "twain.h" #include "sane_i.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(twain); #ifdef SONAME_LIBSANE static SANE_Status sane_find_option(SANE_Handle h, const char *option_name, const SANE_Option_Descriptor **opt_p, int *optno, SANE_Value_Type type) { SANE_Status rc; SANE_Int optcount; const SANE_Option_Descriptor *opt; int i; /* Debian, in 32_net_backend_standard_fix.dpatch, * forces a frontend (that's us) to reload options * manually by invoking get_option_descriptor. */ opt = psane_get_option_descriptor(h, 0); if (! opt) return SANE_STATUS_EOF; rc = psane_control_option(h, 0, SANE_ACTION_GET_VALUE, &optcount, NULL); if (rc != SANE_STATUS_GOOD) return rc; for (i = 1; i < optcount; i++) { opt = psane_get_option_descriptor(h, i); if (opt && (opt->name && strcmp(opt->name, option_name) == 0) && opt->type == type) { *opt_p = opt; *optno = i; return SANE_STATUS_GOOD; } } return SANE_STATUS_EOF; } SANE_Status sane_option_get_int(SANE_Handle h, const char *option_name, SANE_Int *val) { SANE_Status rc; int optno; const SANE_Option_Descriptor *opt; rc = sane_find_option(h, option_name, &opt, &optno, SANE_TYPE_INT); if (rc != SANE_STATUS_GOOD) return rc; return psane_control_option(h, optno, SANE_ACTION_GET_VALUE, val, NULL); } SANE_Status sane_option_set_int(SANE_Handle h, const char *option_name, SANE_Int val, SANE_Int *status) { SANE_Status rc; int optno; const SANE_Option_Descriptor *opt; rc = sane_find_option(h, option_name, &opt, &optno, SANE_TYPE_INT); if (rc != SANE_STATUS_GOOD) return rc; return psane_control_option(h, optno, SANE_ACTION_SET_VALUE, (void *) &val, status); } SANE_Status sane_option_get_bool(SANE_Handle h, const char *option_name, SANE_Bool *val, SANE_Int *status) { SANE_Status rc; int optno; const SANE_Option_Descriptor *opt; rc = sane_find_option(h, option_name, &opt, &optno, SANE_TYPE_BOOL); if (rc != SANE_STATUS_GOOD) return rc; return psane_control_option(h, optno, SANE_ACTION_GET_VALUE, (void *) val, status); } SANE_Status sane_option_set_bool(SANE_Handle h, const char *option_name, SANE_Bool val, SANE_Int *status) { SANE_Status rc; int optno; const SANE_Option_Descriptor *opt; rc = sane_find_option(h, option_name, &opt, &optno, SANE_TYPE_BOOL); if (rc != SANE_STATUS_GOOD) return rc; return psane_control_option(h, optno, SANE_ACTION_SET_VALUE, (void *) &val, status); } SANE_Status sane_option_set_fixed(SANE_Handle h, const char *option_name, SANE_Fixed val, SANE_Int *status) { SANE_Status rc; int optno; const SANE_Option_Descriptor *opt; rc = sane_find_option(h, option_name, &opt, &optno, SANE_TYPE_FIXED); if (rc != SANE_STATUS_GOOD) return rc; return psane_control_option(h, optno, SANE_ACTION_SET_VALUE, (void *) &val, status); } SANE_Status sane_option_get_str(SANE_Handle h, const char *option_name, SANE_String val, size_t len, SANE_Int *status) { SANE_Status rc; int optno; const SANE_Option_Descriptor *opt; rc = sane_find_option(h, option_name, &opt, &optno, SANE_TYPE_STRING); if (rc != SANE_STATUS_GOOD) return rc; if (opt->size < len) return psane_control_option(h, optno, SANE_ACTION_GET_VALUE, (void *) val, status); else return SANE_STATUS_NO_MEM; } /* Important: SANE has the side effect of overwriting val with the returned value */ SANE_Status sane_option_set_str(SANE_Handle h, const char *option_name, SANE_String val, SANE_Int *status) { SANE_Status rc; int optno; const SANE_Option_Descriptor *opt; rc = sane_find_option(h, option_name, &opt, &optno, SANE_TYPE_STRING); if (rc != SANE_STATUS_GOOD) return rc; return psane_control_option(h, optno, SANE_ACTION_SET_VALUE, (void *) val, status); } SANE_Status sane_option_probe_resolution(SANE_Handle h, const char *option_name, SANE_Int *minval, SANE_Int *maxval, SANE_Int *quant) { SANE_Status rc; int optno; const SANE_Option_Descriptor *opt; rc = sane_find_option(h, option_name, &opt, &optno, SANE_TYPE_INT); if (rc != SANE_STATUS_GOOD) return rc; if (opt->constraint_type != SANE_CONSTRAINT_RANGE) return SANE_STATUS_UNSUPPORTED; *minval = opt->constraint.range->min; *maxval = opt->constraint.range->max; *quant = opt->constraint.range->quant; return rc; } SANE_Status sane_option_probe_mode(SANE_Handle h, SANE_String_Const **choices, char *current, int current_size) { SANE_Status rc; int optno; const SANE_Option_Descriptor *opt; rc = sane_find_option(h, "mode", &opt, &optno, SANE_TYPE_STRING); if (rc != SANE_STATUS_GOOD) return rc; if (choices && opt->constraint_type == SANE_CONSTRAINT_STRING_LIST) *choices = (SANE_String_Const *) opt->constraint.string_list; if (opt->size < current_size) return psane_control_option(h, optno, SANE_ACTION_GET_VALUE, current, NULL); else return SANE_STATUS_NO_MEM; } SANE_Status sane_option_probe_scan_area(SANE_Handle h, const char *option_name, SANE_Fixed *val, SANE_Unit *unit, SANE_Fixed *min, SANE_Fixed *max, SANE_Fixed *quant) { SANE_Status rc; int optno; const SANE_Option_Descriptor *opt; rc = sane_find_option(h, option_name, &opt, &optno, SANE_TYPE_FIXED); if (rc != SANE_STATUS_GOOD) return rc; if (unit) *unit = opt->unit; if (min) *min = opt->constraint.range->min; if (max) *max = opt->constraint.range->max; if (quant) *quant = opt->constraint.range->quant; if (val) rc = psane_control_option(h, optno, SANE_ACTION_GET_VALUE, val, NULL); return rc; } TW_UINT16 sane_status_to_twcc(SANE_Status rc) { switch (rc) { case SANE_STATUS_GOOD: return TWCC_SUCCESS; case SANE_STATUS_UNSUPPORTED: return TWCC_CAPUNSUPPORTED; case SANE_STATUS_JAMMED: return TWCC_PAPERJAM; case SANE_STATUS_NO_MEM: return TWCC_LOWMEMORY; case SANE_STATUS_ACCESS_DENIED: return TWCC_DENIED; case SANE_STATUS_IO_ERROR: case SANE_STATUS_NO_DOCS: case SANE_STATUS_COVER_OPEN: case SANE_STATUS_EOF: case SANE_STATUS_INVAL: case SANE_STATUS_CANCELLED: case SANE_STATUS_DEVICE_BUSY: default: return TWCC_BUMMER; } } static void convert_double_fix32(double d, TW_FIX32 *fix32) { TW_INT32 value = (TW_INT32) (d * 65536.0 + 0.5); fix32->Whole = value >> 16; fix32->Frac = value & 0x0000ffffL; } BOOL convert_sane_res_to_twain(double sane_res, SANE_Unit unit, TW_FIX32 *twain_res, TW_UINT16 twtype) { double d; if (unit != SANE_UNIT_MM) return FALSE; if (twtype != TWUN_INCHES) return FALSE; d = (sane_res / 10.0) / 2.54; convert_double_fix32((sane_res / 10.0) / 2.54, twain_res); return TRUE; } #endif