From cc2160de5cc05dc3aa77f3a34358e66f6193c8c9 Mon Sep 17 00:00:00 2001 From: MichaÅ‚ CichoÅ„ Date: Tue, 26 Jun 2012 20:35:30 +0200 Subject: Add support for AAC. --- faad2/src/plugins/QCDMp4/QCDMp4Tag.cpp | 839 +++++++++++++++++++++++++++++++++ 1 file changed, 839 insertions(+) create mode 100644 faad2/src/plugins/QCDMp4/QCDMp4Tag.cpp (limited to 'faad2/src/plugins/QCDMp4/QCDMp4Tag.cpp') diff --git a/faad2/src/plugins/QCDMp4/QCDMp4Tag.cpp b/faad2/src/plugins/QCDMp4/QCDMp4Tag.cpp new file mode 100644 index 0000000..6fabbe1 --- /dev/null +++ b/faad2/src/plugins/QCDMp4/QCDMp4Tag.cpp @@ -0,0 +1,839 @@ +#include +#include +#include "QCDTagsDLL.h" + + +//.............................................................................. +// Global Variables + +typedef struct tag +{ + char *item; + char *value; +} tag; + +typedef struct medialib_tags +{ + struct tag *tags; + unsigned int count; +} medialib_tags; + +int tag_add_field(medialib_tags *tags, const char *item, const char *value) +{ + void *backup = (void *)tags->tags; + + if (!item || (item && !*item) || !value) return 0; + + tags->tags = (struct tag *)realloc(tags->tags, (tags->count+1) * sizeof(tag)); + if (!tags->tags) { + if (backup) free(backup); + return 0; + } + else + { + int i_len = strlen(item); + int v_len = strlen(value); + + tags->tags[tags->count].item = (char *)malloc(i_len+1); + tags->tags[tags->count].value = (char *)malloc(v_len+1); + + if (!tags->tags[tags->count].item || !tags->tags[tags->count].value) + { + if (!tags->tags[tags->count].item) free (tags->tags[tags->count].item); + if (!tags->tags[tags->count].value) free (tags->tags[tags->count].value); + tags->tags[tags->count].item = NULL; + tags->tags[tags->count].value = NULL; + return 0; + } + + memcpy(tags->tags[tags->count].item, item, i_len); + memcpy(tags->tags[tags->count].value, value, v_len); + tags->tags[tags->count].item[i_len] = '\0'; + tags->tags[tags->count].value[v_len] = '\0'; + + tags->count++; + return 1; + } +} + +int tag_set_field(medialib_tags *tags, const char *item, const char *value) +{ + unsigned int i; + + if (!item || (item && !*item) || !value) return 0; + + for (i = 0; i < tags->count; i++) + { + if (!stricmp(tags->tags[i].item, item)) + { + void *backup = (void *)tags->tags[i].value; + int v_len = strlen(value); + + tags->tags[i].value = (char *)realloc(tags->tags[i].value, v_len+1); + if (!tags->tags[i].value) + { + if (backup) free(backup); + return 0; + } + + memcpy(tags->tags[i].value, value, v_len); + tags->tags[i].value[v_len] = '\0'; + + return 1; + } + } + + return tag_add_field(tags, item, value); +} + +void tag_delete(medialib_tags *tags) +{ + unsigned int i; + + for (i = 0; i < tags->count; i++) + { + if (tags->tags[i].item) free(tags->tags[i].item); + if (tags->tags[i].value) free(tags->tags[i].value); + } + + if (tags->tags) free(tags->tags); + + tags->tags = NULL; + tags->count = 0; +} + +int ReadMP4Tag(MP4FileHandle file, medialib_tags *tags) +{ + unsigned __int32 valueSize; + unsigned __int8 *pValue; + char *pName; + unsigned int i = 0; + + do { + pName = 0; + pValue = 0; + valueSize = 0; + + MP4GetMetadataByIndex(file, i, (const char **)&pName, &pValue, &valueSize); + + if (valueSize > 0) + { + char *val = (char *)malloc(valueSize+1); + if (!val) return 0; + memcpy(val, pValue, valueSize); + val[valueSize] = '\0'; + + if (pName[0] == '\xa9') + { + if (memcmp(pName, "©nam", 4) == 0) + { + tag_add_field(tags, "title", val); + } else if (memcmp(pName, "©ART", 4) == 0) { + tag_add_field(tags, "artist", val); + } else if (memcmp(pName, "©wrt", 4) == 0) { + tag_add_field(tags, "writer", val); + } else if (memcmp(pName, "©alb", 4) == 0) { + tag_add_field(tags, "album", val); + } else if (memcmp(pName, "©day", 4) == 0) { + tag_add_field(tags, "date", val); + } else if (memcmp(pName, "©too", 4) == 0) { + tag_add_field(tags, "tool", val); + } else if (memcmp(pName, "©cmt", 4) == 0) { + tag_add_field(tags, "comment", val); + } else if (memcmp(pName, "©gen", 4) == 0) { + tag_add_field(tags, "genre", val); + } else { + tag_add_field(tags, pName, val); + } + } else if (memcmp(pName, "gnre", 4) == 0) { + char *t=0; + if (MP4GetMetadataGenre(file, &t)) + { + tag_add_field(tags, "genre", t); + } + } else if (memcmp(pName, "trkn", 4) == 0) { + unsigned __int16 trkn = 0, tot = 0; + char t[200]; + if (MP4GetMetadataTrack(file, &trkn, &tot)) + { + if (tot > 0) + wsprintf(t, "%d/%d", trkn, tot); + else + wsprintf(t, "%d", trkn); + tag_add_field(tags, "tracknumber", t); + } + } else if (memcmp(pName, "disk", 4) == 0) { + unsigned __int16 disk = 0, tot = 0; + char t[200]; + if (MP4GetMetadataDisk(file, &disk, &tot)) + { + if (tot > 0) + wsprintf(t, "%d/%d", disk, tot); + else + wsprintf(t, "%d", disk); + tag_add_field(tags, "disc", t); + } + } else if (memcmp(pName, "cpil", 4) == 0) { + unsigned __int8 cpil = 0; + char t[200]; + if (MP4GetMetadataCompilation(file, &cpil)) + { + wsprintf(t, "%d", cpil); + tag_add_field(tags, "compilation", t); + } + } else if (memcmp(pName, "tmpo", 4) == 0) { + unsigned __int16 tempo = 0; + char t[200]; + if (MP4GetMetadataTempo(file, &tempo)) + { + wsprintf(t, "%d BPM", tempo); + tag_add_field(tags, "tempo", t); + } + } else if (memcmp(pName, "NDFL", 4) == 0) { + /* Removed */ + } else { + tag_add_field(tags, pName, val); + } + + free(val); + } + + i++; + } while (valueSize > 0); + + return 1; +} + +int mp4_set_metadata(MP4FileHandle file, const char *item, const char *val) +{ + if (!item || (item && !*item) || !val || (val && !*val)) return 0; + + if (!stricmp(item, "track") || !stricmp(item, "tracknumber")) + { + unsigned __int16 trkn, tot; + int t1 = 0, t2 = 0; + sscanf(val, "%d/%d", &t1, &t2); + trkn = t1, tot = t2; + if (!trkn) return 1; + if (MP4SetMetadataTrack(file, trkn, tot)) return 1; + } + else if (!stricmp(item, "disc") || !stricmp(item, "disknumber")) + { + unsigned __int16 disk, tot; + int t1 = 0, t2 = 0; + sscanf(val, "%d/%d", &t1, &t2); + disk = t1, tot = t2; + if (!disk) return 1; + if (MP4SetMetadataDisk(file, disk, tot)) return 1; + } + else if (!stricmp(item, "compilation")) + { + unsigned __int8 cpil = atoi(val); + if (!cpil) return 1; + if (MP4SetMetadataCompilation(file, cpil)) return 1; + } + else if (!stricmp(item, "tempo")) + { + unsigned __int16 tempo = atoi(val); + if (!tempo) return 1; + if (MP4SetMetadataTempo(file, tempo)) return 1; + } + else if (!stricmp(item, "artist")) + { + if (MP4SetMetadataArtist(file, val)) return 1; + } + else if (!stricmp(item, "writer")) + { + if (MP4SetMetadataWriter(file, val)) return 1; + } + else if (!stricmp(item, "title")) + { + if (MP4SetMetadataName(file, val)) return 1; + } + else if (!stricmp(item, "album")) + { + if (MP4SetMetadataAlbum(file, val)) return 1; + } + else if (!stricmp(item, "date") || !stricmp(item, "year")) + { + if (MP4SetMetadataYear(file, val)) return 1; + } + else if (!stricmp(item, "comment")) + { + if (MP4SetMetadataComment(file, val)) return 1; + } + else if (!stricmp(item, "genre")) + { + if (MP4SetMetadataGenre(file, val)) return 1; + } + else if (!stricmp(item, "tool")) + { + if (MP4SetMetadataTool(file, val)) return 1; + } + else + { + if (MP4SetMetadataFreeForm(file, (char *)item, (u_int8_t *)val, (u_int32_t)strlen(val) + 1)) return 1; + } + + return 0; +} + +void WriteMP4Tag(MP4FileHandle file, const medialib_tags *tags) +{ + unsigned int i; + + for (i = 0; i < tags->count; i++) + { + const char *item = tags->tags[i].item; + const char *value = tags->tags[i].value; + + if (value && *value) + { + mp4_set_metadata(file, item, value); + } + } +} + +QCDModInitTag ModInitTag; + +medialib_tags tags; + +BOOL uSetDlgItemText(void *tagHandle, int fieldId, const char *str); +UINT uGetDlgItemText(void *tagHandle, int fieldId, char *str, int max); + +//------------------------------------------------------------------------------ + +PLUGIN_API QCDModInitTag* TAGEDITORDLL_ENTRY_POINT() +{ + ModInitTag.size = sizeof(QCDModInitTag); + ModInitTag.version = PLUGIN_API_VERSION; + ModInitTag.ShutDown = ShutDown_Tag; + + ModInitTag.Read = Read_Tag; + ModInitTag.Write = Write_Tag; // Leave null for operations that plugin does not support + ModInitTag.Strip = Strip_Tag; // ie: if plugin only reads tags, leave Write and Strip null + + ModInitTag.description = "MP4 Tags"; + ModInitTag.defaultexts = "MP4:M4A"; + + return &ModInitTag; +} + +//----------------------------------------------------------------------------- + +void ShutDown_Tag(int flags) +{ + // TODO: + // prepare plugin to be unloaded. All allocations should be freed. + // flags param is unused + tag_delete(&tags); +} + +//----------------------------------------------------------------------------- + +bool Read_Tag(LPCSTR filename, void* tagHandle) +{ + // TODO: + // read metadata from tag and set each field to tagHandle + // only TAGFIELD_* are supported (see QCDModTagEditor.h) + + // example of how to set value to tagHandle + // use SetFieldA for ASCII or MultiBytes strings. + // use SetFieldW for UNICODE strings + // + // ModInitTag.SetFieldW(tagHandle, TAGFIELD_COMPOSER, szwValue); + + // return true for successfull read, false for failure + + MP4FileHandle file = MP4_INVALID_FILE_HANDLE; + char *pVal, dummy1[1024]; + short dummy, dummy2; + u_int32_t valueSize = 0; + +#ifdef DEBUG_OUTPUT + in_mp4_DebugOutput("mp4_tag_read"); +#endif + + file = MP4Read(filename, 0); + + if (file == MP4_INVALID_FILE_HANDLE) + return false; + + /* get Metadata */ + + pVal = NULL; + MP4GetMetadataName(file, &pVal); + uSetDlgItemText(tagHandle, TAGFIELD_TITLE, pVal); + + pVal = NULL; + MP4GetMetadataArtist(file, &pVal); + uSetDlgItemText(tagHandle, TAGFIELD_ARTIST, pVal); + + pVal = NULL; + MP4GetMetadataWriter(file, &pVal); + uSetDlgItemText(tagHandle, TAGFIELD_COMPOSER, pVal); + + pVal = NULL; + MP4GetMetadataComment(file, &pVal); + uSetDlgItemText(tagHandle, TAGFIELD_COMMENT, pVal); + + pVal = NULL; + MP4GetMetadataAlbum(file, &pVal); + uSetDlgItemText(tagHandle, TAGFIELD_ALBUM, pVal); + + pVal = NULL; + MP4GetMetadataGenre(file, &pVal); + uSetDlgItemText(tagHandle, TAGFIELD_GENRE, pVal); + + //dummy = 0; + //MP4GetMetadataTempo(file, &dummy); + //if (dummy) + //{ + // wsprintf(dummy1, "%d", dummy); + // SetDlgItemText(hwndDlg,IDC_METATEMPO, dummy1); + //} + + dummy = 0; dummy2 = 0; + MP4GetMetadataTrack(file, (unsigned __int16*)&dummy, (unsigned __int16*)&dummy2); + if (dummy) + { + wsprintf(dummy1, "%d", dummy); + ModInitTag.SetFieldA(tagHandle, TAGFIELD_TRACK, dummy1); + } + //if (dumm2) + //{ + // wsprintf(dummy1, "%d", dummy2); + // SetDlgItemText(hwndDlg,IDC_METATRACK2, dummy1); + //} + + //dummy = 0; dummy2 = 0; + //MP4GetMetadataDisk(file, &dummy, &dummy2); + //if (dummy) + //{ + // wsprintf(dummy1, "%d", dummy); + // SetDlgItemText(hwndDlg,IDC_METADISK1, dummy1); + //} + //if (dummy) + //{ + // wsprintf(dummy1, "%d", dummy2); + // SetDlgItemText(hwndDlg,IDC_METADISK2, dummy1); + //} + + pVal = NULL; + if (MP4GetMetadataYear(file, &pVal)) + uSetDlgItemText(tagHandle, TAGFIELD_YEAR, pVal); + + //dummy3 = 0; + //MP4GetMetadataCompilation(file, &dummy3); + //if (dummy3) + // SendMessage(GetDlgItem(hwndDlg, IDC_METACOMPILATION), BM_SETCHECK, BST_CHECKED, 0); + + pVal = NULL; + MP4GetMetadataTool(file, &pVal); + uSetDlgItemText(tagHandle, TAGFIELD_ENCODER, pVal); + + pVal = NULL; + MP4GetMetadataFreeForm(file, "CONDUCTOR", (unsigned __int8**)&pVal, &valueSize); + uSetDlgItemText(tagHandle, TAGFIELD_CONDUCTOR, pVal); + + pVal = NULL; + MP4GetMetadataFreeForm(file, "ORCHESTRA", (unsigned __int8**)&pVal, &valueSize); + uSetDlgItemText(tagHandle, TAGFIELD_ORCHESTRA, pVal); + + pVal = NULL; + MP4GetMetadataFreeForm(file, "YEARCOMPOSED", (unsigned __int8**)&pVal, &valueSize); + uSetDlgItemText(tagHandle, TAGFIELD_YEARCOMPOSED, pVal); + + pVal = NULL; + MP4GetMetadataFreeForm(file, "ORIGARTIST", (unsigned __int8**)&pVal, &valueSize); + uSetDlgItemText(tagHandle, TAGFIELD_ORIGARTIST, pVal); + + pVal = NULL; + MP4GetMetadataFreeForm(file, "LABEL", (unsigned __int8**)&pVal, &valueSize); + uSetDlgItemText(tagHandle, TAGFIELD_LABEL, pVal); + + pVal = NULL; + MP4GetMetadataFreeForm(file, "COPYRIGHT", (unsigned __int8**)&pVal, &valueSize); + uSetDlgItemText(tagHandle, TAGFIELD_COPYRIGHT, pVal); + + pVal = NULL; + MP4GetMetadataFreeForm(file, "CDDBTAGID", (unsigned __int8**)&pVal, &valueSize); + uSetDlgItemText(tagHandle, TAGFIELD_CDDBTAGID, pVal); + + /* ! Metadata */ + + MP4Close(file); + + return true; +} + +//----------------------------------------------------------------------------- + +bool Write_Tag(LPCSTR filename, void* tagHandle) +{ + // TODO: + // read metadata from tagHandle and set each field to supported tag + // only TAGFIELD_* are supported (see QCDModTagEditor.h) + + // example of how to get value from tagHandle + // use SetFieldA for ASCII or MultiBytes strings. + // use SetFieldW for UNICODE strings + // + // szwValue = ModInitTag.GetFieldW(tagHandle, TAGFIELD_ORCHESTRA); + + // write tag to file + + MP4FileHandle file = MP4_INVALID_FILE_HANDLE; + char dummy1[1024]; + char temp[1024]; + short dummy, dummy2; + +#ifdef DEBUG_OUTPUT + in_mp4_DebugOutput("mp4_tag_write"); +#endif + + /* save Metadata changes */ + + tag_delete(&tags); + file = MP4Read(filename, 0); + if (file != MP4_INVALID_FILE_HANDLE) + { + ReadMP4Tag(file, &tags); + MP4Close(file); + + file = MP4Modify(filename, 0, 0); + if (file != MP4_INVALID_FILE_HANDLE) + { + MP4MetadataDelete(file); + MP4Close(file); + } + } + + file = MP4Modify(filename, 0, 0); + if (file == MP4_INVALID_FILE_HANDLE) + { + tag_delete(&tags); + //EndDialog(hwndDlg, wParam); + return false; + } + + uGetDlgItemText(tagHandle, TAGFIELD_TITLE, dummy1, 1024); + tag_set_field(&tags, "title", dummy1); + + uGetDlgItemText(tagHandle, TAGFIELD_COMPOSER, dummy1, 1024); + tag_set_field(&tags, "writer", dummy1); + + uGetDlgItemText(tagHandle, TAGFIELD_ARTIST, dummy1, 1024); + tag_set_field(&tags, "artist", dummy1); + + uGetDlgItemText(tagHandle, TAGFIELD_ALBUM, dummy1, 1024); + tag_set_field(&tags, "album", dummy1); + + uGetDlgItemText(tagHandle, TAGFIELD_COMMENT, dummy1, 1024); + tag_set_field(&tags, "comment", dummy1); + + uGetDlgItemText(tagHandle, TAGFIELD_GENRE, dummy1, 1024); + tag_set_field(&tags, "genre", dummy1); + + uGetDlgItemText(tagHandle, TAGFIELD_YEAR, dummy1, 1024); + tag_set_field(&tags, "year", dummy1); + + dummy = 0; + MP4GetMetadataTrack(file, (unsigned __int16*)&dummy, (unsigned __int16*)&dummy2); + memcpy(dummy1, ModInitTag.GetFieldA(tagHandle, TAGFIELD_TRACK), sizeof(dummy1)); + dummy = atoi(dummy1); + wsprintf(temp, "%d/%d", dummy, dummy2); + tag_set_field(&tags, "track", temp); + + //GetDlgItemText(hwndDlg, IDC_METADISK1, dummy1, 1024); + //dummy = atoi(dummy1); + //GetDlgItemText(hwndDlg, IDC_METADISK2, dummy1, 1024); + //dummy2 = atoi(dummy1); + //wsprintf(temp, "%d/%d", dummy, dummy2); + //tag_set_field(&tags, "disc", temp); + + //GetDlgItemText(hwndDlg, IDC_METATEMPO, dummy1, 1024); + //tag_set_field(&tags, "tempo", dummy1); + + //dummy3 = SendMessage(GetDlgItem(hwndDlg, IDC_METACOMPILATION), BM_GETCHECK, 0, 0); + //tag_set_field(&tags, "compilation", (dummy3 ? "1" : "0")); + + uGetDlgItemText(tagHandle, TAGFIELD_ENCODER, dummy1, 1024); + tag_set_field(&tags, "tool", dummy1); + + uGetDlgItemText(tagHandle, TAGFIELD_CONDUCTOR, dummy1, 1024); + tag_set_field(&tags, "CONDUCTOR", dummy1); + + uGetDlgItemText(tagHandle, TAGFIELD_ORCHESTRA, dummy1, 1024); + tag_set_field(&tags, "ORCHESTRA", dummy1); + + uGetDlgItemText(tagHandle, TAGFIELD_YEARCOMPOSED, dummy1, 1024); + tag_set_field(&tags, "YEARCOMPOSED", dummy1); + + uGetDlgItemText(tagHandle, TAGFIELD_ORIGARTIST, dummy1, 1024); + tag_set_field(&tags, "ORIGARTIST", dummy1); + + uGetDlgItemText(tagHandle, TAGFIELD_LABEL, dummy1, 1024); + tag_set_field(&tags, "LABEL", dummy1); + + uGetDlgItemText(tagHandle, TAGFIELD_COPYRIGHT, dummy1, 1024); + tag_set_field(&tags, "COPYRIGHT", dummy1); + + uGetDlgItemText(tagHandle, TAGFIELD_CDDBTAGID, dummy1, 1024); + tag_set_field(&tags, "CDDBTAGID", dummy1); + + WriteMP4Tag(file, &tags); + + MP4Close(file); + + MP4Optimize(filename, NULL, 0); + /* ! */ + + return true; +} + +//----------------------------------------------------------------------------- + +bool Strip_Tag(LPCSTR filename) +{ + // TODO: + // remove tag from file. + // do whatever is need to remove the supported tag from filename + + // return true for successfull strip, false for failure + + MP4FileHandle file; + + file = MP4Modify(filename, 0, 0); + if (file == MP4_INVALID_FILE_HANDLE) + return false; + + MP4MetadataDelete(file); + + MP4Close(file); + + return true; +} + +//----------------------------------------------------------------------------- + +/* Convert UNICODE to UTF-8 + Return number of bytes written */ +int unicodeToUtf8 ( const WCHAR* lpWideCharStr, char* lpMultiByteStr, int cwcChars ) +{ + const unsigned short* pwc = (unsigned short *)lpWideCharStr; + unsigned char* pmb = (unsigned char *)lpMultiByteStr; + const unsigned short* pwce; + size_t cBytes = 0; + + if ( cwcChars >= 0 ) { + pwce = pwc + cwcChars; + } else { + pwce = (unsigned short *)((size_t)-1); + } + + while ( pwc < pwce ) { + unsigned short wc = *pwc++; + + if ( wc < 0x00000080 ) { + *pmb++ = (char)wc; + cBytes++; + } else + if ( wc < 0x00000800 ) { + *pmb++ = (char)(0xC0 | ((wc >> 6) & 0x1F)); + cBytes++; + *pmb++ = (char)(0x80 | (wc & 0x3F)); + cBytes++; + } else + if ( wc < 0x00010000 ) { + *pmb++ = (char)(0xE0 | ((wc >> 12) & 0x0F)); + cBytes++; + *pmb++ = (char)(0x80 | ((wc >> 6) & 0x3F)); + cBytes++; + *pmb++ = (char)(0x80 | (wc & 0x3F)); + cBytes++; + } + if ( wc == L'\0' ) + return cBytes; + } + + return cBytes; +} + +/* Convert UTF-8 coded string to UNICODE + Return number of characters converted */ +int utf8ToUnicode ( const char* lpMultiByteStr, WCHAR* lpWideCharStr, int cmbChars ) +{ + const unsigned char* pmb = (unsigned char *)lpMultiByteStr; + unsigned short* pwc = (unsigned short *)lpWideCharStr; + const unsigned char* pmbe; + size_t cwChars = 0; + + if ( cmbChars >= 0 ) { + pmbe = pmb + cmbChars; + } else { + pmbe = (unsigned char *)((size_t)-1); + } + + while ( pmb < pmbe ) { + char mb = *pmb++; + unsigned int cc = 0; + unsigned int wc; + + while ( (cc < 7) && (mb & (1 << (7 - cc)))) { + cc++; + } + + if ( cc == 1 || cc > 6 ) // illegal character combination for UTF-8 + continue; + + if ( cc == 0 ) { + wc = mb; + } else { + wc = (mb & ((1 << (7 - cc)) - 1)) << ((cc - 1) * 6); + while ( --cc > 0 ) { + if ( pmb == pmbe ) // reached end of the buffer + return cwChars; + mb = *pmb++; + if ( ((mb >> 6) & 0x03) != 2 ) // not part of multibyte character + return cwChars; + wc |= (mb & 0x3F) << ((cc - 1) * 6); + } + } + + if ( wc & 0xFFFF0000 ) + wc = L'?'; + *pwc++ = wc; + cwChars++; + if ( wc == L'\0' ) + return cwChars; + } + + return cwChars; +} + +/* convert Windows ANSI to UTF-8 */ +int ConvertANSIToUTF8 ( const char* ansi, char* utf8 ) +{ + WCHAR* wszValue; // Unicode value + size_t ansi_len; + size_t len; + + *utf8 = '\0'; + if ( ansi == NULL ) + return 0; + + ansi_len = strlen ( ansi ); + + if ( (wszValue = (WCHAR *)malloc ( (ansi_len + 1) * 2 )) == NULL ) + return 0; + + /* Convert ANSI value to Unicode */ + if ( (len = MultiByteToWideChar ( CP_ACP, 0, ansi, ansi_len + 1, wszValue, (ansi_len + 1) * 2 )) == 0 ) { + free ( wszValue ); + return 0; + } + + /* Convert Unicode value to UTF-8 */ + if ( (len = unicodeToUtf8 ( wszValue, utf8, -1 )) == 0 ) { + free ( wszValue ); + return 0; + } + + free ( wszValue ); + + return len-1; +} + +/* convert UTF-8 to Windows ANSI */ +int ConvertUTF8ToANSI ( const char* utf8, char* ansi ) +{ + WCHAR* wszValue; // Unicode value + size_t utf8_len; + size_t len; + + *ansi = '\0'; + if ( utf8 == NULL ) + return 0; + + utf8_len = strlen ( utf8 ); + + if ( (wszValue = (WCHAR *)malloc ( (utf8_len + 1) * 2 )) == NULL ) + return 0; + + /* Convert UTF-8 value to Unicode */ + if ( (len = utf8ToUnicode ( utf8, wszValue, utf8_len + 1 )) == 0 ) { + free ( wszValue ); + return 0; + } + + /* Convert Unicode value to ANSI */ + if ( (len = WideCharToMultiByte ( CP_ACP, 0, wszValue, -1, ansi, (utf8_len + 1) * 2, NULL, NULL )) == 0 ) { + free ( wszValue ); + return 0; + } + + free ( wszValue ); + + return len-1; +} + +BOOL uSetDlgItemText(void *tagHandle, int fieldId, const char *str) +{ + char *temp; + size_t len; + int r; + + if (!str) return FALSE; + if (!*str) return FALSE; + len = strlen(str); + temp = (char *)malloc(len+1); + if (!temp) return FALSE; + memset(temp, '\0', len+1); + r = ConvertUTF8ToANSI(str, temp); + if (r > 0) + ModInitTag.SetFieldA(tagHandle, fieldId, temp); + free(temp); + + return r>0 ? TRUE : FALSE; +} + +UINT uGetDlgItemText(void *tagHandle, int fieldId, char *str, int max) +{ + char *temp, *utf8;; + int len; + + const char *p; + + if (!str || !max) return 0; + len = strlen( ModInitTag.GetFieldA(tagHandle, fieldId) ); + temp = (char *)malloc(len+1); + if (!temp) return 0; + utf8 = (char *)malloc((len+1)*4); + if (!utf8) + { + free(temp); + return 0; + } + + memset(temp, '\0', len+1); + memset(utf8, '\0', (len+1)*4); + memset(str, '\0', max); + p = ModInitTag.GetFieldA(tagHandle, fieldId); + memcpy(temp, p, len+1); + if (len > 0) + { + len = ConvertANSIToUTF8(temp, utf8); + if (len > max-1) + { + len = max-1; + utf8[max] = '\0'; + } + memcpy(str, utf8, len+1); + } + + free(temp); + free(utf8); + + return len; +} -- cgit v1.2.3