user32: Esperanto language update.
[wine/multimedia.git] / dlls / twain / dsm_ctrl.c
blobdce7add51b48223e6c3b64f3f891e8f27d76817a
1 /*
2 * TWAIN32 Source Manager
4 * Copyright 2000 Corel Corporation
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
23 #include <stdlib.h>
24 #include <stdarg.h>
25 #include <stdio.h>
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
29 #include "windef.h"
30 #include "winbase.h"
31 #include "twain.h"
32 #include "twain_i.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(twain);
37 /* DG_CONTROL/DAT_IDENTITY/MSG_CLOSEDS */
38 TW_UINT16 TWAIN_CloseDS (pTW_IDENTITY pOrigin, TW_MEMREF pData)
40 #ifndef HAVE_SANE
41 DSM_twCC = TWCC_NODS;
42 return TWRC_FAILURE;
43 #else
44 TW_UINT16 twRC = TWRC_SUCCESS;
45 pTW_IDENTITY pIdentity = (pTW_IDENTITY) pData;
46 activeDS *currentDS = NULL, *prevDS = NULL;
48 TRACE ("DG_CONTROL/DAT_IDENTITY/MSG_CLOSEDS\n");
50 for (currentDS = activeSources; currentDS; currentDS = currentDS->next)
52 if (currentDS->identity.Id == pIdentity->Id)
53 break;
54 prevDS = currentDS;
56 if (currentDS)
58 /* Only valid to close a data source if it is in state 4 */
59 if (currentDS->currentState == 4)
61 sane_close (currentDS->deviceHandle);
62 /* remove the data source from active data source list */
63 if (prevDS)
64 prevDS->next = currentDS->next;
65 else
66 activeSources = currentDS->next;
67 HeapFree (GetProcessHeap(), 0, currentDS);
68 twRC = TWRC_SUCCESS;
69 DSM_twCC = TWCC_SUCCESS;
71 else
73 twRC = TWRC_FAILURE;
74 DSM_twCC = TWCC_SEQERROR;
77 else
79 twRC = TWRC_FAILURE;
80 DSM_twCC = TWCC_NODS;
83 return twRC;
84 #endif
87 /* Sane returns device names that are longer than the 32 bytes allowed
88 by TWAIN. However, it colon separates them, and the last bit is
89 the most interesting. So we use the last bit, and add a signature
90 to ensure uniqueness */
91 #ifdef HAVE_SANE
92 static void copy_sane_short_name(const char *in, char *out, size_t outsize)
94 const char *p;
95 int signature = 0;
97 if (strlen(in) <= outsize - 1)
99 strcpy(out, in);
100 return;
103 for (p = in; *p; p++)
104 signature += *p;
106 p = strrchr(in, ':');
107 if (!p)
108 p = in;
109 else
110 p++;
112 if (strlen(p) > outsize - 7 - 1)
113 p += strlen(p) - (outsize - 7 - 1);
115 strcpy(out, p);
116 sprintf(out + strlen(out), "(%04X)", signature % 0x10000);
119 #endif
121 /* DG_CONTROL/DAT_IDENTITY/MSG_GETDEFAULT */
122 TW_UINT16 TWAIN_IdentityGetDefault (pTW_IDENTITY pOrigin, TW_MEMREF pData)
124 #ifndef HAVE_SANE
125 DSM_twCC = TWCC_NODS;
126 return TWRC_FAILURE;
127 #else
128 TW_UINT16 twRC = TWRC_SUCCESS;
129 pTW_IDENTITY pSourceIdentity = (pTW_IDENTITY) pData;
131 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_GETDEFAULT\n");
133 if (!device_list)
135 if ((sane_get_devices (&device_list, SANE_FALSE) != SANE_STATUS_GOOD))
137 DSM_twCC = TWCC_NODS;
138 return TWRC_FAILURE;
142 /* FIXME: the default device is not necessarily the first device. *
143 * Users should be able to choose the default device */
144 if (device_list && device_list[0])
146 pSourceIdentity->Id = DSM_sourceId ++;
147 copy_sane_short_name(device_list[0]->name, pSourceIdentity->ProductName, sizeof(pSourceIdentity->ProductName) - 1);
148 TRACE("got: %s (short [%s]), %s, %s\n", device_list[0]->name, pSourceIdentity->ProductName, device_list[0]->vendor, device_list[0]->model);
149 lstrcpynA (pSourceIdentity->Manufacturer, device_list[0]->vendor, sizeof(pSourceIdentity->Manufacturer) - 1);
150 lstrcpynA (pSourceIdentity->ProductFamily, device_list[0]->model, sizeof(pSourceIdentity->ProductFamily) - 1);
151 pSourceIdentity->ProtocolMajor = TWON_PROTOCOLMAJOR;
152 pSourceIdentity->ProtocolMinor = TWON_PROTOCOLMINOR;
154 twRC = TWRC_SUCCESS;
155 DSM_twCC = TWCC_SUCCESS;
158 else
160 twRC = TWRC_FAILURE;
161 DSM_twCC = TWCC_NODS;
164 return twRC;
165 #endif
168 /* DG_CONTROL/DAT_IDENTITY/MSG_GETFIRST */
169 TW_UINT16 TWAIN_IdentityGetFirst (pTW_IDENTITY pOrigin, TW_MEMREF pData)
171 #ifndef HAVE_SANE
172 DSM_twCC = TWCC_NODS;
173 return TWRC_FAILURE;
174 #else
175 TW_UINT16 twRC = TWRC_SUCCESS;
176 pTW_IDENTITY pSourceIdentity = (pTW_IDENTITY) pData;
177 SANE_Status status;
179 TRACE ("DG_CONTROL/DAT_IDENTITY/MSG_GETFIRST\n");
181 device_list = NULL;
182 status = sane_get_devices (&device_list, SANE_FALSE);
183 if (status == SANE_STATUS_GOOD)
185 if (device_list[0])
187 pSourceIdentity->Id = DSM_sourceId ++;
188 copy_sane_short_name(device_list[0]->name, pSourceIdentity->ProductName, sizeof(pSourceIdentity->ProductName) - 1);
189 TRACE("got: %s (short [%s]), %s, %s\n", device_list[0]->name, pSourceIdentity->ProductName, device_list[0]->vendor, device_list[0]->model);
190 lstrcpynA (pSourceIdentity->Manufacturer, device_list[0]->vendor, sizeof(pSourceIdentity->Manufacturer) - 1);
191 lstrcpynA (pSourceIdentity->ProductFamily, device_list[0]->model, sizeof(pSourceIdentity->ProductFamily) - 1);
192 pSourceIdentity->ProtocolMajor = TWON_PROTOCOLMAJOR;
193 pSourceIdentity->ProtocolMinor = TWON_PROTOCOLMINOR;
195 DSM_currentDevice = 1;
196 twRC = TWRC_SUCCESS;
197 DSM_twCC = TWCC_SUCCESS;
199 else
201 TRACE("got empty device list\n");
202 twRC = TWRC_FAILURE;
203 DSM_twCC = TWCC_NODS;
206 else if (status == SANE_STATUS_NO_MEM)
208 twRC = TWRC_FAILURE;
209 DSM_twCC = TWCC_LOWMEMORY;
211 else
213 WARN("sane_get_devices() failed: %s\n", sane_strstatus (status));
214 twRC = TWRC_FAILURE;
215 DSM_twCC = TWCC_NODS;
218 return twRC;
219 #endif
222 /* DG_CONTROL/DAT_IDENTITY/MSG_GETNEXT */
223 TW_UINT16 TWAIN_IdentityGetNext (pTW_IDENTITY pOrigin, TW_MEMREF pData)
225 #ifndef HAVE_SANE
226 DSM_twCC = TWCC_SUCCESS;
227 return TWRC_ENDOFLIST;
228 #else
229 TW_UINT16 twRC = TWRC_SUCCESS;
230 pTW_IDENTITY pSourceIdentity = (pTW_IDENTITY) pData;
232 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_GETNEXT\n");
234 if (device_list && device_list[DSM_currentDevice] &&
235 device_list[DSM_currentDevice]->name &&
236 device_list[DSM_currentDevice]->vendor &&
237 device_list[DSM_currentDevice]->model)
239 pSourceIdentity->Id = DSM_sourceId ++;
240 copy_sane_short_name(device_list[DSM_currentDevice]->name, pSourceIdentity->ProductName, sizeof(pSourceIdentity->ProductName) - 1);
241 TRACE("got: %s (short [%s]), %s, %s\n", device_list[DSM_currentDevice]->name, pSourceIdentity->ProductName, device_list[DSM_currentDevice]->vendor, device_list[DSM_currentDevice]->model);
242 lstrcpynA (pSourceIdentity->Manufacturer, device_list[DSM_currentDevice]->vendor, sizeof(pSourceIdentity->Manufacturer) - 1);
243 lstrcpynA (pSourceIdentity->ProductFamily, device_list[DSM_currentDevice]->model, sizeof(pSourceIdentity->ProductFamily) - 1);
244 pSourceIdentity->ProtocolMajor = TWON_PROTOCOLMAJOR;
245 pSourceIdentity->ProtocolMinor = TWON_PROTOCOLMINOR;
246 DSM_currentDevice ++;
248 twRC = TWRC_SUCCESS;
249 DSM_twCC = TWCC_SUCCESS;
251 else
253 DSM_twCC = TWCC_SUCCESS;
254 twRC = TWRC_ENDOFLIST;
257 return twRC;
258 #endif
261 /* DG_CONTROL/DAT_IDENTITY/MSG_OPENDS */
262 TW_UINT16 TWAIN_OpenDS (pTW_IDENTITY pOrigin, TW_MEMREF pData)
264 #ifndef HAVE_SANE
265 DSM_twCC = TWCC_NODS;
266 return TWRC_FAILURE;
267 #else
268 TW_UINT16 twRC = TWRC_SUCCESS, i = 0;
269 pTW_IDENTITY pIdentity = (pTW_IDENTITY) pData;
270 TW_STR32 shortname;
271 activeDS *newSource;
272 SANE_Status status;
274 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_OPENDS\n");
276 if (DSM_currentState != 3)
278 DSM_twCC = TWCC_SEQERROR;
279 return TWRC_FAILURE;
282 if (!device_list &&
283 (sane_get_devices (&device_list, SANE_FALSE) != SANE_STATUS_GOOD))
285 DSM_twCC = TWCC_NODS;
286 return TWRC_FAILURE;
289 if (pIdentity->ProductName[0] != '\0')
291 /* Make sure the source to be opened exists in the device list */
292 for (i = 0; device_list[i]; i ++)
294 copy_sane_short_name(device_list[i]->name, shortname, sizeof(shortname) - 1);
295 if (strcmp (shortname, pIdentity->ProductName) == 0)
296 break;
301 if (device_list[i])
303 /* the source is found in the device list */
304 newSource = HeapAlloc (GetProcessHeap(), 0, sizeof (activeDS));
305 if (newSource)
307 newSource->deviceIndex = i;
308 status = sane_open(device_list[i]->name,&newSource->deviceHandle);
309 if (status == SANE_STATUS_GOOD)
311 /* Assign name and id for the opened data source */
312 lstrcpynA (pIdentity->ProductName, shortname, sizeof(pIdentity->ProductName) - 1);
313 pIdentity->Id = DSM_sourceId ++;
314 /* add the data source to an internal active source list */
315 newSource->next = activeSources;
316 newSource->identity.Id = pIdentity->Id;
317 strcpy (newSource->identity.ProductName, pIdentity->ProductName);
318 newSource->currentState = 4; /*transition into state 4*/
319 newSource->twCC = TWCC_SUCCESS;
320 activeSources = newSource;
321 twRC = TWRC_SUCCESS;
322 DSM_twCC = TWCC_SUCCESS;
324 else
326 twRC = TWRC_FAILURE;
327 DSM_twCC = TWCC_OPERATIONERROR;
330 else
332 twRC = TWRC_FAILURE;
333 DSM_twCC = TWCC_LOWMEMORY;
336 else
338 twRC = TWRC_FAILURE;
339 DSM_twCC = TWCC_NODS;
342 return twRC;
343 #endif
346 /* DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT */
347 TW_UINT16 TWAIN_UserSelect (pTW_IDENTITY pOrigin, TW_MEMREF pData)
349 #ifndef HAVE_SANE
350 return TWRC_SUCCESS;
351 #else
352 TW_UINT16 twRC = TWRC_SUCCESS;
354 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT\n");
356 /* FIXME: we should replace xscanimage with our own User Select UI */
357 system("xscanimage");
359 DSM_twCC = TWCC_SUCCESS;
360 return twRC;
361 #endif
364 /* DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM */
365 TW_UINT16 TWAIN_CloseDSM (pTW_IDENTITY pOrigin, TW_MEMREF pData)
367 #ifndef HAVE_SANE
368 return TWRC_FAILURE;
369 #else
370 TW_UINT16 twRC = TWRC_SUCCESS;
371 activeDS *currentDS = activeSources, *nextDS;
373 TRACE("DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM\n");
375 if (DSM_currentState == 3)
377 sane_exit ();
378 DSM_initialized = FALSE;
379 DSM_parentHWND = 0;
380 DSM_currentState = 2;
382 /* If there are data sources still open, close them now. */
383 while (currentDS != NULL)
385 nextDS = currentDS->next;
386 sane_close (currentDS->deviceHandle);
387 HeapFree (GetProcessHeap(), 0, currentDS);
388 currentDS = nextDS;
390 activeSources = NULL;
391 DSM_twCC = TWCC_SUCCESS;
392 twRC = TWRC_SUCCESS;
394 else
396 DSM_twCC = TWCC_SEQERROR;
397 twRC = TWRC_FAILURE;
400 return twRC;
401 #endif
404 /* DG_CONTROL/DAT_PARENT/MSG_OPENDSM */
405 TW_UINT16 TWAIN_OpenDSM (pTW_IDENTITY pOrigin, TW_MEMREF pData)
407 #ifndef HAVE_SANE
408 return TWRC_FAILURE;
409 #else
410 TW_UINT16 twRC = TWRC_SUCCESS;
411 SANE_Status status;
412 SANE_Int version_code;
414 TRACE("DG_CONTROL/DAT_PARENT/MSG_OPENDSM\n");
416 if (DSM_currentState == 2)
418 if (!DSM_initialized)
420 DSM_initialized = TRUE;
421 status = sane_init (&version_code, NULL);
422 device_list = NULL;
423 DSM_currentDevice = 0;
424 DSM_sourceId = 0;
426 DSM_parentHWND = *(TW_HANDLE*)pData;
427 DSM_currentState = 3; /* transition to state 3 */
428 DSM_twCC = TWCC_SUCCESS;
429 twRC = TWRC_SUCCESS;
431 else
433 /* operation invoked in invalid state */
434 DSM_twCC = TWCC_SEQERROR;
435 twRC = TWRC_FAILURE;
438 return twRC;
439 #endif
442 /* DG_CONTROL/DAT_STATUS/MSG_GET */
443 TW_UINT16 TWAIN_GetDSMStatus (pTW_IDENTITY pOrigin, TW_MEMREF pData)
445 pTW_STATUS pSourceStatus = (pTW_STATUS) pData;
447 TRACE ("DG_CONTROL/DAT_STATUS/MSG_GET\n");
449 pSourceStatus->ConditionCode = DSM_twCC;
450 DSM_twCC = TWCC_SUCCESS; /* clear the condition code */
452 return TWRC_SUCCESS;