1 // -*- C++ -*-
2 
3 /*
4  * Gnome Chemistry Utils
5  * gcu/loader.cc
6  *
7  * Copyright (C) 2007-2011 Jean Bréfort <jean.brefort@normalesup.org>
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 3 of the
12  * License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
22  * USA
23  */
24 
25 #include "config.h"
26 #include "application.h"
27 #include "cmd-context.h"
28 #include "document.h"
29 #include "loader.h"
30 #include <gsf/gsf-impl-utils.h>
31 #include <glib/gi18n-lib.h>
32 #include <cstring>
33 
34 using namespace std;
35 
36 namespace gcu {
37 
38 static map<string, LoaderStruct> loaders;
39 static map<string, GOPluginService *> services;
40 
41 #define GCU_PLUGIN_SERVICE_CHEMICAL_LOADER_TYPE  (plugin_service_chemical_loader_get_type ())
42 #define GCU_PLUGIN_SERVICE_CHEMICAL_LOADER(o)    (G_TYPE_CHECK_INSTANCE_CAST ((o), GCU_PLUGIN_SERVICE_CHEMICAL_LOADER_TYPE, PluginServiceChemicalLoader))
43 #define IS_GCU_PLUGIN_SERVICE_CHEMICAL_LOADER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GCU_PLUGIN_SERVICE_CHEMICAL_LOADER_TYPE))
44 
45 GType plugin_service_chemical_loader_get_type (void);
46 typedef struct {
47 	GOPluginServiceSimple	base;
48 
49 } PluginServiceChemicalLoader;
50 typedef GOPluginServiceSimpleClass PluginServiceChemicalLoaderClass;
51 
52 static void
plugin_service_chemical_loader_read_xml(GOPluginService * service,xmlNode * tree,GOErrorInfo ** ret_error)53 plugin_service_chemical_loader_read_xml (GOPluginService * service, xmlNode * tree,
54 				    GOErrorInfo ** ret_error)
55 {
56 	xmlNode *ptr;
57 
58 	g_return_if_fail (service->id != NULL);
59 
60 	for (ptr = tree->xmlChildrenNode; ptr != NULL; ptr = ptr->next)
61 		if (0 == xmlStrcmp (ptr->name, (xmlChar const *) "mime_type"))
62 		{
63 			char *name = (char *) xmlGetProp (ptr, (xmlChar const *) "name");
64 			if (name) {
65 				if (loaders.find (name) != loaders.end ()) {
66 					*ret_error = go_error_info_new_printf ("Duplicate loader for mime type %s", name);
67 					xmlFree (name);
68 					return;
69 				}
70 				LoaderStruct l;
71 				l.read = l.write = l.supports2D = l.supports3D = l.supportsCrystals = l.supportsSpectra = false;
72 				l.loader = NULL;
73 				char *prop = (char *) xmlGetProp (ptr, (xmlChar const *) "capabilities");
74 				if (prop) {
75 					if (strchr (prop, 'r') != NULL)
76 						l.read = true;
77 					if (strchr (prop, 'w') != NULL)
78 						l.write = true;
79 					xmlFree (prop);
80 				}
81 				prop = (char *) xmlGetProp (ptr, (xmlChar const *) "scope");
82 				if (prop) {
83 					if (strchr (prop, '2') != NULL)
84 						l.supports2D = true;
85 					if (strchr (prop, '3') != NULL)
86 						l.supports3D = true;
87 					if (strchr (prop, 'c') != NULL || strchr (prop, 'C') != NULL)
88 						l.supportsCrystals = true;
89 					if (strchr (prop, 's') != NULL || strchr (prop, 'S') != NULL)
90 						l.supportsSpectra = true;
91 					xmlFree (prop);
92 				}
93 				loaders[name] = l;
94 				services[name] = service;
95 				xmlFree (name);
96 			}
97 		}
98 }
99 
100 static char *
plugin_service_chemical_loader_get_description(G_GNUC_UNUSED GOPluginService * service)101 plugin_service_chemical_loader_get_description (G_GNUC_UNUSED GOPluginService * service)
102 {
103 	return g_strdup (_("Chemical file loader type."));
104 }
105 
106 static void
plugin_service_chemical_loader_class_init(GObjectClass * gobject_class)107 plugin_service_chemical_loader_class_init (GObjectClass *gobject_class)
108 {
109 	GOPluginServiceClass *plugin_service_class = GO_PLUGIN_SERVICE_CLASS (gobject_class);
110 
111 	plugin_service_class->read_xml = plugin_service_chemical_loader_read_xml;
112 	plugin_service_class->get_description = plugin_service_chemical_loader_get_description;
113 }
114 
115 static void
plugin_service_chemical_loader_init(G_GNUC_UNUSED PluginServiceChemicalLoader * s)116 plugin_service_chemical_loader_init (G_GNUC_UNUSED PluginServiceChemicalLoader *s)
117 {
118 }
119 
GSF_CLASS(PluginServiceChemicalLoader,plugin_service_chemical_loader,plugin_service_chemical_loader_class_init,plugin_service_chemical_loader_init,GO_TYPE_PLUGIN_SERVICE_SIMPLE)120 GSF_CLASS (PluginServiceChemicalLoader, plugin_service_chemical_loader,
121            plugin_service_chemical_loader_class_init, plugin_service_chemical_loader_init,
122            GO_TYPE_PLUGIN_SERVICE_SIMPLE)
123 
124 Loader::Loader ()
125 {
126 }
127 
~Loader()128 Loader::~Loader ()
129 {
130 }
131 
132 bool Loader::Inited = false;
133 
Init(Application * app)134 void Loader::Init (Application *app)
135 {
136 	if (Inited)
137 		return;
138 	go_plugin_service_define ("chemical_loader",
139 		&plugin_service_chemical_loader_get_type);
140 	go_plugin_loader_module_register_version ("gchemutils", VERSION);
141 	char *plugins_dir = g_strdup (GCU_PLUGINS_DIR);
142 	GSList *dirs = g_slist_prepend (NULL, plugins_dir);
143 	go_plugins_init ((app->GetCmdContext ())? app->GetCmdContext ()->GetGOCmdContext (): NULL, NULL, NULL, dirs, true, GO_TYPE_PLUGIN_LOADER_MODULE);
144 	// do not free dirs and plugins_dir, goffice will
145 	Inited = true;
146 }
147 
GetFirstLoader(std::map<std::string,LoaderStruct>::iterator & it)148 bool Loader::GetFirstLoader (std::map<std::string, LoaderStruct>::iterator &it)
149 {
150 	it = loaders.begin ();
151 	return it != loaders.end ();
152 }
153 
GetNextLoader(std::map<std::string,LoaderStruct>::iterator & it)154 bool Loader::GetNextLoader (std::map<std::string, LoaderStruct>::iterator &it)
155 {
156 	it++;
157 	return it != loaders.end ();
158 }
159 
GetLoader(char const * mime_type)160 Loader *Loader::GetLoader (char const *mime_type)
161 {
162 	map<string, LoaderStruct>::iterator it = loaders.find (mime_type);
163 	if (it != loaders.end () && (*it).second.read) {
164 		if ((*it).second.loader == NULL) {
165 			GOErrorInfo *error = NULL;
166 			go_plugin_service_load (services[mime_type], &error);
167 			if (error) {
168 				g_warning ("%s", go_error_info_peek_message (error));
169 				g_free (error);
170 			}
171 		}
172 		return (*it).second.loader;
173 	} else
174 		return NULL;
175 }
176 
GetSaver(char const * mime_type)177 Loader *Loader::GetSaver (char const *mime_type)
178 {
179 	map<string, LoaderStruct>::iterator it = loaders.find (mime_type);
180 	if (it != loaders.end () && (*it).second.write) {
181 		if ((*it).second.loader == NULL) {
182 			GOErrorInfo *error = NULL;
183 			go_plugin_service_load (services[mime_type], &error);
184 			if (error) {
185 				g_warning ("%s", go_error_info_peek_message (error));
186 				g_free (error);
187 			}
188 		}
189 		return (*it).second.loader;
190 	} else
191 		return NULL;
192 }
193 
AddMimeType(const char * mime_type)194 void Loader::AddMimeType (const char *mime_type)
195 {
196 	MimeTypes.push_front (mime_type);
197 	map<string, LoaderStruct>::iterator it = loaders.find (mime_type);
198 	if (it != loaders.end ())
199 		(*it).second.loader = this;
200 }
201 
RemoveMimeType(const char * mime_type)202 void Loader::RemoveMimeType (const char *mime_type)
203 {
204 	MimeTypes.remove (mime_type);
205 	map<string, LoaderStruct>::iterator it = loaders.find (mime_type);
206 	if (it != loaders.end ())
207 		(*it).second.loader = NULL;
208 }
209 
Read(G_GNUC_UNUSED Document * doc,G_GNUC_UNUSED GsfInput * in,G_GNUC_UNUSED char const * mime_type,G_GNUC_UNUSED GOIOContext * io)210 ContentType Loader::Read (G_GNUC_UNUSED Document *doc, G_GNUC_UNUSED GsfInput *in, G_GNUC_UNUSED char const *mime_type, G_GNUC_UNUSED GOIOContext *io)
211 {
212 	return ContentTypeUnknown;
213 }
214 
Write(G_GNUC_UNUSED Object const * obj,G_GNUC_UNUSED GsfOutput * out,G_GNUC_UNUSED char const * mime_type,G_GNUC_UNUSED GOIOContext * io,G_GNUC_UNUSED ContentType type)215 bool Loader::Write (G_GNUC_UNUSED Object const *obj, G_GNUC_UNUSED GsfOutput *out, G_GNUC_UNUSED char const *mime_type, G_GNUC_UNUSED GOIOContext *io, G_GNUC_UNUSED ContentType type)
216 {
217 	return false;
218 }
219 
220 }
221