
// Format a number into decimal format
function fmtDecml(nmbr,p)
{   var N,pm,fmt

    fmt=(fmtDecml.arguments.length>1)
    N=Number(nmbr)
    pm=Sign(N)
    N=Abs(N)
    if (N<1e-36) {return '0'}
    if (fmt)     {return fixed(pm,N,p)}
    if (N>1e9)   {return expon(pm,N)}
    if (N>1e6)   {return fixed(pm,N,0)}
    if (N>1e3)   {return fixed(pm,N,3)}
    if (N>=1e-3) {return fixed(pm,N,6)}
    return expon(pm,N)

    function fixed(pm,N,p)
    {   var P,S
        P=Power(10,p)
        S=String(pm*Round(N*P)/P)
        return S
    }

    function expon(pm,n)
    {   var N,M,S
        N=n
        M=0
        while (N>1) {N=N/1000; M=M+3}
        while (N<1) {N=N*1000; M=M-3}
        S=fixed(pm,N,6)+'e'+String(M)
        return S
    }
}

// Format an angle or a time into sexagesimal format.
function fmtSxgml(angle,xms)
{   var a,pm,d,m,s,D,M,S,b

    a=Number(angle)
    pm=(a<0)?'-':''
    a=Abs(a)
    d=xms.substring(0,1)
    m=xms.substring(1,2)
    s=xms.substring(2,3)
    if (d=='^') {d=_D_}
    if (m=='~') {m=_q_}
    if (s=='~') {s=_Q_}
    b=(d==':')?'':' '
    d=d+b
    m=m+b
    b=Round(3600*a)
    S=Floor(b%60)
    b=b/60
    M=Floor(b%60)
    D=Floor(b/60)
    D=String(D)
    M=String(M)
    if (M.length==1) {M='0'+M}
    S=String(S)
    if (S.length==1) {S='0'+S}
    return pm+D+d+M+m+S+s
}

// Format an angle sensitive to user's desires (flag). Latitudes do not use hour angles
function fmtAngle(flag,lat,Angle)
{   var sxg,hra,rad,pct,dml,arc,L

    sxg=flag[0]; hra=flag[1]; rad=flag[2]
    pct=flag[3]; dml=flag[4]; arc=flag[5]
    L=''
    if ((arc) && (Abs(Angle)>=(1/6))) {arc=false}
    if ((hra) && (lat))               {hra=false; sxg=true}
    if (!(sxg || hra || rad || pct))  {dml=true}
    if (sxg) {L=L+'\n   '+fmtSxgml(Angle,'^~~')}
    if (hra) {L=L+'\n   '+fmtSxgml((Angle/15),'hms')}
    if (rad) {L=L+'\n   '+fmtDecml(Angle*Pi/180)+'R'}
    if (pct) {L=L+'\n   '+fmtDecml((Angle/3.6),2)+'%'}
    if (dml) {L=L+'\n   '+fmtDecml(Angle)}
    if (arc) {L=  '\n   '+fmtDecml(Angle*3600)+' arcseconds'}
    return L
}

// Read an angle in a wide variety of formats. Formats are determined by the first
// non-numeric and non blank character.
function rdAngle(STR)
{   var sxg,hra,rad,pct,dml,arc,ang,str,pm,dd,mm,ss,fmt,nsew,NSEW,n,s,e,w,i,j

    sxg=0; hra=1; rad=2; pct=3; dml=4; arc=5; n=0; s=1; e=2; w=3
    str=strip(String(STR))
    str=str.toLowerCase()
    nsew=lastword(str)
    NSEW='nsew'
    i=NSEW.indexOf(nsew.substring(0,1))
    if (i>none)
    {
        j=str.indexOf(nsew)
        str=str.substring(0,j)
    }
    nsew=i
    fmt=none
    if ((fmt==none) && (str.indexOf('r')>0)) {fmt=rad}
    if ((fmt==none) && (str.indexOf(_D_)>0)) {fmt=sxg}
    if ((fmt==none) && (str.indexOf('^')>0)) {fmt=sxg}
    if ((fmt==none) && (str.indexOf('%')>0)) {fmt=pct}
    if ((fmt==none) && (str.indexOf('h')>0)) {fmt=hra}
    if ((fmt==none) && (str.indexOf(':')>0)) {fmt=hra}
    if ((fmt==none)                        ) {fmt=dml}
    str=RetainOnly(str,'+-.0123456789e ')
    pm=nthword(str,1)
    pm=(pm.substring(0,1)=='-')?-1:1
    dd=Number(nthword(str,1))
    mm=Number(nthword(str,2))
    ss=Number(nthword(str,3))
    ang=Abs(dd)+(Abs(mm)/60)+(Abs(ss)/3600)
    ang=pm*ang
    if (nsew==e)  {ang=360-ang}
    if (nsew==s)  {ang=0-ang}
    if (fmt==hra) {ang=ang*15}
    if (fmt==pct) {ang=ang*3.6}
    if (fmt==rad) {ang=ang*(180/Pi)}
    if (isNaN(ang)) {alert('Angle is incorrect'); ang=0}
    return ang
}

// Read a number, and issue an error message if it is invalid
function rdDecml(D)
{   var d
    d=Number(nthword(D,1))
    if (isNaN(d)) {alert(' '+D+' '+'Decimal number is invalid'); d=0}
    return d
}

// Read units that a user may append to a numeric field
function rdUnits(D,UU)
{   var U
    U=nthword(D,2)
    if ((U=='') && (rdUnits.arguments.length>1)) {U=UU}
    return ' '+U
}

// Convert temperatures to a specified unit
function cvtTemps(T,U)
{   var t,V,v,u
    t=rdDecml(T)
    V=rdUnits(T,'f')
    v=cvt_1(V)
    u=cvt_1(U)
    if (u=='k')
    {
        if (v=='f') {t=273.15+((t-32)/1.8)}
        if (v=='c') {t=273.15+t}
    }
    if (u=='c')
    {
        if (v=='f') {t=((t-32)/1.8)}
        if (v=='k') {t=t-273.15}
    }
    if (u=='f')
    {
        if (v=='c') {t=((t*1.8)+32)}
        if (v=='k') {t=(((t-273.15)*1.8)+32)}
    }
    return t

    // Internal subroutine of cvtTemps
    function cvt_1(X)
    {   var x
        x=strip(X)
        x=x.substring(0,1)
        x=x.toLowerCase()
        return x
    }
}

// Convert distances into a specified unit
function cvtDists(D,U)
{   var d,v,u,k,dv,du,name,dist

    d=rdDecml(D)
    v=rdUnits(D)
    v=cvt_2(v)
    u=cvt_2(U)

    if (v==u) {return d}

    name=new Array('fm','pm','a','nm','um','mm','cm','in','ft','yd','m','rd','fl','km','mi','Mm','ls','gm','lm','au','tm','Pm','lh','ld','ly','pc')
    dist=new Array(_fm_,_pm_,_a_,_nm_,_um_,_mm_,_cm_,_in_,_ft_,_yd_,_m_,_rd_,_fl_,_km_,_mi_,_Mm_,_ls_,_gm_,_lm_,_au_,_tm_,_Pm_,_lh_,_ld_,_ly_,_pc_)

    dv=0
    du=0
    for (k=0;(k<name.length);++k)
    {
        if (v==name[k]) {dv=dist[k]}
        if (u==name[k]) {du=dist[k]}
    }
    if ((dv>0) && (du>0)) {return d*(dv/du)}

    alert('Unknown different distance units')
    return d

    // Internal subroutine of cvtDists
    function cvt_2(X)
    {       var x
        x=strip(X)
        if (x.length>2) {x=x.substring(0,2)}
        if ((x=='Pm') || (x=='PM')) {return 'Pm'}
        if ((x=='Mm') || (x=='MM')) {return 'Mm'}
        x=x.toLowerCase()
        return x
    }

}

