1 
2 
3 /*max@home*/
4 #ifdef __cplusplus
5 extern "C" {
6 #endif
7 
8 #ifdef NOTE
9 ConvertOneValue2Enum() potrebbe essere fonte di errore se
10     DCItemSize[one_value.ItemType] >
11     DCItemSize[TW_INT8] e si utilizzano i bit piu significativi di one_value
12         .Item
13     ConvertEnumeration2Range() potrebbe restituire valori di StepSize non
14     appropriati se enumeration.ItemType e TW_FIX32 potrebbe
15     restituire valori MinValue non corretti se DCItemSize[xxx.ItemType] >
16     DCItemSize[TW_INT8] e si utilizzano i bit piu significativi di xxx.Item
17     ConvertEnum2OneValue ritorna(ovviamente) solo il valore corrente
18 #endif
19 
20 #include <assert.h>
21 #include <string.h>
22 
23 #include "ttwain_capability.h"
24 #include "ttwain_conversion.h"
25 #include "ttwain_error.h"
26 #include "ttwain_state.h"
27 
28 #include "ttwain_global_def.h"
29 
30     /*---------------------------------------------------------------------------*/
31     static const size_t DCItemSize[13] = {
32     sizeof(TW_INT8),   sizeof(TW_INT16),  sizeof(TW_INT32), sizeof(TW_UINT8),
33     sizeof(TW_UINT16), sizeof(TW_UINT32), sizeof(TW_BOOL),  sizeof(TW_FIX32),
34     sizeof(TW_FRAME),  sizeof(TW_STR32),  sizeof(TW_STR64), sizeof(TW_STR128),
35     sizeof(TW_STR255),
36 }; /* see twain.h */
37 
38 /*---------------------------------------------------------------------------*/
39 #define TWON_TWON(TYPE1, TYPE2) (((TYPE1) << 8) | (TYPE2))
40 /*---------------------------------------------------------------------------*/
41 static int ConvertOneValue2Range(TW_ONEVALUE one_value, TW_RANGE *range);
42 static int ConvertEnumeration2Range(TW_ENUMERATION enumeration,
43                                     TW_RANGE *range);
44 static int ConvertOneValue2Enum(TW_ONEVALUE one_value, TW_ENUMERATION *tw_enum);
45 static int ConvertEnum2OneValue(TW_ENUMERATION tw_enum, TW_ONEVALUE *one_value);
46 static int ConvertEnum2Array(TW_ENUMERATION tw_enum, TW_ARRAY *array);
47 
48 static TUINT32 GetContainerSize(int nFormat, unsigned twty, TW_UINT32 nItems);
49 static int TTWAIN_GetCapability(TW_INT16 msgType, TW_UINT16 cap_id,
50                                 TW_UINT16 conType, void *data,
51                                 TUINT32 *cont_size);
52 /*------------------------------------------------------------------------*/
TTWAIN_GetCap(TW_UINT16 cap_id,TW_UINT16 conType,void * data,TUINT32 * cont_size)53 int TTWAIN_GetCap(TW_UINT16 cap_id, TW_UINT16 conType, void *data,
54                   TUINT32 *cont_size) {
55   return TTWAIN_GetCapability(MSG_GET, cap_id, conType, data, cont_size);
56 }
57 /*------------------------------------------------------------------------*/
TTWAIN_GetCapCurrent(TW_UINT16 cap_id,TW_UINT16 conType,void * data,TUINT32 * cont_size)58 int TTWAIN_GetCapCurrent(TW_UINT16 cap_id, TW_UINT16 conType, void *data,
59                          TUINT32 *cont_size) {
60   return TTWAIN_GetCapability(MSG_GETCURRENT, cap_id, conType, data, cont_size);
61 }
62 /*------------------------------------------------------------------------*/
TTWAIN_GetCapQuery(TW_UINT16 cap_id,TW_UINT16 * pattern)63 int TTWAIN_GetCapQuery(TW_UINT16 cap_id, TW_UINT16 *pattern) {
64   int rc;
65   /* GCC9 during compilation shows that this code possible call
66    * TTWAIN_GetCapability() with case TWON_TWON(TWON_RANGE, TWON_RANGE)
67    * whitch cause stack corruption, so make 'data' big enough to store
68    * TW_ONEVALUE. */
69   TW_ONEVALUE data[1 + (sizeof(TW_RANGE) / sizeof(TW_ONEVALUE))];
70   rc = TTWAIN_GetCapability(MSG_QUERYSUPPORT, cap_id, TWON_ONEVALUE, &data, 0);
71   if (!rc) return FALSE;
72   *pattern = (TW_UINT16)data[0].Item;
73   return TRUE;
74 }
75 /*------------------------------------------------------------------------*/
TTWAIN_GetCapability(TW_INT16 msgType,TW_UINT16 cap_id,TW_UINT16 conType,void * data,TUINT32 * cont_size)76 static int TTWAIN_GetCapability(TW_INT16 msgType, TW_UINT16 cap_id,
77                                 TW_UINT16 conType, void *data,
78                                 TUINT32 *cont_size) {
79   TW_CAPABILITY cap;
80   void *pv;
81   TW_ENUMERATION *my_enum;
82   TW_ARRAY *my_array;
83   TW_ONEVALUE *my_one;
84   TW_RANGE *my_range;
85   TUINT32 size = 0;
86 
87   if (!data && !cont_size) return FALSE;
88 
89   if (TTWAIN_GetState() < TWAIN_SOURCE_OPEN) {
90     TTWAIN_ErrorBox("Attempt to get capability value below State 4.");
91     return FALSE;
92   }
93   /* Fill in capability structure */
94   cap.Cap = cap_id; /* capability id */
95   cap.ConType =
96       TWON_DONTCARE16; /* favorite type of container (should be ignored...) */
97   cap.hContainer = NULL;
98 
99   if (TTWAIN_DS(DG_CONTROL, DAT_CAPABILITY, msgType, (TW_MEMREF)&cap) !=
100       TWRC_SUCCESS)
101     return FALSE;
102 
103   if (!cap.hContainer) return FALSE;
104 
105   if (msgType == MSG_QUERYSUPPORT) {
106   }
107 
108   pv       = GLOBAL_LOCK(cap.hContainer);
109   my_enum  = (TW_ENUMERATION *)pv;
110   my_array = (TW_ARRAY *)pv;
111   my_one   = (TW_ONEVALUE *)pv;
112   my_range = (TW_RANGE *)pv;
113 
114   if (cont_size) {
115     switch (TWON_TWON(cap.ConType, conType)) {
116     case TWON_TWON(TWON_ENUMERATION, TWON_ENUMERATION):
117       *cont_size = GetContainerSize(TWON_ENUMERATION, my_enum->ItemType,
118                                     my_enum->NumItems);
119       break;
120     case TWON_TWON(TWON_ONEVALUE, TWON_ENUMERATION):
121       *cont_size = GetContainerSize(TWON_ENUMERATION, my_one->ItemType, 1);
122       break;
123     case TWON_TWON(TWON_ARRAY, TWON_ARRAY):
124       *cont_size =
125           GetContainerSize(TWON_ARRAY, my_array->ItemType, my_array->NumItems);
126       break;
127     case TWON_TWON(TWON_ONEVALUE, TWON_ONEVALUE):
128       *cont_size = GetContainerSize(TWON_ONEVALUE, my_one->ItemType, 1);
129       break;
130     case TWON_TWON(TWON_ENUMERATION, TWON_ARRAY):
131       *cont_size =
132           GetContainerSize(TWON_ARRAY, my_enum->ItemType, my_enum->NumItems);
133       break;
134     default:
135       /*      tmsg_error("Unable to convert type %d to %d (cap 0x%x)\n",
136        * cap.ConType, conType,cap_id);*/
137       assert(0);
138       GLOBAL_UNLOCK(cap.hContainer);
139       GLOBAL_FREE(cap.hContainer);
140       return FALSE;
141     }
142     GLOBAL_UNLOCK(cap.hContainer);
143     GLOBAL_FREE(cap.hContainer);
144     return TRUE;
145   }
146 
147   switch (TWON_TWON(cap.ConType, conType)) {
148   case TWON_TWON(TWON_ENUMERATION, TWON_ENUMERATION):
149     size = GetContainerSize(cap.ConType, my_enum->ItemType, my_enum->NumItems);
150     memcpy(data, my_enum, size);
151     break;
152   case TWON_TWON(TWON_ENUMERATION, TWON_RANGE):
153     ConvertEnumeration2Range(*my_enum, (TW_RANGE *)data);
154     break;
155   case TWON_TWON(TWON_ENUMERATION, TWON_ONEVALUE):
156     ConvertEnum2OneValue(*my_enum, (TW_ONEVALUE *)data);
157     break;
158   case TWON_TWON(TWON_ARRAY, TWON_ARRAY):
159     size =
160         GetContainerSize(cap.ConType, my_array->ItemType, my_array->NumItems);
161     memcpy(data, my_array, size);
162     break;
163   case TWON_TWON(TWON_ONEVALUE, TWON_ONEVALUE):
164     memcpy(data, my_one, sizeof(TW_ONEVALUE));
165     break;
166   case TWON_TWON(TWON_ONEVALUE, TWON_RANGE):
167     ConvertOneValue2Range(*my_one, (TW_RANGE *)data);
168     break;
169   case TWON_TWON(TWON_ONEVALUE, TWON_ENUMERATION):
170     ConvertOneValue2Enum(*my_one, (TW_ENUMERATION *)data);
171     break;
172   case TWON_TWON(TWON_RANGE, TWON_RANGE):
173     memcpy(data, my_range, sizeof(TW_RANGE));
174     break;
175   case TWON_TWON(TWON_ENUMERATION, TWON_ARRAY):
176     ConvertEnum2Array(*my_enum, (TW_ARRAY *)data);
177     break;
178   default:
179     assert(0);
180     GLOBAL_UNLOCK(cap.hContainer);
181     GLOBAL_FREE(cap.hContainer);
182     return FALSE;
183   }
184   GLOBAL_UNLOCK(cap.hContainer);
185   GLOBAL_FREE(cap.hContainer);
186   return TRUE;
187 }
188 /*---------------------------------------------------------------------------*/
189 /*---------------------------------------------------------------------------*/
190 /*---------------------------------------------------------------------------*/
191 
192 /*---------------------------------------------------------------------------*/
ConvertOneValue2Range(TW_ONEVALUE one_value,TW_RANGE * range)193 static int ConvertOneValue2Range(TW_ONEVALUE one_value, TW_RANGE *range) {
194   range->ItemType     = one_value.ItemType;
195   range->MinValue     = one_value.Item;
196   range->MaxValue     = one_value.Item;
197   range->StepSize     = 0;
198   range->DefaultValue = one_value.Item;
199   range->CurrentValue = one_value.Item;
200   return TRUE;
201 }
202 /*---------------------------------------------------------------------------*/
ConvertEnumeration2Range(TW_ENUMERATION enumeration,TW_RANGE * range)203 static int ConvertEnumeration2Range(TW_ENUMERATION enumeration,
204                                     TW_RANGE *range) {
205   range->ItemType = enumeration.ItemType;
206   range->MinValue = enumeration.ItemList[0];
207   range->MaxValue = enumeration.ItemList[enumeration.NumItems - 1];
208   range->StepSize = (range->MaxValue - range->MinValue) / enumeration.NumItems;
209   if (range->MaxValue < range->MinValue) {
210     range->MaxValue = range->MinValue;
211     range->StepSize = 0;
212   }
213   range->DefaultValue = enumeration.ItemList[enumeration.DefaultIndex];
214   range->CurrentValue = enumeration.ItemList[enumeration.CurrentIndex];
215   return TRUE;
216 }
217 /*---------------------------------------------------------------------------*/
ConvertOneValue2Enum(TW_ONEVALUE one_value,TW_ENUMERATION * tw_enum)218 static int ConvertOneValue2Enum(TW_ONEVALUE one_value,
219                                 TW_ENUMERATION *tw_enum) {
220   tw_enum->ItemType     = one_value.ItemType;
221   tw_enum->NumItems     = 1;
222   tw_enum->CurrentIndex = 0; /* Current value is in ItemList[CurrentIndex] */
223   tw_enum->DefaultIndex = 0; /* Powerup value is in ItemList[DefaultIndex] */
224   tw_enum->ItemList[0]  = (TW_UINT8)one_value.Item;
225   return TRUE;
226 }
227 /*---------------------------------------------------------------------------*/
ConvertEnum2OneValue(TW_ENUMERATION tw_enum,TW_ONEVALUE * one_value)228 static int ConvertEnum2OneValue(TW_ENUMERATION tw_enum,
229                                 TW_ONEVALUE *one_value) {
230   unsigned char *base;
231   TW_UINT32 ofs;
232   TW_UINT32 itemSize;
233 
234   itemSize = DCItemSize[tw_enum.ItemType];
235   base     = tw_enum.ItemList;
236   ofs      = tw_enum.CurrentIndex * itemSize;
237 
238   one_value->ItemType = tw_enum.ItemType;
239   one_value->Item     = 0;
240   memcpy(&(one_value->Item), &(base[ofs]), itemSize);
241   return TRUE;
242 }
243 /*---------------------------------------------------------------------------*/
ConvertEnum2Array(TW_ENUMERATION tw_enum,TW_ARRAY * array)244 static int ConvertEnum2Array(TW_ENUMERATION tw_enum, TW_ARRAY *array) {
245   TW_UINT32 itemSize;
246   TW_UINT32 listSize;
247 
248   itemSize        = DCItemSize[tw_enum.ItemType];
249   listSize        = itemSize * tw_enum.NumItems;
250   array->ItemType = tw_enum.ItemType;
251   array->NumItems = tw_enum.NumItems;
252   memcpy(&(array->ItemList), &(tw_enum.ItemList), listSize);
253   return TRUE;
254 }
255 /*---------------------------------------------------------------------------*/
256 /*---------------------------------------------------------------------------*/
257 /*---------------------------------------------------------------------------*/
258 /*	      SET CAP							     */
259 /*---------------------------------------------------------------------------*/
TTWAIN_SetCap(TW_UINT16 cap_id,TW_UINT16 conType,TW_UINT16 itemType,TW_UINT32 * value)260 int TTWAIN_SetCap(TW_UINT16 cap_id, TW_UINT16 conType, TW_UINT16 itemType,
261                   TW_UINT32 *value) {
262   int rc = FALSE;
263   TUINT32 size;
264   TW_CAPABILITY *capability = 0;
265   TW_HANDLE capabilityH     = 0;
266   TW_ONEVALUE *container    = 0;
267   TW_HANDLE containerH      = 0;
268 
269   size       = GetContainerSize(conType, itemType, 1);
270   containerH = GLOBAL_ALLOC(GMEM_FIXED, size);
271   if (!containerH) goto done;
272   container = (TW_ONEVALUE *)GLOBAL_LOCK(containerH);
273 
274   container->ItemType = itemType;
275   container->Item     = *value;
276   capabilityH         = GLOBAL_ALLOC(GMEM_FIXED, sizeof(TW_CAPABILITY));
277   if (!capabilityH) {
278     GLOBAL_UNLOCK(containerH);
279     GLOBAL_FREE(containerH);
280     containerH = NULL;
281     goto done;
282   }
283 
284   capability             = (TW_CAPABILITY *)GLOBAL_LOCK(capabilityH);
285   capability->ConType    = conType;
286   capability->hContainer = containerH;
287 
288   if (TTWAIN_GetState() < TWAIN_SOURCE_OPEN) {
289     /*TTWAIN_ErrorBox("Setting capability in State < 4.");*/
290     TTWAIN_OpenSourceManager(0); /* Bring up to state 4 */
291                                  /*goto done;*/
292   }
293 
294   capability->Cap = cap_id; /* capability id */
295 
296   rc = (TTWAIN_DS(DG_CONTROL, DAT_CAPABILITY, MSG_SET, (TW_MEMREF)capability) ==
297         TWRC_SUCCESS);
298 
299 done:
300   if (containerH) {
301     GLOBAL_UNLOCK(containerH);
302     GLOBAL_FREE(containerH);
303   }
304 
305   if (capabilityH) {
306     GLOBAL_UNLOCK(capabilityH);
307     GLOBAL_FREE(capabilityH);
308   }
309   return rc;
310 }
311 /*---------------------------------------------------------------------------*/
GetContainerSize(int nFormat,unsigned twty,TW_UINT32 nItems)312 static TUINT32 GetContainerSize(int nFormat, unsigned twty, TW_UINT32 nItems) {
313   TUINT32 size;
314   switch (nFormat) {
315   case TWON_ONEVALUE:
316     size = sizeof(TW_ONEVALUE);
317     if (DCItemSize[twty] > sizeof(TW_UINT32)) {
318       size += DCItemSize[twty] - sizeof(TW_UINT32);
319     }
320     break;
321   case TWON_RANGE:
322     size = sizeof(TW_RANGE);
323     break;
324   case TWON_ENUMERATION:
325     size =
326         sizeof(TW_ENUMERATION) + DCItemSize[twty] * nItems - sizeof(TW_UINT8);
327     break;
328   case TWON_ARRAY:
329     size = sizeof(TW_ARRAY) + DCItemSize[twty] * nItems - sizeof(TW_UINT8);
330     break;
331   default:
332     size = 0;
333     break;
334   } /* switch */
335   return size;
336 }
337 /*---------------------------------------------------------------------------*/
338 
339 #ifdef __cplusplus
340 }
341 #endif
342