1
/* vi:set et ai sw=2 sts=2 ts=2: */
3
* Copyright (c) 2006-2007 Benedikt Meurer <benny@xfce.org>
4
* Copyright (c) 2009-2010 Jannis Pohlmann <jannis@xfce.org>
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License as
8
* published by the Free Software Foundation; either version 2 of
9
* the License, or (at your option) any later version.
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.
16
* You should have received a copy of the GNU General Public
17
* License along with this program; if not, write to the Free
18
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19
* Boston, MA 02110-1301, USA.
26
#ifdef HAVE_SYS_TYPES_H
27
#include <sys/types.h>
29
#ifdef HAVE_SYS_PARAM_H
30
#include <sys/param.h>
52
#ifdef G_PLATFORM_WIN32
54
#include <glib/gwin32.h>
57
#include <thunar/thunar-private.h>
58
#include <thunar/thunar-util.h>
63
* thunar_util_expand_filename:
64
* @filename : a local filename.
65
* @working_directory : #GFile of the current working directory.
66
* @error : return location for errors or %NULL.
68
* Takes a user-typed @filename and expands a tilde at the
69
* beginning of the @filename. It also resolves paths prefixed with
70
* '.' using the current working directory.
72
* The caller is responsible to free the returned string using
73
* g_free() when no longer needed.
75
* Return value: the expanded @filename or %NULL on error.
78
thunar_util_expand_filename (const gchar *filename,
79
GFile *working_directory,
82
struct passwd *passwd;
83
const gchar *replacement;
84
const gchar *remainder;
90
g_return_val_if_fail (filename != NULL, NULL);
92
/* check if we have a valid (non-empty!) filename */
93
if (G_UNLIKELY (*filename == '\0'))
95
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, _("Invalid path"));
99
/* check if we start with a '~' */
100
if (*filename == '~')
102
/* examine the remainder of the filename */
103
remainder = filename + 1;
105
/* if we have only the slash, then we want the home dir */
106
if (G_UNLIKELY (*remainder == '\0'))
107
return g_strdup (xfce_get_homedir ());
109
/* lookup the slash */
110
for (slash = remainder; *slash != '\0' && *slash != G_DIR_SEPARATOR; ++slash);
112
/* check if a username was given after the '~' */
113
if (G_LIKELY (slash == remainder))
115
/* replace the tilde with the home dir */
116
replacement = xfce_get_homedir ();
120
/* lookup the pwd entry for the username */
121
username = g_strndup (remainder, slash - remainder);
122
passwd = getpwnam (username);
125
/* check if we have a valid entry */
126
if (G_UNLIKELY (passwd == NULL))
128
username = g_strndup (remainder, slash - remainder);
129
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, _("Unknown user \"%s\""), username);
134
/* use the homedir of the specified user */
135
replacement = passwd->pw_dir;
138
/* generate the filename */
139
return g_build_filename (replacement, slash, NULL);
141
else if (*filename == '.')
143
/* examine the remainder of the filename */
144
remainder = filename + 1;
146
/* transform working directory into a filename string */
147
if (G_LIKELY (working_directory != NULL))
149
pwd = g_file_get_path (working_directory);
151
/* if we only have the slash then we want the working directory only */
152
if (G_UNLIKELY (*remainder == '\0'))
155
/* concatenate working directory and remainder */
156
result = g_build_filename (pwd, remainder, G_DIR_SEPARATOR_S, NULL);
158
/* free the working directory string */
162
result = g_strdup (filename);
164
/* return the resulting path string */
168
return g_strdup (filename);
174
* thunar_util_humanize_file_time:
175
* @file_time : a #guint64 timestamp.
176
* @date_format : the #ThunarDateFormat used to humanize the @file_time.
178
* Returns a human readable date representation of the specified
179
* @file_time. The caller is responsible to free the returned
180
* string using g_free() when no longer needed.
182
* Return value: a human readable date representation of @file_time
183
* according to the @date_format.
186
thunar_util_humanize_file_time (guint64 file_time,
187
ThunarDateStyle date_style)
189
const gchar *date_format;
196
/* check if the file_time is valid */
197
if (G_LIKELY (file_time != 0))
199
ftime = (time_t) file_time;
201
/* determine the local file time */
202
tfile = localtime (&ftime);
204
/* check which style to use to format the time */
205
if (date_style == THUNAR_DATE_STYLE_SIMPLE || date_style == THUNAR_DATE_STYLE_SHORT)
207
/* setup the dates for the time values */
208
g_date_set_time_t (&dfile, (time_t) ftime);
209
g_date_set_time_t (&dnow, time (NULL));
211
/* determine the difference in days */
212
diff = g_date_get_julian (&dnow) - g_date_get_julian (&dfile);
215
if (date_style == THUNAR_DATE_STYLE_SIMPLE)
217
/* TRANSLATORS: file was modified less than one day ago */
218
return g_strdup (_("Today"));
220
else /* if (date_style == THUNAR_DATE_STYLE_SHORT) */
222
/* TRANSLATORS: file was modified less than one day ago */
223
return exo_strdup_strftime (_("Today at %X"), tfile);
228
if (date_style == THUNAR_DATE_STYLE_SIMPLE)
230
/* TRANSLATORS: file was modified less than two days ago */
231
return g_strdup (_("Yesterday"));
233
else /* if (date_style == THUNAR_DATE_STYLE_SHORT) */
235
/* TRANSLATORS: file was modified less than two days ago */
236
return exo_strdup_strftime (_("Yesterday at %X"), tfile);
241
if (diff > 1 && diff < 7)
243
/* Days from last week */
244
date_format = (date_style == THUNAR_DATE_STYLE_SIMPLE) ? "%A" : _("%A at %X");
249
date_format = (date_style == THUNAR_DATE_STYLE_SIMPLE) ? "%x" : _("%x at %X");
252
/* format the date string accordingly */
253
return exo_strdup_strftime (date_format, tfile);
256
else if (date_style == THUNAR_DATE_STYLE_LONG)
258
/* use long, date(1)-like format string */
259
return exo_strdup_strftime ("%c", tfile);
261
else /* if (date_style == THUNAR_DATE_STYLE_ISO) */
263
/* use ISO date formatting */
264
return exo_strdup_strftime ("%Y-%m-%d %H:%M:%S", tfile);
268
/* the file_time is invalid */
269
return g_strdup (_("Unknown"));
275
* thunar_util_parse_parent:
276
* @parent : a #GtkWidget, a #GdkScreen or %NULL.
277
* @window_return : return location for the toplevel #GtkWindow or
280
* Determines the screen for the @parent and returns that #GdkScreen.
281
* If @window_return is not %NULL, the pointer to the #GtkWindow is
282
* placed into it, or %NULL if the window could not be determined.
284
* Return value: the #GdkScreen for the @parent.
287
thunar_util_parse_parent (gpointer parent,
288
GtkWindow **window_return)
291
GtkWidget *window = NULL;
293
_thunar_return_val_if_fail (parent == NULL || GDK_IS_SCREEN (parent) || GTK_IS_WIDGET (parent), NULL);
295
/* determine the proper parent */
298
/* just use the default screen then */
299
screen = gdk_screen_get_default ();
301
else if (GDK_IS_SCREEN (parent))
303
/* yep, that's a screen */
304
screen = GDK_SCREEN (parent);
308
/* parent is a widget, so let's determine the toplevel window */
309
window = gtk_widget_get_toplevel (GTK_WIDGET (parent));
310
if (GTK_WIDGET_TOPLEVEL (window))
312
/* make sure the toplevel window is shown */
313
gtk_widget_show_now (window);
317
/* no toplevel, not usable then */
321
/* determine the screen for the widget */
322
screen = gtk_widget_get_screen (GTK_WIDGET (parent));
325
/* check if we should return the window */
326
if (G_LIKELY (window_return != NULL))
327
*window_return = (GtkWindow *) window;
335
* thunar_util_time_from_rfc3339:
336
* @date_string : an RFC 3339 encoded date string.
338
* Decodes the @date_string, which must be in the special RFC 3339
339
* format <literal>YYYY-MM-DDThh:mm:ss</literal>. This method is
340
* used to decode deletion dates of files in the trash. See the
341
* Trash Specification for details.
343
* Return value: the time value matching the @date_string or
344
* %0 if the @date_string could not be parsed.
347
thunar_util_time_from_rfc3339 (const gchar *date_string)
352
/* using strptime() its easy to parse the date string */
353
if (G_UNLIKELY (strptime (date_string, "%FT%T", &tm) == NULL))
358
/* be sure to start with a clean tm */
359
memset (&tm, 0, sizeof (tm));
361
/* parsing by hand is also doable for RFC 3339 dates */
362
val = strtoul (date_string, (gchar **) &date_string, 10);
363
if (G_UNLIKELY (*date_string != '-'))
367
tm.tm_year = val - 1900;
369
tm.tm_mon = strtoul (date_string, (gchar **) &date_string, 10) - 1;
371
if (G_UNLIKELY (*date_string++ != '-'))
374
tm.tm_mday = strtoul (date_string, (gchar **) &date_string, 10);
376
if (G_UNLIKELY (*date_string++ != 'T'))
379
val = strtoul (date_string, (gchar **) &date_string, 10);
380
if (G_UNLIKELY (*date_string != ':'))
386
tm.tm_min = strtoul (date_string, (gchar **) &date_string, 10);
388
if (G_UNLIKELY (*date_string++ != ':'))
391
tm.tm_sec = strtoul (date_string, (gchar **) &date_string, 10);
392
#endif /* !HAVE_STRPTIME */
394
/* translate tm to time_t */
401
thunar_util_change_working_directory (const gchar *new_directory)
403
gchar *old_directory;
405
_thunar_return_val_if_fail (new_directory != NULL && *new_directory != '\0', NULL);
407
/* allocate a path buffer for the old working directory */
408
old_directory = g_malloc0 (sizeof (gchar) * MAXPATHLEN);
410
/* try to determine the current working directory */
411
#ifdef G_PLATFORM_WIN32
412
if (_getcwd (old_directory, MAXPATHLEN) == NULL)
414
if (getcwd (old_directory, MAXPATHLEN) == NULL)
417
/* working directory couldn't be determined, reset the buffer */
418
g_free (old_directory);
419
old_directory = NULL;
422
/* try switching to the new working directory */
423
#ifdef G_PLATFORM_WIN32
424
if (_chdir (new_directory) != 0)
426
if (chdir (new_directory) != 0)
429
/* switching failed, we don't need to return the old directory */
430
g_free (old_directory);
431
old_directory = NULL;
434
return old_directory;