1 /* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */
2 /* AbiWord
3 * Copyright (C) 2001 Dom Lachowicz
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301 USA.
19 */
20
21 #include <stdio.h>
22
23 #include "ut_Script.h"
24 #include "ut_string.h"
25 #include "ut_vector.h"
26 #include "ut_debugmsg.h"
27 #include "ut_assert.h"
28 #include "ut_misc.h"
29
30 /************************************************************************/
31 /************************************************************************/
32
UT_ScriptSniffer()33 UT_ScriptSniffer::UT_ScriptSniffer()
34 : m_type (-1)
35 {
36 }
37
~UT_ScriptSniffer()38 UT_ScriptSniffer::~UT_ScriptSniffer()
39 {
40 }
41
42 /************************************************************************/
43 /************************************************************************/
44
UT_Script()45 UT_Script::UT_Script ()
46 {
47 }
48
~UT_Script()49 UT_Script::~UT_Script()
50 {
51 }
52
53 /************************************************************************/
54 /************************************************************************/
55 UT_ScriptLibrary * UT_ScriptLibrary::m_pInstance = NULL;
56
UT_ScriptLibrary()57 UT_ScriptLibrary::UT_ScriptLibrary ()
58 : mSniffers (new UT_GenericVector<UT_ScriptSniffer *>(5)),
59 m_stErrMsg("")
60 {
61 m_pInstance = this;
62 UT_DEBUGMSG(("Construct a scriptlibrary %p \n",this));
63 }
64
~UT_ScriptLibrary()65 UT_ScriptLibrary::~UT_ScriptLibrary ()
66 {
67 UT_DEBUGMSG(("Delete the scriptlibrary %p \n",this));
68 DELETEP(mSniffers);
69 }
70
instance()71 UT_ScriptLibrary * UT_ScriptLibrary::instance ()
72 {
73 return m_pInstance;
74 }
75
execute(const char * script,UT_ScriptIdType type)76 UT_Error UT_ScriptLibrary::execute (const char * script,
77 UT_ScriptIdType type )
78 {
79 UT_Script* pScript = NULL;
80 UT_ScriptIdType scriptId = -1;
81
82 UT_Error err = UT_OK;
83
84 if ((err = constructScript(script, type, &pScript, &scriptId)) == UT_OK)
85 {
86 if ((err = pScript->execute(script)) != UT_OK)
87 {
88 UT_DEBUGMSG(("Error executing script: %d\n", err));
89 errmsg(pScript->errmsg());
90 }
91
92 DELETEP(pScript);
93 }
94
95 return err;
96 }
97
getNumScripts() const98 UT_uint32 UT_ScriptLibrary::getNumScripts () const
99 {
100 return mSniffers->size ();
101 }
102
registerScript(UT_ScriptSniffer * s)103 void UT_ScriptLibrary::registerScript ( UT_ScriptSniffer * s )
104 {
105 UT_sint32 ndx = 0;
106 UT_Error err = mSniffers->addItem (s, &ndx);
107
108 UT_return_if_fail(err == UT_OK);
109 s->setType(ndx+1);
110 }
111
unregisterScript(UT_ScriptSniffer * s)112 void UT_ScriptLibrary::unregisterScript ( UT_ScriptSniffer * s )
113 {
114 UT_uint32 ndx = s->getType(); // 1:1 mapping
115
116 UT_return_if_fail( ndx > 0);
117
118 mSniffers->deleteNthItem (ndx-1);
119
120 // Refactor the indexes
121 UT_ScriptSniffer * pSniffer = 0;
122 UT_sint32 size = mSniffers->size();
123 UT_sint32 i = 0;
124 for( i = ndx-1; i < size; i++)
125 {
126 pSniffer = mSniffers->getNthItem(i);
127 if (pSniffer)
128 pSniffer->setType(i+1);
129 }
130 }
131
unregisterAllScripts()132 void UT_ScriptLibrary::unregisterAllScripts ()
133 {
134 UT_ScriptSniffer * pSniffer = 0;
135 UT_sint32 size = mSniffers->size();
136
137 for (UT_sint32 i = 0; i < size; i++)
138 {
139 pSniffer = mSniffers->getNthItem(i);
140 if (pSniffer)
141 delete pSniffer;
142 }
143
144 mSniffers->clear();
145 }
146
typeForContents(const char * szBuf,UT_uint32 iNumbytes)147 UT_ScriptIdType UT_ScriptLibrary::typeForContents(const char * szBuf,
148 UT_uint32 iNumbytes)
149 {
150 // we have to construct the loop this way because a
151 // given filter could support more than one file type,
152 // so we must query a match for all file types
153 UT_uint32 nrElements = getNumScripts();
154
155 for (UT_uint32 k=0; k < nrElements; k++)
156 {
157 const UT_ScriptSniffer * s = mSniffers->getNthItem (k);
158 if (s->recognizeContents(szBuf, iNumbytes))
159 {
160 for (UT_sint32 a = 0; a < static_cast<int>(nrElements); a++)
161 {
162 if (s->supportsType(static_cast<UT_ScriptIdType>(a+1)))
163 return static_cast<UT_ScriptIdType>(a+1);
164 }
165
166 UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
167 // Hm... an importer recognizes the given data
168 // but refuses to support any file type we request.
169 return -1;
170 }
171 }
172
173 // No filter recognizes this data
174 return -1;
175
176 }
177
typeForSuffix(const char * szSuffix)178 UT_ScriptIdType UT_ScriptLibrary::typeForSuffix(const char * szSuffix)
179 {
180 if (!szSuffix || !(*szSuffix))
181 return -1;
182
183 // we have to construct the loop this way because a
184 // given filter could support more than one file type,
185 // so we must query a suffix match for all file types
186 UT_uint32 nrElements = getNumScripts();
187
188 for (UT_uint32 k=0; k < nrElements; k++)
189 {
190 const UT_ScriptSniffer * s = mSniffers->getNthItem(k);
191 if (s->recognizeSuffix(szSuffix))
192 {
193 for (UT_sint32 a = 0; a < static_cast<int>(nrElements); a++)
194 {
195 if (s->supportsType(static_cast<UT_ScriptIdType>(a+1)))
196 return static_cast<UT_ScriptIdType>(a+1);
197 }
198
199 UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
200 // Hm... an importer has registered for the given suffix,
201 // but refuses to support any file type we request.
202 return -1;
203 }
204 }
205
206 // No filter is registered for that extension
207 return -1;
208 }
209
suffixesForType(UT_ScriptIdType ieft)210 const char * UT_ScriptLibrary::suffixesForType(UT_ScriptIdType ieft)
211 {
212 const char * szSuffixes = 0;
213
214 // we have to construct the loop this way because a
215 // given filter could support more than one file type,
216 // so we must query a suffix match for all file types
217 UT_uint32 nrElements = getNumScripts();
218
219 for (UT_uint32 k=0; k < nrElements; k++)
220 {
221 const UT_ScriptSniffer * s = mSniffers->getNthItem(k);
222 if (s->supportsType(ieft))
223 {
224 const char *szDummy;
225 UT_ScriptIdType ieftDummy;
226 if (s->getDlgLabels(&szDummy,&szSuffixes,&ieftDummy))
227 {
228 return szSuffixes;
229 }
230 else
231 {
232 UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
233 }
234 }
235 }
236
237 // The passed in filetype is invalid.
238 return 0;
239 }
240
constructScript(const char * szFilename,UT_ScriptIdType ieft,UT_Script ** ppscript,UT_ScriptIdType * pieft)241 UT_Error UT_ScriptLibrary::constructScript(const char * szFilename,
242 UT_ScriptIdType ieft,
243 UT_Script ** ppscript,
244 UT_ScriptIdType * pieft)
245 {
246 UT_return_val_if_fail(((ieft != -1) || (szFilename && *szFilename)) &&
247 ppscript, UT_ERROR);
248
249 // no filter will support -1, so we try to detect
250 // from the contents of the file or the filename suffix
251 // the importer to use and assign that back to ieft.
252 // Give precedence to the file contents
253 if (ieft == -1 && szFilename && *szFilename)
254 {
255 char szBuf[4096]; // 4096 ought to be enough
256 int iNumbytes;
257 FILE *f;
258 // we must open in binary mode for UCS-2 compatibility
259 if ( ( f = fopen( szFilename, "rb" ) ) != static_cast<FILE *>(0) )
260 {
261 iNumbytes = fread(szBuf, 1, sizeof(szBuf), f);
262 fclose(f);
263 ieft = typeForContents(szBuf, iNumbytes);
264 }
265 }
266 if (ieft == -1 && szFilename && *szFilename)
267 {
268 ieft = typeForSuffix(UT_pathSuffix(szFilename).c_str());
269 }
270
271 UT_return_val_if_fail(ieft != -1, UT_ERROR);
272
273 // tell the caller the type of importer they got
274 if (pieft != NULL)
275 *pieft = ieft;
276
277 // use the importer for the specified file type
278 UT_uint32 nrElements = getNumScripts();
279
280 for (UT_uint32 k=0; k < nrElements; k++)
281 {
282 const UT_ScriptSniffer * s = mSniffers->getNthItem (k);
283 if (s->supportsType(ieft))
284 return s->constructScript(ppscript);
285 }
286
287 // all has failed
288 return UT_ERROR;
289 }
290
enumerateDlgLabels(UT_uint32 ndx,const char ** pszDesc,const char ** pszSuffixList,UT_ScriptIdType * ft)291 bool UT_ScriptLibrary::enumerateDlgLabels(UT_uint32 ndx,
292 const char ** pszDesc,
293 const char ** pszSuffixList,
294 UT_ScriptIdType * ft)
295 {
296 UT_uint32 nrElements = getNumScripts();
297 if (ndx < nrElements)
298 {
299 const UT_ScriptSniffer * s = mSniffers->getNthItem (ndx);
300 return s->getDlgLabels(pszDesc,pszSuffixList,ft);
301 }
302
303 return false;
304 }
305
306