Console: add support for displaying tab-stops

Without this it was necessary to convert pasted text into spaces
for them to display properly.

Since tabs are a valid part of a string, it's incorrect to assume
tabs can always be expanded to spaces.

Pasted text and console output now display tabs properly,
the tab still uses spaces for indenting though.
This commit is contained in:
Campbell Barton
2023-09-22 13:16:28 +10:00
parent 18e07098ef
commit a5cd497543
10 changed files with 45 additions and 36 deletions

View File

@@ -34,8 +34,7 @@ class _TempModuleOverride:
def add_scrollback(text, text_type):
for l in text.split("\n"):
bpy.ops.console.scrollback_append(text=l.replace("\t", " "),
type=text_type)
bpy.ops.console.scrollback_append(text=l, type=text_type)
def replace_help(namespace):

View File

@@ -122,7 +122,8 @@ void BLF_batch_draw_end(void);
void BLF_draw_ex(int fontid, const char *str, size_t str_len, struct ResultBLF *r_info)
ATTR_NONNULL(2);
void BLF_draw(int fontid, const char *str, size_t str_len) ATTR_NONNULL(2);
int BLF_draw_mono(int fontid, const char *str, size_t str_len, int cwidth) ATTR_NONNULL(2);
int BLF_draw_mono(int fontid, const char *str, size_t str_len, int cwidth, int tab_columns)
ATTR_NONNULL(2);
typedef bool (*BLF_GlyphBoundsFn)(const char *str,
size_t str_step_ofs,

View File

@@ -570,7 +570,7 @@ void BLF_draw(int fontid, const char *str, const size_t str_len)
BLF_draw_ex(fontid, str, str_len, nullptr);
}
int BLF_draw_mono(int fontid, const char *str, const size_t str_len, int cwidth)
int BLF_draw_mono(int fontid, const char *str, const size_t str_len, int cwidth, int tab_columns)
{
if (str_len == 0 || str[0] == '\0') {
return 0;
@@ -581,7 +581,7 @@ int BLF_draw_mono(int fontid, const char *str, const size_t str_len, int cwidth)
if (font) {
blf_draw_gl__start(font);
columns = blf_font_draw_mono(font, str, str_len, cwidth);
columns = blf_font_draw_mono(font, str, str_len, cwidth, tab_columns);
blf_draw_gl__end(font);
}

View File

@@ -464,7 +464,8 @@ void blf_font_draw(FontBLF *font, const char *str, const size_t str_len, ResultB
blf_glyph_cache_release(font);
}
int blf_font_draw_mono(FontBLF *font, const char *str, const size_t str_len, int cwidth)
int blf_font_draw_mono(
FontBLF *font, const char *str, const size_t str_len, int cwidth, int tab_columns)
{
GlyphBLF *g;
int columns = 0;
@@ -486,7 +487,8 @@ int blf_font_draw_mono(FontBLF *font, const char *str, const size_t str_len, int
/* do not return this loop if clipped, we want every character tested */
blf_glyph_draw(font, gc, g, ft_pix_to_int_floor(pen_x), ft_pix_to_int_floor(pen_y));
const int col = BLI_wcwidth_safe(char32_t(g->c));
const int col = UNLIKELY(g->c == '\t') ? (tab_columns - (columns % tab_columns)) :
BLI_wcwidth_safe(char32_t(g->c));
columns += col;
pen_x += cwidth_fpx * col;
}

View File

@@ -103,7 +103,8 @@ void blf_font_draw__wrap(struct FontBLF *font,
/**
* Use fixed column width, but an utf8 character may occupy multiple columns.
*/
int blf_font_draw_mono(struct FontBLF *font, const char *str, size_t str_len, int cwidth);
int blf_font_draw_mono(
struct FontBLF *font, const char *str, size_t str_len, int cwidth, int tab_columns);
void blf_font_draw_buffer(struct FontBLF *font,
const char *str,
size_t str_len,

View File

@@ -112,9 +112,11 @@ static void console_cursor_wrap_offset(
const char *str, int width, int *row, int *column, const char *end)
{
int col;
const int tab_width = 4;
for (; *str; str += BLI_str_utf8_size_safe(str)) {
col = BLI_str_utf8_char_width_safe(str);
col = UNLIKELY(*str == '\t') ? (tab_width - (*column % tab_width)) :
BLI_str_utf8_char_width_safe(str);
if (*column + col > width) {
(*row)++;

View File

@@ -36,6 +36,8 @@
#include "console_intern.hh"
#define TAB_LENGTH 4
/* -------------------------------------------------------------------- */
/** \name Utilities
* \{ */
@@ -488,25 +490,13 @@ void CONSOLE_OT_move(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
#define TAB_LENGTH 4
static int console_insert_exec(bContext *C, wmOperator *op)
{
SpaceConsole *sc = CTX_wm_space_console(C);
ARegion *region = CTX_wm_region(C);
ConsoleLine *ci = console_history_verify(C);
char *str = RNA_string_get_alloc(op->ptr, "text", nullptr, 0, nullptr);
int len;
if (str[0] == '\t' && str[1] == '\0') {
len = TAB_LENGTH;
MEM_freeN(str);
str = static_cast<char *>(MEM_mallocN(len + 1, "insert_exec"));
memset(str, ' ', len);
str[len] = '\0';
}
else {
len = strlen(str);
}
int len = strlen(str);
/* Allow trailing newlines (but strip them). */
while (len > 0 && str[len - 1] == '\n') {

View File

@@ -69,8 +69,10 @@ static void textview_draw_sel(const char *str,
const int lheight = tds->lheight;
if (sel[0] <= str_len_draw && sel[1] >= 0) {
const int sta = BLI_str_utf8_offset_to_column(str, str_len_draw, max_ii(sel[0], 0));
const int end = BLI_str_utf8_offset_to_column(str, str_len_draw, min_ii(sel[1], str_len_draw));
const int sta = BLI_str_utf8_offset_to_column_with_tabs(
str, str_len_draw, max_ii(sel[0], 0), TVC_TAB_COLUMNS);
const int end = BLI_str_utf8_offset_to_column_with_tabs(
str, str_len_draw, min_ii(sel[1], str_len_draw), TVC_TAB_COLUMNS);
GPU_blend(GPU_BLEND_ALPHA);
@@ -96,17 +98,20 @@ static int textview_wrap_offsets(
{
int i, end; /* Offset as unicode code-point. */
int j; /* Offset as bytes. */
const int tab_columns = TVC_TAB_COLUMNS;
const int column_width_max = MAX2(tab_columns, BLI_UTF8_WIDTH_MAX);
*r_lines = 1;
*r_offsets = static_cast<int *>(MEM_callocN(
sizeof(**r_offsets) *
(str_len * BLI_UTF8_WIDTH_MAX / MAX2(1, width - (BLI_UTF8_WIDTH_MAX - 1)) + 1),
__func__));
*r_offsets = static_cast<int *>(
MEM_callocN(sizeof(**r_offsets) *
(str_len * column_width_max / MAX2(1, width - (column_width_max - 1)) + 1),
__func__));
(*r_offsets)[0] = 0;
for (i = 0, end = width, j = 0; j < str_len && str[j]; j += BLI_str_utf8_size_safe(str + j)) {
int columns = BLI_str_utf8_char_width_safe(str + j);
int columns = UNLIKELY(*(str + j) == '\t') ? (tab_columns - (i % tab_columns)) :
BLI_str_utf8_char_width_safe(str + j);
if (i + columns > end) {
(*r_offsets)[*r_lines] = j;
@@ -157,8 +162,11 @@ static bool textview_draw_string(TextViewDrawState *tds,
}
/* Last part. */
ofs += BLI_str_utf8_offset_from_column(
str + ofs, str_len - ofs, int(floor(float(tds->mval[0]) / tds->cwidth)));
ofs += BLI_str_utf8_offset_from_column_with_tabs(
str + ofs,
str_len - ofs,
int(floor(float(tds->mval[0]) / tds->cwidth)),
TVC_TAB_COLUMNS);
CLAMP(ofs, 0, str_len);
*tds->mval_pick_offset += str_len - ofs;
@@ -255,7 +263,7 @@ static bool textview_draw_string(TextViewDrawState *tds,
BLF_position(tds->font_id, tds->xy[0], tds->lofs + line_bottom + tds->row_vpadding, 0);
BLF_color4ubv(tds->font_id, fg);
BLF_draw_mono(tds->font_id, s, len, tds->cwidth);
BLF_draw_mono(tds->font_id, s, len, tds->cwidth, TVC_TAB_COLUMNS);
tds->xy[1] += tds->lheight;
@@ -271,7 +279,7 @@ static bool textview_draw_string(TextViewDrawState *tds,
}
BLF_position(tds->font_id, tds->xy[0], tds->lofs + tds->xy[1], 0);
BLF_draw_mono(tds->font_id, s, len, tds->cwidth);
BLF_draw_mono(tds->font_id, s, len, tds->cwidth, TVC_TAB_COLUMNS);
tds->xy[1] += tds->lheight;

View File

@@ -8,6 +8,8 @@
#pragma once
#define TVC_TAB_COLUMNS 4
enum eTextViewContext_LineFlag {
TVC_LINE_FG = (1 << 0),
TVC_LINE_BG = (1 << 1),

View File

@@ -64,16 +64,19 @@ static void text_font_end(const TextDrawContext * /*tdc*/) {}
static int text_font_draw(const TextDrawContext *tdc, int x, int y, const char *str)
{
const char tab_columns = 1; /* Tab characters aren't used here. */
BLF_position(tdc->font_id, x, y, 0);
const int columns = BLF_draw_mono(tdc->font_id, str, BLF_DRAW_STR_DUMMY_MAX, tdc->cwidth_px);
const int columns = BLF_draw_mono(
tdc->font_id, str, BLF_DRAW_STR_DUMMY_MAX, tdc->cwidth_px, tab_columns);
return tdc->cwidth_px * columns;
}
static int text_font_draw_character(const TextDrawContext *tdc, int x, int y, char c)
{
const char tab_columns = 1;
BLF_position(tdc->font_id, x, y, 0);
BLF_draw_mono(tdc->font_id, &c, 1, tdc->cwidth_px);
BLF_draw_mono(tdc->font_id, &c, 1, tdc->cwidth_px, tab_columns);
return tdc->cwidth_px;
}
@@ -82,8 +85,9 @@ static int text_font_draw_character_utf8(
const TextDrawContext *tdc, int x, int y, const char *c, const int c_len)
{
BLI_assert(c_len == BLI_str_utf8_size_safe(c));
const char tab_columns = 1; /* Tab characters aren't used here. */
BLF_position(tdc->font_id, x, y, 0);
const int columns = BLF_draw_mono(tdc->font_id, c, c_len, tdc->cwidth_px);
const int columns = BLF_draw_mono(tdc->font_id, c, c_len, tdc->cwidth_px, tab_columns);
return tdc->cwidth_px * columns;
}