3 * Copyright (C) 1998-2002 A.J. van Os; Released under GPL
6 * Build, read and destroy a list of Word text blocks
14 * Private structure to hide the way the information
15 * is stored from the rest of the program
17 typedef struct list_mem_tag
{
18 text_block_type tInfo
;
19 struct list_mem_tag
*pNext
;
22 /* Variables to describe the start of the five block lists */
23 static list_mem_type
*pTextAnchor
= NULL
;
24 static list_mem_type
*pFootAnchor
= NULL
;
25 static list_mem_type
*pUnused1Anchor
= NULL
;
26 static list_mem_type
*pEndAnchor
= NULL
;
27 static list_mem_type
*pUnused2Anchor
= NULL
;
28 /* Variable needed to build the block list */
29 static list_mem_type
*pBlockLast
= NULL
;
30 /* Variable needed to read the text block list */
31 static list_mem_type
*pTextBlockCurrent
= NULL
;
32 /* Variable needed to read the footnote block list */
33 static list_mem_type
*pFootBlockCurrent
= NULL
;
34 /* Variable needed to read the endnote block list */
35 static list_mem_type
*pEndBlockCurrent
= NULL
;
37 static UCHAR aucBlock
[BIG_BLOCK_SIZE
];
41 * vDestroyTextBlockList - destroy the text block list
44 vDestroyTextBlockList(void)
46 list_mem_type
*apAnchor
[5];
47 list_mem_type
*pCurr
, *pNext
;
50 DBG_MSG("vDestroyTextBlockList");
52 apAnchor
[0] = pTextAnchor
;
53 apAnchor
[1] = pFootAnchor
;
54 apAnchor
[2] = pUnused1Anchor
;
55 apAnchor
[3] = pEndAnchor
;
56 apAnchor
[4] = pUnused2Anchor
;
58 for (iIndex
= 0; iIndex
< 5; iIndex
++) {
59 pCurr
= apAnchor
[iIndex
];
60 while (pCurr
!= NULL
) {
66 /* Show that there are no lists any more */
69 pUnused1Anchor
= NULL
;
71 pUnused2Anchor
= NULL
;
72 /* Reset all the controle variables */
74 pTextBlockCurrent
= NULL
;
75 pFootBlockCurrent
= NULL
;
76 pEndBlockCurrent
= NULL
;
77 } /* end of vDestroyTextBlockList */
80 * bAdd2TextBlockList - add an element to the text block list
82 * returns: TRUE when successful, otherwise FALSE
85 bAdd2TextBlockList(text_block_type
*pTextBlock
)
87 list_mem_type
*pListMember
;
89 fail(pTextBlock
== NULL
);
90 fail(pTextBlock
->ulFileOffset
== FC_INVALID
);
91 fail(pTextBlock
->ulCharPos
== CP_INVALID
);
92 fail(pTextBlock
->ulLength
== 0);
93 fail(pTextBlock
->bUsesUnicode
&& odd(pTextBlock
->ulLength
));
95 NO_DBG_MSG("bAdd2TextBlockList");
96 NO_DBG_HEX(pTextBlock
->ulFileOffset
);
97 NO_DBG_HEX(pTextBlock
->ulCharPos
);
98 NO_DBG_HEX(pTextBlock
->ulLength
);
99 NO_DBG_DEC(pTextBlock
->bUsesUnicode
);
100 NO_DBG_DEC(pTextBlock
->usPropMod
);
102 if (pTextBlock
->ulFileOffset
== FC_INVALID
||
103 pTextBlock
->ulCharPos
== CP_INVALID
||
104 pTextBlock
->ulLength
== 0 ||
105 (pTextBlock
->bUsesUnicode
&& odd(pTextBlock
->ulLength
))) {
106 werr(0, "Software (textblock) error");
110 * Check for continuous blocks of the same character size and
111 * the same properties modifier
113 if (pBlockLast
!= NULL
&&
114 pBlockLast
->tInfo
.ulFileOffset
+
115 pBlockLast
->tInfo
.ulLength
== pTextBlock
->ulFileOffset
&&
116 pBlockLast
->tInfo
.ulCharPos
+
117 pBlockLast
->tInfo
.ulLength
== pTextBlock
->ulCharPos
&&
118 pBlockLast
->tInfo
.bUsesUnicode
== pTextBlock
->bUsesUnicode
&&
119 pBlockLast
->tInfo
.usPropMod
== pTextBlock
->usPropMod
) {
120 /* These are continous blocks */
121 pBlockLast
->tInfo
.ulLength
+= pTextBlock
->ulLength
;
124 /* Make a new block */
125 pListMember
= xmalloc(sizeof(list_mem_type
));
126 /* Add the block to the list */
127 pListMember
->tInfo
= *pTextBlock
;
128 pListMember
->pNext
= NULL
;
129 if (pTextAnchor
== NULL
) {
130 pTextAnchor
= pListMember
;
132 fail(pBlockLast
== NULL
);
133 pBlockLast
->pNext
= pListMember
;
135 pBlockLast
= pListMember
;
137 } /* end of bAdd2TextBlockList */
141 * vSplitBlockList - split the block list in five parts
143 * Split the blocklist in a Text block list, a Footnote block list, a
144 * Endnote block list and two Unused lists.
147 * The various l*Len input parameters are given in characters, but the
148 * length of the blocks are in bytes.
151 vSplitBlockList(ULONG ulTextLen
, ULONG ulFootnoteLen
, ULONG ulUnused1Len
,
152 ULONG ulEndnoteLen
, ULONG ulUnused2Len
, BOOL bMustExtend
)
154 list_mem_type
*apAnchors
[5];
155 list_mem_type
*pGarbageAnchor
, *pCurr
, *pNext
;
156 long lCharsToGo
, lBytesTooFar
;
162 DBG_MSG("vSplitBlockList");
164 fail(ulTextLen
> (ULONG
)LONG_MAX
);
165 fail(ulFootnoteLen
> (ULONG
)LONG_MAX
);
166 fail(ulUnused1Len
> (ULONG
)LONG_MAX
);
167 fail(ulEndnoteLen
> (ULONG
)LONG_MAX
);
168 fail(ulUnused2Len
> (ULONG
)LONG_MAX
);
170 /* Text block list */
172 lCharsToGo
= (long)ulTextLen
;
174 if (ulTextLen
!= 0) {
175 DBG_MSG("Text block list");
177 for (pCurr
= pTextAnchor
;
179 pCurr
= pCurr
->pNext
) {
180 NO_DBG_DEC(pCurr
->tInfo
.ulLength
);
181 fail(pCurr
->tInfo
.ulLength
== 0);
182 if (pCurr
->tInfo
.bUsesUnicode
) {
183 fail(odd(pCurr
->tInfo
.ulLength
));
184 lCharsToGo
-= pCurr
->tInfo
.ulLength
/ 2;
185 if (lCharsToGo
< 0) {
186 lBytesTooFar
= -2 * lCharsToGo
;
189 lCharsToGo
-= pCurr
->tInfo
.ulLength
;
190 if (lCharsToGo
< 0) {
191 lBytesTooFar
= -lCharsToGo
;
194 if (lCharsToGo
<= 0) {
200 if (ulTextLen
== 0) {
201 /* Empty text blocks list */
202 pFootAnchor
= pTextAnchor
;
204 } else if (pCurr
== NULL
) {
205 /* No footnote blocks */
207 } else if (lCharsToGo
== 0) {
208 /* Move the integral number of footnote blocks */
209 pFootAnchor
= pCurr
->pNext
;
212 /* Split the part-text block, part-footnote block */
213 DBG_DEC(lBytesTooFar
);
214 fail(lBytesTooFar
<= 0);
215 pFootAnchor
= xmalloc(sizeof(list_mem_type
));
216 DBG_HEX(pCurr
->tInfo
.ulFileOffset
);
217 pFootAnchor
->tInfo
.ulFileOffset
=
218 pCurr
->tInfo
.ulFileOffset
+
219 pCurr
->tInfo
.ulLength
-
221 DBG_HEX(pFootAnchor
->tInfo
.ulFileOffset
);
222 DBG_HEX(pCurr
->tInfo
.ulCharPos
);
223 pFootAnchor
->tInfo
.ulCharPos
=
224 pCurr
->tInfo
.ulCharPos
+
225 pCurr
->tInfo
.ulLength
-
227 DBG_HEX(pFootAnchor
->tInfo
.ulCharPos
);
228 pFootAnchor
->tInfo
.ulLength
= (ULONG
)lBytesTooFar
;
229 pCurr
->tInfo
.ulLength
-= lBytesTooFar
;
230 pFootAnchor
->tInfo
.bUsesUnicode
= pCurr
->tInfo
.bUsesUnicode
;
231 /* Move the integral number of footnote blocks */
232 pFootAnchor
->pNext
= pCurr
->pNext
;
235 /* Footnote block list */
237 lCharsToGo
= (long)ulFootnoteLen
;
239 if (ulFootnoteLen
!= 0) {
240 DBG_MSG("Footnote block list");
241 DBG_DEC(ulFootnoteLen
);
242 for (pCurr
= pFootAnchor
;
244 pCurr
= pCurr
->pNext
) {
245 DBG_DEC(pCurr
->tInfo
.ulLength
);
246 fail(pCurr
->tInfo
.ulLength
== 0);
247 if (pCurr
->tInfo
.bUsesUnicode
) {
248 fail(odd(pCurr
->tInfo
.ulLength
));
249 lCharsToGo
-= pCurr
->tInfo
.ulLength
/ 2;
250 if (lCharsToGo
< 0) {
251 lBytesTooFar
= -2 * lCharsToGo
;
254 lCharsToGo
-= pCurr
->tInfo
.ulLength
;
255 if (lCharsToGo
< 0) {
256 lBytesTooFar
= -lCharsToGo
;
259 if (lCharsToGo
<= 0) {
265 if (ulFootnoteLen
== 0) {
266 /* Empty footnote list */
267 pUnused1Anchor
= pFootAnchor
;
269 } else if (pCurr
== NULL
) {
270 /* No unused1 blocks */
271 pUnused1Anchor
= NULL
;
272 } else if (lCharsToGo
== 0) {
273 /* Move the integral number of unused1-list blocks */
274 pUnused1Anchor
= pCurr
->pNext
;
277 /* Split the part-footnote block, part-unused1 block */
278 DBG_DEC(lBytesTooFar
);
279 fail(lBytesTooFar
<= 0);
280 pUnused1Anchor
= xmalloc(sizeof(list_mem_type
));
281 DBG_HEX(pCurr
->tInfo
.ulFileOffset
);
282 pUnused1Anchor
->tInfo
.ulFileOffset
=
283 pCurr
->tInfo
.ulFileOffset
+
284 pCurr
->tInfo
.ulLength
-
286 DBG_HEX(pUnused1Anchor
->tInfo
.ulFileOffset
);
287 DBG_HEX(pCurr
->tInfo
.ulCharPos
);
288 pUnused1Anchor
->tInfo
.ulCharPos
=
289 pCurr
->tInfo
.ulCharPos
+
290 pCurr
->tInfo
.ulLength
-
292 DBG_HEX(pUnused1Anchor
->tInfo
.ulCharPos
);
293 pUnused1Anchor
->tInfo
.ulLength
= (ULONG
)lBytesTooFar
;
294 pCurr
->tInfo
.ulLength
-= lBytesTooFar
;
295 pUnused1Anchor
->tInfo
.bUsesUnicode
=
296 pCurr
->tInfo
.bUsesUnicode
;
297 /* Move the integral number of unused1 blocks */
298 pUnused1Anchor
->pNext
= pCurr
->pNext
;
301 /* Unused1 block list */
303 lCharsToGo
= (long)ulUnused1Len
;
305 if (ulUnused1Len
!= 0) {
306 DBG_MSG("Unused1 block list");
307 DBG_DEC(ulUnused1Len
);
308 for (pCurr
= pUnused1Anchor
;
310 pCurr
= pCurr
->pNext
) {
311 DBG_DEC(pCurr
->tInfo
.ulLength
);
312 fail(pCurr
->tInfo
.ulLength
== 0);
313 if (pCurr
->tInfo
.bUsesUnicode
) {
314 fail(odd(pCurr
->tInfo
.ulLength
));
315 lCharsToGo
-= pCurr
->tInfo
.ulLength
/ 2;
316 if (lCharsToGo
< 0) {
317 lBytesTooFar
= -2 * lCharsToGo
;
320 lCharsToGo
-= pCurr
->tInfo
.ulLength
;
321 if (lCharsToGo
< 0) {
322 lBytesTooFar
= -lCharsToGo
;
325 if (lCharsToGo
<= 0) {
331 if (ulUnused1Len
== 0) {
332 /* Empty unused1 list */
333 pEndAnchor
= pUnused1Anchor
;
334 pUnused1Anchor
= NULL
;
335 } else if (pCurr
== NULL
) {
336 /* No endnote blocks */
338 } else if (lCharsToGo
== 0) {
339 /* Move the intergral number of endnote blocks */
340 pEndAnchor
= pCurr
->pNext
;
343 /* Split the part-unused1-list block, part-endnote block */
344 DBG_DEC(lBytesTooFar
);
345 fail(lBytesTooFar
<= 0);
346 pEndAnchor
= xmalloc(sizeof(list_mem_type
));
347 DBG_HEX(pCurr
->tInfo
.ulFileOffset
);
348 pEndAnchor
->tInfo
.ulFileOffset
=
349 pCurr
->tInfo
.ulFileOffset
+
350 pCurr
->tInfo
.ulLength
-
352 DBG_HEX(pEndAnchor
->tInfo
.ulFileOffset
);
353 DBG_HEX(pCurr
->tInfo
.ulCharPos
);
354 pEndAnchor
->tInfo
.ulCharPos
=
355 pCurr
->tInfo
.ulCharPos
+
356 pCurr
->tInfo
.ulLength
-
358 DBG_HEX(pEndAnchor
->tInfo
.ulCharPos
);
359 pEndAnchor
->tInfo
.ulLength
= (ULONG
)lBytesTooFar
;
360 pCurr
->tInfo
.ulLength
-= lBytesTooFar
;
361 pEndAnchor
->tInfo
.bUsesUnicode
= pCurr
->tInfo
.bUsesUnicode
;
362 /* Move the integral number of endnote blocks */
363 pEndAnchor
->pNext
= pCurr
->pNext
;
366 /* Endnote block list */
368 lCharsToGo
= (long)ulEndnoteLen
;
370 if (ulEndnoteLen
!= 0) {
371 DBG_MSG("Endnote block list");
372 DBG_DEC(ulEndnoteLen
);
373 for (pCurr
= pEndAnchor
;
375 pCurr
= pCurr
->pNext
) {
376 DBG_DEC(pCurr
->tInfo
.ulLength
);
377 fail(pCurr
->tInfo
.ulLength
== 0);
378 if (pCurr
->tInfo
.bUsesUnicode
) {
379 fail(odd(pCurr
->tInfo
.ulLength
));
380 lCharsToGo
-= pCurr
->tInfo
.ulLength
/ 2;
381 if (lCharsToGo
<= 0) {
382 lBytesTooFar
= -2 * lCharsToGo
;
385 lCharsToGo
-= pCurr
->tInfo
.ulLength
;
386 if (lCharsToGo
<= 0) {
387 lBytesTooFar
= -lCharsToGo
;
390 if (lCharsToGo
<= 0) {
396 if (ulEndnoteLen
== 0) {
397 /* Empty endnote list */
398 pUnused2Anchor
= pEndAnchor
;
400 } else if (pCurr
== NULL
) {
401 /* No unused2 blocks */
402 pUnused2Anchor
= NULL
;
403 } else if (lCharsToGo
== 0) {
404 /* Move the intergral number of unused2 blocks */
405 pUnused2Anchor
= pCurr
->pNext
;
408 /* Split the part-endnote block, part-unused2 block */
409 DBG_DEC(lBytesTooFar
);
410 fail(lBytesTooFar
<= 0);
411 pUnused2Anchor
= xmalloc(sizeof(list_mem_type
));
412 DBG_HEX(pCurr
->tInfo
.ulFileOffset
);
413 pUnused2Anchor
->tInfo
.ulFileOffset
=
414 pCurr
->tInfo
.ulFileOffset
+
415 pCurr
->tInfo
.ulLength
-
417 DBG_HEX(pUnused2Anchor
->tInfo
.ulFileOffset
);
418 DBG_HEX(pCurr
->tInfo
.ulCharPos
);
419 pUnused2Anchor
->tInfo
.ulCharPos
=
420 pCurr
->tInfo
.ulCharPos
+
421 pCurr
->tInfo
.ulLength
-
423 DBG_HEX(pUnused2Anchor
->tInfo
.ulCharPos
);
424 pUnused2Anchor
->tInfo
.ulLength
= (ULONG
)lBytesTooFar
;
425 pCurr
->tInfo
.ulLength
-= lBytesTooFar
;
426 pUnused2Anchor
->tInfo
.bUsesUnicode
=
427 pCurr
->tInfo
.bUsesUnicode
;
428 /* Move the integral number of unused2 blocks */
429 pUnused2Anchor
->pNext
= pCurr
->pNext
;
432 /* Unused2 block list */
434 lCharsToGo
= (long)ulUnused2Len
;
436 if (ulUnused2Len
!= 0) {
437 DBG_MSG("Unused2 block list");
438 DBG_DEC(ulUnused2Len
);
439 for (pCurr
= pUnused2Anchor
;
441 pCurr
= pCurr
->pNext
) {
442 DBG_DEC(pCurr
->tInfo
.ulLength
);
443 fail(pCurr
->tInfo
.ulLength
== 0);
444 if (pCurr
->tInfo
.bUsesUnicode
) {
445 fail(odd(pCurr
->tInfo
.ulLength
));
446 lCharsToGo
-= pCurr
->tInfo
.ulLength
/ 2;
447 if (lCharsToGo
< 0) {
448 lBytesTooFar
= -2 * lCharsToGo
;
451 lCharsToGo
-= pCurr
->tInfo
.ulLength
;
452 if (lCharsToGo
< 0) {
453 lBytesTooFar
= -lCharsToGo
;
456 if (lCharsToGo
<= 0) {
462 if (ulUnused2Len
== 0) {
463 /* Empty unused2 list */
464 pGarbageAnchor
= pUnused2Anchor
;
465 pUnused2Anchor
= NULL
;
466 } else if (pCurr
== NULL
) {
467 /* No garbage block list */
468 pGarbageAnchor
= NULL
;
469 } else if (lCharsToGo
== 0) {
470 /* Move the intergral number of garbage blocks */
471 pGarbageAnchor
= pCurr
->pNext
;
474 /* Reduce the part-unused2 block */
475 DBG_DEC(lBytesTooFar
);
476 fail(lBytesTooFar
<= 0);
477 pCurr
->tInfo
.ulLength
-= lBytesTooFar
;
478 /* Move the integral number of garbage blocks */
479 pGarbageAnchor
= pCurr
->pNext
;
482 /* Free the garbage block list, this should never be needed */
483 pCurr
= pGarbageAnchor
;
484 while (pCurr
!= NULL
) {
486 DBG_HEX(pCurr
->tInfo
.ulFileOffset
);
487 DBG_DEC(pCurr
->tInfo
.ulLength
);
488 pNext
= pCurr
->pNext
;
489 pCurr
= xfree(pCurr
);
494 /* Check the number of bytes in the block lists */
496 for (pCurr
= pTextAnchor
; pCurr
!= NULL
; pCurr
= pCurr
->pNext
) {
497 NO_DBG_HEX(pCurr
->tInfo
.ulFileOffset
);
498 NO_DBG_HEX(pCurr
->tInfo
.ulCharPos
);
499 NO_DBG_DEC(pCurr
->tInfo
.ulLength
);
500 fail(pCurr
->tInfo
.ulLength
== 0);
501 if (pCurr
->tInfo
.bUsesUnicode
) {
502 fail(odd(pCurr
->tInfo
.ulLength
));
503 ulTotal
+= pCurr
->tInfo
.ulLength
/ 2;
505 ulTotal
+= pCurr
->tInfo
.ulLength
;
509 if (ulTotal
!= ulTextLen
) {
511 werr(1, "Software error (Text)");
514 for (pCurr
= pFootAnchor
; pCurr
!= NULL
; pCurr
= pCurr
->pNext
) {
515 DBG_HEX(pCurr
->tInfo
.ulFileOffset
);
516 NO_DBG_HEX(pCurr
->tInfo
.ulCharPos
);
517 DBG_DEC(pCurr
->tInfo
.ulLength
);
518 fail(pCurr
->tInfo
.ulLength
== 0);
519 if (pCurr
->tInfo
.bUsesUnicode
) {
520 fail(odd(pCurr
->tInfo
.ulLength
));
521 ulTotal
+= pCurr
->tInfo
.ulLength
/ 2;
523 ulTotal
+= pCurr
->tInfo
.ulLength
;
527 if (ulTotal
!= ulFootnoteLen
) {
528 DBG_DEC(ulFootnoteLen
);
529 werr(1, "Software error (Footnotes)");
532 for (pCurr
= pUnused1Anchor
; pCurr
!= NULL
; pCurr
= pCurr
->pNext
) {
533 DBG_HEX(pCurr
->tInfo
.ulFileOffset
);
534 NO_DBG_HEX(pCurr
->tInfo
.ulCharPos
);
535 DBG_DEC(pCurr
->tInfo
.ulLength
);
536 fail(pCurr
->tInfo
.ulLength
== 0);
537 if (pCurr
->tInfo
.bUsesUnicode
) {
538 fail(odd(pCurr
->tInfo
.ulLength
));
539 ulTotal
+= pCurr
->tInfo
.ulLength
/ 2;
541 ulTotal
+= pCurr
->tInfo
.ulLength
;
545 if (ulTotal
!= ulUnused1Len
) {
546 DBG_DEC(ulUnused1Len
);
547 werr(1, "Software error (Unused1-list)");
550 for (pCurr
= pEndAnchor
; pCurr
!= NULL
; pCurr
= pCurr
->pNext
) {
551 DBG_HEX(pCurr
->tInfo
.ulFileOffset
);
552 NO_DBG_HEX(pCurr
->tInfo
.ulCharPos
);
553 DBG_DEC(pCurr
->tInfo
.ulLength
);
554 fail(pCurr
->tInfo
.ulLength
== 0);
555 if (pCurr
->tInfo
.bUsesUnicode
) {
556 fail(odd(pCurr
->tInfo
.ulLength
));
557 ulTotal
+= pCurr
->tInfo
.ulLength
/ 2;
559 ulTotal
+= pCurr
->tInfo
.ulLength
;
563 if (ulTotal
!= ulEndnoteLen
) {
564 DBG_DEC(ulEndnoteLen
);
565 werr(1, "Software error (Endnotes)");
568 for (pCurr
= pUnused2Anchor
; pCurr
!= NULL
; pCurr
= pCurr
->pNext
) {
569 DBG_HEX(pCurr
->tInfo
.ulFileOffset
);
570 NO_DBG_HEX(pCurr
->tInfo
.ulCharPos
);
571 DBG_DEC(pCurr
->tInfo
.ulLength
);
572 fail(pCurr
->tInfo
.ulLength
== 0);
573 if (pCurr
->tInfo
.bUsesUnicode
) {
574 fail(odd(pCurr
->tInfo
.ulLength
));
575 ulTotal
+= pCurr
->tInfo
.ulLength
/ 2;
577 ulTotal
+= pCurr
->tInfo
.ulLength
;
581 if (ulTotal
!= ulUnused2Len
) {
582 DBG_DEC(ulUnused2Len
);
583 werr(1, "Software error (Unused2-list)");
591 * All blocks (except the last one) must have a length that
592 * is a multiple of the Big Block Size
595 apAnchors
[0] = pTextAnchor
;
596 apAnchors
[1] = pFootAnchor
;
597 apAnchors
[2] = pUnused1Anchor
;
598 apAnchors
[3] = pEndAnchor
;
599 apAnchors
[4] = pUnused2Anchor
;
601 for (iIndex
= 0; iIndex
< 5; iIndex
++) {
602 for (pCurr
= apAnchors
[iIndex
];
604 pCurr
= pCurr
->pNext
) {
605 if (pCurr
->pNext
!= NULL
&&
606 pCurr
->tInfo
.ulLength
% BIG_BLOCK_SIZE
!= 0) {
607 DBG_HEX(pCurr
->tInfo
.ulFileOffset
);
608 DBG_HEX(pCurr
->tInfo
.ulCharPos
);
609 DBG_DEC(pCurr
->tInfo
.ulLength
);
610 pCurr
->tInfo
.ulLength
/= BIG_BLOCK_SIZE
;
611 pCurr
->tInfo
.ulLength
++;
612 pCurr
->tInfo
.ulLength
*= BIG_BLOCK_SIZE
;
613 DBG_DEC(pCurr
->tInfo
.ulLength
);
617 } /* end of vSplitBlockList */
619 #if defined(__riscos)
621 * lGetDocumentLength - get the combined character length of the three lists
623 * returns: The total number of characters
626 ulGetDocumentLength(void)
628 list_mem_type
*apAnchors
[3];
629 list_mem_type
*pCurr
;
633 DBG_MSG("ulGetDocumentLength");
635 apAnchors
[0] = pTextAnchor
;
636 apAnchors
[1] = pFootAnchor
;
637 apAnchors
[2] = pEndAnchor
;
640 for (iIndex
= 0; iIndex
< 3; iIndex
++) {
641 for (pCurr
= apAnchors
[iIndex
];
643 pCurr
= pCurr
->pNext
) {
644 fail(pCurr
->tInfo
.ulLength
== 0);
645 if (pCurr
->tInfo
.bUsesUnicode
) {
646 fail(odd(pCurr
->tInfo
.ulLength
));
647 ulTotal
+= pCurr
->tInfo
.ulLength
/ 2;
649 ulTotal
+= pCurr
->tInfo
.ulLength
;
655 } /* end of ulGetDocumentLength */
656 #endif /* __riscos */
659 * usNextTextByte - get the next byte from the text block list
662 usNextTextByte(FILE *pFile
,
663 ULONG
*pulFileOffset
, ULONG
*pulCharPos
, USHORT
*pusPropMod
)
665 static ULONG ulBlockOffset
= 0;
666 static size_t tByteNext
= 0;
670 if (pTextBlockCurrent
== NULL
||
671 tByteNext
>= sizeof(aucBlock
) ||
672 ulBlockOffset
+ tByteNext
>= pTextBlockCurrent
->tInfo
.ulLength
) {
673 if (pTextBlockCurrent
== NULL
) {
674 /* First block, first part */
675 pTextBlockCurrent
= pTextAnchor
;
677 } else if (ulBlockOffset
+ sizeof(aucBlock
) <
678 pTextBlockCurrent
->tInfo
.ulLength
) {
679 /* Same block, next part */
680 ulBlockOffset
+= sizeof(aucBlock
);
682 /* Next block, first part */
683 pTextBlockCurrent
= pTextBlockCurrent
->pNext
;
686 if (pTextBlockCurrent
== NULL
) {
687 /* Past the last part of the last block */
691 (pTextBlockCurrent
->tInfo
.ulLength
- ulBlockOffset
);
692 if (tReadLen
> sizeof(aucBlock
)) {
693 tReadLen
= sizeof(aucBlock
);
695 ulReadOff
= pTextBlockCurrent
->tInfo
.ulFileOffset
+
697 if (!bReadBytes(aucBlock
, tReadLen
, ulReadOff
, pFile
)) {
702 if (pulFileOffset
!= NULL
) {
703 *pulFileOffset
= pTextBlockCurrent
->tInfo
.ulFileOffset
+
704 ulBlockOffset
+ tByteNext
;
706 if (pulCharPos
!= NULL
) {
707 *pulCharPos
= pTextBlockCurrent
->tInfo
.ulCharPos
+
708 ulBlockOffset
+ tByteNext
;
710 if (pusPropMod
!= NULL
) {
711 *pusPropMod
= pTextBlockCurrent
->tInfo
.usPropMod
;
713 return (USHORT
)aucBlock
[tByteNext
++];
714 } /* end of usNextTextByte */
717 * usNextFootByte - get the next byte from the footnote block list
720 usNextFootByte(FILE *pFile
,
721 ULONG
*pulFileOffset
, ULONG
*pulCharPos
, USHORT
*pusPropMod
)
723 static ULONG ulBlockOffset
= 0;
724 static size_t tByteNext
= 0;
728 if (pFootBlockCurrent
== NULL
||
729 tByteNext
>= sizeof(aucBlock
) ||
730 ulBlockOffset
+ tByteNext
>= pFootBlockCurrent
->tInfo
.ulLength
) {
731 if (pFootBlockCurrent
== NULL
) {
732 /* First block, first part */
733 pFootBlockCurrent
= pFootAnchor
;
735 } else if (ulBlockOffset
+ sizeof(aucBlock
) <
736 pFootBlockCurrent
->tInfo
.ulLength
) {
737 /* Same block, next part */
738 ulBlockOffset
+= sizeof(aucBlock
);
740 /* Next block, first part */
741 pFootBlockCurrent
= pFootBlockCurrent
->pNext
;
744 if (pFootBlockCurrent
== NULL
) {
745 /* Past the last part of the last block */
749 (pFootBlockCurrent
->tInfo
.ulLength
- ulBlockOffset
);
750 if (tReadLen
> sizeof(aucBlock
)) {
751 tReadLen
= sizeof(aucBlock
);
753 ulReadOff
= pFootBlockCurrent
->tInfo
.ulFileOffset
+
755 if (!bReadBytes(aucBlock
, tReadLen
, ulReadOff
, pFile
)) {
760 if (pulFileOffset
!= NULL
) {
761 *pulFileOffset
= pFootBlockCurrent
->tInfo
.ulFileOffset
+
762 ulBlockOffset
+ tByteNext
;
764 if (pulCharPos
!= NULL
) {
765 *pulCharPos
= pFootBlockCurrent
->tInfo
.ulCharPos
+
766 ulBlockOffset
+ tByteNext
;
768 if (pusPropMod
!= NULL
) {
769 *pusPropMod
= pFootBlockCurrent
->tInfo
.usPropMod
;
771 return (USHORT
)aucBlock
[tByteNext
++];
772 } /* end of usNextFootByte */
775 * usNextEndByte - get the next byte from the endnote block list
778 usNextEndByte(FILE *pFile
,
779 ULONG
*pulFileOffset
, ULONG
*pulCharPos
, USHORT
*pusPropMod
)
781 static ULONG ulBlockOffset
= 0;
782 static size_t tByteNext
= 0;
786 if (pEndBlockCurrent
== NULL
||
787 tByteNext
>= sizeof(aucBlock
) ||
788 ulBlockOffset
+ tByteNext
>= pEndBlockCurrent
->tInfo
.ulLength
) {
789 if (pEndBlockCurrent
== NULL
) {
790 /* First block, first part */
791 pEndBlockCurrent
= pEndAnchor
;
793 } else if (ulBlockOffset
+ sizeof(aucBlock
) <
794 pEndBlockCurrent
->tInfo
.ulLength
) {
795 /* Same block, next part */
796 ulBlockOffset
+= sizeof(aucBlock
);
798 /* Next block, first part */
799 pEndBlockCurrent
= pEndBlockCurrent
->pNext
;
802 if (pEndBlockCurrent
== NULL
) {
803 /* Past the last part of the last block */
807 (pEndBlockCurrent
->tInfo
.ulLength
- ulBlockOffset
);
808 if (tReadLen
> sizeof(aucBlock
)) {
809 tReadLen
= sizeof(aucBlock
);
811 ulReadOff
= pEndBlockCurrent
->tInfo
.ulFileOffset
+
813 if (!bReadBytes(aucBlock
, tReadLen
, ulReadOff
, pFile
)) {
818 if (pulFileOffset
!= NULL
) {
819 *pulFileOffset
= pEndBlockCurrent
->tInfo
.ulFileOffset
+
820 ulBlockOffset
+ tByteNext
;
822 if (pulCharPos
!= NULL
) {
823 *pulCharPos
= pEndBlockCurrent
->tInfo
.ulCharPos
+
824 ulBlockOffset
+ tByteNext
;
826 if (pusPropMod
!= NULL
) {
827 *pusPropMod
= pEndBlockCurrent
->tInfo
.usPropMod
;
829 return (USHORT
)aucBlock
[tByteNext
++];
830 } /* end of usNextEndByte */
833 * usNextTextChar - get the next character from the text block list
836 usNextTextChar(FILE *pFile
,
837 ULONG
*pulFileOffset
, ULONG
*pulCharPos
, USHORT
*pusPropMod
)
841 usLSB
= usNextTextByte(pFile
, pulFileOffset
, pulCharPos
, pusPropMod
);
842 if (usLSB
== (USHORT
)EOF
) {
845 if (pTextBlockCurrent
->tInfo
.bUsesUnicode
) {
846 usMSB
= usNextTextByte(pFile
, NULL
, NULL
, NULL
);
850 if (usMSB
== (USHORT
)EOF
) {
851 DBG_MSG("usNextTextChar: Unexpected EOF");
852 DBG_HEX_C(pulFileOffset
!= NULL
, *pulFileOffset
);
853 DBG_HEX_C(pulCharPos
!= NULL
, *pulCharPos
);
856 return (usMSB
<< 8) | usLSB
;
857 } /* end of usNextTextChar */
860 * usNextFootChar - get the next character from the footnote block list
863 usNextFootChar(FILE *pFile
,
864 ULONG
*pulFileOffset
, ULONG
*pulCharPos
, USHORT
*pusPropMod
)
868 usLSB
= usNextFootByte(pFile
, pulFileOffset
, pulCharPos
, pusPropMod
);
869 if (usLSB
== (USHORT
)EOF
) {
872 if (pFootBlockCurrent
->tInfo
.bUsesUnicode
) {
873 usMSB
= usNextFootByte(pFile
, NULL
, NULL
, NULL
);
877 if (usMSB
== (USHORT
)EOF
) {
878 DBG_MSG("usNextFootChar: Unexpected EOF");
879 DBG_HEX_C(pulFileOffset
!= NULL
, *pulFileOffset
);
880 DBG_HEX_C(pulCharPos
!= NULL
, *pulCharPos
);
883 return (usMSB
<< 8) | usLSB
;
884 } /* end of usNextFootChar */
887 * usNextEndChar - get the next character from the endnote block list
890 usNextEndChar(FILE *pFile
,
891 ULONG
*pulFileOffset
, ULONG
*pulCharPos
, USHORT
*pusPropMod
)
895 usLSB
= usNextEndByte(pFile
, pulFileOffset
, pulCharPos
, pusPropMod
);
896 if (usLSB
== (USHORT
)EOF
) {
899 if (pEndBlockCurrent
->tInfo
.bUsesUnicode
) {
900 usMSB
= usNextEndByte(pFile
, NULL
, NULL
, NULL
);
904 if (usMSB
== (USHORT
)EOF
) {
905 DBG_MSG("usNextEndChar: Unexpected EOF");
906 DBG_HEX_C(pulFileOffset
!= NULL
, *pulFileOffset
);
907 DBG_HEX_C(pulCharPos
!= NULL
, *pulCharPos
);
910 return (usMSB
<< 8) | usLSB
;
911 } /* end of usNextEndChar */
914 * usNextChar - get the next character from the given block list
917 usNextChar(FILE *pFile
, list_id_enum eListID
,
918 ULONG
*pulFileOffset
, ULONG
*pulCharPos
, USHORT
*pusPropMod
)
924 return usNextTextChar(pFile
,
925 pulFileOffset
, pulCharPos
, pusPropMod
);
927 return usNextFootChar(pFile
,
928 pulFileOffset
, pulCharPos
, pusPropMod
);
930 return usNextEndChar(pFile
,
931 pulFileOffset
, pulCharPos
, pusPropMod
);
933 if (pulFileOffset
!= NULL
) {
934 *pulFileOffset
= FC_INVALID
;
936 if (pulCharPos
!= NULL
) {
937 *pulCharPos
= CP_INVALID
;
939 if (pusPropMod
!= NULL
) {
940 *pusPropMod
= IGNORE_PROPMOD
;
944 } /* end of usNextChar */
947 * Translate a character position to an offset in the file.
948 * Logical to physical offset.
950 * Returns: FC_INVALID: in case of error
951 * otherwise: the computed file offset
954 ulCharPos2FileOffset(ULONG ulCharPos
)
956 list_mem_type
*apAnchors
[3];
957 list_mem_type
*pCurr
;
961 apAnchors
[0] = pTextAnchor
;
962 apAnchors
[1] = pFootAnchor
;
963 apAnchors
[2] = pEndAnchor
;
965 ulBestGuess
= FC_INVALID
; /* Best guess is "fileoffset not found" */
967 for (iIndex
= 0; iIndex
< 3; iIndex
++) {
968 for (pCurr
= apAnchors
[iIndex
];
970 pCurr
= pCurr
->pNext
) {
971 if (ulCharPos
== pCurr
->tInfo
.ulCharPos
+
972 pCurr
->tInfo
.ulLength
&&
973 pCurr
->pNext
!= NULL
) {
975 * The textoffset is one beyond this block,
976 * so we guess it's the first byte of the next
977 * block (if there is a next block)
979 ulBestGuess
= pCurr
->pNext
->tInfo
.ulFileOffset
;
982 if (ulCharPos
< pCurr
->tInfo
.ulCharPos
||
983 ulCharPos
>= pCurr
->tInfo
.ulCharPos
+
984 pCurr
->tInfo
.ulLength
) {
985 /* The textoffset is not in this block */
989 /* The textoffset is in the current block */
990 return pCurr
->tInfo
.ulFileOffset
+
991 ulCharPos
- pCurr
->tInfo
.ulCharPos
;
994 /* Passed beyond the end of the last list */
995 NO_DBG_HEX(ulCharPos
);
996 NO_DBG_HEX(ulBestGuess
);
998 } /* end of ulCharPos2FileOffset */
1001 * Get the sequence number beloning to the given file offset
1003 * Returns the sequence number
1006 ulGetSeqNumber(ULONG ulFileOffset
)
1008 list_mem_type
*pCurr
;
1011 if (ulFileOffset
== FC_INVALID
) {
1016 for (pCurr
= pTextAnchor
; pCurr
!= NULL
; pCurr
= pCurr
->pNext
) {
1017 if (ulFileOffset
>= pCurr
->tInfo
.ulFileOffset
&&
1018 ulFileOffset
< pCurr
->tInfo
.ulFileOffset
+
1019 pCurr
->tInfo
.ulLength
) {
1020 /* The file offset is within the current textblock */
1021 return ulSeq
+ ulFileOffset
- pCurr
->tInfo
.ulFileOffset
;
1023 ulSeq
+= pCurr
->tInfo
.ulLength
;
1026 } /* end of ulGetSeqNumber */