1 /* wvWare
2 * Copyright (C) Caolan McNamara, Dom Lachowicz, and others
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17 * 02111-1307, USA.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include "wv.h"
27 #include "wvinternal.h"
28
29 /*
30 how this works,
31 we seek to the beginning of the text, we loop for a count of charaters that is stored in the fib.
32
33 the piecetable divides the text up into various sections, we keep track of our location vs
34 the next entry in that table, when we reach that location, we seek to the position that
35 the table tells us to go.
36
37 there are special cases for coming to the end of a section, and for the beginning and ends of
38 pages. for the purposes of headers and footers etc.
39 */
40 void
wvDecodeSimple(wvParseStruct * ps,subdocument whichdoc)41 wvDecodeSimple (wvParseStruct * ps, subdocument whichdoc)
42 {
43 PAPX_FKP para_fkp;
44 CHPX_FKP char_fkp;
45 PAP apap;
46 CHP achp;
47 U32 piececount = 0, i, j = 0, spiece;
48 U32 beginfc, endfc;
49 U32 stream_size;
50 U32 begincp, endcp;
51 int ichartype;
52 U8 chartype;
53 U16 eachchar;
54 U32 para_fcFirst, para_fcLim = 0xffffffff;
55 U32 dummy, nextpara_fcLim = 0xffffffff;
56 U32 char_fcFirst, char_fcLim = 0xffffffff;
57 U32 section_fcFirst, section_fcLim = 0xffffffff;
58 U32 comment_cpFirst = 0xffffffffL, comment_cpLim = 0xffffffffL;
59 BTE *btePapx, *bteChpx;
60 U32 *posPapx, *posChpx;
61 U32 para_intervals, char_intervals, section_intervals, atrd_intervals;
62 int para_pendingclose = 0, char_pendingclose = 0, section_pendingclose =
63 0, comment_pendingclose = 0;
64 int para_dirty = 0, char_dirty = 0, section_dirty = 0;
65 SED *sed;
66 SEP sep;
67 U32 *posSedx;
68 ATRD *atrd, *catrd = NULL;
69 U32 *posAtrd;
70 STTBF grpXstAtnOwners, SttbfAtnbkmk;
71 BKF *bkf;
72 U32 *posBKF;
73 U32 bkf_intervals;
74 BKL *bkl;
75 U32 *posBKL;
76 U32 bkl_intervals;
77 FTXBXS *ftxbx;
78 U32 *txbxTxt;
79 U32 txbxTxt_intervals;
80 BKD *bkd;
81 U32 *posBKD;
82 U32 bkd_intervals;
83 wvVersion ver;
84
85 external_wvReleasePAPX_FKP ();
86 external_wvReleaseCHPX_FKP ();
87
88 ver = wvQuerySupported (&ps->fib, NULL);
89
90
91 /*
92 despite what some parts of the spec might have you believe you still need to
93 get the piecetable from even simple files, some simple files can have 8bit
94 chars in one part, and 16bit chars in another, so you have to watch out for
95 that
96 */
97 wvGetCLX (ver, &ps->clx, ps->fib.fcClx, (U32) ps->fib.lcbClx,
98 (U8) ps->fib.fExtChar, ps->tablefd);
99 /* for word 6 and just in case */
100 if (ps->clx.nopcd == 0)
101 wvBuildCLXForSimple6 (&ps->clx, &ps->fib);
102
103 para_fcFirst = char_fcFirst = section_fcFirst = wvGetBeginFC (ps, whichdoc);
104 /*we will need the stylesheet to do anything useful with layout and look */
105 wvGetSTSH (&ps->stsh, ps->fib.fcStshf, ps->fib.lcbStshf, ps->tablefd);
106
107 /*dop */
108 wvGetDOP (ver, &ps->dop, ps->fib.fcDop, ps->fib.lcbDop, ps->tablefd);
109 wvTrace (("tabstops are every %d twips\n", ps->dop.dxaTab));
110
111 /*textbox information */
112 wvGetFTXBXS_PLCF (&ftxbx, &txbxTxt, &txbxTxt_intervals,
113 ps->fib.fcPlcftxbxTxt, ps->fib.lcbPlcftxbxTxt,
114 ps->tablefd);
115 wvGetBKD_PLCF (&bkd, &posBKD, &bkd_intervals, ps->fib.fcPlcftxbxBkd,
116 ps->fib.lcbPlcftxbxBkd, ps->tablefd);
117
118
119 /* this mountain of informatio is just to get comments organized */
120 wvGetATRD_PLCF (&atrd, &posAtrd, &atrd_intervals, ps->fib.fcPlcfandRef,
121 ps->fib.lcbPlcfandRef, ps->tablefd);
122 wvGetGrpXst (&grpXstAtnOwners, ps->fib.fcGrpXstAtnOwners,
123 ps->fib.lcbGrpXstAtnOwners, ps->tablefd);
124 wvTrace (
125 ("offset is %x, len is %d\n", ps->fib.fcSttbfAtnbkmk,
126 ps->fib.lcbSttbfAtnbkmk));
127 wvGetSTTBF (&SttbfAtnbkmk, ps->fib.fcSttbfAtnbkmk,
128 ps->fib.lcbSttbfAtnbkmk, ps->tablefd);
129 wvGetBKF_PLCF (&bkf, &posBKF, &bkf_intervals, ps->fib.fcPlcfAtnbkf,
130 ps->fib.lcbPlcfAtnbkf, ps->tablefd);
131 wvGetBKL_PLCF (&bkl, &posBKL, &bkl_intervals, ps->fib.fcPlcfAtnbkl,
132 ps->fib.lcbPlcfAtnbkl,ps->fib.fcPlcfAtnbkf, ps->fib.lcbPlcfAtnbkf,
133 ps->tablefd);
134
135
136 /* get font list */
137 if ((ver == WORD6)
138 || (ver == WORD7))
139 wvGetFFN_STTBF6 (&ps->fonts, ps->fib.fcSttbfffn, ps->fib.lcbSttbfffn,
140 ps->tablefd);
141 else
142 wvGetFFN_STTBF (&ps->fonts, ps->fib.fcSttbfffn, ps->fib.lcbSttbfffn,
143 ps->tablefd);
144
145 /*we will need the table of names to answer questions like the name of the doc */
146 if ((ver == WORD6)
147 || (ver == WORD7))
148 {
149 wvGetSTTBF6 (&ps->anSttbfAssoc, ps->fib.fcSttbfAssoc,
150 ps->fib.lcbSttbfAssoc, ps->tablefd);
151 wvGetSTTBF6 (&ps->Sttbfbkmk, ps->fib.fcSttbfbkmk,
152 ps->fib.lcbSttbfbkmk, ps->tablefd);
153 }
154 else /*word 97 */
155 {
156 wvGetSTTBF (&ps->anSttbfAssoc, ps->fib.fcSttbfAssoc,
157 ps->fib.lcbSttbfAssoc, ps->tablefd);
158 wvGetSTTBF (&ps->Sttbfbkmk, ps->fib.fcSttbfbkmk,
159 ps->fib.lcbSttbfbkmk, ps->tablefd);
160 }
161
162 /*Extract all the list information that we will need to handle lists later on */
163 wvGetLST (&ps->lst, &ps->noofLST, ps->fib.fcPlcfLst, ps->fib.lcbPlcfLst,
164 ps->tablefd);
165 wvGetLFO_records (&ps->lfo, &ps->lfolvl, &ps->lvl, &ps->nolfo,
166 &ps->nooflvl, ps->fib.fcPlfLfo, ps->fib.lcbPlfLfo,
167 ps->tablefd);
168 /* init the starting list number table */
169 if (ps->nolfo)
170 {
171 ps->liststartnos = (U32 *) wvMalloc (9 * ps->nolfo * sizeof (U32));
172 ps->listnfcs = (U8 *) wvMalloc (9 * ps->nolfo);
173 ps->finallvl = (LVL *) wvMalloc (9 * ps->nolfo * sizeof (LVL));
174 for (i = 0; i < 9 * ps->nolfo; i++)
175 {
176 ps->liststartnos[i] = 0xffffffffL;
177 ps->listnfcs[i] = 0xff;
178 wvInitLVL (&(ps->finallvl[i]));
179 }
180 }
181 else
182 {
183 ps->liststartnos = NULL;
184 ps->listnfcs = NULL;
185 ps->finallvl = NULL;
186 }
187 /*Extract Graphic Information */
188 wvGetFSPA_PLCF (&ps->fspa, &ps->fspapos, &ps->nooffspa,
189 ps->fib.fcPlcspaMom, ps->fib.lcbPlcspaMom, ps->tablefd);
190 wvGetFDOA_PLCF (&ps->fdoa, &ps->fdoapos, &ps->nooffdoa,
191 ps->fib.fcPlcdoaMom, ps->fib.lcbPlcdoaMom, ps->tablefd);
192
193
194
195 /*
196 we will need the paragraph and character bounds table to make decisions as
197 to where a para/char run begins and ends
198 */
199 if ((ver == WORD6)
200 || (ver == WORD7))
201 {
202 wvGetBTE_PLCF6 (&btePapx, &posPapx, ¶_intervals,
203 ps->fib.fcPlcfbtePapx, ps->fib.lcbPlcfbtePapx,
204 ps->tablefd);
205 wvGetBTE_PLCF6 (&bteChpx, &posChpx, &char_intervals,
206 ps->fib.fcPlcfbteChpx, ps->fib.lcbPlcfbteChpx,
207 ps->tablefd);
208 }
209 else /* word 97 */
210 {
211 wvGetBTE_PLCF (&btePapx, &posPapx, ¶_intervals,
212 ps->fib.fcPlcfbtePapx, ps->fib.lcbPlcfbtePapx,
213 ps->tablefd);
214 wvGetBTE_PLCF (&bteChpx, &posChpx, &char_intervals,
215 ps->fib.fcPlcfbteChpx, ps->fib.lcbPlcfbteChpx,
216 ps->tablefd);
217 }
218
219 wvGetSED_PLCF (&sed, &posSedx, §ion_intervals, ps->fib.fcPlcfsed,
220 ps->fib.lcbPlcfsed, ps->tablefd);
221 wvTrace (("section_intervals is %d\n", section_intervals));
222
223 /*
224 The text of the file starts at fib.fcMin, but we will use the piecetable
225 records rather than this basic seek.
226 fseek(ps->mainfd,ps->fib.fcMin,SEEK_SET);
227 */
228
229 /*
230 If !fib.fComplex, the document text stream is represented by the text
231 beginning at fib.fcMin up to (but not including) fib.fcMac.
232 */
233
234 if ((ver == WORD2) && !ps->fib.fComplex)
235 {
236 wvHandleDocument (ps, DOCBEGIN);
237 wvStream_goto (ps->mainfd, ps->fib.fcMin);
238 for (i = ps->fib.fcMin; i < ps->fib.fcMac; i++)
239 {
240 eachchar = wvGetChar (ps->mainfd, 1);
241 (*(ps->charhandler)) (ps, eachchar, 1, ps->fib.lid);
242 /* (*(ps->scharhandler))(ps,eachchar,&achp; no go */
243 /* wvOutputTextChar(eachchar, 1, ps, &achp); no go */
244 /* Formatting still lacking. This is just a start. */
245 }
246 wvHandleDocument (ps, DOCEND);
247 wvReleaseSTTBF (&ps->anSttbfAssoc);
248 wvReleaseSTTBF (&ps->Sttbfbkmk);
249 wvFree (posChpx);
250 wvFree (bteChpx);
251 wvFree (btePapx);
252 wvReleaseCLX (&ps->clx);
253 wvReleaseSTSH (&ps->stsh);
254 return;
255 }
256
257
258 #ifdef DEBUG
259 if (ps->fib.fcMac != wvGetEndFCPiece (ps->clx.nopcd - 1, &ps->clx))
260 wvTrace (
261 ("fcMac is not the same as the piecetable %x %x!\n",
262 ps->fib.fcMac, wvGetEndFCPiece (ps->clx.nopcd - 1,
263 &ps->clx)));
264 #endif
265
266 wvInitPAPX_FKP (¶_fkp);
267 wvInitCHPX_FKP (&char_fkp);
268
269 if(wvHandleDocument (ps, DOCBEGIN))
270 goto finish_processing;
271
272
273 /*get stream size for bounds checking*/
274 stream_size = wvStream_size(ps->mainfd);
275
276 /*for each piece */
277 for (piececount = 0; piececount < ps->clx.nopcd; piececount++)
278 {
279 ichartype =
280 wvGetPieceBoundsFC (&beginfc, &endfc, &ps->clx, piececount);
281 if(ichartype==-1)
282 break;
283 chartype = (U8) ichartype;
284 /*lvm007@aha.ru fix antiloop: check stream size */
285 if(beginfc>stream_size || endfc>stream_size){
286 wvError (
287 ("Piece Bounds out of range!, its a disaster\n"));
288 continue;
289 }
290
291 wvStream_goto (ps->mainfd, beginfc);
292
293 wvTrace (("SEEK %x\n", beginfc));
294
295 /*lvm007@aha.ru fix antiloop fix*/
296 if(wvGetPieceBoundsCP (&begincp, &endcp, &ps->clx, piececount)==-1)
297 break;
298
299 /*
300 text that is not in the same piece is not guaranteed to have the same properties as
301 the rest of the exception run, so force a stop and restart of these properties.
302 */
303 char_fcLim = beginfc;
304 wvTrace (("%d %d %d\n", begincp, endcp, ps->fib.ccpText));
305 for (i = begincp, j = beginfc; (i < endcp /*&& i<ps->fib.ccpText */ );
306 i++, j += wvIncFC (chartype))
307 {
308 /* character properties */
309 if (j == char_fcLim)
310 {
311 wvHandleElement (ps, CHARPROPEND, (void *) &achp,
312 char_dirty);
313 char_pendingclose = 0;
314 }
315
316 /* comment ending location */
317 if (i == comment_cpLim)
318 {
319 wvHandleElement (ps, COMMENTEND, (void *) catrd, 0);
320 comment_pendingclose = 0;
321 }
322
323
324 /* paragraph properties */
325 if (j == para_fcLim)
326 {
327 wvHandleElement (ps, PARAEND, (void *) &apap, para_dirty);
328 para_pendingclose = 0;
329 }
330
331 if (j == section_fcLim)
332 {
333 wvHandleElement (ps, SECTIONEND, (void *) &sep,
334 section_dirty);
335 section_pendingclose = 0;
336 }
337
338 if ((section_fcLim == 0xffffffff) || (section_fcLim == j))
339 {
340 wvTrace (("j i is %x %d\n", j, i));
341 section_dirty =
342 wvGetSimpleSectionBounds (ver, ps,
343 &sep, §ion_fcFirst,
344 §ion_fcLim, i,
345 &ps->clx, sed, &spiece,
346 posSedx,
347 section_intervals,
348 &ps->stsh, ps->mainfd);
349 wvTrace (
350 ("section begins at %x ends %x\n",
351 section_fcFirst, section_fcLim));
352 }
353
354 if (j == section_fcFirst)
355 {
356 wvHandleElement (ps, SECTIONBEGIN, (void *) &sep,
357 section_dirty);
358 section_pendingclose = 1;
359 }
360
361 if ((para_fcLim == 0xffffffff) || (para_fcLim == j))
362 {
363 wvReleasePAPX_FKP (¶_fkp);
364 wvGetSimpleParaBounds (ver, ¶_fkp,
365 ¶_fcFirst, ¶_fcLim,
366 wvConvertCPToFC (i, &ps->clx),
367 btePapx, posPapx, para_intervals,
368 ps->mainfd);
369 wvTrace (
370 ("Para from %x to %x, j is %x\n", para_fcFirst,
371 para_fcLim, j));
372
373 if (0 == para_pendingclose)
374 {
375 /*
376 if there's no paragraph open, but there should be then I believe that the fcFirst search
377 has failed me, so I set it to now. I need to investigate this further. I believe it occurs
378 when a the last piece ended simultaneously with the last paragraph, and that the algorithm
379 for finding the beginning of a para breaks under that condition. I need more examples to
380 be sure, but it happens is very large complex files so its hard to find
381 */
382 if (j != para_fcFirst)
383 {
384 wvWarning (
385 ("There is no paragraph due to open but one should be, plugging the gap.\n"));
386 para_fcFirst = j;
387 }
388 }
389 }
390
391 if (j == para_fcFirst)
392 {
393 para_dirty =
394 wvAssembleSimplePAP (ver, &apap, para_fcLim, ¶_fkp, ps);
395
396 /* test section */
397 wvReleasePAPX_FKP (¶_fkp);
398 wvGetSimpleParaBounds (ver, ¶_fkp,
399 &dummy, &nextpara_fcLim,
400 para_fcLim, btePapx, posPapx,
401 para_intervals, ps->mainfd);
402 wvAssembleSimplePAP (ver, &ps->nextpap, nextpara_fcLim, ¶_fkp, ps);
403 /* end test section */
404
405 if ((apap.fInTable) && (!apap.fTtp))
406 {
407 wvGetFullTableInit (ps, para_intervals, btePapx,
408 posPapx);
409 wvGetRowTap (ps, &apap, para_intervals, btePapx,
410 posPapx);
411 }
412 else if (apap.fInTable == 0)
413 ps->intable = 0;
414 wvHandleElement (ps, PARABEGIN, (void *) &apap,
415 para_dirty);
416
417 char_fcLim = j;
418 para_pendingclose = 1;
419 }
420
421 if ((comment_cpLim == 0xffffffffL) || (comment_cpLim == i))
422 {
423 wvTrace (
424 ("searching for the next comment begin cp is %d\n",
425 i));
426 catrd =
427 wvGetCommentBounds (&comment_cpFirst,
428 &comment_cpLim, i, atrd,
429 posAtrd, atrd_intervals,
430 &SttbfAtnbkmk, bkf, posBKF,
431 bkf_intervals, bkl, posBKL,
432 bkl_intervals);
433 wvTrace (
434 ("begin and end are %d %d\n", comment_cpFirst,
435 comment_cpLim));
436 }
437
438 if (i == comment_cpFirst)
439 {
440 wvHandleElement (ps, COMMENTBEGIN, (void *) catrd, 0);
441 comment_pendingclose = 1;
442 }
443
444
445 if ((char_fcLim == 0xffffffff) || (char_fcLim == j))
446 {
447 wvTrace (("j i is %x %d\n", j, i));
448 wvReleaseCHPX_FKP (&char_fkp);
449 wvGetSimpleCharBounds (ver, &char_fkp,
450 &char_fcFirst, &char_fcLim, i,
451 &ps->clx, bteChpx, posChpx,
452 char_intervals, ps->mainfd);
453 wvTrace (
454 ("char begins at %x ends %x, j is %x\n",
455 char_fcFirst, char_fcLim, j));
456 if (0 == char_pendingclose)
457 {
458 /*
459 if there's no character run open, but there should be then I believe that the fcFirst search
460 has failed me, so I set it to now. I need to investigate this further.
461 */
462 if (j != char_fcFirst)
463 {
464 wvWarning (
465 ("There is no character run due to open but one should be, plugging the gap.\n"));
466 char_fcFirst = j;
467 }
468
469 }
470 else{
471 /* lvm007@aha.ru fix: if currentfc>fcFirst but CHARPROP's changed look examples/charprops.doc*/
472 if(char_fcFirst< j)
473 char_fcFirst = j;
474 }
475 }
476
477 if (j == char_fcFirst)
478 {
479 wvTrace (("assembling CHP...\n"));
480 /* a CHP's base style is in the para style */
481 /* achp.istd = apap.istd; */
482 char_dirty =
483 wvAssembleSimpleCHP (ver, &achp, &apap,
484 char_fcLim, &char_fkp,
485 &ps->stsh);
486 wvTrace (("CHP assembled.\n"));
487 wvTrace (("font is %d\n", achp.ftcAscii));
488 wvTrace (("char spec is %d\n", achp.ftcSym));
489 wvHandleElement (ps, CHARPROPBEGIN, (void *) &achp,
490 char_dirty);
491 wvTrace (("char lid is %x\n", achp.lidDefault));
492 char_pendingclose = 1;
493 }
494
495 eachchar = wvGetChar (ps->mainfd, chartype);
496
497 if ((eachchar == 0x07) && (!achp.fSpec))
498 ps->endcell = 1;
499
500 ps->currentcp = i;
501 wvTrace (("char pos is %x %x\n", j, eachchar));
502 wvOutputTextChar (eachchar, chartype, ps, &achp);
503 }
504
505 if (j == para_fcLim)
506 {
507 wvHandleElement (ps, PARAEND, (void *) &apap, para_dirty);
508 para_pendingclose = 0;
509 para_fcLim = 0xffffffffL;
510 }
511
512 if (i == comment_cpLim)
513 {
514 wvHandleElement (ps, COMMENTEND, (void *) catrd, 0);
515 comment_pendingclose = 0;
516 comment_cpLim = 0xffffffffL;
517 }
518
519 if (j == char_fcLim)
520 {
521 wvHandleElement (ps, CHARPROPEND, (void *) &achp, char_dirty);
522 char_pendingclose = 0;
523 char_fcLim = 0xffffffffL;
524 }
525
526 }
527
528 finish_processing:
529 if (char_pendingclose)
530 {
531 wvInitCHP (&achp);
532 wvHandleElement (ps, CHARPROPEND, (void *) &achp, char_dirty);
533 }
534
535 if (comment_pendingclose)
536 wvHandleElement (ps, COMMENTEND, (void *) catrd, 0);
537
538 if (para_pendingclose)
539 {
540 wvInitPAP (&apap);
541 wvHandleElement (ps, PARAEND, (void *) &apap, para_dirty);
542 }
543
544 if (section_pendingclose)
545 wvHandleElement (ps, SECTIONEND, (void *) &sep, section_dirty);
546
547 wvFree (ps->fspa);
548 wvFree (ps->fspapos);
549 wvFree (ps->fdoa);
550 wvFree (ps->fdoapos);
551
552 wvFree (posBKL);
553 wvFree (bkl);
554 wvFree (posBKF);
555 wvFree (bkf);
556 wvFree (posAtrd);
557 wvFree (atrd);
558
559 internal_wvReleasePAPX_FKP (¶_fkp);
560 internal_wvReleaseCHPX_FKP (&char_fkp);
561 wvHandleDocument (ps, DOCEND);
562 wvFree (posSedx);
563 wvFree (sed);
564 wvFree(bkd);
565 wvFree(posBKD);
566 wvFree(ftxbx);
567 wvFree(txbxTxt);
568 #if defined(WIN32)
569 wvReleasePAPX_FKP (¶_fkp);
570 wvReleaseCHPX_FKP (&char_fkp);
571
572 external_wvReleasePAPX_FKP ();
573 external_wvReleaseCHPX_FKP();
574 #endif
575
576
577 wvFree (ps->liststartnos);
578 wvFree (ps->listnfcs);
579 for (i = 0; i < 9 * ps->nolfo; i++)
580 wvReleaseLVL (&(ps->finallvl[i]));
581 wvFree (ps->finallvl);
582
583 wvReleaseLST (&ps->lst, ps->noofLST);
584 wvReleaseLFO_records (&ps->lfo, &ps->lfolvl, &ps->lvl, ps->nooflvl);
585 wvReleaseSTTBF (&ps->anSttbfAssoc);
586 wvReleaseSTTBF (&ps->Sttbfbkmk);
587 wvFree (btePapx);
588 wvFree (posPapx);
589 wvFree (bteChpx);
590 wvFree (posChpx);
591 wvFree (bkd);
592 wvFree (posBKD);
593 wvFree (txbxTxt);
594 wvFree (ftxbx);
595 #if 0
596 /*
597 so what, this is meaningless
598 C.
599 */
600 if (ps->fib.fcMac != ftell (ps->mainfd))
601 wvError (("fcMac did not match end of input !\n"));
602 #endif
603 wvReleaseCLX (&ps->clx);
604 wvReleaseFFN_STTBF (&ps->fonts);
605 wvReleaseSTSH (&ps->stsh);
606 wvReleaseSTTBF (&SttbfAtnbkmk);
607 wvReleaseSTTBF (&grpXstAtnOwners);
608 if (ps->vmerges)
609 {
610 for (i = 0; i < ps->norows; i++)
611 wvFree (ps->vmerges[i]);
612 wvFree (ps->vmerges);
613 }
614 wvFree (ps->cellbounds);
615 wvOLEFree(ps);
616 tokenTreeFreeAll ();
617 }
618
619
620 /*
621 When a document is recorded in non-complex format, the bounds of the
622 paragraph that contains a particular character can be found by
623
624 1) calculating the FC coordinate of the character,
625
626 2) searching the bin table to find an FKP page that describes that FC,
627
628 3) fetching that FKP, and
629
630 4) then searching the FKP to find the interval in the rgfc that encloses the character.
631
632 5) The bounds of the interval are the fcFirst and fcLim of the containing paragraph.
633
634 Every character greater than or equal to fcFirst and less than fcLim is part of
635 the containing paragraph.
636
637 */
638 int
wvGetSimpleParaBounds(wvVersion ver,PAPX_FKP * fkp,U32 * fcFirst,U32 * fcLim,U32 currentfc,BTE * bte,U32 * pos,int nobte,wvStream * fd)639 wvGetSimpleParaBounds (wvVersion ver, PAPX_FKP * fkp, U32 * fcFirst,
640 U32 * fcLim, U32 currentfc, BTE * bte, U32 * pos,
641 int nobte, wvStream * fd)
642 {
643 BTE entry;
644 long currentpos;
645
646 /*
647 currentfc = wvConvertCPToFC(currentcp,clx);
648 */
649
650 wvTrace (("currentfc is %x\n", currentfc));
651 if (currentfc == 0xffffffffL)
652 {
653 wvError (("Para Bounds not found !\n"));
654 return (1);
655 }
656
657 if (0 != wvGetBTE_FromFC (&entry, currentfc, bte, pos, nobte))
658 {
659 wvError (("BTE not found !\n"));
660 return (1);
661 }
662 currentpos = wvStream_tell (fd);
663 /*The pagenumber of the FKP is entry.pn */
664
665 wvTrace (("pn is %d\n", entry.pn));
666 wvGetPAPX_FKP (ver, fkp, entry.pn, fd);
667 wvTrace (("last entry is %x\n", fkp->rgfc[fkp->crun]));
668 while (fkp->rgfc[fkp->crun] <= currentfc)
669 {
670 if ((fkp->rgfc[fkp->crun] == currentfc) && (currentfc == pos[nobte]))
671 break;
672
673 /* Bad things man... */
674 wvError (("Alert, insane repeat \"insane\" paragraph structure,"
675 "making wild stab in the dark to attempt to continue\n"));
676 wvReleasePAPX_FKP (fkp);
677 entry.pn++;
678 wvGetPAPX_FKP (ver, fkp, entry.pn, fd);
679 }
680
681 wvStream_goto (fd, currentpos);
682
683 return (wvGetIntervalBounds
684 (fcFirst, fcLim, currentfc, fkp->rgfc, fkp->crun + 1));
685 }
686
687 int
wvGetSimpleCharBounds(wvVersion ver,CHPX_FKP * fkp,U32 * fcFirst,U32 * fcLim,U32 currentcp,CLX * clx,BTE * bte,U32 * pos,int nobte,wvStream * fd)688 wvGetSimpleCharBounds (wvVersion ver, CHPX_FKP * fkp, U32 * fcFirst,
689 U32 * fcLim, U32 currentcp, CLX * clx, BTE * bte,
690 U32 * pos, int nobte, wvStream * fd)
691 {
692 U32 currentfc;
693 BTE entry;
694 long currentpos;
695
696 currentfc = wvConvertCPToFC (currentcp, clx);
697
698 if (currentfc == 0xffffffffL)
699 {
700 wvError (("Char Bounds not found !\n"));
701 return (1);
702 }
703
704 wvTrace (("char fc is %x\n", currentfc));
705
706 if (0 != wvGetBTE_FromFC (&entry, currentfc, bte, pos, nobte))
707 {
708 wvError (("BTE not found !\n"));
709 return (1);
710 }
711 currentpos = wvStream_tell (fd);
712 /*The pagenumber of the FKP is entry.pn */
713
714 wvTrace (("pn is %d\n", entry.pn));
715 wvGetCHPX_FKP (ver, fkp, entry.pn, fd);
716
717 while (fkp->rgfc[fkp->crun] <= currentfc)
718 {
719 if ((fkp->rgfc[fkp->crun] == currentfc) && (currentfc == pos[nobte]))
720 break;
721
722 /* Bad things man... */
723 wvError (("Alert, insane repeat \"insane\" character run structure,"
724 "making wild stab in the dark to attempt to continue\n"));
725 wvReleaseCHPX_FKP (fkp);
726 entry.pn++;
727 wvGetCHPX_FKP (ver, fkp, entry.pn, fd);
728 }
729
730 wvStream_goto (fd, currentpos);
731
732 return (wvGetIntervalBounds
733 (fcFirst, fcLim, currentfc, fkp->rgfc, fkp->crun + 1));
734 }
735
736 int
wvGetIntervalBounds(U32 * fcFirst,U32 * fcLim,U32 currentfc,U32 * rgfc,U32 nopos)737 wvGetIntervalBounds (U32 * fcFirst, U32 * fcLim, U32 currentfc, U32 * rgfc,
738 U32 nopos)
739 {
740 U32 i = 0;
741 while (i < nopos - 1)
742 {
743 wvTrace (
744 ("searching...%x %x %x\n", currentfc,
745 wvNormFC (rgfc[i], NULL), wvNormFC (rgfc[i + 1], NULL)));
746 /*
747 if ( (wvNormFC(rgfc[i],NULL) >= currentfc) && (currentfc <= wvNormFC(rgfc[i+1],NULL)) )
748 */
749 if ((currentfc >= wvNormFC (rgfc[i], NULL))
750 && (currentfc < wvNormFC (rgfc[i + 1], NULL)))
751 {
752 *fcFirst = wvNormFC (rgfc[i], NULL);
753 *fcLim = wvNormFC (rgfc[i + 1], NULL);
754 return (0);
755 }
756 i++;
757 }
758 *fcFirst = wvNormFC (rgfc[nopos - 2], NULL);
759 *fcLim = wvNormFC (rgfc[nopos - 1], NULL);
760 wvTrace (("I'd rather not see this happen at all :-)\n"));
761 return (0);
762 }
763
764 /*
765 it is necessary to use the CP of the character to search the
766 plcfsed for the index i of the largest CP that is less than or equal to the
767 character's CP.
768
769 plcfsed.rgcp[i] is the CP of the first character of the
770 section and plcfsed.rgcp[i+1] is the CP of the character following the
771 section mark that terminates the section (call it cpLim).
772
773 Then retrieve plcfsed.rgsed[i]. The FC in this SED gives the location where the SEPX for
774 the section is stored.
775
776 Then create a local SEP with default section properties. If the
777 sed.fc != 0xFFFFFFFF, then the sprms within the SEPX that is stored at offset
778 sed.fc must be applied to the local SEP. The process thus far has created a
779 SEP that describes what the section properties of the section at the last
780 full save.
781 */
782 int
wvGetSimpleSectionBounds(wvVersion ver,wvParseStruct * ps,SEP * sep,U32 * fcFirst,U32 * fcLim,U32 cp,CLX * clx,SED * sed,U32 * spiece,U32 * posSedx,U32 section_intervals,STSH * stsh,wvStream * fd)783 wvGetSimpleSectionBounds (wvVersion ver, wvParseStruct * ps, SEP * sep,
784 U32 * fcFirst, U32 * fcLim, U32 cp, CLX * clx,
785 SED * sed, U32 * spiece, U32 * posSedx,
786 U32 section_intervals, STSH * stsh, wvStream * fd)
787 {
788 U32 i = 0;
789 int ret = 0;
790 SEPX sepx;
791 long pos = wvStream_tell (fd);
792 U32 cpTest = 0, j, dummy;
793
794 if (section_intervals == 0)
795 {
796 wvGetPieceBoundsFC (fcFirst, &dummy, &ps->clx, 0);
797 wvGetPieceBoundsFC (&dummy, fcLim, &ps->clx, ps->clx.nopcd);
798 return (0);
799 }
800
801 j = section_intervals - 1;
802
803 if (cp == 0)
804 j = 0;
805 while (i < section_intervals)
806 {
807 wvTrace (("searching for sep %d %d\n", posSedx[i], cp));
808 if ((posSedx[i] <= cp) && (posSedx[i] > cpTest))
809 {
810 cpTest = posSedx[i];
811 j = i;
812 *spiece = wvGetPieceFromCP (cpTest, clx);
813 }
814 i++;
815 }
816
817 wvTrace (("found at %d %d\n", posSedx[j], posSedx[j + 1]));
818 *fcFirst = wvConvertCPToFC (posSedx[j], clx);
819 *fcLim = wvConvertCPToFC (posSedx[j + 1], clx);
820 wvTrace (("found at %x %x\n", *fcFirst, *fcLim));
821
822 wvInitSEP (sep);
823
824 if (sed[j].fcSepx != 0xffffffffL)
825 {
826 wvStream_goto (fd, wvNormFC (sed[j].fcSepx, NULL));
827 wvGetSEPX (ver, &sepx, fd);
828 if (ver == WORD8)
829 ret = wvAddSEPXFromBucket (sep, &sepx, stsh);
830 else
831 ret = wvAddSEPXFromBucket6 (sep, &sepx, stsh);
832 wvReleaseSEPX (&sepx);
833 }
834
835 wvStream_goto (fd, pos);
836 return (ret);
837 }
838
839 U32
wvGetBeginFC(wvParseStruct * ps,subdocument whichdoc)840 wvGetBeginFC (wvParseStruct * ps, subdocument whichdoc)
841 {
842 U32 para_fcFirst = 0x400;
843 switch (whichdoc)
844 {
845 case Dmain:
846 default:
847 para_fcFirst = wvConvertCPToFC (0, &ps->clx);
848 break;
849 case Dfootnote:
850 para_fcFirst = wvConvertCPToFC (ps->fib.ccpText, &ps->clx);
851 break;
852 case Dheader:
853 para_fcFirst = wvConvertCPToFC (ps->fib.ccpText + ps->fib.ccpFtn,
854 &ps->clx);
855 break;
856 case Dannotation:
857 para_fcFirst = wvConvertCPToFC (ps->fib.ccpText + ps->fib.ccpFtn +
858 ps->fib.ccpHdr, &ps->clx);
859 break;
860 case Dendnote:
861 para_fcFirst = wvConvertCPToFC (ps->fib.ccpText + ps->fib.ccpFtn +
862 ps->fib.ccpHdr + ps->fib.ccpAtn,
863 &ps->clx);
864 break;
865 case Dtextbox:
866 para_fcFirst = wvConvertCPToFC (ps->fib.ccpText + ps->fib.ccpFtn +
867 ps->fib.ccpHdr + ps->fib.ccpAtn +
868 ps->fib.ccpEdn, &ps->clx);
869 break;
870 case Dheader_textbox:
871 para_fcFirst = wvConvertCPToFC (ps->fib.ccpText + ps->fib.ccpFtn +
872 ps->fib.ccpHdr + ps->fib.ccpAtn +
873 ps->fib.ccpEdn + ps->fib.ccpTxbx,
874 &ps->clx);
875 break;
876 }
877 return (para_fcFirst);
878 }
879