// '/inteq/library/dates.js'
//includeOnce -1899925548

// '/inteq/library/enumerators.js'
//includeOnce -1898145969

/**
 * @fileoverview Biblioteca para tratamento de strings.
 * @author Reginaldo
 * @author Paulo Moreno
 * @version 0.1
 */
 
// Tratamento de erro
/**
 * TODO
 * @private
 */
function throwError( message ) {
    message.toString( 'a') // bug fo IE 6
    throw new Error( message )
}

// Retorna somente os caracteres numéricos de uma string
function onlyNumbers( str, withDecimalSeparator ) {
    if ( withDecimalSeparator == undefined ){
        withDecimalSeparator = false
    }

    str = str + ''

    var result = ''
    var ch     = ''
    for ( var i = 0; i < str.length; i += 1 ) {
        ch = str.charAt(i)
        if ( ( ch >= '0' && ch <= '9' ) || ( withDecimalSeparator && ( ch == '.' || ch == ',' ) && i > 0 && i < str.length - 1 ) ) {
            if ( ch >= '0' && ch <= '9' ) {
              result += ch
            } else {
                if ( str.charAt(i-1) >= '0' && str.charAt(i-1) <= '9' && str.charAt(i+1) >= '0' && str.charAt(i+1) <= '9') {
                    result += ch
                }
            }
        }
    }
    return result
}

var onlyArithmeticExpressionTranslateFlagArray = new Array()
for ( var i = 0; i <= 255; i++ ) {
    onlyArithmeticExpressionTranslateFlagArray[i] = false
}
for ( var i = '0'.charCodeAt(0); i <= '9'.charCodeAt(0); i++ ) {
    onlyArithmeticExpressionTranslateFlagArray[i] = true
}
onlyArithmeticExpressionTranslateFlagArray[ '.'.charCodeAt(0) ] = true
onlyArithmeticExpressionTranslateFlagArray[ ','.charCodeAt(0) ] = true
onlyArithmeticExpressionTranslateFlagArray[ '('.charCodeAt(0) ] = true
onlyArithmeticExpressionTranslateFlagArray[ ')'.charCodeAt(0) ] = true
onlyArithmeticExpressionTranslateFlagArray[ '+'.charCodeAt(0) ] = true
onlyArithmeticExpressionTranslateFlagArray[ '-'.charCodeAt(0) ] = true
onlyArithmeticExpressionTranslateFlagArray[ '*'.charCodeAt(0) ] = true
onlyArithmeticExpressionTranslateFlagArray[ '/'.charCodeAt(0) ] = true

function onlyArithmeticExpression( str ) {
    if ( typeof str == 'string' ) {
        str = str.replace( ',', '.' )
        var ar = new Array()
        for ( var i = 0; i < str.length; i++ ) {
            var ch = str.substr( i, 1 )
            if ( onlyArithmeticExpressionTranslateFlagArray[ ch.charCodeAt( 0 ) ] ) {
                ar.push ( ch )
            }
        }
        return ar.join( '' )
    } else {
        throw new DetailedError( 'Parâmetro "str" inválido.',
                                         'Informe um string válida.',
                                         'Objeto passado: ' +  str,
                                         '/inteq/library/strings.js onlyArithmeticExpression()' )
    }
}

// Retorna apenas letras
function onlyChars( str, withoutDecimalSeparator ) {
    if ( typeof str != 'string' )
        str = str + ''

    if ( withoutDecimalSeparator == undefined ){
        withoutDecimalSeparator = false
    }
    var result = ''
    if ( str == undefined ) {
        str = ''
    }
    var ch   = ''
    var v      = 0
    for ( var i = 0; i < str.length; i++ ) {
        ch = str.charAt( i )
        if ( ( ch >= '0' && ch <= '9' ) || ( withoutDecimalSeparator && ( ch == '.' || ch == ',' ) && i > 0 && i < str.length - 1 ) ) {
            if ( ch >= '0' && ch <= '9') {
                result += str.substring(v, i)
                v = i + 1
            } else {
                if ( str.charAt(i-1) >= '0' && str.charAt(i-1) <= '9' && str.charAt(i+1) >= '0' && str.charAt(i+1) <= '9') {
                    result += str.substring( v, i )
                    v = i + 1
                }
            }
        }
    }
    result += str.substring( v, i )
    return result
}

function replaceString( string, oldPattern, newPattern ){
    if ( navigator == undefined ){
        // Servidor
        return string.replace( oldPattern, newPattern )
    } else {
        // Cliente
        var result = ''
        var pos    = 0
        while ( string != '' ){
            pos = string.indexOf( oldPattern )
            if ( pos >= 0 ){
                result += string.substring( 0, pos ) + newPattern
                string  = string.substr( pos + oldPattern.length )
            } else {
                result += string
                string  = ''
            }
        }
        return result
    }
}

// Converte a string em um número. Gera um erro caso não seja possível
function tryStringToNumber( string ){
    var deprecatedMode = !navigator && (server.version.indexOf('3.3.0') == 0)
    if ( deprecatedMode){
        return Number( string )
    } else {
        var number = Number( string )
        if ( isNaN( number ) ){
            throwError( '"' + string + '" não é um número válido.' )
        }
        return number
    }
}

function stringToNumber( string ){
    if ( string == '' || string == null ) {
        var number = 0
    } else {
        try {
            try {
        		var number = tryStringToNumber( string )
            } catch (e){
                var numberStr = ''
                // Descobre qual o primeiro separador ( ',' ou '.' )
                var virgulaPos = string.indexOf( ',' )
                var pontoPos   = string.indexOf( '.' )
                if ( virgulaPos > pontoPos ){
                    var separadorDeMilhar = '.'
                    var separadorDecimal  = ','
                } else {
                    var separadorDeMilhar = ','
                    var separadorDecimal  = '.'
                }
                // Elimina o separador de milhar ( Javascript não suporta )
                numberStr = replaceString( string, separadorDeMilhar, '' )
                // Tenta converter
                try {
                    number = tryStringToNumber( numberStr )
                } catch (e) {
                    // Substitui o separador decimal
                    numberStr = replaceString( numberStr, separadorDecimal, separadorDeMilhar )
                    // Tenta converter
                    number = tryStringToNumber( numberStr )
                }
            }
        } catch (e) {
            throwError( 'O valor informado "' + string + '" deve ser um número.' )
        }
    }
    return number
}

/**
 * Converte a string em um número inteiro.
 * Verifica se o valor passado é um inteiro de 32 bits, limitação do dataset.
 * Esse método será utilizado no validador de campos integer da interface.
 */
function stringToInt32( string ){
    var MAX_INT = Math.pow(2,31) - 1
    
    var number = stringToNumber( string )
    var numberInt = Math.floor(number)

    if ( numberInt <= MAX_INT && number == numberInt ) {
        return number
    } else if ( numberInt > MAX_INT ) {
        throwError( 'Valor informado é inválido, somente são aceitos inteiros entre ' + ( -1 * (MAX_INT + 1) ) + ' e ' + MAX_INT + '.')
    } else {
        // Tratamento paleativo para tratar inteiros JS que
        // excedem o inteiro do Delphi (31 bits)
        // O requisito 2471877 trata do assunto
        if ( (number+"").indexOf(".") == -1 ){
            return number
        } else {
            throwError( 'O valor informado "' + string + '" não é um número inteiro.' )
        }
        return false // remove warning
    }
}

// Converte a string em um número inteiro. Gera um erro caso não seja possível.
function stringToInteger( string ){
    var number = stringToNumber( string )
    var numberInt = Math.floor(number)

    if ( number == numberInt ) {
        return number
    } else {
        // Tratamento paleativo para tratar inteiros JS que
        // excedem o inteiro do Delphi (31 bits)
        // O requisito 2471877 trata do assunto
        if ( (number+"").indexOf(".") == -1 ){
            return number
        } else {
            throwError( 'O valor informado "' + string + '" não é um número inteiro.' )
        }
        return false // remove warning
    }
}

/**
 * Converte uma string que representa um valor númerico em notacão científica para a forma decimal.
 * Exemplo:
 *   scientificNotationToDecimal( "-7.881E2" ) = -788.1
 * @param {Number} number Uma string que representa um valor númerico em notacão científica.
 * @return {String} Número correspondente ao parametro number no formato decimal.
 */
function scientificNotationToDecimal( number ) {
    var dotPosition = number.indexOf( "." )
    var expPosition = number.indexOf( "E" )
    expPosition = (expPosition!=-1)?expPosition:number.indexOf("e")
    var decimalSize = expPosition - dotPosition - 1
    var expValue = number.substring(expPosition+1,number.length)*1

    var result = number.substring(0,dotPosition) + number.substring(dotPosition+1,expPosition) //Elimina o "."(Ponto) e o "E"(Exponêncial)

    var signal = ""
    if( result.charAt(0) == "-" ) {
        signal = "-"
        result = result.substring(1,result.length)
    }

    //Se a parte decimal for maior que o valor o expoente, então o resultado será um ponto flutuante
    //caso contrário, será um inteiro.
    if( decimalSize > expValue ) {
        //Calcula a nova posição do separador decimal
        var newDotPosition = result.length - decimalSize + expValue

        if( newDotPosition <= 0 ) {
            for( ; newDotPosition <=0; newDotPosition++ ) {
              result = "0" + result
            }
        }

        if( newDotPosition < result.length ) {
            result = result.substring(0,newDotPosition) + "." + result.substring(newDotPosition,result.length)
        }

        //Elimina os zeros a esquerda
        for( var i = result.length-1; i > newDotPosition && result.charAt(i) == "0"; i--) {
            result = result.substring(0,result.length-1)
        }
    }
    else { //Inteiro(sem casas decimais)
        for( var i = decimalSize; i < expValue; i++ ) {
          result += "0"
        }
    }

    return signal + result
}


// Formata um número com um determinado número de casas decimais ( arredondando )
function formatNumber( number, nMaxDecimals, nMinDecimals ){
    /* Elissandro - Requisito 2723186
        Estranhamento para números muito pequenos a expressão, number == null,
        está sendo avaliada como true não podemos mudar esse comportamento devido ao impacto,
        porém alterei a expressão conforme abaixo: */
    if ( number === null ) {
        number = 0
    }
    if ( nMinDecimals == undefined ){
        nMinDecimals = nMaxDecimals
    } else {
        if ( nMinDecimals < 0 ){
            nMinDecimals = 0
        } else {
            if ( nMinDecimals > nMaxDecimals ){
                nMinDecimals = nMaxDecimals
            }
        }
    }
    if ( number < 0 ) {
        var signal = '-'
        number = Math.abs( number )
    } else {
        var signal = ''
    }

    var dec = '' + Math.round( number * Math.pow( 10, nMaxDecimals ) )
    if( dec.indexOf( "E" ) != -1 ) {
      dec = scientificNotationToDecimal( dec )
    }
    if ( dec == '0' ) {
        if ( nMinDecimals == 0 ){
            return '0'
        } else {
            return '0.0000000000000000000'.substr( 0, nMinDecimals + 2 )
        }
    } else {
        if ( dec.length <= ( nMaxDecimals + 1 ) ){
        	dec = '00000000000000000000'.substr( 0, ( nMaxDecimals + 1 ) - dec.length ) + dec
        }
        if ( nMaxDecimals == nMinDecimals ){
            if ( nMaxDecimals ) {
                return signal + dec.substr( 0, dec.length - nMaxDecimals ) + '.' + dec.substr( dec.length - nMaxDecimals, nMaxDecimals)
            } else {
                return signal + dec.substr( 0, dec.length - nMaxDecimals )
            }
        } else {
            nDecimals = nMaxDecimals
            while ( ( nDecimals > nMinDecimals ) && ( dec.charAt( dec.length - ( nMaxDecimals - nDecimals ) - 1 ) == '0' ) ){
                nDecimals--
            }
            if ( nDecimals == 0 ){
                return signal + dec.substr( 0, dec.length - nMaxDecimals )
            } else {
                return signal + dec.substr( 0, dec.length - nMaxDecimals ) + '.' + dec.substr( dec.length - nDecimals, nDecimals )
            }
        }
    }
}

