textformatter.cpp
来自「俄罗斯人开发的大名鼎鼎的Pocket Pc 阅读器haaliread的源代码,v」· C++ 代码 · 共 775 行 · 第 1/2 页
CPP
775 行
bool header=true;
for (int page=0;page<m_pages;++page) {
int h=0;
int beg=m_lines.GetSize();
while (h<m_height && start.para<m_tf->Length(start.docid)) {
Paragraph para(m_tf->GetParagraph(start.docid,start.para));
bool empty=para.len==0 || para.len==1 && para.str[0]==_T(' ');
if (h==0 && empty) {
start.off=para.len;
AdjustPos(start);
continue;
}
if (para.flags & Paragraph::header) {
if (!header)
break;
} else
if (!empty && !(para.flags & Paragraph::image))
header=false;
int lh=WrapLine(dc,para,start,m_lines,h,m_height-h);
if (lh<0)
break;
AdjustPos(start);
h+=lh;
}
m_pagelen.SetAtGrow(page,m_lines.GetSize()-beg);
}
m_bot=start;
Highlight();
// add one dummy line always
Line l;
l.pos=m_bot;
m_lines.Add(l);
return true;
}
bool TextFormatter::FormatBack(CFDC& dc,FilePos start,FilePos prev_top) {
AdjustPos(start,true);
if (start.para==0 && start.off==0)
return false; // at the top
m_lines.RemoveAll();
m_bot=start;
for (int page=m_pages-1;page>=0;--page) {
LineArray tmp;
FilePos pos=start;
int h=0;
// while there are still paragrahs before
while (h<m_height && (pos.para>0 || pos.off>0)) {
// format entire paragraph
LineArray cp;
Paragraph para(m_tf->GetParagraph(pos.docid,pos.para));
if (pos.off<para.len) // double check args
para.len=pos.off;
else
pos.off=para.len;
WrapLine(dc,para,FilePos(pos.para,0,pos.docid),cp,0,32768);
// insert the formatted paragraph at start of list
tmp.InsertAt(0,&cp);
for (int i=0;i<cp.GetSize();++i)
h+=cp[i].height;
pos.off=0;
AdjustPos(pos,true);
}
// delete extra lines
int j;
// remove top lines
for (h=0,j=tmp.GetUpperBound();j>=0 && h+tmp[j].height<=m_height;--j)
h+=tmp[j].height;
if (j<tmp.GetUpperBound()) {
if (j>=0 && prev_top!=0 && tmp[j+1].pos>=prev_top) {
--j;
tmp.RemoveAt(0,j+1);
// now remove bottom lines
for (h=j=0;j<tmp.GetSize() && h+tmp[j].height<=m_height;++j)
h+=tmp[j].height;
if (j<tmp.GetSize())
tmp.RemoveAt(j,tmp.GetSize()-j);
} else
tmp.RemoveAt(0,j+1);
}
// save lines
m_lines.InsertAt(0,&tmp);
m_pagelen.SetAtGrow(page,tmp.GetSize());
start=m_lines[0].pos;
if (start.para==0 && start.off==0) // we reached the top of file
return FormatFwd(dc,FilePos(0,0,start.docid));
}
// save positions
m_top=m_lines[0].pos;
Highlight();
// add one dummy line always
Line l;
l.pos=m_bot;
m_lines.Add(l);
return true;
}
void TextFormatter::AdjustPos(FilePos& p,bool back) {
if (back) {
if (p.para>0) {
if (p.para>=m_tf->Length(p.docid)) {
if (m_tf->Length(p.docid)>0) {
p.para=m_tf->Length(p.docid)-1;
p.off=m_tf->GetPLength(p.docid,p.para);
}
} else {
if (p.off==0) {
--p.para;
p.off=m_tf->GetPLength(p.docid,p.para);
}
}
}
} else {
if (p.para>=0 && p.para<m_tf->Length(p.docid) && p.off>=m_tf->GetPLength(p.docid,p.para)) {
p.off=0;
p.para++;
}
}
}
void TextFormatter::SetSize(int width,int margin,int height,int pages,
int angle)
{
if (height<1)
height=1;
if (pages<1)
pages=1;
m_total_width=width;
m_margin=margin;
m_width=m_total_width-2*m_margin;
if (m_width<1)
m_width=1;
m_height=height;
m_pages=pages;
m_angle=angle;
}
bool TextFormatter::AtTop()
{
FilePos p(m_top);
AdjustPos(p,true);
return p.off==0 && p.para==0;
}
bool TextFormatter::AtEof()
{
FilePos p(m_bot);
AdjustPos(p);
return p.para>=m_tf->Length(p.docid);
}
static bool intersect(int a,int la,int b,int lb,int& i,int& li) {
if (a>=b && a<b+lb) {
i=a-b;
if (la>b+lb-a)
li=b+lb-a;
else
li=la;
return true;
}
if (b>=a && b<a+la) {
i=0;
if (lb>a+la-b)
li=a+la-b;
else
li=lb;
return true;
}
return false;
}
void TextFormatter::Highlight() {
if (!m_hllen || m_hlstart.docid!=DocId())
return;
FilePos hls(m_hlstart);
int hll=m_hllen;
for (int i=0;i<m_lines.GetSize();++i)
if (hls.para==m_lines[i].pos.para) {
int beg,len;
if (hls.off-m_lines[i].pos.off<m_lines[i].real_len &&
intersect(hls.off,hll,m_lines[i].pos.off,m_lines[i].str.size(),beg,len))
{
int top=beg+len;
while (beg<top)
m_lines[i].attr[beg++].hibg=true;
m_lines[i].flags&=~Line::defstyle;
} else
m_lines[i].CheckStyle();
// advance our pointer
if (i<m_lines.GetSize()-1 && m_lines[i+1].pos.para>hls.para &&
hls.off+hll>m_tf->GetPLength(hls.docid,hls.para))
{
hll-=m_tf->GetPLength(hls.docid,hls.para)-hls.off;
++hls.para;
hls.off=0;
}
} else
m_lines[i].CheckStyle();
}
bool TextFormatter::SetHighlight(FilePos pos,int len) {
if (m_hllen==len && (!len || pos==m_hlstart)) // avoid extra work
return false;
// remove highlighting
for (int i=0;i<m_lines.GetSize();++i) {
for (int j=0;j<m_lines[i].attr.size();++j)
m_lines[i].attr[j].hibg=false;
}
m_hlstart=pos;
m_hllen=len;
Highlight();
return true;
}
void Line::CheckStyle() {
Attr *p=attr;
Attr *e=p+attr.size();
while (p<e)
if ((*p++).wa) {
flags&=~defstyle;
return;
}
flags|=defstyle;
}
int TextFormatter::Distance(const FilePos& a,const FilePos& b)
{
FilePos start(a), end(b);
bool sign=false;
if (a>b) {
start=b;
end=a;
sign=true;
}
// check bounds
if (start.para<0)
start.para=0;
if (start.para>m_tf->Length(start.docid)) {
start.para=m_tf->Length(start.docid);
start.off=0;
}
if (start.off<0)
start.off=0;
if (start.off>m_tf->GetPLength(start.docid,start.para))
start.off=m_tf->GetPLength(start.docid,start.para);
if (end.para<0)
end.para=0;
if (end.para>m_tf->Length(end.docid)) {
end.para=m_tf->Length(end.docid);
end.off=0;
}
if (end.off<0)
end.off=0;
if (end.off>m_tf->GetPLength(end.docid,end.para))
end.off=m_tf->GetPLength(end.docid,end.para);
// calc distance now
int dist;
if (start.para==end.para)
dist=end.off-start.off;
else {
dist=m_tf->GetPLength(start.docid,start.para)-start.off;
++start.para;
while (start.para<end.para) {
dist+=m_tf->GetPLength(start.docid,start.para);
++start.para;
}
dist+=end.off;
}
return sign ? -dist : dist;
}
bool TextFormatter::EnsureVisible(CFDC& dc,FilePos pos) {
if (pos>=m_top && pos<m_bot)
return false;
FilePos ptop(pos);
ptop.off=0;
if (!FormatFwd(dc,ptop))
return true;
while (m_top.para==pos.para && pos>=m_bot)
if (!FormatFwd(dc))
break;
return true;
}
void TextFormatter::FormatPlainText(CFDC& dc,
int& width,int& height,
int fontsize,
const wchar_t *text,int len,
LineArray& lines)
{
lines.RemoveAll();
int save_width=m_width;
bool save_justified=m_justified;
m_width=width;
m_justified=false;
const wchar_t *top=text+len;
Attr attr;
attr.wa=0;
attr.fsize=fontsize;
int curh=0;
while (text<top && curh<height) {
const wchar_t *p_end=text;
while (p_end<top && *p_end!='\r' && *p_end!='\n')
++p_end;
Paragraph p(p_end-text);
memcpy(p.str,text,(p_end-text)*sizeof(wchar_t));
for (int i=0;i<p.cflags.size();++i)
p.cflags[i].wa=attr.wa;
p.findent=3; // XXX
int last=lines.GetSize();
int lh=WrapLine(dc,p,FilePos(),lines,curh,height-curh);
if (lh<0) { // it still might add something
while (last<lines.GetSize())
curh+=lines[last++].height;
break;
}
curh+=lh;
while (p_end<top && (*p_end=='\r' || *p_end=='\n'))
++p_end;
text=p_end;
}
m_width=save_width;
m_justified=save_justified;
// deduct ispace
int min_ispace=-1,max_width=0;
for (int i=0;i<lines.GetSize();++i) {
const Line& ll=lines[i];
int w=0;
for (int j=0;j<ll.dx.size();++j)
w+=ll.dx[j];
w+=ll.ispace;
if (max_width<w)
max_width=w;
if (min_ispace<0 || min_ispace>ll.ispace)
min_ispace=ll.ispace;
}
if (min_ispace>0) {
for (int i=0;i<lines.GetSize();++i)
lines[i].ispace-=min_ispace;
max_width-=min_ispace;
}
height=curh;
width=max_width;
}
bool TextFormatter::FormatFwdAdj(CFDC& dc) {
// if an image crosses the bottom of the window, and does not start
// at the top of window, then move down only until the image is
// fully visible
AdjustPos(m_bot);
Paragraph p(m_tf->GetParagraph(m_bot.docid,m_bot.para));
if (p.flags&Paragraph::image && // image
m_bot.off>0 && // crosses window border
(m_top.docid!=m_bot.docid || m_top.para!=m_bot.para)) // is not visible at top
// then do a partial move forward to show a whole image
m_bot.off=0;
return FormatFwd(dc,m_bot);
}
void TextFormatter::SetTop(FilePos pos) {
if (pos.docid >= m_tf->GetSubDocCount()) {
pos.docid = m_tf->GetSubDocCount() - 1;
if (pos.docid < 0)
pos.docid=0;
}
if (pos.para >= m_tf->Length(pos.docid)) {
pos.para=m_tf->Length(pos.docid)-1;
if (pos.para<0)
pos.para=0;
}
if (pos.off >= m_tf->GetPLength(pos.docid,pos.para)) {
pos.off = m_tf->GetPLength(pos.docid,pos.para) - 1;
if (pos.off<0)
pos.off=0;
}
m_top=pos;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?