pidgin/purple-plugin-pack

05708390e9b2
Fixed up the message splitter plugin to work and not depend on gdk...

Theres some hackery here though. On !win32, we depend on cairo, which should be alright anyways, however this needs to be tested on windows.

Also, this still needs a lot of cleanup, but it does work.
/*************************************************************************
* GTK Timezone widget module
* by Martijn van Oosterhout <kleptog@svana.org> (C) April 2006
* Licenced under the GNU General Public Licence version 2.
*
* This module creates the GTK widget used to select timezones. It's here to
* clearly seperate the GTK stuff from the plugin itself.
*************************************************************************/
#include <gtk/gtk.h>
#include <string.h>
#include <ctype.h>
#include "recurse.h"
#define DISABLED_STRING "<Disabled>"
#define DEFAULT_STRING "<Default>"
#define MORE_STRING "More..."
struct nodestate
{
GtkWidget *submenu;
gchar *string;
};
struct state
{
GtkWidget *base;
GtkWidget *extra;
int currdepth;
struct nodestate stack[4];
};
static inline const char *
menuitem_get_label(GtkMenuItem * menuitem)
{
return gtk_label_get_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(menuitem))));
}
static GtkMenuItem *
menu_get_first_menuitem(GtkWidget * menu)
{
GList *list = gtk_container_get_children(GTK_CONTAINER(menu));
GtkMenuItem *selection = GTK_MENU_ITEM(g_list_nth_data(list, 0));
g_list_free(list);
return selection;
}
static int
menu_select_cb(GtkMenuItem * menuitem, GtkWidget * menu)
{
const char *label = menuitem_get_label(menuitem);
if(label[0] == '<')
{
GtkWidget *selection;
gchar *selstring;
if(strcmp(label, DEFAULT_STRING) == 0)
selstring = "";
else if(strcmp(label, DISABLED_STRING) == 0)
selstring = "none";
selection = GTK_WIDGET(menu_get_first_menuitem(menu));
gtk_widget_hide(selection);
}
else
{
char *str = g_strdup(label);
GtkWidget *parent;
for (;;)
{
GtkMenuItem *parentitem;
const char *label2;
char *temp;
parent = gtk_widget_get_parent(GTK_WIDGET(menuitem));
if(menu == parent)
break;
parentitem = GTK_MENU_ITEM(gtk_menu_get_attach_widget(GTK_MENU(parent)));
label2 = menuitem_get_label(parentitem);
if(strcmp(label2, MORE_STRING) != 0)
{
temp = g_strconcat(label2, "/", str, NULL);
g_free(str);
str = temp;
}
menuitem = parentitem;
}
{
GtkLabel *label;
GtkMenuItem *selection = menu_get_first_menuitem(menu);
GtkOptionMenu *optionmenu = GTK_OPTION_MENU(gtk_menu_get_attach_widget(GTK_MENU(menu)));
label = GTK_LABEL(gtk_bin_get_child(GTK_BIN(selection)));
gtk_label_set_text(label, str);
gtk_widget_show(GTK_WIDGET(selection));
gtk_option_menu_set_history(optionmenu, 0);
printf("optionmenu=%p, menu=%p, menuitem=%p, label=%p\n", optionmenu, menu, selection,
label);
g_free(str);
}
}
return 0;
}
static int
make_menu_cb(char *path, struct state *state)
{
int i, j;
char **elements;
/* Here we ignore strings not beginning with uppercase, since they are auxilliary files, not timezones */
if(!isupper(path[0]))
return 0;
elements = g_strsplit(path, "/", 4);
for (i = 0; i < state->currdepth && state->stack[i].string; i++)
{
if(strcmp(elements[i], state->stack[i].string) != 0)
break;
}
/* i is now the index of the first non-matching element, so free the rest */
for (j = i; j < state->currdepth; j++)
g_free(state->stack[j].string);
state->currdepth = i;
while (elements[i])
{
GtkWidget *parent = (i == 0) ? state->base : state->stack[i - 1].submenu;
GtkWidget *menuitem;
if(i == 0 && elements[1] == NULL)
parent = state->extra;
menuitem = gtk_menu_item_new_with_label(elements[i]);
gtk_menu_append(parent, menuitem);
if(elements[i + 1] != NULL) /* Has submenu */
{
state->stack[i].submenu = gtk_menu_new();
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), state->stack[i].submenu);
state->currdepth++;
state->stack[i].string = g_strdup(elements[i]);
}
else
g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(menu_select_cb),
state->base);
i++;
}
g_strfreev(elements);
return 0;
}
void *
make_timezone_menu(const char *selected)
{
int i;
struct state state;
GtkWidget *menu;
GtkWidget *optionmenu, *menuitem, *selection;
if(selected == NULL)
selected = "";
menu = gtk_menu_new();
menuitem = gtk_menu_item_new_with_label(selected);
gtk_menu_append(menu, menuitem);
selection = menuitem;
menuitem = gtk_menu_item_new_with_label(DISABLED_STRING);
g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(menu_select_cb), menu);
gtk_menu_append(menu, menuitem);
menuitem = gtk_menu_item_new_with_label(DEFAULT_STRING);
g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(menu_select_cb), menu);
gtk_menu_append(menu, menuitem);
menuitem = gtk_menu_item_new_with_label(MORE_STRING);
gtk_menu_append(menu, menuitem);
state.base = menu;
state.extra = gtk_menu_new();
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), state.extra);
state.currdepth = 0;
recurse_directory("/usr/share/zoneinfo", (DirRecurseMatch) make_menu_cb, &state);
for (i = 0; i < state.currdepth; i++)
g_free(state.stack[i].string);
optionmenu = gtk_option_menu_new();
gtk_option_menu_set_menu(GTK_OPTION_MENU(optionmenu), menu);
gtk_widget_show_all(optionmenu);
if(strcmp(selected, "") == 0)
{
gtk_option_menu_set_history(GTK_OPTION_MENU(optionmenu), 2);
gtk_widget_hide(selection);
}
else if(strcmp(selected, "none") == 0)
{
gtk_option_menu_set_history(GTK_OPTION_MENU(optionmenu), 1);
gtk_widget_hide(selection);
}
else
{
gtk_option_menu_set_history(GTK_OPTION_MENU(optionmenu), 0);
}
return optionmenu;
}
const char *
get_timezone_menu_selection(void *widget)
{
GtkOptionMenu *menu = GTK_OPTION_MENU(widget);
int sel = gtk_option_menu_get_history(menu);
if(sel == 2) /* Default */
return NULL;
if(sel == 1) /* Disabled */
return "none";
GtkLabel *l = GTK_LABEL(gtk_bin_get_child(GTK_BIN(menu)));
return gtk_label_get_text(l);
}