utf: spreadsheet 2
[scilab.git] / scilab / modules / spreadsheet / sci_gateway / cpp / sci_xls_open.cpp
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2005-2008 - INRIA - Serge STEER <serge.steer@inria.fr>
4 * Copyright (C) 2005-2008 - INRIA - Pierrick MODE
5 * Copyright (C) 2007-2008 - INRIA - Allan CORNET <allan.cornet@inria.fr>
6 * Copyright (C) 2011 - DIGITEO - Cedric DELAMARRE
7 *
8 * This file must be used under the terms of the CeCILL.
9 * This source file is licensed as described in the file COPYING, which
10 * you should have received as part of this distribution.  The terms
11 * are also available at
12 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
13 *
14 */
15 /*--------------------------------------------------------------------------*/
16
17 #include "spreadsheet_gw.hxx"
18 #include "function.hxx"
19 #include "string.hxx"
20 #include "double.hxx"
21
22 extern "C"
23 {
24 #include "sci_malloc.h"
25 #include "localization.h"
26 #include "Scierror.h"
27 #include "sciprint.h"
28 #include "xls.h"
29 #include "ole.h"
30 #include "ripole.h"
31 #include "expandPathVariable.h"
32 #include "mopen.h"
33 #include "sci_tmpdir.h"
34 #include "freeArrayOfString.h"
35 #include "FileExist.h"
36 }
37 /*--------------------------------------------------------------------------*/
38 static const char* xls_basename(const char* name);
39 /*--------------------------------------------------------------------------*/
40 types::Function::ReturnValue sci_xls_open(types::typed_list &in, int _iRetCount, types::typed_list &out)
41 {
42
43 #undef IN
44 #define max_char_xls_open 256
45
46     // input
47     types::String* pStrPath = NULL;
48     char* filename_IN    = NULL;
49
50     char TMP[max_char_xls_open];
51     char* TMPDIR = NULL;
52
53     char **sst          = NULL;
54     char **Sheetnames   = NULL;
55
56     int iId     = 0;
57     int iSwap   = 0;
58     int iErr    = 0;
59     int ns      = 0;
60     int* Abspos = NULL;
61     int nsheets = 0;
62
63     char sep[2];
64 #ifdef _MSC_VER
65     sep[0] = '\\';
66 #else
67     sep[0] = '/';
68 #endif
69     sep[1] = '\0';
70
71     // *** check the minimal number of input args. ***
72     if (in.size() > 1)
73     {
74         Scierror(77, _("%s: Wrong number of input argument(s): %d expected.\n"), "xls_open", 1);
75         return types::Function::Error;
76     }
77
78     // *** check number of output args according the methode. ***
79     if (_iRetCount != 4)
80     {
81         Scierror(78, _("%s: Wrong number of output argument(s): %d expected.\n"), "xls_open", 4);
82         return types::Function::Error;
83     }
84
85     // *** check type of input args and get it. ***
86     // path
87     if (in[0]->isString() == false)
88     {
89         Scierror(999, _("%s: Wrong type for input argument #%d : string expected.\n"), "xls_open", 1);
90         return types::Function::Error;
91     }
92
93     pStrPath = in[0]->getAs<types::String>();
94     filename_IN = expandPathVariable(pStrPath->get(0));
95
96     // *** Perform operation. ***
97     if (filename_IN)
98     {
99         /* bug 5615 */
100         /* remove blank characters @ the end */
101         int len = (int)strlen(filename_IN);
102         int i = 0;
103
104         if (len >= 1)
105         {
106             for (i = len - 1; i >= 0  ; i--)
107             {
108                 if (filename_IN[i] != ' ')
109                 {
110                     break;
111                 }
112
113                 filename_IN[i] = '\0';
114             }
115         }
116
117         if (FileExist(filename_IN) == false)
118         {
119             Scierror(999, _("The file %s does not exist.\n"), filename_IN);
120             return types::Function::Error;
121         }
122     }
123
124     TMPDIR = getTMPDIR();
125     strcpy(TMP, TMPDIR);
126
127     if (TMPDIR)
128     {
129         FREE(TMPDIR);
130         TMPDIR = NULL;
131     }
132
133     strcat(TMP, sep);
134     strcat(TMP, xls_basename(filename_IN));
135
136     int result = ripole(filename_IN, TMP, 0, 0);
137
138     if (result != OLE_OK)
139     {
140         if (result == OLEER_NO_INPUT_FILE)
141         {
142             Scierror(999, _("%s: The file %s does not exist.\n"), "xls_open", filename_IN);
143         }
144         else if (result == OLEER_NOT_OLE_FILE ||
145                  result == OLEER_INSANE_OLE_FILE ||
146                  result == OLEER_LOADFAT_BAD_BOUNDARY ||
147                  result == OLEER_MINIFAT_READ_FAIL ||
148                  result == OLEER_PROPERTIES_READ_FAIL)
149         {
150             Scierror(999, _("%s: File %s is not an ole2 file.\n"), "xls_open", filename_IN);
151         }
152         else if (result == -1)
153         {
154             Scierror(999, _("%s: Cannot open file %s.\n"), "xls_open", filename_IN);
155         }
156
157         if (filename_IN)
158         {
159             FREE(filename_IN);
160             filename_IN = NULL;
161         }
162
163         return types::Function::Error;
164     }
165
166     strcat(TMP, sep);
167     strcat(TMP, "Workbook");
168
169     iErr = mopen(TMP, "rb", iSwap, &iId);
170     if (iErr != MOPEN_NO_ERROR)
171     {
172         sciprint(_("There is no xls stream in the ole2 file %s.\n"), filename_IN);
173         if (iErr == MOPEN_CAN_NOT_OPEN_FILE)
174         {
175             Scierror(999, _("%s: Cannot open file %s.\n"), "xls_open", TMP);
176         }
177         else if (iErr == MOPEN_INVALID_FILENAME)
178         {
179             Scierror(999, _("%s: invalid filename.\n"), "xls_open");
180         }
181         else //if(iErr == MOPEN_INVALID_STATUS)
182         {
183             Scierror(999, _("%s: invalid status.\n"), "xls_open");
184         }
185
186         FREE(filename_IN);
187         return types::Function::Error;
188     }
189
190     if (filename_IN)
191     {
192         FREE(filename_IN);
193         filename_IN = NULL;
194     }
195
196     xls_open(&iErr, &iId, &sst , &ns, &Sheetnames, &Abspos, &nsheets);
197
198     /*return *err:
199     0 = OK
200     1 = not an OLE file
201     2 = no Workbook included
202     3 = memory allocation problem
203     4 = incorrect file
204     5 = not a BIFF8 xls file
205     */
206     switch (iErr)
207     {
208         case 0:
209             /* OK */
210             break;
211
212         case 1:
213             Scierror(999, _("%s: Not an ole2 file.\n"), "xls_open");
214             return types::Function::Error;
215             break;
216
217         case 2:
218             Scierror(999, _("%s: The file has no Workbook directory.\n"), "xls_open");
219             return types::Function::Error;
220             break;
221
222         case 3:
223             Scierror(999, _("%s: No more memory.\n"), "xls_open");
224             return types::Function::Error;
225             break;
226
227         case 4:
228             Scierror(990, _("%s: Incorrect or corrupted file.\n"), "xls_open");
229             return types::Function::Error;
230             break;
231
232         case 5:
233             Scierror(999, _("%s: Only BIFF8 file format is handled.\n"), "xls_open");
234             return types::Function::Error;
235             break;
236
237         default :
238             break;
239     }
240
241     // *** Return result in Scilab. ***
242     types::Double* pDblId = new types::Double(static_cast<double>(iId));
243     out.push_back(pDblId);
244
245     if (ns)
246     {
247         /* Create a typed list to return the properties */
248         types::String* pStrSst = new types::String(1, ns);
249         for (int i = 0; i < ns; i++)
250         {
251             pStrSst->set(i, sst[i]);
252         }
253         freeArrayOfString(sst, ns);
254         out.push_back(pStrSst);
255     }
256     else
257     {
258         out.push_back(types::Double::Empty());
259     }
260
261     if (nsheets)
262     {
263         /* Create a typed list to return the properties */
264         types::String* pStrSheets = new types::String(1, nsheets);
265         for (int i = 0; i < nsheets; i++)
266         {
267             pStrSheets->set(i, Sheetnames[i]);
268         }
269         freeArrayOfString(Sheetnames, nsheets);
270         out.push_back(pStrSheets);
271
272         if (Abspos)
273         {
274             types::Double* pDblAbsPos = new types::Double(1, nsheets);
275             for (int i = 0; i < nsheets; i++)
276             {
277                 pDblAbsPos->set(i, static_cast<double>(Abspos[i]));
278             }
279             out.push_back(pDblAbsPos);
280             free(Abspos);
281             Abspos = NULL;
282         }
283         else
284         {
285             out.push_back(types::Double::Empty());
286         }
287     }
288     else
289     {
290         out.push_back(types::Double::Empty());
291         out.push_back(types::Double::Empty());
292     }
293
294     return types::Function::OK;
295 }
296 /*--------------------------------------------------------------------------*/
297 static const char* xls_basename(const char* name)
298 {
299     const char* base = NULL;
300 #ifdef _MSC_VER
301     base = strrchr(name, '\\');
302 #else
303     base = strrchr(name, '/');
304 #endif
305     return base ? base + 1 : name;
306 }
307 /*--------------------------------------------------------------------------*/