1 #   include	"docLayoutConfig.h"
2 
3 #   include	"docDraw.h"
4 #   include	<docPageGrid.h>
5 #   include	"docRowLayout.h"
6 #   include	<docTreeNode.h>
7 #   include	<docTextLine.h>
8 
9 #   include	<appDebugon.h>
10 
11 /************************************************************************/
12 
13 static int docDrawRowPageStrip(	BufferItem *			rowNode,
14 				const LayoutPosition *		lpThisFrame,
15 				BlockFrame *			bf,
16 				void *				through,
17 				DrawingContext *		dc,
18 				const BlockOrigin *		bo );
19 
20 /************************************************************************/
21 /*									*/
22 /*  Draw part of the grid originating from a table row.			*/
23 /*									*/
24 /*  4)  For all cells.....						*/
25 /*  5)  Skip cells that are included in the colspan or rowspan of	*/
26 /*	another cell. The left/top cell of a span has to draw the	*/
27 /*	borders and the background.					*/
28 /*									*/
29 /************************************************************************/
30 
docDrawCellOrnamentsForRow(const BufferItem * rowNode,const BlockFrame * bf,const BlockOrigin * bo,void * through,DrawingContext * dc,int atRowTop,int atRowBottom,const LayoutPosition * lpTop)31 static int docDrawCellOrnamentsForRow(
32 			const BufferItem *			rowNode,
33 			const BlockFrame *			bf,
34 			const BlockOrigin *			bo,
35 			void *					through,
36 			DrawingContext *			dc,
37 			int					atRowTop,
38 			int					atRowBottom,
39 			const LayoutPosition *			lpTop )
40     {
41     const LayoutContext *		lc= &(dc->dcLayoutContext);
42     const BufferDocument *		bd= lc->lcDocument;
43     const CellProperties *		cp;
44     int					col;
45 
46     if  ( ! dc->dcDrawOrnaments )
47 	{ return 0;	}
48 
49     /*  4  */
50     cp= rowNode->biRowCells;
51     for ( col= 0; col < rowNode->biChildCount; cp++, col++ )
52 	{
53 	BufferItem *			cellNode= rowNode->biChildren[col];
54 
55 	BlockOrnaments			cellOrnaments;
56 	DocumentRectangle		drCell;
57 	DocumentRectangle		drOutside;
58 	DocumentRectangle		drInside;
59 
60 	docInitBlockOrnaments( &cellOrnaments );
61 
62 	/*  5  */
63 	if  ( CELL_MERGED( cp ) )
64 	    { continue;	}
65 
66 	docCellRectangleTwips( &drCell, bf, cellNode );
67 
68 	drCell.drX0 += bo->boXShift;
69 	drCell.drX1 += bo->boXShift;
70 	drCell.drY0= lpTop->lpPageYTwips;
71 	drCell.drY1 += bo->boYShift;
72 
73 	docGetCellOrnaments( &cellOrnaments, &drOutside, &drInside, &drCell,
74 			bd, rowNode, col,
75 			atRowTop, atRowBottom, dc->dcDrawTableGrid );
76 
77 	if  ( (*dc->dcDrawOrnaments)( &cellOrnaments, lpTop->lpPage,
78 					&drOutside, &drInside, through, dc ) )
79 	    { LDEB(1); return -1;	}
80 	}
81 
82     return 0;
83     }
84 
85 /************************************************************************/
86 
docDrawAdvanceRowInCell(void * through,BufferItem * rowNode,LayoutPosition * lpThisFrame,LayoutPosition * lpBelow,BlockFrame * bf,DrawingContext * dc,const BlockOrigin * bo)87 static int docDrawAdvanceRowInCell(
88 				void *				through,
89 				BufferItem *			rowNode,
90 				LayoutPosition *		lpThisFrame,
91 				LayoutPosition *		lpBelow,
92 				BlockFrame *			bf,
93 				DrawingContext *		dc,
94 				const BlockOrigin *		bo )
95     {
96     if  ( docDrawRowPageStrip( rowNode, lpThisFrame, bf, through, dc, bo ) )
97 	{ LDEB(1); return -1;	}
98 
99     /*  Only used in same frame */
100     *lpBelow= rowNode->biBelowPosition;
101 
102     return 0;
103     }
104 
105 /************************************************************************/
106 
docDrawAdvanceParaInCell(void * through,BufferItem * paraBi,const LayoutPosition * lpThisFrame,LayoutPosition * lpBelow,BlockFrame * bf,DrawingContext * dc,const BlockOrigin * bo)107 static int docDrawAdvanceParaInCell(
108 				void *				through,
109 				BufferItem *			paraBi,
110 				const LayoutPosition *		lpThisFrame,
111 				LayoutPosition *		lpBelow,
112 				BlockFrame *			bf,
113 				DrawingContext *		dc,
114 				const BlockOrigin *		bo )
115     {
116     ParagraphDrawingStrip	pds;
117     const int			countAfter= 0;
118 
119     ParagraphFrame		pf;
120     int				line= 0;
121 
122     LayoutPosition		lpShadeTop= *lpThisFrame;
123 
124     docParagraphFrameTwips( &pf, bf, paraBi );
125 
126     while( line < paraBi->biParaLineCount )
127 	{
128 	TextLine *	tl= paraBi->biParaLines+ line;
129 	LayoutPosition	lpLine;
130 
131 	docShiftPosition( &lpLine, bo, &(tl->tlTopPosition) );
132 
133 	if  ( ! DOC_COLUMN_AFTER( lpThisFrame, &lpLine ) )
134 	    { break;	}
135 
136 	line++;
137 	}
138 
139     /**/
140     if  ( docDrawParagraphStrip( through, &pds, paraBi, countAfter,
141 				&lpShadeTop, line, &pf, dc, lpThisFrame, bo ) )
142 	{ LDEB(line); return -1;	}
143 
144     /*  Only used in same frame */
145     *lpBelow= pds.pdsShadeBelow;
146 
147     return 0;
148     }
149 
150 /************************************************************************/
151 /*									*/
152 /*  Print as much of a table-cell/column in a row as fits on the	*/
153 /*  current page.							*/
154 /*									*/
155 /*  1)  Skip entries that end before the current page.			*/
156 /*  2)  Draw entries that do not start after the current page.		*/
157 /*									*/
158 /************************************************************************/
159 
docDrawCellPageStrip(void * through,const BufferItem * cellNode,const LayoutPosition * lpThisFrame,BlockFrame * bf,DrawingContext * dc,const BlockOrigin * bo)160 static int docDrawCellPageStrip( void *				through,
161 				const BufferItem *		cellNode,
162 				const LayoutPosition *		lpThisFrame,
163 				BlockFrame *			bf,
164 				DrawingContext *		dc,
165 				const BlockOrigin *		bo )
166 
167     {
168     int			child= 0;
169 
170     LayoutPosition	lpShadeTop= *lpThisFrame;
171     LayoutPosition	lpShadeBelow= *lpThisFrame;
172 
173     /*  1  */
174     while( child < cellNode->biChildCount )
175 	{
176 	BufferItem *		childNode= cellNode->biChildren[child];
177 	const LayoutPosition *	belowChildPos;
178 	LayoutPosition		lpChildBottom;
179 
180 	if  ( docIsRowNode( childNode ) )
181 	    { belowChildPos= &(childNode->biRowBelowAllCellsPosition);	}
182 	else{ belowChildPos= &(childNode->biBelowPosition);		}
183 
184 	docShiftPosition( &lpChildBottom, bo, belowChildPos );
185 	if  ( ! DOC_COLUMN_AFTER( lpThisFrame, &lpChildBottom ) )
186 	    { break;	}
187 
188 	child++;
189 	}
190 
191     /*  2  */
192     while( child < cellNode->biChildCount )
193 	{
194 	BufferItem *	childNode= cellNode->biChildren[child];
195 	LayoutPosition	lpChildTop;
196 
197 	docShiftPosition( &lpChildTop, bo, &(childNode->biTopPosition) );
198 
199 	if  ( DOC_COLUMN_AFTER( &lpChildTop, lpThisFrame ) )
200 	    { break;	}
201 
202 	switch( childNode->biLevel )
203 	    {
204 	    case DOClevPARA:
205 		if  ( docDrawAdvanceParaInCell( through, childNode,
206 				    &lpShadeTop, &lpShadeBelow, bf, dc, bo ) )
207 		    { LDEB(1); return -1;	}
208 		break;
209 
210 	    case DOClevROW:
211 		if  ( docDrawAdvanceRowInCell( through, childNode,
212 				    &lpShadeTop, &lpShadeBelow, bf, dc, bo ) )
213 		    { LDEB(1); return -1;	}
214 		break;
215 
216 	    default:
217 		LDEB(childNode->biLevel);
218 		break;
219 	    }
220 
221 	/*  Only used in same frame */
222 	lpShadeTop= lpShadeBelow;
223 	child++;
224 	}
225 
226     return 0;
227     }
228 
229 /************************************************************************/
230 /*									*/
231 /*  Print as much of a table row as fits on the current page.		*/
232 /*									*/
233 /*  1)  Find the bottom of this row on the page: We need this to draw	*/
234 /*	the cell ornaments before we draw the row contents.		*/
235 /*									*/
236 /************************************************************************/
237 
docDrawRowPageStrip(BufferItem * rowNode,const LayoutPosition * lpThisFrame,BlockFrame * bf,void * through,DrawingContext * dc,const BlockOrigin * bo)238 static int docDrawRowPageStrip(	BufferItem *			rowNode,
239 				const LayoutPosition *		lpThisFrame,
240 				BlockFrame *			bf,
241 				void *				through,
242 				DrawingContext *		dc,
243 				const BlockOrigin *		bo )
244     {
245     int				col;
246 
247     LayoutPosition		lpTop;
248     const CellProperties *	cp;
249 
250     int				atRowTop= 0;
251     int				atRowBottom= 0;
252 
253     if  ( DOC_SAME_FRAME( lpThisFrame,
254 				&(rowNode->biTopPosition) ) )
255 	{ atRowTop= 1;	}
256     if  ( DOC_SAME_FRAME( lpThisFrame,
257 				&(rowNode->biRowBelowAllCellsPosition) ) )
258 	{ atRowBottom= 1;	}
259 
260     lpTop= *lpThisFrame;
261 
262     if  ( ! rowNode->biRowIsTableHeader )
263 	{
264 	if  ( atRowTop )
265 	    {
266 	    docShiftPosition( &lpTop, bo, &(rowNode->biTopPosition) );
267 
268 	    if  ( rowNode->biRowPrecededByHeader )
269 		{
270 		int		high;
271 
272 		if  ( docDrawTableHeader( &high, rowNode, bf, through,
273 				    dc, &(rowNode->biRowAboveHeaderPosition) ) )
274 		    { LDEB(rowNode->biRowPrecededByHeader); return -1;	}
275 		}
276 	    }
277 	else{
278 	    if  ( rowNode->biRowTableHeaderRow >= 0 )
279 		{
280 		int		high;
281 
282 		if  ( docDrawTableHeader( &high, rowNode, bf, through,
283 							    dc, lpThisFrame ) )
284 		    { LDEB(rowNode->biRowIsTableHeader); return -1;	}
285 		}
286 	    }
287 	}
288 
289     if  ( docDrawCellOrnamentsForRow( rowNode, bf, bo, through, dc,
290 					    atRowTop, atRowBottom, &lpTop ) )
291 	{ LDEB(1); return -1;	}
292 
293     cp= rowNode->biRowCells;
294     for ( col= 0; col < rowNode->biChildCount; cp++, col++ )
295 	{
296 	BufferItem *	cellNode= rowNode->biChildren[col];
297 
298 	int		selected;
299 	int		cmp;
300 
301 	if  ( CELL_MERGED( cp ) )
302 	    { continue;	}
303 
304 	cmp= docCompareCellPositionToSelection( &selected, cellNode,
305 						    dc->dcSelection );
306 	if  ( cmp > 0 )
307 	    { break;    }
308 	if  ( cmp < 0 || ! selected )
309 	    { continue; }
310 
311 	if  ( docDrawCellPageStrip( through, cellNode, &lpTop, bf, dc, bo ) )
312 	    { LDEB(1); return -1;	}
313 	}
314 
315     return 0;
316     }
317 
318 /************************************************************************/
319 /*									*/
320 /*  Draw a table header.						*/
321 /*									*/
322 /*  1)  Find the header that belongs to this row.			*/
323 /*  2)  Determine where the header would be drawn to find the		*/
324 /*	horizontal offset for header drawing.				*/
325 /*									*/
326 /************************************************************************/
327 
docDrawTableHeader(int * pHigh,const BufferItem * rowNode,const BlockFrame * bfRef,void * through,DrawingContext * dc,const LayoutPosition * lpHeader)328 int docDrawTableHeader(	int *				pHigh,
329 			const BufferItem *		rowNode,
330 			const BlockFrame *		bfRef,
331 			void *				through,
332 			DrawingContext *		dc,
333 			const LayoutPosition *		lpHeader )
334     {
335     int				rval= 0;
336     const LayoutContext *	lc= &(dc->dcLayoutContext);
337     BufferItem *		headerBi;
338     BlockFrame			bfHeader;
339 
340     BlockOrigin			bo;
341 
342     docInitBlockOrigin( &bo );
343     docLayoutInitBlockFrame( &bfHeader );
344 
345     /*  1  */
346     if  ( rowNode->biRowTableHeaderRow < 0 )
347 	{ LDEB(rowNode->biRowTableHeaderRow); rval= -1; goto ready;	}
348 
349     headerBi= rowNode->biParent->biChildren[rowNode->biRowTableHeaderRow];
350 
351     /*  2  */
352     docBlockFrameTwips( &bfHeader, headerBi,
353 			    lc->lcDocument,
354 			    headerBi->biTopPosition.lpPage,
355 			    headerBi->biTopPosition.lpColumn );
356 
357     bo.boOverrideFrame= 1;
358     bo.boXShift= bfRef->bfContentRect.drX0- bfHeader.bfContentRect.drX0;
359     bo.boYShift= lpHeader->lpPageYTwips- headerBi->biTopPosition.lpPageYTwips;
360     bo.boFrameOverride= *lpHeader;
361 
362     if  ( docDrawRowNode( headerBi, through, dc, &bo ) )
363 	{ LDEB(1); rval= -1; goto ready;	}
364 
365     *pHigh= headerBi->biBelowPosition.lpPageYTwips-
366 					headerBi->biTopPosition.lpPageYTwips;
367 
368   ready:
369 
370     docLayoutCleanBlockFrame( &bfHeader );
371 
372     return rval;
373     }
374 
375 /************************************************************************/
376 /*									*/
377 /*  Draw a table row by successively drawing the portions that fit in	*/
378 /*  the current (newspaper style) column and moving to the next column.	*/
379 /*									*/
380 /*  NOTE that any drawing routine can be recursive.			*/
381 /*									*/
382 /************************************************************************/
383 
docDrawRowNode(BufferItem * rowNode,void * through,DrawingContext * dc,const BlockOrigin * bo)384 int docDrawRowNode(	BufferItem *			rowNode,
385 			void *				through,
386 			DrawingContext *		dc,
387 			const BlockOrigin *		bo )
388     {
389     const LayoutContext *	lc= &(dc->dcLayoutContext);
390     int				rval= 0;
391     LayoutPosition		lpThisFrame;
392     BlockFrame			bf;
393 
394     docLayoutInitBlockFrame( &bf );
395     docBlockFrameTwips( &bf, rowNode, lc->lcDocument,
396 					    rowNode->biTopPosition.lpPage,
397 					    rowNode->biTopPosition.lpColumn );
398 
399     docShiftPosition( &lpThisFrame, bo, &(rowNode->biTopPosition) );
400 
401     if  ( docDrawRowPageStrip( rowNode, &lpThisFrame, &bf, through, dc, bo ) )
402 	{ LDEB(1); rval= -1; goto ready;	}
403 
404     while( DOC_COLUMN_AFTER( &(rowNode->biRowBelowAllCellsPosition),
405 							    &lpThisFrame ) )
406 	{
407 	int			ret;
408 
409 	/*  1  */
410 	ret= docDrawToNextColumn( rowNode, rowNode, through,
411 						    &lpThisFrame, &bf, dc );
412 	if  ( ret < 0 )
413 	    { SLDEB(docLevelStr(rowNode->biLevel),ret); rval= -1; goto ready; }
414 	if  ( ret > 0 )
415 	    { break;	}
416 
417 	if  ( docDrawRowPageStrip( rowNode,
418 				    &lpThisFrame, &bf, through, dc, bo ) )
419 	    { LDEB(1); rval= -1; goto ready;	}
420 	}
421 
422   ready:
423 
424     docLayoutCleanBlockFrame( &bf );
425 
426     return rval;
427     }
428 
429