docs: private int expandHorizontally(Rectangular gp, Rectangular limit, AreaImpl template, boolean right, boolean sep)
      {
          //System.out.println("exp: " + gp + (right?" ->":" <-") + " " + sep);
          int na = right ? gp.getX2() : gp.getX1(); //what to return when it's not possible to expand
          int targetx = right ? (gp.getX2() + 1) : (gp.getX1() - 1); 
          //find candidate boxes
          boolean found = false;
          int y = gp.getY1();
          while (y <= gp.getY2()) //scan everything at the target position
          {
              AreaImpl cand = (AreaImpl) getTopology().findAreaAt(targetx, y);
              //ignore candidates that intersect with our area (could leat to an infinite loop)
              if (cand != null && !cand.getGridPosition().intersects(gp))
              {
                  found = true;
                  if (sep &&
                          ((right && separatorLeft(cand.getGridPosition())) ||
                           (!right && separatorRight(cand.getGridPosition()))))
                      return na; //separated, cannot expand
                  else if ((matchstyles && !cand.hasSameStyle(cand)) || cand.getLevel() > maxlevel)
                      return na; //not the same style or level
                  else
                  {
                      Rectangular cgp = new Rectangular(cand.getGridPosition());
                      if (cgp.getY1() == gp.getY1() && cgp.getY2() == gp.getY2())
                          return targetx; //simple match
                      else if (cgp.getY1() < gp.getY1() || cgp.getY2() > gp.getY2())
                          return na; //area overflows, cannot expand
                      else //candidate is smaller, try to expand align to our width
                      {
                          if (right)
                          {
                              Rectangular newlimit = new Rectangular(targetx, gp.getY1(), limit.getX2(), gp.getY2());
                              expandToLimit(cand, cgp, newlimit, template, false, true, DIR_DOWN, REQ_VERTICAL);
                              if (cgp.getY1() == gp.getY1() && cgp.getY2() == gp.getY2())
                                  return cgp.getX2(); //successfully aligned
                          }
                          else
                          {
                              Rectangular newlimit = new Rectangular(limit.getX1(), gp.getY1(), targetx, gp.getY2());
                              expandToLimit(cand, cgp, newlimit, template, false, true, DIR_DOWN, REQ_VERTICAL);
                              if (cgp.getY1() == gp.getY1() && cgp.getY2() == gp.getY2())
                                  return cgp.getX1(); //successfully aligned
                          }
                      }
                  }
                  //skip the candidate
                  y += cand.getGridPosition().getY2() + 1;
              }
              else
                  y++;
          }
          if (!found)
              return targetx; //everything below/above empty, can safely expand
          else
              return na; //some candidates but none usable
      }