Example #1
0
static void text_draw(
        const SpaceText *st, const TextDrawContext *tdc,
        char *str, int cshift, int maxwidth, int x, int y, const char *format)
{
	const bool use_syntax = (st->showsyntax && format);
	FlattenString fs;
	int columns, size, n, w = 0, padding, amount = 0;
	const char *in = NULL;

	for (n = flatten_string(st, &fs, str), str = fs.buf; n > 0; n--) {
		columns = BLI_str_utf8_char_width_safe(str);
		size = BLI_str_utf8_size_safe(str);

		if (!in) {
			if (w >= cshift) {
				padding = w - cshift;
				in = str;
			}
			else if (format)
				format++;
		}
		if (in) {
			if (maxwidth && w + columns > cshift + maxwidth)
				break;
			amount++;
		}

		w += columns;
		str += size;
	}
	if (!in) {
		flatten_string_free(&fs);
		return; /* String is shorter than shift or ends with a padding */
	}

	x += tdc->cwidth * padding;

	if (use_syntax) {
		int a, str_shift = 0;
		char fmt_prev = 0xff;

		for (a = 0; a < amount; a++) {
			if (format[a] != fmt_prev) format_draw_color(fmt_prev = format[a]);
			x += text_font_draw_character_utf8(tdc, x, y, in + str_shift);
			str_shift += BLI_str_utf8_size_safe(in + str_shift);
		}
	}
	else {
		text_font_draw(tdc, x, y, in);
	}

	flatten_string_free(&fs);
}
int flatten_string(const 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;
}
Example #3
0
static int console_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
	// if (!RNA_struct_property_is_set(op->ptr, "text")) { /* always set from keymap XXX */
	if (!RNA_string_length(op->ptr, "text")) {
		/* if alt/ctrl/super are pressed pass through except for utf8 character event
		 * (when input method are used for utf8 inputs, the user may assign key event
		 * including alt/ctrl/super like ctrl+m to commit utf8 string.  in such case,
		 * the modifiers in the utf8 character event make no sense.) */
		if ((event->ctrl || event->oskey) && !event->utf8_buf[0]) {
			return OPERATOR_PASS_THROUGH;
		}
		else {
			char str[BLI_UTF8_MAX + 1];
			size_t len;
			
			if (event->utf8_buf[0]) {
				len = BLI_str_utf8_size_safe(event->utf8_buf);
				memcpy(str, event->utf8_buf, len);
			}
			else {
				/* in theory, ghost can set value to extended ascii here */
				len = BLI_str_utf8_from_unicode(event->ascii, str);
			}
			str[len] = '\0';
			RNA_string_set(op->ptr, "text", str);
		}
	}
	return console_insert_exec(C, op);
}
Example #4
0
static int text_font_draw_character_utf8(const TextDrawContext *tdc, int x, int y, const char *c)
{
	int columns;

	const size_t len = BLI_str_utf8_size_safe(c);
	BLF_position(tdc->font_id, x, y, 0);
	columns = BLF_draw_mono(tdc->font_id, c, len, tdc->cwidth);

	return tdc->cwidth * columns;
}
Example #5
0
static int text_font_draw_character_utf8(SpaceText *st, int x, int y, const char *c)
{
	int columns;

	const size_t len = BLI_str_utf8_size_safe(c);
	BLF_position(mono, x, y, 0);
	columns = BLF_draw_mono(mono, c, len, st->cwidth);

	return st->cwidth * columns;
}
Example #6
0
int text_get_char_pos(SpaceText *st, const char *line, int cur)
{
	int a = 0, i;
	
	for (i = 0; i < cur && line[i]; i += BLI_str_utf8_size_safe(line + i)) {
		if (line[i] == '\t')
			a += st->tabnumber - a % st->tabnumber;
		else
			a += BLI_str_utf8_char_width_safe(line + i);
	}
	return a;
}
Example #7
0
static const char *txt_utf8_forward_columns(const char *str, int columns, int *padding)
{
	int col;
	const char *p = str;
	while (*p) {
		col = BLI_str_utf8_char_width(p);
		if (columns - col < 0)
			break;
		columns -= col;
		p += BLI_str_utf8_size_safe(p);
		if (columns == 0)
			break;
	}
	if (padding)
		*padding = *p ? columns : 0;
	return p;
}
static void console_cursor_wrap_offset(const char *str, int width, int *row, int *column, const char *end)
{
	int col;

	for (; *str; str += BLI_str_utf8_size_safe(str)) {
		col = BLI_str_utf8_char_width_safe(str);

		if (*column + col > width) {
			(*row)++;
			*column = 0;
		}

		if (end && str >= end)
			break;

		*column += col;
	}
	return;
}
/**
 * Fill the string with formatting constant,
 * advancing \a str_p and \a fmt_p
 *
 * \param len length in bytes of \a fmt_p to fill.
 */
