dockapps/wmcliphist/wmcliphist.c
2018-06-24 07:46:57 -07:00

414 lines
11 KiB
C

/*
* (c) 2001 Michal Krause <michal@krause.cz>
*/
#include "wmcliphist.h"
#define WMCLIPHIST_VERSION "2.1"
/*
* print some help
*/
void
print_help()
{
begin_func("print_help");
fprintf(stderr, "Usage: wmcliphist [options]\n\n"
"wmcliphist is small dock applet for Window Maker which "
"keeps X clipboard history\n\n");
fprintf(stderr, "-h show this help\n"
"-v print version\n"
"-n <num> set number of items to keep (default 10)\n"
"-c color set color for locked items (default is red)\n"
"-s <size> choose wmcliphist icon size:\n"
" 0 = no icon\n"
" 16 = tiny 16x16 px icon\n"
" 30 = icon suitable for 32px dock/slit\n"
" 40 = icon suitable for 48px dock/slit\n"
" 60 = icon suitable for 64px dock/slit (default)\n");
fprintf(stderr, "-i <num> choose wmcliphist icon antialiasing:\n"
" 0 = for mid tones background (default)\n"
" 1 = for dark background\n"
" 2 = for light background\n");
fprintf(stderr, "-d dumps clipboard history to stdout"
" in pseudo XML format (no escaping etc.)\n");
fprintf(stderr, "-b <type> choose clipboard to manage\n"
" PRIMARY = select copies, middle click pastes (default)\n"
" SECONDARY = not used\n"
" CLIPBOARD = Ctrl+C copies, Ctrl+V pastes\n\n");
exit(1);
return_void();
}
static void
wmcliphist_exit(gint code)
{
begin_func("wmcliphist_exit");
gtk_main_quit();
exit(code);
return_void();
}
/*
* main func
*/
int
main(int argc, char **argv)
{
gint i = 1, res;
gchar *arg;
gchar *icon_file;
GList *list_node;
int icon_number = 0;
int icon_size = 60;
gboolean dump_only = FALSE;
XWMHints mywmhints;
GdkDisplay *display;
#ifdef FNCALL_DEBUG
debug_init_nothreads();
#endif
begin_func("main");
/* load configuration */
if ((res = rcconfig_get(rcconfig_get_name("rc"))) != 0) {
fprintf(stderr, "~/.wmcliphistrc parse error (%d)\n", res);
return_val(1);
}
/* parse command line */
while ((arg = argv[i])) {
if (*arg == '-') {
if (*(arg + 1) == 'h')
print_help();
else if (*(arg + 1) == 'n') {
i++;
if (!argv[i]) {
fprintf(stderr, "Missing value of -n\n");
print_help();
}
num_items_to_keep = atol(argv[i]);
} else if (*(arg + 1) == 'c') {
i++;
if (!argv[i]) {
fprintf(stderr, "Missing value of -c\n");
print_help();
}
memset(locked_color_str, 0, 32);
strncpy(locked_color_str, argv[i], 31);
} else if (*(arg + 1) == 'i') {
i++;
if (!argv[i]) {
fprintf(stderr, "Missing value of -i\n");
print_help();
}
icon_number = atoi(argv[i]);
if (icon_number < 0 || icon_number > 2) {
fprintf(stderr, "Invalid value of -i\n");
print_help();
}
} else if (*(arg + 1) == 's') {
i++;
if (!argv[i]) {
fprintf(stderr, "Missing value of -s\n");
print_help();
}
icon_size = atoi(argv[i]);
if (icon_size != 60 && icon_size != 40
&& icon_size != 30
&& icon_size != 16
&& icon_size != 0) {
fprintf(stderr, "Invalid value of -s\n");
print_help();
}
if (icon_size == 0) {
icon_size = 1;
}
} else if (*(arg + 1) == 'd') {
dump_only = TRUE;
} else if (*(arg + 1) == 'v') {
printf("wmcliphist "WMCLIPHIST_VERSION"\n");
exit(1);
} else if (*(arg + 1) == 'b') {
i++;
if (!argv[i]) {
fprintf(stderr, "Missing value of -b\n");
print_help();
}
memset(clipboard_str, 0, 32);
strncpy(clipboard_str, argv[i], 31);
} else {
fprintf(stderr, "Invalid option -%c\n", *(arg + 1));
print_help();
}
} else {
fprintf(stderr, "Invalid option %s\n", arg);
print_help();
}
i++;
}
signal(SIGCHLD, SIG_IGN);
/* initialize Gtk */
gtk_init(&argc, &argv);
/* create main window */
main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
/* set the window title */
gtk_window_set_title(GTK_WINDOW(main_window), "wmcliphist");
/* creat dock icon */
dock_app = main_window;
/* add event box to main window*/
event = gtk_event_box_new();
gtk_container_add(GTK_CONTAINER(dock_app), event);
/* set the default window size */
gtk_window_set_default_size(GTK_WINDOW(dock_app), icon_size, icon_size);
if (icon_size) {
/* create icon_mask */
if (icon_size == 60) {
/* 60x60 icon */
if (icon_number == 0) {
icon_file = "ico_60x60_gray.png";
} else if (icon_number == 1) {
icon_file = "ico_60x60_black.png";
} else {
icon_file = "ico_60x60_white.png";
}
} else if (icon_size == 40) {
/* 40x40 icon */
/* create icon */
if (icon_number == 0) {
icon_file = "ico_40x40_gray.png";
} else if (icon_number == 1) {
icon_file = "ico_40x40_black.png";
} else {
icon_file = "ico_40x40_white.png";
}
} else if (icon_size == 30) {
/* 30x30 icon */
/* create icon */
if (icon_number == 0) {
icon_file = "ico_30x30_gray.png";
} else if (icon_number == 1) {
icon_file = "ico_30x30_black.png";
} else {
icon_file = "ico_30x30_white.png";
}
} else {
/* 16x16 icon */
/* create icon */
icon_file = "ico_16x16.png";
}
icon_file = g_strconcat(DATADIR"/", icon_file, NULL);
pixmap = gtk_image_new_from_file(icon_file);
gtk_widget_show(pixmap);
gtk_container_add(GTK_CONTAINER(event), pixmap);
}
/* use only mouse events */
gtk_widget_add_events(dock_app, GDK_BUTTON_PRESS_MASK);
gtk_widget_show(dock_app);
gtk_widget_show_all(main_window);
/* transparenter Hintergrund für pixmap*/
if (icon_size) {
cairo_region_t *region;
cairo_surface_t *surface;
surface = cairo_image_surface_create_from_png(icon_file);
region = gdk_cairo_region_create_from_surface(surface);
gdk_window_shape_combine_region(gtk_widget_get_window(dock_app),
region, 0, 0);
}
/* set the window as a dockapp*/
display = gdk_display_get_default();
mywmhints.icon_window = GDK_WINDOW_XID(gtk_widget_get_window(main_window));
mywmhints.window_group = GDK_WINDOW_XID(gtk_widget_get_window(main_window));
mywmhints.icon_x = 0;
mywmhints.icon_y = 0;
mywmhints.flags = IconWindowHint | StateHint;
mywmhints.initial_state = WithdrawnState;
XSetWMHints(GDK_DISPLAY_XDISPLAY(display), GDK_WINDOW_XID(gtk_widget_get_window(main_window)), &mywmhints);
/* create clipboard history menu */
menu_hist = gtk_menu_new();
menu_title = gtk_menu_item_new();
gtk_menu_shell_append(GTK_MENU_SHELL(menu_hist), menu_title);
gtk_widget_show(menu_title);
gtk_widget_show(menu_hist);
/* create application menu */
menu_app = gtk_menu_new();
menu_app_clip_lock = gtk_check_menu_item_new_with_label("Clipboard lock");
gtk_menu_shell_append(GTK_MENU_SHELL(menu_app), menu_app_clip_lock);
menu_app_clip_ignore = gtk_check_menu_item_new_with_label("Clipboard ignore");
gtk_menu_shell_append(GTK_MENU_SHELL(menu_app), menu_app_clip_ignore);
menu_app_save = gtk_menu_item_new_with_label("Save history");
gtk_menu_shell_append(GTK_MENU_SHELL(menu_app), menu_app_save);
g_signal_connect(G_OBJECT(menu_app_save),
"activate",
G_CALLBACK(menu_app_item_click),
GINT_TO_POINTER(0));
menu_app_exit = gtk_menu_item_new_with_label("Exit");
gtk_menu_shell_append(GTK_MENU_SHELL(menu_app), menu_app_exit);
g_signal_connect(G_OBJECT(menu_app_exit),
"activate",
G_CALLBACK(menu_app_item_click),
GINT_TO_POINTER(1));
gtk_widget_show_all(menu_app);
list_node = action_list;
while (list_node) {
ACTION *action = list_node->data;
if (action->action == ACT_SUBMENU &&
strcmp(action->command, "-") != 0) {
action->menu_item = gtk_menu_item_new_with_label(
action->command);
gtk_menu_shell_append(GTK_MENU_SHELL(menu_hist),
action->menu_item);
action->submenu = gtk_menu_new();
gtk_menu_item_set_submenu(
GTK_MENU_ITEM(action->menu_item),
action->submenu);
menu_title = gtk_menu_item_new();
gtk_menu_shell_append(GTK_MENU_SHELL(action->submenu), menu_title);
gtk_widget_show(menu_title);
gtk_widget_show(action->menu_item);
gtk_widget_show(action->submenu);
submenu_count++;
}
if (action->action == ACT_SUBMENU &&
strcmp(action->command, "-") == 0) {
printf("'%s'\n", action->command);
action->submenu = menu_hist;
}
list_node = list_node->next;
}
if (submenu_count) {
GtkWidget *separator;
separator = gtk_menu_item_new();
gtk_widget_show(separator);
gtk_menu_shell_insert(GTK_MENU_SHELL(menu_hist), separator, 1);
}
/* prepare colors and styles */
if (gdk_rgba_parse(&locked_color, locked_color_str) == FALSE) {
char msg_str[128];
sprintf(msg_str, "Invalid color string: '%s'.\n"
"Falling back to default (red).",
locked_color_str);
show_message(msg_str, "Warning", "OK", NULL, NULL);
strcpy(locked_color_str, DEF_LOCKED_COLOR);
gdk_rgba_parse(&locked_color, locked_color_str);
}
/* set clipboard */
if (strcmp(clipboard_str, "PRIMARY") == 0) {
clipboard = GDK_SELECTION_PRIMARY;
} else if (strcmp(clipboard_str, "SECONDARY") == 0) {
clipboard = GDK_SELECTION_SECONDARY;
} else if (strcmp(clipboard_str, "CLIPBOARD") == 0) {
clipboard = GDK_SELECTION_CLIPBOARD;
} else {
char msg_str[128];
sprintf(msg_str, "Invalid clipboard string: '%s'.\n"
"Falling back to default ("
DEF_CLIPBOARD_STR
").",
clipboard_str);
show_message(msg_str, "Warning", "OK", NULL, NULL);
clipboard = DEF_CLIPBOARD;
}
/* load previously saved history */
if (history_load(dump_only) != 0) {
if (errno == E_TOO_MUCH) {
if (show_message("Number of items to keep (-n switch or "
"keep directive in ~/.wmcliphistrc)\n"
"is lower than actual number of items "
"in history file.\nSome items from "
"history will be lost. May I continue?",
"Warning", "Yes", "No", NULL) == 1) {
rcconfig_free();
exit(1);
}
} else if (errno != E_OPEN) {
rcconfig_free();
fprintf(stderr, "cannot load history (%d)\n", errno);
exit(1);
}
}
if (dump_only) {
rcconfig_free();
exit(1);
}
/* run clipboard monitor */
g_signal_connect(G_OBJECT(main_window),
"selection_received",
G_CALLBACK(my_get_xselection),
NULL);
g_timeout_add(250, time_conv_select, NULL);
/* run autosave timer */
if (autosave_period > 0)
g_timeout_add(autosave_period * 1000, history_autosave, NULL);
/* setup everything for supplying selection to other apps */
gtk_selection_add_target(dock_app,
clipboard,
GDK_SELECTION_TYPE_STRING,
1);
g_signal_connect(G_OBJECT(dock_app),
"selection_get",
G_CALLBACK(selection_handle),
NULL);
/* connect signal for menu popup */
g_signal_connect(G_OBJECT(dock_app),
"event",
G_CALLBACK(button_press),
NULL);
g_signal_connect(G_OBJECT(dock_app),
"destroy",
G_CALLBACK(wmcliphist_exit),
NULL);
hotkeys_init();
gtk_main();
return_val(0);
}