Logo Search packages:      
Sourcecode: autoprofile version File versions

comp_rss.c

/*--------------------------------------------------------------------------*
 * AUTOPROFILE                                                              *
 *                                                                          *
 * A Gaim 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 "comp_rss.h"
#include "gtkprefs.h"

GList *entries;

static guint rss_refresh_timeout = 0;

static GtkWidget *entry_username = NULL;
static GtkWidget *entry_url = NULL;

/* Core functions */
static char *get_rss_data (const char *field, int index, struct tm **time) 
{
  GList *tmp;
  const struct rss_entry *e;

  char *ret, *t;
  int max;

  tmp = entries;

  if (index < 0)
    return NULL;

  if (tmp == NULL)
    return NULL;

  if (index != 0) {
    while (index-- != 1) {
      tmp = tmp->next;
      if (tmp == NULL)
        return NULL;
    }
  }
 
  e = (struct rss_entry *) tmp->data;

  if (!strcmp (field, "link")) {
    if (e->url)
      return strdup (e->url);
    else
      return NULL;
  } else if (!strcmp (field, "title")) {
    if (e->title)
      return strdup (e->title);
    else
      return NULL;
  } else if (!strcmp (field, "entry")) {
    if (e->entry) {
      max = gaim_prefs_get_int (
        "/plugins/gtk/autoprofile/components/rss/entry_limit");
      ret = strdup (e->entry);
      if (max > g_utf8_strlen (ret, -1)) {
        gchar *tmp = g_utf8_offset_to_pointer (ret, max);    
        *tmp = '\0';
      } 

      return ret;
    } else {
      return NULL;
    }
  } else if (!strcmp (field, "time")) {
    *time = e->t;
    return NULL;
  }
   
  return NULL;
}


static char *rss_generate ()
{
  char *buf, *output, *tmp, *time_tmp;
  int state;
  int count;
  const char *format;
  char fmt_char [3];
  struct tm *time;
  
  fmt_char[0] = '%';
  fmt_char[2] = '\0';
  
  format = gaim_prefs_get_string (
    "/plugins/gtk/autoprofile/components/rss/format");

  output = (char *)malloc (sizeof(char)*AP_SIZE_MAXIMUM);
  *output = '\0';
  buf = (char *)malloc (sizeof(char)*AP_SIZE_MAXIMUM);
  *buf = '\0';
  time_tmp = (char *)malloc (sizeof(char)*AP_SIZE_MAXIMUM);
  
  state = 0;
  count = 0;

  while (*format) {
    if (state == 1) {
      if (isdigit (*format)) {
        count = (count * 10) + (int) *format - 48;
        format++;
      } else {
        switch (*format) {
          case 'H':
          case 'I':
          case 'p':
          case 'M':
          case 'S':
          case 'a':
          case 'A':
          case 'b':
          case 'B':
          case 'm':
          case 'd':
          case 'j':
          case 'W':
          case 'w':
          case 'y':
          case 'Y':
          case 'z':
            time = NULL;
            tmp = get_rss_data ("time", count, &time);
            if (time) {
              fmt_char[1] = *format;
              strftime (time_tmp, AP_SIZE_MAXIMUM, fmt_char, time);
              g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%s", output, time_tmp);
            } else {
              strcpy (buf, output);
            }
            break;
          case 'l':
            tmp = get_rss_data ("link", count, NULL);
            if (tmp) {
              g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%s", output, tmp);
              free (tmp);
            } else {
              strcpy (buf, output);
            }
            break;
          case 't':
            tmp = get_rss_data ("title", count, NULL);
            if (tmp) {
              g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%s", output, tmp);
              free (tmp);
            } else {
              strcpy (buf, output);
            }
            break;
          case 'e':
            tmp = get_rss_data ("entry", count, NULL);
            if (tmp) {
              g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%s", output, tmp);
              free (tmp);
            } else {
              strcpy (buf, output);
            }

            break;
          case '%':
            g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%c", output, *format);
            break;
          default:
            g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%c", output, *format);
            break;
        }

        strcpy (output, buf);
        format++;
        state = 0;
      }
    } else {
      if (*format == '%') {
        state = 1;
        count = 0;
      } else {
        g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%c", output, *format);
        strcpy (output, buf);
      }
      format++;
    }

  }

  free (buf);

  return output;
}

static gboolean rss_update (gpointer user_data)
{
  parse_rss ();
  return TRUE;
}

