Text.c
authorCampbell Barton <ideasman42@gmail.com>
Sat, 20 Sep 2008 04:37:10 +0000 (04:37 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Sat, 20 Sep 2008 04:37:10 +0000 (04:37 +0000)
 - calling Text_reset within C/Api funcs didnt decref the Py_None Text_reset returned.
 - Text_delete wasnt checking if the input was an int.
 - a number of functions wernt checking if the text was removed.
console.py
 - added clear output
 - command history leaves empty command before wrapping
 - add imports as dummy user input so commands written to a text file will run.
 - faster writing of output to a textblock.

release/scripts/console.py
source/blender/python/api2_2x/Text.c

index 9a18c724d4710ca1bf5f61bbc6ba7d07f619c2a9..cc1788ce24ce99b83d870c60a2eb3ecade0b9c92 100644 (file)
@@ -67,6 +67,8 @@ __FONT_SIZE__ = 2 # index for the list above, normal default.
 global __CONSOLE_LINE_OFFSET__
 __CONSOLE_LINE_OFFSET__ = 0
 
+cmdBuffer = [] # dosnt need to be global
+
 '''
 # Generic Blender functions
 def getActScriptWinRect():
@@ -159,19 +161,13 @@ def include(filename):
        return compile(filedata, filename, 'exec')
 
 # Writes command line data to a blender text file.
-def writeCmdData(cmdLineList, type):
-       if type == 3:
-               typeList = [0,1,2, 3, None] # all
-       else:
-               typeList = [type] # so we can use athe lists 'in' methiod
-       
+def writeCmdData(type):
        newText = Text.New('command_output.py', 1)
-       for myCmd in cmdLineList:
-               if myCmd.type in typeList: # user input
-                       newText.write('%s\n' % myCmd.cmd)
+       if type == 3:   newText.write('\n'.join( [ myCmd.cmd for myCmd in cmdBuffer ] ))
+       else:                   newText.write('\n'.join( [ myCmd.cmd for myCmd in cmdBuffer if myCmd.type is type] ))
        Draw.PupMenu('%s written' % newText.name)
 
-def insertCmdData(cmdBuffer):
+def insertCmdData():
        texts = list(bpy.data.texts)
        textNames = [tex.name for tex in texts]
        if textNames:
@@ -337,7 +333,6 @@ def handle_event(evt, val):
        
        # Insert Char into the cammand line
        def insCh(ch): # Instert a char
-               global cmdBuffer
                global cursor
                # Later account for a cursor variable
                cmdBuffer[-1].cmd = ('%s%s%s' % ( cmdBuffer[-1].cmd[:cursor], ch, cmdBuffer[-1].cmd[cursor:]))
@@ -346,7 +341,7 @@ def handle_event(evt, val):
        #                        Define Complex Key Actions                            #
        #------------------------------------------------------------------------------#
        def actionEnterKey():
-               global histIndex, cursor, cmdBuffer
+               global histIndex, cursor
                
                def getIndent(string):
                        # Gather white space to add in the previous line
@@ -412,14 +407,20 @@ def handle_event(evt, val):
                        
                        # Clear the output based on __LINE_HISTORY__
                        if len(cmdBuffer) > __LINE_HISTORY__:
-                               cmdBuffer = cmdBuffer[-__LINE_HISTORY__:]
+                               cmdBuffer[:__LINE_HISTORY__] = []
                
                histIndex = cursor = -1 # Reset cursor and history
        
        def actionUpKey():
-               global histIndex, cmdBuffer
+               global histIndex
                if abs(histIndex)+1 >= len(cmdBuffer):
                        histIndex = -1
+                       
+                       # When wrapping allow 1 plank lines
+                       if cmdBuffer[-1].cmd != '':
+                               cmdBuffer[-1].cmd = ''
+                               return
+               
                histIndex_orig = histIndex
                histIndex -= 1
                
@@ -431,9 +432,15 @@ def handle_event(evt, val):
                        cmdBuffer[-1].cmd = cmdBuffer[histIndex].cmd                    
        
        def actionDownKey():
-               global histIndex, cmdBuffer
+               global histIndex
                if histIndex >= -2:
                        histIndex = -len(cmdBuffer)
+                       
+                       # When wrapping allow 1 plank lines
+                       if cmdBuffer[-1].cmd != '':
+                               cmdBuffer[-1].cmd = ''
+                               return
+                       
                histIndex_orig = histIndex
                histIndex += 1
                while   (cmdBuffer[histIndex].type != 0 and histIndex != -2) or \
@@ -446,18 +453,18 @@ def handle_event(evt, val):
        
        def actionRightMouse():
                global __FONT_SIZE__
-               choice = Draw.PupMenu('Console Menu%t|Write Input Data (white)|Write Output Data (blue)|Write Error Data (red)|Write All Text|%l|Insert Blender text|%l|Font Size|%l|Quit')
+               choice = Draw.PupMenu('Console Menu%t|Write Input Data (white)|Write Output Data (blue)|Write Error Data (red)|Write All Text|%l|Insert Blender text|%l|Font Size|%l|Clear Output|Quit')
                
                if choice == 1:
-                       writeCmdData(cmdBuffer, 0) # type 0 user
+                       writeCmdData(0) # type 0 user
                elif choice == 2:
-                       writeCmdData(cmdBuffer, 1) # type 1 user output
+                       writeCmdData(1) # type 1 user output
                elif choice == 3:
-                       writeCmdData(cmdBuffer, 2) # type 2 errors
+                       writeCmdData(2) # type 2 errors
                elif choice == 4:
-                       writeCmdData(cmdBuffer, 3) # All
+                       writeCmdData(3) # All
                elif choice == 6:
-                       insertCmdData(cmdBuffer) # Insert text from Blender and run it.
+                       insertCmdData() # Insert text from Blender and run it.
                elif choice == 8:
                        # Fontsize.
                        font_choice = Draw.PupMenu('Font Size%t|Large|Normal|Small|Tiny')
@@ -471,8 +478,10 @@ def handle_event(evt, val):
                                elif font_choice == 4:
                                        __FONT_SIZE__ = 0
                                Draw.Redraw()
-                               
-               elif choice == 10: # Exit
+               elif choice == 10: # Clear all output
+                       cmdBuffer[:] = [cmd for cmd in cmdBuffer if cmd.type == 0] # keep user input
+                       Draw.Redraw()
+               elif choice == 11: # Exit
                        Draw.Exit()
        
        
@@ -783,7 +792,6 @@ __CONSOLE_VAR_DICT__ = {} # Initialize var dict
 
 
 # Print Startup lines, add __bpydoc__ to the console startup.
-cmdBuffer = []
 for l in __bpydoc__.split('<br>'):
        cmdBuffer.append( cmdLine(l, 1, None) )
        
@@ -827,12 +835,19 @@ def include_console(includeFile):
 
 def standard_imports():
        # Write local to global __CONSOLE_VAR_DICT__ for reuse,
+       
+       exec('%s%s' % ('__CONSOLE_VAR_DICT__["bpy"]=', 'bpy'))
+       exec('%s%s' % ('__CONSOLE_VAR_DICT__["Blender"]=', 'Blender'))
+       
        for ls in (dir(), dir(Blender)):
                for __TMP_VAR_NAME__ in ls:
                        # Execute the local > global coversion.
                        exec('%s%s' % ('__CONSOLE_VAR_DICT__[__TMP_VAR_NAME__]=', __TMP_VAR_NAME__))
        
-       exec('%s%s' % ('__CONSOLE_VAR_DICT__["bpy"]=', 'bpy'))
+       # Add dummy imports to input so output scripts to a text file work as expected
+       cmdBuffer.append(cmdLine('import bpy', 0, 1))
+       cmdBuffer.append(cmdLine('import Blender', 0, 1)) # pretend we have been executed, as we kindof have.
+       cmdBuffer.append(cmdLine('from Blender import *', 0, 1))
 
 if scriptDir and console_autoexec:
        include_console(console_autoexec) # pass the blender module
index 9719daaa3d4c9d288d12b63e1d5e419a1b5ab0cb..c8b96fbd97e739ad89e8c74d3a9749bafc07edad 100644 (file)
 
 #define EXPP_TEXT_MODE_FOLLOW TXT_FOLLOW
 
+/* checks for the group being removed */
+#define TEXT_DEL_CHECK_PY(bpy_text) if (!(bpy_text->text)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "Text has been removed" ) )
+#define TEXT_DEL_CHECK_INT(bpy_text) if (!(bpy_text->text)) return ( EXPP_ReturnIntError( PyExc_RuntimeError, "Text has been removed" ) )
+
 /*****************************************************************************/
 /* Python API function prototypes for the Text module.                       */
 /*****************************************************************************/
@@ -109,6 +113,8 @@ static PyObject *Text_markSelection( BPy_Text * self, PyObject * args );
 static PyObject *Text_suggest( BPy_Text * self, PyObject * args );
 static PyObject *Text_showDocs( BPy_Text * self, PyObject * args );
 
+static void text_reset_internal( BPy_Text * self ); /* internal func */
+
 /*****************************************************************************/
 /* Python BPy_Text methods table:                                            */
 /*****************************************************************************/
@@ -377,8 +383,7 @@ PyObject *Text_CreatePyObject( Text * txt )
                                              "couldn't create BPy_Text PyObject" );
 
        pytxt->text = txt;
-       pytxt->iol = NULL;
-       pytxt->ioc = -1;
+       text_reset_internal(pytxt);
 
        return ( PyObject * ) pytxt;
 }
@@ -388,6 +393,7 @@ PyObject *Text_CreatePyObject( Text * txt )
 /*****************************************************************************/
 static PyObject *Text_getFilename( BPy_Text * self )
 {
+       TEXT_DEL_CHECK_PY(self);
        if( self->text->name )
                return PyString_FromString( self->text->name );
        
@@ -398,7 +404,9 @@ static PyObject *Text_getNLines( BPy_Text * self )
 {                              /* text->nlines isn't updated in Blender (?) */
        int nlines = 0;
        TextLine *line;
-
+       
+       TEXT_DEL_CHECK_PY(self);
+       
        line = self->text->lines.first;
 
        while( line ) {         /* so we have to count them ourselves */
@@ -415,9 +423,7 @@ static PyObject *Text_clear( BPy_Text * self)
 {
        int oldstate;
 
-       if( !self->text )
-               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
-                                             "This object isn't linked to a Blender Text Object" );
+       TEXT_DEL_CHECK_PY(self);
 
        oldstate = txt_get_undostate(  );
        txt_set_undostate( 1 );
@@ -428,11 +434,15 @@ static PyObject *Text_clear( BPy_Text * self)
        Py_RETURN_NONE;
 }
 
-static PyObject *Text_reset( BPy_Text * self )
+static void text_reset_internal( BPy_Text * self )
 {
        self->iol = NULL;
        self->ioc = -1;
+}
 
+static PyObject *Text_reset( BPy_Text * self )
+{
+       text_reset_internal(self);
        Py_RETURN_NONE;
 }
 
@@ -440,9 +450,7 @@ static PyObject *Text_readline( BPy_Text * self )
 {
        PyObject *tmpstr;
        
-       if( !self->text )
-               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
-                                             "This object isn't linked to a Blender Text Object" );
+       TEXT_DEL_CHECK_PY(self);
 
        /* Reset */
        if (!self->iol && self->ioc == -1) {
@@ -476,20 +484,18 @@ static PyObject *Text_write( BPy_Text * self, PyObject * value )
        char *str = PyString_AsString(value);
        int oldstate;
 
-       if( !self->text )
-               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
-                                             "This object isn't linked to a Blender Text Object" );
-
        if( !str )
                return EXPP_ReturnPyObjError( PyExc_TypeError,
                                              "expected string argument" );
 
+       TEXT_DEL_CHECK_PY(self);
+       
        oldstate = txt_get_undostate(  );
        txt_insert_buf( self->text, str );
        txt_move_eof( self->text, 0 );
        txt_set_undostate( oldstate );
 
-       Text_reset( self );
+       text_reset_internal( self );
 
        Py_RETURN_NONE;
 }
@@ -499,19 +505,17 @@ static PyObject *Text_insert( BPy_Text * self, PyObject * value )
        char *str = PyString_AsString(value);
        int oldstate;
 
-       if( !self->text )
-               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
-                                             "This object isn't linked to a Blender Text Object" );
-
        if( !str )
                return EXPP_ReturnPyObjError( PyExc_TypeError,
                                              "expected string argument" );
+       
+       TEXT_DEL_CHECK_PY(self);
 
        oldstate = txt_get_undostate(  );
        txt_insert_buf( self->text, str );
        txt_set_undostate( oldstate );
 
-       Text_reset( self );
+       text_reset_internal( self );
 
        Py_RETURN_NONE;
 }
@@ -521,11 +525,10 @@ static PyObject *Text_delete( BPy_Text * self, PyObject * value )
        int num = PyInt_AsLong(value);
        int oldstate;
 
-       if( !self->text )
-               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
-                                             "This object isn't linked to a Blender Text Object" );
-
-       if( !num )
+       TEXT_DEL_CHECK_PY(self);
+       
+       /* zero num is invalid and -1 is an error value */
+       if( !num || (num==-1 && PyErr_Occurred()))
                return EXPP_ReturnPyObjError( PyExc_TypeError,
                                              "expected non-zero int argument" );
 
@@ -540,7 +543,7 @@ static PyObject *Text_delete( BPy_Text * self, PyObject * value )
        }
        txt_set_undostate( oldstate );
        
-       Text_reset( self );
+       text_reset_internal( self );
 
        Py_RETURN_NONE;
 }
@@ -550,6 +553,8 @@ static PyObject *Text_set( BPy_Text * self, PyObject * args )
        int ival;
        char *attr;
 
+       TEXT_DEL_CHECK_PY(self);
+       
        if( !PyArg_ParseTuple( args, "si", &attr, &ival ) )
                return EXPP_ReturnPyObjError( PyExc_TypeError,
                                              "expected a string and an int as arguments" );
@@ -570,9 +575,7 @@ static PyObject *Text_asLines( BPy_Text * self, PyObject * args )
        PyObject *list, *tmpstr;
        int start=0, end=-1, i;
 
-       if( !self->text )
-               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
-                                             "This object isn't linked to a Blender Text Object" );
+       TEXT_DEL_CHECK_PY(self);
 
        if( !PyArg_ParseTuple( args, "|ii", &start, &end ) )
                        return EXPP_ReturnPyObjError( PyExc_TypeError,
@@ -608,10 +611,9 @@ static PyObject *Text_getCursorPos( BPy_Text * self )
        TextLine *linep;
        int row, col;
 
+       TEXT_DEL_CHECK_PY(self);
+       
        text = self->text;
-       if( !text )
-               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
-                                             "This object isn't linked to a Blender Text Object" );
 
        for (row=0,linep=text->lines.first; linep!=text->curl; linep=linep->next)
                row++;
@@ -625,9 +627,7 @@ static PyObject *Text_setCursorPos( BPy_Text * self, PyObject * args )
        int row, col;
        SpaceText *st;
 
-       if (!self->text)
-               return EXPP_ReturnPyObjError(PyExc_RuntimeError,
-                                             "This object isn't linked to a Blender Text Object");
+       TEXT_DEL_CHECK_PY(self);
 
        if (!PyArg_ParseTuple(args, "ii", &row, &col))
                return EXPP_ReturnPyObjError(PyExc_TypeError,
@@ -649,10 +649,9 @@ static PyObject *Text_getSelectPos( BPy_Text * self )
        TextLine *linep;
        int row, col;
 
+       TEXT_DEL_CHECK_PY(self);
+       
        text = self->text;
-       if( !text )
-               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
-                                             "This object isn't linked to a Blender Text Object" );
 
        for (row=0,linep=text->lines.first; linep!=text->sell; linep=linep->next)
                row++;
@@ -666,9 +665,7 @@ static PyObject *Text_setSelectPos( BPy_Text * self, PyObject * args )
        int row, col;
        SpaceText *st;
 
-       if (!self->text)
-               return EXPP_ReturnPyObjError(PyExc_RuntimeError,
-                                             "This object isn't linked to a Blender Text Object");
+       TEXT_DEL_CHECK_PY(self);
 
        if (!PyArg_ParseTuple(args, "ii", &row, &col))
                return EXPP_ReturnPyObjError(PyExc_TypeError,
@@ -690,10 +687,9 @@ static PyObject *Text_markSelection( BPy_Text * self, PyObject * args )
        Text *text;
        char color[4];
 
+       TEXT_DEL_CHECK_PY(self);
+       
        text = self->text;
-       if (!text)
-               return EXPP_ReturnPyObjError(PyExc_RuntimeError,
-                                             "This object isn't linked to a Blender Text Object");
 
        if (!PyArg_ParseTuple(args, "i(iii)i", &group, &r, &g, &b, &flags))
                return EXPP_ReturnPyObjError(PyExc_TypeError,
@@ -723,9 +719,7 @@ static PyObject *Text_suggest( BPy_Text * self, PyObject * args )
        char *prefix = NULL, *name, type;
        SpaceText *st;
 
-       if (!self->text)
-               return EXPP_ReturnPyObjError(PyExc_RuntimeError,
-                               "This object isn't linked to a Blender Text Object");
+       TEXT_DEL_CHECK_PY(self);
 
        /* Parse args for a list of strings/tuples */
        if (!PyArg_ParseTuple(args, "O!|s", &PyList_Type, &list, &prefix))
@@ -782,10 +776,8 @@ static PyObject *Text_showDocs( BPy_Text * self, PyObject * args )
 {
        char *docs;
        SpaceText *st;
-
-       if (!self->text)
-               return EXPP_ReturnPyObjError(PyExc_RuntimeError,
-                               "This object isn't linked to a Blender Text Object");
+       
+       TEXT_DEL_CHECK_PY(self);
 
        if (!PyArg_ParseTuple(args, "s", &docs))
                return EXPP_ReturnPyObjError( PyExc_TypeError,
@@ -839,6 +831,7 @@ static PyObject *Text_repr( BPy_Text * self )
 /*****************************************************************************/
 static PyObject *Text_getMode(BPy_Text * self)
 {
+       TEXT_DEL_CHECK_PY(self);
        return PyInt_FromLong( self->text->flags );
 }