Avoid linking programs with plugin libraries
[anjuta.git] / libanjuta / anjuta-plugin-description.c
blob8cbbe7e02edc9dae2b3c1d63420b819041975643
1 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 4 -*- */
2 /*
3 * AnjutaPluginDescription - Plugin meta data
4 * anjuta-plugin-description.c Copyright (C) 2002 Red Hat, Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library 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 GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
22 /**
23 * SECTION:anjuta-plugin-description
24 * @title: AnjutaPluginDescription
25 * @short_description: Plugin description from .plugin file
26 * @see_also: #AnjutaPlugin, #AnjutaPluginHandle
27 * @stability: Unstable
28 * @include: libanjuta/anjuta-plugin-description.h
32 #include <string.h>
33 #include <locale.h>
34 #include <stdlib.h>
36 #include <libanjuta/anjuta-plugin-description.h>
38 typedef struct _AnjutaPluginDescriptionSection AnjutaPluginDescriptionSection;
39 typedef struct _AnjutaPluginDescriptionLine AnjutaPluginDescriptionLine;
40 typedef struct _AnjutaPluginDescriptionParser AnjutaPluginDescriptionParser;
42 struct _AnjutaPluginDescriptionSection {
43 GQuark section_name; /* 0 means just a comment block (before any section) */
44 gint n_lines;
45 gint n_allocated;
46 AnjutaPluginDescriptionLine *lines;
49 struct _AnjutaPluginDescriptionLine {
50 GQuark key; /* 0 means comment or blank line in value */
51 char *locale;
52 gchar *value;
53 GList *override; /* A list of previous value */
56 struct _AnjutaPluginDescription {
57 gint n_sections;
58 gint n_allocated;
59 AnjutaPluginDescriptionSection *sections;
60 char *current_locale[2];
63 struct _AnjutaPluginDescriptionParser {
64 AnjutaPluginDescription *df;
65 gint current_section;
66 gint line_nr;
67 char *line;
70 #define VALID_KEY_CHAR 1
71 #define VALID_LOCALE_CHAR 2
72 guchar valid[256] = {
73 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
74 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
75 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x3 , 0x2 , 0x0 ,
76 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
77 0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 ,
78 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x0 , 0x0 , 0x0 , 0x2 ,
79 0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 ,
80 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
81 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
82 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
83 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
84 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
85 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
86 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
87 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
88 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
91 static void report_error (AnjutaPluginDescriptionParser *parser,
92 char *message,
93 AnjutaPluginDescriptionParseError error_code,
94 GError **error);
96 static AnjutaPluginDescriptionSection *lookup_section (AnjutaPluginDescription *df,
97 const char *section);
99 static AnjutaPluginDescriptionLine *lookup_line (AnjutaPluginDescription *df,
100 AnjutaPluginDescriptionSection *section,
101 const char *keyname,
102 const char *locale);
104 GQuark
105 anjuta_plugin_description_parse_error_quark (void)
107 static GQuark quark;
108 if (!quark)
109 quark = g_quark_from_static_string ("g_desktop_parse_error");
111 return quark;
114 static void
115 parser_free (AnjutaPluginDescriptionParser *parser)
117 anjuta_plugin_description_free (parser->df);
120 static void
121 anjuta_plugin_description_line_free (AnjutaPluginDescriptionLine *line)
123 g_list_free_full (line->override, (GDestroyNotify)g_free);
124 g_free (line->locale);
125 g_free (line->value);
128 static void
129 anjuta_plugin_description_section_free (AnjutaPluginDescriptionSection *section)
131 int i;
133 for (i = 0; i < section->n_lines; i++)
134 anjuta_plugin_description_line_free (&section->lines[i]);
136 g_free (section->lines);
140 * anjuta_plugin_description_free:
141 * @df: an #AnjutaPluginDescription object
143 * Frees the #AnjutaPluginDescription instance.
145 void
146 anjuta_plugin_description_free (AnjutaPluginDescription *df)
148 int i;
150 for (i = 0; i < df->n_sections; i++)
151 for (i = 0; i < df->n_sections; i++)
152 anjuta_plugin_description_section_free (&df->sections[i]);
153 g_free (df->sections);
154 g_free (df->current_locale[0]);
155 g_free (df->current_locale[1]);
157 g_free (df);
160 static void
161 grow_lines (AnjutaPluginDescriptionSection *section)
163 int new_n_lines;
165 if (section->n_allocated == 0)
166 new_n_lines = 1;
167 else
168 new_n_lines = section->n_allocated*2;
170 section->lines = g_realloc (section->lines,
171 sizeof (AnjutaPluginDescriptionLine) * new_n_lines);
172 section->n_allocated = new_n_lines;
175 static void
176 grow_sections (AnjutaPluginDescription *df)
178 int new_n_sections;
180 if (df->n_allocated == 0)
181 new_n_sections = 1;
182 else
183 new_n_sections = df->n_allocated*2;
185 df->sections = g_realloc (df->sections,
186 sizeof (AnjutaPluginDescriptionSection) * new_n_sections);
187 df->n_allocated = new_n_sections;
190 static gchar *
191 unescape_string (gchar *str, gint len)
193 gchar *res;
194 gchar *p, *q;
195 gchar *end;
197 /* len + 1 is enough, because unescaping never makes the
198 * string longer */
199 res = g_new (gchar, len + 1);
200 p = str;
201 q = res;
202 end = str + len;
204 while (p < end)
206 if (*p == 0)
208 /* Found an embedded null */
209 g_free (res);
210 return NULL;
212 if (*p == '\\')
214 p++;
215 if (p >= end)
217 /* Escape at end of string */
218 g_free (res);
219 return NULL;
222 switch (*p)
224 case 's':
225 *q++ = ' ';
226 break;
227 case 't':
228 *q++ = '\t';
229 break;
230 case 'n':
231 *q++ = '\n';
232 break;
233 case 'r':
234 *q++ = '\r';
235 break;
236 case '\\':
237 *q++ = '\\';
238 break;
239 default:
240 /* Invalid escape code */
241 g_free (res);
242 return NULL;
244 p++;
246 else
247 *q++ = *p++;
249 *q = 0;
251 return res;
254 static gchar *
255 escape_string (const gchar *str, gboolean escape_first_space)
257 gchar *res;
258 char *q;
259 const gchar *p;
261 /* len + 1 is enough, because unescaping never makes the
262 * string longer */
263 res = g_new (gchar, strlen (str)*2 + 1);
265 p = str;
266 q = res;
268 while (*p)
270 if (*p == ' ')
272 if (escape_first_space && p == str)
274 *q++ = '\\';
275 *q++ = 's';
277 else
278 *q++ = ' ';
280 else if (*p == '\\')
282 *q++ = '\\';
283 *q++ = '\\';
285 else if (*p == '\t')
287 *q++ = '\\';
288 *q++ = 't';
290 else if (*p == '\n')
292 *q++ = '\\';
293 *q++ = 'n';
295 else if (*p == '\r')
297 *q++ = '\\';
298 *q++ = 'r';
300 else
301 *q++ = *p;
302 p++;
304 *q = 0;
306 return res;
310 static gint
311 create_section (AnjutaPluginDescription *df,
312 const char *name,
313 gboolean first)
315 gint n;
317 if (df->n_allocated == df->n_sections)
318 grow_sections (df);
320 if (first &&
321 df->sections[0].section_name == 0 &&
322 df->sections[0].n_lines == 0)
324 if (!name)
325 g_warning ("non-initial NULL section\n");
327 /* The initial section was empty. Piggyback on it. */
328 df->sections[0].section_name = g_quark_from_string (name);
330 return 0;
333 n = df->n_sections++;
335 if (name)
336 df->sections[n].section_name = g_quark_from_string (name);
337 else
338 df->sections[n].section_name = 0;
339 df->sections[n].n_lines = 0;
340 df->sections[n].n_allocated = 0;
341 df->sections[n].lines = NULL;
343 grow_lines (&df->sections[n]);
345 return n;
348 static AnjutaPluginDescriptionLine *
349 new_line (AnjutaPluginDescriptionSection *section)
351 AnjutaPluginDescriptionLine *line;
353 if (section->n_allocated == section->n_lines)
354 grow_lines (section);
356 line = &section->lines[section->n_lines++];
358 memset (line, 0, sizeof (AnjutaPluginDescriptionLine));
360 return line;
363 static gboolean
364 is_blank_line (AnjutaPluginDescriptionParser *parser)
366 gchar *p;
368 p = parser->line;
370 while (*p && *p != '\n')
372 if (!g_ascii_isspace (*p))
373 return FALSE;
375 p++;
377 return TRUE;
380 static void
381 parse_comment_or_blank (AnjutaPluginDescriptionParser *parser)
383 AnjutaPluginDescriptionLine *line;
384 gchar *line_end;
386 line_end = strchr (parser->line, '\n');
387 if (line_end == NULL)
388 line_end = parser->line + strlen (parser->line);
390 line = new_line (&parser->df->sections[parser->current_section]);
391 line->value = g_strndup (parser->line, line_end - parser->line);
393 parser->line = (line_end) ? line_end + 1 : NULL;
394 parser->line_nr++;
397 static gboolean
398 parse_section_start (AnjutaPluginDescriptionParser *parser, GError **error)
400 gchar *line_end;
401 gchar *section_name;
403 line_end = strchr (parser->line, '\n');
404 if (line_end == NULL)
405 line_end = parser->line + strlen (parser->line);
407 if (line_end - parser->line <= 2 ||
408 line_end[-1] != ']')
410 report_error (parser, "Invalid syntax for section header", ANJUTA_PLUGIN_DESCRIPTION_PARSE_ERROR_INVALID_SYNTAX, error);
411 parser_free (parser);
412 return FALSE;
415 section_name = unescape_string (parser->line + 1, line_end - parser->line - 2);
417 if (section_name == NULL)
419 report_error (parser, "Invalid escaping in section name", ANJUTA_PLUGIN_DESCRIPTION_PARSE_ERROR_INVALID_ESCAPES, error);
420 parser_free (parser);
421 return FALSE;
424 parser->current_section = create_section (parser->df, section_name, parser->current_section == 0);
426 parser->line = (line_end) ? line_end + 1 : NULL;
427 parser->line_nr++;
429 g_free (section_name);
431 return TRUE;
434 static gboolean
435 parse_key_value (AnjutaPluginDescriptionParser *parser, GError **error)
437 AnjutaPluginDescriptionLine *line;
438 gchar *line_end;
439 gchar *key_start;
440 gchar *key_end;
441 gchar *key;
442 gchar *locale_start = NULL;
443 gchar *locale_end = NULL;
444 gchar *value_start;
445 gchar *value;
446 gchar *p;
448 line_end = strchr (parser->line, '\n');
449 if (line_end == NULL)
450 line_end = parser->line + strlen (parser->line);
452 p = parser->line;
453 key_start = p;
454 while (p < line_end &&
455 (valid[(guchar)*p] & VALID_KEY_CHAR))
456 p++;
457 key_end = p;
459 if (key_start == key_end)
461 report_error (parser, "Empty key name", ANJUTA_PLUGIN_DESCRIPTION_PARSE_ERROR_INVALID_SYNTAX, error);
462 parser_free (parser);
463 return FALSE;
466 if (p < line_end && *p == '[')
468 p++;
469 locale_start = p;
470 while (p < line_end && *p != ']')
471 p++;
472 locale_end = p;
474 if (p == line_end)
476 report_error (parser, "Unterminated locale specification in key", ANJUTA_PLUGIN_DESCRIPTION_PARSE_ERROR_INVALID_SYNTAX, error);
477 parser_free (parser);
478 return FALSE;
481 p++;
484 /* Skip space before '=' */
485 while (p < line_end && *p == ' ')
486 p++;
488 if (p < line_end && *p != '=')
490 report_error (parser, "Invalid characters in key name", ANJUTA_PLUGIN_DESCRIPTION_PARSE_ERROR_INVALID_CHARS, error);
491 parser_free (parser);
492 return FALSE;
495 if (p == line_end)
497 report_error (parser, "No '=' in key/value pair", ANJUTA_PLUGIN_DESCRIPTION_PARSE_ERROR_INVALID_SYNTAX, error);
498 parser_free (parser);
499 return FALSE;
502 /* Skip the '=' */
503 p++;
505 /* Skip space after '=' */
506 while (p < line_end && *p == ' ')
507 p++;
509 value_start = p;
511 value = unescape_string (value_start, line_end - value_start);
512 if (value == NULL)
514 report_error (parser, "Invalid escaping in value", ANJUTA_PLUGIN_DESCRIPTION_PARSE_ERROR_INVALID_ESCAPES, error);
515 parser_free (parser);
516 return FALSE;
519 line = new_line (&parser->df->sections[parser->current_section]);
520 key = g_strndup (key_start, key_end - key_start);
521 line->key = g_quark_from_string (key);
522 g_free (key);
523 if (locale_start)
524 line->locale = g_strndup (locale_start, locale_end - locale_start);
525 line->value = value;
527 parser->line = (*line_end) ? line_end + 1 : NULL;
528 parser->line_nr++;
530 return TRUE;
534 static void
535 report_error (AnjutaPluginDescriptionParser *parser,
536 char *message,
537 AnjutaPluginDescriptionParseError error_code,
538 GError **error)
540 AnjutaPluginDescriptionSection *section;
541 const gchar *section_name = NULL;
543 section = &parser->df->sections[parser->current_section];
545 if (section->section_name)
546 section_name = g_quark_to_string (section->section_name);
548 if (error)
550 if (section_name)
551 *error = g_error_new (ANJUTA_PLUGIN_DESCRIPTION_PARSE_ERROR,
552 error_code,
553 "Error in section %s at line %d: %s", section_name, parser->line_nr, message);
554 else
555 *error = g_error_new (ANJUTA_PLUGIN_DESCRIPTION_PARSE_ERROR,
556 error_code,
557 "Error at line %d: %s", parser->line_nr, message);
561 AnjutaPluginDescription*
562 anjuta_plugin_description_copy (AnjutaPluginDescription *df)
564 return anjuta_plugin_description_new_from_string (anjuta_plugin_description_to_string (df),
565 NULL);
568 GType
569 anjuta_plugin_description_get_type (void)
571 static GType type_id = 0;
573 if (!type_id)
574 type_id = g_boxed_type_register_static ("AnjutaPluginDescription",
575 (GBoxedCopyFunc) anjuta_plugin_description_copy,
576 (GBoxedFreeFunc) anjuta_plugin_description_free);
578 return type_id;
583 * anjuta_plugin_description_new_from_string:
584 * @data: The data to parse. The format of the data is .ini style.
586 * Parses the given plugin description data (usally read from the plugin
587 * description file and creates an instance of #AnjutaPluginDescription.
588 * The format of the content string is similar to .ini format.
590 * Return value: a new #AnjutaPluginDescription object
592 AnjutaPluginDescription *
593 anjuta_plugin_description_new_from_string (char *data, GError **error)
595 AnjutaPluginDescriptionParser parser;
597 parser.df = g_new0 (AnjutaPluginDescription, 1);
598 parser.current_section = -1;
600 parser.line_nr = 1;
601 parser.line = data;
603 /* Put any initial comments in a NULL segment */
604 parser.current_section = create_section (parser.df, NULL, FALSE);
605 while (parser.line != NULL && strlen(parser.line))
607 if (*parser.line == '[') {
608 if (!parse_section_start (&parser, error))
609 return NULL;
610 } else if (is_blank_line (&parser) ||
611 *parser.line == '#')
612 parse_comment_or_blank (&parser);
613 else
615 if (!parse_key_value (&parser, error))
616 return NULL;
620 return parser.df;
624 * anjuta_plugin_description_to_string:
625 * @df: an #AnjutaPluginDescription object.
627 * Converts the description detains into string format, usually for
628 * saving it in a file.
630 * Return value: (transfer full) (allow-none): The string representation of the description.
631 * The returned values must be freed after use.
633 char *
634 anjuta_plugin_description_to_string (AnjutaPluginDescription *df)
636 AnjutaPluginDescriptionSection *section;
637 AnjutaPluginDescriptionLine *line;
638 GString *str;
639 char *s;
640 int i, j;
642 str = g_string_sized_new (800);
644 for (i = 0; i < df->n_sections; i ++)
646 section = &df->sections[i];
648 if (section->section_name)
650 g_string_append_c (str, '[');
651 s = escape_string (g_quark_to_string (section->section_name), FALSE);
652 g_string_append (str, s);
653 g_free (s);
654 g_string_append (str, "]\n");
657 for (j = 0; j < section->n_lines; j++)
659 line = &section->lines[j];
661 if (line->key == 0)
663 g_string_append (str, line->value);
664 g_string_append_c (str, '\n');
666 else
668 g_string_append (str, g_quark_to_string (line->key));
669 if (line->locale)
671 g_string_append_c (str, '[');
672 g_string_append (str, line->locale);
673 g_string_append_c (str, ']');
675 g_string_append_c (str, '=');
676 s = escape_string (line->value, TRUE);
677 g_string_append (str, s);
678 g_free (s);
679 g_string_append_c (str, '\n');
684 return g_string_free (str, FALSE);
687 static AnjutaPluginDescriptionSection *
688 lookup_section (AnjutaPluginDescription *df,
689 const char *section_name)
691 AnjutaPluginDescriptionSection *section;
692 GQuark section_quark;
693 int i;
695 section_quark = g_quark_try_string (section_name);
696 if (section_quark == 0)
697 return NULL;
699 for (i = 0; i < df->n_sections; i ++)
701 section = &df->sections[i];
703 if (section->section_name == section_quark)
704 return section;
706 return NULL;
709 static AnjutaPluginDescriptionLine *
710 lookup_line (AnjutaPluginDescription *df,
711 AnjutaPluginDescriptionSection *section,
712 const char *keyname,
713 const char *locale)
715 AnjutaPluginDescriptionLine *line;
716 GQuark key_quark;
717 int i;
719 key_quark = g_quark_try_string (keyname);
720 if (key_quark == 0)
721 return NULL;
723 for (i = 0; i < section->n_lines; i++)
725 line = &section->lines[i];
727 if (line->key == key_quark &&
728 ((locale == NULL && line->locale == NULL) ||
729 (locale != NULL && line->locale != NULL && strcmp (locale, line->locale) == 0)))
730 return line;
733 return NULL;
737 * anjuta_plugin_description_get_raw:
738 * @df: an #AnjutaPluginDescription object.
739 * @section_name: Name of the section.
740 * @keyname: Name of the key.
741 * @locale: The locale for which the value is to be retrieved.
742 * @val: (out) (transfer full) (allow-none): Pointer to the variable to store the string value.
744 * Retrieves the value of a key (in the given section) for the given locale.
745 * The value returned in @val must be freed after use.
747 * Return value: %TRUE if sucessful, otherwise %FALSE.
749 gboolean
750 anjuta_plugin_description_get_raw (AnjutaPluginDescription *df,
751 const char *section_name,
752 const char *keyname,
753 const char *locale,
754 char **val)
756 AnjutaPluginDescriptionSection *section;
757 AnjutaPluginDescriptionLine *line;
759 *val = NULL;
761 section = lookup_section (df, section_name);
762 if (!section)
763 return FALSE;
765 line = lookup_line (df,
766 section,
767 keyname,
768 locale);
770 if (!line)
771 return FALSE;
773 *val = g_strdup (line->value);
775 return TRUE;
779 * anjuta_plugin_description_foreach_section:
780 * @df: an #AnjutaPluginDescription object.
781 * @func: Callback function.
782 * @user_data: User data to pass to @func.
784 * Calls @func for each of the sections in the description.
786 void
787 anjuta_plugin_description_foreach_section (AnjutaPluginDescription *df,
788 AnjutaPluginDescriptionSectionFunc func,
789 gpointer user_data)
791 AnjutaPluginDescriptionSection *section;
792 int i;
794 for (i = 0; i < df->n_sections; i ++)
796 section = &df->sections[i];
798 (*func) (df, g_quark_to_string (section->section_name), user_data);
800 return;
804 * anjuta_plugin_description_foreach_key:
805 * @df: an #AnjutaPluginDescription object.
806 * @section_name: Name of the section.
807 * @include_localized: Whether each localized key should be called separately.
808 * @func: The callback function.
809 * @user_data: User data to pass to @func.
811 * Calls @func for each of the keys in the given section. @include_localized,
812 * if set to %TRUE will make it call @func for the localized keys also,
813 * otherwise only one call is made for the key in current locale.
815 void
816 anjuta_plugin_description_foreach_key (AnjutaPluginDescription *df,
817 const char *section_name,
818 gboolean include_localized,
819 AnjutaPluginDescriptionLineFunc func,
820 gpointer user_data)
822 AnjutaPluginDescriptionSection *section;
823 AnjutaPluginDescriptionLine *line;
824 int i;
826 section = lookup_section (df, section_name);
827 if (!section)
828 return;
830 for (i = 0; i < section->n_lines; i++)
832 line = &section->lines[i];
834 (*func) (df, g_quark_to_string (line->key), line->locale, line->value, user_data);
837 return;
841 static void
842 calculate_locale (AnjutaPluginDescription *df)
844 char *p, *lang;
846 lang = g_strdup (setlocale (LC_MESSAGES, NULL));
848 if (lang)
850 p = strchr (lang, '.');
851 if (p)
852 *p = '\0';
853 p = strchr (lang, '@');
854 if (p)
855 *p = '\0';
857 else
858 lang = g_strdup ("C");
860 p = strchr (lang, '_');
861 if (p)
863 df->current_locale[0] = g_strdup (lang);
864 *p = '\0';
865 df->current_locale[1] = lang;
867 else
869 df->current_locale[0] = lang;
870 df->current_locale[1] = NULL;
875 * anjuta_plugin_description_get_locale_string:
876 * @df: an #AnjutaPluginDescription object.
877 * @section: Section name.
878 * @keyname: Key name.
879 * @val: Pointer to value to store retured value.
881 * Returns the value of key in the given section in current locale.
883 * Return value: %TRUE if sucessful, otherwise %FALSE.
885 gboolean
886 anjuta_plugin_description_get_locale_string (AnjutaPluginDescription *df,
887 const char *section,
888 const char *keyname,
889 char **val)
891 gboolean res;
893 if (df->current_locale[0] == NULL)
894 calculate_locale (df);
896 if (df->current_locale[0] != NULL)
898 res = anjuta_plugin_description_get_raw (df,section, keyname,
899 df->current_locale[0], val);
900 if (res)
901 return TRUE;
904 if (df->current_locale[1] != NULL)
906 res = anjuta_plugin_description_get_raw (df,section, keyname,
907 df->current_locale[1], val);
908 if (res)
909 return TRUE;
912 return anjuta_plugin_description_get_raw (df, section, keyname, NULL, val);
916 * anjuta_plugin_description_get_string:
917 * @df: an #AnjutaPluginDescription object.
918 * @section: Section name.
919 * @keyname: Key name.
920 * @val: Pointer to value to store retured value.
922 * Returns the value of key in the given section.
924 * Return value: %TRUE if sucessful, otherwise %FALSE.
926 gboolean
927 anjuta_plugin_description_get_string (AnjutaPluginDescription *df,
928 const char *section,
929 const char *keyname,
930 char **val)
932 return anjuta_plugin_description_get_raw (df, section, keyname, NULL, val);
936 * anjuta_plugin_description_get_integer:
937 * @df: an #AnjutaPluginDescription object.
938 * @section: Section name.
939 * @keyname: Key name.
940 * @val: Pointer to value to store retured value.
942 * Returns the value of key as integer in the given section.
944 * Return value: %TRUE if sucessful, otherwise %FALSE.
946 gboolean
947 anjuta_plugin_description_get_integer (AnjutaPluginDescription *df,
948 const char *section,
949 const char *keyname,
950 int *val)
952 gboolean res;
953 char *str;
955 *val = 0;
957 res = anjuta_plugin_description_get_raw (df, section, keyname, NULL, &str);
958 if (!res)
959 return FALSE;
962 *val = atoi (str);
963 g_free (str);
965 return TRUE;
970 * anjuta_plugin_description_get_boolean:
971 * @df: an #AnjutaPluginDescription object.
972 * @section: Section name.
973 * @keyname: Key name.
974 * @val: Pointer to value to store retured value.
976 * Returns the value of key as boolean in the given section.
978 * Return value: %TRUE if sucessful, otherwise %FALSE.
980 gboolean
981 anjuta_plugin_description_get_boolean (AnjutaPluginDescription *df,
982 const char *section,
983 const char *keyname,
984 gboolean *val)
986 gboolean res;
987 char *str;
989 *val = 0;
991 res = anjuta_plugin_description_get_raw (df, section, keyname, NULL, &str);
992 if (!res)
993 return FALSE;
995 if ((g_ascii_strcasecmp (str, "yes") == 0) ||
996 (g_ascii_strcasecmp (str, "true") == 0))
998 *val = TRUE;
1000 else if ((g_ascii_strcasecmp (str, "no") == 0) ||
1001 (g_ascii_strcasecmp (str, "false") == 0))
1004 *val = FALSE;
1006 else
1008 res = FALSE;
1011 g_free (str);
1013 return res;
1017 * anjuta_plugin_description_override:
1018 * @df: an #AnjutaPluginDescription object.
1019 * @section_name: Section name.
1020 * @keyname: Key name.
1021 * @val: Pointer to value to store retured value.
1023 * Override the value of a key in the description. This can be removed using
1024 * the function anjuta_plugin_description_remove().
1026 * Return value: TRUE if sucessful, otherwise FALSE.
1028 gboolean anjuta_plugin_description_override (AnjutaPluginDescription *df,
1029 const gchar *section_name,
1030 const gchar *keyname,
1031 const gchar*val)
1033 AnjutaPluginDescriptionSection *section;
1034 AnjutaPluginDescriptionLine *line;
1036 section = lookup_section (df, section_name);
1037 if (!section)
1039 gint n;
1041 n = create_section (df, section_name, FALSE);
1042 if (n == 0) return FALSE;
1043 section = &df->sections[n];
1046 line = lookup_line (df,
1047 section,
1048 keyname,
1049 NULL);
1050 if (line)
1052 line->override = g_list_prepend (line->override, line->value);
1054 else
1056 line = new_line (section);
1057 line->key = g_quark_from_string (keyname);
1059 line->value = g_strdup (val);
1061 return TRUE;
1065 * anjuta_plugin_description_remove:
1066 * @df: an #AnjutaPluginDescription object.
1067 * @section_name: Section name.
1068 * @keyname: Key name.
1070 * Remove a key from the description.
1072 * Return value: TRUE if sucessful, otherwise FALSE.
1074 gboolean anjuta_plugin_description_remove (AnjutaPluginDescription *df,
1075 const gchar *section_name,
1076 const gchar *keyname)
1078 AnjutaPluginDescriptionSection *section;
1079 AnjutaPluginDescriptionLine *line;
1081 section = lookup_section (df, section_name);
1082 if (!section)
1083 return FALSE;
1085 line = lookup_line (df,
1086 section,
1087 keyname,
1088 NULL);
1090 if (!line)
1091 return FALSE;
1093 g_free (line->value);
1094 if (line->override == NULL)
1096 line->value = NULL;
1098 else
1100 line->value = (gchar *)(line->override->data);
1101 line->override = g_list_delete_link (line->override, line->override);
1104 return TRUE;