1 /*
2  *      utils.h - this file is part of Geany, a fast and lightweight IDE
3  *
4  *      Copyright 2005 The Geany contributors
5  *
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.
10  *
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.
15  *
16  *      You should have received a copy of the GNU General Public License along
17  *      with this program; if not, write to the Free Software Foundation, Inc.,
18  *      51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 /**
22  *  @file: utils.h
23  *  General utility functions, non-GTK related.
24  */
25 
26 #ifndef GEANY_UTILS_H
27 #define GEANY_UTILS_H 1
28 
29 #include <string.h>
30 #include <time.h>
31 
32 #include <glib.h>
33 #include <gdk/gdk.h> /* for GdkColor */
34 
35 G_BEGIN_DECLS
36 
37 /** Returns @c TRUE if @a ptr is @c NULL or @c *ptr is @c FALSE. */
38 #define EMPTY(ptr) \
39 	(!(ptr) || !*(ptr))
40 
41 /** @deprecated 2013/08 - use @c !EMPTY() instead. */
42 #ifndef GEANY_DISABLE_DEPRECATED
43 #define NZV(ptr) (!EMPTY(ptr))
44 #endif
45 
46 /** Assigns @a result to @a ptr, then frees the old value.
47  * @a result can be an expression using the 'old' value of @a ptr.
48  * E.g. @code SETPTR(str, g_strndup(str, 5)); @endcode
49  **/
50 #define SETPTR(ptr, result) \
51 	do {\
52 		gpointer setptr_tmp = ptr;\
53 		ptr = result;\
54 		g_free(setptr_tmp);\
55 	} while (0)
56 
57 #ifndef GEANY_DISABLE_DEPRECATED
58 /** @deprecated 2011/11/15 - use SETPTR() instead. */
59 #define setptr(ptr, result) \
60 	{\
61 		gpointer setptr_tmp = ptr;\
62 		ptr = result;\
63 		g_free(setptr_tmp);\
64 	}
65 #endif
66 
67 /** Duplicates a string on the stack using @c g_alloca().
68  * Like glibc's @c strdupa(), but portable.
69  * @note You must include @c string.h yourself.
70  * @warning Don't use excessively or for long strings otherwise there may be stack exhaustion -
71  *          see the GLib docs for @c g_alloca(). */
72 #define utils_strdupa(str) \
73 	strcpy(g_alloca(strlen(str) + 1), str)
74 
75 /* Get a keyfile setting, using the home keyfile if the key exists,
76  * otherwise system keyfile. */
77 #define utils_get_setting(type, home, sys, group, key, default_val)\
78 	(g_key_file_has_key(home, group, key, NULL)) ?\
79 		utils_get_setting_##type(home, group, key, default_val) :\
80 		utils_get_setting_##type(sys, group, key, default_val)
81 
82 /* ignore the case of filenames and paths under WIN32, causes errors if not */
83 #ifdef G_OS_WIN32
84 #define utils_filenamecmp(a, b)	utils_str_casecmp((a), (b))
85 #else
86 #define utils_filenamecmp(a, b)	strcmp((a), (b))
87 #endif
88 
89 
90 /** Iterates all the items in @a array using pointers.
91  * @param item pointer to an item in @a array.
92  * @param array C array to traverse.
93  * @param len Length of the array. */
94 #define foreach_c_array(item, array, len) \
95 	for (item = array; item < &array[len]; item++)
96 
97 /** Iterates all items in @a array.
98  * @param type Type of @a item.
99  * @param item pointer to item in @a array.
100  * @param array @c GArray to traverse. */
101 #define foreach_array(type, item, array) \
102 	foreach_c_array(item, ((type*)(gpointer)array->data), array->len)
103 
104 /** Iterates all the pointers in @a ptr_array.
105  * @param item pointer in @a ptr_array.
106  * @param idx @c guint index into @a ptr_array.
107  * @param ptr_array @c GPtrArray to traverse. */
108 #define foreach_ptr_array(item, idx, ptr_array) \
109 	for (idx = 0, item = ((ptr_array)->len > 0 ? g_ptr_array_index((ptr_array), 0) : NULL); \
110 		idx < (ptr_array)->len; ++idx, item = g_ptr_array_index((ptr_array), idx))
111 
112 /** Iterates all the nodes in @a list.
113  * @param node should be a (@c GList*).
114  * @param list @c GList to traverse. */
115 #define foreach_list(node, list) \
116 	for (node = list; node != NULL; node = node->next)
117 
118 /** Iterates all the nodes in @a list.
119  * @param node should be a (@c GSList*).
120  * @param list @c GSList to traverse. */
121 #define foreach_slist(node, list) \
122 	foreach_list(node, list)
123 
124 /* Iterates all the nodes in @a list. Safe against removal during iteration
125  * @param node should be a (@c GList*).
126  * @param list @c GList to traverse. */
127 #define foreach_list_safe(node, list) \
128 	for (GList *_node = (list), *_next = (list) ? (list)->next : NULL; \
129 	     (node = _node) != NULL; \
130 	     _node = _next, _next = _next ? _next->next : NULL)
131 
132 /** Iterates through each unsorted filename in a @c GDir.
133  * @param filename (@c const @c gchar*) locale-encoded filename, without path. Do not modify or free.
134  * @param dir @c GDir created with @c g_dir_open(). Call @c g_dir_close() afterwards.
135  * @see utils_get_file_list() if you want a sorted list.
136  * @since Geany 0.19. */
137 #define foreach_dir(filename, dir)\
138 	for ((filename) = g_dir_read_name(dir); (filename) != NULL; (filename) = g_dir_read_name(dir))
139 
140 /** Iterates through each character in @a string.
141  * @param char_ptr Pointer to character.
142  * @param string String to traverse.
143  * @warning Doesn't include null terminating character.
144  * @since Geany 0.19. */
145 #define foreach_str(char_ptr, string) \
146 	for (char_ptr = string; *char_ptr; char_ptr++)
147 
148 /** Iterates a null-terminated string vector.
149  * @param str_ptr @c gchar** pointer to string element.
150  * @param strv Can be @c NULL.
151  * @since Geany 0.20 */
152 #define foreach_strv(str_ptr, strv)\
153 	if (!(strv)) {} else foreach_str(str_ptr, strv)
154 
155 /** Iterates from 0 to @a size.
156  * @param i Integer.
157  * @param size Number of iterations.
158  * @since Geany 0.20. */
159 #define foreach_range(i, size) \
160 	for (i = 0; i < size; i++)
161 
162 
163 gboolean utils_str_equal(const gchar *a, const gchar *b);
164 
165 guint utils_string_replace_all(GString *haystack, const gchar *needle, const gchar *replace);
166 
167 GSList *utils_get_file_list(const gchar *path, guint *length, GError **error);
168 
169 GSList *utils_get_file_list_full(const gchar *path, gboolean full_path, gboolean sort, GError **error);
170 
171 gint utils_write_file(const gchar *filename, const gchar *text);
172 
173 gchar *utils_get_locale_from_utf8(const gchar *utf8_text);
174 
175 gchar *utils_get_utf8_from_locale(const gchar *locale_text);
176 
177 gchar *utils_remove_ext_from_filename(const gchar *filename);
178 
179 gint utils_mkdir(const gchar *path, gboolean create_parent_dirs);
180 
181 gboolean utils_get_setting_boolean(GKeyFile *config, const gchar *section, const gchar *key, const gboolean default_value);
182 
183 gint utils_get_setting_integer(GKeyFile *config, const gchar *section, const gchar *key, const gint default_value);
184 
185 gchar *utils_get_setting_string(GKeyFile *config, const gchar *section, const gchar *key, const gchar *default_value);
186 
187 gboolean utils_spawn_sync(const gchar *dir, gchar **argv, gchar **env, GSpawnFlags flags,
188 						  GSpawnChildSetupFunc child_setup, gpointer user_data, gchar **std_out,
189 						  gchar **std_err, gint *exit_status, GError **error);
190 
191 gboolean utils_spawn_async(const gchar *dir, gchar **argv, gchar **env, GSpawnFlags flags,
192 						   GSpawnChildSetupFunc child_setup, gpointer user_data, GPid *child_pid,
193 						   GError **error);
194 
195 gint utils_str_casecmp(const gchar *s1, const gchar *s2);
196 
197 gchar *utils_get_date_time(const gchar *format, time_t *time_to_use);
198 
199 void utils_open_browser(const gchar *uri);
200 
201 guint utils_string_replace_first(GString *haystack, const gchar *needle, const gchar *replace);
202 
203 gchar *utils_str_middle_truncate(const gchar *string, guint truncate_length);
204 
205 gchar *utils_str_remove_chars(gchar *string, const gchar *chars);
206 
207 gchar **utils_copy_environment(const gchar **exclude_vars, const gchar *first_varname, ...) G_GNUC_NULL_TERMINATED;
208 
209 gchar *utils_find_open_xml_tag(const gchar sel[], gint size);
210 
211 const gchar *utils_find_open_xml_tag_pos(const gchar sel[], gint size);
212 
213 gchar *utils_get_real_path(const gchar *file_name);
214 
215 gchar **utils_strv_shorten_file_list(gchar **file_names, gssize file_names_len);
216 
217 #ifdef GEANY_PRIVATE
218 
219 typedef enum
220 {
221 	RESOURCE_DIR_DATA,
222 	RESOURCE_DIR_ICON,
223 	RESOURCE_DIR_DOC,
224 	RESOURCE_DIR_LOCALE,
225 	RESOURCE_DIR_PLUGIN,
226 	RESOURCE_DIR_LIBEXEC,
227 
228 	RESOURCE_DIR_COUNT
229 } GeanyResourceDirType;
230 
231 
232 gint utils_get_line_endings(const gchar* buffer, gsize size);
233 
234 gboolean utils_isbrace(gchar c, gboolean include_angles);
235 
236 gboolean utils_is_opening_brace(gchar c, gboolean include_angles);
237 
238 gboolean utils_is_short_html_tag(const gchar *tag_name);
239 
240 void utils_ensure_same_eol_characters(GString *string, gint target_eol_mode);
241 
242 const gchar *utils_get_eol_char(gint eol_mode);
243 
244 const gchar *utils_get_eol_name(gint eol_mode);
245 
246 const gchar *utils_get_eol_short_name(gint eol_mode);
247 
248 gboolean utils_atob(const gchar *str);
249 
250 void utils_tidy_path(gchar *filename);
251 
252 gboolean utils_is_absolute_path(const gchar *path);
253 
254 const gchar *utils_path_skip_root(const gchar *path);
255 
256 gdouble utils_scale_round(gdouble val, gdouble factor);
257 
258 gchar utils_brace_opposite(gchar ch);
259 
260 gint utils_string_find(GString *haystack, gint start, gint end, const gchar *needle);
261 
262 gint utils_string_replace(GString *str, gint pos, gint len, const gchar *replace);
263 
264 guint utils_string_regex_replace_all(GString *haystack, GRegex *regex,
265 		guint match_num, const gchar *replace, gboolean literal);
266 
267 void utils_str_replace_all(gchar **haystack, const gchar *needle, const gchar *replacement);
268 
269 gint utils_strpos(const gchar* haystack, const gchar *needle);
270 
271 gchar *utils_get_initials(const gchar *name);
272 
273 gchar *utils_get_hex_from_color(GdkColor *color);
274 
275 const gchar *utils_get_default_dir_utf8(void);
276 
277 gchar *utils_get_current_file_dir_utf8(void);
278 
279 void utils_beep(void);
280 
281 gchar *utils_make_human_readable_str(guint64 size, gulong block_size,
282 									 gulong display_unit);
283 
284 gboolean utils_parse_color(const gchar *spec, GdkColor *color);
285 
286 gint utils_color_to_bgr(const GdkColor *color);
287 
288 gint utils_parse_color_to_bgr(const gchar *spec);
289 
290 gchar *utils_get_current_time_string(gboolean include_microseconds);
291 
292 GIOChannel *utils_set_up_io_channel(gint fd, GIOCondition cond, gboolean nblock,
293 									GIOFunc func, gpointer data);
294 
295 gboolean utils_str_replace_escape(gchar *string, gboolean keep_backslash);
296 
297 gboolean utils_wrap_string(gchar *string, gint wrapstart);
298 
299 void utils_free_pointers(gsize arg_count, ...) G_GNUC_NULL_TERMINATED;
300 
301 gchar **utils_strv_new(const gchar *first, ...) G_GNUC_NULL_TERMINATED;
302 
303 gchar **utils_strv_join(gchar **first, gchar **second) G_GNUC_WARN_UNUSED_RESULT;
304 
305 gchar *utils_strv_find_common_prefix(gchar **strv, gssize strv_len) G_GNUC_WARN_UNUSED_RESULT;
306 
307 gchar *utils_strv_find_lcs(gchar **strv, gssize strv_len, const gchar *delim) G_GNUC_WARN_UNUSED_RESULT;
308 
309 GSList *utils_get_config_files(const gchar *subdir);
310 
311 gchar *utils_get_help_url(const gchar *suffix);
312 
313 gboolean utils_str_has_upper(const gchar *str);
314 
315 gint utils_is_file_writable(const gchar *locale_filename);
316 
317 const gchar *utils_get_uri_file_prefix(void);
318 
319 gchar *utils_get_path_from_uri(const gchar *uri);
320 
321 gboolean utils_is_uri(const gchar *uri);
322 
323 gboolean utils_is_remote_path(const gchar *path);
324 
325 GDate *utils_parse_date(const gchar *input);
326 
327 gchar *utils_parse_and_format_build_date(const gchar *input);
328 
329 gchar *utils_get_user_config_dir(void);
330 
331 const gchar *utils_resource_dir(GeanyResourceDirType type);
332 
333 void utils_start_new_geany_instance(const gchar *doc_path);
334 
335 gchar *utils_get_os_info_string(void);
336 
337 #endif /* GEANY_PRIVATE */
338 
339 G_END_DECLS
340 
341 #endif /* GEANY_UTILS_H */
342