* camel/camel-types.h: New header with the typedefs for all camel classes. Now the class headers can just include this and the header for the parent type. This makes it possible for CamelService to include a CamelSession without creating an #include loop. * camel/*: * composer/e-msg-composer-attachment-bar.h: * mail/folder-browser.c: * mail/message-list.c: frob #includes to match the new reality svn path=/trunk/; revision=1850
300 lines
7.2 KiB
C
300 lines
7.2 KiB
C
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
|
||
/* camel-simple-data-wrapper-stream.c
|
||
*
|
||
* Copyright 1999, 2000 HelixCode (http://www.helixcode.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., 59 Temple Place - Suite 330,
|
||
* Boston, MA 02111-1307, USA.
|
||
*
|
||
* Author: Ettore Perazzoli
|
||
*/
|
||
|
||
#ifdef HAVE_CONFIG_H
|
||
#include <config.h>
|
||
#endif
|
||
|
||
#include "camel-simple-data-wrapper-stream.h"
|
||
#include "camel-simple-data-wrapper.h"
|
||
|
||
|
||
static CamelStreamClass *parent_class = NULL;
|
||
|
||
|
||
/* CamelStream methods. */
|
||
|
||
static gint
|
||
read (CamelStream *stream,
|
||
gchar *buffer,
|
||
gint n)
|
||
{
|
||
CamelSimpleDataWrapperStream *wrapper_stream;
|
||
CamelSimpleDataWrapper *wrapper;
|
||
GByteArray *array;
|
||
gint len;
|
||
|
||
wrapper_stream = CAMEL_SIMPLE_DATA_WRAPPER_STREAM (stream);
|
||
wrapper = wrapper_stream->wrapper;
|
||
g_return_val_if_fail (wrapper != NULL, -1);
|
||
array = wrapper->byte_array;
|
||
|
||
len = MIN (n, array->len - wrapper_stream->current_position);
|
||
if (len > 0) {
|
||
memcpy (buffer, wrapper_stream->current_position + array->data, len);
|
||
wrapper_stream->current_position += len;
|
||
return len;
|
||
} else {
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
static gint
|
||
write (CamelStream *stream,
|
||
const gchar *buffer,
|
||
gint n)
|
||
{
|
||
CamelSimpleDataWrapperStream *wrapper_stream;
|
||
CamelSimpleDataWrapper *wrapper;
|
||
GByteArray *array;
|
||
gint len;
|
||
const gchar *buffer_next;
|
||
gint left;
|
||
|
||
wrapper_stream = CAMEL_SIMPLE_DATA_WRAPPER_STREAM (stream);
|
||
wrapper = wrapper_stream->wrapper;
|
||
g_return_val_if_fail (wrapper != NULL, -1);
|
||
array = wrapper->byte_array;
|
||
|
||
len = MIN (n, array->len - wrapper_stream->current_position);
|
||
if (len > 0) {
|
||
memcpy (array->data, buffer, len);
|
||
buffer_next = buffer + len;
|
||
left = n - len;
|
||
} else {
|
||
/* If we are past the end of the array, fill with zeros. */
|
||
if (wrapper_stream->current_position > array->len) {
|
||
gint saved_length;
|
||
|
||
saved_length = array->len;
|
||
g_byte_array_set_size
|
||
(array, wrapper_stream->current_position);
|
||
memset (array->data + saved_length,
|
||
0,
|
||
(wrapper_stream->current_position
|
||
- saved_length));
|
||
}
|
||
|
||
buffer_next = buffer;
|
||
left = n;
|
||
}
|
||
|
||
if (n > 0)
|
||
g_byte_array_append (array, buffer_next, left);
|
||
|
||
wrapper_stream->current_position += n;
|
||
return n;
|
||
}
|
||
|
||
static void
|
||
flush (CamelStream *stream)
|
||
{
|
||
/* No op, as we don't do any buffering. */
|
||
}
|
||
|
||
static gint
|
||
available (CamelStream *stream)
|
||
{
|
||
CamelSimpleDataWrapperStream *wrapper_stream;
|
||
CamelSimpleDataWrapper *wrapper;
|
||
GByteArray *array;
|
||
gint available;
|
||
|
||
wrapper_stream = CAMEL_SIMPLE_DATA_WRAPPER_STREAM (stream);
|
||
wrapper = wrapper_stream->wrapper;
|
||
g_return_val_if_fail (wrapper != NULL, -1);
|
||
array = wrapper->byte_array;
|
||
|
||
available = array->len - wrapper_stream->current_position;
|
||
return MAX (available, 0);
|
||
}
|
||
|
||
static gboolean
|
||
eos (CamelStream *stream)
|
||
{
|
||
if (available (stream) > 0)
|
||
return TRUE;
|
||
else
|
||
return FALSE;
|
||
}
|
||
|
||
static void
|
||
close (CamelStream *stream)
|
||
{
|
||
/* Nothing to do, we have no associated file descriptor. */
|
||
}
|
||
|
||
static gint
|
||
seek (CamelSeekableStream *stream,
|
||
gint offset,
|
||
CamelStreamSeekPolicy policy)
|
||
{
|
||
CamelSimpleDataWrapperStream *wrapper_stream;
|
||
gint new_position;
|
||
|
||
wrapper_stream = CAMEL_SIMPLE_DATA_WRAPPER_STREAM (stream);
|
||
|
||
switch (policy) {
|
||
case CAMEL_STREAM_SET:
|
||
new_position = offset;
|
||
break;
|
||
case CAMEL_STREAM_CUR:
|
||
new_position = wrapper_stream->current_position + offset;
|
||
break;
|
||
case CAMEL_STREAM_END:
|
||
new_position = wrapper_stream->wrapper->byte_array->len - offset;
|
||
break;
|
||
default:
|
||
g_warning ("Unknown CamelStreamSeekPolicy %d.", policy);
|
||
return -1;
|
||
}
|
||
|
||
if (new_position<0)
|
||
new_position = 0;
|
||
else if (new_position>=wrapper_stream->wrapper->byte_array->len)
|
||
new_position = wrapper_stream->wrapper->byte_array->len-1;
|
||
|
||
wrapper_stream->current_position = new_position;
|
||
return new_position;
|
||
}
|
||
|
||
|
||
/* This handles destruction of the associated CamelDataWrapper. */
|
||
/* Hm, this should never happen though, because we gtk_object_ref() the
|
||
wrapper. */
|
||
static void
|
||
wrapper_destroy_cb (GtkObject *object,
|
||
gpointer data)
|
||
{
|
||
CamelSimpleDataWrapperStream *stream;
|
||
|
||
g_warning ("CamelSimpleDataWrapperStream: associated CamelSimpleDataWrapper was destroyed.");
|
||
stream = CAMEL_SIMPLE_DATA_WRAPPER_STREAM (object);
|
||
stream->wrapper = NULL;
|
||
}
|
||
|
||
|
||
/* GtkObject methods. */
|
||
|
||
static void
|
||
destroy (GtkObject *object)
|
||
{
|
||
CamelSimpleDataWrapperStream *stream;
|
||
|
||
stream = CAMEL_SIMPLE_DATA_WRAPPER_STREAM (object);
|
||
|
||
gtk_object_unref (GTK_OBJECT (stream->wrapper));
|
||
|
||
if (GTK_OBJECT_CLASS (parent_class)->destroy != NULL)
|
||
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
|
||
}
|
||
|
||
|
||
static void
|
||
class_init (CamelSimpleDataWrapperStreamClass *klass)
|
||
{
|
||
GtkObjectClass *object_class;
|
||
CamelStreamClass *stream_class;
|
||
CamelSeekableStreamClass *seek_class;
|
||
|
||
object_class = (GtkObjectClass*) klass;
|
||
stream_class = (CamelStreamClass *)klass;
|
||
seek_class = (CamelSeekableStreamClass *)klass;
|
||
|
||
stream_class->read = read;
|
||
stream_class->write = write;
|
||
stream_class->flush = flush;
|
||
stream_class->available = available;
|
||
stream_class->eos = eos;
|
||
stream_class->close = close;
|
||
|
||
seek_class->seek = seek;
|
||
|
||
object_class->destroy = destroy;
|
||
|
||
parent_class = gtk_type_class (camel_stream_get_type ());
|
||
}
|
||
|
||
static void
|
||
init (CamelSimpleDataWrapperStream *simple_data_wrapper_stream)
|
||
{
|
||
simple_data_wrapper_stream->current_position = 0;
|
||
}
|
||
|
||
|
||
GtkType
|
||
camel_simple_data_wrapper_stream_get_type (void)
|
||
{
|
||
static GtkType type = 0;
|
||
|
||
if (type == 0) {
|
||
static const GtkTypeInfo info = {
|
||
"CamelSimpleDataWrapperStream",
|
||
sizeof (CamelSimpleDataWrapperStream),
|
||
sizeof (CamelSimpleDataWrapperStreamClass),
|
||
(GtkClassInitFunc) class_init,
|
||
(GtkObjectInitFunc) init,
|
||
/* reserved_1 */ NULL,
|
||
/* reserved_2 */ NULL,
|
||
(GtkClassInitFunc) NULL,
|
||
};
|
||
|
||
type = gtk_type_unique (camel_stream_get_type (), &info);
|
||
}
|
||
|
||
return type;
|
||
}
|
||
|
||
void
|
||
camel_simple_data_wrapper_stream_construct (CamelSimpleDataWrapperStream *stream,
|
||
CamelSimpleDataWrapper *wrapper)
|
||
{
|
||
g_return_if_fail (stream != NULL);
|
||
g_return_if_fail (CAMEL_IS_SIMPLE_DATA_WRAPPER_STREAM (stream));
|
||
g_return_if_fail (wrapper != NULL);
|
||
g_return_if_fail (CAMEL_IS_SIMPLE_DATA_WRAPPER (wrapper));
|
||
|
||
gtk_object_ref (GTK_OBJECT (wrapper));
|
||
stream->wrapper = wrapper;
|
||
#if 0
|
||
gtk_signal_connect (GTK_OBJECT (wrapper), "destroy",
|
||
wrapper_destroy_cb, stream);
|
||
#endif
|
||
}
|
||
|
||
CamelStream *
|
||
camel_simple_data_wrapper_stream_new (CamelSimpleDataWrapper *wrapper)
|
||
{
|
||
CamelStream *stream;
|
||
|
||
g_return_val_if_fail (wrapper != NULL, NULL);
|
||
g_return_val_if_fail (CAMEL_IS_SIMPLE_DATA_WRAPPER (wrapper), NULL);
|
||
|
||
stream = gtk_type_new (camel_simple_data_wrapper_stream_get_type ());
|
||
|
||
camel_simple_data_wrapper_stream_construct
|
||
(CAMEL_SIMPLE_DATA_WRAPPER_STREAM (stream), wrapper);
|
||
|
||
return stream;
|
||
}
|