diff src/if_py_both.h @ 4401:cfd76908da25 v7.3.949

updated for version 7.3.949 Problem: Python: no easy access to tabpages. Solution: Add vim.tabpages and vim.current.tabpage. (ZyX)
author Bram Moolenaar <bram@vim.org>
date Wed, 15 May 2013 15:12:29 +0200
parents a6f0544df95e
children d4816e7c3328
line wrap: on
line diff
--- a/src/if_py_both.h
+++ b/src/if_py_both.h
@@ -27,6 +27,7 @@ typedef int Py_ssize_t;  /* Python 2.4 a
 
 #define INVALID_BUFFER_VALUE ((buf_T *)(-1))
 #define INVALID_WINDOW_VALUE ((win_T *)(-1))
+#define INVALID_TABPAGE_VALUE ((tabpage_T *)(-1))
 
 static int ConvertFromPyObject(PyObject *, typval_T *);
 static int _ConvertFromPyObject(PyObject *, typval_T *, PyObject *);
@@ -1579,6 +1580,155 @@ static PyMappingMethods OptionsAsMapping
     (objobjargproc) OptionsAssItem,
 };
 
+/* Tabpage object
+ */
+
+typedef struct
+{
+    PyObject_HEAD
+    tabpage_T	*tab;
+} TabPageObject;
+
+static PyObject *WinListNew(TabPageObject *tabObject);
+
+static PyTypeObject TabPageType;
+
+    static int
+CheckTabPage(TabPageObject *this)
+{
+    if (this->tab == INVALID_TABPAGE_VALUE)
+    {
+	PyErr_SetVim(_("attempt to refer to deleted tab page"));
+	return -1;
+    }
+
+    return 0;
+}
+
+    static PyObject *
+TabPageNew(tabpage_T *tab)
+{
+    TabPageObject *self;
+
+    if (TAB_PYTHON_REF(tab))
+    {
+	self = TAB_PYTHON_REF(tab);
+	Py_INCREF(self);
+    }
+    else
+    {
+	self = PyObject_NEW(TabPageObject, &TabPageType);
+	if (self == NULL)
+	    return NULL;
+	self->tab = tab;
+	TAB_PYTHON_REF(tab) = self;
+    }
+
+    return (PyObject *)(self);
+}
+
+    static void
+TabPageDestructor(PyObject *self)
+{
+    TabPageObject *this = (TabPageObject *)(self);
+
+    if (this->tab && this->tab != INVALID_TABPAGE_VALUE)
+	TAB_PYTHON_REF(this->tab) = NULL;
+
+    DESTRUCTOR_FINISH(self);
+}
+
+    static PyObject *
+TabPageAttr(TabPageObject *this, char *name)
+{
+    if (strcmp(name, "windows") == 0)
+	return WinListNew(this);
+    else if (strcmp(name, "number") == 0)
+	return PyLong_FromLong((long) get_tab_number(this->tab));
+    else if (strcmp(name, "vars") == 0)
+	return DictionaryNew(this->tab->tp_vars);
+    else if (strcmp(name, "window") == 0)
+    {
+	/* For current tab window.c does not bother to set or update tp_curwin
+	 */
+	if (this->tab == curtab)
+	    return WindowNew(curwin);
+	else
+	    return WindowNew(this->tab->tp_curwin);
+    }
+    return NULL;
+}
+
+    static PyObject *
+TabPageRepr(PyObject *self)
+{
+    static char repr[100];
+    TabPageObject *this = (TabPageObject *)(self);
+
+    if (this->tab == INVALID_TABPAGE_VALUE)
+    {
+	vim_snprintf(repr, 100, _("<tabpage object (deleted) at %p>"), (self));
+	return PyString_FromString(repr);
+    }
+    else
+    {
+	int	t = get_tab_number(this->tab);
+
+	if (t == 0)
+	    vim_snprintf(repr, 100, _("<tabpage object (unknown) at %p>"),
+								      (self));
+	else
+	    vim_snprintf(repr, 100, _("<tabpage %d>"), t - 1);
+
+	return PyString_FromString(repr);
+    }
+}
+
+static struct PyMethodDef TabPageMethods[] = {
+    /* name,	    function,		calling,    documentation */
+    { NULL,	    NULL,		0,	    NULL }
+};
+
+/*
+ * Window list object
+ */
+
+static PyTypeObject TabListType;
+static PySequenceMethods TabListAsSeq;
+
+typedef struct
+{
+    PyObject_HEAD
+} TabListObject;
+
+    static PyInt
+TabListLength(PyObject *self UNUSED)
+{
+    tabpage_T	*tp = first_tabpage;
+    PyInt	n = 0;
+
+    while (tp != NULL)
+    {
+	++n;
+	tp = tp->tp_next;
+    }
+
+    return n;
+}
+
+    static PyObject *
+TabListItem(PyObject *self UNUSED, PyInt n)
+{
+    tabpage_T	*tp;
+
+    for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, --n)
+	if (n == 0)
+	    return TabPageNew(tp);
+
+    PyErr_SetString(PyExc_IndexError, _("no such tab page"));
+    return NULL;
+}
+
 /* Window object
  */
 
@@ -1588,8 +1738,6 @@ typedef struct
     win_T	*win;
 } WindowObject;
 
-static int WindowSetattr(PyObject *, char *, PyObject *);
-static PyObject *WindowRepr(PyObject *);
 static PyTypeObject WindowType;
 
     static int