static void rss_load ()
{
  entries = NULL;
  rss_update (NULL);
  rss_refresh_timeout = g_timeout_add (
    gaim_prefs_get_int (
      "/plugins/gtk/autoprofile/components/rss/update_rate") * 60 * 1000, 
    rss_update, NULL);
}

static void rss_unload ()
{
  g_source_remove (rss_refresh_timeout);
}

static void rss_init ()
{
  gaim_prefs_add_none ("/plugins/gtk/autoprofile/components/rss");
  gaim_prefs_add_int ("/plugins/gtk/autoprofile/components/rss/type", 
    RSS_XANGA);
  gaim_prefs_add_string ("/plugins/gtk/autoprofile/components/rss/location", 
    "");
  gaim_prefs_add_string ("/plugins/gtk/autoprofile/components/rss/username",
    "");
  gaim_prefs_add_string ("/plugins/gtk/autoprofile/components/rss/format",
    "");
  gaim_prefs_add_int ("/plugins/gtk/autoprofile/components/rss/update_rate", 
    5);
  gaim_prefs_add_int ("/plugins/gtk/autoprofile/components/rss/entry_limit",
    300);
}


/* GUI functions */
static gboolean update_refresh_rate (GtkWidget *widget, GdkEventFocus *evt, 
                              gpointer data)
{
  gaim_prefs_set_int ("/plugins/gtk/autoprofile/components/rss/update_rate",
    gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget)));
   
  // Kill the current timer and run a new one
  g_source_remove(rss_refresh_timeout);
  rss_refresh_timeout = g_timeout_add (
    gaim_prefs_get_int(
      "/plugins/gtk/autoprofile/components/rss/update_rate") * 60 * 1000,
    rss_update, NULL);

  return FALSE;
}

static void rss_data_update (GtkWidget *widget, gpointer data)
{
  rss_update (NULL);
}

static void dropdown_set (GObject *w, int *value)
{
  int real_val = (int) value;

  gaim_prefs_set_int (
    "/plugins/gtk/autoprofile/components/rss/type", real_val);

  if (real_val == RSS_XANGA || real_val == RSS_LIVEJOURNAL) {
    gtk_widget_set_sensitive (entry_username, TRUE);
    gtk_widget_set_sensitive (entry_url, FALSE);
  } else {
    gtk_widget_set_sensitive (entry_username, FALSE);
    gtk_widget_set_sensitive (entry_url, TRUE);
  }
}

static gboolean update_string (GtkWidget *widget, GdkEventFocus *evt,
                               gpointer data)
{
  if (!strcmp ((char *) data, "username")) {
    gaim_prefs_set_string (
      "/plugins/gtk/autoprofile/components/rss/username",
      gtk_entry_get_text (GTK_ENTRY (widget)));
  } else if (!strcmp ((char *) data, "location")) {
    gaim_prefs_set_string (
      "/plugins/gtk/autoprofile/components/rss/location",
      gtk_entry_get_text (GTK_ENTRY (widget)));
  } else if (!strcmp ((char *) data, "format")) {
    gaim_prefs_set_string (
      "/plugins/gtk/autoprofile/components/rss/format",
      gtk_entry_get_text (GTK_ENTRY (widget)));
  }

  return FALSE;
}

