/****************************************************************************** * $Id$ * * Copyright (c) 2005-2007 Transmission authors and contributors * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include #include #include #include #include #include #include #include #include #include "tr_prefs.h" #include "tr_torrent.h" #include "conf.h" #include "util.h" static void errcb(GtkWidget *wind, int resp, gpointer data); int tr_strcmp( const char * a, const char * b ) { if( a && b ) return strcmp( a, b ); if( a ) return 1; if( b ) return -1; return 0; } char* tr_strlsize( char * buf, guint64 size, size_t buflen ) { if( !size ) g_strlcpy( buf, _("None"), buflen ); else { static const char *units[] = { N_("B"), N_("KiB"), N_("MiB"), N_("GiB"), N_("TiB"), N_("PiB"), N_("EiB"), N_("ZiB"), N_("YiB") }; unsigned int i; guint64 small = size; for( i=0; i=1024; ++i ) small >>= 10; if( small < 100 ) g_snprintf( buf, buflen, "%.1f %s", (double)small, _(units[i]) ); else g_snprintf( buf, buflen, "%d %s", (int)small, _(units[i]) ); } return buf; } char* tr_strlspeed( char * buf, double KiBps, size_t buflen ) { const guint64 bps = KiBps * 1024; if( !bps ) g_strlcpy( buf, _("None"), buflen ); else { char bbuf[64]; tr_strlsize( bbuf, (guint64)(KiBps*1024), sizeof(bbuf) ); g_snprintf( buf, buflen, "%s/s", bbuf ); } return buf; } #define SECONDS(s) ((s) % 60) #define MINUTES(s) ((s) / 60 % 60) #define HOURS(s) ((s) / 60 / 60 % 24) #define DAYS(s) ((s) / 60 / 60 / 24 % 7) char * readabletime(int secs) { if(60 > secs) return g_strdup_printf(_("%i %s"), SECONDS(secs), ngettext("sec", "secs", SECONDS(secs))); else if(60 * 60 > secs) return g_strdup_printf(_("%i %s %i %s"), MINUTES(secs), ngettext("min", "mins", MINUTES(secs)), SECONDS(secs), ngettext("sec", "secs", SECONDS(secs))); else if(60 * 60 * 24 > secs) return g_strdup_printf(_("%i %s %i %s"), HOURS(secs), ngettext("hr", "hrs", HOURS(secs)), MINUTES(secs), ngettext("min", "mins", MINUTES(secs))); else return g_strdup_printf(_("%i %s %i %s"), DAYS(secs), ngettext("day", "days", DAYS(secs)), HOURS(secs), ngettext("hr", "hrs", HOURS(secs))); } char * rfc822date (guint64 epoch_msec) { const time_t secs = epoch_msec / 1000; const struct tm tm = *localtime (&secs); char buf[128]; strftime( buf, sizeof(buf), "%a, %d %b %Y %T %Z", &tm ); return g_locale_to_utf8( buf, -1, NULL, NULL, NULL ); } gboolean mkdir_p(const char *name, mode_t mode) { #if GLIB_CHECK_VERSION(2,8,0) return !g_mkdir_with_parents( name, mode ); #else struct stat sb; char *parent; gboolean ret; int oerrno; if(0 != stat(name, &sb)) { if(ENOENT != errno) return FALSE; parent = g_path_get_dirname(name); ret = mkdir_p(parent, mode); oerrno = errno; g_free(parent); errno = oerrno; return (ret ? (0 == mkdir(name, mode)) : FALSE); } if(!S_ISDIR(sb.st_mode)) { errno = ENOTDIR; return FALSE; } return TRUE; #endif } GList * dupstrlist( GList * l ) { GList * ret = NULL; for( ; l!=NULL; l=l->next ) ret = g_list_prepend( ret, g_strdup( l->data ) ); return g_list_reverse( ret ); } char * joinstrlist(GList *list, char *sep) { GList *l; GString *gstr = g_string_new (NULL); for (l=list; l!=NULL; l=l->next) { g_string_append (gstr, (char*)l->data); if (l->next != NULL) g_string_append (gstr, (sep)); } return g_string_free (gstr, FALSE); } void freestrlist(GList *list) { g_list_foreach (list, (GFunc)g_free, NULL); g_list_free (list); } char * urldecode(const char *str, int len) { int ii, jj; char *ret; if( len <= 0 ) len = strlen( str ); for(ii = jj = 0; ii < len; ii++, jj++) if('%' == str[ii]) ii += 2; ret = g_new(char, jj + 1); for(ii = jj = 0; ii < len; ii++, jj++) { switch(str[ii]) { case '%': if(ii + 2 < len) { char buf[3] = { str[ii+1], str[ii+2], '\0' }; ret[jj] = g_ascii_strtoull(buf, NULL, 16); } ii += 2; break; case '+': ret[jj] = ' '; default: ret[jj] = str[ii]; } } ret[jj] = '\0'; return ret; } GList * checkfilenames( int argc, char **argv ) { int i; GList * ret = NULL; char * pwd = g_get_current_dir( ); for( i=0; idata; data = funcdata->next->data; func(data); g_list_free(funcdata); } gtk_widget_destroy(widget); } typedef void (PopupFunc)(GtkWidget*, GdkEventButton*); /* pop up the context menu if a user right-clicks. if the row they right-click on isn't selected, select it. */ gboolean on_tree_view_button_pressed (GtkWidget * view, GdkEventButton * event, gpointer func) { GtkTreeView * tv = GTK_TREE_VIEW( view ); if (event->type == GDK_BUTTON_PRESS && event->button == 3) { GtkTreeSelection * selection = gtk_tree_view_get_selection(tv); GtkTreePath *path; if (gtk_tree_view_get_path_at_pos (tv, (gint) event->x, (gint) event->y, &path, NULL, NULL, NULL)) { if (!gtk_tree_selection_path_is_selected (selection, path)) { gtk_tree_selection_unselect_all (selection); gtk_tree_selection_select_path (selection, path); } gtk_tree_path_free(path); } ((PopupFunc*)func)(view, event); return TRUE; } return FALSE; }