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