@@ -1681,7 +1829,7 @@ WindowAttr(WindowObject *this, char *nam
 	return OptionsNew(SREQ_WIN, this->win, (checkfun) CheckWindow,
 			(PyObject *) this);
     else if (strcmp(name, "number") == 0)
-	return PyLong_FromLong((long) get_win_number(this->win));
+	return PyLong_FromLong((long) get_win_number(this->win, firstwin));
     else if (strcmp(name,"__members__") == 0)
 	return Py_BuildValue("[ssssssss]", "buffer", "cursor", "height", "vars",
 		"options", "number", "row", "col");
@@ -1797,7 +1945,7 @@ WindowRepr(PyObject *self)
     }
     else
     {
-	int	w = get_win_number(this->win);
+	int	w = get_win_number(this->win, firstwin);
 
 	if (w == 0)
 	    vim_snprintf(repr, 100, _("<window object (unknown) at %p>"),
@@ -1824,14 +1972,59 @@ static PySequenceMethods WinListAsSeq;
 typedef struct
 {
     PyObject_HEAD
+    TabPageObject	*tabObject;
 } WinListObject;
 
+    static PyObject *
+WinListNew(TabPageObject *tabObject)
+{
+    WinListObject	*self;
+
+    self = PyObject_NEW(WinListObject, &WinListType);
+    self->tabObject = tabObject;
+    Py_INCREF(tabObject);
+
+    return (PyObject *)(self);
+}
+
+    static void
+WinListDestructor(PyObject *self)
+{
+    TabPageObject	*tabObject = ((WinListObject *)(self))->tabObject;
+
+    if (tabObject)
+	Py_DECREF((PyObject *)(tabObject));
+
+    DESTRUCTOR_FINISH(self);
+}
+
+    static win_T *
+get_firstwin(WinListObject *this)
+{
+    if (this->tabObject)
+    {
+	if (CheckTabPage(this->tabObject))
+	    return NULL;
+	/* For current tab window.c does not bother to set or update tp_firstwin
+	 */
+	else if (this->tabObject->tab == curtab)
+	    return firstwin;
+	else
+	    return this->tabObject->tab->tp_firstwin;
+    }
+    else
+	return firstwin;
+}
+
     static PyInt
-WinListLength(PyObject *self UNUSED)
+WinListLength(PyObject *self)
 {
-    win_T	*w = firstwin;
+    win_T	*w;
     PyInt	n = 0;
 
+    if (!(w = get_firstwin((WinListObject *)(self))))
+	return -1;
+
     while (w != NULL)
     {
 	++n;
@@ -1842,11 +2035,14 @@ WinListLength(PyObject *self UNUSED)
 }
 
     static PyObject *
-WinListItem(PyObject *self UNUSED, PyInt n)
+WinListItem(PyObject *self, PyInt n)
 {
     win_T *w;
 
-    for (w = firstwin; w != NULL; w = W_NEXT(w), --n)
+    if (!(w = get_firstwin((WinListObject *)(self))))
+	return NULL;
+
+    for (; w != NULL; w = W_NEXT(w), --n)
 	if (n == 0)
 	    return WindowNew(w);
 
@@ -3018,12 +3214,15 @@ CurrentGetattr(PyObject *self UNUSED, ch
 	return (PyObject *)BufferNew(curbuf);
     else if (strcmp(name, "window") == 0)
 	return (PyObject *)WindowNew(curwin);
+    else if (strcmp(name, "tabpage") == 0)
+	return (PyObject *)TabPageNew(curtab);
     else if (strcmp(name, "line") == 0)
 	return GetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum);
     else if (strcmp(name, "range") == 0)
 	return RangeNew(curbuf, RangeStart, RangeEnd);
     else if (strcmp(name,"__members__") == 0)
-	return Py_BuildValue("[ssss]", "buffer", "window", "line", "range");
+	return Py_BuildValue("[sssss]", "buffer", "window", "line", "range",
+		"tabpage");
     else
     {
 	PyErr_SetString(PyExc_AttributeError, name);
@@ -3568,6 +3767,23 @@ init_structs(void)
     WindowType.tp_setattr = WindowSetattr;
 #endif
 
+    vim_memset(&TabPageType, 0, sizeof(TabPageType));
+    TabPageType.tp_name = "vim.tabpage";
+    TabPageType.tp_basicsize = sizeof(TabPageObject);
+    TabPageType.tp_dealloc = TabPageDestructor;
+    TabPageType.tp_repr = TabPageRepr;
+    TabPageType.tp_flags = Py_TPFLAGS_DEFAULT;
+    TabPageType.tp_doc = "vim tab page object";
+    TabPageType.tp_methods = TabPageMethods;
+#if PY_MAJOR_VERSION >= 3
+    TabPageType.tp_getattro = TabPageGetattro;
+    TabPageType.tp_alloc = call_PyType_GenericAlloc;
+    TabPageType.tp_new = call_PyType_GenericNew;
+    TabPageType.tp_free = call_PyObject_Free;
+#else
+    TabPageType.tp_getattr = TabPageGetattr;
+#endif
+
     vim_memset(&BufMapType, 0, sizeof(BufMapType));
     BufMapType.tp_name = "vim.bufferlist";
     BufMapType.tp_basicsize = sizeof(BufMapObject);
@@ -3582,6 +3798,14 @@ init_structs(void)
     WinListType.tp_as_sequence = &WinListAsSeq;
     WinListType.tp_flags = Py_TPFLAGS_DEFAULT;
     WinListType.tp_doc = "vim window list";
+    WinListType.tp_dealloc = WinListDestructor;
+
+    vim_memset(&TabListType, 0, sizeof(TabListType));
+    TabListType.tp_name = "vim.tabpagelist";
+    TabListType.tp_basicsize = sizeof(TabListType);
+    TabListType.tp_as_sequence = &TabListAsSeq;
+    TabListType.tp_flags = Py_TPFLAGS_DEFAULT;
+    TabListType.tp_doc = "vim tab page list";
 
     vim_memset(&RangeType, 0, sizeof(RangeType));
     RangeType.tp_name = "vim.range";