2 * RichEdit - functions working on paragraphs of text (diParagraph).
4 * Copyright 2004 by Krzysztof Foltman
5 * Copyright 2006 by Phil Krylov
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 WINE_DEFAULT_DEBUG_CHANNEL(richedit
);
26 static const WCHAR wszParagraphSign
[] = {0xB6, 0};
28 void ME_MakeFirstParagraph(ME_TextEditor
*editor
)
36 ME_TextBuffer
*text
= editor
->pBuffer
;
37 ME_DisplayItem
*para
= ME_MakeDI(diParagraph
);
41 hDC
= GetDC(editor
->hWnd
);
43 ME_InitContext(&c
, editor
, hDC
);
44 hf
= (HFONT
)GetStockObject(SYSTEM_FONT
);
46 GetObjectW(hf
, sizeof(LOGFONTW
), &lf
);
47 ZeroMemory(&cf
, sizeof(cf
));
48 cf
.cbSize
= sizeof(cf
);
49 cf
.dwMask
= CFM_BACKCOLOR
|CFM_COLOR
|CFM_FACE
|CFM_SIZE
|CFM_CHARSET
;
50 cf
.dwMask
|= CFM_ALLCAPS
|CFM_BOLD
|CFM_DISABLED
|CFM_EMBOSS
|CFM_HIDDEN
;
51 cf
.dwMask
|= CFM_IMPRINT
|CFM_ITALIC
|CFM_LINK
|CFM_OUTLINE
|CFM_PROTECTED
;
52 cf
.dwMask
|= CFM_REVISED
|CFM_SHADOW
|CFM_SMALLCAPS
|CFM_STRIKEOUT
;
53 cf
.dwMask
|= CFM_SUBSCRIPT
|CFM_UNDERLINETYPE
|CFM_WEIGHT
;
55 cf
.dwEffects
= CFE_AUTOCOLOR
| CFE_AUTOBACKCOLOR
;
56 lstrcpyW(cf
.szFaceName
, lf
.lfFaceName
);
57 cf
.yHeight
= ME_twips2pointsY(&c
, lf
.lfHeight
);
58 if (lf
.lfWeight
>= 700) cf
.dwEffects
|= CFE_BOLD
;
59 cf
.wWeight
= lf
.lfWeight
;
60 if (lf
.lfItalic
) cf
.dwEffects
|= CFE_ITALIC
;
61 cf
.bUnderlineType
= (lf
.lfUnderline
) ? CFU_CF1UNDERLINE
: CFU_UNDERLINENONE
;
62 if (lf
.lfStrikeOut
) cf
.dwEffects
|= CFE_STRIKEOUT
;
63 cf
.bPitchAndFamily
= lf
.lfPitchAndFamily
;
64 cf
.bCharSet
= lf
.lfCharSet
;
66 ZeroMemory(&fmt
, sizeof(fmt
));
67 fmt
.cbSize
= sizeof(fmt
);
68 fmt
.dwMask
= PFM_ALIGNMENT
| PFM_OFFSET
| PFM_STARTINDENT
| PFM_RIGHTINDENT
| PFM_TABSTOPS
;
69 fmt
.wAlignment
= PFA_LEFT
;
71 CopyMemory(para
->member
.para
.pFmt
, &fmt
, sizeof(PARAFORMAT2
));
73 style
= ME_MakeStyle(&cf
);
74 text
->pDefaultStyle
= style
;
76 run
= ME_MakeRun(style
, ME_MakeString(wszParagraphSign
), MERF_ENDPARA
);
77 run
->member
.run
.nCharOfs
= 0;
79 ME_InsertBefore(text
->pLast
, para
);
80 ME_InsertBefore(text
->pLast
, run
);
81 para
->member
.para
.prev_para
= text
->pFirst
;
82 para
->member
.para
.next_para
= text
->pLast
;
83 text
->pFirst
->member
.para
.next_para
= para
;
84 text
->pLast
->member
.para
.prev_para
= para
;
86 text
->pLast
->member
.para
.nCharOfs
= 1;
88 ME_DestroyContext(&c
);
89 ReleaseDC(editor
->hWnd
, hDC
);
92 void ME_MarkAllForWrapping(ME_TextEditor
*editor
)
94 ME_MarkForWrapping(editor
, editor
->pBuffer
->pFirst
->member
.para
.next_para
, editor
->pBuffer
->pLast
);
97 void ME_MarkForWrapping(ME_TextEditor
*editor
, ME_DisplayItem
*first
, const ME_DisplayItem
*last
)
101 first
->member
.para
.nFlags
|= MEPF_REWRAP
;
102 first
= first
->member
.para
.next_para
;
106 void ME_MarkForPainting(ME_TextEditor
*editor
, ME_DisplayItem
*first
, const ME_DisplayItem
*last
)
110 first
->member
.para
.nFlags
|= MEPF_REPAINT
;
111 first
= first
->member
.para
.next_para
;
115 /* split paragraph at the beginning of the run */
116 ME_DisplayItem
*ME_SplitParagraph(ME_TextEditor
*editor
, ME_DisplayItem
*run
, ME_Style
*style
)
118 ME_DisplayItem
*next_para
= NULL
;
119 ME_DisplayItem
*run_para
= NULL
;
120 ME_DisplayItem
*new_para
= ME_MakeDI(diParagraph
);
121 ME_DisplayItem
*end_run
= ME_MakeRun(style
,ME_MakeString(wszParagraphSign
), MERF_ENDPARA
);
122 ME_UndoItem
*undo
= NULL
;
125 int end_len
= (editor
->bEmulateVersion10
? 2 : 1);
127 assert(run
->type
== diRun
);
129 run_para
= ME_GetParagraph(run
);
130 assert(run_para
->member
.para
.pFmt
->cbSize
== sizeof(PARAFORMAT2
));
132 ofs
= end_run
->member
.run
.nCharOfs
= run
->member
.run
.nCharOfs
;
133 next_para
= run_para
->member
.para
.next_para
;
134 assert(next_para
== ME_FindItemFwd(run_para
, diParagraphOrEnd
));
136 undo
= ME_AddUndoItem(editor
, diUndoJoinParagraphs
, NULL
);
138 undo
->nStart
= run_para
->member
.para
.nCharOfs
+ ofs
;
140 /* the new paragraph will have a different starting offset, so let's update its runs */
142 while(pp
->type
== diRun
) {
143 pp
->member
.run
.nCharOfs
-= ofs
;
144 pp
= ME_FindItemFwd(pp
, diRunOrParagraphOrEnd
);
146 new_para
->member
.para
.nCharOfs
= ME_GetParagraph(run
)->member
.para
.nCharOfs
+ofs
;
147 new_para
->member
.para
.nCharOfs
+= end_len
;
149 new_para
->member
.para
.nFlags
= MEPF_REWRAP
; /* FIXME copy flags (if applicable) */
150 /* FIXME initialize format style and call ME_SetParaFormat blah blah */
151 CopyMemory(new_para
->member
.para
.pFmt
, run_para
->member
.para
.pFmt
, sizeof(PARAFORMAT2
));
153 new_para
->member
.para
.bTable
= run_para
->member
.para
.bTable
;
155 /* Inherit previous cell definitions if any */
156 new_para
->member
.para
.pCells
= NULL
;
157 if (run_para
->member
.para
.pCells
)
159 ME_TableCell
*pCell
, *pNewCell
;
161 for (pCell
= run_para
->member
.para
.pCells
; pCell
; pCell
= pCell
->next
)
163 pNewCell
= ALLOC_OBJ(ME_TableCell
);
164 pNewCell
->nRightBoundary
= pCell
->nRightBoundary
;
165 pNewCell
->next
= NULL
;
166 if (new_para
->member
.para
.pCells
)
167 new_para
->member
.para
.pLastCell
->next
= pNewCell
;
169 new_para
->member
.para
.pCells
= pNewCell
;
170 new_para
->member
.para
.pLastCell
= pNewCell
;
174 /* fix paragraph properties. FIXME only needed when called from RTF reader */
175 if (run_para
->member
.para
.pCells
&& !run_para
->member
.para
.bTable
)
177 /* Paragraph does not have an \intbl keyword, so any table definition
178 * stored is invalid */
179 ME_DestroyTableCellList(run_para
);
182 /* insert paragraph into paragraph double linked list */
183 new_para
->member
.para
.prev_para
= run_para
;
184 new_para
->member
.para
.next_para
= next_para
;
185 run_para
->member
.para
.next_para
= new_para
;
186 next_para
->member
.para
.prev_para
= new_para
;
188 /* insert end run of the old paragraph, and new paragraph, into DI double linked list */
189 ME_InsertBefore(run
, new_para
);
190 ME_InsertBefore(new_para
, end_run
);
192 /* force rewrap of the */
193 run_para
->member
.para
.prev_para
->member
.para
.nFlags
|= MEPF_REWRAP
;
194 new_para
->member
.para
.prev_para
->member
.para
.nFlags
|= MEPF_REWRAP
;
196 /* we've added the end run, so we need to modify nCharOfs in the next paragraphs */
197 ME_PropagateCharOffset(next_para
, end_len
);
198 editor
->nParagraphs
++;
203 /* join tp with tp->member.para.next_para, keeping tp's style; this
204 * is consistent with the original */
205 ME_DisplayItem
*ME_JoinParagraphs(ME_TextEditor
*editor
, ME_DisplayItem
*tp
)
207 ME_DisplayItem
*pNext
, *pFirstRunInNext
, *pRun
, *pTmp
;
209 ME_UndoItem
*undo
= NULL
;
210 int end_len
= (editor
->bEmulateVersion10
? 2 : 1);
212 assert(tp
->type
== diParagraph
);
213 assert(tp
->member
.para
.next_para
);
214 assert(tp
->member
.para
.next_para
->type
== diParagraph
);
216 pNext
= tp
->member
.para
.next_para
;
219 /* null char format operation to store the original char format for the ENDPARA run */
221 ME_InitCharFormat2W(&fmt
);
222 ME_SetCharFormat(editor
, pNext
->member
.para
.nCharOfs
- end_len
, end_len
, &fmt
);
224 undo
= ME_AddUndoItem(editor
, diUndoSplitParagraph
, NULL
);
227 undo
->nStart
= pNext
->member
.para
.nCharOfs
- end_len
;
228 assert(pNext
->member
.para
.pFmt
->cbSize
== sizeof(PARAFORMAT2
));
229 CopyMemory(undo
->di
.member
.para
.pFmt
, pNext
->member
.para
.pFmt
, sizeof(PARAFORMAT2
));
232 shift
= pNext
->member
.para
.nCharOfs
- tp
->member
.para
.nCharOfs
- end_len
;
234 pRun
= ME_FindItemBack(pNext
, diRunOrParagraph
);
235 pFirstRunInNext
= ME_FindItemFwd(pNext
, diRunOrParagraph
);
238 assert(pRun
->type
== diRun
);
239 assert(pRun
->member
.run
.nFlags
& MERF_ENDPARA
);
240 assert(pFirstRunInNext
->type
== diRun
);
242 /* if some cursor points at end of paragraph, make it point to the first
243 run of the next joined paragraph */
244 for (i
=0; i
<editor
->nCursors
; i
++) {
245 if (editor
->pCursors
[i
].pRun
== pRun
) {
246 editor
->pCursors
[i
].pRun
= pFirstRunInNext
;
247 editor
->pCursors
[i
].nOffset
= 0;
253 pTmp
= ME_FindItemFwd(pTmp
, diRunOrParagraphOrEnd
);
254 if (pTmp
->type
!= diRun
)
256 TRACE("shifting \"%s\" by %d (previous %d)\n", debugstr_w(pTmp
->member
.run
.strText
->szData
), shift
, pTmp
->member
.run
.nCharOfs
);
257 pTmp
->member
.run
.nCharOfs
+= shift
;
261 ME_DestroyDisplayItem(pRun
);
263 if (editor
->pLastSelStartPara
== pNext
)
264 editor
->pLastSelStartPara
= tp
;
265 if (editor
->pLastSelEndPara
== pNext
)
266 editor
->pLastSelEndPara
= tp
;
268 tp
->member
.para
.next_para
= pNext
->member
.para
.next_para
;
269 pNext
->member
.para
.next_para
->member
.para
.prev_para
= tp
;
271 ME_DestroyDisplayItem(pNext
);
273 ME_PropagateCharOffset(tp
->member
.para
.next_para
, -end_len
);
275 ME_CheckCharOffsets(editor
);
277 editor
->nParagraphs
--;
278 tp
->member
.para
.nFlags
|= MEPF_REWRAP
;
282 ME_DisplayItem
*ME_GetParagraph(ME_DisplayItem
*item
) {
283 return ME_FindItemBackOrHere(item
, diParagraph
);
286 void ME_DumpParaStyleToBuf(const PARAFORMAT2
*pFmt
, char buf
[2048])
291 #define DUMP(mask, name, fmt, field) \
292 if (pFmt->dwMask & (mask)) p += sprintf(p, "%-22s" fmt "\n", name, pFmt->field); \
293 else p += sprintf(p, "%-22sN/A\n", name);
295 /* we take for granted that PFE_xxx is the hiword of the corresponding PFM_xxx */
296 #define DUMP_EFFECT(mask, name) \
297 p += sprintf(p, "%-22s%s\n", name, (pFmt->dwMask & (mask)) ? ((pFmt->wEffects & ((mask) >> 8)) ? "yes" : "no") : "N/A");
299 DUMP(PFM_NUMBERING
, "Numbering:", "%u", wNumbering
);
300 DUMP_EFFECT(PFM_DONOTHYPHEN
, "Disable auto-hyphen:");
301 DUMP_EFFECT(PFM_KEEP
, "No page break in para:");
302 DUMP_EFFECT(PFM_KEEPNEXT
, "No page break in para & next:");
303 DUMP_EFFECT(PFM_NOLINENUMBER
, "No line number:");
304 DUMP_EFFECT(PFM_NOWIDOWCONTROL
, "No widow & orphan:");
305 DUMP_EFFECT(PFM_PAGEBREAKBEFORE
, "Page break before:");
306 DUMP_EFFECT(PFM_RTLPARA
, "RTL para:");
307 DUMP_EFFECT(PFM_SIDEBYSIDE
, "Side by side:");
308 DUMP_EFFECT(PFM_TABLE
, "Table:");
309 DUMP(PFM_OFFSETINDENT
, "Offset indent:", "%d", dxStartIndent
);
310 DUMP(PFM_STARTINDENT
, "Start indent:", "%d", dxStartIndent
);
311 DUMP(PFM_RIGHTINDENT
, "Right indent:", "%d", dxRightIndent
);
312 DUMP(PFM_OFFSET
, "Offset:", "%d", dxOffset
);
313 if (pFmt
->dwMask
& PFM_ALIGNMENT
) {
314 switch (pFmt
->wAlignment
) {
315 case PFA_LEFT
: p
+= sprintf(p
, "Alignment: left\n"); break;
316 case PFA_RIGHT
: p
+= sprintf(p
, "Alignment: right\n"); break;
317 case PFA_CENTER
: p
+= sprintf(p
, "Alignment: center\n"); break;
318 case PFA_JUSTIFY
: p
+= sprintf(p
, "Alignment: justify\n"); break;
319 default : p
+= sprintf(p
, "Alignment: incorrect %d\n", pFmt
->wAlignment
); break;
322 else p
+= sprintf(p
, "Alignment: N/A\n");
323 DUMP(PFM_TABSTOPS
, "Tab Stops:", "%d", cTabCount
);
324 if (pFmt
->dwMask
& PFM_TABSTOPS
) {
326 p
+= sprintf(p
, "\t");
327 for (i
= 0; i
< pFmt
->cTabCount
; i
++) p
+= sprintf(p
, "%x ", pFmt
->rgxTabs
[i
]);
328 p
+= sprintf(p
, "\n");
330 DUMP(PFM_SPACEBEFORE
, "Space Before:", "%d", dySpaceBefore
);
331 DUMP(PFM_SPACEAFTER
, "Space After:", "%d", dySpaceAfter
);
332 DUMP(PFM_LINESPACING
, "Line spacing:", "%d", dyLineSpacing
);
333 DUMP(PFM_STYLE
, "Text style:", "%d", sStyle
);
334 DUMP(PFM_LINESPACING
, "Line spacing rule:", "%u", bLineSpacingRule
);
335 /* bOutlineLevel should be 0 */
336 DUMP(PFM_SHADING
, "Shading Weigth:", "%u", wShadingWeight
);
337 DUMP(PFM_SHADING
, "Shading Style:", "%u", wShadingStyle
);
338 DUMP(PFM_NUMBERINGSTART
, "Numbering Start:", "%u", wNumberingStart
);
339 DUMP(PFM_NUMBERINGSTYLE
, "Numbering Style:", "0x%x", wNumberingStyle
);
340 DUMP(PFM_NUMBERINGTAB
, "Numbering Tab:", "%u", wNumberingStyle
);
341 DUMP(PFM_BORDER
, "Border Space:", "%u", wBorderSpace
);
342 DUMP(PFM_BORDER
, "Border Width:", "%u", wBorderWidth
);
343 DUMP(PFM_BORDER
, "Borders:", "%u", wBorders
);
349 void ME_SetParaFormat(ME_TextEditor
*editor
, ME_DisplayItem
*para
, const PARAFORMAT2
*pFmt
)
352 assert(sizeof(*para
->member
.para
.pFmt
) == sizeof(PARAFORMAT2
));
353 ME_AddUndoItem(editor
, diUndoSetParagraphFormat
, para
);
355 CopyMemory(©
, para
->member
.para
.pFmt
, sizeof(PARAFORMAT2
));
357 #define COPY_FIELD(m, f) \
358 if (pFmt->dwMask & (m)) { \
359 para->member.para.pFmt->dwMask |= m; \
360 para->member.para.pFmt->f = pFmt->f; \
363 COPY_FIELD(PFM_NUMBERING
, wNumbering
);
364 #define EFFECTS_MASK (PFM_RTLPARA|PFM_KEEP|PFM_KEEPNEXT|PFM_PAGEBREAKBEFORE| \
365 PFM_NOLINENUMBER|PFM_NOWIDOWCONTROL|PFM_DONOTHYPHEN|PFM_SIDEBYSIDE| \
367 /* we take for granted that PFE_xxx is the hiword of the corresponding PFM_xxx */
368 if (pFmt
->dwMask
& EFFECTS_MASK
) {
369 para
->member
.para
.pFmt
->dwMask
&= ~(pFmt
->dwMask
& EFFECTS_MASK
);
370 para
->member
.para
.pFmt
->wEffects
|= pFmt
->wEffects
& HIWORD(pFmt
->dwMask
);
374 COPY_FIELD(PFM_STARTINDENT
, dxStartIndent
);
375 if (pFmt
->dwMask
& PFM_OFFSETINDENT
)
376 para
->member
.para
.pFmt
->dxStartIndent
+= pFmt
->dxStartIndent
;
377 COPY_FIELD(PFM_RIGHTINDENT
, dxRightIndent
);
378 COPY_FIELD(PFM_OFFSET
, dxOffset
);
379 COPY_FIELD(PFM_ALIGNMENT
, wAlignment
);
381 if (pFmt
->dwMask
& PFM_TABSTOPS
)
383 para
->member
.para
.pFmt
->cTabCount
= pFmt
->cTabCount
;
384 memcpy(para
->member
.para
.pFmt
->rgxTabs
, pFmt
->rgxTabs
, pFmt
->cTabCount
*sizeof(LONG
));
386 COPY_FIELD(PFM_SPACEBEFORE
, dySpaceBefore
);
387 COPY_FIELD(PFM_SPACEAFTER
, dySpaceAfter
);
388 COPY_FIELD(PFM_LINESPACING
, dyLineSpacing
);
389 COPY_FIELD(PFM_STYLE
, sStyle
);
390 COPY_FIELD(PFM_LINESPACING
, bLineSpacingRule
);
391 COPY_FIELD(PFM_SHADING
, wShadingWeight
);
392 COPY_FIELD(PFM_SHADING
, wShadingStyle
);
393 COPY_FIELD(PFM_NUMBERINGSTART
, wNumberingStart
);
394 COPY_FIELD(PFM_NUMBERINGSTYLE
, wNumberingStyle
);
395 COPY_FIELD(PFM_NUMBERINGTAB
, wNumberingTab
);
396 COPY_FIELD(PFM_BORDER
, wBorderSpace
);
397 COPY_FIELD(PFM_BORDER
, wBorderWidth
);
398 COPY_FIELD(PFM_BORDER
, wBorders
);
400 para
->member
.para
.pFmt
->dwMask
|= pFmt
->dwMask
;
403 if (memcmp(©
, para
->member
.para
.pFmt
, sizeof(PARAFORMAT2
)))
404 para
->member
.para
.nFlags
|= MEPF_REWRAP
;
409 ME_GetSelectionParas(ME_TextEditor
*editor
, ME_DisplayItem
**para
, ME_DisplayItem
**para_end
)
411 ME_Cursor
*pEndCursor
= &editor
->pCursors
[1];
413 *para
= ME_GetParagraph(editor
->pCursors
[0].pRun
);
414 *para_end
= ME_GetParagraph(editor
->pCursors
[1].pRun
);
415 if ((*para_end
)->member
.para
.nCharOfs
< (*para
)->member
.para
.nCharOfs
) {
416 ME_DisplayItem
*tmp
= *para
;
420 pEndCursor
= &editor
->pCursors
[0];
423 /* selection consists of chars from nFrom up to nTo-1 */
424 if ((*para_end
)->member
.para
.nCharOfs
> (*para
)->member
.para
.nCharOfs
) {
425 if (!pEndCursor
->nOffset
) {
426 *para_end
= ME_GetParagraph(ME_FindItemBack(pEndCursor
->pRun
, diRun
));
432 void ME_SetSelectionParaFormat(ME_TextEditor
*editor
, const PARAFORMAT2
*pFmt
)
434 ME_DisplayItem
*para
, *para_end
;
436 ME_GetSelectionParas(editor
, ¶
, ¶_end
);
439 ME_SetParaFormat(editor
, para
, pFmt
);
440 if (para
== para_end
)
442 para
= para
->member
.para
.next_para
;
446 void ME_GetParaFormat(ME_TextEditor
*editor
, const ME_DisplayItem
*para
, PARAFORMAT2
*pFmt
)
448 if (pFmt
->cbSize
>= sizeof(PARAFORMAT2
))
450 CopyMemory(pFmt
, para
->member
.para
.pFmt
, sizeof(PARAFORMAT2
));
453 CopyMemory(pFmt
, para
->member
.para
.pFmt
, pFmt
->cbSize
);
456 void ME_GetSelectionParaFormat(ME_TextEditor
*editor
, PARAFORMAT2
*pFmt
)
458 ME_DisplayItem
*para
, *para_end
;
461 ME_GetSelectionParas(editor
, ¶
, ¶_end
);
463 ME_GetParaFormat(editor
, para
, pFmt
);
464 if (para
== para_end
) return;
467 ZeroMemory(&tmp
, sizeof(tmp
));
468 tmp
.cbSize
= sizeof(tmp
);
469 ME_GetParaFormat(editor
, para
, &tmp
);
471 #define CHECK_FIELD(m, f) \
472 if (pFmt->f != tmp.f) pFmt->dwMask &= ~(m);
474 CHECK_FIELD(PFM_NUMBERING
, wNumbering
);
475 /* para->member.para.pFmt->wEffects = pFmt->wEffects; */
476 assert(tmp
.dwMask
& PFM_ALIGNMENT
);
477 CHECK_FIELD(PFM_NUMBERING
, wNumbering
);
478 assert(tmp
.dwMask
& PFM_STARTINDENT
);
479 CHECK_FIELD(PFM_STARTINDENT
, dxStartIndent
);
480 assert(tmp
.dwMask
& PFM_RIGHTINDENT
);
481 CHECK_FIELD(PFM_RIGHTINDENT
, dxRightIndent
);
482 assert(tmp
.dwMask
& PFM_OFFSET
);
483 CHECK_FIELD(PFM_OFFSET
, dxOffset
);
484 CHECK_FIELD(PFM_ALIGNMENT
, wAlignment
);
486 assert(tmp
.dwMask
& PFM_TABSTOPS
);
487 if (pFmt
->dwMask
& PFM_TABSTOPS
) {
488 if (pFmt
->cTabCount
!= tmp
.cTabCount
||
489 memcmp(pFmt
->rgxTabs
, tmp
.rgxTabs
, tmp
.cTabCount
*sizeof(int)))
490 pFmt
->dwMask
&= ~PFM_TABSTOPS
;
493 CHECK_FIELD(PFM_SPACEBEFORE
, dySpaceBefore
);
494 CHECK_FIELD(PFM_SPACEAFTER
, dySpaceAfter
);
495 CHECK_FIELD(PFM_LINESPACING
, dyLineSpacing
);
496 CHECK_FIELD(PFM_STYLE
, sStyle
);
497 CHECK_FIELD(PFM_SPACEAFTER
, bLineSpacingRule
);
498 CHECK_FIELD(PFM_SHADING
, wShadingWeight
);
499 CHECK_FIELD(PFM_SHADING
, wShadingStyle
);
500 CHECK_FIELD(PFM_NUMBERINGSTART
, wNumberingStart
);
501 CHECK_FIELD(PFM_NUMBERINGSTYLE
, wNumberingStyle
);
502 CHECK_FIELD(PFM_NUMBERINGTAB
, wNumberingTab
);
503 CHECK_FIELD(PFM_BORDER
, wBorderSpace
);
504 CHECK_FIELD(PFM_BORDER
, wBorderWidth
);
505 CHECK_FIELD(PFM_BORDER
, wBorders
);
509 if (para
== para_end
)
511 para
= para
->member
.para
.next_para
;