use crate::ported::utils::zwarnnam;
use crate::ported::params::{TERMFLAGS, TERM_UNKNOWN};
use std::sync::atomic::Ordering;
#[link(name = "ncurses")]
extern "C" {
fn setupterm(
term: *const libc::c_char,
filedes: libc::c_int,
errret: *mut libc::c_int,
) -> libc::c_int;
fn tigetstr(capname: *const libc::c_char) -> *const libc::c_char;
fn tigetnum(capname: *const libc::c_char) -> libc::c_int;
fn tigetflag(capname: *const libc::c_char) -> libc::c_int;
fn putp(s: *const libc::c_char) -> libc::c_int;
fn tparm(s: *const libc::c_char, p1: libc::c_long, p2: libc::c_long,
p3: libc::c_long, p4: libc::c_long, p5: libc::c_long,
p6: libc::c_long, p7: libc::c_long, p8: libc::c_long,
p9: libc::c_long) -> *const libc::c_char;
}
pub fn bin_echoti(name: &str, argv: &[String], _ops: &crate::ported::zsh_h::options, _func: i32) -> i32 {
const TERM_BAD: i32 = 1 << 1;
if argv.is_empty() {
crate::ported::utils::zwarnnam(name, "missing capability name");
return 1;
}
let s = &argv[0]; let argv_rest = &argv[1..];
if (TERMFLAGS.load(Ordering::Relaxed) & TERM_BAD) != 0 { return 1; }
let interactive = crate::ported::zsh_h::isset(crate::ported::options::optlookup("interactive")); if (TERMFLAGS.load(Ordering::Relaxed) & TERM_UNKNOWN) != 0 && interactive {
return 1; }
let cs = match std::ffi::CString::new(s.as_str()) {
Ok(c) => c,
Err(_) => return 1,
};
let num = unsafe { tigetnum(cs.as_ptr()) }; if num != -1 && num != -2 { println!("{}", num); return 0; }
match unsafe { tigetflag(cs.as_ptr()) } { -1 => {} 0 => { println!("no"); return 0; } _ => { println!("yes"); return 0; } }
let t = unsafe { tigetstr(cs.as_ptr()) }; let t_addr = t as isize;
if t.is_null() || t_addr == -1 || unsafe { *t } == 0 { crate::ported::utils::zwarnnam(name, &format!("no such terminfo capability: {}", s));
return 1; }
if argv_rest.len() > 9 { crate::ported::utils::zwarnnam(name, "too many arguments"); return 1; }
let strcap = ["pfkey", "pfloc", "pfx", "pln", "pfxl"];
let strarg = strcap.iter().any(|c| s.as_str() == *c);
let mut pars: [libc::c_long; 9] = [0; 9]; let mut keep_alive: Vec<std::ffi::CString> = Vec::new(); for (i, a) in argv_rest.iter().enumerate().take(9) {
if strarg && i > 0 { let cs = std::ffi::CString::new(a.as_str()).unwrap_or_default();
pars[i] = cs.as_ptr() as libc::c_long; keep_alive.push(cs);
} else {
pars[i] = a.parse::<libc::c_long>().unwrap_or(0); }
}
if argv_rest.is_empty() { unsafe { putp(t); } } else {
let formatted = unsafe { tparm(t, pars[0], pars[1], pars[2], pars[3], pars[4],
pars[5], pars[6], pars[7], pars[8])
};
if !formatted.is_null() {
unsafe { putp(formatted); }
}
}
drop(keep_alive);
0 }
pub fn getterminfo(name: &str) -> Option<String> { const TERM_BAD: i32 = 1 << 1;
if (TERMFLAGS.load(Ordering::Relaxed) & TERM_BAD) != 0 { return None; }
if (TERMFLAGS.load(Ordering::Relaxed) & TERM_UNKNOWN) != 0 { let interactive = crate::ported::zsh_h::isset(crate::ported::options::optlookup("interactive"));
if interactive { return None; }
}
static INITIALIZED: OnceLock<bool> = OnceLock::new();
let ok = *INITIALIZED.get_or_init(|| {
let mut errret: libc::c_int = 0;
unsafe { setupterm(std::ptr::null(), 1, &mut errret) == 0 }
});
if !ok {
return None;
}
let mut buf = name.as_bytes().to_vec(); crate::ported::utils::unmetafy(&mut buf); let nameu = match std::str::from_utf8(&buf) {
Ok(s) => s.to_string(),
Err(_) => return None,
};
let cname = std::ffi::CString::new(nameu).ok()?;
unsafe {
let n = tigetnum(cname.as_ptr()); if n != -1 && n != -2 { return Some(n.to_string()); }
let b = tigetflag(cname.as_ptr()); if b != -1 { return Some(if b != 0 { "yes".to_string() } else { "no".to_string() }); }
let tistr = tigetstr(cname.as_ptr()); let s_addr = tistr as isize;
if !tistr.is_null() && s_addr != -1 { let raw = std::ffi::CStr::from_ptr(tistr).to_string_lossy().into_owned();
return Some(crate::ported::utils::metafy(&raw)); }
}
None }
pub const COMMON_STRING_CAPS: &[&str] = &[
"kf1", "kf2", "kf3", "kf4", "kf5", "kf6", "kf7", "kf8", "kf9", "kf10",
"kf11", "kf12", "kf13", "kf14", "kf15", "kf16", "kf17", "kf18", "kf19",
"kf20",
"kcuu1", "kcud1", "kcuf1", "kcub1",
"khome", "kend", "kpp", "knp",
"kbs", "kich1", "kdch1",
"clear", "ed", "el", "home", "civis", "cnorm",
"smso", "rmso", "smul", "rmul", "bold", "rev", "sgr0",
"smkx", "rmkx", "smcup", "rmcup", "setaf", "setab",
"cup", "ich1", "dch1", "il1", "dl1",
];
use crate::ported::zsh_h::module;
#[allow(unused_variables)]
pub fn setup_(m: *const module) -> i32 { 0
}
pub fn features_(m: *const module, features: &mut Vec<String>) -> i32 { *features = featuresarray(m, module_features());
0
}
pub fn enables_(m: *const module, enables: &mut Option<Vec<i32>>) -> i32 { handlefeatures(m, module_features(), enables)
}
#[allow(unused_variables)]
pub fn boot_(m: *const module) -> i32 { let _ = crate::ported::utils::zsetupterm(); 0
}
pub fn cleanup_(m: *const module) -> i32 { setfeatureenables(m, module_features(), None)
}
#[allow(unused_variables)]
pub fn finish_(m: *const module) -> i32 { 0
}
pub fn scanterminfo() -> Vec<(String, String)> { let mut out = Vec::new();
const TERM_BAD: i32 = 1 << 1;
if (TERMFLAGS.load(Ordering::Relaxed) & TERM_BAD) != 0 { return out; }
if (TERMFLAGS.load(Ordering::Relaxed) & TERM_UNKNOWN) != 0 {
let interactive = crate::ported::zsh_h::isset(crate::ported::options::optlookup("interactive"));
if interactive { return out; }
}
static INITIALIZED: OnceLock<bool> = OnceLock::new();
let ok = *INITIALIZED.get_or_init(|| {
let mut errret: libc::c_int = 0;
unsafe { setupterm(std::ptr::null(), 1, &mut errret) == 0 }
});
if !ok { return out; }
let boolnames = [
"bw", "am", "bce", "ccc", "xhp", "xhpa", "cpix", "crxm", "xt", "xenl",
"eo", "gn", "hc", "chts", "km", "daisy", "hs", "hls", "in", "lpix",
"da", "db", "mir", "msgr", "nxon", "xsb", "npc", "ndscr", "nrrmc",
"os", "mc5i", "xvpa", "sam", "eslok", "hz", "ul", "xon",
];
let numnames = [
"cols", "it", "lh", "lw", "lines", "lm", "xmc", "ma", "colors",
"pairs", "wnum", "ncv", "nlab", "pb", "vt", "wsl", "bitwin",
"bitype", "bufsz", "btns", "spinh", "spinv", "maddr", "mjump",
"mcs", "mls", "npins", "orc", "orhi", "orl", "orvi", "cps", "widcs",
];
let strnames: &[&str] = &[
"acsc", "cbt", "bel", "cr", "cpi", "lpi", "chr", "cvr", "csr", "rmp",
"tbc", "mgc", "clear", "el1", "el", "ed", "hpa", "cmdch", "cwin",
"cup", "cud1", "home", "civis", "cub1", "mrcup", "cnorm", "cuf1",
"ll", "cuu1", "cvvis", "defc", "dch1", "dl1", "dial", "dsl", "dclk",
"hd", "enacs", "smacs", "smam", "blink", "bold", "smcup", "smdc",
"dim", "swidm", "sdrfq", "smir", "sitm", "slm", "smicm", "snlq",
"snrmq", "prot", "rev", "invis", "sshm", "smso", "ssubm", "ssupm",
"smul", "sum", "smxon", "ech", "rmacs", "rmam", "sgr0", "rmcup",
"rmdc", "rwidm", "rmir", "ritm", "rlm", "rmicm", "rshm", "rmso",
"rsubm", "rsupm", "rmul", "rum", "rmxon", "pause", "hook", "flash",
"ff", "fsl", "wingo", "hup", "is1", "is2", "is3", "if", "iprog",
"initc", "initp", "ich1", "il1", "ip", "ka1", "ka3", "kb2", "kbs",
"kbeg", "kcbt", "kc1", "kc3", "kcan", "ktbc", "kclr", "kclo", "kcmd",
"kcpy", "kcrt", "kctab", "kdch1", "kdl1", "kcud1", "krmir", "kend",
"kent", "kel", "ked", "kext", "kf0", "kf1", "kf10", "kf11", "kf12",
"kf13", "kf14", "kf15", "kf16", "kf17", "kf18", "kf19", "kf2",
"kf20", "kf21", "kf22", "kf23", "kf24", "kf25", "kf26", "kf27",
"kf28", "kf29", "kf3", "kf30", "kf31", "kf32", "kf33", "kf34",
"kf35", "kf36", "kf37", "kf38", "kf39", "kf4", "kf40", "kf41",
"kf42", "kf43", "kf44", "kf45", "kf46", "kf47", "kf48", "kf49",
"kf5", "kf50", "kf51", "kf52", "kf53", "kf54", "kf55", "kf56",
"kf57", "kf58", "kf59", "kf6", "kf60", "kf61", "kf62", "kf63",
"kf7", "kf8", "kf9", "kfnd", "khlp", "khome", "kich1", "kil1",
"kcub1", "kll", "kmrk", "kmsg", "kmov", "knxt", "knp", "kopn",
"kopt", "kpp", "kprv", "kprt", "krdo", "kref", "krfr", "krpl",
"krst", "kres", "kcuf1", "ksav", "kBEG", "kCAN", "kCMD", "kCPY",
"kCRT", "kDC", "kDL", "kslt", "kEND", "kEOL", "kEXT", "kind",
"kFND", "kHLP", "kHOM", "kIC", "kLFT", "kMSG", "kMOV", "kNXT",
"kOPT", "kPRV", "kPRT", "kri", "kRDO", "kRPL", "kRIT", "kRES",
"kSAV", "kSPD", "khts", "kUND", "kspd", "kund", "kcuu1", "rmkx",
"smkx", "lf0", "lf1", "lf10", "lf2", "lf3", "lf4", "lf5", "lf6",
"lf7", "lf8", "lf9", "fln", "rmln", "smln", "rmm", "smm", "mhpa",
"mcud1", "mcub1", "mcuf1", "mvpa", "mcuu1", "nel", "porder", "oc",
"op", "pad", "dch", "dl", "cud", "mcud", "ich", "indn", "il", "cub",
"mcub", "cuf", "mcuf", "rin", "cuu", "mcuu", "pfkey", "pfloc",
"pfx", "pln", "mc0", "mc5p", "mc4", "mc5", "pulse", "qdial",
"rmclk", "rep", "rfi", "rs1", "rs2", "rs3", "rf", "rc", "vpa",
"sc", "ind", "ri", "scs", "sgr", "setb", "smgb", "smgbp", "sclk",
"scp", "setf", "smgl", "smglp", "smgr", "smgrp", "hts", "smgt",
"smgtp", "wind", "sbim", "scsd", "rbim", "rcsd", "subcs",
"supcs", "ht", "docr", "tsl", "tone", "uc", "hu", "u0", "u1",
"u2", "u3", "u4", "u5", "u6", "u7", "u8", "u9", "wait", "xoffc",
"xonc", "zerom", "scesa", "bicr", "binel", "birep", "csnm",
"csin", "colornm", "defbi", "devt", "dispc", "endbi", "smpch",
"smsc", "rmpch", "rmsc", "getm", "kmous", "minfo", "pctrm",
"pfxl", "reqmp", "scesc", "s0ds", "s1ds", "s2ds", "s3ds",
"setab", "setaf", "setcolor", "smglr", "slines", "smgtb",
"ehhlm", "elhlm", "elohlm", "erhlm", "ethlm", "evhlm", "sgr1",
"slength",
];
for cap in &boolnames { let cn = match std::ffi::CString::new(*cap) { Ok(c) => c, Err(_) => continue };
let n = unsafe { tigetflag(cn.as_ptr()) }; if n != -1 { let v = if n != 0 { "yes" } else { "no" }; out.push((cap.to_string(), v.to_string())); }
}
for cap in &numnames { let cn = match std::ffi::CString::new(*cap) { Ok(c) => c, Err(_) => continue };
let n = unsafe { tigetnum(cn.as_ptr()) }; if n != -1 && n != -2 { out.push((cap.to_string(), n.to_string())); }
}
for cap in strnames { let cn = match std::ffi::CString::new(*cap) { Ok(c) => c, Err(_) => continue };
let raw = unsafe { tigetstr(cn.as_ptr()) }; let s_addr = raw as isize;
if !raw.is_null() && s_addr != -1 { let bytes = unsafe { std::ffi::CStr::from_ptr(raw) }
.to_string_lossy()
.into_owned();
out.push((cap.to_string(),
crate::ported::utils::metafy(&bytes))); }
}
out
}
use crate::ported::zsh_h::features as features_t;
use std::sync::{Mutex, OnceLock};
static MODULE_FEATURES: OnceLock<Mutex<features_t>> = OnceLock::new();
fn module_features() -> &'static Mutex<features_t> {
MODULE_FEATURES.get_or_init(|| Mutex::new(features_t {
bn_list: None,
bn_size: 1,
cd_list: None,
cd_size: 0,
mf_list: None,
mf_size: 0,
pd_list: None,
pd_size: 1,
n_abstract: 0,
}))
}
fn featuresarray(_m: *const module, _f: &Mutex<features_t>) -> Vec<String> {
vec!["b:echoti".to_string(), "p:terminfo".to_string()]
}
fn handlefeatures(
_m: *const module,
_f: &Mutex<features_t>,
enables: &mut Option<Vec<i32>>,
) -> i32 {
if enables.is_none() {
*enables = Some(vec![1; 2]);
}
0
}
fn setfeatureenables(
_m: *const module,
_f: &Mutex<features_t>,
_e: Option<&[i32]>,
) -> i32 {
0
}