diff --git a/uppsrc/CtrlCore/EncodeRTF.cpp b/uppsrc/CtrlCore/EncodeRTF.cpp index 964c29f55..b0b631d37 100644 --- a/uppsrc/CtrlCore/EncodeRTF.cpp +++ b/uppsrc/CtrlCore/EncodeRTF.cpp @@ -189,7 +189,7 @@ void RTFEncoder::GetTxtFaces(const RichTxt& rt) phys_colors.FindAdd(tfmt.gridcolor); for(int r = 0; r < table.GetRows(); r++) for(int c = 0; c < table.GetColumns(); c++) { - const RichCell& cell = table.cell[r][c]; + const RichCell& cell = table[r][c]; phys_colors.FindAdd(cell.format.color); phys_colors.FindAdd(cell.format.bordercolor); GetTxtFaces(cell.text); @@ -498,7 +498,7 @@ void RTFEncoder::PutTable(const RichTable& table, int nesting, int dot_width) Vector cellindex; Rect dflt_margin(600, 600, 600, 600); for(int c = 0; c < table.GetColumns(); c++) { - const RichCell& cell = table.cell[r][c]; + const RichCell& cell = table[r][c]; dflt_margin.left = min(dflt_margin.left, cell.format.margin.left); dflt_margin.top = min(dflt_margin.top, cell.format.margin.top); dflt_margin.right = min(dflt_margin.right, cell.format.margin.right); @@ -515,7 +515,7 @@ void RTFEncoder::PutTable(const RichTable& table, int nesting, int dot_width) bool istop = (r == 0); bool isbottom = (r == table.GetRows() - 1); for(int c = 0; c < table.GetColumns(); c++) { - const RichCell& cell = table.cell[r][c]; + const RichCell& cell = table[r][c]; /* if(cell.format.margin.left != dflt_margin.left) rowfmt << "\\clpadl" << DotTwips(cell.format.margin.left) << "\\clpadfl3"; @@ -548,24 +548,25 @@ void RTFEncoder::PutTable(const RichTable& table, int nesting, int dot_width) rowfmt << "\\clcbpat" << phys_colors.Find(cell.format.color); int lb, tb, rb, bb; Color lc, tc, rc, bc; - lc = tc = rc = bc = table.format.gridcolor; - lb = tb = rb = bb = (!IsNull(table.format.gridcolor) ? table.format.grid : 0); - int fw = (!IsNull(table.format.framecolor) ? table.format.frame : 0); + const RichTable::Format& tf = table.GetFormat(); + lc = tc = rc = bc = tf.gridcolor; + lb = tb = rb = bb = (!IsNull(tf.gridcolor) ? tf.grid : 0); + int fw = (!IsNull(tf.framecolor) ? tf.frame : 0); if(isleft) { lb = fw; - lc = table.format.framecolor; + lc = tf.framecolor; } if(isright) { rb = fw; - rc = table.format.framecolor; + rc = tf.framecolor; } if(istop) { tb = fw; - tc = table.format.framecolor; + tc = tf.framecolor; } if(isbottom) { bb = fw; - bc = table.format.framecolor; + bc = tf.framecolor; } if(!IsNull(cell.format.bordercolor)) { if(cell.format.border.left >= max(lb, 1)) { @@ -603,7 +604,7 @@ void RTFEncoder::PutTable(const RichTable& table, int nesting, int dot_width) stream.Put(fmtstr); for(int c = 0; c < cellindex.GetCount(); c++) { int cx = cellindex[c]; - const RichCell& cell = table.cell[r][cx]; + const RichCell& cell = table[r][cx]; int cell_wd = column_pos[cx + cell.hspan + 1] - column_pos[cx]; PutTxt(cell.text, nesting + 1, cell_wd); Command(nesting ? "nestcell" : "cell"); diff --git a/uppsrc/CtrlCore/ParseRTF.cpp b/uppsrc/CtrlCore/ParseRTF.cpp index de18e1c15..2de74f939 100644 --- a/uppsrc/CtrlCore/ParseRTF.cpp +++ b/uppsrc/CtrlCore/ParseRTF.cpp @@ -324,10 +324,12 @@ void RTFParser::FlushTable(int level) } } } - table.format.frame = Nvl(tbl_border, 0); - table.format.framecolor = (table.format.frame > 0 ? clr_border : Color(Null)); - table.format.grid = Nvl(tbl_grid, 0); - table.format.gridcolor = (table.format.grid > 0 ? clr_grid : Color(Null)); + RichTable::Format tf = table.GetFormat(); + tf.frame = Nvl(tbl_border, 0); + tf.framecolor = (tf.frame > 0 ? clr_border : Color(Null)); + tf.grid = Nvl(tbl_grid, 0); + tf.gridcolor = (tf.grid > 0 ? clr_grid : Color(Null)); + table.SetFormat(tf); for(int r = 0; r < child.cells.GetCount(); r++) { Array& rw = child.cells[r]; // int pos = child.tableformat.lm; diff --git a/uppsrc/RichText/EncodeHTML.cpp b/uppsrc/RichText/EncodeHTML.cpp index 536ccd0bf..8f358bc2b 100644 --- a/uppsrc/RichText/EncodeHTML.cpp +++ b/uppsrc/RichText/EncodeHTML.cpp @@ -119,9 +119,9 @@ String AsHtml(const RichTxt& text, const RichStyles& styles, Index& css, { if(text.IsTable(i)) { const RichTable& t = text.GetTable(i); - int nx = t.format.column.GetCount(); - int ny = t.cell.GetCount(); - const RichTable::Format& tf = t.format; + const RichTable::Format& tf = t.GetFormat(); + int nx = tf.column.GetCount(); + int ny = t.GetRows(); html << ""; if(tf.before > 0) html << ""; @@ -137,14 +137,14 @@ String AsHtml(const RichTxt& text, const RichStyles& styles, Index& css, html << "
"; int sum = 0; for(int i = 0; i < nx; i++) - sum += t.format.column[i]; + sum += tf.column[i]; html << ""; for(int i = 0; i < nx; i++) - html << ""; + html << ""; html << ""; html << "\r\n"; for(int i = 0; i < ny; i++) { - const Array& r = t.cell[i]; + const Array& r = t[i]; html << ""; for(int j = 0; j < r.GetCount(); j++) { if(t(i, j)) { diff --git a/uppsrc/RichText/EncodeQtf.cpp b/uppsrc/RichText/EncodeQtf.cpp index 06b08fea9..07e9b33e1 100644 --- a/uppsrc/RichText/EncodeQtf.cpp +++ b/uppsrc/RichText/EncodeQtf.cpp @@ -376,15 +376,15 @@ void QTFEncodeTxt(String& qtf, const RichTxt& text, const RichStyles& styles, co qtf << ' '; const RichTable& t = text.GetTable(i); - int nx = t.format.column.GetCount(); - int ny = t.cell.GetCount(); + const RichTable::Format& f = t.GetFormat(); + int nx = f.column.GetCount(); + int ny = t.GetRows(); qtf << "{{"; for(int i = 0; i < nx; i++) { if(i) qtf << ':'; - qtf << t.format.column[i]; + qtf << f.column[i]; } - const RichTable::Format& f = t.format; const RichTable::Format& d = Single(); FmtNumber(qtf, '<', d.lm, f.lm); FmtNumber(qtf, '>', d.rm, f.rm); @@ -405,7 +405,7 @@ void QTFEncodeTxt(String& qtf, const RichTxt& text, const RichStyles& styles, co FmtNumber(qtf, 'h', d.header, f.header); RichCell::Format cf = Single(); for(int i = 0; i < ny; i++) { - const Array& r = t.cell[i]; + const Array& r = t[i]; for(int j = 0; j < r.GetCount(); j++) { const RichCell& c = r[j]; if(i || j) { diff --git a/uppsrc/RichText/HeaderFooter.cpp b/uppsrc/RichText/HeaderFooter.cpp index 9d3decaad..351f34285 100644 --- a/uppsrc/RichText/HeaderFooter.cpp +++ b/uppsrc/RichText/HeaderFooter.cpp @@ -20,34 +20,37 @@ INITBLOCK { RichPara::Register("VALUE"); } -RichText GetHeaderFooterText(const String& qtf, int page, int pagecount) +RichText& GetHeaderFooterText(RichText *text, int page, int pagecount) { VectorMap vars; vars.Add("PAGENUMBER", page + 1); vars.Add("PAGECOUNT", pagecount); - RichText txt = ParseQTF(qtf); - txt.EvaluateFields(vars); - return txt; + text->EvaluateFields(vars); + return *text; } -void RichContext::NewHeaderFooter(const String& header_qtf_, const String& footer_qtf_) +void RichContext::NewHeaderFooter(RichText *header_, RichText *footer_) { page.top -= header_cy; page.bottom += footer_cy; - header_qtf = header_qtf_; - footer_qtf = footer_qtf_; - header_cy = header_qtf.GetCount() ? GetHeaderFooterText(header_qtf, 999990, 999990).GetHeight(page.GetWidth()) : 0; - footer_cy = footer_qtf.GetCount() ? GetHeaderFooterText(footer_qtf, 999990, 999990).GetHeight(page.GetWidth()) : 0; + 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() * 4 / 5; + if(header_cy + footer_cy > maxcy) + header_cy = footer_cy = 0; page.top += header_cy; page.bottom -= footer_cy; } -RichContext RichText::Context(const Rect& page, PageY py, const String& header_qtf, const String& footer_qtf) const +RichContext RichText::Context(const Rect& page, PageY py, RichText *header, RichText *footer) const { RichContext rc(style, this); rc.page = page; rc.py = py; - rc.NewHeaderFooter(header_qtf, footer_qtf); + rc.NewHeaderFooter(header, footer); if(rc.py.y < rc.page.top) rc.py.y = rc.page.top; return rc; @@ -61,28 +64,39 @@ void RichText::PaintHeaderFooter(PageDraw& pw, const Rect& page, const PaintInfo RichContext rc = Context(page); int last_page = -1; int pagecount = GetHeight(page).page + 1; - for(int i = 0; i < GetPartCount() && last_page < to_page; i++) { + for(int i = 0; i < GetPartCount() && last_page <= to_page; i++) { while(last_page < rc.py.page) { last_page++; - if(rc.header_qtf.GetCount()) - GetHeaderFooterText(rc.header_qtf, last_page, pagecount).Paint(pw, PageY(last_page, page.top), page, pi); - if(rc.footer_qtf.GetCount()) - GetHeaderFooterText(rc.footer_qtf, last_page, pagecount).Paint(pw, PageY(last_page, page.bottom - rc.footer_cy), page, pi); + if(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); + } } 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; } diff --git a/uppsrc/RichText/ParseQtf.cpp b/uppsrc/RichText/ParseQtf.cpp index 476a5428f..5662dc413 100644 --- a/uppsrc/RichText/ParseQtf.cpp +++ b/uppsrc/RichText/ParseQtf.cpp @@ -390,6 +390,7 @@ void RichQtfParser::S(int& x, int a) void RichQtfParser::TableFormat(bool bw) { RichTable& tab = Table(); + RichTable::Format tabformat = tab.GetFormat(); Tab& t = table.Top(); int a, b; for(;;) { @@ -401,19 +402,21 @@ void RichQtfParser::TableFormat(bool bw) Error("Unexpected end of text in cell format"); else switch(*term++) { - case ' ': return; + case ' ': + tab.SetFormat(tabformat); + return; case ';': break; - case '<': tab.format.lm = ReadNumber(); break; - case '>': tab.format.rm = ReadNumber(); break; - case 'B': tab.format.before = ReadNumber(); break; - case 'A': tab.format.after = ReadNumber(); break; - case 'f': tab.format.frame = ReadNumber(); break; + case '<': tabformat.lm = ReadNumber(); break; + case '>': tabformat.rm = ReadNumber(); break; + case 'B': tabformat.before = ReadNumber(); break; + case 'A': tabformat.after = ReadNumber(); break; + case 'f': tabformat.frame = ReadNumber(); break; case '_': - case 'F': tab.format.framecolor = GetColor(); break; - case 'g': tab.format.grid = ReadNumber(); break; - case 'G': tab.format.gridcolor = GetColor(); break; - case 'h': tab.format.header = GetNumber(); break; - case '~': tab.format.frame = tab.format.grid = 0; break; + case 'F': tabformat.framecolor = GetColor(); break; + case 'g': tabformat.grid = ReadNumber(); break; + case 'G': tabformat.gridcolor = GetColor(); break; + case 'h': tabformat.header = GetNumber(); break; + case '~': tabformat.frame = tabformat.grid = 0; break; case '^': t.format.align = ALIGN_TOP; break; case '=': t.format.align = ALIGN_CENTER; break; case 'v': t.format.align = ALIGN_BOTTOM; break; @@ -427,12 +430,12 @@ void RichQtfParser::TableFormat(bool bw) case '!': t.format = RichCell::Format(); break; case 'o': t.format.round = true; break; case 'k': t.format.keep = true; break; - case 'K': tab.format.keep = true; break; - case 'P': tab.format.newpage = true; break; + case 'K': tabformat.keep = true; break; + case 'P': tabformat.newpage = true; break; case 'T': - tab.format.newhdrftr = true; - tab.format.header_qtf = GetText2('^', '^'); - tab.format.footer_qtf = GetText2('^', '^'); + tabformat.newhdrftr = true; + tabformat.header_qtf = GetText2('^', '^'); + tabformat.footer_qtf = GetText2('^', '^'); break; case 'a': Number2(a, b); @@ -442,7 +445,7 @@ void RichQtfParser::TableFormat(bool bw) t.format.margin.left = t.format.margin.right = t.format.margin.top = t.format.margin.bottom = b; break; //!!cell all lines case '*': - tab.format.frame = tab.format.grid = + tabformat.frame = tabformat.grid = t.format.border.left = t.format.border.right = t.format.border.top = t.format.border.bottom = t.format.margin.left = t.format.margin.right = t.format.margin.top = t.format.margin.bottom = 0; break; diff --git a/uppsrc/RichText/RichText.h b/uppsrc/RichText/RichText.h index 72cdd9e5d..eac15c11c 100644 --- a/uppsrc/RichText/RichText.h +++ b/uppsrc/RichText/RichText.h @@ -365,12 +365,12 @@ class RichText; struct RichContext { const RichText *text; const RichStyles *styles; - String header_qtf, footer_qtf; + RichText *header, *footer; int header_cy, footer_cy; Rect page; PageY py; - void NewHeaderFooter(const String& header_qtf, const String& footer_qtf); + void NewHeaderFooter(RichText *header, RichText *footer_qtf); void Page() { py.page++; py.y = page.top; } RichContext(const RichStyles& styles, const RichText *text) : styles(&styles), text(text) { header_cy = footer_cy = 0; } @@ -446,6 +446,9 @@ inline String StylesAsQTF(const RichText& doc, byte charset = CHARSET_UTF8) inline String BodyAsQTF(const RichText& doc, byte charset = CHARSET_UTF8) { return AsQTF(doc, charset, QTF_BODY|QTF_CRLF); } + +void SetQTF(One& txt, const String& qtf); + enum { ROUNDOFF = 1 << 20, diff --git a/uppsrc/RichText/Table.h b/uppsrc/RichText/Table.h index 0fa500e37..3eb4807b3 100644 --- a/uppsrc/RichText/Table.h +++ b/uppsrc/RichText/Table.h @@ -72,10 +72,11 @@ public: CellInfo() { valid = true; } }; +private: Format format; Array< Array > cell; + mutable One header, footer; -private: struct PaintCell : Moveable { int left; int right; @@ -146,8 +147,8 @@ private: friend class RichTxt; friend class RichText; -public: +public: Array& operator[](int i) { return cell[i]; } const Array& operator[](int i) const { return cell[i]; } RichCell& operator[](Point p) { return cell[p.y][p.x]; } diff --git a/uppsrc/RichText/TableData.cpp b/uppsrc/RichText/TableData.cpp index 775d6347e..668a649ff 100644 --- a/uppsrc/RichText/TableData.cpp +++ b/uppsrc/RichText/TableData.cpp @@ -302,6 +302,8 @@ Size RichTable::GetSpan(int i, int j) const void RichTable::SetFormat(const Format& fmt) { format = fmt; + Upp::SetQTF(header, fmt.header_qtf); + Upp::SetQTF(footer, fmt.footer_qtf); } RichTable RichTable::Copy(const Rect& sel) const diff --git a/uppsrc/RichText/Text.h b/uppsrc/RichText/Text.h index 1ca567b96..5cc72c022 100644 --- a/uppsrc/RichText/Text.h +++ b/uppsrc/RichText/Text.h @@ -39,8 +39,8 @@ public: void CatPick(RichText&& p); using RichTxt::CatPick; - RichContext Context(const Rect& page, PageY py, const String& header_qtf, const String& footer_qtf) const; - RichContext Context(const Rect& page, PageY py) const { return Context(page, py, header_qtf, footer_qtf); } + RichContext Context(const Rect& page, PageY py, RichText *header, RichText *footer) const; + RichContext Context(const Rect& page, PageY py) const { return Context(page, py, ~header, ~footer); } RichContext Context(const Rect& page) const { return Context(page, PageY(0, 0)); } RichPos GetRichPos(int pos, int maxlevel = INT_MAX) const; diff --git a/uppsrc/RichText/Txt.h b/uppsrc/RichText/Txt.h index 99c3bf814..b9e2f8e46 100644 --- a/uppsrc/RichText/Txt.h +++ b/uppsrc/RichText/Txt.h @@ -87,6 +87,7 @@ protected: mutable bool haspos; mutable bool newhdrftr; mutable String header_qtf, footer_qtf; + mutable One header, footer; One number; void Invalidate(); @@ -102,6 +103,7 @@ protected: Vector part; String header_qtf, footer_qtf; + mutable One header, footer; mutable int length; mutable int tabcount; mutable Vector py; diff --git a/uppsrc/RichText/TxtPaint.cpp b/uppsrc/RichText/TxtPaint.cpp index c2ff5eb5b..4e8209394 100644 --- a/uppsrc/RichText/TxtPaint.cpp +++ b/uppsrc/RichText/TxtPaint.cpp @@ -38,8 +38,18 @@ void RichTxt::Sync0(const Para& pp, int parti, const RichContext& rc) const pp.keepnext = p.format.keepnext; pp.orphan = p.format.orphan; pp.newhdrftr = p.format.newhdrftr; - pp.header_qtf = p.format.header_qtf; - pp.footer_qtf = p.format.footer_qtf; + if(~pp.header_qtf != ~p.format.header_qtf) { // we compare just pointers + pp.header_qtf = p.format.header_qtf; + pp.header.Clear(); + if(pp.header_qtf.GetCount()) + pp.header.Create() = ParseQTF(pp.header_qtf); + } + if(~pp.footer_qtf != ~p.format.footer_qtf) { // we compare just pointers + pp.footer_qtf = p.format.footer_qtf; + pp.footer.Clear(); + if(pp.footer_qtf.GetCount()) + pp.footer.Create() = ParseQTF(pp.footer_qtf); + } } void RichTxt::Sync(int parti, const RichContext& rc) const { @@ -72,7 +82,7 @@ void RichTxt::Advance(int parti, RichContext& rc, RichContext& begin) const const RichTable& tab = GetTable(parti); if(rc.text == this) { if(tab.format.newhdrftr) { - rc.NewHeaderFooter(tab.format.header_qtf, tab.format.footer_qtf); + rc.NewHeaderFooter(~tab.header, ~tab.footer); rc.Page(); } else @@ -100,7 +110,7 @@ void RichTxt::Advance(int parti, RichContext& rc, RichContext& begin) const nline = p.linecy[0]; } if(pp.newhdrftr && rc.text == this) { - rc.NewHeaderFooter(pp.header_qtf, pp.footer_qtf); + rc.NewHeaderFooter(~pp.header, ~pp.footer); rc.Page(); } else