home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / diverses / leda / prog / graphics / ged.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-15  |  39.3 KB  |  1,767 lines

  1. #include <LEDA/graph.h>
  2. #include <LEDA/d_array.h>
  3. #include <LEDA/plane.h>
  4. #include <LEDA/window.h>
  5.  
  6. #include <math.h>
  7.  
  8. declare2(GRAPH,point,int)
  9. declare(node_array,node)
  10. declare2(d_array,point,node)
  11. declare2(d_array,node,int)
  12.  
  13. void GED(string);
  14.  
  15. /*---------------------- globale Variablen --------------------------*/
  16.  
  17. string   G_filename;
  18.  
  19. window  W;
  20.  
  21. double   W_WIDTH = 100;                      // extension of gwindow W
  22.  
  23. GRAPH(point,int) G;                          // graph G
  24.  
  25. drawing_mode  W_save_mode;
  26.  
  27.  
  28. int    G_max_node_width = 15;         
  29.  
  30. double G_XMAX;
  31. double G_YMAX;
  32. double G_XMIN;
  33. double G_YMIN;
  34.  
  35. int G_node_count;                            // counter of nodes,edges,faces
  36. int G_edge_count;          
  37.  
  38. d_array(node,int)    G_node_name;            // node -> name
  39.  
  40. list(point)          error_nodes;             // error output
  41. list(segment)        error_edges;
  42.  
  43. bool                 output_enable = true;   // output-permission
  44. bool                 still_saved   = true;   // save-control
  45.  
  46.  
  47. /*------------------------------ error --------------------------------*/
  48.  
  49. void error(string text)
  50. {
  51.   if (output_enable)  cout << "\n(error) " << text << "\n";
  52. }
  53.  
  54. /*------------------------------ warn --------------------------------*/
  55.  
  56. void warn(string text)
  57. {
  58.   cout << "(warning) " << text << "\n";
  59. }
  60.  
  61. /*------------------------ draw_node_cursor ---------------------------*/
  62.  
  63. static void draw_node_cursor(double x, double y)
  64. {
  65.   W.draw_node(x,y);
  66. }
  67.  
  68. /*---------------------------- draw_node ------------------------------*/
  69.  
  70. void draw_node(node v,color c=black)
  71. {
  72.    int width = W.get_node_width();
  73.  
  74.    if (width >= 7 ) W.draw_text_node(G[v],form("%d",G_node_name[v]),c);
  75.    else             W.draw_filled_node(G[v],c);
  76. }
  77.  
  78. /*----------------------------- draw_edge -----------------------------*/
  79.  
  80. void draw_edge(edge e,color c=black)
  81. {
  82.   drawing_mode old_mode =  W.set_mode(src_mode);       // src_mode for edge-painting
  83.  
  84.   W.draw_edge_arrow(G[source(e)],G[target(e)],c);
  85.  
  86.   W.set_mode(old_mode);
  87.  
  88. } // draw_edge
  89.  
  90. /*--------------------------- redraw_graph ----------------------------*/
  91.  
  92. void redraw_graph(string clear_permission)
  93. {
  94.   node v;
  95.   edge e;
  96.  
  97.   if (clear_permission == "yes") W.clear();
  98.  
  99.   forall_nodes(v,G) draw_node(v);
  100.  
  101.   forall_edges(e,G) draw_edge(e);
  102.                  
  103. } // redraw_graph
  104.  
  105. void redraw_graph() { redraw_graph("yes"); }
  106.  
  107. /*------------------------ new_error_node --------------------------*/
  108.  
  109. void new_error_node(point p)
  110. {
  111.   if (error_nodes.search(p)==nil) error_nodes.append(p);
  112.  
  113. } // new_error_node
  114.  
  115. /*------------------------ new_error_edge --------------------------*/
  116.  
  117. void new_error_edge(segment s)
  118. {
  119.   if (error_edges.search(s)==nil) error_edges.append(s);
  120.  
  121. } // new_error_edge
  122.  
  123. /*----------------------- overlap_message -------------------------*/
  124.  
  125. void overlap_message(bool draw_permission = true)
  126. {
  127.   point   p;
  128.   segment seg;
  129.  
  130.   line_style old_style     = W.set_line_style(dotted);
  131.   drawing_mode  old_mode      = W.set_mode(src_mode);
  132.  
  133.   forall(seg,error_edges) W.draw_edge_arrow(seg.start(),seg.end());
  134.   forall(p,error_nodes)   W.draw_filled_node(p);
  135.  
  136.   W.message("         node/edge dropped on existing object");
  137.   W.message("");
  138.   W.message("                  < press button >");
  139.   W.read_mouse();
  140.   W.del_message();
  141.  
  142.   W.set_line_style(old_style);       // old-values
  143.   W.set_mode(old_mode);
  144.  
  145.   error_edges.clear();
  146.   error_nodes.clear();
  147.  
  148.   if (draw_permission) redraw_graph();
  149.  
  150. } // overlap_message
  151.  
  152. /*---------------------------- cmp ---------------------------------*/
  153.  
  154. int cmp(point& x,point& p, point& q)
  155.   segment s1(x,p);                   // compare relativ position of s1 & s2
  156.   segment s2(x,q);
  157.  
  158.   return compare(s1.angle(), s2.angle()); 
  159.  
  160. } // cmp
  161.  
  162. /*---------------------- get_node_at_point ---------------------------*/
  163.  
  164. node get_node_at_point(point pv)
  165. {
  166.   node w,n;         
  167.   double dist = W.get_node_width() / W.scale();
  168.  
  169.   forall_nodes(w,G)
  170.   {
  171.     point pw = G[w];
  172.  
  173.     if (pv.distance(pw) < dist)
  174.     {
  175.       n = w;
  176.       G.reset();
  177.       return n;                        // node n on clicked position pv
  178.     }
  179.   }
  180.  
  181.   return nil;                          // no node clicked
  182.  
  183. } // get_node_at_point
  184.  
  185. /*------------------------ get_max_coord ----------------------------*/
  186.  
  187. void get_max_coord()
  188. {
  189.   node n = G.choose_node();
  190.  
  191.   if (n == nil)
  192.   {
  193.     G_XMAX = W.xmin(); G_YMAX = W.ymin();        // reset max.coord. of
  194.     G_XMIN = W.xmax(); G_YMIN = W.ymax();        // empty graph G
  195.   }
  196.   else
  197.   {
  198.     point p = G[n];
  199.  
  200.     G_XMIN = G_XMAX = p.xcoord();           // set max.coord. of graph G
  201.     G_YMIN = G_YMAX = p.ycoord();           // to existing node
  202.   }
  203.  
  204.   forall_nodes(n,G)
  205.   {
  206.      real x = G[n].xcoord();
  207.      real y = G[n].ycoord();
  208.  
  209.      if ( x < G_XMIN ) G_XMIN = x;
  210.      if ( x > G_XMAX ) G_XMAX = x;
  211.      if ( y < G_YMIN ) G_YMIN = y;
  212.      if ( y > G_YMAX ) G_YMAX = y;
  213.   }
  214.  
  215. } // get_max_coord
  216.  
  217. /*------------------------ graph_extension ----------------------------*/
  218.  
  219. void graph_extension(point p)
  220. {
  221.    real x = p.xcoord();            // if node is added, max.coord can change
  222.    real y = p.ycoord();
  223.  
  224.    if ( x < G_XMIN ) G_XMIN = x;
  225.    if ( x > G_XMAX ) G_XMAX = x;
  226.    if ( y < G_YMIN ) G_YMIN = y;
  227.    if ( y > G_YMAX ) G_YMAX = y;
  228.  
  229. } // graph_extension
  230.  
  231. /*-------------------------- init_window --------------------------*/
  232.  
  233. void init_window()
  234. {
  235.   int n_width = G_max_node_width - (2 * int( W_WIDTH / 100));   // new node_width
  236.   int o_width = W.get_node_width();
  237.  
  238.   W.init(0,W_WIDTH,0);
  239.  
  240.   if (o_width >= 7)                   // '>7' = nodes with numbers 
  241.   { 
  242.     if (n_width<o_width) W.set_node_width(n_width); 
  243.     else                 W.set_node_width(o_width); 
  244.  
  245.     W.set_line_width(2);
  246.   }
  247.  
  248.   W.set_mode(xor_mode);
  249.  
  250. } // init_window
  251.  
  252. /*--------------------------- init_graph ----------------------------*/
  253.  
  254. void init_graph()
  255. {
  256.   node v;
  257.   edge e;
  258.  
  259.   G_node_count = 0;
  260.   G_edge_count = 0;
  261.  
  262.   forall_nodes(v,G)  G_node_name[v] = G_node_count++;   // rename nodes
  263.  
  264.   forall_edges(e,G)  G[e] = G_edge_count++;             // rename edges
  265.                  
  266.   get_max_coord();       // test max.coord of graph G
  267.  
  268. } // init_graph
  269.  
  270. /*--------------------------- reset_graph ----------------------------*/
  271.  
  272. void reset_graph()
  273. {
  274.   G.clear();
  275.  
  276.   G_node_count = 0;
  277.   G_edge_count = 0;
  278.  
  279.   G_XMAX = W.xmin();     // if now a node is added to the empty graph
  280.   G_YMAX = W.ymin();     // it's coord. will become the max.coord. of G,
  281.   G_XMIN = W.xmax();     // because the input must be on window W
  282.   G_YMIN = W.ymax();
  283.  
  284. } // reset_graph
  285.  
  286. /*------------------------ scroll_window ------------------------------*/
  287.  
  288. void scroll_window(real xpos,real ypos,int margin=1)
  289. {
  290.   real x,y;
  291.   real xdist,ydist;
  292.   node n;
  293.  
  294.   if (margin == 1)        // scroll to margin
  295.   {
  296.     xdist = xpos;    
  297.     ydist = ypos;   
  298.   }
  299.   else                   // scroll user-define Direction
  300.   {
  301.     W.draw_filled_node(xpos,ypos);
  302.  
  303.     W.message("                     user - scroll");
  304.     W.read_mouse_seg(xpos,ypos,x,y);
  305.  
  306.     xdist = xpos - x;  
  307.     ydist = ypos - y;   
  308.   }
  309.  
  310.   G_XMIN += xdist; G_XMAX += xdist;     // change max.coord. of graph G
  311.   G_YMIN += ydist; G_YMAX += ydist;
  312.  
  313.   vector v(xdist,ydist);
  314.  
  315.   forall_nodes(n,G)                     // change coord. of nodes
  316.   {
  317.     G[n] = G[n] + v;
  318.   }
  319.  
  320.   if (margin == 0) redraw_graph();     // user scroll
  321.  
  322. } //scroll_window 
  323.  
  324. /*------------------------ center_graph ------------------------------*/
  325.  
  326. void center_graph()
  327. {
  328.   scroll_window((W.xmax() - W.xmin() - G_XMAX - G_XMIN) / 2.0,(W.ymax() - W.ymin() - G_YMAX - G_YMIN) / 2.0);
  329.  
  330. } // center_graph
  331.  
  332. /*------------------------ scroll_menu ------------------------------*/
  333.  
  334. void scroll_menu()
  335. {
  336.   int    node_width  = W.get_node_width();
  337.   double margin_dist = (node_width / W.scale()) +1;
  338.   double xpos,ypos;
  339.  
  340.   string header = form(" Scroll-Menu :      scroll to which margin ??");
  341.  
  342.   panel P(header);
  343.  
  344.   P.button(" up-left  "); 
  345.   P.button("    up    "); 
  346.   P.button(" up-right ");
  347.   P.new_button_line();
  348.  
  349.   P.button("   left   "); 
  350.   P.button("  center  "); 
  351.   P.button("   right  ");
  352.   P.new_button_line();
  353.  
  354.   P.button("down-left "); 
  355.   P.button("   down   "); 
  356.   P.button("down-right");
  357.   P.new_button_line();
  358.  
  359.   int scr_option = P.open();
  360.  
  361.   switch(scr_option)
  362.   {
  363.     case 0 : { xpos = W.xmin() - G_XMIN + margin_dist;               // up-left
  364.                ypos = W.ymax() - G_YMAX - margin_dist;
  365.                break;
  366.              }
  367.  
  368.  
  369.     case 1 : { xpos = 0;                                             // upper
  370.                ypos = W.ymax() - G_YMAX - margin_dist;
  371.                break;
  372.              }
  373.  
  374.  
  375.     case 2 : { xpos = W.xmax() - G_XMAX - margin_dist;               // up-right
  376.                ypos = W.ymax() - G_YMAX - margin_dist;
  377.                break;
  378.              }
  379.  
  380.  
  381.     case 3 : { xpos = W.xmin() - G_XMIN + margin_dist;               // left
  382.                ypos = 0;
  383.                break;
  384.              }
  385.  
  386.  
  387.     case 4 : { xpos = (W.xmax() - W.xmin() - G_XMAX - G_XMIN) / 2.0; // center
  388.                ypos = (W.ymax() - W.ymin() - G_YMAX - G_YMIN) / 2.0;
  389.                break;
  390.              }
  391.  
  392.  
  393.     case 5 : { xpos = W.xmax() - G_XMAX - margin_dist;               // right
  394.                ypos = 0;
  395.                break;
  396.              }
  397.  
  398.  
  399.     case 6 : { xpos = W.xmin() - G_XMIN + margin_dist;              // down-left
  400.                ypos = W.ymin() - G_YMIN + margin_dist;
  401.                break;
  402.              }
  403.  
  404.  
  405.     case 7 : { xpos = 0;                                            // lower
  406.                ypos = W.ymin() - G_YMIN + margin_dist;
  407.                break;
  408.              }
  409.  
  410.  
  411.     case 8 : { xpos = W.xmax() - G_XMAX - margin_dist;             // down-right
  412.                ypos = W.ymin() - G_YMIN + margin_dist;
  413.                break;
  414.              }
  415.  
  416.   } // switch(scr_option)
  417.  
  418.   scroll_window(xpos,ypos);
  419.  
  420.   redraw_graph();
  421.  
  422. } // scroll_menu
  423.  
  424.  /*------------------------- look_edge -------------------------------*/
  425.  
  426. edge look_edge(node s,node t)
  427. {
  428.   edge e;
  429.  
  430.   forall_adj_edges(e,s)
  431.   {
  432.     if (G.target(e) == t) 
  433.     {
  434.       G.reset();
  435.       return e;
  436.     }
  437.   }
  438.  
  439.   return nil;
  440.  
  441. } // look_edge
  442.  
  443. /*---------------------- node_intersection_test --------------------*/
  444.  
  445. bool node_intersection_test(point cutp,node original = nil)
  446. {
  447.    node   n,testn;
  448.    edge   e;
  449.    circle cutc(cutp,W.get_node_width() / W.scale() );
  450.  
  451.       // test intersection with other nodes
  452.  
  453.    forall_nodes(n,G)
  454.    {
  455.      if (n != original)
  456.      {
  457.        // test: 'original' is dropped on other node ??
  458.  
  459.        testn = get_node_at_point(cutp);
  460.  
  461.        if ((testn!=nil)&&(testn!=original)) 
  462.        {
  463.          new_error_node(cutp);
  464.          G.reset();
  465.          return true;
  466.        }
  467.  
  468.        // test: 'original' overlaps on other node ??
  469.  
  470.        circle c(G[n],W.get_node_width() / W.scale() );
  471.        list(point) schnitt = cutc.intersection(c);
  472.  
  473.        if (schnitt.length()>0)
  474.        {
  475.          new_error_node(cutp);
  476.          G.reset();
  477.          return true;
  478.        }
  479.      }
  480.    }
  481.  
  482.       // test intersection with (non adjazent & inzident) edges
  483.  
  484.    forall_edges(e,G)
  485.    {
  486.       if ((G.source(e)!=original)&&(G.target(e)!=original)) 
  487.       {
  488.         segment seg(G[G.source(e)],G[G.target(e)]);
  489.         list(point) schnitt = cutc.intersection(seg);
  490.       
  491.         if (schnitt.length()>0)
  492.         {
  493.          new_error_node(cutp);
  494.          G.reset();
  495.          return true;
  496.         }
  497.       }
  498.     }
  499.  
  500.   return false;
  501.  
  502. } // node_intersection_test
  503.  
  504. /*--------------------- edge_intersection_test -----------------------*/
  505.  
  506. bool edge_intersection_test(node s, node t,node ausnahme=nil)
  507. {
  508.    node    n;
  509.    point   p;
  510.    segment st_seg(G[s],G[t]);
  511.  
  512.       // test intersection with other nodes
  513.  
  514.    forall_nodes(n,G)
  515.    {
  516.      if ((n!=s)&&(n!=t)&&(n!=ausnahme))
  517.      {
  518.        circle c(G[n],W.get_node_width() / W.scale() );
  519.        list(point) schnitt = c.intersection(st_seg);
  520.  
  521.        if (schnitt.length()>0)
  522.        {
  523.          new_error_edge(st_seg);
  524.  
  525.          G.reset();   // reset iterator
  526.          return true;
  527.         }
  528.       }
  529.     }
  530.  
  531.   return false;
  532.  
  533. } // edge_intersection_test
  534.  
  535. /*-------------------------- node_resize ---------------------------*/
  536.  
  537. void node_resize()
  538. {
  539.   int  old_node_width,new_node_width;
  540.   int  old_line_width,new_line_width;
  541.   node n;
  542.   bool schnitt = false;
  543.  
  544.   string size_header = form("             Resize Nodes :  select form of nodes !!! ");
  545.   string size[3];
  546.  
  547.   size[0] = " Cancel ";
  548.   size[1] = " without numbers ";
  549.   size[2] = " with numbers (select node_width) ";
  550.  
  551.   int size_option = W.read_panel(size_header,3,size);
  552.  
  553.   switch(size_option)
  554.   {
  555.      case 1 : new_node_width = 4;
  556.               new_line_width = 1;
  557.               newline;
  558.               break;
  559.  
  560.      case 2 : newline;
  561.               do {
  562.                    new_node_width = read_int("Resize Nodes : new size (7<=s<=15) -> ");
  563.               } while ((new_node_width<7)||(new_node_width>G_max_node_width));
  564.  
  565.               new_line_width = 2;
  566.               break;
  567.   }
  568.  
  569.   if (size_option!=0)
  570.   {
  571.     old_node_width = W.set_node_width(new_node_width);
  572.     old_line_width = W.set_line_width(new_line_width);
  573.  
  574.     redraw_graph();
  575.  
  576.     forall_nodes(n,G)
  577.     {
  578.       if (node_intersection_test(G[n],n)) schnitt = true;
  579.     }
  580.  
  581.     if (schnitt)
  582.     {
  583.       overlap_message(false);            // without redraw_graph()
  584.       W.del_message();
  585.  
  586.       W.set_node_width(old_node_width);
  587.       W.set_line_width(old_line_width);
  588.  
  589.       redraw_graph();
  590.       cout<<"RESIZE -> refused\n";
  591.     }
  592.     else cout<<"RESIZE -> ok\n";
  593.  
  594.   }
  595.  
  596. } // node_resize
  597.  
  598. /*----------------------- move_subgraph ------------------------------*/
  599.  
  600. void move_subgraph()
  601. {
  602.   node        n,s,t;
  603.   edge        e;
  604.   real        subx,suby,subX,subY,newx,newy;
  605.   list(point) pol_list;
  606.   list(node)  moved_nodes;
  607.   bool        schnitt = false;
  608.  
  609.   cout<<"\nMOVE   -> (click rectangle for location of subgraph)\n";
  610.  
  611.   W.read_mouse(subx,suby);
  612.  
  613.   point pl(subx,suby);pol_list.append(pl);
  614.   W.draw_filled_node(pl);
  615.  
  616.   W.read_mouse_rect(subx,suby,subX,subY);
  617.   W.draw_filled_node(pl);
  618.  
  619.   point pL(subx,subY);pol_list.append(pL);
  620.   point pR(subX,subY);pol_list.append(pR);
  621.   point pr(subX,suby);pol_list.append(pr);
  622.  
  623.   polygon pol(pol_list);
  624.  
  625.   W<<pol;      // mark subgraph
  626.  
  627.   cout<<"MOVE   -> (click point for location of left-down corner of new position)\n";
  628.  
  629.   W.read_mouse(newx,newy);
  630.  
  631.   W<<pol;     // reset mark subgraph
  632.  
  633.   forall_edges(e,G)              // clear old edges
  634.   {
  635.     s = G.source(e);
  636.     t = G.target(e);
  637.  
  638.     if ( (moved_nodes.search(s)!=nil)||(moved_nodes.search(t)!=nil) ) 
  639.     {
  640.       draw_edge(e,white);
  641.     }
  642.   }
  643.  
  644.     // get new position of subgraph
  645.  
  646.   vector vec(newx - subx,newy - suby);
  647.  
  648.   forall_nodes(n,G)
  649.   {
  650.     if (pol.inside(G[n]))
  651.     {
  652.       draw_node(n);             // clear old nodes
  653.  
  654.       G[n] = G[n] + vec;
  655.       moved_nodes.append(n);
  656.     }
  657.   }
  658.  
  659.     // test : move subgraph possible
  660.  
  661.   forall(n,moved_nodes)
  662.   {
  663.     draw_node(n);                // new position of nodes
  664.  
  665.     if (node_intersection_test(G[n],n)) schnitt = true;
  666.   }
  667.  
  668.   forall_edges(e,G)
  669.   {
  670.     s = G.source(e);
  671.     t = G.target(e);
  672.  
  673.     if ( (moved_nodes.search(s)!=nil)||(moved_nodes.search(t)!=nil) ) 
  674.     {
  675.       if (edge_intersection_test(s,t)) schnitt = true;
  676.       else draw_edge(e);
  677.     }
  678.   }
  679.  
  680.   if (schnitt)
  681.   {
  682.     forall(n,moved_nodes)  G[n] = G[n] + ( vec * -1 );
  683.  
  684.     overlap_message();
  685.  
  686.     cout<<"MOVE   -> refused\n";
  687.   }
  688.   else
  689.   {
  690.     cout<<"MOVE   -> ok\n";
  691.     redraw_graph();
  692.     still_saved = false;
  693.   }
  694.  
  695.   get_max_coord();
  696.  
  697. } // move_subgraph
  698.  
  699. /*-------------------------- add_node -------------------------------*/
  700.  
  701. node add_node(point p)
  702. {
  703.    node v;
  704.  
  705.    if ( node_intersection_test(p) )
  706.    {
  707.      error("add node    : node dropped on existing objects ... 'add' refused");
  708.  
  709.      return nil;
  710.    }
  711.  
  712.        // add_node possible
  713.  
  714.    v = G.new_node(p);
  715.  
  716.    G_node_name[v] = G_node_count++;
  717.    draw_node(v);
  718.  
  719.    graph_extension(p);       // test max.coord. of graph G
  720.  
  721.    return v;
  722.  
  723. } // add_node
  724.  
  725. /*------------------------- add_edge ----------------------------------*/
  726.  
  727. edge add_edge(node s,node t)
  728. {
  729.   edge      e;
  730.  
  731.   // test: e=(s,s) ??
  732.  
  733.   if (s==t)
  734.   {
  735.     error("add edge    : source = target ... 'add' refused");
  736.     return nil;
  737.   }
  738.  
  739.   // test: edge e=(s,t) still exist ??
  740.  
  741.   if (look_edge(s,t)!=nil)
  742.   {
  743.     error("add edge    : marked edge still exist ... 'add' refused");
  744.     return nil;
  745.   }
  746.  
  747.   if (edge_intersection_test(s,t))
  748.   {
  749.     error("add edge    : marked edge dropped on existing nodes ... 'add' refused");
  750.     return nil;
  751.   }
  752.  
  753.     // add new edge to G
  754.  
  755.   e = G.new_edge(s,t);
  756.  
  757.   G[e] = G_edge_count++;
  758.   draw_edge(e); 
  759.  
  760.   return e;
  761.  
  762. } // add_edge
  763.  
  764. /*------------------------ delete_edge -------------------------------*/
  765.  
  766. void delete_edge(edge e)
  767. {
  768.   node s = G.source(e);
  769.   node t = G.target(e);
  770.  
  771.   draw_edge(e,white);
  772.   G.del_edge(e);
  773.   
  774.   edge reverse = look_edge(t,s);
  775.  
  776.   if (reverse!=nil) draw_edge(reverse);
  777.  
  778. } // delete_edge
  779.  
  780. /*--------------------------- move_node ------------------------------*/
  781.  
  782. point move_node(node v)
  783. {
  784.   real       x,y;
  785.   point      p = G[v];                                // old position
  786.   node       s,t;
  787.   edge       e;
  788.   list(edge) e_list;
  789.   bool       schnitt_node = false;
  790.   bool       schnitt_edge = false;
  791.  
  792.   forall_edges(e,G)                                  // get adj.+inz. edges
  793.   {
  794.     if ( (source(e)) == v || (target(e) == v) )
  795.     {
  796.       e_list.append(e);
  797.     }
  798.   }
  799.  
  800.   draw_node(v);                                      // clear old position
  801.  
  802.   W.read_mouse_action(draw_node_cursor,x,y);
  803.  
  804.   point q(x,y);                                      // new position
  805.  
  806.   forall(e,e_list)  draw_edge(e,white);              // clear old edges
  807.  
  808.  
  809.      // test: intersection of v to other nodes
  810.  
  811.   schnitt_node = node_intersection_test(q,v);
  812.  
  813.      // test: intersection of v to other edges
  814.  
  815.   G[v] = q;    // neue position zuweisen
  816.   draw_node(v);
  817.  
  818.   forall(e,e_list)
  819.   {
  820.     s = G.source(e);
  821.     t = G.target(e);
  822.  
  823.     if (edge_intersection_test(s,t)) schnitt_edge = true;
  824.     else draw_edge(e);
  825.   }
  826.  
  827.   if (schnitt_node) error("move node   : node dropped on existing objects ... 'move' refused");
  828.  
  829.   if (schnitt_edge) error("move node   : moved edge dropped on existing node ... 'move' refused");
  830.  
  831.   if ( schnitt_node || schnitt_edge )
  832.   {
  833.     G[v] = p;
  834.     return p;
  835.   }
  836.  
  837.   get_max_coord();                                 // test max.coord of graph G
  838.   graph_extension(q);
  839.  
  840.   return q;
  841.  
  842. } // move_node
  843.  
  844. /*-------------------------- delete_node ----------------------------*/
  845.  
  846. void delete_node(node v)
  847. {
  848.   list(edge) ad_list,in_list;
  849.   edge       e;
  850.  
  851.   forall_edges(e,G) 
  852.   {
  853.     if (source(e) == v) ad_list.append(e);    // adj. edges
  854.  
  855.     if (target(e) == v) in_list.append(e);    // inz. edges
  856.   }
  857.  
  858.   forall(e,ad_list) delete_edge(e);
  859.  
  860.   if (in_list.length()>0)
  861.   {
  862.     warn("delete_node: incoming edges are deleted");
  863.     forall(e,in_list) delete_edge(e);
  864.   }
  865.  
  866.   draw_node(v); 
  867.   G.del_node(v);
  868.  
  869.   get_max_coord();              // test max.coord of graph G
  870.  
  871. } // delete_node
  872.  
  873. /*------------------------ insert_node -------------------------------*/
  874.  
  875. node insert_node(edge e)
  876. {
  877.   node  s = G.source(e);
  878.   node  t = G.target(e);
  879.  
  880.   bool  rev_exist = false;
  881.   node  n;    
  882.   edge  reverse,e1,e2,e3,e4;
  883.  
  884.   real xs = G[s].xcoord();
  885.   real ys = G[s].ycoord();
  886.   real xt = G[t].xcoord();
  887.   real yt = G[t].ycoord();
  888.  
  889.   point mid((xs+xt)/2, (ys+yt)/2);
  890.  
  891.   delete_edge(e);
  892.  
  893.   reverse = look_edge(t,s);        // if (s,t) && (t,s) in G -> insert to both
  894.   if (reverse != nil) 
  895.   {
  896.     rev_exist = true;
  897.     delete_edge(reverse);
  898.   }
  899.  
  900.   output_enable = false;
  901.  
  902.   n = add_node(mid);
  903.  
  904.   if (n!=nil)
  905.   {
  906.     e1 = add_edge(s,n);    
  907.     e2 = add_edge(n,t);    
  908.  
  909.     if (rev_exist)
  910.     {
  911.       e3 = add_edge(t,n);
  912.       e4 = add_edge(n,s);
  913.  
  914.       draw_edge(e3); draw_edge(e4);
  915.     }
  916.  
  917.     draw_edge(e1); draw_edge(e2);
  918.  
  919.     output_enable = true;
  920.  
  921.     return n;
  922.   }
  923.  
  924.   // insert impossible
  925.  
  926.   output_enable = true;
  927.  
  928.   segment s1(G[s],mid);
  929.   segment s2(mid,G[t]);
  930.   new_error_edge(s1);
  931.   new_error_edge(s2);
  932.   overlap_message();
  933.  
  934.   add_edge(s,t);
  935.   if (rev_exist) add_edge(t,s);
  936.  
  937.   error("insert edge : inserted node dropped on existing objects ... 'insert' refused");
  938.  
  939.   return nil;
  940.  
  941. } // insert_node
  942.  
  943. /*-------------------------- join_edges ------------------------------*/
  944.  
  945. void join_edges(node n)
  946. {
  947.   edge       e;
  948.   node       s,t;
  949.   bool       refuse = false;
  950.   list(edge) ad_list,in_list;
  951.  
  952.   forall_edges(e,G)      
  953.   {
  954.     if (G.source(e)==n) ad_list.append(e);         // adj. e = (n,?)
  955.     if (G.target(e)==n) in_list.append(e);         // inz. e = (?,n)
  956.   }
  957.  
  958.         // degree-test
  959.  
  960.   if ((ad_list.length()==in_list.length())&&(0<ad_list.length()<=2))
  961.   {
  962.      list(node) n_list;   // get participant nodes (n,s,t,...)
  963.  
  964.      forall(e,in_list)
  965.      {
  966.        s = G.source(e);
  967.        t = G.target(e);
  968.  
  969.        if (n_list.search(s)==nil) n_list.append(s);
  970.        if (n_list.search(t)==nil) n_list.append(t);
  971.      }
  972.  
  973.      forall(e,ad_list)
  974.      {
  975.        s = G.source(e);
  976.        t = G.target(e);
  977.  
  978.        if (n_list.search(s)==nil) n_list.append(s);
  979.        if (n_list.search(t)==nil) n_list.append(t);
  980.      }
  981.  
  982.      if (n_list.length()==3)
  983.      {
  984.        n_list.del_item(n_list.search(n));    //  get s + t
  985.        s = n_list.head();
  986.        t = n_list.tail();
  987.  
  988.        if (! edge_intersection_test(s,t,n))
  989.        {
  990.           // 'join' possible
  991.  
  992.          if (look_edge(s,t)!=nil)
  993.          {
  994.            error("join edge   : 'joined' edge still exist ... 'join' refused");
  995.            return;
  996.          }
  997.  
  998.          cout<<"\nJoin_Edge   : (";
  999.  
  1000.          forall(e,in_list)
  1001.          {
  1002.            cout<<" ("<<G_node_name[G.source(e)]<<"-"<<G_node_name[G.target(e)]<<")";
  1003.            delete_edge(e);
  1004.          }
  1005.  
  1006.          forall(e,ad_list) 
  1007.          {
  1008.            cout<<" ("<<G_node_name[G.source(e)]<<"-"<<G_node_name[G.target(e)]<<")";
  1009.            delete_edge(e);
  1010.          }
  1011.  
  1012.          delete_node(n);
  1013.  
  1014.          cout<<" ) to (";
  1015.          cout<<" ("<<G_node_name[s]<<"-"<<G_node_name[t]<<")";
  1016.  
  1017.          add_edge(s,t);
  1018.  
  1019.          if (ad_list.length()==2) 
  1020.          {
  1021.            add_edge(t,s);
  1022.            cout<<" ("<<G_node_name[t]<<"-"<<G_node_name[s]<<")";
  1023.          }
  1024.  
  1025.          cout<<" )\n";
  1026.  
  1027.          still_saved = false;
  1028.        }
  1029.        else 
  1030.        {
  1031.          forall(e,ad_list) draw_edge(e,white);
  1032.          forall(e,in_list) draw_edge(e,white);
  1033.          draw_node(n);
  1034.  
  1035.          error("join edge   : joined edge dropped on existing node ... 'join' refused");
  1036.          overlap_message();
  1037.        }
  1038.      }
  1039.      else refuse = true;
  1040.   }
  1041.   else refuse = true;
  1042.  
  1043.   if (refuse)
  1044.   {
  1045.     error("join edge   : wrong degree of node ...  'join' refused");
  1046.   }
  1047.  
  1048. } // join_edges
  1049.  
  1050. /*---------------------------- unzoom ------------------------------*/
  1051.  
  1052. void unzoom()
  1053. {
  1054.   node   n;
  1055.  
  1056.   bool   schnitt = false;
  1057.   double minx = 0;
  1058.   double miny = 0;
  1059.  
  1060.   double factor = 2.0;                
  1061.   double old_width = W_WIDTH;
  1062.   double new_width = (factor * W_WIDTH);
  1063.  
  1064.   if (new_width > 400)  new_width = 400;
  1065.   W_WIDTH = new_width;
  1066.  
  1067.   double dist = (new_width - old_width) / 2;
  1068.   scroll_window(dist,dist);
  1069.  
  1070.   init_window();                       // get new extension 
  1071.   redraw_graph("without_W.clear");
  1072.  
  1073.   forall_nodes(n,G)
  1074.   {
  1075.     if (node_intersection_test(G[n],n)) schnitt = true;
  1076.   }
  1077.  
  1078.   if (schnitt)
  1079.   {
  1080.     overlap_message(false);            // without redraw_graph()
  1081.  
  1082.     W_WIDTH = old_width;
  1083.     scroll_window(-dist,-dist);
  1084.     init_window();
  1085.     redraw_graph("without_W.clear");
  1086.  
  1087.     cout<<"\nUNZOOM -> refused\n";
  1088.   }
  1089.   else cout<<"\nUNZOOM -> ok\n";
  1090.  
  1091. } // unzoom
  1092.  
  1093. /*----------------------------- zoom ------------------------------*/
  1094.  
  1095. void zoom()
  1096. {
  1097.   real x,y,xp,yp;
  1098.   real xdist,ydist;
  1099.   real new_width;
  1100.  
  1101.   cout<<"\nZOOM   -> click rectangle ( = screen after zoom)\n";
  1102.  
  1103.   W.read_mouse(xp,yp);
  1104.   W.draw_filled_node(xp,yp);
  1105.  
  1106.   W.read_mouse_rect(xp,yp,x,y);
  1107.  
  1108.   new_width =  W_WIDTH * (abs(x - xp) / W_WIDTH);
  1109.  
  1110.   if (new_width>0)
  1111.   {
  1112.     W_WIDTH = new_width;
  1113.     init_window();
  1114.     
  1115.     if (xp < x) xdist = xp;
  1116.     else        xdist = x;
  1117.  
  1118.     if (yp < y) ydist = yp;
  1119.     else        ydist = y;
  1120.  
  1121.     scroll_window(-xdist,-ydist);
  1122.  
  1123.     redraw_graph("without_W.clear");
  1124.  
  1125.     cout<<"ZOOM   -> ok\n";
  1126.   }
  1127.   else 
  1128.   {
  1129.     error("zoom        : grid distance out of range ... 'zoom' refused");
  1130.     cout<<"ZOOM   -> refused\n";
  1131.   }
  1132.  
  1133. } // zoom
  1134.  
  1135. /*--------------------------- read_graph -----------------------------*/
  1136.  
  1137. void read_graph(string str)
  1138. {
  1139.   node             v,s,t,knoten;
  1140.   edge             e,kante;
  1141.   real             readx,ready;
  1142.   double           minx = 0;
  1143.   double           miny = 0;
  1144.  
  1145.   GRAPH(point,int) HELP;                       // help graph
  1146.   GRAPH(point,int) old_G = G;                  // old Graph G
  1147.  
  1148.   if (str == "CANCEL")
  1149.   { 
  1150.     cout<<"READ   -> cancelled\n";
  1151.     return;
  1152.   }
  1153.  
  1154.   if (str == "")
  1155.   { 
  1156.     read_graph(read_string("READ   -> read file ( 'CANCEL' to stop ) : "));
  1157.     return;
  1158.   }
  1159.  
  1160.  
  1161.   int modus = HELP.read(str);
  1162.  
  1163.   if (modus == 1)
  1164.   {
  1165.     cout<<"(warning) read_graph: file '"<<str<<"' doesn't exist\n";
  1166.     read_graph(read_string("\nREAD   -> read file ( 'CANCEL' to stop ) : "));
  1167.     return;
  1168.   }
  1169.  
  1170.   if (modus == 2)
  1171.   {
  1172.     cout<<"(warning) read_graph  : graph '"<<str<<"' not created by Graph Editor\n";
  1173.     read_graph(read_string("\nREAD   -> read file ( 'CANCEL' to stop ) : "));
  1174.     return;
  1175.   }
  1176.  
  1177.   if (modus == 3)
  1178.   { 
  1179.     cout<<"(warning) read_graph  : file '"<<str<<"' not represent a graph\n";
  1180.     read_graph(read_string("\nREAD   -> read file ( 'CANCEL' to stop ) : "));
  1181.     return;
  1182.   }
  1183.  
  1184.         // move 'readed' graph to new position
  1185.  
  1186.   cout<<"READ   -> (click left-down corner of new subgraph)\n";
  1187.   
  1188.   W.read_mouse(readx,ready);
  1189.  
  1190.   v = HELP.choose_node();
  1191.   
  1192.   if (v!=nil)
  1193.   {
  1194.     minx = HELP[v].xcoord();
  1195.     miny = HELP[v].ycoord();
  1196.   }
  1197.  
  1198.   forall_nodes(v,HELP)              // min coord. of new_nodes
  1199.   {
  1200.     if (HELP[v].xcoord() < minx) minx = HELP[v].xcoord();
  1201.     if (HELP[v].ycoord() < miny) miny = HELP[v].ycoord();
  1202.   }
  1203.  
  1204.   vector resetvec(-minx,-miny);
  1205.   vector vec(readx,ready);
  1206.  
  1207.   forall_nodes(v,HELP) HELP[v] = HELP[v] + resetvec + vec;
  1208.  
  1209.  
  1210.   // eingelesenen Hilfs-Graphen HELP auf G kopieren
  1211.  
  1212.   bool             complete = true;
  1213.   list(node)       wrong_nodes;
  1214.  
  1215.   node_array(node) corr(HELP);
  1216.  
  1217.   output_enable = false;           // no error and warning output
  1218.  
  1219.   forall_nodes(v,HELP)
  1220.   {
  1221.     knoten = add_node(HELP[v]);
  1222.  
  1223.     if (knoten!=nil) corr[v] = knoten;
  1224.     else
  1225.     {
  1226.       complete = false;
  1227.       wrong_nodes.append(v);    // node not to G added
  1228.       new_error_node(HELP[v]);
  1229.     }
  1230.   }
  1231.  
  1232.   forall_edges(e,HELP)
  1233.   {
  1234.     s = HELP.source(e);
  1235.     t = HELP.target(e);
  1236.  
  1237.     if ( (wrong_nodes.search(s)==nil) && (wrong_nodes.search(t)==nil) )
  1238.     {
  1239.       kante = add_edge(corr[s],corr[t]);
  1240.  
  1241.       if (kante==nil) complete = false;
  1242.     }
  1243.     else 
  1244.     {
  1245.      segment seg(G[s],G[t]);
  1246.      new_error_edge(seg);
  1247.      complete = false;
  1248.     }
  1249.   }
  1250.  
  1251.   output_enable = true;
  1252.   still_saved   = false;
  1253.  
  1254.   if (complete) cout <<"READ   -> ok\n";
  1255.   else  
  1256.   {
  1257.     overlap_message(false);             // without redraw_graph()
  1258.  
  1259.     if (W.confirm(" ??? read incomplete subgraph ??? "))
  1260.     {
  1261.       cout<<"READ   -> incomplete\n";
  1262.       redraw_graph();
  1263.     }
  1264.     else
  1265.     {
  1266.       W.clear();
  1267.       reset_graph();
  1268.       
  1269.       output_enable = false;           // no error and warning output
  1270.  
  1271.       node_array(node) old_corr(old_G);
  1272.  
  1273.       forall_nodes(v,old_G)  old_corr[v] = add_node(old_G[v]);
  1274.       forall_edges(e,old_G)  add_edge(old_corr[old_G.source(e)],old_corr[old_G.target(e)]);
  1275.       output_enable = true;
  1276.       still_saved   = true;
  1277.  
  1278.       cout<<"READ   -> refused\n";
  1279.     }
  1280.   }
  1281.  
  1282.   init_graph();
  1283.  
  1284. } // read_graph
  1285.  
  1286. /*-------------------------- load_graph ------------------------------*/
  1287.  
  1288. void load_graph(string str)
  1289. {
  1290.   node v,s,t,knoten;
  1291.   edge e,kante;
  1292.  
  1293.   GRAPH(point,int) HELP;                       // help graph
  1294.  
  1295.   if (str=="CANCEL") 
  1296.   {
  1297.     cout<<"LOAD   -> cancelled\n";
  1298.     return;
  1299.   }
  1300.  
  1301.   if (str=="")
  1302.   {
  1303.     load_graph(read_string("LOAD   -> edit file ( 'CANCEL' to stop ) : "));
  1304.     return;
  1305.   }
  1306.   
  1307.  
  1308.   int modus = HELP.read(str);
  1309.  
  1310.   if (modus == 1)
  1311.   {
  1312.     cout<<"(warning) load_graph: file '"<<str<<"' doesn't exist\n";
  1313.     load_graph(read_string("\nLOAD   -> edit file ( 'CANCEL' to stop ) : "));
  1314.     return;
  1315.   }
  1316.  
  1317.   if (modus == 2)
  1318.   { 
  1319.     cout<<"(warning) load_graph  : graph '"<<str<<"' not created by Graph Editor\n";
  1320.     load_graph(read_string("\nLOAD   -> edit file ( 'CANCEL' to stop ) : "));
  1321.     return;
  1322.   }
  1323.  
  1324.   if (modus == 3)
  1325.   { 
  1326.     cout<<"(warning) load_graph  : file '"<<str<<"' doesn't represent a graph\n";
  1327.     load_graph(read_string("\nLOAD   -> edit file ( 'CANCEL' to stop ) : "));
  1328.     return;
  1329.   }
  1330.  
  1331.   G_filename = str;
  1332.   reset_graph();
  1333.   W.clear();
  1334.  
  1335.   // eingelesenen Hilfs-Graphen HELP auf G kopieren
  1336.  
  1337.   bool             complete = true;
  1338.   list(node)       wrong_nodes;
  1339.  
  1340.   node_array(node) corr(HELP);
  1341.  
  1342.   forall_nodes(v,HELP)
  1343.   {
  1344.     knoten = add_node(HELP[v]);
  1345.  
  1346.     if (knoten!=nil) corr[v] = knoten;
  1347.     else
  1348.     {
  1349.       complete = false;
  1350.       wrong_nodes.append(v);    // node not to G added
  1351.       new_error_node(HELP[v]);
  1352.     }
  1353.   }
  1354.  
  1355.   forall_edges(e,HELP)
  1356.   {
  1357.     s = HELP.source(e);
  1358.     t = HELP.target(e);
  1359.  
  1360.     if ( (wrong_nodes.search(s)==nil) && (wrong_nodes.search(t)==nil) )
  1361.     {
  1362.       kante = add_edge(corr[s],corr[t]);
  1363.  
  1364.       if (kante==nil) complete = false;
  1365.     }
  1366.     else
  1367.     {
  1368.      segment seg(G[s],G[t]);
  1369.      new_error_edge(seg);
  1370.      complete = false;
  1371.     }
  1372.   }
  1373.  
  1374.   if (complete) cout <<"LOAD   -> ok\n";
  1375.   else 
  1376.   {
  1377.      overlap_message();
  1378.      cout <<"LOAD   -> incomplete\n";
  1379.   }
  1380.  
  1381.   init_graph();
  1382.  
  1383. } //load_graph
  1384.  
  1385. /*--------------------------- save_graph -----------------------------*/
  1386. void save_graph(string f)
  1387. {
  1388.   if (f!="")
  1389.   {
  1390.     G_filename = f;
  1391.     G.write(f);
  1392.  
  1393.     cout << "SAVE   -> ok \n";
  1394.     still_saved = true;
  1395.   }
  1396.   else  save_graph(read_string("SAVE   -> write to file: "));
  1397.  
  1398. } // save_graph
  1399.  
  1400. /*-------------------------- save_test ------------------------------*/
  1401.  
  1402. void save_test()
  1403. {
  1404.   if (! still_saved)
  1405.      if (W.confirm(" ??? save old graph ??? "))
  1406.      {
  1407.          save_graph(read_string("\nSAVE   -> write to file: "));
  1408.      }
  1409.  
  1410.   still_saved = true;
  1411.  
  1412. } // save_test
  1413.  
  1414. /*--------------------------- print_help -----------------------------*/
  1415.  
  1416. void print_help()
  1417.   W.clear();
  1418.   W.message("                                                   ");
  1419.   W.message("                                                   ");
  1420.   W.message("                                                   ");
  1421.   W.message("   +----------------------------------------------+");
  1422.   W.message("   |                  Graph Edit                  |"); 
  1423.   W.message("   +----------------------------------------------+");
  1424.   W.message("   | BUTTON      unshifted              shifted   |");
  1425.   W.message("   +----------------------------------------------+");
  1426.   W.message("   | LEFT:   new node  / move node    delete node |");
  1427.   W.message("   | MIDDLE: new edge  / insert node  delete edge |");
  1428.   W.message("   | RIGHT: join edges / scroll           Menu    |");
  1429.   W.message("   +----------------------------------------------+");
  1430.   W.message("                                                   ");
  1431.   W.message("                                                   ");
  1432.   W.message("                                                   ");
  1433.   W.message("                   < Press Button >                ");
  1434.  
  1435.   W.read_mouse();
  1436.   W.del_message();
  1437.   redraw_graph();
  1438.  
  1439. }
  1440.  
  1441. /*------------------------------ GED --------------------------------*/
  1442.  
  1443. void GED(string filename)
  1444. {
  1445.   node   s,t,v,w,knoten;
  1446.   edge   e,kante;
  1447.   real   x,y;
  1448.   point  p,q,pw;
  1449.   int    key = 0;
  1450.   int    fertig = 0;
  1451.   int    k;
  1452.  
  1453.   int    option   = 0;                        // choosed option in menu 
  1454.  
  1455.   G_node_count = 0;                           // reset counter
  1456.   G_edge_count = 0;          
  1457.  
  1458.   W.init(0,80,0);
  1459.  
  1460.   W_save_mode = W.set_mode(xor_mode);
  1461.  
  1462.   W.set_node_width(12);
  1463.   W.set_line_width(2);
  1464.  
  1465.   G_XMAX = W.xmin();
  1466.   G_YMAX = W.ymin();  
  1467.   G_XMIN = W.xmax();
  1468.   G_YMIN = W.ymax();
  1469.   
  1470.   cout<<"\n\n     *** Planar Graph Editor ***\n\n( Menue : <Shift> right mouse_button )\n\n";
  1471.  
  1472.   cout<<"\n\n         *** Graph Editor ***\n\n( Menue : <Shift> right mouse_button )\n\n";
  1473.  
  1474.   if (filename != "") load_graph(filename);
  1475.   else
  1476.       {
  1477.         center_graph();
  1478.         redraw_graph("without_W.clear");
  1479.       }
  1480.  
  1481.   init_graph();
  1482.  
  1483.                          /* main - routine */
  1484.  
  1485.   while (option != 15)                // option != Quit
  1486.   {
  1487.      key = W.read_mouse(x,y);
  1488.  
  1489.      p = point(x,y);
  1490.     
  1491.      v = get_node_at_point(p);                     // -> node clicked ?
  1492.  
  1493.      switch(key) {
  1494.  
  1495.      case 1:  { 
  1496.                 if (v == nil)
  1497.                 { 
  1498.                   knoten = add_node(p);            /* new node */
  1499.  
  1500.                   if (knoten!=nil) 
  1501.                   {
  1502.                     cout<<"\nAdd Node    : ("<<G_node_name[knoten]<<") \n";
  1503.                     still_saved = false;
  1504.                   }
  1505.                 }
  1506.                 else  
  1507.                 {
  1508.                   move_node(v);                       /* move node */
  1509.  
  1510.                   cout<<"\nMove Node   : ("<<G_node_name[v]<<")\n";
  1511.                   still_saved = false;
  1512.                 }
  1513.  
  1514.                 break;
  1515.  
  1516.                } // case 1
  1517.  
  1518.      case -1: { 
  1519.                 if (v != nil)  
  1520.                 {
  1521.                   cout<<"\nDelete Node : ("<<G_node_name[v]<<")\n";
  1522.  
  1523.                   delete_node(v);                     /* delete node */
  1524.  
  1525.                   still_saved = false;
  1526.                 }
  1527.                 else error("delete node : no node at mouse-position ... 'delete' refused");
  1528.  
  1529.                 break;
  1530.  
  1531.               } // case -1
  1532.  
  1533.      case 2:  {                                  /* new edge / insert node */
  1534.                 if (v != nil)
  1535.                 { 
  1536.                   p = G[v];
  1537.  
  1538.                   do {
  1539.                        W.message("                add edge / insert node");
  1540.                        k = W.read_mouse_seg(p.xcoord(),p.ycoord(),x,y);
  1541.                        W.del_message();
  1542.  
  1543.                        pw = point(x,y);
  1544.  
  1545.                        w = get_node_at_point(pw);
  1546.  
  1547.                        if (w != nil) 
  1548.                        {
  1549.                          if ((e=look_edge(v,w)) == nil) 
  1550.                          {
  1551.                            kante = add_edge(v,w);         /* new edge */
  1552.  
  1553.                            if (kante!=nil) 
  1554.                            {
  1555.                              cout<<"\nAdd Edge    : ("<<G_node_name[v]<<"-"<<G_node_name[w]<<")\n";
  1556.                              still_saved = false;
  1557.                            }
  1558.                          }
  1559.                          else                         
  1560.                          {                               /* insert node */
  1561.                            s = G.source(e);
  1562.                            t = G.target(e);
  1563.  
  1564.                            knoten = insert_node(e);
  1565.  
  1566.                            if (knoten!=nil)
  1567.                            {
  1568.                              cout<<"\nInsert Node : ("<<G_node_name[knoten]<<") to ("<<G_node_name[s]<<"-"<<G_node_name[t]<<")\n";
  1569.                              still_saved = false;
  1570.                            }
  1571.                          }  
  1572.                        }
  1573.  
  1574.                      } while ( w == nil && k == 2);
  1575.                 }
  1576.  
  1577.                 break;
  1578.  
  1579.               } // case 2
  1580.  
  1581.      case -2: {                                          /* delete edge */
  1582.                 if (v != nil) 
  1583.                 { 
  1584.                   p = G[v];
  1585.                   W.message("                     delete edge");
  1586.                   W.read_mouse_seg(p.xcoord(),p.ycoord(),x,y);
  1587.                   W.del_message();
  1588.  
  1589.                   q = point(x,y);
  1590.                   w = get_node_at_point(q);
  1591.  
  1592.                   if (w != nil)
  1593.                   {
  1594.                     e = look_edge(v,w);
  1595.                     if (e != nil) 
  1596.                     {
  1597.                       cout<<"\nDelete Edge : ("<<G_node_name[v]<<"-"<<G_node_name[w]<<")\n";
  1598.                       delete_edge(e);
  1599.  
  1600.                       still_saved = false;
  1601.                     }
  1602.                     else error("delete edge : edge doesn't exist ... 'delete' refused");
  1603.                   }
  1604.                 }
  1605.  
  1606.                 break;
  1607.  
  1608.               } // case -2
  1609.  
  1610.  
  1611.      case 3:  {                                      /* join edges / scroll  */
  1612.  
  1613.                 if (v != nil)
  1614.                 {
  1615.                    join_edges(v);
  1616.                 }
  1617.                 else
  1618.                 {
  1619.                    cout<<"\nUser Scroll : (click distance of window movement)\n";
  1620.                    scroll_window(p.xcoord(),p.ycoord(),0);   // user-scroll
  1621.                 } 
  1622.  
  1623.                 break;
  1624.               }
  1625.  
  1626.  
  1627.      case -3: {                      /* Menu */
  1628.  
  1629.                 string header = form("Graph Editor  (file : \"%s\")",~G_filename);
  1630.  
  1631.                 panel P(header);
  1632.  
  1633.                 P.button("                  Cancel                   ");
  1634.                 P.new_button_line();
  1635.  
  1636.                 P.button("  Help  "); 
  1637.                 P.button(" Resize ");
  1638.                 P.button("  Move  ");
  1639.                 P.button(" Scroll ");
  1640.                 P.new_button_line();
  1641.  
  1642.                 P.button("  Print ");
  1643.                 P.button(" Redraw ");
  1644.                 P.button("  Zoom  "); 
  1645.                 P.button(" Unzoom "); 
  1646.                 P.new_button_line();
  1647.  
  1648.                 P.button("  Load  ");
  1649.                 P.button("  Read  ");
  1650.                 P.button("  Save  "); 
  1651.                 P.button("Save as "); 
  1652.                 P.new_button_line();
  1653.  
  1654.                 P.button("       Clear        ");
  1655.                 P.button("       Quit        "); 
  1656.                 P.new_button_line();
  1657.  
  1658.  
  1659.                 option = P.open();
  1660.  
  1661.                 W.del_message();
  1662.  
  1663.                 switch (option) {
  1664.  
  1665.                 case 1 : { print_help();
  1666.                            break;
  1667.                          }
  1668.  
  1669.                 case 2 : { node_resize();
  1670.                            break;
  1671.                          }
  1672.  
  1673.                 case 3 : { move_subgraph();
  1674.                            break;
  1675.                          }
  1676.  
  1677.                 case 4 : { scroll_menu();
  1678.                            break;
  1679.                          }
  1680.  
  1681.                 case 5 : { cout<<"\nPRINT  -> graph `"<<G_filename<<"`\n";
  1682.                            G.print();
  1683.                            break;
  1684.                          }
  1685.  
  1686.                 case 6 : { redraw_graph();
  1687.                            break;
  1688.                          }
  1689.  
  1690.                 case 7 : { zoom();
  1691.                            break;
  1692.                          }
  1693.  
  1694.                 case 8 : { unzoom();
  1695.                            break;
  1696.                          }
  1697.  
  1698.                 case 9 : { save_test();
  1699.                            load_graph(read_string("\nLOAD   -> edit file: "));
  1700.                            break;
  1701.                          }
  1702.  
  1703.                case 10 : { read_graph(read_string("\nREAD   -> read file: "));
  1704.                            break;
  1705.                          }
  1706.  
  1707.                case 11 : { cout<<"\n";
  1708.                            save_graph(G_filename);
  1709.                            break;
  1710.                          }
  1711.  
  1712.                case 12 : { save_graph(read_string("\nSAVE   -> write to file: "));
  1713.                            break;
  1714.                          } 
  1715.                  
  1716.                case 14 : { save_test();
  1717.                            W.clear();
  1718.                            reset_graph();
  1719.                            init_graph();
  1720.                            G_filename="";
  1721.                            cout<<"\nCLEAR  -> Graph is empty\n";
  1722.                            break;
  1723.                          }
  1724.  
  1725.                 } // switch(option)
  1726.  
  1727.                 W.del_message();
  1728.  
  1729.                 break;
  1730.  
  1731.               } // case -3
  1732.  
  1733.  
  1734.     } // switch(key)
  1735.  
  1736.     if ( (error_nodes.length()>0) || (error_edges.length()>0) )
  1737.     {
  1738.       overlap_message();  // Fehler ausgeben
  1739.     }
  1740.  
  1741.   } // while (option != 15)
  1742.  
  1743.   save_test();
  1744.  
  1745.   W.set_mode(W_save_mode);
  1746.   W.clear();
  1747.  
  1748.   cout<<"\nQUIT   -> you leave 'Graph_Editor'\n";
  1749.   cout<<"\n\n         *** Graph Editor ***\n\n";
  1750.  
  1751. } // GED
  1752.  
  1753. /*---------------------------- main -----------------------------------*/
  1754.  
  1755. main(int argc, char** argv)
  1756. {
  1757.   string f;
  1758.  
  1759.   if (argc < 2)  f="";
  1760.   else           f=argv[1];
  1761.  
  1762.  
  1763.   GED(f);
  1764. }
  1765.