Hi,
While hacking away on some odf change tracking updates [1] I added a
few methods to the core piecetable and pf_frag tree in my git repo. I
was doing some things over and over and they seemed good candidates for
abstraction, but there is also the possibility that I just missed the
current good way to do the same thing :/ I might have missed one or two
changes here, the patch will tell all ;)
I added
pf_Frag_Strux*
pt_PieceTable::_getBlockFromPosition(PT_DocPosition pos) const;
Because using _getStruxOfTypeFromPosition() if pos == a PTX_Block then
you get the previous block instead of the block at pos. Using the new
_getBlockFromPosition() will return the PTX_Block right at pos if one
exists.
I added the below method before the above one, it is a simpler
implementation now. Basically if startpos and endpos are in the same
PTX_Block then a pointer to its Frag_Strux is returned or NULL
otherwise. So it can be used as a bool test to see if these positions
share a block, and also you can use the return value to access that same
block if desired.
pf_Frag_Strux*
pt_PieceTable::inSameBlock(
PT_DocPosition startpos,
PT_DocPosition endpos );
The below will get the first strux that marks the end of the block
containing currentpos or null. The end of block strux has to be
positioned before endpos or null is returned. Note that if currentpos is
itself a block this method will move over that PTX_Block before
searching for the end of block to allow simpler iteration of the
document. endpos could be optional, but it is handy for selections which
is the context I created it for. ie, you want to get the end of block
only if it is not beyond the user's active text selection.
pf_Frag*
pt_PieceTable::getEndOfBlock(
PT_DocPosition currentpos,
PT_DocPosition endpos );
I extended _findLastStruxOfType to take a stopCondition as follows. Note
that the old method is still there too and just delegates to this new
one. IIRC the return value used to be pf_Frag, but as we are explicitly
finding a frag_strux I changed that to the later to give the best type
information to the caller. The stopConditions is an array terminated by
Dummy. The method comment is;
/**
* MIQ11: Extends the old _findLastStruxOfType adding a stopCondition
* for failure and returning a Strux* directly in the case of success.
* This is like a findBackwards() from a fragment.
*
* stopConditions must be terminated with a PTX_StruxDummy entry like:
* PTStruxType stopCondition[] = { PTX_SectionTable, PTX_StruxDummy };
*
* Find a fragment of strux type pst looking backwards from pfStart.
* If a strux fragment matching the stopCondition is found first then
* the function stops and returns 0. If no fragment with pst is found
* then 0 is returned.
*
* MAYBE: extend this again to take yes() and no() functors so a
* function can call _findLastStruxOfType() and decide what is ok
* and what is not using those.
* boost::lambda would be handy to simplify the functors?
*/
pf_Frag_Strux* _findLastStruxOfType(
pf_Frag * pfStart,
PTStruxType pst,
PTStruxType* stopConditions,
bool bSkipEmbededSections );
------------
In pf_frag I added the following:
The getNextStrux() is like getNext() but will skip over fragments until
a strux of this type is found. Return 0 otherwise
pf_Frag_Strux* getNextStrux(PTStruxType t) const;
In the below, if this fragment is a strux, and it is of the type passed
in then return this fragment downcast to the frag_strux type. It seems
to be quite common to test for the strux and then subtype, and then
static_cast<> down to the subtype.
pf_Frag_Strux* tryDownCastStrux(PTStruxType t) const;
It might also be an idea to add templates for downcasts like
template <class Frag>
Frag* tryDownCastStrux() const;
To be used like
pf_Frag_Text* pft = pf->tryDownCastStrux<pf_Frag_Text>();
Of course the template parameter can be omitted if the pft is passed as
an argument instead of as the return value, but then you have to declare
the pft before the call. This way the whole thing can be put into a line
like the following. But if you pass the class or strux enum in this
process doesn't seem to make much difference.
if( pf_Frag_Text* pft = pf->tryDownCastStrux<pf_Frag_Text>() )
{
// use pft
}
Mainly for debugging I added the following to pf_frag_text. This avoids
using getBufIndex() and playing with char pointers directly, but does
require a string copy for the result. Not a huge problem in #if DEBUG
code though.
std::string toString() const;
------------
I also have some additions to pp_revision
To merge another RevisionAttr
void mergeAll( const PP_RevisionAttr& ra );
To add a attr=value at a given revisionid and type
void mergeAttr( UT_uint32 iId, PP_RevisionType t,
const gchar* pzName, const gchar* pzValue );
The same but do not replace an existing value
void mergeAttrIfNotAlreadyThere(
UT_uint32 iId, PP_RevisionType t,
const gchar* pzName, const gchar* pzValue );
Get the lowest deletion revision for content that might be deleted more
than once.
const PP_Revision* getLowestDeletionRevision() const;
I might also add a more STL like interface for PP_Revision to the
PP_RevisionAttr class.
Something like:
iterator begin();
iterator end();
iterator find( PP_Revision* );
iterator find( UT_uint32 iId,
PP_RevisionType t = PP_REVISION_NONE );
[1]
http://lists.oasis-open.org/archives/office-collab/201106/msg00024.html
This archive was generated by hypermail 2.1.8 : Fri Jul 01 2011 - 02:16:44 CEST