1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
6
* Copyright (C) 2005 Free Software Foundation, Inc.
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program. If not, see <http://www.gnu.org/licenses/>.
27
#include <glib/gi18n.h>
28
#include <glib/gprintf.h>
29
#include <glib-object.h>
30
#include "glib-utils.h"
36
#define MAX_PATTERNS 128
43
_g_object_ref (gpointer object)
45
return (object != NULL) ? g_object_ref (object) : NULL;
50
_g_object_unref (gpointer object)
53
g_object_unref (object);
58
_g_clear_object (gpointer p)
60
g_clear_object ((GObject **) p);
65
_g_object_list_ref (GList *list)
72
new_list = g_list_copy (list);
73
g_list_foreach (new_list, (GFunc) g_object_ref, NULL);
80
_g_object_list_unref (GList *list)
82
g_list_foreach (list, (GFunc) g_object_unref, NULL);
90
_g_enum_type_get_value (GType enum_type,
94
GEnumValue *enum_value;
96
class = G_ENUM_CLASS (g_type_class_ref (enum_type));
97
enum_value = g_enum_get_value (class, value);
98
g_type_class_unref (class);
105
_g_enum_type_get_value_by_nick (GType enum_type,
109
GEnumValue *enum_value;
111
class = G_ENUM_CLASS (g_type_class_ref (enum_type));
112
enum_value = g_enum_get_value_by_nick (class, nick);
113
g_type_class_unref (class);
123
_g_error_free (GError *error)
126
g_error_free (error);
134
_g_strchrs (const char *str,
138
for (c = chars; *c != '\0'; c++)
139
if (strchr (str, *c) != NULL)
146
_g_str_substitute (const char *str,
147
const char *from_str,
157
if (from_str == NULL)
158
return g_strdup (str);
160
if (strcmp (str, from_str) == 0)
161
return g_strdup (to_str);
163
tokens = g_strsplit (str, from_str, -1);
165
gstr = g_string_new (NULL);
166
for (i = 0; tokens[i] != NULL; i++) {
167
gstr = g_string_append (gstr, tokens[i]);
168
if ((to_str != NULL) && (tokens[i+1] != NULL))
169
gstr = g_string_append (gstr, to_str);
172
return g_string_free (gstr, FALSE);
177
_g_str_equal (const char *s1,
180
return g_strcmp0 (s1, s2) == 0;
184
/* -- _g_str_escape_full -- */
187
/* counts how many characters to escape in @str. */
189
count_chars_to_escape (const char *str,
190
const char *meta_chars)
192
int meta_chars_n = strlen (meta_chars);
196
for (s = str; *s != 0; s++) {
198
for (i = 0; i < meta_chars_n; i++)
199
if (*s == meta_chars[i]) {
210
_g_str_escape_full (const char *str,
211
const char *meta_chars,
215
int meta_chars_n = strlen (meta_chars);
217
int i, new_l, extra_chars = 0;
229
new_l = strlen (str) + (count_chars_to_escape (str, meta_chars) * extra_chars);
230
escaped = g_malloc (new_l + 1);
235
gboolean is_bad = FALSE;
236
for (i = 0; (i < meta_chars_n) && !is_bad; i++)
237
is_bad = (*s == meta_chars[i]);
238
if (is_bad && prefix)
241
if (is_bad && postfix)
250
/* escape with backslash the string @str. */
252
_g_str_escape (const char *str,
253
const char *meta_chars)
255
return _g_str_escape_full (str, meta_chars, '\\', 0);
259
/* escape with backslash the file name. */
261
_g_str_shell_escape (const char *filename)
263
return _g_str_escape (filename, "$'`\"\\!?* ()[]&|:;<>#");
268
_g_strdup_with_max_size (const char *s,
278
int half_max_size = max_size / 2 + 1;
280
first_half = g_strndup (s, half_max_size);
281
offset = half_max_size + l - max_size;
282
second_half = g_strndup (s + offset, half_max_size);
284
result = g_strconcat (first_half, "...", second_half, NULL);
287
g_free (second_half);
289
result = g_strdup (s);
296
_g_str_eat_spaces (const char *line)
300
while ((*line == ' ') && (*line != 0))
307
_g_str_eat_void_chars (const char *line)
311
while (((*line == ' ') || (*line == '\t')) && (*line != 0))
318
_g_str_split_line (const char *line,
322
const char *scan, *field_end;
325
fields = g_new0 (char *, n_fields + 1);
326
fields[n_fields] = NULL;
328
scan = _g_str_eat_spaces (line);
329
for (i = 0; i < n_fields; i++) {
334
field_end = strchr (scan, ' ');
335
if (field_end != NULL) {
336
fields[i] = g_strndup (scan, field_end - scan);
337
scan = _g_str_eat_spaces (field_end);
346
_g_str_get_last_field (const char *line,
356
field = _g_str_eat_spaces (line);
357
for (i = 0; i < last_field; i++) {
360
field = strchr (field, ' ');
361
field = _g_str_eat_spaces (field);
368
GHashTable *static_strings = NULL;
372
_g_str_get_static (const char *s)
379
if (static_strings == NULL)
380
static_strings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
382
if (! g_hash_table_lookup_extended (static_strings, s, (gpointer*) &result, NULL)) {
383
result = g_strdup (s);
384
g_hash_table_insert (static_strings,
386
GINT_TO_POINTER (1));
397
_g_strv_prepend (char **str_array,
404
result = g_new (char *, g_strv_length (str_array) + 1);
406
result[i++] = g_strdup (str);
407
for (j = 0; str_array[j] != NULL; j++)
408
result[i++] = g_strdup (str_array[j]);
416
_g_strv_remove (char **str_array,
425
for (i = 0; str_array[i] != NULL; i++)
426
if (strcmp (str_array[i], str) == 0)
429
if (str_array[i] == NULL)
432
for (j = i; str_array[j] != NULL; j++)
433
str_array[j] = str_array[j + 1];
443
_g_string_list_free (GList *path_list)
445
if (path_list == NULL)
447
g_list_foreach (path_list, (GFunc) g_free, NULL);
448
g_list_free (path_list);
453
_g_string_list_dup (GList *path_list)
455
GList *new_list = NULL;
458
for (scan = path_list; scan; scan = scan->next)
459
new_list = g_list_prepend (new_list, g_strdup (scan->data));
461
return g_list_reverse (new_list);
469
_g_ptr_array_copy (GPtrArray *array)
471
GPtrArray *new_array;
476
new_array = g_ptr_array_sized_new (array->len);
477
memcpy (new_array->pdata, array->pdata, array->len * sizeof (gpointer));
478
new_array->len = array->len;
485
_g_ptr_array_free_full (GPtrArray *array,
489
g_ptr_array_foreach (array, free_func, user_data);
490
g_ptr_array_free (array, TRUE);
495
_g_ptr_array_reverse (GPtrArray *array)
500
for (i = 0; i < array->len / 2; i++) {
501
j = array->len - i - 1;
502
tmp = g_ptr_array_index (array, i);
503
g_ptr_array_index (array, i) = g_ptr_array_index (array, j);
504
g_ptr_array_index (array, j) = tmp;
510
_g_ptr_array_binary_search (GPtrArray *array,
514
int l, r, p, cmp = -1;
519
p = l + ((r - l) / 2);
520
cmp = func(value, &g_ptr_array_index (array, p));
537
_g_regexp_matchv (GRegex **regexps,
539
GRegexMatchFlags match_options)
544
if ((regexps == NULL) || (regexps[0] == NULL))
551
for (i = 0; regexps[i] != NULL; i++)
552
if (g_regex_match (regexps[i], string, match_options, NULL)) {
562
_g_regexp_freev (GRegex **regexps)
569
for (i = 0; regexps[i] != NULL; i++)
570
g_regex_unref (regexps[i]);
575
/* -- _g_regexp_get_patternv -- */
579
_g_utf8_strstr (const char *haystack,
584
gsize haystack_len = g_utf8_strlen (haystack, -1);
585
gsize needle_len = g_utf8_strlen (needle, -1);
586
int needle_size = strlen (needle);
589
for (i = 0; i <= haystack_len - needle_len; i++) {
590
if (strncmp (s, needle, needle_size) == 0)
592
s = g_utf8_next_char(s);
600
_g_utf8_strsplit (const char *string,
601
const char *delimiter,
604
GSList *string_list = NULL, *slist;
608
const char *remainder;
610
g_return_val_if_fail (string != NULL, NULL);
611
g_return_val_if_fail (delimiter != NULL, NULL);
612
g_return_val_if_fail (delimiter[0] != '\0', NULL);
615
max_tokens = G_MAXINT;
618
s = _g_utf8_strstr (remainder, delimiter);
620
gsize delimiter_size = strlen (delimiter);
622
while (--max_tokens && (s != NULL)) {
623
gsize size = s - remainder;
626
new_string = g_new (char, size + 1);
627
strncpy (new_string, remainder, size);
628
new_string[size] = 0;
630
string_list = g_slist_prepend (string_list, new_string);
632
remainder = s + delimiter_size;
633
s = _g_utf8_strstr (remainder, delimiter);
638
string_list = g_slist_prepend (string_list, g_strdup (remainder));
641
str_array = g_new (char*, n + 1);
643
str_array[n--] = NULL;
644
for (slist = string_list; slist; slist = slist->next)
645
str_array[n--] = slist->data;
647
g_slist_free (string_list);
654
g_utf8_strchug (char *string)
659
g_return_val_if_fail (string != NULL, NULL);
662
c = g_utf8_get_char (scan);
663
while (g_unichar_isspace (c)) {
664
scan = g_utf8_next_char (scan);
665
c = g_utf8_get_char (scan);
668
memmove (string, scan, strlen (scan) + 1);
675
g_utf8_strchomp (char *string)
680
g_return_val_if_fail (string != NULL, NULL);
682
len = g_utf8_strlen (string, -1);
687
scan = g_utf8_offset_to_pointer (string, len - 1);
690
gunichar c = g_utf8_get_char (scan);
691
if (g_unichar_isspace (c))
695
scan = g_utf8_find_prev_char (string, scan);
702
#define g_utf8_strstrip(string) g_utf8_strchomp (g_utf8_strchug (string))
706
_g_regexp_get_patternv (const char *pattern_string)
711
if (pattern_string == NULL)
714
patterns = _g_utf8_strsplit (pattern_string, ";", MAX_PATTERNS);
715
for (i = 0; patterns[i] != NULL; i++) {
718
p1 = g_utf8_strstrip (patterns[i]);
719
p2 = _g_str_substitute (p1, ".", "\\.");
720
patterns[i] = _g_str_substitute (p2, "*", ".*");
731
_g_regexp_split_from_patterns (const char *pattern_string,
732
GRegexCompileFlags compile_options)
738
patterns = _g_regexp_get_patternv (pattern_string);
739
if (patterns == NULL)
742
regexps = g_new0 (GRegex*, g_strv_length (patterns) + 1);
743
for (i = 0; patterns[i] != NULL; i++)
744
regexps[i] = g_regex_new (patterns[i],
745
G_REGEX_OPTIMIZE | compile_options,
746
G_REGEX_MATCH_NOTEMPTY,
748
g_strfreev (patterns);
758
_g_time_to_string (time_t time)
762
char *locale_format = NULL;
765
tm = localtime (&time);
766
/* This is the time format used in the "Date Modified" column and
767
* in the Properties dialog. See the man page of strftime for an
768
* explanation of the values. */
769
locale_format = g_locale_from_utf8 (_("%d %B %Y, %H:%M"), -1, NULL, NULL, NULL);
770
strftime (s_time, sizeof (s_time) - 1, locale_format, tm);
771
g_free (locale_format);
772
time_utf8 = g_locale_to_utf8 (s_time, -1, NULL, NULL, NULL);
778
/* uri/path/filename */
782
_g_uri_get_home (void)
784
static char *home_uri = NULL;
785
if (home_uri == NULL)
786
home_uri = g_filename_to_uri (g_get_home_dir (), NULL, NULL);
792
_g_uri_get_home_relative (const char *partial_uri)
794
return g_strconcat (_g_uri_get_home (),
802
_g_uri_remove_host (const char *uri)
804
const char *idx, *sep;
809
idx = strstr (uri, "://");
815
sep = strstr (idx, "/");
823
_g_uri_get_host (const char *uri)
827
idx = strstr (uri, "://");
830
idx = strstr (idx + 3, "/");
833
return g_strndup (uri, (idx - uri));
838
_g_uri_get_root (const char *uri)
843
host = _g_uri_get_host (uri);
846
root = g_strconcat (host, "/", NULL);
854
_g_uri_cmp (const char *uri1,
857
return g_strcmp0 (uri1, uri2);
861
/* like g_path_get_basename but does not warn about NULL and does not
862
* alloc a new string. */
864
_g_path_get_basename (const gchar *file_name)
867
register gssize last_char;
869
if (file_name == NULL)
872
if (file_name[0] == '\0')
875
last_char = strlen (file_name) - 1;
877
if (file_name [last_char] == G_DIR_SEPARATOR)
880
base = g_utf8_strrchr (file_name, -1, G_DIR_SEPARATOR);
889
_g_path_get_dir_name (const gchar *path)
891
register gssize base;
892
register gssize last_char;
898
return g_strdup ("");
900
last_char = strlen (path) - 1;
901
if (path[last_char] == G_DIR_SEPARATOR)
905
while ((base >= 0) && (path[base] != G_DIR_SEPARATOR))
908
return g_strndup (path + base + 1, last_char - base);
913
_g_path_remove_level (const gchar *path)
916
const char *ptr = path;
922
p = strlen (path) - 1;
926
/* ignore the first slash if it's the last character,
927
* this way /a/b/ is treated as /a/b */
929
if ((ptr[p] == '/') && (p > 0))
932
while ((p > 0) && (ptr[p] != '/'))
934
if ((p == 0) && (ptr[p] == '/'))
936
new_path = g_strndup (path, (guint)p);
943
_g_path_remove_ending_separator (const char *path)
950
copy_len = len = strlen (path);
951
if ((len > 1) && (path[len - 1] == '/'))
954
return g_strndup (path, copy_len);
959
_g_path_remove_extension (const gchar *path)
966
ext = _g_filename_get_extension (path);
968
return g_strdup (path);
970
return g_strndup (path, strlen (path) - strlen (ext));
975
_g_path_remove_first_extension (const gchar *path)
982
ext = strrchr (path, '.');
984
return g_strdup (path);
986
return g_strndup (path, strlen (path) - strlen (ext));
990
/* Check whether the dirname is contained in filename */
992
_g_path_is_parent_of (const char *dirname,
993
const char *filename)
995
int dirname_l, filename_l, separator_position;
997
if ((dirname == NULL) || (filename == NULL))
1000
dirname_l = strlen (dirname);
1001
filename_l = strlen (filename);
1003
if ((dirname_l == filename_l + 1)
1004
&& (dirname[dirname_l - 1] == '/'))
1007
if ((filename_l == dirname_l + 1)
1008
&& (filename[filename_l - 1] == '/'))
1011
if (dirname[dirname_l - 1] == '/')
1012
separator_position = dirname_l - 1;
1014
separator_position = dirname_l;
1016
return ((filename_l > dirname_l)
1017
&& (strncmp (dirname, filename, dirname_l) == 0)
1018
&& (filename[separator_position] == '/'));
1023
_g_path_get_relative_basename (const char *path,
1024
const char *base_dir,
1025
gboolean junk_paths)
1028
const char *base_path;
1031
return _g_path_get_basename (path);
1033
if (base_dir == NULL)
1034
return (path[0] == '/') ? path + 1 : path;
1036
base_dir_len = strlen (base_dir);
1037
if (strlen (path) < base_dir_len)
1040
base_path = path + base_dir_len;
1048
#define ISDOT(c) ((c) == '.')
1049
#define ISSLASH(c) ((c) == '/')
1053
sanitize_filename (const char *file_name)
1058
if (file_name == NULL)
1062
for (p = file_name; *p; ) {
1063
if (ISDOT (p[0]) && ISDOT (p[1]) && (ISSLASH (p[2]) || !p[2]))
1064
prefix_len = p + 2 - file_name;
1074
p = file_name + prefix_len;
1075
while (ISSLASH (*p))
1083
_g_path_get_relative_basename_safe (const char *path,
1084
const char *base_dir,
1085
gboolean junk_paths)
1087
return sanitize_filename (_g_path_get_relative_basename (path, base_dir, junk_paths));
1092
_g_filename_is_hidden (const gchar *name)
1094
if (name[0] != '.') return FALSE;
1095
if (name[1] == '\0') return FALSE;
1096
if ((name[1] == '.') && (name[2] == '\0')) return FALSE;
1103
_g_filename_get_extension (const char *filename)
1105
const char *ptr = filename;
1110
if (filename == NULL)
1113
len = strlen (filename);
1118
while ((p >= 0) && (ptr[p] != '.'))
1124
if (ext - 4 > filename) {
1125
const char *test = ext - 4;
1126
/* .tar.rz cannot be uncompressed in one step */
1127
if ((strncmp (test, ".tar", 4) == 0) && (strncmp (ext, ".rz", 2) != 0))
1135
_g_filename_has_extension (const char *filename,
1138
int filename_l, ext_l;
1140
filename_l = strlen (filename);
1141
ext_l = strlen (ext);
1143
if (filename_l < ext_l)
1145
return strcasecmp (filename + filename_l - ext_l, ext) == 0;
1150
_g_filename_get_random (int random_part_len,
1153
const char *letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
1154
const int n_letters = strlen (letters);
1160
suffix_len = suffix != NULL ? strlen (suffix) + 1 : 0;
1161
result = g_new (char, suffix_len + random_part_len + 1);
1163
rand = g_rand_new ();
1164
for (i = 0, c = result; i < random_part_len; i++, c++)
1165
*c = letters[g_rand_int_range (rand, 0, n_letters)];
1169
if (suffix != NULL) {
1171
strcpy (c + 1, suffix);
1179
_g_mime_type_matches (const char *mime_type,
1180
const char *pattern)
1182
return (strcasecmp (mime_type, pattern) == 0);
1187
_g_mime_type_get_from_content (char *buffer,
1192
static magic_t magic = NULL;
1194
if (magic == NULL) {
1195
magic = magic_open (MAGIC_MIME_TYPE);
1197
magic_load (magic, NULL);
1199
g_warning ("unable to open magic database");
1202
if (magic != NULL) {
1203
const char * mime_type;
1205
mime_type = magic_buffer (magic, buffer, buffer_size);
1206
if ((mime_type != NULL) && (strcmp (mime_type, "application/octet-stream") == 0))
1209
if (mime_type != NULL)
1212
g_warning ("unable to detect filetype from magic: %s", magic_error (magic));
1217
static const struct magic {
1218
const unsigned int off;
1219
const unsigned int len;
1220
const char * const id;
1221
const char * const mime_type;
1224
/* magic ids taken from magic/Magdir/archive from the file-4.21 tarball */
1225
{ 0, 6, "7z\274\257\047\034", "application/x-7z-compressed" },
1226
{ 7, 7, "**ACE**", "application/x-ace" },
1227
{ 0, 2, "\x60\xea", "application/x-arj" },
1228
{ 0, 3, "BZh", "application/x-bzip2" },
1229
{ 0, 2, "\037\213", "application/x-gzip" },
1230
{ 0, 4, "LZIP", "application/x-lzip" },
1231
{ 0, 9, "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a", "application/x-lzop", },
1232
{ 0, 4, "Rar!", "application/x-rar" },
1233
{ 0, 4, "RZIP", "application/x-rzip" },
1234
{ 0, 6, "\3757zXZ\000", "application/x-xz" },
1235
{ 20, 4, "\xdc\xa7\xc4\xfd", "application/x-zoo", },
1236
{ 0, 4, "PK\003\004", "application/zip" },
1237
{ 0, 8, "PK00PK\003\004", "application/zip" },
1238
{ 0, 4, "LRZI", "application/x-lrzip" },
1243
for (i = 0; i < G_N_ELEMENTS (magic_ids); i++) {
1244
const struct magic * const magic = &magic_ids[i];
1246
if ((magic->off + magic->len) > buffer_size)
1247
g_warning ("buffer underrun for mime-type '%s' magic", magic->mime_type);
1248
else if (! memcmp (buffer + magic->off, magic->id, magic->len))
1249
return magic->mime_type;
1262
_g_file_cmp_uris (GFile *a,
1269
uri_a = g_file_get_uri (a);
1270
uri_b = g_file_get_uri (b);
1271
result = g_strcmp0 (uri_a, uri_b);
1281
_g_file_is_local (GFile *file)
1286
scheme = g_file_get_uri_scheme (file);
1287
is_local = strcmp (scheme, "file") == 0;
1296
_g_file_get_home (void)
1298
static GFile *file = NULL;
1303
file = g_file_new_for_path (g_get_home_dir ());
1310
_g_file_get_display_basename (GFile *file)
1312
char *uri, *e_name, *name;
1314
uri = g_file_get_uri (file);
1315
e_name = g_filename_display_basename (uri);
1316
name = g_uri_unescape_string (e_name, "");
1326
_g_file_new_home_relative (const char *partial_uri)
1331
uri = g_strconcat (_g_uri_get_home (), "/", partial_uri, NULL);
1332
file = g_file_new_for_uri (uri);
1340
_g_file_list_dup (GList *l)
1342
GList *r = NULL, *scan;
1343
for (scan = l; scan; scan = scan->next)
1344
r = g_list_prepend (r, g_file_dup ((GFile*) scan->data));
1345
return g_list_reverse (r);
1350
_g_file_list_free (GList *l)
1353
for (scan = l; scan; scan = scan->next)
1354
g_object_unref (scan->data);
1360
_g_file_list_new_from_uri_list (GList *uris)
1362
GList *r = NULL, *scan;
1363
for (scan = uris; scan; scan = scan->next)
1364
r = g_list_prepend (r, g_file_new_for_uri ((char*)scan->data));
1365
return g_list_reverse (r);
1370
_g_file_append_path (GFile *file,
1378
uri = g_file_get_uri (file);
1380
va_start (args, file);
1381
while ((path = va_arg (args, const char *)) != NULL) {
1385
escaped = g_uri_escape_string (path, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, FALSE);
1386
new_uri = g_build_filename (uri, escaped, NULL);
1393
new_file = g_file_new_for_uri (uri);
1405
_g_key_file_get_string_list (GKeyFile *key_file,
1406
const char *group_name,
1414
strv = g_key_file_get_string_list (key_file, group_name, key, NULL, error);
1419
for (i = 0; strv[i] != NULL; i++)
1420
list = g_list_prepend (list, strv[i]);
1424
return g_list_reverse (list);
1428
/* GSettings utils */
1432
_g_settings_new_if_schema_installed (const char *schema_id)
1434
GSettingsSchema *schema;
1436
schema = g_settings_schema_source_lookup (g_settings_schema_source_get_default (),
1442
g_settings_schema_unref (schema);
1444
return g_settings_new (schema_id);
1452
_g_line_matches_pattern (const char *line,
1453
const char *pattern)
1455
const char *l = line, *p = pattern;
1457
for (/* void */; (*p != 0) && (*l != 0); p++, l++) {
1486
_g_line_get_index_from_pattern (const char *line,
1487
const char *pattern)
1489
int line_l, pattern_l;
1492
line_l = strlen (line);
1493
pattern_l = strlen (pattern);
1495
if ((pattern_l == 0) || (line_l == 0))
1498
for (l = line; *l != 0; l++)
1499
if (_g_line_matches_pattern (l, pattern))
1507
_g_line_get_next_field (const char *line,
1511
const char *f_start, *f_end;
1513
line = line + start_from;
1516
while ((*f_start == ' ') && (*f_start != *line))
1520
while ((field_n > 0) && (*f_end != 0)) {
1521
if (*f_end == ' ') {
1524
while ((*f_end == ' ') && (*f_end != *line))
1533
return g_strndup (f_start, f_end - f_start);
1538
_g_line_get_prev_field (const char *line,
1542
const char *f_start, *f_end;
1544
f_start = line + start_from - 1;
1545
while ((*f_start == ' ') && (*f_start != *line))
1549
while ((field_n > 0) && (*f_start != *line)) {
1550
if (*f_start == ' ') {
1553
while ((*f_start == ' ') && (*f_start != *line))
1562
return g_strndup (f_start + 1, f_end - f_start);
1569
debug (const char *file,
1571
const char *function,
1572
const char *format, ...)
1578
g_return_if_fail (format != NULL);
1580
va_start (args, format);
1581
str = g_strdup_vprintf (format, args);
1584
g_fprintf (stderr, "[FR] %s:%d (%s):\n\t%s\n", file, line, function, str);