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
28 /*
29 To find the beginning of the paragraph containing a character in a complex
30 document, it's first necessary to
31
32 1) search for the piece containing the character in the piece table.
33
34 2) Then calculate the FC in the file that stores the character from the piece
35 table information.
36
37 3) Using the FC, search the FCs FKP for the largest FC less than the character's
38 FC, call it fcTest.
39
40 4) If the character at fcTest-1 is contained in the current piece, then the
41 character corresponding to that FC in the piece is the first character of
42 the paragraph.
43
44 5) If that FC is before or marks the beginning of the piece, scan a piece at a
45 time towards the beginning of the piece table until a piece is found that
46 contains a paragraph mark.
47
48 (This can be done by using the end of the piece FC, finding the largest FC in
49 its FKP that is less than or equal to the end of piece FC, and checking to see
50 if the character in front of the FKP FC (which must mark a paragraph end) is
51 within the piece.)
52
53 6) When such an FKP FC is found, the FC marks the first byte of paragraph text.
54 */
55
56 /*
57 To find the end of a paragraph for a character in a complex format file,
58 again
59
60 1) it is necessary to know the piece that contains the character and the
61 FC assigned to the character.
62
63 2) Using the FC of the character, first search the FKP that describes the
64 character to find the smallest FC in the rgfc that is larger than the character
65 FC.
66
67 3) If the FC found in the FKP is less than or equal to the limit FC of the
68 piece, the end of the paragraph that contains the character is at the FKP FC
69 minus 1.
70
71 4) If the FKP FC that was found was greater than the FC of the end of the
72 piece, scan piece by piece toward the end of the document until a piece is
73 found that contains a paragraph end mark.
74
75 5) It's possible to check if a piece contains a paragraph mark by using the
76 FC of the beginning of the piece to search in the FKPs for the smallest FC in
77 the FKP rgfc that is greater than the FC of the beginning of the piece.
78
79 If the FC found is less than or equal to the limit FC of the
80 piece, then the character that ends the paragraph is the character
81 immediately before the FKP FC.
82 */
83 int
wvGetComplexParaBounds(wvVersion ver,PAPX_FKP * fkp,U32 * fcFirst,U32 * fcLim,U32 currentfc,CLX * clx,BTE * bte,U32 * pos,int nobte,U32 piece,wvStream * fd)84 wvGetComplexParaBounds (wvVersion ver, PAPX_FKP * fkp, U32 * fcFirst,
85 U32 * fcLim, U32 currentfc, CLX * clx, BTE * bte,
86 U32 * pos, int nobte, U32 piece, wvStream * fd)
87 {
88 /*
89 U32 currentfc;
90 */
91 BTE entry;
92 long currentpos;
93
94 if (currentfc == 0xffffffffL)
95 {
96 wvError (
97 ("Para Bounds not found !, this is ok if this is the last para, otherwise its a disaster\n"));
98 return (-1);
99 }
100
101 if (0 != wvGetBTE_FromFC (&entry, currentfc, bte, pos, nobte))
102 {
103 wvError (("BTE not found !\n"));
104 return (-1);
105 }
106 currentpos = wvStream_tell (fd);
107 /*The pagenumber of the FKP is entry.pn */
108
109 wvTrace (("the entry.pn is %d\n", entry.pn));
110 wvGetPAPX_FKP (ver, fkp, entry.pn, fd);
111
112 wvGetComplexParafcFirst (ver, fcFirst, currentfc, clx, bte, pos, nobte,
113 piece, fkp, fd);
114
115 wvReleasePAPX_FKP (fkp);
116 wvTrace (("BREAK\n"));
117 wvGetPAPX_FKP (ver, fkp, entry.pn, fd);
118
119 piece =
120 wvGetComplexParafcLim (ver, fcLim, currentfc, clx, bte, pos, nobte,
121 piece, fkp, fd);
122
123 wvStream_goto (fd, currentpos);
124 return (piece);
125 }
126
127 int
wvGetComplexParafcLim(wvVersion ver,U32 * fcLim,U32 currentfc,CLX * clx,BTE * bte,U32 * pos,int nobte,U32 piece,PAPX_FKP * fkp,wvStream * fd)128 wvGetComplexParafcLim (wvVersion ver, U32 * fcLim, U32 currentfc, CLX * clx,
129 BTE * bte, U32 * pos, int nobte, U32 piece,
130 PAPX_FKP * fkp, wvStream * fd)
131 {
132 U32 fcTest, beginfc;
133 BTE entry;
134 *fcLim = 0xffffffffL;
135 wvTrace (("here is fcLim, currentfc is %x\n", currentfc));
136 fcTest = wvSearchNextSmallestFCPAPX_FKP (fkp, currentfc);
137
138 wvTrace (
139 ("fcTest is %x, end is %x\n", fcTest,
140 wvGetEndFCPiece (piece, clx)));
141
142
143 if (fcTest <= wvGetEndFCPiece (piece, clx))
144 {
145 *fcLim = fcTest;
146 }
147 else
148 {
149 /*get end fc of previous piece */
150 piece++;
151 while (piece < clx->nopcd)
152 {
153 wvTrace (("piece is %d\n", piece));
154 beginfc = wvNormFC (clx->pcd[piece].fc, NULL);
155 if (0 != wvGetBTE_FromFC (&entry, beginfc, bte, pos, nobte))
156 {
157 wvError (("BTE not found !\n"));
158 return (-1);
159 }
160 wvReleasePAPX_FKP (fkp);
161 wvGetPAPX_FKP (ver, fkp, entry.pn, fd);
162 fcTest = wvSearchNextSmallestFCPAPX_FKP (fkp, beginfc);
163 wvTrace (
164 ("fcTest(t) is %x, end is %x\n", fcTest,
165 wvGetEndFCPiece (piece, clx)));
166 if (fcTest <= wvGetEndFCPiece (piece, clx))
167 {
168 *fcLim = fcTest;
169 break;
170 }
171 piece++;
172 }
173 }
174 wvTrace (("fcLim is %x\n", *fcLim));
175 if (piece == clx->nopcd)
176 {
177 wvTrace (("failed to find a solution to end of paragraph\n"));
178 *fcLim = fcTest;
179 return (clx->nopcd - 1); /* test using this */
180 }
181 return (piece);
182 }
183
184
185 int
wvGetComplexParafcFirst(wvVersion ver,U32 * fcFirst,U32 currentfc,CLX * clx,BTE * bte,U32 * pos,int nobte,U32 piece,PAPX_FKP * fkp,wvStream * fd)186 wvGetComplexParafcFirst (wvVersion ver, U32 * fcFirst, U32 currentfc,
187 CLX * clx, BTE * bte, U32 * pos, int nobte,
188 U32 piece, PAPX_FKP * fkp, wvStream * fd)
189 {
190 U32 fcTest, endfc;
191 BTE entry;
192 fcTest = wvSearchNextLargestFCPAPX_FKP (fkp, currentfc);
193
194 wvTrace (("fcTest (s) is %x\n", fcTest));
195
196 if (wvQuerySamePiece (fcTest - 1, clx, piece))
197 {
198 wvTrace (("same piece\n"));
199 *fcFirst = fcTest - 1;
200 }
201 else
202 {
203 /*
204 get end fc of previous piece ??, or use the end of the current piece
205 */
206 piece--;
207 while (piece != 0xffffffffL)
208 {
209 wvTrace (("piece is %d\n", piece));
210 endfc = wvGetEndFCPiece (piece, clx);
211 wvTrace (("endfc is %x\n", endfc));
212 if (0 != wvGetBTE_FromFC (&entry, endfc, bte, pos, nobte))
213 {
214 wvError (("BTE not found !\n"));
215 return (-1);
216 }
217 wvReleasePAPX_FKP (fkp);
218 wvGetPAPX_FKP (ver, fkp, entry.pn, fd);
219 fcTest = wvSearchNextLargestFCPAPX_FKP (fkp, endfc);
220 wvTrace (("fcTest(ft) is %x\n", fcTest));
221 if (wvQuerySamePiece (fcTest - 1, clx, piece))
222 {
223 *fcFirst = fcTest - 1;
224 break;
225 }
226 piece--;
227 }
228
229 }
230 if (piece == 0xffffffffL)
231 {
232 wvTrace (
233 ("failed to find a solution to the beginning of the paragraph\n"));
234 *fcFirst = currentfc;
235 }
236 wvTrace (("fcFirst is finally %x\n", *fcFirst));
237 return (0);
238 }
239
240
241 /* char properties version of the above -JB */
242 /* only difference is that we're using CHPX FKP pages,
243 * and specifically just the Get and Release functions are
244 * different between the two. We might be able to
245 * abstract the necessary functions to avoid duplicating them... */
246
247 int
wvGetComplexCharBounds(wvVersion ver,CHPX_FKP * fkp,U32 * fcFirst,U32 * fcLim,U32 currentfc,CLX * clx,BTE * bte,U32 * pos,int nobte,U32 piece,wvStream * fd)248 wvGetComplexCharBounds (wvVersion ver, CHPX_FKP * fkp, U32 * fcFirst,
249 U32 * fcLim, U32 currentfc, CLX * clx, BTE * bte,
250 U32 * pos, int nobte, U32 piece, wvStream * fd)
251 {
252 BTE entry;
253 long currentpos;
254
255 wvTrace (("current fc is %x\n", currentfc));
256
257 if (currentfc == 0xffffffffL)
258 {
259 wvTrace (
260 ("Char Bounds not found !, this is ok if this is the last char, otherwise its a disaster\n"));
261 return (-1);
262 }
263
264 if (0 != wvGetBTE_FromFC (&entry, currentfc, bte, pos, nobte))
265 {
266 wvError (("BTE not found !\n"));
267 return (-1);
268 }
269 currentpos = wvStream_tell (fd);
270 /*The pagenumber of the FKP is entry.pn */
271
272 wvGetCHPX_FKP (ver, fkp, entry.pn, fd);
273
274 wvGetComplexCharfcFirst (ver, fcFirst, currentfc, clx, bte, pos, nobte,
275 piece, fkp, fd);
276 wvTrace (("BEFORE PIECE is %d\n", piece));
277
278 wvReleaseCHPX_FKP (fkp);
279 wvGetCHPX_FKP (ver, fkp, entry.pn, fd);
280
281 piece =
282 wvGetComplexCharfcLim (ver, fcLim, currentfc, clx, bte, pos, nobte,
283 piece, fkp, fd);
284 wvTrace (("AFTER PIECE is %d\n", piece));
285
286 wvStream_goto (fd, currentpos);
287 return (piece);
288 }
289
290 int
wvGetComplexCharfcLim(wvVersion ver,U32 * fcLim,U32 currentfc,CLX * clx,BTE * bte,U32 * pos,int nobte,U32 piece,CHPX_FKP * fkp,wvStream * fd)291 wvGetComplexCharfcLim (wvVersion ver, U32 * fcLim, U32 currentfc, CLX * clx,
292 BTE * bte, U32 * pos, int nobte, U32 piece,
293 CHPX_FKP * fkp, wvStream * fd)
294 {
295 U32 fcTest;
296 /*
297 BTE entry;
298 */
299 *fcLim = 0xffffffffL;
300 /* this only works with the initial rgfc array, which is the
301 * same for both CHPX and PAPX FKPs */
302 fcTest = wvSearchNextSmallestFCPAPX_FKP ((PAPX_FKP *) fkp, currentfc);
303
304 wvTrace (("fcTest is %x\n", fcTest));
305
306 /*
307 this single line replaces all the rest, is it conceivable that i overengineered,
308 careful rereading of the spec makes no mention of repeating the para process to
309 find the boundaries of the exception text runs
310 */
311 *fcLim = fcTest;
312 wvTrace (("fcLim is %x\n", *fcLim));
313 if (piece == clx->nopcd)
314 return (clx->nopcd - 1); /* test using this */
315 return (piece);
316 }
317
318
319 int
wvGetComplexCharfcFirst(wvVersion ver,U32 * fcFirst,U32 currentfc,CLX * clx,BTE * bte,U32 * pos,int nobte,U32 piece,CHPX_FKP * fkp,wvStream * fd)320 wvGetComplexCharfcFirst (wvVersion ver, U32 * fcFirst, U32 currentfc,
321 CLX * clx, BTE * bte, U32 * pos, int nobte,
322 U32 piece, CHPX_FKP * fkp, wvStream * fd)
323 {
324 U32 fcTest /*,endfc */ ;
325 /*BTE entry; */
326 /* this only works with the initial rgfc array, which is the */
327 fcTest = wvSearchNextLargestFCCHPX_FKP (fkp, currentfc);
328
329 wvTrace (("fcTest (s) is %x\n", fcTest));
330
331 /*
332 this single line replaces all the rest, is it conceivable that i overengineered,
333 careful rereading of the spec makes no mention of repeating the para process to
334 find the boundaries of the exception text runs
335 */
336 *fcFirst = fcTest;
337 return (0);
338 }
339
340 /*
341 how this works,
342 we seek to the beginning of the text, we loop for a count of charaters that is stored in the fib.
343
344 the piecetable divides the text up into various sections, we keep track of our location vs
345 the next entry in that table, when we reach that location, we seek to the position that
346 the table tells us to go.
347
348 there are special cases for coming to the end of a section, and for the beginning and ends of
349 pages. for the purposes of headers and footers etc.
350 */
351 void
wvDecodeComplex(wvParseStruct * ps)352 wvDecodeComplex (wvParseStruct * ps)
353 {
354 U32 piececount = 0, i, j, spiece = 0;
355 U32 beginfc, endfc;
356 U32 stream_size;
357 U32 begincp, endcp;
358 int ichartype;
359 U8 chartype;
360 U16 eachchar;
361 U32 para_fcFirst, para_fcLim = 0xffffffffL;
362 U32 dummy, nextpara_fcLim = 0xffffffffL;
363 U32 char_fcFirst, char_fcLim = 0xffffffffL;
364 U32 section_fcFirst, section_fcLim = 0xffffffffL;
365 U32 comment_cpFirst = 0xffffffffL, comment_cpLim = 0xffffffffL;
366 BTE *btePapx = NULL, *bteChpx = NULL;
367 U32 *posPapx = NULL, *posChpx = NULL;
368 U32 para_intervals, char_intervals, section_intervals, atrd_intervals;
369 int cpiece = 0, npiece = 0;
370 PAPX_FKP para_fkp;
371 PAP apap;
372 CHPX_FKP char_fkp;
373 CHP achp;
374 int para_pendingclose = 0, comment_pendingclose = 0, char_pendingclose =
375 0, section_pendingclose = 0;
376 int para_dirty = 0, char_dirty = 0, section_dirty = 0;
377 SED *sed;
378 SEP sep;
379 U32 *posSedx;
380 ATRD *atrd, *catrd = NULL;
381 U32 *posAtrd;
382 STTBF grpXstAtnOwners, SttbfAtnbkmk;
383 BKF *bkf;
384 U32 *posBKF;
385 U32 bkf_intervals;
386 BKL *bkl;
387 U32 *posBKL;
388 U32 bkl_intervals;
389 wvVersion ver = wvQuerySupported (&ps->fib, NULL);
390 external_wvReleasePAPX_FKP ();
391 external_wvReleaseCHPX_FKP ();
392
393 /*dop */
394 wvGetDOP (ver, &ps->dop, ps->fib.fcDop,
395 ps->fib.lcbDop, ps->tablefd);
396
397 #if 0
398 /*
399 this is the versioning name information, the first 22 bytes of each sttbf entry are
400 unknown, the rest is a ordinary unicode string, is the time and date and saved by
401 encoded into the first 22 bytes.
402 */
403 STTBF versioning;
404 if (ver == 0)
405 {
406 U16 *str;
407 wvError (("into the versions\n"));
408 wvGetSTTBF (&versioning, ps->fib.fcSttbfUssr, ps->fib.lcbSttbfUssr,
409 ps->tablefd);
410 str = UssrStrBegin (&versioning, 0);
411 wvError (("versioning text is %s\n", wvWideStrToMB (str)));
412 }
413 #endif
414
415 wvGetATRD_PLCF (&atrd, &posAtrd, &atrd_intervals, ps->fib.fcPlcfandRef,
416 ps->fib.lcbPlcfandRef, ps->tablefd);
417 wvGetGrpXst (&grpXstAtnOwners, ps->fib.fcGrpXstAtnOwners,
418 ps->fib.lcbGrpXstAtnOwners, ps->tablefd);
419 wvTrace (
420 ("offset is %x, len is %d\n", ps->fib.fcSttbfAtnbkmk,
421 ps->fib.lcbSttbfAtnbkmk));
422 wvGetSTTBF (&SttbfAtnbkmk, ps->fib.fcSttbfAtnbkmk,
423 ps->fib.lcbSttbfAtnbkmk, ps->tablefd);
424 wvGetBKF_PLCF (&bkf, &posBKF, &bkf_intervals, ps->fib.fcPlcfAtnbkf,
425 ps->fib.lcbPlcfAtnbkf, ps->tablefd);
426 wvGetBKL_PLCF (&bkl, &posBKL, &bkl_intervals, ps->fib.fcPlcfAtnbkl,
427 ps->fib.lcbPlcfAtnbkl, ps->fib.fcPlcfAtnbkf, ps->fib.lcbPlcfAtnbkf,
428 ps->tablefd);
429
430 /*we will need the stylesheet to do anything useful with layout and look */
431 wvGetSTSH (&ps->stsh, ps->fib.fcStshf, ps->fib.lcbStshf, ps->tablefd);
432
433 /* get font list */
434 if ((ver == WORD6)
435 || (ver == WORD7))
436 wvGetFFN_STTBF6 (&ps->fonts, ps->fib.fcSttbfffn, ps->fib.lcbSttbfffn,
437 ps->tablefd);
438 else
439 wvGetFFN_STTBF (&ps->fonts, ps->fib.fcSttbfffn, ps->fib.lcbSttbfffn,
440 ps->tablefd);
441
442 /*we will need the table of names to answer questions like the name of the doc */
443 if ((ver == WORD6)
444 || (ver == WORD7))
445 {
446 wvGetSTTBF6 (&ps->anSttbfAssoc, ps->fib.fcSttbfAssoc,
447 ps->fib.lcbSttbfAssoc, ps->tablefd);
448 wvGetSTTBF6 (&ps->Sttbfbkmk, ps->fib.fcSttbfbkmk,
449 ps->fib.lcbSttbfbkmk, ps->tablefd);
450 }
451 else
452 {
453 wvGetSTTBF (&ps->anSttbfAssoc, ps->fib.fcSttbfAssoc,
454 ps->fib.lcbSttbfAssoc, ps->tablefd);
455 wvGetSTTBF (&ps->Sttbfbkmk, ps->fib.fcSttbfbkmk,
456 ps->fib.lcbSttbfbkmk, ps->tablefd);
457 }
458
459 /*Extract all the list information that we will need to handle lists later on */
460 wvGetLST (&ps->lst, &ps->noofLST, ps->fib.fcPlcfLst, ps->fib.lcbPlcfLst,
461 ps->tablefd);
462 wvGetLFO_records (&ps->lfo, &ps->lfolvl, &ps->lvl, &ps->nolfo,
463 &ps->nooflvl, ps->fib.fcPlfLfo, ps->fib.lcbPlfLfo,
464 ps->tablefd);
465 /* init the starting list number table */
466 if (ps->nolfo)
467 {
468 ps->liststartnos = (U32 *) wvMalloc (9 * ps->nolfo * sizeof (U32));
469 ps->listnfcs = (U8 *) wvMalloc (9 * ps->nolfo);
470 ps->finallvl = (LVL *) wvMalloc (9 * ps->nolfo * sizeof (LVL));
471 for (i = 0; i < 9 * ps->nolfo; i++)
472 {
473 ps->liststartnos[i] = 0xffffffffL;
474 ps->listnfcs[i] = 0xff;
475 wvInitLVL (&(ps->finallvl[i]));
476 }
477 }
478 else
479 {
480 ps->liststartnos = NULL;
481 ps->listnfcs = NULL;
482 ps->finallvl = NULL;
483 }
484
485 /*Extract Graphic Information */
486 wvGetFSPA_PLCF (&ps->fspa, &ps->fspapos, &ps->nooffspa,
487 ps->fib.fcPlcspaMom, ps->fib.lcbPlcspaMom, ps->tablefd);
488 wvGetFDOA_PLCF (&ps->fdoa, &ps->fdoapos, &ps->nooffdoa,
489 ps->fib.fcPlcdoaMom, ps->fib.lcbPlcdoaMom, ps->tablefd);
490
491 wvGetCLX (ver, &ps->clx,
492 (U32) ps->fib.fcClx, ps->fib.lcbClx, (U8) ps->fib.fExtChar,
493 ps->tablefd);
494
495 para_fcFirst = char_fcFirst = section_fcFirst =
496 wvConvertCPToFC (0, &ps->clx);
497
498 #ifdef DEBUG
499 if ((ps->fib.ccpFtn) || (ps->fib.ccpHdr))
500 wvTrace (("Special ending\n"));
501 #endif
502
503 /*
504 we will need the paragraph and character bounds table to make decisions as
505 to where a table begins and ends
506 */
507 if ((ver == WORD6)
508 || (ver == WORD7))
509 {
510 wvGetBTE_PLCF6 (&btePapx, &posPapx, ¶_intervals,
511 ps->fib.fcPlcfbtePapx, ps->fib.lcbPlcfbtePapx,
512 ps->tablefd);
513 wvGetBTE_PLCF6 (&bteChpx, &posChpx, &char_intervals,
514 ps->fib.fcPlcfbteChpx, ps->fib.lcbPlcfbteChpx,
515 ps->tablefd);
516 }
517 else
518 {
519 wvGetBTE_PLCF (&btePapx, &posPapx, ¶_intervals,
520 ps->fib.fcPlcfbtePapx, ps->fib.lcbPlcfbtePapx,
521 ps->tablefd);
522 wvGetBTE_PLCF (&bteChpx, &posChpx, &char_intervals,
523 ps->fib.fcPlcfbteChpx, ps->fib.lcbPlcfbteChpx,
524 ps->tablefd);
525 }
526
527 wvGetSED_PLCF (&sed, &posSedx, §ion_intervals, ps->fib.fcPlcfsed,
528 ps->fib.lcbPlcfsed, ps->tablefd);
529 wvTrace (("section_intervals is %d\n", section_intervals));
530
531 wvInitPAPX_FKP (¶_fkp);
532 wvInitCHPX_FKP (&char_fkp);
533
534 if(wvHandleDocument (ps, DOCBEGIN))
535 goto finish_processing;
536
537 /*get stream size for bounds checking*/
538 stream_size = wvStream_size(ps->mainfd);
539
540 /*for each piece */
541 for (piececount = 0; piececount < ps->clx.nopcd; piececount++)
542 {
543 ichartype =
544 wvGetPieceBoundsFC (&beginfc, &endfc, &ps->clx, piececount);
545 if(ichartype==-1)
546 break;
547 chartype = (U8) ichartype;
548 /*lvm007@aha.ru fix antiloop: check stream size */
549 if(beginfc>stream_size || endfc>stream_size){
550 wvError (
551 ("Piece Bounds out of range!, its a disaster\n"));
552 continue;
553 }
554 wvStream_goto (ps->mainfd, beginfc);
555 /*lvm007@aha.ru fix antiloop fix*/
556 if(wvGetPieceBoundsCP (&begincp, &endcp, &ps->clx, piececount)==-1)
557 break;
558 wvTrace (
559 ("piece begins at %x and ends just before %x. the char end is %x\n",
560 beginfc, endfc, char_fcLim));
561
562 /*
563 text that is not in the same piece is not guaranteed to have the same properties as
564 the rest of the exception run, so force a stop and restart of these properties.
565 */
566 char_fcLim = beginfc;
567
568 for (i = begincp, j = beginfc; (i < endcp /*&& i<ps->fib.ccpText */ );
569 i++, j += wvIncFC (chartype))
570 {
571 ps->currentcp = i;
572 /* character properties */
573 if (j == char_fcLim)
574 {
575 wvHandleElement (ps, CHARPROPEND, (void *) &achp,
576 char_dirty);
577 char_pendingclose = 0;
578 }
579
580 /* comment ending location */
581 if (i == comment_cpLim)
582 {
583 wvHandleElement (ps, COMMENTEND, (void *) catrd, 0);
584 comment_pendingclose = 0;
585 }
586
587 /* paragraph properties */
588 if (j == para_fcLim)
589 {
590 wvHandleElement (ps, PARAEND, (void *) &apap, para_dirty);
591 para_pendingclose = 0;
592 }
593
594 /* section properties */
595 if (j == section_fcLim)
596 {
597 wvHandleElement (ps, SECTIONEND, (void *) &sep,
598 section_dirty);
599 section_pendingclose = 0;
600 }
601
602 if ((section_fcLim == 0xffffffff) || (section_fcLim == j))
603 {
604 section_dirty =
605 wvGetSimpleSectionBounds (ver, ps,
606 &sep, §ion_fcFirst,
607 §ion_fcLim, i,
608 &ps->clx, sed, &spiece,
609 posSedx,
610 section_intervals,
611 &ps->stsh, ps->mainfd);
612 section_dirty =
613 (wvGetComplexSEP
614 (ver, &sep, spiece,
615 &ps->stsh, &ps->clx) ? 1 : section_dirty);
616 }
617
618 if (j == section_fcFirst)
619 {
620 wvHandleElement (ps, SECTIONBEGIN, (void *) &sep,
621 section_dirty);
622 section_pendingclose = 1;
623 }
624
625
626 if ((para_fcLim == 0xffffffffL) || (para_fcLim == j))
627 {
628 wvReleasePAPX_FKP (¶_fkp);
629 wvTrace (
630 ("cp and fc are %x(%d) %x\n", i, i,
631 wvConvertCPToFC (i, &ps->clx)));
632 cpiece =
633 wvGetComplexParaBounds (ver, ¶_fkp,
634 ¶_fcFirst, ¶_fcLim,
635 wvConvertCPToFC (i,
636 &ps->clx),
637 &ps->clx, btePapx, posPapx,
638 para_intervals, piececount,
639 ps->mainfd);
640 wvTrace (
641 ("para begin and end is %x %x\n", para_fcFirst,
642 para_fcLim));
643
644 if (0 == para_pendingclose)
645 {
646 /*
647 if there's no paragraph open, but there should be then I believe that the fcFirst search
648 has failed me, so I set it to now. I need to investigate this further. I believe it occurs
649 when a the last piece ended simultaneously with the last paragraph, and that the algorithm
650 for finding the beginning of a para breaks under that condition. I need more examples to
651 be sure, but it happens is very large complex files so its hard to find
652 */
653 if (j != para_fcFirst)
654 {
655 wvWarning (
656 ("There is no paragraph due to open but one should be, plugging the gap.\n"));
657 para_fcFirst = j;
658 }
659 }
660
661 }
662
663 if (j == para_fcFirst)
664 {
665 para_dirty =
666 wvAssembleSimplePAP (ver, &apap, para_fcLim, ¶_fkp, ps);
667 para_dirty =
668 (wvAssembleComplexPAP
669 (ver, &apap, cpiece, ps) ? 1 : para_dirty);
670 #ifdef SPRMTEST
671 {
672 int p;
673 wvTrace (("Assembled Complex\n"));
674 for (p = 0; p < apap.itbdMac; p++)
675 wvError (
676 ("Tab stop positions are %f inches (%d)\n",
677 ((float) (apap.rgdxaTab[p])) / 1440,
678 apap.rgdxaTab[p]));
679 }
680 #endif
681
682 /* test section */
683 wvReleasePAPX_FKP (¶_fkp);
684 wvTrace (
685 ("cp and fc are %x(%d) %x\n", i, i,
686 wvConvertCPToFC (i, &ps->clx)));
687 npiece =
688 wvGetComplexParaBounds (ver, ¶_fkp,
689 &dummy, &nextpara_fcLim,
690 para_fcLim, &ps->clx,
691 btePapx, posPapx,
692 para_intervals, piececount,
693 ps->mainfd);
694 wvTrace (
695 ("para begin and end is %x %x\n", para_fcFirst,
696 para_fcLim));
697 if (npiece > -1)
698 {
699 wvAssembleSimplePAP (ver, &ps->nextpap, nextpara_fcLim, ¶_fkp, ps);
700 wvAssembleComplexPAP (ver, &ps->nextpap, npiece,ps);
701 }
702 else
703 wvInitPAP (&ps->nextpap);
704 /* end test section */
705
706 if ((apap.fInTable) && (!apap.fTtp))
707 {
708 wvGetComplexFullTableInit (ps, para_intervals,
709 btePapx, posPapx,
710 piececount);
711 wvGetComplexRowTap (ps, &apap, para_intervals,
712 btePapx, posPapx, piececount);
713 }
714 else if (apap.fInTable == 0)
715 ps->intable = 0;
716
717 wvHandleElement (ps, PARABEGIN, (void *) &apap,
718 para_dirty);
719
720 char_fcLim = j;
721 para_pendingclose = 1;
722 }
723
724
725 if ((comment_cpLim == 0xffffffffL) || (comment_cpLim == i))
726 {
727 wvTrace (
728 ("searching for the next comment begin cp is %d\n",
729 i));
730 catrd =
731 wvGetCommentBounds (&comment_cpFirst,
732 &comment_cpLim, i, atrd,
733 posAtrd, atrd_intervals,
734 &SttbfAtnbkmk, bkf, posBKF,
735 bkf_intervals, bkl, posBKL,
736 bkl_intervals);
737 wvTrace (
738 ("begin and end are %d %d\n", comment_cpFirst,
739 comment_cpLim));
740 }
741
742 if (i == comment_cpFirst)
743 {
744 wvHandleElement (ps, COMMENTBEGIN, (void *) catrd, 0);
745 comment_pendingclose = 1;
746 }
747
748
749 if ((char_fcLim == 0xffffffffL) || (char_fcLim == j))
750 {
751 wvReleaseCHPX_FKP (&char_fkp);
752 /*try this without using the piece of the end char for anything */
753 wvGetComplexCharBounds (ver, &char_fkp,
754 &char_fcFirst, &char_fcLim,
755 wvConvertCPToFC (i, &ps->clx),
756 &ps->clx, bteChpx, posChpx,
757 char_intervals, piececount,
758 ps->mainfd);
759 wvTrace (
760 ("Bounds from %x to %x\n", char_fcFirst,
761 char_fcLim));
762 if (char_fcLim == char_fcFirst)
763 wvError (
764 ("I believe that this is an error, and you might see incorrect character properties\n"));
765 if (0 == char_pendingclose)
766 {
767 /*
768 if there's no character run open, but there should be then I believe that the fcFirst search
769 has failed me, so I set it to now. I need to investigate this further.
770 */
771 if (j != char_fcFirst)
772 {
773 wvTrace (
774 ("There is no character run due to open but one should be, plugging the gap.\n"));
775 char_fcFirst = j;
776 }
777
778 }
779 else{
780 /* lvm007@aha.ru fix: if currentfc>fcFirst but CHARPROP's changed look examples/charprops.doc for decode_simple*/
781 if(char_fcFirst< j)
782 char_fcFirst = j;
783 }
784 }
785
786 if (j == char_fcFirst)
787 {
788 /* a CHP's base style is in the para style */
789 /*achp.istd = apap.istd;*/
790 wvTrace (("getting chp\n"));
791 char_dirty =
792 wvAssembleSimpleCHP (ver, &achp, &apap,
793 char_fcLim, &char_fkp,
794 &ps->stsh);
795 wvTrace (("getting complex chp\n"));
796 char_dirty =
797 (wvAssembleComplexCHP
798 (ver, &achp, cpiece,
799 &ps->stsh, &ps->clx) ? 1 : char_dirty);
800 wvHandleElement (ps, CHARPROPBEGIN, (void *) &achp,
801 char_dirty);
802 char_pendingclose = 1;
803 }
804
805
806 eachchar = wvGetChar (ps->mainfd, chartype);
807
808 /* previously, in place of ps there was a NULL,
809 * but it was crashing Abiword. Was it NULL for a
810 * reason? -JB */
811 /*
812 nah, it was a oversight from when i didn't actually
813 use ps in this function
814 C.
815 */
816 if ((eachchar == 0x07) && (!achp.fSpec))
817 ps->endcell = 1;
818
819 wvTrace (("char pos is %x %x\n", j, eachchar));
820 wvOutputTextChar (eachchar, chartype, ps, &achp);
821 }
822
823 if (j == para_fcLim)
824 {
825 wvHandleElement (ps, PARAEND, (void *) &apap, para_dirty);
826 para_pendingclose = 0;
827 para_fcLim = 0xffffffffL;
828 }
829
830 if (i == comment_cpLim)
831 {
832 wvHandleElement (ps, COMMENTEND, (void *) catrd, 0);
833 comment_pendingclose = 0;
834 comment_cpLim = 0xffffffffL;
835 }
836
837 if (j == char_fcLim)
838 {
839 wvHandleElement (ps, CHARPROPEND, (void *) &achp, char_dirty);
840 char_pendingclose = 0;
841 char_fcLim = 0xffffffffL;
842 }
843
844 #if 0
845 /*
846 I might have to rethink this closing tag enforcer for complex mode, have to think the
847 flow out a bit more, this section one is plain wrong, im leaving it here so i won't
848 forget and be tempted to put it back in :-)
849 if (j == section_fcLim)
850 {
851 wvHandleElement(ps, SECTIONEND, (void*)&sep,section_dirty);
852 section_pendingclose=0;
853 }
854 */
855 #endif
856 }
857
858 finish_processing:
859 if (char_pendingclose)
860 {
861 wvInitCHP (&achp);
862 wvHandleElement (ps, CHARPROPEND, (void *) &achp, char_dirty);
863 }
864
865 if (comment_pendingclose)
866 wvHandleElement (ps, COMMENTEND, (void *) catrd, 0);
867
868 if (para_pendingclose)
869 {
870 wvInitPAP (&apap);
871 wvHandleElement (ps, PARAEND, (void *) &apap, para_dirty);
872 }
873
874 if (section_pendingclose)
875 wvHandleElement (ps, SECTIONEND, (void *) &sep, section_dirty);
876
877 wvFree (ps->fspa);
878 wvFree (ps->fspapos);
879 wvFree (ps->fdoa);
880 wvFree (ps->fdoapos);
881
882 wvFree (posBKL);
883 wvFree (bkl);
884 wvFree (posBKF);
885 wvFree (bkf);
886 wvFree (posAtrd);
887 wvFree (atrd);
888
889 wvReleasePAPX_FKP (¶_fkp);
890 wvReleaseCHPX_FKP (&char_fkp);
891
892 wvHandleDocument (ps, DOCEND);
893 wvFree (posSedx);
894 wvFree (sed);
895
896 wvFree (ps->liststartnos);
897 wvFree (ps->listnfcs);
898 for (i = 0; i < 9 * ps->nolfo; i++)
899 wvReleaseLVL (&(ps->finallvl[i]));
900 wvFree (ps->finallvl);
901
902 wvReleaseLST (&ps->lst, ps->noofLST);
903 wvReleaseLFO_records (&ps->lfo, &ps->lfolvl, &ps->lvl, ps->nooflvl);
904 wvReleaseSTTBF (&ps->anSttbfAssoc);
905
906 wvFree (btePapx);
907 wvFree (posPapx);
908 wvFree (bteChpx);
909 wvFree (posChpx);
910 wvReleaseCLX (&ps->clx);
911 wvReleaseFFN_STTBF (&ps->fonts);
912 wvReleaseSTSH (&ps->stsh);
913 wvReleaseSTTBF (&SttbfAtnbkmk);
914 wvReleaseSTTBF (&grpXstAtnOwners);
915 if (ps->vmerges)
916 {
917 for (i = 0; i < ps->norows; i++)
918 wvFree (ps->vmerges[i]);
919 wvFree (ps->vmerges);
920 }
921 wvFree (ps->cellbounds);
922 wvOLEFree(ps);
923 tokenTreeFreeAll ();
924 }
925
926 /*
927 The process thus far has created a SEP that describes what the section properties of
928 the section at the last full save.
929
930 1) Now apply any section sprms that were linked to the piece that contains the
931 section's section mark.
932
933 2) If pcd.prm.fComplex is 0, pcd.prm contains 1 sprm which should be applied to
934 the local SEP if it is a section sprm.
935
936 3) If pcd.prm.fComplex is 1, pcd.prm.igrpprl is the index of a grpprl in the CLX.
937 If that grpprl contains any section sprms, they should be applied to the local SEP
938 */
939 int
wvGetComplexSEP(wvVersion ver,SEP * sep,U32 cpiece,STSH * stsh,CLX * clx)940 wvGetComplexSEP (wvVersion ver, SEP * sep, U32 cpiece, STSH * stsh, CLX * clx)
941 {
942 int ret = 0;
943 U16 sprm, pos = 0, i = 0;
944 U8 *pointer;
945 U16 index;
946 U8 val;
947 Sprm RetSprm;
948
949 if (clx->pcd[cpiece].prm.fComplex == 0)
950 {
951 val = clx->pcd[cpiece].prm.para.var1.val;
952 pointer = &val;
953 #ifdef SPRMTEST
954 wvError (("singleton\n", clx->pcd[cpiece].prm.para.var1.isprm));
955 #endif
956 RetSprm =
957 wvApplySprmFromBucket (ver,
958 (U16) wvGetrgsprmPrm ( (U16) clx->pcd[cpiece].prm.
959 para.var1.isprm), NULL,
960 NULL, sep, stsh, pointer, &pos, NULL);
961 if (RetSprm.sgc == sgcSep)
962 ret = 1;
963 }
964 else
965 {
966 index = clx->pcd[cpiece].prm.para.var2.igrpprl;
967 #ifdef SPRMTEST
968 fprintf (stderr, "\n");
969 while (i < clx->cbGrpprl[index])
970 {
971 fprintf (stderr, "%x (%d)\n", *(clx->grpprl[index] + i),
972 *(clx->grpprl[index] + i));
973 i++;
974 }
975 fprintf (stderr, "\n");
976 i = 0;
977 #endif
978 while (i < clx->cbGrpprl[index])
979 {
980 if (ver == WORD8)
981 sprm = bread_16ubit (clx->grpprl[index] + i, &i);
982 else
983 {
984 sprm = bread_8ubit (clx->grpprl[index] + i, &i);
985 sprm = (U8) wvGetrgsprmWord6 ( (U8) sprm);
986 }
987 pointer = clx->grpprl[index] + i;
988 RetSprm =
989 wvApplySprmFromBucket (ver, sprm, NULL, NULL, sep, stsh,
990 pointer, &i, NULL);
991 if (RetSprm.sgc == sgcSep)
992 ret = 1;
993 }
994 }
995 return (ret);
996 }
997
998 /*
999 The process thus far has created a PAP that describes
1000 what the paragraph properties of the paragraph were at the last full save.
1001
1002 1) Now it's necessary to apply any paragraph sprms that were linked to the
1003 piece that contains the paragraph's paragraph mark.
1004
1005 2) If pcd.prm.fComplex is 0, pcd.prm contains 1 sprm which should only be
1006 applied to the local PAP if it is a paragraph sprm.
1007
1008 3) If pcd.prm.fComplex is 1, pcd.prm.igrpprl is the index of a grpprl in the
1009 CLX. If that grpprl contains any paragraph sprms, they should be applied to
1010 the local PAP.
1011 */
1012 int
wvAssembleComplexPAP(wvVersion ver,PAP * apap,U32 cpiece,wvParseStruct * ps)1013 wvAssembleComplexPAP (wvVersion ver, PAP * apap, U32 cpiece, wvParseStruct *ps)
1014 {
1015 int ret = 0;
1016 U16 sprm, pos = 0, i = 0;
1017 U8 sprm8;
1018 U8 *pointer;
1019 U16 index;
1020 U8 val;
1021 Sprm RetSprm;
1022
1023 if (ps->clx.pcd[cpiece].prm.fComplex == 0)
1024 {
1025 val = ps->clx.pcd[cpiece].prm.para.var1.val;
1026 pointer = &val;
1027 #ifdef SPRMTEST
1028 wvError (("singleton\n", ps->clx.pcd[cpiece].prm.para.var1.isprm));
1029 #endif
1030 RetSprm =
1031 wvApplySprmFromBucket (ver,
1032 (U16) wvGetrgsprmPrm ( (U16) ps->clx.pcd[cpiece].prm.
1033 para.var1.isprm), apap,
1034 NULL, NULL, &ps->stsh, pointer, &pos, ps->data);
1035 if (RetSprm.sgc == sgcPara)
1036 ret = 1;
1037 }
1038 else
1039 {
1040 index = ps->clx.pcd[cpiece].prm.para.var2.igrpprl;
1041 #ifdef SPRMTEST
1042 wvError (("HERE-->\n"));
1043 fprintf (stderr, "\n");
1044 for (i = 0; i < ps->clx.cbGrpprl[index]; i++)
1045 fprintf (stderr, "%x ", *(ps->clx.grpprl[index] + i));
1046 fprintf (stderr, "\n");
1047 i = 0;
1048 #endif
1049 while (i < ps->clx.cbGrpprl[index])
1050 {
1051 if (ver == WORD8)
1052 sprm = bread_16ubit (ps->clx.grpprl[index] + i, &i);
1053 else
1054 {
1055 sprm8 = bread_8ubit (ps->clx.grpprl[index] + i, &i);
1056 sprm = (U16) wvGetrgsprmWord6 (sprm8);
1057 wvTrace (("sprm is %x\n", sprm));
1058 }
1059 pointer = ps->clx.grpprl[index] + i;
1060 RetSprm =
1061 wvApplySprmFromBucket (ver, sprm, apap, NULL, NULL, &ps->stsh,
1062 pointer, &i, ps->data);
1063 if (RetSprm.sgc == sgcPara)
1064 ret = 1;
1065 }
1066 }
1067 return (ret);
1068 }
1069
1070 /* CHP version of the above. follows the same rules -JB */
1071 int
wvAssembleComplexCHP(wvVersion ver,CHP * achp,U32 cpiece,STSH * stsh,CLX * clx)1072 wvAssembleComplexCHP (wvVersion ver, CHP * achp, U32 cpiece, STSH * stsh,
1073 CLX * clx)
1074 {
1075 int ret = 0;
1076 U16 sprm, pos = 0, i = 0;
1077 U8 sprm8;
1078 U8 *pointer;
1079 U16 index;
1080 U8 val;
1081 Sprm RetSprm;
1082
1083 if (clx->pcd[cpiece].prm.fComplex == 0)
1084 {
1085 val = clx->pcd[cpiece].prm.para.var1.val;
1086 pointer = &val;
1087 #ifdef SPRMTEST
1088 wvError (("singleton %d\n", clx->pcd[cpiece].prm.para.var1.isprm));
1089 #endif
1090 RetSprm =
1091 wvApplySprmFromBucket (ver,
1092 (U16) wvGetrgsprmPrm ( (U16) clx->pcd[cpiece].prm.
1093 para.var1.isprm), NULL,
1094 achp, NULL, stsh, pointer, &pos, NULL);
1095 if (RetSprm.sgc == sgcChp)
1096 ret = 1;
1097 }
1098 else
1099 {
1100 index = clx->pcd[cpiece].prm.para.var2.igrpprl;
1101 #ifdef SPRMTEST
1102 fprintf (stderr, "\n");
1103 for (i = 0; i < clx->cbGrpprl[index]; i++)
1104 fprintf (stderr, "%x ", *(clx->grpprl[index] + i));
1105 fprintf (stderr, "\n");
1106 i = 0;
1107 #endif
1108 while (i < clx->cbGrpprl[index])
1109 {
1110 if (ver == WORD8)
1111 sprm = bread_16ubit (clx->grpprl[index] + i, &i);
1112 else
1113 {
1114 sprm8 = bread_8ubit (clx->grpprl[index] + i, &i);
1115 sprm = (U16) wvGetrgsprmWord6 (sprm8);
1116 }
1117 pointer = clx->grpprl[index] + i;
1118 RetSprm =
1119 wvApplySprmFromBucket (ver, sprm, NULL, achp, NULL, stsh,
1120 pointer, &i, NULL);
1121 if (RetSprm.sgc == sgcChp)
1122 ret = 1;
1123 }
1124 }
1125 return (ret);
1126 }
1127