1 /*
2  *
3  * Copyright (C) 2003 by 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 "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_google_register
36 #define abi_plugin_unregister abipgn_google_unregister
37 #define abi_plugin_supports_version abipgn_google_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("Google")
43 #endif
44 
45 // -----------------------------------------------------------------------
46 // -----------------------------------------------------------------------
47 
48 //
49 // AbiGoogle_invoke
50 // -------------------
51 //   This is the function that we actually call to invoke the on-line dictionary.
52 //   It should be called when the user selects from the context menu
53 //
54 static bool
AbiGoogle_invoke(AV_View *,EV_EditMethodCallData *)55 AbiGoogle_invoke(AV_View* /*v*/, EV_EditMethodCallData * /*d*/)
56 {
57   // Get the current view that the user is in.
58   XAP_Frame *pFrame = XAP_App::getApp()->getLastFocussedFrame();
59   FV_View* pView = static_cast<FV_View*>(pFrame->getCurrentView());
60 
61   // If the user is on a word, but does not have it selected, we need
62   // to go ahead and select that word so that the search/replace goes
63   // correctly.
64   if (pView->isSelectionEmpty()) {
65     pView->moveInsPtTo(FV_DOCPOS_EOW_MOVE);
66     pView->moveInsPtTo(FV_DOCPOS_BOW);
67     pView->extSelTo(FV_DOCPOS_EOW_SELECT);
68   }
69 
70   // Now we will figure out what word to look up
71   UT_UTF8String url ("http://www.google.com/search?hl=en&ie=UTF-8&oe=UTF-8&q=");
72 
73   // url escaping should be moved somewhere more generic
74   UT_UCS4Char *ucs4ST;
75   pView->getSelectionText(*&ucs4ST);
76   UT_UCS4String data (ucs4ST);
77   bool last_was_space = false;
78   for (size_t i = 0; i < data.length (); i++) {
79     UT_UCS4Char ch = data[i];
80     if (!UT_UCS4_isspace (ch)) {
81       url.appendUCS4 (&ch, 1);
82       last_was_space = false;
83     }
84     else if (!last_was_space) {
85       ch = '+';
86       url.appendUCS4 (&ch, 1);
87       last_was_space = true;
88     }
89   }
90 
91   XAP_App::getApp()->openURL( url.utf8_str() );
92   FREEP(ucs4ST);
93 
94   return true;
95 }
96 
97 static const char* Google_MenuLabel = "&Google Search";
98 static const char* Google_MenuTooltip = "Search the web with Google";
99 
100 static void
Google_removeFromMenus()101 Google_removeFromMenus()
102 {
103   // First we need to get a pointer to the application itself.
104   XAP_App *pApp = XAP_App::getApp();
105 
106   // remove the edit method
107   EV_EditMethodContainer* pEMC = pApp->getEditMethodContainer() ;
108   EV_EditMethod * pEM = ev_EditMethod_lookup ( "AbiGoogle_invoke" ) ;
109   pEMC->removeEditMethod ( pEM ) ;
110   DELETEP( pEM ) ;
111 
112   // now remove crap from the menus
113   int frameCount = pApp->getFrameCount();
114   XAP_Menu_Factory * pFact = pApp->getMenuFactory();
115 
116   pFact->removeMenuItem("Main",NULL,Google_MenuLabel);
117   pFact->removeMenuItem("contextText",NULL,Google_MenuLabel);
118   for(int i = 0;i < frameCount;++i)
119     {
120       // Get the current frame that we're iterating through.
121       XAP_Frame* pFrame = pApp->getFrame(i);
122       pFrame->rebuildMenus();
123     }
124 }
125 
126 static void
Google_addToMenus()127 Google_addToMenus()
128 {
129   // First we need to get a pointer to the application itself.
130   XAP_App *pApp = XAP_App::getApp();
131 
132   // Create an EditMethod that will link our method's name with
133   // it's callback function.  This is used to link the name to
134   // the callback.
135   EV_EditMethod *myEditMethod = new EV_EditMethod(
136 						  "AbiGoogle_invoke",  // name of callback function
137 						  AbiGoogle_invoke,    // callback function itself.
138 						  0,                      // no additional data required.
139 						  ""                      // description -- allegedly never used for anything
140 						  );
141 
142   // Now we need to get the EditMethod container for the application.
143   // This holds a series of Edit Methods and links names to callbacks.
144   EV_EditMethodContainer* pEMC = pApp->getEditMethodContainer();
145 
146   // We have to add our EditMethod to the application's EditMethodList
147   // so that the application will know what callback to call when a call
148   // to "AbiGoogle_invoke" is received.
149   pEMC->addEditMethod(myEditMethod);
150 
151 
152   // Now we need to grab an ActionSet.  This is going to be used later
153   // on in our for loop.  Take a look near the bottom.
154   EV_Menu_ActionSet* pActionSet = pApp->getMenuActionSet();
155 
156 
157   // We need to go through and add the menu element to each "frame"
158   // of the application.  We can iterate through the frames by doing
159   // XAP_App::getFrameCount() to tell us how many frames there are,
160   // then calling XAP_App::getFrame(i) to get the i-th frame.
161 
162   int frameCount = pApp->getFrameCount();
163   XAP_Menu_Factory * pFact = pApp->getMenuFactory();
164 
165   //
166   // Put it in the context menu.
167   //
168   XAP_Menu_Id newID = pFact->addNewMenuAfter("contextText",NULL,"Bullets and &Numbering",EV_MLF_Normal);
169   pFact->addNewLabel(NULL,newID,Google_MenuLabel, Google_MenuTooltip);
170 
171   //
172   // Also put it under word Wount in the main menu,
173   //
174   pFact->addNewMenuAfter("Main",NULL,"&Word Count",EV_MLF_Normal,newID);
175 
176   // Create the Action that will be called.
177   EV_Menu_Action* myAction = new EV_Menu_Action(
178 						newID,                     // id that the layout said we could use
179 						0,                      // no, we don't have a sub menu.
180 						0,                      // yes, we raise a dialog.
181 						0,                      // no, we don't have a checkbox.
182 						0,                      // not a radio button
183 						"AbiGoogle_invoke",  // name of callback function to call.
184 						NULL,                   // don't know/care what this is for
185 						NULL                    // don't know/care what this is for
186 						);
187 
188   // Now what we need to do is add this particular action to the ActionSet
189   // of the application.  This forms the link between our new ID that we
190   // got for this particular frame with the EditMethod that knows how to
191   // call our callback function.
192 
193   pActionSet->addAction(myAction);
194 
195   for(int i = 0;i < frameCount;++i)
196     {
197       // Get the current frame that we're iterating through.
198       XAP_Frame* pFrame = pApp->getFrame(i);
199       pFrame->rebuildMenus();
200     }
201 }
202 
203 // -----------------------------------------------------------------------
204 //
205 //      Abiword Plugin Interface
206 //
207 // -----------------------------------------------------------------------
208 
209 ABI_BUILTIN_FAR_CALL
abi_plugin_register(XAP_ModuleInfo * mi)210 int abi_plugin_register (XAP_ModuleInfo * mi)
211 {
212     mi->name = "Google plugin";
213     mi->desc = "Google search for AbiWord";
214     mi->version = ABI_VERSION_STRING;
215     mi->author = "Dom Lachowicz";
216     mi->usage = "No Usage";
217 
218     Google_addToMenus();
219 
220     return 1;
221 }
222 
223 
224 ABI_BUILTIN_FAR_CALL
abi_plugin_unregister(XAP_ModuleInfo * mi)225 int abi_plugin_unregister (XAP_ModuleInfo * mi)
226 {
227     mi->name = 0;
228     mi->desc = 0;
229     mi->version = 0;
230     mi->author = 0;
231     mi->usage = 0;
232 
233     Google_removeFromMenus() ;
234 
235     return 1;
236 }
237 
238 
239 ABI_BUILTIN_FAR_CALL
abi_plugin_supports_version(UT_uint32,UT_uint32,UT_uint32)240 int abi_plugin_supports_version (UT_uint32 /*major*/, UT_uint32 /*minor*/, UT_uint32 /*release*/)
241 {
242     return 1;
243 }
244