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