diff --git a/release/scripts/textplugin_templates.py b/release/scripts/textplugin_templates.py new file mode 100644 index 00000000000..e0e7746abca --- /dev/null +++ b/release/scripts/textplugin_templates.py @@ -0,0 +1,114 @@ +#!BPY +""" +Name: 'Templates' +Blender: 246 +Group: 'TextPlugin' +Shortcut: 'Tab' +Tooltip: 'Completes templates based on the text preceding the cursor' +""" + +# Only run if we have the required modules +try: + import bpy + from BPyTextPlugin import * + from Blender import Text +except ImportError: + OK = False +else: + OK = True + +templates = { + 'ie': + 'if ${1:cond}:\n' + '\t${2}\n' + 'else:\n' + '\t${3}\n', + 'iei': + 'if ${1:cond}:\n' + '\t${2}\n' + 'elif:\n' + '\t${3}\n' + 'else:\n' + '\t${4}\n', + 'def': + 'def ${1:name}(${2:params}):\n' + '\t"""(${2}) - ${3:comment}"""\n' + '\t${4}', + 'cls': + 'class ${1:name}(${2:parent}):\n' + '\t"""${3:docs}"""\n' + '\t\n' + '\tdef __init__(self, ${4:params}):\n' + '\t\t"""Creates a new ${1}"""\n' + '\t\t${5}' +} + +def main(): + txt = bpy.data.texts.active + if not txt: + return + + line, c = current_line(txt) + indent=0 + while indent0)"}, {"set", ( PyCFunction ) Text_set, METH_VARARGS, "(name, val) - Set attribute 'name' to value 'val'"}, {"asLines", ( PyCFunction ) Text_asLines, METH_NOARGS, @@ -136,6 +142,12 @@ static PyMethodDef BPy_Text_methods[] = { "() - Return cursor position as (row, col) tuple"}, {"setCursorPos", ( PyCFunction ) Text_setCursorPos, METH_VARARGS, "(row, col) - Set the cursor position to (row, col)"}, + {"getSelectPos", ( PyCFunction ) Text_getSelectPos, METH_NOARGS, + "() - Return the selection cursor position as (row, col) tuple"}, + {"setSelectPos", ( PyCFunction ) Text_setSelectPos, METH_VARARGS, + "(row, col) - Set the selection cursor position to (row, col)"}, + {"markSelection", ( PyCFunction ) Text_markSelection, METH_VARARGS, + "(group, (r, g, b), flags) - Places a marker over the current selection. Group: number > 0, flags: TMARK_TEMP, TMARK_EDITALL, etc."}, {"suggest", ( PyCFunction ) Text_suggest, METH_VARARGS, "(list, prefix='') - Presents a list of suggestions. List is of strings, or tuples. Tuples must be of the form (name, type) where type is one of 'm', 'v', 'f', 'k' for module, variable, function and keyword respectively or '?' for other types"}, {"showDocs", ( PyCFunction ) Text_showDocs, METH_VARARGS, @@ -327,7 +339,7 @@ static PyObject *M_Text_unlink( PyObject * self, PyObject * args ) /*****************************************************************************/ PyObject *Text_Init( void ) { - PyObject *submodule; + PyObject *submodule, *dict; if( PyType_Ready( &Text_Type ) < 0 ) return NULL; @@ -335,6 +347,19 @@ PyObject *Text_Init( void ) submodule = Py_InitModule3( "Blender.Text", M_Text_methods, M_Text_doc ); + dict = PyModule_GetDict( submodule ); + +#define EXPP_ADDCONST(x) \ + EXPP_dict_set_item_str(dict, #x, PyInt_FromLong(x)) + + /* So, for example: + * EXPP_ADDCONST(LEFTMOUSE) becomes + * EXPP_dict_set_item_str(dict, "LEFTMOUSE", PyInt_FromLong(LEFTMOUSE)) + */ + + EXPP_ADDCONST( TMARK_TEMP ); + EXPP_ADDCONST( TMARK_EDITALL ); + return ( submodule ); } @@ -483,6 +508,33 @@ static PyObject *Text_insert( BPy_Text * self, PyObject * value ) Py_RETURN_NONE; } +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 ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected non-zero int argument" ); + + oldstate = txt_get_undostate( ); + while (num<0) { + txt_backspace_char(self->text); + num++; + } + while (num>0) { + txt_delete_char(self->text); + num--; + } + txt_set_undostate( oldstate ); + + Py_RETURN_NONE; +} + static PyObject *Text_set( BPy_Text * self, PyObject * args ) { int ival; @@ -549,7 +601,6 @@ static PyObject *Text_getCursorPos( BPy_Text * self ) static PyObject *Text_setCursorPos( BPy_Text * self, PyObject * args ) { int row, col; - int oldstate; SpaceText *st; if (!self->text) @@ -559,12 +610,10 @@ static PyObject *Text_setCursorPos( BPy_Text * self, PyObject * args ) if (!PyArg_ParseTuple(args, "ii", &row, &col)) return EXPP_ReturnPyObjError(PyExc_TypeError, "expected two ints as arguments."); + if (row<0) row=0; if (col<0) col=0; - if (col>self->text->curl->len) col=self->text->curl->len; - oldstate = txt_get_undostate(); txt_move_to(self->text, row, col, 0); - txt_set_undostate(oldstate); if (curarea->spacetype == SPACE_TEXT && (st=curarea->spacedata.first)) pop_space_text(st); @@ -572,6 +621,76 @@ static PyObject *Text_setCursorPos( BPy_Text * self, PyObject * args ) Py_RETURN_NONE; } +static PyObject *Text_getSelectPos( BPy_Text * self ) +{ + Text *text; + TextLine *linep; + int row, col; + + 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++; + col= text->selc; + + return Py_BuildValue( "ii", row, col ); +} + +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"); + + if (!PyArg_ParseTuple(args, "ii", &row, &col)) + return EXPP_ReturnPyObjError(PyExc_TypeError, + "expected two ints as arguments."); + if (row<0) row=0; + if (col<0) col=0; + + txt_move_to(self->text, row, col, 1); + + if (curarea->spacetype == SPACE_TEXT && (st=curarea->spacedata.first)) + pop_space_text(st); + + Py_RETURN_NONE; +} + +static PyObject *Text_markSelection( BPy_Text * self, PyObject * args ) +{ + int group = 0, flags = 0,r, g, b; + Text *text; + char clr[4]; + + 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, + "expected int, 3-tuple of ints and int as arguments."); + + if (text->curl != text->sell) + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "Cannot mark multi-line selection."); + + clr[0] = (char) (r&0xFF); + clr[1] = (char) (g&0xFF); + clr[2] = (char) (b&0xFF); + clr[3] = 255; + + txt_add_marker(text, text->curl, text->curc, text->selc, clr, ((group+2)<<16)|flags); + + Py_RETURN_NONE; +} + static PyObject *Text_suggest( BPy_Text * self, PyObject * args ) { PyObject *item = NULL, *tup1 = NULL, *tup2 = NULL; diff --git a/source/blender/src/drawtext.c b/source/blender/src/drawtext.c index 951e71e1f81..5a96a2548d7 100644 --- a/source/blender/src/drawtext.c +++ b/source/blender/src/drawtext.c @@ -814,17 +814,17 @@ static void draw_markers(SpaceText *st) { if (y1==y2) { y -= y1*st->lheight; glBegin(GL_LINE_LOOP); - glVertex2i(x+x2*spacetext_get_fontwidth(st), y); - glVertex2i(x+x1*spacetext_get_fontwidth(st)-1, y); - glVertex2i(x+x1*spacetext_get_fontwidth(st)-1, y-st->lheight); - glVertex2i(x+x2*spacetext_get_fontwidth(st), y-st->lheight); + glVertex2i(x+x2*spacetext_get_fontwidth(st)+1, y); + glVertex2i(x+x1*spacetext_get_fontwidth(st)-2, y); + glVertex2i(x+x1*spacetext_get_fontwidth(st)-2, y-st->lheight); + glVertex2i(x+x2*spacetext_get_fontwidth(st)+1, y-st->lheight); glEnd(); } else { y -= y1*st->lheight; glBegin(GL_LINE_STRIP); glVertex2i(curarea->winx, y); - glVertex2i(x+x1*spacetext_get_fontwidth(st)-1, y); - glVertex2i(x+x1*spacetext_get_fontwidth(st)-1, y-st->lheight); + glVertex2i(x+x1*spacetext_get_fontwidth(st)-2, y); + glVertex2i(x+x1*spacetext_get_fontwidth(st)-2, y-st->lheight); glVertex2i(curarea->winx, y-st->lheight); glEnd(); y-=st->lheight; @@ -839,8 +839,8 @@ static void draw_markers(SpaceText *st) { } glBegin(GL_LINE_STRIP); glVertex2i(x, y); - glVertex2i(x+x2*spacetext_get_fontwidth(st), y); - glVertex2i(x+x2*spacetext_get_fontwidth(st), y-st->lheight); + glVertex2i(x+x2*spacetext_get_fontwidth(st)+1, y); + glVertex2i(x+x2*spacetext_get_fontwidth(st)+1, y-st->lheight); glVertex2i(x, y-st->lheight); glEnd(); } @@ -2329,10 +2329,23 @@ static short do_markers(SpaceText *st, char ascii, unsigned short evnt, short va } break; case TABKEY: - marker= (G.qual & LR_SHIFTKEY) ? txt_prev_marker(text, marker) : txt_next_marker(text, marker); - txt_move_to(text, marker->lineno, marker->start, 0); - txt_move_to(text, marker->lineno, marker->end, 1); - pop_space_text(st); + if (G.qual & LR_SHIFTKEY) { + nxt= marker->prev; + if (!nxt) nxt= text->markers.last; + } else { + nxt= marker->next; + if (!nxt) nxt= text->markers.first; + } + if (marker->flags & TMARK_TEMP) { + if (nxt==marker) nxt= NULL; + BLI_freelinkN(&text->markers, marker); + } + mrk= nxt; + if (mrk) { + txt_move_to(text, mrk->lineno, mrk->start, 0); + txt_move_to(text, mrk->lineno, mrk->end, 1); + pop_space_text(st); + } swallow= 1; draw= 1; break; @@ -2707,7 +2720,7 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } break; /* BREAK S */ case UKEY: - txt_print_undo(text); //debug buffer in console + //txt_print_undo(text); //debug buffer in console if (G.qual == (LR_ALTKEY|LR_SHIFTKEY)) { txt_do_redo(text); do_draw= 1; @@ -2785,17 +2798,21 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) error_libdata(); break; } else { - if (G.qual & LR_SHIFTKEY) { - if (txt_has_sel(text)) { + if (txt_has_sel(text)) { + if (G.qual & LR_SHIFTKEY) { txt_order_cursors(text); unindent(text); if (st->showsyntax) txt_format_text(st); - } - } else { - if ( txt_has_sel(text)) { + } else { txt_order_cursors(text); indent(text); if (st->showsyntax) txt_format_text(st); + } + } else { + TextMarker *mrk= txt_find_marker_region(text, text->curl, 0, text->curl->len, 0); + if (mrk) { + txt_move_to(text, mrk->lineno, mrk->start, 0); + txt_move_to(text, mrk->lineno, mrk->end, 1); } else { txt_add_char(text, '\t'); if (st->showsyntax) txt_format_line(st, text->curl, 1);