1 /*
2  *
3  * Copyright (C) 2001 by Dom Lachowicz & Michael D. Pritchett
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 "xap_Module.h"
22 #include "xap_App.h"
23 #include "xap_Frame.h"
24 #include "fv_View.h"
25 #include "ap_Menu_Id.h"
26 #include "ev_Menu_Actions.h"
27 #include "ev_Menu.h"
28 #include "ev_Menu_Layouts.h"
29 #include "ev_Menu_Labels.h"
30 #include "ev_EditMethod.h"
31 #include "xap_Menu_Layouts.h"
32 #include "ut_string_class.h"
33 
34 #ifdef ABI_PLUGIN_BUILTIN
35 #define abi_plugin_register abipgn_wikipedia_register
36 #define abi_plugin_unregister abipgn_wikipedia_unregister
37 #define abi_plugin_supports_version abipgn_wikipedia_supports_version
38 // dll exports break static linking
39 #define ABI_BUILTIN_FAR_CALL extern "C"
40 #else
41 #define ABI_BUILTIN_FAR_CALL ABI_FAR_CALL
42 ABI_PLUGIN_DECLARE ("Wikipedia")
43 #endif
44 
45 // -----------------------------------------------------------------------
46 // -----------------------------------------------------------------------
47 
48 //
49 // _ucsToAscii
50 // -----------------------
51 //   Helper function to convert UCS-4 strings into Ascii.
52 //   NOTE: you must call delete[] on the returned text!!!
53 //
54 inline static char*
_ucsToAscii(const UT_UCSChar * text)55 _ucsToAscii(const UT_UCSChar* text)
56 {
57   UT_return_val_if_fail(text,0);
58 
59   // calculate length of text so that we can create a character
60   // buffer of equal size.
61   const unsigned int length = UT_UCS4_strlen(static_cast<const UT_UCS4Char *>(text));
62 
63   // allocate ascii characters plus room for a null terminator.
64   char* ret = new char[length+1];
65 
66   // do the string conversion.  this is simple we just cast to
67   // char since UCS-4 is the same as Ascii for english.
68   for(unsigned int i = 0;i < length;++i)
69     {
70       ret[i] = static_cast<char>(text[i]);
71     }
72 
73   // finally null terminate the string.
74   ret[length] = '\0';
75 
76   // and now return it.
77   return ret;
78 }
79 
80 //
81 // Wikipedia_invoke
82 // -------------------
83 //   This is the function that we actually call to invoke the on-line encyclopedia.
84 //   It should be called when the user selects from the context menu
85 //
86 static bool
Wikipedia_invoke(AV_View *,EV_EditMethodCallData *)87 Wikipedia_invoke(AV_View* /*v*/, EV_EditMethodCallData * /*d*/)
88 {
89   // Get the current view that the user is in.
90   XAP_Frame *pFrame = XAP_App::getApp()->getLastFocussedFrame();
91   FV_View* pView = static_cast<FV_View*>(pFrame->getCurrentView());
92 
93   // If the user is on a word, but does not have it selected, we need
94   // to go ahead and select that word so that the search/replace goes
95   // correctly.
96   pView->moveInsPtTo(FV_DOCPOS_EOW_MOVE);
97   pView->moveInsPtTo(FV_DOCPOS_BOW);
98   pView->extSelTo(FV_DOCPOS_EOW_SELECT);
99 
100   // Now we will figure out what word to look up when we open our dialog.
101   // http://en.wikipedia.org/w/wiki.phtml?search=war&go=Go
102   UT_String url ("http://www.wikipedia.com/");
103   if (!pView->isSelectionEmpty())
104     {
105 	url += "w/wiki.phtml?search=";
106       // We need to get the Ascii version of the current word.
107       UT_UCS4Char *ucs4ST;
108       pView->getSelectionText(*&ucs4ST);
109       char* search = _ucsToAscii(
110 				 ucs4ST
111 				 );
112 
113       url += search;
114       DELETEPV(search);
115       FREEP(ucs4ST);
116 
117 	url += "&go=Go";
118     }
119 
120   XAP_App::getApp()->openURL( url.c_str() );
121 
122   return true;
123 }
124 
125 static const char* Wikipedia_MenuLabel = "Wi&ki Encyclopedia";
126 static const char* Wikipedia_MenuTooltip = "Opens the libre Wiki on-line encyclopedia";
127 
128 static void
Wikipedia_removeFromMenus()129 Wikipedia_removeFromMenus()
130 {
131   // First we need to get a pointer to the application itself.
132   XAP_App *pApp = XAP_App::getApp();
133 
134   // remove the edit method
135   EV_EditMethodContainer* pEMC = pApp->getEditMethodContainer() ;
136   EV_EditMethod * pEM = ev_EditMethod_lookup ( "Wikipedia_invoke" ) ;
137   pEMC->removeEditMethod ( pEM ) ;
138   DELETEP( pEM ) ;
139 
140   // now remove crap from the menus
141   int frameCount = pApp->getFrameCount();
142   XAP_Menu_Factory * pFact = pApp->getMenuFactory();
143 
144   pFact->removeMenuItem("Main",NULL,Wikipedia_MenuLabel);
145   pFact->removeMenuItem("contextText",NULL,Wikipedia_MenuLabel);
146   for(int i = 0;i < frameCount;++i)
147     {
148       // Get the current frame that we're iterating through.
149       XAP_Frame* pFrame = pApp->getFrame(i);
150       pFrame->rebuildMenus();
151     }
152 }
153 
154 static void
Wikipedia_addToMenus()155 Wikipedia_addToMenus()
156 {
157   // First we need to get a pointer to the application itself.
158   XAP_App *pApp = XAP_App::getApp();
159 
160   // Create an EditMethod that will link our method's name with
161   // it's callback function.  This is used to link the name to
162   // the callback.
163   EV_EditMethod *myEditMethod = new EV_EditMethod(
164 						  "Wikipedia_invoke",  // name of callback function
165 						  Wikipedia_invoke,    // callback function itself.
166 						  0,                      // no additional data required.
167 						  ""                      // description -- allegedly never used for anything
168 						  );
169 
170   // Now we need to get the EditMethod container for the application.
171   // This holds a series of Edit Methods and links names to callbacks.
172   EV_EditMethodContainer* pEMC = pApp->getEditMethodContainer();
173 
174   // We have to add our EditMethod to the application's EditMethodList
175   // so that the application will know what callback to call when a call
176   // to "Wikipedia_invoke" is received.
177   pEMC->addEditMethod(myEditMethod);
178 
179 
180   // Now we need to grab an ActionSet.  This is going to be used later
181   // on in our for loop.  Take a look near the bottom.
182   EV_Menu_ActionSet* pActionSet = pApp->getMenuActionSet();
183 
184 
185   // We need to go through and add the menu element to each "frame"
186   // of the application.  We can iterate through the frames by doing
187   // XAP_App::getFrameCount() to tell us how many frames there are,
188   // then calling XAP_App::getFrame(i) to get the i-th frame.
189 
190   int frameCount = pApp->getFrameCount();
191   XAP_Menu_Factory * pFact = pApp->getMenuFactory();
192 
193   //
194   // Put it in the context menu.
195   //
196   XAP_Menu_Id newID = pFact->addNewMenuAfter("contextText",NULL,"Bullets and &Numbering",EV_MLF_Normal);
197   pFact->addNewLabel(NULL,newID,Wikipedia_MenuLabel, Wikipedia_MenuTooltip);
198 
199   //
200   // Also put it under word Wount in the main menu,
201   //
202   pFact->addNewMenuAfter("Main",NULL,"&Word Count",EV_MLF_Normal,newID);
203 
204   // Create the Action that will be called.
205   EV_Menu_Action* myAction = new EV_Menu_Action(
206 						newID,                     // id that the layout said we could use
207 						0,                      // no, we don't have a sub menu.
208 						0,                      // no, we don't raise a dialog.
209 						0,                      // no, we don't have a checkbox.
210 						0,
211 						"Wikipedia_invoke",  // name of callback function to call.
212 						NULL,                   // don't know/care what this is for
213 						NULL                    // don't know/care what this is for
214 						);
215 
216   // Now what we need to do is add this particular action to the ActionSet
217   // of the application.  This forms the link between our new ID that we
218   // got for this particular frame with the EditMethod that knows how to
219   // call our callback function.
220 
221   pActionSet->addAction(myAction);
222 
223   for(int i = 0;i < frameCount;++i)
224     {
225       // Get the current frame that we're iterating through.
226       XAP_Frame* pFrame = pApp->getFrame(i);
227       pFrame->rebuildMenus();
228     }
229 }
230 
231 // -----------------------------------------------------------------------
232 //
233 //      Abiword Plugin Interface
234 //
235 // -----------------------------------------------------------------------
236 
237 ABI_BUILTIN_FAR_CALL
abi_plugin_register(XAP_ModuleInfo * mi)238 int abi_plugin_register (XAP_ModuleInfo * mi)
239 {
240     mi->name = "Wikipedia plugin";
241     mi->desc = "On-line Encyclopedia support for AbiWord. Search site is http://www.wikipedia.com/";
242     mi->version = ABI_VERSION_STRING;
243     mi->author = "Francis James Franklin"; // and Michael D. Pritchett and Dom Lachowicz
244     mi->usage = "No Usage";
245 
246     // Add the dictionary to AbiWord's menus.
247     Wikipedia_addToMenus();
248 
249     return 1;
250 }
251 
252 
253 ABI_BUILTIN_FAR_CALL
abi_plugin_unregister(XAP_ModuleInfo * mi)254 int abi_plugin_unregister (XAP_ModuleInfo * mi)
255 {
256     mi->name = 0;
257     mi->desc = 0;
258     mi->version = 0;
259     mi->author = 0;
260     mi->usage = 0;
261 
262     Wikipedia_removeFromMenus();
263 
264     return 1;
265 }
266 
267 
268 ABI_BUILTIN_FAR_CALL
abi_plugin_supports_version(UT_uint32,UT_uint32,UT_uint32)269 int abi_plugin_supports_version (UT_uint32 /*major*/, UT_uint32 /*minor*/, UT_uint32 /*release*/)
270 {
271     return 1;
272 }
273