/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
*
* This library is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation.
*
* This library 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see .
*
* Authors: Jeffrey Stedfast
*/
#ifdef HAVE_CONFIG_H
#include
#endif
#include
#include "camel-mime-filter-linewrap.h"
#define CAMEL_MIME_FILTER_LINEWRAP_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE \
((obj), CAMEL_TYPE_MIME_FILTER_LINEWRAP, CamelMimeFilterLinewrapPrivate))
struct _CamelMimeFilterLinewrapPrivate {
guint wrap_len;
guint max_len;
gchar indent;
gint nchars;
guint32 flags;
};
G_DEFINE_TYPE (CamelMimeFilterLinewrap, camel_mime_filter_linewrap, CAMEL_TYPE_MIME_FILTER)
static void
mime_filter_linewrap_filter (CamelMimeFilter *mime_filter,
const gchar *in,
gsize len,
gsize prespace,
gchar **out,
gsize *outlen,
gsize *outprespace)
{
CamelMimeFilterLinewrapPrivate *priv;
gchar *q;
const gchar *inend, *p;
gint nchars;
priv = CAMEL_MIME_FILTER_LINEWRAP_GET_PRIVATE (mime_filter);
nchars = priv->nchars;
/* we'll be adding chars here so we need a bigger buffer */
camel_mime_filter_set_size (mime_filter, 3 * len, FALSE);
p = in;
q = mime_filter->outbuf;
inend = in + len;
while (p < inend) {
if (*p == '\n') {
*q++ = *p++;
nchars = 0;
} else if (isspace (*p)) {
if (nchars >= priv->wrap_len) {
*q++ = '\n';
while (p < inend && isspace (*p))
p++;
nchars = 0;
} else {
*q++ = *p++;
nchars++;
}
} else {
*q++ = *p++;
nchars++;
}
/* line is getting way too long, we must force a wrap here */
if (nchars >= priv->max_len && *p != '\n') {
gboolean wrapped = FALSE;
if (isspace (*p)) {
while (p < inend && isspace (*p) && *p != '\n')
p++;
} else if ((priv->flags & CAMEL_MIME_FILTER_LINEWRAP_WORD) != 0) {
gchar *r = q - 1;
/* find the first space backward */
while (r > mime_filter->outbuf && !isspace (*r))
r--;
if (r > mime_filter->outbuf && *r != '\n') {
/* found some valid */
*r = '\n';
wrapped = TRUE;
if ((priv->flags & CAMEL_MIME_FILTER_LINEWRAP_NOINDENT) == 0) {
gchar *s = q + 1;
while (s > r) {
*s = *(s - 1);
s--;
}
*r = priv->indent;
q++;
}
nchars = q - r - 1;
}
}
if (!wrapped) {
*q++ = '\n';
if ((priv->flags & CAMEL_MIME_FILTER_LINEWRAP_NOINDENT) == 0) {
*q++ = priv->indent;
nchars = 1;
} else
nchars = 0;
}
}
}
priv->nchars = nchars;
*out = mime_filter->outbuf;
*outlen = q - mime_filter->outbuf;
*outprespace = mime_filter->outpre;
}
static void
mime_filter_linewrap_complete (CamelMimeFilter *mime_filter,
const gchar *in,
gsize len,
gsize prespace,
gchar **out,
gsize *outlen,
gsize *outprespace)
{
if (len)
mime_filter_linewrap_filter (
mime_filter, in, len, prespace,
out, outlen, outprespace);
}
static void
mime_filter_linewrap_reset (CamelMimeFilter *mime_filter)
{
CamelMimeFilterLinewrapPrivate *priv;
priv = CAMEL_MIME_FILTER_LINEWRAP_GET_PRIVATE (mime_filter);
priv->nchars = 0;
}
static void
camel_mime_filter_linewrap_class_init (CamelMimeFilterLinewrapClass *class)
{
CamelMimeFilterClass *mime_filter_class;
g_type_class_add_private (class, sizeof (CamelMimeFilterLinewrapPrivate));
mime_filter_class = CAMEL_MIME_FILTER_CLASS (class);
mime_filter_class->filter = mime_filter_linewrap_filter;
mime_filter_class->complete = mime_filter_linewrap_complete;
mime_filter_class->reset = mime_filter_linewrap_reset;
}
static void
camel_mime_filter_linewrap_init (CamelMimeFilterLinewrap *filter)
{
filter->priv = CAMEL_MIME_FILTER_LINEWRAP_GET_PRIVATE (filter);
}
CamelMimeFilter *
camel_mime_filter_linewrap_new (guint preferred_len,
guint max_len,
gchar indent_char,
guint32 flags)
{
CamelMimeFilter *filter;
CamelMimeFilterLinewrapPrivate *priv;
filter = g_object_new (CAMEL_TYPE_MIME_FILTER_LINEWRAP, NULL);
priv = CAMEL_MIME_FILTER_LINEWRAP_GET_PRIVATE (filter);
priv->indent = indent_char;
priv->wrap_len = preferred_len;
priv->max_len = max_len;
priv->nchars = 0;
if (indent_char == 0)
priv->flags |= CAMEL_MIME_FILTER_LINEWRAP_NOINDENT;
return filter;
}