Fix #19580: text editor - current line is dependent on the
[blender-staging.git] / source / blender / editors / space_text / text_draw.c
index 456060d77a7cd8e13a5daf99e5ff2eb39a15931e..b74e1f6cfb2301a3d7d7a90ea8c8d24ae8409b54 100644 (file)
@@ -41,7 +41,9 @@
 #include "DNA_text_types.h"
 #include "DNA_space_types.h"
 #include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
 
+#include "BKE_context.h"
 #include "BKE_global.h"
 #include "BKE_main.h"
 #include "BKE_suggestions.h"
@@ -94,13 +96,7 @@ static int text_font_draw_character(SpaceText *st, int x, int y, char c)
        BLF_position(x, y, 0);
        BLF_draw(str);
 
-       return text_font_width_character(st);
-}
-
-int text_font_width_character(SpaceText *st)
-{
-       // XXX need quick BLF function, or cache it somewhere
-       return (st->lheight == 12)? 7: 8;
+       return st->cwidth;
 }
 
 int text_font_width(SpaceText *st, char *str)
@@ -114,22 +110,18 @@ static void flatten_string_append(FlattenString *fs, char c, int accum)
 {
        if(fs->pos>=fs->len && fs->pos>=sizeof(fs->fixedbuf)-1) {
                char *nbuf; int *naccum;
-               int olen= fs->len;
-               
-               if(olen) fs->len*= 2;
-               else fs->len= 256;
-               
-               nbuf= MEM_mallocN(sizeof(*fs->buf)*fs->len, "fs->buf");
-               naccum= MEM_mallocN(sizeof(*fs->accum)*fs->len, "fs->accum");
+               if(fs->len) fs->len*= 2;
+               else fs->len= sizeof(fs->fixedbuf) * 2;
+
+               nbuf= MEM_callocN(sizeof(*fs->buf)*fs->len, "fs->buf");
+               naccum= MEM_callocN(sizeof(*fs->accum)*fs->len, "fs->accum");
+
+               memcpy(nbuf, fs->buf, fs->pos);
+               memcpy(naccum, fs->accum, fs->pos);
                
-               if(olen) {
-                       memcpy(nbuf, fs->buf, olen);
-                       memcpy(naccum, fs->accum, olen);
-                       
-                       if(fs->buf != fs->fixedbuf) {
-                               MEM_freeN(fs->buf);
-                               MEM_freeN(fs->accum);
-                       }
+               if(fs->buf != fs->fixedbuf) {
+                       MEM_freeN(fs->buf);
+                       MEM_freeN(fs->accum);
                }
                
                fs->buf= nbuf;
@@ -139,8 +131,7 @@ static void flatten_string_append(FlattenString *fs, char c, int accum)
        fs->buf[fs->pos]= c;    
        fs->accum[fs->pos]= accum;
        
-       if(c==0) fs->pos= 0;
-       else fs->pos++;
+       fs->pos++;
 }
 
 int flatten_string(SpaceText *st, FlattenString *fs, char *in)
@@ -435,60 +426,6 @@ static void format_draw_color(char formatchar)
        }
 }
 
