1089
if (isdigit(string[i-1])) string[j] = string[i-1]-48;
1090
else if (isxdigit(string[i-1])) string[j] = tolower(string[i-1])-87;
1104
if (isdigit(string[i - 1])) string[j] = string[i - 1] - 48;
1105
else if (isxdigit(string[i - 1])) string[j] = tolower(string[i - 1])-87;
1091
1106
else return FALSE;
1092
1107
string[j] <<= 4;
1093
if (isdigit(string[i])) string[j] |= string[i]-48;
1108
if (isdigit(string[i])) string[j] |= string[i] - 48;
1094
1109
else if (isxdigit(string[i])) string[j] |= tolower(string[i])-87;
1095
1110
else return FALSE;
1100
1116
if (i >= strlen(string))
1104
if (isdigit(string[i-1])) unicodechar = string[i-1]-48;
1105
else if (isxdigit(string[i-1])) unicodechar = tolower(string[i-1])-87;
1120
if (isdigit(string[i - 1])) unicodechar = string[i - 1] - 48;
1121
else if (isxdigit(string[i - 1])) unicodechar = tolower(string[i - 1])-87;
1106
1122
else return FALSE;
1107
1123
unicodechar <<= 4;
1108
if (isdigit(string[i])) unicodechar |= string[i]-48;
1124
if (isdigit(string[i])) unicodechar |= string[i] - 48;
1109
1125
else if (isxdigit(string[i])) unicodechar |= tolower(string[i])-87;
1110
1126
else return FALSE;
1111
if (((i+2) < strlen(string)) && (isdigit(string[i+1]) || isxdigit(string[i+1]))
1112
&& (isdigit(string[i+2]) || isxdigit(string[i+2])))
1116
if (isdigit(string[i-1])) unicodechar |= ((string[i-1]-48)<<4);
1117
else unicodechar |= ((tolower(string[i-1])-87) << 4);
1118
if (isdigit(string[i])) unicodechar |= string[i]-48;
1119
else unicodechar |= tolower(string[i])-87;
1121
if (((i+2) < strlen(string)) && (isdigit(string[i+1]) || isxdigit(string[i+1]))
1122
&& (isdigit(string[i+2]) || isxdigit(string[i+2])))
1126
if (isdigit(string[i-1])) unicodechar |= ((string[i-1]-48) << 4);
1127
else unicodechar |= ((tolower(string[i-1])-87) << 4);
1128
if (isdigit(string[i])) unicodechar |= string[i]-48;
1129
else unicodechar |= tolower(string[i])-87;
1131
if(unicodechar < 0x80)
1127
if (((i + 2) < strlen(string)) && (isdigit(string[i + 1]) || isxdigit(string[i + 1]))
1128
&& (isdigit(string[i + 2]) || isxdigit(string[i + 2])))
1132
if (isdigit(string[i - 1])) unicodechar |= ((string[i - 1] - 48) << 4);
1133
else unicodechar |= ((tolower(string[i - 1])-87) << 4);
1134
if (isdigit(string[i])) unicodechar |= string[i] - 48;
1135
else unicodechar |= tolower(string[i])-87;
1137
if (((i + 2) < strlen(string)) && (isdigit(string[i + 1]) || isxdigit(string[i + 1]))
1138
&& (isdigit(string[i + 2]) || isxdigit(string[i + 2])))
1142
if (isdigit(string[i - 1])) unicodechar |= ((string[i - 1] - 48) << 4);
1143
else unicodechar |= ((tolower(string[i - 1])-87) << 4);
1144
if (isdigit(string[i])) unicodechar |= string[i] - 48;
1145
else unicodechar |= tolower(string[i])-87;
1147
if (unicodechar < 0x80)
1133
1149
string[j] = unicodechar;
1135
1151
else if (unicodechar < 0x800)
1137
string[j] = (unsigned char) ((unicodechar >> 6)| 0xC0);
1153
string[j] = (unsigned char) ((unicodechar >> 6) | 0xC0);
1139
string[j] = (unsigned char) ((unicodechar & 0x3F)| 0x80);
1155
string[j] = (unsigned char) ((unicodechar & 0x3F) | 0x80);
1141
1157
else if (unicodechar < 0x10000)
1345
* Gets a sorted list of files from the specified directory.
1346
* Locale encoding is expected for path and used for the file list. The list and the data
1347
* in the list should be freed after use.
1349
* @param path The path of the directory to scan, in locale encoding.
1350
* @param length The location to store the number of non-@c NULL data items in the list,
1352
* @param error The is the location for storing a possible error, or @c NULL.
1354
* @return A newly allocated list or @c NULL if no files found. The list and its data should be
1355
* freed when no longer needed.
1365
* Gets a list of files from the specified directory.
1366
* Locale encoding is expected for @a path and used for the file list. The list and the data
1367
* in the list should be freed after use, e.g.:
1369
* g_slist_foreach(list, (GFunc) g_free, NULL);
1370
* g_slist_free(list); @endcode
1372
* @note If you don't need a list you should use the foreach_dir() macro instead -
1373
* it's more efficient.
1375
* @param path The path of the directory to scan, in locale encoding.
1376
* @param full_path Whether to include the full path for each filename in the list. Obviously this
1377
* will use more memory.
1378
* @param sort Whether to sort alphabetically (UTF-8 safe).
1379
* @param error The location for storing a possible error, or @c NULL.
1381
* @return A newly allocated list or @c NULL if no files were found. The list and its data should be
1382
* freed when no longer needed.
1383
* @see utils_get_file_list().
1357
GSList *utils_get_file_list(const gchar *path, guint *length, GError **error)
1385
GSList *utils_get_file_list_full(const gchar *path, gboolean full_path, gboolean sort, GError **error)
1359
1387
GSList *list = NULL;
1389
const gchar *filename;
1367
1393
g_return_val_if_fail(path != NULL, NULL);
1369
1395
dir = g_dir_open(path, 0, error);
1370
1396
if (dir == NULL)
1399
foreach_dir(filename, dir)
1375
const gchar *filename = g_dir_read_name(dir);
1376
if (filename == NULL)
1379
list = g_slist_append(list, g_strdup(filename));
1401
list = g_slist_append(list, full_path ?
1402
g_build_path(G_DIR_SEPARATOR_S, path, filename, NULL) : g_strdup(filename));
1382
1404
g_dir_close(dir);
1383
1405
/* sorting last is quicker than on insertion */
1384
list = g_slist_sort(list, (GCompareFunc) utils_str_casecmp);
1407
list = g_slist_sort(list, (GCompareFunc) utils_str_casecmp);
1413
* Gets a sorted list of files from the specified directory.
1414
* Locale encoding is expected for @a path and used for the file list. The list and the data
1415
* in the list should be freed after use, e.g.:
1417
* g_slist_foreach(list, (GFunc) g_free, NULL);
1418
* g_slist_free(list); @endcode
1420
* @param path The path of the directory to scan, in locale encoding.
1421
* @param length The location to store the number of non-@c NULL data items in the list,
1423
* @param error The location for storing a possible error, or @c NULL.
1425
* @return A newly allocated list or @c NULL if no files were found. The list and its data should be
1426
* freed when no longer needed.
1427
* @see utils_get_file_list_full().
1429
GSList *utils_get_file_list(const gchar *path, guint *length, GError **error)
1431
GSList *list = utils_get_file_list_full(path, FALSE, TRUE, error);
1434
*length = g_slist_length(list);
1847
static void utils_slist_remove_next(GSList *node)
1849
GSList *old = node->next;
1851
g_return_if_fail(old);
1853
node->next = old->next;
1854
g_slist_free_1(old);
1858
/* Gets list of sorted filenames with no path and no duplicates from user and system config */
1859
GSList *utils_get_config_files(const gchar *subdir)
1861
gchar *path = g_build_path(G_DIR_SEPARATOR_S, app->configdir, subdir, NULL);
1862
GSList *list = utils_get_file_list_full(path, FALSE, FALSE, NULL);
1863
GSList *syslist, *node;
1867
utils_mkdir(path, FALSE);
1869
setptr(path, g_build_path(G_DIR_SEPARATOR_S, app->datadir, subdir, NULL));
1870
syslist = utils_get_file_list_full(path, FALSE, FALSE, NULL);
1872
list = g_slist_concat(list, syslist);
1874
list = g_slist_sort(list, (GCompareFunc) utils_str_casecmp);
1875
/* remove duplicates (next to each other after sorting) */
1876
foreach_slist(node, list)
1878
if (node->next && utils_str_equal(node->next->data, node->data))
1880
g_free(node->next->data);
1881
utils_slist_remove_next(node);
1889
/* Suffix can be NULL or a string which should be appended to the Help URL like
1890
* an anchor link, e.g. "#some_anchor". */
1891
gchar *utils_get_help_url(const gchar *suffix)
1898
uri = g_strconcat("file:///", app->docdir, "/Manual.html", NULL);
1899
g_strdelimit(uri, "\\", '/'); /* replace '\\' by '/' */
1902
uri = g_strconcat("file://", app->docdir, "index.html", NULL);
1905
if (! g_file_test(uri + skip, G_FILE_TEST_IS_REGULAR))
1906
{ /* fall back to online documentation if it is not found on the hard disk */
1908
uri = g_strconcat(GEANY_HOMEPAGE, "manual/", VERSION, "/index.html", NULL);
1913
setptr(uri, g_strconcat(uri, suffix, NULL));
1920
static gboolean str_in_array(const gchar **haystack, const gchar *needle)
1924
for (p = haystack; *p != NULL; ++p)
1926
if (utils_str_equal(*p, needle))
1934
* Copies the current environment into a new array.
1935
* @a exclude_vars is a @c NULL-terminated array of variable names which should be not copied.
1936
* All further arguments are key, value pairs of variables which should be added to
1939
* The argument list must be @c NULL-terminated.
1941
* @param exclude_vars @c NULL-terminated array of variable names to exclude.
1942
* @param first_varname Name of the first variable to copy into the new array.
1943
* @param ... Key-value pairs of variable names and values, @c NULL-terminated.
1945
* @return The new environment array.
1947
gchar **utils_copy_environment(const gchar **exclude_vars, const gchar *first_varname, ...)
1953
const gchar *key, *value;
1956
/* get all the environ variables */
1959
/* count the additional variables */
1960
va_start(args, first_varname);
1961
for (o = 1; va_arg(args, gchar*) != NULL; o++);
1963
/* the passed arguments should be even (key, value pairs) */
1964
g_return_val_if_fail(o % 2 == 0, NULL);
1968
/* create an array large enough to hold the new environment */
1969
n = g_strv_length(env);
1970
/* 'n + o + 1' could leak a little bit when exclude_vars is set */
1971
result = g_new(gchar *, n + o + 1);
1973
/* copy the environment */
1974
for (n = 0, p = env; *p != NULL; ++p)
1976
/* copy the variable */
1977
value = g_getenv(*p);
1978
if (G_LIKELY(value != NULL))
1980
/* skip excluded variables */
1981
if (exclude_vars != NULL && str_in_array(exclude_vars, *p))
1984
result[n++] = g_strconcat(*p, "=", value, NULL);
1989
/* now add additional variables */
1990
va_start(args, first_varname);
1991
key = first_varname;
1992
value = va_arg(args, gchar*);
1995
result[n++] = g_strconcat(key, "=", value, NULL);
1997
key = va_arg(args, gchar*);
2000
value = va_arg(args, gchar*);