1 /************************************************************************/
2 /* */
3 /* Layout of a table row in the document. */
4 /* */
5 /************************************************************************/
6
7 # include "docLayoutConfig.h"
8
9 # include <stddef.h>
10
11 # include "docLayout.h"
12 # include <docTreeType.h>
13 # include <docTreeNode.h>
14 # include "docRowLayout.h"
15 # include <docDebug.h>
16
17 # include <appDebugon.h>
18
19 /************************************************************************/
20 /* */
21 /* Shift cell contents of the cells in a row that are not top-aligned. */
22 /* */
23 /************************************************************************/
24
docLayoutRowValignCells(BufferItem * rowNode,BlockFrame * bf,const LayoutPosition * lpHere,const ParagraphLayoutPosition * rowPlp,const LayoutJob * lj)25 static int docLayoutRowValignCells(
26 BufferItem * rowNode,
27 BlockFrame * bf,
28 const LayoutPosition * lpHere,
29 const ParagraphLayoutPosition * rowPlp,
30 const LayoutJob * lj )
31 {
32 int col;
33 const CellProperties * cp= rowNode->biRowCells;
34 const ParagraphLayoutJob * plj;
35
36 cp= rowNode->biRowCells;
37 plj= rowPlp->pspChildren;
38 for ( col= 0; col < rowNode->biChildCount; cp++, plj++, col++ )
39 {
40 const CellProperties * thisCp= cp;
41 BufferItem * cellNode= rowNode->biChildren[col];
42 int rowTop= rowNode->biTopPosition.lpPageYTwips;
43 int rowHigh;
44 int cellHigh;
45
46 int paraFrom= 0;
47 int paraUpto= cellNode->biChildCount;
48
49 LayoutPosition lpTop;
50
51 if ( cellNode->biCellRowspan > 1 )
52 { continue; }
53
54 if ( cp->cpVerticalMerge == CELLmergeFOLLOW )
55 {
56 if ( cellNode->biCellMergedCellTopRow < 0 )
57 { continue; }
58 else{
59 BufferItem * topRowNode;
60
61 int topRow= cellNode->biCellMergedCellTopRow;
62 int topCol= cellNode->biCellMergedCellTopCol;
63
64 topRowNode= rowNode->biParent->biChildren[topRow];
65 rowTop= topRowNode->biTopPosition.lpPageYTwips;
66 cellNode= topRowNode->biChildren[topCol];
67 thisCp= topRowNode->biRowCells+ topCol;
68 }
69 }
70
71 lpTop= cellNode->biTopPosition;
72 rowHigh= lpHere->lpPageYTwips- rowTop;
73 cellHigh= cellNode->biBelowPosition.lpPageYTwips-
74 cellNode->biTopPosition.lpPageYTwips;
75
76 if ( cellHigh >= rowHigh )
77 { continue; }
78
79 switch( thisCp->cpValign )
80 {
81 case DOCtvaTOP:
82 continue;
83
84 case DOCtvaCENTERED:
85 cellNode->biCellTopInset= ( rowHigh- cellHigh )/ 2;
86 lpTop.lpPageYTwips += cellNode->biCellTopInset;
87
88 docRedoParaStripLayout( lj, bf, &lpTop,
89 cellNode, paraFrom, paraUpto );
90 continue;
91
92 case DOCtvaBOTTOM:
93 cellNode->biCellTopInset= rowHigh- cellHigh;
94 lpTop.lpPageYTwips += cellNode->biCellTopInset;
95
96 docRedoParaStripLayout( lj, bf, &lpTop,
97 cellNode, paraFrom, paraUpto );
98 continue;
99
100 default:
101 LLDEB(col,thisCp->cpValign);
102 continue;
103 }
104 }
105
106 return 0;
107 }
108
109 /************************************************************************/
110 /* */
111 /* Finish row layout. */
112 /* */
113 /* 1) The bottom is below all cells. */
114 /* 2) If there is a bottom inset, step over it. */
115 /* 3) Stretch height to the minimum height (If any) */
116 /* 4) Stretch height to the exact given height (If any) */
117 /* 5) Fix the current position if a fixed-height row exceeds its */
118 /* fixed height. */
119 /* */
120 /************************************************************************/
121
docLayoutFinishRow(LayoutPosition * lpHere,BufferItem * rowNode,BlockFrame * bf,const LayoutJob * lj,ParagraphLayoutPosition * rowPlp)122 static void docLayoutFinishRow( LayoutPosition * lpHere,
123 BufferItem * rowNode,
124 BlockFrame * bf,
125 const LayoutJob * lj,
126 ParagraphLayoutPosition * rowPlp )
127 {
128 int col;
129 CellProperties * cp;
130 ParagraphLayoutJob * plj;
131
132 /* 1 */
133 cp= rowNode->biRowCells;
134 plj= rowPlp->pspChildren;
135 for ( col= 0; col < rowNode->biChildCount; cp++, plj++, col++ )
136 {
137 BufferItem * cellNode= rowNode->biChildren[col];
138 ParagraphLayoutPosition * plp= &(plj->pljPos);
139
140 if ( cp->cpVerticalMerge == CELLmergeFOLLOW &&
141 cellNode->biCellMergedCellTopRow >= 0 )
142 {
143 docLayoutPushBottomDown( &(rowNode->biRowBelowAllCellsPosition),
144 &(plj->cljMergedCellBelowPosion) );
145 docLayoutPushBottomDown( lpHere,
146 &(plj->cljMergedCellBelowPosion) );
147 continue;
148 }
149
150 if ( CELL_MERGED( cp ) )
151 { continue; }
152
153 cellNode->biBelowPosition= plp->plpPos;
154
155 docLayoutPushBottomDown(
156 &(rowNode->biRowBelowAllCellsPosition), &(plp->plpPos) );
157
158 if ( cellNode->biCellRowspan <= 1 )
159 { docLayoutPushBottomDown( lpHere, &(plp->plpPos) ); }
160 }
161
162 if ( DOC_SAME_FRAME( lpHere, &(rowNode->biTopPosition) ) )
163 {
164 int rowHeightTwips;
165
166 rowHeightTwips= lpHere->lpPageYTwips-
167 rowNode->biTopPosition.lpPageYTwips;
168
169 /* 3: if rowNode->biRowHeightTwips > 0 */
170 if ( rowHeightTwips < rowNode->biRowHeightTwips )
171 {
172 lpHere->lpPageYTwips += rowNode->biRowHeightTwips- rowHeightTwips;
173 lpHere->lpAtTopOfColumn= 0;
174 }
175
176 /* 4: if rowNode->biRowHeightTwips < 0 */
177 if ( rowHeightTwips < -rowNode->biRowHeightTwips )
178 {
179 lpHere->lpPageYTwips += -rowNode->biRowHeightTwips- rowHeightTwips;
180 lpHere->lpAtTopOfColumn= 0;
181 }
182
183 /* 5 */
184 if ( rowNode->biRowHeightTwips < 0 &&
185 rowHeightTwips > -rowNode->biRowHeightTwips )
186 {
187 /* LLDEB(rowNode->biRowHeightTwips,rowHeightTwips); */
188 lpHere->lpPageYTwips -= rowHeightTwips+ rowNode->biRowHeightTwips;
189 }
190
191 if ( docLayoutRowValignCells( rowNode, bf, lpHere, rowPlp, lj ) )
192 { LDEB(1); }
193 }
194
195 docLayoutPushBottomDown( &(rowNode->biRowBelowAllCellsPosition), lpHere );
196
197 return;
198 }
199
200 /************************************************************************/
201 /* */
202 /* Layout as much of a table row as fits on the current page. */
203 /* */
204 /* 1) For a fixed height row, determine the amount of space left for */
205 /* it. */
206 /* 2) For all columns in the table.. */
207 /* 3) Cells in a row span or a colspan play no role... */
208 /* 4) This column was already exhausted on a previous page.. */
209 /* 5) Format paragraphs inside this cell. */
210 /* 6) Remember how far we have descended on the page. */
211 /* 7) Anything left over that must be moved to the next page? */
212 /* 7a) Distinguish between the situation where a fixed height row has */
213 /* reached its capacity and that where the page is full. */
214 /* */
215 /************************************************************************/
216
docLayoutRowPageStrip(LayoutPosition * lpHere,int * pToNextColumn,int * pSomeAtHead,BufferItem * rowNode,ParagraphLayoutPosition * rowPlp,BlockFrame * bf,const LayoutJob * lj)217 static int docLayoutRowPageStrip(
218 LayoutPosition * lpHere,
219 int * pToNextColumn,
220 int * pSomeAtHead,
221 BufferItem * rowNode,
222 ParagraphLayoutPosition * rowPlp,
223 BlockFrame * bf,
224 const LayoutJob * lj )
225 {
226 int col;
227
228 int continueInNextFrame= 0;
229 int someAtHead= 0;
230
231 LayoutPosition lpBottom;
232 const CellProperties * cp;
233 ParagraphLayoutJob * plj;
234
235 lpBottom= *lpHere;
236
237 continueInNextFrame= 0;
238
239 if ( rowPlp->pspChildCount != rowNode->biChildCount )
240 { LLDEB(rowPlp->pspChildCount,rowNode->biChildCount); return -1; }
241
242 /* 1 */
243
244 /* 2 */
245 cp= rowNode->biRowCells;
246 plj= rowPlp->pspChildren;
247 for ( col= 0; col < rowNode->biChildCount; cp++, plj++, col++ )
248 {
249 BufferItem * cellNode= rowNode->biChildren[col];
250 ParagraphLayoutPosition * plp= &(plj->pljPos);
251 int stopCode= FORMATstopREADY;
252
253 /* 3 */
254 if ( CELL_MERGED( cp ) )
255 { continue; }
256
257 /* 4 */
258 if ( docLayoutStripDone( plp, plj ) )
259 { continue; }
260
261 /* 5 */
262 plp->plpPos= *lpHere;
263
264 docCellStripFrame( cellNode, bf, plj );
265
266 if ( docLayoutStripChildren( &stopCode, plj, bf, lj, cellNode ) )
267 { LDEB(1); return -1; }
268
269 /* 6 */
270 docLayoutPushBottomDown(
271 &(rowNode->biRowBelowAllCellsPosition), &(plp->plpPos) );
272 if ( cellNode->biCellRowspan <= 1 )
273 { docLayoutPushBottomDown( &lpBottom, &(plp->plpPos) ); }
274
275 /* 7,7a */
276 if ( cellNode->biTreeType == DOCinBODY &&
277 stopCode == FORMATstopBLOCK_FULL )
278 { continueInNextFrame= 1; }
279 }
280
281 cp= rowNode->biRowCells;
282 plj= rowPlp->pspChildren;
283 for ( col= 0; col < rowNode->biChildCount; cp++, plj++, col++ )
284 {
285 const ParagraphLayoutPosition * plp= &(plj->pljPos);
286
287 if ( docLayoutAtStripHead( &(plj->pljPos) ) )
288 {
289 if ( ! docLayoutStripDone( plp, plj ) )
290 { someAtHead= 1; }
291 }
292 else{ rowPlp->pspChildAdvanced= 1; }
293 }
294
295 *lpHere= lpBottom;
296 *pToNextColumn= continueInNextFrame;
297 *pSomeAtHead= someAtHead;
298
299 if ( ! continueInNextFrame )
300 { docLayoutFinishRow( lpHere, rowNode, bf, lj, rowPlp ); }
301
302 return 0;
303 }
304
305 /************************************************************************/
306
docLayoutStartRowCells(BufferItem * rowNode,const BufferDocument * bd,const LayoutPosition * lpHere,const BlockFrame * bf,ParagraphLayoutPosition * rowPlp)307 static int docLayoutStartRowCells(
308 BufferItem * rowNode,
309 const BufferDocument * bd,
310 const LayoutPosition * lpHere,
311 const BlockFrame * bf,
312 ParagraphLayoutPosition * rowPlp )
313 {
314 CellProperties * cp;
315 int col;
316 int l, r;
317 ParagraphLayoutJob * cellPlj;
318
319 int nextRow= rowNode->biNumberInParent+ 1;
320 const BufferItem * nextRowBi= (const BufferItem *)0;
321
322 if ( nextRow < rowNode->biRowTablePast )
323 { nextRowBi= rowNode->biParent->biChildren[nextRow]; }
324
325 rowNode->biRowBelowAllCellsPosition= *lpHere;
326
327 /* 2 */
328 cellPlj= rowPlp->pspChildren;
329 r= rowNode->biRowLeftIndentTwips;
330 cp= rowNode->biRowCells;
331 for ( col= 0; col < rowNode->biChildCount; cp++, cellPlj++, col++ )
332 {
333 BufferItem * cellNode= rowNode->biChildren[col];
334 const int para= 0;
335 const int line= 0;
336 const int part= 0;
337 int colspan= 1;
338
339 const int recursively= 0;
340
341 docDelimitTables( cellNode, recursively );
342
343 cellNode->biCellTopInset= 0;
344
345 docBeginParagraphLayoutProgress( cellPlj, para, line, part,
346 cellNode->biChildCount, lpHere );
347
348 cellNode->biTopPosition= *lpHere;
349
350 l= r; r= cp->cpRightBoundaryTwips;
351 if ( cp->cpHorizontalMerge == CELLmergeHEAD )
352 { r= docGetCellRight( &colspan, cellNode ); }
353
354 /* 3 */
355 cellNode->biCellRowspan= 1;
356 if ( cp->cpVerticalMerge != CELLmergeNONE )
357 {
358 docRowLayoutRowspanAdmin( cellNode, rowNode, nextRowBi, nextRow,
359 cp, l, r, cellPlj );
360 }
361
362 cp += colspan- 1;
363 cellPlj += colspan- 1;
364 col += colspan- 1;
365 }
366
367 return 0;
368 }
369
370 /************************************************************************/
371 /* */
372 /* Calculate the layout of a row in the document. */
373 /* */
374 /* 1) Do not advance by row top inset. This is done between the top */
375 /* of the paragraph and its first line. [This is what MS-Word */
376 /* does.] */
377 /* 2) Begin formatting. */
378 /* 3) Keep track of the rowspan of the cells. */
379 /* */
380 /************************************************************************/
381
docLayoutStartRow(int * pToNextColumn,BufferItem * rowNode,const BufferDocument * bd,LayoutPosition * lpHere,const BlockFrame * bf,ParagraphLayoutPosition * rowPlp)382 static int docLayoutStartRow( int * pToNextColumn,
383 BufferItem * rowNode,
384 const BufferDocument * bd,
385 LayoutPosition * lpHere,
386 const BlockFrame * bf,
387 ParagraphLayoutPosition * rowPlp )
388 {
389 const int atRowTop= 1;
390
391 int minHeightTwips= rowNode->biRowHeightTwips;
392
393 if ( docParagraphLayoutPosClaimChildren( rowPlp, rowNode->biChildCount ) )
394 { LDEB(rowNode->biChildCount); return -1; }
395
396 if ( rowNode->biRowHeightTwips < 0 )
397 { minHeightTwips= -rowNode->biRowHeightTwips; }
398
399 /* 3a */
400 if ( lpHere->lpPageYTwips+ minHeightTwips > bf->bfFlowRect.drY1 &&
401 ! lpHere->lpAtTopOfColumn )
402 { *pToNextColumn= 1; return 0; }
403
404 rowNode->biRowAboveHeaderPosition= rowNode->biTopPosition;
405 rowNode->biRowPrecededByHeader= 0;
406
407 /* 1 */
408 /* NO! lpHere->lpPageYTwips += rowNode->biRowTopInset; */
409
410 {
411 int rti= rowNode->biRowTopInset;
412 docLayoutCalculateRowTopInset( &rti, bd, rowNode, atRowTop );
413 rowNode->biRowTopInset= rti;
414 }
415
416 if ( docLayoutStartRowCells( rowNode, bd, lpHere, bf, rowPlp ) )
417 { LDEB(1); return -1; }
418
419 *pToNextColumn= 0;
420 return 0;
421 }
422
423 /************************************************************************/
424 /* */
425 /* Reserve space for a table header. */
426 /* */
427 /************************************************************************/
428
docLayoutRowSkipHeaderHeight(LayoutPosition * lp,BufferItem * rowNode,int atTopOfRow)429 static void docLayoutRowSkipHeaderHeight( LayoutPosition * lp,
430 BufferItem * rowNode,
431 int atTopOfRow )
432 {
433 const BufferItem * headerBi;
434 int headerHeight;
435
436 if ( rowNode->biRowTableHeaderRow < 0 )
437 { LDEB(rowNode->biRowTableHeaderRow); return; }
438 if ( rowNode->biRowIsTableHeader )
439 { LDEB(rowNode->biRowIsTableHeader); return; }
440
441 headerBi= rowNode->biParent->biChildren[rowNode->biRowTableHeaderRow];
442 if ( ! headerBi->biRowIsTableHeader )
443 { LDEB(headerBi->biRowIsTableHeader); }
444
445 if ( headerBi->biBelowPosition.lpPage !=
446 headerBi->biTopPosition.lpPage )
447 {
448 LLDEB(headerBi->biBelowPosition.lpPage,headerBi->biTopPosition.lpPage);
449 return;
450 }
451
452 if ( atTopOfRow )
453 {
454 rowNode->biRowAboveHeaderPosition= *lp;
455 rowNode->biRowPrecededByHeader= 1;
456 }
457
458 headerHeight= headerBi->biBelowPosition.lpPageYTwips-
459 headerBi->biTopPosition.lpPageYTwips;
460
461 lp->lpAtTopOfColumn= 0;
462 lp->lpPageYTwips += headerHeight;
463
464 return;
465 }
466
467 /************************************************************************/
468 /* */
469 /* Continue a table row on the next page. */
470 /* */
471 /* 1) Finish the footnotes that we found on the current page. */
472 /* 2) Move to the next page. (Column in multi column sections) */
473 /* 3) Skipping to a subsequent page.. Allocate space for the table */
474 /* header. */
475 /* 4) Reserve space for the top border of the cells. */
476 /* 5) Initialize the layout of the different table columns. */
477 /* */
478 /************************************************************************/
479
docRowLayoutToNextColumn(BufferItem * rowNode,LayoutPosition * lpHere,const LayoutJob * lj,int atTopOfRow,BlockFrame * bf)480 static int docRowLayoutToNextColumn(
481 BufferItem * rowNode,
482 LayoutPosition * lpHere,
483 const LayoutJob * lj,
484 int atTopOfRow,
485 BlockFrame * bf )
486 {
487 const LayoutContext * lc= &(lj->ljContext);
488
489 int inset= 0;
490 const int belowText= 0;
491 const int atRowTop= 0;
492 LayoutPosition lpBelowNotes;
493
494 /* 1 */
495 if ( BF_HAS_FOOTNOTES( bf ) &&
496 ( rowNode->biTreeType == DOCinBODY ||
497 rowNode->biTreeType == DOCinENDNOTE ) &&
498 docLayoutFootnotesForColumn( &lpBelowNotes, lpHere, bf,
499 belowText, lj ) )
500 { LDEB(1); return -1; }
501
502 /* 2 */
503 docLayoutToNextColumn( lpHere, bf, rowNode, lj );
504
505 /* 3 */
506 if ( ! rowNode->biRowIsTableHeader &&
507 rowNode->biRowTableHeaderRow >= 0 )
508 { docLayoutRowSkipHeaderHeight( lpHere, rowNode, atTopOfRow ); }
509
510 /* 4 */
511 docLayoutCalculateRowTopInset( &inset, lc->lcDocument, rowNode, atRowTop );
512 lpHere->lpPageYTwips += inset;
513
514 return 0;
515 }
516
docRowToNextColumn(LayoutPosition * lpHere,BufferItem * rowNode,const LayoutJob * lj,int atTopOfRow,BlockFrame * bf,ParagraphLayoutJob * rowPlj)517 static int docRowToNextColumn( LayoutPosition * lpHere,
518 BufferItem * rowNode,
519 const LayoutJob * lj,
520 int atTopOfRow,
521 BlockFrame * bf,
522 ParagraphLayoutJob * rowPlj )
523 {
524 CellProperties * cp;
525 int col;
526
527 ParagraphLayoutJob * plj;
528
529 LayoutPosition lpBefore;
530
531 lpBefore= *lpHere;
532
533 if ( docRowLayoutToNextColumn( rowNode, lpHere, lj, atTopOfRow, bf ) )
534 { LDEB(atTopOfRow); return -1; }
535
536 /* 5 */
537 cp= rowNode->biRowCells;
538 plj= rowPlj->pljPos.pspChildren;
539 for ( col= 0; col < rowNode->biChildCount; cp++, plj++, col++ )
540 {
541 const BufferItem * cellNode= rowNode->biChildren[col];
542 int advanced;
543 int advanceAnyway= 0;
544
545 if ( docLayoutStripDone( &(plj->pljPos), plj ) )
546 { continue; }
547
548 if ( cellNode->biChildren[plj->pljPos0.pspChild]->biLevel ==
549 DOClevROW )
550 { continue; }
551
552 docCommitStripLayout( &advanced, advanceAnyway, plj,
553 lpBefore.lpPage, lpBefore.lpColumn, cellNode );
554 }
555
556 return 0;
557 }
558
559 /************************************************************************/
560 /* */
561 /* Calculate the layout of a nested table row. */
562 /* */
563 /* 1) If the row does not fit in the current page frame, the */
564 /* the situation is hopeless: Proceed on this page: The row will */
565 /* be split. */
566 /* */
567 /************************************************************************/
568
docLayoutRowInStrip(int * pStopCode,ParagraphLayoutPosition * rowPlp,BlockFrame * bf,const LayoutJob * lj,int cellTopInset,BufferItem * rowNode)569 int docLayoutRowInStrip( int * pStopCode,
570 ParagraphLayoutPosition * rowPlp,
571 BlockFrame * bf,
572 const LayoutJob * lj,
573 int cellTopInset,
574 BufferItem * rowNode )
575 {
576 const LayoutContext * lc= &(lj->ljContext);
577 int stopCode= FORMATstopREADY;
578 int toNextColumn= 0;
579 int someAtHead= 0;
580
581 if ( ! rowPlp->pspChildAdvanced )
582 {
583 rowNode->biTopPosition= rowPlp->plpPos;
584
585 if ( docLayoutStartRow( &toNextColumn, rowNode,
586 lc->lcDocument, &(rowPlp->plpPos), bf, rowPlp ) )
587 { LDEB(rowNode->biChildCount); return -1; }
588
589 /* 1 */
590 if ( toNextColumn )
591 { /*LDEB(toNextColumn);*/ toNextColumn= 0; }
592 }
593
594 toNextColumn= 0;
595 if ( docLayoutRowPageStrip( &(rowPlp->plpPos),
596 &toNextColumn, &someAtHead,
597 rowNode, rowPlp, bf, lj ) )
598 { LDEB(1); return -1; }
599
600 if ( toNextColumn )
601 {
602 stopCode= FORMATstopBLOCK_FULL;
603 *pStopCode= FORMATstopBLOCK_FULL;
604 return stopCode;
605 }
606 else{
607 docStripLayoutNextChild( rowPlp );
608 stopCode= FORMATstopREADY;
609 *pStopCode= FORMATstopREADY;
610
611 docLayoutFinishNodeLayout( (int *)0, rowNode, lj, &(rowPlp->plpPos) );
612
613 return stopCode;
614 }
615 }
616
617 /************************************************************************/
618 /* */
619 /* Calculate the layout of a table row. */
620 /* */
621 /* NOTE Table headers that appear by themselves as the last table row */
622 /* on the page should have been pushed to the next page. Some */
623 /* thought reveals however that the result on the formatting of */
624 /* the rest of the document is not altered by moving the header */
625 /* row to the next page. For that reason, and to keep the */
626 /* formatter simple, we simply ignore the situation. To */
627 /* compensate, the drawing code simply skips the row in its home */
628 /* position and the visible result is the same. */
629 /* */
630 /* 1) Sanity check against crashes. */
631 /* This fix is a thourough memory leak. It is hardly ever */
632 /* activated and it prevents crashes with incorrect rtf files. */
633 /* 2) Allocate memory to monitor the progress of the layout of the */
634 /* cells in the row. */
635 /* 3) Initialize and place as much row content on the current page */
636 /* as possible. */
637 /* 3a) As an optimization: It does not make sense to start a row that */
638 /* has a minimum height on a page where it does not fit. */
639 /* The test is not sufficient: Footnotes in the row can use the */
640 /* space in such a way that on our way, we will discover that we */
641 /* have no space left. */
642 /* 4) Some of the content of the row did not fit on the current page. */
643 /* Find out whether the row must be restarted on the next page. */
644 /* (This does not make sense if the top of the row already is at */
645 /* the top of the page.) */
646 /* 5) When there are cells that remain empty on this page.. restart */
647 /* on the next page. */
648 /* 6) Go to the next page. */
649 /* 7) If there is a reason, reinitialize the row layout job, to move */
650 /* the whole row to the next page. */
651 /* 8) Continue or restart (7) on the next page. */
652 /* 9) As long as necessary, move to the next page and place content */
653 /* there. (The exceptions above only apply for the first page, as */
654 /* it is clearly impossible to keep the contents of a table higher */
655 /* than one page on one page) */
656 /* */
657 /* Measurements with MS-Word reveal the following: */
658 /* if trrh < 0, then the height of the row is -trrh. */
659 /* if trrh >= 0, then the height of the row is the maximum of the */
660 /* height of the contents and the value of trrh. Contrary to the */
661 /* exact height case, the width of the horizontal border is */
662 /* added to the height of the row. */
663 /* In the situation where two rows are on top of eachother, the */
664 /* fattest border between them is used with a preference for the top */
665 /* border of the bottom row if they have the same witdh. */
666 /* */
667 /************************************************************************/
668
docLayoutRowNode(int * pStopCode,LayoutPosition * lpBelow,const LayoutPosition * lpTop,BufferItem * rowNode,BlockFrame * bf,int stayInThisColumn,const LayoutJob * lj)669 int docLayoutRowNode( int * pStopCode,
670 LayoutPosition * lpBelow,
671 const LayoutPosition * lpTop,
672 BufferItem * rowNode,
673 BlockFrame * bf,
674 int stayInThisColumn,
675 const LayoutJob * lj )
676 {
677 const LayoutContext * lc= &(lj->ljContext);
678 int stopCode= FORMATstopREADY;
679 int rval= 0;
680 int toNextColumn;
681 int someAtHead= 0;
682
683 ParagraphLayoutJob rowPlj;
684
685 LayoutPosition lpHere;
686
687 {
688 const int line= 0;
689 const int part= 0;
690
691 docInitParagraphLayoutJob( &rowPlj );
692 docBeginParagraphLayoutProgress( &rowPlj,
693 rowNode->biNumberInParent,
694 line, part, rowNode->biNumberInParent+ 1,
695 lpTop );
696 }
697
698 lpHere= *lpTop;
699
700 /* 1 */
701 if ( ! docIsRowNode( rowNode ) )
702 { LLDEB(rowNode->biNumberInParent,rowNode->biRowCellCount); return -1; }
703
704 if ( rowNode->biRowCellCount < rowNode->biChildCount )
705 {
706 LLDEB(rowNode->biRowCellCount,rowNode->biChildCount);
707 docListNode( 0, rowNode, 0 );
708 rowNode->biChildCount= rowNode->biRowCellCount;
709 }
710
711 /* 2,3 */
712 toNextColumn= 0;
713
714 /* 3a */
715 if ( docLayoutStartRow( &toNextColumn, rowNode,
716 lc->lcDocument, &lpHere, bf, &(rowPlj.pljPos) ) )
717 { LDEB(rowNode->biChildCount); rval= -1; goto ready; }
718
719 if ( toNextColumn )
720 {
721 if ( stayInThisColumn )
722 { stopCode= FORMATstopFRAME_FULL; goto ready; }
723 }
724 else{
725 if ( docLayoutRowPageStrip( &lpHere, &toNextColumn, &someAtHead,
726 rowNode, &(rowPlj.pljPos), bf, lj ) )
727 { LDEB(1); rval= -1; goto ready; }
728 }
729
730 /* 4 */
731 if ( toNextColumn &&
732 ! rowNode->biTopPosition.lpAtTopOfColumn )
733 {
734 int restartRow;
735
736 if ( stayInThisColumn )
737 { stopCode= FORMATstopFRAME_FULL; goto ready; }
738
739 /* 5, 7 */
740 restartRow= BI_ROW_IS_ONE_PAGE( rowNode ) ||
741 ! rowPlj.pljPos.pspChildAdvanced ||
742 someAtHead;
743 /* 6 */
744 if ( docRowToNextColumn( &lpHere, rowNode, lj,
745 restartRow, bf, &rowPlj ) )
746 { LDEB(toNextColumn); rval= -1; goto ready; }
747
748 /* 7 */
749 if ( restartRow )
750 {
751 rowNode->biTopPosition= lpHere;
752
753 if ( rowNode->biRowIsTableHeader ||
754 rowNode->biRowTableHeaderRow < 0 )
755 { rowNode->biRowAboveHeaderPosition= rowNode->biTopPosition; }
756
757 if ( docLayoutStartRowCells( rowNode, lc->lcDocument,
758 &lpHere, bf, &(rowPlj.pljPos) ) )
759 { LDEB(rowNode->biChildCount); rval= -1; goto ready; }
760 toNextColumn= 0; /* irrelevant here */
761 }
762
763 /* 8 */
764 if ( docLayoutRowPageStrip( &lpHere, &toNextColumn, &someAtHead,
765 rowNode, &(rowPlj.pljPos), bf, lj ) )
766 { LDEB(1); rval= -1; goto ready; }
767 }
768
769 /* 9 */
770 while( toNextColumn )
771 {
772 const int atTopOfRow= 0;
773
774 if ( stayInThisColumn )
775 { stopCode= FORMATstopFRAME_FULL; goto ready; }
776
777 if ( docRowToNextColumn( &lpHere, rowNode, lj,
778 atTopOfRow, bf, &rowPlj ) )
779 { LDEB(toNextColumn); rval= -1; goto ready; }
780
781 if ( docLayoutRowPageStrip( &lpHere, &toNextColumn, &someAtHead,
782 rowNode, &(rowPlj.pljPos), bf, lj ) )
783 { LDEB(1); rval= -1; goto ready; }
784 }
785
786 ready:
787
788 docCleanParagraphLayoutJob( &rowPlj );
789
790 if ( ! rval )
791 {
792 *pStopCode= stopCode;
793 *lpBelow= lpHere;
794 }
795
796 return rval;
797 }
798
799