-/*********************** utilities ************************/
-
-int text_check_bracket(char ch)
-{
-       int a;
-       char opens[] = "([{";
-       char close[] = ")]}";
-       
-       for(a=0; a<3; a++) {
-               if(ch==opens[a])
-                       return a+1;
-               else if(ch==close[a])
-                       return -(a+1);
-       }
-       return 0;
-}
-
-int text_check_delim(char ch) 
-{
-       int a;
-       char delims[] = "():\"\' ~!%^&*-+=[]{};/<>|.#\t,";
-       
-       for(a=0; a<28; a++) {
-               if(ch==delims[a])
-                       return 1;
-       }
-       return 0;
-}
-
-int text_check_digit(char ch)
-{
-       if(ch < '0') return 0;
-       if(ch <= '9') return 1;
-       return 0;
-}
-
-int text_check_identifier(char ch)
-{
-       if(ch < '0') return 0;
-       if(ch <= '9') return 1;
-       if(ch < 'A') return 0;
-       if(ch <= 'Z' || ch == '_') return 1;
-       if(ch < 'a') return 0;
-       if(ch <= 'z') return 1;
-       return 0;
-}
-
-int text_check_whitespace(char ch)
-{
-       if(ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')
-               return 1;
-       return 0;
-}
-
 /************************** draw text *****************************/
 
 /***********************/ /*
@@ -522,7 +459,7 @@ int wrap_width(SpaceText *st, ARegion *ar)
        int x, max;
        
        x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
-       max= (ar->winx-x)/text_font_width_character(st);
+       max= (ar->winx-x)/st->cwidth;
        return max>8 ? max : 8;
 }
 
@@ -614,7 +551,7 @@ static int text_draw_wrapped(SpaceText *st, char *str, int x, int y, int w, char
        
        len= flatten_string(st, &fs, str);
        str= fs.buf;
-       max= w/text_font_width_character(st);
+       max= w/st->cwidth;
        if(max<8) max= 8;
        basex= x;
 
@@ -686,7 +623,7 @@ static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int dra
        }
        else {
                while(w-- && *acc++ < maxwidth)
-                       r+= text_font_width_character(st);
+                       r+= st->cwidth;
        }
 
        flatten_string_free(&fs);
@@ -701,7 +638,7 @@ static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int dra
 
 /************************ draw scrollbar *****************************/
 
-static void calc_text_rcts(SpaceText *st, ARegion *ar)
+static void calc_text_rcts(SpaceText *st, ARegion *ar, rcti *scroll)
 {
        int lhlstart, lhlend, ltexth;
        short barheight, barstart, hlstart, hlend, blank_lines;
@@ -713,6 +650,14 @@ static void calc_text_rcts(SpaceText *st, ARegion *ar)
        ltexth= txt_get_span(st->text->lines.first, st->text->lines.last);
        blank_lines = st->viewlines / 2;
        
+       /* nicer code: use scroll rect for entire bar */
+       //scroll->xmin= 5;
+       //scroll->xmax= 17;
+       scroll->xmin= ar->winx - 17;
+       scroll->xmax= ar->winx - 5;
+       scroll->ymin= 4;
+       scroll->ymax= 4+pix_available;
+       
        /* when resizing a vieport with the bar at the bottom to a greater height more blank lines will be added */
        if(ltexth + blank_lines < st->top + st->viewlines) {
                blank_lines = st->top + st->viewlines - ltexth;
@@ -728,9 +673,8 @@ static void calc_text_rcts(SpaceText *st, ARegion *ar)
        }
        barstart = (ltexth > 0)? ((pix_available - pix_bardiff) * st->top)/ltexth: 0;
 
-       st->txtbar.xmin = 5;
-       st->txtbar.xmax = 17;
-       st->txtbar.ymax = ar->winy - pix_top_margin - barstart;
+       st->txtbar= *scroll;
+       st->txtbar.ymax -= barstart;
        st->txtbar.ymin = st->txtbar.ymax - barheight;
 
        CLAMP(st->txtbar.ymin, pix_bottom_margin, ar->winy - pix_top_margin);
@@ -796,8 +740,7 @@ static void calc_text_rcts(SpaceText *st, ARegion *ar)
                hlend = hlstart + 2;
        }
        
-       st->txtscroll.xmin= 5;
-       st->txtscroll.xmax= 17;
+       st->txtscroll= *scroll;
        st->txtscroll.ymax= ar->winy - pix_top_margin - hlstart;
        st->txtscroll.ymin= ar->winy - pix_top_margin - hlend;
 
@@ -805,19 +748,22 @@ static void calc_text_rcts(SpaceText *st, ARegion *ar)
        CLAMP(st->txtscroll.ymax, pix_bottom_margin, ar->winy - pix_top_margin);
 }
 
-static void draw_textscroll(SpaceText *st, ARegion *ar)
+static void draw_textscroll(SpaceText *st, ARegion *ar, rcti *scroll)
 {
-       UI_ThemeColorShade(TH_SHADE1, -20);
-       glRecti(2, 2, 20, ar->winy-6);
-       uiEmboss(2, 2, 20, ar->winy-6, 1);
-
-       UI_ThemeColor(TH_SHADE1);
-       glRecti(st->txtbar.xmin, st->txtbar.ymin, st->txtbar.xmax, st->txtbar.ymax);
-
-       UI_ThemeColor(TH_SHADE2);
-       glRecti(st->txtscroll.xmin, st->txtscroll.ymin, st->txtscroll.xmax, st->txtscroll.ymax);
-
-       uiEmboss(st->txtbar.xmin, st->txtbar.ymin, st->txtbar.xmax, st->txtbar.ymax, st->flags & ST_SCROLL_SELECT);
+       bTheme *btheme= U.themes.first;
+       uiWidgetColors wcol= btheme->tui.wcol_scroll;
+       char col[3];
+       float rad;
+       
+       uiWidgetScrollDraw(&wcol, scroll, &st->txtbar, (st->flags & ST_SCROLL_SELECT)?UI_SCROLL_PRESSED:0);
+
+       uiSetRoundBox(15);
+       rad= 0.4f*MIN2(st->txtscroll.xmax - st->txtscroll.xmin, st->txtscroll.ymax - st->txtscroll.ymin);
+       UI_GetThemeColor3ubv(TH_HILITE, col);
+       glColor4ub(col[0], col[1], col[2], 48);
+       glEnable(GL_BLEND);
+       uiRoundBox(st->txtscroll.xmin+1, st->txtscroll.ymin, st->txtscroll.xmax-1, st->txtscroll.ymax, rad);
+       glDisable(GL_BLEND);
 }
 
 /************************** draw markers **************************/
@@ -860,18 +806,18 @@ static void draw_markers(SpaceText *st, ARegion *ar)
                                if(y1==y2) {
                                        y -= y1*st->lheight;
                                        glBegin(GL_LINE_LOOP);
-                                       glVertex2i(x+x2*text_font_width_character(st)+1, y);
-                                       glVertex2i(x+x1*text_font_width_character(st)-2, y);
-                                       glVertex2i(x+x1*text_font_width_character(st)-2, y-st->lheight);
-                                       glVertex2i(x+x2*text_font_width_character(st)+1, y-st->lheight);
+                                       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*text_font_width_character(st)-2, y);
-                                       glVertex2i(x+x1*text_font_width_character(st)-2, y-st->lheight);
+                                       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;
@@ -888,8 +834,8 @@ static void draw_markers(SpaceText *st, ARegion *ar)
 
                                        glBegin(GL_LINE_STRIP);
                                        glVertex2i(x, y);
-                                       glVertex2i(x+x2*text_font_width_character(st)+1, y);
-                                       glVertex2i(x+x2*text_font_width_character(st)+1, y-st->lheight);
+                                       glVertex2i(x+x2*st->cwidth+1, y);
+                                       glVertex2i(x+x2*st->cwidth+1, y-st->lheight);
                                        glVertex2i(x, y-st->lheight);
                                        glEnd();
                                }
@@ -923,18 +869,18 @@ static void draw_documentation(SpaceText *st, ARegion *ar)
        if(l<0) return;
        
        if(st->showlinenrs) {
-               x= text_font_width_character(st)*(st->text->curc-st->left) + TXT_OFFSET + TEXTXLOC - 4;
+               x= st->cwidth*(st->text->curc-st->left) + TXT_OFFSET + TEXTXLOC - 4;
        }
        else {
-               x= text_font_width_character(st)*(st->text->curc-st->left) + TXT_OFFSET - 4;
+               x= st->cwidth*(st->text->curc-st->left) + TXT_OFFSET - 4;
        }
        if(texttool_suggest_first()) {
-               x += SUGG_LIST_WIDTH*text_font_width_character(st) + 50;
+               x += SUGG_LIST_WIDTH*st->cwidth + 50;
        }
 
        top= y= ar->winy - st->lheight*l - 2;
        len= strlen(docs);
-       boxw= DOC_WIDTH*text_font_width_character(st) + 20;
+       boxw= DOC_WIDTH*st->cwidth + 20;
        boxh= (DOC_HEIGHT+1)*st->lheight;
 
        /* Draw panel */
@@ -1017,14 +963,14 @@ static void draw_suggestion_list(SpaceText *st, ARegion *ar)
        if(l<0) return;
        
        if(st->showlinenrs) {
-               x = text_font_width_character(st)*(st->text->curc-st->left) + TXT_OFFSET + TEXTXLOC - 4;
+               x = st->cwidth*(st->text->curc-st->left) + TXT_OFFSET + TEXTXLOC - 4;
        }
        else {
-               x = text_font_width_character(st)*(st->text->curc-st->left) + TXT_OFFSET - 4;
+               x = st->cwidth*(st->text->curc-st->left) + TXT_OFFSET - 4;
        }
        y = ar->winy - st->lheight*l - 2;
 
-       boxw = SUGG_LIST_WIDTH*text_font_width_character(st) + 20;
+       boxw = SUGG_LIST_WIDTH*st->cwidth + 20;
        boxh = SUGG_LIST_SIZE*st->lheight + 8;
        
        UI_ThemeColor(TH_SHADE1);
@@ -1094,9 +1040,9 @@ static void draw_cursor(SpaceText *st, ARegion *ar)
                if(vcurl==vsell) {
                        y -= vcurl*st->lheight;
                        if(vcurc < vselc)
-                               glRecti(x+vcurc*text_font_width_character(st)-1, y, x+vselc*text_font_width_character(st), y-st->lheight);
+                               glRecti(x+vcurc*st->cwidth-1, y, x+vselc*st->cwidth, y-st->lheight);
                        else
-                               glRecti(x+vselc*text_font_width_character(st)-1, y, x+vcurc*text_font_width_character(st), y-st->lheight);
+                               glRecti(x+vselc*st->cwidth-1, y, x+vcurc*st->cwidth, y-st->lheight);
                }
                else {
                        int froml, fromc, tol, toc;
@@ -1111,11 +1057,11 @@ static void draw_cursor(SpaceText *st, ARegion *ar)
                        }
 
                        y -= froml*st->lheight;
-                       glRecti(x+fromc*text_font_width_character(st)-1, y, ar->winx, y-st->lheight); y-=st->lheight;
+                       glRecti(x+fromc*st->cwidth-1, y, ar->winx, y-st->lheight); y-=st->lheight;
                        for(i=froml+1; i<tol; i++)
                                glRecti(x-4, y, ar->winx, y-st->lheight),  y-=st->lheight;
 
-                       glRecti(x-4, y, x+toc*text_font_width_character(st), y-st->lheight);  y-=st->lheight;
+                       glRecti(x-4, y, x+toc*st->cwidth, y-st->lheight);  y-=st->lheight;
                }
        }
        else {
@@ -1132,13 +1078,13 @@ static void draw_cursor(SpaceText *st, ARegion *ar)
        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*text_font_width_character(st);
+               x += vselc*st->cwidth;
                y= ar->winy-2 - vsell*st->lheight;
                
                if(st->overwrite) {
                        char ch= text->sell->line[text->selc];
                        if(!ch) ch= ' ';
-                       w= text_font_width_character(st);
+                       w= st->cwidth;
                        UI_ThemeColor(TH_HILITE);
                        glRecti(x, y-st->lheight-1, x+w, y-st->lheight+1);
                }
@@ -1238,8 +1184,8 @@ static void draw_brackets(SpaceText *st, ARegion *ar)
        if(viewc >= 0){
                viewl= txt_get_span(text->lines.first, startl) - st->top + offl;
 
-               text_font_draw_character(st, x+viewc*text_font_width_character(st), y-viewl*st->lheight, ch);
-               text_font_draw_character(st, x+viewc*text_font_width_character(st)+1, y-viewl*st->lheight, ch);
+               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 */
@@ -1250,8 +1196,8 @@ static void draw_brackets(SpaceText *st, ARegion *ar)
        if(viewc >= 0) {
                viewl= txt_get_span(text->lines.first, endl) - st->top + offl;
 
-               text_font_draw_character(st, x+viewc*text_font_width_character(st), y-viewl*st->lheight, ch);
-               text_font_draw_character(st, x+viewc*text_font_width_character(st)+1, y-viewl*st->lheight, ch);
+               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);
        }
 }
 
@@ -1261,6 +1207,7 @@ void draw_text_main(SpaceText *st, ARegion *ar)
 {
        Text *text= st->text;
        TextLine *tmp;
+       rcti scroll;
        char linenr[12];
        int i, x, y, linecount= 0;
 
@@ -1276,7 +1223,7 @@ void draw_text_main(SpaceText *st, ARegion *ar)
        else st->viewlines= 0;
        
        /* update rects for scroll */
-       calc_text_rcts(st, ar);
+       calc_text_rcts(st, ar, &scroll);        /* scroll will hold the entire bar size */
 
        /* update syntax formatting if needed */
        tmp= text->lines.first;
@@ -1288,13 +1235,23 @@ void draw_text_main(SpaceText *st, ARegion *ar)
                linecount++;
        }
 
