var GVhelplinks = new Array();

function trim(str)
  { return str.replace(/^\s+|\s+$/g,''); }


function docElem(name)
  { return document.getElementById(name); }


function in_arraylist(val, arr)
  {
    for (var i = arr.length - 1; i >= 0; i--)
      { if (arr[i] == val) { return true; } }
    return false;
  }

function numDP(num)
  {
    // returns the number of decimal places in num, or -1 if not a valid number
    var tmp = trim(num);
    if(!tmp.match(/^-?\d+(\.\d+)?$/))
      { return -1; }
    var parts = tmp.split('.');
    if (parts.length > 2)
      { return -1; }
    if (parts.length == 1)
      { return 0; }
    return parts[1].length;
  }

function insert_commas(int)
  {
    if (typeof(int) == 'string')
      { int = parseInt10(int); }
    var sign = (int < 0 ? '-' : '');
    int = Math.abs(int);
    var s = int.toString();
    var bits = new Array();
    while (s.length > 3)
      { bits.unshift(s.substr(s.length-3,3)); s = s.substr(0,s.length-3); }
    if (s.length > 0)
      { bits.unshift(s); }
    return sign + bits.join(',');
  }


function parseInt10(numstr)
  {
    // always parses as base 10, even if the string contains leading zeros
    if (typeof(numstr) == 'number')
      { return numstr; }
    if (!numstr.match(/^\-?\d+$/))
      { return null; }
    numstr = numstr.replace(/^0+/,'');
    return (numstr.length ? parseInt(numstr) : 0);
  }

function vatpence(pence,vatrate)
  { return Math.floor((pence*vatrate)+0.0001); }


function pence2pounds(num, omit_commas)
  {
    if (typeof(num) == 'string')
      { num = parseInt10(num); }
    var sign = '';
    if (num < 0)
      { sign = '-'; num *= -1; }
    pence = num % 100;
    pence = (pence < 10 ? '0'+pence : ''+pence);
    var pounds = (num >= 0 ? Math.floor(num/100) : Math.ceil(num/100));
    if (!omit_commas)
      { pounds = insert_commas(pounds); }
    return sign+pounds+'.'+pence;
  }

function pounds2pence(num)
  {
    var decimals = numDP(num);
    if (decimals == 0)
      { return num * 100; }
    else if (decimals == 2)
      {
        var parts = num.split('.');
        return (parseInt10(parts[0]) * 100) + parseInt10(parts[1]);
      }
    return null;
  }


function price2dp_error(price, minval)
  {
    if (!price.length)
      { return 'Please enter a price.'; }
    var dp = numDP(price);
    if (dp < 0)
      { return "Bad price \""+price+"\": not a number"; }
    if (dp != 2)
      { return "Bad price \""+price+"\": please enter price in pounds and pence, eg 0.99 or 1.49"; }
    if (price < minval)
      { return "Bad price \""+price+"\": minimum value is "+minval; }
    return false;
  }


function set_element_displaystyle(mode, elems)
  {
    for (var i = 0; i < elems.length; i++)
      {
        var arg = elems[i];
        var idlist = (typeof(arg) == 'object' ? arg : new Array(arg));
        for (var j in idlist)
          { docElem(idlist[j]).style.display = mode; }
      }
  }


function table_row_show()
  {
    var mode = (navigator.appName.indexOf('Microsoft') != -1 ? 'block' : 'table-row');
    set_element_displaystyle(mode, arguments);
//     for (var i = 0; i < arguments.length; i++)
//       {
//         var arg = arguments[i];
//         var idlist = (typeof(arg) == 'object' ? arg : new Array(arg));
//         for (var j in idlist)
//           { docElem(idlist[j]).style.display = mode; }
//         //docElem(id).style.display = (navigator.appName.indexOf('Microsoft') != -1 ? 'block' : 'table-row');
//       }
  }

function table_row_hide()
  {
    set_element_displaystyle('none', arguments);
//     for (var i = 0; i < arguments.length; i++)
//       { var id = arguments[i]; docElem(id).style.display = 'none'; }
  }


function htmlenc(str)
  {
    if (typeof(str) !== 'string')
      { return str; }
    return str.replace(/&/g,'&amp;').replace(/\"/g,'&quot;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
  }


function fix_alert_indents(msg)
  {
    // convert any spaces at the start of a line into non-breaking spaces:
    var lines = msg.split(/\n/);
    for (var i in lines)
      {
        var prefix = '';
        while (lines[i].match(/^\s/))
          { prefix += String.fromCharCode(160); lines[i] = lines[i].substr(1); }
        lines[i] = prefix + lines[i];
      }

   return lines.join('\n');
  }

function helplink(msg)
  {
    GVhelplinks.push(msg);
    var i = GVhelplinks.length - 1;
    return "<img title=\"explain this\" border=\"0\" class=\"clickable\" align=\"absmiddle\" src=\"/images/icon_help.gif\"" +
           " onClick=\"helplink_alert("+i+");\");/>";
  }

function helplink_alert(i)
  { alert(fix_alert_indents(GVhelplinks[i])); }


// function hexbyte(num,digits)
//   {
//     var str=num.toString(16);
//     while (str.length<digits) {str='0'+str;}
//     return str;
//   }
// 
// function colbias(col,biasto,pc)
//   {
//     var i; var c; var res='';
//     for (i=0; i<=4; i+=2)
//       { c=parseInt10(col.substring(i,i+2),16); res+=hexbyte(Math.floor(c+((parseInt10(biasto.substring(i,i+2),16)-c)*(pc/100))),2); }
//     return res;
//   }


// makes a copy of a structure, not another pointer to the same:
function struct_copy(struct)
  { return kjax_unserialize(kjax_serialize(struct)); }


function is_leapyear(year)
  { return (!(year%400) || (year%100 && !(year%4)) ? 1: 0); }


function days_in(m,yr)
  {
    var arr = new Array(31,28+is_leapyear(yr),31,30,31,30,31,31,30,31,30,31);
    return arr[m-1];
  }


function monthnum(monthstr)
  {
    var tmp;
    if (monthstr.match(/^\d+$/))
      {
        tmp = parseInt10(monthstr);
        return (tmp >= 1 && tmp <= 12 ? tmp : -1);
      }
    tmp = 'jan feb mar apr may jun jul aug sep oct nov dec '.indexOf(monthstr.toLowerCase().substr(0,3)+' ');
    return (tmp >= 0 ? (tmp/4)+1 : tmp);
  }


function monthstr(monthnum)
  { return 'JanFebMarAprMayJunJulAugSepOctNovDec'.substr(3*(parseInt10(monthnum)-1),3); }


function nicedate(isodate)
  {
    var bits = isodate.split(/-/);
    return (bits.length>1?bits[2]+' ':'')+monthstr(bits[1])+' '+bits[0];
  }


function nicedate_to_isodate(nicedate)
  {
    var bits = trim(nicedate).split(/\W+/);
    var d=parseInt10(bits[0]); var m=monthnum(bits[1]); var yr=parseInt10(bits[2]);
    if (yr < 100) { yr += (yr < 70 ? 2000: 1900); }
    if (yr >= 1900 && yr <= 9999 && m > 0 && d > 0 && d <= days_in(m,yr))
      { return yr.toString()+'-'+(m<10?'0':'')+m.toString()+'-'+(d<10?'0':'')+d.toString(); }
    return false;
  }
