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); }
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_dpi; /* 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_dpi; 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; }
/* Sets (offl, offc) for transforming (line, curs) to its wrapped position */ void wrap_offset(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int *offl, int *offc) { Text *text; TextLine *linep; int i, j, start, end, max, chop; char ch; *offl = *offc = 0; if (!st->text) return; if (!st->wordwrap) return; text = st->text; /* Move pointer to first visible line (top) */ linep = text->lines.first; i = st->top; while (i > 0 && linep) { 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); cursin = txt_utf8_offset_to_column(linein->line, cursin); while (linep) { start = 0; end = max; chop = 1; *offc = 0; for (i = 0, j = 0; linep->line[j]; 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; if (linep == linein && i < cursin) cursin += chars - 1; ch = ' '; } else { chars = 1; } while (chars--) { if (i + columns - start > max) { end = MIN2(end, i); if (chop && linep == linein && 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 (linep == linein && i >= cursin) return; } i += columns; } } if (linep == linein) break; linep = linep->next; } }
static void draw_cursor(SpaceText *st, ARegion *ar) { Text *text = st->text; int vcurl, vcurc, vsell, vselc, hidden = 0; int x, y, w, i; const int lheight = st->lheight_dpi + TXT_LINE_SPACING; /* 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 = 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 = 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; UI_ThemeColor(TH_SHADE2); x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; y = ar->winy; if (vcurl == vsell) { y -= vcurl * lheight; if (vcurc < vselc) glRecti(x + vcurc * st->cwidth - 1, y, x + vselc * st->cwidth, y - lheight); else glRecti(x + vselc * st->cwidth - 1, y, x + vcurc * st->cwidth, y - lheight); } else { int froml, fromc, tol, toc; if (vcurl < vsell) { froml = vcurl; tol = vsell; fromc = vcurc; toc = vselc; } else { froml = vsell; tol = vcurl; fromc = vselc; toc = vcurc; } y -= froml * lheight; glRecti(x + fromc * st->cwidth - 1, y, ar->winx, y - lheight); y -= lheight; for (i = froml + 1; i < tol; i++) glRecti(x - 4, y, ar->winx, y - lheight), y -= lheight; glRecti(x - 4, y, x + toc * st->cwidth, y - lheight); y -= lheight; } } 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 = text_get_char_pos(st, text->sell->line, text->selc) - st->left + offc; if (vselc < 0) { vselc = 0; hidden = 1; } } if (st->line_hlight) { 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 - (vsell - offl) * lheight; y2 = y1 - (lheight * visible_lines); } else { y1 = ar->winy - vsell * lheight; y2 = y1 - (lheight); } if (!(y1 < 0 || y2 > ar->winy)) { /* check we need to draw */ x1 = 0; // 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, y1, x2, y2); glDisable(GL_BLEND); } } if (!hidden) { /* Draw the cursor itself (we draw the sel. cursor as this is the leading edge) */ x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; x += vselc * st->cwidth; y = ar->winy - vsell * lheight; if (st->overwrite) { char ch = text->sell->line[text->selc]; y += TXT_LINE_SPACING; w = st->cwidth; if (ch == '\t') w *= st->tabnumber - (vselc + st->left) % st->tabnumber; UI_ThemeColor(TH_HILITE); glRecti(x, y - lheight - 1, x + w, y - lheight + 1); } else { UI_ThemeColor(TH_HILITE); glRecti(x - 1, y, x + 1, y - lheight); } } }
/* Sets (offl, offc) for transforming (line, curs) to its wrapped position */ void wrap_offset(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int *offl, int *offc) { Text *text; TextLine *linep; int i, j, start, end, chars, max, chop; char ch; *offl= *offc= 0; if(!st->text) return; if(!st->wordwrap) return; text= st->text; /* Move pointer to first visible line (top) */ linep= text->lines.first; i= st->top; while(i>0 && linep) { 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); while(linep) { start= 0; end= max; chop= 1; chars= 0; *offc= 0; for(i=0, j=0; linep->line[j]!='\0'; j++) { /* Mimic replacement of tabs */ ch= linep->line[j]; if(ch=='\t') { chars= st->tabnumber-i%st->tabnumber; if(linep==linein && i<cursin) cursin += chars-1; ch= ' '; } else chars= 1; while(chars--) { if(i-start>=max) { if(chop && linep==linein && 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(linep==linein && i >= cursin) return; } i++; } } if(linep==linein) break; linep= linep->next; } }