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