static GtkWidget *rss_menu ()
{
  GtkWidget *ret;

  GtkWidget *label, *hbox, *button, *spinner, *entry, *sw;
  GtkWidget *dropdown, *opt, *menu;

  int value;

  ret = gtk_vbox_new (FALSE, 5);

  /* Format string */
  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);

  entry = gtk_entry_new ();
  gtk_box_pack_start (GTK_BOX(ret), entry, FALSE, FALSE, 0);
  gtk_entry_set_max_length (GTK_ENTRY(entry), AP_SIZE_MAXIMUM - 1);
  gtk_entry_set_text (GTK_ENTRY(entry), gaim_prefs_get_string (
    "/plugins/gtk/autoprofile/components/rss/format"));
  g_signal_connect (G_OBJECT (entry), "focus-out-event",
                    G_CALLBACK (update_string), "format");

  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"
    "%d\tDay of month of entry\n"
    "%w\tDay of week of entry (abbreviated)\n"
    "%W\tDay of week of entry (full name)\n"
    "%m\tMonth of year of entry (numerical)\n"
    "%M\tMonth of year of entry (named)\n"
    "%y\tYear of entry (last two digits)\n"
    "%Y\tYear of entry (four digits)\n"
    "%h\tHour of entry (12-hour clock)\n"
    "%H\tHour of entry (24-hour clock)\n"
    "%m\tMinute of entry\n"
    "%p\tAM or PM for entry\n"
    "\nOther options\n\n"
    "%%\t%"));

  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 (ret), 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);

  dropdown = gtk_option_menu_new ();
  menu = gtk_menu_new ();

  opt = gtk_menu_item_new_with_label("Xanga");
  g_signal_connect (G_OBJECT(opt), "activate",
    G_CALLBACK (dropdown_set), (int *)RSS_XANGA);
  gtk_widget_show (opt);
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), opt);

  opt = gtk_menu_item_new_with_label("LiveJournal");
  g_signal_connect (G_OBJECT(opt), "activate",
    G_CALLBACK (dropdown_set), (int *)RSS_LIVEJOURNAL);
  gtk_widget_show (opt);
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), opt);

  opt = gtk_menu_item_new_with_label("RSS 2.0");
  g_signal_connect (G_OBJECT(opt), "activate",
    G_CALLBACK (dropdown_set), (int *)RSS_2);
  gtk_widget_show (opt);
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), opt);

  value = gaim_prefs_get_int (
    "/plugins/gtk/autoprofile/components/rss/type");

  gtk_menu_set_active (GTK_MENU(menu), value);
  
  gtk_option_menu_set_menu (GTK_OPTION_MENU(dropdown), menu);
  gtk_widget_show (dropdown);

  gtk_box_pack_start (GTK_BOX(ret), dropdown, FALSE, FALSE, 0);

  entry_username = gtk_hbox_new (FALSE, 5);
  gtk_box_pack_start (GTK_BOX(ret), entry_username, FALSE, FALSE, 0);
  label = gtk_label_new (_("Username:"));
  gtk_box_pack_start (GTK_BOX(entry_username), label, FALSE, FALSE, 0);
  entry = gtk_entry_new ();
  gtk_box_pack_start (GTK_BOX(entry_username), entry, TRUE, TRUE, 0);
  gtk_entry_set_text (GTK_ENTRY(entry), gaim_prefs_get_string (
    "/plugins/gtk/autoprofile/components/rss/username"));
  gtk_entry_set_max_length (GTK_ENTRY(entry), MAX_USERNAME_LENGTH);
  g_signal_connect (G_OBJECT (entry), "focus-out-event",
                    G_CALLBACK (update_string), "username");

  entry_url = gtk_hbox_new (FALSE, 5);
  gtk_box_pack_start (GTK_BOX(ret), entry_url, FALSE, FALSE, 0);
  label = gtk_label_new (_("URL of feed:"));
  gtk_box_pack_start (GTK_BOX(entry_url), label, FALSE, FALSE, 0);
  entry = gtk_entry_new ();
  gtk_box_pack_start (GTK_BOX(entry_url), entry, TRUE, TRUE, 0);
  gtk_entry_set_text (GTK_ENTRY(entry), gaim_prefs_get_string (
    "/plugins/gtk/autoprofile/components/rss/location"));
  g_signal_connect (G_OBJECT (entry), "focus-out-event",
                    G_CALLBACK (update_string), "location");

  if (value == RSS_XANGA || value == RSS_LIVEJOURNAL) {
    gtk_widget_set_sensitive (entry_username, TRUE);
    gtk_widget_set_sensitive (entry_url, FALSE);
  } else {
    gtk_widget_set_sensitive (entry_username, FALSE);
    gtk_widget_set_sensitive (entry_url, TRUE);
  }

  /* Other options */
  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 */
  gaim_gtk_prefs_labeled_spin_button (
    ret, "Max characters to show in entry (%e)",
    "/plugins/gtk/autoprofile/components/rss/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),
    gaim_prefs_get_int (
      "/plugins/gtk/autoprofile/components/rss/update_rate"));
  g_signal_connect (G_OBJECT (spinner), "value-changed",
                    G_CALLBACK (update_refresh_rate), NULL);

  button = gtk_button_new_with_label ("Update Now!");
  g_signal_connect (G_OBJECT (button), "clicked",
                    G_CALLBACK (rss_data_update), NULL);
  gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);

  return ret;
}

/* Le end */
struct component rss =
{
  N_("RSS / Blogs"),
  N_("Information taken from an RSS feed\n(Xanga and LiveJournal capable)"),
  'r',
  &rss_generate,
  &rss_init,
  &rss_load,
  &rss_unload,
  &rss_menu
};


Generated by  Doxygen 1.6.0   Back to index