/**
 * Prepara a formatacao de acordo com as propriedades minDecimalPrecission e maxDecimalPrecision
 * @param {Number} value Valor a ser formatado
 * @param {Integer} decimalPrecision Precisao decimal padrao
 * @param {Integer} minDecimalPrecision Mínimo de precisao decimal a formatar
 * @param {Integer} maxDecimalPrecision Máximo de presisão decimal a formatar
 * @return {String} Número formatado
 */
function formatNumberPrecision( value, decimalPrecision, minDecimalPrecision, maxDecimalPrecision ){
    if( decimalPrecision == null ) decimalPrecision = 0
    if( minDecimalPrecision == null ) minDecimalPrecision = decimalPrecision
    if( maxDecimalPrecision == null ) maxDecimalPrecision = decimalPrecision
    
    if ( value && ( minDecimalPrecision !== null || maxDecimalPrecision !== null ) ) {
        var strValue = value + ""
        var decimalLen =  ( strValue ).length - ( strValue ).indexOf(".") - 1
        var precision = minDecimalPrecision !== null ? minDecimalPrecision : 2
        if ( decimalLen ) {
            if ( decimalLen >= precision ) {
                precision = decimalLen
            }
            var maxPrecision = maxDecimalPrecision !== null ? maxDecimalPrecision : 8
            if ( decimalLen >= maxPrecision ) {
                precision = maxPrecision
            }
        }
        return formatNumber( value, precision )
    } else {
        return formatNumber( value, decimalPrecision )
    }
}


// Converte uma data em uma string no formato dd/mm/aaaa
function dateToString( date, dateFormat ){
    if ( date == null ) {
        return ''
    }

    // Valor default será o formato dd/mm/yyyy
    if ( !dateFormat )
        dateFormat = DateFormat.DDMMYYYY
    else
        if ( DateFormat.values.indexOf( dateFormat) < 0 )
            throw new DetailedError( 'Parâmetro dateFormat inválido!',
                                             'Informe um valor válido. Possíveis valores: ' + DateFormat.properties,
                                             'Valor informado: ' +  dateFormat,
                                             '/inteq/library/strings.js dateToString()' )

    // Dia
    var result = ''
    if ( dateFormat === DateFormat.DDMMYYYY || dateFormat === DateFormat.DDMM ) {
        dateStr = '00' + date.getDate()
        dateStr = dateStr.substr( dateStr.length - 2 )
        result += dateStr + '/'
    }

    // Mês
    monthStr = '00' + ( date.getMonth() + 1 )
    monthStr = monthStr.substr( monthStr.length - 2 )
    result += monthStr

    // Ano
    if ( dateFormat === DateFormat.DDMMYYYY ||
          dateFormat === DateFormat.MMYYYY ) {
        result += '/' + date.getFullYear()
    }

    return result
}

