Fix wcwidth on cygwin

This commit is contained in:
王宇逸
2025-03-08 00:51:49 +08:00
committed by Johannes Altmanninger
parent f88470aa3c
commit 2e89f37446
2 changed files with 17 additions and 4 deletions

View File

@@ -199,7 +199,10 @@ fn guess_emoji_width(vars: &EnvStack) {
} else {
// Default to whatever the system's wcwidth gives for U+1F603, but only if it's at least
// 1 and at most 2.
#[cfg(not(target_os = "cygwin"))]
let width = crate::fallback::wcwidth('😃').clamp(1, 2);
#[cfg(target_os = "cygwin")]
let width = 2_isize;
FISH_EMOJI_WIDTH.store(width, Ordering::Relaxed);
FLOG!(term_support, "default emoji width:", width);
}

View File

@@ -8,10 +8,10 @@
use errno::{errno, Errno};
use once_cell::sync::Lazy;
use std::cmp;
use std::ffi::CString;
use std::fs::File;
use std::os::fd::FromRawFd;
use std::sync::atomic::{AtomicIsize, Ordering};
use std::{ffi::CString, mem};
/// Width of ambiguous East Asian characters and, as of TR11, all private-use characters.
/// 1 is the typical default, but we accept any non-negative override via `$fish_ambiguous_width`.
@@ -32,12 +32,13 @@
static WC_LOOKUP_TABLE: Lazy<WcLookupTable> = Lazy::new(WcLookupTable::new);
/// A safe wrapper around the system `wcwidth()` function
#[cfg(not(target_os = "cygwin"))]
pub fn wcwidth(c: char) -> isize {
extern "C" {
pub fn wcwidth(c: libc::wchar_t) -> libc::c_int;
}
const _: () = assert!(mem::size_of::<libc::wchar_t>() >= mem::size_of::<char>());
const _: () = assert!(std::mem::size_of::<libc::wchar_t>() >= std::mem::size_of::<char>());
let width = unsafe { wcwidth(c as libc::wchar_t) };
isize::try_from(width).unwrap()
}
@@ -48,6 +49,7 @@ pub fn fish_wcwidth(c: char) -> isize {
// The system version of wcwidth should accurately reflect the ability to represent characters
// in the console session, but knows nothing about the capabilities of other terminal emulators
// or ttys. Use it from the start only if we are logged in to the physical console.
#[cfg(not(target_os = "cygwin"))]
if is_console_session() {
return wcwidth(c);
}
@@ -73,8 +75,16 @@ pub fn fish_wcwidth(c: char) -> isize {
let width = WC_LOOKUP_TABLE.classify(c);
match width {
WcWidth::NonCharacter | WcWidth::NonPrint | WcWidth::Combining | WcWidth::Unassigned => {
// Fall back to system wcwidth in this case.
wcwidth(c)
#[cfg(not(target_os = "cygwin"))]
{
// Fall back to system wcwidth in this case.
wcwidth(c)
}
#[cfg(target_os = "cygwin")]
{
// No system wcwidth for UTF-32 on cygwin.
0
}
}
WcWidth::Ambiguous | WcWidth::PrivateUse => {
// TR11: "All private-use characters are by default classified as Ambiguous".