pidgin/purple-plugin-pack
Clone
Merged in default (pull request #19)
Remove defunct plugins
Approved-by: Elliott Sales de Andrade
--- a/autoprofile/README.md Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-Allows user to place dynamic text into profiles and status messages, with the text automatically updated whenever content changes
--- a/autoprofile/autoaway.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 "autoprofile.h"
-#include "conversation.h"
-#define AP_IDLE_CHECK_INTERVAL 5
-static guint check_timeout = 0;
-static guint pref_cb = 0;
-static time_t last_active_time = 0;
-static gboolean is_idle ()
- PurpleIdleUiOps *ui_ops;
- const gchar *idle_reporting;
- ui_ops = purple_idle_get_ui_ops ();
- idle_reporting = purple_prefs_get_string ("/purple/away/idle_reporting");
- if (!strcmp (idle_reporting, "system") &&
- (ui_ops != NULL) && (ui_ops->get_time_idle != NULL)) {
- time_idle = time (NULL) - last_active_time;
- } else if (!strcmp (idle_reporting, "gaim")) {
- time_idle = time (NULL) - last_active_time;
- (60 * purple_prefs_get_int("/purple/away/mins_before_away")));
-static gboolean ap_check_idleness (gpointer data)
- // 0 0 0 don't do anything
- // 0 0 1 ap_use_idleaway ()
- // 1 0 x don't do anything, we're already away
- // 1 1 0 ap_dont_use_idleaway ()
- // 1 1 1 don't do anything
- if (ap_is_currently_away () && !ap_autoaway_in_use ()) return TRUE;
- auto_away = purple_prefs_get_bool (
- "/plugins/gtk/autoprofile/away_when_idle");
- if (auto_away && !ap_is_currently_away () && !ap_autoaway_in_use ()) {
- if (ap_is_currently_away () && ap_autoaway_in_use ()) {
- ap_autoaway_disable ();
-void ap_autoaway_touch ()
- time (&last_active_time);
-static gboolean writing_im_msg_cb (PurpleAccount *account, const char *who,
- char **message, PurpleConversation *conv, PurpleMessageFlags flags)
- ap_check_idleness (NULL);
-static void auto_pref_cb (
- const char *name, PurplePrefType type, gconstpointer val, gpointer data)
- if (!purple_prefs_get_bool ("/purple/away/away_when_idle")) return;
- purple_notify_error (NULL, NULL,
- N_("This preference is disabled"),
- N_("This preference currently has no effect because AutoProfile is in "
- "use. To modify this behavior, use the AutoProfile configuration "
- purple_prefs_set_bool ("/purple/away/away_when_idle", FALSE);
-/*--------------------------------------------------------------------------*
- * Global functions to start it all *
- *--------------------------------------------------------------------------*/
-void ap_autoaway_start ()
- purple_prefs_set_bool ("/purple/away/away_when_idle", FALSE);
- check_timeout = purple_timeout_add (AP_IDLE_CHECK_INTERVAL * 1000,
- ap_check_idleness, NULL);
- purple_signal_connect (purple_conversations_get_handle (), "writing-im-msg",
- ap_get_plugin_handle (), PURPLE_CALLBACK(writing_im_msg_cb), NULL);
- pref_cb = purple_prefs_connect_callback (ap_get_plugin_handle (),
- "/purple/away/away_when_idle", auto_pref_cb, NULL);
-void ap_autoaway_finish ()
- // Assumes signals are disconnected globally
- purple_prefs_disconnect_callback (pref_cb);
- if (check_timeout > 0) purple_timeout_remove (check_timeout);
- purple_prefs_set_bool ("/purple/away/away_when_idle",
- purple_prefs_get_bool ("/plugins/gtk/autoprofile/away_when_idle"));
--- a/autoprofile/autoprofile.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,867 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 "autoprofile.h"
-#include "savedstatuses.h"
-static void ap_status_changed (
- const char *, PurplePrefType, gconstpointer, gpointer);
-static void ap_account_connected (PurpleConnection *);
-static void ap_delete_legacy_prefs ();
-static void ap_update_queue_start ();
-static void ap_update_queue_finish ();
-/*--------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
-static PurplePlugin *plugin_handle = NULL;
-static PurpleSavedStatus *current_ap_status = NULL;
-static GStaticMutex update_timeout_mutex = G_STATIC_MUTEX_INIT;
-static GHashTable *update_timeouts = NULL;
-static gboolean using_idleaway = FALSE;
-static GStaticMutex update_queue_mutex = G_STATIC_MUTEX_INIT;
-static GList *queued_profiles = NULL;
-static guint update_queue_timeout = 0;
-/* Functions related to general variables */
-PurplePlugin *ap_get_plugin_handle () { return plugin_handle; }
-gboolean ap_is_currently_away () {
- return current_ap_status != NULL &&
- purple_savedstatus_get_type (current_ap_status) == PURPLE_STATUS_AWAY;
-/*--------------------------------------------------------------------------
- * REQUIRED GAIM FUNCTIONS- INFO, INITIALIZATION, UNLOADING
- *------------------------------------------------------------------------*/
-/* What to do when plugin is loaded */
-static gboolean plugin_load (PurplePlugin *plugin)
- ap_debug ("general", "AutoProfile is being loaded");
- plugin_handle = plugin;
- current_ap_status = purple_savedstatus_new (NULL, PURPLE_STATUS_UNSET);
- update_timeouts = g_hash_table_new (NULL, NULL);
- ap_delete_legacy_prefs ();
- /* The core autoprofile tracking system */
- purple_prefs_connect_callback (plugin_handle, "/purple/savedstatus/current",
- ap_status_changed, NULL);
- purple_signal_connect (purple_connections_get_handle (),
- "signed-on", plugin_handle,
- PURPLE_CALLBACK (ap_account_connected), NULL);
- accounts_pref = purple_prefs_get_string_list (
- "/plugins/gtk/autoprofile/profile_accounts");
- ap_gtk_set_progress_visible (AP_UPDATE_PROFILE, (accounts_pref != NULL));
- free_string_list (accounts_pref);
- ap_update_after_delay (AP_UPDATE_STATUS);
- ap_update_after_delay (AP_UPDATE_PROFILE);
- ap_update_queue_start ();
-/* What to do when plugin is unloaded */
-static gboolean plugin_unload (PurplePlugin *plugin)
- ap_update_queue_finish ();
- ap_autoreply_finish ();
- using_idleaway = FALSE;
- ap_update_stop (AP_UPDATE_STATUS);
- ap_update_stop (AP_UPDATE_PROFILE);
- /* Disconnect tracking system */
- purple_signals_disconnect_by_handle (plugin);
- ap_component_finish ();
- g_hash_table_destroy (update_timeouts);
-/* General information */
-static PurplePluginInfo info =
- PURPLE_PLUGIN_STANDARD, /* type */
- PIDGIN_PLUGIN_TYPE, /* ui_requirement */
- NULL, /* dependencies */
- PURPLE_PRIORITY_DEFAULT, /* priority */
- "gtk-kluge-autoprofile", /* id */
- PP_VERSION, /* version */
- NULL, /* description */
- PP_WEBSITE, /* homepage */
- plugin_load, /* load */
- plugin_unload, /* unload */
- &ui_info, /* ui_info */
-/*--------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
-static gint get_max_size_status (
- const PurpleAccount *account, const PurpleStatusPrimitive type) {
- case PURPLE_STATUS_AVAILABLE: return AP_SIZE_AVAILABLE_MAX;
- case PURPLE_STATUS_AWAY: return AP_SIZE_AWAY_MAX;
- default: return AP_SIZE_MAXIMUM;
- id = purple_account_get_protocol_id (account);
- case PURPLE_STATUS_AVAILABLE:
- if (!strcmp (id, "prpl-oscar")) return AP_SIZE_AVAILABLE_AIM;
- else if (!strcmp (id, "prpl-msn")) return AP_SIZE_AVAILABLE_MSN;
- else if (!strcmp (id, "prpl-yahoo")) return AP_SIZE_AVAILABLE_YAHOO;
- else return AP_SIZE_AVAILABLE_MAX;
- case PURPLE_STATUS_AWAY:
- if (!strcmp (id, "prpl-oscar")) return AP_SIZE_AWAY_AIM;
- else return AP_SIZE_AWAY_MAX;
- return AP_SIZE_MAXIMUM;
-static const char *ap_savedstatus_get_message (
- const PurpleSavedStatus *status, const PurpleAccount *account)
- const PurpleSavedStatusSub *substatus;
- substatus = purple_savedstatus_get_substatus(status, account);
- if (substatus != NULL) {
- return purple_savedstatus_substatus_get_message (substatus);
- return purple_savedstatus_get_message (status);
-static PurpleStatusPrimitive ap_savedstatus_get_type (
- const PurpleSavedStatus *status, const PurpleAccount *account)
- const PurpleSavedStatusSub *substatus;
- substatus = purple_savedstatus_get_substatus(status, account);
- if (substatus != NULL) {
- return purple_status_type_get_primitive (
- purple_savedstatus_substatus_get_type (substatus));
- return purple_savedstatus_get_type (status);
-gchar *ap_get_sample_status_message (PurpleAccount *account)
- const PurpleSavedStatus *s;
- PurpleStatusPrimitive type;
- s = (using_idleaway? purple_savedstatus_get_idleaway () :
- purple_savedstatus_get_current ());
- message = ap_savedstatus_get_message (s, account);
- type = ap_savedstatus_get_type (s, account);
- if (!message) return NULL;
- return ap_generate (message, get_max_size_status (account, type));
-static gchar *ap_process_replacement (const gchar *f) {
- w = ap_widget_find (f);
- result = w->component->generate (w);
- g_string_printf (s, "[%s]", f);
- g_string_free (s, FALSE);
-/* The workhorse generation function! */
-gchar *ap_generate (const gchar *f, gint max_length) {
- gchar *format, *format_start, *percent_start;
- output = g_string_new ("");
- format_start = format = purple_utf8_salvage (f);
- /* When a % has been read (and searching for next %), state is 1
- g_string_append_unichar (output, g_utf8_get_char ("["));
- g_string_append (output, percent_start);
- percent_start = format = format+1;
- } else if (*format == ']') {
- replacement = ap_process_replacement (percent_start);
- g_string_append (output, replacement);
- format = g_utf8_next_char (format);
- g_string_append (output, "<br>");
- } else if (*format == '[') {
- percent_start = format+1;
- g_string_append_unichar (output, g_utf8_get_char (format));
- format = g_utf8_next_char (format);
- /* Deal with case where final ] not found */
- g_string_append_unichar (output, g_utf8_get_char ("["));
- g_string_append (output, percent_start);
- g_string_truncate (output, max_length);
- result = purple_utf8_salvage(output->str);
- g_string_free (output, TRUE);
-void ap_account_enable_profile (const PurpleAccount *account, gboolean enable) {
- gboolean original_status;
- gchar *username, *protocol_id;
- original_status = ap_account_has_profile_enabled (account);
- if (original_status == enable) {
- ap_debug_warn ("profile", "New status identical to original, skipping");
- original = purple_prefs_get_string_list (
- "/plugins/gtk/autoprofile/profile_accounts");
- username = strdup (purple_account_get_username (account));
- protocol_id = strdup (purple_account_get_protocol_id (account));
- /* Remove from the list */
- ap_debug ("profile", "Disabling profile updates for account");
- if (!strcmp (original->data, username) &&
- !strcmp (original->next->data, protocol_id)) {
- original = original->next->next;
- original = original->next->next;
- node->next->next = ret;
- GList *ret_start, *ret_end;
- ap_debug ("profile", "enabling profile updates for account");
- ret_start = (GList *) malloc (sizeof (GList));
- ret_end = (GList *) malloc (sizeof (GList));
- ret_start->data = username;
- ret_start->next = ret_end;
- ret_end->data = protocol_id;
- ret_end->next = original;
- purple_prefs_set_string_list (
- "/plugins/gtk/autoprofile/profile_accounts", new);
- ap_gtk_set_progress_visible (AP_UPDATE_PROFILE, (new != NULL));
- free_string_list (new);
-gboolean ap_account_has_profile_enabled (const PurpleAccount *account) {
- GList *accounts_list, *start_list;
- accounts_list = purple_prefs_get_string_list (
- "/plugins/gtk/autoprofile/profile_accounts");
- start_list = accounts_list;
- /* Search through list of values */
- while (accounts_list) {
- // Make sure these things come in pairs
- if (accounts_list->next == NULL) {
- ap_debug_error ("is_account_profile_enabled", "invalid account string");
- free_string_list (start_list);
- if (!strcmp ((char *) accounts_list->data, account->username)) {
- if (!strcmp ((char *) accounts_list->next->data, account->protocol_id))
- free_string_list (start_list);
- accounts_list = accounts_list->next->next;
- /* Not found, hence it wasn't enabled */
- free_string_list (start_list);
-/* Profiles: Update every so often */
-static gboolean ap_update_profile () {
- PurpleAccount *account;
- const GList *purple_accounts;
- gboolean account_updated;
- char *generated_profile;
- /* Generate the profile text */
- format = purple_prefs_get_string ("/plugins/gtk/autoprofile/profile");
- ap_debug_error ("general", "profile is null");
- generated_profile = ap_generate (format, AP_SIZE_PROFILE_MAX);
- // If string is blank, nothing would happen
- if (*generated_profile == '\0') {
- free (generated_profile);
- ap_debug_misc ("general", "empty profile set");
- generated_profile = strdup (" ");
- /* Get all accounts and search through each */
- account_updated = FALSE;
- for (purple_accounts = purple_accounts_get_all ();
- purple_accounts != NULL;
- purple_accounts = purple_accounts->next) {
- account = (PurpleAccount *)purple_accounts->data;
- old_info = purple_account_get_user_info (account);
- /* Check to see if update option set on account */
- if (ap_account_has_profile_enabled (account) &&
- (old_info == NULL || strcmp (old_info, generated_profile))) {
- purple_account_set_user_info (account, generated_profile);
- account_updated = TRUE;
- if (purple_account_is_connected (account)) {
- g_static_mutex_lock (&update_queue_mutex);
- if (g_list_find (queued_profiles, account) == NULL) {
- queued_profiles = g_list_append (queued_profiles, account);
- g_static_mutex_unlock (&update_queue_mutex);
- ap_debug_misc ("general", "account not online, not setting profile");
- ap_gtk_add_message (AP_UPDATE_PROFILE, AP_MESSAGE_TYPE_PROFILE,
- free (generated_profile);
- return account_updated;
-static gboolean ap_update_status ()
- const PurpleSavedStatus *template_status;
- GHashTable *substatus_messages;
- gchar *new_message, *new_substatus_message;
- const gchar *sample_message, *old_message;
- PurpleStatusPrimitive old_type, new_type;
- const PurpleStatusType *substatus_type;
- PurpleAccount *account;
- PurpleSavedStatusSub *substatus;
- template_status = (using_idleaway? purple_savedstatus_get_idleaway () :
- purple_savedstatus_get_current ());
- /* If there are substatuses */
- if (purple_savedstatus_has_substatuses (template_status)) {
- substatus_messages = g_hash_table_new (NULL, NULL);
- for (accounts = purple_accounts_get_all ();
- accounts = accounts->next)
- account = (PurpleAccount *) accounts->data;
- substatus = purple_savedstatus_get_substatus (template_status, account);
- new_type = purple_status_type_get_primitive (
- purple_savedstatus_substatus_get_type (substatus));
- purple_savedstatus_substatus_get_message (substatus);
- new_substatus_message = ap_generate (sample_message,
- get_max_size_status (account, new_type));
- new_substatus_message = NULL;
- g_hash_table_insert (substatus_messages, account,
- new_substatus_message);
- old_type = ap_savedstatus_get_type (current_ap_status, account);
- ap_savedstatus_get_message (current_ap_status, account);
- if ((old_type != new_type) ||
- ((old_message == NULL || new_substatus_message == NULL) &&
- (old_message != new_substatus_message)) ||
- (old_message != NULL && new_substatus_message != NULL &&
- strcmp (old_message, new_substatus_message)))
- substatus_messages = NULL;
- /* And then the generic main message */
- sample_message = purple_savedstatus_get_message (template_status);
- new_message = ap_generate (sample_message, get_max_size_status (NULL,
- purple_savedstatus_get_type (template_status)));
- new_type = purple_savedstatus_get_type (template_status);
- old_type = purple_savedstatus_get_type (current_ap_status);
- old_message = purple_savedstatus_get_message (current_ap_status);
- if ((old_type != new_type) ||
- ((old_message == NULL || new_message == NULL) &&
- (old_message != new_message)) ||
- (old_message != NULL && new_message != NULL &&
- strcmp (old_message, new_message)))
- PurpleSavedStatus *new_status;
- new_status = purple_savedstatus_new (NULL, new_type);
- purple_savedstatus_set_message (new_status, new_message);
- for (accounts = purple_accounts_get_all ();
- accounts = accounts->next) {
- account = (PurpleAccount *) accounts->data;
- substatus = purple_savedstatus_get_substatus (template_status, account);
- if (substatus != NULL) {
- substatus_type = purple_savedstatus_substatus_get_type (substatus);
- new_substatus_message = (gchar *)
- g_hash_table_lookup (substatus_messages, account);
- purple_savedstatus_set_substatus (
- new_status, account, substatus_type, new_substatus_message);
- free (new_substatus_message);
- purple_savedstatus_activate_for_account (new_status, account);
- current_ap_status = new_status;
- if (new_type == PURPLE_STATUS_AVAILABLE) type = AP_MESSAGE_TYPE_AVAILABLE;
- else if (new_type == PURPLE_STATUS_AWAY) type = AP_MESSAGE_TYPE_AWAY;
- else type = AP_MESSAGE_TYPE_STATUS;
- ap_gtk_add_message (AP_UPDATE_STATUS, type, new_message);
- if (new_message) free (new_message);
- if (substatus_messages) {
- g_hash_table_destroy (substatus_messages);
-static gboolean ap_update_cb (gpointer data) {
- g_static_mutex_lock (&update_timeout_mutex);
- /* Start by removing timeout to self no matter what */
- timeout = GPOINTER_TO_INT (g_hash_table_lookup (update_timeouts, data));
- if (timeout) purple_timeout_remove (timeout);
- /* In future, check here if widget content has changed? */
- switch (GPOINTER_TO_INT (data)) {
- result = ap_update_status ();
- case AP_UPDATE_PROFILE:
- result = ap_update_profile ();
- ap_debug ("general", "Content hasn't changed, updating later");
- delay = AP_SCHEDULE_UPDATE_DELAY;
- ap_debug ("general", "Content updated");
- purple_prefs_get_int ("/plugins/gtk/autoprofile/delay_update") * 1000;
- timeout = purple_timeout_add (delay, ap_update_cb, data);
- g_hash_table_insert (update_timeouts, data, GINT_TO_POINTER (timeout));
- g_static_mutex_unlock (&update_timeout_mutex);
-void ap_update (APUpdateType type)
- ap_update_cb (GINT_TO_POINTER (type));
-void ap_update_after_delay (APUpdateType type)
- g_static_mutex_lock (&update_timeout_mutex);
- timeout = GPOINTER_TO_INT (g_hash_table_lookup (update_timeouts,
- GINT_TO_POINTER (type)));
- if (timeout) purple_timeout_remove (timeout);
- timeout = purple_timeout_add (AP_SCHEDULE_UPDATE_DELAY, ap_update_cb,
- GINT_TO_POINTER (type));
- g_hash_table_insert (update_timeouts, GINT_TO_POINTER (type),
- GINT_TO_POINTER (timeout));
- g_static_mutex_unlock (&update_timeout_mutex);
-void ap_update_stop (APUpdateType type)
- g_static_mutex_lock (&update_timeout_mutex);
- timeout = GPOINTER_TO_INT (g_hash_table_lookup (update_timeouts,
- GINT_TO_POINTER (type)));
- if (timeout) purple_timeout_remove (timeout);
- g_hash_table_insert (update_timeouts, GINT_TO_POINTER (type), 0);
- g_static_mutex_unlock (&update_timeout_mutex);
-static void ap_account_connected (PurpleConnection *gc) {
- ap_debug ("general", "Account connection detected");
- ap_update_after_delay (AP_UPDATE_PROFILE);
- ap_update_after_delay (AP_UPDATE_STATUS);
-void ap_update_queueing () {
- if (ap_is_currently_away ()) {
- if (purple_prefs_get_bool(
- "/plugins/gtk/autoprofile/queue_messages_when_away")) {
- purple_prefs_set_string (PIDGIN_PREFS_ROOT "/conversations/im/hide_new", "away");
- purple_prefs_set_string (PIDGIN_PREFS_ROOT "/conversations/im/hide_new", "never");
-/* Called whenever current status is changed by Purple's status menu
-static void ap_status_changed (
- const char *name, PurplePrefType type, gconstpointer val, gpointer data) {
- ap_debug ("general", "Status change detected");
- using_idleaway = FALSE;
- ap_update (AP_UPDATE_STATUS);
-void ap_autoaway_enable () {
- ap_debug ("idle", "Using idleaway");
- ap_update (AP_UPDATE_STATUS);
-void ap_autoaway_disable () {
- ap_debug ("idle", "Disabling idleaway");
- using_idleaway = FALSE;
- ap_update (AP_UPDATE_STATUS);
-gboolean ap_autoaway_in_use () {
-static gboolean ap_update_queue (gpointer data)
- PurpleAccount *account = NULL;
- PurpleConnection *gc = NULL;
- g_static_mutex_lock (&update_queue_mutex);
- if (queued_profiles != NULL) {
- account = (PurpleAccount *) queued_profiles->data;
- queued_profiles = queued_profiles->next;
- g_static_mutex_unlock (&update_queue_mutex);
- gc = purple_account_get_connection (account);
- serv_set_info (gc, purple_account_get_user_info (account));
-static void ap_update_queue_start ()
- update_queue_timeout = purple_timeout_add (2000, ap_update_queue, NULL);
-static void ap_update_queue_finish ()
- purple_timeout_remove (update_queue_timeout);
- update_queue_timeout = 0;
-/*--------------------------------------------------------------------------*
- *--------------------------------------------------------------------------*/
-static void ap_delete_legacy_prefs () {
- if (purple_prefs_exists ("/plugins/gtk/autoprofile/tab_number")) {
- ap_debug ("general", "Deleting legacy preferences");
- purple_prefs_remove ("/plugins/gtk/autoprofile/components");
- purple_prefs_remove ("/plugins/gtk/autoprofile/tab_number");
- purple_prefs_remove ("/plugins/gtk/autoprofile/accounts/enable_away");
- purple_prefs_remove ("/plugins/gtk/autoprofile/accounts/enable_profile");
- purple_prefs_remove ("/plugins/gtk/autoprofile/accounts");
- purple_prefs_remove ("/plugins/gtk/autoprofile/message_titles");
- purple_prefs_remove ("/plugins/gtk/autoprofile/message_texts");
- purple_prefs_remove ("/plugins/gtk/autoprofile/default_profile");
- purple_prefs_remove ("/plugins/gtk/autoprofile/default_away");
- purple_prefs_remove ("/plugins/gtk/autoprofile/current_away");
- purple_prefs_remove ("/plugins/gtk/autoprofile/added_text");
- purple_prefs_remove ("/plugins/gtk/autoprofile/delay_profile");
- purple_prefs_remove ("/plugins/gtk/autoprofile/delay_away");
- purple_prefs_rename ("/plugins/gtk/autoprofile/text_respond",
- "/plugins/gtk/autoprofile/autorespond/text");
- purple_prefs_rename ("/plugins/gtk/autoprofile/text_trigger",
- "/plugins/gtk/autoprofile/autorespond/trigger");
- purple_prefs_rename ("/plugins/gtk/autoprofile/delay_respond",
- "/plugins/gtk/autoprofile/autorespond/delay");
- purple_prefs_rename ("/plugins/gtk/autoprofile/use_trigger",
- "/plugins/gtk/autoprofile/autorespond/enable");
-static void ap_init_preferences () {
- ap_debug ("general", "Initializing preference defaults if necessary");
- /* Adding the folders */
- purple_prefs_add_none ("/plugins/gtk");
- purple_prefs_add_none ("/plugins/gtk/autoprofile");
- purple_prefs_add_none ("/plugins/gtk/autoprofile/widgets");
- purple_prefs_add_none ("/plugins/gtk/autoprofile/autorespond");
- /* Behavior-settings */
- purple_prefs_add_int ("/plugins/gtk/autoprofile/delay_update", 30);
- purple_prefs_add_string ("/plugins/gtk/autoprofile/show_summary", "always");
- purple_prefs_add_bool ("/plugins/gtk/autoprofile/queue_messages_when_away",
- purple_prefs_add_bool ("/plugins/gtk/autoprofile/away_when_idle",
- purple_prefs_get_bool ("/purple/away/away_when_idle"));
- /* Auto-response settings */
- purple_prefs_add_string ("/plugins/gtk/autoprofile/autorespond/auto_reply",
- purple_prefs_get_string ("/purple/away/auto_reply"));
- purple_prefs_add_string ("/plugins/gtk/autoprofile/autorespond/text",
- _("Say the magic word if you want me to talk more!"));
- purple_prefs_add_string ("/plugins/gtk/autoprofile/autorespond/trigger",
- purple_prefs_add_int ("/plugins/gtk/autoprofile/autorespond/delay", 2);
- purple_prefs_add_bool ("/plugins/gtk/autoprofile/autorespond/enable", TRUE);
- purple_prefs_add_string_list(
- "/plugins/gtk/autoprofile/profile_accounts", NULL);
- purple_prefs_add_string ("/plugins/gtk/autoprofile/profile",
- _("Get AutoProfile for Purple at <a href=\""
- "http://autoprofile.sourceforge.net/\">"
- "autoprofile.sourceforge.net</a><br><br>[Timestamp]"));
-/*--------------------------------------------------------------------------*
- *--------------------------------------------------------------------------*/
-static void init_plugin (PurplePlugin *plugin)
- info.name = _("AutoProfile");
- info.summary = _("User profile and status message content generator");
- info.description = _("Allows user to place dynamic text into profiles\n"
- "and status messages, with the text automatically\n"
- "updated whenever content changes");
- info.author = _("Casey Ho <casey at hkn-berkeley-edu>\n\t\t\taim:caseyho");
- ap_debug ("general", "Initializing AutoProfile");
- ap_init_preferences ();
-PURPLE_INIT_PLUGIN (autoprofile, init_plugin, info)
--- a/autoprofile/autoprofile.h Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 "../common/pp_internal.h"
-#define AP_SCHEDULE_UPDATE_DELAY 3000
-#define AP_GTK_MAX_MESSAGES 50
- AP_MESSAGE_TYPE_OTHER = -1,
- AP_MESSAGE_TYPE_PROFILE,
- AP_MESSAGE_TYPE_AVAILABLE,
-/* Variable access functions */
-PurplePlugin *ap_get_plugin_handle ();
-gboolean ap_is_currently_away ();
-void ap_account_enable_profile (const PurpleAccount *, gboolean);
-gboolean ap_account_has_profile_enabled (const PurpleAccount *);
-/* Core behavior functions */
-gchar *ap_generate (const char *, gint);
-gchar *ap_get_sample_status_message (PurpleAccount *account);
-void ap_update (APUpdateType);
-void ap_update_after_delay (APUpdateType);
-void ap_update_stop (APUpdateType);
-/* Queueing functions */
-void ap_update_queueing ();
-/* Auto-away functions */
-void ap_autoaway_start ();
-void ap_autoaway_finish ();
-void ap_autoaway_touch ();
-void ap_autoaway_enable ();
-void ap_autoaway_disable ();
-gboolean ap_autoaway_in_use ();
-/* Auto-reply functions */
-void ap_autoreply_start ();
-void ap_autoreply_finish ();
-void ap_gtk_make_visible ();
-void ap_gtk_add_message (APUpdateType, APMessageType, const gchar *);
-void ap_gtk_set_progress_visible (APUpdateType, gboolean);
-GList *actions (PurplePlugin *, gpointer);
-void ap_actions_finish ();
-extern PidginPluginUiInfo ui_info;
-void ap_preferences_display ();
-void ap_gtk_prefs_add_summary_option (GtkWidget *);
-GtkWidget *get_account_page ();
-#endif /* #ifndef AUTOPROFILE_H */
--- a/autoprofile/autoreply.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,324 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 "autoprofile.h"
-#include "conversation.h"
-#define SECS_BEFORE_RESENDING_AUTORESPONSE 600
-#define SEX_BEFORE_RESENDING_AUTORESPONSE "Only after you're married"
-#define MILLISECS_BEFORE_PROCESSING_MSG 100
-static GSList *last_auto_responses = NULL;
-struct last_auto_response {
-static time_t response_timeout = 0;
-/*--------------------------------------------------------------------------*
- * Auto-response utility functions *
- *--------------------------------------------------------------------------*/
-expire_last_auto_responses(gpointer data)
- struct last_auto_response *lar;
- tmp = last_auto_responses;
- lar = (struct last_auto_response *)cur->data;
- if ((time(NULL) - lar->sent) > SECS_BEFORE_RESENDING_AUTORESPONSE) {
- last_auto_responses = g_slist_remove(last_auto_responses, lar);
- return FALSE; /* do not run again */
-static struct last_auto_response *
-get_last_auto_response(PurpleConnection *gc, const char *name)
- struct last_auto_response *lar;
- /* because we're modifying or creating a lar, schedule the
- * function to expire them as the pref dictates */
- purple_timeout_add((SECS_BEFORE_RESENDING_AUTORESPONSE + 5) * 1000,
- expire_last_auto_responses, NULL);
- tmp = last_auto_responses;
- lar = (struct last_auto_response *)tmp->data;
- if (gc == lar->gc && !strncmp(name, lar->name, sizeof(lar->name)))
- lar = (struct last_auto_response *)g_new0(struct last_auto_response, 1);
- g_snprintf(lar->name, sizeof(lar->name), "%s", name);
- last_auto_responses = g_slist_append(last_auto_responses, lar);
-/*--------------------------------------------------------------------------*
- * Message send/receive general functionality *
- *--------------------------------------------------------------------------*/
-/* Detecting sent message stuff */
-static void sent_im_msg_cb (PurpleAccount *account, const char *receiver,
- PurplePresence *presence;
- const gchar *auto_reply_pref;
- gc = purple_account_get_connection (account);
- presence = purple_account_get_presence (account);
- * FIXME - If "only auto-reply when away & idle" is set, then shouldn't
- * this only reset lar->sent if we're away AND idle?
- purple_prefs_get_string ("/plugins/gtk/autoprofile/autorespond/auto_reply");
- if ((gc->flags & PURPLE_CONNECTION_AUTO_RESP) &&
- !purple_presence_is_available(presence) &&
- strcmp(auto_reply_pref, "never"))
- struct last_auto_response *lar;
- lar = get_last_auto_response(gc, receiver);
- lar->sent = time(NULL);
-/* Detecting received message stuff */
-struct received_im_msg {
- PurpleAccount *account;
-static gint process_received_im_msg (gpointer data)
- struct received_im_msg *received_im;
- PurpleAccount *account;
- PurpleConversation *conv;
- received_im = (struct received_im_msg *) data;
- account = received_im->account;
- sender = received_im->sender;
- message = received_im->message;
- gc = purple_account_get_connection (account);
- /* search for conversation again in case it was created by other handlers */
- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, sender);
- * Don't autorespond if:
- * - it's not supported on this connection
- * - or we're not idle and the 'only auto respond if idle' pref
- if (gc->flags & PURPLE_CONNECTION_AUTO_RESP)
- PurplePresence *presence;
- PurpleStatusType *status_type;
- PurpleStatusPrimitive primitive;
- const gchar *auto_reply_pref;
- auto_reply_pref = purple_prefs_get_string(
- "/plugins/gtk/autoprofile/autorespond/auto_reply");
- presence = purple_account_get_presence(account);
- status = purple_presence_get_active_status(presence);
- status_type = purple_status_get_type(status);
- primitive = purple_status_type_get_primitive(status_type);
- if ((primitive == PURPLE_STATUS_AVAILABLE) ||
- (primitive == PURPLE_STATUS_INVISIBLE) ||
- (primitive == PURPLE_STATUS_MOBILE) ||
- !strcmp(auto_reply_pref, "never") ||
- (!purple_presence_is_idle(presence) &&
- !strcmp(auto_reply_pref, "awayidle")))
- away_msg = ap_get_sample_status_message (account);
- if ((away_msg != NULL) && (*away_msg != '\0')) {
- struct last_auto_response *lar;
- gboolean autorespond_enable;
- time_t now = time(NULL);
- autorespond_enable = purple_prefs_get_bool (
- "/plugins/gtk/autoprofile/autorespond/enable");
- * This used to be based on the conversation window. But um, if
- * you went away, and someone sent you a message and got your
- * auto-response, and then you closed the window, and then they
- * sent you another one, they'd get the auto-response back too
- * soon. Besides that, we need to keep track of this even if we've
- * got a queue. So the rest of this block is just the auto-response,
- lar = get_last_auto_response(gc, sender);
- if ((now - lar->sent) >= SECS_BEFORE_RESENDING_AUTORESPONSE) {
- // Send basic autoresponse
- serv_send_im (gc, sender, away_msg, PURPLE_MESSAGE_AUTO_RESP);
- purple_conv_im_write (PURPLE_CONV_IM(conv), NULL, away_msg,
- PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_AUTO_RESP,
- // Send additional hint if enabled
- if (autorespond_enable) {
- const gchar *query = purple_prefs_get_string (
- "/plugins/gtk/autoprofile/autorespond/text");
- serv_send_im (gc, sender, query, PURPLE_MESSAGE_AUTO_RESP);
- purple_conv_im_write (PURPLE_CONV_IM (conv), NULL, query,
- PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_AUTO_RESP,
- } else if (autorespond_enable &&
- difftime (time(NULL), response_timeout) >
- purple_prefs_get_int ("/plugins/gtk/autoprofile/autorespond/delay")) {
- gchar *text = purple_markup_strip_html (message);
- if (match_start (text, purple_prefs_get_string (
- "/plugins/gtk/autoprofile/autorespond/trigger")) == 1) {
- serv_send_im (gc, sender, away_msg, PURPLE_MESSAGE_AUTO_RESP);
- purple_conv_im_write (PURPLE_CONV_IM (conv), NULL, away_msg,
- PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_AUTO_RESP,
- response_timeout = time (NULL);
- ap_debug ("autorespond", "string matched, responding");
-static void received_im_msg_cb (PurpleAccount *account, char *sender,
- char *message, PurpleConversation *conv, PurpleMessageFlags flags)
- struct received_im_msg *received_im;
- (struct received_im_msg *) malloc (sizeof (struct received_im_msg));
- received_im->account = account;
- received_im->sender = strdup (sender);
- received_im->message = strdup (message);
- purple_timeout_add (MILLISECS_BEFORE_PROCESSING_MSG, process_received_im_msg,
-static void auto_pref_cb (
- const char *name, PurplePrefType type, gconstpointer val, gpointer data)
- if (!strcmp (purple_prefs_get_string ("/purple/away/auto_reply"), "never"))
- purple_notify_error (NULL, NULL,
- N_("This preference is disabled"),
- N_("This preference currently has no effect because AutoProfile is in "
- "use. To modify this behavior, use the AutoProfile configuration "
- purple_prefs_set_string ("/purple/away/auto_reply", "never");
-/*--------------------------------------------------------------------------*
- *--------------------------------------------------------------------------*/
-void ap_autoreply_start ()
- purple_prefs_set_string ("/purple/away/auto_reply", "never");
- purple_signal_connect (purple_conversations_get_handle (), "sent-im-msg",
- ap_get_plugin_handle (), PURPLE_CALLBACK(sent_im_msg_cb), NULL);
- purple_signal_connect (purple_conversations_get_handle (), "received-im-msg",
- ap_get_plugin_handle (), PURPLE_CALLBACK(received_im_msg_cb), NULL);
- pref_cb = purple_prefs_connect_callback (ap_get_plugin_handle (),
- "/purple/away/auto_reply", auto_pref_cb, NULL);
-void ap_autoreply_finish ()
- // Assumes signals are disconnected globally
- purple_prefs_disconnect_callback (pref_cb);
- purple_prefs_set_string ("/purple/away/auto_reply", purple_prefs_get_string (
- "/plugins/gtk/autoprofile/autorespond/auto_reply"));
- while (last_auto_responses) {
- tmp = last_auto_responses->next;
- g_free (last_auto_responses->data);
- g_slist_free_1 (last_auto_responses);
- last_auto_responses = tmp;
--- a/autoprofile/comp_countdownup.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,438 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 "../common/pp_internal.h"
-static GtkWidget *spin_secs;
-static GtkWidget *spin_mins;
-static GtkWidget *spin_hour;
-static GtkWidget *spin_day;
-static GtkWidget *spin_month;
-static GtkWidget *spin_year;
-/* Generate the time! */
-char *count_generate (struct widget *w)
- double d_secs, d_mins, d_hours, d_days;
- char *s_secs, *s_mins, *s_hours, *s_days;
- ref_time = (struct tm *) malloc (sizeof (struct tm));
- ref_time->tm_sec = ap_prefs_get_int (w, "secs");
- ref_time->tm_min = ap_prefs_get_int (w, "mins");
- ref_time->tm_hour = ap_prefs_get_int (w, "hour");
- ref_time->tm_mday = ap_prefs_get_int (w, "day");
- ref_time->tm_mon = ap_prefs_get_int (w, "month") - 1;
- ref_time->tm_year = ap_prefs_get_int (w, "year") - 1900;
- ref_time->tm_isdst = -1;
- if (ap_prefs_get_int (w, "down") == 1)
- difference = difftime (mktime (ref_time), time(NULL));
- difference = difftime (time(NULL), mktime (ref_time));
- d_mins = floor (difference / 60);
- d_secs = difference - (d_mins * 60);
- d_hours = floor (d_mins / 60);
- d_mins = d_mins - (d_hours * 60);
- d_days = floor (d_hours / 24);
- d_hours = d_hours - (d_days * 24);
- result = (char *)malloc(sizeof (char) * AP_SIZE_MAXIMUM);
- l = ap_prefs_get_int (w, "large");
- s = ap_prefs_get_int (w, "small");
- g_snprintf(result, AP_SIZE_MAXIMUM,
- "%.0f days, %.0f hours, %.0f minutes, %.0f seconds",
- d_days, d_hours, d_mins, d_secs);
- d_hours = d_hours + (d_days * 24);
- d_mins = d_mins + (d_hours * 60);
- d_secs = d_secs + (d_mins * 60);
- s_days = g_strdup ("day");
- s_days = g_strdup ("days");
- s_hours = g_strdup ("hour");
- s_hours = g_strdup ("hours");
- s_mins = g_strdup ("minute");
- s_mins = g_strdup ("minutes");
- s_secs = g_strdup ("second");
- s_secs = g_strdup ("seconds");
- g_snprintf (result, AP_SIZE_MAXIMUM, "%.0f %s",
- g_snprintf (result, AP_SIZE_MAXIMUM, "%.0f %s, %.0f %s",
- d_days, s_days, d_hours, s_hours);
- g_snprintf (result, AP_SIZE_MAXIMUM, "%.0f %s, %.0f %s, %.0f %s",
- d_days, s_days, d_hours, s_hours, d_mins, s_mins);
- g_snprintf (result, AP_SIZE_MAXIMUM,
- "%.0f %s, %.0f %s, %.0f %s, %.0f %s",
- d_days, s_days, d_hours, s_hours, d_mins, s_mins, d_secs, s_secs);
- g_snprintf (result, AP_SIZE_MAXIMUM, "%.0f %s",
- g_snprintf (result, AP_SIZE_MAXIMUM, "%.0f %s, %.0f %s",
- d_hours, s_hours, d_mins, s_mins);
- g_snprintf (result, AP_SIZE_MAXIMUM, "%.0f %s, %.0f %s, %.0f %s",
- d_hours, s_hours, d_mins, s_mins, d_secs, s_secs);
- g_snprintf (result, AP_SIZE_MAXIMUM, "%.0f %s",
- g_snprintf (result, AP_SIZE_MAXIMUM, "%.0f %s, %.0f %s",
- d_mins, s_mins, d_secs, s_secs);
- g_snprintf (result, AP_SIZE_MAXIMUM, "%.0f %s",
-static void update_year (GtkSpinButton *spinner, struct widget *w)
- int value = gtk_spin_button_get_value_as_int (spinner);
- ap_prefs_set_int (w, "year", value);
-static void update_month (GtkSpinButton *spinner, struct widget *w)
- int value = gtk_spin_button_get_value_as_int (spinner);
- ap_prefs_set_int (w, "month", value);
-static void update_day (GtkSpinButton *spinner, struct widget *w)
- int value = gtk_spin_button_get_value_as_int (spinner);
- ap_prefs_set_int (w, "day", value);
-static void update_hour (GtkSpinButton *spinner, struct widget *w)
- int value = gtk_spin_button_get_value_as_int (spinner);
- ap_prefs_set_int (w, "hour", value);
-static void update_mins (GtkSpinButton *spinner, struct widget *w)
- int value = gtk_spin_button_get_value_as_int (spinner);
- ap_prefs_set_int (w, "mins", value);
-static void update_secs (GtkSpinButton *spinner, struct widget *w)
- int value = gtk_spin_button_get_value_as_int (spinner);
- ap_prefs_set_int (w, "secs", value);
-static void set_to_current_time (GtkButton *button, struct widget *w)
- ref_time = ap_localtime(&the_time);
- ap_prefs_set_int (w, "year", ref_time->tm_year + 1900);
- ap_prefs_set_int (w, "month", ref_time->tm_mon + 1);
- ap_prefs_set_int (w, "day", ref_time->tm_mday);
- ap_prefs_set_int (w, "hour", ref_time->tm_hour);
- ap_prefs_set_int (w, "mins", ref_time->tm_min);
- ap_prefs_set_int (w, "secs", ref_time->tm_sec);
- if (spin_secs != NULL) {
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_secs),
- ap_prefs_get_int (w, "secs"));
- if (spin_mins != NULL) {
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_mins),
- ap_prefs_get_int (w, "mins"));
- if (spin_hour != NULL) {
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_hour),
- ap_prefs_get_int (w, "hour"));
- if (spin_day != NULL) {
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_day),
- ap_prefs_get_int (w, "day"));
- if (spin_month != NULL) {
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_month),
- ap_prefs_get_int (w, "month"));
- if (spin_year != NULL) {
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_year),
- ap_prefs_get_int (w, "year"));
-GtkWidget *count_menu (struct widget *w)
- GtkWidget *vbox, *hbox, *big_hbox, *frame;
- GtkWidget *label, *spinner, *dropbox, *button;
- big_hbox = gtk_hbox_new (FALSE, 6);
- frame = pidgin_make_frame (big_hbox, _("Start/end time"));
- vbox = gtk_vbox_new (FALSE, 6);
- gtk_container_add (GTK_CONTAINER (frame), vbox);
- hbox = gtk_hbox_new (FALSE, 6);
- gtk_box_pack_start (GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
- label = gtk_label_new (_("Year: "));
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- gtk_box_pack_start (GTK_BOX(hbox), label, TRUE, TRUE, 0);
- spinner = gtk_spin_button_new_with_range (1970, 2035, 1);
- gtk_box_pack_end (GTK_BOX (hbox), spinner, FALSE, FALSE, 0);
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinner),
- ap_prefs_get_int (w, "year"));
- g_signal_connect (G_OBJECT (spinner), "value-changed",
- G_CALLBACK (update_year), w);
- hbox = gtk_hbox_new (FALSE, 6);
- gtk_box_pack_start (GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
- label = gtk_label_new (_("Month: "));
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- gtk_box_pack_start (GTK_BOX(hbox), label, TRUE, TRUE, 0);
- spinner = gtk_spin_button_new_with_range (1, 12, 1);
- gtk_box_pack_end (GTK_BOX (hbox), spinner, FALSE, FALSE, 0);
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinner),
- ap_prefs_get_int (w, "month"));
- g_signal_connect (G_OBJECT (spinner), "value-changed",
- G_CALLBACK (update_month), w);
- hbox = gtk_hbox_new (FALSE, 6);
- gtk_box_pack_start (GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
- label = gtk_label_new (_("Day: "));
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- gtk_box_pack_start (GTK_BOX(hbox), label, TRUE, TRUE, 0);
- spinner = gtk_spin_button_new_with_range (1, 31, 1);
- gtk_box_pack_end (GTK_BOX (hbox), spinner, FALSE, FALSE, 0);
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinner),
- ap_prefs_get_int (w, "day"));
- g_signal_connect (G_OBJECT (spinner), "value-changed",
- G_CALLBACK (update_day), w);
- hbox = gtk_hbox_new (FALSE, 6);
- gtk_box_pack_start (GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
- label = gtk_label_new (_("Hour: "));
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- gtk_box_pack_start (GTK_BOX(hbox), label, TRUE, TRUE, 0);
- spinner = gtk_spin_button_new_with_range (0, 23, 1);
- gtk_box_pack_end (GTK_BOX (hbox), spinner, FALSE, FALSE, 0);
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinner),
- ap_prefs_get_int (w, "hour"));
- g_signal_connect (G_OBJECT (spinner), "value-changed",
- G_CALLBACK (update_hour), w);
- hbox = gtk_hbox_new (FALSE, 6);
- gtk_box_pack_start (GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
- label = gtk_label_new (_("Minutes: "));
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- gtk_box_pack_start (GTK_BOX(hbox), label, TRUE, TRUE, 0);
- spinner = gtk_spin_button_new_with_range (0, 59, 1);
- gtk_box_pack_end (GTK_BOX (hbox), spinner, FALSE, FALSE, 0);
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinner),
- ap_prefs_get_int (w, "mins"));
- g_signal_connect (G_OBJECT (spinner), "value-changed",
- G_CALLBACK (update_mins), w);
- hbox = gtk_hbox_new (FALSE, 12);
- gtk_box_pack_start (GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
- label = gtk_label_new (_("Seconds: "));
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- gtk_box_pack_start (GTK_BOX(hbox), label, TRUE, TRUE, 0);
- spinner = gtk_spin_button_new_with_range (0, 59, 1);
- gtk_box_pack_end (GTK_BOX (hbox), spinner, FALSE, FALSE, 0);
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinner),
- ap_prefs_get_int (w, "secs"));
- g_signal_connect (G_OBJECT (spinner), "value-changed",
- G_CALLBACK (update_secs), w);
- hbox = gtk_hbox_new (FALSE, 12);
- gtk_box_pack_start (GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
- button = gtk_button_new_with_label ("Set to current time");
- g_signal_connect (G_OBJECT (button), "clicked",
- G_CALLBACK (set_to_current_time), w);
- gtk_box_pack_start (GTK_BOX(hbox), button, FALSE, FALSE, 0);
- frame = pidgin_make_frame (big_hbox, _("Which way"));
- vbox = gtk_vbox_new (FALSE, 6);
- gtk_container_add (GTK_CONTAINER (frame), vbox);
- options = g_list_append (NULL, (char *) _("Count down to stop date"));
- options = g_list_append (options, GINT_TO_POINTER(1));
- options = g_list_append (options, (char *)
- _("Count time since start date"));
- options = g_list_append (options, GINT_TO_POINTER(0));
- dropbox = ap_prefs_dropdown_from_list (w, vbox, NULL,
- PURPLE_PREF_INT, "down", options);
- options = g_list_append (NULL, (char *) _("Days"));
- options = g_list_append (options, GINT_TO_POINTER(3));
- options = g_list_append (options, (char *) _("Hours"));
- options = g_list_append (options, GINT_TO_POINTER(2));
- options = g_list_append (options, (char *) _("Minutes"));
- options = g_list_append (options, GINT_TO_POINTER(1));
- options = g_list_append (options, (char *) _("Seconds"));
- options = g_list_append (options, GINT_TO_POINTER(0));
- dropbox = ap_prefs_dropdown_from_list (w, vbox,
- _("Largest units displayed"), PURPLE_PREF_INT, "large", options);
- dropbox = ap_prefs_dropdown_from_list (w, vbox,
- _("Smallest units displayed"), PURPLE_PREF_INT, "small", options);
-void count_init (struct widget *w) {
- ref_time = ap_localtime(&the_time);
- ap_prefs_add_int (w, "down", 1);
- ap_prefs_add_int (w, "small", 0);
- ap_prefs_add_int (w, "large", 3);
- ap_prefs_add_int (w, "year",
- ref_time->tm_year + 1900);
- ap_prefs_add_int (w, "month",
- ap_prefs_add_int (w, "day",
- ap_prefs_add_int (w, "hour",
- ap_prefs_add_int (w, "mins",
- ap_prefs_add_int (w, "secs",
-struct component count =
- N_("Given a date, shows amount of time until it (or since it)"),
--- a/autoprofile/comp_executable.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,169 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 "../common/pp_internal.h"
-/*---------- EXECUTABLE: STDOUT from a program ----------*/
-static GtkWidget *file_selector;
-static GtkWidget *file_entry;
-/* Read file into string and return */
-char *executable_generate (struct widget *w)
- char *text, *text_start;
- max = ap_prefs_get_int (w, "max_size");
- exec = g_spawn_command_line_sync (ap_prefs_get_string (w, "command"),
- &text_start, NULL, NULL, &return_error);
- ap_debug ("executable", "command failed to execute");
- return g_strdup (_("[ERROR: command failed to execute]"));
- if (strlen (text_start) < max)
- text = text_start + strlen(text_start);
- text = text_start + max;
- /* Should back off only if the last item is newline */
- /* Gets rid of the extra <BR> in output */
-void executable_filename (GtkWidget *widget, gpointer user_data) {
- const gchar *selected_filename;
- selected_filename = gtk_file_selection_get_filename (
- GTK_FILE_SELECTION (file_selector));
- ap_prefs_set_string ((struct widget *) user_data, "command",
- gtk_entry_set_text (GTK_ENTRY (file_entry), selected_filename);
-/* Creates and pops up file selection dialog for fortune file */
-void executable_selection (GtkWidget *widget, struct widget *w) {
- /* Create the selector */
- file_selector = gtk_file_selection_new (
- "Select the location of the program");
- cur_file = ap_prefs_get_string (w, "command");
- if (strlen (cur_file) > 1) {
- gtk_file_selection_set_filename (
- GTK_FILE_SELECTION (file_selector), cur_file);
- g_signal_connect (GTK_OBJECT(
- GTK_FILE_SELECTION(file_selector)->ok_button),
- "clicked", G_CALLBACK (executable_filename), w);
- /* Destroy dialog box when the user clicks button. */
- g_signal_connect_swapped (GTK_OBJECT(
- GTK_FILE_SELECTION(file_selector)->ok_button),
- "clicked", G_CALLBACK (gtk_widget_destroy), (gpointer) file_selector);
- g_signal_connect_swapped (GTK_OBJECT (
- GTK_FILE_SELECTION (file_selector)->cancel_button),
- "clicked", G_CALLBACK (gtk_widget_destroy), (gpointer) file_selector);
- gtk_widget_show (file_selector);
-static gboolean executable_update (GtkWidget *widget, GdkEventFocus *evt,
- ap_prefs_set_string ((struct widget *) data, "command",
- gtk_entry_get_text (GTK_ENTRY (file_entry)));
-GtkWidget *executable_menu (struct widget *w)
- GtkWidget *ret = gtk_vbox_new (FALSE, 5);
- GtkWidget *hbox, *label, *button;
- label = gtk_label_new (
- _("Specify the command line you wish to execute"));
- gtk_box_pack_start (GTK_BOX (ret), label, FALSE, FALSE, 0);
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- hbox = gtk_hbox_new (FALSE, 5);
- gtk_box_pack_start (GTK_BOX (ret), hbox, FALSE, FALSE, 0);
- /* Text entry to type in program name */
- file_entry = gtk_entry_new ();
- gtk_box_pack_start (GTK_BOX (hbox), file_entry, FALSE, FALSE, 0);
- gtk_entry_set_text (GTK_ENTRY (file_entry),
- ap_prefs_get_string (w, "command"));
- g_signal_connect (G_OBJECT (file_entry), "focus-out-event",
- G_CALLBACK (executable_update), w);
- /* Button to bring up file select dialog */
- button = gtk_button_new_with_label ("Browse for program");
- g_signal_connect (G_OBJECT (button), "clicked",
- G_CALLBACK (executable_selection), w);
- gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
- ap_prefs_labeled_spin_button (w, ret,
- _("Max characters to read from output: "), "max_size",
- 1, AP_SIZE_MAXIMUM, NULL);
-void executable_init (struct widget *w) {
- ap_prefs_add_string (w, "command", "date");
- ap_prefs_add_int (w, "max_size", 1000);
-struct component executable =
- N_("Reproduces standard output of running a program on the command line"),
--- a/autoprofile/comp_http.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,204 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 "../common/pp_internal.h"
-static GHashTable *refresh_timeouts = NULL;
-/*---------- HTTP: HTTP requested Data ----------*/
-static void http_response (PurpleUtilFetchUrlData *reuqest_data, gpointer data, const char *c, gsize len, const gchar *error_message)
- w = (struct widget *) data;
- ap_prefs_set_string (w, "http_data",
- _("[AutoProfile error: Invalid URL or no internet connection]"));
- w = (struct widget *) data;
- ap_prefs_set_string (w, "http_data", c);
-static char* http_generate (struct widget *w)
- const char *result, *url;
- url = ap_prefs_get_string (w, "http_url");
- if (!url || url[0] == '\0') {
- return g_strdup (_("[AutoProfile error: No URL specified]"));
- result = ap_prefs_get_string (w, "http_data");
- if (result == NULL) return g_strdup ("");
- return g_strdup (result);
-static gboolean http_refresh_update (gpointer user_data)
- w = (struct widget *) user_data;
- http_url = g_strdup (ap_prefs_get_string (w, "http_url"));
- if( http_url && (http_url[0] != '\0') ) {
- purple_util_fetch_url(http_url, TRUE, NULL, FALSE, http_response, w);
- ap_prefs_set_string (w, "http_data", "");
-static void http_load (struct widget *w)
- gpointer http_refresh_timeout;
- if (refresh_timeouts == NULL) {
- refresh_timeouts = g_hash_table_new (NULL, NULL);
- http_refresh_update (w);
- http_refresh_timeout = GINT_TO_POINTER (g_timeout_add (
- ap_prefs_get_int (w, "http_refresh_mins") * 60 * 1000,
- http_refresh_update, w));
- g_hash_table_insert (refresh_timeouts, w, http_refresh_timeout);
-static void http_unload (struct widget *w)
- gpointer http_refresh_timeout;
- http_refresh_timeout = g_hash_table_lookup (refresh_timeouts, w);
- g_source_remove (GPOINTER_TO_INT (http_refresh_timeout));
- g_hash_table_remove (refresh_timeouts, w);
-static void http_init (struct widget *w)
- ap_prefs_add_string (w, "http_url", "");
- ap_prefs_add_string (w, "http_data", "");
- ap_prefs_add_int (w, "http_refresh_mins", 1);
-static gboolean http_url_update (GtkWidget *widget, GdkEventFocus *evt,
- struct widget *w = (struct widget *) data;
- ap_prefs_set_string (w, "http_url",
- gtk_entry_get_text (GTK_ENTRY (widget)));
-static gboolean http_refresh_mins_update (GtkWidget *widget, gpointer data)
- minutes = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget));
- w = (struct widget *) data;
- ap_prefs_set_int (w, "http_refresh_mins", minutes);
- // Kill the current timer and run a new one
- timeout = g_hash_table_lookup (refresh_timeouts, w);
- g_source_remove (GPOINTER_TO_INT(timeout));
- timeout = GINT_TO_POINTER (g_timeout_add (minutes * 60 * 1000,
- http_refresh_update, w));
- g_hash_table_replace (refresh_timeouts, w, timeout);
-static void http_data_update (GtkWidget *w, gpointer data) {
- http_refresh_update (data);
-static GtkWidget *http_menu (struct widget *w)
- GtkWidget *ret = gtk_vbox_new (FALSE, 5);
- GtkWidget *label, *hbox, *button, *spinner;
- GtkWidget *http_url_entry;
- label = gtk_label_new (_("Select URL with source content"));
- gtk_box_pack_start (GTK_BOX (ret), label, FALSE, FALSE, 0);
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- hbox = gtk_hbox_new (FALSE, 5);
- gtk_box_pack_start (GTK_BOX (ret), hbox, FALSE, FALSE, 0);
- http_url_entry = gtk_entry_new ();
- gtk_box_pack_start (GTK_BOX (hbox), http_url_entry, TRUE, TRUE, 0);
- gtk_entry_set_text (GTK_ENTRY (http_url_entry),
- ap_prefs_get_string (w, "http_url"));
- g_signal_connect (G_OBJECT (http_url_entry), "focus-out-event",
- G_CALLBACK (http_url_update), w);
- button = gtk_button_new_with_label (_("Fetch page now!"));
- g_signal_connect (G_OBJECT (button), "clicked",
- G_CALLBACK (http_data_update), w);
- gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
- hbox = gtk_hbox_new (FALSE, 5);
- gtk_box_pack_start (GTK_BOX (ret), hbox, FALSE, FALSE, 0);
- label = gtk_label_new (_("Delay"));
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
- spinner = gtk_spin_button_new_with_range (1, 60, 1);
- gtk_box_pack_start (GTK_BOX (hbox), spinner, FALSE, FALSE, 0);
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinner),
- ap_prefs_get_int (w, "http_refresh_mins"));
- g_signal_connect (G_OBJECT (spinner), "value-changed",
- G_CALLBACK (http_refresh_mins_update), w);
- label = gtk_label_new (_("minutes between page fetches"));
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
- N_("Data fetched from an internet URL using HTTP"),
--- a/autoprofile/comp_logstats.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1042 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 "autoprofile.h"
-#include "conversation.h"
-#include "comp_logstats.h"
-struct conversation_time {
-/* Represents data about a particular 24 hour period in the logs */
- int month; // The month
- int received_msgs; // # msgs received
- int received_words; // # words received
- int sent_msgs; // # msgs sent
- int sent_words; // # words sent
- GSList *conversation_times; // List of conversation_time pointers
-/* List of struct log_dates
- This is SORTED by most recent first */
-static GSList *dates = NULL;
-/* Hashtable of log_dates */
-static GHashTable *dates_table = NULL;
-/* Is the current line part of a message sent or received? */
-static gboolean receiving = FALSE;
-static char *cur_receiver = NULL;
-static char *cur_sender = NULL;
-/* Implements GCompareFunc */
-static gint conversation_time_compare (gconstpointer x, gconstpointer y) {
- const struct conversation_time *a = x;
- const struct conversation_time *b = y;
- if (difftime (*(a->start_time), *(b->start_time)) == 0.0) {
- if (!strcmp (a->name, b->name))
-/* Implements GCompareFunc */
-static gint log_date_compare (gconstpointer x, gconstpointer y)
- const struct log_date *a = y;
- const struct log_date *b = x;
- if (a->year == b->year) {
- if (a->month == b->month) {
- return a->day - b->day;
- return a->month - b->month;
- return a->year - b->year;
-/* Implements GHashFunc */
-static guint log_date_hash (gconstpointer key)
- const struct log_date *d = key;
- return ((d->year * 365) + (d->month * 12) + (d->day));
-/* Implements GEqualFunc */
-static gboolean log_date_equal (gconstpointer x, gconstpointer y)
- const struct log_date *a = y;
- const struct log_date *b = x;
- if (a->year == b->year &&
- a->month == b->month &&
-/* Returns the struct log_date associated with a particular date.
- Will MODIFY list of dates and insert sorted if not yet created */
-static struct log_date *get_date (int year, int month, int day)
- struct log_date *cur_date;
- cur_date = (struct log_date *)malloc(sizeof(struct log_date));
- cur_date->month = month;
- if ((node = g_hash_table_lookup (dates_table, cur_date))) {
- return (struct log_date *)node;
- g_hash_table_insert (dates_table, cur_date, cur_date);
- cur_date->received_msgs = 0;
- cur_date->received_words = 0;
- cur_date->sent_msgs = 0;
- cur_date->sent_words = 0;
- cur_date->conversation_times = NULL;
-/* Like get_date, except specific to the current date */
-static struct log_date *get_today ()
- cur_time = localtime (&the_time);
- return get_date (cur_time->tm_year, cur_time->tm_mon, cur_time->tm_mday);
-static int string_word_count (const char *line)
- /* If state is 1, currently processing a word */
-/* Figure out if a person is yourself or someone else */
-static gboolean is_self (PurpleAccount *a, const char *name) {
- GList *accounts, *aliases, *aliases_start;
- PurpleAccount *account;
- const char *normalized_alias;
- if (cur_sender && !strcmp (cur_sender, name)) {
- if (cur_receiver && !strcmp (cur_receiver, name)) {
- normalized = strdup (purple_normalize (a, name));
- accounts = purple_accounts_get_all ();
- aliases_start = aliases = purple_prefs_get_string_list (
- "/plugins/gtk/autoprofile/components/logstat/aliases");
- normalized_alias = purple_normalize (a, (char *)aliases->data);
- if (!strcmp (normalized, normalized_alias)) {
- free_string_list (aliases_start);
- cur_sender = strdup (name);
- aliases = aliases->next;
- free_string_list (aliases_start);
- account = (PurpleAccount *)accounts->data;
- if (!strcmp (normalized, purple_account_get_username (account))) {
- cur_sender = strdup (name);
- accounts = accounts->next;
- cur_receiver = strdup (name);
-/* Parses a line of a conversation */
-static void parse_line (PurpleLog *cur_log, char *l, struct log_date *d)
- char *cur_line, *cur_line_start;
- if (strlen (line) > 14 && *line == ' ')
- if (strlen (line) > 13 &&
- isdigit (*(line + 1)) &&
- isdigit (*(line + 2)) &&
- isdigit (*(line + 4)) &&
- isdigit (*(line + 5)) &&
- isdigit (*(line + 7)) &&
- isdigit (*(line + 8)) &&
- isspace (*(line + 10))) {
- cur_line_start = cur_line = line + 11;
- if (*cur_line == ':') {
- receiving = !is_self (cur_log->account, name);
- d->received_words += string_word_count (message);
- d->sent_words += string_word_count (message);
- d->received_words += string_word_count (line);
- d->sent_words += string_word_count (line);
-/* Parses a conversation if hasn't been handled yet */
-static void parse_log (PurpleLog *cur_log)
- struct log_date *the_date;
- struct conversation_time *conv_time;
- PurpleLogReadFlags flags;
- char *content, *cur_content, *cur_content_start, *temp;
- the_time = localtime (&(cur_log->time));
- the_date = get_date (the_time->tm_year, the_time->tm_mon, the_time->tm_mday);
- /* Check for old log and if no conflicts, add to list */
- conv_time = (struct conversation_time *)malloc (
- sizeof (struct conversation_time));
- conv_time->start_time = (time_t *)malloc (sizeof(time_t));
- *(conv_time->start_time) = cur_log->time;
- conv_time->name = strdup (cur_log->name);
- if (g_slist_find_custom (the_date->conversation_times, conv_time,
- conversation_time_compare)) {
- /* We already processed this! Halt! */
- free (conv_time->start_time);
- free (conv_time->name);
- the_date->conversation_times = g_slist_prepend (the_date->conversation_times,
- /* Start rolling the counters! */
- temp = purple_log_read (cur_log, &flags);
- if (!strcmp ("html", cur_log->logger->id)) {
- content = purple_markup_strip_html (temp);
- cur_content_start = cur_content = content;
- /* Splits the conversation into lines (each line may not necessarily
- be a seperate message */
- if (*cur_content == '\n') {
- parse_line (cur_log, cur_content_start, the_date);
- cur_content_start = cur_content + 1;
- parse_line (cur_log, cur_content_start, the_date);
-/* Get names of users in logs */
-static GList *logstats_get_names (PurpleLogType type, PurpleAccount *account)
- if (type == PURPLE_LOG_CHAT)
- me = g_strdup_printf ("%s.chat", purple_normalize(account,
- purple_account_get_username(account)));
- me = g_strdup (purple_normalize(account,
- purple_account_get_username(account)));
- /* Get the old logger names */
- path = g_build_filename(purple_user_dir(), "logs", NULL);
- if (!(dir = g_dir_open(path, 0, NULL))) {
- while ((filename = g_dir_read_name (dir))) {
- if (purple_str_has_suffix (filename, ".log")) {
- tmp = strdup (filename);
- *(tmp + strlen (filename) - 4) = '\0';
- if (!string_list_find (ret, tmp))
- ret = g_list_prepend (ret, strdup (tmp));
- /* Get the account-specific names */
- prpl = PURPLE_PLUGIN_PROTOCOL_INFO
- (purple_find_prpl (purple_account_get_protocol_id(account)))->list_icon(
- path = g_build_filename(purple_user_dir(), "logs", prpl, me, NULL);
- if (!(dir = g_dir_open(path, 0, NULL))) {
- while ((filename = g_dir_read_name (dir))) {
- if (!string_list_find (ret, filename))
- ret = g_list_prepend (ret, strdup (filename));
-/* On load, reads in all logs and initializes stats database */
-static void logstats_read_logs ()
- GList *accounts, *logs, *logs_start, *names, *names_start;
- accounts = purple_accounts_get_all();
- ap_debug ("logstats", "parsing log files");
- names_start = names = logstats_get_names (PURPLE_LOG_IM,
- (PurpleAccount *)accounts->data);
- logs_start = purple_log_get_logs (PURPLE_LOG_IM, (char *)names->data,
- (PurpleAccount *)accounts->data);
- cur_log = (PurpleLog *)logs->data;
- purple_log_free (cur_log);
- g_list_free (logs_start);
- free_string_list (names_start);
- accounts = accounts->next;
- ap_debug ("logstats", "finished parsing log files");
-static void add_element (gpointer key, gpointer value, gpointer data)
- dates = g_slist_insert_sorted (dates, value, log_date_compare);
-/* Updates GList against hashtable */
-static void logstats_update_dates ()
- g_hash_table_foreach (dates_table, add_element, NULL);
-/*--------------------- Total calculations -------------------*/
-static int get_total (const char *field)
- d = (struct log_date *)cur_day->data;
- if (!strcmp (field, "received_msgs")) {
- count += d->received_msgs;
- } else if (!strcmp (field, "received_words")) {
- count += d->received_words;
- } else if (!strcmp (field, "sent_msgs")) {
- } else if (!strcmp (field, "sent_words")) {
- count += d->sent_words;
- } else if (!strcmp (field, "num_convos")) {
- count += g_slist_length (d->conversation_times);
- cur_day = cur_day->next;
-static int get_recent_total (const char *field, int hours)
- d = (struct log_date *)cur_day->data;
- cur_day_time = purple_time_build (d->year + 1900, d->month + 1, d->day,
- if (difftime (time (NULL), cur_day_time) > (double) hours * 60.0 * 60.0)
- if (!strcmp (field, "received_msgs")) {
- count += d->received_msgs;
- } else if (!strcmp (field, "sent_msgs")) {
- } else if (!strcmp (field, "num_convos")) {
- count += g_slist_length (d->conversation_times);
- cur_day = cur_day->next;
-static int num_days_since_start ()
- first_day = g_slist_last (dates);
- d = (struct log_date *)first_day->data;
- difference = difftime (
- time (NULL), purple_time_build (d->year + 1900, d->month + 1, d->day,
- return (int) difference / (60.0 * 60.0 * 24.0);
-static struct log_date *get_max_date (const char *field)
- struct log_date *max_date, *cur_date;
- int max_so_far, cur_max;
- cur_date = (struct log_date *)cur_day->data;
- if (!strcmp (field, "conversations")) {
- cur_max = g_slist_length (cur_date->conversation_times);
- } else if (!strcmp (field, "received")) {
- cur_max = cur_date->received_msgs;
- } else if (!strcmp (field, "sent")) {
- cur_max = cur_date->sent_msgs;
- } else if (!strcmp (field, "total")) {
- cur_max = cur_date->sent_msgs + cur_date->received_msgs;
- if (cur_max >= max_so_far) {
- cur_day = cur_day->next;
-static char *date_string (const char *field)
- last_day = g_slist_last (dates);
- if (!strcmp (field, "first")) {
- d = (struct log_date *) last_day->data;
- d = get_max_date (field);
- output = (char *)malloc (sizeof(char) * AP_SIZE_MAXIMUM);
- t_struct = (struct tm *)malloc(sizeof(struct tm));
- t_struct->tm_year = d->year;
- t_struct->tm_mon = d->month;
- t_struct->tm_mday = d->day;
- t_struct = localtime (&t);
- strftime (output, AP_SIZE_MAXIMUM - 1, "%a %b %d, %Y", t_struct);
-static int get_max (const char *field)
- struct log_date *max_date = get_max_date (field);
- if (!strcmp (field, "conversations")) {
- return g_slist_length (max_date->conversation_times);
- } else if (!strcmp (field, "received")) {
- return max_date->received_msgs;
- } else if (!strcmp (field, "sent")) {
- return max_date->sent_msgs;
- } else if (!strcmp (field, "total")) {
- return max_date->sent_msgs + max_date->received_msgs;
- ap_debug ("logstats", "get-max: invalid parameter");
-/*--------------------- Signal handlers ----------------------*/
-static void logstats_received_im (PurpleAccount *account, char *sender,
- char *message, int flags)
- struct log_date *the_date;
- the_date = get_today ();
- the_date->received_msgs++;
- the_date->received_words += string_word_count (message);
-static void logstats_sent_im (PurpleAccount *account, const char *receiver,
- struct log_date *the_date;
- the_date = get_today ();
- the_date->sent_words += string_word_count (message);
-static void logstats_conv_created (PurpleConversation *conv)
- struct log_date *the_date;
- struct conversation_time *the_time;
- if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
- the_time = malloc (sizeof(struct conversation_time));
- the_time->name = strdup (purple_conversation_get_name(conv));
- the_time->start_time = malloc (sizeof(time_t));
- time (the_time->start_time);
- the_date = get_today ();
- the_date->conversation_times = g_slist_prepend (
- the_date->conversation_times, the_time);
- logstats_update_dates ();
-/*--------------------------- Main functions -------------------------*/
-void logstats_load (struct widget *w)
- if (!purple_prefs_get_bool (
- "/plugins/gtk/autoprofile/components/logstat/enabled")) {
- /* Initialize database */
- dates_table = g_hash_table_new (log_date_hash, log_date_equal);
- logstats_update_dates ();
- msg = (char *)malloc (sizeof(char) * AP_SIZE_MAXIMUM);
- count = get_total ("received_msgs");
- g_snprintf (msg, AP_SIZE_MAXIMUM, "received msg total is %d", count);
- ap_debug ("logstats", msg);
- count = get_total ("sent_msgs");
- g_snprintf (msg, AP_SIZE_MAXIMUM, "sent msg total is %d", count);
- ap_debug ("logstats", msg);
- count = get_total ("received_words");
- g_snprintf (msg, AP_SIZE_MAXIMUM, "received word total is %d", count);
- ap_debug ("logstats", msg);
- count = get_total ("sent_words");
- g_snprintf (msg, AP_SIZE_MAXIMUM, "sent word total is %d", count);
- ap_debug ("logstats", msg);
- count = get_total ("num_convos");
- g_snprintf (msg, AP_SIZE_MAXIMUM, "num conversations is %d", count);
- ap_debug ("logstats", msg);
- count = g_slist_length (dates);
- g_snprintf (msg, AP_SIZE_MAXIMUM, "num days with conversations is %d", count);
- ap_debug ("logstats", msg);
- purple_signal_connect (purple_conversations_get_handle (),
- "received-im-msg", ap_get_plugin_handle (),
- PURPLE_CALLBACK (logstats_received_im), NULL);
- purple_signal_connect (purple_conversations_get_handle (),
- "sent-im-msg", ap_get_plugin_handle (),
- PURPLE_CALLBACK (logstats_sent_im), NULL);
- purple_signal_connect (purple_conversations_get_handle (),
- "conversation-created", ap_get_plugin_handle (),
- PURPLE_CALLBACK (logstats_conv_created), NULL);
-void logstats_unload (struct widget *w)
- struct log_date *cur_date;
- struct conversation_time *cur_time;
- if (!purple_prefs_get_bool (
- "/plugins/gtk/autoprofile/components/logstat/enabled")) {
- /* Disconnect signals */
- purple_signal_disconnect (purple_conversations_get_handle (),
- "received-im-msg", ap_get_plugin_handle (),
- PURPLE_CALLBACK (logstats_received_im));
- purple_signal_disconnect (purple_conversations_get_handle (),
- "sent-im-msg", ap_get_plugin_handle (),
- PURPLE_CALLBACK (logstats_sent_im));
- purple_signal_disconnect (purple_conversations_get_handle (),
- "conversation-created", ap_get_plugin_handle (),
- PURPLE_CALLBACK (logstats_conv_created));
- logstats_update_dates ();
- /* Free all the memory */
- cur_date = (struct log_date *)dates->data;
- while (cur_date->conversation_times) {
- temp = cur_date->conversation_times;
- cur_time = (struct conversation_time *)temp->data;
- cur_date->conversation_times = temp->next;
- free (cur_time->start_time);
- g_hash_table_destroy (dates_table);
-/* Generate the output */
-static char *logstats_generate (struct widget *w)
- char *buf, *output, *date;
- if (!purple_prefs_get_bool (
- "/plugins/gtk/autoprofile/components/logstat/enabled")) {
- format = purple_prefs_get_string (
- "/plugins/gtk/autoprofile/components/logstat/format");
- output = (char *)malloc (sizeof(char)*AP_SIZE_MAXIMUM);
- buf = (char *)malloc (sizeof(char)*AP_SIZE_MAXIMUM);
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%c", output, *format);
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, get_total ("received_msgs"));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, get_total ("received_words"));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, get_total ("sent_msgs"));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, get_total ("sent_words"));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output,
- get_total ("sent_msgs") + get_total ("received_msgs"));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output,
- get_total ("sent_words") + get_total ("received_words"));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output,
- num_days_since_start ());
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, g_slist_length (dates));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, get_total ("num_convos"));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
- (double) get_total ("num_convos") / (double) g_slist_length (dates));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, get_max ("conversations"));
- date = date_string ("conversations");
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%s", output, date);
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, get_max ("sent"));
- date = date_string ("sent");
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%s", output, date);
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, get_max ("received"));
- date = date_string ("received");
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%s", output, date);
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, get_max ("total"));
- date = date_string ("total");
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%s", output, date);
- date = date_string ("first");
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%s", output, date);
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
- (double) get_total ("received_words") / (double) get_total ("received_msgs"));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
- (double) get_total ("sent_words") / (double) get_total ("sent_msgs"));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
- (double) (get_total ("received_words") + get_total ("sent_words")) / (double) (get_total("received_msgs") + get_total ("sent_msgs")));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
- (double) get_total ("received_msgs") / (double) get_total ("num_convos"));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
- (double) get_total ("sent_msgs") / (double) get_total ("num_convos"));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
- (double) (get_total ("received_msgs") + get_total ("sent_msgs")) / (double) get_total("num_convos"));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
- (double) get_total ("received_words") / (double) g_slist_length (dates));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
- (double) get_total ("sent_words") / (double) g_slist_length (dates));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
- ((double) get_total ("received_words") + (double) get_total ("sent_words")) / (double) g_slist_length (dates));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
- (double) get_total ("received_msgs") / (double) g_slist_length (dates));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
- (double) get_total ("sent_msgs") / (double) g_slist_length (dates));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
- (double) (get_total ("received_msgs") + get_total ("sent_msgs")) / (double) g_slist_length (dates));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.1f", output,
- 100.0 * (double) g_slist_length (dates) / (double) num_days_since_start ());
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output,
- ((struct log_date *) dates->data)->received_msgs);
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output,
- ((struct log_date *) dates->data)->sent_msgs);
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output,
- g_slist_length (((struct log_date *) dates->data)->conversation_times));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output,
- ((struct log_date *) dates->data)->sent_msgs + ((struct log_date *) dates->data)->received_msgs);
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, get_recent_total ("received_msgs", 24 * 7));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, get_recent_total ("sent_msgs", 24 * 7));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, get_recent_total ("num_convos", 24 * 7));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output,
- get_recent_total ("received_msgs", 24 * 7) + get_recent_total ("received_msgs", 24 * 7));
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%c", output, *format);
- g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%c", output, *format);
-/* Initialize preferences */
-static void logstats_init (struct widget *w)
- purple_prefs_add_none ("/plugins/gtk/autoprofile/components/logstat");
- purple_prefs_add_bool (
- "/plugins/gtk/autoprofile/components/logstat/enabled", FALSE);
- purple_prefs_add_string (
- "/plugins/gtk/autoprofile/components/logstat/format", "");
- purple_prefs_add_string_list (
- "/plugins/gtk/autoprofile/components/logstat/aliases", NULL);
-/* The heart of the component */
-static char *identifiers [7] = {
-struct component logstats =
- N_("Purple log statistics"),
- N_("Display various statistics about your message and system logs"),
--- a/autoprofile/comp_logstats.h Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 *
- *--------------------------------------------------------------------------*/
-void logstats_load (struct widget *w);
-void logstats_unload (struct widget *w);
-GtkWidget *logstats_prefs (struct widget *w);
--- a/autoprofile/comp_logstats_gtk.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,355 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 "autoprofile.h"
-#include "comp_logstats.h"
-GtkWidget *checkbox = NULL;
-GtkListStore *alias_list = NULL;
-GtkWidget *alias_view = NULL;
-/* General callbacks from main preferences */
-static void logstats_response_cb (GtkDialog *dialog, gint id,
- purple_prefs_set_bool (
- "/plugins/gtk/autoprofile/components/logstat/enabled", TRUE);
- gtk_widget_set_sensitive (widget, TRUE);
- gtk_widget_destroy (GTK_WIDGET(dialog));
-static void toggle_enable (GtkButton *button, gpointer data)
- GtkWidget *popup, *vbox, *label;
- if (purple_prefs_get_bool (
- "/plugins/gtk/autoprofile/components/logstat/enabled")) {
- logstats_unload (NULL);
- purple_prefs_set_bool (
- "/plugins/gtk/autoprofile/components/logstat/enabled", FALSE);
- gtk_widget_set_sensitive (vbox, FALSE);
- popup = gtk_dialog_new_with_buttons (
- "Enable stats for logs", NULL, 0,
- GTK_STOCK_OK, 42, NULL);
- g_signal_connect (G_OBJECT(popup), "response",
- G_CALLBACK(logstats_response_cb), vbox);
- label = gtk_label_new(NULL);
- gtk_label_set_markup(GTK_LABEL(label),
- "\nEnabling this component will have some minor side effects. Doing so "
- "will cause Purple to take slightly longer to start up because it must "
- "parse a large amount of data to gather statistics. On average, this "
- "can take slightly over a second for every 100,000 messages in your "
- "logs.\n\nThe time from when you press the OK button to the time "
- "when this dialog vanishes is a good approximation of how much extra "
- "time will elapse before the login screen is shown.\n"
- gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
- gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
- gtk_box_pack_start(GTK_BOX(GTK_DIALOG(popup)->vbox), label,
- gtk_widget_show_all (popup);
-static gboolean logstat_format (GtkWidget *widget, GdkEventFocus *event,
- purple_prefs_set_string (
- "/plugins/gtk/autoprofile/components/logstat/format",
- gtk_entry_get_text (GTK_ENTRY (widget)));
-static void new_alias (gpointer data, PurpleRequestFields *fields)
- alias = purple_request_fields_get_string (fields, "alias");
- aliases = purple_prefs_get_string_list (
- "/plugins/gtk/autoprofile/components/logstat/aliases");
- aliases = g_list_append (aliases, strdup (alias));
- purple_prefs_set_string_list (
- "/plugins/gtk/autoprofile/components/logstat/aliases", aliases);
- free_string_list (aliases);
- gtk_list_store_insert (alias_list, &iter, 0);
- gtk_list_store_set (alias_list, &iter,
-static void alias_add (GtkButton *button, gpointer data)
- PurpleRequestFields *fields;
- PurpleRequestFieldGroup *group;
- PurpleRequestField *field;
- fields = purple_request_fields_new();
- group = purple_request_field_group_new(NULL);
- purple_request_fields_add_group(fields, group);
- field = purple_request_field_string_new("alias", _("Alias"),
- purple_request_field_set_required(field, TRUE);
- purple_request_field_set_type_hint(field, "alias");
- purple_request_field_group_add_field(group, field);
- purple_request_fields(purple_get_blist(), _("Add Alias"),
- _("Type in the alias that you use"),
- _("OK"), G_CALLBACK(new_alias),
- NULL, NULL, NULL, NULL);
-static void alias_delete (GtkButton *button, gpointer data)
- GtkTreeSelection *selection;
- GList *aliases, *aliases_start, *new_aliases;
- selection = gtk_tree_view_get_selection (
- GTK_TREE_VIEW (alias_view));
- if (!gtk_tree_selection_get_selected (selection, NULL, &iter))
- gtk_tree_model_get (GTK_TREE_MODEL (alias_list), &iter,
- gtk_list_store_remove (alias_list, &iter);
- aliases = purple_prefs_get_string_list (
- "/plugins/gtk/autoprofile/components/logstat/aliases");
- aliases_start = aliases;
- if (strcmp ((char *)aliases->data, alias)) {
- new_aliases = g_list_append (new_aliases, aliases->data);
- aliases = aliases->next;
- purple_prefs_set_string_list (
- "/plugins/gtk/autoprofile/components/logstat/aliases", new_aliases);
- free_string_list (aliases_start);
- g_list_free (new_aliases);
-static void alias_what (GtkButton *button, gpointer data)
- purple_notify_formatted (NULL, _("Aliases"), _("What this list is for"), NULL,
- _("Logs in Purple are stored verbatim with what you see on the screen. "
- "The names of the people in the conversation (both yourself and your "
- "buddy) are shown with their given aliases as opposed to actual screen "
- "names. If you have given yourself an alias in a conversation, list "
- "it using this dialog. If you do not, messages written by you will "
- "be incorrectly identified as received instead of sent.<br><br>Correct "
- "capitalization and whitespace are not required for detection to "
- "work.<br><br>You must disable/re-enable log stats to refresh the "
- "database after an alias change."),
-GtkWidget *logstats_prefs (struct widget *w)
- GtkWidget *ret, *vbox, *hbox;
- GtkWidget *label, *button, *entry, *sw;
- GtkCellRenderer *renderer;
- GtkTreeSelection *selection;
- GtkTreeViewColumn *col;
- GList *aliases, *aliases_start;
- ret = gtk_vbox_new (FALSE, 6);
- /* Checkbox for enabling/disabling */
- checkbox = gtk_check_button_new_with_mnemonic (
- "Enable statistics for logs");
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(checkbox),
- purple_prefs_get_bool (
- "/plugins/gtk/autoprofile/components/logstat/enabled"));
- gtk_box_pack_start (GTK_BOX(ret), checkbox, FALSE, FALSE, 0);
- vbox = gtk_vbox_new (FALSE, 6);
- gtk_box_pack_start (GTK_BOX(ret), vbox, TRUE, TRUE, 0);
- label = gtk_label_new (NULL);
- gtk_label_set_markup (GTK_LABEL(label), "<b>Format string for output</b>");
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- gtk_box_pack_start (GTK_BOX(vbox), label, FALSE, FALSE, 0);
- entry = gtk_entry_new ();
- gtk_box_pack_start (GTK_BOX(vbox), entry, FALSE, FALSE, 0);
- gtk_entry_set_max_length (GTK_ENTRY(entry), 1000);
- gtk_entry_set_text (GTK_ENTRY(entry), purple_prefs_get_string (
- "/plugins/gtk/autoprofile/components/logstat/format"));
- g_signal_connect (G_OBJECT (entry), "focus-out-event",
- G_CALLBACK (logstat_format), NULL);
- label = gtk_label_new (_(
- "%R\tTotal messages received\n"
- "%r\tTotal words received\n"
- "%S\tTotal messages sent\n"
- "%s\tTotal words sent\n"
- "%T\tTotal messages sent/received\n"
- "%t\tTotal words sent/received\n"
- "%D\tNumber of days since first logged conversation\n"
- "%d\tNumber of days with logged conversations\n"
- "%N\tNumber of logged conversations\n"
- "%n\tAverage number of conversations per day with logs\n"
- "%i\tMost conversations in a single day\n"
- "%I\tDate with most conversations\n"
- "%j\tMost messages sent in a single day\n"
- "%J\tDate with most messages sent\n"
- "%k\tMost messages received in a single day\n"
- "%K\tDate with most messages received\n"
- "%l\tMost total messages sent/received in a single day\n"
- "%L\tDate with most total messages sent/received\n"
- "%f\tDate of first logged conversation\n"
- "%u\tAverage words per message received\n"
- "%v\tAverage words per message sent\n"
- "%w\tAverage words per message sent/received\n"
- "%U\tAverage messages received per conversation\n"
- "%V\tAverage messages sent per conversation\n"
- "%W\tAverage messages sent/received per conversation\n"
- "%x\tAverage words received per day with logs\n"
- "%y\tAverage words sent per day with logs\n"
- "%z\tAverage words sent/received per day with logs\n"
- "%X\tAverage messages received per day with logs\n"
- "%Y\tAverage messages sent per day with logs\n"
- "%Z\tAverage messages sent/received per day with logs\n"
- "%p\tPercentage of days with logs\n"
- "%a\tNumber of messages received today\n"
- "%b\tNumber of messages sent today\n"
- "%c\tNumber of conversations started today\n"
- "%e\tNumber of messages sent/received today\n"
- "%A\tNumber of messages received in last week\n"
- "%B\tNumber of messages sent in last week\n"
- "%C\tNumber of conversations started in last week\n"
- "%E\tNumber of messages sent/received in last week\n"
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- sw = gtk_scrolled_window_new (NULL,NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
- GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
- gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE , 0);
- gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(sw), label);
- label = gtk_label_new (NULL);
- gtk_label_set_markup (GTK_LABEL(label), "<b>Personal aliases</b>");
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- gtk_box_pack_start (GTK_BOX(vbox), label, FALSE, FALSE, 0);
- label = gtk_label_new (NULL);
- gtk_label_set_markup (GTK_LABEL(label),
- "You need this if you have an alias for your own screen name,\n"
- "else IM's you sent will be incorrectly counted as received");
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- gtk_box_pack_start (GTK_BOX(vbox), label, FALSE, FALSE, 0);
- hbox = gtk_hbox_new (FALSE, 3);
- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
- button = gtk_button_new_with_label (_("Add alias"));
- g_signal_connect (G_OBJECT(button), "clicked",
- G_CALLBACK (alias_add), NULL);
- gtk_box_pack_start (GTK_BOX(hbox), button, TRUE, TRUE, 0);
- button = gtk_button_new_with_label (_("Delete alias"));
- g_signal_connect (G_OBJECT(button), "clicked",
- G_CALLBACK (alias_delete), NULL);
- gtk_box_pack_start (GTK_BOX(hbox), button, TRUE, TRUE, 0);
- button = gtk_button_new_with_label (_("?"));
- g_signal_connect (G_OBJECT(button), "clicked",
- G_CALLBACK (alias_what), NULL);
- gtk_box_pack_start (GTK_BOX(hbox), button, FALSE, FALSE, 0);
- sw = gtk_scrolled_window_new (0, 0);
- gtk_box_pack_start (GTK_BOX(vbox), sw, FALSE, FALSE, 0);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(sw),
- GTK_POLICY_NEVER, GTK_POLICY_NEVER);
- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw),
- alias_list = gtk_list_store_new (1, G_TYPE_STRING);
- alias_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (alias_list));
- gtk_container_add (GTK_CONTAINER(sw), alias_view);
- renderer = gtk_cell_renderer_text_new ();
- gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(alias_view), FALSE);
- selection = gtk_tree_view_get_selection (
- GTK_TREE_VIEW (alias_view));
- gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
- col = gtk_tree_view_column_new_with_attributes (
- _("Alias"), renderer, "text", 0, NULL);
- gtk_tree_view_append_column (GTK_TREE_VIEW(alias_view), col);
- aliases = purple_prefs_get_string_list (
- "/plugins/gtk/autoprofile/components/logstat/aliases");
- aliases_start = aliases;
- gtk_list_store_append (alias_list, &iter);
- gtk_list_store_set (alias_list, &iter,
- 0, (char *)aliases->data, -1);
- aliases = aliases->next;
- free_string_list (aliases_start);
- /* Finish up the checkbox stuff */
- g_signal_connect (G_OBJECT(checkbox), "clicked",
- G_CALLBACK(toggle_enable), vbox);
- if (!purple_prefs_get_bool (
- "/plugins/gtk/autoprofile/components/logstat/enabled")) {
- gtk_widget_set_sensitive (vbox, FALSE);
- gtk_widget_set_sensitive (vbox, TRUE);
--- a/autoprofile/comp_quotation.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,602 +0,0 @@
-/*----------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 "autoprofile.h"
- QUOTATION_LIST_STORE = 1,
- QUOTATION_FILE_SELECTOR,
-/*--------------------------------------------------------------------------*
- * Menu related things *
- *--------------------------------------------------------------------------*/
-static void append_quote (struct widget *w, GtkListStore *ls, gchar *quote)
- GtkTreeSelection *selection;
- gtk_list_store_append (ls, &iter);
- quote_tmp = purple_markup_strip_html (quote);
- g_string_printf (s, "%ld bytes", g_utf8_strlen (quote, -1));
- gtk_list_store_set (ls, &iter,
- g_string_free (s, TRUE);
- treeview = (GtkWidget *) ap_widget_get_data (w, QUOTATION_TREE_VIEW);
- if (treeview == NULL) return;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(treeview));
- gtk_tree_selection_select_iter (selection, &iter);
-static void file_dialog_cb (GtkWidget *dialog, int response, struct widget *w)
- GList *quotes, *quotes_start, *new_quotes;
- case GTK_RESPONSE_ACCEPT:
- ls = ap_widget_get_data (w, QUOTATION_LIST_STORE);
- filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(dialog));
- checkbox = gtk_file_chooser_get_extra_widget (GTK_FILE_CHOOSER(dialog));
- g_object_get (checkbox, "active", &include_html, NULL);
- quotes = ap_prefs_get_string_list (w, "quotes");
- new_quotes = read_fortune_file (filename, !include_html);
- quotes = g_list_concat (quotes, new_quotes);
- ap_prefs_set_string_list (w, "quotes", quotes);
- for (quotes = new_quotes; quotes != NULL; quotes = quotes->next) {
- append_quote (w, ls, quotes->data);
- free_string_list (quotes_start);
- case GTK_RESPONSE_CANCEL:
- case GTK_RESPONSE_DELETE_EVENT:
- ap_widget_set_data (w, QUOTATION_FILE_SELECTOR, NULL);
- gtk_widget_destroy (dialog);
-static void quotation_explain_fortune_file (GtkMenuItem *item, gpointer data)
- purple_notify_formatted (NULL, _("Fortune files"),
- _("A quick definition of a fortune file"), NULL,
- _("A fortune file is a simple text file with a number of quotes. "
- "The following is an example:<br><br>"
- "<b>\"Glory is fleeing, but obscurity is forver.\"<br>"
- "- Napoleon Bonaparte (1769-1821)<br>"
- "Yet another quote<br>"
- "Quotes can have any sort of text within them. They end when there "
- "is a newline followed by a percent sign \"%\" on the next line.<br>"
- "<br>Fortune files with pre-selected quotes can be found on the"
-static void quotation_select_import_file (GtkMenuItem *item, struct widget *w)
- dialog = gtk_file_chooser_dialog_new (
- _("Select fortune file to import quotes from"),
- GTK_FILE_CHOOSER_ACTION_OPEN,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
- g_signal_connect (G_OBJECT(dialog), "response", G_CALLBACK (file_dialog_cb),
- ap_widget_set_data (w, QUOTATION_FILE_SELECTOR, dialog);
- checkbox = gtk_check_button_new_with_label (
- _("Interpret bracketed text (such as \"<br>\") as HTML tags"));
- gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(dialog), checkbox);
- gtk_widget_show_all (dialog);
-static void quotation_edit_dialog_cb (struct widget *w, const char *quote)
- GtkTreeSelection *selection;
- treeview = (GtkWidget *) ap_widget_get_data (w, QUOTATION_TREE_VIEW);
- if (treeview == NULL) return;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(treeview));
- if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
- gchar *quote_tmp, *old_quote;
- gtk_tree_model_get (model, &iter, 1, &old_quote, -1);
- start = ap_prefs_get_string_list (w, "quotes");
- /* FIXME: this could grab the wrong quote, if two quotes are identical */
- for (node = start; node != NULL; node = node->next) {
- if (!strcmp ((char *) node->data, old_quote)) {
- /* Update saved prefs */
- node->data = strdup (quote);
- ap_prefs_set_string_list (w, "quotes", start);
- free_string_list (start);
- /* Update list store */
- quote_tmp = purple_markup_strip_html (quote);
- g_string_printf (s, "%ld bytes", g_utf8_strlen (quote, -1));
- gtk_list_store_set (GTK_LIST_STORE (model), &iter,
- g_string_free (s, TRUE);
- free_string_list (start);
- purple_notify_error (NULL, NULL,
- N_("Unable to edit quote"),
- N_("No quote is currently selected"));
-static void quotation_edit_dialog (struct widget *w, const gchar *quote)
- purple_request_input (ap_get_plugin_handle (), NULL,
- _("Save"), G_CALLBACK(quotation_edit_dialog_cb),
- _("Cancel"), NULL, NULL, NULL, NULL,
-static void quotation_edit (GtkWidget *button, struct widget *w)
- GtkTreeSelection *selection;
- treeview = (GtkWidget *) ap_widget_get_data (w, QUOTATION_TREE_VIEW);
- if (treeview == NULL) return;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(treeview));
- if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
- gtk_tree_model_get (model, &iter, 1, "e, -1);
- quotation_edit_dialog (w, quote);
- purple_notify_error (NULL, NULL,
- N_("Unable to edit quote"),
- N_("No quote is currently selected"));
-static void quotation_create (GtkWidget *button, struct widget *w)
- ls = ap_widget_get_data (w, QUOTATION_LIST_STORE);
- if (ls == NULL) return;
- append_quote (w, ls, "");
- quotes = ap_prefs_get_string_list (w, "quotes");
- quotes = g_list_append (quotes, strdup (""));
- ap_prefs_set_string_list (w, "quotes", quotes);
- free_string_list (quotes);
- quotation_edit_dialog (w, "");
-static void quotation_delete (GtkWidget *button, struct widget *w)
- GtkTreeSelection *selection;
- treeview = (GtkWidget *) ap_widget_get_data (w, QUOTATION_TREE_VIEW);
- if (treeview == NULL) return;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(treeview));
- if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
- gtk_tree_model_get (model, &iter, 1, "e, -1);
- start = ap_prefs_get_string_list (w, "quotes");
- /* FIXME: this could grab the wrong quote, if two quotes are identical */
- for (node = start; node != NULL; node = node->next) {
- if (!strcmp ((char *) node->data, quote)) {
- start = g_list_remove_link (start, node);
- ap_prefs_set_string_list (w, "quotes", start);
- free_string_list (start);
- gtk_list_store_remove (GTK_LIST_STORE(model), &iter);
- free_string_list (start);
- purple_notify_error (NULL, NULL,
- N_("Unable to delete quote"),
- N_("No quote is currently selected"));
-static void quotation_delete_all_cb (struct widget *w)
- ls = ap_widget_get_data (w, QUOTATION_LIST_STORE);
- if (ls == NULL) return;
- gtk_list_store_clear (ls);
- ap_prefs_set_string_list (w, "quotes", NULL);
-static void quotation_delete_all (GtkMenuItem *item, struct widget *w)
- purple_request_ok_cancel (ap_get_plugin_handle (),
- NULL, _("Delete all quotes?"), NULL, 0, NULL, NULL,
- NULL, w, G_CALLBACK(quotation_delete_all_cb), NULL);
-static void quotation_more_menu (GtkWidget *button, struct widget *w)
- menu = gtk_menu_new ();
- menu_item = gtk_menu_item_new_with_label (_("Delete all quotes"));
- gtk_menu_shell_append (GTK_MENU_SHELL(menu), menu_item);
- g_signal_connect (G_OBJECT(menu_item), "activate",
- G_CALLBACK(quotation_delete_all), w);
- menu_item = gtk_separator_menu_item_new ();
- gtk_menu_shell_append (GTK_MENU_SHELL(menu), menu_item);
- menu_item = gtk_menu_item_new_with_label (
- _("Import quotes from from fortune file"));
- gtk_menu_shell_append (GTK_MENU_SHELL(menu), menu_item);
- g_signal_connect (G_OBJECT(menu_item), "activate",
- G_CALLBACK(quotation_select_import_file), w);
- menu_item = gtk_menu_item_new_with_label (
- _("What is a fortune file?"));
- gtk_menu_shell_append (GTK_MENU_SHELL(menu), menu_item);
- g_signal_connect (G_OBJECT(menu_item), "activate",
- G_CALLBACK(quotation_explain_fortune_file), NULL);
- gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, w, 0,
- gtk_get_current_event_time ());
- gtk_widget_show_all (menu);
-static void quotation_rate_changed (GtkSpinButton *spinner, struct widget *w)
- int value = gtk_spin_button_get_value_as_int (spinner);
- ap_prefs_set_int (w, "update_rate", value);
-static void quotation_force_change (GtkButton *button, struct widget *w)
- ap_prefs_set_int (w, "current_index",
- ap_prefs_get_int (w, "current_index") + 1);
-search_func(GtkTreeModel *model, gint column, const gchar *key,
- GtkTreeIter *iter, gpointer search_data)
- gtk_tree_model_get (model, iter, 1, &haystack, -1);
- result = (purple_strcasestr(haystack, key) == NULL);
-static void menu_destroy_cb (GtkWidget *widget, struct widget *w)
- GtkWidget *file_selector;
- ap_widget_set_data (w, QUOTATION_LIST_STORE, NULL);
- ap_widget_set_data (w, QUOTATION_TREE_VIEW, NULL);
- file_selector = (GtkWidget *) ap_widget_get_data (w, QUOTATION_FILE_SELECTOR);
- if (file_selector != NULL) {
- file_dialog_cb (file_selector, GTK_RESPONSE_DELETE_EVENT, w);
-static GtkWidget *quotation_menu (struct widget *w)
- GtkWidget *button, *label, *spinner;
- GList *quotes, *quotes_start;
- GtkTreeViewColumn *col;
- ret = gtk_vbox_new (FALSE, 6);
- g_signal_connect (G_OBJECT(ret), "destroy", G_CALLBACK (menu_destroy_cb), w);
- sw = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(sw),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw),
- gtk_box_pack_start (GTK_BOX(ret), sw, TRUE, TRUE, 0);
- ls = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
- ap_widget_set_data (w, QUOTATION_LIST_STORE, ls);
- treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL(ls));
- ap_widget_set_data (w, QUOTATION_TREE_VIEW, treeview);
- rend = gtk_cell_renderer_text_new ();
- col = gtk_tree_view_column_new_with_attributes (_("Size"),
- rend, "text", 2, NULL);
- gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), col);
- g_object_set (G_OBJECT(rend),
- "cell-background-set", TRUE,
- "cell-background", "gray",
- rend = gtk_cell_renderer_text_new ();
- col = gtk_tree_view_column_new_with_attributes (_("Quotes"),
- rend, "text", 0, NULL);
- gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), col);
- /* Enable CTRL+F searching */
- gtk_tree_view_set_search_column (GTK_TREE_VIEW(treeview), 0);
- gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW(treeview),
- search_func, NULL, NULL);
- gtk_container_add (GTK_CONTAINER(sw), treeview);
- /* Add in the original quotes */
- quotes_start = ap_prefs_get_string_list (w, "quotes");
- for (quotes = quotes_start; quotes != NULL; quotes = quotes->next) {
- append_quote (w, ls, quotes->data);
- free_string_list (quotes_start);
- gtk_tree_view_set_rules_hint (GTK_TREE_VIEW(treeview), TRUE);
- hbox = gtk_hbutton_box_new ();
- gtk_button_box_set_layout (GTK_BUTTON_BOX(hbox),
- gtk_box_pack_start (GTK_BOX(ret), hbox, FALSE, FALSE, 0);
- button = gtk_button_new_with_label (_("New quote"));
- gtk_box_pack_start (GTK_BOX(hbox), button, FALSE, FALSE, 0);
- g_signal_connect (G_OBJECT(button), "clicked",
- G_CALLBACK(quotation_create), w);
- button = gtk_button_new_with_label (_("Edit"));
- gtk_box_pack_start (GTK_BOX(hbox), button, FALSE, FALSE, 0);
- g_signal_connect (G_OBJECT(button), "clicked",
- G_CALLBACK(quotation_edit), w);
- button = gtk_button_new_with_label (_("Delete"));
- gtk_box_pack_start (GTK_BOX(hbox), button, FALSE, FALSE, 0);
- g_signal_connect (G_OBJECT(button), "clicked",
- G_CALLBACK(quotation_delete), w);
- button = gtk_button_new_with_label (_("More..."));
- gtk_box_pack_start (GTK_BOX(hbox), button, FALSE, FALSE, 0);
- g_signal_connect (G_OBJECT(button), "clicked",
- G_CALLBACK(quotation_more_menu), w);
- gtk_box_pack_start (GTK_BOX(ret), gtk_hseparator_new (), FALSE, FALSE, 0);
- /* Behavior selection */
- hbox = gtk_hbox_new (FALSE, 5);
- gtk_box_pack_start (GTK_BOX(ret), hbox, FALSE, FALSE, 0);
- label = gtk_label_new (_("Change quote every "));
- gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 0);
- spinner = gtk_spin_button_new_with_range (0, G_MAXINT, 1);
- gtk_box_pack_start (GTK_BOX(hbox), spinner, FALSE, FALSE, 0);
- gtk_spin_button_set_value (GTK_SPIN_BUTTON(spinner),
- ap_prefs_get_int (w, "update_rate"));
- g_signal_connect (G_OBJECT(spinner), "value-changed",
- G_CALLBACK(quotation_rate_changed), w);
- label = gtk_label_new (_("hours (0: always show a new quote)"));
- gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 0);
- button = gtk_button_new_with_label (_("Change quote now"));
- gtk_box_pack_end (GTK_BOX(hbox), button, FALSE, FALSE, 0);
- g_signal_connect (G_OBJECT (button), "clicked",
- G_CALLBACK (quotation_force_change), w);
-/*--------------------------------------------------------------------------*
- * Core quotation things *
- *--------------------------------------------------------------------------*/
-static gchar *quotation_generate (struct widget *w)
- time_t cur_time, old_time;
- index = ap_prefs_get_int (w, "current_index");
- quotes = ap_prefs_get_string_list (w, "quotes");
- /* Sanity check the quotes */
- num_quotes = g_list_length (quotes);
- return strdup (_("[ERROR: no quotes available]"));
- /* Increment index if time has elapsed */
- old_time = purple_str_to_time (ap_prefs_get_string (w, "last_update"), TRUE,
- cur_time = time (NULL);
- if (difftime (cur_time, old_time) >
- 60.0 * 60.0 * (double) ap_prefs_get_int (w, "update_rate"))
- ap_debug ("quote", "time interval elapsed, moving to new quote");
- time_string = (char *)malloc(1000);
- t = ap_gmtime (&cur_time);
- strftime (time_string, 999, "%Y-%m-%dT%H:%M:%S+00:00", t);
- ap_prefs_set_string (w, "last_update", time_string);
- ap_prefs_set_int (w, "current_index", index);
- /* Wrap around when last quote is reached */
- if (index >= num_quotes) {
- ap_prefs_set_int (w, "current_index", 0);
- /* Choose and output the quote */
- ret = strdup((gchar *) g_list_nth_data (quotes, index));
- free_string_list (quotes);
-static void quotation_init (struct widget *w)
- time_string = (char *)malloc(1000);
- strftime (time_string, 999, "%Y-%m-%dT%H:%M:%S+00:00", gmtime (&the_time));
- ap_prefs_add_string_list (w, "quotes", NULL);
- ap_prefs_add_int (w, "current_index", 0);
- ap_prefs_add_int (w, "update_rate", 0);
- ap_prefs_add_string (w, "last_update", time_string);
-struct component quotation =
- N_("Displays a quotation from a provided selection"),
--- a/autoprofile/comp_rss.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,477 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 "autoprofile.h"
-static GtkWidget *entry_username = NULL;
-static GtkWidget *entry_url = NULL;
-GHashTable *rss_entries = NULL;
-static GHashTable *rss_timeouts = NULL;
-GStaticMutex rss_mutex = G_STATIC_MUTEX_INIT;
-static char *get_rss_data (struct widget *w, const char *field, int index,
- const struct rss_entry *e;
- g_static_mutex_lock (&rss_mutex);
- tmp = (GList *) g_hash_table_lookup (rss_entries, w);
- g_static_mutex_unlock (&rss_mutex);
- return strdup (_("[ERROR: Invalid entry number]"));
- g_static_mutex_unlock (&rss_mutex);
- return strdup (_("[ERROR: No data, invalid URL/account?]"));
- g_static_mutex_unlock (&rss_mutex);
- return strdup (_("[ERROR: Insufficient number of entries]"));
- e = (struct rss_entry *) tmp->data;
- if (!strcmp (field, "link")) {
- } else if (!strcmp (field, "title")) {
- ret = strdup (e->title);
- } else if (!strcmp (field, "entry")) {
- max = ap_prefs_get_int (w, "entry_limit");
- ret = strdup (e->entry);
- if (max < g_utf8_strlen (ret, -1)) {
- gchar *tmp = g_utf8_offset_to_pointer (ret, max);
- } else if (!strcmp (field, "time")) {
- g_static_mutex_unlock (&rss_mutex);
-static char *rss_generate (struct widget *w)
- format = ap_prefs_get_string (w, "format");
- output = g_string_new ("");
- time_tmp = (char *)malloc (sizeof(char)*AP_SIZE_MAXIMUM);
- if (isdigit (*format)) {
- count = (count * 10) + (int) *format - 48;
- tmp = get_rss_data (w, "time", count, &time);
- strftime (time_tmp, AP_SIZE_MAXIMUM, fmt_char, time);
- g_string_append_printf (output, "%s", time_tmp);
- tmp = get_rss_data (w, "link", count, NULL);
- g_string_append_printf (output, "%s", tmp);
- tmp = get_rss_data (w, "title", count, NULL);
- g_string_append_printf (output, "%s", tmp);
- tmp = get_rss_data (w, "entry", count, NULL);
- g_string_append_printf (output, "%s", tmp);
- g_string_append_printf (output, "%c", *format);
- g_string_append_unichar (output, g_utf8_get_char (format));
- format = g_utf8_next_char (format);
- g_string_append_unichar (output, g_utf8_get_char (format));
- format = g_utf8_next_char (format);
- g_string_free (output, FALSE);
-static gboolean rss_update (gpointer data)
- parse_rss ((struct widget *) data);
-static void rss_load (struct widget *w)
- g_static_mutex_lock (&rss_mutex);
- rss_entries = g_hash_table_new (NULL, NULL);
- rss_timeouts = g_hash_table_new (NULL, NULL);
- rss_timeout = GINT_TO_POINTER (g_timeout_add (
- ap_prefs_get_int (w, "update_rate") * 60 * 1000,
- g_hash_table_insert (rss_timeouts, w, rss_timeout);
- g_static_mutex_unlock (&rss_mutex);
-static void rss_unload (struct widget *w)
- g_static_mutex_lock (&rss_mutex);
- rss_timeout = g_hash_table_lookup (rss_timeouts, w);
- g_source_remove (GPOINTER_TO_INT (rss_timeout));
- g_hash_table_remove (rss_timeouts, w);
- g_static_mutex_unlock (&rss_mutex);
-static void rss_init (struct widget *w)
- ap_prefs_add_int (w, "type", RSS_XANGA);
- ap_prefs_add_string (w, "location", "");
- ap_prefs_add_string (w, "username", "");
- ap_prefs_add_string (w, "format",
- "My <a href=\"%l\">blog</a> was most recently updated on "
- "%1B %1d at %I:%M %p");
- ap_prefs_add_int (w, "update_rate", 5);
- ap_prefs_add_int (w, "entry_limit", 1000);
-static gboolean update_refresh_rate (GtkWidget *widget, GdkEventFocus *evt,
- minutes = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget));
- ap_prefs_set_int (w, "update_rate", minutes);
- // Kill the current timer and run a new one
- g_static_mutex_lock (&rss_mutex);
- timeout = g_hash_table_lookup (rss_timeouts, w);
- g_source_remove (GPOINTER_TO_INT(timeout));
- timeout = GINT_TO_POINTER (g_timeout_add (minutes * 60 * 1000,
- g_hash_table_replace (rss_timeouts, w, timeout);
- g_static_mutex_unlock (&rss_mutex);
-static void rss_data_update (GtkWidget *widget, struct widget *w)
-static void sensitivity_cb (const char *name, PurplePrefType type,
- gconstpointer val, gpointer data)
- int real_val = GPOINTER_TO_INT (val);
- if (real_val == RSS_XANGA || real_val == RSS_LIVEJOURNAL) {
- gtk_widget_set_sensitive (entry_username, TRUE);
- gtk_widget_set_sensitive (entry_url, FALSE);
- gtk_widget_set_sensitive (entry_username, FALSE);
- gtk_widget_set_sensitive (entry_url, TRUE);
-static GtkWidget *entry;
-static void event_cb (GtkWidget *widget, struct widget *w)
- ap_prefs_set_string (w, "format",
- gtk_imhtml_get_markup (GTK_IMHTML(entry)));
-static void formatting_toggle_cb (GtkIMHtml *imhtml,
- GtkIMHtmlButtons buttons, struct widget *w)
- ap_prefs_set_string (w, "format",
- gtk_imhtml_get_markup (GTK_IMHTML(entry)));
-static void formatting_clear_cb (GtkIMHtml *imhtml,
- ap_prefs_set_string (w, "format",
- gtk_imhtml_get_markup (GTK_IMHTML(entry)));
-static GtkWidget *rss_menu (struct widget *w)
- GtkWidget *label, *hbox, *button, *spinner, *sw;
- GtkWidget *entry_window, *toolbar;
- GtkTextBuffer *text_buffer;
- ret = gtk_vbox_new (FALSE, 5);
- label = gtk_label_new (NULL);
- gtk_label_set_markup (GTK_LABEL(label), "<b>Format string for output</b>");
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- gtk_box_pack_start (GTK_BOX(ret), label, FALSE, FALSE, 0);
- hbox = gtk_hbox_new (FALSE, 5);
- gtk_box_pack_start (GTK_BOX(ret), hbox, TRUE, TRUE, 0);
- entry_window = pidgin_create_imhtml (TRUE, &entry, &toolbar, &sw);
- gtk_box_pack_start (GTK_BOX (hbox), entry_window, TRUE, TRUE, 0);
- gtk_imhtml_append_text_with_images (GTK_IMHTML(entry),
- ap_prefs_get_string (w, "format"),
- text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (entry));
- g_signal_connect (G_OBJECT (text_buffer), "changed",
- G_CALLBACK (event_cb), w);
- g_signal_connect_after(G_OBJECT(entry), "format_function_toggle",
- G_CALLBACK(formatting_toggle_cb), w);
- g_signal_connect_after(G_OBJECT(entry), "format_function_clear",
- G_CALLBACK(formatting_clear_cb), w);
- label = gtk_label_new (_(
- "The following options can be specified with a numerical modifier\n"
- "(i.e. \"%e\" can also be written \"%1e\" or \"%2e\"). The optional\n"
- "number specifies which entry to get the data for. \"1\" refers to the\n"
- "most recent entry, \"2\" refers to the second-most recent entry, and so\n"
- "forth. \"1\" is used if no number is specified.\n\n"
- "%e\tStarting text of the entry.\n"
- "%l\tLink to the specific entry.\n"
- "%t\tTitle of entry (Xanga incompatible)\n"
- "%H\thour of entry(24-hour clock)\n"
- "%I\thour (12-hour clock)\n"
- "%a\tabbreviated weekday name\n"
- "%A\tfull weekday name\n"
- "%b\tabbreviated month name\n"
- "%B\tfull month name\n"
- "%m\tmonth (numerical)\n"
- "%d\tday of the month\n"
- "%j\tday of the year\n"
- "%W\tweek number of the year\n"
- "%w\tweekday (numerical)\n"
- "%y\tyear without century\n"
- "%Y\tyear with century\n"
- "%z\ttime zone name, if any\n"
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- sw = gtk_scrolled_window_new (NULL,NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
- GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
- gtk_box_pack_start (GTK_BOX (hbox), sw, TRUE, TRUE , 0);
- gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(sw), label);
- /* Type/URL/Username selection */
- label = gtk_label_new (NULL);
- gtk_label_set_markup (GTK_LABEL(label), "<b>RSS/Blog location</b>");
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- gtk_box_pack_start (GTK_BOX(ret), label, FALSE, FALSE, 0);
- hbox = gtk_hbox_new (FALSE, 5);
- gtk_box_pack_start (GTK_BOX(ret), hbox, FALSE, FALSE, 0);
- options = g_list_append (NULL, (char *) _("Xanga"));
- options = g_list_append (options, GINT_TO_POINTER(RSS_XANGA));
- options = g_list_append (options, (char *) _("LiveJournal"));
- options = g_list_append (options, GINT_TO_POINTER(RSS_LIVEJOURNAL));
- options = g_list_append (options, (char *) _("RSS 2.0"));
- options = g_list_append (options, GINT_TO_POINTER(RSS_2));
- ap_prefs_dropdown_from_list (w, hbox, NULL, PURPLE_PREF_INT, "type", options);
- pref = ap_prefs_get_pref_name (w, "type");
- purple_prefs_connect_callback (ap_get_plugin_handle (), pref,
- /* Username/URL fields */
- entry_username = ap_prefs_labeled_entry (w, hbox, _("Username:"),
- entry_url = ap_prefs_labeled_entry (w, hbox, _("URL of feed:"),
- value = ap_prefs_get_int (w, "type");
- if (value == RSS_XANGA || value == RSS_LIVEJOURNAL) {
- gtk_widget_set_sensitive (entry_username, TRUE);
- gtk_widget_set_sensitive (entry_url, FALSE);
- gtk_widget_set_sensitive (entry_username, FALSE);
- gtk_widget_set_sensitive (entry_url, TRUE);
- label = gtk_label_new (NULL);
- gtk_label_set_markup (GTK_LABEL(label), "<b>Other options</b>");
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- gtk_box_pack_start (GTK_BOX(ret), label, FALSE, FALSE, 0);
- /* # of chars to display from description */
- ap_prefs_labeled_spin_button (w, ret,
- "Max characters to show in entry (%e)", "entry_limit", 1,
- AP_SIZE_MAXIMUM - 1, NULL);
- /* Update rate selection */
- hbox = gtk_hbox_new (FALSE, 5);
- gtk_box_pack_start (GTK_BOX (ret), hbox, FALSE, FALSE, 0);
- label = gtk_label_new (_("Minutes between checks for updates:"));
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
- spinner = gtk_spin_button_new_with_range (1, 60, 1);
- gtk_box_pack_start (GTK_BOX(hbox), spinner, FALSE, FALSE, 0);
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinner),
- ap_prefs_get_int (w, "update_rate"));
- g_signal_connect (G_OBJECT (spinner), "value-changed",
- G_CALLBACK (update_refresh_rate), w);
- button = gtk_button_new_with_label ("Fetch data now!");
- g_signal_connect (G_OBJECT (button), "clicked",
- G_CALLBACK (rss_data_update), w);
- gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
- N_("Information taken from an RSS feed (Xanga and LiveJournal capable)"),
--- a/autoprofile/comp_rss.h Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 *
- *--------------------------------------------------------------------------*/
-#define MAX_USERNAME_LENGTH 1000
-extern GHashTable *rss_entries;
-extern GStaticMutex rss_mutex;
-void parse_rss (struct widget *);
-void parse_xanga_rss (struct widget *, gchar *);
-extern GMarkupParser rss_parser;
--- a/autoprofile/comp_rss_parser.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,352 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 "autoprofile.h"
-static gboolean parsing_rss = FALSE;
-static gboolean parsing_item = FALSE;
-static gboolean item_title = FALSE;
-static gboolean item_link = FALSE;
-static gboolean item_description = FALSE;
-static gboolean item_comments = FALSE;
-static gboolean item_pubdate = FALSE;
-/* Get URL of RSS feed */
-static char *get_url (struct widget *w)
- type = ap_prefs_get_int (w, "type");
- username = ap_prefs_get_string (w, "username");
- g_string_append_printf (s,
- "http://www.livejournal.com/users/%s/data/rss", username);
- username = ap_prefs_get_string (w, "username");
- g_string_append_printf (s, "http://www.xanga.com/%s/rss", username);
- g_string_append_printf (s, "%s", ap_prefs_get_string (w, "location"));
- g_string_free (s, FALSE);
-static void free_entries (struct widget *w) {
- entries = (GList *) g_hash_table_lookup (rss_entries, w);
- e = (struct rss_entry *) entries->data;
- entries = entries->next;
- g_hash_table_replace (rss_entries, w, NULL);
-/* Date parsing functions */
-static struct tm *parse_date_rfc822 (const char *date_string)
- time_t t, gmt_time, local_time;
- struct tm *ret, *result;
- local_time = time(NULL);
- gmt_time = mktime(gmtime(&gmt_time));
- // TODO: Change this to GDate
- t = rfc_parse_date_time (date_string);
- // if (rfc_parse_was_gmt ()) {
- // FIXME: Handle time zones
- ret = (struct tm *) malloc (sizeof (struct tm));
- result = localtime(&t);
- ret->tm_sec = result->tm_sec;
- ret->tm_min = result->tm_min;
- ret->tm_hour = result->tm_hour;
- ret->tm_mday = result->tm_mday;
- ret->tm_mon = result->tm_mon;
- ret->tm_year = result->tm_year;
-/* XML Parser Callbacks */
-static void start_element_handler (GMarkupParseContext *context,
- const gchar *element_name,
- const gchar **attribuate_names,
- const gchar **attribute_values,
- gpointer data, GError **error)
- struct widget *w = (struct widget *) data;
- //printf ("start:%s\n", element_name);
- if (!parsing_rss && !strcmp (element_name, "rss"))
- else if (parsing_rss && !parsing_item &&
- !strcmp (element_name, "item")) {
- e = (struct rss_entry *) malloc (sizeof(struct rss_entry));
- entries = (GList *) g_hash_table_lookup (rss_entries, w);
- entries = g_list_prepend (entries, e);
- g_hash_table_replace (rss_entries, w, entries);
- else if (parsing_item && !strcmp (element_name, "title"))
- else if (parsing_item && !strcmp (element_name, "link"))
- else if (parsing_item && !strcmp (element_name, "description"))
- item_description = TRUE;
- else if (parsing_item && !strcmp (element_name, "comments"))
- else if (parsing_item && !strcmp (element_name, "pubDate"))
-static void end_element_handler (GMarkupParseContext *context,
- const gchar *element_name,
- gpointer data, GError **error)
- struct widget *w = (struct widget *) w;
- //printf ("end:%s\n", element_name);
- if (!strcmp (element_name, "rss"))
- else if (!strcmp (element_name, "item"))
- else if (!strcmp (element_name, "title"))
- else if (!strcmp (element_name, "link"))
- else if (!strcmp (element_name, "description"))
- item_description = FALSE;
- else if (!strcmp (element_name, "comments"))
- else if (!strcmp (element_name, "pubDate"))
-static void text_handler (GMarkupParseContext *context,
- const gchar *text, gsize text_len,
- gpointer data, GError **error)
- struct widget *w = (struct widget *) data;
- entries = (GList *) g_hash_table_lookup (rss_entries, w);
- e = (struct rss_entry *) entries->data;
- e->url = g_strdup (text);
- else if (item_description) {
- e->entry = purple_unescape_html (text);
- // If there is a standard format for Xanga titles (there really isn't)
- // it will probably be devised from the actual content. Will be placed
- // here if there is proven demand.
- else if (item_comments) {
- e->comments = g_strdup (text);
- e->title = g_strdup (text);
- else if (item_pubdate) {
- e->t = parse_date_rfc822 (text);
-/* Final parser variable */
-GMarkupParser rss_parser =
-/* Callback for HTTP data fetcher */
-static void url_callback (PurpleUtilFetchUrlData *url_data, gpointer data,
- const char *text, size_t size, const gchar *error_message)
- GMarkupParseContext *context;
- gchar *filtered_text = NULL, *convert = NULL, *next = NULL;
- struct widget *w = (struct widget *) data;
- /* Make sure URL exists/connected to Internet */
- ap_debug ("rss", "error, unable to fetch page via internet");
- item_description = FALSE;
- g_static_mutex_lock (&rss_mutex);
- filtered_text = purple_utf8_salvage (text);
- *convert = purple_utf8_try_convert ("<");
- *next = g_utf8_strchr (filtered_text, 10, g_utf8_get_char (convert));
- g_static_mutex_unlock (&rss_mutex);
- if (ap_prefs_get_int (w, "type") == RSS_XANGA) {
- parse_xanga_rss (w, filtered_text);
- entries = (GList *) g_hash_table_lookup (rss_entries, w);
- entries = g_list_reverse (entries);
- g_hash_table_replace (rss_entries, w, entries);
- g_static_mutex_unlock (&rss_mutex);
- context = g_markup_parse_context_new (&rss_parser, 0, w, NULL);
- if (!g_markup_parse_context_parse (context, next, size, &err)) {
- g_markup_parse_context_free (context);
- ap_debug ("rss", "error, unable to start parser");
- ap_debug ("rss", err->message);
- if (!g_markup_parse_context_end_parse (context, &err)) {
- g_markup_parse_context_free (context);
- ap_debug ("rss", "error, unable to end parser");
- g_markup_parse_context_free (context);
- entries = (GList *) g_hash_table_lookup (rss_entries, w);
- entries = g_list_reverse (entries);
- g_hash_table_replace (rss_entries, w, entries);
- g_static_mutex_unlock (&rss_mutex);
-void parse_rss (struct widget *w)
- if (strcmp (url, "") != 0) {
- purple_util_fetch_url (url, TRUE, NULL, FALSE, url_callback, w);
--- a/autoprofile/comp_rss_xanga.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 "autoprofile.h"
-static gchar *convert_char;
-static gchar *find_next_tag (gchar *text) {
- return g_utf8_strchr (text, -1, g_utf8_get_char (convert_char));
-static gchar *find_end_of_tag (gchar *text) {
- return g_utf8_strchr (text, -1, g_utf8_get_char (convert_char));
-static gboolean starts_with (gchar *text, gchar letter) {
- *convert_char = letter;
- return (g_utf8_strchr (text, 1, g_utf8_get_char (convert_char)) == text);
-void parse_xanga_rss (struct widget *w, gchar *text) {
- gchar *next_tag, *end_prev_tag;
- gchar *tag_first_char, *tag_second_char;
- convert_char = (gchar *) malloc (sizeof(gchar) * 2);
- *(convert_char+1) = '\0';
- rss_parser.start_element (NULL, "rss", NULL, NULL, w, NULL);
- while ((next_tag = find_next_tag (end_prev_tag)) != NULL) {
- tag_first_char = g_utf8_next_char (next_tag);
- tag_second_char = g_utf8_next_char (tag_first_char);
- if (starts_with (tag_first_char, 't')) rss_parser.start_element (
- NULL, "title", NULL, NULL, w, NULL);
- else if (starts_with (tag_first_char, 'l')) rss_parser.start_element (
- NULL, "link", NULL, NULL, w, NULL);
- else if (starts_with (tag_first_char, 'p')) rss_parser.start_element (
- NULL, "pubDate", NULL, NULL, w, NULL);
- else if (starts_with (tag_first_char, 'd')) rss_parser.start_element (
- NULL, "description", NULL, NULL, w, NULL);
- else if (starts_with (tag_first_char, 'c')) rss_parser.start_element (
- NULL, "comments", NULL, NULL, w, NULL);
- else if (starts_with (tag_first_char, '/')) {
- rss_parser.text (NULL, end_prev_tag, -1, w, NULL);
- if (starts_with (tag_second_char, 't'))
- rss_parser.end_element (NULL, "title", w, NULL);
- else if (starts_with (tag_second_char, 'l'))
- rss_parser.end_element (NULL, "link", w, NULL);
- else if (starts_with (tag_second_char, 'p'))
- rss_parser.end_element (NULL, "pubDate", w, NULL);
- else if (starts_with (tag_second_char, 'd'))
- rss_parser.end_element (NULL, "description", w, NULL);
- else if (starts_with (tag_second_char, 'c'))
- rss_parser.end_element (NULL, "comments", w, NULL);
- else if (starts_with (tag_second_char, 'i')) {
- rss_parser.end_element (NULL, "item", w, NULL);
- // TODO: WARN USER IN THIS CASE
- if (starts_with (tag_first_char, 'i') &&
- starts_with (tag_second_char, 't')) {
- rss_parser.start_element (NULL, "item", NULL, NULL, w, NULL);
- if ((next_tag = find_end_of_tag (tag_first_char)) == NULL) {
- // TODO: NOTIFY USER THAT WE REACHED END
- end_prev_tag = g_utf8_next_char (next_tag);
--- a/autoprofile/comp_textfile.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,268 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 "../common/pp_internal.h"
-/*---------- TEXT FILE: Text from a file ----------*/
-static GtkWidget *file_entry;
-static GtkWidget *file_selector;
-/* Read file into string and return */
-char *text_file_generate (struct widget *w)
- gchar *text, *salvaged, *converted;
- int max = ap_prefs_get_int (w, "text_size");
- filename = ap_prefs_get_string (w, "text_file");
- if (!g_file_test (filename, G_FILE_TEST_EXISTS)) {
- return g_strdup (_("[ERROR: File does not exist]"));
- if (!g_file_get_contents (filename, &text, NULL, NULL)) {
- return g_strdup (_("[ERROR: Unable to open file]"));
- converted = purple_utf8_try_convert (text);
- if (converted != NULL) {
- if (strlen (text) > max) {
- salvaged = purple_utf8_salvage (text);
-static gboolean text_file_update (GtkWidget *widget, GdkEventFocus *evt,
- ap_prefs_set_string (w, "text_file",
- gtk_entry_get_text (GTK_ENTRY (file_entry)));
-static void text_file_filename (GtkWidget *widget, gpointer user_data) {
- const gchar *selected_filename;
- struct widget *w = (struct widget *) user_data;
- selected_filename = gtk_file_selection_get_filename (
- GTK_FILE_SELECTION (file_selector));
- ap_prefs_set_string (w, "text_file", selected_filename);
- gtk_entry_set_text (GTK_ENTRY (file_entry), selected_filename);
-/* Creates and pops up file selection dialog for fortune file */
-static void text_file_selection (GtkWidget *widget, gpointer user_data) {
- struct widget *w = (struct widget *) user_data;
- /* Create the selector */
- file_selector = gtk_file_selection_new (
- "Select a text file with content");
- cur_file = ap_prefs_get_string (w, "text_file");
- if (cur_file && strlen (cur_file) > 1) {
- gtk_file_selection_set_filename (
- GTK_FILE_SELECTION (file_selector), cur_file);
- g_signal_connect (GTK_OBJECT(
- GTK_FILE_SELECTION(file_selector)->ok_button),
- "clicked", G_CALLBACK (text_file_filename), w);
- /* Destroy dialog box when the user clicks button. */
- g_signal_connect_swapped (GTK_OBJECT(
- GTK_FILE_SELECTION(file_selector)->ok_button),
- "clicked", G_CALLBACK (gtk_widget_destroy), (gpointer) file_selector);
- g_signal_connect_swapped (GTK_OBJECT (
- GTK_FILE_SELECTION (file_selector)->cancel_button),
- "clicked", G_CALLBACK (gtk_widget_destroy), (gpointer) file_selector);
- gtk_widget_show (file_selector);
-/* Pop up message with instructions */
-static void text_file_info_button (GtkButton *button, gpointer data)
- if (!strcmp ((char *) data, "itunes")) {
- purple_notify_formatted (NULL, _("iTunes"), _("Current song in iTunes"), NULL,
- _("Get TuneCam from <a href=\""
- "http://www.soft-o-mat.com/productions.shtml\">"
- "http://www.soft-o-mat.com/productions.shtml</a> and start it.<br>"
- "Create a html file that contains the following text:<br><br><tc"
- ">artist</tc> - <tc>title</tc><br><br>and "
- "press the \"T\" button. Import the html file as a template for "
- "the \"File Track\" and whatever else you see fit. Then select "
- "the \"G\" button and choose the location of the output file which "
- "will be used in this component"),
- } else if (!strcmp ((char *) data, "xmms")) {
- purple_notify_formatted (NULL, _("XMMS"), _("Current song in XMMS"), NULL,
- _("Included in the misc folder of AutoProfile is a script called \""
- "xmms_currenttrack\". Install this script in your $PATH and give it "
- "executable permissions, and specify the program using a pipe.<br><br>"
- "Alternatively, in XMMS, go to Options->Preferences->Effects/General "
- "Plugins.<br>Configure the \"Song Change\" plugin. In the song change"
- " command box, put<br><br>echo \"%s\" > /path/to/output/file<br><br>"
- "and be sure to enable the plugin. Select the file location in "
- "AutoProfile and you should be done"),
- } else if (!strcmp ((char *) data, "wmp")) {
- purple_notify_formatted (NULL, _("Windows Media Player"),
- _("Current song in Windows Media Player"), NULL,
- _("Download NowPlaying, a plugin for WMP from <a href=\""
- "http://www.wmplugins.com/ItemDetail.aspx?ItemID=357\">"
- "http://www.wmplugins.com/ItemDetail.aspx?ItemID=357</a> and follow "
- "the included installation instructions.<br>Set the output filename "
- "to the file you choose in this component"),
- } else if (!strcmp ((char *) data, "amip")) {
- purple_notify_formatted (NULL, _("iTunes/Winamp/Foobar/Apollo/QCD"),
- _("Current song in iTunes/Winamp/Foobar/Apollo/QCD"), NULL,
- _("Get the version of AMIP associated with your player from <a href=\""
- "http://amip.tools-for.net/\">"
- "http://amip.tools-for.net/</a> and install/"
- "Check the box \"Write song info to file\", play with the settings, "
- "and set the file in this component to be the file in the AMIP "
-GtkWidget *text_file_menu (struct widget *w)
- GtkWidget *ret = gtk_vbox_new (FALSE, 5);
- GtkWidget *hbox, *label, *button;
- label = gtk_label_new (_("Select text file with source content"));
- gtk_box_pack_start (GTK_BOX (ret), label, FALSE, FALSE, 0);
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- hbox = gtk_hbox_new (FALSE, 5);
- gtk_box_pack_start (GTK_BOX (ret), hbox, FALSE, FALSE, 0);
- /* Text entry to type in file name */
- file_entry = gtk_entry_new ();
- gtk_box_pack_start (GTK_BOX (hbox), file_entry, FALSE, FALSE, 0);
- gtk_entry_set_text (GTK_ENTRY (file_entry),
- ap_prefs_get_string (w, "text_file"));
- g_signal_connect (G_OBJECT (file_entry), "focus-out-event",
- G_CALLBACK (text_file_update), w);
- /* Button to bring up file select dialog */
- button = gtk_button_new_with_label ("Browse ...");
- g_signal_connect (G_OBJECT (button), "clicked",
- G_CALLBACK (text_file_selection), w);
- gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
- ap_prefs_labeled_spin_button (w, ret,
- _("Max characters to read from file:"), "text_size",
- 1, AP_SIZE_MAXIMUM - 1, NULL);
- gtk_box_pack_start (GTK_BOX (ret),
- gtk_hseparator_new (), 0, 0, 0);
- label = gtk_label_new (_("Windows users: Play the current song in:"));
- gtk_box_pack_start (GTK_BOX (ret), label, FALSE, FALSE, 0);
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- hbox = gtk_hbox_new (FALSE, 5);
- gtk_box_pack_start (GTK_BOX (ret), hbox, FALSE, FALSE, 0);
- button = gtk_button_new_with_label ("iTunes/Winamp/Foobar/Apollo/QCD");
- g_signal_connect (G_OBJECT (button), "clicked",
- G_CALLBACK (text_file_info_button), "amip");
- gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
- button = gtk_button_new_with_label ("Windows Media Player");
- g_signal_connect (G_OBJECT (button), "clicked",
- G_CALLBACK (text_file_info_button), "wmp");
- gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
- hbox = gtk_hbox_new (FALSE, 5);
- gtk_box_pack_start (GTK_BOX (ret), hbox, FALSE, FALSE, 0);
- label = gtk_label_new (_("*nix users: Play the current song in:"));
- gtk_box_pack_start (GTK_BOX (ret), label, FALSE, FALSE, 0);
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- hbox = gtk_hbox_new (FALSE, 5);
- gtk_box_pack_start (GTK_BOX (ret), hbox, FALSE, FALSE, 0);
- button = gtk_button_new_with_label ("XMMS");
- g_signal_connect (G_OBJECT (button), "clicked",
- G_CALLBACK (text_file_info_button), "xmms");
- gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
- label = gtk_label_new (_("OS X users: Play the current song in:"));
- gtk_box_pack_start (GTK_BOX (ret), label, FALSE, FALSE, 0);
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- hbox = gtk_hbox_new (FALSE, 5);
- gtk_box_pack_start (GTK_BOX (ret), hbox, FALSE, FALSE, 0);
- button = gtk_button_new_with_label ("iTunes");
- g_signal_connect (G_OBJECT (button), "clicked",
- G_CALLBACK (text_file_info_button), "itunes");
- gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
-void text_file_init (struct widget *w) {
- ap_prefs_add_string (w, "text_file", "");
- ap_prefs_add_int (w, "text_size", AP_SIZE_MAXIMUM - 1);
- N_("Text File / Songs"),
- N_("Copies text from file that external programs "
- "(e.g. XMMS, Winamp, iTunes) can modify on a regular basis"),
--- a/autoprofile/comp_timestamp.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 "../common/pp_internal.h"
-/*---------- TIMESTAMP: Display time at creation ---------------------------*/
-static char *timestamp_generate (struct widget *w) {
- time_t *general_time = (time_t *)malloc(sizeof(time_t));
- cur_time = ap_localtime (general_time);
- ret = (char *)malloc (AP_SIZE_MAXIMUM);
- strftime (ret, AP_SIZE_MAXIMUM - 1,
- ap_prefs_get_string (w, "timestamp_format"),
-static void timestamp_init (struct widget *w) {
- ap_prefs_add_string (w, "timestamp_format",
- "Automatically created at %I:%M %p");
-static GtkWidget *entry;
-static void event_cb (GtkWidget *widget, struct widget *w)
- ap_prefs_set_string (w, "timestamp_format",
- gtk_imhtml_get_markup (GTK_IMHTML(entry)));
-static void formatting_toggle_cb (GtkIMHtml *imhtml,
- GtkIMHtmlButtons buttons, struct widget *w)
- ap_prefs_set_string (w, "timestamp_format",
- gtk_imhtml_get_markup (GTK_IMHTML(entry)));
-static void formatting_clear_cb (GtkIMHtml *imhtml,
- ap_prefs_set_string (w, "timestamp_format",
- gtk_imhtml_get_markup (GTK_IMHTML(entry)));
-static GtkWidget *timestamp_menu (struct widget *w)
- GtkWidget *ret = gtk_vbox_new (FALSE, 5);
- GtkWidget *entry_window, *toolbar;
- GtkTextBuffer *text_buffer;
- entry_window = pidgin_create_imhtml (TRUE, &entry, &toolbar, &sw);
- gtk_box_pack_start (GTK_BOX (ret), entry_window, FALSE, FALSE, 0); gtk_imhtml_append_text_with_images (GTK_IMHTML(entry),
- ap_prefs_get_string (w, "timestamp_format"),
- text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (entry));
- g_signal_connect (G_OBJECT (text_buffer), "changed",
- G_CALLBACK (event_cb), w);
- g_signal_connect_after(G_OBJECT(entry), "format_function_toggle",
- G_CALLBACK(formatting_toggle_cb), w);
- g_signal_connect_after(G_OBJECT(entry), "format_function_clear",
- G_CALLBACK(formatting_clear_cb), w);
- label = gtk_label_new (_(
- "Insert the following characters where time is to be displayed:\n\n"
- "%H\thour (24-hour clock)\n"
- "%I\thour (12-hour clock)\n"
- "%a\tabbreviated weekday name\n"
- "%A\tfull weekday name\n"
- "%b\tabbreviated month name\n"
- "%B\tfull month name\n"
- "%m\tmonth (numerical)\n"
- "%d\tday of the month\n"
- "%j\tday of the year\n"
- "%W\tweek number of the year\n"
- "%w\tweekday (numerical)\n"
- "%y\tyear without century\n"
- "%Y\tyear with century\n"
- "%z\ttime zone name, if any\n"
- sw = gtk_scrolled_window_new (NULL,NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
- GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
- gtk_box_pack_start (GTK_BOX (ret), sw, TRUE, TRUE , 0);
- gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(sw), label);
-struct component timestamp =
- N_("Displays custom text showing when message was created"),
--- a/autoprofile/comp_uptime.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 "../common/pp_internal.h"
-/*---------- UPTIME: Display the computer uptime --*/
-char *uptime_generate (struct widget *w) {
- char *out, *line, *working;
- char *p_character, *colon_character, *comma_character, *m_character;
- exec = g_spawn_command_line_sync (line,
- &out, NULL, NULL, &return_error);
- /* Buffer length for safety */
- working = (char *)malloc (strlen (out)+7+8+8+1);
- strcpy (working, "Uptime:");
- /* Break into minutes, hours, and everything else */
- p_character = strchr (out, 'p');
- m_character = strchr (p_character, 'm');
- /* Uptime format including "pm" */
- if (m_character != NULL && m_character == p_character + 1) {
- p_character = strchr (m_character, 'p');
- m_character = strchr (p_character, 'm');
- /* Uptime if < 1 hour */
- if (m_character != NULL && *(m_character+1) == 'i') {
- strcat (working, p_character);
- strcat (working, "minutes");
- colon_character = strchr (p_character, ':');
- comma_character = strchr (colon_character, ',');
- *colon_character++ = '\0';
- *comma_character = '\0';
- /* Yank it all together */
- strcat (working, p_character);
- strcat (working, " hours, ");
- strcat (working, colon_character);
- strcat (working, " minutes");
- ap_debug ("uptime", "command failed to execute");
- return g_strdup(_("[ERROR: failed to execute uptime command]"));
-struct component uptime =
- N_("Show how long your computer has been running"),
--- a/autoprofile/component.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 "autoprofile.h"
-static GList *components = NULL;
-static GList *get_components ();
-void ap_component_start () {
- if (components) g_list_free (components);
- components = get_components ();
-void ap_component_finish () {
- g_list_free (components);
-GList *ap_component_get_components () {
-struct component *ap_component_get_component (const gchar *identifier) {
- struct component *cur_comp;
- for (comps = components; comps != NULL; comps = comps->next) {
- cur_comp = (struct component *) comps->data;
- if (!strcmp (cur_comp->identifier, identifier))
-static GList *get_components ()
- /* Add each listed component */
- XXX BEFORE YOU UNCOMMENT THIS, FIX THE IDENTIFIERS in logstats
- ret = g_list_append (ret, &logstats);
- ret = g_list_append (ret, &text);
- ret = g_list_append (ret, "ation);
- ret = g_list_append (ret, &rss);
- ret = g_list_append (ret, ×tamp);
- ret = g_list_append (ret, &http);
- ret = g_list_append (ret, &count);
- ret = g_list_append (ret, &executable);
- ret = g_list_append (ret, &uptime);
--- a/autoprofile/component.h Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 *
- *--------------------------------------------------------------------------*/
-#ifndef _AP_COMPONENT_H_
-#define _AP_COMPONENT_H_
-# include "../pp_config.h"
-/* A component is composed of code that generates some sort of content,
- and a widget is a specific _instance_ of a component */
- char *(*generate)(struct widget *);
- void (*init_pref)(struct widget *);
- void (*load)(struct widget *);
- void (*unload)(struct widget *);
- gboolean (*has_content_changed)(struct widget *);
- GtkWidget *(*pref_menu)(struct widget *);
-void ap_component_start ();
-void ap_component_finish ();
-GList *ap_component_get_components ();
-struct component *ap_component_get_component (const gchar *);
-extern struct component logstats;
-extern struct component count;
-extern struct component executable;
-extern struct component http;
-extern struct component quotation;
-extern struct component rss;
-extern struct component text;
-extern struct component timestamp;
-extern struct component uptime;
-#endif /* _AP_COMPONENT_H_ */
--- a/autoprofile/gtk_actions.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,341 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 "autoprofile.h"
-#include "gtkimhtmltoolbar.h"
-static GtkWidget *current_profile = NULL;
-static GtkWidget *accounts_dialog = NULL;
-static GtkWidget *content_win = NULL;
-/*--------------------------------------------------------------------------*
- * Accounts edit popup window *
- *--------------------------------------------------------------------------*/
-static void accounts_response_cb (GtkWidget *d, int response, gpointer data)
- gtk_widget_destroy (accounts_dialog);
- accounts_dialog = NULL;
-static void display_accounts_dialog () {
- if (accounts_dialog != NULL) {
- gtk_window_present (GTK_WINDOW (accounts_dialog));
- accounts_dialog = gtk_dialog_new_with_buttons (_("Edit Profile Accounts"),
- NULL, GTK_DIALOG_NO_SEPARATOR, NULL, NULL);
- gtk_dialog_set_has_separator (GTK_DIALOG(accounts_dialog), TRUE);
- gtk_dialog_add_button (GTK_DIALOG(accounts_dialog), GTK_STOCK_OK,
- label = gtk_label_new ("");
- gtk_label_set_markup (GTK_LABEL (label),
- _("<b>No accounts currently enabled:</b> You have not yet specified\n "
- "what accounts AutoProfile should set the profile for. Until you\n "
- "check one of the boxes below, AutoProfile will effectively do\n "
- gtk_box_pack_start (GTK_BOX(GTK_DIALOG(accounts_dialog)->vbox), label,
- gtk_box_pack_start (GTK_BOX(GTK_DIALOG(accounts_dialog)->vbox),
- get_account_page (), TRUE, TRUE, 0);
- g_signal_connect (G_OBJECT(accounts_dialog), "response",
- G_CALLBACK(accounts_response_cb), NULL);
- gtk_window_set_default_size (GTK_WINDOW(accounts_dialog), 400, 450);
- gtk_widget_show_all (accounts_dialog);
-/*--------------------------------------------------------------------------*
- * Profile edit window *
- *--------------------------------------------------------------------------*/
-/* Callbacks for refreshing profile preview window */
-static void refresh_preview (GtkWidget *preview) {
- // TODO: See if a delay timeout is necessary here
- if (preview == NULL || current_profile == NULL) return;
- gtk_imhtml_clear (GTK_IMHTML(preview));
- input = gtk_imhtml_get_markup ((GtkIMHtml *) current_profile);
- output = ap_generate (input, AP_SIZE_PROFILE_MAX);
- gtk_imhtml_append_text (GTK_IMHTML(preview), output,
-static void refresh_cb (GtkWidget *widget, gpointer data)
- refresh_preview ((GtkWidget *) data);
-static void event_cb (GtkWidget *widget, gpointer data)
- refresh_preview ((GtkWidget *) data);
-static void formatting_toggle_cb (GtkIMHtml *imhtml,
- GtkIMHtmlButtons buttons, gpointer data)
- refresh_preview ((GtkWidget *) data);
-static void formatting_clear_cb (GtkIMHtml *imhtml, gpointer data)
- refresh_preview ((GtkWidget *) data);
-static void revert_cb (GtkWidget *button, GtkWidget *imhtml)
- gtk_imhtml_clear (GTK_IMHTML(imhtml));
- gtk_imhtml_append_text_with_images (GTK_IMHTML(imhtml),
- purple_prefs_get_string ("/plugins/gtk/autoprofile/profile"),
-static void save_cb (GtkWidget *button, GtkWidget *imhtml)
- if (imhtml == NULL) return;
- new_text = gtk_imhtml_get_markup ((GtkIMHtml *) imhtml);
- purple_prefs_set_string ("/plugins/gtk/autoprofile/profile", new_text);
- if (NULL == purple_prefs_get_string_list (
- "/plugins/gtk/autoprofile/profile_accounts")) {
- // If no accounts set, ask for one!
- display_accounts_dialog ();
-/* Profile edit window */
-static GtkWidget *get_profile_page ()
- GtkWidget *hbox, *vbox, *dialog_box, *preview, *edit_window;
- GtkWidget *label, *sw, *toolbar, *bbox;
- GtkWidget *refresh_button, *revert_button, *save_button;
- GtkTextBuffer *text_buffer;
- ret = gtk_vbox_new (FALSE, 6);
- dialog_box = gtk_vbox_new (FALSE, 4);
- gtk_container_set_border_width (GTK_CONTAINER(dialog_box), 6);
- gtk_box_pack_start (GTK_BOX(ret), dialog_box, TRUE, TRUE, 0);
- hbox = gtk_hbox_new (FALSE, 0);
- gtk_box_pack_start (GTK_BOX(dialog_box), hbox, FALSE, FALSE, 0);
- label = gtk_label_new ("");
- gtk_label_set_markup (GTK_LABEL(label), _("<b>Preview</b>"));
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 0);
- refresh_button = gtk_button_new_with_label (_("Refresh"));
- gtk_box_pack_end (GTK_BOX(hbox), refresh_button, FALSE, FALSE, 0);
- sw = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(sw),
- GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw),
- gtk_box_pack_start (GTK_BOX(dialog_box), sw, TRUE, TRUE, 0);
- preview = gtk_imhtml_new (NULL, NULL);
- gtk_container_add (GTK_CONTAINER(sw), preview);
- pidgin_setup_imhtml (preview);
- gtk_imhtml_append_text (GTK_IMHTML(preview),
- purple_prefs_get_string ("/plugins/gtk/autoprofile/profile"),
- gtk_box_pack_start (GTK_BOX(ret), gtk_hseparator_new (), FALSE, FALSE, 0);
- dialog_box = gtk_vbox_new (FALSE, 6);
- gtk_container_set_border_width (GTK_CONTAINER(dialog_box), 6);
- gtk_box_pack_start (GTK_BOX(ret), dialog_box, TRUE, TRUE, 0);
- label = gtk_label_new ("");
- gtk_label_set_markup (GTK_LABEL(label),
- _("<b>Edit</b> (Drag widgets into profile / "
- "Use shift+enter to insert a new line)"));
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- gtk_box_pack_start (GTK_BOX(dialog_box), label, FALSE, FALSE, 0);
- hbox = gtk_hbox_new (FALSE, 6);
- gtk_box_pack_start (GTK_BOX(dialog_box), hbox, TRUE, TRUE, 0);
- vbox = gtk_vbox_new (FALSE, 6);
- gtk_box_pack_start (GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
- get_widget_list (vbox, &sel);
- bbox = gtk_hbox_new (FALSE, 6);
- gtk_box_pack_start (GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
- revert_button = gtk_button_new_with_label (_("Revert"));
- gtk_box_pack_start (GTK_BOX(bbox), revert_button, TRUE, TRUE, 0);
- save_button = gtk_button_new_with_label (_("Save profile"));
- gtk_box_pack_start (GTK_BOX(bbox), save_button, TRUE, TRUE, 0);
- edit_window = pidgin_create_imhtml (TRUE, ¤t_profile, &toolbar,
- gtk_box_pack_start (GTK_BOX(hbox), edit_window, TRUE, TRUE, 0);
- g_signal_connect (G_OBJECT(save_button), "clicked",
- G_CALLBACK(save_cb), current_profile);
- g_signal_connect (G_OBJECT(revert_button), "clicked",
- G_CALLBACK(revert_cb), current_profile);
- g_signal_connect (G_OBJECT (refresh_button), "clicked",
- G_CALLBACK (refresh_cb), preview);
- text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (current_profile));
- g_signal_connect (G_OBJECT (text_buffer), "changed",
- G_CALLBACK (event_cb), preview);
- g_signal_connect_after(G_OBJECT(current_profile), "format_function_toggle",
- G_CALLBACK(formatting_toggle_cb), preview);
- g_signal_connect_after(G_OBJECT(current_profile), "format_function_clear",
- G_CALLBACK(formatting_clear_cb), preview);
- revert_cb (revert_button, current_profile);
- refresh_cb (refresh_button, preview);
-/*--------------------------------------------------------------------------*
- * General edit window *
- *--------------------------------------------------------------------------*/
-ap_edit_content_destroy (GtkWidget *button, GtkWidget *window)
- gtk_widget_destroy (content_win);
- done_with_widget_list ();
- current_profile = NULL;
-static void ap_edit_content_show ()
- gtk_window_present (GTK_WINDOW(content_win));
- /* Create the window */
- content_win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- gtk_window_set_role (GTK_WINDOW(content_win), "ap_edit_content");
- gtk_window_set_title (GTK_WINDOW(content_win), _("Edit Content"));
- gtk_window_set_default_size (GTK_WINDOW(content_win), 700, 550);
- gtk_container_set_border_width (GTK_CONTAINER(content_win), 6);
- g_signal_connect (G_OBJECT(content_win), "destroy",
- G_CALLBACK(ap_edit_content_destroy), NULL);
- vbox = gtk_vbox_new (FALSE, 6);
- gtk_container_add (GTK_CONTAINER(content_win), vbox);
- notebook = gtk_notebook_new ();
- gtk_box_pack_start (GTK_BOX (vbox), notebook, TRUE, TRUE, 0);
- gtk_notebook_append_page (GTK_NOTEBOOK(notebook),
- ap_widget_get_config_page (), gtk_label_new (_("Widgets")));
- gtk_notebook_append_page (GTK_NOTEBOOK(notebook), get_profile_page (),
- gtk_label_new (_("Info/profile")));
- /* The buttons to press! */
- bbox = gtk_hbutton_box_new ();
- gtk_box_set_spacing (GTK_BOX(bbox), PIDGIN_HIG_BOX_SPACE);
- gtk_button_box_set_layout (GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
- gtk_box_pack_start (GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
- button = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
- g_signal_connect (G_OBJECT(button), "clicked",
- G_CALLBACK(ap_edit_content_destroy), NULL);
- gtk_box_pack_start (GTK_BOX(bbox), button, FALSE, FALSE, 0);
- gtk_widget_show_all (content_win);
-/*--------------------------------------------------------------------------*
- * The actions themselves *
- *--------------------------------------------------------------------------*/
-static void edit_content (PurplePluginAction *action)
- ap_edit_content_show ();
-static void edit_preferences (PurplePluginAction *action)
- ap_preferences_display ();
-static void make_visible (PurplePluginAction *action)
- ap_gtk_make_visible ();
-/* Return the actions */
-GList *actions (PurplePlugin *plugin, gpointer context)
- PurplePluginAction *act;
- act = purple_plugin_action_new (_("Edit Content"), edit_content);
- list = g_list_append (list, act);
- act = purple_plugin_action_new (_("Preferences"), edit_preferences);
- list = g_list_append (list, act);
- act = purple_plugin_action_new (_("Show summary"), make_visible);
- list = g_list_append (list, act);
-void ap_actions_finish ()
- if (content_win) ap_edit_content_destroy (NULL, NULL);
- if (accounts_dialog) accounts_response_cb (NULL, 0, NULL);
--- a/autoprofile/gtk_away_msgs.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,487 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 "autoprofile.h"
-/* VARIABLE DEFINITIONS */
-static guint queue_pref_cb = 0;
-static guint sound_pref_cb = 0;
-static gboolean ap_previously_away = FALSE;
-/* The list containing data on generated profiles / status messages */
-static GtkListStore *message_list = NULL;
-/* The general window */
-static GtkWidget *dialog = NULL;
-typedef struct _ap_progress_bar {
-static GHashTable *progress_bars = NULL;
-/*--------------------------------------------------------------------------*
- *--------------------------------------------------------------------------*/
-static void hide_cb (GtkButton *button, gpointer data) {
- gtk_widget_hide_all (dialog);
- const char *name, PurplePrefType type, gconstpointer val, gpointer data)
- const char *name, PurplePrefType type, gconstpointer val, gpointer data)
- button = (GtkWidget *) data;
- value = purple_prefs_get_bool ("/purple/sound/while_away");
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), value);
-static void update_summary_visibility ()
- const gchar *summary_pref;
- // Decide whether or not to show window
- summary_pref = purple_prefs_get_string (
- "/plugins/gtk/autoprofile/show_summary");
- if (!strcmp (summary_pref, "always")) {
- gtk_widget_show_all (dialog);
- } else if (!strcmp (summary_pref, "away") && ap_is_currently_away ()) {
- gtk_widget_show_all (dialog);
- gtk_widget_hide_all (dialog);
- ap_previously_away = ap_is_currently_away ();
-/*--------------------------------------------------------------------------*
- * Displayed message stuff *
- *--------------------------------------------------------------------------*/
-static void display_diff_msg (GtkTreeSelection *select, gpointer data)
- GtkWidget *imhtml = (GtkWidget *) data;
- if (gtk_tree_selection_get_selected (select, &model, &iter))
- gtk_tree_model_get (model, &iter, 3, &string, -1);
- gtk_imhtml_clear (GTK_IMHTML(imhtml));
- gtk_imhtml_append_text (GTK_IMHTML(imhtml), string,
- gtk_imhtml_append_text (GTK_IMHTML(imhtml), "<BR>",
-/*--------------------------------------------------------------------------*
- *--------------------------------------------------------------------------*/
-static APProgressBar *progress_create (APUpdateType type,
- APProgressBar *progress_bar;
- progress_bar = (APProgressBar *) malloc (sizeof (APProgressBar));
- progress_bar->timeout = 0;
- progress_bar->type = type;
- progress_bar->bar = gtk_progress_bar_new ();
- gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR(progress_bar->bar), GTK_PROGRESS_CONTINUOUS);
- gtk_box_pack_start (GTK_BOX(container), progress_bar->bar, FALSE, FALSE, 0);
- if (type == AP_UPDATE_PROFILE) {
- gtk_progress_bar_set_text (GTK_PROGRESS_BAR (progress_bar->bar),
- _("no updates made to profile"));
- } else if (type == AP_UPDATE_STATUS) {
- gtk_progress_bar_set_text (GTK_PROGRESS_BAR (progress_bar->bar),
- _("no updates made to status"));
- g_hash_table_insert (progress_bars, GINT_TO_POINTER(type), progress_bar);
-static void progress_update_stop (APProgressBar *progress_bar) {
- if (progress_bar->timeout) {
- purple_timeout_remove (progress_bar->timeout);
- progress_bar->timeout = 0;
- gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(progress_bar->bar), 1.0);
- if (progress_bar->type == AP_UPDATE_PROFILE) {
- gtk_progress_bar_set_text (GTK_PROGRESS_BAR (progress_bar->bar),
- _("waiting for new profile content"));
- } else if (progress_bar->type == AP_UPDATE_STATUS) {
- gtk_progress_bar_set_text (GTK_PROGRESS_BAR (progress_bar->bar),
- _("waiting for new status content"));
-static gboolean progress_update (gpointer data) {
- int total_milliseconds;
- double fraction_increment;
- APProgressBar *progress_bar = (APProgressBar *) data;
- // Update fraction on bar
- purple_prefs_get_int ("/plugins/gtk/autoprofile/delay_update") * 1000;
- fraction_increment = BAH / ((double) total_milliseconds);
- cur_fraction = gtk_progress_bar_get_fraction (
- GTK_PROGRESS_BAR(progress_bar->bar));
- result = cur_fraction + fraction_increment;
- progress_update_stop (progress_bar);
- gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(progress_bar->bar), result);
- seconds_remaining = (int)
- (((double) total_milliseconds / 1000) -
- (cur_fraction * (double) total_milliseconds / 1000));
- text = g_string_new ("");
- if (progress_bar->type == AP_UPDATE_PROFILE) {
- g_string_printf (text, _("next profile update in %d seconds"),
- } else if (progress_bar->type == AP_UPDATE_STATUS) {
- g_string_printf (text, _("next status update in %d seconds"),
- gtk_progress_bar_set_text (GTK_PROGRESS_BAR (progress_bar->bar), text->str);
- g_string_free (text, TRUE);
-static void ap_gtk_timeout_start (APUpdateType type) {
- APProgressBar *progress_bar;
- progress_bar = g_hash_table_lookup (progress_bars, GINT_TO_POINTER(type));
- if (progress_bar->timeout) {
- purple_timeout_remove (progress_bar->timeout);
- gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (progress_bar->bar), 0);
- progress_bar->timeout =
- purple_timeout_add (BAH, progress_update, progress_bar);
- progress_update (progress_bar);
-void ap_gtk_set_progress_visible (APUpdateType type, gboolean visible)
- APProgressBar *progress_bar;
- progress_bar = g_hash_table_lookup (progress_bars, GINT_TO_POINTER(type));
- if (visible) gtk_widget_show (progress_bar->bar);
- else gtk_widget_hide (progress_bar->bar);
-/*--------------------------------------------------------------------------*
- * Create the main window *
- *--------------------------------------------------------------------------*/
-static void create_dialog () {
- GtkTreeViewColumn *column;
- GtkCellRenderer *renderer;
- GtkTreeSelection *selection;
- GtkWidget *message_list_view;
- GtkWidget *vbox, *vpane, *hbox, *config_vbox;
- GtkWidget *sw, *imhtml, *msg_window, *button;
- imhtml = gtk_imhtml_new (NULL, NULL);
- /* Create main display window */
- dialog = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- gtk_window_set_type_hint (GTK_WINDOW(dialog), GDK_WINDOW_TYPE_HINT_DIALOG);
- gtk_window_set_title (GTK_WINDOW(dialog), _("AutoProfile Summary"));
- gtk_widget_realize (dialog);
- vbox = gtk_vbox_new (FALSE, 5);
- gtk_container_add (GTK_CONTAINER (dialog), vbox);
- gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
- /* Set up progress bar container */
- progress_create (AP_UPDATE_PROFILE, vbox);
- progress_create (AP_UPDATE_STATUS, vbox);
- /* Set up list of past away messages */
- vpane = gtk_vpaned_new ();
- gtk_box_pack_start (GTK_BOX(vbox), vpane, TRUE, TRUE, 0);
- message_list = gtk_list_store_new (4,
- G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
- message_list_view = gtk_tree_view_new_with_model (
- GTK_TREE_MODEL (message_list));
- renderer = gtk_cell_renderer_text_new ();
- column = gtk_tree_view_column_new_with_attributes (
- _("Time"), renderer, "markup", 0, NULL);
- gtk_tree_view_append_column (GTK_TREE_VIEW (message_list_view), column);
- gtk_tree_view_column_set_sort_column_id (column, 0);
- column = gtk_tree_view_column_new_with_attributes (
- _("Type"), renderer, "markup", 1, NULL);
- gtk_tree_view_append_column (GTK_TREE_VIEW (message_list_view), column);
- gtk_tree_view_column_set_sort_column_id (column, 1);
- renderer = gtk_cell_renderer_text_new ();
- g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
- column = gtk_tree_view_column_new_with_attributes (
- _("Text"), renderer, "markup", 2, NULL);
- gtk_tree_view_append_column (GTK_TREE_VIEW (message_list_view), column);
- gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
- sw = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(sw),
- GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw),
- gtk_container_add (GTK_CONTAINER (sw), message_list_view);
- gtk_paned_add1 (GTK_PANED(vpane), sw);
- selection = gtk_tree_view_get_selection (
- GTK_TREE_VIEW (message_list_view));
- gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
- g_signal_connect (G_OBJECT (selection), "changed",
- G_CALLBACK (display_diff_msg), imhtml);
- /* Set up the window to display away message in */
- msg_window = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(msg_window),
- GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(msg_window),
- gtk_paned_add2 (GTK_PANED(vpane), msg_window);
- gtk_container_add (GTK_CONTAINER(msg_window), imhtml);
- pidgin_setup_imhtml (imhtml);
- hbox = gtk_hbox_new (FALSE, 6);
- gtk_box_pack_start (GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
- config_vbox = gtk_vbox_new (FALSE, 4);
- gtk_box_pack_start (GTK_BOX(hbox), config_vbox, TRUE, TRUE, 0);
- pidgin_prefs_checkbox (
- _("Queue new messages while away"),
- "/plugins/gtk/autoprofile/queue_messages_when_away",
- button = pidgin_prefs_checkbox (
- _("Play sounds while away"),
- "/purple/sound/while_away",
- sound_pref_cb = purple_prefs_connect_callback (ap_get_plugin_handle (),
- "/purple/sound/while_away", sound_cb, button);
- gtk_box_pack_start (GTK_BOX(hbox), gtk_vseparator_new (), FALSE, FALSE, 0);
- config_vbox = gtk_vbox_new (FALSE, 4);
- gtk_box_pack_start (GTK_BOX(hbox), config_vbox, TRUE, TRUE, 0);
- ap_gtk_prefs_add_summary_option (config_vbox);
- button = gtk_button_new_with_label (_("Hide summary now"));
- gtk_box_pack_start (GTK_BOX(config_vbox), button, FALSE, FALSE, 0);
- g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (hide_cb), NULL);
- g_signal_connect (G_OBJECT(dialog), "delete-event",
- G_CALLBACK(gtk_widget_hide_on_delete), NULL);
- gtk_paned_set_position (GTK_PANED(vpane), 250);
- gtk_window_set_default_size (GTK_WINDOW(dialog), 430, 430);
-/*--------------------------------------------------------------------------*
- *--------------------------------------------------------------------------*/
-void ap_gtk_add_message (APUpdateType update_type, APMessageType type,
- char *time_string, *simple_text, *s;
- // Create the time string
- general_time = (time_t *) malloc (sizeof(time_t));
- cur_time = ap_localtime (general_time);
- time_string = (char *) malloc (sizeof(char[32]));
- strftime (time_string, 31, "<b>%I:%M %p</b>", cur_time);
- // Create the type string
- type_string = strdup("<b>Status</b>");
- case AP_MESSAGE_TYPE_PROFILE:
- type_string = strdup (_("<b>User profile</b>"));
- case AP_MESSAGE_TYPE_AWAY:
- type_string = strdup (_("<b>Away message</b>"));
- case AP_MESSAGE_TYPE_AVAILABLE:
- type_string = strdup (_("<b>Available message</b>"));
- case AP_MESSAGE_TYPE_STATUS:
- type_string = strdup (_("<b>Status message</b>"));
- type_string = strdup (_("<b>Other</b>"));
- simple_text = strdup (text);
- // Only show the first line
- s = (gchar *) purple_strcasestr (simple_text, "<br>");
- simple_text = purple_markup_strip_html (simple_text);
- gtk_list_store_prepend (message_list, &iter);
- gtk_list_store_set (message_list, &iter,
- if (simple_text) free (simple_text);
- if (gtk_tree_model_iter_nth_child
- (GTK_TREE_MODEL(message_list), &iter, NULL,
- AP_GTK_MAX_MESSAGES)) {
- gtk_list_store_remove (message_list, &iter);
- // Move the timeout bar
- ap_gtk_timeout_start (update_type);
- // Check if it needs to be visible or not
- if (type != AP_MESSAGE_TYPE_PROFILE &&
- ap_is_currently_away () != ap_previously_away) {
- update_summary_visibility ();
-void ap_gtk_make_visible ()
- gtk_widget_show_all (dialog);
- gtk_window_present (GTK_WINDOW(dialog));
- progress_bars = g_hash_table_new (NULL, NULL);
- queue_pref_cb = purple_prefs_connect_callback (
- ap_get_plugin_handle (),
- "/plugins/gtk/autoprofile/queue_messages_when_away", queue_cb, NULL);
- update_summary_visibility ();
-static void ap_gtk_finish_progress_bar (APUpdateType type)
- APProgressBar *progress_bar;
- progress_bar = g_hash_table_lookup (progress_bars, GINT_TO_POINTER(type));
- if (progress_bar->timeout) {
- purple_timeout_remove (progress_bar->timeout);
- g_hash_table_insert (progress_bars, GINT_TO_POINTER(type), NULL);
- // Kill the window and associated variables
- gtk_widget_destroy (dialog);
- ap_gtk_finish_progress_bar (AP_UPDATE_PROFILE);
- ap_gtk_finish_progress_bar (AP_UPDATE_STATUS);
- // Disconnect queue message
- purple_prefs_disconnect_callback (queue_pref_cb);
- purple_prefs_disconnect_callback (sound_pref_cb);
- g_hash_table_destroy (progress_bars);
--- a/autoprofile/gtk_widget.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,778 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 "autoprofile.h"
-#define AP_RESPONSE_CHOOSE 98125
-static GtkWidget *dialog_box = NULL;
-static GtkWidget *dialog_box_contents = NULL;
-static GtkWidget *dialog_box_preview = NULL;
-static struct widget *dialog_box_widget = NULL;
-static GStaticMutex preview_mutex = G_STATIC_MUTEX_INIT;
-static GtkWidget *component_dialog = NULL;
-static GtkWidget *choose_button = NULL;
-static GtkWidget *widget_dialog = NULL;
-static GtkWidget *delete_button = NULL;
-static GtkWidget *rename_button = NULL;
-static GtkListStore *tree_list = NULL;
-static GHashTable *pref_names = NULL;
-static void component_dialog_show ();
-void ap_widget_prefs_updated (struct widget *w) {
- if (dialog_box_preview == NULL) return;
- if (w != dialog_box_widget) return;
- // TODO: Investigate how laggy this is, possibly add a timeout
- output = w->component->generate (w);
- g_static_mutex_lock (&preview_mutex);
- gtk_imhtml_clear (GTK_IMHTML(dialog_box_preview));
- gtk_imhtml_append_text (GTK_IMHTML(dialog_box_preview), output,
- g_static_mutex_unlock (&preview_mutex);
-static void update_widget_list (GtkListStore *ls) {
- GList *widgets, *widgets_start;
- gtk_list_store_clear (ls);
- widgets_start = widgets = ap_widget_get_widgets ();
- for (widgets = widgets_start; widgets != NULL; widgets = widgets->next) {
- gtk_list_store_append (ls, &iter);
- w = (struct widget *) widgets->data;
- g_string_printf (s, "<b>%s</b>", w->alias);
- gtk_list_store_set (ls, &iter,
- g_list_free (widgets_start);
- g_string_free (s, TRUE);
-static void refresh_cb (GtkWidget *widget, gpointer data) {
- w = (struct widget *) data;
- ap_widget_prefs_updated (w);
-/* Widget configuration menu */
-static GtkWidget *get_widget_configuration (struct widget *w) {
- GtkWidget *config, *hbox, *vbox, *sw;
- GtkWidget *label, *button;
- config = gtk_vbox_new (FALSE, 0);
- /* Title/Description */
- hbox = gtk_hbox_new (FALSE, 8);
- gtk_container_set_border_width (GTK_CONTAINER(hbox), 6);
- gtk_box_pack_start (GTK_BOX(config), hbox, FALSE, FALSE, 0);
- g_string_printf (s, "<b>%s:</b> %s", w->component->name,
- w->component->description);
- label = gtk_label_new ("");
- gtk_label_set_markup (GTK_LABEL(label), s->str);
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- g_string_free (s, TRUE);
- gtk_box_pack_start (GTK_BOX (config), gtk_hseparator_new (),
- vbox = gtk_vbox_new (FALSE, 6);
- gtk_container_set_border_width (GTK_CONTAINER(vbox), 6);
- gtk_box_pack_start (GTK_BOX(config), vbox, FALSE, FALSE, 0);
- hbox = gtk_hbox_new (FALSE, 8);
- gtk_box_pack_start (GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
- label = gtk_label_new ("");
- gtk_label_set_markup (GTK_LABEL(label), _("<b>Preview</b>"));
- gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 0);
- button = gtk_button_new_with_label (_("Refresh"));
- gtk_box_pack_end (GTK_BOX(hbox), button, FALSE, FALSE, 0);
- g_signal_connect (G_OBJECT (button), "clicked",
- G_CALLBACK (refresh_cb), w);
- sw = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(sw),
- GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw),
- gtk_box_pack_start (GTK_BOX(vbox), sw, TRUE, TRUE, 0);
- dialog_box_preview = gtk_imhtml_new (NULL, NULL);
- gtk_container_add (GTK_CONTAINER(sw), dialog_box_preview);
- pidgin_setup_imhtml (dialog_box_preview);
- output = w->component->generate (w);
- gtk_imhtml_append_text (GTK_IMHTML(dialog_box_preview),
- output, GTK_IMHTML_NO_SCROLL);
- gtk_box_pack_start (GTK_BOX (config), gtk_hseparator_new (),
- /* Configuration stuff */
- vbox = gtk_vbox_new (FALSE, 8);
- gtk_container_set_border_width (GTK_CONTAINER(vbox), 6);
- gtk_box_pack_start (GTK_BOX(config), vbox, TRUE, TRUE, 0);
- label = gtk_label_new ("");
- gtk_label_set_markup (GTK_LABEL(label), _("<b>Configuration</b>"));
- gtk_box_pack_start (GTK_BOX(vbox), label, FALSE, FALSE, 0);
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- if (w->component->pref_menu == NULL ||
- (menu = (w->component->pref_menu) (w)) == NULL) {
- label = gtk_label_new (_("No options available for this component"));
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
- gtk_box_pack_start (GTK_BOX (vbox), menu, TRUE, TRUE, 0);
-static GtkWidget *get_info_message () {
- page = gtk_vbox_new (FALSE, 8);
- gtk_container_set_border_width (GTK_CONTAINER (page), 12);
- aboutwin = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(aboutwin),
- GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(aboutwin),
- gtk_box_pack_start (GTK_BOX(page), aboutwin, TRUE, TRUE, 0);
- text = gtk_imhtml_new (NULL, NULL);
- gtk_container_add (GTK_CONTAINER(aboutwin), text);
- pidgin_setup_imhtml (text);
- gtk_imhtml_append_text (GTK_IMHTML(text),
- _("<b><u>Basic info</u></b><br>"), GTK_IMHTML_NO_SCROLL);
- gtk_imhtml_append_text (GTK_IMHTML(text),
- _("A <b>widget</b> is a little piece/snippet of automatically "
- "generated text. There are all sorts of widgets; each type has "
- "different content (i.e. a random quote, text from a blog, the "
- "song currently playing, etc).<br><br>"), GTK_IMHTML_NO_SCROLL);
- gtk_imhtml_append_text (GTK_IMHTML(text),
- _("To use a widget, simply drag it from the list on the left and "
- "drop it into a profile or status message. <i>It's that easy!</i>"
- "<br><br>"), GTK_IMHTML_NO_SCROLL);
- gtk_imhtml_append_text (GTK_IMHTML(text),
- _("<b>To edit your profile:</b> "
- "Use the \"Info/profile\" tab in this window.<br>"),
- gtk_imhtml_append_text (GTK_IMHTML(text),
- _("<b>To edit your available/away/status message:</b> "
- "Use the regular Purple interface built into the bottom of the buddy "
- "list.<br><br>"), GTK_IMHTML_NO_SCROLL);
- gtk_imhtml_append_text (GTK_IMHTML(text),
- _("<b><u>Advanced Tips</u></b><br>"), GTK_IMHTML_NO_SCROLL);
- gtk_imhtml_append_text (GTK_IMHTML(text),
- _("You can insert a widget into a profile or status by typing its name. "
- "To do this, just type \"[widget-name]\" wherever you want to "
- "place a widget (names of widgets are listed on the left). <br><br>"
- "<b>You type:</b> The song I am playing now is [iTunesInfo].<br>"
- "<b>AutoProfile result:</b> The song I am playing now is "
- "The Beatles - Yellow Submarine.<br><br>"), GTK_IMHTML_NO_SCROLL);
-/* Dialog window actions */
-static void widget_popup_rename_cb (
- struct widget *w, const char *new_text) {
- struct widget *cur_widget;
- gtk_tree_model_get_iter_first (GTK_TREE_MODEL(tree_list), &iter);
- gtk_tree_model_get_value (GTK_TREE_MODEL(tree_list), &iter, 1, &val);
- cur_widget = g_value_get_pointer(&val);
- if (cur_widget == w) break;
- if (!gtk_tree_model_iter_next (GTK_TREE_MODEL(tree_list), &iter)) {
- purple_notify_error (NULL, NULL,
- N_("Unable to change name"),
- N_("The specified widget no longer exists."));
- if (ap_widget_rename (w, new_text)) {
- g_string_printf (s, "<b>%s</b>", w->alias);
- gtk_list_store_set (tree_list, &iter,
- g_string_free (s, TRUE);
- purple_notify_error (NULL, NULL,
- N_("Unable to change name"),
- N_("The widget name you have specified is already in use."));
-static void delete_cb (GtkWidget *button, GtkTreeSelection *sel)
- gtk_tree_selection_get_selected (sel, &model, &iter);
- gtk_tree_model_get_value (model, &iter, 1, &val);
- w = g_value_get_pointer(&val);
- gtk_list_store_remove (GTK_LIST_STORE(model), &iter);
-static void rename_cb (GtkWidget *button, GtkTreeSelection *sel)
- gtk_tree_selection_get_selected (sel, &model, &iter);
- gtk_tree_model_get_value (model, &iter, 1, &val);
- w = g_value_get_pointer(&val);
- purple_request_input(NULL,
- _("Rename Widget"), NULL,
- _("Enter a new name for this widget."), w->alias,
- _("Rename"), G_CALLBACK(widget_popup_rename_cb),
- _("Cancel"), NULL, NULL, NULL, NULL, w);
-static void add_cb (GtkWidget *button, GtkTreeSelection *sel)
- component_dialog_show ();
-void ap_widget_gtk_start () {
- pref_names = g_hash_table_new (g_str_hash, g_str_equal);
-void ap_widget_gtk_finish () {
- done_with_widget_list ();
- g_hash_table_destroy (pref_names);
-static void widget_sel_cb (GtkTreeSelection *sel, GtkTreeModel *model) {
- gtk_widget_destroy (dialog_box_contents);
- if (!gtk_tree_selection_get_selected (sel, &model, &iter)) {
- gtk_widget_set_sensitive(rename_button, FALSE);
- gtk_widget_set_sensitive(delete_button, FALSE);
- dialog_box_contents = get_info_message ();
- dialog_box_preview = NULL;
- dialog_box_widget = NULL;
- gtk_widget_set_sensitive(rename_button, TRUE);
- gtk_widget_set_sensitive(delete_button, TRUE);
- gtk_tree_model_get_value (GTK_TREE_MODEL(tree_list), &iter, 1, &val);
- w = g_value_get_pointer(&val);
- dialog_box_contents = get_widget_configuration (w);
- gtk_box_pack_start (GTK_BOX(dialog_box), dialog_box_contents,
- gtk_widget_show_all (dialog_box);
-GtkWidget *ap_widget_get_config_page ()
- /* Arrange main parts of window */
- dialog_box = gtk_hbox_new (FALSE, 0);
- vbox = gtk_vbox_new (FALSE, 0);
- gtk_box_pack_start (GTK_BOX(dialog_box), vbox, FALSE, FALSE, 0);
- get_widget_list (vbox, &sel);
- g_signal_connect (G_OBJECT (sel), "changed", G_CALLBACK (widget_sel_cb),
- add_button = gtk_button_new_with_label (_("New Widget"));
- g_signal_connect (G_OBJECT(add_button), "clicked",
- G_CALLBACK(add_cb), sel);
- gtk_box_pack_start (GTK_BOX(vbox), add_button, FALSE, FALSE, 0);
- rename_button = gtk_button_new_with_label (_("Rename"));
- gtk_widget_set_sensitive(rename_button, FALSE);
- g_signal_connect (G_OBJECT(rename_button), "clicked",
- G_CALLBACK(rename_cb), sel);
- gtk_box_pack_start (GTK_BOX(vbox), rename_button, FALSE, FALSE, 0);
- delete_button = gtk_button_new_with_label (_("Delete"));
- gtk_widget_set_sensitive(delete_button, FALSE);
- g_signal_connect (G_OBJECT(delete_button), "clicked",
- G_CALLBACK(delete_cb), sel);
- gtk_box_pack_start (GTK_BOX(vbox), delete_button, FALSE, FALSE, 0);
- dialog_box_contents = get_info_message ();
- gtk_box_pack_start (GTK_BOX(dialog_box), dialog_box_contents,
-drag_data_get_cb(GtkWidget *widget, GdkDragContext *ctx,
- GtkSelectionData *data, guint info, guint time,
- GtkListStore *ls = (GtkListStore *) user_data;
- if (ls == NULL) return;
- if (data->target == gdk_atom_intern ("STRING", FALSE)) {
- GtkTreeRowReference *ref;
- GtkTreePath *source_row;
- ref = g_object_get_data (G_OBJECT(ctx), "gtk-tree-view-source-row");
- source_row = gtk_tree_row_reference_get_path (ref);
- if (source_row == NULL) return;
- gtk_tree_model_get_iter(GTK_TREE_MODEL(ls), &iter, source_row);
- gtk_tree_model_get_value(GTK_TREE_MODEL(ls), &iter,
- w = g_value_get_pointer (&val);
- g_string_printf (s, "[%s]", w->alias);
- gtk_selection_data_set (data, gdk_atom_intern ("STRING", FALSE),
- 8, (guchar *)s->str, strlen(s->str)+1);
- g_string_free (s, TRUE);
- gtk_tree_path_free (source_row);
-void done_with_widget_list () {
- g_object_unref (tree_list);
- dialog_box_contents = NULL;
- dialog_box_preview = NULL;
- dialog_box_widget = NULL;
- if (component_dialog != NULL) {
- gtk_widget_destroy (component_dialog);
- component_dialog = NULL;
-GtkWidget *get_widget_list (GtkWidget *box, GtkTreeSelection **sel)
- GtkTreeViewColumn *col;
- GtkTargetEntry gte [] = {{"STRING", 0, GTK_IMHTML_DRAG_STRING}};
- if (tree_list == NULL) {
- tree_list = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_POINTER);
- gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(tree_list),
- 0, GTK_SORT_ASCENDING);
- update_widget_list (tree_list);
- g_object_ref (G_OBJECT(tree_list));
- sw = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(sw),
- GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw),
- gtk_box_pack_start (GTK_BOX(box), sw, TRUE, TRUE, 0);
- event_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(tree_list));
- *sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (event_view));
- rend = gtk_cell_renderer_text_new ();
- col = gtk_tree_view_column_new_with_attributes (_("Widget"), rend,
- gtk_tree_view_append_column (GTK_TREE_VIEW (event_view), col);
- gtk_tree_view_column_set_sort_column_id (col, 0);
- gtk_container_add (GTK_CONTAINER(sw), event_view);
- gtk_tree_view_enable_model_drag_source(
- GTK_TREE_VIEW(event_view), GDK_BUTTON1_MASK, gte,
- g_signal_connect(G_OBJECT(event_view), "drag-data-get",
- G_CALLBACK(drag_data_get_cb), tree_list);
-/*********************************************************
- Component selection window
-**********************************************************/
-static void add_component (struct component *c) {
- w = ap_widget_create (c);
- gtk_list_store_append (tree_list, &iter);
- g_string_printf (s, "<b>%s</b>", w->alias);
- gtk_list_store_set (tree_list, &iter,
- g_string_free (s, TRUE);
-static void component_row_activate_cb (GtkTreeView *view, GtkTreePath *path,
- GtkTreeViewColumn *column, gpointer null)
- sel = gtk_tree_view_get_selection (view);
- if (gtk_tree_selection_get_selected (sel, &model, &iter)) {
- gtk_tree_model_get (model, &iter, 1, &c, -1);
- gtk_widget_destroy (component_dialog);
- component_dialog = NULL;
-static void component_response_cb(GtkWidget *d, int response,
- case AP_RESPONSE_CHOOSE:
- gtk_tree_selection_get_selected (sel, &model, &iter);
- gtk_tree_model_get_value (model, &iter, 1, &val);
- c = g_value_get_pointer(&val);
- case GTK_RESPONSE_CLOSE:
- case GTK_RESPONSE_CANCEL:
- case GTK_RESPONSE_DELETE_EVENT:
- component_dialog = NULL;
-static void component_sel_cb (GtkTreeSelection *sel, GtkTreeModel *model) {
- if (!gtk_tree_selection_get_selected (sel, &model, &iter)) {
- gtk_widget_set_sensitive(choose_button, FALSE);
- gtk_widget_set_sensitive(choose_button, TRUE);
-static void update_component_list (GtkListStore *ls) {
- gchar *name, *description;
- gtk_list_store_clear (ls);
- for (components = ap_component_get_components ();
- components = components->next) {
- gtk_list_store_append (ls, &iter);
- c = (struct component *) components->data;
- name = g_markup_escape_text (c->name, -1);
- description = g_markup_escape_text (c->description, -1);
- g_string_printf (s, "<b>%s</b>\n%s", name, description);
- gtk_list_store_set (ls, &iter,
- g_string_free (s, TRUE);
-static void component_dialog_show ()
- GtkCellRenderer *rendt;
- GtkTreeViewColumn *col;
- if (component_dialog != NULL) {
- gtk_window_present(GTK_WINDOW(component_dialog));
- component_dialog = gtk_dialog_new_with_buttons (_("Select a widget type"),
- GTK_DIALOG_NO_SEPARATOR,
- choose_button = gtk_dialog_add_button (GTK_DIALOG(component_dialog),
- _("Create widget"), AP_RESPONSE_CHOOSE);
- gtk_dialog_add_button (GTK_DIALOG(component_dialog),
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
- gtk_widget_set_sensitive (choose_button, FALSE);
- sw = gtk_scrolled_window_new (NULL,NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(sw),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw),
- gtk_box_pack_start (GTK_BOX(GTK_DIALOG(component_dialog)->vbox), sw,
- ls = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_POINTER);
- gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(ls),
- 0, GTK_SORT_ASCENDING);
- update_component_list (ls);
- event_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL(ls));
- g_signal_connect(G_OBJECT(event_view), "row-activated",
- G_CALLBACK(component_row_activate_cb), event_view);
- sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (event_view));
- rendt = gtk_cell_renderer_text_new ();
- col = gtk_tree_view_column_new_with_attributes (_("Widget type"),
-#if GTK_CHECK_VERSION(2,6,0)
- gtk_tree_view_column_set_expand (col, TRUE);
- g_object_set(rendt, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
- gtk_tree_view_append_column (GTK_TREE_VIEW(event_view), col);
- gtk_tree_view_column_set_sort_column_id (col, 0);
- g_object_unref (G_OBJECT(ls));
- gtk_container_add (GTK_CONTAINER(sw), event_view);
- g_signal_connect (G_OBJECT (sel), "changed",
- G_CALLBACK (component_sel_cb), NULL);
- g_signal_connect(G_OBJECT(component_dialog), "response",
- G_CALLBACK(component_response_cb), sel);
- gtk_window_set_default_size(GTK_WINDOW(component_dialog), 550, 430);
- gtk_widget_show_all(component_dialog);
-static void pref_callback (const char *name, PurplePrefType type,
- gconstpointer val, gpointer data) {
- struct widget *w = (struct widget *) data;
- ap_widget_prefs_updated (w);
-static const gchar *get_const_pref (struct widget *w, const char *key) {
- // This is here to prevent memory leaks
- pref = ap_prefs_get_pref_name (w, key);
- if (pref_names == NULL) {
- pref_names = g_hash_table_new (g_str_hash, g_str_equal);
- result = g_hash_table_lookup (pref_names, pref);
- g_hash_table_insert (pref_names, pref, pref);
-GtkWidget *ap_prefs_checkbox (struct widget *w, const char *title,
- const char *key, GtkWidget *page)
- pref = get_const_pref (w, key);
- result = pidgin_prefs_checkbox (title, pref, page);
- purple_prefs_connect_callback (ap_get_plugin_handle (), pref,
-GtkWidget *ap_prefs_dropdown_from_list (struct widget *w, GtkWidget *page,
- const gchar *title, PurplePrefType type, const char *key, GList *menuitems)
- pref = get_const_pref (w, key);
- result = pidgin_prefs_dropdown_from_list (
- page, title, type, pref, menuitems);
- purple_prefs_connect_callback (ap_get_plugin_handle (), pref,
-GtkWidget *ap_prefs_labeled_entry (struct widget *w, GtkWidget *page,
- const gchar *title, const char *key, GtkSizeGroup *sg) {
- pref = get_const_pref (w, key);
- result = pidgin_prefs_labeled_entry (page, title, pref, sg);
- purple_prefs_connect_callback (ap_get_plugin_handle (), pref,
-GtkWidget *ap_prefs_labeled_spin_button (struct widget *w,
- GtkWidget *page, const gchar *title, const char *key, int min,
- int max, GtkSizeGroup *sg)
- pref = get_const_pref (w, key);
- result = pidgin_prefs_labeled_spin_button (page, title, pref,
- purple_prefs_connect_callback (ap_get_plugin_handle (), pref,
--- a/autoprofile/meson.build Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-if TYPES.contains('incomplete') and PIDGIN.found()
- autoprofile = shared_module('autoprofile',
- dependencies : [PIDGIN, GTK],
- install_dir : PIDGIN_LIBDIR)
- PP_PIDGIN_BUILD += 'autoprofile'
--- a/autoprofile/preferences.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,750 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 "autoprofile.h"
-#include "gtksavedstatuses.h"
-/*--------------------------------------------------------------------------*
- *--------------------------------------------------------------------------*/
-static GtkWidget *get_info_page () {
- gchar *labeltext, *str;
- page = gtk_vbox_new (FALSE, 5);
- gtk_container_set_border_width (GTK_CONTAINER (page), 5);
- /* AutoProfile title */
- labeltext = g_strdup_printf (
- _("<span weight=\"bold\" size=\"larger\">AutoProfile %s</span>"),
- label = gtk_label_new (NULL);
- gtk_label_set_markup (GTK_LABEL(label), labeltext);
- gtk_label_set_line_wrap (GTK_LABEL(label), TRUE);
- gtk_misc_set_alignment (GTK_MISC(label), 0.5, 0);
- gtk_box_pack_start (GTK_BOX(page), label, FALSE, FALSE, 0);
- aboutwin = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(aboutwin),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(aboutwin),
- gtk_box_pack_start (GTK_BOX(page), aboutwin, TRUE, TRUE, 0);
- text = gtk_imhtml_new (NULL, NULL);
- gtk_container_add (GTK_CONTAINER(aboutwin), text);
- pidgin_setup_imhtml (text);
- gtk_imhtml_append_text (GTK_IMHTML(text),
- _("Use the <b>Autoprofile</b> portion of the <b>Tools</b> "
- "buddy list</b> to configure the actual content that will go in your "
- "status messages and profiles and set options.<br><br>"),
- gtk_imhtml_append_text (GTK_IMHTML(text),
- _("<u>DOCUMENTATION / HELP</u><br>"), GTK_IMHTML_NO_SCROLL);
- gtk_imhtml_append_text (GTK_IMHTML(text),
- _("Complete documentation can be found at:<br> <a href="
- "\"http://hkn.eecs.berkeley.edu/~casey/autoprofile/documentation.php\">"
- "hkn.eecs.berkeley.edu/~casey/autoprofile/documentation.php</a><br>"),
- gtk_imhtml_append_text (GTK_IMHTML(text),
- _("<br><u>ABOUT</u><br>"), GTK_IMHTML_NO_SCROLL);
- "<font size=\"3\"><b>", _("Developers"), ":</b></font><br>"
- " Casey Ho (Lead Developer)<br>"
- " Mitchell Harwell<br>", NULL);
- gtk_imhtml_append_text(GTK_IMHTML(text), str, GTK_IMHTML_NO_SCROLL);
- "<font size=\"3\"><b>", _("Contributors/Patchers"), ":</b></font><br>"
- " Michael Milligan<br>"
- " Mark Painter<br>", NULL);
- gtk_imhtml_append_text(GTK_IMHTML(text), str, GTK_IMHTML_NO_SCROLL);
- "<font size=\"3\"><b>", _("Website"), ":</b></font><br>"
- " <a href=\"http://autoprofile.sourceforge.net\">"
- "autoprofile.sourceforge.net<br>", NULL);
- gtk_imhtml_append_text(GTK_IMHTML(text), str, GTK_IMHTML_NO_SCROLL);
-/*----------------------------------------------------------------------------
- *--------------------------------------------------------------------------*/
-/* PRIMARILY RIPPED FROM GAIM GTKACCOUNT.C */
- PurpleAccount *account;
-} PidginAccountAddUserData;
- GtkTreeViewColumn *screenname_col;
-static void add_account_to_liststore(PurpleAccount *, gpointer);
-static void set_account(GtkListStore *, GtkTreeIter *, PurpleAccount *);
-static gboolean is_profile_settable (PurpleAccount *a) {
- const gchar *id = purple_account_get_protocol_id (a);
- if (!strcmp (id, "prpl-yahoo") ||
- !strcmp (id, "prpl-msn") ||
- !strcmp (id, "prpl-jabber")) {
-drag_data_get_cb(GtkWidget *widget, GdkDragContext *ctx,
- GtkSelectionData *data, guint info, guint time,
- AccountsWindow *dialog)
- if (data->target == gdk_atom_intern("PURPLE_ACCOUNT", FALSE)) {
- GtkTreeRowReference *ref;
- GtkTreePath *source_row;
- PurpleAccount *account = NULL;
- ref = g_object_get_data(G_OBJECT(ctx), "gtk-tree-view-source-row");
- source_row = gtk_tree_row_reference_get_path(ref);
- if (source_row == NULL) return;
- gtk_tree_model_get_iter(GTK_TREE_MODEL(dialog->model), &iter, source_row);
- gtk_tree_model_get_value(GTK_TREE_MODEL(dialog->model), &iter,
- dialog->drag_iter = iter;
- account = g_value_get_pointer(&val);
- gtk_selection_data_set(data, gdk_atom_intern("PURPLE_ACCOUNT", FALSE),
- 8, (void *)&account, sizeof(account));
- gtk_tree_path_free(source_row);
-move_account_after(GtkListStore *store, GtkTreeIter *iter,
- PurpleAccount *account;
- gtk_tree_model_get(GTK_TREE_MODEL(store), iter, COLUMN_DATA, &account, -1);
- gtk_list_store_insert_after(store, &new_iter, position);
- set_account(store, &new_iter, account);
- gtk_list_store_remove(store, iter);
-move_account_before(GtkListStore *store, GtkTreeIter *iter,
- PurpleAccount *account;
- gtk_tree_model_get(GTK_TREE_MODEL(store), iter, COLUMN_DATA, &account, -1);
- gtk_list_store_insert_before(store, &new_iter, position);
- set_account(store, &new_iter, account);
- gtk_list_store_remove(store, iter);
-drag_data_received_cb(GtkWidget *widget, GdkDragContext *ctx,
- guint x, guint y, GtkSelectionData *sd,
- guint info, guint t, AccountsWindow *dialog)
- if (sd->target == gdk_atom_intern("PURPLE_ACCOUNT", FALSE) && sd->data) {
- PurpleAccount *a = NULL;
- GtkTreePath *path = NULL;
- GtkTreeViewDropPosition position;
- memcpy(&a, sd->data, sizeof(a));
- if (gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(widget), x, y,
- PurpleAccount *account;
- gtk_tree_model_get_iter(GTK_TREE_MODEL(dialog->model), &iter, path);
- gtk_tree_model_get_value(GTK_TREE_MODEL(dialog->model), &iter,
- account = g_value_get_pointer(&val);
- case GTK_TREE_VIEW_DROP_AFTER:
- case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
- move_account_after(dialog->model, &dialog->drag_iter, &iter);
- dest_index = g_list_index(purple_accounts_get_all(), account) + 1;
- case GTK_TREE_VIEW_DROP_BEFORE:
- case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
- dest_index = g_list_index(purple_accounts_get_all(), account);
- move_account_before(dialog->model, &dialog->drag_iter, &iter);
- purple_accounts_reorder(a, dest_index);
-enabled_cb(GtkCellRendererToggle *renderer, gchar *path_str, gpointer data)
- AccountsWindow *dialog = (AccountsWindow *)data;
- PurpleAccount *account;
- GtkTreeModel *model = GTK_TREE_MODEL(dialog->model);
- gtk_tree_model_get_iter_from_string(model, &iter, path_str);
- gtk_tree_model_get(model, &iter,
- COLUMN_ENABLED, &enabled,
- /* Change profile settings */
- ap_account_enable_profile (account, !enabled);
- set_account (dialog->model, &iter, account);
-add_columns(GtkWidget *treeview, AccountsWindow *dialog)
- GtkCellRenderer *renderer;
- GtkTreeViewColumn *column;
- /* Screen Name column */
- column = gtk_tree_view_column_new();
- gtk_tree_view_column_set_title(column, _("Screen Name"));
- gtk_tree_view_insert_column(GTK_TREE_VIEW(treeview), column, -1);
- gtk_tree_view_column_set_resizable(column, TRUE);
- renderer = gtk_cell_renderer_pixbuf_new();
- gtk_tree_view_column_pack_start(column, renderer, FALSE);
- gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", COLUMN_ICON);
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_column_pack_start(column, renderer, TRUE);
- gtk_tree_view_column_add_attribute(column, renderer,
- "text", COLUMN_SCREENNAME);
- dialog->screenname_col = column;
- renderer = gtk_cell_renderer_toggle_new();
- g_signal_connect(G_OBJECT(renderer), "toggled",
- G_CALLBACK(enabled_cb), dialog);
- gtk_tree_view_column_new_with_attributes(_("AutoProfile sets user info"),
- renderer, "active", COLUMN_ENABLED, NULL);
- gtk_tree_view_insert_column(GTK_TREE_VIEW(treeview), column, -1);
- gtk_tree_view_column_set_resizable(column, TRUE);
- column = gtk_tree_view_column_new();
- gtk_tree_view_column_set_title(column, _("Protocol"));
- gtk_tree_view_insert_column(GTK_TREE_VIEW(treeview), column, -1);
- gtk_tree_view_column_set_resizable(column, TRUE);
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_column_pack_start(column, renderer, TRUE);
- gtk_tree_view_column_add_attribute(column, renderer,
- "text", COLUMN_PROTOCOL);
-set_account(GtkListStore *store, GtkTreeIter *iter, PurpleAccount *account)
- pixbuf = pidgin_create_prpl_icon(account, 0.5);
- scale = gdk_pixbuf_scale_simple(pixbuf, 16, 16, GDK_INTERP_BILINEAR);
- if (purple_account_is_disconnected(account))
- gdk_pixbuf_saturate_and_pixelate(scale, scale, 0.0, FALSE);
- gtk_list_store_set(store, iter,
- COLUMN_SCREENNAME, purple_account_get_username(account),
- COLUMN_ENABLED, ap_account_has_profile_enabled(account),
- COLUMN_PROTOCOL, purple_account_get_protocol_name(account),
- if (pixbuf != NULL) g_object_unref(G_OBJECT(pixbuf));
- if (scale != NULL) g_object_unref(G_OBJECT(scale));
-add_account_to_liststore(PurpleAccount *account, gpointer user_data)
- AccountsWindow *dialog = (AccountsWindow *) user_data;
- if (dialog == NULL) return;
- if (!is_profile_settable (account)) return;
- gtk_list_store_append(dialog->model, &iter);
- set_account(dialog->model, &iter, account);
-populate_accounts_list(AccountsWindow *dialog)
- gtk_list_store_clear(dialog->model);
- for (l = purple_accounts_get_all(); l != NULL; l = l->next)
- add_account_to_liststore((PurpleAccount *)l->data, dialog);
-#if !GTK_CHECK_VERSION(2,2,0)
-get_selected_helper(GtkTreeModel *model, GtkTreePath *path,
- GtkTreeIter *iter, gpointer user_data)
- *((gboolean *)user_data) = TRUE;
-account_selected_cb(GtkTreeSelection *sel, AccountsWindow *dialog)
- gboolean selected = FALSE;
-#if GTK_CHECK_VERSION(2,2,0)
- selected = (gtk_tree_selection_count_selected_rows(sel) > 0);
- gtk_tree_selection_selected_foreach(sel, get_selected_helper, &selected);
-create_accounts_list(AccountsWindow *dialog)
- GtkTargetEntry gte[] = {{"PURPLE_ACCOUNT", GTK_TARGET_SAME_APP, 0}};
- /* Create the scrolled window. */
- sw = gtk_scrolled_window_new(0, 0);
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
- gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN);
- /* Create the list model. */
- dialog->model = gtk_list_store_new(NUM_COLUMNS,
- GDK_TYPE_PIXBUF, G_TYPE_STRING,
- G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_POINTER,
- /* And now the actual treeview */
- treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog->model));
- dialog->treeview = treeview;
- gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE);
- sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
- gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE);
- g_signal_connect(G_OBJECT(sel), "changed",
- G_CALLBACK(account_selected_cb), dialog);
- gtk_container_add(GTK_CONTAINER(sw), treeview);
- gtk_widget_show(treeview);
- add_columns(treeview, dialog);
- populate_accounts_list(dialog);
- /* Setup DND. I wanna be an orc! */
- gtk_tree_view_enable_model_drag_source(
- GTK_TREE_VIEW(treeview), GDK_BUTTON1_MASK, gte,
- gtk_tree_view_enable_model_drag_dest(
- GTK_TREE_VIEW(treeview), gte, 1,
- GDK_ACTION_COPY | GDK_ACTION_MOVE);
- g_signal_connect(G_OBJECT(treeview), "drag-data-received",
- G_CALLBACK(drag_data_received_cb), dialog);
- g_signal_connect(G_OBJECT(treeview), "drag-data-get",
- G_CALLBACK(drag_data_get_cb), dialog);
-static void account_page_delete_cb (GtkObject *object, gpointer data)
-GtkWidget *get_account_page () {
- AccountsWindow *accounts_window;
- page = gtk_vbox_new (FALSE, 8);
- gtk_container_set_border_width (GTK_CONTAINER (page), 12);
- accounts_window = g_new0(AccountsWindow, 1);
- /* Setup the scrolled window that will contain the list of accounts. */
- sw = create_accounts_list(accounts_window);
- gtk_box_pack_start(GTK_BOX(page), sw, TRUE, TRUE, 0);
- label = gtk_label_new (
- _("Accounts that do not support user-specified profiles are not shown"));
- gtk_box_pack_start(GTK_BOX(page), label, FALSE, FALSE, 0);
- g_signal_connect (G_OBJECT (page), "destroy",
- G_CALLBACK (account_page_delete_cb), accounts_window);
-/*----------------------------------------------------------------------------
- *--------------------------------------------------------------------------*/
-void ap_gtk_prefs_add_summary_option (GtkWidget *widget) {
- pidgin_prefs_dropdown (widget,
- "Show AutoProfile summary window",
- "/plugins/gtk/autoprofile/show_summary",
- "Always", "always", "When away", "away", "Never", "never", NULL);
-set_idle_away(PurpleSavedStatus *status)
- purple_prefs_set_int("/core/savedstatus/idleaway",
- purple_savedstatus_get_creation_time(status));
-static GtkWidget *get_behavior_page () {
- GtkWidget *frame, *vbox, *hbox;
- GtkWidget *button, *select, *menu;
- page = gtk_vbox_new (FALSE, 8);
- gtk_container_set_border_width (GTK_CONTAINER (page), 12);
- /*---------- Update frequency ----------*/
- frame = pidgin_make_frame (page, _("Update frequency"));
- vbox = gtk_vbox_new (FALSE, 0);
- gtk_container_add (GTK_CONTAINER (frame), vbox);
- pidgin_prefs_labeled_spin_button (vbox,
- _("Minimum number of seconds between updates"),
- "/plugins/gtk/autoprofile/delay_update",
- label = gtk_label_new ("");
- markup = g_markup_printf_escaped ("<span style=\"italic\">%s</span>",
- _("WARNING: Using values below 60 seconds may increase the frequency\n"
- "of rate limiting errors"));
- gtk_label_set_markup (GTK_LABEL (label), markup);
- gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
- /*----------- Auto-away stuff ------------*/
- frame = pidgin_make_frame(page, _("Auto-away"));
- button = pidgin_prefs_checkbox(_("Change status when idle"),
- "/plugins/gtk/autoprofile/away_when_idle", frame);
- sg = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
- select = pidgin_prefs_labeled_spin_button(frame,
- _("Minutes before changing status:"), "/core/away/mins_before_away",
- g_signal_connect(G_OBJECT(button), "clicked",
- G_CALLBACK(pidgin_toggle_sensitive), select);
- hbox = gtk_hbox_new(FALSE, 0);
- gtk_container_add(GTK_CONTAINER(frame), hbox);
- label = gtk_label_new_with_mnemonic(_("Change status to:"));
- gtk_size_group_add_widget(sg, label);
- gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
- g_signal_connect(G_OBJECT(button), "clicked",
- G_CALLBACK(pidgin_toggle_sensitive), label);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
- /* TODO: Show something useful if we don't have any saved statuses. */
- menu = pidgin_status_menu(purple_savedstatus_get_idleaway(),
- G_CALLBACK(set_idle_away));
- gtk_box_pack_start(GTK_BOX(frame), menu, FALSE, FALSE, 0);
- g_signal_connect(G_OBJECT(button), "clicked",
- G_CALLBACK(pidgin_toggle_sensitive), menu);
- gtk_label_set_mnemonic_widget(GTK_LABEL(label), menu);
- if (!purple_prefs_get_bool("/plugins/gtk/autoprofile/away_when_idle")) {
- gtk_widget_set_sensitive(GTK_WIDGET(menu), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(select), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(label), FALSE);
-/*----------------------------------------------------------------------------
- *--------------------------------------------------------------------------*/
-/* Update string arguments */
-static gboolean update_behavior_string (GtkWidget *widget, GdkEventFocus *evt,
- ap_debug ("preferences", "behavior string preference modified");
- if (!strcmp (data, "text_trigger")) {
- purple_prefs_set_string ("/plugins/gtk/autoprofile/autorespond/trigger",
- gtk_entry_get_text (GTK_ENTRY (widget)));
- } else if (!strcmp (data, "text_respond")) {
- purple_prefs_set_string ("/plugins/gtk/autoprofile/autorespond/text",
- gtk_entry_get_text (GTK_ENTRY (widget)));
- ap_debug_error ("preferences", "invalid data argument to string update");
-/* Update value returned from spinner for auto-respond delay */
-static gboolean update_delay_respond (GtkWidget *widget, GdkEventFocus *evt,
- purple_prefs_set_int ("/plugins/gtk/autoprofile/delay_respond",
- gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget)));
-static GtkWidget *get_autoreply_page () {
- GtkWidget *label, *checkbox, *spinner, *entry;
- GtkWidget *frame, *vbox, *large_vbox, *hbox;
- page = gtk_vbox_new (FALSE, 8);
- gtk_container_set_border_width (GTK_CONTAINER (page), 12);
- frame = pidgin_make_frame(page, _("General"));
- dd = pidgin_prefs_dropdown(frame, _("Auto-reply:"),
- PURPLE_PREF_STRING, "/plugins/gtk/autoprofile/autorespond/auto_reply",
- _("When away"), "away",
- _("When both away and idle"), "awayidle",
- sg = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
- gtk_size_group_add_widget(sg, dd);
- gtk_misc_set_alignment(GTK_MISC(dd), 0, 0.5);
- /*---------- Auto-responses ----------*/
- frame = pidgin_make_frame (page, _("Dynamic auto-responses"));
- vbox = gtk_vbox_new (FALSE, 5);
- gtk_container_add (GTK_CONTAINER (frame), vbox);
- /* Auto-response activated */
- checkbox = pidgin_prefs_checkbox (
- _("Allow users to request more auto-responses"),
- "/plugins/gtk/autoprofile/autorespond/enable", vbox);
- large_vbox = gtk_vbox_new (FALSE, 5);
- gtk_box_pack_start (GTK_BOX (vbox), large_vbox, FALSE, FALSE, 0);
- /* Auto-response delay */
- hbox = gtk_hbox_new (FALSE, 5);
- gtk_box_pack_start (GTK_BOX (large_vbox), hbox, FALSE, FALSE, 0);
- label = gtk_label_new (_("Delay"));
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
- spinner = gtk_spin_button_new_with_range (1, G_MAXINT, 1);
- gtk_box_pack_start (GTK_BOX (hbox), spinner, TRUE, TRUE, 0);
- label = gtk_label_new (_("seconds between auto-responses"));
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinner), purple_prefs_get_int (
- "/plugins/gtk/autoprofile/autorespond/delay"));
- g_signal_connect (G_OBJECT (spinner), "value-changed",
- G_CALLBACK (update_delay_respond), NULL);
- /* Auto-response message string */
- label = gtk_label_new (_("Message sent with first autoresponse:"));
- gtk_box_pack_start (GTK_BOX (large_vbox), label, FALSE, FALSE, 0);
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- entry = gtk_entry_new ();
- gtk_box_pack_start (GTK_BOX (large_vbox), entry, FALSE, FALSE, 0);
- gtk_entry_set_max_length (GTK_ENTRY (entry), 100);
- gtk_entry_set_text (GTK_ENTRY (entry), purple_prefs_get_string (
- "/plugins/gtk/autoprofile/autorespond/text"));
- g_signal_connect (G_OBJECT (entry), "focus-out-event",
- G_CALLBACK (update_behavior_string), "text_respond");
- label = gtk_label_new (_("Request trigger message:"));
- gtk_box_pack_start (GTK_BOX (large_vbox), label, FALSE, FALSE, 0);
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- entry = gtk_entry_new ();
- gtk_box_pack_start (GTK_BOX (large_vbox), entry, FALSE, FALSE, 0);
- gtk_entry_set_max_length (GTK_ENTRY (entry), 50);
- gtk_entry_set_text (GTK_ENTRY (entry), purple_prefs_get_string (
- "/plugins/gtk/autoprofile/autorespond/trigger"));
- g_signal_connect (G_OBJECT (entry), "focus-out-event",
- G_CALLBACK (update_behavior_string), "text_trigger");
- /* Sensitivity signals */
- g_signal_connect(G_OBJECT(checkbox), "clicked",
- G_CALLBACK(pidgin_toggle_sensitive), large_vbox);
- if (!purple_prefs_get_bool ("/plugins/gtk/autoprofile/autorespond/enable")) {
- gtk_widget_set_sensitive (large_vbox, FALSE);
- gtk_widget_set_sensitive (large_vbox, TRUE);
-/*----------------------------------------------------------------------------
- *--------------------------------------------------------------------------*/
-static GtkWidget *get_config_frame (PurplePlugin *plugin)
- GtkWidget *info = get_info_page ();
- gtk_widget_set_size_request (info, 350, 400);
-static void dialog_cb (GtkDialog *dialog, gint arg1, gpointer user_data)
- gtk_widget_destroy ((GtkWidget *)dialog);
-void ap_preferences_display ()
- GtkWidget *dialog, *notebook;
- notebook = gtk_notebook_new ();
- gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
- get_behavior_page (), gtk_label_new (_("General")));
- gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
- get_account_page (), gtk_label_new (_("User info/profiles")));
- gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
- get_autoreply_page (), gtk_label_new (_("Auto-reply")));
- g_object_set (notebook, "homogeneous", TRUE, NULL);
- dialog = gtk_dialog_new_with_buttons(PIDGIN_ALERT_TITLE, NULL,
- GTK_DIALOG_NO_SEPARATOR,
- GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
- gtk_container_add (GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), notebook);
- gtk_window_set_default_size (GTK_WINDOW(dialog), 400, 400);
- gtk_widget_show_all (dialog);
- g_signal_connect (G_OBJECT(dialog), "response",
- G_CALLBACK(dialog_cb), dialog);
-/*--------------- Generate the preference widget once ----------------*/
-PidginPluginUiInfo ui_info =
--- a/autoprofile/sizes.h Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 *
- *--------------------------------------------------------------------------*/
-/* Size definitions (0 indicates not compatible) */
-#define AP_SIZE_MAXIMUM 2048
-#define AP_SIZE_PROFILE_MAX 2048
-#define AP_SIZE_PROFILE_AIM 2048
-#define AP_SIZE_PROFILE_ICQ 0
-#define AP_SIZE_PROFILE_JABBER 0
-#define AP_SIZE_PROFILE_MSN 0
-#define AP_SIZE_PROFILE_YAHOO 0
-/* Away message sizes */
-#define AP_SIZE_AWAY_MAX 2048
-#define AP_SIZE_AWAY_AIM 2048
-/* Available message sizes */
-#define AP_SIZE_AVAILABLE_MAX 512
-#define AP_SIZE_AVAILABLE_AIM 60
-#define AP_SIZE_AVAILABLE_ICQ 0
-#define AP_SIZE_AVAILABLE_MSN 0
-#define AP_SIZE_AVAILABLE_YAHOO 512
-/* End size definitions */
--- a/autoprofile/utility.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,221 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 "autoprofile.h"
-/* TODO: get rid of this and port to glib time */
-static GStaticMutex time_mutex = G_STATIC_MUTEX_INIT;
-static struct tm *ap_tm_copy (const struct tm *t) {
- r = (struct tm *) malloc (sizeof (struct tm));
- r->tm_hour = t->tm_hour;
- r->tm_mday = t->tm_mday;
- r->tm_year = t->tm_year;
- r->tm_wday = t->tm_wday;
- r->tm_yday = t->tm_yday;
- r->tm_isdst = t->tm_isdst;
-struct tm *ap_localtime (const time_t *tp) {
- g_static_mutex_lock (&time_mutex);
- result = ap_tm_copy (localtime (tp));
- g_static_mutex_unlock (&time_mutex);
-struct tm *ap_gmtime (const time_t *tp) {
- g_static_mutex_lock (&time_mutex);
- result = ap_tm_copy (gmtime (tp));
- g_static_mutex_unlock (&time_mutex);
-/* Reads from fortune-style file and returns GList of each quote */
-static void fortune_helper (GString *s, gchar *data, gboolean escape_html) {
- g_string_append_printf (s, "<br>");
- case '"': g_string_append_printf (s, """); return;
- case '&': g_string_append_printf (s, "&"); return;
- case '<': g_string_append_printf (s, "<"); return;
- case '>': g_string_append_printf (s, ">"); return;
- g_string_append_unichar (s, g_utf8_get_char (data));
-GList *read_fortune_file (const char *filename, gboolean escape_html)
- gchar *raw_data, *raw_data_start;
- gchar *converted, *text;
- if (!g_file_test (filename, G_FILE_TEST_EXISTS)) {
- if (!g_file_get_contents (filename, &text, NULL, NULL)) {
- converted = purple_utf8_try_convert (text);
- if (converted != NULL) {
- raw_data_start = raw_data = purple_utf8_salvage (text);
- purple_str_strip_char (raw_data, '\r');
- /* Modeling the parser as a finite state machine */
- cur_quote = g_string_new ("");
- /* State after newline (potential quote) */
- if (*raw_data == '%') { // Found it
- quotes = g_list_append (quotes, strdup (cur_quote->str));
- g_string_truncate (cur_quote, 0);
- g_string_append_printf (cur_quote, "<br>");
- fortune_helper (cur_quote, raw_data, escape_html);
- /* State after end of a quote */
- if (*raw_data != '\n' && *raw_data != '%') {
- fortune_helper (cur_quote, raw_data, escape_html);
- if (*raw_data == '\n') {
- fortune_helper (cur_quote, raw_data, escape_html);
- raw_data = g_utf8_next_char (raw_data);
- if (strlen (cur_quote->str) > 0) {
- quotes = g_list_append (quotes, strdup (cur_quote->str));
- g_string_free (cur_quote, TRUE);
-/* Returns 1 if a pattern is found at the start of a string */
-int match_start (const char *text, const char *pattern)
- if (!*text || *pattern++ != *text++)
-/* Free's a GList as well as the internal contents */
-void free_string_list (GList *list)
-/* Check if string is in GList */
-gboolean string_list_find (GList *lst, const char *data)
- if (!strcmp (data, (char *) lst->data)) {
-/* Prints out debug messages with repetitive formatting completed */
-static void auto_debug_helper (
- PurpleDebugLevel level, const char *category, const char *message)
- g_string_printf (s, "%s: %s\n", category, message);
- purple_debug (level, "autoprofile", "%s", s->str);
- g_string_free (s, TRUE);
-void ap_debug (const char *category, const char *message) {
- auto_debug_helper (PURPLE_DEBUG_INFO, category, message);
-void ap_debug_misc (const char *category, const char *message) {
- auto_debug_helper (PURPLE_DEBUG_MISC, category, message);
-void ap_debug_warn (const char *category, const char *message) {
- auto_debug_helper (PURPLE_DEBUG_WARNING, category, message);
-void ap_debug_error (const char *category, const char *message) {
- auto_debug_helper (PURPLE_DEBUG_ERROR, category, message);
--- a/autoprofile/utility.h Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 *
- *--------------------------------------------------------------------------*/
-struct tm *ap_localtime (const time_t *);
-struct tm *ap_gmtime (const time_t *);
-GList *read_fortune_file (const char *, gboolean);
-int match_start (const char *, const char *);
-void free_string_list (GList *);
-gboolean string_list_find (GList *, const char *);
-void ap_debug (const char *, const char *);
-void ap_debug_misc (const char *, const char *);
-void ap_debug_warn (const char *, const char *);
-void ap_debug_error (const char *, const char *);
-time_t rfc_parse_date_time (const char *data);
-int rfc_parse_was_gmt ();
--- a/autoprofile/utility_rfc822.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,191 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 "autoprofile.h"
-static struct tm parsed_datetime;
-static int parsed_gmttime = 0;
-/* Strip leading whitespace */
-static const char* rfc_parse_whitespace (const char *data) {
- while (*data && isspace (*data))
-/* Strip leading digits */
-static const char* rfc_parse_num (const char *data) {
- while (*data && isdigit (*data))
-/* Strip leading whitespace and digits */
-static const char* rfc_parse_whitespace_num (const char *data) {
- while (*data && (isspace (*data) || isdigit (*data)))
-static const char* rfc_parse_date (const char *data) {
- sscanf (data, "%d", &day);
- data = rfc_parse_whitespace_num (data);
- sscanf (data, "%s", month);
- if (!strcmp (month, "Jan")) { monthnum = 0; } else
- if (!strcmp (month, "Feb")) { monthnum = 1; } else
- if (!strcmp (month, "Mar")) { monthnum = 2; } else
- if (!strcmp (month, "Apr")) { monthnum = 3; } else
- if (!strcmp (month, "May")) { monthnum = 4; } else
- if (!strcmp (month, "Jun")) { monthnum = 5; } else
- if (!strcmp (month, "Jul")) { monthnum = 6; } else
- if (!strcmp (month, "Aug")) { monthnum = 7; } else
- if (!strcmp (month, "Sep")) { monthnum = 8; } else
- if (!strcmp (month, "Oct")) { monthnum = 9; } else
- if (!strcmp (month, "Nov")) { monthnum = 10; } else
- if (!strcmp (month, "Dec")) { monthnum = 11; }
- sscanf (data, "%d", &year);
- data = rfc_parse_whitespace (data);
- data = rfc_parse_num (data);
- } else if (year > 100) {
- parsed_datetime.tm_mday = day;
- parsed_datetime.tm_mon = monthnum;
- parsed_datetime.tm_year = year;
-static const char* rfc_parse_hour (const char *data) {
- sscanf (data, "%d", &hour);
- data = strchr (data, ':');
- sscanf (++data, "%d", &minutes);
- if (strchr (data, ':')) {
- data = strchr (data, ':') + 1;
- sscanf (data, "%d", &seconds);
- data = rfc_parse_whitespace_num (data);
- parsed_datetime.tm_hour = hour;
- parsed_datetime.tm_min = minutes;
- parsed_datetime.tm_sec = seconds;
-static const char *rfc_parse_zone (const char *data) {
- if (strstr (data, "GMT"))
-static const char* rfc_parse_time (const char *data) {
- data = rfc_parse_hour (data);
- data = rfc_parse_zone (data);
-static const char* rfc_parse_day (const char *data) {
- return strchr (data, ',') + 1;
-int rfc_parse_was_gmt () {
-time_t rfc_parse_date_time (const char *data) {
- /* Initialize values */
- parsed_datetime.tm_sec = 0;
- parsed_datetime.tm_min = 0;
- parsed_datetime.tm_hour = 0;
- parsed_datetime.tm_mday = 0;
- parsed_datetime.tm_mon = 0;
- parsed_datetime.tm_year = 0;
- parsed_datetime.tm_isdst = -1;
- data = rfc_parse_whitespace (data);
- data = rfc_parse_day (data);
- data = rfc_parse_date (data);
- data = rfc_parse_time (data);
- result = mktime(&parsed_datetime);
- if (rfc_parse_was_gmt ())
- struct tm *x = rfc_parse_date_time ("Mon, 06 Jun 2005 20:24:18 GMT");
- printf ("Sec: %d\n", x->tm_sec);
- printf ("Min: %d\n", x->tm_min);
- printf ("Hour: %d\n", x->tm_hour);
- printf ("Day: %d\n", x->tm_mday);
- printf ("Month: %d\n", x->tm_mon);
- printf ("Year: %d\n", x->tm_year);
- printf ("GMT: %d\n", parsed_gmttime);
--- a/autoprofile/widget.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,607 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 "../common/pp_internal.h"
-static GStaticMutex widget_mutex = G_STATIC_MUTEX_INIT;
-static GList *widgets = NULL;
-static GHashTable *identifiers = NULL;
-static char *widget_pref = "/plugins/gtk/autoprofile/widgets/widget_ids";
-static void ap_widget_init_default_statuses ()
- // Make sure we don't keep on readding the default statuses if a user
- if (!purple_prefs_exists (widget_pref)) {
- purple_prefs_add_none ("/plugins/gtk/autoprofile/widgets/42");
- purple_prefs_add_string (
- "/plugins/gtk/autoprofile/widgets/42/component", "Timestamp");
- purple_prefs_add_string (
- "/plugins/gtk/autoprofile/widgets/42/alias", "Timestamp");
- purple_prefs_add_string (
- "/plugins/gtk/autoprofile/widgets/42/timestamp_format",
- "Automatically created at %I:%M %p");
-void ap_widget_init () {
- ap_widget_init_default_statuses ();
- node = g_list_append (NULL, g_strdup ("42"));
- purple_prefs_add_string_list (widget_pref, node);
- free_string_list (node);
-static gchar *strip_whitespace (const gchar *text) {
- gchar *result, *end, *search;
- while (isspace (*text)) {
- search = result = g_strdup (text);
- if (end == NULL && isspace (*search)) {
- if (!isspace (*search)) {
- if (end != NULL) *end = '\0';
-static void update_widget_ids () {
- struct widget *cur_widget;
- for (cur_node = widgets; cur_node != NULL; cur_node = cur_node->next) {
- cur_widget = (struct widget *) cur_node->data;
- ids = g_list_append (ids, cur_widget->wid);
- purple_prefs_set_string_list (widget_pref, ids);
-// Mutex is ALREADY HELD when this function is called
-static struct widget *ap_widget_find_internal (const gchar *search_text) {
- struct widget *cur_widget;
- alias = strip_whitespace (search_text);
- cur_widget = (struct widget *) cur_node->data;
- if (!purple_utf8_strcasecmp (alias, cur_widget->alias)) {
- cur_node = cur_node->next;
-struct widget *ap_widget_find (const gchar *search_text) {
- g_static_mutex_lock (&widget_mutex);
- w = ap_widget_find_internal (search_text);
- g_static_mutex_unlock (&widget_mutex);
-struct widget *ap_widget_find_by_identifier (const gchar *search_text) {
- g_static_mutex_lock (&widget_mutex);
- w = (struct widget *) g_hash_table_lookup (identifiers, search_text);
- g_static_mutex_unlock (&widget_mutex);
-void ap_widget_start () {
- GList *widget_identifiers, *widget_identifiers_start;
- const gchar *identifier, *component_identifier;
- struct component *comp;
- g_static_mutex_lock (&widget_mutex);
- identifiers = g_hash_table_new (g_str_hash, g_str_equal);
- pref_name = g_string_new ("");
- widget_identifiers_start = purple_prefs_get_string_list (widget_pref);
- for (widget_identifiers = widget_identifiers_start;
- widget_identifiers != NULL;
- widget_identifiers = widget_identifiers->next) {
- g_string_printf (pref_name,
- "/plugins/gtk/autoprofile/widgets/%s/component",
- (gchar *) widget_identifiers->data);
- component_identifier = purple_prefs_get_string (pref_name->str);
- if (component_identifier == NULL) {
- ap_debug_error ("widget", "widget does not have component information");
- comp = ap_component_get_component (component_identifier);
- ap_debug_error ("widget", "no component matches widget identifier");
- g_string_printf (pref_name,
- "/plugins/gtk/autoprofile/widgets/%s/alias",
- (gchar *) widget_identifiers->data);
- identifier = purple_prefs_get_string (pref_name->str);
- if (identifier == NULL) {
- ap_debug_error ("widget", "widget does not have alias information");
- w = ap_widget_find_internal (identifier);
- ap_debug_error ("widget", "widget alias already in use");
- w = (struct widget *) malloc (sizeof (struct widget));
- w->alias = g_strdup (identifier);
- w->wid = g_strdup ((gchar *) widget_identifiers->data);
- w->data = g_hash_table_new (NULL, NULL);
- widgets = g_list_append (widgets, w);
- g_hash_table_insert (identifiers, w->wid, w);
- if (w->component->load) {
- w->component->load (w);
- g_string_printf (pref_name,
- "loaded saved widget with alias %s and identifier %s",
- ap_debug_misc ("widget", pref_name->str);
- free_string_list (widget_identifiers_start);
- g_string_free (pref_name, TRUE);
- g_static_mutex_unlock (&widget_mutex);
- ap_widget_gtk_start ();
-void ap_widget_finish () {
- g_static_mutex_lock (&widget_mutex);
- ap_widget_gtk_finish ();
- g_hash_table_destroy (identifiers);
- w = (struct widget *) widgets->data;
- if (w->component->unload) {
- w->component->unload (w);
- g_hash_table_destroy (w->data);
- g_list_free_1 (widgets);
- g_static_mutex_unlock (&widget_mutex);
-gboolean ap_widget_has_content_changed () {
- gboolean changed = FALSE;
- g_static_mutex_lock (&widget_mutex);
- for (node = widgets; node != NULL; node = node->next) {
- w = (struct widget *) node->data;
- if (w->component->has_content_changed == NULL ||
- w->component->has_content_changed (w)) {
- g_static_mutex_unlock (&widget_mutex);
-GList *ap_widget_get_widgets () {
- g_static_mutex_lock (&widget_mutex);
- result = g_list_copy (widgets);
- g_static_mutex_unlock (&widget_mutex);
-struct widget *ap_widget_create (struct component *comp)
- gchar *identifier, *alias;
- g_static_mutex_lock (&widget_mutex);
- // Sanity check to make sure we dont "delete" old widgets by
- if (identifiers == NULL) {
- ap_debug_warn ("widget",
- "tried to create widget when variables unitialized");
- g_static_mutex_unlock (&widget_mutex);
- ap_debug ("widget", "instantiating new widget from component");
- w = ap_widget_find_internal (comp->identifier);
- alias = NULL; // Stupid compiler
- alias = g_strdup (comp->identifier);
- for (i = 1; i < 10000; i++) {
- g_string_printf (s, "%s%d", comp->identifier, i);
- w = ap_widget_find_internal (s->str);
- alias = g_strdup (s->str);
- // This would happen....very very rarely...
- ap_debug_error ("widget", "ran out of aliases for component");
- g_string_free (s, TRUE);
- g_static_mutex_unlock (&widget_mutex);
- g_string_printf (s, "%d", i);
- w = (struct widget *) node->data;
- if (!strcmp (s->str, w->wid)) {
- identifier = g_strdup (s->str);
- w = (struct widget *) malloc (sizeof (struct widget));
- w->data = g_hash_table_new (NULL, NULL);
- widgets = g_list_append (widgets, w);
- g_hash_table_insert (identifiers, w->wid, w);
- g_string_printf (s, "/plugins/gtk/autoprofile/widgets/%s", w->wid);
- purple_prefs_add_none (s->str);
- g_string_printf (s, "/plugins/gtk/autoprofile/widgets/%s/component",
- purple_prefs_add_string (s->str, w->component->identifier);
- g_string_printf (s, "/plugins/gtk/autoprofile/widgets/%s/alias", w->wid);
- purple_prefs_add_string (s->str, w->alias);
- if (w->component->init_pref) {
- w->component->init_pref (w);
- if (w->component->load) {
- w->component->load (w);
- g_string_printf (s, "Created widget with alias %s and identifier %s",
- ap_debug ("widget", s->str);
- g_string_free (s, TRUE);
- g_static_mutex_unlock (&widget_mutex);
-void ap_widget_delete (struct widget *w) {
- ap_debug_error ("widget", "attempt to delete NULL widget");
- g_static_mutex_lock (&widget_mutex);
- // Sanity check to make sure we dont "delete" old widgets by
- if (identifiers == NULL) {
- ap_debug_warn ("widget",
- "tried to delete widget when variables unitialized");
- g_static_mutex_unlock (&widget_mutex);
- g_string_printf (s, "Deleting widget with alias %s and identifier %s",
- ap_debug ("widget", s->str);
- widgets = g_list_remove (widgets, w);
- g_hash_table_remove (identifiers, w->wid);
- g_string_printf (s, "/plugins/gtk/autoprofile/widgets/%s", w->wid);
- purple_prefs_remove (s->str);
- g_string_free (s, TRUE);
- if (w->component->unload) {
- w->component->unload (w);
- g_hash_table_destroy (w->data);
- g_static_mutex_unlock (&widget_mutex);
-// TRUE if rename succeeds, FALSE otherwise
-gboolean ap_widget_rename (struct widget *orig, const gchar *new_alias) {
- g_static_mutex_lock (&widget_mutex);
- w = ap_widget_find_internal (new_alias);
- if (w != NULL && w != orig) {
- g_static_mutex_unlock (&widget_mutex);
- orig_alias = orig->alias;
- orig->alias = g_strdup (new_alias);
- g_string_printf (s, "/plugins/gtk/autoprofile/widgets/%s/alias", orig->wid);
- purple_prefs_set_string (s->str, new_alias);
- g_string_printf (s, "Changed alias of widget from %s to %s",
- orig_alias, new_alias);
- ap_debug ("widget", s->str);
- g_string_free (s, TRUE);
- g_static_mutex_unlock (&widget_mutex);
-/* Widget data galore! */
-void ap_widget_set_data (struct widget *w, int id, gpointer data) {
- g_static_mutex_lock (&widget_mutex);
- g_hash_table_insert (w->data, GINT_TO_POINTER(id), data);
- g_static_mutex_unlock (&widget_mutex);
-gpointer ap_widget_get_data (struct widget *w, int id) {
- g_static_mutex_lock (&widget_mutex);
- result = g_hash_table_lookup (w->data, GINT_TO_POINTER(id));
- g_static_mutex_unlock (&widget_mutex);
-/* Widget preferences galore! */
-gchar *ap_prefs_get_pref_name (struct widget *w, const char *name) {
- g_string_append (s, "/plugins/gtk/autoprofile/widgets/");
- g_string_append_printf (s, "%s/%s", w->wid, name);
- g_string_free (s, FALSE);
-void ap_prefs_add_bool (struct widget *w, const char *name, gboolean value) {
- gchar *pref = ap_prefs_get_pref_name (w, name);
- purple_prefs_add_bool (pref, value);
-void ap_prefs_add_int (struct widget *w, const char *name, int value) {
- gchar *pref = ap_prefs_get_pref_name (w, name);
- purple_prefs_add_int (pref, value);
-void ap_prefs_add_none (struct widget *w, const char *name) {
- gchar *pref = ap_prefs_get_pref_name (w, name);
- purple_prefs_add_none (pref);
-void ap_prefs_add_string (struct widget *w, const char *name,
- gchar *pref = ap_prefs_get_pref_name (w, name);
- purple_prefs_add_string (pref, value);
-void ap_prefs_add_string_list (struct widget *w, const char *name,
- gchar *pref = ap_prefs_get_pref_name (w, name);
- purple_prefs_add_string_list (pref, value);
-gboolean ap_prefs_get_bool (struct widget *w, const char *name) {
- gchar *pref = ap_prefs_get_pref_name (w, name);
- result = purple_prefs_get_bool (pref);
-int ap_prefs_get_int (struct widget *w, const char *name) {
- gchar *pref = ap_prefs_get_pref_name (w, name);
- result = purple_prefs_get_int (pref);
-const char *ap_prefs_get_string (struct widget *w, const char *name) {
- gchar *pref = ap_prefs_get_pref_name (w, name);
- result = purple_prefs_get_string (pref);
-GList *ap_prefs_get_string_list (struct widget *w, const char *name) {
- gchar *pref = ap_prefs_get_pref_name (w, name);
- result = purple_prefs_get_string_list (pref);
-void ap_prefs_set_bool (struct widget *w, const char *name, gboolean value) {
- gchar *pref = ap_prefs_get_pref_name (w, name);
- purple_prefs_set_bool (pref, value);
- ap_widget_prefs_updated (w);
-void ap_prefs_set_int (struct widget *w, const char *name, int value) {
- gchar *pref = ap_prefs_get_pref_name (w, name);
- purple_prefs_set_int (pref, value);
- ap_widget_prefs_updated (w);
-void ap_prefs_set_string (struct widget *w, const char *name,
- gchar *pref = ap_prefs_get_pref_name (w, name);
- purple_prefs_set_string (pref, value);
- ap_widget_prefs_updated (w);
-void ap_prefs_set_string_list (struct widget *w, const char *name,
- gchar *pref = ap_prefs_get_pref_name (w, name);
- purple_prefs_set_string_list (pref, value);
- ap_widget_prefs_updated (w);
--- a/autoprofile/widget.h Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/*--------------------------------------------------------------------------*
- * A Purple away message and profile manager that supports dynamic text *
- * AutoProfile is the legal property of its developers. Please refer to *
- * the COPYRIGHT file distributed with this source distribution. *
- * 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 *
- *--------------------------------------------------------------------------*/
-/* The heart of everything */
- struct component *component;
-void ap_widget_start ();
-void ap_widget_finish ();
-void ap_widget_gtk_start ();
-void ap_widget_gtk_finish ();
-gboolean ap_widget_has_content_changed ();
-GList *ap_widget_get_widgets ();
-struct widget *ap_widget_find (const gchar *);
-struct widget *ap_widget_find_by_identifier (const gchar *);
-struct widget *ap_widget_create (struct component *);
-void ap_widget_delete (struct widget *);
-// TRUE if rename succeeds, FALSE otherwise
-gboolean ap_widget_rename (struct widget *, const gchar *);
-GtkWidget *ap_widget_get_config_page ();
-void ap_widget_prefs_updated (struct widget *);
-GtkWidget *get_widget_list (GtkWidget *, GtkTreeSelection **);
-void done_with_widget_list ();
-/* Widget data galore! */
-void ap_widget_set_data (struct widget *, int, gpointer);
-gpointer ap_widget_get_data (struct widget *, int);
-/* Widget preferences galore! */
-gchar *ap_prefs_get_pref_name (struct widget *, const char *);
-GtkWidget *ap_prefs_checkbox (struct widget *, const char *, const char *,
-GtkWidget *ap_prefs_dropdown_from_list (struct widget *, GtkWidget *,
- const gchar *, PurplePrefType, const char *, GList *);
-GtkWidget *ap_prefs_labeled_entry (struct widget *, GtkWidget *page,
- const gchar *, const char *, GtkSizeGroup *);
-GtkWidget *ap_prefs_labeled_spin_button (struct widget *, GtkWidget *,
- const gchar *, const char *, int, int, GtkSizeGroup *);
-void ap_prefs_add_bool (struct widget *, const char *name, gboolean value);
-void ap_prefs_add_int (struct widget *, const char *name, int value);
-void ap_prefs_add_none (struct widget *, const char *name);
-void ap_prefs_add_string (struct widget *, const char *, const char *);
-void ap_prefs_add_string_list (struct widget *, const char *, GList *);
-gboolean ap_prefs_get_bool (struct widget *, const char *name);
-int ap_prefs_get_int (struct widget *, const char *name);
-const char * ap_prefs_get_string (struct widget *, const char *name);
-GList * ap_prefs_get_string_list (struct widget *, const char *name);
-void ap_prefs_set_bool (struct widget *, const char *name, gboolean value);
-void ap_prefs_set_int (struct widget *, const char *name, int value);
-void ap_prefs_set_string (struct widget *, const char *name, const char *);
-void ap_prefs_set_string_list (struct widget *, const char *, GList *);
-#endif /* _AP_WIDGET_H_ */
--- a/awaynotify/README.md Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-# Away State Notification
-Shows when someone goes away/back in a conversation.
--- a/awaynotify/awaynotify.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,268 +0,0 @@
- * awaynotify - show notices when status changes
- * Copyright (C) 2005-2008 Matt Perry <guy@somewhere.fscked.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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
-/* If you can't figure out what this line is for, DON'T TOUCH IT. */
-#include "../common/pp_internal.h"
-#include <conversation.h>
-#define PLUGIN_ID "core-plugin_pack-awaynotify"
-#define CHECK_AWAY_MESSAGE_TIME_MS 1000
-typedef struct _Infochecker Infochecker;
- PurpleAccount *account;
-GList* infochecker_list = NULL;
-static gint infocheck_timeout(gpointer data);
-static Infochecker* infocheck_new(PurpleAccount* account, char* buddy)
- Infochecker* checker = g_new0(Infochecker, 1);
- checker->account = account;
- checker->buddy = g_strdup(buddy);
-static void infocheck_delete(Infochecker* checker)
- g_free(checker->buddy);
-static void infocheck_remove(GList* node)
- Infochecker* checker = (Infochecker*)node->data;
- g_source_remove(checker->timeout_id);
- infochecker_list = g_list_remove_link(infochecker_list, node);
- infocheck_delete(checker);
-static gint infocheck_compare(gconstpointer pa, gconstpointer pb)
- Infochecker* a = (Infochecker*)pa;
- Infochecker* b = (Infochecker*)pb;
- return (a->account == b->account) ? strcmp(a->buddy, b->buddy) : 1;
-static void write_status(PurpleBuddy *buddy, const char *message, const char* status)
- PurpleConversation *conv;
- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, buddy->account);
- who = purple_buddy_get_alias(buddy);
- escaped = g_markup_escape_text(who, -1);
- g_snprintf(buf, sizeof(buf), message, escaped, status);
- purple_conversation_write(conv, NULL, buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
-static char* parse_away_message(char* statustext)
- char* away_ptr = strstr(statustext, "Away Message:");
- away_ptr += 4 + 1 + 7 + 1;
- if (*away_ptr == '<') {
- char* tmp = strchr(away_ptr, '>');
- if (tmp) away_ptr = tmp + 1;
- while (*away_ptr == ' ') away_ptr++;
- return g_strdup(away_ptr);
-static char* get_away_message(PurpleBuddy* buddy)
- PurplePluginProtocolInfo *prpl_info = NULL;
- char* statustext = NULL;
- prpl = purple_find_prpl(purple_account_get_protocol_id(buddy->account));
- prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
- if (prpl_info && prpl_info->tooltip_text) {
- char *statustext = NULL;
- PurpleNotifyUserInfo *info = purple_notify_user_info_new();
- prpl_info->tooltip_text(buddy, info, TRUE);
- statustext = purple_notify_user_info_get_text_with_newline(info, "\n");
- purple_notify_user_info_destroy(info);
- if (statustext && !g_utf8_validate(statustext, -1, &end)) {
- char *new = g_strndup(statustext, g_utf8_pointer_to_offset(statustext, end));
- char* away_message = parse_away_message(statustext);
-static gint infocheck_timeout(gpointer data)
- GList* node = (GList*)data;
- Infochecker* checker = node ? (Infochecker*)node->data : NULL;
- if (node == NULL || checker == NULL) {
- purple_debug_warning("awaynotify", "checker called without being active!\n");
- buddy = purple_find_buddy(checker->account, checker->buddy);
- away_message = get_away_message(buddy);
- if (away_message == NULL) {
- /* He must have signed off or there was some other error. Give up. */
- infocheck_remove(node);
- if (away_message[0] == 0) {
- /* Not away yet. Return true to try again. */
- write_status(buddy, _("%s is away: %s"), away_message);
- infocheck_remove(node);
-static void infocheck_add(Infochecker* checker)
- infochecker_list = g_list_prepend(infochecker_list, checker);
- checker->timeout_id = g_timeout_add(CHECK_AWAY_MESSAGE_TIME_MS,
- infocheck_timeout, g_list_first(infochecker_list));
-static void buddy_away_cb(PurpleBuddy *buddy, void *data)
- if (purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, buddy->account) == NULL)
- return; /* Ignore if there's no conv open. */
- infocheck_add(infocheck_new(buddy->account, buddy->name));
-static void buddy_unaway_cb(PurpleBuddy *buddy, void *data)
- GList* node = g_list_find_custom(infochecker_list, buddy->name, infocheck_compare);
- infocheck_remove(node);
- write_status(buddy, _("%s is no longer away."), NULL);
-static gboolean plugin_load(PurplePlugin *plugin)
- void *blist_handle = purple_blist_get_handle();
- purple_signal_connect(blist_handle, "buddy-away",
- plugin, PURPLE_CALLBACK(buddy_away_cb), NULL);
- purple_signal_connect(blist_handle, "buddy-back",
- plugin, PURPLE_CALLBACK(buddy_unaway_cb), NULL);
-static PurplePluginInfo info =
- PURPLE_PLUGIN_STANDARD, /**< type */
- NULL, /**< ui_requirement */
- NULL, /**< dependencies */
- PURPLE_PRIORITY_DEFAULT, /**< priority */
- PP_VERSION, /**< version */
- NULL, /** description */
- "Matt Perry <guy@somewhere.fscked.org>", /**< author */
- PP_WEBSITE, /**< homepage */
- plugin_load, /**< load */
- NULL, /**< extra_info */
- NULL, /**< prefs_info */
-init_plugin(PurplePlugin *plugin)
- info.name = _("Away State Notification");
- _("Notifies in a conversation window when a buddy goes or returns from away");
- info.description = info.summary;
-PURPLE_INIT_PLUGIN(statenotify, init_plugin, info)
--- a/awaynotify/meson.build Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-if TYPES.contains('incomplete') and PURPLE.found()
- awaynotify = shared_library('awaynotify',
- dependencies : [PURPLE, GLIB],
- install_dir : PURPLE_LIBDIR)
- PP_PURPLE_BUILD += 'awaynotify'
--- a/bit/README.md Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-Tools to manipulate buddy icons *DANGEROUS*.
-Whilst working on Purple 2.0.0, I found a need to destroy all my buddies' buddy icons. There's nothing to do these functions in Purple, so here they are. Completely, thoroughly untested.
--- a/bit/bit.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,240 +0,0 @@
- * Copyright (C) 2005-2008 Peter Lawler <bleeter from users.sf.net>
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
-/* If you can't figure out what this line is for, DON'T TOUCH IT. */
-#include "../common/pp_internal.h"
-PurplePlugin *bit = NULL; /* the request api prefers this for a plugin */
-static PurpleBuddyList *buddies = NULL;
-/* TODO: Add a function to clear unused icons */
-/* TODO: Ensure all this stuff I have at the moment is safe for others to use */
-blist_iterate_action(gboolean remove)
- PurpleBlistNode *node = NULL;
- PurpleConversation *conv = NULL;
- /* this grabs the purple buddy list, which will be walked through */
- buddies = purple_get_blist();
- /* Use the utility function to loop over the nodes of the tree */
- for (node = buddies->root; node && PURPLE_BLIST_NODE_IS_BUDDY(node);
- node = purple_blist_node_next(node, TRUE)) {
- PurpleBuddy *buddy = (PurpleBuddy *)node;
- const char *tmpname = purple_buddy_get_name(buddy);
- PurpleBuddyIcon *icon = purple_buddy_get_icon(buddy);
- purple_debug_info("bit", "Processing %s (%p)\n", tmpname, icon);
- if (!icon->ref_count > 0 && remove == TRUE) {
- for ( n = icon->ref_count; n !=0; n-- ) {
- purple_debug_info("bit", "ref_count: %d\n", n);
- purple_buddy_icon_unref(icon);
- /* XXX: This *may* cause a segfault. - Sadrul */
- purple_debug_info("bit", "Uncaching icon for %s\n", tmpname);
- /* XXX: The new buddy icon API doesn't have purple_buddy_icon_uncache() */
- purple_buddy_icon_uncache(buddy);
- /* XXX: This *definately* causes a segfault. From reading the
- * source, I may not need to unref but just straight destroy it
- * haven't played/investigated enough to decide if I want to
- * keep/move/delete this - Bleeter
- purple_debug_info("bit", "Destroying icon for %s\n", tmpname);
- purple_buddy_icon_destroy(icon);*/
- purple_debug_info("bit", "No icon to flush for %s\n", tmpname);
- if (purple_account_is_connected(purple_buddy_get_account(buddy))) {
- purple_debug_info("bit", "Updating icon for %s\n",
- purple_blist_update_buddy_icon(buddy);
- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
- tmpname,purple_buddy_get_account(buddy));
- purple_conversation_update(conv, PURPLE_CONV_UPDATE_ICON);
-flush_buddy_icon_action(PurplePluginAction *action)
- blist_iterate_action(TRUE);
-refresh_buddy_icon_action(PurplePluginAction *action)
- blist_iterate_action(FALSE);
-destroy_unused_icons_action(PurplePluginAction *action)
- const char *path, *filename;
- path = purple_buddy_icons_get_cache_dir();
- str = g_strdup_printf(_("Unable to locate the buddy icon cache directory %s"), path);
- purple_debug_error("bit", str);
- purple_notify_error(bit, _("Destroy Unused Icons"), _("Unable to locate"),
- if (!(dir = g_dir_open(path, 0, NULL))) {
- str = g_strdup_printf(_("Unable to read the buddy icon cache directory %s"), path);
- purple_debug_error("bit", str);
- purple_notify_error(bit, _("Destroy Unused Icons"), _("Unable to read"),
- while ((filename = g_dir_read_name(dir))) {
- PurpleBlistNode *cur_node = NULL;
- PurpleConversation *conv = NULL;
- buddies = purple_get_blist();
- for (cur_node = buddies->root; cur_node;
- cur_node = purple_blist_node_next(cur_node, TRUE)) {
- if(PURPLE_BLIST_NODE_IS_BUDDY(cur_node)) {
- PurpleBuddy *buddy = (PurpleBuddy *)cur_node;
- const char *tmpname = purple_buddy_get_name(buddy);
- PurpleBuddyIcon *icon = purple_buddy_get_icon(buddy);
- /* store each found icon FILENAME into *l */
- /* checksums are done in prpl, so don't bother trying */
- /* remove files not in SOMWHERE*/
- purple_debug_info("bit", "Filename %s\n", filename);
- type = purple_buddy_icon_get_type(filename);
- purple_debug_info("bit", "Type %s\n", type);
-bit_actions(PurplePlugin *plugin, gpointer context)
- PurplePluginAction *act = NULL;
-/* buddy icon structs currently suck, I think
- it's impossible to tell from a filename which buddy it's associated with
- without going through every file, and the blist...
- ... a huge hash type table *may help*, but I'd consider it highly inefficient
- then again, some of the stuff in here ain't exactly a TGV either */
- act = purple_plugin_action_new(_("Destroy Unused Icons"),
- destroy_unused_icons_action);
- list = g_list_append(list, act);
- act = purple_plugin_action_new(_("Flush Buddy Icons"),
- flush_buddy_icon_action);
- list = g_list_append(list, act);
- act = purple_plugin_action_new(_("Refresh Buddy Icons"),
- refresh_buddy_icon_action);
- list = g_list_append(list, act);
- purple_debug_info("bit", "Action list created\n");
-static PurplePluginInfo info =
- PURPLE_PLUGIN_MAGIC, /**< magic */
- PURPLE_MAJOR_VERSION, /**< major version */
- PURPLE_MINOR_VERSION, /**< minor version */
- PURPLE_PLUGIN_STANDARD, /**< type */
- NULL, /**< ui_requirement */
- NULL, /**< dependencies */
- PURPLE_PRIORITY_DEFAULT, /**< priority */
- "core-plugin_pack-bit", /**< id */
- PP_VERSION, /**< version */
- NULL, /** description */
- "Peter Lawler <bleeter from users.sf.net>",
- PP_WEBSITE, /**< homepage */
- NULL, /**< extra_info */
- NULL, /**< prefs_info */
- bit_actions, /**< actions */
- NULL, /**< reserved 1 */
- NULL, /**< reserved 2 */
- NULL, /**< reserved 3 */
- NULL /**< reserved 4 */
-init_plugin(PurplePlugin *plugin)
- bindtextdomain(GETTEXT_PACKAGE, PP_LOCALEDIR);
- bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
- info.name = _("Buddy Icon Tools");
- info.summary = _("Tools to manipulate buddy icons. *DANGEROUS*");
- info.description = _("Whilst working on Purple 2.0.0, I found a need to "
- "destroy all my buddies' buddy icons. There's nothing to do "
- "these functions in Purple, so here they are. Completely, "
- "thoroughly untested.");
- bit = plugin; /* handle needed for request API file selector */
-PURPLE_INIT_PLUGIN(bit, init_plugin, info)
--- a/bit/meson.build Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-if TYPES.contains('incomplete') and PIDGIN.found()
- bit = shared_module('bit',
- dependencies : [PIDGIN, GTK],
- install_dir : PIDGIN_LIBDIR)
- PP_PIDGIN_BUILD += 'bit'
--- a/buddytime/README.md Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-dependencies: libpurple, pidgin (optional)
-authors: Gary Kramlich, Richard Laager
-Quickly see the local time of a buddy.
--- a/buddytime/buddyedit.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,412 +0,0 @@
-/*************************************************************************
- * A Purple plugin that adds an edit to to buddies allowing you to change
- * various details you can't normally change. It also provides a mechanism
- * for subsequent plugins to add themselves to that dialog.
- * by Martijn van Oosterhout <kleptog@svana.org> (C) April 2006
- * Some code copyright (C) 2006, Richard Laager <rlaager@users.sf.net>
- * 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
- *************************************************************************/
-#define PLUGIN "core-kleptog-buddyedit"
-#include "debug.h" /* Debug output functions */
-#include "request.h" /* Requests stuff */
-static PurplePlugin *plugin_self;
-buddyedit_editcomplete_cb(PurpleBlistNode * data, PurpleRequestFields * fields)
- gboolean blist_destroy = FALSE;
- PurpleBlistNode *olddata = data; /* Keep pointer in case we need to destroy it */
- /* Account detail stuff */
- case PURPLE_BLIST_BUDDY_NODE:
- PurpleBuddy *buddy = (PurpleBuddy *) data;
- PurpleAccount *account = purple_request_fields_get_account(fields, "account");
- const char *name = purple_request_fields_get_string(fields, "name");
- const char *alias = purple_request_fields_get_string(fields, "alias");
- /* If any details changes, create the buddy */
- if((account != buddy->account) || strcmp(name, buddy->name))
- PurpleBuddy *newbuddy = purple_buddy_new(account, name, alias);
- purple_blist_add_buddy(newbuddy, NULL, NULL, data); /* Copy it to correct location */
- /* Now this is ugly, but we want to copy the settings and avoid issues with memory management */
- tmp = ((PurpleBlistNode *) buddy)->settings;
- ((PurpleBlistNode *) buddy)->settings = ((PurpleBlistNode *) newbuddy)->settings;
- ((PurpleBlistNode *) newbuddy)->settings = tmp;
- data = (PurpleBlistNode *) newbuddy;
- purple_blist_alias_buddy(buddy, alias);
- case PURPLE_BLIST_CONTACT_NODE:
- PurpleContact *contact = (PurpleContact *) data;
- const char *alias = purple_request_fields_get_string(fields, "alias");
- purple_contact_set_alias(contact, alias);
- case PURPLE_BLIST_GROUP_NODE:
- PurpleGroup *group = (PurpleGroup *) data;
- const char *alias = purple_request_fields_get_string(fields, "alias");
- purple_blist_rename_group(group, alias);
- case PURPLE_BLIST_CHAT_NODE:
- PurpleChat *chat = (PurpleChat *) data;
- gboolean new_chat = FALSE;
- GList *list = NULL, *tmp;
- gc = purple_account_get_connection(chat->account);
- if(PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info != NULL)
- list = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info(gc);
- PurpleAccount *newaccount = purple_request_fields_get_account(fields, "account");
- /* In Purple2 each prot_chat_entry has a field "required". We use
- * this to determine if a field is important enough to recreate
- * the chat if it changes. Non-required fields we just change
- if(newaccount != chat->account)
- const char *oldvalue, *newvalue;
- for (tmp = g_list_first(list); tmp && !new_chat; tmp = g_list_next(tmp))
- struct proto_chat_entry *pce = tmp->data;
- if(!pce->required) /* Only checking required fields at this point */
- continue; /* Not yet */
- oldvalue = g_hash_table_lookup(chat->components, pce->identifier);
- newvalue = purple_request_fields_get_string(fields, pce->identifier);
- if(strcmp(oldvalue, newvalue) != 0)
- const char *oldvalue, *newvalue;
- GHashTable *components =
- g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
- for (tmp = g_list_first(list); tmp; tmp = g_list_next(tmp))
- struct proto_chat_entry *pce = tmp->data;
- oldvalue = g_hash_table_lookup(chat->components, pce->identifier);
- g_hash_table_replace(components, g_strdup(pce->identifier),
- newvalue = purple_request_fields_get_string(fields, pce->identifier);
- g_hash_table_replace(components, g_strdup(pce->identifier),
- PurpleChat *newchat = purple_chat_new(newaccount, NULL, components);
- purple_blist_add_chat(newchat, NULL, data); /* Copy it to correct location */
- data = (PurpleBlistNode *) newchat;
- else /* Just updating values in old chat */
- for (tmp = g_list_first(list); tmp; tmp = g_list_next(tmp))
- struct proto_chat_entry *pce = tmp->data;
- newvalue = purple_request_fields_get_string(fields, pce->identifier);
- g_hash_table_replace(chat->components, g_strdup(pce->identifier),
- const char *alias = purple_request_fields_get_string(fields, "alias");
- purple_blist_alias_chat(chat, alias);
- case PURPLE_BLIST_OTHER_NODE:
- purple_signal_emit(purple_blist_get_handle(), PLUGIN "-submit-fields", fields, data);
- if(olddata->type == PURPLE_BLIST_BUDDY_NODE)
- purple_blist_remove_buddy((PurpleBuddy *) olddata);
- else if(olddata->type == PURPLE_BLIST_CHAT_NODE)
- purple_blist_remove_chat((PurpleChat *) olddata);
- purple_blist_schedule_save();
-static PurpleAccount *buddyedit_account_filter_func_data;
-buddyedit_account_filter_func(PurpleAccount * account)
- PurplePluginProtocolInfo *gppi1 =
- PURPLE_PLUGIN_PROTOCOL_INFO(purple_account_get_connection(account)->prpl);
- PurplePluginProtocolInfo *gppi2 =
- PURPLE_PLUGIN_PROTOCOL_INFO(purple_account_get_connection(buddyedit_account_filter_func_data)->
-/* Node is either a contact or a buddy */
-buddy_edit_cb(PurpleBlistNode * node, gpointer data)
- purple_debug(PURPLE_DEBUG_INFO, PLUGIN, "buddy_edit_cb(%p)\n", node);
- PurpleRequestFields *fields;
- PurpleRequestField *field;
- PurpleRequestFieldGroup *group;
- char *request_title = NULL;
- fields = purple_request_fields_new();
- case PURPLE_BLIST_BUDDY_NODE:
- PurpleBuddy *buddy = (PurpleBuddy *) node;
- group = purple_request_field_group_new("Buddy Details");
- purple_request_fields_add_group(fields, group);
- field = purple_request_field_account_new("account", "Account", buddy->account);
- purple_request_field_account_set_show_all(field, TRUE);
- purple_request_field_group_add_field(group, field);
- field = purple_request_field_string_new("name", "Name", buddy->name, FALSE);
- purple_request_field_group_add_field(group, field);
- field = purple_request_field_string_new("alias", "Alias", buddy->alias, FALSE);
- purple_request_field_group_add_field(group, field);
- request_title = "Edit Buddy";
- case PURPLE_BLIST_CONTACT_NODE:
- PurpleContact *contact = (PurpleContact *) node;
- group = purple_request_field_group_new("Contact Details");
- purple_request_fields_add_group(fields, group);
- field = purple_request_field_string_new("alias", "Alias", contact->alias, FALSE);
- purple_request_field_group_add_field(group, field);
- request_title = "Edit Contact";
- case PURPLE_BLIST_GROUP_NODE:
- PurpleGroup *grp = (PurpleGroup *) node;
- group = purple_request_field_group_new("Group Details");
- purple_request_fields_add_group(fields, group);
- field = purple_request_field_string_new("alias", "Name", grp->name, FALSE);
- purple_request_field_group_add_field(group, field);
- request_title = "Edit Group";
- case PURPLE_BLIST_CHAT_NODE:
- PurpleChat *chat = (PurpleChat *) node;
- GList *list = NULL, *tmp;
- group = purple_request_field_group_new("Chat Details");
- purple_request_fields_add_group(fields, group);
- field = purple_request_field_account_new("account", "Account", chat->account);
- purple_request_field_account_set_filter(field, buddyedit_account_filter_func);
- buddyedit_account_filter_func_data = chat->account;
- purple_request_field_group_add_field(group, field);
- gc = purple_account_get_connection(chat->account);
- if(PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info != NULL)
- list = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info(gc);
- for (tmp = g_list_first(list); tmp; tmp = g_list_next(tmp))
- struct proto_chat_entry *pce = tmp->data;
- purple_debug(PURPLE_DEBUG_INFO, PLUGIN,
- "identifier=%s, label=%s, is_int=%d, required=%d\n", pce->identifier,
- pce->label, pce->is_int, pce->required);
- continue; /* Not yet */
- value = g_hash_table_lookup(chat->components, pce->identifier);
- field = purple_request_field_string_new(pce->identifier, pce->label, value, FALSE);
- purple_request_field_set_required(field, pce->required);
- purple_request_field_group_add_field(group, field);
- field = purple_request_field_string_new("alias", "Alias", chat->alias, FALSE);
- purple_request_field_group_add_field(group, field);
- request_title = "Edit Chat";
- request_title = "Edit";
- purple_signal_emit(purple_blist_get_handle(), PLUGIN "-create-fields", fields, node);
- purple_request_fields(plugin_self, request_title, NULL, NULL, fields,
- "OK", G_CALLBACK(buddyedit_editcomplete_cb),
- NULL, NULL, NULL, /* XXX: These should be set. */
-buddy_menu_cb(PurpleBlistNode * node, GList ** menu, void *data)
- PurpleMenuAction *action;
- /* These are the types we handle */
- case PURPLE_BLIST_BUDDY_NODE:
- case PURPLE_BLIST_CONTACT_NODE:
- case PURPLE_BLIST_GROUP_NODE:
- case PURPLE_BLIST_CHAT_NODE:
- case PURPLE_BLIST_OTHER_NODE:
- action = purple_menu_action_new("Edit...", PURPLE_CALLBACK(buddy_edit_cb), NULL, NULL);
- *menu = g_list_append(*menu, action);
-plugin_load(PurplePlugin * plugin)
- void *blist_handle = purple_blist_get_handle();
- purple_signal_register(blist_handle, PLUGIN "-create-fields", /* Called when about to create dialog */
- purple_marshal_VOID__POINTER_POINTER, NULL, 2, /* (FieldList*,BlistNode*) */
- purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_TYPE_POINTER), /* FieldList */
- purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_BLIST));
- purple_signal_register(blist_handle, PLUGIN "-submit-fields", /* Called when dialog submitted */
- purple_marshal_VOID__POINTER_POINTER, NULL, 2, /* (FieldList*,BlistNode*) */
- purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_TYPE_POINTER), /* FieldList */
- purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_BLIST));
- purple_signal_connect(blist_handle, "blist-node-extended-menu", plugin,
- PURPLE_CALLBACK(buddy_menu_cb), NULL);
-static PurplePluginInfo info = {
- PURPLE_PLUGIN_STANDARD,
- PURPLE_PRIORITY_DEFAULT,
- G_STRINGIFY(PLUGIN_VERSION),
- "Enable editing of buddy properties",
- "A plugin that adds an edit to to buddies allowing you to change various details you can't normally change. "
- "It also provides a mechanism for subsequent plugins to add themselves to that dialog. ",
- "Martijn van Oosterhout <kleptog@svana.org>",
- "http://buddytools.sf.net",
-init_plugin(PurplePlugin * plugin)
-PURPLE_INIT_PLUGIN(buddyedit, init_plugin, info);
--- a/buddytime/buddytime.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,490 +0,0 @@
- * Buddy Time - Displays a buddy's local time
- * A libpurple plugin that allows you to configure a timezone on a per-contact
- * basis so it can display the localtime of your contact when a conversation
- * starts. Convenient if you deal with contacts from many parts of the
- * Copyright (C) 2006-2007, Richard Laager <rlaager@pidgin.im>
- * Copyright (C) 2006, Martijn van Oosterhout <kleptog@svana.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
-/* If you can't figure out what this line is for, DON'T TOUCH IT. */
-#include "../common/pp_internal.h"
-#define PLUGIN_STATIC_NAME CORE_PLUGIN_STATIC_NAME
-#define PLUGIN_ID CORE_PLUGIN_ID
-#define SETTING_NAME "timezone"
-#define CONTROL_NAME PLUGIN_ID "-" SETTING_NAME
-#include "conversation.h"
-#define TIMEZONE_FLAG ((void*)1)
-#define DISABLED_FLAG ((void*)2)
-BuddyTimeUiOps *ui_ops = NULL;
-static PurplePlugin *plugin_self;
-/* Resolve specifies what the return value should mean:
- * If TRUE, it's for display, we want to know the *effect* thus hiding the
- * "none" value and going to going level to find the default
- * If false, we only want what the user enter, thus the string "none" if
- * data is here so we can use this as a callback for IPC
-buddy_get_timezone(PurpleBlistNode * node, gboolean resolve, void *data)
- PurpleBlistNode *datanode = NULL;
- case PURPLE_BLIST_BUDDY_NODE:
- datanode = (PurpleBlistNode *) purple_buddy_get_contact((PurpleBuddy *) node);
- case PURPLE_BLIST_CONTACT_NODE:
- case PURPLE_BLIST_GROUP_NODE:
- timezone = purple_blist_node_get_string(datanode, SETTING_NAME);
- /* The effect of "none" is to stop recursion */
- if (timezone && strcmp(timezone, "none") == 0)
- if (datanode->type == PURPLE_BLIST_CONTACT_NODE)
- /* There is no purple_blist_contact_get_group(), though there probably should be */
- datanode = datanode->parent;
- timezone = purple_blist_node_get_string(datanode, SETTING_NAME);
- if (timezone && strcmp(timezone, "none") == 0)
-/* Calcuates the difference between two struct tm's. */
-timezone_calc_difference(struct tm *remote_tm, struct tm *tmp_tm)
- /* Note this only works because the times are
- * known to be within 24 hours of each other! */
- if (remote_tm->tm_mday != tmp_tm->tm_mday)
- hours_diff += (remote_tm->tm_hour - tmp_tm->tm_hour);
- minutes_diff = (remote_tm->tm_min - tmp_tm->tm_min);
- return (double)minutes_diff / 60.0 + hours_diff;
-/* data is here so we can use this as a callback for IPC */
-timezone_get_time(const char *timezone, struct tm *tm, double *diff, void *data)
- struct state *tzinfo = timezone_load(timezone);
- localsub(&now, 0, tm, tzinfo);
- /* Store the current TZ value. */
- old_tz = g_getenv("TZ");
- g_setenv("TZ", timezone, TRUE);
- tm_tmp = localtime(&now);
- *tm = *tm_tmp; /* Must copy, localtime uses local buffer */
- /* Reset the old TZ value. */
- g_setenv("TZ", old_tz, TRUE);
- /* Calculate user's localtime, and compare. If same, no output */
- tm_tmp = localtime(&now);
- if (tm_tmp->tm_hour == tm->tm_hour && tm_tmp->tm_min == tm->tm_min)
- *diff = timezone_calc_difference(tm, tm_tmp);
-timezone_createconv_cb(PurpleConversation * conv, void *data)
- if (purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_IM)
- name = purple_conversation_get_name(conv);
- buddy = purple_find_buddy(purple_conversation_get_account(conv), name);
- timezone = buddy_get_timezone((PurpleBlistNode *) buddy, TRUE, NULL);
- ret = timezone_get_time(timezone, &tm, &diff, NULL);
- const char *text = purple_time_format(&tm);
- str = g_strdup_printf(dngettext(GETTEXT_PACKAGE,
- "Remote Local Time: %s (%.4g hour behind)",
- "Remote Local Time: %s (%.4g hours behind)", diff),
- str = g_strdup_printf(dngettext(GETTEXT_PACKAGE,
- "Remote Local Time: %s (%.4g hour ahead)",
- "Remote Local Time: %s (%.4g hours ahead)", diff),
- purple_conversation_write(conv, PLUGIN_STATIC_NAME, str, PURPLE_MESSAGE_SYSTEM, time(NULL));
-buddytimezone_submitfields_cb(PurpleRequestFields * fields, PurpleBlistNode * data)
- PurpleRequestField *list;
- purple_debug(PURPLE_DEBUG_INFO, PLUGIN_STATIC_NAME, "buddytimezone_submitfields_cb(%p,%p)\n", fields, data);
- case PURPLE_BLIST_BUDDY_NODE:
- node = (PurpleBlistNode *) purple_buddy_get_contact((PurpleBuddy *) data);
- case PURPLE_BLIST_CONTACT_NODE:
- case PURPLE_BLIST_GROUP_NODE:
- /* code handles either case */
- case PURPLE_BLIST_CHAT_NODE:
- case PURPLE_BLIST_OTHER_NODE:
- list = purple_request_fields_get_field(fields, CONTROL_NAME);
- if (ui_ops != NULL && ui_ops->get_timezone_menu_selection != NULL)
- const char *seldata = ui_ops->get_timezone_menu_selection(list->ui_data);
- purple_blist_node_remove_setting(node, SETTING_NAME);
- purple_blist_node_set_string(node, SETTING_NAME, seldata);
- sellist = purple_request_field_list_get_selected(list);
- seldata = purple_request_field_list_get_data(list, sellist->data);
- /* Otherwise, it's fixed value and this means deletion */
- if (seldata == TIMEZONE_FLAG)
- purple_blist_node_set_string(node, SETTING_NAME, sellist->data);
- else if (seldata == DISABLED_FLAG)
- purple_blist_node_set_string(node, SETTING_NAME, "none");
- purple_blist_node_remove_setting(node, SETTING_NAME);
-buddy_add_timezone_cb(char *filename, void *data)
- PurpleRequestField *field = (PurpleRequestField *) data;
- if (isupper(filename[0]))
- purple_request_field_list_add(field, filename, TIMEZONE_FLAG);
-buddytimezone_createfields_cb(PurpleRequestFields * fields, PurpleBlistNode * data)
- purple_debug(PURPLE_DEBUG_INFO, PLUGIN_STATIC_NAME, "buddytimezone_createfields_cb(%p,%p)\n", fields, data);
- PurpleRequestField *field;
- PurpleRequestFieldGroup *group;
- case PURPLE_BLIST_BUDDY_NODE:
- case PURPLE_BLIST_CONTACT_NODE:
- case PURPLE_BLIST_GROUP_NODE:
- case PURPLE_BLIST_CHAT_NODE:
- case PURPLE_BLIST_OTHER_NODE:
- group = purple_request_field_group_new(NULL);
- purple_request_fields_add_group(fields, group);
- timezone = buddy_get_timezone(data, FALSE, NULL);
- if (ui_ops != NULL && ui_ops->create_menu)
- purple_request_field_new(CONTROL_NAME,
- is_default ? "Default timezone for group" : "Timezone of contact",
- PURPLE_REQUEST_FIELD_LIST);
- field->ui_data = ui_ops->create_menu(timezone);
- purple_request_field_list_new(CONTROL_NAME,
- is_default ? "Default timezone for group" :
- "Timezone of contact (type to select)");
- purple_request_field_list_set_multi_select(field, FALSE);
- purple_request_field_list_add(field, "<Default>", "");
- purple_request_field_list_add(field, "<Disabled>", DISABLED_FLAG);
- recurse_directory("/usr/share/zoneinfo/", buddy_add_timezone_cb, field);
- if (strcmp(timezone, "none") == 0)
- purple_request_field_list_add_selected(field, "<Disabled>");
- purple_request_field_list_add_selected(field, timezone);
- purple_request_field_list_add_selected(field, "<Default>");
- purple_request_field_group_add_field(group, field);
-marshal_POINTER__POINTER_BOOL(PurpleCallback cb, va_list args, void *data,
- void *arg1 = va_arg(args, void *);
- gboolean arg2 = va_arg(args, gboolean);
- ret_val = ((gpointer (*)(void *, gboolean, void *))cb)(arg1, arg2, data);
- if (return_val != NULL)
-marshal_POINTER__POINTER_POINTER_POINTER(PurpleCallback cb, va_list args, void *data,
- void *arg1 = va_arg(args, void *);
- void *arg2 = va_arg(args, void *);
- void *arg3 = va_arg(args, void *);
- ret_val = ((gpointer (*)(void *, void *, void *, void *))cb)(arg1, arg2, arg3, data);
- if (return_val != NULL)
-load_ui_plugin(gpointer data)
- PurplePlugin *ui_plugin;
- ui_plugin_id = g_strconcat(purple_core_get_ui(), "-", PLUGIN_STATIC_NAME, NULL);
- ui_plugin = purple_plugins_find_with_id(ui_plugin_id);
- if (!purple_plugin_load(ui_plugin))
- purple_notify_error(ui_plugin, NULL, _("Failed to load the Buddy Timezone UI."),
- ui_plugin->error ? ui_plugin->error : "");
-plugin_load(PurplePlugin * plugin)
- purple_signal_connect(purple_conversations_get_handle(), "conversation-created", plugin,
- PURPLE_CALLBACK(timezone_createconv_cb), NULL);
- purple_plugin_ipc_register(plugin, BUDDYTIME_BUDDY_GET_TIMEZONE,
- PURPLE_CALLBACK(buddy_get_timezone),
- marshal_POINTER__POINTER_BOOL,
- purple_value_new(PURPLE_TYPE_STRING),
- purple_value_new(PURPLE_TYPE_SUBTYPE,
- PURPLE_SUBTYPE_BLIST_NODE),
- purple_value_new(PURPLE_TYPE_BOOLEAN));
- purple_plugin_ipc_register(plugin, BUDDYTIME_TIMEZONE_GET_TIME,
- PURPLE_CALLBACK(timezone_get_time),
- marshal_POINTER__POINTER_POINTER_POINTER,
- purple_value_new(PURPLE_TYPE_INT),
- purple_value_new(PURPLE_TYPE_POINTER),
- purple_value_new(PURPLE_TYPE_POINTER));
- /* This is done as an idle callback to avoid an infinite loop
- * when we try to load the UI plugin which depends on this plugin
- * which isn't officially loaded yet. */
- purple_timeout_add(0, load_ui_plugin, NULL);
-static PurplePluginInfo info =
- PURPLE_PLUGIN_STANDARD, /**< type */
- NULL, /**< ui_requirement */
- NULL, /**< dependencies */
- PURPLE_PRIORITY_DEFAULT, /**< priority */
- PP_VERSION, /**< version */
- NULL, /**< description */
- PLUGIN_AUTHOR, /**< author */
- PP_WEBSITE, /**< homepage */
- plugin_load, /**< load */
- NULL, /**< extra_info */
- NULL, /**< prefs_info */
- NULL, /**< reserved 1 */
- NULL, /**< reserved 2 */
- NULL, /**< reserved 3 */
- NULL /**< reserved 4 */
-init_plugin(PurplePlugin * plugin)
- bindtextdomain(GETTEXT_PACKAGE, PP_LOCALEDIR);
- bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
- info.name = _("Buddy Time");
- info.summary = _("Quickly see the local time of a buddy");
- info.description = _("Quickly see the local time of a buddy");
-PURPLE_INIT_PLUGIN(PLUGIN_STATIC_NAME, init_plugin, info);
--- a/buddytime/buddytime.c.old Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,260 +0,0 @@
- * Plugin Name - Summary
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA
-#include "../common/pp_internal.h"
-#define PLUGIN_ID "gtk-plugin_pack-buddytime"
-#define PLUGIN_STATIC_NAME "buddytime"
-#define PLUGIN_AUTHOR "Gary Kramlich <grim@reaperworld.com>"
-/******************************************************************************
- *****************************************************************************/
-#define BT_NODE_SETTING "bt-timezone"
-/******************************************************************************
- *****************************************************************************/
- PurpleRequestField *timezone;
- PurpleConversation *conv;
-/******************************************************************************
- *****************************************************************************/
-static GList *dialogs = NULL;
-static GList *widgets = NULL;
-/******************************************************************************
- *****************************************************************************/
-bt_widget_new(PurpleConversation *conv) {
- g_return_val_if_fail(conv, NULL);
- ret = g_new0(BTWidget, 1);
- ret->ebox = gtk_event_box_new();
- ret->label = gtk_label_new("label");
- gtk_container_add(GTK_CONTAINER(ret->ebox), ret->label);
-/******************************************************************************
- *****************************************************************************/
-bt_dialog_ok_cb(gpointer data, PurpleRequestFields *fields) {
- BTDialog *dialog = (BTDialog *)data;
- dialogs = g_list_remove(dialogs, dialog);
-bt_dialog_cancel_cb(gpointer data, PurpleRequestFields *fields) {
- BTDialog *dialog = (BTDialog *)data;
- dialogs = g_list_remove(dialogs, dialog);
-bt_show_dialog(PurpleBlistNode *node) {
- PurpleRequestFields *fields;
- PurpleRequestFieldGroup *group;
- PurpleAccount *account = NULL;
- dialog = g_new0(BTDialog, 1);
- current = purple_blist_node_get_int(node, BT_NODE_SETTING);
- /* TODO: set account from node */
- /* build the request fields */
- fields = purple_request_fields_new();
- group = purple_request_field_group_new(NULL);
- purple_request_fields_add_group(fields, group);
- dialog->timezone = purple_request_field_choice_new("timezone",
- purple_request_field_group_add_field(group, dialog->timezone);
- purple_request_field_choice_add(dialog->timezone, _("Clear setting"));
- purple_request_field_choice_add(dialog->timezone, _("GMT-12"));
- purple_request_field_choice_add(dialog->timezone, _("GMT-11"));
- purple_request_field_choice_add(dialog->timezone, _("GMT-10"));
- purple_request_field_choice_add(dialog->timezone, _("GMT-9"));
- purple_request_field_choice_add(dialog->timezone, _("GMT-8"));
- purple_request_field_choice_add(dialog->timezone, _("GMT-7"));
- purple_request_field_choice_add(dialog->timezone, _("GMT-6"));
- purple_request_field_choice_add(dialog->timezone, _("GMT-5"));
- purple_request_field_choice_add(dialog->timezone, _("GMT-4"));
- purple_request_field_choice_add(dialog->timezone, _("GMT-3"));
- purple_request_field_choice_add(dialog->timezone, _("GMT-2"));
- purple_request_field_choice_add(dialog->timezone, _("GMT-1"));
- purple_request_field_choice_add(dialog->timezone, _("GMT"));
- purple_request_field_choice_add(dialog->timezone, _("GMT+1"));
- purple_request_field_choice_add(dialog->timezone, _("GMT+2"));
- purple_request_field_choice_add(dialog->timezone, _("GMT+3"));
- purple_request_field_choice_add(dialog->timezone, _("GMT+4"));
- purple_request_field_choice_add(dialog->timezone, _("GMT+5"));
- purple_request_field_choice_add(dialog->timezone, _("GMT+6"));
- purple_request_field_choice_add(dialog->timezone, _("GMT+7"));
- purple_request_field_choice_add(dialog->timezone, _("GMT+8"));
- purple_request_field_choice_add(dialog->timezone, _("GMT+9"));
- purple_request_field_choice_add(dialog->timezone, _("GMT+10"));
- purple_request_field_choice_add(dialog->timezone, _("GMT+11"));
- purple_request_field_choice_add(dialog->timezone, _("GMT+12"));
-// purple_request_field_choice_set_default_value(dialog->timezone, current);
-// purple_request_field_coice_set_value(dialog->timezone, current);
- /* TODO: set who from blist node */
- purple_request_fields(NULL, _("Select timezone"),
- _("OK"), PURPLE_CALLBACK(bt_dialog_ok_cb),
- _("Cancel"), PURPLE_CALLBACK(bt_dialog_cancel_cb),
- account, NULL /* who */, NULL, dialog);
- dialogs = g_list_append(dialogs, dialog);
-bt_edit_timezone_cb(PurpleBlistNode *node, gpointer data) {
-bt_blist_drawing_menu_cb(PurpleBlistNode *node, GList **menu) {
- PurpleMenuAction *action;
- if (purple_blist_node_get_flags(node) & PURPLE_BLIST_NODE_FLAG_NO_SAVE)
- /* ignore chats and groups */
- if(PURPLE_BLIST_NODE_IS_CHAT(node) || PURPLE_BLIST_NODE_IS_GROUP(node))
- action = purple_menu_action_new(_("Timezone"),
- PURPLE_CALLBACK(bt_edit_timezone_cb),
- (*menu) = g_list_append(*menu, action);
-/******************************************************************************
- *****************************************************************************/
-/******************************************************************************
- *****************************************************************************/
-plugin_load(PurplePlugin *plugin) {
- purple_signal_connect(purple_blist_get_handle(),
- "blist-node-extended-menu",
- PURPLE_CALLBACK(bt_blist_drawing_menu_cb),
-plugin_unload(PurplePlugin *plugin) {
-static PurplePluginInfo info = {
- PURPLE_PLUGIN_MAGIC, /* Magic */
- PURPLE_MAJOR_VERSION, /* Purple Major Version */
- PURPLE_MINOR_VERSION, /* Purple Minor Version */
- PURPLE_PLUGIN_STANDARD, /* plugin type */
- PIDGIN_PLUGIN_TYPE, /* ui requirement */
- NULL, /* dependencies */
- PURPLE_PRIORITY_DEFAULT, /* priority */
- PLUGIN_ID, /* plugin id */
- PP_VERSION, /* version */
- NULL, /* description */
- PLUGIN_AUTHOR, /* author */
- PP_WEBSITE, /* website */
- plugin_load, /* load */
- plugin_unload, /* unload */
-init_plugin(PurplePlugin *plugin) {
- bindtextdomain(GETTEXT_PACKAGE, PP_LOCALEDIR);
- bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
- info.name = _("Buddy Time");
- info.summary = _("summary");
- info.description = _("description");
-PURPLE_INIT_PLUGIN(PLUGIN_STATIC_NAME, init_plugin, info)
--- a/buddytime/buddytime.h Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
- * Buddy Time - Displays a buddy's local time
- * A libpurple plugin that allows you to configure a timezone on a per-contact
- * basis so it can display the localtime of your contact when a conversation
- * starts. Convenient if you deal with contacts from many parts of the
- * Copyright (C) 2006-2007, Richard Laager <rlaager@users.sf.net>
- * Copyright (C) 2006, Martijn van Oosterhout <kleptog@svana.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
-#define CORE_PLUGIN_STATIC_NAME "buddytime"
-#define CORE_PLUGIN_ID "core-kleptog-" CORE_PLUGIN_STATIC_NAME
-#define PLUGIN_AUTHOR "Martijn van Oosterhout <kleptog@svana.org>" \
- "\n\t\t\tRichard Laager <rlaager@pidgin.im>"
-#define BUDDYTIME_BUDDY_GET_TIMEZONE "buddy_get_timezone"
-#define BUDDYTIME_TIMEZONE_GET_TIME "timezone_get_time"
-typedef struct _BuddyTimeUiOps BuddyTimeUiOps;
- void *(*create_menu)(const char *selected); /**< Creates a timezone menu. */
- const char * (*get_timezone_menu_selection)(void *ui_data); /**< Retrieves the menu setting. */
- void (*_buddytime_reserved1)(void);
- void (*_buddytime_reserved2)(void);
- void (*_buddytime_reserved3)(void);
- void (*_buddytime_reserved4)(void);
-#endif /* _BUDDYTIME_H_ */
--- a/buddytime/gtkbuddytime.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
- * Buddy Time - Displays a buddy's local time
- * A libpurple plugin that allows you to configure a timezone on a per-contact
- * basis so it can display the localtime of your contact when a conversation
- * starts. Convenient if you deal with contacts from many parts of the
- * Copyright (C) 2006-2007, Richard Laager <rlaager@pidgin.im>
- * Copyright (C) 2006, Martijn van Oosterhout <kleptog@svana.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
-/* If you can't figure out what this line is for, DON'T TOUCH IT. */
-#include "../common/pp_internal.h"
-#define PLUGIN_STATIC_NAME "gtkbuddytime"
-#define PLUGIN_ID PIDGIN_UI "-buddytime"
-PurplePlugin *core_plugin = NULL;
-buddytimezone_tooltip_cb(PurpleBlistNode * node, char **text, gboolean full, void *data)
- timezone = purple_plugin_ipc_call(core_plugin, BUDDYTIME_BUDDY_GET_TIMEZONE,
- ret = GPOINTER_TO_INT(purple_plugin_ipc_call(core_plugin, BUDDYTIME_TIMEZONE_GET_TIME,
- NULL, timezone, &tm, &diff));
- newtext = g_strdup_printf("%s\n<b>Timezone:</b> %s (error)", *text, timezone);
- const char *timetext = purple_time_format(&tm);
- newtext = g_strdup_printf(dngettext(GETTEXT_PACKAGE,
- "%s\n<b>Local Time:</b> %s (%.4g hour behind)",
- "%s\n<b>Local Time:</b> %s (%.4g hours behind)", diff),
- *text, timetext, diff);
- newtext = g_strdup_printf(dngettext(GETTEXT_PACKAGE,
- "%s\n<b>Local Time:</b> %s (%.4g hour ahead)",
- "%s\n<b>Local Time:</b> %s (%.4g hours ahead)", diff),
- *text, timetext, diff); }
-plugin_load(PurplePlugin * plugin)
- purple_signal_connect(pidgin_blist_get_handle(), "drawing-tooltip", plugin,
- PURPLE_CALLBACK(buddytimezone_tooltip_cb), NULL);
- core_plugin = purple_plugins_find_with_id(CORE_PLUGIN_ID);
- return (core_plugin != NULL);
-static PurplePluginInfo info =
- PURPLE_PLUGIN_STANDARD, /**< type */
- PIDGIN_PLUGIN_TYPE, /**< ui_requirement */
- PURPLE_PLUGIN_FLAG_INVISIBLE, /**< flags */
- NULL, /**< dependencies */
- PURPLE_PRIORITY_DEFAULT, /**< priority */
- PP_VERSION, /**< version */
- NULL, /**< description */
- PLUGIN_AUTHOR, /**< author */
- PP_WEBSITE, /**< homepage */
- plugin_load, /**< load */
- NULL, /**< extra_info */
- NULL, /**< prefs_info */
- NULL, /**< reserved 1 */
- NULL, /**< reserved 2 */
- NULL, /**< reserved 3 */
- NULL /**< reserved 4 */
-init_plugin(PurplePlugin * plugin)
- info.dependencies = g_list_append(info.dependencies, CORE_PLUGIN_ID);
- bindtextdomain(GETTEXT_PACKAGE, PP_LOCALEDIR);
- bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
- info.name = _("Buddy Time (Pidgin UI)");
- info.summary = _("Pidgin user interface for the Buddy Time plugin.");
- info.description = _("Pidgin user interface for the Buddy Time plugin.");
-PURPLE_INIT_PLUGIN(PLUGIN_STATIC_NAME, init_plugin, info);
--- a/buddytime/gtktimezone.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,229 +0,0 @@
-/*************************************************************************
- * 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.
- *************************************************************************/
-#define DISABLED_STRING "<Disabled>"
-#define DEFAULT_STRING "<Default>"
-#define MORE_STRING "More..."
- 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))));
-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));
-menu_select_cb(GtkMenuItem * menuitem, GtkWidget * menu)
- const char *label = menuitem_get_label(menuitem);
- GtkWidget *selection = GTK_WIDGET(menu_get_first_menuitem(menu));
- gtk_widget_hide(selection);
- char *str = g_strdup(label);
- GtkMenuItem *parentitem;
- parent = gtk_widget_get_parent(GTK_WIDGET(menuitem));
- 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);
- 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,
-make_menu_cb(char *path, struct state *state)
- /* Here we ignore strings not beginning with uppercase, since they are auxilliary files, not timezones */
- 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)
- /* 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);
- GtkWidget *parent = (i == 0) ? state->base : state->stack[i - 1].submenu;
- if(i == 0 && elements[1] == NULL)
- 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->stack[i].string = g_strdup(elements[i]);
- g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(menu_select_cb),
-make_timezone_menu(const char *selected)
- GtkWidget *optionmenu, *menuitem, *selection;
- menuitem = gtk_menu_item_new_with_label(selected);
- gtk_menu_append(menu, 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.extra = gtk_menu_new();
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), state.extra);
- 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);
- gtk_option_menu_set_history(GTK_OPTION_MENU(optionmenu), 0);
-get_timezone_menu_selection(void *widget)
- GtkOptionMenu *menu = GTK_OPTION_MENU(widget);
- int sel = gtk_option_menu_get_history(menu);
- if(sel == 2) /* Default */
- if(sel == 1) /* Disabled */
- GtkLabel *l = GTK_LABEL(gtk_bin_get_child(GTK_BIN(menu)));
- return gtk_label_get_text(l);
--- a/buddytime/gtktimezonetest.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,335 +0,0 @@
-/*************************************************************************
- * GTK Timezone test program
- * by Martijn van Oosterhout <kleptog@svana.org> (C) April 2006
- * Licenced under the GNU General Public Licence version 2.
- * A test program to play with different ways that user could select from
- * the huge list of timezones. Eventually things tested here should migrate
- * to the module itself.
- *************************************************************************/
-#define PACKAGE "Hello World"
-#define DISABLED_STRING "<Disabled>"
-#define DEFAULT_STRING "<Default>"
-#define MORE_STRING "More..."
- * Terminate the main loop.
-on_destroy(GtkWidget * widget, gpointer data)
- 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))));
-menu_get_first_menuitem(GtkMenu * menu)
- GList *list = gtk_container_get_children(GTK_CONTAINER(menu));
- GtkWidget *selection = GTK_WIDGET(g_list_nth_data(list, 0));
-menu_select_cb(GtkMenuItem * menuitem, GtkWidget * menu)
- const char *label = menuitem_get_label(menuitem);
-// printf( "menuitem = %s(%p), menu = %s(%p)\n", G_OBJECT_TYPE_NAME(menuitem), menuitem, G_OBJECT_TYPE_NAME(menu), menu );
- GtkWidget *selection = menu_get_first_menuitem(GTK_MENU(menu));
- gtk_widget_hide(selection);
- char *str = g_strdup(label);
- GtkMenuItem *parentitem;
- parent = gtk_widget_get_parent(GTK_WIDGET(menuitem));
-// printf( "parent = %s(%p)\n", G_OBJECT_TYPE_NAME(parent), parent);
- parentitem = GTK_MENU_ITEM(gtk_menu_get_attach_widget(GTK_MENU(parent)));
-// printf( "parentitem = %s(%p)\n", G_OBJECT_TYPE_NAME(parentitem), parentitem);
- label2 = menuitem_get_label(parentitem);
- if(strcmp(label2, MORE_STRING) != 0)
- temp = g_strconcat(label2, "/", str, NULL);
- GtkWidget *selection = menu_get_first_menuitem(GTK_MENU(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);
-make_menu_cb(char *path, struct state *state)
- /* Here we ignore strings not beginning with uppercase, since they are auxilliary files, not timezones */
- 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)
- /* 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);
- GtkTreeIter *parent = (i == 0) ? NULL : &state->stack[i - 1].iter;
- GtkWidget *parent = (i == 0) ? state->base : state->stack[i - 1].submenu;
- if(i == 0 && elements[1] == NULL)
- gtk_tree_store_append(state->store, &state->stack[i].iter, parent);
- gtk_tree_store_set(state->store, &state->stack[i].iter, STRING_COLUMN, elements[i], -1);
- state->stack[i].string = g_strdup(elements[i]);
- 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->stack[i].string = g_strdup(elements[i]);
- g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(menu_select_cb),
-make_menu2(char *selected)
- GtkTreeStore *store = gtk_tree_store_new(N_COLUMNS, /* Total number of columns */
- G_TYPE_STRING); /* Timezone */
- GtkCellRenderer *renderer;
- GtkTreeIter iter1, iter2;
- gtk_tree_store_append(store, &iter1, NULL); /* Acquire an iterator */
- gtk_tree_store_set(store, &iter1, STRING_COLUMN, DISABLED_STRING, -1);
- gtk_tree_store_append(store, &iter1, NULL); /* Acquire an iterator */
- gtk_tree_store_set(store, &iter1, STRING_COLUMN, DEFAULT_STRING, -1);
- gtk_tree_store_append(store, &iter2, &iter1);
- gtk_tree_store_set(store, &iter1, STRING_COLUMN, MORE_STRING, -1);
- GtkWidget *optionmenu, *menuitem, *selection;
- menuitem = gtk_menu_item_new_with_label(selected);
- gtk_menu_append(menu, 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.extra = gtk_menu_new();
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), state.extra);
- recurse_directory("/usr/share/zoneinfo", (DirRecurseMatch) make_menu_cb, &state);
- for (i = 0; i < state.currdepth; i++)
- g_free(state.stack[i].string);
- tree = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store));
- renderer = gtk_cell_renderer_text_new();
- gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(tree), renderer, TRUE);
- gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(tree), renderer, "text", 0, NULL);
- gtk_widget_show_all(tree);
- 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);
- gtk_option_menu_set_history(GTK_OPTION_MENU(optionmenu), 0);
-main(int argc, char *argv[])
- gtk_init(&argc, &argv);
- /* create the main, top level, window */
- window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- /* give the window a 20px wide border */
- gtk_container_set_border_width(GTK_CONTAINER(window), 20);
- /* give it the title */
- gtk_window_set_title(GTK_WINDOW(window), PACKAGE " " VERSION);
- /* open it a bit wider so that both the label and title show up */
- gtk_window_set_default_size(GTK_WINDOW(window), 200, 50);
- /* Connect the destroy event of the window with our on_destroy function
- * When the window is about to be destroyed we get a notificaiton and
- * stop the main GTK loop
- g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(on_destroy), NULL);
- /* Create the "Hello, World" label */
- label = gtk_label_new("Select a timezone:");
- gtk_widget_show(label);
- frame = gtk_vbox_new(FALSE, 0);
- gtk_widget_show(frame);
- /* and insert it into the main window */
- gtk_container_add(GTK_CONTAINER(window), frame);
- gtk_container_add(GTK_CONTAINER(frame), label);
- menu = make_menu2("none");
- gtk_container_add(GTK_CONTAINER(frame), menu);
- /* make sure that everything, window and label, are visible */
- gtk_widget_show(window);
- /* start the main loop */
--- a/buddytime/localtime.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1250 +0,0 @@
-/*************************************************************************
- * copied from the Olson Timezone code, licence unchanged.
- * by Martijn van Oosterhout <kleptog@svana.org> April 2006
- * Original Licence below (public domain).
- * This code has been copied from the Olson Timezone code, but heavily
- * adapted to meet my needs. In particular, you can load multiple timezones
- * and specify which timezone to convert with.
- *************************************************************************/
-** This file is in the public domain, so clarified as of
-** 1996-06-05 by Arthur David Olson.
-#define TM_GMTOFF tm_gmtoff
-** Leap second handling from Bradley White.
-** POSIX-style TZ environment variable handling from Guy Harris.
-#include "float.h" /* for FLT_MAX and DBL_MAX */
-#define TZ_ABBR_MAX_LEN 16
-#endif /* !defined TZ_ABBR_MAX_LEN */
-#ifndef TZ_ABBR_CHAR_SET
-#define TZ_ABBR_CHAR_SET \
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
-#endif /* !defined TZ_ABBR_CHAR_SET */
-#ifndef TZ_ABBR_ERR_CHAR
-#define TZ_ABBR_ERR_CHAR '_'
-#endif /* !defined TZ_ABBR_ERR_CHAR */
-** SunOS 4.1.1 headers lack O_BINARY.
-#define OPEN_MODE (O_RDONLY | O_BINARY)
-#endif /* defined O_BINARY */
-#define OPEN_MODE O_RDONLY
-#endif /* !defined O_BINARY */
-** Someone might make incorrect use of a time zone abbreviation:
-** 1. They might reference tzname[0] before calling tzset (explicitly
-** 2. They might reference tzname[1] before calling tzset (explicitly
-** 3. They might reference tzname[1] after setting to a time zone
-** in which Daylight Saving Time is never observed.
-** 4. They might reference tzname[0] after setting to a time zone
-** in which Standard Time is never observed.
-** 5. They might reference tm.TM_ZONE after calling offtime.
-** What's best to do in the above cases is open to debate;
-** for now, we just set things up so that in any of the five cases
-** WILDABBR is used. Another possibility: initialize tzname[0] to the
-** string "tzname[0] used before set", and similarly for the other cases.
-** And another: initialize tzname[0] to "ERA", with an explanation in the
-** manual page of what this "time zone abbreviation" means (doing this so
-** that tzname[0] has the "normal" length of three characters).
-#endif /* !defined WILDABBR */
-static char wildabbr[] = WILDABBR;
-static const char gmt[] = "GMT";
-** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
-** We default to US rules as of 1999-08-17.
-** POSIX 1003.1 section 8.1.1 says that the default DST rules are
-** implementation dependent; for historical reasons, US rules are a
-#define TZDEFRULESTRING ",M4.1.0,M10.5.0"
-#endif /* !defined TZDEFDST */
-struct ttinfo { /* time type information */
- long tt_gmtoff; /* UTC offset in seconds */
- int tt_isdst; /* used to set tm_isdst */
- int tt_abbrind; /* abbreviation list index */
- int tt_ttisstd; /* TRUE if transition is std time */
- int tt_ttisgmt; /* TRUE if transition is UTC */
-struct lsinfo { /* leap second information */
- time_t ls_trans; /* transition time */
- long ls_corr; /* correction to apply */
-#define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
-#define MY_TZNAME_MAX TZNAME_MAX
-#endif /* defined TZNAME_MAX */
-#define MY_TZNAME_MAX 255
-#endif /* !defined TZNAME_MAX */
- time_t ats[TZ_MAX_TIMES];
- unsigned char types[TZ_MAX_TIMES];
- struct ttinfo ttis[TZ_MAX_TYPES];
- char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
- (2 * (MY_TZNAME_MAX + 1)))];
- struct lsinfo lsis[TZ_MAX_LEAPS];
- int r_type; /* type of rule--see below */
- int r_day; /* day number of rule */
- int r_week; /* week number of rule */
- int r_mon; /* month number of rule */
- long r_time; /* transition time of rule */
-#define JULIAN_DAY 0 /* Jn - Julian day */
-#define DAY_OF_YEAR 1 /* n - day of year */
-#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
-** Prototypes for static functions.
-static long detzcode P((const char * codep));
-static const char * getzname P((const char * strp));
-static const char * getqzname P((const char * strp, const char delim));
-static const char * getnum P((const char * strp, int * nump, int min,
-static const char * getsecs P((const char * strp, long * secsp));
-static const char * getoffset P((const char * strp, long * offsetp));
-static const char * getrule P((const char * strp, struct rule * rulep));
-static void gmtload P((struct state * sp));
-struct tm * gmtsub P((const time_t * timep, long offset,
-struct tm * localsub P((const time_t * timep, long offset,
- struct tm * tmp, struct state *sp));
-static int increment_overflow P((int * number, int delta));
-static int leaps_thru_end_of P((int y));
-static struct tm * timesub P((const time_t * timep, long offset,
- const struct state * sp, struct tm * tmp));
-static time_t transtime P((time_t janfirst, int year,
- const struct rule * rulep, long offset));
-static int tzload P((const char * name, struct state * sp));
-static int tzparse P((const char * name, struct state * sp,
-struct state *timezone_load P((const char * name));
-static struct state * gmtptr;
-#endif /* defined ALL_STATE */
-static struct state gmtmem;
-#define gmtptr (&gmtmem)
-#define TZ_STRLEN_MAX 255
-#endif /* !defined TZ_STRLEN_MAX */
-//static char lcl_TZname[TZ_STRLEN_MAX + 1];
-//static int lcl_is_set;
-** Section 4.12.3 of X3.159-1989 requires that
-** Except for the strftime function, these functions [asctime,
-** ctime, gmtime, localtime] return values in one of two static
-** objects: a broken-down time structure and an array of char.
-** Thanks to Paul Eggert for noting this.
-#endif /* defined USG_COMPAT */
-#endif /* defined ALTZONE */
-const char * const codep;
- result = (codep[0] & 0x80) ? ~0L : 0L;
- for (i = 0; i < 4; ++i)
- result = (result << 8) | (codep[i] & 0xff);
-register const char * name;
-register struct state * const sp;
- register const char * p;
- if (name == NULL && (name = TZDEFAULT) == NULL)
- ** Section 4.9.1 of the C standard says that
- ** "FILENAME_MAX expands to an integral constant expression
- ** that is the size needed for an array of char large enough
- ** to hold the longest file name string that the implementation
- ** guarantees can be opened."
- char fullname[FILENAME_MAX + 1];
- doaccess = name[0] == '/';
- if ((p = tzdir) == NULL)
- if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
- (void) strcpy(fullname, p);
- (void) strcat(fullname, "/");
- (void) strcat(fullname, name);
- ** Set doaccess if '.' (as in "../") shows up in name.
- if (strchr(name, '.') != NULL)
- if (doaccess && access(name, R_OK) != 0)
- if ((fid = open(name, OPEN_MODE)) == -1)
- char buf[sizeof *sp + sizeof *tzhp];
- i = read(fid, u.buf, sizeof u.buf);
- ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
- ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
- sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
- sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
- sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
- sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
- p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
- if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
- sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
- sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
- sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
- (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
- (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
- if (i - (p - u.buf) < sp->timecnt * 4 + /* ats */
- sp->timecnt + /* types */
- sp->typecnt * (4 + 2) + /* ttinfos */
- sp->charcnt + /* chars */
- sp->leapcnt * (4 + 4) + /* lsinfos */
- ttisstdcnt + /* ttisstds */
- ttisgmtcnt) /* ttisgmts */
- for (i = 0; i < sp->timecnt; ++i) {
- sp->ats[i] = detzcode(p);
- for (i = 0; i < sp->timecnt; ++i) {
- sp->types[i] = (unsigned char) *p++;
- if (sp->types[i] >= sp->typecnt)
- for (i = 0; i < sp->typecnt; ++i) {
- register struct ttinfo * ttisp;
- ttisp->tt_gmtoff = detzcode(p);
- ttisp->tt_isdst = (unsigned char) *p++;
- if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
- ttisp->tt_abbrind = (unsigned char) *p++;
- if (ttisp->tt_abbrind < 0 ||
- ttisp->tt_abbrind > sp->charcnt)
- for (i = 0; i < sp->charcnt; ++i)
- sp->chars[i] = '\0'; /* ensure '\0' at end */
- for (i = 0; i < sp->leapcnt; ++i) {
- register struct lsinfo * lsisp;
- lsisp->ls_trans = detzcode(p);
- lsisp->ls_corr = detzcode(p);
- for (i = 0; i < sp->typecnt; ++i) {
- register struct ttinfo * ttisp;
- ttisp->tt_ttisstd = FALSE;
- ttisp->tt_ttisstd = *p++;
- if (ttisp->tt_ttisstd != TRUE &&
- ttisp->tt_ttisstd != FALSE)
- for (i = 0; i < sp->typecnt; ++i) {
- register struct ttinfo * ttisp;
- ttisp->tt_ttisgmt = FALSE;
- ttisp->tt_ttisgmt = *p++;
- if (ttisp->tt_ttisgmt != TRUE &&
- ttisp->tt_ttisgmt != FALSE)
- ** Out-of-sort ats should mean we're running on a
- ** signed time_t system but using a data file with
- ** unsigned values (or vice versa).
- for (i = 0; i < sp->timecnt - 2; ++i)
- if (sp->ats[i] > sp->ats[i + 1]) {
- if (TYPE_SIGNED(time_t)) {
- ** Ignore the end (easy).
- ** Ignore the beginning (harder).
- for (j = 0; j + i < sp->timecnt; ++j) {
- sp->ats[j] = sp->ats[j + i];
- sp->types[j] = sp->types[j + i];
-struct state *timezone_load(name)
- struct state *sp = malloc( sizeof(struct state) );
- res = tzload( name, sp );
-static const int mon_lengths[2][MONSPERYEAR] = {
- { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
- { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
-static const int year_lengths[2] = {
- DAYSPERNYEAR, DAYSPERLYEAR
-** Given a pointer into a time zone string, scan until a character that is not
-** a valid character in a zone name is found. Return a pointer to that
-register const char * strp;
- while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
-** Given a pointer into an extended time zone string, scan until the ending
-** delimiter of the zone name is located. Return a pointer to the delimiter.
-** As with getzname above, the legal character set is actually quite
-** restricted, with other characters producing undefined results.
-** We choose not to care - allowing almost anything to be in the zone abbrev.
-getqzname(register const char *strp, const char delim)
-register const char * strp;
- while ((c = *strp) != '\0' && c != delim)
-** Given a pointer into a time zone string, extract a number from that string.
-** Check that the number is within a specified range; if it is not, return
-** Otherwise, return a pointer to the first character not part of the number.
-getnum(strp, nump, min, max)
-register const char * strp;
- if (strp == NULL || !is_digit(c = *strp))
- num = num * 10 + (c - '0');
- return NULL; /* illegal value */
- return NULL; /* illegal value */
-** Given a pointer into a time zone string, extract a number of seconds,
-** in hh[:mm[:ss]] form, from the string.
-** If any error occurs, return NULL.
-** Otherwise, return a pointer to the first character not part of the number
-register const char * strp;
- ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
- ** "M10.4.6/26", which does not conform to Posix,
- ** but which specifies the equivalent of
- ** ``02:00 on the first Sunday on or after 23 Oct''.
- strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
- *secsp = num * (long) SECSPERHOUR;
- strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
- *secsp += num * SECSPERMIN;
- /* `SECSPERMIN' allows for leap seconds. */
- strp = getnum(strp, &num, 0, SECSPERMIN);
-** Given a pointer into a time zone string, extract an offset, in
-** [+-]hh[:mm[:ss]] form, from the string.
-** If any error occurs, return NULL.
-** Otherwise, return a pointer to the first character not part of the time.
-getoffset(strp, offsetp)
-register const char * strp;
- } else if (*strp == '+')
- strp = getsecs(strp, offsetp);
- return NULL; /* illegal time */
-** Given a pointer into a time zone string, extract a rule in the form
-** date[/time]. See POSIX section 8 for the format of "date" and "time".
-** If a valid rule is not found, return NULL.
-** Otherwise, return a pointer to the first character not part of the rule.
-register struct rule * const rulep;
- rulep->r_type = JULIAN_DAY;
- strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
- } else if (*strp == 'M') {
- rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
- strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
- strp = getnum(strp, &rulep->r_week, 1, 5);
- strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
- } else if (is_digit(*strp)) {
- rulep->r_type = DAY_OF_YEAR;
- strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
- } else return NULL; /* invalid format */
- strp = getsecs(strp, &rulep->r_time);
- } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
-** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
-** year, a rule, and the offset from UTC at the time that rule takes effect,
-** calculate the Epoch-relative time that rule takes effect.
-transtime(janfirst, year, rulep, offset)
-register const struct rule * const rulep;
- int d, m1, yy0, yy1, yy2, dow;
- leapyear = isleap(year);
- switch (rulep->r_type) {
- ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
- ** In non-leap years, or if the day number is 59 or less, just
- ** add SECSPERDAY times the day number-1 to the time of
- ** January 1, midnight, to get the day.
- value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
- if (leapyear && rulep->r_day >= 60)
- ** Just add SECSPERDAY times the day number to the time of
- ** January 1, midnight, to get the day.
- value = janfirst + rulep->r_day * SECSPERDAY;
- case MONTH_NTH_DAY_OF_WEEK:
- ** Mm.n.d - nth "dth day" of month m.
- for (i = 0; i < rulep->r_mon - 1; ++i)
- value += mon_lengths[leapyear][i] * SECSPERDAY;
- ** Use Zeller's Congruence to get day-of-week of first day of
- m1 = (rulep->r_mon + 9) % 12 + 1;
- yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
- dow = ((26 * m1 - 2) / 10 +
- 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
- ** "dow" is the day-of-week of the first day of the month. Get
- ** the day-of-month (zero-origin) of the first "dow" day of the
- d = rulep->r_day - dow;
- for (i = 1; i < rulep->r_week; ++i) {
- mon_lengths[leapyear][rulep->r_mon - 1])
- ** "d" is the day-of-month (zero-origin) of the day we want.
- value += d * SECSPERDAY;
- ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
- ** question. To get the Epoch-relative time of the specified local
- ** time on that day, add the transition time and the current offset
- return value + rulep->r_time + offset;
-** Given a POSIX section 8-style TZ string, fill in the rule tables as
-tzparse(name, sp, lastditch)
-register struct state * const sp;
- register unsigned char * typep;
- register int load_result;
- stdlen = strlen(name); /* length of standard zone name */
- if (stdlen >= sizeof sp->chars)
- stdlen = (sizeof sp->chars) - 1;
- name = getqzname(name, '>');
- stdlen = name - stdname;
- stdlen = name - stdname;
- name = getoffset(name, &stdoffset);
- load_result = tzload(TZDEFRULES, sp);
- sp->leapcnt = 0; /* so, we're off a little */
- name = getqzname(name, '>');
- dstlen = name - dstname;
- dstlen = name - dstname; /* length of DST zone name */
- if (*name != '\0' && *name != ',' && *name != ';') {
- name = getoffset(name, &dstoffset);
- } else dstoffset = stdoffset - SECSPERHOUR;
- if (*name == '\0' && load_result != 0)
- name = TZDEFRULESTRING;
- if (*name == ',' || *name == ';') {
- register time_t janfirst;
- if ((name = getrule(name, &start)) == NULL)
- if ((name = getrule(name, &end)) == NULL)
- sp->typecnt = 2; /* standard time and DST */
- ** Two transitions per year, from EPOCH_YEAR to 2037.
- sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1);
- if (sp->timecnt > TZ_MAX_TIMES)
- sp->ttis[0].tt_gmtoff = -dstoffset;
- sp->ttis[0].tt_isdst = 1;
- sp->ttis[0].tt_abbrind = stdlen + 1;
- sp->ttis[1].tt_gmtoff = -stdoffset;
- sp->ttis[1].tt_isdst = 0;
- sp->ttis[1].tt_abbrind = 0;
- for (year = EPOCH_YEAR; year <= 2037; ++year) {
- starttime = transtime(janfirst, year, &start,
- endtime = transtime(janfirst, year, &end,
- if (starttime > endtime) {
- *typep++ = 1; /* DST ends */
- *typep++ = 0; /* DST begins */
- *typep++ = 0; /* DST begins */
- *typep++ = 1; /* DST ends */
- janfirst += year_lengths[isleap(year)] *
- register long theirstdoffset;
- register long theirdstoffset;
- register long theiroffset;
- ** Initial values of theirstdoffset and theirdstoffset.
- for (i = 0; i < sp->timecnt; ++i) {
- if (!sp->ttis[j].tt_isdst) {
- -sp->ttis[j].tt_gmtoff;
- for (i = 0; i < sp->timecnt; ++i) {
- if (sp->ttis[j].tt_isdst) {
- -sp->ttis[j].tt_gmtoff;
- ** Initially we're assumed to be in standard time.
- theiroffset = theirstdoffset;
- ** Now juggle transition times and types
- ** tracking offsets as you do.
- for (i = 0; i < sp->timecnt; ++i) {
- sp->types[i] = sp->ttis[j].tt_isdst;
- if (sp->ttis[j].tt_ttisgmt) {
- /* No adjustment to transition time */
- ** If summer time is in effect, and the
- ** transition time was not specified as
- ** standard time, add the summer time
- ** offset to the transition time;
- ** otherwise, add the standard time
- ** offset to the transition time.
- ** Transitions from DST to DDST
- ** will effectively disappear since
- ** POSIX provides for only one DST
- if (isdst && !sp->ttis[j].tt_ttisstd) {
- sp->ats[i] += dstoffset -
- sp->ats[i] += stdoffset -
- theiroffset = -sp->ttis[j].tt_gmtoff;
- if (sp->ttis[j].tt_isdst)
- theirdstoffset = theiroffset;
- else theirstdoffset = theiroffset;
- ** Finally, fill in ttis.
- ** ttisstd and ttisgmt need not be handled.
- sp->ttis[0].tt_gmtoff = -stdoffset;
- sp->ttis[0].tt_isdst = FALSE;
- sp->ttis[0].tt_abbrind = 0;
- sp->ttis[1].tt_gmtoff = -dstoffset;
- sp->ttis[1].tt_isdst = TRUE;
- sp->ttis[1].tt_abbrind = stdlen + 1;
- sp->typecnt = 1; /* only standard time */
- sp->ttis[0].tt_gmtoff = -stdoffset;
- sp->ttis[0].tt_isdst = 0;
- sp->ttis[0].tt_abbrind = 0;
- sp->charcnt = stdlen + 1;
- sp->charcnt += dstlen + 1;
- if ((size_t) sp->charcnt > sizeof sp->chars)
- (void) strncpy(cp, stdname, stdlen);
- (void) strncpy(cp, dstname, dstlen);
-struct state * const sp;
- if (tzload(gmt, sp) != 0)
- (void) tzparse(gmt, sp, TRUE);
-** The easy way to behave "as if no library function calls" localtime
-** is to not call it--so we drop its guts into "localsub", which can be
-** freely called. (And no, the PANS doesn't require the above behavior--
-** but it *is* desirable.)
-** The unused offset argument is for the benefit of mktime variants.
-localsub(timep, offset, tmp, sp)
-const time_t * const timep;
- register const struct ttinfo * ttisp;
- register struct tm * result;
- const time_t t = *timep;
- return gmtsub(timep, offset, tmp);
-#endif /* defined ALL_STATE */
- if (sp->timecnt == 0 || t < sp->ats[0]) {
- while (sp->ttis[i].tt_isdst)
- if (++i >= sp->typecnt) {
- for (i = 1; i < sp->timecnt; ++i)
- i = (int) sp->types[i - 1];
- ** To get (wrong) behavior that's compatible with System V Release 2.0
- ** you'd replace the statement below with
- ** t += ttisp->tt_gmtoff;
- ** timesub(&t, 0L, sp, tmp);
- result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
- tmp->tm_isdst = ttisp->tt_isdst;
- tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
- tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
-#endif /* defined TM_ZONE */
-** gmtsub is to gmtime as localsub is to localtime.
-gmtsub(timep, offset, tmp)
-const time_t * const timep;
- register struct tm * result;
- gmtptr = (struct state *) malloc(sizeof *gmtptr);
-#endif /* defined ALL_STATE */
- result = timesub(timep, offset, gmtptr, tmp);
- ** Could get fancy here and deliver something such as
- ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
- ** but this is no time for a treasure hunt.
- tmp->TM_ZONE = wildabbr;
- else tmp->TM_ZONE = gmtptr->chars;
-#endif /* defined ALL_STATE */
- tmp->TM_ZONE = gmtptr->chars;
-#endif /* defined TM_ZONE */
-** Return the number of leap years through the end of the given year
-** where, to make the math easy, the answer for year zero is defined as zero.
- return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
- -(leaps_thru_end_of(-(y + 1)) + 1);
-timesub(timep, offset, sp, tmp)
-const time_t * const timep;
-register const struct state * const sp;
-register struct tm * const tmp;
- register const struct lsinfo * lp;
- register int idays; /* unsigned would be so 2003 */
- register const int * ip;
- i = (sp == NULL) ? 0 : sp->leapcnt;
-#endif /* defined ALL_STATE */
- if (*timep >= lp->ls_trans) {
- if (*timep == lp->ls_trans) {
- hit = ((i == 0 && lp->ls_corr > 0) ||
- lp->ls_corr > sp->lsis[i - 1].ls_corr);
- sp->lsis[i].ls_trans ==
- sp->lsis[i - 1].ls_trans + 1 &&
- sp->lsis[i - 1].ls_corr + 1) {
- tdays = *timep / SECSPERDAY;
- rem = *timep - tdays * SECSPERDAY;
- while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
- register time_t tdelta;
- tdelta = tdays / DAYSPERLYEAR;
- if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
- idelta = (tdays < 0) ? -1 : 1;
- if (increment_overflow(&newy, idelta))
- leapdays = leaps_thru_end_of(newy - 1) -
- leaps_thru_end_of(y - 1);
- tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
- seconds = tdays * SECSPERDAY + 0.5;
- tdays = seconds / SECSPERDAY;
- rem += seconds - tdays * SECSPERDAY;
- ** Given the range, we can now fearlessly cast...
- while (rem >= SECSPERDAY) {
- if (increment_overflow(&y, -1))
- idays += year_lengths[isleap(y)];
- while (idays >= year_lengths[isleap(y)]) {
- idays -= year_lengths[isleap(y)];
- if (increment_overflow(&y, 1))
- if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
- ** The "extra" mods below avoid overflow problems.
- tmp->tm_wday = EPOCH_WDAY +
- ((y - EPOCH_YEAR) % DAYSPERWEEK) *
- (DAYSPERNYEAR % DAYSPERWEEK) +
- leaps_thru_end_of(y - 1) -
- leaps_thru_end_of(EPOCH_YEAR - 1) +
- tmp->tm_wday %= DAYSPERWEEK;
- tmp->tm_wday += DAYSPERWEEK;
- tmp->tm_hour = (int) (rem / SECSPERHOUR);
- tmp->tm_min = (int) (rem / SECSPERMIN);
- ** A positive leap second requires a special
- ** representation. This uses "... ??:59:60" et seq.
- tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
- ip = mon_lengths[isleap(y)];
- for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
- idays -= ip[tmp->tm_mon];
- tmp->tm_mday = (int) (idays + 1);
- tmp->TM_GMTOFF = offset;
-#endif /* defined TM_GMTOFF */
-** Adapted from code provided by Robert Elz, who writes:
-** The "best" way to do mktime I think is based on an idea of Bob
-** Kridle's (so its said...) from a long time ago.
-** It does a binary search of the time_t space. Since time_t's are
-** just 32 bits, its a max of 32 iterations (even at 64 bits it
-** would still be very reasonable).
-#endif /* !defined WRONG */
-** Simplified normalize logic courtesy Paul Eggert.
-increment_overflow(number, delta)
- return (*number < number0) != (delta < 0);
-int tz_init( const char *zoneinfo_dir )
- if( zoneinfo_dir == NULL )
- ptr = malloc( strlen(zoneinfo_dir) + 10 );
- sprintf( ptr, "%s/zone.tab", zoneinfo_dir );
- fd = open( ptr, O_RDONLY );
- tzdir = strdup(zoneinfo_dir);
--- a/buddytime/localtime.h Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-/*************************************************************************
- * Header file for timezone module
- * by Martijn van Oosterhout <kleptog@svana.org> (C) April 2006
- * Licenced under the GNU General Public Licence version 2.
- *************************************************************************/
-struct state *timezone_load (const char * name);
-struct tm * gmtsub (const time_t * timep, long offset,
-struct tm * localsub (const time_t * timep, long offset,
- struct tm * tmp, struct state *sp);
-int tz_init(const char *zoneinfo_dir);
--- a/buddytime/meson.build Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-if TYPES.contains('incomplete') and PURPLE.found()
- executable('recursetest',
- buddytime = shared_library('buddytime',
- # FIXME: I don't think this file should use Pidgin.
- dependencies : [PIDGIN, PURPLE, GLIB],
- install_dir : PURPLE_LIBDIR)
- PP_PURPLE_BUILD += 'buddytime'
- executable('gtktimezonetest',
- gtkbuddytime = shared_module('gtkbuddytime',
- dependencies : [PIDGIN, GTK],
- install_dir : PIDGIN_LIBDIR)
- PP_PIDGIN_BUILD += 'gtkbuddytime'
--- a/buddytime/private.h Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,316 +0,0 @@
-/*************************************************************************
- * Private Header file for timezone module
- * copied from Olson timezone code, licence unchanged
- * by Martijn van Oosterhout <kleptog@svana.org> (C) April 2006
- *************************************************************************/
-** This file is in the public domain, so clarified as of
-** 1996-06-05 by Arthur David Olson.
-** This header is for use ONLY with the time conversion code.
-** There is no guarantee that it will remain unchanged,
-** or that it will remain at all.
-** Do NOT copy it to any system include directory.
-#define GRANDPARENTED "Local time zone must be set--see zic manual page"
-** Defaults for preprocessor symbols.
-** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'.
-#endif /* !defined HAVE_ADJTIME */
-#endif /* !defined HAVE_GETTEXT */
-#ifndef HAVE_INCOMPATIBLE_CTIME_R
-#define HAVE_INCOMPATIBLE_CTIME_R 0
-#endif /* !defined INCOMPATIBLE_CTIME_R */
-#ifndef HAVE_SETTIMEOFDAY
-#define HAVE_SETTIMEOFDAY 3
-#endif /* !defined HAVE_SETTIMEOFDAY */
-#endif /* !defined HAVE_STRERROR */
-#endif /* !defined HAVE_SYMLINK */
-#define HAVE_SYS_STAT_H 1
-#endif /* !defined HAVE_SYS_STAT_H */
-#define HAVE_SYS_WAIT_H 1
-#endif /* !defined HAVE_SYS_WAIT_H */
-#endif /* !defined HAVE_UNISTD_H */
-#endif /* !defined HAVE_UTMPX_H */
-#define LOCALE_HOME "/usr/lib/locale"
-#endif /* !defined LOCALE_HOME */
-#if HAVE_INCOMPATIBLE_CTIME_R
-#define asctime_r _incompatible_asctime_r
-#define ctime_r _incompatible_ctime_r
-#endif /* HAVE_INCOMPATIBLE_CTIME_R */
-#include "sys/types.h" /* for time_t */
-#include "limits.h" /* for CHAR_BIT */
-#endif /* HAVE_GETTEXT */
-#include <sys/wait.h> /* for WIFEXITED and WEXITSTATUS */
-#endif /* HAVE_SYS_WAIT_H */
-#define WIFEXITED(status) (((status) & 0xff) == 0)
-#endif /* !defined WIFEXITED */
-#define WEXITSTATUS(status) (((status) >> 8) & 0xff)
-#endif /* !defined WEXITSTATUS */
-#include "unistd.h" /* for F_OK and R_OK */
-#endif /* HAVE_UNISTD_H */
-#endif /* !defined F_OK */
-#endif /* !defined R_OK */
-#endif /* !HAVE_UNISTD_H */
-/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
-#define is_digit(c) ((unsigned)(c) - '0' <= 9)
-** Workarounds for compilers/systems.
-** SunOS 4.1.1 cc lacks prototypes.
-** SunOS 4.1.1 headers lack EXIT_SUCCESS.
-#endif /* !defined EXIT_SUCCESS */
-** SunOS 4.1.1 headers lack EXIT_FAILURE.
-#endif /* !defined EXIT_FAILURE */
-** SunOS 4.1.1 headers lack FILENAME_MAX.
-#endif /* defined unix */
-#endif /* !defined MAXPATHLEN */
-#define FILENAME_MAX MAXPATHLEN
-#endif /* defined MAXPATHLEN */
-#define FILENAME_MAX 1024 /* Pure guesswork */
-#endif /* !defined MAXPATHLEN */
-#endif /* !defined FILENAME_MAX */
-** SunOS 4.1.1 libraries lack remove.
-extern int unlink P((const char * filename));
-#endif /* !defined remove */
-** Some ancient errno.h implementations don't declare errno.
-** But some newer errno.h implementations define it as a macro.
-** Fix the former without affecting the latter.
-#endif /* !defined errno */
-** Some time.h implementations don't declare asctime_r.
-** Others might define it as a macro.
-** Fix the former without affecting the latter.
-extern char * asctime_r();
-** Private function declarations.
-char * icalloc P((int nelem, int elsize));
-char * icatalloc P((char * old, const char * new));
-char * icpyalloc P((const char * string));
-char * imalloc P((int n));
-void * irealloc P((void * pointer, int size));
-void icfree P((char * pointer));
-void ifree P((char * pointer));
-const char *scheck P((const char *string, const char *format));
-** Finally, some convenience items.
-#endif /* !defined TRUE */
-#endif /* !defined FALSE */
-#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
-#endif /* !defined TYPE_BIT */
-#define TYPE_SIGNED(type) (((type) -1) < 0)
-#endif /* !defined TYPE_SIGNED */
-** Since the definition of TYPE_INTEGRAL contains floating point numbers,
-** it cannot be used in preprocessor directives.
-#define TYPE_INTEGRAL(type) (((type) 0.5) != 0.5)
-#endif /* !defined TYPE_INTEGRAL */
-#ifndef INT_STRLEN_MAXIMUM
-** 302 / 1000 is log10(2.0) rounded up.
-** Subtract one for the sign bit if the type is signed;
-** add one for integer division truncation;
-** add one more for a minus sign if the type is signed.
-#define INT_STRLEN_MAXIMUM(type) \
- ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \
-#endif /* !defined INT_STRLEN_MAXIMUM */
-#endif /* defined lint */
-#endif /* defined __GNUC__ */
-#endif /* !defined lint */
-#endif /* !defined GNUC_or_lint */
-#define INITIALIZE(x) ((x) = 0)
-#endif /* defined GNUC_or_lint */
-#endif /* !defined GNUC_or_lint */
-#endif /* !defined INITIALIZE */
-** For the benefit of GNU folk...
-** `_(MSGID)' uses the current locale's message library string for MSGID.
-** The default is to use gettext if available, and use MSGID otherwise.
-#define _(msgid) gettext(msgid)
-#else /* !HAVE_GETTEXT */
-#endif /* !HAVE_GETTEXT */
-#endif /* !defined TZ_DOMAIN */
-#if HAVE_INCOMPATIBLE_CTIME_R
-char *asctime_r P((struct tm const *, char *));
-char *ctime_r P((time_t const *, char *));
-#endif /* HAVE_INCOMPATIBLE_CTIME_R */
-** UNIX was a registered trademark of The Open Group in 2003.
-#endif /* !defined PRIVATE_H */
--- a/buddytime/recurse.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,141 +0,0 @@
-/*************************************************************************
- * by Martijn van Oosterhout <kleptog@svana.org> (C) April 2006
- * Licenced under the GNU General Public Licence version 2.
- * Provides a function to recurse a directory and call a callback for each
- *************************************************************************/
-/* GLibc specific version. In this version, the entries are sorted */
-/* We assume dirname ends in a /, prefix also unless empty */
-recurse_directory_int(char *dirname, char *prefix, DirRecurseMatch func, void *data)
- struct dirent **namelist;
- if((ents = scandir(dirname, &namelist, 0, alphasort)) < 0)
- for (i = 0; i < ents; i++)
- asprintf(&ptr, "%s%s", dirname, ent->d_name);
- asprintf(&ptr, "%s%s", prefix, ent->d_name);
- else if(S_ISDIR(s.st_mode))
- char *newdirname, *newprefix;
- if(ent->d_name[0] != '.')
- asprintf(&newdirname, "%s%s/", dirname, ent->d_name);
- asprintf(&newprefix, "%s%s/", prefix, ent->d_name);
- ret = recurse_directory_int(newdirname, newprefix, func, data);
-/* generic version, here they are unsorted */
-/* We assume dirname ends in a /, prefix also unless empty */
-recurse_directory_int(char *dirname, char *prefix, DirRecurseMatch func, void *data)
- dir = opendir(dirname);
- while ((ent = readdir(dir)) != NULL)
- asprintf(&ptr, "%s%s", dirname, ent->d_name);
- asprintf(&ptr, "%s%s", prefix, ent->d_name);
- else if(S_ISDIR(s.st_mode))
- char *newdirname, *newprefix;
- if(ent->d_name[0] != '.')
- asprintf(&newdirname, "%s%s/", dirname, ent->d_name);
- asprintf(&newprefix, "%s%s/", prefix, ent->d_name);
- ret = recurse_directory_int(newdirname, newprefix, func, data);
-recurse_directory(char *dirname, DirRecurseMatch func, void *data)
- char *newdirname = NULL;
- if(dirname[strlen(dirname) - 1] != '/')
- asprintf(&newdirname, "%s/", dirname);
- ret = recurse_directory_int(newdirname ? newdirname : dirname, "", func, data);
--- a/buddytime/recurse.h Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-/*************************************************************************
- * Header file for recursion module
- * by Martijn van Oosterhout <kleptog@svana.org> (C) April 2006
- * Licenced under the GNU General Public Licence version 2.
- *************************************************************************/
-typedef int (*DirRecurseMatch)(char *filename, void *data);
-int recurse_directory( char *dirname, DirRecurseMatch func, void *data );
--- a/buddytime/recursetest.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/*************************************************************************
- * Recursion test module
- * by Martijn van Oosterhout <kleptog@svana.org> (C) April 2006
- * Licenced under the GNU General Public Licence version 2.
- * Code to test the recursion module.
- *************************************************************************/
-process_entry(char *str, void *ptr)
- recurse_directory("/usr/share/zoneinfo", process_entry, main);
--- a/buddytime/timetest.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*************************************************************************
- * by Martijn van Oosterhout <kleptog@svana.org> (C) April 2006
- * Licenced under the GNU General Public Licence version 2.
- * Code to test the timezone module.
- *************************************************************************/
- time_t now = time(NULL);
- state = timezone_load("Australia/Sydney");
- localsub(&now, 0, &tm, state);
--- a/buddytime/tzfile.h Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,175 +0,0 @@
-/*************************************************************************
- * Private Header file for timezone module
- * copied from Olson timezone code, licence unchanged
- * by Martijn van Oosterhout <kleptog@svana.org> (C) April 2006
- *************************************************************************/
-** This file is in the public domain, so clarified as of
-** 1996-06-05 by Arthur David Olson.
-** This header is for use ONLY with the time conversion code.
-** There is no guarantee that it will remain unchanged,
-** or that it will remain at all.
-** Do NOT copy it to any system include directory.
-** Information about time zone files.
-#define TZDIR "/usr/share/zoneinfo" /* Default time zone object file directory */
-#endif /* !defined TZDIR */
-#define TZDEFAULT "localtime"
-#endif /* !defined TZDEFAULT */
-#define TZDEFRULES "posixrules"
-#endif /* !defined TZDEFRULES */
-** Each file begins with. . .
- char tzh_magic[4]; /* TZ_MAGIC */
- char tzh_reserved[16]; /* reserved for future use */
- char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
- char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
- char tzh_leapcnt[4]; /* coded number of leap seconds */
- char tzh_timecnt[4]; /* coded number of transition times */
- char tzh_typecnt[4]; /* coded number of local time types */
- char tzh_charcnt[4]; /* coded number of abbr. chars */
-** . . .followed by. . .
-** tzh_timecnt (char [4])s coded transition times a la time(2)
-** tzh_timecnt (unsigned char)s types of local time starting at above
-** tzh_typecnt repetitions of
-** one (char [4]) coded UTC offset in seconds
-** one (unsigned char) used to set tm_isdst
-** one (unsigned char) that's an abbreviation list index
-** tzh_charcnt (char)s '\0'-terminated zone abbreviations
-** tzh_leapcnt repetitions of
-** one (char [4]) coded leap second transition times
-** one (char [4]) total correction after above
-** tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition
-** time is standard time, if FALSE,
-** transition time is wall clock time
-** if absent, transition times are
-** assumed to be wall clock time
-** tzh_ttisgmtcnt (char)s indexed by type; if TRUE, transition
-** time is UTC, if FALSE,
-** transition time is local time
-** if absent, transition times are
-** assumed to be local time
-** In the current implementation, "tzset()" refuses to deal with files that
-** exceed any of the limits below.
-** The TZ_MAX_TIMES value below is enough to handle a bit more than a
-** year's worth of solar time (corrected daily to the nearest second) or
-** 138 years of Pacific Presidential Election time
-** (where there are three time zone transitions every fourth year).
-#define TZ_MAX_TIMES 370
-#endif /* !defined TZ_MAX_TIMES */
-#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */
-#endif /* !defined NOSOLAR */
-** Must be at least 14 for Europe/Riga as of Jan 12 1995,
-** as noted by Earl Chew.
-#define TZ_MAX_TYPES 20 /* Maximum number of local time types */
-#endif /* !defined NOSOLAR */
-#endif /* !defined TZ_MAX_TYPES */
-#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */
- /* (limited by what unsigned chars can hold) */
-#endif /* !defined TZ_MAX_CHARS */
-#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */
-#endif /* !defined TZ_MAX_LEAPS */
-#define DAYSPERNYEAR 365
-#define DAYSPERLYEAR 366
-#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
-#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY)
-#define TM_YEAR_BASE 1900
-#define EPOCH_WDAY TM_THURSDAY
-#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
-** Since everything in isleap is modulo 400 (or a factor of 400), we know that
-** isleap(y) == isleap(y % 400)
-** isleap(a + b) == isleap((a + b) % 400)
-** isleap(a + b) == isleap(a % 400 + b % 400)
-** This is true even if % means modulo rather than Fortran remainder
-** (which is allowed by C89 but not C99).
-** We use this to avoid addition overflow problems.
-#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
-#endif /* !defined TZFILE_H */
--- a/chronic/README.md Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-Allows buddies to remotely trigger sound playing in your running libpurple client with {S <sound>. Inspired by IRC channel resident EvilDennisR and ancient versions of AOL. THIS PLUGIN IS NOT YET FUNCTIONAL! IT IS USELESS!
--- a/chronic/chronic.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
- * Chronic - Remote sound play triggering
- * Copyright (C) 2006-2008 John Bailey <rekkanoryo@rekkanoryo.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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
-/* If you can't figure out what this line is for, DON'T TOUCH IT. */
-#include "../common/pp_internal.h"
-#include <conversation.h>
-chronic_received_cb(PurpleAccount *account, char *sender, char *message,
- PurpleConversation *conv, PurpleMessageFlags flags)
- /* this needs some work... */
- char *sound = NULL, *path = NULL;
- if(strlen(message) > 3) {
- if(!strncmp(message, "{S ", 3)) {
- /* add code to find a matching sound */
- /* purple_sound_play_file(); */
-chronic_load(PurplePlugin *plugin)
- convhandle = purple_conversations_get_handle();
- purple_signal_connect(convhandle, "received-im-msg", plugin,
- PURPLE_CALLBACK(chronic_received_cb), NULL);
- purple_signal_connect(convhandle, "received-chat-msg", plugin,
- PURPLE_CALLBACK(chronic_received_cb), NULL);
-static PurplePluginInfo chronic_info =
- PURPLE_PLUGIN_MAGIC, /* magic? do you think i'm gullible enough to
- PURPLE_PLUGIN_STANDARD,
- PURPLE_PRIORITY_DEFAULT,
- "core-plugin_pack-chronic",
- "John Bailey <rekkanoryo@rekkanoryo.org>",
- /* comment below is temporary until i decide if i need the function */
- NULL, /*chronic_unload,*/
-chronic_init(PurplePlugin *plugin)
- bindtextdomain(GETTEXT_PACKAGE, PP_LOCALEDIR);
- bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
- chronic_info.name = _("Chronic");
- chronic_info.summary = _("Sound playing triggers");
- chronic_info.description = _("Allows buddies to remotely trigger sound"
- " playing in your instance of Purple with {S <sound>. Inspired"
- " by #guifications channel resident EvilDennisR and ancient"
- " versions of AOL. THIS PLUGIN IS NOT YET FUNCTIONAL!"
-PURPLE_INIT_PLUGIN(chronic, chronic_init, chronic_info)
--- a/chronic/meson.build Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-if TYPES.contains('incomplete') and PURPLE.found()
- chronic = shared_library('chronic',
- dependencies : [PURPLE, GLIB],
- install_dir : PURPLE_LIBDIR)
- PP_PURPLE_BUILD += 'chronic'
--- a/findip/README.md Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-authors: Sadrul Habib Chowdhury
-Find the IP of a person in the buddylist. This doesn't really work.
--- a/findip/findip.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,182 +0,0 @@
- * Find IP - Find the IP of a person in the buddylist
- * Copyright (C) 2007-2008
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA
-/* If you can't figure out what this line is for, DON'T TOUCH IT. */
-#include "../common/pp_internal.h"
-#define PLUGIN_ID "core-plugin_pack-findip"
-#define PLUGIN_STATIC_NAME "findip"
-#define PLUGIN_AUTHOR "someone <someone@somewhere.tld>"
-/* If you can't figure out what this line is for, DON'T TOUCH IT. */
-#include "../common/pp_internal.h"
-#define PREF_ROOT "/plugins/core/plugin_pack/" PLUGIN_STATIC_NAME
-#define PREF_NOTIFY PREF_ROOT "/notify"
- PurpleConversation *conv;
- buddy = (PurpleBuddy*)node;
- if (buddy->account == NULL || buddy->account->gc == NULL)
- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, buddy->account, buddy->name);
- purple_conversation_write(conv, NULL, _("Looked up IP: 127.0.0.1\n"),
- PURPLE_MESSAGE_NOTIFY | PURPLE_MESSAGE_SYSTEM,
- if (purple_prefs_get_bool(PREF_NOTIFY))
- serv_send_im(buddy->account->gc, buddy->name, _("Yo! What's your IP?"), 0);
-find_ip(PurpleBlistNode *node, gpointer plugin)
- PurpleConversation *conv;
- if (PURPLE_BLIST_NODE_IS_CONTACT(node))
- node = (PurpleBlistNode*)purple_contact_get_priority_buddy((PurpleContact*)node);
- if (!PURPLE_BLIST_NODE_IS_BUDDY(node))
- purple_timeout_add_seconds(5, show_ip, node);
- buddy = (PurpleBuddy*)node;
- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, buddy->account, buddy->name);
- purple_conversation_write(conv, NULL, _("Looking up the IP ...\n"),
- PURPLE_MESSAGE_NOTIFY | PURPLE_MESSAGE_SYSTEM,
-context_menu(PurpleBlistNode *node, GList **menu, gpointer plugin)
- PurpleMenuAction *action;
- if (!PURPLE_BLIST_NODE_IS_BUDDY(node) && !PURPLE_BLIST_NODE_IS_CONTACT(node))
- action = purple_menu_action_new(_("Find IP"),
- PURPLE_CALLBACK(find_ip), plugin, NULL);
- (*menu) = g_list_prepend(*menu, action);
-plugin_load(PurplePlugin *plugin)
- purple_signal_connect(purple_blist_get_handle(), "blist-node-extended-menu", plugin,
- PURPLE_CALLBACK(context_menu), plugin);
-plugin_unload(PurplePlugin *plugin)
-static PurplePluginPrefFrame *
-get_plugin_pref_frame(PurplePlugin *plugin)
- PurplePluginPrefFrame *frame;
- PurplePluginPref *pref;
- frame = purple_plugin_pref_frame_new();
- pref = purple_plugin_pref_new_with_name_and_label(PREF_NOTIFY,
- _("Notify the user that you are trying to get the IP"));
- purple_plugin_pref_frame_add(frame, pref);
-static PurplePluginUiInfo pref_info = {
-static PurplePluginInfo info = {
- PURPLE_PLUGIN_MAGIC, /* Magic */
- PURPLE_MAJOR_VERSION, /* Purple Major Version */
- PURPLE_MINOR_VERSION, /* Purple Minor Version */
- PURPLE_PLUGIN_STANDARD, /* plugin type */
- NULL, /* ui requirement */
- NULL, /* dependencies */
- PURPLE_PRIORITY_DEFAULT, /* priority */
- PLUGIN_ID, /* plugin id */
- PP_VERSION, /* version */
- NULL, /* description */
- PLUGIN_AUTHOR, /* author */
- PP_WEBSITE , /* website */
- plugin_load, /* load */
- plugin_unload, /* unload */
- &pref_info, /* prefs_info */
-init_plugin(PurplePlugin *plugin) {
- bindtextdomain(GETTEXT_PACKAGE, PP_LOCALEDIR);
- bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
- info.name = _("Find IP");
- info.summary = _("Find the IP of a person in the buddylist.");
- info.description = _("Find the IP of a person in the buddylist. This doesn't really work.");
- purple_prefs_add_none(PREF_ROOT);
- purple_prefs_add_bool(PREF_NOTIFY, TRUE);
-PURPLE_INIT_PLUGIN(PLUGIN_STATIC_NAME, init_plugin, info)
--- a/findip/meson.build Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-if TYPES.contains('default') and PURPLE.found()
- findip = shared_library('findip',
- dependencies : [PURPLE, GLIB],
- install_dir : PURPLE_LIBDIR)
- PP_PURPLE_BUILD += 'findip'
--- a/hideconv/README.md Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-authors: Sadrul Habib Chowdhury
-notes: Superseded by functionality present in Pidgin 2.3.0 and newer
-Hide conversations without closing them.
--- a/hideconv/hideconv.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,291 +0,0 @@
- * Hide Conversations - You can hide conversations without having to close them.
- * Copyright (C) 2007-2008 Sadrul Habib Chowdhury <sadrul@users.sourceforge.net>
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA
-/* If you can't figure out what this line is for, DON'T TOUCH IT. */
-#include "../common/pp_internal.h"
-#define PLUGIN_ID "gtk-plugin_pack-hideconv"
-#define PLUGIN_STATIC_NAME "hideconv"
-#define PLUGIN_AUTHOR "Sadrul H Chowdhury <sadrul@users.sourceforge.net>"
-#define MENUSET "hideconv::menuset"
-static PidginWindow *window = NULL;
-static void (*orig_conv_present)(PurpleConversation *conv);
-static void conv_created(PurpleConversation *conv, gpointer null);
- /* This is a 'wee bit' hacky. Create two conv windows, remove the second
- * one from the list, and then destroy the first one. This is because we
- * want to hide this entire conversation window from pidgin itself.
- PidginWindow *tmp = pidgin_conv_window_new();
- window = pidgin_conv_window_new();
- null = pidgin_conv_windows_get_list();
- null = g_list_remove(null, window);
- pidgin_conv_window_hide(window);
- pidgin_conv_window_destroy(tmp);
-gtkconv_redisplaying(PidginConversation *gtkconv)
- conv_created(gtkconv->active_conv, NULL);
- g_signal_handlers_disconnect_by_func(G_OBJECT(gtkconv->imhtml),
- G_CALLBACK(gtkconv_redisplaying), gtkconv);
-hide_gtkconv(PidginConversation *gtkconv)
- pidgin_conv_window_add_gtkconv(window, gtkconv);
- g_signal_connect_swapped(G_OBJECT(gtkconv->imhtml), "visibility_notify_event",
- G_CALLBACK(gtkconv_redisplaying), gtkconv);
-hide_conv_cb(GtkWidget *wid, PidginWindow *win)
- PidginConversation *gtkconv = pidgin_conv_window_get_active_gtkconv(win);
- pidgin_conv_window_remove_gtkconv(win, gtkconv);
-show_convs_cb(PurplePluginAction *dontcare)
- GList *list = g_list_copy(pidgin_conv_window_get_gtkconvs(window)), *iter;
- for (iter = list; iter; iter = iter->next) {
- PidginConversation *gtkconv = iter->data;
- pidgin_conv_window_remove_gtkconv(window, gtkconv);
- pidgin_conv_placement_place(gtkconv);
- purple_conversation_present(gtkconv->active_conv);
- conv_created(gtkconv->active_conv, NULL);
- create_hidden_convwin();
-attach_menu_to_window(PidginWindow *win)
- GtkWidget *widget, *item;
- if (g_object_get_data(G_OBJECT(win->window), MENUSET))
- g_object_set_data(G_OBJECT(win->window), MENUSET, GINT_TO_POINTER(TRUE));
- widget = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Options"));
- /* We cannot use pidgin_separator, unfortunately. */
- item = gtk_separator_menu_item_new();
- gtk_menu_shell_append(GTK_MENU_SHELL(widget), item);
- g_object_set_data(G_OBJECT(item), MENUSET, GINT_TO_POINTER(TRUE));
- item = gtk_menu_item_new_with_mnemonic(_("_Hide Conversation"));
- g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(hide_conv_cb), win);
- gtk_menu_shell_append(GTK_MENU_SHELL(widget), item);
- g_object_set_data(G_OBJECT(item), MENUSET, GINT_TO_POINTER(TRUE));
- item = gtk_menu_item_new_with_mnemonic(_("Show Hidden Conversations"));
- g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(show_convs_cb), NULL);
- gtk_menu_shell_append(GTK_MENU_SHELL(widget), item);
- g_object_set_data(G_OBJECT(item), MENUSET, GINT_TO_POINTER(TRUE));
-detach_menu_from_window(PidginWindow *win)
- widget = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Options"));
- children = gtk_container_get_children(GTK_CONTAINER(widget));
- GtkWidget *item = children->data;
- children = children->next;
- if (g_object_get_data(G_OBJECT(item), MENUSET))
- gtk_widget_destroy(item);
- g_object_set_data(G_OBJECT(win->window), MENUSET, GINT_TO_POINTER(FALSE));
-conv_created_to(PurpleConversation *conv)
- PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
- if (!gtkconv || !gtkconv->win || !gtkconv->win->window)
- if (!GTK_WIDGET_VISIBLE(gtkconv->win->window))
- attach_menu_to_window(gtkconv->win);
-conv_created(PurpleConversation *conv, gpointer null)
- g_timeout_add(1000, (GSourceFunc)conv_created_to, conv);
-twisted_present(PurpleConversation *conv)
- PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
- if (gtkconv && gtkconv->win == window) {
- gboolean last = (g_list_length(window->gtkconvs) == 1);
- pidgin_conv_window_remove_gtkconv(window, gtkconv);
- pidgin_conv_placement_place(gtkconv);
- create_hidden_convwin();
- orig_conv_present(conv);
- conv_created(conv, NULL);
-hide_all_conv(PurplePluginAction *dontcare)
- GList *iter = pidgin_conv_windows_get_list();
- GList *it = pidgin_conv_window_get_gtkconvs(iter->data);
- PidginConversation *gtkconv = it->data;
- pidgin_conv_window_remove_gtkconv(gtkconv->win, gtkconv);
-plugin_load(PurplePlugin *plugin)
- PurpleConversationUiOps *ops = pidgin_conversations_get_conv_ui_ops();
- orig_conv_present = ops->present;
- ops->present = twisted_present;
- create_hidden_convwin();
- purple_signal_connect(purple_conversations_get_handle(), "conversation-created",
- plugin, PURPLE_CALLBACK(conv_created), NULL);
- g_list_foreach(pidgin_conv_windows_get_list(), (GFunc)attach_menu_to_window, NULL);
-plugin_unload(PurplePlugin *plugin)
- PurpleConversationUiOps *ops = pidgin_conversations_get_conv_ui_ops();
- ops->present = orig_conv_present;
- pidgin_conv_window_destroy(window);
- g_list_foreach(pidgin_conv_windows_get_list(), (GFunc)detach_menu_from_window, NULL);
-actions(PurplePlugin *plugin, gpointer context)
- PurplePluginAction *act;
- act = purple_plugin_action_new(_("Show All Hidden Conversations"), show_convs_cb);
- list = g_list_append(list, act);
- act = purple_plugin_action_new(_("Hide All Conversations"), hide_all_conv);
- list = g_list_append(list, act);
-static PurplePluginInfo info =
- PURPLE_PLUGIN_MAGIC, /* Magic */
- PURPLE_MAJOR_VERSION, /* Purple Major Version */
- PURPLE_MINOR_VERSION, /* Purple Minor Version */
- PURPLE_PLUGIN_STANDARD, /* plugin type */
- PIDGIN_PLUGIN_TYPE, /* ui requirement */
- NULL, /* dependencies */
- PURPLE_PRIORITY_DEFAULT, /* priority */
- PLUGIN_ID, /* plugin id */
- PP_VERSION, /* version */
- NULL, /* description */
- PLUGIN_AUTHOR, /* author */
- PP_WEBSITE, /* website */
- plugin_load, /* load */
- plugin_unload, /* unload */
-init_plugin(PurplePlugin *plugin) {
- bindtextdomain(GETTEXT_PACKAGE, PP_LOCALEDIR);
- bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
- info.name = _("Hide Conversation");
- info.summary = _("Hide conversations without closing them.");
- info.description = _("Hide conversations without closing them.");
-PURPLE_INIT_PLUGIN(PLUGIN_STATIC_NAME, init_plugin, info)
--- a/hideconv/meson.build Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-if TYPES.contains('incomplete') and PIDGIN.found()
- hideconv = shared_module('hideconv',
- dependencies : [PIDGIN, GTK],
- install_dir : PIDGIN_LIBDIR)
- PP_PIDGIN_BUILD += 'hideconv'
--- a/ignorance/README.md Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-notes: Needs some TLC. It builds and probably works, but is far from an acceptible state.
-Allows management of users with various levels of activity.
--- a/ignorance/callbacks.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,701 +0,0 @@
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
-#include "ignorance_internal.h"
-static gboolean populate_panel(GtkTreeSelection *sel);
-static gboolean verify_form();
-static gboolean add_rule_from_form(GtkTreeView *view);
-static gboolean add_group_from_form(GtkTreeView *view);
-static gboolean edit_rule_from_form(GtkTreeView *view);
-static gboolean del_rule_from_form(GtkTreeView *view);
-static gboolean del_group_from_form(GtkTreeView *view);
-static gboolean ignorance_rule_valid(const gchar *ruletext, gint ruletype);
-static gboolean ignorance_rulename_valid(const gchar *rule_name);
-gboolean on_levelView_row_activated (GtkTreeSelection *sel, gpointer user_data) {
-void on_levelAdd_clicked (GtkButton *button, gpointer user_data) {
- if(!add_rule_from_form(user_data)) {
-void on_groupAdd_clicked (GtkButton *button, gpointer user_data) {
- if(!add_group_from_form(user_data)) {
- /* XXX: Do something I guess? -- sadrul */
-void on_levelEdit_clicked (GtkButton *button, gpointer user_data) {
- if(!edit_rule_from_form(user_data)) {
- /* XXX: Do something I guess? -- sadrul */
-on_levelDel_clicked (GtkButton *button, gpointer user_data) {
- if(!del_rule_from_form(user_data)) {
- del_group_from_form(user_data);
-static gboolean populate_panel(GtkTreeSelection *sel) {
- gchar *levnames, *rulenames;
- ignorance_level *level=NULL;
- ignorance_rule *rule=NULL;
- GString *levgs, *rulegs;
- if (gtk_tree_selection_get_selected (sel, &model, &iter)) {
- gtk_tree_model_get (model, &iter, LEVEL_COLUMN, &levnames, -1);
- gtk_tree_model_get(model,&iter,RULE_COLUMN,&rulenames,-1);
- if(strlen(rulenames)) {
- levgs=g_string_new(levnames);
- rulegs=g_string_new(rulenames);
- level=ignorance_get_level_name(levgs);
- rule=ignorance_level_get_rule(level,rulegs);
- fprintf(stderr,"Ignorance: Unable to find rule %s on level %s\n",
- rulegs->str,level->name->str);
- gtk_entry_set_text(GTK_ENTRY(rulename),rulenames);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(filter_cb),
- rule->score & IGNORANCE_FLAG_FILTER);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ignore_cb),
- rule->score & IGNORANCE_FLAG_IGNORE);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(message_cb),
- rule->score & IGNORANCE_FLAG_MESSAGE);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sound_cb),
- rule->score & IGNORANCE_FLAG_SOUND);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(execute_cb),
- rule->score & IGNORANCE_FLAG_EXECUTE);
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(message_cb))) {
- gtk_entry_set_text(GTK_ENTRY(message_entry),rule->message);
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sound_cb))) {
- gtk_entry_set_text(GTK_ENTRY(sound_entry),rule->sound);
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(execute_cb))) {
- gtk_entry_set_text(GTK_ENTRY(execute_entry),rule->command);
- gtk_entry_set_text(GTK_ENTRY(filtervalue),
- (const gchar*)(rule->value));
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(im_type_cb),
- rule->flags & IGNORANCE_APPLY_IM);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chat_type_cb),
- rule->flags & IGNORANCE_APPLY_CHAT);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(username_type_cb),
- rule->flags & IGNORANCE_APPLY_USER);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enterleave_type_cb),
- rule->flags & IGNORANCE_APPLY_ENTERLEAVE);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(invite_type_cb),
- rule->flags & IGNORANCE_APPLY_INVITE);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(regex_cb),
- rule->type & IGNORANCE_RULE_REGEX);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(repeat_cb),
- rule->type & IGNORANCE_RULE_REPEAT);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enabled_cb),
- gtk_button_set_label(GTK_BUTTON(levelDel),"Remove rule");
- g_string_free(levgs,TRUE);
- g_string_free(rulegs,TRUE);
- gtk_entry_set_text(GTK_ENTRY(rulename),"");
- gtk_entry_set_text(GTK_ENTRY(filtervalue),"");
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(im_type_cb),FALSE);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chat_type_cb),FALSE);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(username_type_cb),
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enterleave_type_cb),
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(invite_type_cb),
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(filter_cb),FALSE);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ignore_cb),FALSE);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(message_cb),FALSE);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sound_cb),FALSE);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(execute_cb),FALSE);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(regex_cb),FALSE);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(repeat_cb),FALSE);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enabled_cb),FALSE);
- gtk_button_set_label(GTK_BUTTON(levelDel),"Remove group");
-void on_filter_cb_toggled (GtkButton *button, gpointer user_data) {
- gboolean amdisabled=!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(message_cb),amdisabled);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ignore_cb),amdisabled);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sound_cb),amdisabled);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(execute_cb),amdisabled);
- /* Maybe we *should* allow them to send a message on filter */
- gtk_widget_set_sensitive(message_cb,amdisabled);
- gtk_widget_set_sensitive(ignore_cb,amdisabled);
- gtk_widget_set_sensitive(sound_cb,amdisabled);
- gtk_widget_set_sensitive(execute_cb,amdisabled);
-void on_ignore_cb_toggled (GtkButton *button, gpointer user_data) {
- gboolean amdisabled=!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(message_cb),amdisabled);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(filter_cb),amdisabled);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sound_cb),amdisabled);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(execute_cb),amdisabled);
- /* Maybe we *should* allow them to send a message on ignore */
- gtk_widget_set_sensitive(message_cb,amdisabled);
- gtk_widget_set_sensitive(filter_cb,amdisabled);
- gtk_widget_set_sensitive(sound_cb,amdisabled);
- gtk_widget_set_sensitive(execute_cb,amdisabled);
-void on_message_cb_toggled (GtkButton *button, gpointer user_data) {
- gboolean isactive=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(message_cb));
- gtk_entry_set_text(GTK_ENTRY(message_entry),"");
- gtk_widget_set_sensitive(message_entry,isactive);
-void on_sound_cb_toggled (GtkButton *button, gpointer user_data) {
- gboolean isactive=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sound_cb));
- gtk_entry_set_text(GTK_ENTRY(sound_entry),"");
- gtk_widget_set_sensitive(sound_entry,isactive);
-#if GTK_CHECK_VERSION(2,4,0)
- gtk_widget_set_sensitive(sound_browse,isactive);
-void on_execute_cb_toggled (GtkButton *button, gpointer user_data) {
- gboolean isactive=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(execute_cb));
- gtk_entry_set_text(GTK_ENTRY(execute_entry),"");
- gtk_widget_set_sensitive(execute_entry,isactive);
- /*gtk_widget_set_sensitive(execute_browse,isactive);*/
-void on_sound_browse_clicked (GtkButton *button, gpointer user_data) {
-#if GTK_CHECK_VERSION(2,4,0)
- GtkWidget *fcd=gtk_file_chooser_dialog_new("Choose sound",NULL,
- GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL,
- GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
- if(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(fcd))) {
- filename=gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fcd));
- gtk_entry_set_text(GTK_ENTRY(sound_entry),filename);
- gtk_widget_destroy(fcd);
-/*No command browser for now
-void on_execute_browse_clicked (GtkButton *button, gpointer user_data) {
- gchar *filename=gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(execute_browse));
- gtk_entry_set_text(GTK_ENTRY(execute_entry),filename);
-static gboolean verify_form() {
- gint type=IGNORANCE_RULE_SIMPLETEXT;
- tmp=(gchar*)gtk_entry_get_text(GTK_ENTRY(filtervalue));
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(regex_cb))) {
- type=IGNORANCE_RULE_REGEX;
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(repeat_cb))) {
- type=IGNORANCE_RULE_REPEAT;
- rv=ignorance_rule_valid(tmp,type);
- purple_debug_error("ignorance","Rule invalid: %s\n",tmp);
- tmp=(gchar*)gtk_entry_get_text(GTK_ENTRY(rulename));
- rv=ignorance_rulename_valid(tmp);
- purple_debug_error("ignorance","Rule name invalid: %s\n",tmp);
-static gboolean add_rule_from_form(GtkTreeView *view) {
- ignorance_rule *rule=NULL;
- ignorance_level *level=NULL;
- GString *rule_name, *level_name;
- GtkTreeIter iter, childiter;
- gchar *rule_value=NULL, *rule_message=NULL, *rule_sound=NULL,
- gint rule_score=0, rule_type=IGNORANCE_RULE_SIMPLETEXT, rule_flags=0;
- gboolean rv=FALSE, rule_enable;
- sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
- if (!gtk_tree_selection_get_selected (sel, &model, &iter)) {
- gtk_tree_model_get (model, &iter, LEVEL_COLUMN, &rule_value, -1);
- }else if(!strlen(rule_value)) {
- level_name=g_string_new(rule_value);
- gtk_tree_model_get(model,&iter,RULE_COLUMN,&rule_value,-1);
- if(strlen(rule_value)) {
- gtk_tree_model_iter_parent(model,&iter,&childiter);
- level=ignorance_get_level_name(level_name);
- rule_name=g_string_new(gtk_entry_get_text(GTK_ENTRY(rulename)));
- rule=ignorance_level_get_rule(level,rule_name);
- g_string_free(level_name,TRUE);
- g_string_free(rule_name,TRUE);
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(regex_cb))) {
- rule_type=IGNORANCE_RULE_REGEX;
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(repeat_cb))) {
- rule_type=IGNORANCE_RULE_REPEAT;
- rule_value=(gchar*)gtk_entry_get_text(GTK_ENTRY(filtervalue));
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(im_type_cb))) {
- rule_flags |= IGNORANCE_APPLY_IM;
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(chat_type_cb))) {
- rule_flags |= IGNORANCE_APPLY_CHAT;
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(username_type_cb))) {
- rule_flags |= IGNORANCE_APPLY_USER;
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enterleave_type_cb))) {
- rule_flags |= IGNORANCE_APPLY_ENTERLEAVE;
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(invite_type_cb))) {
- rule_flags |= IGNORANCE_APPLY_INVITE;
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(filter_cb))) {
- rule_score |= IGNORANCE_FLAG_FILTER;
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ignore_cb))) {
- rule_score |= IGNORANCE_FLAG_IGNORE;
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(message_cb))) {
- rule_score |= IGNORANCE_FLAG_MESSAGE;
- rule_message=(gchar*)gtk_entry_get_text(GTK_ENTRY(message_entry));
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sound_cb))) {
- rule_score |= IGNORANCE_FLAG_SOUND;
- rule_sound=(gchar*)gtk_entry_get_text(GTK_ENTRY(sound_entry));
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(execute_cb))) {
- rule_score |= IGNORANCE_FLAG_EXECUTE;
- rule_command=(gchar*)gtk_entry_get_text(GTK_ENTRY(execute_entry));
- rule_enable=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enabled_cb));
- rule=ignorance_rule_newp(rule_name,rule_type,rule_value,rule_score,
- rule_flags,rule_enable,rule_message,rule_sound,
- rv=ignorance_level_add_rule(level,rule);
- gtk_tree_store_append(GTK_TREE_STORE(model),&childiter,&iter);
- gtk_tree_store_set(GTK_TREE_STORE(model),&childiter,LEVEL_COLUMN,level_name->str,RULE_COLUMN,rule_name->str,-1);
- g_string_free(level_name,TRUE);
- g_string_free(rule_name,TRUE);
-static gboolean add_group_from_form(GtkTreeView *view) {
- GtkTreeStore *store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(view)));
- ignorance_level *level=ignorance_level_new();
- level->name=g_string_new(gtk_entry_get_text(GTK_ENTRY(rulename)));
- rv=ignorance_add_level(level);
- gtk_tree_store_append(store,&iter,NULL);
- gtk_tree_store_set (store, &iter, LEVEL_COLUMN, level->name->str,
-static gboolean edit_rule_from_form(GtkTreeView *view) {
- ignorance_level *level;
- GString *rule_name, *level_name;
- gchar *rule_value, *rule_message=NULL, *rule_sound=NULL, *rule_command=NULL;
- gint rule_score=0, rule_type=IGNORANCE_RULE_SIMPLETEXT, rule_flags=0;
- gboolean rule_enable, rv;
- sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
- if (!gtk_tree_selection_get_selected (sel, &model, &iter)) {
- gtk_tree_model_get (model, &iter, LEVEL_COLUMN, &rule_value, -1);
- }else if(!strlen(rule_value)) {
- level_name=g_string_new(rule_value);
- level=ignorance_get_level_name(level_name);
- rule_name=g_string_new(gtk_entry_get_text(GTK_ENTRY(rulename)));
- rule=ignorance_level_get_rule(level,rule_name);
- fprintf(stderr,"Ignorance: Rule \"%s\" not found on level %s\n",rule_name->str,level_name->str);
- g_string_free(rule_name,TRUE);
- g_string_free(level_name,TRUE);
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(regex_cb))) {
- rule_type=IGNORANCE_RULE_REGEX;
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(repeat_cb))) {
- rule_type=IGNORANCE_RULE_REPEAT;
- rule_value=(gchar*)gtk_entry_get_text(GTK_ENTRY(filtervalue));
- rule->value=g_strdup(rule_value);
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(im_type_cb))) {
- rule_flags |= IGNORANCE_APPLY_IM;
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(chat_type_cb))) {
- rule_flags |= IGNORANCE_APPLY_CHAT;
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(username_type_cb))) {
- rule_flags |= IGNORANCE_APPLY_USER;
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enterleave_type_cb))) {
- rule_flags |= IGNORANCE_APPLY_ENTERLEAVE;
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(invite_type_cb))) {
- rule_flags |= IGNORANCE_APPLY_INVITE;
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(filter_cb))) {
- rule_score |= IGNORANCE_FLAG_FILTER;
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ignore_cb))) {
- rule_score |= IGNORANCE_FLAG_IGNORE;
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(message_cb))) {
- rule_score |= IGNORANCE_FLAG_MESSAGE;
- rule_message=(gchar*)gtk_entry_get_text(GTK_ENTRY(message_entry));
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sound_cb))) {
- rule_score |= IGNORANCE_FLAG_SOUND;
- rule_sound=(gchar*)gtk_entry_get_text(GTK_ENTRY(sound_entry));
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(execute_cb))) {
- rule_score |= IGNORANCE_FLAG_EXECUTE;
- rule_command=(gchar*)gtk_entry_get_text(GTK_ENTRY(execute_entry));
- rule_enable=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enabled_cb));
- rule=ignorance_rule_newp(rule_name, rule_type, rule_value, rule_score,
- rule_flags,rule_enable,rule_message,rule_sound,
- rv=ignorance_level_remove_rule(level,rule_name);
- rv=ignorance_level_add_rule(level,rule);
- rule->flags=rule_flags;
- rule->enabled=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enabled_cb));
- g_string_free(rule_name,TRUE);
- g_string_free(level_name,TRUE);
-static gboolean del_rule_from_form(GtkTreeView *view) {
- ignorance_level *level;
- GString *rule_name, *level_name;
- sel=gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
- if (!gtk_tree_selection_get_selected (sel, &model, &iter)) {
- gtk_tree_model_get (model, &iter, LEVEL_COLUMN, &rule_value, -1);
- }else if(!strlen(rule_value)) {
- level_name=g_string_new(rule_value);
- level=ignorance_get_level_name(level_name);
- rule_name=g_string_new(gtk_entry_get_text(GTK_ENTRY(rulename)));
- rule=ignorance_level_get_rule(level,rule_name);
- fprintf(stderr,"Ignorance: Rule \"%s\" not found on level %s\n",
- rule_name->str,level_name->str);
- g_string_free(rule_name,TRUE);
- g_string_free(level_name,TRUE);
- rv=ignorance_level_remove_rule(level,rule_name);
- gtk_tree_store_remove(GTK_TREE_STORE(model),&iter);
- g_string_free(rule_name,TRUE);
- g_string_free(level_name,TRUE);
-static gboolean del_group_from_form(GtkTreeView *view) {
- sel=gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
- if (!gtk_tree_selection_get_selected (sel, &model, &iter)) {
- gtk_tree_model_get (model, &iter, LEVEL_COLUMN, &rule_value, -1);
- }else if(!strlen(rule_value)) {
- level_name=g_string_new(rule_value);
- ignorance_remove_level(level_name);
- gtk_tree_store_remove(GTK_TREE_STORE(model),&iter);
-gboolean load_form_with_levels(GtkTreeView *tree, GPtrArray *levels) {
- GtkTreeStore *store=GTK_TREE_STORE(gtk_tree_view_get_model(tree));
- GtkTreeIter iter, ruleiter;
- ignorance_level *level;
- for(i=0;i<levels->len;++i) {
- level=(ignorance_level*)g_ptr_array_index(levels,i);
- gtk_tree_store_append(store,&iter,NULL);
- gtk_tree_store_set (store, &iter, LEVEL_COLUMN, level->name->str,
- for(j=0;j<level->rules->len;++j) {
- rule=(ignorance_rule*)g_ptr_array_index(level->rules,j);
- gtk_tree_store_append(store,&ruleiter,&iter);
- gtk_tree_store_set(store,&ruleiter, LEVEL_COLUMN, level->name->str,
- RULE_COLUMN, rule->name->str, -1);
-static gboolean ignorance_rule_valid(const gchar *ruletext, gint ruletype) {
- case IGNORANCE_RULE_SIMPLETEXT:
- case IGNORANCE_RULE_REPEAT:
- case IGNORANCE_RULE_REGEX:
- rv=!((gboolean)regcomp(®,ruletext,REG_EXTENDED | REG_NOSUB));
- rv=(rv && strlen(ruletext));
-static gboolean ignorance_rulename_valid(const gchar *rule_name) {
--- a/ignorance/callbacks.h Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
-#ifndef IGNORANCE_CALLBACKS_H
-#define IGNORANCE_CALLBACKS_H
-gboolean on_levelView_row_activated (GtkTreeSelection *sel, gpointer user_data);
-void on_levelAdd_clicked (GtkButton *button, gpointer user_data);
-void on_groupAdd_clicked (GtkButton *button, gpointer user_data);
-void on_levelEdit_clicked (GtkButton *button, gpointer user_data);
-void on_levelDel_clicked (GtkButton *button, gpointer user_data);
-void on_sound_browse_clicked (GtkButton *button, gpointer user_data);
-void on_execute_browse_clicked (GtkButton *button, gpointer user_data);
-void on_filter_cb_toggled (GtkButton *button, gpointer user_data);
-void on_ignore_cb_toggled (GtkButton *button, gpointer user_data);
-void on_message_cb_toggled (GtkButton *button, gpointer user_data);
-void on_sound_cb_toggled (GtkButton *button, gpointer user_data);
-void on_execute_cb_toggled (GtkButton *button, gpointer user_data);
-gboolean load_form_with_levels (GtkTreeView *tree, GPtrArray *levels);
--- a/ignorance/ignorance.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1209 +0,0 @@
- * Ignorance - Make up for deficiencies in Purple's privacy
- * Copyright (c) 200?-2006 Levi Bard
- * Copyright (c) 2005-2006 Peter Lawler
- * Copyright (c) 2005-2006 John Bailey
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
-#include "ignorance_level.h"
-#include "ignorance_internal.h"
-#include "ignorance_denizen.h"
-#include "ignorance_violation.h"
-#include "ignorance_rule.h"
-/* GTK Purple headers */
-#include <conversation.h>
-/* for OSes that can at least *pretend* to be decent... */
-# include <sys/select.h>
-static GPtrArray *levels;
-static ignorance_level* ignorance_get_default_level() {
- for(i = 0; i < levels->len; ++i) {
- il = (ignorance_level*)g_ptr_array_index(levels, i);
- if(!strcmp(il->name->str, "Default"))
-static gboolean ignorance_user_match(ignorance_level *il, const GString *username){
- return (ignorance_level_has_denizen(il,username));
-static ignorance_level* ignorance_get_user_level(const GString *username){
- ignorance_level *il = NULL;
- for(i = 0; i < levels->len; ++i){
- il = (ignorance_level*)g_ptr_array_index(levels, i);
- if(ignorance_user_match(il, username))
- return ignorance_get_default_level();
-static void purple_buddy_add(gpointer key, gpointer value, gpointer user_data) {
- PurpleBuddy *buddy = (PurpleBuddy*)value;
- ignorance_level *level = (ignorance_level*)user_data;
- PurpleAccount *account = NULL;
- name = (gchar*)buddy->name;
- account = buddy->account;
- tmp = g_string_new(purple_account_get_protocol_id(account));
- g_string_append(tmp, purple_normalize_nocase(account, name));
- if(ignorance_get_user_level(tmp) == ignorance_get_default_level()) {
- ignorance_level_add_denizen(level, tmp);
- if(strstr(level->name->str, "WL")) {
- purple_privacy_deny_remove(account, name, FALSE);
- purple_privacy_permit_add(account, name, FALSE);
- } else if(strstr(level->name->str,"BL")) {
- purple_privacy_permit_remove(account, name, FALSE);
- purple_privacy_deny_add(account, name, FALSE);
- g_string_free(tmp, TRUE);
- purple_debug_error("ignorance", "Bad arguments to purple_buddy_add\n");
-static gint buf_get_line(gchar *ibuf, gchar **buf, gint *position, gint len) {
- while (ibuf[pos++] != '\n') {
-static gboolean import_curphoo_list() {
- rule_flags = IGNORANCE_APPLY_CHAT | IGNORANCE_APPLY_IM | IGNORANCE_APPLY_ENTERLEAVE;
- ignorance_level *curphoolevel = NULL;
- ignorance_rule *curphoorule = NULL;
- buf = g_build_filename(g_get_home_dir(), ".curphoo", "ignore", NULL);
- if(!(curphoofile = fopen(buf, "r"))) {
- purple_debug_error("ignorance", "Unable to open %s\n", buf);
- g_file_get_contents(buf, &ibuf, &size, NULL);
- tmp = g_string_new("CurphooBL");
- curphoolevel = ignorance_get_level_name(tmp);
- purple_debug_info("ignorance", "Creating new Curphoo blacklist\n");
- curphoorule = ignorance_rule_newp(g_string_new("Everything"),
- IGNORANCE_RULE_REGEX,(gchar*)".*", IGNORANCE_FLAG_FILTER,
- rule_flags, TRUE, NULL, NULL, NULL);
- curphoorule=ignorance_rule_newp(g_string_new("Everything"),
- IGNORANCE_RULE_SIMPLETEXT, (gchar*)"", IGNORANCE_FLAG_FILTER,
- rule_flags, TRUE, NULL, NULL, NULL);
- curphoolevel = ignorance_level_new();
- curphoolevel->name = g_string_new(tmp->str);
- ignorance_level_add_rule(curphoolevel, curphoorule);
- ignorance_add_level(curphoolevel);
- tmp = g_string_new("");
- purple_debug_info("ignorance", "Preparing to read in curphoo blacklist users\n");
- for(; buf_get_line(ibuf, &buf, &pnt, size); ){
- g_string_assign(tmp, "prpl-yahoo");
- g_string_append(tmp, purple_normalize_nocase(NULL,buf));
- if(ignorance_get_user_level(tmp) == ignorance_get_default_level())
- ignorance_level_add_denizen(curphoolevel, tmp);
- buf = g_build_filename(g_get_home_dir(), ".curphoo", "buddies", NULL);
- g_file_get_contents(buf, &ibuf, &size, NULL);
- g_string_assign(tmp, "CurphooWL");
- curphoolevel = ignorance_get_level_name(tmp);
- purple_debug_info("ignorance", "Creating new Curphoo whitelist\n");
- curphoolevel = ignorance_level_new();
- curphoolevel->name = g_string_new(tmp->str);
- ignorance_add_level(curphoolevel);
- purple_debug_info("ignorance", "Preparing to read in curphoo whitelist users\n");
- for(; buf_get_line(ibuf, &buf, &pnt, size); ) {
- g_string_assign(tmp, "prpl-yahoo");
- g_string_append(tmp, purple_normalize_nocase(NULL, buf));
- if(ignorance_get_user_level(tmp) == ignorance_get_default_level())
- ignorance_level_add_denizen(curphoolevel, tmp);
- purple_debug_info("ignorance", "Done importing Curphoo users\n");
-static gboolean import_purple_list() {
- bl = purple_get_blist();
- wlname = g_string_new("WL");
- wl = ignorance_get_level_name(wlname);
- g_hash_table_foreach(bl->buddies, purple_buddy_add, wl);
- purple_debug_error("ignorance", "Unable to get Purple buddy list!\n");
- g_string_free(wlname, TRUE);
-static gboolean import_zinc_list()
- rule_flags = IGNORANCE_APPLY_CHAT | IGNORANCE_APPLY_IM | IGNORANCE_APPLY_ENTERLEAVE;
- ignorance_level *zinclevel = NULL;
- ignorance_rule *zincrule = NULL;
- buf = g_build_filename(g_get_home_dir(), ".zinc", "ignore", NULL);
- if(!(zincfile = fopen(buf, "r"))) {
- purple_debug_error("ignorance", "Unable to open %s\n",buf);
- g_file_get_contents(buf, &ibuf, &size, NULL);
- tmp = g_string_new("ZincBL");
- zinclevel = ignorance_get_level_name(tmp);
- purple_debug_info("ignorance", "Creating new Zinc blacklist\n");
- zincrule = ignorance_rule_newp(g_string_new("Everything"),
- IGNORANCE_RULE_REGEX, (gchar*)".*", IGNORANCE_FLAG_FILTER,
- rule_flags, TRUE, NULL, NULL, NULL);
- zincrule = ignorance_rule_newp(g_string_new("Everything"),
- IGNORANCE_RULE_SIMPLETEXT, (gchar*)"", IGNORANCE_FLAG_FILTER,
- rule_flags, TRUE, NULL, NULL, NULL);
- zinclevel = ignorance_level_new();
- zinclevel->name = g_string_new(tmp->str);
- ignorance_level_add_rule(zinclevel, zincrule);
- ignorance_add_level(zinclevel);
- purple_debug_info("ignorance", "Preparing to read in zinc blacklist users\n");
- for(; buf_get_line(ibuf, &buf, &pnt, size); ) {
- g_string_assign(tmp, "prpl-yahoo");
- g_string_append(tmp, purple_normalize_nocase(NULL, buf));
- if(ignorance_get_user_level(tmp) == ignorance_get_default_level())
- ignorance_level_add_denizen(zinclevel, tmp);
- buf = g_build_filename(g_get_home_dir(), ".zinc", "whitelist", NULL);
- g_file_get_contents(buf, &ibuf, &size, NULL);
- g_string_assign(tmp, "ZincWL");
- zinclevel = ignorance_get_level_name(tmp);
- purple_debug_info("ignorance", "Creating new Zinc whitelist\n");
- zinclevel = ignorance_level_new();
- zinclevel->name = g_string_new(tmp->str);
- ignorance_add_level(zinclevel);
- purple_debug_info("ignorance", "Preparing to read in zinc whitelist users\n");
- for(; buf_get_line(ibuf, &buf, &pnt, size); ) {
- /* maybe this will be this way eventually, when i kill unnecessary
- * GStrings - rekkanoryo */
- /* tmp = g_strdup_printf("prpl-yahoo %s", purple_normalize_nocase(NULL, buf)); */
- g_string_assign(tmp, "prpl-yahoo");
- g_string_append(tmp, purple_normalize_nocase(NULL, buf));
- if(ignorance_get_user_level(tmp) == ignorance_get_default_level())
- ignorance_level_add_denizen(zinclevel, tmp);
- purple_debug_info("ignorance", "Done importing Zinc users\n");
-static gboolean ignorance_rm_user(PurpleConversation *conv, const gchar *username) {
- gchar *msgbuf = NULL, *cursor = NULL;
- gboolean retval = FALSE;
- ignorance_level *level = NULL;
- usergs = g_string_new(purple_normalize_nocase(NULL, username));
- level=ignorance_get_user_level(usergs);
- retval = ignorance_level_remove_denizen(level, usergs);
- purple_debug_info("ignorance", "Done removing denizen from level\n");
- purple_debug_info("ignorance",
- "Creating status message for username %x and level %x\n",
- msgbuf = g_strdup_printf(_("Successfully removed %s from %s"),
- username, level->name->str);
- msgbuf = g_strdup_printf(_("Unable to remove %s from %s\n"),
- username, level->name->str);
- purple_debug_info("ignorance", "Writing status message\n");
- purple_conversation_write(conv, NULL, msgbuf, PURPLE_MESSAGE_NO_LOG,
- purple_debug_info("ignorance",
- "Preparing to push through to purple privacy\n");
- len = strlen(purple_account_get_protocol_id(
- purple_conversation_get_account(conv)));
- cursor = (gchar*)username + len;
- if(cursor && (strlen(username) > len)) {
- purple_debug_info("ignorance", "Removing from permit list\n");
- purple_privacy_permit_remove(purple_conversation_get_account(conv),
- purple_debug_info("ignorance", "Removing from deny list\n");
- purple_privacy_deny_remove(purple_conversation_get_account(conv), cursor,
- if(purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
- purple_debug_info("ignorance", "Removing from chat ignore list\n");
- purple_conv_chat_unignore(PURPLE_CONV_CHAT(conv), cursor);
- g_string_free(usergs, TRUE);
- purple_debug_info("ignorance", "Exiting\n");
-ignorance_place_user_name(const GString *level_name, const GString *username) {
- ignorance_level *current_level = ignorance_get_user_level(username),
- *newlevel = ignorance_get_level_name(level_name);
- if(newlevel != current_level) {
- ignorance_level_remove_denizen(current_level, username);
- ignorance_level_add_denizen(newlevel, username);
- purple_debug_error("ignorance", "Invalid level %s\n", level_name->str);
-static gboolean ignorance_bl_user(PurpleConversation *conv, const gchar *username,
- const gchar *actual_levelname)
- gboolean retval = FALSE;
- GString *wlname, *usergs;
- PurpleAccount *account = NULL;
- wlname = g_string_new(actual_levelname);
- g_return_val_if_fail(conv != NULL, retval);
- account = purple_conversation_get_account(conv);
- usergs = g_string_new(purple_account_get_protocol_id(account));
- g_string_append(usergs, purple_normalize_nocase(NULL, username));
- if(ignorance_place_user_name(wlname, usergs)){
- purple_privacy_permit_remove(account, username, FALSE);
- purple_privacy_deny_add(account, username, FALSE);
- if(purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT)
- purple_conv_chat_ignore(PURPLE_CONV_CHAT(conv), username);
- msgbuf = g_strdup_printf(_("Assigned user %s to %s"), username,
- msgbuf = g_strdup_printf(
- _("Unable to assign user %s to %s - may already be there"),
- username, actual_levelname);
- purple_conversation_write(conv, NULL, msgbuf, PURPLE_MESSAGE_NO_LOG, time(NULL));
- g_string_free(usergs, TRUE);
- g_string_free(wlname, TRUE);
-static int read_nonblock(int fd,unsigned long len,unsigned long timeout,GString *inp){
- int chrs=0, timedout=FALSE, rv=0;
- unsigned long timeout_usec=timeout*1000000, tlapsed=0;
- static const int SLEEP_INTERVAL=50000;
- gchar *ptr=g_malloc((len+1)*sizeof(gchar));
- if (tlapsed > timeout_usec){
- if ((rv = read (fd, ptr, (len - chrs))) < 0){
- usleep (SLEEP_INTERVAL);
- tlapsed += SLEEP_INTERVAL;
- g_string_append(inp,ptr);
-yahoo_strip_tattoo(gchar *origmessage) {
- gchar *cursor = NULL, *cursor2 = NULL, *beginstack = NULL,
- *endstack = NULL, *message = NULL;
- message = g_ascii_strdown(origmessage, -1);
- cursor = strstr(message, "<font");
- if(message == cursor) {
- cursor2 = strstr(message, "tattoo");
- cursor = strstr(cursor2, ">");
- endstack = strstr(cursor, "</");
- beginstack = strstr(cursor, "<");
- if(endstack == NULL || beginstack== NULL) {
- cursor = strstr(endstack, ">");
- if(beginstack == endstack)
- rvindex = cursor + 1 - message;
- purple_debug_info("yahoo", "%s\nconverted to \n%s\n%s\n\n",
- origmessage, cursor + 1, origmessage + rvindex);
- return origmessage + rvindex;
-handle_exec_command (const gchar *command, GString *result,unsigned long maxlen) {
- GString *inp=g_string_new("");
- if ((pid = fork ()) == -1) {
- g_string_assign (result, command);
- g_string_append (result, ": couldn't fork");
- int flags = fcntl (p[0], F_GETFL, 0);
- fcntl (p[0], F_SETFL, flags | O_NONBLOCK);
- rv=read_nonblock(p[0],maxlen-chrs,EXEC_TIMEOUT,inp);
- if (kill (pid, 0) == 0)
- g_string_append (inp, "[process timed out]");
- else if(maxlen==(rv+chrs))
- g_string_append(inp,"...");
- else if(('\n'==(inp->str)[inp->len-1]))
- g_string_truncate(inp,inp->len-1);
- g_string_assign (result, inp->str);
- g_string_free(inp,TRUE);
- waitpid (pid, NULL, 0);
- if (p[1] != STDOUT_FILENO){
- dup2 (p[1], STDOUT_FILENO);
- if (STDERR_FILENO != STDOUT_FILENO)
- dup2 (STDOUT_FILENO, STDERR_FILENO);
- execlp ("sh", "sh", "-c", command, NULL);
- g_string_assign (result, command);
- g_string_append (result, ": ");
- if (G_WIN32_HAVE_WIDECHAR_API ()) {
- wchar_t *wc_cmd = g_utf8_to_utf16(command,
- retval = (gint)ShellExecuteW(NULL,NULL,wc_cmd,NULL,NULL,SW_SHOWNORMAL);
- char *l_cmd = g_locale_from_utf8(command,
- retval = (gint)ShellExecuteA(NULL,NULL,l_cmd,NULL,NULL,SW_SHOWNORMAL);
- message = g_win32_error_message(retval);
- g_string_append(result,message);
- purple_debug_info("Ignorance", "Execute command called for: "
- "%s\n%s%s%s", command, retval ? "" : "Error: ",
- retval ? "" : message, retval ? "" : "\n");
-apply_rule(PurpleConversation *conv, PurpleAccount *account,
- const GString *username, const GString *text, gint flags)
- gboolean rv = TRUE, newconv = FALSE;
- GList *violations = NULL, *cursor = NULL;
- GString *prpluser = g_string_new(purple_account_get_protocol_id(account));
- ignorance_level *user_level;
- ignorance_violation *viol;
- PurpleConversationType conv_type;
- g_string_append(prpluser, purple_normalize_nocase(account, username->str));
- user_level=ignorance_get_user_level(prpluser);
- purple_debug_info("ignorance", "Preparing to check %s\n", text->str);
- text_score=ignorance_level_rulecheck(user_level, prpluser, text, flags,
- purple_debug_info("ignorance", "Got score %d\n", text_score);
- if(!(text_score & (IGNORANCE_FLAG_FILTER | IGNORANCE_FLAG_IGNORE))) {
- for(cursor = violations; cursor; cursor = cursor->next) {
- viol = (ignorance_violation*)(cursor->data);
- purple_debug_info("ignorance", "Got violation type %d: %s\n",
- viol->type,viol->value);
- case IGNORANCE_FLAG_SOUND:
- purple_debug_info("ignorance",
- "Attempting to play sound %s\n", viol->value);
- purple_sound_play_file(viol->value, account);
- case IGNORANCE_FLAG_EXECUTE:
- purple_debug_info("ignorance",
- "Attempting to execute command %s\n",
- tmp = g_string_new("");
- handle_exec_command(viol->value, tmp, 512);
- purple_conversation_write(conv,
- purple_account_get_username(account),
- tmp->str, PURPLE_MESSAGE_NO_LOG, time(NULL));
- g_string_free(tmp, TRUE);
- case IGNORANCE_FLAG_MESSAGE:
- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM,
- account, username->str);
- conv_type = purple_conversation_get_type(conv);
- if(conv_type == PURPLE_CONV_TYPE_IM) {
- purple_conv_im_send(PURPLE_CONV_IM(conv), viol->value);
- } else if(conv_type == PURPLE_CONV_TYPE_CHAT) {
- purple_conv_chat_send(PURPLE_CONV_CHAT(conv),
- } /* braces for readability only */
- purple_conversation_destroy(conv);
- } else if(text_score & IGNORANCE_FLAG_IGNORE)
- ignorance_bl_user(conv, username->str, "BL");
- g_string_free(prpluser, TRUE);
- purple_debug_info("ignorance", "Preparing to free violation items\n");
- g_list_foreach(violations, ignorance_violation_free_g, NULL);
- purple_debug_info("ignorance",
- "Done freeing violation items, now freeing list itself\n");
- g_list_free(violations);
- purple_debug_info("ignorance",
- "Done checking, returning from applying rules\n");
-static gboolean substitute (PurpleConversation *conv,PurpleAccount *account,
- const gchar *sender, gchar **message, gint msgflags) {
- GString *username=NULL, *text=NULL;
- gchar *newmsg, *cursor;
- else if (NULL == (*message))
- username=g_string_new(purple_normalize_nocase(account,sender));
- purple_debug_info("ignorance","Got message \"%s\" from user \"%s\"\n",*message,sender);
- cursor=yahoo_strip_tattoo(*message);
- newmsg=g_strdup(cursor);
- text=g_string_new(*message);
- rv=apply_rule(conv,account,username,text,msgflags);
- purple_debug_info("ignorance", "%s: %s violated!\n",username->str,text->str);
- g_string_free(username,TRUE);
- g_string_free(text,TRUE);
- purple_debug_info("ignorance","Returning from substitution\n");
-static gboolean chat_cb(PurpleAccount *account, gchar **sender, gchar **buffer,
- PurpleConversation *chat, void *data){
- return substitute(chat, account, *sender, buffer,
- IGNORANCE_APPLY_CHAT | IGNORANCE_APPLY_USER);
-static gboolean im_cb(PurpleAccount *account, gchar **sender, gchar **buffer,
- gint *flags, void *data){
- PurpleConversation *gc;
- gc=purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,*sender,account);
- return substitute(gc, account, *sender,buffer,
- IGNORANCE_APPLY_IM | IGNORANCE_APPLY_USER);
-static gboolean chat_joinleave_cb (PurpleConversation *conv, const gchar *name,
- gchar *message=g_strdup(name);
- gboolean rv=substitute(conv, purple_conversation_get_account(conv), name,
- &message,IGNORANCE_APPLY_ENTERLEAVE | IGNORANCE_APPLY_USER);
-static gint chat_invited_cb(PurpleAccount *account,const gchar *inviter, const gchar *chat, const gchar *invite_message, const GHashTable *components, void *data){
- gchar *message=g_strdup(invite_message);
- PurpleConversation *gc;
- gc=purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,inviter,account);
- rv=substitute(gc,account,inviter,&message,IGNORANCE_APPLY_INVITE | IGNORANCE_APPLY_USER | IGNORANCE_APPLY_CHAT);
-static void buddy_added_cb(PurpleBuddy *buddy, gpointer data){
- GString *wlname=g_string_new("WL");
- ignorance_level *wl=ignorance_get_level_name(wlname);
- PurpleAccount *account=buddy->account;
- gchar *name=(gchar*)buddy->name;
- purple_debug_info("ignorance","Caught buddy-added for %s%s\n",
- purple_account_get_protocol_id(account), name);
- purple_buddy_add(NULL,buddy,wl);
- g_string_free(wlname,TRUE);
-static void buddy_removed_cb(PurpleBuddy *buddy, gpointer data){
- PurpleConversation *conv=NULL;
- PurpleAccount *account=buddy->account;
- gchar *name=(gchar*)buddy->name;
- tmp=g_string_new(purple_account_get_protocol_id(account));
- conv=purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,tmp->str,account);
- purple_debug_info("ignorance","Caught buddy-removed for %s%s\n",
- purple_account_get_protocol_id(account), name);
- g_string_append(tmp,purple_normalize_nocase(account,name));
- ignorance_rm_user(conv,tmp->str);
- g_string_free(tmp,TRUE);
-static gboolean generate_default_levels() {
- ignorance_level *tmplvl;
- ignorance_rule *tmprule;
- tmplvl=ignorance_level_new();
- tmplvl->name=g_string_new("Default");
- ignorance_add_level(tmplvl);
- tmplvl=ignorance_level_new();
- tmplvl->name=g_string_new("WL");
- ignorance_add_level(tmplvl);
- tmplvl=ignorance_level_new();
- tmplvl->name=g_string_new("BL");
- ignorance_add_level(tmplvl);
- tmpgs=g_string_new("Everything");
- tmprule=ignorance_rule_newp(tmpgs,IGNORANCE_RULE_REGEX,".*",
- IGNORANCE_APPLY_CHAT | IGNORANCE_APPLY_IM,
- tmprule=ignorance_rule_newp(tmpgs,IGNORANCE_RULE_SIMPLETEXT,"",
- IGNORANCE_APPLY_CHAT | IGNORANCE_APPLY_IM,
- ignorance_level_add_rule(tmplvl,tmprule);
- g_string_free(tmpgs,TRUE);
- gchar *name, tempfilename[BUF_LONG];
- name = g_build_filename(purple_user_dir(), "ignorance", NULL);
- strcpy(tempfilename, name);
- strcat(tempfilename,".XXXXXX");
- fd = g_mkstemp(tempfilename);
- if (!(f = fdopen(fd, "w"))) {
- fchmod(fd, S_IRUSR | S_IWUSR);
- for(i=0;i<levels->len;++i){
- ignorance_level_write(g_ptr_array_index(levels,i),f);
- purple_debug_error("ignorance",
- "Error writing to %s: %m\n", tempfilename);
- rename(tempfilename, name);
-ignorance_level* ignorance_get_level_name(const GString *levelname){
- ignorance_level *il=NULL;
- for(i=0;i<levels->len;++i){
- il=(ignorance_level*)g_ptr_array_index(levels,i);
- if(g_string_equal(levelname,il->name))
-gboolean ignorance_add_level(ignorance_level *level){
- g_ptr_array_add(levels,level);
-gboolean ignorance_remove_level(const GString *levelname){
- ignorance_level *level=ignorance_get_level_name(levelname);
- rv=g_ptr_array_remove(levels,level);
- ignorance_level_free(level);
-ignorance_signals_connect(PurplePlugin *plugin)
- void *conv_handle, *blist_handle;
- conv_handle = purple_conversations_get_handle();
- blist_handle = purple_blist_get_handle();
- purple_signal_connect(conv_handle, "receiving-im-msg", plugin,
- PURPLE_CALLBACK (im_cb), NULL);
- purple_signal_connect(conv_handle, "receiving-chat-msg", plugin,
- PURPLE_CALLBACK (chat_cb), NULL);
- purple_signal_connect(conv_handle,"chat-buddy-joining", plugin,
- PURPLE_CALLBACK(chat_joinleave_cb),NULL);
- purple_signal_connect(conv_handle,"chat-buddy-leaving", plugin,
- PURPLE_CALLBACK(chat_joinleave_cb),NULL);
- purple_signal_connect(conv_handle,"chat-invited", plugin,
- PURPLE_CALLBACK(chat_invited_cb),NULL);
- purple_signal_connect(blist_handle,"buddy-added", plugin,
- PURPLE_CALLBACK(buddy_added_cb),NULL);
- purple_signal_connect(blist_handle,"buddy-removed", plugin,
- PURPLE_CALLBACK(buddy_removed_cb),NULL);
-static gboolean load_conf() {
- static ignorance_level *tmplvl = NULL;
- static ignorance_rule *tmprule = NULL;
- buf = g_build_filename(purple_user_dir(), "ignorance", NULL);
- purple_debug_info("ignorance", "Attempting to load conf file %s\n",buf);
- levels = g_ptr_array_new();
- if(!(conffile = fopen(buf, "r"))) {
- buf=g_build_filename(IGNORANCE_CONFDIR,"ignorance.conf",NULL);
- if(!(conffile = fopen(buf,"r"))) {
- purple_debug_info("ignorance",
- "Unable to open local or global conf files; falling back to defaults\n");
- generate_default_levels();
- g_file_get_contents(buf, &ibuf, &size, NULL);
- generate_default_levels();
- while(buf_get_line(ibuf, &buf, &pnt, size)) {
- } else if(strstr(buf, "level")){
- tmpgs = g_string_new("");
- for( ; buf != strstr(buf, "/level");
- buf_get_line(ibuf, &buf, &pnt, size))
- g_string_append(tmpgs, buf);
- g_string_append(tmpgs, "\n");
- tmplvl = ignorance_level_read(tmpgs->str);
- g_string_free(tmpgs, TRUE);
- tmplvl=ignorance_level_read(buf);
- purple_debug_info("ignorance", "Adding level %s\n",
- ignorance_add_level(tmplvl);
- } else if(strstr(buf, "rule") && tmplvl) {
- tmpgs = g_string_new("");
- for( ; buf != strstr(buf, "/rule");
- buf_get_line(ibuf, &buf, &pnt, size))
- g_string_append(tmpgs, buf);
- g_string_append(tmpgs, "\n");
- purple_debug_info("ignorance", "Attempting to read rule %s\n",
- tmprule = ignorance_rule_read(tmpgs->str);
- g_string_free(tmpgs, TRUE);
- tmprule = ignorance_rule_read(buf);
- purple_debug_info("ignorance", "Adding rule %s: %s\n",
- tmprule->name->str, (gchar*)(tmprule->value));
- ignorance_level_add_rule(tmplvl, tmprule);
- tmpgs = g_string_new(purple_normalize_nocase(NULL, buf));
- purple_debug_info("ignorance", "Adding denizen %s\n", buf);
- if(ignorance_get_user_level(tmpgs) == ignorance_get_default_level())
- ignorance_level_add_denizen(tmplvl, tmpgs);
- g_string_free(tmpgs,TRUE);
-ignorance_load (PurplePlugin *plugin) {
- purple_debug_info("ignorance", "Loading ignorance plugin");
- ignorance_signals_connect(plugin);
-plugin_unload(PurplePlugin *plugin) {
- purple_debug_info("ignorance", "Unloading ignorance plugin\n");
-static GtkWidget *get_config_frame(PurplePlugin *plugin) {
- return create_uiinfo(levels);
-static PidginPluginUiInfo ui_info = {
-static PurplePluginInfo ig_info = {
- PURPLE_PLUGIN_STANDARD,
- PURPLE_PRIORITY_DEFAULT,
- "Peter Lawler <bleeter from users.sf.net>, "
- "Levi Bard <taktaktaktaktaktaktaktaktaktak@gmail.com> (original author)",
- "http://guifications.sourceforge.net",
-ignorance_init (PurplePlugin * plugin)
- bindtextdomain(GETTEXT_PACKAGE, PP_LOCALEDIR);
- bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
- ig_info.name = _("Ignorance");
- _("Allows you to manage lists of users with various levels of allowable activity.");
- _("Allows you to manage lists of users with various levels of allowable activity.");
-PURPLE_INIT_PLUGIN (ignorance, ignorance_init, ig_info)
--- a/ignorance/ignorance.conf Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-level index="100" name="Default" upper_threshhold="10" lower_threshhold="-10" allow_passthrough="0"
-rule name="link" type="1" score="1" value="http://" flags="3" enabled="0"
-rule name="PM" type="2" score="1" value="." flags="2" enabled="1"
-rule name="playing" type="2" score="1" value="[Pp]laying" flags="3" enabled="0"
-rule name="enterleave" type="2" score="1" value="." flags="16" enabled="1"
-rule name="invite" type="2" score="1" value="." flags="32" enabled="1"
-rule name="profilebot" type="1" score="1" value="profile" flags="4" enabled="1"
-level index="1" name="WL" upper_threshhold="10" lower_threshhold="-10" allow_passthrough="0"
-level index="80" name="PM" upper_threshhold="10" lower_threshhold="-10" allow_passthrough="0"
-rule name="enterleave" type="2" score="1" value="." flags="16" enabled="1"
-level index="90" name="Link" upper_threshhold="10" lower_threshhold="-10" allow_passthrough="0"
-rule name="PM" type="2" score="1" value="." flags="2" enabled="1"
-rule name="enterleave" type="2" score="1" value="." flags="16" enabled="1"
-rule name="playing" type="2" score="1" value="[Pp]laying" flags="3" enabled="0"
-rule name="invite" type="2" score="1" value="." flags="32" enabled="1"
-level index="1001" name="BL" upper_threshhold="10" lower_threshhold="-10" allow_passthrough="0"
-rule name="everything" type="2" score="1" value="." flags="55" enabled="1"
-level index="999" name="ZincBL" upper_threshhold="9" lower_threshhold="-9" allow_passthrough="0"
-rule name="Everything" type="2" score="1" value="." flags="3" enabled="1"
-level index="2" name="ZincWL" upper_threshhold="9" lower_threshhold="-9" allow_passthrough="0"
--- a/ignorance/ignorance.h Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
-# include "../pp_config.h"
-#include "../common/pp_internal.h"
-#include "ignorance_level.h"
-#define IGNORANCE_APPLY_CHAT 1
-#define IGNORANCE_APPLY_IM 2
-#define IGNORANCE_APPLY_USER 4
-#define IGNORANCE_APPLY_HOST 8
-#define IGNORANCE_APPLY_ENTERLEAVE 16
-#define IGNORANCE_APPLY_INVITE 32
-ignorance_level* ignorance_get_level_name(const GString *levelname);
-gboolean ignorance_add_level(ignorance_level *level);
-gboolean ignorance_remove_level(const GString *levelname);
-gint ignorance_get_new_level_index();
--- a/ignorance/ignorance_denizen.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
-#include "ignorance_denizen.h"
-#include "ignorance_internal.h"
-ignorance_denizen* ignorance_denizen_new(const gchar *newname) {
- ignorance_denizen *id=(ignorance_denizen*)g_malloc(sizeof(ignorance_denizen));
- id->name=g_strdup(newname);
- id->last_message=g_strdup("");
-void ignorance_denizen_free(ignorance_denizen *id) {
- g_free(id->last_message);
-gchar *ignorance_denizen_get_name(ignorance_denizen *id) {
-gchar *ignorance_denizen_get_last_message(ignorance_denizen *id) {
- return id->last_message;
-gint ignorance_denizen_get_repeats(ignorance_denizen *id) {
-gint ignorance_denizen_set_message(ignorance_denizen *id, const gchar *message) {
- if(!strcasecmp(id->last_message,message)){
- purple_debug_info("ignorance","Got repeat %d for message %s\n",
- id->repeats+1,message);
- purple_debug_info("ignorance","New message %s replacing old message %s",
- message,id->last_message);
- g_free(id->last_message);
- id->last_message=g_strdup(message);
--- a/ignorance/ignorance_denizen.h Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
-#ifndef IGNORANCE_DENIZEN_H
-#define IGNORANCE_DENIZEN_H
-typedef struct ignorance_denizen{
-ignorance_denizen* ignorance_denizen_new(const gchar *newname);
-void ignorance_denizen_free(ignorance_denizen *denizen);
-gchar* ignorance_denizen_get_name(ignorance_denizen *id);
-gchar* ignorance_denizen_get_last_message(ignorance_denizen *id);
-gint ignorance_denizen_get_repeats(ignorance_denizen *id);
-gint ignorance_denizen_set_message(ignorance_denizen *id, const gchar *message);
--- a/ignorance/ignorance_internal.h Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
- * Guifications - The end all, be all, toaster popup plugin
- * Copyright (C) 2003-2005 Gary Kramlich
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
-#define IGNORANCE_PLUGIN_ID "gtk-bleeter-ignorance"
-#define SHORTDESC "Ignorance filter"
-#ifndef IGNORANCE_CONFDIR
-# define IGNORANCE_CONFDIR purple_user_dir()
-#define GREATER(x,y) ((x)?((x)>(y)):(y))
-#if ((PURPLE_MAJOR_VERSION) < 2)
-#define PURPLE_CONV_TYPE_CHAT PURPLE_CONV_CHAT
-#define PURPLE_CONV_TYPE_IM PURPLE_CONV_IM
-#if GLIB_CHECK_VERSION(2,6,0)
-# include <glib/gstdio.h>
-#if !GLIB_CHECK_VERSION(2,6,0)
-# define g_freopen freopen
-# define g_remove remove
-# define g_unlink unlink
-# define g_rename rename
-/* The above should normally be the same as BUF_LEN,
- * but just so we're explicitly asking for the max message
-#define BUF_LONG BUF_LEN * 2
--- a/ignorance/ignorance_level.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,328 +0,0 @@
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
-#include "ignorance_denizen.h"
-#include "ignorance_internal.h"
-#include "ignorance_level.h"
-#include "ignorance_violation.h"
-void ignorance_level_write_hashitem(gpointer key, gpointer value,
-void ignorance_hash_free(gpointer key, gpointer value,
-void ignorance_level_regex_hashitem(gpointer key, gpointer value,
-gboolean assign_level_token(ignorance_level *lvl,const gchar *tokentxt);
-gint g_string_compare(gconstpointer a, gconstpointer z);
-ignorance_level* ignorance_level_new() {
- ignorance_level *il=(ignorance_level*)g_malloc(sizeof(ignorance_level));
- il->name=g_string_new("Default");
- il->denizens_hash=g_hash_table_new(g_str_hash,g_str_equal);
- il->rules=g_ptr_array_new();
-void ignorance_level_free(ignorance_level *il) {
- g_string_free(il->name,TRUE);
- g_hash_table_foreach(il->denizens_hash,ignorance_hash_free,NULL);
- g_hash_table_destroy(il->denizens_hash);
- g_ptr_array_foreach(il->rules,ignorance_rule_free_g,NULL);
-void ignorance_level_free_g(gpointer il,gpointer user_data) {
- ignorance_level_free((ignorance_level*)il);
-gboolean ignorance_level_add_rule(ignorance_level *level,ignorance_rule *rule) {
- g_ptr_array_add(level->rules,(gpointer)rule);
-ignorance_rule* ignorance_level_get_rule(ignorance_level *level,
- const GString *rulename) {
- ignorance_rule *rule=NULL;
- for(i=0;i<level->rules->len;++i){
- rule=g_ptr_array_index(level->rules,i);
- if(g_string_equal(rulename,rule->name))
- return g_ptr_array_index(level->rules,i);
-gboolean ignorance_level_remove_rule(ignorance_level *level,
- const GString *rulename) {
- return g_ptr_array_remove_fast(level->rules,
- ignorance_level_get_rule(level,rulename));
-gboolean ignorance_level_add_denizen(ignorance_level *level,
- const GString *username) {
- if(!g_hash_table_lookup(level->denizens_hash,username->str)){
- ignorance_denizen *id=ignorance_denizen_new(username->str);
- g_hash_table_insert(level->denizens_hash,
- ignorance_denizen_get_name(id),id);
-gboolean ignorance_level_has_denizen_regex(ignorance_level *level,
- const gchar *regex, GList **denizens) {
- if(regcomp(®,regex,REG_EXTENDED | REG_NOSUB)) {
- purple_debug_error("ignorance", "Error parsing regex %s\n",
- g_hash_table_foreach(level->denizens_hash,ignorance_level_regex_hashitem,
- return (denizens!=NULL);
-gboolean ignorance_level_has_denizen(ignorance_level *level,
- const GString *username) {
- rv = (NULL != g_hash_table_lookup(level->denizens_hash,username->str));
-gint g_string_compare(gconstpointer a, gconstpointer z) {
- const GString *gsa=(const GString*)a, *gsz=(const GString*)z;
- return g_ascii_strcasecmp(gsa->str, gsz->str);
-gboolean ignorance_level_remove_denizen(ignorance_level *level,
- const GString *username) {
- gpointer kptr=NULL, vptr=NULL;
- rv=g_hash_table_lookup_extended(level->denizens_hash, username->str, &kptr,
- purple_debug_info("ignorance","Remove: found id %x\n",vptr);
- purple_debug_info("ignorance","Removing from hash\n");
- g_hash_table_remove(level->denizens_hash,username->str);
- purple_debug_info("ignorance","Freeing denizen\n");
- ignorance_denizen_free((ignorance_denizen*)vptr);
- purple_debug_info("ignorance","Done freeing denizen\n");
-gint ignorance_level_rulecheck(ignorance_level *level,
- const GString *username, const GString *text,
- gint flags, GList **violations) {
- int i=0, totalscore=0, curscore;
- purple_debug_info("ignorance","Preparing to lookup %s\n", username->str);
- id = g_hash_table_lookup(level->denizens_hash, username->str);
- purple_debug_info("ignorance","Got denizen %x\n",id);
- purple_debug_info("ignorance","Making sure text isn't name\n");
- if(strcasecmp(ignorance_denizen_get_name(id),text->str)){
- purple_debug_info("ignorance","Setting new message to %s\n", text->str);
- ignorance_denizen_set_message(id, text->str);
- for(i=0;i<level->rules->len;++i) {
- cur=(ignorance_rule*)g_ptr_array_index(level->rules,i);
- if(cur->flags & IGNORANCE_APPLY_USER) {
- curscore=ignorance_rule_rulecheck(cur,username,flags);
- if(curscore & IGNORANCE_FLAG_MESSAGE)
- (*violations)=g_list_prepend(*violations,
- ignorance_violation_newp(IGNORANCE_FLAG_MESSAGE,
- if(curscore & IGNORANCE_FLAG_SOUND)
- (*violations)=g_list_prepend(*violations,
- ignorance_violation_newp(IGNORANCE_FLAG_SOUND,
- if(curscore & IGNORANCE_FLAG_EXECUTE)
- (*violations)=g_list_prepend(*violations,
- ignorance_violation_newp(IGNORANCE_FLAG_EXECUTE,
- curscore=ignorance_rule_rulecheck(cur, text,
- flags & (~IGNORANCE_APPLY_USER));
- if(curscore & IGNORANCE_FLAG_MESSAGE)
- (*violations)=g_list_prepend(*violations,
- ignorance_violation_newp(IGNORANCE_FLAG_MESSAGE, cur->message));
- if(curscore & IGNORANCE_FLAG_SOUND)
- (*violations)=g_list_prepend(*violations,
- ignorance_violation_newp(IGNORANCE_FLAG_SOUND, cur->sound));
- if(curscore & IGNORANCE_FLAG_EXECUTE)
- (*violations)=g_list_prepend(*violations,
- ignorance_violation_newp(IGNORANCE_FLAG_EXECUTE, cur->command));
-ignorance_level* ignorance_level_read_old(const gchar *lvltext) {
- gchar *tokptr=strchr((gchar*)lvltext,' '), **tokens=NULL;
- ignorance_level *lvl=ignorance_level_new();
- ignorance_level_free(lvl);
- tokens=g_strsplit(lvltext," ",INT_MAX);
- assign_level_token(lvl,tokens[i]);
-ignorance_level* ignorance_level_read(const gchar *lvltext) {
- gchar *tokptr=strchr((gchar*)lvltext,'\n'), **tokens=NULL;
- ignorance_level *lvl=ignorance_level_new();
- ignorance_level_free(lvl);
- return ignorance_level_read_old(lvltext);
- tokens=g_strsplit(lvltext,"\n",INT_MAX);
- assign_level_token(lvl,tokens[i]);
-/* Parses out a token of the form tokenname="value" and assigns it to a rulename
- * rule is the rule to be updated
- * tokentxt is the token string
- * true returned if token is valid and successfully added to the rule
- * level name1="value1" name2="value2" ...
-gboolean assign_level_token(ignorance_level *lvl,const gchar *tokentxt) {
- gchar *name=NULL, *value=NULL;
- value=strchr(tokentxt,'=');
- cursor=strlen(value)-1;
- if(!strncasecmp(name,"name",BUFSIZ))
- g_string_assign(lvl->name,value);
-gboolean ignorance_level_write(ignorance_level *level,FILE *f) {
- fprintf(f,"level\nname=\"%s\"\n/level\n", level->name->str);
- for(i=0;i<level->rules->len;++i)
- ignorance_rule_write(g_ptr_array_index(level->rules,i),f);
- g_hash_table_foreach(level->denizens_hash,ignorance_level_write_hashitem,f);
-void ignorance_level_regex_hashitem(gpointer key, gpointer value,
- gpointer *udata=(gpointer*)user_data;
- GList **denizens=(GList**)udata[0];
- if(!(regexec((regex_t*)udata[1],(gchar*)key,1,NULL,0)))
- (*denizens)=g_list_prepend(*denizens,g_string_new((gchar*)key));
-void ignorance_hash_free(gpointer key, gpointer value, gpointer user_data) {
- ignorance_denizen_free((ignorance_denizen*)value);
-void ignorance_level_write_hashitem(gpointer key, gpointer value,
- fprintf((FILE*)user_data,"%s\n",(gchar*)key);
--- a/ignorance/ignorance_level.h Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
-#ifndef IGNORANCE_LEVEL_H
-#define IGNORANCE_LEVEL_H
-#include "ignorance_rule.h"
- * describes an ignorance level
- * index is an index for keeping track
- * of levels' relative positions
- * the idea is for 0 to be the "default" level,
- * >0 to be "better" levels, and <0 to be "worse"
- * allow_passthrough flags whether a user
- * is allowed to be "passed through" this level
- * to the next consecutive level, as in:
- * if someone on my friends list does something
- * that flags 12 of my rules, do I send them
- * straight to /dev/null, or just
- * bump them down a level?
- * name - user's name for the level
- * denizens - list of users in this level
- * I may get rid of this in favor of a more global
- * rules - list of rules for this level
-typedef struct ignorance_level{
- GHashTable *denizens_hash;
-ignorance_level* ignorance_level_new();
-void ignorance_level_free(ignorance_level *il);
-void ignorance_level_free_g(gpointer il,gpointer user_data);
-gboolean ignorance_level_add_rule(ignorance_level *level,ignorance_rule *rule);
-ignorance_rule* ignorance_level_get_rule(ignorance_level *level,
- const GString *rulename);
-gboolean ignorance_level_remove_rule(ignorance_level *level,
- const GString *rulename);
-gboolean ignorance_level_add_denizen(ignorance_level *level,
- const GString *username);
-gboolean ignorance_level_add_denizen_fast(ignorance_level *level,
- const GString *username);
-gboolean ignorance_level_has_denizen(ignorance_level *level,
- const GString *username);
-gboolean ignorance_level_has_denizen_regex(ignorance_level *level,
- const gchar *regex, GList **denizens);
-gboolean ignorance_level_remove_denizen(ignorance_level *level,
- const GString *username);
- * Determines whether a string violates one of
- * the rules defined in an ignorance level
- * il is the ignorance level
- * text is the possibly offending string
- * flags are the rule flags to match
-gint ignorance_level_rulecheck(ignorance_level *il,const GString *username,
- const GString *text, gint flags,
-ignorance_level* ignorance_level_read(const gchar *lvltext);
-gboolean ignorance_level_write(ignorance_level *level,FILE *f);
--- a/ignorance/ignorance_rule.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,243 +0,0 @@
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
-#include "ignorance_rule.h"
-#include "ignorance_internal.h"
-gboolean assign_rule_token(ignorance_rule *rule, const char *tokentxt);
-ignorance_rule* ignorance_rule_new() {
- ignorance_rule *ir=(ignorance_rule*)g_malloc(sizeof(ignorance_rule));
- ir->name=g_string_new("");
- ir->type=IGNORANCE_RULE_SIMPLETEXT;
-ignorance_rule* ignorance_rule_newp(const GString *name, gint type,
- const gchar *value, gint score, gint flags,
- gboolean enabled, const gchar *message,
- const gchar *sound, const gchar *command) {
- ignorance_rule *ir=(ignorance_rule*)g_malloc(sizeof(ignorance_rule));
- ir->name=g_string_new(name->str);
- if(ignorance_rule_has_type(type))
- ir->type=IGNORANCE_RULE_INVALID;
- ir->value=g_strdup(value);
- ir->message=g_strdup(message);
- ir->sound=g_strdup(sound);
- ir->command=g_strdup(command);
-void ignorance_rule_free(ignorance_rule *ir) {
- g_string_free(ir->name,TRUE);
-void ignorance_rule_free_g(gpointer ir,gpointer user_data) {
- ignorance_rule_free((ignorance_rule*)ir);
-gboolean ignorance_rule_has_type(gint type) {
- if((type>=IGNORANCE_RULE_MINVALID) || (type<=IGNORANCE_RULE_INVALID))
-gint ignorance_rule_rulecheck(ignorance_rule *rule, const GString *text,
- if((flags & rule->flags) && rule->enabled){
- case IGNORANCE_RULE_SIMPLETEXT:
- return simple_text_rulecheck(rule,text);
- case IGNORANCE_RULE_REGEX:
- return regex_rulecheck(rule,text);
-gint simple_text_rulecheck(ignorance_rule *rule,const GString *text) {
- const gchar *rulevalue=(const gchar*)(rule->value);
- if(NULL!=g_strstr_len(text->str,text->len,rulevalue))
-gint regex_rulecheck(ignorance_rule *rule, const GString *text) {
- if(regcomp(®,(const gchar*)rule->value,REG_EXTENDED | REG_NOSUB))
- purple_debug_error("ignorance", "Error parsing regex %s\n",
- (const gchar*)(rule->value));
- else if(!regexec(®,text->str,1,NULL,0))
-gint repeat_rulecheck(ignorance_rule *rule, gint repeats) {
- gint allowed_repeats = atoi((gchar*)(rule->value));
- if(repeats >= allowed_repeats)
-ignorance_rule* ignorance_rule_read_old(const gchar *ruletext) {
- gchar *tokptr=strchr((gchar*)ruletext,' '), **tokens=NULL;
- ignorance_rule *rule=ignorance_rule_new();
- ignorance_rule_free(rule);
- tokens=g_strsplit(ruletext," ",INT_MAX);
- assign_rule_token(rule,tokens[i]);
- if(rule->score > 9 || rule->score < -9)
- rule->score=IGNORANCE_FLAG_IGNORE;
- rule->score=IGNORANCE_FLAG_FILTER;
-ignorance_rule* ignorance_rule_read(const gchar *ruletext) {
- gchar*tokptr=strchr((gchar*)ruletext,'\n'), **tokens;
- ignorance_rule *rule=ignorance_rule_new();
- ignorance_rule_free(rule);
- return ignorance_rule_read_old(ruletext);
- tokens=g_strsplit(ruletext,"\n",INT_MAX);
- assign_rule_token(rule,tokens[i]);
- * Parses out a token of the form tokenname="value" and assigns it to a rulename
- * rule is the rule to be updated
- * tokentxt is the token string
- * true returned if token is valid and successfully added to the rule
- * level name1="value1" name2="value2" ...
-gboolean assign_rule_token(ignorance_rule *rule,const gchar *tokentxt) {
- gchar *name=(gchar*)tokentxt, *value=NULL;
- value=strchr(tokentxt,'=');
- cursor=strlen(value)-1;
- if(!strncasecmp(name,"name",BUFSIZ))
- g_string_assign(rule->name,value);
- else if(!strncasecmp(name,"type",BUFSIZ))
- rule->type=atoi(value);
- else if(!strncasecmp(name,"value",BUFSIZ)) {
- rule->value=(gchar*)g_malloc((strlen(value)+1)*sizeof(gchar));
- strncpy(rule->value,value,strlen(value)+1);
- }else if(!strncasecmp(name,"score",BUFSIZ))
- rule->score=atoi(value);
- else if(!strncasecmp(name,"flags",BUFSIZ))
- rule->flags=atoi(value);
- else if(!strncasecmp(name,"enabled",BUFSIZ))
- rule->enabled=(gboolean)atoi(value);
- else if(!strncasecmp(name,"message",BUFSIZ)) {
- rule->message=(gchar*)g_malloc((strlen(value)+1)*sizeof(gchar));
- strncpy(rule->message,value,strlen(value)+1);
- } else if(!strncasecmp(name,"command",BUFSIZ)) {
- rule->command=(gchar*)g_malloc((strlen(value)+1)*sizeof(gchar));
- strncpy(rule->command,value,strlen(value)+1);
- } else if(!strncasecmp(name,"sound",BUFSIZ)) {
- rule->sound=(gchar*)g_malloc((strlen(value)+1)*sizeof(gchar));
- strncpy(rule->sound,value,strlen(value)+1);
-gboolean ignorance_rule_write(ignorance_rule *rule,FILE *f){
- fprintf(f,"rule\nname=\"%s\"\ntype=\"%d\"\nscore=\"%d\"\nvalue=\"%s\"\nflags=\"%d\"\nenabled=\"%d\"\nmessage=\"%s\"\ncommand=\"%s\"\nsound=\"%s\"\n/rule\n",
- rule->name->str, rule->type, rule->score, (gchar*)(rule->value),
- rule->flags, rule->enabled, rule->message, rule->command, rule->sound);
--- a/ignorance/ignorance_rule.h Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
-#ifndef IGNORANCE_RULE_H
-#define IGNORANCE_RULE_H
-# include "../pp_config.h"
-#include <glib/gprintf.h>
-#define IGNORANCE_RULE_INVALID 0
-#define IGNORANCE_RULE_MINVALID INT_MAX
-#define IGNORANCE_RULE_SIMPLETEXT 1
-#define IGNORANCE_RULE_SIMPLETEXT_NUMTOKENS 6
-#define IGNORANCE_RULE_REGEX 2
-#define IGNORANCE_RULE_REGEX_NUMTOKENS 6
-#define IGNORANCE_RULE_REPEAT 4
-#define IGNORANCE_RULE_REPEAT_NUMTOKENS 6
-#define IGNORANCE_FLAG_FILTER 1
-#define IGNORANCE_FLAG_IGNORE 2
-#define IGNORANCE_FLAG_MESSAGE 4
-#define IGNORANCE_FLAG_EXECUTE 8
-#define IGNORANCE_FLAG_SOUND 16
- * describes an ignorance rule
- * name - user's name for the rule
- * type - one of the ruletypes defined within this struct
- * value - the actual value of the rule
- * could be a string/regex, integer, other
- * depending on the rule type
- * score - an arbitrary (user-assigned) number
- * that determines the severity of the rule
-typedef struct ignorance_rule {
-ignorance_rule* ignorance_rule_new();
-ignorance_rule* ignorance_rule_newp(const GString *name, gint type,
- const gchar *value, gint score, gint flags,
- gboolean enabled, const gchar *message,
- const gchar *sound, const gchar *command);
-void ignorance_rule_free(ignorance_rule *ir);
-void ignorance_rule_free_g(gpointer ir,gpointer user_data);
-gboolean ignorance_rule_has_type(gint type);
- * Determines whether a string violates a rule
- * text is the possibly offending string
-gint ignorance_rule_rulecheck(ignorance_rule *rule, const GString *text,
-gint simple_text_rulecheck(ignorance_rule *rule, const GString *text);
-gint regex_rulecheck(ignorance_rule *rule, const GString *text);
-gint repeat_rulecheck(ignorance_rule *rule, gint repeats);
-ignorance_rule* ignorance_rule_read(const gchar *ruletext);
- * Writes out an ignorance rule to a file
- * rule is the rule to write
- * f is the file which will be written
- * success/failure returned
-gboolean ignorance_rule_write(ignorance_rule *rule, FILE *f);
--- a/ignorance/ignorance_violation.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
-#include "ignorance_violation.h"
-#include "ignorance_internal.h"
-ignorance_violation* ignorance_violation_new() {
- return ignorance_violation_newp(IGNORANCE_FLAG_MESSAGE,"");
-ignorance_violation* ignorance_violation_newp(gint newtype,
- const gchar *newvalue){
- ignorance_violation *iv=(ignorance_violation*)g_malloc(sizeof(ignorance_violation));
- iv->value=g_strdup(newvalue);
-void ignorance_violation_free(ignorance_violation *iv) {
-void ignorance_violation_free_g(gpointer iv, gpointer user_data) {
- ignorance_violation_free((ignorance_violation*)iv);
--- a/ignorance/ignorance_violation.h Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
-#ifndef IGNORANCE_VIOLATION_H
-#define IGNORANCE_VIOLATION_H
-typedef struct ignorance_violation {
-ignorance_violation* ignorance_violation_new();
-ignorance_violation* ignorance_violation_newp(gint newtype, const gchar *newvalue);
-void ignorance_violation_free(ignorance_violation *iv);
-void ignorance_violation_free_g(gpointer iv, gpointer user_data);
--- a/ignorance/interface.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,284 +0,0 @@
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
-#include <gdk/gdkkeysyms.h>
-#include "ignorance_internal.h"
-GtkWidget* create_uiinfo (GPtrArray *levels) {
- GtkWidget *frame, *table, *hbox, *label;
- GtkWidget *scrolledwindow, *levelView, *button;
- vbox1=gtk_vbox_new(FALSE, 0);
- gtk_widget_show(vbox1);
- vbox2 = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
- gtk_widget_show(vbox2);
- gtk_box_pack_start(GTK_BOX (vbox1), vbox2, TRUE, TRUE, 0);
- scrolledwindow=gtk_scrolled_window_new (NULL, NULL);
- gtk_widget_show(scrolledwindow);
- gtk_box_pack_start(GTK_BOX (vbox2), scrolledwindow, TRUE, TRUE, 0);
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrolledwindow),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW (scrolledwindow),
- store=gtk_tree_store_new(NUM_COLUMNS,G_TYPE_STRING,G_TYPE_STRING);
- levelView=gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
- renderer=gtk_cell_renderer_text_new ();
- column=gtk_tree_view_column_new_with_attributes ("Levels", renderer,
- "text", LEVEL_COLUMN, NULL);
- gtk_tree_view_append_column(GTK_TREE_VIEW (levelView), column);
- column=gtk_tree_view_column_new_with_attributes("Rules", renderer, "text",
- gtk_tree_view_append_column (GTK_TREE_VIEW (levelView), column);
- load_form_with_levels(GTK_TREE_VIEW(levelView), levels);
- gtk_widget_show(levelView);
- gtk_container_add(GTK_CONTAINER(scrolledwindow), levelView);
- sel=gtk_tree_view_get_selection(GTK_TREE_VIEW(levelView));
- gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
- hbox = gtk_hbox_new (FALSE, 0);
- gtk_widget_show (hbox);
- gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, FALSE, 0);
- button=pidgin_pixbuf_button_from_stock(_("Create new rule"),
- GTK_STOCK_ADD, PIDGIN_BUTTON_HORIZONTAL);
- gtk_widget_show (button);
- gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
- g_signal_connect((gpointer) button, "clicked",
- G_CALLBACK (on_levelAdd_clicked), levelView);
- button=pidgin_pixbuf_button_from_stock(_("Create new group"),
- GTK_STOCK_ADD, PIDGIN_BUTTON_HORIZONTAL);
- gtk_widget_show (button);
- gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
- g_signal_connect ((gpointer) button, "clicked",
- G_CALLBACK (on_groupAdd_clicked), levelView);
- button=pidgin_pixbuf_button_from_stock(_("Save changes"), GTK_STOCK_YES,
- PIDGIN_BUTTON_HORIZONTAL);
- gtk_widget_show (button);
- gtk_box_pack_start(GTK_BOX (hbox), button, TRUE, TRUE, 0);
- g_signal_connect((gpointer) button, "clicked",
- G_CALLBACK (on_levelEdit_clicked), levelView);
-/* XXX: The stock-icon for levelDel doesn't show, because the text is
- * set from callback.c. Can we do with just `Remove' for the text
- * and not updating as the selection in the tree changes?
- levelDel=pidgin_pixbuf_button_from_stock(_("Remove rule"), GTK_STOCK_REMOVE,
- PIDGIN_BUTTON_HORIZONTAL);
- gtk_widget_show (levelDel);
- gtk_box_pack_start (GTK_BOX (hbox), levelDel, TRUE, TRUE, 0);
- g_signal_connect((gpointer) levelDel, "clicked",
- G_CALLBACK (on_levelDel_clicked), levelView);
- table=gtk_table_new(3, 2, FALSE);
- gtk_container_set_border_width(GTK_CONTAINER(table), PIDGIN_HIG_BOX_SPACE);
- gtk_table_set_col_spacings(GTK_TABLE(table), PIDGIN_HIG_BOX_SPACE);
- gtk_table_set_row_spacings(GTK_TABLE(table), PIDGIN_HIG_BOX_SPACE);
- gtk_widget_show (table);
- gtk_box_pack_start (GTK_BOX (vbox2), table, FALSE, TRUE, 0);
- label=gtk_label_new_with_mnemonic(_("Name: "));
- gtk_widget_show(label);
- gtk_table_attach(GTK_TABLE (table), label, 0, 1, 0, 1, GTK_FILL, 0, 0, 0);
- rulename=gtk_entry_new ();
- gtk_widget_show(rulename);
- gtk_table_attach_defaults(GTK_TABLE (table), rulename, 1, 2, 0, 1);
- label=gtk_label_new_with_mnemonic(_("Filter: "));
- gtk_widget_show(label);
- gtk_table_attach(GTK_TABLE (table), label, 0, 1, 1, 2, GTK_FILL, 0, 0, 0);
- filtervalue=gtk_entry_new ();
- gtk_widget_show(filtervalue);
- gtk_table_attach_defaults(GTK_TABLE (table), filtervalue, 1, 2, 1, 2);
- hbox=gtk_hbox_new (FALSE, 0);
- gtk_table_attach_defaults(GTK_TABLE (table), hbox, 0, 2, 2, 3);
- enabled_cb=gtk_check_button_new_with_mnemonic(_("Enabled"));
- gtk_widget_show(enabled_cb);
- gtk_box_pack_start(GTK_BOX(hbox),enabled_cb,FALSE,FALSE,0);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enabled_cb),TRUE);
- regex_cb=gtk_check_button_new_with_mnemonic (_("Regular Expression"));
- gtk_widget_show(regex_cb);
- gtk_box_pack_start (GTK_BOX (hbox), regex_cb, FALSE, FALSE, 0);
- repeat_cb=gtk_check_button_new_with_mnemonic (_("Repeat"));
- gtk_widget_set_sensitive(repeat_cb,FALSE);
- gtk_widget_show(repeat_cb);
- gtk_box_pack_start(GTK_BOX (hbox), repeat_cb, FALSE, FALSE, 0);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (repeat_cb), FALSE);
- frame=gtk_frame_new (NULL);
- gtk_widget_show(frame);
- gtk_box_pack_start(GTK_BOX (vbox2), frame, FALSE, TRUE, 0);
- table=gtk_table_new(4, 2, FALSE);
- gtk_container_set_border_width(GTK_CONTAINER(table), PIDGIN_HIG_BOX_SPACE);
- gtk_table_set_col_spacings(GTK_TABLE(table), PIDGIN_HIG_BOX_SPACE);
- gtk_widget_show(table);
- gtk_container_add(GTK_CONTAINER(frame), table);
- hbox=gtk_hbox_new(FALSE, 0);
- gtk_table_attach_defaults(GTK_TABLE(table), hbox, 0, 2, 0, 1);
- filter_cb=gtk_check_button_new_with_label(_("Filter"));
- gtk_widget_show(filter_cb);
- gtk_box_pack_start(GTK_BOX (hbox), filter_cb, FALSE, FALSE, 0);
- ignore_cb=gtk_check_button_new_with_label(_("Ignore"));
- gtk_widget_show(ignore_cb);
- gtk_box_pack_start(GTK_BOX (hbox), ignore_cb, FALSE, FALSE, 0);
- message_cb = gtk_check_button_new_with_label(_("Send Message"));
- gtk_widget_show(message_cb);
- gtk_table_attach(GTK_TABLE(table), message_cb, 0, 1, 1, 2, GTK_FILL, 0, 0, 0);
- message_entry=gtk_entry_new();
- gtk_widget_set_sensitive(message_entry,FALSE);
- gtk_widget_show(message_entry);
- gtk_table_attach_defaults(GTK_TABLE(table), message_entry, 1, 2, 1, 2);
- sound_cb = gtk_check_button_new_with_label(_("Play sound"));
- gtk_widget_show(sound_cb);
- gtk_table_attach(GTK_TABLE(table), sound_cb, 0, 1, 2, 3, GTK_FILL, 0, 0, 0);
- hbox=gtk_hbox_new (FALSE, 0);
- gtk_widget_show (hbox);
- gtk_table_attach_defaults(GTK_TABLE(table), hbox, 1, 2, 2, 3);
- sound_entry=gtk_entry_new();
- gtk_widget_set_sensitive(sound_entry,FALSE);
- gtk_widget_show(sound_entry);
- gtk_box_pack_start(GTK_BOX(hbox),sound_entry,FALSE,FALSE,0);
- sound_browse=gtk_button_new_with_label(_("Browse"));
- gtk_widget_set_sensitive(sound_browse,FALSE);
- gtk_widget_show(sound_browse);
- gtk_box_pack_start(GTK_BOX(hbox),sound_browse,FALSE,FALSE,0);
- execute_cb=gtk_check_button_new_with_label(_("Execute command"));
- gtk_widget_show(execute_cb);
- gtk_table_attach(GTK_TABLE(table), execute_cb, 0, 1, 3, 4, GTK_FILL, 0, 0, 0);
- execute_entry=gtk_entry_new();
- gtk_widget_set_sensitive(execute_entry,FALSE);
- gtk_widget_show(execute_entry);
- gtk_table_attach_defaults(GTK_TABLE(table), execute_entry, 1, 2, 3, 4);
- label=gtk_label_new(_("Take action"));
- gtk_widget_show(label);
- gtk_frame_set_label_widget(GTK_FRAME (frame), label);
- frame=gtk_frame_new (NULL);
- gtk_widget_show(frame);
- gtk_box_pack_start(GTK_BOX (vbox2), frame, FALSE, TRUE, 0);
- table=gtk_table_new (3, 2, FALSE);
- gtk_widget_show(table);
- gtk_container_set_border_width(GTK_CONTAINER(table), PIDGIN_HIG_BOX_SPACE);
- gtk_table_set_col_spacings(GTK_TABLE(table), PIDGIN_HIG_BOX_SPACE);
- gtk_container_add(GTK_CONTAINER (frame), table);
- im_type_cb=gtk_check_button_new_with_mnemonic(_("IM Text"));
- gtk_widget_show(im_type_cb);
- gtk_table_attach(GTK_TABLE (table), im_type_cb, 0, 1, 0, 1,
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
- chat_type_cb=gtk_check_button_new_with_mnemonic(_("Chat Text"));
- gtk_widget_show(chat_type_cb);
- gtk_table_attach(GTK_TABLE (table), chat_type_cb, 1, 2, 0, 1,
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (chat_type_cb), TRUE);
- username_type_cb=gtk_check_button_new_with_mnemonic(_("User names"));
- gtk_widget_show(username_type_cb);
- gtk_table_attach(GTK_TABLE (table), username_type_cb, 0, 1, 1, 2,
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
- enterleave_type_cb=gtk_check_button_new_with_mnemonic (_("Enter/Leave"));
- gtk_widget_show(enterleave_type_cb);
- gtk_table_attach(GTK_TABLE (table), enterleave_type_cb, 1, 2, 1, 2,
- (GtkAttachOptions) (GTK_FILL),
- (GtkAttachOptions) (0), 0, 0);
- invite_type_cb=gtk_check_button_new_with_mnemonic (_("Invitations"));
- gtk_widget_show(invite_type_cb);
- gtk_table_attach(GTK_TABLE (table), invite_type_cb, 0, 1, 2, 3,
- (GtkAttachOptions) (GTK_FILL),
- (GtkAttachOptions) (0), 0, 0);
- label=gtk_label_new (_("Filter"));
- gtk_widget_show(label);
- gtk_frame_set_label_widget(GTK_FRAME (frame), label);
- g_signal_connect(GTK_WIDGET(vbox1), "destroy", G_CALLBACK(save_conf),NULL);
- g_signal_connect((gpointer)sel, "changed",
- G_CALLBACK (on_levelView_row_activated), NULL);
- g_signal_connect((gpointer) filter_cb, "toggled",
- G_CALLBACK (on_filter_cb_toggled), NULL);
- g_signal_connect((gpointer) ignore_cb, "toggled",
- G_CALLBACK (on_ignore_cb_toggled), NULL);
- g_signal_connect((gpointer) message_cb, "toggled",
- G_CALLBACK (on_message_cb_toggled), NULL);
- g_signal_connect((gpointer) sound_cb, "toggled",
- G_CALLBACK (on_sound_cb_toggled), NULL);
- g_signal_connect((gpointer) execute_cb, "toggled",
- G_CALLBACK (on_execute_cb_toggled), NULL);
- g_signal_connect((gpointer) sound_browse, "clicked",
- G_CALLBACK (on_sound_browse_clicked), NULL);
--- a/ignorance/interface.h Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
-#ifndef IGNORANCE_INTERFACE_H
-#define IGNORANCE_INTERFACE_H
-GtkWidget *chat_type_cb;
-GtkWidget *username_type_cb;
-GtkWidget *enterleave_type_cb;
-GtkWidget *invite_type_cb;
-GtkWidget *message_cb, *message_entry;
-GtkWidget *sound_cb, *sound_entry, *sound_browse;
-GtkWidget *execute_cb, *execute_entry, *execute_browse;
-GtkCellRenderer *renderer;
-GtkTreeViewColumn *column;
-GtkWidget* create_uiinfo(GPtrArray *levels);
--- a/ignorance/meson.build Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-if TYPES.contains('incomplete') and PIDGIN.found()
- ignorance_confdir = join_paths(
- get_option('sysconfdir'),
- install_data('ignorance.conf', install_dir : ignorance_confdir)
- ignorance = shared_module('ignorance',
- 'ignorance_violation.c',
- '-DIGNORANCE_CONFDIR="@0@"'.format(ignorance_confdir),
- dependencies : [PIDGIN, GTK],
- install_dir : PIDGIN_LIBDIR)
- PP_PIDGIN_BUILD += 'ignorance'
--- a/ignorance/regex.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,4952 +0,0 @@
-/* Extended regular expression matching and search library,
- (Implements POSIX draft P10003.2/D11.2, except for
- internationalization features.)
- Copyright (C) 1993 Free Software Foundation, Inc.
- 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, or (at your option)
- 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
-/* AIX requires this to be the first thing in the file. */
-#if defined (_AIX) && !defined (REGEX_MALLOC)
-/* We need this for `regex.h', and perhaps for the Emacs include files. */
-#include "../ig_config.h"
-/* The `emacs' switch turns on certain matching commands
- that make sense only in Emacs. */
-/* Emacs uses `NULL' as a predicate. */
-/* We used to test for `BSTRING' here, but only GCC and Emacs define
- `BSTRING', as far as I know, and neither of them use this code. */
-#if HAVE_STRING_H || STDC_HEADERS
-#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n))
-#define bcopy(s, d, n) memcpy ((d), (s), (n))
-#define bzero(s, n) memset ((s), 0, (n))
-/* Define the syntax stuff for \<, \>, etc. */
-/* This must be nonzero for the wordchar and notwordchar pattern
- commands in re_match_2. */
-extern char *re_syntax_table;
-#else /* not SYNTAX_TABLE */
-/* How many characters in the character set. */
-#define CHAR_SET_SIZE 256
-static char re_syntax_table[CHAR_SET_SIZE];
- bzero (re_syntax_table, sizeof re_syntax_table);
- for (c = 'a'; c <= 'z'; c++)
- re_syntax_table[c] = Sword;
- for (c = 'A'; c <= 'Z'; c++)
- re_syntax_table[c] = Sword;
- for (c = '0'; c <= '9'; c++)
- re_syntax_table[c] = Sword;
- re_syntax_table['_'] = Sword;
-#endif /* not SYNTAX_TABLE */
-#define SYNTAX(c) re_syntax_table[c]
-/* Get the interface, including the syntax bits. */
-/* isalpha etc. are used for the character classes. */
-#define ISBLANK(c) (isascii (c) && isblank (c))
-#define ISBLANK(c) ((c) == ' ' || (c) == '\t')
-#define ISGRAPH(c) (isascii (c) && isgraph (c))
-#define ISGRAPH(c) (isascii (c) && isprint (c) && !isspace (c))
-#define ISPRINT(c) (isascii (c) && isprint (c))
-#define ISDIGIT(c) (isascii (c) && isdigit (c))
-#define ISALNUM(c) (isascii (c) && isalnum (c))
-#define ISALPHA(c) (isascii (c) && isalpha (c))
-#define ISCNTRL(c) (isascii (c) && iscntrl (c))
-#define ISLOWER(c) (isascii (c) && islower (c))
-#define ISPUNCT(c) (isascii (c) && ispunct (c))
-#define ISSPACE(c) (isascii (c) && isspace (c))
-#define ISUPPER(c) (isascii (c) && isupper (c))
-#define ISXDIGIT(c) (isascii (c) && isxdigit (c))
-/* We remove any previous definition of `SIGN_EXTEND_CHAR',
- since ours (we hope) works properly with all combinations of
- machines, compilers, `char' and `unsigned char' argument types.
- (Per Bothner suggested the basic approach.) */
-#define SIGN_EXTEND_CHAR(c) ((signed char) (c))
-#else /* not __STDC__ */
-/* As in Harbison and Steele. */
-#define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128)
-/* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we
- use `alloca' instead of `malloc'. This is because using malloc in
- re_search* or re_match* could cause memory leaks when C-g is used in
- Emacs; also, malloc is slower and causes storage fragmentation. On
- the other hand, malloc is more portable, and easier to debug.
- Because we sometimes use alloca, some routines have to be macros,
- not functions -- `alloca'-allocated space disappears at the end of the
- function it is called in. */
-#define REGEX_ALLOCATE malloc
-#define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize)
-#else /* not REGEX_MALLOC */
-/* Emacs already defines alloca, sometimes. */
-/* Make alloca work the best possible way. */
-#define alloca __builtin_alloca
-#else /* not __GNUC__ */
-#else /* not __GNUC__ or HAVE_ALLOCA_H */
-#ifndef _AIX /* Already did AIX, up at the top. */
-#endif /* not HAVE_ALLOCA_H */
-#endif /* not __GNUC__ */
-#define REGEX_ALLOCATE alloca
-/* Assumes a `char *destination' variable. */
-#define REGEX_REALLOCATE(source, osize, nsize) \
- (destination = (char *) alloca (nsize), \
- bcopy (source, destination, osize), \
-#endif /* not REGEX_MALLOC */
-/* True if `size1' is non-NULL and PTR is pointing anywhere inside
- `string1' or just past its end. This works if PTR is NULL, which is
-#define FIRST_STRING_P(ptr) \
- (size1 && string1 <= (ptr) && (ptr) <= string1 + size1)
-/* (Re)Allocate N items of type T using malloc, or fail. */
-#define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t)))
-#define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t)))
-#define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t)))
-#define BYTEWIDTH 8 /* In bits. */
-#define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-/* These are the command codes that appear in compiled regular
- expressions. Some opcodes are followed by argument bytes. A
- command code can specify any interpretation whatsoever for its
- arguments. Zero bytes may appear in the compiled regular expression.
- The value of `exactn' is needed in search.c (search_buffer) in Emacs.
- So regex.h defines a symbol `RE_EXACTN_VALUE' to be 1; the value of
- `exactn' we use here must also be 1. */
- /* Followed by one byte giving n, then by n literal bytes. */
- /* Matches any (more or less) character. */
- /* Matches any one char belonging to specified set. First
- following byte is number of bitmap bytes. Then come bytes
- for a bitmap saying which chars are in. Bits in each byte
- are ordered low-bit-first. A character is in the set if its
- bit is 1. A character too large to have a bit in the map is
- automatically not in the set. */
- /* Same parameters as charset, but match any character that is
- not one of those specified. */
- /* Start remembering the text that is matched, for storing in a
- register. Followed by one byte with the register number, in
- the range 0 to one less than the pattern buffer's re_nsub
- field. Then followed by one byte with the number of groups
- inner to this one. (This last has to be part of the
- start_memory only because we need it in the on_failure_jump
- /* Stop remembering the text that is matched and store it in a
- memory register. Followed by one byte with the register
- number, in the range 0 to one less than `re_nsub' in the
- pattern buffer, and one byte with the number of inner groups,
- just like `start_memory'. (We need the number of inner
- groups here because we don't have any easy way of finding the
- corresponding start_memory when we're at a stop_memory.) */
- /* Match a duplicate of something remembered. Followed by one
- byte containing the register number. */
- /* Fail unless at beginning of line. */
- /* Fail unless at end of line. */
- /* Succeeds if at beginning of buffer (if emacs) or at beginning
- of string to be matched (if not). */
- /* Analogously, for end of buffer/string. */
- /* Followed by two byte relative address to which to jump. */
- /* Same as jump, but marks the end of an alternative. */
- /* Followed by two-byte relative address of place to resume at
- /* Like on_failure_jump, but pushes a placeholder instead of the
- current string position when executed. */
- on_failure_keep_string_jump,
- /* Throw away latest failure point and then jump to following
- two-byte relative address. */
- /* Change to pop_failure_jump if know won't have to backtrack to
- match; otherwise change to jump. This is used to jump
- back to the beginning of a repeat. If what follows this jump
- clearly won't match what the repeat does, such that we can be
- sure that there is no use backtracking out of repetitions
- already matched, then we change it to a pop_failure_jump.
- Followed by two-byte address. */
- /* Jump to following two-byte address, and push a dummy failure
- point. This failure point will be thrown away if an attempt
- is made to use it for a failure. A `+' construct makes this
- before the first repeat. Also used as an intermediary kind
- of jump when compiling an alternative. */
- /* Push a dummy failure point and continue. Used at the end of
- /* Followed by two-byte relative address and two-byte number n.
- After matching N times, jump to the address upon failure. */
- /* Followed by two-byte relative address, and two-byte number n.
- Jump to the address N times, then fail. */
- /* Set the following two-byte relative address to the
- subsequent two-byte number. The address *includes* the two
- wordchar, /* Matches any word-constituent character. */
- notwordchar, /* Matches any char that is not a word-constituent. */
- wordbeg, /* Succeeds if at word beginning. */
- wordend, /* Succeeds if at word end. */
- wordbound, /* Succeeds if at a word boundary. */
- notwordbound /* Succeeds if not at a word boundary. */
- ,before_dot, /* Succeeds if before point. */
- at_dot, /* Succeeds if at point. */
- after_dot, /* Succeeds if after point. */
- /* Matches any character whose syntax is specified. Followed by
- a byte which contains a syntax code, e.g., Sword. */
- /* Matches any character whose syntax is not that specified. */
-/* Common operations on the compiled pattern. */
-/* Store NUMBER in two contiguous bytes starting at DESTINATION. */
-#define STORE_NUMBER(destination, number) \
- (destination)[0] = (number) & 0377; \
- (destination)[1] = (number) >> 8; \
-/* Same as STORE_NUMBER, except increment DESTINATION to
- the byte after where the number is stored. Therefore, DESTINATION
-#define STORE_NUMBER_AND_INCR(destination, number) \
- STORE_NUMBER (destination, number); \
-/* Put into DESTINATION a number stored in two contiguous bytes starting
-#define EXTRACT_NUMBER(destination, source) \
- (destination) = *(source) & 0377; \
- (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \
-extract_number (dest, source)
- int temp = SIGN_EXTEND_CHAR (*(source + 1));
- *dest = *source & 0377;
-#ifndef EXTRACT_MACROS /* To debug the macros. */
-#define EXTRACT_NUMBER(dest, src) extract_number (&dest, src)
-#endif /* not EXTRACT_MACROS */
-/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number.
- SOURCE must be an lvalue. */
-#define EXTRACT_NUMBER_AND_INCR(destination, source) \
- EXTRACT_NUMBER (destination, source); \
-extract_number_and_incr (destination, source)
- unsigned char **source;
- extract_number (destination, *source);
-#undef EXTRACT_NUMBER_AND_INCR
-#define EXTRACT_NUMBER_AND_INCR(dest, src) \
- extract_number_and_incr (&dest, &src)
-#endif /* not EXTRACT_MACROS */
-/* If DEBUG is defined, Regex prints many voluminous messages about what
- it is doing (if the variable `debug' is nonzero). If linked with the
- main program in `iregex.c', you can enter patterns and strings
- interactively. And if linked with the main program in `main.c' and
- the other test files, you can run the already-written tests. */
-/* We use standard I/O for debugging. */
-/* It is useful to test things that ``must'' be true when debugging. */
-#define DEBUG_STATEMENT(e) e
-#define DEBUG_PRINT1(x) if (debug) printf (x)
-#define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2)
-#define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3)
-#define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4)
-#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \
- if (debug) print_partial_compiled_pattern (s, e)
-#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \
- if (debug) print_double_string (w, s1, sz1, s2, sz2)
-extern void printchar ();
-/* Print the fastmap in human-readable form. */
- unsigned was_a_range = 0;
- while (i < (1 << BYTEWIDTH))
- while (i < (1 << BYTEWIDTH) && fastmap[i])
-/* Print a compiled pattern string in human-readable form, starting at
- the START pointer into it and ending just before the pointer END. */
-print_partial_compiled_pattern (start, end)
- unsigned char *p = start;
- unsigned char *pend = end;
- /* Loop over pattern commands. */
- switch ((re_opcode_t) *p++)
- printf ("/exactn/%d", mcnt);
- printf ("/start_memory/%d/%d", mcnt, *p++);
- printf ("/stop_memory/%d/%d", mcnt, *p++);
- printf ("/duplicate/%d", *p++);
- (re_opcode_t) *(p - 1) == charset_not ? "_not" : "");
- assert (p + *p < pend);
- for (c = 0; c < *p; c++)
- unsigned char map_byte = p[1 + c];
- for (bit = 0; bit < BYTEWIDTH; bit++)
- if (map_byte & (1 << bit))
- printchar (c * BYTEWIDTH + bit);
- extract_number_and_incr (&mcnt, &p);
- printf ("/on_failure_jump/0/%d", mcnt);
- case on_failure_keep_string_jump:
- extract_number_and_incr (&mcnt, &p);
- printf ("/on_failure_keep_string_jump/0/%d", mcnt);
- case dummy_failure_jump:
- extract_number_and_incr (&mcnt, &p);
- printf ("/dummy_failure_jump/0/%d", mcnt);
- case push_dummy_failure:
- printf ("/push_dummy_failure");
- extract_number_and_incr (&mcnt, &p);
- printf ("/maybe_pop_jump/0/%d", mcnt);
- extract_number_and_incr (&mcnt, &p);
- printf ("/pop_failure_jump/0/%d", mcnt);
- extract_number_and_incr (&mcnt, &p);
- printf ("/jump_past_alt/0/%d", mcnt);
- extract_number_and_incr (&mcnt, &p);
- printf ("/jump/0/%d", mcnt);
- extract_number_and_incr (&mcnt, &p);
- extract_number_and_incr (&mcnt2, &p);
- printf ("/succeed_n/0/%d/0/%d", mcnt, mcnt2);
- extract_number_and_incr (&mcnt, &p);
- extract_number_and_incr (&mcnt2, &p);
- printf ("/jump_n/0/%d/0/%d", mcnt, mcnt2);
- extract_number_and_incr (&mcnt, &p);
- extract_number_and_incr (&mcnt2, &p);
- printf ("/set_number_at/0/%d/0/%d", mcnt, mcnt2);
- printf ("/notwordbound");
- printf ("/before_dot");
- printf ("/syntaxspec");
- printf ("/notsyntaxspec");
- printf ("/notwordchar");
- printf ("?%d", *(p-1));
-print_compiled_pattern (bufp)
- struct re_pattern_buffer *bufp;
- unsigned char *buffer = bufp->buffer;
- print_partial_compiled_pattern (buffer, buffer + bufp->used);
- printf ("%d bytes used/%d bytes allocated.\n", bufp->used, bufp->allocated);
- if (bufp->fastmap_accurate && bufp->fastmap)
- print_fastmap (bufp->fastmap);
- printf ("re_nsub: %d\t", bufp->re_nsub);
- printf ("regs_alloc: %d\t", bufp->regs_allocated);
- printf ("can_be_null: %d\t", bufp->can_be_null);
- printf ("newline_anchor: %d\n", bufp->newline_anchor);
- printf ("no_sub: %d\t", bufp->no_sub);
- printf ("not_bol: %d\t", bufp->not_bol);
- printf ("not_eol: %d\t", bufp->not_eol);
- printf ("syntax: %d\n", bufp->syntax);
- /* Perhaps we should print the translate table? */
-print_double_string (where, string1, size1, string2, size2)
- if (FIRST_STRING_P (where))
- for (this_char = where - string1; this_char < size1; this_char++)
- printchar (string1[this_char]);
- for (this_char = where - string2; this_char < size2; this_char++)
- printchar (string2[this_char]);
-#define DEBUG_STATEMENT(e)
-#define DEBUG_PRINT2(x1, x2)
-#define DEBUG_PRINT3(x1, x2, x3)
-#define DEBUG_PRINT4(x1, x2, x3, x4)
-#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e)
-#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)
-/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can
- also be assigned to arbitrarily: each pattern buffer stores its own
- syntax, so it can be changed between regex compilations. */
-reg_syntax_t re_syntax_options = RE_SYNTAX_EMACS;
-/* Specify the precise syntax of regexps for compilation. This provides
- for compatibility for various utilities which historically have
- different, incompatible syntaxes.
- The argument SYNTAX is a bit mask comprised of the various bits
- defined in regex.h. We return the old syntax. */
- reg_syntax_t ret = re_syntax_options;
- re_syntax_options = syntax;
-/* This table gives an error message for each of the error codes listed
- in regex.h. Obviously the order here has to be same as there. */
-static const char *re_error_msg[] =
- { NULL, /* REG_NOERROR */
- "No match", /* REG_NOMATCH */
- "Invalid regular expression", /* REG_BADPAT */
- "Invalid collation character", /* REG_ECOLLATE */
- "Invalid character class name", /* REG_ECTYPE */
- "Trailing backslash", /* REG_EESCAPE */
- "Invalid back reference", /* REG_ESUBREG */
- "Unmatched [ or [^", /* REG_EBRACK */
- "Unmatched ( or \\(", /* REG_EPAREN */
- "Unmatched \\{", /* REG_EBRACE */
- "Invalid content of \\{\\}", /* REG_BADBR */
- "Invalid range end", /* REG_ERANGE */
- "Memory exhausted", /* REG_ESPACE */
- "Invalid preceding regular expression", /* REG_BADRPT */
- "Premature end of regular expression", /* REG_EEND */
- "Regular expression too big", /* REG_ESIZE */
- "Unmatched ) or \\)", /* REG_ERPAREN */
-/* Subroutine declarations and macros for regex_compile. */
-static void store_op1 (), store_op2 ();
-static void insert_op1 (), insert_op2 ();
-static boolean at_begline_loc_p (), at_endline_loc_p ();
-static boolean group_in_compile_stack ();
-static reg_errcode_t compile_range ();
-/* Fetch the next character in the uncompiled pattern---translating it
- if necessary. Also cast from a signed character in the constant
- string passed to us by the user to an unsigned char that we can use
- as an array index (in, e.g., `translate'). */
- do {if (p == pend) return REG_EEND; \
- c = (unsigned char) *p++; \
- if (translate) c = translate[c]; \
-/* Fetch the next character in the uncompiled pattern, with no
-#define PATFETCH_RAW(c) \
- do {if (p == pend) return REG_EEND; \
- c = (unsigned char) *p++; \
-/* Go backwards one character in the pattern. */
-/* If `translate' is non-null, return translate[D], else just D. We
- cast the subscript to translate because some data is declared as
- `char *', to avoid warnings when a string constant is passed. But
- when we use a character as a subscript we must make it unsigned. */
-#define TRANSLATE(d) (translate ? translate[(unsigned char) (d)] : (d))
-/* Macros for outputting the compiled pattern into `buffer'. */
-/* If the buffer isn't allocated when it comes in, use this. */
-#define INIT_BUF_SIZE 32
-/* Make sure we have at least N more bytes of space in buffer. */
-#define GET_BUFFER_SPACE(n) \
- while (b - bufp->buffer + (n) > bufp->allocated) \
-/* Make sure we have one more byte of buffer space and then add C to it. */
- GET_BUFFER_SPACE (1); \
- *b++ = (unsigned char) (c); \
-/* Ensure we have two more bytes of buffer space and then append C1 and C2. */
-#define BUF_PUSH_2(c1, c2) \
- GET_BUFFER_SPACE (2); \
- *b++ = (unsigned char) (c1); \
- *b++ = (unsigned char) (c2); \
-/* As with BUF_PUSH_2, except for three bytes. */
-#define BUF_PUSH_3(c1, c2, c3) \
- GET_BUFFER_SPACE (3); \
- *b++ = (unsigned char) (c1); \
- *b++ = (unsigned char) (c2); \
- *b++ = (unsigned char) (c3); \
-/* Store a jump with opcode OP at LOC to location TO. We store a
- relative address offset by the three bytes the jump itself occupies. */
-#define STORE_JUMP(op, loc, to) \
- store_op1 (op, loc, (to) - (loc) - 3)
-/* Likewise, for a two-argument jump. */
-#define STORE_JUMP2(op, loc, to, arg) \
- store_op2 (op, loc, (to) - (loc) - 3, arg)
-/* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */
-#define INSERT_JUMP(op, loc, to) \
- insert_op1 (op, loc, (to) - (loc) - 3, b)
-/* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */
-#define INSERT_JUMP2(op, loc, to, arg) \
- insert_op2 (op, loc, (to) - (loc) - 3, arg, b)
-/* This is not an arbitrary limit: the arguments which represent offsets
- into the pattern are two bytes long. So if 2^16 bytes turns out to
- be too small, many things would have to change. */
-#define MAX_BUF_SIZE (1L << 16)
-/* Extend the buffer by twice its current size via realloc and
- reset the pointers that pointed into the old block to point to the
- correct places in the new one. If extending the buffer results in it
- being larger than MAX_BUF_SIZE, then flag memory exhausted. */
-#define EXTEND_BUFFER() \
- unsigned char *old_buffer = bufp->buffer; \
- if (bufp->allocated == MAX_BUF_SIZE) \
- bufp->allocated <<= 1; \
- if (bufp->allocated > MAX_BUF_SIZE) \
- bufp->allocated = MAX_BUF_SIZE; \
- bufp->buffer = (unsigned char *) realloc (bufp->buffer, bufp->allocated);\
- if (bufp->buffer == NULL) \
- /* If the buffer moved, move all the pointers into it. */ \
- if (old_buffer != bufp->buffer) \
- b = (b - old_buffer) + bufp->buffer; \
- begalt = (begalt - old_buffer) + bufp->buffer; \
- fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\
- laststart = (laststart - old_buffer) + bufp->buffer; \
- pending_exact = (pending_exact - old_buffer) + bufp->buffer; \
-/* Since we have one byte reserved for the register number argument to
- {start,stop}_memory, the maximum number of groups we can report
- things about is what fits in that byte. */
-/* But patterns can have more than `MAX_REGNUM' registers. We just
-typedef unsigned regnum_t;
-/* Macros for the compile stack. */
-/* Since offsets can go either forwards or backwards, this type needs to
- be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1. */
-typedef int pattern_offset_t;
- pattern_offset_t begalt_offset;
- pattern_offset_t fixup_alt_jump;
- pattern_offset_t inner_group_offset;
- pattern_offset_t laststart_offset;
- compile_stack_elt_t *stack;
- unsigned avail; /* Offset of next open position. */
-#define INIT_COMPILE_STACK_SIZE 32
-#define COMPILE_STACK_EMPTY (compile_stack.avail == 0)
-#define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size)
-/* The next available element. */
-#define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail])
-/* Set the bit for character C in a list. */
-#define SET_LIST_BIT(c) \
- (b[((unsigned char) (c)) / BYTEWIDTH] \
- |= 1 << (((unsigned char) c) % BYTEWIDTH))
-/* Get the next unsigned number in the uncompiled pattern. */
-#define GET_UNSIGNED_NUMBER(num) \
- num = num * 10 + c - '0'; \
-#define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */
-#define IS_CHAR_CLASS(string) \
- (STREQ (string, "alpha") || STREQ (string, "upper") \
- || STREQ (string, "lower") || STREQ (string, "digit") \
- || STREQ (string, "alnum") || STREQ (string, "xdigit") \
- || STREQ (string, "space") || STREQ (string, "print") \
- || STREQ (string, "punct") || STREQ (string, "graph") \
- || STREQ (string, "cntrl") || STREQ (string, "blank"))
-/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX.
- Returns one of error codes defined in `regex.h', or zero for success.
- Assumes the `allocated' (and perhaps `buffer') and `translate'
- fields are set in BUFP on entry.
- If it succeeds, results are put in BUFP (if it returns an error, the
- contents of BUFP are undefined):
- `buffer' is the compiled pattern;
- `syntax' is set to SYNTAX;
- `used' is set to the length of the compiled pattern;
- `fastmap_accurate' is zero;
- `re_nsub' is the number of subexpressions in PATTERN;
- `not_bol' and `not_eol' are zero;
- The `fastmap' and `newline_anchor' fields are neither
-regex_compile (pattern, size, syntax, bufp)
- struct re_pattern_buffer *bufp;
- /* We fetch characters from PATTERN here. Even though PATTERN is
- `char *' (i.e., signed), we declare these variables as unsigned, so
- they can be reliably used as array indices. */
- register unsigned char c, c1;
- /* A random tempory spot in PATTERN. */
- /* Points to the end of the buffer, where we should append. */
- register unsigned char *b;
- /* Keeps track of unclosed groups. */
- compile_stack_type compile_stack;
- /* Points to the current (ending) position in the pattern. */
- const char *p = pattern;
- const char *pend = pattern + size;
- /* How to translate the characters in the pattern. */
- char *translate = bufp->translate;
- /* Address of the count-byte of the most recently inserted `exactn'
- command. This makes it possible to tell if a new exact-match
- character can be added to that command or if the character requires
- a new `exactn' command. */
- unsigned char *pending_exact = 0;
- /* Address of start of the most recently finished expression.
- This tells, e.g., postfix * where to find the start of its
- operand. Reset at the beginning of groups and alternatives. */
- unsigned char *laststart = 0;
- /* Address of beginning of regexp, or inside of last group. */
- /* Place in the uncompiled pattern (i.e., the {) to
- which to go back if the interval is invalid. */
- const char *beg_interval;
- /* Address of the place where a forward jump should go to the end of
- the containing expression. Each alternative of an `or' -- except the
- last -- ends with a forward jump of this sort. */
- unsigned char *fixup_alt_jump = 0;
- /* Counts open-groups as they are encountered. Remembered for the
- matching close-group on the compile stack, so the same register
- number is put in the stop_memory as the start_memory. */
- DEBUG_PRINT1 ("\nCompiling pattern: ");
- for (debug_count = 0; debug_count < size; debug_count++)
- printchar (pattern[debug_count]);
- /* Initialize the compile stack. */
- compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t);
- if (compile_stack.stack == NULL)
- compile_stack.size = INIT_COMPILE_STACK_SIZE;
- compile_stack.avail = 0;
- /* Initialize the pattern buffer. */
- bufp->fastmap_accurate = 0;
- bufp->not_bol = bufp->not_eol = 0;
- /* Set `used' to zero, so that if we return an error, the pattern
- printer (for debugging) will think there's no pattern. We reset it
- /* Always count groups, whether or not bufp->no_sub is set. */
-#if !defined (emacs) && !defined (SYNTAX_TABLE)
- /* Initialize the syntax table. */
- if (bufp->allocated == 0)
- { /* If zero allocated, but buffer is non-null, try to realloc
- enough space. This loses if buffer's address is bogus, but
- that is the user's responsibility. */
- RETALLOC (bufp->buffer, INIT_BUF_SIZE, unsigned char);
- { /* Caller did not allocate a buffer. Do it for them. */
- bufp->buffer = TALLOC (INIT_BUF_SIZE, unsigned char);
- if (!bufp->buffer) return REG_ESPACE;
- bufp->allocated = INIT_BUF_SIZE;
- begalt = b = bufp->buffer;
- /* Loop through the uncompiled pattern until we're at the end. */
- if ( /* If at start of pattern, it's an operator. */
- /* If context independent, it's an operator. */
- || syntax & RE_CONTEXT_INDEP_ANCHORS
- /* Otherwise, depends on what's come before. */
- || at_begline_loc_p (pattern, p, syntax))
- if ( /* If at end of pattern, it's an operator. */
- /* If context independent, it's an operator. */
- || syntax & RE_CONTEXT_INDEP_ANCHORS
- /* Otherwise, depends on what's next. */
- || at_endline_loc_p (p, pend, syntax))
- if ((syntax & RE_BK_PLUS_QM)
- || (syntax & RE_LIMITED_OPS))
- /* If there is no previous pattern... */
- if (syntax & RE_CONTEXT_INVALID_OPS)
- else if (!(syntax & RE_CONTEXT_INDEP_OPS))
- /* Are we optimizing this jump? */
- boolean keep_string_p = false;
- /* 1 means zero (many) matches is allowed. */
- char zero_times_ok = 0, many_times_ok = 0;
- /* If there is a sequence of repetition chars, collapse it
- down to just one (the right one). We can't combine
- interval operators with these because of, e.g., `a{2}*',
- which should only match an even number of `a's. */
- zero_times_ok |= c != '+';
- many_times_ok |= c != '?';
- || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?')))
- else if (syntax & RE_BK_PLUS_QM && c == '\\')
- if (p == pend) return REG_EESCAPE;
- if (!(c1 == '+' || c1 == '?'))
- /* If we get here, we found another repeat character. */
- /* Star, etc. applied to an empty pattern is equivalent
- to an empty pattern. */
- /* Now we know whether or not zero matches is allowed
- and also whether or not two or more matches is allowed. */
- { /* More than one repetition is allowed, so put in at the
- end a backward relative jump from `b' to before the next
- jump we're going to put in below (which jumps from
- laststart to after this jump).
- But if we are at the `*' in the exact sequence `.*\n',
- insert an unconditional jump backwards to the .,
- instead of the beginning of the loop. This way we only
- push a failure point once, instead of every time
- assert (p - 1 > pattern);
- /* Allocate the space for the jump. */
- /* We know we are not at the first character of the pattern,
- because laststart was nonzero. And we've already
- incremented `p', by the way, to be the character after
- the `*'. Do we have to do something analogous here
- for null bytes, because of RE_DOT_NOT_NULL? */
- if (TRANSLATE (*(p - 2)) == TRANSLATE ('.')
- && p < pend && TRANSLATE (*p) == TRANSLATE ('\n')
- && !(syntax & RE_DOT_NEWLINE))
- STORE_JUMP (jump, b, laststart);
- STORE_JUMP (maybe_pop_jump, b, laststart - 3);
- /* We've added more stuff to the buffer. */
- /* On failure, jump from laststart to b + 3, which will be the
- end of the buffer after this jump is inserted. */
- INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump
- /* At least one repetition is required, so insert a
- `dummy_failure_jump' before the initial
- `on_failure_jump' instruction of the loop. This
- effects a skip over that instruction the first time
- INSERT_JUMP (dummy_failure_jump, laststart, laststart + 6);
- boolean had_char_class = false;
- if (p == pend) return REG_EBRACK;
- /* Ensure that we have enough space to push a charset: the
- opcode, the length count, and the bitset; 34 bytes in all. */
- /* We test `*p == '^' twice, instead of using an if
- statement, so we only need one BUF_PUSH. */
- BUF_PUSH (*p == '^' ? charset_not : charset);
- /* Remember the first position in the bracket expression. */
- /* Push the number of bytes in the bitmap. */
- BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH);
- /* Clear the whole map. */
- bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH);
- /* charset_not matches newline according to a syntax bit. */
- if ((re_opcode_t) b[-2] == charset_not
- && (syntax & RE_HAT_LISTS_NOT_NEWLINE))
- /* Read in characters and ranges, setting map bits. */
- if (p == pend) return REG_EBRACK;
- /* \ might escape characters inside [...] and [^...]. */
- if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\')
- if (p == pend) return REG_EESCAPE;
- /* Could be the end of the bracket expression. If it's
- not (i.e., when the bracket expression is `[]' so
- far), the ']' character bit gets set way below. */
- if (c == ']' && p != p1 + 1)
- /* Look ahead to see if it's a range when the last thing
- was a character class. */
- if (had_char_class && c == '-' && *p != ']')
- /* Look ahead to see if it's a range when the last thing
- was a character: if this is a hyphen not at the
- beginning or the end of a list, then it's the range
- && !(p - 2 >= pattern && p[-2] == '[')
- && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^')
- = compile_range (&p, pend, translate, syntax, b);
- if (ret != REG_NOERROR) return ret;
- else if (p[0] == '-' && p[1] != ']')
- { /* This handles ranges made up of characters only. */
- /* Move past the `-'. */
- ret = compile_range (&p, pend, translate, syntax, b);
- if (ret != REG_NOERROR) return ret;
- /* See if we're at the beginning of a possible character
- else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':')
- { /* Leave room for the null. */
- char str[CHAR_CLASS_MAX_LENGTH + 1];
- /* If pattern is `[[:'. */
- if (p == pend) return REG_EBRACK;
- if (c == ':' || c == ']' || p == pend
- || c1 == CHAR_CLASS_MAX_LENGTH)
- /* If isn't a word bracketed by `[:' and:`]':
- undo the ending character, the letters, and leave
- the leading `:' and `[' (but set bits for them). */
- if (c == ':' && *p == ']')
- boolean is_alnum = STREQ (str, "alnum");
- boolean is_alpha = STREQ (str, "alpha");
- boolean is_blank = STREQ (str, "blank");
- boolean is_cntrl = STREQ (str, "cntrl");
- boolean is_digit = STREQ (str, "digit");
- boolean is_graph = STREQ (str, "graph");
- boolean is_lower = STREQ (str, "lower");
- boolean is_print = STREQ (str, "print");
- boolean is_punct = STREQ (str, "punct");
- boolean is_space = STREQ (str, "space");
- boolean is_upper = STREQ (str, "upper");
- boolean is_xdigit = STREQ (str, "xdigit");
- if (!IS_CHAR_CLASS (str)) return REG_ECTYPE;
- /* Throw away the ] at the end of the character
- if (p == pend) return REG_EBRACK;
- for (ch = 0; ch < 1 << BYTEWIDTH; ch++)
- if ( (is_alnum && ISALNUM (ch))
- || (is_alpha && ISALPHA (ch))
- || (is_blank && ISBLANK (ch))
- || (is_cntrl && ISCNTRL (ch))
- || (is_digit && ISDIGIT (ch))
- || (is_graph && ISGRAPH (ch))
- || (is_lower && ISLOWER (ch))
- || (is_print && ISPRINT (ch))
- || (is_punct && ISPUNCT (ch))
- || (is_space && ISSPACE (ch))
- || (is_upper && ISUPPER (ch))
- || (is_xdigit && ISXDIGIT (ch)))
- had_char_class = false;
- had_char_class = false;
- /* Discard any (non)matching list bytes that are all 0 at the
- end of the map. Decrease the map-length byte too. */
- while ((int) b[-1] > 0 && b[b[-1] - 1] == 0)
- if (syntax & RE_NO_BK_PARENS)
- if (syntax & RE_NO_BK_PARENS)
- if (syntax & RE_NEWLINE_ALT)
- if (syntax & RE_NO_BK_VBAR)
- if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES)
- if (p == pend) return REG_EESCAPE;
- /* Do not translate the character after the \, so that we can
- distinguish, e.g., \B from \b, even if we normally would
- translate, e.g., B to b. */
- if (syntax & RE_NO_BK_PARENS)
- if (COMPILE_STACK_FULL)
- RETALLOC (compile_stack.stack, compile_stack.size << 1,
- if (compile_stack.stack == NULL) return REG_ESPACE;
- compile_stack.size <<= 1;
- /* These are the values to restore when we hit end of this
- group. They are all relative offsets, so that if the
- whole pattern moves because of realloc, they will still
- COMPILE_STACK_TOP.begalt_offset = begalt - bufp->buffer;
- COMPILE_STACK_TOP.fixup_alt_jump
- = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0;
- COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer;
- COMPILE_STACK_TOP.regnum = regnum;
- /* We will eventually replace the 0 with the number of
- groups inner to this one. But do not push a
- start_memory for groups beyond the last one we can
- represent in the compiled pattern. */
- if (regnum <= MAX_REGNUM)
- COMPILE_STACK_TOP.inner_group_offset = b - bufp->buffer + 2;
- BUF_PUSH_3 (start_memory, regnum, 0);
- /* If we've reached MAX_REGNUM groups, then this open
- won't actually generate any code, so we'll have to
- clear pending_exact explicitly. */
- if (syntax & RE_NO_BK_PARENS) goto normal_backslash;
- if (COMPILE_STACK_EMPTY){
- if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD){
- { /* Push a dummy failure point at the end of the
- alternative for a possible future
- `pop_failure_jump' to pop. See comments at
- `push_dummy_failure' in `re_match_2'. */
- BUF_PUSH (push_dummy_failure);
- /* We allocated space for this jump when we assigned
- to `fixup_alt_jump', in the `handle_alt' case below. */
- STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1);
- /* See similar code for backslashed left paren above. */
- if (COMPILE_STACK_EMPTY){
- if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD){
- /* Since we just checked for an empty stack above, this
- assert (compile_stack.avail != 0);
- /* We don't just want to restore into `regnum', because
- later groups should continue to be numbered higher,
- as in `(ab)c(de)' -- the second group is #2. */
- regnum_t this_group_regnum;
- begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset;
- = COMPILE_STACK_TOP.fixup_alt_jump
- ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1
- laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset;
- this_group_regnum = COMPILE_STACK_TOP.regnum;
- /* If we've reached MAX_REGNUM groups, then this open
- won't actually generate any code, so we'll have to
- clear pending_exact explicitly. */
- /* We're at the end of the group, so now we know how many
- groups were inside this one. */
- if (this_group_regnum <= MAX_REGNUM)
- unsigned char *inner_group_loc
- = bufp->buffer + COMPILE_STACK_TOP.inner_group_offset;
- *inner_group_loc = regnum - this_group_regnum;
- BUF_PUSH_3 (stop_memory, this_group_regnum,
- regnum - this_group_regnum);
- if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR)
- if (syntax & RE_LIMITED_OPS)
- /* Insert before the previous alternative a jump which
- jumps to this alternative if the former fails. */
- INSERT_JUMP (on_failure_jump, begalt, b + 6);
- /* The alternative before this one has a jump after it
- which gets executed if it gets matched. Adjust that
- jump so it will jump to this alternative's analogous
- jump (put in below, which in turn will jump to the next
- (if any) alternative's such jump, etc.). The last such
- jump jumps to the correct final destination. A picture:
- If we are at `b', then fixup_alt_jump right now points to a
- three-byte space after `a'. We'll put in the jump, set
- fixup_alt_jump to right after `b', and leave behind three
- bytes which we'll fill in when we get to after `c'. */
- STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
- /* Mark and leave space for a jump after this alternative,
- to be filled in later either by next alternative or
- when know we're at the end of a series of alternatives. */
- /* If \{ is a literal. */
- if (!(syntax & RE_INTERVALS)
- /* If we're at `\{' and it's not the open-interval
- || ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
- || (p - 2 == pattern && p == pend))
- /* If got here, then the syntax allows intervals. */
- /* At least (most) this many matches must be made. */
- int lower_bound = -1, upper_bound = -1;
- if (syntax & RE_NO_BK_BRACES)
- GET_UNSIGNED_NUMBER (lower_bound);
- GET_UNSIGNED_NUMBER (upper_bound);
- if (upper_bound < 0) upper_bound = RE_DUP_MAX;
- /* Interval such as `{1}' => match exactly once. */
- upper_bound = lower_bound;
- if (lower_bound < 0 || upper_bound > RE_DUP_MAX
- || lower_bound > upper_bound)
- if (syntax & RE_NO_BK_BRACES)
- if (!(syntax & RE_NO_BK_BRACES))
- if (c != '\\') return REG_EBRACE;
- if (syntax & RE_NO_BK_BRACES)
- /* We just parsed a valid interval. */
- /* If it's invalid to have no preceding re. */
- if (syntax & RE_CONTEXT_INVALID_OPS)
- else if (syntax & RE_CONTEXT_INDEP_OPS)
- /* If the upper bound is zero, don't want to succeed at
- all; jump from `laststart' to `b + 3', which will be
- the end of the buffer after we insert the jump. */
- INSERT_JUMP (jump, laststart, b + 3);
- /* Otherwise, we have a nontrivial interval. When
- we're all done, the pattern will look like:
- set_number_at <jump count> <upper bound>
- set_number_at <succeed_n count> <lower bound>
- succeed_n <after jump addr> <succed_n count>
- jump_n <succeed_n addr> <jump count>
- (The upper bound and `jump_n' are omitted if
- `upper_bound' is 1, though.) */
- { /* If the upper bound is > 1, we need to insert
- more at the end of the loop. */
- unsigned nbytes = 10 + (upper_bound > 1) * 10;
- GET_BUFFER_SPACE (nbytes);
- /* Initialize lower bound of the `succeed_n', even
- though it will be set during matching by its
- attendant `set_number_at' (inserted next),
- because `re_compile_fastmap' needs to know.
- Jump to the `jump_n' we might insert below. */
- INSERT_JUMP2 (succeed_n, laststart,
- b + 5 + (upper_bound > 1) * 5,
- /* Code to initialize the lower bound. Insert
- before the `succeed_n'. The `5' is the last two
- bytes of this `set_number_at', plus 3 bytes of
- the following `succeed_n'. */
- insert_op2 (set_number_at, laststart, 5, lower_bound, b);
- { /* More than one repetition is allowed, so
- append a backward jump to the `succeed_n'
- that starts this interval.
- When we've reached this during matching,
- we'll have matched the interval once, so
- jump back only `upper_bound - 1' times. */
- STORE_JUMP2 (jump_n, b, laststart + 5,
- /* The location we want to set is the second
- parameter of the `jump_n'; that is `b-2' as
- an absolute address. `laststart' will be
- the `set_number_at' we're about to insert;
- `laststart+3' the number to set, the source
- for the relative address. But we are
- inserting into the middle of the pattern --
- so everything is getting moved up by 5.
- Conclusion: (b - 2) - (laststart + 3) + 5,
- We insert this at the beginning of the loop
- so that if we fail during matching, we'll
- reinitialize the bounds. */
- insert_op2 (set_number_at, laststart, b - laststart,
- /* If an invalid interval, match the characters as literals. */
- /* normal_char and normal_backslash need `c'. */
- if (!(syntax & RE_NO_BK_BRACES))
- if (p > pattern && p[-1] == '\\')
- /* There is no way to specify the before_dot and after_dot
- operators. rms says this is ok. --karl */
- BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]);
- BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]);
- BUF_PUSH (notwordchar);
- BUF_PUSH (notwordbound);
- case '1': case '2': case '3': case '4': case '5':
- case '6': case '7': case '8': case '9':
- if (syntax & RE_NO_BK_REFS)
- /* Can't back reference to a subexpression if inside of it. */
- if (group_in_compile_stack (compile_stack, c1))
- BUF_PUSH_2 (duplicate, c1);
- if (syntax & RE_BK_PLUS_QM)
- /* You might think it would be useful for \ to mean
- not to translate; but if we don't translate it
- it will never match anything. */
- /* Expects the character in `c'. */
- /* If no exactn currently being built. */
- /* If last exactn not at current position. */
- || pending_exact + *pending_exact + 1 != b
- /* We have only one byte following the exactn for the count. */
- || *pending_exact == (1 << BYTEWIDTH) - 1
- /* If followed by a repetition operator. */
- || *p == '*' || *p == '^'
- || ((syntax & RE_BK_PLUS_QM)
- ? *p == '\\' && (p[1] == '+' || p[1] == '?')
- : (*p == '+' || *p == '?'))
- || ((syntax & RE_INTERVALS)
- && ((syntax & RE_NO_BK_BRACES)
- : (p[0] == '\\' && p[1] == '{'))))
- /* Start building a new exactn. */
- BUF_PUSH_2 (exactn, 0);
- } /* while p != pend */
- /* Through the pattern now. */
- STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
- if (!COMPILE_STACK_EMPTY)
- free (compile_stack.stack);
- /* We have succeeded; set the length of the buffer. */
- bufp->used = b - bufp->buffer;
- DEBUG_PRINT1 ("\nCompiled pattern: ");
- print_compiled_pattern (bufp);
-/* Subroutines for `regex_compile'. */
-/* Store OP at LOC followed by two-byte integer parameter ARG. */
-store_op1 (op, loc, arg)
- *loc = (unsigned char) op;
- STORE_NUMBER (loc + 1, arg);
-/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */
-store_op2 (op, loc, arg1, arg2)
- *loc = (unsigned char) op;
- STORE_NUMBER (loc + 1, arg1);
- STORE_NUMBER (loc + 3, arg2);
-/* Copy the bytes from LOC to END to open up three bytes of space at LOC
- for OP followed by two-byte integer parameter ARG. */
-insert_op1 (op, loc, arg, end)
- register unsigned char *pfrom = end;
- register unsigned char *pto = end + 3;
- store_op1 (op, loc, arg);
-/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */
-insert_op2 (op, loc, arg1, arg2, end)
- register unsigned char *pfrom = end;
- register unsigned char *pto = end + 5;
- store_op2 (op, loc, arg1, arg2);
-/* P points to just after a ^ in PATTERN. Return true if that ^ comes
- after an alternative or a begin-subexpression. We assume there is at
- least one character before the ^. */
-at_begline_loc_p (pattern, p, syntax)
- const char *pattern, *p;
- const char *prev = p - 2;
- boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\';
- /* After a subexpression? */
- (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash))
- /* After an alternative? */
- || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash));
-/* The dual of at_begline_loc_p. This one is for $. We assume there is
- at least one character after the $, i.e., `P < PEND'. */
-at_endline_loc_p (p, pend, syntax)
- boolean next_backslash = *next == '\\';
- const char *next_next = p + 1 < pend ? p + 1 : NULL;
- /* Before a subexpression? */
- (syntax & RE_NO_BK_PARENS ? *next == ')'
- : next_backslash && next_next && *next_next == ')')
- /* Before an alternative? */
- || (syntax & RE_NO_BK_VBAR ? *next == '|'
- : next_backslash && next_next && *next_next == '|');
-/* Returns true if REGNUM is in one of COMPILE_STACK's elements and
-group_in_compile_stack (compile_stack, regnum)
- compile_stack_type compile_stack;
- for (this_element = compile_stack.avail - 1;
- if (compile_stack.stack[this_element].regnum == regnum)
-/* Read the ending character of a range (in a bracket expression) from the
- uncompiled pattern *P_PTR (which ends at PEND). We assume the
- starting character is in `P[-2]'. (`P[-1]' is the character `-'.)
- Then we set the translation of all bits between the starting and
- ending characters (inclusive) in the compiled pattern B.
- We use these short variable names so we can use the same macros as
- `regex_compile' itself. */
-compile_range (p_ptr, pend, translate, syntax, b)
- const char **p_ptr, *pend;
- const char *p = *p_ptr;
- int range_start, range_end;
- /* Even though the pattern is a signed `char *', we need to fetch
- with unsigned char *'s; if the high bit of the pattern character
- is set, the range endpoints will be negative if we fetch using a
- We also want to fetch the endpoints without translating them; the
- appropriate translation is done in the bit-setting loop below. */
- range_start = ((unsigned char *) p)[-2];
- range_end = ((unsigned char *) p)[0];
- /* Have to increment the pointer into the pattern string, so the
- caller isn't still at the ending character. */
- /* If the start is after the end, the range is empty. */
- if (range_start > range_end)
- return syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR;
- /* Here we see why `this_char' has to be larger than an `unsigned
- char' -- the range is inclusive, so if `range_end' == 0xff
- (assuming 8-bit characters), we would otherwise go into an infinite
- loop, since all characters <= 0xff. */
- for (this_char = range_start; this_char <= range_end; this_char++)
- SET_LIST_BIT (TRANSLATE (this_char));
-/* Failure stack declarations and macros; both re_compile_fastmap and
- re_match_2 use a failure stack. These have to be macros because of
-/* Number of failure points for which to initially allocate space
- when matching. If this number is exceeded, we allocate more
- space, so it is not a hard limit. */
-#ifndef INIT_FAILURE_ALLOC
-#define INIT_FAILURE_ALLOC 5
-/* Roughly the maximum number of failure points on the stack. Would be
- exactly that if always used MAX_FAILURE_SPACE each time we failed.
- This is a variable only so users of regex can assign to it; we never
- change it ourselves. */
-int re_max_failures = 2000;
-typedef const unsigned char *fail_stack_elt_t;
- fail_stack_elt_t *stack;
- unsigned avail; /* Offset of next open position. */
-#define FAIL_STACK_EMPTY() (fail_stack.avail == 0)
-#define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0)
-#define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size)
-#define FAIL_STACK_TOP() (fail_stack.stack[fail_stack.avail])
-/* Initialize `fail_stack'. Do `return -2' if the alloc fails. */
-#define INIT_FAIL_STACK() \
- fail_stack.stack = (fail_stack_elt_t *) \
- REGEX_ALLOCATE (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \
- if (fail_stack.stack == NULL) \
- fail_stack.size = INIT_FAILURE_ALLOC; \
- fail_stack.avail = 0; \
-/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items.
- Return 1 if succeeds, and 0 if either ran out of memory
- allocating space for it or it was already too large.
- REGEX_REALLOCATE requires `destination' be declared. */
-#define DOUBLE_FAIL_STACK(fail_stack) \
- ((fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS \
- : ((fail_stack).stack = (fail_stack_elt_t *) \
- REGEX_REALLOCATE ((fail_stack).stack, \
- (fail_stack).size * sizeof (fail_stack_elt_t), \
- ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)), \
- (fail_stack).stack == NULL \
- : ((fail_stack).size <<= 1, \
-/* Push PATTERN_OP on FAIL_STACK.
- Return 1 if was able to do so and 0 if ran out of memory allocating
-#define PUSH_PATTERN_OP(pattern_op, fail_stack) \
- && !DOUBLE_FAIL_STACK (fail_stack)) \
- : ((fail_stack).stack[(fail_stack).avail++] = pattern_op, \
-/* This pushes an item onto the failure stack. Must be a four-byte
- value. Assumes the variable `fail_stack'. Probably should only
- be called from within `PUSH_FAILURE_POINT'. */
-#define PUSH_FAILURE_ITEM(item) \
- fail_stack.stack[fail_stack.avail++] = (fail_stack_elt_t) item
-/* The complement operation. Assumes `fail_stack' is nonempty. */
-#define POP_FAILURE_ITEM() fail_stack.stack[--fail_stack.avail]
-/* Used to omit pushing failure point id's when we're not debugging. */
-#define DEBUG_PUSH PUSH_FAILURE_ITEM
-#define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_ITEM ()
-#define DEBUG_PUSH(item)
-#define DEBUG_POP(item_addr)
-/* Push the information about the state we will need
- if we ever fail back to it.
- Requires variables fail_stack, regstart, regend, reg_info, and
- num_regs be declared. DOUBLE_FAIL_STACK requires `destination' be
- Does `return FAILURE_CODE' if runs out of memory. */
-#define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \
- /* Must be int, so when we don't save any registers, the arithmetic \
- of 0 + -1 isn't done as unsigned. */ \
- DEBUG_STATEMENT (failure_id++); \
- DEBUG_STATEMENT (nfailure_points_pushed++); \
- DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \
- DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\
- DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\
- DEBUG_PRINT2 (" slots needed: %d\n", NUM_FAILURE_ITEMS); \
- DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \
- /* Ensure we have enough space allocated for what we will push. */ \
- while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \
- if (!DOUBLE_FAIL_STACK (fail_stack)) \
- DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \
- DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\
- /* Push the info, starting with the registers. */ \
- for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \
- DEBUG_PRINT2 (" Pushing reg: %d\n", this_reg); \
- DEBUG_STATEMENT (num_regs_pushed++); \
- DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \
- PUSH_FAILURE_ITEM (regstart[this_reg]); \
- DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \
- PUSH_FAILURE_ITEM (regend[this_reg]); \
- DEBUG_PRINT2 (" info: 0x%x\n ", reg_info[this_reg]); \
- DEBUG_PRINT2 (" match_null=%d", \
- REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \
- DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \
- DEBUG_PRINT2 (" matched_something=%d", \
- MATCHED_SOMETHING (reg_info[this_reg])); \
- DEBUG_PRINT2 (" ever_matched=%d", \
- EVER_MATCHED_SOMETHING (reg_info[this_reg])); \
- PUSH_FAILURE_ITEM (reg_info[this_reg].word); \
- DEBUG_PRINT2 (" Pushing low active reg: %d\n", lowest_active_reg);\
- PUSH_FAILURE_ITEM (lowest_active_reg); \
- DEBUG_PRINT2 (" Pushing high active reg: %d\n", highest_active_reg);\
- PUSH_FAILURE_ITEM (highest_active_reg); \
- DEBUG_PRINT2 (" Pushing pattern 0x%x: ", pattern_place); \
- DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \
- PUSH_FAILURE_ITEM (pattern_place); \
- DEBUG_PRINT2 (" Pushing string 0x%x: `", string_place); \
- DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \
- DEBUG_PRINT1 ("'\n"); \
- PUSH_FAILURE_ITEM (string_place); \
- DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \
- DEBUG_PUSH (failure_id); \
-/* This is the number of items that are pushed and popped on the stack
-/* Individual items aside from the registers. */
-#define NUM_NONREG_ITEMS 5 /* Includes failure point id. */
-#define NUM_NONREG_ITEMS 4
-/* We push at most this many items on the stack. */
-#define MAX_FAILURE_ITEMS ((num_regs - 1) * NUM_REG_ITEMS + NUM_NONREG_ITEMS)
-/* We actually push this many items. */
-#define NUM_FAILURE_ITEMS \
- ((highest_active_reg - lowest_active_reg + 1) * NUM_REG_ITEMS \
-/* How many items can still be added to the stack without overflowing it. */
-#define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail)
-/* Pops what PUSH_FAIL_STACK pushes.
- We restore into the parameters, all of which should be lvalues:
- STR -- the saved data position.
- PAT -- the saved pattern position.
- LOW_REG, HIGH_REG -- the highest and lowest active registers.
- REGSTART, REGEND -- arrays of string positions.
- REG_INFO -- array of information about each subexpression.
- Also assumes the variables `fail_stack' and (if debugging), `bufp',
- `pend', `string1', `size1', `string2', and `size2'. */
-#define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\
- DEBUG_STATEMENT (fail_stack_elt_t failure_id;) \
- const unsigned char *string_temp; \
- assert (!FAIL_STACK_EMPTY ()); \
- /* Remove failure points and point to how many regs pushed. */ \
- DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \
- DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \
- DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \
- assert (fail_stack.avail >= NUM_NONREG_ITEMS); \
- DEBUG_POP (&failure_id); \
- DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \
- /* If the saved string location is NULL, it came from an \
- on_failure_keep_string_jump opcode, and we want to throw away the \
- saved NULL, thus retaining our current position in the string. */ \
- string_temp = POP_FAILURE_ITEM (); \
- if (string_temp != NULL) \
- str = (const char *) string_temp; \
- DEBUG_PRINT2 (" Popping string 0x%x: `", str); \
- DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \
- DEBUG_PRINT1 ("'\n"); \
- pat = (unsigned char *) POP_FAILURE_ITEM (); \
- DEBUG_PRINT2 (" Popping pattern 0x%x: ", pat); \
- DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \
- /* Restore register info. */ \
- high_reg = (unsigned) POP_FAILURE_ITEM (); \
- DEBUG_PRINT2 (" Popping high active reg: %d\n", high_reg); \
- low_reg = (unsigned) POP_FAILURE_ITEM (); \
- DEBUG_PRINT2 (" Popping low active reg: %d\n", low_reg); \
- for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \
- DEBUG_PRINT2 (" Popping reg: %d\n", this_reg); \
- reg_info[this_reg].word = POP_FAILURE_ITEM (); \
- DEBUG_PRINT2 (" info: 0x%x\n", reg_info[this_reg]); \
- regend[this_reg] = (const char *) POP_FAILURE_ITEM (); \
- DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \
- regstart[this_reg] = (const char *) POP_FAILURE_ITEM (); \
- DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \
- DEBUG_STATEMENT (nfailure_points_popped++); \
-} /* POP_FAILURE_POINT */
-/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in
- BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible
- characters can start a string that matches the pattern. This fastmap
- is used by re_search to skip quickly over impossible starting points.
- The caller must supply the address of a (1 << BYTEWIDTH)-byte data
- We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in
- Returns 0 if we succeed, -2 if an internal error. */
-re_compile_fastmap (bufp)
- struct re_pattern_buffer *bufp;
- fail_stack_type fail_stack;
- /* We don't push any register information onto the failure stack. */
- register char *fastmap = bufp->fastmap;
- unsigned char *pattern = bufp->buffer;
- unsigned long size = bufp->used;
- const unsigned char *p = pattern;
- register unsigned char *pend = pattern + size;
- /* Assume that each path through the pattern can be null until
- proven otherwise. We set this false at the bottom of switch
- statement, to which we get only if a particular path doesn't
- match the empty string. */
- boolean path_can_be_null = true;
- /* We aren't doing a `succeed_n' to begin with. */
- boolean succeed_n_p = false;
- assert (fastmap != NULL && p != NULL);
- bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */
- bufp->fastmap_accurate = 1; /* It will be when we're done. */
- while (p != pend || !FAIL_STACK_EMPTY ())
- bufp->can_be_null |= path_can_be_null;
- /* Reset for next path. */
- path_can_be_null = true;
- p = fail_stack.stack[--fail_stack.avail];
- /* We should never be about to go beyond the end of the pattern. */
- switch ((int) ((re_opcode_t) *p++))
- switch ((re_opcode_t) *p++)
- /* I guess the idea here is to simply not bother with a fastmap
- if a backreference is used, since it's too hard to figure out
- the fastmap for the corresponding group. Setting
- `can_be_null' stops `re_search_2' from using the fastmap, so
- /* Following are the cases which match a character. These end
- for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
- if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))
- /* Chars beyond end of map must be allowed. */
- for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++)
- for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
- if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))))
- for (j = 0; j < (1 << BYTEWIDTH); j++)
- if (SYNTAX (j) == Sword)
- for (j = 0; j < (1 << BYTEWIDTH); j++)
- if (SYNTAX (j) != Sword)
- /* `.' matches anything ... */
- for (j = 0; j < (1 << BYTEWIDTH); j++)
- /* ... except perhaps newline. */
- if (!(bufp->syntax & RE_DOT_NEWLINE))
- /* Return if we have already set `can_be_null'; if we have,
- then the fastmap is irrelevant. Something's wrong here. */
- else if (bufp->can_be_null)
- /* Otherwise, have to check alternative paths. */
- for (j = 0; j < (1 << BYTEWIDTH); j++)
- if (SYNTAX (j) == (enum syntaxcode) k)
- for (j = 0; j < (1 << BYTEWIDTH); j++)
- if (SYNTAX (j) != (enum syntaxcode) k)
- /* All cases after this match the empty string. These end with
- case push_dummy_failure:
- case dummy_failure_jump:
- EXTRACT_NUMBER_AND_INCR (j, p);
- /* Jump backward implies we just went through the body of a
- loop and matched nothing. Opcode jumped to should be
- `on_failure_jump' or `succeed_n'. Just treat it like an
- ordinary jump. For a * loop, it has pushed its failure
- point already; if so, discard that as redundant. */
- if ((re_opcode_t) *p != on_failure_jump
- && (re_opcode_t) *p != succeed_n)
- EXTRACT_NUMBER_AND_INCR (j, p);
- /* If what's on the stack is where we are now, pop it. */
- if (!FAIL_STACK_EMPTY ()
- && fail_stack.stack[fail_stack.avail - 1] == p)
- case on_failure_keep_string_jump:
- handle_on_failure_jump:
- EXTRACT_NUMBER_AND_INCR (j, p);
- /* For some patterns, e.g., `(a?)?', `p+j' here points to the
- end of the pattern. We don't want to push such a point,
- since when we restore it above, entering the switch will
- increment `p' past the end of the pattern. We don't need
- to push such a point since we obviously won't find any more
- fastmap entries beyond `pend'. Such a pattern can match
- the null string, though. */
- if (!PUSH_PATTERN_OP (p + j, fail_stack))
- EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */
- /* Get to the number of times to succeed. */
- /* Increment p past the n for when k != 0. */
- EXTRACT_NUMBER_AND_INCR (k, p);
- succeed_n_p = true; /* Spaghetti code alert. */
- goto handle_on_failure_jump;
- abort (); /* We have listed all the cases. */
- /* Getting here means we have found the possible starting
- characters for one path of the pattern -- and that the empty
- string does not match. We need not follow this path further.
- Instead, look at the next alternative (remembered on the
- stack), or quit if no more. The test at the top of the loop
- path_can_be_null = false;
- /* Set `can_be_null' for the last path (also the first path, if the
- bufp->can_be_null |= path_can_be_null;
-} /* re_compile_fastmap */
-/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
- ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use
- this memory for recording register information. STARTS and ENDS
- must be allocated using the malloc library routine, and must each
- be at least NUM_REGS * sizeof (regoff_t) bytes long.
- If NUM_REGS == 0, then subsequent matches should allocate their own
- Unless this function is called, the first search or match using
- PATTERN_BUFFER will allocate its own register data, without
- freeing the old data. */
-re_set_registers (bufp, regs, num_regs, starts, ends)
- struct re_pattern_buffer *bufp;
- struct re_registers *regs;
- regoff_t *starts, *ends;
- bufp->regs_allocated = REGS_REALLOCATE;
- regs->num_regs = num_regs;
- bufp->regs_allocated = REGS_UNALLOCATED;
- regs->start = regs->end = (regoff_t) 0;
-/* Searching routines. */
-/* Like re_search_2, below, but only one string is specified, and
- doesn't let you say where to stop matching. */
-re_search (bufp, string, size, startpos, range, regs)
- struct re_pattern_buffer *bufp;
- int size, startpos, range;
- struct re_registers *regs;
- return re_search_2 (bufp, NULL, 0, string, size, startpos, range,
-/* Using the compiled pattern in BUFP->buffer, first tries to match the
- virtual concatenation of STRING1 and STRING2, starting first at index
- STARTPOS, then at STARTPOS + 1, and so on.
- STRING1 and STRING2 have length SIZE1 and SIZE2, respectively.
- RANGE is how far to scan while trying to match. RANGE = 0 means try
- only at STARTPOS; in general, the last start tried is STARTPOS +
- In REGS, return the indices of the virtual concatenation of STRING1
- and STRING2 that matched the entire BUFP->buffer and its contained
- Do not consider matching one past the index STOP in the virtual
- concatenation of STRING1 and STRING2.
- We return either the position in the strings at which the match was
- found, -1 if no match, or -2 if error (such as failure
-re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop)
- struct re_pattern_buffer *bufp;
- const char *string1, *string2;
- struct re_registers *regs;
- register char *fastmap = bufp->fastmap;
- register char *translate = bufp->translate;
- int total_size = size1 + size2;
- int endpos = startpos + range;
- /* Check for out-of-range STARTPOS. */
- if (startpos < 0 || startpos > total_size)
- /* Fix up RANGE if it might eventually take us outside
- the virtual concatenation of STRING1 and STRING2. */
- else if (endpos > total_size)
- range = total_size - startpos;
- /* If the search isn't to be a backwards one, don't waste time in a
- search for a pattern that must be anchored. */
- if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == begbuf && range > 0)
- /* Update the fastmap now if not correct already. */
- if (fastmap && !bufp->fastmap_accurate)
- if (re_compile_fastmap (bufp) == -2)
- /* Loop through the string, looking for a place to start matching. */
- /* If a fastmap is supplied, skip quickly over characters that
- cannot be the start of a match. If the pattern can match the
- null string, however, we don't need to skip characters; we want
- the first null string. */
- if (fastmap && startpos < total_size && !bufp->can_be_null)
- if (range > 0) /* Searching forwards. */
- register const char *d;
- if (startpos < size1 && startpos + range >= size1)
- lim = range - (size1 - startpos);
- d = (startpos >= size1 ? string2 - size1 : string1) + startpos;
- /* Written out as an if-else to avoid testing `translate'
- && !fastmap[(unsigned char)
- translate[(unsigned char) *d++]])
- while (range > lim && !fastmap[(unsigned char) *d++])
- startpos += irange - range;
- else /* Searching backwards. */
- register char c = (size1 == 0 || startpos >= size1
- ? string2[startpos - size1]
- if (!fastmap[(unsigned char) TRANSLATE (c)])
- /* If can't match the null string, and that's all we have left, fail. */
- if (range >= 0 && startpos == total_size && fastmap
- val = re_match_2 (bufp, string1, size1, string2, size2,
-/* Declarations and macros for re_match_2. */
-static int bcmp_translate ();
-static boolean alt_match_null_string_p (),
- common_op_match_null_string_p (),
- group_match_null_string_p ();
-/* Structure for per-register (a.k.a. per-group) information.
- This must not be longer than one word, because we push this value
- onto the failure stack. Other register information, such as the
- starting and ending positions (which are addresses), and the list of
- inner groups (which is a bits list) are maintained in separate
- We are making a (strictly speaking) nonportable assumption here: that
- the compiler will pack our bit fields into something that fits into
- the type of `word', i.e., is something that fits into one item on the
- /* This field is one if this group can match the empty string,
- zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */
-#define MATCH_NULL_UNSET_VALUE 3
- unsigned match_null_string_p : 2;
- unsigned is_active : 1;
- unsigned matched_something : 1;
- unsigned ever_matched_something : 1;
-#define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p)
-#define IS_ACTIVE(R) ((R).bits.is_active)
-#define MATCHED_SOMETHING(R) ((R).bits.matched_something)
-#define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something)
-/* Call this when have matched a real character; it sets `matched' flags
- for the subexpressions which we are currently inside. Also records
- that those subexprs have matched. */
-#define SET_REGS_MATCHED() \
- for (r = lowest_active_reg; r <= highest_active_reg; r++) \
- MATCHED_SOMETHING (reg_info[r]) \
- = EVER_MATCHED_SOMETHING (reg_info[r]) \
-/* This converts PTR, a pointer into one of the search strings `string1'
- and `string2' into an offset from the beginning of that string. */
-#define POINTER_TO_OFFSET(ptr) \
- (FIRST_STRING_P (ptr) ? (ptr) - string1 : (ptr) - string2 + size1)
-/* Registers are set to a sentinel when they haven't yet matched. */
-#define REG_UNSET_VALUE ((char *) -1)
-#define REG_UNSET(e) ((e) == REG_UNSET_VALUE)
-/* Macros for dealing with the split strings in re_match_2. */
-#define MATCHING_IN_FIRST_STRING (dend == end_match_1)
-/* Call before fetching a character with *d. This switches over to
- string2 if necessary. */
- /* End of string2 => fail. */ \
- if (dend == end_match_2) \
- /* End of string1 => advance to string2. */ \
-/* Test if at very beginning or at very end of the virtual concatenation
- of `string1' and `string2'. If only one string, it's `string2'. */
-#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2)
-#define AT_STRINGS_END(d) ((d) == end2)
-/* Test if D points to a character which is word-constituent. We have
- two special cases to check for: if past the end of string1, look at
- the first character in string2; and if before the beginning of
- string2, look at the last character in string1. */
- (SYNTAX ((d) == end1 ? *string2 \
- : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \
-/* Test if the character before D and the one at D differ with respect
- to being word-constituent. */
-#define AT_WORD_BOUNDARY(d) \
- (AT_STRINGS_BEG (d) || AT_STRINGS_END (d) \
- || WORDCHAR_P (d - 1) != WORDCHAR_P (d))
-/* Free everything we malloc. */
-#define FREE_VAR(var) if (var) free (var); var = NULL
-#define FREE_VARIABLES() \
- FREE_VAR (fail_stack.stack); \
- FREE_VAR (old_regstart); \
- FREE_VAR (old_regend); \
- FREE_VAR (best_regstart); \
- FREE_VAR (best_regend); \
- FREE_VAR (reg_dummy); \
- FREE_VAR (reg_info_dummy); \
-#else /* not REGEX_MALLOC */
-/* Some MIPS systems (at least) want this to free alloca'd storage. */
-#define FREE_VARIABLES() alloca (0)
-#endif /* not REGEX_MALLOC */
-/* These values must meet several constraints. They must not be valid
- register values; since we have a limit of 255 registers (because
- we use only one byte in the pattern for the register number), we can
- use numbers larger than 255. They must differ by 1, because of
- NUM_FAILURE_ITEMS above. And the value for the lowest register must
- be larger than the value for the highest register, so we do not try
- to actually save any registers when none are active. */
-#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH)
-#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1)
-/* Matching routines. */
-#ifndef emacs /* Emacs never uses this. */
-/* re_match is like re_match_2 except it takes only a single string. */
-re_match (bufp, string, size, pos, regs)
- struct re_pattern_buffer *bufp;
- struct re_registers *regs;
- return re_match_2 (bufp, NULL, 0, string, size, pos, regs, size);
-/* re_match_2 matches the compiled pattern in BUFP against the
- the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1
- and SIZE2, respectively). We start matching at POS, and stop
- If REGS is non-null and the `no_sub' field of BUFP is nonzero, we
- store offsets for the substring each group matched in REGS. See the
- documentation for exactly how many groups we fill.
- We return -1 if no match, -2 if an internal error (such as the
- failure stack overflowing). Otherwise, we return the length of the
-re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
- struct re_pattern_buffer *bufp;
- const char *string1, *string2;
- struct re_registers *regs;
- /* General temporaries. */
- /* Just past the end of the corresponding string. */
- const char *end1, *end2;
- /* Pointers into string1 and string2, just past the last characters in
- each to consider matching. */
- const char *end_match_1, *end_match_2;
- /* Where we are in the data, and the end of the current string. */
- /* Where we are in the pattern, and the end of the pattern. */
- unsigned char *p = bufp->buffer;
- register unsigned char *pend = p + bufp->used;
- /* We use this to map every character in the string. */
- char *translate = bufp->translate;
- /* Failure point stack. Each place that can handle a failure further
- down the line pushes a failure point on this stack. It consists of
- restart, regend, and reg_info for all registers corresponding to
- the subexpressions we're currently inside, plus the number of such
- registers, and, finally, two char *'s. The first char * is where
- to resume scanning the pattern; the second one is where to resume
- scanning the strings. If the latter is zero, the failure point is
- a ``dummy''; if a failure happens and the failure point is a dummy,
- it gets discarded and the next next one is tried. */
- fail_stack_type fail_stack;
- static unsigned failure_id = 0;
- unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0;
- /* We fill all the registers internally, independent of what we
- return, for use in backreferences. The number here includes
- an element for register zero. */
- unsigned num_regs = bufp->re_nsub + 1;
- /* The currently active registers. */
- unsigned lowest_active_reg = NO_LOWEST_ACTIVE_REG;
- unsigned highest_active_reg = NO_HIGHEST_ACTIVE_REG;
- /* Information on the contents of registers. These are pointers into
- the input strings; they record just what was matched (on this
- attempt) by a subexpression part of the pattern, that is, the
- regnum-th regstart pointer points to where in the pattern we began
- matching and the regnum-th regend points to right after where we
- stopped matching the regnum-th subexpression. (The zeroth register
- keeps track of what the whole pattern matches.) */
- const char **regstart=NULL, **regend=NULL;
- /* If a group that's operated upon by a repetition operator fails to
- match anything, then the register for its start will need to be
- restored because it will have been set to wherever in the string we
- are when we last see its open-group operator. Similarly for a
- const char **old_regstart=NULL, **old_regend=NULL;
- /* The is_active field of reg_info helps us keep track of which (possibly
- nested) subexpressions we are currently in. The matched_something
- field of reg_info[reg_num] helps us tell whether or not we have
- matched any of the pattern so far this time through the reg_num-th
- subexpression. These two fields get reset each time through any
- loop their register is in. */
- register_info_type *reg_info=NULL;
- /* The following record the register info as found in the above
- variables when we find a match better than any we've seen before.
- This happens as we backtrack through the failure points, which in
- turn happens only if we have not yet matched the entire string. */
- unsigned best_regs_set = false;
- const char **best_regstart=NULL, **best_regend=NULL;
- /* Logically, this is `best_regend[0]'. But we don't want to have to
- allocate space for that if we're not allocating space for anything
- else (see below). Also, we never need info about register 0 for
- any of the other register vectors, and it seems rather a kludge to
- treat `best_regend' differently than the rest. So we keep track of
- the end of the best match so far in a separate variable. We
- initialize this to NULL so that when we backtrack the first time
- and need to test it, it's not garbage. */
- const char *match_end = NULL;
- /* Used when we pop values we don't care about. */
- const char **reg_dummy=NULL;
- register_info_type *reg_info_dummy=NULL;
- /* Counts the total number of registers pushed. */
- unsigned num_regs_pushed = 0;
- DEBUG_PRINT1 ("\n\nEntering re_match_2.\n");
- /* Do not bother to initialize all the register variables if there are
- no groups in the pattern, as it takes a fair amount of time. If
- there are groups, we include space for register 0 (the whole
- pattern), even though we never use it, since it simplifies the
- array indexing. We should fix this. */
- regstart = REGEX_TALLOC (num_regs, const char *);
- regend = REGEX_TALLOC (num_regs, const char *);
- old_regstart = REGEX_TALLOC (num_regs, const char *);
- old_regend = REGEX_TALLOC (num_regs, const char *);
- best_regstart = REGEX_TALLOC (num_regs, const char *);
- best_regend = REGEX_TALLOC (num_regs, const char *);
- reg_info = REGEX_TALLOC (num_regs, register_info_type);
- reg_dummy = REGEX_TALLOC (num_regs, const char *);
- reg_info_dummy = REGEX_TALLOC (num_regs, register_info_type);
- if (!(regstart && regend && old_regstart && old_regend && reg_info
- && best_regstart && best_regend && reg_dummy && reg_info_dummy))
- /* We must initialize all our variables to NULL, so that
- `FREE_VARIABLES' doesn't try to free them. */
- regstart = regend = old_regstart = old_regend = best_regstart
- = best_regend = reg_dummy = NULL;
- reg_info = reg_info_dummy = (register_info_type *) NULL;
-#endif /* REGEX_MALLOC */
- /* The starting position is bogus. */
- if (pos < 0 || pos > size1 + size2)
- /* Initialize subexpression text positions to -1 to mark ones that no
- start_memory/stop_memory has been seen for. Also initialize the
- register information struct. */
- for (mcnt = 1; mcnt < num_regs; mcnt++)
- regstart[mcnt] = regend[mcnt]
- = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE;
- REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE;
- IS_ACTIVE (reg_info[mcnt]) = 0;
- MATCHED_SOMETHING (reg_info[mcnt]) = 0;
- EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0;
- /* We move `string1' into `string2' if the latter's empty -- but not if
- if (size2 == 0 && string1 != NULL)
- end1 = string1 + size1;
- end2 = string2 + size2;
- /* Compute where to stop matching, within the two strings. */
- end_match_1 = string1 + stop;
- end_match_2 = string2 + stop - size1;
- /* `p' scans through the pattern as `d' scans through the data.
- `dend' is the end of the input string that `d' points within. `d'
- is advanced into the following input string whenever necessary, but
- this happens before fetching; therefore, at the beginning of the
- loop, `d' can be pointing at the end of a string, but it cannot
- if (size1 > 0 && pos <= size1)
- d = string2 + pos - size1;
- DEBUG_PRINT1 ("The compiled pattern is: ");
- DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend);
- DEBUG_PRINT1 ("The string to match is: `");
- DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2);
- /* This loops over pattern commands. It exits by returning from the
- function if the match is complete, or it drops through if the match
- fails at this starting point in the input data. */
- DEBUG_PRINT2 ("\n0x%x: ", p);
- { /* End of pattern means we might have succeeded. */
- DEBUG_PRINT1 ("end of pattern ... ");
- /* If we haven't matched the entire string, and we want the
- longest match, try backtracking. */
- DEBUG_PRINT1 ("backtracking.\n");
- if (!FAIL_STACK_EMPTY ())
- { /* More failure points to try. */
- boolean same_str_p = (FIRST_STRING_P (match_end)
- == MATCHING_IN_FIRST_STRING);
- /* If exceeds best match so far, save it. */
- || (same_str_p && d > match_end)
- || (!same_str_p && !MATCHING_IN_FIRST_STRING))
- DEBUG_PRINT1 ("\nSAVING match as best so far.\n");
- for (mcnt = 1; mcnt < num_regs; mcnt++)
- best_regstart[mcnt] = regstart[mcnt];
- best_regend[mcnt] = regend[mcnt];
- /* If no failure points, don't restore garbage. */
- else if (best_regs_set)
- /* Restore best match. It may happen that `dend ==
- end_match_1' while the restored d is in string2.
- For example, the pattern `x.*y.*z' against the
- strings `x-' and `y-z-', if the two strings are
- not consecutive in memory. */
- DEBUG_PRINT1 ("Restoring best registers.\n");
- dend = ((d >= string1 && d <= end1)
- ? end_match_1 : end_match_2);
- for (mcnt = 1; mcnt < num_regs; mcnt++)
- regstart[mcnt] = best_regstart[mcnt];
- regend[mcnt] = best_regend[mcnt];
- } /* d != end_match_2 */
- DEBUG_PRINT1 ("Accepting match.\n");
- /* If caller wants register contents data back, do it. */
- if (regs && !bufp->no_sub)
- /* Have the register data arrays been allocated? */
- if (bufp->regs_allocated == REGS_UNALLOCATED)
- { /* No. So allocate them with malloc. We need one
- extra element beyond `num_regs' for the `-1' marker
- regs->num_regs = MAX (RE_NREGS, num_regs + 1);
- regs->start = TALLOC (regs->num_regs, regoff_t);
- regs->end = TALLOC (regs->num_regs, regoff_t);
- if (regs->start == NULL || regs->end == NULL)
- bufp->regs_allocated = REGS_REALLOCATE;
- else if (bufp->regs_allocated == REGS_REALLOCATE)
- { /* Yes. If we need more elements than were already
- allocated, reallocate them. If we need fewer, just
- if (regs->num_regs < num_regs + 1)
- regs->num_regs = num_regs + 1;
- RETALLOC (regs->start, regs->num_regs, regoff_t);
- RETALLOC (regs->end, regs->num_regs, regoff_t);
- if (regs->start == NULL || regs->end == NULL)
- assert (bufp->regs_allocated == REGS_FIXED);
- /* Convert the pointer data in `regstart' and `regend' to
- indices. Register zero has to be set differently,
- since we haven't kept track of any info for it. */
- if (regs->num_regs > 0)
- regs->end[0] = (MATCHING_IN_FIRST_STRING ? d - string1
- : d - string2 + size1);
- /* Go through the first `min (num_regs, regs->num_regs)'
- registers, since that is all we initialized. */
- for (mcnt = 1; mcnt < MIN (num_regs, regs->num_regs); mcnt++)
- if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt]))
- regs->start[mcnt] = regs->end[mcnt] = -1;
- regs->start[mcnt] = POINTER_TO_OFFSET (regstart[mcnt]);
- regs->end[mcnt] = POINTER_TO_OFFSET (regend[mcnt]);
- /* If the regs structure we return has more elements than
- were in the pattern, set the extra elements to -1. If
- we (re)allocated the registers, this is the case,
- because we always allocate enough to have at least one
- for (mcnt = num_regs; mcnt < regs->num_regs; mcnt++)
- regs->start[mcnt] = regs->end[mcnt] = -1;
- } /* regs && !bufp->no_sub */
- DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n",
- nfailure_points_pushed, nfailure_points_popped,
- nfailure_points_pushed - nfailure_points_popped);
- DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed);
- mcnt = d - pos - (MATCHING_IN_FIRST_STRING
- DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt);
- /* Otherwise match next pattern command. */
- switch ((int) ((re_opcode_t) *p++))
- switch ((re_opcode_t) *p++)
- /* Ignore these. Used to ignore the n of succeed_n's which
- currently have n == 0. */
- DEBUG_PRINT1 ("EXECUTING no_op.\n");
- /* Match the next n pattern characters exactly. The following
- byte in the pattern defines n, and the n bytes after that
- are the characters to match. */
- DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt);
- /* This is written out as an if-else so we don't waste time
- testing `translate' inside the loop. */
- if (translate[(unsigned char) *d++] != (char) *p++)
- if (*d++ != (char) *p++) goto fail;
- /* Match any character except possibly a newline or a null. */
- DEBUG_PRINT1 ("EXECUTING anychar.\n");
- if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n')
- || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000'))
- DEBUG_PRINT2 (" Matched `%d'.\n", *d);
- register unsigned char c;
- boolean not = (re_opcode_t) *(p - 1) == charset_not;
- DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : "");
- c = TRANSLATE (*d); /* The character to match. */
- /* Cast to `unsigned' instead of `unsigned char' in case the
- bit list is a full 32 bytes long. */
- if (c < (unsigned) (*p * BYTEWIDTH)
- && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
- /* The beginning of a group is represented by start_memory.
- The arguments are the register number in the next byte, and the
- number of groups inner to this one in the next. The text
- matched within the group is recorded (in the internal
- registers data structure) under the register number. */
- DEBUG_PRINT3 ("EXECUTING start_memory %d (%d):\n", *p, p[1]);
- /* Find out if this group can match the empty string. */
- p1 = p; /* To send to group_match_null_string_p. */
- if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE)
- REG_MATCH_NULL_STRING_P (reg_info[*p])
- = group_match_null_string_p (&p1, pend, reg_info);
- /* Save the position in the string where we were the last time
- we were at this open-group operator in case the group is
- operated upon by a repetition operator, e.g., with `(a*)*b'
- against `ab'; then we want to ignore where we are now in
- the string in case this attempt to match fails. */
- old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
- ? REG_UNSET (regstart[*p]) ? d : regstart[*p]
- DEBUG_PRINT2 (" old_regstart: %d\n",
- POINTER_TO_OFFSET (old_regstart[*p]));
- DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p]));
- IS_ACTIVE (reg_info[*p]) = 1;
- MATCHED_SOMETHING (reg_info[*p]) = 0;
- /* This is the new highest active register. */
- highest_active_reg = *p;
- /* If nothing was active before, this is the new lowest active
- if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
- lowest_active_reg = *p;
- /* Move past the register number and inner group count. */
- /* The stop_memory opcode represents the end of a group. Its
- arguments are the same as start_memory's: the register
- number, and the number of inner groups. */
- DEBUG_PRINT3 ("EXECUTING stop_memory %d (%d):\n", *p, p[1]);
- /* We need to save the string position the last time we were at
- this close-group operator in case the group is operated
- upon by a repetition operator, e.g., with `((a*)*(b*)*)*'
- against `aba'; then we want to ignore where we are now in
- the string in case this attempt to match fails. */
- old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
- ? REG_UNSET (regend[*p]) ? d : regend[*p]
- DEBUG_PRINT2 (" old_regend: %d\n",
- POINTER_TO_OFFSET (old_regend[*p]));
- DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p]));
- /* This register isn't active anymore. */
- IS_ACTIVE (reg_info[*p]) = 0;
- /* If this was the only register active, nothing is active
- if (lowest_active_reg == highest_active_reg)
- lowest_active_reg = NO_LOWEST_ACTIVE_REG;
- highest_active_reg = NO_HIGHEST_ACTIVE_REG;
- { /* We must scan for the new highest active register, since
- it isn't necessarily one less than now: consider
- (a(b)c(d(e)f)g). When group 3 ends, after the f), the
- new highest active register is 1. */
- unsigned char r = *p - 1;
- while (r > 0 && !IS_ACTIVE (reg_info[r]))
- /* If we end up at register zero, that means that we saved
- the registers as the result of an `on_failure_jump', not
- a `start_memory', and we jumped to past the innermost
- `stop_memory'. For example, in ((.)*) we save
- registers 1 and 2 as a result of the *, but when we pop
- back to the second ), we are at the stop_memory 1.
- Thus, nothing is active. */
- lowest_active_reg = NO_LOWEST_ACTIVE_REG;
- highest_active_reg = NO_HIGHEST_ACTIVE_REG;
- highest_active_reg = r;
- /* If just failed to match something this time around with a
- group that's operated on by a repetition operator, try to
- force exit from the ``loop'', and restore the register
- information for this group that we had before trying this
- if ((!MATCHED_SOMETHING (reg_info[*p])
- || (re_opcode_t) p[-3] == start_memory)
- boolean is_a_jump_n = false;
- switch ((re_opcode_t) *p1++)
- case dummy_failure_jump:
- EXTRACT_NUMBER_AND_INCR (mcnt, p1);
- /* If the next operation is a jump backwards in the pattern
- to an on_failure_jump right before the start_memory
- corresponding to this stop_memory, exit from the loop
- by forcing a failure after pushing on the stack the
- on_failure_jump's jump in the pattern, and d. */
- if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump
- && (re_opcode_t) p1[3] == start_memory && p1[4] == *p)
- /* If this group ever matched anything, then restore
- what its registers were before trying this last
- failed match, e.g., with `(a*)*b' against `ab' for
- regstart[1], and, e.g., with `((a*)*(b*)*)*'
- against `aba' for regend[3].
- Also restore the registers for inner groups for,
- e.g., `((a*)(b*))*' against `aba' (register 3 would
- otherwise get trashed). */
- if (EVER_MATCHED_SOMETHING (reg_info[*p]))
- EVER_MATCHED_SOMETHING (reg_info[*p]) = 0;
- /* Restore this and inner groups' (if any) registers. */
- for (r = *p; r < *p + *(p + 1); r++)
- regstart[r] = old_regstart[r];
- /* xx why this test? */
- if ((int) old_regend[r] >= (int) regstart[r])
- regend[r] = old_regend[r];
- EXTRACT_NUMBER_AND_INCR (mcnt, p1);
- PUSH_FAILURE_POINT (p1 + mcnt, d, -2);
- /* Move past the register number and the inner group count. */
- /* \<digit> has been turned into a `duplicate' command which is
- followed by the numeric value of <digit> as the register number. */
- register const char *d2, *dend2;
- int regno = *p++; /* Get which register to match against. */
- DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno);
- /* Can't back reference a group which we've never matched. */
- if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno]))
- /* Where in input to try to start matching. */
- /* Where to stop matching; if both the place to start and
- the place to stop matching are in the same string, then
- set to the place to stop, otherwise, for now have to use
- the end of the first string. */
- dend2 = ((FIRST_STRING_P (regstart[regno])
- == FIRST_STRING_P (regend[regno]))
- ? regend[regno] : end_match_1);
- /* If necessary, advance to next segment in register
- if (dend2 == end_match_2) break;
- if (dend2 == regend[regno]) break;
- /* End of string1 => advance to string2. */
- /* At end of register contents => success */
- if (d2 == dend2) break;
- /* If necessary, advance to next segment in data. */
- /* How many characters left in this segment to match. */
- /* Want how many consecutive characters we can match in
- one shot, so, if necessary, adjust the count. */
- /* Compare that many; failure if mismatch, else move
- ? bcmp_translate (d, d2, mcnt, translate)
- /* begline matches the empty string at the beginning of the string
- (unless `not_bol' is set in `bufp'), and, if
- `newline_anchor' is set, after newlines. */
- DEBUG_PRINT1 ("EXECUTING begline.\n");
- if (AT_STRINGS_BEG (d))
- if (!bufp->not_bol) break;
- else if (d[-1] == '\n' && bufp->newline_anchor)
- /* In all other cases, we fail. */
- /* endline is the dual of begline. */
- DEBUG_PRINT1 ("EXECUTING endline.\n");
- if (AT_STRINGS_END (d))
- if (!bufp->not_eol) break;
- /* We have to ``prefetch'' the next character. */
- else if ((d == end1 ? *string2 : *d) == '\n'
- && bufp->newline_anchor)
- /* Match at the very beginning of the data. */
- DEBUG_PRINT1 ("EXECUTING begbuf.\n");
- if (AT_STRINGS_BEG (d))
- /* Match at the very end of the data. */
- DEBUG_PRINT1 ("EXECUTING endbuf.\n");
- if (AT_STRINGS_END (d))
- /* on_failure_keep_string_jump is used to optimize `.*\n'. It
- pushes NULL as the value for the string on the stack. Then
- `pop_failure_point' will keep the current value for the
- string, instead of restoring it. To see why, consider
- matching `foo\nbar' against `.*\n'. The .* matches the foo;
- then the . fails against the \n. But the next thing we want
- to do is match the \n against the \n; if we restored the
- string value, we would be back at the foo.
- Because this is used only in specific cases, we don't need to
- check all the things that `on_failure_jump' does, to make
- sure the right things get saved on the stack. Hence we don't
- share its code. The only reason to push anything on the
- stack at all is that otherwise we would have to change
- `anychar's code to do something besides goto fail in this
- case; that seems worse than this. */
- case on_failure_keep_string_jump:
- DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump");
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt);
- PUSH_FAILURE_POINT (p + mcnt, NULL, -2);
- /* Uses of on_failure_jump:
- Each alternative starts with an on_failure_jump that points
- to the beginning of the next alternative. Each alternative
- except the last ends with a jump that in effect jumps past
- the rest of the alternatives. (They really jump to the
- ending jump of the following alternative, because tensioning
- these jumps is a hassle.)
- Repeats start with an on_failure_jump that points past both
- the repetition text and either the following jump or
- pop_failure_jump back to this on_failure_jump. */
- DEBUG_PRINT1 ("EXECUTING on_failure_jump");
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt);
- /* If this on_failure_jump comes right before a group (i.e.,
- the original * applied to a group), save the information
- for that group and all inner ones, so that if we fail back
- to this point, the group's information will be correct.
- For example, in \(a*\)*\1, we need the preceding group,
- and in \(\(a*\)b*\)\2, we need the inner group. */
- /* We can't use `p' to check ahead because we push
- a failure point to `p + mcnt' after we do this. */
- /* We need to skip no_op's before we look for the
- start_memory in case this on_failure_jump is happening as
- the result of a completed succeed_n, as in \(a\)\{1,3\}b\1
- while (p1 < pend && (re_opcode_t) *p1 == no_op)
- if (p1 < pend && (re_opcode_t) *p1 == start_memory)
- /* We have a new highest active register now. This will
- get reset at the start_memory we are about to get to,
- but we will have saved all the registers relevant to
- this repetition op, as described above. */
- highest_active_reg = *(p1 + 1) + *(p1 + 2);
- if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
- lowest_active_reg = *(p1 + 1);
- PUSH_FAILURE_POINT (p + mcnt, d, -2);
- /* A smart repeat ends with `maybe_pop_jump'.
- We change it to either `pop_failure_jump' or `jump'. */
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt);
- register unsigned char *p2 = p;
- /* Compare the beginning of the repeat with what in the
- pattern follows its end. If we can establish that there
- is nothing that they would both match, i.e., that we
- would have to backtrack because of (as in, e.g., `a*a')
- then we can change to pop_failure_jump, because we'll
- never have to backtrack.
- This is not true in the case of alternatives: in
- `(a|ab)*' we do need to backtrack to the `ab' alternative
- (e.g., if the string was `ab'). But instead of trying to
- detect that here, the alternative has put on a dummy
- failure point which is what we will end up popping. */
- /* Skip over open/close-group commands. */
- && ((re_opcode_t) *p2 == stop_memory
- || (re_opcode_t) *p2 == start_memory))
- p2 += 3; /* Skip over args, too. */
- /* If we're at the end of the pattern, we can change. */
- /* Consider what happens when matching ":\(.*\)"
- against ":/". I don't really understand this code
- p[-3] = (unsigned char) pop_failure_jump;
- (" End of pattern: change to `pop_failure_jump'.\n");
- else if ((re_opcode_t) *p2 == exactn
- || (bufp->newline_anchor && (re_opcode_t) *p2 == endline))
- register unsigned char c
- = *p2 == (unsigned char) endline ? '\n' : p2[2];
- /* p1[0] ... p1[2] are the `on_failure_jump' corresponding
- to the `maybe_finalize_jump' of this case. Examine what
- if ((re_opcode_t) p1[3] == exactn && p1[5] != c)
- p[-3] = (unsigned char) pop_failure_jump;
- DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n",
- else if ((re_opcode_t) p1[3] == charset
- || (re_opcode_t) p1[3] == charset_not)
- int not = (re_opcode_t) p1[3] == charset_not;
- if (c < (unsigned char) (p1[4] * BYTEWIDTH)
- && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
- /* `not' is equal to 1 if c would match, which means
- that we can't change to pop_failure_jump. */
- p[-3] = (unsigned char) pop_failure_jump;
- DEBUG_PRINT1 (" No match => pop_failure_jump.\n");
- p -= 2; /* Point at relative address again. */
- if ((re_opcode_t) p[-1] != pop_failure_jump)
- p[-1] = (unsigned char) jump;
- DEBUG_PRINT1 (" Match => jump.\n");
- goto unconditional_jump;
- /* Note fall through. */
- /* The end of a simple repeat has a pop_failure_jump back to
- its matching on_failure_jump, where the latter will push a
- failure point. The pop_failure_jump takes off failure
- points put on by this pop_failure_jump's matching
- on_failure_jump; we got through the pattern to here from the
- matching on_failure_jump, so didn't fail. */
- /* We need to pass separate storage for the lowest and
- highest registers, even though we don't care about the
- actual values. Otherwise, we will restore only one
- register from the stack, since lowest will == highest in
- `pop_failure_point'. */
- unsigned dummy_low_reg, dummy_high_reg;
- DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n");
- POP_FAILURE_POINT (sdummy, pdummy,
- dummy_low_reg, dummy_high_reg,
- reg_dummy, reg_dummy, reg_info_dummy);
- /* Note fall through. */
- /* Unconditionally jump (without popping any failure points). */
- EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */
- DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt);
- p += mcnt; /* Do the jump. */
- DEBUG_PRINT2 ("(to 0x%x).\n", p);
- /* We need this opcode so we can detect where alternatives end
- in `group_match_null_string_p' et al. */
- DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n");
- goto unconditional_jump;
- /* Normally, the on_failure_jump pushes a failure point, which
- then gets popped at pop_failure_jump. We will end up at
- pop_failure_jump, also, and with a pattern of, say, `a+', we
- are skipping over the on_failure_jump, so we have to push
- something meaningless for pop_failure_jump to pop. */
- case dummy_failure_jump:
- DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n");
- /* It doesn't matter what we push for the string here. What
- the code at `fail' tests is the value for the pattern. */
- PUSH_FAILURE_POINT (0, 0, -2);
- goto unconditional_jump;
- /* At the end of an alternative, we need to push a dummy failure
- point in case we are followed by a `pop_failure_jump', because
- we don't want the failure point for the alternative to be
- popped. For example, matching `(a|ab)*' against `aab'
- requires that we match the `ab' alternative. */
- case push_dummy_failure:
- DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n");
- /* See comments just above at `dummy_failure_jump' about the
- PUSH_FAILURE_POINT (0, 0, -2);
- /* Have to succeed matching what follows at least n times.
- After that, handle like `on_failure_jump'. */
- EXTRACT_NUMBER (mcnt, p + 2);
- DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt);
- /* Originally, this is how many times we HAVE to succeed. */
- STORE_NUMBER_AND_INCR (p, mcnt);
- DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p, mcnt);
- DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n", p+2);
- p[2] = (unsigned char) no_op;
- p[3] = (unsigned char) no_op;
- EXTRACT_NUMBER (mcnt, p + 2);
- DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt);
- /* Originally, this is how many times we CAN jump. */
- STORE_NUMBER (p + 2, mcnt);
- goto unconditional_jump;
- /* If don't have to jump any more, skip over the rest of command. */
- DEBUG_PRINT1 ("EXECUTING set_number_at.\n");
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt);
- STORE_NUMBER (p1, mcnt);
- DEBUG_PRINT1 ("EXECUTING wordbound.\n");
- if (AT_WORD_BOUNDARY (d))
- DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
- if (AT_WORD_BOUNDARY (d))
- DEBUG_PRINT1 ("EXECUTING wordbeg.\n");
- if (WORDCHAR_P (d) && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1)))
- DEBUG_PRINT1 ("EXECUTING wordend.\n");
- if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1)
- && (!WORDCHAR_P (d) || AT_STRINGS_END (d)))
- DEBUG_PRINT1 ("EXECUTING before_dot.\n");
- if (PTR_CHAR_POS ((unsigned char *) d) >= point)
- DEBUG_PRINT1 ("EXECUTING at_dot.\n");
- if (PTR_CHAR_POS ((unsigned char *) d) != point)
- DEBUG_PRINT1 ("EXECUTING after_dot.\n");
- if (PTR_CHAR_POS ((unsigned char *) d) <= point)
- DEBUG_PRINT1 ("EXECUTING at_dot.\n");
- if (PTR_CHAR_POS ((unsigned char *) d) + 1 != point)
-#endif /* not emacs19 */
- DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt);
- DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n");
- if (SYNTAX (*d++) != (enum syntaxcode) mcnt)
- DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt);
- DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n");
- if (SYNTAX (*d++) == (enum syntaxcode) mcnt)
- DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n");
- DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n");
- continue; /* Successfully executed one pattern command; keep going. */
- /* We goto here if a matching operation fails. */
- if (!FAIL_STACK_EMPTY ())
- { /* A restart point is known. Restore to that state. */
- DEBUG_PRINT1 ("\nFAIL:\n");
- POP_FAILURE_POINT (d, p,
- lowest_active_reg, highest_active_reg,
- regstart, regend, reg_info);
- /* If this failure point is a dummy, try the next one. */
- /* If we failed to the end of the pattern, don't examine *p. */
- boolean is_a_jump_n = false;
- /* If failed to a backwards jump that's part of a repetition
- loop, need to pop this failure point and use the next one. */
- switch ((re_opcode_t) *p)
- EXTRACT_NUMBER_AND_INCR (mcnt, p1);
- if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n)
- && (re_opcode_t) *p1 == on_failure_jump))
- if (d >= string1 && d <= end1)
- break; /* Matching at this starting point really fails. */
- goto restore_best_regs;
- return -1; /* Failure to match. */
-/* Subroutine definitions for re_match_2. */
-/* We are passed P pointing to a register number after a start_memory.
- Return true if the pattern up to the corresponding stop_memory can
- match the empty string, and false otherwise.
- If we find the matching stop_memory, sets P to point to one past its number.
- Otherwise, sets P to an undefined byte less than or equal to END.
- We don't handle duplicates properly (yet). */
-group_match_null_string_p (p, end, reg_info)
- unsigned char **p, *end;
- register_info_type *reg_info;
- /* Point to after the args to the start_memory. */
- unsigned char *p1 = *p + 2;
- /* Skip over opcodes that can match nothing, and return true or
- false, as appropriate, when we get to one that can't, or to the
- matching stop_memory. */
- switch ((re_opcode_t) *p1)
- /* Could be either a loop or a series of alternatives. */
- EXTRACT_NUMBER_AND_INCR (mcnt, p1);
- /* If the next operation is not a jump backwards in the
- /* Go through the on_failure_jumps of the alternatives,
- seeing if any of the alternatives cannot match nothing.
- The last alternative starts with only a jump,
- whereas the rest start with on_failure_jump and end
- with a jump, e.g., here is the pattern for `a|b|c':
- /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6
- /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3
- So, we have to first go through the first (n-1)
- alternatives and then deal with the last one separately. */
- /* Deal with the first (n-1) alternatives, which start
- with an on_failure_jump (see above) that jumps to right
- past a jump_past_alt. */
- while ((re_opcode_t) p1[mcnt-3] == jump_past_alt)
- /* `mcnt' holds how many bytes long the alternative
- is, including the ending `jump_past_alt' and
- if (!alt_match_null_string_p (p1, p1 + mcnt - 3,
- /* Move to right after this alternative, including the
- /* Break if it's the beginning of an n-th alternative
- that doesn't begin with an on_failure_jump. */
- if ((re_opcode_t) *p1 != on_failure_jump)
- /* Still have to check that it's not an n-th
- alternative that starts with an on_failure_jump. */
- EXTRACT_NUMBER_AND_INCR (mcnt, p1);
- if ((re_opcode_t) p1[mcnt-3] != jump_past_alt)
- /* Get to the beginning of the n-th alternative. */
- /* Deal with the last alternative: go back and get number
- of the `jump_past_alt' just before it. `mcnt' contains
- the length of the alternative. */
- EXTRACT_NUMBER (mcnt, p1 - 2);
- if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info))
- p1 += mcnt; /* Get past the n-th alternative. */
- if (!common_op_match_null_string_p (&p1, end, reg_info))
-} /* group_match_null_string_p */
-/* Similar to group_match_null_string_p, but doesn't deal with alternatives:
- It expects P to be the first byte of a single alternative and END one
- byte past the last. The alternative can contain groups. */
-alt_match_null_string_p (p, end, reg_info)
- unsigned char *p, *end;
- register_info_type *reg_info;
- /* Skip over opcodes that can match nothing, and break when we get
- switch ((re_opcode_t) *p1)
- EXTRACT_NUMBER_AND_INCR (mcnt, p1);
- if (!common_op_match_null_string_p (&p1, end, reg_info))
-} /* alt_match_null_string_p */
-/* Deals with the ops common to group_match_null_string_p and
- alt_match_null_string_p.
- Sets P to one after the op and its arguments, if any. */
-common_op_match_null_string_p (p, end, reg_info)
- unsigned char **p, *end;
- register_info_type *reg_info;
- unsigned char *p1 = *p;
- switch ((re_opcode_t) *p1++)
- assert (reg_no > 0 && reg_no <= MAX_REGNUM);
- ret = group_match_null_string_p (&p1, end, reg_info);
- /* Have to set this here in case we're checking a group which
- contains a group and a back reference to it. */
- if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE)
- REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret;
- /* If this is an optimized succeed_n for zero times, make the jump. */
- EXTRACT_NUMBER_AND_INCR (mcnt, p1);
- /* Get to the number of times to succeed. */
- EXTRACT_NUMBER_AND_INCR (mcnt, p1);
- EXTRACT_NUMBER_AND_INCR (mcnt, p1);
- if (!REG_MATCH_NULL_STRING_P (reg_info[*p1]))
- /* All other opcodes mean we cannot match the empty string. */
-} /* common_op_match_null_string_p */
-/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN
- bytes; nonzero otherwise. */
-bcmp_translate (s1, s2, len, translate)
- unsigned char *s1, *s2;
- register unsigned char *p1 = s1, *p2 = s2;
- if (translate[*p1++] != translate[*p2++]) return 1;
-/* Entry points for GNU code. */
-/* re_compile_pattern is the GNU regular expression compiler: it
- compiles PATTERN (of length SIZE) and puts the result in BUFP.
- Returns 0 if the pattern was valid, otherwise an error string.
- Assumes the `allocated' (and perhaps `buffer') and `translate' fields
- are set in BUFP on entry.
- We call regex_compile to do the actual compilation. */
-re_compile_pattern (pattern, length, bufp)
- struct re_pattern_buffer *bufp;
- /* GNU code is written to assume at least RE_NREGS registers will be set
- (and at least one extra will be -1). */
- bufp->regs_allocated = REGS_UNALLOCATED;
- /* And GNU code determines whether or not to get register information
- by passing null for the REGS argument to re_match, etc., not by
- /* Match anchors at newline. */
- bufp->newline_anchor = 1;
- ret = regex_compile (pattern, length, re_syntax_options, bufp);
- return re_error_msg[(int) ret];
-/* Entry points compatible with 4.2 BSD regex library. We don't define
- them if this is an Emacs or POSIX compilation. */
-#if !defined (emacs) && !defined (_POSIX_SOURCE)
-/* BSD has one and only one pattern buffer. */
-static struct re_pattern_buffer re_comp_buf;
- if (!re_comp_buf.buffer)
- return "No previous regular expression";
- if (!re_comp_buf.buffer)
- re_comp_buf.buffer = (unsigned char *) malloc (200);
- if (re_comp_buf.buffer == NULL)
- return "Memory exhausted";
- re_comp_buf.allocated = 200;
- re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH);
- if (re_comp_buf.fastmap == NULL)
- return "Memory exhausted";
- /* Since `re_exec' always passes NULL for the `regs' argument, we
- don't need to initialize the pattern buffer fields which affect it. */
- /* Match anchors at newlines. */
- re_comp_buf.newline_anchor = 1;
- ret = regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf);
- /* Yes, we're discarding `const' here. */
- return (char *) re_error_msg[(int) ret];
- const int len = strlen (s);
- 0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0);
-#endif /* not emacs and not _POSIX_SOURCE */
-/* POSIX.2 functions. Don't define these for Emacs. */
-/* regcomp takes a regular expression as a string and compiles it.
- PREG is a regex_t *. We do not expect any fields to be initialized,
- since POSIX says we shouldn't. Thus, we set
- `buffer' to the compiled pattern;
- `used' to the length of the compiled pattern;
- `syntax' to RE_SYNTAX_POSIX_EXTENDED if the
- REG_EXTENDED bit in CFLAGS is set; otherwise, to
- `newline_anchor' to REG_NEWLINE being set in CFLAGS;
- `fastmap' and `fastmap_accurate' to zero;
- `re_nsub' to the number of subexpressions in PATTERN.
- PATTERN is the address of the pattern string.
- CFLAGS is a series of bits which affect compilation.
- If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
- use POSIX basic syntax.
- If REG_NEWLINE is set, then . and [^...] don't match newline.
- Also, regexec will try a match beginning after every newline.
- If REG_ICASE is set, then we considers upper- and lowercase
- versions of letters to be equivalent when matching.
- If REG_NOSUB is set, then when PREG is passed to regexec, that
- routine will report only success or failure, and nothing about the
- It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for
- the return codes and their meanings.) */
-regcomp (preg, pattern, cflags)
- = (cflags & REG_EXTENDED) ?
- RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC;
- /* regex_compile will allocate the space for the compiled pattern. */
- /* Don't bother to use a fastmap when searching. This simplifies the
- REG_NEWLINE case: if we used a fastmap, we'd have to put all the
- characters after newlines into the fastmap. This way, we just try
- if (cflags & REG_ICASE)
- preg->translate = (char *) malloc (CHAR_SET_SIZE);
- if (preg->translate == NULL)
- return (int) REG_ESPACE;
- /* Map uppercase characters to corresponding lowercase ones. */
- for (i = 0; i < CHAR_SET_SIZE; i++)
- preg->translate[i] = ISUPPER (i) ? tolower (i) : i;
- preg->translate = NULL;
- /* If REG_NEWLINE is set, newlines are treated differently. */
- if (cflags & REG_NEWLINE)
- { /* REG_NEWLINE implies neither . nor [^...] match newline. */
- syntax &= ~RE_DOT_NEWLINE;
- syntax |= RE_HAT_LISTS_NOT_NEWLINE;
- /* It also changes the matching behavior. */
- preg->newline_anchor = 1;
- preg->newline_anchor = 0;
- preg->no_sub = !!(cflags & REG_NOSUB);
- /* POSIX says a null character in the pattern terminates it, so we
- can use strlen here in compiling the pattern. */
- ret = regex_compile (pattern, strlen (pattern), syntax, preg);
- /* POSIX doesn't distinguish between an unmatched open-group and an
- unmatched close-group: both are REG_EPAREN. */
- if (ret == REG_ERPAREN) ret = REG_EPAREN;
-/* regexec searches for a given pattern, specified by PREG, in the
- If NMATCH is zero or REG_NOSUB was set in the cflags argument to
- `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at
- least NMATCH elements, and we set them to the offsets of the
- corresponding matched substrings.
- EFLAGS specifies `execution flags' which affect matching: if
- REG_NOTBOL is set, then ^ does not match at the beginning of the
- string; if REG_NOTEOL is set, then $ does not match at the end.
- We return 0 if we find a match and REG_NOMATCH if not. */
-regexec (preg, string, nmatch, pmatch, eflags)
- struct re_registers regs;
- int len = strlen (string);
- boolean want_reg_info = !preg->no_sub && nmatch > 0;
- private_preg.not_bol = !!(eflags & REG_NOTBOL);
- private_preg.not_eol = !!(eflags & REG_NOTEOL);
- /* The user has told us exactly how many registers to return
- information about, via `nmatch'. We have to pass that on to the
- private_preg.regs_allocated = REGS_FIXED;
- regs.num_regs = nmatch;
- regs.start = TALLOC (nmatch, regoff_t);
- regs.end = TALLOC (nmatch, regoff_t);
- if (regs.start == NULL || regs.end == NULL)
- return (int) REG_NOMATCH;
- /* Perform the searching operation. */
- ret = re_search (&private_preg, string, len,
- /* start: */ 0, /* range: */ len,
- want_reg_info ? ®s : (struct re_registers *) 0);
- /* Copy the register information to the POSIX structure. */
- for (r = 0; r < nmatch; r++)
- pmatch[r].rm_so = regs.start[r];
- pmatch[r].rm_eo = regs.end[r];
- /* If we needed the temporary register info, free the space now. */
- /* We want zero return to mean success, unlike `re_search'. */
- return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH;
-/* Returns a message corresponding to an error code, ERRCODE, returned
- from either regcomp or regexec. We don't use PREG here. */
-regerror (errcode, preg, errbuf, errbuf_size)
- || errcode >= (sizeof (re_error_msg) / sizeof (re_error_msg[0])))
- /* Only error codes returned by the rest of the code should be passed
- to this routine. If we are given anything else, or if other regex
- code generates an invalid error code, then the program has a bug.
- Dump core so we can fix it. */
- msg = re_error_msg[errcode];
- /* POSIX doesn't require that we do anything in this case, but why
- msg_size = strlen (msg) + 1; /* Includes the null. */
- if (msg_size > errbuf_size)
- strncpy (errbuf, msg, errbuf_size - 1);
- errbuf[errbuf_size - 1] = 0;
-/* Free dynamically allocated space used by PREG. */
- if (preg->buffer != NULL)
- if (preg->fastmap != NULL)
- preg->fastmap_accurate = 0;
- if (preg->translate != NULL)
- free (preg->translate);
- preg->translate = NULL;
-trim-versions-without-asking: nil
--- a/ignorance/regex.h Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,490 +0,0 @@
-/* Definitions for data structures and routines for the regular
- expression library, version 0.12.
- Copyright (C) 1985, 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
- 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, or (at your option)
- 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
-#ifndef __REGEXP_LIBRARY_H__
-#define __REGEXP_LIBRARY_H__
-/* POSIX says that <sys/types.h> must be included (by the caller) before
-/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it
-/* The following bits are used to determine the regexp syntax we
- recognize. The set/not-set meanings are chosen so that Emacs syntax
- remains the value 0. The bits are given in alphabetical order, and
- the definitions shifted by one from the previous bit; thus, when we
- add or remove a bit, only one other definition need change. */
-typedef unsigned reg_syntax_t;
-/* If this bit is not set, then \ inside a bracket expression is literal.
- If set, then such a \ quotes the following character. */
-#define RE_BACKSLASH_ESCAPE_IN_LISTS (1)
-/* If this bit is not set, then + and ? are operators, and \+ and \? are
- If set, then \+ and \? are operators and + and ? are literals. */
-#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
-/* If this bit is set, then character classes are supported. They are:
- [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:],
- [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
- If not set, then character classes are not supported. */
-#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
-/* If this bit is set, then ^ and $ are always anchors (outside bracket
- expressions, of course).
- If this bit is not set, then it depends:
- ^ is an anchor if it is at the beginning of a regular
- expression or after an open-group or an alternation operator;
- $ is an anchor if it is at the end of a regular expression, or
- before a close-group or an alternation operator.
- This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
- POSIX draft 11.2 says that * etc. in leading positions is undefined.
- We already implemented a previous draft which made those constructs
- invalid, though, so we haven't changed the code back. */
-#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
-/* If this bit is set, then special characters are always special
- regardless of where they are in the pattern.
- If this bit is not set, then special characters are special only in
- some contexts; otherwise they are ordinary. Specifically,
- * + ? and intervals are only special when not after the beginning,
- open-group, or alternation operator. */
-#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
-/* If this bit is set, then *, +, ?, and { cannot be first in an re or
- immediately after an alternation or begin-group operator. */
-#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
-/* If this bit is set, then . matches newline.
- If not set, then it doesn't. */
-#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
-/* If this bit is set, then . doesn't match NUL.
- If not set, then it does. */
-#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
-/* If this bit is set, nonmatching lists [^...] do not match newline.
- If not set, they do. */
-#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
-/* If this bit is set, either \{...\} or {...} defines an
- interval, depending on RE_NO_BK_BRACES.
- If not set, \{, \}, {, and } are literals. */
-#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
-/* If this bit is set, +, ? and | aren't recognized as operators.
- If not set, they are. */
-#define RE_LIMITED_OPS (RE_INTERVALS << 1)
-/* If this bit is set, newline is an alternation operator.
- If not set, newline is literal. */
-#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
-/* If this bit is set, then `{...}' defines an interval, and \{ and \}
- If not set, then `\{...\}' defines an interval. */
-#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
-/* If this bit is set, (...) defines a group, and \( and \) are literals.
- If not set, \(...\) defines a group, and ( and ) are literals. */
-#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
-/* If this bit is set, then \<digit> matches <digit>.
- If not set, then \<digit> is a back-reference. */
-#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
-/* If this bit is set, then | is an alternation operator, and \| is literal.
- If not set, then \| is an alternation operator, and | is literal. */
-#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
-/* If this bit is set, then an ending range point collating higher
- than the starting range point, as in [z-a], is invalid.
- If not set, then when ending range point collates higher than the
- starting range point, the range is ignored. */
-#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
-/* If this bit is set, then an unmatched ) is ordinary.
- If not set, then an unmatched ) is invalid. */
-#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
-/* This global variable defines the particular regexp syntax to use (for
- some interfaces). When a regexp is compiled, the syntax used is
- stored in the pattern buffer, so changing this does not affect
- already-compiled regexps. */
-extern reg_syntax_t re_syntax_options;
-/* Define combinations of the above bits for the standard possibilities.
- (The [[[ comments delimit what gets put into the Texinfo file, so
-/* [[[begin syntaxes]]] */
-#define RE_SYNTAX_EMACS 0
- (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \
- | RE_NO_BK_PARENS | RE_NO_BK_REFS \
- | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \
- | RE_UNMATCHED_RIGHT_PAREN_ORD)
-#define RE_SYNTAX_POSIX_AWK \
- (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS)
-#define RE_SYNTAX_GREP \
- (RE_BK_PLUS_QM | RE_CHAR_CLASSES \
- | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \
-#define RE_SYNTAX_EGREP \
- (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \
- | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \
- | RE_NEWLINE_ALT | RE_NO_BK_PARENS \
-#define RE_SYNTAX_POSIX_EGREP \
- (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES)
-/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */
-#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
-#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
-/* Syntax bits common to both basic and extended POSIX regex syntax. */
-#define _RE_SYNTAX_POSIX_COMMON \
- (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \
- | RE_INTERVALS | RE_NO_EMPTY_RANGES)
-#define RE_SYNTAX_POSIX_BASIC \
- (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM)
-/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
- RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this
- isn't minimal, since other operators, such as \`, aren't disabled. */
-#define RE_SYNTAX_POSIX_MINIMAL_BASIC \
- (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
-#define RE_SYNTAX_POSIX_EXTENDED \
- (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
- | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \
- | RE_NO_BK_PARENS | RE_NO_BK_VBAR \
- | RE_UNMATCHED_RIGHT_PAREN_ORD)
-/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INVALID_OPS
- replaces RE_CONTEXT_INDEP_OPS and RE_NO_BK_REFS is added. */
-#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \
- (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
- | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \
- | RE_NO_BK_PARENS | RE_NO_BK_REFS \
- | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD)
-/* [[[end syntaxes]]] */
-/* Maximum number of duplicates an interval can allow. Some systems
- (erroneously) define this in other header files, but we want our
- value, so remove any previous define. */
-#define RE_DUP_MAX ((1 << 15) - 1)
-/* POSIX `cflags' bits (i.e., information for `regcomp'). */
-/* If this bit is set, then use extended regular expression syntax.
- If not set, then use basic regular expression syntax. */
-/* If this bit is set, then ignore case when matching.
- If not set, then case is significant. */
-#define REG_ICASE (REG_EXTENDED << 1)
-/* If this bit is set, then anchors do not match at newline
- characters in the string.
- If not set, then anchors do match at newlines. */
-#define REG_NEWLINE (REG_ICASE << 1)
-/* If this bit is set, then report only success or fail in regexec.
- If not set, then returns differ between not matching and errors. */
-#define REG_NOSUB (REG_NEWLINE << 1)
-/* POSIX `eflags' bits (i.e., information for regexec). */
-/* If this bit is set, then the beginning-of-line operator doesn't match
- the beginning of the string (presumably because it's not the
- If not set, then the beginning-of-line operator does match the
- beginning of the string. */
-/* Like REG_NOTBOL, except for the end-of-line. */
-#define REG_NOTEOL (1 << 1)
-/* If any error codes are removed, changed, or added, update the
- `re_error_msg' table in regex.c. */
- REG_NOERROR = 0, /* Success. */
- REG_NOMATCH, /* Didn't find a match (for regexec). */
- /* POSIX regcomp return error codes. (In the order listed in the
- REG_BADPAT, /* Invalid pattern. */
- REG_ECOLLATE, /* Not implemented. */
- REG_ECTYPE, /* Invalid character class name. */
- REG_EESCAPE, /* Trailing backslash. */
- REG_ESUBREG, /* Invalid back reference. */
- REG_EBRACK, /* Unmatched left bracket. */
- REG_EPAREN, /* Parenthesis imbalance. */
- REG_EBRACE, /* Unmatched \{. */
- REG_BADBR, /* Invalid contents of \{\}. */
- REG_ERANGE, /* Invalid range end. */
- REG_ESPACE, /* Ran out of memory. */
- REG_BADRPT, /* No preceding re for repetition op. */
- /* Error codes we've added. */
- REG_EEND, /* Premature end. */
- REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */
- REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */
-/* This data structure represents a compiled pattern. Before calling
- the pattern compiler, the fields `buffer', `allocated', `fastmap',
- `translate', and `no_sub' can be set. After the pattern has been
- compiled, the `re_nsub' field is available. All other fields are
- private to the regex routines. */
-struct re_pattern_buffer
-/* [[[begin pattern_buffer]]] */
- /* Space that holds the compiled pattern. It is declared as
- `unsigned char *' because its elements are
- sometimes used as array indexes. */
- /* Number of bytes to which `buffer' points. */
- unsigned long allocated;
- /* Number of bytes actually used in `buffer'. */
- /* Syntax setting with which the pattern was compiled. */
- /* Pointer to a fastmap, if any, otherwise zero. re_search uses
- the fastmap, if there is one, to skip over impossible
- starting points for matches. */
- /* Either a translate table to apply to all characters before
- comparing them, or zero for no translation. The translation
- is applied to a pattern when it is compiled and to a string
- /* Number of subexpressions found by the compiler. */
- /* Zero if this pattern cannot match the empty string, one else.
- Well, in truth it's used only in `re_search_2', to see
- whether or not we should use the fastmap, so we don't set
- this absolutely perfectly; see `re_compile_fastmap' (the
- unsigned can_be_null : 1;
- /* If REGS_UNALLOCATED, allocate space in the `regs' structure
- for `max (RE_NREGS, re_nsub + 1)' groups.
- If REGS_REALLOCATE, reallocate space if necessary.
- If REGS_FIXED, use what's there. */
-#define REGS_UNALLOCATED 0
-#define REGS_REALLOCATE 1
- unsigned regs_allocated : 2;
- /* Set to zero when `regex_compile' compiles a pattern; set to one
- by `re_compile_fastmap' if it updates the fastmap. */
- unsigned fastmap_accurate : 1;
- /* If set, `re_match_2' does not return information about
- /* If set, a beginning-of-line anchor doesn't match at the
- beginning of the string. */
- /* Similarly for an end-of-line anchor. */
- /* If true, an anchor at a newline matches. */
- unsigned newline_anchor : 1;
-/* [[[end pattern_buffer]]] */
-typedef struct re_pattern_buffer regex_t;
-/* search.c (search_buffer) in Emacs needs this one opcode value. It is
- defined both in `regex.c' and here. */
-#define RE_EXACTN_VALUE 1
-/* Type for byte offsets within the string. POSIX mandates this. */
-/* This is the structure we store register match data in. See
- regex.texinfo for a full description of what registers match. */
-/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
- `re_match_2' returns information about at least this many registers
- the first time a `regs' structure is passed. */
-/* POSIX specification for registers. Aside from the different names than
- `re_registers', POSIX uses an array of structures, instead of a
- structure of arrays. */
- regoff_t rm_so; /* Byte offset from string's start to substring's start. */
- regoff_t rm_eo; /* Byte offset from string's start to substring's end. */
-/* Declarations for routines. */
-/* To avoid duplicating every routine declaration -- once with a
- prototype (if we are ANSI), and once without (if we aren't) -- we
- use the following macro to declare argument types. This
- unfortunately clutters up the declarations a bit, but I think it's
-#define _RE_ARGS(args) args
-#else /* not __STDC__ */
-#define _RE_ARGS(args) ()
-#endif /* not __STDC__ */
-/* Sets the current default syntax to SYNTAX, and return the old syntax.
- You can also simply assign to the `re_syntax_options' variable. */
-extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax));
-/* Compile the regular expression PATTERN, with length LENGTH
- and syntax given by the global `re_syntax_options', into the buffer
- BUFFER. Return NULL if successful, and an error string if not. */
-extern const char *re_compile_pattern
- _RE_ARGS ((const char *pattern, int length,
- struct re_pattern_buffer *buffer));
-/* Compile a fastmap for the compiled pattern in BUFFER; used to
- accelerate searches. Return 0 if successful and -2 if was an
-extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer));
-/* Search in the string STRING (with length LENGTH) for the pattern
- compiled into BUFFER. Start searching at position START, for RANGE
- characters. Return the starting position of the match, -1 for no
- match, or -2 for an internal error. Also return register
- information in REGS (if REGS and BUFFER->no_sub are nonzero). */
- _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
- int length, int start, int range, struct re_registers *regs));
-/* Like `re_search', but search in the concatenation of STRING1 and
- STRING2. Also, stop searching at index START + STOP. */
- _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
- int length1, const char *string2, int length2,
- int start, int range, struct re_registers *regs, int stop));
-/* Like `re_search', but return how many characters in STRING the regexp
- in BUFFER matched, starting at position START. */
- _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
- int length, int start, struct re_registers *regs));
-/* Relates to `re_match' as `re_search_2' relates to `re_search'. */
- _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
- int length1, const char *string2, int length2,
- int start, struct re_registers *regs, int stop));
-/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
- ENDS. Subsequent matches using BUFFER and REGS will use this memory
- for recording register information. STARTS and ENDS must be
- allocated with malloc, and must each be at least `NUM_REGS * sizeof
- (regoff_t)' bytes long.
- If NUM_REGS == 0, then subsequent matches should allocate their own
- Unless this function is called, the first search or match using
- PATTERN_BUFFER will allocate its own register data, without
- freeing the old data. */
-extern void re_set_registers
- _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs,
- unsigned num_regs, regoff_t *starts, regoff_t *ends));
-/* 4.2 bsd compatibility. */
-extern char *re_comp _RE_ARGS ((const char *));
-extern int re_exec _RE_ARGS ((const char *));
-/* POSIX compatibility. */
-extern int regcomp _RE_ARGS ((regex_t *preg, const char *pattern, int cflags));
- _RE_ARGS ((const regex_t *preg, const char *string, size_t nmatch,
- regmatch_t pmatch[], int eflags));
- _RE_ARGS ((int errcode, const regex_t *preg, char *errbuf,
-extern void regfree _RE_ARGS ((regex_t *preg));
-#endif /* not __REGEXP_LIBRARY_H__ */
-trim-versions-without-asking: nil
--- a/ignorance/support.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,158 +0,0 @@
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
-# include "../pp_config.h"
-#include "../common/pp_internal.h"
-#include "ignorance_internal.h"
-lookup_widget (GtkWidget *widget,
- const gchar *widget_name)
- GtkWidget *parent, *found_widget;
- if (GTK_IS_MENU (widget))
- parent = gtk_menu_get_attach_widget (GTK_MENU (widget));
- parent = widget->parent;
- parent = (GtkWidget*) g_object_get_data (G_OBJECT (widget), "GladeParentKey");
- found_widget = (GtkWidget*) g_object_get_data (G_OBJECT (widget),
- g_warning ("Widget not found: %s", widget_name);
-static GList *pixmaps_directories = NULL;
-/* Use this function to set the directory containing installed pixmaps. */
-add_pixmap_directory (const gchar *directory)
- pixmaps_directories = g_list_prepend (pixmaps_directories,
-/* This is an internally used function to find pixmap files. */
-find_pixmap_file (const gchar *filename)
- /* We step through each of the pixmaps directory to find it. */
- elem = pixmaps_directories;
- gchar *pathname = g_strdup_printf ("%s%s%s", (gchar*)elem->data,
- G_DIR_SEPARATOR_S, filename);
- if (g_file_test (pathname, G_FILE_TEST_EXISTS))
-/* This is an internally used function to create pixmaps. */
-create_pixmap (GtkWidget *widget,
- gchar *pathname = NULL;
- if (!filename || !filename[0])
- return gtk_image_new ();
- pathname = find_pixmap_file (filename);
- g_warning (_("Couldn't find pixmap file: %s"), filename);
- return gtk_image_new ();
- pixmap = gtk_image_new_from_file (pathname);
-/* This is an internally used function to create pixmaps. */
-create_pixbuf (const gchar *filename)
- gchar *pathname = NULL;
- if (!filename || !filename[0])
- pathname = find_pixmap_file (filename);
- g_warning (_("Couldn't find pixmap file: %s"), filename);
- pixbuf = gdk_pixbuf_new_from_file (pathname, &error);
- fprintf (stderr, "Failed to load pixbuf file: %s: %s\n",
- pathname, error->message);
-/* This is used to set ATK action descriptions. */
-glade_set_atk_action_description (AtkAction *action,
- const gchar *action_name,
- const gchar *description)
- n_actions = atk_action_get_n_actions (action);
- for (i = 0; i < n_actions; i++)
- if (!strcmp (atk_action_get_name (action, i), action_name))
- atk_action_set_description (action, i, description);
--- a/ignorance/support.h Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
-#ifndef IGNORANCE_SUPPORT_H
-#define IGNORANCE_SUPPORT_H
- * This function returns a widget in a component created by Glade.
- * Call it with the toplevel widget in the component (i.e. a window/dialog),
- * or alternatively any widget in the component, and the name of the widget
-GtkWidget* lookup_widget (GtkWidget *widget,
- const gchar *widget_name);
-/* Use this function to set the directory containing installed pixmaps. */
-void add_pixmap_directory (const gchar *directory);
-/* This is used to create the pixmaps used in the interface. */
-GtkWidget* create_pixmap (GtkWidget *widget,
- const gchar *filename);
-/* This is used to create the pixbufs used in the interface. */
-GdkPixbuf* create_pixbuf (const gchar *filename);
-/* This is used to set ATK action descriptions. */
-void glade_set_atk_action_description (AtkAction *action,
- const gchar *action_name,
- const gchar *description);
--- a/infopane/README.md Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-authors: Sadrul Habib Chowdhury
-notes: Requires Pidgin 2.1.0 or newer.
-Adds some options for the information pane in conversations.
--- a/infopane/infopane.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,261 +0,0 @@
- * Infopane - Use different views for the details information in conversation windows.
- * Copyright (C) 2007-2008 Sadrul Habib Chowdhury <sadrul@users.sourceforge.net>
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA
-/* If you can't figure out what this line is for, DON'T TOUCH IT. */
-#include "../common/pp_internal.h"
-#include "conversation.h"
-#define PLUGIN_ID "gtk-plugin_pack-infopane"
-#define PREF_PREFIX "/plugins/gtk/infopane"
-#define PREF_POSITION PREF_PREFIX "/position"
-#define PREF_DRAG PREF_PREFIX "/drag"
-#define PREF_SINGLE PREF_PREFIX "/single"
-#define PREF_ICON PREF_PREFIX "/icon"
-static gboolean ensure_tabs_are_showing(PurpleConversation *conv)
- PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
- PidginWindow *win = gtkconv->win;
- if (win && win->gtkconvs && win->gtkconvs->next)
- if (purple_prefs_get_bool(PREF_SINGLE)) {
- gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), TRUE);
- } else if (win->gtkconvs->next == NULL) {
- gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), FALSE);
-static void set_conv_window_prefs(PidginConversation *gtkconv)
- GtkWidget *paned, *vbox;
- pref = purple_prefs_get_string(PREF_POSITION)[0];
- gtk_widget_hide_all(gtkconv->infopane_hbox->parent);
- list = gtk_container_get_children(GTK_CONTAINER(gtkconv->tab_cont));
- vbox = gtk_paned_get_child1(GTK_PANED(paned));
- g_object_ref(G_OBJECT(gtkconv->infopane_hbox->parent));
- gtk_container_remove(GTK_CONTAINER(vbox), gtkconv->infopane_hbox->parent);
- gtk_box_pack_end(GTK_BOX(vbox), gtkconv->infopane_hbox->parent, FALSE, FALSE, 0);
- g_object_unref(G_OBJECT(gtkconv->infopane_hbox->parent));
- /* To disable dragging, setup a listener for button_press_event and return TRUE if the
- * click is not going to popup up the sendto or the context menu */
- ensure_tabs_are_showing(gtkconv->active_conv);
- if (purple_prefs_get_bool(PREF_ICON)) {
- gtk_widget_show(gtkconv->icon);
- gtk_widget_hide(gtkconv->icon);
-static void conversation_deleted(PurpleConversation *conv)
- PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
- PidginWindow *win = gtkconv->win;
- if (win->gtkconvs->next && !win->gtkconvs->next->next) { /* There are only two tabs in the window */
- PidginConversation *p = win->gtkconvs->data;
- p = win->gtkconvs->next->data;
- id = g_timeout_add(0, (GSourceFunc)ensure_tabs_are_showing, p->active_conv);
- g_signal_connect_swapped(G_OBJECT(win->window), "destroy",
- G_CALLBACK(g_source_remove), GINT_TO_POINTER(id));
-pref_changed(gpointer data, ...)
- GList *wins = pidgin_conv_windows_get_list();
- for (; wins; wins = wins->next) {
- GList *tabs = pidgin_conv_window_get_gtkconvs(wins->data);
- for (; tabs; tabs = tabs->next) {
- set_conv_window_prefs(tabs->data);
-plugin_load(PurplePlugin *plugin)
- regsuccess = purple_signal_connect(pidgin_conversations_get_handle(),
- "conversation-displayed",
- plugin, PURPLE_CALLBACK(set_conv_window_prefs), NULL);
- purple_debug_error(PLUGIN_ID, "Libpurple and Pidgin are too old!\n");
- purple_debug_error(PLUGIN_ID, _("Libpurple and Pidgin are too old!\n"));
- purple_notify_error(plugin, _("Incompatible Plugin"),
- _("You need to update Pidgin!"),
- _("This plugin is incompatible with the running version of Pidgin and Libpurple because it is too old. Please upgrade to the newest version of Pidgin."));
- purple_signal_connect(purple_conversations_get_handle(),
- "deleting-conversation",
- plugin, PURPLE_CALLBACK(conversation_deleted), NULL);
- purple_signal_connect(pidgin_conversations_get_handle(),
- "conversation-switched",
- plugin, PURPLE_CALLBACK(ensure_tabs_are_showing), NULL);
- purple_prefs_connect_callback(plugin, PREF_POSITION, (PurplePrefCallback)pref_changed, NULL);
- purple_prefs_connect_callback(plugin, PREF_DRAG, (PurplePrefCallback)pref_changed, NULL);
- purple_prefs_connect_callback(plugin, PREF_ICON, (PurplePrefCallback)pref_changed, NULL);
- purple_prefs_connect_callback(plugin, PREF_SINGLE, (PurplePrefCallback)pref_changed, NULL);
- purple_prefs_trigger_callback(PREF_POSITION);
-static PurplePluginPrefFrame *
-get_plugin_pref_frame(PurplePlugin *plugin)
- PurplePluginPrefFrame *frame;
- PurplePluginPref *pref;
- frame = purple_plugin_pref_frame_new();
- /* XXX: Is there a better way than this? There really should be. */
- pref = purple_plugin_pref_new_with_name_and_label(PREF_POSITION, _("Position of the infopane ('top', 'bottom' or 'none')"));
- purple_plugin_pref_frame_add(frame, pref);
- pref = purple_plugin_pref_new_with_name_and_label(PREF_ICON,
- _("Show icon in the tabs"));
- purple_plugin_pref_frame_add(frame, pref);
- pref = purple_plugin_pref_new_with_name_and_label(PREF_SINGLE,
- _("Always show the tab"));
- purple_plugin_pref_frame_add(frame, pref);
-static PurplePluginUiInfo prefs_info =
-static PurplePluginInfo info =
- PURPLE_PLUGIN_STANDARD,
- PURPLE_PRIORITY_DEFAULT,
- "Sadrul H Chowdhury <sadrul@pidgin.im>",
-init_plugin(PurplePlugin *plugin)
- bindtextdomain(GETTEXT_PACKAGE, PP_LOCALEDIR);
- bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
- if(purple_version_check(2,2,0) == NULL) {
- info.name = _("Infopane Options");
- info.summary = _("Allow customizing the details information in conversation windows.");
- info.description = _("Allow customizing the details information in conversation windows.");
- purple_prefs_add_none(PREF_PREFIX);
- purple_prefs_add_string(PREF_POSITION, "top");
- purple_prefs_add_bool(PREF_DRAG, FALSE);
- purple_prefs_add_bool(PREF_SINGLE, TRUE);
- purple_prefs_add_bool(PREF_ICON, TRUE);
- purple_debug_error(PLUGIN_ID, "Libpurple and Pidgin are too old!\n");
- purple_debug_error(PLUGIN_ID, _("Libpurple and Pidgin are too old!\n"));
- info.name = _("Incompatible Plugin! - Check plugin details!");
- info.summary = _("This plugin is NOT compatible with this version of Pidgin!");
- info.description = _("This plugin is NOT compatible with this version of Pidgin!");
-PURPLE_INIT_PLUGIN(infopane, init_plugin, info)
--- a/infopane/meson.build Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-if TYPES.contains('default') and PIDGIN.found()
- infopane = shared_module('infopane',
- dependencies : [PIDGIN, GTK],
- install_dir : PIDGIN_LIBDIR)
- PP_PIDGIN_BUILD += 'infopane'
--- a/meson.build Thu Mar 05 06:36:45 2020 +0000
+++ b/meson.build Thu Mar 05 09:53:21 2020 +0000
@@ -164,15 +164,10 @@
subdir('dewysiwygification')
@@ -180,29 +175,22 @@
@@ -212,14 +200,10 @@
--- a/msglen/README.md Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-Shows the length of your current message in the menu tray.
--- a/msglen/meson.build Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-if TYPES.contains('incomplete') and PIDGIN.found()
- msglen = shared_module('msglen',
- dependencies : [PIDGIN, GTK],
- install_dir : PIDGIN_LIBDIR)
- PP_PIDGIN_BUILD += 'msglen'
--- a/msglen/msglen.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,258 +0,0 @@
- * msglen - Adds the current message's length to the menutray of a conversation
- * Copyright (C) 2008 Gary Kramlich <grim@reaperworld.com>
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
-/* If you can't figure out what this line is for, DON'T TOUCH IT. */
-#include "../common/pp_internal.h"
-#include <conversation.h>
-#include <gtkmenutray.h>
-/******************************************************************************
- *****************************************************************************/
- PurpleConversation *conv;
-/******************************************************************************
- *****************************************************************************/
-static GHashTable *data = NULL;
-/******************************************************************************
- *****************************************************************************/
-msg_len_data_free(MsgLenData *mld) {
- if(mld->label && GTK_IS_LABEL(mld->label))
- gtk_widget_destroy(mld->label);
-msg_len_data_free_helper(gpointer k, gpointer v, gpointer d) {
- MsgLenData *mld = (MsgLenData *)v;
- msg_len_data_free(mld);
-static void msg_len_update(PidginWindow *win, PurpleConversation *conv);
-msg_len_key_released_cb(GtkWidget *w, GdkEventKey *e, gpointer d) {
- MsgLenData *mld = (MsgLenData *)d;
- msg_len_update(mld->win, mld->conv);
-msg_len_add_signal(PidginConversation *pconv, MsgLenData *mld) {
- g_signal_connect(G_OBJECT(pconv->entry),
- G_CALLBACK(msg_len_key_released_cb), mld);
-msg_len_find_data(PidginWindow *win) {
- MsgLenData *mld = NULL;
- mld = g_hash_table_lookup(data, win);
- mld = g_new0(MsgLenData, 1);
- mld->label = gtk_label_new("");
- pidgin_menu_tray_append(PIDGIN_MENU_TRAY(win->menu.tray), mld->label,
- gtk_widget_show(mld->label);
- g_signal_connect_swapped(G_OBJECT(mld->label), "destroy",
- G_CALLBACK(g_nullify_pointer), &mld->label);
-msg_len_update(PidginWindow *win, PurpleConversation *conv) {
- PidginConversation *gtkconv = NULL;
- MsgLenData *mld = NULL;
- g_return_if_fail(conv);
- gtkconv = PIDGIN_CONVERSATION(conv);
- mld = msg_len_find_data(win);
- count = gtk_text_buffer_get_char_count(gtkconv->entry_buffer);
- text = g_strdup_printf("%d", count);
- gtk_label_set_text(GTK_LABEL(mld->label), text);
- g_hash_table_insert(data, win, mld);
-/******************************************************************************
- *****************************************************************************/
-msg_len_conv_created_cb(PurpleConversation *conv, gpointer d) {
- PidginConversation *pconv = PIDGIN_CONVERSATION(conv);
- PidginWindow *win = pidgin_conv_get_window(pconv);
- MsgLenData *mld = NULL;
- mld = msg_len_find_data(win);
- msg_len_add_signal(pconv, mld);
- msg_len_update(win, conv);
-msg_len_conv_destroyed_cb(PurpleConversation *conv, gpointer d) {
- g_hash_table_remove(data, conv);
-msg_len_conv_switched_cb(PurpleConversation *conv, gpointer d) {
- PidginConversation *pconv = PIDGIN_CONVERSATION(conv);
- PidginWindow *win = pidgin_conv_get_window(pconv);
- msg_len_update(win, conv);
-/******************************************************************************
- *****************************************************************************/
-plugin_load(PurplePlugin *plugin) {
- void *conv_handle = purple_conversations_get_handle();
- data = g_hash_table_new_full(g_direct_hash, g_direct_equal,
- purple_signal_connect(conv_handle, "conversation-created", plugin,
- PURPLE_CALLBACK(msg_len_conv_created_cb), NULL);
- purple_signal_connect(conv_handle, "deleting-conversation", plugin,
- PURPLE_CALLBACK(msg_len_conv_destroyed_cb), NULL);
- purple_signal_connect(pidgin_conversations_get_handle(),
- "conversation-switched", plugin,
- PURPLE_CALLBACK(msg_len_conv_switched_cb), NULL);
- for(convs = purple_get_conversations(); convs; convs = convs->next) {
- PurpleConversation *conv = (PurpleConversation *)convs->data;
- PidginConversation *pconv = PIDGIN_CONVERSATION(conv);
- MsgLenData *mld = msg_len_find_data(pconv->win);
- msg_len_add_signal(pconv, mld);
- msg_len_update(pconv->win, conv);
-plugin_unload(PurplePlugin *plugin) {
- g_hash_table_foreach(data, msg_len_data_free_helper, NULL);
- g_hash_table_destroy(data);
-static PurplePluginInfo info = {
- PURPLE_PLUGIN_STANDARD,
- PURPLE_PRIORITY_DEFAULT,
- "gtk-plugin_pack-msglen",
- "Gary Kramlich <grim@reaperworld.com>",
-init_plugin(PurplePlugin *plugin) {
- bindtextdomain(GETTEXT_PACKAGE, PP_LOCALEDIR);
- bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
- info.name = _("Message Length");
- info.summary = _("Shows the length of your current message in the menu "
- info.description = info.summary;
-PURPLE_INIT_PLUGIN(msg_len, init_plugin, info)
Binary file napster/16/napster.png has changed
Binary file napster/22/napster.png has changed
Binary file napster/48/napster.png has changed
--- a/napster/README.md Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-# Napster Protocol Plugin
-notes: Introduced into the Purple Plugin Pack after it was removed from libpurple.
--- a/napster/meson.build Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-if TYPES.contains('default') and PURPLE.found() and IS_PURPLE_TWO
- napster = shared_library('napster',
- dependencies : [PURPLE, GLIB],
- install_dir : PURPLE_LIBDIR)
- PP_PURPLE_BUILD += 'napster'
- foreach size : [16, 22, 48]
- install_data('@0@/napster.png'.format(size),
- install_dir : join_paths(PIDGIN_PIXMAPSDIR, 'protocols/@0@'.format(size)))
--- a/napster/napster.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,765 +0,0 @@
- * napster - Napster Protocol Plugin
- * Copyright (C) 2000-2001, Rob Flynn <rob@marko.net>
- * Assimilated for inclusion in the Plugin Pack:
- * Copyright (C) 2006-2008 Gary Kramlich <grim@reaperworld.com>
- * Copyright (C) 2007 John Bailey <rekkanoryo@rekkanoryo.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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-/* If you can't figure out what this line is for, DON'T TOUCH IT. */
-#include "../common/pp_internal.h"
-#include <conversation.h>
-#define NAP_SERVER "64.124.41.187"
-#define NAPSTER_CONNECT_STEPS 2
-GSList *nap_connections = NULL;
-static PurpleConversation *
-nap_find_chat(PurpleConnection *gc, const char *name) {
- GSList *bcs = gc->buddy_chats;
- PurpleConversation *b = bcs->data;
- if (!purple_utf8_strcasecmp(b->name, name))
-nap_write_packet(PurpleConnection *gc, unsigned short command,
- const char *format, ...)
- struct nap_data *ndata = (struct nap_data *)gc->proto_data;
- message = g_strdup_vprintf(format, ap);
- size = strlen(message);
- purple_debug(PURPLE_DEBUG_MISC, "napster", "S %3hd: %s\n", command, message);
- write(ndata->fd, &size, 2);
- write(ndata->fd, &command, 2);
- write(ndata->fd, message, size);
-nap_do_irc_style(PurpleConnection *gc, const char *message, const char *name) {
- purple_debug(PURPLE_DEBUG_MISC, "napster", "C %s\n", message);
- res = g_strsplit(message, " ", 2);
- if (!g_ascii_strcasecmp(res[0], "/ME")) { /* MSG_CLIENT_PUBLIC */
- nap_write_packet(gc, 824, "%s \"%s\"", name, res[1]);
- } else if (!g_ascii_strcasecmp(res[0], "/MSG")) { /* MSG_CLIENT_PUBLIC */
- nap_write_packet(gc, 205, "%s", res[1]);
- } else if (!g_ascii_strcasecmp(res[0], "/JOIN")) { /* join chatroom MSG_CLIENT_JOIN */
- nap_write_packet(gc, 400, "#%s", res[1]);
- nap_write_packet(gc, 400, "%s", res[1]);
- } else if (!g_ascii_strcasecmp(res[0], "/PART")) { /* partchatroom MSG_CLIENT_PART */
- nap_write_packet(gc, 401, "%s", res[1] ? res[1] : name);
- } else if (!g_ascii_strcasecmp(res[0], "/TOPIC")) { /* set topic MSG_SERVER_TOPIC */
- nap_write_packet(gc, 410, "%s", res[1] ? res[1] : name);
- } else if (!g_ascii_strcasecmp(res[0], "/WHOIS")) { /* whois request MSG_CLIENT_WHOIS */
- nap_write_packet(gc, 603, "%s", res[1]);
- } else if (!g_ascii_strcasecmp(res[0], "/PING")) { /* send ping MSG_CLIENT_PING */
- nap_write_packet(gc, 751, "%s", res[1]);
- } else if (!g_ascii_strcasecmp(res[0], "/KICK")) { /* kick asswipe MSG_CLIENT_KICK */
- nap_write_packet(gc, 829, "%s", res[1]);
-/* 205 - MSG_CLIENT_PRIVMSG */
-nap_send_im(PurpleConnection *gc, const char *who, const char *message,
- PurpleMessageFlags flags)
- char *tmp = purple_unescape_html(message);
- if ((strlen(tmp) < 2) || (tmp[0] != '/' ) || (tmp[1] == '/')) {
- /* Actually send a chat message */
- nap_write_packet(gc, 205, "%s %s", who, tmp);
- /* user typed an IRC-style command */
- nap_do_irc_style(gc, tmp, who);
-/* 207 - MSG_CLIENT_ADD_HOTLIST */
-nap_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) {
- nap_write_packet(gc, 207, "%s", buddy->name);
-/* 208 - MSG_CLIENT_ADD_HOTLIST_SEQ */
-nap_send_buddylist(PurpleConnection *gc) {
- PurpleBuddyList *blist;
- PurpleBlistNode *gnode, *cnode, *bnode;
- if ((blist = purple_get_blist()) != NULL)
- for (gnode = blist->root; gnode != NULL; gnode = gnode->next)
- if (!PURPLE_BLIST_NODE_IS_GROUP(gnode))
- for (cnode = gnode->child; cnode != NULL; cnode = cnode->next)
- if (!PURPLE_BLIST_NODE_IS_CONTACT(cnode))
- for (bnode = cnode->child; bnode != NULL; bnode = bnode->next)
- if (!PURPLE_BLIST_NODE_IS_BUDDY(bnode))
- buddy = (PurpleBuddy *)bnode;
- nap_write_packet(gc, 208, "%s", buddy->name);
-/* 303 - MSG_CLIENT_REMOVE_HOTLIST */
-nap_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) {
- nap_write_packet(gc, 303, "%s", buddy->name);
-nap_get_chat_name(GHashTable *data) {
- char *name = g_hash_table_lookup(data, "group");
- /* Make sure the name has a # preceding it */
- return g_strdup_printf("#%s", name);
-/* 400 - MSG_CLIENT_JOIN */
-nap_join_chat(PurpleConnection *gc, GHashTable *data) {
- name = nap_get_chat_name(data);
- nap_write_packet(gc, 400, "%s", name);
-/* 401 - MSG_CLIENT_PART */
-nap_chat_leave(PurpleConnection *gc, int id) {
- PurpleConversation *c = purple_find_chat(gc, id);
- nap_write_packet(gc, 401, "%s", c->name);
-/* 402 - MSG_CLIENT_PUBLIC */
-nap_chat_send(PurpleConnection *gc, int id, const char *message,
- PurpleMessageFlags flags)
- PurpleConversation *c = purple_find_chat(gc, id);
- char *tmp = purple_unescape_html(message);
- if ((strlen(tmp) < 2) || (tmp[0] != '/' ) || (tmp[1] == '/')) {
- /* Actually send a chat message */
- nap_write_packet(gc, 402, "%s %s", c->name, tmp);
- /* user typed an IRC-style command */
- nap_do_irc_style(gc, tmp, c->name);
-/* 603 - MSG_CLIENT_WHOIS */
-nap_get_info(PurpleConnection *gc, const char *who) {
- nap_write_packet(gc, 603, "%s", who);
-nap_callback(gpointer data, gint source, PurpleInputCondition condition) {
- PurpleConnection *gc = data;
- struct nap_data *ndata = gc->proto_data;
- PurpleAccount *account = NULL;
- PurpleConversation *c = NULL;
- PurpleNotifyUserInfo *pnui = NULL;
- gchar *buf = NULL, *buf2 = NULL, *buf3 = NULL, **res = NULL;
- unsigned short header[2] = { 0 , 0 };
- account = purple_connection_get_account(gc);
- if (read(source, (void*)header, 4) != 4) {
- purple_connection_error(gc, _("Unable to read header from server"));
- buf = (gchar *)g_malloc((len + 1) * sizeof(gchar));
- int tmp = read(source, buf + i, len - i);
- buf = g_strdup_printf(_("Unable to read message from server: %s. Command is %hd, length is %hd."), strerror(errno), len, command);
- purple_connection_error(gc, buf);
- purple_debug(PURPLE_DEBUG_MISC, "napster", "R %3hd: %s\n", command, buf);
- case 000: /* MSG_SERVER_ERROR */
- purple_notify_error(gc, NULL, buf, NULL);
- purple_input_remove(gc->inpa);
- purple_connection_error(gc, _("Unknown server error."));
- case 003: /* MSG_SERVER_EMAIL */
- purple_debug(PURPLE_DEBUG_MISC, "napster", "Registered with e-mail address: %s\n", buf);
- ndata->email = g_strdup(buf);
- /* Our signon is complete */
- purple_connection_set_state(gc, PURPLE_CONNECTED);
- /* Send the server our buddy list */
- nap_send_buddylist(gc);
- case 201: /* MSG_SERVER_SEARCH_RESULT */
- res = g_strsplit(buf, " ", 0);
- purple_prpl_got_user_status(account, res[0], "available", NULL);
- case 202: /* MSG_SERVER_SEARCH_END */
- purple_prpl_got_user_status(account, buf, "offline", NULL);
- case 205: /* MSG_CLIENT_PRIVMSG */
- res = g_strsplit(buf, " ", 2);
- buf2 = g_markup_escape_text(res[1], -1);
- serv_got_im(gc, res[0], buf2, 0, time(NULL));
- case 209: /* MSG_SERVER_USER_SIGNON */
- res = g_strsplit(buf, " ", 2);
- purple_prpl_got_user_status(account, res[0], "available", NULL);
- case 210: /* MSG_SERVER_USER_SIGNOFF */
- res = g_strsplit(buf, " ", 2);
- purple_prpl_got_user_status(account, res[0], "offline", NULL);
- case 214: /* MSG_SERVER_STATS */
- res = g_strsplit(buf, " ", 3);
- buf2 = g_strdup_printf(_("users: %s, files: %s, size: %sGB"), res[0], res[1], res[2]);
- serv_got_im(gc, "server", buf2, 0, time(NULL));
- case 301: /* MSG_SERVER_HOTLIST_ACK */
- /* Our buddy was added successfully */
- case 302: /* MSG_SERVER_HOTLIST_ERROR */
- buf2 = g_strdup_printf(_("Unable to add \"%s\" to your Napster hotlist"), buf);
- purple_notify_error(gc, NULL, buf2, NULL);
- case 316: /* MSG_SERVER_DISCONNECTING */
- /* we have been kicked off =^( */
- purple_connection_error(gc, _("You were disconnected from the server."));
- case 401: /* MSG_CLIENT_PART */
- c = nap_find_chat(gc, buf);
- serv_got_chat_left(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(c)));
- case 403: /* MSG_SERVER_PUBLIC */
- res = g_strsplit(buf, " ", 3);
- c = nap_find_chat(gc, res[0]);
- serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(c)), res[1], 0, res[2], time(NULL));
- case 404: /* MSG_SERVER_NOSUCH */
- /* abused by opennap servers to broadcast stuff */
- buf2 = g_markup_escape_text(buf, -1);
- serv_got_im(gc, "server", buf2, 0, time(NULL));
- case 405: /* MSG_SERVER_JOIN_ACK */
- c = nap_find_chat(gc, buf);
- serv_got_joined_chat(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(c)), buf);
- case 407: /* MSG_SERVER_PART */
- res = g_strsplit(buf, " ", 0);
- c = nap_find_chat(gc, res[0]);
- purple_conv_chat_remove_user(PURPLE_CONV_CHAT(c), res[1], NULL);
- case 406: /* MSG_SERVER_JOIN */
- case 408: /* MSG_SERVER_CHANNEL_USER_LIST */
- res = g_strsplit(buf, " ", 4);
- c = nap_find_chat(gc, res[0]);
- purple_conv_chat_add_user(PURPLE_CONV_CHAT(c), res[1], NULL, PURPLE_CBFLAGS_NONE, TRUE);
- case 409: /* MSG_SERVER_CHANNEL_USER_LIST_END */
- case 410: /* MSG_SERVER_TOPIC */
- /* display the topic in the channel */
- res = g_strsplit(buf, " ", 2);
- c = nap_find_chat(gc, res[0]);
- purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), res[0], res[1]);
- case 603: /* MSG_CLIENT_WHOIS */
- buf2 = g_strdup_printf(_("%s requested your information"), buf);
- serv_got_im(gc, "server", buf2, 0, time(NULL));
- case 604: /* MSG_SERVER_WHOIS_RESPONSE */
- /* XXX - Format is: "Elite" 37 " " "Active" 0 0 0 0 "purple 0.63cvs" 0 0 192.168.1.41 32798 0 unknown flounder */
- res = g_strsplit(buf, " ", 2);
- /* res[0] == username */
- pnui = purple_notify_user_info_new();
- purple_notify_user_info_add_pair(pnui, _("Napster User Info:"), res[1]);
- purple_notify_userinfo(gc, res[0], pnui, NULL, NULL);
- case 622: /* MSG_CLIENT_MOTD */
- /* also replaces MSG_SERVER_MOTD, so we should display it */
- buf2 = g_markup_escape_text(buf, -1);
- serv_got_im(gc, "motd", buf2, 0, time(NULL));
- case 627: /* MSG_CLIENT_WALLOP */
- /* abused by opennap server maintainers to broadcast stuff */
- buf2 = g_markup_escape_text(buf, -1);
- serv_got_im(gc, "wallop", buf2, 0, time(NULL));
- case 628: /* MSG_CLIENT_ANNOUNCE */
- buf2 = g_markup_escape_text(buf, -1);
- serv_got_im(gc, "announce", buf2, 0, time(NULL));
- case 748: /* MSG_SERVER_GHOST */
- /* Looks like someone logged in as us! =-O */
- purple_connection_error(gc, _("You have signed on from another location."));
- case 751: /* MSG_CLIENT_PING */
- buf2 = g_strdup_printf(_("%s requested a PING"), buf);
- serv_got_im(gc, "server", buf2, 0, time(NULL));
- nap_write_packet(gc, 752, "%s", buf);
- case 752: /* MSG_CLIENT_PONG */
- buf2 = g_strdup_printf("Received pong from %s", buf);
- purple_notify_info(gc, NULL, buf2, NULL);
- case 824: /* MSG_CLIENT_EMOTE */
- res = g_strsplit(buf, " ", 3);
- buf2 = g_strndup(res[2]+1, strlen(res[2]) - 2); /* chomp off the surround quotes */
- buf3 = g_strdup_printf("/me %s", buf2);
- if ((c = nap_find_chat(gc, res[0]))) {
- purple_conv_chat_write(PURPLE_CONV_CHAT(c), res[1], buf3, PURPLE_MESSAGE_NICK, time(NULL));
- purple_debug(PURPLE_DEBUG_MISC, "napster", "Unknown packet %hd: %s\n", command, buf);
-/* 002 - MSG_CLIENT_LOGIN */
-nap_login_connect(gpointer data, gint source, const gchar *error_message) {
- PurpleConnection *gc = data;
- struct nap_data *ndata = (struct nap_data *)gc->proto_data;
- if (!g_list_find(purple_connections_get_all(), gc)) {
- purple_connection_error(gc, _("Unable to connect."));
- /* Clear the nonblocking flag
- This protocol should be updated to support nonblocking I/O if
- anyone is going to actually use it */
- fcntl(source, F_SETFL, 0);
- /* Update the login progress status display */
- buf = g_strdup_printf("Logging in: %s", purple_account_get_username(gc->account));
- purple_connection_update_progress(gc, buf, 1, NAPSTER_CONNECT_STEPS);
- /* Write our signon data */
- nap_write_packet(gc, 2, "%s %s 0 \"purple %s\" 0",
- purple_account_get_username(gc->account),
- purple_connection_get_password(gc), PP_VERSION);
- /* And set up the input watcher */
- gc->inpa = purple_input_add(ndata->fd, PURPLE_INPUT_READ, nap_callback, gc);
-nap_login(PurpleAccount *account) {
- PurpleConnection *gc = purple_account_get_connection(account);
- purple_connection_update_progress(gc, _("Connecting"), 0, NAPSTER_CONNECT_STEPS);
- gc->proto_data = g_new0(struct nap_data, 1);
- if (purple_proxy_connect(gc, account,
- purple_account_get_string(account, "server", NAP_SERVER),
- purple_account_get_int(account, "port", NAP_PORT),
- nap_login_connect, gc) != 0) {
- purple_connection_error(gc, _("Unable to connect."));
-nap_close(PurpleConnection *gc) {
- struct nap_data *ndata = (struct nap_data *)gc->proto_data;
- purple_input_remove(gc->inpa);
-nap_list_icon(PurpleAccount *a, PurpleBuddy *b) {
-nap_status_types(PurpleAccount *account) {
- PurpleStatusType *type;
- g_return_val_if_fail(account != NULL, NULL);
- type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE,
- NULL, NULL, TRUE, TRUE, FALSE);
- types = g_list_append(types, type);
- type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE,
- NULL, NULL, TRUE, TRUE, FALSE);
- types = g_list_append(types, type);
-nap_chat_info(PurpleConnection *gc) {
- struct proto_chat_entry *pce;
- pce = g_new0(struct proto_chat_entry, 1);
- pce->label = _("_Group:");
- pce->identifier = "group";
- m = g_list_append(m, pce);
-nap_chat_info_defaults(PurpleConnection *gc, const char *chat_name) {
- defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
- g_hash_table_insert(defaults, "group", g_strdup(chat_name));
-static PurplePlugin *my_protocol = NULL;
-static PurplePluginProtocolInfo prpl_info = {
- NULL, /* user_splits */
- NULL, /* protocol_options */
- NO_BUDDY_ICONS, /* icon_spec */
- nap_list_icon, /* list_icon */
- NULL, /* list_emblems */
- NULL, /* status_text */
- NULL, /* tooltip_text */
- nap_status_types, /* status_types */
- NULL, /* blist_node_menu */
- nap_chat_info, /* chat_info */
- nap_chat_info_defaults, /* chat_info_defaults */
- nap_send_im, /* send_im */
- NULL, /* send_typing */
- nap_get_info, /* get_info */
- NULL, /* change_passwd */
- nap_add_buddy, /* add_buddy */
- NULL, /* add_buddies */
- nap_remove_buddy, /* remove_buddy */
- NULL, /* remove_buddies */
- NULL, /* set_permit_deny */
- nap_join_chat, /* join_chat */
- NULL, /* reject chat invite */
- nap_get_chat_name, /* get_chat_name */
- NULL, /* chat_invite */
- nap_chat_leave, /* chat_leave */
- NULL, /* chat_whisper */
- nap_chat_send, /* chat_send */
- NULL, /* register_user */
- NULL, /* get_cb_info */
- NULL, /* get_cb_away */
- NULL, /* alias_buddy */
- NULL, /* group_buddy */
- NULL, /* rename_group */
- NULL, /* convo_closed */
- NULL, /* set_buddy_icon */
- NULL, /* remove_group */
- NULL, /* get_cb_real_name */
- NULL, /* set_chat_topic */
- NULL, /* find_blist_chat */
- NULL, /* roomlist_get_list */
- NULL, /* roomlist_cancel */
- NULL, /* roomlist_expand_category */
- NULL, /* can_receive_file */
- NULL, /* offline_message */
- NULL, /* whiteboard_prpl_ops */
- NULL, /* roomlist_room_serialize */
- NULL, /* unregister_user */
- NULL, /* send_attention */
- NULL, /* get_attention_types */
- sizeof(PurplePluginProtocolInfo), /* struct_size */
- NULL, /* get_account_text_table */
- NULL, /* initiate_media */
- NULL, /* get_media_caps */
- NULL, /* set_public_alias */
- NULL /* get_public_alias */
-static PurplePluginInfo info = {
- PURPLE_PLUGIN_PROTOCOL, /**< type */
- NULL, /**< ui_requirement */
- NULL, /**< dependencies */
- PURPLE_PRIORITY_DEFAULT, /**< priority */
- "prpl-napster", /**< id */
- N_("Napster"), /**< name */
- PP_VERSION, /**< version */
- N_("NAPSTER Protocol Plugin"),
- N_("NAPSTER Protocol Plugin"),
- PP_WEBSITE, /**< homepage */
- &prpl_info, /**< extra_info */
-init_plugin(PurplePlugin *plugin) {
- PurpleAccountOption *option;
- bindtextdomain(GETTEXT_PACKAGE, PP_LOCALEDIR);
- bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
- option = purple_account_option_string_new(_("Server"), "server", NAP_SERVER);
- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
- option = purple_account_option_int_new(_("Port"), "port", 8888);
- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
- info.description = _(info.description);
- info.summary = _(info.summary);
-PURPLE_INIT_PLUGIN(napster, init_plugin, info);
--- a/nomobility/README.md Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-Stops you from messaging mobile users.
--- a/nomobility/meson.build Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-if TYPES.contains('incomplete') and PURPLE.found()
- nomobility = shared_library('nomobility',
- dependencies : [PURPLE, GLIB],
- install_dir : PURPLE_LIBDIR)
- PP_PURPLE_BUILD += 'nomobility'
--- a/nomobility/nomobility.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,314 +0,0 @@
- * nomobility - stops you from sending messages to mobile users
- * Copyright (C) 2008 Gary Kramlich <grim@reaperworld.com>
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
-/* If you can't figure out what this line is for, DON'T TOUCH IT. */
-#include "../common/pp_internal.h"
-#include <conversation.h>
-/******************************************************************************
- *****************************************************************************/
-#define NO_MOBILITY_QUEUE_KEY "no-mobility"
-#define NO_MOBILITY_COMMAND "mobile"
-static PurpleCmdId nomobility_cmd_id = 0;
-/******************************************************************************
- *****************************************************************************/
-nomobility_list_messages(PurpleConversation *conv, GList *queue) {
- const gchar *name = purple_conversation_get_name(conv);
- purple_conv_im_write(PURPLE_CONV_IM(conv), name,
- _("There are no messages in the queue."),
- PURPLE_MESSAGE_NO_LOG, time(NULL));
- for(l = queue; l; l = l->next, i++) {
- gchar *msg = g_strdup_printf(_("%d. %s"), i + 1, (gchar *)l->data);
- purple_conv_im_write(PURPLE_CONV_IM(conv), name, msg,
- PURPLE_MESSAGE_NO_LOG, time(NULL));
-nomobility_clear(PurpleConversation *conv, GList *queue) {
- for(l = queue; l; l = l->next)
- purple_conversation_set_data(conv, NO_MOBILITY_QUEUE_KEY, NULL);
-nomobility_send(PurpleConversation *conv, GList *queue) {
- GString *str = g_string_new("");
- for(l = queue; l; l = l->next) {
- gchar *msg = (gchar *)l->data;
- const gchar *suffix = (l->next) ? "\n" : "";
- g_string_append_printf(str, "%s%s", msg, suffix);
- purple_conv_im_send(PURPLE_CONV_IM(conv), str->str);
- g_string_free(str, TRUE);
- nomobility_clear(conv, queue);
-nomobility_delete(PurpleConversation *conv, GList *queue, gint n_msg) {
- for(l = queue; i < n_msg - 1; i++, l = l->next);
- queue = g_list_remove(queue, l);
- purple_conversation_set_data(conv, NO_MOBILITY_QUEUE_KEY, queue);
-/******************************************************************************
- *****************************************************************************/
-sending_im_msg(PurpleAccount *account, gchar *receiver, gchar **message,
- PurpleBuddy *buddy = NULL;
- PurplePresence *presence = NULL;
- if(!message || !*message)
- buddy = purple_find_buddy(account, receiver);
- presence = purple_buddy_get_presence(buddy);
- if(purple_presence_is_status_primitive_active(presence,
- PurpleConversation *conv = NULL;
- msg = g_strdup_printf(_("Cancelled message to %s, they are currently "
- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
- /* if we have the account, add the message to our queue */
- queue = purple_conversation_get_data(conv, NO_MOBILITY_QUEUE_KEY);
- queue = g_list_append(queue, g_strdup(*message));
- purple_conversation_set_data(conv, NO_MOBILITY_QUEUE_KEY, queue);
- /* now actually kill the message */
- /* if we failed to find the conv, write a debug message and bail */
- purple_debug_info("nomobility", "%s\n", msg);
- /* we have a conv, so note that we queue the message in conv */
- purple_conv_im_write(PURPLE_CONV_IM(conv), receiver, msg,
- PURPLE_MESSAGE_NO_LOG | PURPLE_MESSAGE_DELAYED,
-nomobility_cmd(PurpleConversation *conv, const gchar *cmd, gchar **args,
- gchar **error, gpointer data)
- if(!*args && !args[0]) {
- *error = g_strdup("eek!");
- return PURPLE_CMD_RET_FAILED;
- queue = purple_conversation_get_data(conv, NO_MOBILITY_QUEUE_KEY);
- lower = g_ascii_strdown(args[0], strlen(args[0]));
- if(strcmp(lower, "clear") == 0) {
- nomobility_clear(conv, queue);
- } else if(strcmp(lower, "delete") == 0) {
- *error = g_strdup(_("Delete failed: no message number given!"));
- return PURPLE_CMD_RET_FAILED;
- if(n_msg < 0 || n_msg >= g_list_length(queue)) {
- g_strdup_printf(_("Delete failed: no messaged numbered %d!"),
- return PURPLE_CMD_RET_FAILED;
- nomobility_delete(conv, queue, n_msg);
- } else if(strcmp(lower, "list") == 0) {
- nomobility_list_messages(conv, queue);
- } else if(strcmp(lower, "sendall") == 0) {
- nomobility_send(conv, queue);
- return PURPLE_CMD_RET_OK;
-/******************************************************************************
- *****************************************************************************/
-plugin_load(PurplePlugin *plugin) {
- PurpleCmdFlag flags = PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS;
- void *conv_handle = purple_conversations_get_handle();
- purple_signal_connect(conv_handle, "sending-im-msg", plugin,
- PURPLE_CALLBACK(sending_im_msg), NULL);
- help = g_strdup_printf(_("%s <[clear][clear][delete][send]>\n"
- "clear Clears all queued messages\n"
- "delete # Deletes the message numbered #\n"
- "list Lists all queued messages\n"
- "sendall Sends all queued messages\n"),
- purple_cmd_register(NO_MOBILITY_COMMAND, "ws", PURPLE_CMD_P_PLUGIN,
- PURPLE_CMD_FUNC(nomobility_cmd), help, NULL);
-plugin_unload(PurplePlugin *plugin)
-static PurplePluginInfo info =
- PURPLE_PLUGIN_STANDARD,
- PURPLE_PRIORITY_DEFAULT,
- "core-plugin_pack-nomobility",
- "Gary Kramlich <grim@reaperworld.com>",
-init_plugin(PurplePlugin *plugin)
- bindtextdomain(GETTEXT_PACKAGE, PP_LOCALEDIR);
- bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
- info.name = _("No Mobility");
- info.summary = _("Stops you from messaging mobile users");
- info.description = info.summary;
-PURPLE_INIT_PLUGIN(nomobility, init_plugin, info)
--- a/smartear/README.md Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-depends: libpurple, pidgin (optional), libgnt (optional)
-introduced: not yet finished
-The Core component of the Smart Ear plugins
--- a/smartear/gtksmartear.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +0,0 @@
- * gktsmartear.c - GTK+ configuration UI plugin to accompany smartear.
- * Copyright (C) 2007 John Bailey <rekkanoryo@rekkanoryo.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
-# include "../pp_config.h"
-/* Pack/Local headers */
-#include "../common/pp_internal.h"
-gtksmartear_blist_menu_cb(PurpleBlistNode *node, gpointer data) {
-gtksmartear_drawing_blist_menu_cb(PurpleBlistNode *node, GList **menu) {
- /* Don't do anything if the blistnode won't be saved */
- if(purple_blist_node_get_flags(node) & PURPLE_BLIST_NODE_FLAG_NO_SAVE)
- /* We don't support setting anything for a chat, since there's no way
- * to get the name of a chat */
- if(PURPLE_BLIST_NODE_IS_CHAT(node))
- (*menu) = g_list_append(*menu, purple_menu_action_new(_("SmartEar Options"),
- PURPLE_CALLBACK(gtksmartear_blist_menu_cb),
-plugin_load(PurplePlugin *plugin) {
- purple_signal_connect(purple_blist_get_handle(),
- "blist-node-extended-menu",
- PURPLE_CALLBACK(gtksmartear_drawing_blist_menu_cb),
-plugin_unload(PurplePlugin *plugin) {
-static PurplePluginInfo info = {
- PURPLE_PLUGIN_MAGIC, /* Magic */
- PURPLE_MAJOR_VERSION, /* Purple Major Version */
- PURPLE_MINOR_VERSION, /* Purple Minor Version */
- PURPLE_PLUGIN_STANDARD, /* plugin type */
- PIDGIN_PLUGIN_TYPE, /* ui requirement */
- NULL, /* dependencies */
- PURPLE_PRIORITY_DEFAULT, /* priority */
- "gtk-plugin_pack-smartear", /* plugin id */
- PP_VERSION, /* version */
- NULL, /* description */
- "John Bailey <rekkanoryo@rekkanoryo.org>",
- PP_WEBSITE, /* website */
- plugin_load, /* load */
- plugin_unload, /* unload */
-init_plugin(PurplePlugin *plugin) {
- bindtextdomain(GETTEXT_PACKAGE, PP_LOCALEDIR);
- bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
- info.name = _("SmartEar");
- info.summary = _("The GTK+ (Pidgin) component of the SmartEar plugin suite");
- info.description = _("This plugin provides the Pidgin interface to the "
- "SmartEar plugin suite's functionality. The suite "
- "allows you to specify sounds per-buddy, per-contact, "
- "or per-group for specific events.");
- info.dependencies = g_list_append(NULL, "core-plugin_pack-smartear");
-PURPLE_INIT_PLUGIN(PLUGIN_STATIC_NAME, init_plugin, info)
--- a/smartear/interface.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,566 +0,0 @@
- * DO NOT EDIT THIS FILE - it is generated by Glade.
-#include <gdk/gdkkeysyms.h>
-#define GLADE_HOOKUP_OBJECT(component,widget,name) \
- g_object_set_data_full (G_OBJECT (component), name, \
- gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref)
-#define GLADE_HOOKUP_OBJECT_NO_REF(component,widget,name) \
- g_object_set_data (G_OBJECT (component), name, widget)
- GtkWidget *config_vbox;
- GtkObject *delay_spin_adj;
- GtkWidget *scrolledwindow2;
- GtkWidget *hbuttonbox1;
- config = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- gtk_window_set_title (GTK_WINDOW (config), "SmartEar Configuration");
- gtk_window_set_destroy_with_parent (GTK_WINDOW (config), TRUE);
- config_vbox = gtk_vbox_new (FALSE, 0);
- gtk_widget_show (config_vbox);
- gtk_container_add (GTK_CONTAINER (config), config_vbox);
- gtk_widget_set_size_request (config_vbox, -1, 640);
- frame1 = gtk_frame_new (NULL);
- gtk_widget_show (frame1);
- gtk_box_pack_start (GTK_BOX (config_vbox), frame1, FALSE, TRUE, 0);
- gtk_container_set_border_width (GTK_CONTAINER (frame1), 5);
- table1 = gtk_table_new (3, 2, FALSE);
- gtk_widget_show (table1);
- gtk_container_add (GTK_CONTAINER (frame1), table1);
- gtk_container_set_border_width (GTK_CONTAINER (table1), 5);
- gtk_table_set_row_spacings (GTK_TABLE (table1), 10);
- gtk_table_set_col_spacings (GTK_TABLE (table1), 10);
- label9 = gtk_label_new ("Time delay between playing sounds for a particular buddy:");
- gtk_widget_show (label9);
- gtk_table_attach (GTK_TABLE (table1), label9, 0, 1, 0, 1,
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
- (GtkAttachOptions) (0), 0, 0);
- gtk_misc_set_alignment (GTK_MISC (label9), 0, 0.5);
- delay_spin_adj = gtk_adjustment_new (60, 0, 1000000, 1, 10, 10);
- delay_spin = gtk_spin_button_new (GTK_ADJUSTMENT (delay_spin_adj), 1, 0);
- gtk_widget_show (delay_spin);
- gtk_table_attach (GTK_TABLE (table1), delay_spin, 1, 2, 0, 1,
- (GtkAttachOptions) (0),
- (GtkAttachOptions) (0), 0, 0);
- gtk_spin_button_set_update_policy (GTK_SPIN_BUTTON (delay_spin), GTK_UPDATE_IF_VALID);
- focus_but = gtk_check_button_new_with_mnemonic ("Don't play sounds for the conversation that has focus.");
- gtk_widget_show (focus_but);
- gtk_table_attach (GTK_TABLE (table1), focus_but, 0, 2, 1, 2,
- (GtkAttachOptions) (GTK_FILL),
- (GtkAttachOptions) (0), 0, 0);
- timer_but = gtk_check_button_new_with_mnemonic ("Also play sounds if you don't respond to a particular IM within a delay period.");
- gtk_widget_show (timer_but);
- gtk_table_attach (GTK_TABLE (table1), timer_but, 0, 2, 2, 3,
- (GtkAttachOptions) (GTK_FILL),
- (GtkAttachOptions) (0), 0, 0);
- label8 = gtk_label_new ("Options");
- gtk_widget_show (label8);
- gtk_frame_set_label_widget (GTK_FRAME (frame1), label8);
- frame2 = gtk_frame_new (NULL);
- gtk_widget_show (frame2);
- gtk_box_pack_start (GTK_BOX (config_vbox), frame2, TRUE, TRUE, 0);
- gtk_container_set_border_width (GTK_CONTAINER (frame2), 5);
- table2 = gtk_table_new (2, 3, FALSE);
- gtk_widget_show (table2);
- gtk_container_add (GTK_CONTAINER (frame2), table2);
- gtk_container_set_border_width (GTK_CONTAINER (table2), 5);
- gtk_table_set_row_spacings (GTK_TABLE (table2), 10);
- gtk_table_set_col_spacings (GTK_TABLE (table2), 10);
- delete_but = gtk_button_new_from_stock ("gtk-delete");
- gtk_widget_show (delete_but);
- gtk_table_attach (GTK_TABLE (table2), delete_but, 2, 3, 1, 2,
- (GtkAttachOptions) (0),
- (GtkAttachOptions) (0), 0, 0);
- GTK_WIDGET_SET_FLAGS (delete_but, GTK_CAN_DEFAULT);
- new_but = gtk_button_new_from_stock ("gtk-new");
- gtk_widget_show (new_but);
- gtk_table_attach (GTK_TABLE (table2), new_but, 0, 1, 1, 2,
- (GtkAttachOptions) (0),
- (GtkAttachOptions) (0), 0, 0);
- GTK_WIDGET_SET_FLAGS (new_but, GTK_CAN_DEFAULT);
- scrolledwindow2 = gtk_scrolled_window_new (NULL, NULL);
- gtk_widget_show (scrolledwindow2);
- gtk_table_attach (GTK_TABLE (table2), scrolledwindow2, 0, 3, 0, 1,
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow2), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
- treeview = gtk_tree_view_new ();
- gtk_widget_show (treeview);
- gtk_container_add (GTK_CONTAINER (scrolledwindow2), treeview);
- edit_but = gtk_button_new_from_stock ("gtk-properties");
- gtk_widget_show (edit_but);
- gtk_table_attach (GTK_TABLE (table2), edit_but, 1, 2, 1, 2,
- (GtkAttachOptions) (0),
- (GtkAttachOptions) (0), 0, 0);
- label7 = gtk_label_new ("Entries");
- gtk_widget_show (label7);
- gtk_frame_set_label_widget (GTK_FRAME (frame2), label7);
- hbuttonbox1 = gtk_hbutton_box_new ();
- gtk_widget_show (hbuttonbox1);
- gtk_box_pack_start (GTK_BOX (config_vbox), hbuttonbox1, FALSE, TRUE, 0);
- gtk_container_set_border_width (GTK_CONTAINER (hbuttonbox1), 5);
- gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox1), GTK_BUTTONBOX_SPREAD);
- revert_but = gtk_button_new_from_stock ("gtk-revert-to-saved");
- gtk_widget_show (revert_but);
- gtk_container_add (GTK_CONTAINER (hbuttonbox1), revert_but);
- GTK_WIDGET_SET_FLAGS (revert_but, GTK_CAN_DEFAULT);
- save_but = gtk_button_new_from_stock ("gtk-save");
- gtk_widget_show (save_but);
- gtk_container_add (GTK_CONTAINER (hbuttonbox1), save_but);
- GTK_WIDGET_SET_FLAGS (save_but, GTK_CAN_DEFAULT);
- g_signal_connect ((gpointer) config_vbox, "destroy",
- G_CALLBACK (on_config_destroy),
- g_signal_connect ((gpointer) delay_spin, "changed",
- G_CALLBACK (on_delay_changed),
- g_signal_connect ((gpointer) focus_but, "toggled",
- G_CALLBACK (on_focus_toggled),
- g_signal_connect ((gpointer) timer_but, "toggled",
- G_CALLBACK (on_timer_toggled),
- g_signal_connect ((gpointer) delete_but, "clicked",
- G_CALLBACK (on_delete_clicked),
- g_signal_connect ((gpointer) new_but, "clicked",
- G_CALLBACK (on_new_clicked),
- g_signal_connect ((gpointer) edit_but, "clicked",
- G_CALLBACK (on_edit_clicked),
- g_signal_connect ((gpointer) revert_but, "clicked",
- G_CALLBACK (on_revert_clicked),
- g_signal_connect ((gpointer) save_but, "clicked",
- G_CALLBACK (on_save_clicked),
- /* Store pointers to all widgets, for use by lookup_widget(). */
- GLADE_HOOKUP_OBJECT_NO_REF (config, config, "config");
- GLADE_HOOKUP_OBJECT (config, config_vbox, "config_vbox");
- GLADE_HOOKUP_OBJECT (config, frame1, "frame1");
- GLADE_HOOKUP_OBJECT (config, table1, "table1");
- GLADE_HOOKUP_OBJECT (config, label9, "label9");
- GLADE_HOOKUP_OBJECT (config, delay_spin, "delay_spin");
- GLADE_HOOKUP_OBJECT (config, focus_but, "focus_but");
- GLADE_HOOKUP_OBJECT (config, timer_but, "timer_but");
- GLADE_HOOKUP_OBJECT (config, label8, "label8");
- GLADE_HOOKUP_OBJECT (config, frame2, "frame2");
- GLADE_HOOKUP_OBJECT (config, table2, "table2");
- GLADE_HOOKUP_OBJECT (config, delete_but, "delete_but");
- GLADE_HOOKUP_OBJECT (config, new_but, "new_but");
- GLADE_HOOKUP_OBJECT (config, scrolledwindow2, "scrolledwindow2");
- GLADE_HOOKUP_OBJECT (config, treeview, "treeview");
- GLADE_HOOKUP_OBJECT (config, edit_but, "edit_but");
- GLADE_HOOKUP_OBJECT (config, label7, "label7");
- GLADE_HOOKUP_OBJECT (config, hbuttonbox1, "hbuttonbox1");
- GLADE_HOOKUP_OBJECT (config, revert_but, "revert_but");
- GLADE_HOOKUP_OBJECT (config, save_but, "save_but");
-create_file_browse (void)
- GtkWidget *file_browse;
- GtkWidget *cancel_button1;
- file_browse = gtk_file_selection_new ("Select Sound");
- gtk_container_set_border_width (GTK_CONTAINER (file_browse), 10);
- gtk_window_set_destroy_with_parent (GTK_WINDOW (file_browse), TRUE);
- gtk_window_set_type_hint (GTK_WINDOW (file_browse), GDK_WINDOW_TYPE_HINT_DIALOG);
- ok_button1 = GTK_FILE_SELECTION (file_browse)->ok_button;
- gtk_widget_show (ok_button1);
- GTK_WIDGET_SET_FLAGS (ok_button1, GTK_CAN_DEFAULT);
- cancel_button1 = GTK_FILE_SELECTION (file_browse)->cancel_button;
- gtk_widget_show (cancel_button1);
- GTK_WIDGET_SET_FLAGS (cancel_button1, GTK_CAN_DEFAULT);
- g_signal_connect ((gpointer) file_browse, "destroy",
- G_CALLBACK (on_file_browse_destroy),
- g_signal_connect ((gpointer) ok_button1, "clicked",
- G_CALLBACK (on_browse_ok_clicked),
- g_signal_connect_swapped ((gpointer) ok_button1, "clicked",
- G_CALLBACK (gtk_widget_destroy),
- GTK_OBJECT (file_browse));
- g_signal_connect_swapped ((gpointer) cancel_button1, "clicked",
- G_CALLBACK (gtk_widget_destroy),
- GTK_OBJECT (file_browse));
- /* Store pointers to all widgets, for use by lookup_widget(). */
- GLADE_HOOKUP_OBJECT_NO_REF (file_browse, file_browse, "file_browse");
- GLADE_HOOKUP_OBJECT_NO_REF (file_browse, ok_button1, "ok_button1");
- GLADE_HOOKUP_OBJECT_NO_REF (file_browse, cancel_button1, "cancel_button1");
- GtkWidget *type_option;
- GtkWidget *hbuttonbox2;
- GtkWidget *applysave_but;
- GtkWidget *unaway_sound_entry;
- GtkWidget *unidle_sound_entry;
- GtkWidget *signon_sound_entry;
- GtkWidget *unaway_test_but;
- GtkWidget *unidle_test_but;
- GtkWidget *signon_test_but;
- GtkWidget *unaway_browse_but;
- GtkWidget *unidle_browse_but;
- GtkWidget *signon_browse_but;
- GtkWidget *im_browse_but;
- GtkWidget *im_sound_entry;
- GtkWidget *im_test_but;
- edit_win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- gtk_widget_set_size_request (edit_win, 600, 300);
- gtk_window_set_title (GTK_WINDOW (edit_win), "Edit Entry");
- gtk_window_set_default_size (GTK_WINDOW (edit_win), 600, 300);
- vbox1 = gtk_vbox_new (FALSE, 0);
- gtk_widget_show (vbox1);
- gtk_container_add (GTK_CONTAINER (edit_win), vbox1);
- hbox1 = gtk_hbox_new (FALSE, 5);
- gtk_widget_show (hbox1);
- gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, TRUE, 10);
- gtk_container_set_border_width (GTK_CONTAINER (hbox1), 5);
- label29 = gtk_label_new ("Name:");
- gtk_widget_show (label29);
- gtk_box_pack_start (GTK_BOX (hbox1), label29, FALSE, FALSE, 0);
- gtk_misc_set_alignment (GTK_MISC (label29), 1, 0.5);
- name_entry = gtk_entry_new ();
- gtk_widget_show (name_entry);
- gtk_box_pack_start (GTK_BOX (hbox1), name_entry, TRUE, TRUE, 0);
- label30 = gtk_label_new ("Type:");
- gtk_widget_show (label30);
- gtk_box_pack_start (GTK_BOX (hbox1), label30, FALSE, TRUE, 0);
- gtk_misc_set_alignment (GTK_MISC (label30), 1, 0.5);
- type_option = gtk_option_menu_new ();
- gtk_widget_show (type_option);
- gtk_box_pack_start (GTK_BOX (hbox1), type_option, FALSE, FALSE, 0);
- menu1 = gtk_menu_new ();
- item_buddy = gtk_menu_item_new_with_mnemonic ("Buddy");
- gtk_widget_show (item_buddy);
- gtk_container_add (GTK_CONTAINER (menu1), item_buddy);
- item_group = gtk_menu_item_new_with_mnemonic ("Group");
- gtk_widget_show (item_group);
- gtk_container_add (GTK_CONTAINER (menu1), item_group);
- gtk_option_menu_set_menu (GTK_OPTION_MENU (type_option), menu1);
- hbuttonbox2 = gtk_hbutton_box_new ();
- gtk_widget_show (hbuttonbox2);
- gtk_box_pack_end (GTK_BOX (vbox1), hbuttonbox2, FALSE, TRUE, 0);
- gtk_container_set_border_width (GTK_CONTAINER (hbuttonbox2), 5);
- gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox2), GTK_BUTTONBOX_SPREAD);
- applysave_but = gtk_button_new_with_mnemonic ("Apply and Save");
- gtk_widget_show (applysave_but);
- gtk_container_add (GTK_CONTAINER (hbuttonbox2), applysave_but);
- GTK_WIDGET_SET_FLAGS (applysave_but, GTK_CAN_DEFAULT);
- apply_but = gtk_button_new_from_stock ("gtk-apply");
- gtk_widget_show (apply_but);
- gtk_container_add (GTK_CONTAINER (hbuttonbox2), apply_but);
- GTK_WIDGET_SET_FLAGS (apply_but, GTK_CAN_DEFAULT);
- cancel_but = gtk_button_new_from_stock ("gtk-cancel");
- gtk_widget_show (cancel_but);
- gtk_container_add (GTK_CONTAINER (hbuttonbox2), cancel_but);
- GTK_WIDGET_SET_FLAGS (cancel_but, GTK_CAN_DEFAULT);
- frame3 = gtk_frame_new (NULL);
- gtk_widget_show (frame3);
- gtk_box_pack_start (GTK_BOX (vbox1), frame3, FALSE, FALSE, 0);
- gtk_widget_set_size_request (frame3, -1, 200);
- gtk_container_set_border_width (GTK_CONTAINER (frame3), 5);
- table5 = gtk_table_new (4, 5, FALSE);
- gtk_widget_show (table5);
- gtk_container_add (GTK_CONTAINER (frame3), table5);
- gtk_widget_set_size_request (table5, 600, 400);
- gtk_container_set_border_width (GTK_CONTAINER (table5), 5);
- gtk_table_set_row_spacings (GTK_TABLE (table5), 10);
- gtk_table_set_col_spacings (GTK_TABLE (table5), 10);
- label31 = gtk_label_new ("Play On IM:");
- gtk_widget_show (label31);
- gtk_table_attach (GTK_TABLE (table5), label31, 0, 1, 0, 1,
- (GtkAttachOptions) (0),
- (GtkAttachOptions) (0), 0, 0);
- gtk_misc_set_alignment (GTK_MISC (label31), 0, 0.5);
- label34 = gtk_label_new ("Play On Unaway:");
- gtk_widget_show (label34);
- gtk_table_attach (GTK_TABLE (table5), label34, 0, 1, 3, 4,
- (GtkAttachOptions) (0),
- (GtkAttachOptions) (0), 0, 0);
- gtk_misc_set_alignment (GTK_MISC (label34), 0, 0.5);
- label33 = gtk_label_new ("Play On Unidle:");
- gtk_widget_show (label33);
- gtk_table_attach (GTK_TABLE (table5), label33, 0, 1, 2, 3,
- (GtkAttachOptions) (0),
- (GtkAttachOptions) (0), 0, 0);
- gtk_misc_set_alignment (GTK_MISC (label33), 0, 0.5);
- label32 = gtk_label_new ("Play On Signon:");
- gtk_widget_show (label32);
- gtk_table_attach (GTK_TABLE (table5), label32, 0, 1, 1, 2,
- (GtkAttachOptions) (0),
- (GtkAttachOptions) (0), 0, 0);
- gtk_misc_set_alignment (GTK_MISC (label32), 0, 0.5);
- unaway_sound_entry = gtk_entry_new ();
- gtk_widget_show (unaway_sound_entry);
- gtk_table_attach (GTK_TABLE (table5), unaway_sound_entry, 1, 3, 3, 4,
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
- (GtkAttachOptions) (0), 0, 0);
- unidle_sound_entry = gtk_entry_new ();
- gtk_widget_show (unidle_sound_entry);
- gtk_table_attach (GTK_TABLE (table5), unidle_sound_entry, 1, 3, 2, 3,
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
- (GtkAttachOptions) (0), 0, 0);
- signon_sound_entry = gtk_entry_new ();
- gtk_widget_show (signon_sound_entry);
- gtk_table_attach (GTK_TABLE (table5), signon_sound_entry, 1, 3, 1, 2,
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
- (GtkAttachOptions) (0), 0, 0);
- unaway_test_but = gtk_button_new_with_mnemonic ("Test");
- gtk_widget_show (unaway_test_but);
- gtk_table_attach (GTK_TABLE (table5), unaway_test_but, 4, 5, 3, 4,
- (GtkAttachOptions) (0),
- (GtkAttachOptions) (0), 0, 0);
- unidle_test_but = gtk_button_new_with_mnemonic ("Test");
- gtk_widget_show (unidle_test_but);
- gtk_table_attach (GTK_TABLE (table5), unidle_test_but, 4, 5, 2, 3,
- (GtkAttachOptions) (0),
- (GtkAttachOptions) (0), 0, 0);
- signon_test_but = gtk_button_new_with_mnemonic ("Test");
- gtk_widget_show (signon_test_but);
- gtk_table_attach (GTK_TABLE (table5), signon_test_but, 4, 5, 1, 2,
- (GtkAttachOptions) (0),
- (GtkAttachOptions) (0), 0, 0);
- unaway_browse_but = gtk_button_new_from_stock ("gtk-open");
- gtk_widget_show (unaway_browse_but);
- gtk_table_attach (GTK_TABLE (table5), unaway_browse_but, 3, 4, 3, 4,
- (GtkAttachOptions) (0),
- (GtkAttachOptions) (0), 0, 0);
- unidle_browse_but = gtk_button_new_from_stock ("gtk-open");
- gtk_widget_show (unidle_browse_but);
- gtk_table_attach (GTK_TABLE (table5), unidle_browse_but, 3, 4, 2, 3,
- (GtkAttachOptions) (0),
- (GtkAttachOptions) (0), 0, 0);
- signon_browse_but = gtk_button_new_from_stock ("gtk-open");
- gtk_widget_show (signon_browse_but);
- gtk_table_attach (GTK_TABLE (table5), signon_browse_but, 3, 4, 1, 2,
- (GtkAttachOptions) (0),
- (GtkAttachOptions) (0), 0, 0);
- im_browse_but = gtk_button_new_from_stock ("gtk-open");
- gtk_widget_show (im_browse_but);
- gtk_table_attach (GTK_TABLE (table5), im_browse_but, 3, 4, 0, 1,
- (GtkAttachOptions) (0),
- (GtkAttachOptions) (0), 0, 0);
- im_sound_entry = gtk_entry_new ();
- gtk_widget_show (im_sound_entry);
- gtk_table_attach (GTK_TABLE (table5), im_sound_entry, 1, 3, 0, 1,
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
- (GtkAttachOptions) (0), 0, 0);
- im_test_but = gtk_button_new_with_mnemonic ("Test");
- gtk_widget_show (im_test_but);
- gtk_table_attach (GTK_TABLE (table5), im_test_but, 4, 5, 0, 1,
- (GtkAttachOptions) (0),
- (GtkAttachOptions) (0), 0, 0);
- label24 = gtk_label_new ("Sound Events");
- gtk_widget_show (label24);
- gtk_frame_set_label_widget (GTK_FRAME (frame3), label24);
- g_signal_connect ((gpointer) edit_win, "destroy",
- G_CALLBACK (on_edit_win_destroy),
- g_signal_connect ((gpointer) applysave_but, "clicked",
- G_CALLBACK (on_apply_clicked),
- g_signal_connect ((gpointer) applysave_but, "clicked",
- G_CALLBACK (on_save_clicked),
- g_signal_connect_swapped ((gpointer) applysave_but, "clicked",
- G_CALLBACK (gtk_widget_destroy),
- GTK_OBJECT (edit_win));
- g_signal_connect ((gpointer) apply_but, "clicked",
- G_CALLBACK (on_apply_clicked),
- g_signal_connect_swapped ((gpointer) apply_but, "clicked",
- G_CALLBACK (gtk_widget_destroy),
- GTK_OBJECT (edit_win));
- g_signal_connect_swapped ((gpointer) cancel_but, "clicked",
- G_CALLBACK (gtk_widget_destroy),
- GTK_OBJECT (edit_win));
- g_signal_connect ((gpointer) unaway_test_but, "clicked",
- G_CALLBACK (on_unaway_test_clicked),
- g_signal_connect ((gpointer) unidle_test_but, "clicked",
- G_CALLBACK (on_unidle_test_clicked),
- g_signal_connect ((gpointer) signon_test_but, "clicked",
- G_CALLBACK (on_signon_test_clicked),
- g_signal_connect ((gpointer) unaway_browse_but, "clicked",
- G_CALLBACK (on_unaway_browse_clicked),
- g_signal_connect ((gpointer) unidle_browse_but, "clicked",
- G_CALLBACK (on_unidle_browse_clicked),
- g_signal_connect ((gpointer) signon_browse_but, "clicked",
- G_CALLBACK (on_signon_browse_clicked),
- g_signal_connect ((gpointer) im_browse_but, "clicked",
- G_CALLBACK (on_im_browse_clicked),
- g_signal_connect ((gpointer) im_test_but, "clicked",
- G_CALLBACK (on_im_test_clicked),
- /* Store pointers to all widgets, for use by lookup_widget(). */
- GLADE_HOOKUP_OBJECT_NO_REF (edit_win, edit_win, "edit_win");
- GLADE_HOOKUP_OBJECT (edit_win, vbox1, "vbox1");
- GLADE_HOOKUP_OBJECT (edit_win, hbox1, "hbox1");
- GLADE_HOOKUP_OBJECT (edit_win, label29, "label29");
- GLADE_HOOKUP_OBJECT (edit_win, name_entry, "name_entry");
- GLADE_HOOKUP_OBJECT (edit_win, label30, "label30");
- GLADE_HOOKUP_OBJECT (edit_win, type_option, "type_option");
- GLADE_HOOKUP_OBJECT (edit_win, menu1, "menu1");
- GLADE_HOOKUP_OBJECT (edit_win, item_buddy, "item_buddy");
- GLADE_HOOKUP_OBJECT (edit_win, item_group, "item_group");
- GLADE_HOOKUP_OBJECT (edit_win, hbuttonbox2, "hbuttonbox2");
- GLADE_HOOKUP_OBJECT (edit_win, applysave_but, "applysave_but");
- GLADE_HOOKUP_OBJECT (edit_win, apply_but, "apply_but");
- GLADE_HOOKUP_OBJECT (edit_win, cancel_but, "cancel_but");
- GLADE_HOOKUP_OBJECT (edit_win, frame3, "frame3");
- GLADE_HOOKUP_OBJECT (edit_win, table5, "table5");
- GLADE_HOOKUP_OBJECT (edit_win, label31, "label31");
- GLADE_HOOKUP_OBJECT (edit_win, label34, "label34");
- GLADE_HOOKUP_OBJECT (edit_win, label33, "label33");
- GLADE_HOOKUP_OBJECT (edit_win, label32, "label32");
- GLADE_HOOKUP_OBJECT (edit_win, unaway_sound_entry, "unaway_sound_entry");
- GLADE_HOOKUP_OBJECT (edit_win, unidle_sound_entry, "unidle_sound_entry");
- GLADE_HOOKUP_OBJECT (edit_win, signon_sound_entry, "signon_sound_entry");
- GLADE_HOOKUP_OBJECT (edit_win, unaway_test_but, "unaway_test_but");
- GLADE_HOOKUP_OBJECT (edit_win, unidle_test_but, "unidle_test_but");
- GLADE_HOOKUP_OBJECT (edit_win, signon_test_but, "signon_test_but");
- GLADE_HOOKUP_OBJECT (edit_win, unaway_browse_but, "unaway_browse_but");
- GLADE_HOOKUP_OBJECT (edit_win, unidle_browse_but, "unidle_browse_but");
- GLADE_HOOKUP_OBJECT (edit_win, signon_browse_but, "signon_browse_but");
- GLADE_HOOKUP_OBJECT (edit_win, im_browse_but, "im_browse_but");
- GLADE_HOOKUP_OBJECT (edit_win, im_sound_entry, "im_sound_entry");
- GLADE_HOOKUP_OBJECT (edit_win, im_test_but, "im_test_but");
- GLADE_HOOKUP_OBJECT (edit_win, label24, "label24");
--- a/smartear/meson.build Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-if TYPES.contains('incomplete') and PURPLE.found()
- smartear = shared_library('smartear',
- dependencies : [PURPLE, GLIB],
- install_dir : PURPLE_LIBDIR)
- PP_PURPLE_BUILD += 'smartear'
-if TYPES.contains('incomplete') and PIDGIN.found()
- gtksmartear = shared_module('gtksmartear',
- dependencies : [PIDGIN, GTK],
- install_dir : PIDGIN_LIBDIR)
- PP_PIDGIN_BUILD += 'gtksmartear'
-if TYPES.contains('incomplete') and FINCH.found()
- gntsmartear = shared_library('gntsmartear',
- dependencies : [FINCH, GNT],
- install_dir : FINCH_LIBDIR)
- PP_FINCH_BUILD += 'gntsmartear'
--- a/smartear/smartear.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,266 +0,0 @@
- * smartear.c - SmartEar plugin for libpurple
- * Copyright (c) 2007 John Bailey <rekkanoryo@rekkanoryo.org>
- * Original code copyright (c) 2003-2007 Matt Perry
- * 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
- * This plugin is a hidden plugin. It follows preferences set by other plugins
- * which are specific to the libpurple UI in use. The GTK+ plugin for Pidgin
- * and the GNT plugin for Finch will list this plugin as a dependency, causing
- * libpurple to load this plugin.
-# include "../pp_config.h"
-#endif /* HAVE_CONFIG_H */
-#include "../common/pp_internal.h"
- SMARTEAR_EVENT_SIGNOFF,
- SMARTEAR_EVENT_IDLECHG,
- SMARTEAR_EVENT_RECEIVEDMSG,
-smartear_event_get_setting_string(SmartEarEvent event)
- const char *setting = NULL;
- case SMARTEAR_EVENT_SIGNON:
- setting = "signon_sound";
- case SMARTEAR_EVENT_SIGNOFF:
- setting = "signoff_sound";
- case SMARTEAR_EVENT_IDLECHG:
- setting = "idlechg_sound";
- case SMARTEAR_EVENT_RECEIVEDMSG:
- setting = "receivedmsg_sound";
- case SMARTEAR_EVENT_SENTMSG:
- setting = "sentmsg_sound";
-smartear_sound_get_default(SmartEarEvent event)
- const char *prefname = NULL, *prefval = NULL;
- prefname = smartear_event_get_setting_string(event);
- prefpath = g_strdup_printf("/plugins/core/smartear/%s", prefname);
- prefval = purple_prefs_get_string(prefpath);
-smartear_sound_determine(const char *bfile, const char *cfile, const char *gfile, SmartEarEvent event)
- const char *pfile = NULL;
- /* if the string is "(Default)" then set the pointer to NULL */
- if(!g_ascii_strcasecmp(bfile, "(Default)"))
- if(!g_ascii_strcasecmp(cfile, "(Default)"))
- if(!g_ascii_strcasecmp(gfile, "(Default)"))
- /* determine the sound to play - if the pointer is NULL, try falling back
- * to another sound - if no sound defined at any level, fall back to the
- pfile = smartear_sound_get_default(event);
-smartear_sound_play(PurpleBuddy *buddy, PurpleAccount *account, SmartEarEvent event)
- const char *bfile = NULL, *cfile = NULL, *gfile = NULL, *pfile = NULL, *setting = NULL;
- PurpleBlistNode *bnode = (PurpleBlistNode *)buddy,
- *cnode = (PurpleBlistNode *)(bnode->parent),
- *gnode = (PurpleBlistNode *)(cnode->parent);
- /* get the setting string */
- setting = smartear_event_get_setting_string(event);
- /* grab the settings from each blist node in the hierarchy */
- bfile = purple_blist_node_get_string(bnode, setting);
- cfile = purple_blist_node_get_string(cnode, setting);
- gfile = purple_blist_node_get_string(gnode, setting);
- /* determine which sound to play */
- pfile = smartear_sound_determine(bfile, cfile, gfile, event);
- purple_sound_play_file(pfile, account);
-smartear_cb_sent_msg(PurpleAccount *account, const gchar *receiver, const gchar *message)
- PurpleBuddy *buddy = purple_find_buddy(account, receiver);
- smartear_sound_play(buddy, account, SMARTEAR_EVENT_SENTMSG);
-smartear_cb_received_msg(PurpleAccount *account, gchar *sender, char *message,
- PurpleConversation *conv, PurpleMessageFlags flags)
- if(!(flags & PURPLE_MESSAGE_SYSTEM)) {
- PurpleBuddy *buddy = purple_find_buddy(account, sender);
- smartear_sound_play(buddy, account, SMARTEAR_EVENT_RECEIVEDMSG);
-smartear_cb_idle(PurpleBuddy *buddy, gboolean wasidle, gboolean nowidle)
- smartear_sound_play(buddy, purple_buddy_get_account(buddy), SMARTEAR_EVENT_IDLECHG);
-smartear_cb_signoff(PurpleBuddy *buddy)
- smartear_sound_play(buddy, purple_buddy_get_account(buddy), SMARTEAR_EVENT_SIGNOFF);
-smartear_cb_signon(PurpleBuddy *buddy)
- smartear_sound_play(buddy, purple_buddy_get_account(buddy), SMARTEAR_EVENT_SIGNON);
-/* Purple Plugin stuff */
-smartear_load(PurplePlugin *plugin)
- void *blist_handle = purple_blist_get_handle();
- void *conv_handle = purple_conversations_get_handle();
- /* blist signals we need to detect the buddy's activities */
- purple_signal_connect(blist_handle, "buddy-signed-on", plugin,
- PURPLE_CALLBACK(smartear_cb_signon), NULL);
- purple_signal_connect(blist_handle, "buddy-signed-off", plugin,
- PURPLE_CALLBACK(smartear_cb_signoff), NULL);
- purple_signal_connect(blist_handle, "buddy-idle-changed", plugin,
- PURPLE_CALLBACK(smartear_cb_idle), NULL);
- /* conv signals we need to detect activities */
- purple_signal_connect(conv_handle, "received-im-msg", plugin,
- PURPLE_CALLBACK(smartear_cb_received_msg), NULL);
- purple_signal_connect(conv_handle, "sent-im-msg", plugin,
- PURPLE_CALLBACK(smartear_cb_sent_msg), NULL);
-smartear_unload(PurplePlugin *plugin)
-PurplePluginInfo smartear_info =
- PURPLE_PLUGIN_MAGIC, /* Magic, my ass */
- PURPLE_MAJOR_VERSION, /* libpurple major version */
- PURPLE_MINOR_VERSION, /* libpurple minor version */
- PURPLE_PLUGIN_STANDARD, /* plugin type - this is a normal plugin */
- NULL, /* UI requirement - we're invisible! */
- PURPLE_PLUGIN_FLAG_INVISIBLE, /* flags - we're invisible! */
- NULL, /* dependencies - we have none */
- PURPLE_PRIORITY_DEFAULT, /* priority - nothing special here */
- "core-plugin_pack-smartear", /* Plugin ID */
- NULL, /* name - defined later for i18n */
- PP_VERSION, /* plugin version - use plugin pack version */
- NULL, /* summary - defined later for i18n */
- NULL, /* description - defined later for i18n */
- "John Bailey <rekkanoryo@rekkanoryo.org>", /* author */
- PP_WEBSITE, /* plugin website - use plugin pack website */
- smartear_load, /* plugin load - purple calls this when loading */
- smartear_unload, /* plugin unload - purple calls this when unloading */
- NULL, /* plugin destroy - we don't need one */
- NULL, /* ui_info - we don't need this */
- NULL, /* extra_info - we don't need this */
- NULL, /* prefs_info - we don't need this yet */
- NULL, /* actions - we don't have any */
-smartear_init(PurplePlugin *plugin)
- bindtextdomain(GETTEXT_PACKAGE, PP_LOCALEDIR);
- bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
- smartear_info.name = _("Smart Ear - Hidden Core Plugin");
- smartear_info.summary = _("The Core component of the Smart Ear plugins");
- smartear_info.description = _("The Core component of the Smart Ear plugins");
-PURPLE_INIT_PLUGIN(smartear, smartear_init, smartear_info)
--- a/stocker/README.md Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-notes: This plugin partially works but is buggy and in need of TLC.
-Adds a stock ticker similar to the one in the Windows AIM client to the bottom of the buddy list.
--- a/stocker/gtkticker.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,513 +0,0 @@
-/* GTK - The GIMP Toolkit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- * This library 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
- * Library General Public License for more details.
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02111-1301, USA.
- * GtkTicker Copyright 2000 Syd Logan
-static void gtk_ticker_compute_offsets (GtkTicker *ticker);
-static void gtk_ticker_class_init (GtkTickerClass *klass);
-static void gtk_ticker_init (GtkTicker *ticker);
-static void gtk_ticker_map (GtkWidget *widget);
-static void gtk_ticker_realize (GtkWidget *widget);
-static void gtk_ticker_size_request (GtkWidget *widget,
- GtkRequisition *requisition);
-static void gtk_ticker_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation);
-static void gtk_ticker_add_real (GtkContainer *container,
-static void gtk_ticker_remove_real (GtkContainer *container,
-static void gtk_ticker_forall (GtkContainer *container,
- gboolean include_internals,
- gpointer callback_data);
-static GtkType gtk_ticker_child_type (GtkContainer *container);
-static GtkContainerClass *parent_class = NULL;
-GType gtk_ticker_get_type (void)
- static GType ticker_type = 0;
- ticker_type = g_type_from_name("GtkTicker");
- static const GTypeInfo ticker_info =
- sizeof(GtkTickerClass),
- (GClassInitFunc) gtk_ticker_class_init,
- (GInstanceInitFunc) gtk_ticker_init
- ticker_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkTicker",
- /* kludge to re-initialise the class if it's already registered */
- else if (parent_class == NULL) {
- gtk_ticker_class_init((GtkTickerClass *)g_type_class_peek(ticker_type));
-static void gtk_ticker_finalize(GObject *object) {
- gtk_ticker_stop_scroll(GTK_TICKER(object));
- G_OBJECT_CLASS(parent_class)->finalize(object);
-static void gtk_ticker_class_init (GtkTickerClass *class)
- GObjectClass *gobject_class;
- GtkWidgetClass *widget_class;
- GtkContainerClass *container_class;
- gobject_class = (GObjectClass*) class;
- widget_class = (GtkWidgetClass*) class;
- container_class = (GtkContainerClass*) class;
- parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
- gobject_class->finalize = gtk_ticker_finalize;
- widget_class->map = gtk_ticker_map;
- widget_class->realize = gtk_ticker_realize;
- widget_class->size_request = gtk_ticker_size_request;
- widget_class->size_allocate = gtk_ticker_size_allocate;
- container_class->add = gtk_ticker_add_real;
- container_class->remove = gtk_ticker_remove_real;
- container_class->forall = gtk_ticker_forall;
- container_class->child_type = gtk_ticker_child_type;
-static GtkType gtk_ticker_child_type (GtkContainer *container)
- return GTK_TYPE_WIDGET;
-static void gtk_ticker_init (GtkTicker *ticker)
- GTK_WIDGET_UNSET_FLAGS (ticker, GTK_NO_WINDOW);
- ticker->interval = (guint) 200;
- ticker->scootch = (guint) 2;
- ticker->children = NULL;
-GtkWidget* gtk_ticker_new (void)
- return GTK_WIDGET(g_object_new(GTK_TYPE_TICKER, NULL));
-static void gtk_ticker_put (GtkTicker *ticker, GtkWidget *widget)
- GtkTickerChild *child_info;
- g_return_if_fail (ticker != NULL);
- g_return_if_fail (GTK_IS_TICKER (ticker));
- g_return_if_fail (widget != NULL);
- child_info = g_new(GtkTickerChild, 1);
- child_info->widget = widget;
- gtk_widget_set_parent(widget, GTK_WIDGET (ticker));
- ticker->children = g_list_append (ticker->children, child_info);
- if (GTK_WIDGET_REALIZED (ticker))
- gtk_widget_realize (widget);
- if (GTK_WIDGET_VISIBLE (ticker) && GTK_WIDGET_VISIBLE (widget))
- if (GTK_WIDGET_MAPPED (ticker))
- gtk_widget_map (widget);
- gtk_widget_queue_resize (GTK_WIDGET (ticker));
-void gtk_ticker_set_interval (GtkTicker *ticker, gint interval)
- g_return_if_fail (ticker != NULL);
- g_return_if_fail (GTK_IS_TICKER (ticker));
- ticker->interval = interval;
-guint gtk_ticker_get_interval (GtkTicker *ticker)
- g_return_val_if_fail (ticker != NULL, -1);
- g_return_val_if_fail (GTK_IS_TICKER (ticker), -1);
- return ticker->interval;
-void gtk_ticker_set_scootch (GtkTicker *ticker, gint scootch)
- g_return_if_fail (ticker != NULL);
- g_return_if_fail (GTK_IS_TICKER (ticker));
- ticker->scootch = scootch;
-guint gtk_ticker_get_scootch (GtkTicker *ticker )
- g_return_val_if_fail (ticker != NULL, -1);
- g_return_val_if_fail (GTK_IS_TICKER (ticker), -1);
- return ticker->scootch;
-void gtk_ticker_set_spacing (GtkTicker *ticker, gint spacing )
- g_return_if_fail (ticker != NULL);
- g_return_if_fail (GTK_IS_TICKER (ticker));
- ticker->spacing = spacing;
-static int ticker_timeout(gpointer data)
- GtkTicker *ticker = (GtkTicker *) data;
- if (GTK_WIDGET_VISIBLE (ticker))
- gtk_widget_queue_resize (GTK_WIDGET (ticker));
-void gtk_ticker_start_scroll(GtkTicker *ticker)
- g_return_if_fail (ticker != NULL);
- g_return_if_fail (GTK_IS_TICKER (ticker));
- if ( ticker->timer != 0 )
- ticker->timer = g_timeout_add(ticker->interval, ticker_timeout, ticker);
-void gtk_ticker_stop_scroll(GtkTicker *ticker)
- g_return_if_fail (ticker != NULL);
- g_return_if_fail (GTK_IS_TICKER (ticker));
- if ( ticker->timer == 0 )
- g_source_remove(ticker->timer);
-guint gtk_ticker_get_spacing (GtkTicker *ticker )
- g_return_val_if_fail (ticker != NULL, -1);
- g_return_val_if_fail (GTK_IS_TICKER (ticker), -1);
- return ticker->spacing;
-static void gtk_ticker_map (GtkWidget *widget)
- g_return_if_fail (widget != NULL);
- g_return_if_fail (GTK_IS_TICKER (widget));
- GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
- ticker = GTK_TICKER (widget);
- children = ticker->children;
- child = children->data;
- children = children->next;
- if (GTK_WIDGET_VISIBLE (child->widget) &&
- !GTK_WIDGET_MAPPED (child->widget))
- gtk_widget_map (child->widget);
- gdk_window_show (widget->window);
-static void gtk_ticker_realize (GtkWidget *widget)
- GdkWindowAttr attributes;
- g_return_if_fail (widget != NULL);
- g_return_if_fail (GTK_IS_TICKER (widget));
- GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
- attributes.window_type = GDK_WINDOW_CHILD;
- attributes.x = widget->allocation.x;
- attributes.y = widget->allocation.y;
- attributes.width = widget->allocation.width;
- attributes.height = widget->allocation.height;
- attributes.wclass = GDK_INPUT_OUTPUT;
- attributes.visual = gtk_widget_get_visual (widget);
- attributes.colormap = gtk_widget_get_colormap (widget);
- attributes.event_mask = gtk_widget_get_events (widget);
- attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK;
- attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
- widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
- &attributes, attributes_mask);
- gdk_window_set_user_data (widget->window, widget);
- widget->style = gtk_style_attach (widget->style, widget->window);
- gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
-static void gtk_ticker_size_request (GtkWidget *widget, GtkRequisition *requisition)
- GtkRequisition child_requisition;
- g_return_if_fail (widget != NULL);
- g_return_if_fail (GTK_IS_TICKER (widget));
- g_return_if_fail (requisition != NULL);
- ticker = GTK_TICKER (widget);
- requisition->width = 0;
- requisition->height = 0;
- children = ticker->children;
- child = children->data;
- children = children->next;
- if (GTK_WIDGET_VISIBLE (child->widget))
- gtk_widget_size_request (child->widget, &child_requisition);
- requisition->height = MAX (requisition->height,
- child_requisition.height);
- requisition->width += child_requisition.width + ticker->spacing;
- if ( requisition->width > ticker->spacing )
- requisition->width -= ticker->spacing;
- requisition->height += GTK_CONTAINER (ticker)->border_width * 2;
- requisition->width += GTK_CONTAINER (ticker)->border_width * 2;
-static void gtk_ticker_compute_offsets (GtkTicker *ticker)
- GtkRequisition child_requisition;
- g_return_if_fail (ticker != NULL);
- g_return_if_fail (GTK_IS_TICKER(ticker));
- border_width = GTK_CONTAINER (ticker)->border_width;
- ticker->width = GTK_WIDGET(ticker)->allocation.width;
- children = ticker->children;
- child = children->data;
- if (GTK_WIDGET_VISIBLE (child->widget)) {
- gtk_widget_get_child_requisition (child->widget, &child_requisition);
- child->offset = ticker->total;
- child_requisition.width + border_width + ticker->spacing;
- children = children->next;
-static void gtk_ticker_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation)
- GtkAllocation child_allocation;
- GtkRequisition child_requisition;
- g_return_if_fail (widget != NULL);
- g_return_if_fail (GTK_IS_TICKER(widget));
- g_return_if_fail (allocation != NULL);
- ticker = GTK_TICKER (widget);
- if ( GTK_WIDGET(ticker)->allocation.width != ticker->width )
- if ( ticker->dirty == TRUE ) {
- gtk_ticker_compute_offsets( ticker );
- widget->allocation = *allocation;
- if (GTK_WIDGET_REALIZED (widget))
- gdk_window_move_resize (widget->window,
- border_width = GTK_CONTAINER (ticker)->border_width;
- children = ticker->children;
- child = children->data;
- child->x -= ticker->scootch;
- if (GTK_WIDGET_VISIBLE (child->widget)) {
- gtk_widget_get_child_requisition (child->widget, &child_requisition);
- child_allocation.width = child_requisition.width;
- child_allocation.x = child->offset + border_width + child->x;
- if ( ( child_allocation.x + child_allocation.width ) < GTK_WIDGET(ticker)->allocation.x ) {
- if ( ticker->total >= GTK_WIDGET(ticker)->allocation.width ) {
- child->x += GTK_WIDGET(ticker)->allocation.x + GTK_WIDGET(ticker)->allocation.width + ( ticker->total - ( GTK_WIDGET(ticker)->allocation.x + GTK_WIDGET(ticker)->allocation.width ) );
- child->x += GTK_WIDGET(ticker)->allocation.x + GTK_WIDGET(ticker)->allocation.width;
- child_allocation.y = border_width;
- child_allocation.height = child_requisition.height;
- gtk_widget_size_allocate (child->widget, &child_allocation);
- children = children->next;
-void gtk_ticker_add(GtkTicker *ticker, GtkWidget *widget)
- gtk_ticker_add_real( GTK_CONTAINER( ticker ), widget );
-void gtk_ticker_remove(GtkTicker *ticker, GtkWidget *widget)
- gtk_ticker_remove_real( GTK_CONTAINER( ticker ), widget );
-static void gtk_ticker_add_real(GtkContainer *container, GtkWidget *widget)
- g_return_if_fail (container != NULL);
- g_return_if_fail (GTK_IS_TICKER (container));
- g_return_if_fail (widget != NULL);
- gtk_ticker_put(GTK_TICKER (container), widget);
-static void gtk_ticker_remove_real(GtkContainer *container, GtkWidget *widget)
- g_return_if_fail (container != NULL);
- g_return_if_fail (GTK_IS_TICKER (container));
- g_return_if_fail (widget != NULL);
- ticker = GTK_TICKER (container);
- children = ticker->children;
- child = children->data;
- if (child->widget == widget)
- gboolean was_visible = GTK_WIDGET_VISIBLE (widget);
- gtk_widget_unparent (widget);
- ticker->children = g_list_remove_link (ticker->children, children);
- g_list_free (children);
- if (was_visible && GTK_WIDGET_VISIBLE (container))
- gtk_widget_queue_resize (GTK_WIDGET (container));
- children = children->next;
-static void gtk_ticker_forall (GtkContainer *container,
- gboolean include_internals,
- gpointer callback_data)
- g_return_if_fail (container != NULL);
- g_return_if_fail (GTK_IS_TICKER (container));
- g_return_if_fail (callback != NULL);
- ticker = GTK_TICKER (container);
- children = ticker->children;
- child = children->data;
- children = children->next;
- (* callback) (child->widget, callback_data);
--- a/stocker/gtkticker.h Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/* GTK - The GIMP Toolkit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- * This library 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
- * Library General Public License for more details.
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02111-1301, USA.
- * Copyright 2000 Syd Logan
-#ifndef __GTK_TICKER_H__
-#define __GTK_TICKER_H__
-#include <gtk/gtkcontainer.h>
-#include <gtk/gtkmain.h>
-#endif /* __cplusplus */
-#define GTK_TYPE_TICKER (gtk_ticker_get_type ())
-#define GTK_TICKER(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_TICKER, GtkTicker))
-#define GTK_TICKER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_TICKER, GtkTickerClass))
-#define GTK_IS_TICKER(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_TICKER))
-#define GTK_IS_TICKER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_TICKER))
-typedef struct _GtkTicker GtkTicker;
-typedef struct _GtkTickerClass GtkTickerClass;
-typedef struct _GtkTickerChild GtkTickerChild;
-/* XXX children move from right to left, should be able to go other way */
- GtkContainer container;
- guint interval; /* how often to scootch */
- gint spacing; /* inter-child horizontal spacing */
- guint scootch; /* how many pixels to move each scootch */
- gint timer; /* timer object */
- gint total; /* total width of widgets */
- gint width; /* width of containing window */
- GtkContainerClass parent_class;
- gint x; /* current position */
- gint offset; /* offset in list */
-GtkType gtk_ticker_get_type (void);
-GtkWidget* gtk_ticker_new (void);
-void gtk_ticker_add (GtkTicker *ticker,
-void gtk_ticker_remove (GtkTicker *ticker,
-void gtk_ticker_set_interval (GtkTicker *ticker,
-guint gtk_ticker_get_interval (GtkTicker *ticker);
-void gtk_ticker_set_spacing (GtkTicker *ticker,
-guint gtk_ticker_get_spacing (GtkTicker *ticker);
-void gtk_ticker_set_scootch (GtkTicker *ticker,
-guint gtk_ticker_get_scootch (GtkTicker *ticker);
-void gtk_ticker_start_scroll (GtkTicker *ticker);
-void gtk_ticker_stop_scroll (GtkTicker *ticker);
-#endif /* __cplusplus */
-#endif /* __GTK_TICKER_H__ */
--- a/stocker/meson.build Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-if TYPES.contains('incomplete') and PIDGIN.found()
- stocker = shared_module('stocker',
- dependencies : [PIDGIN, GTK],
- install_dir : PIDGIN_LIBDIR)
- PP_PIDGIN_BUILD += 'stocker'
--- a/stocker/stocker.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,412 +0,0 @@
- * Stocker - Adds a stock ticker to the buddy list
- * Copyright (C) 2005-2008 Gary Kramlich <grim@reaperworld.com>
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA
-/* If you can't figure out what this line is for, DON'T TOUCH IT. */
-#include "../common/pp_internal.h"
-#include "stocker_prefs.h"
-#define URL_REQUEST "http://quotewebvip-m01.blue.aol.com/?action=aim&syms=%s&fields=nspg"
-#define CHANGE_INCREASE "<span color=\"green3\">%+0.04g</span>"
-#define CHANGE_DECREASE "<span color=\"red\">%+0.04g</span>"
-#define CHANGE_NONE "%0.04g"
-/******************************************************************************
- *****************************************************************************/
-#define STOCKER_QUOTE(obj) ((StockerQuote *)(obj))
-/******************************************************************************
- *****************************************************************************/
-static GtkWidget *ticker = NULL;
-static GHashTable *quotes = NULL;
-static guint quotes_id = 0, interval_id = 0, interval_timer = 0;
-/******************************************************************************
- *****************************************************************************/
-stocker_quote_new(const gchar *symbol) {
- StockerQuote *ret = g_new0(StockerQuote, 1);
- ret->symbol = g_strdup(symbol);
- label = g_strdup_printf("%s (refreshing)", symbol);
- ret->label = gtk_label_new(label);
- gtk_ticker_add(GTK_TICKER(ticker), ret->label);
- gtk_widget_show(ret->label);
-stocker_quote_ref(StockerQuote *quote) {
-stocker_quote_unref(StockerQuote *quote) {
- gtk_widget_destroy(quote->label);
-stocker_quote_update(StockerQuote *quote, const gchar *name, gdouble current,
- GString *str = g_string_sized_new(512);
- g_string_append_printf(str,
- "<span weight=\"bold\">%s</span> "
- "<span size=\"small\">(%s)</span> $%g ",
- name, quote->symbol, current);
- g_string_append_printf(str, CHANGE_DECREASE, change);
- g_string_append_printf(str, CHANGE_INCREASE, change);
- g_string_append_printf(str, CHANGE_NONE, change);
- gtk_label_set_markup(GTK_LABEL(quote->label), str->str);
- g_string_free(str, TRUE);
-/******************************************************************************
- *****************************************************************************/
-stocker_refresh_url_cb(PurpleUtilFetchUrlData *url_data, gpointer data,
- const gchar *text, gsize len, const gchar *errmsg)
- while((p = g_strstr_len(p, strlen(p), "DATA="))) {
- const gchar *name = NULL, *symbol = NULL;
- gdouble current = 0.0, change = 0.0;
- /* move paste the data text */
- /* find the current price */
- /* now move p to the EOL */
- StockerQuote *quote = g_hash_table_lookup(quotes, symbol);
- stocker_quote_update(quote, name, current, change);
-stocker_refresh_helper(gpointer k, gpointer v, gpointer d) {
- GString *str = (GString *)d;
- gchar *symbol = (gchar *)k;
- g_string_append_printf(str, "%s%s",
- (str->len > 0) ? "," : "",
- GString *syms = g_string_sized_new(64);
- g_hash_table_foreach(quotes, stocker_refresh_helper, syms);
- url = g_strdup_printf(URL_REQUEST, syms->str);
- g_string_free(syms, TRUE);
- purple_util_fetch_url(url, TRUE, "purple", TRUE,
- stocker_refresh_url_cb,
- PurpleBuddyList *blist;
- PidginBuddyList *gtkblist;
- if(GTK_IS_WIDGET(ticker))
- gtk_widget_destroy(ticker);
- blist = purple_get_blist();
- gtkblist = PIDGIN_BLIST(blist);
- ticker = gtk_ticker_new();
- gtk_box_pack_start(GTK_BOX(gtkblist->vbox), ticker, FALSE, FALSE, 0);
- gtk_ticker_set_spacing(GTK_TICKER(ticker), 16);
- gtk_ticker_start_scroll(GTK_TICKER(ticker));
- gtk_widget_show_all(ticker);
-stocker_blist_created(PurpleBuddyList *blist, gpointer data) {
-stocker_quotes_refresh(GList *symbols) {
- StockerQuote *quote = NULL;
- GHashTable *new_quotes = NULL, *temp = NULL;
- /* this is a bit more complicated than I'd like, but we need a way to be
- * able to remove quotes that we don't know by name. So we create a new
- * hashtable, copy all the existing quotes over to it, add the new ones,
- * then delete the old table and use the new one.
- new_quotes = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
- (GDestroyNotify)stocker_quote_unref);
- for(l = symbols; l; l = l->next) {
- gchar *symbol = l->data;
- /* sanity check to make sure we have a symbol */
- quote = g_hash_table_lookup(quotes, symbol);
- /* ref the quote so it stays alive */
- stocker_quote_ref(quote);
- /* this is a new symbol, create a quote for it */
- quote = stocker_quote_new(symbol);
- /* insert the quote into the new hashtable */
- g_hash_table_insert(new_quotes, g_strdup(symbol), quote);
- /* hold onto the old pointer */
- /* update the pointer to the updated list */
- /* kill the old table */
- g_hash_table_destroy(temp);
- /* refresh everything */
-stocker_quotes_changed_cb(const gchar *name, PurplePrefType type,
- gconstpointer value, gpointer data)
- stocker_quotes_refresh((GList *)value);
-stocker_refresh_cb(gpointer data) {
-stocker_interval_changed_cb(const gchar *name, PurplePrefType type,
- gconstpointer value, gpointer data)
- gint new_time = GPOINTER_TO_INT(value);
- /* remove the old timer */
- purple_timeout_remove(interval_timer);
- interval_timer = purple_timeout_add_seconds(new_time * 60,
- stocker_refresh_cb, NULL);
-/******************************************************************************
- *****************************************************************************/
-stocker_load(PurplePlugin *plugin) {
- void *prefs_handle = purple_prefs_get_handle();
- quotes = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
- (GDestroyNotify)stocker_quote_unref);
- purple_signal_connect(pidgin_blist_get_handle(), "gtkblist-created",
- PURPLE_CALLBACK(stocker_blist_created), NULL);
- quotes_id = purple_prefs_connect_callback(prefs_handle, PREF_SYMBOLS,
- stocker_quotes_changed_cb,
- interval_id = purple_prefs_connect_callback(prefs_handle, PREF_INTERVAL,
- stocker_interval_changed_cb,
- interval = 60 * purple_prefs_get_int(PREF_INTERVAL);
- interval_timer = purple_timeout_add_seconds(interval, stocker_refresh_cb,
- stocker_quotes_refresh(purple_prefs_get_string_list(PREF_SYMBOLS));
-stocker_unload(PurplePlugin *plugin) {
-stocker_destroy(PurplePlugin *plugin) {
- purple_timeout_remove(interval_timer);
- if(GTK_IS_WIDGET(ticker))
- gtk_widget_destroy(ticker);
-static PidginPluginUiInfo stocker_ui_info = { stocker_prefs_get_frame };
-static PurplePluginInfo stocker_info =
- PURPLE_PLUGIN_STANDARD,
- PURPLE_PRIORITY_DEFAULT,
- "gtk-plugin_pack-stocker",
- "Gary Kramlich <grim@reaperworld.com>",
-stocker_init(PurplePlugin *plugin) {
- bindtextdomain(GETTEXT_PACKAGE, PP_LOCALEDIR);
- bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
- stocker_info.name = _("Stocker");
- stocker_info.summary = _("A stock ticker");
- stocker_info.description =
- _("Adds a stock ticker similar to the one in the Windows AIM client to"
- " the bottom of the buddy list.");
-PURPLE_INIT_PLUGIN(stocker, stocker_init, stocker_info)
--- a/stocker/stocker_prefs.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,323 +0,0 @@
- * Stocker - Adds a stock ticker to the buddy list
- * Copyright (C) 2005-2008 Gary Kramlich <grim@reaperworld.com>
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA
-/* If you can't figure out what this line is for, DON'T TOUCH IT. */
-#include "../common/pp_internal.h"
-#include "stocker_prefs.h"
-/******************************************************************************
- *****************************************************************************/
-#define STOCKER_PREFS(obj) ((StockerPrefs *)(obj))
-/******************************************************************************
- *****************************************************************************/
-stocker_prefs_update_list(StockerPrefs *prefs) {
- gtk_list_store_clear(prefs->symbols);
- for(l = purple_prefs_get_string_list(PREF_SYMBOLS); l; l = l->next) {
- symbol = (gchar *)l->data;
- gtk_list_store_append(prefs->symbols, &iter);
- gtk_list_store_set(prefs->symbols, &iter,
-stocker_prefs_apply_helper(GtkTreeModel *model, GtkTreePath *path,
- GtkTreeIter *iter, gpointer data)
- GList **symbols = (GList **)data;
- gtk_tree_model_get(model, iter,
- *symbols = g_list_append(*symbols, symbol);
-stocker_prefs_apply_cb(GtkButton *button, gpointer data) {
- StockerPrefs *prefs = (StockerPrefs *)data;
- GList *symbols = NULL, *l;
- gtk_tree_model_foreach(GTK_TREE_MODEL(prefs->symbols),
- stocker_prefs_apply_helper, &symbols);
- purple_prefs_set_string_list(PREF_SYMBOLS, symbols);
- for(l = symbols; l; l = l->next)
-stocker_prefs_add_cb(GtkButton *button, gpointer data) {
- StockerPrefs *prefs = (StockerPrefs *)data;
- symbol = gtk_entry_get_text(GTK_ENTRY(prefs->entry));
- if(g_utf8_strlen(symbol, -1) <= 0)
- gtk_list_store_append(prefs->symbols, &iter);
- gtk_list_store_set(prefs->symbols, &iter,
- gtk_entry_set_text(GTK_ENTRY(prefs->entry), "");
-stocker_prefs_remove_cb(GtkButton *button, gpointer data) {
- StockerPrefs *prefs = (StockerPrefs *)data;
- sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(prefs->list));
- if(!gtk_tree_selection_get_selected(sel, NULL, &iter))
- gtk_tree_model_get(GTK_TREE_MODEL(prefs->symbols), &iter,
- gtk_entry_set_text(GTK_ENTRY(prefs->entry), symbol);
- gtk_list_store_remove(prefs->symbols, &iter);
-stocker_prefs_move_up_cb(GtkButton *button, gpointer data) {
- StockerPrefs *prefs = STOCKER_PREFS(data);
- GtkTreeIter siter, diter;
- sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(prefs->list));
- if(!gtk_tree_selection_get_selected(sel, NULL, &siter)) {
- path = gtk_tree_model_get_path(GTK_TREE_MODEL(prefs->symbols), &siter);
- if(!gtk_tree_path_prev(path))
- if(!gtk_tree_model_get_iter(GTK_TREE_MODEL(prefs->symbols), &diter, path))
- gtk_tree_path_free(path);
- gtk_tree_path_free(path);
-#if GTK_CHECK_VERSION(2,2,0)
- gtk_list_store_swap(prefs->symbols, &siter, &diter);
-# warning Someone make me work on gtk < 2.2.0
-stocker_prefs_move_down_cb(GtkButton *button, gpointer data) {
- StockerPrefs *prefs = STOCKER_PREFS(data);
- GtkTreeIter siter, diter;
- sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(prefs->list));
- if(!gtk_tree_selection_get_selected(sel, NULL, &siter)) {
- path = gtk_tree_model_get_path(GTK_TREE_MODEL(prefs->symbols), &siter);
- gtk_tree_path_next(path);
- if(!gtk_tree_model_get_iter(GTK_TREE_MODEL(prefs->symbols), &diter, path))
- gtk_tree_path_free(path);
- gtk_tree_path_free(path);
-#if GTK_CHECK_VERSION(2,2,0)
- gtk_list_store_swap(prefs->symbols, &siter, &diter);
-# warning Someone make me work on gtk < 2.2.0
-stocker_prefs_destroyed(gpointer data) {
- StockerPrefs *prefs = STOCKER_PREFS(data);
- g_object_unref(G_OBJECT(prefs->symbols));
-/******************************************************************************
- *****************************************************************************/
-stocker_prefs_init(void) {
- GList *def_syms = NULL;
- def_syms = g_list_append(def_syms, "GOOG");
- def_syms = g_list_append(def_syms, "YHOO");
- def_syms = g_list_append(def_syms, "RHT");
- def_syms = g_list_append(def_syms, "VMW");
- purple_prefs_add_none(PREF_MY);
- purple_prefs_add_none(PREF_ROOT);
- purple_prefs_add_string_list(PREF_SYMBOLS, def_syms);
- purple_prefs_add_int(PREF_INTERVAL, 30);
-stocker_prefs_get_frame(PurplePlugin *plugin) {
- StockerPrefs *prefs = g_new0(StockerPrefs, 1);
- GtkWidget *ret, *vbox, *hbox, *box, *frame, *sw, *label, *button;
- GtkTreeViewColumn *col;
- sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
- ret = gtk_vbox_new(FALSE, 4);
- gtk_container_set_border_width(GTK_CONTAINER(ret), 12);
- g_object_set_data_full(G_OBJECT(ret), "prefs", prefs,
- stocker_prefs_destroyed);
- /**********************************
- *********************************/
- frame = pidgin_make_frame(ret, _("Symbols"));
- box = gtk_hbox_new(FALSE, 4);
- gtk_box_pack_start(GTK_BOX(frame), box, FALSE, FALSE, 0);
- vbox = gtk_vbox_new(FALSE, 4);
- gtk_box_pack_start(GTK_BOX(box), vbox, FALSE, FALSE, 0);
- hbox = gtk_hbox_new(FALSE, 4);
- gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
- label = gtk_label_new(_("Symbol:"));
- gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
- gtk_size_group_add_widget(sg, label);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
- prefs->entry = gtk_entry_new();
- gtk_box_pack_start(GTK_BOX(hbox), prefs->entry, FALSE, FALSE, 0);
- sw = gtk_scrolled_window_new(NULL, NULL);
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
- GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN);
- gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0);
- /* yes we purposely keep a reference.... */
- prefs->symbols = gtk_list_store_new(1, G_TYPE_STRING);
- stocker_prefs_update_list(prefs);
- prefs->list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(prefs->symbols));
- gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(prefs->list), FALSE);
- gtk_tree_view_set_reorderable(GTK_TREE_VIEW(prefs->list), TRUE);
- gtk_container_add(GTK_CONTAINER(sw), prefs->list);
- rend = gtk_cell_renderer_text_new();
- col = gtk_tree_view_column_new_with_attributes("Symbol", rend,
- gtk_tree_view_append_column(GTK_TREE_VIEW(prefs->list), col);
- vbox = gtk_vbox_new(FALSE, 4);
- gtk_box_pack_start(GTK_BOX(box), vbox, FALSE, FALSE, 0);
- button = gtk_button_new_from_stock(GTK_STOCK_ADD);
- g_signal_connect(G_OBJECT(button), "clicked",
- G_CALLBACK(stocker_prefs_add_cb), prefs);
- gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
- button = gtk_button_new_from_stock(GTK_STOCK_REMOVE);
- g_signal_connect(G_OBJECT(button), "clicked",
- G_CALLBACK(stocker_prefs_remove_cb), prefs);
- gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
- button = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN);
- g_signal_connect(G_OBJECT(button), "clicked",
- G_CALLBACK(stocker_prefs_move_down_cb), prefs);
- gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
- button = gtk_button_new_from_stock(GTK_STOCK_GO_UP);
- g_signal_connect(G_OBJECT(button), "clicked",
- G_CALLBACK(stocker_prefs_move_up_cb), prefs);
- gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
- button = gtk_button_new_from_stock(GTK_STOCK_APPLY);
- g_signal_connect(G_OBJECT(button), "clicked",
- G_CALLBACK(stocker_prefs_apply_cb), prefs);
- gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
- /**********************************
- *********************************/
- frame = pidgin_make_frame(ret, _("Options"));
- pidgin_prefs_labeled_spin_button(frame, "Update interval (minutes):",
- PREF_INTERVAL, 1, 1440, sg);
- /* show and return it already! */
- gtk_widget_show_all(ret);
--- a/stocker/stocker_prefs.h Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
- * Stocker - Adds a stock ticker to the buddy list
- * Copyright (C) 2005-2008 Gary Kramlich <grim@reaperworld.com>
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA
-#define PREF_MY "/plugins/gtk/plugin_pack"
-#define PREF_ROOT "/plugins/gtk/plugin_pack/stocker"
-#define PREF_SYMBOLS "/plugins/gtk/plugin_pack/stocker/symbols"
-#define PREF_INTERVAL "/plugins/gtk/plugin_pack/stocker/interval"
-void stocker_prefs_init(void);
-GtkWidget *stocker_prefs_get_frame(PurplePlugin *plugin);
-#endif /* STOCKER_PREFS_H */
--- a/stress/README.md Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
--- a/stress/meson.build Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-if TYPES.contains('abusive') and PURPLE.found()
- stress = shared_library('stress',
- dependencies : [PURPLE, GLIB],
- install_dir : PURPLE_LIBDIR)
- PP_PURPLE_BUILD += 'stress'
--- a/stress/stress.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,494 +0,0 @@
- * stress - stresses libpurple's event system
- * Copyright (C) 2008 Gary Kramlich <grim@reaperworld.com>
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
-#include "../common/pp_internal.h"
-#define STRESS_BUDDY(buddy) \
- ((StressBuddy *)purple_buddy_get_protocol_data(buddy))
-/******************************************************************************
- *****************************************************************************/
-/******************************************************************************
- *****************************************************************************/
- STRESS_EVENT_STOPPED_TYPING,
- STRESS_EVENT_SEND_MESSAGE,
-/******************************************************************************
- *****************************************************************************/
-static GList *buddies = NULL;
-static GList *events = NULL;
-static gint nevents = 0;
-static gint message_min = 0;
-static gint message_max = 0;
-/******************************************************************************
- *****************************************************************************/
-stress_send_im(PurpleAccount *account, PurpleBuddy *buddy, const gchar *name) {
- PurpleConnection *pc = NULL;
- gint length = 0, i = 0;
- /* build the message */
- msg = g_string_new("");
- length = (rand() % (message_max - message_min)) + message_min;
- for(i = 0; i < length; i += 4) {
- gint value = rand() % 65536;
- g_string_append_printf(msg, "%04x", value);
- pc = purple_account_get_connection(account);
- serv_got_im(pc, name, msg->str, 0, time(NULL));
- g_string_free(msg, TRUE);
-stress_close_convs(PurpleAccount *account, const gchar *name) {
- PurpleConversation *conv = NULL;
- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name,
- purple_conversation_destroy(conv);
-stress_event_cb(gpointer data) {
- StressBuddy *sb = (StressBuddy *)data;
- PurpleAccount *account = purple_buddy_get_account(sb->buddy);
- PurpleStatus *status = NULL;
- gint event = rand() % nevents;
- const gchar *name = purple_buddy_get_name(sb->buddy), *sevent = NULL;
- /* increment our event counter */
- event = GPOINTER_TO_INT(g_list_nth_data(events, event));
- case STRESS_EVENT_SIGN_ON: sevent = "signon"; break;
- case STRESS_EVENT_SIGN_OFF: sevent = "signoff"; break;
- case STRESS_EVENT_IDLE: sevent = "idle"; break;
- case STRESS_EVENT_UNIDLE: sevent = "unidle"; break;
- case STRESS_EVENT_AWAY: sevent = "away"; break;
- case STRESS_EVENT_BACK: sevent = "back"; break;
- case STRESS_EVENT_TYPING: sevent = "typing"; break;
- case STRESS_EVENT_STOPPED_TYPING: sevent = "stopped typing"; break;
- case STRESS_EVENT_SEND_MESSAGE: sevent = "message"; break;
- purple_debug_info("stress", "firing '%s' for '%s' (event %d of %d)\n",
- sevent, name, sb->nevents, sb->maxevents);
- case STRESS_EVENT_SIGN_ON:
- case STRESS_EVENT_BACK:
- purple_prpl_got_user_status(account, name, "available", NULL);
- case STRESS_EVENT_SIGN_OFF:
- purple_prpl_got_user_status(account, name, "offline", NULL);
- case STRESS_EVENT_IDLE:
- purple_prpl_got_user_idle(account, name, TRUE, 0);
- case STRESS_EVENT_UNIDLE:
- purple_prpl_got_user_idle(account, name, FALSE, 0);
- case STRESS_EVENT_AWAY:
- purple_prpl_got_user_status(account, name, "away", NULL);
- case STRESS_EVENT_SEND_MESSAGE:
- stress_send_im(account, sb->buddy, name);
- msg = g_strdup_printf("event %d of %d", sb->nevents, sb->maxevents);
- status = purple_presence_get_active_status(sb->buddy->presence);
- purple_status_set_attr_string(status, "message", msg);
- if(sb->maxevents > 0 && sb->nevents >= sb->maxevents) {
- purple_prpl_got_user_status(account, name, "available",
- purple_prpl_got_user_idle(account, name, FALSE, 0);
- stress_close_convs(account, name);
-/******************************************************************************
- *****************************************************************************/
-stress_list_icon(PurpleAccount *account, PurpleBuddy *b) {
-stress_status_text(PurpleBuddy *buddy) {
- PurplePresence *presence = purple_buddy_get_presence(buddy);
- PurpleStatus *status = purple_presence_get_active_status(presence);
- const gchar *msg = NULL;
- msg = purple_status_get_attr_string(status, "message");
- return (msg) ? g_strdup(msg) : NULL;
-#define add_event(setting, e1, e2) G_STMT_START { \
- if(purple_account_get_bool(account, (setting), TRUE)) { \
- events = g_list_prepend(events, GINT_TO_POINTER((e1))); \
- events = g_list_prepend(events, GINT_TO_POINTER((e2))); \
-stress_login(PurpleAccount *account) {
- PurpleConnection *pc = NULL;
- gint n_buddies = 0, i = 0, interval = 0, maxevents = 0;
- /* build our possible events from the account settings */
- add_event("trigger_signon", STRESS_EVENT_SIGN_ON, STRESS_EVENT_SIGN_OFF);
- add_event("trigger_idle", STRESS_EVENT_IDLE, STRESS_EVENT_UNIDLE);
- add_event("trigger_away", STRESS_EVENT_AWAY, STRESS_EVENT_BACK);
- add_event("trigger_typing", STRESS_EVENT_TYPING, STRESS_EVENT_STOPPED_TYPING);
- add_event("send_messages", STRESS_EVENT_SEND_MESSAGE, -1);
- nevents = g_list_length(events);
- /* get our connection and set it as online */
- pc = purple_account_get_connection(account);
- purple_connection_set_state(pc, PURPLE_CONNECTED);
- /* grab the account settings we need for buddies */
- n_buddies = purple_account_get_int(account, "nbuddies", 50);
- maxevents = purple_account_get_int(account, "maxevents", 100);
- interval = (guint)purple_account_get_int(account, "interval", 500);
- message_min = purple_account_get_int(account, "message_min", 16);
- message_max = purple_account_get_int(account, "message_max", 128);
- g = purple_group_new("prpl-stress");
- for(i = 0; i < n_buddies; i++) {
- StressBuddy *sb = NULL;
- /* create the buddy and it's name */
- name = g_strdup_printf("stress-%04x", i);
- b = purple_buddy_new(account, name, NULL);
- /* add our data to the buddy */
- sb = g_new0(StressBuddy, 1);
- sb->maxevents = maxevents;
- purple_buddy_set_protocol_data(b, sb);
- /* add the buddy to our list and the purple blist */
- buddies = g_list_prepend(buddies, sb);
- purple_blist_add_buddy(b, NULL, g, NULL);
- /* add our event timer to the buddy */
- sb->timer_id = g_timeout_add(interval, stress_event_cb, sb);
-stress_close(PurpleConnection *pc) {
- for(l = buddies; l; l = l->next) {
- StressBuddy *sb = l->data;
- purple_blist_remove_buddy(sb->buddy);
- g = purple_find_group("prpl-stress");
- purple_blist_remove_group(g);
-stress_buddy_free(PurpleBuddy *buddy) {
- StressBuddy *sb = STRESS_BUDDY(buddy);
- g_source_remove(sb->timer_id);
-stress_status_types(PurpleAccount *account) {
- PurpleStatusType *type = NULL;
- g_return_val_if_fail(account != NULL, NULL);
- purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE, NULL,
- NULL, TRUE, TRUE, FALSE,
- "message", _("Message"),
- purple_value_new(PURPLE_TYPE_STRING),
- types = g_list_prepend(types, type);
- purple_status_type_new_with_attrs(PURPLE_STATUS_OFFLINE, NULL,
- NULL, TRUE, TRUE, FALSE,
- "message", _("Message"),
- purple_value_new(PURPLE_TYPE_STRING),
- types = g_list_prepend(types, type);
- purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY, NULL,
- NULL, TRUE, TRUE, FALSE,
- "message", _("Message"),
- purple_value_new(PURPLE_TYPE_STRING),
- types = g_list_prepend(types, type);
-static PurplePluginProtocolInfo prpl_info = {
- NULL, /* stress_send_im, */
- NULL, /* stress_add_buddies, */
- NULL, /* stress_remove_buddies, */
-/******************************************************************************
- *****************************************************************************/
-plugin_load(PurplePlugin *plugin) {
-plugin_unload(PurplePlugin *plugin) {
-stress_actions(PurplePlugin *plugin, gpointer context) {
- PurplePluginAction *act = NULL;
- action = purple_plugin_action_new(_("Start"));
- menu = g_list_append(menu, action);
-static PurplePluginInfo info = {
- PURPLE_PLUGIN_PROTOCOL,
- PURPLE_PRIORITY_DEFAULT,
- "core-plugin_pack-stress",
- "Gary Kramlich <grim@reaperworld.com>",
-#define add_option(type, label, name, def) G_STMT_START { \
- option = purple_account_option_##type##_new((label), (name), (def)); \
- prpl_info.protocol_options = g_list_prepend(prpl_info.protocol_options, (option)); \
-init_plugin(PurplePlugin *plugin) {
- PurpleAccountOption *option = NULL;
- bindtextdomain(GETTEXT_PACKAGE, PP_LOCALEDIR);
- bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
- /* seed the randome number generator */
- info.name = _("Stress");
- info.summary = _("A PRPL to stress libpurple");
- info.description = info.summary;
- add_option(int, _("Buddies to stress with"), "nbuddies", 50);
- add_option(int, _("Event interval, in milliseconds"), "interval", 500);
- add_option(int, _("Max events per buddy"), "maxevents", 100);
- add_option(bool, _("Trigger signoff/signoff"), "trigger_signon", TRUE);
- add_option(bool, _("Trigger idle/unidle"), "trigger_idle", TRUE);
- add_option(bool, _("Trigger away/back"), "trigger_away", TRUE);
- add_option(bool, _("Trigger typing/stopped typing"), "trigger_typing", TRUE);
- add_option(bool, _("Send messages"), "send_messages", TRUE);
- add_option(int, _("Minimum message length"), "message_min", 16);
- add_option(int, _("Maxium message length"), "message_max", 128);
- prpl_info.protocol_options = g_list_reverse(prpl_info.protocol_options);
-PURPLE_INIT_PLUGIN(stress, init_plugin, info)
--- a/talkfilters/README.md Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-dependencies: pidgin, talkfilters
-authors: Mark Lindner, Peter Lawler
-notes: Requires GNU Talkfilters
-The GNU Talk Filters are filter programs that convert ordinary English text into text that mimics a stereotyped or otherwise humorous dialect. These filters have been in the public domain for many years, and have been made available as a single integrated package. The filters include austro, b1ff, brooklyn, chef, cockney, drawl, dubya, fudd, funetak, jethro, jive, kraut, pansy, pirate, postmodern, redneck, valspeak, and warez.
--- a/talkfilters/meson.build Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-TALKFILTERS = dependency('talkfilters', required : false)
-if TYPES.contains('default') and PIDGIN.found() and TALKFILTERS.found()
- talkfilters = shared_module('talkfilters',
- dependencies : [TALKFILTERS, PIDGIN, GTK],
- install_dir : PIDGIN_LIBDIR)
- PP_PIDGIN_BUILD += 'talkfilters'
--- a/talkfilters/talkfilters.c Thu Mar 05 06:36:45 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,416 +0,0 @@
- * A neat little Purple plugin to integrate with GNU Talk Filters.
- * http://www.hyperrealm.com/talkfilters/talkfilters.html
- * Mark Lindner <markl@gnu.org> 1/6/04
- * Updates for the purple plugin pack (C) 2005 by
- * Peter Lawler <bleeter from users.sf.net>
--- slash commands (allowing it to be a one liner)
--- allow saving different filters for different buddies (or accounts)
-/* If you can't figure out what this line is for, DON'T TOUCH IT. */
-#include "../common/pp_internal.h"
-#include <talkfilters.h>
-#define PREF_PREFIX "/plugins/gtk/bleeter/talkfilters"
-#define PREF_ENABLED PREF_PREFIX "/enabled"
-#define PREF_FILTER PREF_PREFIX "/filter"
-#define PROP_FILTER "talkfilter::filter"
-static const gtf_filter_t *current_filter = NULL;
-static const gtf_filter_t *filter_list = NULL;
-static int filter_count = 0;
-translate_message(char **message, const gtf_filter_t *filter) {
- if (message == NULL || *message == NULL) {
- purple_debug_info("talkfilters","Null message\n");
- size_t len = strlen(*message);
- /* XXX: Is it always true, or are we just hoping it is? */
- tmp = (gchar *)g_malloc(len);
- filter->filter(*message, tmp, len);
- purple_debug_info("talkfilters","No filter set\n");
-static void translate_message_im(PurpleAccount *account, char *who,
- char **message, gpointer dontcare) {
- PurpleConversation *conv;
- PidginConversation *gtkconv;
- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, account);
- gtkconv = PIDGIN_CONVERSATION(conv);
- translate_message(message, g_object_get_data(G_OBJECT(gtkconv->imhtml), PROP_FILTER));
-static void translate_message_chat(PurpleAccount *account, char **message,
- int id, gpointer dontcare) {
- PurpleConversation *conv;
- PidginConversation *gtkconv;
- conv = purple_find_chat(account->gc, id);
- gtkconv = PIDGIN_CONVERSATION(conv);
- translate_message(message, g_object_get_data(G_OBJECT(gtkconv->imhtml), PROP_FILTER));
-update_selected_filter() {
- const gtf_filter_t *filter;
- const char *val = purple_prefs_get_string(PREF_FILTER);
- for(filter = filter_list; ct; filter++, ct--) {
- /* XXX: Is this overkill? Is strcmp enough? */
- if (g_utf8_collate(val, filter->name) == 0) {
- current_filter = filter;
- purple_debug_info("talkfilters", "found default filter \"%s\"\n", filter->name);
-filter_changed_cb(const char *name, PurplePrefType type, gconstpointer val, gpointer dontcare) {
- update_selected_filter();
-static gboolean writing_im_msg(PurpleAccount *account, const char *who, char **message,
- PurpleConversation *conv, PurpleMessageFlags flags, gpointer dontcare) {
- if (flags & PURPLE_MESSAGE_SEND)
- PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
- translate_message(message, g_object_get_data(G_OBJECT(gtkconv->imhtml), PROP_FILTER));
-menu_filter_changed_cb(GtkWidget *w, PidginWindow *win)
- if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)))
- PidginConversation *gtkconv = pidgin_conv_window_get_active_gtkconv(win);
- g_object_set_data(G_OBJECT(gtkconv->imhtml), PROP_FILTER,
- g_object_get_data(G_OBJECT(w), PROP_FILTER));
-regenerate_talkfilter_menu(PidginConversation *gtkconv)
- const gtf_filter_t *filter;
- const gtf_filter_t *curfilter;
- GtkWidget *mitem, *item;
- win = pidgin_conv_get_window(gtkconv);
- mitem = g_object_get_data(G_OBJECT(win->window), PROP_FILTER);
- mitem = gtk_menu_item_new_with_mnemonic(_("_Talkfilters")); /* XXX: or is it "Talk Filters"? */
- gtk_menu_shell_insert(GTK_MENU_SHELL(win->menu.menubar), mitem, 3);
- g_object_set_data(G_OBJECT(win->window), PROP_FILTER, mitem);
- gtk_widget_show(mitem);
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem), menu);
- curfilter = g_object_get_data(G_OBJECT(gtkconv->imhtml), PROP_FILTER);
- item = gtk_radio_menu_item_new_with_label(list, _("(None)"));
- list = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item));
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
- g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(menu_filter_changed_cb), win);
- for (count = filter_count, filter = filter_list; count; filter++, count--)
- item = gtk_radio_menu_item_new_with_label(list, filter->desc);
- g_object_set_data(G_OBJECT(item), PROP_FILTER, (gpointer)filter);
- list = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item));
- g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(menu_filter_changed_cb), win);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
- gtk_widget_show_all(menu);
-update_talkfilter_selection(PidginConversation *gtkconv)
- const gtf_filter_t *filter;
- win = pidgin_conv_get_window(gtkconv);
- menu = g_object_get_data(G_OBJECT(win->window), PROP_FILTER);
- menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu));
- filter = g_object_get_data(G_OBJECT(gtkconv->imhtml), PROP_FILTER);
- for (item = gtk_container_get_children(GTK_CONTAINER(menu));
- item; item = item->next)
- if (filter == g_object_get_data(G_OBJECT(item->data), PROP_FILTER))
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item->data), TRUE);
-conversation_switched_cb(PurpleConversation *conv)
- PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
- regenerate_talkfilter_menu(gtkconv);
- update_talkfilter_selection(gtkconv);
-conversation_created_cb(PurpleConversation *conv)
- PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
- /* hopefully fix a crash related to persistent convs */
- g_object_set_data(G_OBJECT(gtkconv->imhtml), PROP_FILTER, (gpointer)current_filter);
- update_talkfilter_selection(gtkconv);
-static void attach_talkfilter_menu(gpointer data, gpointer dontcare)
- PidginWindow *win = data;
- PidginConversation *gtkconv;
- gtkconv = pidgin_conv_window_get_active_gtkconv(win);
- regenerate_talkfilter_menu(gtkconv);
- update_talkfilter_selection(gtkconv);
-static gboolean plugin_load(PurplePlugin *plugin)
- void *conv_handle = purple_conversations_get_handle();
- filter_list = gtf_filter_list();
- filter_count = gtf_filter_count();
- update_selected_filter();
- purple_signal_connect(conv_handle, "sending-im-msg",
- plugin, PURPLE_CALLBACK(translate_message_im), NULL);
- purple_signal_connect(conv_handle, "sending-chat-msg",
- plugin, PURPLE_CALLBACK(translate_message_chat), NULL);
- /* XXX: This is necessary because the changed message isn't displayed locally.
- * This doesn't always show the exact filtered message that is sent, but
- * I guess it's better than no indication that the message was filtered.
- purple_signal_connect(conv_handle, "writing-im-msg", plugin,
- PURPLE_CALLBACK(writing_im_msg), NULL);
- purple_prefs_connect_callback(plugin, PREF_FILTER,
- filter_changed_cb, NULL);
- /* Add a `Talkfilters' menu in the conversation window */
- purple_signal_connect(conv_handle, "conversation-created", plugin,
- PURPLE_CALLBACK(conversation_created_cb), NULL);
- purple_signal_connect(pidgin_conversations_get_handle(), "conversation-switched",
- plugin, PURPLE_CALLBACK(conversation_switched_cb), NULL);
- g_list_foreach(pidgin_conv_windows_get_list(), attach_talkfilter_menu, NULL);
-static void remove_talkfilter_menu(gpointer data, gpointer dontcare)
- PidginWindow *win = data;
- menu = g_object_get_data(G_OBJECT(win->window), PROP_FILTER);
- gtk_widget_destroy(menu);
- g_object_set_data(G_OBJECT(win->window), PROP_FILTER, NULL);
- /* XXX: Do we need to set PROP_FILTER data to NULL for each gtkconv->imhtml as well?
- * It doesn't seem to be necessary right now. The GTF library probably gets loaded
- * at the very beginning when Purple starts, and not when this plugin is loaded. */
-static gboolean plugin_unload(PurplePlugin *plugin)
- purple_prefs_disconnect_by_handle(plugin);
- g_list_foreach(pidgin_conv_windows_get_list(), remove_talkfilter_menu, NULL);
-static PurplePluginPrefFrame *
-get_plugin_pref_frame(PurplePlugin *plugin)
- PurplePluginPrefFrame *frame;
- PurplePluginPref *pref;
- const gtf_filter_t *filter;
- frame = purple_plugin_pref_frame_new();
- pref = purple_plugin_pref_new_with_label(_("Talk Filters"));
- purple_plugin_pref_frame_add(frame, pref);
- pref = purple_plugin_pref_new_with_name_and_label(PREF_FILTER, _("Active filter:"));
- purple_plugin_pref_set_type(pref, PURPLE_PLUGIN_PREF_CHOICE);
- purple_plugin_pref_add_choice(pref, _("(None)"), "");
- for(filter = filter_list; ct; filter++, ct--)
- purple_plugin_pref_add_choice(pref, filter->desc, (gpointer)filter->name);
- purple_plugin_pref_frame_add(frame, pref);
-static PurplePluginUiInfo prefs_info = {
-static PurplePluginInfo talkfilters_info = {
- PURPLE_PLUGIN_STANDARD, /* type */
- PIDGIN_PLUGIN_TYPE, /* ui requirement */
- NULL, /* dependencies */
- PURPLE_PRIORITY_DEFAULT, /* priority */
- "gtk-plugin_pack-talkfilters", /* id */
- NULL, /* description */
- "Mark Lindner <markl@gnu.org>, "
- "Peter Lawler <bleeter@users.sf.net>",
-static void init_plugin(PurplePlugin *plugin) {
- purple_prefs_add_none("/plugins/gtk/bleeter");
- purple_prefs_add_none("/plugins/gtk/bleeter/talkfilters");
- purple_prefs_add_bool("/plugins/gtk/bleeter/talkfilters/enabled", FALSE);
- purple_prefs_add_string("/plugins/gtk/bleeter/talkfilters/filter", "");
- talkfilters_info.name = _("GNU Talk Filters");
- talkfilters_info.summary =
- _("Translates text in outgoing messages into humorous dialects.");
- talkfilters_info.description =
- _("The GNU Talk Filters are filter programs that convert ordinary "
- "English text into text that mimics a stereotyped or otherwise "
- "humorous dialect. These filters have been in the public domain for "
- "many years, and have been made available as a single integrated "
- "package. The filters include austro, b1ff, brooklyn, chef, cockney, "
- "drawl, dubya, fudd, funetak, jethro, jive, kraut, pansy, pirate, "
- "postmodern, redneck, valspeak, and warez.");
-PURPLE_INIT_PLUGIN(talkfilters, init_plugin, talkfilters_info)