function stringToDate( string, dateFormat ) {
    if ( string == null ) {
        string = ''
    }

    // Valor default será o formato dd/mm/yyyy
    if ( !dateFormat )
        dateFormat = DateFormat.DDMMYYYY
    else
        if ( DateFormat.values.indexOf( dateFormat) < 0 )
            throw new DetailedError( 'Parâmetro dateFormat inválido!',
                                             'Informe um valor válido. Possíveis valores: ' + DateFormat.properties,
                                             'Valor informado: ' +  dateFormat,
                                             '/inteq/library/strings.js stringToDate()' )

    var monthYearFormat = dateFormat === DateFormat.MMYYYY

    try {
        // Checa strings especiais
        if ( string.length > 0 ) {
            var data = new Date()
            data.setHours( 0, 0, 0, 0)
            string = string.toLowerCase()
            if ( string.length == 1 ) {
                if ( string == 'h' || string == '0' ) { // Hoje
                    return data
                }
                if ( string == 'o' ) { // Ontem
                    if ( monthYearFormat ) {
                        return data//Date.incMonth( data, -1)
                    } else {
                        return incDate( data, -1)
                    }
                }
                if ( string == 'a' ) { // Amanhã
                    if ( monthYearFormat ) {
                        return data//Date.incMonth( data, 1)
                    } else {
                        return incDate( data, 1)
                    }
                }
            } else {
                if (string == 'fm') {
                    if ( monthYearFormat ) {
                        return data//Date.incMonth( data, 1)
                    } else {
                        data = incMonth(data, 1);
                        data.setDate(1);
                        return incDate(data, -1);
                    }
                } else {
                    if ( string.charAt(string.length - 1) == 'm' ){
                        // Checa se a data foi dada relativa a hoje em mês fechados. +xxxm ou -xxxm
                        if ( string.charAt(0) == '+' ){
                            return Date.incMonth( data, stringToNumber( string.substring(1, string.length - 1) ) )
                        } else {
                            if ( string.charAt(0) == '-' ){
                                return Date.incMonth( data, -1 * stringToNumber( string.substring(1, string.length - 1) ) )
                            }
                        }
                    } else {
                        // Checa se a data foi dada relativa a hoje. +xxx ou -xxx
                        if ( string.charAt(0) == '+' ){
                            if ( monthYearFormat ) {
                                return Date.incMonth( data, stringToNumber( string.substr(1) ) )
                            } else {
                                return incDate( data, stringToNumber( string.substr(1) ) )
                            }
                        } else {
                            if ( string.charAt(0) == '-' ){
                                if ( monthYearFormat ) {
                                    return Date.incMonth( data, -1 * stringToNumber( string.substr(1) ) )
                                } else {
                                    return incDate( data, -1 * stringToNumber( string.substr(1) ) )
                                }
                            }
                        }
                    }
                }
            }
        }

        // 1o formata string para padrao definido em dateFormat
        var diaMesAno = new Array()
        diaMesAno[0] = ''
        diaMesAno[1] = ''
        diaMesAno[2] = ''

        var contador = 0

        if ( monthYearFormat && string.length <= 7 ) {
            contador = 1
        }

        for ( var i=0; i < string.length ; i++ ) {
            var code = string.charAt( i)
            if ( code >= '0' && code <= '9' ) {
                if ( diaMesAno[ contador].length >= 2 ) { // aceite até 2 numeros para mes e dia, se não pula contador
                    if ( contador == 2 ) { // esta no ano?
                        if ( diaMesAno[ contador].length > 3 ) { // aceita até 4 numeros
                            throw ''
                        }
                    } else {
                        contador++
                    }
                }
                code = diaMesAno[ contador] + code
                diaMesAno[ contador] = code
            } else {
                contador++
                if ( contador > 2 ) {
                    throw ''
                }
            }
        }

        // Se mês não foi preenchido, usa o mes atual
        if ( diaMesAno[ 1] == '' ) {
            var mes        = new Date()
            mes            = '00' + ( mes.getMonth() + 1 )
            diaMesAno[ 1]  = mes.substr( mes.length - 2 )
        }
        // Se ano nao foi preenchido, usa o ano atual
        if ( diaMesAno[ 2] == '' ) {
            var ano        = new Date()
            diaMesAno[ 2]  = '' + ano.getFullYear()
        }
        // Garante que dia, mes e ano, possuem 2 caracteres
        for ( var i = 0 ; i < 3 ; i++ ) {
            if ( diaMesAno[i].length == 1 ) {
                var numero = '0' + diaMesAno[i]
                diaMesAno[i] = numero
            }
        }

        // Faz tratamento de ano com 2 digitos, e se tiver 3 digitos coloca um '0' como prefixo
        var anoOriginal = diaMesAno[2]
        var numero = stringToNumber( diaMesAno[2])
        if ( numero < 1000 ) {
            if ( numero < 100 ) {
                var ano        = new Date()
                ano            = ano.getFullYear()
                ano            = '' + ano
                var seculo     = Number( ano.substr( 0, 2) )
                var ano        = Number( ano.substr( 2) )
                var limiteMin  = ano - 80
                var limiteMax  = ano + 19
                var incremento = 0
                if ( limiteMin < 0 ) {
                    limiteMin   = 0
                    incremento  = -1
                }
                if ( limiteMax > 99 ) {
                    limiteMax   = 99
                    incremento  = +1
                }
                if ( numero < limiteMin || numero > limiteMax ) {
                    seculo += incremento
                }
                numero = seculo + diaMesAno[2]
            } else {
                numero = '0' + diaMesAno[2]
            }
            diaMesAno[2] = numero
        }

        // Prepara string final
        var stringToValidate = ''
        string = ''                                            // 11/83
        if ( !monthYearFormat ) {                              // 11/1983
            string += diaMesAno[0] + '/'                        // 04/11
            stringToValidate += diaMesAno[0] + '/'              // 04/11/1983
        }
        
        string += diaMesAno[1] + '/' + diaMesAno[2]
        stringToValidate += diaMesAno[1]
        
        // Atendendo ao CRM 1650822, devo validar se a data final é válida
        // o browser não acusa erro, ele simplesmente "vira" a data.
        // Ex: stringToDate('3106') retorna 01/07/YYYY !!
        if ( dateFormat != DateFormat.DDMM )
            stringToValidate += '/' + diaMesAno[2]

        // Quando for no formato mes/ano assume sempre o primeiro dia do mês
        var day, year, month
        if ( monthYearFormat ) {
            day   = 1
            month = Number( string.substr( 0, 2 ) ) - 1
            year  = Number( string.substr( 3, 4 ) )
        } else {
            day   = Number( string.substr( 0, 2 ) )
            month = Number( string.substr( 3, 2 ) ) - 1
            year  = Number( string.substr( 6, 4 ) )
        }

        if ( month > 11 )
          throw new Error('Mês inválido!')

        if ( day > 31 )
          throw new Error('Dia inválido!')

        //Edgard, requisito 2450716, workaround para resolver problema com datas com horário de verão no browser
        var result = new Date( year, month, day )
        if ( result.getDate() != day ) {
            result = new Date( year, month, day, 1, 0, 0 )
        }

        // Se Strings não baterem a data está inválida
        var dateToValidate = dateToString( result, dateFormat )
        if ( stringToValidate != dateToValidate )
            throw ""

        return result
    } catch (e) {
        throwError( 'Informe uma data válida! Valor informado: ' + string + ( e.message ? ' - ' + e.message : '' ) )
        return false // remove warning
    }
}

function upperFirstChar( s){
    if ( s){
        var ch = s.charAt(0)
        s = ch.toUpperCase() + s.substr(1)
    }
    return s
}

/**
 * TODO
 * @private
 */
function _nameTitleCaseTreatment( s, upperChars, excepts ){
    s = s.toLowerCase()
    var ar = s.split( ' ')
    // Primeira palavra sempre com primeira maiúscula
    ar[0] = upperFirstChar( ar[0])
    // navigator antes, pois o client não possui server
    if ( navigator || !(server.version.indexOf("3.3.0") == 0)){
        for ( var i = 1; i < ar.length; ++i ){
            s = ar[i]
            if ( (upperChars || s.length > 1) && !excepts['_' + s]){
                ar[i] = upperFirstChar( s)
            }
        }
    } else {
        // 3.3.0
        for ( var i = 1; i < ar.length; ++i ){
            s = ar[i]
            if ( (upperChars || s.length > 1) && ! eval( 'excepts._' + s)){
                ar[i] = upperFirstChar( s)
            }
        }
    }
    return ar.join(' ')
}

// Utiliza underscore, pois algumas das palavras são reservadas
var _caseTreatment_nameExcepts      = new Date() // Não uso object, pois não existe no 3.3.0
_caseTreatment_nameExcepts._of   = true
_caseTreatment_nameExcepts._da   = true
_caseTreatment_nameExcepts._do   = true
_caseTreatment_nameExcepts._de   = true
_caseTreatment_nameExcepts._dos  = true
_caseTreatment_nameExcepts._das  = true
var _caseTreatment_titleExcepts      = new Date() // Não uso object, pois não existe no 3.3.0
_caseTreatment_titleExcepts._of   = true
_caseTreatment_titleExcepts._the  = true
_caseTreatment_titleExcepts._to   = true
_caseTreatment_titleExcepts._with = true
_caseTreatment_titleExcepts._da   = true
_caseTreatment_titleExcepts._do   = true
_caseTreatment_titleExcepts._de   = true
_caseTreatment_titleExcepts._dos  = true
_caseTreatment_titleExcepts._das  = true
_caseTreatment_titleExcepts._com  = true
_caseTreatment_titleExcepts._para = true
_caseTreatment_titleExcepts._no   = true
_caseTreatment_titleExcepts._na   = true
_caseTreatment_titleExcepts._nos  = true
_caseTreatment_titleExcepts._nas  = true

function caseTreatment( s, caseType ) {
    s = s + ''
    if ( caseType == 'upper' ){
        return s.toUpperCase()
    } else {
        if ( caseType == 'lower' ){
            return s.toLowerCase()
        } else {
            if ( caseType == 'name' || caseType == 'mixed' ){
                return _nameTitleCaseTreatment( s, true, _caseTreatment_nameExcepts)
            } else {
                if ( caseType == 'title' ){
                    return _nameTitleCaseTreatment( s, false, _caseTreatment_titleExcepts)
                } else {
                    if ( caseType == 'statement' ){
                        s = s.toLowerCase()
                        var character     = ''
                        var result        = ''
                        var upperNextChar = true
                        for ( var i = 0; i < s.length; i++ ){
                            if (  upperNextChar &&
                                    ( s.charAt(i)     != ' ' ) &&
                                    ( s.charAt(i)     != '.' ) &&
                                    ( s.charCodeAt(i) != 13  ) &&
                                    ( s.charCodeAt(i) != 10  ) ){
                                character     = s.charAt(i)
                                result       += character.toUpperCase()
                                upperNextChar = false
                            } else {
                                result       += s.charAt(i)
                                if ( s.charAt(i) != ' ' ){
                                    upperNextChar = ( s.charAt(i) == '.' ) || ( s.charCodeAt(i) == 13 ) || ( s.charCodeAt(i) == 10 )
                                }
                            }
                        }
                        return result
                    } else {
                        throwError( '/inteq/library/strings.js caseTreatment() CaseType "' + caseType + '" invalid.' )
                        return false // remove warning
                    }
                }
            }
        }
    }
}

// Converte qualquer valor em string
function formatValue( value, dateFormat ) {
    if ( value instanceof Date || typeof value == 'date' ) {
        return dateToString( value, dateFormat )
    } else {
        if ( !value && typeof value != 'number' ) {
            return ''
        } else {
            return '' + value
        }
    }
}

// prepara array para conversor htmlString()
var htmlStringTranslateFlagArray = new Array()
var htmlStringTranslateFlagArrayCriado = false
/**
 * TODO
 * @private
 */
function criaHtmlStringTranslateFlagArray() {
    for ( var i = 0 ; i < 256 ; i++ ) {
        htmlStringTranslateFlagArray[ i] = false
    }
    htmlStringTranslateFlagArray[   9] = true //Horizontal tab
    htmlStringTranslateFlagArray[  10] = true //Line feed
    htmlStringTranslateFlagArray[  13] = true //Carriage return
    for ( var i = 34 ; i <= 38 ; i++ ) { // aspas duplas até apostrofo
        htmlStringTranslateFlagArray[ i] = true
    }
    htmlStringTranslateFlagArray[  42] = true // *
    htmlStringTranslateFlagArray[  43] = true // +
    htmlStringTranslateFlagArray[  47] = true // /
    htmlStringTranslateFlagArray[  60] = true // <
    htmlStringTranslateFlagArray[  62] = true // >
    htmlStringTranslateFlagArray[  91] = true // ]
    htmlStringTranslateFlagArray[  92] = true //    htmlStringTranslateFlagArray[  94] = true // ^
    htmlStringTranslateFlagArray[  93] = true // [
    htmlStringTranslateFlagArray[  95] = true // _
    htmlStringTranslateFlagArray[  96] = true // `
    htmlStringTranslateFlagArray[ 124] = true // |
    htmlStringTranslateFlagArray[ 126] = true // ~
    htmlStringTranslateFlagArray[ 160] = true //Non-breaking space
    for ( var i = 160 ; i <= 255 ; i++ ) {
        htmlStringTranslateFlagArray[ i] = true
    }
    htmlStringTranslateFlagArrayCriado = true
}

function htmlString( vText ) {
    if ( navigator == undefined ) {
        return vText.toHtmlString()
    } else {
        if ( vText == null ) {
            vText = ''
        } else {
            if ( vText instanceof Date || typeof vText == 'date' ) {
                vText = dateToString( vText)
            } else {
                vText = '' + vText
            }
        }
        // Se ainda nao existe array de flags, cria-o
        if ( ! htmlStringTranslateFlagArrayCriado ) {
            criaHtmlStringTranslateFlagArray()
        }
    	var result = ''
        if ( vText.length > 0 ) {
            for ( var i = 0 ; i < vText.length ; i++ ) {
                var code = vText.charAt( i)
                if ( htmlStringTranslateFlagArray[ code.charCodeAt(0)]  ) {
                    result += '&#' + code.charCodeAt(0) + ';'
                } else {
                    if ( i > 0 ) {
                        if ( code == ' ' ) {
                            if ( vText.charAt( i-1) == ' ' ) {
                                code = '&#160;'
                            }
                        }
                    }
                    result += code
                }
            }
        }
        return result
    }
}

// prepara array para conversor que Tira Acentuacao
var noAccentTranslateArray = new Array()
var noAccentTranslateArrayCriado = false
function criaNoAccentTranslateArray() {
    for ( var i = 0 ; i < 256 ; i++ ) {
        noAccentTranslateArray[ i] = ''
    }
    noAccentTranslateArray[ 'Ç'.charCodeAt(0)] = 'C'
    noAccentTranslateArray[ 'ç'.charCodeAt(0)] = 'c'
    noAccentTranslateArray[ 'Á'.charCodeAt(0)] = 'A'
    noAccentTranslateArray[ 'á'.charCodeAt(0)] = 'a'
    noAccentTranslateArray[ 'À'.charCodeAt(0)] = 'A'
    noAccentTranslateArray[ 'à'.charCodeAt(0)] = 'a'
    noAccentTranslateArray[ 'Ä'.charCodeAt(0)] = 'A'
    noAccentTranslateArray[ 'ä'.charCodeAt(0)] = 'a'
    noAccentTranslateArray[ 'Ã'.charCodeAt(0)] = 'A'
    noAccentTranslateArray[ 'ã'.charCodeAt(0)] = 'a'
    noAccentTranslateArray[ 'Â'.charCodeAt(0)] = 'A'
    noAccentTranslateArray[ 'â'.charCodeAt(0)] = 'a'
    noAccentTranslateArray[ 'É'.charCodeAt(0)] = 'E'
    noAccentTranslateArray[ 'é'.charCodeAt(0)] = 'e'
    noAccentTranslateArray[ 'È'.charCodeAt(0)] = 'E'
    noAccentTranslateArray[ 'è'.charCodeAt(0)] = 'e'
    noAccentTranslateArray[ 'Ë'.charCodeAt(0)] = 'E'
    noAccentTranslateArray[ 'ë'.charCodeAt(0)] = 'e'
    noAccentTranslateArray[ 'Ê'.charCodeAt(0)] = 'E'
    noAccentTranslateArray[ 'ê'.charCodeAt(0)] = 'e'
    noAccentTranslateArray[ 'Í'.charCodeAt(0)] = 'I'
    noAccentTranslateArray[ 'í'.charCodeAt(0)] = 'i'
    noAccentTranslateArray[ 'Ì'.charCodeAt(0)] = 'I'
    noAccentTranslateArray[ 'ì'.charCodeAt(0)] = 'i'
    noAccentTranslateArray[ 'Ï'.charCodeAt(0)] = 'I'
    noAccentTranslateArray[ 'ï'.charCodeAt(0)] = 'i'
    noAccentTranslateArray[ 'Î'.charCodeAt(0)] = 'I'
    noAccentTranslateArray[ 'î'.charCodeAt(0)] = 'i'
    noAccentTranslateArray[ 'Ó'.charCodeAt(0)] = 'O'
    noAccentTranslateArray[ 'ó'.charCodeAt(0)] = 'o'
    noAccentTranslateArray[ 'Ò'.charCodeAt(0)] = 'O'
    noAccentTranslateArray[ 'ò'.charCodeAt(0)] = 'o'
    noAccentTranslateArray[ 'Ö'.charCodeAt(0)] = 'O'
    noAccentTranslateArray[ 'ö'.charCodeAt(0)] = 'o'
    noAccentTranslateArray[ 'Õ'.charCodeAt(0)] = 'O'
    noAccentTranslateArray[ 'õ'.charCodeAt(0)] = 'o'
    noAccentTranslateArray[ 'Ô'.charCodeAt(0)] = 'O'
    noAccentTranslateArray[ 'ô'.charCodeAt(0)] = 'o'
    noAccentTranslateArray[ 'Ú'.charCodeAt(0)] = 'U'
    noAccentTranslateArray[ 'ú'.charCodeAt(0)] = 'u'
    noAccentTranslateArray[ 'Ù'.charCodeAt(0)] = 'U'
    noAccentTranslateArray[ 'ù'.charCodeAt(0)] = 'u'
    noAccentTranslateArray[ 'Ü'.charCodeAt(0)] = 'U'
    noAccentTranslateArray[ 'ü'.charCodeAt(0)] = 'u'
    noAccentTranslateArray[ 'Û'.charCodeAt(0)] = 'U'
    noAccentTranslateArray[ 'û'.charCodeAt(0)] = 'u'
    noAccentTranslateArrayCriado = true
}

function noAccent( vText ) {
    if ( vText instanceof Date || typeof vText == 'date' ) {
        return dateToString( vText)
    }
    vText = vText + ''
    // Se ainda nao existe array de flags, cria-o
    if ( ! noAccentTranslateArrayCriado ) {
        criaNoAccentTranslateArray()
    }
	var substitui = ''
    for ( var i = 0 ; i < vText.length ; i++ ) {
        substitui = noAccentTranslateArray[ vText.charCodeAt(i)]
        if ( substitui ) {
            vText = vText.substr( 0, i) + substitui + vText.substr( i+1)
        }
    }
    return vText
}

function identifierToName( identifier ) {
    //profiler.startOperation( "identifierToName()", null, true)
    // try {
        // Exceção. Se o nome for todo maiúsculo, transforma em mixed. Muito útil para
        //  não precisar definir label para campos como NOME
        if ( identifier == identifier.toUpperCase()){
            return caseTreatment( identifier, 'mixed')
        } else {
            var result = identifier.charAt( 0 )
            result     = result.toUpperCase()
            var s = 1
            var ch = ''
            for ( var i = 1; i < identifier.length; i++ ) {
                ch = identifier.charAt( i)
                if ( ch == ch.toUpperCase() ) {
                    result += identifier.substring( s, i ) + ' ' + ch
                    s = i + 1
                }
            }
            if ( ch != ch.toUpperCase() ) {
                result += identifier.substring( s, identifier.length )
            }
            // Torna mais legível o name. Ex: "de" ao invés de "De".
            result = caseTreatment( result, 'title')
            return result
        }
    //} finally {
    //   profiler.endOperation()
    //}
}

function nameToIdentifier( name, firstCharUpperCase, ifOnlyWordDontChangeCase ) {
    name = noAccent( name )
    if ( firstCharUpperCase == undefined ) {
        firstCharUpperCase = false
    }
    if ( name.charAt(0) >= '0' && name.charAt(0) <= '9' ) {
        throwError( 'O nome informado não pode ser convertido num identificador por iniciar com número. Nome informado: ' + name )
    }
    var result = ''
    var s = 0
    var upperCase = firstCharUpperCase

    if ( ifOnlyWordDontChangeCase && name.indexOf( ' ' ) < 0 ) {
        if ( firstCharUpperCase ) {
            var ch = name.charAt( 0 )
            result = ch.toUpperCase() + name.substr( 1 )
        } else {
            var ch = name.charAt( 0 )
            result = ch.toLowerCase() + name.substr( 1 )
        }
    } else {
        for ( var i = 0; i < name.length; i++ ) {
            var ch = name.charAt( i)
            if ( ch == '_' || ( ch >= 'a' && ch <= 'z' ) || ( ch >= 'A' && ch <= 'Z' ) || ( ch >= '0' && ch <= '9' ) ) {
                if ( ch == ch.toUpperCase() && !upperCase ) {
                    result += name.substring( s, i ) + ch.toLowerCase()
                    s = i + 1
                } else {
                    if ( upperCase ) {
                        result += name.substring( s, i ) + ch.toUpperCase()
                        s = i + 1
                        upperCase = false
                    }
                }

            } else {
                result += name.substring( s, i )
                s = i + 1
                if ( result.length == 0 ) {
                    upperCase = firstCharUpperCase
                } else {
                    upperCase = true
                }
            }
        }
        result += name.substring( s, i )
    }
    return result
}

/**
 * @private <optional>
 */
_toStringExpression_numberToStringUsePointSeparator = ((10.2).toString()).indexOf(".") >= 0
function toStringExpression( value, parentString ) {
    profiler.startOperation( "toStringExpression()", null, true)
    try {
        // Otimizado para os casos mais frequentes
        if ( value === null || value === undefined){
            // O framework conta que undefined irá retornar "null"
            return "null"
        } else {
            var typeofValue = typeof value
            if ( typeofValue == "string" || value instanceof String ){
                if ( value ){
                    value = value.replace( '\\', '\\\\' )
                    value = value.replace( '\r', '\\r' )
                    value = value.replace( '\n', '\\n' )
                    value = value.replace( '"', '\\"' )
                    return '"' + value + '"'
                } else {
                    return '""'
                }

            } else if ( typeofValue == "number" || value instanceof Number){
                if ( _toStringExpression_numberToStringUsePointSeparator ){
                    return value.toString()
                } else {
                    value = value.toString()
                    return value.replace( ",", ".")
                }

            } else if ( typeofValue == "boolean"){
                // Framework conta que retorna um boolean ao invés de string
                return value

            } else if ( value instanceof Date || typeofValue == 'date' ) {            
                var year = value.getFullYear()
                var month = value.getMonth()
                var dayOfMonth = value.getDate()

                //Edgard, requisito 2450716, workaround para resolver problema com datas com horário de verão no browser
                var dt = 'new ' + ( parentString ? parentString : '' ) + 'Date( ' + year + ', ' + month + ', ' + dayOfMonth + ', ' + value.getHours() + ', ' + value.getMinutes() + ', ' + value.getSeconds() + ' )'             
                return "( " + dt + " ).getDate() == " + dayOfMonth + " ? " + dt + " : new Date( " + year + ", " + month + ", " + dayOfMonth + ", 1, 0, 0 )"
            } else if (value instanceof Array) {
                var ar = [];
                for (var i = 0; i < value.length; ++i) {
                    ar.push(toStringExpression(value[i]));
                }

                return "[ " + ar.join(", ") + " ]";
            }
        }

    } finally {
        profiler.endOperation()
    }
}

function extractNameFromUrl( url ) {
    var result = ''
    if ( url ) {
        var endName   = url.lastIndexOf( '.' )
        if ( endName < 0) {
            endName = url.length
        }
        var startName = url.lastIndexOf( '/' )
        if ( startName < 0 ) {
            startName = 0
        } else {
            startName += 1
        }
        result = url.substring( startName, endName )
    }
    return result
}

function padString( content, size, align, padChar ) {
    if ( typeof size == 'number' ) {
        if ( !align ) {
            align = 'left'
        }
        if ( !padChar ) {
            padChar = ' '
        }
        var result = padChar.repeat( size)
        if ( content ) {
            content = content + ''
            if ( size < content.length ) {
                content = content.substr( 0, size)
            } else {
                if ( align == 'right' ) {
                    content = padChar.repeat( size - content.length) + content
                } else {
                    if ( align == 'center' ) {
                        content = padChar.repeat( Math.round( ( size - content.length ) / 2 ) ) + content
                    }
                    content += padChar.repeat( size - content.length) // Alinhamento a esquerda
                }
            }
            result = content
        }
        return result
    } else {
        throw new DetailedError( 'Parâmetro "size" inválido.',
                                         'Informe um size válido.',
                                         'Objeto passado: ' +  size,
                                         '/inteq/library/strings.js padString()' )
    }
}

function padNumber( content, size, decimalPrecision, decimalSeparator, align, padChar ) {
    if ( !align ) {
        align = 'right'
    }
    if ( !padChar ) {
        padChar = '0'
    }
    if ( !decimalPrecision && decimalPrecision != 0 ) {
        decimalPrecision = 2
    }
    if ( !decimalSeparator && decimalSeparator != '' ) {
        decimalSeparator = '.'
    }
    content = stringToNumber( content + '' )

    if ( content < -0.00001 ){
        content    = Math.abs( content )
        var prefix = '-'
        size--
    } else {
        var prefix = ''
    }
    content = formatNumber( content, decimalPrecision )
    content = content.replace( '.', decimalSeparator )

    var result = prefix + padString( content, size, align, padChar)
    return result
}

