+ // 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 parent is a phantom group, so it was a
+ // delimited argument of the MACRO and the corrisponding
+ // delimeter is inserted. So, the action of deleting means
+ // removing this delimeter
+ cursor.remove();
+ parent.remove();
+ uncle.append(cursor);
+ frame.pos -= 2;
+ }
+ 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 // the grand futher is math
+ {
+ // nothing to do...i think
+ assert(frames.empty());
+ }