/* vim: set ai et ts=4 sw=4: */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include "util.h" //@@backport{{ gchar *la_utf8_regularize(const gchar * str) { gchar *ret; gchar *ptr; ret = g_strdup(str); ptr = ret; // replaces all invalid characters with '?' while (!g_utf8_validate(ptr, -1, (const gchar **) &ptr)) *ptr = '?'; return ret; } gchar *la_utf8_recover(const gchar * str, const gchar * codeset, gint endurance) { gchar *ptr; gchar *ret; gint len; gint bytes_read; gint bytes_written; GError *error; ptr = g_strdup(str); // it's a already valid utf-8 string! :D if (g_utf8_validate(str, -1, NULL)) return ptr; len = strlen(ptr); do { error = NULL; ret = g_convert(ptr, -1, "UTF-8", codeset, &bytes_read, &bytes_written, &error); // ok! we recover it :D if (error == NULL) { g_free(ptr); return ret; } // skip the character makes illegal sequence error if (error->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE) { memmove(ptr + bytes_read, ptr + bytes_read + 1, --len - bytes_read); } // try again :( if (ret) g_free(ret); g_error_free(error); } while (--endurance); g_free(ptr); return la_utf8_regularize(str); } gchar *la_str_to_utf8_with_fallback(const gchar * str, GSList *fallback_codesets, gchar **used_codeset) { gchar *ret; gchar *ptr; gint len; gint i; const gchar *codeset; gint bytes_read; gint bytes_written; GError *error = NULL; gint retry_chance; if (used_codeset) *used_codeset = NULL; // it's a already valid utf-8 string! :D if (g_utf8_validate(str, -1, NULL)) return g_strdup(str); // try to convert with current locale error = NULL; ret = g_locale_to_utf8(str, -1, NULL, NULL, &error); if (error == NULL) return ret; if (ret) g_free(ret); // no fallback codesets specified. if (!fallback_codesets) return g_strdup(str); // try to convert whole string // with speficifed fallback codesets while (fallback_codesets) { codeset = fallback_codesets->data; if (!codeset) continue; error = NULL; ret = g_convert(str, -1, "UTF-8", codeset, &bytes_read, &bytes_written, &error); if (error == NULL) { if (used_codeset) *used_codeset = (gchar *) codeset; return ret; } g_error_free(error); fallback_codesets = g_slist_next(fallback_codesets); } // give up :( if (used_codeset) *used_codeset = NULL; return la_utf8_regularize(str); } inline gchar *la_str_to_utf8(const gchar * str) { return la_str_to_utf8_with_fallback(str, NULL, NULL); } inline gchar *la_ltostr(gchar * buf, gint length, glong l) { g_snprintf(buf, length, "%d", l); return buf; } inline gchar *la_ltostr_new(glong l) { return g_strdup_printf("%d", l); } glong la_strtol(const gchar * str, glong fallback) { glong l; gchar *tail; if (LA_STR_IS_EMPTY(str)) return fallback; l = strtol(str, &tail, 10); return (str != tail) ? l : fallback; } inline gchar *la_btostr(gchar * buf, gint length, gboolean b) { g_strlcpy(buf, (b) ? "true" : "false", length); return buf; } inline gchar *la_btostr_new(gboolean b) { return g_strdup((b) ? "true" : "false"); } gboolean la_strtob(const gchar * str, gboolean fallback) { if (LA_STR_IS_EMPTY(str)) return fallback; if (strcasecmp(str, "false") && strcasecmp(str, "no") && strcmp(str, "off") && strcmp(str, "0")) return TRUE; return fallback; } //@@}} // FIXME: more elegant way to detect application pixmaps directory #define PIXMAP_DIR PACKAGE_DATA_DIR \ G_DIR_SEPARATOR_S \ "pixmaps" \ G_DIR_SEPARATOR_S \ PACKAGE \ G_DIR_SEPARATOR_S /* This is an internally used function to find pixmap files. */ gchar* find_pixmap_file(const gchar* filename) { gchar* pathname; // absolute path if(filename[0] == '/') { if(g_file_test(filename, G_FILE_TEST_EXISTS)) return g_strdup(filename); } // relative path pathname = g_strdup_printf(PIXMAP_DIR "%s", filename); if(g_file_test(pathname, G_FILE_TEST_EXISTS)) { return pathname; } g_warning(_("Couldn't find pixmap file: %s"), pathname); g_free(pathname); return NULL; //return gnome_program_locate_file(liteamp.program, GNOME_FILE_DOMAIN_PIXMAP, filename, TRUE, NULL); } GtkWidget* create_pixmap(const gchar* filename) { GdkPixbuf* pixbuf = create_pixbuf(filename); return (pixbuf) ? gtk_image_new_from_pixbuf(pixbuf) : gtk_image_new(); } GtkWidget* create_pixmap_with_size(const gchar* filename, gint width, gint height) { GdkPixbuf* pixbuf = create_pixbuf_with_size(filename, width, height); return (pixbuf) ? gtk_image_new_from_pixbuf(pixbuf) : gtk_image_new(); } GdkPixbuf* create_pixbuf(const gchar* filename) { GdkPixbuf *pixbuf; gchar* pathname = NULL; GError* error = NULL; if(!filename || !filename[0]) return NULL; pathname = find_pixmap_file(filename); if(!pathname) return NULL; pixbuf = gdk_pixbuf_new_from_file(pathname, &error); if(!pixbuf) { fprintf(stderr, "Failed to load pixbuf file: %s: %s\n", pathname, error->message); g_error_free(error); } g_free(pathname); return pixbuf; } GdkPixbuf* create_pixbuf_with_size(const gchar* filename, gint width, gint height) { GdkPixbuf* pixbuf = create_pixbuf(filename); GdkPixbuf* scaled_pixbuf; if(pixbuf) { scaled_pixbuf = gdk_pixbuf_scale_simple(pixbuf, width, height, GDK_INTERP_BILINEAR); return scaled_pixbuf; } //return pixbuf; return NULL; } gboolean str_has_suffix(const gchar* str, const gchar* suffix, gboolean case_sensitive) { int len, suffix_len; if((len = strlen(str)) < (suffix_len = strlen(suffix))) { return FALSE; } return (case_sensitive) ? !strncmp(str + len - suffix_len, suffix, suffix_len) : !strncasecmp(str + len - suffix_len, suffix, suffix_len); } gint strfindv(const gchar* str, const gchar** str_array, gboolean case_sensitive) { int i; for(i = 0; str_array[i] != NULL; i++) { if(case_sensitive) { if(!strcmp(str, str_array[i])) return i; } else { if(!strcasecmp(str, str_array[i])) return i; } } return -1; } gchar* format_size_str(gchar* buf, gint length, gulong size) { if(size > 1024 * 1024 * 1024) g_snprintf(buf, length, "%.1fG", (gdouble)size / (1024 * 1024 * 1024)); else if(size > 1024 * 1024) g_snprintf(buf, length, "%.1fM", (gdouble)size / (1024 * 1024)); else if(size > 1024) g_snprintf(buf, length, "%.1fK", (gdouble)size / 1024); else g_snprintf(buf, length, "%u", size); return buf; } gchar* format_time_str(gchar* buf, gint length, gulong sec) { if(sec > 3600) g_snprintf(buf, length, "%u:%02u:%02u", sec / 3600, (sec % 3600) / 60, (sec % 3600) % 60); else g_snprintf(buf, length, "%02u:%02u", sec / 60, sec % 60); return buf; } gulong file_length(const gchar* filename) { struct stat st; stat(filename, &st); return st.st_size; } /* g_filename_to_utf8 */ gchar* filename_to_utf8(const gchar* str) { gchar* ret = g_filename_to_utf8(str, -1, NULL, NULL, NULL); //FIXME: more elegant way to determine charset if(ret == NULL) { ret = g_locale_to_utf8(str, -1, NULL, NULL, NULL); if(ret == NULL) { // give up! return itself ret = g_convert_with_fallback(str, -1, "UTF-8", "UTF-8", NULL, NULL, NULL, NULL); //ret = g_strdup(str); } } return ret; } /* g_filename_from_utf8 */ gchar* utf8_to_filename(const gchar* str) { gchar* ret = g_filename_from_utf8(str, -1, NULL, NULL, NULL); if(ret == NULL) { // give up! return itself ret = g_strdup(str); } return ret; } /** g_locale_to_utf8 */ gchar* locale_to_utf8(const gchar* str) { gchar* ret = g_locale_to_utf8(str, -1, NULL, NULL, NULL); if(ret == NULL) { // give up! return itself ret = g_convert_with_fallback(str, -1, "UTF-8", "UTF-8", NULL, NULL, NULL, NULL); //ret = g_strdup(str); } return ret; } /** g_locale_from_utf8 */ gchar* utf8_to_locale(const gchar* str) { gchar* ret = g_locale_from_utf8(str, -1, NULL, NULL, NULL); if(ret == NULL) { // give up! return itself ret = g_strdup(str); } return ret; } gchar* escape_str(const gchar* str) { gchar *ret = g_markup_escape_text(g_strstrip((gchar *) str), -1); if (!ret) { ret = g_strdup(str); } return ret; } gint show_message_box(GtkWindow* parent, GtkMessageType type, GtkButtonsType buttons, const gchar* message) { GtkWidget* dlg; gint result; dlg = gtk_message_dialog_new(parent, GTK_DIALOG_DESTROY_WITH_PARENT, type, buttons, message); result = gtk_dialog_run(GTK_DIALOG(dlg)); gtk_widget_destroy(dlg); return result; } GList* array_to_list(gpointer* array) { GList* list = NULL; gpointer* ptr = array; while(*ptr != NULL) { list = g_list_append(list, *ptr); ptr++; } return list; } /*util.c*/