[Bf-blender-cvs] [066df84] master: Fix T46340: Auto scrolling in text editor with upward selection not work.

Bastien Montagne noreply at git.blender.org
Thu Oct 1 15:34:49 CEST 2015


Commit: 066df84f730d213c3e6ea875c202aa46cf1a6642
Author: Bastien Montagne
Date:   Thu Oct 1 15:27:11 2015 +0200
Branches: master
https://developer.blender.org/rB066df84f730d213c3e6ea875c202aa46cf1a6642

Fix T46340: Auto scrolling in text editor with upward selection not work.

Cleanup and rework a bit text_cursor_set_to_pos_wrapped(), it did not handle correctly negative y valuesi,
because it was only checking lines starting from first visible one.

Mostly, we now directly get line matching given y position (be it an invisible one) from the helper
(renamed `get_line_pos_wrapped()`), instead of first visible one, which allows us to get rid of
additional complexity of looping over next lines until we find correct one.

This code remains rather complex to follow, added some asserts to ensure everything works as expected,
and tested it rather seriously, but DO NOT backport this to 2.76!

===================================================================

M	source/blender/editors/space_text/text_ops.c

===================================================================

diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 543fa0a..060bf24 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -2367,21 +2367,23 @@ static int flatten_column_to_offset(SpaceText *st, const char *str, int index)
 	return j;
 }
 
-static TextLine *get_first_visible_line(SpaceText *st, ARegion *ar, int *y)
+static TextLine *get_line_pos_wrapped(SpaceText *st, ARegion *ar, int *y)
 {
 	TextLine *linep = st->text->lines.first;
-	int i;
-	for (i = st->top; i > 0 && linep; ) {
-		int lines = text_get_visible_lines(st, ar, linep->line);
-		
-		if (i - lines < 0) {
-			*y += i;
+	int i, lines;
+
+	if (*y < -st->top) {
+		return NULL;  /* We are beyond the first line... */
+	}
+
+	for (i = -st->top; i <= *y && linep; linep = linep->next, i += lines) {
+		lines = text_get_visible_lines(st, ar, linep->line);
+
+		if (i + lines > *y) {
+			/* We found the line matching given vertical 'coordinate', now set y relative to this line's start. */
+			*y -= i;
 			break;
 		}
-		else {
-			linep = linep->next;
-			i -= lines;
-		}
 	}
 	return linep;
 }
@@ -2391,23 +2393,22 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in
 	Text *text = st->text;
 	int max = wrap_width(st, ar); /* column */
 	int charp = -1;               /* mem */
-	int loop = 1, found = 0;      /* flags */
-	char ch;
-	
-	/* Point to first visible line */
-	TextLine *linep = get_first_visible_line(st, ar, &y);
+	bool found = false;           /* flags */
 	
-	while (loop && linep) {
+	/* Point to line matching given y position, if any. */
+	TextLine *linep = get_line_pos_wrapped(st, ar, &y);
+
+	if (linep) {
 		int i = 0, start = 0, end = max; /* column */
-		int j = 0, curs = 0, endj = 0;   /* mem */
-		int chop = 1;                    /* flags */
-		
-		for (; loop; j += BLI_str_utf8_size_safe(linep->line + j)) {
+		int j, curs = 0, endj = 0;       /* mem */
+		bool chop = true;                /* flags */
+		char ch;
+
+		for (j = 0 ; !found && ((ch = linep->line[j]) != '\0'); j += BLI_str_utf8_size_safe(linep->line + j)) {
 			int chars;
 			int columns = BLI_str_utf8_char_width_safe(linep->line + j); /* = 1 for tab */
 			
 			/* Mimic replacement of tabs */
-			ch = linep->line[j];
 			if (ch == '\t') {
 				chars = st->tabnumber - i % st->tabnumber;
 				ch = ' ';
@@ -2420,7 +2421,8 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in
 				/* Gone too far, go back to last wrap point */
 				if (y < 0) {
 					charp = endj;
-					loop = 0;
+					y = 0;
+					found = true;
 					break;
 					/* Exactly at the cursor */
 				}
@@ -2428,7 +2430,7 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in
 					/* current position could be wrapped to next line */
 					/* this should be checked when end of current line would be reached */
 					charp = curs = j;
-					found = 1;
+					found = true;
 					/* Prepare curs for next wrap */
 				}
 				else if (i - end <= x && i + columns - end > x) {
@@ -2438,68 +2440,70 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in
 					end = MIN2(end, i);
 					
 					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;
+						/* 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;
 						break;
 					}
 					
-					if (chop) endj = j;
+					if (chop)
+						endj = j;
 					start = end;
 					end += max;
 					
 					if (j < linep->len)
 						y--;
 					
-					chop = 1;
+					chop = true;
 					if (y == 0 && i + columns - start > x) {
 						charp = curs;
-						loop = 0;
+						found = true;
 						break;
 					}
 				}
 				else if (ch == ' ' || ch == '-' || ch == '\0') {
 					if (found) {
-						loop = 0;
 						break;
 					}
 					
 					if (y == 0 && i + columns - start > x) {
 						charp = curs;
-						loop = 0;
+						found = true;
 						break;
 					}
 					end = i + 1;
 					endj = j;
-					chop = 0;
+					chop = false;
 				}
 				i += columns;
 			}
-			
-			if (ch == '\0') break;
-		}
-		
-		if (!loop || found) break;
-		
-		if (!linep->next) {
-			charp = linep->len;
-			break;
 		}
+
+		BLI_assert(y == 0);
 		
-		/* On correct line but didn't meet cursor, must be at end */
-		if (y == 0) {
+		if (!found) {
+			/* On correct line but didn't meet cursor, must be at end */
 			charp = linep->len;
-			break;
 		}
-		linep = linep->next;
-		
-		y--;
+	}
+	else if (y < 0) {  /* Before start of text. */
+		linep = st->text->lines.first;
+		charp = 0;
+	}
+	else {  /* Beyond end of text */
+		linep = st->text->lines.last;
+		charp = linep->len;
 	}
 
-	if (linep && charp != -1) {
-		if (sel) { text->sell = linep; text->selc = charp; }
-		else     { text->curl = linep; text->curc = charp; }
+	BLI_assert(linep && charp != -1);
+
+	if (sel) {
+		text->sell = linep;
+		text->selc = charp;
+	}
+	else {
+		text->curl = linep;
+		text->curc = charp;
 	}
 }




More information about the Bf-blender-cvs mailing list