use std::io::{Read, Seek};
use super::{WML_NS, read_zip_text, twips_attr, wml, wml_attr, wml_bool};
pub(super) struct DocumentSettings {
pub even_and_odd_headers: bool,
pub mirror_margins: bool,
pub default_tab_stop: f32,
pub gutter_at_top: bool,
pub east_asia_lang: Option<String>,
pub bidi_lang: Option<String>,
pub default_lang: Option<String>,
pub compress_punctuation: bool,
pub compat_mode: u32,
pub styles_from_normal_template: bool,
pub do_not_expand_shift_return: bool,
pub adjust_line_height_in_table: bool,
}
impl Default for DocumentSettings {
fn default() -> Self {
Self {
even_and_odd_headers: false,
mirror_margins: false,
default_tab_stop: 36.0, gutter_at_top: false,
east_asia_lang: None,
bidi_lang: None,
default_lang: None,
compress_punctuation: false,
compat_mode: 0,
styles_from_normal_template: false,
do_not_expand_shift_return: false,
adjust_line_height_in_table: false,
}
}
}
pub(super) fn parse_settings<R: Read + Seek>(zip: &mut zip::ZipArchive<R>) -> DocumentSettings {
let Some(xml_text) = read_zip_text(zip, "word/settings.xml") else {
return DocumentSettings::default();
};
let Ok(doc) = roxmltree::Document::parse(&xml_text) else {
return DocumentSettings::default();
};
let root = doc.root_element();
let default_tab_stop = wml(root, "defaultTabStop")
.and_then(|n| twips_attr(n, "val"))
.unwrap_or(36.0);
let theme_font_lang = wml(root, "themeFontLang");
let lang = |attr| {
theme_font_lang
.and_then(|n| n.attribute((WML_NS, attr)))
.map(str::to_string)
};
let east_asia_lang = lang("eastAsia");
let default_lang = lang("val");
let bidi_lang = lang("bidi");
let compat = wml(root, "compat");
let compat_flag = |name| compat.and_then(|c| wml_bool(c, name)).unwrap_or(false);
DocumentSettings {
even_and_odd_headers: wml_bool(root, "evenAndOddHeaders").unwrap_or(false),
mirror_margins: wml_bool(root, "mirrorMargins").unwrap_or(false),
default_tab_stop,
gutter_at_top: wml_bool(root, "gutterAtTop").unwrap_or(false),
east_asia_lang,
bidi_lang,
default_lang,
compress_punctuation: wml_attr(root, "characterSpacingControl")
.is_some_and(|v| v.starts_with("compressPunctuation")),
compat_mode: compat
.into_iter()
.flat_map(|c| c.children())
.find(|n| n.attribute((WML_NS, "name")) == Some("compatibilityMode"))
.and_then(|n| n.attribute((WML_NS, "val")))
.and_then(|v| v.parse().ok())
.unwrap_or(0),
styles_from_normal_template: wml_bool(root, "linkStyles").unwrap_or(false)
&& wml(root, "attachedTemplate").is_none(),
do_not_expand_shift_return: compat_flag("doNotExpandShiftReturn"),
adjust_line_height_in_table: compat_flag("adjustLineHeightInTable"),
}
}