CPLString ACTextUnescape( const char *pszRawInput, const char *pszEncoding )

{
    CPLString osResult;
    CPLString osInput = pszRawInput;
    
/* -------------------------------------------------------------------- */
/*      Translate text from Win-1252 to UTF8.  We approximate this      */
/*      by treating Win-1252 as Latin-1.  Note that we likely ought     */
/*      to be consulting the $DWGCODEPAGE header variable which         */
/*      defaults to ANSI_1252 if not set.                               */
/* -------------------------------------------------------------------- */
    osInput.Recode( pszEncoding, CPL_ENC_UTF8 );

    const char *pszInput = osInput.c_str();

/* -------------------------------------------------------------------- */
/*      Now translate escape sequences.  They are all plain ascii       */
/*      characters and won't have been affected by the UTF8             */
/*      recoding.                                                       */
/* -------------------------------------------------------------------- */
    while( *pszInput != '\0' )
    {
        if( pszInput[0] == '\\' && pszInput[1] == 'P' )
        {
            osResult += '\n';
            pszInput++;
        }
        else if( pszInput[0] == '\\' && pszInput[1] == '~' )
        {
            osResult += ' ';
            pszInput++;
        }
        else if( pszInput[0] == '\\' && pszInput[1] == 'U' 
                 && pszInput[2] == '+' )
        {
            CPLString osHex;
            int iChar;

            osHex.assign( pszInput+3, 4 );
            sscanf( osHex.c_str(), "%x", &iChar );

            wchar_t anWCharString[2];
            anWCharString[0] = (wchar_t) iChar;
            anWCharString[1] = 0;
            
            char *pszUTF8Char = CPLRecodeFromWChar( anWCharString,
                                                    CPL_ENC_UCS2, 
                                                    CPL_ENC_UTF8 );

            osResult += pszUTF8Char;
            CPLFree( pszUTF8Char );
            
            pszInput += 6;
        }
        else if( pszInput[0] == '\\'
                 && (pszInput[1] == 'W' 
                     || pszInput[1] == 'T'
                     || pszInput[1] == 'A' ) )
        {
            // eg. \W1.073172x;\T1.099;Bonneuil de Verrines
            // See data/dwg/EP/42002.dwg
            // Not sure what \W and \T do, but we skip them. 
            // According to qcad rs_text.cpp, \A values are vertical
            // alignment, 0=bottom, 1=mid, 2=top but we ignore for now.
            
            while( *pszInput != ';' && *pszInput != '\0' )
                pszInput++;
        }
        else if( pszInput[0] == '\\' && pszInput[1] == '\\' )
        {
            osResult += '\\';
            pszInput++;
        }
        else if( EQUALN(pszInput,"%%c",3) 
                 || EQUALN(pszInput,"%%d",3)
                 || EQUALN(pszInput,"%%p",3) )
        {
            wchar_t anWCharString[2];

            anWCharString[1] = 0;

            // These are especial symbol representations for autocad.
            if( EQUALN(pszInput,"%%c",3) )
                anWCharString[0] = 0x2300; // diameter (0x00F8 is a good approx)
            else if( EQUALN(pszInput,"%%d",3) )
                anWCharString[0] = 0x00B0; // degree
            else if( EQUALN(pszInput,"%%p",3) )
                anWCharString[0] = 0x00B1; // plus/minus

            char *pszUTF8Char = CPLRecodeFromWChar( anWCharString,
                                                    CPL_ENC_UCS2, 
                                                    CPL_ENC_UTF8 );

            osResult += pszUTF8Char;
            CPLFree( pszUTF8Char );
            
            pszInput += 2;
        }
        else 
            osResult += *pszInput;

        pszInput++;
    }
    
    return osResult;
}