Place: Word 97-2003 .doc files place as area type with their formatting

File > Place reads a Word 97-2003 document (a compound file named .doc,
or one that holds a WordDocument stream) and sets its main text as area
type, as it does for .rtf and .docx files. The text comes from the
piece table, in 16-bit Unicode or compressed 8-bit pieces. Formatting
is resolved from the style sheet's default font, the paragraph style,
the character style and the direct character and paragraph properties,
and keeps the same properties the .docx reader maps.

Table cells are separated by tabs and each row is a paragraph, and a
field places as its result. Hidden and deleted text, pictures, headers,
footers, notes, comments and text boxes are left out, and the reply's
warnings name each kind of content left out or changed once. Word 6.0
and Word 95 documents, encrypted documents and documents last saved
with fast save are refused, and so are structures that lie outside
their streams.

The compound file is read with the cfb crate (MIT), which adds one
package to Cargo.lock.
This commit is contained in:
dotCooCoo
2026-11-01 07:16:29 +07:00
committed by bflatastic
parent 859b3732c1
commit 5fdccdf602
11 changed files with 1734 additions and 15 deletions
+11 -4
View File
@@ -566,8 +566,14 @@ pub const RTF_EXTS: &[&str] = &["rtf"];
/// Word documents: File → Place sets them as area type with their formatting.
pub const DOCX_EXTS: &[&str] = &["docx"];
/// Every extension File → Place reads: [`OPEN_EXTS`], [`TEXT_EXTS`], [`RTF_EXTS`] and
/// [`DOCX_EXTS`].
/// Word 97-2003 documents: File → Place sets them as area type with their formatting.
pub const DOC_EXTS: &[&str] = &["doc"];
/// The Place dialog's Word filter: Word documents and Word 97-2003 documents.
const WORD_EXTS: &[&str] = &["docx", "doc"];
/// Every extension File → Place reads: [`OPEN_EXTS`], [`TEXT_EXTS`], [`RTF_EXTS`],
/// [`DOCX_EXTS`] and [`DOC_EXTS`].
pub const PLACE_EXTS: &[&str] = &[
"vectorcraft",
"drawcraft",
@@ -610,6 +616,7 @@ pub const PLACE_EXTS: &[&str] = &[
"txt",
"rtf",
"docx",
"doc",
];
/// One dialog filter per readable format.
@@ -645,13 +652,13 @@ pub fn library_open_filters(
}
/// File → Place dialog filters: "All placeable files", then one per placeable format, then text,
/// RTF and Word.
/// RTF and Word (`.docx` and `.doc`).
pub fn place_filters() -> impl Iterator<Item = (&'static str, &'static [&'static str])> {
std::iter::once(("All placeable files", PLACE_EXTS))
.chain(format_filters().filter(|(_, exts)| exts.iter().all(|ext| PLACE_EXTS.contains(ext))))
.chain(std::iter::once(("Text", TEXT_EXTS)))
.chain(std::iter::once(("RTF", RTF_EXTS)))
.chain(std::iter::once(("Word", DOCX_EXTS)))
.chain(std::iter::once(("Word", WORD_EXTS)))
}
/// A format by id or extension (any case, leading dot allowed; `jpeg` finds `jpg`): a built-in