OOFILE  1.9
oofrpWin.cpp
Go to the documentation of this file.
1 // COPYRIGHT 1997 A.D. Software, All rights reserved
2 
3 // report-writer layer of OOFILE database
4 // renderer factories for Windows
5 
6 
7 #include "oofpch_r.h" // for precompilation of report files
8 
9 #ifndef _INC_WINDOWSX
10  #include "windowsx.h"
11 #endif
12 
13 #ifdef OOF_MEM_DEBUG_LAST_INCLUDE
14  #include OOF_MEM_DEBUG_LAST_INCLUDE
15 #endif
16 
17 #ifndef OOF_NO_STDLIB
18  #ifndef std
19  using namespace std;
20  #endif
21 #endif
22 
23 
24 // -------------------------------------------------------
25 // o o f R e p W i n E n v
26 // -------------------------------------------------------
28 {
29 // now the magic bit.
30 // by dereferencing this, we make an overriding function match against the virtual
31 // method that takes an oofRepWinEnv&.
32 // The implication is that, if we add an environment, each drawable must have a makeRender
33 // added to match, or it will not be rendered (the base empty method will be invoked).
34 
35 // eg: if we need to handle printing and previewing differently on the Mac, we would end up
36 // with a makeRender(const oofRepMacPrint&) and makeRender(const oofRepMacGUIPreviewPP&)
37 // for each oofRepDrawable
38 
39 // The alternative would be to have each environment know each drawable. That is far
40 // less extensible - users can add their own drawables that we wouldn't know about,
41 // so the environment classes wouldn't be closed for extension.
42  drawable->makeRender(*this);
43 }
44 
46 {
47  drawable->makeRender(*this);
48 }
49 
51 {
52  return eRenderType;
53 }
54 
55 unsigned short
57 {
58  if (theStyle != NULL)
59  {
60  HDC ic = oofCurrentDraw::getInfoDC();
61  assert(ic != NULL);
62 
63  LOGFONT lf = theStyle->getLogFont();
64 // const int pixelsY = ::GetDeviceCaps(ic, LOGPIXELSY);
65  lf.lfHeight = -theStyle->fontSize(); // -MulDiv(theStyle->fontSize(), pixelsY, 72);
66  HFONT hFont = oofTextDrawer::createFontIndirect(&lf);
67  assert(hFont != NULL);
68  HFONT hOldFont = (HFONT)::SelectObject(ic, hFont);
69  assert(hOldFont);
70 
71  TEXTMETRIC aTM;
72  memset(&aTM, 0, sizeof(TEXTMETRIC));
73  ::GetTextMetrics(ic, &aTM);
74 
75  ::SelectObject(ic, hOldFont);
76  ::DeleteObject(hFont);
77 
78  return (unsigned short)aTM.tmHeight;
79  }
80  else
81  return 10;
82 }
83 
84 
85 SIZE
87 {
88  HDC ic = oofCurrentDraw::getInfoDC();
89  assert(ic != NULL);
90 
91  LOGFONT lf = textStyle->getLogFont();
92  lf.lfHeight = -textStyle->fontSize(); // -MulDiv(textStyle->fontSize(), ::GetDeviceCaps(ic, LOGPIXELSY), 72);
93 
94  HFONT hFont = oofTextDrawer::createFontIndirect(&lf);
95  HFONT hOldFont = (HFONT)::SelectObject(ic, hFont);
96 
97  SIZE size;
98 // doesn't work with win32s ::GetTextExtentPoint32(ic, text, text.length(), &size);
99  const unsigned long textLen = text.length();
100  if (textLen==0)
101  size.cx = 0;
102  else {
103  DWORD retSize = ::GetTabbedTextExtent(ic, text, textLen, 0, 0 /* no tab positions */);
104  if (retSize==0) {
105  const DWORD lastErr = ::GetLastError(); //lint !e165 not ref // so we can check in debugger
106  assert(!"Error in oofRepWinEnv::getTextExtent() getting text size"); //lint !e506 constant Boolean
107  }
108  else
109  size.cx = LOWORD(retSize); // assume don't care about cy - NOT YET IMPLEMENTED rewrite this call to return X value alone
110  }
111  ::SelectObject(ic, hOldFont);
112  ::DeleteObject(hFont);
113 
114  return size;
115 }
116 
117 
118 void
120 {
121  oofCurrentDraw::resetCoordinates();
122 }
123 
124 
125 // -------------------------------------------------------
126 // r e n d e r f a c t o r i e s
127 // -------------------------------------------------------
128 void
130 {
131  delete mRender;
132  mRender = new oofRepSpaceBand_WinRender(this);
133 }
134 
135 
136 void
138 {
139  delete mRender;
140  mRender = new oofRepGraphBand_WinRender(this);
141 }
142 
143 
144 void
146 {
147  delete mRender;
148  mRender = new oofRepLineBand_WinRender(this);
149 }
150 
151 
152 void
154 {
155  delete mRender;
156  mRender = new oofRepPictBand_WinRender(this);
157 }
158 
159 
160 void
162 {
163  delete mRender;
164  mRender = new oofRepTextBlock_WinRender(this);
165 }
166 
167 
168 void
170 {
171  delete mRender;
172  mRender = new oofRepPictBlock_WinRender(this);
173 }
174 
175 
176 void
178 {
179  delete mRender;
180  mRender = new oofRepLayoutBand_WinRender(this);
181 }
182 
183 
184 void
186 {
187  delete mRender; // assume if we're called and have existing it's wrong type
188  oofRepViewBand_Render* theRender = new oofRepViewBand_WinRender(this);
189  mRender = theRender;
190  mTableExtraRender = theRender;
191  mRender->finishConstruction();
192 }
193 
194 
195 void
197 {
198  MakeAnyRender();
199 }
200 
201 
202 
203 // -------------------------------------------------------
204 // o o f R e p V i e w B a n d _ W i n R e n d e r
205 // -------------------------------------------------------
208 {
209  return new oofRepViewBand_WinRender((oofRepViewBand*)newOwner); // safe downcast
210 }
211 
212 
213 void
215 {
217  if (!mDrawnColHeadersThisPage) // indicates will be drawing them
218  mColHeaders.initSizers(mOwner->view()->count());
219 }
220 
221 
222 void
224 {
225 // reset here in case we redraw a Windows render once constructed,
226 // eg: if printing after generating a preview
227  if (oofRep::currentReport()->shouldDrawViewColumnHeaders()) {
228  mDrawnColHeadersThisPage = false;
229  if (headersHaveChanged)
230  CalcColHeaderWrapping();
231  }
232  else
233  mDrawnColHeadersThisPage = true;
234 }
235 
236 
237 void
239 {
240  dbView* view = mOwner->view();
241  const unsigned short numFlds = view->count();
242 
243 // HACK - force column headers to bold, NOT YET IMPLEMENTED - need a global setting for this
244  oofRepTextStyle* OS = mOwner->textStyle();
245  oofRepTextStyle hackStyle(OS->fontName(), OS->fontSize(), bold);
246  oofRep::currentReport()->changeTextStyle(&hackStyle);
247 
248  view->start();
249  for (unsigned short i=0; i<numFlds; i++) {
250  mColHeaders.text(i) = view->getHeading(i);
251  mColHeaders.CalculateWrapping(i,view->colSizer()->width(i));
252  }
253 }
254 
255 
256 void
258 {
259  oofRep* curRep = oofRep::currentReport();
260  const oofRepSettings* currSettings = curRep->settings();
261  const unsigned short colSepWidth = currSettings->colSepWidth();
262 //AD981030 const unsigned short bandIndenting = currSettings->bandIndenting();
263 //AD981030 const unsigned long bodyWidth = curRep->bodyWidth();
264 //AD981030 const unsigned short leftMargin = currSettings->leftMargin();
265 
266  mDrawnColHeadersThisPage = true; // not conditional! we want to avoid calling this method again this page
267  if (!curRep->shouldDrawViewColumnHeaders())
268  return;
269 
270  dbView* view = mOwner->view();
271  const unsigned numFlds = view->count();
272 
273 // HACK - force column headers to bold, NOT YET IMPLEMENTED - need a global setting for this
274  oofRepTextStyle* OS = mOwner->textStyle();
275  oofRepTextStyle hackStyle(OS->fontName(), OS->fontSize(), bold);
276  oofRepTextStyle* style = &hackStyle; // changes all code below that used to refer to owner's style
277 
278  curRep->changeTextStyle(style);
279  const unsigned short lineHeight = style->fixedHeight()+style->leading();
280  const short DrawHeight = mColHeaders.maxRows()*lineHeight;
281  HDC hdc = oofCurrentDraw::getCurrentDC();
282 
283  // Render the Headers
284  unsigned long xPos=currSettings->leftMargin()+currSettings->bandIndenting();
285 
286  const unsigned long adornCount = mOwner->adorners().count();
287  unsigned long cellY = 0;
288 
289  if( adornCount )
290  xPos += colSepWidth/2;
291 
292  for(unsigned int i=0;i<numFlds;i++){
293  unsigned short numrows=mColHeaders.GetNumRows(i);
294  const unsigned long* lines = mColHeaders.GetLineStarts(i);
295  const unsigned long* lengths = mColHeaders.GetLineLengths(i);
296  short bytes;
297  oofColSizer::colAlignT alignment = view->colSizer()->alignment(i);
298  // Cope with natural alignment
299  if(alignment==oofColSizer::alignNatural)
300  alignment = oofColSizer::naturalAlignmentForField(view->field(i).fieldType());
301 
302  const int ybase=curRep->currentVerticalPos()-style->leading();
303 
304  // Adorner information for the cell
305  unsigned long cellWidth = view->colSizer()->width(i) + colSepWidth;
306  unsigned long cellHeight = DrawHeight;
307  int cellHorizontalPos = xPos - (colSepWidth/2);
308  int cellVerticalPos = curRep->currentVerticalPos();
309 
310  if( i==numFlds-1 ) { // resize the last cell to right edge
311  cellWidth = curRep->bodyWidth() - currSettings->bandIndenting() +
312  currSettings->leftMargin() + (colSepWidth/2) - xPos;
313  }
314 
315  if( adornCount ) {
316  // call before adorners for cell
317  mOwner->adorners().start();
318  for( unsigned long ad=0; ad<adornCount; ad++ ) {
319  oofAdorner* currentAdorner = mOwner->adorners().current();
320  if( currentAdorner->drawWhen() == oofAdorner::drawBefore ) {
321  oofCurrentDraw::moveToEx( hdc, cellHorizontalPos, cellVerticalPos, NULL );
322  currentAdorner->drawcell(i,cellY,mOwner,cellHeight,cellWidth);
323  }
324  mOwner->adorners().next();
325  }
326  }
327 
328  for(unsigned short rownum=0;rownum<numrows;rownum++){
329  unsigned long drawPos;
330  switch(alignment){
331  case (oofColSizer::alignRight):{
332  drawPos=xPos+view->colSizer()->width(i)-lengths[rownum];
333  }
334  break;
335  case (oofColSizer::alignCentre):{
336  drawPos=xPos+((view->colSizer()->width(i)-lengths[rownum])/2);
337  }
338  break;
339  default: drawPos=xPos;
340  break;
341  }
342  const OOF_String& text = mColHeaders.text(i);
343  if(rownum==(numrows-1))
344  bytes=text.length()-lines[rownum];
345  else
346  bytes=lines[rownum+1]-lines[rownum];
347  if (bytes>0) {
348  const int yPos = ybase+rownum*lineHeight;
349  oofWinTextDE::recordElement( drawPos, yPos, text.chars() + lines[rownum], bytes);
350 //981015 oofTextDrawer::textOut(oofCurrentDraw::getCurrentDC(), drawPos, yPos, Text[i]+lines[rownum],bytes);
351  }
352  }
353  /* ::MoveTo(xPos,ybase+numrows*(fi.ascent+fi.descent+fi.leading+textStyle()->leading())+1);
354  ::PenSize(1,1);
355  ::Line(mview->colSizer()->width(i),0); // Rule under the headings
356  */
357  //xPos+=view->colSizer()->width(i)+curRep->settings()->colSepWidth();
358  //if((isBoxed)&&(i<numflds-1)){
359  // ::MoveToEx(
360  // oofCurrentDraw::getCurrentDC(),
361  // xPos-(curRep->settings()->colSepWidth()/2),
362  // curRep->currentVerticalPos(),
363  // NULL);
364  // ::LineTo(hdc, 0, DrawHeight);
365  //}
366 
367  if( adornCount ) {
368  // call after adorners for cell
369  mOwner->adorners().start();
370  for( unsigned long ad=0; ad<adornCount; ad++ ) {
371  oofAdorner* currentAdorner = mOwner->adorners().current();
372  if( currentAdorner->drawWhen() == oofAdorner::drawAfter ) {
373  oofCurrentDraw::moveToEx( hdc, cellHorizontalPos, cellVerticalPos, NULL );
374  currentAdorner->drawcell(i,cellY,mOwner,cellHeight,cellWidth);
375  }
376  mOwner->adorners().next();
377  }
378  }
379 
380  xPos += view->colSizer()->width(i) + colSepWidth;
381  }
382  curRep->currentVerticalPos() += DrawHeight;
383 
384 //AD983010 delete [] Text;
385 //AD983010 delete [] Sizer;
386 }
387 
388 
389 void
391 {
392  HDC hdc = oofCurrentDraw::getCurrentDC();
393  oofRep* curRep = oofRep::currentReport();
394  const oofRepSettings* curSettings = curRep->settings();
395  const unsigned short colSepWidth = curSettings->colSepWidth();
396  const unsigned short bandIndenting = curSettings->bandIndenting();
397  const unsigned long bodyWidth = curRep->bodyWidth();
398  const unsigned short leftMargin = curSettings->leftMargin();
399 
400  oofRepTextStyle* style = mOwner->textStyle();
401 
403 // int charHeight = style->calcCharHeight();
404 // int charHeight = style->fixedHeight();
405 // int descent = style->calcDescent();
406  const unsigned short lineHeight = style->fixedHeight()+style->leading();
407  dbView* view = mOwner->view();
408 
409  const unsigned numFlds=view->count();
410  oofSizedTextArray sizedBody(numFlds);
411 
412  // Setup for adorners
413  const unsigned long adornCount = mOwner->adorners().count();
414  unsigned long cellY;
415  if( adornCount ) {
416  // Calculate the current record number we're drawing
417  cellY = view->recordNumber();
418  }
419  else
420  cellY = 0;
421 
422  unsigned int i;
423 
424  // Get the field text and calculate the wrapping and height
425  view->start();
426  bool hasCustomDrawers=false;
427  unsigned long maxCustomDrawerHeight = 0;
428  for (i=0; i<numFlds; i++) {
429  oofRepCustomViewDrawer* theDrawer = mOwner->customDrawer(i);
430  if (theDrawer) {
431  hasCustomDrawers = true;
432  unsigned long wrappedHeight;
433  theDrawer->calculateWrapping(&view->field(i), view->colSizer()->width(i), wrappedHeight);
434  if (wrappedHeight>maxCustomDrawerHeight)
435  maxCustomDrawerHeight = wrappedHeight;
436  curRep->changeTextStyle(style); // in case custom drawer changed
437  }
438  else {
439  sizedBody.text(i) = view->field(i).copyString();
440  sizedBody.CalculateWrapping(i,view->colSizer()->width(i));
441  }
442  }
443  unsigned short colHeaderHeight = 0;
444  if (!mDrawnColHeadersThisPage)
445  colHeaderHeight = mColHeaders.maxRows()*lineHeight; // add in col headers when deciding if room on page
446 
447  unsigned short rowDrawHeight = sizedBody.maxRows()*lineHeight;
448  if (maxCustomDrawerHeight>rowDrawHeight)
449  rowDrawHeight = maxCustomDrawerHeight;
450  const unsigned short DrawHeight = rowDrawHeight + colHeaderHeight;
451 
452  // Render the Fields
453  unsigned long xPos = leftMargin + bandIndenting;
454 
455  if( (DrawHeight + curRep->currentVerticalPos()) > curRep->bodyEnd() ) {
456  // We don't fit, and we'll need to cope with this!
457  DrawContinuingOverPage( 0, DrawHeight, sizedBody, hasCustomDrawers);
458  } else {
459  if( adornCount ) {
460  xPos += colSepWidth/2;
461  }
462  if( !mDrawnColHeadersThisPage ) {
463  mOwner->drawColumnHeaders();
464  // restore the style - col headers may have changed this
465  curRep->changeTextStyle( mOwner->textStyle());
466  }
467 
468  for(i=0;i<numFlds;i++){
469  oofColSizer::colAlignT alignment = view->colSizer()->alignment(i);
470  // Cope with natural alignment
471  if(alignment==oofColSizer::alignNatural)
472  alignment = oofColSizer::naturalAlignmentForField(view->field(i).fieldType());
473 
474  // Windows different vertical motion!
475  int ybase=oofRep::currentReport()->currentVerticalPos() - style->leading();
476 
477  // Adorner information for the cell
478  unsigned long cellWidth = view->colSizer()->width(i) + colSepWidth;
479  unsigned long cellHeight = rowDrawHeight;
480  int cellHorizontalPos = xPos - (colSepWidth/2);
481  int cellVerticalPos = curRep->currentVerticalPos()-1;
482 
483  if( i==numFlds-1 ) {
484  cellWidth = bodyWidth - bandIndenting + leftMargin + (colSepWidth/2) - xPos;
485  }
486 
487  if( adornCount ) {
488  // call before adorners for cell
489  mOwner->adorners().start();
490  for( unsigned long ad=0; ad<adornCount; ad++ ) {
491  oofAdorner* currentAdorner = mOwner->adorners().current();
492  if( currentAdorner->drawWhen() == oofAdorner::drawBefore ) {
493  oofCurrentDraw::moveToEx( hdc, cellHorizontalPos, cellVerticalPos, NULL );
494  currentAdorner->drawcell(i,cellY,mOwner,cellHeight,cellWidth);
495  }
496  mOwner->adorners().next();
497  }
498  }
499  // draw the contents of the cell
500  oofRepCustomViewDrawer* theDrawer = mOwner->customDrawer(i);
501  if (theDrawer) {
502  oofDE::appendElement(theDrawer->makeDrawDE(xPos, ybase));
503  curRep->changeTextStyle(style); // in case custom drawer changed style
504  }
505  else { // draw normal text
506  unsigned short numrows=sizedBody.GetNumRows(i);
507  const unsigned long* lines = sizedBody.GetLineStarts(i);
508  const unsigned long* lengths = sizedBody.GetLineLengths(i);
509 
510  unsigned short bytes;
511  for(unsigned short rownum=0;rownum<numrows;rownum++){
512  if (lengths[rownum]) {
513  unsigned long drawPos;
514  switch(alignment){
515  case (oofColSizer::alignRight):{
516  drawPos=xPos+view->colSizer()->width(i)-lengths[rownum];
517  }
518  break;
519  case (oofColSizer::alignCentre):{
520  drawPos=xPos+((view->colSizer()->width(i)-lengths[rownum])/2);
521  }
522  break;
523  default: drawPos=xPos;
524  break;
525  }
526  if(rownum==(numrows-1)) {
527  // all the bytes in the string minus the start of the last line
528  bytes=sizedBody.text(i).length()-lines[rownum];
529  }
530  else
531  bytes=lines[rownum+1]-lines[rownum];
532 
533  // bit of a hack to avoid CRLF at end of line
534  {
535  const char* lastLine = lines[rownum] + sizedBody.text(i).chars();
536  if (bytes>0) {
537  unsigned long lastCharAt = bytes -1;
538  char lastChar = lastLine[lastCharAt];
539  while(lastCharAt >0 && (lastChar=='\r' || lastChar=='\n')) {
540  lastCharAt--;
541  lastChar = lastLine[lastCharAt];
542  }
543  bytes = lastCharAt+1;
544  }
545  }
546  if (bytes) {
547  const int yPos = ybase+rownum * lineHeight;
548  oofWinTextDE::recordElement( drawPos, yPos, sizedBody.text(i).chars() + lines[rownum], bytes);
549  //981015 oofTextDrawer::textOut(hdc, drawPos, yPos, sizedBody.text(i)+ lines[rownum], bytes);
550  }
551  } // if any length in this row
552  } // loop through rows of report
553  } // custom draw vs normal text
554 
555  if( adornCount ) {
556  // call after adorners for cell
557  mOwner->adorners().start();
558  for( unsigned long ad=0; ad<adornCount; ad++ ) {
559  oofAdorner* currentAdorner = mOwner->adorners().current();
560  if( currentAdorner->drawWhen() == oofAdorner::drawAfter ) {
561  oofCurrentDraw::moveToEx( hdc, cellHorizontalPos, cellVerticalPos, NULL );
562  currentAdorner->drawcell(i,cellY,mOwner,cellHeight,cellWidth);
563  }
564  mOwner->adorners().next();
565  }
566  }
567 
568  xPos += view->colSizer()->width(i) + colSepWidth;
569  }
570  oofRep::currentReport()->currentVerticalPos() += rowDrawHeight;
571  }
572 }
573 
574 
575 void
576 oofRepViewBand_WinRender::DrawContinuingOverPage(unsigned long startRow, unsigned long heightLeft, oofSizedTextArray& sizedBody, bool hasCustomDrawers)
577 {
578 // NOTE heightLeft will include the height of the column headers if they are still to be printed
579 
580  HDC hdc = oofCurrentDraw::getCurrentDC();
581  dbView* view = mOwner->view();
582  const unsigned long numFlds = view->count();
583  oofRep* curRep = oofRep::currentReport();
584  const oofRepSettings* curSettings = curRep->settings();
585  const unsigned short colSepWidth = curSettings->colSepWidth();
586  const unsigned short bandIndenting = curSettings->bandIndenting();
587 // const unsigned long bodyWidth = curRep->bodyWidth();
588  const unsigned short leftMargin = curSettings->leftMargin();
589  oofRepTextStyle* style = mOwner->textStyle();
590 
591  const unsigned long adornCount = mOwner->adorners().count();
592  unsigned long cellY;
593 
594  if( adornCount ) {
595  // Calculate the current record number we're drawing
596  cellY = view->recordNumber();
597  }
598  else
599  cellY = 0;
600 
601  unsigned long xPos = leftMargin + bandIndenting;
602  bool lastpage = false;
603  unsigned long DrawHeight = 0, rowDrawHeight=0;
604 
605 // draw whatever fits on the page, or the remaining portion of the record
606 
607  long roomLeftOnPage = curRep->bodyEnd() - curRep->currentVerticalPos();
608  if( roomLeftOnPage < 0 )
609  roomLeftOnPage = 0; // even one line won't fit, so force to next page
610 
611  if( heightLeft > roomLeftOnPage ) {
612  DrawHeight = roomLeftOnPage; // WARNING may be less than one line room left!!!
613  } else {
614  DrawHeight=heightLeft;
615  lastpage=true;
616  }
617 
618  curRep->changeTextStyle( style );
619  const unsigned long lineHeight = style->fixedHeight() + style->leading();
620 
621  unsigned long possiblerows;
622  if (!mDrawnColHeadersThisPage) {
623  const unsigned long colHeaderHeight = mColHeaders.maxRows()*lineHeight;
624 // colHeaderHeight will only be non-zero if we are drawing headers and haven't yet drawn them
625  rowDrawHeight = DrawHeight-colHeaderHeight;
626  if (DrawHeight > colHeaderHeight)
627  possiblerows = rowDrawHeight/lineHeight; // must be truncation divide - don't draw half rows
628  else
629  possiblerows = 0;
630  }
631  else {
632  possiblerows=DrawHeight/lineHeight; // could be zero rows if a single line too tall
633  rowDrawHeight = DrawHeight;
634  }
635 
636  unsigned long maxCustomDrawerHeight = 0; // largest chunk drawn by a custom drawer
637  // helps define total height drawn if a custom drawer is a few pixels higher than adjacent rows of uniform text
638  unsigned long maxCustomDrawerHeightLeft = 0; // our total left - allows for custom drawers to take more room
639  // drawing in chunks than in the original estimate of a single chunk, so our incoming heightLeft may be too low
640  // if we have a page break this page - see the correction before recursing below
641 
642  if (hasCustomDrawers) {
643  // repeat a loop to calc height each page because we don't assume that N rows are
644  // consumed, unlike the plain text, as we know NOTHING about what is drawn and
645  // a custom drawer is free to consume more height over multiple pages than it
646  // said its unbroken total height would be
647  for (unsigned int i=0; i<numFlds; i++) {
648  oofRepCustomViewDrawer* theDrawer = mOwner->customDrawer(i);
649  if (theDrawer) {
650  unsigned long drawnHeight;
651  const unsigned long heightLeftToDraw = theDrawer->calcNextDrawHeight(rowDrawHeight, drawnHeight);
652  if (drawnHeight > maxCustomDrawerHeight)
653  maxCustomDrawerHeight = drawnHeight;
654  assert(drawnHeight<=rowDrawHeight);
655  if (heightLeftToDraw>0) {
656  lastpage=false; // correction to calc above, in case the custom draw broke in a way
657  // that changed the remaining height we've been passing through. We might have thought
658  // this is the last page because other columns fit, but this could correct that.
659  if (heightLeftToDraw > maxCustomDrawerHeightLeft)
660  maxCustomDrawerHeightLeft = heightLeftToDraw;
661  } // height to draw
662  curRep->changeTextStyle(style); // in case custom drawer changed
663  } // custom drawer
664  } // loop fields to see if have custom draw
665  } // if has custom draw
666 
667  unsigned short rowsDrawn;
668  if( lastpage || possiblerows > 1 ) { // don't allow a widow left on page if more than one row to draw
669 
670  if( adornCount ) {
671  xPos+=colSepWidth/2;
672  }
673 
674  // we know we have made room for the col headers if not drawn on this page
675  if (!mDrawnColHeadersThisPage) {
676  mOwner->drawColumnHeaders();
677 // restore the style - headers may have changed
678  curRep->changeTextStyle(style);
679  }
680 
681  for( unsigned long i=0; i<numFlds; i++ ) {
682  oofColSizer::colAlignT alignment = view->colSizer()->alignment(i);
683  // Cope with natural alignment
684  if(alignment==oofColSizer::alignNatural)
685  alignment = oofColSizer::naturalAlignmentForField(view->field(i).fieldType());
686 
687  // Windows different vertical motion!
688  int ybase=curRep->currentVerticalPos() - style->leading();
689 
690  // Adorner information for the cell
691  long cellWidth = view->colSizer()->width(i) + colSepWidth;
692  long cellHeight = rowDrawHeight;
693  int cellHorizontalPos = xPos-(colSepWidth/2);
694  int cellVerticalPos = curRep->currentVerticalPos()-1;
695 
696  if( i==numFlds-1 ) { // resize the last cell to right edge
697  cellWidth = curRep->bodyWidth() - curSettings->bandIndenting() +
698  curSettings->leftMargin() + (colSepWidth/2) - xPos;
699  }
700 
701  if (adornCount) {
702  // call before adorners for cell
703  mOwner->adorners().start();
704  for( unsigned long ad=0; ad<adornCount; ad++ ) {
705  oofAdorner* currentAdorner = mOwner->adorners().current();
706  if( currentAdorner->drawWhen() == oofAdorner::drawBefore ) {
707  oofCurrentDraw::moveToEx( hdc, cellHorizontalPos, cellVerticalPos, NULL );
708  // draw the correct style for draw overrun cells
709  if( lastpage ) {
710  if( startRow ) {
711  currentAdorner->drawcell( i, cellY, mOwner, cellHeight, cellWidth, oofAdorner::continueStop );
712  } else {
713  currentAdorner->drawcell( i, cellY, mOwner, cellHeight, cellWidth, oofAdorner::startStop );
714  }
715  } else {
716  if( !startRow ) {
717  currentAdorner->drawcell( i, cellY, mOwner, cellHeight, cellWidth, oofAdorner::startContinue );
718  } else {
719  currentAdorner->drawcell( i, cellY, mOwner, cellHeight, cellWidth, oofAdorner::continueContinue );
720  }
721  }
722  }
723  mOwner->adorners().next();
724  }
725  }
726 
727  oofRepCustomViewDrawer* theDrawer = mOwner->customDrawer(i);
728  if (theDrawer) {
729  oofDE::appendElement(theDrawer->makeDrawDE(xPos, ybase));
730  curRep->changeTextStyle(style); // in case custom drawer changed style
731  }
732  else {
733  long rowsToEndField = sizedBody.GetNumRows(i) - startRow;
734  long numRowsFldOnPage;
735  if( rowsToEndField < 0 ) { // This field might not have any more rows to draw
736  numRowsFldOnPage = 0;
737  rowsToEndField = 0;
738  }
739  if( rowsToEndField > possiblerows )
740  numRowsFldOnPage = possiblerows;
741  else
742  numRowsFldOnPage = rowsToEndField;
743  const unsigned long* lines = sizedBody.GetLineStarts(i);
744  const unsigned long* lengths = sizedBody.GetLineLengths(i);
745  short bytes;
746  // OK - for clarity:
747  // * rownum is always 0-based here, but is offset by startRow from the actual textSizer row
748  // * numRowsFldOnPage is the number of rows we can fit on this page
749  // So we always use these values unmodified for calculating position, BUT
750  // we use them offset for any calculations on the sizer info...
751  for(unsigned short rownum=0;rownum<numRowsFldOnPage;rownum++){
752  const unsigned short actualRow = rownum+startRow;
753  if (lengths[actualRow]) {
754  unsigned long drawPos;
755  switch(alignment){
756  case (oofColSizer::alignRight):{
757  drawPos=xPos+view->colSizer()->width(i)-lengths[actualRow];
758  }
759  break;
760  case (oofColSizer::alignCentre):{
761  drawPos=xPos+((view->colSizer()->width(i)-lengths[actualRow])/2);
762  }
763  break;
764  default: drawPos=xPos;
765  break;
766  }
767  if(actualRow==(sizedBody.GetNumRows(i)-1)) {
768  if (rowsToEndField>numRowsFldOnPage) // more in this field than on this page
769  bytes=lines[actualRow+1]-lines[actualRow]; // so safe to measure to line on next page
770  else
771  bytes=sizedBody.text(i).length()-lines[actualRow]; // remaining text in string is this line
772  }
773  else
774  bytes=lines[actualRow+1]-lines[actualRow];
775 
776  // bit of a hack to avoid CRLF at end of line
777  {
778  const char* lastLine = sizedBody.text(i).chars() + lines[actualRow];
779  if (bytes>0) {
780  unsigned long lastCharAt = bytes -1;
781  char lastChar = lastLine[lastCharAt];
782  while(lastCharAt >0 && (lastChar=='\r' || lastChar=='\n')) {
783  lastCharAt--;
784  lastChar = lastLine[lastCharAt];
785  }
786  bytes = lastCharAt+1;
787  }
788  }
789 
790  if (bytes>0) {
791  const char* toDraw = sizedBody.text(i).chars() + lines[actualRow];
792  const int yPos = ybase+rownum * lineHeight;
793  oofWinTextDE::recordElement( drawPos, yPos, toDraw, bytes);
794  // oofTextDrawer::textOut(hdc, drawPos, yPos, toDraw, bytes);
795  }
796  } // if any length in this row
797  } // loop through rows of report
798  } // draw custom or normal
799 
800  if (adornCount) {
801  // call after adorners for cell
802  mOwner->adorners().start();
803  for( unsigned long ad=0; ad<adornCount; ad++ ) {
804  oofAdorner* currentAdorner = mOwner->adorners().current();
805  if( currentAdorner->drawWhen() == oofAdorner::drawAfter ) {
806  oofCurrentDraw::moveToEx( hdc, cellHorizontalPos, cellVerticalPos, NULL );
807  //::MoveTo(cellHorizontalPos, cellVerticalPos);
808  // draw the correct style for draw overrun cells
809  if( lastpage ) {
810  if( startRow ) {
811  currentAdorner->drawcell( i, cellY, mOwner, cellHeight, cellWidth, oofAdorner::continueStop );
812  } else {
813  currentAdorner->drawcell( i, cellY, mOwner, cellHeight, cellWidth, oofAdorner::startStop );
814  }
815  } else {
816  if( !startRow ) {
817  currentAdorner->drawcell( i, cellY, mOwner, cellHeight, cellWidth, oofAdorner::startContinue );
818  } else {
819  currentAdorner->drawcell( i, cellY, mOwner, cellHeight, cellWidth, oofAdorner::continueContinue );
820  }
821  }
822  }
823  mOwner->adorners().next();
824  }
825  }
826  xPos+=view->colSizer()->width(i)+colSepWidth;
827  }
828  rowsDrawn = possiblerows;
829  unsigned long heightDrawn = rowsDrawn*lineHeight;
830  if (maxCustomDrawerHeight > heightDrawn)
831  heightDrawn = maxCustomDrawerHeight; // may have custom draw go a few pixels past the rows
832  assert (heightDrawn <= DrawHeight); // difference is fractional row that didn't fit
833  heightLeft -= heightDrawn;
834  if (maxCustomDrawerHeightLeft > heightLeft)
835  heightLeft = maxCustomDrawerHeightLeft; // may have custom draw extend the earlier total
836  } // fitted at least 2 rows
837  else {
838 // heightLeft stays the same as on entry - ie: we've called overrun from draw because row didn't fit entirely on original page
839  rowsDrawn = 0;
840  }
841 
842  if(!lastpage){
843  oofRepEnvironment* theEnv = curRep->environment();
844  theEnv->splitBandOverPage();
845  curRep->drawPageBreak();
846 
847  // unconditionally draw headers - we KNOW we haven't drawn them
848  mOwner->drawColumnHeaders(); // NOT YET IMPLEMENTED - setting to say that we don't draw these on subsequent pages
849  theEnv->resumeBandOverPage();
850  curRep->changeTextStyle(mOwner->textStyle()); // In case the page break or col headers changed styles
851  DrawContinuingOverPage(startRow+rowsDrawn, heightLeft, sizedBody, hasCustomDrawers);
852  } else
853  curRep->currentVerticalPos() += DrawHeight;
854 }
855 
856 
857 // -------------------------------------------------------
858 // o o f R e p S p a c e B a n d _ W i n R e n d e r
859 // -------------------------------------------------------
862 {
863  return new oofRepSpaceBand_WinRender((oofRepSpaceBand*)newOwner); // safe downcast
864 }
865 
866 
867 void
869 {
870  oofRep::currentReport()->currentVerticalPos() += mOwner->fixedHeight();
871 }
872 
873 
874 // -------------------------------------------------------
875 // o o f R e p G r a p h B a n d _ W i n R e n d e r
876 // -------------------------------------------------------
879 {
880  return new oofRepGraphBand_WinRender((oofRepGraphBand*)newOwner); // safe downcast
881 }
882 
883 
884 void
886 {
887  oofRep* currentReport = oofRep::currentReport();
888  bool printMono = currentReport->environment()->isPrintingEnvironment() && currentReport->settings()->printGraphsInMono();
889  if (printMono)
890  mOwner->graph()->setStyleToMono();
891 
892  currentReport->changeTextStyle(mOwner->textStyle());
893 
894  const unsigned long drawingHeight = mOwner->drawingHeight();
895  const unsigned long bodyWidth = currentReport->bodyWidth();
896  const unsigned long graphWidth = mOwner->graphWidth();
897  const unsigned long graphHeight = mOwner->graphHeight();
898 
899  assert(mOwner->graphWidth()>0);
900 
901  oofRect theFrame;
902 
903  unsigned long graphLeft, graphRight, graphBottom, graphTop;
904  if (bodyWidth > graphWidth) {
905  graphLeft = (bodyWidth-graphWidth)/2;
906  graphRight = graphWidth+graphLeft;
907  }
908  else {
909  graphLeft = 0;
910  graphRight = bodyWidth;
911  }
912  if (drawingHeight > graphHeight) {
913  graphTop = (drawingHeight-graphHeight)/2;
914  graphBottom = graphTop+graphHeight;
915  }
916  else {
917  graphTop = 0;
918  graphBottom = drawingHeight;
919  }
920  theFrame.set(graphLeft,graphTop,graphRight ,graphBottom);
921 
922  theFrame.offset(currentReport->settings()->leftMargin(),
923  currentReport->currentVerticalPos());
924 
925  oofGraphDE::recordElement(theFrame, mOwner->graph(), printMono);
926 
927  mOwner->graph()->setPaneRect(theFrame);
928 
929  currentReport->currentVerticalPos() += drawingHeight;
930 
931  if (printMono)
932  mOwner->graph()->setStyleToColor();
933 }
934 
935 
936 // -------------------------------------------------------
937 // o o f R e p L i n e B a n d _ W i n R e n d e r
938 // -------------------------------------------------------
941 {
942  return new oofRepLineBand_WinRender((oofRepLineBand*)newOwner); // safe downcast
943 }
944 
945 
946 void
948 {
949  unsigned long fixedHeight = mOwner->fixedHeight();
950  oofRect theLine;
951 
952  theLine.set(oofRep::currentReport()->settings()->leftMargin() +
953  oofRep::currentReport()->settings()->bandIndenting(),
954  oofRep::currentReport()->currentVerticalPos(),
955  oofRep::currentReport()->settings()->leftMargin() +
956  oofRep::currentReport()->bodyWidth() -
957  oofRep::currentReport()->settings()->bandIndenting(),
958  oofRep::currentReport()->currentVerticalPos() + fixedHeight);
959 //981015 HDC hdc = oofCurrentDraw::getCurrentDC();
960 
961  if( mOwner->grey() )
962  {
963 //981015 ::FillRect(hdc, theLine, (HBRUSH)GetStockObject(GRAY_BRUSH));
964  oofWinShadeDE::recordElement(theLine, GRAY_BRUSH);
965  }
966  else {
967 //981015 ::FillRect(hdc, theLine, (HBRUSH)GetStockObject(BLACK_BRUSH));
968  oofWinShadeDE::recordElement(theLine, BLACK_BRUSH);
969  }
970 
971  oofRep::currentReport()->currentVerticalPos() += fixedHeight;
972 }
973 
974 // -------------------------------------------------------
975 // o o f R e p P i c t B a n d _ W i n R e n d e r
976 // -------------------------------------------------------
979 {
980  return new oofRepPictBand_WinRender((oofRepPictBand*)newOwner); // safe downcast
981 }
982 
983 
984 void
986 {
987  const unsigned short leftMargin = oofRep::currentReport()->settings()->leftMargin();
988  const unsigned short topBand = oofRep::currentReport()->currentVerticalPos();
990  leftMargin,
991  topBand,
992  leftMargin + oofRep::currentReport()->bodyWidth(),
993  topBand+mOwner->fixedHeight(),
994  mOwner->picture()
995  );
996  oofRep::currentReport()->currentVerticalPos() += mOwner->fixedHeight();
997 }
998 
999 
1000 // -------------------------------------------------------
1001 // o o f R e p T e x t B l o c k _ W i n R e n d e r
1002 // -------------------------------------------------------
1003 oofRepRender*
1005 {
1006  return new oofRepTextBlock_WinRender((oofRepTextBlock*)newOwner); // safe downcast
1007 }
1008 
1009 
1010 void
1012 {
1013  oofRep::currentReport()->changeTextStyle(mOwner->textStyle());
1014 
1015 //981015 HDC hdc = oofCurrentDraw::getCurrentDC();
1016  const oofString& text = mOwner->text();
1017 //981015 ::SetBkMode(hdc, TRANSPARENT);
1018  oofWinTextDE::recordElement( oofCurrentDraw::x(), oofCurrentDraw::y(), text); // BEFORE textOutCP advances
1019 //981015 oofTextDrawer::textOutCP(hdc, text, width());
1020 }
1021 
1022 
1023 unsigned long
1025 {
1026  oofRep::currentReport()->changeTextStyle(mOwner->textStyle());
1027  return oofRepWinEnv::getTextExtent(mOwner->textStyle(), mOwner->text()).cx;
1028 }
1029 
1030 // -------------------------------------------------------
1031 // o o f R e p P i c t B l o c k _ W i n R e n d e r
1032 // -------------------------------------------------------
1033 oofRepRender*
1035 {
1036  return new oofRepPictBlock_WinRender((oofRepPictBlock*)newOwner); // safe downcast
1037 }
1038 
1039 
1040 void
1042 {
1043  oofPict* thePict = mOwner->picture();
1044  const long pictWidth = mOwner->width();
1045  const long x = oofCurrentDraw::x();
1046  const long y = oofCurrentDraw::y();
1047  const long rightX = x + pictWidth;
1048  const long bottom = y + mOwner->fixedHeight();
1049  oofWinPictDE::recordElement(x, y, rightX, bottom, thePict);
1050 }
1051 
1052 unsigned long
1054 {
1055  return mOwner->width();
1056 }
1057 
1058 
1059 
1060 
1061 // -------------------------------------------------------
1062 // o o f R e p L a y o u t B a n d _ W i n R e n d e r
1063 // -------------------------------------------------------
1064 oofRepRender*
1066 {
1067  return new oofRepLayoutBand_WinRender((oofRepLayoutBand*)newOwner); // safe downcast
1068 }
1069 
1070 
1071 /*
1072 void
1073 oofRepLayoutBand_WinRender::draw()
1074 {
1075  oofRepBlockList& blocks = mOwner->blocks();
1076 
1077  blocks.start();
1078  oofRep::currentReport()->changeTextStyle(blocks()->textStyle());
1079 // int charHeight = mBlocks()->textStyle()->calcCharHeight();
1080 // int ascent = mBlocks()->textStyle()->calcAscent();
1081  int charHeight = blocks()->textStyle()->fixedHeight();
1082  int ascent = 5;
1083 
1084  HDC hdc = oofCurrentDraw::getCurrentDC();
1085 
1086  // When we render the bands, we want to control the positioning from here, not within the
1087  // band itself. Therefore, get the text functions to ignore the positioning arguments
1088  UINT oldAlign = ::GetTextAlign(hdc);
1089  ::SetTextAlign(hdc, oldAlign | TA_UPDATECP);
1090 
1091  ::MoveToEx(hdc, oofRep::currentReport()->settings()->leftMargin() +
1092  oofRep::currentReport()->settings()->bandIndenting(),
1093  oofRep::currentReport()->currentVerticalPos(), NULL);
1094 
1095  while(blocks.more()) {
1096  oofRepBlock* theBlock = blocks();
1097  // KENTODO - Handle other alignments !
1098  // BOLD ASSUMPTION - only one right aligned item per line.
1099  if(theBlock->align()==oofRepBlock::alignRight) {
1100  POINT pt;
1101 
1102  // Get the current position first
1103  ::MoveToEx(hdc, 0, 0, &pt);
1104  // Now reposition properly for the right alignment
1105  ::MoveToEx(hdc, oofRep::currentReport()->bodyWidth() +
1106  oofRep::currentReport()->settings()->leftMargin() -
1107  oofRep::currentReport()->settings()->bandIndenting() -
1108  theBlock->width(), pt.y, NULL);
1109  }
1110 
1111  if(theBlock->align()==oofRepBlock::alignCentre) {
1112  POINT pt;
1113 
1114  // Get the current position first
1115  ::MoveToEx(hdc, 0, 0, &pt);
1116  // Now reposition for centre alignment
1117  ::MoveToEx(hdc, (oofRep::currentReport()->bodyWidth()
1118  +oofRep::currentReport()->settings()->leftMargin())/2
1119  -(theBlock->width()/2), pt.y, NULL);
1120  }
1121 
1122  theBlock->draw();
1123  if (theBlock->fixedWidth()) {
1124  POINT pt;
1125  ::MoveToEx(hdc, 0, 0, &pt);
1126  const int fixedRemainder = theBlock->fixedWidth() - theBlock->width();
1127  ::MoveToEx(hdc, pt.x+fixedRemainder, pt.y, NULL);// move horizontally
1128  }
1129  if (theBlock->moveDownAfter()) {
1130  // KENTODO - Cope with multi-block lines with differing heights !
1131  POINT pt;
1132 
1133  // Get the current position first
1134  ::MoveToEx(hdc, 0, 0, &pt);
1135  // Now reposition properly for the right alignment
1136  ::MoveToEx(hdc, oofRep::currentReport()->settings()->leftMargin() +
1137  oofRep::currentReport()->settings()->bandIndenting(),
1138  pt.y + charHeight + blocks()->textStyle()->leading(), NULL);
1139 
1140  // Terminate this line
1141  blocks.next();
1142  if(blocks.more()) {
1143  oofRep::currentReport()->changeTextStyle(blocks()->textStyle());
1144  }
1145  } else
1146  blocks.next();
1147  }
1148 
1149  // Re-enable the text function positioning
1150  ::SetTextAlign(hdc, oldAlign);
1151 
1152  oofRep::currentReport()->currentVerticalPos() += mOwner->fixedHeight();
1153 }
1154 */
1155 
1156 
1162 void
1164 {
1165  oofRepBlockList& blocks = mOwner->blocks();
1166 
1167  blocks.start();
1168  oofRep::currentReport()->changeTextStyle(blocks()->textStyle());
1169 // int charHeight = mBlocks()->textStyle()->calcCharHeight();
1170 // int ascent = mBlocks()->textStyle()->calcAscent();
1171  int charHeight = blocks()->textStyle()->fixedHeight();
1172 
1173  HDC hdc = oofCurrentDraw::getCurrentDC();
1174 
1175  oofCurrentDraw::moveToEx(hdc, oofRep::currentReport()->settings()->leftMargin() +
1176  oofRep::currentReport()->settings()->bandIndenting(),
1177  oofRep::currentReport()->currentVerticalPos(), NULL);
1178 
1179  while(blocks.more()) {
1180  oofRepBlock* theBlock = blocks();
1181  switch(theBlock->align()) {
1182  // BOLD ASSUMPTION - only one right aligned item per line.
1183  case oofRepBlock::alignRight : {
1184  POINT pt;
1185 
1186  // Get the current position first
1187  oofCurrentDraw::moveToEx(hdc, 0, 0, &pt);
1188  // Now reposition properly for the right alignment
1189  oofCurrentDraw::moveToEx(hdc, oofRep::currentReport()->bodyWidth() +
1190  oofRep::currentReport()->settings()->leftMargin() -
1191  oofRep::currentReport()->settings()->bandIndenting() -
1192  theBlock->width(), pt.y, NULL
1193  );
1194  }
1195  break;
1196 
1197  case oofRepBlock::alignCentre : {
1198  POINT pt;
1199 
1200  // Get the current position first
1201  oofCurrentDraw::moveToEx(hdc, 0, 0, &pt);
1202  // Now reposition for centre alignment
1203  const long newX = oofRep::currentReport()->settings()->leftMargin() + (oofRep::currentReport()->bodyWidth()-theBlock->width())/2;
1204  oofCurrentDraw::moveToEx(hdc, newX, pt.y, NULL);
1205  }
1206  break;
1207 
1208  default :
1209  ; // NOT YET IMPLEMENTED - cope with other alignments?
1210  } // switch alignments
1211 
1212  SetCurrentBlockCoords(oofCurrentDraw::x(), oofCurrentDraw::y(), theBlock); // save for callbacks
1213  theBlock->draw();
1214  if (theBlock->fixedWidth()) {
1215  POINT pt;
1216  oofCurrentDraw::moveToEx(hdc, 0, 0, &pt);
1217  const int fixedRemainder = theBlock->fixedWidth() - theBlock->width();
1218  oofCurrentDraw::moveToEx(hdc, pt.x+fixedRemainder, pt.y, NULL);// move horizontally
1219  }
1220  else
1221  oofCurrentDraw::incX(theBlock->width()); // slide along so next block adjacent
1222 
1223  if (theBlock->moveDownAfter()) {
1224  POINT pt;
1225 
1226  // Get the current position first
1227  oofCurrentDraw::moveToEx(hdc, 0, 0, &pt);
1228  // Now reposition properly for the right alignment
1229  oofCurrentDraw::moveToEx(hdc, oofRep::currentReport()->settings()->leftMargin() +
1230  oofRep::currentReport()->settings()->bandIndenting(),
1231  pt.y + charHeight + blocks()->textStyle()->leading(), NULL);
1232 
1233  // Terminate this line
1234  blocks.next();
1235  if(blocks.more()) {
1236  oofRep::currentReport()->changeTextStyle(blocks()->textStyle());
1237  }
1238  } else {
1240  // AD 99/02/18 HACK TO COPE WITH BAD NT RENDERING
1241  POINT pt;
1242  const int kArbitraryExtraMargin = theBlock->width()/20+2;
1243  // Get the current position first
1244  oofCurrentDraw::moveToEx(hdc, 0, 0, &pt);
1245  oofCurrentDraw::moveToEx(hdc, pt.x+kArbitraryExtraMargin, pt.y, NULL);
1246  }
1247  blocks.next();
1248  }
1249  }
1250 
1251  oofRep::currentReport()->currentVerticalPos() += mOwner->fixedHeight();
1252 }
1253 
1254 
1255 
1256 // -------------------------------------------------------
1257 // o o f W i n T e x t S t y l e D E
1258 // -------------------------------------------------------
1259 
1260 void
1262 {
1263  assert(mStyle);
1264  safeChangeStyle(mStyle);
1265 }
1266 
1267 
1268 void
1270 {
1271  // horrible hack to get access to an environment that will track the font
1272  // generated by using this text style and not delete it until later
1273  // the following is not quite as dangerous as it seems - we wouldn't be using Windows
1274  // style DE's unless some kind of Windows environment, but maybe vulnerable if
1275  // we ever move responsibilities up into oofRepWinEnv
1276 
1277  // copied from oofRepWinGUIPreviewMFC::drawWithTextStyle
1278 
1279  HDC dc = oofCurrentDraw::getCurrentDC(); // maybe there's another context in use apart from us
1280  if (dc != NULL) {
1281 
1282  LOGFONT lf = inStyle->getLogFont();
1283 // HDC ic = oofCurrentDraw::getInfoDC();
1284 // const int pixelsY = ::GetDeviceCaps(ic, LOGPIXELSY);
1285  lf.lfHeight = -inStyle->fontSize(); // -MulDiv(inStyle->fontSize(), pixelsY, 72);
1286  HFONT hFont = oofTextDrawer::createFontIndirect(&lf);
1287 
1288  if (hFont != NULL) {
1289  oofTextDrawer::selectFont(dc, hFont);
1290  }
1291  // Set the foreground colour for text drawing (returns CLR_INVALID if fails)
1292  ::SetTextColor(dc, inStyle->color());
1293  } // have a DC
1294 }
1295 
1296 
1297 
1298 void
1300 // factory that records element with current page
1301 {
1302  appendElement(new oofWinTextStyleDE(copiedStyle));
1303 }
1304 
1305 
1306 
1307 // -------------------------------------------------------
1308 // o o f W i n T e x t D E
1309 // -------------------------------------------------------
1310 
1311 void
1313 {
1314  const unsigned long strLen = mString.length();
1315  if (strLen>0) {
1316  HDC hdc = oofCurrentDraw::getCurrentDC();
1317  ::SetBkMode(hdc, TRANSPARENT);
1318  ::TextOut(hdc, mX, mY, mString, strLen);
1319  }
1320 }
1321 
1322 
1323 void
1324 oofWinTextDE::recordElement(int x, int y, const oofString& inStr)
1325 // factory that records element with current page
1326 {
1327  appendElement(new oofWinTextDE(x, y, inStr));
1328 }
1329 
1330 
1331 void
1332 oofWinTextDE::recordElement(int x, int y, LPCTSTR lpString, int cbString)
1333 // factory that records element with current page
1334 {
1335  appendElement(new oofWinTextDE(x, y, lpString, cbString));
1336 }
1337 
1338 
1339 // -------------------------------------------------------
1340 // o o f G r a p h D E
1341 // -------------------------------------------------------
1342 void
1344 {
1345  if (mIsMono)
1346  mGraph->setStyleToMono();
1347  const oofRect theFrame(mX, mY, mRight, mBottom);
1348  mGraph->setPaneRect(theFrame);
1349  mGraph->draw();
1350  if (mIsMono)
1351  mGraph->setStyleToColor();
1352 }
1353 
1354 
1355 void
1356 oofGraphDE::recordElement(int inX, int inY, int inRight, int inBottom, oofGraph* inGraph, bool isMono)
1357 // factory that records element with current page
1358 {
1359  appendElement(new oofGraphDE(inX, inY, inRight, inBottom, inGraph, isMono));
1360 }
1361 
1362 
1363 void
1364 oofGraphDE::recordElement(const oofRect& R, oofGraph* inGraph, bool isMono)
1365 // factory that records element with current page
1366 {
1367  appendElement(new oofGraphDE(R, inGraph, isMono));
1368 }
1369 
1370 
1371 // -------------------------------------------------------
1372 // o o f W i n L i n e D E
1373 // -------------------------------------------------------
1374 void
1376 {
1377  POINT pt;
1378  HDC hdc = oofCurrentDraw::getCurrentDC();
1379  ::MoveToEx(hdc, mX, mY, &pt);
1380  ::LineTo(hdc, mRight, mBottom );
1381 }
1382 
1383 
1384 void
1385 oofWinLineDE::recordElement(int inX, int inY, int inRight, int inBottom)
1386 // factory that records element with current page
1387 {
1388  appendElement(new oofWinLineDE(inX, inY, inRight, inBottom));
1389 }
1390 
1391 
1392 void
1394 // factory that records element with current page
1395 {
1396  appendElement(new oofWinLineDE(R));
1397 }
1398 
1399 
1400 // -------------------------------------------------------
1401 // o o f W i n R e c t D E
1402 // -------------------------------------------------------
1403 void
1405 {
1406  HDC hdc = oofCurrentDraw::getCurrentDC();
1407  const oofRect theBox(mX, mY, mRight, mBottom);
1408  ::FrameRect(hdc, theBox, (HBRUSH)GetStockObject(BLACK_BRUSH));
1409 }
1410 
1411 
1412 void
1413 oofWinRectDE::recordElement(int inX, int inY, int inRight, int inBottom)
1414 // factory that records element with current page
1415 {
1416  appendElement(new oofWinRectDE(inX, inY, inRight, inBottom));
1417 }
1418 
1419 
1420 void
1422 // factory that records element with current page
1423 {
1424  appendElement(new oofWinRectDE(R));
1425 }
1426 
1427 
1428 // -------------------------------------------------------
1429 // o o f W i n S h a d e D E
1430 // -------------------------------------------------------
1431 oofWinShadeDE::oofWinShadeDE(int inX, int inY, int inRight, int inBottom, int stockBrush) :
1432  oofSizedDE(inX, inY, inRight, inBottom),
1433  mUseStockBrush(true),
1434  mStockBrush(stockBrush)
1435 {
1436 // based on constants in wingdi.h
1437  assert(stockBrush >= WHITE_BRUSH && stockBrush <=NULL_BRUSH);
1438 }
1439 
1440 oofWinShadeDE::oofWinShadeDE(const oofRect& R, int stockBrush) :
1441  oofSizedDE(R),
1442  mUseStockBrush(true),
1443  mStockBrush(stockBrush)
1444 {
1445  assert(stockBrush >= WHITE_BRUSH && stockBrush <=NULL_BRUSH);
1446 }
1447 
1448 
1449 void
1451 {
1452  HBRUSH colourBrush;
1453  const oofRect theBox(mX, mY, mRight, mBottom);
1454  if (mUseStockBrush)
1455  colourBrush = CreateSolidBrush(mStockBrush);
1456  else
1457  colourBrush = CreateSolidBrush(mFillColor);
1458  HDC hdc = oofCurrentDraw::getCurrentDC();
1459  ::FillRect(hdc, theBox, colourBrush);
1460  ::DeleteBrush( colourBrush );
1461 }
1462 
1463 
1464 void
1465 oofWinShadeDE::recordElement(int inX, int inY, int inRight, int inBottom, COLORREF fillColor)
1466 // factory that records element with current page
1467 {
1468  appendElement(new oofWinShadeDE(inX, inY, inRight, inBottom, fillColor));
1469 }
1470 
1471 
1472 void
1473 oofWinShadeDE::recordElement(const oofRect& R, COLORREF fillColor)
1474 // factory that records element with current page
1475 {
1476  appendElement(new oofWinShadeDE(R, fillColor));
1477 }
1478 
1479 
1480 // -------------------------------------------------------
1481 // o o f W i n P i c t D E
1482 // -------------------------------------------------------
1484  oofSizedDE(rhs)
1485 {
1486  assert(rhs.mPict);
1487  mPict = rhs.mPict;
1488 }
1489 
1490 
1492 {
1493  mPict = 0; // for lint, zero pointer to parent pict
1494 }
1495 
1496 
1502 void
1504 {
1505  HDC drawDC = oofCurrentDraw::getCurrentDC();
1507 
1508  bool isPrinting = false;
1509  if (currEnv)
1510  isPrinting = currEnv->isPrintingEnvironment();
1511  mPict->draw(mX, mY, mRight, mBottom, isPrinting, drawDC);
1512 }
1513 
1514 
1515 void
1516 oofWinPictDE::recordElement(int inX, int inY, int inRight, int inBottom, oofPict* thePict)
1517 // factory that records element with current page
1518 {
1519  appendElement(new oofWinPictDE(inX, inY, inRight, inBottom, thePict));
1520 }
1521 
1522 
1523 void
1525 // factory that records element with current page
1526 {
1527  appendElement(new oofWinPictDE(R, thePict));
1528 }
static void recordElement(int x, int y, int right, int bottom)
Definition: oofrpWin.cpp:1385
void DrawContinuingOverPage(unsigned long, unsigned long, oofSizedTextArray &sizedBody, bool hasCustomDrawers)
Definition: oofrpWin.cpp:576
virtual oofRepRender * clone(const oofRepDrawable *newOwner) const
Definition: oofrpWin.cpp:1065
void colSizer(oofColSizer *adoptedSizer)
Definition: oofsize.cpp:71
Cross-platform way to specify rectangle with Mac-style setter.
Definition: oofRect.h:39
const char * chars() const
Primary test: oofStringTest::stringInitOneCharFromConstant ()
Definition: oofstr.h:383
int mBottom
Definition: oofrep.h:1726
virtual bool isPrintingEnvironment() const
Definition: oofrep2.cpp:1232
void start()
Definition: oof1.h:1505
short leading() const
Definition: oofrep.h:2563
COLORREF mFillColor
Definition: oofrpWin.h:297
virtual void draw() const
Definition: oofrpWin.cpp:1450
virtual void makeRender(const oofRepMacEnv &env)
Definition: oofrepMac.cpp:169
Abstract base for anything drawn on report.
Definition: oofrep.h:860
virtual oofRepRenderT renderType() const
Definition: oofrpWin.cpp:50
virtual void draw()
Loop our blocks, aligning them and breaking into rows.
Definition: oofrpWin.cpp:1163
virtual void makeRender(const oofRepMacEnv &)
Definition: oofrepMac.cpp:137
Array of oofStrings paired with oofTextSizer.
Definition: oofdraw.h:127
unsigned short maxRows() const
Definition: oofdraw.h:377
virtual ~oofWinPictDE()
Definition: oofrpWin.cpp:1491
virtual oofRepRender * clone(const oofRepDrawable *newOwner) const
Definition: oofrpWin.cpp:861
unsigned long fixedHeight()
Definition: oofrep1.cpp:1757
oofRepEnvironment * environment() const
Definition: oofrep.h:1900
virtual void draw() const
Definition: oofrpWin.cpp:1375
void next()
Definition: oofrep.h:2385
virtual void calculateWrapping(const dbField *, unsigned long sizedWidth, unsigned long &wrappedHeight)=0
static void appendElement(oofDE *adoptedDE)
Definition: oofrep1.cpp:2187
Base for specifying Win32 GUI drawing environment.
Definition: oofrpWin.h:46
virtual void startEnvironment()
Definition: oofrpWin.cpp:119
Draw oofRepViewBand contents as grid with page breaks.
Definition: oofrpWin.h:128
virtual unsigned short heightOfTextStyle(oofRepTextStyle *theStyle)
Definition: oofrpWin.cpp:56
virtual unsigned long width() const
Definition: oofrpWin.cpp:1024
virtual bool shouldDrawViewColumnHeaders() const
Definition: oofrep1.cpp:726
virtual void draw()
Definition: oofrpWin.cpp:947
static oofRuntimeEnvT runtimeEnv()
Definition: oof1.cpp:3334
const dbField & field(unsigned int) const
Definition: oofview.h:206
blockAlignT align() const
Definition: oofrep.h:2205
Most commonly used top band in a report.
Definition: oofrep.h:1283
virtual void makeRender(const oofRepMacEnv &env)
Definition: oofrepMac.cpp:177
unsigned long bodyWidth()
Definition: oofrep.h:1968
Call oofPict::draw positioned centred within oofRepPictBand.
Definition: oofrpWin.h:115
virtual oofRepRender * clone(const oofRepDrawable *newOwner) const
Definition: oofrpWin.cpp:207
Base rendering class.
Definition: oofrep.h:816
void drawPageBreak()
Definition: oofrep1.cpp:658
int mRight
Definition: oofrep.h:1726
static void recordElement(const oofRepTextStyle *copiedStyle)
Definition: oofrpWin.cpp:1299
Graph class subclassed to draw different graph types.
Definition: oofGrphs.h:71
virtual void makeRenderDispatch(oofRepDrawable *drawable) const
Definition: oofrpWin.cpp:27
static void recordElement(int x, int y, int right, int bottom, oofGraph *inGraph, bool isMono)
Definition: oofrpWin.cpp:1356
const oofRepSettings * settings() const
Definition: oofrep1.cpp:469
bool mUseStockBrush
Definition: oofrpWin.h:298
const unsigned long * GetLineLengths(unsigned short index) const
Definition: oofdraw.cpp:1103
static void recordElement(int x, int y, int right, int bottom, oofPict *)
Definition: oofrpWin.cpp:1516
bool more() const
Definition: oofrep.h:2378
virtual void makeRender(const oofRepMacEnv &env)
Definition: oofrepMac.cpp:145
void changeTextStyle(oofRepTextStyle *)
Provide forwarding so report objects that are drawing can affect environment text style...
Definition: oofrep.h:2059
unsigned short fontSize() const
Definition: oofrep.h:2548
Iterate blocks in oofRepLayoutBand changing pen position for each.
Definition: oofrpWin.h:92
Abstracts a drawing environment.
Definition: oofrep.h:406
Provide an iterable set of fields.
Definition: oofview.h:26
unsigned long & currentVerticalPos()
Definition: oofrep.h:1941
void start()
Definition: oofrep.h:2371
unsigned short bandIndenting() const
Definition: oofrep3.cpp:326
virtual void draw() const
Definition: oofrpWin.cpp:1312
Draw a line in a report.
Definition: oofrpWin.h:230
virtual void draw() const
Definition: oofrpWin.cpp:1343
virtual void CalculateWrapping(unsigned short index, unsigned short inColWidth, bool inTruncWords=true)
Definition: oofdraw.cpp:1119
unsigned long recordNumber() const
Definition: oofview.h:223
Top level class for a report.
Definition: oofrep.h:571
virtual void draw() const
Draw, calling oofPict stuff that actually doesn't care that much if printing or not.
Definition: oofrpWin.cpp:1503
virtual void makeRender(const oofRepMacEnv &env)
Definition: oofrepMac.cpp:161
unsigned long length() const
Primary test: oofStringTest::emptyStringByNullInitIsLenZero()
Definition: oofstr.h:447
virtual oofRepRender * clone(const oofRepDrawable *newOwner) const
Definition: oofrpWin.cpp:1004
static SIZE getTextExtent(const oofRepTextStyle *textStyle, const OOF_String &text)
Definition: oofrpWin.cpp:86
Call oofPict::draw positioned centred within oofRepPictBlock.
Definition: oofrpWin.h:165
Draw text in the current style.
Definition: oofrpWin.h:152
virtual oofRepRender * clone(const oofRepDrawable *newOwner) const
Definition: oofrpWin.cpp:978
Abstract report-writer drawing element with position & rectangular size.
Definition: oofrep.h:1708
unsigned long oofRepRenderT
Definition: oofrep.h:113
AdornerContextCode drawWhen()
Definition: oofadorn.h:43
bool moveDownAfter() const
Indicate if a layout band should start a new row of blocks.
Definition: oofrep.h:2215
Abstract base for user column drawer.
Definition: oofrep.h:1239
virtual void makeRender(const oofRepMacEnv &)
Definition: oofadorn.cpp:167
static void recordElement(int x, int y, const oofString &inStr)
Definition: oofrpWin.cpp:1324
const oofString & fontName() const
Definition: oofrep.h:2540
Abstract base for rendering an oofRepViewBand.
Definition: oofreprn.h:129
virtual void finishConstruction()
Definition: oofrep2.cpp:426
virtual void drawcell(int x, int y, OOF_mixColumnarBand *drawable, unsigned long height, unsigned long width, AdornerCellCode overrunCode=startStop)
Definition: oofadorn.cpp:157
static void safeChangeStyle(oofRepTextStyle *)
Definition: oofrpWin.cpp:1269
Specify a fixed height band containing an oofGraph with additional height & width.
Definition: oofrep.h:1080
unsigned int count() const
Definition: oof1.h:1498
virtual oofRepRender * clone(const oofRepDrawable *newOwner) const
Definition: oofrpWin.cpp:940
virtual void makeRender(const oofRepMacEnv &env)
Definition: oofrepMac.cpp:122
virtual unsigned long width()
Definition: oofrep1.cpp:1282
Portable highly capable string class.
Definition: oofstr.h:101
unsigned long fixedWidth()
Definition: oofrep.h:2229
oofPict * mPict
Definition: oofrpWin.h:328
virtual void finishConstruction()
Definition: oofrpWin.cpp:214
virtual oofRepRender * clone(const oofRepDrawable *newOwner) const
Definition: oofrpWin.cpp:878
Draw colour or mono graph as specified by oofRepGraphBand.
Definition: oofrpWin.h:79
virtual void makeRender(const oofRepMacEnv &env)
Definition: oofrepMac.cpp:110
virtual void makeRender(const oofRepMacEnv &)
Definition: oofrep1.cpp:1334
virtual oofRepRender * clone(const oofRepDrawable *newOwner) const
Definition: oofrpWin.cpp:1034
oofWinShadeDE(int x, int y, int right, int bottom, COLORREF fillColor)
Definition: oofrpWin.h:277
Settings object for overriding behaviours of an instance of oofRep.
Definition: oofrep.h:173
Specify a fixed-height band that contains a series of oofRepBlock's.
Definition: oofrep.h:1182
const oofColor & color() const
Definition: oofrep.h:2570
Abstract base for a fixed-size block drawn by an oofRepLayoutBand.
Definition: oofrep.h:1408
virtual void draw()
Definition: oofrpWin.cpp:390
Draw an oofPict in a report.
Definition: oofrpWin.h:308
Draw text in Windows using current font settings.
Definition: oofrpWin.h:178
Cross-platform specification of text style.
Definition: oofrep.h:732
unsigned short colSepWidth() const
Definition: oofrep3.cpp:421
static void recordElement(int x, int y, int right, int bottom, COLORREF fillColor)
Definition: oofrpWin.cpp:1465
int mStockBrush
Definition: oofrpWin.h:299
virtual void makeRender(const oofRepMacEnv &env)
Definition: oofrepMac.cpp:153
Draw a rectangle in a report.
Definition: oofrpWin.h:252
Base object to derive adorners from.
Definition: oofadorn.h:32
void draw(int x, int y, int right, int bottom, bool onPrinter=false)
Definition: oofdraw.cpp:1370
virtual oofString copyString() const
Definition: oof3.cpp:472
unsigned long bodyEnd()
Definition: oofrep.h:1955
virtual void splitBandOverPage()
Definition: oofrep.h:426
virtual OOF_fieldTypes fieldType() const =0
unsigned short leftMargin() const
Definition: oofrep3.cpp:344
virtual void makeRender(const oofRepMacEnv &env)
Definition: oofrepMac.cpp:129
static oofRep * currentReport()
Definition: oofrep.h:2003
Specify a block to draw mono-styled text in an oofRepLayoutBand.
Definition: oofrep.h:1445
virtual void draw()
central default call for drawing, but still able to be overriden in extreme cases.
Definition: oofrep1.cpp:1296
void set(int left, int top, int right, int bottom)
Definition: oofRect.cpp:80
unsigned short GetNumRows(unsigned short index) const
Definition: oofdraw.cpp:1111
virtual void drawColumnHeaders()
Definition: oofrpWin.cpp:257
virtual unsigned long width() const
Definition: oofrpWin.cpp:1053
Specify a fixed height band to draw an oofPict.
Definition: oofrep.h:1649
Draw an oofGraph within a report.
Definition: oofrpWin.h:200
const unsigned long * GetLineStarts(unsigned short index) const
Definition: oofdraw.cpp:1095
List of blocks in an oofRepLayoutBand.
Definition: oofrep.h:336
Advance report vertical position.
Definition: oofrpWin.h:66
Draw a line as filled rectangle specified by oofRepLineBand.
Definition: oofrpWin.h:104
Specify a fixed height band to draw a horizontal line black or grey in given thickness.
Definition: oofrep.h:1143
virtual void startTableBody(bool headersHaveChanged)
Definition: oofrpWin.cpp:223
bool printGraphsInMono() const
Definition: oofrep3.cpp:535
oofString & text(unsigned short index) const
Definition: oofdraw.cpp:1088
Specify a block to draw an oofPict in an oofRepLayoutBand.
Definition: oofrep.h:1516
unsigned long width()
Definition: oofdraw.cpp:1251
virtual void draw()
Definition: oofrpWin.cpp:985
static void recordElement(int x, int y, int right, int bottom)
Definition: oofrpWin.cpp:1413
oofWinPictDE(int x, int y, int right, int bottom, oofPict *inPict)
Definition: oofrpWin.h:310
virtual void resumeBandOverPage()
Definition: oofrep.h:427
Specify a band which provides a vertical gap on the page.
Definition: oofrep.h:1050
virtual unsigned long calcNextDrawHeight(unsigned long heightAvailable, unsigned long &heightUsed)=0
virtual void draw() const
Definition: oofrpWin.cpp:1404
Change current font settings to affect all oofWinTextDE from now until next change.
Definition: oofrpWin.h:336
virtual void draw() const
Definition: oofrpWin.cpp:1261
unsigned long fixedHeight()
Definition: oofrep1.cpp:2006
Cross-platform picture representation can load from file or resource and draw.
Definition: oofdraw.h:201
static oofColSizer::colAlignT naturalAlignmentForField(OOF_fieldTypes)
Definition: oofsize.cpp:249
oofString getHeading(unsigned int, bool *tellIfOverride=0) const
Definition: oofview.cpp:278