- assert(parent);
- if (parent.isG())
- {
- TNode prev = cursor.prev();
- if (prev)
- {
- // i try to delete the preceding element
- gdelete_prev();
-
- if ((parent.first() == cursor) && parent.isG() && parent.hasId())
- rgreplace_futher();
-
- }
- else // no previous node is present
- {
- // if here, we are in a gruop whose only child is the cursor.
-
- if (!parent.hasId())
- {
- // the parent is a phantom group
- assert(parent.parent());
- if (!parent.parent().is("math"))
- {
- TNode gfuther = parent.parent();
-
- // if the grand futher is a group with Id, it should be removed,
- // but i don't know if it will never occur...
- if (gfuther.isG() && gfuther.hasId())
- {
- cursor.remove();
- parent.replace(cursor);
-
- // re-start the process
- do_gdelete();
- }
- else if (gfuther.isC())
- {
- // the grand futher is a control element: since the parent is a phantom group,
- // the TML tree should be in a inconsistent state (once removed the parent).
-
- // being here means that there is a frame in the stack
- assert(!frames.empty());
- cout << "do_gdelete: i have to remove a phantom group whuch is a child of a MACRO" << endl;
- Frame& frame = frames.top();
- if (frame.entry.leftOpen && frame.entry.rightOpen)
- {
- // in this case, the cursor is in the second and last child
- // of the MACRO. We can assert that the grand futher has two
- // children. which are both phantom group
- cout << "do_gdelete: the MACRO is leftOpen and rigthOpen" << endl;
- assert(gfuther.size() == 2);
- assert((gfuther.last() == parent) && (gfuther.first().isG() && !gfuther.first().hasId()));
- assert(frame.pos == 0);
-
- TNode ggfuther = gfuther.parent();
- assert(ggfuther);
- cursor.remove();
- parent.remove();
- // i have to replace the gfuther with the elements of its first child
- gfuther.replace(gfuther.first().first(), TNode());
- cout << "do_gdelete: i have removed the control element, and replaced it with its first child" << endl;
- ggfuther.append(cursor);
- cout << "do_gdelete: cursor appended to the grand grand futher" << endl;
-
- // now we have the situation preceding the insertion of the MACRO leftOpen and rightOpen
- // this MACRO no longer exists.
- frames.pop();
- }
- else if (frame.entry.rightOpen)
- {
- // the user has inserted a MACRO rightOpen. Since the cursor is the
- // only child of the MACRO, the user want to remove it.
- // We can assert that cursor's parent is the only child of the MACRO
- cout << "do_gdelete: the MACRO is rightOpen only" << endl;
- assert(gfuther.size() == 1);
- assert(frame.pos == 0); // i think this assert has no sense
-
- cursor.remove();
- parent.remove();
- gfuther.replace(cursor);
-
- // now we have the situation preceding the MACRO rightOpen, so i have to pop the frame
- frames.pop();
- }
- else if (frame.entry.leftOpen)
- {
- // it' s an unpredicted situation
- cout << "it's a bad situation, maybe handlable, but unpredicted" << endl;
- }
- else if (!frame.entry.pattern.empty())
- {
- // the MACRO (the cursor's grand futher) accepts arguments.
- // we have to control if the cursor's uncle does exist.
-
- if (parent.prev())
- {
- // in this case, we can assert that frame in the stack has
- // pos greater than 0
- assert(frame.pos > 0);
-
- // cursor's uncle does exist. we have to control
- // its nature (is it a phantom group?)
- TNode uncle = parent.prev();
- if (uncle.isG() && !uncle.hasId())
- {
- // the cursor's uncle is a phantom group, so it was a
- // delimited argument of the MACRO and the corrisponding sequence of
- // delimeters is inserted. So, the action of deleting means
- // removing this sequence
- assert(frame.pos > 1);
- unsigned sequence_length = frame.pos - frame.entry.previousParam(frame.pos) - 1;
- assert(frame.entry.previousParam(frame.pos) != frame.entry.pattern.size());
- assert(sequence_length);
- // sequence_length is the length of the delimiters sequence which separates
- // the current parameter and the previous parameter
- frame.pos = frame.pos - sequence_length - 1;
- cursor.remove();
- parent.remove();
- uncle.append(cursor);
- }
- else
- {
- // the uncle was a NOT delimited argument. So i try to
- // remove it
- cursor.remove();
- parent.replace(cursor);
-
- parent = cursor.parent(); // i update the parent (it should be the MACRO)
- assert(parent.isC());
-
- gdelete_prev();
-
- }
- }
- else
- {
- // cursor's parent is the only child of the MACRO, which accepts arguments
- // i can assert that frame.pos == 0.
- // In this case i can replace the MACRO with the cursor
- assert(frame.pos == 0);
-
- cursor.remove();
- parent.remove();
- gfuther.replace(cursor);
-
- frames.pop();
- }
-
- }
- }
- else if (gfuther.is("cell"))
- {
- // being here means that there is a frame in the stack
- // associated to the "table"
- cout << "do_gdelete: i have to delete a cell" << endl;
- assert(!frames.empty());
- assert(frames.top().pos == 1);
- assert(frames.top().entry.table == 1);
- // a cell MUST be child of row element, which in turn MUST be child of an element
- // havin attribute table.
- assert(gfuther.parent() && gfuther.parent().is("row") && gfuther.parent().parent());
- TNode row = gfuther.parent();
-
- // in this case the cell has no element, so the user wants to delete this cell.
- TNode prev_cell = gfuther.prev();
-
- cursor.remove();
- parent.remove();
- gfuther.remove();
- // now the cell no longer exists
-
- if (!prev_cell)
- {
- // i this case, the cell is the only cell in the row.
- // So, i assume that the user wants to delete the entire row.
- TNode table = row.parent();
- TNode prev_row = row.prev();
- row.remove();
- if (!prev_row)
- {
- // the row was the only child of the table.
- // I think have to delete the entire table
- assert(table.parent());
- TNode parent_table = table.parent();
- table.remove();
- frames.pop();
- parent_table.append(cursor);
- }
- else
- {
- // there are other rows (one at least)
- assert(prev_row.is("row"));
- assert(prev_row.last());
- TNode last_cell = prev_row.last();
- assert(last_cell.is("cell"));
- assert(last_cell.size() == 1);
- assert(last_cell.first().isG() && !last_cell.first().hasId());
- last_cell.first().append(cursor);
- }
- }
- else
- {
- // being here means that there is a previous cell,
- // so we append the cursor to group.
- assert(prev_cell.size() == 1);
- assert(prev_cell.first().isG() && !prev_cell.first().hasId());
- prev_cell.first().append(cursor);
- }
- }
- }
- else // the grand futher is math
- {
- // nothing to do...i think
- assert(frames.empty());
- }
- }
- else
- {
- // the parent is a group with id and has no elements other than cursor
- // so we replace it with the cursor.
- rgreplace_futher();