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
, CAP_UICONTROLLABLE
,
129 ICAP_XFERMECH
, ICAP_PIXELTYPE
, ICAP_COMPRESSION
};
131 pCapability
->hContainer
= GlobalAlloc (0, FIELD_OFFSET( TW_ARRAY
, ItemList
[sizeof(supported_caps
)] ));
132 pCapability
->ConType
= TWON_ARRAY
;
134 if (pCapability
->hContainer
)
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
);
148 return TWCC_LOWMEMORY
;
153 static TW_UINT16
SANE_ICAPXferMech (pTW_CAPABILITY pCapability
, TW_UINT16 action
)
155 static const TW_UINT32 possible_values
[] = { TWSX_NATIVE
, TWSX_MEMORY
};
157 TW_UINT16 twCC
= TWCC_BADCAP
;
159 TRACE("ICAP_XFERMECH\n");
163 case MSG_QUERYSUPPORT
:
164 twCC
= set_onevalue(pCapability
, TWTY_INT32
,
165 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
169 twCC
= msg_get_enum(pCapability
, possible_values
, sizeof(possible_values
) / sizeof(possible_values
[0]),
170 TWTY_UINT16
, activeDS
.capXferMech
, TWSX_NATIVE
);
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
);
183 twCC
= set_onevalue(pCapability
, TWTY_UINT16
, TWSX_NATIVE
);
187 activeDS
.capXferMech
= TWSX_NATIVE
;
188 /* .. fall through intentional .. */
191 twCC
= set_onevalue(pCapability
, TWTY_UINT16
, activeDS
.capXferMech
);
192 FIXME("Partial Stub: XFERMECH of %d not actually used\n", activeDS
.capXferMech
);
200 static TW_UINT16
SANE_CAPXferCount (pTW_CAPABILITY pCapability
, TW_UINT16 action
)
203 TW_UINT16 twCC
= TWCC_BADCAP
;
205 TRACE("CAP_XFERCOUNT\n");
209 case MSG_QUERYSUPPORT
:
210 twCC
= set_onevalue(pCapability
, TWTY_INT32
,
211 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
215 twCC
= set_onevalue(pCapability
, TWTY_INT16
, -1);
216 FIXME("Partial Stub: Reporting only support for transfer all\n");
220 twCC
= msg_set(pCapability
, &val
);
221 if (twCC
== TWCC_SUCCESS
)
222 FIXME("Partial Stub: XFERCOUNT set to %d, but ignored\n", val
);
226 twCC
= set_onevalue(pCapability
, TWTY_INT16
, -1);
230 /* .. fall through intentional .. */
233 twCC
= set_onevalue(pCapability
, TWTY_INT16
, -1);
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
};
244 TW_UINT16 twCC
= TWCC_BADCAP
;
246 TRACE("ICAP_PIXELTYPE\n");
250 case MSG_QUERYSUPPORT
:
251 twCC
= set_onevalue(pCapability
, TWTY_INT32
,
252 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
256 twCC
= msg_get_enum(pCapability
, possible_values
, sizeof(possible_values
) / sizeof(possible_values
[0]),
257 TWTY_UINT16
, activeDS
.capXferMech
, TWPT_BW
);
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
);
270 twCC
= set_onevalue(pCapability
, TWTY_UINT16
, TWPT_BW
);
274 activeDS
.capPixelType
= TWPT_BW
;
275 /* .. fall through intentional .. */
278 twCC
= set_onevalue(pCapability
, TWTY_UINT16
, activeDS
.capPixelType
);
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");
294 case MSG_QUERYSUPPORT
:
295 twCC
= set_onevalue(pCapability
, TWTY_INT32
, TWQC_GET
);
299 twCC
= set_onevalue(pCapability
, TWTY_BOOL
, TRUE
);
306 /* ICAP_COMPRESSION */
307 static TW_UINT16
SANE_ICAPCompression (pTW_CAPABILITY pCapability
, TW_UINT16 action
)
309 static const TW_UINT32 possible_values
[] = { TWCP_NONE
};
311 TW_UINT16 twCC
= TWCC_BADCAP
;
313 TRACE("ICAP_COMPRESSION\n");
317 case MSG_QUERYSUPPORT
:
318 twCC
= set_onevalue(pCapability
, TWTY_INT32
,
319 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
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");
329 twCC
= msg_set(pCapability
, &val
);
330 if (twCC
== TWCC_SUCCESS
)
331 FIXME("Partial Stub: COMPRESSION set to %d, but ignored\n", val
);
335 twCC
= set_onevalue(pCapability
, TWTY_UINT16
, TWCP_NONE
);
339 /* .. fall through intentional .. */
342 twCC
= set_onevalue(pCapability
, TWTY_UINT16
, TWCP_NONE
);
348 TW_UINT16
SANE_SaneCapability (pTW_CAPABILITY pCapability
, TW_UINT16 action
)
350 TW_UINT16 twCC
= TWCC_CAPUNSUPPORTED
;
352 TRACE("capability=%d action=%d\n", pCapability
->Cap
, action
);
354 switch (pCapability
->Cap
)
356 case CAP_SUPPORTEDCAPS
:
357 if (action
== MSG_GET
)
358 twCC
= TWAIN_GetSupportedCaps(pCapability
);
360 twCC
= TWCC_BADVALUE
;
364 twCC
= SANE_CAPXferCount (pCapability
, action
);
367 case CAP_UICONTROLLABLE
:
368 twCC
= SANE_CAPUiControllable (pCapability
, action
);
372 twCC
= SANE_ICAPPixelType (pCapability
, action
);
376 twCC
= SANE_ICAPXferMech (pCapability
, action
);
379 case ICAP_COMPRESSION
:
380 twCC
= SANE_ICAPCompression(pCapability
, action
);
384 /* Twain specifies that you should return a 0 in response to QUERYSUPPORT,
385 * even if you don't formally support the capability */
386 if (twCC
== TWCC_CAPUNSUPPORTED
&& action
== MSG_QUERYSUPPORT
)
387 twCC
= set_onevalue(pCapability
, 0, TWTY_INT32
);
389 if (twCC
== TWCC_CAPUNSUPPORTED
)
390 TRACE("capability 0x%x/action=%d being reported as unsupported\n", pCapability
->Cap
, action
);