Imported from antiword-0.33.tar.gz.
[antiword.git] / blocklist.c
bloba938119d3e06bfb950a7f1c6d166f4271e847f06
1 /*
2 * blocklist.c
3 * Copyright (C) 1998-2002 A.J. van Os; Released under GPL
5 * Description:
6 * Build, read and destroy a list of Word text blocks
7 */
9 #include <stdlib.h>
10 #include "antiword.h"
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;
20 } list_mem_type;
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;
36 /* Last block read */
37 static UCHAR aucBlock[BIG_BLOCK_SIZE];
41 * vDestroyTextBlockList - destroy the text block list
43 void
44 vDestroyTextBlockList(void)
46 list_mem_type *apAnchor[5];
47 list_mem_type *pCurr, *pNext;
48 int iIndex;
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) {
61 pNext = pCurr->pNext;
62 pCurr = xfree(pCurr);
63 pCurr = pNext;
66 /* Show that there are no lists any more */
67 pTextAnchor = NULL;
68 pFootAnchor = NULL;
69 pUnused1Anchor = NULL;
70 pEndAnchor = NULL;
71 pUnused2Anchor = NULL;
72 /* Reset all the controle variables */
73 pBlockLast = NULL;
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
84 BOOL
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");
107 return FALSE;
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;
122 return TRUE;
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;
131 } else {
132 fail(pBlockLast == NULL);
133 pBlockLast->pNext = pListMember;
135 pBlockLast = pListMember;
136 return TRUE;
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.
146 * NOTE:
147 * The various l*Len input parameters are given in characters, but the
148 * length of the blocks are in bytes.
150 void
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;
157 int iIndex;
158 #if defined(DEBUG)
159 ULONG ulTotal;
160 #endif /* DEBUG */
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 */
171 pCurr = NULL;
172 lCharsToGo = (long)ulTextLen;
173 lBytesTooFar = -1;
174 if (ulTextLen != 0) {
175 DBG_MSG("Text block list");
176 DBG_DEC(ulTextLen);
177 for (pCurr = pTextAnchor;
178 pCurr != NULL;
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;
188 } else {
189 lCharsToGo -= pCurr->tInfo.ulLength;
190 if (lCharsToGo < 0) {
191 lBytesTooFar = -lCharsToGo;
194 if (lCharsToGo <= 0) {
195 break;
199 /* Split the list */
200 if (ulTextLen == 0) {
201 /* Empty text blocks list */
202 pFootAnchor = pTextAnchor;
203 pTextAnchor = NULL;
204 } else if (pCurr == NULL) {
205 /* No footnote blocks */
206 pFootAnchor = NULL;
207 } else if (lCharsToGo == 0) {
208 /* Move the integral number of footnote blocks */
209 pFootAnchor = pCurr->pNext;
210 pCurr->pNext = NULL;
211 } else {
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 -
220 lBytesTooFar;
221 DBG_HEX(pFootAnchor->tInfo.ulFileOffset);
222 DBG_HEX(pCurr->tInfo.ulCharPos);
223 pFootAnchor->tInfo.ulCharPos =
224 pCurr->tInfo.ulCharPos +
225 pCurr->tInfo.ulLength -
226 lBytesTooFar;
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;
233 pCurr->pNext = NULL;
235 /* Footnote block list */
236 pCurr = NULL;
237 lCharsToGo = (long)ulFootnoteLen;
238 lBytesTooFar = -1;
239 if (ulFootnoteLen != 0) {
240 DBG_MSG("Footnote block list");
241 DBG_DEC(ulFootnoteLen);
242 for (pCurr = pFootAnchor;
243 pCurr != NULL;
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;
253 } else {
254 lCharsToGo -= pCurr->tInfo.ulLength;
255 if (lCharsToGo < 0) {
256 lBytesTooFar = -lCharsToGo;
259 if (lCharsToGo <= 0) {
260 break;
264 /* Split the list */
265 if (ulFootnoteLen == 0) {
266 /* Empty footnote list */
267 pUnused1Anchor = pFootAnchor;
268 pFootAnchor = NULL;
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;
275 pCurr->pNext = NULL;
276 } else {
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 -
285 lBytesTooFar;
286 DBG_HEX(pUnused1Anchor->tInfo.ulFileOffset);
287 DBG_HEX(pCurr->tInfo.ulCharPos);
288 pUnused1Anchor->tInfo.ulCharPos =
289 pCurr->tInfo.ulCharPos +
290 pCurr->tInfo.ulLength -
291 lBytesTooFar;
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;
299 pCurr->pNext = NULL;
301 /* Unused1 block list */
302 pCurr = NULL;
303 lCharsToGo = (long)ulUnused1Len;
304 lBytesTooFar = -1;
305 if (ulUnused1Len != 0) {
306 DBG_MSG("Unused1 block list");
307 DBG_DEC(ulUnused1Len);
308 for (pCurr = pUnused1Anchor;
309 pCurr != NULL;
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;
319 } else {
320 lCharsToGo -= pCurr->tInfo.ulLength;
321 if (lCharsToGo < 0) {
322 lBytesTooFar = -lCharsToGo;
325 if (lCharsToGo <= 0) {
326 break;
330 /* Split the list */
331 if (ulUnused1Len == 0) {
332 /* Empty unused1 list */
333 pEndAnchor = pUnused1Anchor;
334 pUnused1Anchor = NULL;
335 } else if (pCurr == NULL) {
336 /* No endnote blocks */
337 pEndAnchor = NULL;
338 } else if (lCharsToGo == 0) {
339 /* Move the intergral number of endnote blocks */
340 pEndAnchor = pCurr->pNext;
341 pCurr->pNext = NULL;
342 } else {
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 -
351 lBytesTooFar;
352 DBG_HEX(pEndAnchor->tInfo.ulFileOffset);
353 DBG_HEX(pCurr->tInfo.ulCharPos);
354 pEndAnchor->tInfo.ulCharPos =
355 pCurr->tInfo.ulCharPos +
356 pCurr->tInfo.ulLength -
357 lBytesTooFar;
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;
364 pCurr->pNext = NULL;
366 /* Endnote block list */
367 pCurr = NULL;
368 lCharsToGo = (long)ulEndnoteLen;
369 lBytesTooFar = -1;
370 if (ulEndnoteLen != 0) {
371 DBG_MSG("Endnote block list");
372 DBG_DEC(ulEndnoteLen);
373 for (pCurr = pEndAnchor;
374 pCurr != NULL;
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;
384 } else {
385 lCharsToGo -= pCurr->tInfo.ulLength;
386 if (lCharsToGo <= 0) {
387 lBytesTooFar = -lCharsToGo;
390 if (lCharsToGo <= 0) {
391 break;
395 /* Split the list */
396 if (ulEndnoteLen == 0) {
397 /* Empty endnote list */
398 pUnused2Anchor = pEndAnchor;
399 pEndAnchor = NULL;
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;
406 pCurr->pNext = NULL;
407 } else {
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 -
416 lBytesTooFar;
417 DBG_HEX(pUnused2Anchor->tInfo.ulFileOffset);
418 DBG_HEX(pCurr->tInfo.ulCharPos);
419 pUnused2Anchor->tInfo.ulCharPos =
420 pCurr->tInfo.ulCharPos +
421 pCurr->tInfo.ulLength -
422 lBytesTooFar;
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;
430 pCurr->pNext = NULL;
432 /* Unused2 block list */
433 pCurr = NULL;
434 lCharsToGo = (long)ulUnused2Len;
435 lBytesTooFar = -1;
436 if (ulUnused2Len != 0) {
437 DBG_MSG("Unused2 block list");
438 DBG_DEC(ulUnused2Len);
439 for (pCurr = pUnused2Anchor;
440 pCurr != NULL;
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;
450 } else {
451 lCharsToGo -= pCurr->tInfo.ulLength;
452 if (lCharsToGo < 0) {
453 lBytesTooFar = -lCharsToGo;
456 if (lCharsToGo <= 0) {
457 break;
461 /* Split the list */
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;
472 pCurr->pNext = NULL;
473 } else {
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;
480 pCurr->pNext = NULL;
482 /* Free the garbage block list, this should never be needed */
483 pCurr = pGarbageAnchor;
484 while (pCurr != NULL) {
485 DBG_FIXME();
486 DBG_HEX(pCurr->tInfo.ulFileOffset);
487 DBG_DEC(pCurr->tInfo.ulLength);
488 pNext = pCurr->pNext;
489 pCurr = xfree(pCurr);
490 pCurr = pNext;
493 #if defined(DEBUG)
494 /* Check the number of bytes in the block lists */
495 ulTotal = 0;
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;
504 } else {
505 ulTotal += pCurr->tInfo.ulLength;
508 DBG_DEC(ulTotal);
509 if (ulTotal != ulTextLen) {
510 DBG_DEC(ulTextLen);
511 werr(1, "Software error (Text)");
513 ulTotal = 0;
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;
522 } else {
523 ulTotal += pCurr->tInfo.ulLength;
526 DBG_DEC(ulTotal);
527 if (ulTotal != ulFootnoteLen) {
528 DBG_DEC(ulFootnoteLen);
529 werr(1, "Software error (Footnotes)");
531 ulTotal = 0;
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;
540 } else {
541 ulTotal += pCurr->tInfo.ulLength;
544 DBG_DEC(ulTotal);
545 if (ulTotal != ulUnused1Len) {
546 DBG_DEC(ulUnused1Len);
547 werr(1, "Software error (Unused1-list)");
549 ulTotal = 0;
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;
558 } else {
559 ulTotal += pCurr->tInfo.ulLength;
562 DBG_DEC(ulTotal);
563 if (ulTotal != ulEndnoteLen) {
564 DBG_DEC(ulEndnoteLen);
565 werr(1, "Software error (Endnotes)");
567 ulTotal = 0;
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;
576 } else {
577 ulTotal += pCurr->tInfo.ulLength;
580 DBG_DEC(ulTotal);
581 if (ulTotal != ulUnused2Len) {
582 DBG_DEC(ulUnused2Len);
583 werr(1, "Software error (Unused2-list)");
585 #endif /* DEBUG */
587 if (!bMustExtend) {
588 return;
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];
603 pCurr != NULL;
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
625 ULONG
626 ulGetDocumentLength(void)
628 list_mem_type *apAnchors[3];
629 list_mem_type *pCurr;
630 long ulTotal;
631 int iIndex;
633 DBG_MSG("ulGetDocumentLength");
635 apAnchors[0] = pTextAnchor;
636 apAnchors[1] = pFootAnchor;
637 apAnchors[2] = pEndAnchor;
639 ulTotal = 0;
640 for (iIndex = 0; iIndex < 3; iIndex++) {
641 for (pCurr = apAnchors[iIndex];
642 pCurr != NULL;
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;
648 } else {
649 ulTotal += pCurr->tInfo.ulLength;
653 DBG_DEC(ulTotal);
654 return ulTotal;
655 } /* end of ulGetDocumentLength */
656 #endif /* __riscos */
659 * usNextTextByte - get the next byte from the text block list
661 static USHORT
662 usNextTextByte(FILE *pFile,
663 ULONG *pulFileOffset, ULONG *pulCharPos, USHORT *pusPropMod)
665 static ULONG ulBlockOffset = 0;
666 static size_t tByteNext = 0;
667 ULONG ulReadOff;
668 size_t tReadLen;
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;
676 ulBlockOffset = 0;
677 } else if (ulBlockOffset + sizeof(aucBlock) <
678 pTextBlockCurrent->tInfo.ulLength) {
679 /* Same block, next part */
680 ulBlockOffset += sizeof(aucBlock);
681 } else {
682 /* Next block, first part */
683 pTextBlockCurrent = pTextBlockCurrent->pNext;
684 ulBlockOffset = 0;
686 if (pTextBlockCurrent == NULL) {
687 /* Past the last part of the last block */
688 return (USHORT)EOF;
690 tReadLen = (size_t)
691 (pTextBlockCurrent->tInfo.ulLength - ulBlockOffset);
692 if (tReadLen > sizeof(aucBlock)) {
693 tReadLen = sizeof(aucBlock);
695 ulReadOff = pTextBlockCurrent->tInfo.ulFileOffset +
696 ulBlockOffset;
697 if (!bReadBytes(aucBlock, tReadLen, ulReadOff, pFile)) {
698 return (USHORT)EOF;
700 tByteNext = 0;
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
719 static USHORT
720 usNextFootByte(FILE *pFile,
721 ULONG *pulFileOffset, ULONG *pulCharPos, USHORT *pusPropMod)
723 static ULONG ulBlockOffset = 0;
724 static size_t tByteNext = 0;
725 ULONG ulReadOff;
726 size_t tReadLen;
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;
734 ulBlockOffset = 0;
735 } else if (ulBlockOffset + sizeof(aucBlock) <
736 pFootBlockCurrent->tInfo.ulLength) {
737 /* Same block, next part */
738 ulBlockOffset += sizeof(aucBlock);
739 } else {
740 /* Next block, first part */
741 pFootBlockCurrent = pFootBlockCurrent->pNext;
742 ulBlockOffset = 0;
744 if (pFootBlockCurrent == NULL) {
745 /* Past the last part of the last block */
746 return (USHORT)EOF;
748 tReadLen = (size_t)
749 (pFootBlockCurrent->tInfo.ulLength - ulBlockOffset);
750 if (tReadLen > sizeof(aucBlock)) {
751 tReadLen = sizeof(aucBlock);
753 ulReadOff = pFootBlockCurrent->tInfo.ulFileOffset +
754 ulBlockOffset;
755 if (!bReadBytes(aucBlock, tReadLen, ulReadOff, pFile)) {
756 return (USHORT)EOF;
758 tByteNext = 0;
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
777 static USHORT
778 usNextEndByte(FILE *pFile,
779 ULONG *pulFileOffset, ULONG *pulCharPos, USHORT *pusPropMod)
781 static ULONG ulBlockOffset = 0;
782 static size_t tByteNext = 0;
783 ULONG ulReadOff;
784 size_t tReadLen;
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;
792 ulBlockOffset = 0;
793 } else if (ulBlockOffset + sizeof(aucBlock) <
794 pEndBlockCurrent->tInfo.ulLength) {
795 /* Same block, next part */
796 ulBlockOffset += sizeof(aucBlock);
797 } else {
798 /* Next block, first part */
799 pEndBlockCurrent = pEndBlockCurrent->pNext;
800 ulBlockOffset = 0;
802 if (pEndBlockCurrent == NULL) {
803 /* Past the last part of the last block */
804 return (USHORT)EOF;
806 tReadLen = (size_t)
807 (pEndBlockCurrent->tInfo.ulLength - ulBlockOffset);
808 if (tReadLen > sizeof(aucBlock)) {
809 tReadLen = sizeof(aucBlock);
811 ulReadOff = pEndBlockCurrent->tInfo.ulFileOffset +
812 ulBlockOffset;
813 if (!bReadBytes(aucBlock, tReadLen, ulReadOff, pFile)) {
814 return (USHORT)EOF;
816 tByteNext = 0;
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
835 static USHORT
836 usNextTextChar(FILE *pFile,
837 ULONG *pulFileOffset, ULONG *pulCharPos, USHORT *pusPropMod)
839 USHORT usLSB, usMSB;
841 usLSB = usNextTextByte(pFile, pulFileOffset, pulCharPos, pusPropMod);
842 if (usLSB == (USHORT)EOF) {
843 return (USHORT)EOF;
845 if (pTextBlockCurrent->tInfo.bUsesUnicode) {
846 usMSB = usNextTextByte(pFile, NULL, NULL, NULL);
847 } else {
848 usMSB = 0x00;
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);
854 return (USHORT)EOF;
856 return (usMSB << 8) | usLSB;
857 } /* end of usNextTextChar */
860 * usNextFootChar - get the next character from the footnote block list
862 static USHORT
863 usNextFootChar(FILE *pFile,
864 ULONG *pulFileOffset, ULONG *pulCharPos, USHORT *pusPropMod)
866 USHORT usLSB, usMSB;
868 usLSB = usNextFootByte(pFile, pulFileOffset, pulCharPos, pusPropMod);
869 if (usLSB == (USHORT)EOF) {
870 return (USHORT)EOF;
872 if (pFootBlockCurrent->tInfo.bUsesUnicode) {
873 usMSB = usNextFootByte(pFile, NULL, NULL, NULL);
874 } else {
875 usMSB = 0x00;
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);
881 return (USHORT)EOF;
883 return (usMSB << 8) | usLSB;
884 } /* end of usNextFootChar */
887 * usNextEndChar - get the next character from the endnote block list
889 static USHORT
890 usNextEndChar(FILE *pFile,
891 ULONG *pulFileOffset, ULONG *pulCharPos, USHORT *pusPropMod)
893 USHORT usLSB, usMSB;
895 usLSB = usNextEndByte(pFile, pulFileOffset, pulCharPos, pusPropMod);
896 if (usLSB == (USHORT)EOF) {
897 return (USHORT)EOF;
899 if (pEndBlockCurrent->tInfo.bUsesUnicode) {
900 usMSB = usNextEndByte(pFile, NULL, NULL, NULL);
901 } else {
902 usMSB = 0x00;
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);
908 return (USHORT)EOF;
910 return (usMSB << 8) | usLSB;
911 } /* end of usNextEndChar */
914 * usNextChar - get the next character from the given block list
916 USHORT
917 usNextChar(FILE *pFile, list_id_enum eListID,
918 ULONG *pulFileOffset, ULONG *pulCharPos, USHORT *pusPropMod)
920 fail(pFile == NULL);
922 switch (eListID) {
923 case text_list:
924 return usNextTextChar(pFile,
925 pulFileOffset, pulCharPos, pusPropMod);
926 case footnote_list:
927 return usNextFootChar(pFile,
928 pulFileOffset, pulCharPos, pusPropMod);
929 case endnote_list:
930 return usNextEndChar(pFile,
931 pulFileOffset, pulCharPos, pusPropMod);
932 default:
933 if (pulFileOffset != NULL) {
934 *pulFileOffset = FC_INVALID;
936 if (pulCharPos != NULL) {
937 *pulCharPos = CP_INVALID;
939 if (pusPropMod != NULL) {
940 *pusPropMod = IGNORE_PROPMOD;
942 return (USHORT)EOF;
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
953 ULONG
954 ulCharPos2FileOffset(ULONG ulCharPos)
956 list_mem_type *apAnchors[3];
957 list_mem_type *pCurr;
958 ULONG ulBestGuess;
959 int iIndex;
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];
969 pCurr != NULL;
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 */
986 continue;
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);
997 return ulBestGuess;
998 } /* end of ulCharPos2FileOffset */
1001 * Get the sequence number beloning to the given file offset
1003 * Returns the sequence number
1005 ULONG
1006 ulGetSeqNumber(ULONG ulFileOffset)
1008 list_mem_type *pCurr;
1009 ULONG ulSeq;
1011 if (ulFileOffset == FC_INVALID) {
1012 return FC_INVALID;
1015 ulSeq = 0;
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;
1025 return FC_INVALID;
1026 } /* end of ulGetSeqNumber */