Blame gtksourceview/gtksourcebufferinputstream.c

Packit a7d494
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- */
Packit a7d494
/* gtksourcebufferinputstream.c
Packit a7d494
 * This file is part of GtkSourceView
Packit a7d494
 *
Packit a7d494
 * Copyright (C) 2010 - Ignacio Casal Quinteiro
Packit a7d494
 * Copyright (C) 2014 - Sébastien Wilmet <swilmet@gnome.org>
Packit a7d494
 *
Packit a7d494
 * GtkSourceView is free software; you can redistribute it and/or
Packit a7d494
 * modify it under the terms of the GNU Lesser General Public
Packit a7d494
 * License as published by the Free Software Foundation; either
Packit a7d494
 * version 2.1 of the License, or (at your option) any later version.
Packit a7d494
 *
Packit a7d494
 * GtkSourceView is distributed in the hope that it will be useful,
Packit a7d494
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit a7d494
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit a7d494
 * Lesser General Public License for more details.
Packit a7d494
 *
Packit a7d494
 * You should have received a copy of the GNU Lesser General Public
Packit a7d494
 * License along with this library; if not, write to the Free Software
Packit a7d494
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
Packit a7d494
 */
Packit a7d494
Packit a7d494
#ifdef HAVE_CONFIG_H
Packit a7d494
#include <config.h>
Packit a7d494
#endif
Packit a7d494
Packit a7d494
#include <glib.h>
Packit a7d494
#include <gio/gio.h>
Packit a7d494
#include <string.h>
Packit a7d494
#include "gtksourcebufferinputstream.h"
Packit a7d494
#include "gtksourceview-enumtypes.h"
Packit a7d494
Packit a7d494
/* NOTE: never use async methods on this stream, the stream is just
Packit a7d494
 * a wrapper around GtkTextBuffer api so that we can use GIO Stream
Packit a7d494
 * methods, but the underlying code operates on a GtkTextBuffer, so
Packit a7d494
 * there is no I/O involved and should be accessed only by the main
Packit a7d494
 * thread.
Packit a7d494
 */
