Unable to preserve newlines in RichEdit - c++

I'm having problems preserving newslines from a RichEdit control inside strings.
What I'm doing is:
Get text from RichEdit control
Split everything delimited by a space
Add some RTF formatting
"Fuse" words back together
Send text to control
I'm not sure what part causes this so here's the most relevant bits:
int RichEdit::GetTextLength() const
{
GETTEXTLENGTHEX len;
len.codepage = 1200;
len.flags = GTL_NUMBYTES;
return (int)SendMessage(this->handle, EM_GETTEXTLENGTHEX, (WPARAM)&len, 0) + 1;
}
tstring RichEdit::GetText() const
{
auto len = this->GetTextLength();
GETTEXTEX str;
TCHAR* tmp = new TCHAR[len];
str.cb = len;
str.flags = GT_USECRLF;
str.codepage = 1200;
str.lpDefaultChar = NULL;
str.lpUsedDefChar = NULL;
(void)SendMessage(this->handle, EM_GETTEXTEX, (WPARAM)&str, (LPARAM)tmp);
tstring ret(tmp);
delete[] tmp;
return ret;
}
void RichEdit::SetRtfText(const tstring& text, int flags)
{
DWORD WideLength = text.length();
DWORD Length = WideLength * 4;
PSTR Utf8 = (PSTR)malloc(Length);
int ReturnedLength = WideCharToMultiByte(CP_UTF8,
0,
text.c_str(),
WideLength-1,
Utf8,
Length-1,
NULL,
NULL);
if (ReturnedLength)
Utf8[ReturnedLength] = 0;
SETTEXTEX st = {0};
st.flags = flags;
st.codepage = CP_UTF8;
(void)SendMessage(this->handle, EM_SETTEXTEX, (WPARAM)&st, (LPARAM)Utf8 );
free(Utf8);
}
void split ( tstring input , tstring split_id, std::vector<std::pair<tstring,bool>>& res ) {
std::vector<std::pair<tstring,bool>> result;
int i = 0;
bool add;
tstring temp;
std::wstringstream ss;
size_t found;
tstring real;
int r = 0;
while ( i != input.length() )
{
add = false;
ss << input.at(i);
temp = ss.str();
found = temp.find(split_id);
if ( found != tstring::npos )
{
add = true;
real.append ( temp , 0 , found );
} else if ( r > 0 && ( i+1 ) == input.length() )
{
add = true;
real.append ( temp , 0 , found );
}
if ( add )
{
result.emplace_back(std::make_pair(real,false));
ss.str(tstring());
ss.clear();
temp.clear();
real.clear();
r = 0;
}
i++;
r++;
}
res = result;
}
ps: tstring is just a typedef for std::wstring/std::string
How can I preserve the newlines?

There are quite a few problems with your code.
Your code is TCHAR based, but you are not actually retrieving/setting the RTF data using TCHAR correctly.
When retreiving the text, you are normalizing line breaks to CRLF, but you are not doing that same normalizing when retreiving the text length, so they are going to be out of sync with each other.
You are writing data to the RichEdit using UTF-8, but RTF is an ASCII-based format that uses escape sequences for Unicode data. If you are going to retrieve data as Unicode, you may as well write it using Unicode as well, and make sure you are doing all of that correctly to begin with. Let the RichEdit control handle the Unicode for you.
Your use of WideCharToMultiByte() is wrong. You should not be subtracting -1 from the string lengths at all. You are likely trying to account for null terminators, but the length values do not include null terminators to begin with. If you are going to stick with UTF-8 then you should be using WideCharToMultiByte() to calculate the correct UTF-8 length instead of hard-coding it.
int Length = WideCharToMultiByte(CP_UTF8, 0, text.c_str(), text.length(), NULL, 0, NULL, NULL);
char Utf8 = new char[Length+1];
WideCharToMultiByte(CP_UTF8, 0, text.c_str(), text.length(), Utf8, Length, NULL, NULL);
Utf8[Length] = 0;
...
delete[] Utf8;
With that said, if you are going to stick with TCHAR then try this:
#ifdef UNICODE
#define RTFCodePage 1200
#else
#define RTFCodePage CP_ACP
#endif
int RichEdit::GetTextLength() const
{
GETTEXTLENGTHEX len = {0};
len.codepage = RTFCodePage;
len.flags = GTL_NUMCHARS | GTL_USECRLF;
return SendMessage(this->handle, EM_GETTEXTLENGTHEX, (WPARAM)&len, 0);
}
tstring RichEdit::GetText() const
{
int len = this->GetTextLength() + 1;
GETTEXTEX str = {0};
str.cb = len * sizeof(TCHAR);
str.flags = GT_USECRLF;
str.codepage = RTFCodePage;
vector<TCHAR> tmp(len);
len = SendMessage(this->handle, EM_GETTEXTEX, (WPARAM)&str, (LPARAM)&tmp[0]);
return tstring(&tmp[0], len-1);
}
void RichEdit::SetRtfText(const tstring& text, int flags)
{
SETTEXTEX st = {0};
st.flags = flags;
st.codepage = RTFCodePage;
#ifdef UNICODE
st.flags |= ST_UNICODE;
#endif
SendMessage(this->handle, EM_SETTEXTEX, (WPARAM)&st, (LPARAM)text.c_str());
}
It would be better to drop TCHAR and just use Unicode for everything:
int RichEdit::GetTextLength() const
{
GETTEXTLENGTHEX len = {0};
len.codepage = 1200;
len.flags = GTL_NUMCHARS | GTL_USECRLF;
return SendMessage(this->handle, EM_GETTEXTLENGTHEX, (WPARAM)&len, 0);
}
wstring RichEdit::GetText() const
{
int len = this->GetTextLength() + 1;
GETTEXTEX str = {0};
str.cb = len * sizeof(WCHAR);
str.flags = GT_USECRLF;
str.codepage = 1200;
vector<WCHAR> tmp(len);
len = SendMessage(this->handle, EM_GETTEXTEX, (WPARAM)&str, (LPARAM)&tmp[0]);
return wstring(tmp, len-1);
}
void RichEdit::SetRtfText(const wstring& text, int flags)
{
SETTEXTEX st = {0};
st.flags = flags | ST_UNICODE;
st.codepage = 1200;
SendMessage(this->handle, EM_SETTEXTEX, (WPARAM)&st, (LPARAM)text.c_str());
}
Update: if you have to go back to UTF-8 for the EM_SETTEXTEX message then try this:
void RichEdit::SetRtfText(const tstring& text, int flags)
{
string Utf8;
int Length;
#ifdef UNICODE
Length = WideCharToMultiByte(CP_UTF8, 0, text.c_str(), text.length(), NULL, 0, NULL, NULL);
if (Length > 0)
{
Utf8.resize(Length);
WideCharToMultiByte(CP_UTF8, 0, text.c_str(), text.length(), &Utf8[0], Length, NULL, NULL);
}
#else
Length = MultiByteToWideChar(CP_ACP, 0, text.c_str(), text.length(), NULL, 0);
if (Length > 0)
{
vector<WCHAR> tmp(Length);
MultiByteToWideChar(CP_ACP, 0, text.c_str(), text.length(), &tmp[0], Length);
Length = WideCharToMultiByte(CP_UTF8, 0, tmp.c_str(), tmp.length(), NULL, 0, NULL, NULL);
if (Length > 0)
{
Utf8.resize(Length);
WideCharToMultiByte(CP_UTF8, 0, tmp.c_str(), tmp.length(), &Utf8[0], Length, NULL, NULL);
}
}
#endif
SETTEXTEX st = {0};
st.flags = flags & ~ST_UNICODE;
st.codepage = CP_UTF8;
SendMessage(this->handle, EM_SETTEXTEX, (WPARAM)&st, (LPARAM)Utf8.c_str());
}

Related

How do I resolve vccorlib_lib_should_be_specified_before_msvcrt_lib_to_linker mismatch in the C++WinRT project using Boost.Locale & Boost.Predef?

I'm working on a C++/WinRT project and would like to use Boost (1.73.0) Locale in it. Inspired by a Microsoft blog post I have replaced calls to unsupported WinApi functions in the library sources and compiled with windows-api=store. I managed to build all intended library variants (arm / x64, debug / release) and went on to build the UWP app. That is the point where I am stuck right now. The build fails to link with the following output:
vccorlibd.lib(init.obj) : error LNK2038: mismatch detected for 'vccorlib_lib_should_be_specified_before_msvcrt_lib_to_linker': value '1' doesn't match value '0' in MSVCRTD.lib(app_appinit.obj)
vccorlibd.lib(init.obj) : error LNK2005: __crtWinrtInitType already
defined in MSVCRTD.lib(app_appinit.obj)
The line triggering the failure:
const auto text = boost::locale::conv::to_utf<char>("xxx", "yyy");
My setup is Visual Studio 17 & 19, SDK 10.0.19041.0. I have tried this solution proposed to a similar question but to no avail. The modifications I made in the boost_1_73_0/libs/locale/src/win32 directory follow:
api.h
// detecting UWP
#include <boost/predef.h>
// ...
class winlocale{
public:
winlocale() :
lcid(0)
{
}
winlocale(std::string const name)
{
#if BOOST_PLAT_WINDOWS_RUNTIME
str.assign(cbegin(name), cend(name));
#endif
lcid = locale_to_lcid(name);
}
#if BOOST_PLAT_WINDOWS_RUNTIME
std::wstring str;
#endif
unsigned lcid;
bool is_c() const
{
return lcid == 0;
}
};
// ...
inline std::wstring win_map_string_l(unsigned flags,wchar_t const *begin,wchar_t const *end,winlocale const &l)
{
std::wstring res;
#if BOOST_PLAT_WINDOWS_RUNTIME
int len = LCMapStringEx(l.str.c_str(), flags, begin, end - begin, 0, 0,
/* >=win_vista must set to null*/ 0,
/*Reserved; must be NULL.*/ 0,
/*Reserved; must be 0.*/ 0);
if (len == 0)
return res;
std::vector<wchar_t> buf(len + 1);
int l2 = LCMapStringEx(l.str.c_str(), flags, begin, end - begin, &buf.front(), buf.size(),
/* >=win_vista must set to null*/ 0,
/*Reserved; must be NULL.*/ 0,
/*Reserved; must be 0.*/ 0);
res.assign(&buf.front(), l2);
#else
int len = LCMapStringW(l.lcid,flags,begin,end-begin,0,0);
if(len == 0)
return res;
std::vector<wchar_t> buf(len+1);
int l2 = LCMapStringW(l.lcid,flags,begin,end-begin,&buf.front(),buf.size());
res.assign(&buf.front(),l2);
#endif
return res;
}
// …
inline std::wstring wcsfmon_l(double value,winlocale const &l)
{
std::wostringstream ss;
ss.imbue(std::locale::classic());
ss << std::setprecision(std::numeric_limits<double>::digits10+1) << value;
std::wstring sval = ss.str();
#if BOOST_PLAT_WINDOWS_RUNTIME
int len = GetCurrencyFormatEx(l.str.c_str(), 0, sval.c_str(), 0, 0, 0);
std::vector<wchar_t> buf(len + 1);
GetCurrencyFormatEx(l.str.c_str(), 0, sval.c_str(), 0, &buf.front(), len);
#else
int len = GetCurrencyFormatW(l.lcid,0,sval.c_str(),0,0,0);
std::vector<wchar_t> buf(len+1);
GetCurrencyFormatW(l.lcid,0,sval.c_str(),0,&buf.front(),len);
#endif
return &buf.front();
}
inline std::wstring wcs_format_date_l(wchar_t const *format,SYSTEMTIME const *tm,winlocale const &l)
{
#if BOOST_PLAT_WINDOWS_RUNTIME
int len = GetDateFormatEx(l.str.c_str(), 0, tm, format, 0, 0,
/*Reserved; must set to NULL.*/ 0);
std::vector<wchar_t> buf(len + 1);
GetDateFormatEx(l.str.c_str(), 0, tm, format, &buf.front(), len,
/*Reserved; must set to NULL.*/ 0);
#else
int len = GetDateFormatW(l.lcid,0,tm,format,0,0);
std::vector<wchar_t> buf(len+1);
GetDateFormatW(l.lcid,0,tm,format,&buf.front(),len);
#endif
return &buf.front();
}
inline std::wstring wcs_format_time_l(wchar_t const *format,SYSTEMTIME const *tm,winlocale const &l)
{
#if BOOST_PLAT_WINDOWS_RUNTIME
int len = GetTimeFormatEx(l.str.c_str(), 0, tm, format, 0, 0);
std::vector<wchar_t> buf(len + 1);
GetTimeFormatEx(l.str.c_str(), 0, tm, format, &buf.front(), len);
#else
int len = GetTimeFormatW(l.lcid, 0, tm, format, 0, 0);
std::vector<wchar_t> buf(len + 1);
GetTimeFormatW(l.lcid, 0, tm, format, &buf.front(), len);
#endif
return &buf.front();
}
lcid.cpp
BOOL CALLBACK procEx(LPWSTR s, DWORD, LPARAM)
{
table_type& tbl = real_lcid_table();
try {
std::wistringstream ss;
ss.str(s);
ss >> std::hex;
unsigned lcid;
ss >> lcid; // <----- not sure about this line, but anyway...
if (ss.fail() || !ss.eof()) {
return FALSE;
}
char iso_639_lang[16];
char iso_3166_country[16];
if (GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, iso_639_lang, sizeof(iso_639_lang)) == 0)
return FALSE;
std::string lc_name = iso_639_lang;
if (GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, iso_3166_country, sizeof(iso_3166_country)) != 0) {
lc_name += "_";
lc_name += iso_3166_country;
}
table_type::iterator p = tbl.find(lc_name);
if (p != tbl.end()) {
if (p->second > lcid)
p->second = lcid;
}
else {
tbl[lc_name] = lcid;
}
}
catch (...) {
tbl.clear();
return FALSE;
}
return TRUE;
}
table_type const &get_ready_lcid_table()
{
if(table)
return *table;
else {
boost::unique_lock<boost::mutex> lock(lcid_table_mutex());
if(table)
return *table;
#if BOOST_PLAT_WINDOWS_RUNTIME
EnumSystemLocalesEx(procEx, LCID_INSTALLED,
/*callback arg*/ 0, /*reserved*/ 0);
#else
EnumSystemLocalesA(proc, LCID_INSTALLED);
#endif
table = &real_lcid_table();
return *table;
}
}
UPDATE
I found out, that the problem is actually caused by inclusion of <boost/predef.h> in the api.h, which I use to define the BOOST_PLAT_WINDOWS_RUNTIME macro when appropriate. I still don't know how to handle this situation however. Can anybody point me somewhere? Thank you.

Why this code runs perfectly in visual studio with multibyte characher set but not with unicode char set?

when I run this code on g++ , it runs smoothly, but when I run this code on visual studio wiith unicode char set option, it doesn't print product id.
can you explain me how to fix this problem and why it happens?
#include <windows.h>
#include <stdio.h>
#include <iostream>
using namespace std;
wchar_t* GetRegistryKeyValue(const char* RegKey, const char* pPIDName)
{
HKEY Registry;
long ReturnStatus;
DWORD regType = 0;
DWORD regSize = 0;
char* pPID = 0;
ReturnStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, RegKey, 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &Registry);
if (ReturnStatus == ERROR_SUCCESS)
{
ReturnStatus = RegQueryValueEx(Registry, pPIDName, 0, &regType, 0, &regSize);
pPID = new char[regSize];
/* Get Value. */
ReturnStatus = RegQueryValueEx(Registry, pPIDName, 0, &regType, (LPBYTE)pPID, &regSize);
RegCloseKey(Registry);
if (pPID[regSize] > 127 || pPID[regSize] < 32)
{
pPID[regSize] = '\0';
}
if (regSize > 1)
{
int s = 0;
int i=0;
while (pPID[i] != NULL)
{
s++;
i++;
}
const size_t cSize = s ;
wchar_t* wc = new wchar_t[cSize];
mbstowcs(wc, pPID, cSize);
return wc;
}
else
{
printf("Size not > 1 (%d)\n", regSize);
return NULL;
}
}
else
{
RegCloseKey(Registry);
return NULL;
}
}
int main()
{
wchar_t * resultData=NULL;
resultData = GetRegistryKeyValue("SOFTWARE\\MICROSOFT\\Windows NT\\CurrentVersion", "ProductId");
wcout << resultData;
cout << endl;
delete resultData;
system("PAUSE");
return 0;
}
You are using TCHAR-based APIs that rely on char* data when compiling for MBCS and wchar_t* data when compiling for Unicode. You are not taking that difference into account correctly. Your code should not even compile when set for Unicode, because you would be passing ANSI parameters to Unicode functions. Since you want to return a Unicode string, you should be using the Unicode API functions to begin with.
There are other logic errors in your code, such as leaking memory, not allocating the right number of bytes for the wc buffer, insufficient error handling, etc.
Try something more like this instead:
#include <windows.h>
#include <stdio.h>
#include <iostream>
using namespace std;
wchar_t* GetRegistryKeyValue(const wchar_t* RegKey, const wchar_t* pValueName)
{
long ReturnStatus;
DWORD regType = 0;
DWORD regSize = 0;
DWORD dwFlags = RRF_RT_REG_SZ | RRF_RT_REG_MULTI_SZ | RRF_RT_REG_EXPAND_SZ | RRF_SUBKEY_WOW6464KEY;
wchar_t* ws = 0;
ReturnStatus = RegGetValueW(HKEY_LOCAL_MACHINE, RegKey, pValueName, dwFlags, &regType, 0, &regSize);
if (ReturnStatus == ERROR_SUCCESS)
{
ws = new wchar_t[regSize / sizeof(WCHAR)];
ReturnStatus = RegGetValueW(HKEY_LOCAL_MACHINE, RegKey, pValueName, dwFlags, &regType, ws, &regSize);
if (ReturnStatus != ERROR_SUCCESS)
{
delete[] ws;
ws = NULL;
}
}
return ws;
}
int main()
{
wchar_t* resultData = GetRegistryKeyValue(L"SOFTWARE\\MICROSOFT\\Windows NT\\CurrentVersion", L"ProductId");
wcout << resultData << endl;
delete[] resultData;
system("PAUSE");
return 0;
}
Alternatively:
#include <windows.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
wstring GetRegistryKeyValue(const wchar_t* RegKey, const wchar_t* pValueName)
{
long ReturnStatus;
DWORD regType = 0;
DWORD regSize = 0;
DWORD dwFlags = RRF_RT_REG_SZ | RRF_RT_REG_MULTI_SZ | RRF_RT_REG_EXPAND_SZ | RRF_SUBKEY_WOW6464KEY;
ReturnStatus = RegGetValueW(HKEY_LOCAL_MACHINE, RegKey, pValueName, dwFlags, &regType, 0, &regSize);
if (ReturnStatus == ERROR_SUCCESS)
{
vector<BYTE> buf;
buf.resize(regSize);
ReturnStatus = RegGetValueW(HKEY_LOCAL_MACHINE, RegKey, pValueName, dwFlags, &regType, &buf[0], &regSize);
if (ReturnStatus == ERROR_SUCCESS)
return wstring((wchar_t*)&buf[0], (regSize / sizeof(WCHAR)) - 1);
}
return wstring();
}
int main()
{
wcout << GetRegistryKeyValue(L"SOFTWARE\\MICROSOFT\\Windows NT\\CurrentVersion", L"ProductId") << endl;
system("PAUSE");
return 0;
}
According to this documentation:
http://www.cplusplus.com/reference/cstdlib/mbstowcs/
If max characters are successfully translated, the resulting string stored in dest is not null-terminated.
The tricky way you're trying to calculate string length (which, btw, could be replaced by strlen(pPID) ) will skip the '\0' in the first string and thus the result might not have '\0' on the end. Why don't you use regSize there?

wcscpy_s not affecting wchar_t*

I'm trying to load some strings from a database into a struct, but I keep running into an odd issue. Using my struct datum,
struct datum {
wchar_t* name;
wchar_t* lore;
};
I tried the following code snippet
datum thisDatum;
size_t len = 0;
wchar_t wBuffer[2048];
mbstowcs_s(&len, wBuffer, (const char*)sqlite3_column_text(pStmt, 1), 2048);
if (len) {
thisDatum.name = new wchar_t[len + 1];
wcscpy_s(thisDatum.name, len + 1, wBuffer);
} else thisDatum.name = 0;
mbstowcs_s(&len, wBuffer, (const char*)sqlite3_column_text(pStmt, 2), 2048);
if (len) {
thisDatum.lore = new wchar_t[len + 1];
wcscpy_s(thisDatum.lore, len + 1, wBuffer);
} else thisDatum.name = 0;
However, while thisDatum.name copies correctly, thisDatum.lore is always garbage, except on two occassions. If the project is Debug, everything is fine, but that just isn't an option. I also discovered that rewriting the struct datum
struct datum {
wchar_t* lore;
wchar_t* name;
};
completely fixes the issue for thisDatum.lore, but gives me garbage for thisDatum.name.
Try something more like this:
struct datum {
wchar_t* name;
wchar_t* lore;
};
wchar_t* widen(const char *str)
{
wchar_t *wBuffer = NULL;
size_t len = strlen(str) + 1;
size_t wlen = 0;
mbstowcs_s(&wlen, NULL, 0, str, len);
if (wlen)
{
wBuffer = new wchar_t[wlen];
mbstowcs_s(NULL, wBuffer, wlen, str, len);
}
return wBuffer;
}
datum thisDatum;
thisDatum.name = widen((const char*)sqlite3_column_text(pStmt, 1));
thisDatum.lore = widen((const char*)sqlite3_column_text(pStmt, 2));
...
delete[] thisDatum.name;
delete[] thisDatum.lore;
That being said, I would use std::wstring instead:
struct datum {
std::wstring name;
std::wstring lore;
};
#include <locale>
#include <codecvt>
std::wstring widen(const char *str)
{
std::wstring_convert< std::codecvt<wchar_t, char, std::mbstate_t> > conv;
return conv.from_bytes(str);
}
datum thisDatum;
thisDatum.name = widen((const char*)sqlite3_column_text(pStmt, 1));
thisDatum.lore = widen((const char*)sqlite3_column_text(pStmt, 2));

application crashes at first strcat_s

I have tried both strcat and strcat_s, but they both crash. Does anyone know why this happens? I can't find the problem.
Crash: "Unhandled exception at 0x58636D2A (msvcr110d.dll)"
_Dst 0x00ea6b30 "C:\\Users\\Ruben\\Documents\\School\\" char *
_SizeInBytes 260 unsigned int
_Src 0x0032ef64 "CKV" const char *
available 228 unsigned int
p 0x00ea6b50 "" char *
Code:
#include <Windows.h>
#include <strsafe.h>
extern "C"
{
char* GetFilesInFolders(LPCWSTR filedir, char* path)
{
char* files = "";
char DefChar = ' ';
char* Streepje = "-";
bool LastPoint = false;
WIN32_FIND_DATA ffd;
TCHAR szDir[MAX_PATH];
HANDLE hFind = INVALID_HANDLE_VALUE;
DWORD dwError = 0;
StringCchCopy(szDir, MAX_PATH, filedir);
hFind = FindFirstFile(szDir, &ffd);
if (INVALID_HANDLE_VALUE == hFind)
return "";
do
{
DWORD attributes = ffd.dwFileAttributes;
LPCWSTR nm = ffd.cFileName;
char name[260];
WideCharToMultiByte(CP_ACP,0,ffd.cFileName,-1, name,260,&DefChar, NULL);
for (int i = 0; i <= 260; i++)
{
if (name[i] == '.')
LastPoint = true;
else if (name[i] == ' ')
break;
}
if (LastPoint == true)
{
LastPoint = false;
continue;
}
if (attributes & FILE_ATTRIBUTE_HIDDEN)
{
continue;
}
else if (attributes & FILE_ATTRIBUTE_DIRECTORY)
{
char* newfiledir = "";
char* newpath = path;
char* add = "\\";
char* extra = "*";
strcat_s(newpath, sizeof(name), name);
strcat_s(newpath, sizeof(add), add);
puts(newpath);
strcpy_s(newfiledir, sizeof(newpath) + 1, newpath);
strcat_s(newfiledir, sizeof(extra) + 1, extra);
puts(newfiledir);
size_t origsize = strlen(newfiledir) + 1;
const size_t newsize = 100;
size_t convertedChars = 0;
wchar_t wcstring[newsize];
mbstowcs_s(&convertedChars, wcstring, origsize, newfiledir, _TRUNCATE);
LPCWSTR dir = wcstring;
GetFilesInFolders(dir, newpath);
}
else
{
char* file = path;
strcat_s(file, sizeof(name), name);
puts(file);
strcat_s(files, sizeof(file), file);
strcat_s(files, sizeof(Streepje), Streepje);
puts(files);
}
}
while (FindNextFile(hFind, &ffd) != 0);
FindClose(hFind);
return files;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
char* path = "C:\\Users\\Ruben\\Documents\\School\\";
char* filedir = "C:\\Users\\Ruben\\Documents\\School\\*";
size_t origsize = strlen(filedir) + 1;
const size_t newsize = 100;
size_t convertedChars = 0;
wchar_t wcstring[newsize];
mbstowcs_s(&convertedChars, wcstring, origsize, filedir, _TRUNCATE);
LPCWSTR dir = wcstring;
char* files = GetFilesInFolders(dir, path);
return 0;
}
Extra info: I don't want to use boost or strings and I want to keep this in unicode (default).
You assign a const char* to files, then attempt to append to it.
char* files = "";
// ...
strcat_s(files, sizeof(file), file);
You cannot modify a constant string literal.
I would recommend that you turn on compiler warnings and make sure to look at them. This would warn you about assigning a const char* to a char*. To fix it, you might have changed files to be const, which would then cause your strcpy_s to no longer compile.
It looks like you don't understand how variables are stored in memory or how pointers work. In your _tmain() you have char * path pointing to a constant string literal, which you pass into GetFilesInFolders(), where it gets modified. Compilers tend to allow char *s to point at constant strings for backward compatibility with old C programs. You cannot modify these. You cannot append to them. The compiler (generally) puts these in a read-only segment. That's one reason why you're getting an exception.
Your whole GetFilesInFolders() is wrong. And as DarkFalcon pointed out, you haven't allocated any space anywhere for files, you have it pointing to a constant string literal.
Get "The C++ Programming Language" and read chapter 5.

why UChar* is not working with this ICU conversion?

When converting from UTF-8 to ISO-8859-6 this code didn't work:
UnicodeString ustr = UnicodeString::fromUTF8(StringPiece(input));
const UChar* source = ustr.getBuffer();
char target[1000];
UErrorCode status = U_ZERO_ERROR;
UConverter *conv;
int32_t len;
// set up the converter
conv = ucnv_open("iso-8859-6", &status);
assert(U_SUCCESS(status));
// convert
len = ucnv_fromUChars(conv, target, 100, source, -1, &status);
assert(U_SUCCESS(status));
// close the converter
ucnv_close(conv);
string s(target);
return s;
images: (1,2)
However when replacing UChar* with a hard-coded UChar[] it works well!!
image : (3)
It looks like you're taking the difficult approach. How about this:
static char const* const cp = "iso-8859-6";
UnicodeString ustr = UnicodeString::fromUTF8(StringPiece(input));
std::vector<char> buf(ustr.length() + 1);
std::vector<char>::size_type len = ustr.extract(0, ustr.length(), &buf[0], buf.size(), cp);
if (len >= buf.size())
{
buf.resize(len + 1);
len = ustr.extract(0, ustr.length(), &buf[0], buf.size(), cp);
}
std::string ret;
if (len)
ret.assign(buf.begin(), buf.begin() + len));
return ret;