/* GNU mailutils - a suite of utilities for electronic mail Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Library Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #ifdef HAVE_STRINGS_H # include #endif #include #include int (attribute_add_ref) (attribute_t attribute) { if (attribute == NULL || attribute->vtable == NULL || attribute->vtable->add_ref == NULL) return MU_ERROR_NOT_SUPPORTED; return attribute->vtable->add_ref (attribute); } int (attribute_release) (attribute_t attribute) { if (attribute == NULL || attribute->vtable == NULL || attribute->vtable->release == NULL) return MU_ERROR_NOT_SUPPORTED; return attribute->vtable->release (attribute); } int (attribute_destroy) (attribute_t attribute) { if (attribute == NULL || attribute->vtable == NULL || attribute->vtable->destroy == NULL) return MU_ERROR_NOT_SUPPORTED; return attribute->vtable->destroy (attribute); } int (attribute_get_flags) (attribute_t attribute, int *pflags) { if (attribute == NULL || attribute->vtable == NULL || attribute->vtable->get_flags == NULL) return MU_ERROR_NOT_SUPPORTED; return attribute->vtable->get_flags (attribute, pflags); } int (attribute_set_flags) (attribute_t attribute, int flags) { if (attribute == NULL || attribute->vtable == NULL || attribute->vtable->set_flags == NULL) return MU_ERROR_NOT_SUPPORTED; return attribute->vtable->set_flags (attribute, flags); } int (attribute_unset_flags) (attribute_t attribute, int flags) { if (attribute == NULL || attribute->vtable == NULL || attribute->vtable->unset_flags == NULL) return MU_ERROR_NOT_SUPPORTED; return attribute->vtable->unset_flags (attribute, flags); } int (attribute_clear_flags) (attribute_t attribute) { if (attribute == NULL || attribute->vtable == NULL || attribute->vtable->clear_flags == NULL) return MU_ERROR_NOT_SUPPORTED; return attribute->vtable->clear_flags (attribute); } /* Stub helpers for the wellknown flags. */ int attribute_set_seen (attribute_t attribute) { if (attribute == NULL) return MU_ERROR_INVALID_PARAMETER; return attribute_set_flags (attribute, MU_ATTRIBUTE_SEEN); } int attribute_set_answered (attribute_t attribute) { if (attribute == NULL) return MU_ERROR_INVALID_PARAMETER; return attribute_set_flags (attribute, MU_ATTRIBUTE_ANSWERED); } int attribute_set_flagged (attribute_t attribute) { if (attribute == NULL) return MU_ERROR_INVALID_PARAMETER; return attribute_set_flags (attribute, MU_ATTRIBUTE_FLAGGED); } int attribute_set_read (attribute_t attribute) { if (attribute == NULL) return MU_ERROR_INVALID_PARAMETER; return attribute_set_flags (attribute, MU_ATTRIBUTE_READ); } int attribute_set_deleted (attribute_t attribute) { if (attribute == NULL) return MU_ERROR_INVALID_PARAMETER; return attribute_set_flags (attribute, MU_ATTRIBUTE_DELETED); } int attribute_set_draft (attribute_t attribute) { if (attribute == NULL) return MU_ERROR_INVALID_PARAMETER; return attribute_set_flags (attribute, MU_ATTRIBUTE_DRAFT); } int attribute_set_recent (attribute_t attribute) { if (attribute == NULL) return MU_ERROR_INVALID_PARAMETER; attribute_unset_flags (attribute, MU_ATTRIBUTE_READ); return attribute_unset_flags (attribute, MU_ATTRIBUTE_SEEN); } int attribute_set_modified (attribute_t attribute) { if (attribute == NULL) return MU_ERROR_INVALID_PARAMETER; return attribute_set_flags (attribute, MU_ATTRIBUTE_MODIFIED); } int attribute_is_seen (attribute_t attribute) { int flags = 0; if (attribute == NULL) return 0; attribute_get_flags (attribute, &flags); return flags & MU_ATTRIBUTE_SEEN; } int attribute_is_answered (attribute_t attribute) { int flags = 0; if (attribute == NULL) return 0; attribute_get_flags (attribute, &flags); return flags & MU_ATTRIBUTE_ANSWERED; } int attribute_is_flagged (attribute_t attribute) { int flags = 0; if (attribute == NULL) return 0; attribute_get_flags (attribute, &flags); return flags & MU_ATTRIBUTE_FLAGGED; } int attribute_is_read (attribute_t attribute) { int flags = 0; if (attribute == NULL) return 0; attribute_get_flags (attribute, &flags); return flags & MU_ATTRIBUTE_READ; } int attribute_is_deleted (attribute_t attribute) { int flags = 0; if (attribute == NULL) return 0; attribute_get_flags (attribute, &flags); return flags & MU_ATTRIBUTE_DELETED; } int attribute_is_draft (attribute_t attribute) { int flags = 0; if (attribute == NULL) return 0; attribute_get_flags (attribute, &flags); return flags & MU_ATTRIBUTE_DRAFT; } int attribute_is_recent (attribute_t attribute) { int flags = 0; if (attribute == NULL) return 0; attribute_get_flags (attribute, &flags); /* Something is recent when it is not read and not seen. */ return (flags == 0 || ! ((flags & MU_ATTRIBUTE_SEEN) || (flags & MU_ATTRIBUTE_READ))); } int attribute_is_modified (attribute_t attribute) { int flags = 0; if (attribute == NULL) return 0; attribute_get_flags (attribute, &flags); return flags & MU_ATTRIBUTE_MODIFIED; } int attribute_unset_seen (attribute_t attribute) { if (attribute == NULL) return 0; return attribute_unset_flags (attribute, MU_ATTRIBUTE_SEEN); } int attribute_unset_answered (attribute_t attribute) { if (attribute == NULL) return 0; return attribute_unset_flags (attribute, MU_ATTRIBUTE_ANSWERED); } int attribute_unset_flagged (attribute_t attribute) { if (attribute == NULL) return 0; return attribute_unset_flags (attribute, MU_ATTRIBUTE_FLAGGED); } int attribute_unset_read (attribute_t attribute) { if (attribute == NULL) return 0; return attribute_unset_flags (attribute, MU_ATTRIBUTE_READ); } int attribute_unset_deleted (attribute_t attribute) { if (attribute == NULL) return 0; return attribute_unset_flags (attribute, MU_ATTRIBUTE_DELETED); } int attribute_unset_draft (attribute_t attribute) { if (attribute == NULL) return 0; return attribute_unset_flags (attribute, MU_ATTRIBUTE_DRAFT); } int attribute_unset_recent (attribute_t attribute) { if (attribute == NULL) return 0; return attribute_unset_flags (attribute, MU_ATTRIBUTE_SEEN); } int attribute_unset_modified (attribute_t attribute) { if (attribute == NULL) return 0; return attribute_unset_flags (attribute, MU_ATTRIBUTE_MODIFIED); } /* Miscellaneous. */ int attribute_is_equal (attribute_t attribute1, attribute_t attribute2) { int flags1 = 0; int flags2 = 0; if (attribute1) attribute_get_flags (attribute1, &flags1); if (attribute2) attribute_get_flags (attribute2, &flags2); return flags1 == flags2; } int attribute_copy (attribute_t dest, attribute_t src) { int sflags = 0; if (dest == NULL || src == NULL) return MU_ERROR_INVALID_PARAMETER; attribute_get_flags (src, &sflags); attribute_clear_flags (dest); attribute_set_flags (dest, sflags); return 0; } static int _da_add_ref (attribute_t attribute) { struct _da *da = (struct _da *)attribute; int status; monitor_lock (da->lock); status = ++da->ref; monitor_unlock (da->lock); return status; } static int _da_destroy (attribute_t attribute) { struct _da *da = (struct _da *)attribute; monitor_destroy (da->lock); free (da); return 0; } static int _da_release (attribute_t attribute) { struct _da *da = (struct _da *)attribute; int status; monitor_lock (da->lock); status = --da->ref; if (status <= 0) { monitor_unlock (da->lock); _da_destroy (attribute); return 0; } monitor_unlock (da->lock); return status; } static int _da_get_flags (attribute_t attribute, int *pflags) { struct _da *da = (struct _da *)attribute; monitor_lock (da->lock); if (pflags) *pflags = da->flags; monitor_unlock (da->lock); return 0; } static int _da_set_flags (attribute_t attribute, int flags) { struct _da *da = (struct _da *)attribute; monitor_lock (da->lock); da->flags |= (flags | MU_ATTRIBUTE_MODIFIED); monitor_unlock (da->lock); return 0; } static int _da_unset_flags (attribute_t attribute, int flags) { struct _da *da = (struct _da *)attribute; monitor_lock (da->lock); da->flags &= ~flags; /* If Modified was being unset do not reset it. */ if (!(flags & MU_ATTRIBUTE_MODIFIED)) da->flags |= MU_ATTRIBUTE_MODIFIED; monitor_unlock (da->lock); return 0; } static int _da_clear_flags (attribute_t attribute) { struct _da *da = (struct _da *)attribute; monitor_lock (da->lock); da->flags = 0; monitor_unlock (da->lock); return 0; } static struct _attribute_vtable _da_vtable = { _da_add_ref, _da_release, _da_destroy, _da_get_flags, _da_set_flags, _da_unset_flags, _da_clear_flags }; int attribute_create (attribute_t *pattribute) { struct _da *da; if (pattribute == NULL) return MU_ERROR_INVALID_PARAMETER; da = calloc (1, sizeof *da); if (da == NULL) return MU_ERROR_NO_MEMORY; da->base.vtable = &_da_vtable; da->ref = 1; da->flags = 0; monitor_create (&(da->lock)); *pattribute = &da->base; return 0; }