d780795d2a16a458b9788418d5c0f8d757ba7447
[geeqie.git] / src / misc.c
1 /*
2  * Copyright (C) 2008 - 2016 The Geeqie Team
3  *
4  * Authors: Vladimir Nadvornik, Laurent Monin
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 #include "main.h"
22 #include "misc.h"
23 #include "ui_fileops.h"
24
25 #include <langinfo.h>
26
27 gdouble get_zoom_increment(void)
28 {
29         return ((options->image.zoom_increment != 0) ? (gdouble)options->image.zoom_increment / 100.0 : 1.0);
30 }
31
32 gchar *utf8_validate_or_convert(const gchar *text)
33 {
34         gint len;
35
36         if (!text) return NULL;
37
38         len = strlen(text);
39         if (!g_utf8_validate(text, len, NULL))
40                 return g_convert(text, len, "UTF-8", "ISO-8859-1", NULL, NULL, NULL);
41
42         return g_strdup(text);
43 }
44
45 gint utf8_compare(const gchar *s1, const gchar *s2, gboolean case_sensitive)
46 {
47         gchar *s1_key, *s2_key;
48         gchar *s1_t, *s2_t;
49         gint ret;
50
51         g_assert(g_utf8_validate(s1, -1, NULL));
52         g_assert(g_utf8_validate(s2, -1, NULL));
53
54         if (!case_sensitive)
55                 {
56                 s1_t = g_utf8_casefold(s1, -1);
57                 s2_t = g_utf8_casefold(s2, -1);
58                 }
59         else
60                 {
61                 s1_t = (gchar *) s1;
62                 s2_t = (gchar *) s2;
63                 }
64
65         s1_key = g_utf8_collate_key(s1_t, -1);
66         s2_key = g_utf8_collate_key(s2_t, -1);
67
68         ret = strcmp(s1_key, s2_key);
69
70         g_free(s1_key);
71         g_free(s2_key);
72
73         if (!case_sensitive)
74                 {
75                 g_free(s1_t);
76                 g_free(s2_t);
77                 }
78
79         return ret;
80 }
81
82 /* Borrowed from gtkfilesystemunix.c */
83 gchar *expand_tilde(const gchar *filename)
84 {
85 #ifndef G_OS_UNIX
86         return g_strdup(filename);
87 #else
88         const gchar *notilde;
89         const gchar *slash;
90         const gchar *home;
91
92         if (filename[0] != '~')
93                 return g_strdup(filename);
94
95         notilde = filename + 1;
96         slash = strchr(notilde, G_DIR_SEPARATOR);
97         if (slash == notilde || !*notilde)
98                 {
99                 home = g_get_home_dir();
100                 if (!home)
101                         return g_strdup(filename);
102                 }
103         else
104                 {
105                 gchar *username;
106                 struct passwd *passwd;
107
108                 if (slash)
109                         username = g_strndup(notilde, slash - notilde);
110                 else
111                         username = g_strdup(notilde);
112
113                 passwd = getpwnam(username);
114                 g_free(username);
115
116                 if (!passwd)
117                         return g_strdup(filename);
118
119                 home = passwd->pw_dir;
120                 }
121
122         if (slash)
123                 return g_build_filename(home, G_DIR_SEPARATOR_S, slash + 1, NULL);
124         else
125                 return g_build_filename(home, G_DIR_SEPARATOR_S, NULL);
126 #endif
127 }
128
129 /* Search for latitude/longitude parameters in a string
130  */
131
132 #define GEOCODE_NAME "geocode-parameters.awk"
133 #define BUFSIZE 128
134
135 gchar *decode_geo_script(const gchar *path_dir, const gchar *input_text)
136 {
137         gchar *message;
138         gchar *path = g_build_filename(path_dir, GEOCODE_NAME, NULL);
139         gchar *cmd = g_strconcat("echo \'", input_text, "\'  | awk -f ", path, NULL);
140
141         if (g_file_test(path, G_FILE_TEST_EXISTS))
142                 {
143                 gchar buf[BUFSIZE];
144                 FILE *fp;
145
146                 if ((fp = popen(cmd, "r")) == NULL)
147                         {
148                         message = g_strconcat("Error: opening pipe\n", input_text, NULL);
149                         }
150                 else
151                         {
152                         while (fgets(buf, BUFSIZE, fp))
153                                 {
154                                 DEBUG_1("Output: %s", buf);
155                                 }
156
157                         message = g_strconcat(buf, NULL);
158
159                         if(pclose(fp))
160                                 {
161                                 message = g_strconcat("Error: Command not found or exited with error status\n", input_text, NULL);
162                                 }
163                         }
164                 }
165         else
166                 {
167                 message = g_strconcat(input_text, NULL);
168                 }
169
170         g_free(path);
171         g_free(cmd);
172         return message;
173 }
174
175 gchar *decode_geo_parameters(const gchar *input_text)
176 {
177         gchar *message;
178         gchar *dir;
179
180         message = decode_geo_script(GQ_BIN_DIR, input_text);
181         if (strstr(message, "Error"))
182                 {
183                 g_free(message);
184                 dir = g_build_filename(get_rc_dir(), "applications", NULL);
185                 message = decode_geo_script(dir, input_text);
186                 g_free(dir);
187                 }
188
189         return message;
190 }
191
192 /* Run a command like system() but may output debug messages. */
193 int runcmd(gchar *cmd)
194 {
195 #if 1
196         return system(cmd);
197         return 0;
198 #else
199         /* For debugging purposes */
200         int retval = -1;
201         FILE *in;
202
203         DEBUG_1("Running command: %s", cmd);
204
205         in = popen(cmd, "r");
206         if (in)
207                 {
208                 int status;
209                 const gchar *msg;
210                 gchar buf[2048];
211
212                 while (fgets(buf, sizeof(buf), in) != NULL )
213                         {
214                         DEBUG_1("Output: %s", buf);
215                         }
216
217                 status = pclose(in);
218
219                 if (WIFEXITED(status))
220                         {
221                         msg = "Command terminated with exit code";
222                         retval = WEXITSTATUS(status);
223                         }
224                 else if (WIFSIGNALED(status))
225                         {
226                         msg = "Command was killed by signal";
227                         retval = WTERMSIG(status);
228                         }
229                 else
230                         {
231                         msg = "pclose() returned";
232                         retval = status;
233                         }
234
235                 DEBUG_1("%s : %d\n", msg, retval);
236         }
237
238         return retval;
239 #endif
240 }
241
242 /**
243  * @brief Returns integer representing first_day_of_week
244  * @returns Integer in range 1 to 7
245  * 
246  * Uses current locale to get first day of week
247  * 
248  * Sunday == 1
249  */
250 gint date_get_first_day_of_week()
251 {
252         return nl_langinfo(_NL_TIME_FIRST_WEEKDAY)[0];
253 }
254
255 /**
256  * @brief Get an abbreviated day name from locale
257  * @param day Integer in range 1 to 7, representing day of week
258  * @returns String containing abbreviated day name
259  * 
260  *  Uses current locale to get day name
261  * 
262  * Sunday == 1
263  * Result must be freed
264  */
265 gchar *date_get_abbreviated_day_name(gint day)
266 {
267         gchar *abday = NULL;
268
269         switch (day)
270                 {
271                 case 1:
272                 abday = g_strdup(nl_langinfo(ABDAY_1));
273                 break;
274                 case 2:
275                 abday = g_strdup(nl_langinfo(ABDAY_2));
276                 break;
277                 case 3:
278                 abday = g_strdup(nl_langinfo(ABDAY_3));
279                 break;
280                 case 4:
281                 abday = g_strdup(nl_langinfo(ABDAY_4));
282                 break;
283                 case 5:
284                 abday = g_strdup(nl_langinfo(ABDAY_5));
285                 break;
286                 case 6:
287                 abday = g_strdup(nl_langinfo(ABDAY_6));
288                 break;
289                 case 7:
290                 abday = g_strdup(nl_langinfo(ABDAY_7));
291                 break;
292                 }
293
294         return abday;
295 }
296
297 gchar *convert_rating_to_stars(gint rating)
298 {
299         gchar *ret;
300         GString *str = g_string_new(NULL);
301
302         if (rating == -1)
303                 {
304                 str = g_string_append_unichar(str, options->star_rating.rejected);
305                 ret = g_strdup(str->str);
306                 g_string_free(str, TRUE);
307                 }
308         else if (rating > 0 && rating < 6)
309                 {
310                 while (rating > 0)
311                         {
312                         str = g_string_append_unichar(str, options->star_rating.star);
313                         rating = rating - 1;
314                         }
315                 ret = g_strdup(str->str);
316                 g_string_free(str, TRUE);
317                 }
318         else
319                 {
320                 ret = g_strdup("");
321                 }
322
323         return ret;
324 }
325
326 gchar *get_symbolic_link(const gchar *path_utf8)
327 {
328         gchar *sl;
329         struct stat st;
330         gchar *ret = g_strdup("");
331
332         sl = path_from_utf8(path_utf8);
333
334         if (lstat(sl, &st) == 0 && S_ISLNK(st.st_mode))
335                 {
336                 gchar *buf;
337                 gint l;
338
339                 buf = g_malloc(st.st_size + 1);
340                 l = readlink(sl, buf, st.st_size);
341
342                 if (l == st.st_size)
343                         {
344                         buf[l] = '\0';
345
346                         ret = buf;
347                         }
348                 else
349                         {
350                         g_free(buf);
351                         }
352                 }
353
354         g_free(sl);
355
356         return ret;
357 }
358
359 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */