mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-21 06:45:39 -06:00
Updating uppdev
git-svn-id: svn://ultimatepp.org/upp/trunk@527 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
4b999ee468
commit
893a7924da
49 changed files with 12859 additions and 65 deletions
|
|
@ -56,6 +56,7 @@ AddressBook::AddressBook()
|
|||
SetupSearch();
|
||||
fs.AllFilesType();
|
||||
menu.Set(THISBACK(MainMenu));
|
||||
|
||||
}
|
||||
|
||||
void AddressBook::FileMenu(Bar& bar)
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ struct App : public TopWindow {
|
|||
|
||||
w.DrawImage(20, 500, a);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
GUI_APP_MAIN
|
||||
|
|
|
|||
|
|
@ -9,8 +9,12 @@ thread__ int *alfa[10] = { &x, &x };
|
|||
CONSOLE_APP_MAIN
|
||||
{
|
||||
Any alpha;
|
||||
|
||||
alpha.Create<int>();
|
||||
|
||||
One<String> x;
|
||||
x.
|
||||
|
||||
if(alpha.Is<int>())
|
||||
RLOG("int");
|
||||
if(alpha.Is<int>())
|
||||
|
|
|
|||
590
uppdev/CoreTopics/src.tpp/TestTest$en-us.tpp
Normal file
590
uppdev/CoreTopics/src.tpp/TestTest$en-us.tpp
Normal file
|
|
@ -0,0 +1,590 @@
|
|||
topic "";
|
||||
[ $$0,0#00000000000000000000000000000000:Default]
|
||||
[H6;0 $$1,0#05600065144404261032431302351956:begin]
|
||||
[i448;a25;kKO9;2 $$2,0#37138531426314131252341829483370:codeitem]
|
||||
[l288;2 $$3,0#27521748481378242620020725143825:desc]
|
||||
[0 $$4,0#96390100711032703541132217272105:end]
|
||||
[{_}%EN-US
|
||||
[s1;%- &]
|
||||
[s2;:pteback`(OBJECT`*`,void`(`*`)`(P1 p1`,P2 p2`)`):%- Callback_[* Proxy](Callback[@(0.0.255) `&
|
||||
]_[*@3 cb])&]
|
||||
[s3; [%-*@3 cb].&]
|
||||
[s4; &]
|
||||
[s1; &]
|
||||
[s2;:pteback`(OBJECT`*`,void`(`*`)`(P1 p1`,P2 p2`)`):%- Callback_[* callback](Callback_
|
||||
[*@3 cb1], Callback_[*@3 cb2])&]
|
||||
[s3; [%-*@3 cb1] [%-*@3 cb2].&]
|
||||
[s4; &]
|
||||
[s1; &]
|
||||
[s2;:pteback`(OBJECT`*`,void`(`*`)`(P1 p1`,P2 p2`)`):%- Callback[@(0.0.255) `&]_[* operat
|
||||
or<<](Callback[@(0.0.255) `&]_[*@3 a], Callback_[*@3 b])&]
|
||||
[s3; [%-*@3 a] [%-*@3 b].&]
|
||||
[s4; &]
|
||||
[s1; &]
|
||||
[s2;:pteback`(OBJECT`*`,void`(`*`)`(P1 p1`,P2 p2`)`):%- [@(0.0.255) template]_<[@(0.0.255) c
|
||||
lass]_[*@4 OBJECT], [@(0.0.255) class]_[*@4 METHOD], [@(0.0.255) class]_[*@4 P1][@(0.0.255) >
|
||||
]_Callback1[@(0.0.255) <][*@4 P1][@(0.0.255) >]_[* pteback]([*@4 OBJECT]_`*[*@3 object],
|
||||
[@(0.0.255) void]_(METHOD`::[@(0.0.255) `*][*@3 method])([*@4 P1]_p1))&]
|
||||
[s3; [%-*@3 object] [%-*@3 method].&]
|
||||
[s4; &]
|
||||
[s1; &]
|
||||
[s2;:pteback`(OBJECT`*`,void`(`*`)`(P1 p1`,P2 p2`)`):%- [@(0.0.255) template]_<[@(0.0.255) c
|
||||
lass]_[*@4 OBJECT], [@(0.0.255) class]_[*@4 METHOD], [@(0.0.255) class]_[*@4 P1][@(0.0.255) >
|
||||
]_Callback1[@(0.0.255) <][*@4 P1][@(0.0.255) >]_[* callback]([*@4 OBJECT]_`*[*@3 object],
|
||||
[@(0.0.255) void]_(METHOD`::[@(0.0.255) `*][*@3 method])([*@4 P1]_p1))&]
|
||||
[s3; [%-*@3 object] [%-*@3 method].&]
|
||||
[s4; &]
|
||||
[s1; &]
|
||||
[s2;:pteback`(OBJECT`*`,void`(`*`)`(P1 p1`,P2 p2`)`):%- [@(0.0.255) template]_<[@(0.0.255) c
|
||||
lass]_[*@4 OBJECT], [@(0.0.255) class]_[*@4 METHOD], [@(0.0.255) class]_[*@4 P1][@(0.0.255) >
|
||||
]_Callback1[@(0.0.255) <][*@4 P1][@(0.0.255) >]_[* callback]([@(0.0.255) const]_[*@4 OBJECT]_
|
||||
`*[*@3 object], [@(0.0.255) void]_(METHOD`::[@(0.0.255) `*][*@3 method])([*@4 P1]_p1)_[@(0.0.255) c
|
||||
onst])&]
|
||||
[s3; [%-*@3 object] [%-*@3 method].&]
|
||||
[s4; &]
|
||||
[s1; &]
|
||||
[s2;:pteback`(OBJECT`*`,void`(`*`)`(P1 p1`,P2 p2`)`):%- [@(0.0.255) template]_<[@(0.0.255) c
|
||||
lass]_[*@4 P1][@(0.0.255) >]_Callback1[@(0.0.255) <][*@4 P1][@(0.0.255) >]_[* callback]([@(0.0.255) v
|
||||
oid]_(`*[*@3 fn])([*@4 P1]_p1))&]
|
||||
[s3; [%-*@3 fn].&]
|
||||
[s4; &]
|
||||
[s1; &]
|
||||
[s2;:pteback`(OBJECT`*`,void`(`*`)`(P1 p1`,P2 p2`)`):%- [@(0.0.255) template]_<[@(0.0.255) c
|
||||
lass]_[*@4 P1][@(0.0.255) >]_Callback1[@(0.0.255) <][*@4 P1][@(0.0.255) >]_[* Proxy](Callback
|
||||
1[@(0.0.255) <][*@4 P1][@(0.0.255) >`&]_[*@3 cb])&]
|
||||
[s3; [%-*@3 cb].&]
|
||||
[s4; &]
|
||||
[s1; &]
|
||||
[s2;:pteback`(OBJECT`*`,void`(`*`)`(P1 p1`,P2 p2`)`):%- [@(0.0.255) template]_<[@(0.0.255) c
|
||||
lass]_[*@4 P1][@(0.0.255) >]_Callback1[@(0.0.255) <][*@4 P1][@(0.0.255) >]_[* callback](Callb
|
||||
ack1[@(0.0.255) <][*@4 P1][@(0.0.255) >]_[*@3 cb1], Callback1[@(0.0.255) <][*@4 P1][@(0.0.255) >
|
||||
]_[*@3 cb2])&]
|
||||
[s3; [%-*@3 cb1] [%-*@3 cb2].&]
|
||||
[s4; &]
|
||||
[s1; &]
|
||||
[s2;:pteback`(OBJECT`*`,void`(`*`)`(P1 p1`,P2 p2`)`):%- [@(0.0.255) template]_<[@(0.0.255) c
|
||||
lass]_[*@4 P1][@(0.0.255) >]_Callback1[@(0.0.255) <][*@4 P1][@(0.0.255) >`&]_[* operator<<](C
|
||||
allback1[@(0.0.255) <][*@4 P1][@(0.0.255) >`&]_[*@3 a], Callback1[@(0.0.255) <][*@4 P1][@(0.0.255) >
|
||||
]_[*@3 b])&]
|
||||
[s3; [%-*@3 a] [%-*@3 b].&]
|
||||
[s4; &]
|
||||
[s1; &]
|
||||
[s2;:pteback`(OBJECT`*`,void`(`*`)`(P1 p1`,P2 p2`)`):%- [@(0.0.255) template]_<[@(0.0.255) c
|
||||
lass]_[*@4 OBJECT], [@(0.0.255) class]_[*@4 METHOD], [@(0.0.255) class]_[*@4 P1],
|
||||
[@(0.0.255) class]_[*@4 P2][@(0.0.255) >]_Callback2[@(0.0.255) <][*@4 P1],
|
||||
[*@4 P2][@(0.0.255) >]_[* pteback]([*@4 OBJECT]_`*[*@3 object], [@(0.0.255) void]_(METHOD`::[@(0.0.255) `*
|
||||
][*@3 method])([*@4 P1]_p1, [*@4 P2]_p2))&]
|
||||
[s3; [%-*@3 object] [%-*@3 method].&]
|
||||
[s4; &]
|
||||
[s0;%- &]
|
||||
[ {{10000 [s0;%- AIndex]
|
||||
:: [s0;%- AIndex`::ConstIterator]
|
||||
:: [s0;%- AIndex`::ValueType]
|
||||
:: [s0;%- AMap]
|
||||
:: [s0;%- AMap`::ConstIterator]
|
||||
:: [s0;%- AMap`::Iterator]
|
||||
:: [s0;%- AMap`::KeyConstIterator]
|
||||
:: [s0;%- AMap`::KeyType]
|
||||
:: [s0;%- AMap`::ValueType]
|
||||
:: [s0;%- AString]
|
||||
:: [s0;%- AString`::String]
|
||||
:: [s0;%- AString`::bchar]
|
||||
:: [s0;%- AString`::buffer]
|
||||
:: [s0;%- AString`::tchar]
|
||||
:: [s0;%- AbortExc]
|
||||
:: [s0;%- AddOps]
|
||||
:: [s0;%- Any]
|
||||
:: [s0;%- Any`::BaseData]
|
||||
:: [s0;%- Any`::Data]
|
||||
:: [s0;%- Array]
|
||||
:: [s0;%- Array`::ConstIterator]
|
||||
:: [s0;%- Array`::ConstIterator`::Array`::ConstIterator]
|
||||
:: [s0;%- Array`::ConstIterator`::NP]
|
||||
:: [s0;%- Array`::Iterator]
|
||||
:: [s0;%- Array`::Iterator`::B]
|
||||
:: [s0;%- Array`::Iterator`::NP]
|
||||
:: [s0;%- Array`::ValueType]
|
||||
:: [s0;%- ArrayIndex]
|
||||
:: [s0;%- ArrayIndex`::B]
|
||||
:: [s0;%- ArrayIndex`::ConstIterator]
|
||||
:: [s0;%- ArrayMap]
|
||||
:: [s0;%- ArrayMap`::B]
|
||||
:: [s0;%- ArrayMap`::ConstIterator]
|
||||
:: [s0;%- ArrayMap`::Iterator]
|
||||
:: [s0;%- AssignValueTypeNo]
|
||||
:: [s0;%- Atomic]
|
||||
:: [s0;%- BiArray]
|
||||
:: [s0;%- BiArray`::ConstIterator]
|
||||
:: [s0;%- BiArray`::Iterator]
|
||||
:: [s0;%- BiArray`::ValueType]
|
||||
:: [s0;%- BiVector]
|
||||
:: [s0;%- BiVector`::ConstIterator]
|
||||
:: [s0;%- BiVector`::Iterator]
|
||||
:: [s0;%- BiVector`::ValueType]
|
||||
:: [s0;%- BitAndPtr]
|
||||
:: [s0;%- Bits]
|
||||
:: [s0;%- BlockStream]
|
||||
:: [s0;%- Buffer]
|
||||
:: [s0;%- CParser]
|
||||
:: [s0;%- CParser`::Error]
|
||||
:: [s0;%- CParser`::Pos]
|
||||
:: [s0;%- Callback]
|
||||
:: [s0;%- Callback1]
|
||||
:: [s0;%- Callback1`::CLASSNAME]
|
||||
:: [s0;%- Callback1Action]
|
||||
:: [s0;%- Callback1FnAction]
|
||||
:: [s0;%- Callback1ForkAction]
|
||||
:: [s0;%- Callback1MethodAction]
|
||||
:: [s0;%- Callback1MethodActionPte]
|
||||
:: [s0;%- Callback2]
|
||||
:: [s0;%- Callback2`::CLASSNAME]
|
||||
:: [s0;%- Callback2Action]
|
||||
:: [s0;%- Callback2FnAction]
|
||||
:: [s0;%- Callback2ForkAction]
|
||||
:: [s0;%- Callback2MethodAction]
|
||||
:: [s0;%- Callback2MethodActionPte]
|
||||
:: [s0;%- Callback3]
|
||||
:: [s0;%- Callback3`::CLASSNAME]
|
||||
:: [s0;%- Callback3Action]
|
||||
:: [s0;%- Callback3FnAction]
|
||||
:: [s0;%- Callback3ForkAction]
|
||||
:: [s0;%- Callback3MethodAction]
|
||||
:: [s0;%- Callback3MethodActionPte]
|
||||
:: [s0;%- Callback4]
|
||||
:: [s0;%- Callback4`::CLASSNAME]
|
||||
:: [s0;%- Callback4Action]
|
||||
:: [s0;%- Callback4FnAction]
|
||||
:: [s0;%- Callback4ForkAction]
|
||||
:: [s0;%- Callback4MethodAction]
|
||||
:: [s0;%- Callback4MethodActionPte]
|
||||
:: [s0;%- Callback`::CLASSNAME]
|
||||
:: [s0;%- CallbackAction]
|
||||
:: [s0;%- CallbackActionCallArg]
|
||||
:: [s0;%- CallbackActionCallArg1]
|
||||
:: [s0;%- CallbackActionCallArg2]
|
||||
:: [s0;%- CallbackActionCallArg3]
|
||||
:: [s0;%- CallbackActionCallArg4]
|
||||
:: [s0;%- CallbackArgTarget]
|
||||
:: [s0;%- CallbackArgTarget`::CLASSNAME]
|
||||
:: [s0;%- CallbackFnAction]
|
||||
:: [s0;%- CallbackForkAction]
|
||||
:: [s0;%- CallbackMethodAction]
|
||||
:: [s0;%- CallbackMethodActionArg]
|
||||
:: [s0;%- CallbackMethodActionArg1]
|
||||
:: [s0;%- CallbackMethodActionArg1Pte]
|
||||
:: [s0;%- CallbackMethodActionArg2]
|
||||
:: [s0;%- CallbackMethodActionArg2Pte]
|
||||
:: [s0;%- CallbackMethodActionArg3]
|
||||
:: [s0;%- CallbackMethodActionArg3Pte]
|
||||
:: [s0;%- CallbackMethodActionArg4]
|
||||
:: [s0;%- CallbackMethodActionArg4Pte]
|
||||
:: [s0;%- CallbackMethodActionArgPte]
|
||||
:: [s0;%- CallbackMethodActionPte]
|
||||
:: [s0;%- Callexit]
|
||||
:: [s0;%- Callinit]
|
||||
:: [s0;%- CerrStream]
|
||||
:: [s0;%- CharFilter]
|
||||
:: [s0;%- CharFilterTextTest]
|
||||
:: [s0;%- CharS]
|
||||
:: [s0;%- CharSetData]
|
||||
:: [s0;%- CoWork]
|
||||
:: [s0;%- CoWork`::Lock]
|
||||
:: [s0;%- CoWork`::MJob]
|
||||
:: [s0;%- CoWork`::Pool]
|
||||
:: [s0;%- Color]
|
||||
:: [s0;%- ColorF]
|
||||
:: [s0;%- CombineCompare]
|
||||
:: [s0;%- CombineHash]
|
||||
:: [s0;%- Comparable]
|
||||
:: [s0;%- CompareRelOps]
|
||||
:: [s0;%- CompareStream]
|
||||
:: [s0;%- ConstIIterator]
|
||||
:: [s0;%- ConstIIterator`::NP]
|
||||
:: [s0;%- ConstIIterator`::T]
|
||||
:: [s0;%- Convert]
|
||||
:: [s0;%- ConvertDate]
|
||||
:: [s0;%- ConvertDouble]
|
||||
:: [s0;%- ConvertInt]
|
||||
:: [s0;%- ConvertInt64]
|
||||
:: [s0;%- ConvertString]
|
||||
:: [s0;%- ConvertTime]
|
||||
:: [s0;%- CoutStream]
|
||||
:: [s0;%- Crc32]
|
||||
:: [s0;%- CriticalSection]
|
||||
:: [s0;%- DLLHANDLE]
|
||||
:: [s0;%- DLLTYPE]
|
||||
:: [s0;%- Data`_S`_]
|
||||
:: [s0;%- Date]
|
||||
:: [s0;%- DbgBlkHeader]
|
||||
:: [s0;%- DebugLogBlock]
|
||||
:: [s0;%- DeepCopyOption]
|
||||
:: [s0;%- DefaultWildcardCompare]
|
||||
:: [s0;%- EmptyClass]
|
||||
:: [s0;%- Event]
|
||||
:: [s0;%- Exc]
|
||||
:: [s0;%- FieldRelationCls]
|
||||
:: [s0;%- FileAppend]
|
||||
:: [s0;%- FileIn]
|
||||
:: [s0;%- FileMapping]
|
||||
:: [s0;%- FileMapping`::stat]
|
||||
:: [s0;%- FileOut]
|
||||
:: [s0;%- FileStream]
|
||||
:: [s0;%- FileSystemInfo]
|
||||
:: [s0;%- FileSystemInfo`::FileInfo]
|
||||
:: [s0;%- FileTime]
|
||||
:: [s0;%- FindFile]
|
||||
:: [s0;%- FindFile`::stat]
|
||||
:: [s0;%- FnValueOrder]
|
||||
:: [s0;%- FormId]
|
||||
:: [s0;%- FormatConvert]
|
||||
:: [s0;%- Formatter]
|
||||
:: [s0;%- Formatting]
|
||||
:: [s0;%- Gate]
|
||||
:: [s0;%- Gate1]
|
||||
:: [s0;%- Gate1`::CLASSNAME]
|
||||
:: [s0;%- Gate1Action]
|
||||
:: [s0;%- Gate1FnAction]
|
||||
:: [s0;%- Gate1ForkAction]
|
||||
:: [s0;%- Gate1MethodAction]
|
||||
:: [s0;%- Gate1MethodActionPte]
|
||||
:: [s0;%- Gate2]
|
||||
:: [s0;%- Gate2`::CLASSNAME]
|
||||
:: [s0;%- Gate2Action]
|
||||
:: [s0;%- Gate2FnAction]
|
||||
:: [s0;%- Gate2ForkAction]
|
||||
:: [s0;%- Gate2MethodAction]
|
||||
:: [s0;%- Gate2MethodActionPte]
|
||||
:: [s0;%- Gate3]
|
||||
:: [s0;%- Gate3`::CLASSNAME]
|
||||
:: [s0;%- Gate3Action]
|
||||
:: [s0;%- Gate3FnAction]
|
||||
:: [s0;%- Gate3ForkAction]
|
||||
:: [s0;%- Gate3MethodAction]
|
||||
:: [s0;%- Gate3MethodActionPte]
|
||||
:: [s0;%- Gate4]
|
||||
:: [s0;%- Gate4`::CLASSNAME]
|
||||
:: [s0;%- Gate4Action]
|
||||
:: [s0;%- Gate4FnAction]
|
||||
:: [s0;%- Gate4ForkAction]
|
||||
:: [s0;%- Gate4MethodAction]
|
||||
:: [s0;%- Gate4MethodActionPte]
|
||||
:: [s0;%- Gate`::CLASSNAME]
|
||||
:: [s0;%- GateAction]
|
||||
:: [s0;%- GateFnAction]
|
||||
:: [s0;%- GateForkAction]
|
||||
:: [s0;%- GateMethodAction]
|
||||
:: [s0;%- GateMethodActionPte]
|
||||
:: [s0;%- H`_l`_]
|
||||
:: [s0;%- HashBase]
|
||||
:: [s0;%- HashBase`::Link]
|
||||
:: [s0;%- Heap]
|
||||
:: [s0;%- Heap`::BigHdr]
|
||||
:: [s0;%- Heap`::DLink]
|
||||
:: [s0;%- Heap`::FreeLink]
|
||||
:: [s0;%- Heap`::Header]
|
||||
:: [s0;%- Heap`::Page]
|
||||
:: [s0;%- HitCountInspector]
|
||||
:: [s0;%- IIterator]
|
||||
:: [s0;%- IIterator`::NP]
|
||||
:: [s0;%- IIterator`::T]
|
||||
:: [s0;%- Id]
|
||||
:: [s0;%- IdConst]
|
||||
:: [s0;%- IdList]
|
||||
:: [s0;%- Index]
|
||||
:: [s0;%- Index`::B]
|
||||
:: [s0;%- Index`::ConstIterator]
|
||||
:: [s0;%- IndexSort2Iterator]
|
||||
:: [s0;%- IndexSort2Iterator`::Iter]
|
||||
:: [s0;%- IndexSort3Iterator]
|
||||
:: [s0;%- IndexSort3Iterator`::Iter]
|
||||
:: [s0;%- IndexSortIterator]
|
||||
:: [s0;%- IndexSortIterator`::Iter]
|
||||
:: [s0;%- JoinConvert]
|
||||
:: [s0;%- JoinConvert`::Item]
|
||||
:: [s0;%- LCIDMap]
|
||||
:: [s0;%- LCTYPE]
|
||||
:: [s0;%- LRUCache]
|
||||
:: [s0;%- LRUCache`::Item]
|
||||
:: [s0;%- LRUCache`::Maker]
|
||||
:: [s0;%- LangConvertClass]
|
||||
:: [s0;%- LangModuleRecord]
|
||||
:: [s0;%- LangTextRecord]
|
||||
:: [s0;%- LanguageInfo]
|
||||
:: [s0;%- LanguageInfo`::WildcardCompare]
|
||||
:: [s0;%- LanguageInfoCS]
|
||||
:: [s0;%- LanguageInfoEN]
|
||||
:: [s0;%- LanguageInfoES]
|
||||
:: [s0;%- LanguageInfoFR]
|
||||
:: [s0;%- LanguageInfoGE]
|
||||
:: [s0;%- LanguageInfoMap]
|
||||
:: [s0;%- Link]
|
||||
:: [s0;%- LinkOwner]
|
||||
:: [s0;%- LngEntry`_`_]
|
||||
:: [s0;%- LngModule]
|
||||
:: [s0;%- LngRec]
|
||||
:: [s0;%- LoadingError]
|
||||
:: [s0;%- LogStream]
|
||||
:: [s0;%- MapConvert]
|
||||
:: [s0;%- MemReadStream]
|
||||
:: [s0;%- MemStream]
|
||||
:: [s0;%- MemoryIgnoreLeaksBlock]
|
||||
:: [s0;%- MemoryProfile]
|
||||
:: [s0;%- MethodRelationCls]
|
||||
:: [s0;%- Mitor]
|
||||
:: [s0;%- Moveable]
|
||||
:: [s0;%- MoveableAndDeepCopyOption]
|
||||
:: [s0;%- MtInspector]
|
||||
:: [s0;%- Mutex]
|
||||
:: [s0;%- Mutex`::Lock]
|
||||
:: [s0;%- NetNode]
|
||||
:: [s0;%- NilStreamClass]
|
||||
:: [s0;%- NoConvertClass]
|
||||
:: [s0;%- NoCopy]
|
||||
:: [s0;%- Nuller]
|
||||
:: [s0;%- One]
|
||||
:: [s0;%- ParamHelper`_`_]
|
||||
:: [s0;%- PeFile]
|
||||
:: [s0;%- Point]
|
||||
:: [s0;%- Point16]
|
||||
:: [s0;%- Point64]
|
||||
:: [s0;%- Point`_]
|
||||
:: [s0;%- Point`_`::Sz]
|
||||
:: [s0;%- Pointf]
|
||||
:: [s0;%- PolyDeepCopyNew]
|
||||
:: [s0;%- PostfixOps]
|
||||
:: [s0;%- Pte]
|
||||
:: [s0;%- PteBase]
|
||||
:: [s0;%- PteBase`::Prec]
|
||||
:: [s0;%- Ptr]
|
||||
:: [s0;%- PtrBase]
|
||||
:: [s0;%- PtrHash]
|
||||
:: [s0;%- RGBA]
|
||||
:: [s0;%- RWMutex]
|
||||
:: [s0;%- RWMutex`::ReadLock]
|
||||
:: [s0;%- RWMutex`::WriteLock]
|
||||
:: [s0;%- RawPickValue]
|
||||
:: [s0;%- RawPickValue`::PickRep]
|
||||
:: [s0;%- RawPickValueRep]
|
||||
:: [s0;%- RawRef]
|
||||
:: [s0;%- RawValue]
|
||||
:: [s0;%- RawValue`::Rep]
|
||||
:: [s0;%- RawValueCreate]
|
||||
:: [s0;%- RawValueCreate`::Rep]
|
||||
:: [s0;%- RawValueCreateRep]
|
||||
:: [s0;%- RawValueRep]
|
||||
:: [s0;%- Rect]
|
||||
:: [s0;%- Rect16]
|
||||
:: [s0;%- Rect64]
|
||||
:: [s0;%- Rect`_]
|
||||
:: [s0;%- Rect`_`::Pt]
|
||||
:: [s0;%- Rect`_`::Sz]
|
||||
:: [s0;%- Rectf]
|
||||
:: [s0;%- Ref]
|
||||
:: [s0;%- Ref`::ValueRef]
|
||||
:: [s0;%- RefManager]
|
||||
:: [s0;%- RelOps]
|
||||
:: [s0;%- RichRef]
|
||||
:: [s0;%- RichValue]
|
||||
:: [s0;%- RichValue`::Rep]
|
||||
:: [s0;%- RichValueRep]
|
||||
:: [s0;%- Segtor]
|
||||
:: [s0;%- Segtor`::Block]
|
||||
:: [s0;%- Segtor`::ConstIterator]
|
||||
:: [s0;%- Segtor`::Iterator]
|
||||
:: [s0;%- Segtor`::ValueType]
|
||||
:: [s0;%- SegtorMap]
|
||||
:: [s0;%- SegtorMap`::B]
|
||||
:: [s0;%- SegtorMap`::ConstIterator]
|
||||
:: [s0;%- SegtorMap`::Iterator]
|
||||
:: [s0;%- Semaphore]
|
||||
:: [s0;%- Size]
|
||||
:: [s0;%- Size16]
|
||||
:: [s0;%- Size64]
|
||||
:: [s0;%- SizeStream]
|
||||
:: [s0;%- Size`_]
|
||||
:: [s0;%- Sizef]
|
||||
:: [s0;%- SortOrderIterator]
|
||||
:: [s0;%- SortOrderIterator`::Iter]
|
||||
:: [s0;%- StableSortItem]
|
||||
:: [s0;%- StableSortIterator]
|
||||
:: [s0;%- StableSortIterator`::Iter]
|
||||
:: [s0;%- StableSortLessCmp`_]
|
||||
:: [s0;%- StableSortLess`_]
|
||||
:: [s0;%- StableSortOrderIterator]
|
||||
:: [s0;%- StableSortOrderIterator`::Iter]
|
||||
:: [s0;%- StaticCriticalSection]
|
||||
:: [s0;%- StaticMutex]
|
||||
:: [s0;%- StaticRWMutex]
|
||||
:: [s0;%- StaticSemaphore]
|
||||
:: [s0;%- StdCmp]
|
||||
:: [s0;%- StdEqual]
|
||||
:: [s0;%- StdGreater]
|
||||
:: [s0;%- StdHash]
|
||||
:: [s0;%- StdLess]
|
||||
:: [s0;%- StdValueOrder]
|
||||
:: [s0;%- Stream]
|
||||
:: [s0;%- StreamError]
|
||||
:: [s0;%- String]
|
||||
:: [s0;%- String0]
|
||||
:: [s0;%- String0`::Buffer]
|
||||
:: [s0;%- String0`::Rc]
|
||||
:: [s0;%- String0`::String]
|
||||
:: [s0;%- String0`::bchar]
|
||||
:: [s0;%- String0`::tchar]
|
||||
:: [s0;%- String`::operatorstd]
|
||||
:: [s0;%- StringBuffer]
|
||||
:: [s0;%- StringBuffer`::Rc]
|
||||
:: [s0;%- StringC]
|
||||
:: [s0;%- StringICompare`_`_]
|
||||
:: [s0;%- StringMap]
|
||||
:: [s0;%- StringStream]
|
||||
:: [s0;%- SyncObject]
|
||||
:: [s0;%- TEC]
|
||||
:: [s0;%- TextSettings]
|
||||
:: [s0;%- TextTest]
|
||||
:: [s0;%- Thread]
|
||||
:: [s0;%- Time]
|
||||
:: [s0;%- TimeStop]
|
||||
:: [s0;%- TimingInspector]
|
||||
:: [s0;%- TimingInspector`::Routine]
|
||||
:: [s0;%- Topic]
|
||||
:: [s0;%- TopicData`_`_]
|
||||
:: [s0;%- TopicLink]
|
||||
:: [s0;%- Uuid]
|
||||
:: [s0;%- UuidValueGenClass]
|
||||
:: [s0;%- Value]
|
||||
:: [s0;%- Value`::Void]
|
||||
:: [s0;%- ValueArray]
|
||||
:: [s0;%- ValueArray`::Data]
|
||||
:: [s0;%- ValueArray`::NullData]
|
||||
:: [s0;%- ValueErrorCls]
|
||||
:: [s0;%- ValueGen]
|
||||
:: [s0;%- ValueMap]
|
||||
:: [s0;%- ValueMap`::Data]
|
||||
:: [s0;%- ValueMap`::NullData]
|
||||
:: [s0;%- ValueOrder]
|
||||
:: [s0;%- Vector]
|
||||
:: [s0;%- Vector`::ConstIterator]
|
||||
:: [s0;%- Vector`::Iterator]
|
||||
:: [s0;%- Vector`::ValueType]
|
||||
:: [s0;%- VectorMap]
|
||||
:: [s0;%- VectorMap`::B]
|
||||
:: [s0;%- VectorMap`::ConstIterator]
|
||||
:: [s0;%- VectorMap`::Iterator]
|
||||
:: [s0;%- Vector`_]
|
||||
:: [s0;%- WString]
|
||||
:: [s0;%- WString0]
|
||||
:: [s0;%- WString0`::Buffer]
|
||||
:: [s0;%- WString0`::String]
|
||||
:: [s0;%- WString0`::bchar]
|
||||
:: [s0;%- WString0`::tchar]
|
||||
:: [s0;%- WString`::operatorstd]
|
||||
:: [s0;%- WStringBuffer]
|
||||
:: [s0;%- WStringICompare`_`_]
|
||||
:: [s0;%- WildcardCompareCS]
|
||||
:: [s0;%- WithDeepCopy]
|
||||
:: [s0;%- XmlError]
|
||||
:: [s0;%- XmlIO]
|
||||
:: [s0;%- XmlNode]
|
||||
:: [s0;%- XmlParser]
|
||||
:: [s0;%- XmlParser`::Nesting]
|
||||
:: [s0;%- XmlTag]
|
||||
:: [s0;%- ZoneAlloc]
|
||||
:: [s0;%- byte]
|
||||
:: [s0;%- chrTextTest]
|
||||
:: [s0;%- dword]
|
||||
:: [s0;%- int16]
|
||||
:: [s0;%- int32]
|
||||
:: [s0;%- int64]
|
||||
:: [s0;%- int8]
|
||||
:: [s0;%- operatorstd]
|
||||
:: [s0;%- qword]
|
||||
:: [s0;%- stat]
|
||||
:: [s0;%- uint16]
|
||||
:: [s0;%- uint32]
|
||||
:: [s0;%- uint64]
|
||||
:: [s0;%- uint8]
|
||||
:: [s0;%- wchar]
|
||||
:: [s0;%- word]}}&]
|
||||
[s1;%- &]
|
||||
[s2;:cmp`(const T`&`,const T`&`):%- [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 T][@(0.0.255) >
|
||||
]_[@(0.0.255) int]_[* cmp]([@(0.0.255) const]_[*@4 T][@(0.0.255) `&]_[*@3 a],
|
||||
[@(0.0.255) const]_[*@4 T][@(0.0.255) `&]_[*@3 b])&]
|
||||
[s3; [%-*@3 a] [%-*@3 b].&]
|
||||
[s4; &]
|
||||
[s1; &]
|
||||
[s2;:cmp`(const T`&`,const T`&`):%- [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 I][@(0.0.255) >
|
||||
]_[@(0.0.255) void]_[* Reverse]([*@4 I]_[*@3 start], [*@4 I]_[*@3 end])&]
|
||||
[s3; [%-*@3 start] [%-*@3 end].&]
|
||||
[s4; &]
|
||||
[s1; &]
|
||||
[s2;:cmp`(const T`&`,const T`&`):%- [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 C][@(0.0.255) >
|
||||
]_[@(0.0.255) void]_[* Reverse]([*@4 C][@(0.0.255) `&]_[*@3 container])&]
|
||||
[s3; [%-*@3 container].&]
|
||||
[s4; &]
|
||||
[s1; &]
|
||||
[s2;:cmp`(const T`&`,const T`&`):%- [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 T],
|
||||
[@(0.0.255) class]_[*@4 V][@(0.0.255) >]_[@(0.0.255) void]_[* Sum]([*@4 V][@(0.0.255) `&]_[*@3 su
|
||||
m], [*@4 T]_[*@3 ptr], [*@4 T]_[*@3 end])&]
|
||||
[s3; [%-*@3 sum] [%-*@3 ptr] [%-*@3 end].&]
|
||||
[s4; &]
|
||||
[s1; &]
|
||||
[s2;:cmp`(const T`&`,const T`&`):%- [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 T][@(0.0.255) >
|
||||
]_[@(0.0.255) typename]_T`::ValueType_[* Sum]([@(0.0.255) const]_[*@4 T][@(0.0.255) `&]_[*@3 c
|
||||
], [@(0.0.255) const]_[@(0.0.255) typename]_T`::ValueType[@(0.0.255) `&]_[*@3 init]_`=_[@(0.0.255) t
|
||||
ypename]_T`::ValueType())&]
|
||||
[s3; [%-*@3 c] [%-*@3 init].&]
|
||||
[s4; &]
|
||||
[s1; &]
|
||||
[s2;:cmp`(const T`&`,const T`&`):%- [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 T][@(0.0.255) >
|
||||
]_[@(0.0.255) typename]_T`::ValueType_[* Sum0]([@(0.0.255) const]_[*@4 T][@(0.0.255) `&]_[*@3 c
|
||||
])&]
|
||||
[s3; [%-*@3 c].&]
|
||||
[s4; &]
|
||||
[s1; &]
|
||||
[s2;:cmp`(const T`&`,const T`&`):%- [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 T][@(0.0.255) >
|
||||
]_[*@4 T]_[* MinElement]([*@4 T]_[*@3 ptr], [*@4 T]_[*@3 end])&]
|
||||
[s3; [%-*@3 ptr] [%-*@3 end].&]
|
||||
[s4; &]
|
||||
[s1; &]
|
||||
[s2;:cmp`(const T`&`,const T`&`):%- [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 C][@(0.0.255) >
|
||||
]_[@(0.0.255) int]_[* MinIndex]([@(0.0.255) const]_[*@4 C][@(0.0.255) `&]_[*@3 c])&]
|
||||
[s3; [%-*@3 c].&]
|
||||
[s4; &]
|
||||
[s1; &]
|
||||
[s2;:cmp`(const T`&`,const T`&`):%- [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 C][@(0.0.255) >
|
||||
]_[@(0.0.255) int]_[* MaxIndex]([@(0.0.255) const]_[*@4 C][@(0.0.255) `&]_[*@3 c])&]
|
||||
[s3; [%-*@3 c].&]
|
||||
[s4; &]
|
||||
[s1; &]
|
||||
[s2;:cmp`(const T`&`,const T`&`):%- [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 T][@(0.0.255) >
|
||||
]_[@(0.0.255) const]_[@(0.0.255) typename]_T`::ValueType[@(0.0.255) `&]_[* Min]([@(0.0.255) c
|
||||
onst]_[*@4 T][@(0.0.255) `&]_[*@3 c])&]
|
||||
[s3; [%-*@3 c].&]
|
||||
[s4; &]
|
||||
[s1; &]
|
||||
[s2;:Min`(const T`&`):%- [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 T][@(0.0.255) >]_[*@4 T
|
||||
]_[* MaxElement]([*@4 T]_[*@3 ptr], [*@4 T]_[*@3 end])&]
|
||||
[s3; [%-*@3 ptr] [%-*@3 end].&]
|
||||
[s4; &]
|
||||
[s1;%- &]
|
||||
[s2;:MaxIndex`(const C`&`):%- [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 T][@(0.0.255) >]_
|
||||
[*@4 T]_[* MinElement]([*@4 T]_[*@3 ptr], [*@4 T]_[*@3 end])&]
|
||||
[s3; [%-*@3 ptr] [%-*@3 end].&]
|
||||
[s4; &]
|
||||
[s1; &]
|
||||
[s2;:MinElement`(T`,T`):%- [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 C][@(0.0.255) >]_[@(0.0.255) i
|
||||
nt]_[* MinIndex]([@(0.0.255) const]_[*@4 C][@(0.0.255) `&]_[*@3 c])&]
|
||||
[s3; [%-*@3 c].&]
|
||||
[s4; &]
|
||||
[s1; &]
|
||||
[s2;:MaxIndex`(const C`&`):%- [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 C][@(0.0.255) >]_
|
||||
[@(0.0.255) int]_[* MaxIndex]([@(0.0.255) const]_[*@4 C][@(0.0.255) `&]_[*@3 c])&]
|
||||
[s3; [%-*@3 c].&]
|
||||
[s4; &]
|
||||
[s1;%- &]
|
||||
[s2;:Sum0`(const T`&`):%- [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 T][@(0.0.255) >]_[@(0.0.255) t
|
||||
ypename]_T`::ValueType_[* Sum0]([@(0.0.255) const]_[*@4 T][@(0.0.255) `&]_[*@3 c])&]
|
||||
[s3; [%-*@3 c].&]
|
||||
[s4; &]
|
||||
[s0; ]
|
||||
15
uppdev/CoreTopics/src.tpp/TestTest$en-us.tppi
Normal file
15
uppdev/CoreTopics/src.tpp/TestTest$en-us.tppi
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
TITLE("")
|
||||
COMPRESSED
|
||||
120,156,237,91,251,115,219,184,17,254,87,52,211,75,70,206,56,25,241,33,219,177,211,206,217,178,28,43,39,201,26,75,137,218,122,52,18,68,194,50,107,138,228,145,80,98,93,38,255,123,1,62,36,98,241,160,227,58,246,165,109,126,72,132,239,195,99,119,177,88,44,64,228,170,246,203,47,141,221,198,95,26,21,127,14,79,241,53,90,249,100,114,117,190,119,212,160,141,12,214,168,185,71,169,189,166,97,219,118,195,54,247,140,134,101,218,150,97,53,76,171,105,188,109,238,29,206,241,194,11,38,87,158,109,31,28,33,179,121,116,251,219,197,219,35,147,182,54,105,107,107,223,176,14,154,150,65,27,210,191,12,203,48,155,166,101,27,7,230,91,251,192,178,246,27,135,78,232,98,143,224,229,228,202,55,15,14,210,118,22,109,103,238,55,77,99,223,62,176,15,12,107,255,192,164,205,205,70,195,108,236,155,84,14,235,192,108,30,186,56,113,38,87,76,72,155,86,127,187,103,189,109,24,141,198,190,193,196,219,111,88,77,219,48,44,147,118,97,238,155,70,163,121,136,3,119,
|
||||
114,245,117,250,237,69,187,255,250,227,176,118,149,24,71,47,94,215,94,78,174,18,243,232,48,34,120,142,156,219,89,253,226,228,67,187,53,154,189,154,237,126,14,61,119,86,167,191,118,102,245,129,81,139,140,217,238,192,172,69,38,45,239,28,210,150,45,228,251,172,205,244,234,85,109,16,135,119,235,73,189,128,174,126,173,55,222,52,222,152,205,230,78,109,246,114,66,107,252,106,213,156,249,100,135,141,102,29,213,106,87,47,94,231,208,27,6,217,71,169,28,198,209,35,137,227,228,191,183,18,21,34,24,147,221,26,196,76,137,92,198,100,251,219,124,124,33,69,3,213,194,8,199,136,132,241,187,119,21,118,68,130,10,162,97,209,70,252,71,180,112,89,26,234,174,145,143,8,158,76,223,149,97,199,71,73,146,202,105,215,178,142,169,176,170,10,189,246,232,252,226,84,83,97,96,76,202,212,223,38,211,66,111,163,140,191,155,40,106,83,171,230,106,78,234,101,145,166,179,87,169,221,194,249,191,176,67,128,0,204,10,147,105,61,19,110,118,120,200,205,193,171,73,218,112,137,
|
||||
201,77,232,78,118,234,197,192,211,200,216,129,115,144,247,94,20,243,54,255,211,179,177,93,151,255,159,142,63,215,116,148,7,9,131,132,240,98,254,152,25,154,138,163,254,185,39,237,135,153,60,55,97,110,229,235,160,194,149,105,133,159,216,4,32,87,184,79,187,167,202,33,158,211,31,190,183,169,144,206,124,87,195,39,204,121,158,212,168,154,100,234,187,28,13,61,204,176,255,197,153,152,134,52,85,51,102,202,45,71,187,146,183,123,210,132,109,43,197,52,50,31,144,46,52,242,227,83,237,235,87,131,29,29,107,57,116,220,9,92,124,55,57,60,228,1,42,89,139,237,113,29,146,185,166,172,194,39,228,175,240,104,29,225,50,217,67,17,40,234,186,202,104,53,243,27,94,87,180,165,53,36,34,168,164,27,146,216,11,22,34,66,235,107,168,185,115,131,98,57,179,186,190,198,114,138,192,70,243,48,38,237,59,167,12,185,238,69,148,148,129,96,205,151,104,63,39,40,193,167,136,32,129,128,96,28,163,53,44,235,108,47,227,105,249,161,237,250,3,73,37,77,251,82,211,19,
|
||||
61,45,237,89,58,189,140,19,252,121,3,202,70,170,116,118,86,9,248,116,14,201,186,171,112,247,109,21,25,155,36,222,34,216,232,213,15,203,28,9,151,94,217,117,78,60,56,223,57,162,25,126,91,67,75,202,44,123,226,125,162,241,5,52,200,32,237,128,155,42,122,86,62,36,57,14,220,1,225,155,144,242,114,57,241,67,231,150,46,56,140,150,101,20,174,201,214,0,197,137,12,161,35,183,227,56,148,51,131,176,60,84,177,71,72,32,67,134,49,171,116,143,135,195,254,113,175,45,227,143,29,226,133,129,140,57,11,52,92,24,223,170,217,94,26,245,239,199,15,8,150,84,49,101,88,133,42,166,114,64,83,163,138,169,85,197,172,80,197,172,86,197,146,97,21,170,88,202,1,45,141,42,150,86,21,171,66,21,171,90,21,91,134,85,168,98,43,7,180,53,170,216,90,85,236,10,85,236,106,85,42,164,86,118,157,17,172,116,28,47,170,120,217,130,228,42,200,220,156,171,32,115,30,174,130,108,74,40,60,66,241,2,19,29,87,97,0,205,220,104,167,166,98,102,202,180,
|
||||
220,128,160,134,204,132,176,138,124,134,65,45,153,169,97,149,123,117,36,155,18,88,229,94,29,201,166,14,86,185,87,71,213,149,196,26,248,206,131,238,225,5,60,132,227,88,216,210,90,52,149,60,243,124,194,111,98,27,112,132,239,200,8,39,4,144,67,88,198,4,228,140,173,112,76,189,74,0,168,147,118,67,71,138,247,62,132,115,25,62,8,67,159,195,125,126,91,101,229,51,14,88,206,189,0,211,127,34,20,99,145,56,71,201,13,143,210,122,104,238,99,1,196,151,216,231,179,232,28,23,173,152,166,41,146,76,132,39,96,198,41,176,35,158,252,140,99,34,34,167,136,159,252,28,13,87,80,135,20,239,4,146,46,40,184,103,139,176,112,80,201,241,145,183,228,123,94,17,209,4,177,99,113,75,50,246,136,231,32,127,136,97,232,56,237,118,207,143,251,167,221,54,143,141,254,49,224,16,234,79,179,233,112,54,229,177,178,28,167,243,197,137,127,123,142,145,203,121,239,41,158,175,22,221,112,145,230,112,28,142,163,86,24,173,47,34,40,80,246,169,115,236,249,174,131,98,
|
||||
87,244,156,246,50,34,235,86,122,210,47,129,159,49,103,90,254,0,118,230,97,223,165,254,131,210,208,238,39,28,229,227,227,40,98,159,33,121,176,19,0,128,38,244,17,63,33,37,148,186,75,66,16,1,228,197,10,34,194,76,165,224,58,33,120,217,9,174,67,37,65,251,207,132,18,234,0,119,56,243,2,151,193,18,72,34,99,118,12,185,136,249,57,163,91,208,178,227,2,0,17,113,13,100,56,17,26,83,140,183,212,123,222,87,88,209,128,101,197,150,153,114,194,142,151,162,146,93,52,195,101,91,104,202,40,246,79,129,27,8,226,154,176,172,17,87,76,149,83,84,33,174,60,69,78,25,141,184,154,212,152,209,22,44,107,196,21,211,225,20,85,136,43,79,131,83,70,35,174,38,253,101,180,13,203,26,113,197,148,55,69,21,226,202,83,221,148,209,136,171,73,113,25,173,145,78,218,157,66,54,165,104,26,201,212,130,157,207,166,62,23,160,217,222,202,110,149,36,16,219,249,189,160,28,143,105,224,142,64,145,93,124,120,139,115,55,22,241,83,73,107,22,162,98,140,229,
|
||||
140,176,47,228,248,0,45,56,249,60,26,101,86,1,221,18,147,8,94,68,200,118,116,229,102,174,218,199,185,176,214,113,211,61,159,67,186,30,15,128,91,38,217,5,83,213,221,82,202,15,195,152,152,247,34,243,91,20,89,29,75,215,129,117,143,14,116,237,213,205,63,132,94,32,6,255,18,154,53,41,111,107,221,86,231,148,191,78,235,182,64,78,209,189,252,216,66,206,13,150,64,146,254,182,76,15,221,114,210,117,81,176,200,229,128,89,1,163,122,161,187,242,105,242,232,132,177,11,40,150,79,75,137,21,245,74,176,213,150,97,42,132,58,61,41,87,108,13,21,68,187,175,34,84,45,206,46,21,196,251,182,130,0,230,231,151,37,43,94,124,9,120,67,6,139,118,64,226,245,108,202,133,145,110,97,67,30,163,134,43,3,33,114,233,150,15,175,217,104,226,39,100,60,84,46,209,153,122,120,121,73,67,132,88,25,47,101,88,24,175,59,139,32,140,113,23,163,219,4,230,150,89,133,65,28,94,243,137,80,22,59,229,121,96,207,227,151,69,47,252,140,193,57,164,128,142,
|
||||
3,87,153,189,246,164,161,171,183,34,92,20,73,203,226,233,171,143,73,63,116,203,67,246,61,63,83,31,122,118,63,84,184,60,35,162,242,125,113,127,69,143,163,101,97,46,130,242,8,3,122,220,90,158,99,63,194,49,152,247,1,6,121,228,128,46,120,2,203,198,30,68,184,179,76,138,240,221,102,8,251,18,243,7,132,175,57,192,95,23,102,238,227,47,28,147,144,107,239,142,63,12,242,123,33,45,129,157,47,71,216,150,19,115,158,203,223,60,211,146,208,48,6,135,212,203,247,39,199,229,226,24,78,111,142,208,177,152,79,131,73,222,146,99,122,40,195,144,69,95,6,158,115,155,166,229,10,152,169,64,127,95,226,72,81,65,96,46,241,53,15,72,186,47,186,22,26,167,68,139,250,32,145,181,200,136,138,118,114,14,160,236,187,38,95,228,92,139,1,156,103,49,128,115,172,12,96,214,129,29,137,222,198,80,206,38,24,148,138,143,21,2,209,67,1,141,175,49,7,130,123,137,75,207,185,1,237,40,34,216,188,192,68,227,21,12,15,15,241,130,143,42,25,192,146,17,
|
||||
16,255,54,132,42,35,217,84,208,113,178,143,53,25,201,239,44,27,12,164,69,101,92,47,136,242,83,217,16,47,81,116,19,114,251,235,208,251,3,22,57,71,97,0,231,40,12,16,246,16,6,114,222,195,128,242,148,177,140,40,61,23,203,196,130,156,152,50,13,9,219,41,242,180,106,169,34,132,142,5,82,215,115,23,39,73,107,25,241,106,112,172,130,82,234,37,175,33,149,129,120,142,250,82,41,227,97,88,204,80,49,92,102,184,116,174,137,75,21,228,129,246,239,43,228,243,208,251,52,202,240,2,186,32,104,83,132,89,132,71,164,183,31,162,175,164,0,76,109,132,235,185,12,104,136,8,91,23,240,91,229,150,186,116,164,176,170,123,201,51,133,45,3,223,34,108,30,41,20,47,143,18,226,10,180,66,182,12,150,11,216,18,144,78,158,8,131,28,34,35,65,188,72,49,209,202,235,192,185,200,158,183,108,193,81,187,60,20,203,215,135,56,189,91,74,0,12,174,197,71,55,180,247,178,170,224,150,140,21,135,36,140,120,136,233,33,201,222,0,195,76,18,174,168,16,92,
|
||||
135,97,196,125,183,79,203,217,173,41,103,144,20,7,185,248,199,149,231,130,98,234,152,239,113,0,179,59,184,137,20,27,200,167,144,235,34,133,225,195,129,45,40,62,42,225,56,150,49,202,248,116,5,240,89,115,33,39,132,248,25,47,32,197,184,25,163,26,21,46,79,225,129,66,229,243,4,221,227,4,237,211,132,140,4,186,20,24,216,237,202,184,94,16,229,110,151,203,82,118,151,177,16,6,198,98,152,25,107,226,204,88,19,81,198,234,144,50,86,199,148,113,69,80,25,43,162,202,88,27,40,192,121,154,59,56,143,61,114,83,156,4,74,240,223,151,62,140,201,20,234,92,240,101,112,160,162,136,240,74,100,131,49,47,164,113,132,183,18,101,71,168,12,252,51,12,240,177,79,83,174,18,54,95,115,217,177,115,35,251,86,231,126,225,111,26,224,233,137,150,185,143,54,240,44,69,203,7,165,162,220,252,191,131,65,192,141,255,10,14,186,130,163,174,224,176,43,48,238,23,224,16,233,128,223,190,101,207,71,95,108,254,239,150,67,51,147,122,250,126,190,54,154,189,156,237,
|
||||
110,127,62,228,177,232,72,120,148,89,42,178,99,105,250,108,153,230,10,202,255,52,192,247,192,61,169,253,206,38,15,121,78,251,184,214,232,232,172,145,189,60,165,230,184,196,159,49,117,235,252,209,106,39,151,158,58,68,76,138,199,174,5,200,62,127,65,165,178,138,69,137,213,120,10,213,90,15,80,173,37,159,39,42,8,65,30,187,227,18,94,149,111,152,167,80,73,247,198,249,211,189,212,29,174,150,185,170,159,228,170,38,180,66,62,165,163,28,138,72,12,33,233,44,211,150,197,111,214,228,169,231,91,187,176,9,221,143,3,68,51,183,233,168,188,69,111,77,242,125,11,215,81,172,245,234,17,165,221,165,47,58,166,179,191,222,167,131,186,240,148,219,217,152,58,237,231,79,110,235,198,3,140,45,106,252,60,74,110,150,64,173,231,5,109,31,47,217,83,129,250,67,22,203,115,44,16,109,64,44,118,62,170,88,246,165,74,57,75,170,24,249,76,179,116,63,173,208,221,207,165,149,118,129,253,39,209,134,77,240,15,92,129,180,247,178,21,30,125,217,161,187,31,184,236,182,
|
||||
41,103,225,47,133,46,173,159,54,132,108,71,153,213,71,179,221,209,79,29,57,30,107,90,158,59,102,108,29,141,109,136,143,191,96,158,113,51,110,28,213,38,255,6,106,173,94,54,
|
||||
|
||||
|
|
@ -158,3 +158,7 @@ TOPIC("Atest$en-us")
|
|||
#include "Atest$en-us.tppi"
|
||||
END_TOPIC
|
||||
|
||||
TOPIC("TestTest$en-us")
|
||||
#include "TestTest$en-us.tppi"
|
||||
END_TOPIC
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
uses
|
||||
RichEdit;
|
||||
Core,
|
||||
CtrlLib,
|
||||
CodeEditor;
|
||||
|
||||
file
|
||||
test.cpp,
|
||||
test2.cpp,
|
||||
ignorelist;
|
||||
|
||||
mainconfig
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
#ifndef _Parser_icpp_init_stub
|
||||
#define _Parser_icpp_init_stub
|
||||
#include "RichEdit/init"
|
||||
#include "Core/init"
|
||||
#include "CtrlLib/init"
|
||||
#include "CodeEditor/init"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,11 +1,124 @@
|
|||
#include <RichEdit/RichEdit.h>
|
||||
|
||||
struct alpha {
|
||||
int beta;
|
||||
};
|
||||
|
||||
struct oper2 {
|
||||
int oper2m;
|
||||
};
|
||||
|
||||
struct oper3 {
|
||||
int oper3m;
|
||||
};
|
||||
|
||||
struct X {
|
||||
alpha a;
|
||||
|
||||
alpha operator[](int i);
|
||||
};
|
||||
|
||||
struct Y : X{
|
||||
X b;
|
||||
int a;
|
||||
|
||||
struct H {
|
||||
int x;
|
||||
};
|
||||
|
||||
H x;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct Tm {
|
||||
template <class V>
|
||||
struct H {
|
||||
T Test();
|
||||
V Test2();
|
||||
};
|
||||
|
||||
T x;
|
||||
};
|
||||
|
||||
|
||||
void Test(int a, long b)
|
||||
{
|
||||
X().;
|
||||
Y x;
|
||||
x.;
|
||||
x.a. ; // should not work...
|
||||
x.X::a. ;
|
||||
x.b.a. ;
|
||||
x[]. ;
|
||||
x(). ;
|
||||
x. ;
|
||||
x-> ;
|
||||
y. ;
|
||||
Tm<X> tm;
|
||||
Tm< X > :: H <alpha > tt;
|
||||
tt. ;
|
||||
tt.Test(). ;
|
||||
tt.Test2(). ;
|
||||
X:: ;
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
|
||||
void Foo()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CppItemInfoDisplay ItemList::display;
|
||||
|
||||
class ItemList : public ColumnList {
|
||||
CppItemInfoDisplay display;
|
||||
|
||||
friend struct ItemDisplay;
|
||||
|
||||
int GetTopic(Point p, String& key);
|
||||
String Item(int i);
|
||||
|
||||
public:
|
||||
bool active_topics;
|
||||
|
||||
void Clear();
|
||||
|
||||
ItemList();
|
||||
};
|
||||
|
||||
void ItemList::Clear()
|
||||
{
|
||||
}
|
||||
|
||||
void ItemList::Clear(int)
|
||||
{
|
||||
}
|
||||
|
||||
void Clear();
|
||||
|
||||
typedef short unsigned word;
|
||||
|
||||
typedef unsigned char byte;
|
||||
typedef signed char int8;
|
||||
typedef unsigned char uint8;
|
||||
|
||||
typedef short int int16;
|
||||
typedef short unsigned uint16;
|
||||
|
||||
struct FindBrokenRefIterator : RichTxt::Iterator {
|
||||
int cursor;
|
||||
Uuid itemstyle;
|
||||
|
||||
void Test();
|
||||
|
||||
virtual bool operator()(int pos, const RichPara& para)
|
||||
{
|
||||
|
||||
this-> ;
|
||||
THISBACK( ;
|
||||
if(pos >= cursor) {
|
||||
if(para.format.label != "noref") {
|
||||
if(IsNull(para.format.label))
|
||||
|
|
@ -27,3 +140,44 @@ struct FindBrokenRefIterator : RichTxt::Iterator {
|
|||
}
|
||||
};
|
||||
|
||||
void FindBrokenRefIterator::Test()
|
||||
{
|
||||
}
|
||||
|
||||
void Foo()
|
||||
{
|
||||
String x;
|
||||
x.Right(). ;
|
||||
String(xxx). ;
|
||||
String x;
|
||||
x.;
|
||||
x->;
|
||||
AttrText("Hello!"). ;
|
||||
Vector<String> vx;
|
||||
vx. ;
|
||||
vx[0]. ;
|
||||
vx.Add(). ;
|
||||
vx[654].Right(). ;
|
||||
vx[654]->Right(). ;
|
||||
Vector<String>(). ;
|
||||
x > x.;
|
||||
EditorBar bar;
|
||||
bar. ;
|
||||
EditString es;
|
||||
es. ;
|
||||
es.NullText(). ;
|
||||
THISBACK(
|
||||
}
|
||||
|
||||
struct Dlg : WithEditStringLayout<TopWindow> {
|
||||
Dlg() {
|
||||
Ctrl:: ;
|
||||
Dlg x;
|
||||
x. ;
|
||||
this. ;
|
||||
this-> ;
|
||||
a
|
||||
}
|
||||
Vector<String>::
|
||||
};
|
||||
|
||||
|
|
|
|||
4
uppdev/Parser/test2.cpp
Normal file
4
uppdev/Parser/test2.cpp
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
void ItemList::Clear(String x)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
file
|
||||
hh.cpp,
|
||||
test.cpp;
|
||||
|
||||
mainconfig
|
||||
|
|
|
|||
|
|
@ -1 +1,68 @@
|
|||
void Test(int a, long b);
|
||||
struct alpha {
|
||||
int beta;
|
||||
};
|
||||
|
||||
struct oper2 {
|
||||
int oper2m;
|
||||
};
|
||||
|
||||
struct oper3 {
|
||||
int oper3m;
|
||||
};
|
||||
|
||||
struct X {
|
||||
alpha a;
|
||||
|
||||
alpha operator[](int i);
|
||||
};
|
||||
|
||||
struct Y : X{
|
||||
X b;
|
||||
int a;
|
||||
|
||||
struct H {
|
||||
int x;
|
||||
};
|
||||
|
||||
H x;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct Tm {
|
||||
template <class V>
|
||||
struct H {
|
||||
T Test();
|
||||
V Test2();
|
||||
};
|
||||
|
||||
T x;
|
||||
};
|
||||
|
||||
|
||||
void Test(int a, long b)
|
||||
{
|
||||
X().;
|
||||
Y x;
|
||||
x.;
|
||||
x.a. ; // should not work...
|
||||
x.X::a. ;
|
||||
x.b.a. ;
|
||||
x[]. ;
|
||||
x(). ;
|
||||
x. ;
|
||||
x-> ;
|
||||
y. ;
|
||||
Tm<X> tm;
|
||||
Tm< X > :: H <alpha > tt;
|
||||
tt. ;
|
||||
tt.Test(). ;
|
||||
tt.Test2(). ;
|
||||
X:: ;
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
void Foo(volatile ::String)
|
||||
{
|
||||
|
||||
}
|
||||
21
uppdev/RichTextP/Copying
Normal file
21
uppdev/RichTextP/Copying
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
Copyright 1998-2008 The U++ Project. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||
conditions and the following disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE U++ PROJECT ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
361
uppdev/RichTextP/EncodeHTML.cpp
Normal file
361
uppdev/RichTextP/EncodeHTML.cpp
Normal file
|
|
@ -0,0 +1,361 @@
|
|||
#include "RichText.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
String HtmlFontStyle(Font f, Font base)
|
||||
{
|
||||
String style;
|
||||
if(f.GetFace() != base.GetFace())
|
||||
switch(f.GetFace()) {
|
||||
case Font::ARIAL: style = "font-family:sans-serif;"; break;
|
||||
case Font::ROMAN: style = "font-family:serif;"; break;
|
||||
case Font::COURIER: style = "font-family:monospace;"; break;
|
||||
}
|
||||
if(f.GetHeight() != base.GetHeight())
|
||||
style << Sprintf("font-size:%dpt;", f.GetHeight() * 72 / 600);
|
||||
if(f.IsBold() != base.IsBold())
|
||||
style << (f.IsBold() ? "font-weight:bold;" : "font-weight:normal;");
|
||||
if(f.IsItalic() != base.IsItalic())
|
||||
style << (f.IsItalic() ? "font-style:italic;" : "font-style:normal;");
|
||||
if(f.IsUnderline() != base.IsUnderline())
|
||||
style << (f.IsUnderline() ? "text-decoration:underline;" : "text-decoration:none;");
|
||||
return style;
|
||||
}
|
||||
|
||||
String HtmlFontStyle(Font f)
|
||||
{
|
||||
String style;
|
||||
switch(f.GetFace()) {
|
||||
case Font::ARIAL: style = "font-family:sans-serif;"; break;
|
||||
case Font::ROMAN: style = "font-family:serif;"; break;
|
||||
case Font::COURIER: style = "font-family:monospace;"; break;
|
||||
}
|
||||
style << Sprintf("font-size:%dpt;", f.GetHeight() * 72 / 600);
|
||||
style << (f.IsBold() ? "font-weight:bold;" : "font-weight:normal;");
|
||||
style << (f.IsItalic() ? "font-style:italic;" : "font-style:normal;");
|
||||
style << (f.IsUnderline() ? "text-decoration:underline;" : "text-decoration:none;");
|
||||
return style;
|
||||
}
|
||||
|
||||
String HtmlDot(int q, Zoom z)
|
||||
{
|
||||
return String().Cat() << ' ' << z * q << "px";
|
||||
}
|
||||
|
||||
String HtmlDotl(int q, Zoom z)
|
||||
{
|
||||
return String().Cat() << ' ' << max((int)!!q, z * q) << "px";
|
||||
}
|
||||
|
||||
String HtmlStyleColor(Color c, const char *cl = "color")
|
||||
{
|
||||
return Format(String(cl) + ":#%02x%02x%02x;", c.GetR(), c.GetG(), c.GetB());
|
||||
}
|
||||
|
||||
String HtmlCharStyle(const RichPara::CharFormat& cf, const RichPara::CharFormat& sf)
|
||||
{
|
||||
String style;
|
||||
if(cf.ink != sf.ink)
|
||||
style = HtmlStyleColor(cf.ink);
|
||||
return style + HtmlFontStyle(cf, sf);
|
||||
}
|
||||
|
||||
String HtmlParaStyle(const RichPara::Format& f, Zoom z)
|
||||
{
|
||||
String style;
|
||||
int lm = z * f.lm;
|
||||
if(f.bullet && f.bullet != RichPara::BULLET_TEXT) {
|
||||
style << "display:list-item;line-style-type:";
|
||||
switch(f.bullet) {
|
||||
case RichPara::BULLET_ROUND: style << "disc"; break;
|
||||
case RichPara::BULLET_ROUNDWHITE: style << "circle"; break;
|
||||
case RichPara::BULLET_BOX:
|
||||
case RichPara::BULLET_BOXWHITE: style << "square"; break;
|
||||
}
|
||||
style << ";line-style-position:inside;";
|
||||
lm += 20;
|
||||
}
|
||||
style << Format("margin:%d %d %d %d;text-indent:%d;",
|
||||
z * f.before,
|
||||
z * f.rm,
|
||||
z * f.after,
|
||||
lm,
|
||||
z * (f.bullet ? 0 : f.indent)
|
||||
);
|
||||
style << "text-align:";
|
||||
switch(f.align) {
|
||||
case ALIGN_LEFT: style << "left;"; break;
|
||||
case ALIGN_RIGHT: style << "right;"; break;
|
||||
case ALIGN_CENTER: style << "center;"; break;
|
||||
case ALIGN_JUSTIFY: style << "justify;"; break;
|
||||
}
|
||||
style << HtmlStyleColor(f.ink) + HtmlFontStyle(f);
|
||||
if(!IsNull(f.paper))
|
||||
style << HtmlStyleColor(f.paper, "background-color");
|
||||
return style;
|
||||
}
|
||||
|
||||
String FormatClass(Index<String>& css, const String& fmt)
|
||||
{
|
||||
return " CLASS=" + FormatIntAlpha(css.FindAdd(fmt) + 1);
|
||||
}
|
||||
|
||||
void TabBorder(String& style, const char *txt, int border, Color bordercolor, const RichTable::Format& tf, Zoom z)
|
||||
{
|
||||
style << "border-" << txt << ':' << HtmlDotl(border + tf.grid, z) << " solid "
|
||||
<< ColorToHtml(border ? bordercolor : tf.gridcolor) << ';';
|
||||
}
|
||||
|
||||
|
||||
String AsHtml(const RichTxt& text, const RichStyles& styles, Index<String>& css,
|
||||
const VectorMap<String, String>& links,
|
||||
const VectorMap<String, String>& labels,
|
||||
const String& outdir, const String& namebase, Zoom z, int& im,
|
||||
const VectorMap<String, String>& escape,
|
||||
int imtolerance)
|
||||
{
|
||||
String html;
|
||||
for(int i = 0; i < text.GetPartCount(); i++)
|
||||
{
|
||||
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;
|
||||
html << "<TABLE WIDTH=\"100%\" BORDER=0>";
|
||||
if(tf.before > 0)
|
||||
html << "<TR><TD HEIGHT=" << HtmlDot(tf.before, z) << " COLSPAN=3></TD></TR>";
|
||||
html << "<TR><TD><TABLE BORDER=0 WIDTH=" << HtmlDot(tf.lm, z) << "><TR><TD></TD></TR></TABLE></TD>\r\n"
|
||||
"<TD WIDTH=\"98%\">";
|
||||
|
||||
String style;
|
||||
style << "border-collapse:collapse;table-layout:auto;"
|
||||
<< "border:" << HtmlDotl(tf.frame, z) << " solid " << ColorToHtml(tf.framecolor) << ';';
|
||||
|
||||
html << "<TABLE WIDTH=\"100%\"" << FormatClass(css, style) << ">";
|
||||
int sum = 0;
|
||||
for(int i = 0; i < nx; i++)
|
||||
sum += t.format.column[i];
|
||||
html << "<COLGROUP>";
|
||||
for(int i = 0; i < nx; i++)
|
||||
html << "<COL width=\"" << 100 * t.format.column[i] / sum << "%\">";
|
||||
html << "\r\n";
|
||||
for(int i = 0; i < ny; i++) {
|
||||
const Array<RichCell>& r = t.cell[i];
|
||||
html << "<TR>";
|
||||
for(int j = 0; j < r.GetCount(); j++) {
|
||||
if(t(i, j)) {
|
||||
const RichCell& c = r[j];
|
||||
const RichCell::Format& cf = c.format;
|
||||
String style;
|
||||
style << "padding:" << HtmlDot(cf.margin.top, z) << HtmlDot(cf.margin.right, z)
|
||||
<< HtmlDot(cf.margin.bottom, z) << HtmlDot(cf.margin.left, z) << ';';
|
||||
TabBorder(style, "left", cf.border.left, cf.bordercolor, tf, z);
|
||||
TabBorder(style, "top", cf.border.top, cf.bordercolor, tf, z);
|
||||
TabBorder(style, "right", cf.border.right, cf.bordercolor, tf, z);
|
||||
TabBorder(style, "bottom", cf.border.bottom, cf.bordercolor, tf, z);
|
||||
style << "background-color:" << ColorToHtml(cf.color) << ';';
|
||||
style << "vertical-align:";
|
||||
switch(cf.align) {
|
||||
case ALIGN_TOP: style << "top"; break;
|
||||
case ALIGN_CENTER: style << "middle"; break;
|
||||
case ALIGN_BOTTOM: style << "bottom"; break;
|
||||
}
|
||||
style << ';';
|
||||
html << "<TD" << FormatClass(css, style);
|
||||
if(c.hspan)
|
||||
html << " colspan=" << c.hspan + 1;
|
||||
if(c.vspan)
|
||||
html << " rowspan=" << c.vspan + 1;
|
||||
html << '>';
|
||||
html << AsHtml(c.text, styles, css, links, labels, outdir, namebase, z,
|
||||
im, escape, imtolerance);
|
||||
html << "</TD>\r\n";
|
||||
}
|
||||
}
|
||||
html << "</TR>\r\n";
|
||||
}
|
||||
html << "</TABLE></TD>\r\n"
|
||||
<< "<TD><TABLE BORDER=0 WIDTH=" << HtmlDot(tf.rm, z) << "><TR><TD></TD></TR></TABLE></TD>";
|
||||
if(tf.after > 0)
|
||||
html << "<TR><TD HEIGHT=" << HtmlDot(tf.after, z) << " COLSPAN=3></TD></TR>";
|
||||
html << "</TABLE>\r\n";
|
||||
}
|
||||
else
|
||||
if(text.IsPara(i)) {
|
||||
RichPara p = text.Get(i, styles);
|
||||
if(p.format.ruler)
|
||||
html << "<HR>";
|
||||
String lbl;
|
||||
if(!IsNull(p.format.label)) {
|
||||
lbl = labels.Get(p.format.label, Null);
|
||||
if(lbl.GetCount())
|
||||
html << "<A NAME=\"" << lbl << "\">";
|
||||
}
|
||||
bool bultext = false;
|
||||
if(p.format.bullet == RichPara::BULLET_TEXT)
|
||||
for(int i = 0; i < p.part.GetCount(); i++) {
|
||||
const RichPara::Part& part = p.part[i];
|
||||
if(part.text.Find(9) >= 0) {
|
||||
bultext = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(bultext) {
|
||||
html << "<TABLE WIDTH=\"100%\" BORDER=0 "
|
||||
"CELLPADDING=2 CELLSPACING=2>"
|
||||
"<TR>";
|
||||
int q = z * p.format.lm - 8;
|
||||
if(q > 0)
|
||||
html << Format("<TD WIDTH=%d></TD>", q);
|
||||
html << Format("<TD VALIGN=\"top\" WIDTH=%d BGCOLOR=\"#F0F0F0\">\r\n",
|
||||
max(z * p.format.indent, 0));
|
||||
p.format.ruler = p.format.after = p.format.before = p.format.indent = p.format.lm = 0;
|
||||
}
|
||||
String par = "<P" + FormatClass(css, HtmlParaStyle(p.format, z)) + ">";
|
||||
html << par;
|
||||
for(int i = 0; i < p.part.GetCount(); i++) {
|
||||
const RichPara::Part& part = p.part[i];
|
||||
int q;
|
||||
if(part.object) {
|
||||
String name;
|
||||
name << namebase << "_" << im++ << ".png";
|
||||
Size psz = part.object.GetPixelSize();
|
||||
String lname;
|
||||
lname << "L$" << name;
|
||||
Size sz = z * part.object.GetSize();
|
||||
if(abs(100 * (psz.cx - sz.cx) / sz.cx) < imtolerance)
|
||||
sz = psz;
|
||||
PNGEncoder png;
|
||||
png.SaveFile(AppendFileName(outdir, name), part.object.ToImage(sz));
|
||||
if(psz.cx * psz.cy)
|
||||
html << "<A HREF=\"" << lname << "\">";
|
||||
html << "<IMG SRC=\"" << name << "\" BORDER=0 ALT=\"\">";
|
||||
if(psz.cx * psz.cy) {
|
||||
html << "</A>";
|
||||
PNGEncoder png;
|
||||
png.SaveFile(AppendFileName(outdir, lname), part.object.ToImage(psz));
|
||||
}
|
||||
}
|
||||
else
|
||||
if(part.format.indexentry.GetCount() &&
|
||||
(q = escape.Find(part.format.indexentry.ToString())) >= 0)
|
||||
html << escape[q];
|
||||
else {
|
||||
String lnk = part.format.link;
|
||||
if(lnk.GetCount()) {
|
||||
int q = links.Find(lnk);
|
||||
if(q < 0) {
|
||||
int q = lnk.ReverseFind('#');
|
||||
if(q >= 0) {
|
||||
String l = lnk.Left(q);
|
||||
lnk = links.Get(l, l) + '#' + lnk.Mid(q + 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
lnk = links[q];
|
||||
}
|
||||
String endtag;
|
||||
if(!lnk.IsEmpty() && lnk[0] != ':') {
|
||||
html << "<A HREF=\"" << lnk << "\">";
|
||||
endtag = "</A>";
|
||||
}
|
||||
String cs;
|
||||
if(part.text[0] != 9)
|
||||
cs = HtmlCharStyle(part.format, p.format);
|
||||
if(!cs.IsEmpty()) {
|
||||
html << "<SPAN" << FormatClass(css, cs) << ">";
|
||||
endtag = "</SPAN>" + endtag;
|
||||
}
|
||||
if(part.format.sscript == 1) {
|
||||
html << "<SUP>";
|
||||
endtag = "</SUP>" + endtag;
|
||||
}
|
||||
if(part.format.sscript == 2) {
|
||||
html << "<SUB>";
|
||||
endtag = "</SUB>" + endtag;
|
||||
}
|
||||
if(part.format.IsStrikeout()) {
|
||||
html << "<STRIKE>";
|
||||
endtag = "</STRIKE>" + endtag;
|
||||
}
|
||||
if(part.format.capitals) {
|
||||
html << "<SPAN STYLE=\"font-variant: small-caps;\">";
|
||||
endtag << "</SPAN>";
|
||||
}
|
||||
bool spc = false;
|
||||
const wchar *end = part.text.End();
|
||||
for(const wchar *s = part.text.Begin(); s != end; s++) {
|
||||
if(*s == ' ') {
|
||||
html.Cat(spc ? " " : " ");
|
||||
spc = true;
|
||||
}
|
||||
else {
|
||||
spc = false;
|
||||
if(*s == 160) html.Cat(" ");
|
||||
else
|
||||
if(*s == '<') html.Cat("<");
|
||||
else
|
||||
if(*s == '>') html.Cat(">");
|
||||
else
|
||||
if(*s == '&') html.Cat("&");
|
||||
else
|
||||
if(*s == '\"') html.Cat(""");
|
||||
else
|
||||
if(*s == 9) {
|
||||
if(bultext) {
|
||||
if(!cs.IsEmpty() && part.text[0] != 9)
|
||||
html << "</SPAN>";
|
||||
html << "</P>";
|
||||
html << "</TD>\r\n<TD VALIGN=\"top\" BGCOLOR=\"#F0F0F0\">\r\n";
|
||||
html << par;
|
||||
if(s[1]) {
|
||||
cs = HtmlCharStyle(part.format, p.format);
|
||||
if(!cs.IsEmpty())
|
||||
html << "<SPAN" << FormatClass(css, cs) << ">";
|
||||
}
|
||||
}
|
||||
else
|
||||
html.Cat(" ");
|
||||
}
|
||||
else
|
||||
html.Cat(ToUtf8(*s));
|
||||
}
|
||||
}
|
||||
html << endtag;
|
||||
}
|
||||
}
|
||||
if(p.part.GetCount() == 0)
|
||||
html << " ";
|
||||
html << "</P>";
|
||||
if(bultext)
|
||||
html << "</TD></TR></TABLE>";
|
||||
if(lbl.GetCount())
|
||||
html << "</A>";
|
||||
html << "\r\n";
|
||||
}
|
||||
}
|
||||
return html;
|
||||
}
|
||||
|
||||
String EncodeHtml(const RichText& text, Index<String>& css,
|
||||
const VectorMap<String, String>& links,
|
||||
const VectorMap<String, String>& labels,
|
||||
const String& outdir, const String& namebase, Zoom z,
|
||||
const VectorMap<String, String>& escape, int imt)
|
||||
{
|
||||
int im = 0;
|
||||
return AsHtml(text, text.GetStyles(), css, links, labels, outdir, namebase, z, im, escape, imt);
|
||||
}
|
||||
|
||||
String AsCss(Index<String>& ss)
|
||||
{
|
||||
String css;
|
||||
for(int i = 0; i < ss.GetCount(); i++) {
|
||||
css << "." + FormatIntAlpha(i + 1);
|
||||
css << "{" << ss[i] << "}\r\n";
|
||||
}
|
||||
return css;
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
552
uppdev/RichTextP/EncodeQtf.cpp
Normal file
552
uppdev/RichTextP/EncodeQtf.cpp
Normal file
|
|
@ -0,0 +1,552 @@
|
|||
#include "RichText.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
extern Color (*QTFColor[])();
|
||||
extern int QTFFontHeight[];
|
||||
|
||||
void SeparateNumber(String& s)
|
||||
{
|
||||
if(*s.Last() >= '0' && *s.Last() <= '9')
|
||||
s.Cat(';');
|
||||
}
|
||||
|
||||
String FmtColor(Color c)
|
||||
{
|
||||
if(IsNull(c)) return "N";
|
||||
for(int i = 0; i < 10; i++)
|
||||
if((*QTFColor[i])() == c)
|
||||
return String(i + '0', 1);
|
||||
if(c.GetR() == c.GetG() && c.GetG() == c.GetB())
|
||||
return Sprintf("(%d)", c.GetR());
|
||||
return Sprintf("(%d.%d.%d)", c.GetR(), c.GetG(), c.GetB());
|
||||
}
|
||||
|
||||
void LngFmt(String& fmt, dword l, dword lang)
|
||||
{
|
||||
if(lang != (dword)l)
|
||||
if(l == 0)
|
||||
fmt << "%-";
|
||||
else
|
||||
if(l == LNG_ENGLISH)
|
||||
fmt << "%%";
|
||||
else
|
||||
fmt << "%" << LNGAsText(l);
|
||||
}
|
||||
|
||||
void CharFmt(String& fmt, const RichPara::CharFormat& a, const RichPara::CharFormat& b)
|
||||
{
|
||||
if(a.IsBold() != b.IsBold()) fmt.Cat('*');
|
||||
if(a.IsItalic() != b.IsItalic()) fmt.Cat('/');
|
||||
if(a.IsUnderline() != b.IsUnderline()) fmt.Cat('_');
|
||||
if(a.IsStrikeout() != b.IsStrikeout()) fmt.Cat('-');
|
||||
if(a.IsNonAntiAliased() != b.IsNonAntiAliased()) fmt.Cat('t');
|
||||
if(a.capitals != b.capitals) fmt.Cat('c');
|
||||
if(a.dashed != b.dashed) fmt.Cat('d');
|
||||
if(a.sscript != b.sscript)
|
||||
fmt.Cat(b.sscript == 0 ? a.sscript == 1 ? '`' : ',' :
|
||||
b.sscript == 1 ? '`' : ',');
|
||||
if(a.GetFace() != b.GetFace())
|
||||
switch(b.GetFace()) {
|
||||
case Font::ARIAL: fmt.Cat('A'); break;
|
||||
case Font::ROMAN: fmt.Cat('R'); break;
|
||||
case Font::COURIER: fmt.Cat('C'); break;
|
||||
case Font::STDFONT: fmt.Cat('G'); break;
|
||||
case Font::SYMBOL: fmt.Cat('S'); break;
|
||||
default:
|
||||
fmt << "!" << b.GetFaceName() << "!";
|
||||
}
|
||||
if(a.link != b.link)
|
||||
fmt << '^' << DeQtf(b.link) << '^';
|
||||
if(a.indexentry != b.indexentry)
|
||||
fmt << 'I' << DeQtf(ToUtf8(b.indexentry)) << ';';
|
||||
if(a.ink != b.ink)
|
||||
fmt << "@" << FmtColor(b.ink);
|
||||
if(a.paper != b.paper)
|
||||
fmt << "$" << FmtColor(b.paper);
|
||||
if(a.GetHeight() != b.GetHeight()) {
|
||||
for(int i = 0; i < 10; i++)
|
||||
if(b.GetHeight() == QTFFontHeight[i]) {
|
||||
SeparateNumber(fmt);
|
||||
fmt.Cat('0' + i);
|
||||
return;
|
||||
}
|
||||
fmt.Cat(Format("+%d", b.GetHeight()));
|
||||
}
|
||||
}
|
||||
|
||||
void FmtNumber(String& qtf, char c, int former, int current)
|
||||
{
|
||||
qtf << (former != current ? Format("%c%d;", c, current) : String());
|
||||
}
|
||||
|
||||
void QTFEncodeParaFormat(String& qtf, const RichPara::Format& format, const RichPara::Format& style)
|
||||
{
|
||||
if(format.align != style.align)
|
||||
switch(format.align) {
|
||||
case ALIGN_LEFT: qtf << '<'; break;
|
||||
case ALIGN_RIGHT: qtf << '>'; break;
|
||||
case ALIGN_CENTER: qtf << '='; break;
|
||||
case ALIGN_JUSTIFY: qtf << '#'; break;
|
||||
}
|
||||
FmtNumber(qtf, 'l', style.lm, format.lm);
|
||||
FmtNumber(qtf, 'r', style.rm, format.rm);
|
||||
FmtNumber(qtf, 'i', style.indent, format.indent);
|
||||
FmtNumber(qtf, 'H', style.ruler, format.ruler);
|
||||
if(style.rulerink != format.rulerink)
|
||||
qtf << "h" << FmtColor(format.rulerink);
|
||||
FmtNumber(qtf, 'b', style.before, format.before);
|
||||
FmtNumber(qtf, 'a', style.after, format.after);
|
||||
if(style.newpage != format.newpage)
|
||||
qtf << 'P';
|
||||
if(style.keep != format.keep)
|
||||
qtf << 'k';
|
||||
if(style.keepnext != format.keepnext)
|
||||
qtf << 'K';
|
||||
if(style.orphan != format.orphan)
|
||||
qtf << 'Q';
|
||||
if(style.linespacing != format.linespacing)
|
||||
switch(format.linespacing) {
|
||||
case RichPara::LSP15: qtf << "ph"; break;
|
||||
case RichPara::LSP20: qtf << "pd"; break;
|
||||
default: qtf << "po"; break;
|
||||
}
|
||||
if(style.bullet != format.bullet) {
|
||||
qtf << 'O';
|
||||
switch(format.bullet) {
|
||||
case RichPara::BULLET_NONE: qtf << '_'; break;
|
||||
case RichPara::BULLET_ROUNDWHITE: qtf << '1'; break;
|
||||
case RichPara::BULLET_BOX: qtf << '2'; break;
|
||||
case RichPara::BULLET_BOXWHITE: qtf << '3'; break;
|
||||
case RichPara::BULLET_TEXT: qtf << '9'; break;
|
||||
default: qtf << '0'; break;
|
||||
}
|
||||
qtf << ';';
|
||||
}
|
||||
if(!IsEmpty(format.label))
|
||||
qtf << ':' << DeQtf(format.label) << ':';
|
||||
if(NumberingDiffers(style, format)) {
|
||||
if(format.before_number != style.before_number) {
|
||||
qtf << "n";
|
||||
qtf << DeQtf(format.before_number);
|
||||
qtf << ';';
|
||||
}
|
||||
if(format.after_number != style.after_number) {
|
||||
qtf << "m";
|
||||
qtf << DeQtf(format.after_number);
|
||||
qtf << ";";
|
||||
}
|
||||
int l;
|
||||
for(l = 7; l >= 0; --l)
|
||||
if(format.number[l])
|
||||
break;
|
||||
qtf << "N";
|
||||
for(int i = 0; i <= l; i++) {
|
||||
static char h[] = { '-', '1', '0', 'a', 'A', 'i', 'I' };
|
||||
if(format.number[i] <= RichPara::NUMBER_I)
|
||||
qtf << h[format.number[i]];
|
||||
else
|
||||
qtf << '-';
|
||||
}
|
||||
if(format.reset_number)
|
||||
qtf << '!';
|
||||
else
|
||||
qtf << ';';
|
||||
}
|
||||
FmtNumber(qtf, 't', style.tabsize, format.tabsize);
|
||||
if(style.tab != format.tab) {
|
||||
qtf << "~~";
|
||||
int i;
|
||||
for(i = 0; i < format.tab.GetCount(); i++) {
|
||||
RichPara::Tab tab = format.tab[i];
|
||||
qtf << '~';
|
||||
if(tab.align == ALIGN_RIGHT)
|
||||
qtf << '>';
|
||||
if(tab.align == ALIGN_CENTER)
|
||||
qtf << '=';
|
||||
if(tab.fillchar == 1)
|
||||
qtf << '.';
|
||||
if(tab.fillchar == 2)
|
||||
qtf << '-';
|
||||
if(tab.fillchar == 3)
|
||||
qtf << '_';
|
||||
qtf << tab.pos;
|
||||
}
|
||||
if(i)
|
||||
qtf << ';';
|
||||
}
|
||||
}
|
||||
|
||||
bool s_nodeqtf[128];
|
||||
|
||||
void QTFEncodePara(String& qtf, const RichPara& p, const RichPara::Format& style, byte charset, dword lang, bool crlf)
|
||||
{
|
||||
int d = qtf.GetLength();
|
||||
QTFEncodeParaFormat(qtf, p.format, style);
|
||||
if(p.part.GetCount()) {
|
||||
dword l = p.part.Top().format.language;
|
||||
LngFmt(qtf, l, lang);
|
||||
lang = l;
|
||||
}
|
||||
else {
|
||||
CharFmt(qtf, style, p.format);
|
||||
LngFmt(qtf, p.format.language, lang);
|
||||
}
|
||||
qtf.Cat(' ');
|
||||
d = qtf.GetLength() - d;
|
||||
for(int i = 0; i < p.part.GetCount(); i++) {
|
||||
const RichPara::Part& part = p.part[i];
|
||||
String cf;
|
||||
LngFmt(cf, part.format.language, lang);
|
||||
CharFmt(cf, style, part.format);
|
||||
if(!cf.IsEmpty()) {
|
||||
qtf << '[' << cf << ' ';
|
||||
d += cf.GetLength();
|
||||
}
|
||||
if(part.field) {
|
||||
if(crlf)
|
||||
qtf << "\r\n";
|
||||
qtf << "{:" + DeQtf(part.field.ToString()) + ":" + DeQtf(part.fieldparam) + ":}";
|
||||
if(crlf)
|
||||
qtf << "\r\n";
|
||||
d = 0;
|
||||
}
|
||||
else
|
||||
if(part.object) {
|
||||
const RichObject& object = part.object;
|
||||
Size sz = object.GetSize();
|
||||
if(crlf)
|
||||
qtf << "\r\n";
|
||||
qtf << "@@" << object.GetTypeName() << ':' << sz.cx
|
||||
<< (object.IsKeepRatio() ? '&' : '*') << sz.cy;
|
||||
if(object.GetYDelta())
|
||||
qtf << '/' << object.GetYDelta();
|
||||
if(crlf)
|
||||
qtf << "\r\n";
|
||||
String data = object.Write();
|
||||
const char *q = data.Begin();
|
||||
const char *slim = data.End();
|
||||
int n = 0;
|
||||
qtf.Reserve(8 * data.GetLength() / 7);
|
||||
while(q < slim - 7) {
|
||||
byte data[8];
|
||||
data[0] = ((q[0] & 0x80) >> 7) |
|
||||
((q[1] & 0x80) >> 6) |
|
||||
((q[2] & 0x80) >> 5) |
|
||||
((q[3] & 0x80) >> 4) |
|
||||
((q[4] & 0x80) >> 3) |
|
||||
((q[5] & 0x80) >> 2) |
|
||||
((q[6] & 0x80) >> 1) |
|
||||
0x80;
|
||||
data[1] = q[0] | 0x80;
|
||||
data[2] = q[1] | 0x80;
|
||||
data[3] = q[2] | 0x80;
|
||||
data[4] = q[3] | 0x80;
|
||||
data[5] = q[4] | 0x80;
|
||||
data[6] = q[5] | 0x80;
|
||||
data[7] = q[6] | 0x80;
|
||||
qtf.Cat(data, 8);
|
||||
if(crlf && ++n % 10 == 0)
|
||||
qtf << "\r\n";
|
||||
q += 7;
|
||||
}
|
||||
while(q < slim) {
|
||||
byte seven = 0;
|
||||
const char *lim = slim;
|
||||
const char *s;
|
||||
for(s = q; s < lim; s++)
|
||||
seven = (seven >> 1) | (*s & 0x80);
|
||||
seven >>= 8 - (lim - q);
|
||||
qtf.Cat(seven | 0x80);
|
||||
for(s = q; s < lim; s++)
|
||||
qtf.Cat(*s | 0x80);
|
||||
if(crlf && ++n % 10 == 0)
|
||||
qtf << "\r\n";
|
||||
q += 7;
|
||||
}
|
||||
if(crlf)
|
||||
qtf << "\r\n";
|
||||
d = 0;
|
||||
}
|
||||
else {
|
||||
for(const wchar *s = part.text.Begin(); s != part.text.End(); s++) {
|
||||
int c = *s;
|
||||
if(c < 128) {
|
||||
if(s_nodeqtf[c]) {
|
||||
qtf.Cat(c);
|
||||
d++;
|
||||
}
|
||||
else
|
||||
if(c == 9) {
|
||||
qtf.Cat("-|");
|
||||
d++;
|
||||
}
|
||||
else
|
||||
if(c == ':' && s[1] != ':')
|
||||
qtf.Cat(':');
|
||||
else {
|
||||
qtf.Cat('`');
|
||||
qtf.Cat(c);
|
||||
d += 2;
|
||||
}
|
||||
if(crlf && d > 60 && c == ' ') {
|
||||
qtf.Cat("\r\n");
|
||||
d = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(c == 160) {
|
||||
qtf.Cat("_");
|
||||
d++;
|
||||
}
|
||||
else
|
||||
if(charset == CHARSET_UTF8) {
|
||||
String q = ToUtf8(c);
|
||||
d += q.GetLength();
|
||||
qtf << q;
|
||||
}
|
||||
else {
|
||||
int ch = FromUnicode(c, charset, 0);
|
||||
if(ch)
|
||||
qtf << (char)ch;
|
||||
else
|
||||
qtf << "@$" << Format("%04X", ch) << ';';
|
||||
d++;
|
||||
}
|
||||
}
|
||||
if(crlf && d > 80) {
|
||||
qtf.Cat("\r\n");
|
||||
d = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!cf.IsEmpty()) {
|
||||
d++;
|
||||
qtf << ']';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FmtNumber2(String& qtf, char c, int da, int a, int db, int b)
|
||||
{
|
||||
if(da != a || db != b) {
|
||||
qtf << c;
|
||||
if(da != a)
|
||||
qtf << a;
|
||||
qtf << '/';
|
||||
qtf << b;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void QTFEncodeTxt(String& qtf, const RichTxt& text, const RichStyles& styles, const RichStyle& defstyle,
|
||||
dword options, const Index<Uuid>& sm, byte charset, dword lang)
|
||||
{
|
||||
qtf << '[';
|
||||
for(int i = 0; i < text.GetPartCount(); i++) {
|
||||
if(i) {
|
||||
qtf << "&]";
|
||||
if(options & QTF_CRLF)
|
||||
qtf << "\r\n";
|
||||
qtf << '[';
|
||||
}
|
||||
if(text.IsTable(i)) {
|
||||
qtf << ' ';
|
||||
|
||||
const RichTable& t = text.GetTable(i);
|
||||
int nx = t.format.column.GetCount();
|
||||
int ny = t.cell.GetCount();
|
||||
qtf << "{{";
|
||||
for(int i = 0; i < nx; i++) {
|
||||
if(i)
|
||||
qtf << ':';
|
||||
qtf << t.format.column[i];
|
||||
}
|
||||
const RichTable::Format& f = t.format;
|
||||
const RichTable::Format& d = Single<RichTable::Format>();
|
||||
FmtNumber(qtf, '<', d.lm, f.lm);
|
||||
FmtNumber(qtf, '>', d.rm, f.rm);
|
||||
FmtNumber(qtf, 'B', d.before, f.before);
|
||||
FmtNumber(qtf, 'A', d.after, f.after);
|
||||
FmtNumber(qtf, 'f', d.frame, f.frame);
|
||||
if(f.keep)
|
||||
qtf << "K";
|
||||
if(f.framecolor != d.framecolor)
|
||||
qtf << 'F' << FmtColor(f.framecolor);
|
||||
FmtNumber(qtf, 'g', d.grid, f.grid);
|
||||
if(f.gridcolor != d.gridcolor)
|
||||
qtf << 'G' << FmtColor(f.gridcolor);
|
||||
FmtNumber(qtf, 'h', d.header, f.header);
|
||||
RichCell::Format cf = Single<RichCell::Format>();
|
||||
for(int i = 0; i < ny; i++) {
|
||||
const Array<RichCell>& r = t.cell[i];
|
||||
for(int j = 0; j < r.GetCount(); j++) {
|
||||
const RichCell& c = r[j];
|
||||
if(i || j) {
|
||||
if(options & QTF_CRLF)
|
||||
qtf << "\r\n";
|
||||
qtf << "::";
|
||||
}
|
||||
const RichCell::Format& f = c.format;
|
||||
if(f.align != cf.align)
|
||||
switch(f.align) {
|
||||
case ALIGN_TOP: qtf << '^'; break;
|
||||
case ALIGN_CENTER: qtf << '='; break;
|
||||
case ALIGN_BOTTOM: qtf << 'v'; break;
|
||||
}
|
||||
FmtNumber2(qtf, 'l', cf.border.left, f.border.left, cf.margin.left, f.margin.left);
|
||||
FmtNumber2(qtf, 'r', cf.border.right, f.border.right, cf.margin.right, f.margin.right);
|
||||
FmtNumber2(qtf, 't', cf.border.top, f.border.top, cf.margin.top, f.margin.top);
|
||||
FmtNumber2(qtf, 'b', cf.border.bottom, f.border.bottom, cf.margin.bottom, f.margin.bottom);
|
||||
FmtNumber(qtf, 'H', cf.minheight, f.minheight);
|
||||
if(f.color != cf.color)
|
||||
qtf << '@' << FmtColor(f.color);
|
||||
if(f.bordercolor != cf.bordercolor)
|
||||
qtf << 'R' << FmtColor(f.bordercolor);
|
||||
cf = f;
|
||||
if(c.hspan)
|
||||
qtf << '-' << c.hspan;
|
||||
if(c.vspan)
|
||||
qtf << '|' << c.vspan;
|
||||
if(f.keep)
|
||||
qtf << "k";
|
||||
qtf << ' ';
|
||||
QTFEncodeTxt(qtf, c.text, styles, defstyle, options, sm, charset, lang);
|
||||
}
|
||||
}
|
||||
qtf << "}}";
|
||||
}
|
||||
else {
|
||||
RichPara p = text.Get(i, styles);
|
||||
int si = sm.Find(text.GetParaStyle(i));
|
||||
if(!(options & QTF_NOSTYLES))
|
||||
qtf << "s" << si;
|
||||
SeparateNumber(qtf);
|
||||
const RichStyle& s = si < 0 ? defstyle : GetStyle(styles, sm[si]);
|
||||
QTFEncodePara(qtf, p, options & QTF_NOSTYLES ? defstyle.format : s.format, charset, lang,
|
||||
(options & QTF_CRLF));
|
||||
}
|
||||
}
|
||||
qtf << ']';
|
||||
}
|
||||
|
||||
void init_s_nodeqtf()
|
||||
{
|
||||
ONCELOCK {
|
||||
for(int c = 1; c < 128; c++)
|
||||
s_nodeqtf[c] = IsAlNum(c) || strchr(".,;!?%()/<># ", c);
|
||||
}
|
||||
}
|
||||
|
||||
String AsQTF(const RichText& text, byte charset, dword options)
|
||||
{
|
||||
int i;
|
||||
String qtf;
|
||||
|
||||
init_s_nodeqtf();
|
||||
|
||||
RichPara::Format dpf;
|
||||
dpf.Face(Font::ARIAL);
|
||||
dpf.Height(100);
|
||||
dpf.language = LNG_ENGLISH;
|
||||
|
||||
bool crlf = options & QTF_CRLF;
|
||||
|
||||
Index<Uuid> sm;
|
||||
// if(options & QTF_ALL_STYLES) //!!!! problem -> GetUsedStyles!!!!
|
||||
for(i = 0; i < text.GetStyleCount(); i++)
|
||||
sm.FindAdd(text.GetStyleId(i));
|
||||
// else
|
||||
// for(i = 0; i < text.GetPartCount(); i++)
|
||||
// sm.FindAdd(text.GetParaStyle(i));
|
||||
|
||||
if(!(options & QTF_NOSTYLES))
|
||||
for(i = 0; i < sm.GetCount(); i++) {
|
||||
Uuid id = sm[i];
|
||||
const RichStyle& s = text.GetStyle(id);
|
||||
qtf << '[';
|
||||
QTFEncodeParaFormat(qtf, s.format, dpf);
|
||||
CharFmt(qtf, dpf, s.format);
|
||||
qtf << ' ';
|
||||
qtf << "$$" << i << ',' << max(sm.Find(s.next), 0)
|
||||
<< '#' << Format(id)
|
||||
<< ':' << DeQtf(s.name) << "]";
|
||||
if(crlf)
|
||||
qtf << "\r\n";
|
||||
}
|
||||
|
||||
if(text.GetPartCount() && (options & QTF_BODY)) {
|
||||
VectorMap<dword, int> lngc;
|
||||
int m = min(text.GetPartCount(), 30);
|
||||
for(int i = 0; i < m; i++)
|
||||
if(text.IsPara(i)) {
|
||||
RichPara p = text.Get(i);
|
||||
lngc.GetAdd(p.format.language, 0)++;
|
||||
}
|
||||
dword lang = lngc.GetCount() ? lngc.GetKey(MaxIndex(lngc.GetValues())) : 0;
|
||||
qtf << "[";
|
||||
if(!(options & QTF_NOCHARSET)) {
|
||||
qtf << "{";
|
||||
if(charset == CHARSET_UTF8)
|
||||
qtf << "_";
|
||||
else
|
||||
if(charset >= CHARSET_WIN1250 && charset <= CHARSET_WIN1258)
|
||||
qtf << (char)('0' + charset - CHARSET_WIN1250);
|
||||
else
|
||||
if(charset >= CHARSET_ISO8859_1 && charset <= CHARSET_ISO8859_16)
|
||||
qtf << (char)('A' + charset - CHARSET_ISO8859_1);
|
||||
else
|
||||
qtf << CharsetName(charset);
|
||||
qtf << "}";
|
||||
}
|
||||
if(lang && !(options & QTF_NOLANG))
|
||||
qtf << "%" << LNGAsText(SetLNGCharset(lang, CHARSET_DEFAULT));
|
||||
qtf << " ";
|
||||
if(crlf)
|
||||
qtf << "\r\n";
|
||||
RichStyle defstyle;
|
||||
defstyle.format.Height(100);
|
||||
|
||||
QTFEncodeTxt(qtf, text, text.GetStyles(), defstyle, options, sm, charset, lang);
|
||||
}
|
||||
return qtf;
|
||||
}
|
||||
|
||||
String DeQtf(const char *s) {
|
||||
String r;
|
||||
r.Reserve(256);
|
||||
while(*s) {
|
||||
if((byte)*s > ' ' && !IsDigit(*s) && !IsAlpha(*s) && (byte)*s < 128)
|
||||
r.Cat('`');
|
||||
r.Cat(*s++);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
String DeQtfLf(const char *s) {
|
||||
String r;
|
||||
r.Reserve(256);
|
||||
while(*s) {
|
||||
if((byte)*s > ' ' && !IsDigit(*s) && !IsAlpha(*s) && (byte)*s < 128)
|
||||
r.Cat('`');
|
||||
if((byte)*s >= ' ')
|
||||
r.Cat(*s);
|
||||
else
|
||||
if(*s == '\n')
|
||||
r.Cat('&');
|
||||
s++;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
String AsQTF(const RichObject& obj)
|
||||
{
|
||||
RichText x;
|
||||
RichPara p;
|
||||
RichPara::Format fmt;
|
||||
p.Cat(obj, fmt);
|
||||
x.Cat(p);
|
||||
return AsQTF(x);
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
658
uppdev/RichTextP/EncodeRTF.cpp
Normal file
658
uppdev/RichTextP/EncodeRTF.cpp
Normal file
|
|
@ -0,0 +1,658 @@
|
|||
#include "RichText.h"
|
||||
|
||||
#include <plugin/png/png.h>
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
static int GetParaHeight(const Array<RichPara::Part>& parts)
|
||||
{
|
||||
int ht = 0;
|
||||
for(int i = 0; i < parts.GetCount(); i++) {
|
||||
int pht = 0;
|
||||
const RichPara::Part& part = parts[i];
|
||||
if(part.object)
|
||||
pht = part.object.GetSize().cy;
|
||||
else if(part.field)
|
||||
pht = GetParaHeight(part.fieldpart);
|
||||
else
|
||||
pht = tabs(part.format.GetHeight());
|
||||
if(pht > ht)
|
||||
ht = pht;
|
||||
}
|
||||
return ht;
|
||||
}
|
||||
|
||||
class RTFEncoder {
|
||||
public:
|
||||
RTFEncoder(Stream& stream, const RichText& richtext, byte charset);
|
||||
|
||||
void Run();
|
||||
|
||||
private:
|
||||
void FacesAddFormat(const RichPara::CharFormat& format);
|
||||
void GetFaces();
|
||||
void GetTxtFaces(const RichTxt& txt);
|
||||
|
||||
void PutHeader();
|
||||
void PutDocument();
|
||||
void PutTxt(const RichTxt& txt, int nesting, int dot_width);
|
||||
void PutTable(const RichTable& table, int nesting, int dot_width);
|
||||
void PutParts(const Array<RichPara::Part>& parts,
|
||||
RichPara::CharFormat& base, int bpart, int boff, int epart, int eoff);
|
||||
|
||||
void Begin() { stream.Put('{'); }
|
||||
void Begin(const char *cmd) { Begin(); Command(cmd); }
|
||||
void Begin(const char *cmd, int param) { Begin(); Command(cmd, param); }
|
||||
void End() { stream.Put('}'); }
|
||||
|
||||
void Command(const char *cmd);
|
||||
void Command(const char *cmd, int param);
|
||||
void Space() { stream.Put(' '); }
|
||||
void PutText(const char *text);
|
||||
void PutObject(const RichObject& object);
|
||||
void PutTabs(const Vector<RichPara::Tab>& tabs);
|
||||
void PutBinHex(const byte *data, int count);
|
||||
void PutBinHex(const String& s) { PutBinHex(s, s.GetLength()); }
|
||||
|
||||
bool PutParaFormat(const RichPara::Format& pf, const RichPara::Format& difpf);
|
||||
bool PutCharFormat(const RichPara::CharFormat& cf, const RichPara::CharFormat& difcf, bool pn);
|
||||
|
||||
struct Group;
|
||||
|
||||
friend struct Group;
|
||||
|
||||
struct Group {
|
||||
Group(RTFEncoder *owner) : owner(owner) { owner->Begin(); }
|
||||
Group(RTFEncoder *owner, const char *cmd) : owner(owner) { owner->Begin(cmd); }
|
||||
Group(RTFEncoder *owner, const char *cmd, int param) : owner(owner) { owner->Begin(cmd, param); }
|
||||
~Group() { owner->End(); }
|
||||
RTFEncoder *owner;
|
||||
};
|
||||
|
||||
private:
|
||||
Stream& stream;
|
||||
const RichText& richtext;
|
||||
byte charset;
|
||||
|
||||
RichPara::CharFormat charfmt;
|
||||
RichPara::Format parafmt;
|
||||
Uuid oldstyle;
|
||||
int old_ht;
|
||||
int para_ht;
|
||||
|
||||
Index<int> used_faces;
|
||||
enum { SYMBOL_INDEX = 1, WINGDINGS_INDEX = 2 };
|
||||
VectorMap<Color, int> used_ink, used_paper;
|
||||
Index<Color> phys_colors;
|
||||
Index<Uuid> styleid;
|
||||
};
|
||||
|
||||
void EncodeRTF(Stream& stream, const RichText& richtext, byte charset)
|
||||
{
|
||||
RTFEncoder(stream, richtext, charset).Run();
|
||||
}
|
||||
|
||||
String EncodeRTF(const RichText& richtext, byte charset)
|
||||
{
|
||||
StringStream out;
|
||||
EncodeRTF(out, richtext, charset);
|
||||
String s = out.GetResult();
|
||||
LOG("EncodeRTF <<<<<\n" << s << "\n>>>>> EncodeRTF");
|
||||
return s;
|
||||
}
|
||||
|
||||
String EncodeRTF(const RichText& richtext)
|
||||
{
|
||||
return EncodeRTF(richtext, GetDefaultCharset() == CHARSET_UTF8 ? GetLNGCharset(GetSystemLNG())
|
||||
: GetDefaultCharset());
|
||||
}
|
||||
|
||||
RTFEncoder::RTFEncoder(Stream& stream, const RichText& richtext, byte charset)
|
||||
: stream(stream)
|
||||
, richtext(richtext)
|
||||
, charset(charset)
|
||||
{
|
||||
for(int i = 0; i < richtext.GetStyleCount(); i++)
|
||||
styleid.Add(richtext.GetStyleId(i));
|
||||
}
|
||||
|
||||
void RTFEncoder::Run()
|
||||
{
|
||||
GetFaces();
|
||||
Group docgrp(this, "rtf");
|
||||
PutHeader();
|
||||
PutDocument();
|
||||
}
|
||||
|
||||
void RTFEncoder::FacesAddFormat(const RichPara::CharFormat& format)
|
||||
{
|
||||
used_faces.FindAdd(format.GetFace());
|
||||
if(used_ink.Find(format.ink) < 0) {
|
||||
Color i(format.ink.GetR(), format.ink.GetG(), format.ink.GetB());
|
||||
int x = used_ink.Get(i, -1);
|
||||
if(x < 0)
|
||||
x = phys_colors.FindAdd(i);
|
||||
used_ink.Add(format.ink, x);
|
||||
}
|
||||
if(used_paper.Find(format.paper) < 0) {
|
||||
Color p(format.paper.GetR(), format.paper.GetG(), format.paper.GetB());
|
||||
int x = used_paper.Get(p, -1);
|
||||
if(x < 0)
|
||||
x = phys_colors.FindAdd(p);
|
||||
used_paper.Add(format.paper, x);
|
||||
}
|
||||
}
|
||||
|
||||
void RTFEncoder::GetFaces()
|
||||
{
|
||||
used_faces.Add(Font::ARIAL); // default font
|
||||
used_faces.Add(Font::SYMBOL); // used for bullets
|
||||
#ifdef PLATFORM_WIN32
|
||||
used_faces.Add(Font::WINGDINGS); // used for bullets
|
||||
#endif
|
||||
phys_colors.Add(Null);
|
||||
used_ink.Add(Null, 0);
|
||||
used_paper.Add(Null, 0);
|
||||
used_ink.Add(Black(), 0);
|
||||
used_paper.Add(White(), 0);
|
||||
GetTxtFaces(richtext);
|
||||
for(int i = 0; i < richtext.GetStyleCount(); i++)
|
||||
FacesAddFormat(richtext.GetStyle(i).format);
|
||||
}
|
||||
|
||||
void RTFEncoder::GetTxtFaces(const RichTxt& rt)
|
||||
{
|
||||
for(int i = 0; i < rt.GetPartCount(); i++) {
|
||||
if(rt.IsTable(i)) {
|
||||
const RichTable& table = rt.GetTable(i);
|
||||
const RichTable::Format& tfmt = table.GetFormat();
|
||||
phys_colors.FindAdd(tfmt.framecolor);
|
||||
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];
|
||||
phys_colors.FindAdd(cell.format.color);
|
||||
phys_colors.FindAdd(cell.format.bordercolor);
|
||||
GetTxtFaces(cell.text);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const RichPara& para = rt.Get(i, richtext.GetStyles());
|
||||
FacesAddFormat(para.format);
|
||||
for(int p = 0; p < para.part.GetCount(); p++) {
|
||||
const RichPara::Part& part = para.part[p];
|
||||
if(part.IsText())
|
||||
FacesAddFormat(part.format);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RTFEncoder::Command(const char *cmd)
|
||||
{
|
||||
stream.Put('\\');
|
||||
stream.Put(cmd);
|
||||
}
|
||||
|
||||
void RTFEncoder::Command(const char *cmd, int param)
|
||||
{
|
||||
stream.Put('\\');
|
||||
stream.Put(cmd);
|
||||
stream.Put(IntStr(param));
|
||||
}
|
||||
|
||||
void RTFEncoder::PutText(const char *text)
|
||||
{
|
||||
while(*text) {
|
||||
if(*text == '{' || *text == '}' || *text == '\\')
|
||||
stream.Put('\\');
|
||||
stream.Put(*text++);
|
||||
}
|
||||
}
|
||||
|
||||
void RTFEncoder::PutBinHex(const byte *b, int count)
|
||||
{
|
||||
enum { BLOCK = 32 };
|
||||
for(int l = count; l > 0; l -= BLOCK) {
|
||||
stream.PutCrLf();
|
||||
for(const byte *e = b + min<int>(l, BLOCK); b < e; b++) {
|
||||
static const char binhex[] = "0123456789abcdef";
|
||||
stream.Put(binhex[*b >> 4]);
|
||||
stream.Put(binhex[*b & 15]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RTFEncoder::PutCharFormat(const RichPara::CharFormat& cf, const RichPara::CharFormat& difcf, bool pn)
|
||||
{
|
||||
int64 pos = stream.GetPos();
|
||||
int pn2 = (pn ? 0 : 2);
|
||||
bool f;
|
||||
int t;
|
||||
if(cf.GetFace() != difcf.GetFace())
|
||||
Command("pnf" + pn2, used_faces.Find(cf.GetFace()));
|
||||
if((t = DotPoints(2 * tabs(cf.GetHeight()))) != DotPoints(2 * tabs(difcf.GetHeight())))
|
||||
Command("pnfs" + pn2, t);
|
||||
if(!pn && dword(t = cf.sscript) != difcf.sscript)
|
||||
Command(t == 0 ? "nosupersub" : t == 1 ? "super" : "sub");
|
||||
if((f = cf.IsBold()) != difcf.IsBold()) Command((f ? "pnb" : "pnb0") + pn2);
|
||||
if((f = cf.IsItalic()) != difcf.IsItalic()) Command((f ? "pni" : "pni0") + pn2);
|
||||
if((f = cf.IsUnderline()) != difcf.IsUnderline()) Command((f ? "pnul" : "pnul0") + pn2);
|
||||
if((f = cf.IsStrikeout()) != difcf.IsStrikeout()) Command((f ? "pnstrike" : "pnstrike0") + pn2);
|
||||
if((f = cf.capitals) != difcf.capitals) Command((f ? "pncaps" : "pncaps0") + pn2);
|
||||
if((t = used_ink.Get(cf.ink)) != used_ink.Get(difcf.ink)) Command("pncf" + pn2, t);
|
||||
if((t = used_paper.Get(cf.paper)) != used_paper.Get(difcf.paper)) Command("pncb" + pn2, t);
|
||||
#ifdef PLATFORM_WIN32 //zapoznamkoval Fidler kdyz chtel zkompilovat pod Linuxem...
|
||||
if(!pn && cf.language != difcf.language) Command("lang", GetLanguageLCID(cf.language));
|
||||
#endif
|
||||
// todo: link
|
||||
return stream.GetPos() != pos;
|
||||
}
|
||||
|
||||
void RTFEncoder::PutObject(const RichObject& object)
|
||||
{
|
||||
#ifdef PLATFORM_WIN32
|
||||
#ifndef PLATFORM_WINCE
|
||||
Size log_size = object.GetPixelSize(), out_size = object.GetSize();
|
||||
if(log_size.cx <= 0 || log_size.cy <= 0) log_size = out_size;
|
||||
// Size scale = out_size * 100 / log_size;
|
||||
Group pict_grp(this, "pict");
|
||||
Command("picw", log_size.cx);
|
||||
Command("pich", log_size.cy);
|
||||
Command("picwgoal", DotTwips(out_size.cx));
|
||||
Command("pichgoal", DotTwips(out_size.cy));
|
||||
// Command("picscalex", scale.cx);
|
||||
// Command("picscaley", scale.cy);
|
||||
|
||||
if(object.GetTypeName() == "PING") {
|
||||
Command("pngblip");
|
||||
PutBinHex(object.GetData());
|
||||
}
|
||||
else {
|
||||
Command("wmetafile", 8);
|
||||
WinMetaFileDraw wmd(log_size.cx, log_size.cy);
|
||||
object.Paint(wmd, log_size);
|
||||
WinMetaFile wmf = wmd.Close();
|
||||
HENHMETAFILE hemf = wmf.GetHEMF();
|
||||
int size = GetWinMetaFileBits(hemf, 0, 0, MM_ANISOTROPIC, ScreenHDC());
|
||||
if(size > 0) {
|
||||
Buffer<byte> buffer(size);
|
||||
GetWinMetaFileBits(hemf, size, buffer, MM_ANISOTROPIC, ScreenHDC());
|
||||
PutBinHex(buffer, size);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
bool RTFEncoder::PutParaFormat(const RichPara::Format& pf, const RichPara::Format& difpf)
|
||||
{
|
||||
int64 pos = stream.GetPos();
|
||||
if(pf.align != difpf.align)
|
||||
switch(pf.align) {
|
||||
case ALIGN_NULL:
|
||||
case ALIGN_LEFT: Command("ql"); break;
|
||||
case ALIGN_CENTER: Command("qc"); break;
|
||||
case ALIGN_RIGHT: Command("qr"); break;
|
||||
case ALIGN_JUSTIFY: Command("qj"); break;
|
||||
default: NEVER();
|
||||
}
|
||||
int oind = difpf.indent, olm = difpf.lm;
|
||||
if(difpf.bullet != RichPara::BULLET_NONE) {
|
||||
olm += oind;
|
||||
oind = -oind;
|
||||
}
|
||||
int nind = pf.indent, nlm = pf.lm;
|
||||
if(pf.bullet != RichPara::BULLET_NONE) {
|
||||
nlm += nind;
|
||||
nind = -nind;
|
||||
}
|
||||
if(nind != oind) Command("fi", DotTwips(nind));
|
||||
if(nlm != olm) Command("li", DotTwips(nlm));
|
||||
if(pf.rm != difpf.rm) Command("ri", DotTwips(pf.rm));
|
||||
if(pf.newpage)
|
||||
Command("pagebb");
|
||||
if(pf.before != difpf.before) Command("sb", DotTwips(pf.before));
|
||||
if(pf.after != difpf.after) Command("sa", DotTwips(pf.after));
|
||||
if(pf.tab != difpf.tab) PutTabs(pf.tab);
|
||||
return stream.GetPos() != pos;
|
||||
}
|
||||
|
||||
void RTFEncoder::PutTabs(const Vector<RichPara::Tab>& tabs)
|
||||
{
|
||||
for(int i = 0; i < tabs.GetCount(); i++) {
|
||||
RichPara::Tab t = tabs[i];
|
||||
switch(t.align) {
|
||||
case ALIGN_NULL:
|
||||
case ALIGN_LEFT: break;
|
||||
case ALIGN_CENTER: Command("tqc"); break;
|
||||
case ALIGN_RIGHT: Command("tqr"); break;
|
||||
default: NEVER();
|
||||
}
|
||||
switch(t.fillchar) {
|
||||
case 0: break;
|
||||
case 1: Command("tldot"); break;
|
||||
case 2: Command("tlhyph"); break;
|
||||
case 3: Command("tlul"); break;
|
||||
default: NEVER();
|
||||
}
|
||||
Command("tx", DotTwips(t.pos));
|
||||
}
|
||||
}
|
||||
|
||||
void RTFEncoder::PutParts(const Array<RichPara::Part>& parts,
|
||||
RichPara::CharFormat& base, int bpart, int boff, int epart, int eoff)
|
||||
{
|
||||
if(epart >= parts.GetCount()) {
|
||||
epart = parts.GetCount() - 1;
|
||||
eoff = INT_MAX;
|
||||
}
|
||||
ASSERT(boff >= 0 && bpart >= 0);
|
||||
for(int p = bpart; p <= epart; p++) {
|
||||
const RichPara::Part& part = parts[p];
|
||||
if(part.IsText()) {
|
||||
WString px = part.text;
|
||||
if(p == epart && px.GetLength() > eoff)
|
||||
px.Trim(eoff);
|
||||
if(p == bpart)
|
||||
px.Remove(0, boff);
|
||||
if(!px.IsEmpty()) {
|
||||
if(PutCharFormat(part.format, base, false) || p == 0)
|
||||
Space();
|
||||
base = part.format;
|
||||
PutText(FromUnicode(px, charset));
|
||||
}
|
||||
}
|
||||
else if(part.object)
|
||||
PutObject(part.object);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void RTFEncoder::PutHeader()
|
||||
{
|
||||
static const short ansicpg[][2] = {
|
||||
{ CHARSET_WIN1250, 1250 },
|
||||
{ CHARSET_WIN1251, 1251 },
|
||||
{ CHARSET_WIN1252, 1252 },
|
||||
{ CHARSET_WIN1253, 1253 },
|
||||
{ CHARSET_WIN1254, 1254 },
|
||||
{ CHARSET_WIN1255, 1255 },
|
||||
{ CHARSET_WIN1256, 1256 },
|
||||
{ CHARSET_WIN1257, 1257 },
|
||||
{ CHARSET_WIN1258, 1258 },
|
||||
};
|
||||
int i;
|
||||
for(i = __countof(ansicpg); --i >= 0;)
|
||||
if(charset == ansicpg[i][0]) {
|
||||
Command("ansicpg", ansicpg[i][1]);
|
||||
break;
|
||||
}
|
||||
|
||||
Command("deff", 0);
|
||||
{
|
||||
Group ftbl(this, "fonttbl");
|
||||
for(int i = 0; i < used_faces.GetCount(); i++) {
|
||||
Group fnt(this, "f", i);
|
||||
int fn = used_faces[i];
|
||||
dword info = Font::GetFaceInfo(fn);
|
||||
if(info & Font::SYMBOLTYPE)
|
||||
Command("ftech");
|
||||
else if(info & Font::FIXEDPITCH)
|
||||
Command("fmodern");
|
||||
else if(fn == Font::ROMAN)
|
||||
Command("froman");
|
||||
else if(fn == Font::ARIAL
|
||||
#ifdef PLATFORM_WIN32
|
||||
|| fn == Font::TAHOMA
|
||||
#endif
|
||||
)
|
||||
Command("fswiss");
|
||||
Space();
|
||||
stream.Put(Font::GetFaceName(fn));
|
||||
stream.Put(';');
|
||||
}
|
||||
}
|
||||
|
||||
if(phys_colors.GetCount() > 1) {
|
||||
Group ctbl(this, "colortbl");
|
||||
stream.Put(';');
|
||||
for(int i = 1; i < phys_colors.GetCount(); i++) {
|
||||
Color rgb = phys_colors[i];
|
||||
Command("red", rgb.GetR());
|
||||
Command("green", rgb.GetG());
|
||||
Command("blue", rgb.GetB());
|
||||
stream.Put(';');
|
||||
}
|
||||
}
|
||||
|
||||
Begin("stylesheet");
|
||||
RichPara::CharFormat empcfmt;
|
||||
RichPara::Format emppfmt;
|
||||
|
||||
for(i = 0; i < richtext.GetStyleCount(); i++) {
|
||||
const RichStyle& style = richtext.GetStyle(i);
|
||||
Begin("s", i);
|
||||
PutParaFormat(style.format, emppfmt);
|
||||
PutCharFormat(style.format, empcfmt, false);
|
||||
Command("sbasedon", 222);
|
||||
if(style.next != richtext.GetStyleId(i))
|
||||
Command("snext", styleid.Find(style.next));
|
||||
Space();
|
||||
for(const char *n = style.name; *n; n++)
|
||||
stream.Put(*n == ';' ? '_' : *n);
|
||||
stream.Put(';');
|
||||
End();
|
||||
}
|
||||
End();
|
||||
}
|
||||
|
||||
void RTFEncoder::PutTable(const RichTable& table, int nesting, int dot_width)
|
||||
{
|
||||
Vector<int> vspan_counts;
|
||||
const RichTable::Format& tfmt = table.GetFormat();
|
||||
Vector<int> column_pos;
|
||||
column_pos.SetCount(tfmt.column.GetCount() + 1);
|
||||
column_pos[0] = tfmt.lm;
|
||||
int sum = 0;
|
||||
for(int c = 0; c < tfmt.column.GetCount(); c++)
|
||||
sum += tfmt.column[c];
|
||||
int rem_width = dot_width - tfmt.lm - tfmt.rm;
|
||||
for(int c = 0; c < tfmt.column.GetCount(); c++) {
|
||||
int part = iscale(tfmt.column[c], rem_width, max(sum, 1));
|
||||
sum -= tfmt.column[c];
|
||||
rem_width -= part;
|
||||
column_pos[c + 1] = column_pos[c] + part;
|
||||
}
|
||||
for(int r = 0; r < table.GetRows(); r++) {
|
||||
String rowfmt;
|
||||
if(nesting)
|
||||
rowfmt << "\\*\\nesttableprops";
|
||||
rowfmt << "\\trowd"
|
||||
"\\trleft" << DotTwips(tfmt.lm)
|
||||
// trbrdr[ltrbv]
|
||||
;
|
||||
Vector<int> cellindex;
|
||||
Rect dflt_margin(600, 600, 600, 600);
|
||||
for(int c = 0; c < table.GetColumns(); c++) {
|
||||
const RichCell& cell = table.cell[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);
|
||||
dflt_margin.bottom = min(dflt_margin.bottom, cell.format.margin.bottom);
|
||||
c += cell.hspan;
|
||||
}
|
||||
/*
|
||||
rowfmt <<
|
||||
"\\trpaddl" << DotTwips(dflt_margin.left) << "\\trpaddfl3"
|
||||
"\\trpaddt" << DotTwips(dflt_margin.top) << "\\trpaddft3"
|
||||
"\\trpaddr" << DotTwips(dflt_margin.right) << "\\trpaddfr3"
|
||||
"\\trpaddb" << DotTwips(dflt_margin.bottom) << "\\trpaddfb3";
|
||||
*/
|
||||
for(int c = 0; c < table.GetColumns(); c++) {
|
||||
const RichCell& cell = table.cell[r][c];
|
||||
/*
|
||||
if(cell.format.margin.left != dflt_margin.left)
|
||||
rowfmt << "\\clpadl" << DotTwips(cell.format.margin.left) << "\\clpadfl3";
|
||||
if(cell.format.margin.top != dflt_margin.top)
|
||||
rowfmt << "\\clpadt" << DotTwips(cell.format.margin.top) << "\\clpadft3";
|
||||
if(cell.format.margin.right != dflt_margin.right)
|
||||
rowfmt << "\\clpadr" << DotTwips(cell.format.margin.right) << "\\clpadfr3";
|
||||
if(cell.format.margin.bottom != dflt_margin.bottom)
|
||||
rowfmt << "\\clpadb" << DotTwips(cell.format.margin.bottom) << "\\clpadfb3";
|
||||
*/
|
||||
switch(cell.format.align) {
|
||||
case ALIGN_TOP: rowfmt << "\\clvertalt"; break;
|
||||
default:
|
||||
case ALIGN_CENTER: rowfmt << "\\clvertalc"; break;
|
||||
case ALIGN_BOTTOM: rowfmt << "\\clvertalb"; break;
|
||||
}
|
||||
cellindex.Add(c);
|
||||
if(cell.hspan)
|
||||
c += cell.hspan;
|
||||
int cell_end = column_pos[c + 1];
|
||||
if(cell.vspan) {
|
||||
vspan_counts.At(c, 0) = cell.vspan;
|
||||
rowfmt << "\\clvmgf";
|
||||
}
|
||||
else if(c < vspan_counts.GetCount() && vspan_counts[c] > 0)
|
||||
rowfmt << "\\clvmrg";
|
||||
if(!IsNull(cell.format.color))
|
||||
rowfmt << "\\clcbpat" << phys_colors.Find(cell.format.color);
|
||||
rowfmt << "\\cellx" << DotTwips(cell_end);
|
||||
}
|
||||
Begin();
|
||||
Command("pard");
|
||||
Command("intbl");
|
||||
parafmt = RichPara::Format();
|
||||
charfmt = RichPara::CharFormat();
|
||||
if(nesting)
|
||||
Command("itap", nesting + 1);
|
||||
if(!nesting)
|
||||
stream.Put(rowfmt);
|
||||
for(int c = 0; c < cellindex.GetCount(); c++) {
|
||||
int cx = cellindex[c];
|
||||
const RichCell& cell = table.cell[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");
|
||||
}
|
||||
stream.Put(rowfmt);
|
||||
Command(nesting ? "nestrow" : "row");
|
||||
End();
|
||||
}
|
||||
}
|
||||
|
||||
void RTFEncoder::PutTxt(const RichTxt& txt, int nesting, int dot_width)
|
||||
{
|
||||
for(int i = 0; i < txt.GetPartCount(); i++) {
|
||||
if(txt.IsTable(i))
|
||||
PutTable(txt.GetTable(i), nesting, dot_width);
|
||||
else {
|
||||
const RichPara& para = txt.Get(i, richtext.GetStyles());
|
||||
Uuid pstyle = txt.GetParaStyle(i);
|
||||
int para_ht = GetParaHeight(para.part);
|
||||
int first_part = 0, first_ind = 0;
|
||||
bool hdiff = (para.format.bullet != RichPara::BULLET_NONE
|
||||
&& para.format.bullet != RichPara::BULLET_TEXT && para_ht != para_ht);
|
||||
if(pstyle != oldstyle
|
||||
|| para.format.bullet != parafmt.bullet || para.format.bullet == RichPara::BULLET_TEXT
|
||||
|| hdiff || para.format.tab != parafmt.tab || para.format.newpage || parafmt.newpage) {
|
||||
Command("s", styleid.Find(pstyle));
|
||||
oldstyle = pstyle;
|
||||
parafmt = richtext.GetStyle(pstyle).format;
|
||||
Command("pard");
|
||||
if(nesting)
|
||||
Command("intbl");
|
||||
if(nesting > 1)
|
||||
Command("itap", nesting);
|
||||
parafmt = RichPara::Format();
|
||||
para_ht = 0;
|
||||
}
|
||||
if(para.format.bullet == RichPara::BULLET_TEXT) {
|
||||
int epart = 0, eoff = 0;
|
||||
while(epart < para.part.GetCount() && (eoff = para.part[epart].text.Find('\t')) < 0)
|
||||
epart++;
|
||||
|
||||
RichPara::CharFormat rcf = charfmt;
|
||||
rcf.Height(0);
|
||||
Begin("pntext");
|
||||
PutParts(para.part, rcf, 0, 0, epart, eoff);
|
||||
stream.Put('\t');
|
||||
End();
|
||||
|
||||
Begin("*\\pn");
|
||||
Command("pnhang");
|
||||
Command("pnql");
|
||||
rcf = charfmt;
|
||||
if(epart > 0 || eoff > 0)
|
||||
PutCharFormat(para.part[0].format, rcf, true);
|
||||
Begin("pntxta");
|
||||
End();
|
||||
Begin("pntxtb");
|
||||
Space();
|
||||
PutParts(para.part, rcf, 0, 0, epart, eoff);
|
||||
stream.Put('\t');
|
||||
End();
|
||||
End();
|
||||
}
|
||||
else if(para.format.bullet != RichPara::BULLET_NONE) {
|
||||
int sym_face = SYMBOL_INDEX;
|
||||
byte sym_char = 0xB7;
|
||||
|
||||
switch(para.format.bullet) {
|
||||
default:
|
||||
NEVER();
|
||||
|
||||
case RichPara::BULLET_ROUND: sym_face = SYMBOL_INDEX; sym_char = 0xB7; break;
|
||||
case RichPara::BULLET_ROUNDWHITE: sym_face = WINGDINGS_INDEX; sym_char = 0xA1; break;
|
||||
case RichPara::BULLET_BOX: sym_face = WINGDINGS_INDEX; sym_char = 'n'; break;
|
||||
case RichPara::BULLET_BOXWHITE: sym_face = WINGDINGS_INDEX; sym_char = 'o'; break;
|
||||
}
|
||||
|
||||
Begin("pntext");
|
||||
// Command("tqr");
|
||||
// Command("tx", DotTwips(para.format.indent));
|
||||
// Command("qr");
|
||||
Command("f", sym_face);
|
||||
Command("fs", DotPoints(2 * para_ht));
|
||||
Space();
|
||||
stream.Put(sym_char);
|
||||
stream.Put('\t');
|
||||
End();
|
||||
|
||||
Begin("*\\pn");
|
||||
Command("pnlvlblt");
|
||||
Command("pnf", sym_face);
|
||||
Command("pnfs", DotPoints(2 * para_ht));
|
||||
Command("pnql");
|
||||
Begin("pntxtb");
|
||||
Space();
|
||||
stream.Put(sym_char);
|
||||
// stream.Put('\t');
|
||||
End();
|
||||
Begin("pntxta");
|
||||
End();
|
||||
End();
|
||||
}
|
||||
PutParaFormat(para.format, parafmt);
|
||||
para_ht = para_ht;
|
||||
parafmt = para.format;
|
||||
PutParts(para.part, charfmt, first_part, first_ind, para.part.GetCount(), 0);
|
||||
if(i + 1 < txt.GetPartCount())
|
||||
Command("par");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RTFEncoder::PutDocument()
|
||||
{
|
||||
charfmt.Height(PointDots(0));
|
||||
charfmt.language = 0;
|
||||
old_ht = DotPoints(2 * tabs(charfmt.GetHeight()));
|
||||
para_ht = 0;
|
||||
oldstyle = Uuid::Create();
|
||||
PutTxt(richtext, 0, 3600);
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
212
uppdev/RichTextP/Format.cpp
Normal file
212
uppdev/RichTextP/Format.cpp
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
#include "RichText.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
void RichTxt::FormatInfo::Set(const RichPara::Format& fmt)
|
||||
{
|
||||
(RichPara::Format&)*this = fmt;
|
||||
charvalid = paravalid = 0xffffffff;
|
||||
}
|
||||
|
||||
void RichTxt::FormatInfo::Set(const RichPara::CharFormat& fmt)
|
||||
{
|
||||
(RichPara::CharFormat&)*this = fmt;
|
||||
charvalid = 0xffffffff;
|
||||
}
|
||||
|
||||
void RichTxt::FormatInfo::Combine(const RichPara::CharFormat& fmt)
|
||||
{
|
||||
if(IsBold() != fmt.IsBold()) {
|
||||
charvalid &= ~BOLD;
|
||||
NoBold();
|
||||
}
|
||||
if(IsItalic() != fmt.IsItalic()) {
|
||||
charvalid &= ~ITALIC;
|
||||
NoItalic();
|
||||
}
|
||||
if(IsUnderline() != fmt.IsUnderline()) {
|
||||
charvalid &= ~UNDERLINE;
|
||||
NoUnderline();
|
||||
}
|
||||
if(IsStrikeout() != fmt.IsStrikeout()) {
|
||||
charvalid &= ~STRIKEOUT;
|
||||
NoStrikeout();
|
||||
}
|
||||
if(IsNonAntiAliased() != fmt.IsNonAntiAliased()) {
|
||||
charvalid &= ~NOAA;
|
||||
NoNonAntiAliased();
|
||||
}
|
||||
if(capitals != fmt.capitals) {
|
||||
charvalid &= ~CAPITALS;
|
||||
capitals = false;
|
||||
}
|
||||
if(dashed != fmt.dashed) {
|
||||
charvalid &= ~DASHED;
|
||||
dashed = false;
|
||||
}
|
||||
if(sscript != fmt.sscript) {
|
||||
charvalid &= ~SSCRIPT;
|
||||
sscript = 0;
|
||||
}
|
||||
if(GetFace() != fmt.GetFace())
|
||||
charvalid &= ~FACE;
|
||||
if(GetHeight() != fmt.GetHeight())
|
||||
charvalid &= ~HEIGHT;
|
||||
if(ink != fmt.ink) {
|
||||
charvalid &= ~INK;
|
||||
ink = Null;
|
||||
}
|
||||
if(paper != fmt.paper) {
|
||||
charvalid &= ~PAPER;
|
||||
paper = Null;
|
||||
}
|
||||
if(language != fmt.language) {
|
||||
charvalid &= ~LANG;
|
||||
language = 0;
|
||||
}
|
||||
if(link != fmt.link) {
|
||||
charvalid &= ~LINK;
|
||||
link = Null;
|
||||
}
|
||||
if(indexentry != fmt.indexentry) {
|
||||
charvalid &= ~INDEXENTRY;
|
||||
indexentry = Null;
|
||||
}
|
||||
}
|
||||
|
||||
void RichTxt::FormatInfo::Combine(const RichPara::Format& fmt)
|
||||
{
|
||||
if(align != fmt.align)
|
||||
paravalid &= ~ALIGN;
|
||||
if(before != fmt.before)
|
||||
paravalid &= ~BEFORE;
|
||||
if(lm != fmt.lm)
|
||||
paravalid &= ~LM;
|
||||
if(indent != fmt.indent)
|
||||
paravalid &= ~INDENT;
|
||||
if(rm != fmt.rm)
|
||||
paravalid &= ~RM;
|
||||
if(after != fmt.after)
|
||||
paravalid &= ~AFTER;
|
||||
if(tabsize != fmt.tabsize)
|
||||
paravalid &= ~TABSIZE;
|
||||
if(bullet != fmt.bullet)
|
||||
paravalid &= ~BULLET;
|
||||
if(newpage != fmt.newpage)
|
||||
paravalid &= ~NEWPAGE;
|
||||
if(keep != fmt.keep)
|
||||
paravalid &= ~KEEP;
|
||||
if(keepnext != fmt.keepnext)
|
||||
paravalid &= ~KEEPNEXT;
|
||||
if(orphan != fmt.orphan)
|
||||
paravalid &= ~ORPHAN;
|
||||
if(label != fmt.label)
|
||||
paravalid &= ~LABEL;
|
||||
if(NumberingDiffers(*this, fmt))
|
||||
paravalid &= ~NUMBERING;
|
||||
if(tab.GetCount() != fmt.tab.GetCount()) {
|
||||
paravalid &= ~TABS;
|
||||
tab.Clear();
|
||||
}
|
||||
else
|
||||
for(int i = 0; i < tab.GetCount(); i++)
|
||||
if(tab[i].pos != fmt.tab[i].pos || tab[i].align != fmt.tab[i].align ||
|
||||
tab[i].fillchar != fmt.tab[i].fillchar) {
|
||||
paravalid &= ~TABS;
|
||||
tab.Clear();
|
||||
break;
|
||||
}
|
||||
if(styleid != fmt.styleid)
|
||||
paravalid &= ~STYLE;
|
||||
if(linespacing != fmt.linespacing)
|
||||
paravalid &= ~SPACING;
|
||||
if(ruler != fmt.ruler)
|
||||
paravalid &= ~RULER;
|
||||
if(rulerink != fmt.rulerink)
|
||||
paravalid &= ~RULERINK;
|
||||
}
|
||||
|
||||
void RichTxt::FormatInfo::ApplyTo(RichPara::CharFormat& fmt) const
|
||||
{
|
||||
if(charvalid & BOLD)
|
||||
fmt.Bold(IsBold());
|
||||
if(charvalid & ITALIC)
|
||||
fmt.Italic(IsItalic());
|
||||
if(charvalid & UNDERLINE)
|
||||
fmt.Underline(IsUnderline());
|
||||
if(charvalid & STRIKEOUT)
|
||||
fmt.Strikeout(IsStrikeout());
|
||||
if(charvalid & NOAA)
|
||||
fmt.NonAntiAliased(IsNonAntiAliased());
|
||||
if(charvalid & CAPITALS)
|
||||
fmt.capitals = capitals;
|
||||
if(charvalid & DASHED)
|
||||
fmt.dashed = dashed;
|
||||
if(charvalid & SSCRIPT)
|
||||
fmt.sscript = sscript;
|
||||
if(charvalid & FACE)
|
||||
fmt.Face(GetFace());
|
||||
if(charvalid & HEIGHT)
|
||||
fmt.Height(GetHeight());
|
||||
if(charvalid & LANGUAGE)
|
||||
fmt.language = language;
|
||||
if(charvalid & INK)
|
||||
fmt.ink = ink;
|
||||
if(charvalid & PAPER)
|
||||
fmt.paper = paper;
|
||||
if(charvalid & LANG)
|
||||
fmt.language = language;
|
||||
if(charvalid & LINK)
|
||||
fmt.link = link;
|
||||
if(charvalid & INDEXENTRY)
|
||||
fmt.indexentry = indexentry;
|
||||
}
|
||||
|
||||
void RichTxt::FormatInfo::ApplyTo(RichPara::Format& fmt) const
|
||||
{
|
||||
ApplyTo((RichPara::CharFormat &)fmt);
|
||||
if(paravalid & ALIGN)
|
||||
fmt.align = align;
|
||||
if(paravalid & RULER)
|
||||
fmt.ruler = ruler;
|
||||
if(paravalid & BEFORE)
|
||||
fmt.before = before;
|
||||
if(paravalid & LM)
|
||||
fmt.lm = lm;
|
||||
if(paravalid & INDENT)
|
||||
fmt.indent = indent;
|
||||
if(paravalid & RM)
|
||||
fmt.rm = rm;
|
||||
if(paravalid & AFTER)
|
||||
fmt.after = after;
|
||||
if(paravalid & TABSIZE)
|
||||
fmt.tabsize = tabsize;
|
||||
if(paravalid & BULLET)
|
||||
fmt.bullet = bullet;
|
||||
if(paravalid & NEWPAGE)
|
||||
fmt.newpage = newpage;
|
||||
if(paravalid & KEEP)
|
||||
fmt.keep = keep;
|
||||
if(paravalid & KEEPNEXT)
|
||||
fmt.keepnext = keepnext;
|
||||
if(paravalid & ORPHAN)
|
||||
fmt.orphan = orphan;
|
||||
if(paravalid & LABEL)
|
||||
fmt.label = label;
|
||||
if(paravalid & NUMBERING) {
|
||||
fmt.before_number = before_number;
|
||||
fmt.after_number = after_number;
|
||||
fmt.reset_number = reset_number;
|
||||
memcpy(fmt.number, number, sizeof(number));
|
||||
}
|
||||
// if(paravalid & TABS)
|
||||
// fmt.tab = tab;
|
||||
if(paravalid & STYLE)
|
||||
fmt.styleid = styleid;
|
||||
if(paravalid & SPACING)
|
||||
fmt.linespacing = linespacing;
|
||||
if(paravalid & RULERINK)
|
||||
fmt.rulerink = rulerink;
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
401
uppdev/RichTextP/Object.cpp
Normal file
401
uppdev/RichTextP/Object.cpp
Normal file
|
|
@ -0,0 +1,401 @@
|
|||
#include "RichText.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
RichObjectType::RichObjectType() {}
|
||||
RichObjectType::~RichObjectType() {}
|
||||
|
||||
String RichObjectType::GetCreateName() const
|
||||
{
|
||||
return Null;
|
||||
}
|
||||
|
||||
Size RichObjectType::GetDefaultSize(const Value& data, Size maxsize) const
|
||||
{
|
||||
if(IsNull(data)) return Size(0, 0);
|
||||
Size psz = GetPhysicalSize(data);
|
||||
if((psz.cx | psz.cy) == 0)
|
||||
psz = 625 * GetPixelSize(data) / 100;
|
||||
Size sz;
|
||||
for(int i = 1; i < 10000; i++) {
|
||||
sz = psz / i;
|
||||
if(sz.cx <= maxsize.cx && sz.cy <= maxsize.cy)
|
||||
break;
|
||||
}
|
||||
return sz;
|
||||
}
|
||||
|
||||
Value RichObjectType::Read(const String& s) const
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
String RichObjectType::Write(const Value& v) const
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
bool RichObjectType::Accept(PasteClip& clip)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Value RichObjectType::Read(PasteClip& clip)
|
||||
{
|
||||
return Null;
|
||||
}
|
||||
|
||||
String RichObjectType::GetClipFmts() const
|
||||
{
|
||||
return Null;
|
||||
}
|
||||
|
||||
String RichObjectType::GetClip(const Value& data, const String& fmt) const
|
||||
{
|
||||
return Null;
|
||||
}
|
||||
|
||||
void RichObjectType::Menu(Bar& bar, RichObject& data) const {}
|
||||
void RichObjectType::DefaultAction(RichObject& data) const {}
|
||||
Size RichObjectType::GetPhysicalSize(const Value& data) const { return Size(0, 0); }
|
||||
Size RichObjectType::GetPixelSize(const Value& data) const { return Size(1, 1); }
|
||||
void RichObjectType::Paint(const Value& data, Draw& w, Size sz) const {}
|
||||
|
||||
Image RichObjectType::ToImage(const Value& data, Size sz) const
|
||||
{
|
||||
ImageDraw w(sz);
|
||||
Paint(data, w, sz);
|
||||
return w;
|
||||
}
|
||||
|
||||
String RichObjectType::GetLink(const Value& data, Point pt, Size sz) const
|
||||
{
|
||||
return Null;
|
||||
}
|
||||
|
||||
void RichObject::InitSize(int cx, int cy)
|
||||
{
|
||||
Size sz;
|
||||
Size phsz = GetPixelSize();
|
||||
if(cx || cy)
|
||||
sz = GetRatioSize(phsz, cx, cy);
|
||||
else
|
||||
sz = phsz;
|
||||
if(sz.cx > 2000 || sz.cy > 2000)
|
||||
sz = sz.cx > sz.cy ? GetRatioSize(phsz, 2000, 0)
|
||||
: GetRatioSize(phsz, 0, 2000);
|
||||
SetSize(sz);
|
||||
}
|
||||
|
||||
typedef VectorMap<String, RichObjectType *> RichObjectHT;
|
||||
|
||||
GLOBAL_VAR(RichObjectHT, RichObject::Map);
|
||||
|
||||
void RichObject::NewSerial()
|
||||
{
|
||||
INTERLOCKED {
|
||||
static int64 s;
|
||||
serial = ++s;
|
||||
}
|
||||
}
|
||||
|
||||
void RichObject::Register(const char *name, RichObjectType *type)
|
||||
{
|
||||
AssertST();
|
||||
Map().FindAdd(name, type);
|
||||
}
|
||||
|
||||
void RichObject::Paint(Draw& w, Size sz) const
|
||||
{
|
||||
if(type)
|
||||
type->Paint(data, w, sz);
|
||||
else {
|
||||
w.DrawRect(sz, SColorFace());
|
||||
DrawFrame(w, sz, SColorText());
|
||||
w.DrawText(2, 2, type_name);
|
||||
}
|
||||
}
|
||||
|
||||
Image RichObject::ToImage(Size sz) const
|
||||
{
|
||||
if(type)
|
||||
return type->ToImage(data, sz);
|
||||
else {
|
||||
ImageDraw w(sz);
|
||||
Paint(w, sz);
|
||||
return w;
|
||||
}
|
||||
}
|
||||
|
||||
struct UnknownRichObject : RichObjectType {
|
||||
virtual String GetTypeName(const Value&) const;
|
||||
};
|
||||
|
||||
String UnknownRichObject::GetTypeName(const Value&) const
|
||||
{
|
||||
return Null;
|
||||
}
|
||||
|
||||
const RichObjectType& RichObject::GetType() const
|
||||
{
|
||||
if(type)
|
||||
return *type;
|
||||
return Single<UnknownRichObject>();
|
||||
}
|
||||
|
||||
void RichObject::Set(RichObjectType *_type, const Value& _data, Size maxsize)
|
||||
{
|
||||
Clear();
|
||||
type = _type;
|
||||
if(type) {
|
||||
data = _data;
|
||||
physical_size = type->GetPhysicalSize(data);
|
||||
pixel_size = type->GetPixelSize(data);
|
||||
size = type->GetDefaultSize(data, maxsize);
|
||||
}
|
||||
NewSerial();
|
||||
}
|
||||
|
||||
bool RichObject::Set(const String& _type_name, const Value& _data, Size maxsize)
|
||||
{
|
||||
NewSerial();
|
||||
type_name = _type_name;
|
||||
RichObjectType *t = Map().Get(type_name, NULL);
|
||||
if(t) {
|
||||
Set(t, _data);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
Clear();
|
||||
data = _data;
|
||||
physical_size = pixel_size = size = Size(64, 64);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RichObject::Read(const String& _type_name, const String& _data, Size sz)
|
||||
{
|
||||
NewSerial();
|
||||
type_name = _type_name;
|
||||
RichObjectType *t = Map().Get(type_name, NULL);
|
||||
if(t) {
|
||||
Clear();
|
||||
type = t;
|
||||
data = type->Read(_data);
|
||||
physical_size = type->GetPhysicalSize(data);
|
||||
pixel_size = type->GetPixelSize(data);
|
||||
size = sz;
|
||||
return true;
|
||||
}
|
||||
data = _data;
|
||||
physical_size = pixel_size = size = sz;
|
||||
return false;
|
||||
}
|
||||
|
||||
String RichObject::GetTypeName() const
|
||||
{
|
||||
return type ? type->GetTypeName(data) : type_name;
|
||||
}
|
||||
|
||||
void RichObject::Clear()
|
||||
{
|
||||
NewSerial();
|
||||
keepratio = true;
|
||||
type = NULL;
|
||||
data = Value();
|
||||
size = physical_size = pixel_size = Size(0, 0);
|
||||
ydelta = 0;
|
||||
type_name.Clear();
|
||||
}
|
||||
|
||||
RichObject::RichObject()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
RichObject::RichObject(RichObjectType *type, const Value& data, Size maxsize)
|
||||
{
|
||||
Set(type, data, maxsize);
|
||||
}
|
||||
|
||||
RichObject::RichObject(const String& type, const Value& data, Size maxsize)
|
||||
{
|
||||
Set(type, data, maxsize);
|
||||
}
|
||||
|
||||
struct RichObjectTypeDrawingCls : public RichObjectType
|
||||
{
|
||||
virtual String GetTypeName(const Value&) const;
|
||||
virtual Size GetPhysicalSize(const Value& data) const;
|
||||
virtual Size GetPixelSize(const Value& data) const;
|
||||
virtual void Paint(const Value& data, Draw& w, Size sz) const;
|
||||
virtual Value Read(const String& s) const;
|
||||
virtual String Write(const Value& v) const;
|
||||
|
||||
struct Data
|
||||
{
|
||||
void Serialize(Stream& stream);
|
||||
|
||||
Drawing drawing;
|
||||
Size dot_size;
|
||||
};
|
||||
};
|
||||
|
||||
RichObjectType *RichObjectTypeDrawing() { return &Single<RichObjectTypeDrawingCls>(); }
|
||||
|
||||
void RichObjectTypeDrawingCls::Data::Serialize(Stream& stream)
|
||||
{
|
||||
int version = 1;
|
||||
stream % version % dot_size % drawing;
|
||||
}
|
||||
|
||||
String RichObjectTypeDrawingCls::GetTypeName(const Value&) const
|
||||
{
|
||||
return "Drawing";
|
||||
}
|
||||
|
||||
RichObject CreateDrawingObject(const Drawing& dwg, Size dot_size, Size out_size)
|
||||
{
|
||||
RichObjectTypeDrawingCls::Data data;
|
||||
data.drawing = dwg;
|
||||
data.dot_size = dot_size;
|
||||
RichObject obj(RichObjectTypeDrawing(), RawToValue(data));
|
||||
if(!IsNull(out_size))
|
||||
obj.SetSize(out_size);
|
||||
return obj;
|
||||
}
|
||||
|
||||
RichObject CreateDrawingObject(const Drawing& dwg, int cx, int cy)
|
||||
{
|
||||
Size dsz = dwg.GetSize();
|
||||
return CreateDrawingObject(dwg, dsz, cx || cy ? GetRatioSize(dsz, cx, cy) : dsz);
|
||||
}
|
||||
|
||||
Size RichObjectTypeDrawingCls::GetPixelSize(const Value& data) const
|
||||
{
|
||||
if(IsTypeRaw<Data>(data))
|
||||
return ValueTo<Data>(data).drawing.GetSize(); // dot_size; TRC 08/04/04
|
||||
return Size(0, 0);
|
||||
}
|
||||
|
||||
Size RichObjectTypeDrawingCls::GetPhysicalSize(const Value& data) const
|
||||
{
|
||||
if(IsTypeRaw<Data>(data))
|
||||
return ValueTo<Data>(data).dot_size;
|
||||
return Size(0, 0);
|
||||
}
|
||||
|
||||
Value RichObjectTypeDrawingCls::Read(const String& s) const
|
||||
{
|
||||
Data data;
|
||||
StringStream ss(s);
|
||||
ss % data;
|
||||
if(ss.IsError())
|
||||
return Value();
|
||||
return RawToValue(data);
|
||||
}
|
||||
|
||||
String RichObjectTypeDrawingCls::Write(const Value& v) const
|
||||
{
|
||||
if(IsTypeRaw<Data>(v))
|
||||
{
|
||||
StringStream ss;
|
||||
ss % const_cast<Data&>(ValueTo<Data>(v));
|
||||
return ss;
|
||||
}
|
||||
return Null;
|
||||
}
|
||||
|
||||
void RichObjectTypeDrawingCls::Paint(const Value& data, Draw& w, Size sz) const
|
||||
{
|
||||
w.DrawRect(sz, White);
|
||||
if(IsTypeRaw<Data>(data))
|
||||
w.DrawDrawing(Rect(sz), ValueTo<Data>(data).drawing);
|
||||
}
|
||||
|
||||
INITBLOCK {
|
||||
RichObject::Register("Drawing", &Single<RichObjectTypeDrawingCls>());
|
||||
};
|
||||
|
||||
struct RichObjectTypePNGCls : public RichObjectType
|
||||
{
|
||||
virtual String GetTypeName(const Value&) const;
|
||||
virtual Size GetPhysicalSize(const Value& data) const;
|
||||
virtual Size GetPixelSize(const Value& data) const;
|
||||
virtual void Paint(const Value& data, Draw& w, Size sz) const;
|
||||
virtual Value Read(const String& s) const;
|
||||
virtual String Write(const Value& v) const;
|
||||
};
|
||||
|
||||
RichObjectType *RichObjectTypePNG() { return &Single<RichObjectTypePNGCls>(); }
|
||||
|
||||
String RichObjectTypePNGCls::GetTypeName(const Value&) const
|
||||
{
|
||||
return "PING";
|
||||
}
|
||||
|
||||
RichObject CreatePNGObject(const Image& img, Size dot_size, Size out_size)
|
||||
{
|
||||
RichObject obj(RichObjectTypePNG(), PNGEncoder().SaveString(img));
|
||||
if(!IsNull(out_size))
|
||||
obj.SetSize(out_size);
|
||||
return obj;
|
||||
}
|
||||
|
||||
RichObject CreatePNGObject(const Image& img, int cx, int cy)
|
||||
{
|
||||
Size dsz = img.GetSize();
|
||||
return CreatePNGObject(img, dsz, cx || cy ? GetRatioSize(dsz, cx, cy) : dsz);
|
||||
}
|
||||
|
||||
Size RichObjectTypePNGCls::GetPixelSize(const Value& data) const
|
||||
{
|
||||
if(IsString(data)) {
|
||||
StringStream strm(data);
|
||||
One<StreamRaster> ras = StreamRaster::OpenAny(strm);
|
||||
if(!!ras)
|
||||
return ras->GetSize();
|
||||
}
|
||||
return Size(0, 0);
|
||||
}
|
||||
|
||||
Size RichObjectTypePNGCls::GetPhysicalSize(const Value& data) const
|
||||
{
|
||||
if(IsString(data)) {
|
||||
StringStream strm(data);
|
||||
One<StreamRaster> ras = StreamRaster::OpenAny(strm);
|
||||
if(!!ras)
|
||||
return ras->GetInfo().dots;
|
||||
}
|
||||
return Size(0, 0);
|
||||
}
|
||||
|
||||
Value RichObjectTypePNGCls::Read(const String& s) const
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
String RichObjectTypePNGCls::Write(const Value& v) const
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
void RichObjectTypePNGCls::Paint(const Value& data, Draw& w, Size sz) const
|
||||
{
|
||||
if(IsString(data)) {
|
||||
StringStream strm(data);
|
||||
One<StreamRaster> ras = StreamRaster::OpenAny(strm);
|
||||
if(!!ras) {
|
||||
w.DrawRect(sz, White);
|
||||
w.DrawImage(Rect(sz), ras->GetImage());
|
||||
return;
|
||||
}
|
||||
}
|
||||
w.DrawRect(sz, LtRed());
|
||||
}
|
||||
|
||||
INITBLOCK {
|
||||
RichObject::Register("PING", &Single<RichObjectTypePNGCls>());
|
||||
};
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
294
uppdev/RichTextP/Para.h
Normal file
294
uppdev/RichTextP/Para.h
Normal file
|
|
@ -0,0 +1,294 @@
|
|||
struct RichCaret;
|
||||
struct RichPos;
|
||||
|
||||
struct RichPara {
|
||||
enum Code {
|
||||
NONE,
|
||||
|
||||
INDEXENTRY = 2,
|
||||
FIELD = 3,
|
||||
FACE = 4,
|
||||
HEIGHT = 5,
|
||||
LANGUAGE = 6,
|
||||
INK = 7,
|
||||
PAPER = 8,
|
||||
|
||||
TAB = 9, // placeholder
|
||||
|
||||
LINK = 10,
|
||||
SSCRIPT = 11,
|
||||
|
||||
BOLD0 = 12,
|
||||
BOLD1 = 13,
|
||||
BOLDS = 14,
|
||||
ITALIC0 = 15,
|
||||
ITALIC1 = 16,
|
||||
ITALICS = 17,
|
||||
UNDERLINE0 = 18,
|
||||
UNDERLINE1 = 19,
|
||||
UNDERLINES = 20,
|
||||
CAPITALS0 = 21,
|
||||
CAPITALS1 = 22,
|
||||
CAPITALSS = 23,
|
||||
STRIKEOUT0 = 24,
|
||||
STRIKEOUT1 = 25,
|
||||
STRIKEOUTS = 26,
|
||||
DASHED0 = 27,
|
||||
DASHED1 = 28,
|
||||
DASHEDS = 29,
|
||||
|
||||
EXT = 30,
|
||||
|
||||
OBJECT = 31
|
||||
};
|
||||
|
||||
enum ExtCode {
|
||||
NONAA0 = 1,
|
||||
NONAA1 = 2,
|
||||
NONAAS = 3,
|
||||
};
|
||||
|
||||
enum BULLET_STYLE {
|
||||
BULLET_NONE,
|
||||
BULLET_ROUND,
|
||||
BULLET_ROUNDWHITE,
|
||||
BULLET_BOX,
|
||||
BULLET_BOXWHITE,
|
||||
BULLET_TEXT
|
||||
};
|
||||
|
||||
enum NUMBER_STYLE {
|
||||
NUMBER_NONE,
|
||||
NUMBER_1,
|
||||
NUMBER_0,
|
||||
NUMBER_a,
|
||||
NUMBER_A,
|
||||
NUMBER_i,
|
||||
NUMBER_I,
|
||||
};
|
||||
|
||||
enum LINESPACING {
|
||||
LSP10 = 0,
|
||||
LSP15 = -1,
|
||||
LSP20 = -2,
|
||||
};
|
||||
|
||||
struct CharFormat : public Font {
|
||||
int language;
|
||||
Color ink, paper;
|
||||
String link;
|
||||
WString indexentry;
|
||||
dword sscript:2;
|
||||
bool capitals;
|
||||
bool dashed;
|
||||
|
||||
#ifdef _DEBUG
|
||||
String ToString() const;
|
||||
#endif
|
||||
|
||||
CharFormat();
|
||||
};
|
||||
|
||||
struct Tab : Moveable<Tab> {
|
||||
int pos;
|
||||
byte align;
|
||||
byte fillchar;
|
||||
|
||||
Tab() { align = ALIGN_LEFT; pos = 0; fillchar = 0; }
|
||||
};
|
||||
|
||||
struct NumberFormat {
|
||||
String before_number, after_number;
|
||||
bool reset_number;
|
||||
byte number[8];
|
||||
|
||||
bool IsNumbered() const;
|
||||
int GetNumberLevel() const;
|
||||
};
|
||||
|
||||
struct Format : NumberFormat, CharFormat {
|
||||
int align;
|
||||
int ruler, before, lm, indent, rm, after;
|
||||
Color rulerink;
|
||||
int tabsize;
|
||||
int bullet;
|
||||
int linespacing;
|
||||
bool newpage, keep, keepnext, orphan;
|
||||
WithDeepCopy< Vector<Tab> > tab;
|
||||
String label;
|
||||
Uuid styleid;
|
||||
|
||||
void SortTabs();
|
||||
|
||||
#ifdef _DEBUG
|
||||
String ToString() const;
|
||||
#endif
|
||||
|
||||
Format();
|
||||
};
|
||||
|
||||
struct Number {
|
||||
int n[8];
|
||||
|
||||
String AsText(const NumberFormat& format) const;
|
||||
void TestReset(const NumberFormat& format);
|
||||
void Next(const NumberFormat& format);
|
||||
|
||||
Number();
|
||||
};
|
||||
|
||||
struct Part {
|
||||
RichObject object;
|
||||
WString text;
|
||||
CharFormat format;
|
||||
Id field;
|
||||
String fieldparam;
|
||||
WithDeepCopy< Array<Part> > fieldpart;
|
||||
|
||||
bool NonText() const { return object || field; }
|
||||
bool IsText() const { return !NonText(); }
|
||||
int GetLength() const { return object || field ? 1 : text.GetLength(); }
|
||||
};
|
||||
|
||||
struct FieldType {
|
||||
virtual Array<Part> Evaluate(const String& param, VectorMap<String, Value>& vars,
|
||||
const CharFormat& fmt) = 0;
|
||||
virtual void Menu(Bar& bar, String *param) const {}
|
||||
virtual void DefaultAction(String *param) const {}
|
||||
virtual ~FieldType() {}
|
||||
};
|
||||
|
||||
struct HeightInfo {
|
||||
int ascent;
|
||||
int descent;
|
||||
int external;
|
||||
int ydelta;
|
||||
const RichObject *object;
|
||||
|
||||
int Sum() const { return ascent + descent + external; }
|
||||
};
|
||||
|
||||
struct Line : public HeightInfo {
|
||||
int pos;
|
||||
int len;
|
||||
int ppos;
|
||||
int plen;
|
||||
int xpos;
|
||||
int cx;
|
||||
int objecti;
|
||||
bool withtabs;
|
||||
};
|
||||
|
||||
struct Lines {
|
||||
int len;
|
||||
int clen;
|
||||
int cx;
|
||||
Buffer<wchar> text;
|
||||
Buffer<byte> spell;
|
||||
Buffer<int> pos;
|
||||
Buffer<int> width;
|
||||
Buffer<HeightInfo> height;
|
||||
Buffer<const CharFormat *> format;
|
||||
Array<Line> line;
|
||||
Array<CharFormat> hformat;
|
||||
int first_indent;
|
||||
int next_indent;
|
||||
|
||||
|
||||
int GetCount() const { return line.GetCount(); }
|
||||
Line& operator[](int i) { return line[i]; }
|
||||
const Line& operator[](int i) const { return line[i]; }
|
||||
void Justify(const Format& format);
|
||||
int BodyHeight();
|
||||
};
|
||||
|
||||
static const VectorMap<Id, FieldType *>& fieldtype();
|
||||
static void Register(Id id, FieldType& ft) init_;
|
||||
|
||||
Format format;
|
||||
Array<Part> part;
|
||||
|
||||
static void Charformat(Stream& out, const CharFormat& o, const CharFormat& n,
|
||||
const CharFormat& s);
|
||||
|
||||
void Cat(const WString& s, const CharFormat& f);
|
||||
void Cat(const char *s, const CharFormat& f);
|
||||
void Cat(const RichObject& o, const CharFormat& f);
|
||||
void Cat(Id fieldtype, const String& param, const CharFormat& f);
|
||||
|
||||
int GetLength() const;
|
||||
int GetCount() const { return part.GetCount(); }
|
||||
bool IsEmpty() const;
|
||||
String Pack(const Format& style, Array<RichObject>& obj) const;
|
||||
void Unpack(const String& s, const Array<RichObject>& obj, const Format& style);
|
||||
|
||||
void ApplyStyle(const Format& newstyle);
|
||||
|
||||
Part& operator[](int i) { return part[i]; }
|
||||
const Part& operator[](int i) const { return part[i]; }
|
||||
int FindPart(int& pos) const;
|
||||
void Trim(int pos);
|
||||
void Mid(int pos);
|
||||
void Append(const RichPara& p) { part.Append(p.part); }
|
||||
|
||||
void GetRichPos(RichPos& rp, int pos) const;
|
||||
|
||||
Lines FormatLines(int cx) const;
|
||||
void Paint(PageDraw& pw, const Rect& page, PageY py, const PaintInfo& pi,
|
||||
const Number& n, const Bits& spellerrors,
|
||||
int nbefore, int nline) const;
|
||||
RichCaret GetCaret(int pos, const Rect& page, PageY py, int nbefore, int nline) const;
|
||||
int GetPos(int x, PageY y, const Rect& page, PageY py, int nbefore, int nline) const;
|
||||
void GatherLabels(Vector<RichValPos>& info, const Rect& page, PageY py,
|
||||
int pos, int nbefore, int nline) const;
|
||||
void GatherIndexes(Vector<RichValPos>& info, const Rect& page, PageY py,
|
||||
int pos, int nbefore, int nline) const;
|
||||
int GetVertMove(int pos, int gx, const Rect& page, int dir) const;
|
||||
|
||||
WString GetText() const;
|
||||
|
||||
bool HasPos() const;
|
||||
|
||||
bool EvaluateFields(VectorMap<String, Value>& vars);
|
||||
|
||||
void operator<<=(const RichPara& p) { format = p.format; part <<= p.part; }
|
||||
|
||||
#ifdef _DEBUG
|
||||
void Dump();
|
||||
#endif
|
||||
|
||||
void ApplyZoom(Zoom z);
|
||||
|
||||
private:
|
||||
Tab GetNextTab(int pos) const;
|
||||
void Smh(Lines& lines, HeightInfo *th, int cx) const;
|
||||
Lines Begin(const Rect& page, PageY& py, int nbefore, int nline) const;
|
||||
bool BreaksPage(PageY py, const Lines& pl, int i, const Rect& page) const;
|
||||
void PackParts(Stream& out, const CharFormat& chrstyle,
|
||||
const Array<Part>& part, CharFormat& cf,
|
||||
Array<RichObject>& obj) const;
|
||||
void UnpackParts(Stream& in, const CharFormat& chrstyle,
|
||||
Array<Part>& part, const Array<RichObject>& obj, int& oi);
|
||||
static void Flush(Draw& draw, const PaintInfo& pi, wchar *text, const CharFormat **i0,
|
||||
int *wd, int pos, int len, int x0, int x, int y0, int y, int linecy,
|
||||
int lineascent, Zoom z, bool highlight);
|
||||
int PosInLine(int x, const Rect& page, const Lines& pl, int lni) const;
|
||||
struct StorePart;
|
||||
};
|
||||
|
||||
inline bool operator==(const RichPara::Tab& a, const RichPara::Tab& b) {
|
||||
return a.pos == b.pos && a.align == b.align && a.fillchar == b.fillchar;
|
||||
}
|
||||
|
||||
bool operator==(const Vector<RichPara::Tab>& a, const Vector<RichPara::Tab>& b);
|
||||
|
||||
inline
|
||||
bool operator!=(const Vector<RichPara::Tab>& a, const Vector<RichPara::Tab>& b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
bool NumberingDiffers(const RichPara::Format& fmt1, const RichPara::Format& fmt2);
|
||||
|
||||
void Sort(Vector<RichPara::Tab>& tab);
|
||||
|
||||
void operator*=(RichPara::Format& fmt, Zoom z);
|
||||
772
uppdev/RichTextP/ParaData.cpp
Normal file
772
uppdev/RichTextP/ParaData.cpp
Normal file
|
|
@ -0,0 +1,772 @@
|
|||
#include "RichText.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
PaintInfo::PaintInfo()
|
||||
{
|
||||
sell = selh = 0;
|
||||
tablesel = 0;
|
||||
top = PageY(0, 0);
|
||||
bottom = PageY(INT_MAX, INT_MAX);
|
||||
hyperlink = SColorMark();
|
||||
usecache = false;
|
||||
sizetracking = false;
|
||||
showcodes = Null;
|
||||
spellingchecker = NULL;
|
||||
highlightpara = -1;
|
||||
highlight = Yellow();
|
||||
indexentry = LtGreen();
|
||||
coloroverride = false;
|
||||
}
|
||||
|
||||
String RichPara::Number::AsText(const RichPara::NumberFormat& format) const
|
||||
{
|
||||
String result;
|
||||
for(int i = 0; i < 8; i++)
|
||||
if(format.number[i]) {
|
||||
if(result.GetLength())
|
||||
result.Cat('.');
|
||||
int q = n[i];
|
||||
switch(format.number[i]) {
|
||||
case NUMBER_1:
|
||||
result << AsString(q);
|
||||
break;
|
||||
case NUMBER_0:
|
||||
result << AsString(q - 1);
|
||||
break;
|
||||
case NUMBER_a:
|
||||
result << FormatIntAlpha(q, false);
|
||||
break;
|
||||
case NUMBER_A:
|
||||
result << FormatIntAlpha(q, true);
|
||||
break;
|
||||
case NUMBER_i:
|
||||
result << FormatIntRoman(q, false);
|
||||
break;
|
||||
case NUMBER_I:
|
||||
result << FormatIntRoman(q, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return format.before_number + result + format.after_number;
|
||||
}
|
||||
|
||||
void RichPara::Number::TestReset(const RichPara::NumberFormat& fmt)
|
||||
{
|
||||
if(fmt.reset_number) {
|
||||
bool done = false;
|
||||
for(int i = 7; i >= 0; --i)
|
||||
if(fmt.number[i]) {
|
||||
n[i] = 0;
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
if(!done && !IsNull(n[0]))
|
||||
n[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void RichPara::Number::Next(const RichPara::NumberFormat& fmt)
|
||||
{
|
||||
for(int i = 7; i >= 0; --i)
|
||||
if(fmt.number[i]) {
|
||||
n[i++]++;
|
||||
while(i <= 7)
|
||||
n[i++] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RichPara::Number::Number()
|
||||
{
|
||||
memset(n, 0, sizeof(n));
|
||||
}
|
||||
|
||||
bool RichPara::NumberFormat::IsNumbered() const
|
||||
{
|
||||
if(before_number.GetLength() || after_number.GetLength())
|
||||
return true;
|
||||
for(int i = 0; i < 8; i++)
|
||||
if(number[i])
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int RichPara::NumberFormat::GetNumberLevel() const
|
||||
{
|
||||
for(int i = 7; i >= 0; i--)
|
||||
if(number[i])
|
||||
return i + 1;
|
||||
if(before_number.GetLength() || after_number.GetLength())
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool NumberingDiffers(const RichPara::Format& fmt1, const RichPara::Format& fmt2)
|
||||
{
|
||||
return fmt1.before_number != fmt2.before_number ||
|
||||
fmt1.after_number != fmt2.after_number ||
|
||||
fmt1.reset_number != fmt2.reset_number ||
|
||||
memcmp(fmt1.number, fmt2.number, sizeof(fmt1.number));
|
||||
}
|
||||
|
||||
bool operator==(const Vector<RichPara::Tab>& a, const Vector<RichPara::Tab>& b)
|
||||
{
|
||||
if(a.GetCount() != b.GetCount()) return false;
|
||||
for(int i = 0; i < a.GetCount(); i++)
|
||||
if(a[i].pos != b[i].pos || a[i].align != b[i].align || a[i].fillchar != b[i].fillchar)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
RichPara::CharFormat::CharFormat()
|
||||
{
|
||||
(Font &)*this = Arial(100);
|
||||
ink = Black;
|
||||
paper = Null;
|
||||
language = 0;
|
||||
link = Null;
|
||||
sscript = 0;
|
||||
capitals = dashed = false;
|
||||
}
|
||||
|
||||
RichPara::Format::Format()
|
||||
{
|
||||
align = ALIGN_LEFT;
|
||||
ruler = before = lm = rm = indent = after = 0;
|
||||
rulerink = Black;
|
||||
bullet = 0;
|
||||
keep = newpage = keepnext = orphan = false;
|
||||
tabsize = 296;
|
||||
memset(number, 0, sizeof(number));
|
||||
reset_number = false;
|
||||
linespacing = 0;
|
||||
tab.Clear();
|
||||
styleid = RichStyle::GetDefaultId();
|
||||
}
|
||||
|
||||
void RichPara::Charformat(Stream& out, const RichPara::CharFormat& o,
|
||||
const RichPara::CharFormat& n, const RichPara::CharFormat& s)
|
||||
{
|
||||
if(o.IsBold() != n.IsBold())
|
||||
out.Put(n.IsBold() == s.IsBold() ? BOLDS : BOLD0 + n.IsBold());
|
||||
if(o.IsItalic() != n.IsItalic())
|
||||
out.Put(n.IsItalic() == s.IsItalic() ? ITALICS
|
||||
: ITALIC0 + n.IsItalic());
|
||||
if(o.IsUnderline() != n.IsUnderline())
|
||||
out.Put(n.IsUnderline() == s.IsUnderline() ? UNDERLINES
|
||||
: UNDERLINE0 + n.IsUnderline());
|
||||
if(o.IsStrikeout() != n.IsStrikeout())
|
||||
out.Put(n.IsStrikeout() == s.IsStrikeout() ? STRIKEOUTS
|
||||
: STRIKEOUT0 + n.IsStrikeout());
|
||||
if(o.IsNonAntiAliased() != n.IsNonAntiAliased()) {
|
||||
out.Put(EXT);
|
||||
out.Put(n.IsNonAntiAliased() == s.IsNonAntiAliased() ? NONAAS
|
||||
: NONAA0 + n.IsNonAntiAliased());
|
||||
}
|
||||
if(o.capitals != n.capitals)
|
||||
out.Put(n.capitals == s.capitals ? CAPITALSS
|
||||
: CAPITALS0 + n.capitals);
|
||||
if(o.dashed != n.dashed)
|
||||
out.Put(n.dashed == s.dashed ? DASHEDS
|
||||
: DASHED0 + n.dashed);
|
||||
if(o.sscript != n.sscript) {
|
||||
out.Put(SSCRIPT);
|
||||
out.Put(n.sscript);
|
||||
}
|
||||
if(o.GetFace() != n.GetFace()) {
|
||||
out.Put(FACE);
|
||||
out.Put16(n.GetFace() == s.GetFace() ? 0xffff : n.GetFace());
|
||||
}
|
||||
if(o.GetHeight() != n.GetHeight()) {
|
||||
out.Put(HEIGHT);
|
||||
out.Put16(n.GetHeight() == s.GetHeight() ? 0xffff : n.GetHeight());
|
||||
}
|
||||
if(o.link != n.link) {
|
||||
out.Put(LINK);
|
||||
String s = n.link;
|
||||
out % s;
|
||||
}
|
||||
if(o.ink != n.ink) {
|
||||
out.Put(INK);
|
||||
Color c = n.ink;
|
||||
c.Serialize(out);
|
||||
}
|
||||
if(o.paper != n.paper) {
|
||||
out.Put(PAPER);
|
||||
Color c = n.paper;
|
||||
c.Serialize(out);
|
||||
}
|
||||
if(o.language != n.language) {
|
||||
out.Put(LANGUAGE);
|
||||
out.Put32(n.language);
|
||||
}
|
||||
if(o.indexentry != n.indexentry) {
|
||||
out.Put(INDEXENTRY);
|
||||
WString s = n.indexentry;
|
||||
out % s;
|
||||
}
|
||||
}
|
||||
|
||||
void RichPara::Cat(const WString& s, const RichPara::CharFormat& f)
|
||||
{
|
||||
part.Add();
|
||||
part.Top().text = s;
|
||||
part.Top().format = f;
|
||||
}
|
||||
|
||||
void RichPara::Cat(const char *s, const CharFormat& f)
|
||||
{
|
||||
Cat(WString(s), f);
|
||||
}
|
||||
|
||||
void RichPara::Cat(const RichObject& o, const RichPara::CharFormat& f)
|
||||
{
|
||||
part.Add();
|
||||
part.Top().object = o;
|
||||
part.Top().format = f;
|
||||
}
|
||||
|
||||
void RichPara::Cat(Id field, const String& param, const RichPara::CharFormat& f)
|
||||
{
|
||||
Part& p = part.Add();
|
||||
p.field = field;
|
||||
p.fieldparam = param;
|
||||
p.format = f;
|
||||
VectorMap<String, Value> dummy;
|
||||
FieldType *ft = fieldtype().Get(field, NULL);
|
||||
if(ft)
|
||||
p.fieldpart ^= ft->Evaluate(param, dummy, f);
|
||||
}
|
||||
|
||||
struct TabLess {
|
||||
bool operator () (const RichPara::Tab& a, const RichPara::Tab& b) const {
|
||||
return a.pos == b.pos ? a.align < b.align : a.pos < b.pos;
|
||||
}
|
||||
};
|
||||
|
||||
void RichPara::Format::SortTabs()
|
||||
{
|
||||
Sort(tab, TabLess());
|
||||
}
|
||||
|
||||
void RichPara::PackParts(Stream& out, const RichPara::CharFormat& chrstyle,
|
||||
const Array<RichPara::Part>& part, CharFormat& cf,
|
||||
Array<RichObject>& obj) const
|
||||
{
|
||||
for(int i = 0; i < part.GetCount(); i++) {
|
||||
const Part& p = part[i];
|
||||
Charformat(out, cf, p.format, chrstyle);
|
||||
cf = p.format;
|
||||
if(p.field) {
|
||||
out.Put(FIELD);
|
||||
out.Put32(p.field.AsNdx());
|
||||
String s = p.fieldparam;
|
||||
out % s;
|
||||
StringStream oout;
|
||||
CharFormat subf = cf;
|
||||
PackParts(oout, chrstyle, p.fieldpart, subf, obj);
|
||||
s = oout;
|
||||
out % s;
|
||||
}
|
||||
else
|
||||
if(p.object) {
|
||||
obj.Add(p.object);
|
||||
out.Put(OBJECT);
|
||||
}
|
||||
else {
|
||||
String x = ToUtf8(p.text);
|
||||
out.Put(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String RichPara::Pack(const RichPara::Format& style, Array<RichObject>& obj) const
|
||||
{
|
||||
StringStream out;
|
||||
dword pattr = 0;
|
||||
if(format.align != style.align) pattr |= 1;
|
||||
if(format.before != style.before) pattr |= 2;
|
||||
if(format.lm != style.lm) pattr |= 4;
|
||||
if(format.indent != style.indent) pattr |= 8;
|
||||
if(format.rm != style.rm) pattr |= 0x10;
|
||||
if(format.after != style.after) pattr |= 0x20;
|
||||
if(format.bullet != style.bullet) pattr |= 0x40;
|
||||
if(format.keep != style.keep) pattr |= 0x80;
|
||||
if(format.newpage != style.newpage) pattr |= 0x100;
|
||||
if(format.tabsize != style.tabsize) pattr |= 0x200;
|
||||
if(!IsNull(format.label)) pattr |= 0x400;
|
||||
if(format.keepnext != style.keepnext) pattr |= 0x800;
|
||||
if(format.orphan != style.orphan) pattr |= 0x1000;
|
||||
if(NumberingDiffers(format, style)) pattr |= 0x2000;
|
||||
if(format.linespacing != style.linespacing) pattr |= 0x4000;
|
||||
if(format.tab != style.tab) pattr |= 0x8000;
|
||||
if(format.ruler != style.ruler) pattr |= 0x10000;
|
||||
if(format.rulerink != style.rulerink) pattr |= 0x20000;
|
||||
out.Put32(pattr);
|
||||
if(pattr & 1) out.Put16(format.align);
|
||||
if(pattr & 2) out.Put16(format.before);
|
||||
if(pattr & 4) out.Put16(format.lm);
|
||||
if(pattr & 8) out.Put16(format.indent);
|
||||
if(pattr & 0x10) out.Put16(format.rm);
|
||||
if(pattr & 0x20) out.Put16(format.after);
|
||||
if(pattr & 0x40) out.Put16(format.bullet);
|
||||
if(pattr & 0x80) out.Put(format.keep);
|
||||
if(pattr & 0x100) out.Put(format.newpage);
|
||||
if(pattr & 0x200) out.Put16(format.tabsize);
|
||||
if(pattr & 0x400) { String t = format.label; out % t; }
|
||||
if(pattr & 0x800) out.Put(format.keepnext);
|
||||
if(pattr & 0x1000) out.Put(format.orphan);
|
||||
if(pattr & 0x2000) {
|
||||
String b = format.before_number, a = format.after_number;
|
||||
out % b % a;
|
||||
out.Put(format.reset_number);
|
||||
out.Put(format.number, 8);
|
||||
}
|
||||
if(pattr & 0x4000)
|
||||
out.Put(format.linespacing);
|
||||
if(pattr & 0x8000) {
|
||||
int c = 0;
|
||||
int i;
|
||||
for(i = 0; i < format.tab.GetCount(); i++) {
|
||||
if(!IsNull(format.tab[i].pos))
|
||||
c++;
|
||||
}
|
||||
out.Put16(c);
|
||||
for(i = 0; i < format.tab.GetCount(); i++) {
|
||||
const RichPara::Tab& w = format.tab[i];
|
||||
if(!IsNull(w.pos)) {
|
||||
out.Put32(w.pos);
|
||||
out.Put(w.align);
|
||||
out.Put(w.fillchar);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(pattr & 0x10000)
|
||||
out.Put16(format.ruler);
|
||||
if(pattr & 0x20000) {
|
||||
Color c = format.rulerink;
|
||||
c.Serialize(out);
|
||||
}
|
||||
obj.Clear();
|
||||
CharFormat cf = style;
|
||||
if(part.GetCount())
|
||||
PackParts(out, style, part, cf, obj);
|
||||
else
|
||||
Charformat(out, style, format, cf);
|
||||
String r = out;
|
||||
r.Shrink();
|
||||
return r;
|
||||
}
|
||||
|
||||
void RichPara::UnpackParts(Stream& in, const RichPara::CharFormat& chrstyle,
|
||||
Array<RichPara::Part>& part, const Array<RichObject>& obj,
|
||||
int& oi) {
|
||||
part.Add();
|
||||
part.Top().format = format;
|
||||
int c;
|
||||
while((c = in.Term()) >= 0)
|
||||
if(c < 31 && c != 9 && c != FIELD) {
|
||||
do
|
||||
switch(in.Get()) {
|
||||
case BOLD0:
|
||||
format.NoBold();
|
||||
break;
|
||||
case BOLD1:
|
||||
format.Bold();
|
||||
break;
|
||||
case BOLDS:
|
||||
format.Bold(chrstyle.IsBold());
|
||||
break;
|
||||
case ITALIC0:
|
||||
format.NoItalic();
|
||||
break;
|
||||
case ITALIC1:
|
||||
format.Italic();
|
||||
break;
|
||||
case ITALICS:
|
||||
format.Italic(chrstyle.IsItalic());
|
||||
break;
|
||||
case UNDERLINE0:
|
||||
format.NoUnderline();
|
||||
break;
|
||||
case UNDERLINE1:
|
||||
format.Underline();
|
||||
break;
|
||||
case UNDERLINES:
|
||||
format.Underline(chrstyle.IsUnderline());
|
||||
break;
|
||||
case STRIKEOUT0:
|
||||
format.NoStrikeout();
|
||||
break;
|
||||
case STRIKEOUT1:
|
||||
format.Strikeout();
|
||||
break;
|
||||
case STRIKEOUTS:
|
||||
format.Strikeout(chrstyle.IsStrikeout());
|
||||
break;
|
||||
case CAPITALS0:
|
||||
format.capitals = false;
|
||||
break;
|
||||
case CAPITALS1:
|
||||
format.capitals = true;
|
||||
break;
|
||||
case CAPITALSS:
|
||||
format.capitals = chrstyle.capitals;
|
||||
break;
|
||||
case DASHED0:
|
||||
format.dashed = false;
|
||||
break;
|
||||
case DASHED1:
|
||||
format.dashed = true;
|
||||
break;
|
||||
case DASHEDS:
|
||||
format.dashed = chrstyle.dashed;
|
||||
break;
|
||||
case SSCRIPT:
|
||||
format.sscript = in.Get();
|
||||
if(format.sscript == 3)
|
||||
format.sscript = chrstyle.sscript;
|
||||
break;
|
||||
case FACE:
|
||||
c = in.Get16();
|
||||
format.Face(c == 0xffff ? chrstyle.GetFace() : c);
|
||||
break;
|
||||
case HEIGHT:
|
||||
c = in.Get16();
|
||||
format.Height(c == 0xffff ? chrstyle.GetHeight() : c);
|
||||
break;
|
||||
case LINK:
|
||||
in % format.link;
|
||||
break;
|
||||
case INDEXENTRY:
|
||||
in % format.indexentry;
|
||||
break;
|
||||
case INK:
|
||||
in % format.ink;
|
||||
break;
|
||||
case PAPER:
|
||||
in % format.paper;
|
||||
break;
|
||||
case LANGUAGE:
|
||||
format.language = in.Get32();
|
||||
break;
|
||||
case EXT:
|
||||
switch(in.Get()) {
|
||||
case NONAA0:
|
||||
format.NonAntiAliased(false);
|
||||
break;
|
||||
case NONAA1:
|
||||
format.NonAntiAliased(true);
|
||||
break;
|
||||
case NONAAS:
|
||||
format.NonAntiAliased(chrstyle.IsNonAntiAliased());
|
||||
break;
|
||||
}
|
||||
}
|
||||
while((c = in.Term()) < 31 && c != 9 && c != FIELD && c >= 0);
|
||||
if(part.Top().text.GetLength())
|
||||
part.Add();
|
||||
part.Top().format = format;
|
||||
}
|
||||
else
|
||||
if(in.Term() == FIELD) {
|
||||
RichPara::Format pformat = format;
|
||||
if(part.Top().text.GetLength()) {
|
||||
part.Add();
|
||||
part.Top().format = pformat;
|
||||
}
|
||||
in.Get();
|
||||
Part& p = part.Top();
|
||||
p.field = Id(in.Get32());
|
||||
in % p.fieldparam;
|
||||
String s;
|
||||
in % s;
|
||||
StringStream sn(s);
|
||||
UnpackParts(sn, chrstyle, p.fieldpart, obj, oi);
|
||||
part.Add();
|
||||
part.Top().format = format = pformat;
|
||||
}
|
||||
else
|
||||
if(in.Term() == OBJECT) {
|
||||
if(part.Top().text.GetLength()) {
|
||||
part.Add();
|
||||
part.Top().format = format;
|
||||
}
|
||||
part.Top().object = obj[oi++];
|
||||
part.Top().format = format;
|
||||
part.Add();
|
||||
part.Top().format = format;
|
||||
in.Get();
|
||||
}
|
||||
else
|
||||
part.Top().text.Cat(in.GetUtf8());
|
||||
if(part.Top().text.GetLength() == 0 && part.Top().IsText())
|
||||
part.Drop();
|
||||
}
|
||||
|
||||
void RichPara::Unpack(const String& data, const Array<RichObject>& obj,
|
||||
const RichPara::Format& style)
|
||||
{
|
||||
part.Clear();
|
||||
StringStream in(data);
|
||||
|
||||
format = style;
|
||||
|
||||
dword pattr = in.Get32();
|
||||
|
||||
if(pattr & 1) format.align = in.Get16();
|
||||
if(pattr & 2) format.before = in.Get16();
|
||||
if(pattr & 4) format.lm = in.Get16();
|
||||
if(pattr & 8) format.indent = in.Get16();
|
||||
if(pattr & 0x10) format.rm = in.Get16();
|
||||
if(pattr & 0x20) format.after = in.Get16();
|
||||
if(pattr & 0x40) format.bullet = in.Get16();
|
||||
if(pattr & 0x80) format.keep = in.Get();
|
||||
if(pattr & 0x100) format.newpage = in.Get();
|
||||
if(pattr & 0x200) format.tabsize = in.Get16();
|
||||
if(pattr & 0x400) in % format.label;
|
||||
if(pattr & 0x800) format.keepnext = in.Get();
|
||||
if(pattr & 0x1000) format.orphan = in.Get();
|
||||
if(pattr & 0x2000) {
|
||||
in % format.before_number;
|
||||
in % format.after_number;
|
||||
format.reset_number = in.Get();
|
||||
in.Get(format.number, 8);
|
||||
}
|
||||
if(pattr & 0x4000) {
|
||||
format.linespacing = (int8)in.Get();
|
||||
}
|
||||
if(pattr & 0x8000) {
|
||||
format.tab.Clear();
|
||||
int n = in.Get16();
|
||||
format.tab.Reserve(n);
|
||||
for(int i = 0; i < n; i++) {
|
||||
RichPara::Tab& w = format.tab.Add();
|
||||
w.pos = in.Get32();
|
||||
w.align = in.Get();
|
||||
w.fillchar = in.Get();
|
||||
}
|
||||
}
|
||||
if(pattr & 0x10000)
|
||||
format.ruler = in.Get16();
|
||||
if(pattr & 0x20000)
|
||||
format.rulerink.Serialize(in);
|
||||
part.Clear();
|
||||
int oi = 0;
|
||||
UnpackParts(in, style, part, obj, oi);
|
||||
}
|
||||
|
||||
bool RichPara::IsEmpty() const
|
||||
{
|
||||
return part.GetCount() == 0 || GetLength() == 0;
|
||||
}
|
||||
|
||||
int RichPara::GetLength() const
|
||||
{
|
||||
int n = 0;
|
||||
for(int i = 0; i < part.GetCount(); i++)
|
||||
n += part[i].GetLength();
|
||||
return n;
|
||||
}
|
||||
|
||||
WString RichPara::GetText() const
|
||||
{
|
||||
WString r;
|
||||
for(int i = 0; i < part.GetCount(); i++)
|
||||
if(part[i].IsText())
|
||||
r.Cat(part[i].text);
|
||||
else
|
||||
r.Cat(127);
|
||||
return r;
|
||||
}
|
||||
|
||||
typedef VectorMap<Id, RichPara::FieldType *> FieldTypeMap;
|
||||
GLOBAL_VAR(FieldTypeMap, fieldtype0)
|
||||
|
||||
const VectorMap<Id, RichPara::FieldType *>& RichPara::fieldtype()
|
||||
{
|
||||
return fieldtype0();
|
||||
}
|
||||
|
||||
void RichPara::Register(Id id, FieldType& ft) init_
|
||||
{
|
||||
AssertST();
|
||||
fieldtype0().GetAdd(id, &ft);
|
||||
}
|
||||
|
||||
bool RichPara::EvaluateFields(VectorMap<String, Value>& vars)
|
||||
{
|
||||
bool b = false;
|
||||
for(int i = 0; i < GetCount(); i++) {
|
||||
Part& p = part[i];
|
||||
if(p.field) {
|
||||
FieldType *f = fieldtype().Get(p.field, NULL);
|
||||
if(f) {
|
||||
p.fieldpart ^= f->Evaluate(p.fieldparam, vars, p.format);
|
||||
b = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
bool RichPara::HasPos() const
|
||||
{
|
||||
if(!format.label.IsEmpty()) return true;
|
||||
for(int i = 0; i < part.GetCount(); i++)
|
||||
if(!part[i].format.indexentry.IsEmpty())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int RichPara::FindPart(int& pos) const
|
||||
{
|
||||
int pi = 0;
|
||||
while(pi < part.GetCount() && pos >= part[pi].GetLength()) {
|
||||
pos -= part[pi].GetLength();
|
||||
pi++;
|
||||
}
|
||||
return pi;
|
||||
}
|
||||
|
||||
void RichPara::Trim(int pos)
|
||||
{
|
||||
int i = FindPart(pos);
|
||||
if(pos) {
|
||||
ASSERT(part[i].IsText());
|
||||
part[i].text.Trim(pos);
|
||||
part.SetCount(i + 1);
|
||||
}
|
||||
else
|
||||
part.SetCount(i);
|
||||
}
|
||||
|
||||
void RichPara::Mid(int pos)
|
||||
{
|
||||
int i = FindPart(pos);
|
||||
part.Remove(0, i);
|
||||
if(pos) {
|
||||
ASSERT(part[0].IsText());
|
||||
part[0].text = part[0].text.Mid(pos);
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyCharStyle(RichPara::CharFormat& format, const RichPara::CharFormat& f0,
|
||||
const RichPara::CharFormat& newstyle) {
|
||||
if(format.IsBold() == f0.IsBold())
|
||||
format.Bold(newstyle.IsBold());
|
||||
if(format.IsUnderline() == f0.IsUnderline())
|
||||
format.Underline(newstyle.IsUnderline());
|
||||
if(format.IsItalic() == f0.IsItalic())
|
||||
format.Italic(newstyle.IsItalic());
|
||||
if(format.IsStrikeout() == f0.IsStrikeout())
|
||||
format.Strikeout(newstyle.IsStrikeout());
|
||||
if(format.IsNonAntiAliased() == f0.IsNonAntiAliased())
|
||||
format.NonAntiAliased(newstyle.IsNonAntiAliased());
|
||||
if(format.capitals == f0.capitals)
|
||||
format.capitals = newstyle.capitals;
|
||||
if(format.dashed == f0.dashed)
|
||||
format.dashed = newstyle.dashed;
|
||||
if(format.sscript == f0.sscript)
|
||||
format.sscript = newstyle.sscript;
|
||||
if(format.GetFace() == f0.GetFace())
|
||||
format.Face(newstyle.GetFace());
|
||||
if(format.GetHeight() == f0.GetHeight())
|
||||
format.Height(newstyle.GetHeight());
|
||||
if(format.ink == f0.ink)
|
||||
format.ink = newstyle.ink;
|
||||
if(format.paper == f0.paper)
|
||||
format.paper = newstyle.paper;
|
||||
}
|
||||
|
||||
void RichPara::ApplyStyle(const Format& newstyle)
|
||||
{
|
||||
CharFormat f0 = part.GetCount() ? part[0].format : format;
|
||||
for(int i = 0; i < part.GetCount(); i++)
|
||||
ApplyCharStyle(part[i].format, f0, newstyle);
|
||||
CharFormat h = format;
|
||||
ApplyCharStyle(h, f0, newstyle);
|
||||
format = newstyle;
|
||||
(CharFormat&)format = h;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
void RichPara::Dump()
|
||||
{
|
||||
LOG("RichPara dump" << LOG_BEGIN);
|
||||
LOG("RULER: " << format.ruler << " " << format.rulerink);
|
||||
LOG("BEFORE: " << format.before);
|
||||
LOG("INDENT: " << format.indent);
|
||||
LOG("LM: " << format.lm);
|
||||
LOG("RM: " << format.rm);
|
||||
LOG("AFTER: " << format.after);
|
||||
LOG("KEEP: " << format.keep);
|
||||
LOG("NEWPAGE: " << format.newpage);
|
||||
LOG("BULLET: " << format.bullet);
|
||||
int i;
|
||||
for(i = 0; i < format.tab.GetCount(); i++)
|
||||
LOG("TAB " << format.tab[i].pos << " : " << format.tab[i].align);
|
||||
for(i = 0; i < part.GetCount(); i++)
|
||||
LOG("Part[" << i << "] = \"" << part[i].text << "\" "
|
||||
<< part[i].format);
|
||||
LOG(LOG_END << "---------");
|
||||
}
|
||||
|
||||
|
||||
String RichPara::CharFormat::ToString() const
|
||||
{
|
||||
String out;
|
||||
out
|
||||
<< Font(*this)
|
||||
<< ", ink " << DumpColor(ink);
|
||||
if(!UPP::IsNull(paper))
|
||||
out << ", paper " << DumpColor(paper);
|
||||
switch(sscript)
|
||||
{
|
||||
case 0: break;
|
||||
case 1: out << ", superscript"; break;
|
||||
case 2: out << ", subscript"; break;
|
||||
default: out << ", sscript(" << (int)sscript << ")"; break;
|
||||
}
|
||||
out << ", lang " << DumpLanguage(language);
|
||||
if(!UPP::IsNull(link))
|
||||
out << ", link " << link;
|
||||
if(capitals)
|
||||
out << ", capitals";
|
||||
if(dashed)
|
||||
out << ", dashed";
|
||||
return out;
|
||||
}
|
||||
|
||||
String RichPara::Format::ToString() const
|
||||
{
|
||||
String out;
|
||||
if(!UPP::IsNull(label))
|
||||
out << "label <" << label << ">: ";
|
||||
out
|
||||
<< DumpAlign(align) << ", left " << lm << ", right " << rm
|
||||
<< ", indent " << indent << ", before " << before << ", after " << after
|
||||
<< ", tabsize " << tabsize << ", bullet " << bullet
|
||||
<< (newpage ? ", newpage" : "")
|
||||
<< (keep ? ", keep" : "")
|
||||
<< (keepnext ? ", keepnext" : "")
|
||||
<< (orphan ? ", orphan" : "");
|
||||
int i;
|
||||
for(i = 0; i < tab.GetCount(); i++)
|
||||
out << (i ? "\n" : ", ")
|
||||
<< "tab[" << i << "] = " << tab[i].pos << ", align " << DumpAlign(tab[i].align)
|
||||
<< ", fill " << FormatIntHex(tab[i].fillchar, 2);
|
||||
out << "\n";
|
||||
out << "before_number " << before_number << ", after_number " << after_number
|
||||
<< (reset_number ? ", reset_number" : "");
|
||||
for(i = 0; i < __countof(number); i++)
|
||||
if(number[i] != RichPara::NUMBER_NONE)
|
||||
out << " num[" << i << "] = " << (int)number[i];
|
||||
out << "\n";
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
587
uppdev/RichTextP/ParaPaint.cpp
Normal file
587
uppdev/RichTextP/ParaPaint.cpp
Normal file
|
|
@ -0,0 +1,587 @@
|
|||
#include "RichText.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#define IMAGECLASS RichTextImg
|
||||
#define IMAGEFILE <RichText/RichText.iml>
|
||||
#include <Draw/iml.h>
|
||||
|
||||
RichPara::Lines RichPara::Begin(const Rect& page, PageY& py, int nbefore, int nline) const
|
||||
{
|
||||
Lines pl = FormatLines(page.Width());
|
||||
int cy = format.ruler + format.before;
|
||||
if(format.keep || format.keepnext)
|
||||
cy += pl.BodyHeight();
|
||||
else
|
||||
cy += pl[0].Sum();
|
||||
int after = format.after;
|
||||
if(!format.keepnext)
|
||||
nbefore = nline = after = 0;
|
||||
if(page.Height() < 32000 &&
|
||||
(format.newpage || py.y + cy + after + nbefore + nline > page.bottom &&
|
||||
cy < page.Height())) {
|
||||
py.page++;
|
||||
py.y = page.top;
|
||||
}
|
||||
py.y += format.before + format.ruler;
|
||||
pl.Justify(format);
|
||||
return pl;
|
||||
}
|
||||
|
||||
void RichPara::Flush(Draw& draw, const PaintInfo& pi, wchar *text,
|
||||
const CharFormat **i0,
|
||||
int *wd, int pos, int len, int x0, int x, int y0,
|
||||
int y, int linecy, int lineascent, Zoom z,
|
||||
bool highlight)
|
||||
{
|
||||
if(*i0) {
|
||||
const CharFormat& f = **i0;
|
||||
int width = z * x - z * x0;
|
||||
int zy0 = z * y0;
|
||||
int zx0 = z * x0;
|
||||
if(!IsNull(f.paper) && !highlight)
|
||||
draw.DrawRect(zx0, z * y, width, z * (y + linecy) - z * y,
|
||||
pi.coloroverride ? SColorPaper() : f.paper);
|
||||
if(!IsNull(f.indexentry) && !IsNull(pi.indexentry))
|
||||
draw.DrawRect(zx0, zy0, width, 2, pi.indexentry);
|
||||
Font fnt = f;
|
||||
int zht = z * tabs(f.GetHeight());
|
||||
int ssa;
|
||||
int ssd;
|
||||
if(f.sscript) {
|
||||
FontInfo fi = fnt(zht).Info();
|
||||
ssa = fi.GetAscent();
|
||||
ssd = fi.GetDescent();
|
||||
zht = 3 * zht / 5;
|
||||
}
|
||||
fnt.Height(zht ? zht : 1);
|
||||
FontInfo fi = fnt.Info();
|
||||
if(f.dashed) {
|
||||
int dx = max(fi.GetAscent() / 5, 2);
|
||||
for(int i = 0; dx * i < width; i++)
|
||||
draw.DrawRect(zx0 + i * dx, zy0 + fi.GetDescent() / 2,
|
||||
dx / 2, max(fi.GetDescent() / 3, 1),
|
||||
pi.coloroverride ? SColorText() : f.ink);
|
||||
}
|
||||
Color ink = pi.coloroverride ? SColorText() : f.ink;
|
||||
if(!IsNull(f.link) && !IsNull(pi.hyperlink) && !(fnt.IsUnderline() || f.dashed)) {
|
||||
fnt.Underline();
|
||||
if(!pi.coloroverride)
|
||||
ink = pi.hyperlink;
|
||||
}
|
||||
x = zx0;
|
||||
for(int i = 0; i < len; i++) {
|
||||
int w = wd[pos + i];
|
||||
Image img;
|
||||
wchar& c = text[pos + i];
|
||||
if(c == ' ')
|
||||
img = RichTextImg::SpaceChar();
|
||||
if(c == 160)
|
||||
img = RichTextImg::HardSpaceChar();
|
||||
if(c >= 9 && c < 9 + 4) {
|
||||
if(c > 9) {
|
||||
static char fct[] = { ' ', '.', '-', '_' };
|
||||
int fc = fct[c - 9];
|
||||
int pw = fi[fc];
|
||||
int px = (x + pw - 1) / pw * pw;
|
||||
while(px + pw < x + w) {
|
||||
draw.DrawText(px, zy0 - fi.GetAscent(), String(fc, 1), fnt, Black);
|
||||
px += pw;
|
||||
}
|
||||
}
|
||||
img = RichTextImg::TabChar();
|
||||
c = ' ';
|
||||
}
|
||||
if(img && !IsNull(pi.showcodes)) {
|
||||
Size sz = img.GetSize();
|
||||
if(sz.cy < z * lineascent)
|
||||
draw.DrawImage(x + (w - sz.cx) / 2, zy0 - sz.cy, img, pi.showcodes);
|
||||
}
|
||||
x += w;
|
||||
}
|
||||
draw.DrawText(zx0,
|
||||
f.sscript == 1 ? zy0 - ssa :
|
||||
f.sscript == 2 ? zy0 + ssd - fi.GetHeight()
|
||||
: zy0 - fi.GetAscent(),
|
||||
text + pos, fnt, ink, len, wd + pos);
|
||||
}
|
||||
}
|
||||
|
||||
bool RichPara::BreaksPage(PageY py, const Lines& pl, int i, const Rect& page) const
|
||||
{
|
||||
int linecy = pl[i].Sum();
|
||||
if(linecy >= page.Height()) return false;
|
||||
if(linecy + py.y > page.bottom)
|
||||
return true;
|
||||
if(format.orphan || pl.GetCount() < 2) return false;
|
||||
if((i == 0 || i == pl.GetCount() - 2) && py.y + linecy + pl[i + 1].Sum() > page.bottom)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
struct RichObjectImageMaker : ImageMaker {
|
||||
RichObject object;
|
||||
Size sz;
|
||||
|
||||
virtual String Key() const;
|
||||
virtual Image Make() const;
|
||||
};
|
||||
|
||||
String RichObjectImageMaker::Key() const
|
||||
{
|
||||
StringBuffer b;
|
||||
int64 id = object.GetSerialId();
|
||||
b.Cat((const char *)&id, sizeof(id));
|
||||
b.Cat((const char *)&sz.cx, sizeof(sz.cx));
|
||||
b.Cat((const char *)&sz.cy, sizeof(sz.cy));
|
||||
return b;
|
||||
}
|
||||
|
||||
Image RichObjectImageMaker::Make() const
|
||||
{
|
||||
ImageDraw iw(sz);
|
||||
iw.DrawRect(sz, SColorPaper());
|
||||
object.Paint(iw, sz);
|
||||
return iw;
|
||||
}
|
||||
|
||||
void RichPara::Paint(PageDraw& pw, const Rect& page, PageY py, const PaintInfo& pi,
|
||||
const Number& n, const Bits& spellerror,
|
||||
int nbefore, int nline) const
|
||||
{
|
||||
Zoom z = pi.zoom;
|
||||
PageY opy = py;
|
||||
Lines pl = Begin(page, py, nbefore, nline);
|
||||
bool highlight = pi.highlightpara >= 0 && pi.highlightpara < pl.len;
|
||||
int hy = py.y - format.before - format.ruler;
|
||||
int phy = py.page;
|
||||
if(pi.sell < 0 && pi.selh > 0)
|
||||
for(int p = opy.page; p <= py.page; p++) {
|
||||
int top = z * (p == opy.page ? opy.y : page.top);
|
||||
int bottom = z * (p == py.page ? py.y : page.bottom);
|
||||
pw.Page(p).DrawRect(z * page.left, top, z * page.right - z * page.left,
|
||||
bottom - top, InvertColor);
|
||||
}
|
||||
opy = py;
|
||||
int oi = 0;
|
||||
int x;
|
||||
int y0;
|
||||
int lineascent = 0;
|
||||
for(int lni = 0; lni < pl.GetCount(); lni++) {
|
||||
Line& li = pl[lni];
|
||||
int linecy = li.Sum();
|
||||
lineascent = li.ascent;
|
||||
if(BreaksPage(py, pl, lni, page)) {
|
||||
if(li.ppos > pi.sell && li.ppos < pi.selh) {
|
||||
int y = z * py.y;
|
||||
pw.Page(py.page).DrawRect(z * page.left, y, z * page.right - z * page.left,
|
||||
z * page.bottom - y, InvertColor);
|
||||
}
|
||||
py.y = page.top;
|
||||
py.page++;
|
||||
}
|
||||
if(py > pi.bottom)
|
||||
break;
|
||||
|
||||
const CharFormat **cf = pl.format + li.pos;
|
||||
const CharFormat **i = cf;
|
||||
const CharFormat **ilim = i + li.len;
|
||||
const HeightInfo *hg = pl.height + li.pos;
|
||||
if(py + linecy >= pi.top) {
|
||||
Draw& draw = pw.Page(py.page);
|
||||
#ifdef _DEBUG
|
||||
int cloff = draw.GetCloffLevel();
|
||||
#endif
|
||||
Buffer<int> wd(li.len);
|
||||
int x0 = li.xpos + page.left;
|
||||
x = x0;
|
||||
int *w = pl.width + li.pos;
|
||||
int *wl = w + li.len;
|
||||
int *t = wd;
|
||||
while(w < wl) {
|
||||
int x1 = x + *w++;
|
||||
*t++ = z * x1 - z * x;
|
||||
x = x1;
|
||||
}
|
||||
|
||||
if(highlight)
|
||||
draw.DrawRect(z * page.left, z * py.y, z * page.Width(),
|
||||
z * (py.y + linecy) - z * py.y,
|
||||
pi.highlight);
|
||||
|
||||
const CharFormat **i0 = i;
|
||||
wchar *text = pl.text + li.pos;
|
||||
x = x0;
|
||||
w = pl.width + li.pos;
|
||||
y0 = py.y + li.ascent;
|
||||
int pp = li.pos;
|
||||
int l = page.right;
|
||||
int h = -1;
|
||||
|
||||
while(i < ilim) {
|
||||
if(pl.pos[pp] == pi.sell && x < l)
|
||||
l = x;
|
||||
if(pl.pos[pp] == pi.selh && h < 0)
|
||||
h = x;
|
||||
pp++;
|
||||
if(*i0 != *i || hg->object) {
|
||||
Flush(draw, pi, text, i0, wd, (int)(i0 - cf),(int)( i - i0), x0, x, y0, py.y, linecy,
|
||||
lineascent, z, highlight);
|
||||
i0 = i;
|
||||
x0 = x;
|
||||
}
|
||||
if(hg->object) {
|
||||
const RichObject& o = *hg->object;
|
||||
if(o) {
|
||||
Size sz = z * o.GetSize();
|
||||
draw.DrawRect(z * x, z * py.y, sz.cx, z * linecy, (*i)->paper);
|
||||
draw.Clipoff(z * x, z * (y0 - hg->ascent), sz.cx, sz.cy);
|
||||
if(pi.sizetracking)
|
||||
draw.DrawRect(sz, SColorFace);
|
||||
else
|
||||
if(pi.usecache) {
|
||||
RichObjectImageMaker im;
|
||||
im.object = o;
|
||||
im.sz = sz;
|
||||
draw.DrawImage(0, 0, MakeImagePaintOnly(im));
|
||||
}
|
||||
else
|
||||
o.Paint(draw, sz);
|
||||
draw.End();
|
||||
}
|
||||
i++;
|
||||
hg++;
|
||||
x += *w++;
|
||||
i0 = i;
|
||||
x0 = x;
|
||||
}
|
||||
else {
|
||||
i++;
|
||||
hg++;
|
||||
x += *w++;
|
||||
}
|
||||
}
|
||||
if(i > i0)
|
||||
Flush(draw, pi, text, i0, wd, (int)(i0 - cf), (int)(i - i0), x0, x, y0, py.y, linecy,
|
||||
lineascent, z, highlight);
|
||||
if(lni == 0) {
|
||||
Rect r;
|
||||
r.left = page.left + format.lm;
|
||||
int q = li.ascent / 2;
|
||||
r.top = py.y + 4 * (li.ascent - q) / 5;
|
||||
r.right = r.left + q;
|
||||
r.bottom = r.top + q;
|
||||
q = z * (r.Width() / 4);
|
||||
r.left = z * r.left;
|
||||
r.top = z * r.top;
|
||||
r.right = z * r.right;
|
||||
r.bottom = z * r.bottom;
|
||||
Rect r1 = r;
|
||||
r1.Deflate(max(1, q));
|
||||
switch(format.bullet) {
|
||||
case BULLET_BOX:
|
||||
draw.DrawRect(r, pi.coloroverride ? SColorText() : format.ink);
|
||||
break;
|
||||
case BULLET_BOXWHITE:
|
||||
draw.DrawRect(r, pi.coloroverride ? SColorText() : format.ink);
|
||||
draw.DrawRect(r1, White);
|
||||
break;
|
||||
case BULLET_ROUNDWHITE:
|
||||
draw.DrawEllipse(r, pi.coloroverride ? SColorText() : format.ink);
|
||||
draw.DrawEllipse(r1, pi.coloroverride ? SColorPaper() : White);
|
||||
break;
|
||||
case BULLET_ROUND:
|
||||
draw.DrawEllipse(r, pi.coloroverride ? SColorText() : format.ink);
|
||||
break;
|
||||
default:
|
||||
String s = n.AsText(format);
|
||||
if(!IsNull(s)) {
|
||||
CharFormat cf = li.len && *pl.format ? **pl.format : format;
|
||||
cf.Height(z * cf.GetHeight());
|
||||
draw.DrawText(r.left,
|
||||
z * y0 - cf.Info().GetAscent(),
|
||||
s, cf, pi.coloroverride ? SColorText() : cf.ink);
|
||||
}
|
||||
}
|
||||
}
|
||||
int zlcy = z * linecy;
|
||||
if(pi.spellingchecker && zlcy > 3) {
|
||||
int x = z * (li.xpos + page.left);
|
||||
w = wd;
|
||||
wl = w + li.len;
|
||||
int i = li.pos;
|
||||
int q = z * (py.y + linecy);
|
||||
while(w < wl) {
|
||||
if(spellerror[pl.pos[i++]]) {
|
||||
if(zlcy > 10)
|
||||
draw.DrawRect(x, q - 3, *w, 1, Red);
|
||||
draw.DrawRect(x, q - 2, *w, 1, LtRed);
|
||||
}
|
||||
x += *w++;
|
||||
}
|
||||
}
|
||||
|
||||
if(pi.selh == li.ppos + li.plen)
|
||||
h = x;
|
||||
if(pi.sell == li.ppos + li.plen)
|
||||
l = x;
|
||||
if(pi.sell < li.ppos)
|
||||
l = page.left;
|
||||
if(pi.selh > li.ppos + li.plen)
|
||||
h = page.right;
|
||||
if(pi.sell < pi.selh && pi.selh > li.ppos)
|
||||
draw.DrawRect(z * l, z * py.y, z * h - z * l,
|
||||
z * (py.y + linecy) - z * py.y, InvertColor);
|
||||
ASSERT(draw.GetCloffLevel() == cloff);
|
||||
}
|
||||
else
|
||||
while(i < ilim) {
|
||||
if(hg->object)
|
||||
oi++;
|
||||
i++;
|
||||
hg++;
|
||||
}
|
||||
py.y += linecy;
|
||||
}
|
||||
Size sz = RichTextImg::EndParaChar().GetSize();
|
||||
if(sz.cy < z * lineascent && !IsNull(pi.showcodes))
|
||||
pw.Page(py.page).DrawImage(z * x, z * y0 - sz.cy,
|
||||
RichTextImg::EndParaChar(),
|
||||
format.indexentry.GetCount() ? pi.indexentry : pi.showcodes);
|
||||
if(format.newpage && !IsNull(pi.showcodes)) {
|
||||
Draw& w = pw.Page(opy.page);
|
||||
int wd = z * page.right - z * page.left;
|
||||
int step = w.Pixels() ? 8 : 50;
|
||||
int y = z * opy.y;
|
||||
for(int x = 0; x < wd; x += step)
|
||||
w.DrawRect(z * page.left + x, y, step >> 1, step >> 3, pi.showcodes);
|
||||
}
|
||||
if(pl.len >= pi.sell && pl.len < pi.selh && py < pi.bottom) {
|
||||
int top = z * py.y;
|
||||
pw.Page(py.page).DrawRect(z * page.left, top, z * page.right - z * page.left,
|
||||
z * min(py.y + format.after, page.bottom) - top, InvertColor);
|
||||
}
|
||||
if(format.ruler && hy >= 0 && hy + format.ruler < page.bottom)
|
||||
pw.Page(phy).DrawRect(z * page.left + z * format.lm, z * hy,
|
||||
z * page.right - z * page.left - z * format.rm - z * format.lm,
|
||||
max(1, z * format.ruler), format.rulerink);
|
||||
}
|
||||
|
||||
void RichPara::GetRichPos(RichPos& rp, int pos) const
|
||||
{
|
||||
rp.format = format;
|
||||
int i = FindPart(pos);
|
||||
if(i < GetCount()) {
|
||||
const Part& p = part[i];
|
||||
(CharFormat&)rp.format = p.format;
|
||||
if(p.object) {
|
||||
rp.chr = -1;
|
||||
rp.object = p.object;
|
||||
}
|
||||
else
|
||||
if(p.IsText())
|
||||
rp.chr = p.text[pos];
|
||||
else {
|
||||
rp.chr = -2;
|
||||
rp.field = p.field;
|
||||
rp.fieldparam = p.fieldparam;
|
||||
if(p.fieldpart.GetCount() > 0)
|
||||
rp.fieldformat = p.fieldpart[0].format;
|
||||
}
|
||||
}
|
||||
else
|
||||
rp.chr = '\n';
|
||||
}
|
||||
|
||||
RichCaret RichPara::GetCaret(int pos, const Rect& page, PageY py, int nbefore, int nline) const
|
||||
{
|
||||
Lines pl = Begin(page, py, nbefore, nline);
|
||||
RichCaret pr;
|
||||
FontInfo fi = format.Info();
|
||||
pr.caretascent = fi.GetAscent();
|
||||
pr.caretdescent = fi.GetDescent();
|
||||
for(int lni = 0; lni < pl.GetCount(); lni++) {
|
||||
Line& li = pl[lni];
|
||||
int linecy = li.Sum();
|
||||
if(BreaksPage(py, pl, lni, page)) {
|
||||
py.y = page.top;
|
||||
py.page++;
|
||||
}
|
||||
pr.page = py.page;
|
||||
pr.top = py.y;
|
||||
pr.bottom = py.y + linecy;
|
||||
pr.lineascent = li.ascent;
|
||||
pr.line = lni;
|
||||
if(pos < li.ppos + li.plen) {
|
||||
int *w = pl.width + li.pos;
|
||||
int *p = pl.pos + li.pos;
|
||||
const CharFormat **i = pl.format + li.pos;
|
||||
const HeightInfo *h = pl.height + li.pos;
|
||||
int x = li.xpos + page.left;
|
||||
if(li.len && *i) {
|
||||
pr.caretascent = h->ascent;
|
||||
pr.caretdescent = h->descent;
|
||||
}
|
||||
while(pos > *p) {
|
||||
x += *w++;
|
||||
if(*i) {
|
||||
pr.caretascent = h->ascent;
|
||||
pr.caretdescent = h->descent;
|
||||
}
|
||||
h++;
|
||||
i++;
|
||||
p++;
|
||||
}
|
||||
pr.objectcy = h->ascent + h->ydelta;
|
||||
pr.objectyd = h->ydelta;
|
||||
pr.left = x;
|
||||
pr.right = x + *w;
|
||||
pr.caretdescent = min(pr.caretdescent, pr.Height() - pr.lineascent);
|
||||
return pr;
|
||||
}
|
||||
py.y += linecy;
|
||||
}
|
||||
const Line& li = pl.line.Top();
|
||||
pr.left = li.cx + li.xpos + page.left;
|
||||
pr.right = page.right;
|
||||
pr.caretdescent = min(pr.caretdescent, pr.Height() - pr.lineascent);
|
||||
return pr;
|
||||
}
|
||||
|
||||
int RichPara::PosInLine(int x, const Rect& page, const Lines& pl, int lni) const
|
||||
{
|
||||
const Line& li = pl[lni];
|
||||
const int *w = pl.width + li.pos;
|
||||
const int *wl = w + li.len;
|
||||
if(lni < pl.GetCount() - 1 && li.len > 0 && pl.text[li.pos + li.len - 1] == ' ')
|
||||
wl--;
|
||||
int xp = li.xpos + page.left;
|
||||
while(w < wl && xp + *w <= x)
|
||||
xp += *w++;
|
||||
int pos = (int)(w - pl.width);
|
||||
return pos < pl.clen ? pl.pos[pos] : pl.len;
|
||||
}
|
||||
|
||||
int RichPara::GetPos(int x, PageY y, const Rect& page, PageY py, int nbefore, int nline) const
|
||||
{
|
||||
Lines pl = Begin(page, py, nbefore, nline);
|
||||
if(pl.len)
|
||||
for(int lni = 0; lni < pl.GetCount(); lni++) {
|
||||
const Line& li = pl[lni];
|
||||
int linecy = li.Sum();
|
||||
if(BreaksPage(py, pl, lni, page)) {
|
||||
py.y = page.top;
|
||||
py.page++;
|
||||
}
|
||||
py.y += linecy;
|
||||
if(y < py || lni == pl.GetCount() - 1)
|
||||
return PosInLine(x, page, pl, lni);
|
||||
}
|
||||
return pl.len;
|
||||
}
|
||||
|
||||
int RichPara::GetVertMove(int pos, int gx, const Rect& page, int dir) const
|
||||
{
|
||||
Lines pl = FormatLines(page.Width());
|
||||
int lni;
|
||||
if(pos >= 0) {
|
||||
for(lni = 0; lni < pl.GetCount() - 1; lni++) {
|
||||
const Line& li = pl[lni];
|
||||
if(pos < li.ppos + li.plen)
|
||||
break;
|
||||
}
|
||||
lni += sgn(dir);
|
||||
if(lni < 0 || lni >= pl.GetCount())
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
lni = dir < 0 ? pl.GetCount() - 1 : 0;
|
||||
return PosInLine(gx, page, pl, lni);
|
||||
}
|
||||
|
||||
void RichPara::GatherLabels(Vector<RichValPos>& info, const Rect& page, PageY py,
|
||||
int pos, int nbefore, int nline) const
|
||||
{
|
||||
Lines pl = Begin(page, py, nbefore, nline);
|
||||
WString ie;
|
||||
if(!pl.GetCount())
|
||||
return;
|
||||
if(BreaksPage(py, pl, 0, page)) {
|
||||
py.y = page.top;
|
||||
py.page++;
|
||||
}
|
||||
if(format.label.IsEmpty())
|
||||
return;
|
||||
RichValPos& f = info.Add();
|
||||
f.py = py;
|
||||
f.pos = pos;
|
||||
f.data = format.label.ToWString();
|
||||
}
|
||||
|
||||
void RichPara::GatherIndexes(Vector<RichValPos>& info, const Rect& page, PageY py,
|
||||
int pos, int nbefore, int nline) const
|
||||
{
|
||||
Lines pl = Begin(page, py, nbefore, nline);
|
||||
WString ie;
|
||||
for(int lni = 0; lni < pl.GetCount(); lni++) {
|
||||
Line& li = pl[lni];
|
||||
int linecy = li.Sum();
|
||||
if(BreaksPage(py, pl, lni, page)) {
|
||||
py.y = page.top;
|
||||
py.page++;
|
||||
}
|
||||
const CharFormat **i0 = pl.format + li.pos;
|
||||
const CharFormat **i = i0;
|
||||
const CharFormat **ilim = i + li.len;
|
||||
while(i < ilim) {
|
||||
if(*i && (*i)->indexentry != ie) {
|
||||
ie = (*i)->indexentry;
|
||||
if(!ie.IsEmpty()) {
|
||||
RichValPos& f = info.Add();
|
||||
f.py = py;
|
||||
f.pos = (int)(i - i0) + pos;
|
||||
f.data = ie;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
py.y += linecy;
|
||||
}
|
||||
}
|
||||
|
||||
void FontHeightRound(Font& fnt, Zoom z)
|
||||
{
|
||||
fnt.Height((fnt.GetHeight() * z.m + (z.d >> 1)) / z.d);
|
||||
}
|
||||
|
||||
void operator*=(RichPara::Format& format, Zoom z)
|
||||
{
|
||||
FontHeightRound(format, z);
|
||||
format.before *= z;
|
||||
if(format.ruler) {
|
||||
format.ruler *= z;
|
||||
if(format.ruler == 0)
|
||||
format.ruler = 1;
|
||||
}
|
||||
int ll = format.lm + format.indent;
|
||||
format.lm *= z;
|
||||
format.indent = z * ll - format.lm;
|
||||
format.rm *= z;
|
||||
format.after *= z;
|
||||
format.tabsize *= z;
|
||||
for(int i = 0; i < format.tab.GetCount(); i++)
|
||||
format.tab[i].pos *= z;
|
||||
}
|
||||
|
||||
void RichPara::ApplyZoom(Zoom z)
|
||||
{
|
||||
format *= z;
|
||||
for(int i = 0; i < part.GetCount(); i++)
|
||||
if(part[i].IsText())
|
||||
FontHeightRound(part[i].format, z);
|
||||
else
|
||||
if(part[i].object)
|
||||
part[i].object.SetSize(z * part[i].object.GetSize());
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
376
uppdev/RichTextP/ParaType.cpp
Normal file
376
uppdev/RichTextP/ParaType.cpp
Normal file
|
|
@ -0,0 +1,376 @@
|
|||
#include "RichText.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
void RichPara::Smh(Lines& lines, HeightInfo *th, int cx) const
|
||||
{
|
||||
Line& l = lines.line.Top();
|
||||
l.ascent = l.descent = l.external = 0;
|
||||
const HeightInfo *he = th + l.pos + l.len;
|
||||
for(const HeightInfo *h = th + l.pos; h < he; h++) {
|
||||
if(h->ascent > l.ascent) l.ascent = h->ascent;
|
||||
if(h->descent > l.descent) l.descent = h->descent;
|
||||
if(h->external > l.external) l.external = h->external;
|
||||
}
|
||||
if(format.linespacing == LSP15) {
|
||||
l.ascent = (3 * l.ascent) >> 1;
|
||||
l.descent = (3 * l.descent) >> 1;
|
||||
}
|
||||
if(format.linespacing == LSP20) {
|
||||
l.ascent = 2 * l.ascent;
|
||||
l.descent = 2 * l.descent;
|
||||
}
|
||||
l.xpos = format.lm;
|
||||
cx -= format.lm + format.rm;
|
||||
l.xpos += lines.GetCount() == 1 ? lines.first_indent : lines.next_indent;
|
||||
if(!l.withtabs)
|
||||
switch(format.align) {
|
||||
case ALIGN_RIGHT:
|
||||
l.xpos += cx - l.cx;
|
||||
break;
|
||||
case ALIGN_CENTER:
|
||||
l.xpos += (cx - l.cx) / 2;
|
||||
break;
|
||||
}
|
||||
l.cx -= lines.GetCount() == 1 ? lines.first_indent : lines.next_indent;
|
||||
}
|
||||
|
||||
RichPara::Tab RichPara::GetNextTab(int pos) const
|
||||
{
|
||||
int tabi = -1;
|
||||
int dist = INT_MAX;
|
||||
for(int i = 0; i < format.tab.GetCount(); i++) {
|
||||
const Tab& tab = format.tab[i];
|
||||
if(tab.pos > pos && tab.pos - pos < dist) {
|
||||
tabi = i;
|
||||
dist = tab.pos - pos;
|
||||
}
|
||||
}
|
||||
if(format.bullet == BULLET_TEXT) {
|
||||
int q = format.indent + format.lm;
|
||||
if(q > pos && q - pos < dist) {
|
||||
Tab tab;
|
||||
tab.align = ALIGN_LEFT;
|
||||
tab.pos = q;
|
||||
return tab;
|
||||
}
|
||||
}
|
||||
if(tabi < 0) {
|
||||
Tab tab;
|
||||
tab.pos = format.tabsize ? (pos + format.tabsize) / format.tabsize * format.tabsize : 0;
|
||||
tab.align = ALIGN_LEFT;
|
||||
return tab;
|
||||
}
|
||||
return format.tab[tabi];
|
||||
}
|
||||
|
||||
struct RichPara::StorePart {
|
||||
wchar *t;
|
||||
int *w;
|
||||
int *p;
|
||||
const CharFormat **f;
|
||||
HeightInfo *h;
|
||||
int pos;
|
||||
FontInfo pfi;
|
||||
|
||||
void Store(Lines& lines, const Part& p, int pinc);
|
||||
};
|
||||
|
||||
void RichPara::StorePart::Store(Lines& lines, const Part& part, int pinc)
|
||||
{
|
||||
if(part.field && pinc) {
|
||||
for(int i = 0; i < part.fieldpart.GetCount(); i++)
|
||||
Store(lines, part.fieldpart[i], 0);
|
||||
pos++;
|
||||
}
|
||||
else
|
||||
if(part.object) {
|
||||
*f++ = &part.format;
|
||||
Size sz = part.object.GetSize();
|
||||
*w++ = sz.cx;
|
||||
h->ydelta = part.object.GetYDelta();
|
||||
h->ascent = sz.cy - h->ydelta;
|
||||
h->descent = max(h->ydelta, 0);
|
||||
h->external = 0;
|
||||
h->object = &part.object;
|
||||
h++;
|
||||
*t++ = 'x';
|
||||
*p++ = pos;
|
||||
pos += pinc;
|
||||
}
|
||||
else {
|
||||
const wchar *s = part.text;
|
||||
const wchar *lim = part.text.End();
|
||||
Font fnt = part.format;
|
||||
FontInfo fi = fnt.Info();
|
||||
FontInfo wfi = fi;
|
||||
if(part.format.sscript) {
|
||||
fnt.Height(fnt.GetHeight() * 3 / 5);
|
||||
wfi = fnt.Info();
|
||||
}
|
||||
if(part.format.capitals) {
|
||||
CharFormat& cfmt = lines.hformat.Add();
|
||||
cfmt = part.format;
|
||||
cfmt.Height(cfmt.GetHeight() * 4 / 5);
|
||||
FontInfo cfi = cfmt.Info();
|
||||
FontInfo cwfi = cfi;
|
||||
if(part.format.sscript) {
|
||||
Font fnt = cfmt;
|
||||
fnt.Height(fnt.GetHeight() * 3 / 5);
|
||||
cwfi = fnt.Info();
|
||||
}
|
||||
|
||||
while(s < lim) {
|
||||
wchar c = *s++;
|
||||
if(c == 9) {
|
||||
*f++ = &part.format;
|
||||
h->ascent = pfi.GetAscent();
|
||||
h->descent = pfi.GetDescent();
|
||||
h->external = pfi.GetExternal();
|
||||
*w++ = 0;
|
||||
}
|
||||
else
|
||||
if(IsLower(c)) {
|
||||
*f++ = &cfmt;
|
||||
c = ToUpper(c);
|
||||
h->ascent = cfi.GetAscent();
|
||||
h->descent = cfi.GetDescent();
|
||||
h->external = cfi.GetExternal();
|
||||
*w++ = c >= 32 ? cwfi[c] : 0;
|
||||
}
|
||||
else {
|
||||
*f++ = &part.format;
|
||||
h->ascent = fi.GetAscent();
|
||||
h->descent = fi.GetDescent();
|
||||
h->external = fi.GetExternal();
|
||||
*w++ = c >= 32 ? wfi[c] : 0;
|
||||
}
|
||||
h->object = NULL;
|
||||
*t++ = c;
|
||||
*p++ = pos;
|
||||
pos += pinc;
|
||||
h++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while(s < lim) {
|
||||
wchar c = *s++;
|
||||
*f++ = &part.format;
|
||||
if(c == 9) {
|
||||
h->ascent = pfi.GetAscent();
|
||||
h->descent = pfi.GetDescent();
|
||||
h->external = pfi.GetExternal();
|
||||
}
|
||||
else {
|
||||
h->ascent = fi.GetAscent();
|
||||
h->descent = fi.GetDescent();
|
||||
h->external = fi.GetExternal();
|
||||
}
|
||||
h->object = NULL;
|
||||
*p++ = pos;
|
||||
pos += pinc;
|
||||
h++;
|
||||
*w++ = c >= 32 ? wfi[c] : 0;
|
||||
*t++ = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int CountChars(const Array<RichPara::Part>& part)
|
||||
{
|
||||
int n = 0;
|
||||
for(int i = 0; i < part.GetCount(); i++) {
|
||||
const RichPara::Part& p = part[i];
|
||||
if(p.field)
|
||||
n += CountChars(p.fieldpart);
|
||||
else
|
||||
n += p.GetLength();
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
RichPara::Lines RichPara::FormatLines(int acx) const
|
||||
{
|
||||
int i;
|
||||
Lines lines;
|
||||
lines.cx = acx;
|
||||
lines.len = GetLength();
|
||||
lines.clen = CountChars(part);
|
||||
lines.first_indent = lines.next_indent = format.indent;
|
||||
if(format.bullet == BULLET_TEXT)
|
||||
lines.first_indent = 0;
|
||||
else
|
||||
if(!format.bullet && !format.IsNumbered())
|
||||
lines.next_indent = 0;
|
||||
|
||||
FontInfo pfi = format.Info();
|
||||
if(lines.len == 0) {
|
||||
Line& l = lines.line.Add();
|
||||
l.pos = 0;
|
||||
l.ppos = 0;
|
||||
l.plen = 0;
|
||||
l.len = 0;
|
||||
l.cx = lines.first_indent;
|
||||
l.withtabs = false;
|
||||
HeightInfo dummy;
|
||||
Smh(lines, &dummy, lines.cx);
|
||||
l.ascent = pfi.GetAscent();
|
||||
l.descent = pfi.GetDescent();
|
||||
l.external = pfi.GetExternal();
|
||||
return lines;
|
||||
}
|
||||
|
||||
lines.text.Alloc(lines.clen);
|
||||
lines.width.Alloc(lines.clen);
|
||||
lines.pos.Alloc(lines.clen);
|
||||
lines.format.Alloc(lines.clen);
|
||||
lines.height.Alloc(lines.clen);
|
||||
|
||||
StorePart sp;
|
||||
sp.t = lines.text;
|
||||
sp.w = lines.width;
|
||||
sp.p = lines.pos;
|
||||
sp.f = lines.format;
|
||||
sp.h = lines.height;
|
||||
sp.pfi = pfi;
|
||||
sp.pos = 0;
|
||||
|
||||
for(i = 0; i < part.GetCount(); i++)
|
||||
sp.Store(lines, part[i], 1);
|
||||
|
||||
wchar *s = lines.text;
|
||||
wchar *text = s;
|
||||
wchar *end = lines.text + lines.clen;
|
||||
wchar *space = NULL;
|
||||
int *w = lines.width;
|
||||
int cx = lines.first_indent;
|
||||
int rcx = lines.cx - format.lm - format.rm;
|
||||
bool withtabs = false;
|
||||
int scx;
|
||||
while(s < end) {
|
||||
Tab t;
|
||||
if(*s == ' ') {
|
||||
space = s;
|
||||
scx = cx;
|
||||
}
|
||||
else {
|
||||
if(*s == '\t') {
|
||||
t = GetNextTab(cx + format.lm);
|
||||
space = NULL;
|
||||
}
|
||||
if(cx + *w > rcx && s > text || *s == '\t' && t.pos - format.lm >= rcx) {
|
||||
Line& l = lines.line.Add();
|
||||
l.withtabs = withtabs;
|
||||
l.pos = (int)(text - lines.text);
|
||||
if(space) {
|
||||
l.len = (int)(space - text) + 1;
|
||||
l.cx = scx;
|
||||
text = s = space + 1;
|
||||
}
|
||||
else {
|
||||
l.len = (int)(s - text);
|
||||
l.cx = cx;
|
||||
text = s;
|
||||
}
|
||||
Smh(lines, lines.height, lines.cx);
|
||||
cx = lines.next_indent;
|
||||
w = text - ~lines.text + lines.width;
|
||||
space = NULL;
|
||||
rcx = lines.cx - format.lm - format.rm;
|
||||
withtabs = false;
|
||||
t = GetNextTab(cx + format.lm);
|
||||
}
|
||||
}
|
||||
if(*s == '\t') {
|
||||
*s += t.fillchar;
|
||||
if(t.align == ALIGN_LEFT) {
|
||||
*w++ = t.pos - format.lm - cx;
|
||||
cx = t.pos - format.lm;
|
||||
}
|
||||
else {
|
||||
int tcx = 0;
|
||||
int *tw = w + 1;
|
||||
for(wchar *ts = s + 1; ts < end && *ts != '\t'; ts++)
|
||||
tcx += *tw++;
|
||||
int ww = t.pos - format.lm - cx - (t.align == ALIGN_RIGHT ? tcx : tcx / 2);
|
||||
if(ww > 0) {
|
||||
*w++ = ww;
|
||||
cx += ww;
|
||||
}
|
||||
else
|
||||
*w++ = 0;
|
||||
}
|
||||
withtabs = true;
|
||||
}
|
||||
else
|
||||
cx += *w++;
|
||||
s++;
|
||||
}
|
||||
Line& l = lines.line.Add();
|
||||
l.withtabs = withtabs;
|
||||
l.pos = (int)(text - lines.text);
|
||||
l.len = (int)(s - text);
|
||||
l.cx = cx;
|
||||
Smh(lines, lines.height, lines.cx);
|
||||
for(i = 0; i < lines.line.GetCount(); i++) {
|
||||
Line& l = lines.line[i];
|
||||
l.ppos = lines.pos[l.pos];
|
||||
l.plen = (l.pos + l.len < lines.clen ? lines.pos[l.pos + l.len] : lines.len) - l.ppos;
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
void RichPara::Lines::Justify(const RichPara::Format& format)
|
||||
{
|
||||
if(format.align != ALIGN_JUSTIFY) return;
|
||||
for(int i = 0; i < line.GetCount() - 1; i++) {
|
||||
const Line& li = line[i];
|
||||
if(!li.withtabs && li.len) {
|
||||
const wchar *s = ~text + li.pos;
|
||||
const wchar *lim = s + li.len;
|
||||
while(lim - 1 > s) {
|
||||
if(*(lim - 1) != ' ') break;
|
||||
lim--;
|
||||
}
|
||||
while(s < lim) {
|
||||
if(*s != ' ' && *s != 160) break;
|
||||
s++;
|
||||
}
|
||||
|
||||
const wchar *beg = s;
|
||||
int nspc = 0;
|
||||
while(s < lim) {
|
||||
if(*s == ' ' || *s == 160) nspc++;
|
||||
s++;
|
||||
}
|
||||
s = beg;
|
||||
if(nspc) {
|
||||
int q = ((cx - format.lm - format.rm -
|
||||
(i == 0 ? first_indent : next_indent) - li.cx) << 16)
|
||||
/ nspc;
|
||||
int *w = beg - ~text + width;
|
||||
int prec = 0;
|
||||
while(s < lim) {
|
||||
if(*s == ' ' || *s == 160) {
|
||||
*w += (prec + q) >> 16;
|
||||
prec = (prec + q) & 0xffff;
|
||||
}
|
||||
w++;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int RichPara::Lines::BodyHeight()
|
||||
{
|
||||
int sum = 0;
|
||||
for(int i = 0; i < line.GetCount(); i++)
|
||||
sum += line[i].Sum();
|
||||
return sum;
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
967
uppdev/RichTextP/ParseQtf.cpp
Normal file
967
uppdev/RichTextP/ParseQtf.cpp
Normal file
|
|
@ -0,0 +1,967 @@
|
|||
#include "RichText.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
Color (*QTFColor[])() = {
|
||||
Black, LtGray, White, Red, Green, Blue, LtRed, WhiteGray, LtCyan, Yellow
|
||||
};
|
||||
|
||||
Color (*QTFSColor[])()= {
|
||||
SColorText, SColorFace, SColorPaper, Red, Green, Blue, LtRed, WhiteGray, LtCyan, Yellow
|
||||
};
|
||||
|
||||
Color NullColorF()
|
||||
{
|
||||
return Null;
|
||||
}
|
||||
|
||||
static Color (*QTFColorl[])() = {
|
||||
/*a*/White, /*b*/Blue, /*c*/Cyan, /*d*/White, /*e*/White, /*f*/White, /*g*/ Green, /*h*/White,
|
||||
/*i*/White, /*j*/White, /*k*/Black, /*l*/LtGray, /*m*/Magenta, /*n*/NullColorF, /*o*/Brown, /*p*/White,
|
||||
/*q*/White, /*r*/Red, /*s*/White, /*t*/White, /*u*/White, /*v*/White, /*w*/WhiteGray, /*x*/White,
|
||||
/*y*/Yellow, /*z*/ White
|
||||
};
|
||||
|
||||
static Color (*QTFColorL[])() = {
|
||||
/*A*/White, /*B*/LtBlue, /*C*/LtCyan, /*D*/White, /*E*/White, /*F*/White, /*G*/LtGreen, /*H*/White,
|
||||
/*I*/White, /*J*/White, /*K*/Gray, /*L*/WhiteGray, /*M*/LtMagenta, /*N*/NullColorF, /*O*/Brown, /*P*/White,
|
||||
/*Q*/White, /*R*/LtRed, /*S*/White, /*T*/White, /*U*/White, /*V*/White, /*W*/White, /*X*/White,
|
||||
/*Y*/LtYellow, /*Z*/White
|
||||
};
|
||||
|
||||
static Color (*QTFSColorl[])() = { //TODO
|
||||
/*a*/SColorPaper, /*b*/SColorHighlight, /*c*/Cyan, /*d*/SColorPaper, /*e*/SColorPaper, /*f*/SColorPaper, /*g*/ Green, /*h*/SColorPaper,
|
||||
/*i*/SColorPaper, /*j*/SColorPaper, /*k*/SColorText, /*l*/SColorFace, /*m*/Magenta, /*n*/NullColorF, /*o*/Brown, /*p*/SColorPaper,
|
||||
/*q*/SColorPaper, /*r*/Red, /*s*/SColorPaper, /*t*/SColorPaper, /*u*/SColorPaper, /*v*/SColorPaper, /*w*/WhiteGray, /*x*/SColorPaper,
|
||||
/*y*/Yellow, /*z*/ White
|
||||
};
|
||||
|
||||
static Color (*QTFSColorL[])() = { //TODO
|
||||
/*A*/SColorPaper, /*B*/LtBlue, /*C*/LtCyan, /*D*/SColorPaper, /*E*/SColorPaper, /*F*/SColorPaper, /*G*/LtGreen, /*H*/SColorPaper,
|
||||
/*I*/SColorPaper, /*J*/SColorPaper, /*K*/SColorShadow, /*L*/WhiteGray, /*M*/LtMagenta, /*N*/NullColorF, /*O*/Brown, /*P*/SColorPaper,
|
||||
/*Q*/SColorPaper, /*R*/LtRed, /*S*/SColorPaper, /*T*/SColorPaper, /*U*/SColorPaper, /*V*/SColorPaper, /*W*/SColorPaper, /*X*/SColorPaper,
|
||||
/*Y*/LtYellow, /*Z*/White
|
||||
};
|
||||
|
||||
int QTFFontHeight[] = {
|
||||
50, 67, 84, 100, 134, 167, 200, 234, 300, 400
|
||||
};
|
||||
|
||||
class RichQtfParser {
|
||||
const char *term;
|
||||
bool scolors;
|
||||
WString text;
|
||||
RichPara paragraph;
|
||||
RichTable tablepart;
|
||||
bool istable;
|
||||
bool breakpage;
|
||||
byte accesskey;
|
||||
|
||||
struct PFormat : public RichPara::Format {
|
||||
byte charset;
|
||||
};
|
||||
|
||||
struct Tab {
|
||||
RichCell::Format format;
|
||||
int vspan, hspan;
|
||||
RichTxt text;
|
||||
RichTable table;
|
||||
int cell;
|
||||
Vector<int> rown;
|
||||
|
||||
void Old() { RichTable::Format fmt; fmt.grid = 10; table.SetFormat(fmt); }
|
||||
|
||||
Tab() { cell = 0; vspan = hspan = 0; }
|
||||
};
|
||||
|
||||
PFormat format;
|
||||
Array<PFormat> fstack;
|
||||
Vector<Uuid> styleid;
|
||||
Vector<int> stylenext;
|
||||
Array<Tab> table;
|
||||
bool oldtab;
|
||||
|
||||
bool Key(int c) { if(*term == c) { term++; return true; } return false; }
|
||||
bool Key2(int c, int d);
|
||||
bool Key2(int c) { return Key2(c, c); }
|
||||
int GetNumber();
|
||||
int ReadNumber();
|
||||
String GetText(int delim);
|
||||
Color GetColor();
|
||||
void Number2(int& a, int& b);
|
||||
|
||||
void Flush();
|
||||
void SetFormat();
|
||||
void FlushStyles();
|
||||
void Error(const char *s);
|
||||
|
||||
void ReadObject();
|
||||
|
||||
RichTable& Table();
|
||||
void TableFormat(bool bw = false);
|
||||
void FinishCell();
|
||||
void FinishTable();
|
||||
void FinishOldTable();
|
||||
void S(int& x, int a);
|
||||
|
||||
void EndPart();
|
||||
|
||||
void Cat(int chr);
|
||||
|
||||
public:
|
||||
struct Exc {};
|
||||
|
||||
RichText target;
|
||||
|
||||
void Parse(const char *qtf, byte accesskey);
|
||||
|
||||
RichQtfParser(bool scolors);
|
||||
};
|
||||
|
||||
void init_s_nodeqtf();
|
||||
|
||||
RichQtfParser::RichQtfParser(bool _scolors)
|
||||
{
|
||||
format.Face(Font::ARIAL);
|
||||
format.Height(100);
|
||||
format.charset = GetDefaultCharset();
|
||||
format.language = 0;
|
||||
breakpage = false;
|
||||
istable = false;
|
||||
oldtab = false;
|
||||
init_s_nodeqtf();
|
||||
scolors = _scolors;
|
||||
}
|
||||
|
||||
bool RichQtfParser::Key2(int c, int d)
|
||||
{
|
||||
if(term[0] == c && term[1] == d) {
|
||||
term += 2;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int RichQtfParser::GetNumber()
|
||||
{
|
||||
int n = 0;
|
||||
int sgn = 1;
|
||||
if(*term == '-') {
|
||||
sgn = -1;
|
||||
term++;
|
||||
}
|
||||
while(IsDigit(*term))
|
||||
n = n * 10 + *term++ - '0';
|
||||
return sgn * n;
|
||||
}
|
||||
|
||||
String RichQtfParser::GetText(int delim) {
|
||||
String s;
|
||||
for(;;) {
|
||||
if(*term == '\0') return s;
|
||||
if(*term == '`') {
|
||||
term++;
|
||||
if(*term == '\0') return s;
|
||||
s.Cat(*term++);
|
||||
}
|
||||
else
|
||||
if(*term == delim) {
|
||||
term++;
|
||||
return s;
|
||||
}
|
||||
else
|
||||
s.Cat(*term++);
|
||||
}
|
||||
}
|
||||
|
||||
int RichQtfParser::ReadNumber()
|
||||
{
|
||||
if(!IsDigit(*term))
|
||||
Error("Expected number");
|
||||
return GetNumber();
|
||||
}
|
||||
|
||||
void RichQtfParser::Number2(int& a, int& b)
|
||||
{
|
||||
a = -1;
|
||||
b = -1;
|
||||
if(IsDigit(*term))
|
||||
a = GetNumber();
|
||||
if(*term == '/') {
|
||||
term++;
|
||||
b = GetNumber();
|
||||
}
|
||||
}
|
||||
|
||||
Color RichQtfParser::GetColor()
|
||||
{
|
||||
int c = *term++;
|
||||
if(c == '(') {
|
||||
byte r = GetNumber();
|
||||
if(Key(')')) {
|
||||
r &= 255;
|
||||
return Color(r, r, r);
|
||||
}
|
||||
Key('.');
|
||||
byte g = GetNumber();
|
||||
Key('.');
|
||||
byte b = GetNumber();
|
||||
Key(')');
|
||||
return Color(r & 255, g & 255, b & 255);
|
||||
}
|
||||
else
|
||||
if(c >= '0' && c <= '9')
|
||||
return (*((scolors ? QTFSColor : QTFColor)[c - '0']))();
|
||||
else
|
||||
if(c >= 'a' && c <= 'z')
|
||||
return (*((scolors ? QTFSColorl : QTFColorl)[c - 'a']))();
|
||||
else
|
||||
if(c >= 'A' && c <= 'Z')
|
||||
return (*((scolors ? QTFSColorL : QTFColorL)[c - 'A']))();
|
||||
else
|
||||
return Red;
|
||||
}
|
||||
|
||||
void RichQtfParser::SetFormat()
|
||||
{
|
||||
paragraph.format = format;
|
||||
}
|
||||
|
||||
void RichQtfParser::Flush() {
|
||||
if(text.GetLength()) {
|
||||
ASSERT(!istable);
|
||||
paragraph.Cat(text, format);
|
||||
text.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
void RichQtfParser::EndPart()
|
||||
{
|
||||
if(istable) {
|
||||
if(paragraph.GetCount() == 0 && text.GetCount() == 0)
|
||||
if(table.GetCount())
|
||||
table.Top().text.CatPick(tablepart);
|
||||
else
|
||||
target.CatPick(tablepart);
|
||||
else {
|
||||
paragraph.part.Clear();
|
||||
text.Clear();
|
||||
}
|
||||
}
|
||||
else {
|
||||
Flush();
|
||||
bool b = paragraph.format.newpage;
|
||||
if(breakpage)
|
||||
paragraph.format.newpage = true;
|
||||
if(table.GetCount())
|
||||
table.Top().text.Cat(paragraph, target.GetStyles());
|
||||
else
|
||||
target.Cat(paragraph);
|
||||
paragraph.part.Clear();;
|
||||
paragraph.format.newpage = b;
|
||||
SetFormat();
|
||||
breakpage = false;
|
||||
}
|
||||
istable = false;
|
||||
}
|
||||
|
||||
void RichQtfParser::ReadObject()
|
||||
{
|
||||
Flush();
|
||||
RichObject obj;
|
||||
if(*term == '#') {
|
||||
term++;
|
||||
#ifdef CPU_64
|
||||
obj = *(RichObject *)stou64(term, &term);
|
||||
#else
|
||||
obj = *(RichObject *)stou(term, &term);
|
||||
#endif
|
||||
term++;
|
||||
}
|
||||
else {
|
||||
String type;
|
||||
while(IsAlNum(*term) || *term == '_')
|
||||
type.Cat(*term++);
|
||||
Size sz;
|
||||
Key(':');
|
||||
sz.cx = ReadNumber();
|
||||
bool keepratio = false;
|
||||
if(Key('&'))
|
||||
keepratio = true;
|
||||
else
|
||||
Key('*');
|
||||
sz.cy = ReadNumber();
|
||||
int yd = 0;
|
||||
if(Key('/'))
|
||||
yd = GetNumber();
|
||||
StringBuffer data;
|
||||
for(;;) {
|
||||
while(*term < 32 && *term > 0) term++;
|
||||
if((byte)*term >= ' ' && (byte)*term <= 127 || *term == '\0') break;
|
||||
byte seven = *term++;
|
||||
for(int i = 0; i < 7; i++) {
|
||||
while((byte)*term < 32 && (byte)*term > 0) term++;
|
||||
if((byte)*term >= ' ' && (byte)*term <= 127 || *term == '\0') break;
|
||||
data.Cat((*term++ & 0x7f) | ((seven << 7) & 0x80));
|
||||
seven >>= 1;
|
||||
}
|
||||
}
|
||||
obj.Read(type, data, sz);
|
||||
obj.KeepRatio(keepratio);
|
||||
obj.SetYDelta(yd);
|
||||
}
|
||||
paragraph.Cat(obj, format);
|
||||
}
|
||||
|
||||
int NoLow(int c) {
|
||||
return (byte)c >= 32 ? c : 0;
|
||||
}
|
||||
|
||||
void RichQtfParser::Error(const char *s) {
|
||||
RichPara::CharFormat ef;
|
||||
(Font&) ef = Arial(84).Bold().Underline();
|
||||
ef.ink = Red;
|
||||
paragraph.Cat(("ERROR: " + String(s) + ": " +
|
||||
Filter(String(term, min<int>((int)strlen(term), 20)), NoLow)).ToWString(), ef);
|
||||
target.Cat(paragraph);
|
||||
FlushStyles();
|
||||
throw Exc();
|
||||
}
|
||||
|
||||
void RichQtfParser::FlushStyles()
|
||||
{
|
||||
for(int i = 0; i < styleid.GetCount(); i++)
|
||||
if(stylenext[i] >= 0 && stylenext[i] < styleid.GetCount()) {
|
||||
RichStyle s = target.GetStyle(styleid[i]);
|
||||
s.next = styleid[stylenext[i]];
|
||||
target.SetStyle(styleid[i], s);
|
||||
}
|
||||
}
|
||||
|
||||
RichTable& RichQtfParser::Table()
|
||||
{
|
||||
if(table.GetCount() == 0)
|
||||
Error("Not in table");
|
||||
return table.Top().table;
|
||||
}
|
||||
|
||||
void RichQtfParser::S(int& x, int a)
|
||||
{
|
||||
if(a >= 0)
|
||||
x = a;
|
||||
}
|
||||
|
||||
void RichQtfParser::TableFormat(bool bw)
|
||||
{
|
||||
RichTable& tab = Table();
|
||||
Tab& t = table.Top();
|
||||
int a, b;
|
||||
for(;;) {
|
||||
if(bw && IsDigit(*term)) {
|
||||
t.hspan = GetNumber();
|
||||
}
|
||||
else
|
||||
switch(*term++) {
|
||||
case ' ': 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 '_':
|
||||
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 '^': t.format.align = ALIGN_TOP; break;
|
||||
case '=': t.format.align = ALIGN_CENTER; break;
|
||||
case 'v': t.format.align = ALIGN_BOTTOM; break;
|
||||
case 'l': Number2(a, b); S(t.format.border.left, a); S(t.format.margin.left, b); break;
|
||||
case 'r': Number2(a, b); S(t.format.border.right, a); S(t.format.margin.right, b); break;
|
||||
case 't': Number2(a, b); S(t.format.border.top, a); S(t.format.margin.top, b); break;
|
||||
case 'b': Number2(a, b); S(t.format.border.bottom, a); S(t.format.margin.bottom, b); break;
|
||||
case 'H': t.format.minheight = ReadNumber(); break;
|
||||
case '@': t.format.color = GetColor(); break;
|
||||
case 'R': t.format.bordercolor = GetColor(); break;
|
||||
case '!': t.format = RichCell::Format(); break;
|
||||
case 'k': t.format.keep = true;
|
||||
case 'K': tab.format.keep = true;
|
||||
case 'a':
|
||||
Number2(a, b);
|
||||
if(a >= 0)
|
||||
t.format.border.left = t.format.border.right = t.format.border.top = t.format.border.bottom = a;
|
||||
if(b >= 0)
|
||||
t.format.margin.left = t.format.margin.right = t.format.margin.top = t.format.margin.bottom = b;
|
||||
break; //!!cell all lines
|
||||
case '-': t.hspan = GetNumber(); break;
|
||||
case '+':
|
||||
case '|': t.vspan = GetNumber(); break;
|
||||
default:
|
||||
Error("Invalid cell format");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RichQtfParser::FinishCell()
|
||||
{
|
||||
EndPart();
|
||||
RichTable& t = Table();
|
||||
Tab& b = table.Top();
|
||||
int i, j;
|
||||
if(oldtab) {
|
||||
i = b.rown.GetCount() - 1;
|
||||
j = b.rown.Top();
|
||||
b.rown.Top()++;
|
||||
}
|
||||
else {
|
||||
i = b.cell / t.GetColumns();
|
||||
j = b.cell % t.GetColumns();
|
||||
}
|
||||
t.SetPick(i, j, b.text);
|
||||
b.text.Clear();
|
||||
t.SetFormat(i, j, b.format);
|
||||
t.SetSpan(i, j, b.vspan, b.hspan);
|
||||
if(oldtab && b.rown.GetCount() > 1 && j + 1 < b.rown[0])
|
||||
b.format = t.GetFormat(0, j + 1);
|
||||
else {
|
||||
b.cell++;
|
||||
b.vspan = 0;
|
||||
b.hspan = oldtab;
|
||||
}
|
||||
b.format.keep = false;
|
||||
}
|
||||
|
||||
void RichQtfParser::FinishTable()
|
||||
{
|
||||
FinishCell();
|
||||
tablepart = Table();
|
||||
istable = true;
|
||||
table.Drop();
|
||||
}
|
||||
|
||||
void RichQtfParser::FinishOldTable()
|
||||
{
|
||||
FinishCell();
|
||||
Index<int> pos;
|
||||
Vector<int> srow;
|
||||
RichTable& t = Table();
|
||||
Tab& b = table.Top();
|
||||
for(int i = 0; i < t.GetRows(); i++) {
|
||||
int& s = srow.Add();
|
||||
s = 0;
|
||||
int nx = b.rown[i];
|
||||
for(int j = 0; j < nx; j++)
|
||||
s += t.GetSpan(i, j).cx;
|
||||
int xn = 0;
|
||||
for(int j = 0; j < nx; j++) {
|
||||
pos.FindAdd(xn * 10000 / s);
|
||||
xn += t.GetSpan(i, j).cx;
|
||||
}
|
||||
}
|
||||
Vector<int> h = pos.PickKeys();
|
||||
if(h.GetCount() == 0)
|
||||
Error("table");
|
||||
Sort(h);
|
||||
pos = h;
|
||||
pos.Add(10000);
|
||||
RichTable tab;
|
||||
tab.SetFormat(t.GetFormat());
|
||||
for(int i = 0; i < pos.GetCount() - 1; i++) {
|
||||
tab.AddColumn(pos[i + 1] - pos[i]);
|
||||
}
|
||||
for(int i = 0; i < t.GetRows(); i++) {
|
||||
int s = srow[i];
|
||||
int nx = b.rown[i];
|
||||
int xn = 0;
|
||||
int xi = 0;
|
||||
for(int j = 0; j < nx; j++) {
|
||||
Size span = t.GetSpan(i, j);
|
||||
xn += span.cx;
|
||||
int nxi = pos.Find(xn * 10000 / s);
|
||||
tab.SetPick(i, xi, t.GetPick(i, j));
|
||||
tab.SetFormat(i, xi, t.GetFormat(i, j));
|
||||
tab.SetSpan(i, xi, max(span.cy - 1, 0), nxi - xi - 1);
|
||||
xi = nxi;
|
||||
}
|
||||
}
|
||||
table.Drop();
|
||||
if(table.GetCount())
|
||||
table.Top().text.CatPick(tab);
|
||||
else
|
||||
target.CatPick(tab);
|
||||
oldtab = false;
|
||||
}
|
||||
|
||||
void RichQtfParser::Cat(int chr)
|
||||
{
|
||||
if(accesskey && ToUpper(ToAscii(chr)) == accesskey) {
|
||||
Flush();
|
||||
format.Underline(!format.IsUnderline());
|
||||
text.Cat(chr);
|
||||
Flush();
|
||||
format.Underline(!format.IsUnderline());
|
||||
accesskey = 0;
|
||||
}
|
||||
else {
|
||||
text.Cat(chr);
|
||||
}
|
||||
}
|
||||
|
||||
extern bool s_nodeqtf[128];
|
||||
|
||||
void RichQtfParser::Parse(const char *qtf, byte _accesskey)
|
||||
{
|
||||
accesskey = _accesskey;
|
||||
term = qtf;
|
||||
while(*term) {
|
||||
if(Key('[')) {
|
||||
Flush();
|
||||
fstack.Add(format);
|
||||
for(;;) {
|
||||
int c = *term;
|
||||
if(!c)
|
||||
Error("Unexpected end of text");
|
||||
term++;
|
||||
if(c == ' ' || c == '\n') break;
|
||||
switch(c) {
|
||||
case 's': {
|
||||
Uuid id;
|
||||
c = *term;
|
||||
if(Key('\"') || Key('\''))
|
||||
id = target.GetStyleId(GetText(c));
|
||||
else {
|
||||
int i = ReadNumber();
|
||||
if(i >= 0 && i < styleid.GetCount())
|
||||
id = styleid[i];
|
||||
else
|
||||
id = RichStyle::GetDefaultId();
|
||||
}
|
||||
const RichStyle& s = target.GetStyle(id);
|
||||
bool p = format.newpage;
|
||||
int lng = format.language;
|
||||
(RichPara::Format&) format = s.format;
|
||||
format.styleid = id;
|
||||
format.language = lng;
|
||||
format.newpage = p;
|
||||
break;
|
||||
}
|
||||
case '/': format.Italic(!format.IsItalic()); break;
|
||||
case '*': format.Bold(!format.IsBold()); break;
|
||||
case '_': format.Underline(!format.IsUnderline()); break;
|
||||
case 'T': format.NonAntiAliased(!format.IsNonAntiAliased()); break;
|
||||
case '-': format.Strikeout(!format.IsStrikeout()); break;
|
||||
case 'c': format.capitals = !format.capitals; break;
|
||||
case 'd': format.dashed = !format.dashed; break;
|
||||
case '`': format.sscript = format.sscript == 1 ? 0 : 1; break;
|
||||
case ',': format.sscript = format.sscript == 2 ? 0 : 2; break;
|
||||
case '^': format.link = GetText('^'); break;
|
||||
case 'I': format.indexentry = FromUtf8(GetText(';')); break;
|
||||
case '+': format.Height(GetNumber()); break;
|
||||
case '@': format.ink = GetColor(); break;
|
||||
case '$': format.paper = GetColor(); break;
|
||||
case 'A': format.Face(Font::ARIAL); break;
|
||||
case 'R': format.Face(Font::ROMAN); break;
|
||||
case 'C': format.Face(Font::COURIER); break;
|
||||
case 'G': format.Face(Font::STDFONT); break;
|
||||
case 'S': format.Face(Font::SYMBOL); break;
|
||||
case '.': {
|
||||
int n = GetNumber();
|
||||
if(n >= Font::GetFaceCount())
|
||||
Error("Invalid face number");
|
||||
format.Face(n); break;
|
||||
}
|
||||
case '!': {
|
||||
String fn = GetText('!');
|
||||
int i = Font::FindFaceNameIndex(fn);
|
||||
if(i < 0)
|
||||
i = Font::ARIAL;
|
||||
format.Face(i);
|
||||
}
|
||||
break;
|
||||
case '{': {
|
||||
String cs = GetText('}');
|
||||
if(cs.GetLength() == 1) {
|
||||
int c = *cs;
|
||||
if(c == '_')
|
||||
format.charset = CHARSET_UTF8;
|
||||
if(c >= '0' && c <= '8')
|
||||
format.charset = c - '0' + CHARSET_WIN1250;
|
||||
if(c >= 'A' && c <= 'Z')
|
||||
format.charset = c - '0' + CHARSET_ISO8859_1;
|
||||
}
|
||||
else {
|
||||
for(int i = 0; i < CharsetCount(); i++)
|
||||
if(stricmp(CharsetName(i), cs) == 0) {
|
||||
format.charset = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '%': {
|
||||
String h;
|
||||
if(*term == '-') {
|
||||
format.language = 0;
|
||||
term++;
|
||||
}
|
||||
else
|
||||
if(*term == '%') {
|
||||
format.language = LNG_ENGLISH;
|
||||
term++;
|
||||
}
|
||||
else {
|
||||
while(*term && h.GetLength() < 5)
|
||||
h.Cat(*term++);
|
||||
format.language = LNGFromText(h);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if(c >= '0' && c <= '9') {
|
||||
format.Height(QTFFontHeight[c - '0']);
|
||||
break;
|
||||
}
|
||||
switch(c) {
|
||||
case ':': format.label = GetText(':'); break;
|
||||
case '<': format.align = ALIGN_LEFT; break;
|
||||
case '>': format.align = ALIGN_RIGHT; break;
|
||||
case '=': format.align = ALIGN_CENTER; break;
|
||||
case '#': format.align = ALIGN_JUSTIFY; break;
|
||||
case 'l': format.lm = GetNumber(); break;
|
||||
case 'r': format.rm = GetNumber(); break;
|
||||
case 'i': format.indent = GetNumber(); break;
|
||||
case 'b': format.before = GetNumber(); break;
|
||||
case 'a': format.after = GetNumber(); break;
|
||||
case 'P': format.newpage = !format.newpage; break;
|
||||
case 'k': format.keep = !format.keep; break;
|
||||
case 'K': format.keepnext = !format.keepnext; break;
|
||||
case 'H': format.ruler = GetNumber(); break;
|
||||
case 'h': format.rulerink = GetColor(); break;
|
||||
case 'Q': format.orphan = !format.orphan; break;
|
||||
case 'n': format.before_number = GetText(';'); break;
|
||||
case 'm': format.after_number = GetText(';'); break;
|
||||
case 'N': {
|
||||
memset(format.number, 0, sizeof(format.number));
|
||||
format.reset_number = false;
|
||||
int i = 0;
|
||||
while(i < 8) {
|
||||
int c;
|
||||
if(Key('-'))
|
||||
c = RichPara::NUMBER_NONE;
|
||||
else
|
||||
if(Key('1'))
|
||||
c = RichPara::NUMBER_1;
|
||||
else
|
||||
if(Key('0'))
|
||||
c = RichPara::NUMBER_0;
|
||||
else
|
||||
if(Key('a'))
|
||||
c = RichPara::NUMBER_a;
|
||||
else
|
||||
if(Key('A'))
|
||||
c = RichPara::NUMBER_A;
|
||||
else
|
||||
if(Key('i'))
|
||||
c = RichPara::NUMBER_i;
|
||||
else
|
||||
if(Key('I'))
|
||||
c = RichPara::NUMBER_I;
|
||||
else
|
||||
break;
|
||||
format.number[i++] = c;
|
||||
}
|
||||
if(Key('!'))
|
||||
format.reset_number = true;
|
||||
break;
|
||||
}
|
||||
case 'o': format.bullet = RichPara::BULLET_ROUND;
|
||||
format.indent = 150; break;
|
||||
case 'O':
|
||||
if(Key('_'))
|
||||
format.bullet = RichPara::BULLET_NONE;
|
||||
else {
|
||||
int c = *term++;
|
||||
if(!c)
|
||||
Error("Unexpected end of text");
|
||||
format.bullet =
|
||||
c == '1' ? RichPara::BULLET_ROUNDWHITE :
|
||||
c == '2' ? RichPara::BULLET_BOX :
|
||||
c == '3' ? RichPara::BULLET_BOXWHITE :
|
||||
c == '9' ? RichPara::BULLET_TEXT :
|
||||
RichPara::BULLET_ROUND;
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
switch(*term++) {
|
||||
case 0: Error("Unexpected end of text");
|
||||
case 'h': format.linespacing = RichPara::LSP15; break;
|
||||
case 'd': format.linespacing = RichPara::LSP20; break;
|
||||
default: format.linespacing = RichPara::LSP10;
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
if(IsDigit(*term)) //temporary fix... :(
|
||||
format.tabsize = ReadNumber();
|
||||
break;
|
||||
case '~': {
|
||||
if(Key('~'))
|
||||
format.tab.Clear();
|
||||
else {
|
||||
RichPara::Tab tab;
|
||||
Key('<');
|
||||
if(Key('>'))
|
||||
tab.align = ALIGN_RIGHT;
|
||||
if(Key('='))
|
||||
tab.align = ALIGN_CENTER;
|
||||
if(Key('.'))
|
||||
tab.fillchar = 1;
|
||||
if(Key('-'))
|
||||
tab.fillchar = 2;
|
||||
if(Key('_'))
|
||||
tab.fillchar = 3;
|
||||
tab.pos = ReadNumber();
|
||||
format.tab.Add(tab);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
SetFormat();
|
||||
}
|
||||
else
|
||||
if(Key(']')) {
|
||||
Flush();
|
||||
if(fstack.GetCount()) {
|
||||
format = fstack.Top();
|
||||
fstack.Drop();
|
||||
}
|
||||
else
|
||||
Error("Unmatched ']'");
|
||||
}
|
||||
else
|
||||
if(Key2('{')) {
|
||||
if(oldtab)
|
||||
Error("{{ in ++ table");
|
||||
if(text.GetLength() || paragraph.GetCount())
|
||||
EndPart();
|
||||
table.Add();
|
||||
int r = IsDigit(*term) ? ReadNumber() : 1;
|
||||
Table().AddColumn(r);
|
||||
while(Key(':'))
|
||||
Table().AddColumn(ReadNumber());
|
||||
TableFormat();
|
||||
}
|
||||
else
|
||||
if(Key2('}')) {
|
||||
if(oldtab)
|
||||
Error("}} in ++ table");
|
||||
FinishTable();
|
||||
}
|
||||
else
|
||||
if(Key2('+'))
|
||||
if(oldtab)
|
||||
FinishOldTable();
|
||||
else {
|
||||
Flush();
|
||||
if(text.GetLength() || paragraph.GetCount())
|
||||
EndPart();
|
||||
Tab& b = table.Add();
|
||||
b.rown.Add(0);
|
||||
b.hspan = 1;
|
||||
b.Old();
|
||||
oldtab = true;
|
||||
}
|
||||
else
|
||||
if(Key2('|'))
|
||||
FinishCell();
|
||||
else
|
||||
if(Key2('-')) {
|
||||
FinishCell();
|
||||
table.Top().rown.Add(0);
|
||||
}
|
||||
else
|
||||
if(Key2(':')) {
|
||||
if(!oldtab)
|
||||
FinishCell();
|
||||
TableFormat(oldtab);
|
||||
}
|
||||
else
|
||||
if(Key2('^')) {
|
||||
EndPart();
|
||||
breakpage = true;
|
||||
}
|
||||
else
|
||||
if(Key2('@')) {
|
||||
ReadObject();
|
||||
}
|
||||
else
|
||||
if(Key2('@', '$')) {
|
||||
String xu;
|
||||
while(isxdigit(*term))
|
||||
xu.Cat(*term++);
|
||||
int c = stou(~xu, NULL, 16);
|
||||
if(c >= 32)
|
||||
Cat(c);
|
||||
if(*term == ';')
|
||||
term++;
|
||||
SetFormat();
|
||||
}
|
||||
else
|
||||
if(Key2('{', ':')) {
|
||||
Flush();
|
||||
String field = GetText(':');
|
||||
String param = GetText(':');
|
||||
Id fid(field);
|
||||
if(RichPara::fieldtype().Find(fid) >= 0)
|
||||
paragraph.Cat(fid, param, format);
|
||||
Key('}');
|
||||
}
|
||||
else
|
||||
if(Key('&')) {
|
||||
SetFormat();
|
||||
EndPart();
|
||||
}
|
||||
else
|
||||
if(Key2('$')) {
|
||||
Flush();
|
||||
int i = GetNumber();
|
||||
Uuid id;
|
||||
RichStyle style;
|
||||
style.format = format;
|
||||
if(Key(','))
|
||||
stylenext.At(i, 0) = GetNumber();
|
||||
else
|
||||
stylenext.At(i, 0) = i;
|
||||
if(Key('#')) {
|
||||
String xu;
|
||||
while(isxdigit(*term))
|
||||
xu.Cat(*term++);
|
||||
if(xu.GetLength() != 32)
|
||||
Error("Invalid UUID !");
|
||||
id = ScanUuid(xu);
|
||||
}
|
||||
else
|
||||
if(i)
|
||||
id = Uuid::Create();
|
||||
else
|
||||
id = RichStyle::GetDefaultId();
|
||||
if(Key(':'))
|
||||
style.name = GetText(']');
|
||||
if(fstack.GetCount()) {
|
||||
format = fstack.Top();
|
||||
fstack.Drop();
|
||||
}
|
||||
target.SetStyle(id, style);
|
||||
styleid.At(i, RichStyle::GetDefaultId()) = id;
|
||||
if(id == RichStyle::GetDefaultId()) {
|
||||
bool p = format.newpage;
|
||||
int lng = format.language;
|
||||
(RichPara::Format&) format = style.format;
|
||||
format.styleid = id;
|
||||
format.language = lng;
|
||||
format.newpage = p;
|
||||
}
|
||||
}
|
||||
else
|
||||
if(*term == '_') {
|
||||
SetFormat();
|
||||
text.Cat(160);
|
||||
term++;
|
||||
}
|
||||
else
|
||||
if(Key2('-', '|')) {
|
||||
SetFormat();
|
||||
text.Cat(9);
|
||||
}
|
||||
else
|
||||
if(*term == '\1') {
|
||||
if(istable)
|
||||
EndPart();
|
||||
SetFormat();
|
||||
const char *b = ++term;
|
||||
for(; *term && *term != '\1'; term++)
|
||||
if(*term == '\n') {
|
||||
text.Cat(ToUnicode(b, (int)(term - b), format.charset));
|
||||
EndPart();
|
||||
b = term + 1;
|
||||
}
|
||||
text.Cat(ToUnicode(b, (int)(term - b), format.charset));
|
||||
if(*term == '\1')
|
||||
term++;
|
||||
}
|
||||
else {
|
||||
if(!Key('`')) Key('\\');
|
||||
if((byte)*term >= ' ') {
|
||||
SetFormat();
|
||||
do {
|
||||
if(istable)
|
||||
EndPart();
|
||||
if(format.charset == CHARSET_UTF8) {
|
||||
word code = (byte)*term++;
|
||||
if(code <= 0x7F)
|
||||
Cat(code);
|
||||
else
|
||||
if(code <= 0xDF) {
|
||||
if(*term == '\0') break;
|
||||
int c0 = (byte)*term++;
|
||||
if(c0 < 0x80)
|
||||
Error("Invalid UTF-8 sequence");
|
||||
Cat(((code - 0xC0) << 6) + c0 - 0x80);
|
||||
}
|
||||
else
|
||||
if(code <= 0xEF) {
|
||||
int c0 = (byte)*term++;
|
||||
int c1 = (byte)*term++;
|
||||
if(c0 < 0x80 || c1 < 0x80)
|
||||
Error("Invalid UTF-8 sequence");
|
||||
Cat(((code - 0xE0) << 12) + ((c0 - 0x80) << 6) + c1 - 0x80);
|
||||
}
|
||||
else
|
||||
Error("Invalid UTF-8 sequence");
|
||||
}
|
||||
else
|
||||
Cat(ToUnicode((byte)*term++, format.charset));
|
||||
}
|
||||
while((byte)*term >= 128 || s_nodeqtf[(byte)*term]);
|
||||
}
|
||||
else
|
||||
if(*term)
|
||||
term++;
|
||||
}
|
||||
}
|
||||
if(paragraph.GetCount() == 0)
|
||||
SetFormat();
|
||||
if(oldtab)
|
||||
FinishOldTable();
|
||||
else
|
||||
while(table.GetCount())
|
||||
FinishTable();
|
||||
EndPart();
|
||||
FlushStyles();
|
||||
}
|
||||
|
||||
RichText ParseQTF(const char *qtf, bool scolors, byte accesskey)
|
||||
{
|
||||
RichQtfParser p(scolors);
|
||||
try {
|
||||
p.Parse(qtf, accesskey);
|
||||
}
|
||||
catch(RichQtfParser::Exc) {}
|
||||
return p.target;
|
||||
}
|
||||
|
||||
String QtfRichObject::ToString() const
|
||||
{
|
||||
return String("@@#").Cat() << uintptr_t(&obj) << ";";
|
||||
}
|
||||
|
||||
QtfRichObject::QtfRichObject(const RichObject& o)
|
||||
: obj(o)
|
||||
{}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
1106
uppdev/RichTextP/ParseRTF.cpp
Normal file
1106
uppdev/RichTextP/ParseRTF.cpp
Normal file
File diff suppressed because it is too large
Load diff
237
uppdev/RichTextP/RichImage.icpp
Normal file
237
uppdev/RichTextP/RichImage.icpp
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
#include "RichText.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#ifdef NEWIMAGE
|
||||
|
||||
struct RichImage : public RichObjectType {
|
||||
virtual String GetTypeName(const Value& v) const;
|
||||
virtual Size GetPhysicalSize(const Value& data) const;
|
||||
virtual Size GetPixelSize(const Value& data) const;
|
||||
virtual void Paint(const Value& data, Draw& w, Size sz) const;
|
||||
virtual Image ToImage(const Value& data, Size sz) const;
|
||||
|
||||
virtual bool Accept(PasteClip& clip);
|
||||
virtual Value Read(PasteClip& clip);
|
||||
virtual String GetClipFmts() const;
|
||||
virtual String GetClip(const Value& data, const String& fmt) const;
|
||||
|
||||
typedef RichImage CLASSNAME;
|
||||
};
|
||||
|
||||
String RichImage::GetTypeName(const Value& v) const
|
||||
{
|
||||
return "image";
|
||||
}
|
||||
|
||||
bool RichImage::Accept(PasteClip& clip)
|
||||
{
|
||||
return AcceptImage(clip);
|
||||
}
|
||||
|
||||
Value RichImage::Read(PasteClip& clip)
|
||||
{
|
||||
return StoreImageAsString(GetImage(clip));
|
||||
}
|
||||
|
||||
String RichImage::GetClipFmts() const
|
||||
{
|
||||
return ClipFmtsImage();
|
||||
}
|
||||
|
||||
String RichImage::GetClip(const Value& data, const String& fmt) const
|
||||
{
|
||||
return GetImageClip(LoadImageFromString(data), fmt);
|
||||
}
|
||||
|
||||
Size RichImage::GetPixelSize(const Value& data) const
|
||||
{
|
||||
return GetImageStringSize(data);
|
||||
}
|
||||
|
||||
Size RichImage::GetPhysicalSize(const Value& data) const
|
||||
{
|
||||
Size sz = GetImageStringDots(data);
|
||||
if(sz.cx == 0 || sz.cy == 0)
|
||||
sz = 600 * GetPixelSize(data) / 96;
|
||||
return sz;
|
||||
}
|
||||
|
||||
void RichImage::Paint(const Value& data, Draw& w, Size sz) const
|
||||
{
|
||||
Image x = LoadImageFromString(data);
|
||||
// Size outsz(min(sz.cx, 4 * x.GetWidth()), min(sz.cy, 4 * x.GetHeight()));
|
||||
w.DrawImage(0, 0, sz.cx, sz.cy, x);
|
||||
}
|
||||
|
||||
Image RichImage::ToImage(const Value& data, Size sz) const
|
||||
{
|
||||
return Rescale(LoadImageFromString(data), sz);
|
||||
}
|
||||
|
||||
INITBLOCK {
|
||||
RichObject::Register("image", &Single<RichImage>());
|
||||
};
|
||||
|
||||
RichObject CreateImageObject(const Image& img, int cx, int cy)
|
||||
{
|
||||
RichObject o = RichObject("image", StoreImageAsString(img));
|
||||
if(cx || cy)
|
||||
o.SetSize(GetRatioSize(o.GetPixelSize(), cx, cy));
|
||||
return o;
|
||||
}
|
||||
|
||||
struct RichPNG : public RichObjectType {
|
||||
virtual String GetTypeName(const Value& v) const;
|
||||
virtual Value Read(const String& s) const;
|
||||
virtual String Write(const Value& v) const;
|
||||
virtual Size GetPhysicalSize(const Value& data) const;
|
||||
virtual Size GetPixelSize(const Value& data) const;
|
||||
virtual void Paint(const Value& data, Draw& w, Size sz) const;
|
||||
virtual Image ToImage(const Value& data, Size sz) const;
|
||||
};
|
||||
|
||||
String RichPNG::GetTypeName(const Value& v) const
|
||||
{
|
||||
return IsString(v) ? "PNG" : "image";
|
||||
}
|
||||
|
||||
Value RichPNG::Read(const String& s) const
|
||||
{
|
||||
Image img = StreamRaster::LoadStringAny(s);
|
||||
if(img)
|
||||
return img;
|
||||
return s;
|
||||
}
|
||||
|
||||
String RichPNG::Write(const Value& v) const
|
||||
{
|
||||
if(IsString(v))
|
||||
return v;
|
||||
return StoreImageAsString(v);
|
||||
}
|
||||
|
||||
Size RichPNG::GetPhysicalSize(const Value& data) const
|
||||
{
|
||||
if(IsString(data))
|
||||
return Size(0, 0);
|
||||
return Image(data).GetDots();
|
||||
}
|
||||
|
||||
Size RichPNG::GetPixelSize(const Value& data) const
|
||||
{
|
||||
if(IsString(data))
|
||||
return Size(0, 0);
|
||||
return Image(data).GetDots();
|
||||
}
|
||||
|
||||
void RichPNG::Paint(const Value& data, Draw& w, Size sz) const
|
||||
{
|
||||
if(IsString(data)) {
|
||||
w.DrawRect(sz, SColorFace());
|
||||
DrawFrame(w, sz, SColorText());
|
||||
w.DrawText(2, 2, "plugin/png missing!");
|
||||
return;
|
||||
}
|
||||
Image x = Image(data);
|
||||
Size outsz(min(sz.cx, 4 * x.GetWidth()), min(sz.cy, 4 * x.GetHeight()));
|
||||
w.DrawImage(0, 0, outsz.cx, outsz.cy, x);
|
||||
}
|
||||
|
||||
Image RichPNG::ToImage(const Value& data, Size sz) const
|
||||
{
|
||||
if(IsString(data)) {
|
||||
ImageDraw iw(sz);
|
||||
Paint(data, iw, sz);
|
||||
return iw;
|
||||
}
|
||||
Image x = Image(data);
|
||||
Size outsz(min(sz.cx, 4 * x.GetWidth()), min(sz.cy, 4 * x.GetHeight()));
|
||||
return Rescale(x, outsz);
|
||||
}
|
||||
|
||||
INITBLOCK {
|
||||
RichObject::Register("PNG", &Single<RichPNG>());
|
||||
};
|
||||
|
||||
struct RichRawImage : public RichObjectType {
|
||||
virtual String GetTypeName(const Value& v) const;
|
||||
virtual Value Read(const String& s) const;
|
||||
virtual String Write(const Value& v) const;
|
||||
virtual Size GetPhysicalSize(const Value& data) const;
|
||||
virtual Size GetPixelSize(const Value& data) const;
|
||||
virtual void Paint(const Value& data, Draw& w, Size sz) const;
|
||||
virtual Image ToImage(const Value& data, Size sz) const;
|
||||
};
|
||||
|
||||
String RichRawImage::GetTypeName(const Value& v) const
|
||||
{
|
||||
return "rawimage";
|
||||
}
|
||||
|
||||
Value RichRawImage::Read(const String& s) const
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
String RichRawImage::Write(const Value& v) const
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
Size RichRawImage::GetPhysicalSize(const Value& data) const
|
||||
{
|
||||
String s = data;
|
||||
StringStream ss(s);
|
||||
One<StreamRaster> r = StreamRaster::OpenAny(ss);
|
||||
if(r)
|
||||
return r->GetInfo().dots;
|
||||
return Size(0, 0);
|
||||
}
|
||||
|
||||
Size RichRawImage::GetPixelSize(const Value& data) const
|
||||
{
|
||||
String s = data;
|
||||
StringStream ss(s);
|
||||
One<StreamRaster> r = StreamRaster::OpenAny(ss);
|
||||
if(r)
|
||||
return r->GetSize();
|
||||
return Size(0, 0);
|
||||
}
|
||||
|
||||
void RichRawImage::Paint(const Value& data, Draw& w, Size sz) const
|
||||
{
|
||||
String s = data;
|
||||
StringStream ss(s);
|
||||
One<StreamRaster> r = StreamRaster::OpenAny(ss);
|
||||
if(r) {
|
||||
ImageEncoder m;
|
||||
Rescale(m, sz, *r, r->GetSize());
|
||||
w.DrawImage(0, 0, sz.cx, sz.cy, m);
|
||||
}
|
||||
}
|
||||
|
||||
Image RichRawImage::ToImage(const Value& data, Size sz) const
|
||||
{
|
||||
String s = data;
|
||||
StringStream ss(s);
|
||||
One<StreamRaster> r = StreamRaster::OpenAny(ss);
|
||||
if(r)
|
||||
return r->GetImage();
|
||||
return Null;
|
||||
}
|
||||
|
||||
INITBLOCK {
|
||||
RichObject::Register("rawimage", &Single<RichRawImage>());
|
||||
};
|
||||
|
||||
RichObject CreateRawImageObject(const String& s, int cx, int cy)
|
||||
{
|
||||
RichObject o = RichObject("rawimage", s);
|
||||
o.InitSize(cx, cy);
|
||||
return o;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
462
uppdev/RichTextP/RichText.h
Normal file
462
uppdev/RichTextP/RichText.h
Normal file
|
|
@ -0,0 +1,462 @@
|
|||
#ifndef RICHTEXT_H
|
||||
#define RICHTEXT_H
|
||||
|
||||
#include <CtrlCore/CtrlCore.h>
|
||||
#include <plugin/png/png.h>
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
struct Zoom {
|
||||
int m, d;
|
||||
|
||||
int operator*(int x) const { return d ? iscale(x, m, d) : 0; }
|
||||
int operator&(int x) const { int q = d ? iscale(x, m, d) : 0; return x > 0 ? max(q, 1) : q; }
|
||||
|
||||
double AsDouble() const { return (double)m / d; }
|
||||
|
||||
Zoom() { m = d = 1; }
|
||||
Zoom(const Nuller&) { m = d = 0; }
|
||||
Zoom(int _m, int _d) { m = _m, d = _d; }
|
||||
|
||||
void Serialize(Stream& s) { s % m % d; }
|
||||
|
||||
bool operator==(Zoom a) { return m == a.m && d == a.d; }
|
||||
bool operator!=(Zoom a) { return m != a.m || d != a.d; }
|
||||
|
||||
friend int operator/(int x, Zoom z) { return z.m ? iscale(x, z.d, z.m) : 0; }
|
||||
};
|
||||
|
||||
inline bool IsNull(Zoom z) { return (z.m | z.d) == 0; }
|
||||
|
||||
inline int operator*(int x, Zoom m)
|
||||
{
|
||||
return m * x;
|
||||
}
|
||||
|
||||
inline void operator*=(int& i, Zoom m)
|
||||
{
|
||||
i = m * i;
|
||||
}
|
||||
|
||||
inline void operator*=(Rect& r, Zoom m)
|
||||
{
|
||||
r.left *= m;
|
||||
r.right *= m;
|
||||
r.top *= m;
|
||||
r.bottom *= m;
|
||||
}
|
||||
|
||||
inline Size operator*(Zoom m, Size sz)
|
||||
{
|
||||
return Size(m * sz.cx, m * sz.cy);
|
||||
}
|
||||
|
||||
inline Size operator/(Size sz, Zoom m)
|
||||
{
|
||||
return Size(sz.cx / m, sz.cy / m);
|
||||
}
|
||||
|
||||
struct PageY : Moveable<PageY, RelOps<PageY> > {
|
||||
int page;
|
||||
int y;
|
||||
|
||||
PageY(int page, int y) : page(page), y(y) {}
|
||||
PageY() { page = y = 0; }
|
||||
|
||||
#ifdef _DEBUG
|
||||
String ToString() const { return AsString(page) + ":" + AsString(y); }
|
||||
#endif
|
||||
};
|
||||
|
||||
inline bool operator<(PageY a, PageY b)
|
||||
{
|
||||
return a.page < b.page ? true : a.page == b.page ? a.y < b.y : false;
|
||||
}
|
||||
|
||||
inline bool operator==(PageY a, PageY b)
|
||||
{
|
||||
return a.page == b.page && a.y == b.y;
|
||||
}
|
||||
|
||||
inline PageY operator+(PageY a, int b)
|
||||
{
|
||||
return PageY(a.page, a.y + b);
|
||||
}
|
||||
|
||||
struct PageRect : public Rect {
|
||||
int page;
|
||||
|
||||
operator int() const { return page; }
|
||||
operator PageY() const { return PageY(page, top); }
|
||||
PageRect& operator=(const Rect& r) { (Rect&)(*this) = r; page = 0; return *this; }
|
||||
PageRect(const Rect& r) { (Rect&)(*this) = r; page = 0; }
|
||||
PageRect() { Clear(); page = 0; }
|
||||
};
|
||||
|
||||
struct PageDraw {
|
||||
virtual Draw& Info() = 0;
|
||||
virtual Draw& Page(int i) = 0;
|
||||
|
||||
operator Draw&() { return Info(); }
|
||||
|
||||
virtual ~PageDraw() {}
|
||||
};
|
||||
|
||||
class RichObject;
|
||||
class Bar;
|
||||
|
||||
struct RichObjectType : Moveable<RichObjectType> {
|
||||
virtual String GetTypeName(const Value& v) const = 0;
|
||||
virtual String GetCreateName() const;
|
||||
virtual Size GetDefaultSize(const Value& data, Size maxsize) const;
|
||||
virtual Size GetPhysicalSize(const Value& data) const;
|
||||
virtual Size GetPixelSize(const Value& data) const;
|
||||
virtual void Paint(const Value& data, Draw& w, Size sz) const;
|
||||
virtual Image ToImage(const Value& data, Size sz) const;
|
||||
virtual Value Read(const String& s) const;
|
||||
virtual String Write(const Value& v) const;
|
||||
virtual void Menu(Bar& bar, RichObject& ex) const;
|
||||
virtual void DefaultAction(RichObject& ex) const;
|
||||
virtual String GetLink(const Value& data, Point pt, Size sz) const;
|
||||
|
||||
virtual bool Accept(PasteClip& clip);
|
||||
virtual Value Read(PasteClip& clip);
|
||||
virtual String GetClipFmts() const;
|
||||
virtual String GetClip(const Value& data, const String& fmt) const;
|
||||
|
||||
RichObjectType();
|
||||
virtual ~RichObjectType();
|
||||
};
|
||||
|
||||
class RichObject : Moveable<RichObject> {
|
||||
Value data;
|
||||
int ydelta;
|
||||
Size size;
|
||||
Size physical_size;
|
||||
Size pixel_size;
|
||||
bool keepratio;
|
||||
const RichObjectType *type;
|
||||
int64 serial;
|
||||
String type_name;
|
||||
|
||||
static VectorMap<String, RichObjectType *>& Map();
|
||||
|
||||
void NewSerial();
|
||||
|
||||
public:
|
||||
static void Register(const char *name, RichObjectType *type) init_;
|
||||
static int GetTypeCount() { return Map().GetCount(); }
|
||||
static int FindType(const String& name) { return Map().Find(name); }
|
||||
static RichObjectType& GetType(int i) { return *Map()[i]; }
|
||||
static String GetTypeName(int i) { return Map().GetKey(i); }
|
||||
|
||||
void SetSize(int cx, int cy) { size = Size(cx, cy); NewSerial(); }
|
||||
void SetSize(Size sz) { size = sz; NewSerial(); }
|
||||
Size GetSize() const { return size; }
|
||||
void Paint(Draw& w, Size sz) const;
|
||||
Image ToImage(Size sz) const;
|
||||
Size GetPhysicalSize() const { return physical_size; }
|
||||
Size GetPixelSize() const { return pixel_size; }
|
||||
Size GetDefaultSize(Size maxsize) const { return type ? type->GetDefaultSize(data, maxsize) : physical_size; }
|
||||
|
||||
void Set(RichObjectType *type, const Value& data, Size maxsize = Size(3967, 3967));
|
||||
bool Set(const String& type_name, const Value& data, Size maxsize = Size(3967, 3967));
|
||||
|
||||
String GetTypeName() const;
|
||||
Value GetData() const { return data; }
|
||||
String GetLink(Point pt, Size sz) const { return type ? type->GetLink(data, pt, sz) : String(); }
|
||||
|
||||
const RichObjectType& GetType() const;
|
||||
|
||||
bool Read(const String& type, const String& data, Size sz);
|
||||
String Write() const { return type ? type->Write(data) : (String)data; }
|
||||
|
||||
void KeepRatio(bool b) { keepratio = b; }
|
||||
bool IsKeepRatio() const { return keepratio; }
|
||||
|
||||
void SetYDelta(int yd) { ydelta = yd; }
|
||||
int GetYDelta() const { return ydelta; }
|
||||
|
||||
void Menu(Bar& bar) { if(type) type->Menu(bar, *this); }
|
||||
void DefaultAction() { if(type) type->DefaultAction(*this); }
|
||||
|
||||
operator bool() const { return !IsNull(data); }
|
||||
|
||||
void Clear();
|
||||
|
||||
int64 GetSerialId() const { return serial; }
|
||||
|
||||
void InitSize(int cx, int cy);
|
||||
|
||||
RichObject();
|
||||
RichObject(RichObjectType *type, const Value& data, Size maxsize = Size(3967, 3967));
|
||||
RichObject(const String& type, const Value& data, Size maxsize = Size(3967, 3967));
|
||||
};
|
||||
|
||||
RichObject CreateDrawingObject(const Drawing& dwg, Size dot_size, Size size);
|
||||
RichObject CreateDrawingObject(const Drawing& dwg, int cx = 0, int cy = 0);
|
||||
RichObject CreatePNGObject(const Image& img, Size dot_size, Size size);
|
||||
RichObject CreatePNGObject(const Image& img, Size dot_size, Size size);
|
||||
RichObject CreateImageObject(const Image& img, int cx = 0, int cy = 0);
|
||||
RichObject CreateRawImageObject(const String& s, int cx = 0, int cy = 0);
|
||||
|
||||
struct RichPara;
|
||||
|
||||
enum {
|
||||
RICHHOT_LM = -1,
|
||||
RICHHOT_RM = -2,
|
||||
};
|
||||
|
||||
struct RichHotPos {
|
||||
int table;
|
||||
int column;
|
||||
int delta;
|
||||
int left, cx;
|
||||
int textleft, textcx;
|
||||
|
||||
RichHotPos() { table = 0; column = Null; }
|
||||
};
|
||||
|
||||
struct RichValPos : Moveable<RichValPos> {
|
||||
PageY py;
|
||||
int pos;
|
||||
WString data;
|
||||
};
|
||||
|
||||
struct PaintInfo {
|
||||
Zoom zoom;
|
||||
int sell, selh;
|
||||
int tablesel;
|
||||
Rect cells;
|
||||
PageY top;
|
||||
PageY bottom;
|
||||
Color hyperlink;
|
||||
Color indexentry;
|
||||
bool usecache;
|
||||
bool sizetracking;
|
||||
Color showcodes;
|
||||
Bits (*spellingchecker)(const RichPara& para);
|
||||
int highlightpara;
|
||||
Color highlight;
|
||||
bool coloroverride;
|
||||
|
||||
PaintInfo();
|
||||
};
|
||||
|
||||
int LineZoom(Zoom z, int a);
|
||||
|
||||
class RichTable;
|
||||
|
||||
#include "Para.h"
|
||||
|
||||
struct RichPos {
|
||||
int tabtextparti;
|
||||
int tabtextpartcount;
|
||||
int tabposintabtext;
|
||||
int tabtextlen;
|
||||
|
||||
int table;
|
||||
Size tabsize;
|
||||
Point cell;
|
||||
|
||||
int tablen;
|
||||
int posintab;
|
||||
|
||||
int celllen;
|
||||
int posincell;
|
||||
|
||||
int parai;
|
||||
int partcount;
|
||||
int posinpara;
|
||||
int paralen;
|
||||
|
||||
int level;
|
||||
int parenttab;
|
||||
|
||||
RichPara::Format format;
|
||||
int chr;
|
||||
RichObject object;
|
||||
Id field;
|
||||
String fieldparam;
|
||||
RichPara::CharFormat fieldformat;
|
||||
|
||||
#ifdef _DEBUG
|
||||
String ToString() const;
|
||||
#endif
|
||||
|
||||
RichPos();
|
||||
};
|
||||
|
||||
inline bool InSameTxt(const RichPos& a, const RichPos& b)
|
||||
{
|
||||
return a.table == b.table && (a.table == 0 || a.cell == b.cell);
|
||||
}
|
||||
|
||||
struct RichCaret : PageRect {
|
||||
int lineascent;
|
||||
int caretascent;
|
||||
int caretdescent;
|
||||
int objectcy;
|
||||
int objectyd;
|
||||
int line;
|
||||
Rect textpage;
|
||||
|
||||
RichCaret() { lineascent = caretascent = caretdescent = 0; }
|
||||
};
|
||||
|
||||
struct RichStyle {
|
||||
RichPara::Format format;
|
||||
String name;
|
||||
Uuid next;
|
||||
|
||||
static Uuid GetDefaultId();
|
||||
static const RichStyle& GetDefault();
|
||||
|
||||
RichStyle() { next = GetDefaultId(); }
|
||||
};
|
||||
|
||||
typedef ArrayMap<Uuid, RichStyle> RichStyles;
|
||||
|
||||
const RichStyle& GetStyle(const RichStyles& s, const Uuid& id);
|
||||
int FindStyleWithName(const RichStyles& style, const String& name);
|
||||
|
||||
struct RichContext {
|
||||
const RichStyles& styles;
|
||||
Rect page;
|
||||
PageY py;
|
||||
|
||||
void Page() { py.page++; py.y = page.top; }
|
||||
|
||||
RichContext(const RichStyles& styles) : styles(styles) {}
|
||||
};
|
||||
|
||||
struct RichCellPos;
|
||||
|
||||
#include "Txt.h"
|
||||
#include "Table.h"
|
||||
#include "Text.h"
|
||||
|
||||
struct RichCellPos {
|
||||
int pos;
|
||||
|
||||
int textlen;
|
||||
|
||||
Size tabsize;
|
||||
int tabpos;
|
||||
int tablen;
|
||||
int cellpos;
|
||||
int celllen;
|
||||
int level;
|
||||
RichCell::Format format;
|
||||
RichTable::Format tableformat;
|
||||
|
||||
#ifdef _DEBUG
|
||||
String ToString() const;
|
||||
#endif
|
||||
};
|
||||
|
||||
String DeQtf(const char *s);
|
||||
String DeQtfLf(const char *s);
|
||||
|
||||
struct QtfRichObject {
|
||||
RichObject obj;
|
||||
|
||||
public:
|
||||
String ToString() const;
|
||||
|
||||
QtfRichObject() {}
|
||||
QtfRichObject(const RichObject& o);
|
||||
};
|
||||
|
||||
String AsQTF(const RichObject& obj);
|
||||
|
||||
RichText ParseQTF(const char *qtf, bool scolors = false, byte accesskey = 0);
|
||||
|
||||
RichText AsRichText(const wchar *s, const RichPara::Format& f = RichPara::Format());
|
||||
|
||||
enum
|
||||
{
|
||||
QTF_BODY = 1,
|
||||
QTF_ALL_STYLES = 2,
|
||||
QTF_NOSTYLES = 4,
|
||||
QTF_CRLF = 8,
|
||||
QTF_NOCHARSET = 16,
|
||||
QTF_NOLANG = 32,
|
||||
};
|
||||
|
||||
String AsQTF(const RichText& doc, byte charset = CHARSET_UTF8,
|
||||
dword options = QTF_BODY|QTF_ALL_STYLES|QTF_CRLF);
|
||||
|
||||
inline String StylesAsQTF(const RichText& doc, byte charset = CHARSET_UTF8)
|
||||
{ return AsQTF(doc, charset, QTF_ALL_STYLES|QTF_CRLF); }
|
||||
|
||||
inline String BodyAsQTF(const RichText& doc, byte charset = CHARSET_UTF8)
|
||||
{ return AsQTF(doc, charset, QTF_BODY|QTF_CRLF); }
|
||||
|
||||
enum
|
||||
{
|
||||
ROUNDOFF = 1 << 20,
|
||||
MAX_FONTS = 10000,
|
||||
MAX_DOTS = 600 * 100,
|
||||
MAX_DOT_HEIGHT = 1200,
|
||||
MAX_POINT_HEIGHT = MAX_DOT_HEIGHT * 3 / 25,
|
||||
};
|
||||
|
||||
inline int DotTwips (int dots) { return (dots * 12 + 5 * ROUNDOFF + 2) / 5 - ROUNDOFF; }
|
||||
inline int TwipDots (int twp) { return (twp * 5 + 12 * ROUNDOFF + 6) / 12 - ROUNDOFF; }
|
||||
inline int DotPoints(int dots) { return (dots * 3 + 25 * ROUNDOFF + 12) / 25 - ROUNDOFF; }
|
||||
inline int PointDots(int pts) { return (pts * 25 + 3 * ROUNDOFF + 1) / 3 - ROUNDOFF; }
|
||||
inline int TwipDotSize(int twp) { return IsNull(twp) ? 0 : minmax<int>(TwipDots(twp), 0, MAX_DOTS); }
|
||||
inline int PointDotHeight(int p) { return (minmax<int>(Nvl(p, 0), 0, MAX_POINT_HEIGHT) * 25 + 5) / 6; }
|
||||
|
||||
void EncodeRTF(Stream& stream, const RichText& richtext, byte charset);
|
||||
String EncodeRTF(const RichText& richtext, byte charset);
|
||||
String EncodeRTF(const RichText& richtext);
|
||||
RichText ParseRTF(const char *rtf);
|
||||
|
||||
Zoom GetRichTextStdScreenZoom();
|
||||
|
||||
const Display& QTFDisplay();
|
||||
const Display& QTFDisplayVCenter();
|
||||
|
||||
String EncodeHtml(const RichText& text, Index<String>& css,
|
||||
const VectorMap<String, String>& links,
|
||||
const VectorMap<String, String>& labels,
|
||||
const String& path, const String& base = Null, Zoom z = Zoom(8, 40),
|
||||
const VectorMap<String, String>& escape = VectorMap<String, String>(),
|
||||
int imtolerance = 0);
|
||||
String AsCss(Index<String>& ss);
|
||||
|
||||
inline //BW - no labels
|
||||
String EncodeHtml(const RichText& text, Index<String>& css,
|
||||
const VectorMap<String, String>& links,
|
||||
const String& path, const String& base = Null, Zoom z = Zoom(8, 40)) {
|
||||
return EncodeHtml(text, css, links, VectorMap<String, String>(), path, base, z);
|
||||
}
|
||||
|
||||
struct SimplePageDraw : PageDraw {
|
||||
Draw& w;
|
||||
|
||||
virtual Draw& Info();
|
||||
virtual Draw& Page(int);
|
||||
|
||||
SimplePageDraw(Draw& w) : w(w) {}
|
||||
virtual ~SimplePageDraw() {}
|
||||
};
|
||||
|
||||
struct PrintPageDraw : PageDraw {
|
||||
int page;
|
||||
Draw& w;
|
||||
NilDraw nw;
|
||||
|
||||
Draw& Page(int _page) { return page == _page ? w : (Draw&)nw; }
|
||||
Draw& Info() { return w; }
|
||||
void SetPage(int _page) { page = _page; }
|
||||
|
||||
PrintPageDraw(Draw& w) : w(w) {}
|
||||
virtual ~PrintPageDraw() {}
|
||||
};
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
||||
#endif
|
||||
9
uppdev/RichTextP/RichText.iml
Normal file
9
uppdev/RichTextP/RichText.iml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
IMAGE_ID(EndParaChar)
|
||||
IMAGE_ID(TabChar)
|
||||
IMAGE_ID(SpaceChar)
|
||||
IMAGE_ID(HardSpaceChar)
|
||||
|
||||
IMAGE_BEGIN_DATA
|
||||
IMAGE_DATA(120,156,99,96,101,224,96,192,3,254,147,33,246,31,11,141,206,70,199,232,234,176,155,205,198,192,74,138,67,73,177,28)
|
||||
IMAGE_DATA(155,122,236,230,51,1,157,129,199,34,92,6,64,0,11,225,224,198,101,16,46,62,97,75,113,0,0,165,164,44,1,0)
|
||||
IMAGE_END_DATA(64, 4)
|
||||
0
uppdev/RichTextP/RichText.usc
Normal file
0
uppdev/RichTextP/RichText.usc
Normal file
39
uppdev/RichTextP/RichTextP.upp
Normal file
39
uppdev/RichTextP/RichTextP.upp
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
description "Rich-text data structures and painting, including RTF and HTML export/import";
|
||||
|
||||
file
|
||||
RichText.h,
|
||||
Object.cpp,
|
||||
RichImage.icpp,
|
||||
Para.h,
|
||||
ParaData.cpp optimize_speed,
|
||||
ParaType.cpp optimize_speed,
|
||||
ParaPaint.cpp,
|
||||
Txt.h,
|
||||
TxtData.cpp,
|
||||
TxtPaint.cpp,
|
||||
TxtOp.cpp,
|
||||
Format.cpp,
|
||||
Table.h,
|
||||
TableCell.cpp,
|
||||
TableLayout.cpp,
|
||||
TablePaint.cpp,
|
||||
TableData.cpp,
|
||||
Text.h,
|
||||
TextPaint.cpp,
|
||||
TextStyle.cpp,
|
||||
TextData.cpp,
|
||||
TextTable.cpp,
|
||||
EncodeQtf.cpp optimize_speed,
|
||||
ParseQtf.cpp optimize_speed,
|
||||
EncodeRTF.cpp optimize_speed,
|
||||
ParseRTF.cpp optimize_speed,
|
||||
EncodeHTML.cpp optimize_speed,
|
||||
Util.cpp,
|
||||
RichText.iml,
|
||||
Info readonly separator,
|
||||
srcdoc.tpp,
|
||||
Copying;
|
||||
|
||||
mainconfig
|
||||
"" = "";
|
||||
|
||||
220
uppdev/RichTextP/Table.h
Normal file
220
uppdev/RichTextP/Table.h
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
class RichCell : DeepCopyOption<RichCell> {
|
||||
public:
|
||||
struct Format {
|
||||
Rect border;
|
||||
Rect margin;
|
||||
int align;
|
||||
int minheight;
|
||||
Color color;
|
||||
Color bordercolor;
|
||||
bool keep;
|
||||
|
||||
Format();
|
||||
};
|
||||
|
||||
Format format;
|
||||
int vspan, hspan;
|
||||
RichTxt text;
|
||||
|
||||
private:
|
||||
bool Reduce(RichContext& rc) const;
|
||||
PageY Align(const RichContext& rc, PageY npy) const;
|
||||
void DrawCell(Draw& w, int l, int r, int y, int yy, const Rect& border) const;
|
||||
|
||||
void ClearText();
|
||||
void ClearText(const RichPara::Format& format, const RichStyles& style);
|
||||
void Clear();
|
||||
|
||||
PageY GetTop(RichContext rc) const;
|
||||
PageY GetHeight(RichContext rc) const;
|
||||
void Paint(PageDraw& pw, RichContext rc, PageY npy,
|
||||
const Rect& xpg, int y, int ny, const PaintInfo& pi,
|
||||
bool select) const;
|
||||
RichCaret GetCaret(int pos, RichContext rc, PageY pyy) const;
|
||||
int GetPos(int x, PageY y, RichContext rc, PageY pyy) const;
|
||||
RichHotPos GetHotPos(int x, PageY y, int tolerance, RichContext rc, PageY pyy) const;
|
||||
|
||||
void GatherValPos(Vector<RichValPos>& f, RichContext rc, PageY pyy, int pos, int type) const;
|
||||
|
||||
friend class RichTable;
|
||||
friend class RichText;
|
||||
|
||||
public:
|
||||
RichCell(const RichCell& src, int);
|
||||
RichCell();
|
||||
};
|
||||
|
||||
class RichTable : DeepCopyOption<RichTable> {
|
||||
public:
|
||||
struct Format {
|
||||
int before, lm, rm, after;
|
||||
int frame;
|
||||
Color framecolor;
|
||||
int grid;
|
||||
Color gridcolor;
|
||||
WithDeepCopy< Vector<int> > column;
|
||||
int header;
|
||||
bool keep;
|
||||
|
||||
Format();
|
||||
};
|
||||
|
||||
struct CellInfo {
|
||||
bool valid;
|
||||
Point master;
|
||||
|
||||
operator bool() const { return valid; }
|
||||
|
||||
CellInfo() { valid = true; }
|
||||
};
|
||||
|
||||
Format format;
|
||||
Array< Array<RichCell> > cell;
|
||||
|
||||
private:
|
||||
struct PaintCell : Moveable<PaintCell> {
|
||||
int left;
|
||||
int right;
|
||||
Rect page;
|
||||
PageY hy;
|
||||
bool top;
|
||||
bool bottom;
|
||||
|
||||
PaintCell() { top = true; }
|
||||
};
|
||||
|
||||
struct PaintRow : Moveable<PaintRow> {
|
||||
PageY gpy;
|
||||
PageY py, pyy;
|
||||
Buffer<PaintCell> cell;
|
||||
bool first;
|
||||
|
||||
PaintCell& operator[](int i) { return cell[i]; }
|
||||
const PaintCell& operator[](int i) const { return cell[i]; }
|
||||
};
|
||||
|
||||
struct Layout {
|
||||
Buffer<Rect> col;
|
||||
Buffer<PaintRow> row;
|
||||
int frame;
|
||||
int grid;
|
||||
PageY pyy;
|
||||
|
||||
PaintRow& operator[](int i) { return row[i]; }
|
||||
const PaintRow& operator[](int i) const { return row[i]; }
|
||||
};
|
||||
|
||||
struct TabLayout : Layout {
|
||||
bool hasheader;
|
||||
Layout header;
|
||||
Rect page;
|
||||
int page0;
|
||||
Size sz;
|
||||
};
|
||||
|
||||
mutable TabLayout clayout;
|
||||
mutable Rect cpage;
|
||||
mutable PageY cpy;
|
||||
|
||||
Buffer< Buffer<CellInfo> > ci;
|
||||
int r_row, r_column;
|
||||
Rect r_page;
|
||||
PageY r_py, r_pyy;
|
||||
|
||||
void Invalidate();
|
||||
void InvalidateRefresh(int i, int j);
|
||||
void InvalidateRefresh(Point p) { InvalidateRefresh(p.y, p.x); }
|
||||
|
||||
bool Reduce(RichContext& rc) const;
|
||||
Layout Realize(RichContext rc, int ny) const;
|
||||
bool RowPaint(PageDraw& pw, const RichStyles& st, const Layout& tab,
|
||||
int i, int ny, const Rect& pg, VectorMap<int, Rect>& frr,
|
||||
PaintInfo& pi, int pd, bool sel) const;
|
||||
|
||||
const TabLayout& Realize(RichContext rc) const;
|
||||
|
||||
mutable int length, tabcount;
|
||||
|
||||
static void ExpandFrr(VectorMap<int, Rect>& frr, int pi, int l, int r, int t, int b);
|
||||
|
||||
friend class RichTxt;
|
||||
friend class RichText;
|
||||
public:
|
||||
|
||||
Array<RichCell>& operator[](int i) { return cell[i]; }
|
||||
const Array<RichCell>& operator[](int i) const { return cell[i]; }
|
||||
RichCell& operator[](Point p) { return cell[p.y][p.x]; }
|
||||
const RichCell& operator[](Point p) const { return cell[p.y][p.x]; }
|
||||
int GetCellPos(int i, int j) const;
|
||||
int GetCellPos(Point p) const { return GetCellPos(p.y, p.x); }
|
||||
int GetTableCount(int i, int j) const;
|
||||
int GetTableCount(Point p) const { return GetTableCount(p.y, p.x); }
|
||||
Point GetMasterCell(int i, int j) const;
|
||||
Point GetMasterCell(Point p) const { return GetMasterCell(p.y, p.x); }
|
||||
const RichCell& GetMaster(int i, int j) const;
|
||||
|
||||
int GetLength() const;
|
||||
int GetTableCount() const;
|
||||
|
||||
private:
|
||||
void Normalize0();
|
||||
|
||||
RichTable Copy(const Rect& sel) const;
|
||||
void Paste(Point pos, const RichTable& tab);
|
||||
void RemoveRow0(int rowi);
|
||||
void RemoveRow(int rowi);
|
||||
void InsertRow(int rowi, const RichStyles& style);
|
||||
void RemoveColumn0(int column);
|
||||
void RemoveColumn(int column);
|
||||
void InsertColumn(int column, const RichStyles& style);
|
||||
bool IsRowEmpty(int row);
|
||||
bool IsColumnEmpty(int column);
|
||||
void SplitCell(Point cl, Size sz, const RichStyles& style);
|
||||
RichCell::Format GetCellFormat(const Rect& sel) const;
|
||||
void SetCellFormat(const Rect& sel, const RichCell::Format& fmt, bool setkeep);
|
||||
|
||||
PageY GetHeight(RichContext rc) const;
|
||||
PageY GetTop(RichContext rc) const;
|
||||
void Paint(PageDraw& pw, RichContext rc, const PaintInfo& pi) const;
|
||||
RichCaret GetCaret(int pos, RichContext rc) const;
|
||||
int GetPos(int x, PageY y, RichContext rc) const;
|
||||
int GetVertMove(int pos, int gx, RichContext rc, int dir) const;
|
||||
RichHotPos GetHotPos(int x, PageY y, int tolerance, RichContext rc) const;
|
||||
void AdjustSel(Rect& sel) const;
|
||||
|
||||
void GatherValPos(Vector<RichValPos>& f, RichContext rc, int pos, int type) const;
|
||||
void ClearSpelling();
|
||||
|
||||
Point FindCell(int& pos) const;
|
||||
RichPos GetRichPos(int pos, const RichStyles& st) const;
|
||||
|
||||
CellInfo GetCellInfo(int i, int j) { return ci[i][j]; }
|
||||
|
||||
int GetInvalid(PageY& top, PageY& bottom, RichContext rc) const;
|
||||
void Validate();
|
||||
|
||||
void ApplyZoom(Zoom z, const RichStyles& ostyle, const RichStyles& zstyle);
|
||||
|
||||
public:
|
||||
void AddColumn(int cx);
|
||||
void SetPick(int i, int j, pick_ RichTxt& text);
|
||||
RichTxt GetPick(int i, int j);
|
||||
const RichTxt& Get(int i, int j) const { return cell[i][j].text; }
|
||||
void SetQTF(int i, int j, const char *qtf);
|
||||
void SetFormat(int i, int j, const RichCell::Format& fmt);
|
||||
const RichCell::Format& GetFormat(int i, int j) { return cell[i][j].format; }
|
||||
bool operator()(int i, int j) const { return ci[i][j].valid; }
|
||||
void SetSpan(int i, int j, int vspan, int hspan);
|
||||
Size GetSpan(int i, int j) const;
|
||||
void SetFormat(const Format& fmt);
|
||||
const Format& GetFormat() const { return format; }
|
||||
|
||||
int GetColumns() const { return format.column.GetCount(); }
|
||||
int GetRows() const { return cell.GetCount(); }
|
||||
Size GetSize() const { return Size(GetColumns(), GetRows()); }
|
||||
|
||||
void Normalize();
|
||||
|
||||
RichTable(const RichTable& src, int);
|
||||
RichTable();
|
||||
};
|
||||
194
uppdev/RichTextP/TableCell.cpp
Normal file
194
uppdev/RichTextP/TableCell.cpp
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
#include "RichText.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
int LineZoom(Zoom z, int a)
|
||||
{
|
||||
return a ? max(1, z * a) : 0;
|
||||
}
|
||||
|
||||
RichCell::Format::Format()
|
||||
{
|
||||
margin.left = margin.right = 25;
|
||||
margin.top = margin.bottom = 15;
|
||||
border.Clear();
|
||||
align = ALIGN_CENTER;
|
||||
color = White;
|
||||
bordercolor = Black;
|
||||
keep = false;
|
||||
minheight = 0;
|
||||
}
|
||||
|
||||
void RichCell::ClearText()
|
||||
{
|
||||
text.Clear();
|
||||
RichPara h;
|
||||
text.Cat(h, RichStyles());
|
||||
}
|
||||
|
||||
void RichCell::ClearText(const RichPara::Format& format, const RichStyles& style)
|
||||
{
|
||||
text.Clear();
|
||||
RichPara h;
|
||||
h.format = format;
|
||||
text.Cat(h, style);
|
||||
}
|
||||
|
||||
void RichCell::Clear()
|
||||
{
|
||||
format = Format();
|
||||
vspan = hspan = 0;
|
||||
ClearText();
|
||||
}
|
||||
|
||||
bool RichCell::Reduce(RichContext& rc) const
|
||||
{
|
||||
Rect br = rc.page;
|
||||
rc.page.top += format.margin.top + format.border.top;
|
||||
rc.page.bottom -= format.margin.bottom + format.border.bottom;
|
||||
rc.page.left += format.margin.left + format.border.left;
|
||||
rc.page.right -= format.margin.right + format.border.right;
|
||||
if(rc.page.IsEmpty())
|
||||
rc.page = br;
|
||||
return !rc.page.IsEmpty();
|
||||
}
|
||||
|
||||
PageY RichCell::GetTop(RichContext rc) const
|
||||
{
|
||||
if(!Reduce(rc))
|
||||
return rc.py;
|
||||
rc.py.y += format.margin.top + format.border.top;
|
||||
return text.GetTop(rc);
|
||||
}
|
||||
|
||||
PageY RichCell::GetHeight(RichContext rc) const
|
||||
{
|
||||
if(Reduce(rc)) {
|
||||
PageY py = rc.py;
|
||||
rc.py.y += format.margin.top + format.border.top;
|
||||
rc.py = text.GetHeight(rc);
|
||||
rc.py.y += format.margin.bottom + format.border.bottom;
|
||||
py.y += format.margin.top + format.border.top +
|
||||
format.minheight +
|
||||
format.margin.bottom + format.border.bottom;
|
||||
return py.y <= rc.page.bottom && py > rc.py ? py : rc.py;
|
||||
}
|
||||
else {
|
||||
rc.py.y += format.margin.top + format.border.top;
|
||||
rc.py.y += 80;
|
||||
rc.py.y += format.margin.bottom + format.border.bottom;
|
||||
if(rc.py.y >= rc.page.bottom) {
|
||||
rc.Page();
|
||||
rc.py.y += 80;
|
||||
}
|
||||
}
|
||||
return rc.py;
|
||||
}
|
||||
|
||||
void RichCell::DrawCell(Draw& w, int l, int r, int y, int yy, const Rect& border) const
|
||||
{
|
||||
w.DrawRect(l, y, r - l, border.top, format.bordercolor);
|
||||
w.DrawRect(l, y, border.left, yy - y, format.bordercolor);
|
||||
w.DrawRect(r - border.right, y, border.right, yy - y, format.bordercolor);
|
||||
w.DrawRect(l, yy - border.bottom, r - l, border.bottom, format.bordercolor);
|
||||
w.DrawRect(l + border.left, y + border.top,
|
||||
r - l - border.left - border.right, yy - y - border.top - border.bottom,
|
||||
format.color);
|
||||
}
|
||||
|
||||
PageY RichCell::Align(const RichContext& rc, PageY npy) const
|
||||
{
|
||||
PageY y = rc.py;
|
||||
y.y += format.margin.top + format.border.top;
|
||||
if(rc.py.page == npy.page) {
|
||||
int dx = npy.y - text.GetHeight(rc).y
|
||||
- format.margin.top - format.border.top
|
||||
- format.margin.bottom - format.border.bottom;
|
||||
if(format.align == ALIGN_CENTER)
|
||||
y.y += dx / 2;
|
||||
else
|
||||
if(format.align == ALIGN_BOTTOM)
|
||||
y.y += dx;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
void RichCell::Paint(PageDraw& pw, RichContext rc, PageY npy,
|
||||
const Rect& xpg, int y, int ny, const PaintInfo& pi, bool select) const
|
||||
{
|
||||
if(!Reduce(rc))
|
||||
return;
|
||||
Rect border(LineZoom(pi.zoom, format.border.left), LineZoom(pi.zoom, format.border.top),
|
||||
LineZoom(pi.zoom, format.border.right), LineZoom(pi.zoom, format.border.bottom));
|
||||
if(rc.py.page == npy.page)
|
||||
DrawCell(pw.Page(rc.py.page), xpg.left, xpg.right, y, ny, border);
|
||||
else {
|
||||
DrawCell(pw.Page(rc.py.page), xpg.left, xpg.right, y, xpg.bottom, border);
|
||||
for(int i = rc.py.page + 1; i < npy.page; i++)
|
||||
DrawCell(pw.Page(i), xpg.left, xpg.right, xpg.top, xpg.bottom, border);
|
||||
DrawCell(pw.Page(npy.page), xpg.left, xpg.right, xpg.top, ny, border);
|
||||
}
|
||||
|
||||
rc.py = Align(rc, npy);
|
||||
text.Paint(pw, rc, pi);
|
||||
|
||||
if(select) {
|
||||
int cx = xpg.right - xpg.left;
|
||||
if(rc.py.page == npy.page)
|
||||
pw.Page(rc.py.page).DrawRect(xpg.left, y, cx, ny - y, InvertColor);
|
||||
else {
|
||||
pw.Page(rc.py.page).DrawRect(xpg.left, y, cx, xpg.bottom - y, InvertColor);
|
||||
for(int i = rc.py.page + 1; i < npy.page; i++)
|
||||
pw.Page(i).DrawRect(xpg.left, xpg.top, cx, xpg.Height(), InvertColor);
|
||||
pw.Page(npy.page).DrawRect(xpg.left, xpg.top, cx, ny - xpg.top, InvertColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RichCaret RichCell::GetCaret(int pos, RichContext rc, PageY pyy) const
|
||||
{
|
||||
if(!Reduce(rc))
|
||||
return RichCaret();
|
||||
rc.py = Align(rc, pyy);
|
||||
return text.GetCaret(pos, rc);
|
||||
}
|
||||
|
||||
int RichCell::GetPos(int x, PageY y, RichContext rc, PageY pyy) const
|
||||
{
|
||||
if(!Reduce(rc))
|
||||
return 0;
|
||||
rc.py = Align(rc, pyy);
|
||||
return text.GetPos(x, y, rc);
|
||||
}
|
||||
|
||||
RichHotPos RichCell::GetHotPos(int x, PageY y, int tolerance, RichContext rc, PageY pyy) const
|
||||
{
|
||||
if(!Reduce(rc))
|
||||
return RichHotPos();
|
||||
rc.py = Align(rc, pyy);
|
||||
return text.GetHotPos(x, y, tolerance, rc);
|
||||
}
|
||||
|
||||
void RichCell::GatherValPos(Vector<RichValPos>& f, RichContext rc, PageY pyy, int pos, int type) const
|
||||
{
|
||||
if(!Reduce(rc))
|
||||
return;
|
||||
rc.py = Align(rc, pyy);
|
||||
text.GatherValPos(f, rc, pos, type);
|
||||
}
|
||||
|
||||
RichCell::RichCell()
|
||||
{
|
||||
vspan = hspan = 0;
|
||||
Clear();
|
||||
}
|
||||
|
||||
RichCell::RichCell(const RichCell& src, int)
|
||||
{
|
||||
format = src.format;
|
||||
hspan = src.hspan;
|
||||
vspan = src.vspan;
|
||||
text <<= src.text;
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
580
uppdev/RichTextP/TableData.cpp
Normal file
580
uppdev/RichTextP/TableData.cpp
Normal file
|
|
@ -0,0 +1,580 @@
|
|||
#include "RichText.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
void RichTable::Invalidate()
|
||||
{
|
||||
cpy.page = -1;
|
||||
length = tabcount = -1;
|
||||
}
|
||||
|
||||
void RichTable::InvalidateRefresh(int i, int j)
|
||||
{
|
||||
if(i < format.header)
|
||||
r_row = -1;
|
||||
else
|
||||
if(r_row != i || r_column != j)
|
||||
if(r_row == -2 && clayout.sz == GetSize()) {
|
||||
r_row = i;
|
||||
r_column = j;
|
||||
r_py = cpy;
|
||||
r_pyy = clayout[min(GetRows() - 1, i + cell[i][j].vspan)].pyy;
|
||||
r_page = cpage;
|
||||
}
|
||||
else
|
||||
r_row = -1;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void RichTable::Normalize0()
|
||||
{
|
||||
int nx = format.column.GetCount();
|
||||
int ny = cell.GetCount();
|
||||
|
||||
for(int i = 0; i < ny; i++)
|
||||
cell[i].SetCount(nx);
|
||||
|
||||
Invalidate();
|
||||
r_py.page = -1;
|
||||
r_row = -1;
|
||||
|
||||
ci.Alloc(ny);
|
||||
for(int i = 0; i < ny; i++)
|
||||
ci[i].Alloc(nx);
|
||||
for(int i = 0; i < ny; i++)
|
||||
for(int j = 0; j < nx; j++)
|
||||
if(ci[i][j].valid) {
|
||||
RichCell& c = cell[i][j];
|
||||
int vs = i < format.header ? min(format.header - 1, i + c.vspan) : min(ny - 1, i + c.vspan);
|
||||
int hs = min(nx - 1, j + c.hspan);
|
||||
c.vspan = vs - i;
|
||||
c.hspan = hs - j;
|
||||
for(int ii = i; ii <= vs; ii++)
|
||||
for(int jj = j; jj <= hs; jj++) {
|
||||
if(i != ii || j != jj) {
|
||||
CellInfo& f = ci[ii][jj];
|
||||
f.valid = false;
|
||||
cell[ii][jj].Clear();
|
||||
f.master = Point(j, i);
|
||||
cell[ii][jj].hspan = hs - jj;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RichTable::IsRowEmpty(int row)
|
||||
{
|
||||
for(int i = 0; i < GetColumns(); i++)
|
||||
if(ci[row][i].valid && cell[row][i].vspan == 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RichTable::IsColumnEmpty(int column)
|
||||
{
|
||||
for(int i = 0; i < GetRows(); i++)
|
||||
if(ci[i][column].valid)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void RichTable::RemoveRow0(int rowi)
|
||||
{
|
||||
if(rowi < format.header)
|
||||
format.header--;
|
||||
for(int i = 0; i < GetColumns(); i++) {
|
||||
CellInfo& cf = ci[rowi][i];
|
||||
if(!cf.valid && cf.master.x == i)
|
||||
cell[cf.master.y][cf.master.x].vspan--;
|
||||
}
|
||||
cell.Remove(rowi);
|
||||
}
|
||||
|
||||
void RichTable::RemoveColumn0(int column)
|
||||
{
|
||||
for(int i = 0; i < cell.GetCount(); i++) {
|
||||
CellInfo& cf = ci[i][column];
|
||||
if(!cf.valid && cf.master.y == i)
|
||||
cell[cf.master.y][cf.master.x].hspan--;
|
||||
cell[i].Remove(column);
|
||||
}
|
||||
format.column.Remove(column);
|
||||
}
|
||||
|
||||
void RichTable::Normalize()
|
||||
{
|
||||
Normalize0();
|
||||
int i = 0;
|
||||
while(i < GetRows())
|
||||
if(IsRowEmpty(i)) {
|
||||
Array<RichCell> r(cell[i], 1);
|
||||
RemoveRow0(i);
|
||||
for(int j = 0; j < GetColumns(); j++)
|
||||
if(ci[i][j].valid) {
|
||||
cell[i][j] <<= r[j];
|
||||
cell[i][j].vspan--;
|
||||
}
|
||||
Normalize0();
|
||||
}
|
||||
else
|
||||
i++;
|
||||
int j = 0;
|
||||
while(j < GetColumns())
|
||||
if(IsColumnEmpty(j)) {
|
||||
Array<RichCell> r;
|
||||
for(int i = 0; i < GetRows(); i++)
|
||||
r.Add() <<= cell[i][j];
|
||||
int c = format.column[j];
|
||||
RemoveColumn0(j);
|
||||
format.column[min(GetColumns() - 1, j)] += c;
|
||||
for(int i = 0; i < GetRows(); i++)
|
||||
if(ci[i][j].valid)
|
||||
cell[i][j] <<= r[i];
|
||||
Normalize0();
|
||||
}
|
||||
else
|
||||
j++;
|
||||
int sum = Sum0(format.column);
|
||||
if(sum != 10000) {
|
||||
r_row = -1;
|
||||
if(format.column.GetCount()) {
|
||||
if(format.column.GetCount() > 1) {
|
||||
int q = 0;
|
||||
for(int i = 0; i < format.column.GetCount() - 1; i++)
|
||||
q += sum <= 0 ? (format.column[i] = 10000 / format.column.GetCount())
|
||||
: (format.column[i] = format.column[i] * 10000 / sum);
|
||||
format.column[format.column.GetCount() - 1] = 10000 - q;
|
||||
}
|
||||
else
|
||||
format.column[0] = 10000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int RichTable::GetLength() const
|
||||
{
|
||||
if(length < 0) {
|
||||
length = 0;
|
||||
for(int i = 0; i < cell.GetCount(); i++)
|
||||
for(int j = 0; j < format.column.GetCount(); j++)
|
||||
if(ci[i][j].valid)
|
||||
length += cell[i][j].text.GetLength() + 1;
|
||||
}
|
||||
return length ? length - 1 : 0;
|
||||
}
|
||||
|
||||
Point RichTable::FindCell(int& pos) const
|
||||
{
|
||||
for(int i = 0; i < cell.GetCount(); i++)
|
||||
for(int j = 0; j < format.column.GetCount(); j++)
|
||||
if(ci[i][j].valid) {
|
||||
int l = cell[i][j].text.GetLength() + 1;
|
||||
if(pos < l)
|
||||
return Point(j, i);
|
||||
pos -= l;
|
||||
}
|
||||
NEVER();
|
||||
return Point();
|
||||
}
|
||||
|
||||
int RichTable::GetCellPos(int ii, int jj) const
|
||||
{
|
||||
int pos = 0;
|
||||
for(int i = 0; i < ii; i++)
|
||||
for(int j = 0; j < format.column.GetCount(); j++)
|
||||
if(ci[i][j].valid)
|
||||
pos += cell[i][j].text.GetLength() + 1;
|
||||
for(int j = 0; j < jj; j++)
|
||||
if(ci[ii][j].valid)
|
||||
pos += cell[ii][j].text.GetLength() + 1;
|
||||
return pos;
|
||||
}
|
||||
|
||||
Point RichTable::GetMasterCell(int i, int j) const
|
||||
{
|
||||
i = min(GetRows() - 1, i);
|
||||
j = min(GetColumns() - 1, j);
|
||||
const CellInfo& cf = ci[i][j];
|
||||
return cf.valid ? Point(j, i) : cf.master;
|
||||
}
|
||||
|
||||
const RichCell& RichTable::GetMaster(int i, int j) const
|
||||
{
|
||||
Point p = GetMasterCell(i, j);
|
||||
return cell[p.y][p.x];
|
||||
}
|
||||
|
||||
int RichTable::GetTableCount(int ii, int jj) const
|
||||
{
|
||||
int ti = 0;
|
||||
for(int i = 0; i < ii; i++)
|
||||
for(int j = 0; j < format.column.GetCount(); j++)
|
||||
if(ci[i][j].valid)
|
||||
ti += cell[i][j].text.GetTableCount();
|
||||
for(int j = 0; j < jj; j++)
|
||||
if(ci[ii][j].valid)
|
||||
ti += cell[ii][j].text.GetTableCount();
|
||||
return ti;
|
||||
}
|
||||
|
||||
|
||||
void RichTable::ClearSpelling()
|
||||
{
|
||||
for(int i = 0; i < cell.GetCount(); i++)
|
||||
for(int j = 0; j < format.column.GetCount(); j++)
|
||||
if(ci[i][j].valid)
|
||||
cell[i][j].text.ClearSpelling();
|
||||
}
|
||||
|
||||
int RichTable::GetTableCount() const
|
||||
{
|
||||
if(tabcount < 0) {
|
||||
tabcount = 0;
|
||||
for(int i = 0; i < cell.GetCount(); i++) {
|
||||
for(int j = 0; j < format.column.GetCount(); j++)
|
||||
if(ci[i][j].valid)
|
||||
tabcount += cell[i][j].text.GetTableCount();
|
||||
}
|
||||
}
|
||||
return tabcount;
|
||||
}
|
||||
|
||||
void RichTable::Validate()
|
||||
{
|
||||
r_row = -2;
|
||||
}
|
||||
|
||||
int RichTable::GetInvalid(PageY& top, PageY& bottom, RichContext rc) const
|
||||
{
|
||||
if(r_row == -2)
|
||||
return -1;
|
||||
const TabLayout& tab = Realize(rc);
|
||||
if(r_row >= 0 && r_page == rc.page
|
||||
&& r_py == rc.py && tab[min(GetRows() - 1, r_row + cell[r_row][r_column].vspan)].pyy == r_pyy) {
|
||||
const PaintRow& pr = tab[r_row];
|
||||
const RichCell& cl = cell[r_row][r_column];
|
||||
top = pr.py;
|
||||
bottom = tab[min(cell.GetCount() - 1, r_row + cl.vspan)].pyy;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void RichTable::AddColumn(int cx)
|
||||
{
|
||||
format.column.Add(cx);
|
||||
}
|
||||
|
||||
void RichTable::SetPick(int i, int j, pick_ RichTxt& text)
|
||||
{
|
||||
cell.At(i).At(j).text = text;
|
||||
}
|
||||
|
||||
RichTxt RichTable::GetPick(int i, int j)
|
||||
{
|
||||
return cell[i][j].text;
|
||||
}
|
||||
|
||||
void RichTable::SetQTF(int i, int j, const char *qtf)
|
||||
{
|
||||
SetPick(i, j, ParseQTF(qtf));
|
||||
}
|
||||
|
||||
void RichTable::SetFormat(int i, int j, const RichCell::Format& fmt)
|
||||
{
|
||||
cell.At(i).At(j).format = fmt;
|
||||
}
|
||||
|
||||
void RichTable::SetSpan(int i, int j, int vspan, int hspan)
|
||||
{
|
||||
RichCell& c = cell.At(i).At(j);
|
||||
c.vspan = vspan;
|
||||
c.hspan = hspan;
|
||||
}
|
||||
|
||||
Size RichTable::GetSpan(int i, int j) const
|
||||
{
|
||||
const RichCell& c = cell[i][j];
|
||||
return Size(c.hspan, c.vspan);
|
||||
}
|
||||
|
||||
void RichTable::SetFormat(const Format& fmt)
|
||||
{
|
||||
format = fmt;
|
||||
}
|
||||
|
||||
RichTable RichTable::Copy(const Rect& sel) const
|
||||
{
|
||||
RichTable r;
|
||||
r.format = format;
|
||||
r.format.header = max(0, format.header - sel.top);
|
||||
r.format.column.Remove(0, sel.left);
|
||||
r.format.column.SetCount(sel.right - sel.left + 1);
|
||||
for(int i = sel.top; i <= sel.bottom; i++)
|
||||
for(int j = sel.left; j <= sel.right; j++)
|
||||
r.cell.At(i - sel.top).At(j - sel.left) <<= cell[i][j];
|
||||
r.Normalize();
|
||||
return r;
|
||||
}
|
||||
|
||||
void RichTable::RemoveRow(int rowi)
|
||||
{
|
||||
RemoveRow0(rowi);
|
||||
Normalize();
|
||||
}
|
||||
|
||||
void RichTable::InsertRow(int rowi, const RichStyles& style)
|
||||
{
|
||||
if(rowi < format.header)
|
||||
format.header++;
|
||||
int si;
|
||||
if(rowi < GetRows()) {
|
||||
for(int i = 0; i < GetColumns(); i++) {
|
||||
CellInfo& cf = ci[rowi][i];
|
||||
if(!cf.valid && cf.master.x == i)
|
||||
cell[cf.master.y][cf.master.x].vspan++;
|
||||
}
|
||||
si = rowi + 1;
|
||||
}
|
||||
else
|
||||
si = rowi - 1;
|
||||
cell.Insert(rowi).SetCount(GetColumns());
|
||||
if(si >= 0)
|
||||
for(int i = 0; i < GetColumns(); i++) {
|
||||
RichCell& c = cell[rowi][i];
|
||||
const RichCell& sc = cell[si][i];
|
||||
c.format = sc.format;
|
||||
DUMP(sc.hspan);
|
||||
c.hspan = sc.hspan;
|
||||
c.ClearText(sc.text.GetFirstFormat(style), style);
|
||||
}
|
||||
Normalize();
|
||||
}
|
||||
|
||||
void RichTable::RemoveColumn(int column)
|
||||
{
|
||||
RemoveColumn0(column);
|
||||
Normalize();
|
||||
}
|
||||
|
||||
void RichTable::InsertColumn(int column, const RichStyles& style)
|
||||
{
|
||||
int sci = column < GetColumns() ? column + 1 : column - 1;
|
||||
for(int i = 0; i < cell.GetCount(); i++) {
|
||||
CellInfo& cf = ci[i][column];
|
||||
if(!cf.valid && cf.master.y == i)
|
||||
cell[cf.master.y][cf.master.x].hspan++;
|
||||
RichCell& c = cell[i].Insert(column);
|
||||
if(sci >= 0) {
|
||||
const RichCell& sc = cell[i][sci];
|
||||
c.format = sc.format;
|
||||
c.vspan = sc.vspan;
|
||||
c.ClearText(sc.text.GetFirstFormat(style), style);
|
||||
}
|
||||
}
|
||||
int c = format.column[min(column, GetColumns() - 1)];
|
||||
format.column.Insert(column, c);
|
||||
Normalize();
|
||||
}
|
||||
|
||||
void RichTable::SplitCell(Point cl, Size sz, const RichStyles& style)
|
||||
{
|
||||
const RichCell& sc = cell[cl.y][cl.x];
|
||||
int ext = sz.cy - cell[cl.y][cl.x].vspan - 1;
|
||||
if(ext > 0) {
|
||||
cell.InsertN(cl.y + 1, ext);
|
||||
if(cl.y < format.header)
|
||||
format.header += ext;
|
||||
for(int i = 0; i < ext; i++) {
|
||||
cell[cl.y + 1 + i].SetCount(GetColumns());
|
||||
for(int j = 0; j < GetColumns(); j++) {
|
||||
RichCell& c = cell[cl.y + 1 + i][j];
|
||||
const RichCell& sc = cell[cl.y][j];
|
||||
c.format = sc.format;
|
||||
c.hspan = sc.hspan;
|
||||
c.ClearText(sc.text.GetFirstFormat(style), style);
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < GetColumns(); i++) {
|
||||
CellInfo& cf = ci[cl.y][i];
|
||||
if(cf.valid)
|
||||
cell[cl.y][i].vspan += ext;
|
||||
else
|
||||
if(cf.master.x == i)
|
||||
cell[cf.master.y][cf.master.x].vspan += ext;
|
||||
}
|
||||
}
|
||||
|
||||
cell[cl.y][cl.x].vspan = 0;
|
||||
if(ext < 0)
|
||||
cell[cl.y + sz.cy - 1][cl.x].vspan = -ext;
|
||||
for(int i = 1; i < sz.cy; i++) {
|
||||
RichCell& c = cell[cl.y + i][cl.x];
|
||||
c.format = sc.format;
|
||||
c.hspan = sc.hspan;
|
||||
c.ClearText(sc.text.GetFirstFormat(style), style);
|
||||
}
|
||||
|
||||
Normalize0();
|
||||
ext = sz.cx - cell[cl.y][cl.x].hspan - 1;
|
||||
if(ext > 0) {
|
||||
int clx = 0;
|
||||
for(int i = 0; i <= cell[cl.y][cl.x].hspan; i++)
|
||||
clx += format.column[cl.x + i];
|
||||
format.column.InsertN(cl.x, ext);
|
||||
int q = clx / sz.cx;
|
||||
for(int i = 1; i < sz.cx; i++)
|
||||
format.column[cl.x + i] = q;
|
||||
format.column[cl.x] = clx - (sz.cx - 1) * q;
|
||||
for(int i = 0; i < cell.GetCount(); i++) {
|
||||
cell[i].InsertN(cl.x + 1, ext);
|
||||
for(int q = 0; q < ext; q++) {
|
||||
RichCell& c = cell[i][cl.x + 1 + q];
|
||||
const RichCell& sc = cell[i][cl.x];
|
||||
c.format = sc.format;
|
||||
c.vspan = sc.vspan;
|
||||
c.ClearText(sc.text.GetFirstFormat(style), style);
|
||||
}
|
||||
CellInfo& cf = ci[i][cl.x];
|
||||
if(cf.valid)
|
||||
cell[i][cl.x].hspan += ext;
|
||||
else
|
||||
if(cf.master.y == i)
|
||||
cell[cf.master.y][cf.master.x].hspan += ext;
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < sz.cy; i++)
|
||||
for(int j = 0; j < sz.cx; j++) {
|
||||
RichCell& c = cell[cl.y + i][cl.x + j];
|
||||
if(j < sz.cx - 1)
|
||||
c.hspan = 0;
|
||||
if(j) {
|
||||
const RichCell& sc = cell[cl.y + i][cl.x];
|
||||
c.format = sc.format;
|
||||
c.vspan = sc.vspan;
|
||||
c.ClearText(sc.text.GetFirstFormat(style), style);
|
||||
}
|
||||
}
|
||||
Normalize();
|
||||
}
|
||||
|
||||
void sMatchRect(Rect& t, const Rect& s)
|
||||
{
|
||||
if(t.left != s.left)
|
||||
t.left = Null;
|
||||
if(t.top != s.top)
|
||||
t.top = Null;
|
||||
if(t.right != s.right)
|
||||
t.right = Null;
|
||||
if(t.bottom != s.bottom)
|
||||
t.bottom = Null;
|
||||
}
|
||||
|
||||
RichCell::Format RichTable::GetCellFormat(const Rect& sel) const
|
||||
{
|
||||
RichCell::Format fmt;
|
||||
for(int i = sel.top; i <= sel.bottom; i++)
|
||||
for(int j = sel.left; j <= sel.right; j++)
|
||||
if(i == sel.top && j == sel.left)
|
||||
fmt = cell[i][j].format;
|
||||
else
|
||||
if(ci[i][j].valid) {
|
||||
const RichCell::Format& f = cell[i][j].format;
|
||||
sMatchRect(fmt.border, f.border);
|
||||
sMatchRect(fmt.margin, f.margin);
|
||||
if(fmt.align != f.align)
|
||||
fmt.align = Null;
|
||||
if(fmt.color != f.color)
|
||||
fmt.color = Null;
|
||||
if(fmt.bordercolor != f.bordercolor)
|
||||
fmt.bordercolor = Null;
|
||||
}
|
||||
return fmt;
|
||||
}
|
||||
|
||||
void sSetRect(Rect& t, const Rect& s)
|
||||
{
|
||||
if(!IsNull(s.left))
|
||||
t.left = s.left;
|
||||
if(!IsNull(s.top))
|
||||
t.top = s.top;
|
||||
if(!IsNull(s.right))
|
||||
t.right = s.right;
|
||||
if(!IsNull(s.bottom))
|
||||
t.bottom = s.bottom;
|
||||
}
|
||||
|
||||
void RichTable::SetCellFormat(const Rect& sel, const RichCell::Format& fmt, bool setkeep)
|
||||
{
|
||||
for(int i = sel.top; i <= sel.bottom; i++)
|
||||
for(int j = sel.left; j <= sel.right; j++)
|
||||
if(ci[i][j].valid) {
|
||||
RichCell::Format& f = cell[i][j].format;
|
||||
sSetRect(f.border, fmt.border);
|
||||
sSetRect(f.margin, fmt.margin);
|
||||
if(!IsNull(fmt.align))
|
||||
f.align = fmt.align;
|
||||
if(!IsNull(fmt.color))
|
||||
f.color = fmt.color;
|
||||
if(!IsNull(fmt.bordercolor))
|
||||
f.bordercolor = fmt.bordercolor;
|
||||
if(!IsNull(fmt.minheight))
|
||||
f.minheight = fmt.minheight;
|
||||
if(setkeep)
|
||||
f.keep = fmt.keep;
|
||||
}
|
||||
|
||||
Normalize();
|
||||
}
|
||||
|
||||
void RichTable::Paste(Point pos, const RichTable& tab)
|
||||
{
|
||||
for(int i = 0; i < tab.GetRows(); i++)
|
||||
for(int j = 0; j < min(GetColumns() - pos.x, tab.GetColumns()); j++)
|
||||
cell.At(i + pos.y, cell[cell.GetCount() - 1]).At(j + pos.x) <<= tab[i][j];
|
||||
Normalize();
|
||||
}
|
||||
|
||||
void RichTable::AdjustSel(Rect& sel) const
|
||||
{
|
||||
again:
|
||||
for(int i = sel.top; i <= sel.bottom; i++)
|
||||
for(int j = sel.left; j <= sel.right; j++) {
|
||||
Point p = GetMasterCell(i, j);
|
||||
const RichCell& c = cell[p.y][p.x];
|
||||
Point pp = p + Point(c.hspan, c.vspan);
|
||||
if(p.x < sel.left) {
|
||||
sel.left = p.x;
|
||||
goto again;
|
||||
}
|
||||
if(pp.x > sel.right) {
|
||||
sel.right = pp.x;
|
||||
goto again;
|
||||
}
|
||||
if(p.y < sel.top) {
|
||||
sel.top = p.y;
|
||||
goto again;
|
||||
}
|
||||
if(pp.y > sel.bottom) {
|
||||
sel.bottom = pp.y;
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RichTable::RichTable(const RichTable& src, int)
|
||||
{
|
||||
format = src.format;
|
||||
cell <<= src.cell;
|
||||
r_row = -1;
|
||||
Normalize();
|
||||
}
|
||||
|
||||
RichTable::RichTable()
|
||||
{
|
||||
cpy.page = -1;
|
||||
r_row = -1;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
176
uppdev/RichTextP/TableLayout.cpp
Normal file
176
uppdev/RichTextP/TableLayout.cpp
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
#include "RichText.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
bool RichTable::Reduce(RichContext& rc) const
|
||||
{
|
||||
Rect br = rc.page;
|
||||
rc.page.left += format.lm;
|
||||
rc.page.right -= format.rm;
|
||||
rc.page.Deflate(format.frame);
|
||||
if(rc.page.IsEmpty())
|
||||
rc.page = br;
|
||||
return !rc.page.IsEmpty();
|
||||
}
|
||||
|
||||
|
||||
const RichTable::TabLayout& RichTable::Realize(RichContext rc) const
|
||||
{
|
||||
if(rc.py != cpy || rc.page != cpage) {
|
||||
rc.py.y += format.before;
|
||||
if(rc.py.y > rc.page.bottom) {
|
||||
rc.py.y = rc.page.top;
|
||||
rc.py.page++;
|
||||
}
|
||||
cpage = rc.page;
|
||||
cpy = rc.py;
|
||||
Reduce(rc);
|
||||
clayout.page = rc.page;
|
||||
clayout.hasheader = false;
|
||||
clayout.sz = GetSize();
|
||||
if(format.header && cell.GetCount()) {
|
||||
int hy = min(format.header, cell.GetCount());
|
||||
RichContext nrc = rc;
|
||||
nrc.py.page = 0;
|
||||
nrc.py.y = clayout.page.top;
|
||||
clayout.header = Realize(nrc, hy);
|
||||
if(clayout.header[0].py.page == clayout.header[hy - 1].pyy.page) {
|
||||
Layout x = Realize(rc, cell.GetCount());
|
||||
if(cell.GetCount() > hy && rc.py.page != x[hy].py.page) {
|
||||
rc.py.page++;
|
||||
rc.py.y = rc.page.top;
|
||||
}
|
||||
clayout.hasheader = true;
|
||||
rc.page.top = clayout.page.top = clayout.header[hy - 1].pyy.y + format.grid;
|
||||
}
|
||||
}
|
||||
clayout.page0 = rc.py.page;
|
||||
(Layout&)clayout = Realize(rc, cell.GetCount());
|
||||
if(format.keep && cell.GetCount()) {
|
||||
if(clayout[0].py.page != clayout[cell.GetCount() - 1].pyy.page) {
|
||||
rc.py.page++;
|
||||
rc.py.y = rc.page.top;
|
||||
}
|
||||
clayout.page0 = rc.py.page;
|
||||
(Layout&)clayout = Realize(rc, cell.GetCount());
|
||||
}
|
||||
}
|
||||
return clayout;
|
||||
}
|
||||
|
||||
RichTable::Layout RichTable::Realize(RichContext rc, int ny) const
|
||||
{
|
||||
Layout tab;
|
||||
|
||||
int nx = format.column.GetCount();
|
||||
tab.row.Alloc(ny);
|
||||
for(int i = 0; i < ny; i++)
|
||||
tab[i].cell.Alloc(nx);
|
||||
tab.col.Alloc(nx);
|
||||
|
||||
int sum = 0;
|
||||
for(int i = 0; i < nx; i++)
|
||||
sum += format.column[i];
|
||||
|
||||
int x = 0;
|
||||
int xx = rc.page.left;
|
||||
int dcx = rc.page.Width();
|
||||
for(int i = 0; i < nx; i++) {
|
||||
Rect& cp = tab.col[i];
|
||||
cp = rc.page;
|
||||
cp.left = xx;
|
||||
x += format.column[i];
|
||||
xx = cp.right = x * dcx / sum + rc.page.left;
|
||||
}
|
||||
|
||||
int f2 = format.grid / 2;
|
||||
int ff2 = format.grid - f2;
|
||||
|
||||
rc.py.y += format.frame;
|
||||
for(int i = 0; i < ny; i++) {
|
||||
const Array<RichCell>& row = cell[i];
|
||||
PaintRow& pr = tab[i];
|
||||
pr.first = i == 0;
|
||||
pr.gpy = rc.py;
|
||||
if(i)
|
||||
rc.py.y += format.grid;
|
||||
for(int j = 0; j < nx;) {
|
||||
PaintCell& pc = pr[j];
|
||||
const RichCell& cell = row[j];
|
||||
if(pc.top) {
|
||||
pc.page = tab.col[j];
|
||||
pc.page.right = tab.col[min(nx - 1, j + cell.hspan)].right;
|
||||
pc.bottom = false;
|
||||
int ms = min(ny - 1, i + cell.vspan);
|
||||
for(int k = i + 1; k <= ms; k++) {
|
||||
PaintCell& pc = tab[k][j];
|
||||
pc.top = pc.bottom = false;
|
||||
}
|
||||
tab[ms][j].bottom = true;
|
||||
pc.left = pc.page.left;
|
||||
pc.right = pc.page.right;
|
||||
if(j)
|
||||
pc.page.left += f2;
|
||||
if(j + cell.hspan < nx - 1)
|
||||
pc.page.right -= ff2;
|
||||
}
|
||||
j += cell.hspan + 1;
|
||||
}
|
||||
bool keep = i < format.header || format.keep;
|
||||
for(int j = 0; j < nx;) {
|
||||
const RichCell& cell = row[j];
|
||||
if(pr[j].top && cell.format.keep) {
|
||||
keep = true;
|
||||
break;
|
||||
}
|
||||
j += cell.hspan + 1;
|
||||
}
|
||||
bool span = false;
|
||||
for(int j = 0; j < nx;) {
|
||||
const RichCell& cell = row[j];
|
||||
if(!pr[j].top) {
|
||||
span = true;
|
||||
break;
|
||||
}
|
||||
j += cell.hspan + 1;
|
||||
}
|
||||
if(!span)
|
||||
for(int j = 0; j < nx;) {
|
||||
const RichCell& cell = row[j];
|
||||
PaintCell& pc = pr[j];
|
||||
if(pc.top) {
|
||||
rc.page = pc.page;
|
||||
PageY ty = cell.GetTop(rc);
|
||||
PageY ky = rc.py;
|
||||
if(keep)
|
||||
ky = cell.GetHeight(rc);
|
||||
if(ty.page != rc.py.page || ky.page != rc.py.page) {
|
||||
rc.Page();
|
||||
pr.gpy = rc.py;
|
||||
pr.first = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
j += cell.hspan + 1;
|
||||
}
|
||||
pr.py = rc.py;
|
||||
for(int j = 0; j < nx;) {
|
||||
const RichCell& cell = row[j];
|
||||
PaintCell& pc = pr[j];
|
||||
rc.page = pc.page;
|
||||
if(pc.top)
|
||||
tab[min(ny - 1, i + cell.vspan)][j].hy = cell.GetHeight(rc);
|
||||
j += cell.hspan + 1;
|
||||
}
|
||||
for(int j = 0; j < nx;) {
|
||||
const RichCell& cell = row[j];
|
||||
if(pr[j].bottom)
|
||||
rc.py = max(pr[j].hy, rc.py);
|
||||
j += cell.hspan + 1;
|
||||
}
|
||||
tab.pyy = pr.pyy = rc.py;
|
||||
}
|
||||
return tab;
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
372
uppdev/RichTextP/TablePaint.cpp
Normal file
372
uppdev/RichTextP/TablePaint.cpp
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
#include "RichText.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
RichTable::Format::Format()
|
||||
{
|
||||
grid = 4;
|
||||
gridcolor = Black;
|
||||
frame = 10;
|
||||
framecolor = Black;
|
||||
before = after = lm = rm = 0;
|
||||
header = 0;
|
||||
keep = false;
|
||||
}
|
||||
|
||||
#include "RichText.h"
|
||||
|
||||
void RichTable::ExpandFrr(VectorMap<int, Rect>& frr, int pi, int l, int r, int t, int b)
|
||||
{
|
||||
Rect& fr = frr.GetAdd(pi, Rect(INT_MAX, INT_MAX, INT_MIN, INT_MIN));
|
||||
fr.left = min(fr.left, l);
|
||||
fr.right = max(fr.right, r);
|
||||
fr.top = min(fr.top, t);
|
||||
fr.bottom = max(fr.bottom, b);
|
||||
}
|
||||
|
||||
bool RichTable::RowPaint(PageDraw& pw, const RichStyles& st, const Layout& tab,
|
||||
int i, int ny, const Rect& pg, VectorMap<int, Rect>& frr,
|
||||
PaintInfo& pi, int pd, bool sel) const
|
||||
{
|
||||
RichContext rc(st);
|
||||
const Array<RichCell>& row = cell[i];
|
||||
const PaintRow& pr = tab[i];
|
||||
rc.py = pr.py;
|
||||
rc.py.page += pd;
|
||||
int gridln = LineZoom(pi.zoom, format.grid);
|
||||
int ff2ln = gridln - gridln / 2;
|
||||
Color gc = format.gridcolor;
|
||||
if(gridln == 0 && !IsNull(pi.showcodes)) {
|
||||
gridln = 1;
|
||||
gc = pi.showcodes;
|
||||
}
|
||||
for(int j = 0; j < format.column.GetCount();) {
|
||||
const RichCell& cell = row[j];
|
||||
const PaintCell& pc = pr[j];
|
||||
if(pc.top) {
|
||||
PageY pyy = tab[min(ny - 1, i + cell.vspan)].pyy;
|
||||
pyy.page += pd;
|
||||
bool paint = pyy > pi.top;
|
||||
rc.page = pr[j].page;
|
||||
Rect xpg = pg;
|
||||
int y;
|
||||
int ny = pi.zoom * pyy.y;
|
||||
y = pi.zoom * pr.gpy.y;
|
||||
if(j) {
|
||||
xpg.left = pi.zoom * pc.left - ff2ln;
|
||||
if(pyy.page == rc.py.page)
|
||||
pw.Page(rc.py.page).DrawRect(xpg.left, y, gridln, ny - y, gc);
|
||||
else {
|
||||
pw.Page(rc.py.page).DrawRect(xpg.left, y, gridln, pg.bottom - y, gc);
|
||||
for(int i = rc.py.page + 1; i < pyy.page; i++)
|
||||
pw.Page(i).DrawRect(xpg.left, pg.top, gridln, pg.bottom - pg.top, gc);
|
||||
pw.Page(pyy.page).DrawRect(xpg.left, pg.top, gridln, ny - pg.top, gc);
|
||||
}
|
||||
xpg.left += gridln;
|
||||
}
|
||||
if(j + cell.hspan < format.column.GetCount() - 1)
|
||||
xpg.right = pi.zoom * pc.right - ff2ln;
|
||||
if(!pr.first) {
|
||||
y += gridln;
|
||||
if(paint)
|
||||
pw.Page(rc.py.page).DrawRect(xpg.left, y - gridln, xpg.Width(), gridln, gc);
|
||||
}
|
||||
if(paint)
|
||||
row[j].Paint(pw, rc, pyy, xpg, y, ny, pi,
|
||||
sel && j >= pi.cells.left && i >= pi.cells.top &&
|
||||
j + cell.hspan <= pi.cells.right && i + cell.vspan <= pi.cells.bottom);
|
||||
if(pyy.page == rc.py.page)
|
||||
ExpandFrr(frr, pyy.page, xpg.left, xpg.right, y, ny);
|
||||
else {
|
||||
ExpandFrr(frr, rc.py.page, xpg.left, xpg.right, y, xpg.bottom);
|
||||
for(int i = rc.py.page + 1; i < pyy.page; i++)
|
||||
ExpandFrr(frr, i, xpg.left, xpg.right, xpg.top, xpg.bottom);
|
||||
ExpandFrr(frr, pyy.page, xpg.left, xpg.right, xpg.top, ny);
|
||||
}
|
||||
int l = cell.text.GetLength() + 1;
|
||||
pi.sell -= l;
|
||||
pi.selh -= l;
|
||||
pi.tablesel -= cell.text.GetTableCount();
|
||||
}
|
||||
j += cell.hspan + 1;
|
||||
}
|
||||
|
||||
return rc.py >= pi.bottom;
|
||||
}
|
||||
|
||||
void RichTable::Paint(PageDraw& pw, RichContext rc, const PaintInfo& _pi) const
|
||||
{
|
||||
const TabLayout& tab = Realize(rc);
|
||||
if(tab.page.IsEmpty())
|
||||
return;
|
||||
Rect p = tab.page;
|
||||
PaintInfo pi = _pi;
|
||||
int frameln = LineZoom(pi.zoom, format.frame);
|
||||
int gridln = LineZoom(pi.zoom, format.grid);
|
||||
Rect pg = rc.page;
|
||||
pg.left += format.lm;
|
||||
pg.right -= format.rm;
|
||||
pg.left = pi.zoom * pg.left;
|
||||
pg.right = pi.zoom * pg.right;
|
||||
pg.top = pi.zoom * pg.top;
|
||||
pg.bottom = pi.zoom * pg.bottom;
|
||||
pg.Deflate(frameln);
|
||||
int hy = min(format.header, cell.GetCount());
|
||||
Rect hpg = pg;
|
||||
if(tab.hasheader) {
|
||||
hpg.bottom = pi.zoom * tab.header[hy - 1].pyy.y;
|
||||
pg.top = hpg.bottom + gridln;
|
||||
}
|
||||
bool allsel = false;
|
||||
if(pi.sell < 0 && pi.selh >= 0) {
|
||||
pi.sell = pi.selh = 0;
|
||||
allsel = true;
|
||||
}
|
||||
bool sel = pi.tablesel == 0;
|
||||
int ny = cell.GetCount();
|
||||
VectorMap<int, Rect> frr;
|
||||
for(int i = 0; i < ny; i++)
|
||||
if(RowPaint(pw, rc.styles, tab, i, ny, pg, frr, pi, 0, sel))
|
||||
break;
|
||||
|
||||
Color gc = format.gridcolor;
|
||||
Color fc = format.framecolor;
|
||||
int fl = frameln;
|
||||
if(!IsNull(pi.showcodes)) {
|
||||
if(fl == 0 && !IsNull(pi.showcodes)) {
|
||||
fl = 1;
|
||||
fc = pi.showcodes;
|
||||
}
|
||||
if(gridln == 0) {
|
||||
gridln = 1;
|
||||
gc = pi.showcodes;
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < frr.GetCount(); i++) {
|
||||
PaintInfo _pi = pi;
|
||||
pi.tablesel = 0;
|
||||
pi.sell = pi.selh = -1;
|
||||
int pgi = frr.GetKey(i);
|
||||
Draw& w = pw.Page(pgi);
|
||||
if(pgi > tab.page0 && tab.hasheader)
|
||||
for(int i = 0; i < hy; i++) {
|
||||
RowPaint(pw, rc.styles, tab.header, i, hy, hpg, frr, pi, pgi, false);
|
||||
w.DrawRect(pg.left, hpg.bottom, pg.Width(), gridln, format.gridcolor);
|
||||
}
|
||||
Rect r = frr[i].Inflated(frameln);
|
||||
if(!r.IsEmpty()) {
|
||||
DrawFatFrame(w, r, fc, fl);
|
||||
if(allsel)
|
||||
w.DrawRect(r, InvertColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PageY RichTable::GetHeight(RichContext rc) const
|
||||
{
|
||||
PageY pyy = Realize(rc).pyy;
|
||||
pyy.y += format.frame;
|
||||
pyy.y += format.after;
|
||||
if(pyy.y > rc.page.bottom) {
|
||||
pyy.y = rc.page.top;
|
||||
pyy.page++;
|
||||
}
|
||||
return pyy;
|
||||
}
|
||||
|
||||
PageY RichTable::GetTop(RichContext rc) const
|
||||
{
|
||||
if(cell.GetCount() == 0)
|
||||
return rc.py;
|
||||
rc.py = Realize(rc)[0].py;
|
||||
rc.py.y -= format.frame;
|
||||
return rc.py;
|
||||
}
|
||||
|
||||
RichCaret RichTable::GetCaret(int pos, RichContext rc) const
|
||||
{
|
||||
ASSERT(pos >= 0);
|
||||
int nx = format.column.GetCount();
|
||||
int ny = cell.GetCount();
|
||||
int ti = 0;
|
||||
const TabLayout& tab = Realize(rc);
|
||||
for(int i = 0; i < ny; i++) {
|
||||
const PaintRow& pr = tab[i];
|
||||
rc.py = pr.py;
|
||||
PageY pyy;
|
||||
for(int j = 0; j < nx; j++) {
|
||||
if(ci[i][j].valid) {
|
||||
const RichCell& cl = cell[i][j];
|
||||
pyy = tab[min(ny - 1, i + cl.vspan)].pyy;
|
||||
int l = cl.text.GetLength() + 1;
|
||||
if(pos < l) {
|
||||
rc.page = pr[j].page;
|
||||
return cl.GetCaret(pos, rc, pyy);
|
||||
}
|
||||
ti += cl.text.GetTableCount();
|
||||
pos -= l;
|
||||
}
|
||||
}
|
||||
}
|
||||
NEVER();
|
||||
return RichCaret();
|
||||
}
|
||||
|
||||
int RichTable::GetPos(int x, PageY y, RichContext rc) const
|
||||
{
|
||||
int nx = format.column.GetCount();
|
||||
int ny = cell.GetCount();
|
||||
const TabLayout& tab = Realize(rc);
|
||||
int pos = 0;
|
||||
for(int i = 0; i < ny; i++) {
|
||||
const PaintRow& pr = tab[i];
|
||||
rc.py = pr.py;
|
||||
for(int j = 0; j < nx; j++)
|
||||
if(ci[i][j].valid) {
|
||||
const RichCell& cl = cell[i][j];
|
||||
const PaintCell& pc = pr[j];
|
||||
PageY pyy = tab[min(ny - 1, i + cl.vspan)].pyy;
|
||||
if(y < pyy
|
||||
&& (j == 0 || x >= pc.page.left - format.grid)
|
||||
&& (j == nx - 1 || x < pc.page.right)) {
|
||||
rc.page = pc.page;
|
||||
return cl.GetPos(x, y, rc, pyy) + pos;
|
||||
}
|
||||
pos += cl.text.GetLength() + 1;
|
||||
}
|
||||
}
|
||||
return pos ? pos - 1 : 0;
|
||||
}
|
||||
|
||||
RichHotPos RichTable::GetHotPos(int x, PageY y, int tolerance, RichContext rc) const
|
||||
{
|
||||
RichHotPos hp;
|
||||
hp.textleft = rc.page.left;
|
||||
hp.textcx = rc.page.Width();
|
||||
int nx = format.column.GetCount();
|
||||
int ny = cell.GetCount();
|
||||
const TabLayout& tab = Realize(rc);
|
||||
if(abs(x - tab.page.left) <= tolerance) {
|
||||
hp.table = 0;
|
||||
hp.column = RICHHOT_LM;
|
||||
hp.delta = x - tab.page.left;
|
||||
return hp;
|
||||
}
|
||||
if(abs(x - tab.page.right) <= tolerance) {
|
||||
hp.table = 0;
|
||||
hp.column = RICHHOT_RM;
|
||||
hp.delta = x - tab.page.right;
|
||||
return hp;
|
||||
}
|
||||
int ti = 0;
|
||||
for(int i = 0; i < ny; i++) {
|
||||
const PaintRow& pr = tab[i];
|
||||
rc.py = pr.py;
|
||||
for(int j = 0; j < nx; j++) {
|
||||
if(ci[i][j].valid) {
|
||||
const RichCell& cl = cell[i][j];
|
||||
const PaintCell& pc = pr[j];
|
||||
PageY pyy = tab[min(ny - 1, i + cl.vspan)].pyy;
|
||||
if(y < pyy) {
|
||||
if(j < nx - 1 && abs(x - pc.page.right) <= tolerance) {
|
||||
hp.table = 0;
|
||||
hp.column = j + cl.hspan;
|
||||
hp.delta = x - pc.page.right;
|
||||
hp.left = tab.page.left;
|
||||
hp.cx = tab.page.Width();
|
||||
return hp;
|
||||
}
|
||||
if((j == 0 || x >= pc.page.left - format.grid) && (j == nx - 1 || x < pc.page.right)) {
|
||||
rc.page = pc.page;
|
||||
hp = cl.GetHotPos(x, y, tolerance, rc, pyy);
|
||||
hp.table += ti;
|
||||
return hp;
|
||||
}
|
||||
}
|
||||
ti += cl.text.GetTableCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
return RichHotPos();
|
||||
}
|
||||
|
||||
int RichTable::GetVertMove(int pos, int gx, RichContext rc, int dir) const
|
||||
{
|
||||
if(cell.GetCount() == 0)
|
||||
return -1;
|
||||
int nx = format.column.GetCount();
|
||||
int ny = cell.GetCount();
|
||||
const TabLayout& tab = Realize(rc);
|
||||
Point cp;
|
||||
if(pos >= 0)
|
||||
cp = FindCell(pos);
|
||||
else {
|
||||
cp.y = dir > 0 ? 0 : cell.GetCount() - 1;
|
||||
cp.x = 0;
|
||||
const PaintRow& pr = tab[cp.y];
|
||||
for(int j = 0; j < nx; j++)
|
||||
if(ci[cp.y][cp.x].valid && gx < pr[j].page.right) {
|
||||
cp.x = j;
|
||||
break;
|
||||
}
|
||||
pos = -1;
|
||||
}
|
||||
for(;;) {
|
||||
rc.page = tab[cp.y][cp.x].page;
|
||||
const RichCell& c = cell[cp.y][cp.x];
|
||||
RichContext rc1 = rc;
|
||||
if(c.Reduce(rc1)) {
|
||||
int q = cell[cp.y][cp.x].text.GetVertMove(pos, gx, rc1, dir);
|
||||
if(q >= 0)
|
||||
return q + GetCellPos(cp);
|
||||
}
|
||||
pos = -1;
|
||||
cp.y += dir;
|
||||
if(cp.y < 0 || cp.y >= ny)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void RichTable::GatherValPos(Vector<RichValPos>& f, RichContext rc, int pos, int type) const
|
||||
{
|
||||
ASSERT(pos >= 0);
|
||||
int nx = format.column.GetCount();
|
||||
int ny = cell.GetCount();
|
||||
const TabLayout& tab = Realize(rc);
|
||||
for(int i = 0; i < ny; i++) {
|
||||
const PaintRow& pr = tab[i];
|
||||
rc.py = pr.py;
|
||||
for(int j = 0; j < nx; j++)
|
||||
if(ci[i][j].valid) {
|
||||
const RichCell& cl = cell[i][j];
|
||||
rc.page = pr[j].page;
|
||||
cl.GatherValPos(f, rc, tab[min(ny - 1, i + cl.vspan)].pyy, pos, type);
|
||||
pos += cl.text.GetLength() + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RichTable::ApplyZoom(Zoom z, const RichStyles& ostyle, const RichStyles& zstyle)
|
||||
{
|
||||
Invalidate();
|
||||
r_row = -1;
|
||||
int nx = format.column.GetCount();
|
||||
int ny = cell.GetCount();
|
||||
format.frame = LineZoom(z, format.frame);
|
||||
format.grid = LineZoom(z, format.grid);
|
||||
format.before *= z;
|
||||
format.lm *= z;
|
||||
format.rm *= z;
|
||||
format.after *= z;
|
||||
for(int i = 0; i < ny; i++)
|
||||
for(int j = 0; j < nx; j++)
|
||||
if(ci[i][j].valid) {
|
||||
RichCell& c = cell[i][j];
|
||||
c.format.border *= z;
|
||||
c.format.margin *= z;
|
||||
c.format.minheight *= z;
|
||||
c.text.ApplyZoom(z, ostyle, zstyle);
|
||||
}
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
135
uppdev/RichTextP/Text.h
Normal file
135
uppdev/RichTextP/Text.h
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
class RichText : public RichTxt, public DeepCopyOption<RichText> {
|
||||
RichStyles style;
|
||||
String footer; // ugly hack
|
||||
bool nolinks;
|
||||
|
||||
void Init();
|
||||
|
||||
struct StyleChangeOp;
|
||||
struct SetStylesOp;
|
||||
struct RemoveStyleOp;
|
||||
struct MergeStylesOp;
|
||||
friend struct MergeStylesOp;
|
||||
struct OverrideStylesOp;
|
||||
|
||||
public:
|
||||
void Clear();
|
||||
|
||||
int GetStyleCount() const { return style.GetCount(); }
|
||||
Uuid GetStyleId(int i) const { return style.GetKey(i); }
|
||||
Uuid GetStyleId(const String& name) const;
|
||||
const RichStyle& GetStyle(int i) const { return style[i]; }
|
||||
const RichStyle& GetStyle(const Uuid& id) const { return UPP::GetStyle(style, id); }
|
||||
void SetStyle(const Uuid& id, const RichStyle& _style);
|
||||
bool HasStyle(const Uuid& id) { return style.Find(id) >= 0; }
|
||||
void RemoveStyle(const Uuid& id);
|
||||
|
||||
const RichStyles& GetStyles() const { return style; }
|
||||
void SetStyles(const RichStyles& styles);
|
||||
void OverrideStyles(const RichStyles& masterstyles,
|
||||
bool matchname = true, bool addmissing = true);
|
||||
void MergeStyles(const RichText& text);
|
||||
|
||||
RichPara Get(int i) const { return RichTxt::Get(i, style); }
|
||||
void Cat(const RichPara& p) { RichTxt::Cat(p, style); }
|
||||
void CatPick(pick_ RichText& p);
|
||||
using RichTxt::CatPick;
|
||||
|
||||
RichContext Context(const Rect& page) const;
|
||||
|
||||
RichPos GetRichPos(int pos, int maxlevel = INT_MAX) const;
|
||||
int operator[](int pos) const { return GetRichPos(pos).chr; }
|
||||
|
||||
void ApplyZoom(Zoom z);
|
||||
|
||||
PageY GetHeight(PageY py, const Rect& page) const;
|
||||
PageY GetHeight(const Rect& page) const;
|
||||
void Paint(PageDraw& w, PageY py, const Rect& page, const PaintInfo& pi) const;
|
||||
void Paint(PageDraw& w, const Rect& page, const PaintInfo& pi) const;
|
||||
RichCaret GetCaret(int pos, const Rect& page) const;
|
||||
int GetPos(int x, PageY y, const Rect& page) const;
|
||||
RichHotPos GetHotPos(int x, PageY y, int tolerance, const Rect& page) const;
|
||||
int GetVertMove(int pos, int gx, const Rect& page, int dir) const;
|
||||
int GetWidth() const;
|
||||
|
||||
int GetHeight(int cx) const;
|
||||
int GetHeight(Zoom zoom, int cx) const;
|
||||
void Paint(Draw& w, int x, int y, int cx, const PaintInfo& pi) const;
|
||||
void Paint(Zoom zoom, Draw& w, int x, int y, int cx) const;
|
||||
void Paint(Draw& w, int x, int y, int cx) const;
|
||||
|
||||
Vector<RichValPos> GetValPos(const Rect& page, int type) const;
|
||||
|
||||
int AdjustCursor(int anchor, int cursor) const;
|
||||
|
||||
void Remove(int pos, int count);
|
||||
void Insert(int pos, const RichText& p);
|
||||
RichText Copy(int pos, int count) const;
|
||||
|
||||
FormatInfo GetFormatInfo(int pos, int count) const;
|
||||
void ApplyFormatInfo(int pos, const FormatInfo& fi, int count);
|
||||
|
||||
void ReStyle(int pos, const Uuid& id);
|
||||
|
||||
Formating SaveFormat(int pos, int count) const;
|
||||
void RestoreFormat(int pos, const Formating& info);
|
||||
|
||||
|
||||
RichTable::Format GetTableFormat(int table) const;
|
||||
void SetTableFormat(int table, const RichTable::Format& fmt);
|
||||
int SetTable(int pos, const RichTable& table);
|
||||
void DestroyTable(int table);
|
||||
RichTable CopyTable(int table) const;
|
||||
void ReplaceTable(int table, const RichTable& tab);
|
||||
void RemoveParaSpecial(int table, bool before);
|
||||
bool CanRemoveParaSpecial(int table, bool before);
|
||||
void InsertParaSpecial(int table, bool before, const RichPara::Format& fmt);
|
||||
bool ShouldInsertParaSpecial(int table, bool before);
|
||||
RichTable CopyTable(int table, const Rect& sel) const;
|
||||
void ClearTable(int table, const Rect& sel);
|
||||
void PasteTable(int table, Point pos, const RichTable& tab);
|
||||
void InsertTableRow(int table, int row);
|
||||
void RemoveTableRow(int table, int row);
|
||||
void InsertTableColumn(int table, int column);
|
||||
void RemoveTableColumn(int table, int column);
|
||||
Point GetMasterCell(int table, int row, int column);
|
||||
Point GetMasterCell(int table, Point p) { return GetMasterCell(table, p.y, p.x); }
|
||||
void SplitCell(int table, Point cell, Size sz);
|
||||
void JoinCell(int table, const Rect& sel);
|
||||
RichCell::Format GetCellFormat(int table, const Rect& sel) const;
|
||||
void SetCellFormat(int table, const Rect& sel, const RichCell::Format& fmt, bool setkeep);
|
||||
FormatInfo GetTableFormatInfo(int table, const Rect& sel) const;
|
||||
void ApplyTableFormatInfo(int table, const Rect& sel, const RichText::FormatInfo& fi);
|
||||
void AdjustTableSel(int table, Rect& sel) const { return GetConstTable(table).AdjustSel(sel); }
|
||||
|
||||
bool Iterate(Iterator& r) const { return RichTxt::Iterate(r, 0, style); }
|
||||
bool Iterate(UpdateIterator& r) { return RichTxt::Iterate(r, 0, style); }
|
||||
|
||||
bool EvaluateFields(VectorMap<String, Value>& vars) { return RichTxt::EvaluateFields(style, vars); }
|
||||
|
||||
void InvalidateAll() { r_type = ALL; }
|
||||
void Validate();
|
||||
bool GetInvalid(PageY& top, PageY& bottom, const Rect& page,
|
||||
int sell, int selh, int osell, int oselh) const;
|
||||
|
||||
struct ClipboardType {
|
||||
ClipboardType();
|
||||
virtual ~ClipboardType();
|
||||
|
||||
virtual int Level();
|
||||
virtual RichText ReadClipboard(const RichPara::Format& f) = 0;
|
||||
virtual void WriteClipboard(const RichText& text) = 0;
|
||||
};
|
||||
|
||||
static void Register(ClipboardType& type);
|
||||
|
||||
//Ugly hacks
|
||||
void SetFooter(const String& s) { footer = s; }
|
||||
String GetFooter() const { return footer; }
|
||||
void PrintNoLinks(bool b = true) { nolinks = b; }
|
||||
bool IsPrintNoLinks() const { return nolinks; }
|
||||
|
||||
RichText() { Init(); }
|
||||
RichText(const RichText& x, int);
|
||||
RichText(pick_ RichTxt& x, pick_ RichStyles& st);
|
||||
};
|
||||
332
uppdev/RichTextP/TextData.cpp
Normal file
332
uppdev/RichTextP/TextData.cpp
Normal file
|
|
@ -0,0 +1,332 @@
|
|||
#include "RichText.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
void RichText::CatPick(pick_ RichText& p)
|
||||
{
|
||||
MergeStyles(p);
|
||||
int c = part.GetCount();
|
||||
part.AppendPick(p.part);
|
||||
for(int i = c; i < part.GetCount(); i++)
|
||||
if(IsPara(i))
|
||||
part[i].Get<Para>().cx = -1;
|
||||
RefreshAll();
|
||||
}
|
||||
|
||||
RichPos::RichPos()
|
||||
{
|
||||
tabtextparti = tabtextpartcount = tabposintabtext = tabtextlen = table = tablen = posintab =
|
||||
celllen = posincell = parai = partcount = posinpara = paralen = 0;
|
||||
parenttab = Null;
|
||||
|
||||
tabsize = Size(0, 0);
|
||||
cell = Point(0, 0);
|
||||
chr = '?';
|
||||
}
|
||||
|
||||
RichPos RichText::GetRichPos(int pos, int maxlevel) const
|
||||
{
|
||||
RichPos rp;
|
||||
rp.level = 0;
|
||||
RichTxt::GetRichPos(pos, rp, 0, maxlevel, style);
|
||||
if(IsNull(rp.parenttab))
|
||||
rp.parenttab = 0;
|
||||
return rp;
|
||||
}
|
||||
|
||||
int RichText::AdjustCursor(int anchor, int cursor) const
|
||||
{
|
||||
int d = anchor;
|
||||
const RichTxt& txt = GetConstText(anchor);
|
||||
d -= anchor;
|
||||
if(!(cursor == txt.GetLength() && !txt.IsTable(txt.GetPartCount() - 1)))
|
||||
cursor = minmax(cursor - d, 0, txt.GetLength());
|
||||
int c = cursor;
|
||||
int pi = txt.FindPart(c);
|
||||
if(txt.IsTable(pi)) {
|
||||
if(cursor < anchor) {
|
||||
while(--pi >= 0)
|
||||
if(txt.IsPara(pi))
|
||||
return d + txt.GetPartPos(pi) + txt.GetPartLength(pi);
|
||||
while(++pi < txt.GetPartCount())
|
||||
if(txt.IsPara(pi))
|
||||
return d + txt.GetPartPos(pi);
|
||||
return d + anchor;
|
||||
}
|
||||
else {
|
||||
while(++pi < txt.GetPartCount())
|
||||
if(txt.IsPara(pi))
|
||||
return d + txt.GetPartPos(pi);
|
||||
while(--pi >= 0)
|
||||
if(txt.IsPara(pi))
|
||||
return d + txt.GetPartPos(pi) + txt.GetPartLength(pi);
|
||||
return d + anchor;
|
||||
}
|
||||
}
|
||||
return d + cursor;
|
||||
}
|
||||
|
||||
void RichText::Remove(int pos, int count)
|
||||
{
|
||||
GetLength();
|
||||
int p = pos;
|
||||
int l = GetConstText(p).GetLength();
|
||||
count = min(l - p, count);
|
||||
RichTxt& txt = GetUpdateText(pos);
|
||||
int pos2 = pos + count;
|
||||
int pi = txt.FindPart(pos);
|
||||
int pi2 = txt.FindPart(pos2);
|
||||
if(pi == pi2) {
|
||||
RichPara pa, pa1;
|
||||
pa = txt.Get(pi, style);
|
||||
pa1 <<= pa;
|
||||
pa.Trim(pos);
|
||||
pa1.Mid(pos2);
|
||||
pa.Append(pa1);
|
||||
txt.Put(pi, pa, style);
|
||||
}
|
||||
else {
|
||||
RichPara pa2 = txt.Get(pi2, style);
|
||||
RichPara pa = txt.Get(pi, pa2.format.styleid, style);
|
||||
txt.part.Remove(pi, pi2 - pi);
|
||||
pa.Trim(pos);
|
||||
pa2.Mid(pos2);
|
||||
pa.Append(pa2);
|
||||
pa.format = pa2.format;
|
||||
txt.Put(pi, pa, style);
|
||||
txt.SetRefreshFrom(pi);
|
||||
}
|
||||
}
|
||||
|
||||
void RichText::Insert(int pos, const RichText& p)
|
||||
{
|
||||
MergeStyles(p);
|
||||
if(p.GetLength() == 0)
|
||||
return;
|
||||
ASSERT(pos >= 0 && pos <= GetLength());
|
||||
RichTxt& txt = GetUpdateText(pos);
|
||||
int pi = txt.FindPart(pos);
|
||||
int n = p.part.GetCount() - 1;
|
||||
if(n) {
|
||||
txt.part.Insert(pi + 1, p.part, 1, n);
|
||||
RichPara pa1, pa2;
|
||||
pa1 = txt.Get(pi, style);
|
||||
pa2 = txt.Get(pi + n, pa1.format.styleid, style);
|
||||
pa1.Mid(pos);
|
||||
pa2.Append(pa1);
|
||||
pa2.format = pa1.format;
|
||||
txt.Put(pi + n, pa2, style);
|
||||
pa2 = p.RichTxt::Get(0, p.GetStyle(p.GetParaStyle(0)));
|
||||
pa1 = txt.Get(pi, pa2.format.styleid, style);
|
||||
pa1.Trim(pos);
|
||||
pa1.Append(pa2);
|
||||
pa1.format = pa2.format;
|
||||
txt.Put(pi, pa1, style);
|
||||
txt.SetRefreshFrom(pi);
|
||||
}
|
||||
else {
|
||||
RichPara pa0, pa2;
|
||||
pa0 = txt.Get(pi, style);
|
||||
pa2 <<= pa0;
|
||||
pa0.Trim(pos);
|
||||
pa2.Mid(pos);
|
||||
pa0.Append(p.RichTxt::Get(0, p.GetStyle(pa0.format.styleid)));
|
||||
pa0.Append(pa2);
|
||||
txt.Put(pi, pa0, style);
|
||||
}
|
||||
}
|
||||
|
||||
RichText RichText::Copy(int pos, int count) const
|
||||
{
|
||||
RichText r;
|
||||
r.SetStyles(style);
|
||||
|
||||
const RichTxt& txt = GetConstText(pos);
|
||||
bool addp = false;
|
||||
if(count > txt.GetLength() - pos) {
|
||||
count = txt.GetLength() - pos;
|
||||
addp = true;
|
||||
}
|
||||
int pos2 = pos + count;
|
||||
int pi = txt.FindPart(pos);
|
||||
int pi2 = txt.FindPart(pos2);
|
||||
|
||||
if(pi == pi2) {
|
||||
RichPara pa = txt.Get(pi, style);
|
||||
pa.Trim(pos2);
|
||||
pa.Mid(pos);
|
||||
r.Cat(pa);
|
||||
}
|
||||
else {
|
||||
RichPara pa = txt.Get(pi++, style);
|
||||
pa.Mid(pos);
|
||||
r.Cat(pa);
|
||||
while(pi < pi2) {
|
||||
if(txt.IsPara(pi))
|
||||
r.Cat(txt.Get(pi, style));
|
||||
else {
|
||||
RichTable tab(txt.GetTable(pi), 1);
|
||||
r.CatPick(tab);
|
||||
}
|
||||
pi++;
|
||||
}
|
||||
pa = txt.Get(pi2, style);
|
||||
pa.Trim(pos2);
|
||||
r.Cat(pa);
|
||||
}
|
||||
if(addp)
|
||||
r.Cat(RichPara());
|
||||
return r;
|
||||
}
|
||||
|
||||
RichText::FormatInfo RichText::GetFormatInfo(int pos, int count) const
|
||||
{
|
||||
const RichTxt& txt = GetConstText(pos);
|
||||
|
||||
count = min(txt.GetLength() - pos, count);
|
||||
|
||||
int pos2 = pos + count;
|
||||
int pi = txt.FindPart(pos);
|
||||
int pi2 = txt.FindPart(pos2);
|
||||
|
||||
FormatInfo fi;
|
||||
RichPara::Format fmt;
|
||||
RichPara pa = txt.Get(pi, style);
|
||||
fmt = pa.format;
|
||||
int i = pa.FindPart(pos);
|
||||
if(i < pa.GetCount())
|
||||
(RichPara::CharFormat&)fmt = pa[i].format;
|
||||
fi.Set(fmt);
|
||||
i++;
|
||||
if(pi == pi2) {
|
||||
int i2 = pa.FindPart(pos2);
|
||||
while(i < i2)
|
||||
fi.Combine(pa[i++].format);
|
||||
if(pos2 && i2 < pa.GetCount())
|
||||
fi.Combine(pa[i2].format);
|
||||
}
|
||||
else {
|
||||
while(i < pa.GetCount())
|
||||
fi.Combine(pa[i++].format);
|
||||
fi.Combine(pa.format);
|
||||
pi++;
|
||||
bool first = false;
|
||||
txt.CombineFormat(fi, pi, pi2, first, style);
|
||||
pa = txt.Get(pi2, style);
|
||||
int i2 = pa.FindPart(pos2);
|
||||
for(i = 0; i < i2; i++)
|
||||
fi.Combine(pa[i].format);
|
||||
if(pos2 && i2 < pa.GetCount())
|
||||
fi.Combine(pa[i2].format);
|
||||
}
|
||||
return fi;
|
||||
}
|
||||
|
||||
void RichText::ApplyFormatInfo(int pos, const FormatInfo& fi, int count)
|
||||
{
|
||||
RichTxt& txt = GetUpdateText(pos);
|
||||
|
||||
int pos2 = min(txt.GetLength(), pos + count);
|
||||
int pi = txt.FindPart(pos);
|
||||
int pi2 = txt.FindPart(pos2);
|
||||
|
||||
ASSERT(txt.IsPara(pi) && txt.IsPara(pi2));
|
||||
|
||||
if(pi == pi2) {
|
||||
RichPara pa, pa1, pa2;
|
||||
pa = txt.Get(pi, style);
|
||||
ApplyStyle(fi, pa, style);
|
||||
pa1 <<= pa;
|
||||
pa2 <<= pa;
|
||||
pa.Trim(pos);
|
||||
pa2.Mid(pos2);
|
||||
pa1.Trim(pos2);
|
||||
pa1.Mid(pos);
|
||||
Apply(fi, pa1, style);
|
||||
pa.Append(pa1);
|
||||
pa.Append(pa2);
|
||||
fi.ApplyTo(pa.format);
|
||||
txt.Put(pi, pa, style);
|
||||
}
|
||||
else {
|
||||
RichPara pa, pa1;
|
||||
// if(fi.paravalid & RichText::STYLE)
|
||||
// pa = txt.Get(pi, fi.styleid, style);
|
||||
// else
|
||||
pa = txt.Get(pi, style);
|
||||
ApplyStyle(fi, pa, style);
|
||||
pa1 <<= pa;
|
||||
pa.Trim(pos);
|
||||
pa1.Mid(pos);
|
||||
Apply(fi, pa1, style);
|
||||
fi.ApplyTo(pa.format);
|
||||
pa.Append(pa1);
|
||||
txt.Put(pi, pa, style);
|
||||
pi++;
|
||||
txt.ApplyFormat(fi, pi, pi2, style);
|
||||
// if(fi.paravalid & RichText::STYLE)
|
||||
// pa = txt.Get(pi2, fi.styleid, style);
|
||||
// else
|
||||
pa = txt.Get(pi2, style);
|
||||
ApplyStyle(fi, pa, style);
|
||||
pa1 <<= pa;
|
||||
pa.Trim(pos2);
|
||||
pa1.Mid(pos2);
|
||||
Apply(fi, pa, style);
|
||||
pa.Append(pa1);
|
||||
txt.Put(pi2, pa, style);
|
||||
}
|
||||
}
|
||||
|
||||
void RichText::ReStyle(int pos, const Uuid& id)
|
||||
{
|
||||
int p = FindPart(pos);
|
||||
RichPara pa = Get(p);
|
||||
pa.format.styleid = id;
|
||||
Put(p, pa, style);
|
||||
}
|
||||
|
||||
RichText::Formating RichText::SaveFormat(int pos, int count) const
|
||||
{
|
||||
const RichTxt& txt = GetConstText(pos);
|
||||
count += pos;
|
||||
Formating r;
|
||||
txt.SaveFormat(r, txt.FindPart(pos), txt.FindPart(count), style);
|
||||
return r;
|
||||
}
|
||||
|
||||
void RichText::RestoreFormat(int pos, const RichText::Formating& info)
|
||||
{
|
||||
RichTxt& txt = GetUpdateText(pos);
|
||||
int ii = 0;
|
||||
txt.RestoreFormat(txt.FindPart(pos), info, ii, style);
|
||||
}
|
||||
|
||||
void RichText::Init()
|
||||
{
|
||||
RichTxt::Init();
|
||||
RichStyle& s = style.Add(RichStyle::GetDefaultId());
|
||||
s.name = "Default";
|
||||
nolinks = false;
|
||||
}
|
||||
|
||||
void RichText::Clear()
|
||||
{
|
||||
RichTxt::Clear();
|
||||
style.Clear();
|
||||
Init();
|
||||
}
|
||||
|
||||
RichText::RichText(const RichText& x, int)
|
||||
: RichTxt(x, 1), style(x.style, 1)
|
||||
{
|
||||
nolinks = x.nolinks;
|
||||
}
|
||||
|
||||
RichText::RichText(pick_ RichTxt& x, pick_ RichStyles& st)
|
||||
: RichTxt(x), style(st)
|
||||
{
|
||||
nolinks = false;
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
183
uppdev/RichTextP/TextPaint.cpp
Normal file
183
uppdev/RichTextP/TextPaint.cpp
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
#include "RichText.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
RichContext RichText::Context(const Rect& page) const
|
||||
{
|
||||
RichContext c(style);
|
||||
c.page = page;
|
||||
c.py = PageY(0, page.top);
|
||||
return c;
|
||||
}
|
||||
|
||||
PageY RichText::GetHeight(const Rect& page) const
|
||||
{
|
||||
return RichTxt::GetHeight(Context(page));
|
||||
}
|
||||
|
||||
PageY RichText::GetHeight(PageY py, const Rect& page) const
|
||||
{
|
||||
RichContext ctx = Context(page);
|
||||
ctx.py = py;
|
||||
return RichTxt::GetHeight(ctx);
|
||||
}
|
||||
|
||||
int RichText::GetWidth() const
|
||||
{
|
||||
return RichTxt::GetWidth(style);
|
||||
}
|
||||
|
||||
void RichText::Paint(PageDraw& w, PageY py, const Rect& page, const PaintInfo& pi) const
|
||||
{
|
||||
RichContext ctx = Context(page);
|
||||
ctx.py = py;
|
||||
RichTxt::Paint(w, ctx, pi);
|
||||
}
|
||||
|
||||
void RichText::Paint(PageDraw& w, const Rect& page, const PaintInfo& pi) const
|
||||
{
|
||||
RichTxt::Paint(w, Context(page), pi);
|
||||
}
|
||||
|
||||
RichCaret RichText::GetCaret(int pos, const Rect& page) const
|
||||
{
|
||||
return RichTxt::GetCaret(pos, Context(page));
|
||||
}
|
||||
|
||||
int RichText::GetPos(int x, PageY y, const Rect& page) const
|
||||
{
|
||||
return RichTxt::GetPos(x, y, Context(page));
|
||||
}
|
||||
|
||||
int RichText::GetVertMove(int pos, int gx, const Rect& page, int dir) const
|
||||
{
|
||||
return RichTxt::GetVertMove(pos, gx, Context(page), dir);
|
||||
}
|
||||
|
||||
RichHotPos RichText::GetHotPos(int x, PageY y, int tolerance, const Rect& page) const
|
||||
{
|
||||
RichHotPos p = RichTxt::GetHotPos(x, y, tolerance, Context(page));
|
||||
if(p.column < -2)
|
||||
p.table = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
Vector<RichValPos> RichText::GetValPos(const Rect& page, int type) const
|
||||
{
|
||||
Vector<RichValPos> f;
|
||||
GatherValPos(f, Context(page), 0, type);
|
||||
return f;
|
||||
}
|
||||
|
||||
void RichText::Validate()
|
||||
{
|
||||
r_type = NONE;
|
||||
for(int i = 0; i < part.GetCount(); i++)
|
||||
if(IsTable(i))
|
||||
part[i].Get<RichTable>().Validate();
|
||||
}
|
||||
|
||||
bool RichText::GetInvalid(PageY& top, PageY& bottom, const Rect& page,
|
||||
int sell, int selh, int osell, int oselh) const
|
||||
{
|
||||
int spi;
|
||||
int rtype = r_type;
|
||||
if(sell != selh || osell != oselh) {
|
||||
if(sell != osell) {
|
||||
if(rtype == NONE) {
|
||||
spi = FindPart(sell);
|
||||
rtype = spi == FindPart(osell) ? SPARA : ALL;
|
||||
}
|
||||
else
|
||||
rtype = ALL;
|
||||
}
|
||||
if(selh != oselh) {
|
||||
if(rtype == NONE) {
|
||||
spi = FindPart(selh);
|
||||
rtype = spi == FindPart(oselh) ? SPARA : ALL;
|
||||
}
|
||||
else
|
||||
rtype = ALL;
|
||||
}
|
||||
}
|
||||
bottom = top = PageY(0, page.top);
|
||||
if(rtype == NONE) {
|
||||
bottom = top;
|
||||
return false;
|
||||
}
|
||||
if(rtype == ALL) {
|
||||
bottom = GetHeight(page);
|
||||
return true;
|
||||
}
|
||||
RichContext rc = Context(page);
|
||||
if(rtype == SPARA) {
|
||||
rc.py = top = GetPartPageY(spi, rc);
|
||||
bottom = GetNextPageY(spi, rc);
|
||||
return true;
|
||||
}
|
||||
rc.py = top = GetPartPageY(r_parti, rc);
|
||||
if(rtype == PARA) {
|
||||
if(IsTable(r_parti))
|
||||
switch(GetTable(r_parti).GetInvalid(top, bottom, rc)) {
|
||||
case -1: return false;
|
||||
case 0: return true;
|
||||
default:
|
||||
bottom = GetHeight(page);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
Sync(r_parti, rc);
|
||||
const Para& pp = part[r_parti].Get<Para>();
|
||||
if(r_paraocx == pp.cx &&
|
||||
r_paraocy == Sum(pp.linecy, 0) + pp.ruler + pp.before + pp.after &&
|
||||
r_keep == pp.keep &&
|
||||
r_keepnext == pp.keepnext &&
|
||||
r_newpage == pp.newpage) {
|
||||
bottom = GetNextPageY(r_parti, rc);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
bottom = GetHeight(page);
|
||||
return true;
|
||||
}
|
||||
|
||||
int RichText::GetHeight(Zoom zoom, int cx) const
|
||||
{
|
||||
int lwd = cx / zoom;
|
||||
return GetHeight(Size(lwd, 0xFFFFFFF)).y * zoom;
|
||||
}
|
||||
|
||||
int RichText::GetHeight(int cx) const
|
||||
{
|
||||
return GetHeight(Size(cx, 0xFFFFFFF)).y;
|
||||
}
|
||||
|
||||
void RichText::Paint(Draw& w, int x, int y, int cx, const PaintInfo& pinit) const
|
||||
{
|
||||
SimplePageDraw pw(w);
|
||||
PaintInfo pi(pinit);
|
||||
pi.top = PageY(0, 0);
|
||||
pi.bottom = PageY(0, INT_MAX);
|
||||
pi.usecache = true;
|
||||
pi.sizetracking = false;
|
||||
pi.highlight = Null;
|
||||
w.Offset(x, y);
|
||||
Paint(pw, Size(cx / pi.zoom, INT_MAX), pi);
|
||||
w.End();
|
||||
}
|
||||
|
||||
void RichText::Paint(Zoom zoom, Draw& w, int x, int y, int cx) const
|
||||
{
|
||||
PaintInfo pi;
|
||||
pi.highlightpara = false;
|
||||
pi.zoom = zoom;
|
||||
Paint(w, x, y, cx, pi);
|
||||
}
|
||||
|
||||
void RichText::Paint(Draw& w, int x, int y, int cx) const
|
||||
{
|
||||
Paint(Zoom(1, 1), w, x, y, cx);
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
153
uppdev/RichTextP/TextStyle.cpp
Normal file
153
uppdev/RichTextP/TextStyle.cpp
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
#include "RichText.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
const RichStyle& RichStyle::GetDefault()
|
||||
{
|
||||
return Single<RichStyle>();
|
||||
}
|
||||
|
||||
Uuid RichStyle::GetDefaultId()
|
||||
{
|
||||
Uuid id;
|
||||
id.a = 0;
|
||||
id.b = 0;
|
||||
id.c = 0;
|
||||
id.d = 0;
|
||||
return id;
|
||||
}
|
||||
|
||||
const RichStyle& GetStyle(const RichStyles& s, const Uuid& id)
|
||||
{
|
||||
return s.Get(id, RichStyle::GetDefault());
|
||||
}
|
||||
|
||||
int FindStyleWithName(const RichStyles& style, const String& name)
|
||||
{
|
||||
for(int j = 0; j < style.GetCount(); j++)
|
||||
if(style[j].name == name)
|
||||
return j;
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct RichText::StyleChangeOp : RichTxt::ParaOp {
|
||||
Uuid id, nid;
|
||||
|
||||
virtual bool operator()(RichTxt::Para& p) {
|
||||
if(p.styleid == id) {
|
||||
p.styleid = nid;
|
||||
p.cx = -1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
void RichText::SetStyle(const Uuid& id, const RichStyle& _style)
|
||||
{
|
||||
Invalidate();
|
||||
RichStyle& s = style.GetAdd(id);
|
||||
s = _style;
|
||||
s.format.styleid = id;
|
||||
s.format.language = 0;
|
||||
s.format.newpage = false;
|
||||
StyleChangeOp op;
|
||||
op.nid = op.id = id;
|
||||
Update(op);
|
||||
}
|
||||
|
||||
struct RichText::SetStylesOp : RichTxt::ParaOp {
|
||||
RichStyles *style;
|
||||
|
||||
virtual bool operator()(RichTxt::Para& p) {
|
||||
p.cx = -1;
|
||||
if(style->Find(p.styleid) < 0)
|
||||
p.styleid = RichStyle::GetDefaultId();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void RichText::SetStyles(const RichStyles& _style)
|
||||
{
|
||||
Invalidate();
|
||||
style <<= _style;
|
||||
SetStylesOp op;
|
||||
op.style = &style;
|
||||
Update(op);
|
||||
}
|
||||
|
||||
Uuid RichText::GetStyleId(const String& name) const
|
||||
{
|
||||
int i = FindStyleWithName(style, name);
|
||||
return i >= 0 ? style.GetKey(i) : RichStyle::GetDefaultId();
|
||||
}
|
||||
|
||||
void RichText::RemoveStyle(const Uuid& id)
|
||||
{
|
||||
ASSERT(id != RichStyle::GetDefaultId());
|
||||
Invalidate();
|
||||
StyleChangeOp op;
|
||||
op.id = id;
|
||||
op.nid = RichStyle::GetDefaultId();
|
||||
Update(op);
|
||||
style.RemoveKey(id);
|
||||
}
|
||||
|
||||
struct RichText::MergeStylesOp : RichTxt::ParaOp {
|
||||
RichText *text;
|
||||
const RichText *stxt;
|
||||
|
||||
virtual bool operator()(RichTxt::Para& p) {
|
||||
if(text->style.Find(p.styleid) < 0) {
|
||||
RichStyle& s = text->style.GetAdd(p.styleid);
|
||||
s = stxt->GetStyle(p.styleid);
|
||||
s.format.styleid = p.styleid;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
void RichText::MergeStyles(const RichText& text)
|
||||
{
|
||||
Invalidate();
|
||||
MergeStylesOp op;
|
||||
op.stxt = &text;
|
||||
op.text = this;
|
||||
const_cast<RichText&>(text).Update(op);
|
||||
}
|
||||
|
||||
struct RichText::OverrideStylesOp : RichTxt::ParaOp {
|
||||
VectorMap<Uuid, Uuid> cs;
|
||||
|
||||
virtual bool operator()(RichTxt::Para& p) {
|
||||
p.styleid = cs.Get(p.styleid, RichStyle::GetDefaultId());
|
||||
p.cx = -1;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void RichText::OverrideStyles(const RichStyles& ms, bool matchname, bool addmissing)
|
||||
{
|
||||
Invalidate();
|
||||
RichStyles orig = style;
|
||||
style <<= ms;
|
||||
OverrideStylesOp op;
|
||||
for(int i = 0; i < orig.GetCount(); i++) {
|
||||
Uuid pid = orig.GetKey(i);
|
||||
int q;
|
||||
if(ms.Find(pid) >= 0)
|
||||
op.cs.Add(pid, pid);
|
||||
else
|
||||
if(matchname && (q = FindStyleWithName(style, orig[i].name)) >= 0)
|
||||
op.cs.Add(pid, style.GetKey(q));
|
||||
else
|
||||
if(addmissing) {
|
||||
SetStyle(pid, orig[i]);
|
||||
op.cs.Add(pid, pid);
|
||||
}
|
||||
}
|
||||
|
||||
Update(op);
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
225
uppdev/RichTextP/TextTable.cpp
Normal file
225
uppdev/RichTextP/TextTable.cpp
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
#include "RichText.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
RichTable::Format RichText::GetTableFormat(int table) const
|
||||
{
|
||||
return GetConstTable(table).GetFormat();
|
||||
}
|
||||
|
||||
void RichText::SetTableFormat(int table, const RichTable::Format& fmt)
|
||||
{
|
||||
RichTable& tab = GetUpdateTable(table);
|
||||
tab.SetFormat(fmt);
|
||||
tab.Normalize();
|
||||
}
|
||||
|
||||
int RichText::SetTable(int pos, const RichTable& table)
|
||||
{
|
||||
RefreshAll();
|
||||
RichPos p = GetRichPos(pos);
|
||||
int bpos = pos;
|
||||
RichTxt& txt = GetUpdateText(pos);
|
||||
int pi = txt.FindPart(pos);
|
||||
ASSERT(pos == 0 && txt.GetPartLength(pi) == 0 && txt.IsPara(pi));
|
||||
RichTable pt(table, 1);
|
||||
txt.SetPick(pi, pt);
|
||||
return GetRichPos(bpos).table;
|
||||
}
|
||||
|
||||
RichTable RichText::CopyTable(int table) const
|
||||
{
|
||||
RichTable tab(GetConstTable(table), 1);
|
||||
return tab;
|
||||
}
|
||||
|
||||
void RichText::ReplaceTable(int table, const RichTable& tab)
|
||||
{
|
||||
(GetUpdateTable(table) <<= tab).Normalize();
|
||||
RefreshAll();
|
||||
}
|
||||
|
||||
void RichText::DestroyTable(int table)
|
||||
{
|
||||
int pi;
|
||||
RichTxt& txt = GetTableUpdateText(table, style, pi);
|
||||
RichPara p;
|
||||
txt.Set(pi, p, style);
|
||||
RefreshAll();
|
||||
}
|
||||
|
||||
void RichText::RemoveParaSpecial(int table, bool before)
|
||||
{
|
||||
int pi;
|
||||
RichTxt& txt = GetTableUpdateText(table, style, pi);
|
||||
if(before)
|
||||
pi--;
|
||||
else
|
||||
pi++;
|
||||
ASSERT(txt.IsPara(pi) && txt.GetPartLength(pi) == 0);
|
||||
txt.part.Remove(pi);
|
||||
RefreshAll();
|
||||
}
|
||||
|
||||
bool RichText::CanRemoveParaSpecial(int table, bool before)
|
||||
{
|
||||
int pi;
|
||||
if(!table)
|
||||
return false;
|
||||
RichTxt& txt = GetTableUpdateText(table, style, pi);
|
||||
if(before)
|
||||
pi--;
|
||||
else
|
||||
pi++;
|
||||
return pi >= 0 && pi < txt.GetPartCount() && txt.IsPara(pi) && txt.GetPartLength(pi) == 0;
|
||||
}
|
||||
|
||||
bool RichText::ShouldInsertParaSpecial(int table, bool before)
|
||||
{
|
||||
int pi;
|
||||
RichTxt& txt = GetTableUpdateText(table, style, pi);
|
||||
if(!before)
|
||||
pi++;
|
||||
return pi == 0 || pi >= txt.GetPartCount() || txt.IsTable(pi);
|
||||
}
|
||||
|
||||
|
||||
void RichText::InsertParaSpecial(int table, bool before, const RichPara::Format& fmt)
|
||||
{
|
||||
int pi;
|
||||
RichTxt& txt = GetTableUpdateText(table, style, pi);
|
||||
if(!before)
|
||||
pi++;
|
||||
txt.RefreshAll();
|
||||
txt.part.Insert(pi);
|
||||
RichPara p;
|
||||
p.format = fmt;
|
||||
txt.Set(pi, p, style);
|
||||
RefreshAll();
|
||||
}
|
||||
|
||||
RichTable RichText::CopyTable(int table, const Rect& sel) const
|
||||
{
|
||||
return GetConstTable(table).Copy(sel);
|
||||
}
|
||||
|
||||
Point RichText::GetMasterCell(int table, int row, int column)
|
||||
{
|
||||
return GetConstTable(table).GetMasterCell(row, column);
|
||||
}
|
||||
|
||||
void RichText::PasteTable(int table, Point pos, const RichTable& tab)
|
||||
{
|
||||
GetUpdateTable(table).Paste(pos, tab);
|
||||
RefreshAll();
|
||||
}
|
||||
|
||||
void RichText::InsertTableRow(int table, int row)
|
||||
{
|
||||
GetUpdateTable(table).InsertRow(row, style);
|
||||
RefreshAll();
|
||||
}
|
||||
|
||||
void RichText::RemoveTableRow(int table, int row)
|
||||
{
|
||||
GetUpdateTable(table).RemoveRow(row);
|
||||
RefreshAll();
|
||||
}
|
||||
|
||||
void RichText::InsertTableColumn(int table, int column)
|
||||
{
|
||||
GetUpdateTable(table).InsertColumn(column, style);
|
||||
RefreshAll();
|
||||
}
|
||||
|
||||
void RichText::RemoveTableColumn(int table, int column)
|
||||
{
|
||||
GetUpdateTable(table).RemoveColumn(column);
|
||||
RefreshAll();
|
||||
}
|
||||
|
||||
void RichText::SplitCell(int table, Point cell, Size sz)
|
||||
{
|
||||
GetUpdateTable(table).SplitCell(cell, sz, style);
|
||||
RefreshAll();
|
||||
}
|
||||
|
||||
void RichText::JoinCell(int table, const Rect& sel)
|
||||
{
|
||||
RichTable& tab = GetUpdateTable(table);
|
||||
RichCell& cell = tab[sel.top][sel.left];
|
||||
cell.vspan = sel.bottom - sel.top;
|
||||
cell.hspan = sel.right - sel.left;
|
||||
for(int i = sel.top; i <= sel.bottom; i++)
|
||||
for(int j = sel.left; j <= sel.right; j++) {
|
||||
if(tab(i, j) && (i != sel.top || j != sel.left)) {
|
||||
RichTxt& t = tab[i][j].text;
|
||||
for(int pi = 0; pi < t.GetPartCount(); pi++)
|
||||
if(t.IsTable(pi))
|
||||
cell.text.CatPick(t.part[pi].Get<RichTable>());
|
||||
else
|
||||
if(pi < t.GetPartCount() - 1 || t.GetPartLength(pi))
|
||||
cell.text.Cat(t.Get(pi, style), style);
|
||||
tab[i][j].ClearText();
|
||||
}
|
||||
}
|
||||
tab.Normalize();
|
||||
RefreshAll();
|
||||
}
|
||||
|
||||
RichCell::Format RichText::GetCellFormat(int table, const Rect& sel) const
|
||||
{
|
||||
return GetConstTable(table).GetCellFormat(sel);
|
||||
}
|
||||
|
||||
void RichText::SetCellFormat(int table, const Rect& sel, const RichCell::Format& fmt, bool setkeep)
|
||||
{
|
||||
GetUpdateTable(table).SetCellFormat(sel, fmt, setkeep);
|
||||
RefreshAll();
|
||||
}
|
||||
|
||||
void RichText::ClearTable(int table, const Rect& sel)
|
||||
{
|
||||
RichTable& tab = GetUpdateTable(table);
|
||||
for(int i = sel.top; i <= sel.bottom; i++)
|
||||
for(int j = sel.left; j <= sel.right; j++) {
|
||||
if(tab(i, j)) {
|
||||
tab.InvalidateRefresh(i, j);
|
||||
tab[i][j].ClearText(tab[i][j].text.GetFirstFormat(style), style);
|
||||
}
|
||||
}
|
||||
tab.Normalize();
|
||||
RefreshAll();
|
||||
}
|
||||
|
||||
RichText::FormatInfo RichText::GetTableFormatInfo(int table, const Rect& sel) const
|
||||
{
|
||||
const RichTable& tab = GetConstTable(table);
|
||||
bool first = true;
|
||||
FormatInfo fi;
|
||||
for(int i = sel.top; i <= sel.bottom; i++)
|
||||
for(int j = sel.left; j <= sel.right; j++) {
|
||||
if(tab(i, j)) {
|
||||
const RichTxt& txt = tab[i][j].text;
|
||||
txt.CombineFormat(fi, 0, txt.GetPartCount(), first, style);
|
||||
}
|
||||
}
|
||||
return fi;
|
||||
}
|
||||
|
||||
void RichText::ApplyTableFormatInfo(int table, const Rect& sel, const RichText::FormatInfo& fi)
|
||||
{
|
||||
RichTable& tab = GetUpdateTable(table);
|
||||
for(int i = sel.top; i <= sel.bottom; i++)
|
||||
for(int j = sel.left; j <= sel.right; j++) {
|
||||
if(tab(i, j)) {
|
||||
tab.InvalidateRefresh(i, j);
|
||||
RichTxt& txt = tab[i][j].text;
|
||||
txt.ApplyFormat(fi, 0, txt.GetPartCount(), style);
|
||||
}
|
||||
}
|
||||
tab.Normalize();
|
||||
RefreshAll();
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
247
uppdev/RichTextP/Txt.h
Normal file
247
uppdev/RichTextP/Txt.h
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
class RichTxt : DeepCopyOption<RichTxt> {
|
||||
public:
|
||||
enum {
|
||||
BOLD = 0x00000001,
|
||||
ITALIC = 0x00000002,
|
||||
UNDERLINE = 0x00000004,
|
||||
FACE = 0x00000008,
|
||||
HEIGHT = 0x00000010,
|
||||
LANGUAGE = 0x00000020,
|
||||
INK = 0x00000040,
|
||||
PAPER = 0x00000080,
|
||||
LINK = 0x00000100,
|
||||
SSCRIPT = 0x00000200,
|
||||
CAPITALS = 0x00000400,
|
||||
STRIKEOUT = 0x00000800,
|
||||
LANG = 0x00001000,
|
||||
INDEXENTRY = 0x00002000,
|
||||
DASHED = 0x00004000,
|
||||
NOAA = 0x00008000,
|
||||
};
|
||||
|
||||
enum {
|
||||
ALIGN = 0x80000000,
|
||||
BEFORE = 0x40000000,
|
||||
LM = 0x20000000,
|
||||
INDENT = 0x10000000,
|
||||
RM = 0x08000000,
|
||||
AFTER = 0x04000000,
|
||||
TABSIZE = 0x02000000,
|
||||
BULLET = 0x01000000,
|
||||
NEWPAGE = 0x00800000,
|
||||
KEEP = 0x00400000,
|
||||
TABS = 0x00200000,
|
||||
STYLE = 0x00100000,
|
||||
LABEL = 0x00080000,
|
||||
KEEPNEXT = 0x00040000,
|
||||
ORPHAN = 0x00020000,
|
||||
NUMBERING = 0x00010000,
|
||||
SPACING = 0x00008000,
|
||||
RULER = 0x00004000,
|
||||
RULERINK = 0x00002000,
|
||||
};
|
||||
|
||||
struct FormatInfo : RichPara::Format {
|
||||
dword charvalid;
|
||||
dword paravalid;
|
||||
|
||||
void Set(const RichPara::Format& fmt);
|
||||
void Set(const RichPara::CharFormat& fmt);
|
||||
void Combine(const RichPara::CharFormat& fmt);
|
||||
void Combine(const RichPara::Format& fmt);
|
||||
void Combine(const FormatInfo& fmt);
|
||||
void ApplyTo(RichPara::CharFormat& fmt) const;
|
||||
void ApplyTo(RichPara::Format& fmt) const;
|
||||
};
|
||||
|
||||
class Formating {
|
||||
Vector<Uuid> styleid;
|
||||
Vector<String> format;
|
||||
friend class RichText;
|
||||
friend class RichTxt;
|
||||
};
|
||||
|
||||
protected:
|
||||
struct Para : DeepCopyOption<Para> {
|
||||
Uuid styleid;
|
||||
int length;
|
||||
String content;
|
||||
Array<RichObject> object;
|
||||
mutable int cx;
|
||||
mutable int cy;
|
||||
mutable int ruler;
|
||||
mutable int before;
|
||||
mutable Vector<int> linecy;
|
||||
mutable int after;
|
||||
mutable bool newpage;
|
||||
mutable bool keep;
|
||||
mutable bool keepnext;
|
||||
mutable bool orphan;
|
||||
mutable int numbering;
|
||||
mutable Bits spellerrors;
|
||||
mutable bool checked;
|
||||
mutable bool haspos;
|
||||
One<RichPara::NumberFormat> number;
|
||||
|
||||
Para(const Para& src, int);
|
||||
Para() { length = 0; cx = -1; numbering = -1; checked = false; haspos = false; }
|
||||
};
|
||||
|
||||
struct Part : MoveableAndDeepCopyOption< Part, Any> {
|
||||
Part(const Part& src, int);
|
||||
Part();
|
||||
};
|
||||
|
||||
Vector<Part> part;
|
||||
mutable int length;
|
||||
mutable int tabcount;
|
||||
mutable Rect rect;
|
||||
mutable Vector<PageY> py;
|
||||
|
||||
enum {
|
||||
NONE, SPARA, PARA, FROM, ALL
|
||||
};
|
||||
|
||||
int r_type;
|
||||
int r_parti;
|
||||
int r_paraocx;
|
||||
int r_paraocy;
|
||||
bool r_keep;
|
||||
bool r_keepnext;
|
||||
bool r_newpage;
|
||||
|
||||
void Init();
|
||||
|
||||
void Invalidate();
|
||||
|
||||
void SetRefresh(int parai);
|
||||
void SetRefreshFrom(int parai);
|
||||
void RefreshAll() { SetRefreshFrom(0); }
|
||||
|
||||
void ParaRemove(int parai, int pos, int count);
|
||||
void ParaInsert(int parai, int pos, const RichPara& p);
|
||||
RichPara ParaCopy(int parai, int pos, int count) const;
|
||||
|
||||
void Put(int i, const RichPara& p, const RichStyle& s);
|
||||
void Put(int i, const RichPara& p, const RichStyles& s);
|
||||
|
||||
void Sync0(const Para& pp, int parti, const RichContext& rc) const;
|
||||
inline void Sync(int parti, const RichContext& rc) const {
|
||||
int cx = rc.page.Width();
|
||||
ASSERT(part[parti].Is<Para>());
|
||||
const Para& pp = part[parti].Get<Para>();
|
||||
if(pp.cx == cx) return;
|
||||
Sync0(pp, parti, rc);
|
||||
}
|
||||
bool BreaksPage(PageY py, const Para& pp, int i, const Rect& page) const;
|
||||
PageY GetNextPageY(int parti, const RichContext& rc) const;
|
||||
PageY GetPartPageY(int parti, RichContext rc) const;
|
||||
|
||||
struct ParaOp {
|
||||
virtual bool operator()(RichTxt::Para& p) = 0;
|
||||
virtual ~ParaOp() {}
|
||||
};
|
||||
bool Update(ParaOp& op);
|
||||
RichTxt& GetText0(int& pos, bool update);
|
||||
RichTxt& GetUpdateText(int& pos);
|
||||
const RichTxt& GetConstText(int& pos) const;
|
||||
RichTable& GetTable0(int table, bool update);
|
||||
RichTable& GetUpdateTable(int table);
|
||||
const RichTable& GetConstTable(int table) const;
|
||||
RichTxt& GetTableUpdateText(int table, const RichStyles& style, int& pi);
|
||||
|
||||
void CombineFormat(FormatInfo& f, int pi, int pi2, bool& first, const RichStyles& style) const;
|
||||
static void ApplyStyle(const FormatInfo& fi, RichPara& pa, const RichStyles& style);
|
||||
static void Apply(const FormatInfo& fi, RichPara& pa, const RichStyles& style);
|
||||
void ApplyFormat(const FormatInfo& f, int pi, int pi2, const RichStyles& style);
|
||||
void SaveFormat(Formating& f, int p1, int p2, const RichStyles& style) const;
|
||||
void RestoreFormat(int pi, const Formating& info, int& ii, const RichStyles& style);
|
||||
|
||||
void GetAllLanguages(Index<int>& all) const;
|
||||
|
||||
friend class RichTable;
|
||||
friend class RichText;
|
||||
friend class RichCell;
|
||||
|
||||
int ComputeLength() const;
|
||||
|
||||
void GetRichPos(int pos, RichPos& rp, int ti, int maxlevel, const RichStyles& st) const;
|
||||
RichPara::Format GetFirstFormat(const RichStyles& st) const;
|
||||
|
||||
PageY GetTop(RichContext rc) const;
|
||||
PageY GetHeight(RichContext rc) const;
|
||||
int GetWidth(const RichStyles& st) const;
|
||||
void Paint(PageDraw& w, RichContext rc, const PaintInfo& pi) const;
|
||||
RichCaret GetCaret(int pos, RichContext rc) const;
|
||||
int GetPos(int x, PageY y, RichContext rc) const;
|
||||
int GetVertMove(int pos, int gx, RichContext rc, int dir) const;
|
||||
RichHotPos GetHotPos(int x, PageY y, int tolerance, RichContext rc) const;
|
||||
|
||||
void GatherValPos(Vector<RichValPos>& f, RichContext rc, int pos, int type) const;
|
||||
|
||||
bool EvaluateFields(const RichStyles& s, VectorMap<String, Value>& vars);
|
||||
|
||||
void ApplyZoom(Zoom z, const RichStyles& ostyle, const RichStyles& zstyle);
|
||||
|
||||
public:
|
||||
enum ValPosType { LABELS, INDEXENTRIES };
|
||||
|
||||
int GetPartCount() const { return part.GetCount(); }
|
||||
bool IsPara(int i) const { return part[i].Is<Para>(); }
|
||||
bool IsTable(int i) const;
|
||||
int GetPartLength(int pi) const;
|
||||
int FindPart(int& pos) const;
|
||||
int GetPartPos(int pi) const;
|
||||
|
||||
RichPara Get(int i, const RichStyles& s) const;
|
||||
RichPara Get(int i, const Uuid& styleid, const RichStyles& s) const;
|
||||
RichPara Get(int i, const RichStyle& style) const;
|
||||
Uuid GetParaStyle(int i) const { return part[i].Get<Para>().styleid; }
|
||||
void SetParaStyle(int i, const Uuid& si);
|
||||
|
||||
const RichTable& GetTable(int i) const;
|
||||
|
||||
int GetLength() const;
|
||||
int GetTableCount() const;
|
||||
bool IsEmpty() const;
|
||||
|
||||
RichCellPos GetCellPos(int table, int row, int column) const;
|
||||
RichCellPos GetCellPos(int table, Point p) const;
|
||||
|
||||
void Clear();
|
||||
|
||||
void ClearSpelling();
|
||||
|
||||
void SetPick(int parti, pick_ RichTable& table);
|
||||
void CatPick(pick_ RichTable& table) { SetPick(GetPartCount(), table); }
|
||||
void Set(int parai, const RichPara& p, const RichStyles& s);
|
||||
void Insert(int parai, const RichPara& p, const RichStyles& s);
|
||||
void Cat(const RichPara& p, const RichStyles& s) { Set(GetPartCount(), p, s); }
|
||||
|
||||
void RemovePart(int parti);
|
||||
|
||||
void Normalize();
|
||||
|
||||
Vector<int> GetAllLanguages() const;
|
||||
WString GetPlainText() const;
|
||||
|
||||
struct UpdateIterator {
|
||||
enum { CONTINUE = 0, STOP = 1, UPDATE = 2 };
|
||||
virtual int operator()(int pos, RichPara& para) = 0;
|
||||
virtual ~UpdateIterator() {}
|
||||
};
|
||||
bool Iterate(UpdateIterator& r, int gpos, const RichStyles& s);
|
||||
|
||||
struct Iterator {
|
||||
virtual bool operator()(int pos, const RichPara& para) = 0;
|
||||
virtual ~Iterator() {}
|
||||
};
|
||||
bool Iterate(Iterator& r, int gpos, const RichStyles& s) const;
|
||||
|
||||
RichTxt(const RichTxt& src, int);
|
||||
RichTxt();
|
||||
|
||||
#ifdef _DEBUG
|
||||
void Dump();
|
||||
#endif
|
||||
};
|
||||
472
uppdev/RichTextP/TxtData.cpp
Normal file
472
uppdev/RichTextP/TxtData.cpp
Normal file
|
|
@ -0,0 +1,472 @@
|
|||
#include "RichText.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
RichTxt::Para::Para(const Para& src, int)
|
||||
: object(src.object, 1)
|
||||
{
|
||||
length = src.length;
|
||||
styleid = src.styleid;
|
||||
content = src.content;
|
||||
haspos = src.haspos;
|
||||
if(src.number)
|
||||
number = new RichPara::NumberFormat(*src.number);
|
||||
cx = -1;
|
||||
checked = false;
|
||||
}
|
||||
|
||||
RichTxt::Part::Part(const Part& src, int) {
|
||||
if(src.Is<Para>())
|
||||
Create<Para>() <<= src.Get<Para>();
|
||||
else
|
||||
Create<RichTable>() <<= src.Get<RichTable>();
|
||||
}
|
||||
|
||||
RichTxt::Part::Part() {}
|
||||
|
||||
void RichTxt::Invalidate()
|
||||
{
|
||||
length = -1;
|
||||
tabcount = -1;
|
||||
py.Clear();
|
||||
}
|
||||
|
||||
int RichTxt::GetPartLength(int pi) const
|
||||
{
|
||||
return part[pi].Is<RichTable>() ? part[pi].Get<RichTable>().GetLength() : part[pi].Get<Para>().length;
|
||||
}
|
||||
|
||||
bool RichTxt::IsTable(int i) const { return part[i].Is<RichTable>(); }
|
||||
const RichTable& RichTxt::GetTable(int i) const { return part[i].Get<RichTable>(); }
|
||||
|
||||
|
||||
int RichTxt::FindPart(int& pos) const
|
||||
{
|
||||
int pi = 0;
|
||||
while(pi < part.GetCount()) {
|
||||
int l = GetPartLength(pi) + 1;
|
||||
if(pos < l)
|
||||
break;
|
||||
pos -= l;
|
||||
pi++;
|
||||
}
|
||||
if(pi >= part.GetCount())
|
||||
pos = 0;
|
||||
return pi;
|
||||
}
|
||||
|
||||
int RichTxt::GetPartPos(int pi) const
|
||||
{
|
||||
int pos = 0;
|
||||
for(int i = 0; i < pi; i++)
|
||||
pos += GetPartLength(i) + 1;
|
||||
return pos;
|
||||
}
|
||||
|
||||
void RichTxt::SetRefresh(int parti)
|
||||
{
|
||||
switch(r_type) {
|
||||
case NONE:
|
||||
r_parti = parti;
|
||||
r_type = PARA;
|
||||
if(IsPara(parti)) {
|
||||
Para& pp = part[parti].Get<Para>();
|
||||
if(pp.cx >= 0) {
|
||||
r_paraocx = pp.cx;
|
||||
r_paraocy = Sum(pp.linecy, 0) + pp.before + pp.after;
|
||||
r_keep = pp.keep;
|
||||
r_keepnext = pp.keepnext;
|
||||
r_newpage = pp.newpage;
|
||||
break;
|
||||
}
|
||||
else
|
||||
r_type = FROM;
|
||||
}
|
||||
break;
|
||||
case PARA:
|
||||
if(parti == r_parti) break;
|
||||
case FROM:
|
||||
r_parti = min(parti, r_parti);
|
||||
r_type = FROM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RichTxt::SetRefreshFrom(int parti)
|
||||
{
|
||||
r_type = FROM;
|
||||
if(r_type == NONE)
|
||||
r_parti = parti;
|
||||
else
|
||||
r_parti = min(parti, r_parti);
|
||||
}
|
||||
|
||||
void RichTxt::Put(int i, const RichPara& p, const RichStyle& s)
|
||||
{
|
||||
if(i >= part.GetCount() || !IsPara(i))
|
||||
part.At(i).Create<Para>();
|
||||
Para& pp = part[i].Get<Para>();
|
||||
int numbering = p.format.GetNumberLevel();
|
||||
if(pp.numbering != numbering)
|
||||
SetRefreshFrom(i);
|
||||
else
|
||||
SetRefresh(i);
|
||||
pp.number.Clear();
|
||||
pp.content = p.Pack(s.format, pp.object);
|
||||
pp.cx = -1;
|
||||
pp.checked = false;
|
||||
pp.styleid = p.format.styleid;
|
||||
pp.length = p.GetLength();
|
||||
pp.numbering = numbering;
|
||||
pp.spellerrors.Clear();
|
||||
pp.haspos = p.HasPos();
|
||||
if(numbering >= 0 || p.format.reset_number) {
|
||||
pp.number = new RichPara::NumberFormat;
|
||||
*pp.number = p.format;
|
||||
}
|
||||
}
|
||||
|
||||
void RichTxt::Put(int i, const RichPara& p, const RichStyles& s)
|
||||
{
|
||||
Put(i, p, GetStyle(s, p.format.styleid));
|
||||
}
|
||||
|
||||
void RichTxt::Set(int i, const RichPara& p, const RichStyles& s)
|
||||
{
|
||||
Put(i, p, s);
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void RichTxt::Insert(int i, const RichPara& p, const RichStyles& s)
|
||||
{
|
||||
part.Insert(i);
|
||||
Set(i, p, s);
|
||||
}
|
||||
|
||||
void RichTxt::RemovePart(int parti)
|
||||
{
|
||||
part.Remove(parti);
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void RichTxt::SetPick(int i, pick_ RichTable& p)
|
||||
{
|
||||
const_cast<RichTable&>(p).Normalize();
|
||||
part.At(i).Create<RichTable>() = p;
|
||||
Invalidate();
|
||||
SetRefresh(i);
|
||||
}
|
||||
|
||||
RichPara RichTxt::Get(int parai, const RichStyle& style) const
|
||||
{
|
||||
ASSERT(part[parai].Is<Para>());
|
||||
const Para& pp = part[parai].Get<Para>();
|
||||
RichPara p;
|
||||
p.Unpack(pp.content, pp.object, style.format);
|
||||
return p;
|
||||
}
|
||||
|
||||
RichPara RichTxt::Get(int parai, const Uuid& styleid, const RichStyles& s) const
|
||||
{
|
||||
RichPara p = Get(parai, GetStyle(s, styleid));
|
||||
p.format.styleid = styleid;
|
||||
return p;
|
||||
}
|
||||
|
||||
RichPara RichTxt::Get(int parti, const RichStyles& s) const
|
||||
{
|
||||
return Get(parti, part[parti].Get<Para>().styleid, s);
|
||||
}
|
||||
|
||||
bool RichTxt::IsEmpty() const
|
||||
{
|
||||
return part.IsEmpty() || part.GetCount() == 1 && ComputeLength() == 0;
|
||||
}
|
||||
|
||||
int RichTxt::ComputeLength() const
|
||||
{
|
||||
int length = part.GetCount() - 1;
|
||||
for(int i = 0; i < part.GetCount(); i++)
|
||||
length += GetPartLength(i);
|
||||
return length;
|
||||
}
|
||||
|
||||
int RichTxt::GetLength() const
|
||||
{
|
||||
if(length < 0)
|
||||
length = ComputeLength();
|
||||
return length;
|
||||
}
|
||||
|
||||
int RichTxt::GetTableCount() const
|
||||
{
|
||||
if(tabcount < 0) {
|
||||
tabcount = 0;
|
||||
for(int i = 0; i < part.GetCount(); i++)
|
||||
if(IsTable(i))
|
||||
tabcount += GetTable(i).GetTableCount() + 1;
|
||||
}
|
||||
return tabcount;
|
||||
}
|
||||
|
||||
bool RichTxt::EvaluateFields(const RichStyles& s, VectorMap<String, Value>& vars)
|
||||
{
|
||||
bool b = false;
|
||||
for(int i = 0; i < part.GetCount(); i++)
|
||||
if(IsTable(i)) {
|
||||
RichTable& tab = part[i].Get<RichTable>();
|
||||
for(int i = 0; i < tab.GetRows(); i++)
|
||||
for(int j = 0; j < tab.GetColumns(); j++)
|
||||
if(tab(i, j) && tab[i][j].text.EvaluateFields(s, vars)) {
|
||||
tab.InvalidateRefresh(i, j);
|
||||
b = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
RichPara p = Get(i, s);
|
||||
if(p.EvaluateFields(vars)) {
|
||||
b = true;
|
||||
Set(i, p, s);
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
void RichTxt::ClearSpelling()
|
||||
{
|
||||
for(int i = 0; i < part.GetCount(); i++) {
|
||||
if(IsTable(i)) {
|
||||
RichTable& tab = part[i].Get<RichTable>();
|
||||
for(int i = 0; i < tab.GetRows(); i++)
|
||||
for(int j = 0; j < tab.GetColumns(); j++)
|
||||
if(tab(i, j)) {
|
||||
tab[i][j].text.ClearSpelling();
|
||||
tab.InvalidateRefresh(i, j);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Para& p = part[i].Get<Para>();
|
||||
p.spellerrors.Clear();
|
||||
p.checked = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RichTxt::SetParaStyle(int i, const Uuid& id)
|
||||
{
|
||||
ASSERT(IsPara(i));
|
||||
Para& p = part[i].Get<Para>();
|
||||
p.styleid = id;
|
||||
p.cx = -1;
|
||||
SetRefreshFrom(i);
|
||||
}
|
||||
|
||||
void RichTxt::GetRichPos(int pos, RichPos& rp, int ti, int maxlevel, const RichStyles& st) const
|
||||
{
|
||||
int p = pos;
|
||||
int pti = ti;
|
||||
for(int i = 0; i < part.GetCount(); i++) {
|
||||
int l = GetPartLength(i) + 1;
|
||||
if(pos < l) {
|
||||
if(IsTable(i)) {
|
||||
const RichTable& tab = GetTable(i);
|
||||
rp.level++;
|
||||
rp.tabtextparti = i;
|
||||
rp.tabtextpartcount = part.GetCount();
|
||||
rp.tabtextlen = GetLength();
|
||||
rp.tabposintabtext = p - pos;
|
||||
rp.posintab = pos;
|
||||
rp.cell = tab.FindCell(pos);
|
||||
rp.posincell = pos;
|
||||
rp.tabsize = tab.GetSize();
|
||||
rp.tablen = tab.GetLength();
|
||||
const RichTxt& ct = tab[rp.cell].text;
|
||||
rp.celllen = ct.GetLength();
|
||||
rp.parenttab = pti;
|
||||
rp.table = ti + 1;
|
||||
if(rp.level < maxlevel)
|
||||
ct.GetRichPos(pos, rp, ti + 1 + tab.GetTableCount(rp.cell), maxlevel, st);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
rp.posinpara = pos;
|
||||
rp.parai = i;
|
||||
rp.partcount = part.GetCount();
|
||||
rp.paralen = l - 1;
|
||||
Get(i, st).GetRichPos(rp, pos);
|
||||
return;
|
||||
}
|
||||
}
|
||||
pos -= l;
|
||||
if(IsTable(i))
|
||||
ti += 1 + GetTable(i).GetTableCount();
|
||||
}
|
||||
rp.parai = part.GetCount();
|
||||
rp.posinpara = 0;
|
||||
rp.partcount = part.GetCount();
|
||||
rp.paralen = 0;
|
||||
}
|
||||
|
||||
RichPara::Format RichTxt::GetFirstFormat(const RichStyles& style) const
|
||||
{
|
||||
if(IsTable(0)) {
|
||||
const RichTable& tab = GetTable(0);
|
||||
return tab[0][0].text.GetFirstFormat(style);
|
||||
}
|
||||
RichPos rp;
|
||||
Get(0, style).GetRichPos(rp, 0);
|
||||
return rp.format;
|
||||
}
|
||||
|
||||
RichCellPos RichTxt::GetCellPos(int table, int row, int column) const
|
||||
{
|
||||
int pos = 0;
|
||||
for(int i = 0;; i++) {
|
||||
if(IsTable(i)) {
|
||||
table--;
|
||||
const RichTable& tab = part[i].Get<RichTable>();
|
||||
if(table <= tab.GetTableCount()) {
|
||||
if(table == 0) {
|
||||
RichCellPos p;
|
||||
p.tabsize = tab.GetSize();
|
||||
p.tablen = tab.GetLength();
|
||||
p.cellpos = tab.GetCellPos(row, column);
|
||||
p.pos = p.tabpos = pos;
|
||||
p.pos += p.cellpos;
|
||||
p.textlen = GetLength();
|
||||
p.level = 1;
|
||||
return p;
|
||||
}
|
||||
for(int i = 0; i < tab.GetRows(); i++)
|
||||
for(int j = 0; j < tab.GetColumns(); j++)
|
||||
if(tab(i, j)) {
|
||||
const RichTxt& txt = tab[i][j].text;
|
||||
if(table <= txt.GetTableCount()) {
|
||||
RichCellPos p = txt.GetCellPos(table, row, column);
|
||||
p.pos += pos + tab.GetCellPos(i, j);
|
||||
p.level++;
|
||||
return p;
|
||||
}
|
||||
table -= txt.GetTableCount();
|
||||
}
|
||||
NEVER();
|
||||
}
|
||||
else
|
||||
table -= tab.GetTableCount();
|
||||
}
|
||||
pos += GetPartLength(i) + 1;
|
||||
}
|
||||
NEVER();
|
||||
return RichCellPos();
|
||||
}
|
||||
|
||||
RichCellPos RichTxt::GetCellPos(int table, Point p) const
|
||||
{
|
||||
return GetCellPos(table, p.y, p.x);
|
||||
}
|
||||
|
||||
bool RichTxt::Iterate(UpdateIterator& r, int gpos, const RichStyles& s)
|
||||
{
|
||||
for(int pi = 0; pi < part.GetCount(); pi++)
|
||||
if(IsTable(pi)) {
|
||||
RichTable& tab = part[pi].Get<RichTable>();
|
||||
for(int i = 0; i < tab.GetRows(); i++)
|
||||
for(int j = 0; j < tab.GetColumns(); j++)
|
||||
if(tab(i, j)) {
|
||||
if(tab[i][j].text.Iterate(r, gpos, s))
|
||||
return true;
|
||||
gpos += tab[i][j].text.GetLength() + 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
RichPara p = Get(pi, s);
|
||||
int q = r(gpos, p);
|
||||
if(q & UpdateIterator::UPDATE)
|
||||
Set(pi, p, s);
|
||||
if(q & UpdateIterator::STOP)
|
||||
return true;
|
||||
gpos += GetPartLength(pi) + 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
struct sIter__ : RichTxt::UpdateIterator {
|
||||
RichTxt::Iterator *iter;
|
||||
virtual int operator()(int pos, RichPara& para) {
|
||||
return iter->operator()(pos, para) ? STOP : CONTINUE;
|
||||
}
|
||||
};
|
||||
|
||||
bool RichTxt::Iterate(Iterator& r, int gpos, const RichStyles& s) const
|
||||
{
|
||||
sIter__ it;
|
||||
it.iter = &r;
|
||||
return const_cast<RichTxt *>(this)->Iterate(it, gpos, s);
|
||||
}
|
||||
|
||||
void RichTxt::Init()
|
||||
{
|
||||
r_type = ALL;
|
||||
r_parti = 0;
|
||||
tabcount = length = 0;
|
||||
}
|
||||
|
||||
void RichTxt::Clear()
|
||||
{
|
||||
part.Clear();
|
||||
Init();
|
||||
}
|
||||
|
||||
RichTxt::RichTxt()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
RichTxt::RichTxt(const RichTxt& src, int)
|
||||
{
|
||||
Init();
|
||||
part <<= src.part;
|
||||
length = src.length;
|
||||
tabcount = src.tabcount;
|
||||
py.Clear();
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
#define DMP(x) s << #x << "=" << x << ", "
|
||||
|
||||
String RichPos::ToString() const
|
||||
{
|
||||
String s;
|
||||
DMP(tabtextparti);
|
||||
DMP(tabtextpartcount);
|
||||
DMP(tabposintabtext);
|
||||
DMP(tabtextlen);
|
||||
DMP(table);
|
||||
DMP(tabsize);
|
||||
DMP(cell);
|
||||
DMP(tablen);
|
||||
DMP(posintab);
|
||||
DMP(celllen);
|
||||
DMP(posincell);
|
||||
DMP(parai);
|
||||
DMP(partcount);
|
||||
DMP(posinpara);
|
||||
DMP(paralen);
|
||||
DMP(level);
|
||||
DMP(parenttab);
|
||||
s << "char: " << (char)chr;
|
||||
return s;
|
||||
}
|
||||
|
||||
String RichCellPos::ToString() const
|
||||
{
|
||||
String s;
|
||||
s << "pos: " << pos << ", textlen: " << textlen << ", size: " << tabsize << ", tabpos: " << tabpos
|
||||
<< ", tablen: " << tablen << ", cellpos: " << cellpos << ", celllen: " << celllen << ", level: " << level;
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
358
uppdev/RichTextP/TxtOp.cpp
Normal file
358
uppdev/RichTextP/TxtOp.cpp
Normal file
|
|
@ -0,0 +1,358 @@
|
|||
#include "RichText.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
void RichTxt::GetAllLanguages(Index<int>& all) const
|
||||
{
|
||||
for(int i = 0; i < part.GetCount(); i++) {
|
||||
if(IsTable(i)) {
|
||||
const RichTable& tab = part[i].Get<RichTable>();
|
||||
for(int i = 0; i < tab.GetRows(); i++)
|
||||
for(int j = 0; j < tab.GetColumns(); j++)
|
||||
if(tab(i, j))
|
||||
tab[i][j].text.GetAllLanguages(all);
|
||||
}
|
||||
else {
|
||||
RichPara p = Get(i, RichStyle::GetDefault());
|
||||
all.FindAdd(p.format.language);
|
||||
for(int i = 0; i < p.GetCount(); i++)
|
||||
all.FindAdd(p[i].format.language);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vector<int> RichTxt::GetAllLanguages() const
|
||||
{
|
||||
Index<int> all;
|
||||
GetAllLanguages(all);
|
||||
return all.PickKeys();
|
||||
}
|
||||
|
||||
bool RichTxt::Update(ParaOp& op)
|
||||
{
|
||||
bool val = false;
|
||||
for(int i = 0; i < part.GetCount(); i++)
|
||||
if(IsTable(i)) {
|
||||
RichTable& tab = part[i].Get<RichTable>();
|
||||
for(int i = 0; i < tab.GetRows(); i++)
|
||||
for(int j = 0; j < tab.GetColumns(); j++)
|
||||
if(tab(i, j))
|
||||
if(tab[i][j].text.Update(op)) {
|
||||
tab.InvalidateRefresh(i, j);
|
||||
val = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
if(op(part[i].Get<Para>()))
|
||||
val = true;
|
||||
RefreshAll();
|
||||
return val;
|
||||
}
|
||||
|
||||
RichTxt& RichTxt::GetText0(int& pos, bool update)
|
||||
{
|
||||
if(update)
|
||||
Invalidate();
|
||||
int p = pos;
|
||||
int pi = FindPart(p);
|
||||
if(IsTable(pi)) {
|
||||
RichTable& tab = part[pi].Get<RichTable>();
|
||||
Point cl = tab.FindCell(p);
|
||||
if(update) {
|
||||
tab.InvalidateRefresh(cl);
|
||||
SetRefresh(pi);
|
||||
}
|
||||
pos = p;
|
||||
return tab[cl].text.GetText0(pos, update);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
RichTxt& RichTxt::GetUpdateText(int& pos)
|
||||
{
|
||||
return GetText0(pos, true);
|
||||
}
|
||||
|
||||
const RichTxt& RichTxt::GetConstText(int& pos) const
|
||||
{
|
||||
return const_cast<RichTxt *>(this)->GetText0(pos, false);
|
||||
}
|
||||
|
||||
RichTable& RichTxt::GetTable0(int table, bool update)
|
||||
{
|
||||
if(update)
|
||||
Invalidate();
|
||||
for(int i = 0;; i++)
|
||||
if(IsTable(i)) {
|
||||
table--;
|
||||
RichTable& tab = part[i].Get<RichTable>();
|
||||
if(table <= tab.GetTableCount()) {
|
||||
if(update)
|
||||
SetRefresh(i);
|
||||
if(table == 0)
|
||||
return tab;
|
||||
for(int i = 0; i < tab.GetRows(); i++)
|
||||
for(int j = 0; j < tab.GetColumns(); j++)
|
||||
if(tab(i, j)) {
|
||||
RichTxt& txt = tab[i][j].text;
|
||||
if(table <= txt.GetTableCount()) {
|
||||
if(update)
|
||||
tab.InvalidateRefresh(i, j);
|
||||
return txt.GetTable0(table, update);
|
||||
}
|
||||
table -= txt.GetTableCount();
|
||||
}
|
||||
NEVER();
|
||||
}
|
||||
else
|
||||
table -= tab.GetTableCount();
|
||||
}
|
||||
}
|
||||
|
||||
RichTable& RichTxt::GetUpdateTable(int table)
|
||||
{
|
||||
return GetTable0(table, true);
|
||||
}
|
||||
|
||||
const RichTable& RichTxt::GetConstTable(int table) const {
|
||||
return const_cast<RichTxt *>(this)->GetTable0(table, false);
|
||||
}
|
||||
|
||||
void RichTxt::CombineFormat(FormatInfo& fi, int pi, int pi2, bool& first, const RichStyles& style) const
|
||||
{
|
||||
while(pi < pi2) {
|
||||
if(IsTable(pi)) {
|
||||
const RichTable& tab = part[pi].Get<RichTable>();
|
||||
for(int i = 0; i < tab.GetRows(); i++)
|
||||
for(int j = 0; j < tab.GetColumns(); j++)
|
||||
if(tab(i, j)) {
|
||||
const RichTxt& txt = tab[i][j].text;
|
||||
txt.CombineFormat(fi, 0, txt.GetPartCount(), first, style);
|
||||
}
|
||||
}
|
||||
else {
|
||||
RichPara pa = Get(pi, style);
|
||||
if(first) {
|
||||
fi.Set(pa.format);
|
||||
if(pa.GetCount())
|
||||
fi.Set(pa[0].format);
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
fi.Combine(pa.format);
|
||||
for(int i = first; i < pa.GetCount(); i++)
|
||||
fi.Combine(pa[i].format);
|
||||
}
|
||||
pi++;
|
||||
}
|
||||
}
|
||||
|
||||
void RichTxt::ApplyStyle(const RichText::FormatInfo& fi, RichPara& pa, const RichStyles& style)
|
||||
{
|
||||
if(fi.paravalid & STYLE) {
|
||||
int q = style.Find(fi.styleid);
|
||||
if(q >= 0) {
|
||||
pa.ApplyStyle(style[q].format);
|
||||
pa.format.styleid = fi.styleid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RichTxt::Apply(const RichText::FormatInfo& fi, RichPara& pa, const RichStyles& style)
|
||||
{
|
||||
ApplyStyle(fi, pa, style);
|
||||
for(int i = 0; i < pa.GetCount(); i++)
|
||||
fi.ApplyTo(pa[i].format);
|
||||
fi.ApplyTo(pa.format);
|
||||
}
|
||||
|
||||
void RichTxt::ApplyFormat(const FormatInfo& fi, int pi, int pi2, const RichStyles& style)
|
||||
{
|
||||
while(pi < pi2) {
|
||||
if(IsTable(pi)) {
|
||||
RichTable& tab = part[pi].Get<RichTable>();
|
||||
for(int i = 0; i < tab.GetRows(); i++)
|
||||
for(int j = 0; j < tab.GetColumns(); j++)
|
||||
if(tab(i, j)) {
|
||||
RichTxt& txt = tab[i][j].text;
|
||||
tab.InvalidateRefresh(i, j);
|
||||
txt.ApplyFormat(fi, 0, txt.GetPartCount(), style);
|
||||
}
|
||||
}
|
||||
else {
|
||||
RichPara pa;
|
||||
if(fi.paravalid & RichText::STYLE)
|
||||
pa = RichTxt::Get(pi, fi.styleid, style);
|
||||
else
|
||||
pa = Get(pi, style);
|
||||
Apply(fi, pa, style);
|
||||
Put(pi, pa, style);
|
||||
}
|
||||
pi++;
|
||||
}
|
||||
}
|
||||
|
||||
void RichTxt::SaveFormat(Formating& r, int p1, int p2, const RichStyles& style) const
|
||||
{
|
||||
Array<RichObject> dummy;
|
||||
for(int i = p1; i <= p2; i++)
|
||||
if(IsTable(i)) {
|
||||
const RichTable& tab = part[i].Get<RichTable>();
|
||||
for(int i = 0; i < tab.GetRows(); i++)
|
||||
for(int j = 0; j < tab.GetColumns(); j++)
|
||||
if(tab(i, j)) {
|
||||
const RichTxt& txt = tab[i][j].text;
|
||||
txt.SaveFormat(r, 0, txt.GetPartCount() - 1, style);
|
||||
}
|
||||
}
|
||||
else {
|
||||
RichPara pa = Get(i, style);
|
||||
for(int i = 0; i < pa.GetCount(); i++) {
|
||||
RichPara::Part& p = pa[i];
|
||||
int q = p.GetLength();
|
||||
p.field = Id();
|
||||
p.object = RichObject();
|
||||
WString h;
|
||||
while(q) {
|
||||
int c = min(q, 50000);
|
||||
h.Cat(c + 32);
|
||||
q -= c;
|
||||
}
|
||||
p.text = h;
|
||||
}
|
||||
r.styleid.Add(pa.format.styleid);
|
||||
r.format.Add(pa.Pack(GetStyle(style, pa.format.styleid).format, dummy));
|
||||
}
|
||||
}
|
||||
|
||||
void RichTxt::RestoreFormat(int pi, const Formating& info, int& ii, const RichStyles& style)
|
||||
{
|
||||
Array<RichObject> dummy;
|
||||
while(ii < info.format.GetCount() && pi < GetPartCount()) {
|
||||
if(IsTable(pi)) {
|
||||
RichTable& tab = part[pi].Get<RichTable>();
|
||||
for(int i = 0; i < tab.GetRows(); i++)
|
||||
for(int j = 0; j < tab.GetColumns(); j++) {
|
||||
if(tab(i, j)) {
|
||||
if(ii >= info.format.GetCount())
|
||||
return;
|
||||
tab.InvalidateRefresh(i, j);
|
||||
tab[i][j].text.RestoreFormat(0, info, ii, style);
|
||||
}
|
||||
}
|
||||
pi++;
|
||||
}
|
||||
else {
|
||||
RichPara pa = Get(pi, style);
|
||||
RichPara pf;
|
||||
pf.Unpack(info.format[ii], dummy, GetStyle(style, info.styleid[ii]).format);
|
||||
RichPara t;
|
||||
t.format = pf.format;
|
||||
int si = 0;
|
||||
int sp = 0;
|
||||
for(int j = 0; j < pf.GetCount(); j++) {
|
||||
const RichPara::Part& q = pf[j];
|
||||
for(int k = 0; k < q.text.GetLength(); k++) {
|
||||
int len = q.text[k] - 32;
|
||||
t.part.Add().format = q.format;
|
||||
while(len) {
|
||||
const RichPara::Part& p = pa[si];
|
||||
if(p.IsText()) {
|
||||
int l = min(len, p.GetLength() - sp);
|
||||
t.part.Top().text.Cat(p.text.Mid(sp, l));
|
||||
sp += l;
|
||||
len -= l;
|
||||
ASSERT(sp <= p.GetLength());
|
||||
if(sp >= p.GetLength()) {
|
||||
sp = 0;
|
||||
si++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ASSERT(sp == 0);
|
||||
(t.part.Add() = pa[si++]).format = q.format;
|
||||
len--;
|
||||
sp = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ASSERT(si == pa.GetCount() && sp == 0);
|
||||
Put(pi, t, style);
|
||||
ii++;
|
||||
pi++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WString RichTxt::GetPlainText() const {
|
||||
WString clip;
|
||||
for(int pi = 0; pi < GetPartCount(); pi++) {
|
||||
if(pi) {
|
||||
clip.Cat('\r');
|
||||
clip.Cat('\n');
|
||||
}
|
||||
if(IsTable(pi)) {
|
||||
const RichTable& tab = part[pi].Get<RichTable>();
|
||||
for(int i = 0; i < tab.GetRows(); i++)
|
||||
for(int j = 0; j < tab.GetColumns(); j++)
|
||||
if(tab(i, j)) {
|
||||
if(i || j) {
|
||||
clip.Cat('\r');
|
||||
clip.Cat('\n');
|
||||
}
|
||||
clip << tab[i][j].text.GetPlainText();
|
||||
}
|
||||
}
|
||||
else
|
||||
clip.Cat(Get(pi, RichStyle::GetDefault()).GetText());
|
||||
}
|
||||
return clip;
|
||||
}
|
||||
|
||||
RichTxt& RichTxt::GetTableUpdateText(int table, const RichStyles& style, int& pi)
|
||||
{
|
||||
Invalidate();
|
||||
for(int i = 0;; i++)
|
||||
if(IsTable(i)) {
|
||||
table--;
|
||||
RichTable& tab = part[i].Get<RichTable>();
|
||||
if(table <= tab.GetTableCount()) {
|
||||
SetRefresh(i);
|
||||
if(table == 0) {
|
||||
pi = i;
|
||||
return *this;
|
||||
}
|
||||
for(int i = 0; i < tab.GetRows(); i++)
|
||||
for(int j = 0; j < tab.GetColumns(); j++)
|
||||
if(tab(i, j)) {
|
||||
RichTxt& txt = tab[i][j].text;
|
||||
if(table <= txt.GetTableCount()) {
|
||||
tab.InvalidateRefresh(i, j);
|
||||
return txt.GetTableUpdateText(table, style, pi);
|
||||
}
|
||||
table -= txt.GetTableCount();
|
||||
}
|
||||
NEVER();
|
||||
}
|
||||
else
|
||||
table -= tab.GetTableCount();
|
||||
}
|
||||
NEVER();
|
||||
}
|
||||
|
||||
void RichTxt::Normalize()
|
||||
{
|
||||
RichPara pa;
|
||||
if(GetPartCount() && IsTable(0)) {
|
||||
part.Insert(0);
|
||||
Put(0, pa, RichStyle::GetDefault());
|
||||
Invalidate();
|
||||
}
|
||||
if(GetPartCount() == 0 || IsTable(GetPartCount() - 1)) {
|
||||
Put(GetPartCount(), pa, RichStyle::GetDefault());
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
377
uppdev/RichTextP/TxtPaint.cpp
Normal file
377
uppdev/RichTextP/TxtPaint.cpp
Normal file
|
|
@ -0,0 +1,377 @@
|
|||
#include "RichText.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
int RichTxt::GetWidth(const RichStyles& st) const
|
||||
{
|
||||
int cx = 0;
|
||||
for(int i = 0; i < part.GetCount(); i++) {
|
||||
if(IsPara(i)) {
|
||||
RichPara p = Get(i, st);
|
||||
RichPara::Lines pl = p.FormatLines(INT_MAX);
|
||||
int ccx = 0;
|
||||
Sum(ccx, ~pl.width, ~pl.width + pl.clen);
|
||||
cx = max(cx, ccx);
|
||||
}
|
||||
else
|
||||
return 10000;
|
||||
}
|
||||
return cx;
|
||||
}
|
||||
|
||||
|
||||
void RichTxt::Sync0(const Para& pp, int parti, const RichContext& rc) const
|
||||
{
|
||||
int cx = rc.page.Width();
|
||||
pp.cx = cx;
|
||||
RichPara p = Get(parti, rc.styles);
|
||||
RichPara::Lines pl = p.FormatLines(cx);
|
||||
pp.ruler = p.format.ruler;
|
||||
pp.before = p.format.before;
|
||||
pp.linecy.Clear();
|
||||
pp.linecy.SetCount(pl.GetCount());
|
||||
for(int i = 0; i < pl.GetCount(); i++)
|
||||
pp.linecy[i] = pl[i].Sum();
|
||||
pp.cy = Sum0(pp.linecy);
|
||||
pp.after = p.format.after;
|
||||
pp.newpage = p.format.newpage;
|
||||
pp.keep = p.format.keep;
|
||||
pp.keepnext = p.format.keepnext;
|
||||
pp.orphan = p.format.orphan;
|
||||
}
|
||||
|
||||
inline
|
||||
bool RichTxt::BreaksPage(PageY py, const Para& pp, int i, const Rect& page) const
|
||||
{
|
||||
int linecy = pp.linecy[i];
|
||||
if(linecy >= page.Height()) return false;
|
||||
if(linecy + py.y > page.bottom)
|
||||
return true;
|
||||
if(pp.orphan || pp.linecy.GetCount() < 2) return false;
|
||||
if((i == 0 || i == pp.linecy.GetCount() - 2) &&
|
||||
py.y + linecy + pp.linecy[i + 1] > page.bottom)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
PageY RichTxt::GetNextPageY(int parti, const RichContext& rc) const
|
||||
{
|
||||
if(part[parti].Is<RichTable>())
|
||||
return GetTable(parti).GetHeight(rc);
|
||||
else {
|
||||
Sync(parti, rc);
|
||||
const Para& pp = part[parti].Get<Para>();
|
||||
int cy = pp.before + pp.ruler;
|
||||
if(pp.keep || pp.keepnext)
|
||||
cy += pp.cy;
|
||||
else
|
||||
cy += pp.linecy[0];
|
||||
PageY py = rc.py;
|
||||
if(rc.page.Height() < 30000) {
|
||||
int nbefore = 0;
|
||||
int nline = 0;
|
||||
if(pp.keepnext && parti + 1 < part.GetCount() && part[parti + 1].Is<Para>()) {
|
||||
Sync(parti + 1, rc);
|
||||
const Para& p = part[parti + 1].Get<Para>();
|
||||
nbefore = p.before + p.ruler;
|
||||
nline = p.linecy[0];
|
||||
}
|
||||
if(pp.newpage || py.y + cy + nbefore + nline > rc.page.bottom && cy < rc.page.Height()) {
|
||||
py.page++;
|
||||
py.y = rc.page.top;
|
||||
}
|
||||
py.y += pp.before;
|
||||
if(py.y + pp.cy < rc.page.bottom)
|
||||
py.y += pp.cy;
|
||||
else
|
||||
for(int lni = 0; lni < pp.linecy.GetCount(); lni++) {
|
||||
if(BreaksPage(py, pp, lni, rc.page)) {
|
||||
py.y = rc.page.top;
|
||||
py.page++;
|
||||
}
|
||||
py.y += pp.linecy[lni];
|
||||
}
|
||||
py.y += pp.after;
|
||||
if(py.y > rc.page.bottom) {
|
||||
py.y = rc.page.top;
|
||||
py.page++;
|
||||
}
|
||||
}
|
||||
else
|
||||
py.y += pp.before + pp.cy + pp.after;
|
||||
return py;
|
||||
}
|
||||
}
|
||||
|
||||
PageY RichTxt::GetPartPageY(int parti, RichContext rc) const
|
||||
{
|
||||
for(int i = 0; i < parti; i++)
|
||||
rc.py = GetNextPageY(i, rc);
|
||||
return rc.py;
|
||||
}
|
||||
|
||||
bool IsPainting(PageDraw& pw, Zoom z, const Rect& page, PageY top, PageY bottom)
|
||||
{
|
||||
int t = top.y;
|
||||
for(int pi = top.page; pi < bottom.page; pi++) {
|
||||
if(pw.Page(pi).IsPainting(Rect(z * page.left, z * top.y, z * page.right, z * page.bottom)))
|
||||
return true;
|
||||
t = page.top;
|
||||
}
|
||||
return pw.Page(bottom.page).IsPainting(Rect(z * page.left, z * t, z * page.right, z * bottom.y));
|
||||
}
|
||||
|
||||
|
||||
void RichTxt::Paint(PageDraw& pw, RichContext rc, const PaintInfo& _pi) const
|
||||
{
|
||||
PaintInfo pi = _pi;
|
||||
int parti = 0;
|
||||
int pos = 0;
|
||||
RichPara::Number n;
|
||||
while(rc.py < pi.bottom && parti < part.GetCount()) {
|
||||
if(part[parti].Is<RichTable>()) {
|
||||
pi.tablesel--;
|
||||
const RichTable& tab = GetTable(parti);
|
||||
tab.Paint(pw, rc, pi);
|
||||
rc.py = tab.GetHeight(rc);
|
||||
pi.tablesel -= tab.GetTableCount();
|
||||
}
|
||||
else {
|
||||
const Para& pp = part[parti].Get<Para>();
|
||||
if(pp.number) {
|
||||
n.TestReset(*pp.number);
|
||||
n.Next(*pp.number);
|
||||
}
|
||||
PageY next = GetNextPageY(parti, rc);
|
||||
if(next >= pi.top) {
|
||||
int nbefore = 0;
|
||||
int nline = 0;
|
||||
if(pp.keepnext && parti + 1 < part.GetCount() && part[parti + 1].Is<Para>()) {
|
||||
Sync(parti + 1, rc);
|
||||
const Para& pp = part[parti + 1].Get<Para>();
|
||||
nbefore = pp.before;
|
||||
nline = pp.linecy[0];
|
||||
}
|
||||
RichPara p = Get(parti, rc.styles);
|
||||
if(pi.spellingchecker) {
|
||||
if(!pp.checked) {
|
||||
pp.spellerrors = (*pi.spellingchecker)(p);
|
||||
pp.checked = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
pp.checked = false;
|
||||
pp.spellerrors.Clear();
|
||||
}
|
||||
if(IsPainting(pw, pi.zoom, rc.page, rc.py, next))
|
||||
p.Paint(pw, rc.page, rc.py, pi, n, pp.spellerrors, nbefore, nline);
|
||||
}
|
||||
rc.py = next;
|
||||
}
|
||||
int l = GetPartLength(parti) + 1;
|
||||
pi.highlightpara -= l;
|
||||
pi.sell -= l;
|
||||
pi.selh -= l;
|
||||
pos += l;
|
||||
++parti;
|
||||
}
|
||||
}
|
||||
|
||||
RichCaret RichTxt::GetCaret(int pos, RichContext rc) const
|
||||
{
|
||||
int parti = 0;
|
||||
if(pos > GetLength())
|
||||
pos = GetLength();
|
||||
while(parti < part.GetCount()) {
|
||||
int l = GetPartLength(parti) + 1;
|
||||
if(pos < l)
|
||||
if(IsTable(parti))
|
||||
return GetTable(parti).GetCaret(pos, rc);
|
||||
else {
|
||||
const Para& p = part[parti].Get<Para>();
|
||||
int nbefore = 0;
|
||||
int nline = 0;
|
||||
if(p.keepnext && parti + 1 < part.GetCount() && part[parti + 1].Is<Para>()) {
|
||||
Sync(parti + 1, rc);
|
||||
const Para& pp = part[parti + 1].Get<Para>();
|
||||
nbefore = pp.before;
|
||||
nline = pp.linecy[0];
|
||||
}
|
||||
RichCaret tp = Get(parti, rc.styles).GetCaret(pos, rc.page, rc.py, nbefore, nline);
|
||||
tp.textpage = rc.page;
|
||||
return tp;
|
||||
}
|
||||
pos -= l;
|
||||
rc.py = GetNextPageY(parti++, rc);
|
||||
}
|
||||
return RichCaret();
|
||||
}
|
||||
|
||||
int RichTxt::GetPos(int x, PageY y, RichContext rc) const
|
||||
{
|
||||
int parti = 0;
|
||||
int pos = 0;
|
||||
|
||||
if(part.GetCount()) {
|
||||
PageY nnext = GetNextPageY(parti, rc);
|
||||
while(parti < part.GetCount()) {
|
||||
PageY next = nnext;
|
||||
if(parti + 1 < part.GetCount()) {
|
||||
RichContext nrc = rc;
|
||||
nrc.py = next;
|
||||
nnext = GetNextPageY(parti + 1, nrc);
|
||||
}
|
||||
if(y < next || y.page < next.page) {
|
||||
if(IsTable(parti))
|
||||
return GetTable(parti).GetPos(x, y, rc) + pos;
|
||||
else {
|
||||
int nbefore = 0;
|
||||
int nline = 0;
|
||||
if(part[parti].Get<Para>().keepnext && parti + 1 < part.GetCount() && IsPara(parti + 1)) {
|
||||
Sync(parti + 1, rc);
|
||||
const Para& pp = part[parti + 1].Get<Para>();
|
||||
nbefore = pp.before;
|
||||
nline = pp.linecy[0];
|
||||
}
|
||||
return Get(parti, rc.styles).GetPos(x, y, rc.page, rc.py, nbefore, nline) + pos;
|
||||
}
|
||||
}
|
||||
pos += GetPartLength(parti) + 1;
|
||||
parti++;
|
||||
rc.py = next;
|
||||
}
|
||||
}
|
||||
|
||||
return pos - 1;
|
||||
}
|
||||
|
||||
RichHotPos RichTxt::GetHotPos(int x, PageY y, int tolerance, RichContext rc) const
|
||||
{
|
||||
int parti = 0;
|
||||
int pos = 0;
|
||||
int ti = 0;
|
||||
if(part.GetCount()) {
|
||||
PageY nnext = GetNextPageY(parti, rc);
|
||||
while(parti < part.GetCount()) {
|
||||
PageY next = nnext;
|
||||
if(parti + 1 < part.GetCount()) {
|
||||
RichContext nrc = rc;
|
||||
nrc.py = next;
|
||||
nnext = GetNextPageY(parti + 1, nrc);
|
||||
}
|
||||
if(y < next || y.page < next.page) {
|
||||
if(IsTable(parti)) {
|
||||
RichHotPos pos = GetTable(parti).GetHotPos(x, y, tolerance, rc);
|
||||
pos.table += ti + 1;
|
||||
return pos;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
if(IsTable(parti))
|
||||
ti += 1 + GetTable(parti).GetTableCount();
|
||||
pos += GetPartLength(parti) + 1;
|
||||
parti++;
|
||||
rc.py = next;
|
||||
}
|
||||
}
|
||||
|
||||
return RichHotPos();
|
||||
}
|
||||
|
||||
int RichTxt::GetVertMove(int pos, int gx, RichContext rc, int dir) const
|
||||
{
|
||||
ASSERT(dir == -1 || dir == 1);
|
||||
if(GetPartCount() == 0)
|
||||
return -1;
|
||||
int pi;
|
||||
int p = pos;
|
||||
if(pos >= 0) {
|
||||
pi = FindPart(p);
|
||||
pos -= p;
|
||||
}
|
||||
else {
|
||||
pi = dir > 0 ? 0 : GetPartCount() - 1;
|
||||
p = -1;
|
||||
pos = 0;
|
||||
}
|
||||
while(pi < GetPartCount()) {
|
||||
int q = IsTable(pi) ? GetTable(pi).GetVertMove(p, gx, rc, dir)
|
||||
: Get(pi, rc.styles).GetVertMove(p, gx, rc.page, dir);
|
||||
if(q >= 0)
|
||||
return q + pos;
|
||||
if(dir > 0)
|
||||
pos += GetPartLength(pi) + 1;
|
||||
p = -1;
|
||||
pi += dir;
|
||||
if(pi < 0)
|
||||
break;
|
||||
if(dir < 0)
|
||||
pos -= GetPartLength(pi) + 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void RichTxt::GatherValPos(Vector<RichValPos>& f, RichContext rc, int pos, int type) const
|
||||
{
|
||||
int parti = 0;
|
||||
while(parti < part.GetCount()) {
|
||||
if(part[parti].Is<RichTable>())
|
||||
GetTable(parti).GatherValPos(f, rc, pos, type);
|
||||
else {
|
||||
int nbefore = 0;
|
||||
int nline = 0;
|
||||
const Para& p = part[parti].Get<Para>();
|
||||
if(p.keepnext && parti + 1 < part.GetCount() && IsPara(parti + 1)) {
|
||||
Sync(parti + 1, rc);
|
||||
const Para& pp = part[parti + 1].Get<Para>();
|
||||
nbefore = pp.before;
|
||||
nline = pp.linecy[0];
|
||||
}
|
||||
if(p.haspos)
|
||||
if(type == LABELS)
|
||||
Get(parti, rc.styles).GatherLabels(f, rc.page, rc.py, pos, nbefore, nline);
|
||||
else
|
||||
Get(parti, rc.styles).GatherIndexes(f, rc.page, rc.py, pos, nbefore, nline);
|
||||
}
|
||||
pos += GetPartLength(parti) + 1;
|
||||
rc.py = GetNextPageY(parti++, rc);
|
||||
}
|
||||
}
|
||||
|
||||
PageY RichTxt::GetHeight(RichContext rc) const
|
||||
{
|
||||
for(int i = 0; i < GetPartCount(); i++)
|
||||
rc.py = GetNextPageY(i, rc);
|
||||
return rc.py;
|
||||
}
|
||||
|
||||
PageY RichTxt::GetTop(RichContext rc) const
|
||||
{
|
||||
if(part.GetCount() == 0)
|
||||
return rc.py;
|
||||
if(part[0].Is<RichTable>())
|
||||
return GetTable(0).GetTop(rc);
|
||||
else {
|
||||
Sync(0, rc);
|
||||
const Para& pp = part[0].Get<Para>();
|
||||
rc.py.y += pp.before;
|
||||
if(BreaksPage(rc.py, pp, 0, rc.page))
|
||||
rc.Page();
|
||||
return rc.py;
|
||||
}
|
||||
}
|
||||
|
||||
void RichTxt::ApplyZoom(Zoom z, const RichStyles& ostyle, const RichStyles& zstyle)
|
||||
{
|
||||
for(int i = 0; i < GetPartCount(); i++)
|
||||
if(IsTable(i))
|
||||
part[i].Get<RichTable>().ApplyZoom(z, ostyle, zstyle);
|
||||
else {
|
||||
RichPara p = Get(i, ostyle);
|
||||
p.ApplyZoom(z);
|
||||
Set(i, p, zstyle);
|
||||
}
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
123
uppdev/RichTextP/Util.cpp
Normal file
123
uppdev/RichTextP/Util.cpp
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
#include "RichText.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
Draw& SimplePageDraw::Info()
|
||||
{
|
||||
return w;
|
||||
}
|
||||
|
||||
Draw& SimplePageDraw::Page(int)
|
||||
{
|
||||
return w;
|
||||
}
|
||||
|
||||
void RichText::ApplyZoom(Zoom z)
|
||||
{
|
||||
RichStyles ostyle(style, 1);
|
||||
for(int i = 0; i < style.GetCount(); i++)
|
||||
style[i].format *= z;
|
||||
RichTxt::ApplyZoom(z, ostyle, style);
|
||||
RefreshAll();
|
||||
}
|
||||
|
||||
Zoom GetRichTextStdScreenZoom()
|
||||
{
|
||||
return Zoom(Ctrl::HorzLayoutZoom(96), 600);
|
||||
}
|
||||
|
||||
struct QTFDisplayCls : Display {
|
||||
virtual void Paint(Draw& w, const Rect& r, const Value& q,
|
||||
Color ink, Color paper, dword style) const;
|
||||
virtual Size GetStdSize(const Value& q) const;
|
||||
virtual Size RatioSize(const Value& q, int cx, int cy) const;
|
||||
};
|
||||
|
||||
Size QTFDisplayCls::GetStdSize(const Value& q) const
|
||||
{
|
||||
Size sz;
|
||||
RichText txt = ParseQTF((String)q);
|
||||
txt.ApplyZoom(GetRichTextStdScreenZoom());
|
||||
sz.cx = txt.GetWidth();
|
||||
sz.cy = txt.GetHeight(Zoom(1, 1), sz.cx);
|
||||
return sz;
|
||||
}
|
||||
|
||||
Size QTFDisplayCls::RatioSize(const Value& q, int cx, int cy) const
|
||||
{
|
||||
if(cy == 0 && cx > 0) {
|
||||
RichText txt = ParseQTF((String)q);
|
||||
return Size(cx, txt.GetHeight(Zoom(1, 1), cx));
|
||||
}
|
||||
return GetStdSize(q);
|
||||
}
|
||||
|
||||
void QTFDisplayCls::Paint(Draw& draw, const Rect& r, const Value& v, Color ink, Color paper, dword style) const
|
||||
{
|
||||
String s;
|
||||
s << "[@(" << ink.GetR() << "." << ink.GetG() << "." << ink.GetB() << ") " << v;
|
||||
RichText rtext = ParseQTF(s);
|
||||
rtext.ApplyZoom(GetRichTextStdScreenZoom());
|
||||
draw.DrawRect(r, paper);
|
||||
draw.Clipoff(r);
|
||||
rtext.Paint(Zoom(1, 1), draw, 0, 0, r.Width());
|
||||
draw.End();
|
||||
}
|
||||
|
||||
const Display& QTFDisplay()
|
||||
{
|
||||
return Single<QTFDisplayCls>();
|
||||
}
|
||||
|
||||
struct QTFDisplayCCls : QTFDisplayCls {
|
||||
virtual void Paint(Draw& w, const Rect& r, const Value& q,
|
||||
Color ink, Color paper, dword style) const;
|
||||
};
|
||||
|
||||
void QTFDisplayCCls::Paint(Draw& draw, const Rect& r, const Value& v, Color ink, Color paper, dword style) const
|
||||
{
|
||||
String s;
|
||||
s << "[@(" << ink.GetR() << "." << ink.GetG() << "." << ink.GetB() << ") " << v;
|
||||
RichText rtext = ParseQTF(s);
|
||||
rtext.ApplyZoom(GetRichTextStdScreenZoom());
|
||||
draw.DrawRect(r, paper);
|
||||
draw.Clipoff(r);
|
||||
int cy = rtext.GetHeight(Zoom(1, 1), r.Width());
|
||||
rtext.Paint(Zoom(1, 1), draw, 0, max(0, (r.Height() - cy) / 2), r.Width());
|
||||
draw.End();
|
||||
}
|
||||
|
||||
const Display& QTFDisplayVCenter()
|
||||
{
|
||||
return Single<QTFDisplayCCls>();
|
||||
}
|
||||
|
||||
RichText AsRichText(const wchar *s, const RichPara::Format& f)
|
||||
{
|
||||
RichText clip;
|
||||
RichPara p;
|
||||
p.format = f;
|
||||
p.part.Add().format = f;
|
||||
RichStyle cs;
|
||||
cs.format = f;
|
||||
cs.format.sscript = 0;
|
||||
cs.format.link.Clear();
|
||||
cs.format.indexentry.Clear();
|
||||
cs.format.language = LNG_ENGLISH;
|
||||
cs.format.label.Clear();
|
||||
clip.SetStyle(f.styleid, cs);
|
||||
WString& part = p.part.Top().text;
|
||||
while(*s) {
|
||||
if(*s == '\n') {
|
||||
clip.Cat(p);
|
||||
part.Clear();
|
||||
}
|
||||
if(*s >= 32 || *s == '\t')
|
||||
part.Cat(*s);
|
||||
s++;
|
||||
}
|
||||
clip.Cat(p);
|
||||
return clip;
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
8
uppdev/RichTextP/init
Normal file
8
uppdev/RichTextP/init
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef _RichTextP_icpp_init_stub
|
||||
#define _RichTextP_icpp_init_stub
|
||||
#include "CtrlCore/init"
|
||||
#include "plugin\png/init"
|
||||
#define BLITZ_INDEX__ F70234807CBDCCBF7C7FC03C2E97EA2EC
|
||||
#include "RichImage.icpp"
|
||||
#undef BLITZ_INDEX__
|
||||
#endif
|
||||
705
uppdev/RichTextP/srcdoc.tpp/QTF$en-us.tpp
Normal file
705
uppdev/RichTextP/srcdoc.tpp/QTF$en-us.tpp
Normal file
|
|
@ -0,0 +1,705 @@
|
|||
topic "QTF";
|
||||
[2 $$0,0#00000000000000000000000000000000:Default]
|
||||
[@(128.0.255)2 $$1,0#65874547464505293575048467215454:QTF Chr]
|
||||
[*/+117 $$2,0#07143242482611002448121871408047:title]
|
||||
[*C@3+75 $$3,3#36268203433472503231438721581057:code]
|
||||
[{_}%EN-US
|
||||
[s0;= [*8 QTF]&]
|
||||
[s0; &]
|
||||
[s0; QTF is the native format of Ultimate`+`+ rich texts (formatted
|
||||
texts).&]
|
||||
[s0; &]
|
||||
[s0; It is byte oriented format. Bytes with values 2`-31 are ignored.
|
||||
Other are interpreted as characters or formatting commands.&]
|
||||
[s0; &]
|
||||
[s0; Letters ([@4 a]`-[@4 zA]`-[@4 Z]), numbers ([@4 0]`-[@4 9]), space (32)
|
||||
and characters&]
|
||||
[s0; &]
|
||||
[s0; [*@4 . , ; ! ? % ( ) / < > #]&]
|
||||
[s0; &]
|
||||
[s0; and bytes greater than 127 are guaranteed to be never used as
|
||||
command characters (not even in future versions of QTF). Other
|
||||
characters should be prefixed with escape character `` (reverse
|
||||
apostrophe). Group of characters can be escaped using byte 1.
|
||||
Example:&]
|
||||
[s0; &]
|
||||
[s3; `"`\1a`[x`]`\1`[`* bold`]`"&]
|
||||
[s0; &]
|
||||
[s0; Byte 0 represents the end of input sequence.&]
|
||||
[s0; &]
|
||||
[s0; Dimension units of QTF are dots `- one dot is defined as 1/600
|
||||
of inch.&]
|
||||
[s0; &]
|
||||
[s0; Colors are described as either number [@(128.0.255) 0]`-[@(128.0.255) 9],
|
||||
with meaning&]
|
||||
[s0; &]
|
||||
[ {{1000:1000:1000:1000:1000:1000:1000:1000:1000:1000<96;>96;f4; [s0;%- [* 0]]
|
||||
:: [s0;%- [* 1]]
|
||||
:: [s0;%- [* 2]]
|
||||
:: [s0;%- [* 3]]
|
||||
:: [s0;%- [* 4]]
|
||||
:: [s0;%- [* 5]]
|
||||
:: [s0;%- [* 6]]
|
||||
:: [s0;%- [* 7]]
|
||||
:: [s0;%- [* 8]]
|
||||
:: [s0;%- [* 9]]
|
||||
::l/0r/0t/0b/0@0 [s0; ]
|
||||
::@1 [s0; ]
|
||||
::@2 [s0; ]
|
||||
::@3 [s0; ]
|
||||
::@4 [s0; ]
|
||||
::@5 [s0; ]
|
||||
::@6 [s0; ]
|
||||
::@7 [s0; ]
|
||||
::@8 [s0; ]
|
||||
::@9 [s0; ]
|
||||
::l/25r/25t/15b/15@2 [s0;%- [1 Black]]
|
||||
:: [s0; [1 LtGray]]
|
||||
:: [s0; [1 White]]
|
||||
:: [s0;%- [1 Red]]
|
||||
:: [s0;%- [1 Green]]
|
||||
:: [s0;%- [1 Blue]]
|
||||
:: [s0;%- [1 LtRed]]
|
||||
:: [s0;%- [1 WhiteGray]]
|
||||
:: [s0;%- [1 LtCyan]]
|
||||
:: [s0;%- [1 Yellow]]}}&]
|
||||
[s0; &]
|
||||
[s0; or letters&]
|
||||
[s0; &]
|
||||
[ {{1109:1109:1109:1109:1109:1109:1109:1109:1128<96;>96;f4; [s0;%- [*C@(128.0.255) b]]
|
||||
:: [s0;%- [*C@(128.0.255) c]]
|
||||
:: [s0;%- [*C@(128.0.255) g]]
|
||||
:: [s0;%- [*C@(128.0.255) k]]
|
||||
:: [s0;%- [*C@(128.0.255) l]]
|
||||
:: [s0;%- [*C@(128.0.255) m]]
|
||||
:: [s0;%- [*C@(128.0.255) o]]
|
||||
:: [s0;%- [*C@(128.0.255) r]]
|
||||
:: [s0;%- [*C@(128.0.255) y]]
|
||||
::l/0r/0t/0b/0@5 [s0; ]
|
||||
::@(0.128.128) [s0; ]
|
||||
::@4 [s0; ]
|
||||
::@0 [s0; ]
|
||||
::@1 [s0; ]
|
||||
::@(128.0.255) [s0; ]
|
||||
::@(128.128.0) [s0; ]
|
||||
::@3 [s0; ]
|
||||
::@9 [s0; ]
|
||||
::l/25r/25t/15b/15@2 [s0;%- [1 Blue]]
|
||||
:: [s0;%- [1 Cyan]]
|
||||
:: [s0;%- [1 Green]]
|
||||
:: [s0;%- [1 Black]]
|
||||
:: [s0;%- [1 LtGray]]
|
||||
:: [s0;%- [1 Magenta]]
|
||||
:: [s0;%- [1 Brown]]
|
||||
:: [s0;%- [1 Red]]
|
||||
:: [s0;%- [1 Yellow]]}}&]
|
||||
[s0; &]
|
||||
[ {{1109:1109:1109:1109:1109:1109:1109:1109:1128<96;>96;f4; [s0;%- [*@(128.0.255) B]]
|
||||
:: [s0;%- [*@(128.0.255) C]]
|
||||
:: [s0;%- [*@(128.0.255) G]]
|
||||
:: [s0;%- [*@(128.0.255) K]]
|
||||
:: [s0;%- [*@(128.0.255) L]]
|
||||
:: [s0;%- [*@(128.0.255) M]]
|
||||
:: [s0;%- [*@(128.0.255) W]]
|
||||
:: [s0;%- [*@(128.0.255) R]]
|
||||
:: [s0;%- [*@(128.0.255) Y]]
|
||||
::l/0r/0t/0b/0@(0.0.255) [s0; ]
|
||||
::@8 [s0; ]
|
||||
::@(0.255.0) [s0; ]
|
||||
::@(128) [s0; ]
|
||||
::@(238) [s0; ]
|
||||
::@(255.0.255) [s0; ]
|
||||
::@2 [s0; ]
|
||||
::@6 [s0; ]
|
||||
::@(255.255.180) [s0; ]
|
||||
::l/25r/25t/15b/15@2 [s0;%- [1 LtBlue]]
|
||||
:: [s0;%- [1 LtCyan]]
|
||||
:: [s0;%- [1 LtGreen]]
|
||||
:: [s0;%- [1 Gray]]
|
||||
:: [s0;%- [1 WhiteGray]]
|
||||
:: [s0;%- [1 LtMagenta]]
|
||||
:: [s0;%- [1 White]]
|
||||
:: [s0;%- [1 LtRed]]
|
||||
:: [s0;%- [1 LtYellow]]}}&]
|
||||
[s0; &]
|
||||
[s0; or as the RGB value in form&]
|
||||
[s0; &]
|
||||
[s0; [@(128.0.255) (][/@(0.0.255) number][@(128.0.255) .][/@(0.0.255) number][@(128.0.255) .][/@(0.0.255) n
|
||||
umber][@(128.0.255) )]&]
|
||||
[s0;@(128.0.255) &]
|
||||
[s0; where [/@(0.0.255) number] is 0`-255.&]
|
||||
[s0; &]
|
||||
[s0; Form with single [/@(0.0.255) number]&]
|
||||
[s0; &]
|
||||
[s0; [@(128.0.255) (][/@(0.0.255) number][@(128.0.255) )]&]
|
||||
[s0;@(128.0.255) &]
|
||||
[s0; specifies grays.&]
|
||||
[s0; &]
|
||||
[s0; Letter&]
|
||||
[s0; &]
|
||||
[s0; [@(128.0.255) N]&]
|
||||
[s0;@(128.0.255) &]
|
||||
[s0; used in place of color designates transparent color.&]
|
||||
[s0; &]
|
||||
[s0; &]
|
||||
[s2; Basic QTF codes&]
|
||||
[s0; &]
|
||||
[s0; &]
|
||||
[ {{2003:7997<96;>96; [s0; [C@(128.0.255) `_]]
|
||||
:: [s0; Hard`-space `- space that cannot be divided at the end of line.]
|
||||
:: [s0; [C@(128.0.255) `&]]
|
||||
:: [s0; New paragraph.]
|
||||
:: [s0; [C@(128.0.255) `-`|]]
|
||||
:: [s0; Tabulator]
|
||||
:: [s0;%- [%%C@(128.0.255) `@`$][%%*C@(0.0.255) hex][C@(128.0.255) ;]]
|
||||
:: [s0; Unicode character as hexadecimal number.]}}&]
|
||||
[s0; &]
|
||||
[s0; &]
|
||||
[s2; Character and paragraph formatting&]
|
||||
[s0; &]
|
||||
[s0; Character and paragraph formatting starts with&]
|
||||
[s0;@(128.0.255) &]
|
||||
[s0; [@(128.0.255) `[]&]
|
||||
[s0;@(128.0.255) &]
|
||||
[s0; character followed by [*/ character/paragraph formating][/ sequence]
|
||||
ended with single space character and applies to the text until
|
||||
matching&]
|
||||
[s0; &]
|
||||
[s0; [@(128.0.255) `]]&]
|
||||
[s0;@(128.0.255) &]
|
||||
[s0; is encountered.&]
|
||||
[s0; &]
|
||||
[ {{1879:8121^@(229.229.248)-1 [s0; [*/ Character/paragraph formating sequence]]
|
||||
::=@2 [s0;%- ]
|
||||
::^ [s0;%- [C@(128.0.255) /]]
|
||||
::= [s0; Italic.]
|
||||
::^ [s0;%- [C@(128.0.255) `*]]
|
||||
::= [s0; Bold.]
|
||||
::^ [s0;%- [C@(128.0.255) `_]]
|
||||
::= [s0; Underline.]
|
||||
::^ [s0;%- [C@(128.0.255) `-]]
|
||||
::= [s0; Strikeout.]
|
||||
::^ [s0;%- [C@(128.0.255) c]]
|
||||
::= [s0; Capitals.]
|
||||
::^ [s0;%- [C@(128.0.255) ``]]
|
||||
::= [s0; Superscript.]
|
||||
::^ [s0;%- [C@(128.0.255) ,]]
|
||||
::= [s0; Subscript.]
|
||||
::^ [s0;%- [C@(128.0.255) d]]
|
||||
::= [s0; Dashed underline.]
|
||||
::^ [s0;%- [C@(128.0.255) T]]
|
||||
::= [s0; Non anti aliased font.]
|
||||
::^ [s0;%- [C@(128.0.255) `^][/C@(0.0.255) text][C@(128.0.255) `^]]
|
||||
::= [s0; Hyperlink.]
|
||||
::^ [s0;%- [C@(128.0.255) I][/C@(0.0.255) text][C@(128.0.255) ;]]
|
||||
::= [s0; Index entry.]
|
||||
::^ [s0;%- [C@(128.0.255) `+][/C@(0.0.255) number]]
|
||||
::= [s0; Font height in dots.]
|
||||
::^ [s0;%- [C@(128.0.255) 0]]
|
||||
::= [s0; Font height 50 dots (6 points).]
|
||||
::^ [s0;%- [C@(128.0.255) 1]]
|
||||
::= [s0; Font height 67 dots (8 points).]
|
||||
::^ [s0;%- [C@(128.0.255) 2]]
|
||||
::= [s0; Font height 84 dots (10 points).]
|
||||
::^ [s0;%- [C@(128.0.255) 3]]
|
||||
::= [s0; Font height 100 dots (12 points).]
|
||||
::^ [s0;%- [C@(128.0.255) 4]]
|
||||
::= [s0; Font height 134 dots (16 points).]
|
||||
::^ [s0;%- [C@(128.0.255) 5]]
|
||||
::= [s0; Font height 167 dots (20 points).]
|
||||
::^ [s0;%- [C@(128.0.255) 6]]
|
||||
::= [s0; Font height 200 dots (24 points).]
|
||||
::^ [s0;%- [C@(128.0.255) 7]]
|
||||
::= [s0; Font height 234 dots (28 points).]
|
||||
::^ [s0;%- [C@(128.0.255) 8]]
|
||||
::= [s0; Font height 300 dots (36 points).]
|
||||
::^ [s0;%- [C@(128.0.255) 9]]
|
||||
::= [s0; Font height 400 dots (48 points).]
|
||||
::^ [s0;%- [C@(128.0.255) `@][/C@(0.0.255) color]]
|
||||
::= [s0; Text color.]
|
||||
::^ [s0;%- [C@(128.0.255) `$][/C@(0.0.255) color]]
|
||||
::= [s0; Text background color.]
|
||||
::^ [s0;%- [C@(128.0.255) A]]
|
||||
::= [s0; Arial font.]
|
||||
::^ [s0;%- [C@(128.0.255) R]]
|
||||
::= [s0; Times New Roman font.]
|
||||
::^ [s0;%- [C@(128.0.255) C]]
|
||||
::= [s0; Courier font.]
|
||||
::^ [s0;%- [C@(128.0.255) G]]
|
||||
::= [s0; Standard GUI font.]
|
||||
::^ [s0;%- [C@(128.0.255) S]]
|
||||
::= [s0; Symbol font.]
|
||||
::^ [s0;%- [C@(128.0.255) .][/C@(0.0.255) number]]
|
||||
::= [s0; Font with specified font [/@(0.0.255) number].]
|
||||
::^ [s0;%- [C@(128.0.255) !][/C@(0.0.255) text][C@(128.0.255) !]]
|
||||
::= [s0; Font with face name equal to [/@(0.0.255) text]. If such font
|
||||
does not exist on system, Arial is used.]
|
||||
::^ [s1;%- [C `{][/C@(0.0.255) charset][C `}]&]
|
||||
[s0; ]
|
||||
::= [s0; Character set. It can be defined as either single character&]
|
||||
[s0; &]
|
||||
[ {{1840:8160<330;>1757;f4;h1; [s0; [C@(128.0.255) `_]]
|
||||
:: [s0; utf`-8]
|
||||
:: [s0; [C@(128.0.255) 0]]
|
||||
:: [s0; windows`-1250]
|
||||
:: [s0; [C@(128.0.255) 1]]
|
||||
:: [s0; windows`-1251]
|
||||
:: [s0; [C@(128.0.255) 2]]
|
||||
:: [s0; windows`-1252]
|
||||
:: [s0; [C@(128.0.255) 3]]
|
||||
:: [s0; windows`-1253]
|
||||
:: [s0; [C@(128.0.255) 4]]
|
||||
:: [s0; windows`-1254]
|
||||
:: [s0; [C@(128.0.255) 5]]
|
||||
:: [s0; windows`-1255]
|
||||
:: [s0; [C@(128.0.255) 6]]
|
||||
:: [s0; windows`-1256]
|
||||
:: [s0; [C@(128.0.255) 7]]
|
||||
:: [s0; windows`-1257]
|
||||
:: [s0; [C@(128.0.255) A]]
|
||||
:: [s0; iso`-8859`-1]
|
||||
:: [s0; [C@(128.0.255) B]]
|
||||
:: [s0; iso`-8859`-2]
|
||||
:: [s0; [C@(128.0.255) C]]
|
||||
:: [s0; iso`-8859`-3]
|
||||
:: [s0; [C@(128.0.255) D]]
|
||||
:: [s0; iso`-8859`-4]
|
||||
:: [s0; [C@(128.0.255) E]]
|
||||
:: [s0; iso`-8859`-5]
|
||||
:: [s0; [C@(128.0.255) F]]
|
||||
:: [s0; iso`-8859`-6]
|
||||
:: [s0; [C@(128.0.255) G]]
|
||||
:: [s0; iso`-8859`-7]
|
||||
:: [s0; [C@(128.0.255) H]]
|
||||
:: [s0; iso`-8859`-8]
|
||||
:: [s0; [C@(128.0.255) I]]
|
||||
:: [s0; iso`-8859`-9]
|
||||
:: [s0; [C@(128.0.255) J]]
|
||||
:: [s0; iso`-8859`-10]}}&]
|
||||
[s0; &]
|
||||
[s0; or as the string designating character set (example: [*C@3 `"`[`{`_`}_...`]`"][* ,
|
||||
][*C@3 `"`[`{windows`-1250`}_...`]`"]).]
|
||||
::^ [s0;%- [C@(128.0.255) %][/C@(0.0.255) lang]]
|
||||
::= [s0; Language. It is defined in form [@(0.0.255) XX]`-[@(0.0.255) YY],
|
||||
according to ISO 639 and ISO 3166 standards. (example: [*C@3 `"`[%EN`-US_...`]`"]).
|
||||
[*C@3 `"`[%00`-00_`"] represents `"none`" language. As special
|
||||
optimization, [*@(128.0.255) %`-] is equivalent to [@(128.0.255) %][@(0.0.255) 00`-00]
|
||||
(no language) and&]
|
||||
[s0; [@(128.0.255) %%] is equivalent to [@(128.0.255) %][@(0.0.255) EN`-US].]
|
||||
::^ [s0;%- [C@(128.0.255) :][/C@(0.0.255) text][C@(128.0.255) :]]
|
||||
::= [s0; Paragraph label.]
|
||||
::^ [s0;%- [C@(128.0.255) <]]
|
||||
::= [s0; Align paragraph left.]
|
||||
::^ [s0;%- [C@(128.0.255) `=]]
|
||||
::= [s0; Center paragraph.]
|
||||
::^ [s0;%- [C@(128.0.255) >]]
|
||||
::= [s0; Align paragraph right.]
|
||||
::^ [s0;%- [C@(128.0.255) #]]
|
||||
::= [s0; Justify paragraph.]
|
||||
::^ [s0;%- [C@(128.0.255) l][/C@(0.0.255) number]]
|
||||
::= [s0; Left margin in dots.]
|
||||
::^ [s0;%- [C@(128.0.255) r][/C@(0.0.255) number]]
|
||||
::= [s0; Right margin in dots.]
|
||||
::^ [s0;%- [C@(128.0.255) i][/C@(0.0.255) number]]
|
||||
::= [s0; Indent in dots.]
|
||||
::^ [s0;%- [C@(128.0.255) pn]]
|
||||
::= [s0; Line spacing 1.0.]
|
||||
::^ [s0;%- [C@(128.0.255) ph]]
|
||||
::= [s0; Line spacing 1.5.]
|
||||
::^ [s0;%- [C@(128.0.255) pd]]
|
||||
::= [s0; Line spacing 2.0.]
|
||||
::^ [s0;%- [C@(128.0.255) H][/C@(0.0.255) number]]
|
||||
::= [s0; Horizontal ruler height (if zero, there is no ruler).]
|
||||
::^ [s0;%- [C@(128.0.255) h][/C@(0.0.255) color]]
|
||||
::= [s0; Color of horizontal ruler (default is black).]
|
||||
::^ [s0;%- [C@(128.0.255) b][/C@(0.0.255) number]]
|
||||
::= [s0; Space before paragraph in dots.]
|
||||
::^ [s0;%- [C@(128.0.255) a][/C@(0.0.255) number]]
|
||||
::= [s0; Space after paragraph in dots.]
|
||||
::^ [s0;%- [C@(128.0.255) P]]
|
||||
::= [s0; Page break before paragraph.]
|
||||
::^ [s0;%- [C@(128.0.255) k]]
|
||||
::= [s0; Keep paragraph on single page.]
|
||||
::^ [s0;%- [C@(128.0.255) K]]
|
||||
::= [s0; Keep paragraph on same page as next one.]
|
||||
::^ [s0;%- [C@(128.0.255) Q]]
|
||||
::= [s0; Orphan control.]
|
||||
::^ [s0;%- [C@(128.0.255) n][/C@(0.0.255) text][C@(128.0.255) ;]]
|
||||
::= [s0; Text to insert before paragraph number.]
|
||||
::^ [s0;%- [C@(128.0.255) m][/C@(0.0.255) text][C@(128.0.255) ;]]
|
||||
::= [s0; Text to insert after paragraph number.]
|
||||
::^ [s0;%- [C@(128.0.255) N]]
|
||||
::= [s0; Numbering. It is followed by up to 8 characters defining numbering
|
||||
style of each level&]
|
||||
[s0; &]
|
||||
[ {{864:9136<342;>861;f4; [s0; [C@(128.0.255) `-]]
|
||||
:: [s0; Level is not used.]
|
||||
:: [s0; [C@(128.0.255) 1]]
|
||||
:: [s0; Numbers, starting with 1.]
|
||||
:: [s0; [C@(128.0.255) 0]]
|
||||
:: [s0; Numbers, starting with 0.]
|
||||
:: [s0; [C@(128.0.255) a]]
|
||||
:: [s0; Lowercase letters, starting with a.]
|
||||
:: [s0; [C@(128.0.255) A]]
|
||||
:: [s0; Uppercase letters, starting with A.]
|
||||
:: [s0; [C@(128.0.255) i]]
|
||||
:: [s0; Lowercase roman numbers, starting with i.]
|
||||
:: [s0; [C@(128.0.255) I]]
|
||||
:: [s0; Uppercase roman numbers, starting with I]}}&]
|
||||
[s0; ]
|
||||
::^ [s0;%- [C@(128.0.255) o]]
|
||||
::= [s0; Bullet style.]
|
||||
::^ [s0;%- [C@(128.0.255) O`_]]
|
||||
::= [s0; No bullet.]
|
||||
::^ [s0;%- [C@(128.0.255) O0]]
|
||||
::= [s0; Bullet style.]
|
||||
::^ [s0;%- [C@(128.0.255) O1]]
|
||||
::= [s0; Bullet style.]
|
||||
::^ [s0;%- [C@(128.0.255) O2]]
|
||||
::= [s0; Bullet style.]
|
||||
::^ [s0;%- [C@(128.0.255) O3]]
|
||||
::= [s0; Bullet style.]
|
||||
::^ [s0;%- [C@(128.0.255) O9]]
|
||||
::= [s0; Text bullet style.]
|
||||
::^ [s0;%- [C@(128.0.255) t][/C@(0.0.255) number]]
|
||||
::= [s0; Default tab size.]
|
||||
::^ [s0;%- [C@(128.0.255) `~]]
|
||||
::= [s0; Tabulator setting. Can be followed by character designating
|
||||
type of tabulation&]
|
||||
[s0; &]
|
||||
[ {{864:9136<342;>861;f4; [s0; [C@(128.0.255) >]]
|
||||
:: [s0; Normal tabulation.]
|
||||
:: [s0; [C@(128.0.255) <]]
|
||||
:: [s0; Left tabulation.]
|
||||
:: [s0; [C@(128.0.255) `=]]
|
||||
:: [s0; Centered tabulation.]}}&]
|
||||
[s0; &]
|
||||
[s0; (default is normal) and by filler character &]
|
||||
[s0; &]
|
||||
[ {{3312:3436:3252<342;>861;f4; [s0; [C@(128.0.255) .]]
|
||||
:: [s0; [C@(128.0.255) `-]]
|
||||
:: [s0; [C@(128.0.255) `_]]}}&]
|
||||
[s0; &]
|
||||
[s0; and must be followed by number specifying tabulator position
|
||||
in dots.&]
|
||||
[s0; &]
|
||||
[s0; When followed by [C@(128.0.255) `~] ([*C@3 `"`~`~`"]), clears all
|
||||
current tab settings (including those inherited from paragraph
|
||||
style).]
|
||||
::^ [s0;%- [C@(128.0.255) ;]]
|
||||
::= [s0; NOP separator. In some cases it is needed to separate command
|
||||
code. Example: [*C@3 `"`[l200;4 `"]]
|
||||
::^ [s1; [%-C s][/C@(0.0.255) number]&]
|
||||
[s0; [%-C@(128.0.255) s][/C@(0.0.255) `"text`"]]
|
||||
:: [s0; Paragraph style, either defined by style number, or style name.]}}&]
|
||||
[s0;3 &]
|
||||
[s0;3 &]
|
||||
[s2; Styles&]
|
||||
[s0; &]
|
||||
[s0; Paragraph styles are defined using normal character/paragraph
|
||||
formatting sequence with&]
|
||||
[s0; &]
|
||||
[s0; [@(128.0.255) `$`$][@(0.0.255) number][@(128.0.255) ,][@(0.0.255) nnumber][@(128.0.255) #][@(0.0.255) u
|
||||
uid][@(128.0.255) :][@(0.0.255) name]&]
|
||||
[s0; &]
|
||||
[s0; instead of text, where&]
|
||||
[s0; &]
|
||||
[ {{1879:8121^ [s0;%- [@(0.0.255) number]]
|
||||
:: [s0; Number of style `- can be used with [@(128.0.255) s] paragraph
|
||||
format command code.]
|
||||
:: [s0;%- [@(0.0.255) nnumber]]
|
||||
:: [s0; Number of style of next paragraph `- used by RichText editor
|
||||
when inserting paragraphs.]
|
||||
:: [s0;%- [@(0.0.255) uuid]]
|
||||
:: [s0; 32 digit unique hexadecimal identifier of style.]
|
||||
:: [s0;%- [@(0.0.255) name]]
|
||||
:: [s0; Name of style, displayed by editors. Can also be used with [@(128.0.255) s]
|
||||
paragraph format command code.]}}&]
|
||||
[s0; &]
|
||||
[s0; Style with [@(0.0.255) number] `= 0 and [@(0.0.255) uuid `= ]00000000000000000000000
|
||||
000000000 is [*/ default] style.&]
|
||||
[s0; &]
|
||||
[s0; Example:&]
|
||||
[s0; &]
|
||||
[s0; [C@3 `"`[`*/`+117 `$`$2,0#07143242482611002448121871408047:title`]`"]&]
|
||||
[s0;@(0.0.255) &]
|
||||
[s0;@(0.0.255) &]
|
||||
[s2; Objects&]
|
||||
[s0;@(0.0.255) &]
|
||||
[s0; Object plays the role of the single character and is displayed
|
||||
according to its type. It is started with a header in the form&]
|
||||
[s0; &]
|
||||
[s0; [@(128.0.255) `@`@][@(0.0.255) format][@(128.0.255) :][@(0.0.255) cx][@(128.0.255) `&][@(0.0.255) c
|
||||
y]&]
|
||||
[s0;@(0.0.255) &]
|
||||
[s0;%- where&]
|
||||
[s0; &]
|
||||
[ {{1879:8121^ [s0; [@(0.0.255) format]]
|
||||
:: [s0; Format of objects. This format must be recognized by the application.
|
||||
By default, RichText recognizes the PNG format.]
|
||||
:: [s0; [@(0.0.255) cx]]
|
||||
:: [s0; Width of object in dots.]
|
||||
:: [s0; [@(0.0.255) cy]]
|
||||
:: [s0; Height of object in dots.]}}&]
|
||||
[s0;@(0.0.255) &]
|
||||
[s0; Header is followed by binary data of object, encoded in 7 bit
|
||||
format. Bit 7 of data bytes is always 1, so that actual data
|
||||
bytes are in range 128`-255. First byte in range 32`-127 ends
|
||||
data sequence.&]
|
||||
[s0; &]
|
||||
[s0; Data are encoded in 7 byte groups, which corresponds to 8 bytes
|
||||
of encoded format. First byte of this 8 bytes block always contains
|
||||
eight bits of following bytes, LSB (that is bit 0) being the
|
||||
eight bit for first byte in block.&]
|
||||
[s0;@(0.0.255) &]
|
||||
[s0;@(0.0.255) &]
|
||||
[s2; Tables&]
|
||||
[s0; &]
|
||||
[s0; Table definition starts with&]
|
||||
[s0;3 &]
|
||||
[s0; [@(128.0.255) `{`{]&]
|
||||
[s0;@(128.0.255) &]
|
||||
[s0; pair, followed by set of numbers separated with&]
|
||||
[s0; &]
|
||||
[s0; [@(128.0.255) :]&]
|
||||
[s0;@(128.0.255) &]
|
||||
[s0; Numbers represent ratios of column widths; count of numbers
|
||||
is equivalent to count of columns. Next there is [/ table/cell
|
||||
formatting sequence] ended with single space character. Cells
|
||||
are separated with&]
|
||||
[s0; &]
|
||||
[s0; [@(128.0.255) `::]&]
|
||||
[s0;@(128.0.255) &]
|
||||
[s0; characters and another table/cell formating sequence (to setup
|
||||
format for each individual cell). Formating of cells is inherited
|
||||
from previous cells. Table ends with&]
|
||||
[s0; &]
|
||||
[s0; [@(128.0.255) `}`}]&]
|
||||
[s0;@(128.0.255) &]
|
||||
[s0; pair.&]
|
||||
[s0; &]
|
||||
[ {{1993:8007^@(229.229.248)-1 [s0; [*/ Table/cell formating sequence]]
|
||||
::=@2 [s0;%- ]
|
||||
::^ [s0;%- [C@(128.0.255) <][/C@(0.0.255) number]]
|
||||
:: [s0; Left margin of table in dots.]
|
||||
:: [s0;%- [C@(128.0.255) >][/C@(0.0.255) number]]
|
||||
:: [s0; Right margin of table in dots.]
|
||||
:: [s0;%- [C@(128.0.255) B][/C@(0.0.255) number]]
|
||||
:: [s0; Space before table in dots.]
|
||||
:: [s0;%- [C@(128.0.255) A][/C@(0.0.255) number]]
|
||||
:: [s0; Space after table in dots.]
|
||||
:: [s0;%- [C@(128.0.255) f][/C@(0.0.255) number]]
|
||||
:: [s0; Frame thickness in dots. Frame is outer border of table. Default
|
||||
value is 10.]
|
||||
:: [s0;%- [C@(128.0.255) F][/C@(0.0.255) color]]
|
||||
:: [s0; Color of the frame.]
|
||||
:: [s0; [%-C@(128.0.255) g][/C@(0.0.255) number]]
|
||||
:: [s0; Grid thickness in dots. Grid are lines dividing cells inside
|
||||
table. Default value is 4.]
|
||||
:: [s0;%- [C@(128.0.255) G][/C@(0.0.255) color]]
|
||||
:: [s0; Color of the grid.]
|
||||
:: [s0;%- [C@(128.0.255) k]]
|
||||
:: [s0; Keep the cell on single page.]
|
||||
:: [s0;%- [C@(128.0.255) K]]
|
||||
:: [s0; Keep the table on single page.]
|
||||
:: [s0;%- [C@(128.0.255) `~]]
|
||||
:: [s0; Sets grid and frame thickness to zero. Useful when using tables
|
||||
to organize text.]
|
||||
:: [s0; [%-C@(128.0.255) h][/C@(0.0.255) number]]
|
||||
:: [s0; Number of header rows. Header rows are repeated at the beginning
|
||||
of every page.]
|
||||
:: [s0;%- [C@(128.0.255) `^]]
|
||||
:: [s0; Cell aligns to top. Default.]
|
||||
:: [s0;%- [C@(128.0.255) `=]]
|
||||
:: [s0; Cell aligns to center (vertical).]
|
||||
:: [s0;%- [C@(128.0.255) v]]
|
||||
:: [s0; Cell aligns to bottom.]
|
||||
:: [s1; [%-C l][/C@(0.0.255) number/number]&]
|
||||
[s0; [%-C@(128.0.255) l][/C@(0.0.255) number]&]
|
||||
[s0; [%-C@(128.0.255) l][/C@(0.0.255) /number]]
|
||||
:: [s0; Sets left cell border (first [/@(0.0.255) number]) and margin
|
||||
in dots. If any of numbers is missing, sets only the one present.
|
||||
Default is border: 0, margin: 25.]
|
||||
:: [s1; [C r][/C@(0.0.255) number/number]&]
|
||||
[s0; [C@(128.0.255) r][/C@(0.0.255) number]&]
|
||||
[s0; [C@(128.0.255) r][/C@(0.0.255) /number]]
|
||||
:: [s0; Sets right cell border (first [/@(0.0.255) number]) and margin
|
||||
in dots. If any of numbers is missing, sets only the one present.
|
||||
Default is border: 0, margin: 25.]
|
||||
:: [s1; [C t][/C@(0.0.255) number/number]&]
|
||||
[s0; [C@(128.0.255) t][/C@(0.0.255) number]&]
|
||||
[s0; [C@(128.0.255) t][/C@(0.0.255) /number]]
|
||||
:: [s0; Sets top cell border (first [/@(0.0.255) number]) and margin in
|
||||
dots. If any of numbers is missing, sets only the one present.
|
||||
Default is border: 0, margin: 15.]
|
||||
:: [s1; [C b][/C@(0.0.255) number/number]&]
|
||||
[s0; [C@(128.0.255) b][/C@(0.0.255) number]&]
|
||||
[s0; [C@(128.0.255) b][/C@(0.0.255) /number]]
|
||||
:: [s0; Sets bottom cell border (first [/@(0.0.255) number]) and margin
|
||||
in dots. If any of numbers is missing, sets only the one present.
|
||||
Default is border: 0, margin: 15.]
|
||||
:: [s1; [C a][/C@(0.0.255) number/number]&]
|
||||
[s0; [C@(128.0.255) a][/C@(0.0.255) number]&]
|
||||
[s0; [C@(128.0.255) a][/C@(0.0.255) /number]]
|
||||
:: [s0; Sets all cell borders (first [/@(0.0.255) number]) and margins
|
||||
in dots. If any of numbers is missing, sets only the one present.]
|
||||
:: [s0; [C@(128.0.255) `@][/C@(0.0.255) color]]
|
||||
:: [s0; Cell background color. Default is White.]
|
||||
:: [s0; [C@(128.0.255) R][/C@(0.0.255) color]]
|
||||
:: [s0; Cell border color. Default is Black.]
|
||||
:: [s0; [C@(128.0.255) !]]
|
||||
:: [s0; Resets cell formatting to default values.]
|
||||
:: [s0; [C@(128.0.255) H][/C@(0.0.255) number]]
|
||||
:: [s0; Sets the minimal height of cell (and therefore also of row)
|
||||
in dots.]
|
||||
:: [s0; [C@(128.0.255) `-][/C@(0.0.255) number]]
|
||||
:: [s0; Horizontal cell span.]
|
||||
:: [s0; [C@(128.0.255) `|][/C@(0.0.255) number]]
|
||||
:: [s0; Vertical cell span.]
|
||||
:: [s0; [C@(128.0.255) ;]]
|
||||
::= [s0; NOP separator. In some cases it helps to separate command code.]}}&]
|
||||
[s0;3 &]
|
||||
[s0; Note: There is also legacy support for old table format (from
|
||||
previous QTF version) that is based on [@(128.0.255) `+`+ ]pair
|
||||
as table start/stop and [@(128.0.255) `|`| `-`-] to divide cells/lines.
|
||||
&]
|
||||
[s0;3 &]
|
||||
[s0;3 &]
|
||||
[s2; [3 Examples]&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"Normal `[`* bold`] `[/ italic`] `[`_ underline`] `[``
|
||||
superscript`] `[, subscript`]`"]]
|
||||
:: [s0; Normal [* bold] [/ italic] [_ underline] [` superscript] [, subscript]]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"```[ ```] `\1`[escaped`]`\1 `[`* bold`]`"]]
|
||||
:: [s0; `[ `] `[escaped`] [* bold]]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"`[A Arial (Sans`-Serif)`] `[R Times New Roman (Serif)`]
|
||||
`[C Courier (Monospace)`]`"]]
|
||||
:: [s0; Arial (Sans`-Serif) [R Times New Roman (Serif)] [C Courier (Monospace)]]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"`[0 6pt `]`[1 8pt `]`[2 10pt `]`[3 12pt `]`[4 16pt `]`[5
|
||||
20pt `]`[6 24pt `]`[7 28pt `]`[8 36pt `]`[9 48pt `]`"]]
|
||||
:: [s0; [0 6pt ][1 8pt ]10pt [3 12pt] [4 16pt ][5 20pt ][6 24pt ][7 28pt ][8 36pt ][9 48pt
|
||||
]]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"`[!Tahoma! Tahoma`]`"]]
|
||||
:: [s0; Tahoma]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"`[`+500 500dots`]`"]]
|
||||
:: [s0; [+500 500dots]]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"`[`@4 Green text`] `[`$(255.220.200) Pink background`]`"]]
|
||||
:: [s0; [@4 Green text] [$(255.220.200) Pink background]]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"`[%EN`-US English language`] `[%CS`-CZ Czech language`]`"]]
|
||||
:: [s0;%CS-CZ [%% English language ]Czech language]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"`[`^upp.sf.net`^ Hyperlink`] `[Icompiler, linker; Index
|
||||
entry`]`"]]
|
||||
:: [s0; [^upp`.sf`.net^ Hyperlink] [Icompiler`, linker; Index entry]]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"`[:label: Labeled paragraph`]`"]]
|
||||
:: [s0; Labeled paragraph]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"`[< Left paragraph alignment`]`"]]
|
||||
:: [s0; Left paragraph alignment]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"`[`= Center paragraph alignment`]`"]]
|
||||
:: [s0; Center paragraph alignment]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"`[> Right paragraph alignment`]`"]]
|
||||
:: [s0; Right paragraph alignment]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"`[# Justify alignment. Just some text to demosntrate
|
||||
it... Just some text to demonstrate it... Just some text to demonstrate
|
||||
it...`]`"]]
|
||||
:: [s0; Justify alignment. Just some text to demosntrate it... Just
|
||||
some text to demonstrate it... Just some text to demonstrate
|
||||
it...]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"`[l1000 Left margin 1000dots`]`"]]
|
||||
:: [s0; Left margin 1000dots]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"`[i1000 Indent 1000 dots.Just some text to demonstrate
|
||||
it... Just some text to demonstrate it...`]`"]]
|
||||
:: [s0; Indent 1000 dots.Just some text to demonstrate it... Just some
|
||||
text to demonstrate it...]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"`[r1000 Right margin 1000 dots.Just some text to demonstrate
|
||||
it... Just some text to demonstrate it...`]`"]]
|
||||
:: [s0; Right margin 1000 dots.Just some text to demonstrate it... Just
|
||||
some text to demonstrate it...]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"Paragraph`&`[b200 Before 200dots`]`"]]
|
||||
:: [s0; Paragraph&]
|
||||
[s0; Before 200dots]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"`[a200 After 200dots`]`&Paragraph`"]]
|
||||
:: [s0;a200; After 200dots&]
|
||||
[s0; Paragraph]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"`[i200 `[O0 bullet`&`]`[O1 bullet`&`]`[O2 bullet`&`]`[O3
|
||||
bullet`]`]`"]]
|
||||
:: [s0;i200;O0; bullet&]
|
||||
[s0;i200;O1; bullet&]
|
||||
[s0;i200;O2; bullet&]
|
||||
[s0; bullet]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"`[O9i500 text bullet`-`|Just some text to demonstrate
|
||||
it... Just some text to demonstrate it...Just some text to demonstrate
|
||||
it... Just some text to demonstrate it...`]`"]]
|
||||
:: [s0; text bullet-|Just some text to demonstrate it... Just some text
|
||||
to demonstrate it...Just some text to demonstrate it... Just
|
||||
some text to demonstrate it...]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"`[O9i200 `[N1m.; `-`|level 1`&`]`[N1a `-`|level 2`&`]`[N1a
|
||||
`-`|level 2`&`]`[N1 `-`|level 1`&`]`[N1a `-`|level 2`]`]`"]]
|
||||
:: [s0;i200;O9;m`.;N1; -|level 1&]
|
||||
[s0;i200;O9;N1a; -|level 2&]
|
||||
[s0;i200;O9;N1a; -|level 2&]
|
||||
[s0;i200;O9;N1; -|level 1&]
|
||||
[s0; -|level 2]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"`[`~300`~`=.2000`~>`-3000 `-`|Normal tab`-`|Centered
|
||||
tab`-`|Right tab`]`"]]
|
||||
:: [s0; -|Normal tab-|Centered tab-|Right tab]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"`{`{1:2 A1]]
|
||||
:: [s0; [*C@3;1 A2]]
|
||||
:: [s0; [*C@3;1 B1]]
|
||||
:: [s0; [*C@3;1 B2`}`}`"]]
|
||||
:: [ {{3333:6667 [s0; A1]
|
||||
:: [s0; A2]
|
||||
:: [s0; B1]
|
||||
:: [s0; B2]}}]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"`{`{2:1G4g100F5f50 A1`:: A2`:: B1`:: B2`}`}`"]]
|
||||
:: [ {{6666:3334f50;F5g100;G4 [s0; A1]
|
||||
:: [s0; A2]
|
||||
:: [s0; B1]
|
||||
:: [s0; B2]}}]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"`{`{1:2 A1`::l40/60R6`@3 A2`::! B1`:: B2`}`}`"]]
|
||||
:: [ {{3333:6667 [s0; A1]
|
||||
::l40/60@3R6 [s0; A2]
|
||||
::l0/25@2R0 [s0; B1]
|
||||
:: [s0; B2]}}]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"`{`{1:1:1`|2 A1`::`-2 A2`:: A3`:: B1`:: B2`:: B3`}`}`"]]
|
||||
:: [ {{3333:3333:3334|1 [s0; A1]
|
||||
::-1 [s0; A2]
|
||||
:: [s0;%- ]
|
||||
:: [s0;%- ]
|
||||
:: [s0; B2]
|
||||
:: [s0; B3]}}]}}&]
|
||||
[s0; &]
|
||||
[ {{10000 [s0; [*C@3;1 `"`{`{1:2 A1`:: A2`:: B1`:: `{`{1:2 a1`:: a2`:: a1`:: a2`}`}`}`}`"]]
|
||||
:: [ {{3333:6667 [s0; A1]
|
||||
:: [s0; A2]
|
||||
:: [s0; B1]
|
||||
:: [ {{3333:6667 [s0; a1]
|
||||
:: [s0; a2]
|
||||
:: [s0; a1]
|
||||
:: [s0; a2]}}]}}]}}&]
|
||||
[s0; ]
|
||||
|
|
@ -1,18 +1,35 @@
|
|||
#ifndef _SyntaxHighlight_test_h_
|
||||
#define _SyntaxHighlight_test_h_
|
||||
#include <Core/Core.h>
|
||||
#include <vector>
|
||||
|
||||
#include "Common.h"
|
||||
using namespace Upp;
|
||||
using namespace std;
|
||||
|
||||
class XXX {
|
||||
typedef XXX yyy;
|
||||
public:
|
||||
|
||||
private:
|
||||
namespace Upp {
|
||||
template<> void Xmlize(XmlIO xml, vector<int>& data) {
|
||||
if(xml.IsStoring())
|
||||
for(int i = 0; i < (int)data.size(); i++)
|
||||
Xmlize(xml.Add("item"), data[i]);
|
||||
else {
|
||||
data.clear();
|
||||
for(int i = 0; i < xml->GetCount(); i++)
|
||||
if(xml->Node(i).IsTag("item")) {
|
||||
data.push_back(0);
|
||||
Xmlize(xml.At(i), data.back());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct Y {
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
CONSOLE_APP_MAIN
|
||||
{
|
||||
vector<int> x;
|
||||
x.push_back(1);
|
||||
x.push_back(2);
|
||||
x.push_back(3);
|
||||
String s = StoreAsXML(x, "std-test");
|
||||
DUMP(s);
|
||||
vector<int> y;
|
||||
LoadFromXML(y, s);
|
||||
for(int i = 0; i < (int)y.size(); i++)
|
||||
DUMP(y[i]);
|
||||
}
|
||||
|
|
|
|||
8
uppdev/uncompress/uncompress.cpp
Normal file
8
uppdev/uncompress/uncompress.cpp
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#include <Core/Core.h>
|
||||
|
||||
using namespace Upp;
|
||||
|
||||
CONSOLE_APP_MAIN
|
||||
{
|
||||
SaveFile("z:/zaci/5-2007-2.xml", ZDecompress(LoadFile("z:/zaci/5-2007-2.zml")));
|
||||
}
|
||||
9
uppdev/uncompress/uncompress.upp
Normal file
9
uppdev/uncompress/uncompress.upp
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
uses
|
||||
Core;
|
||||
|
||||
file
|
||||
uncompress.cpp;
|
||||
|
||||
mainconfig
|
||||
"" = "";
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue