RMichelsen / Nvy

Nvy - A Neovim client in C++
MIT License
333 stars 28 forks source link

file name is not correctly displayed on status line when it contains Japanese character #103

Closed bsdfan closed 1 year ago

bsdfan commented 1 year ago

When file name contains Japanese character, it is not displayed correctly on status line.

For example, file name is "abc日本語.txt". Only "ab" is displayed. j-1

With some colorschme, I can see all file name, but color is strange. j-2

This issue occurs in versions 0.3.7 and 0.3.8, but not in 0.3.6.

R00dRallec commented 1 year ago

I have a similar observation regarding text and colors since 0.3.7 (added Unicode support). In my statusline (lualine.nvim), the text color is different, compared to plain Terminal instance.

Expected behavior (Nvy <= 0.3.6, Windows Terminal, Neovide or nvim-qt): image

Actual behavior (Nvy > 0.3.6): image

After setting colorscheme to 'murphy' (Nvy <= 0.3.6, Windows Terminal, Neovide or nvim-qt): image

After setting colorscheme to 'murphy' (Nvy > 0.3.6): image

calbonaler commented 1 year ago

I experienced a similar issue. In my case, it occurs even when the filename or path has no Japanese characters. image But the whole filename can be seen depending on the colorscheme, which is similar to the @bsdfan's comment. image

I took a look for the source code, and probably found the cause. DrawGridLine function first calls ConvertToWide function, which sets Renderer::wchar_buffer_length according to the input length, in this case, to the wchar_t length of the grid characters. But, afterward, in DrawGridLine function, ConvertToWide function is called (indirectly) with different input lengths a few times and Renderer::wchar_buffer_length is rewritten. In this way, the end of the range passed to ApplyHighlightAttributes and SetTypography functions is no longer the length of the grid characters, resulting in the incorrect range being highlighted.

This can seem to be fixed by saving the Renderer::wchar_buffer_length before being rewritten as follows: In src/renderer/renderer.cpp from line 547:

    IDWriteTextLayout *temp_text_layout = nullptr;
    ConvertToWide(renderer, &renderer->grid_chars[base], renderer->grid_cols);
    WIN_CHECK(renderer->dwrite_factory->CreateTextLayout(
        renderer->wchar_buffer,
        renderer->wchar_buffer_length,
        renderer->dwrite_text_format,
        rect.right - rect.left,
        rect.bottom - rect.top,
        &temp_text_layout
    ));
+   size_t grid_chars_length = renderer->wchar_buffer_length;
    IDWriteTextLayout1 *text_layout;
    temp_text_layout->QueryInterface<IDWriteTextLayout1>(&text_layout);
    temp_text_layout->Release();

In src/renderer/renderer.cpp from line 619:

    // Draw the remaining columns, there is always atleast the last column to draw,
    // but potentially more in case the last X columns share the same hl_attrib
    D2D1_RECT_F last_rect = rect;
    last_rect.left = col_offset * renderer->font_width;
    DrawBackgroundRect(renderer, last_rect, &renderer->hl_attribs[hl_attrib_id]);
-   ApplyHighlightAttributes(renderer, &renderer->hl_attribs[hl_attrib_id], text_layout, col_offset_wchars, renderer->wchar_buffer_length);
+   ApplyHighlightAttributes(renderer, &renderer->hl_attribs[hl_attrib_id], text_layout, col_offset_wchars, grid_chars_length);

    renderer->d2d_context->PushAxisAlignedClip(rect, D2D1_ANTIALIAS_MODE_ALIASED);
    if(renderer->disable_ligatures) {
        text_layout->SetTypography(renderer->dwrite_typography, DWRITE_TEXT_RANGE { 
            .startPosition = 0, 
-           .length = static_cast<uint32_t>(renderer->wchar_buffer_length)
+           .length = static_cast<uint32_t>(grid_chars_length)
        });
    }
    text_layout->Draw(renderer, renderer->glyph_renderer, 0.0f, rect.top);
    renderer->d2d_context->PopAxisAlignedClip();
    text_layout->Release();
R00dRallec commented 1 year ago

@calbonaler Your proposed patch fixes the observation from my comment with regards to the coloring in the statusline.