diff options
author | Campbell Barton <ideasman42@gmail.com> | 2012-12-19 08:02:19 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2012-12-19 08:02:19 +0400 |
commit | f43923d86d0a4d6dbbdc8d7fc05d383a23b3e5e2 (patch) | |
tree | 8167b27c9cfd062892dd503c916eda7e788f6fb2 /source/blender/editors/space_text/text_draw.c | |
parent | bfde24a36836e7b4d9d7721c791abb90ed145024 (diff) |
generalize formatting code so different formatters can be registered and each has their own source file,
Since we will likely have OSL formatting added soon.
Diffstat (limited to 'source/blender/editors/space_text/text_draw.c')
-rw-r--r-- | source/blender/editors/space_text/text_draw.c | 350 |
1 files changed, 4 insertions, 346 deletions
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c index 24f40dbbe2a..2066df39b73 100644 --- a/source/blender/editors/space_text/text_draw.c +++ b/source/blender/editors/space_text/text_draw.c @@ -58,6 +58,7 @@ #include "UI_resources.h" #include "text_intern.h" +#include "text_format.h" /******************** text font drawing ******************/ // XXX, fixme @@ -105,350 +106,6 @@ static int text_font_draw_character_utf8(SpaceText *st, int x, int y, const char return st->cwidth; } -/****************** flatten string **********************/ - -static void flatten_string_append(FlattenString *fs, const char *c, int accum, int len) -{ - int i; - - if (fs->pos + len > fs->len) { - char *nbuf; int *naccum; - fs->len *= 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 * sizeof(*fs->buf)); - memcpy(naccum, fs->accum, fs->pos * sizeof(*fs->accum)); - - if (fs->buf != fs->fixedbuf) { - MEM_freeN(fs->buf); - MEM_freeN(fs->accum); - } - - fs->buf = nbuf; - fs->accum = naccum; - } - - for (i = 0; i < len; i++) { - fs->buf[fs->pos + i] = c[i]; - fs->accum[fs->pos + i] = accum; - } - - fs->pos += len; -} - -int flatten_string(SpaceText *st, FlattenString *fs, const char *in) -{ - int r, i, total = 0; - - memset(fs, 0, sizeof(FlattenString)); - fs->buf = fs->fixedbuf; - fs->accum = fs->fixedaccum; - fs->len = sizeof(fs->fixedbuf); - - for (r = 0, i = 0; *in; r++) { - if (*in == '\t') { - i = st->tabnumber - (total % st->tabnumber); - total += i; - - while (i--) - flatten_string_append(fs, " ", r, 1); - - in++; - } - else { - size_t len = BLI_str_utf8_size_safe(in); - flatten_string_append(fs, in, r, len); - in += len; - total++; - } - } - - flatten_string_append(fs, "\0", r, 1); - - return total; -} - -void flatten_string_free(FlattenString *fs) -{ - if (fs->buf != fs->fixedbuf) - MEM_freeN(fs->buf); - if (fs->accum != fs->fixedaccum) - MEM_freeN(fs->accum); -} - -/* Checks the specified source string for a Python built-in function name. This - * name must start at the beginning of the source string and must be followed by - * a non-identifier (see text_check_identifier(char)) or null character. - * - * If a built-in function is found, the length of the matching name is returned. - * Otherwise, -1 is returned. - * - * See: - * http://docs.python.org/py3k/reference/lexical_analysis.html#keywords - */ - -static int find_builtinfunc(char *string) -{ - int a, i; - const char *builtinfuncs[] = { - /* "False", "None", "True", */ /* see find_bool() */ - "and", "as", "assert", "break", - "class", "continue", "def", "del", "elif", "else", "except", - "finally", "for", "from", "global", "if", "import", "in", - "is", "lambda", "nonlocal", "not", "or", "pass", "raise", - "return", "try", "while", "with", "yield", - }; - - for (a = 0; a < sizeof(builtinfuncs) / sizeof(builtinfuncs[0]); a++) { - i = 0; - while (1) { - /* If we hit the end of a keyword... (eg. "def") */ - if (builtinfuncs[a][i] == '\0') { - /* If we still have identifier chars in the source (eg. "definate") */ - if (text_check_identifier(string[i])) - i = -1; /* No match */ - break; /* Next keyword if no match, otherwise we're done */ - - /* If chars mismatch, move on to next keyword */ - } - else if (string[i] != builtinfuncs[a][i]) { - i = -1; - break; /* Break inner loop, start next keyword */ - } - i++; - } - if (i > 0) break; /* If we have a match, we're done */ - } - return i; -} - -/* Checks the specified source string for a Python special name. This name must - * start at the beginning of the source string and must be followed by a non- - * identifier (see text_check_identifier(char)) or null character. - * - * If a special name is found, the length of the matching name is returned. - * Otherwise, -1 is returned. */ - -static int find_specialvar(char *string) -{ - int i = 0; - /* Check for "def" */ - if (string[0] == 'd' && string[1] == 'e' && string[2] == 'f') - i = 3; - /* Check for "class" */ - else if (string[0] == 'c' && string[1] == 'l' && string[2] == 'a' && string[3] == 's' && string[4] == 's') - i = 5; - /* If next source char is an identifier (eg. 'i' in "definate") no match */ - if (i == 0 || text_check_identifier(string[i])) - return -1; - return i; -} - -static int find_decorator(char *string) -{ - if (string[0] == '@') { - int i = 1; - while (text_check_identifier(string[i])) { - i++; - } - return i; - } - return -1; -} - -static int find_bool(char *string) -{ - int i = 0; - /* Check for "False" */ - if (string[0] == 'F' && string[1] == 'a' && string[2] == 'l' && string[3] == 's' && string[4] == 'e') - i = 5; - /* Check for "True" */ - else if (string[0] == 'T' && string[1] == 'r' && string[2] == 'u' && string[3] == 'e') - i = 4; - /* Check for "None" */ - else if (string[0] == 'N' && string[1] == 'o' && string[2] == 'n' && string[3] == 'e') - i = 4; - /* If next source char is an identifier (eg. 'i' in "definate") no match */ - if (i == 0 || text_check_identifier(string[i])) - return -1; - return i; -} - -/* Ensures the format string for the given line is long enough, reallocating - * as needed. Allocation is done here, alone, to ensure consistency. */ -static int text_check_format_len(TextLine *line, unsigned int len) -{ - if (line->format) { - if (strlen(line->format) < len) { - MEM_freeN(line->format); - line->format = MEM_mallocN(len + 2, "SyntaxFormat"); - if (!line->format) return 0; - } - } - else { - line->format = MEM_mallocN(len + 2, "SyntaxFormat"); - if (!line->format) return 0; - } - - return 1; -} - -/* Formats the specified line. If do_next is set, the process will move on to - * the succeeding line if it is affected (eg. multiline strings). Format strings - * may contain any of the following characters: - * '_' Whitespace - * '#' Comment text - * '!' Punctuation and other symbols - * 'n' Numerals - * 'l' String letters - * 'v' Special variables (class, def) - * 'b' Built-in names (print, for, etc.) - * 'q' Other text (identifiers, etc.) - * It is terminated with a null-terminator '\0' followed by a continuation - * flag indicating whether the line is part of a multi-line string. */ - -static void txt_format_line(SpaceText *st, TextLine *line, int do_next) -{ - FlattenString fs; - char *str, *fmt, orig, cont, find, prev = ' '; - int len, i; - - /* Get continuation from previous line */ - if (line->prev && line->prev->format != NULL) { - fmt = line->prev->format; - cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */ - } - else cont = 0; - - /* Get original continuation from this line */ - if (line->format != NULL) { - fmt = line->format; - orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */ - } - else orig = 0xFF; - - len = flatten_string(st, &fs, line->line); - str = fs.buf; - if (!text_check_format_len(line, len)) { - flatten_string_free(&fs); - return; - } - fmt = line->format; - - while (*str) { - /* Handle escape sequences by skipping both \ and next char */ - if (*str == '\\') { - *fmt = prev; fmt++; str++; - if (*str == '\0') break; - *fmt = prev; fmt++; str += BLI_str_utf8_size_safe(str); - continue; - } - /* Handle continuations */ - else if (cont) { - /* Triple strings ("""...""" or '''...''') */ - if (cont & TXT_TRISTR) { - find = (cont & TXT_DBLQUOTSTR) ? '"' : '\''; - if (*str == find && *(str + 1) == find && *(str + 2) == find) { - *fmt = 'l'; fmt++; str++; - *fmt = 'l'; fmt++; str++; - cont = 0; - } - /* Handle other strings */ - } - else { - find = (cont & TXT_DBLQUOTSTR) ? '"' : '\''; - if (*str == find) cont = 0; - } - - *fmt = 'l'; - str += BLI_str_utf8_size_safe(str) - 1; - } - /* Not in a string... */ - else { - /* Deal with comments first */ - if (prev == '#' || *str == '#') { - *fmt = '#'; - str += BLI_str_utf8_size_safe(str) - 1; - } - else if (*str == '"' || *str == '\'') { - /* Strings */ - find = *str; - cont = (*str == '"') ? TXT_DBLQUOTSTR : TXT_SNGQUOTSTR; - if (*(str + 1) == find && *(str + 2) == find) { - *fmt = 'l'; fmt++; str++; - *fmt = 'l'; fmt++; str++; - cont |= TXT_TRISTR; - } - *fmt = 'l'; - } - /* Whitespace (all ws. has been converted to spaces) */ - else if (*str == ' ') - *fmt = '_'; - /* Numbers (digits not part of an identifier and periods followed by digits) */ - else if ((prev != 'q' && text_check_digit(*str)) || (*str == '.' && text_check_digit(*(str + 1)))) - *fmt = 'n'; - /* Booleans */ - else if (prev != 'q' && (i = find_bool(str)) != -1) - if (i > 0) { - while (i > 1) { - *fmt = 'n'; fmt++; str++; - i--; - } - *fmt = 'n'; - } - else { - str += BLI_str_utf8_size_safe(str) - 1; - *fmt = 'q'; - } - /* Punctuation */ - else if (text_check_delim(*str)) - *fmt = '!'; - /* Identifiers and other text (no previous ws. or delims. so text continues) */ - else if (prev == 'q') { - str += BLI_str_utf8_size_safe(str) - 1; - *fmt = 'q'; - } - /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */ - else { - /* Special vars(v) or built-in keywords(b) */ - if ((i = find_specialvar(str)) != -1) - prev = 'v'; - else if ((i = find_builtinfunc(str)) != -1) - prev = 'b'; - else if ((i = find_decorator(str)) != -1) - prev = 'v'; /* could have a new color for this */ - if (i > 0) { - while (i > 1) { - *fmt = prev; fmt++; str++; - i--; - } - *fmt = prev; - } - else { - str += BLI_str_utf8_size_safe(str) - 1; - *fmt = 'q'; - } - } - } - prev = *fmt; - fmt++; - str++; - } - - /* Terminate and add continuation char */ - *fmt = '\0'; fmt++; - *fmt = cont; - - /* If continuation has changed and we're allowed, process the next line */ - if (cont != orig && do_next && line->next) { - txt_format_line(st, line->next, do_next); - } - - flatten_string_free(&fs); -} - #if 0 /* Formats every line of the current text */ static void txt_format_text(SpaceText *st) @@ -1620,6 +1277,7 @@ static void draw_brackets(SpaceText *st, ARegion *ar) void draw_text_main(SpaceText *st, ARegion *ar) { Text *text = st->text; + TextFormatType *tft = ED_text_format_get(text); TextLine *tmp; rcti scroll, back; char linenr[12]; @@ -1651,7 +1309,7 @@ void draw_text_main(SpaceText *st, ARegion *ar) lineno = 0; for (i = 0; i < st->top && tmp; i++) { if (st->showsyntax && !tmp->format) - txt_format_line(st, tmp, 0); + tft->format_line(st, tmp, 0); if (st->wordwrap) { int lines = text_get_visible_lines_no(st, lineno); @@ -1700,7 +1358,7 @@ void draw_text_main(SpaceText *st, ARegion *ar) for (i = 0; y > 0 && i < st->viewlines && tmp; i++, tmp = tmp->next) { if (st->showsyntax && !tmp->format) - txt_format_line(st, tmp, 0); + tft->format_line(st, tmp, 0); if (st->showlinenrs && !wrap_skip) { /* draw line number */ |