code: package wprover;
  
  import maths.TPoly;
  
  import java.util.Vector;
  import java.io.DataOutputStream;
  import java.io.IOException;
  import java.io.DataInputStream;
  import java.awt.*;
  import java.awt.event.ActionListener;
  import java.awt.event.ActionEvent;
  
  /**
   * Created by IntelliJ IDEA.
   * User: Ye
   * Date: 2005-8-11
   * Time: 9:34:44
   * To change this template use File | Settings | File Templates.
   */
  
  class UndoStruct {
      static public int INDEX = 0;
  
      final public static int T_UNDO_NODE = 0;
      final public static int T_TO_PROVE_NODE = 1;
      final public static int T_PROVE_NODE = 2;
  
      final public static int T_COMBINED_NODE = 3;
  
      final public static int T_ROOT = 98;
      final public static int T_PLAIN_TEXT = 99;
  
  
      public UndoStruct() {
      }
  
      public UndoStruct(int pc) {
          m_id = INDEX++;
  
          m_type = T_UNDO_NODE;
          paraCounter = pc;
          id = CMisc.id_count;
      }
  
      public UndoStruct(int type, int pc) {
          m_id = INDEX++;
          m_type = type;
          paraCounter = pc;
          id = CMisc.id_count;
      }
  
      int m_id;
  
      int m_type;
      boolean done = false;
      boolean flash = false;
      int action;
      int id = 0;
      int current_id = 0;
      int paraCounter = 1;
      int pnameCounter = 0;
      int plineCounter = 0;
      int pcircleCounter = 0;
  
      String msg = new String(); // information about this step;
  
      int id_b = 0;
      int paraCounter_b = 1;
      int pnameCounter_b = 0;
      int plineCounter_b = 0;
      int pcircleCounter_b = 0;
  
  
      //////////////////////////////////////////////////////
      TPoly polylist = null;
      TPoly pblist = null;
  
      Vector pointlist = new Vector();
      Vector linelist = new Vector();
      Vector circlelist = new Vector();
      Vector anglelist = new Vector();
      Vector constraintlist = new Vector();
      Vector distancelist = new Vector();
      Vector polygonlist = new Vector();
      Vector textlist = new Vector();
      Vector tracklist = new Vector();
      Vector otherlist = new Vector();
      ////////////////////////////
      Vector objectlist = new Vector(); // object related to this node.
      Vector childundolist = new Vector();
  
      ////////////////////////////////////////////// added 2006.7.8.
      Vector dlist = new Vector();
  
      public void adddOjbect(Object obj) {
          dlist.add(obj);
      }
  
      public String toString() {
          if (dlist.size() == 0) {
              return msg;
          } else {
              if (action == drawbase.D_PARELINE) {
                  CLine ln1 = ((CLine) dlist.get(0));
                  CLine ln2 = ((CLine) dlist.get(1));
                  CPoint p = ((CPoint) dlist.get(2));
                  return ln1.getDiscription() + " paral " + ln2.getDiscription() +
                          " passing " + p.getname();
  
              } else if (action == drawbase.D_PERPLINE) {
                  CLine ln1 = ((CLine) dlist.get(0));
                  CLine ln2 = ((CLine) dlist.get(1));
                  CPoint p = ((CPoint) dlist.get(2));
                  return ln1.getDiscription() + " perp " + ln2.getDiscription() +
                          " passing " + p.getname();
              } else {
                  return msg;
              }
          }
      }
  
      public void clear() {
          polylist = pblist = null;
          pointlist.clear();
          linelist.clear();
          circlelist.clear();
          anglelist.clear();
          distancelist.clear();
          constraintlist.clear();
          textlist.clear();
          polygonlist.clear();
          otherlist.clear();
  
      }
  
      public void draw(Graphics2D g2) {
          drawlist(polygonlist, g2);
          drawlist(tracklist, g2);
          drawlist(distancelist, g2);
          drawlist(anglelist, g2);
          drawlist(linelist, g2);
          drawlist(circlelist, g2);
  
          drawlist(pointlist, g2);
  
          drawlist(textlist, g2);
          drawlist(otherlist, g2);
  
      }
  
      public UndoStruct getUndoStructByid(int id) {
          if (this.m_id == id) {
              return this;
          } else {
              for (int i = 0; i < childundolist.size(); i++) {
                  UndoStruct un = (UndoStruct) childundolist.get(i);
                  UndoStruct u1 = un.getUndoStructByid(id);
                  if (u1 != null) {
                      return u1;
                  }
              }
              return null;
          }
      }
  
      public void setInFlashing(boolean inflash) {
          setListInFlashing(objectlist, inflash);
      }
  
      private void setListInFlashing(Vector v, boolean inflash) {
          for (int i = 0; i < v.size(); i++) {
              CClass cc = (CClass) v.get(i);
              cc.setInFlashing(inflash);
  
          }
      }
  
      private void drawlist(Vector v, Graphics2D g2) {
          for (int i = 0; i < v.size(); i++) {
              CClass c = (CClass) v.get(i);
              c.draw(g2);
          }
      }
  
      public void addRelatedObject(CClass cc) {
          if (!objectlist.contains(cc)) {
              objectlist.add(cc);
          }
      }
  
      public boolean isNodeValued() {
          // return pointlist.size() != 0 ;
          if (m_id - id_b != 0) return true;
  
          return pnameCounter - pnameCounter_b != 0
                  || plineCounter_b - plineCounter != 0
                  || plineCounter_b - plineCounter != 0;
      }
  
  
      public void merge(UndoStruct undo1, UndoStruct undo2) {
  
          action = -1; // combined.
          msg = "cb";
  
          id = undo1.id;
          current_id = undo1.current_id;
          paraCounter = undo1.paraCounter;
          pnameCounter = undo1.pnameCounter;
          plineCounter = undo1.plineCounter;
          pcircleCounter = undo1.pcircleCounter;
  
          id_b = undo2.id_b;
          paraCounter_b = undo2.paraCounter_b;
          pnameCounter_b = undo2.pnameCounter_b;
          plineCounter_b = undo2.plineCounter_b;
          pcircleCounter_b = undo2.pcircleCounter_b;
  
      }
  
      public void addchild(UndoStruct u) {
          if (!childundolist.contains(u)) {
              childundolist.add(u);
          }
      }
  
      public void addObjectRelatedList(Vector v) {
          for (int i = 0; i < v.size(); i++) {
              Object obj = v.get(i);
              if (!objectlist.contains(obj)) {
                  objectlist.add(obj);
              }
          }
      }
  
      public Vector getAllObjects(drawProcess dp) {
          Vector v = new Vector();
  
          if (this.m_type == T_UNDO_NODE) {
              dp.selectUndoObjectFromList(v, dp.pointlist, id, id_b);
              dp.selectUndoObjectFromList(v, dp.linelist, id, id_b);
              dp.selectUndoObjectFromList(v, dp.circlelist, id, id_b);
              dp.selectUndoObjectFromList(v, dp.anglelist, id, id_b);
              dp.selectUndoObjectFromList(v, dp.distancelist, id, id_b);
              dp.selectUndoObjectFromList(v, dp.polygonlist, id, id_b);
              dp.selectUndoObjectFromList(v, dp.textlist, id, id_b);
              dp.selectUndoObjectFromList(v, dp.tracelist, id, id_b);
              dp.selectUndoObjectFromList(v, dp.otherlist, id, id_b);
  
          } else if (this.m_type == UndoStruct.T_COMBINED_NODE) {
              for (int i = 0; i < childundolist.size(); i++) {
                  UndoStruct un = (UndoStruct) childundolist.get(i);
                  Vector vt = un.getAllObjects(dp);
                  v.addAll(vt);
              }
          } else if (this.m_type == UndoStruct.T_PROVE_NODE) {
              for (int i = 0; i < childundolist.size(); i++) {
                  UndoStruct un = (UndoStruct) childundolist.get(i);
                  Vector vt = un.getAllObjects(dp);
                  v.addAll(vt);
              }
          }
  
          v.addAll(objectlist);
          return v;
      }
  
      public void SaveList(DataOutputStream out, Vector v) throws IOException {
          int n = v.size();
          if (n > 999) {
              int k = 0;
          }
          out.writeInt(n);
          for (int i = 0; i < v.size(); i++) {
              CClass cc = (CClass) v.get(i);
              out.writeInt(cc.m_id);
          }
      }
  
      public Vector ReadList(DataInputStream in, drawProcess dp) throws
              IOException {
          int size = in.readInt();
          Vector v = new Vector();
  
          for (int i = 0; i < size; i++) {
              int id = in.readInt();
              Object obj = dp.getOjbectById(id);
              if (obj != null) {
                  v.add(obj);
              }
          }
          return v;
      }
  
  
      public void Save(DataOutputStream out) throws IOException {
  
          out.writeInt(m_id);
          out.writeInt(m_type);
          out.writeBoolean(done);
          out.writeBoolean(flash);
          out.writeInt(action);
  
          out.writeInt(id);
          out.writeInt(current_id);
          out.writeInt(paraCounter);
          out.writeInt(pnameCounter);
          out.writeInt(plineCounter);
          out.writeInt(pcircleCounter);
  
          // for 0.11
          int n = 0;
          if (msg != null) {
              byte[] b = msg.getBytes();
              n = b.length;
              out.writeInt(n);
              if (n > 0)
                  out.write(b);
          } else
              out.writeInt(n);
  
  //        if (msg != null && n > 0) {
  //            byte[] b = msg.getBytes();
  //            out.write(b);
  //        }
  
          out.writeInt(id_b);
          out.writeInt(paraCounter_b);
          out.writeInt(pnameCounter_b);
          out.writeInt(plineCounter_b);
          out.writeInt(pcircleCounter_b);
  
          SaveList(out, objectlist);
  
          out.writeInt(childundolist.size());
  
          if (childundolist.size() != 0) {
              for (int i = 0; i < childundolist.size(); i++) {
                  UndoStruct u = (UndoStruct) childundolist.get(i);
                  u.Save(out);
              }
  
          }
      }
  
      public void Load(DataInputStream in, drawProcess dp) throws IOException {
          if (CMisc.version_load_now >= 0.019) {
              m_id = in.readInt();
  
          } else {
              m_id = CMisc.id_count++;
          }
  
          if (CMisc.version_load_now >= 0.015) {
              m_type = in.readInt();
          }
          if (CMisc.version_load_now > 0.01) {
              this.done = in.readBoolean();
              this.flash = in.readBoolean();
              action = in.readInt();
          }
  
          if (CMisc.version_load_now < 0.01) {
              int size = in.readInt();
              byte[] str = new byte[size];
              in.read(str, 0, size);
          }
          id = in.readInt();
          current_id = in.readInt();
          paraCounter = in.readInt();
          pnameCounter = in.readInt();
          plineCounter = in.readInt();
          pcircleCounter = in.readInt();
  
          // for 0.01
          if (CMisc.version_load_now > 0.010) {
              int size = in.readInt();
              if (size > 0) {
                  byte[] str = new byte[size];
                  in.read(str, 0, str.length);
                  msg = new String(str);
              }
          }
  
          id_b = in.readInt();
          paraCounter_b = in.readInt();
          pnameCounter_b = in.readInt();
          plineCounter_b = in.readInt();
          pcircleCounter_b = in.readInt();
  
          if (CMisc.version_load_now >= 0.016) {
              objectlist.addAll(this.ReadList(in, dp));
          }
  
          if (CMisc.version_load_now >= 0.012) {
              int size = in.readInt();
              for (int i = 0; i < size; i++) {
                  UndoStruct u = new UndoStruct(-1, -1);
                  u.Load(in, dp);
                  childundolist.add(u);
              }
              if (m_type == T_UNDO_NODE && childundolist.size() > 0) {
                  m_type = T_COMBINED_NODE;
              }
          }
      }
  }
  