Packit a7d494
Packit a7d494
struct _GtkSourceBufferInputStreamPrivate
Packit a7d494
{
Packit a7d494
	GtkTextBuffer *buffer;
Packit a7d494
	GtkTextMark *pos;
Packit a7d494
	gint bytes_partial;
Packit a7d494
Packit a7d494
	GtkSourceNewlineType newline_type;
Packit a7d494
Packit a7d494
	guint newline_added : 1;
Packit a7d494
	guint is_initialized : 1;
Packit a7d494
	guint add_trailing_newline : 1;
Packit a7d494
};
Packit a7d494
Packit a7d494
enum
Packit a7d494
{
Packit a7d494
	PROP_0,
Packit a7d494
	PROP_BUFFER,
Packit a7d494
	PROP_NEWLINE_TYPE,
Packit a7d494
	PROP_ADD_TRAILING_NEWLINE
Packit a7d494
};
Packit a7d494
Packit a7d494
G_DEFINE_TYPE_WITH_PRIVATE (GtkSourceBufferInputStream, _gtk_source_buffer_input_stream, G_TYPE_INPUT_STREAM);
Packit a7d494
Packit a7d494
static gsize
Packit a7d494
get_new_line_size (GtkSourceBufferInputStream *stream)
Packit a7d494
{
Packit a7d494
	switch (stream->priv->newline_type)
Packit a7d494
	{
Packit a7d494
		case GTK_SOURCE_NEWLINE_TYPE_CR:
Packit a7d494
		case GTK_SOURCE_NEWLINE_TYPE_LF:
Packit a7d494
			return 1;
Packit a7d494
Packit a7d494
		case GTK_SOURCE_NEWLINE_TYPE_CR_LF:
Packit a7d494
			return 2;
Packit a7d494
Packit a7d494
		default:
Packit a7d494
			g_warn_if_reached ();
Packit a7d494
			break;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	return 1;
Packit a7d494
}
Packit a7d494
Packit a7d494
static const gchar *
Packit a7d494
get_new_line (GtkSourceBufferInputStream *stream)
Packit a7d494
{
Packit a7d494
	switch (stream->priv->newline_type)
Packit a7d494
	{
Packit a7d494
		case GTK_SOURCE_NEWLINE_TYPE_LF:
Packit a7d494
			return "\n";
Packit a7d494
Packit a7d494
		case GTK_SOURCE_NEWLINE_TYPE_CR:
Packit a7d494
			return "\r";
Packit a7d494
Packit a7d494
		case GTK_SOURCE_NEWLINE_TYPE_CR_LF:
Packit a7d494
			return "\r\n";
Packit a7d494
Packit a7d494
		default:
Packit a7d494
			g_warn_if_reached ();
Packit a7d494
			break;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	return "\n";
Packit a7d494
}
Packit a7d494
Packit a7d494
static gsize
Packit a7d494
read_line (GtkSourceBufferInputStream *stream,
Packit a7d494
	   gchar                      *outbuf,
Packit a7d494
	   gsize                       space_left)
Packit a7d494
{
Packit a7d494
	GtkTextIter start, next, end;
Packit a7d494
	gchar *buf;
Packit a7d494
	gint bytes; /* int since it's what iter_get_offset returns */
Packit a7d494
	gsize bytes_to_write, newline_size, read;
Packit a7d494
	const gchar *newline;
Packit a7d494
	gboolean is_last;
Packit a7d494
Packit a7d494
	if (stream->priv->buffer == NULL)
Packit a7d494
	{
Packit a7d494
		return 0;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	gtk_text_buffer_get_iter_at_mark (stream->priv->buffer,
Packit a7d494
					  &start,
Packit a7d494
					  stream->priv->pos);
Packit a7d494
Packit a7d494
	if (gtk_text_iter_is_end (&start))
Packit a7d494
	{
Packit a7d494
		return 0;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	end = next = start;
Packit a7d494
	newline = get_new_line (stream);
Packit a7d494
Packit a7d494
	/* Check needed for empty lines */
Packit a7d494
	if (!gtk_text_iter_ends_line (&end))
Packit a7d494
	{
Packit a7d494
		gtk_text_iter_forward_to_line_end (&end;;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	gtk_text_iter_forward_line (&next;;
Packit a7d494
Packit a7d494
	buf = gtk_text_iter_get_slice (&start, &end;;
Packit a7d494
Packit a7d494
	/* the bytes of a line includes also the newline, so with the
Packit a7d494
	   offsets we remove the newline and we add the new newline size */
Packit a7d494
	bytes = gtk_text_iter_get_bytes_in_line (&start) - stream->priv->bytes_partial;
Packit a7d494
Packit a7d494
	/* bytes_in_line includes the newlines, so we remove that assuming that
Packit a7d494
	   they are single byte characters */
Packit a7d494
	bytes -= gtk_text_iter_get_offset (&next) - gtk_text_iter_get_offset (&end;;
Packit a7d494
	is_last = gtk_text_iter_is_end (&end;;
Packit a7d494
Packit a7d494
	/* bytes_to_write contains the amount of bytes we would like to write.
Packit a7d494
	   This means its the amount of bytes in the line (without the newline
Packit a7d494
	   in the buffer) + the amount of bytes for the newline we want to
Packit a7d494
	   write (newline_size) */
Packit a7d494
	bytes_to_write = bytes;
Packit a7d494
Packit a7d494
	/* do not add the new newline_size for the last line */
Packit a7d494
	newline_size = get_new_line_size (stream);
Packit a7d494
	if (!is_last)
Packit a7d494
	{
Packit a7d494
		bytes_to_write += newline_size;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	if (bytes_to_write > space_left)
Packit a7d494
	{
Packit a7d494
		gchar *ptr;
Packit a7d494
		gint char_offset;
Packit a7d494
		gint written;
Packit a7d494
		glong to_write;
Packit a7d494
Packit a7d494
		/* Here the line does not fit in the buffer, we thus write
Packit a7d494
		   the amount of bytes we can still fit, storing the position
Packit a7d494
		   for the next read with the mark. Do not try to write the
Packit a7d494
		   new newline in this case, it will be handled in the next
Packit a7d494
		   iteration */
Packit a7d494
		to_write = MIN ((glong)space_left, bytes);
Packit a7d494
		ptr = buf;
Packit a7d494
		written = 0;
Packit a7d494
		char_offset = 0;
Packit a7d494
Packit a7d494
		while (written < to_write)
Packit a7d494
		{
Packit a7d494
			gint w;
Packit a7d494
Packit a7d494
			ptr = g_utf8_next_char (ptr);
Packit a7d494
			w = (ptr - buf);
Packit a7d494
			if (w > to_write)
Packit a7d494
			{
Packit a7d494
				break;
Packit a7d494
			}
Packit a7d494
			else
Packit a7d494
			{
Packit a7d494
				written = w;
Packit a7d494
				++char_offset;
Packit a7d494
			}
Packit a7d494
		}
Packit a7d494
Packit a7d494
		memcpy (outbuf, buf, written);
Packit a7d494
Packit a7d494
		/* Note: offset is one past what we wrote */
Packit a7d494
		gtk_text_iter_forward_chars (&start, char_offset);
Packit a7d494
		stream->priv->bytes_partial += written;
Packit a7d494
		read = written;
Packit a7d494
	}
Packit a7d494
	else
Packit a7d494
	{
Packit a7d494
		/* First just copy the bytes without the newline */
Packit a7d494
		memcpy (outbuf, buf, bytes);
Packit a7d494
Packit a7d494
		/* Then add the newline, but not for the last line */
Packit a7d494
		if (!is_last)
Packit a7d494
		{
Packit a7d494
			memcpy (outbuf + bytes, newline, newline_size);
Packit a7d494
		}
Packit a7d494
Packit a7d494
		start = next;
Packit a7d494
		stream->priv->bytes_partial = 0;
Packit a7d494
		read = bytes_to_write;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	gtk_text_buffer_move_mark (stream->priv->buffer,
Packit a7d494
				   stream->priv->pos,
Packit a7d494
				   &start;;
Packit a7d494
Packit a7d494
	g_free (buf);
Packit a7d494
	return read;
Packit a7d494
}
Packit a7d494
Packit a7d494
static gssize
Packit a7d494
_gtk_source_buffer_input_stream_read (GInputStream  *input_stream,
Packit a7d494
				      void          *buffer,
Packit a7d494
				      gsize          count,
Packit a7d494
				      GCancellable  *cancellable,
Packit a7d494
				      GError       **error)
Packit a7d494
{
Packit a7d494
	GtkSourceBufferInputStream *stream;
Packit a7d494
	GtkTextIter iter;
Packit a7d494
	gssize space_left, read, n;
Packit a7d494
Packit a7d494
	stream = GTK_SOURCE_BUFFER_INPUT_STREAM (input_stream);
Packit a7d494
Packit a7d494
	if (count < 6)
Packit a7d494
	{
Packit a7d494
		g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE,
Packit a7d494
				     "Not enougth space in destination");
Packit a7d494
		return -1;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	if (g_cancellable_set_error_if_cancelled (cancellable, error))
Packit a7d494
	{
Packit a7d494
		return -1;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	if (stream->priv->buffer == NULL)
Packit a7d494
	{
Packit a7d494
		return 0;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	/* Initialize the mark to the first char in the text buffer */
Packit a7d494
	if (!stream->priv->is_initialized)
Packit a7d494
	{
Packit a7d494
		gtk_text_buffer_get_start_iter (stream->priv->buffer, &iter);
Packit a7d494
		stream->priv->pos = gtk_text_buffer_create_mark (stream->priv->buffer,
Packit a7d494
								 NULL,
Packit a7d494
								 &iter,
Packit a7d494
								 FALSE);
Packit a7d494
Packit a7d494
		stream->priv->is_initialized = TRUE;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	space_left = count;
Packit a7d494
	read = 0;
Packit a7d494
Packit a7d494
	do
Packit a7d494
	{
Packit a7d494
		n = read_line (stream, (gchar *)buffer + read, space_left);
Packit a7d494
		read += n;
Packit a7d494
		space_left -= n;
Packit a7d494
	} while (space_left > 0 && n != 0 && stream->priv->bytes_partial == 0);
Packit a7d494
Packit a7d494
	/* Make sure that non-empty files are always terminated with \n (see bug #95676).
Packit a7d494
	 * Note that we strip the trailing \n when loading the file */
Packit a7d494
	gtk_text_buffer_get_iter_at_mark (stream->priv->buffer,
Packit a7d494
					  &iter,
Packit a7d494
					  stream->priv->pos);
Packit a7d494
Packit a7d494
	if (gtk_text_iter_is_end (&iter) &&
Packit a7d494
	    !gtk_text_iter_is_start (&iter) &&
Packit a7d494
	    stream->priv->add_trailing_newline)
Packit a7d494
	{
Packit a7d494
		gssize newline_size;
Packit a7d494
Packit a7d494
		newline_size = get_new_line_size (stream);
Packit a7d494
Packit a7d494
		if (space_left >= newline_size &&
Packit a7d494
		    !stream->priv->newline_added)
Packit a7d494
		{
Packit a7d494
			const gchar *newline;
Packit a7d494
Packit a7d494
			newline = get_new_line (stream);
Packit a7d494
Packit a7d494
			memcpy ((gchar *)buffer + read, newline, newline_size);
Packit a7d494
Packit a7d494
			read += newline_size;
Packit a7d494
			stream->priv->newline_added = TRUE;
Packit a7d494
		}
Packit a7d494
	}
Packit a7d494
Packit a7d494
	return read;
Packit a7d494
}
Packit a7d494
Packit a7d494
static gboolean
Packit a7d494
_gtk_source_buffer_input_stream_close (GInputStream  *input_stream,
Packit a7d494
				       GCancellable  *cancellable,
Packit a7d494
				       GError       **error)
Packit a7d494
{
Packit a7d494
	GtkSourceBufferInputStream *stream = GTK_SOURCE_BUFFER_INPUT_STREAM (input_stream);
Packit a7d494
Packit a7d494
	stream->priv->newline_added = FALSE;
Packit a7d494
Packit a7d494
	if (stream->priv->is_initialized &&
Packit a7d494
	    stream->priv->buffer != NULL)
Packit a7d494
	{
Packit a7d494
		gtk_text_buffer_delete_mark (stream->priv->buffer, stream->priv->pos);
Packit a7d494
	}
Packit a7d494
Packit a7d494
	return TRUE;
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
_gtk_source_buffer_input_stream_set_property (GObject      *object,
Packit a7d494
					      guint         prop_id,
Packit a7d494
					      const GValue *value,
Packit a7d494
					      GParamSpec   *pspec)
Packit a7d494
{
Packit a7d494
	GtkSourceBufferInputStream *stream = GTK_SOURCE_BUFFER_INPUT_STREAM (object);
Packit a7d494
Packit a7d494
	switch (prop_id)
Packit a7d494
	{
Packit a7d494
		case PROP_BUFFER:
Packit a7d494
			g_assert (stream->priv->buffer == NULL);
Packit a7d494
			stream->priv->buffer = g_value_dup_object (value);
Packit a7d494
			break;
Packit a7d494
Packit a7d494
		case PROP_NEWLINE_TYPE:
Packit a7d494
			stream->priv->newline_type = g_value_get_enum (value);
Packit a7d494
			break;
Packit a7d494
Packit a7d494
		case PROP_ADD_TRAILING_NEWLINE:
Packit a7d494
			stream->priv->add_trailing_newline = g_value_get_boolean (value);
Packit a7d494
			break;
Packit a7d494
Packit a7d494
		default:
Packit a7d494
			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit a7d494
			break;
Packit a7d494
	}
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
_gtk_source_buffer_input_stream_get_property (GObject    *object,
Packit a7d494
					  guint       prop_id,
Packit a7d494
					  GValue     *value,
Packit a7d494
					  GParamSpec *pspec)
Packit a7d494
{
Packit a7d494
	GtkSourceBufferInputStream *stream = GTK_SOURCE_BUFFER_INPUT_STREAM (object);
Packit a7d494
Packit a7d494
	switch (prop_id)
Packit a7d494
	{
Packit a7d494
		case PROP_BUFFER:
Packit a7d494
			g_value_set_object (value, stream->priv->buffer);
Packit a7d494
			break;
Packit a7d494
Packit a7d494
		case PROP_NEWLINE_TYPE:
Packit a7d494
			g_value_set_enum (value, stream->priv->newline_type);
Packit a7d494
			break;
Packit a7d494
Packit a7d494
		case PROP_ADD_TRAILING_NEWLINE:
Packit a7d494
			g_value_set_boolean (value, stream->priv->add_trailing_newline);
Packit a7d494
			break;
Packit a7d494
Packit a7d494
		default:
Packit a7d494
			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit a7d494
			break;
Packit a7d494
	}
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
_gtk_source_buffer_input_stream_dispose (GObject *object)
Packit a7d494
{
Packit a7d494
	GtkSourceBufferInputStream *stream = GTK_SOURCE_BUFFER_INPUT_STREAM (object);
Packit a7d494
Packit a7d494
	g_clear_object (&stream->priv->buffer);
Packit a7d494
Packit a7d494
	G_OBJECT_CLASS (_gtk_source_buffer_input_stream_parent_class)->dispose (object);
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
_gtk_source_buffer_input_stream_class_init (GtkSourceBufferInputStreamClass *klass)
Packit a7d494
{
Packit a7d494
	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
Packit a7d494
	GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
Packit a7d494
Packit a7d494
	gobject_class->get_property = _gtk_source_buffer_input_stream_get_property;
Packit a7d494
	gobject_class->set_property = _gtk_source_buffer_input_stream_set_property;
Packit a7d494
	gobject_class->dispose = _gtk_source_buffer_input_stream_dispose;
Packit a7d494
Packit a7d494
	stream_class->read_fn = _gtk_source_buffer_input_stream_read;
Packit a7d494
	stream_class->close_fn = _gtk_source_buffer_input_stream_close;
Packit a7d494
Packit a7d494
	g_object_class_install_property (gobject_class,
Packit a7d494
					 PROP_BUFFER,
Packit a7d494
					 g_param_spec_object ("buffer",
Packit a7d494
							      "GtkTextBuffer",
Packit a7d494
							      "",
Packit a7d494
							      GTK_TYPE_TEXT_BUFFER,
Packit a7d494
							      G_PARAM_READWRITE |
Packit a7d494
							      G_PARAM_CONSTRUCT_ONLY |
Packit a7d494
							      G_PARAM_STATIC_STRINGS));
Packit a7d494
Packit a7d494
	/**
Packit a7d494
	 * GtkSourceBufferInputStream:newline-type:
Packit a7d494
	 *
Packit a7d494
	 * The :newline-type property determines what is considered
Packit a7d494
	 * as a line ending when reading complete lines from the stream.
Packit a7d494
	 */
Packit a7d494
	g_object_class_install_property (gobject_class,
Packit a7d494
					 PROP_NEWLINE_TYPE,
Packit a7d494
					 g_param_spec_enum ("newline-type",
Packit a7d494
							    "Newline type",
Packit a7d494
							    "",
Packit a7d494
							    GTK_SOURCE_TYPE_NEWLINE_TYPE,
Packit a7d494
							    GTK_SOURCE_NEWLINE_TYPE_LF,
Packit a7d494
							    G_PARAM_READWRITE |
Packit a7d494
							    G_PARAM_STATIC_STRINGS |
Packit a7d494
							    G_PARAM_CONSTRUCT_ONLY));
Packit a7d494
Packit a7d494
	/**
Packit a7d494
	 * GtkSourceBufferInputStream:add-trailing-newline:
Packit a7d494
	 *
Packit a7d494
	 * The :add-trailing-newline property specifies whether or not to
Packit a7d494
	 * add a trailing newline when reading the buffer.
Packit a7d494
	 */
Packit a7d494
	g_object_class_install_property (gobject_class,
Packit a7d494
	                                 PROP_ADD_TRAILING_NEWLINE,
Packit a7d494
	                                 g_param_spec_boolean ("add-trailing-newline",
Packit a7d494
	                                                       "Add trailing newline",
Packit a7d494
	                                                       "",
Packit a7d494
	                                                       TRUE,
Packit a7d494
	                                                       G_PARAM_READWRITE |
Packit a7d494
	                                                       G_PARAM_STATIC_STRINGS |
Packit a7d494
	                                                       G_PARAM_CONSTRUCT_ONLY));
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
_gtk_source_buffer_input_stream_init (GtkSourceBufferInputStream *stream)
Packit a7d494
{
Packit a7d494
	stream->priv = _gtk_source_buffer_input_stream_get_instance_private (stream);
Packit a7d494
}
Packit a7d494
Packit a7d494
/**
Packit a7d494
 * _gtk_source_buffer_input_stream_new:
Packit a7d494
 * @buffer: a #GtkTextBuffer
Packit a7d494
 *
Packit a7d494
 * Reads the data from @buffer.
Packit a7d494
 *
Packit a7d494
 * Returns: a new input stream to read @buffer
Packit a7d494
 */
Packit a7d494
GtkSourceBufferInputStream *
Packit a7d494
_gtk_source_buffer_input_stream_new (GtkTextBuffer        *buffer,
Packit a7d494
				     GtkSourceNewlineType  type,
Packit a7d494
				     gboolean              add_trailing_newline)
Packit a7d494
{
Packit a7d494
	g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
Packit a7d494
Packit a7d494
	return g_object_new (GTK_SOURCE_TYPE_BUFFER_INPUT_STREAM,
Packit a7d494
			     "buffer", buffer,
Packit a7d494
			     "newline-type", type,
Packit a7d494
			     "add-trailing-newline", add_trailing_newline,
Packit a7d494
			     NULL);
Packit a7d494
}
Packit a7d494
Packit a7d494
gsize
Packit a7d494
_gtk_source_buffer_input_stream_get_total_size (GtkSourceBufferInputStream *stream)
Packit a7d494
{
Packit a7d494
	g_return_val_if_fail (GTK_SOURCE_IS_BUFFER_INPUT_STREAM (stream), 0);
Packit a7d494
Packit a7d494
	if (stream->priv->buffer == NULL)
Packit a7d494
	{
Packit a7d494
		return 0;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	return gtk_text_buffer_get_char_count (stream->priv->buffer);
Packit a7d494
}
Packit a7d494
Packit a7d494
gsize
Packit a7d494
_gtk_source_buffer_input_stream_tell (GtkSourceBufferInputStream *stream)
Packit a7d494
{
Packit a7d494
	g_return_val_if_fail (GTK_SOURCE_IS_BUFFER_INPUT_STREAM (stream), 0);
Packit a7d494
Packit a7d494
	/* FIXME: is this potentially inefficient? If yes, we could keep
Packit a7d494
	   track of the offset internally, assuming the mark doesn't move
Packit a7d494
	   during the operation */
Packit a7d494
	if (!stream->priv->is_initialized ||
Packit a7d494
	    stream->priv->buffer == NULL)
Packit a7d494
	{
Packit a7d494
		return 0;
Packit a7d494
	}
Packit a7d494
	else
Packit a7d494
	{
Packit a7d494
		GtkTextIter iter;
Packit a7d494
Packit a7d494
		gtk_text_buffer_get_iter_at_mark (stream->priv->buffer,
Packit a7d494
						  &iter,
Packit a7d494
						  stream->priv->pos);
Packit a7d494
		return gtk_text_iter_get_offset (&iter);
Packit a7d494
	}
Packit a7d494
}