aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2025-10-09 12:07:57 +0300
committerEli Zaretskii2025-10-09 12:07:57 +0300
commit5a70f5096eafb9bf2ea5b2e798293def1a8cf404 (patch)
treecae03524b0f46464ba2791b2802eaff16b6f0047 /src
parent73423a1e0e98534512f63929e174a8578a1ac4f2 (diff)
downloademacs-5a70f5096eafb9bf2ea5b2e798293def1a8cf404.tar.gz
emacs-5a70f5096eafb9bf2ea5b2e798293def1a8cf404.zip
Fix text-terminal output with UTF-8 encoding on MS-Windows
* src/w32console.c (w32con_write_glyphs) (w32con_write_glyphs_with_face): Support UTF-8 encoded text better, by counting characters and using display columns, not bytes, to move the cursor after writing the text. (Bug#79298)
Diffstat (limited to 'src')
-rw-r--r--src/w32console.c38
1 files changed, 30 insertions, 8 deletions
diff --git a/src/w32console.c b/src/w32console.c
index 1bca0cadff9..30f511d93f9 100644
--- a/src/w32console.c
+++ b/src/w32console.c
@@ -351,10 +351,23 @@ w32con_write_glyphs (struct frame *f, register struct glyph *string,
351 conversion_buffer = (LPCSTR) encode_terminal_code (string, n, coding); 351 conversion_buffer = (LPCSTR) encode_terminal_code (string, n, coding);
352 if (coding->produced > 0) 352 if (coding->produced > 0)
353 { 353 {
354 /* By default, assume single-byte encoding and single-column
355 characters... */
356 ptrdiff_t nchars = coding->produced;
357 ptrdiff_t ncols = nchars;
358 /* ...but if we are using UTF-8, correct that by computing
359 characters. Note: multibyte_chars_in_text and strwidth
360 handle the internal encoding of characters, which is a
361 superset of UTF-8.
362 FIXME: this doesn't handle character compositions. */
363 if (coding->encoder == encode_coding_utf_8)
364 {
365 ncols = strwidth (conversion_buffer, nchars);
366 nchars = multibyte_chars_in_text (conversion_buffer, nchars);
367 }
354 /* Set the attribute for these characters. */ 368 /* Set the attribute for these characters. */
355 if (!FillConsoleOutputAttribute (cur_screen, char_attr, 369 if (!FillConsoleOutputAttribute (cur_screen, char_attr, nchars,
356 coding->produced, cursor_coords, 370 cursor_coords, &r))
357 &r))
358 { 371 {
359 printf ("Failed writing console attributes: %lu\n", 372 printf ("Failed writing console attributes: %lu\n",
360 GetLastError ()); 373 GetLastError ());
@@ -371,7 +384,7 @@ w32con_write_glyphs (struct frame *f, register struct glyph *string,
371 fflush (stdout); 384 fflush (stdout);
372 } 385 }
373 386
374 cursor_coords.X += coding->produced; 387 cursor_coords.X += ncols;
375 w32con_move_cursor (f, cursor_coords.Y, cursor_coords.X); 388 w32con_move_cursor (f, cursor_coords.Y, cursor_coords.X);
376 } 389 }
377 len -= n; 390 len -= n;
@@ -407,19 +420,28 @@ w32con_write_glyphs_with_face (struct frame *f, register int x, register int y,
407 /* Compute the character attributes corresponding to the face. */ 420 /* Compute the character attributes corresponding to the face. */
408 DWORD char_attr = w32_face_attributes (f, face_id); 421 DWORD char_attr = w32_face_attributes (f, face_id);
409 COORD start_coords; 422 COORD start_coords;
423 /* By default, assume single-byte encoding... */
424 ptrdiff_t nchars = coding->produced;
425 /* ...but if we are using UTF-8, correct that by counting
426 characters. Note: multibyte_chars_in_text handles the
427 internal encoding of characters, which is a superset of
428 UTF-8.
429 FIXME: this doesn't handle character compositions. */
430 if (coding->encoder == encode_coding_utf_8)
431 nchars = multibyte_chars_in_text (conversion_buffer, nchars);
410 432
411 start_coords.X = x; 433 start_coords.X = x;
412 start_coords.Y = y; 434 start_coords.Y = y;
413 /* Set the attribute for these characters. */ 435 /* Set the attribute for these characters. */
414 if (!FillConsoleOutputAttribute (cur_screen, char_attr, 436 if (!FillConsoleOutputAttribute (cur_screen, char_attr, nchars,
415 coding->produced, start_coords, 437 start_coords, &filled))
416 &filled))
417 DebPrint (("Failed writing console attributes: %d\n", GetLastError ())); 438 DebPrint (("Failed writing console attributes: %d\n", GetLastError ()));
418 else 439 else
419 { 440 {
420 /* Write the characters. */ 441 /* Write the characters. */
421 if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer, 442 if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
422 filled, start_coords, &written)) 443 coding->produced, start_coords,
444 &written))
423 DebPrint (("Failed writing console characters: %d\n", 445 DebPrint (("Failed writing console characters: %d\n",
424 GetLastError ())); 446 GetLastError ()));
425 } 447 }