mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -06:00
650 lines
14 KiB
C++
650 lines
14 KiB
C++
#include "RichEdit.h"
|
|
|
|
namespace Upp {
|
|
|
|
Point RichEdit::GetPreedit()
|
|
{
|
|
Rect r = GetCaretRect();
|
|
if(formatinfo.sscript == 2) {
|
|
Point p = r.BottomRight();
|
|
p.y -= 3 * r.GetHeight() / 5;
|
|
return p;
|
|
}
|
|
return r.TopRight();
|
|
}
|
|
|
|
Font RichEdit::GetPreeditFont()
|
|
{
|
|
Font fnt = formatinfo;
|
|
int h = abs(fnt.GetHeight());
|
|
if(formatinfo.sscript)
|
|
h = 3 * h / 5;
|
|
return fnt(max(GetZoom() * abs(h), 1));
|
|
}
|
|
|
|
void RichEdit::ApplyFormat(dword charvalid, dword paravalid)
|
|
{
|
|
if(IsReadOnly())
|
|
return;
|
|
RichText::FormatInfo f = formatinfo;
|
|
f.charvalid = charvalid;
|
|
f.paravalid = paravalid;
|
|
if(objectpos >= 0) {
|
|
ModifyFormat(objectpos, f, 1);
|
|
Finish();
|
|
}
|
|
if(IsSelection()) {
|
|
if(tablesel) {
|
|
NextUndo();
|
|
SaveTable(tablesel);
|
|
text.ApplyTableFormatInfo(tablesel, cells, f);
|
|
}
|
|
else {
|
|
int l = min(cursor, anchor);
|
|
int h = max(cursor, anchor);
|
|
RichPos rp = text.GetRichPos(h);
|
|
if(rp.posinpara == 0 && h > l) {
|
|
RichPos rp1 = text.GetRichPos(h - 1);
|
|
if(InSameTxt(rp, rp1))
|
|
h--;
|
|
}
|
|
ModifyFormat(l, f, h - l);
|
|
}
|
|
Finish();
|
|
}
|
|
else
|
|
if(cursorp.paralen == 0) {
|
|
ModifyFormat(cursor, f, 0);
|
|
Finish();
|
|
}
|
|
else
|
|
if(f.paravalid) {
|
|
ModifyFormat(cursor, f, 0);
|
|
Finish();
|
|
}
|
|
else
|
|
RefreshBar();
|
|
}
|
|
|
|
void RichEdit::ApplyFormatInfo(const RichText::FormatInfo& fi)
|
|
{
|
|
fi.ApplyTo(formatinfo);
|
|
formatinfo.charvalid |= fi.charvalid;
|
|
formatinfo.paravalid |= fi.paravalid;
|
|
ApplyFormat(fi.charvalid, fi.paravalid);
|
|
}
|
|
|
|
void RichEdit::Bold()
|
|
{
|
|
NextUndo();
|
|
formatinfo.Bold(!(formatinfo.IsBold() && (formatinfo.charvalid & RichText::BOLD)));
|
|
ApplyFormat(RichText::BOLD);
|
|
}
|
|
|
|
void RichEdit::Italic()
|
|
{
|
|
NextUndo();
|
|
formatinfo.Italic(!(formatinfo.IsItalic() && (formatinfo.charvalid & RichText::ITALIC)));
|
|
ApplyFormat(RichText::ITALIC);
|
|
}
|
|
|
|
void RichEdit::Underline()
|
|
{
|
|
NextUndo();
|
|
formatinfo.Underline(!(formatinfo.IsUnderline() && (formatinfo.charvalid & RichText::UNDERLINE)));
|
|
ApplyFormat(RichText::UNDERLINE);
|
|
}
|
|
|
|
void RichEdit::Strikeout()
|
|
{
|
|
NextUndo();
|
|
formatinfo.Strikeout(!(formatinfo.IsStrikeout() && (formatinfo.charvalid & RichText::STRIKEOUT)));
|
|
ApplyFormat(RichText::STRIKEOUT);
|
|
}
|
|
|
|
void RichEdit::Capitals()
|
|
{
|
|
NextUndo();
|
|
formatinfo.capitals = !formatinfo.capitals && (formatinfo.charvalid & RichText::CAPITALS);
|
|
ApplyFormat(RichText::CAPITALS);
|
|
}
|
|
|
|
void RichEdit::SetScript(int i)
|
|
{
|
|
NextUndo();
|
|
formatinfo.sscript = i;
|
|
ApplyFormat(RichText::SSCRIPT);
|
|
}
|
|
|
|
void RichEdit::SetFace()
|
|
{
|
|
NextUndo();
|
|
formatinfo.Face(~face);
|
|
ApplyFormat(RichText::FACE);
|
|
SetFocus();
|
|
}
|
|
|
|
void RichEdit::SetHeight()
|
|
{
|
|
NextUndo();
|
|
formatinfo.Height(PtToDot(~height, unit));
|
|
ApplyFormat(RichText::HEIGHT);
|
|
SetFocus();
|
|
}
|
|
|
|
void RichEdit::SetInk()
|
|
{
|
|
NextUndo();
|
|
formatinfo.ink = ~ink;
|
|
ApplyFormat(RichText::INK);
|
|
SetFocus();
|
|
}
|
|
|
|
void RichEdit::SetPaper()
|
|
{
|
|
NextUndo();
|
|
formatinfo.paper = ~paper;
|
|
ApplyFormat(RichText::PAPER);
|
|
SetFocus();
|
|
}
|
|
|
|
void RichEdit::SetLanguage()
|
|
{
|
|
NextUndo();
|
|
formatinfo.language = (int)~language;
|
|
ApplyFormat(RichText::LANGUAGE);
|
|
SetFocus();
|
|
}
|
|
|
|
void RichEdit::Language()
|
|
{
|
|
WithRichLanguageLayout<TopWindow> d;
|
|
CtrlLayoutOKCancel(d, t_("Language"));
|
|
d.lang <<= ~language;
|
|
if(d.Run() != IDOK)
|
|
return;
|
|
formatinfo.language = (int)~d.lang;
|
|
ApplyFormat(RichText::LANGUAGE);
|
|
SetFocus();
|
|
if(!language.HasKey((int)~d.lang)) {
|
|
Vector<int> h;
|
|
for(int i = 0; i < language.GetCount(); i++)
|
|
h.Add(language.GetKey(i));
|
|
h.Add(~d.lang);
|
|
SetupLanguage(pick(h));
|
|
}
|
|
}
|
|
|
|
void RichEdit::IndentMark()
|
|
{
|
|
RichRuler::Marker m;
|
|
int l = formatinfo.lm;
|
|
int r = cursorc.textpage.Width() - formatinfo.rm;
|
|
m.pos = l + formatinfo.indent;
|
|
m.minpos = max(l, 0);
|
|
m.maxpos = max(r - 120, 0);
|
|
m.top = true;
|
|
m.image = formatinfo.paravalid & RichText::INDENT ? RichEditImg::Indent()
|
|
: RichEditImg::IndentMixed();
|
|
ruler.Set(2, m);
|
|
}
|
|
|
|
void RichEdit::ReadFormat()
|
|
{
|
|
if(objectpos >= 0)
|
|
formatinfo = text.GetFormatInfo(objectpos, 1);
|
|
else
|
|
if(IsSelection())
|
|
if(tablesel)
|
|
formatinfo = text.GetTableFormatInfo(tablesel, cells);
|
|
else
|
|
formatinfo = text.GetFormatInfo(min(cursor, anchor), abs(cursor - anchor));
|
|
else {
|
|
RichPos p = cursorp;
|
|
if(cursor && p.posinpara)
|
|
p = text.GetRichPos(cursor - 1);
|
|
formatinfo.Set(p.format);
|
|
}
|
|
ShowFormat();
|
|
}
|
|
|
|
void RichEdit::ShowFormat()
|
|
{
|
|
RefreshBar();
|
|
|
|
if(formatinfo.charvalid & RichText::FACE)
|
|
face <<= formatinfo.GetFace();
|
|
else
|
|
face <<= Null;
|
|
|
|
if(formatinfo.charvalid & RichText::HEIGHT)
|
|
height <<= DotToPt(formatinfo.GetHeight(), unit);
|
|
else
|
|
height <<= Null;
|
|
|
|
if(formatinfo.charvalid & RichText::LINK)
|
|
hyperlink <<= formatinfo.link;
|
|
else
|
|
hyperlink <<= Null;
|
|
|
|
if(formatinfo.charvalid & RichText::INDEXENTRY)
|
|
indexentry <<= formatinfo.indexentry;
|
|
else
|
|
indexentry <<= Null;
|
|
|
|
if(formatinfo.charvalid & RichText::INK)
|
|
ink <<= formatinfo.ink;
|
|
else
|
|
ink <<= Null;
|
|
|
|
if(formatinfo.charvalid & RichText::PAPER)
|
|
paper <<= formatinfo.paper;
|
|
else
|
|
paper <<= Null;
|
|
|
|
if(formatinfo.charvalid & RichText::LANG)
|
|
language <<= (int)formatinfo.language;
|
|
else
|
|
language <<= Null;
|
|
|
|
if(IsSelection())
|
|
label <<= Null;
|
|
else
|
|
label <<= formatinfo.label;
|
|
|
|
int l = formatinfo.lm;
|
|
int r = cursorc.textpage.Width() - formatinfo.rm;
|
|
|
|
RichRuler::Marker m;
|
|
m.pos = l;
|
|
m.minpos = 0;
|
|
m.maxpos = max(r - formatinfo.indent - 120, 0);
|
|
m.image = formatinfo.paravalid & RichText::LM ? RichEditImg::Margin() : RichEditImg::MarginMixed();
|
|
ruler.Set(0, m);
|
|
|
|
m.pos = r;
|
|
m.minpos = max(l + formatinfo.indent + 120, 0);
|
|
m.maxpos = cursorc.textpage.Width();
|
|
m.image = formatinfo.paravalid & RichText::RM ? RichEditImg::Margin() : RichEditImg::MarginMixed();
|
|
ruler.Set(1, m);
|
|
IndentMark();
|
|
|
|
int maxpos = 0;
|
|
m.minpos = 0;
|
|
m.deletable = true;
|
|
if(formatinfo.paravalid & RichText::TABS) {
|
|
for(int i = 0; i < formatinfo.tab.GetCount(); i++) {
|
|
RichPara::Tab tab = formatinfo.tab[i];
|
|
m.pos = tab.pos;
|
|
if(tab.pos > maxpos)
|
|
maxpos = tab.pos;
|
|
switch(tab.align) {
|
|
case ALIGN_LEFT:
|
|
m.image = RichEditImg::LeftTab();
|
|
break;
|
|
case ALIGN_RIGHT:
|
|
m.image = RichEditImg::RightTab();
|
|
break;
|
|
case ALIGN_CENTER:
|
|
m.image = RichEditImg::CenterTab();
|
|
break;
|
|
}
|
|
ruler.Set(i + 3, m);
|
|
}
|
|
ruler.SetTabs(maxpos, formatinfo.tabsize);
|
|
ruler.SetCount(formatinfo.tab.GetCount() + 3);
|
|
}
|
|
else {
|
|
ruler.SetTabs(INT_MAX / 2, 1);
|
|
ruler.SetCount(3);
|
|
}
|
|
|
|
if(formatinfo.paravalid & RichText::STYLE)
|
|
style <<= formatinfo.styleid;
|
|
else
|
|
style <<= Null;
|
|
setstyle->Enable(!IsSelection());
|
|
}
|
|
|
|
void RichEdit::HighLightTab(int r)
|
|
{
|
|
RichRuler::Marker m = ruler[r + 3];
|
|
RichPara::Tab tab = formatinfo.tab[r];
|
|
m.image = tab.align == ALIGN_RIGHT ? RichEditImg::RightTabTrack() :
|
|
tab.align == ALIGN_CENTER ? RichEditImg::CenterTabTrack() :
|
|
RichEditImg::LeftTabTrack();
|
|
ruler.Set(r + 3, m);
|
|
}
|
|
|
|
void RichEdit::Hyperlink()
|
|
{
|
|
String s = formatinfo.link;
|
|
if(!IsSelection() && !IsNull(s) && cursorp.format.link == s && text[cursor] != '\n') {
|
|
int l = cursor - 1;
|
|
while(l >= 0 && text[l] != '\n' && text.GetRichPos(l).format.link == s)
|
|
l--;
|
|
l++;
|
|
int h = cursor;
|
|
while(h < text.GetLength() && text[h] != '\n' && text.GetRichPos(h).format.link == s)
|
|
h++;
|
|
if(l < h)
|
|
Select(l, h - l);
|
|
}
|
|
WString linktext;
|
|
WhenHyperlink(s, linktext);
|
|
if(s != formatinfo.link || linktext.GetLength()) {
|
|
formatinfo.link = s;
|
|
hyperlink <<= s;
|
|
NextUndo();
|
|
ApplyFormat(RichText::LINK);
|
|
if(linktext.GetLength()) {
|
|
RemoveSelection();
|
|
RichPara p;
|
|
p.format = formatinfo;
|
|
p.Cat(linktext, formatinfo);
|
|
RichText txt;
|
|
txt.SetStyles(text.GetStyles());
|
|
txt.Cat(p);
|
|
Insert(cursor, txt, true);
|
|
Move(cursor + linktext.GetCount(), false);
|
|
}
|
|
}
|
|
SetFocus();
|
|
}
|
|
|
|
void RichEdit::Label()
|
|
{
|
|
if(IsSelection()) return;
|
|
String s = formatinfo.label;
|
|
WhenLabel(s);
|
|
if(s != formatinfo.label) {
|
|
formatinfo.label = s;
|
|
NextUndo();
|
|
ApplyFormat(0, RichText::LABEL);
|
|
SetFocus();
|
|
}
|
|
}
|
|
|
|
void RichEdit::IndexEntry()
|
|
{
|
|
String s = formatinfo.indexentry.ToString();
|
|
String s0 = s;
|
|
WhenIndexEntry(s);
|
|
if(s != s0) {
|
|
formatinfo.indexentry = s.ToWString();
|
|
ApplyFormat(RichText::INDEXENTRY);
|
|
NextUndo();
|
|
SetFocus();
|
|
}
|
|
}
|
|
|
|
void RichEdit::BeginRulerTrack()
|
|
{
|
|
NextUndo();
|
|
SaveFormat();
|
|
int r = ruler.GetTrack();
|
|
if(r < 0) return;
|
|
RichRuler::Marker m = ruler[r];
|
|
switch(r) {
|
|
case 0:
|
|
case 1:
|
|
m.image = RichEditImg::MarginTrack();
|
|
break;
|
|
case 2:
|
|
m.image = RichEditImg::IndentTrack();
|
|
break;
|
|
default:
|
|
HighLightTab(r - 3);
|
|
return;
|
|
}
|
|
ruler.Set(r, m);
|
|
}
|
|
|
|
void RichEdit::SetParaFormat(dword paravalid)
|
|
{
|
|
RichText::FormatInfo f = formatinfo;
|
|
f.charvalid = 0;
|
|
f.paravalid = paravalid;
|
|
if(IsSelection())
|
|
if(tablesel)
|
|
text.ApplyTableFormatInfo(tablesel, cells, f);
|
|
else
|
|
text.ApplyFormatInfo(min(cursor, anchor), f, abs(cursor - anchor));
|
|
else
|
|
text.ApplyFormatInfo(cursor, f, 0);
|
|
}
|
|
|
|
void RichEdit::RulerTrack()
|
|
{
|
|
int r = ruler.GetTrack();
|
|
if(r < 0) return;
|
|
RichRuler::Marker m = ruler[r];
|
|
switch(r) {
|
|
case 0:
|
|
formatinfo.lm = m.pos;
|
|
SetParaFormat(RichText::LM);
|
|
IndentMark();
|
|
break;
|
|
case 1:
|
|
formatinfo.rm = cursorc.textpage.Width() - m.pos;
|
|
SetParaFormat(RichText::RM);
|
|
break;
|
|
case 2:
|
|
formatinfo.indent = m.pos - formatinfo.lm;
|
|
SetParaFormat(RichText::INDENT);
|
|
break;
|
|
default:
|
|
formatinfo.tab[r - 3].pos = m.pos;
|
|
SetParaFormat(RichText::TABS);
|
|
int maxpos = 0;
|
|
for(int i = 0; i < formatinfo.tab.GetCount(); i++) {
|
|
RichPara::Tab tab = formatinfo.tab[i];
|
|
if(tab.pos > maxpos)
|
|
maxpos = tab.pos;
|
|
}
|
|
ruler.SetTabs(maxpos, formatinfo.tabsize);
|
|
break;
|
|
}
|
|
FinishNF();
|
|
}
|
|
|
|
void RichEdit::TabAdd(int align)
|
|
{
|
|
RichPara::Tab tab;
|
|
tab.pos = ruler.GetPos();
|
|
tab.align = align;
|
|
if(formatinfo.tab.GetCount() > 30000 || tab.pos < 0 || tab.pos >= cursorc.textpage.Width()) return;
|
|
formatinfo.tab.Add(tab);
|
|
SetParaFormat(RichText::TABS);
|
|
Finish();
|
|
}
|
|
|
|
void RichEdit::AddTab()
|
|
{
|
|
NextUndo();
|
|
SaveFormat();
|
|
TabAdd(ruler.GetNewTabAlign());
|
|
}
|
|
|
|
void RichEdit::TabMenu()
|
|
{
|
|
NextUndo();
|
|
int r = ruler.GetTrack() - 3;
|
|
if(r >= 0)
|
|
HighLightTab(r);
|
|
CallbackArgTarget<int> align;
|
|
CallbackArgTarget<int> fill;
|
|
MenuBar menu;
|
|
menu.Add(t_("Left"), RichEditImg::LeftTab(), align[ALIGN_LEFT]);
|
|
menu.Add(t_("Right"), RichEditImg::RightTab(), align[ALIGN_RIGHT]);
|
|
menu.Add(t_("Center"), RichEditImg::CenterTab(), align[ALIGN_CENTER]);
|
|
if(r >= 0) {
|
|
int f = formatinfo.tab[r].fillchar;
|
|
menu.Separator();
|
|
menu.Add(t_("No fill"), fill[0])
|
|
.Radio(f == 0);
|
|
menu.Add(t_("Fill with ...."), fill[1])
|
|
.Radio(f == 1);
|
|
menu.Add(t_("Fill with ----"), fill[2])
|
|
.Radio(f == 2);
|
|
menu.Add(t_("Fill with __"), fill[3])
|
|
.Radio(f == 3);
|
|
menu.Separator();
|
|
menu.Add(t_("Remove"), fill[-1]);
|
|
}
|
|
menu.Execute();
|
|
if(!IsNull(align)) {
|
|
SaveFormat();
|
|
if(r >= 0) {
|
|
formatinfo.tab[r].align = (int)align;
|
|
SetParaFormat(RichText::TABS);
|
|
}
|
|
else
|
|
TabAdd(align);
|
|
}
|
|
if(!IsNull(fill) && r >= 0) {
|
|
SaveFormat();
|
|
if(r >= 0) {
|
|
if(fill == -1)
|
|
formatinfo.tab[r].pos = Null;
|
|
else
|
|
formatinfo.tab[r].fillchar = (int)fill;
|
|
SetParaFormat(RichText::TABS);
|
|
}
|
|
}
|
|
Finish();
|
|
}
|
|
|
|
void RichEdit::AlignLeft()
|
|
{
|
|
NextUndo();
|
|
formatinfo.align = ALIGN_LEFT;
|
|
ApplyFormat(0, RichText::ALIGN);
|
|
}
|
|
|
|
void RichEdit::AlignRight()
|
|
{
|
|
NextUndo();
|
|
formatinfo.align = ALIGN_RIGHT;
|
|
ApplyFormat(0, RichText::ALIGN);
|
|
}
|
|
|
|
void RichEdit::AlignCenter()
|
|
{
|
|
NextUndo();
|
|
formatinfo.align = ALIGN_CENTER;
|
|
ApplyFormat(0, RichText::ALIGN);
|
|
}
|
|
|
|
void RichEdit::AlignJustify()
|
|
{
|
|
NextUndo();
|
|
formatinfo.align = ALIGN_JUSTIFY;
|
|
ApplyFormat(0, RichText::ALIGN);
|
|
}
|
|
|
|
void RichEdit::SetBullet(int bullet)
|
|
{
|
|
NextUndo();
|
|
if((formatinfo.paravalid & RichText::BULLET) && formatinfo.bullet == bullet) {
|
|
formatinfo.bullet = RichPara::BULLET_NONE;
|
|
formatinfo.indent = formatinfo.paravalid & RichText::STYLE ?
|
|
text.GetStyle(formatinfo.styleid).format.indent : 0;
|
|
}
|
|
else {
|
|
formatinfo.bullet = bullet;
|
|
formatinfo.indent = bullet_indent;
|
|
}
|
|
ApplyFormat(0, RichText::INDENT|RichText::BULLET);
|
|
}
|
|
|
|
void RichEdit::Style()
|
|
{
|
|
NextUndo();
|
|
SaveFormat(cursor, 0);
|
|
formatinfo.Set(text.GetStyle((Uuid)~style).format);
|
|
ApplyFormat(0, RichText::STYLE);
|
|
SetFocus();
|
|
Finish();
|
|
}
|
|
|
|
void RichEdit::AdjustObjectSize()
|
|
{
|
|
NextUndo();
|
|
RichObject obj = cursorp.object;
|
|
if(!obj) return;
|
|
WithObjectSizeLayout<TopWindow> d;
|
|
CtrlLayoutOKCancel(d, t_("Object position"));
|
|
Size sz = obj.GetSize();
|
|
Size psz = GetPhysicalSize(obj);
|
|
if(psz.cx == 0) psz.cx = 2000;
|
|
if(psz.cy == 0) psz.cy = 2000;
|
|
d.width.Set(unit, sz.cx);
|
|
d.height.Set(unit, sz.cy);
|
|
d.widthp.SetInc(5).Pattern("%.1f");
|
|
d.widthp <<= 100.0 * sz.cx / psz.cx;
|
|
d.heightp.SetInc(5).Pattern("%.1f");
|
|
d.heightp <<= 100.0 * sz.cy / psz.cy;
|
|
d.keepratio = obj.IsKeepRatio();
|
|
d.width <<= d.height <<= d.widthp <<= d.heightp <<= d.Breaker(IDYES);
|
|
d.ydelta.WithSgn().Set(unit, obj.GetYDelta());
|
|
d.keepratio <<= d.Breaker(IDNO);
|
|
for(;;) {
|
|
switch(d.Run()) {
|
|
case IDCANCEL:
|
|
return;
|
|
case IDYES:
|
|
if(d.width.HasFocus() && !IsNull(d.width)) {
|
|
d.widthp <<= 100 * (double)~d.width / psz.cx;
|
|
if(d.keepratio) {
|
|
d.height <<= psz.cy * (double)~d.width / psz.cx;
|
|
d.heightp <<= ~d.widthp;
|
|
}
|
|
}
|
|
if(d.height.HasFocus() && !IsNull(d.height)) {
|
|
d.heightp <<= 100 * (double)~d.height / psz.cy;
|
|
if(d.keepratio) {
|
|
d.width <<= psz.cx * (double)~d.height / psz.cy;
|
|
d.widthp <<= ~d.heightp;
|
|
}
|
|
}
|
|
if(d.widthp.HasFocus() && !IsNull(d.widthp)) {
|
|
d.width <<= psz.cx * (double)~d.widthp / 100;
|
|
if(d.keepratio) {
|
|
d.height <<= psz.cy * (double)~d.width / psz.cx;
|
|
d.heightp <<= ~d.widthp;
|
|
}
|
|
}
|
|
if(d.heightp.HasFocus() && !IsNull(d.heightp)) {
|
|
d.height <<= psz.cy * (double)~d.heightp / 100;
|
|
if(d.keepratio) {
|
|
d.width <<= psz.cx * (double)~d.height / psz.cy;
|
|
d.widthp <<= ~d.heightp;
|
|
}
|
|
}
|
|
break;
|
|
case IDNO:
|
|
if(d.keepratio && !IsNull(d.width)) {
|
|
d.widthp <<= 100 * (double)~d.width / psz.cx;
|
|
if(d.keepratio) {
|
|
d.height <<= psz.cy * (double)~d.width / psz.cx;
|
|
d.heightp <<= ~d.widthp;
|
|
}
|
|
}
|
|
break;
|
|
case IDOK:
|
|
if(!IsNull(d.width) && (int)~d.width > 0)
|
|
sz.cx = ~d.width;
|
|
if(!IsNull(d.height) && (int)~d.height > 0)
|
|
sz.cy = ~d.height;
|
|
obj.SetSize(sz);
|
|
if(!IsNull(d.ydelta))
|
|
obj.SetYDelta(~d.ydelta);
|
|
obj.KeepRatio(d.keepratio);
|
|
ReplaceObject(obj);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|