The field reader dropped the value "Off" for every field kind, so a text field, combo box or single-select list set to "Off" read as empty and exported an empty value to CSV, text, XML, XFDF and FDF, although the document stored it. "Off" is now treated as no value only for check boxes and radio buttons, where it is the off state. Adds tests::a_literal_off_value_reads_as_off_outside_buttons, which fails before this change.
This commit is contained in:
parent
3e2877cbbb
commit
24ccb5f3ae
|
|
@ -430,12 +430,14 @@ fn actions_of(doc: &Document, d: &Dict, widgets: &[ObjRef]) -> af::Actions {
|
|||
out
|
||||
}
|
||||
|
||||
fn values_of(doc: &Document, o: Option<&Object>) -> Vec<String> {
|
||||
fn values_of(doc: &Document, o: Option<&Object>, kind: FieldKind) -> Vec<String> {
|
||||
let Some(o) = o else { return Vec::new() };
|
||||
// "Off" is a button's off state; in a text or choice field it is the value.
|
||||
let button = matches!(kind, FieldKind::CheckBox | FieldKind::Radio);
|
||||
match &*doc.resolve(o) {
|
||||
Object::Array(a) => a.iter().filter_map(|x| text_of(&doc.resolve(x))).collect(),
|
||||
Object::Stream(s) => s.decoded().ok().map(|b| PdfString::literal(b).to_text()).into_iter().collect(),
|
||||
other => text_of(other).filter(|s| s != "Off" && !s.is_empty()).into_iter().collect(),
|
||||
other => text_of(other).filter(|s| !(button && s == "Off") && !s.is_empty()).into_iter().collect(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -818,8 +820,8 @@ fn walk(
|
|||
name: inh.name.clone(),
|
||||
obj: r,
|
||||
kind,
|
||||
value: values_of(doc, inh.v.as_ref()),
|
||||
default: values_of(doc, inh.dv.as_ref()),
|
||||
value: values_of(doc, inh.v.as_ref(), kind),
|
||||
default: values_of(doc, inh.dv.as_ref(), kind),
|
||||
flags: ff,
|
||||
max_len: inh.max_len,
|
||||
options,
|
||||
|
|
|
|||
|
|
@ -1850,3 +1850,23 @@ fn invalid_appearance_patches_are_refused_before_anything_is_written() {
|
|||
assert!(set_props(&mut doc, "name", &props).is_err());
|
||||
assert_eq!(write_incremental(&doc, &SaveOptions::default()).unwrap(), before);
|
||||
}
|
||||
|
||||
/// "Off" is a button's off state, not a value; a text or choice field that holds "Off" reads
|
||||
/// it (#1320), while an unchecked check box still reads as no value.
|
||||
#[test]
|
||||
fn a_literal_off_value_reads_as_off_outside_buttons() {
|
||||
for (kind, value) in [
|
||||
(NewField::Text { multiline: false }, FieldValue::Text("Off".into())),
|
||||
(NewField::Combo { options: vec!["On".into(), "Off".into()], editable: false }, FieldValue::Choice(vec!["Off".into()])),
|
||||
(NewField::List { options: vec!["On".into(), "Off".into()], multi: false }, FieldValue::Choice(vec!["Off".into()])),
|
||||
] {
|
||||
let mut doc = one_page();
|
||||
add_field(&mut doc, 0, [50.0, 600.0, 250.0, 620.0], &kind, Some("power")).unwrap();
|
||||
set_value(&mut doc, "power", &value).unwrap();
|
||||
assert_eq!(field(&fields(&reopen(&doc)), "power").value, ["Off"], "{kind:?}");
|
||||
}
|
||||
let mut doc = one_page();
|
||||
add_field(&mut doc, 0, [50.0, 600.0, 70.0, 620.0], &NewField::CheckBox, Some("power")).unwrap();
|
||||
set_value(&mut doc, "power", &FieldValue::Check(false)).unwrap();
|
||||
assert!(field(&fields(&doc), "power").value.is_empty());
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue