/*
 * Copyright (c) 2003 by Hyperwave AG. All rights reserved.
 * Object.js,v 1.10 2003/04/23 09:29:14 szwoelf Exp
 *
 * The following functions form the Object JavaScript 1.2 environment.
 */

var ua$ = navigator.userAgent.toLowerCase();
var ua_isSafari$ = (ua$.indexOf("safari") >= 0);
var ua_isKonqueror$ = (ua$.indexOf("konqueror") >= 0);

if ( typeof ojs != "undefined" && !ua_isSafari$ )
{
  var text = "Illegal State: double include of Object.js"
  alert(text);
  throw text;
}

/*
 * "zoom factor" - uncomment these lines when measuring memory leaks:
 *
var s = "1234567890";
var zoom = [];
for ( var i = 0; i < 18; ++i )
{
  zoom[zoom.length] = s = s + s;
}
//zoom = null;
*/
 
/**
 * This function can be used to create instances of classes which are
 * not native in JavaScript (unlike Function, Object, Array,...).
 * It can be used instead of the JavaScript <code>new</code> operator.
 * 
 * @param aClass: Function: the constructor function of the class to
 *   instantiate.  
 * 
 * @deprecated since 2002-12-03.
 *   Reasons:
 *   <ul>
 *     <li>JavaScript 1.3 isn't required anymore. 
 *     <li>JavaScript constructors seem to work quite well now ;-).
 *   </ul>
 */
function newInstanceOf ( aClass )
{
  // ... and if this something might be a constructor function of a
  // class
  if ( typeof (aClass) != "function" )
  {
    // an exception should be thrown, but to use the function on 
    // client and server side, returns only null
    return null;
  }

  // create a new instance of the wished class using the new keyword
  // CAUTION: only 5 parameters are allowed in a constructor!
  var myObj;
  switch ( arguments.length - 1 )
  {
  case 0:
    myObj = new aClass ();
    break;
  case 1:
    myObj = new aClass ( arguments[1] );
    break;
  case 2:
    myObj = new aClass ( arguments[1], arguments[2] );
    break;
  case 3:
    myObj = new aClass ( arguments[1], arguments[2], arguments[3] );
    break;
  case 4:
    myObj = new aClass ( arguments[1], arguments[2], arguments[3],
                         arguments[4] );
    break;
  case 5:
    myObj = new aClass ( arguments[1], arguments[2], arguments[3],
                         arguments[4], arguments[5] );
    break;
  default:
    return null;
  }
  return myObj;
}

/** 
 * This function implements ECMA conform inheritance for JavaScript
 * classes. This inheritance covers all topics concerning
 * prototyping, such as: 
 * <UL>
 *   <LI>access to prototyped members of the baseClass.</LI>
 *   <LI>It adds a <code>static_</code> object holding all static
 *       properties and methods to the derivedClass. Takes also care
 *       about retrieving static members of the super class by
 *       accessing these via the using the  derived Class.</LI>
 *   <LI>It adds a handle to the base Class (super_) to enable access
 *       to eventually overridden baseClassfunctions.</LI>
 * </UL>
 * 
 * Invariant: We cannot assign the <code>super_</code> property to
 *   the <code>static_</code> or the prototype chain. The reason
 *   can be explained by the following example.
 * 
 *   If one derives Class C from Class B and
 *                  Class B from Class A. Now he or she can
 *   instantiate an object o of Class C. Any method inherited from
 *   Class B called in the scope of object o will have Class B
 *   as <code>super</code> (because it was asigned to the prototype
 *   chain or the "static chain"). In fact the programmer will expect 
 *   Class A in this case! </p>
 *   A possible solution: the super_ property will be assigned
 *   to the classes constructors and methods of super classes are
 *   called explicitly by method indirection. The following example
 *   shows this solution:
 * 
 * <pre>
 * ClassB
 * {
 *   method aMethod ( ... )
 *   {
 *     // call super method ...
 *     this._indirectedmethod_ = ClassB.super_.aMethod;
 *     this._indirectedmethod_ ( ... );
 *     delete this._indirectedmethod_;
 *   }
 * }
 * </pre>
 *
 * Note: although this function and kind of class definition works
 * quite well it is recommended to use the class definition syntax
 * since object JavaScript 1.2.
 * 
 * @since Object JavaScript 1.0
 * 
 * @param derivedClass: Function: the constructor function of the
 *   class to derive
 * @param baseClass: Function: the constructor function of the base class 
 */
function doInherit ( derivedClass, baseClass )
{
  if ( baseClass == null )
  {
    if ( doInherit.base_ != null )
      baseClass = doInherit.base_;
  }
  
  // Inheritance ... ?
  if ( baseClass != null )
  {
    // ECMA Inheritance, nothing JavaScript specific used.
    // call the constructor with "__proto__" to give it a 
    // chance to differ between calls for instantiation and 
    // calls for inheritance (this one)
    derivedClass.prototype = new baseClass ( "__proto__" );

    // "Repair" constructor (a JavaScript internally used property)
    derivedClass.prototype.constructor = derivedClass;
  
    // Linking back the Super Class:
    derivedClass.super_ = baseClass.prototype;
  }
  else
    derivedClass.prototype.constructor = derivedClass;

  // Static part: always assign a default static_ object to a new class
  var static_constructor = function() {};

  // Inherit the new static <b>OBJECT</b> from the
  // Baseclasses' static object (if existent).
  if ( baseClass != null && baseClass.static_ != null )
    static_constructor.prototype = baseClass.static_;

  // Now construct the Static object (with the inheritance
  // defined above) and link it both to the derived class
  // AND to the prototype of this class!
  derivedClass.static_ = 
    derivedClass.prototype.static_ = new static_constructor;

  // now get the Class name ...
  if ( initPackage.lastPackage_ )
  {
    var cur_package = initPackage.packageList_ [initPackage.lastPackage_];
    var package_name = initPackage.lastPackage_ + ".";
    
    for ( var i in cur_package )
    {
      if ( cur_package [i] == derivedClass )
      {
        derivedClass.prototype.static_.className_ = package_name + i;
        return derivedClass.prototype;
      }
    }
  }

  // no Class name can be determined. In these cases we use
  // the "undefined" value.
  derivedClass.prototype.static_.className_ = "undefined";
  return derivedClass.prototype;
}

/** 
 * Initializes a <code>package</code> within the current scope.
 * The scope depends on the current environment e.g. the
 * browser JavaScript engine. <p>
 *
 * This implementation uses the browser's <code>window</code> object
 * as the default scope. <b>Note</b> that each Frame or Frameset has
 * its own window object and its own function definitions. Hence you
 * have to load classes and initialize packages in each window,
 * framesets and obviously all (i)frames where the class mechanism is
 * used.
 * 
 * @param String: aPackageName: a string defining a package
 *   name with sub-packages e.g. "com.hw.util".
 * 
 * @return Object: the package object that serves as an associative
 *   array for classes. 
 */
function initPackage ( aPackageName )
{
  initPackage.lastPackage_ = aPackageName;

  if ( initPackage.packageList_ [aPackageName] )
    return initPackage.packageList_ [aPackageName];
  
  var packages = aPackageName.split ( "." );
  var root_pkg_name = packages [0];
  var cur_package = window [root_pkg_name];

  if ( !cur_package )
    cur_package = window [root_pkg_name] = {};
  initPackage.rootPackageList_ [root_pkg_name] = cur_package;

  for ( var i = 1; i < packages.length; ++i )
  {
    if ( cur_package [ packages [i] ] == null )
      cur_package [ packages [i] ] = {};
    cur_package = cur_package [ packages [i] ];
  }
  
  initPackage.packageList_ [aPackageName] = cur_package;
  return cur_package;
}

/** 
 * Initialize the Packaging system and create the <code>ojs.object</code>
 * class.
 */
initPackage.packageList_ = {};
initPackage.rootPackageList_ = {};
initPackage.lastPackage_ = null;
initPackage ( "ojs" );


/**
 * (At the moment, only String arguments are supported.)
 */
function importPackage ( arg1 )
{
  var packageName;
  if ( typeof arg1 == "string" )
    packageName = arg1;

  var packageArray = initPackage.packageList_ [packageName];
  if ( !packageArray )
    packageArray = initPackage(packageName);
    
  return packageArray;
}


/**
 * Extends the classpath with <code>top</code> scope. This means that
 * the "classloader" searches the base classes not only in the current
 * scope (that is normally the <code>window</code> or
 * <code>self</code> object witin client-side JavaScript) but also in
 * the outermost frameset <code>top</code>. It also allows to
 * instantiate objects from classes that were only defined in
 * <code>top</code>.
 * If <code>allowClassDuplicates</code> is not set (the default case),
 * an exception will be thrown if a class is defined that already exists
 * in the <code>top</code> "classpath"
 *
 * @param allowClassDuplicates: boolean: if set and not <code>false</code>,
 *   OJS allows the definition of a class with the same name as already
 *   defined in the <code>top</code> "classpath"
 */
function addTopToClasspath( allowClassDuplicates )
{
  if ( ua_isSafari$ )
    return;
  
  defineClass.allowClassDuplicates_ = allowClassDuplicates || false;
  
  // this check seems useless because <script src=""> code is usually executed
  // before code inside <script> tags, no matter in which order they occur in the page
  // (that is why there has to be a try-catch clause around addTopToClasspath):
    for ( var i in defineClass.classCache_ )
    if ( i )
    {
      var text = "Illegal State: 'addTopToClasspath' can only be called before " +
	      "classes (other than 'ojs.Object') are defined";
      alert(text);
      throw text;
    }
    
  // Connect Classcache to the top classcache:
  var classcache_constructor = function() {};
  classcache_constructor.prototype = top.defineClass.classCache_;
  defineClass.classCache_ = new classcache_constructor ();
  
  // Connect the base class to the top baseclass:
  doInherit.base_ = top.doInherit.base_;
  
  // Finally initialize the classpath structure:
  _connectPackage ( top.initPackage.rootPackageList_, window );
}

/**
 * Internal function that "connects" an object <code>topPackage</cdoe>
 * that is normally a <code>package</code> of the frameset
 * into a destination object - the <code>ownPackage</code>.
 * <p>
 * Connecting means that in the destination object a property
 * be created that is "linked" by means of prototyping to the
 * source object's property. As a consequence the properties
 * of the source object can be accessed within the destination
 * object.
 *
 * @param topPackage:Object: the source "package" that will be
 *   cloned to the destination.
 * @param ownPackage:Object: the destination "package" which
 *   is initially empty and will be the destination of new
 *   properties linked with the properties of the source
 *   package.
 */
function _connectPackage ( topPackage, ownPackage )
{
  for ( var i in topPackage )
  {
    if ( !topPackage.hasOwnProperty (i) ||
         typeof topPackage [i] == "function" )
      continue;

    var help_constr = function () {};
    help_constr.prototype = topPackage [i];
    ownPackage [i] = new help_constr ();
    _connectPackage ( topPackage [i], ownPackage [i] ); 
  }
}

  /** 
   * Constructor for all JavaScript Objects. This constructor is 
   * considered to be empty because any check for "__proto__" would
   * be senseless.
   */
  ojs.Object = function ()
  {
  }
  class$ = doInherit ( ojs.Object );
  
  /** 
   * Returns true if a class is an instance of another class. The
   * other class might be given by a class object (strong) or a class
   * string (weak). Strong means, that the class is of this type and
   * the class is defined in the same scope. A weak check might result
   * in a result that is true even the class is defined in another
   * scope (or window).
   * 
   * @signature (aClass:Function)
   * @signature (aClassName:string)
   * 
   * @param aClass a class defined by its constructor function like
   *   <code>ojs.Object</code>.
   * @param aClassName a class defined by its class name like
   * <code>&quot;ojs.Object&quot;</code>.
   */
  class$.instanceOf = function ( aClass )
  {
    if ( typeof aClass == "function" )
    {
      var class_iter = this.constructor;
      while ( class_iter != null )
      {
        if ( class_iter.static_ == aClass.static_ )
          return true;
        class_iter = class_iter.super_;
      }
    }
    else if ( typeof aClass == "string" )
    {
      var class_iter = this.constructor;
      while ( class_iter != null )
      {
        if ( class_iter.static_.getClassName () == aClass )
          return true;
        class_iter = class_iter.super_;
      }
    }
    
    return false;
  }
  
  /** 
   * Returns a function that redirects to the given method
   * in the specified scope. This can be used in event handlers or other
   * techniqeus that require callback functions.
   *
   * @param aScope: Object: the object that provides the scope
   * @param aMethod: Function: the function that should be called in the 
   * given scope
   *  
   * @return Function: a function that redirects to the given method
   * in the specified scope
   */
  class$.static_.getMethodRedirector = function ( aScope, aMethod )
  {
    return function()
    {
      return aMethod.apply(aScope, arguments);
    }
  }

  /** 
   * Returns the full qualified class name of the class.
   * 
   * @return string: a string containing the class name.
   */
  class$.static_.getClassName = function ()
  {
    return this.className_;
  }
  doInherit.base_ = ojs.Object;

  /**
   * Returns the type of the given object. It can be used if <code>typeof</code> is not exact
   * enough. The following return strings are supported (they should be self explanatory):
   * <ul>
   *   <li>undefined</li>
   *   <li>null</li>
   *   <li>string</li>
   *   <li>number</li>
   *   <li>boolean</li>
   *   <li>array</li>
   *   <li>function</li>
   *   <li>object (for everything else)</li>
   * </ul>
   * 
   * @param anObject: Object: the object for determining its type
   
   * @return String: the type of anObject
   */
  class$.static_.getType = function ( anObject ) 
  {
    var index, id;
    var type_of_result = typeof anObject; 

    if (type_of_result == "undefined")
      return "undefined";
    if (anObject == null)
      return "null";
    if ((type_of_result == "object" || anObject.constructor == "[function]") || (anObject.constructor == "(Internal function)")) {
      // Konqueror only returns "[function]" whereas Safari returns "(Internal function)"
      var ctor_str = anObject.constructor + "";
      if ((anObject.constructor === [].constructor) || (ctor_str.indexOf("Array") >= 0))
        return "array";
      if ((anObject.constructor === "".constructor) || (ctor_str.indexOf("String") >= 0))
        return "string";
      if ((anObject.constructor === new Boolean().constructor) || (ctor_str.indexOf("Boolean") >= 0))
        return "boolean";
      if ((anObject.constructor === new Number().constructor) || (ctor_str.indexOf("Number") >= 0))
        return "number";
      if (anObject.constructor === new Function().constructor ||
          (typeof anObject.constructor == "undefined" && (anObject + "").indexOf("function") >= 0)) // IE
        return "function";
      else
        return "object";
    }
    else
    {
      return type_of_result;
    }
  }
   
/** 
 * Loads a class or a package into the current scope. The function
 * was prepared for dynamic class loading and is deprecated now.
 * 
 * @param String: aClassName: a string defining a class name
 *   or even a whole package.
 * 
 * @deprecated since Object JavaScript 1.2.
 *  Reasons:
 *  <ul>
 *    <li>
 *      Dynamic class loading is considered to be too complex because
 *      on the server side the constraints will provide a JavaScript
 *      hell even for very experienced programmers. On the client side
 *      class loading can only be done synchronously which is in fact
 *      only a technique that can be done during the loading of a page
 *      or by applets. During page loading we cannot use constructors
 *      or constructor functions because an additional (dynamically
 *      written) &lt;script src...&gt; will only be valid in the next
 *      script block. Applets could be used synchronously but only
 *      after applet initialization. Hence we should keep our hands
 *      from such techniques. If ever we could re-use the "loadClass"
 *      mechanism to do this.
 *  </ul>
 * @see #addTopToClasspath()
 */
function loadClass ( aClassName )
{
}

/** 
 * This function implements ECMA conform inheritance for JavaScript
 * classes like <code>doInherit</code> does. The underlying method is
 * a little bit different from doInherit because we write a class
 * within a function body. This body looks like:
 *
 * <pre>
 * function xyz ( class$ )
 * {
 *   class$.method = function ( ... )
 *   {
 *   }
 * }
 * </pre>
 *
 * This function is called <b>class definition function</b>. It is
 * associated with a class name by means of
 * <code>defineClass</code>. Here all necessary constructs for a
 * <i>real</i> ECMA conform inheritance are produced and the
 * constructor (that is either explicitly defined with a method called
 * constructor or that is otherwise implicitly constructed) is
 * accociated with the package and the class name.</p>
 * 
 * <p>This implementation relies on the internals of <code>doInherit
 * </code> because the needs of this function are somewhat different.
 * <code>doInherit</code> implies that it has a constructor function
 * and returns the class prototype. <code>defineClass</code> implies
 * that the static object is inherited correctly and no class
 * constructor exists. Hence we have to copy the internals of 
 * <code>doInherit</code> Another dependency is the <code>initPackage
 * </code> function - this function is used to initialize the
 * classes' packages.
 *
 * @signature (String aClassName, Function theDefinition)
 * @signature (String aClassName, String baseClass, Function
 *   theDefinition)
 * @signature (String aClassName, Function baseClass, Function
 *   theDefinition)
 *
 * @param aClassName a string defining the whole qualified class name
 * @param theDefinition the definition function of the class to be
 *   defined
 * @param baseClass the super class of the new class
 * 
 * @since Object JavaScript 1.2
 */
function defineClass ( aClassName, arg2, arg3 )
{
  if ( defineClass.classCache_ [aClassName] && !defineClass.allowClassDuplicates_ && !ua_isSafari$ )
  {
    // class already defined
    var text = "Illegal State: class " + aClassName + " already defined";
    alert(text);
    throw text;
  }

  // Rename unnamed parameters 
  var baseClass;
  var theDefinition = arg2;
  if ( arg3 )
  {
    theDefinition = arg3;
    baseClass = arg2;
  }

  // Separate Class and Package Name ...
  var sep = /^((.*)\.)?([^.]+)$/;
  var arr = sep.exec ( aClassName );
  var package_name = arr [2];
  var unqualified_class_name = arr [3];
  var class_package;

  if ( package_name )
    class_package = initPackage ( package_name );
  else
    class_package = window;

  // get the *real* baseClass object. But be aware of classes that
  // have not been created by defineClass ...
  if ( baseClass == null )
    baseClass = doInherit.base_;
  else
    if ( typeof baseClass == "string" )
    {
      var desired = defineClass.classCache_ [baseClass];
      if ( desired )
        baseClass = desired;
      else
        try
        {
          var class_function;
          class_function = eval ( baseClass );
//          if ( typeof class_function != "function" )
//            class_function = top.eval ( baseClass );
          if ( typeof class_function != "function" )
            throw baseClass + " is not a function";
          baseClass = class_function;
        }
        catch ( e )
        {
          var text = "'" + baseClass + "' is not a class (" + e + ")";
          alert(text);
          throw text;
        }
    }
//else if ( typeof baseClass == "undefined" ) 
//  baseClass = top.eval(baseClass.static_.getClassName());
  
  // Step 1: Static - always assign a default static_ object to a new
  // class.
  var static_constructor = function() {};
  // [The former technique of using the Function constructor does not work with Konqueror/Safari.]

  var base_static_onclassload, base_static_onfinalization;

  // Inherit the new static <b>OBJECT</b> from the
  // Baseclasses' static object (if existent).
  if ( baseClass != null && baseClass.static_ != null )
  {
    static_constructor.prototype = baseClass.static_;
    base_static_onclassload = baseClass.static_.onClassLoad;
    base_static_onfinalization = baseClass.static_.onFinalization;
  }

  // ECMA Inheritance, nothing JavaScript specific used.
  // call the constructor with "__proto__" to give it a 
  // chance to differ between calls for instantiation and 
  // calls for inheritance (this one)
  var class_prototype;
  if ( baseClass != null )
    class_prototype = new baseClass ( "__proto__" );
  else
    class_prototype = {};

  // Step 2: Initialize the "class" object and call the class
  // definition function.
  class_prototype.super_ = baseClass.prototype;
  class_prototype.superConstructor_ = baseClass;
  class_prototype.static_ = new static_constructor;
  class_prototype.static_.className_ = aClassName;
  var mark_constructor = class_prototype.constructor;

  theDefinition ( class_prototype );

  // Step 3: get/make the constructor (if any) and "wire" the prototype
  // chain.
  if ( class_prototype.constructor == mark_constructor )
    class_prototype.constructor = 
      function () 
      { 
        if (baseClass)
          baseClass.apply (this, arguments);
      }

  var derived_class;
  defineClass.classCache_ [aClassName]
    = class_package [unqualified_class_name]
    = derived_class 
      = class_prototype.constructor;
  derived_class.prototype = class_prototype;

  // Step 4: Link the static object both to the derived class
  // AND to the prototype of this class!
  derived_class.static_ = 
    derived_class.prototype.static_ = class_prototype.static_;
  derived_class.super_ = baseClass.prototype;

  // Step 5: Call the static_.onClassLoad method (if it exists)
  if ( class_prototype.static_.onClassLoad != base_static_onclassload )
    class_prototype.static_.onClassLoad ();
  
  // Step 6: register the static finalizer method (if it exists)
  if ( class_prototype.static_.onFinalization != base_static_onfinalization )
    defineClass.finalizerList_[defineClass.finalizerList_.length] = 
      { function_: class_prototype.static_.onFinalization, scope_: class_prototype.static_ };
      
  class_package = null;
}
defineClass.classCache_ = {};
defineClass.finalizerList_ = [];
defineClass.allowClassDuplicates_ = false;

//--------------------------------------------------------------------
//                   Class Finalization & Logging
//--------------------------------------------------------------------

defineClass.doLog = function ( aText )
{
  if ( typeof top.gDebug_ != "undefined" )
    top.gDebug_.debug ( aText );
}

defineClass.unloadHandler = function( anEvent )
{
  defineClass.doLog ( "Start of unloadHandler(), window:" + window.name );

  // dispatch the uda unload event via the uda window instance
  try
  {
    //# neccessary browser dependency (because IE has access denied if You try to access event
    //# object in other frame)
    com.hyperwave.uda.core.Window.static_.dispatchUnloadEvent(window, anEvent ? anEvent : window.event);
  }
  catch ( e )
  {
    // no classes, no uda window, or errors in unload handlers!
    // reporting is only possible in debug cases
    defineClass.doLog ( "Error in dispatchUnloadEvent, window:" + window.name );
  } 
  
  defineClass.finalize(window);
  if ( window.detachEvent )
    window.detachEvent("onbeforeunload", defineClass.unloadHandler);
  else if ( window.removeEventListener )
  {
    window.removeEventListener("unload", defineClass.unloadHandler, true);
    window.removeEventListener("unload", defineClass.unloadHandler, false);
  }
  else
    window["onunload"] = null;

  if ( window.CollectGarbage )
    window.CollectGarbage ();    
  defineClass.doLog ( "End of unloadHandler(), window:" + window.name );
}

defineClass.finalize = function( aWindow )
{
  defineClass.doLog ( "Start finalize(), window:" + window.name + ", aWindow: " + aWindow.name );

  // call all registered <code>static_.onFinalization</code> methods
  for ( var i = 0; i < defineClass.finalizerList_.length; ++i )
  {
    try
    {
      defineClass.doLog ( "Finalize Class:" + defineClass.finalizerList_[i].scope_.getClassName() );
      defineClass.finalizerList_[i].function_.call(defineClass.finalizerList_[i].scope_, aWindow);
    }
    catch ( e )
    {
      defineClass.doLog ( "Error during finalization, Class:" + defineClass.finalizerList_[i].scope_.getClassName() );
    }
  }
    
  // if we are within the frameset with addTopToClasspath also notify top
  if ( window != top )
  {
    if ( top.defineClass )
      top.defineClass.finalize ( window );
    registry$._registry = [];
  }
  else if ( (window == top) && (!frames || frames.length == 0) )
  {
    // clean registry in dialog windows (cannot be done in framesets because top is unloaded 1st):
    registry$._registry = [];
  }
  else if ( window == aWindow && window == top )
    registry$._registry = [];
  defineClass.doLog ( "End finalize(), window:" + window.name + ", aWindow: " + aWindow.name );
}

if ( window.attachEvent )  //# browser dependency IE
  window.attachEvent("onbeforeunload", defineClass.unloadHandler);
else if ( window.addEventListener )  //# browser dependency W3C
  window.addEventListener("unload", defineClass.unloadHandler, false);
else
 window.onunload = defineClass.unloadHandler;

//--------------------------------------------------------------------
//                   Window Close Overloading
//--------------------------------------------------------------------
if ( window.CollectGarbage )  // online necessary in IE (and dangerous in Mozilla)
{
	window.close = function ()
	{
	  closeChecker.close_ = true;
	}
	
	function closeChecker ()
	{
	  if ( closeChecker.close_ )
	  {
	    defineClass.doLog ( "Triggered closeChecker(), window:" + window.name );
	    clearInterval ( closeChecker.id_ );
	
	    document.open ();
	    document.writeln ( "<script>window.close();<\/script>" );
	    document.close ();
	    
	    defineClass.doLog ( "End closeChecker, window:" + window.name );
	  }
	}
	
	closeChecker.id_ = setInterval ( closeChecker, 250 );
}

//--------------------------------------------------------------------
//                        Unique ID Generator
//--------------------------------------------------------------------
function getUniqueId()
{
  if ( window != top && top.getUniqueId )
    return top.getUniqueId();
  else
    return getUniqueId._uniqueIdCounter$++;
}
getUniqueId._uniqueIdCounter$ = new Date().valueOf();

//--------------------------------------------------------------------
//                       Global Object Registry
//--------------------------------------------------------------------
function registry$()
{
}
registry$._registry = [];

/**
 * Puts an object into the registry. This object is associated with a browser window.
 * The method returns the unique identifier that can be used in <code>registry$.get</code>.
 * The registry is distributed over the frames of a frameset in a way that each frame holds
 * the objects that are associated with this frame.<p>
 * Mind that if an object has already been put into the registry it will be contained twice
 * which should be avoided (but due to performance issues there is no lookup before adding it)!
 *
 * @param anObject: object: an object that should be stored in the registry and associated with
 *   the returned id
 * @param aWindow: object | void: an optional argument that defines the window where the object resides,
 *   the default is the window where Object.js is loaded
 *
 * @return int: a unique identifier for the registered object
 */
registry$.put = function(anObject, aWindow)
{
  var win = aWindow || window;
  if ( (win != window) && win.registry$ )
    return win.registry$.put(anObject, win);
  else 
  {
    var id = getUniqueId();
    registry$._registry[id] = anObject;
    return id;
  }
}

/**
 * Returns the object registered with the given identifier or <code>null</code> if none is found.
 * The identifier should be obtained when registering via <code>registry$.put</code>.<br>
 * This implementation first looks for an entry in the local registry and if none is found it starts
 * with the lookup in the top frame, which searches all its subframes.
 *
 * @param anId: int: a unique identifier that was returned by <code>registry$.put</code>
 *
 * @return Object: the object registered with the given identifier or <code>null</code>
 *   if none is found
 */
registry$.get = function(anId)
{
  if ( registry$._registry[anId] )      //1st, search in local frame
    return registry$._registry[anId];
  else if ( top.registry$ )             //2nd, search via top registry (if there is one)
    return top.registry$._get(anId);
  else                                  //3rd, search in sub frames (very unlikely)
    return registry$._get(anId);
}

/**
 * Helper method that returns the object registered with the given identifier or <code>null</code> if none is found.
 * The identifier should be obtained when registering via <code>registry$.put</code>.<br>
 * This implementation first looks for an entry in the local registry and if none is found it starts
 * with the lookup in all its subframes (even recursive in those that did not load Object.js).
 *
 * @param anId: int: a unique identifier that was returned by <code>registry$.put</code>
 * @param aFrame: Object: an optional frame reference that is used internally
 *
 * @return Object: the object registered with the given identifier or <code>null</code>
 *   if none is found
 */
registry$._get = function(anId, aFrame)
{
  var aFrame = aFrame || window;
  
  if ( registry$._registry[anId] )
    return registry$._registry[anId];
  else if ( aFrame.frames && aFrame.frames.length > 0 )
  {
    // search in all frames:
    for ( var i = 0; i < aFrame.frames.length; ++i )
    {
      if ( aFrame.frames[i].registry$ && aFrame.frames[i].registry$._registry )
      {
        var obj = aFrame.frames[i].registry$._get(anId);
        if ( obj )
          return obj;
      }
      else {
        var obj = registry$._get(anId, aFrame.frames[i]);
        if ( obj ) {
          return obj;
        }
      }
    }
    return null;
  }
}

/**
 * Removes the object that was registered with the given identifier from the registry. 
 * If there is no such object, the registry is not touched. If such an object exists
 * it is returned (otherwise <code>null</code> is returned).
 *
 * @param anId: int: a unique identifier that was returned by <code>registry$.put</code>
 *
 * @return Object: the object registered with the given identifier that has been removed 
 *   or <code>null</code> if none is found
 */
registry$.remove = function(anId)
{
  if ( top.registry$ )
    return top.registry$._remove(anId);
  else
    return registry$._remove(anId); 
}
 
/**
 * Helper method that removes the object that was registered with the given identifier 
 * from the registry. If there is no such object, the registry is not touched. If such an object exists
 * it is returned (otherwise <code>null</code> is returned).
 *
 * @param anId: int: a unique identifier that was returned by <code>registry$.put</code>
 * @param aFrame: Object: an optional frame reference that is used internally
 *
 * @return Object: the object registered with the given identifier that has been removed 
 *   or <code>null</code> if none is found
 */
registry$._remove = function(anId, aFrame)
{
  var aFrame = aFrame || window;
   
  if ( registry$._registry[anId] )
  {
    var obj = registry$._registry[anId];
    delete registry$._registry[anId];
    return obj;
  }
  else if ( aFrame.frames && aFrame.frames.length > 0 )
  {
    // search in all frames:
    for ( var i = 0; i < aFrame.frames.length; ++i )
    {
      if ( aFrame.frames[i].registry$ && aFrame.frames[i].registry$._registry )
      {
        var obj = aFrame.frames[i].registry$._remove(anId);
        if ( obj )
          return obj;
      }
      else
        return registry$._remove(anId, aFrame.frames[i]);
    }
    return null;
  }
}
 
//--------------------------------------------------------------------
//                   HAF Compatibility Library
//--------------------------------------------------------------------
// The following functions are used to extend the default behavior
// of the JavaScript Engine. These are mostly encoders and decoders
// for UTF8 and escaped UTF8.

// IMPORTANT:
// Note that these functions are to be synched in ojs.js, ojs1.js
// and within the Clientlib (Object.js).

// Global variable that is true if lambda expressions are
// supoorted.


/**
 * Checks whether Lamda expressions are supported or not.
 * @return boolean: true if lambda expressions are supported.
 */
function lambdaExpressionsSupported ()
{
  if ( lambdaExpressionsSupported.supported_ )
    return lambdaExpressionsSupported.supported_;

  lambdaExpressionsSupported.supported_ =
    (" ".replace ( " ", function () { return "x" } ) == "x" );

  return lambdaExpressionsSupported.supported_;
}  

/**
 * Encodes a character string (that exists of UCS2 characters) to
 * a character string that is UTF8 encoded. The characters of the
 * source string are transcoded to their one, two or three "byte"
 * representation in UTF8. As a consequence the final string contains
 * only characters with codes between 0 and 255.<p>
 *
 * For example: the German umlaut &?uml; (small "o" with quotes) has
 *   the UCS2 (Unicode) character code 246. Constructing a string
 *   with this character can be done by
 *     <code>String.fromCharCode (246)</code>.
 *   If this string is converted with this function this character
 *   is transcoded to its 2-byte representation in UTF-8 (195, 182).
 *   The resulting string will contain 2 characters with the character
 *   codes above.
 *
 * This implementation uses two strategies:
 * <ul>
 *   <li>For IS6.2 and lower it uses JavaScript Lambda Expressions to get
 *     better performance for long strings (in comparision to normal
 *     string operations).
 *   <li>For DANTE+ the built in method "fromEncoding" (C++) is used
 *     to get another boost (approx. 30 times faster).
 * </ul>
 *
 * @param theText: string: The text that has to be transcoded to
 *   UTF8.
 * @return string: the converted string.
 */
if ( !lambdaExpressionsSupported () )
{
  encodeUtf8 = function ( theText )
  {
    var utf = [];
    var j = 0;
    for ( var n = 0; n < theText.length; ++n )
    {
      // ermitteln des Unicodes des aktuellen Zeichens
      var c = theText.charCodeAt(n);
      // alle Zeichen von 0-127 => 1byte
      if (c < 128)
        utf [utf.length] = String.fromCharCode(c);
      // alle Zeichen von 127 bis 2047 => 2byte
      else if (c < 2048)
      {
        utf [utf.length] = String.fromCharCode((c >> 6) | 192)
                        + String.fromCharCode((c & 63) | 128);
      }
      // alle Zeichen von 2048 bis 66536 => 3byte
      else
      {
        utf [utf.length] = String.fromCharCode((c >> 12) | 224)
                        + String.fromCharCode(((c >> 6) & 63) | 128)
                        + String.fromCharCode((c & 63) | 128);
      }
    }
    return utf.join ("");
  }
  }
else
{
  encodeUtf8 = function ( theText )
  {
    return theText.replace ( /(.)|(\s)/g, encodeUtf8.lambdaEncode );
  }

  // Internal Lambda Funtion for encodeUTF8. This Lambda function
  // matches any character and translates the character to one
  // two or three byte representations concerning to the UTF8
  // algorithm. Note that this function must be kept in sync
  // with the regular expression of the caller.
  encodeUtf8.lambdaEncode = function ( c1 )
  {
    var c = c1.charCodeAt(0);

    // alle Zeichen von 0-127 => 1byte
    if (c < 128)
      return c1;

    // alle Zeichen von 127 bis 2047 => 2byte
    if (c < 2048)
      return ( String.fromCharCode((c >> 6) | 192)
               + String.fromCharCode((c & 63) | 128) );

    // alle Zeichen von 2048 bis 66536 => 3byte
    return ( String.fromCharCode((c >> 12) | 224)
             + String.fromCharCode(((c >> 6) & 63) | 128)
             + String.fromCharCode((c & 63) | 128) );
  }
}

/**
 * Checks whether a string is UTF8 encoded or not. This is done
 * with a Regular Expression that matches UTF8-patterns.The following
 * constraints have to be fulfilled:
 *
 * <ul>
 *   <li>The string has to contain only characters with codes between 0 and
 *     255.
 *   <li>The patterns must be conform to the UTF8 encoding for UCS2. This
 *     means that only 1, 2 or 3 Byte representations are allowed.
 * </ul>
 *
 * @param theText: string: The text that has to be checked.
 * @return boolean: true if the text is a UTF-8 text.
 */
function testUtf8 ( theText )
{
  pattern =
    /([\x00-\x7F])|([\xC0-\xDF][\x80-\xBF])|([\xE0-\xEF][\x80-\xBF][\x80-\xBF])/g;
  var res = theText.replace ( pattern, "" );
  return res.length == 0;
}

/**
 * Decodes an UTF-8 encoded string into the internal JavaScript
 * (UCS-2) representation. It forms the inverse function of
 * <code>encodeUtf8</code>.
 *
 * This implementation uses either lambda expressions or simple
 * array operations.
 *
 * @param theText: string: a text that should be decoded from
 *   UTF-8 representation back to "JavaScript".
 * @return string: the decoded string. Note that the
 *   original text will be returned if the text is not a "real"
 *   UTF-8 string.
 */
if ( !lambdaExpressionsSupported () )
{
  decodeUtf8 = function ( theText )
  {
    var plaintext = [];
    var i = 0;
    var c = c1 = c2 = 0;
    
    while ( i < theText.length )
    {
      c = theText.charCodeAt(i);
      if (c < 128)
      {
        plaintext [plaintext.length] = String.fromCharCode(c);
        ++i;
      }
      else if ((c > 191) && (c < 224))
      {
        c2 = theText.charCodeAt(i + 1);
        if ( c2 >= 0x80 && c2 <= 0xBF  )
        {
          plaintext [plaintext.length] =
            String.fromCharCode(((c & 31) << 6) | (c2 & 63));
          i += 2;
        }
        else
          return theText;
      }
      else
      {
        c2 = theText.charCodeAt(i + 1);
        c3 = theText.charCodeAt(i + 2);
        if ( c2 >= 0x80 && c2 <= 0xBF && c3 >= 0x80 && c3 <= 0xBF )
        {
          plaintext [plaintext.length] =
            String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
          i += 3;
        }
        else
          return theText;
      }
    }
    return plaintext.join ("");
  }
}
else
{
  decodeUtf8 = function (theText)
  {
    if ( !testUtf8 ( theText ) )
      return theText;
    pattern = /([\xC0-\xDF][\x80-\xBF])|([\xE0-\xEF][\x80-\xBF][\x80-\xBF])/g;

    return theText.replace ( pattern, decodeUtf8.lambdaDecode );
  }

  // Internal lambda function that matches the two byte or three
  // byte sequences and constructs the original character.
  // The parameters of these function depend on the regular expression
  // of the decodeUtf8 function.
  
  decodeUtf8.lambdaDecode = function ( whole, two, three )
  {
    if ( two )
    {
      c = two.charCodeAt (0);
      c2 = two.charCodeAt(1);
      return String.fromCharCode(((c & 31) << 6) | (c2 & 63));
    }

    if ( three )
    {
      c = three.charCodeAt (0);
      c2 = three.charCodeAt(1);
      c3 = three.charCodeAt(2);
      return String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
    }
  }
}

/**
 * Encodes a string into its "escaped-utf-8" representation.  This
 * means that all characters are firstly encoded into utf-8 and in a
 * subsequent step the resulting bytes are "escaped" with %CC.<p>
 *
 * Additionally a set can be given that defines character codes that
 * are not to be encoded. They will be simply transferred to the
 * returned string as they are.<p>
 *
 * Normally this function will not be called directly - it is used in
 * "encodeURIxxxx" functions instead.<p>
 *
 * This implementation also defines two three sets that have been
 * produced with the following code:
 *
 * <pre>
 * function invert ( a )
 * {
 *   var o = [];
 *   for ( var i = 0; i < a.length; ++i )
 *   {
 *     o [a.charCodeAt(i)] = 1;
 *   }
 *   writeln ( "  " + o.toSource ().replace ( / /g, "" ) );
 * }
 * var s1 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!*";
 * writeln ( "escapeUtf8.encodeURIComponentSet = " );
 * invert ( s1 );
 * var s2 = "()'" + ";/?:@&=+$,~" + s1 + "#";
 * writeln ( "escapeUtf8.encodeURISet = " );
 * invert ( s2 );
 * </pre>
 *
 * The sets are used to define the behavior of the
 * <code>encodeURI</code> and <code>encodeURIComponent</code>
 * functions.
 *
 * @param aString: string: the string that should be encoded.
 * @param aSet: array: an array of flags that defines the character
 *   codes of characters that should not be transcoded. Each character
 *   code with a nonzero value in the set will be simply transferred to
 *   the result without any conversion.
 * @return string: the original string in "escaped-utf-8" encoding.
 */
function escapeUtf8 ( aString, aSet )
{
  var i2a = ["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"];
  var u = encodeUtf8 ( aString );
  var a = [];
  if ( aSet == null )
    aSet = escapeUtf8.emptySet;

  for ( var i = 0; i < u.length; ++ i )
  {
    var c = u.charCodeAt (i);
    if ( aSet[c] )
      a [a.length] = u.charAt(i);
    else
      a [a.length] = "%" + i2a [c >> 4] + i2a [c & 0xf ];
  }

  return a.join ( "" );
}

// Sets for encodeURI and encodeURIComponent that are internally
// used.
escapeUtf8.emptySet = {};

escapeUtf8.encodeURIComponentSet = 
  [0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,1,,,1,1,,1,1,1,1,1,1,1,1,
   1,1,,,,,,,,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,,,,,1,
   ,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
escapeUtf8.encodeURISet = 
  [0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,1,1,,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
   1,1,1,1,1,1,1,1,,1,,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
   1,1,1,,,,,1,,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,,,,1]

/**
 * Encodes a URI Component part into escaped UTF-8 encoding
 * as defined in ECMA 262-3. The set of reserved characters
 * is more strict as in the standard and is defined with:
 * "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!~*"
 *
 * @param anObject: object: an object (that is normally a portionof a
 *   URI) that should be converted to a string and
 *   escaped-utf8-encoded. In case of a string the string will be used -
 *   if an Object is used the <code>toString</code> method of the object
 *   will be called first. In the "undefined" case, or when
 *   <code>null</code> will be used "undefined" will be returned.
 * 
 * @return string: the encoded URI portion in escaped-utf8 encoding.
 */
function encodeURIComponent ( anObject )
{
  switch ( typeof anObject )
  {
    case "undefined":
      return "undefined";
    case "string":
      return escapeUtf8 ( anObject, escapeUtf8.encodeURIComponentSet );
    default:
      return escapeUtf8 ( anObject.toString(), escapeUtf8.encodeURIComponentSet );
  }
}

/**
 * Encodes a URI as defined in ECMA 262-3. It is strongly recommended
 * that you DO NOT USE this function. Use partial escaping of URLs
 * (or classes that help you with this task) instead.
 *
 * @param aString: string: a string that contains a URI that should
 *   be encoded to be conform to RFC 2396.
 * @return string: the encoded URI
 */
function encodeURI ( aString )
{
  return escapeUtf8 ( aString, escapeUtf8.encodeURISet );
}

/**
 * Converts a URI that was formerly converted with <code>encodeURI</code>
 * to Escaped-UTF8 into its original form (ECMA 262-3). This function
 * works in a way that leads to undesirable results (sometimes). It is
 * strongly recommended to divide a URL into its distinct parts and
 * decode these parts in different steps.
 *
 * @deprecated since 2003-06-17
 */
function decodeURI ( aString )
{
  throw "Illegal Function (Object JavaScript Support Library.)";
}

/**
 * Decodes an "escaped-utf-8" encoded portion of a URL (or something
 * else) into its original character string.<p>
 *
 * Note that on the server side this implementation is NOT necessary.
 *
 * @param anObject: object: an object (that is normally a portionof a
 *   URI) that should be converted from escaped-utf8 encoding into
 *   the original string. In case of a string the string will be used -
 *   if an Object is used the <code>toString</code> method of the object
 *   will be called first. In the "undefined" case, or when
 *   <code>null</code> will be used "undefined" will be returned.
 * @return string: the original character string
 */
if ( typeof decodeURIComponent == "undefined" )
{
  decodeURIComponent = function ( anObject )
  {
    var aString;
    switch ( typeof anObject )
    {
      case "undefined":
        aString = "undefined";
      case "string":
        aString = anObject;
        break;
      default:
        aString = anObject.toString ();
    }

    var a = [];
    var conv = { "0":0,  "1":1,  "2":2,  "3":3,
                 "4":4,  "5":5,  "6":6,  "7":7,
                 "8":8,  "9":9,  "A":10, "B":11,
                 "C":12, "D":13, "E":14, "F":15 };
  
    var i = 0;
    while ( i < aString.length )
    {
      var c = aString.charCodeAt ( i );
      if ( c == 37 /* "=" */ )
      {
        var c1 = conv[aString.charAt ( i+1 )];
        var c2 = conv[aString.charAt ( i+2 )];
        if ( isNaN (c1) || isNaN (c2) )
        {
          a [a.length] = String.fromCharCode (c);
          ++i;
        }
        else
        {
          a [a.length] = String.fromCharCode ( (c1 << 4) + c2 );
          i += 3;
        }
      }
      else
      {
        a [a.length] = String.fromCharCode (c);
        ++i;
      }
    }
    return ( decodeUtf8 ( a.join ( "" ) ) );
  }
}

/**
 * Encodes an arbitrary URI path by encoding its path components.
 * The path will be splitted and then encoded by means of
 * "encodeURIComponent". Finally it will be returned by
 * joining the segments with slashes.
 *
 * @param aURI: string: the path segments that should be encoded
 * @return string: the encoded path information
 */

function encodeURIPath ( aURI )
{
  var components = aURI.split('/');
  for (var i=0; i<components.length; i++) {

    components[i] = encodeURIComponent(components[i]);
  }
  return components.join('/');
}

/** 
 * IE 5.5 compatibility library.
 * This library defines the two methods <code>apply</code> and
 * <code>call</code> for IE 5.5. Note that since IE 6.0 and obviously
 * for all Netscape derivates this will work well. The code for both
 * functions is similar to <code>newInstanceOf</code> and is
 * deprecated per definition.
 */

if ( !Function.prototype.apply )
  Function.prototype.apply = function ( theObject, theArguments )
  {
    theObject.$f$ = this;
    var ret;
    switch ( theArguments.length )
    {
      case 0:
        ret = theObject.$f$ ();
        break;
      case 1:
        ret = theObject.$f$ ( theArguments [0] );
        break;
      case 2:
        ret = theObject.$f$ ( theArguments [0], theArguments [1] );
        break;
      case 3:
        ret = theObject.$f$ ( theArguments [0], theArguments [1], theArguments [2] );
        break;
      case 4:
        ret = theObject.$f$ ( theArguments [0], theArguments [1], theArguments [2], theArguments [3] );
        break;
      case 5:
        ret = theObject.$f$ ( theArguments [0], theArguments [1], theArguments [2], theArguments [3], theArguments [4] );
        break;
    }
    delete theObject.$f$;
    return ret;
  }
  
if ( !Function.prototype.call )
  Function.prototype.call = function ( theObject )
  {
    theObject.$f$ = this;
    var ret;
    switch ( arguments.length )
    {
      case 1:
        ret = theObject.$f$ ();
        break;
      case 2:
        ret = theObject.$f$ ( arguments [1] );
        break;
      case 3:
        ret = theObject.$f$ ( arguments [1], arguments [2] );
        break;
      case 4:
        ret = theObject.$f$ ( arguments [1], arguments [2], arguments [3] );
        break;
      case 5:
        ret = theObject.$f$ ( arguments [1], arguments [2], arguments [3], arguments [4] );
        break;
      case 6:
        ret = theObject.$f$ ( arguments [1], arguments [2], arguments [3], arguments [4], arguments [5] );
        break;
    }
    delete theObject.$f$;
    return ret;
  }

/**
 * Returns an array holding all functions that participate in the current execution stack.
 * The first element holds the last entry in the stack and so on (as it is typical for stack traces).
 * Attention: Does not work for Safari at the moment
 * (no arguments.caller and only provides the ECMA properties name and message for error objects),
 * it always returns an empty array there.<p>
 * Example:<br>
 * <code>
 * function a(str1, str2) {
 *   return b(str1);
 * }
 *   
 * function b(aString) {
 *   return c(aString);
 * }
 *   
 * c = function(anotherString) {
 *   return getStackTrace();
 * }
 * </code>
 * Calling <code>a(x,y)</code> returns the following entries:
 * <code>
 * anonymous(anotherString)
 * b(aString) 
 * a(str1, str2)
 * </code>
 * Remark: The Mozilla implementation does not hold the function parameters as abstract variables
 * but the concrete values.
 *
 * @return String[]: an array of stack trace entries
 */
function getStackTrace() 
{
  // per default, we ignore one stack trace entry (the one of getStackTrace itself):
  var ignoredEntries = arguments.length > 0 ? arguments[0] : 1;
  var ret_val = [];
  var regexp = /function([^{}]+)/;

  if ( typeof(arguments.caller) != "undefined" )
  { // IE, not ECMA
    // FIXXXME: arguments.caller is null in the case of OJS 1.2 (works if getStackTrace is a simple function)
    for (var a = arguments.caller; a != null; a = a.caller) 
    {
      var func = a.callee.toString().match( regexp )[0];
      ret_val[ret_val.length] = ((func == null) || (func.length == 0) ? "anonymous" : func);
      if ( a.caller == a )
      {
        ret_val[ret_val.length] = "*";
        break;
      }
    }
  }
  else 
  { // Mozilla, not ECMA - fake an exception so we can get Mozilla's error stack
    var test_exception;
    try
    {
      this_throws.an_exception;
    }
    catch(test_exception)
    {
		  var m, name;
		  
		  if ( !test_exception || !test_exception )
		    return ret_val;
		
		  var stacklist = test_exception.stack.split("\n");
		
		  for ( var i = 0; i < stacklist.length - 1; ++i )
		  {
		    var framedata = stacklist[i];
		
		    m = framedata.match(/^(\w*)\s*\(\s*([^\)]*)/);
		
		    if ( !m || m.length < 2 )
		      continue;
		
		    name = m[1] || "anonymous";
		
		    ret_val[ret_val.length] = name + "(" + (m.length > 2 ? m[2] : "") + ")";
		  }
		  // remove ignored entries
		  if ( ignoredEntries )
		    ret_val = ret_val.slice(ignoredEntries);
    }
  }
  return ret_val;
}

/** 
 * Safari compatibility library.
 * This library defines the method <code>hasOwnProperty</code> which returns
 * <code>true</code> if an object has a noninherited property with the given name.
 */

if ( !Object.prototype.hasOwnProperty )
{
  Object.prototype.hasOwnProperty = function ( thePropertyName )
  {
    return (typeof this[thePropertyName] != "undefined") && (this.constructor.prototype[thePropertyName] == null);
  }
}

// level 1 mapping
var gChangeLevel1={
  "\u0041":"a",   // writing chracters in the unicode way is necessary because of PR-4581
  "\u0061":"a",   // to see the real character have a look at gChangeLevel2
  "\u00c6":"ae",
  "\u00e6":"ae",
  "\u00e1":"a",
  "\u00c1":"a",
  "\u00e0":"a",
  "\u00c0":"a",
  "\u00e2":"a",
  "\u00c2":"a",
  "\u00e5":"a",
  "\u00c5":"a",
  "\u00e4":"a",
  "\u00c4":"a",
  "\u00e3":"a",
  "\u00c3":"a",
  "\u0043":"c",
  "\u0063":"c",
  "\u00e7":"c",
  "\u00c7":"c",
  "\u0044":"d",
  "\u0064":"d",
  "\u00d0":"d",
  "\u00f0":"d",
  "\u0065":"e",
  "\u0045":"e",
  "\u00e9":"e",
  "\u00c9":"e",
  "\u00e8":"e",
  "\u00c8":"e",
  "\u00ea":"e",
  "\u00ca":"e",
  "\u00eb":"e",
  "\u00cb":"e",
  "\u0049":"i",
  "\u0069":"i",
  "\u00ed":"i",
  "\u00cd":"i",
  "\u00ec":"i",
  "\u00cc":"i",
  "\u00ee":"i",
  "\u00ce":"i",
  "\u00ef":"i",
  "\u00cf":"i",
  "\u004f":"o",
  "\u006f":"o",
  "\u00d8":"o",
  "\u00f8":"o",
  "\u00f3":"o",
  "\u00d3":"o",
  "\u00f2":"o",
  "\u00d2":"o",
  "\u00f4":"o",
  "\u00d4":"o",
  "\u00f5":"o",
  "\u00f6":"o",
  "\u00d6":"o",
  "\u0053":"s",
  "\u0073":"s",
  "\u00df":"ss",
  "\u0055":"u",
  "\u0075":"u",
  "\u00fa":"u",
  "\u00da":"u",
  "\u00f9":"u",
  "\u00d9":"u",
  "\u00fb":"u",
  "\u00db":"u",
  "\u00fc":"u",
  "\u00dc":"u",
  "\u0059":"y",
  "\u0079":"y",
  "\u00fd":"y",
  "\u00dd":"y",
  "\u00ff":"y",
  "\u00f1":"n",
  "\u00d1":"n",
  "-":"",
  "'":"",
  "!":"",
  '"':"",
  "#":"",
  "$":"",
  "%":"",
  "&":"",
  "'":"",
  "(":"",
  ")":"",
  "*":"",
  "+":"",
  ",":"",
  "-":"",
  ".":"",
  "/":"",
  ":":"",
  ";":"",
  "<":"",
  "=":"",
  ">":"",
  "?":"",
  "@":"",
  "[":"",
  "\\":"",
  "]":"",
  "^":"",
  "_":"",
  "`":"",
  "{":"",
  "|":"",
  "}":"",
  "~":""
}

// level 2 mapping
var gChangeLevel2={
  "\u0041":"a\000",//A
  "\u0061":"a\000",//a
  "\u00c6":"ae",//Æ
  "\u00e6":"ae",//æ
  "\u00e1":"a\001",//á
  "\u00c1":"a\001",//Á
  "\u00e0":"a\002",//à
  "\u00c0":"a\002",//À
  "\u00e2":"a\003",//â
  "\u00c2":"a\003",//Â
  "\u00e5":"a\004",//å
  "\u00c5":"a\004",//Å
  "\u00e4":"a\005",//ä
  "\u00c4":"a\005",//Ä
  "\u00e3":"a\006",//ã
  "\u00c3":"a\006",//Ã
  "\u0043":"c\000",//C
  "\u0063":"c\000",//c
  "\u00e7":"c\001",//ç
  "\u00c7":"c\001",//Ç
  "\u0044":"d\000",//D
  "\u0064":"d\000",//d
  "\u00d0":"d\000",//Ð
  "\u00f0":"d\000",//ð
  "\u0065":"e\000",//e
  "\u0045":"e\000",//E
  "\u00e9":"e\001",//é
  "\u00c9":"e\001",//É
  "\u00e8":"e\002",//è
  "\u00c8":"e\002",//È
  "\u00ea":"e\003",//ê
  "\u00ca":"e\003",//Ê
  "\u00eb":"e\004",//ë
  "\u00cb":"e\004",//Ë
  "\u0049":"i\000",//I
  "\u0069":"i\000",//i
  "\u00ed":"i\001",//í
  "\u00cd":"i\001",//Í
  "\u00ec":"i\002",//ì
  "\u00cc":"i\002",//Ì
  "\u00ee":"i\003",//î
  "\u00ce":"i\003",//Î
  "\u00ef":"i\004",//ï
  "\u00cf":"i\004",//Ï
  "\u004f":"o\000",//O
  "\u006f":"o\000",//o
  "\u00d8":"o\000",//Ø
  "\u00f8":"o\000",//ø
  "\u00f3":"o\001",//ó
  "\u00d3":"o\001",//Ó
  "\u00f2":"o\002",//ò
  "\u00d2":"o\002",//Ò
  "\u00f4":"o\003",//ô
  "\u00d4":"o\003",//Ô
  "\u00f5":"o\004",//õ
  "\u00f6":"o\005",//ö
  "\u00d6":"o\005",//Ö
  "\u0053":"s\000",//S
  "\u0073":"s\000",//s
  "\u00df":"ss",//ß
  "\u0055":"u\001",//U
  "\u0075":"u\001",//u
  "\u00fa":"u\001",//ú
  "\u00da":"u\001",//Ú
  "\u00f9":"u\002",//ù
  "\u00d9":"u\002",//Ù
  "\u00fb":"u\003",//û
  "\u00db":"u\003",//Û
  "\u00fc":"u\004",//ü
  "\u00dc":"u\004",//Ü
  "\u0059":"y\000",//Y
  "\u0079":"y\000",//y
  "\u00fd":"y\001",//ý
  "\u00dd":"y\001",//Ý
  "\u00ff":"y\002",//ÿ
  "\u00f1":"n\001",//ñ
  "\u00d1":"n\001",//Ñ
  "-":"",
  "'":"",
  "!":"",
  '"':"",
  "#":"",
  "$":"",
  "%":"",
  "&":"",
  "'":"",
  "(":"",
  ")":"",
  "*":"",
  "+":"",
  ",":"",
  "-":"",
  ".":"",
  "/":"",
  ":":"",
  ";":"",
  "<":"",
  "=":"",
  ">":"",
  "?":"",
  "@":"",
  "[":"",
  "\\":"",
  "]":"",
  "^":"",
  "_":"",
  "`":"",
  "{":"",
  "|":"",
  "}":"",
  "~":""
}

/**
 * Creates an simple compareable string out of an internationalized string
 * This is done using EOR conform rules and level 1 mapping
 *
 * @param aStr: string: an arbitrary string the path segments that should be encoded
 * @return string: the by >< compareable representation of aStr
 */
function intStrKeyLevel1(aStr)
{  // create internationalised sortable string
  var theStr=aStr.replace(/^ +/g,"");
  var theStr=theStr.replace(/ +$/g,"");
  function lamdaExp(key)
  {
    var ret=gChangeLevel1[key];
    if (typeof ret !="undefined")
      return ret;
    else
      return key;
  }

  if (!lambdaExpressionsSupported()) {
    return theStr;
  }
  else {
    return theStr.replace ( /[AaÆæáÁàÀâÂåÅäÄãÃCcçÇDdÐðéeEÉèÈêÊëËIiíÍìÌîÎïÏOoØøóÓòÒôÔõöÖSsßUuúÚùÙûÛüÜYyýÝÿñÑ\-\'\!\"#%&\'\(\)\*\+,\.\/:;<=>\?\@\[\\\]\^_\`\{\|\}\~]/g, lamdaExp );
  }
}

/**
 * Creates an simple compareable string out of an internationalized string
 * This is done using EOR conform rules and level 2 mapping
 *
 * @param aStr: string: an arbitrary string the path segments that should be encoded
 * @return string: the by >< compareable representation of aStr
 */
function intStrKeyLevel2(aStr)
{  // create internationalised sortable string
  var theStr=aStr.replace(/^ +/g,"");
  var theStr=theStr.replace(/ +$/g,"");
  function lamdaExp(key)
  {
    var ret=gChangeLevel2[key];
    if (typeof ret != "undefined")
      return ret;
    else
      return key;
  }

  if (!lambdaExpressionsSupported()) {
    return theStr;
  }
  else {
    return theStr.replace ( /[AaÆæáÁàÀâÂåÅäÄãÃCcçÇDdÐðéeEÉèÈêÊëËIiíÍìÌîÎïÏOoØøóÓòÒôÔõöÖSsßUuúÚùÙûÛüÜYyýÝÿñÑ\-\'\!\"#%&\'\(\)\*\+,\.\/:;<=>\?\@\[\\\]\^_\`\{\|\}\~]/g, lamdaExp );
  }
}

/**
 * Sorts two string using insensitive EOR sorting.
 *
 * @param a: string: the first string
 * @param b: string: the second string
 * @return string: the by >< compareable representation of strings
 */
function caseInsensitiveSort(a,b)
{
  // compare level 1
  var aa = intStrKeyLevel1(a.toLowerCase());
  var bb = intStrKeyLevel1(b.toLowerCase());
  if (aa > bb) { return 1;  };
  if (aa < bb) { return -1; };

  // compare level 2
  var aa = intStrKeyLevel2(a.toLowerCase());
  var bb = intStrKeyLevel2(b.toLowerCase());
  if (aa > bb) { return  1; };
  if (aa < bb) { return -1; };

  // strings are equal
  return 0;
}

/* End of  "Object.js" */

