Mercurial > pidgin.yaz
changeset 18407:b618770c34b1
propagate from branch 'im.pidgin.soc.2007.remotelogging' (head 64d3e6a75d2827d3c93ac39eb27408b26dc735ea)
to branch 'im.pidgin.pidgin' (head 2718e6de1b8eadac86bb0e75f1eb46df683d7919)
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Sun, 01 Jul 2007 15:44:59 +0000 |
parents | 29e48078a899 (diff) e7546fb1c1a3 (current diff) |
children | 49173b32df0d |
files | |
diffstat | 37 files changed, 560 insertions(+), 149 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Sun Jul 01 08:02:31 2007 +0000 +++ b/ChangeLog Sun Jul 01 15:44:59 2007 +0000 @@ -11,6 +11,7 @@ notifications in chats * With the HTML logger, images in conversations are now saved. NOTE: Saved images are not yet displayed when loading logs. + * Added support for QIP logs to the Log Reader plugin (Michael Shkutkov) Pidgin: * Ensure only one copy of Pidgin is running with a given configuration @@ -18,6 +19,13 @@ second time will raise the buddy list. (Gabriel Schulhof) * Undo capability in the conversation window + Finch: + * There's support for workspaces now (details in the manpage) + * There's a new custom window manager, Irssi + * Some improvements for tab-completion, tooltip and the password entries + * Some bugs regarding search results fixed + * A new DBus-script to create a docklet for finch + version 2.0.2 (06/14/2007): Pidgin: * Added a custom conversation font option to preferences
--- a/ChangeLog.API Sun Jul 01 08:02:31 2007 +0000 +++ b/ChangeLog.API Sun Jul 01 15:44:59 2007 +0000 @@ -73,6 +73,7 @@ * pidgin_menu_position_func_helper * pidgin_blist_get_name_markup, returns the buddy list markup text for a given buddy. + * pidgin_themes_remove_smiley_theme Changed: * pidgin_append_menu_action returns the menuitem added to the menu. @@ -88,10 +89,28 @@ Added: * finch_retrieve_user_info - Changed: - * gnt_tree_get_rows() now returns a GList* instead of a const - GList*, as const is not very useful with GLists. The - returned value still must not be modified or freed. + libgnt: + Added: + * GntWS for workspaces + * gnt_tree_set_column_title + * GntSlider widget + * "completion" signal for GntEntry + * "terminal-refresh" signal for GntWM, with a corresponding entry + in GntWMClass + * New flags for GntTextView to decide whether to word-wrap or show + scrollbars (GntTextViewFlag) which can be set by + gnt_text_view_set_flag + * gnt_style_get_from_name + * gnt_window_present + * gnt_tree_set_column_width_ratio + * gnt_tree_set_column_resizable + + Changed: + * gnt_tree_get_rows() now returns a GList* instead of a const + GList*, as const is not very useful with GLists. The + returned value still must not be modified or freed. + * Instead of keeping an 'invisible' item, the GntTreeColumns now + maintain 'flags' with the appropriate flags set version 2.0.2 (6/14/2007): Pidgin:
--- a/doc/finch.1.in Sun Jul 01 08:02:31 2007 +0000 +++ b/doc/finch.1.in Sun Jul 01 15:44:59 2007 +0000 @@ -110,14 +110,26 @@ Bring up the menu (if there is one) for a window. Note that currently only the buddylist has a menu. .TP -.B Alt \+ Shift \+ . +.B Alt \+ / +Show a list of available key-bindings for the current widget in focus. +.TP +.B Alt \+ \> Switch to the next workspace .TP -.B Alt \+ Shift \+ , +.B Alt \+ \< Switch to the previous workspace .TP +.B Alt \+ t +Tag (or untag) the current window +.TP +.B Alt \+ T +Attached all the tag windows to the current workspace +.TP .B Alt \+ s Show the workspace list +.TP +.B F9 +Create a new workspace and switch to it .SH FILES \fI~/.gntrc\fR: configuration file for gnt applications. @@ -135,7 +147,9 @@ .br # To use some custom window-manager .br -wm = /usr/local/lib/purple/s.so +wm = /usr/local/lib/gnt/s.so +.br +# There's also a custom window manager called irssi.so .br # Remember window-positions based on the titles (on by default) .br @@ -308,6 +322,8 @@ .br pagedown = page-down .br +backspace = move-parent +.br # Following is the default binding for the context-menu .br menu = context-menu @@ -377,6 +393,16 @@ .br a-l = refresh-screen .br +a-s = workspace-list +.br +a-t = window-tag +.br +a-T = place-tagged +.br +a-C = toggle-clipboard +.br +a-/ = help-for-widget +.br # The following action is still incomplete, and doesn't have a default binding .br # switch-window-n @@ -387,8 +413,18 @@ [GntS::binding] .br a-b = toggle-buddylist + +# For the irssi window manager .br -a-C = toggle-clipboard +[Irssi::binding] +.br +a-L = move-right +.br +a-H = move-left +.br +a-J = move-down +.br +a-K = move-up .SH Conversation Commands There are a few helpful commands in addition to the regular commands. You can
--- a/finch/gntconv.c Sun Jul 01 08:02:31 2007 +0000 +++ b/finch/gntconv.c Sun Jul 01 15:44:59 2007 +0000 @@ -140,13 +140,6 @@ break; } g_free(error); -#if 0 - gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(ggconv->tv), - _("Commands are not supported yet. Message was NOT sent."), - GNT_TEXT_FLAG_DIM | GNT_TEXT_FLAG_UNDERLINE); - gnt_text_view_next_line(GNT_TEXT_VIEW(ggconv->tv)); - gnt_text_view_scroll(GNT_TEXT_VIEW(ggconv->tv), 0); -#endif } else { @@ -451,6 +444,13 @@ } static void +completion_cb(GntEntry *entry, const char *start, const char *end) +{ + if (start == entry->start) + gnt_widget_key_pressed(GNT_WIDGET(entry), ": "); +} + +static void finch_create_conversation(PurpleConversation *conv) { FinchConv *ggc = conv->ui_data; @@ -542,6 +542,7 @@ gnt_text_view_attach_scroll_widget(GNT_TEXT_VIEW(ggc->tv), ggc->entry); g_signal_connect_after(G_OBJECT(ggc->entry), "key_pressed", G_CALLBACK(entry_key_pressed), ggc); + g_signal_connect(G_OBJECT(ggc->entry), "completion", G_CALLBACK(completion_cb), NULL); g_signal_connect(G_OBJECT(ggc->window), "destroy", G_CALLBACK(closing_window), ggc); gnt_widget_set_position(ggc->window, purple_prefs_get_int(PREF_ROOT "/position/x"),
--- a/finch/gntft.c Sun Jul 01 08:02:31 2007 +0000 +++ b/finch/gntft.c Sun Jul 01 15:44:59 2007 +0000 @@ -178,6 +178,7 @@ GntWidget *button; GntWidget *checkbox; GntWidget *tree; + int widths[] = {8, 12, 8, 8, 8, 8, -1}; if (!xfer_dialog) xfer_dialog = g_new0(PurpleGntXferDialog, 1); @@ -195,12 +196,12 @@ xfer_dialog->tree = tree = gnt_tree_new_with_columns(NUM_COLUMNS); gnt_tree_set_column_titles(GNT_TREE(tree), _("Progress"), _("Filename"), _("Size"), _("Speed"), _("Remaining"), _("Status")); - gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_PROGRESS, 8); - gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_FILENAME, 8); - gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_SIZE, 10); - gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_SPEED, 10); - gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_REMAINING, 10); - gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_STATUS, 10); + gnt_tree_set_column_width_ratio(GNT_TREE(tree), widths); + gnt_tree_set_column_resizable(GNT_TREE(tree), COLUMN_PROGRESS, FALSE); + gnt_tree_set_column_resizable(GNT_TREE(tree), COLUMN_SIZE, FALSE); + gnt_tree_set_column_resizable(GNT_TREE(tree), COLUMN_SPEED, FALSE); + gnt_tree_set_column_resizable(GNT_TREE(tree), COLUMN_REMAINING, FALSE); + gnt_widget_set_size(tree, 70, -1); gnt_tree_set_show_title(GNT_TREE(tree), TRUE); gnt_box_add_widget(GNT_BOX(window), tree);
--- a/finch/gntstatus.c Sun Jul 01 08:02:31 2007 +0000 +++ b/finch/gntstatus.c Sun Jul 01 15:44:59 2007 +0000 @@ -163,6 +163,7 @@ void finch_savedstatus_show_all() { GntWidget *window, *tree, *box, *button; + int widths[] = {25, 12, 35}; if (statuses.window) { gnt_window_present(statuses.window); return; @@ -179,9 +180,8 @@ statuses.tree = tree = gnt_tree_new_with_columns(3); gnt_tree_set_column_titles(GNT_TREE(tree), _("Title"), _("Type"), _("Message")); gnt_tree_set_show_title(GNT_TREE(tree), TRUE); - gnt_tree_set_col_width(GNT_TREE(tree), 0, 25); - gnt_tree_set_col_width(GNT_TREE(tree), 1, 12); - gnt_tree_set_col_width(GNT_TREE(tree), 2, 35); + gnt_tree_set_column_width_ratio(GNT_TREE(tree), widths); + gnt_widget_set_size(tree, 72, 0); gnt_box_add_widget(GNT_BOX(window), tree); populate_statuses(GNT_TREE(tree));
--- a/finch/libgnt/gntentry.c Sun Jul 01 08:02:31 2007 +0000 +++ b/finch/libgnt/gntentry.c Sun Jul 01 15:44:59 2007 +0000 @@ -25,6 +25,7 @@ #include "gntbox.h" #include "gntentry.h" +#include "gntmarshal.h" #include "gntstyle.h" #include "gnttree.h" #include "gntutils.h" @@ -32,6 +33,7 @@ enum { SIG_TEXT_CHANGED, + SIG_COMPLETION, SIGS, }; static guint signals[SIGS] = { 0 }; @@ -69,9 +71,12 @@ complete_suggest(GntEntry *entry, const char *text) { gboolean changed = FALSE; + int offstart = 0, offend = 0; + if (entry->word) { char *s = get_beginning_of_word(entry); const char *iter = text; + offstart = g_utf8_pointer_to_offset(entry->start, s); while (*iter && toupper(*s) == toupper(*iter)) { if (*s != *iter) changed = TRUE; @@ -81,10 +86,17 @@ gnt_entry_key_pressed(GNT_WIDGET(entry), iter); changed = TRUE; } + offend = g_utf8_pointer_to_offset(entry->start, entry->cursor); } else { + offstart = 0; gnt_entry_set_text_internal(entry, text); changed = TRUE; + offend = g_utf8_strlen(text, -1); } + + if (changed) + g_signal_emit(G_OBJECT(entry), signals[SIG_COMPLETION], 0, + entry->start + offstart, entry->start + offend); return changed; } @@ -687,6 +699,14 @@ g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + signals[SIG_COMPLETION] = + g_signal_new("completion", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + gnt_closure_marshal_VOID__POINTER_POINTER, + G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER); + gnt_bindable_class_register_action(bindable, "cursor-home", move_start, GNT_KEY_CTRL_A, NULL); gnt_bindable_register_binding(bindable, "cursor-home", GNT_KEY_HOME, NULL);
--- a/finch/libgnt/gntmenu.c Sun Jul 01 08:02:31 2007 +0000 +++ b/finch/libgnt/gntmenu.c Sun Jul 01 15:44:59 2007 +0000 @@ -329,6 +329,7 @@ GNT_TREE(widget)->show_separator = FALSE; _gnt_tree_init_internals(GNT_TREE(widget), 2); gnt_tree_set_col_width(GNT_TREE(widget), 1, 1); /* The second column is to indicate that it has a submenu */ + gnt_tree_set_column_resizable(GNT_TREE(widget), 1, FALSE); GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_NO_BORDER); }
--- a/finch/libgnt/gnttree.c Sun Jul 01 08:02:31 2007 +0000 +++ b/finch/libgnt/gnttree.c Sun Jul 01 15:44:59 2007 +0000 @@ -31,6 +31,8 @@ #define SEARCH_TIMEOUT 4000 /* 4 secs */ #define SEARCHING(tree) (tree->search && tree->search->len > 0) +#define COLUMN_INVISIBLE(tree, index) (tree->columns[index].flags & GNT_TREE_COLUMN_INVISIBLE) + enum { SIG_SELECTION_CHANGED, @@ -75,6 +77,36 @@ static GntWidgetClass *parent_class = NULL; static guint signals[SIGS] = { 0 }; +static void +readjust_columns(GntTree *tree) +{ + int i, col, total; + int width; +#define WIDTH(i) (tree->columns[i].width_ratio ? tree->columns[i].width_ratio : tree->columns[i].width) + gnt_widget_get_size(GNT_WIDGET(tree), &width, NULL); + for (i = 0, total = 0; i < tree->ncol ; i++) { + if (tree->columns[i].flags & GNT_TREE_COLUMN_INVISIBLE) + continue; + if (tree->columns[i].flags & GNT_TREE_COLUMN_FIXED_SIZE) + width -= WIDTH(i); + else + total += WIDTH(i); + } + + if (total == 0) + return; + + for (i = 0; i < tree->ncol; i++) { + if (tree->columns[i].flags & GNT_TREE_COLUMN_INVISIBLE) + continue; + if (tree->columns[i].flags & GNT_TREE_COLUMN_FIXED_SIZE) + col = WIDTH(i); + else + col = (WIDTH(i) * width) / total; + gnt_tree_set_col_width(GNT_TREE(tree), i, col); + } +} + /* Move the item at position old to position new */ static GList * g_list_reposition_child(GList *list, int old, int new) @@ -249,7 +281,7 @@ gboolean notfirst = FALSE; int lastvisible = tree->ncol; - while (lastvisible && tree->columns[lastvisible].invisible) + while (lastvisible && COLUMN_INVISIBLE(tree, lastvisible)) lastvisible--; for (i = 0, iter = row->columns; i < tree->ncol && iter; i++, iter = iter->next) @@ -261,7 +293,7 @@ gboolean cut = FALSE; int width; - if (tree->columns[i].invisible) + if (COLUMN_INVISIBLE(tree, i)) continue; if (i == lastvisible) @@ -335,11 +367,11 @@ for (i = 0; i < tree->ncol - 1; i++) { - if (!tree->columns[i].invisible) { + if (!COLUMN_INVISIBLE(tree, i)) { notfirst = TRUE; NEXT_X; } - if (!tree->columns[i+1].invisible && notfirst) + if (!COLUMN_INVISIBLE(tree, i+1) && notfirst) mvwaddch(widget->window, y, x, type); } } @@ -383,7 +415,7 @@ for (i = 0; i < tree->ncol; i++) { - if (tree->columns[i].invisible) { + if (COLUMN_INVISIBLE(tree, i)) { continue; } mvwaddstr(widget->window, pos, x + 1, tree->columns[i].title); @@ -555,7 +587,7 @@ GntTree *tree = GNT_TREE(widget); int i, width = 0; for (i = 0; i < tree->ncol; i++) - if (!tree->columns[i].invisible) + if (!COLUMN_INVISIBLE(tree, i)) width += tree->columns[i].width + 1; widget->priv.width = width; } @@ -829,16 +861,10 @@ gnt_tree_size_changed(GntWidget *widget, int w, int h) { GntTree *tree = GNT_TREE(widget); - int i; - int n = 0; if (widget->priv.width <= 0) return; - for (i = 0; i < tree->ncol; ++i) - n += tree->columns[i].width; - if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER)) - tree->columns[tree->ncol - 1].width += widget->priv.width - n - 1 * tree->ncol; - else - tree->columns[tree->ncol - 1].width += widget->priv.width - n - 2 - 1 * tree->ncol; + + readjust_columns(tree); } static gboolean @@ -1524,6 +1550,8 @@ g_return_if_fail(col < tree->ncol); tree->columns[col].width = width; + if (tree->columns[col].width_ratio == 0) + tree->columns[col].width_ratio = width; } void gnt_tree_set_column_title(GntTree *tree, int index, const char *title) @@ -1598,7 +1626,7 @@ twidth = 1 + 2 * (!GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_NO_BORDER)); for (i = 0; i < tree->ncol; i++) { gnt_tree_set_col_width(tree, i, widths[i]); - if (!tree->columns[i].invisible) + if (!COLUMN_INVISIBLE(tree, i)) twidth += widths[i] + (tree->show_separator ? 1 : 0) + 1; } g_free(widths); @@ -1613,9 +1641,32 @@ tree->hash = g_hash_table_new_full(hash, eq, kd, free_tree_row); } +static void +set_column_flag(GntTree *tree, int col, GntTreeColumnFlag flag, gboolean set) +{ + if (set) + tree->columns[col].flags |= flag; + else + tree->columns[col].flags &= ~flag; +} + void gnt_tree_set_column_visible(GntTree *tree, int col, gboolean vis) { g_return_if_fail(col < tree->ncol); - tree->columns[col].invisible = !vis; + set_column_flag(tree, col, GNT_TREE_COLUMN_INVISIBLE, !vis); +} + +void gnt_tree_set_column_resizable(GntTree *tree, int col, gboolean res) +{ + g_return_if_fail(col < tree->ncol); + set_column_flag(tree, col, GNT_TREE_COLUMN_FIXED_SIZE, !res); } +void gnt_tree_set_column_width_ratio(GntTree *tree, int cols[]) +{ + int i; + for (i = 0; i < tree->ncol && cols[i]; i++) { + tree->columns[i].width_ratio = cols[i]; + } +} +
--- a/finch/libgnt/gnttree.h Sun Jul 01 08:02:31 2007 +0000 +++ b/finch/libgnt/gnttree.h Sun Jul 01 15:44:59 2007 +0000 @@ -40,10 +40,6 @@ #define GNT_IS_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_TREE)) #define GNT_TREE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_TREE, GntTreeClass)) -#define GNT_TREE_FLAGS(obj) (GNT_TREE(obj)->priv.flags) -#define GNT_TREE_SET_FLAGS(obj, flags) (GNT_TREE_FLAGS(obj) |= flags) -#define GNT_TREE_UNSET_FLAGS(obj, flags) (GNT_TREE_FLAGS(obj) &= ~(flags)) - typedef struct _GntTree GntTree; typedef struct _GntTreePriv GntTreePriv; typedef struct _GntTreeClass GntTreeClass; @@ -51,6 +47,11 @@ typedef struct _GntTreeRow GntTreeRow; typedef struct _GntTreeCol GntTreeCol; +typedef enum { + GNT_TREE_COLUMN_INVISIBLE = 1 << 0, + GNT_TREE_COLUMN_FIXED_SIZE = 1 << 1, +} GntTreeColumnFlag; + struct _GntTree { GntWidget parent; @@ -74,7 +75,8 @@ { int width; char *title; - gboolean invisible; + int width_ratio; + GntTreeColumnFlag flags; } *columns; /* Would a GList be better? */ gboolean show_title; gboolean show_separator; /* Whether to show column separators */ @@ -368,16 +370,39 @@ */ void gnt_tree_set_hash_fns(GntTree *tree, gpointer hash, gpointer eq, gpointer kd); -/* This can be useful when, for example, we want to store some data - * which we don't want/need to display. */ /** + * Set whether a column is visible or not. + * This can be useful when, for example, we want to store some data + * which we don't want/need to display. * - * @param tree - * @param col - * @param vis + * @param tree The tree + * @param col The index of the column + * @param vis If @c FALSE, the column will not be displayed */ void gnt_tree_set_column_visible(GntTree *tree, int col, gboolean vis); +/** + * Set whether a column can be resized to keep the same ratio when the + * tree is resized. + * + * @param tree The tree + * @param col The index of the column + * @param res If @c FALSE, the column will not be resized when the + * tree is resized + */ +void gnt_tree_set_column_resizable(GntTree *tree, int col, gboolean res); + +/** + * Set column widths to use when calculating column widths after a tree + * is resized. + * + * @param tree The tree + * @param cols Array of widths. The width must have the same number + * of entries as the number of columns in the tree, or + * end with a negative value for a column-width. + */ +void gnt_tree_set_column_width_ratio(GntTree *tree, int cols[]); + G_END_DECLS /* The following functions should NOT be used by applications. */
--- a/finch/libgnt/wms/irssi.c Sun Jul 01 08:02:31 2007 +0000 +++ b/finch/libgnt/wms/irssi.c Sun Jul 01 15:44:59 2007 +0000 @@ -126,7 +126,7 @@ int x, y, w, h; name = gnt_widget_get_name(win); - if (!name || strcmp(name, "conversation-window")) { + if (!name || !strstr(name, "conversation-window")) { if (!GNT_IS_MENU(win) && !GNT_WIDGET_IS_FLAG_SET(win, GNT_WIDGET_TRANSIENT)) { if ((!name || strcmp(name, "buddylist"))) { gnt_widget_get_size(win, &w, &h); @@ -191,7 +191,7 @@ { GntWidget *win = node->me; const char *name = gnt_widget_get_name(win); - if (!name || !GNT_IS_BOX(win) || strcmp(name, "conversation-window")) + if (!name || !GNT_IS_BOX(win) || !strstr(name, "conversation-window")) return; g_object_set_data(G_OBJECT(win), "irssi-index", GINT_TO_POINTER(g_list_index(wm->cws->list, win))); g_timeout_add(0, (GSourceFunc)update_conv_window_title, node);
--- a/finch/plugins/pietray.py Sun Jul 01 08:02:31 2007 +0000 +++ b/finch/plugins/pietray.py Sun Jul 01 15:44:59 2007 +0000 @@ -78,9 +78,27 @@ def toggle_pref(item, pref): purple.PurplePrefsSetBool(pref, item.get_active()) +def quit_finch(item, null): + # XXX: Ask first + purple.PurpleCoreQuit() + gtk.main_quit() + +def close_docklet(item, null): + gtk.main_quit() + def popup_menu(icon, button, tm, none): menu = gtk.Menu() + #item = gtk.ImageMenuItem(gtk.STOCK_QUIT) + #item.connect("activate", quit_finch, None) + #menu.append(item) + + item = gtk.ImageMenuItem(gtk.STOCK_CLOSE) + item.connect("activate", close_docklet, None) + menu.append(item) + + menu.append(gtk.MenuItem()) + item = gtk.CheckMenuItem("Blink for unread IM") item.set_active(purple.PurplePrefsGetBool("/plugins/dbus/docklet/blink/im")) item.connect("activate", toggle_pref, "/plugins/dbus/docklet/blink/im") @@ -176,8 +194,14 @@ t = gtk.StatusIcon() t.connect("popup-menu", popup_menu, None) -init_prefs() -detect_unread_conversations() +try: + init_prefs() + detect_unread_conversations() + gtk.main () +except: + dialog = gtk.Dialog("pietray: Error", None, gtk.DIALOG_NO_SEPARATOR | gtk.DIALOG_MODAL, ("Close", gtk.RESPONSE_CLOSE)) + dialog.set_resizable(False) + dialog.vbox.pack_start(gtk.Label("There was some error. Perhaps a purple client is not running."), False, False, 0) + dialog.show_all() + dialog.run() -gtk.main () -
--- a/libpurple/dnssrv.c Sun Jul 01 08:02:31 2007 +0000 +++ b/libpurple/dnssrv.c Sun Jul 01 15:44:59 2007 +0000 @@ -50,11 +50,11 @@ u_char buf[1024]; } queryans; #else -static DNS_STATUS WINAPI (*MyDnsQuery_UTF8) ( +static DNS_STATUS (WINAPI *MyDnsQuery_UTF8) ( PCSTR lpstrName, WORD wType, DWORD fOptions, PIP4_ARRAY aipServers, PDNS_RECORD* ppQueryResultsSet, PVOID* pReserved) = NULL; -static void WINAPI (*MyDnsRecordListFree) (PDNS_RECORD pRecordList, +static void (WINAPI *MyDnsRecordListFree) (PDNS_RECORD pRecordList, DNS_FREE_TYPE FreeType) = NULL; #endif
--- a/libpurple/internal.h Sun Jul 01 08:02:31 2007 +0000 +++ b/libpurple/internal.h Sun Jul 01 15:44:59 2007 +0000 @@ -111,11 +111,16 @@ # include <unistd.h> #endif -#ifndef MAXPATHLEN -# ifdef PATH_MAX -# define MAXPATHLEN PATH_MAX -# else -# define MAXPATHLEN 1024 +/* MAXPATHLEN should only be used with readlink() on glib < 2.4.0. For + * anything else, use g_file_read_link() or other dynamic functions. This is + * important because Hurd has no hard limits on path length. */ +#if !GLIB_CHECK_VERSION(2,4,0) +# ifndef MAXPATHLEN +# ifdef PATH_MAX +# define MAXPATHLEN PATH_MAX +# else +# define MAXPATHLEN 1024 +# endif # endif #endif
--- a/libpurple/network.c Sun Jul 01 08:02:31 2007 +0000 +++ b/libpurple/network.c Sun Jul 01 15:44:59 2007 +0000 @@ -517,7 +517,7 @@ WSAQUERYSET qs; time_t last_trigger = time(NULL); - int WSAAPI (*MyWSANSPIoctl) ( + int (WSAAPI *MyWSANSPIoctl) ( HANDLE hLookup, DWORD dwControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPDWORD lpcbBytesReturned, LPWSACOMPLETION lpCompletion) = NULL;
--- a/libpurple/plugins/filectl.c Sun Jul 01 08:02:31 2007 +0000 +++ b/libpurple/plugins/filectl.c Sun Jul 01 15:44:59 2007 +0000 @@ -56,7 +56,7 @@ purple_debug_misc("filectl", "read: %s\n", buffer); command = getarg(buffer, 0, 0); - if (!strncasecmp(command, "login", 6)) { + if (!g_ascii_strncasecmp(command, "login", 6)) { PurpleAccount *account; arg1 = getarg(buffer, 1, 0); @@ -69,7 +69,7 @@ free(arg1); free(arg2); - } else if (!strncasecmp(command, "logout", 7)) { + } else if (!g_ascii_strncasecmp(command, "logout", 7)) { PurpleAccount *account; arg1 = getarg(buffer, 1, 1); @@ -88,7 +88,7 @@ /* purple_find_conversation() is gone in 2.0.0. */ #if 0 - } else if (!strncasecmp(command, "send", 4)) { + } else if (!g_ascii_strncasecmp(command, "send", 4)) { PurpleConversation *conv; arg1 = getarg(buffer, 1, 0); @@ -107,21 +107,21 @@ free(arg2); #endif - } else if (!strncasecmp(command, "away", 4)) { + } else if (!g_ascii_strncasecmp(command, "away", 4)) { arg1 = getarg(buffer, 1, 1); /* serv_set_away_all(arg1); */ free(arg1); - } else if (!strncasecmp(command, "hide", 4)) { + } else if (!g_ascii_strncasecmp(command, "hide", 4)) { purple_blist_set_visible(FALSE); - } else if (!strncasecmp(command, "unhide", 6)) { + } else if (!g_ascii_strncasecmp(command, "unhide", 6)) { purple_blist_set_visible(TRUE); - } else if (!strncasecmp(command, "back", 4)) { + } else if (!g_ascii_strncasecmp(command, "back", 4)) { /* do_im_back(); */ - } else if (!strncasecmp(command, "quit", 4)) { + } else if (!g_ascii_strncasecmp(command, "quit", 4)) { purple_core_quit(); }
--- a/libpurple/protocols/gg/lib/http.c Sun Jul 01 08:02:31 2007 +0000 +++ b/libpurple/protocols/gg/lib/http.c Sun Jul 01 15:44:59 2007 +0000 @@ -349,7 +349,7 @@ gg_debug(GG_DEBUG_MISC, "=> -----BEGIN-HTTP-HEADER-----\n%s\n=> -----END-HTTP-HEADER-----\n", h->header); while (line) { - if (!strncasecmp(line, "Content-length: ", 16)) { + if (!g_ascii_strncasecmp(line, "Content-length: ", 16)) { h->body_size = atoi(line + 16); } line = strchr(line, '\n');
--- a/libpurple/protocols/gg/lib/pubdir50.c Sun Jul 01 08:02:31 2007 +0000 +++ b/libpurple/protocols/gg/lib/pubdir50.c Sun Jul 01 15:44:59 2007 +0000 @@ -347,7 +347,7 @@ /* je¶li dostali¶my namier na nastêpne wyniki, to znaczy ¿e * mamy koniec wyników i nie jest to kolejna osoba. */ - if (!strcasecmp(field, "nextstart")) { + if (!g_ascii_strcasecmp(field, "nextstart")) { res->next = atoi(value); num--; } else { @@ -390,7 +390,7 @@ } for (i = 0; i < res->entries_count; i++) { - if (res->entries[i].num == num && !strcasecmp(res->entries[i].field, field)) { + if (res->entries[i].num == num && !g_ascii_strcasecmp(res->entries[i].field, field)) { value = res->entries[i].value; break; }
--- a/libpurple/protocols/msn/msn-utils.c Sun Jul 01 08:02:31 2007 +0000 +++ b/libpurple/protocols/msn/msn-utils.c Sun Jul 01 15:44:59 2007 +0000 @@ -296,7 +296,7 @@ char *attr_dir; attributes = g_strndup(c, attr_len); attr_dir = purple_markup_get_css_property(attributes, "direction"); - if (attr_dir && (!strncasecmp(attr_dir, "RTL", 3))) + if (attr_dir && (!g_ascii_strncasecmp(attr_dir, "RTL", 3))) direction = '1'; g_free(attr_dir); g_free(attributes);
--- a/libpurple/protocols/oscar/odc.c Sun Jul 01 08:02:31 2007 +0000 +++ b/libpurple/protocols/oscar/odc.c Sun Jul 01 15:44:59 2007 +0000 @@ -314,7 +314,7 @@ tmp += size; /* Skip past the closing </data> tag */ - if (strncasecmp(tmp, "</data>", 7)) + if (g_ascii_strncasecmp(tmp, "</data>", 7)) { g_free(embedded_data); break;
--- a/libpurple/protocols/qq/im.c Sun Jul 01 08:02:31 2007 +0000 +++ b/libpurple/protocols/qq/im.c Sun Jul 01 15:44:59 2007 +0000 @@ -573,7 +573,7 @@ read_packet_b(data, &cursor, len, &reply); if (reply != QQ_SEND_IM_REPLY_OK) { purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Send IM fail\n"); - purple_notify_error(gc, _("Server ACK"), _("Send IM fail\n"), NULL); + purple_notify_error(gc, _("Server ACK"), _("Failed to send IM."), NULL); } else purple_debug(PURPLE_DEBUG_INFO, "QQ", "IM ACK OK\n");
--- a/libpurple/protocols/silc/buddy.c Sun Jul 01 08:02:31 2007 +0000 +++ b/libpurple/protocols/silc/buddy.c Sun Jul 01 15:44:59 2007 +0000 @@ -1252,7 +1252,7 @@ SilcClientEntry entry; silc_dlist_start(clients); while ((entry = silc_dlist_get(clients))) { - if (!strncasecmp(b->name, entry->nickname, + if (!g_ascii_strncasecmp(b->name, entry->nickname, strlen(b->name))) { client_entry = entry; break;
--- a/libpurple/protocols/silc/util.c Sun Jul 01 08:02:31 2007 +0000 +++ b/libpurple/protocols/silc/util.c Sun Jul 01 15:44:59 2007 +0000 @@ -623,15 +623,15 @@ ct = strrchr(filename, '.'); if (!ct) return NULL; - else if (!strcasecmp(".png", ct)) + else if (!g_ascii_strcasecmp(".png", ct)) return strdup("image/png"); - else if (!strcasecmp(".jpg", ct)) + else if (!g_ascii_strcasecmp(".jpg", ct)) return strdup("image/jpeg"); - else if (!strcasecmp(".jpeg", ct)) + else if (!g_ascii_strcasecmp(".jpeg", ct)) return strdup("image/jpeg"); - else if (!strcasecmp(".gif", ct)) + else if (!g_ascii_strcasecmp(".gif", ct)) return strdup("image/gif"); - else if (!strcasecmp(".tiff", ct)) + else if (!g_ascii_strcasecmp(".tiff", ct)) return strdup("image/tiff"); return NULL;
--- a/libpurple/protocols/silc10/buddy.c Sun Jul 01 08:02:31 2007 +0000 +++ b/libpurple/protocols/silc10/buddy.c Sun Jul 01 15:44:59 2007 +0000 @@ -1246,7 +1246,7 @@ buddy nickname. */ int i; for (i = 0; i < clients_count; i++) { - if (!strncasecmp(b->name, clients[i]->nickname, + if (!g_ascii_strncasecmp(b->name, clients[i]->nickname, strlen(b->name))) { clients[0] = clients[i]; break;
--- a/libpurple/protocols/simple/simple.c Sun Jul 01 08:02:31 2007 +0000 +++ b/libpurple/protocols/simple/simple.c Sun Jul 01 15:44:59 2007 +0000 @@ -337,7 +337,7 @@ return; } - if(!g_strncasecmp(hdr, "NTLM", 4)) { + if(!g_ascii_strncasecmp(hdr, "NTLM", 4)) { purple_debug_info("simple", "found NTLM\n"); auth->type = 2; parts = g_strsplit(hdr+5, "\", ", 0);
--- a/libpurple/protocols/yahoo/yahoo_picture.c Sun Jul 01 08:02:31 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo_picture.c Sun Jul 01 15:44:59 2007 +0000 @@ -110,7 +110,7 @@ } /* Yahoo IM 6 spits out 0.png as the URL if the buddy icon is not set */ - if (who && got_icon_info && url && !strncasecmp(url, "http://", 7)) { + if (who && got_icon_info && url && !g_ascii_strncasecmp(url, "http://", 7)) { /* TODO: make this work p2p, try p2p before the url */ PurpleUtilFetchUrlData *url_data; struct yahoo_fetch_picture_data *data;
--- a/libpurple/protocols/zephyr/ZVariables.c Sun Jul 01 08:02:31 2007 +0000 +++ b/libpurple/protocols/zephyr/ZVariables.c Sun Jul 01 15:44:59 2007 +0000 @@ -186,7 +186,7 @@ #define max(a,b) ((a > b) ? (a) : (b)) #endif - if (strncasecmp(bfr, var, max(strlen(var),cp - bfr))) + if (g_strncasecmp(bfr, var, max(strlen(var), cp - bfr))) return(0); /* var is not the var in bfr ==> no match */
--- a/libpurple/util.c Sun Jul 01 08:02:31 2007 +0000 +++ b/libpurple/util.c Sun Jul 01 15:44:59 2007 +0000 @@ -1730,7 +1730,7 @@ if (cdata_close_tag) { /* Note: Don't even assume any other tag is a tag in CDATA */ - if (strncasecmp(str2 + i, cdata_close_tag, + if (g_ascii_strncasecmp(str2 + i, cdata_close_tag, strlen(cdata_close_tag)) == 0) { i += strlen(cdata_close_tag) - 1; @@ -1738,12 +1738,12 @@ } continue; } - else if (strncasecmp(str2 + i, "<td", 3) == 0 && closing_td_p) + else if (g_ascii_strncasecmp(str2 + i, "<td", 3) == 0 && closing_td_p) { str2[j++] = '\t'; visible = TRUE; } - else if (strncasecmp(str2 + i, "</td>", 5) == 0) + else if (g_ascii_strncasecmp(str2 + i, "</td>", 5) == 0) { closing_td_p = TRUE; visible = FALSE; @@ -1771,7 +1771,7 @@ /* If we've got an <a> tag with an href, save the address * to print later. */ - if (strncasecmp(str2 + i, "<a", 2) == 0 && + if (g_ascii_strncasecmp(str2 + i, "<a", 2) == 0 && g_ascii_isspace(str2[i+2])) { int st; /* start of href, inclusive [ */ @@ -1780,7 +1780,7 @@ /* Find start of href */ for (st = i + 3; st < k; st++) { - if (strncasecmp(str2+st, "href=", 5) == 0) + if (g_ascii_strncasecmp(str2+st, "href=", 5) == 0) { st += 5; if (str2[st] == '"' || str2[st] == '\'') @@ -1812,7 +1812,7 @@ /* Replace </a> with an ascii representation of the * address the link was pointing to. */ - else if (href != NULL && strncasecmp(str2 + i, "</a>", 4) == 0) + else if (href != NULL && g_ascii_strncasecmp(str2 + i, "</a>", 4) == 0) { size_t hrlen = strlen(href); @@ -1834,29 +1834,29 @@ } /* Check for tags which should be mapped to newline */ - else if (strncasecmp(str2 + i, "<p>", 3) == 0 - || strncasecmp(str2 + i, "<tr", 3) == 0 - || strncasecmp(str2 + i, "<br", 3) == 0 - || strncasecmp(str2 + i, "<hr", 3) == 0 - || strncasecmp(str2 + i, "<li", 3) == 0 - || strncasecmp(str2 + i, "<div", 4) == 0 - || strncasecmp(str2 + i, "</table>", 8) == 0) + else if (g_ascii_strncasecmp(str2 + i, "<p>", 3) == 0 + || g_ascii_strncasecmp(str2 + i, "<tr", 3) == 0 + || g_ascii_strncasecmp(str2 + i, "<br", 3) == 0 + || g_ascii_strncasecmp(str2 + i, "<hr", 3) == 0 + || g_ascii_strncasecmp(str2 + i, "<li", 3) == 0 + || g_ascii_strncasecmp(str2 + i, "<div", 4) == 0 + || g_ascii_strncasecmp(str2 + i, "</table>", 8) == 0) { str2[j++] = '\n'; } /* Check for tags which begin CDATA and need to be closed */ #if 0 /* FIXME.. option is end tag optional, we can't handle this right now */ - else if (strncasecmp(str2 + i, "<option", 7) == 0) + else if (g_ascii_strncasecmp(str2 + i, "<option", 7) == 0) { /* FIXME: We should not do this if the OPTION is SELECT'd */ cdata_close_tag = "</option>"; } #endif - else if (strncasecmp(str2 + i, "<script", 7) == 0) + else if (g_ascii_strncasecmp(str2 + i, "<script", 7) == 0) { cdata_close_tag = "</script>"; } - else if (strncasecmp(str2 + i, "<style", 6) == 0) + else if (g_ascii_strncasecmp(str2 + i, "<style", 6) == 0) { cdata_close_tag = "</style>"; } @@ -3079,7 +3079,7 @@ i = 0; /* position in the source string */ j = 0; /* number of occurrences of "delimiter" */ while (string[i] != '\0') { - if (!strncasecmp(&string[i], delimiter, length_del)) { + if (!g_ascii_strncasecmp(&string[i], delimiter, length_del)) { i += length_del; j += length_rep; } else { @@ -3093,7 +3093,7 @@ i = 0; /* position in the source string */ j = 0; /* position in the destination string */ while (string[i] != '\0') { - if (!strncasecmp(&string[i], delimiter, length_del)) { + if (!g_ascii_strncasecmp(&string[i], delimiter, length_del)) { strncpy(&ret[j], replacement, length_rep); i += length_del; j += length_rep;
--- a/libpurple/win32/libc_interface.c Sun Jul 01 08:02:31 2007 +0000 +++ b/libpurple/win32/libc_interface.c Sun Jul 01 15:44:59 2007 +0000 @@ -413,8 +413,8 @@ /* newname exists */ if(g_stat(newname, &newstat) == 0) { /* oldname is a dir */ - if(_S_ISDIR(oldstat.st_mode)) { - if(!_S_ISDIR(newstat.st_mode)) { + if(S_ISDIR(oldstat.st_mode)) { + if(!S_ISDIR(newstat.st_mode)) { return g_rename(oldname, newname); } /* newname is a dir */ @@ -430,7 +430,7 @@ /* oldname is not a dir */ else { /* newname is a dir */ - if(_S_ISDIR(newstat.st_mode)) { + if(S_ISDIR(newstat.st_mode)) { errno = EISDIR; return -1; }
--- a/libpurple/win32/libc_interface.h Sun Jul 01 08:02:31 2007 +0000 +++ b/libpurple/win32/libc_interface.h Sun Jul 01 15:44:59 2007 +0000 @@ -29,6 +29,16 @@ #include "libc_internal.h" #include <glib.h> +#ifdef _MSC_VER +#define S_IRUSR S_IREAD +#define S_IWUSR S_IWRITE +#define S_IXUSR S_IEXEC + +#define S_ISDIR(m) (((m)&S_IFDIR)==S_IFDIR) + +#define F_OK 0 +#endif + /* sys/socket.h */ #define socket( namespace, style, protocol ) \ wpurple_socket( namespace, style, protocol ) @@ -36,11 +46,11 @@ #define connect( socket, addr, length ) \ wpurple_connect( socket, addr, length ) -#define getsockopt( args... ) \ -wpurple_getsockopt( args ) +#define getsockopt( socket, level, optname, optval, optlenptr ) \ +wpurple_getsockopt( socket, level, optname, optval, optlenptr ) -#define setsockopt( args... ) \ -wpurple_setsockopt( args ) +#define setsockopt( socket, level, optname, optval, optlen ) \ +wpurple_setsockopt( socket, level, optname, optval, optlen ) #define getsockname( socket, addr, lenptr ) \ wpurple_getsockname( socket, addr, lenptr )
--- a/pidgin/gtkblist.c Sun Jul 01 08:02:31 2007 +0000 +++ b/pidgin/gtkblist.c Sun Jul 01 15:44:59 2007 +0000 @@ -2873,7 +2873,11 @@ { N_("/_Help"), NULL, NULL, 0, "<Branch>", NULL }, { N_("/Help/Online _Help"), "F1", gtk_blist_show_onlinehelp_cb, 0, "<StockItem>", GTK_STOCK_HELP }, { N_("/Help/_Debug Window"), NULL, toggle_debug, 0, "<Item>", NULL }, +#if GTK_CHECK_VERSION(2,6,0) + { N_("/Help/_About"), NULL, pidgin_dialogs_about, 0, "<StockItem>", GTK_STOCK_ABOUT }, +#else { N_("/Help/_About"), NULL, pidgin_dialogs_about, 0, "<Item>", NULL }, +#endif }; /*********************************************************
--- a/pidgin/gtkimhtml.c Sun Jul 01 08:02:31 2007 +0000 +++ b/pidgin/gtkimhtml.c Sun Jul 01 15:44:59 2007 +0000 @@ -494,6 +494,8 @@ GSList *tags = NULL, *templist = NULL; GdkColor *norm, *pre; GtkTextTag *tag = NULL, *oldprelit_tag; + GtkTextChildAnchor* anchor; + gboolean hand = TRUE; oldprelit_tag = GTK_IMHTML(imhtml)->prelit_tag; @@ -551,8 +553,15 @@ GTK_IMHTML(imhtml)->tip_timer = 0; } + /* If we don't have a tip from a URL, let's see if we have a tip from a smiley */ + anchor = gtk_text_iter_get_child_anchor(&iter); + if (anchor) { + tip = g_object_get_data(G_OBJECT(anchor), "gtkimhtml_plaintext"); + hand = FALSE; + } + if (tip){ - if (!GTK_IMHTML(imhtml)->editable) + if (!GTK_IMHTML(imhtml)->editable && hand) gdk_window_set_cursor(win, GTK_IMHTML(imhtml)->hand_cursor); GTK_IMHTML(imhtml)->tip_timer = g_timeout_add (TOOLTIP_TIMEOUT, gtk_imhtml_tip, imhtml); @@ -2153,7 +2162,7 @@ gint i; for(i=0; i<accepted_protocols_size; i++){ - if( strncasecmp(text, accepted_protocols[i], strlen(accepted_protocols[i])) == 0 ){ + if( g_ascii_strncasecmp(text, accepted_protocols[i], strlen(accepted_protocols[i])) == 0 ){ return strlen(accepted_protocols[i]); } } @@ -2726,7 +2735,7 @@ /* NEW_BIT (NEW_TEXT_BIT); */ /* Bi-Directional text support */ - if (direction && (!strncasecmp(direction, "RTL", 3))) { + if (direction && (!g_ascii_strncasecmp(direction, "RTL", 3))) { rtl_direction = TRUE; /* insert RLE character to set direction */ ws[wpos++] = 0xE2; @@ -2738,7 +2747,7 @@ } g_free(direction); - if (alignment && (!strncasecmp(alignment, "RIGHT", 5))) { + if (alignment && (!g_ascii_strncasecmp(alignment, "RIGHT", 5))) { align_right = TRUE; align_line = gtk_text_iter_get_line(iter); } @@ -4621,6 +4630,7 @@ GtkWidget *img = gtk_image_new_from_stock(GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_MENU); gtk_container_add(GTK_CONTAINER(ebox), img); gtk_widget_show(img); + g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_plaintext", g_strdup(unescaped), g_free); gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), ebox, anchor); } } else {
--- a/pidgin/gtkimhtmltoolbar.c Sun Jul 01 08:02:31 2007 +0000 +++ b/pidgin/gtkimhtmltoolbar.c Sun Jul 01 15:44:59 2007 +0000 @@ -37,6 +37,8 @@ #include "gtkthemes.h" #include "gtkutils.h" +#include <gdk/gdkkeysyms.h> + static GtkHBoxClass *parent_class = NULL; static void toggle_button_set_active_block(GtkToggleButton *button, @@ -629,7 +631,6 @@ return ls; } - static gboolean smiley_is_unique(GSList *list, GtkIMHtmlSmiley *smiley) { @@ -642,6 +643,18 @@ return TRUE; } +static gboolean +smiley_dialog_input_cb(GtkWidget *dialog, GdkEvent *event, GtkIMHtmlToolbar *toolbar) +{ + if ((event->type == GDK_KEY_PRESS && event->key.keyval == GDK_Escape) || + (event->type == GDK_BUTTON_PRESS && event->button.button == 1)) + { + close_smiley_dialog(NULL, NULL, toolbar); + return TRUE; + } + + return FALSE; +} static void insert_smiley_cb(GtkWidget *smiley, GtkIMHtmlToolbar *toolbar) @@ -720,11 +733,16 @@ free(it_tmp); } gtk_box_pack_start(GTK_BOX(smiley_table), line, FALSE, TRUE, 0); + + gtk_widget_add_events(dialog, GDK_KEY_PRESS_MASK); } else { smiley_table = gtk_label_new(_("This theme has no available smileys.")); + gtk_widget_add_events(dialog, GDK_KEY_PRESS_MASK | GDK_BUTTON_PRESS_MASK); + g_signal_connect(G_OBJECT(dialog), "button-press-event", (GCallback)smiley_dialog_input_cb, toolbar); } + g_signal_connect(G_OBJECT(dialog), "key-press-event", (GCallback)smiley_dialog_input_cb, toolbar); gtk_container_add(GTK_CONTAINER(dialog), smiley_table); gtk_widget_show(smiley_table);
--- a/pidgin/gtkprefs.c Sun Jul 01 08:02:31 2007 +0000 +++ b/pidgin/gtkprefs.c Sun Jul 01 15:44:59 2007 +0000 @@ -60,6 +60,7 @@ static GtkWidget *sound_entry = NULL; static GtkListStore *smiley_theme_store = NULL; +static GtkTreeSelection *smiley_theme_sel = NULL; static GtkWidget *prefs_proxy_frame = NULL; static GtkWidget *prefs = NULL; @@ -366,9 +367,12 @@ GValue val; GtkTreePath *path, *oldpath; struct smiley_theme *new_theme, *old_theme; + GtkWidget *remove_button = g_object_get_data(G_OBJECT(sel), "remove_button"); - if (!gtk_tree_selection_get_selected(sel, &model, &iter)) + if (!gtk_tree_selection_get_selected(sel, &model, &iter)) { + gtk_widget_set_sensitive(remove_button, FALSE); return; + } old_theme = current_smiley_theme; val.g_type = 0; @@ -376,6 +380,9 @@ path = gtk_tree_model_get_path(model, &iter); themename = g_value_get_string(&val); purple_prefs_set_string(PIDGIN_PREFS_ROOT "/smileys/theme", themename); + + gtk_widget_set_sensitive(remove_button, (strcmp(themename, "none") && + strcmp(themename, _("Default")))); g_value_unset (&val); /* current_smiley_theme is set in callback for the above pref change */ @@ -514,8 +521,13 @@ g_free(destdir); theme_rowref = theme_refresh_theme_list(); - if (theme_rowref != NULL) + if (theme_rowref != NULL) { + GtkTreePath *tp = gtk_tree_row_reference_get_path(theme_rowref); + + if (tp) + gtk_tree_selection_select_path(smiley_theme_sel, tp); gtk_tree_row_reference_free(theme_rowref); + } } static void @@ -619,9 +631,55 @@ return ret; } +static void +request_theme_file_name_cb(gpointer data, char *theme_file_name) +{ + theme_install_theme(theme_file_name, NULL) ; +} + +static void +add_theme_button_clicked_cb(GtkWidget *widget, gpointer null) +{ + purple_request_file(NULL, "Install Theme", NULL, FALSE, (GCallback)request_theme_file_name_cb, NULL, NULL, NULL, NULL, NULL) ; +} + +static void +remove_theme_button_clicked_cb(GtkWidget *button, GtkTreeView *tv) +{ + char *theme_name = NULL, *theme_file = NULL; + GtkTreeModel *tm; + GtkTreeIter itr; + GtkTreeRowReference *trr = NULL; + + if ((tm = gtk_tree_view_get_model(tv)) == NULL) + return; + if (!gtk_tree_selection_get_selected(smiley_theme_sel, NULL, &itr)) + return; + gtk_tree_model_get(tm, &itr, 2, &theme_file, 3, &theme_name, -1); + + if (theme_file && theme_name && strcmp(theme_name, "none")) + pidgin_themes_remove_smiley_theme(theme_file); + + if ((trr = theme_refresh_theme_list()) != NULL) { + GtkTreePath *tp = gtk_tree_row_reference_get_path(trr); + + if (tp) { + gtk_tree_selection_select_path(smiley_theme_sel, tp); + gtk_tree_path_free(tp); + } + gtk_tree_row_reference_free(trr); + } + + g_free(theme_file); + g_free(theme_name); +} + static GtkWidget * theme_page() { + GtkWidget *add_button, *remove_button; + GtkWidget *hbox_buttons; + GtkWidget *alignment; GtkWidget *ret; GtkWidget *sw; GtkWidget *view; @@ -661,7 +719,7 @@ g_signal_connect(G_OBJECT(view), "drag_data_received", G_CALLBACK(theme_dnd_recv), smiley_theme_store); rend = gtk_cell_renderer_pixbuf_new(); - sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (view)); + smiley_theme_sel = sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (view)); /* Custom sort so "none" theme is at top of list */ gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(smiley_theme_store), @@ -687,6 +745,25 @@ g_signal_connect(G_OBJECT(sel), "changed", G_CALLBACK(smiley_sel), NULL); + alignment = gtk_alignment_new(1.0, 0.5, 0.0, 1.0); + gtk_widget_show(alignment); + gtk_box_pack_start(GTK_BOX(ret), alignment, FALSE, TRUE, 0); + + hbox_buttons = gtk_hbox_new(TRUE, PIDGIN_HIG_CAT_SPACE); + gtk_widget_show(hbox_buttons); + gtk_container_add(GTK_CONTAINER(alignment), hbox_buttons); + + add_button = gtk_button_new_from_stock(GTK_STOCK_ADD); + gtk_widget_show(add_button); + gtk_box_pack_start(GTK_BOX(hbox_buttons), add_button, FALSE, TRUE, 0); + g_signal_connect(G_OBJECT(add_button), "clicked", (GCallback)add_theme_button_clicked_cb, view); + + remove_button = gtk_button_new_from_stock(GTK_STOCK_REMOVE); + gtk_widget_show(remove_button); + gtk_box_pack_start(GTK_BOX(hbox_buttons), remove_button, FALSE, TRUE, 0); + g_signal_connect(G_OBJECT(remove_button), "clicked", (GCallback)remove_theme_button_clicked_cb, view); + g_object_set_data(G_OBJECT(sel), "remove_button", remove_button); + if (rowref) { GtkTreePath *path = gtk_tree_row_reference_get_path(rowref); gtk_tree_row_reference_free(rowref); @@ -975,7 +1052,7 @@ GTK_IMHTML_BACKCOLOR | GTK_IMHTML_BACKGROUND); - gtk_imhtml_append_text(GTK_IMHTML(imhtml), _("This is how your outgoing message text will appear when you use protocols that support formatting. :)"), 0); + gtk_imhtml_append_text(GTK_IMHTML(imhtml), _("This is how your outgoing message text will appear when you use protocols that support formatting."), 0); gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
--- a/pidgin/gtkthemes.c Sun Jul 01 08:02:31 2007 +0000 +++ b/pidgin/gtkthemes.c Sun Jul 01 15:44:59 2007 +0000 @@ -36,6 +36,8 @@ GSList *smiley_themes = NULL; struct smiley_theme *current_smiley_theme; +static void pidgin_themes_destroy_smiley_theme_smileys(struct smiley_theme *theme); + gboolean pidgin_themes_smileys_disabled() { if (!current_smiley_theme) @@ -44,6 +46,79 @@ return strcmp(current_smiley_theme->name, "none") == 0; } +static void +pidgin_themes_destroy_smiley_theme(struct smiley_theme *theme) +{ + pidgin_themes_destroy_smiley_theme_smileys(theme); + + g_free(theme->name); + g_free(theme->desc); + g_free(theme->author); + g_free(theme->icon); + g_free(theme->path); + g_free(theme); +} + +static void pidgin_themes_remove_theme_dir(const char *theme_dir_name) +{ + GString *str = NULL; + const char *file_name = NULL; + GDir *theme_dir = NULL; + + if ((theme_dir = g_dir_open(theme_dir_name, 0, NULL)) != NULL) { + if ((str = g_string_new(theme_dir_name)) != NULL) { + while ((file_name = g_dir_read_name(theme_dir)) != NULL) { + g_string_printf(str, "%s%s%s", theme_dir_name, G_DIR_SEPARATOR_S, file_name); + g_unlink(str->str); + } + g_string_free(str, TRUE); + } + g_dir_close(theme_dir); + g_rmdir(theme_dir_name); + } +} + +void pidgin_themes_remove_smiley_theme(const char *file) +{ + char *theme_dir = NULL, *last_slash = NULL; + g_return_if_fail(NULL != file); + + if (!g_file_test(file, G_FILE_TEST_EXISTS)) return; + if ((theme_dir = g_strdup(file)) == NULL) return ; + + if ((last_slash = g_strrstr(theme_dir, G_DIR_SEPARATOR_S)) != NULL) { + GSList *iter = NULL; + struct smiley_theme *theme = NULL, *new_theme = NULL; + + *last_slash = 0; + + /* Delete files on disk */ + pidgin_themes_remove_theme_dir(theme_dir); + + /* Find theme in themes list and remove it */ + for (iter = smiley_themes ; iter ; iter = iter->next) { + theme = ((struct smiley_theme *)(iter->data)); + if (!strcmp(theme->path, file)) + break ; + } + if (iter) { + if (theme == current_smiley_theme) { + new_theme = ((struct smiley_theme *)(NULL == iter->next ? (smiley_themes == iter ? NULL : smiley_themes->data) : iter->next->data)); + if (new_theme) + purple_prefs_set_string(PIDGIN_PREFS_ROOT "/smileys/theme", new_theme->name); + else + current_smiley_theme = NULL; + } + smiley_themes = g_slist_delete_link(smiley_themes, iter); + + /* Destroy theme structure */ + pidgin_themes_destroy_smiley_theme(theme); + } + } + + g_free(theme_dir); +} + void pidgin_themes_smiley_themeize(GtkWidget *imhtml) { struct smiley_list *list; @@ -64,7 +139,7 @@ } static void -pidgin_themes_destroy_smiley_theme(struct smiley_theme *theme) +pidgin_themes_destroy_smiley_theme_smileys(struct smiley_theme *theme) { GHashTable *already_freed; struct smiley_list *wer; @@ -92,6 +167,32 @@ g_hash_table_destroy(already_freed); } +static void +pidgin_smiley_themes_remove_non_existing() +{ + static struct smiley_theme *theme = NULL; + GSList *iter = NULL; + + if (!smiley_themes) return ; + + for (iter = smiley_themes ; iter ; iter = iter->next) { + theme = ((struct smiley_theme *)(iter->data)); + if (!g_file_test(theme->path, G_FILE_TEST_EXISTS)) { + if (theme == current_smiley_theme) + current_smiley_theme = ((struct smiley_theme *)(NULL == iter->next ? NULL : iter->next->data)); + pidgin_themes_destroy_smiley_theme(theme); + iter->data = NULL; + } + } + /* Remove all elements whose data is NULL */ + smiley_themes = g_slist_remove_all(smiley_themes, NULL); + + if (!current_smiley_theme && smiley_themes) { + struct smiley_theme *smile = g_slist_last(smiley_themes)->data; + pidgin_themes_load_smiley_theme(smile->path, TRUE); + } +} + void pidgin_themes_load_smiley_theme(const char *file, gboolean load) { FILE *f = g_fopen(file, "r"); @@ -221,14 +322,6 @@ purple_debug_error("gtkthemes", "Invalid file format, not loading smiley theme from '%s'\n", file); pidgin_themes_destroy_smiley_theme(theme); - - g_free(theme->name); - g_free(theme->desc); - g_free(theme->author); - g_free(theme->icon); - g_free(theme->path); - g_free(theme); - return; } @@ -240,7 +333,7 @@ GList *cnv; if (current_smiley_theme) - pidgin_themes_destroy_smiley_theme(current_smiley_theme); + pidgin_themes_destroy_smiley_theme_smileys(current_smiley_theme); current_smiley_theme = theme; for (cnv = purple_get_conversations(); cnv != NULL; cnv = cnv->next) { @@ -258,10 +351,12 @@ { GDir *dir; const gchar *file; - gchar *path; + gchar *path, *test_path; int l; + char* probedirs[3]; - char* probedirs[3]; + pidgin_smiley_themes_remove_non_existing(); + probedirs[0] = g_build_filename(DATADIR, "pixmaps", "pidgin", "emotes", NULL); probedirs[1] = g_build_filename(purple_user_dir(), "smileys", NULL); probedirs[2] = 0; @@ -269,14 +364,18 @@ dir = g_dir_open(probedirs[l], 0, NULL); if (dir) { while ((file = g_dir_read_name(dir))) { - path = g_build_filename(probedirs[l], file, "theme", NULL); + test_path = g_build_filename(probedirs[l], file, NULL); + if (g_file_test(test_path, G_FILE_TEST_IS_DIR)) { + path = g_build_filename(probedirs[l], file, "theme", NULL); - /* Here we check to see that the theme has proper syntax. - * We set the second argument to FALSE so that it doesn't load - * the theme yet. - */ - pidgin_themes_load_smiley_theme(path, FALSE); - g_free(path); + /* Here we check to see that the theme has proper syntax. + * We set the second argument to FALSE so that it doesn't load + * the theme yet. + */ + pidgin_themes_load_smiley_theme(path, FALSE); + g_free(path); + } + g_free(test_path); } g_dir_close(dir); } else if (l == 1) { @@ -284,6 +383,11 @@ } g_free(probedirs[l]); } + + if (!current_smiley_theme && smiley_themes) { + struct smiley_theme *smile = smiley_themes->data; + pidgin_themes_load_smiley_theme(smile->path, TRUE); + } } GSList *pidgin_themes_get_proto_smileys(const char *id) { @@ -333,5 +437,4 @@ struct smiley_theme *smile = smiley_themes->data; pidgin_themes_load_smiley_theme(smile->path, TRUE); } - }
--- a/pidgin/gtkthemes.h Sun Jul 01 08:02:31 2007 +0000 +++ b/pidgin/gtkthemes.h Sun Jul 01 15:44:59 2007 +0000 @@ -49,5 +49,6 @@ void pidgin_themes_smiley_themeize(GtkWidget *); void pidgin_themes_smiley_theme_probe(void); void pidgin_themes_load_smiley_theme(const char *file, gboolean load); +void pidgin_themes_remove_smiley_theme(const char *file); GSList *pidgin_themes_get_proto_smileys(const char *id); #endif /* _PIDGINDIALOGS_H_ */
--- a/pidgin/plugins/spellchk.c Sun Jul 01 08:02:31 2007 +0000 +++ b/pidgin/plugins/spellchk.c Sun Jul 01 15:44:59 2007 +0000 @@ -45,9 +45,6 @@ #include <stdio.h> #include <string.h> -#ifndef _WIN32 -#include <strings.h> -#endif #include <sys/types.h> #include <sys/stat.h> @@ -1787,19 +1784,19 @@ while (buf_get_line(ibuf, &buf, &pnt, size)) { if (*buf != '#') { - if (!strncasecmp(buf, "BAD ", 4)) + if (!g_ascii_strncasecmp(buf, "BAD ", 4)) { strncpy(bad, buf + 4, 81); } - else if(!strncasecmp(buf, "CASE ", 5)) + else if(!g_ascii_strncasecmp(buf, "CASE ", 5)) { case_sensitive = *(buf+5) == '0' ? FALSE : TRUE; } - else if(!strncasecmp(buf, "COMPLETE ", 9)) + else if(!g_ascii_strncasecmp(buf, "COMPLETE ", 9)) { complete = *(buf+9) == '0' ? FALSE : TRUE; } - else if (!strncasecmp(buf, "GOOD ", 5)) + else if (!g_ascii_strncasecmp(buf, "GOOD ", 5)) { strncpy(good, buf + 5, 255);