1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 Copyright (C) 2004 Sebastien Granjoux
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 * header data read in .wiz file, used in the first page (project selection)
24 *---------------------------------------------------------------------------*/
32 #include <glib/gdir.h>
33 #include <libanjuta/anjuta-utils.h>
35 /*---------------------------------------------------------------------------*/
37 #define STRING_CHUNK_SIZE 256
39 /*---------------------------------------------------------------------------*/
44 GStringChunk
* string_pool
;
54 GList
* required_programs
;
55 GList
* required_packages
;
61 *---------------------------------------------------------------------------*/
64 npw_header_new (NPWHeaderList
* owner
)
68 g_return_val_if_fail (owner
, NULL
);
70 this = g_chunk_new0(NPWHeader
, owner
->data_pool
);
72 this->node
= g_node_append_data (owner
->list
, this);
78 npw_header_free (NPWHeader
* this)
82 /* Memory allocated in string pool and project pool is not free */
83 node
= g_node_find (this->owner
->list
, G_IN_ORDER
, G_TRAVERSE_ALL
, this);
85 g_node_destroy (node
);
86 if (this->required_programs
)
87 g_list_free (this->required_programs
);
88 if (this->required_packages
)
89 g_list_free (this->required_packages
);
93 npw_header_set_name (NPWHeader
* this, const gchar
* name
)
95 this->name
= g_string_chunk_insert (this->owner
->string_pool
, name
);
99 npw_header_get_name (const NPWHeader
* this)
105 npw_header_set_filename (NPWHeader
* this, const gchar
* filename
)
107 this->filename
= g_string_chunk_insert (this->owner
->string_pool
, filename
);
111 npw_header_get_filename (const NPWHeader
* this)
113 return this->filename
;
117 npw_header_set_category (NPWHeader
* this, const gchar
* category
)
119 npw_header_list_organize(this->owner
, category
, this);
120 this->category
= ((NPWHeader
*)this->node
->parent
->data
)->category
;
124 npw_header_get_category (const NPWHeader
* this)
126 return this->category
;
130 npw_header_set_description (NPWHeader
* this, const gchar
* description
)
132 this->description
= g_string_chunk_insert (this->owner
->string_pool
, description
);
136 npw_header_get_description (const NPWHeader
* this)
138 return this->description
;
142 npw_header_set_iconfile (NPWHeader
* this, const gchar
* iconfile
)
144 this->iconfile
= g_string_chunk_insert (this->owner
->string_pool
, iconfile
);
148 npw_header_get_iconfile (const NPWHeader
* this)
150 return this->iconfile
;
154 npw_header_add_required_program (NPWHeader
* this, const gchar
* program
)
156 this->required_programs
=
157 g_list_prepend (this->required_programs
,
158 g_string_chunk_insert (this->owner
->string_pool
,
164 npw_header_add_required_package (NPWHeader
* this, const gchar
* package
)
166 this->required_packages
=
167 g_list_prepend (this->required_packages
,
168 g_string_chunk_insert (this->owner
->string_pool
,
173 npw_header_check_required_programs (NPWHeader
* this)
176 GList
*failed_programs
= NULL
;
177 for (node
= this->required_programs
; node
; node
= g_list_next (node
))
179 if (!anjuta_util_prog_is_installed (node
->data
, FALSE
))
181 failed_programs
= g_list_prepend (failed_programs
, node
->data
);
184 return failed_programs
;
188 package_is_installed (const gchar
*package
)
193 if ((pid
= fork()) == 0)
195 execlp ("pkg-config", "pkg-config", "--exists", package
, NULL
);
197 waitpid (pid
, &status
, 0);
198 exit_status
= WEXITSTATUS (status
);
199 return (exit_status
== 0);
203 npw_header_check_required_packages (NPWHeader
* this)
206 GList
*failed_packages
= NULL
;
207 for (node
= this->required_packages
; node
; node
= g_list_next (node
))
209 if (!package_is_installed (node
->data
))
211 failed_packages
= g_list_prepend (failed_packages
, node
->data
);
214 return failed_packages
;
218 npw_header_is_leaf(const NPWHeader
* this)
220 return G_NODE_IS_LEAF(this->node
);
225 *---------------------------------------------------------------------------*/
228 npw_header_list_find_parent(NPWHeaderList
* this, const gchar
* category
, gboolean create
)
233 for (node
= g_node_first_child(this->list
); node
!= NULL
; node
= g_node_next_sibling(node
))
237 s
= ((NPWHeader
*)node
->data
)->category
;
240 order
= g_ascii_strcasecmp (s
, category
);
243 /* Find right category */
250 /* Category doesn't exist create a new node */
251 NPWHeader
* new_parent
;
253 new_parent
= npw_header_new (this);
254 new_parent
->category
= g_string_chunk_insert (this->string_pool
, category
);
255 g_node_unlink (new_parent
->node
);
256 g_node_insert_before (this->list
, node
, new_parent
->node
);
257 node
= new_parent
->node
;
268 if (create
&& (node
== NULL
))
270 NPWHeader
* new_parent
;
272 new_parent
= npw_header_new (this);
273 new_parent
->category
= g_string_chunk_insert (this->string_pool
, category
);
274 node
= new_parent
->node
;
280 typedef struct _HeaderListForeachProjectData
282 NPWHeaderForeachFunc func
;
284 } HeaderListForeachProjectData
;
287 cb_header_list_foreach_project (GNode
* node
, gpointer data
)
289 HeaderListForeachProjectData
* d
= (HeaderListForeachProjectData
*)data
;
291 (d
->func
)((NPWHeader
*)node
->data
, d
->data
);
295 npw_header_list_foreach_node (GNode
* list
, NPWHeaderForeachFunc func
, gpointer data
, GTraverseFlags flag
)
297 HeaderListForeachProjectData d
;
299 if (g_node_first_child (list
) == NULL
) return FALSE
;
304 g_node_children_foreach (list
, flag
, cb_header_list_foreach_project
, &d
);
309 /*---------------------------------------------------------------------------*/
312 npw_header_list_new (void)
316 this = g_new (NPWHeaderList
, 1);
317 this->string_pool
= g_string_chunk_new (STRING_CHUNK_SIZE
);
318 this->data_pool
= g_mem_chunk_new ("project pool", sizeof (NPWHeader
), STRING_CHUNK_SIZE
* sizeof (NPWHeader
) / 4, G_ALLOC_ONLY
);
319 this->list
= g_node_new (NULL
);
325 npw_header_list_free (NPWHeaderList
* this)
327 g_return_if_fail (this != NULL
);
329 g_string_chunk_free (this->string_pool
);
330 g_mem_chunk_destroy (this->data_pool
);
331 g_node_destroy (this->list
);
336 npw_header_list_organize(NPWHeaderList
* this, const gchar
* category
, NPWHeader
* header
)
342 /* node without a category stay on top */
343 if ((category
== NULL
) || (*category
== '\0')) return;
345 /* Detach the node */
346 g_node_unlink(header
->node
);
349 parent
= npw_header_list_find_parent(this, category
, TRUE
);
351 /* Insert node as a child in alphabetic order*/
352 name
= npw_header_get_name (header
);
353 for (node
= g_node_first_child(parent
); node
!= NULL
; node
= g_node_next_sibling(node
))
355 if (g_ascii_strcasecmp (npw_header_get_name ((NPWHeader
*)node
->data
), name
) > 0)
357 g_node_insert_before (parent
, node
, header
->node
);
361 g_node_insert(parent
, -1, header
->node
);
365 npw_header_list_foreach_project (const NPWHeaderList
* this, NPWHeaderForeachFunc func
, gpointer data
)
367 return npw_header_list_foreach_node (this->list
, func
, data
, G_TRAVERSE_LEAFS
);
371 npw_header_list_foreach_project_in (const NPWHeaderList
* this, const gchar
* category
, NPWHeaderForeachFunc func
, gpointer data
)
375 /* FIXME: const modified has been removed because the find function
376 * with TRUE as the third argument could create a parent if it
377 * doesn't exist. It could be better to split this function in two */
378 node
= npw_header_list_find_parent((NPWHeaderList
*)this, category
, FALSE
);
379 if (node
== NULL
) return FALSE
;
381 return npw_header_list_foreach_node (node
, func
, data
, G_TRAVERSE_LEAFS
);
385 npw_header_list_foreach_category (const NPWHeaderList
* this, NPWHeaderForeachFunc func
, gpointer data
)
387 return npw_header_list_foreach_node (this->list
, func
, data
, G_TRAVERSE_NON_LEAFS
);