Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

293 lines
7.4 KiB

  1. /*
  2. * @doc INTERNAL
  3. *
  4. * @module dispprt.cpp -- Special logic for printer object |
  5. *
  6. * Authors:
  7. * Original RichEdit code: David R. Fulmer
  8. * Christian Fortini
  9. * Jon Matousek
  10. */
  11. #include "_common.h"
  12. #include "_dispprt.h"
  13. #include "_edit.h"
  14. #include "_font.h"
  15. #include "_measure.h"
  16. #include "_render.h"
  17. #include "_select.h"
  18. #define PARA_NUMBER_NOT_SET ((WORD) -1)
  19. ASSERTDATA
  20. /*
  21. * CDisplayPrinter::CDisplayPrinter(ped, hdc, x, y, prtcon)
  22. *
  23. * @mfunc
  24. * Contructs a object that can be used to print a text control
  25. */
  26. CDisplayPrinter::CDisplayPrinter(
  27. CTxtEdit* ped, //@parm CTxtEdit
  28. HDC hdc, //@parm HDC for drawing
  29. RECT *prc, //@parm dimensions of current area to print to.
  30. SPrintControl prtcon//@parm Special controls for this print object
  31. )
  32. : CDisplayML(ped), _prtcon(prtcon)
  33. {
  34. TRACEBEGIN(TRCSUBSYSPRT, TRCSCOPEINTERN, "CDisplayPrinter::CDisplayPrinter");
  35. Assert (hdc);
  36. _fNoUpdateView = TRUE;
  37. SetTflow(ped->_pdp->GetTflow());
  38. GetDupDvpFromRect(*prc, GetTflow(), _dulTarget, _dvlTarget);
  39. _wNumber = PARA_NUMBER_NOT_SET;
  40. }
  41. /*
  42. * CDisplayPrinter::SetPrintDimensions(prc)
  43. *
  44. * @mfunc
  45. * Set area to print.
  46. */
  47. void CDisplayPrinter::SetPrintDimensions(
  48. RECT *prc) //@parm dimensions of current area to print to.
  49. {
  50. GetDupDvpFromRect(*prc, GetTflow(), _dulTarget, _dvlTarget);
  51. }
  52. /*
  53. * CDisplayPrinter::FormatRange(cpFirst, cpMost)
  54. *
  55. * @mfunc
  56. * Format a range of text into this display and used only for printing.
  57. *
  58. * @rdesc
  59. * actual end of range position (updated)
  60. */
  61. LONG CDisplayPrinter::FormatRange(
  62. LONG cpFirst, //@parm Start of text range
  63. LONG cpMost, //@parm End of text range
  64. BOOL fWidowOrphanControl) //@parm If TRUE, suppress widow/orphan
  65. {
  66. TRACEBEGIN(TRCSUBSYSPRT, TRCSCOPEINTERN, "CDisplayPrinter::FormatRange");
  67. LONG cch;
  68. WCHAR ch;
  69. BOOL fFirstInPara = TRUE;
  70. CLine liTarget;
  71. CLine * pliNew = NULL;
  72. LONG dvp;
  73. LONG dvt;
  74. const CDevDesc *pddTarget = GetDdTarget() ? GetDdTarget() : this;
  75. // Set client height for zooming
  76. _dvpClient = LYtoDY(_dvlTarget);
  77. // Set maximum in terms of target DC.
  78. LONG dvtMax = pddTarget->LYtoDY(_dvlTarget);
  79. if(cpMost < 0)
  80. cpMost = _ped->GetTextLength();
  81. CMeasurer me(this);
  82. cpFirst = me.SetCp(cpFirst); // Validate cpFirst while setting me
  83. ch = me.GetChar();
  84. // TODO: COMPATIBILITY ISSUE: Richedit 1.0 adjusted to before a
  85. // CRLF/CRCRLF boundary. if_ped->fUseCRLF(), adjust accordingly
  86. _cpMin = cpFirst;
  87. _cpFirstVisible = cpFirst;
  88. dvt = 0;
  89. dvp = 0;
  90. if(me.GetCp())
  91. fFirstInPara = me._rpTX.IsAfterEOP();
  92. // Clear line CArray
  93. DeleteSubLayouts(0, -1);
  94. Clear(AF_DELETEMEM);
  95. // Assume that we will break on words
  96. UINT uiBreakAtWord = MEASURE_BREAKATWORD;
  97. if(_prtcon._fPrintFromDraw)
  98. {
  99. // This is from Draw so we want to take inset into account
  100. LONG dut = LYtoDY(_dulTarget);
  101. GetViewDim(dut, dvtMax);
  102. _dupView = dut;
  103. // Restore client height
  104. _dvpClient = this->LYtoDY(_dvlTarget);
  105. }
  106. else // Message-based printing always does word wrap
  107. SetWordWrap(TRUE);
  108. // Set paragraph numbering. This is a fairly difficult problem
  109. // because printing can start anywhere and end anywhere. However,
  110. // most printing will involve a contiguous range of pages. Therefore,
  111. // we cache the paragraph number and the cp for that number and
  112. // only resort to looking in the line array if the cached information
  113. // has become invalid.
  114. if ((PARA_NUMBER_NOT_SET == _wNumber) || (cpFirst != _cpForNumber))
  115. {
  116. CLinePtr rp(_ped->_pdp);
  117. rp.SetCp(cpFirst, FALSE);
  118. _wNumber = rp.GetNumber();
  119. _cpForNumber = cpFirst;
  120. }
  121. me.SetNumber(_wNumber);
  122. while(me.GetCp() < cpMost)
  123. {
  124. // Add one new line
  125. pliNew = Add(1, NULL);
  126. if(!pliNew)
  127. {
  128. _ped->GetCallMgr()->SetOutOfMemory();
  129. goto err;
  130. }
  131. // Store the current number of the paragraph. We do it
  132. // here because we have to measure and that potentially
  133. // updates the number of the paragraph in the measurer
  134. // for a line that might not be on the page.
  135. _wNumber = me.GetNumber();
  136. // Stuff some text into this new line
  137. if(!Measure(me, pliNew, Count() - 1, uiBreakAtWord | (fFirstInPara ? MEASURE_FIRSTINPARA : 0), &liTarget))
  138. {
  139. Assert(FALSE);
  140. goto err;
  141. }
  142. //FUTURE (keithcu) We break tables across pages on row boundaries which
  143. //isn't very granular--especially in the HTML world.
  144. // Note, we always put at least one line on a page. Otherwise, if the
  145. // first line is too big, we would cause our client to infinite loop
  146. // because we would never advance the print cp.
  147. if(_cel > 1 && (dvt + liTarget.GetHeight() > dvtMax))
  148. {
  149. cch = -pliNew->_cch; // Bump last line to next page
  150. _cel--; // One less line
  151. #if 0
  152. CLine *pli = pliNew - 1; // Point at previous line
  153. // If this line and the previous one are in the same para and
  154. // either this one ends in an EOP or the previous one starts
  155. // a para, bump both to following page (widow/orphan)
  156. if(fWidowOrphanControl)
  157. {
  158. if(_cel > 1 && !fFirstInPara &&
  159. (pli->_bFlags & fliFirstInPara || (pliNew->_bFlags & fliHasEOP)))
  160. {
  161. cch -= pli->_cch;
  162. _cel--; // One less line
  163. pli--; // Point to previous line
  164. }
  165. if(_cel > 1 && pli->_nHeading)
  166. { // Don't end page with a heading
  167. cch -= pli->_cch;
  168. _cel--; // One less line
  169. }
  170. }
  171. #endif
  172. me.Move(cch); // Move back over lines discarded
  173. delete pliNew->GetPlo(); //Delete the CLayout which didn't get added to the CLineArray
  174. break;
  175. }
  176. fFirstInPara = (pliNew->_fHasEOP);
  177. dvt += liTarget.GetHeight();
  178. dvp += pliNew->GetHeight();
  179. if (me.GetPrevChar() == FF)
  180. break;
  181. }
  182. // If there was no text, then add a single blank line
  183. if(!pliNew)
  184. {
  185. pliNew = Add(1, NULL);
  186. if(!pliNew)
  187. {
  188. _ped->GetCallMgr()->SetOutOfMemory();
  189. goto err;
  190. }
  191. me.NewLine(fFirstInPara);
  192. *pliNew = me._li;
  193. }
  194. // Update display height
  195. _dvp = dvp;
  196. // Update display width
  197. _dupLineMax = CalcDisplayDup();
  198. cpMost = me.GetCp();
  199. _cpCalcMax = cpMost;
  200. _vpCalcMax = _dvp;
  201. // Update paragraph caching information.
  202. _cpForNumber = cpMost;
  203. return cpMost;
  204. err:
  205. DeleteSubLayouts(0, -1);
  206. Clear(AF_DELETEMEM);
  207. _dupLineMax = 0;
  208. _dvp = 0;
  209. return -1;
  210. }
  211. /*
  212. * CDisplayPrinter::GetNaturalSize(hdcDraw, hicTarget, dwMode, pwidth, pheight)
  213. *
  214. * @mfunc
  215. * Recalculate display to input width & height for TXTNS_FITTOCONTENT.
  216. *
  217. * @rdesc
  218. * S_OK - Call completed successfully <nl>
  219. *
  220. * @devnote
  221. * This assumes that FormatRange was called just prior to this.
  222. */
  223. HRESULT CDisplayPrinter::GetNaturalSize(
  224. HDC hdcDraw, //@parm DC for drawing
  225. HDC hicTarget, //@parm DC for information
  226. DWORD dwMode, //@parm Type of natural size required
  227. LONG *pwidth, //@parm Width in device units to use for fitting
  228. LONG *pheight) //@parm Height in device units to use for fitting
  229. {
  230. TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplayPrinter::GetNaturalSize");
  231. *pwidth = _dupLineMax;
  232. *pheight = _dvp;
  233. return S_OK;
  234. }
  235. /*
  236. * CDisplayPrinter::IsPrinter()
  237. *
  238. * @mfunc
  239. * Returns whether this is a printer
  240. *
  241. * @rdesc
  242. * TRUE - is a display to a printer
  243. * FALSE - is not a display to a printer
  244. */
  245. BOOL CDisplayPrinter::IsPrinter() const
  246. {
  247. AssertSz(_hdc, "CDisplayPrinter::IsPrinter no hdc set");
  248. return GetDeviceCaps(_hdc, TECHNOLOGY) == DT_RASPRINTER;
  249. }