# Writer Application Code

Exact history was lost before Sept. 18th, 2000, but old source code
comments show that Writer core dates back until at least November
1990.

## Module Contents
 * `inc`: headers available to all source files inside the module
 * `qa`: unit, slow and subsequent tests
 * `sdi`
 * `source`: see below
 * `uiconfig`: user interface configuration
 * `util`: UNO passive registration config

## Source Contents
 * `core`: Writer core (document model, layout, UNO API implementation)
 * `filter`: Writer internal filters
   * `ascii`: plain text filter
   * `basflt`
   * `docx`: wrapper for the UNO DOCX import filter (in writerfilter) for autotext purposes
   * `html`: HTML filter
   * `inc`: include files for filters
   * `rtf`: thin copy&paste helper around the UNO RTF import filter (in writerfilter)
   * `writer`
   * `ww8`: DOC import, DOC/DOCX/RTF export
   * `xml`: ODF import/export, subclassed from xmloff (where most of the work is done)
 * `uibase`: user interface (those parts that are linked into `sw` & always loaded)
 * `ui`: user interface (optional parts that are loaded on demand (`swui`))

## Core

There is a good overview documentation of basic architecture of Writer core
in the OOo wiki:

- <https://web.archive.org/web/20240703103909/https://wiki.openoffice.org/wiki/Writer/Core_And_Layout>
- <https://web.archive.org/web/20240703234819/https://wiki.openoffice.org/wiki/Writer/Text_Formatting>

Writer specific WhichIds are defined in `sw/inc/hintids.hxx`.

The details below are mainly about details missing from the wiki pages.

### SwDoc

The central class for a document is `SwDoc`, which represents a document.

A lot of the functionality is split out into separate Manager classes,
each of which implements some `IDocument*` interface; there are
`SwDoc::getIDocument*()` methods to retrieve the managers.

However there are still too many members and methods in this class,
many of which could be moved to some Manager or other...

### SwNodes

Basically a (fancy) array of `SwNode` pointers.  There are special subclasses of
`SwNode` (`SwStartNode` and `SwEndNode`) which are used to encode a nested tree
structure into the flat array; the range of nodes from `SwStartNode` to its
corresponding `SwEndNode` is sometimes called a "section" (but is not necessarily
what the high-level document model calls a "Section"; that is just one of the
possibilities).

The `SwNodes` contains the following top-level sections:

1. Empty
2. Footnote content
3. Frame / Header / Footer content
4. Deleted Change Tracking content
5. Body content

### Undo

The Undo/Redo information is stored in a `sw::UndoManager` member of `SwDoc`,
which implements the `IDocumentUndoRedo` interface.
Its members include a `SwNodes` array containing the document content that
is currently not in the actual document but required for Undo/Redo, and
a stack of `SwUndo` actions, each of which represents one user-visible
Undo/Redo step.

There are also `ListActions` which internally contain several individual `SwUndo`
actions; these are created by the StartUndo/EndUndo wrapper methods.

### Text Attributes

The sub-structure of paragraphs is stored in the `SwpHintsArray` member
`SwTextNode::m_pSwpHints`.  There is a base class `SwTextAttr` with numerous
subclasses; the `SwTextAttr` has a start and end index and a `SfxPoolItem`
to store the actual formatting attribute.

There are several sub-categories of `SwTextAttr`:

- formatting attributes: Character Styles (`SwTextCharFormat`, `RES_TXTATR_CHARFMT`)
  and Automatic Styles (no special class, `RES_TXTATR_AUTOFMT`):
  these are handled by `SwpHintsArray::BuildPortions` and MergePortions,
  which create non-overlapping portions of formatting attributes.

- nesting attributes: Hyperlinks (`SwTextINetFormat`, `RES_TXTATR_INETFMT`),
  Ruby (`SwTextRuby`, `RES_TXTATR_CJK_RUBY`) and Meta/MetaField (`SwTextMeta`,
  `RES_TXTATR_META/RES_TXTATR_METAFIELD`):
  these maintain a properly nested tree structure.
  The Meta/Metafield are "special" because they have both start/end
  and a dummy character at the start.

- misc. attributes: Reference Marks, ToX Marks

- attributes without end: Fields, Footnotes, Flys (`AS_CHAR`)
  These all have a corresponding dummy character in the paragraph text, which
  is a placeholder for the "expansion" of the attribute, e.g. field content.

### Fields

There are multiple model classes involved for fields:

- `enum SwFieldIds` enumerates the different types of fields.
- `SwFieldType` contains some shared stuff for all fields of a type.
  There are many subclasses of `SwFieldType`, one for each different type
  of field.
  For most types of fields there is one shared instance of this per type,
  which is created in `DocumentFieldsManager::InitFieldTypes()`
  but for some there are more than one, and they are dynamically created, see
  `DocumentFieldsManager::InsertFieldType()`.  An example for the latter are
  variable fields (`SwFieldIds::GetExp/SwFieldIds::SetExp`), with one `SwFieldType` per
  variable.
- `SwXFieldMaster` is the UNO wrapper of a field type.
  It is a `SwClient` registered at the `SwFieldType`.
  Its life-cycle is determined by UNO clients outside of `sw`; it will get
  disposed when the `SwFieldType` dies.
- `SwFormatField` is the `SfxPoolItem` of a field.
  The `SwFormatField` is a `SwClient` registered at its `SwFieldType`.
  The `SwFormatField` owns the `SwField` of the field.
- `SwField` contains the core logic of a field.
  The `SwField` is owned by the `SwFormatField` of the field.
  There are many subclasses of `SwField`, one for each different type of field.
  Note that there are not many places that can Expand the field to its
  correct value, since for example page number fields require a View
  with an up to date layout; therefore the correct expansion is cached.
- `SwTextField` is the text attribute of a field.
  It owns the `SwFormatField` of the field (like all text attributes).
- `SwXTextField` is the UNO wrapper object of a field.
  It is a `SwClient` registered at the `SwFormatField`.
  Its life-cycle is determined by UNO clients outside of `sw`; it will get
  disposed when the `SwFormatField` dies.

### Lists

- `SwNumFormat` (subclass of `SvxNumFormat`) determines the formatting of a single
  numbering level.

- `SwNumRule` (NOT a subclass of `SvxNumRule`) is a *list style*, containing one
  `SwNumFormat` per list level.
  `SwNumRule::maTextNodeList` is the list of `SwTextNode` that have this list style
  applied.

- `SwNumberTreeNode` is a base class that represents an abstract node in a
  hierarchical tree of numbered nodes.

- `SwNodeNum` is the subclass of `SwNumberTreeNode` that connects it with an
  actual `SwTextNode` and also with a `SwNumRule`;
  `SwTextNode::mpNodeNum` points back in the other direction

- `SwList` represents a list, which is (mostly) a vector of `SwNodeNum` trees,
  one per `SwNodes` top-level section (why that?).

- `IDocumentListsAccess`, `sw::DocumentListsManager` owns all `SwList` instances,
  and maintains mappings:
  + from list-id to `SwList`
  + from list style name to `SwList` (the "default" `SwList` for that list style)

- `IDocumentListItems`, `sw::DocumentListItemsManager` contains a set of all
  `SwNodeNum` instances, ordered by `SwNode` index

- the special Outline numbering rule: `SwDoc::mpOutlineRule`

- `IDocumentOutlineNodes`, `sw::DocumentOutlineNodesManager` maintain
  a list (which is actually stored in `SwNodes::m_pOutlineNodes`) of `SwTextNodes`
  that either have the Outline numrule applied,
  or have the `RES_PARATR_OUTLINELEVEL` item set (note that in the latter case,
  the `SwTextNode` does not have a `SwNodeNum` and is not associated with the
  `SwDoc::mpOutlineRule`).

- `SwTextNodes` and paragraph styles have items/properties:
  + `RES_PARATR_OUTLINELEVEL/"OutlineLevel"` to specify an outline level without
    necessarily having the outline `SwNumRule` assigned
  + `RES_PARATR_NUMRULE/"NumberingStyleName"` the list style to apply; may be
    empty `""` which means no list style (to override inherited value)
  Only `SwTextNode` has these items:
  + `RES_PARATR_LIST_ID/"ListId"`
    determines the `SwList` to which the node is added
  + `RES_PARATR_LIST_LEVEL/"NumberingLevel"`
    the level at which the `SwTextNode` will appear in the list
  + `RES_PARATR_LIST_ISRESTART/"ParaIsNumberingRestart"`
    restart numbering sequence at this `SwTextNode`
  + `RES_PARATR_LIST_RESTARTVALUE/"NumberingStartValue"`
    restart numbering sequence at this `SwTextNode` with this value
  + `RES_PARATR_LIST_ISCOUNTED/"NumberingIsNumber"`
    determines if the node is actually counted in the numbering sequence;
    these are different from `"phantoms"` because there's still a `SwTextNode`.

Note that there is no UNO service to represent a list.

### Styles

Styles are either user-defined, or built-in.

User-defined styles simply have a user-defined name.

Built-in styles are identified by `RES_POOL*` constants in `inc/poolfmt.hxx`.

Each built-in style has 2 names:

* programmatic name (ProgName): this is defined in functions
  `SwStyleNameMapper::GetTextProgNameArray()` etc, and *never* *ever* changes.

* translatable name (UIName): this is defined as `STR_POOL*` constants
  for en-US in `sw/inc/strings.hrc` and is translated like any other
  translatable string.
  These strings have been changed and may change in future versions.

At the UNO API, and in ODF documents, only ProgNames are relevant.

In the UI, the UINames are used.

Unfortunately the core code also uses UIName, it would be better if it used
ProgName and the conversion would happen in UI code.

### Layout

The layout is a tree of `SwFrame` subclasses, the following relationships are
possible between frames:

- You can visit the tree by following the upper, lower, next and previous pointers.
- The functionality of flowing of a frame across multiple parents (e.g. pages)
  is implemented in `SwFlowFrame`, which is not an `SwFrame` subclass. The logical
  chain of such frames can be visited using the follow and precede pointers.
  ("Leaf" is a term that refers to such a relationship.)
- In case a frame is split into multiple parts, then the first one is called
  master, while the others are called follows.
