Code

switch from invokeBbox to getBounds (need to fix problems with empty
[inkscape.git] / src / extension / dependency.cpp
1 /*
2  * Author:
3  *   Ted Gould <ted@gould.cx>
4  *
5  * Copyright (C) 2006 Johan Engelen, johan@shouraizou.nl
6  * Copyright (C) 2004 Author
7  *
8  * Released under GNU GPL, read the file 'COPYING' for more information
9  */
11 #ifdef HAVE_CONFIG_H
12 #include "config.h"
13 #endif
15 #include <glibmm/i18n.h>
16 #include "config.h"
17 #include "path-prefix.h"
18 #include "dependency.h"
19 #include "db.h"
21 namespace Inkscape {
22 namespace Extension {
24 // These strings are for XML attribute comparisons and should not be translated
25 gchar const * Dependency::_type_str[] = {
26     "executable",
27     "file",
28     "extension",
29     "plugin",
30 };
32 // These strings are for XML attribute comparisons and should not be translated
33 gchar const * Dependency::_location_str[] = {
34     "path",
35     "extensions",
36     "absolute",
37 };
39 /**
40     \brief   Create a dependency using an XML definition
41     \param   in_repr   XML definition of the dependency
43     This function mostly looks for the 'location' and 'type' attributes
44     and turns them into the enums of the same name.  This makes things
45     a little bit easier to use later.  Also, a pointer to the core
46     content is pulled out -- also to make things easier.
47 */
48 Dependency::Dependency (Inkscape::XML::Node * in_repr)
49 {
50     _type = TYPE_FILE;
51     _location = LOCATION_PATH;
52     _repr = in_repr;
53     _string = NULL;
54     _description = NULL;
56     Inkscape::GC::anchor(_repr);
58     const gchar * location = _repr->attribute("location");
59     for (int i = 0; i < LOCATION_CNT && location != NULL; i++) {
60         if (!strcmp(location, _location_str[i])) {
61             _location = (location_t)i;
62             break;
63         }
64     }
66     const gchar * type = _repr->attribute("type");
67     for (int i = 0; i < TYPE_CNT && type != NULL; i++) {
68         if (!strcmp(type, _type_str[i])) {
69             _type = (type_t)i;
70             break;
71         }
72     }
74     _string = sp_repr_children(_repr)->content();
76     _description = _repr->attribute("description");
77     if (_description == NULL)
78         _description = _repr->attribute("_description");
80     return;
81 }
83 /**
84     \brief   This depenency is not longer needed
86     Unreference the XML structure.
87 */
88 Dependency::~Dependency (void)
89 {
90     Inkscape::GC::release(_repr);
91 }
93 /**
94     \brief   Check if the dependency passes.
95     \return  Whether or not the dependency passes.
97     This function depends largely on all of the enums.  The first level
98     that is evaluted is the \c _type.
100     If the type is \c TYPE_EXTENSION then the id for the extension is
101     looked up in the database.  If the extension is found, and it is
102     not deactivated, the dependency passes.
104     If the type is \c TYPE_PLUGIN then the path for the plugin is found
105     using the Glib::Module routines.  When the path is found, then there
106     is a check to see if the file exists using the \c file_test function.
108     If the type is \c TYPE_EXECUTABLE or \c TYPE_FILE things are getting
109     even more interesting because now the \c _location variable is also
110     taken into account.  First, the difference between the two is that
111     the file test for \c TYPE_EXECUTABLE also tests to make sure the
112     file is executable, besides checking that it exists.
114     If the \c _location is \c LOCATION_EXTENSIONS then the \c INKSCAPE_EXTENSIONDIR
115     is put on the front of the string with \c build_filename.  Then the
116     appopriate filetest is run.
118     If the \c _location is \c LOCATION_ABSOLUTE then the file test is
119     run directly on the string.
121     If the \c _location is \c LOCATION_PATH or not specified then the
122     path is used to find the file.  Each entry in the path is stepped
123     through, attached to the string, and then tested.  If the file is
124     found then a TRUE is returned.  If we get all the way through the
125     path then a FALSE is returned, the command could not be found.
126 */
127 bool
128 Dependency::check (void) const
130     // std::cout << "Checking: " << *this << std::endl;
132     if (_string == NULL) return FALSE;
134     switch (_type) {
135         case TYPE_EXTENSION: {
136             Extension * myext = db.get(_string);
137             if (myext == NULL) return FALSE;
138             if (myext->deactivated()) return FALSE;
139             break;
140         }
141         case TYPE_PLUGIN: {
142             if (!Glib::Module::get_supported()) {
143                 return FALSE;
144             }
146             std::string path = Glib::Module::build_path(INKSCAPE_PLUGINDIR, _string);
147             if (!Glib::file_test(path, Glib::FILE_TEST_EXISTS))
148                 return FALSE;
149             break;
150         }
151         case TYPE_EXECUTABLE:
152         case TYPE_FILE: {
153             Glib::FileTest filetest = Glib::FILE_TEST_EXISTS;
154             if (_type == TYPE_EXECUTABLE) {
155                 filetest |= Glib::FILE_TEST_IS_EXECUTABLE;
156             }
158             std::string location(_string);
159             switch (_location) {
160                 case LOCATION_EXTENSIONS: {
161                     for (unsigned int i=0; i<Inkscape::Extension::Extension::search_path.size(); i++) {
162                         std::string temploc = Glib::build_filename(Inkscape::Extension::Extension::search_path[i], location);
163                         if (Glib::file_test(temploc, filetest)) {
164                             location = temploc;
165                             break;
166                         }
167                     }
168                 } /* PASS THROUGH!!! */
169                 case LOCATION_ABSOLUTE: {
170                     if (!Glib::file_test(location, filetest)) {
171                         // std::cout << "Failing on location: " << location << std::endl;
172                         return FALSE;
173                     }
174                     break;
175                 }
176                 /* The default case is to look in the path */
177                 case LOCATION_PATH:
178                 default: {
179                     gchar * path = g_strdup(g_getenv("PATH"));
181                     if (path == NULL) {
182                         /* There is no `PATH' in the environment.
183                            The default search path is the current directory */
184                         path = g_strdup(G_SEARCHPATH_SEPARATOR_S);
185                     }
187                     gchar * orig_path = path;
189                     for (; path != NULL;) {
190                         gchar * local_path;
191                         gchar * final_name;
193                         local_path = path;
194                         path = g_utf8_strchr(path, -1, G_SEARCHPATH_SEPARATOR);
195                         /* Not sure whether this is UTF8 happy, but it would seem
196                            like it considering that I'm searching (and finding)
197                            the ':' character */
198                         if (path != local_path && path != NULL) {
199                             path[0] = '\0';
200                             path++;
201                         } else {
202                             path = NULL;
203                         }
205                         if (local_path == '\0') {
206                             final_name = g_strdup(_string);
207                         } else {
208                             final_name = g_build_filename(local_path, _string, NULL);
209                         }
211                         if (Glib::file_test(final_name, filetest)) {
212                             g_free(final_name);
213                             g_free(orig_path);
214                             return TRUE;
215                         }
216                         // give it a 2nd try with ".exe" added
217                         gchar * final_name_exe = g_strdup_printf ("%s.exe", final_name);                        
218                         if (Glib::file_test(final_name_exe, filetest)) {
219                             g_free(final_name);
220                             g_free(final_name_exe);
221                             g_free(orig_path);
222                             return TRUE;
223                         }
225                         g_free(final_name);
226                         g_free(final_name_exe);
227                     }
229                     g_free(orig_path);
230                     return FALSE; /* Reverse logic in this one */
231                     break;
232                 }
233             } /* switch _location */
234             break;
235         } /* TYPE_FILE, TYPE_EXECUTABLE */
236         default:
237             return FALSE;
238     } /* switch _type */
240     return TRUE;
243 /**
244     \brief   Print out a dependency to a string.
245 */
246 std::ostream &
247 operator<< (std::ostream &out_file, const Dependency & in_dep)
249     out_file << _("Dependency:") << '\n';
250     out_file << _("  type: ") << _(in_dep._type_str[in_dep._type]) << '\n';
251     out_file << _("  location: ") << _(in_dep._location_str[in_dep._location]) << '\n';
252     out_file << _("  string: ") << in_dep._string << '\n';
254     if (in_dep._description != NULL) {
255         out_file << _("  description: ") << _(in_dep._description) << '\n';
256     }
258     out_file << std::flush;
260     return out_file;
263 } }  /* namespace Inkscape, Extension */
265 /*
266   Local Variables:
267   mode:c++
268   c-file-style:"stroustrup"
269   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
270   indent-tabs-mode:nil
271   fill-column:99
272   End:
273 */
274 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :