Logo Search packages:      
Sourcecode: pan version File versions  Download package

gui-headers.c

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 * Pan - A Newsreader for Gtk+
 * Copyright (C) 2002  Charles Kerr <charles@rebelbase.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; version 2 of the License.
 *
 * 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 <config.h>

#include <string.h>

#include <glib.h>
#include <gtk/gtk.h>

#include <pan/base/debug.h>
/* #include <pan/base/run.h> */
#include <pan/base/pan-i18n.h>
#include <pan/base/pan-glib-extensions.h>
#include <pan/base/util-mime.h>

#include <pan/globals.h>
#include <pan/gui-headers.h>
#include <pan/prefs.h>
#include <pan/util.h>

gulong header_flags = ~0;
static const int max_header_width = 60;
extern GtkTooltips * ttips;


/*****
******
*****/

static void
showmore_cb (GtkButton *button, gpointer user_data)
{
      GtkWidget * w;
      const char* showme = (const char*) gtk_object_get_data (GTK_OBJECT(button), "text");

      w = gtk_message_dialog_new (GTK_WINDOW(Pan.window), 0, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, "%s", showme);
      g_signal_connect_swapped (GTK_OBJECT(w), "response", G_CALLBACK (gtk_widget_destroy), GTK_OBJECT(w));
      gtk_widget_show_all (w);
}

static int
find_breakpoint (const char  * str,
                 char          delimiter,
                 int           max_width)
{
      int len;
      int retval;
      debug_enter ("find_breakpoint");

      /* sanity clause */
      g_return_val_if_fail (is_nonempty_string(str), -1);
      g_return_val_if_fail (max_width>0, -1);

            len = strlen (str);
      if (!delimiter || len<=max_width)
      {
            retval = -1;
      }
      else
      {
            const char * pch = str;
            const char * last_match = NULL;
            for (; *pch; ++pch)
            {
                  if (*pch == delimiter)
                        last_match = pch;
                  if (pch-str > max_width)
                        break;
            }

            retval = last_match ? last_match-str : max_width;
      }

      debug_exit ("find_breakpoint");
      return retval;
}

static void
add_header_nolock (GtkWidget      * table,
                 int               row,
                 const char      * str1,
                 const char      * str2,
                 char             delimiter,
                   int              max_width)
{
      GtkTable * t;
      GtkWidget * w1;
      GtkWidget * w2 = NULL;
      char * str1_tmp;
      const char * utf8_str1;
      const char * utf8_str2;
      char * freeme1;
      char * freeme2;
      int breakpoint;
      debug_enter ("add_header_nolock");

      str1_tmp = g_strdup_printf ("%s: ", str1);      
      utf8_str1 = pan_utf8ize (str1_tmp, -1, &freeme1);
      utf8_str2 = pan_utf8ize (str2, -1, &freeme2);
      
            t = GTK_TABLE(table);
            w1 = gtk_label_new (utf8_str1);

      breakpoint = find_breakpoint (utf8_str2, delimiter, max_width);
      if (breakpoint == -1)
      {
            /* string is short; show it all */
            w2 = gtk_label_new (utf8_str2);
            gtk_misc_set_alignment (GTK_MISC(w2), 0.0, 0.5);
      }
      else
      {
            /* string is long, so truncate and make a "<More>" button */
            GtkWidget * hbox = gtk_hbox_new (FALSE, 0);
            GtkWidget * l = NULL;
            GtkWidget * l2 = gtk_label_new (_("<More>"));
            GString * lines;
            char * pch = NULL;

            /* create the truncated label */
            pch = pan_strdup_alloca (utf8_str2);
            pch[breakpoint] = '\0';
            l = gtk_label_new (pch);

            /* add them both to the button */
            gtk_box_pack_start (GTK_BOX(hbox), l, FALSE, FALSE, 0);
            gtk_box_pack_end (GTK_BOX(hbox), l2, FALSE, FALSE, 0);

            /* break the line into easier-to-read
             * pieces for the popup dialog */
            lines = g_string_new (utf8_str2);
            pch = lines->str;
            if (delimiter != ' ') {
                  for (; *pch; pch = g_utf8_next_char (pch))
                        if (*pch == delimiter)
                              *pch = '\n';
            }
            else for (;;) {
                  const int index = find_breakpoint (pch, delimiter, max_width);
                  if (index == -1)
                        break;
                  else {
                        const int lines_offset = pch - lines->str;
                        const int lines_index = index + lines_offset;
                        g_string_insert_c (lines, lines_index, '\n');
                        pch += (index + 2); /* 1 for the delimiter, 1 for the linefeed */
                  }
            }

            /* create a button */
            w2 = gtk_button_new ( );
            gtk_button_set_relief (GTK_BUTTON(w2), GTK_RELIEF_NONE);
            gtk_container_add (GTK_CONTAINER(w2), hbox);
            gtk_widget_show (l);
            gtk_widget_show (l2);
            gtk_widget_show (hbox);
            g_object_set_data_full (G_OBJECT(w2), "text",
                                    g_string_free(lines,FALSE), g_free);
            g_signal_connect (GTK_OBJECT(w2), "clicked",
                              G_CALLBACK(showmore_cb), NULL);
            gtk_tooltips_set_tip (GTK_TOOLTIPS(ttips), w2, utf8_str2, NULL);
      }

      gtk_misc_set_alignment (GTK_MISC(w1), 1.0, 0.5);

      gtk_table_resize (t, row+1,2);

      gtk_table_attach (t, w1, 0,1, row, row+1, GTK_FILL, 0,2,1 );
      gtk_table_attach (t, w2, 1,2, row, row+1, GTK_EXPAND|GTK_FILL, 0,2,1 );
      gtk_widget_show (w1);
      gtk_widget_show (w2);

      g_free (freeme1);
      g_free (freeme2);
      g_free (str1_tmp);

      debug_exit ("add_header_nolock");
}

static void
add_header (GtkWidget      * table,
            GMimeMessage   * message,
            const char     * fallback_charset,
            const char     * key,
            const char     * key_i18n,
            char             delimiter,
            int              row)
{
      const char * pch = g_mime_message_get_header (message, key);
      if (is_nonempty_string (pch))
      {
            char * tmp = pan_header_to_utf8 (pch, -1, fallback_charset);
            add_header_nolock (table, row, key_i18n, tmp ? tmp : pch, delimiter, max_header_width);
            g_free (tmp);
      }
}

void
gui_headers_set_nolock (GtkWidget       * table,
                    GMimeMessage    * message,
                    gulong            header_fields)
{
      int row = 0;
      const char * charset;
      debug_enter ("gui_headers_set_nolock");

      /* remove previous children */
      g_return_if_fail (GTK_IS_TABLE(table));
      gtk_container_foreach (GTK_CONTAINER (table),
                             (GtkCallback)(gtk_widget_destroy), NULL);

      if (message == NULL)
            return;

      charset = group_get_default_charset (
                  pan_g_mime_message_get_group (message));

      if (header_fields & UI_HEADER_SUBJECT)
            add_header (table, message, charset, HEADER_SUBJECT, _("Subject"), ' ', row++);

      if (header_fields & UI_HEADER_AUTHOR)
            add_header (table, message, charset, HEADER_FROM, _("From"), ' ', row++);

      if (header_fields & UI_HEADER_REPLY_TO)
            add_header (table, message, charset, HEADER_REPLY_TO, _("Reply-To"), ' ', row++);

      if (header_fields & UI_HEADER_NEWSGROUPS)
            add_header (table, message, charset, HEADER_NEWSGROUPS, _("Newsgroups"), ',', row++);

      if (header_fields & UI_HEADER_FOLLOWUP_TO)
            add_header (table, message, charset, HEADER_FOLLOWUP_TO, _("Followup-To"), ',', row++);

      if (header_fields & UI_HEADER_MESSAGE_ID)
            add_header (table, message, charset, HEADER_MESSAGE_ID, _("Message-ID"), ' ', row++);

      if (header_fields & UI_HEADER_REFERENCES)
            add_header (table, message, charset, HEADER_REFERENCES, _("References"), ' ', row++);

      if (header_fields & UI_HEADER_DATE)
            add_header (table, message, charset, HEADER_DATE, _("Date"), '\0', row++);

      if (header_fields & UI_HEADER_NEWSREADER) {
            const char * pch = g_mime_message_get_header (message, HEADER_X_NEWSREADER);
            if (is_nonempty_string (pch))
                  add_header_nolock (table, row++, _("X-Newsreader"), pch, ' ', max_header_width);

            pch = g_mime_message_get_header (message, HEADER_X_MAILER);
            if (is_nonempty_string (pch))
                  add_header_nolock (table, row++, _("X-Mailer"), pch, ' ', max_header_width);

            pch = g_mime_message_get_header (message, HEADER_USER_AGENT);
            if (is_nonempty_string (pch))
                  add_header_nolock (table, row++, _("User-Agent"), pch, ' ', max_header_width);
      }

      debug_exit ("gui_headers_set_nolock");
}

void
gui_headers_set_default_nolock (GtkWidget      * table,
                          GMimeMessage   * message)
{
      gui_headers_set_nolock (table, message, header_flags);
}

Generated by  Doxygen 1.6.0   Back to index