[
https://issues.apache.org/jira/browse/GUACAMOLE-2091?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
orange-guo updated GUACAMOLE-2091:
----------------------------------
Description:
*Problem Description:*
When pasting text containing Chinese characters from the clipboard into a
Guacamole SSH terminal session, the very first Chinese character of the pasted
text fails to render correctly (appears missing).
Subsequent characters within the same pasted text, render correctly.
!image-2025-06-30-10-04-04-535.png!
*Steps to Reproduce:*
* Connect to a remote machine via a SSH protocol.
* Copy a string of Chinese characters (e.g., "我是人") from your local machine's
clipboard.
* Paste the copied text into the terminal session.
* Observe the terminal display: the first Chinese character (e.g., "我") is not
visible or is corrupted, while "是人" appears correctly.
*Example Debug Logs (before fix, pasting "我是人" starting at `col=26`):*
{code:java}
guacd[...]: DEBUG: echo: Codepoint ready for processing: 0x6211 ('我')
guacd[...]: DEBUG: echo: Calling guac_terminal_set for char 0x6211 at
(39,26).
guacd[...]: DEBUG: Rendering char: row=39, col=26, codepoint=0x6211 ('我'),
width=2
guacd[...]: DEBUG: set_columns: Primary set for row=39, cols=[26,27],
char=0x6211('我'), width=2
guacd[...]: DEBUG: display_set_columns: row=39, input_start_col=26,
input_end_col=27, char_codepoint=0x6211 ('我'), char_width=2
guacd[...]: DEBUG: display_set_columns: Starting loop to set columns from 26
to 27 (char_width=2).
guacd[...]: DEBUG: display_set_columns: Processing col 26, current_op_type=0
(GUAC_CHAR_COPY=1)
guacd[...]: DEBUG: display_set_columns: Set op for col 26: type=2,
char_codepoint=0x6211.
guacd[...]: DEBUG: display_set_columns: Marking unflushed_set for row 39.
guacd[...]: DEBUG: set_columns: Cursor detected at row=39, col=26. Character
width is 2.
guacd[...]: DEBUG: set_columns: Redrawing cursor char. Original
visible_cursor_col=26. Adjusted redraw range: [26,27].
guacd[...]: DEBUG: display_set_columns: row=39, input_start_col=26,
input_end_col=26, char_codepoint=0x6211 ('我'), char_width=2 # <--- This line
caused the issue
guacd[...]: DEBUG: display_set_columns: Starting loop to set columns from 26
to 26 (char_width=2).
guacd[...]: DEBUG: display_set_columns: Processing col 26, current_op_type=2
(GUAC_CHAR_COPY=1)
guacd[...]: DEBUG: display_set_columns: Set op for col 26: type=2,
char_codepoint=0x6211.
guacd[...]: DEBUG: display_set_columns: Marking unflushed_set for row 39.
# ... (other characters '是', '人' processing - these were fine) ...
guacd[...]: DEBUG: display_set_columns: row=39, input_start_col=26,
input_end_col=26, char_codepoint=0x20 (' '), char_width=1 # <--- Final overwrite
guacd[...]: DEBUG: display_set_columns: Starting loop to set columns from 26
to 26 (char_width=1).
guacd[...]: DEBUG: display_set_columns: Processing col 26, current_op_type=2
(GUAC_CHAR_COPY=1)
guacd[...]: DEBUG: display_set_columns: Set op for col 26: type=2,
char_codepoint=0x20.
guacd[...]: DEBUG: display_set_columns: Marking unflushed_set for row 39.
{code}
*Root Cause Analysis*
The root cause lies in how terminal display logic handles *double-width
characters* (like Chinese) when they overlap with the cursor, leading to
inconsistent updates and eventual overwrites in the display buffer.
*Proposed Solution:*
The problem can be resolved by ensuring that the cursor redraw logic within
{*}guac_{*}{*}terminal_set_columns{*} correctly accounts for the full width of
multi-column characters. This ensures that the character's state in the display
buffer remains consistent throughout all operations.
File: terminal.c
Function: guac_terminal_set_columns{*}{*}
{code:java}
void guac_terminal_set_columns(guac_terminal* terminal, int row,
int start_column, int end_column, guac_terminal_char* character) {
// Primary set for the character
__guac_terminal_set_columns(terminal, row, start_column, end_column,
character);
// If visible cursor in current row, preserve state
if (row == terminal->visible_cursor_row
&& terminal->visible_cursor_col >= start_column
&& terminal->visible_cursor_col <= end_column) {
guac_terminal_char cursor_character = *character;
cursor_character.attributes.cursor = true;
// Correctly calculate the redraw range to cover the entire
character width
int cursor_redraw_start_col = terminal->visible_cursor_col;
int cursor_redraw_end_col = terminal->visible_cursor_col +
character->width - 1;
// Ensure redraw range does not exceed the original set bounds
if (cursor_redraw_start_col < start_column)
cursor_redraw_start_col = start_column;
if (cursor_redraw_end_col > end_column)
cursor_redraw_end_col = end_column;
// Re-submit the character with cursor attributes, covering its
full width
__guac_terminal_set_columns(terminal, row,
cursor_redraw_start_col,
cursor_redraw_end_col,
&cursor_character);
}
} {code}
I can create a pull request on Github to fix this issue later, if needed.
Here is the screen screenshot after the problem was fixed
!https://git.fastonetech.com:8443/-/project/401/uploads/fe322ac1b7eea72bb5ccb8b0a3a0c1ef/image.png!
was:
*Problem Description:*
When pasting text containing Chinese characters from the clipboard into a
Guacamole SSH terminal session, the very first Chinese character of the pasted
text fails to render correctly (appears missing).
Subsequent characters within the same pasted text, render correctly.
!image-2025-06-30-10-04-04-535.png!
*Steps to Reproduce:*
* Connect to a remote machine via a SSH protocol.
* Copy a string of Chinese characters (e.g., "我是人") from your local machine's
clipboard.
* Paste the copied text into the Guacamole terminal session.
* Observe the terminal display: the first Chinese character (e.g., "我") is not
visible or is corrupted, while "是人" appears correctly.
*Example Debug Logs (before fix, pasting "我是人" starting at `col=26`):*
{code:java}
guacd[...]: DEBUG: echo: Codepoint ready for processing: 0x6211 ('我')
guacd[...]: DEBUG: echo: Calling guac_terminal_set for char 0x6211 at
(39,26).
guacd[...]: DEBUG: Rendering char: row=39, col=26, codepoint=0x6211 ('我'),
width=2
guacd[...]: DEBUG: set_columns: Primary set for row=39, cols=[26,27],
char=0x6211('我'), width=2
guacd[...]: DEBUG: display_set_columns: row=39, input_start_col=26,
input_end_col=27, char_codepoint=0x6211 ('我'), char_width=2
guacd[...]: DEBUG: display_set_columns: Starting loop to set columns from 26
to 27 (char_width=2).
guacd[...]: DEBUG: display_set_columns: Processing col 26, current_op_type=0
(GUAC_CHAR_COPY=1)
guacd[...]: DEBUG: display_set_columns: Set op for col 26: type=2,
char_codepoint=0x6211.
guacd[...]: DEBUG: display_set_columns: Marking unflushed_set for row 39.
guacd[...]: DEBUG: set_columns: Cursor detected at row=39, col=26. Character
width is 2.
guacd[...]: DEBUG: set_columns: Redrawing cursor char. Original
visible_cursor_col=26. Adjusted redraw range: [26,27].
guacd[...]: DEBUG: display_set_columns: row=39, input_start_col=26,
input_end_col=26, char_codepoint=0x6211 ('我'), char_width=2 # <--- This line
caused the issue
guacd[...]: DEBUG: display_set_columns: Starting loop to set columns from 26
to 26 (char_width=2).
guacd[...]: DEBUG: display_set_columns: Processing col 26, current_op_type=2
(GUAC_CHAR_COPY=1)
guacd[...]: DEBUG: display_set_columns: Set op for col 26: type=2,
char_codepoint=0x6211.
guacd[...]: DEBUG: display_set_columns: Marking unflushed_set for row 39.
# ... (other characters '是', '人' processing - these were fine) ...
guacd[...]: DEBUG: display_set_columns: row=39, input_start_col=26,
input_end_col=26, char_codepoint=0x20 (' '), char_width=1 # <--- Final overwrite
guacd[...]: DEBUG: display_set_columns: Starting loop to set columns from 26
to 26 (char_width=1).
guacd[...]: DEBUG: display_set_columns: Processing col 26, current_op_type=2
(GUAC_CHAR_COPY=1)
guacd[...]: DEBUG: display_set_columns: Set op for col 26: type=2,
char_codepoint=0x20.
guacd[...]: DEBUG: display_set_columns: Marking unflushed_set for row 39.
{code}
**
*Root Cause Analysis*
The root cause lies in how terminal display logic handles *double-width
characters* (like Chinese) when they overlap with the cursor, leading to
inconsistent updates and eventual overwrites in the display buffer.
{*}Proposed Solution:{*}{*}{*}
The problem can be resolved by ensuring that the cursor redraw logic within
*guac_*{*}terminal_set_columns{*} correctly accounts for the full width of
multi-column characters. This ensures that the character's state in the display
buffer remains consistent throughout all operations.
File: terminal.c
Function: guac_terminal_set_columns{*}{*}
{code:java}
void guac_terminal_set_columns(guac_terminal* terminal, int row,
int start_column, int end_column, guac_terminal_char* character) {
// Primary set for the character
__guac_terminal_set_columns(terminal, row, start_column, end_column,
character);
// If visible cursor in current row, preserve state
if (row == terminal->visible_cursor_row
&& terminal->visible_cursor_col >= start_column
&& terminal->visible_cursor_col <= end_column) {
guac_terminal_char cursor_character = *character;
cursor_character.attributes.cursor = true;
// Correctly calculate the redraw range to cover the entire
character width
int cursor_redraw_start_col = terminal->visible_cursor_col;
int cursor_redraw_end_col = terminal->visible_cursor_col +
character->width - 1;
// Ensure redraw range does not exceed the original set bounds
if (cursor_redraw_start_col < start_column)
cursor_redraw_start_col = start_column;
if (cursor_redraw_end_col > end_column)
cursor_redraw_end_col = end_column;
// Re-submit the character with cursor attributes, covering its
full width
__guac_terminal_set_columns(terminal, row,
cursor_redraw_start_col,
cursor_redraw_end_col,
&cursor_character);
}
} {code}
I can create a pull request on Github to fix this issue later, if needed.
Here is the screen screenshot after the problem was fixed
!https://git.fastonetech.com:8443/-/project/401/uploads/fe322ac1b7eea72bb5ccb8b0a3a0c1ef/image.png!
> Double-width Characters Rendering Problem (First Character Missing/Corrupted)
> when Pasting from Clipboard in SSH Terminal
> -------------------------------------------------------------------------------------------------------------------------
>
> Key: GUACAMOLE-2091
> URL: https://issues.apache.org/jira/browse/GUACAMOLE-2091
> Project: Guacamole
> Issue Type: Bug
> Components: guacamole-server
> Affects Versions: 1.6.0
> Reporter: orange-guo
> Priority: Major
> Attachments: image-2025-06-30-10-03-00-698.png,
> image-2025-06-30-10-04-04-535.png
>
>
> *Problem Description:*
> When pasting text containing Chinese characters from the clipboard into a
> Guacamole SSH terminal session, the very first Chinese character of the
> pasted text fails to render correctly (appears missing).
> Subsequent characters within the same pasted text, render correctly.
> !image-2025-06-30-10-04-04-535.png!
> *Steps to Reproduce:*
> * Connect to a remote machine via a SSH protocol.
> * Copy a string of Chinese characters (e.g., "我是人") from your local
> machine's clipboard.
> * Paste the copied text into the terminal session.
> * Observe the terminal display: the first Chinese character (e.g., "我") is
> not visible or is corrupted, while "是人" appears correctly.
> *Example Debug Logs (before fix, pasting "我是人" starting at `col=26`):*
> {code:java}
> guacd[...]: DEBUG: echo: Codepoint ready for processing: 0x6211 ('我')
> guacd[...]: DEBUG: echo: Calling guac_terminal_set for char 0x6211 at
> (39,26).
> guacd[...]: DEBUG: Rendering char: row=39, col=26, codepoint=0x6211 ('我'),
> width=2
> guacd[...]: DEBUG: set_columns: Primary set for row=39, cols=[26,27],
> char=0x6211('我'), width=2
> guacd[...]: DEBUG: display_set_columns: row=39, input_start_col=26,
> input_end_col=27, char_codepoint=0x6211 ('我'), char_width=2
> guacd[...]: DEBUG: display_set_columns: Starting loop to set columns from
> 26 to 27 (char_width=2).
> guacd[...]: DEBUG: display_set_columns: Processing col 26,
> current_op_type=0 (GUAC_CHAR_COPY=1)
> guacd[...]: DEBUG: display_set_columns: Set op for col 26: type=2,
> char_codepoint=0x6211.
> guacd[...]: DEBUG: display_set_columns: Marking unflushed_set for row 39.
> guacd[...]: DEBUG: set_columns: Cursor detected at row=39, col=26.
> Character width is 2.
> guacd[...]: DEBUG: set_columns: Redrawing cursor char. Original
> visible_cursor_col=26. Adjusted redraw range: [26,27].
> guacd[...]: DEBUG: display_set_columns: row=39, input_start_col=26,
> input_end_col=26, char_codepoint=0x6211 ('我'), char_width=2 # <--- This line
> caused the issue
> guacd[...]: DEBUG: display_set_columns: Starting loop to set columns from
> 26 to 26 (char_width=2).
> guacd[...]: DEBUG: display_set_columns: Processing col 26,
> current_op_type=2 (GUAC_CHAR_COPY=1)
> guacd[...]: DEBUG: display_set_columns: Set op for col 26: type=2,
> char_codepoint=0x6211.
> guacd[...]: DEBUG: display_set_columns: Marking unflushed_set for row 39.
> # ... (other characters '是', '人' processing - these were fine) ...
> guacd[...]: DEBUG: display_set_columns: row=39, input_start_col=26,
> input_end_col=26, char_codepoint=0x20 (' '), char_width=1 # <--- Final
> overwrite
> guacd[...]: DEBUG: display_set_columns: Starting loop to set columns from
> 26 to 26 (char_width=1).
> guacd[...]: DEBUG: display_set_columns: Processing col 26,
> current_op_type=2 (GUAC_CHAR_COPY=1)
> guacd[...]: DEBUG: display_set_columns: Set op for col 26: type=2,
> char_codepoint=0x20.
> guacd[...]: DEBUG: display_set_columns: Marking unflushed_set for row 39.
> {code}
>
> *Root Cause Analysis*
> The root cause lies in how terminal display logic handles *double-width
> characters* (like Chinese) when they overlap with the cursor, leading to
> inconsistent updates and eventual overwrites in the display buffer.
> *Proposed Solution:*
> The problem can be resolved by ensuring that the cursor redraw logic within
> {*}guac_{*}{*}terminal_set_columns{*} correctly accounts for the full width
> of multi-column characters. This ensures that the character's state in the
> display buffer remains consistent throughout all operations.
> File: terminal.c
> Function: guac_terminal_set_columns{*}{*}
> {code:java}
> void guac_terminal_set_columns(guac_terminal* terminal, int row,
> int start_column, int end_column, guac_terminal_char* character) {
> // Primary set for the character
> __guac_terminal_set_columns(terminal, row, start_column, end_column,
> character);
> // If visible cursor in current row, preserve state
> if (row == terminal->visible_cursor_row
> && terminal->visible_cursor_col >= start_column
> && terminal->visible_cursor_col <= end_column) {
> guac_terminal_char cursor_character = *character;
> cursor_character.attributes.cursor = true;
> // Correctly calculate the redraw range to cover the entire
> character width
> int cursor_redraw_start_col = terminal->visible_cursor_col;
> int cursor_redraw_end_col = terminal->visible_cursor_col +
> character->width - 1;
> // Ensure redraw range does not exceed the original set bounds
> if (cursor_redraw_start_col < start_column)
> cursor_redraw_start_col = start_column;
> if (cursor_redraw_end_col > end_column)
> cursor_redraw_end_col = end_column;
> // Re-submit the character with cursor attributes, covering its
> full width
> __guac_terminal_set_columns(terminal, row,
> cursor_redraw_start_col,
> cursor_redraw_end_col,
> &cursor_character);
> }
> } {code}
> I can create a pull request on Github to fix this issue later, if needed.
> Here is the screen screenshot after the problem was fixed
> !https://git.fastonetech.com:8443/-/project/401/uploads/fe322ac1b7eea72bb5ccb8b0a3a0c1ef/image.png!
>
--
This message was sent by Atlassian Jira
(v8.20.10#820010)