1 /* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */
2
3 /* AbiSource Program Utilities
4 * Copyright (C) 1998 AbiSource, Inc.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program 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
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301 USA.
20 */
21
22 #include <string.h>
23 #include <stdlib.h>
24
25 #include "ev_EditMethod.h"
26 #include "ut_assert.h"
27 #include "ut_vector.h"
28 #include "ut_string.h"
29 #include "ut_string_class.h"
30
31 #include "xap_App.h"
32 #include "xap_Frame.h"
33
34 /*****************************************************************/
35 /*****************************************************************/
36
EV_EditMethodCallData()37 EV_EditMethodCallData::EV_EditMethodCallData()
38 : m_pData(0),
39 m_dataLength(0),
40 m_bAllocatedData(false),
41 m_xPos(0),
42 m_yPos(0)
43 {
44 }
45
EV_EditMethodCallData(const UT_String & stScriptName)46 EV_EditMethodCallData::EV_EditMethodCallData(const UT_String& stScriptName)
47 : m_pData(0),
48 m_dataLength(0),
49 m_bAllocatedData(false),
50 m_xPos(0),
51 m_yPos(0),
52 m_stScriptName(stScriptName)
53 {
54 }
55
56 /* TF NOTE:
57 I hate the fact that we need two almost identical constructors. It really licks,
58 not to mention the fact that nothing actually checks to see if the m_bAlocatedData
59 flag is actually set, so covering this "failure" case may be pointless if other
60 things don't play along. Comment out this code just to see how well it would work.
61 */
EV_EditMethodCallData(const UT_UCSChar * pData,UT_uint32 dataLength)62 EV_EditMethodCallData::EV_EditMethodCallData(const UT_UCSChar * pData, UT_uint32 dataLength)
63 : m_xPos(0),
64 m_yPos(0)
65 {
66 m_pData = new UT_UCSChar[dataLength];
67 if (m_pData)
68 {
69 for (UT_uint32 k = 0; k < dataLength; k++)
70 m_pData[k] = pData[k];
71 m_dataLength = dataLength;
72 m_bAllocatedData = true;
73 }
74 else // since constructors can't fail, we create a zombie.
75 {
76 m_dataLength = 0;
77 m_bAllocatedData = false;
78 }
79 }
80
EV_EditMethodCallData(const char * pChar,UT_uint32 dataLength)81 EV_EditMethodCallData::EV_EditMethodCallData(const char * pChar, UT_uint32 dataLength)
82 : m_xPos(0),
83 m_yPos(0)
84 {
85 m_pData = new UT_UCSChar[dataLength];
86 if (m_pData)
87 {
88 for (UT_uint32 k = 0; k < dataLength; k++)
89 m_pData[k] = pChar[k];
90 m_dataLength = dataLength;
91 m_bAllocatedData = true;
92 }
93 else // since constructors can't fail, we create a zombie.
94 {
95 m_dataLength = 0;
96 m_bAllocatedData = false;
97 }
98 }
99
~EV_EditMethodCallData()100 EV_EditMethodCallData::~EV_EditMethodCallData()
101 {
102 delete [] m_pData;
103 }
104
105 /*****************************************************************/
106 /*****************************************************************/
107
EV_EditMethod(const char * szName,EV_EditMethod_pFn fn,EV_EditMethodType emt,const char * szDescription)108 EV_EditMethod::EV_EditMethod(const char * szName, EV_EditMethod_pFn fn, EV_EditMethodType emt,
109 const char * szDescription)
110 : m_szName(szName),
111 m_fn(fn),
112 m_CtxtFn(0),
113 m_emt(emt),
114 m_szDescription(szDescription),
115 m_context(0)
116 {
117 }
118
EV_EditMethod(const char * szName,EV_EditMethod_pCtxtFn fn,EV_EditMethodType emt,const char * szDescription,void * context)119 EV_EditMethod::EV_EditMethod(const char * szName, EV_EditMethod_pCtxtFn fn, EV_EditMethodType emt,
120 const char * szDescription, void * context)
121 : m_szName(szName),
122 m_fn(0),
123 m_CtxtFn(fn),
124 m_emt(emt),
125 m_szDescription(szDescription),
126 m_context(context)
127 {
128 }
129
Fn(AV_View * pView,EV_EditMethodCallData * pCallData) const130 bool EV_EditMethod::Fn(AV_View * pView, EV_EditMethodCallData * pCallData) const
131 {
132 if (m_fn)
133 return (*m_fn) (pView, pCallData);
134 else if (m_CtxtFn)
135 return (*m_CtxtFn) (pView, pCallData, m_context);
136
137 UT_ASSERT(m_fn || m_CtxtFn);
138 return false;
139 }
140
getType() const141 EV_EditMethodType EV_EditMethod::getType() const
142 {
143 return m_emt;
144 }
145
getName() const146 const char * EV_EditMethod::getName() const
147 {
148 return m_szName;
149 }
150
getDescription() const151 const char * EV_EditMethod::getDescription() const
152 {
153 return m_szDescription;
154 }
155
156 /*****************************************************************/
157 /*****************************************************************/
158
EV_EditMethodContainer(UT_uint32 cStatic,EV_EditMethod arrayStaticEditMethods[])159 EV_EditMethodContainer::EV_EditMethodContainer(UT_uint32 cStatic,EV_EditMethod arrayStaticEditMethods[])
160 {
161 m_countStatic = cStatic;
162 m_arrayStaticEditMethods = arrayStaticEditMethods;
163 }
164
~EV_EditMethodContainer()165 EV_EditMethodContainer::~EV_EditMethodContainer()
166 {
167 UT_VECTOR_PURGEALL(EV_EditMethod *, m_vecDynamicEditMethods);
168 }
169
addEditMethod(EV_EditMethod * pem)170 bool EV_EditMethodContainer::addEditMethod(EV_EditMethod * pem)
171 {
172 UT_ASSERT(pem);
173
174 int error = m_vecDynamicEditMethods.addItem(pem);
175 return (error == 0);
176 }
177
removeEditMethod(EV_EditMethod * pem)178 bool EV_EditMethodContainer::removeEditMethod(EV_EditMethod * pem)
179 {
180 UT_ASSERT(pem);
181 xxx_UT_DEBUGMSG(("Bsearch for name \n"));
182
183 UT_sint32 pos = m_vecDynamicEditMethods.findItem ( pem ) ;
184
185 if ( pos >= 0 )
186 m_vecDynamicEditMethods.deleteNthItem(pos);
187 return (pos >= 0) ;
188 }
189
countEditMethods()190 UT_uint32 EV_EditMethodContainer::countEditMethods()
191 {
192 return m_countStatic + m_vecDynamicEditMethods.getItemCount();
193 }
194
getNthEditMethod(UT_uint32 ndx)195 EV_EditMethod * EV_EditMethodContainer::getNthEditMethod(UT_uint32 ndx)
196 {
197 if (ndx < m_countStatic)
198 return &m_arrayStaticEditMethods[ndx];
199 else
200 return m_vecDynamicEditMethods.getNthItem(ndx-m_countStatic);
201 }
202
203 // for use in a binary search of an EV_EditMethod array
ev_compar(const void * a,const void * b)204 static int ev_compar (const void * a, const void * b)
205 {
206 const char * str = static_cast<const char *>(a);
207 const EV_EditMethod * ev = static_cast<const EV_EditMethod *>(b);
208
209 return (strcmp (str, ev->getName()));
210 }
211
findEditMethodByName(const char * szName) const212 EV_EditMethod * EV_EditMethodContainer::findEditMethodByName(const char * szName) const
213 {
214 if (!szName)
215 return 0;
216
217 EV_EditMethod *mthd = NULL;
218
219 // TODO: make this also use a hashtable + bsearch
220
221 // first, see if it's in our hashtable
222 // TODO: should this be class-wide instead of static here?
223 static std::map<std::string,EV_EditMethod *> emHash;
224 std::map<std::string,EV_EditMethod *>::const_iterator iter;
225 iter = emHash.find(szName);
226 if (iter != emHash.end())
227 return iter->second;
228
229 // nope, bsearch for it in our private array
230 mthd = static_cast<EV_EditMethod *>(bsearch(szName,
231 m_arrayStaticEditMethods,
232 m_countStatic,
233 sizeof (EV_EditMethod),
234 ev_compar));
235
236 if (mthd)
237 {
238 // found it, insert it into our hash table for quicker lookup
239 // in the future and return
240 emHash.insert(std::make_pair(szName, mthd));
241 return mthd;
242 }
243
244 // else do a linear search through our dynamic method vector
245
246 UT_uint32 k, kLast;
247 xxx_UT_DEBUGMSG(("Linear search for it \n"));
248 kLast = m_vecDynamicEditMethods.getItemCount();
249 for (k=0; k<kLast; k++)
250 {
251 xxx_UT_DEBUGMSG(("Looking at method %d \n",k));
252 EV_EditMethod * pem = m_vecDynamicEditMethods.getNthItem(k);
253 if(pem == NULL)
254 continue;
255 if(pem->getName() == NULL)
256 continue;
257 if (strcmp(szName,pem->getName()) == 0)
258 return pem;
259 }
260
261 return 0;
262 }
263
264 /*****************************************************************/
265 /*****************************************************************/
266
ev_EditMethod_invoke(const EV_EditMethod * pEM,EV_EditMethodCallData * pData)267 bool ev_EditMethod_invoke (const EV_EditMethod * pEM,
268 EV_EditMethodCallData * pData)
269 {
270 // no method or no call data == bad joo joo - return false
271 UT_ASSERT(pEM);
272 UT_ASSERT(pData);
273 if ( !pEM || !pData )
274 return false ;
275
276 // no controlling view == bad joo joo - return false
277 // Actually allow this for plugins invoked from the command line
278 //
279 AV_View * pView = NULL;
280 XAP_Frame * pFrame = XAP_App::getApp()->getLastFocussedFrame();
281 if(!pFrame)
282 {
283 return pEM->Fn(pView, pData);
284 }
285 pView = pFrame->getCurrentView() ;
286 UT_return_val_if_fail(pView, false);
287
288 // return whatever the method says to based on the data at hand
289 return pEM->Fn(pView, pData);
290 }
291
ev_EditMethod_invoke(const EV_EditMethod * pEM,const UT_String & data)292 bool ev_EditMethod_invoke (const EV_EditMethod * pEM, const UT_String & data)
293 {
294 EV_EditMethodCallData callData ( data.c_str(), static_cast<UT_uint32>(data.size()) ) ;
295 return ev_EditMethod_invoke ( pEM, &callData ) ;
296 }
297
ev_EditMethod_invoke(const EV_EditMethod * pEM,const UT_UCS4String & data)298 bool ev_EditMethod_invoke (const EV_EditMethod * pEM, const UT_UCS4String & data)
299 {
300 EV_EditMethodCallData callData ( data.ucs4_str(), static_cast<UT_uint32>(data.size()) ) ;
301 return ev_EditMethod_invoke ( pEM, &callData ) ;
302 }
303
ev_EditMethod_invoke(const char * methodName,const UT_String & data)304 bool ev_EditMethod_invoke (const char * methodName, const UT_String & data)
305 {
306 return ev_EditMethod_invoke ( ev_EditMethod_lookup ( methodName ), data ) ;
307 }
308
ev_EditMethod_invoke(const char * methodName,const UT_UCS4String & data)309 bool ev_EditMethod_invoke (const char * methodName, const UT_UCS4String & data)
310 {
311 return ev_EditMethod_invoke ( ev_EditMethod_lookup ( methodName ), data ) ;
312 }
313
ev_EditMethod_invoke(const char * methodName,const char * data)314 bool ev_EditMethod_invoke (const char * methodName, const char * data)
315 {
316 UT_return_val_if_fail(data, false);
317 return ev_EditMethod_invoke ( methodName, UT_String(data) ) ;
318 }
319
ev_EditMethod_invoke(const char * methodName,const UT_UCSChar * data)320 bool ev_EditMethod_invoke (const char * methodName, const UT_UCSChar * data)
321 {
322 UT_return_val_if_fail(data, false);
323 return ev_EditMethod_invoke ( methodName, UT_UCS4String(data) ) ;
324 }
325
ev_EditMethod_invoke(const UT_String & methodName,const UT_String & data)326 bool ev_EditMethod_invoke (const UT_String& methodName, const UT_String & data)
327 {
328 return ev_EditMethod_invoke ( methodName.c_str(), data ) ;
329 }
330
ev_EditMethod_invoke(const UT_String & methodName,const UT_UCS4String & data)331 bool ev_EditMethod_invoke (const UT_String& methodName, const UT_UCS4String & data)
332 {
333 return ev_EditMethod_invoke ( methodName.c_str(), data ) ;
334 }
335
336 /*****************************************************************/
337 /*****************************************************************/
338
ev_EditMethod_exists(const char * methodName)339 bool ev_EditMethod_exists (const char * methodName)
340 {
341 return ( ev_EditMethod_lookup ( methodName ) != NULL ) ;
342 }
343
ev_EditMethod_exists(const UT_String & methodName)344 bool ev_EditMethod_exists (const UT_String & methodName)
345 {
346 return ev_EditMethod_exists ( methodName.c_str() ) ;
347 }
348
349 /*****************************************************************/
350 /*****************************************************************/
351
ev_EditMethod_lookup(const char * methodName)352 EV_EditMethod* ev_EditMethod_lookup (const char * methodName)
353 {
354 UT_ASSERT(methodName);
355 EV_EditMethodContainer* pEMC = XAP_App::getApp()->getEditMethodContainer() ;
356 return pEMC->findEditMethodByName ( methodName ) ;
357 }
358
ev_EditMethod_lookup(const UT_String & methodName)359 EV_EditMethod* ev_EditMethod_lookup (const UT_String & methodName)
360 {
361 return ev_EditMethod_lookup ( methodName.c_str() ) ;
362 }
363
364
365