From: Ilia Docin ilya.docin@contentai.ru
--- dlls/sane.ds/capability.c | 144 ++++++++++++++++++++++++-------------- dlls/sane.ds/options.c | 41 +++++++---- dlls/sane.ds/sane_i.h | 2 +- dlls/sane.ds/unixlib.c | 1 + dlls/sane.ds/unixlib.h | 1 + 5 files changed, 121 insertions(+), 68 deletions(-)
diff --git a/dlls/sane.ds/capability.c b/dlls/sane.ds/capability.c index 555575c45a4..ca58482b1ee 100644 --- a/dlls/sane.ds/capability.c +++ b/dlls/sane.ds/capability.c @@ -277,47 +277,32 @@ static TW_UINT16 SANE_CAPXferCount (pTW_CAPABILITY pCapability, TW_UINT16 action return twCC; }
-static TW_UINT16 set_color_mode(TW_UINT32 pixeltype) +static TW_UINT16 set_option_value(const char* option_name, char* option_value) { - TW_UINT16 twCC = TWCC_BADCAP; + TW_UINT16 twCC = TWCC_BADVALUE; BOOL reload = FALSE; - int i; - const char * const * modes; - /* most of the values are taken from https://gitlab.gnome.org/GNOME/simple-scan/-/blob/master/src/scanner.vala */ - static const char * const gray[] = {"Gray", "Grayscale", "True Gray", "8-bit Grayscale", "Grayscale - 256 Levels", "gray", - 0}; - static const char * const rgb[] = {"Color", "24bit Color[Fast]", "24bit Color", - "24 bit Color", "Color - 16 Million Colors", 0}; - static const char * const bw[] = {"Lineart", "LineArt", "Black & White", "Binary", "Thresholded", "1-bit Black & White", - "Black and White - Line Art", "Black and White - Halftone", "Monochrome", 0}; - switch (pixeltype) - { - case TWPT_GRAY: - modes = gray; - break; - case TWPT_RGB: - modes = rgb; - break; - case TWPT_BW: - modes = bw; - break; - default: - ERR("Unsupported pixeltype %lu\n", pixeltype); - return TWCC_BADVALUE; - break; - } - TRACE("Setting pixeltype to %lu\n", pixeltype); - for(i=0; modes[i]; ++i) + if (*option_value) { - twCC = sane_option_set_str("mode", (char*)modes[i], &reload); + twCC = sane_option_set_str(option_name, option_value, &reload); if (twCC == TWCC_SUCCESS) { if (reload) get_sane_params(&activeDS.frame_params); - break; } } return twCC; }
+static TW_UINT16 find_value_pos(const char* value, const char* values, TW_UINT16 buf_len, TW_UINT16 buf_count) +{ + TW_UINT16 index; + for (index=0; index<buf_count; ++index) + { + if (!strcmp(value, values)) + return index; + value += buf_len; + } + return buf_count; +} + /* ICAP_PIXELTYPE */ static TW_UINT16 SANE_ICAPPixelType (pTW_CAPABILITY pCapability, TW_UINT16 action) { @@ -326,16 +311,35 @@ static TW_UINT16 SANE_ICAPPixelType (pTW_CAPABILITY pCapability, TW_UINT16 actio int possible_value_count; TW_UINT32 val; TW_UINT16 current_pixeltype = TWPT_BW; + enum { buf_len = 64, buf_count = 3 }; + char color_modes[buf_len * buf_count] = {'\0'}, current_mode[buf_len], *output; + static const WCHAR* bw[] = {L"Lineart", L"Black", L"Binary", L"Threshold", L"Mono", 0}; + static const WCHAR* gray[] = {L"Gray", L"gray", 0}; + static const WCHAR* rgb[] = {L"Color", 0}; + static const WCHAR* const* filter[] = {bw, gray, rgb, 0};
TRACE("ICAP_PIXELTYPE\n"); + twCC = sane_option_probe_str("mode", filter, color_modes, buf_len); + if (twCC != TWCC_SUCCESS) + { + ERR("Unable to retrieve modes from sane, ICAP_PIXELTYPE unsupported\n"); + return twCC; + }
- twCC = sane_option_probe_mode(¤t_pixeltype, possible_values, &possible_value_count); + twCC = sane_option_get_str("mode", current_mode, buf_len); if (twCC != TWCC_SUCCESS) { - ERR("Unable to retrieve mode from sane, ICAP_PIXELTYPE unsupported\n"); + ERR("Unable to retrieve current mode from sane, ICAP_PIXELTYPE unsupported\n"); return twCC; }
+ current_pixeltype = find_value_pos(current_mode, color_modes, buf_len, buf_count); + if (current_pixeltype == buf_count) + { + ERR("Wrong current mode value, ICAP_PIXELTYPE unsupported\n"); + twCC = TWCC_BADVALUE; + return twCC; + } /* Sane does not support a concept of a default mode, so we simply cache * the first mode we find */ if (! activeDS.PixelTypeSet) @@ -352,17 +356,28 @@ static TW_UINT16 SANE_ICAPPixelType (pTW_CAPABILITY pCapability, TW_UINT16 actio break;
case MSG_GET: + possible_value_count = 0; + for (val=TWPT_BW; val<=TWPT_RGB; ++val) + { + if (*(color_modes + val * buf_len)) + possible_values[possible_value_count++] = val; + } twCC = msg_get_enum(pCapability, possible_values, possible_value_count, TWTY_UINT16, current_pixeltype, activeDS.defaultPixelType); break;
case MSG_SET: twCC = msg_set(pCapability, &val); - if (twCC == TWCC_SUCCESS) + if ((twCC == TWCC_SUCCESS) && (val < buf_count)) { - TRACE("Setting pixeltype to %ld\n", val); - twCC = set_color_mode(val); + output = color_modes + val * buf_len; + TRACE("Setting pixeltype to %lu: %s\n", val, output); + twCC = set_option_value("mode", output); + if (twCC != TWCC_SUCCESS) + ERR("Unable to set pixeltype to %lu: %s\n", val, output); } + else + twCC = TWCC_BADVALUE; break;
case MSG_GETDEFAULT: @@ -370,7 +385,7 @@ static TW_UINT16 SANE_ICAPPixelType (pTW_CAPABILITY pCapability, TW_UINT16 actio break;
case MSG_RESET: - twCC = set_color_mode(activeDS.defaultPixelType); + twCC = set_option_value("mode", color_modes + activeDS.defaultPixelType * buf_len); if (twCC == TWCC_SUCCESS) current_pixeltype = activeDS.defaultPixelType; else @@ -933,17 +948,35 @@ static TW_UINT16 SANE_CAPFeederEnabled (pTW_CAPABILITY pCapability, TW_UINT16 ac TW_UINT16 twCC = TWCC_BADCAP; TW_UINT32 val; TW_BOOL enabled; - char source[64]; + enum { buf_len = 64, buf_count = 2 }; + char paper_sources[buf_len * buf_count] = {'\0'}, current_source[buf_len], *output; + static const WCHAR* flatbed[] = {L"Flatbed", L"FlatBed", L"Platen", 0}; + static const WCHAR* autofeeder[] = {L"ADF", L"DP", L"Auto"}; + static const WCHAR* const* filter[] = {flatbed, autofeeder, 0};
TRACE("CAP_FEEDERENABLED\n"); + twCC = sane_option_probe_str("source", filter, paper_sources, buf_len); + if (twCC != TWCC_SUCCESS) + { + ERR("Unable to retrieve paper sources from sane, CAP_FEEDERENABLED unsupported\n"); + return twCC; + }
- if (sane_option_get_str("source", source, sizeof(source)) != TWCC_SUCCESS) - return TWCC_BADCAP; + twCC = sane_option_get_str("source", current_source, buf_len); + if (twCC != TWCC_SUCCESS) + { + ERR("Unable to retrieve current paper source from sane, CAP_FEEDERENABLED unsupported\n"); + return twCC; + }
- if (strcmp(source, "Auto") == 0 || strcmp(source, "ADF") == 0) - enabled = TRUE; - else - enabled = FALSE; + val = find_value_pos(current_source, paper_sources, buf_len, buf_count); + if (val == buf_count) + { + ERR("Wrong current paper source value, CAP_FEEDERENABLED unsupported\n"); + twCC = TWCC_BADVALUE; + return twCC; + } + enabled = val > 0;
switch (action) { @@ -958,16 +991,16 @@ static TW_UINT16 SANE_CAPFeederEnabled (pTW_CAPABILITY pCapability, TW_UINT16 ac
case MSG_SET: twCC = msg_set(pCapability, &val); - if (twCC == TWCC_SUCCESS) + if ((twCC == TWCC_SUCCESS) && (val < buf_count)) { - strcpy(source, "ADF"); - twCC = sane_option_set_str("source", source, NULL); + output = paper_sources + val * buf_len; + TRACE("Setting paper source to %lu: %s\n", val, output); + twCC = set_option_value("source", output); if (twCC != TWCC_SUCCESS) - { - strcpy(source, "Auto"); - twCC = sane_option_set_str("source", source, NULL); - } + ERR("Unable to set paper source to %lu: %s\n", val, output); } + else + twCC = TWCC_BADVALUE; break;
case MSG_GETDEFAULT: @@ -975,9 +1008,12 @@ static TW_UINT16 SANE_CAPFeederEnabled (pTW_CAPABILITY pCapability, TW_UINT16 ac break;
case MSG_RESET: - strcpy(source, "Auto"); - if (sane_option_set_str("source", source, NULL) == TWCC_SUCCESS) - enabled = TRUE; + val = *(paper_sources + buf_len) ? 1 : 0; + output = paper_sources + val * buf_len; + TRACE("Resetting paper source to %lu: %s\n", val, output); + twCC = set_option_value("source", output); + if (twCC != TWCC_SUCCESS) + ERR("Unable to reset paper source to %lu: %s\n", val, output); /* .. fall through intentional .. */
case MSG_GETCURRENT: diff --git a/dlls/sane.ds/options.c b/dlls/sane.ds/options.c index 1d39844a770..473cf30e820 100644 --- a/dlls/sane.ds/options.c +++ b/dlls/sane.ds/options.c @@ -59,6 +59,7 @@ TW_UINT16 sane_option_set_int(const char *option_name, int val, BOOL *needs_relo { struct option_descriptor opt; TW_UINT16 rc = sane_find_option(option_name, TYPE_INT, &opt); + if (!opt.is_settable) return TWCC_OPERATIONERROR;
if (rc == TWCC_SUCCESS) rc = sane_option_set_value( opt.optno, &val, needs_reload ); return rc; @@ -77,6 +78,7 @@ TW_UINT16 sane_option_set_bool(const char *option_name, int val ) { struct option_descriptor opt; TW_UINT16 rc = sane_find_option(option_name, TYPE_BOOL, &opt); + if (!opt.is_settable) return TWCC_OPERATIONERROR;
if (rc == TWCC_SUCCESS) rc = sane_option_set_value( opt.optno, &val, NULL ); return rc; @@ -102,6 +104,7 @@ TW_UINT16 sane_option_set_str(const char *option_name, char *val, BOOL *needs_re { struct option_descriptor opt; TW_UINT16 rc = sane_find_option(option_name, TYPE_STRING, &opt); + if (!opt.is_settable) return TWCC_OPERATIONERROR;
if (rc == TWCC_SUCCESS) rc = sane_option_set_value( opt.optno, val, needs_reload ); return rc; @@ -112,30 +115,42 @@ TW_UINT16 sane_option_probe_resolution(const char *option_name, struct option_de return sane_find_option(option_name, TYPE_INT, opt); }
-TW_UINT16 sane_option_probe_mode(TW_UINT16 *current, TW_UINT32 *choices, int *count) +static TW_UINT32 sane_categorize_value(const WCHAR* value, const WCHAR* const* filter[], char* categories, int buf_len) +{ + TW_UINT32 i, j; + for(i=0; filter[i]; ++i) + { + if (!*categories) + { + for(j=0; filter[i][j]; ++j) + { + if (wcsstr(filter[i][j], value)) + { + wcstombs(categories, value, buf_len); + return i; + } + } + } + categories += buf_len; + } + return 0; +} + +TW_UINT16 sane_option_probe_str(const char* option_name, const WCHAR* const* filter[], char* opt_values, int buf_len) { WCHAR *p; - char buffer[256]; struct option_descriptor opt; - TW_UINT16 rc = sane_find_option("mode", TYPE_STRING, &opt); + TW_UINT16 rc = sane_find_option(option_name, TYPE_STRING, &opt);
if (rc != TWCC_SUCCESS) return rc; - if (opt.size > sizeof(buffer)) return TWCC_BADVALUE; - rc = sane_option_get_value( opt.optno, buffer ); + if (opt.size > buf_len) return TWCC_BADVALUE; if (rc != TWCC_SUCCESS) return rc;
- 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 += lstrlenW(p) + 1) { - if (!wcscmp( p, L"Lineart" )) choices[(*count)++] = TWPT_BW; - else if (!wcscmp( p, L"Color" )) choices[(*count)++] = TWPT_RGB; - else if (!wcsncmp( p, L"Gray", 4 )) choices[(*count)++] = TWPT_GRAY; + sane_categorize_value(p, filter, opt_values, buf_len); } } return rc; diff --git a/dlls/sane.ds/sane_i.h b/dlls/sane.ds/sane_i.h index 47c5d69c82e..e35ed77c935 100644 --- a/dlls/sane.ds/sane_i.h +++ b/dlls/sane.ds/sane_i.h @@ -201,7 +201,7 @@ TW_UINT16 sane_option_set_int( const char *option_name, int val, BOOL *reload ); TW_UINT16 sane_option_get_str( const char *option_name, char *val, int len ); TW_UINT16 sane_option_set_str( const char *option_name, char *val, BOOL *reload ); TW_UINT16 sane_option_probe_resolution( const char *option_name, struct option_descriptor *opt ); -TW_UINT16 sane_option_probe_mode(TW_UINT16 *current, TW_UINT32 *choices, int *count); +TW_UINT16 sane_option_probe_str( const char* option_name, const WCHAR* const* filter[], char* opt_vals, int buf_len ); TW_UINT16 sane_option_get_bool( const char *option_name, BOOL *val ); TW_UINT16 sane_option_set_bool( const char *option_name, BOOL val ); TW_UINT16 sane_option_get_scan_area( int *tlx, int *tly, int *brx, int *bry ); diff --git a/dlls/sane.ds/unixlib.c b/dlls/sane.ds/unixlib.c index 897aa09e5ef..69f085450a8 100644 --- a/dlls/sane.ds/unixlib.c +++ b/dlls/sane.ds/unixlib.c @@ -159,6 +159,7 @@ static void map_descr( struct option_descriptor *descr, const SANE_Option_Descri descr->constraint_type = map_constraint_type( opt->constraint_type ); descr->size = opt->size; descr->is_active = SANE_OPTION_IS_ACTIVE( opt->cap ); + descr->is_settable = SANE_OPTION_IS_SETTABLE( opt->cap ); if (opt->title) len = ntdll_umbstowcs( opt->title, strlen(opt->title), descr->title, ARRAY_SIZE(descr->title) ); descr->title[len] = 0; diff --git a/dlls/sane.ds/unixlib.h b/dlls/sane.ds/unixlib.h index d3ffbf1878d..34e7a9a9796 100644 --- a/dlls/sane.ds/unixlib.h +++ b/dlls/sane.ds/unixlib.h @@ -39,6 +39,7 @@ struct option_descriptor int optno; int size; int is_active; + int is_settable; 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;