#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(dead_code)]
use core::ffi::c_int;
use crate::ported::functionbar::FunctionBar_newEnterEsc;
use crate::ported::listitem::ListItem_new;
use crate::ported::object::Object;
use crate::ported::panel::{Panel, Panel_add, Panel_new, Panel_setHeader, Panel_setSelected};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct SignalItem {
pub name: &'static str,
pub number: c_int,
}
pub const SIGNALSPANEL_INITSELECTEDSIGNAL: c_int = libc::SIGTERM;
pub fn SignalsPanel_new(preSelectedSignal: c_int, signals: &[SignalItem]) -> Panel {
let mut this = Panel_new(
1,
1,
1,
1,
Some(FunctionBar_newEnterEsc("Send ", "Cancel ")),
);
let mut defaultPosition: c_int = 15;
for (i, sig) in signals.iter().enumerate() {
let item: Box<dyn Object> = Box::new(ListItem_new(sig.name, sig.number));
Panel_add(&mut this, item);
if sig.number == preSelectedSignal {
defaultPosition = i as c_int;
}
}
#[cfg(target_os = "linux")]
{
let sigrtmin = libc::SIGRTMIN();
let sigrtmax = libc::SIGRTMAX();
if sigrtmax - sigrtmin <= 100 {
let mut sig = sigrtmin;
while sig <= sigrtmax {
let n = sig - sigrtmin;
let mut buf = format!("{:2} SIGRTMIN{:<+3}", sig, n);
if n == 0 {
buf.truncate(11);
}
let item: Box<dyn Object> = Box::new(ListItem_new(&buf, sig));
Panel_add(&mut this, item);
sig += 1;
}
}
}
Panel_setHeader(&mut this, "Send signal:");
Panel_setSelected(&mut this, defaultPosition);
this
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ported::listitem::ListItem;
use crate::ported::panel::{Panel_get, Panel_size};
fn indexed_signals() -> Vec<SignalItem> {
[
" 0 Cancel",
" 1 SIGHUP",
" 2 SIGINT",
" 3 SIGQUIT",
" 4 SIGILL",
" 5 SIGTRAP",
" 6 SIGABRT",
" 7 SIGEMT",
" 8 SIGFPE",
" 9 SIGKILL",
"10 SIGBUS",
"11 SIGSEGV",
"12 SIGSYS",
"13 SIGPIPE",
"14 SIGALRM",
"15 SIGTERM",
]
.iter()
.enumerate()
.map(|(i, name)| SignalItem {
name,
number: i as c_int,
})
.collect()
}
fn item_value(p: &Panel, i: c_int) -> String {
let any: &dyn std::any::Any = Panel_get(p, i);
any.downcast_ref::<ListItem>().unwrap().value.clone()
}
#[test]
fn builds_one_item_per_signal_in_order() {
let sigs = indexed_signals();
let p = SignalsPanel_new(SIGNALSPANEL_INITSELECTEDSIGNAL, &sigs);
assert!(Panel_size(&p) >= sigs.len() as c_int);
for (i, sig) in sigs.iter().enumerate() {
assert_eq!(item_value(&p, i as c_int), sig.name);
}
}
#[test]
fn header_is_send_signal() {
use crate::ported::richstring::RichString_sizeVal;
let p = SignalsPanel_new(15, &indexed_signals());
assert_eq!(RichString_sizeVal(&p.header), "Send signal:".len() as c_int);
}
#[test]
fn function_bar_is_send_cancel() {
let p = SignalsPanel_new(15, &indexed_signals());
let bar = p.currentBar.as_ref().expect("currentBar set");
assert_eq!(
bar.functions,
vec!["Send ".to_string(), "Cancel ".to_string()]
);
assert_eq!(bar.keys, vec!["Enter".to_string(), "Esc".to_string()]);
assert_eq!(bar.events, vec![13, 27]);
}
#[test]
fn preselected_signal_sets_selection_to_its_index() {
let sigs = indexed_signals();
let p = SignalsPanel_new(9, &sigs);
assert_eq!(p.selected, 9);
assert_eq!(item_value(&p, p.selected), " 9 SIGKILL");
}
#[test]
fn absent_preselected_signal_keeps_default_15_clamped() {
let sigs = indexed_signals();
let p = SignalsPanel_new(999, &sigs);
let expected = 15.min(Panel_size(&p) - 1);
assert_eq!(p.selected, expected);
}
#[test]
fn selection_is_clamped_when_default_exceeds_size() {
let sigs: Vec<SignalItem> = (0..3)
.map(|i| SignalItem {
name: " x",
number: i,
})
.collect();
let p = SignalsPanel_new(-1, &sigs);
assert_eq!(p.selected, 15.min(Panel_size(&p) - 1));
assert!(p.selected >= 0);
}
#[test]
fn empty_table_still_sets_header_and_bar() {
use crate::ported::richstring::RichString_sizeVal;
let p = SignalsPanel_new(15, &[]);
assert_eq!(RichString_sizeVal(&p.header), "Send signal:".len() as c_int);
assert!(p.selected >= 0);
}
#[test]
fn rt_signal_label_format_matches_c_snprintf() {
let mut zero = format!("{:2} SIGRTMIN{:<+3}", 34, 0);
zero.truncate(11);
assert_eq!(zero, "34 SIGRTMIN");
assert_eq!(format!("{:2} SIGRTMIN{:<+3}", 35, 1), "35 SIGRTMIN+1 ");
assert_eq!(format!("{:2} SIGRTMIN{:<+3}", 64, 30), "64 SIGRTMIN+30");
}
}