ultimatepp/uppsrc/DocTypes/RtfDocOut.cpp
mdelfede 263ff5f895 changed svn layout
git-svn-id: svn://ultimatepp.org/upp/trunk@281 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2008-06-07 22:31:27 +00:00

272 lines
7.4 KiB
C++

#include <DocTypes/DocTypes.h>
NAMESPACE_UPP
RtfDocOut::RtfDocOut() {
color.Add(Black());
pgcx = 3968;
imagescale = 6;
page = false;
rtf.Reserve(8192);
}
#ifdef flagSO
RtfDocOut::~RtfDocOut() {}
#endif
void RtfDocOut::Clear() {
color.Clear();
color.Add(Black());
pgcx = 3968;
imagescale = 6;
page = false;
rtf.Clear();
}
void RtfDocOut::PutColor(const char *cmd, dword col) {
rtf.Cat(Format("\\%s%d", cmd, color.FindAdd(col) + 1));
}
void RtfDocOut::Border(const char *cmd, int width, dword color) {
if(width) {
rtf.Cat(Format("\\%s\\brdrth\\brdrw%d", cmd, Dow(width)));
PutColor("brdrcf", color);
}
}
Draw& ScreenInfo();
void RtfDocOut::PutPicture(const Drawing& iw, Size sz) {
#ifdef PLATFORM_WIN32
WinMetaFile wmf = iw.AsWMF();
HENHMETAFILE hemf = wmf.GetHEMF();
if(!hemf) return;
dword size = GetWinMetaFileBits(hemf, 0, NULL, MM_ANISOTROPIC, ScreenInfo());
if(size <= 0) return;
StringBuffer b(size);
GetWinMetaFileBits(hemf, size, (byte *) ~b, MM_ANISOTROPIC, ScreenInfo());
String data = b;
rtf.Cat(Format("\r\n{\\pict\\wmetafile8\\picw%d\\pich%d\\picwgoal%d\\pichgoal%d \r\n",
254 * sz.cx / 60, 254 * sz.cy / 60, Dow(sz.cx), Dow(sz.cy)));
static const char hex[] = "0123456789ABCDEF";
const byte *lim = (byte *) data.End();
for(const byte *s = data; s < lim; s++)
rtf << hex[*s >> 4] << hex[*s & 15];
rtf.Cat("\r\n}\r\n");
#endif
}
void RtfDocOut::PutPara(const Paragraph& p, bool par, bool table, int ls, int rs, int ts, int bs) {
int i;
const Paragraph::Style& st = p.GetStyle();
String bt;
String bf;
String bfs;
Font bsf = p.GetParaFont();
for(i = 0; i < p.GetCount(); i++) {
const Paragraph::Part& pi = p.GetParts()[i];
if(!pi.pr) {
bsf = pi.font;
break;
}
}
bfs = Format("%d ", 6 * abs(bsf.GetHeight()) / 25);
if(st.bullet) {
const Display *d = &st.bullet.GetDisplay();
bf = "4";
if(d == &Paragraph::WhiteBullet().GetDisplay())
bt = "\\'a1";
else
if(d == &Paragraph::BoxBullet().GetDisplay())
bt = "n";
else
if(d == &Paragraph::WhiteBoxBullet().GetDisplay())
bt = "o";
else {
bf = "3";
bt = "\\'b7";
}
rtf.Cat("{\\pntext\\pard\\plain\\f");
rtf.Cat(bf);
rtf.Cat("\\fs");
rtf.Cat(bfs);
rtf.Cat(bt);
rtf.Cat("\\tab}\r\n");
}
rtf.Cat("\\pard\\lang1029");
if(page) {
rtf.Cat("\\pagebb");
page = false;
}
rtf.Cat("\\q");
switch(st.align) {
default: rtf.Cat('l'); break;
case ALIGN_RIGHT: rtf.Cat('r'); break;
case ALIGN_JUSTIFY: rtf.Cat('j'); break;
case ALIGN_CENTER: rtf.Cat('c'); break;
}
if(table)
rtf.Cat("\\intbl");
int bi = st.bullet ? st.bulletindent : 0;
rtf.Cat(Format("\\fi%d\\li%d\\ri%d\\sb%d\\sa%d \r\n",
Dow(st.bullet ? -bi : st.indent), Dow(st.lm + ls + bi), Dow(st.rm + rs),
Dow(st.before + ts), Dow(st.after + bs)));
if(st.bullet) {
rtf.Cat("{\\*\\pn \\pnlvlblt\\pnf");
rtf.Cat(bf);
rtf.Cat("\\pnfs");
rtf.Cat(bfs);
rtf.Cat(Format("\\pnindent%d\\pnhang{\\pntxtb ", Dow(bi + st.indent)));
rtf.Cat(bt);
rtf.Cat("}}\r\n");
}
for(i = 0; i < p.GetCount(); i++) {
const Paragraph::Part& pi = p.GetParts()[i];
if(pi.pr) {
Size sz = (int)imagescale * pi.pr.GetStdSize();
if(pi.sz.cx) sz.cx = pi.sz.cx;
if(pi.sz.cy) sz.cy = pi.sz.cy;
DrawingDraw wd(sz);
pi.pr.Paint(wd, 0, 0, sz.cx, sz.cy, Black, White);
PutPicture(wd, sz);
}
else {
rtf.Cat('{');
if(pi.font.IsBold()) rtf.Cat("\\b");
if(pi.font.IsItalic()) rtf.Cat("\\i");
if(pi.font.IsUnderline()) rtf.Cat("\\ul");
if(pi.font.IsStrikeout()) rtf.Cat("\\strike");
switch(pi.font.GetFace()) {
case Font::ROMAN: rtf.Cat("\\f1"); break;
case Font::COURIER: rtf.Cat("\\f2"); break;
case Font::SYMBOL: rtf.Cat("\\f3"); break;
}
rtf.Cat(Format("\\fs%d", 6 * abs(pi.font.GetHeight()) / 25));
if(pi.color != Black)
PutColor("cf", pi.color);
rtf.Cat(' ');
for(const char *s = pi.text; *s; s++) {
int c = byte(*s);
if(c == 31)
rtf.Cat("\\~");
else
if(c < 128 && c != '{' && c != '\\' && c != '}')
rtf.Cat(c);
else
rtf.Cat(Format("\\'%2x", c));
}
rtf.Cat("}\r\n");
}
}
if(par) rtf.Cat("\\par ");
rtf.Cat("\r\n");
}
void RtfDocOut::Put(const Paragraph& paragraph) {
PutPara(paragraph);
}
struct RtfDocOut::VSpan : Moveable<RtfDocOut::VSpan> {
int x1, x2;
int span;
};
void RtfDocOut::Put(const Table& tab) {
const Table::Style& tst = tab.GetStyle();
int cx = pgcx - tst.lm - tst.rm;
Vector<VSpan> vspan;
rtf.Cat("\\par \r\n");
int lastrowi = tab.GetRows() - 1;
while(lastrowi > 0) {
if(tab[lastrowi].GetCount()) break;
lastrowi--;
}
for(int rowi = 0; rowi < tab.GetRows(); rowi++) {
int j;
const Array<TableCell>& row = tab[rowi];
if(row.GetCount()) {
rtf.Cat(Format("\\trowd \\trgaph0\\trleft%d", Dow(tst.lm)));
if(rowi < tab.GetHeaderRows())
rtf.Cat("\\trhdr");
rtf.Cat("\\trkeep \r\n");
int x = 0;
int n = GetTotalRatio(row);
for(j = 0; j < row.GetCount(); j++) {
const TableCell& cell = row[j];
const TableCell::Style& st = cell.GetStyle();
int x1 = cx * x / n + tst.lm;
int x2 = cx * (x + row[j].GetRatio()) / n + tst.lm;
if(cell.GetSpan() > 1) {
VSpan& v = vspan.Add();
v.span = cell.GetSpan();
v.x1 = x1;
v.x2 = x2;
rtf.Cat("\\clvmgf");
}
else
for(int i = 0; i < vspan.GetCount(); i++) {
VSpan& v = vspan[i];
if(v.x1 == x1 && v.x2 == x2)
rtf.Cat("\\clvmrg");
}
rtf.Cat("\\clvertal");
rtf.Cat(st.align == ALIGN_TOP ? 't' : st.align == ALIGN_CENTER ? 'c' : 'b');
Border("clbrdrt", st.topwidth + (rowi == 0) * tst.framewidth, tst.framecolor);
Border("clbrdrl", st.leftwidth + (j == 0) * tst.framewidth, tst.framecolor);
Border("clbrdrb", st.bottomwidth + (rowi == lastrowi) * tst.framewidth,
tst.framecolor);
Border("clbrdrr", st.rightwidth + (j == row.GetCount() - 1) * tst.framewidth,
tst.framecolor);
if(GetRValue(st.paper) == GetGValue(st.paper) &&
GetGValue(st.paper) == GetBValue(st.paper))
rtf.Cat(Format("\\clshdng%d", 10000 - 10000 * GetBValue(st.paper) / 255));
else
PutColor("clcbpat", st.paper);
rtf.Cat(Format("\\cellx%d \n", Dow(x2)));
x += row[j].GetRatio();
}
for(j = 0; j < row.GetCount(); j++) {
const TableCell& cell = row[j];
const TableCell::Style& st = row[j].GetStyle();
for(int i = 0; i < cell.GetCount(); i++)
PutPara(cell[i], i < cell.GetCount() - 1, true, st.leftspace, st.rightspace,
(i == 0) * st.topspace, (i == cell.GetCount() - 1) * st.bottomspace);
rtf.Cat("\\cell \r\n");
}
rtf.Cat("\\pard\\intbl\\row \r\n");
for(int i = 0; i < vspan.GetCount();)
if(--vspan[i].span <= 0)
vspan.Remove(i);
else
i++;
}
}
rtf.Cat("\\pard \r\n");
}
void RtfDocOut::Page() {
page = true;
}
String RtfDocOut::Get() {
String out =
"{\\rtf1\\ansi\\ansicpg1250\r\n"
"{\\fonttbl\r\n"
"{\\f0\\fswiss\\fcharset238\\cpg1250 Arial CE;Arial;}\r\n"
"{\\f1\\froman\\fcharset238\\cpg1250 Times New Roman CE;Times New Roman;}\r\n"
"{\\f2\\fmodern\\fcharset238\\cpg1250 Courier New CE;Courier New;}\r\n"
"{\\f3\\ftech\\fcharset238\\cpg1250 Symbol;}\r\n"
"{\\f4\\ftech\\fcharset238\\cpg1250 WingDings;}\r\n"
"}\r\n"
"{\\colortbl;\r\n";
for(int i = 0; i < color.GetCount(); i++)
out.Cat(Format("\\red%d\\green%d\\blue%d;\r\n",
GetRValue(color[i]), GetGValue(color[i]), GetBValue(color[i])));
out += "}\n"
"\\f0\\pard\\plain \r\n";
out += rtf;
out += "}\r\n";
return out;
}
END_UPP_NAMESPACE