diff options
author | Nick Samarin <nicks1987@bigmir.net> | 2011-02-16 20:07:18 +0300 |
---|---|---|
committer | Nick Samarin <nicks1987@bigmir.net> | 2011-02-16 20:07:18 +0300 |
commit | c5f6a01dd5998976addd2085470bb73a150579e5 (patch) | |
tree | 42b3345fb3ea2e7607a6d1eec379b8ce23b5ffbc /source/blender/editors/space_text | |
parent | 4cf62f1e7e2bb28b47f79e4bd7c1482ab742ebbd (diff) | |
parent | 9e9e028f059f29d493dc020dda965a9bea8ffd6b (diff) |
synched with trunk at revision 34793
Diffstat (limited to 'source/blender/editors/space_text')
-rw-r--r-- | source/blender/editors/space_text/CMakeLists.txt | 25 | ||||
-rw-r--r-- | source/blender/editors/space_text/Makefile | 55 | ||||
-rw-r--r-- | source/blender/editors/space_text/SConscript | 4 | ||||
-rw-r--r-- | source/blender/editors/space_text/space_text.c | 45 | ||||
-rw-r--r-- | source/blender/editors/space_text/text_draw.c | 685 | ||||
-rw-r--r-- | source/blender/editors/space_text/text_header.c | 57 | ||||
-rw-r--r-- | source/blender/editors/space_text/text_intern.h | 22 | ||||
-rw-r--r-- | source/blender/editors/space_text/text_ops.c | 803 | ||||
-rw-r--r-- | source/blender/editors/space_text/text_python.c | 20 |
9 files changed, 1245 insertions, 471 deletions
diff --git a/source/blender/editors/space_text/CMakeLists.txt b/source/blender/editors/space_text/CMakeLists.txt index eabf508b5f6..8c18630ab7d 100644 --- a/source/blender/editors/space_text/CMakeLists.txt +++ b/source/blender/editors/space_text/CMakeLists.txt @@ -19,9 +19,7 @@ # # ***** END GPL LICENSE BLOCK ***** -FILE(GLOB SRC *.c) - -SET(INC +set(INC ../include ../../blenfont ../../blenkernel @@ -32,10 +30,19 @@ SET(INC ../../../../intern/guardedalloc ) -IF(WITH_PYTHON) - LIST(APPEND INC ${PYTHON_INC} ../../python) -ELSE(WITH_PYTHON) - ADD_DEFINITIONS(-DDISABLE_PYTHON) -ENDIF(WITH_PYTHON) +set(SRC + space_text.c + text_draw.c + text_header.c + text_ops.c + text_python.c + + text_intern.h +) + +if(WITH_PYTHON) + list(APPEND INC ${PYTHON_INCLUDE_DIRS} ../../python) + add_definitions(-DWITH_PYTHON) +endif() -BLENDERLIB(bf_editor_text "${SRC}" "${INC}") +blender_add_lib(bf_editor_text "${SRC}" "${INC}") diff --git a/source/blender/editors/space_text/Makefile b/source/blender/editors/space_text/Makefile deleted file mode 100644 index 8bc12852e18..00000000000 --- a/source/blender/editors/space_text/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -# -# $Id$ -# -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# The Original Code is Copyright (C) 2007 Blender Foundation -# All rights reserved. -# -# The Original Code is: all of this file. -# -# Contributor(s): none yet. -# -# ***** END GPL LICENSE BLOCK ***** -# -# Makes module object directory and bounces make to subdirectories. - -LIBNAME = ed_text -DIR = $(OCGDIR)/blender/$(LIBNAME) - -include nan_compile.mk - -CFLAGS += $(LEVEL_1_C_WARNINGS) - -CPPFLAGS += -I$(NAN_GLEW)/include -CPPFLAGS += -I$(OPENGL_HEADERS) - -# not very neat.... -CPPFLAGS += -I../../windowmanager -CPPFLAGS += -I../../blenloader -CPPFLAGS += -I../../blenkernel -CPPFLAGS += -I../../blenlib -CPPFLAGS += -I../../blenfont -CPPFLAGS += -I../../makesdna -CPPFLAGS += -I../../makesrna -CPPFLAGS += -I../../imbuf -CPPFLAGS += -I../../python -CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include - -# own include - -CPPFLAGS += -I../include diff --git a/source/blender/editors/space_text/SConscript b/source/blender/editors/space_text/SConscript index bd87a799756..6d2816b7834 100644 --- a/source/blender/editors/space_text/SConscript +++ b/source/blender/editors/space_text/SConscript @@ -7,7 +7,7 @@ incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' incs += ' ../../python ../../makesrna ../../blenfont' -if not env['WITH_BF_PYTHON']: - defs.append('DISABLE_PYTHON') +if env['WITH_BF_PYTHON']: + defs.append('WITH_PYTHON') env.BlenderLib ( 'bf_editors_space_text', sources, Split(incs), defs, libtype=['core'], priority=[95] ) diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index 7f7a07f8cf7..75001b9514c 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -37,6 +37,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_rand.h" +#include "BLI_utildefines.h" #include "BKE_context.h" #include "BKE_screen.h" @@ -59,7 +60,7 @@ /* ******************** default callbacks for text space ***************** */ -static SpaceLink *text_new(const bContext *C) +static SpaceLink *text_new(const bContext *UNUSED(C)) { ARegion *ar; SpaceText *stext; @@ -92,11 +93,12 @@ static void text_free(SpaceLink *sl) SpaceText *stext= (SpaceText*) sl; stext->text= NULL; + text_free_caches(stext); } /* spacetype; init callback */ -static void text_init(struct wmWindowManager *wm, ScrArea *sa) +static void text_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa)) { } @@ -104,9 +106,11 @@ static void text_init(struct wmWindowManager *wm, ScrArea *sa) static SpaceLink *text_duplicate(SpaceLink *sl) { SpaceText *stextn= MEM_dupallocN(sl); - + /* clear or remove stuff from old */ - + + stextn->drawcache= NULL; /* space need it's own cache */ + return (SpaceLink *)stextn; } @@ -132,8 +136,11 @@ static void text_listener(ScrArea *sa, wmNotifier *wmn) switch(wmn->action) { case NA_EDITED: - if(st->text) + if(st->text) { + text_drawcache_tag_update(st, 1); text_update_edited(st->text); + } + ED_area_tag_redraw(sa); /* no break -- fall down to tag redraw */ case NA_ADDED: @@ -215,9 +222,21 @@ static void text_keymap(struct wmKeyConfig *keyconf) #ifdef __APPLE__ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", LEFTARROWKEY, KM_PRESS, KM_OSKEY, 0)->ptr, "type", LINE_BEGIN); - RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", RIGHTARROWKEY, KM_PRESS, KM_OSKEY, 0)->ptr, "type", LINE_BEGIN); + RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", RIGHTARROWKEY, KM_PRESS, KM_OSKEY, 0)->ptr, "type", LINE_END); + RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", LEFTARROWKEY, KM_PRESS, KM_ALT, 0)->ptr, "type", PREV_WORD); + RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", RIGHTARROWKEY, KM_PRESS, KM_ALT, 0)->ptr, "type", NEXT_WORD); + RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", UPARROWKEY, KM_PRESS, KM_OSKEY, 0)->ptr, "type", FILE_TOP); + RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", DOWNARROWKEY, KM_PRESS, KM_OSKEY, 0)->ptr, "type", FILE_BOTTOM); + RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_select", LEFTARROWKEY, KM_PRESS, KM_SHIFT|KM_OSKEY, 0)->ptr, "type", LINE_BEGIN); - RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_select", RIGHTARROWKEY, KM_PRESS, KM_SHIFT|KM_OSKEY, 0)->ptr, "type", LINE_BEGIN); + RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_select", RIGHTARROWKEY, KM_PRESS, KM_SHIFT|KM_OSKEY, 0)->ptr, "type", LINE_END); + RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_select", LEFTARROWKEY, KM_PRESS, KM_SHIFT|KM_ALT, 0)->ptr, "type", PREV_WORD); + RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_select", RIGHTARROWKEY, KM_PRESS, KM_SHIFT|KM_ALT, 0)->ptr, "type", NEXT_WORD); + RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_select", UPARROWKEY, KM_PRESS, KM_SHIFT|KM_OSKEY, 0)->ptr, "type", FILE_TOP); + RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_select", DOWNARROWKEY, KM_PRESS, KM_SHIFT|KM_OSKEY, 0)->ptr, "type", FILE_BOTTOM); + + RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_delete", BACKSPACEKEY, KM_PRESS, KM_ALT, 0)->ptr, "type", DEL_PREV_WORD); + WM_keymap_add_item(keymap, "TEXT_OT_save", SKEY, KM_PRESS, KM_ALT|KM_OSKEY, 0); WM_keymap_add_item(keymap, "TEXT_OT_save_as", SKEY, KM_PRESS, KM_ALT|KM_SHIFT|KM_OSKEY, 0); WM_keymap_add_item(keymap, "TEXT_OT_cut", XKEY, KM_PRESS, KM_OSKEY, 0); @@ -311,7 +330,7 @@ static void text_keymap(struct wmKeyConfig *keyconf) RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_delete", BACKSPACEKEY, KM_PRESS, 0, 0)->ptr, "type", DEL_PREV_CHAR); RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_delete", DELKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", DEL_NEXT_WORD); RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_delete", BACKSPACEKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", DEL_PREV_WORD); - + WM_keymap_add_item(keymap, "TEXT_OT_overwrite_toggle", INSERTKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "TEXT_OT_scroll", MIDDLEMOUSE, KM_PRESS, 0, 0); @@ -378,7 +397,7 @@ static void text_main_area_draw(const bContext *C, ARegion *ar) UI_ThemeClearColor(TH_BACK); glClear(GL_COLOR_BUFFER_BIT); - // UI_view2d_view_ortho(C, v2d); + // UI_view2d_view_ortho(v2d); /* data... */ draw_text_main(st, ar); @@ -389,7 +408,7 @@ static void text_main_area_draw(const bContext *C, ARegion *ar) /* scrollers? */ } -static void text_cursor(wmWindow *win, ScrArea *sa, ARegion *ar) +static void text_cursor(wmWindow *win, ScrArea *UNUSED(sa), ARegion *UNUSED(ar)) { WM_cursor_set(win, BC_TEXTEDITCURSOR); } @@ -398,10 +417,10 @@ static void text_cursor(wmWindow *win, ScrArea *sa, ARegion *ar) /* ************* dropboxes ************* */ -static int text_drop_poll(bContext *C, wmDrag *drag, wmEvent *event) +static int text_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event)) { if(drag->type==WM_DRAG_PATH) - if(ELEM(drag->icon, 0, ICON_FILE_BLANK)) /* rule might not work? */ + if(ELEM(drag->icon, ICON_FILE_SCRIPT, ICON_FILE_BLANK)) /* rule might not work? */ return 1; return 0; } @@ -427,7 +446,7 @@ static void text_dropboxes(void) /****************** header region ******************/ /* add handlers, stuff you only do once or on area/region changes */ -static void text_header_area_init(wmWindowManager *wm, ARegion *ar) +static void text_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar) { ED_region_header_init(ar); } diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c index 62274fc664a..6f9ad138bac 100644 --- a/source/blender/editors/space_text/text_draw.c +++ b/source/blender/editors/space_text/text_draw.c @@ -10,7 +10,6 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License @@ -37,6 +36,7 @@ #include "BLF_api.h" #include "BLI_blenlib.h" +#include "BLI_utildefines.h" #include "DNA_text_types.h" #include "DNA_space_types.h" @@ -46,7 +46,7 @@ #include "BKE_context.h" #include "BKE_suggestions.h" #include "BKE_text.h" -#include "BKE_utildefines.h" + #include "BIF_gl.h" @@ -57,25 +57,22 @@ #include "text_intern.h" /******************** text font drawing ******************/ -static int mono= -1; // XXX needs proper storage and change all the BLF_* here +// XXX, fixme +#define mono blf_mono_font static void text_font_begin(SpaceText *st) { - if(mono == -1) - mono= BLF_load_mem("monospace", (unsigned char*)datatoc_bmonofont_ttf, datatoc_bmonofont_ttf_size); - - BLF_aspect(mono, 1.0); BLF_size(mono, st->lheight, 72); } -static void text_font_end(SpaceText *st) +static void text_font_end(SpaceText *UNUSED(st)) { } -static int text_font_draw(SpaceText *st, int x, int y, char *str) +static int text_font_draw(SpaceText *UNUSED(st), int x, int y, char *str) { BLF_position(mono, x, y, 0); - BLF_draw(mono, str); + BLF_draw(mono, str, 65535); /* XXX, use real length */ return BLF_width(mono, str); } @@ -83,17 +80,16 @@ static int text_font_draw(SpaceText *st, int x, int y, char *str) static int text_font_draw_character(SpaceText *st, int x, int y, char c) { char str[2]; - str[0]= c; str[1]= '\0'; BLF_position(mono, x, y, 0); - BLF_draw(mono, str); + BLF_draw(mono, str, 1); return st->cwidth; } -int text_font_width(SpaceText *st, char *str) +int text_font_width(SpaceText *UNUSED(st), const char *str) { return BLF_width(mono, str); } @@ -128,7 +124,7 @@ static void flatten_string_append(FlattenString *fs, char c, int accum) fs->pos++; } -int flatten_string(SpaceText *st, FlattenString *fs, char *in) +int flatten_string(SpaceText *st, FlattenString *fs, const char *in) { int r = 0, i = 0; @@ -498,7 +494,7 @@ int wrap_width(SpaceText *st, ARegion *ar) int x, max; x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; - max= (winx-x)/st->cwidth; + max= st->cwidth ? (winx-x)/st->cwidth : 0; return max>8 ? max : 8; } @@ -521,9 +517,22 @@ void wrap_offset(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int * linep= text->lines.first; i= st->top; while(i>0 && linep) { - if(linep == linein) return; /* Line before top */ - linep= linep->next; - i--; + int lines= text_get_visible_lines(st, ar, linep->line); + + /* Line before top */ + if(linep == linein) { + if(lines <= i) + /* no visible part of line */ + return; + } + + if (i-lines<0) { + break; + } else { + linep= linep->next; + (*offl)+= lines-1; + i-= lines; + } } max= wrap_width(st, ar); @@ -548,10 +557,18 @@ void wrap_offset(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int * while(chars--) { if(i-start>=max) { - if(chop && linep==linein && i >= cursin) + if(chop && linep==linein && i >= cursin) { + if (i==cursin) { + (*offl)++; + *offc -= end-start; + } + return; + } + (*offl)++; *offc -= end-start; + start= end; end += max; chop= 1; @@ -570,7 +587,65 @@ void wrap_offset(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int * } } -static int get_char_pos(SpaceText *st, char *line, int cur) +void wrap_offset_in_line(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int *offl, int *offc) +{ + int i, j, start, end, chars, max, chop; + char ch; + + *offl= *offc= 0; + + if(!st->text) return; + if(!st->wordwrap) return; + + max= wrap_width(st, ar); + + start= 0; + end= max; + chop= 1; + *offc= 0; + + for(i=0, j=0; linein->line[j]!='\0'; j++) { + + /* Mimic replacement of tabs */ + ch= linein->line[j]; + if(ch=='\t') { + chars= st->tabnumber-i%st->tabnumber; + if(i<cursin) cursin += chars-1; + ch= ' '; + } + else + chars= 1; + + while(chars--) { + if(i-start>=max) { + if(chop && i >= cursin) { + if (i==cursin) { + (*offl)++; + *offc -= end-start; + } + + return; + } + + (*offl)++; + *offc -= end-start; + + start= end; + end += max; + chop= 1; + } + else if(ch==' ' || ch=='-') { + end = i+1; + chop= 0; + if(i >= cursin) + return; + } + i++; + } + } +} + +int text_get_char_pos(SpaceText *st, const char *line, int cur) { int a=0, i; @@ -583,7 +658,7 @@ static int get_char_pos(SpaceText *st, char *line, int cur) return a; } -static int text_draw_wrapped(SpaceText *st, char *str, int x, int y, int w, char *format) +static int text_draw_wrapped(SpaceText *st, char *str, int x, int y, int w, char *format, int skip) { FlattenString fs; int basex, i, a, len, start, end, max, lines; @@ -599,6 +674,14 @@ static int text_draw_wrapped(SpaceText *st, char *str, int x, int y, int w, char end= max; for(i=0; i<len; i++) { if(i-start >= max) { + /* skip hidden part of line */ + if(skip) { + skip--; + start= end; + end += max; + continue; + } + /* Draw the visible portion of text on the overshot line */ for(a=start; a<end; a++) { if(st->showsyntax && format) format_draw_color(format[a]); @@ -609,6 +692,8 @@ static int text_draw_wrapped(SpaceText *st, char *str, int x, int y, int w, char lines++; start= end; end += max; + + if(y<=0) break; } else if(str[i]==' ' || str[i]=='-') { end = i+1; @@ -616,7 +701,7 @@ static int text_draw_wrapped(SpaceText *st, char *str, int x, int y, int w, char } /* Draw the remaining text */ - for(a=start; a<len; a++) { + for(a=start; a<len && y > 0; a++) { if(st->showsyntax && format) format_draw_color(format[a]); @@ -631,7 +716,7 @@ static int text_draw_wrapped(SpaceText *st, char *str, int x, int y, int w, char static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int draw, int x, int y, char *format) { FlattenString fs; - int r=0, w= 0; + int r=0, w= 0, amount; int *acc; char *in; @@ -647,18 +732,26 @@ static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int dra if(draw) { if(st->showsyntax && format) { - int amount, a; + int a; format = format+cshift; amount = strlen(in); + if(maxwidth) + amount= MIN2(amount, maxwidth); for(a = 0; a < amount; a++) { format_draw_color(format[a]); x += text_font_draw_character(st, x, y, in[a]); } } - else + else { + amount = strlen(in); + if(maxwidth) + amount= MIN2(amount, maxwidth); + + in[amount]= 0; text_font_draw(st, x, y, in); + } } else { while(w-- && *acc++ < maxwidth) @@ -675,23 +768,313 @@ static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int dra return r+TXT_OFFSET; } +/************************ cache utilities *****************************/ + +typedef struct DrawCache { + int *line_height; + int total_lines, nlines; + + /* this is needed to check cache relevance */ + int winx, wordwrap, showlinenrs, tabnumber; + short lheight; + char cwidth; + char text_id[MAX_ID_NAME]; + + /* for partial lines recalculation */ + short update_flag; + int valid_head, valid_tail; /* amount of unchanged lines */ +} DrawCache; + +static void text_drawcache_init(SpaceText *st) +{ + DrawCache *drawcache= MEM_callocN(sizeof (DrawCache), "text draw cache"); + + drawcache->winx= -1; + drawcache->nlines= BLI_countlist(&st->text->lines); + drawcache->text_id[0]= '\0'; + + st->drawcache= drawcache; +} + +static void text_update_drawcache(SpaceText *st, ARegion *ar) +{ + DrawCache *drawcache; + int full_update= 0, nlines= 0; + Text *txt= st->text; + + if(!st->drawcache) text_drawcache_init(st); + + text_update_character_width(st); + + drawcache= (DrawCache *)st->drawcache; + nlines= drawcache->nlines; + + /* check if full cache update is needed */ + full_update|= drawcache->winx != ar->winx; /* area was resized */ + full_update|= drawcache->wordwrap != st->wordwrap; /* word-wrapping option was toggled */ + full_update|= drawcache->showlinenrs != st->showlinenrs; /* word-wrapping option was toggled */ + full_update|= drawcache->tabnumber != st->tabnumber; /* word-wrapping option was toggled */ + full_update|= drawcache->lheight != st->lheight; /* word-wrapping option was toggled */ + full_update|= drawcache->cwidth != st->cwidth; /* word-wrapping option was toggled */ + full_update|= strncmp(drawcache->text_id, txt->id.name, MAX_ID_NAME); /* text datablock was changed */ + + if(st->wordwrap) { + /* update line heights */ + if(full_update || !drawcache->line_height) { + drawcache->valid_head = 0; + drawcache->valid_tail = 0; + drawcache->update_flag = 1; + } + + if(drawcache->update_flag) { + TextLine *line= st->text->lines.first; + int lineno= 0, size, lines_count; + int *fp= drawcache->line_height, *new_tail, *old_tail; + + nlines= BLI_countlist(&txt->lines); + size= sizeof(int)*nlines; + + if(fp) fp= MEM_reallocN(fp, size); + else fp= MEM_callocN(size, "text drawcache line_height"); + + drawcache->valid_tail= drawcache->valid_head= 0; + old_tail= fp + drawcache->nlines - drawcache->valid_tail; + new_tail= fp + nlines - drawcache->valid_tail; + memmove(new_tail, old_tail, drawcache->valid_tail); + + drawcache->total_lines= 0; + + if(st->showlinenrs) + st->linenrs_tot= (int)floor(log10((float)nlines)) + 1; + + while(line) { + if(drawcache->valid_head) { /* we're inside valid head lines */ + lines_count= fp[lineno]; + drawcache->valid_head--; + } else if (lineno > new_tail - fp) { /* we-re inside valid tail lines */ + lines_count= fp[lineno]; + } else { + lines_count= text_get_visible_lines(st, ar, line->line); + } + + fp[lineno]= lines_count; + + line= line->next; + lineno++; + drawcache->total_lines+= lines_count; + } + + drawcache->line_height= fp; + } + } else { + if(drawcache->line_height) { + MEM_freeN(drawcache->line_height); + drawcache->line_height= NULL; + } + + if(full_update || drawcache->update_flag) { + nlines= BLI_countlist(&txt->lines); + + if(st->showlinenrs) + st->linenrs_tot= (int)floor(log10((float)nlines)) + 1; + } + + drawcache->total_lines= nlines; + } + + drawcache->nlines= nlines; + + /* store settings */ + drawcache->winx = ar->winx; + drawcache->wordwrap = st->wordwrap; + drawcache->lheight = st->lheight; + drawcache->cwidth = st->cwidth; + drawcache->showlinenrs = st->showlinenrs; + drawcache->tabnumber = st->tabnumber; + + strncpy(drawcache->text_id, txt->id.name, MAX_ID_NAME); + + /* clear update flag */ + drawcache->update_flag = 0; + drawcache->valid_head = 0; + drawcache->valid_tail = 0; +} + +void text_drawcache_tag_update(SpaceText *st, int full) +{ + DrawCache *drawcache= (DrawCache *)st->drawcache; + + if(drawcache) { + Text *txt= st->text; + + if(drawcache->update_flag) { + /* happens when tagging update from space listener */ + /* should do nothing to prevent locally tagged cache be fully recalculated */ + return; + } + + if(!full) { + int sellno= BLI_findindex(&txt->lines, txt->sell); + int curlno= BLI_findindex(&txt->lines, txt->curl); + + if(curlno < sellno) { + drawcache->valid_head= curlno; + drawcache->valid_tail= drawcache->nlines - sellno - 1; + } else { + drawcache->valid_head= sellno; + drawcache->valid_tail= drawcache->nlines - curlno - 1; + } + + /* quick cache recalculation is also used in delete operator, + which could merge lines which are adjusent to current selection lines + expand recalculate area to this lines */ + if(drawcache->valid_head>0) drawcache->valid_head--; + if(drawcache->valid_tail>0) drawcache->valid_tail--; + } else { + drawcache->valid_head= 0; + drawcache->valid_tail= 0; + } + + drawcache->update_flag= 1; + } +} + +void text_free_caches(SpaceText *st) +{ + DrawCache *drawcache= (DrawCache *)st->drawcache; + + if(drawcache) { + if(drawcache->line_height) + MEM_freeN(drawcache->line_height); + + MEM_freeN(drawcache); + } +} + +/************************ word-wrap utilities *****************************/ + +/* cache should be updated in caller */ +int text_get_visible_lines_no(SpaceText *st, int lineno) +{ + DrawCache *drawcache= (DrawCache *)st->drawcache; + + return drawcache->line_height[lineno]; +} + +int text_get_visible_lines(SpaceText *st, ARegion *ar, const char *str) +{ + int i, j, start, end, max, lines, chars; + char ch; + + max= wrap_width(st, ar); + lines= 1; + start= 0; + end= max; + for(i= 0, j= 0; str[j] != '\0'; j++) { + /* Mimic replacement of tabs */ + ch= str[j]; + if(ch=='\t') { + chars= st->tabnumber-i%st->tabnumber; + ch= ' '; + } + else chars= 1; + + while(chars--) { + if(i-start >= max) { + lines++; + start= end; + end += max; + } + else if(ch==' ' || ch=='-') { + end= i+1; + } + + i++; + } + } + + return lines; +} + +int text_get_span_wrap(SpaceText *st, ARegion *ar, TextLine *from, TextLine *to) +{ + if(st->wordwrap) { + int ret=0; + TextLine *tmp= from; + + /* Look forwards */ + while (tmp) { + if (tmp == to) return ret; + ret+= text_get_visible_lines(st, ar, tmp->line); + tmp= tmp->next; + } + + return ret; + } else return txt_get_span(from, to); +} + +int text_get_total_lines(SpaceText *st, ARegion *ar) +{ + DrawCache *drawcache; + + text_update_drawcache(st, ar); + drawcache= (DrawCache *)st->drawcache; + + return drawcache->total_lines; +} + +/* Move pointer to first visible line (top) */ +static TextLine *first_visible_line(SpaceText *st, ARegion *ar, int *wrap_top) +{ + Text *text= st->text; + TextLine* pline= text->lines.first; + int i= st->top, lineno= 0; + + text_update_drawcache(st, ar); + + if(wrap_top) *wrap_top= 0; + + if(st->wordwrap) { + while(i>0 && pline) { + int lines= text_get_visible_lines_no(st, lineno); + + if (i-lines<0) { + if(wrap_top) *wrap_top= i; + break; + } else { + pline= pline->next; + i-= lines; + lineno++; + } + } + } else { + for(i=st->top; pline->next && i>0; i--) + pline= pline->next; + } + + return pline; +} + /************************ draw scrollbar *****************************/ -static void calc_text_rcts(SpaceText *st, ARegion *ar, rcti *scroll) +static void calc_text_rcts(SpaceText *st, ARegion *ar, rcti *scroll, rcti *back) { - int lhlstart, lhlend, ltexth; + int lhlstart, lhlend, ltexth, sell_off, curl_off; short barheight, barstart, hlstart, hlend, blank_lines; short pix_available, pix_top_margin, pix_bottom_margin, pix_bardiff; pix_top_margin = 8; pix_bottom_margin = 4; pix_available = ar->winy - pix_top_margin - pix_bottom_margin; - ltexth= txt_get_span(st->text->lines.first, st->text->lines.last); + ltexth= text_get_total_lines(st, ar); blank_lines = st->viewlines / 2; /* nicer code: use scroll rect for entire bar */ - //scroll->xmin= 5; - //scroll->xmax= 17; + back->xmin= ar->winx -18; + back->xmax= ar->winx; + back->ymin= 0; + back->ymax= ar->winy; + scroll->xmin= ar->winx - 17; scroll->xmax= ar->winx - 5; scroll->ymin= 4; @@ -722,10 +1105,10 @@ static void calc_text_rcts(SpaceText *st, ARegion *ar, rcti *scroll) st->pix_per_line= (pix_available > 0)? (float) ltexth/pix_available: 0; if(st->pix_per_line<.1) st->pix_per_line=.1f; - lhlstart = MIN2(txt_get_span(st->text->lines.first, st->text->curl), - txt_get_span(st->text->lines.first, st->text->sell)); - lhlend = MAX2(txt_get_span(st->text->lines.first, st->text->curl), - txt_get_span(st->text->lines.first, st->text->sell)); + curl_off= text_get_span_wrap(st, ar, st->text->lines.first, st->text->curl); + sell_off= text_get_span_wrap(st, ar, st->text->lines.first, st->text->sell); + lhlstart = MIN2(curl_off, sell_off); + lhlend = MAX2(curl_off, sell_off); if(ltexth > 0) { hlstart = (lhlstart * pix_available)/ltexth; @@ -787,19 +1170,23 @@ static void calc_text_rcts(SpaceText *st, ARegion *ar, rcti *scroll) CLAMP(st->txtscroll.ymax, pix_bottom_margin, ar->winy - pix_top_margin); } -static void draw_textscroll(SpaceText *st, ARegion *ar, rcti *scroll) +static void draw_textscroll(SpaceText *st, rcti *scroll, rcti *back) { bTheme *btheme= U.themes.first; uiWidgetColors wcol= btheme->tui.wcol_scroll; - char col[3]; + unsigned char col[4]; float rad; + UI_ThemeColor(TH_BACK); + glRecti(back->xmin, back->ymin, back->xmax, back->ymax); + uiWidgetScrollDraw(&wcol, scroll, &st->txtbar, (st->flags & ST_SCROLL_SELECT)?UI_SCROLL_PRESSED:0); uiSetRoundBox(15); rad= 0.4f*MIN2(st->txtscroll.xmax - st->txtscroll.xmin, st->txtscroll.ymax - st->txtscroll.ymin); UI_GetThemeColor3ubv(TH_HILITE, col); - glColor4ub(col[0], col[1], col[2], 48); + col[3]= 48; + glColor4ubv(col); glEnable(GL_BLEND); uiRoundBox(st->txtscroll.xmin+1, st->txtscroll.ymin, st->txtscroll.xmax-1, st->txtscroll.ymax, rad); glDisable(GL_BLEND); @@ -811,78 +1198,80 @@ static void draw_markers(SpaceText *st, ARegion *ar) { Text *text= st->text; TextMarker *marker, *next; - TextLine *top, *bottom, *line; - int offl, offc, i, cy, x1, x2, y1, y2, x, y; + TextLine *top, *line; + int offl, offc, i, x1, x2, y1, y2, x, y; + int topi, topy; - for(i=st->top, top= text->lines.first; top->next && i>0; i--) - top= top->next; + /* Move pointer to first visible line (top) */ + top= first_visible_line(st, ar, NULL); + topi= BLI_findindex(&text->lines, top); + + topy= txt_get_span(text->lines.first, top); - for(i=st->viewlines-1, bottom=top; bottom->next && i>0; i--) - bottom= bottom->next; - for(marker= text->markers.first; marker; marker= next) { next= marker->next; - for(cy= 0, line= top; line; cy++, line= line->next) { - if(cy+st->top==marker->lineno) { - /* Remove broken markers */ - if(marker->end>line->len || marker->start>marker->end) { - BLI_freelinkN(&text->markers, marker); - break; - } + /* invisible line (before top) */ + if(marker->lineno<topi) continue; - wrap_offset(st, ar, line, marker->start, &offl, &offc); - x1= get_char_pos(st, line->line, marker->start) - st->left + offc; - y1= cy + offl; - wrap_offset(st, ar, line, marker->end, &offl, &offc); - x2= get_char_pos(st, line->line, marker->end) - st->left + offc; - y2= cy + offl; - - glColor3ub(marker->color[0], marker->color[1], marker->color[2]); - x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; - y= ar->winy-3; - - if(y1==y2) { - y -= y1*st->lheight; - glBegin(GL_LINE_LOOP); - glVertex2i(x+x2*st->cwidth+1, y); - glVertex2i(x+x1*st->cwidth-2, y); - glVertex2i(x+x1*st->cwidth-2, y-st->lheight); - glVertex2i(x+x2*st->cwidth+1, y-st->lheight); - glEnd(); - } - else { - y -= y1*st->lheight; - glBegin(GL_LINE_STRIP); - glVertex2i(ar->winx, y); - glVertex2i(x+x1*st->cwidth-2, y); - glVertex2i(x+x1*st->cwidth-2, y-st->lheight); - glVertex2i(ar->winx, y-st->lheight); - glEnd(); - y-=st->lheight; - - for(i=y1+1; i<y2; i++) { - glBegin(GL_LINES); - glVertex2i(x, y); - glVertex2i(ar->winx, y); - glVertex2i(x, y-st->lheight); - glVertex2i(ar->winx, y-st->lheight); - glEnd(); - y-=st->lheight; - } + line= BLI_findlink(&text->lines, marker->lineno); - glBegin(GL_LINE_STRIP); - glVertex2i(x, y); - glVertex2i(x+x2*st->cwidth+1, y); - glVertex2i(x+x2*st->cwidth+1, y-st->lheight); - glVertex2i(x, y-st->lheight); - glEnd(); - } + /* Remove broken markers */ + if(marker->end>line->len || marker->start>marker->end) { + BLI_freelinkN(&text->markers, marker); + continue; + } - break; + wrap_offset(st, ar, line, marker->start, &offl, &offc); + y1 = txt_get_span(top, line) - st->top + offl + topy; + x1 = text_get_char_pos(st, line->line, marker->start) - st->left + offc; + + wrap_offset(st, ar, line, marker->end, &offl, &offc); + y2 = txt_get_span(top, line) - st->top + offl + topy; + x2 = text_get_char_pos(st, line->line, marker->end) - st->left + offc; + + /* invisible part of line (before top, after last visible line) */ + if(y2 < 0 || y1 > st->top+st->viewlines) continue; + + glColor3ubv(marker->color); + x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; + y= ar->winy-3; + + if(y1==y2) { + y -= y1*st->lheight; + glBegin(GL_LINE_LOOP); + glVertex2i(x+x2*st->cwidth+1, y); + glVertex2i(x+x1*st->cwidth-2, y); + glVertex2i(x+x1*st->cwidth-2, y-st->lheight); + glVertex2i(x+x2*st->cwidth+1, y-st->lheight); + glEnd(); + } + else { + y -= y1*st->lheight; + glBegin(GL_LINE_STRIP); + glVertex2i(ar->winx, y); + glVertex2i(x+x1*st->cwidth-2, y); + glVertex2i(x+x1*st->cwidth-2, y-st->lheight); + glVertex2i(ar->winx, y-st->lheight); + glEnd(); + y-=st->lheight; + + for(i=y1+1; i<y2; i++) { + glBegin(GL_LINES); + glVertex2i(x, y); + glVertex2i(ar->winx, y); + glVertex2i(x, y-st->lheight); + glVertex2i(ar->winx, y-st->lheight); + glEnd(); + y-=st->lheight; } - if(line==bottom) break; + glBegin(GL_LINE_STRIP); + glVertex2i(x, y); + glVertex2i(x+x2*st->cwidth+1, y); + glVertex2i(x+x2*st->cwidth+1, y-st->lheight); + glVertex2i(x, y-st->lheight); + glEnd(); } } } @@ -893,7 +1282,7 @@ static void draw_documentation(SpaceText *st, ARegion *ar) { TextLine *tmp; char *docs, buf[DOC_WIDTH+1], *p; - int len, i, br, lines; + int i, br, lines; int boxw, boxh, l, x, y, top; if(!st || !st->text) return; @@ -918,7 +1307,6 @@ static void draw_documentation(SpaceText *st, ARegion *ar) } top= y= ar->winy - st->lheight*l - 2; - len= strlen(docs); boxw= DOC_WIDTH*st->cwidth + 20; boxh= (DOC_HEIGHT+1)*st->lheight; @@ -1033,7 +1421,7 @@ static void draw_suggestion_list(SpaceText *st, ARegion *ar) UI_ThemeColor(TH_SHADE2); glRecti(x+16, y-3, x+16+w, y+st->lheight-3); } - b=1; /* b=1 colour block, text is default. b=0 no block, colour text */ + b=1; /* b=1 color block, text is default. b=0 no block, color text */ switch (item->type) { case 'k': UI_ThemeColor(TH_SYNTAX_B); b=0; break; case 'm': UI_ThemeColor(TH_TEXT); break; @@ -1057,17 +1445,18 @@ static void draw_cursor(SpaceText *st, ARegion *ar) { Text *text= st->text; int vcurl, vcurc, vsell, vselc, hidden=0; - int offl, offc, x, y, w, i; - + int x, y, w, i; + /* Draw the selection */ if(text->curl!=text->sell || text->curc!=text->selc) { + int offl, offc; /* Convert all to view space character coordinates */ wrap_offset(st, ar, text->curl, text->curc, &offl, &offc); vcurl = txt_get_span(text->lines.first, text->curl) - st->top + offl; - vcurc = get_char_pos(st, text->curl->line, text->curc) - st->left + offc; + vcurc = text_get_char_pos(st, text->curl->line, text->curc) - st->left + offc; wrap_offset(st, ar, text->sell, text->selc, &offl, &offc); vsell = txt_get_span(text->lines.first, text->sell) - st->top + offl; - vselc = get_char_pos(st, text->sell->line, text->selc) - st->left + offc; + vselc = text_get_char_pos(st, text->sell->line, text->selc) - st->left + offc; if(vcurc<0) vcurc=0; if(vselc<0) vselc=0, hidden=1; @@ -1104,9 +1493,10 @@ static void draw_cursor(SpaceText *st, ARegion *ar) } } else { + int offl, offc; wrap_offset(st, ar, text->sell, text->selc, &offl, &offc); vsell = txt_get_span(text->lines.first, text->sell) - st->top + offl; - vselc = get_char_pos(st, text->sell->line, text->selc) - st->left + offc; + vselc = text_get_char_pos(st, text->sell->line, text->selc) - st->left + offc; if(vselc<0) { vselc= 0; @@ -1115,17 +1505,30 @@ static void draw_cursor(SpaceText *st, ARegion *ar) } if(st->line_hlight) { - y= ar->winy-2 - vsell*st->lheight; - if(!(y<0 || y > ar->winy)) { /* check we need to draw */ - int x1= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; - int x2= x1 + ar->winx; - y= ar->winy-2 - vsell*st->lheight; - + int x1, x2, y1, y2; + + if(st->wordwrap) { + int visible_lines = text_get_visible_lines(st, ar, text->sell->line); + int offl, offc; + + wrap_offset_in_line(st, ar, text->sell, text->selc, &offl, &offc); + + y1= ar->winy-2 - (vsell-offl)*st->lheight; + y2= y1-st->lheight*visible_lines+1; + } else { + y1= ar->winy-2 - vsell*st->lheight; + y2= y1-st->lheight+1; + } + + if(!(y1<0 || y2 > ar->winy)) { /* check we need to draw */ + x1= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; + x2= x1 + ar->winx; + glColor4ub(255, 255, 255, 32); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - glRecti(x1-4, y, x2, y-st->lheight+1); + glRecti(x1-4, y1, x2, y2); glDisable(GL_BLEND); } } @@ -1138,8 +1541,10 @@ static void draw_cursor(SpaceText *st, ARegion *ar) if(st->overwrite) { char ch= text->sell->line[text->selc]; - if(!ch) ch= ' '; + w= st->cwidth; + if(ch=='\t') w*= st->tabnumber-(vselc+st->left)%st->tabnumber; + UI_ThemeColor(TH_HILITE); glRecti(x, y-st->lheight-1, x+w, y-st->lheight+1); } @@ -1243,7 +1648,7 @@ static void draw_brackets(SpaceText *st, ARegion *ar) /* draw opening bracket */ ch= startl->line[startc]; wrap_offset(st, ar, startl, startc, &offl, &offc); - viewc= get_char_pos(st, startl->line, startc) - st->left + offc; + viewc= text_get_char_pos(st, startl->line, startc) - st->left + offc; if(viewc >= 0){ viewl= txt_get_span(text->lines.first, startl) - st->top + offl; @@ -1255,7 +1660,7 @@ static void draw_brackets(SpaceText *st, ARegion *ar) /* draw closing bracket */ ch= endl->line[endc]; wrap_offset(st, ar, endl, endc, &offl, &offc); - viewc= get_char_pos(st, endl->line, endc) - st->left + offc; + viewc= text_get_char_pos(st, endl->line, endc) - st->left + offc; if(viewc >= 0) { viewl= txt_get_span(text->lines.first, endl) - st->top + offl; @@ -1271,14 +1676,17 @@ void draw_text_main(SpaceText *st, ARegion *ar) { Text *text= st->text; TextLine *tmp; - rcti scroll; + rcti scroll, back; char linenr[12]; - int i, x, y, winx, linecount= 0; + int i, x, y, winx, linecount= 0, lineno= 0; + int wraplinecount= 0, wrap_skip= 0; /* if no text, nothing to do */ if(!text) return; + text_update_drawcache(st, ar); + /* make sure all the positional pointers exist */ if(!text->curl || !text->sell || !text->lines.first || !text->lines.last) txt_clean_text(text); @@ -1287,16 +1695,32 @@ void draw_text_main(SpaceText *st, ARegion *ar) else st->viewlines= 0; /* update rects for scroll */ - calc_text_rcts(st, ar, &scroll); /* scroll will hold the entire bar size */ + calc_text_rcts(st, ar, &scroll, &back); /* scroll will hold the entire bar size */ /* update syntax formatting if needed */ tmp= text->lines.first; + lineno= 0; for(i= 0; i<st->top && tmp; i++) { if(st->showsyntax && !tmp->format) txt_format_line(st, tmp, 0); - tmp= tmp->next; - linecount++; + if(st->wordwrap) { + int lines= text_get_visible_lines_no(st, lineno); + + if (wraplinecount+lines>st->top) { + wrap_skip= st->top-wraplinecount; + break; + } else { + wraplinecount+= lines; + tmp= tmp->next; + linecount++; + } + } else { + tmp= tmp->next; + linecount++; + } + + lineno++; } text_font_begin(st); @@ -1305,7 +1729,6 @@ void draw_text_main(SpaceText *st, ARegion *ar) /* draw line numbers background */ if(st->showlinenrs) { - st->linenrs_tot = (int)floor(log10((float)(linecount + st->viewlines))) + 1; x= TXT_OFFSET + TEXTXLOC; UI_ThemeColor(TH_GRID); @@ -1328,7 +1751,7 @@ void draw_text_main(SpaceText *st, ARegion *ar) if(st->showsyntax && !tmp->format) txt_format_line(st, tmp, 0); - if(st->showlinenrs) { + if(st->showlinenrs && !wrap_skip) { /* draw line number */ if(tmp == text->curl) UI_ThemeColor(TH_HILITE); @@ -1344,21 +1767,23 @@ void draw_text_main(SpaceText *st, ARegion *ar) if(st->wordwrap) { /* draw word wrapped text */ - int lines = text_draw_wrapped(st, tmp->line, x, y, winx-x, tmp->format); + int lines = text_draw_wrapped(st, tmp->line, x, y, winx-x, tmp->format, wrap_skip); y -= lines*st->lheight; } else { /* draw unwrapped text */ - text_draw(st, tmp->line, st->left, 0, 1, x, y, tmp->format); + text_draw(st, tmp->line, st->left, ar->winx/st->cwidth, 1, x, y, tmp->format); y -= st->lheight; } + + wrap_skip= 0; } /* draw other stuff */ draw_brackets(st, ar); draw_markers(st, ar); glTranslatef(0.375f, 0.375f, 0.0f); /* XXX scroll requires exact pixel space */ - draw_textscroll(st, ar, &scroll); + draw_textscroll(st, &scroll, &back); draw_documentation(st, ar); draw_suggestion_list(st, ar); @@ -1398,6 +1823,12 @@ void text_update_cursor_moved(bContext *C) text_update_character_width(st); i= txt_get_span(text->lines.first, text->sell); + if(st->wordwrap) { + int offl, offc; + wrap_offset(st, CTX_wm_region(C), text->sell, text->selc, &offl, &offc); + i+= offl; + } + if(st->top+st->viewlines <= i || st->top > i) st->top= i - st->viewlines/2; diff --git a/source/blender/editors/space_text/text_header.c b/source/blender/editors/space_text/text_header.c index 672940cf3cb..1287f68dc04 100644 --- a/source/blender/editors/space_text/text_header.c +++ b/source/blender/editors/space_text/text_header.c @@ -47,6 +47,7 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" +#include "BLI_utildefines.h" #include "BKE_context.h" @@ -57,7 +58,7 @@ -#ifndef DISABLE_PYTHON +#ifdef WITH_PYTHON // XXX #include "BPY_menus.h" #endif @@ -101,7 +102,7 @@ static int properties_poll(bContext *C) return (CTX_wm_space_text(C) != NULL); } -static int properties_exec(bContext *C, wmOperator *op) +static int properties_exec(bContext *C, wmOperator *UNUSED(op)) { ScrArea *sa= CTX_wm_area(C); ARegion *ar= text_has_properties_region(sa); @@ -133,23 +134,23 @@ void TEXT_OT_properties(wmOperatorType *ot) uiPopupMenu *pup; if(text) { - pup= uiPupMenuBegin(C, "Text", 0); + pup= uiPupMenuBegin(C, "Text", ICON_NULL); if(txt_has_sel(text)) { - uiItemO(layout, NULL, 0, "TEXT_OT_cut"); - uiItemO(layout, NULL, 0, "TEXT_OT_copy"); + uiItemO(layout, NULL, ICON_NULL, "TEXT_OT_cut"); + uiItemO(layout, NULL, ICON_NULL, "TEXT_OT_copy"); } - uiItemO(layout, NULL, 0, "TEXT_OT_paste"); - uiItemO(layout, NULL, 0, "TEXT_OT_new"); - uiItemO(layout, NULL, 0, "TEXT_OT_open"); - uiItemO(layout, NULL, 0, "TEXT_OT_save"); - uiItemO(layout, NULL, 0, "TEXT_OT_save_as"); - uiItemO(layout, NULL, 0, "TEXT_OT_run_script"); + uiItemO(layout, NULL, ICON_NULL, "TEXT_OT_paste"); + uiItemO(layout, NULL, ICON_NULL, "TEXT_OT_new"); + uiItemO(layout, NULL, ICON_NULL, "TEXT_OT_open"); + uiItemO(layout, NULL, ICON_NULL, "TEXT_OT_save"); + uiItemO(layout, NULL, ICON_NULL, "TEXT_OT_save_as"); + uiItemO(layout, NULL, ICON_NULL, "TEXT_OT_run_script"); uiPupMenuEnd(C, pup); } else { - pup= uiPupMenuBegin(C, "File", 0); - uiItemO(layout, NULL, 0, "TEXT_OT_new"); - uiItemO(layout, NULL, 0, "TEXT_OT_open"); + pup= uiPupMenuBegin(C, "File", ICON_NULL); + uiItemO(layout, NULL, ICON_NULL, "TEXT_OT_new"); + uiItemO(layout, NULL, ICON_NULL, "TEXT_OT_open"); uiPupMenuEnd(C, pup); } } @@ -159,10 +160,10 @@ void TEXT_OT_properties(wmOperatorType *ot) uiPopupMenu *pup; - pup= uiPupMenuBegin(C, "Edit", 0); - uiItemO(layout, NULL, 0, "TEXT_OT_cut"); - uiItemO(layout, NULL, 0, "TEXT_OT_copy"); - uiItemO(layout, NULL, 0, "TEXT_OT_paste"); + pup= uiPupMenuBegin(C, "Edit", ICON_NULL); + uiItemO(layout, NULL, ICON_NULL, "TEXT_OT_cut"); + uiItemO(layout, NULL, ICON_NULL, "TEXT_OT_copy"); + uiItemO(layout, NULL, ICON_NULL, "TEXT_OT_paste"); uiPupMenuEnd(C, pup); } @@ -172,18 +173,18 @@ void TEXT_OT_properties(wmOperatorType *ot) uiPopupMenu *pup; if(text) { - pup= uiPupMenuBegin(C, "Text", 0); - uiItemO(layout, NULL, 0, "TEXT_OT_new"); - uiItemO(layout, NULL, 0, "TEXT_OT_open"); - uiItemO(layout, NULL, 0, "TEXT_OT_save"); - uiItemO(layout, NULL, 0, "TEXT_OT_save_as"); - uiItemO(layout, NULL, 0, "TEXT_OT_run_script"); + pup= uiPupMenuBegin(C, "Text", ICON_NULL); + uiItemO(layout, NULL, ICON_NULL, "TEXT_OT_new"); + uiItemO(layout, NULL, ICON_NULL, "TEXT_OT_open"); + uiItemO(layout, NULL, ICON_NULL, "TEXT_OT_save"); + uiItemO(layout, NULL, ICON_NULL, "TEXT_OT_save_as"); + uiItemO(layout, NULL, ICON_NULL, "TEXT_OT_run_script"); uiPupMenuEnd(C, pup); } else { - pup= uiPupMenuBegin(C, "File", 0); - uiItemO(layout, NULL, 0, "TEXT_OT_new"); - uiItemO(layout, NULL, 0, "TEXT_OT_open"); + pup= uiPupMenuBegin(C, "File", ICON_NULL); + uiItemO(layout, NULL, ICON_NULL, "TEXT_OT_new"); + uiItemO(layout, NULL, ICON_NULL, "TEXT_OT_open"); uiPupMenuEnd(C, pup); } } @@ -193,7 +194,7 @@ void TEXT_OT_properties(wmOperatorType *ot) uiPopupMenu *pup; - pup= uiPupMenuBegin(C, "Text", 0); + pup= uiPupMenuBegin(C, "Text", ICON_NULL); uiItemEnumO(layout, "TEXT_OT_move", "Top of File", 0, "type", FILE_TOP); uiItemEnumO(layout, "TEXT_OT_move", "Bottom of File", 0, "type", FILE_BOTTOM); uiItemEnumO(layout, "TEXT_OT_move", "Page Up", 0, "type", PREV_PAGE); diff --git a/source/blender/editors/space_text/text_intern.h b/source/blender/editors/space_text/text_intern.h index a93f30ac62a..5f6b2e05ba7 100644 --- a/source/blender/editors/space_text/text_intern.h +++ b/source/blender/editors/space_text/text_intern.h @@ -44,16 +44,10 @@ struct wmWindowManager; /* text_draw.c */ void draw_text_main(struct SpaceText *st, struct ARegion *ar); -int text_check_bracket(char ch); -int text_check_delim(char ch); -int text_check_digit(char ch); -int text_check_identifier(char ch); -int text_check_whitespace(char ch); - int text_font_width_character(struct SpaceText *st); -int text_font_width(struct SpaceText *st, char *str); +int text_font_width(struct SpaceText *st, const char *str); -void text_update_line_edited(struct Text *text, struct TextLine *line); +void text_update_line_edited(struct TextLine *line); void text_update_edited(struct Text *text); void text_update_character_width(struct SpaceText *st); void text_update_cursor_moved(struct bContext *C); @@ -85,17 +79,25 @@ typedef struct FlattenString { int pos, len; } FlattenString; -int flatten_string(struct SpaceText *st, FlattenString *fs, char *in); +int flatten_string(struct SpaceText *st, FlattenString *fs, const char *in); void flatten_string_free(FlattenString *fs); int wrap_width(struct SpaceText *st, struct ARegion *ar); void wrap_offset(struct SpaceText *st, struct ARegion *ar, struct TextLine *linein, int cursin, int *offl, int *offc); +void wrap_offset_in_line(struct SpaceText *st, struct ARegion *ar, struct TextLine *linep, int cursin, int *offl, int *offc); +int text_get_char_pos(struct SpaceText *st, const char *line, int cur); + +void text_drawcache_tag_update(struct SpaceText *st, int full); +void text_free_caches(struct SpaceText *st); int text_file_modified(struct Text *text); int text_do_suggest_select(struct SpaceText *st, struct ARegion *ar); -void text_pop_suggest_list(); +void text_pop_suggest_list(void); +int text_get_visible_lines(struct SpaceText *st, struct ARegion *ar, const char *str); +int text_get_span_wrap(struct SpaceText *st, struct ARegion *ar, struct TextLine *from, struct TextLine *to); +int text_get_total_lines(struct SpaceText *st, struct ARegion *ar); /* text_ops.c */ enum { LINE_BEGIN, LINE_END, FILE_TOP, FILE_BOTTOM, PREV_CHAR, NEXT_CHAR, diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index ed70f31f970..bfec734dad6 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -38,6 +38,8 @@ #include "DNA_userdef_types.h" #include "BLI_blenlib.h" +#include "BLI_utildefines.h" + #include "PIL_time.h" #include "BKE_context.h" @@ -58,7 +60,7 @@ #include "RNA_access.h" #include "RNA_define.h" -#ifndef DISABLE_PYTHON +#ifdef WITH_PYTHON #include "BPY_extern.h" #endif @@ -66,7 +68,7 @@ /************************ poll ***************************/ -static int text_new_poll(bContext *C) +static int text_new_poll(bContext *UNUSED(C)) { return 1; } @@ -122,10 +124,9 @@ static int text_region_edit_poll(bContext *C) return 1; } - /********************** updates *********************/ -void text_update_line_edited(Text *text, TextLine *line) +void text_update_line_edited(TextLine *line) { if(!line) return; @@ -142,12 +143,12 @@ void text_update_edited(Text *text) TextLine *line; for(line=text->lines.first; line; line=line->next) - text_update_line_edited(text, line); + text_update_line_edited(line); } /******************* new operator *********************/ -static int new_exec(bContext *C, wmOperator *op) +static int new_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceText *st= CTX_wm_space_text(C); Text *text; @@ -162,7 +163,9 @@ static int new_exec(bContext *C, wmOperator *op) if(prop) { /* when creating new ID blocks, use is already 1, but RNA * pointer se also increases user, so this compensates it */ - text->id.us--; + /* doesnt always seem to happen... (ton) */ + if(text->id.us>1) + text->id.us--; RNA_id_pointer_create(&text->id, &idptr); RNA_property_pointer_set(&ptr, prop, idptr); @@ -171,6 +174,7 @@ static int new_exec(bContext *C, wmOperator *op) else if(st) { st->text= text; st->top= 0; + text_drawcache_tag_update(st, 1); } WM_event_add_notifier(C, NC_TEXT|NA_ADDED, text); @@ -203,7 +207,7 @@ static void open_init(bContext *C, wmOperator *op) uiIDContextProperty(C, &pprop->ptr, &pprop->prop); } -static int open_cancel(bContext *C, wmOperator *op) +static int open_cancel(bContext *UNUSED(C), wmOperator *op) { MEM_freeN(op->customdata); return OPERATOR_CANCELLED; @@ -220,7 +224,7 @@ static int open_exec(bContext *C, wmOperator *op) RNA_string_get(op->ptr, "filepath", str); - text= add_text(str, G.sce); + text= add_text(str, G.main->name); if(!text) { if(op->customdata) MEM_freeN(op->customdata); @@ -254,6 +258,7 @@ static int open_exec(bContext *C, wmOperator *op) text->name = NULL; } + text_drawcache_tag_update(st, 1); WM_event_add_notifier(C, NC_TEXT|NA_ADDED, text); MEM_freeN(op->customdata); @@ -261,10 +266,10 @@ static int open_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int open_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int open_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { Text *text= CTX_data_edit_text(C); - char *path= (text && text->name)? text->name: G.sce; + char *path= (text && text->name)? text->name: G.main->name; if(RNA_property_is_set(op->ptr, "filepath")) return open_exec(C, op); @@ -308,13 +313,14 @@ static int reload_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } -#ifndef DISABLE_PYTHON +#ifdef WITH_PYTHON if(text->compiled) - BPY_free_compiled_text(text); + BPY_text_free_code(text); #endif text_update_edited(text); text_update_cursor_moved(C); + text_drawcache_tag_update(CTX_wm_space_text(C), 1); WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text); return OPERATOR_FINISHED; @@ -335,7 +341,13 @@ void TEXT_OT_reload(wmOperatorType *ot) /******************* delete operator *********************/ -static int unlink_exec(bContext *C, wmOperator *op) +static int text_unlink_poll(bContext *C) +{ + /* it should be possible to unlink texts if they're lib-linked in... */ + return CTX_data_edit_text(C) != NULL; +} + +static int unlink_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain= CTX_data_main(C); SpaceText *st= CTX_wm_space_text(C); @@ -357,6 +369,8 @@ static int unlink_exec(bContext *C, wmOperator *op) unlink_text(bmain, text); free_libblock(&bmain->text, text); + + text_drawcache_tag_update(st, 1); WM_event_add_notifier(C, NC_TEXT|NA_REMOVED, NULL); return OPERATOR_FINISHED; @@ -372,7 +386,7 @@ void TEXT_OT_unlink(wmOperatorType *ot) /* api callbacks */ ot->exec= unlink_exec; ot->invoke= WM_operator_confirm; - ot->poll= text_edit_poll; + ot->poll= text_unlink_poll; /* flags */ ot->flag= OPTYPE_UNDO; @@ -380,7 +394,7 @@ void TEXT_OT_unlink(wmOperatorType *ot) /******************* make internal operator *********************/ -static int make_internal_exec(bContext *C, wmOperator *op) +static int make_internal_exec(bContext *C, wmOperator *UNUSED(op)) { Text *text= CTX_data_edit_text(C); @@ -433,7 +447,7 @@ static void txt_write_file(Text *text, ReportList *reports) char file[FILE_MAXDIR+FILE_MAXFILE]; BLI_strncpy(file, text->name, FILE_MAXDIR+FILE_MAXFILE); - BLI_path_abs(file, G.sce); + BLI_path_abs(file, G.main->name); fp= fopen(file, "w"); if(fp==NULL) { @@ -506,7 +520,7 @@ static int save_as_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int save_as_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int save_as_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { Text *text= CTX_data_edit_text(C); char *str; @@ -519,7 +533,7 @@ static int save_as_invoke(bContext *C, wmOperator *op, wmEvent *event) else if(text->flags & TXT_ISMEM) str= text->id.name+2; else - str= G.sce; + str= G.main->name; RNA_string_set(op->ptr, "filepath", str); WM_event_add_fileselect(C, op); @@ -552,7 +566,9 @@ static int run_script_poll(bContext *C) static int run_script_exec(bContext *C, wmOperator *op) { -#ifdef DISABLE_PYTHON +#ifndef WITH_PYTHON + (void)C; /* unused */ + BKE_report(op->reports, RPT_ERROR, "Python disabled in this build"); return OPERATOR_CANCELLED; @@ -560,7 +576,7 @@ static int run_script_exec(bContext *C, wmOperator *op) Text *text= CTX_data_edit_text(C); SpaceText *st= CTX_wm_space_text(C); - if (BPY_run_python_script(C, NULL, text, op->reports)) + if (BPY_text_exec(C, text, op->reports)) return OPERATOR_FINISHED; /* Dont report error messages while live editing */ @@ -588,9 +604,9 @@ void TEXT_OT_run_script(wmOperatorType *ot) /******************* refresh pyconstraints operator *********************/ -static int refresh_pyconstraints_exec(bContext *C, wmOperator *op) +static int refresh_pyconstraints_exec(bContext *UNUSED(C), wmOperator *UNUSED(op)) { -#ifndef DISABLE_PYTHON +#ifdef WITH_PYTHON #if 0 Text *text= CTX_data_edit_text(C); Object *ob; @@ -622,7 +638,7 @@ static int refresh_pyconstraints_exec(bContext *C, wmOperator *op) } if(update) { - DAG_id_flush_update(&ob->id, OB_RECALC_DATA); + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); } } #endif @@ -738,6 +754,8 @@ static int paste_exec(bContext *C, wmOperator *op) if(!buf) return OPERATOR_CANCELLED; + text_drawcache_tag_update(CTX_wm_space_text(C), 0); + txt_insert_buf(text, buf); text_update_edited(text); @@ -782,7 +800,7 @@ static void txt_copy_clipboard(Text *text) } } -static int copy_exec(bContext *C, wmOperator *op) +static int copy_exec(bContext *C, wmOperator *UNUSED(op)) { Text *text= CTX_data_edit_text(C); @@ -809,6 +827,8 @@ static int cut_exec(bContext *C, wmOperator *op) { Text *text= CTX_data_edit_text(C); + text_drawcache_tag_update(CTX_wm_space_text(C), 0); + txt_copy_clipboard(text); txt_delete_selected(text); @@ -836,10 +856,12 @@ void TEXT_OT_cut(wmOperatorType *ot) /******************* indent operator *********************/ -static int indent_exec(bContext *C, wmOperator *op) +static int indent_exec(bContext *C, wmOperator *UNUSED(op)) { Text *text= CTX_data_edit_text(C); + text_drawcache_tag_update(CTX_wm_space_text(C), 0); + if(txt_has_sel(text)) { txt_order_cursors(text); indent(text); @@ -869,11 +891,13 @@ void TEXT_OT_indent(wmOperatorType *ot) /******************* unindent operator *********************/ -static int unindent_exec(bContext *C, wmOperator *op) +static int unindent_exec(bContext *C, wmOperator *UNUSED(op)) { Text *text= CTX_data_edit_text(C); if(txt_has_sel(text)) { + text_drawcache_tag_update(CTX_wm_space_text(C), 0); + txt_order_cursors(text); unindent(text); @@ -902,13 +926,15 @@ void TEXT_OT_unindent(wmOperatorType *ot) /******************* line break operator *********************/ -static int line_break_exec(bContext *C, wmOperator *op) +static int line_break_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceText *st= CTX_wm_space_text(C); Text *text= CTX_data_edit_text(C); int a, curts; int space = (text->flags & TXT_TABSTOSPACES) ? st->tabnumber : 1; + text_drawcache_tag_update(st, 0); + // double check tabs/spaces before splitting the line curts= setcurr_tab_spaces(text, space); txt_split_curline(text); @@ -923,8 +949,8 @@ static int line_break_exec(bContext *C, wmOperator *op) if(text->curl) { if(text->curl->prev) - text_update_line_edited(text, text->curl->prev); - text_update_line_edited(text, text->curl); + text_update_line_edited(text->curl->prev); + text_update_line_edited(text->curl); } text_update_cursor_moved(C); @@ -947,11 +973,13 @@ void TEXT_OT_line_break(wmOperatorType *ot) /******************* comment operator *********************/ -static int comment_exec(bContext *C, wmOperator *op) +static int comment_exec(bContext *C, wmOperator *UNUSED(op)) { Text *text= CTX_data_edit_text(C); if(txt_has_sel(text)) { + text_drawcache_tag_update(CTX_wm_space_text(C), 0); + txt_order_cursors(text); comment(text); text_update_edited(text); @@ -978,11 +1006,13 @@ void TEXT_OT_comment(wmOperatorType *ot) /******************* uncomment operator *********************/ -static int uncomment_exec(bContext *C, wmOperator *op) +static int uncomment_exec(bContext *C, wmOperator *UNUSED(op)) { Text *text= CTX_data_edit_text(C); if(txt_has_sel(text)) { + text_drawcache_tag_update(CTX_wm_space_text(C), 0); + txt_order_cursors(text); uncomment(text); text_update_edited(text); @@ -1130,6 +1160,7 @@ static int convert_whitespace_exec(bContext *C, wmOperator *op) text_update_edited(text); text_update_cursor_moved(C); + text_drawcache_tag_update(st, 1); WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text); return OPERATOR_FINISHED; @@ -1152,7 +1183,7 @@ void TEXT_OT_convert_whitespace(wmOperatorType *ot) /******************* select all operator *********************/ -static int select_all_exec(bContext *C, wmOperator *op) +static int select_all_exec(bContext *C, wmOperator *UNUSED(op)) { Text *text= CTX_data_edit_text(C); @@ -1178,7 +1209,7 @@ void TEXT_OT_select_all(wmOperatorType *ot) /******************* select line operator *********************/ -static int select_line_exec(bContext *C, wmOperator *op) +static int select_line_exec(bContext *C, wmOperator *UNUSED(op)) { Text *text= CTX_data_edit_text(C); @@ -1204,7 +1235,7 @@ void TEXT_OT_select_line(wmOperatorType *ot) /******************* previous marker operator *********************/ -static int previous_marker_exec(bContext *C, wmOperator *op) +static int previous_marker_exec(bContext *C, wmOperator *UNUSED(op)) { Text *text= CTX_data_edit_text(C); TextMarker *mrk; @@ -1240,7 +1271,7 @@ void TEXT_OT_previous_marker(wmOperatorType *ot) /******************* next marker operator *********************/ -static int next_marker_exec(bContext *C, wmOperator *op) +static int next_marker_exec(bContext *C, wmOperator *UNUSED(op)) { Text *text= CTX_data_edit_text(C); TextMarker *mrk; @@ -1276,7 +1307,7 @@ void TEXT_OT_next_marker(wmOperatorType *ot) /******************* clear all markers operator *********************/ -static int clear_all_markers_exec(bContext *C, wmOperator *op) +static int clear_all_markers_exec(bContext *C, wmOperator *UNUSED(op)) { Text *text= CTX_data_edit_text(C); @@ -1317,146 +1348,370 @@ static EnumPropertyItem move_type_items[]= { {NEXT_PAGE, "NEXT_PAGE", 0, "Next Page", ""}, {0, NULL, 0, NULL, NULL}}; +/* get cursor position in line by relative wrapped line and column positions */ +static int text_get_cursor_rel(SpaceText* st, ARegion *ar, TextLine *linein, int rell, int relc) +{ + int i, j, start, end, max, chop, curs, loop, endj, found, selc; + char ch; + + max= wrap_width(st, ar); + + selc= start= endj= curs= found= 0; + end= max; + chop= loop= 1; + + for(i=0, j=0; loop; j++) { + int chars; + /* Mimic replacement of tabs */ + ch= linein->line[j]; + if(ch=='\t') { + chars= st->tabnumber-i%st->tabnumber; + ch= ' '; + } + else chars= 1; + + while(chars--) { + if(rell==0 && i-start==relc) { + /* current position could be wrapped to next line */ + /* this should be checked when end of current line would be reached */ + selc= j; + found= 1; + } + else if(i-end==relc) { + curs= j; + } + if(i-start>=max) { + if(found) { + /* exact cursor position was found, check if it's */ + /* still on needed line (hasn't been wrapped) */ + if(selc>endj && !chop) selc= endj; + loop= 0; + break; + } + + if(chop) endj= j; + + start= end; + end += max; + chop= 1; + rell--; + + if(rell==0 && i-start>=relc) { + selc= curs; + loop= 0; + break; + } + } + else if (ch=='\0') { + if(!found) selc= linein->len; + loop= 0; + break; + } + else if(ch==' ' || ch=='-') { + if(found) { + loop= 0; + break; + } + + if(rell==0 && i-start>=relc) { + selc= curs; + loop= 0; + break; + } + end= i+1; + endj= j; + chop= 0; + } + i++; + } + } + + return selc; +} + +static int cursor_skip_find_line(SpaceText* st, ARegion *ar, + int lines, TextLine **linep, int *charp, int *rell, int *relc) +{ + int offl, offc, visible_lines; + + wrap_offset_in_line(st, ar, *linep, *charp, &offl, &offc); + *relc= text_get_char_pos(st, (*linep)->line, *charp) + offc; + *rell= lines; + + /* handle current line */ + if(lines>0) { + visible_lines= text_get_visible_lines(st, ar, (*linep)->line); + + if(*rell-visible_lines+offl>=0) { + if(!(*linep)->next) { + if(offl < visible_lines-1) { + *rell= visible_lines-1; + return 1; + } + + *charp= (*linep)->len; + return 0; + } + + *rell-= visible_lines-offl; + *linep=(*linep)->next; + } else { + *rell+= offl; + return 1; + } + } else { + if(*rell+offl<=0) { + if(!(*linep)->prev) { + if(offl) { + *rell= 0; + return 1; + } + + *charp= 0; + return 0; + } + + *rell+= offl; + *linep=(*linep)->prev; + } else { + *rell+= offl; + return 1; + } + } + + /* skip lines and find destination line and offsets */ + while(*linep) { + visible_lines= text_get_visible_lines(st, ar, (*linep)->line); + + if(lines<0) { /* moving top */ + if(*rell+visible_lines >= 0) { + *rell+= visible_lines; + break; + } + + if(!(*linep)->prev) { + *rell= 0; + break; + } + + *rell+= visible_lines; + *linep=(*linep)->prev; + } else { /* moving bottom */ + if(*rell-visible_lines < 0) break; + + if(!(*linep)->next) { + *rell= visible_lines-1; + break; + } + + *rell-= visible_lines; + *linep=(*linep)->next; + } + } + + return 1; +} + static void wrap_move_bol(SpaceText *st, ARegion *ar, short sel) { Text *text= st->text; - int offl, offc, lin; + TextLine **linep; + int *charp; + int oldl, oldc, i, j, max, start, end, endj, chop, loop; + char ch; text_update_character_width(st); - lin= txt_get_span(text->lines.first, text->sell); - wrap_offset(st, ar, text->sell, text->selc, &offl, &offc); + if (sel) linep= &text->sell, charp= &text->selc; + else linep= &text->curl, charp= &text->curc; - if (sel) { - txt_undo_add_toop(text, UNDO_STO, lin, text->selc, lin, -offc); - text->selc= -offc; - } else { - txt_undo_add_toop(text, UNDO_CTO, lin, text->curc, lin, -offc); - text->curc= -offc; - txt_pop_sel(text); + oldc= *charp; + oldl= txt_get_span(text->lines.first, *linep); + + max= wrap_width(st, ar); + + start= endj= 0; + end= max; + chop= loop= 1; + *charp= 0; + + for(i=0, j=0; loop; j++) { + int chars; + /* Mimic replacement of tabs */ + ch= (*linep)->line[j]; + if(ch=='\t') { + chars= st->tabnumber-i%st->tabnumber; + ch= ' '; + } + else chars= 1; + + while(chars--) { + if(i-start>=max) { + *charp= endj; + + if(j>=oldc) { + if(ch=='\0') *charp= start; + loop= 0; + break; + } + + if(chop) endj= j; + + start= end; + end += max; + chop= 1; + } + else if(ch==' ' || ch=='-' || ch=='\0') { + if(j>=oldc) { + *charp= start; + loop= 0; + break; + } + + end= i+1; + endj= j+1; + chop= 0; + } + i++; + } } + + if (!sel) txt_pop_sel(text); + txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, oldl, oldc, oldl, *charp); } static void wrap_move_eol(SpaceText *st, ARegion *ar, short sel) { Text *text= st->text; - int offl, offc, lin, startl, c; + TextLine **linep; + int *charp; + int oldl, oldc, i, j, max, start, end, endj, chop, loop; + char ch; text_update_character_width(st); - lin= txt_get_span(text->lines.first, text->sell); - wrap_offset(st, ar, text->sell, text->selc, &offl, &offc); - startl= offl; - c= text->selc; - while (offl==startl && text->sell->line[c]!='\0') { - c++; - wrap_offset(st, ar, text->sell, c, &offl, &offc); - } if (offl!=startl) c--; - - if (sel) { - txt_undo_add_toop(text, UNDO_STO, lin, text->selc, lin, c); - text->selc= c; - } else { - txt_undo_add_toop(text, UNDO_CTO, lin, text->curc, lin, c); - text->curc= c; - txt_pop_sel(text); + if (sel) linep= &text->sell, charp= &text->selc; + else linep= &text->curl, charp= &text->curc; + + oldc= *charp; + oldl= txt_get_span(text->lines.first, *linep); + + max= wrap_width(st, ar); + + start= endj= 0; + end= max; + chop= loop= 1; + *charp= 0; + + for(i=0, j=0; loop; j++) { + int chars; + /* Mimic replacement of tabs */ + ch= (*linep)->line[j]; + if(ch=='\t') { + chars= st->tabnumber-i%st->tabnumber; + ch= ' '; + } + else chars= 1; + + while(chars--) { + if(i-start>=max) { + if(chop) endj= j-1; + + if(endj>=oldc) { + if(ch=='\0') *charp= (*linep)->len; + else *charp= endj; + loop= 0; + break; + } + + start= end; + end += max; + chop= 1; + } else if(ch=='\0') { + *charp= (*linep)->len; + loop= 0; + break; + } else if(ch==' ' || ch=='-') { + end= i+1; + endj= j; + chop= 0; + } + i++; + } } + + if (!sel) txt_pop_sel(text); + txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, oldl, oldc, oldl, *charp); } static void wrap_move_up(SpaceText *st, ARegion *ar, short sel) { Text *text= st->text; - int offl, offl_1, offc, fromline, toline, c, target; + TextLine **linep; + int *charp; + int oldl, oldc, offl, offc, col, newl; text_update_character_width(st); - wrap_offset(st, ar, text->sell, 0, &offl_1, &offc); - wrap_offset(st, ar, text->sell, text->selc, &offl, &offc); - fromline= toline= txt_get_span(text->lines.first, text->sell); - target= text->selc + offc; + if (sel) linep= &text->sell, charp= &text->selc; + else linep= &text->curl, charp= &text->curc; - if (offl==offl_1) { - if (!text->sell->prev) { - txt_move_bol(text, sel); - return; - } - toline--; - c= text->sell->prev->len; /* End of prev. line */ - wrap_offset(st, ar, text->sell->prev, c, &offl, &offc); - c= -offc+target; + /* store previous position */ + oldc= *charp; + newl= oldl= txt_get_span(text->lines.first, *linep); + + wrap_offset_in_line(st, ar, *linep, *charp, &offl, &offc); + col= text_get_char_pos(st, (*linep)->line, *charp) + offc; + if(offl) { + *charp= text_get_cursor_rel(st, ar, *linep, offl-1, col); + newl= BLI_findindex(&text->lines, linep); } else { - c= -offc-1; /* End of prev. line */ - wrap_offset(st, ar, text->sell, c, &offl, &offc); - c= -offc+target; - } - if (c<0) c=0; - - if (sel) { - txt_undo_add_toop(text, UNDO_STO, fromline, text->selc, toline, c); - if (toline<fromline) text->sell= text->sell->prev; - if(text->sell) { - if (c>text->sell->len) c= text->sell->len; - text->selc= c; - } - } - else if(text->curl) { - txt_undo_add_toop(text, UNDO_CTO, fromline, text->curc, toline, c); - if (toline<fromline) text->curl= text->curl->prev; - if(text->curl) { - if (c>text->curl->len) c= text->curl->len; - text->curc= c; - txt_pop_sel(text); - } + if((*linep)->prev) { + int visible_lines; + + *linep= (*linep)->prev; + visible_lines= text_get_visible_lines(st, ar, (*linep)->line); + *charp= text_get_cursor_rel(st, ar, *linep, visible_lines-1, col); + newl--; + } else *charp= 0; } + + if (!sel) txt_pop_sel(text); + txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, oldl, oldc, newl, *charp); } static void wrap_move_down(SpaceText *st, ARegion *ar, short sel) { Text *text= st->text; - int offl, startoff, offc, fromline, toline, c, target; + TextLine **linep; + int *charp; + int oldl, oldc, offl, offc, col, newl, visible_lines; text_update_character_width(st); - wrap_offset(st, ar, text->sell, text->selc, &offl, &offc); - fromline= toline= txt_get_span(text->lines.first, text->sell); - target= text->selc + offc; - startoff= offl; - c= text->selc; - while (offl==startoff && text->sell->line[c]!='\0') { - c++; - wrap_offset(st, ar, text->sell, c, &offl, &offc); - } + if (sel) linep= &text->sell, charp= &text->selc; + else linep= &text->curl, charp= &text->curc; - if (text->sell->line[c]=='\0') { - if (!text->sell->next) { - txt_move_eol(text, sel); - return; - } - toline++; - c= target; + /* store previous position */ + oldc= *charp; + newl= oldl= txt_get_span(text->lines.first, *linep); + + wrap_offset_in_line(st, ar, *linep, *charp, &offl, &offc); + col= text_get_char_pos(st, (*linep)->line, *charp) + offc; + visible_lines= text_get_visible_lines(st, ar, (*linep)->line); + if(offl<visible_lines-1) { + *charp= text_get_cursor_rel(st, ar, *linep, offl+1, col); + newl= BLI_findindex(&text->lines, linep); } else { - c += target; - if (c > text->sell->len) c= text->sell->len; - } - if (c<0) c=0; - - if (sel) { - txt_undo_add_toop(text, UNDO_STO, fromline, text->selc, toline, c); - if (toline>fromline) text->sell= text->sell->next; - if(text->sell) { - if (c>text->sell->len) c= text->sell->len; - text->selc= c; - } - } - else if(text->curl) { - txt_undo_add_toop(text, UNDO_CTO, fromline, text->curc, toline, c); - if (toline>fromline) text->curl= text->curl->next; - if(text->curl) { - if (c > text->curl->len) c= text->curl->len; - text->curc= c; - txt_pop_sel(text); - } + if((*linep)->next) { + *linep= (*linep)->next; + *charp= text_get_cursor_rel(st, ar, *linep, 0, col); + newl++; + } else *charp= (*linep)->len; } + + if (!sel) txt_pop_sel(text); + txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, oldl, oldc, newl, *charp); } /* Moves the cursor vertically by the specified number of lines. @@ -1465,7 +1720,7 @@ static void wrap_move_down(SpaceText *st, ARegion *ar, short sel) This is to replace screen_skip for PageUp/Down operations. */ -static void cursor_skip(Text *text, int lines, int sel) +static void cursor_skip(SpaceText* st, ARegion *ar, Text *text, int lines, int sel) { TextLine **linep; int oldl, oldc, *charp; @@ -1475,13 +1730,21 @@ static void cursor_skip(Text *text, int lines, int sel) oldl= txt_get_span(text->lines.first, *linep); oldc= *charp; - while (lines>0 && (*linep)->next) { - *linep= (*linep)->next; - lines--; - } - while (lines<0 && (*linep)->prev) { - *linep= (*linep)->prev; - lines++; + if(st && ar && st->wordwrap) { + int rell, relc; + + /* find line and offsets inside it needed to set cursor position */ + if(cursor_skip_find_line(st, ar, lines, linep, charp, &rell, &relc)) + *charp= text_get_cursor_rel (st, ar, *linep, rell, relc); + } else { + while (lines>0 && (*linep)->next) { + *linep= (*linep)->next; + lines--; + } + while (lines<0 && (*linep)->prev) { + *linep= (*linep)->prev; + lines++; + } } if (*charp > (*linep)->len) *charp= (*linep)->len; @@ -1546,18 +1809,18 @@ static int move_cursor(bContext *C, int type, int select) break; case PREV_PAGE: - if(st) cursor_skip(text, -st->viewlines, select); - else cursor_skip(text, -10, select); + if(st) cursor_skip(st, ar, st->text, -st->viewlines, select); + else cursor_skip(NULL, NULL, text, -10, select); break; case NEXT_PAGE: - if(st) cursor_skip(text, st->viewlines, select); - else cursor_skip(text, 10, select); + if(st) cursor_skip(st, ar, st->text, st->viewlines, select); + else cursor_skip(NULL, NULL, text, 10, select); break; } text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text); + WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text); return OPERATOR_FINISHED; } @@ -1629,7 +1892,7 @@ static int jump_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int jump_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int jump_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { return WM_operator_props_dialog_popup(C,op,200,100); @@ -1665,6 +1928,8 @@ static int delete_exec(bContext *C, wmOperator *op) Text *text= CTX_data_edit_text(C); int type= RNA_enum_get(op->ptr, "type"); + text_drawcache_tag_update(CTX_wm_space_text(C), 0); + if(type == DEL_PREV_WORD) txt_backspace_word(text); else if(type == DEL_PREV_CHAR) @@ -1674,7 +1939,7 @@ static int delete_exec(bContext *C, wmOperator *op) else if(type == DEL_NEXT_CHAR) txt_delete_char(text); - text_update_line_edited(text, text->curl); + text_update_line_edited(text->curl); text_update_cursor_moved(C); WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text); @@ -1703,7 +1968,7 @@ void TEXT_OT_delete(wmOperatorType *ot) /******************* toggle overwrite operator **********************/ -static int toggle_overwrite_exec(bContext *C, wmOperator *op) +static int toggle_overwrite_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceText *st= CTX_wm_space_text(C); @@ -1729,39 +1994,53 @@ void TEXT_OT_overwrite_toggle(wmOperatorType *ot) /******************* scroll operator **********************/ /* Moves the view vertically by the specified number of lines */ -static void screen_skip(SpaceText *st, int lines) +static void screen_skip(SpaceText *st, ARegion *ar, int lines) { int last; - st->top += lines; + st->top += lines; - last= txt_get_span(st->text->lines.first, st->text->lines.last); + last= text_get_total_lines(st, ar); last= last - (st->viewlines/2); if(st->top>last) st->top= last; if(st->top<0) st->top= 0; } +/* quick enum for tsc->zone (scroller handles) */ +enum { + SCROLLHANDLE_BAR, + SCROLLHANDLE_MIN_OUTSIDE, + SCROLLHANDLE_MAX_OUTSIDE +} TextScrollerHandle_Zone; + typedef struct TextScroll { short old[2]; - short hold[2]; short delta[2]; int first; - int characters; - int lines; int scrollbar; + + int zone; } TextScroll; +static int text_scroll_poll(bContext *C) +{ + /* it should be possible to still scroll linked texts to read them, even if they can't be edited... */ + return CTX_data_edit_text(C) != NULL; +} + static int scroll_exec(bContext *C, wmOperator *op) { SpaceText *st= CTX_wm_space_text(C); + ARegion *ar= CTX_wm_region(C); + int lines= RNA_int_get(op->ptr, "lines"); if(lines == 0) return OPERATOR_CANCELLED; - screen_skip(st, lines*U.wheellinescroll); + screen_skip(st, ar, lines*U.wheellinescroll); ED_area_tag_redraw(CTX_wm_area(C)); @@ -1771,41 +2050,44 @@ static int scroll_exec(bContext *C, wmOperator *op) static void scroll_apply(bContext *C, wmOperator *op, wmEvent *event) { SpaceText *st= CTX_wm_space_text(C); + ARegion *ar= CTX_wm_region(C); TextScroll *tsc= op->customdata; - short *mval= event->mval; + short mval[2]= {event->x, event->y}; + short txtdelta[2] = {0, 0}; text_update_character_width(st); if(tsc->first) { tsc->old[0]= mval[0]; tsc->old[1]= mval[1]; - tsc->hold[0]= mval[0]; - tsc->hold[1]= mval[1]; tsc->first= 0; } + tsc->delta[0]+= mval[0] - tsc->old[0]; + tsc->delta[1]+= mval[1] - tsc->old[1]; + if(!tsc->scrollbar) { - tsc->delta[0]= (tsc->hold[0]-mval[0])/st->cwidth; - tsc->delta[1]= (mval[1]-tsc->hold[1])/st->lheight; + txtdelta[0]= -tsc->delta[0]/st->cwidth; + txtdelta[1]= tsc->delta[1]/st->lheight; + + tsc->delta[0]%= st->cwidth; + tsc->delta[1]%= st->lheight; + } + else { + txtdelta[1]= -tsc->delta[1]*st->pix_per_line; + tsc->delta[1]+= txtdelta[1]/st->pix_per_line; } - else - tsc->delta[1]= (tsc->hold[1]-mval[1])*st->pix_per_line; - - if(tsc->delta[0] || tsc->delta[1]) { - screen_skip(st, tsc->delta[1]); - tsc->lines += tsc->delta[1]; + if(txtdelta[0] || txtdelta[1]) { + screen_skip(st, ar, txtdelta[1]); if(st->wordwrap) { st->left= 0; } else { - st->left+= tsc->delta[0]; + st->left+= txtdelta[0]; if(st->left<0) st->left= 0; } - - tsc->hold[0]= mval[0]; - tsc->hold[1]= mval[1]; ED_area_tag_redraw(CTX_wm_area(C)); } @@ -1824,13 +2106,30 @@ static void scroll_exit(bContext *C, wmOperator *op) static int scroll_modal(bContext *C, wmOperator *op, wmEvent *event) { + TextScroll *tsc= op->customdata; + SpaceText *st= CTX_wm_space_text(C); + ARegion *ar= CTX_wm_region(C); + switch(event->type) { case MOUSEMOVE: - scroll_apply(C, op, event); + if(tsc->zone == SCROLLHANDLE_BAR) + scroll_apply(C, op, event); break; case LEFTMOUSE: case RIGHTMOUSE: case MIDDLEMOUSE: + if(ELEM(tsc->zone, SCROLLHANDLE_MIN_OUTSIDE, SCROLLHANDLE_MAX_OUTSIDE)) { + int last; + + st->top+= st->viewlines * (tsc->zone==SCROLLHANDLE_MIN_OUTSIDE ? 1 : -1); + + last= text_get_total_lines(st, ar); + last= last - (st->viewlines/2); + + CLAMP(st->top, 0, last); + + ED_area_tag_redraw(CTX_wm_area(C)); + } scroll_exit(C, op); return OPERATOR_FINISHED; } @@ -1855,6 +2154,7 @@ static int scroll_invoke(bContext *C, wmOperator *op, wmEvent *event) tsc= MEM_callocN(sizeof(TextScroll), "TextScroll"); tsc->first= 1; + tsc->zone= SCROLLHANDLE_BAR; op->customdata= tsc; st->flags|= ST_SCROLL_SELECT; @@ -1862,11 +2162,11 @@ static int scroll_invoke(bContext *C, wmOperator *op, wmEvent *event) if (event->type == MOUSEPAN) { text_update_character_width(st); - tsc->hold[0] = event->prevx; - tsc->hold[1] = event->prevy; + tsc->old[0] = event->x; + tsc->old[1] = event->x; /* Sensitivity of scroll set to 4pix per line/char */ - event->mval[0] = event->prevx + (event->x - event->prevx)*st->cwidth/4; - event->mval[1] = event->prevy + (event->y - event->prevy)*st->lheight/4; + tsc->delta[0] = (event->x - event->prevx)*st->cwidth/4; + tsc->delta[1] = (event->y - event->prevy)*st->lheight/4; tsc->first = 0; tsc->scrollbar = 0; scroll_apply(C, op, event); @@ -1894,10 +2194,10 @@ void TEXT_OT_scroll(wmOperatorType *ot) ot->invoke= scroll_invoke; ot->modal= scroll_modal; ot->cancel= scroll_cancel; - ot->poll= text_space_edit_poll; + ot->poll= text_scroll_poll; /* flags */ - ot->flag= OPTYPE_BLOCKING; + ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER; /* properties */ RNA_def_int(ot->srna, "lines", 1, INT_MIN, INT_MAX, "Lines", "Number of lines to scroll.", -100, 100); @@ -1905,24 +2205,54 @@ void TEXT_OT_scroll(wmOperatorType *ot) /******************** scroll bar operator *******************/ +static int text_region_scroll_poll(bContext *C) +{ + /* same as text_region_edit_poll except it works on libdata too */ + SpaceText *st= CTX_wm_space_text(C); + Text *text= CTX_data_edit_text(C); + ARegion *ar= CTX_wm_region(C); + + if(!st || !text) + return 0; + + if(!ar || ar->regiontype != RGN_TYPE_WINDOW) + return 0; + + return 1; +} + static int scroll_bar_invoke(bContext *C, wmOperator *op, wmEvent *event) { SpaceText *st= CTX_wm_space_text(C); ARegion *ar= CTX_wm_region(C); TextScroll *tsc; short *mval= event->mval; + int zone= -1; if(RNA_property_is_set(op->ptr, "lines")) return scroll_exec(C, op); /* verify we are in the right zone */ - if(!(mval[0]>ar->winx-TXT_SCROLL_WIDTH && mval[0]<ar->winx-TXT_SCROLL_SPACE - && mval[1]>TXT_SCROLL_SPACE && mval[1]<ar->winy)) + if(mval[0]>st->txtbar.xmin && mval[0]<st->txtbar.xmax) { + if(mval[1]>=st->txtbar.ymin && mval[1]<=st->txtbar.ymax) { + /* mouse inside scroll handle */ + zone = SCROLLHANDLE_BAR; + } + else if(mval[1]>TXT_SCROLL_SPACE && mval[1]<ar->winy-TXT_SCROLL_SPACE) { + if(mval[1]<st->txtbar.ymin) zone= SCROLLHANDLE_MIN_OUTSIDE; + else zone= SCROLLHANDLE_MAX_OUTSIDE; + } + } + + if(zone == -1) { + /* we are outside slider - nothing to do */ return OPERATOR_PASS_THROUGH; + } tsc= MEM_callocN(sizeof(TextScroll), "TextScroll"); tsc->first= 1; tsc->scrollbar= 1; + tsc->zone= zone; op->customdata= tsc; st->flags|= ST_SCROLL_SELECT; @@ -1946,7 +2276,7 @@ void TEXT_OT_scroll_bar(wmOperatorType *ot) ot->invoke= scroll_bar_invoke; ot->modal= scroll_modal; ot->cancel= scroll_cancel; - ot->poll= text_region_edit_poll; + ot->poll= text_region_scroll_poll; /* flags */ ot->flag= OPTYPE_BLOCKING; @@ -1976,7 +2306,7 @@ static void set_cursor_to_pos(SpaceText *st, ARegion *ar, int x, int y, int sel) if(sel) { linep= &text->sell; charp= &text->selc; } else { linep= &text->curl; charp= &text->curc; } - y= (ar->winy - y)/st->lheight; + y= (ar->winy - 2 - y)/st->lheight; if(st->showlinenrs) x-= TXT_OFFSET+TEXTXLOC; @@ -1987,24 +2317,36 @@ static void set_cursor_to_pos(SpaceText *st, ARegion *ar, int x, int y, int sel) x = (x/st->cwidth) + st->left; if(st->wordwrap) { - int i, j, endj, curs, max, chop, start, end, chars, loop; + int i, j, endj, curs, max, chop, start, end, loop, found; char ch; /* Point to first visible line */ *linep= text->lines.first; - for(i=0; i<st->top && (*linep)->next; i++) *linep= (*linep)->next; + i= st->top; + while(i>0 && *linep) { + int lines= text_get_visible_lines(st, ar, (*linep)->line); + + if (i-lines<0) { + y+= i; + break; + } else { + *linep= (*linep)->next; + i-= lines; + } + } max= wrap_width(st, ar); loop= 1; + found= 0; while(loop && *linep) { start= 0; end= max; chop= 1; - chars= 0; curs= 0; endj= 0; for(i=0, j=0; loop; j++) { + int chars; /* Mimic replacement of tabs */ ch= (*linep)->line[j]; @@ -2021,22 +2363,34 @@ static void set_cursor_to_pos(SpaceText *st, ARegion *ar, int x, int y, int sel) *charp= endj; loop= 0; break; - /* Exactly at the cursor, done */ + /* Exactly at the cursor */ } else if(y==0 && i-start==x) { + /* current position could be wrapped to next line */ + /* this should be checked when end of current line would be reached */ *charp= curs= j; - loop= 0; - break; + found= 1; /* Prepare curs for next wrap */ } else if(i-end==x) { curs= j; } if(i-start>=max) { + if(found) { + /* exact cursor position was found, check if it's */ + /* still on needed line (hasn't been wrapped) */ + if(*charp>endj && !chop && ch!='\0') (*charp)= endj; + loop= 0; + break; + } + if(chop) endj= j; - y--; start= end; end += max; + + if(j<(*linep)->len) + y--; + chop= 1; if(y==0 && i-start>=x) { *charp= curs; @@ -2045,6 +2399,11 @@ static void set_cursor_to_pos(SpaceText *st, ARegion *ar, int x, int y, int sel) } } else if(ch==' ' || ch=='-' || ch=='\0') { + if(found) { + loop= 0; + break; + } + if(y==0 && i-start>=x) { *charp= curs; loop= 0; @@ -2058,13 +2417,13 @@ static void set_cursor_to_pos(SpaceText *st, ARegion *ar, int x, int y, int sel) } if(ch=='\0') break; } - if(!loop || y<0) break; + if(!loop || found) break; if(!(*linep)->next) { *charp= (*linep)->len; break; } - + /* On correct line but didn't meet cursor, must be at end */ if(y==0) { *charp= (*linep)->len; @@ -2102,7 +2461,7 @@ static void set_cursor_apply(bContext *C, wmOperator *op, wmEvent *event) if(event->mval[1]<0 || event->mval[1]>ar->winy) { int d= (scu->old[1]-event->mval[1])*st->pix_per_line; - if(d) screen_skip(st, d); + if(d) screen_skip(st, ar, d); set_cursor_to_pos(st, ar, event->mval[0], event->mval[1]<0?0:ar->winy, 1); @@ -2234,7 +2593,7 @@ void TEXT_OT_cursor_set(wmOperatorType *ot) /******************* line number operator **********************/ -static int line_number_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int line_number_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) { SpaceText *st= CTX_wm_space_text(C); Text *text= CTX_data_edit_text(C); @@ -2244,10 +2603,12 @@ static int line_number_invoke(bContext *C, wmOperator *op, wmEvent *event) static int jump_to= 0; static double last_jump= 0; + text_update_character_width(st); + if(!st->showlinenrs) return OPERATOR_PASS_THROUGH; - if(!(mval[0]>2 && mval[0]<60 && mval[1]>2 && mval[1]<ar->winy-2)) + if(!(mval[0]>2 && mval[0]<(TXT_OFFSET + TEXTXLOC) && mval[1]>2 && mval[1]<ar->winy-2)) return OPERATOR_PASS_THROUGH; if(!(event->ascii>='0' && event->ascii<='9')) @@ -2290,6 +2651,8 @@ static int insert_exec(bContext *C, wmOperator *op) char *str; int done = 0, i; + text_drawcache_tag_update(st, 0); + str= RNA_string_get_alloc(op->ptr, "text", NULL, 0); if(st && st->overwrite) { @@ -2307,7 +2670,7 @@ static int insert_exec(bContext *C, wmOperator *op) if(!done) return OPERATOR_CANCELLED; - text_update_line_edited(text, text->curl); + text_update_line_edited(text->curl); text_update_cursor_moved(C); WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text); @@ -2317,18 +2680,22 @@ static int insert_exec(bContext *C, wmOperator *op) static int insert_invoke(bContext *C, wmOperator *op, wmEvent *event) { - char str[2]; int ret; - /* XXX old code from winqreadtextspace, is it still needed somewhere? */ - /* smartass code to prevent the CTRL/ALT events below from not working! */ - /*if(qual & (LR_ALTKEY|LR_CTRLKEY)) - if(!ispunct(ascii)) - ascii= 0;*/ - str[0]= event->ascii; - str[1]= '\0'; + // if(!RNA_property_is_set(op->ptr, "text")) { /* always set from keymap XXX */ + if(!RNA_string_length(op->ptr, "text")) { + /* if alt/ctrl/super are pressed pass through */ + if(event->ctrl || event->oskey) { + return OPERATOR_PASS_THROUGH; + } + else { + char str[2]; + str[0]= event->ascii; + str[1]= '\0'; + RNA_string_set(op->ptr, "text", str); + } + } - RNA_string_set(op->ptr, "text", str); ret = insert_exec(C, op); /* run the script while editing, evil but useful */ @@ -2396,9 +2763,10 @@ static int find_and_replace(bContext *C, wmOperator *op, short mode) } text_update_cursor_moved(C); WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text); + text_drawcache_tag_update(CTX_wm_space_text(C), 1); } else if(mode==TEXT_MARK_ALL) { - char color[4]; + unsigned char color[4]; UI_GetThemeColor4ubv(TH_SHADE2, color); if(txt_find_marker(text, text->curl, text->selc, TMARK_GRP_FINDALL, 0)) { @@ -2529,7 +2897,7 @@ void TEXT_OT_find_set_selected(wmOperatorType *ot) /******************* replace set selected *********************/ -static int replace_set_selected_exec(bContext *C, wmOperator *op) +static int replace_set_selected_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceText *st= CTX_wm_space_text(C); Text *text= CTX_data_edit_text(C); @@ -2579,7 +2947,7 @@ int text_file_modified(Text *text) return 0; BLI_strncpy(file, text->name, FILE_MAXDIR+FILE_MAXFILE); - BLI_path_abs(file, G.sce); + BLI_path_abs(file, G.main->name); if(!BLI_exists(file)) return 2; @@ -2607,7 +2975,7 @@ static void text_ignore_modified(Text *text) if(!text || !text->name) return; BLI_strncpy(file, text->name, FILE_MAXDIR+FILE_MAXFILE); - BLI_path_abs(file, G.sce); + BLI_path_abs(file, G.main->name); if(!BLI_exists(file)) return; @@ -2639,7 +3007,7 @@ static int resolve_conflict_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } -static int resolve_conflict_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int resolve_conflict_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { Text *text= CTX_data_edit_text(C); uiPopupMenu *pup; @@ -2649,7 +3017,7 @@ static int resolve_conflict_invoke(bContext *C, wmOperator *op, wmEvent *event) case 1: if(text->flags & TXT_ISDIRTY) { /* modified locally and externally, ahhh. offer more possibilites. */ - pup= uiPupMenuBegin(C, "File Modified Outside and Inside Blender", 0); + pup= uiPupMenuBegin(C, "File Modified Outside and Inside Blender", ICON_NULL); layout= uiPupMenuLayout(pup); uiItemEnumO(layout, op->type->idname, "Reload from disk (ignore local changes)", 0, "resolution", RESOLVE_RELOAD); uiItemEnumO(layout, op->type->idname, "Save to disk (ignore outside changes)", 0, "resolution", RESOLVE_SAVE); @@ -2657,7 +3025,7 @@ static int resolve_conflict_invoke(bContext *C, wmOperator *op, wmEvent *event) uiPupMenuEnd(C, pup); } else { - pup= uiPupMenuBegin(C, "File Modified Outside Blender", 0); + pup= uiPupMenuBegin(C, "File Modified Outside Blender", ICON_NULL); layout= uiPupMenuLayout(pup); uiItemEnumO(layout, op->type->idname, "Reload from disk", 0, "resolution", RESOLVE_RELOAD); uiItemEnumO(layout, op->type->idname, "Make text internal (separate copy)", 0, "resolution", RESOLVE_MAKE_INTERNAL); @@ -2666,7 +3034,7 @@ static int resolve_conflict_invoke(bContext *C, wmOperator *op, wmEvent *event) } break; case 2: - pup= uiPupMenuBegin(C, "File Deleted Outside Blender", 0); + pup= uiPupMenuBegin(C, "File Deleted Outside Blender", ICON_NULL); layout= uiPupMenuLayout(pup); uiItemEnumO(layout, op->type->idname, "Make text internal", 0, "resolution", RESOLVE_MAKE_INTERNAL); uiItemEnumO(layout, op->type->idname, "Recreate file", 0, "resolution", RESOLVE_SAVE); @@ -2741,6 +3109,7 @@ void ED_text_undo_step(bContext *C, int step) text_update_edited(text); text_update_cursor_moved(C); + text_drawcache_tag_update(CTX_wm_space_text(C), 1); WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text); } diff --git a/source/blender/editors/space_text/text_python.c b/source/blender/editors/space_text/text_python.c index aee1a7ecfd6..1c75e6f65ca 100644 --- a/source/blender/editors/space_text/text_python.c +++ b/source/blender/editors/space_text/text_python.c @@ -182,7 +182,7 @@ static void confirm_suggestion(Text *text, int skipleft) #define LR_SHIFTKEY 0 #define LR_ALTKEY 0 #define LR_CTRLKEY 0 -#define LR_COMMANDKEY 0 +#define LR_OSKEY 0 // XXX static int doc_scroll= 0; @@ -204,7 +204,7 @@ short do_texttools(SpaceText *st, char ascii, unsigned short evnt, short val) if(tools & TOOL_SUGG_LIST) { if((ascii != '_' && ascii != '*' && ispunct(ascii)) || text_check_whitespace(ascii)) { confirm_suggestion(st->text, 0); - text_update_line_edited(st->text, st->text->curl); + text_update_line_edited(st->text->curl); } else if((st->overwrite && txt_replace_char(st->text, ascii)) || txt_add_char(st->text, ascii)) { get_suggest_prefix(st->text, 0); @@ -230,7 +230,7 @@ short do_texttools(SpaceText *st, char ascii, unsigned short evnt, short val) case MIDDLEMOUSE: if(text_do_suggest_select(st, ar)) { confirm_suggestion(st->text, 0); - text_update_line_edited(st->text, st->text->curl); + text_update_line_edited(st->text->curl); swallow= 1; } else { @@ -248,7 +248,7 @@ short do_texttools(SpaceText *st, char ascii, unsigned short evnt, short val) case RETKEY: if(tools & TOOL_SUGG_LIST) { confirm_suggestion(st->text, 0); - text_update_line_edited(st->text, st->text->curl); + text_update_line_edited(st->text->curl); swallow= 1; draw= 1; } @@ -358,7 +358,7 @@ short do_texttools(SpaceText *st, char ascii, unsigned short evnt, short val) } #if 0 -#ifndef DISABLE_PYTHON +#ifdef WITH_PYTHON /* Run text plugin scripts if enabled */ if(st->doplugins && event && val) { if(BPY_menu_do_shortcut(PYMENU_TEXTPLUGIN, event, qual)) { @@ -388,7 +388,7 @@ short do_textmarkers(SpaceText *st, char ascii, unsigned short evnt, short val) /* Find the next temporary marker */ if(evnt==TABKEY) { int lineno= txt_get_span(text->lines.first, text->curl); - TextMarker *mrk= text->markers.first; + mrk= text->markers.first; while(mrk) { if(!marker && (mrk->flags & TMARK_TEMP)) marker= mrk; if((mrk->flags & TMARK_TEMP) && (mrk->lineno > lineno || (mrk->lineno==lineno && mrk->end > text->curc))) { @@ -430,11 +430,11 @@ short do_textmarkers(SpaceText *st, char ascii, unsigned short evnt, short val) if(s!=c) txt_move_to(text, mrk->lineno, mrk->start+s, 1); if(st->overwrite) { if(txt_replace_char(text, ascii)) - text_update_line_edited(st->text, st->text->curl); + text_update_line_edited(st->text->curl); } else { if(txt_add_char(text, ascii)) { - text_update_line_edited(st->text, st->text->curl); + text_update_line_edited(st->text->curl); } } @@ -459,7 +459,7 @@ short do_textmarkers(SpaceText *st, char ascii, unsigned short evnt, short val) txt_move_to(text, mrk->lineno, mrk->start+c, 0); if(s!=c) txt_move_to(text, mrk->lineno, mrk->start+s, 1); txt_backspace_char(text); - text_update_line_edited(st->text, st->text->curl); + text_update_line_edited(st->text->curl); if(mrk==marker || mrk==nxt) break; mrk= nxt; } @@ -479,7 +479,7 @@ short do_textmarkers(SpaceText *st, char ascii, unsigned short evnt, short val) txt_move_to(text, mrk->lineno, mrk->start+c, 0); if(s!=c) txt_move_to(text, mrk->lineno, mrk->start+s, 1); txt_delete_char(text); - text_update_line_edited(st->text, st->text->curl); + text_update_line_edited(st->text->curl); if(mrk==marker || mrk==nxt) break; mrk= nxt; } |