/* -*- Mode: C; c-basic-offset: 4 -*- */

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include "pygobject-private.h"
#include "pythread.h"
#include <structmember.h> /* for PyMemberDef */


typedef struct {
    PyObject_HEAD
    GIOChannel *channel;
    int softspace;         /* to make print >> chan, "foo" ... work */
} PyGIOChannel;

static PyObject*
py_io_channel_next(PyGIOChannel *self)
{
    PyObject* ret_obj = NULL;
    gsize length = 0, terminator_pos;
    gchar *str_return = NULL;
    GError *error = NULL;
    GIOStatus status;

    status = g_io_channel_read_line(self->channel, &str_return, &length,
                                    &terminator_pos, &error);
    if (pyg_error_check(&error))
        return NULL;

    if (status == G_IO_STATUS_EOF) {
        PyErr_SetString(PyExc_StopIteration, "EOF");
        return NULL;
    }

    ret_obj = PyString_FromStringAndSize(str_return, length);
    g_free(str_return);
    return ret_obj;

}

static int
py_io_channel_compare(PyGIOChannel *self, PyGIOChannel *v)
{
    if (self->channel == v->channel) return 0;
    if (self->channel > v->channel) return -1;
    return 1;
}

static PyObject*
py_io_channel_get_iter(PyObject *self)
{
    Py_INCREF(self);
    return self;
}

static long
py_io_channel_hash(PyGIOChannel *self)
{
    return (long) self->channel;
}

static void
py_io_channel_dealloc(PyGIOChannel *self)
{
    if (self->channel)
        g_io_channel_unref(self->channel);
    PyObject_DEL(self);
}

static PyObject*
py_io_channel_shutdown(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "flush", NULL };
    GIOStatus ret;
    PyObject* flush = Py_True;
    GError* error = NULL;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:gobject.IOChannel.shutdown", kwlist, &flush))
        return NULL;
	
    ret = g_io_channel_shutdown(self->channel, PyObject_IsTrue(flush), &error);
    if (pyg_error_check(&error))
	return NULL;
	
    return PyInt_FromLong(ret);
}

/* character encoding conversion involved functions.
 */
 
static PyObject*
py_io_channel_set_buffer_size(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "size", NULL };
    int size;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:gobject.IOChannel.set_buffer_size", kwlist, &size))
        return NULL;
	
    g_io_channel_set_buffer_size(self->channel, size);
    
    Py_INCREF(Py_None);
    return Py_None;
}

static PyObject*
py_io_channel_get_buffer_size(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { NULL };
    int size;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:gobject.IOChannel.get_buffer_size", kwlist))
        return NULL;
	
    size = g_io_channel_get_buffer_size(self->channel);
    
    return PyInt_FromLong(size);
}

static PyObject*
py_io_channel_set_buffered(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "buffered", NULL };
    int buffered;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:gobject.IOChannel.set_buffered", kwlist, &buffered))
        return NULL;
	
    g_io_channel_set_buffered(self->channel, buffered);
    
    Py_INCREF(Py_None);
    return Py_None;
}

static PyObject*
py_io_channel_get_buffered(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { NULL };
    int buffered;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, ":gobject.IOChannel.get_buffered", kwlist))
        return NULL;
	
    buffered = g_io_channel_get_buffered(self->channel);
    
    return PyInt_FromLong(buffered);
}

static PyObject*
py_io_channel_set_encoding(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "encoding", NULL };
    const char* encoding;
    GError* error = NULL;
    
    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z:gobject.IOChannel.set_encoding", kwlist, &encoding))
        return NULL;
    
    g_io_channel_set_encoding(self->channel, encoding, &error);
    if (pyg_error_check(&error))
	return NULL;
    
    Py_INCREF(Py_None);
    return Py_None;
}

static PyObject*
py_io_channel_get_encoding(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { NULL };
    const char* encoding;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, ":gobject.IOChannel.get_encoding", kwlist))
        return NULL;
	
    encoding = g_io_channel_get_encoding(self->channel);
    
    if (encoding == NULL) {
	Py_INCREF(Py_None);
	return Py_None;
    }

    return PyString_FromString(encoding);
}

