push 43f03fe87c2254c6df67b2de3c08b5b20fd64327
[wine/hacks.git] / dlls / sane.ds / capability.c
blobad2d7ba086e85e26e89a0871199c200c9ad03757
1 /*
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
22 #include "config.h"
24 #include <stdarg.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "twain.h"
29 #include "sane_i.h"
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);
39 if (pVal)
41 *value = pVal->Item;
42 if (type)
43 *type = pVal->ItemType;
44 GlobalUnlock (pCapability->hContainer);
45 return TWCC_SUCCESS;
48 return TWCC_BUMMER;
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);
59 if (pVal)
61 pCapability->ConType = TWON_ONEVALUE;
62 pVal->ItemType = type;
63 pVal->Item = value;
64 GlobalUnlock (pCapability->hContainer);
65 return TWCC_SUCCESS;
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");
77 return TWCC_BADCAP;
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;
85 TW_UINT32 *p32;
86 TW_UINT16 *p16;
87 int i;
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);
101 if (! enumv)
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)
116 p16[i] = values[i];
117 if (type == TWTY_INT32 || type == TWTY_UINT32)
118 p32[i] = values[i];
121 GlobalUnlock(pCapability->hContainer);
122 return TWCC_SUCCESS;
125 static TW_UINT16 TWAIN_GetSupportedCaps(pTW_CAPABILITY pCapability)
127 TW_ARRAY *a;
128 static const UINT16 supported_caps[] = { CAP_SUPPORTEDCAPS, CAP_XFERCOUNT, CAP_UICONTROLLABLE,
129 ICAP_XFERMECH, ICAP_PIXELTYPE, ICAP_COMPRESSION, ICAP_PIXELFLAVOR };
131 pCapability->hContainer = GlobalAlloc (0, FIELD_OFFSET( TW_ARRAY, ItemList[sizeof(supported_caps)] ));
132 pCapability->ConType = TWON_ARRAY;
134 if (pCapability->hContainer)
136 UINT16 *u;
137 int i;
138 a = GlobalLock (pCapability->hContainer);
139 a->ItemType = TWTY_UINT16;
140 a->NumItems = sizeof(supported_caps) / sizeof(supported_caps[0]);
141 u = (UINT16 *) a->ItemList;
142 for (i = 0; i < a->NumItems; i++)
143 u[i] = supported_caps[i];
144 GlobalUnlock (pCapability->hContainer);
145 return TWCC_SUCCESS;
147 else
148 return TWCC_LOWMEMORY;
152 /* ICAP_XFERMECH */
153 static TW_UINT16 SANE_ICAPXferMech (pTW_CAPABILITY pCapability, TW_UINT16 action)
155 static const TW_UINT32 possible_values[] = { TWSX_NATIVE, TWSX_MEMORY };
156 TW_UINT32 val;
157 TW_UINT16 twCC = TWCC_BADCAP;
159 TRACE("ICAP_XFERMECH\n");
161 switch (action)
163 case MSG_QUERYSUPPORT:
164 twCC = set_onevalue(pCapability, TWTY_INT32,
165 TWQC_GET | TWQC_SET | TWQC_GETDEFAULT | TWQC_GETCURRENT | TWQC_RESET );
166 break;
168 case MSG_GET:
169 twCC = msg_get_enum(pCapability, possible_values, sizeof(possible_values) / sizeof(possible_values[0]),
170 TWTY_UINT16, activeDS.capXferMech, TWSX_NATIVE);
171 break;
173 case MSG_SET:
174 twCC = msg_set(pCapability, &val);
175 if (twCC == TWCC_SUCCESS)
177 activeDS.capXferMech = (TW_UINT16) val;
178 FIXME("Partial Stub: XFERMECH set to %d, but ignored\n", val);
180 break;
182 case MSG_GETDEFAULT:
183 twCC = set_onevalue(pCapability, TWTY_UINT16, TWSX_NATIVE);
184 break;
186 case MSG_RESET:
187 activeDS.capXferMech = TWSX_NATIVE;
188 /* .. fall through intentional .. */
190 case MSG_GETCURRENT:
191 twCC = set_onevalue(pCapability, TWTY_UINT16, activeDS.capXferMech);
192 FIXME("Partial Stub: XFERMECH of %d not actually used\n", activeDS.capXferMech);
193 break;
195 return twCC;
199 /* CAP_XFERCOUNT */
200 static TW_UINT16 SANE_CAPXferCount (pTW_CAPABILITY pCapability, TW_UINT16 action)
202 TW_UINT32 val;
203 TW_UINT16 twCC = TWCC_BADCAP;
205 TRACE("CAP_XFERCOUNT\n");
207 switch (action)
209 case MSG_QUERYSUPPORT:
210 twCC = set_onevalue(pCapability, TWTY_INT32,
211 TWQC_GET | TWQC_SET | TWQC_GETDEFAULT | TWQC_GETCURRENT | TWQC_RESET );
212 break;
214 case MSG_GET:
215 twCC = set_onevalue(pCapability, TWTY_INT16, -1);
216 FIXME("Partial Stub: Reporting only support for transfer all\n");
217 break;
219 case MSG_SET:
220 twCC = msg_set(pCapability, &val);
221 if (twCC == TWCC_SUCCESS)
222 FIXME("Partial Stub: XFERCOUNT set to %d, but ignored\n", val);
223 break;
225 case MSG_GETDEFAULT:
226 twCC = set_onevalue(pCapability, TWTY_INT16, -1);
227 break;
229 case MSG_RESET:
230 /* .. fall through intentional .. */
232 case MSG_GETCURRENT:
233 twCC = set_onevalue(pCapability, TWTY_INT16, -1);
234 break;
236 return twCC;
239 /* ICAP_PIXELTYPE */
240 static TW_UINT16 SANE_ICAPPixelType (pTW_CAPABILITY pCapability, TW_UINT16 action)
242 static const TW_UINT32 possible_values[] = { TWPT_BW, TWPT_GRAY, TWPT_RGB };
243 TW_UINT32 val;
244 TW_UINT16 twCC = TWCC_BADCAP;
246 TRACE("ICAP_PIXELTYPE\n");
248 switch (action)
250 case MSG_QUERYSUPPORT:
251 twCC = set_onevalue(pCapability, TWTY_INT32,
252 TWQC_GET | TWQC_SET | TWQC_GETDEFAULT | TWQC_GETCURRENT | TWQC_RESET );
253 break;
255 case MSG_GET:
256 twCC = msg_get_enum(pCapability, possible_values, sizeof(possible_values) / sizeof(possible_values[0]),
257 TWTY_UINT16, activeDS.capXferMech, TWPT_BW);
258 break;
260 case MSG_SET:
261 twCC = msg_set(pCapability, &val);
262 if (twCC == TWCC_SUCCESS)
264 activeDS.capPixelType = (TW_UINT16) val;
265 FIXME("Partial Stub: PIXELTYPE set to %d, but ignored\n", val);
267 break;
269 case MSG_GETDEFAULT:
270 twCC = set_onevalue(pCapability, TWTY_UINT16, TWPT_BW);
271 break;
273 case MSG_RESET:
274 activeDS.capPixelType = TWPT_BW;
275 /* .. fall through intentional .. */
277 case MSG_GETCURRENT:
278 twCC = set_onevalue(pCapability, TWTY_UINT16, activeDS.capPixelType);
279 break;
282 return twCC;
285 /* CAP_UICONTROLLABLE */
286 static TW_UINT16 SANE_CAPUiControllable(pTW_CAPABILITY pCapability, TW_UINT16 action)
288 TW_UINT16 twCC = TWCC_BADCAP;
290 TRACE("CAP_UICONTROLLABLE\n");
292 switch (action)
294 case MSG_QUERYSUPPORT:
295 twCC = set_onevalue(pCapability, TWTY_INT32, TWQC_GET);
296 break;
298 case MSG_GET:
299 twCC = set_onevalue(pCapability, TWTY_BOOL, TRUE);
300 break;
303 return twCC;
306 /* ICAP_COMPRESSION */
307 static TW_UINT16 SANE_ICAPCompression (pTW_CAPABILITY pCapability, TW_UINT16 action)
309 static const TW_UINT32 possible_values[] = { TWCP_NONE };
310 TW_UINT32 val;
311 TW_UINT16 twCC = TWCC_BADCAP;
313 TRACE("ICAP_COMPRESSION\n");
315 switch (action)
317 case MSG_QUERYSUPPORT:
318 twCC = set_onevalue(pCapability, TWTY_INT32,
319 TWQC_GET | TWQC_SET | TWQC_GETDEFAULT | TWQC_GETCURRENT | TWQC_RESET );
320 break;
322 case MSG_GET:
323 twCC = msg_get_enum(pCapability, possible_values, sizeof(possible_values) / sizeof(possible_values[0]),
324 TWTY_UINT16, TWCP_NONE, TWCP_NONE);
325 FIXME("Partial stub: We don't attempt to support compression\n");
326 break;
328 case MSG_SET:
329 twCC = msg_set(pCapability, &val);
330 if (twCC == TWCC_SUCCESS)
331 FIXME("Partial Stub: COMPRESSION set to %d, but ignored\n", val);
332 break;
334 case MSG_GETDEFAULT:
335 twCC = set_onevalue(pCapability, TWTY_UINT16, TWCP_NONE);
336 break;
338 case MSG_RESET:
339 /* .. fall through intentional .. */
341 case MSG_GETCURRENT:
342 twCC = set_onevalue(pCapability, TWTY_UINT16, TWCP_NONE);
343 break;
345 return twCC;
348 /* ICAP_PIXELFLAVOR */
349 static TW_UINT16 SANE_ICAPPixelFlavor (pTW_CAPABILITY pCapability, TW_UINT16 action)
351 static const TW_UINT32 possible_values[] = { TWPF_CHOCOLATE, TWPF_VANILLA };
352 TW_UINT32 val;
353 TW_UINT16 twCC = TWCC_BADCAP;
355 TRACE("ICAP_PIXELFLAVOR\n");
357 switch (action)
359 case MSG_QUERYSUPPORT:
360 twCC = set_onevalue(pCapability, TWTY_INT32,
361 TWQC_GET | TWQC_SET | TWQC_GETDEFAULT | TWQC_GETCURRENT | TWQC_RESET );
362 break;
364 case MSG_GET:
365 twCC = msg_get_enum(pCapability, possible_values, sizeof(possible_values) / sizeof(possible_values[0]),
366 TWTY_UINT16, TWPF_CHOCOLATE, TWPF_CHOCOLATE);
367 break;
369 case MSG_SET:
370 twCC = msg_set(pCapability, &val);
371 if (twCC == TWCC_SUCCESS)
373 FIXME("Stub: PIXELFLAVOR set to %d, but ignored\n", val);
375 break;
377 case MSG_GETDEFAULT:
378 twCC = set_onevalue(pCapability, TWTY_UINT16, TWPF_CHOCOLATE);
379 break;
381 case MSG_RESET:
382 /* .. fall through intentional .. */
384 case MSG_GETCURRENT:
385 twCC = set_onevalue(pCapability, TWTY_UINT16, TWPF_CHOCOLATE);
386 break;
388 return twCC;
392 TW_UINT16 SANE_SaneCapability (pTW_CAPABILITY pCapability, TW_UINT16 action)
394 TW_UINT16 twCC = TWCC_CAPUNSUPPORTED;
396 TRACE("capability=%d action=%d\n", pCapability->Cap, action);
398 switch (pCapability->Cap)
400 case CAP_SUPPORTEDCAPS:
401 if (action == MSG_GET)
402 twCC = TWAIN_GetSupportedCaps(pCapability);
403 else
404 twCC = TWCC_BADVALUE;
405 break;
407 case CAP_XFERCOUNT:
408 twCC = SANE_CAPXferCount (pCapability, action);
409 break;
411 case CAP_UICONTROLLABLE:
412 twCC = SANE_CAPUiControllable (pCapability, action);
413 break;
415 case ICAP_PIXELTYPE:
416 twCC = SANE_ICAPPixelType (pCapability, action);
417 break;
419 case ICAP_XFERMECH:
420 twCC = SANE_ICAPXferMech (pCapability, action);
421 break;
423 case ICAP_PIXELFLAVOR:
424 twCC = SANE_ICAPPixelFlavor (pCapability, action);
425 break;
427 case ICAP_COMPRESSION:
428 twCC = SANE_ICAPCompression(pCapability, action);
429 break;
432 /* Twain specifies that you should return a 0 in response to QUERYSUPPORT,
433 * even if you don't formally support the capability */
434 if (twCC == TWCC_CAPUNSUPPORTED && action == MSG_QUERYSUPPORT)
435 twCC = set_onevalue(pCapability, 0, TWTY_INT32);
437 if (twCC == TWCC_CAPUNSUPPORTED)
438 TRACE("capability 0x%x/action=%d being reported as unsupported\n", pCapability->Cap, action);
440 return twCC;