[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [32441] trunk/blender/source/blender: Text space

Sergey Sharybin g.ulairi at gmail.com
Wed Oct 13 08:06:40 CEST 2010


Revision: 32441
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=32441
Author:   nazgul
Date:     2010-10-13 08:06:39 +0200 (Wed, 13 Oct 2010)

Log Message:
-----------
Text space
==========

Main changes:
- lines could be partially shown when they starts somewhere behind the upper
  boundary of area but because of word-wrapping some part of line will be show
- fixed caret navigatiog in area when tabs aren't replaced by spaces
- highlight the whole current line not only it's wrapped segment with caret
- when you're in replace mode cursor would be as long as the tab's width if it's under tab symbol

This fixes:
  #22399: Text Editor: word-wrapped lines prevent navigating through text with up-arrow.
  #21163: Text editor scrollbar problem with word wrap

Modified Paths:
--------------
    trunk/blender/source/blender/blenloader/intern/readfile.c
    trunk/blender/source/blender/editors/space_text/space_text.c
    trunk/blender/source/blender/editors/space_text/text_draw.c
    trunk/blender/source/blender/editors/space_text/text_intern.h
    trunk/blender/source/blender/editors/space_text/text_ops.c
    trunk/blender/source/blender/makesdna/DNA_space_types.h

Modified: trunk/blender/source/blender/blenloader/intern/readfile.c
===================================================================
--- trunk/blender/source/blender/blenloader/intern/readfile.c	2010-10-13 04:00:01 UTC (rev 32440)
+++ trunk/blender/source/blender/blenloader/intern/readfile.c	2010-10-13 06:06:39 UTC (rev 32441)
@@ -4646,6 +4646,7 @@
 						SpaceText *st= (SpaceText *)sl;
 
 						st->text= newlibadr(fd, sc->id.lib, st->text);
+						st->drawcache= NULL;
 
 					}
 					else if(sl->spacetype==SPACE_SCRIPT) {
@@ -4877,6 +4878,8 @@
 
 					st->text= restore_pointer_by_name(newmain, (ID *)st->text, 1);
 					if(st->text==NULL) st->text= newmain->text.first;
+
+					st->drawcache= NULL;
 				}
 				else if(sl->spacetype==SPACE_SCRIPT) {
 					SpaceScript *scpt= (SpaceScript *)sl;

Modified: trunk/blender/source/blender/editors/space_text/space_text.c
===================================================================
--- trunk/blender/source/blender/editors/space_text/space_text.c	2010-10-13 04:00:01 UTC (rev 32440)
+++ trunk/blender/source/blender/editors/space_text/space_text.c	2010-10-13 06:06:39 UTC (rev 32441)
@@ -92,6 +92,7 @@
 	SpaceText *stext= (SpaceText*) sl;
 	
 	stext->text= NULL;
+	text_free_caches(stext);
 }
 
 
@@ -104,9 +105,11 @@
 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 +135,11 @@
 
 			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:

Modified: trunk/blender/source/blender/editors/space_text/text_draw.c
===================================================================
--- trunk/blender/source/blender/editors/space_text/text_draw.c	2010-10-13 04:00:01 UTC (rev 32440)
+++ trunk/blender/source/blender/editors/space_text/text_draw.c	2010-10-13 06:06:39 UTC (rev 32441)
@@ -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
@@ -521,9 +520,22 @@
 	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 +560,18 @@
 
 			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,8 +590,67 @@
 	}
 }
 
-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;
+	chars= 0;
+	*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, char *line, int cur)
+{
 	int a=0, i;
 	
 	for(i=0; i<cur && line[i]; i++) {
@@ -583,7 +662,7 @@
 	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 +678,14 @@
 	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 +696,8 @@
 			lines++;
 			start= end;
 			end += max;
+
+			if(y<=0) break;
 		}
 		else if(str[i]==' ' || str[i]=='-') {
 			end = i+1;
@@ -616,7 +705,7 @@
 	}
 
 	/* 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 +720,7 @@
 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 +736,26 @@
 
 	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,18 +772,307 @@
 		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 */

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list