Unicode-преобразования

Clarion, Clarion 7

Модератор: Дед Пахом

Правила форума
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
Ответить
Гость

Сообщение Гость »

Поделитесь опытом использования API-функции WideCharToMultiByte (у кого этот опыт имеется).
Задача такая - нужно получить вместо русской буквы "А" символы "0430" (или просто два соответствующих байта), вместо "Б" - "0431" и так далее. А также интересует обратное преобразование.
В принципе, можно самому прописать таблицу соответствий, но не хочется туда пихать весь русский алфавит, да еще в придачу остальные славянские символы.

Написал: Booroondook(77)
Гость

Сообщение Гость »

А в чём проблема?

Module('Windows API')

MultiByteToWideChar(UINT Codepage,DWORD dwFlags,ULong LpMultuByteStr, !
Long cbMultiByte, ULong LpWideCharStr,Long cchWideChar),RAW,DWord,PASCAL

WideCharToMultiByte(UINT Codepage,DWORD dwFlags,ULong LpWideCharStr,Long cchWideChar, !
ULong lpMultuByteStr, Long cbMultiByte, Ulong LpDefalutChar,LpBool lpUsedDefalutChar), !
Raw,DWord,Pascal

GETACP(),RAW,DWORD,PASCAL
End

If WideCharToMultiByte(GetACP(),0,Address(UnicodeText),BufSize,Address(Buffer),BufSize+1,0,0).
Buffer[BufSize+1]='<0>'

Cpage - кодовая страница (получается как Cpage=GetACP())
UnicodeText - адрес юникода (должен кончаться на <0,0>)
BufSize - размер выходного буфера ( половина от размера юникода)
Buffer - куда класть результат

If MultiByteToWideChar(GetACP(),0,Address(Buffer),BufSize,Address(UnicodeText),BufSize*2+2).

Buffer должен кончаться на '<0>'

А напоследок маленькая рутинка преобразования HTML-строки из Unicode в ASCII

Переменная S содержит содержимое некоторого HTML-файла в Юникоде &#1040&#1041 ... . После завершения она перекодирована в ASCII. Может быть, это и нужно?

Код: Выделить всё

ReplaceHex    Routine  ! Замена Unicode
              Data