+       text_font_begin(st);
+       st->cwidth= BLF_fixed_width();
+       st->cwidth= MAX2(st->cwidth, 1);
+
        /* 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);
-               glRecti(23, 0, (st->lheight==15)? 63: 59, ar->winy - 2);
+               glRecti((TXT_OFFSET-12), 0, (TXT_OFFSET-5) + TEXTXLOC, ar->winy - 2);
        }
-
-       text_font_begin(st);
+       else {
+               st->linenrs_tot= 0; /* not used */
+               x= TXT_OFFSET;
+       }
+       y= ar->winy-st->lheight;
 
        /* draw cursor */
        draw_cursor(st, ar);
@@ -1302,9 +1259,6 @@ void draw_text_main(SpaceText *st, ARegion *ar)
        /* draw the text */
        UI_ThemeColor(TH_TEXT);
 
-       y= ar->winy-st->lheight;
-       x= (st->showlinenrs)? TXT_OFFSET + TEXTXLOC: TXT_OFFSET;
-
        for(i=0; y>0 && i<st->viewlines && tmp; i++, tmp= tmp->next) {
                if(st->showsyntax && !tmp->format)
                        txt_format_line(st, tmp, 0);
@@ -1316,14 +1270,9 @@ void draw_text_main(SpaceText *st, ARegion *ar)
                        else
                                UI_ThemeColor(TH_TEXT);
 
-                       if(((float)(i + linecount + 1)/10000.0) < 1.0) {
-                               sprintf(linenr, "%4d", i + linecount + 1);
-                               text_font_draw(st, TXT_OFFSET - 7, y, linenr);
-                       }
-                       else {
-                               sprintf(linenr, "%5d", i + linecount + 1);
-                               text_font_draw(st, TXT_OFFSET - 11, y, linenr);
-                       }
+                       sprintf(linenr, "%d", i + linecount + 1);
+                       /* itoa(i + linecount + 1, linenr, 10); */ /* not ansi-c :/ */
+                       text_font_draw(st, TXT_OFFSET - 7, y, linenr);
 
                        UI_ThemeColor(TH_TEXT);
                }
@@ -1343,7 +1292,8 @@ void draw_text_main(SpaceText *st, ARegion *ar)
        /* draw other stuff */
        draw_brackets(st, ar);
        draw_markers(st, ar);
-       draw_textscroll(st, ar);
+       glTranslatef(0.375f, 0.375f, 0.0f); /* XXX scroll requires exact pixel space */
+       draw_textscroll(st, ar, &scroll);
        draw_documentation(st, ar);
        draw_suggestion_list(st, ar);
        
@@ -1352,15 +1302,34 @@ void draw_text_main(SpaceText *st, ARegion *ar)
 
 /************************** update ***************************/
 
+void text_update_character_width(SpaceText *st)
+{
+       text_font_begin(st);
+       st->cwidth= BLF_fixed_width();
+       st->cwidth= MAX2(st->cwidth, 1);
+       text_font_end(st);
+}
+
 /* Moves the view to the cursor location,
   also used to make sure the view isnt outside the file */
-void text_update_cursor_moved(SpaceText *st, ARegion *ar)
+void text_update_cursor_moved(bContext *C)
 {
+       ScrArea *sa= CTX_wm_area(C);
+       SpaceText *st= CTX_wm_space_text(C);
        Text *text= st->text;
-       int i, x;
+       ARegion *ar;
+       int i, x, winx= 0;
+
+       if(!st) return;
+
+       for(ar=sa->regionbase.first; ar; ar= ar->next)
+               if(ar->regiontype==RGN_TYPE_WINDOW)
+                       winx= ar->winx;
 
        if(!text || !text->curl) return;
 
+       text_update_character_width(st);
+
        i= txt_get_span(text->lines.first, text->sell);
        if(st->top+st->viewlines <= i || st->top > i)
                st->top= i - st->viewlines/2;
@@ -1371,8 +1340,8 @@ void text_update_cursor_moved(SpaceText *st, ARegion *ar)
        else {
                x= text_draw(st, text->sell->line, st->left, text->selc, 0, 0, 0, NULL);
 
-               if(x==0 || x>ar->winx)
-                       st->left= text->curc-0.5*(ar->winx)/text_font_width_character(st);
+               if(x==0 || x>winx)
+                       st->left= text->curc-0.5*winx/st->cwidth;
        }
 
        if(st->top < 0) st->top= 0;