~ubuntu-branches/ubuntu/trusty/blender/trusty

« back to all changes in this revision

Viewing changes to source/blender/editors/space_text/text_draw.c

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2013-03-06 12:08:47 UTC
  • mfrom: (1.5.1) (14.1.8 experimental)
  • Revision ID: package-import@ubuntu.com-20130306120847-frjfaryb2zrotwcg
Tags: 2.66a-1ubuntu1
* Resynchronize with Debian (LP: #1076930, #1089256, #1052743, #999024,
  #1122888, #1147084)
* debian/control:
  - Lower build-depends on libavcodec-dev since we're not
    doing the libav9 transition in Ubuntu yet

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
 */
30
30
 
31
31
 
32
 
#include <math.h>
33
 
#include <stdlib.h>
34
 
#include <string.h>
35
 
#include <sys/stat.h>
36
32
 
37
33
#include "MEM_guardedalloc.h"
38
34
 
39
35
#include "BLF_api.h"
40
36
 
41
37
#include "BLI_blenlib.h"
42
 
#include "BLI_utildefines.h"
 
38
#include "BLI_math.h"
43
39
 
44
40
#include "DNA_text_types.h"
45
41
#include "DNA_space_types.h"
46
42
#include "DNA_screen_types.h"
47
 
#include "DNA_userdef_types.h"
48
43
 
49
44
#include "BKE_context.h"
50
45
#include "BKE_suggestions.h"
51
46
#include "BKE_text.h"
52
47
 
53
 
 
54
48
#include "BIF_gl.h"
55
49
 
56
 
#include "ED_datafiles.h"
57
50
#include "UI_interface.h"
58
51
#include "UI_resources.h"
 
52
#include "UI_view2d.h"
59
53
 
60
54
#include "text_intern.h"
 
55
#include "text_format.h"
61
56
 
62
57
/******************** text font drawing ******************/
63
58
// XXX, fixme
65
60
 
66
61
static void text_font_begin(SpaceText *st)
67
62
{
68
 
        BLF_size(mono, st->lheight, 72);
 
63
        BLF_size(mono, st->lheight_dpi, 72);
69
64
}
70
65
 
71
66
static void text_font_end(SpaceText *UNUSED(st))
82
77
 
83
78
static int text_font_draw_character(SpaceText *st, int x, int y, char c)
84
79
{
85
 
        char str[2];
86
 
        str[0] = c;
87
 
        str[1] = '\0';
88
 
 
89
80
        BLF_position(mono, x, y, 0);
90
 
        BLF_draw(mono, str, 1);
 
81
        BLF_draw(mono, &c, 1);
91
82
 
92
83
        return st->cwidth;
93
84
}
94
85
 
95
86
static int text_font_draw_character_utf8(SpaceText *st, int x, int y, const char *c)
96
87
{
97
 
        char str[BLI_UTF8_MAX + 1];
98
 
        size_t len = BLI_str_utf8_size(c);
99
 
        memcpy(str, c, len);
100
 
        str[len] = '\0';
101
 
 
 
88
        const size_t len = BLI_str_utf8_size_safe(c);
102
89
        BLF_position(mono, x, y, 0);
103
 
        BLF_draw(mono, str, len);
104
 
 
 
90
        BLF_draw(mono, c, len);
105
91
        return st->cwidth;
106
92
}
107
93
 
108
 
/****************** flatten string **********************/
109
 
 
110
 
static void flatten_string_append(FlattenString *fs, const char *c, int accum, int len) 
111
 
{
112
 
        int i;
113
 
        
114
 
        if (fs->pos + len > fs->len) {
115
 
                char *nbuf; int *naccum;
116
 
                fs->len *= 2;
117
 
 
118
 
                nbuf = MEM_callocN(sizeof(*fs->buf) * fs->len, "fs->buf");
119
 
                naccum = MEM_callocN(sizeof(*fs->accum) * fs->len, "fs->accum");
120
 
 
121
 
                memcpy(nbuf, fs->buf, fs->pos * sizeof(*fs->buf));
122
 
                memcpy(naccum, fs->accum, fs->pos * sizeof(*fs->accum));
123
 
                
124
 
                if (fs->buf != fs->fixedbuf) {
125
 
                        MEM_freeN(fs->buf);
126
 
                        MEM_freeN(fs->accum);
127
 
                }
128
 
                
129
 
                fs->buf = nbuf;
130
 
                fs->accum = naccum;
131
 
        }
132
 
        
133
 
        for (i = 0; i < len; i++)
134
 
        {
135
 
                fs->buf[fs->pos + i] = c[i];
136
 
                fs->accum[fs->pos + i] = accum;
137
 
        }
138
 
 
139
 
        fs->pos += len;
140
 
}
141
 
 
142
 
int flatten_string(SpaceText *st, FlattenString *fs, const char *in)
143
 
{
144
 
        int r, i, total = 0;
145
 
 
146
 
        memset(fs, 0, sizeof(FlattenString));
147
 
        fs->buf = fs->fixedbuf;
148
 
        fs->accum = fs->fixedaccum;
149
 
        fs->len = sizeof(fs->fixedbuf);
150
 
 
151
 
        for (r = 0, i = 0; *in; r++) {
152
 
                if (*in == '\t') {
153
 
                        i = st->tabnumber - (total % st->tabnumber);
154
 
                        total += i;
155
 
                        
156
 
                        while (i--)
157
 
                                flatten_string_append(fs, " ", r, 1);
158
 
                        
159
 
                        in++;
160
 
                }
161
 
                else {
162
 
                        size_t len = BLI_str_utf8_size(in);
163
 
                        flatten_string_append(fs, in, r, len);
164
 
                        in += len;
165
 
                        total++;
166
 
                }
167
 
        }
168
 
        
169
 
        flatten_string_append(fs, "\0", r, 1);
170
 
 
171
 
        return total;
172
 
}
173
 
 
174
 
void flatten_string_free(FlattenString *fs)
175
 
{
176
 
        if (fs->buf != fs->fixedbuf)
177
 
                MEM_freeN(fs->buf);
178
 
        if (fs->accum != fs->fixedaccum)
179
 
                MEM_freeN(fs->accum);
180
 
}
181
 
 
182
 
/* Checks the specified source string for a Python built-in function name. This
183
 
 * name must start at the beginning of the source string and must be followed by
184
 
 * a non-identifier (see text_check_identifier(char)) or null character.
185
 
 * 
186
 
 * If a built-in function is found, the length of the matching name is returned.
187
 
 * Otherwise, -1 is returned.
188
 
 *
189
 
 * See:
190
 
 * http://docs.python.org/py3k/reference/lexical_analysis.html#keywords
191
 
 */
192
 
 
193
 
static int find_builtinfunc(char *string)
194
 
{
195
 
        int a, i;
196
 
        const char *builtinfuncs[] = {
197
 
                /* "False", "None", "True", */ /* see find_bool() */
198
 
                "and", "as", "assert", "break",
199
 
                "class", "continue", "def", "del", "elif", "else", "except",
200
 
                "finally", "for", "from", "global", "if", "import", "in",
201
 
                "is", "lambda", "nonlocal", "not", "or", "pass", "raise",
202
 
                "return", "try", "while", "with", "yield",
203
 
        };
204
 
 
205
 
        for (a = 0; a < sizeof(builtinfuncs) / sizeof(builtinfuncs[0]); a++) {
206
 
                i = 0;
207
 
                while (1) {
208
 
                        /* If we hit the end of a keyword... (eg. "def") */
209
 
                        if (builtinfuncs[a][i] == '\0') {
210
 
                                /* If we still have identifier chars in the source (eg. "definate") */
211
 
                                if (text_check_identifier(string[i]))
212
 
                                        i = -1;  /* No match */
213
 
                                break; /* Next keyword if no match, otherwise we're done */
214
 
                                
215
 
                                /* If chars mismatch, move on to next keyword */
216
 
                        }
217
 
                        else if (string[i] != builtinfuncs[a][i]) {
218
 
                                i = -1;
219
 
                                break; /* Break inner loop, start next keyword */
220
 
                        }
221
 
                        i++;
222
 
                }
223
 
                if (i > 0) break;  /* If we have a match, we're done */
224
 
        }
225
 
        return i;
226
 
}
227
 
 
228
 
/* Checks the specified source string for a Python special name. This name must
229
 
 * start at the beginning of the source string and must be followed by a non-
230
 
 * identifier (see text_check_identifier(char)) or null character.
231
 
 * 
232
 
 * If a special name is found, the length of the matching name is returned.
233
 
 * Otherwise, -1 is returned. */
234
 
 
235
 
static int find_specialvar(char *string) 
236
 
{
237
 
        int i = 0;
238
 
        /* Check for "def" */
239
 
        if (string[0] == 'd' && string[1] == 'e' && string[2] == 'f')
240
 
                i = 3;
241
 
        /* Check for "class" */
242
 
        else if (string[0] == 'c' && string[1] == 'l' && string[2] == 'a' && string[3] == 's' && string[4] == 's')
243
 
                i = 5;
244
 
        /* If next source char is an identifier (eg. 'i' in "definate") no match */
245
 
        if (i == 0 || text_check_identifier(string[i]))
246
 
                return -1;
247
 
        return i;
248
 
}
249
 
 
250
 
static int find_decorator(char *string) 
251
 
{
252
 
        if (string[0] == '@') {
253
 
                int i = 1;
254
 
                while (text_check_identifier(string[i])) {
255
 
                        i++;
256
 
                }
257
 
                return i;
258
 
        }
259
 
        return -1;
260
 
}
261
 
 
262
 
static int find_bool(char *string) 
263
 
{
264
 
        int i = 0;
265
 
        /* Check for "False" */
266
 
        if (string[0] == 'F' && string[1] == 'a' && string[2] == 'l' && string[3] == 's' && string[4] == 'e')
267
 
                i = 5;
268
 
        /* Check for "True" */
269
 
        else if (string[0] == 'T' && string[1] == 'r' && string[2] == 'u' && string[3] == 'e')
270
 
                i = 4;
271
 
        /* Check for "None" */
272
 
        else if (string[0] == 'N' && string[1] == 'o' && string[2] == 'n' && string[3] == 'e')
273
 
                i = 4;
274
 
        /* If next source char is an identifier (eg. 'i' in "definate") no match */
275
 
        if (i == 0 || text_check_identifier(string[i]))
276
 
                return -1;
277
 
        return i;
278
 
}
279
 
 
280
 
/* Ensures the format string for the given line is long enough, reallocating
281
 
 * as needed. Allocation is done here, alone, to ensure consistency. */
282
 
static int text_check_format_len(TextLine *line, unsigned int len)
283
 
{
284
 
        if (line->format) {
285
 
                if (strlen(line->format) < len) {
286
 
                        MEM_freeN(line->format);
287
 
                        line->format = MEM_mallocN(len + 2, "SyntaxFormat");
288
 
                        if (!line->format) return 0;
289
 
                }
290
 
        }
291
 
        else {
292
 
                line->format = MEM_mallocN(len + 2, "SyntaxFormat");
293
 
                if (!line->format) return 0;
294
 
        }
295
 
 
296
 
        return 1;
297
 
}
298
 
 
299
 
/* Formats the specified line. If do_next is set, the process will move on to
300
 
 * the succeeding line if it is affected (eg. multiline strings). Format strings
301
 
 * may contain any of the following characters:
302
 
 *  '_'  Whitespace
303
 
 *  '#'  Comment text
304
 
 *  '!'  Punctuation and other symbols
305
 
 *  'n'  Numerals
306
 
 *  'l'  String letters
307
 
 *  'v'  Special variables (class, def)
308
 
 *  'b'  Built-in names (print, for, etc.)
309
 
 *  'q'  Other text (identifiers, etc.)
310
 
 * It is terminated with a null-terminator '\0' followed by a continuation
311
 
 * flag indicating whether the line is part of a multi-line string. */
312
 
 
313
 
static void txt_format_line(SpaceText *st, TextLine *line, int do_next)
314
 
{
315
 
        FlattenString fs;
316
 
        char *str, *fmt, orig, cont, find, prev = ' ';
317
 
        int len, i;
318
 
 
319
 
        /* Get continuation from previous line */
320
 
        if (line->prev && line->prev->format != NULL) {
321
 
                fmt = line->prev->format;
322
 
                cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
323
 
        }
324
 
        else cont = 0;
325
 
 
326
 
        /* Get original continuation from this line */
327
 
        if (line->format != NULL) {
328
 
                fmt = line->format;
329
 
                orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
330
 
        }
331
 
        else orig = 0xFF;
332
 
 
333
 
        len = flatten_string(st, &fs, line->line);
334
 
        str = fs.buf;
335
 
        if (!text_check_format_len(line, len)) {
336
 
                flatten_string_free(&fs);
337
 
                return;
338
 
        }
339
 
        fmt = line->format;
340
 
 
341
 
        while (*str) {
342
 
                /* Handle escape sequences by skipping both \ and next char */
343
 
                if (*str == '\\') {
344
 
                        *fmt = prev; fmt++; str++;
345
 
                        if (*str == '\0') break;
346
 
                        *fmt = prev; fmt++; str += BLI_str_utf8_size(str);
347
 
                        continue;
348
 
                }
349
 
                /* Handle continuations */
350
 
                else if (cont) {
351
 
                        /* Triple strings ("""...""" or '''...''') */
352
 
                        if (cont & TXT_TRISTR) {
353
 
                                find = (cont & TXT_DBLQUOTSTR) ? '"' : '\'';
354
 
                                if (*str == find && *(str + 1) == find && *(str + 2) == find) {
355
 
                                        *fmt = 'l'; fmt++; str++;
356
 
                                        *fmt = 'l'; fmt++; str++;
357
 
                                        cont = 0;
358
 
                                }
359
 
                                /* Handle other strings */
360
 
                        }
361
 
                        else {
362
 
                                find = (cont & TXT_DBLQUOTSTR) ? '"' : '\'';
363
 
                                if (*str == find) cont = 0;
364
 
                        }
365
 
 
366
 
                        *fmt = 'l';
367
 
                        str += BLI_str_utf8_size(str) - 1;
368
 
                }
369
 
                /* Not in a string... */
370
 
                else {
371
 
                        /* Deal with comments first */
372
 
                        if (prev == '#' || *str == '#') {
373
 
                                *fmt = '#';
374
 
                                str += BLI_str_utf8_size(str) - 1;
375
 
                        }
376
 
                        else if (*str == '"' || *str == '\'') {
377
 
                                /* Strings */
378
 
                                find = *str;
379
 
                                cont = (*str == '"') ? TXT_DBLQUOTSTR : TXT_SNGQUOTSTR;
380
 
                                if (*(str + 1) == find && *(str + 2) == find) {
381
 
                                        *fmt = 'l'; fmt++; str++;
382
 
                                        *fmt = 'l'; fmt++; str++;
383
 
                                        cont |= TXT_TRISTR;
384
 
                                }
385
 
                                *fmt = 'l';
386
 
                        }
387
 
                        /* Whitespace (all ws. has been converted to spaces) */
388
 
                        else if (*str == ' ')
389
 
                                *fmt = '_';
390
 
                        /* Numbers (digits not part of an identifier and periods followed by digits) */
391
 
                        else if ((prev != 'q' && text_check_digit(*str)) || (*str == '.' && text_check_digit(*(str + 1))))
392
 
                                *fmt = 'n';
393
 
                        /* Booleans */
394
 
                        else if (prev != 'q' && (i = find_bool(str)) != -1)
395
 
                                if (i > 0) {
396
 
                                        while (i > 1) {
397
 
                                                *fmt = 'n'; fmt++; str++;
398
 
                                                i--;
399
 
                                        }
400
 
                                        *fmt = 'n';
401
 
                                }
402
 
                                else {
403
 
                                        str += BLI_str_utf8_size(str) - 1;
404
 
                                        *fmt = 'q';
405
 
                                }
406
 
                        /* Punctuation */
407
 
                        else if (text_check_delim(*str))
408
 
                                *fmt = '!';
409
 
                        /* Identifiers and other text (no previous ws. or delims. so text continues) */
410
 
                        else if (prev == 'q') {
411
 
                                str += BLI_str_utf8_size(str) - 1;
412
 
                                *fmt = 'q';
413
 
                        }
414
 
                        /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
415
 
                        else {
416
 
                                /* Special vars(v) or built-in keywords(b) */
417
 
                                if ((i = find_specialvar(str)) != -1)
418
 
                                        prev = 'v';
419
 
                                else if ((i = find_builtinfunc(str)) != -1)
420
 
                                        prev = 'b';
421
 
                                else if ((i = find_decorator(str)) != -1)
422
 
                                        prev = 'v';  /* could have a new color for this */
423
 
                                if (i > 0) {
424
 
                                        while (i > 1) {
425
 
                                                *fmt = prev; fmt++; str++;
426
 
                                                i--;
427
 
                                        }
428
 
                                        *fmt = prev;
429
 
                                }
430
 
                                else {
431
 
                                        str += BLI_str_utf8_size(str) - 1;
432
 
                                        *fmt = 'q';
433
 
                                }
434
 
                        }
435
 
                }
436
 
                prev = *fmt;
437
 
                fmt++;
438
 
                str++;
439
 
        }
440
 
 
441
 
        /* Terminate and add continuation char */
442
 
        *fmt = '\0'; fmt++;
443
 
        *fmt = cont;
444
 
 
445
 
        /* If continuation has changed and we're allowed, process the next line */
446
 
        if (cont != orig && do_next && line->next) {
447
 
                txt_format_line(st, line->next, do_next);
448
 
        }
449
 
        
450
 
        flatten_string_free(&fs);
451
 
}
452
 
 
453
94
#if 0
454
95
/* Formats every line of the current text */
455
96
static void txt_format_text(SpaceText *st) 
467
108
static void format_draw_color(char formatchar)
468
109
{
469
110
        switch (formatchar) {
470
 
                case '_': /* Whitespace */
471
 
                        break;
472
 
                case '!': /* Symbols */
473
 
                        UI_ThemeColorBlend(TH_TEXT, TH_BACK, 0.5f);
474
 
                        break;
475
 
                case '#': /* Comments */
 
111
                case FMT_TYPE_WHITESPACE:
 
112
                        break;
 
113
                case FMT_TYPE_SYMBOL:
 
114
                        UI_ThemeColor(TH_SYNTAX_S);
 
115
                        break;
 
116
                case FMT_TYPE_COMMENT:
476
117
                        UI_ThemeColor(TH_SYNTAX_C);
477
118
                        break;
478
 
                case 'n': /* Numerals */
 
119
                case FMT_TYPE_NUMERAL:
479
120
                        UI_ThemeColor(TH_SYNTAX_N);
480
121
                        break;
481
 
                case 'l': /* Strings */
 
122
                case FMT_TYPE_STRING:
482
123
                        UI_ThemeColor(TH_SYNTAX_L);
483
124
                        break;
484
 
                case 'v': /* Specials: class, def */
 
125
                case FMT_TYPE_DIRECTIVE:
 
126
                        UI_ThemeColor(TH_SYNTAX_D);
 
127
                        break;
 
128
                case FMT_TYPE_SPECIAL:
485
129
                        UI_ThemeColor(TH_SYNTAX_V);
486
130
                        break;
487
 
                case 'b': /* Keywords: for, print, etc. */
 
131
                case FMT_TYPE_RESERVED:
 
132
                        UI_ThemeColor(TH_SYNTAX_R);
 
133
                        break;
 
134
                case FMT_TYPE_KEYWORD:
488
135
                        UI_ThemeColor(TH_SYNTAX_B);
489
136
                        break;
490
 
                case 'q': /* Other text (identifiers) */
 
137
                case FMT_TYPE_DEFAULT:
491
138
                default:
492
139
                        UI_ThemeColor(TH_TEXT);
493
140
                        break;
576
223
                end = max;
577
224
                chop = 1;
578
225
                *offc = 0;
579
 
                for (i = 0, j = 0; linep->line[j]; j += BLI_str_utf8_size(linep->line + j)) {
 
226
                for (i = 0, j = 0; linep->line[j]; j += BLI_str_utf8_size_safe(linep->line + j)) {
580
227
                        int chars;
581
228
 
582
229
                        /* Mimic replacement of tabs */
641
288
        *offc = 0;
642
289
        cursin = txt_utf8_offset_to_index(linein->line, cursin);
643
290
 
644
 
        for (i = 0, j = 0; linein->line[j]; j += BLI_str_utf8_size(linein->line + j)) {
 
291
        for (i = 0, j = 0; linein->line[j]; j += BLI_str_utf8_size_safe(linein->line + j)) {
645
292
 
646
293
                /* Mimic replacement of tabs */
647
294
                ch = linein->line[j];
686
333
{
687
334
        int a = 0, i;
688
335
        
689
 
        for (i = 0; i < cur && line[i]; i += BLI_str_utf8_size(line + i)) {
 
336
        for (i = 0; i < cur && line[i]; i += BLI_str_utf8_size_safe(line + i)) {
690
337
                if (line[i] == '\t')
691
338
                        a += st->tabnumber - a % st->tabnumber;
692
339
                else
699
346
{
700
347
        int pos = 0;
701
348
        while (str[pos] && n--) {
702
 
                pos += BLI_str_utf8_size(str + pos);
 
349
                pos += BLI_str_utf8_size_safe(str + pos);
703
350
        }
704
351
        return str + pos;
705
352
}
709
356
        FlattenString fs;
710
357
        int basex, i, a, start, end, max, lines; /* view */
711
358
        int mi, ma, mstart, mend;                /* mem */
 
359
        char fmt_prev = 0xff;
712
360
        
713
361
        flatten_string(st, &fs, str);
714
362
        str = fs.buf;
720
368
        start = 0; mstart = 0;
721
369
        end = max; mend = txt_utf8_get_nth(str, max) - str;
722
370
        
723
 
        for (i = 0, mi = 0; str[mi]; i++, mi += BLI_str_utf8_size(str + mi)) {
 
371
        for (i = 0, mi = 0; str[mi]; i++, mi += BLI_str_utf8_size_safe(str + mi)) {
724
372
                if (i - start >= max) {
725
373
                        /* skip hidden part of line */
726
374
                        if (skip) {
731
379
                        }
732
380
 
733
381
                        /* Draw the visible portion of text on the overshot line */
734
 
                        for (a = start, ma = mstart; a < end; a++, ma += BLI_str_utf8_size(str + ma)) {
735
 
                                if (st->showsyntax && format) format_draw_color(format[a]);
 
382
                        for (a = start, ma = mstart; a < end; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
 
383
                                if (st->showsyntax && format) {
 
384
                                        if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]);
 
385
                                }
736
386
                                x += text_font_draw_character_utf8(st, x, y, str + ma);
737
387
                        }
738
 
                        y -= st->lheight;
 
388
                        y -= st->lheight_dpi + TXT_LINE_SPACING;
739
389
                        x = basex;
740
390
                        lines++;
741
391
                        start = end; mstart = mend;
749
399
        }
750
400
 
751
401
        /* Draw the remaining text */
752
 
        for (a = start, ma = mstart; str[ma] && y > 0; a++, ma += BLI_str_utf8_size(str + ma)) {
753
 
                if (st->showsyntax && format)
754
 
                        format_draw_color(format[a]);
 
402
        for (a = start, ma = mstart; str[ma] && y > 0; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
 
403
                if (st->showsyntax && format) {
 
404
                        if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]);
 
405
                }
755
406
 
756
407
                x += text_font_draw_character_utf8(st, x, y, str + ma);
757
408
        }
782
433
                
783
434
                if (st->showsyntax && format) {
784
435
                        int a, str_shift = 0;
 
436
                        char fmt_prev = 0xff;
785
437
                        format = format + cshift;
786
438
 
787
439
                        for (a = 0; a < amount; a++) {
788
 
                                format_draw_color(format[a]);
 
440
                                if (format[a] != fmt_prev) format_draw_color(fmt_prev = format[a]);
789
441
                                x += text_font_draw_character_utf8(st, x, y, in + str_shift);
790
 
                                str_shift += BLI_str_utf8_size(in + str_shift);
 
442
                                str_shift += BLI_str_utf8_size_safe(in + str_shift);
791
443
                        }
792
444
                }
793
 
                else text_font_draw(st, x, y, in);
 
445
                else {
 
446
                        text_font_draw(st, x, y, in);
 
447
                }
794
448
        }
795
449
        else {
796
450
                while (w-- && *acc++ < maxwidth)
826
480
 
827
481
static void text_drawcache_init(SpaceText *st)
828
482
{
829
 
        DrawCache *drawcache = MEM_callocN(sizeof (DrawCache), "text draw cache");
 
483
        DrawCache *drawcache = MEM_callocN(sizeof(DrawCache), "text draw cache");
830
484
 
831
485
        drawcache->winx = -1;
832
486
        drawcache->nlines = BLI_countlist(&st->text->lines);
853
507
        full_update |= drawcache->wordwrap != st->wordwrap;       /* word-wrapping option was toggled */
854
508
        full_update |= drawcache->showlinenrs != st->showlinenrs; /* word-wrapping option was toggled */
855
509
        full_update |= drawcache->tabnumber != st->tabnumber;     /* word-wrapping option was toggled */
856
 
        full_update |= drawcache->lheight != st->lheight;         /* word-wrapping option was toggled */
 
510
        full_update |= drawcache->lheight != st->lheight_dpi;         /* word-wrapping option was toggled */
857
511
        full_update |= drawcache->cwidth != st->cwidth;           /* word-wrapping option was toggled */
858
512
        full_update |= strncmp(drawcache->text_id, txt->id.name, MAX_ID_NAME); /* text datablock was changed */
859
513
 
929
583
        /* store settings */
930
584
        drawcache->winx        = ar->winx;
931
585
        drawcache->wordwrap    = st->wordwrap;
932
 
        drawcache->lheight     = st->lheight;
 
586
        drawcache->lheight     = st->lheight_dpi;
933
587
        drawcache->cwidth      = st->cwidth;
934
588
        drawcache->showlinenrs = st->showlinenrs;
935
589
        drawcache->tabnumber   = st->tabnumber;
1017
671
        lines = 1;
1018
672
        start = 0;
1019
673
        end = max;
1020
 
        for (i = 0, j = 0; str[j]; j += BLI_str_utf8_size(str + j)) {
 
674
        for (i = 0, j = 0; str[j]; j += BLI_str_utf8_size_safe(str + j)) {
1021
675
                /* Mimic replacement of tabs */
1022
676
                ch = str[j];
1023
677
                if (ch == '\t') {
1071
725
        return drawcache->total_lines;
1072
726
}
1073
727
 
1074
 
/* Move pointer to first visible line (top) */
1075
 
static TextLine *first_visible_line(SpaceText *st, ARegion *ar, int *wrap_top)
1076
 
{
1077
 
        Text *text = st->text;
1078
 
        TextLine *pline = text->lines.first;
1079
 
        int i = st->top, lineno = 0;
1080
 
 
1081
 
        text_update_drawcache(st, ar);
1082
 
 
1083
 
        if (wrap_top) *wrap_top = 0;
1084
 
 
1085
 
        if (st->wordwrap) {
1086
 
                while (i > 0 && pline) {
1087
 
                        int lines = text_get_visible_lines_no(st, lineno);
1088
 
 
1089
 
                        if (i - lines < 0) {
1090
 
                                if (wrap_top) *wrap_top = i;
1091
 
                                break;
1092
 
                        }
1093
 
                        else {
1094
 
                                pline = pline->next;
1095
 
                                i -= lines;
1096
 
                                lineno++;
1097
 
                        }
1098
 
                }
1099
 
        }
1100
 
        else {
1101
 
                for (i = st->top; pline->next && i > 0; i--)
1102
 
                        pline = pline->next;
1103
 
        }
1104
 
 
1105
 
        return pline;
1106
 
}
1107
 
 
1108
728
/************************ draw scrollbar *****************************/
1109
729
 
1110
730
static void calc_text_rcts(SpaceText *st, ARegion *ar, rcti *scroll, rcti *back)
1120
740
        blank_lines = st->viewlines / 2;
1121
741
        
1122
742
        /* nicer code: use scroll rect for entire bar */
1123
 
        back->xmin = ar->winx - 18;
 
743
        back->xmin = ar->winx - (V2D_SCROLL_WIDTH + 1);
1124
744
        back->xmax = ar->winx;
1125
745
        back->ymin = 0;
1126
746
        back->ymax = ar->winy;
1127
747
        
1128
 
        scroll->xmin = ar->winx - 17;
 
748
        scroll->xmin = ar->winx - V2D_SCROLL_WIDTH;
1129
749
        scroll->xmax = ar->winx - 5;
1130
750
        scroll->ymin = 4;
1131
751
        scroll->ymax = 4 + pix_available;
1140
760
        barheight = (ltexth > 0) ? (st->viewlines * pix_available) / ltexth : 0;
1141
761
        pix_bardiff = 0;
1142
762
        if (barheight < 20) {
1143
 
                pix_bardiff = 20 - barheight; /* take into account the now non-linear sizing of the bar */      
 
763
                pix_bardiff = 20 - barheight; /* take into account the now non-linear sizing of the bar */
1144
764
                barheight = 20;
1145
765
        }
1146
766
        barstart = (ltexth > 0) ? ((pix_available - pix_bardiff) * st->top) / ltexth : 0;
1167
787
                /* the scrollbar is non-linear sized */
1168
788
                if (pix_bardiff > 0) {
1169
789
                        /* the start of the highlight is in the current viewport */
1170
 
                        if (ltexth && st->viewlines && lhlstart >= st->top && lhlstart <= st->top + st->viewlines) { 
 
790
                        if (ltexth && st->viewlines && lhlstart >= st->top && lhlstart <= st->top + st->viewlines) {
1171
791
                                /* speed the progresion of the start of the highlight through the scrollbar */
1172
 
                                hlstart = ( ( (pix_available - pix_bardiff) * lhlstart) / ltexth) + (pix_bardiff * (lhlstart - st->top) / st->viewlines);       
 
792
                                hlstart = ( ( (pix_available - pix_bardiff) * lhlstart) / ltexth) + (pix_bardiff * (lhlstart - st->top) / st->viewlines);
1173
793
                        }
1174
794
                        else if (lhlstart > st->top + st->viewlines && hlstart < barstart + barheight && hlstart > barstart) {
1175
795
                                /* push hl start down */
1176
796
                                hlstart = barstart + barheight;
1177
797
                        }
1178
 
                        else if (lhlend > st->top  && lhlstart < st->top && hlstart > barstart) {
 
798
                        else if (lhlend > st->top && lhlstart < st->top && hlstart > barstart) {
1179
799
                                /*fill out start */
1180
800
                                hlstart = barstart;
1181
801
                        }
1182
802
 
1183
 
                        if (hlend <= hlstart) { 
 
803
                        if (hlend <= hlstart) {
1184
804
                                hlend = hlstart + 2;
1185
805
                        }
1186
806
 
1187
807
                        /* the end of the highlight is in the current viewport */
1188
 
                        if (ltexth && st->viewlines && lhlend >= st->top && lhlend <= st->top + st->viewlines) { 
 
808
                        if (ltexth && st->viewlines && lhlend >= st->top && lhlend <= st->top + st->viewlines) {
1189
809
                                /* speed the progresion of the end of the highlight through the scrollbar */
1190
810
                                hlend = (((pix_available - pix_bardiff) * lhlend) / ltexth) + (pix_bardiff * (lhlend - st->top) / st->viewlines);
1191
811
                        }
1192
812
                        else if (lhlend < st->top && hlend >= barstart - 2 && hlend < barstart + barheight) {
1193
813
                                /* push hl end up */
1194
814
                                hlend = barstart;
1195
 
                        }                                       
 
815
                        }
1196
816
                        else if (lhlend > st->top + st->viewlines && lhlstart < st->top + st->viewlines && hlend < barstart + barheight) {
1197
817
                                /* fill out end */
1198
818
                                hlend = barstart + barheight;
1199
819
                        }
1200
820
 
1201
 
                        if (hlend <= hlstart) { 
 
821
                        if (hlend <= hlstart) {
1202
822
                                hlstart = hlend - 2;
1203
 
                        }       
1204
 
                }       
 
823
                        }
 
824
                }
1205
825
        }
1206
826
        else {
1207
827
                hlstart = 0;
1208
828
                hlend = 0;
1209
829
        }
1210
830
 
1211
 
        if (hlend - hlstart < 2) { 
 
831
        if (hlend - hlstart < 2) {
1212
832
                hlend = hlstart + 2;
1213
833
        }
1214
834
        
1233
853
        uiWidgetScrollDraw(&wcol, scroll, &st->txtbar, (st->flags & ST_SCROLL_SELECT) ? UI_SCROLL_PRESSED : 0);
1234
854
 
1235
855
        uiSetRoundBox(UI_CNR_ALL);
1236
 
        rad = 0.4f * MIN2(st->txtscroll.xmax - st->txtscroll.xmin, st->txtscroll.ymax - st->txtscroll.ymin);
 
856
        rad = 0.4f * min_ii(BLI_rcti_size_x(&st->txtscroll), BLI_rcti_size_y(&st->txtscroll));
1237
857
        UI_GetThemeColor3ubv(TH_HILITE, col);
1238
858
        col[3] = 48;
1239
859
        glColor4ubv(col);
1242
862
        glDisable(GL_BLEND);
1243
863
}
1244
864
 
1245
 
/************************** draw markers **************************/
1246
 
 
1247
 
static void draw_markers(SpaceText *st, ARegion *ar)
1248
 
{
1249
 
        Text *text = st->text;
1250
 
        TextMarker *marker, *next;
1251
 
        TextLine *top, *line;
1252
 
        int offl, offc, i, x1, x2, y1, y2, x, y;
1253
 
        int topi, topy;
1254
 
 
1255
 
        /* Move pointer to first visible line (top) */
1256
 
        top = first_visible_line(st, ar, NULL);
1257
 
        topi = BLI_findindex(&text->lines, top);
1258
 
 
1259
 
        topy = txt_get_span(text->lines.first, top);
1260
 
 
1261
 
        for (marker = text->markers.first; marker; marker = next) {
1262
 
                next = marker->next;
1263
 
 
1264
 
                /* invisible line (before top) */
1265
 
                if (marker->lineno < topi) continue;
1266
 
 
1267
 
                line = BLI_findlink(&text->lines, marker->lineno);
1268
 
 
1269
 
                /* Remove broken markers */
1270
 
                if (marker->end > line->len || marker->start > marker->end) {
1271
 
                        BLI_freelinkN(&text->markers, marker);
1272
 
                        continue;
1273
 
                }
1274
 
 
1275
 
                wrap_offset(st, ar, line, marker->start, &offl, &offc);
1276
 
                y1 = txt_get_span(top, line) - st->top + offl + topy;
1277
 
                x1 = text_get_char_pos(st, line->line, marker->start) - st->left + offc;
1278
 
 
1279
 
                wrap_offset(st, ar, line, marker->end, &offl, &offc);
1280
 
                y2 = txt_get_span(top, line) - st->top + offl + topy;
1281
 
                x2 = text_get_char_pos(st, line->line, marker->end) - st->left + offc;
1282
 
 
1283
 
                /* invisible part of line (before top, after last visible line) */
1284
 
                if (y2 < 0 || y1 > st->top + st->viewlines) continue;
1285
 
 
1286
 
                glColor3ubv(marker->color);
1287
 
                x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
1288
 
                y = ar->winy - 3;
1289
 
 
1290
 
                if (y1 == y2) {
1291
 
                        y -= y1 * st->lheight;
1292
 
                        glBegin(GL_LINE_LOOP);
1293
 
                        glVertex2i(x + x2 * st->cwidth + 1, y);
1294
 
                        glVertex2i(x + x1 * st->cwidth - 2, y);
1295
 
                        glVertex2i(x + x1 * st->cwidth - 2, y - st->lheight);
1296
 
                        glVertex2i(x + x2 * st->cwidth + 1, y - st->lheight);
1297
 
                        glEnd();
1298
 
                }
1299
 
                else {
1300
 
                        y -= y1 * st->lheight;
1301
 
                        glBegin(GL_LINE_STRIP);
1302
 
                        glVertex2i(ar->winx, y);
1303
 
                        glVertex2i(x + x1 * st->cwidth - 2, y);
1304
 
                        glVertex2i(x + x1 * st->cwidth - 2, y - st->lheight);
1305
 
                        glVertex2i(ar->winx, y - st->lheight);
1306
 
                        glEnd();
1307
 
                        y -= st->lheight;
1308
 
 
1309
 
                        for (i = y1 + 1; i < y2; i++) {
1310
 
                                glBegin(GL_LINES);
1311
 
                                glVertex2i(x, y);
1312
 
                                glVertex2i(ar->winx, y);
1313
 
                                glVertex2i(x, y - st->lheight);
1314
 
                                glVertex2i(ar->winx, y - st->lheight);
1315
 
                                glEnd();
1316
 
                                y -= st->lheight;
1317
 
                        }
1318
 
 
1319
 
                        glBegin(GL_LINE_STRIP);
1320
 
                        glVertex2i(x, y);
1321
 
                        glVertex2i(x + x2 * st->cwidth + 1, y);
1322
 
                        glVertex2i(x + x2 * st->cwidth + 1, y - st->lheight);
1323
 
                        glVertex2i(x, y - st->lheight);
1324
 
                        glEnd();
1325
 
                }
1326
 
        }
1327
 
}
1328
 
 
1329
865
/*********************** draw documentation *******************************/
1330
866
 
1331
867
static void draw_documentation(SpaceText *st, ARegion *ar)
1356
892
                x += SUGG_LIST_WIDTH * st->cwidth + 50;
1357
893
        }
1358
894
 
1359
 
        /* top= */ /* UNUSED */ y = ar->winy - st->lheight * l - 2;
 
895
        /* top = */ /* UNUSED */ y = ar->winy - st->lheight_dpi * l - 2;
1360
896
        boxw = DOC_WIDTH * st->cwidth + 20;
1361
 
        boxh = (DOC_HEIGHT + 1) * st->lheight;
 
897
        boxh = (DOC_HEIGHT + 1) * (st->lheight_dpi + TXT_LINE_SPACING);
1362
898
 
1363
899
        /* Draw panel */
1364
900
        UI_ThemeColor(TH_BACK);
1390
926
                else if (*p == '\n') {
1391
927
                        buf[i] = '\0';
1392
928
                        if (lines >= 0) {
1393
 
                                y -= st->lheight;
 
929
                                y -= st->lheight_dpi;
1394
930
                                text_draw(st, buf, 0, 0, 1, x + 4, y - 3, NULL);
1395
931
                        }
1396
932
                        i = 0; br = DOC_WIDTH; lines++;
1399
935
                if (i == DOC_WIDTH) { /* Reached the width, go to last break and wrap there */
1400
936
                        buf[br] = '\0';
1401
937
                        if (lines >= 0) {
1402
 
                                y -= st->lheight;
 
938
                                y -= st->lheight_dpi;
1403
939
                                text_draw(st, buf, 0, 0, 1, x + 4, y - 3, NULL);
1404
940
                        }
1405
941
                        p -= i - br - 1; /* Rewind pointer to last break */
1421
957
        SuggItem *item, *first, *last, *sel;
1422
958
        TextLine *tmp;
1423
959
        char str[SUGG_LIST_WIDTH + 1];
1424
 
        int w, boxw = 0, boxh, i, l, x, y, b, *top;
 
960
        int w, boxw = 0, boxh, i, l, x, y, *top;
 
961
        const int lheight = st->lheight_dpi + TXT_LINE_SPACING;
 
962
        const int margin_x = 2;
1425
963
        
1426
 
        if (!st || !st->text) return;
 
964
        if (!st->text) return;
1427
965
        if (!texttool_text_is_active(st->text)) return;
1428
966
 
1429
967
        first = texttool_suggest_first();
1445
983
        else {
1446
984
                x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET - 4;
1447
985
        }
1448
 
        y = ar->winy - st->lheight * l - 2;
 
986
        /* offset back so the start of the text lines up with the suggestions,
 
987
         * not essential but makes suggestions easier to follow */
 
988
        x -= st->cwidth * (st->text->curc - text_find_identifier_start(st->text->curl->line, st->text->curc));
 
989
        y = ar->winy - lheight * l - 2;
1449
990
 
1450
991
        boxw = SUGG_LIST_WIDTH * st->cwidth + 20;
1451
 
        boxh = SUGG_LIST_SIZE * st->lheight + 8;
 
992
        boxh = SUGG_LIST_SIZE * lheight + 8;
1452
993
        
 
994
        /* not needed but stands out nicer */
 
995
        uiDrawBoxShadow(220, x, y - boxh, x + boxw, y);
 
996
 
1453
997
        UI_ThemeColor(TH_SHADE1);
1454
998
        glRecti(x - 1, y + 1, x + boxw + 1, y - boxh - 1);
1455
 
        UI_ThemeColor(TH_BACK);
 
999
        UI_ThemeColorShade(TH_BACK, 16);
1456
1000
        glRecti(x, y, x + boxw, y - boxh);
1457
1001
 
1458
1002
        /* Set the top 'item' of the visible list */
1460
1004
 
1461
1005
        for (i = 0; i < SUGG_LIST_SIZE && item; i++, item = item->next) {
1462
1006
 
1463
 
                y -= st->lheight;
 
1007
                y -= lheight;
1464
1008
 
1465
1009
                BLI_strncpy(str, item->name, SUGG_LIST_WIDTH);
1466
1010
 
1468
1012
                
1469
1013
                if (item == sel) {
1470
1014
                        UI_ThemeColor(TH_SHADE2);
1471
 
                        glRecti(x + 16, y - 3, x + 16 + w, y + st->lheight - 3);
1472
 
                }
1473
 
                b = 1; /* b=1 color block, text is default. b=0 no block, color text */
1474
 
                switch (item->type) {
1475
 
                        case 'k': UI_ThemeColor(TH_SYNTAX_B); b = 0; break;
1476
 
                        case 'm': UI_ThemeColor(TH_TEXT); break;
1477
 
                        case 'f': UI_ThemeColor(TH_SYNTAX_L); break;
1478
 
                        case 'v': UI_ThemeColor(TH_SYNTAX_N); break;
1479
 
                        case '?': UI_ThemeColor(TH_TEXT); b = 0; break;
1480
 
                }
1481
 
                if (b) {
1482
 
                        glRecti(x + 8, y + 2, x + 11, y + 5);
1483
 
                        UI_ThemeColor(TH_TEXT);
1484
 
                }
1485
 
                text_draw(st, str, 0, 0, 1, x + 16, y - 1, NULL);
 
1015
                        glRecti(x + margin_x, y - 3, x + margin_x + w, y + lheight - 3);
 
1016
                }
 
1017
 
 
1018
                format_draw_color(item->type);
 
1019
                text_draw(st, str, 0, 0, 1, x + margin_x, y - 1, NULL);
1486
1020
 
1487
1021
                if (item == last) break;
1488
1022
        }
1495
1029
        Text *text = st->text;
1496
1030
        int vcurl, vcurc, vsell, vselc, hidden = 0;
1497
1031
        int x, y, w, i;
 
1032
        const int lheight = st->lheight_dpi + TXT_LINE_SPACING;
1498
1033
 
1499
1034
        /* Draw the selection */
1500
1035
        if (text->curl != text->sell || text->curc != text->selc) {
1512
1047
                
1513
1048
                UI_ThemeColor(TH_SHADE2);
1514
1049
                x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
1515
 
                y = ar->winy - 2;
 
1050
                y = ar->winy;
1516
1051
 
1517
1052
                if (vcurl == vsell) {
1518
 
                        y -= vcurl * st->lheight;
 
1053
                        y -= vcurl * lheight;
1519
1054
                        if (vcurc < vselc)
1520
 
                                glRecti(x + vcurc * st->cwidth - 1, y, x + vselc * st->cwidth, y - st->lheight);
 
1055
                                glRecti(x + vcurc * st->cwidth - 1, y, x + vselc * st->cwidth, y - lheight);
1521
1056
                        else
1522
 
                                glRecti(x + vselc * st->cwidth - 1, y, x + vcurc * st->cwidth, y - st->lheight);
 
1057
                                glRecti(x + vselc * st->cwidth - 1, y, x + vcurc * st->cwidth, y - lheight);
1523
1058
                }
1524
1059
                else {
1525
1060
                        int froml, fromc, tol, toc;
1533
1068
                                fromc = vselc; toc = vcurc;
1534
1069
                        }
1535
1070
 
1536
 
                        y -= froml * st->lheight;
1537
 
                        glRecti(x + fromc * st->cwidth - 1, y, ar->winx, y - st->lheight); y -= st->lheight;
 
1071
                        y -= froml * lheight;
 
1072
                        glRecti(x + fromc * st->cwidth - 1, y, ar->winx, y - lheight); y -= lheight;
1538
1073
                        for (i = froml + 1; i < tol; i++)
1539
 
                                glRecti(x - 4, y, ar->winx, y - st->lheight),  y -= st->lheight;
 
1074
                                glRecti(x - 4, y, ar->winx, y - lheight),  y -= lheight;
1540
1075
 
1541
 
                        glRecti(x - 4, y, x + toc * st->cwidth, y - st->lheight);  y -= st->lheight;
 
1076
                        glRecti(x - 4, y, x + toc * st->cwidth, y - lheight);  y -= lheight;
1542
1077
                }
1543
1078
        }
1544
1079
        else {
1562
1097
 
1563
1098
                        wrap_offset_in_line(st, ar, text->sell, text->selc, &offl, &offc);
1564
1099
 
1565
 
                        y1 = ar->winy - 2 - (vsell - offl) * st->lheight;
1566
 
                        y2 = y1 - st->lheight * visible_lines + 1;
 
1100
                        y1 = ar->winy - 2 - (vsell - offl) * lheight;
 
1101
                        y2 = y1 - (lheight * visible_lines + TXT_LINE_SPACING);
1567
1102
                }
1568
1103
                else {
1569
 
                        y1 = ar->winy - 2 - vsell * st->lheight;
1570
 
                        y2 = y1 - st->lheight + 1;
 
1104
                        y1 = ar->winy - 2 - vsell * lheight;
 
1105
                        y2 = y1 - (lheight + TXT_LINE_SPACING);
1571
1106
                }
1572
1107
 
1573
1108
                if (!(y1 < 0 || y2 > ar->winy)) { /* check we need to draw */
1578
1113
                        
1579
1114
                        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1580
1115
                        glEnable(GL_BLEND);
1581
 
                        glRecti(x1 - 4, y1, x2, y2);
 
1116
                        glRecti(x1 - 4, y1, x2, y2 + TXT_LINE_SPACING);
1582
1117
                        glDisable(GL_BLEND);
1583
1118
                }
1584
1119
        }
1587
1122
                /* Draw the cursor itself (we draw the sel. cursor as this is the leading edge) */
1588
1123
                x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
1589
1124
                x += vselc * st->cwidth;
1590
 
                y = ar->winy - 2 - vsell * st->lheight;
 
1125
                y = ar->winy - vsell * lheight;
1591
1126
                
1592
1127
                if (st->overwrite) {
1593
1128
                        char ch = text->sell->line[text->selc];
1594
1129
                        
 
1130
                        y += TXT_LINE_SPACING;
1595
1131
                        w = st->cwidth;
1596
1132
                        if (ch == '\t') w *= st->tabnumber - (vselc + st->left) % st->tabnumber;
1597
1133
                        
1598
1134
                        UI_ThemeColor(TH_HILITE);
1599
 
                        glRecti(x, y - st->lheight - 1, x + w, y - st->lheight + 1);
 
1135
                        glRecti(x, y - lheight - 1, x + w, y - lheight + 1);
1600
1136
                }
1601
1137
                else {
1602
1138
                        UI_ThemeColor(TH_HILITE);
1603
 
                        glRecti(x - 1, y, x + 1, y - st->lheight);
 
1139
                        glRecti(x - 1, y, x + 1, y - lheight);
1604
1140
                }
1605
1141
        }
1606
1142
}
1634
1170
        stack = 0;
1635
1171
        
1636
1172
        /* Don't highlight backets if syntax HL is off or bracket in string or comment. */
1637
 
        if (!linep->format || linep->format[fc] == 'l' || linep->format[fc] == '#')
 
1173
        if (!linep->format || linep->format[fc] == FMT_TYPE_STRING || linep->format[fc] == FMT_TYPE_COMMENT)
1638
1174
                return;
1639
1175
 
1640
1176
        if (b > 0) {
1641
1177
                /* opening bracket, search forward for close */
1642
1178
                fc++;
1643
 
                c += BLI_str_utf8_size(linep->line + c);
 
1179
                c += BLI_str_utf8_size_safe(linep->line + c);
1644
1180
                while (linep) {
1645
1181
                        while (c < linep->len) {
1646
 
                                if (linep->format && linep->format[fc] != 'l' && linep->format[fc] != '#') {
 
1182
                                if (linep->format && linep->format[fc] != FMT_TYPE_STRING && linep->format[fc] != FMT_TYPE_COMMENT) {
1647
1183
                                        b = text_check_bracket(linep->line[c]);
1648
1184
                                        if (b == find) {
1649
1185
                                                if (stack == 0) {
1658
1194
                                        }
1659
1195
                                }
1660
1196
                                fc++;
1661
 
                                c += BLI_str_utf8_size(linep->line + c);
 
1197
                                c += BLI_str_utf8_size_safe(linep->line + c);
1662
1198
                        }
1663
1199
                        if (endl) break;
1664
1200
                        linep = linep->next;
1672
1208
                if (c > 0) c -= linep->line + c - BLI_str_prev_char_utf8(linep->line + c);
1673
1209
                while (linep) {
1674
1210
                        while (fc >= 0) {
1675
 
                                if (linep->format && linep->format[fc] != 'l' && linep->format[fc] != '#') {
 
1211
                                if (linep->format && linep->format[fc] != FMT_TYPE_STRING && linep->format[fc] != FMT_TYPE_COMMENT) {
1676
1212
                                        b = text_check_bracket(linep->line[c]);
1677
1213
                                        if (b == find) {
1678
1214
                                                if (stack == 0) {
1703
1239
        if (!endl || endc == -1)
1704
1240
                return;
1705
1241
 
1706
 
        UI_ThemeColor(TH_HILITE);       
 
1242
        UI_ThemeColor(TH_HILITE);
1707
1243
        x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
1708
 
        y = ar->winy - st->lheight;
 
1244
        y = ar->winy - st->lheight_dpi;
1709
1245
 
1710
1246
        /* draw opening bracket */
1711
1247
        ch = startl->line[startc];
1715
1251
        if (viewc >= 0) {
1716
1252
                viewl = txt_get_span(text->lines.first, startl) - st->top + offl;
1717
1253
 
1718
 
                text_font_draw_character(st, x + viewc * st->cwidth, y - viewl * st->lheight, ch);
1719
 
                text_font_draw_character(st, x + viewc * st->cwidth + 1, y - viewl * st->lheight, ch);
 
1254
                text_font_draw_character(st, x + viewc * st->cwidth, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch);
 
1255
                text_font_draw_character(st, x + viewc * st->cwidth + 1, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch);
1720
1256
        }
1721
1257
 
1722
1258
        /* draw closing bracket */
1727
1263
        if (viewc >= 0) {
1728
1264
                viewl = txt_get_span(text->lines.first, endl) - st->top + offl;
1729
1265
 
1730
 
                text_font_draw_character(st, x + viewc * st->cwidth, y - viewl * st->lheight, ch);
1731
 
                text_font_draw_character(st, x + viewc * st->cwidth + 1, y - viewl * st->lheight, ch);
 
1266
                text_font_draw_character(st, x + viewc * st->cwidth, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch);
 
1267
                text_font_draw_character(st, x + viewc * st->cwidth + 1, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch);
1732
1268
        }
1733
1269
}
1734
1270
 
1737
1273
void draw_text_main(SpaceText *st, ARegion *ar)
1738
1274
{
1739
1275
        Text *text = st->text;
 
1276
        TextFormatType *tft;
1740
1277
        TextLine *tmp;
1741
1278
        rcti scroll, back;
1742
1279
        char linenr[12];
1743
1280
        int i, x, y, winx, linecount = 0, lineno = 0;
1744
1281
        int wraplinecount = 0, wrap_skip = 0;
 
1282
        int margin_column_x;
1745
1283
 
1746
 
        if (st->lheight) st->viewlines = (int)ar->winy / st->lheight;
 
1284
        /* dpi controlled line height and font size */
 
1285
        st->lheight_dpi = (U.widget_unit * st->lheight) / 20;
 
1286
        
 
1287
        if (st->lheight_dpi) st->viewlines = (int)ar->winy / (st->lheight_dpi + TXT_LINE_SPACING);
1747
1288
        else st->viewlines = 0;
1748
1289
 
1749
1290
        /* if no text, nothing to do */
1760
1301
        calc_text_rcts(st, ar, &scroll, &back); /* scroll will hold the entire bar size */
1761
1302
 
1762
1303
        /* update syntax formatting if needed */
 
1304
        tft = ED_text_format_get(text);
1763
1305
        tmp = text->lines.first;
1764
1306
        lineno = 0;
1765
1307
        for (i = 0; i < st->top && tmp; i++) {
1766
1308
                if (st->showsyntax && !tmp->format)
1767
 
                        txt_format_line(st, tmp, 0);
 
1309
                        tft->format_line(st, tmp, 0);
1768
1310
 
1769
1311
                if (st->wordwrap) {
1770
1312
                        int lines = text_get_visible_lines_no(st, lineno);
1789
1331
 
1790
1332
        text_font_begin(st);
1791
1333
        st->cwidth = BLF_fixed_width(mono);
1792
 
        st->cwidth = MAX2(st->cwidth, 1);
 
1334
        st->cwidth = MAX2(st->cwidth, (char)1);
1793
1335
 
1794
1336
        /* draw line numbers background */
1795
1337
        if (st->showlinenrs) {
1802
1344
                st->linenrs_tot = 0; /* not used */
1803
1345
                x = TXT_OFFSET;
1804
1346
        }
1805
 
        y = ar->winy - st->lheight;
 
1347
        y = ar->winy - st->lheight_dpi;
1806
1348
        winx = ar->winx - TXT_SCROLL_WIDTH;
1807
1349
        
1808
1350
        /* draw cursor */
1813
1355
 
1814
1356
        for (i = 0; y > 0 && i < st->viewlines && tmp; i++, tmp = tmp->next) {
1815
1357
                if (st->showsyntax && !tmp->format)
1816
 
                        txt_format_line(st, tmp, 0);
 
1358
                        tft->format_line(st, tmp, 0);
1817
1359
 
1818
1360
                if (st->showlinenrs && !wrap_skip) {
1819
1361
                        /* draw line number */
1832
1374
                if (st->wordwrap) {
1833
1375
                        /* draw word wrapped text */
1834
1376
                        int lines = text_draw_wrapped(st, tmp->line, x, y, winx - x, tmp->format, wrap_skip);
1835
 
                        y -= lines * st->lheight;
 
1377
                        y -= lines * (st->lheight_dpi + TXT_LINE_SPACING);
1836
1378
                }
1837
1379
                else {
1838
1380
                        /* draw unwrapped text */
1839
1381
                        text_draw(st, tmp->line, st->left, ar->winx / st->cwidth, 1, x, y, tmp->format);
1840
 
                        y -= st->lheight;
 
1382
                        y -= st->lheight_dpi + TXT_LINE_SPACING;
1841
1383
                }
1842
 
 
 
1384
                
1843
1385
                wrap_skip = 0;
1844
1386
        }
1845
1387
        
1846
1388
        if (st->flags & ST_SHOW_MARGIN) {
1847
1389
                UI_ThemeColor(TH_HILITE);
1848
1390
 
1849
 
                glBegin(GL_LINES);
1850
 
                glVertex2i(x + st->cwidth * st->margin_column, 0);
1851
 
                glVertex2i(x + st->cwidth * st->margin_column, ar->winy - 2);
1852
 
                glEnd();
 
1391
                margin_column_x = x + st->cwidth * (st->margin_column - st->left);
 
1392
                
 
1393
                if (margin_column_x >= x) {
 
1394
                        glBegin(GL_LINES);
 
1395
                        glVertex2i(margin_column_x, 0);
 
1396
                        glVertex2i(margin_column_x, ar->winy - 2);
 
1397
                        glEnd();
 
1398
                }
1853
1399
        }
1854
1400
 
1855
1401
        /* draw other stuff */
1856
1402
        draw_brackets(st, ar);
1857
 
        draw_markers(st, ar);
1858
 
        glTranslatef(0.375f, 0.375f, 0.0f); /* XXX scroll requires exact pixel space */
 
1403
        glTranslatef(GLA_PIXEL_OFS, GLA_PIXEL_OFS, 0.0f); /* XXX scroll requires exact pixel space */
1859
1404
        draw_textscroll(st, &scroll, &back);
1860
1405
        draw_documentation(st, ar);
1861
1406
        draw_suggestion_list(st, ar);
1869
1414
{
1870
1415
        text_font_begin(st);
1871
1416
        st->cwidth = BLF_fixed_width(mono);
1872
 
        st->cwidth = MAX2(st->cwidth, 1);
 
1417
        st->cwidth = MAX2(st->cwidth, (char)1);
1873
1418
        text_font_end(st);
1874
1419
}
1875
1420