Loc:InPos     Long
Loc:OutPos    Long
Loc:Len       Long
Loc:S1        String(1)
              Code
              Loc:InPos=1
              Loc:OutPos=1
              Loc:Len=Len(S)
              Loop
                 If Loc:InPos>Loc:Len Then Break.
                 Loc:S1=S[Loc:InPos]
                 Case Loc:S1
                 Of '<0>'
                   Break
                 Of '&'
                   Loc:S1=S[Loc:InPos+1]
                   If Loc:S1='#'
                     I#=S[Loc:Inpos+2 : Loc:InPos+5]
                     If Inrange(I#,1040,1103)
                       Loc:S1=Chr(Val('А')+(I#-1040))
                     Elsif I#=1025
                       Loc:S1='Ё'
                     Elsif I#=1105
                       Loc:S1='ё'
                     Else
                       Loc:S1=''
                     End
                     S[Loc:OutPos]=Loc:S1
                     Loc:InPos+=7
                     Loc:OutPos+=1
                   Else
                     S[Loc:OutPos]=S[Loc:InPos]
                     Loc:InPos+=1
                     Loc:OutPos+=1
                   End
                 Else
                   S[Loc:OutPos]=S[Loc:InPos]
                   Loc:InPos+=1
                   Loc:OutPos+=1
                 End
              End
              S=Sub(S,1,Loc:OutPos-1)
              Exit
--
C уважением
Yuri
Адрес:yufil@mail.ru
Написал: ClaList(2)
Гость

Сообщение Гость »

Спасибо - у меня все получилось.
Отдельное спасибо за совет с получением кодовой страницы.
Я ее получаю из реестра, но вызов функии GetACP выглядит намного изящнее - буду использовать именно эту функцию.
Написал: Booroondook(77)
NewUser
Старожил
Сообщения: 238
Зарегистрирован: 10 Ноябрь 2005, 23:07
Откуда: Краснодар
Благодарил (а): 6 раз

Unicode-преобразования

Сообщение NewUser »

Здравствуйте!
Посмотрите, пожалуйста, что я делаю не так и почему при вызове функции WideCharToMultiByte компилятор выдает сообщение об ошибке прототипирования.
В GMap:
WideCharToMultiByte(UINT Codepage,DWORD dwFlags,ULong LpWideCharStr,Long cchWideChar, ULong lpMultuByteStr, Long cbMultiByte, Ulong LpDefalutChar,LpBool lpUsedDefalutChar), Raw,DWord,Pascal
GETACP(),RAW,DWORD,PASCAL

В локальных переменных:
loc:Unicode CString(255)
loc:ASCII CString(255)
Codepage Unsigned
BufSize Long

Вызов функции:
!--- Преобразование Unicode в ASCII----------------------
loc:Unicode = SUB(Buffer,1,10) !Информация, полученная с сайта в UTF-кодировке
Codepage = GetACP()
BufSize = Size(loc:ASCII) + 1
!If WideCharToMultiByte(GetACP(),0,Address(loc:Unicode),BufSize,Address(loc:ASCII),BufSize+1,0,0).
If WideCharToMultiByte(Codepage,0,Address(loc:Unicode),BufSize,Address(loc:ASCII),Size(loc:ASCII),0,0).
loc:ASCII[BufSize+1]='<0>'
VKUQ:UserName = loc:ASCII

Выдаются следующие ошибки:
Label in prototype not defined: UINT
Label in prototype not defined: LPBOOL
No matching prototype available
kreator
✯ Ветеран ✯
Сообщения: 5190
Зарегистрирован: 28 Май 2009, 15:54
Откуда: Москва
Благодарил (а): 11 раз
Поблагодарили: 26 раз

Unicode-преобразования

Сообщение kreator »

Либо в "Global Embeds" в "After global Includes" написать типа:

Код: Выделить всё

UINT                    EQUATE(UNSIGNED)
Либо подключить в проект svapifnc.inc (там эти функции прописаны).
Либо в svapifnc.inc посмотреть их описание.
Можно ещё подождать одиннадцатой версии с полной поддержкой Unicode :mrgreen: .
We are hard at work… for you. :)
NewUser
Старожил
Сообщения: 238
Зарегистрирован: 10 Ноябрь 2005, 23:07
Откуда: Краснодар
Благодарил (а): 6 раз

Unicode-преобразования

Сообщение NewUser »

Прописал в указанное место вместе с UINT'ом и LPBOOL и все заработало. Спасибо!
Но результат работы не тот, который ожидался. Программа получает с сайта данные в Buffer, распарсивает их и... До внедрения обсуждаемой функции было:
Before.jpg
После применения функции преобразования стало:
After.jpg
Куда дальше смотреть?
Аватара пользователя
Дед Пахом
Старичок
Сообщения: 3306
Зарегистрирован: 07 Июль 2005, 16:51
Откуда: Москва, Россия
Благодарил (а): 15 раз
Поблагодарили: 51 раз
Контактная информация:

Unicode-преобразования

Сообщение Дед Пахом »

Честно говоря, не вдаваясь в детали, могу сказать, что написан полный и опасный бред. Во-первых, почему всё в CString-ах? Во-вторых, посмотрите сюда:

BufSize = Size(loc:ASCII) + 1
loc:ASCII[BufSize+1]='<0>'

вторая строка делает присвоение за границами loc:ASCII.

В-третьих, WideCharToMultiByte надо вызывать дважды, первый раз с нулём вместо Size(loc:ASCII), тогда она вернёт размер строки, второй раз с эти размером.
С уважением, ДП
kreator
✯ Ветеран ✯
Сообщения: 5190
Зарегистрирован: 28 Май 2009, 15:54
Откуда: Москва
Благодарил (а): 11 раз
Поблагодарили: 26 раз

Unicode-преобразования

Сообщение kreator »

NewUser, посмотри файл svcom.clw. Там есть использование этой функции. Вдруг поможет.
We are hard at work… for you. :)
Yufil
Ветеран движения
Сообщения: 1277
Зарегистрирован: 16 Май 2006, 14:34
Контактная информация:

Unicode-преобразования

Сообщение Yufil »

Речь не идёт о UTF-8? Много раз рассылал класс CSTR, в котором это с полпинка

https://mega.co.nz/#!RlAilJIT!2hvwWBkAn ... J3FmCLcmvw

Там эта операция примерно так звучит
U Cstr
....
U.Set(MyString)
U.toUTF8()
После чего U.S содержит строку MyString, перекодированную в UTF-8. Ну и всякий другой сахар для работы со строками неопределённой длины - конкатенация, загрузка файла, сохранение в файл, загрузка из Blob, сохранение в Blob.
Ответить