1 /************************************************************************/
2 /*									*/
3 /*  Buffer administration routines.					*/
4 /*									*/
5 /************************************************************************/
6 
7 #   include	"docBaseConfig.h"
8 
9 #   include	<stdlib.h>
10 
11 #   include	<appDebugon.h>
12 
13 #   include	"docRowProperties.h"
14 #   include	"docPropVal.h"
15 
16 /************************************************************************/
17 
18 static const int DocRowIntProperties[]=
19 {
20     RPpropGAP_WIDTH,
21     RPpropLEFT_INDENT,
22     RPpropHEIGHT,
23     RPpropALIGNMENT,
24     RPpropIS_TABLE_HEADER,
25     RPpropKEEP_ON_ONE_PAGE,
26     RPprop_KEEPFOLLOW,
27     RPpropAUTOFIT,
28     RPpropRTOL,
29     RPpropTRW_WIDTH,
30     RPpropTRFTS_WIDTH,
31     RPpropTRSPDL,
32     RPpropTRSPDR,
33     RPpropTRSPDT,
34     RPpropTRSPDB,
35     RPpropTRSPDFL,
36     RPpropTRSPDFR,
37     RPpropTRSPDFT,
38     RPpropTRSPDFB,
39     RPpropTRPADDL,
40     RPpropTRPADDR,
41     RPpropTRPADDT,
42     RPpropTRPADDB,
43     RPpropTRPADDFL,
44     RPpropTRPADDFR,
45     RPpropTRPADDFT,
46     RPpropTRPADDFB,
47     RPpropTRW_WIDTHB,
48     RPpropTRW_WIDTHA,
49     RPpropTRFTS_WIDTHB,
50     RPpropTRFTS_WIDTHA,
51 };
52 
53 static const int DocRowIntPropertyCount=
54 				sizeof(DocRowIntProperties)/sizeof(int);
55 
56 static const int DocRowBorderProperties[]=
57 {
58     RPpropTOP_BORDER,
59     RPpropBOTTOM_BORDER,
60     RPpropLEFT_BORDER,
61     RPpropRIGHT_BORDER,
62     RPpropHORIZ_BORDER,
63     RPpropVERT_BORDER,
64 };
65 
66 static const int DocRowBorderPropertyCount=
67 				sizeof(DocRowBorderProperties)/sizeof(int);
68 
69 /************************************************************************/
70 /*									*/
71 /*  Initialise row properties.						*/
72 /*									*/
73 /************************************************************************/
74 
docCleanRowProperties(RowProperties * rp)75 void docCleanRowProperties(	RowProperties *	rp )
76     {
77     if  ( rp->rpCells )
78 	{ free( rp->rpCells );	}
79     }
80 
docInitRowProperties(RowProperties * rp)81 void docInitRowProperties(	RowProperties *	rp )
82     {
83     rp->rpCellCount= 0;
84     rp->rpCells= (CellProperties *)0;
85 
86     rp->rpHalfGapWidthTwips= 0;
87     rp->rpHeightTwips= 0;
88     rp->rpLeftIndentTwips= 0;
89 
90     rp->rpIsTableHeader= 0;
91     rp->rpKeepOnOnePage= 0;
92     rp->rp_Keepfollow= 0;
93     rp->rpAutofit= 0;
94     rp->rpRToL= 0;
95 
96     rp->rpTopBorderNumber= 0;
97     rp->rpBottomBorderNumber= 0;
98     rp->rpLeftBorderNumber= 0;
99     rp->rpRightBorderNumber= 0;
100     rp->rpHorizontalBorderNumber= 0;
101     rp->rpVerticalBorderNumber= 0;
102 
103     rp->rpShadingNumber= 0;
104     rp->rpFrameNumber= 0;
105 
106     rp->rpAlignment= DOCthaLEFT;
107 
108     /**/
109     rp->rpPreferredWidth= 0;
110     rp->rpPreferredWidthUnit= TRautoNONE;
111 
112     /**/
113     rp->rpLeftDefaultCellSpacing= 0;
114     rp->rpRightDefaultCellSpacing= 0;
115     rp->rpTopDefaultCellSpacing= 0;
116     rp->rpBottomDefaultCellSpacing= 0;
117 
118     rp->rpLeftDefaultCellSpacingUnit= TRautoNONE;
119     rp->rpRightDefaultCellSpacingUnit= TRautoNONE;
120     rp->rpTopDefaultCellSpacingUnit= TRautoNONE;
121     rp->rpBottomDefaultCellSpacingUnit= TRautoNONE;
122 
123     /**/
124     rp->rpLeftCellPadding= 0;
125     rp->rpRightCellPadding= 0;
126     rp->rpTopCellPadding= 0;
127     rp->rpBottomCellPadding= 0;
128 
129     rp->rpLeftCellPaddingUnit= TRautoNONE;
130     rp->rpRightCellPaddingUnit= TRautoNONE;
131     rp->rpTopCellPaddingUnit= TRautoNONE;
132     rp->rpBottomCellPaddingUnit= TRautoNONE;
133 
134     /**/
135     rp->rpCellWidthBefore= 0;
136     rp->rpCellWidthAfter= 0;
137 
138     rp->rpCellWidthBeforeUnit= TRautoNONE;
139     rp->rpCellWidthAfterUnit= TRautoNONE;
140 
141     /**/
142     rp->rpRowNumber= -1;
143     rp->rpRowBandNumber= -1;
144     rp->rpRowStyle= -1;
145 
146     rp->rpIsLastRow= 0;
147     rp->rpAuthor= -1;
148 
149     return;
150     }
151 
152 /************************************************************************/
153 /*									*/
154 /*  Insert the description of a column into those for a row.		*/
155 /*									*/
156 /*  If we are asked to shift the columns to the right, shift them by	*/
157 /*  the width of the new column. I.E. Its new right hand position minus	*/
158 /*  the left hand position of the first cell that it will push to the	*/
159 /*  right. This value is not influenced by the operation.		*/
160 /*									*/
161 /************************************************************************/
162 
docInsertRowColumn(RowProperties * rp,int col,int shiftTail,const CellProperties * cp,const DocumentAttributeMap * dam)163 int docInsertRowColumn(	RowProperties *			rp,
164 			int				col,
165 			int				shiftTail,
166 			const CellProperties *		cp,
167 			const DocumentAttributeMap *	dam )
168     {
169     int			i;
170     CellProperties *	fresh;
171     int			shiftTailBy= 0;
172 
173     fresh= (CellProperties *)realloc( rp->rpCells,
174 			(rp->rpCellCount+ 1)* sizeof(CellProperties) );
175     if  ( ! fresh )
176 	{ LXDEB(rp->rpCellCount,fresh); return -1;	}
177     rp->rpCells= fresh;
178 
179     if  ( col < 0 )
180 	{ col= rp->rpCellCount;	}
181 
182     if  ( col < rp->rpCellCount && shiftTail )
183 	{
184 	shiftTailBy= cp->cpRightBoundaryTwips- docColumnLeft( rp, col );
185 	}
186 
187     for ( i= rp->rpCellCount; i > col; i-- )
188 	{
189 	docCopyCellProperties( fresh+ i, fresh+ i- 1, dam );
190 	fresh[i].cpRightBoundaryTwips += shiftTailBy;
191 	}
192 
193     docInitCellProperties( fresh+ col );
194     docCopyCellProperties( fresh+ col, cp, dam );
195 
196     rp->rpCellCount++;
197 
198     return 0;
199     }
200 
201 /************************************************************************/
202 /*									*/
203 /*  Make a column wider (or narrower).					*/
204 /*									*/
205 /************************************************************************/
206 
docRowPropertiesMakeColWider(RowProperties * rp,int col,int wider)207 int docRowPropertiesMakeColWider(	RowProperties *		rp,
208 					int			col,
209 					int			wider )
210     {
211     int			i;
212     CellProperties *	cp;
213 
214     if  ( col < 0 || col >= rp->rpCellCount )
215 	{ LLDEB(col,rp->rpCellCount); return -1;	}
216 
217     cp= rp->rpCells+ col;
218     for ( i= col; i < rp->rpCellCount; cp++, i++ )
219 	{ cp->cpRightBoundaryTwips += wider;	}
220 
221     return 0;
222     }
223 
224 /************************************************************************/
225 /*									*/
226 /*  Set the width of a range of columns. Space might have been stolen	*/
227 /*  from a victim column that has become narrower. Also adjust its	*/
228 /*  width.								*/
229 /*									*/
230 /************************************************************************/
231 
docRowPropertiesSetWidth(RowProperties * rp,int col0,int col1,int wide,int victim,int victimWide)232 void docRowPropertiesSetWidth(		RowProperties *		rp,
233 					int			col0,
234 					int			col1,
235 					int			wide,
236 					int			victim,
237 					int			victimWide )
238     {
239     CellProperties *	cp;
240     int			col;
241 
242     int			ox0= rp->rpLeftIndentTwips;
243     int			nx0= rp->rpLeftIndentTwips;
244 
245     cp= rp->rpCells;
246     for ( col= 0; col < col0; cp++, col++ )
247 	{
248 	int		ox1= cp->cpRightBoundaryTwips;
249 	int		w= cp->cpRightBoundaryTwips- ox0;
250 
251 	if  ( col == victim )
252 	    { w= victimWide;	}
253 
254 	ox0= ox1;
255 	nx0= cp->cpRightBoundaryTwips= nx0+ w;
256 	}
257 
258     for ( col= col0; col <= col1; cp++, col++ )
259 	{
260 	int		ox1= cp->cpRightBoundaryTwips;
261 
262 	ox0= ox1;
263 	nx0= cp->cpRightBoundaryTwips= nx0+ wide;
264 	}
265 
266     for ( col= col1+ 1; col < rp->rpCellCount; cp++, col++ )
267 	{
268 	int		ox1= cp->cpRightBoundaryTwips;
269 	int		w= cp->cpRightBoundaryTwips- ox0;
270 
271 	if  ( col == victim )
272 	    { w= victimWide;	}
273 
274 	ox0= ox1;
275 	nx0= cp->cpRightBoundaryTwips= nx0+ w;
276 	}
277 
278     return;
279     }
280 
281 /************************************************************************/
282 /*									*/
283 /*  Calculate the width of a column.					*/
284 /*  Calculate the left hand side coordinate.				*/
285 /*  Calculate the right hand side coordinate.				*/
286 /*									*/
287 /************************************************************************/
288 
docColumnWidth(const RowProperties * rp,int col)289 int docColumnWidth(		const RowProperties *	rp,
290 				int			col )
291     {
292     int		left;
293 
294     if  ( col < 0 || col >= rp->rpCellCount )
295 	{ LLDEB(col,rp->rpCellCount); return -1;	}
296 
297     if  ( col == 0 )
298 	{ left= rp->rpLeftIndentTwips;				}
299     else{ left= rp->rpCells[col-1].cpRightBoundaryTwips;	}
300 
301     return rp->rpCells[col].cpRightBoundaryTwips- left;
302     }
303 
docColumnLeft(const RowProperties * rp,int col)304 int docColumnLeft(		const RowProperties *	rp,
305 				int			col )
306     {
307     if  ( col == 0 )
308 	{ return rp->rpLeftIndentTwips;			}
309     else{
310 	if  ( col <= 0 || col > rp->rpCellCount )
311 	    { LLDEB(col,rp->rpCellCount); return -1;	}
312 
313 	return rp->rpCells[col-1].cpRightBoundaryTwips;
314 	}
315     }
316 
docColumnRight(const RowProperties * rp,int col)317 int docColumnRight(		const RowProperties *	rp,
318 				int			col )
319     {
320     if  ( col < 0 || col >= rp->rpCellCount )
321 	{ LLDEB(col,rp->rpCellCount); return -1;	}
322 
323     return rp->rpCells[col].cpRightBoundaryTwips;
324     }
325 
docCellRight(int * pColspan,const RowProperties * rp,int col)326 int docCellRight(	int *			pColspan,
327 			const RowProperties *	rp,
328 			int			col )
329     {
330     int				colspan= 1;
331     const CellProperties *	cp= rp->rpCells+ col;
332     int				right= cp->cpRightBoundaryTwips;
333 
334     if  ( cp->cpHorizontalMerge == CELLmergeHEAD )
335 	{
336 	int		c;
337 
338 	for ( c= col+ 1; c < rp->rpCellCount; c++ )
339 	    {
340 	    if  ( rp->rpCells[c].cpHorizontalMerge != CELLmergeFOLLOW )
341 		{ break;	}
342 
343 	    colspan++;
344 	    right= rp->rpCells[c].cpRightBoundaryTwips;
345 	    }
346 	}
347 
348     *pColspan= colspan;
349     return right;
350     }
351 
352 /************************************************************************/
353 /*									*/
354 /*  Delete a number of columns from row properties.			*/
355 /*									*/
356 /************************************************************************/
357 
docDeleteColumnsFromRow(RowProperties * rp,int col0,int count,int shiftTail)358 int docDeleteColumnsFromRow(	RowProperties *		rp,
359 				int			col0,
360 				int			count,
361 				int			shiftTail )
362     {
363     int		col1= col0+ count- 1;
364     int		shiftBy= 0;
365     int		col;
366 
367     if  ( col0+ count > rp->rpCellCount )
368 	{ LLLDEB(col0,count,rp->rpCellCount); return -1;	}
369 
370     if  ( shiftTail )
371 	{
372 	int	left= docColumnLeft( rp, col0 );
373 
374 	shiftBy= rp->rpCells[col1].cpRightBoundaryTwips- left;
375 	}
376 
377     rp->rpCellCount -= count;
378 
379     for ( col= col0; col < rp->rpCellCount; col++ )
380 	{
381 	docCleanCellProperties( &(rp->rpCells[col]) );
382 	rp->rpCells[col]= rp->rpCells[col+ count];
383 	rp->rpCells[col].cpRightBoundaryTwips -= shiftBy;
384 	}
385 
386     return 0;
387     }
388 
389 /************************************************************************/
390 
docRowMaskToCellMask(PropertyMask * cellMask,const PropertyMask * rowMask)391 void docRowMaskToCellMask(	PropertyMask *		cellMask,
392 				const PropertyMask *	rowMask )
393     {
394     utilPropMaskClear( cellMask );
395 
396     if  ( PROPmaskISSET( rowMask, RPpropCELL_PROPS ) )
397 	{ utilPropMaskFill( cellMask, CLprop_COUNT );	}
398 
399     if  ( PROPmaskISSET( rowMask, RPpropCELL_LAYOUT ) )
400 	{ PROPmaskADD( cellMask, CLpropCELLX );	}
401     else{ PROPmaskUNSET( cellMask, CLpropCELLX );	}
402 
403     return;
404     }
405 
docRowMaskApplyCellMask(PropertyMask * rowMask,const PropertyMask * cellMask)406 void docRowMaskApplyCellMask(	PropertyMask *		rowMask,
407 				const PropertyMask *	cellMask )
408     {
409     if  ( cellMask && ! utilPropMaskIsEmpty( cellMask ) )
410 	{
411 	PropertyMask	cellMaskCopy= *cellMask;
412 
413 	if  ( PROPmaskISSET( &cellMaskCopy, CLpropCELLX ) )
414 	    {
415 	    PROPmaskADD( rowMask, RPpropCELL_LAYOUT );
416 	    PROPmaskUNSET( &cellMaskCopy, CLpropCELLX );
417 	    }
418 
419 	if  ( ! utilPropMaskIsEmpty( &cellMaskCopy ) )
420 	    { PROPmaskADD( rowMask, RPpropCELL_PROPS );	}
421 	}
422 
423     return;
424     }
425 
426 /************************************************************************/
427 /*									*/
428 /*  Compare row properties.						*/
429 /*									*/
430 /************************************************************************/
431 
docRowPropertyDifference(PropertyMask * pRpDifPask,const RowProperties * rp1,const PropertyMask * rpCmpMask,const RowProperties * rp2,const DocumentAttributeMap * dam)432 void docRowPropertyDifference(	PropertyMask *			pRpDifPask,
433 				const RowProperties *		rp1,
434 				const PropertyMask *		rpCmpMask,
435 				const RowProperties *		rp2,
436 				const DocumentAttributeMap *	dam )
437     {
438     int				p;
439     PropertyMask		rpDifMask;
440 
441     utilPropMaskClear( &rpDifMask );
442 
443     if  ( PROPmaskISSET( rpCmpMask, RPpropCELL_LAYOUT )	||
444 	  PROPmaskISSET( rpCmpMask, RPpropCELL_PROPS )	)
445 	{
446 	int			col;
447 	const CellProperties *	cp1;
448 	const CellProperties *	cp2;
449 
450 	if  ( rp1->rpCellCount != rp2->rpCellCount )
451 	    {
452 	    PROPmaskADD( &rpDifMask, RPpropCELL_LAYOUT );
453 	    PROPmaskADD( &rpDifMask, RPpropCELL_PROPS );
454 	    }
455 
456 	cp1= rp1->rpCells;
457 	cp2= rp2->rpCells;
458 	for ( col= 0; col < rp1->rpCellCount && col < rp2->rpCellCount; cp1++, cp2++, col++ )
459 	    {
460 	    PropertyMask	cpCmpMask;
461 	    PropertyMask	cpDifMask;
462 
463 	    docRowMaskToCellMask( &cpCmpMask, rpCmpMask );
464 	    utilPropMaskClear( &cpDifMask );
465 
466 	    docCellPropertyDifference( &cpDifMask, cp1, &cpCmpMask, cp2, dam );
467 	    docRowMaskApplyCellMask( &rpDifMask, &cpDifMask );
468 	    }
469 	}
470 
471     for ( p= 0; p < DocRowIntPropertyCount; p++ )
472 	{
473 	int	prop= DocRowIntProperties[p];
474 
475 	if  ( PROPmaskISSET( rpCmpMask, prop ) )
476 	    {
477 	    int		val1= docGetRowProperty( rp1, prop );
478 	    int		val2= docGetRowProperty( rp2, prop );
479 
480 	    if  ( val1 != val2 )
481 		{ PROPmaskADD( &rpDifMask, prop );	}
482 	    }
483 	}
484 
485     for ( p= 0; p < DocRowBorderPropertyCount; p++ )
486 	{
487 	int	prop= DocRowBorderProperties[p];
488 
489 	if  ( PROPmaskISSET( rpCmpMask, prop ) )
490 	    {
491 	    int		val1= docGetRowProperty( rp1, prop );
492 	    int		val2= docGetRowProperty( rp2, prop );
493 
494 	    if  ( val2 >= 0 && dam && dam->damBorderMap )
495 		{ val2= dam->damBorderMap[val2];	}
496 
497 	    if  ( val1 != val2 )
498 		{ PROPmaskADD( &rpDifMask, prop );	}
499 	    }
500 	}
501 
502     /**/
503     if  ( PROPmaskISSET( rpCmpMask, RPpropSHADING ) )
504 	{
505 	int	fromNumber= rp2->rpShadingNumber;
506 
507 	if  ( fromNumber >= 0 && dam && dam->damShadingMap )
508 	    { fromNumber= dam->damShadingMap[fromNumber];	}
509 
510 	if  ( rp1->rpShadingNumber != fromNumber )
511 	    { PROPmaskADD( &rpDifMask, RPpropSHADING );	}
512 	}
513 
514     if  ( PROPmaskISSET( rpCmpMask, RPpropFRAME ) )
515 	{
516 	int	fromNumber= rp2->rpFrameNumber;
517 
518 	if  ( fromNumber >= 0 && dam && dam->damFrameMap )
519 	    { fromNumber= dam->damFrameMap[fromNumber];	}
520 
521 	if  ( rp1->rpFrameNumber != fromNumber )
522 	    { PROPmaskADD( &rpDifMask, RPpropFRAME );	}
523 	}
524 
525     *pRpDifPask= rpDifMask; return;
526     }
527 
528 /************************************************************************/
529 /*									*/
530 /*  Copy row properties. As this routine is not called very often,	*/
531 /*  just call the 'update' routine.					*/
532 /*									*/
533 /************************************************************************/
534 
docCopyRowProperties(RowProperties * rpTo,const RowProperties * rpFrom,const DocumentAttributeMap * dam)535 int docCopyRowProperties(	RowProperties *			rpTo,
536 				const RowProperties *		rpFrom,
537 				const DocumentAttributeMap *	dam )
538     {
539     PropertyMask		rpDoneMask;
540     PropertyMask		rpSetMask;
541 
542     utilPropMaskClear( &rpDoneMask );
543     utilPropMaskClear( &rpSetMask );
544 
545     utilPropMaskFill( &rpSetMask, RPprop_FULL_COUNT );
546 
547     if  ( docUpdRowProperties( &rpDoneMask, rpTo, &rpSetMask, rpFrom, dam ) )
548 	{ LDEB(1); return -1;	}
549 
550     return 0;
551     }
552 
553 /************************************************************************/
554 /*									*/
555 /*  1)  Are the columns in two RowProperties 'the same' (Do they	*/
556 /*	align?)								*/
557 /*  2)  All internal borders equal?					*/
558 /*  3)  All column properties identical?				*/
559 /*									*/
560 /************************************************************************/
561 
562 /*  1  */
docApproximatelyAlignedColumns(const RowProperties * rp1,const RowProperties * rp2)563 int docApproximatelyAlignedColumns(	const RowProperties *	rp1,
564 					const RowProperties *	rp2 )
565     {
566     CellProperties *	cp1;
567     CellProperties *	cp2;
568     int			i;
569 
570     const int		D= 40;
571 
572     if  ( rp1->rpCellCount != rp2->rpCellCount )
573 	{ return 0;	}
574 
575     /* No!
576     if  ( rp1->rpHalfGapWidthTwips != rp2->rpHalfGapWidthTwips )
577 	{ return 0;	}
578     */
579 
580     if  ( rp1->rpLeftIndentTwips > rp2->rpLeftIndentTwips+ D	||
581 	  rp1->rpLeftIndentTwips < rp2->rpLeftIndentTwips- D	)
582 	{ return 0;	}
583 
584     cp1= rp1->rpCells;
585     cp2= rp2->rpCells;
586     for ( i= 0; i < rp1->rpCellCount; cp2++, cp1++, i++ )
587 	{
588 	if  ( cp1->cpRightBoundaryTwips > cp2->cpRightBoundaryTwips+ D	||
589 	      cp1->cpRightBoundaryTwips < cp2->cpRightBoundaryTwips- D	)
590 	    { return 0;	}
591 	}
592 
593     return 1;
594     }
595 
596 /************************************************************************/
597 /*									*/
598 /*  Change row properties and tell what has been changed.		*/
599 /*									*/
600 /************************************************************************/
601 
docUpdRowProperties(PropertyMask * pRpDonePask,RowProperties * rpTo,const PropertyMask * rpSetMask,const RowProperties * rpFrom,const DocumentAttributeMap * dam)602 int docUpdRowProperties(	PropertyMask *			pRpDonePask,
603 				RowProperties *			rpTo,
604 				const PropertyMask *		rpSetMask,
605 				const RowProperties *		rpFrom,
606 				const DocumentAttributeMap *	dam )
607     {
608     int			p;
609     PropertyMask	rpDoneMask;
610 
611     int			updCellLayout;
612     int			updCellProps;
613 
614     updCellLayout= PROPmaskISSET( rpSetMask, RPpropCELL_LAYOUT );
615     updCellProps= PROPmaskISSET( rpSetMask, RPpropCELL_PROPS );
616 
617     utilPropMaskClear( &rpDoneMask );
618 
619     if  ( updCellLayout || updCellProps )
620 	{
621 	int			col;
622 	CellProperties *	cpTo;
623 	const CellProperties *	cpFrom;
624 
625 	if  ( updCellLayout )
626 	    {
627 	    while( rpTo->rpCellCount > rpFrom->rpCellCount )
628 		{
629 		docCleanCellProperties( &(rpTo->rpCells[rpTo->rpCellCount-1]) );
630 		PROPmaskADD( &rpDoneMask, RPpropCELL_LAYOUT );
631 		if  ( updCellProps )
632 		    { PROPmaskADD( &rpDoneMask, RPpropCELL_PROPS );	}
633 		rpTo->rpCellCount--;
634 		}
635 	    }
636 
637 	cpTo= rpTo->rpCells;
638 	cpFrom= rpFrom->rpCells;
639 	for ( col= 0;
640 	      col < rpTo->rpCellCount && col < rpFrom->rpCellCount;
641 	      cpTo++, cpFrom++, col++ )
642 	    {
643 	    PropertyMask	cpSetMask;
644 	    PropertyMask	cpDoneMask;
645 
646 	    docRowMaskToCellMask( &cpSetMask, rpSetMask );
647 	    utilPropMaskClear( &cpDoneMask );
648 
649 	    if  ( docUpdCellProperties( &cpDoneMask, cpTo,
650 						&cpSetMask, cpFrom, dam ) )
651 		{ LDEB(1); return -1;	}
652 
653 	    docRowMaskApplyCellMask( &rpDoneMask, &cpDoneMask );
654 	    }
655 
656 	if  ( updCellLayout )
657 	    {
658 	    while( rpTo->rpCellCount < rpFrom->rpCellCount )
659 		{
660 		const int	shiftTail= 0; /* at end: irrelevant */
661 
662 		if  ( docInsertRowColumn( rpTo, rpTo->rpCellCount, shiftTail,
663 								cpFrom, dam ) )
664 		    { LDEB(rpTo->rpCellCount); return -1;	}
665 
666 		PROPmaskADD( &rpDoneMask, RPpropCELL_LAYOUT );
667 		if  ( updCellProps )
668 		    { PROPmaskADD( &rpDoneMask, RPpropCELL_PROPS );	}
669 		cpFrom++;
670 		}
671 	    }
672 	}
673 
674     for ( p= 0; p < DocRowIntPropertyCount; p++ )
675 	{
676 	int	prop= DocRowIntProperties[p];
677 
678 	if  ( PROPmaskISSET( rpSetMask, prop ) )
679 	    {
680 	    int		valt= docGetRowProperty( rpTo, prop );
681 	    int		valf= docGetRowProperty( rpFrom, prop );
682 
683 	    if  ( valt != valf )
684 		{
685 		if  ( docSetRowProperty( rpTo, prop, valf ) )
686 		    { LLDEB(prop,valf); return -1;	}
687 
688 		PROPmaskADD( &rpDoneMask, prop );
689 		}
690 	    }
691 	}
692 
693     for ( p= 0; p < DocRowBorderPropertyCount; p++ )
694 	{
695 	int	prop= DocRowBorderProperties[p];
696 
697 	if  ( PROPmaskISSET( rpSetMask, prop ) )
698 	    {
699 	    int		valt= docGetRowProperty( rpTo, prop );
700 	    int		valf= docGetRowProperty( rpFrom, prop );
701 
702 	    if  ( valf >= 0 && dam && dam->damBorderMap )
703 		{ valf= dam->damBorderMap[valf];	}
704 
705 	    if  ( valt != valf )
706 		{
707 		if  ( docSetRowProperty( rpTo, prop, valf ) )
708 		    { LLDEB(prop,valf); return -1;	}
709 
710 		PROPmaskADD( &rpDoneMask, prop );
711 		}
712 	    }
713 	}
714 
715     if  ( PROPmaskISSET( rpSetMask, RPpropSHADING ) )
716 	{
717 	int	fromNumber= rpFrom->rpShadingNumber;
718 
719 	if  ( fromNumber >= 0 && dam && dam->damShadingMap )
720 	    { fromNumber= dam->damShadingMap[fromNumber];	}
721 
722 	if  ( rpTo->rpShadingNumber != fromNumber )
723 	    {
724 	    rpTo->rpShadingNumber= fromNumber;
725 	    PROPmaskADD( &rpDoneMask, RPpropSHADING );
726 	    }
727 	}
728 
729     if  ( PROPmaskISSET( rpSetMask, RPpropFRAME ) )
730 	{
731 	int	fromNumber= rpFrom->rpFrameNumber;
732 
733 	if  ( fromNumber >= 0 && dam && dam->damFrameMap )
734 	    { fromNumber= dam->damFrameMap[fromNumber];	}
735 
736 	if  ( rpTo->rpFrameNumber != fromNumber )
737 	    {
738 	    rpTo->rpFrameNumber= fromNumber;
739 	    PROPmaskADD( &rpDoneMask, RPpropFRAME );
740 	    }
741 	}
742 
743     if  ( pRpDonePask )
744 	{ utilPropMaskOr( pRpDonePask, pRpDonePask, &rpDoneMask );	}
745 
746     return 0;
747     }
748 
749 /************************************************************************/
750 /*									*/
751 /*  Make a kind of 'default' row layout: Evenly distribute the		*/
752 /*  available width over the columns.					*/
753 /*									*/
754 /************************************************************************/
755 
docEqualWidthColumns(RowProperties * rp,int columns,int wide,int fontHalfPoints)756 int docEqualWidthColumns(		RowProperties *		rp,
757 					int			columns,
758 					int			wide,
759 					int			fontHalfPoints )
760     {
761     int				rval= 0;
762     int				col;
763 
764     CellProperties		cp;
765 
766     const int			shiftTail= 0; /* at end: irrelevant */
767 
768     docInitCellProperties( &cp );
769 
770     rp->rpHalfGapWidthTwips= 5* fontHalfPoints;
771     rp->rpLeftIndentTwips=  -5* fontHalfPoints;
772 
773     for ( col= 0; col < columns; col++ )
774 	{
775 	cp.cpRightBoundaryTwips= ( ( col+ 1 )* wide )/ columns;
776 
777 	if  ( docInsertRowColumn( rp, col, shiftTail, &cp,
778 					(const DocumentAttributeMap *)0 ) )
779 	    { LDEB(col); rval= -1; goto ready;	}
780 	}
781 
782   ready:
783     docCleanCellProperties( &cp );
784 
785     return rval;
786     }
787 
docSetRowProperty(RowProperties * rp,int prop,int arg)788 int docSetRowProperty(		RowProperties *		rp,
789 				int			prop,
790 				int			arg )
791     {
792     switch( prop )
793 	{
794 	case RPpropGAP_WIDTH:
795 	    rp->rpHalfGapWidthTwips= arg;
796 	    break;
797 
798 	case RPpropLEFT_INDENT:
799 	    rp->rpLeftIndentTwips= arg;
800 	    break;
801 
802 	case RPpropHEIGHT:
803 	    rp->rpHeightTwips= arg;
804 	    break;
805 
806 	case RPpropTOP_BORDER:
807 	    rp->rpTopBorderNumber= arg;
808 	    break;
809 	case RPpropBOTTOM_BORDER:
810 	    rp->rpBottomBorderNumber= arg;
811 	    break;
812 	case RPpropLEFT_BORDER:
813 	    rp->rpLeftBorderNumber= arg;
814 	    break;
815 	case RPpropRIGHT_BORDER:
816 	    rp->rpRightBorderNumber= arg;
817 	    break;
818 	case RPpropHORIZ_BORDER:
819 	    rp->rpHorizontalBorderNumber= arg;
820 	    break;
821 	case RPpropVERT_BORDER:
822 	    rp->rpVerticalBorderNumber= arg;
823 	    break;
824 
825 	case RPpropSHADING:
826 	    rp->rpShadingNumber= arg;
827 	    break;
828 	case RPpropFRAME:
829 	    rp->rpFrameNumber= arg;
830 	    break;
831 
832 	/**/
833 	case RPpropALIGNMENT:
834 	    rp->rpAlignment= arg;
835 	    break;
836 
837 	case RPpropIS_TABLE_HEADER:
838 	    rp->rpIsTableHeader= ( arg != 0 );
839 	    break;
840 	case RPpropKEEP_ON_ONE_PAGE:
841 	    rp->rpKeepOnOnePage= ( arg != 0 );
842 	    break;
843 	case RPprop_KEEPFOLLOW:
844 	    rp->rp_Keepfollow= ( arg != 0 );
845 	    break;
846 	case RPpropAUTOFIT:
847 	    rp->rpAutofit= ( arg != 0 );
848 	    break;
849 	case RPpropRTOL:
850 	    rp->rpRToL= ( arg != 0 );
851 	    break;
852 
853 	/**/
854 	case RPpropTRW_WIDTH:
855 	    rp->rpPreferredWidth= arg;
856 	    break;
857 	case RPpropTRFTS_WIDTH:
858 	    rp->rpPreferredWidthUnit= arg;
859 	    break;
860 
861 	/**/
862 	case RPpropTRSPDL:
863 	    rp->rpLeftDefaultCellSpacing= arg;
864 	    break;
865 	case RPpropTRSPDR:
866 	    rp->rpRightDefaultCellSpacing= arg;
867 	    break;
868 	case RPpropTRSPDT:
869 	    rp->rpTopDefaultCellSpacing= arg;
870 	    break;
871 	case RPpropTRSPDB:
872 	    rp->rpBottomDefaultCellSpacing= arg;
873 	    break;
874 
875 	case RPpropTRSPDFL:
876 	    rp->rpLeftDefaultCellSpacingUnit= arg;
877 	    break;
878 	case RPpropTRSPDFR:
879 	    rp->rpRightDefaultCellSpacingUnit= arg;
880 	    break;
881 	case RPpropTRSPDFT:
882 	    rp->rpTopDefaultCellSpacingUnit= arg;
883 	    break;
884 	case RPpropTRSPDFB:
885 	    rp->rpBottomDefaultCellSpacingUnit= arg;
886 	    break;
887 
888 	/**/
889 	case RPpropTRPADDL:
890 	    rp->rpLeftCellPadding= arg;
891 	    break;
892 	case RPpropTRPADDR:
893 	    rp->rpRightCellPadding= arg;
894 	    break;
895 	case RPpropTRPADDT:
896 	    rp->rpTopCellPadding= arg;
897 	    break;
898 	case RPpropTRPADDB:
899 	    rp->rpBottomCellPadding= arg;
900 	    break;
901 
902 	case RPpropTRPADDFL:
903 	    rp->rpLeftCellPaddingUnit= arg;
904 	    break;
905 	case RPpropTRPADDFR:
906 	    rp->rpRightCellPaddingUnit= arg;
907 	    break;
908 	case RPpropTRPADDFT:
909 	    rp->rpTopCellPaddingUnit= arg;
910 	    break;
911 	case RPpropTRPADDFB:
912 	    rp->rpBottomCellPaddingUnit= arg;
913 	    break;
914 
915 	/**/
916 	case RPpropTRW_WIDTHB:
917 	    rp->rpCellWidthBefore= arg;
918 	    break;
919 	case RPpropTRW_WIDTHA:
920 	    rp->rpCellWidthAfter= arg;
921 	    break;
922 
923 	case RPpropTRFTS_WIDTHB:
924 	    rp->rpCellWidthBeforeUnit= arg;
925 	    break;
926 	case RPpropTRFTS_WIDTHA:
927 	    rp->rpCellWidthAfterUnit= arg;
928 	    break;
929 
930 	case RPpropAUTOFORMAT_BORDERS:
931 	    rp->rpAutoformatBorders= ( arg != 0 );
932 	    break;
933 	case RPpropAUTOFORMAT_SHADING:
934 	    rp->rpAutoformatShading= ( arg != 0 );
935 	    break;
936 	case RPpropAUTOFORMAT_FONT:
937 	    rp->rpAutoformatFont= ( arg != 0 );
938 	    break;
939 	case RPpropAUTOFORMAT_COLOR:
940 	    rp->rpAutoformatColor= ( arg != 0 );
941 	    break;
942 	case RPpropAUTOFORMAT_APPLY_BEST_FIT:
943 	    rp->rpAutoformatApplyBestFit= ( arg != 0 );
944 	    break;
945 	case RPpropAUTOFORMAT_FIRST_ROW:
946 	    rp->rpAutoformatFirstRow= ( arg != 0 );
947 	    break;
948 	case RPpropAUTOFORMAT_LAST_ROW:
949 	    rp->rpAutoformatLastRow= ( arg != 0 );
950 	    break;
951 	case RPpropAUTOFORMAT_FIRST_COLUMN:
952 	    rp->rpAutoformatFirstColumn= ( arg != 0 );
953 	    break;
954 	case RPpropAUTOFORMAT_LAST_COLUMN:
955 	    rp->rpAutoformatLastColumn= ( arg != 0 );
956 	    break;
957 
958 	case RPpropROW_NUMBER:
959 	    rp->rpRowNumber= arg;
960 	    break;
961 	case RPpropROW_BAND_NUMBER:
962 	    rp->rpRowBandNumber= arg;
963 	    break;
964 	case RPpropROW_STYLE:
965 	    rp->rpRowStyle= arg;
966 	    break;
967 
968 	case RPpropIS_LAST_ROW:
969 	    rp->rpIsLastRow= ( arg != 0 );
970 	    break;
971 
972 	case RPpropTRAUTH:
973 	    rp->rpAuthor= arg;
974 	    break;
975 
976 	case RPpropCELL_LAYOUT:
977 	case RPpropCELL_PROPS:
978 	default:
979 	    LDEB(prop); return -1;
980 	}
981 
982     return 0;
983     }
984 
docGetRowProperty(const RowProperties * rp,int prop)985 int docGetRowProperty(		const RowProperties *	rp,
986 				int			prop )
987     {
988     switch( prop )
989 	{
990 	case RPpropGAP_WIDTH:
991 	    return rp->rpHalfGapWidthTwips;
992 	    break;
993 
994 	case RPpropLEFT_INDENT:
995 	    return rp->rpLeftIndentTwips;
996 	    break;
997 
998 	case RPpropHEIGHT:
999 	    return rp->rpHeightTwips;
1000 	    break;
1001 
1002 	case RPpropTOP_BORDER:
1003 	    return rp->rpTopBorderNumber;
1004 	    break;
1005 	case RPpropBOTTOM_BORDER:
1006 	    return rp->rpBottomBorderNumber;
1007 	    break;
1008 	case RPpropLEFT_BORDER:
1009 	    return rp->rpLeftBorderNumber;
1010 	    break;
1011 	case RPpropRIGHT_BORDER:
1012 	    return rp->rpRightBorderNumber;
1013 	    break;
1014 	case RPpropHORIZ_BORDER:
1015 	    return rp->rpHorizontalBorderNumber;
1016 	    break;
1017 	case RPpropVERT_BORDER:
1018 	    return rp->rpVerticalBorderNumber;
1019 	    break;
1020 
1021 	case RPpropSHADING:
1022 	    return rp->rpShadingNumber;
1023 	    break;
1024 	case RPpropFRAME:
1025 	    return rp->rpFrameNumber;
1026 	    break;
1027 
1028 	/**/
1029 	case RPpropALIGNMENT:
1030 	    return rp->rpAlignment;
1031 	    break;
1032 
1033 	case RPpropIS_TABLE_HEADER:
1034 	    return rp->rpIsTableHeader;
1035 	    break;
1036 	case RPpropKEEP_ON_ONE_PAGE:
1037 	    return rp->rpKeepOnOnePage;
1038 	    break;
1039 	case RPprop_KEEPFOLLOW:
1040 	    return rp->rp_Keepfollow;
1041 	    break;
1042 	case RPpropAUTOFIT:
1043 	    return rp->rpAutofit;
1044 	    break;
1045 	case RPpropRTOL:
1046 	    return rp->rpRToL;
1047 	    break;
1048 
1049 	/**/
1050 	case RPpropTRW_WIDTH:
1051 	    return rp->rpPreferredWidth;
1052 	    break;
1053 	case RPpropTRFTS_WIDTH:
1054 	    return rp->rpPreferredWidthUnit;
1055 	    break;
1056 
1057 	/**/
1058 	case RPpropTRSPDL:
1059 	    return rp->rpLeftDefaultCellSpacing;
1060 	    break;
1061 	case RPpropTRSPDR:
1062 	    return rp->rpRightDefaultCellSpacing;
1063 	    break;
1064 	case RPpropTRSPDT:
1065 	    return rp->rpTopDefaultCellSpacing;
1066 	    break;
1067 	case RPpropTRSPDB:
1068 	    return rp->rpBottomDefaultCellSpacing;
1069 	    break;
1070 
1071 	case RPpropTRSPDFL:
1072 	    return rp->rpLeftDefaultCellSpacingUnit;
1073 	    break;
1074 	case RPpropTRSPDFR:
1075 	    return rp->rpRightDefaultCellSpacingUnit;
1076 	    break;
1077 	case RPpropTRSPDFT:
1078 	    return rp->rpTopDefaultCellSpacingUnit;
1079 	    break;
1080 	case RPpropTRSPDFB:
1081 	    return rp->rpBottomDefaultCellSpacingUnit;
1082 	    break;
1083 
1084 	/**/
1085 	case RPpropTRPADDL:
1086 	    return rp->rpLeftCellPadding;
1087 	    break;
1088 	case RPpropTRPADDR:
1089 	    return rp->rpRightCellPadding;
1090 	    break;
1091 	case RPpropTRPADDT:
1092 	    return rp->rpTopCellPadding;
1093 	    break;
1094 	case RPpropTRPADDB:
1095 	    return rp->rpBottomCellPadding;
1096 	    break;
1097 
1098 	case RPpropTRPADDFL:
1099 	    return rp->rpLeftCellPaddingUnit;
1100 	    break;
1101 	case RPpropTRPADDFR:
1102 	    return rp->rpRightCellPaddingUnit;
1103 	    break;
1104 	case RPpropTRPADDFT:
1105 	    return rp->rpTopCellPaddingUnit;
1106 	    break;
1107 	case RPpropTRPADDFB:
1108 	    return rp->rpBottomCellPaddingUnit;
1109 	    break;
1110 
1111 	/**/
1112 	case RPpropTRW_WIDTHB:
1113 	    return rp->rpCellWidthBefore;
1114 	    break;
1115 	case RPpropTRW_WIDTHA:
1116 	    return rp->rpCellWidthAfter;
1117 	    break;
1118 
1119 	case RPpropTRFTS_WIDTHB:
1120 	    return rp->rpCellWidthBeforeUnit;
1121 	    break;
1122 	case RPpropTRFTS_WIDTHA:
1123 	    return rp->rpCellWidthAfterUnit;
1124 	    break;
1125 
1126 	case RPpropAUTOFORMAT_BORDERS:
1127 	    return rp->rpAutoformatBorders;
1128 	    break;
1129 	case RPpropAUTOFORMAT_SHADING:
1130 	    return rp->rpAutoformatShading;
1131 	    break;
1132 	case RPpropAUTOFORMAT_FONT:
1133 	    return rp->rpAutoformatFont;
1134 	    break;
1135 	case RPpropAUTOFORMAT_COLOR:
1136 	    return rp->rpAutoformatColor;
1137 	    break;
1138 	case RPpropAUTOFORMAT_APPLY_BEST_FIT:
1139 	    return rp->rpAutoformatApplyBestFit;
1140 	    break;
1141 	case RPpropAUTOFORMAT_FIRST_ROW:
1142 	    return rp->rpAutoformatFirstRow;
1143 	    break;
1144 	case RPpropAUTOFORMAT_LAST_ROW:
1145 	    return rp->rpAutoformatLastRow;
1146 	    break;
1147 	case RPpropAUTOFORMAT_FIRST_COLUMN:
1148 	    return rp->rpAutoformatFirstColumn;
1149 	    break;
1150 	case RPpropAUTOFORMAT_LAST_COLUMN:
1151 	    return rp->rpAutoformatLastColumn;
1152 	    break;
1153 
1154 	case RPpropROW_NUMBER:
1155 	    return rp->rpRowNumber;
1156 	    break;
1157 	case RPpropROW_BAND_NUMBER:
1158 	    return rp->rpRowBandNumber;
1159 	    break;
1160 	case RPpropROW_STYLE:
1161 	    return rp->rpRowStyle;
1162 	    break;
1163 
1164 	case RPpropIS_LAST_ROW:
1165 	    return rp->rpIsLastRow;
1166 	    break;
1167 
1168 	case RPpropTRAUTH:
1169 	    return rp->rpAuthor;
1170 	    break;
1171 
1172 	case RPpropCELL_LAYOUT:
1173 	case RPpropCELL_PROPS:
1174 	default:
1175 	    LDEB(prop); return -1;
1176 	}
1177 
1178     return 0;
1179     }
1180