/* Moves the view to the cursor location, * also used to make sure the view isn't outside the file */ void text_scroll_to_cursor(SpaceText *st, ARegion *ar, const bool center) { Text *text; int i, x, winx = ar->winx; if (ELEM(NULL, st, st->text, st->text->curl)) return; text = st->text; text_update_character_width(st); i = txt_get_span(text->lines.first, text->sell); if (st->wordwrap) { int offl, offc; wrap_offset(st, ar, text->sell, text->selc, &offl, &offc); i += offl; } if (center) { if (st->top + st->viewlines <= i || st->top > i) { st->top = i - st->viewlines / 2; } } else { if (st->top + st->viewlines <= i) { st->top = i - (st->viewlines - 1); } else if (st->top > i) { st->top = i; } } if (st->wordwrap) { st->left = 0; } else { x = st->cwidth * (text_get_char_pos(st, text->sell->line, text->selc) - st->left); winx -= TXT_OFFSET + (st->showlinenrs ? TEXTXLOC : 0) + TXT_SCROLL_WIDTH; if (center) { if (x <= 0 || x > winx) { st->left += (x - winx / 2) / st->cwidth; } } else { if (x <= 0) { st->left += ((x + 1) / st->cwidth) - 1; } else if (x > winx) { st->left += ((x - (winx + 1)) / st->cwidth) + 1; } } } if (st->top < 0) st->top = 0; if (st->left < 0) st->left = 0; st->scroll_accum[0] = 0.0f; st->scroll_accum[1] = 0.0f; }
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); }
/* Moves the view to the cursor location, also used to make sure the view isnt outside the file */ void text_update_cursor_moved(bContext *C) { ScrArea *sa= CTX_wm_area(C); SpaceText *st= CTX_wm_space_text(C); Text *text; ARegion *ar; int i, x, winx= 0; if(ELEM3(NULL, st, st->text, st->text->curl)) return; text= st->text; for(ar=sa->regionbase.first; ar; ar= ar->next) if(ar->regiontype==RGN_TYPE_WINDOW) winx= ar->winx; winx -= TXT_SCROLL_WIDTH; 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; if(st->wordwrap) { st->left= 0; } else { x= text_draw(st, text->sell->line, st->left, text->selc, 0, 0, 0, NULL); if(x==0 || x>winx) st->left= text->curc-0.5*winx/st->cwidth; } if(st->top < 0) st->top= 0; if(st->left <0) st->left= 0; }
/* Moves the view to the cursor location, * also used to make sure the view isn't outside the file */ void text_scroll_to_cursor(SpaceText *st, ScrArea *sa) { Text *text; ARegion *ar = NULL; int i, x, winx = 0; if (ELEM3(NULL, st, st->text, st->text->curl)) return; text = st->text; for (ar = sa->regionbase.first; ar; ar = ar->next) if (ar->regiontype == RGN_TYPE_WINDOW) { winx = ar->winx; break; } text_update_character_width(st); i = txt_get_span(text->lines.first, text->sell); if (st->wordwrap) { int offl, offc; wrap_offset(st, ar, text->sell, text->selc, &offl, &offc); i += offl; } if (st->top + st->viewlines <= i || st->top > i) st->top = i - st->viewlines / 2; if (st->wordwrap) { st->left = 0; } else { x = st->cwidth * (text_get_char_pos(st, text->sell->line, text->selc) - st->left); winx -= TXT_OFFSET + (st->showlinenrs ? TEXTXLOC : 0) + TXT_SCROLL_WIDTH; if (x <= 0 || x > winx) st->left += (x - winx / 2) / st->cwidth; } if (st->top < 0) st->top = 0; if (st->left < 0) st->left = 0; }
static void draw_suggestion_list(SpaceText *st, ARegion *ar) { SuggItem *item, *first, *last, *sel; char str[SUGG_LIST_WIDTH * BLI_UTF8_MAX + 1]; int offl, offc, vcurl, vcurc; int w, boxw = 0, boxh, i, x, y, *top; const int lheight = st->lheight_dpi + TXT_LINE_SPACING; const int margin_x = 2; if (!st->text) return; if (!texttool_text_is_active(st->text)) return; first = texttool_suggest_first(); last = texttool_suggest_last(); if (!first || !last) return; text_pop_suggest_list(); sel = texttool_suggest_selected(); top = texttool_suggest_top(); wrap_offset(st, ar, st->text->curl, st->text->curc, &offl, &offc); vcurl = txt_get_span(st->text->lines.first, st->text->curl) - st->top + offl; vcurc = text_get_char_pos(st, st->text->curl->line, st->text->curc) - st->left + offc; x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; x += vcurc * st->cwidth - 4; y = ar->winy - (vcurl + 1) * lheight - 2; /* offset back so the start of the text lines up with the suggestions, * not essential but makes suggestions easier to follow */ x -= st->cwidth * (st->text->curc - text_find_identifier_start(st->text->curl->line, st->text->curc)); boxw = SUGG_LIST_WIDTH * st->cwidth + 20; boxh = SUGG_LIST_SIZE * lheight + 8; if (x + boxw > ar->winx) x = MAX2(0, ar->winx - boxw); /* not needed but stands out nicer */ uiDrawBoxShadow(220, x, y - boxh, x + boxw, y); UI_ThemeColor(TH_SHADE1); glRecti(x - 1, y + 1, x + boxw + 1, y - boxh - 1); UI_ThemeColorShade(TH_BACK, 16); glRecti(x, y, x + boxw, y - boxh); /* Set the top 'item' of the visible list */ for (i = 0, item = first; i < *top && item->next; i++, item = item->next) ; for (i = 0; i < SUGG_LIST_SIZE && item; i++, item = item->next) { int len = txt_utf8_forward_columns(item->name, SUGG_LIST_WIDTH, NULL) - item->name; y -= lheight; BLI_strncpy(str, item->name, len + 1); w = st->cwidth * text_get_char_pos(st, str, len); if (item == sel) { UI_ThemeColor(TH_SHADE2); glRecti(x + margin_x, y - 3, x + margin_x + w, y + lheight - 3); } format_draw_color(item->type); text_draw(st, str, 0, 0, x + margin_x, y - 1, NULL); if (item == last) break; } }
static void draw_brackets(SpaceText *st, ARegion *ar) { TextLine *startl, *endl, *linep; Text *text = st->text; int b, fc, find, stack, viewc, viewl, offl, offc, x, y; int startc, endc, c; char ch; // showsyntax must be on or else the format string will be null if (!text->curl || !st->showsyntax) return; startl = text->curl; startc = text->curc; b = text_check_bracket(startl->line[startc]); if (b == 0 && startc > 0) b = text_check_bracket(startl->line[--startc]); if (b == 0) return; linep = startl; c = startc; fc = txt_utf8_offset_to_index(linep->line, startc); endl = NULL; endc = -1; find = -b; stack = 0; /* Don't highlight backets if syntax HL is off or bracket in string or comment. */ if (!linep->format || linep->format[fc] == FMT_TYPE_STRING || linep->format[fc] == FMT_TYPE_COMMENT) return; if (b > 0) { /* opening bracket, search forward for close */ fc++; c += BLI_str_utf8_size_safe(linep->line + c); while (linep) { while (c < linep->len) { if (linep->format && linep->format[fc] != FMT_TYPE_STRING && linep->format[fc] != FMT_TYPE_COMMENT) { b = text_check_bracket(linep->line[c]); if (b == find) { if (stack == 0) { endl = linep; endc = c; break; } stack--; } else if (b == -find) { stack++; } } fc++; c += BLI_str_utf8_size_safe(linep->line + c); } if (endl) break; linep = linep->next; c = 0; fc = 0; } } else { /* closing bracket, search backward for open */ fc--; if (c > 0) c -= linep->line + c - BLI_str_prev_char_utf8(linep->line + c); while (linep) { while (fc >= 0) { if (linep->format && linep->format[fc] != FMT_TYPE_STRING && linep->format[fc] != FMT_TYPE_COMMENT) { b = text_check_bracket(linep->line[c]); if (b == find) { if (stack == 0) { endl = linep; endc = c; break; } stack--; } else if (b == -find) { stack++; } } fc--; if (c > 0) c -= linep->line + c - BLI_str_prev_char_utf8(linep->line + c); } if (endl) break; linep = linep->prev; if (linep) { if (linep->format) fc = strlen(linep->format) - 1; else fc = -1; if (linep->len) c = BLI_str_prev_char_utf8(linep->line + linep->len) - linep->line; else fc = -1; } } } if (!endl || endc == -1) return; UI_ThemeColor(TH_HILITE); x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; y = ar->winy - st->lheight_dpi; /* draw opening bracket */ ch = startl->line[startc]; wrap_offset(st, ar, startl, startc, &offl, &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; text_font_draw_character(st, x + viewc * st->cwidth, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch); text_font_draw_character(st, x + viewc * st->cwidth + 1, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch); } /* draw closing bracket */ ch = endl->line[endc]; wrap_offset(st, ar, endl, endc, &offl, &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; text_font_draw_character(st, x + viewc * st->cwidth, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch); text_font_draw_character(st, x + viewc * st->cwidth + 1, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch); } }
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); } } }
static void draw_brackets(SpaceText *st, ARegion *ar) { TextLine *startl, *endl, *linep; Text *text = st->text; int b, c, startc, endc, find, stack; int viewc, viewl, offl, offc, x, y; char ch; // showsyntax must be on or else the format string will be null if(!text->curl || !st->showsyntax) return; startl= text->curl; startc= text->curc; b= text_check_bracket(startl->line[startc]); if(b==0 && startc>0) b = text_check_bracket(startl->line[--startc]); if(b==0) return; linep= startl; c= startc; endl= NULL; endc= -1; find= -b; stack= 0; /* Dont highlight backets if syntax HL is off or bracket in string or comment. */ if(!linep->format || linep->format[c] == 'l' || linep->format[c] == '#') return; if(b>0) { /* opening bracket, search forward for close */ c++; while(linep) { while(c<linep->len) { if(linep->format && linep->format[c] != 'l' && linep->format[c] != '#') { b= text_check_bracket(linep->line[c]); if(b==find) { if(stack==0) { endl= linep; endc= c; break; } stack--; } else if(b==-find) { stack++; } } c++; } if(endl) break; linep= linep->next; c= 0; } } else { /* closing bracket, search backward for open */ c--; while(linep) { while(c>=0) { if(linep->format && linep->format[c] != 'l' && linep->format[c] != '#') { b= text_check_bracket(linep->line[c]); if(b==find) { if(stack==0) { endl= linep; endc= c; break; } stack--; } else if(b==-find) { stack++; } } c--; } if(endl) break; linep= linep->prev; if(linep) c= linep->len-1; } } if(!endl || endc==-1) return; UI_ThemeColor(TH_HILITE); x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; y= ar->winy - st->lheight; /* draw opening bracket */ ch= startl->line[startc]; wrap_offset(st, ar, startl, startc, &offl, &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; text_font_draw_character(st, x+viewc*st->cwidth, y-viewl*st->lheight, ch); text_font_draw_character(st, x+viewc*st->cwidth+1, y-viewl*st->lheight, ch); } /* draw closing bracket */ ch= endl->line[endc]; wrap_offset(st, ar, endl, endc, &offl, &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; text_font_draw_character(st, x+viewc*st->cwidth, y-viewl*st->lheight, ch); text_font_draw_character(st, x+viewc*st->cwidth+1, y-viewl*st->lheight, ch); } }
static void draw_markers(SpaceText *st, ARegion *ar) { Text *text= st->text; TextMarker *marker, *next; TextLine *top, *line; int offl, offc, i, x1, x2, y1, y2, x, y; int topi, topy; /* 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(marker= text->markers.first; marker; marker= next) { next= marker->next; /* invisible line (before top) */ if(marker->lineno<topi) continue; line= BLI_findlink(&text->lines, marker->lineno); /* Remove broken markers */ if(marker->end>line->len || marker->start>marker->end) { BLI_freelinkN(&text->markers, marker); continue; } 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; } 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(); } } }