
_svsys_init();


// _sv.fie = 1;

///--------------------------------------------------------------------------------------
function _svsys_init() {
  var x,i,ii,j,jj,a,b,c,d,n,w,m,y,dp;
  w = window;
  dp = false;
  if(w._sv) {
    if(w._sv.debug_panel) {
      dp = w._sv.debug_panel;
    }
  }
  _sv = [];
  svsys = x = w._sv;
  _sv.select_list = [];
  _sv.object_list = [];
  x.loaded = 0;
  x.tbl_hdrs_p = [];  /// Array de cabeceras de tabla provisional.
  x.tbl_hdrs = [];    /// Array de cabeceras de tabla.
  document._sv_unload = 0;
  /**--------------------------------------------------------------------------
  *** '_sv._he' será un array asociativo donde cada índice será el nombre de
  *** un evento normal de DOM, y el item será un array normal con dos items:
  *** 
  *** - Un número con el tipo de evento SV que desencadenará
  *** 
  *** - El nombre de la función que será llamada.
  *** 
  ***--------------------------------------------------------------------------*/
  x._he ={mousedown:[1,mhmd],
          mouseup:[1,mhmu],
          mousemove:[1,mhmm],
          mouseout:[1,mhmo],
          dblclick:[1,mhdc],
          click:[1,mhcl],
          dragstart:[1,mhds],
          keydown:[2,khkd],
          keyup:[2,khku],
          keypress:[2,khkp],
          selectstart:[3,ghss],
          copy:[3,ghcp],
          scroll:[4,whsc],
          submit:[4,whsb],
          resize:[4,whrs],
          load:[4,whld],
          unload:[4,whul],
          change:[5,chch]
  };
  ///---------------------------------------------------------------------------------
  x.rv = [];
  x.a1 = [];  /// Array auxiliar 1. Se usa como array temporal en algunas operaciones
  x.a2 = [];  /// Array auxiliar 2. Se usa como array temporal en algunas operaciones
  x.uid='AF1RTJVNAGFJDJ2BW6C2SO3PER';
  x.aid=1;
  x._loadfuncs = [];
  x._handlers  = [];
  x.init_sv_title=init_sv_title;
  
  x.debug_panel = null;                     //# Almacena una referencia a la ventana.
  x.debug_init = [];
  x._debug_id = null;                       //# Almacena el ID del temporizador de debug.
  x._set_debug_panel = false;               //# A true indica que el valor siguiente es válido.
  x._new_debug_panel = null;                //# Referencia al nuevo debug panel.
  x._debug_msgs = [[], [], []];             //# Triple buffer de mensajes de error.
  x._debug_msgs_i = 0;                      //# Indice dentro del anterior.
  
  if(dp) {
    sdp(dp);
  }
  _out_dbg("Consola de depuración de Javascript");
  _out_dbg("La Vega Multimedia. Abril de 2008");
  _out_dbg("---------------------------------------------");


  x.create_element = create_element;
  x.set_att = _set_att;
  x.sprintf = _sprintf;
  x.def_val = _def_val;
  x.status  = _status;
  x.clone   = _clone;
  x.is_array= _is_array
  x.arr_cpy = _arr_cpy;
  x.tolc = _tolc;
  x.touc = _touc;
  x.submit_form=submit_form;
  x.is_frm_obj=_is_frm_obj;
  x.print_r = _print_r;
  x.get_win = _get_win;
  x.append_child   = append_child;
  x.init_node = _init_node;
  x.insert_before  = insert_before;
  x.move_child   = _move_child;
  x.remove_child   = _remove_child;
  x.remove_childs  = _remove_childs;
  x.add_event_handler = add_event_handler;
  x.add_notify_handler = add_notify_handler;
  x.focus = _focus;
  x.load_function = load_function;
  x.set_debug_panel = sdp;
  x.trim = _trim;
  x.parse_atts = parse_atts;
  x.fire = fire;
  x.out_dbg = _out_dbg;
  x.dbg = _out_dbg;
  x._go_r = _go_r;
  x.whsc2 = whsc2;
  x.get_sibling  = _get_sibling;
  x.get_rsibling = _get_rsibling;
  x.get_parent   = _get_parent;
  x.get_child    = _get_child;
  x.get_childs   = _get_childs;
  x.object_pos   = _op;
  x.object_rec   = _or;
  x.user_agent   = _ua;
  x.set_prop = _set_prop;
  x.get_prop = _get_prop;
  x.table_header = _table_header;
  x.auto_plug = _set_auto_plug;
  x.set_plug_value = _set_plug_value;
  x.get_plug_value = _get_plug_value;
  x.set_plugin     = _set_plugin;
  x.set_plugout    = _set_plugout;

  x.gaid = gaid;
  x.said = said;
  x.auto_scroll = _auto_scroll;
  x.popup = _l_popup;
  x.close_popup = _l_close_popup;
  x.start = _start;
  x._l_entities      = _l_entities;
  x.detect_collision = _collision;
  x.is_emp=is_emp;
  x.cpy_frm=cpy_frm;
  x.scroll=[0,0];
  x.ppps = [];
  x.pp_z = [];
  x.pp_tp = [];
  x.pp_n = 0;
  x._is_svsys = true;
  x.nodeName = '#_sv';
  x.className = '';
  
  x.plug_values = {}; /// Array asociativo de valores de enchufes.
  x.plug_links  = {}; /// Array asociativo de enlaces.
  x.auto_id = 0;      /// Auxiliar para crear ID automaticos.
  x.mouse = {};

  x._props ={
            display:2
            ,visibility:2
            ,backgroundColor:2
            //,checked:1
  };
  
  m = x.mouse;
  m.client = [0,0];
  m.screen = [0,0];
  m.page   = [0,0];
  m.cancels= [0,0,0];
  /**---------------------------------------------------------------------------------
  /// Cada índice numérico de svsys está para un botón.
  /// st : STate : Diferente de cero si está presionado.
  /// ob : Objeto que espera el próximo mouseup (esta propiedad se activa en cada
  ///      mousedown, y se desactiva en el mouseup).
  /// md : Contador de m_down. Se incrementa en cada m_down, y se pone a cero con
  ///      m_dblclick. Se usa para garantizar que ningún m_dblclick es generado sin
  ///      al menos dos m_down entre dos m_dblclick consecutivos.
  /// le : LastEvent : identifica al último evento disparado por el botón:
  ///      0: Ninguno  1:mousedown  2:mouseup  3:mouseup descolocado (sin mousedown)
  ///      4: click    5: dblclick
  ///---------------------------------------------------------------------------------*/
  for(i=0; i<4; i++) {
    x[i] = {ob:null,st:0,md:0,le:0};
  }
  m.buttons=0;
  x.pointed=null;   /// El objeto sobre el que está el ratón.
  x._sv_events = {};
  x.focusObj = x;
  x._keysys = {};
  x.ppp_obj = false;  /// El objeto popup abierto actualmente.
  y = x._keysys;
  y.skp = [];
  a = [ 1,9,    11,12,    14,26,
        28,31,   33,40,    45,46,
        91,93,  112,123,  144,145 ];
  for(j=0; j<a.length; j+=2) {
    for(i=a[j]; i<=a[j+1]; i++) {
      y.skp[i] = 1;
    }
  }
  y.lkp = [];
  y.ckd = [];
  for(i=0; i<256; i++) {
    y.ckd[i] = y.lkp[i] = 0;
  }
  y = x._sv_events;
  y.m_down = [[]];
  y.m_down[0].eh = hmd;
  y.m_up = [[]];
  y.m_up[0].eh = hmu;
  y.m_leave = [[]];
  y.m_leave[0].eh = hml;
  y.m_enter = [[]];
  y.m_enter[0].eh = hme;


  _l_add_sys_event_handler(w,hcbe,"load",w,hiee,"onload");

  function sdp(w) {
    if(!_sv.debug_panel) {
      _sv._debug_id = setInterval(_tmp_dbg, 250);
    }
    _sv._new_debug_panel = w;
    _sv._set_debug_panel = true;
  }

  function _tmp_dbg() {
    var dp,i,ii,d,fn,m,mi;
    if(_sv._set_debug_panel) {
      _sv._set_debug_panel = false;
      dp = _sv._new_debug_panel;
      _sv.debug_panel = dp;
      if(!dp) {
        clearInterval(_sv._debug_id);
        return;
      }
    }
    dp = _sv.debug_panel;
    if(dp.out_consola_js) {
      fn = dp.out_consola_js;
      d = null;
    } else if(dp.get_consola_js) {
      d = dp.get_consola_js();
      if(!d) {
        return;
      }
      fn = _tmp_out_dbg;
    } else {
      return;
    }
    i = _sv._debug_msgs_i;
    i = (i==2) ? 0 : i+1 ;
    _sv._debug_msgs_i = i;
    mi = (i==2) ? 0 : i+1 ;
    m = _sv._debug_msgs[mi];
    ii = m.length;
    if(!ii) {
      return;
    }
    for(i=0; i<ii; i++) {
      fn(d, m[i]);
    }
    _sv._debug_msgs[mi] = [];
  }

  function _tmp_out_dbg(d, t) {
    d.innerHTML = String(d.innerHTML) + t + '<br>';
  }

  function _out_dbg(t) {
    var i, ii;
    i = _sv._debug_msgs_i;
    ii = _sv._debug_msgs[i].length;
    _sv._debug_msgs[i][ii] = t;
  }

  /**
   *  Obtiene el objeto window correspondiente a la aplicación (será aquella que muestre
   *  un documento con un formulario).
   */
  function _get_win() {
    var w,i,ii,c,fs,cn;
    w = window;
    if(w.document.forms.length) return w;
    fs = _sv.get_child(w.document, "FRAMESET", null);
    if(!fs) {
      fs = _sv.get_child(w.parent.document, "FRAMESET", null);
    }
    if(!fs) {
      return null;
    }
    cn=fs.childNodes;
    ii = cn.length;
    for(i=0; i<ii; i++) {
      c = cn[i];
      if(c.nodeName=='FRAME') {
        w = c.contentWindow;
        if(w.document.forms.length) {
          return w;
        }
      }
    }
    return null;
  }

  function _table_header(ids, idd) {
    var h;
    h = _sv.tbl_hdrs_p;
    h[h.length] = [ids, idd];
  }


  /**
   * Establece las propiedades virtuales de un objeto y, si es necesario,
   * establece el valor de los plugs relacionados con ellas.
   * 
   * @return: Objeto.
   * @author: a_vera
   */
  function _refresh_plug_props(o) {
    var nn,i,v;
    nn = o.nodeName;
    if(nn=='SELECT') {
      i = o.selectedIndex;
      v = o.options[i].value;
      o.sv_value = v;
    }
    _set_plugs_props(o);
  }

  /**
   * @return: ID único automático.
   * @author: a_vera
   */
  function _get_auto_id() {
    var i;
    i = _sv.auto_id;
    _sv.auto_id++;
    return '_SVAI_' + String(i);
  }

  function _set_plugouts_str(o, s) {
    var a,ii,i;
    a = [];
    parse_atts2(s,a);
    ii=a.length;
    for(i=0; i<ii; i+=2) {
      _set_plugout(o, a[i], a[i+1]);
    }
  }
  /**
   * @param: objeto al que establecer el plugout.
   * @param: Nombre de propiedad.
   * @param: valor del plugout
   * @author: a_vera
   */
  function _set_plugout(o, pn, v) {
    var as,a,pv;
    if(!_is_array(v)) {
      v = [v];
    }
    as = o._sv_plugouts;
    if(as==undefined) {
      o._sv_plugouts = {};
      as = o._sv_plugouts;
    }
    a = as[pn];
    if(a==undefined) {
      as[pn] = [];
      a = as[pn];
    }
    a[a.length] = v;
    pv = _get_prop(o, pn);
    _set_plug_prop(v, pv);

  }

  function _set_plugins_str(o, s) {
    var a;
    a = {};
    parse_atts(s,a);
    for(var i in a) {
      _set_plugin(o,i,a[i]);
    }
  }

  /**
   * @param: objeto al que establecer el plugin.
   * @param: id del plug.
   * @param: descriptor del plugin (propiedad, condiciones y valores).
   * @author: a_vera
   */
  function _set_plugin(o, id, d) {
    var hid,v, pl;
    id = id.toLowerCase();
    if(!o.getAttribute) {           /// Si el objeto no tiene este método.
      return;                       /// | Terminar
    }                               /// -------------------------------------------------
    hid = o.getAttribute('id');     /// Tomar el atributo 'id'.
    if(hid==null || hid=='') {
      hid = _get_auto_id();
      o.setAttribute('id', hid);
    }
    if(!_is_array(d)) {
      d = [d];
    }
    pl = _sv.plug_links[id];
    if(pl==undefined) {
      _sv.plug_links[id] = [];
      pl = _sv.plug_links[id];
    }
    pl[pl.length] = [hid, d];
    v = _sv.plug_values[id];
    _fire_plugin(o, v, d);
  }

  /**
   * Si no existe el plug, lo crea y le asigna el valor por defecto recibido, si existe, no hace nada.
   * 
   * 
   * @param: ID del plug.
   * @param: Valor para el plug.
   * @author: a_vera
   */
  function _create_plug_value(id, v) {
    var va;
    id = id.toLowerCase();
    va = _sv.plug_values[id];
    if(va==undefined) {
      _set_plug_value(id, v);
    }
  }

  /**
   * Dado un ID de plug, y un valor para el mismo, lo establece, disparando si es
   * necesario todas las acciones enchufadas.
   * 
   * @param: ID del plug.
   * @param: Valor para el plug.
   * @author: a_vera
   */
  function _set_plug_value(id, v) {
    var va;
    id = id.toLowerCase();
    va = _sv.plug_values[id];
    _sv.plug_values[id] = v;
    if(va==undefined) {
      _fire_plugins(id);
    } else if(va!=v) {
      _fire_plugins(id);
    }
  }

  function _get_plug_value(id) {
    id = id.toLowerCase();
    return _sv.plug_values[id];
  }

  /**
   * Dado un ID de plug, establece el valor de todas las propiedades de objetos
   * asociados al valor adecuado.
   * 
   * @param: ID del plug.
   * @author: a_vera
   */
  function _fire_plugins(id) {
    var v,pl,pls,hid,d,o;
    v = _sv.plug_values[id];
    if(v==undefined) {
      return;
    }
    pls = _sv.plug_links[id];
    if(pls==undefined) {
      return;
    }
    ii = pls.length;
    for(i=0; i<ii; i++) {
      pl = pls[i];
      hid = pl[0];
      d = pl[1];
      o = document.getElementById(hid);
      if(o) {
        _fire_plugin(o, v, d);
      }
    }
  }
  
  /**
   * Dado un objeto, el valor de un plug, y un descriptor de plugin que asocia a
   * ambos (objeto y plug), establece el valor de la propiedad del objeto de la
   * forma que indique el plugin.
   * 
   * @param: objeto.
   * @param: valor del plug.
   * @param: descriptor del plugin.
   * @author: a_vera
   */
  function _fire_plugin(o, v, d) {
    var ii,i,pvs,vs;
    if(v==undefined) {
      return;
    }
    ii = d.length;
    if(ii==1) {                         /// Si es del tipo '[propiedad]'
      _set_prop(o, d[0], v);
      return;
    }
    if(ii!=4) {                         /// Si es erróneo.
      return;
    }
    if(_is_array(d[1])) {
      pvs = d[1];
    } else {
      pvs = [d[1]];
    }
    if(_is_array(d[2])) {
      vs = d[2];
    } else {
      vs = [d[2]];
    }
    ii = pvs.length;
    for(i=0; i<ii; i++) {
      if(v==pvs[i]) {
        _set_prop(o, d[0], vs[i]);
        return;
      }
    }
    _set_prop(o, d[0], d[3]);
  }
                            
  /**
   * Obtiene el valor de una propiedad de un objeto.
   * 
   * @param: objeto.
   * @param: propiedad.
   * @author: a_vera
   */
  function _get_prop(o, p) {
    var tp;
    tp=_sv._props[p];
    if(tp==undefined) {
      tp = 0;
    }
    switch(tp) {
    case 1:
      return o.getAttribute(p);
    case 2:
      return o.style[p];
    default:
      return o[p];
    }
  }

  /**
   * Establece el valor de una propiedad de un objeto.
   * 
   * @param: objeto.
   * @param: propiedad.
   * @param: valor.
   * @author: a_vera
   */
  function _set_prop(o, p, v) {
    var tp,pb;
    tp=_sv._props[p];
    if(tp==undefined) {
      tp = 0;
    }
    try {
      switch(tp) {
      case 1:
        o.setAttribute(p, v);
        break;
      case 2:
        o.style[p] = v;
        break;
      default:
        o[p] = v;
        break;
      }
    } catch(err) {
    }
    _set_plugs_prop(o, p, v);
  }

  /**
   * Establece el valor de los plugs de las propiedades de un objeto.
   * 
   * @param: objeto.
   * @author: a_vera
   */
  function _set_plugs_props(o) {
    var a, v, po, i, ii;
    a = o._sv_plugouts;
    if(a==undefined) {
      return;
    }
    for(var p in a) {
      v = _get_prop(o, p);
      po = a[p];
      ii = po.length;
      for(i=0; i<ii; i++) {
        _set_plug_prop(po[i],v);
      }
    }
  }

  /**
   * Establece el valor de los plugs de una propiedad de un objeto.
   * 
   * @param: objeto.
   * @param: propiedad.
   * @param: valor.
   * @author: a_vera
   */
  function _set_plugs_prop(o, p, v) {
    var pos,po,i,ii;
    pos = o._sv_plugouts;
    if(pos==undefined) {
      return;
    }
    po=pos[p];
    if(po==undefined) {
      return;
    }
    ii = po.length;
    for(i=0; i<ii; i++) {
      _set_plug_prop(po[i],v);
    }
  }

  /**
   * Establece el valor de un plug de una propiedad de un objeto.
   * 
   * @param: descriptor.
   * @param: valor de la propiedad.
   * @author: a_vera
   */
  function _set_plug_prop(d, v) {
    var id,ii,i,dd, pvs,vs,ve,tp,par,vv,p2;
    dd = d.length;
    if(!dd) {
      return;
    }
    id = d[0];
    if(dd==1) {
      _set_plug_value(id, v);
      return;
    }
    if(dd<4) {
      return;
    }
    //  [id_enchufe, VP, VE, VEd]
    if(_is_array(d[1])) {
      pvs = d[1];
    } else {
      pvs = [d[1]];
    }
    if(_is_array(d[2])) {
      vs = d[2];
    } else {
      vs = [d[2]];
    }
    ii = pvs.length;
    ve = d[3];
    for(i=0; i<ii; i++) {
      if(v==pvs[i]) {
        ve = vs[i];
      }
    }
    tp = 0;
    par = 0;
    if(dd>4) {
      tp = d[4];
      if(dd>5) {
        par = d[5];
      }
    }
    switch(tp) {
    case 1:
      par = parseInt(par);
      if(!par) {
        break;
      }
      vv = _get_plug_value(id);
      vv = parseInt(vv);
      if(!vv) { vv = 0; }
      ve = parseInt(ve);
      if(!ve) { ve = 0; }
      p2 = par;
      while(!(p2&1)) {
        p2>>=1;
        ve<<=1;
      }
      vv &= ~par;
      ve &= par;
      _set_plug_value(id, vv|ve);
      break;
    default:
      _set_plug_value(id, ve);
      break;
    }
    
  }
  /**---------------------------------------------------------------------------------
  *** svsys::is_frm_obj                                              svsys::is_frm_obj
  ***---------------------------------------------------------------------------------
  *** Devuelve un valor verdadero si el objeto que recibe por parámetro es un
  *** objeto de formulario (INPUT, SELECT...). Además, en caso de devolver un
  *** valor verdadero, _sv.rv[0] contendrá el objeto de FORM contenedor.
  *** Casi siempre el objeto de FORM pasado será el mismo contenedor pero en
  *** algunos casos no será así (por ejemplo, si el objeto es un 'OPTION'
  *** entonces se tratará de un objeto de FORM, pero en _sv.rv[0] estará el
  *** SELECT correspondiente.
  ***---------------------------------------------------------------------------------*/
  function _is_frm_obj(o) {
    var m,n;
    if(!_is_frm_obj.tgs){   /// Si no se ha establecido el array de nombres de
                            /// objetos de FORM.
      _is_frm_obj.tgs={     /// | Se establece:
        SELECT:1,           /// | | SELECT es un objeto de FORM.
        OPTION:1,           /// | | OPTION es un objeto de FORM.
        INPUT:1,            /// | | INPUT es un objeto de FORM.
        TEXTAREA:1,         /// | | TEXTAREA es un objeto de FORM.
        BUTTON:1            /// | | BUTTON es un objeto de FORM.
      };                    /// | | 
    }                       /// | | 
    /**--------------------------------------------------------------------------
    *** Aquí hay que comprobar si el nombre de nodo del objeto está en el array
    *** anterior, en cuyo caso se trata de un objeto de FORM. Sin embargo,
    *** algunos navegadores reconocen como objetos algunas partes pequeñas de
    *** los controles de FORM (por ejemplo un botón de una barra de
    *** desplazamiento de un SELECT), así que para estar seguros, la función
    *** comprueba también los padres (de momento asciende sólo un nivel)
    ***--------------------------------------------------------------------------*/
    m=_is_frm_obj.tgs;      /// m se refiere a este array de nombres.
    n=o.nodeName;           /// n contiene el nombre de nodo del objeto.
    if(!(n in m)){          /// Si el nombre no está en el array.
      o=_get_parent(o);     /// | Se toma el objeto padre.
      if(!o){               /// | Si no tiene objeto padre.
        return false;       /// | | No es un objeto de FORM.
      }                     /// | |
      n=o.nodeName;         /// | n contiene el nombre de nodo del padre.
      if(!(n in m)){        /// | Si el nombre no está en el array.
        return false;       /// | | No es un objeto de FORM.
      }                     /// | | 
    }                       /// | | 
    /**--------------------------------------------------------------------------
    *** Aquí, el objeto es un objeto de FORM, pero además _sv.rv[0] debe
    *** contener una referencia al verdadero objeto de FORM. Este objeto
    *** está ahora en 'o', salvo que el nombre del mismo (en 'n') sea
    *** 'OPTION'.
    *** 
    ***--------------------------------------------------------------------------*/
    if(n=='OPTION') {       /// Si 'o' es un objeto 'OPTION'
      o=_get_parent(o);     /// | Se toma el objeto padre.
    }                       /// | 
    _sv.rv[0]=o;            /// En _sv.rv[0] el verdadero objeto de FORM.
    return true;            /// Es un objeto de FORM.
  }
  ///---------------------------------------------------------------------------------
  /// svsys::clone                                                        svsys::clone
  ///---------------------------------------------------------------------------------
  function _clone(a) {
    var t,r;
    if(a.nodeName) return a;
    r=[];
    for(var i in a) {
      t = typeof(a[i]);
      if(t=='object') {
        r[i]=_clone(a[i]);
      } else {
        r[i]=a[i];
      }
    }
    return r;
  }

  ///---------------------------------------------------------------------------------
  /// svsys::is_array                                                  svsys::is_array
  ///---------------------------------------------------------------------------------
  function _is_array(a) {
    if(typeof(a)=='object') {
      if(typeof(a.length)=='number') {
        return 1;
      }
    }
    return 0;
  }

  ///---------------------------------------------------------------------------------
  /// svsys::arr_cpy                                                    svsys::arr_cpy
  ///---------------------------------------------------------------------------------
  function _arr_cpy(f,t) {
    var ii,i;
    ii = f.length;
    for(i=0;i<ii;i++) {
      t[i] = f[i];
    }
  }
  
  ///---------------------------------------------------------------------------------
  /// svsys::status                                                      svsys::status
  ///---------------------------------------------------------------------------------
  function _status(t) {
    if(!window.sv_status) {
      window.sv_status=0;
    }
    window.sv_status++;
    window.status=String(window.sv_status)+': '+String(t);
  }

  ///---------------------------------------------------------------------------------
  /// svsys::_print_r                                                  svsys::_print_r
  ///---------------------------------------------------------------------------------
  function _print_r(a, r) {
    var t;
    if(a==null) return '[javascript: null]';
    if(a==undefined) return '[javascript: undefined]';
    if(a==NaN) return '[javascript: NaN]';
    t = typeof(a);
    if(!r) r=2;
    if(t=='object') return '[javascript: '+t+']'+'<br>'+__print_r(a,'&nbsp;&nbsp;','&nbsp;&nbsp;','<br>',r);
    return '[javascript: '+t+']:'+String(a);
  }

  ///---------------------------------------------------------------------------------
  /// private::__print_r                                            private::__print_r
  ///---------------------------------------------------------------------------------
  function __print_r(a,s,su,nl,r) {
    var t,n;
    if(a==null) return '[javascript: null]'+nl;
    if(a==undefined) return '[javascript: undefined]'+nl;
    if(a==NaN) return '[javascript: NaN]'+nl;
    n=a.nodeName;
    if(n) return s+"[DOM Object '<b>"+n+"</b> ]"+nl;
    if(a[_sv.uid]) return s+"[Internal recursion to object ID"+a[_sv.uid]+"]"+nl;
    if(!r) return s+"[No more iterations allowed]"+nl;
    n='';
    a[_sv.uid]=_sv.aid;
    //n=n+s+"[Object ID"+_sv.aid+"]"+nl;
    _sv.aid++;
    for(var i in a) {
      if(i==_sv.uid)continue;
      t = typeof(a[i]);
      n = n+s+"["+i+"] = ";
      if(t=='object') {
        n=n+"[Object]"+nl+__print_r(a[i],s+su,su,nl,r-1);
      } else {
        n=n+String(a[i]);
        n=n+nl;
      }
    }
    delete(a[_sv.uid]);
    return n;
  }
  function gaid() {
    var v;
    v=_sv.aid;
    _sv.aid++;
    return v;
  }
  ///---------------------------------------------------------------------------------
  /// said:
  ///---------------------------------------------------------------------------------
  function said(v) {
    v++;
    if(v>_sv.aid) {
      _sv.aid=v;
    }
  }
  /**---------------------------------------------------------------------------------
  *** svsys::def_val                                                    svsys::def_val
  ***---------------------------------------------------------------------------------
  *** RECIBE:
  *** 
  *** - La cadena de formato.
  *** - Los parámetros.
  *** 
  ***---------------------------------------------------------------------------------*/
  function _def_val(o, p, d) {
    var x;
    x = o[p];
    if(x==undefined) x=d;
    return x;
  }

  /**---------------------------------------------------------------------------------
  *** svsys::sprintf                                                    svsys::sprintf
  ***---------------------------------------------------------------------------------
  *** RECIBE:
  *** 
  *** - La cadena de formato.
  *** - Los parámetros.
  *** 
  ***---------------------------------------------------------------------------------*/
  function _sprintf(s) {
    _sv._sprf = _sprintf.arguments;
    return s.replace(/\%([0-9]+)/g, _cb_sprintf);
  }
  function _cb_sprintf(o1, o2) {
    var i;
    i = parseInt(o2);
    if(!i) return '%';
    return String(_sv._sprf[i]);
  }
  /**---------------------------------------------------------------------------------
  *** svsys::set_att                                                    svsys::set_att
  ***---------------------------------------------------------------------------------
  *** RECIBE:
  *** 
  *** - Un objeto HTML.
  *** - Un atributo HTML
  *** - El nombre que tendria este atributo como propiedad directa en internet
  ***   explorer.
  *** - El valor para el atributo.
  *** 
  ***---------------------------------------------------------------------------------*/
  function _set_att(o, a1, a2, v) {
    if(o[a2]!=undefined) {
      o[a2]=v;
      return;
    }
    o.setAttribute(a1,v);
  }
  ///---------------------------------------------------------------------------------
  /// svsys::get_sibling                                            svsys::get_sibling
  ///---------------------------------------------------------------------------------
  function _get_sibling(o, t) {
    if(o==null) return o;
    if(t=='') {
      return o.nextSibling;
    }
    do {
      o = o.nextSibling;
      if(o==null) break;
    } while(o.nodeName!=t);
    return o;
  }
  ///---------------------------------------------------------------------------------
  /// svsys::get_rsibling                                          svsys::get_rsibling
  ///---------------------------------------------------------------------------------
  function _get_rsibling(o, t) {
    var cs,i,ii,p;
    if(o==null) return o;
    p=_get_parent(o);
    cs=p.childNodes;
    ii=cs.length;
    for(i=0;i<ii;i++) {
      if(cs[i]==o)break;
    }
    if(i>=ii)return null;
    i--;
    if(t=='')return cs[i];
    while(i>=0) {
      if(cs[i].nodeName==t)return cs[i];
      i--;
    }
    return null;
  }


  ///---------------------------------------------------------------------------------
  /// svsys::get_parent                                              svsys::get_parent
  ///---------------------------------------------------------------------------------
  function _get_parent(o,t,f,s) {
    if(o==null) return o;
    if(!s) {
      o = o.parentNode;
    }
    do {
      if(o==null) break;
      if(!t || o.nodeName==t) {
        if(!f)break;
        if(f(o))break;
      }
      o = o.parentNode;
    } while(1);
    return o;
  }
  /**---------------------------------------------------------------------------------
  *** svsys::get_child                                                svsys::get_child
  ***---------------------------------------------------------------------------------
  *** o : Referencia a un objeto DOM.
  *** t : Tipo de objeto buscado ("TD", "INPUT", etc.).
  *** f : null o una referencia a una función que recibirá una referencia a un
  ***     objeto DOM y debe devolver true si es un hijo buscado.
  ***---------------------------------------------------------------------------------*/
  function _get_child(o, t, f) {
    var cs, m, i, r, a, c;
    if(o==null) return o;
    cs = o.childNodes;
    m = cs.length;
    for(i=0;i<m;i++) {
      c = cs[i];
      if(t) if(c.nodeName!=t) continue;
      if(!f || f==null || f(c)) return c;
    }
    for(i=0;i<m;i++) {
      r = _get_child(cs[i], t, f);
      if(r!=null) return r;
    }
    return null;
  }

  /**---------------------------------------------------------------------------------
  *** svsys::get_childs                                              svsys::get_childs
  ***---------------------------------------------------------------------------------
  *** o : Referencia a un objeto DOM.
  *** t : Tipo de objeto buscado ("TD", "INPUT", etc.).
  *** f : null o una referencia a una función que recibirá una referencia a un
  ***     objeto DOM y debe devolver true si es un hijo buscado.
  *** nt : Si se especifica, Tipo de objeto en el que no es posible recurrir.
  *** st : Si se especifica y es verdadero, deja de buscar hijos en cuanto se
  ***      encuentre uno, salvo que sean hijos hermanos (mismo padre directo)
  ***---------------------------------------------------------------------------------*/
  function _get_childs(o, t, f, nt, st) {
    x = [];
    _get_childs_r(o, t, f, x, nt);
    return x;
  }

  function _get_childs_r(o, t, fn, x, nt, st) {
    var cs, m, i, xx, r, a, c, f, nn;
    if(o==null) return;
    cs = o.childNodes;
    m = cs.length;
    xx = x.length;
    for(i=0;i<m;i++) {
      c = cs[i];
      nn = c.nodeName;
      f = 1;
      if(t) {
        if(nn!=t) {
          f = 0;
        }
      }
      if(f) {
        if(fn) {
          if(!fn(c)) {
            f=0;
          }
        }
      }
      if(f) {
        x[xx] = c;
        xx++;
      } else {
        r = 1;
        if(st && xx) {
          r = 0;
        } else if(nt) {
          if(nn==nt) {
            r = 0;
          }
        }
        if(r) {
          _get_childs_r(c,t,f,x);
          xx = x.length;
          if(st && xx) {
            break;
          }
        }
      }
    }
  }
  
  /**---------------------------------------------------------------------------------
  *** _l_add_sys_event_handler                                _l_add_sys_event_handler
  ***---------------------------------------------------------------------------------
  *** o : Objeto al que vincular el evento en un browser compatible.
  *** h : Handler en un browser compatible.
  *** e : Nombre del evento.
  *** x : Objeto al que vincular el evento en IE.
  *** y : Handler en IE.
  *** z : Nombre del evento en IE.
  ***---------------------------------------------------------------------------------*/
  function _l_add_sys_event_handler(o,h,e,x,y,z) {
    if((x.attachEvent && _sv.fie) || (!o.addEventListener)) {
      x.attachEvent(z, y);
    } else {
      o.addEventListener(e,h,true);
    }
  }
/**-----------------------------------------------------------------------------------
*** _l_set_sys_event_handlers                                _l_set_sys_event_handlers
***-----------------------------------------------------------------------------------*/
  function _l_set_sys_event_handlers() {
    var o, b, h, w, i,e,p,q,fs,ii,f;
    o = document;
    w = window;
    h = _get_child(o, 'HTML', null);
    if(h==null) { h=o; }
    b = _get_child(o, 'BODY', null);
    if(b==null) {
      b = _get_child(o, 'FRAMESET', null);
      if(b==null) { b=h; }
    }
    _sv.root = h ;
    _sv.body = b ;
    if(b.setAttribute)b.setAttribute("onscroll", '_sv.whsc2()');
    e=_sv._he;
    for(var i in e) {
      if(i=='submit') continue;
      p=o; q=b;
      if(e[i][0]==4) {
        p=q=w;
      }
      _l_add_sys_event_handler(p, hcbe, i, q, hiee, 'on'+i);
    }
    fs = document.forms;  /// fs = lista de los formularios del documento.
    ii = fs.length;       /// ii = tamaño de la misma.
    for(i=0;i<ii;i++) {   /// Para cada formulario.
      f=fs[i];            /// | Se referencia en 'f'.
                          /// | Se le vincula 
      _l_add_sys_event_handler(f, hcbe, 'submit', f, hiee, 'onsubmit');
    }
  }

/**-----------------------------------------------------------------------------------
*** private::hcbe                                                        private::hcbe
***-----------------------------------------------------------------------------------*/
  function hcbe(e) {
    a=_sv._he[e.type];      /// a contiene el array [tipo_evento, funcion].
    if(a) {                 /// Si se ha definido este array.
      a[1](gefcb(e,a[0]));  /// | Llamar a la función manejadora, pasándole el
                            /// | objeto svEvent
    }
  }

/**-----------------------------------------------------------------------------------
*** private::hiee                                                        private::hiee
***-----------------------------------------------------------------------------------*/
  function hiee() {
    a=_sv._he[event.type];
    if(a) {
      a[1](gefie(a[0]));
    }
  }
/**-----------------------------------------------------------------------------------
*** private::gefcb                                                      private::gefcb
***-----------------------------------------------------------------------------------
*** gefcb = Get Event From Compatible Browser.
*** 
*** Obtiene un objeto svEvent, a partir de un objeto event de un navegador compatible
*** y un tipo de evento.
*** 
*** Se limita a invocar al constructor de svEvent (_svEventObject).
***-----------------------------------------------------------------------------------*/
  function gefcb(e, c) {
    return new _svEventObject(e,c);
  }
/**-----------------------------------------------------------------------------------
*** private::gefie                                                      private::gefie
***-----------------------------------------------------------------------------------
*** gefcb = Get Event From Internet Explorer.
*** 
*** Obtiene un objeto svEvent, a partir de un objeto event de internet explorer.
*** 
*** RECIBE:
*** 
*** - El tipo de evento (propiedad group de svEvent).
*** - Indirectamente, en la variable global event, recibe el objeto event de IE.
*** 
*** DEVUELVE:
*** 
*** - Un objeto svEvent.
*** 
*** COMENTARIOS:
*** 
*** Primero invoca al constructor de svEvent (_svEventObject). Sin embargo, el
*** objeto obtenido así no tiene la propiedad button correctaemnte asignada
*** en los eventos del ratón, ya que IE deja en esta propiedad el estado de los
*** tres botones como un campo de bits, en lugar de dejar sencillamente el número
*** del botón que disparó el evento, como hacen los navegadores compatibles.
*** 
*** Así que después de construir el objeto svEvent, la función repara como
*** buenamente puede el valor de esta propiedad, basándose en los valores de la
*** misma en eventos anteriores. Él arreglo de la propiedad no es posible siempre
*** pero sí en la mayoría de los casos prácticos.
*** 
*** Aún así, el objeto svEvent no está completo, ya que algunas propiedades son
*** establecidas por los manejadores individuales de cada evento. Por ejemplo, la
*** propiedad buttons.
***-----------------------------------------------------------------------------------*/
  function gefie(ec) {
    var r, t, b, lb, c, nb;
    r = new _svEventObject(event,ec);
    t = r.type;
    lb = (gefie.btn_st)?gefie.btn_st:256 ;
    b = r.button;
    /**-------------------------------------------------------------------------------
    *** Ahora se comprueba si el evento disparador ha sido un mousedown, si este es
    *** el caso, lo más sencillo es ir comprobando botón por botón (empezando por
    *** los más importantes) a ver si alguno está presionado y ha cambiado de estado.
    *** Se se da alguno de estos casos para alguno de los botones, ya tenemos el
    *** botón disparador.
    *** 
    *** Si es un mousedown pero no se ha podido determinar que botón disparó el
    *** evento, se comprueban uno a uno el estado de los botones, contantdo cuantos
    *** de ellos están presionados. Si sólo hay uno presionado, ese el que disparó
    *** el evento.
    *** 
    *** Si ni así es posible determinar que botón fue el disparador, la función
    *** se da por vencida y asigna el código ficticio 3 al boton disparador.
    ***-------------------------------------------------------------------------------*/
    if(t=='mousedown') {        /// Si el evento es un mousedown.
      lb |= 256;                /// |
      if((b&1)&&!(lb&1)){       /// | Si el botón izquierdo está presionado y su
                                /// | estado ha cambiado.
        lb |= 1;                /// | | Se marca el botón izquierdo como pisado.
        b = 0;                  /// | | El botón disparador fue el izquierdo.
      }else if((b&2)&&!(lb&2)){ /// | Si el botón derecho está presionado y su
                                /// | estado ha cambiado.
        lb |= 2;                /// | | Se marca el botón derecho como pisado.
        b = 2;                  /// | | El botón disparador fue el derecho.
      }else if((b&4)&&!(lb&4)){ /// | Si el botón central está presionado y su
                                /// | estado ha cambiado.
        lb |= 4;                /// | | Se marca el botón central como pisado.
        b = 1;                  /// | | El botón disparador fue el central.
      } else {
        c=0;
        if(b&1){lb|=1;nb=0;c++;}
        if(b&2){lb|=2;nb=2;c++;}
        if(b&4){lb|=4;nb=1;c++;}
        b = (c==1)?nb:3;
      }
    /**-------------------------------------------------------------------------------
    *** Ahora se comprueba si el evento disparador ha sido un mouseup.
    *** 
    *** Este caso es más sencillo puesto que Internet Explorer sólo activa en este
    *** caso el bit correspondiente al botón que disparó el evento.
    ***-------------------------------------------------------------------------------*/
    } else if(t=='mouseup') {   /// Si el evento es un mouseup.
      if(b&1) {                 /// | Si el disparador es el botón izquierdo.
        b = 0;                  /// | | Se señala.
        lb &= 0xFFFE;           /// | | Se pone a cero el bit correspondiente.
      } else if(b&2) {          /// | Si el disparador es el botón derecho.
        b = 2;                  /// | | Se señala.
        lb &= 0xFFFD;           /// | | Se pone a cero el bit correspondiente.
      } else if(b&4) {          /// | Si el disparador es el botón central.
        b = 1;                  /// | | Se señala.
        lb &= 0xFFFB;           /// | | Se pone a cero el bit correspondiente.
      } else {                  /// | En cualquier otro caso.
        b = 3;                  /// | | El disparador es el botón ficticio 3.
      }                         /// 
    /**-------------------------------------------------------------------------------
    /// Si el evento disparador no es ni mousedown ni mouseup entonces el botón
    /// disparador debe ser cero, ya que sólo el botón izquierdo puede generar click
    /// y dblclick en IE, y el evento mousemove no es generado por ningún botón.
    /// 
    /// Además de para poner a cero la propiedad button, este caso sirve para
    /// actualizar el estado de los botones en los eventos mousemove.
    ///-------------------------------------------------------------------------------*/
    } else {                    /// 
      if(t=='mousemove') {  /// Si el evento es mouse move
        lb = 256 | b;       /// | Tomamos el estado de los botones.
      }                     /// |
      b = 0;                /// Ningún botón desencadenó el evento
    }
    r.button = b;           /// La propiedad button del svEvent contiene ahora
                            /// el número del botón que disparó el evento.
    gefie.btn_st = lb;      /// La variable estática lb contiene el estado actual
                            /// de los botones del ratón.
    /**-------------------------------------------------------------------------------
    /// if(r.group==1) {
    ///   if(t!='mousemove') {
    ///     status = [t,b];
    ///   }
    /// }
    ///-------------------------------------------------------------------------------*/
    return r;               /// Devolver el objeto svEvent.
  }
/**-----------------------------------------------------------------------------------
*** private::mhmd                                                        private::mhmd
***-----------------------------------------------------------------------------------
*** Función manejadora del evento mousedown.
*** 
*** 
***-----------------------------------------------------------------------------------*/
  function mhmd(e) {
    /// ppp_obj está para ventanas popup, no hacer mucho caso de momento-
    _refresh_plug_props(e.target);
    if(_sv.ppp_obj) {
      if(!is_over(e.target, _sv.ppp_obj)) {
        _l_close(_sv.ppp_obj);
      }
    }
    _sv[e.button].le=1;
    mhmdx(e);
  }
  
  function _set_auto_plug(o) {
    var nn, tp,pnm, v, f;
    nn = o.nodeName;
    if(!nn) {
      return;
    }
    if(!o.getAttribute) {
      return;
    }
    if(nn=='INPUT') {
      pnm = o.name;
      if(!pnm) {
        return;
      }
      pnm = _sv.tolc(pnm);
      tp = o.getAttribute('type');
      if(!tp) {
        return;
      }
      tp = _sv.tolc(tp);
      if(tp=='checkbox') {
        pnm = "__ap_" + pnm;
        v = 0;
        if(o.checked) {
          v = 1;
        }
        _set_plug_value(pnm, v);
      }
      if(tp=='radio') {
        pnm = "__ap_" + pnm;
        v = 0;
        f = 0;
        if(o.checked) {
          v = parseInt(o.value);
          f = 1;
        }
        //_set_plug_value(
        _create_plug_value(pnm, v);
        if(f) {
          _set_plug_value(pnm, v);
        }
      }
    }
  }

/**-----------------------------------------------------------------------------------
*** private::mhmdx                                                      private::mhmdx
***-----------------------------------------------------------------------------------
*** hace casi todo el trabajo de mhmd, excepto activar el 
***-----------------------------------------------------------------------------------*/
  function mhmdx(e) {
    var o, b, t;
    o = _sv[e.button];
    if(o.st!=0) {
      t = e.target;
      e.target = _sv.root;
      hsmux(e);
      e.target = t;
    }
    _sv.mouse.buttons |= Math.pow(2,e.button);
    mh_elx(e);
    if(e._kf) return;
    o.ob = e.target;
    o.st = 1;
    o.md++;
    _set_auto_plug(e.target);
    e.type = 'm_down';
    _go(e.target, e);
    /// if(e._kf) return;
  }
///--------------------------------------------------------------------------------------
  function mhmu(e) {
    var b, o;
    _refresh_plug_props(e.target);
    b = e.button;
    o = _sv[b];
    if(o.st==0) {
      o.le = 3;
    } else {
      o.le = 2;
      hsmux(e);
    }
    _sv.mouse.cancels[b] = 0;
  }
///--------------------------------------------------------------------------------------
  function hsmux(e) {
    var o, et, ot, b;
    b = e.button;
    o = _sv[b];
    _sv.mouse.buttons&=0xFFFF^Math.pow(2,e.button);
    et = e.target;
    ot = o.ob;
    o.st = 0;
    o.ob = null;
    _set_auto_plug(et);
    e.type='m_up';
    _go(ot, e);
    if(e._kf) return;
    if(ot==et) {
      _set_auto_plug(et);
      e.type='m_click';
      _go(ot, e);
      if(e._kf) return;
    }
    e.target=et;
    mh_elx(e);
  }
/**-----------------------------------------------------------------------------------
*** private::mh_elx                                                    private::mh_elx
***-----------------------------------------------------------------------------------
*** Esta función es llamada en los eventos de ratón justo antes de generar un eveto 
*** m_down o un evento m_move, y justo despues de generar un evento m_up.
*** 
*** Se encarga de enviar los eventos m_enter y m_leave, si procede, y de mantener
*** actualizada la propiedad _sv.pointed. Además, devuelve el objeto al cual
*** hay que enviar el m_move (solo para el caso de que la función sea llamada
*** justo antes de generar el m_move).
***-----------------------------------------------------------------------------------*/
  function mh_elx(e) {
    var t,p;
    t=e.target;
    p=_sv.pointed;
    if(_sv.pointed!=t) {    /// Si el objeto apuntado no es el target del evento
      if(!_sv[0].ob) {      /// | Si no se ha pulsado el boton izquierdo sobre
                            /// | ningún objeto.
        if(p) {             /// | | Si hay algun objeto apuntado 
          e.type='m_leave'; /// | | | Se le envia un m_leave.
          e.fromto=t;       /// | | | e.target recibirá el m_enter
          _go(p, e);        /// | | | 
          if(e._kf) {       /// | | | Si se mató el evento.
            return null;    /// | | | | Devolver null.
          }                 /// | | |
        }                   /// | | |
        _sv.pointed=t;      /// | | El apuntado ahora es e.target.
        e.type = 'm_enter'; /// | | Se le enviará un m_enter.
        e.fromto=p;         /// | | El ratón salió de p.
        _go(t, e);          /// | |
        if(e._kf) {         /// | | Si se mató el evento.
          return null;      /// | | | Devolver null.
        }                   /// | |
      } else {              /// | Si el botón izquierdo está pulsado sobre algún
                            /// | objeto, 
        t = p;              /// | | No se envían eventos m_enter y m_leave, y el
                            /// | | evento actual se debe enviar al objeto apuntado.
      }
    }
    return t;
  }
/**-----------------------------------------------------------------------------------
*** private::mhmm                                                        private::mhmm
***-----------------------------------------------------------------------------------
*** Función manejadora del evento mousemove.
***-----------------------------------------------------------------------------------*/
  function mhmm(e) {
    e.target = mh_elx(e);
    if(e._kf) return;
    e.type = 'm_move';
    _go(e.target, e);
  }
/**--------------------------------------------------------------------------------------
*** private::mhcl                                                           private::mhcl
***--------------------------------------------------------------------------------------
*** Función manejadora del evento click.
*** 
*** RECIBE: El objeto svEvent.
*** 
*** COMENTARIOS:
*** 
*** Este evento NO se usa para enviar el evento m_click de svsys. El evento m_click
*** es generado tras el m_up, si se dirigió hacia el mismo objeto que el último
*** m_down.
*** 
*** El evento click se observa para detectar dobles clicks. Concretamente, si un
*** evento click llega justo despues de un evento dblclick, el sistema svsys debe
*** intentar generar un m_dblclick.
***-----------------------------------------------------------------------------------*/
  function mhcl(e) {
    var o;
    _refresh_plug_props(e.target);
    o=_sv[e.button];
    if(o.le==5) {
      mhdcx(e,1);
    }
    o.le=4;
  }
/**--------------------------------------------------------------------------------------
*** private::mhds                                                           private::mhds
***--------------------------------------------------------------------------------------
*** Función manejadora del evento dragstart.
*** 
*** NO ENTIENDO QUE HACE.
***-----------------------------------------------------------------------------------*/
  function mhds(e) {
    e.prevent_default();
  }
/**--------------------------------------------------------------------------------------
*** private::mhdc                                                           private::mhdc
***--------------------------------------------------------------------------------------
*** Función manejadora del evento dblclick.
*** 
*** RECIBE: El objeto svEvent.
*** 
*** COMENTARIOS:
*** 
*** Si el evento anterior para el botón disparador fue un mouseup descolocado, la
*** función llamará a mhdcx con un segundo parámetro activado, para que simule una
*** secuencia m_down - m_up - m_click, antes de generar, si procede, el evento
*** m_dblclick.
*** 
*** Si el evento anterior para el botón disparador fue un click, la función llamará
*** a mhdcx con un segundo parámetro desactivado, para que genere, si procede, el
*** evento m_dblclick sin simular dicha secuencia.
*** 
*** En cualquier otro caso, este evento no genera un m_dblclick. Aunque puede
*** generarlo posteriormente, si inmediatamente a este evento sigue un evento
*** click.
***-----------------------------------------------------------------------------------*/
  function mhdc(e) {
    var o;
    _refresh_plug_props(e.target);
    o=_sv[e.button];
    if(o.le==3) {
      mhdcx(e,1);
    } else if(o.le==4) {
      mhdcx(e,0);
    }
    o.le=5;
  }
/**--------------------------------------------------------------------------------------
*** private::mhdcx                                                         private::mhdcx
***--------------------------------------------------------------------------------------
*** RECIBE:
*** 
*** - El objeto svEvent.
*** - Un indicador de si se debe generar una secuencia m_down - m_up (con el
***   m_click implícito). Si es diferente de cero, se genera dicha secuencia.
***-----------------------------------------------------------------------------------*/
  function mhdcx(e,f) {
    var o;
    o=_sv[e.button];        /// o se refiere al objeto de estado del botón en svsys.
    if(f) {                 /// Si hay que simular un mousedown y un mouseup antes
      mhmdx(e);             /// | Se simula el mousedown.
      hsmux(e);             /// | Se simula el mouseup.
    }                       /// | 
    if(o.md>1) {            /// Si hubo más de un m_down desde el último m_dblclick
      e.type='m_dblclick';  /// | Generear un m_dblclick.
      _go(e.target, e);     /// |
      if(e._kf) return;     /// | Si el evento se mató: terminar.
      o.md = 0;             /// | Poner a cero el contador de m_down.
    }
  }
///--------------------------------------------------------------------------------------
  function mhmo(e) {}

/**-----------------------------------------------------------------------------------
*** private::kh_nf                                                      private::kh_nf
***-----------------------------------------------------------------------------------
*** Keyboard Handler New Focus.
*** 
*** Es llamada en algunos eventos de teclado para observar la posibilidad de que
*** el foco haya cambiado sin que svsys se haya percatado de ello.
***-----------------------------------------------------------------------------------*/
  function kh_nf(e) {
    var t,f,n,c;
    c=0;
    t=e.target;
    f=_sv.focusObj;
    if(t==f) return;
    n=t.nodeName;
    if(n=='INPUT'){if(!t.disabled)c=1;}
    if(n=='SELECT'){if(!t.disabled)c=1;}
    if(c) _focus(t);
  }
///--------------------------------------------------------------------------------------
  function khkd(e) {
    var skp,lkp,kc,cc,t,ckd;
    _refresh_plug_props(e.target);
    skp = _sv._keysys.skp;
    lkp = _sv._keysys.lkp;
    ckd = _sv._keysys.ckd;
    kc=e.key_code;
    cc=e.char_code;
    t = e.time - lkp[kc];
    ckd[kc] = 0;
    lkp[kc] = e.time;
    e.char_code = 0;
    if(t>2000) {
      kh_nf(e);
      /// window.status=_sv.focusObj.nodeName;
      e.type = 'k_down';
      _go(_sv.focusObj, e);
      if(e._kf) return;
    }
    if(skp[kc]) {
      e.type = 'k_press';
      _go(_sv.focusObj, e);
      if(e._kf) return;
      if(e._cf) {
        ckd[kc] = 1;
      }
    }
    e.char_code = cc;
  }
///--------------------------------------------------------------------------------------
  function khku(e) {
    var lkp, cc, kc, ckd;
    _refresh_plug_props(e.target);
    lkp = _sv._keysys.lkp;
    ckd = _sv._keysys.ckd;
    kc=e.key_code;
    cc=e.char_code;
    lkp[kc] = 0;
    ckd[kc] = 0;
    e.type = 'k_up';
    e.char_code = 0;
    _go(_sv.focusObj, e);
    if(e._kf) return;
    e.char_code = cc;
  }
///--------------------------------------------------------------------------------------
  function khkp(e) {
    var skp, lkp, kc, cc, t, ckd;
    _refresh_plug_props(e.target);
    skp = _sv._keysys.skp;
    lkp = _sv._keysys.lkp;
    ckd = _sv._keysys.ckd;
    kc=e.key_code;
    cc=e.char_code;
    lkp[kc] = e.time;
    if(kc!=0 && kc<32) {
      if(kc==13 || kc==10) {
        cc = kc;
      } else if(kc) {
        cc = 0;
      }
    }
    if(cc==0) {
      if(skp[kc]) {
        skp[kc] = 0;
        if(ckd[kc]) {
          ckd[kc] = 0;
          e.prevent_default();
        }
        return;
      }
    }
    ckd[kc] = 0;
    e.char_code = cc;
    if(cc) {
      e.key_code = 0;
    }
    e.type = 'k_press';
    _go(_sv.focusObj, e);  
    /// if(e._kf) return;
  }
///--------------------------------------------------------------------------------------
  function ghss(e) {
    if(_sv.mouse.cancels[0]) {
      e.prevent_default();
    }
  }
///--------------------------------------------------------------------------------------
  function ghcp(e) { }
///--------------------------------------------------------------------------------------
  function whsc2() {
    var e;
    e = gneo(_sv, 'scroll');
    whsc(e);
  }
  
  function whsc(e) {
    var b,x,y,s;
    s=_sv.scroll;
    b = _sv.body;
    x=b.scrollLeft;
    y=b.scrollTop;
    if(x!=s[0] || y!=s[1]) {
      move_table_headers(x, y);
      s[0]=x;
      s[1]=y;
      x=e.group;
      e.group=4;
      e.type = 'w_scroll';
      _go(b, e);
      if(e._kf) return;
      e.group=x;
    }
  }
///--------------------------------------------------------------------------------------
  function whsb(e) {
    var b,i,ii,c,cc;
    cc = e.target.elements;
    ii = cc.length;
    for(i=0; i<ii; i++) {
        c = cc[i];
        if(c._sv_frm) {
            c._sv_frm[0](e, c);
        }
    }
    e.type = 'w_submit';
    e.group=4;
    _go(e.target, e);
    /// if(e._kf) return;
  }
///--------------------------------------------------------------------------------------
  function whrs(e) {
    var b;
    e.type = 'w_resize';
    _go(_sv.body, e);
    /// if(e._kf) return;
  }
  
///--------------------------------------------------------------------------------------
  function whld(e) {
    var t,n;
    t=e.target;
    n=(!t)?'BODY':t.nodeName;
    if(t==window || t==document || n=='BODY') {
///      _start();
    }
  }
///--------------------------------------------------------------------------------------
  function chch(e) {
    _refresh_plug_props(e.target);
  }

  function whul(e) {
    var w,d,w2,e,oo;
    w = _sv.get_win();
    if(!w) return;
    d = w.document;
    if(d._sv_unload) return;
    d._sv_unload = 1;
/*
    if(!confirm("¿Desea salir de la aplicación?")) {
      e = new _svEventObject(null,4); 
      e.type  = 'w_submit';
      _go(d.forms["frm"], e);
      w2 = w.open();
      svjs_do_aux2(w,w2,[svdo, 'reload']);
    }
    */
///    if(t==window || t==document || n=='BODY') {
///      _start();
///    }
  }
/**--------------------------------------------------------------------------------------
*** svsys::start                                                          svsys::start
***--------------------------------------------------------------------------------------
*** Inicia el sistema svsys.
*** 
***--------------------------------------------------------------------------------------*/
  function _start() {
    var o,h,hs,hsp,i,ii;
    if(!_sv.loaded) {
      _sv.loaded=1;
      load_func_exec(-5000);
      _init_node(document, _sv.fie);
      _l_set_sys_event_handlers();
      load_func_exec(5000);
      hsp = _sv.tbl_hdrs_p;
      hs = _sv.tbl_hdrs;
      ii = hsp.length;
      for(i=0; i<ii; i++) {
        h = hsp[i];
        h[2] = document.getElementById(h[0]);
        h[3] = document.getElementById(h[1]);
        if(h[2] && h[3]) {
          h[4] = 0;
          hs[hs.length] = h;
        }
      }
    }
  }

  function _ua() {
    var re, s, r, v;
    re = /msie\s?(\d+)|(msie)|(firefox)|(opera)/gi;
    if(!navigator) {
        return "UNKNOWN";
    }
    s = navigator.userAgent;
    if(!s) {
        return "UNKNOWN";
    }
    r = re.exec(s);
    if(!r) {
        return "UNKNOWN";
    }
    if(r[1]) {
        v = parseInt(r[1]);
        if(v>6) {
          return "IE7";
        }
        return "IE";
    }
    if(r[2]) {
        return "IE";
    }
    if(r[3]) {
        return "FIREFOX";
    }
    if(r[4]) {
        return "OPERA";
    }
    return "UNKNOWN";
  }

  function move_table_headers(x, y) {
    var h,hs,i,ii,x1,y1,x2,y2td1,td2,cw1,cw2;
    hs = _sv.tbl_hdrs;
    ii = hs.length;
    for(i=0; i<ii; i++) {
      h = hs[i];
      _or(h[2]);
      x1 = _sv.rv[0];
      y1 = _sv.rv[1];
      x2 = _sv.rv[2];
      y2 = _sv.rv[3];
      if((y>y1) && y<(y2-20)) {
        if(!h[4]) {
          h[4] = 1;
          h[3].style.display='';
        }
        h[3].style.top = y;
        h[3].style.left = x1;
        h[3].style.width = x2-x1;
        td1 = _get_child(h[2], 'TD', null);
        td2 = _get_child(h[3], 'TD', null);
        
        while(td1 && td2) {
          cw1 = td1.clientWidth;
          td2.style.width = cw1;
          cw2 = td2.clientWidth;
          if(cw2>cw1) {
            td2.style.width = 2*cw1-cw2;
          }
          td1 = _get_sibling(td1, 'TD');
          td2 = _get_sibling(td2, 'TD');
        }
        
      } else {
        if(h[4]) {
          h[4] = 0;
          h[3].style.display='none';
        }
      }
    }
  }

///--------------------------------------------------------------------------------------
/// svsys:init_node                                                       svsys:init_node
///--------------------------------------------------------------------------------------
  function _init_node(o) {
    var cs, i, ii;
    init_1_node(o);
    cs = o.childNodes;
    ii = cs.length;
    for(i=0; i<ii; i++) {
      _init_node(cs[i]);
    }
  }
  ///------------------------------------------------------------------------------------
  /// 
  ///------------------------------------------------------------------------------------
  function init_1_node(o) {
  ///------------------------------------------------------------------------------------
    var e, en, eht, i, ii, i1, i2, re, ra, ar, rer, t, c, pt, pe, tp, fnm, h, nn;
  ///------------------------------------------------------------------------------------
    nn = o.nodeName;
    if(nn=='SELECT') {
      _refresh_plug_props(o);
      _sv.select_list[_sv.select_list.length] = o;
    } else if(nn=='OBJECT') {
      _sv.object_list[_sv.object_list.length] = o;
    } else if(nn=='INPUT') {
      _set_auto_plug(o);
    }
    if(!o.getAttribute) {             /// Si el objeto no tiene este método.
      return;                         /// | Terminar
    }                                 /// -------------------------------------------------
    tp = o.getAttribute('sv_plugout');/// Tomar el atributo 'sv_plugout'.
    if(tp!=null && tp!='') {          /// Si está definido.
      _set_plugouts_str(o, tp);
    }
    tp = o.getAttribute('sv_plugin'); /// Tomar el atributo 'sv_plugin'.
    if(tp!=null && tp!='') {          /// Si está definido.
      _set_plugins_str(o, tp);
    }


    tp = o.getAttribute('sv_type'); /// Tomar el atributo 'sv_type'.
    if(tp!=null && tp!='') {        /// Si está definido.
      pt = "_f_sv_"+tp;             /// | pt = nombre de la marca de inicialización.
      if(!o[pt]) {                  /// | Si el objeto no ha sido ya inicializado.
        fnm = "init_sv_"+tp;        /// | | fnm = nombre de la función de inicialización.
        if(_sv[fnm]) {              /// | | Si la función existe en svsys.
          _sv[fnm](o);              /// | | | Llamarla.
        } else if(window[fnm]) {    /// | | Si la función existe en el ámbito global.
          window[fnm](o);           /// | | | Llamarla.
        }                           /// | | 
        o[pt] = 1;                  /// | | El objeto ya ha sido inicializado.
      }                             /// | 
    }                               /// 
    e = o.getAttribute('sv_event'); /// Tomar el atributo sv_event.
    if(e==null || e=='') {          /// Si no está definido o es nulo.
        return;                     /// | Terminar
    }                               /// 
    i = -1;                         /// 
    ii = e.length;                  /// 
    /**-------------------------------------------------------------------------------
    /// La siguiente expresión regular busca las siguientes cadenas:
    /// 
    /// - Uno o mas espacios consecutivos (las tabulaciones cuentan como espacios).
    /// - Un carácter @.
    /// - Un carácter ;.
    /// - Un carácter : seguido opcionalmente de un signo + o un signo -.
    /// - Una cadena encerrada entre comillas dobles.
    /// - Una cadena encerrada entre comillas simples.
    ///-------------------------------------------------------------------------------*/
    re = /[ \t]+|[@;]|:[\+\-]?|\"([^\\\"]|\\.)*\"|\'([^\\\']|\\.)*\'+/g;
    ra = [];
    ar = [];
    regexp_exec_all(re,e,ra);
    i=0;
    ii=ra.length;
    ra[ii] = 1;
    ra[ii+1] = ':';
    ii+=2;
    pt = 1; /** pt podrá valer, en el bucle siguiente, uno de estos valores:
            /// 1 : Se espera un nombre de evento.
            /// 2 : Se espera un nombre de handler.
            /// 3 : Se espera el primer parámetro opcional para el handler.
            /// 4 : Se espera el segundo parámetro opcional para el handler.
            /// N : Se espera parámetro (N-2) opcional para el handler. */
    i1=0;
    while(i<ii) {
      tp=ra[i];
      t=ra[i+1];
      if(tp!=0) {
        c=t.charAt(0);
        if(c==';') {
          pt=1;
        } else if(c==':') {
          if((pt==1)||(pt==2)) {
            pt=2;
            if(t==':+') {
              eht=10;
            } else if(t==':') {
              eht=11;
            } else {
              eht=12;
            }
          } else {
            pt=0;
          }
        } else if((c=='"')||(c=="'")) {
          if(pt>=3) {
            tp=0;
          }
        }
      }
      if(tp==0){
        if(pt==1) {
          en=t;
          pt=2;
          eht=11;
        } else if(pt==2) {
          ar[i1]=en;
          ar[i1+1]=eht;
          ar[i1+2]=t;
          ar[i1+3]=0;
          i2=i1+3;
          i1+=4;
          pt=3;
        } else if(pt>=3) {
          ar[i1] = eval(t);
          i1++;
          ar[i2]++;
          pt++;
        }
      }
      i+=2;
    }
    ii = i1;
    i = 0;
    while (i<ii) {
      h = ar[i+2];
      h = (window[h]) ? window[h] : eval(h) ;
      i = add_event_handler_x(o, ar[i], ar[i+1], h, ar[i+3], ar, i+4, _sv);
    }
  }
  /**
   * 
   *
   *
   *
   * @return 
   */
  function add_event_handler_x(o, en, eht, h, c, ar, i, n) {
    var s, pe, b;
    if(eht==11) {            /// Si es un manejador normal.
      if(!o._sv_events) {
        o._sv_events = {};
      }
      s=o._sv_events;
      if(!s[en]) {
        s[en] = [];          /// | Se crea una entrada para él
                             /// | en el objeto.
      }
      b = s[en].length;
      s[en][b] = [];
      pe = s[en][b];         /// | Se referencia.
    } else {                 /// Si es un manejador de notify.
      if(eht==10) {          /// | Si es previo
        if(!n._sv_pre) {
          n._sv_pre={};

        }
        pe = n._sv_pre;      /// | | Se referencia el array de previos.
      } else {               /// | Si NO es previo
        if(!n._sv_poe) {
          n._sv_poe={};
        }
        pe = n._sv_poe;      /// | | Se referencia el array de posteriores.
      }
      if(!pe[en]) {          /// | Si no existe ningún notify para este mensaje.
        pe[en] = [];         /// | | Se crea el array notifys de este tipo.
      }
      b = pe[en].length;     /// | Se va a añadir en pe[en][b].
      pe[en][b] = [];        /// | Se crea el siguiente descriptor de manejador
      pe = pe[en][b];        /// | Se referencia.
      pe.eo = o;
    }
    /// Aquí pe se refiere a un Array donde hay que dejar la descripción del manejador
    /// (la función y la lista de parámetros que recibe).
    pe.eh = h ;
    for(b=0; b<c; b++,i++) {
      pe[b] = ar[i];
    }
    return i;
  }

  /**
   * Añade un manejador para un evento a un objeto.
   * 
   * @param: object (DOM). El objeto.
   * @param: string. El nombre del evento.
   * @param: object (function). La función manejadora del evento.
   * @param: [opcional] Parámetro de usuario a enviar a la funcion manejadora.
   * @param: [opcional] Parámetro de usuario a enviar a la funcion manejadora.
   * ...
   * @param: [opcional] Parámetro de usuario a enviar a la funcion manejadora.
   */
  function add_event_handler(o, e, h) {
    var a,c;
    a = add_event_handler.arguments;
    c = a.length;
    add_event_handler_x(o, e, 11, h, c-3, a, 3, _sv);
  }

  /**
   * Añade un manejador de notificación para un evento a un objeto. Los eventos de
   * notificación los voy a quitar, y creo que actualmente no los uso, así que mejor
   * no hacer mucho caso a esto.
   */
  function add_notify_handler(n, m, o, e, h) {
    var a,c;
    a = add_notify_handler.arguments;
    c = a.length;
    m=(m)?12:10;
    add_event_handler_x(n, e, m, h, c-5, a, 5, o);
  }
///--------------------------------------------------------------------------------------
  function parse_atts(t,o) {
    var re,ar,ii,i;
    t = t + ';'
    re = /[ \t]*[a-zA-Z_][a-zA-Z0-9_-]*[ \t]*:(\"([^\\\"]|\\.)*\"|\'([^\\\']|\\.)*\'|[^;])*;/g;
    ar = [];
    regexp_exec_all(re,t,ar);
    ii=ar.length;
    for(i=0;i<ii;i+=2) {
      if(ar[i]) {
        patt(ar[i+1],o);
      }
    }
  }
///--------------------------------------------------------------------------------------
  function patt(t,o) {
    var i, ii, k, v, c;
    i = t.indexOf(':');
    if(i<0) { return false; }
    ii = t.length;
    while(ii) {
      c = t.charAt(ii-1);
      if(c!=';') {
        break;
      }
      ii--;
    }
    k = t.substr(0,i);
    v = t.substr(i+1,ii-i-1);
    k = _sv.trim(k);
    if(k=='') { return; }
    o[k]=eval(v);
  }
///--------------------------------------------------------------------------------------
  function parse_atts2(t,o) {
    var re,ar,ii,i,oo;
    t = t + ';'
    re = /[ \t]*[a-zA-Z_][a-zA-Z0-9_-]*[ \t]*:(\"([^\\\"]|\\.)*\"|\'([^\\\']|\\.)*\'|[^;])*;/g;
    ar = [];
    regexp_exec_all(re,t,ar);
    ii=ar.length;
    for(i=0;i<ii;i+=2) {
      if(ar[i]) {
        patt2(ar[i+1],o);
      }
    }
  }
///--------------------------------------------------------------------------------------
  function patt2(t,o) {
    var i, ii, k, v, c;
    i = t.indexOf(':');
    if(i<0) { return false; }
    ii = t.length;
    while(ii) {
      c = t.charAt(ii-1);
      if(c!=';') {
        break;
      }
      ii--;
    }
    k = t.substr(0,i);
    v = t.substr(i+1,ii-i-1);
    k = _sv.trim(k);
    if(k=='') { return; }
    o.push(k, eval(v));
  }

/**
 * Dada una expresión regular, un texto y un array, divide el texto en tramos,
 * usando la expresión regular como delimitador, y deja en el array la
 * siguiente información:
 * 
 * - Por cada tramo en el texto, dos items (N y N+1), de los cuales el primero
 *   es 0 o 1, y el segundo es el texto del tramo.
 * 
 * - Si el primer item vale 0, indica que el tramo no coincide con la expresión regular
 *   (texto huérfano).
 * 
 * - Si el primer item vale 1, indica que el tramo coincide con la expresión regular
 *   (coincidencia).
 * 
 * Los tramos en el array se guardan en el orden de aparición.
 * 
 * @param: object(RegExp) Expresión regular, debe tener establecida la opción 'g'.
 * @param: string. El texto que hay que dividir en trozos.
 * @param: array (salida). El array donde dejar los trozos (OJO: usar el valor devuelto
 *         para ver cuantos son válidos porque puede no coincidir con el tamaño final/2)
 * @return: El número de trozos descritos en el array.
 * @author: a_vera
 */
  function regexp_exec_all(re,t,ar) {
    var r,ii,i2,i1,i3,i,m;
    i1=i=0;
    ii=t.length;
    do {
      r = re.exec(t);
      if(r==null) {         /// Si no hay coincidencia.
        m='';               /// | Se considera vacía.
        i2=i3=ii;           /// | Y que empieza y termina en al final de la cadena.
      } else {              /// Si hay coincidencia.
        i2=re.lastIndex;    /// | La coincidencia termina en i2 (no incluido).
        i3=r.index;         /// | Y comienza en i3.
        m=r[0];             /// | El texto de la coincidencia en m.
      }                     /// 
      //# El tramo huérfano va desde i1 hasta i3 (no incluido)
      if(i3!=i1) {          /// Si el tramo huérfano no está vacío.
        ar[i]=0;            /// | Se añade al array.
        ar[i+1]=t.substr(i1,i3-i1);
        i+=2;
      }                     
      if(i2!=i3) {          /// Si la coincidencia no está vacía.
        ar[i]=1;            /// | Se añade al array.
        ar[i+1]=m;
        i+=2;
      }
      i1=i2;                /// El primer caracter a analizar en i1.
    } while(r!=null);       
    return i/2;
  }
///--------------------------------------------------------------------------------------
  function _go(o, e) {
    var r, p;
    e.target = o;
    e.self = o;
    e._fsvsys = 0;    /// Este indicador se hará 1 si el evento alcanza a
                      /// a _sv.
    _go_r(o, e);
    if(e._kf) return;
    if(!e._fsvsys) {
      e.prevent_default();
    }
  }
///--------------------------------------------------------------------------------------
  function _go_r(o, e) {
    var tp,t,gr;
    t = e.target;
    tp = e.type;
    gr = String(e.group);
    e._fwd = 0;
    do {
      if(o._sv_pre){
        _cpp(e, o._sv_pre, tp);
        if(e._kf) break;
      }
      if(o._sv_events) {
        if(o._sv_events[tp]) {
          _call(o, e, o._sv_events[tp]);
          if(e._kf) break;
        } else if(o._sv_events[gr]) {
          _call(o, e, o._sv_events[gr]);
          if(e._kf) break;
        } else if(o._sv_events.all) {
          _call(o, e, o._sv_events.all);
          if(e._kf) break;
        }
      }
      if(o._sv_poe){
        _cpp(e, o._sv_poe, tp);
        if(e._kf) break;
      }
      if(o._is_svsys) {
        e._fsvsys = 1;          /// El evento alcanzó al sistema.
        break;
      }
      if(e._fwd) {              /// Si el evento ya ha sido propagado:
        break;                  ///  | Se detiene la propagación.
      }
      if(t!=e.target) {         /// Si se ha cambiado el objetivo del evento.
        o=t=e.target;
      } else {
        o=(o==_sv.body)
          ? _sv
          : ((o.parentNode)?o.parentNode:_sv);
      }
    } while(o!=null);
  }
///--------------------------------------------------------------------------------------
  /**
   * Llama a los manejadores de eventos de un objeto.
   * 
   * @param: El objeto cuyos manejadores hay que invocar.
   * @param: El evento (objeto svEvent).
   * @param: El array de manejadores.
   * @author: a_vera
   */
  function _call(o, e, dd) {
    var i, ii;
    ii = dd.length;
    e.self = o;
    for(i=0; i<ii; i++) {
      d = dd[i];
      switch(d.length) {
      case 0 : d.eh(e); break;
      case 1 : d.eh(e, d[0]); break;
      case 2 : d.eh(e, d[0], d[1]); break;
      case 3 : d.eh(e, d[0], d[1], d[2]); break;
      case 4 : d.eh(e, d[0], d[1], d[2], d[3]); break;
      case 5 : d.eh(e, d[0], d[1], d[2], d[3], d[4]); break;
      default: d.eh(e, d[0], d[1], d[2], d[3], d[4], d); break;
      }
    }
  }
///--------------------------------------------------------------------------------------
  function _cpp(e, ds, tp) {
    var i, ii, d;
    if(ds[tp]) {
      d = ds[tp];
      ii = d.length;
      for(i=0; i<ii; i++) {
        _call(d[i].eo, e, d[i]);
        if(e._kf) break;
      }
    }
  }
///--------------------------------------------------------------------------------------
  function load_function(f, o) { /// Función, orden.
    var b, ii, jj, h, h2, u;
    b = _sv._loadfuncs;
    h = String(o);
    ii = h.length;
    while(ii<4) {
      h='0'+h;
      ii++;
    }
    h = '_S'+h.substr(0,4);
    ii = 65;
    jj = 65;
    h2 = h;
    u = '_';
    while(b[h]) {
      h=h2+u+String.fromCharCode(jj)+String.fromCharCode(ii);
      ii++;
      if(ii>=90){
        ii=65;
        jj++;
        if(jj>=90){
          jj=65;
          u = u + 'Z';
        }
      }
    }
    b[h] = f;
    b[b.length] = h;
  }
///--------------------------------------------------------------------------------------
  function load_func_exec(l) {
    var a, i, ii, n;
    a = _sv._loadfuncs;
    a.sort();
    ii = a.length;
    if(l>=0) {
      for(i=0; i<ii; i++) {
        n = parseInt(a[i].substr(2,4));
        if(n>=0) {
          a[a[i]]();
        }
      }
    } else {
      for(i=0; i<ii; i++) {
        n = parseInt(a[i].substr(2,4));
        if(n<0) {
          a[a[i]]();
        }
      }
    }
  }
/**-----------------------------------------------------------------------------------
*** private::_unfocus                                                private::_unfocus
***-----------------------------------------------------------------------------------
*** Envía el evento k_unfocus a un objeto. Además, si se trata de un objeto de
*** formulario, llamará a su método blur.
*** 
*** RECIBE:
*** 
*** - Un objeto svEvent.
*** - El objeto al que enviar el unfocus.
*** 
*** COMENTARIOS
*** 
*** Esta función es para uso interno, y realmente en este momento no hay ninguna
*** razón para que sea una función diferente.
***-----------------------------------------------------------------------------------*/
  function _unfocus(e, o) {
    var n;
    if(_is_frm_obj(o)) {    /// Si se trata de un objeto de FORM.
      n=_sv.rv[0];          /// | Tomar el raiz del objeto.
      if(!n.disabled) {     /// | Si no está desabilitado.
        n.blur();           /// | | Quitarle el foco del sistema.
      }                     /// | 
    }                       /// | 
    e.type  = 'k_unfocus';  /// Se prepara e el mensaje 'k_unfocus'.
    _go(o, e);              /// Se envía al objeto.
  }
  
  
  function submit_form(f) {
    var e, oo;
    e = new _svEventObject(null,4); 
    e.type  = 'w_submit';
    _go(f, e);
    return true;
  }
  
/**-----------------------------------------------------------------------------------
*** svsys::focus                                                          svsys::focus
***-----------------------------------------------------------------------------------
*** Le da el foco de teclado a un determinado objeto.
***-----------------------------------------------------------------------------------*/
  function _focus(o) {
    var e, oo;
    e = new _svEventObject(null,2); 
    oo = _sv.focusObj;
    if(o==null) { o=_sv; }
    if(o==oo) { return; }

    /// Enviar k_unfocus al objeto que pierde el foco.
    e.fromto = o;
    _unfocus(e, oo);
    if(e._kf) return;

    /// Enviar k_focus al objeto que recibe el foco.
    if(_is_frm_obj(o)) o.focus(); 
    e.type  = 'k_focus';
    e.fromto = oo;
    _go(o, e);
    if(e._kf) return;

    _sv.focusObj = o;
  }
///--------------------------------------------------------------------------------------
  function fire(o, en) {
    var e;
    e = gneo(fire.arguments);
    _go(o, e);
    /// if(e._kf) return;
  }

///--------------------------------------------------------------------------------------
  function gneo(a) {
    var e, i, ii, a;

                            /// Crear el nuevo objeto svEvent.
    e = new _svEventObject(null,0); 
    e.type = a[1];          /// Actualizar el nombre del [sv-]evento.
    e.target = a[0];        /// Actualizar el target del [sv-]evento.
    ii = a.length;          
    for(i=2; i<ii; i++) {   /// Para cada argumento presente en el
                            /// array de entrada.
      e.args[i-2] = a[i];   /// | Crear un item en el array de argumentos
                            /// | del objeto svEvent.
    }                       ///
    return e;               /// Devover el objeto svEvent creado.
  }

///--------------------------------------------------------------------------------------
  function get_node(o) {
    var v;
    v=typeof(o);
    if(v=='string') {
      o=document.getElementById(o);
    }
    return o;
  }
///--------------------------------------------------------------------------------------
  function is_opened(o) {
    o=get_node(o);
    if(!o) { return 0;}
    return (!o._sv_dopen) ? 0: 1;
  }
/**--------------------------------------------------------------------------------------
*** Abre un objeto como si fuera una ventana popup.
*** - Una referencia al objeto o bien su ID.
*** - El tipo de ventana popup:
***   bit[0] : Modal. Impide que mientras esté abierta, otros controles reciban eventos.
***   bit[1] : Close on click (Cierra al pulsar cualquier boton fuera de la ventana).
***   bit[2] : Close on leave (Cierra al alejarse el cursor fuera de la ventana).
*** De momento solo soporto el bit 1.
***--------------------------------------------------------------------------------------*/
  function _l_close(o) {
    var e,i,ii,sl;
    sl = _sv.select_list;
    ii = sl.length;
    for(i=0; i<ii; i++) {
      sl[i].style.visibility='visible';
    }
    o = get_node(o);
    if(_sv.ppp_obj==o) {
      _sv.ppp_obj = false;


    }
    if(o) {
        if(o.style) {
            o.style.display = 'none';
            e = new _svEventObject(null,4); 
            e.type  = 'd_close';
            _go(o, e);
        }
    }
    return true;
  }

  function _l_close_popup() {
      return _l_close(_sv.ppp_obj);
  }

  function _l_popup(o, t, x, y, w, h) {
    var s,a1,a2,b,r,i,ii,sl;
    var sw, sh;
    s = _sv;
    b = s.ppp_obj;
    if(b) _l_close(b);
    sl = _sv.select_list;
    ii = sl.length;
    for(i=0; i<ii; i++) {
      sl[i].style.visibility='hidden';
    }
    a1 = s.a1;
    a2 = s.a2;
    b = _sv.body;
    r = _sv.rv;
    o = get_node(o);

    sw = sh = sx = sy = false;
    if(t==undefined) t = true;
    if(w!=undefined) sw = true;
    if(h!=undefined) sh = true;
    if(x!=undefined) {
        sx = true;
    } else {
        if(t&1) sx = true;
    }
    if(y!=undefined) {
        sy = true;
    } else {
        if(t&2) sy = true;
    }
    o.style.display = 'block';
    if(!sw) w = o.clientWidth;
    if(!sh) h = o.clientHeight;
    if(t&1) {
        x = b.scrollLeft + (b.clientWidth-w)/2
    }
    if(t&2) {
        y = b.scrollTop + (b.clientHeight-h)/2
    }
    if(sx) o.style.left = "" + x + "px";
    if(sy) o.style.top = "" + y + "px";
    if(sw) o.style.width = "" + w + "px";
    if(sh) o.style.height = "" + h + "px";
    s.ppp_obj = o;
    e = new _svEventObject(null,4); 
    e.type  = 'd_open';
    _go(o, e);
  }

///--------------------------------------------------------------------------------------
  function _l_test_popups() {
  }
///--------------------------------------------------------------------------------------
  function get_rv(n) {
    var a;
    a=new Array();
    cpy_rv(a,n);
    return a;
  }
///--------------------------------------------------------------------------------------
  function cpy_rv(a,n) {
    var i;
    for(i=0;i<n;i++) {
      a[i]=_sv.rv[i];
    }
  }
///--------------------------------------------------------------------------------------
  function is_emp(a) {
    return (a==''||a==null||a==undefined) ? 1 : 0 ;
  }
///--------------------------------------------------------------------------------------
  function get_z(o) { /// FALTA: Ahora no mira estilos computados, tal vez sea más
    var z;            /// rápido y fiable consultar el valor computado.
    if(is_emp(o)||!o.style)return 0;
    z=o.style.zIndex;
    return (is_emp(z))?get_z(o.parentNode):z;
  }
///--------------------------------------------------------------------------------------
  function is_over(o,p) {
    var o2;
    do {
        o2 = o;
        if(o==p) {
            return true;
        }
        o = o.parentNode;
        if(o==o2) {
            return false;
        }
    } while(o);
    return false;
  }
///--------------------------------------------------------------------------------------
  function _collision(a,b) {
    _dcx(a,b,0);
    _dcx(a,b,1);
  }
///--------------------------------------------------------------------------------------
  function _dcx(a,b,i) { /// Auxiliar para {_collision}.
    var c;
    c=a[i]-b[i];
    if(c>=0) {
      c=a[i+2]-b[i+2];
      if(c<0)c=0;
    }
    _sv.rv[i]=c;
  }

  function hml(e) {
    //get_node("popup2").style.visibility='hidden';
  }
  function hme(e) {
    //get_node("popup2").style.visibility='visible';
/**
    window.status=e.target.nodeName;
    if(e.target.nodeName=='IMG')
    e.target.style.cursor='wait';
*/
  }
///--------------------------------------------------------------------------------------
  function hmd(e) {
    /// Función del sistema para 'm_down'
/*
    if(!is_opened("popup2")) {
      //    ("popup2",2);
    } else {
      //_l_popup("popup1",2);
    }
*/
  }
///--------------------------------------------------------------------------------------
  function hmu(e) { }
///--------------------------------------------------------------------------------------
  function create_element(t) { return document.createElement(t); }
///--------------------------------------------------------------------------------------
  function append_child(o,c) { return o.appendChild(c); }
///--------------------------------------------------------------------------------------
  function insert_before(o,b,c) {
    if(b==null) {
      return append_child(o, c);
    }
    if(o!=b.parentNode) {
      return append_child(o, c);
    }
    return o.insertBefore(c, b);
  }
///--------------------------------------------------------------------------------------
  function _remove_child(o,c) { return o.removeChild(c); }
/**-----------------------------------------------------------------------------------
*** svsys::remove_childs                                          svsys::remove_childs
***-----------------------------------------------------------------------------------
*** Elimina todos o un rango de hijos de un objeto DOM dado.
*** 
*** RECIBE:
*** 
*** - El objeto cuyos hijos hay que eliminar.
***-----------------------------------------------------------------------------------*/
  function _remove_childs(o,i1,i2) {
    var c,i,ii,g;
    c=o.childNodes;
    ii=c.length;
    if(i1==null)i1=0;
    if(i2==null)i2=ii;
    if(i2>ii){i2=ii;}
    for(i=i1;i<i2;i++){
      g=c[i1];
      o.removeChild(c[i1]);
      delete g;
    }
    return i2-i1;
  }

  /**
   * Mueve un objeto dentro de su contenedor a una posición diferente.
   * 
   * @param: Objeto a mover, o un hijo del mismo (si el siguiente parámetro no coincide,
   *         con el tipo de objeto pasado se buscará un padre que si coincida).
   * @param: Tipo del objeto a mover (TR pra mover filas, TD para mover columnas...).
   * @param: Tipo del objeto padre en el que buscar hermanos (TABLE pra mover filas,
   *         TR para mover columnas...).
   * @param: Desplazamiento (un numero positivo para abajo o derecha, negativo para
   *         arriba o izquierda).
   * @param: opcional, posición mínima que ocupará el objeto en el padre.
   * @param: opcional, posición máxima que ocupará el objeto en el padre, si es cero
   *         o negativo, se considera un valor relativo a la ultima posición.
   * @author: a_vera.
   */
  function _move_child(r,tr,tbl,n,mn,mx) {
    var r,t,rs,ii,i,ni;
    r = _sv.get_parent(r, tr, null, 1);
    if(!r) {
      return null;
    }
    t = _sv.get_parent(r);
    rs = _sv.get_childs(t, tr, null, null, 1);
    ii = rs.length;
    if(mn==undefined) {
      mn = 0;
    }
    if(mx==undefined) {
      mx = ii-1;
    } else if(mx<0) {
      mx = ii-1+mx;
    }
    if(mx<0) {
      return null;
    }
    if(mn>=ii) {
      return null;
    }
    if(mx<mn) {
      return null;
    }
    for(i=0; i<ii; i++) {
      if(rs[i]==r) {
        ni = i + n;
        if(ni<mn) {
          ni=mn;
        }
        if(ni>mx) {
          ni=mx;
        }
        if(ni==i) {
          break;
        }
        if(ni>i) {
          if(n<=0) {
            break;
          }
          ni++;
        } else {
          if(n>=0) {
            break;
          }
        }
        _sv.remove_child(t, rs[i]);
        if(ni>=ii) {
          _sv.insert_before(t, null, rs[i]);
        } else {
          _sv.insert_before(t, rs[ni], rs[i]);
        }
        rs = _sv.get_childs(t, tr, null, null, 1);
        return rs;
      }
    }
  }

  /**---------------------------------------------------------------------------------
  /// svsys::trim (_trim)                                          svsys::trim (_trim)
  ///---------------------------------------------------------------------------------
  /// Dada una cadena, la devuelve trimeada. Es decir sin caracteres de espacio
  /// tanto al principio como al final de la misma. Considera espacios el caracter
  /// de espacio y los caracteres: \f \n \r \t \v
  ///---------------------------------------------------------------------------------*/
  function _trim(t) {
    var a;
    if(!_trim.r) _trim.r = /^\s*(\S*(\s*\S+)*)\s*$/;
    a = _trim.r.exec(t);
    return a[1];
  }

  /**---------------------------------------------------------------------------------
  /// svsys::object_pos (_op)                                  svsys::object_pos (_op)
  ///---------------------------------------------------------------------------------
  /// Dado un objeto obtiene las coordenadas de su posición en el array de salida
  /// _sv.rv (generalmente los valores buscados se encuentran en _sv.rv[4] y
  /// _sv.rv[5]).
  /// 
  /// RECIBE:
  /// 
  /// - Una referencia al objeto.
  /// 
  /// SALIDA:
  /// 
  /// - _sv.rv[0] : Coordenada X relativa al objeto offsetParent.
  /// - _sv.rv[1] : Coordenada Y relativa al objeto offsetParent.
  /// - _sv.rv[2] : Coordenada X del objeto offsetParent relativa al cuerpo del
  ///               documento.
  /// - _sv.rv[3] : Coordenada Y del objeto offsetParent relativa al cuerpo del
  ///               documento.
  /// - _sv.rv[4] : Coordenada X relativa al cuerpo del documento y teniendo en
  ///               cuenta todos los posibles scroll.
  /// - _sv.rv[5] : Coordenada Y relativa al cuerpo del documento y teniendo en
  ///               cuenta todos los posibles scroll.
  /// 
  /// COMENTARIOS:
  /// 
  /// No esta establecido en qué condiciones offsetParent es diferente del documento
  /// (es algo que depende de cada navegador), esta función está pensada para obtener
  /// las propiedades offsetLeft y offsetTop referidas al borde del documento. Los
  /// valores devueltos en _sv.rv[0] y _sv.rv[1] son dependientes del navegador, los
  /// otros no deberían serlo.
  ///---------------------------------------------------------------------------------*/
  function _op(o) {
    var p;
    for(p=0;p<6;p++) {
      _sv.rv[p] = 0;
    }
    p=o.offsetLeft;
    if(p!=undefined) {
      _sv.rv[0] = p;
      _sv.rv[1] = o.offsetTop;
      {
        ot = 'offsetTop';
        op = 'offsetParent';

        //alert([o[ot], o[op][ot], o[op][op][ot], o[op][op][op][ot], o[op][op][op][op]]);
      }
      p = o.offsetParent;
      if(p) opx(p,2);                  /// Primero se suman los offsetLeft y offsetTop.
      _sv.rv[4] = _sv.rv[0]+_sv.rv[2];
      _sv.rv[5] = _sv.rv[1]+_sv.rv[3];
      p=o.parentNode;
      
      //# 
      //# BUG OPERA. En rigor, el siguiente if no debería estar comentado. Sirve para
      //# corregir la posición calculada del elemento, teniendo en cuenta la posibilidad
      //# de que se encuentre dentro de una div o una celda con un scroll interno.
      //# 
      //# Afortunadamente esa posibilidad no se da en los proyectos actuales, y es poco
      //# probable que se de en el futuro.
      //# 

      //if(p) opx2(p, 4);                 /// Y después se computan los scrollLeft y
      //                                  /// scrollTop en todos los padres.
    }
  }
  /**---------------------------------------------------------------------------------
  /// Función auxiliar para svsys::obj_pos (_op).
  /// 
  /// Recibe un objeto, y un índice i. Acumula los valores de offsetLeft y offsetTop
  /// del objeto (si los tiene) sobre _sv.rv[i] y _sv.rv[i+1] respectivamente,
  /// comprueba si estos valores se refieren a otro objeto (offsetParent) y si es
  /// así se llama recursivamente para acumular todos los offsets hasta alcanzar
  /// el documento.
  ///---------------------------------------------------------------------------------*/
  function opx(o,i) {
    var l;
    l = o.offsetLeft;
    if(l!=undefined) {
      _sv.rv[i] += l;
      _sv.rv[i+1] += o.offsetTop;
      l = o.offsetParent;
      if(l) opx(l,i);
    }
  }
  /**---------------------------------------------------------------------------------
  /// Función auxiliar para svsys::obj_pos (_op).
  /// 
  /// Recibe un objeto, y un índice i. Acumula los valores de scrollLeft y scrollTop
  /// del objeto (si los tiene) sobre _sv.rv[i] y _sv.rv[i+1] respectivamente,
  /// comprueba si existe un nodo padre que ademas sea diferente de la ventana
  /// y si es así se llama recursivamente para acumular todos los scrolls hasta
  /// alcanzar el documento.
  ///---------------------------------------------------------------------------------*/
  function opx2(o, i) {
    var p,s;
    if(o!=document.body) {
      s=o.scrollLeft;
      if(s!=undefined) {
        _sv.rv[i]   -= s;
        _sv.rv[i+1] -= o.scrollTop;
      }
      p = o.parentNode;
      if(p && p!=window) opx2(p, i);
    }
  }
  /**---------------------------------------------------------------------------------
  /// Dado un objeto obtiene las coordenadas de sus bordes (X1, Y1, X2, Y2) en
  /// el array de salida _sv.rv.
  /// 
  /// RECIBE:
  /// 
  /// - Una referencia al objeto.
  /// 
  /// SALIDA:
  /// 
  /// - _sv.rv[0] : Coordenada X1.
  /// - _sv.rv[1] : Coordenada Y1.
  /// - _sv.rv[2] : Coordenada X2.
  /// - _sv.rv[3] : Coordenada Y2.
  ///-----------------------------------------------------------------------------------*/
  function _or(o) {
    var r;
    _op(o);
    r=_sv.rv;
    r[0]=r[4];
    r[1]=r[5];
    r[2]=r[0]+o.offsetWidth;
    r[3]=r[1]+o.offsetHeight;
  }
  /**---------------------------------------------------------------------------------
  /// Dado un objeto, hace un scroll de modo que dicho objeto quede dentro de los
  /// límites visibles página.
  /// 
  /// RECIBE:
  /// 
  /// - El objeto que debe quedar dentro de los límites visibles.
  /// - Opcionalmente (0 por defecto) el margen adicional alrededor del objeto que
  ///   debe considerarse a la hora de computar sus límites.
  /// 
  ///---------------------------------------------------------------------------------*/
  function _auto_scroll(o,t) {
    var b,r,p;
    b = _sv.body;           /// b contiene una referencia al body.
    r = _sv.rv;             
    p=[b.scrollLeft,b.scrollTop,b.clientWidth,b.clientHeight];
    p[2]+=p[0];
    p[3]+=p[1];
    _or(o);
    if(t) {
      r[0]-=t;r[1]-=t;r[2]+=t;r[3]+=t;
    }
    _collision(r,p);
    if(r[0]) b.scrollLeft+=r[0];
    if(r[1]) b.scrollTop+=r[1];
  }

///--------------------------------------------------------------------------------------
  function _l_entities(t) {
    t = String(t);
    t = t.replace(/&/g, "&amp;");
    t = t.replace(/</g, "&lt;");
    t = t.replace(/>/g, "&gt;");
    t = t.replace(/\n/g, "<br>");
    return t;
  }
///--------------------------------------------------------------------------------------
  function cpy_frm(fnm, sd, dd, act) {
    var frm, i, t, n, v, e;
    frm = sd.forms[fnm];
    dd=dd;
    dd.write("<html><head></head><body onload='sub_frm()'>\r\n");
    dd.write("<form\r\n name='frm' method='POST' action='"+act+"'>");
    for(i=0; i<frm.length; i++) {
      e = frm.elements[i];
      t = e.nodeName;
      n = frm.elements[i].name;
      if(t=="SELECT") {
        v = e.options[e.selectedIndex].value;
      } else {
        v = frm.elements[i].value;
      }

      dd.write("<input\r\n type='HIDDEN' name='"+n+"' value='"+v+"'>");
    }
    dd.write("<input\r\n type='HIDDEN' name='frm_new_win' value='1'>");
    dd.write("</form></body></html>");
    dd.write("<"+"script>document.forms.frm.submit();</"+"script>");
  }
///--------------------------------------------------------------------------------------
  function strs_to_assoc(s1,s2) {
    var i,ii,o;
    ii=Math.min(s1.length, s2.length);;
    o={};
    for(i=0;i<ii;i++) {
      o[s1.charAt(i)]=s2.charAt(i);
    }
    return o;
  }
/**-----------------------------------------------------------------------------------
*** private::tolcuc_x                                                private::tolcuc_x
***-----------------------------------------------------------------------------------
*** Auxiliar para las funciones de transformación de mayusculas a minusculas,
*** minusculas a mayusculas, y quitar tildes.
*** 
*** Devuelve un array de transformación según el parámetro entero que recibe:
*** 
*** 0: Array de transformación de minúsculas a mayúsculas, respetando tildes.
*** 1: Array de transformación de mayúsculas a minúsculas, respetando tildes.
*** 2: Array de transformación de minúsculas a mayúsculas, quitando tildes.
*** 3: Array de transformación de mayúsculas a minúsculas, quitando tildes.
*** 4: Array de transformación de quitar tildes respetando case.
***-----------------------------------------------------------------------------------*/
  function tolcuc_x(n) {
    var f,o;
    if(!tolcuc_x.arr_str) {
      tolcuc_x.arr_str=[];
      f=tolcuc_x.arr_str;
      f[1]='ÁÉÍÓÚÀÈÌÒÙÄËÏÖÜÂÊÎÔÛÃÕÑ'; /// | 1:  Mayusculas con tilde.
      f[2]='áéíóúàèìòùäëïöüâêîôûãõñ'; /// | 2:  Minusculas con tilde.
      f[3]='AEIOUAEIOUAEIOUAEIOUAOÑ'; /// | 3:  Mayusculas sin tilde.
      f[4]='aeiouaeiouaeiouaeiouaoñ'; /// | 4:  Minusculas sin tilde.
      
      f[5] = f[1] + f[2];             /// | 5:  Mayusculas y minusculas con tilde.
      f[6] = f[3] + f[4];             /// | 6:  Mayusculas y minusculas sin tilde.
      f[7] = f[1] + f[3];             /// | 7:  Mayusculas con y sin tildes.
      f[8] = f[2] + f[4];             /// | 8:  Minusculas con y sin tildes.
 
      f[9] = f[5] + f[3];             /// | 9:  Cualquiera con tilde, o mayusculas.
      f[10]= f[5] + f[4];             /// | 10: Cualquiera con tilde, o minusculas.
      
      f[11] = f[3] + f[3] + f[3];     /// | 11: Mayusculas triple.
      f[12] = f[4] + f[4] + f[4];     /// | 11: Minusculas triple.
      
      tolcuc_x.arr_opt = [[8,7],[7,8],[10,11],[9,12],[5,6]];
    } else {
      f=tolcuc_x.arr_str;
    }
    o=tolcuc_x.arr_opt;
    return strs_to_assoc(f[o[n][0]],f[o[n][1]]);
  }
/**-----------------------------------------------------------------------------------
*** private::toat                                                        private::toat
***-----------------------------------------------------------------------------------
*** Aplica un array de transformación a una cadena.
*** 
*** RECIBE:
*** 
*** - La cadena.
*** - El array de transformación.
*** - (Opcional) Una expresion regular que identifica los caracteres que deben.
***   ser transformados. Por defecto son todos los caracteres no habituales ya
***   que esta función está pensada para convertir caracteres 'raros'.
*** 
*** SALIDA:
*** 
*** COMENTARIOS
***-----------------------------------------------------------------------------------*/
  function toat(s,a,er) {
    if(!er) {
      er=/[^a-zA-Z0-9_ \.\,-]/g;
    }
    toat_x.arr=a;
    return s.replace(er, toat_x);
  }
/**-----------------------------------------------------------------------------------
*** Callback para el replace de toat.
***-----------------------------------------------------------------------------------*/
  function toat_x(a) {
    if(a in toat_x.arr) {   /// Si el caracter está en el array de transformación.
      return toat_x.arr[a]; /// | Devolver la transformación.
    }                       /// | 
    return a;               /// Devolver el caracter sin transformar.
  }
/**-----------------------------------------------------------------------------------
*** svsys::tolc                                                            svsys::tolc
***-----------------------------------------------------------------------------------
*** TO Lower Case (convierte a minúsculas la cadena pasada).
*** 
*** - La cadena que hay que convertir a minúsculas.
*** - Un parámetro opcional que si es verdadero, además, quitará las tildes de la
***   cadena.
***-----------------------------------------------------------------------------------*/
  function _tolc(s,f) {
    var r;
    if(!_tolc.ar1) {
      _tolc.ar1=tolcuc_x(1);
      _tolc.ar2=tolcuc_x(3);
    }
    r = (f) ? toat(s,_tolc.ar2) : toat(s,_tolc.ar1);
    return r.toLowerCase();
  }
/**-----------------------------------------------------------------------------------
*** svsys::touc                                                            svsys::touc
***-----------------------------------------------------------------------------------
*** TO Upper Case (convierte a mayúsculas la cadena pasada).
*** 
*** - La cadena que hay que convertir a mayúsculas.
*** - Un parámetro opcional que si es verdadero, además, quitará las tildes de la
***   cadena.
***-----------------------------------------------------------------------------------*/
  function _touc(s,f) { 
    var r;
    if(!_touc.ar1) {
      _touc.ar1=tolcuc_x(0);
      _touc.ar2=tolcuc_x(2);
    }
    r = (f) ? toat(s,_touc.ar2) : toat(s,_touc.ar1);
    return r.toUpperCase();
  }
///--------------------------------------------------------------------------------------
  function init_sv_title(o) {
    var c,d,p,w;
    c = o.getAttribute("sv_conf");
    if(_sv.is_emp(c)) { c=''; }
    d = new Object();
    _sv.parse_atts(c,d);
    if(d.value) {
      p = window;
      do {
        w=p;
        p=w.parent;
      } while(p!=null && p!=w);
      w.document.title=d.value;
    }
  }

}
/**-----------------------------------------------------------------------------------
*** Constructor _svEventObject                              Constructor _svEventObject
***-----------------------------------------------------------------------------------
*** 
*** RECIBE
*** 
*** - Un 
*** 
*** 
*** 
***-----------------------------------------------------------------------------------*/
function _svEventObject(e, c) {
  var t, dt, x, db, cc, kc;
  t = this;
  t._so = e;
  x = _sv.mouse;
  t.type = '';
  t.group = c;
  t.target = null;
  t.self = null;
  t.user_window = 
  t.target_window = window;
  t.client=x.client;
  t.screen=x.screen;
  t.page  =x.page;
  t.button=0;
  t.char_code=-1;
  t.key_code=-1;
  t.altKey=false;
  t.shiftKey=false;
  t.ctrlKey=false;
  t._cf = 0; /// _cf : Cancel Flag
  t._kf = 0; /// _kf : Kill Flag
  if(e!=null) {
    //if(e.type=='keypress')
    t.type = e.type;
    t.group = c;
    if(e.target) {
      dt = e.target;                
    } else {
      dt = e.srcElement;
    }
    if(dt==_sv.root) {
      dt=_sv.body;
    }
    t.target = dt;
    t.self = null;
    if(c==1) {
      t.client[0]=e.clientX;
      t.client[1]=e.clientY;
      t.screen[0]=e.screenX;
      t.screen[1]=e.screenY;
      if(e.pageX!=undefined) {
        t.page[0]=e.pageX;
        t.page[1]=e.pageY;
      } else {
        db = document.body;
        t.page[0]=e.clientX+db.scrollLeft;
        t.page[1]=e.clientY+db.scrollTop;
        if(db.clientLeft!=undefined) {
          t.page[0]-=db.clientLeft;
          t.page[1]-=db.clientTop;
        }
      }
      t.button = e.button;
    }
    if(c==2) {
      cc = (e.which!=undefined) ? e.which : e.keyCode ;
      kc = e.keyCode;
      cc = parseInt(cc);
      kc = parseInt(kc);
      if(cc==9) { cc=0; kc=9; }
      t.char_code = cc;
      t.key_code = kc;
    }
    if(c==1 || c==2) {
      t.altKey  =e.altKey;
      t.shiftKey=e.shiftKey;
      t.ctrlKey =e.ctrlKey;
    }
  }
  dt = new Date();
  t.time = dt.getTime();
  // t.time = Date.getTime();
  t.args = [];

  t._fwd = 0;
  t.system  = system;
  t.stop    = stop;
  t.forward = forward;
  t.kill = kill;
  if(e==null) {
    t.prevent_default = ce_ue;
  } else if(t._so.preventDefault) {
    t.prevent_default = ce_cb;
  } else {
    t.prevent_default = ce_ie;
  }
  
///--------------------------------------------------------------------------------------
  function kill(e){this._kf=1;}
///--------------------------------------------------------------------------------------
  function system(e){ this.forward(_sv); }
///--------------------------------------------------------------------------------------
  function stop(e){ this.forward(null); }
///--------------------------------------------------------------------------------------
  function forward() {
    var s, a, o;
    s = this.self;
    a = forward.arguments;
    if(a.length) {
      o = a[0];
    } else {
      o = (s.parentNode) ? s.parentNode : null ;
    }
    if(o!=null) {
      _sv._go_r(o, this);
      this.self = s;
    }
    this._fwd = 1;
  }
///--------------------------------------------------------------------------------------
  function _l_ce_cm(e) {  /// CancelEvent_Common
    e._cf = 1;
    if(e.type=='m_down') {
      _sv.mouse.cancels[e.button]=1;
    }
  }
///--------------------------------------------------------------------------------------
  function ce_cb() {      /// CancelEvent_CB
    if(this._so!=null) {
      _l_ce_cm(this);
      this._so.preventDefault();
    }
  }
///--------------------------------------------------------------------------------------
  function ce_ie() {      /// CancelEvent_IE
    if(this._so!=null) {
      _l_ce_cm(this);
      this._so.returnValue=false;

    }
  }
///--------------------------------------------------------------------------------------
  function ce_ue(){ }
}
///--------------------------------------------------------------------------------------
