Removed trailing whitespace.
[wine] / dlls / twain / dsm_ctrl.c
1 /*
2  * TWAIN32 Source Manager
3  *
4  * Copyright 2000 Corel Corporation
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "config.h"
22
23 #include <stdlib.h>
24 #include "winbase.h"
25 #include "twain.h"
26 #include "twain_i.h"
27 #include "wine/debug.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(twain);
30
31 /* DG_CONTROL/DAT_IDENTITY/MSG_CLOSEDS */
32 TW_UINT16 TWAIN_CloseDS (pTW_IDENTITY pOrigin, TW_MEMREF pData)
33 {
34 #ifndef HAVE_SANE
35     DSM_twCC = TWCC_NODS;
36     return TWRC_FAILURE;
37 #else
38     TW_UINT16 twRC = TWRC_SUCCESS;
39     pTW_IDENTITY pIdentity = (pTW_IDENTITY) pData;
40     activeDS *currentDS = NULL, *prevDS = NULL;
41
42     TRACE ("DG_CONTROL/DAT_IDENTITY/MSG_CLOSEDS\n");
43
44     for (currentDS = activeSources; currentDS; currentDS = currentDS->next)
45     {
46         if (currentDS->identity.Id == pIdentity->Id)
47             break;
48         prevDS = currentDS;
49     }
50     if (currentDS)
51     {
52         /* Only valid to close a data source if it is in state 4 */
53         if (currentDS->currentState == 4)
54         {
55             sane_close (currentDS->deviceHandle);
56             /* remove the data source from active data source list */
57             if (prevDS)
58                 prevDS->next = currentDS->next;
59             else
60                 activeSources = currentDS->next;
61             HeapFree (GetProcessHeap(), 0, currentDS);
62             twRC = TWRC_SUCCESS;
63             DSM_twCC = TWCC_SUCCESS;
64         }
65         else
66         {
67             twRC = TWRC_FAILURE;
68             DSM_twCC = TWCC_SEQERROR;
69         }
70     }
71     else
72     {
73         twRC = TWRC_FAILURE;
74         DSM_twCC = TWCC_NODS;
75     }
76
77     return twRC;
78 #endif
79 }
80
81 /* DG_CONTROL/DAT_IDENTITY/MSG_GETDEFAULT */
82 TW_UINT16 TWAIN_IdentityGetDefault (pTW_IDENTITY pOrigin, TW_MEMREF pData)
83 {
84 #ifndef HAVE_SANE
85     DSM_twCC = TWCC_NODS;
86     return TWRC_FAILURE;
87 #else
88     TW_UINT16 twRC = TWRC_SUCCESS;
89     pTW_IDENTITY pSourceIdentity = (pTW_IDENTITY) pData;
90
91     TRACE("DG_CONTROL/DAT_IDENTITY/MSG_GETDEFAULT\n");
92
93     if (!device_list)
94     {
95         if ((sane_get_devices (&device_list, SANE_FALSE) != SANE_STATUS_GOOD))
96         {
97             DSM_twCC = TWCC_NODS;
98             return TWRC_FAILURE;
99         }
100     }
101
102     /* FIXME: the default device is not necessarily the first device.  *
103      * Users should be able to choose the default device               */
104     if (device_list && device_list[0])
105     {
106         pSourceIdentity->Id = DSM_sourceId ++;
107         strcpy (pSourceIdentity->ProductName, device_list[0]->name);
108         strcpy (pSourceIdentity->Manufacturer, device_list[0]->vendor);
109         strcpy (pSourceIdentity->ProductFamily, device_list[0]->model);
110         pSourceIdentity->ProtocolMajor = TWON_PROTOCOLMAJOR;
111         pSourceIdentity->ProtocolMinor = TWON_PROTOCOLMINOR;
112
113         twRC = TWRC_SUCCESS;
114         DSM_twCC = TWCC_SUCCESS;
115     }
116     else
117     {
118         twRC = TWRC_FAILURE;
119         DSM_twCC = TWCC_NODS;
120     }
121
122     return twRC;
123 #endif
124 }
125
126 /* DG_CONTROL/DAT_IDENTITY/MSG_GETFIRST */
127 TW_UINT16 TWAIN_IdentityGetFirst (pTW_IDENTITY pOrigin, TW_MEMREF pData)
128 {
129 #ifndef HAVE_SANE
130     DSM_twCC = TWCC_NODS;
131     return TWRC_FAILURE;
132 #else
133     TW_UINT16 twRC = TWRC_SUCCESS;
134     pTW_IDENTITY pSourceIdentity;/* = (pTW_IDENTITY) pData;*/
135     SANE_Status status;
136
137     TRACE ("DG_CONTROL/DAT_IDENTITY/MSG_GETFIRST\n");
138
139     status = sane_get_devices (&device_list, SANE_FALSE);
140     if (status == SANE_STATUS_GOOD)
141     {
142         if (device_list[0])
143         {
144             pSourceIdentity->Id = DSM_sourceId ++;
145             strcpy (pSourceIdentity->ProductName, device_list[0]->name);
146             strcpy (pSourceIdentity->Manufacturer, device_list[0]->vendor);
147             strcpy (pSourceIdentity->ProductFamily, device_list[0]->model);
148             pSourceIdentity->ProtocolMajor = TWON_PROTOCOLMAJOR;
149             pSourceIdentity->ProtocolMinor = TWON_PROTOCOLMINOR;
150         }
151         DSM_currentDevice = 1;
152         twRC = TWRC_SUCCESS;
153         DSM_twCC = TWCC_SUCCESS;
154     }
155     else if (status == SANE_STATUS_NO_MEM)
156     {
157         twRC = TWRC_FAILURE;
158         DSM_twCC = TWCC_LOWMEMORY;
159     }
160     else
161     {
162         WARN("sane_get_devices() failed: %s\n", sane_strstatus (status));
163         twRC = TWRC_FAILURE;
164         DSM_twCC = TWCC_NODS;
165     }
166
167     return twRC;
168 #endif
169 }
170
171 /* DG_CONTROL/DAT_IDENTITY/MSG_GETNEXT */
172 TW_UINT16 TWAIN_IdentityGetNext (pTW_IDENTITY pOrigin, TW_MEMREF pData)
173 {
174 #ifndef HAVE_SANE
175     DSM_twCC = TWCC_SUCCESS;
176     return TWRC_ENDOFLIST;
177 #else
178     TW_UINT16 twRC = TWRC_SUCCESS;
179     pTW_IDENTITY pSourceIdentity = (pTW_IDENTITY) pData;
180
181     TRACE("DG_CONTROL/DAT_IDENTITY/MSG_GETNEXT\n");
182
183     if (device_list && device_list[DSM_currentDevice])
184     {
185         pSourceIdentity->Id = DSM_sourceId ++;
186         strcpy (pSourceIdentity->ProductName, device_list[DSM_currentDevice]->name);
187         strcpy (pSourceIdentity->Manufacturer, device_list[DSM_currentDevice]->vendor);
188         strcpy (pSourceIdentity->ProductFamily, device_list[DSM_currentDevice]->model);
189         pSourceIdentity->ProtocolMajor = TWON_PROTOCOLMAJOR;
190         pSourceIdentity->ProtocolMinor = TWON_PROTOCOLMINOR;
191         DSM_currentDevice ++;
192
193         twRC = TWRC_SUCCESS;
194         DSM_twCC = TWCC_SUCCESS;
195     }
196     else
197     {
198         DSM_twCC = TWCC_SUCCESS;
199         twRC = TWRC_ENDOFLIST;
200     }
201
202     return twRC;
203 #endif
204 }
205
206 /* DG_CONTROL/DAT_IDENTITY/MSG_OPENDS */
207 TW_UINT16 TWAIN_OpenDS (pTW_IDENTITY pOrigin, TW_MEMREF pData)
208 {
209 #ifndef HAVE_SANE
210     DSM_twCC = TWCC_NODS;
211     return TWRC_FAILURE;
212 #else
213     TW_UINT16 twRC = TWRC_SUCCESS, i = 0;
214     pTW_IDENTITY pIdentity = (pTW_IDENTITY) pData;
215     activeDS *newSource;
216     SANE_Status status;
217
218     TRACE("DG_CONTROL/DAT_IDENTITY/MSG_OPENDS\n");
219
220     if (DSM_currentState != 3)
221     {
222         DSM_twCC = TWCC_SEQERROR;
223         return TWRC_FAILURE;
224     }
225
226     if (!device_list &&
227        (sane_get_devices (&device_list, SANE_FALSE) != SANE_STATUS_GOOD))
228     {
229         DSM_twCC = TWCC_NODS;
230         return TWRC_FAILURE;
231     }
232
233     if (pIdentity->ProductName[0] != '\0')
234     {
235         /* Make sure the source to be open exists in the device list */
236         for (i = 0; device_list[i]; i ++)
237         {
238             if (strcmp (device_list[i]->name, pIdentity->ProductName) == 0)
239                 break;
240         }
241     }
242
243     if (device_list[i])
244     {
245         /* the source is found in the device list */
246         newSource = HeapAlloc (GetProcessHeap(), 0, sizeof (activeDS));
247         if (newSource)
248         {
249             status = sane_open(device_list[i]->name,&newSource->deviceHandle);
250             if (status == SANE_STATUS_GOOD)
251             {
252                 /* Assign name and id for the opened data source */
253                 strcpy (pIdentity->ProductName, device_list[i]->name);
254                 pIdentity->Id = DSM_sourceId ++;
255                 /* add the data source to an internal active source list */
256                 newSource->next = activeSources;
257                 newSource->identity.Id = pIdentity->Id;
258                 strcpy (newSource->identity.ProductName, pIdentity->ProductName);
259                 newSource->currentState = 4; /*transition into state 4*/
260                 newSource->twCC = TWCC_SUCCESS;
261                 activeSources = newSource;
262                 twRC = TWRC_SUCCESS;
263                 DSM_twCC = TWCC_SUCCESS;
264             }
265             else
266             {
267                 twRC = TWRC_FAILURE;
268                 DSM_twCC = TWCC_OPERATIONERROR;
269             }
270         }
271         else
272         {
273             twRC = TWRC_FAILURE;
274             DSM_twCC = TWCC_LOWMEMORY;
275         }
276     }
277     else
278     {
279         twRC = TWRC_FAILURE;
280         DSM_twCC = TWCC_NODS;
281     }
282
283     return twRC;
284 #endif
285 }
286
287 /* DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT */
288 TW_UINT16 TWAIN_UserSelect (pTW_IDENTITY pOrigin, TW_MEMREF pData)
289 {
290 #ifndef HAVE_SANE
291     return TWRC_SUCCESS;
292 #else
293     TW_UINT16 twRC = TWRC_SUCCESS;
294
295     TRACE("DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT\n");
296
297     /* FIXME: we should replace xscanimage with our own  User Select UI */
298     system("xscanimage");
299
300     DSM_twCC = TWCC_SUCCESS;
301     return twRC;
302 #endif
303 }
304
305 /* DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM */
306 TW_UINT16 TWAIN_CloseDSM (pTW_IDENTITY pOrigin, TW_MEMREF pData)
307 {
308 #ifndef HAVE_SANE
309     return TWRC_FAILURE;
310 #else
311     TW_UINT16 twRC = TWRC_SUCCESS;
312     activeDS *currentDS = activeSources, *nextDS;
313
314     TRACE("DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM\n");
315
316     if (DSM_currentState == 3)
317     {
318         sane_exit ();
319         DSM_initialized = FALSE;
320         DSM_parentHWND = 0;
321         DSM_currentState = 2;
322
323         /* If there are data sources still open, close them now. */
324         while (currentDS != NULL)
325         {
326             nextDS = currentDS->next;
327             sane_close (currentDS->deviceHandle);
328             HeapFree (GetProcessHeap(), 0, currentDS);
329             currentDS = nextDS;
330         }
331         activeSources = NULL;
332         DSM_twCC = TWCC_SUCCESS;
333         twRC = TWRC_SUCCESS;
334     }
335     else
336     {
337         DSM_twCC = TWCC_SEQERROR;
338         twRC = TWRC_FAILURE;
339     }
340
341     return twRC;
342 #endif
343 }
344
345 /* DG_CONTROL/DAT_PARENT/MSG_OPENDSM */
346 TW_UINT16 TWAIN_OpenDSM (pTW_IDENTITY pOrigin, TW_MEMREF pData)
347 {
348 #ifndef HAVE_SANE
349     return TWRC_FAILURE;
350 #else
351     TW_UINT16 twRC = TWRC_SUCCESS;
352     SANE_Status status;
353     SANE_Int version_code;
354
355     TRACE("DG_CONTROL/DAT_PARENT/MSG_OPENDSM\n");
356
357     if (DSM_currentState == 2)
358     {
359         if (!DSM_initialized)
360         {
361             DSM_initialized = TRUE;
362             status = sane_init (&version_code, NULL);
363             device_list = NULL;
364             DSM_currentDevice = 0;
365             DSM_sourceId = 0;
366         }
367         DSM_parentHWND = *(HWND*)pData;
368         DSM_currentState = 3; /* transition to state 3 */
369         DSM_twCC = TWCC_SUCCESS;
370         twRC = TWRC_SUCCESS;
371     }
372     else
373     {
374         /* operation invoked in invalid state */
375         DSM_twCC = TWCC_SEQERROR;
376         twRC = TWRC_FAILURE;
377     }
378
379     return twRC;
380 #endif
381 }
382
383 /* DG_CONTROL/DAT_STATUS/MSG_GET */
384 TW_UINT16 TWAIN_GetDSMStatus (pTW_IDENTITY pOrigin, TW_MEMREF pData)
385 {
386     pTW_STATUS pSourceStatus = (pTW_STATUS) pData;
387
388     TRACE ("DG_CONTROL/DAT_STATUS/MSG_GET\n");
389
390     pSourceStatus->ConditionCode = DSM_twCC;
391     DSM_twCC = TWCC_SUCCESS;  /* clear the condition code */
392
393     return TWRC_SUCCESS;
394 }
395