Skip to content

Commit 844f3ea

Browse files
committed
docs: TabStops analysis document
1 parent bc34ec9 commit 844f3ea

File tree

1 file changed

+232
-0
lines changed

1 file changed

+232
-0
lines changed
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
2+
Tab Stop Specification
3+
====================
4+
5+
WordprocessingML allows for custom specification of tab stops at the paragraph
6+
level. Tab stop spacing is a subset of paragraph formatting in this system,
7+
so will be implemented within the docx.text.parfmt.ParagraphFormatting object.
8+
Tab stops will be handled as a List-like TabStops object made up of TabStop
9+
objects.
10+
11+
A TabStop object has three properties, alignment, leader, and position.
12+
Alignment is a WD_TAB_ALIGNMENT member and position is a Length() object.
13+
14+
Tab stops are always sorted in position order. Alignment defaults to
15+
WD_TAB_ALIGNMENT.LEFT, and leader defaults to WD_TAB_LEADER.SPACES.
16+
17+
Tab character insertion is already properly handled as part of Runs. This
18+
feature deals with the horizontal spacing of tabs within the document only.
19+
20+
21+
Protocol
22+
~~~~~~~~
23+
24+
.. highlight:: python
25+
26+
Getting and setting tab stops::
27+
28+
>>> tab_stops = paragraph.paragraph_format.tab_stops
29+
>>> tab_stops
30+
<docx.text.parfmt.TabStops object at 0x104ea8c30>
31+
32+
>>> tab_stop = tab_stops.add_tab_stop(Inches(1), WD_TAB_ALIGNMENT.LEFT, WD_TAB_LEADER.DOTS)
33+
# Defaults to WD_TAB_ALIGNMENT.LEFT
34+
>>> tab_stop = tab_stops.add_tab_stop(Inches(2))
35+
# Change settings after creation
36+
>>> tab_stop.position = Inches(2.5)
37+
>>> tab_stop.alignment = WD_TAB_ALIGNMENT.CENTER
38+
>>> tab_stop.leader = WD_TAB_LEADER.DASHES
39+
40+
>>> len(tab_stops)
41+
2
42+
>>> [(t.position, t.alignment) for t in tab_stops]
43+
[(914400, WD_TAB_ALIGNMENT.LEFT), (2286000, WD_TAB_ALIGNMENT.CENTER)]
44+
>>> tab_stops[1].position = Inches(2)
45+
>>> del(tab_stops[1])
46+
# Restore default tabs
47+
>>> tab_stops.clear()
48+
49+
50+
Word Behavior
51+
~~~~~~~~~~~~~
52+
53+
When tab_stops are empty or the w:tabs structure is empty, Word uses default
54+
tab stops at every half inch.
55+
56+
Word defaults to tabs every half inch following the last specified tab_stop.
57+
58+
TabStops must be in position order within the XML. If they are not, the out-
59+
of-order tab stop will appear in the ruler and in the properties dialog, but
60+
will not actually be used by Word.
61+
62+
63+
64+
XML Semantics
65+
~~~~~~~~~~~~~
66+
67+
* Tab stops have a type (w:val), which allows the specification of left,
68+
center, right, decimal, bar, and list alignment.
69+
70+
* The details of the list alignment are elusive. (I have not been able to
71+
create this type of tab stops in Word, even within lists. Perhaps a later
72+
version of Word than I use is required.)
73+
74+
* Tab stops can have a "leader" (w:leader) character.
75+
76+
Specimen XML
77+
~~~~~~~~~~~~
78+
79+
.. highlight:: xml
80+
81+
::
82+
83+
<w:pPr>
84+
<w:tabs>
85+
<w:tab w:val="left" w:leader="dot" w:pos="2880"/>
86+
<w:tab w:val="decimal" w:pos="6480"/>
87+
</w:tabs>
88+
</w:pPr>
89+
90+
91+
Enumerations
92+
------------
93+
94+
* `WdTabAlignment Enumeration on MSDN`_
95+
96+
.. _WdTabAlignment Enumeration on MSDN:
97+
https://msdn.microsoft.com/EN-US/library/office/ff195609.aspx
98+
99+
===================== =============== =================
100+
Type xml text Numeric value
101+
===================== =============== =================
102+
wdAlignTabBar bar 4
103+
wdAlignTabCenter center 1
104+
wdAlignTabDecimal decimal 3
105+
wdAlignTabLeft left 0
106+
wdAlignTabList list 6
107+
wdAlignTabRight right 2
108+
===================== =============== =================
109+
110+
Additional Enumeration values not appearing in WdTabAlignment
111+
===================== =============== =================
112+
Type xml text Numeric value
113+
===================== =============== =================
114+
wdAlignTabClear clear 107
115+
wdAlignTabEnd end 102
116+
wdAlignTabNum num 103
117+
wdAlignTabStart start 100
118+
===================== =============== =================
119+
120+
https://msdn.microsoft.com/en-us/library/ff531527(v=office.12).aspx suggests that "start" is equivalent to "left" and that "end" is equivalent to "right". (I've confirmed this through manual editing of the XML.) "num" produces a "left" tab stop rather than the "decimal" tab stop I'd expected. A "clear" tab stop is not shown in Word's tab bar and default tab behavior is followed in the document. That is, Word ignores that tab stop specification completely, acting as if it were not there at all. This allows a tab stop inherited from a style, for example, to be ignored.
121+
122+
* `WdTabLeader Enumeration on MSDN`_
123+
124+
.. _WdTabLeader Enumeration on MSDN:
125+
https://msdn.microsoft.com/en-us/library/office/ff845050.aspx
126+
127+
===================== =============== =================
128+
Type xml text Numeric value
129+
===================== =============== =================
130+
wdTabLeaderDashes hyphen 2
131+
wdTabLeaderDots dot 1
132+
wdTabLeaderHeavy heavy 4
133+
wdTabLeaderLines underscore 3
134+
wdTabLeaderMiddleDot middleDot 5
135+
wdTabLeaderSpaces none 0
136+
===================== =============== =================
137+
138+
139+
MS API Protocol
140+
~~~~~~~~~~~~~~~
141+
The MS API defines a `TabStops object`_ which is made up of `TabStop objects`_.
142+
143+
.. _TabStops object:
144+
https://msdn.microsoft.com/EN-US/library/office/ff192806.aspx
145+
146+
.. _TabStop objects:
147+
https://msdn.microsoft.com/EN-US/library/office/ff195736.aspx
148+
149+
150+
Schema excerpt
151+
--------------
152+
153+
::
154+
155+
<xsd:complexType name="CT_PPr"> <!-- denormalized -->
156+
<xsd:sequence>
157+
<xsd:element name="pStyle" type="CT_String" minOccurs="0"/>
158+
<xsd:element name="keepNext" type="CT_OnOff" minOccurs="0"/>
159+
<xsd:element name="keepLines" type="CT_OnOff" minOccurs="0"/>
160+
<xsd:element name="pageBreakBefore" type="CT_OnOff" minOccurs="0"/>
161+
<xsd:element name="framePr" type="CT_FramePr" minOccurs="0"/>
162+
<xsd:element name="widowControl" type="CT_OnOff" minOccurs="0"/>
163+
<xsd:element name="numPr" type="CT_NumPr" minOccurs="0"/>
164+
<xsd:element name="suppressLineNumbers" type="CT_OnOff" minOccurs="0"/>
165+
<xsd:element name="pBdr" type="CT_PBdr" minOccurs="0"/>
166+
<xsd:element name="shd" type="CT_Shd" minOccurs="0"/>
167+
<xsd:element name="tabs" type="CT_Tabs" minOccurs="0"/>
168+
<xsd:element name="suppressAutoHyphens" type="CT_OnOff" minOccurs="0"/>
169+
<xsd:element name="kinsoku" type="CT_OnOff" minOccurs="0"/>
170+
<xsd:element name="wordWrap" type="CT_OnOff" minOccurs="0"/>
171+
<xsd:element name="overflowPunct" type="CT_OnOff" minOccurs="0"/>
172+
<xsd:element name="topLinePunct" type="CT_OnOff" minOccurs="0"/>
173+
<xsd:element name="autoSpaceDE" type="CT_OnOff" minOccurs="0"/>
174+
<xsd:element name="autoSpaceDN" type="CT_OnOff" minOccurs="0"/>
175+
<xsd:element name="bidi" type="CT_OnOff" minOccurs="0"/>
176+
<xsd:element name="adjustRightInd" type="CT_OnOff" minOccurs="0"/>
177+
<xsd:element name="snapToGrid" type="CT_OnOff" minOccurs="0"/>
178+
<xsd:element name="spacing" type="CT_Spacing" minOccurs="0"/>
179+
<xsd:element name="ind" type="CT_Ind" minOccurs="0"/>
180+
<xsd:element name="contextualSpacing" type="CT_OnOff" minOccurs="0"/>
181+
<xsd:element name="mirrorIndents" type="CT_OnOff" minOccurs="0"/>
182+
<xsd:element name="suppressOverlap" type="CT_OnOff" minOccurs="0"/>
183+
<xsd:element name="jc" type="CT_Jc" minOccurs="0"/>
184+
<xsd:element name="textDirection" type="CT_TextDirection" minOccurs="0"/>
185+
<xsd:element name="textAlignment" type="CT_TextAlignment" minOccurs="0"/>
186+
<xsd:element name="textboxTightWrap" type="CT_TextboxTightWrap" minOccurs="0"/>
187+
<xsd:element name="outlineLvl" type="CT_DecimalNumber" minOccurs="0"/>
188+
<xsd:element name="divId" type="CT_DecimalNumber" minOccurs="0"/>
189+
<xsd:element name="cnfStyle" type="CT_Cnf" minOccurs="0"/>
190+
<xsd:element name="rPr" type="CT_ParaRPr" minOccurs="0"/>
191+
<xsd:element name="sectPr" type="CT_SectPr" minOccurs="0"/>
192+
<xsd:element name="pPrChange" type="CT_PPrChange" minOccurs="0"/>
193+
</xsd:sequence>
194+
</xsd:complexType>
195+
196+
197+
<xsd:complexType name="CT_Tabs">
198+
<xsd:sequence>
199+
<xsd:element name="tab" type="CT_TabStop" maxOccurs="unbounded"/>
200+
</xsd:sequence>
201+
</xsd:complexType>
202+
203+
<xsd:complexType name="CT_TabStop">
204+
<xsd:attribute name="val" type="ST_TabJc" use="required"/>
205+
<xsd:attribute name="leader" type="ST_TabTlc" use="optional"/>
206+
<xsd:attribute name="pos" type="ST_SignedTwipsMeasure" use="required"/>
207+
</xsd:complexType>
208+
209+
<xsd:simpleType name="ST_TabJc">
210+
<xsd:restriction base="xsd:string">
211+
<xsd:enumeration value="clear"/>
212+
<xsd:enumeration value="start"/>
213+
<xsd:enumeration value="center"/>
214+
<xsd:enumeration value="end"/>
215+
<xsd:enumeration value="decimal"/>
216+
<xsd:enumeration value="bar"/>
217+
<xsd:enumeration value="num"/>
218+
<xsd:enumeration value="left"/>
219+
<xsd:enumeration value="right"/>
220+
</xsd:restriction>
221+
</xsd:simpleType>
222+
223+
<xsd:simpleType name="ST_TabTlc">
224+
<xsd:restriction base="xsd:string">
225+
<xsd:enumeration value="none"/>
226+
<xsd:enumeration value="dot"/>
227+
<xsd:enumeration value="hyphen"/>
228+
<xsd:enumeration value="underscore"/>
229+
<xsd:enumeration value="heavy"/>
230+
<xsd:enumeration value="middleDot"/>
231+
</xsd:restriction>
232+
</xsd:simpleType>

0 commit comments

Comments
 (0)