2 * Copyright 2000 Corel Corporation
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define NONAMELESSUNION
20 #define NONAMELESSSTRUCT
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(twain);
34 static TW_UINT16 get_onevalue(pTW_CAPABILITY pCapability, TW_UINT16 *type, TW_UINT32 *value)
36 if (pCapability->hContainer)
38 pTW_ONEVALUE pVal = GlobalLock (pCapability->hContainer);
43 *type = pVal->ItemType;
44 GlobalUnlock (pCapability->hContainer);
52 static TW_UINT16 set_onevalue(pTW_CAPABILITY pCapability, TW_UINT16 type, TW_UINT32 value)
54 pCapability->hContainer = GlobalAlloc (0, sizeof(TW_ONEVALUE));
56 if (pCapability->hContainer)
58 pTW_ONEVALUE pVal = GlobalLock (pCapability->hContainer);
61 pCapability->ConType = TWON_ONEVALUE;
62 pVal->ItemType = type;
64 GlobalUnlock (pCapability->hContainer);
68 return TWCC_LOWMEMORY;
71 static TW_UINT16 msg_set(pTW_CAPABILITY pCapability, TW_UINT32 *val)
73 if (pCapability->ConType == TWON_ONEVALUE)
74 return get_onevalue(pCapability, NULL, val);
76 FIXME("Partial Stub: MSG_SET only supports TW_ONEVALUE\n");
81 static TW_UINT16 msg_get_enum(pTW_CAPABILITY pCapability, const TW_UINT32 *values, int value_count,
82 TW_UINT16 type, TW_UINT32 current, TW_UINT32 default_value)
84 TW_ENUMERATION *enumv = NULL;
89 pCapability->ConType = TWON_ENUMERATION;
90 pCapability->hContainer = 0;
92 if (type == TWTY_INT16 || type == TWTY_UINT16)
93 pCapability->hContainer = GlobalAlloc (0, FIELD_OFFSET( TW_ENUMERATION, ItemList[value_count * sizeof(TW_UINT16)]));
95 if (type == TWTY_INT32 || type == TWTY_UINT32)
96 pCapability->hContainer = GlobalAlloc (0, FIELD_OFFSET( TW_ENUMERATION, ItemList[value_count * sizeof(TW_UINT32)]));
98 if (pCapability->hContainer)
99 enumv = GlobalLock(pCapability->hContainer);
102 return TWCC_LOWMEMORY;
104 enumv->ItemType = type;
105 enumv->NumItems = value_count;
107 p16 = (TW_UINT16 *) enumv->ItemList;
108 p32 = (TW_UINT32 *) enumv->ItemList;
109 for (i = 0; i < value_count; i++)
111 if (values[i] == current)
112 enumv->CurrentIndex = i;
113 if (values[i] == default_value)
114 enumv->DefaultIndex = i;
115 if (type == TWTY_INT16 || type == TWTY_UINT16)
117 if (type == TWTY_INT32 || type == TWTY_UINT32)
121 GlobalUnlock(pCapability->hContainer);
125 static TW_UINT16 TWAIN_GetSupportedCaps(pTW_CAPABILITY pCapability)
128 static const UINT16 supported_caps[] = { CAP_SUPPORTEDCAPS, CAP_XFERCOUNT, ICAP_XFERMECH };
130 pCapability->hContainer = GlobalAlloc (0, FIELD_OFFSET( TW_ARRAY, ItemList[sizeof(supported_caps)] ));
131 pCapability->ConType = TWON_ARRAY;
133 if (pCapability->hContainer)
137 a = GlobalLock (pCapability->hContainer);
138 a->ItemType = TWTY_UINT16;
139 a->NumItems = sizeof(supported_caps) / sizeof(supported_caps[0]);
140 u = (UINT16 *) a->ItemList;
141 for (i = 0; i < a->NumItems; i++)
142 u[i] = supported_caps[i];
143 GlobalUnlock (pCapability->hContainer);
147 return TWCC_LOWMEMORY;
152 static TW_UINT16 SANE_ICAPXferMech (pTW_CAPABILITY pCapability, TW_UINT16 action)
154 static const TW_UINT32 possible_values[] = { TWSX_NATIVE, TWSX_MEMORY };
156 TW_UINT16 twCC = TWCC_BADCAP;
158 TRACE("ICAP_XFERMECH\n");
162 case MSG_QUERYSUPPORT:
163 twCC = set_onevalue(pCapability, TWTY_INT32,
164 TWQC_GET | TWQC_SET | TWQC_GETDEFAULT | TWQC_GETCURRENT | TWQC_RESET );
168 twCC = msg_get_enum(pCapability, possible_values, sizeof(possible_values) / sizeof(possible_values[0]),
169 TWTY_UINT16, activeDS.capXferMech, TWSX_NATIVE);
173 twCC = msg_set(pCapability, &val);
174 if (twCC == TWCC_SUCCESS)
176 activeDS.capXferMech = (TW_UINT16) val;
177 FIXME("Partial Stub: XFERMECH set to %d, but ignored\n", val);
182 twCC = set_onevalue(pCapability, TWTY_UINT16, TWSX_NATIVE);
186 activeDS.capXferMech = TWSX_NATIVE;
187 /* .. fall through intentional .. */
190 twCC = set_onevalue(pCapability, TWTY_UINT16, activeDS.capXferMech);
191 FIXME("Partial Stub: XFERMECH of %d not actually used\n", activeDS.capXferMech);
199 static TW_UINT16 SANE_CAPXferCount (pTW_CAPABILITY pCapability, TW_UINT16 action)
202 TW_UINT16 twCC = TWCC_BADCAP;
204 TRACE("CAP_XFERCOUNT\n");
208 case MSG_QUERYSUPPORT:
209 twCC = set_onevalue(pCapability, TWTY_INT32,
210 TWQC_GET | TWQC_SET | TWQC_GETDEFAULT | TWQC_GETCURRENT | TWQC_RESET );
214 twCC = set_onevalue(pCapability, TWTY_INT16, -1);
215 FIXME("Partial Stub: Reporting only support for transfer all\n");
219 twCC = msg_set(pCapability, &val);
220 if (twCC == TWCC_SUCCESS)
221 FIXME("Partial Stub: XFERCOUNT set to %d, but ignored\n", val);
225 twCC = set_onevalue(pCapability, TWTY_INT16, -1);
229 /* .. fall through intentional .. */
232 twCC = set_onevalue(pCapability, TWTY_INT16, -1);
238 TW_UINT16 SANE_SaneCapability (pTW_CAPABILITY pCapability, TW_UINT16 action)
240 TW_UINT16 twCC = TWCC_CAPUNSUPPORTED;
242 TRACE("capability=%d action=%d\n", pCapability->Cap, action);
244 switch (pCapability->Cap)
246 case CAP_SUPPORTEDCAPS:
247 if (action == MSG_GET)
248 twCC = TWAIN_GetSupportedCaps(pCapability);
250 twCC = TWCC_BADVALUE;
254 twCC = SANE_CAPXferCount (pCapability, action);
258 twCC = SANE_ICAPXferMech (pCapability, action);
262 /* Twain specifies that you should return a 0 in response to QUERYSUPPORT,
263 * even if you don't formally support the capability */
264 if (twCC == TWCC_CAPUNSUPPORTED && action == MSG_QUERYSUPPORT)
265 twCC = set_onevalue(pCapability, 0, TWTY_INT32);