@@ -1978,6 +1978,105 @@ static PyTypeObject Tkapp_Type =
19781978
19791979/**** Tkinter Module ****/
19801980
1981+ typedef struct {
1982+ PyObject * tuple ;
1983+ int size ; /* current size */
1984+ int maxsize ; /* allocated size */
1985+ } FlattenContext ;
1986+
1987+ static int
1988+ _bump (FlattenContext * context , int size )
1989+ {
1990+ /* expand tuple to hold (at least) size new items. return true if
1991+ successful, false if an exception was raised*/
1992+
1993+ int maxsize = context -> maxsize * 2 ;
1994+
1995+ if (maxsize < context -> size + size )
1996+ maxsize = context -> size + size ;
1997+
1998+ context -> maxsize = maxsize ;
1999+
2000+ return _PyTuple_Resize (& context -> tuple , maxsize , 0 ) >= 0 ;
2001+ }
2002+
2003+ static int
2004+ _flatten1 (FlattenContext * context , PyObject * item )
2005+ {
2006+ /* add tuple or list to argument tuple (recursively) */
2007+
2008+ int i , size ;
2009+
2010+ if (PyList_Check (item )) {
2011+ size = PyList_GET_SIZE (item );
2012+ /* preallocate (assume no nesting) */
2013+ if (context -> size + size > context -> maxsize && !_bump (context , size ))
2014+ return 0 ;
2015+ /* copy items to output tuple */
2016+ for (i = 0 ; i < size ; i ++ ) {
2017+ PyObject * o = PyList_GET_ITEM (item , i );
2018+ if (PyList_Check (o ) || PyTuple_Check (o )) {
2019+ if (!_flatten1 (context , o ))
2020+ return 0 ;
2021+ } else if (o != Py_None ) {
2022+ if (context -> size + 1 > context -> maxsize && !_bump (context , 1 ))
2023+ return 0 ;
2024+ Py_INCREF (o );
2025+ PyTuple_SET_ITEM (context -> tuple , context -> size ++ , o );
2026+ }
2027+ }
2028+ } else if (PyTuple_Check (item )) {
2029+ /* same, for tuples */
2030+ size = PyTuple_GET_SIZE (item );
2031+ if (context -> size + size > context -> maxsize && !_bump (context , size ))
2032+ return 0 ;
2033+ for (i = 0 ; i < size ; i ++ ) {
2034+ PyObject * o = PyTuple_GET_ITEM (item , i );
2035+ if (PyList_Check (o ) || PyTuple_Check (o )) {
2036+ if (!_flatten1 (context , o ))
2037+ return 0 ;
2038+ } else if (o != Py_None ) {
2039+ if (context -> size + 1 > context -> maxsize && !_bump (context , 1 ))
2040+ return 0 ;
2041+ Py_INCREF (o );
2042+ PyTuple_SET_ITEM (context -> tuple , context -> size ++ , o );
2043+ }
2044+ }
2045+ } else {
2046+ PyErr_SetString (PyExc_TypeError , "argument must be sequence" );
2047+ return 0 ;
2048+ }
2049+ return 1 ;
2050+ }
2051+
2052+ static PyObject *
2053+ Tkinter_Flatten (PyObject * self , PyObject * args )
2054+ {
2055+ FlattenContext context ;
2056+ PyObject * item ;
2057+
2058+ if (!PyArg_ParseTuple (args , "O:_flatten" , & item ))
2059+ return NULL ;
2060+
2061+ context .maxsize = PySequence_Length (item );
2062+ if (context .maxsize <= 0 )
2063+ return PyTuple_New (0 );
2064+
2065+ context .tuple = PyTuple_New (context .maxsize );
2066+ if (!context .tuple )
2067+ return NULL ;
2068+
2069+ context .size = 0 ;
2070+
2071+ if (!_flatten1 (& context , item ))
2072+ return NULL ;
2073+
2074+ if (_PyTuple_Resize (& context .tuple , context .size , 0 ))
2075+ return NULL ;
2076+
2077+ return context .tuple ;
2078+ }
2079+
19812080static PyObject *
19822081Tkinter_Create (self , args )
19832082 PyObject * self ;
@@ -2006,6 +2105,7 @@ Tkinter_Create(self, args)
20062105
20072106static PyMethodDef moduleMethods [] =
20082107{
2108+ {"_flatten" , Tkinter_Flatten , 1 },
20092109 {"create" , Tkinter_Create , 1 },
20102110#ifdef HAVE_CREATEFILEHANDLER
20112111 {"createfilehandler" , Tkapp_CreateFileHandler , 1 },
0 commit comments