void text_format_fill(const char **str_p, char **fmt_p, const char type, const int len)
{
	const char *str = *str_p;
	char *fmt = *fmt_p;
	int i = 0;

	while (i < len) {
		const int size = BLI_str_utf8_size_safe(str);
		*fmt++ = type;

		str += size;
		i   += 1;
	}

	str--;
	fmt--;

	BLI_assert(*str != '\0');

	*str_p = str;
	*fmt_p = fmt;
}
Example #10
0
int text_get_visible_lines(SpaceText *st, ARegion *ar, const char *str)
{
	int i, j, start, end, max, lines, chars;
	char ch;

	max = wrap_width(st, ar);
	lines = 1;
	start = 0;
	end = max;
	for (i = 0, j = 0; str[j]; j += BLI_str_utf8_size_safe(str + j)) {
		int columns = BLI_str_utf8_char_width_safe(str + j); /* = 1 for tab */

		/* Mimic replacement of tabs */
		ch = str[j];
		if (ch == '\t') {
			chars = st->tabnumber - i % st->tabnumber;
			ch = ' ';
		}
		else {
			chars = 1;
		}

		while (chars--) {
			if (i + columns - start > max) {
				lines++;
				start = MIN2(end, i);
				end += max;
			}
			else if (ch == ' ' || ch == '-') {
				end = i + 1;
			}

			i += columns;
		}
	}

	return lines;
}
Example #11
0
/* warning: allocated memory for 'offsets' must be freed by caller */
static int console_wrap_offsets(const char *str, int len, int width, int *lines, int **offsets)
{
	int i, end;  /* column */
	int j;       /* mem */

	*lines = 1;

	*offsets = MEM_callocN(sizeof(**offsets) * (len * BLI_UTF8_WIDTH_MAX / MAX2(1, width - (BLI_UTF8_WIDTH_MAX - 1)) + 1),
	                       "console_wrap_offsets");
	(*offsets)[0] = 0;

	for (i = 0, end = width, j = 0; j < len && str[j]; j += BLI_str_utf8_size_safe(str + j)) {
		int columns = BLI_str_utf8_char_width_safe(str + j);

		if (i + columns > end) {
			(*offsets)[*lines] = j;
			(*lines)++;

			end = i + width;
		}
		i += columns;
	}
	return j; /* return actual length */
}
Example #12
0
static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w, const char *format, int skip)
{
	FlattenString fs;
	int basex, lines;
	int i, wrap, end, max, columns, padding; /* column */
	int a, fstart, fpos;                     /* utf8 chars */
	int mi, ma, mstart, mend;                /* mem */
	char fmt_prev = 0xff;
	
	flatten_string(st, &fs, str);
	str = fs.buf;
	max = w / st->cwidth;
	if (max < 8) max = 8;
	basex = x;
	lines = 1;
	
	fpos = fstart = 0; mstart = 0;
	mend = txt_utf8_forward_columns(str, max, &padding) - str;
	end = wrap = max - padding;
	
	for (i = 0, mi = 0; str[mi]; i += columns, mi += BLI_str_utf8_size_safe(str + mi)) {
		columns = BLI_str_utf8_char_width_safe(str + mi);
		if (i + columns > end) {
			/* skip hidden part of line */
			if (skip) {
				skip--;
				fstart = fpos; mstart = mend;
				mend = txt_utf8_forward_columns(str + mend, max, &padding) - str;
				end = (wrap += max - padding);
				continue;
			}

			/* Draw the visible portion of text on the overshot line */
			for (a = fstart, ma = mstart; ma < mend; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
				if (st->showsyntax && format) {
					if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]);
				}
				x += text_font_draw_character_utf8(st, x, y, str + ma);
				fpos++;
			}
			y -= st->lheight_dpi + TXT_LINE_SPACING;
			x = basex;
			lines++;
			fstart = fpos; mstart = mend;
			mend = txt_utf8_forward_columns(str + mend, max, &padding) - str;
			end = (wrap += max - padding);

			if (y <= 0) break;
		}
		else if (str[mi] == ' ' || str[mi] == '-') {
			wrap = i + 1; mend = mi + 1;
		}
	}

	/* Draw the remaining text */
	for (a = fstart, ma = mstart; str[ma] && y > 0; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
		if (st->showsyntax && format) {
			if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]);
		}

		x += text_font_draw_character_utf8(st, x, y, str + ma);
	}

	flatten_string_free(&fs);

	return lines;
}
Example #13
0
static int text_draw_wrapped(
        const SpaceText *st, const TextDrawContext *tdc,
        const char *str, int x, int y, int w, const char *format, int skip)
{
	const bool use_syntax = (st->showsyntax && format);
	FlattenString fs;
	int basex, lines;
	int i, wrap, end, max, columns, padding; /* column */
	/* warning, only valid when 'use_syntax' is set */
	int a, fstart, fpos;                     /* utf8 chars */
	int mi, ma, mstart, mend;                /* mem */
	char fmt_prev = 0xff;
	/* don't draw lines below this */
	const int clip_min_y = -(int)(st->lheight_dpi - 1);

	flatten_string(st, &fs, str);
	str = fs.buf;
	max = w / st->cwidth;
	if (max < 8) max = 8;
	basex = x;
	lines = 1;
	
	fpos = fstart = 0; mstart = 0;
	mend = txt_utf8_forward_columns(str, max, &padding) - str;
	end = wrap = max - padding;
	
	for (i = 0, mi = 0; str[mi]; i += columns, mi += BLI_str_utf8_size_safe(str + mi)) {
		columns = BLI_str_utf8_char_width_safe(str + mi);
		if (i + columns > end) {
			/* skip hidden part of line */
			if (skip) {
				skip--;
				if (use_syntax) {
					/* currently fpos only used when formatting */
					fpos += BLI_strnlen_utf8(str + mstart, mend - mstart);
				}
				fstart = fpos; mstart = mend;
				mend = txt_utf8_forward_columns(str + mend, max, &padding) - str;
				end = (wrap += max - padding);
				continue;
			}

			/* Draw the visible portion of text on the overshot line */
			for (a = fstart, ma = mstart; ma < mend; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
				if (use_syntax) {
					if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]);
				}
				x += text_font_draw_character_utf8(tdc, x, y, str + ma);
				fpos++;
			}
			y -= st->lheight_dpi + TXT_LINE_SPACING;
			x = basex;
			lines++;
			fstart = fpos; mstart = mend;
			mend = txt_utf8_forward_columns(str + mend, max, &padding) - str;
			end = (wrap += max - padding);

			if (y <= clip_min_y)
				break;
		}
		else if (str[mi] == ' ' || str[mi] == '-') {
			wrap = i + 1; mend = mi + 1;
		}
	}

	/* Draw the remaining text */
	for (a = fstart, ma = mstart; str[ma] && y > clip_min_y; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
		if (use_syntax) {
			if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]);
		}

		x += text_font_draw_character_utf8(tdc, x, y, str + ma);
	}

	flatten_string_free(&fs);

	return lines;
}
Example #14
0
/* cursin - mem, offc - view */
void wrap_offset_in_line(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int *offl, int *offc)
{
	int i, j, start, end, chars, max, chop;
	char ch;

	*offl = *offc = 0;

	if (!st->text) return;
	if (!st->wordwrap) return;

	max = wrap_width(st, ar);

	start = 0;
	end = max;
	chop = 1;
	*offc = 0;
	cursin = txt_utf8_offset_to_column(linein->line, cursin);

	for (i = 0, j = 0; linein->line[j]; j += BLI_str_utf8_size_safe(linein->line + j)) {
		int columns = BLI_str_utf8_char_width_safe(linein->line + j); /* = 1 for tab */

		/* Mimic replacement of tabs */
		ch = linein->line[j];
		if (ch == '\t') {
			chars = st->tabnumber - i % st->tabnumber;
			if (i < cursin) cursin += chars - 1;
			ch = ' ';
		}
		else
			chars = 1;

		while (chars--) {
			if (i + columns - start > max) {
				end = MIN2(end, i);

				if (chop && i >= cursin) {
					if (i == cursin) {
						(*offl)++;
						*offc -= end - start;
					}

					return;
				}

				(*offl)++;
				*offc -= end - start;

				start = end;
				end += max;
				chop = 1;
			}
			else if (ch == ' ' || ch == '-') {
				end = i + 1;
				chop = 0;
				if (i >= cursin)
					return;
			}
			i += columns;
		}
	}
}
Example #15
0
/* Sets (offl, offc) for transforming (line, curs) to its wrapped position */
void wrap_offset(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int *offl, int *offc)
{
	Text *text;
	TextLine *linep;
	int i, j, start, end, max, chop;
	char ch;

	*offl = *offc = 0;

	if (!st->text) return;
	if (!st->wordwrap) return;

	text = st->text;

	/* Move pointer to first visible line (top) */
	linep = text->lines.first;
	i = st->top;
	while (i > 0 && linep) {
		int lines = text_get_visible_lines(st, ar, linep->line);

		/* Line before top */
		if (linep == linein) {
			if (lines <= i)
				/* no visible part of line */
				return;
		}

		if (i - lines < 0) {
			break;
		}
		else {
			linep = linep->next;
			(*offl) += lines - 1;
			i -= lines;
		}
	}

	max = wrap_width(st, ar);
	cursin = txt_utf8_offset_to_column(linein->line, cursin);

	while (linep) {
		start = 0;
		end = max;
		chop = 1;
		*offc = 0;
		for (i = 0, j = 0; linep->line[j]; j += BLI_str_utf8_size_safe(linep->line + j)) {
			int chars;
			int columns = BLI_str_utf8_char_width_safe(linep->line + j); /* = 1 for tab */

			/* Mimic replacement of tabs */
			ch = linep->line[j];
			if (ch == '\t') {
				chars = st->tabnumber - i % st->tabnumber;
				if (linep == linein && i < cursin) cursin += chars - 1;
				ch = ' ';
			}
			else {
				chars = 1;
			}

			while (chars--) {
				if (i + columns - start > max) {
					end = MIN2(end, i);

					if (chop && linep == linein && i >= cursin) {
						if (i == cursin) {
							(*offl)++;
							*offc -= end - start;
						}

						return;
					}

					(*offl)++;
					*offc -= end - start;

					start = end;
					end += max;
					chop = 1;
				}
				else if (ch == ' ' || ch == '-') {
					end = i + 1;
					chop = 0;
					if (linep == linein && i >= cursin)
						return;
				}
				i += columns;
			}
		}
		if (linep == linein) break;
		linep = linep->next;
	}
}
Example #16
0
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);
	}
}
Example #17
0
static void txtfmt_lua_format_line(SpaceText *st, TextLine *line, const bool do_next)
{
	FlattenString fs;
	const char *str;
	char *fmt;
	char cont_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 */
		BLI_assert((FMT_CONT_ALL & cont) == cont);
	}
	else {
		cont = FMT_CONT_NOP;
	}

	/* Get original continuation from this line */
	if (line->format != NULL) {
		fmt = line->format;
		cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
		BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig);
	}
	else {
		cont_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) {
			/* Multi-line comments */
			if (cont & FMT_CONT_COMMENT_C) {
				if (*str == ']' && *(str + 1) == ']') {
					*fmt = FMT_TYPE_COMMENT; fmt++; str++;
					*fmt = FMT_TYPE_COMMENT;
					cont = FMT_CONT_NOP;
				}
				else {
					*fmt = FMT_TYPE_COMMENT;
				}
				/* Handle other comments */
			}
			else {
				find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
				if (*str == find) cont = 0;
				*fmt = FMT_TYPE_STRING;
			}

			str += BLI_str_utf8_size_safe(str) - 1;
		}
		/* Not in a string... */
		else {
			/* Multi-line comments */
			if (*str == '-'       && *(str + 1) == '-' &&
			    *(str + 2) == '[' && *(str + 3) == '[')
			{
				cont = FMT_CONT_COMMENT_C;
				*fmt = FMT_TYPE_COMMENT; fmt++; str++;
				*fmt = FMT_TYPE_COMMENT; fmt++; str++;
				*fmt = FMT_TYPE_COMMENT; fmt++; str++;
				*fmt = FMT_TYPE_COMMENT;
			}
			/* Single line comment */
			else if (*str == '-' && *(str + 1) == '-') {
				text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(fmt - line->format));
			}
			else if (*str == '"' || *str == '\'') {
				/* Strings */
				find = *str;
				cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
				*fmt = FMT_TYPE_STRING;
			}
			/* Whitespace (all ws. has been converted to spaces) */
			else if (*str == ' ') {
				*fmt = FMT_TYPE_WHITESPACE;
			}
			/* Numbers (digits not part of an identifier and periods followed by digits) */
			else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) ||
			         (*str == '.' && text_check_digit(*(str + 1))))
			{
				*fmt = FMT_TYPE_NUMERAL;
			}
			/* Booleans */
			else if (prev != FMT_TYPE_DEFAULT && (i = txtfmt_lua_find_bool(str)) != -1) {
				if (i > 0) {
					text_format_fill_ascii(&str, &fmt, FMT_TYPE_NUMERAL, i);
				}
				else {
					str += BLI_str_utf8_size_safe(str) - 1;
					*fmt = FMT_TYPE_DEFAULT;
				}
			}
			/* Punctuation */
			else if ((*str != '#') && text_check_delim(*str)) {
				*fmt = FMT_TYPE_SYMBOL;
			}
			/* Identifiers and other text (no previous ws. or delims. so text continues) */
			else if (prev == FMT_TYPE_DEFAULT) {
				str += BLI_str_utf8_size_safe(str) - 1;
				*fmt = FMT_TYPE_DEFAULT;
			}
			/* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
			else {
				/* Special vars(v) or built-in keywords(b) */
				/* keep in sync with 'txtfmt_osl_format_identifier()' */
				if      ((i = txtfmt_lua_find_specialvar(str))   != -1) prev = FMT_TYPE_SPECIAL;
				else if ((i = txtfmt_lua_find_keyword(str))      != -1) prev = FMT_TYPE_KEYWORD;

				if (i > 0) {
					text_format_fill_ascii(&str, &fmt, prev, i);
				}
				else {
					str += BLI_str_utf8_size_safe(str) - 1;
					*fmt = FMT_TYPE_DEFAULT;
				}
			}
		}
		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 != cont_orig && do_next && line->next) {
		txtfmt_lua_format_line(st, line->next, do_next);
	}

	flatten_string_free(&fs);
}