# -*- coding: iso-8859-1 -*-

# ==============================================================================
# COPYRIGHT (C) 1991 - 2003  EDF R&D                  WWW.CODE-ASTER.ORG
# THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
# IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
# THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
# (AT YOUR OPTION) ANY LATER VERSION.
#
# THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
# WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
# GENERAL PUBLIC LICENSE FOR MORE DETAILS.
#
# YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
# ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
#    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
# ==============================================================================

"""Utilities to clean, convert, deal with accentuation of strings...
and to clean bad CR.
"""

__revision__ = "$Id: mystring.py 2626 2006-12-18 07:50:27Z courtois $"


__all__ = ['convert',
           'indent', 'cleanCR', 'fclean',
           'accents2code', 'accents2sans', 'code2accents', 'code2sans',
           'clean_string', 'clean_multilines_string']

import os

# ----- differ messages translation
def _(mesg):
   return mesg

# ------------------------------------------------------------------------------
def convert(content, in_encoding, out_encoding):
   """Convertir `content` encodé en `in_encoding` vers `out_encoding`.
   """
   us = content.decode(in_encoding, 'replace')
   return us.encode(out_encoding, 'replace')

# ------------------------------------------------------------------------------
def to_utf8(content):
   """Retourne `content` (supposé être en latin-1) en utf-8.
   """
   return convert(content, 'iso-8859-1', 'utf-8')

# ------------------------------------------------------------------------------
def to_latin1(content):
   """Retourne `content` (supposé être en utf-8) en latin-1.
   """
   return convert(content, 'utf-8', 'iso-8859-1')

# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
s0 = 'àâäéèêëîïôöùûüç'
s2 = 'aaaeeeeiioouuuc'
# us = s0.decode('iso-8859-1')
us = ('xe0', 'xe2', 'xe4',
      'xe9', 'xe8', 'xea', 'xeb',
      'xee', 'xef',
      'xf4', 'xf6',
      'xf9', 'xfb', 'xfc', 'xe7')

lls = len(s0)
d_accents2code = {}
d_accents2sans = {}
d_code2accents = {}
d_code2sans    = {}
for i in range(lls):
   d_accents2code[s0[i]] = us[i]
   d_accents2sans[s0[i]] = s2[i]
   d_code2accents[us[i]] = s0[i]
   d_code2sans[us[i]]    = s2[i]


# ------------------------------------------------------------------------------
def accents2code(string):
   """Convertir une chaine accentuée en une pseudo-chaine unicode
   """
   for code in d_accents2code.keys():
      string = string.replace(code, d_accents2code[code])
   return string

# ------------------------------------------------------------------------------
def code2accents(string):
   """Convertir une pseudo-chaine unicode en une chaine accentuée
   """
   for code in d_code2accents.keys():
      string = string.replace(code, d_code2accents[code])
   return string

# ------------------------------------------------------------------------------
def code2sans(string):
   """Convertir une pseudo-chaine unicode en une chaine sans accent
   """
   for code in d_code2sans.keys():
      string = string.replace(code, d_code2sans[code])
   return string

# ------------------------------------------------------------------------------
def accents2sans(string):
   """Convertir une chaine accentuée en une chaine sans accent
   """
   for code in d_accents2sans.keys():
      string = string.replace(code, d_accents2sans[code])
   return string

# ------------------------------------------------------------------------------
def utf2latin(string):
   """Décode une chaine utf8 en latin1
   """
   try:
      ustr = string.decode('utf8')
   except UnicodeDecodeError:
      ustr = decode_chars(string, 'utf8')
   for code in d_accents2sans.keys():
      ustr = ustr.replace(code.decode('latin1'), d_accents2sans[code])
   try:
      string = ustr.encode('latin1')
   except UnicodeEncodeError:
      string = encode_chars(ustr, 'utf8')
   return string

# ------------------------------------------------------------------------------
def char_by_char(method, string, encoding):
   """Encode/Décode caractère par caractère.
   Ignore les caractères qui ne passent pas.
   """
   l_s = []
   for char in string:
      try:
         l_s.append(getattr(char, method)(encoding))
      except UnicodeEncodeError, UnicodeDecodeError:
         pass
      except:
         print _('Unexpected error in `char_by_char`')
   return ''.join(l_s)

def decode_chars(string, encoding):
   """Décode caractère par caractère.
   """
   return char_by_char('decode', string, encoding)

def encode_chars(string, encoding):
   """Décode caractère par caractère.
   """
   return char_by_char('encode', string, encoding)

# ------------------------------------------------------------------------------
def clean_string(string):
   """Nettoie une chaine
   """
   string = string.strip()
   string = accents2sans(string)
   string = code2sans(string)
   try:
      string = utf2latin(string)
   except UnicodeDecodeError, msg:
      print 'STRING : ', string
      raise UnicodeDecodeError, msg
   return string

# ------------------------------------------------------------------------------
def clean_multilines_string(ch, maxlen=90):
   """Filtre les messages :
      - retour chariot pour limiter la taille des lignes,
      - accents.
   """
   txt = []
   for l in ch.split('\n'):
      while len(l) > maxlen:
         ib = l.rfind(' ', 0, maxlen)
         if ib < 0:
            ib = maxlen
         txt.append(clean_string(l[:ib].strip()))
         l = l[ib:].strip()
      txt.append(clean_string(l.strip()))
   return '\n'.join(txt)

# ------------------------------------------------------------------------------
def indent(text, prefix):
   """Add `prefix` before each line of `text`.
   """
   l_s = [prefix+line for line in text.split(os.linesep)]
   return os.linesep.join(l_s)

# -----------------------------------------------------------------------------
def cleanCR(content):
   """Cette fonction nettoie les retours chariot d'une chaine de caractères.
   """
   # nettoyage : `os.linesep` est le bon séparateur sur cette plate-forme
   # pour conserver le dernier CR, on ajoute un blanc qu'on enlèvera après.
   content += ' '
   l_new = content.splitlines()
   s_new = os.linesep.join(l_new)[:-1]
   return s_new

# -----------------------------------------------------------------------------
def fclean(filename):
   """Cette fonction nettoie les retours chariot d'un fichier texte.
   On écrase le contenu.
   Attention si le fichier n'existe pas : IOError !
   """
   # verif
   filename = filename.strip()
   if not os.path.isfile(filename):
      raise IOError, 'File not found : %s' % filename
   elif not os.access(filename, os.W_OK):
      raise IOError, 'No write access to %s' % filename
   # nettoyage
   content = open(filename, 'r').read()
   open(filename, 'w').write(cleanCR(content))

# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
if __name__ == '__main__':
   su8 = 'texte accentuÃ© en franÃ§ais'
   print su8
   sl1 = to_latin1(su8)
   print sl1
   bis = to_latin1(sl1)
   print bis
   
   dl1 = 'déjà accentué'
   print dl1
   du8 = to_utf8(dl1)
   print du8
   bis = to_utf8(du8)
   print du8
   
