// '/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. Gera um erro caso não seja possível.
function stringToInteger( string ){
   var number = stringToNumber( string )
   if ( number == Math.floor( number ) ){
      return number
   } else {
      // Tratamento paleativo para tratar inteiros JS que
      // excedem o inteiro do Delphi (31 bits)
      // O requisito ??? 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
   }
}

/*
   // Reginaldo: Código temporariamente comentado, pois o mesmo será retirado

// Formata um número com um determinado número de casas decimais
function formatNumber( number, nMaxDecimals, nMinDecimals ){
   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.000001 ){
      var signal = '-'
      number = Math.abs( number )
   } else {
      var signal = ''
   }
   var dec = '' + Math.round( number * Math.pow( 10, nMaxDecimals ) )
   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 ){
         return signal + dec.substr( 0, dec.length - nMaxDecimals ) + '.' + dec.substr( dec.length - nMaxDecimals, 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 )
         }
      }
   }
}

// Converte qualquer valor em string
function formatValue( value ) {
   if ( value instanceof Date || typeof value == 'date' ) {
      return dateToString( value)
   } else {
      if ( value == null ) {
         return ''
      } else {
         return '' + value
      }
   }
}

*/

// Formata um número com um determinado número de casas decimais ( arredondando )
function formatNumber( number, nMaxDecimals, nMinDecimals ){
   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.000001 ){
      var signal = '-'
      number = Math.abs( number )
   } else {
      var signal = ''
   }
   var dec = '' + Math.round( number * Math.pow( 10, nMaxDecimals ) )
   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 ( 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.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 >= '3.3.1'){
      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 == 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 ( ! 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 ) {
   // 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
   }
}

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
}

function toStringExpression( value, parentString ) {
   var typeofValue = typeof value
   if ( !value && ( typeofValue != 'string' ) && ( typeofValue != 'number' ) && ( typeofValue != 'boolean' ) && !( value instanceof Date || typeof value == 'date' ) ) {
      return 'null'
   } else {
      if ( value instanceof Date || typeof value == '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 ( typeofValue == 'number' ) {
            value = value.toString()
            if ( typeof value == 'number' ){
               value = value.toString()
               if ( typeof value == 'number' ){
                  throw new Error( 'Opa:' + value )
               }
            }
            return value.replace( ',', '.' )
         } else {
            if ( typeofValue == 'string' || value instanceof String ) {
               value = value.replace( '\\', '\\\\' )
               value = value.replace( '\r\n', '\\r\\n' )
               value = value.replace( '\r', '\\r' )
               value = value.replace( '\n', '\\n' )
               return '"' + value.replace( '"', '\\"' ) + '"'
            } else {
               return value
            }
         }
      }
   }
}

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;
}