// Prepara um fonte HTML para ser exibido dentro de uma página HTML
function prepareHtmlSourceToDisplay( str ){
    var result = ''
    var i = 0
    while ( i < str.length ){
        if ( str.charAt(i) == '<' ){
            result += '&lt;'
        } else {
            if ( str.charAt(i) == '>' ){
                result += '&gt;'
            } else {
                if ( str.charCodeAt(i) == 9 ){
                    result += '&nbsp;&nbsp;'
                } else {
                    if ( ( str.charCodeAt(i) == 13 ) || ( str.charCodeAt(i) == 10 ) ){
                        result += '<br>'
                        if ( ( i + 1 ) < str.length ){
                            if ( str.charCodeAt( i + 1 ) == 10 ){
                                i++
                            }
                        }
                    } else {
                        result += str.charAt(i)
                    }
                }
            }
        }
        i++
    }
    return result.toHtmlString()
}

/* Substituído pelo String.prototype.repeat abaixo
function repeatString( str, len ){
    var result = ''
    if ( navigator == undefined ){
        // Servidor
        result = str.repeat( len )
    } else {
        // Cliente
        for ( var i=0; i<len; i++) result += str
    }
    return result
}
*/

if ( navigator != undefined ){

    // Implementa String.compare() no cliente
    //                                            1         2         3          4         5         6         7         8         9          0         1         2         3         4         5         6         7         8         9         0         1         2         3         4         5
    //                                  0123456789012345678901234567890123456789 01234567890123456789012345678901234567890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345
    var stringCompareTranslateVector = '                                 !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~                                                                 AAAAAA CEEEEIIII  OOOOO  UUUUY  AAAAAA CEEEEIIII  OOOOO  UUUUY Y';
    String.prototype.compare = function ( string ){
        if ( this.length <= string.length ){
            var minLength = this.length
        } else {
            var minLength = string.length
        }
        var cmpResult = 0
        for ( var i = 0; i < minLength; i++ ){
            cmpResult = stringCompareTranslateVector.charCodeAt( this.charCodeAt(i) ) - stringCompareTranslateVector.charCodeAt( string.charCodeAt(i) )
            if ( cmpResult != 0 ){
                return cmpResult
            }
        }
        // Se foram iguais até o momento, compara o tamanho das strings
        return this.length - string.length
    }

    String.prototype.toHtmlString = function (){
        return htmlString( this )
    }

    String.prototype.trim = function () {
        var pos, len
        len = this.length
        pos = 0
        // Retira espaços do início
        while ( pos <= len && this.charAt(pos) <= ' ' ) {
            ++pos
        }
        // Caso só tenha espaços na string
        if ( pos > len ) {
            return ''
        } else {
            // Retira espaços do final
            while ( this.charAt(len) <= ' ' ) {
                --len
            }
            return this.substr( pos, len - pos + 1 )
        }
    }
    
    String.prototype.repeat = function ( len) {
        var result = ''
        for ( var i = 0; i < len; i++ )
            result += this;
        return result
    }
}

// Tradução de strings
function _( s){
    return s
}

function htmlToText( str ) {
    a = str.indexOf("<");
    b = str.indexOf(">");
    len = str.length;
    c = str.substring(0, a);
    if( b == -1 ){
        b = a;
    }
    d = str.substring((b + 1), len);
    str = c + d;
    tagCheck = str.indexOf("<");
    if( tagCheck != -1 )
        str = htmlToText(str);
    return str;
}

function htmlStringLength( str ){
    var endChar = null;
    var blockLimit = 0;
    var blockLen = 0;
    var length = 0;
    var beginBlockChars = new Object();
    beginBlockChars["<"] = true;
    beginBlockChars["&"] = true;

    for ( var i = 0; i < str.length; ++i ){
        var ch = str.charAt(i);
        if ( beginBlockChars[ch] ){
            blockLimit = Math.min( ch == "&" ? 7 : Number.MAX_VALUE, str.length - i );
            endChar = ch == "&" ? ";" : ">";
            // Adiciona no tamanho, o bloco atualmente aberto. Isto é necessário para
            // tratar os casos em que existe mais de uma abertura de bloco sem o
            // fechamento correspondente. Exemplo: A&BCDEF;&nbsp;
            length+= blockLen;
            blockLen = 1;
        } else {
            if ( endChar == null ){
                length++;
            } else {
                blockLen++;
                if ( ch == endChar || blockLen > blockLimit ){
                    if ( ch != endChar ){
                        // Se o bloco ultrapassar o limite, devo considerar os caracteres
                        length += blockLen;
                    }
                    // Se for o fim do bloco e for um bloco &xxx; entao devo acrescentar
                    // 1 ao length, pois consideramos esta entidade como um espaço em branco.
                    length += endChar == ";" ? 1 : 0;
                    endChar = null;
                    blockLen = 0;
                }
            }
        }
    }

    // Acrescenta o último bloco aberto
    length+= blockLen;

    return length;
}

function trim( s ) {
    if ( !s ) return ''

    pos = 0
    len = s.length
    // Retira espaços do início
    while ( pos <= len && s.charAt(pos) <= ' ' ) {
        ++pos
    }
    // Caso só tenha espaços na string
    if ( pos > len ) {
        return ''
    } else {
        // Retira espaços do final
        while ( s.charAt(len) <= ' ' ) {
            --len
        }
        return s.substr( pos, len - pos + 1 )
    }
}

/*
function numberToMoney( num ) {
    var result
    var isNegative = false

    if( num < 0) {
        num = Math.abs( num )
        isNegative = true
    }

    if( isNaN( num ) ){
         result = "0"
    }
    cents = Math.floor( ( num*100 + 0.5 ) % 100 );
    num = Math.floor((num*100+0.5)/100).toString();
    if(cents < 10) cents = "0" + cents;
        for (var i = 0; i < Math.floor((num.length-(1+i))/3); i++)
            num = num.substring(0,num.length-(4*i+3))+'.'
                    +num.substring(num.length-(4*i+3));
    ret = num + ',' + cents;
    if (x == 1) ret = ' - ' + ret;
    return ret;
}
*/

