sane.ds: Convert the SANE option descriptor to a private structure.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-10-27 13:38:59 +02:00
parent 383bb720e4
commit 999d05f695
4 changed files with 376 additions and 332 deletions

View File

@ -293,19 +293,6 @@ static BOOL pixeltype_to_sane_mode(TW_UINT16 pixeltype, SANE_String mode, int le
strcpy(mode, m);
return TRUE;
}
static BOOL sane_mode_to_pixeltype(SANE_String_Const mode, TW_UINT16 *pixeltype)
{
if (strcmp(mode, SANE_VALUE_SCAN_MODE_LINEART) == 0)
*pixeltype = TWPT_BW;
else if (memcmp(mode, SANE_VALUE_SCAN_MODE_GRAY, strlen(SANE_VALUE_SCAN_MODE_GRAY)) == 0)
*pixeltype = TWPT_GRAY;
else if (strcmp(mode, SANE_VALUE_SCAN_MODE_COLOR) == 0)
*pixeltype = TWPT_RGB;
else
return FALSE;
return TRUE;
}
/* ICAP_PIXELTYPE */
static TW_UINT16 SANE_ICAPPixelType (pTW_CAPABILITY pCapability, TW_UINT16 action)
@ -315,22 +302,18 @@ static TW_UINT16 SANE_ICAPPixelType (pTW_CAPABILITY pCapability, TW_UINT16 actio
int possible_value_count;
TW_UINT32 val;
BOOL reload = FALSE;
const char * const *choices;
char current_mode[64];
TW_UINT16 current_pixeltype = TWPT_BW;
SANE_Char mode[64];
TRACE("ICAP_PIXELTYPE\n");
twCC = sane_option_probe_mode(&choices, current_mode, sizeof(current_mode));
twCC = sane_option_probe_mode(&current_pixeltype, possible_values, &possible_value_count);
if (twCC != TWCC_SUCCESS)
{
ERR("Unable to retrieve mode from sane, ICAP_PIXELTYPE unsupported\n");
return twCC;
}
sane_mode_to_pixeltype(current_mode, &current_pixeltype);
/* Sane does not support a concept of a default mode, so we simply cache
* the first mode we find */
if (! activeDS.PixelTypeSet)
@ -347,12 +330,6 @@ static TW_UINT16 SANE_ICAPPixelType (pTW_CAPABILITY pCapability, TW_UINT16 actio
break;
case MSG_GET:
for (possible_value_count = 0; choices && *choices && possible_value_count < 3; choices++)
{
TW_UINT16 pix;
if (sane_mode_to_pixeltype(*choices, &pix))
possible_values[possible_value_count++] = pix;
}
twCC = msg_get_enum(pCapability, possible_values, possible_value_count,
TWTY_UINT16, current_pixeltype, activeDS.defaultPixelType);
break;

View File

@ -18,8 +18,13 @@
#include "config.h"
#include <stdarg.h>
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "sane_i.h"
#include "wine/unicode.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(twain);
@ -51,6 +56,89 @@ static TW_UINT16 sane_status_to_twcc(SANE_Status rc)
}
}
static int map_type( SANE_Value_Type type )
{
switch (type)
{
case SANE_TYPE_BOOL: return TYPE_BOOL;
case SANE_TYPE_INT: return TYPE_INT;
case SANE_TYPE_FIXED: return TYPE_FIXED;
case SANE_TYPE_STRING: return TYPE_STRING;
case SANE_TYPE_BUTTON: return TYPE_BUTTON;
case SANE_TYPE_GROUP: return TYPE_GROUP;
default: return -1;
}
}
static int map_unit( SANE_Unit unit )
{
switch (unit)
{
case SANE_UNIT_NONE: return UNIT_NONE;
case SANE_UNIT_PIXEL: return UNIT_PIXEL;
case SANE_UNIT_BIT: return UNIT_BIT;
case SANE_UNIT_MM: return UNIT_MM;
case SANE_UNIT_DPI: return UNIT_DPI;
case SANE_UNIT_PERCENT: return UNIT_PERCENT;
case SANE_UNIT_MICROSECOND: return UNIT_MICROSECOND;
default: return -1;
}
}
static int map_constraint_type( SANE_Constraint_Type type )
{
switch (type)
{
case SANE_CONSTRAINT_NONE: return CONSTRAINT_NONE;
case SANE_CONSTRAINT_RANGE: return CONSTRAINT_RANGE;
case SANE_CONSTRAINT_WORD_LIST: return CONSTRAINT_WORD_LIST;
case SANE_CONSTRAINT_STRING_LIST: return CONSTRAINT_STRING_LIST;
default: return CONSTRAINT_NONE;
}
}
static void map_descr( struct option_descriptor *descr, const SANE_Option_Descriptor *opt )
{
unsigned int i, size;
WCHAR *p;
descr->type = map_type( opt->type );
descr->unit = map_unit( opt->unit );
descr->constraint_type = map_constraint_type( opt->constraint_type );
descr->size = opt->size;
descr->is_active = SANE_OPTION_IS_ACTIVE( opt->cap );
if (opt->title)
MultiByteToWideChar( CP_UNIXCP, 0, opt->title, -1, descr->title, ARRAY_SIZE(descr->title) );
else
descr->title[0] = 0;
switch (descr->constraint_type)
{
case CONSTRAINT_RANGE:
descr->constraint.range.min = opt->constraint.range->min;
descr->constraint.range.max = opt->constraint.range->max;
descr->constraint.range.quant = opt->constraint.range->quant;
break;
case CONSTRAINT_WORD_LIST:
size = min( opt->constraint.word_list[0], ARRAY_SIZE(descr->constraint.word_list) - 1 );
descr->constraint.word_list[0] = size;
for (i = 1; i <= size; i++) descr->constraint.word_list[i] = opt->constraint.word_list[i];
break;
case CONSTRAINT_STRING_LIST:
p = descr->constraint.strings;
size = ARRAY_SIZE(descr->constraint.strings) - 1;
for (i = 0; size && opt->constraint.string_list[i]; i++)
{
int len = MultiByteToWideChar( CP_UNIXCP, 0, opt->constraint.string_list[i], -1, p, size );
size -= len;
p += len;
}
*p = 0;
break;
default:
break;
}
}
TW_UINT16 sane_option_get_value( int optno, void *val )
{
return sane_status_to_twcc( sane_control_option( activeDS.deviceHandle, optno,
@ -67,88 +155,76 @@ TW_UINT16 sane_option_set_value( int optno, void *val, BOOL *reload )
return rc;
}
static TW_UINT16 sane_find_option(const char *option_name,
const SANE_Option_Descriptor **opt_p, int *optno, SANE_Value_Type type)
TW_UINT16 sane_option_get_descriptor( struct option_descriptor *descr )
{
const SANE_Option_Descriptor *opt = sane_get_option_descriptor( activeDS.deviceHandle, descr->optno );
if (!opt) return TWCC_CAPUNSUPPORTED;
map_descr( descr, opt );
return TWCC_SUCCESS;
}
static TW_UINT16 sane_find_option( const char *name, int type, struct option_descriptor *descr )
{
TW_UINT16 rc;
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 = sane_get_option_descriptor(activeDS.deviceHandle, 0);
if (! opt)
return TWCC_BUMMER;
rc = sane_option_get_value( 0, &optcount );
if (rc != TWCC_SUCCESS) return rc;
for (i = 1; i < optcount; i++)
for (i = 1; (opt = sane_get_option_descriptor( activeDS.deviceHandle, i )) != NULL; i++)
{
opt = sane_get_option_descriptor(activeDS.deviceHandle, i);
if (opt && (opt->name && strcmp(opt->name, option_name) == 0) &&
opt->type == type)
{
*opt_p = opt;
*optno = i;
return TWCC_SUCCESS;
}
if (type != map_type( opt->type )) continue;
if (strcmp( name, opt->name )) continue;
descr->optno = i;
map_descr( descr, opt );
return TWCC_SUCCESS;
}
return TWCC_CAPUNSUPPORTED;
}
TW_UINT16 sane_option_get_int(const char *option_name, int *val)
{
int optno;
const SANE_Option_Descriptor *opt;
TW_UINT16 rc = sane_find_option(option_name, &opt, &optno, SANE_TYPE_INT);
struct option_descriptor opt;
TW_UINT16 rc = sane_find_option(option_name, TYPE_INT, &opt);
if (rc == TWCC_SUCCESS) rc = sane_option_get_value( optno, val );
if (rc == TWCC_SUCCESS) rc = sane_option_get_value( opt.optno, val );
return rc;
}
TW_UINT16 sane_option_set_int(const char *option_name, int val, BOOL *needs_reload )
{
int optno;
const SANE_Option_Descriptor *opt;
TW_UINT16 rc = sane_find_option(option_name, &opt, &optno, SANE_TYPE_INT);
struct option_descriptor opt;
TW_UINT16 rc = sane_find_option(option_name, TYPE_INT, &opt);
if (rc == TWCC_SUCCESS) rc = sane_option_set_value( optno, &val, needs_reload );
if (rc == TWCC_SUCCESS) rc = sane_option_set_value( opt.optno, &val, needs_reload );
return rc;
}
TW_UINT16 sane_option_get_bool(const char *option_name, int *val)
{
int optno;
const SANE_Option_Descriptor *opt;
TW_UINT16 rc = sane_find_option(option_name, &opt, &optno, SANE_TYPE_BOOL);
struct option_descriptor opt;
TW_UINT16 rc = sane_find_option(option_name, TYPE_BOOL, &opt);
if (rc == TWCC_SUCCESS) rc = sane_option_get_value( optno, val );
if (rc == TWCC_SUCCESS) rc = sane_option_get_value( opt.optno, val );
return rc;
}
TW_UINT16 sane_option_set_bool(const char *option_name, int val )
{
int optno;
const SANE_Option_Descriptor *opt;
TW_UINT16 rc = sane_find_option(option_name, &opt, &optno, SANE_TYPE_BOOL);
struct option_descriptor opt;
TW_UINT16 rc = sane_find_option(option_name, TYPE_BOOL, &opt);
if (rc == TWCC_SUCCESS) rc = sane_option_set_value( optno, &val, NULL );
if (rc == TWCC_SUCCESS) rc = sane_option_set_value( opt.optno, &val, NULL );
return rc;
}
TW_UINT16 sane_option_get_str(const char *option_name, char *val, int len)
{
int optno;
const SANE_Option_Descriptor *opt;
TW_UINT16 rc = sane_find_option(option_name, &opt, &optno, SANE_TYPE_STRING);
struct option_descriptor opt;
TW_UINT16 rc = sane_find_option(option_name, TYPE_STRING, &opt);
if (rc == TWCC_SUCCESS)
{
if (opt->size < len)
rc = sane_option_get_value( optno, val );
if (opt.size < len)
rc = sane_option_get_value( opt.optno, val );
else
rc = TWCC_BADVALUE;
}
@ -158,97 +234,106 @@ TW_UINT16 sane_option_get_str(const char *option_name, char *val, int len)
/* Important: SANE has the side effect of overwriting val with the returned value */
TW_UINT16 sane_option_set_str(const char *option_name, char *val, BOOL *needs_reload)
{
int optno;
const SANE_Option_Descriptor *opt;
TW_UINT16 rc = sane_find_option(option_name, &opt, &optno, SANE_TYPE_STRING);
struct option_descriptor opt;
TW_UINT16 rc = sane_find_option(option_name, TYPE_STRING, &opt);
if (rc == TWCC_SUCCESS) rc = sane_option_set_value( optno, &val, needs_reload );
if (rc == TWCC_SUCCESS) rc = sane_option_set_value( opt.optno, &val, needs_reload );
return rc;
}
TW_UINT16 sane_option_probe_resolution(const char *option_name, int *minval, int *maxval, int *quant)
{
int optno;
const SANE_Option_Descriptor *opt;
TW_UINT16 rc = sane_find_option(option_name, &opt, &optno, SANE_TYPE_INT);
struct option_descriptor opt;
TW_UINT16 rc = sane_find_option(option_name, TYPE_INT, &opt);
if (rc != TWCC_SUCCESS) return rc;
if (opt->constraint_type != SANE_CONSTRAINT_RANGE) return TWCC_CAPUNSUPPORTED;
*minval = opt->constraint.range->min;
*maxval = opt->constraint.range->max;
*quant = opt->constraint.range->quant;
if (opt.constraint_type != CONSTRAINT_RANGE) return TWCC_CAPUNSUPPORTED;
*minval = opt.constraint.range.min;
*maxval = opt.constraint.range.max;
*quant = opt.constraint.range.quant;
return rc;
}
TW_UINT16 sane_option_probe_mode(const char * const **choices, char *current, int current_size)
TW_UINT16 sane_option_probe_mode(TW_UINT16 *current, TW_UINT32 *choices, int *count)
{
int optno;
const SANE_Option_Descriptor *opt;
TW_UINT16 rc = sane_find_option("mode", &opt, &optno, SANE_TYPE_STRING);
WCHAR *p;
char buffer[256];
struct option_descriptor opt;
TW_UINT16 rc = sane_find_option("mode", TYPE_STRING, &opt);
if (rc != TWCC_SUCCESS) return rc;
if (choices && opt->constraint_type == SANE_CONSTRAINT_STRING_LIST)
*choices = opt->constraint.string_list;
if (opt.size > sizeof(buffer)) return TWCC_BADVALUE;
rc = sane_option_get_value( opt.optno, buffer );
if (rc != TWCC_SUCCESS) return rc;
if (opt->size < current_size)
return sane_option_get_value( optno, current );
else
return TWCC_BADVALUE;
if (!strcmp( buffer, "Lineart" )) *current = TWPT_BW;
else if (!strcmp( buffer, "Color" )) *current = TWPT_RGB;
else if (!strncmp( buffer, "Gray", 4 )) *current = TWPT_GRAY;
*count = 0;
if (opt.constraint_type == CONSTRAINT_STRING_LIST)
{
for (p = opt.constraint.strings; *p; p += strlenW(p) + 1)
{
static const WCHAR lineartW[] = {'L','i','n','e','a','r','t',0};
static const WCHAR colorW[] = {'C','o','l','o','r',0};
static const WCHAR grayW[] = {'G','r','a','y',0};
if (!strcmpW( p, lineartW )) choices[(*count)++] = TWPT_BW;
else if (!strcmpW( p, colorW )) choices[(*count)++] = TWPT_RGB;
else if (!strncmpW( p, grayW, 4 )) choices[(*count)++] = TWPT_GRAY;
}
}
return rc;
}
TW_UINT16 sane_option_get_scan_area( int *tlx, int *tly, int *brx, int *bry )
{
TW_UINT16 rc;
int optno;
const SANE_Option_Descriptor *opt;
struct option_descriptor opt;
if ((rc = sane_find_option( "tl-x", &opt, &optno, SANE_TYPE_FIXED )) != TWCC_SUCCESS) return rc;
if ((rc = sane_option_get_value( optno, tlx )) != TWCC_SUCCESS) return rc;
if ((rc = sane_find_option( "tl-y", &opt, &optno, SANE_TYPE_FIXED )) != TWCC_SUCCESS) return rc;
if ((rc = sane_option_get_value( optno, tly )) != TWCC_SUCCESS) return rc;
if ((rc = sane_find_option( "br-x", &opt, &optno, SANE_TYPE_FIXED )) != TWCC_SUCCESS) return rc;
if ((rc = sane_option_get_value( optno, brx )) != TWCC_SUCCESS) return rc;
if ((rc = sane_find_option( "br-y", &opt, &optno, SANE_TYPE_FIXED )) != TWCC_SUCCESS) return rc;
if ((rc = sane_option_get_value( optno, bry )) != TWCC_SUCCESS) return rc;
if (opt->unit != SANE_UNIT_MM) FIXME( "unsupported unit %u\n", opt->unit );
if ((rc = sane_find_option( "tl-x", TYPE_FIXED, &opt )) != TWCC_SUCCESS) return rc;
if ((rc = sane_option_get_value( opt.optno, tlx )) != TWCC_SUCCESS) return rc;
if ((rc = sane_find_option( "tl-y", TYPE_FIXED, &opt )) != TWCC_SUCCESS) return rc;
if ((rc = sane_option_get_value( opt.optno, tly )) != TWCC_SUCCESS) return rc;
if ((rc = sane_find_option( "br-x", TYPE_FIXED, &opt )) != TWCC_SUCCESS) return rc;
if ((rc = sane_option_get_value( opt.optno, brx )) != TWCC_SUCCESS) return rc;
if ((rc = sane_find_option( "br-y", TYPE_FIXED, &opt )) != TWCC_SUCCESS) return rc;
if ((rc = sane_option_get_value( opt.optno, bry )) != TWCC_SUCCESS) return rc;
if (opt.unit != UNIT_MM) FIXME( "unsupported unit %u\n", opt.unit );
return rc;
}
TW_UINT16 sane_option_get_max_scan_area( int *tlx, int *tly, int *brx, int *bry )
{
TW_UINT16 rc;
int optno;
const SANE_Option_Descriptor *opt;
struct option_descriptor opt;
if ((rc = sane_find_option( "tl-x", &opt, &optno, SANE_TYPE_FIXED )) != TWCC_SUCCESS) return rc;
*tlx = opt->constraint.range->min;
if ((rc = sane_find_option( "tl-y", &opt, &optno, SANE_TYPE_FIXED )) != TWCC_SUCCESS) return rc;
*tly = opt->constraint.range->min;
if ((rc = sane_find_option( "br-x", &opt, &optno, SANE_TYPE_FIXED )) != TWCC_SUCCESS) return rc;
*brx = opt->constraint.range->max;
if ((rc = sane_find_option( "br-y", &opt, &optno, SANE_TYPE_FIXED )) != TWCC_SUCCESS) return rc;
*bry = opt->constraint.range->max;
if (opt->unit != SANE_UNIT_MM) FIXME( "unsupported unit %u\n", opt->unit );
if ((rc = sane_find_option( "tl-x", TYPE_FIXED, &opt )) != TWCC_SUCCESS) return rc;
*tlx = opt.constraint.range.min;
if ((rc = sane_find_option( "tl-y", TYPE_FIXED, &opt )) != TWCC_SUCCESS) return rc;
*tly = opt.constraint.range.min;
if ((rc = sane_find_option( "br-x", TYPE_FIXED, &opt )) != TWCC_SUCCESS) return rc;
*brx = opt.constraint.range.max;
if ((rc = sane_find_option( "br-y", TYPE_FIXED, &opt )) != TWCC_SUCCESS) return rc;
*bry = opt.constraint.range.max;
if (opt.unit != UNIT_MM) FIXME( "unsupported unit %u\n", opt.unit );
return rc;
}
TW_UINT16 sane_option_set_scan_area( int tlx, int tly, int brx, int bry, BOOL *reload )
{
TW_UINT16 rc;
int optno;
const SANE_Option_Descriptor *opt;
struct option_descriptor opt;
if ((rc = sane_find_option( "tl-x", &opt, &optno, SANE_TYPE_FIXED )) != TWCC_SUCCESS) return rc;
if ((rc = sane_option_set_value( optno, &tlx, reload )) != TWCC_SUCCESS) return rc;
if ((rc = sane_find_option( "tl-y", &opt, &optno, SANE_TYPE_FIXED )) != TWCC_SUCCESS) return rc;
if ((rc = sane_option_set_value( optno, &tly, reload )) != TWCC_SUCCESS) return rc;
if ((rc = sane_find_option( "br-x", &opt, &optno, SANE_TYPE_FIXED )) != TWCC_SUCCESS) return rc;
if ((rc = sane_option_set_value( optno, &brx, reload )) != TWCC_SUCCESS) return rc;
if ((rc = sane_find_option( "br-y", &opt, &optno, SANE_TYPE_FIXED )) != TWCC_SUCCESS) return rc;
if ((rc = sane_option_set_value( optno, &bry, reload )) != TWCC_SUCCESS) return rc;
if ((rc = sane_find_option( "tl-x", TYPE_FIXED, &opt )) != TWCC_SUCCESS) return rc;
if ((rc = sane_option_set_value( opt.optno, &tlx, reload )) != TWCC_SUCCESS) return rc;
if ((rc = sane_find_option( "tl-y", TYPE_FIXED, &opt )) != TWCC_SUCCESS) return rc;
if ((rc = sane_option_set_value( opt.optno, &tly, reload )) != TWCC_SUCCESS) return rc;
if ((rc = sane_find_option( "br-x", TYPE_FIXED, &opt )) != TWCC_SUCCESS) return rc;
if ((rc = sane_option_set_value( opt.optno, &brx, reload )) != TWCC_SUCCESS) return rc;
if ((rc = sane_find_option( "br-y", TYPE_FIXED, &opt )) != TWCC_SUCCESS) return rc;
if ((rc = sane_option_set_value( opt.optno, &bry, reload )) != TWCC_SUCCESS) return rc;
return rc;
}

View File

@ -47,6 +47,25 @@ struct frame_parameters
int depth;
};
struct option_descriptor
{
int optno;
int size;
int is_active;
enum { TYPE_BOOL, TYPE_INT, TYPE_FIXED, TYPE_STRING, TYPE_BUTTON, TYPE_GROUP } type;
enum { UNIT_NONE, UNIT_PIXEL, UNIT_BIT, UNIT_MM, UNIT_DPI, UNIT_PERCENT, UNIT_MICROSECOND } unit;
enum { CONSTRAINT_NONE, CONSTRAINT_RANGE, CONSTRAINT_WORD_LIST, CONSTRAINT_STRING_LIST } constraint_type;
WCHAR title[256];
union
{
WCHAR strings[256];
int word_list[256]; /* first element is list-length */
struct { int min, max, quant; } range;
} constraint;
};
/* internal information about an active data source */
struct tagActiveDS
{
@ -216,12 +235,13 @@ HWND ScanningDialogBox(HWND dialog, LONG progress) DECLSPEC_HIDDEN;
/* Option functions */
TW_UINT16 sane_option_get_value( int optno, void *val ) DECLSPEC_HIDDEN;
TW_UINT16 sane_option_set_value( int optno, void *val, BOOL *reload ) DECLSPEC_HIDDEN;
TW_UINT16 sane_option_get_descriptor( struct option_descriptor *descr ) DECLSPEC_HIDDEN;
TW_UINT16 sane_option_get_int( const char *option_name, int *val ) DECLSPEC_HIDDEN;
TW_UINT16 sane_option_set_int( const char *option_name, int val, BOOL *reload ) DECLSPEC_HIDDEN;
TW_UINT16 sane_option_get_str( const char *option_name, char *val, int len ) DECLSPEC_HIDDEN;
TW_UINT16 sane_option_set_str( const char *option_name, char *val, BOOL *reload ) DECLSPEC_HIDDEN;
TW_UINT16 sane_option_probe_resolution( const char *option_name, int *minval, int *maxval, int *quant) DECLSPEC_HIDDEN;
TW_UINT16 sane_option_probe_mode(const char * const **choices, char *current, int current_size) DECLSPEC_HIDDEN;
TW_UINT16 sane_option_probe_mode(TW_UINT16 *current, TW_UINT32 *choices, int *count) DECLSPEC_HIDDEN;
TW_UINT16 sane_option_get_bool( const char *option_name, BOOL *val ) DECLSPEC_HIDDEN;
TW_UINT16 sane_option_set_bool( const char *option_name, BOOL val ) DECLSPEC_HIDDEN;
TW_UINT16 sane_option_get_scan_area( int *tlx, int *tly, int *brx, int *bry ) DECLSPEC_HIDDEN;

View File

@ -44,13 +44,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(twain);
static INT_PTR CALLBACK DialogProc (HWND , UINT , WPARAM , LPARAM );
static INT CALLBACK PropSheetProc(HWND, UINT,LPARAM);
static int create_leading_static(HDC hdc, LPCSTR text,
static int create_leading_static(HDC hdc, const WCHAR *text,
LPDLGITEMTEMPLATEW* template_out, int y, int id)
{
LPDLGITEMTEMPLATEW tpl = NULL;
INT len;
SIZE size;
LPBYTE ptr;
WORD *ptr;
LONG base;
*template_out = NULL;
@ -60,10 +60,9 @@ static int create_leading_static(HDC hdc, LPCSTR text,
base = GetDialogBaseUnits();
len = MultiByteToWideChar(CP_ACP,0,text,-1,NULL,0);
len *= sizeof(WCHAR);
len = strlenW(text) * sizeof(WCHAR);
len += sizeof(DLGITEMTEMPLATE);
len += 3*sizeof(WORD);
len += 4*sizeof(WORD);
tpl = HeapAlloc(GetProcessHeap(),0,len);
tpl->style=WS_VISIBLE;
@ -72,28 +71,27 @@ static int create_leading_static(HDC hdc, LPCSTR text,
tpl->y = y;
tpl->id = ID_BASE;
GetTextExtentPoint32A(hdc,text,lstrlenA(text),&size);
GetTextExtentPoint32W(hdc,text,lstrlenW(text),&size);
tpl->cx = MulDiv(size.cx,4,LOWORD(base));
tpl->cy = MulDiv(size.cy,8,HIWORD(base)) * 2;
ptr = (LPBYTE)tpl + sizeof(DLGITEMTEMPLATE);
*(LPWORD)ptr = 0xffff;
ptr += sizeof(WORD);
*(LPWORD)ptr = 0x0082;
ptr += sizeof(WORD);
ptr += MultiByteToWideChar(CP_ACP,0,text,-1,(LPWSTR)ptr,len) * sizeof(WCHAR);
*(LPWORD)ptr = 0x0000;
ptr = (WORD *)(tpl + 1);
*ptr++ = 0xffff;
*ptr++ = 0x0082;
strcpyW( ptr, text );
ptr += strlenW(ptr) + 1;
*ptr = 0;
*template_out = tpl;
return len;
}
static int create_trailing_edit(HDC hdc, LPDLGITEMTEMPLATEW* template_out, int id,
int y, LPCSTR text,BOOL is_int)
int y, const WCHAR *text,BOOL is_int)
{
LPDLGITEMTEMPLATEW tpl = NULL;
INT len;
LPBYTE ptr;
WORD *ptr;
SIZE size;
LONG base;
static const char int_base[] = "0000 xxx";
@ -101,10 +99,9 @@ static int create_trailing_edit(HDC hdc, LPDLGITEMTEMPLATEW* template_out, int i
base = GetDialogBaseUnits();
len = MultiByteToWideChar(CP_ACP,0,text,-1,NULL,0);
len *= sizeof(WCHAR);
len = strlenW(text) * sizeof(WCHAR);
len += sizeof(DLGITEMTEMPLATE);
len += 3*sizeof(WORD);
len += 4*sizeof(WORD);
tpl = HeapAlloc(GetProcessHeap(),0,len);
tpl->style=WS_VISIBLE|ES_READONLY|WS_BORDER;
@ -121,33 +118,32 @@ static int create_trailing_edit(HDC hdc, LPDLGITEMTEMPLATEW* template_out, int i
tpl->cx = MulDiv(size.cx*2,4,LOWORD(base));
tpl->cy = MulDiv(size.cy,8,HIWORD(base)) * 2;
ptr = (LPBYTE)tpl + sizeof(DLGITEMTEMPLATE);
*(LPWORD)ptr = 0xffff;
ptr += sizeof(WORD);
*(LPWORD)ptr = 0x0081;
ptr += sizeof(WORD);
ptr += MultiByteToWideChar(CP_ACP,0,text,-1,(LPWSTR)ptr,len) * sizeof(WCHAR);
*(LPWORD)ptr = 0x0000;
ptr = (WORD *)(tpl + 1);
*ptr++ = 0xffff;
*ptr++ = 0x0081;
strcpyW( ptr, text );
ptr += strlenW(ptr) + 1;
*ptr = 0;
*template_out = tpl;
return len;
}
static int create_item(HDC hdc, const SANE_Option_Descriptor *opt,
static int create_item(HDC hdc, const struct option_descriptor *opt,
INT id, LPDLGITEMTEMPLATEW *template_out, int y, int *cx, int* count)
{
LPDLGITEMTEMPLATEW tpl = NULL,rc = NULL;
WORD class = 0xffff;
DWORD styles = WS_VISIBLE;
LPBYTE ptr = NULL;
WORD *ptr = NULL;
LPDLGITEMTEMPLATEW lead_static = NULL;
LPDLGITEMTEMPLATEW trail_edit = NULL;
DWORD leading_len = 0;
DWORD trail_len = 0;
DWORD local_len = 0;
LPCSTR title = NULL;
CHAR buffer[255];
const WCHAR *title = NULL;
WCHAR buffer[255];
int padding = 0;
int padding2 = 0;
int base_x = 0;
@ -159,122 +155,110 @@ static int create_item(HDC hdc, const SANE_Option_Descriptor *opt,
base = GetDialogBaseUnits();
base_x = MulDiv(size.cx,4,LOWORD(base));
if (opt->type == SANE_TYPE_BOOL)
switch (opt->type)
{
case TYPE_BOOL:
class = 0x0080; /* Button */
styles |= BS_AUTOCHECKBOX;
local_len += MultiByteToWideChar(CP_ACP,0,opt->title,-1,NULL,0);
local_len *= sizeof(WCHAR);
title = opt->title;
}
else if (opt->type == SANE_TYPE_INT)
break;
case TYPE_INT:
{
int i;
static const WCHAR fmtW[] = {'%','i',0};
sane_option_get_value( id - ID_BASE, &i );
sprintf(buffer,"%i",i);
sprintfW(buffer,fmtW,i);
if (opt->constraint_type == SANE_CONSTRAINT_NONE)
switch (opt->constraint_type)
{
case CONSTRAINT_NONE:
class = 0x0081; /* Edit*/
styles |= ES_NUMBER;
title = buffer;
local_len += MultiByteToWideChar(CP_ACP,0,title,-1,NULL,0);
local_len *= sizeof(WCHAR);
}
else if (opt->constraint_type == SANE_CONSTRAINT_RANGE)
{
break;
case CONSTRAINT_RANGE:
class = 0x0084; /* scroll */
ctl_cx = 10 * base_x;
trail_len += create_trailing_edit(hdc, &trail_edit, id +
ID_EDIT_BASE, y,buffer,TRUE);
}
else
{
break;
default:
class= 0x0085; /* Combo */
ctl_cx = 10 * base_x;
styles |= CBS_DROPDOWNLIST;
break;
}
leading_len += create_leading_static(hdc, opt->title, &lead_static, y,
id+ID_STATIC_BASE);
leading_len += create_leading_static(hdc, opt->title, &lead_static, y, id+ID_STATIC_BASE);
break;
}
else if (opt->type == SANE_TYPE_FIXED)
case TYPE_FIXED:
{
SANE_Fixed *i;
double dd;
static const WCHAR fmtW[] = {'%','f',0};
i = HeapAlloc(GetProcessHeap(),0,opt->size*sizeof(SANE_Word));
sane_option_get_value( id - ID_BASE, i );
dd = SANE_UNFIX(*i);
sprintf(buffer,"%f",dd);
sprintfW(buffer,fmtW,dd);
HeapFree(GetProcessHeap(),0,i);
if (opt->constraint_type == SANE_CONSTRAINT_NONE)
switch (opt->constraint_type)
{
case CONSTRAINT_NONE:
class = 0x0081; /* Edit */
title = buffer;
local_len += MultiByteToWideChar(CP_ACP,0,title,-1,NULL,0);
local_len *= sizeof(WCHAR);
}
else if (opt->constraint_type == SANE_CONSTRAINT_RANGE)
{
break;
case CONSTRAINT_RANGE:
class= 0x0084; /* scroll */
ctl_cx = 10 * base_x;
trail_len += create_trailing_edit(hdc, &trail_edit, id +
ID_EDIT_BASE, y,buffer,FALSE);
}
else
{
trail_len += create_trailing_edit(hdc, &trail_edit, id + ID_EDIT_BASE, y,buffer,FALSE);
break;
default:
class= 0x0085; /* Combo */
ctl_cx = 10 * base_x;
styles |= CBS_DROPDOWNLIST;
break;
}
leading_len += create_leading_static(hdc, opt->title, &lead_static, y,
id+ID_STATIC_BASE);
leading_len += create_leading_static(hdc, opt->title, &lead_static, y, id+ID_STATIC_BASE);
break;
}
else if (opt->type == SANE_TYPE_STRING)
case TYPE_STRING:
{
if (opt->constraint_type == SANE_CONSTRAINT_NONE)
char str[256];
switch (opt->constraint_type)
{
case CONSTRAINT_NONE:
class = 0x0081; /* Edit*/
}
else
{
break;
default:
class= 0x0085; /* Combo */
ctl_cx = opt->size * base_x;
styles |= CBS_DROPDOWNLIST;
break;
}
leading_len += create_leading_static(hdc, opt->title, &lead_static, y,
id+ID_STATIC_BASE);
sane_option_get_value( id - ID_BASE, buffer );
leading_len += create_leading_static(hdc, opt->title, &lead_static, y, id+ID_STATIC_BASE);
sane_option_get_value( id - ID_BASE, str );
MultiByteToWideChar( CP_UNIXCP, 0, str, -1, buffer, ARRAY_SIZE(buffer) );
title = buffer;
local_len += MultiByteToWideChar(CP_ACP,0,title,-1,NULL,0);
local_len *= sizeof(WCHAR);
break;
}
else if (opt->type == SANE_TYPE_BUTTON)
{
case TYPE_BUTTON:
class = 0x0080; /* Button */
local_len += MultiByteToWideChar(CP_ACP,0,opt->title,-1,NULL,0);
local_len *= sizeof(WCHAR);
title = opt->title;
}
else if (opt->type == SANE_TYPE_GROUP)
{
break;
case TYPE_GROUP:
class = 0x0080; /* Button */
styles |= BS_GROUPBOX;
local_len += MultiByteToWideChar(CP_ACP,0,opt->title,-1,NULL,0);
local_len *= sizeof(WCHAR);
title = opt->title;
break;
}
local_len += sizeof(DLGITEMTEMPLATE);
if (title)
local_len += 3*sizeof(WORD);
else
local_len += 4*sizeof(WORD);
if (title) local_len += strlenW(title) * sizeof(WCHAR);
local_len += 4*sizeof(WORD);
if (lead_static)
{
@ -289,7 +273,7 @@ static int create_item(HDC hdc, const SANE_Option_Descriptor *opt,
tpl->dwExtendedStyle = 0;
if (lead_static)
tpl->x = lead_static->x + lead_static->cx + 1;
else if (opt->type == SANE_TYPE_GROUP)
else if (opt->type == TYPE_GROUP)
tpl->x = 2;
else
tpl->x = 4;
@ -298,7 +282,7 @@ static int create_item(HDC hdc, const SANE_Option_Descriptor *opt,
if (title)
{
GetTextExtentPoint32A(hdc,title,lstrlenA(title),&size);
GetTextExtentPoint32W(hdc,title,lstrlenW(title),&size);
tpl->cx = size.cx;
tpl->cy = size.cy;
}
@ -314,23 +298,16 @@ static int create_item(HDC hdc, const SANE_Option_Descriptor *opt,
tpl->cx = ctl_cx;
}
ptr = (LPBYTE)tpl + sizeof(DLGITEMTEMPLATE);
*(LPWORD)ptr = 0xffff;
ptr += sizeof(WORD);
*(LPWORD)ptr = class;
ptr += sizeof(WORD);
ptr = (WORD *)(tpl + 1);
*ptr++ = 0xffff;
*ptr++ = class;
if (title)
{
ptr += MultiByteToWideChar(CP_ACP,0,title,-1,(LPWSTR)ptr,local_len) * sizeof(WCHAR);
strcpyW( ptr, title );
ptr += strlenW(ptr);
}
else
{
*(LPWORD)ptr = 0x0000;
ptr += sizeof(WORD);
}
*((LPWORD)ptr) = 0x0000;
ptr += sizeof(WORD);
*ptr++ = 0;
*ptr = 0;
if (trail_edit)
{
@ -378,17 +355,16 @@ static LPDLGTEMPLATEW create_options_page(HDC hdc, int *from_index,
for (i = *from_index; i < optcount; i++)
{
LPDLGITEMTEMPLATEW item_tpl = NULL;
const SANE_Option_Descriptor *opt;
struct option_descriptor opt;
int len;
int padding = 0;
int x;
int count;
int hold_for_group = 0;
opt = sane_get_option_descriptor(activeDS.deviceHandle, i);
if (!opt)
continue;
if (opt->type == SANE_TYPE_GROUP && split_tabs)
opt.optno = i;
if (sane_option_get_descriptor( &opt )) continue;
if (opt.type == TYPE_GROUP && split_tabs)
{
if (control_len > 0)
{
@ -401,10 +377,10 @@ static LPDLGTEMPLATEW create_options_page(HDC hdc, int *from_index,
return NULL;
}
}
if (!SANE_OPTION_IS_ACTIVE (opt->cap))
if (!opt.is_active)
continue;
len = create_item(hdc, opt, ID_BASE + i, &item_tpl, y, &x, &count);
len = create_item(hdc, &opt, ID_BASE + i, &item_tpl, y, &x, &count);
control_count += count;
@ -445,7 +421,7 @@ static LPDLGTEMPLATEW create_options_page(HDC hdc, int *from_index,
}
}
if (opt->type == SANE_TYPE_GROUP)
if (opt.type == TYPE_GROUP)
{
if (group_offset == -1)
{
@ -532,20 +508,17 @@ BOOL DoScannerUI(void)
while (index < optcount)
{
const SANE_Option_Descriptor *opt;
struct option_descriptor opt;
psp[page_count].u.pResource = create_options_page(hdc, &index,
optcount, TRUE);
opt = sane_get_option_descriptor(activeDS.deviceHandle, index);
opt.optno = index;
sane_option_get_descriptor( &opt );
if (opt->type == SANE_TYPE_GROUP)
if (opt.type == TYPE_GROUP)
{
LPWSTR title = NULL;
INT len;
len = MultiByteToWideChar(CP_ACP,0,opt->title,-1,NULL,0);
title = HeapAlloc(GetProcessHeap(),0,len * sizeof(WCHAR));
MultiByteToWideChar(CP_ACP,0,opt->title,-1,title,len);
LPWSTR title = HeapAlloc(GetProcessHeap(),0,(strlenW(opt.title) + 1) * sizeof(WCHAR));
strcpyW( title, opt.title );
psp[page_count].pszTitle = title;
}
@ -596,31 +569,33 @@ BOOL DoScannerUI(void)
return FALSE;
}
static void UpdateRelevantEdit(HWND hwnd, const SANE_Option_Descriptor *opt,
int index, int position)
static void UpdateRelevantEdit(HWND hwnd, const struct option_descriptor *opt, int position)
{
WCHAR buffer[244];
HWND edit_w;
int len;
if (opt->type == SANE_TYPE_INT)
switch (opt->type)
{
case TYPE_INT:
{
static const WCHAR formatW[] = {'%','i',0};
INT si;
if (opt->constraint.range->quant)
si = position * opt->constraint.range->quant;
if (opt->constraint.range.quant)
si = position * opt->constraint.range.quant;
else
si = position;
len = sprintfW( buffer, formatW, si );
break;
}
else if (opt->type == SANE_TYPE_FIXED)
case TYPE_FIXED:
{
static const WCHAR formatW[] = {'%','f',0};
double s_quant, dd;
s_quant = SANE_UNFIX(opt->constraint.range->quant);
s_quant = SANE_UNFIX(opt->constraint.range.quant);
if (s_quant)
dd = position * s_quant;
@ -628,39 +603,44 @@ static void UpdateRelevantEdit(HWND hwnd, const SANE_Option_Descriptor *opt,
dd = position * 0.01;
len = sprintfW( buffer, formatW, dd );
break;
}
default:
return;
}
else return;
buffer[len++] = ' ';
LoadStringW( SANE_instance, opt->unit, buffer + len, ARRAY_SIZE( buffer ) - len );
edit_w = GetDlgItem(hwnd,index+ID_BASE+ID_EDIT_BASE);
edit_w = GetDlgItem(hwnd,opt->optno + ID_BASE + ID_EDIT_BASE);
if (edit_w) SetWindowTextW(edit_w,buffer);
}
static BOOL UpdateSaneScrollOption(
const SANE_Option_Descriptor *opt, int index, DWORD position)
static BOOL UpdateSaneScrollOption(const struct option_descriptor *opt, DWORD position)
{
BOOL result = FALSE;
if (opt->type == SANE_TYPE_INT)
switch (opt->type)
{
case TYPE_INT:
{
int si;
if (opt->constraint.range->quant)
si = position * opt->constraint.range->quant;
if (opt->constraint.range.quant)
si = position * opt->constraint.range.quant;
else
si = position;
sane_option_set_value( index, &si, &result );
sane_option_set_value( opt->optno, &si, &result );
break;
}
else if (opt->type == SANE_TYPE_FIXED)
case TYPE_FIXED:
{
double s_quant, dd;
SANE_Fixed *sf;
s_quant = SANE_UNFIX(opt->constraint.range->quant);
s_quant = SANE_UNFIX(opt->constraint.range.quant);
if (s_quant)
dd = position * s_quant;
@ -671,9 +651,13 @@ static BOOL UpdateSaneScrollOption(
*sf = SANE_FIX(dd);
sane_option_set_value( index, sf, &result );
sane_option_set_value( opt->optno, sf, &result );
HeapFree(GetProcessHeap(),0,sf);
break;
}
default:
break;
}
return result;
@ -695,39 +679,32 @@ static INT_PTR InitializeDialog(HWND hwnd)
for ( i = 1; i < optcount; i++)
{
const SANE_Option_Descriptor *opt;
struct option_descriptor opt;
control = GetDlgItem(hwnd,i+ID_BASE);
if (!control)
continue;
opt = sane_get_option_descriptor(activeDS.deviceHandle, i);
opt.optno = i;
sane_option_get_descriptor( &opt );
TRACE("%i %s %i %i\n",i,opt->title,opt->type,opt->constraint_type);
if (!SANE_OPTION_IS_ACTIVE(opt->cap))
EnableWindow(control,FALSE);
else
EnableWindow(control,TRUE);
TRACE("%i %s %i %i\n",i,debugstr_w(opt.title),opt.type,opt.constraint_type);
EnableWindow(control,opt.is_active);
SendMessageA(control,CB_RESETCONTENT,0,0);
/* initialize values */
if (opt->type == SANE_TYPE_STRING && opt->constraint_type !=
SANE_CONSTRAINT_NONE)
if (opt.type == TYPE_STRING && opt.constraint_type != CONSTRAINT_NONE)
{
int j = 0;
CHAR buffer[255];
while (opt->constraint.string_list[j]!=NULL)
{
SendMessageA(control,CB_ADDSTRING,0,
(LPARAM)opt->constraint.string_list[j]);
j++;
}
WCHAR *p;
for (p = opt.constraint.strings; *p; p += strlenW(p) + 1)
SendMessageW( control,CB_ADDSTRING,0, (LPARAM)p );
sane_option_get_value( i, buffer );
SendMessageA(control,CB_SELECTSTRING,0,(LPARAM)buffer);
}
else if (opt->type == SANE_TYPE_BOOL)
else if (opt.type == TYPE_BOOL)
{
BOOL b;
sane_option_get_value( i, &b );
@ -735,46 +712,43 @@ static INT_PTR InitializeDialog(HWND hwnd)
SendMessageA(control,BM_SETCHECK,BST_CHECKED,0);
}
else if (opt->type == SANE_TYPE_INT &&
opt->constraint_type == SANE_CONSTRAINT_WORD_LIST)
else if (opt.type == TYPE_INT && opt.constraint_type == CONSTRAINT_WORD_LIST)
{
int j, count = opt->constraint.word_list[0];
int j, count = opt.constraint.word_list[0];
CHAR buffer[16];
int val;
for (j=1; j<=count; j++)
{
sprintf(buffer, "%d", opt->constraint.word_list[j]);
sprintf(buffer, "%d", opt.constraint.word_list[j]);
SendMessageA(control, CB_ADDSTRING, 0, (LPARAM)buffer);
}
sane_option_get_value( i, &val );
sprintf(buffer, "%d", val);
SendMessageA(control,CB_SELECTSTRING,0,(LPARAM)buffer);
}
else if (opt->constraint_type == SANE_CONSTRAINT_RANGE)
else if (opt.constraint_type == CONSTRAINT_RANGE)
{
if (opt->type == SANE_TYPE_INT)
if (opt.type == TYPE_INT)
{
int si;
int min,max;
min = (SANE_Int)opt->constraint.range->min /
(((SANE_Int)opt->constraint.range->quant)?
(SANE_Int)opt->constraint.range->quant:1);
min = opt.constraint.range.min /
(opt.constraint.range.quant ? opt.constraint.range.quant : 1);
max = (SANE_Int)opt->constraint.range->max /
(((SANE_Int)opt->constraint.range->quant)
?(SANE_Int)opt->constraint.range->quant:1);
max = opt.constraint.range.max /
(opt.constraint.range.quant ? opt.constraint.range.quant : 1);
SendMessageA(control,SBM_SETRANGE,min,max);
sane_option_get_value( i, &si );
if (opt->constraint.range->quant)
si = si / opt->constraint.range->quant;
if (opt.constraint.range.quant)
si = si / opt.constraint.range.quant;
SendMessageW(control,SBM_SETPOS, si, TRUE);
UpdateRelevantEdit(hwnd, opt, i, si);
UpdateRelevantEdit(hwnd, &opt, si);
}
else if (opt->type == SANE_TYPE_FIXED)
else if (opt.type == TYPE_FIXED)
{
SANE_Fixed *sf;
@ -783,9 +757,9 @@ static INT_PTR InitializeDialog(HWND hwnd)
INT pos;
int min,max;
s_min = SANE_UNFIX(opt->constraint.range->min);
s_max = SANE_UNFIX(opt->constraint.range->max);
s_quant = SANE_UNFIX(opt->constraint.range->quant);
s_min = SANE_UNFIX(opt.constraint.range.min);
s_max = SANE_UNFIX(opt.constraint.range.max);
s_quant = SANE_UNFIX(opt.constraint.range.quant);
if (s_quant)
{
@ -801,7 +775,7 @@ static INT_PTR InitializeDialog(HWND hwnd)
SendMessageA(control,SBM_SETRANGE,min,max);
sf = HeapAlloc(GetProcessHeap(),0,opt->size*sizeof(SANE_Word));
sf = HeapAlloc(GetProcessHeap(),0,opt.size*sizeof(SANE_Word));
sane_option_get_value( i, sf );
dd = SANE_UNFIX(*sf);
@ -818,7 +792,7 @@ static INT_PTR InitializeDialog(HWND hwnd)
SendMessageW(control, SBM_SETPOS, pos, TRUE);
UpdateRelevantEdit(hwnd, opt, i, pos);
UpdateRelevantEdit(hwnd, &opt, pos);
}
}
}
@ -828,19 +802,15 @@ static INT_PTR InitializeDialog(HWND hwnd)
static INT_PTR ProcessScroll(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
int index;
const SANE_Option_Descriptor *opt;
struct option_descriptor opt;
WORD scroll;
DWORD position;
index = GetDlgCtrlID((HWND)lParam)- ID_BASE;
if (index < 0)
opt.optno = GetDlgCtrlID((HWND)lParam)- ID_BASE;
if (opt.optno < 0)
return FALSE;
opt = sane_get_option_descriptor(activeDS.deviceHandle, index);
if (!opt)
return FALSE;
if (sane_option_get_descriptor( &opt )) return FALSE;
scroll = LOWORD(wParam);
@ -875,8 +845,8 @@ static INT_PTR ProcessScroll(HWND hwnd, WPARAM wParam, LPARAM lParam)
SendMessageW((HWND)lParam,SBM_SETPOS, position, TRUE);
position = SendMessageW((HWND)lParam,SBM_GETPOS,0,0);
UpdateRelevantEdit(hwnd, opt, index, position);
if (UpdateSaneScrollOption(opt, index, position))
UpdateRelevantEdit(hwnd, &opt, position);
if (UpdateSaneScrollOption(&opt, position))
InitializeDialog(hwnd);
return TRUE;
@ -885,44 +855,36 @@ static INT_PTR ProcessScroll(HWND hwnd, WPARAM wParam, LPARAM lParam)
static void ButtonClicked(HWND hwnd, INT id, HWND control)
{
int index;
const SANE_Option_Descriptor *opt;
struct option_descriptor opt;
BOOL changed = FALSE;
index = id - ID_BASE;
if (index < 0)
opt.optno = id - ID_BASE;
if (opt.optno < 0)
return;
opt = sane_get_option_descriptor(activeDS.deviceHandle, index);
if (sane_option_get_descriptor( &opt )) return;
if (!opt)
return;
if (opt->type == SANE_TYPE_BOOL)
if (opt.type == TYPE_BOOL)
{
BOOL r = SendMessageW(control,BM_GETCHECK,0,0)==BST_CHECKED;
sane_option_set_value( index, &r, &changed );
sane_option_set_value( opt.optno, &r, &changed );
if (changed) InitializeDialog(hwnd);
}
}
static void ComboChanged(HWND hwnd, INT id, HWND control)
{
int index;
int selection;
int len;
const SANE_Option_Descriptor *opt;
struct option_descriptor opt;
SANE_String value;
BOOL changed = FALSE;
index = id - ID_BASE;
if (index < 0)
opt.optno = id - ID_BASE;
if (opt.optno < 0)
return;
opt = sane_get_option_descriptor(activeDS.deviceHandle, index);
if (!opt)
return;
if (sane_option_get_descriptor( &opt )) return;
selection = SendMessageW(control,CB_GETCURSEL,0,0);
len = SendMessageW(control,CB_GETLBTEXTLEN,selection,0);
@ -931,14 +893,14 @@ static void ComboChanged(HWND hwnd, INT id, HWND control)
value = HeapAlloc(GetProcessHeap(),0,len);
SendMessageA(control,CB_GETLBTEXT,selection,(LPARAM)value);
if (opt->type == SANE_TYPE_STRING)
if (opt.type == TYPE_STRING)
{
sane_option_set_value( index, value, &changed );
sane_option_set_value( opt.optno, value, &changed );
}
else if (opt->type == SANE_TYPE_INT)
else if (opt.type == TYPE_INT)
{
int val = atoi( value );
sane_option_set_value( index, &val, &changed );
sane_option_set_value( opt.optno, &val, &changed );
}
if (changed) InitializeDialog(hwnd);
}