1 /* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */
2 
3 /* AbiSource Application Framework
4  * Copyright (C) 2004 Francis James Franklin
5  * Copyright (C) 2007 Hubert Figuiere
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20  * 02110-1301 USA.
21  */
22 
23 #include "config.h"
24 
25 #include "ut_string_class.h"
26 #include "ut_xml.h"
27 
28 #include "xap_CocoaApp.h"
29 #include "xap_CocoaAppController.h"
30 #include "xap_CocoaPlugin.h"
31 
32 #include "ap_CocoaPlugin.h"
33 
34 class s_SimpleXML_Listener : public UT_XML::Listener
35 {
36 private:
37 	id <XAP_CocoaPlugin_SimpleXML>	m_callback;
38 
39 	NSString *	m_error;
40 
41 	UT_XML		m_parser;
42 
43 public:
s_SimpleXML_Listener(id<XAP_CocoaPlugin_SimpleXML> callback)44 	s_SimpleXML_Listener (id <XAP_CocoaPlugin_SimpleXML> callback) :
45 		m_callback(callback),
46 		m_error(0)
47 		{
48 			m_parser.setListener(this);
49 		}
50 
~s_SimpleXML_Listener()51 	virtual ~s_SimpleXML_Listener ()
52 		{
53 			if (m_error)
54 			{
55 				[m_error release];
56 				m_error = 0;
57 			}
58 		}
59 
parse(NSString * path)60 	NSString * parse (NSString * path)
61 		{
62 			if (m_parser.parse ([path UTF8String]) != UT_OK)
63 			{
64 				if (!m_error)
65 				{
66 					m_error = [NSString stringWithFormat:@"Error while parsing \"%@\"", path];
67 					[m_error retain];
68 				}
69 			}
70 			return m_error;
71 		}
72 
startElement(const gchar * element_name,const gchar ** atts)73 	virtual void startElement (const gchar * element_name, const gchar ** atts)
74 		{
75 			NSMutableDictionary * dictionary = [NSMutableDictionary dictionaryWithCapacity:4];
76 
77 			NSString * name = [NSString stringWithUTF8String:element_name];
78 
79 			const gchar ** attr = atts;
80 
81 			while (*attr)
82 			{
83 				const gchar * key   = *attr++;
84 				const gchar * value = *attr++;
85 
86 				if (*key && value)
87 				{
88 					[dictionary setObject:[NSString stringWithUTF8String:value] forKey:[NSString stringWithUTF8String:key]];
89 				}
90 			}
91 			if (![m_callback startElement:name attributes:dictionary])
92 			{
93 				m_parser.stop();
94 
95 				m_error = @"Simple XML parser stopped by callback method \"startElement:attributes:\".";
96 				[m_error retain];
97 			}
98 		}
99 
endElement(const gchar * element_name)100 	virtual void endElement (const gchar * element_name)
101 		{
102 			NSString * name = [NSString stringWithUTF8String:element_name];
103 
104 			if (![m_callback endElement:name])
105 			{
106 				m_parser.stop();
107 
108 				m_error = @"Simple XML parser stopped by callback method \"endElement:\".";
109 				[m_error retain];
110 			}
111 		}
112 
charData(const gchar * buffer,int length)113 	virtual void charData (const gchar * buffer, int length)
114 		{
115 			UT_UTF8String data(buffer,length);
116 			// FIXME: remove the UT_UTF8String from here
117 			if (![m_callback characterData:[NSString stringWithUTF8String:(data.utf8_str())]])
118 			{
119 				m_parser.stop();
120 
121 				m_error = @"Simple XML parser stopped by callback method \"characterData:\".";
122 				[m_error retain];
123 			}
124 		}
125 };
126 
127 @implementation XAP_CocoaPlugin
128 
129 - (id)init
130 {
131 	if (![super init])
132 	{
133 		return nil;
134 	}
135 	m_delegate = nil;
136 	return self;
137 }
138 
139 - (void)dealloc
140 {
141 	//
142 	[super dealloc];
143 }
144 
145 - (BOOL)loadBundleWithPath:(NSString *)path
146 {
147 	BOOL bLoaded = NO;
148 
149 	if (NSBundle * bundle = [NSBundle bundleWithPath:path]) {
150 		if (![bundle isLoaded]) {
151 			if ([bundle load]) {
152 				if (Class bundleClass = [bundle principalClass]) {
153 					if (id <NSObject, XAP_CocoaPluginDelegate> instance = [[bundleClass alloc] init])
154 					{
155 						if ([instance respondsToSelector:@selector(pluginCanRegisterForAbiWord:version:interface:)])
156 						{
157 							[self setDelegate:instance];
158 							unsigned long interface = XAP_COCOAPLUGIN_INTERFACE;
159 							NSString * version = [NSString stringWithUTF8String:VERSION];
160 							bLoaded = [instance pluginCanRegisterForAbiWord:self version:version interface:interface];
161 						}
162 						if (!bLoaded)
163 						{
164 							[instance release];
165 						}
166 					}
167 				}
168 			}
169 		}
170 	}
171 	return bLoaded;
172 }
173 
174 - (void)setDelegate:(id <NSObject, XAP_CocoaPluginDelegate>)delegate
175 {
176 	m_delegate = delegate;
177 }
178 
179 - (id <NSObject, XAP_CocoaPluginDelegate>)delegate
180 {
181 	return m_delegate;
182 }
183 
184 - (void)appendMenuItem:(NSMenuItem *)menuItem
185 {
186 	XAP_CocoaAppController * pController = (XAP_CocoaAppController *) [NSApp delegate];
187 	[pController appendPluginMenuItem:menuItem];
188 }
189 
190 - (void)removeMenuItem:(NSMenuItem *)menuItem
191 {
192 	XAP_CocoaAppController * pController = (XAP_CocoaAppController *) [NSApp delegate];
193 	[pController removePluginMenuItem:menuItem];
194 }
195 
196 - (id <NSObject, XAP_CocoaPlugin_Document>)currentDocument // may return nil;
197 {
198 	return [AP_CocoaPlugin_Document currentDocument];
199 }
200 
201 - (NSArray *)documents
202 {
203 	return [AP_CocoaPlugin_Document documents];
204 }
205 
206 - (NSString *)selectMailMergeSource // may return nil
207 {
208 	return [AP_CocoaPlugin_Document selectMailMergeSource];
209 }
210 
211 /* Returns an NSMutableArray whose objects are NSMutableArray of NSString, the first row holding the
212  * field names, the rest being records; returns nil on failure.
213  */
214 - (NSMutableArray *)importMailMergeSource:(NSString *)path
215 {
216 	return [AP_CocoaPlugin_Document importMailMergeSource:path];
217 }
218 
219 - (id <NSObject, XAP_CocoaPlugin_FramelessDocument>)importDocumentFromFile:(NSString *)path importOptions:(NSDictionary *)options
220 {
221 	return [AP_CocoaPlugin_FramelessDocument documentFromFile:path importOptions:options];
222 }
223 
224 - (id <NSObject, XAP_CocoaPlugin_MenuItem>)contextMenuItemWithLabel:(NSString *)label
225 {
226 	return [AP_CocoaPlugin_ContextMenuItem itemWithLabel:label];
227 }
228 
229 - (NSArray *)toolProviders
230 {
231 	XAP_CocoaAppController * pController = (XAP_CocoaAppController *) [NSApp delegate];
232 	return [pController toolProviders];
233 }
234 
235 - (id <NSObject, XAP_CocoaPlugin_ToolProvider>)toolProvider:(NSString *)name
236 {
237 	XAP_CocoaAppController * pController = (XAP_CocoaAppController *) [NSApp delegate];
238 	return [pController toolProvider:name];
239 }
240 
241 - (NSString *)findResourcePath:(NSString *)relativePath
242 {
243 	XAP_CocoaApp * pApp = static_cast<XAP_CocoaApp *>(XAP_App::getApp());
244 
245 	NSString * resource_path = 0;
246 
247 	if (relativePath)
248 	{
249 		if ([relativePath length])
250 		{
251 			std::string path;
252 
253 			if (pApp->findAbiSuiteLibFile(path, [relativePath UTF8String]))
254 			{
255 				resource_path = [NSString stringWithUTF8String:(path.c_str())];
256 			}
257 		}
258 	}
259 	return resource_path;
260 }
261 
262 - (NSString *)userResourcePath:(NSString *)relativePath
263 {
264 	XAP_CocoaApp * pApp = static_cast<XAP_CocoaApp *>(XAP_App::getApp());
265 
266 	NSString * resource_path = [NSString stringWithUTF8String:(pApp->getUserPrivateDirectory())];
267 
268 	if (relativePath) {
269 		if ([relativePath length]) {
270 			resource_path = [resource_path stringByAppendingPathComponent:relativePath];
271 		}
272 	}
273 
274 	return resource_path;
275 }
276 
277 - (NSString *)parseFile:(NSString *)path simpleXML:(id <XAP_CocoaPlugin_SimpleXML>)callback
278 {
279 	NSString * error = 0;
280 
281 	if (path && callback)
282 	{
283 		s_SimpleXML_Listener parser(callback);
284 		error = parser.parse(path);
285 	}
286 	else
287 	{
288 		error = @"Method \"parseFile:simpleXML:\" requires path and callback!";
289 	}
290 	return error;
291 }
292 
293 @end
294