⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ui_tabcomp.c

📁 Gqview,Linux下基于GTK+库写成的轻量级而能丰富的图像浏览程序。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * (SLIK) SimpLIstic sKin functions * (C) 2004 John Ellis * * Author: John Ellis * * This software is released under the GNU General Public License (GNU GPL). * Please read the included file COPYING for more information. * This software comes with no warranty of any kind, use at your own risk! */#ifdef HAVE_CONFIG_H#  include "config.h"#endif#include "intl.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <dirent.h>#include <gdk/gdk.h>#include <gtk/gtk.h>#include <gdk-pixbuf/gdk-pixbuf.h>#include "ui_tabcomp.h"#include "ui_bookmark.h"#include "ui_fileops.h"#include "ui_spinner.h"#include "ui_utildlg.h"#include <gdk/gdkkeysyms.h> /* for key values *//* define this to enable a pop-up menu that shows possible matches * #define TAB_COMPLETION_ENABLE_POPUP_MENU */#define TAB_COMPLETION_ENABLE_POPUP_MENU 1#define TAB_COMP_POPUP_MAX 500#ifdef TAB_COMPLETION_ENABLE_POPUP_MENU#include "ui_menu.h"#endif/* ----------------------------------------------------------------   Tab completion routines, can be connected to any gtkentry widget   using the tab_completion_add_to_entry() function.   Use remove_trailing_slash() to strip the trailing '/'.   ----------------------------------------------------------------*/typedef struct _TabCompData TabCompData;struct _TabCompData{	GtkWidget *entry;	gchar *dir_path;	GList *file_list;	void (*enter_func)(const gchar *, gpointer);	void (*tab_func)(const gchar *, gpointer);	gpointer enter_data;	gpointer tab_data;	GtkWidget *combo;	gint has_history;	gchar *history_key;	gint history_levels;	FileDialog *fd;	gchar *fd_title;	gint fd_folders_only;	GtkWidget *fd_button;};static void tab_completion_select_show(TabCompData *td);static void tab_completion_free_list(TabCompData *td){	GList *list;	g_free(td->dir_path);	td->dir_path = NULL;	list = td->file_list;	while(list)		{		g_free(list->data);		list = list->next;		}	g_list_free(td->file_list);	td->file_list = NULL;}static void tab_completion_read_dir(TabCompData *td, const gchar *path){        DIR *dp;        struct dirent *dir;        GList *list = NULL;	gchar *pathl;	tab_completion_free_list(td);	pathl = path_from_utf8(path);        dp = opendir(pathl);	g_free(pathl);	if (!dp)                {                /* dir not found */                return;                }        while ((dir = readdir(dp)) != NULL)                {                /* skips removed files */                if (dir->d_ino > 0)                        {			gchar *name = dir->d_name;			if (strcmp(name, ".") != 0 && strcmp(name, "..") != 0)				{				list = g_list_prepend(list, path_to_utf8(name));				}                        }		}        closedir(dp);	td->dir_path = g_strdup(path);	td->file_list = list;}static void tab_completion_destroy(GtkWidget *widget, gpointer data){	TabCompData *td = data;	tab_completion_free_list(td);	g_free(td->history_key);	if (td->fd) file_dialog_close(td->fd);	g_free(td->fd_title);	g_free(td);}static gint tab_completion_emit_enter_signal(TabCompData *td){	gchar *text;	if (!td->enter_func) return FALSE;	text = g_strdup(gtk_entry_get_text(GTK_ENTRY(td->entry)));	if (text[0] == '~')		{		gchar *t = text;		text = g_strconcat(homedir(), t + 1, NULL);		g_free(t);		}	td->enter_func(text, td->enter_data);	g_free(text);	return TRUE;}static void tab_completion_emit_tab_signal(TabCompData *td){	gchar *text;	if (!td->tab_func) return;	text = g_strdup(gtk_entry_get_text(GTK_ENTRY(td->entry)));	if (text[0] == '~')		{		gchar *t = text;		text = g_strconcat(homedir(), t + 1, NULL);		g_free(t);		}	td->tab_func(text, td->tab_data);	g_free(text);}#ifdef TAB_COMPLETION_ENABLE_POPUP_MENUstatic gint tab_completion_popup_key_press(GtkWidget *widget, GdkEventKey *event, gpointer data){	TabCompData *td = data;	if (event->keyval == GDK_Tab ||	    event->keyval == GDK_BackSpace ||	    (event->keyval >= 0x20 && event->keyval <= 0xFF) )		{		if (event->keyval >= 0x20 && event->keyval <= 0xFF)			{			gchar buf[2];			gint p = -1;			buf[0] = event->keyval;			buf[1] = '\0';			gtk_editable_insert_text(GTK_EDITABLE(td->entry), buf, 1, &p);			gtk_editable_set_position(GTK_EDITABLE(td->entry), -1);			}		/*close the menu */		gtk_menu_popdown(GTK_MENU(widget));		/* doing this does not emit the "selection done" signal, unref it ourselves */		gtk_widget_unref(widget);					return TRUE;		}	return FALSE;}static void tab_completion_popup_cb(GtkWidget *widget, gpointer data){	gchar *name = data;	TabCompData *td;	gchar *buf;	gchar *ptr;	td = g_object_get_data(G_OBJECT(widget), "tab_completion_data");	if (!td) return;	ptr = td->dir_path + strlen(td->dir_path) - 1;	buf = g_strconcat(td->dir_path, (ptr[0] == '/') ? "" : "/", name, NULL);	gtk_entry_set_text(GTK_ENTRY(td->entry), buf);	gtk_editable_set_position(GTK_EDITABLE(td->entry), strlen(buf));	g_free(buf);	tab_completion_emit_tab_signal(td);}static void tab_completion_popup_pos_cb(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data){	TabCompData *td = data;	gint height;	PangoLayout *layout;	PangoRectangle strong_pos, weak_pos;	gint length;	gint xoffset, yoffset;	GtkRequisition req;	GdkScreen *screen;	gint monitor_num;	GdkRectangle monitor;	gdk_window_get_origin(td->entry->window, x, y);	screen = gtk_widget_get_screen(GTK_WIDGET(menu));	monitor_num = gdk_screen_get_monitor_at_window(screen, td->entry->window);	gdk_screen_get_monitor_geometry(screen, monitor_num, &monitor);	gtk_widget_size_request(GTK_WIDGET(menu), &req);	length = strlen(gtk_entry_get_text(GTK_ENTRY(td->entry)));	gtk_entry_get_layout_offsets(GTK_ENTRY(td->entry), &xoffset, &yoffset);	layout = gtk_entry_get_layout(GTK_ENTRY(td->entry));	pango_layout_get_cursor_pos(layout, length, &strong_pos, &weak_pos);	*x += strong_pos.x / PANGO_SCALE + xoffset;	height = MIN(td->entry->requisition.height, td->entry->allocation.height);	if (req.height > monitor.y + monitor.height - *y - height &&	    *y - monitor.y >  monitor.y + monitor.height - *y)		{		height = MIN(*y - monitor.y, req.height);		gtk_widget_set_size_request(GTK_WIDGET(menu), -1, height);		*y -= height;		}	else		{		*y += height;		}}static void tab_completion_popup_list(TabCompData *td, GList *list){	GtkWidget *menu;	GList *work;	GdkEvent *event;	guint32 etime;	gint ebutton;	gint count = 0;	if (!list) return;#if 0	/*	 * well, the menu would be too long anyway...	 * (listing /dev causes gtk+ window allocation errors, -> too big a window)	 * this is why menu popups are disabled, this really should be a popup scrollable listview.	 */	if (g_list_length(list) > 200) return;#endif	menu = popup_menu_short_lived();	work = list;	while (work && count < TAB_COMP_POPUP_MAX)		{		gchar *name = work->data;		GtkWidget *item;		item = menu_item_add_simple(menu, name, G_CALLBACK(tab_completion_popup_cb), name);		g_object_set_data(G_OBJECT(item), "tab_completion_data", td);		work = work->next;		count++;		}	g_signal_connect(G_OBJECT(menu), "key_press_event",			 G_CALLBACK(tab_completion_popup_key_press), td);	/* peek at the current event to get the time, etc. */	event = gtk_get_current_event();	if (event && event->type == GDK_BUTTON_RELEASE)		{		ebutton = event->button.button;		}	else		{		ebutton = 0;		}	if (event)		{		etime = gdk_event_get_time(event);		gdk_event_free(event);		}	else		{		etime = 0;		}	gtk_menu_popup(GTK_MENU(menu), NULL, NULL,		       tab_completion_popup_pos_cb, td, ebutton, etime);}#ifndef CASE_SORT#define CASE_SORT strcmp#endifstatic gint simple_sort(gconstpointer a, gconstpointer b){        return CASE_SORT((gchar *)a, (gchar *)b);}#endifstatic gint tab_completion_do(TabCompData *td){	const gchar *entry_text = gtk_entry_get_text(GTK_ENTRY(td->entry));	const gchar *entry_file;	gchar *entry_dir;	gchar *ptr;	gint home_exp = FALSE;	/* home dir expansion */	if (entry_text[0] == '~')		{		entry_dir = g_strconcat(homedir(), entry_text + 1, NULL);		home_exp = TRUE;		}	else		{		entry_dir = g_strdup(entry_text);		}	entry_file = filename_from_path(entry_text);	if (isfile(entry_dir))		{		if (home_exp)			{			gtk_entry_set_text(GTK_ENTRY(td->entry), entry_dir);			gtk_editable_set_position(GTK_EDITABLE(td->entry), strlen(entry_dir));			}		g_free(entry_dir);		return home_exp;		}	if (isdir(entry_dir) && strcmp(entry_file, ".") != 0 && strcmp(entry_file, "..") != 0)		{		ptr = entry_dir + strlen(entry_dir) - 1;		if (ptr[0] == '/')			{			if (home_exp)				{				gtk_entry_set_text(GTK_ENTRY(td->entry), entry_dir);				gtk_editable_set_position(GTK_EDITABLE(td->entry), strlen(entry_dir));				}			tab_completion_read_dir(td, entry_dir);			td->file_list = g_list_sort(td->file_list, simple_sort);			if (td->file_list && !td->file_list->next)				{				gchar *buf;				const gchar *file;				file = td->file_list->data;				buf = g_strconcat(entry_dir, file, NULL);				if (isdir(buf))					{					g_free(buf);					buf = g_strconcat(entry_dir, file, "/", NULL);					}				gtk_entry_set_text(GTK_ENTRY(td->entry), buf);				gtk_editable_set_position(GTK_EDITABLE(td->entry), strlen(buf));				g_free(buf);				}#ifdef TAB_COMPLETION_ENABLE_POPUP_MENU			else				{				tab_completion_popup_list(td, td->file_list);				}#endif			g_free(entry_dir);			return home_exp;			}		else			{			gchar *buf = g_strconcat(entry_dir, "/", NULL);			gtk_entry_set_text(GTK_ENTRY(td->entry), buf);			gtk_editable_set_position(GTK_EDITABLE(td->entry), strlen(buf));			g_free(buf);			g_free(entry_dir);			return TRUE;			}		}	ptr = (gchar *)filename_from_path(entry_dir);	if (ptr > entry_dir) ptr--;	ptr[0] = '\0';	if (strlen(entry_dir) == 0)		{		g_free(entry_dir);		entry_dir = g_strdup("/");		}	if (isdir(entry_dir))		{		GList *list;		GList *poss = NULL;		gint l = strlen(entry_file);		if (!td->dir_path || !td->file_list || strcmp(td->dir_path, entry_dir) != 0)			{			tab_completion_read_dir(td, entry_dir);			}		if (strcmp(entry_dir, "/") == 0) entry_dir[0] = '\0';		list = td->file_list;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -