/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * e-destination.c * * Copyright (C) 2001 Ximian, Inc. * * Developed by Jon Trowbridge */ /* * 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 #include #include #include #include #include "e-destination.h" struct _EDestinationPrivate { ECard *card; gint card_email_num; gchar *name; gchar *string; gchar *string_email; gchar *string_email_verbose; gboolean html_mail_override; gboolean wants_html_mail; }; static void e_destination_clear_card (EDestination *); static void e_destination_clear_strings (EDestination *); static GtkObjectClass *parent_class; static void e_destination_destroy (GtkObject *obj) { EDestination *dest = E_DESTINATION (obj); e_destination_clear_card (dest); e_destination_clear_strings (dest); g_free (dest->priv); if (parent_class->destroy) parent_class->destroy (obj); } static void e_destination_class_init (EDestinationClass *klass) { GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass); parent_class = GTK_OBJECT_CLASS (gtk_type_class (GTK_TYPE_OBJECT)); object_class->destroy = e_destination_destroy; } static void e_destination_init (EDestination *dest) { dest->priv = g_new0 (struct _EDestinationPrivate, 1); } GtkType e_destination_get_type (void) { static GtkType dest_type = 0; if (!dest_type) { GtkTypeInfo dest_info = { "EDestination", sizeof (EDestination), sizeof (EDestinationClass), (GtkClassInitFunc) e_destination_class_init, (GtkObjectInitFunc) e_destination_init, NULL, NULL, /* reserved */ (GtkClassInitFunc) NULL }; dest_type = gtk_type_unique (gtk_object_get_type (), &dest_info); } return dest_type; } EDestination * e_destination_new (void) { return E_DESTINATION (gtk_type_new (E_TYPE_DESTINATION)); } EDestination * e_destination_copy (EDestination *dest) { EDestination *new_dest; g_return_val_if_fail (dest && E_IS_DESTINATION (dest), NULL); new_dest = e_destination_new (); new_dest->priv->card = dest->priv->card; if (new_dest->priv->card) gtk_object_ref (GTK_OBJECT (new_dest->priv->card)); new_dest->priv->card_email_num = dest->priv->card_email_num; new_dest->priv->string = g_strdup (dest->priv->string); new_dest->priv->string_email = g_strdup (dest->priv->string_email); new_dest->priv->string_email_verbose = g_strdup (dest->priv->string_email_verbose); return new_dest; } gboolean e_destination_is_empty (EDestination *dest) { g_return_val_if_fail (dest && E_IS_DESTINATION (dest), TRUE); return !(dest->priv->card || (dest->priv->string && *dest->priv->string)); } static void e_destination_clear_card (EDestination *dest) { if (dest->priv->card) gtk_object_unref (GTK_OBJECT (dest->priv->card)); dest->priv->card = NULL; dest->priv->card_email_num = -1; } static void e_destination_clear_strings (EDestination *dest) { g_free (dest->priv->name); g_free (dest->priv->string); g_free (dest->priv->string_email); g_free (dest->priv->string_email_verbose); dest->priv->name = NULL; dest->priv->string = NULL; dest->priv->string_email = NULL; dest->priv->string_email_verbose = NULL; } void e_destination_set_card (EDestination *dest, ECard *card, gint email_num) { g_return_if_fail (dest && E_IS_DESTINATION (dest)); g_return_if_fail (card && E_IS_CARD (card)); if (dest->priv->card != card) { if (dest->priv->card) gtk_object_unref (GTK_OBJECT (dest->priv->card)); dest->priv->card = card; gtk_object_ref (GTK_OBJECT (card)); } dest->priv->card_email_num = email_num; e_destination_clear_strings (dest); } void e_destination_set_string (EDestination *dest, const gchar *string) { g_return_if_fail (dest && E_IS_DESTINATION (dest)); g_return_if_fail (string != NULL); g_free (dest->priv->string); dest->priv->string = g_strdup (string); } void e_destination_set_html_mail_pref (EDestination *dest, gboolean x) { g_return_if_fail (dest && E_IS_DESTINATION (dest)); dest->priv->html_mail_override = TRUE; dest->priv->wants_html_mail = x; } ECard * e_destination_get_card (const EDestination *dest) { g_return_val_if_fail (dest && E_IS_DESTINATION (dest), NULL); return dest->priv->card; } gint e_destination_get_email_num (const EDestination *dest) { g_return_val_if_fail (dest && E_IS_DESTINATION (dest), -1); return dest->priv->card_email_num; } const gchar * e_destination_get_string (const EDestination *dest) { struct _EDestinationPrivate *priv; g_return_val_if_fail (dest && E_IS_DESTINATION (dest), NULL); priv = (struct _EDestinationPrivate *)dest->priv; /* cast out const */ if (priv->string == NULL) { if (priv->card) { priv->string = e_card_name_to_string (priv->card->name); if (priv->string) { g_strstrip (priv->string); if (*(priv->string) == '\0') { g_free (priv->string); priv->string = NULL; } } if (priv->string == NULL) priv->string = g_strdup (e_destination_get_email (dest)); if (priv->string == NULL) priv->string = g_strdup (_("???")); } } return priv->string; } gint e_destination_get_strlen (const EDestination *dest) { const gchar *str; g_return_val_if_fail (dest && E_IS_DESTINATION (dest), 0); str = e_destination_get_string (dest); return str ? strlen (str) : 0; } const gchar * e_destination_get_name (const EDestination *dest) { struct _EDestinationPrivate *priv; g_return_val_if_fail (dest && E_IS_DESTINATION (dest), NULL); priv = (struct _EDestinationPrivate *)dest->priv; /* cast out const */ if (priv->name == NULL) { if (priv->card) { priv->name = e_card_name_to_string (priv->card->name); } } return priv->name; } const gchar * e_destination_get_email (const EDestination *dest) { struct _EDestinationPrivate *priv; g_return_val_if_fail (dest && E_IS_DESTINATION (dest), NULL); priv = (struct _EDestinationPrivate *)dest->priv; /* cast out const */ if (priv->string_email == NULL) { if (priv->card) { /* Pull the address out of the card. */ EIterator *iter = e_list_get_iterator (priv->card->email); gint n = priv->card_email_num; if (n >= 0) { while (n > 0) { e_iterator_next (iter); --n; } if (e_iterator_is_valid (iter)) { gconstpointer ptr = e_iterator_get (iter); priv->string_email = g_strdup ((gchar *) ptr); } } } else if (priv->string) { /* Use the string as an e-mail address */ return priv->string; } /* else we just return NULL */ } return priv->string_email; } const gchar * e_destination_get_email_verbose (const EDestination *dest) { struct _EDestinationPrivate *priv; g_return_val_if_fail (dest && E_IS_DESTINATION (dest), NULL); priv = (struct _EDestinationPrivate *)dest->priv; /* cast out const */ if (priv->string_email_verbose == NULL) { const gchar *email = e_destination_get_email (dest); const gchar *name = e_destination_get_name (dest); if (name) { priv->string_email_verbose = g_strdup_printf ("%s <%s>", name, email); } else { return email; } } return priv->string_email_verbose; } gboolean e_destination_get_html_mail_pref (const EDestination *dest) { g_return_val_if_fail (dest && E_IS_DESTINATION (dest), FALSE); if (dest->priv->html_mail_override || dest->priv->card == NULL) return dest->priv->wants_html_mail; return dest->priv->card->wants_html; } gchar * e_destination_get_address_textv (EDestination **destv) { gint i, j, len = 0; gchar **strv; gchar *str; g_return_val_if_fail (destv, NULL); while (destv[len]) { g_return_val_if_fail (E_IS_DESTINATION (destv[len]), NULL); ++len; } strv = g_new0 (gchar *, len+1); for (i = 0, j = 0; destv[i]; ++i) { const gchar *addr = e_destination_get_email_verbose (destv[i]); strv[j++] = addr ? (gchar *) addr : ""; } str = g_strjoinv (", ", strv); g_free (strv); return str; } /* * * Serialization code * */ #define DESTINATION_TAG "DEST" #define DESTINATION_SEPARATOR "|" static gchar * join_strings (gchar **strv) { /* FIXME: Should also quote any |'s that occur in any of the strings. */ return g_strjoinv (DESTINATION_SEPARATOR, strv); } static gchar ** unjoin_string (const gchar *str) { /* FIXME: Should properly handle quoteded |'s in the string. */ return g_strsplit (str, DESTINATION_SEPARATOR, 0); } static gchar * build_field (const gchar *key, const gchar *value) { return g_strdup_printf ("%s=%s", key, value); } /* Modifies string in place, \0-terminates after the key, returns pointer to "value", or NULL if the field is malformed. */ static gchar * extract_field (gchar *field) { gchar *s = strchr (field, '='); if (s == NULL) return NULL; *s = '\0'; return s+1; } gchar * e_destination_export (const EDestination *dest) { gchar **fields; gchar *str; gint i; g_return_val_if_fail (dest && E_IS_DESTINATION (dest), NULL); fields = g_new (gchar *, 5); fields[0] = g_strdup (DESTINATION_TAG); fields[1] = build_field ("addr", e_destination_get_email (dest)); i = 2; if (e_destination_get_name (dest)) fields[i++] = build_field ("name", e_destination_get_name (dest)); fields[i++] = build_field ("html", e_destination_get_html_mail_pref (dest) ? "Y" : "N"); fields[i] = NULL; str = join_strings (fields); g_strfreev (fields); return str; } EDestination * e_destination_import (const gchar *str) { EDestination *dest; gchar **fields; gint i; gchar *addr = NULL, *name = NULL; gboolean want_html = FALSE; g_return_val_if_fail (str, NULL); fields = unjoin_string (str); g_return_val_if_fail (fields && fields[0], NULL); g_return_val_if_fail (!strcmp (fields[0], DESTINATION_TAG), NULL); for (i = 1; fields[i]; ++i) { gchar *key = fields[i]; gchar *value = extract_field (fields[i]); if (value) { if (!strcmp ("addr", key)) { if (addr) { g_warning ("addr redefined: \"%s\" => \"%s\"", addr, value); } addr = g_strdup (value); } else if (!strcmp ("name", key)) { if (name) { g_warning ("name redefined: \"%s\" => \"%s\"", name, value); } name = g_strdup (name); } else if (!strcmp ("html", key)) { want_html = (*value == 'Y'); } } } dest = e_destination_new (); /* We construct this part of the object in a rather abusive way. */ dest->priv->string_email = addr; dest->priv->name = name; e_destination_set_html_mail_pref (dest, want_html); g_strfreev (fields); return dest; } #define VEC_SEPARATOR "\1" gchar * e_destination_exportv (EDestination **destv) { gint i, len = 0; gchar **strv; gchar *str; g_return_val_if_fail (destv, NULL); while (destv[len]) { g_return_val_if_fail (E_IS_DESTINATION (destv[len]), NULL); ++len; } strv = g_new0 (gchar *, len+1); for (i = 0; i < len; ++i) strv[i] = e_destination_export (destv[i]); str = g_strjoinv (VEC_SEPARATOR, strv); for (i = 0; i < len; ++i) g_free (strv[i]); g_free (strv); return str; } EDestination ** e_destination_importv (const gchar *str) { gchar** strv; EDestination **destv; gint i = 0, j = 0, len = 0; if (!(str && *str)) return NULL; strv = g_strsplit (str, VEC_SEPARATOR, 0); while (strv[len]) ++len; destv = g_new0 (EDestination *, len+1); while (strv[i]) { EDestination *dest = e_destination_import (strv[i]); if (dest) { destv[j++] = dest; } ++i; } g_strfreev (strv); return destv; }