#include "RichText.h" namespace Upp { struct RichNumberField : RichPara::FieldType { virtual Array Evaluate(const String& param, VectorMap& vars, const RichPara::CharFormat& fmt) { String h = AsString(vars.Get(param, Null)); Array ps; RichPara::Part& p = ps.Add(); p.format = fmt; if(!IsNull(vars.Get("__DISPLAY_VALUE_FIELDS", Null))) p.format.paper = WhiteGray(); p.text = h.ToWString(); return ps; } }; INITBLOCK { RichPara::Register("VALUE"); } RichText& GetHeaderFooterText(RichText *text, int page, int pagecount) { VectorMap vars; vars.Add("PAGENUMBER", page + 1); vars.Add("PAGECOUNT", pagecount); text->EvaluateFields(vars); return *text; } RichContext::RichContext(const RichStyles& styles, const RichText *text) : text(text), styles(&styles) { header_cy = footer_cy = 0; current_header_cy = current_footer_cy = 0; } void RichContext::HeaderFooter(RichText *header_, RichText *footer_) { header = header_; footer = footer_; int cx = page.GetWidth(); header_cy = header ? GetHeaderFooterText(header, 999990, 999990).GetHeight(cx) : 0; footer_cy = footer ? GetHeaderFooterText(footer, 999990, 999990).GetHeight(cx) : 0; int maxcy = page.GetHeight(); if(maxcy < INT_MAX / 2) maxcy = maxcy * 4 / 5; if(header_cy + footer_cy > maxcy) header_cy = footer_cy = 0; } void RichContext::AdjustPage() { page.top += header_cy - current_header_cy; page.bottom -= footer_cy - current_footer_cy; current_header_cy = header_cy; current_footer_cy = footer_cy; } void RichContext::Set(PageY p0, const Rect& first_page, const Rect& next_page, PageY p) { // table layout helper, real hdr/ftr is irrelevant, need correct page.top / page.bottom current_header_cy = current_footer_cy = 0; if(p.page != p0.page) { // we are already on next page page = next_page; header_cy = footer_cy = 0; } else { page = first_page; header_cy = next_page.top - page.top; footer_cy = page.bottom - next_page.bottom; } py = p; } void RichContext::Page() { py.page++; AdjustPage(); py.y = page.top; } RichContext RichText::Context(const Rect& page, PageY py, RichText *header, RichText *footer) const { RichContext rc(style, this); rc.page = page; rc.py = py; rc.HeaderFooter(header, footer); rc.AdjustPage(); if(rc.py.y < rc.page.top) rc.py.y = rc.page.top; return rc; } void RichText::PaintHeaderFooter(PageDraw& pw, const Rect& page, PageY py, const PaintInfo& pi_, int from_page, int to_page) const { PaintInfo pi = pi_; pi.sell = pi.selh = 0; RichContext rc = Context(page, py); int last_page = -1; int pagecount = GetHeight(page).page + 1; int i = 0; while(last_page <= to_page) { while(last_page < rc.py.page) { last_page++; if(last_page >= from_page && (rc.header || rc.footer)) { if(rc.header_cy) GetHeaderFooterText(rc.header, last_page, pagecount).Paint(pw, PageY(last_page, page.top), page, pi); if(rc.footer_cy) GetHeaderFooterText(rc.footer, last_page, pagecount).Paint(pw, PageY(last_page, page.bottom - rc.footer_cy), page, pi); } } if(++i >= GetPartCount()) break; RichContext begin; Advance(i, rc, begin); } } void SetQTF(One& txt, const String& qtf) { txt.Clear(); if(qtf.GetCount()) txt.Create() = ParseQTF(qtf); } void RichTxt::SetHeaderQtf(const char *qtf) { header_qtf = qtf; SetQTF(header, header_qtf); r_type = ALL; } void RichTxt::SetFooterQtf(const char *qtf) { footer_qtf = qtf; SetQTF(footer, footer_qtf); r_type = ALL; } }