mojira.dev
MC-30217

All text fields can cut off the last few characters / Phantom selection highlighting appears at the end of text fields with some texts

The bug

All text fields can cut off the last few characters and display them incorrectly, see for example

[media]

.

How to reproduce

  1. Paste (or write) the following text in chat or in a command block

    iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii_
  2. Look at the end of the text field
    → ❌ The last characters are cut off and are displayed incorrectly

Code analysis

The following is based on decompiled version of Minecraft 1.9 using MCP 9.24 beta. All method and class names are the names used in the decompiled version.

The reason why this happens is very likely that the method net.minecraft.client.gui.GuiTextField.setSelectionPos(int) calls the method net.minecraft.client.gui.FontRenderer.trimStringToWidth(String, int) without reversing the text of the text field. This is a problem because the text of the textfield should not be trimmed at the end, but instead at the beginning. To prevent the underscore from overflowing over the text field, the width could be reduced by the width of the underscore.

/**
 * Sets the position of the selection anchor (i.e. position the selection was started at)
 */
public void setSelectionPos(int p_146199_1_)
{
    int i = this.text.length();

    if (p_146199_1_ > i)
    {
        p_146199_1_ = i;
    }

    if (p_146199_1_ < 0)
    {
        p_146199_1_ = 0;
    }

    this.selectionEnd = p_146199_1_;

    if (this.fontRendererInstance != null)
    {
        if (this.lineScrollOffset > i)
        {
            this.lineScrollOffset = i;
        }

        // Replaced this
        //int j = this.getWidth();
        //String s = this.fontRendererInstance.trimStringToWidth(this.text.substring(this.lineScrollOffset), j);
        int j = this.getWidth() - this.fontRendererInstance.getCharWidth('_');
        String s = this.fontRendererInstance.trimStringToWidth(this.text.substring(this.lineScrollOffset), j, true);
        
        
        int k = s.length() + this.lineScrollOffset;

        if (p_146199_1_ == this.lineScrollOffset)
        {
            this.lineScrollOffset -= this.fontRendererInstance.trimStringToWidth(this.text, j, true).length();
        }

        if (p_146199_1_ > k)
        {
            this.lineScrollOffset += p_146199_1_ - k;
        }
        else if (p_146199_1_ <= this.lineScrollOffset)
        {
            this.lineScrollOffset -= this.lineScrollOffset - p_146199_1_;
        }

        this.lineScrollOffset = MathHelper.clamp_int(this.lineScrollOffset, 0, i);
    }
}

Linked issues

Attachments

Comments 20

Confirmed, although the characters exist. You just need to go right two characters.

Does happen too on the flatworld preset string

Related to (if not duplicate) of MC-1237

Confirmed for

  • 1.9.1-pre3

Please link to this comment in the description

The following is based on decompiled version of Minecraft 1.9 using MCP 9.24 beta. All method and class names are the names used in the decompiled version.

The reason why this happens is very likely that the method net.minecraft.client.gui.GuiTextField.setSelectionPos(int) calls the method net.minecraft.client.gui.FontRenderer.trimStringToWidth(String, int) without reversing the text of the text field. This is a problem because the text of the textfield should not be trimmed at the end, but instead at the beginning. To prevent the underscore from overflowing over the text field, the width could be reduced by the width of the underscore.

/**
 * Sets the position of the selection anchor (i.e. position the selection was started at)
 */
public void setSelectionPos(int p_146199_1_)
{
    int i = this.text.length();

    if (p_146199_1_ > i)
    {
        p_146199_1_ = i;
    }

    if (p_146199_1_ < 0)
    {
        p_146199_1_ = 0;
    }

    this.selectionEnd = p_146199_1_;

    if (this.fontRendererInstance != null)
    {
        if (this.lineScrollOffset > i)
        {
            this.lineScrollOffset = i;
        }

        // Replaced this
        //int j = this.getWidth();
        //String s = this.fontRendererInstance.trimStringToWidth(this.text.substring(this.lineScrollOffset), j);
        int j = this.getWidth() - this.fontRendererInstance.getCharWidth('_');
        String s = this.fontRendererInstance.trimStringToWidth(this.text.substring(this.lineScrollOffset), j, true);
        
        
        int k = s.length() + this.lineScrollOffset;

        if (p_146199_1_ == this.lineScrollOffset)
        {
            this.lineScrollOffset -= this.fontRendererInstance.trimStringToWidth(this.text, j, true).length();
        }

        if (p_146199_1_ > k)
        {
            this.lineScrollOffset += p_146199_1_ - k;
        }
        else if (p_146199_1_ <= this.lineScrollOffset)
        {
            this.lineScrollOffset -= this.lineScrollOffset - p_146199_1_;
        }

        this.lineScrollOffset = MathHelper.clamp_int(this.lineScrollOffset, 0, i);
    }
}
10 more comments

Can confirm in 1.17.

Can confirm in 1.19 Release Candidate 2.

Can confirm in 1.19.

Can confirm in 1.19.2.

kumasasa

(Unassigned)

Confirmed

Platform

Low

UI

LastOutput, chat, text-field

Minecraft 13w36b, Minecraft 13w37a, Minecraft 13w38a, Minecraft 13w38b, Minecraft 13w38c, ..., 1.19, 1.19.2, 1.19.3, 1.20.3 Release Candidate 1, 1.21.4

Retrieved