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
This commit is contained in:
2010-10-13 06:06:39 +00:00
parent 554f4df542
commit 54ffc23cd5
6 changed files with 954 additions and 224 deletions

View File

@@ -4646,6 +4646,7 @@ static void lib_link_screen(FileData *fd, Main *main)
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 @@ void lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *curscene)
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;

View File

@@ -92,6 +92,7 @@ static void text_free(SpaceLink *sl)
SpaceText *stext= (SpaceText*) sl;
stext->text= NULL;
text_free_caches(stext);
}
@@ -104,9 +105,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 +135,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:

View File

@@ -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 @@ 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 +560,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 +590,66 @@ 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;
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;
@@ -583,7 +662,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 +678,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 +696,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 +705,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 +720,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 +736,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,18 +772,307 @@ 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, 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;
DrawCache *drawcache;
text_update_drawcache(st, ar);
drawcache= (DrawCache *)st->drawcache;
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= text->lines.first; pline->next && i>0; i--)
pline= pline->next;
}
return pline;
}
/************************ draw scrollbar *****************************/
static void calc_text_rcts(SpaceText *st, ARegion *ar, rcti *scroll)
{
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 */
@@ -722,10 +1108,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;
@@ -811,78 +1197,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;
line= BLI_findlink(&text->lines, marker->lineno);
glColor3ub(marker->color[0], marker->color[1], marker->color[2]);
x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
y= ar->winy-3;
/* Remove broken markers */
if(marker->end>line->len || marker->start>marker->end) {
BLI_freelinkN(&text->markers, marker);
continue;
}
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;
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;
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;
}
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;
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();
}
/* invisible part of line (before top, after last visible line) */
if(y2 < 0 || y1 > st->top+st->viewlines) continue;
break;
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;
}
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();
}
}
}
@@ -1058,16 +1446,16 @@ 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;
/* Draw the selection */
if(text->curl!=text->sell || text->curc!=text->selc) {
/* 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;
@@ -1106,7 +1494,7 @@ static void draw_cursor(SpaceText *st, ARegion *ar)
else {
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 +1503,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 +1539,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 +1646,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 +1658,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;
@@ -1273,12 +1676,15 @@ void draw_text_main(SpaceText *st, ARegion *ar)
TextLine *tmp;
rcti scroll;
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);
@@ -1291,12 +1697,28 @@ void draw_text_main(SpaceText *st, ARegion *ar)
/* 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 +1727,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 +1749,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,14 +1765,16 @@ 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 */
@@ -1398,6 +1821,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;

View File

@@ -90,12 +90,20 @@ 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, 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();
int text_get_visible_lines(struct SpaceText *st, struct ARegion *ar, 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,

View File

@@ -173,6 +173,7 @@ static int new_exec(bContext *C, wmOperator *op)
st->top= 0;
}
text_drawcache_tag_update(st, 1);
WM_event_add_notifier(C, NC_TEXT|NA_ADDED, text);
return OPERATOR_FINISHED;
@@ -254,6 +255,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);
@@ -315,6 +317,7 @@ static int reload_exec(bContext *C, wmOperator *op)
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;
@@ -357,6 +360,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;
@@ -738,6 +743,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);
@@ -809,6 +816,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);
@@ -840,6 +849,8 @@ static int indent_exec(bContext *C, wmOperator *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);
@@ -874,6 +885,8 @@ static int unindent_exec(bContext *C, wmOperator *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);
@@ -909,6 +922,8 @@ static int line_break_exec(bContext *C, wmOperator *op)
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);
@@ -952,6 +967,8 @@ static int comment_exec(bContext *C, wmOperator *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);
@@ -983,6 +1000,8 @@ static int uncomment_exec(bContext *C, wmOperator *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 +1149,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;
@@ -1317,146 +1337,360 @@ 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, chars, max, chop, curs, loop, endj, found, selc;
char ch;
max= wrap_width(st, ar);
selc= start= chars= endj= curs= found= 0;
end= max;
chop= loop= 1;
for(i=0, j=0; loop; j++) {
/* 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, Text *text,
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, chars, 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= chars= endj= 0;
end= max;
chop= loop= 1;
*charp= 0;
for(i=0, j=0; loop; j++) {
/* 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) {
loop= 0;
break;
}
if(chop) endj= j;
start= end;
end += max;
chop= 0;
}
else if(ch==' ' || ch=='-' || ch=='\0') {
if(j>=oldc) {
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, chars, 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) 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, c);
text->selc= c;
} else {
txt_undo_add_toop(text, UNDO_CTO, lin, text->curc, lin, c);
text->curc= c;
txt_pop_sel(text);
oldc= *charp;
oldl= txt_get_span(text->lines.first, *linep);
max= wrap_width(st, ar);
start= chars= endj= 0;
end= max;
chop= loop= 1;
*charp= 0;
for(i=0, j=0; loop; j++) {
/* 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(endj>=oldc) {
*charp= endj;
loop= 0;
break;
}
if(chop) endj= j;
start= end;
end += max;
chop= 0;
} 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);
} 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((*linep)->prev) {
int visible_lines;
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);
}
*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);
} 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);
} else {
c += target;
if (c > text->sell->len) c= text->sell->len;
if((*linep)->next) {
*linep= (*linep)->next;
*charp= text_get_cursor_rel(st, ar, *linep, 0, col);
} else *charp= (*linep)->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 (!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 +1699,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 +1709,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, text, 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 +1788,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;
}
@@ -1665,6 +1907,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)
@@ -1729,13 +1973,13 @@ 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;
@@ -1756,12 +2000,14 @@ typedef struct TextScroll {
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,6 +2017,7 @@ 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;
@@ -1792,7 +2039,7 @@ static void scroll_apply(bContext *C, wmOperator *op, wmEvent *event)
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]);
screen_skip(st, ar, tsc->delta[1]);
tsc->lines += tsc->delta[1];
@@ -1969,7 +2216,7 @@ static void set_cursor_to_pos(SpaceText *st, ARegion *ar, int x, int y, int sel)
Text *text= st->text;
TextLine **linep;
int *charp;
int w;
int w, tabs;
text_update_character_width(st);
@@ -1987,16 +2234,28 @@ 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, chars, 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;
@@ -2004,12 +2263,14 @@ static void set_cursor_to_pos(SpaceText *st, ARegion *ar, int x, int y, int sel)
chars= 0;
curs= 0;
endj= 0;
tabs= 0;
for(i=0, j=0; loop; j++) {
/* Mimic replacement of tabs */
ch= (*linep)->line[j];
if(ch=='\t') {
chars= st->tabnumber-i%st->tabnumber;
tabs+= chars-1;
ch= ' ';
}
else
@@ -2021,22 +2282,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) (*charp)= endj;
loop= 0;
break;
}
if(chop) endj= j;
y--;
start= end;
end += max;
if(start-tabs<(*linep)->len)
y--;
chop= 1;
if(y==0 && i-start>=x) {
*charp= curs;
@@ -2045,6 +2318,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;
@@ -2102,7 +2380,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);
@@ -2290,6 +2568,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) {
@@ -2396,6 +2676,7 @@ 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];
@@ -2741,6 +3022,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);
}

View File

@@ -318,6 +318,8 @@ typedef struct SpaceText {
char findstr[256]; /* ST_MAX_FIND_STR */
char replacestr[256]; /* ST_MAX_FIND_STR */
void *drawcache; /* cache for faster drawing */
} SpaceText;
typedef struct Script {