📄 util.c
字号:
/* XMMS - Cross-platform multimedia player * Copyright (C) 1998-2001 Peter Alm, Mikael Alm, Olle Hallnas, * Thomas Nilsson and 4Front Technologies * Copyright (C) 1999-2001 Haavard Kvaalen <havardk@xmms.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "xmms.h"#include <gdk/gdkprivate.h>#include <X11/Xlib.h>#include <sys/ipc.h>#include <ctype.h>#ifdef HAVE_FTS_H#include <fts.h>#endifstatic GQuark quark_popup_data;/* * find_file_recursively() by J鰎g Schuler Wed, 17 Feb 1999 23:50:52 * +0100 Placed under GPL version 2 or (at your option) any later * version *//* * find <file> in directory <dirname> or subdirectories. return * pointer to complete filename which has to be freed by calling * "g_free()" after use. Returns NULL if file could not be found. */gchar *find_file_recursively(const char *dirname, const char *file){ DIR *dir; struct dirent *dirent; char *result, *found; struct stat buf; if ((dir = opendir(dirname)) == NULL) return NULL; while ((dirent = readdir(dir)) != NULL) { /* Don't scan "." and ".." */ if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, "..")) continue; /* We need this in order to find out if file is directory */ found = g_strconcat(dirname, "/", dirent->d_name, NULL); if (stat(found, &buf) != 0) { /* Error occured */ g_free(found); closedir(dir); return NULL; } if (!S_ISDIR(buf.st_mode)) { /* Normal file -- maybe just what we are looking for? */ if (!strcasecmp(dirent->d_name, file)) { if (strlen(found) > FILENAME_MAX) { /* No good! File + path too long */ g_free(found); closedir(dir); return NULL; } else { closedir(dir); return found; } } } g_free(found); } rewinddir(dir); while ((dirent = readdir(dir)) != NULL) { /* Don't scan "." and ".." */ if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, "..")) continue; /* We need this in order to find out if file is directory */ found = g_strconcat(dirname, "/", dirent->d_name, NULL); if (stat(found, &buf) != 0) { /* Error occured */ g_free(found); closedir(dir); return NULL; } if (S_ISDIR(buf.st_mode)) { /* Found directory -- descend into it */ result = find_file_recursively(found, file); if (result != NULL) { /* Found file there -- exit */ g_free(found); closedir(dir); return result; } } g_free(found); } closedir(dir); return NULL;}void del_directory(const char *dirname){#ifdef HAVE_FTS_H char * const argv[2] = { (char *) dirname, NULL }; FTS *fts; FTSENT *p; fts = fts_open(argv, FTS_PHYSICAL, (int (*)())NULL); while ((p = fts_read(fts)) != NULL) { switch (p->fts_info) { case FTS_D: break; case FTS_DNR: case FTS_ERR: break; case FTS_DP: rmdir(p->fts_accpath); break; default: unlink(p->fts_accpath); break; } } fts_close(fts);#else /* !HAVE_FTS_H */ DIR *dir; struct dirent *dirent; char *file; if ((dir = opendir(dirname)) != NULL) { while ((dirent = readdir(dir)) != NULL) { if (strcmp(dirent->d_name, ".") && strcmp(dirent->d_name, "..")) { file = g_strdup_printf("%s/%s", dirname, dirent->d_name); if (unlink(file) == -1) if (errno == EISDIR) del_directory(file); g_free(file); } } closedir(dir); } rmdir(dirname);#endif /* !HAVE_FTS_H */}GdkImage *create_dblsize_image(GdkImage * img){ GdkImage *dblimg; register guint x, y; /* * This needs to be optimized */ dblimg = gdk_image_new(GDK_IMAGE_NORMAL, gdk_visual_get_best(), img->width << 1, img->height << 1); if (dblimg->bpp == 1) { register guint8 *srcptr, *ptr, *ptr2, pix; srcptr = GDK_IMAGE_XIMAGE(img)->data; ptr = GDK_IMAGE_XIMAGE(dblimg)->data; ptr2 = ptr + dblimg->bpl; for (y = 0; y < img->height; y++) { for (x = 0; x < img->width; x++) { pix = *srcptr++; *ptr++ = pix; *ptr++ = pix; *ptr2++ = pix; *ptr2++ = pix; } srcptr += img->bpl - img->width; ptr += (dblimg->bpl << 1) - dblimg->width; ptr2 += (dblimg->bpl << 1) - dblimg->width; } } if (dblimg->bpp == 2) { guint16 *srcptr, *ptr, *ptr2, pix; srcptr = (guint16 *) GDK_IMAGE_XIMAGE(img)->data; ptr = (guint16 *) GDK_IMAGE_XIMAGE(dblimg)->data; ptr2 = ptr + (dblimg->bpl >> 1); for (y = 0; y < img->height; y++) { for (x = 0; x < img->width; x++) { pix = *srcptr++; *ptr++ = pix; *ptr++ = pix; *ptr2++ = pix; *ptr2++ = pix; } srcptr += (img->bpl >> 1) - img->width; ptr += (dblimg->bpl) - dblimg->width; ptr2 += (dblimg->bpl) - dblimg->width; } } if (dblimg->bpp == 3) { register guint8 *srcptr, *ptr, *ptr2, pix1, pix2, pix3; srcptr = GDK_IMAGE_XIMAGE(img)->data; ptr = GDK_IMAGE_XIMAGE(dblimg)->data; ptr2 = ptr + dblimg->bpl; for (y = 0; y < img->height; y++) { for (x = 0; x < img->width; x++) { pix1 = *srcptr++; pix2 = *srcptr++; pix3 = *srcptr++; *ptr++ = pix1; *ptr++ = pix2; *ptr++ = pix3; *ptr++ = pix1; *ptr++ = pix2; *ptr++ = pix3; *ptr2++ = pix1; *ptr2++ = pix2; *ptr2++ = pix3; *ptr2++ = pix1; *ptr2++ = pix2; *ptr2++ = pix3; } srcptr += img->bpl - (img->width * 3); ptr += (dblimg->bpl << 1) - (dblimg->width * 3); ptr2 += (dblimg->bpl << 1) - (dblimg->width * 3); } } if (dblimg->bpp == 4) { register guint32 *srcptr, *ptr, *ptr2, pix; srcptr = (guint32 *) GDK_IMAGE_XIMAGE(img)->data; ptr = (guint32 *) GDK_IMAGE_XIMAGE(dblimg)->data; ptr2 = ptr + (dblimg->bpl >> 2); for (y = 0; y < img->height; y++) { for (x = 0; x < img->width; x++) { pix = *srcptr++; *ptr++ = pix; *ptr++ = pix; *ptr2++ = pix; *ptr2++ = pix; } srcptr += (img->bpl >> 2) - img->width; ptr += (dblimg->bpl >> 1) - dblimg->width; ptr2 += (dblimg->bpl >> 1) - dblimg->width; } } return dblimg;}static char *read_string(const char *filename, const char *section, const char *key, gboolean comment){ FILE *file; char *buffer, *ret_buffer = NULL; int found_section = 0, off = 0, len = 0; struct stat statbuf; if (!filename) return NULL; if ((file = fopen(filename, "r")) == NULL) return NULL; if (stat(filename, &statbuf) < 0) { fclose(file); return NULL; } buffer = g_malloc(statbuf.st_size); fread(buffer, 1, statbuf.st_size, file); while (!ret_buffer && off < statbuf.st_size) { while (off < statbuf.st_size && (buffer[off] == '\r' || buffer[off] == '\n' || buffer[off] == ' ' || buffer[off] == '\t')) off++; if (off >= statbuf.st_size) break; if (buffer[off] == '[') { int slen = strlen(section); off++; found_section = 0; if (off + slen + 1 < statbuf.st_size && !strncasecmp(section, &buffer[off], slen)) { off += slen; if (buffer[off] == ']') { off++; found_section = 1; } } } else if (found_section && off + strlen(key) < statbuf.st_size && !strncasecmp(key, &buffer[off], strlen(key))) { off += strlen(key); while (off < statbuf.st_size && (buffer[off] == ' ' || buffer[off] == '\t')) off++; if (off >= statbuf.st_size) break; if (buffer[off] == '=') { off++; while (off < statbuf.st_size && (buffer[off] == ' ' || buffer[off] == '\t')) off++; if (off >= statbuf.st_size) break; len = 0; while (off + len < statbuf.st_size && buffer[off + len] != '\r' && buffer[off + len] != '\n' && (!comment || buffer[off + len] != ';')) len++; ret_buffer = g_strndup(&buffer[off], len); off += len; } } while (off < statbuf.st_size && buffer[off] != '\r' && buffer[off] != '\n') off++; } g_free(buffer); fclose(file); return ret_buffer;}char *read_ini_string(const char *filename, const char *section, const char *key){ return read_string(filename, section, key, TRUE);}char *read_ini_string_no_comment(const char *filename, const char *section, const char *key){ return read_string(filename, section, key, FALSE);}GArray *string_to_garray(const gchar * str){ GArray *array; gint temp; const gchar *ptr = str; gchar *endptr; array = g_array_new(FALSE, TRUE, sizeof (gint)); for (;;) { temp = strtol(ptr, &endptr, 10); if (ptr == endptr) break; g_array_append_val(array, temp); ptr = endptr; while (!isdigit(*ptr) && (*ptr) != '\0') ptr++; if (*ptr == '\0') break; } return (array);}GArray *read_ini_array(const gchar * filename, const gchar * section, const gchar * key){ gchar *temp; GArray *a; if ((temp = read_ini_string(filename, section, key)) == NULL) return NULL; a = string_to_garray(temp); g_free(temp); return a;}void glist_movedown(GList * list){ gpointer temp; if (g_list_next(list)) { temp = list->data; list->data = list->next->data; list->next->data = temp; }}void glist_moveup(GList * list){ gpointer temp; if (g_list_previous(list)) { temp = list->data; list->data = list->prev->data; list->prev->data = temp; }}struct MenuPos{ gint x; gint y;};static void util_menu_position(GtkMenu *menu, gint *x, gint *y, gpointer data){ GtkRequisition requisition; gint screen_width; gint screen_height; struct MenuPos *pos = data; gtk_widget_size_request(GTK_WIDGET(menu), &requisition); screen_width = gdk_screen_width(); screen_height = gdk_screen_height(); *x = CLAMP(pos->x - 2, 0, MAX(0, screen_width - requisition.width)); *y = CLAMP(pos->y - 2, 0, MAX(0, screen_height - requisition.height));}static void util_menu_delete_popup_data(GtkObject *object, GtkItemFactory *ifactory){ gtk_signal_disconnect_by_func(object, GTK_SIGNAL_FUNC(util_menu_delete_popup_data), ifactory); gtk_object_remove_data_by_id(GTK_OBJECT(ifactory), quark_popup_data);}/* * util_item_factory_popup[_with_data]() is a replacement for * gtk_item_factory_popup[_with_data](). * * The difference is that the menu is always popped up whithin the * screen. This means it does not neccesarily pop up at (x,y). */void util_item_factory_popup_with_data(GtkItemFactory * ifactory, gpointer data, GtkDestroyNotify destroy, guint x, guint y, guint mouse_button, guint32 time){ static GQuark quark_user_menu_pos = 0; struct MenuPos *pos; if (!quark_user_menu_pos) quark_user_menu_pos = g_quark_from_static_string("user_menu_pos"); if (!quark_popup_data) quark_popup_data = g_quark_from_static_string("GtkItemFactory-popup-data"); pos = gtk_object_get_data_by_id(GTK_OBJECT(ifactory), quark_user_menu_pos); if (!pos) { pos = g_malloc0(sizeof (struct MenuPos)); gtk_object_set_data_by_id_full(GTK_OBJECT(ifactory->widget), quark_user_menu_pos, pos, g_free); } pos->x = x; pos->y = y; if (data != NULL) { gtk_object_set_data_by_id_full(GTK_OBJECT (ifactory), quark_popup_data, data, destroy);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -