Discussion:
clarification of structure of cursor
Tommaso Cucinotta
2014-05-11 00:05:07 UTC
Permalink
Hi Tommaso,
I had sent you an email , you might have missed it!
Hi,

actually, I can't see your message below in my inbox .. strange, anyway,
if you don't get an answer from me within 24h, feel free to send it again.
---------- Forwarded message ----------
Date: Thu, May 8, 2014 at 11:56 PM
Subject: clarification of structure of cursor
Did you check if my patch works?
the patch applies almost seamlessly -- I needed to add an end of line at the end, otherwise
"patch" was giving me an error.
first of all whats the difference between cursorslice and dociterator?
a LyX buffer / document is a nested structure of a Text, made up of multiple Paragraph,
made up of a sequence of characters and insets. A DocIterator is a full absolute pointer
within this structure; it is made up of a stack of relative pointers, called CursorSlice.

Let me show it graphically:

Text {
Par1 {
"The lazy fox jumps on some maths: "
InsetMathWhatever {
some stuff...
}
}
Par2 {
"Second paragraph etc..."
}
}

Note that the actual text is stored in Paragraph::text_[] for text stuff, and within the various
inset classes for other insets. Whenever in a paragraph we add an inset (math stuff, floating
environment, image, table, etc.), in that position we have a special marker character, within
text_[] (in class Paragraph), which, instead of containing a character, contains the META_INSET
special value (see Paragraph::isInset()). So, if, when scanning text_[], we see META_INSET, it
means that in that position there's an inset. The actual Inset subclass can be retrieved using
Paragraph::getInset(), in which you see that insets are stored in Paragraph::insetlist_.
An Inset can also contain again a Text (for example a cell in a table), made up of paragraphs
again, etc..., recursively.

A CursorSlice provides a position within a specific inset, in terms of:
-) paragraph within the text: "pit"
-) position, namely which character within a paragraph: "pos"
-) index, namely what cell, in a multi-cell type of Inset (e.g., table or mathematics)

Just look at the private members of CursorSlice in CursorSlice.h:

/// pointer to 'owning' inset. This is some kind of cache.
Inset * inset_;
idx_type idx_;
/// paragraph in this cell (used by texted)
pit_type pit_;
/// position in this cell
pos_type pos_;

(see more extended comments in code)

A DocIterator, as said, is a stack of these CursorSlices:
when the cursor is within a nested inset, following the slices
allows you to go from the outer Text ("bottom()"most slice) to
the innsermost Inset ("top()"most slice)
and paragraph class and specific character where the cursor
is positioned.

Finally, a Cursor is the specific DocIterator representing your
on-screen cursor. So, you can create as many DocIterator as
you like, typically temporary, for editing purposes, in the code.
However, only a Cursor instance per BufferView / GuiWorkArea
should exist, which represents the on-screen cursor as moved
by the user.
---------------------
is it possible to find difference between two cursors in every scenario, may it be simple text or mathematical formula ?
Not sure what you mean by difference, but you should check:
-) are the 2 cursors in the same inset() ? Use dit1.top() == dit2.top()
-) are the 2 cursors in the same inset AND paragraph ?
dit1.top() == dit2.top() && dit1.pit() == dit2.pit()
etc...

You can see the ::operator<() to just check that a DocIterator is before another, but you won't know exactly whether it's before in the same innermost inset and paragraph, or it's in an outer inset, preceeding the point of insertion of nested stuff, where the 2nd iterator is, etc...
---------------------
If i do manage to find the difference say manually(by subtracting pit, idx, pos) and if I add the difference to the cursor will I get the original cursor back..
Cursor 1 is in front of Cursor 2
if Cursor 1 - Cursor 2 = +X
then is Cursor 1 = Cursor 2 +X ? in every case (considering Insets as well)?
As from above, cursors can be:
-) in same inset, then their difference may be expressed as paragraph, text and idx difference (which in turn becomes row() diff and col() diff for matrix-like grids and maths)
-) in different inset, then it's more complex; you may need to find the common ancestor in the nesting hierarchy, something like:

int i1 = 0;
int i2 = 0;
while (docit1[i1] ->inset() == docit2[i2]->inset()){
++i1;
++i2;
}

but be sure to scan the 2 docit from bottom() (ie, outer) towards top() (ie, inner).

Now, you need to think of 3 cases:

a) cursors in same inset
if I add a character, and other cursor in same paragraph and after me, then its position needs to be shifted forward (++pos)
if I add a newline, and other cursor in paragraph following mine, then other cursor's paragraph needs to be shifted forward (++pit)
etc...
b) cursors in different insets, I think the only 2 cases are when a cursor is editing an inset which is an ancestor of another cursor,
namely I'm editing a paragraph text containing also maths, and another cursor is within those maths; if I insert stuff before the outer
math inset, then the cursorslice of that other cursor will need to be shifted (in pos or pit, see above).
--------------------
I read in Cursor.h
"
a DocIterator contains a vector of CursorSlices that describes the nesting of insets up to the
point of interest.
"
could you elaborate?
guess it's done above.
____________
What is an inset basically?
whenever we don't add a simple character, but rather we add something complex in a paragraph while editing, then we're adding an Inset data structure containing all the details (number of rows and cols for a table, on-disk file position for an image, mathematic stuff, ...)
---------------------
BufferView provides a function
bool moveToPosition(pit_type bottom_pit, pos_type bottom_pos,
int top_id, pos_type top_pos)
If i store difference in changed cursor position (after dispatch) and use this diff for updating each remote cursor location, will I be able to use this function to to set my cursor position according to the revision it is in?
Not sure when this specific one is used, however a BufferView Cursor position can be set to whatever by calling Cursor::setCursor().

So, code can be alike:

DocIterator dit = cursor;
if (whatever)
dit.pos()++;
elseif (whatever else)
dit.pit()++;
else
//
cursor.setCursor(dit);

Play a bit with the above, pls ask whatever is still unclear.

Start from simple case: one cursor adds char before another cursor on same paragraph; the pos() of the other cursor needs to be increased accordingly.

T.

Loading...