#define CHUNK_SIZE (8 * 1024)

static PyObject*
py_io_channel_read_chars(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "max_count", NULL };
    int max_count = -1;
    PyObject* ret_obj = NULL;
    gsize total_read = 0;
    GError* error = NULL;
    GIOStatus status = G_IO_STATUS_NORMAL;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:gobject.IOChannel.read", kwlist, &max_count))
        return NULL;
	
    if (max_count == 0)
	return PyString_FromString("");
    
    while (status == G_IO_STATUS_NORMAL
	   && (max_count == -1 || total_read < max_count)) {
	gsize single_read;
	char* buf;
	gsize buf_size;
	
	if (max_count == -1) 
	    buf_size = CHUNK_SIZE;
	else {
	    buf_size = max_count - total_read;
	    if (buf_size > CHUNK_SIZE)
		buf_size = CHUNK_SIZE;
        }
	
	if ( ret_obj == NULL ) {
	    ret_obj = PyString_FromStringAndSize((char *)NULL, buf_size);
	    if (ret_obj == NULL)
		goto failure;
	}
	else if (buf_size + total_read > PyString_GET_SIZE(ret_obj)) {
	    if (_PyString_Resize(&ret_obj, buf_size + total_read) == -1)
		goto failure;
	}
       
        buf = PyString_AS_STRING(ret_obj) + total_read;

        pyg_unblock_threads();
        status = g_io_channel_read_chars(self->channel, buf, buf_size, 
                                         &single_read, &error);
        pyg_block_threads();
	if (pyg_error_check(&error))
	    goto failure;
	
	total_read += single_read;
    }
	
    if ( total_read != PyString_GET_SIZE(ret_obj) ) {
	if (_PyString_Resize(&ret_obj, total_read) == -1)
	    goto failure;
    }
    return ret_obj;

  failure:
    Py_XDECREF(ret_obj);
    return NULL;
}

static PyObject*
py_io_channel_write_chars(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "buf", NULL };
    const char* buf;
    Py_ssize_t buf_len;
    gsize count;
    GError* error = NULL;
    GIOStatus status;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#:gobject.IOChannel.write",
                                     kwlist, &buf, &buf_len))
        return NULL;
	
    pyg_unblock_threads();
    status = g_io_channel_write_chars(self->channel, buf, buf_len, &count, &error);
    pyg_block_threads();
    if (pyg_error_check(&error))
	return NULL;
	
    return PyInt_FromLong(count);
}

static PyObject*
py_io_channel_write_lines(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "lines", NULL };
    char *buf;
    Py_ssize_t buf_len;
    gsize count;
    GError* error = NULL;
    GIOStatus status;
    PyObject *iter, *value, *pylines;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:gobject.IOChannel.writelines",
                                     kwlist, &pylines))
        return NULL;

    iter = PyObject_GetIter(pylines);
    
    while (1) {
        value = PyIter_Next(iter);
        if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
            PyErr_Clear();
            goto normal_exit;
        }
        if (!PyString_Check(value)) {
            PyErr_SetString(PyExc_TypeError, "gobject.IOChannel.writelines must"
                            " be sequence/iterator of strings");
            Py_DECREF(iter);
            return NULL;
        }
        PyString_AsStringAndSize(value, &buf, &buf_len);
        pyg_unblock_threads();
        status = g_io_channel_write_chars(self->channel, buf, buf_len, &count, &error);
        pyg_unblock_threads();
        Py_DECREF(value);
        if (pyg_error_check(&error)) {
            Py_DECREF(iter);
            return NULL;
        }
    }
normal_exit:
    Py_DECREF(iter);
    Py_INCREF(Py_None);
    return Py_None;
}

static PyObject*
py_io_channel_flush(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { NULL };
    GError* error = NULL;
    GIOStatus status;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, ":gobject.IOChannel.flush",
                                     kwlist))
        return NULL;
	
    pyg_unblock_threads();
    status = g_io_channel_flush(self->channel, &error);
    pyg_block_threads();
    if (pyg_error_check(&error))
	return NULL;
	
    return PyInt_FromLong(status);
}

static PyObject*
py_io_channel_set_flags(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "flags", NULL };
    GIOFlags flags;
    GIOStatus status;
    GError* error = NULL;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:gobject.IOChannel.set_flags",
                                     kwlist, &flags))
        return NULL;
	
    status = g_io_channel_set_flags(self->channel, flags, &error);
    if (pyg_error_check(&error))
	return NULL;
	
    return PyInt_FromLong(status);
}

static PyObject*
py_io_channel_get_flags(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { NULL };
    GIOFlags flags;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, ":gobject.IOChannel.get_flags",
                                     kwlist))
        return NULL;
	
    flags = g_io_channel_get_flags(self->channel);
    return PyInt_FromLong(flags);
}

static PyObject*
py_io_channel_get_buffer_condition(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { NULL };
    GIOCondition cond;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, ":gobject.IOChannel.get_buffer_condition",
                                     kwlist))
        return NULL;
	
    cond = g_io_channel_get_buffer_condition(self->channel);
    return PyInt_FromLong(cond);
}

static PyObject*
py_io_channel_set_close_on_unref(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "do_close", NULL };
    PyObject *do_close;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:gobject.IOChannel.set_close_on_unref",
                                     kwlist, &do_close))
        return NULL;
	
    g_io_channel_set_close_on_unref(self->channel, PyObject_IsTrue(do_close));
    Py_INCREF(Py_None);
    return Py_None;
}

static PyObject*
py_io_channel_get_close_on_unref(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
{
    if (g_io_channel_get_close_on_unref(self->channel)) {
        Py_INCREF(Py_True);
        return Py_True;
    } else {
        Py_INCREF(Py_False);
        return Py_False;
    }
}

typedef struct {
    PyObject *callback;
    PyObject *iochannel;
    PyObject *user_data;
} PyGIOWatchData;

static void
pyg_iowatch_data_free(PyGIOWatchData *data)
{
    Py_DECREF(data->callback);
    Py_XDECREF(data->user_data);
    Py_DECREF(data->iochannel);
    g_free(data);
}

static gboolean
pyg_iowatch_marshal(GIOChannel *source,
                    GIOCondition condition,
                    gpointer user_data)
{
    PyObject *ret;
    gboolean res;
    PyGIOWatchData *data = (PyGIOWatchData *) user_data;
    PyGILState_STATE state;

    g_return_val_if_fail(user_data != NULL, FALSE);
    g_return_val_if_fail(((PyGIOChannel *) data->iochannel)->channel == source,
                         FALSE);

    state = pyg_gil_state_ensure();

    if (data->user_data)
        ret = PyObject_CallFunction(data->callback, "OiO", data->iochannel,
                                    condition, data->user_data);
    else
        ret = PyObject_CallFunction(data->callback, "Oi", data->iochannel,
                                    condition);

    if (!ret) {
	PyErr_Print();
	res = FALSE;
    } else {
	res = PyObject_IsTrue(ret);
	Py_DECREF(ret);
    }
    pyg_gil_state_release(state);

    return res;
}



static PyObject *
py_io_channel_add_watch(PyObject *self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "condition", "callback", "user_data", "priority", NULL };
    PyObject *callback, *user_data = NULL;
    int priority = G_PRIORITY_DEFAULT, condition;
    GIOChannel *iochannel = NULL;
    guint handler_id;
    PyGIOWatchData *data;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                     "iO|Oi:gobject.IOChannel.add_watch",
                                     kwlist, &condition, &callback,
                                     &user_data, &priority))
        return NULL;

    iochannel = ((PyGIOChannel *) self)->channel;

    if (!PyCallable_Check(callback)) {
        PyErr_SetString(PyExc_TypeError, "second must be callable");
        return NULL;
    }

    data = g_new(PyGIOWatchData, 1);
    data->callback = callback; Py_INCREF(callback);
    data->user_data = user_data; Py_XINCREF(user_data);
    data->iochannel = self; Py_INCREF(self);

    handler_id = g_io_add_watch_full(((PyGIOChannel *) self)->channel,
                                     priority, condition,
				     pyg_iowatch_marshal, data,
				     (GDestroyNotify) pyg_iowatch_data_free);
    return PyLong_FromUnsignedLong(handler_id);
}


#ifdef G_OS_WIN32

static PyObject *
py_io_channel_win32_poll(PyObject *self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "fds", "timeout", NULL };
    GPollFD *pollfd;
    PyObject *pyfds, *pyfd;
    guint len, i;
    gint timeout = -1;
    gint result;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                     "O!|i:gobject.IOChannel.win32_poll",
                                     kwlist, &PyList_Type, &pyfds, &timeout))
        return NULL;

    len = PyList_Size(pyfds);
    pollfd = g_newa(GPollFD, len);
    for (i = 0; i < len; ++i) {
        pyfd = PyList_GET_ITEM(pyfds, i);
        if (!PyObject_TypeCheck(pyfd, &PyGPollFD_Type)) {
            PyErr_SetString(PyExc_TypeError, "'fds' must be a list of gobject.PollFD objects");
            return NULL;
        }
        pollfd[i] = ((PyGPollFD *) pyfd)->pollfd;
    }

    result = g_io_channel_win32_poll(pollfd, len, timeout);
    for (i = 0; i < len; ++i) {
        pyfd = PyList_GET_ITEM(pyfds, i);
        ((PyGPollFD *) pyfd)->pollfd = pollfd[i];
    }
    return PyInt_FromLong(result);
}

static PyObject *
py_io_channel_win32_make_pollfd(PyObject *self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "condition", NULL };
    int condition;
    GPollFD pollfd;
    PyGPollFD *pypollfd;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                     "i:gobject.IOChannel.win32_make_pollfd",
                                     kwlist, &condition))
        return NULL;

    g_io_channel_win32_make_pollfd(((PyGIOChannel *) self)->channel,
                                   condition, &pollfd);
    pypollfd = PyObject_NEW(PyGPollFD, &PyGPollFD_Type);
    pypollfd->pollfd = pollfd;
    return (PyObject *) pypollfd;
}
#endif /* def G_OS_WIN32 */


static PyObject*
py_io_channel_read_line(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "size", NULL };
    PyObject* ret_obj = NULL;
    gsize length = 0, terminator_pos;
    gchar *str_return = NULL;
    GError *error = NULL;
    gint size_hint = -1;
    GIOStatus status;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:gobject.IOChannel.readline", kwlist,
                                     &size_hint))
        return NULL;

    status = g_io_channel_read_line(self->channel, &str_return, &length,
                                    &terminator_pos, &error);
    if (pyg_error_check(&error))
        return NULL;
    ret_obj = PyString_FromStringAndSize(str_return, length);
    g_free(str_return);
    return ret_obj;
}

static PyObject*
py_io_channel_read_lines(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "size", NULL };
    PyObject *line = NULL;
    gsize length = 0, terminator_pos;
    gchar *str_return = NULL;
    GError *error = NULL;
    gint size_hint = -1;
    GIOStatus status = G_IO_STATUS_NORMAL;
    PyObject *list;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:gobject.IOChannel.readlines", kwlist,
                                     &size_hint))
        return NULL;

    list = PyList_New(0);
    while (status == G_IO_STATUS_NORMAL) {
        status = g_io_channel_read_line(self->channel, &str_return, &length,
                                        &terminator_pos, &error);
        if (pyg_error_check(&error)) {
            Py_DECREF(line);
            return NULL;
        }
        line = PyString_FromStringAndSize(str_return, length);
        g_free(str_return);
        if (PyList_Append(list, line)) {
            Py_DECREF(line);
            Py_DECREF(list);
            return NULL;
        }
    }
    return list;
}


static PyObject*
py_io_channel_seek(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "offset", "whence", NULL };
    gint64 offset;
    int whence = 0;
    GIOStatus status;
    GSeekType seek_type;
    GError* error = NULL;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "L|i:gobject.IOChannel.seek",
                                     kwlist, &offset, &whence))
        return NULL;

    switch (whence)
    {
    case 0: seek_type = G_SEEK_SET; break;
    case 1: seek_type = G_SEEK_CUR; break;
    case 2: seek_type = G_SEEK_END; break;
    default:
        PyErr_SetString(PyExc_ValueError, "invalid 'whence' value");
        return NULL;
    }
	
    status = g_io_channel_seek_position(self->channel, offset,
                                        seek_type, &error);
    if (pyg_error_check(&error))
	return NULL;
	
    return PyInt_FromLong(status);
}

#if 0 // Not wrapped
void                  g_io_channel_set_line_term        (GIOChannel   *channel,
							 const gchar  *line_term,
							 gint          length);

G_CONST_RETURN gchar* g_io_channel_get_line_term        (GIOChannel   *channel,
							 gint         *length);



GIOStatus   g_io_channel_read_line_string (GIOChannel   *channel,
					   GString      *buffer,
					   gsize        *terminator_pos,
					   GError      **error);
GIOStatus   g_io_channel_read_to_end      (GIOChannel   *channel,
					   gchar       **str_return,
					   gsize        *length,
					   GError      **error);
GIOStatus   g_io_channel_read_unichar     (GIOChannel   *channel,
					   gunichar     *thechar,
					   GError      **error);
GIOStatus   g_io_channel_write_unichar    (GIOChannel   *channel,
					   gunichar      thechar,
					   GError      **error);
#endif // Not wrapped

static PyMemberDef py_io_channel_members[] = {
    { "softspace", T_INT, offsetof(PyGIOChannel, softspace), 0, NULL },
    { NULL, 0, 0, 0, NULL }
};

static PyMethodDef py_io_channel_methods[] = {
    { "close", (PyCFunction)py_io_channel_shutdown, METH_KEYWORDS },
    { "flush", (PyCFunction)py_io_channel_flush, METH_KEYWORDS },
    { "set_encoding", (PyCFunction)py_io_channel_set_encoding, METH_KEYWORDS },
    { "get_encoding", (PyCFunction)py_io_channel_get_encoding, METH_KEYWORDS },
    { "set_buffered", (PyCFunction)py_io_channel_set_buffered, METH_KEYWORDS },
    { "get_buffered", (PyCFunction)py_io_channel_get_buffered, METH_KEYWORDS },
    { "set_buffer_size", (PyCFunction)py_io_channel_set_buffer_size, METH_KEYWORDS },
    { "get_buffer_size", (PyCFunction)py_io_channel_get_buffer_size, METH_KEYWORDS },
    { "read", (PyCFunction)py_io_channel_read_chars, METH_KEYWORDS },
    { "readline", (PyCFunction)py_io_channel_read_line, METH_KEYWORDS },
    { "readlines", (PyCFunction)py_io_channel_read_lines, METH_KEYWORDS },
    { "write", (PyCFunction)py_io_channel_write_chars, METH_KEYWORDS },
    { "writelines", (PyCFunction)py_io_channel_write_lines, METH_KEYWORDS },
    { "set_flags", (PyCFunction)py_io_channel_set_flags, METH_KEYWORDS },
    { "get_flags", (PyCFunction)py_io_channel_get_flags, METH_KEYWORDS },
    { "get_buffer_condition", (PyCFunction)py_io_channel_get_buffer_condition, METH_KEYWORDS },
    { "set_close_on_unref", (PyCFunction)py_io_channel_set_close_on_unref, METH_NOARGS },
    { "get_close_on_unref", (PyCFunction)py_io_channel_get_close_on_unref, METH_KEYWORDS },
    { "add_watch", (PyCFunction)py_io_channel_add_watch, METH_KEYWORDS },
    { "seek", (PyCFunction)py_io_channel_seek, METH_KEYWORDS },
#ifdef G_OS_WIN32
    { "win32_make_pollfd", (PyCFunction)py_io_channel_win32_make_pollfd, METH_KEYWORDS },
    { "win32_poll", (PyCFunction)py_io_channel_win32_poll, METH_KEYWORDS|METH_STATIC },
#endif
    { NULL, NULL, 0 }
};


static int
py_io_channel_init(PyGIOChannel *self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "filedes", "filename", "mode",
#ifdef G_OS_WIN32
                              "hwnd",
#endif
                              NULL };
    int fd = -1;
    char *mode = "r", *filename = NULL;
    GError *error = NULL;
#ifdef G_OS_WIN32
    guint hwnd = 0;
#endif

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iss"
#ifdef G_OS_WIN32
                                     "I"
#endif
                                     ":gobject.IOChannel.__init__",
                                     kwlist, &fd, &filename, &mode
#ifdef G_OS_WIN32
                                     , &hwnd
#endif
            ))
        return -1;

    if (fd != -1)
        self->channel = g_io_channel_unix_new(fd);
    else if (filename != NULL) {
        self->channel = g_io_channel_new_file(filename, mode, &error);
        if (pyg_error_check(&error))
            return -1;
    }
#ifdef G_OS_WIN32
    else if (hwnd != 0) {
        self->channel = g_io_channel_win32_new_messages(hwnd);
    }
#endif
    else {
#ifdef G_OS_WIN32
        PyErr_SetString(PyExc_TypeError, "either a valid file descriptor, "
                        "file name, or window handle must be supplied");
#else
        PyErr_SetString(PyExc_TypeError, "either a valid file descriptor "
                        "or file name must be supplied");
#endif
        return -1;
    }
    return 0;
}


PyTypeObject PyGIOChannel_Type = {
    PyObject_HEAD_INIT(NULL)
    0,					/* ob_size */
    "gobject.IOChannel",		/* tp_name */
    sizeof(PyGIOChannel),		/* tp_basicsize */
    0,					/* tp_itemsize */
    /* methods */
    (destructor)py_io_channel_dealloc,	/* tp_dealloc */
    (printfunc)0,			/* tp_print */
    (getattrfunc)NULL,             	/* tp_getattr */
    (setattrfunc)0,			/* tp_setattr */
    (cmpfunc)py_io_channel_compare,	/* tp_compare */
    (reprfunc)0,			/* tp_repr */
    0,					/* tp_as_number */
    0,					/* tp_as_sequence */
    0,					/* tp_as_mapping */
    (hashfunc)py_io_channel_hash,	/* tp_hash */
    (ternaryfunc)0,			/* tp_call */
    (reprfunc)0,			/* tp_str */
    (getattrofunc)0,			/* tp_getattro */
    (setattrofunc)0,			/* tp_setattro */
    0,					/* tp_as_buffer */
    Py_TPFLAGS_DEFAULT,			/* tp_flags */
    NULL, /* Documentation string */
    (traverseproc)0,			/* tp_traverse */
    (inquiry)0,				/* tp_clear */
    (richcmpfunc)0,			/* tp_richcompare */
    0,					/* tp_weaklistoffset */
    (getiterfunc)py_io_channel_get_iter,/* tp_iter */
    (iternextfunc)py_io_channel_next,   /* tp_iternext */
    py_io_channel_methods,		/* tp_methods */
    py_io_channel_members,		/* tp_members */
    NULL,				/* tp_getset */
    (PyTypeObject *)0,			/* tp_base */
    (PyObject *)0,			/* tp_dict */
    0,					/* tp_descr_get */
    0,					/* tp_descr_set */
    0,					/* tp_dictoffset */
    (initproc)py_io_channel_init,	/* tp_init */
    (allocfunc)0,			/* tp_alloc */
    (newfunc)0,				/* tp_new */
    0,					/* tp_free */
    (inquiry)0,				/* tp_is_gc */
    (PyObject *)0,			/* tp_bases */
};



syntax highlighted by Code2HTML, v. 0.9.1