Code

Node tool: special case node duplication for endnodes - select new endnode
[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 };
31 // These strings are for XML attribute comparisons and should not be translated
32 gchar const * Dependency::_location_str[] = {
33     "path",
34     "extensions",
35     "absolute",
36 };
38 /**
39     \brief   Create a dependency using an XML definition
40     \param   in_repr   XML definition of the dependency
42     This function mostly looks for the 'location' and 'type' attributes
43     and turns them into the enums of the same name.  This makes things
44     a little bit easier to use later.  Also, a pointer to the core
45     content is pulled out -- also to make things easier.
46 */
47 Dependency::Dependency (Inkscape::XML::Node * in_repr)
48 {
49     _type = TYPE_FILE;
50     _location = LOCATION_PATH;
51     _repr = in_repr;
52     _string = NULL;
53     _description = NULL;
55     Inkscape::GC::anchor(_repr);
57     const gchar * location = _repr->attribute("location");
58     for (int i = 0; i < LOCATION_CNT && location != NULL; i++) {
59         if (!strcmp(location, _location_str[i])) {
60             _location = (location_t)i;
61             break;
62         }
63     }
65     const gchar * type = _repr->attribute("type");
66     for (int i = 0; i < TYPE_CNT && type != NULL; i++) {
67         if (!strcmp(type, _type_str[i])) {
68             _type = (type_t)i;
69             break;
70         }
71     }
73     _string = sp_repr_children(_repr)->content();
75     _description = _repr->attribute("description");
76     if (_description == NULL)
77         _description = _repr->attribute("_description");
79     return;
80 }
82 /**
83     \brief   This depenency is not longer needed
85     Unreference the XML structure.
86 */
87 Dependency::~Dependency (void)
88 {
89     Inkscape::GC::release(_repr);
90 }
92 /**
93     \brief   Check if the dependency passes.
94     \return  Whether or not the dependency passes.
96     This function depends largely on all of the enums.  The first level
97     that is evaluted is the \c _type.
99     If the type is \c TYPE_EXTENSION then the id for the extension is
100     looked up in the database.  If the extension is found, and it is
101     not deactivated, the dependency passes.
103     If the type is \c TYPE_EXECUTABLE or \c TYPE_FILE things are getting
104     even more interesting because now the \c _location variable is also
105     taken into account.  First, the difference between the two is that
106     the file test for \c TYPE_EXECUTABLE also tests to make sure the
107     file is executable, besides checking that it exists.
109     If the \c _location is \c LOCATION_EXTENSIONS then the \c INKSCAPE_EXTENSIONDIR
110     is put on the front of the string with \c build_filename.  Then the
111     appopriate filetest is run.
113     If the \c _location is \c LOCATION_ABSOLUTE then the file test is
114     run directly on the string.
116     If the \c _location is \c LOCATION_PATH or not specified then the
117     path is used to find the file.  Each entry in the path is stepped
118     through, attached to the string, and then tested.  If the file is
119     found then a TRUE is returned.  If we get all the way through the
120     path then a FALSE is returned, the command could not be found.
121 */
122 bool
123 Dependency::check (void) const
125     // std::cout << "Checking: " << *this << std::endl;
127     if (_string == NULL) return FALSE;
129     switch (_type) {
130         case TYPE_EXTENSION: {
131             Extension * myext = db.get(_string);
132             if (myext == NULL) return FALSE;
133             if (myext->deactivated()) return FALSE;
134             break;
135         }
136         case TYPE_EXECUTABLE:
137         case TYPE_FILE: {
138             Glib::FileTest filetest = Glib::FILE_TEST_EXISTS;
139             if (_type == TYPE_EXECUTABLE) {
140                 filetest |= Glib::FILE_TEST_IS_EXECUTABLE;
141             }
143             std::string location(_string);
144             switch (_location) {
145                 case LOCATION_EXTENSIONS: {
146                     for (unsigned int i=0; i<Inkscape::Extension::Extension::search_path.size(); i++) {
147                         std::string temploc = Glib::build_filename(Inkscape::Extension::Extension::search_path[i], location);
148                         if (Glib::file_test(temploc, filetest)) {
149                             location = temploc;
150                             break;
151                         }
152                     }
153                 } /* PASS THROUGH!!! */
154                 case LOCATION_ABSOLUTE: {
155                     if (!Glib::file_test(location, filetest)) {
156                         // std::cout << "Failing on location: " << location << std::endl;
157                         return FALSE;
158                     }
159                     break;
160                 }
161                 /* The default case is to look in the path */
162                 case LOCATION_PATH:
163                 default: {
164                     gchar * path = g_strdup(g_getenv("PATH"));
166                     if (path == NULL) {
167                         /* There is no `PATH' in the environment.
168                            The default search path is the current directory */
169                         path = g_strdup(G_SEARCHPATH_SEPARATOR_S);
170                     }
172                     gchar * orig_path = path;
174                     for (; path != NULL;) {
175                         gchar * local_path;
176                         gchar * final_name;
178                         local_path = path;
179                         path = g_utf8_strchr(path, -1, G_SEARCHPATH_SEPARATOR);
180                         /* Not sure whether this is UTF8 happy, but it would seem
181                            like it considering that I'm searching (and finding)
182                            the ':' character */
183                         if (path != local_path && path != NULL) {
184                             path[0] = '\0';
185                             path++;
186                         } else {
187                             path = NULL;
188                         }
190                         if (local_path == '\0') {
191                             final_name = g_strdup(_string);
192                         } else {
193                             final_name = g_build_filename(local_path, _string, NULL);
194                         }
196                         if (Glib::file_test(final_name, filetest)) {
197                             g_free(final_name);
198                             g_free(orig_path);
199                             return TRUE;
200                         }
202                         // give it a 2nd try with ".exe" added
203                         gchar * final_name_exe = g_strdup_printf("%s.exe", final_name);                        
204                         if (Glib::file_test(final_name_exe, filetest)) {
205                             g_free(final_name);
206                             g_free(final_name_exe);
207                             g_free(orig_path);
208                             return TRUE;
209                         }
210                         g_free(final_name_exe);
212                         // and a 3rd try with ".cmd" added (mainly for UniConvertor)
213                         gchar * final_name_cmd = g_strdup_printf("%s.cmd", final_name);
214                         if (Glib::file_test(final_name_cmd, filetest)) {
215                             g_free(final_name);
216                             g_free(final_name_cmd);
217                             g_free(orig_path);
218                             return TRUE;
219                         }
220                         g_free(final_name_cmd);
222                         // give up
223                         g_free(final_name);
224                     }
226                     g_free(orig_path);
227                     return FALSE; /* Reverse logic in this one */
228                     break;
229                 }
230             } /* switch _location */
231             break;
232         } /* TYPE_FILE, TYPE_EXECUTABLE */
233         default:
234             return FALSE;
235     } /* switch _type */
237     return TRUE;
240 /**
241     \brief   Print out a dependency to a string.
242 */
243 std::ostream &
244 operator<< (std::ostream &out_file, const Dependency & in_dep)
246     out_file << _("Dependency:") << '\n';
247     out_file << _("  type: ") << _(in_dep._type_str[in_dep._type]) << '\n';
248     out_file << _("  location: ") << _(in_dep._location_str[in_dep._location]) << '\n';
249     out_file << _("  string: ") << in_dep._string << '\n';
251     if (in_dep._description != NULL) {
252         out_file << _("  description: ") << _(in_dep._description) << '\n';
253     }
255     out_file << std::flush;
257     return out_file;
260 } }  /* namespace Inkscape, Extension */
262 /*
263   Local Variables:
264   mode:c++
265   c-file-style:"stroustrup"
266   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
267   indent-tabs-mode:nil
268   fill-column:99
269   End:
270 */
271 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :