
/* Font Manager module */

#include "Python.h"

#include <gl.h>
#include <device.h>
#include <fmclient.h>


/* Font Handle object implementation */

typedef struct {
    PyObject_HEAD
    fmfonthandle fh_fh;
} fhobject;

static PyTypeObject Fhtype;

#define is_fhobject(v)          ((v)->ob_type == &Fhtype)

static PyObject *
newfhobject(fmfonthandle fh)
{
    fhobject *fhp;
    if (fh == NULL) {
        PyErr_SetString(PyExc_RuntimeError,
                        "error creating new font handle");
        return NULL;
    }
    fhp = PyObject_New(fhobject, &Fhtype);
    if (fhp == NULL)
        return NULL;
    fhp->fh_fh = fh;
    return (PyObject *)fhp;
}

/* Font Handle methods */

static PyObject *
fh_scalefont(fhobject *self, PyObject *args)
{
    double size;
    if (!PyArg_ParseTuple(args, "d", &size))
        return NULL;
    return newfhobject(fmscalefont(self->fh_fh, size));
}

/* XXX fmmakefont */

static PyObject *
fh_setfont(fhobject *self)
{
    fmsetfont(self->fh_fh);
    Py_INCREF(Py_None);
    return Py_None;
}

static PyObject *
fh_getfontname(fhobject *self)
{
    char fontname[256];
    int len;
    len = fmgetfontname(self->fh_fh, sizeof fontname, fontname);
    if (len < 0) {
        PyErr_SetString(PyExc_RuntimeError, "error in fmgetfontname");
        return NULL;
    }
    return PyString_FromStringAndSize(fontname, len);
}

static PyObject *
fh_getcomment(fhobject *self)
{
    char comment[256];
    int len;
    len = fmgetcomment(self->fh_fh, sizeof comment, comment);
    if (len < 0) {
        PyErr_SetString(PyExc_RuntimeError, "error in fmgetcomment");
        return NULL;
    }
    return PyString_FromStringAndSize(comment, len);
}

static PyObject *
fh_getfontinfo(fhobject *self)
{
    fmfontinfo info;
    if (fmgetfontinfo(self->fh_fh, &info) < 0) {
        PyErr_SetString(PyExc_RuntimeError, "error in fmgetfontinfo");
        return NULL;
    }
    return Py_BuildValue("(llllllll)",
                         info.printermatched,
                         info.fixed_width,
                         info.xorig,
                         info.yorig,
                         info.xsize,
                         info.ysize,
                         info.height,
                         info.nglyphs);
}

#if 0
static PyObject *
fh_getwholemetrics(fhobject *self, PyObject *args)
{
}
#endif

static PyObject *
fh_getstrwidth(fhobject *self, PyObject *args)
{
    char *str;
    if (!PyArg_ParseTuple(args, "s", &str))
        return NULL;
    return PyInt_FromLong(fmgetstrwidth(self->fh_fh, str));
}

static PyMethodDef fh_methods[] = {
    {"scalefont",       (PyCFunction)fh_scalefont,   METH_VARARGS},
    {"setfont",         (PyCFunction)fh_setfont,     METH_NOARGS},
    {"getfontname",     (PyCFunction)fh_getfontname, METH_NOARGS},
    {"getcomment",      (PyCFunction)fh_getcomment,  METH_NOARGS},
    {"getfontinfo",     (PyCFunction)fh_getfontinfo, METH_NOARGS},
#if 0
    {"getwholemetrics",         (PyCFunction)fh_getwholemetrics, METH_VARARGS},
#endif
    {"getstrwidth",     (PyCFunction)fh_getstrwidth, METH_VARARGS},
    {NULL,              NULL}           /* sentinel */
};

static PyObject *
fh_getattr(fhobject *fhp, char *name)
{
    return Py_FindMethod(fh_methods, (PyObject *)fhp, name);
}

static void
fh_dealloc(fhobject *fhp)
{
    fmfreefont(fhp->fh_fh);
    PyObject_Del(fhp);
}

static PyTypeObject Fhtype = {
    PyObject_HEAD_INIT(&PyType_Type)
    0,                                  /*ob_size*/
    "fm.font handle",                   /*tp_name*/
    sizeof(fhobject),                   /*tp_size*/
    0,                                  /*tp_itemsize*/
    /* methods */
    (destructor)fh_dealloc,             /*tp_dealloc*/
    0,                                  /*tp_print*/
    (getattrfunc)fh_getattr,            /*tp_getattr*/
    0,                                  /*tp_setattr*/
    0,                                  /*tp_compare*/
    0,                                  /*tp_repr*/
};


/* Font Manager functions */

static PyObject *
fm_init(PyObject *self)
{
    fminit();
    Py_INCREF(Py_None);
    return Py_None;
}

static PyObject *
fm_findfont(PyObject *self, PyObject *args)
{
    char *str;
    if (!PyArg_ParseTuple(args, "s", &str))
        return NULL;
    return newfhobject(fmfindfont(str));
}

static PyObject *
fm_prstr(PyObject *self, PyObject *args)
{
    char *str;
    if (!PyArg_ParseTuple(args, "s", &str))
        return NULL;
    fmprstr(str);
    Py_INCREF(Py_None);
    return Py_None;
}

/* XXX This uses a global variable as temporary! Not re-entrant! */

static PyObject *fontlist;

static void
clientproc(char *fontname)
{
    int err;
    PyObject *v;
    if (fontlist == NULL)
        return;
    v = PyString_FromString(fontname);
    if (v == NULL)
        err = -1;
    else {
        err = PyList_Append(fontlist, v);
        Py_DECREF(v);
    }
    if (err != 0) {
        Py_DECREF(fontlist);
        fontlist = NULL;
    }
}

static PyObject *
fm_enumerate(PyObject *self)
{
    PyObject *res;
    fontlist = PyList_New(0);
    if (fontlist == NULL)
        return NULL;
    fmenumerate(clientproc);
    res = fontlist;
    fontlist = NULL;
    return res;
}

static PyObject *
fm_setpath(PyObject *self, PyObject *args)
{
    char *str;
    if (!PyArg_ParseTuple(args, "s", &str))
        return NULL;
    fmsetpath(str);
    Py_INCREF(Py_None);
    return Py_None;
}

static PyObject *
fm_fontpath(PyObject *self)
{
    return PyString_FromString(fmfontpath());
}

static PyMethodDef fm_methods[] = {
    {"init",            fm_init,      METH_NOARGS},
    {"findfont",        fm_findfont,  METH_VARARGS},
    {"enumerate",       fm_enumerate, METH_NOARGS},
    {"prstr",           fm_prstr,     METH_VARARGS},
    {"setpath",         fm_setpath,   METH_VARARGS},
    {"fontpath",        fm_fontpath,  METH_NOARGS},
    {NULL,              NULL}           /* sentinel */
};


void
initfm(void)
{
    if (PyErr_WarnPy3k("the fm module has been removed in "
                       "Python 3.0", 2) < 0)
        return;

    Py_InitModule("fm", fm_methods);
    if (m == NULL)
        return;
    fminit();
}
