CNode *CTerm::newaccess (int x, int y, int z, int ident, CNet *net)
  throw (dup_term, bad_grab, merge_term)
{
  list<CDRGrid::iterator>::iterator  itNode;
       CDRGrid::iterator             coord;

  CNode *pNode;

  coord = net->_drgrid->origin;
  coord.set (x, y, z);

  pNode = &coord.node ();
  if ((z == 0) && coord.isnodehole()) {
    pNode = &coord.addnode ();
  }

  if (pNode->data.owner) {
    // Check if the node has already been took by another terminal.
    if (pNode->data.owner != net)
      throw bad_grab ( pNode->data.owner->terms[pNode->getid()]->name
                     , net->name
                     , coord.x()
                     , coord.y()
                     , coord.z()
                     , 0
                     , pNode->data.pri
                     , pNode->terminal()
                     , pNode->data.ident
                     );

    // Check if the node belongs to another terminal of this net.
    // If so, send a merging exception to CNet::newaccess ().
    if (pNode->getid () != ident) throw merge_term ( pNode->getid()
                                                   , pNode->data.owner->terms[pNode->getid()]->name
                                                   , pNode->data.owner->terms[ident]->name
                                                   , net->name
                                                   , coord.x()
                                                   , coord.y()
                                                   , coord.z()
                                                   );

    return (NULL);
  }

  // Check if the node is already in the list (this should never appens !)
  for (itNode = nodes.begin (); itNode != nodes.end (); itNode++) {
    if (*itNode == coord) {
      throw dup_term (name, *itNode);
    }
  }

  pNode->data.owner    = net;
  pNode->data.obstacle = false;
  pNode->setid (ident);
  nodes.push_back (coord);

  return (pNode);
}
void  CTerm::lockalone (bool global)
{
  CDRGrid::iterator  coord;
  CDRGrid::iterator  coord2;
                int  z, i;
               bool  adjust;

  if (nodes.size() != 1) return;


  coord  = nodes.back ();
  coord2 = coord;

  CDRGrid* drgrid = coord._drgrid;

  if ( (coord.z() > 0) && !global ) return;
  if (  coord.onAB()) return;

  //cerr << "+ locking lone terminal : " << coord.node().data.owner->name
  //     << " at " << coord
  //     << endl;

  // All terminal case, eat up z=1 (ALU2) if not already took.
  if (coord.z() == 0) {
    // Go to z=1 (ALU2).
    //cerr << "+   locking z=1          " << coord << endl;
    newaccess ( coord.x()
              , coord.y()
              , 1
              , coord.node().getid()
              , coord.node().data.owner
              );

    coord2.top();
  }

  if (!global) return;


  if (coord.z() < 2) {
    // Go to z=2 (ALU3).
    //cerr << "+   locking z=2          " << coord2 << endl;
    newaccess ( coord2.x()
              , coord2.y()
              , 2
              , coord.node().getid()
              , coord.node().data.owner
              );
  }


  if ( drgrid->Z < 3 ) return;
  // Global terminal : when zupper=4, find the nearest VIA on the
  // double pitch grid.

  // Is the terminal in ALU3 (or less).
  if ( (coord.z() < 3) && (coord.zupper () == 4) ) {
    if ( coord2.y() % 2 ) {
      // We are not on the double pitch grid. Try to go there.
      // Look for up and down grid node.
      adjust = true;

      for (i = 0; i < 3; i++) {
        switch (i) {
          case 0: coord2.dy (+1); break;
          case 1: coord2.dy (-2); break;
        }

        // Neither node are accessibles, we are probably doomed ...
        if (i == 2) { coord2.dy (+1); adjust = false; break; }

        if (coord2.inside()) {
          if (    !coord2.node().data.obstacle
              &&  (   (coord2.node().data.owner == NULL )
                   || (coord2.node().data.owner == coord.node().data.owner) ) )
            { break; }
        }
      }

      if (adjust) {
        // Adjust to the double grid pitch to z=2 (ALU3).
        //cerr << "+   locking z=2 (ADJUST) " << coord2 << endl;
        newaccess ( coord2.x()
                  , coord2.y()
                  , 2
                  , coord.node().getid()
                  , coord.node().data.owner
                  );
      }
    }
  }

  if ( drgrid->Z < 4 ) return;

  if (coord.z() < 4) {
    // Go to z=3 (ALU3).
    //cerr << "+   locking z=3          " << coord2 << endl;
    newaccess ( coord2.x()
              , coord2.y()
              , 3
              , coord.node().getid()
              , coord.node().data.owner
              );
  }
}