/**********************************************************************
 *                       TABCleanFieldName()
 *
 * Return a copy of pszSrcName that contains only valid characters for a
 * TAB field name.  All invalid characters are replaced by '_'.
 *
 * The returned string should be freed by the caller.
 **********************************************************************/
char *TABCleanFieldName(const char *pszSrcName)
{
    char *pszNewName;
    int numInvalidChars = 0;

    pszNewName = CPLStrdup(pszSrcName);

    if (strlen(pszNewName) > 31)
    {
        pszNewName[31] = '\0';
        CPLError(CE_Warning, TAB_WarningInvalidFieldName,
                 "Field name '%s' is longer than the max of 31 characters. "
                 "'%s' will be used instead.", pszSrcName, pszNewName);
    }

#if defined(_WIN32) && !defined(unix) && !defined(WIN32CE)
    /*-----------------------------------------------------------------
     * On Windows, check if we're using a double-byte codepage, and
     * if so then just keep the field name as is... 
     *----------------------------------------------------------------*/
    if (_getmbcp() != 0)
        return pszNewName;
#endif

    /*-----------------------------------------------------------------
     * According to the MapInfo User's Guide (p. 240, v5.5)
     * New Table Command:
     *  Name:
     * Displays the field name in the name box. You can also enter new field
     * names here. Defaults are Field1, Field2, etc. A field name can contain
     * up to 31 alphanumeric characters. Use letters, numbers, and the 
     * underscore. Do not use spaces; instead, use the underscore character
     * (_) to separate words in a field name. Use upper and lower case for
     * legibility, but MapInfo is not case-sensitive.
     *
     * It was also verified that extended chars with accents are also 
     * accepted.
     *----------------------------------------------------------------*/
    for(int i=0; pszSrcName && pszSrcName[i] != '\0'; i++)
    {
        if ( !( pszSrcName[i] == '_' ||
                (pszSrcName[i]>='0' && pszSrcName[i]<='9') || 
                (pszSrcName[i]>='a' && pszSrcName[i]<='z') || 
                (pszSrcName[i]>='A' && pszSrcName[i]<='Z') ||
                (GByte)pszSrcName[i]>=192 ) )
        {
            pszNewName[i] = '_';
            numInvalidChars++;
        }
    }

    if (numInvalidChars > 0)
    {
        CPLError(CE_Warning, TAB_WarningInvalidFieldName,
                 "Field name '%s' contains invalid characters. "
                 "'%s' will be used instead.", pszSrcName, pszNewName);
    }

    return pszNewName;
}
Beispiel #2
0
//=================================================================================
//	Narrow2Wide()
//=================================================================================
wstring PictureHandler::Narrow2Wide(const std::string& narrowString)
{
	int m_codepage = _getmbcp();

	int numChars =
	::MultiByteToWideChar( m_codepage, 
						   MB_PRECOMPOSED, 
						   narrowString.c_str(), 
						   -1, 
						   0, 
						   0
						  );
	_ASSERT(numChars);
//	TRACE("Number of characters in the string is %d", numChars);

	wchar_t* test = new wchar_t[numChars+1];
	numChars =
	::MultiByteToWideChar( m_codepage, 
						   MB_PRECOMPOSED, 
						   narrowString.c_str(), 
						   -1, 
						   test, 
						   numChars
						  );

	std::wstring temp(test);
	delete []test;

	return temp;
}
Beispiel #3
0
static void test_splitpath(void)
{
    const char* path = "c:\\\x83\x5c\x83\x74\x83\x67.bin";
    char drive[3], dir[MAX_PATH], fname[MAX_PATH], ext[MAX_PATH];
    int prev_cp = _getmbcp();

    /* SBCS codepage */
    _setmbcp(1252);
    _splitpath(path, drive, dir, fname, ext);
    ok(!strcmp(drive, "c:"), "got %s\n", drive);
    ok(!strcmp(dir, "\\\x83\x5c"), "got %s\n", dir);
    ok(!strcmp(fname, "\x83\x74\x83\x67"), "got %s\n", fname);
    ok(!strcmp(ext, ".bin"), "got %s\n", ext);

    /* MBCS (Japanese) codepage */
    _setmbcp(932);
    _splitpath(path, drive, dir, fname, ext);
    ok(!strcmp(drive, "c:"), "got %s\n", drive);
    ok(!strcmp(dir, "\\"), "got %s\n", dir);
    ok(!strcmp(fname, "\x83\x5c\x83\x74\x83\x67"), "got %s\n", fname);
    ok(!strcmp(ext, ".bin"), "got %s\n", ext);

    _setmbcp(prev_cp);
}
Beispiel #4
0
UINT FileListFromDirectory(FILELIST **filelist,char *directory,BOOL *UserCancel)
{
	HANDLE hFindFile;
	WIN32_FIND_DATAW FindFileDataW;
	WIN32_FIND_DATAA FindFileDataA;
	BOOL RetVal=FALSE;
	BOOL KeepGoing;
	char *search;
	char *filename;
	char *name;
	LPWSTR wide;
	int widelen;
	int namelen;
	int retval;
	BOOL IsNT=FALSE;
	DWORD dwFileAttributes;
	OSVERSIONINFO osid;

	memset(&osid,0x00,sizeof(OSVERSIONINFO));

	osid.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
	GetVersionEx (&osid);   
	IsNT=(osid.dwPlatformId == VER_PLATFORM_WIN32_NT);

	if(directory[strlen(directory)-1]!='\\')
		strcat(directory,"\\");

	if(IsNT)
	{
		search=(char *)malloc(strlen("\\\\?\\")+strlen(directory)+strlen("*.*")+1);

		if(search==NULL)
			return TRUE;

		strcpy(search,"\\\\?\\");
		strcat(search,directory);
		strcat(search,"*.*");

		widelen=MultiByteToWideChar(_getmbcp(), 0, search, -1, 0,0);

		wide=(LPWSTR)malloc(widelen*sizeof(WCHAR));
		memset(wide,0x00,widelen*sizeof(WCHAR));

		retval=MultiByteToWideChar(_getmbcp(), 0, search,
			-1, wide,widelen);

		hFindFile=FindFirstFileW(wide,&FindFileDataW);
	
		free(wide);
		memset(search,0x00,sizeof(search));
		free(search);
	}
	else	
	{
		int bufsize;
		char shrtpath[MAX_PATH+1];

		bufsize=strlen(directory)+strlen("*.*")+1;

		GetShortPathName(directory,shrtpath,MAX_PATH);

		strcat(shrtpath,"*.*");

		hFindFile=FindFirstFileA(shrtpath,&FindFileDataA);

		memset(shrtpath,0x00,MAX_PATH);
	}

	if(hFindFile!=INVALID_HANDLE_VALUE)
	{
		RetVal=TRUE;

		while(RetVal==TRUE)
		{
			// Our quick fix callback to allow user to back out
			// of operation
			if(UserCancel!=NULL)
			{
				if(*UserCancel)
				{
					FindClose(hFindFile);
					return FALSE;
				}
			}

			if(IsNT)
			{
				namelen=WideCharToMultiByte(_getmbcp(), 0, FindFileDataW.cFileName,
					-1, 0,0,NULL,NULL);
				namelen++; // If we need to add directory slash

				name=(char *)malloc(namelen);
				memset(name,0x00,namelen);

				WideCharToMultiByte(_getmbcp(), 0, FindFileDataW.cFileName,
					-1, name,namelen,NULL,NULL);

				filename=(char *)malloc(strlen(directory)+namelen+1);

				strcpy(filename,directory);
				strcat(filename,name);

				dwFileAttributes=FindFileDataW.dwFileAttributes;
			}
			else
			{
				namelen=strlen(FindFileDataA.cFileName);
				namelen++;

				name=(char *)malloc(namelen);
				strcpy(name,FindFileDataA.cFileName);

				filename=(char *)malloc(strlen(directory)+namelen+1);
				strcpy(filename,directory);
				strcat(filename,name);

				dwFileAttributes=FindFileDataA.dwFileAttributes;
			}
	
			if((dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
				!=FILE_ATTRIBUTE_DIRECTORY)
			{
				FileListFromFile(filelist,filename,UserCancel);
			}
			else
			{
				if((strcmp(name,"."))&&
					(strcmp(name,"..")))
				{
					KeepGoing=FileListFromFile(filelist,filename,UserCancel);
					if(!KeepGoing)
					{
						FindClose(hFindFile);
						return FALSE;
					}

					(*filelist)->IsDirectory=TRUE;
					KeepGoing=FileListFromDirectory(filelist,filename,UserCancel);

					if(!KeepGoing)
					{
						FindClose(hFindFile);
						return FALSE;
					}
				}
			}

			memset(name,0x00,strlen(name));
			free(name);
			memset(filename,0x00,strlen(filename));
			free(filename);

			if(IsNT)
			{
				RetVal=FindNextFileW(hFindFile,&FindFileDataW);
			}
			else
			{
				RetVal=FindNextFileA(hFindFile,&FindFileDataA);
			}
		}

		FindClose(hFindFile);
	}

	return TRUE;
} 
Beispiel #5
0
void main()
  {
    printf( "%d\n", _setmbcp( 932 ) );
    printf( "%d\n", _getmbcp() );
  }
void findExecutablePath()
{
#ifdef _WIN32
    static const int BUFSIZE = 1024;
    TCHAR execFilePath[BUFSIZE];
    if(GetModuleFileName(NULL, execFilePath, BUFSIZE)){
#ifndef UNICODE
        executablePath_ = execFilePath;
#else
        int codepage = _getmbcp();
        const int newSize = WideCharToMultiByte(codepage, 0, execFilePath, -1, NULL, 0, NULL, NULL);
        if(newSize > 0){
            vector<filesystem::path::String> execFilePathMB(newSize + 1);
            newSize = WideCharToMultiByte(codepage, 0, execFilePath, -1, &execFilePathMB[0], newSize + 1, NULL, NULL);
            executablePath_ = execFilePathUtf8;
            ;
        }
#endif // UNICODE
    }
#endif

#ifdef __linux__
    utsname info;
    if(uname(&info) == 0){
        if(strncmp(info.sysname, "Linux", 6) == 0){
            static const int BUFSIZE = 1024;
            char buf[BUFSIZE];
            int n = readlink("/proc/self/exe", buf, BUFSIZE - 1);
            buf[n] = 0;
            executablePath_ = buf;
        }
    }
#endif

#ifdef MACOSX
    char buf[1024];
    uint32_t n = sizeof(buf);
    if(_NSGetExecutablePath(buf, &n) == 0){
        executablePath_ = buf;
    }
        
    filesystem::path path;
    // remove dot from a path like bin/./choreonoid
    makePathCompact(filesystem::path(executablePath_), path);
    //filesystem::path path = filesystem::canonical(filesystem::path(executablePath_));
#else
    filesystem::path path(executablePath_);
#endif

    filesystem::path topPath = path.parent_path().parent_path();
    executableTopDirectory_ = topPath.string();
        
    filesystem::path sharePath = topPath / CNOID_SHARE_SUBDIR;
    if(filesystem::is_directory(sharePath)){
        shareDirectory_ = getNativePathString(sharePath);

    } else if(filesystem::is_directory(sharePath.parent_path())){
        shareDirectory_ = getNativePathString(sharePath.parent_path());

    } else if(topPath.has_parent_path()){ // case of a sub build directory
        sharePath = topPath.parent_path() / "share";
        if(filesystem::is_directory(sharePath)){
            shareDirectory_ = getNativePathString(sharePath);
        }
    }

#ifdef _WIN32
    if(path.extension() == ".exe"){
        executableBasename_ = getBasename(path);
    } else {
        executableBasename_ = getFilename(path);
    }
#else
    executableBasename_ = getFilename(path);
#endif
}
Beispiel #7
0
/**
   \note This implementation cannot be used because the extension is omitted
   when the exploer hides the extension of registered file types.
   \todo Support the case where the exploer hides the extension of registered file types.
*/
std::string toActualPathName(const std::string& path)
{
    int codepage = _getmbcp();
    size_t length = ::MultiByteToWideChar(codepage, 0, path.c_str(), path.size(), NULL, 0);
    if(length >= 0){
        wchar_t wpath[MAX_PATH];
        ::MultiByteToWideChar(codepage, 0, path.c_str(), path.size(), wpath, MAX_PATH);
        
        // The following code was based on the code posted at
        // http://stackoverflow.com/questions/74451/getting-actual-file-name-with-proper-casing-on-windowsis
        // Thank you.
        
        const wchar_t kSeparator = L'\\';
        size_t i = 0;
        std::wstring result;
        
        // for network paths (\\server\share\RestOfPath), getting the display
        // name mangles it into unusable form (e.g. "\\server\share" turns
        // into "share on server (server)"). So detect this case and just skip
        // up to two path components
        if( length >= 2 && wpath[0] == kSeparator && wpath[1] == kSeparator ) {
            int skippedCount = 0;
            i = 2; // start after '\\'
            while( i < length && skippedCount < 2 ) {
                if( wpath[i] == kSeparator ){
                    ++skippedCount;
                }
                ++i;
            }
            result.append( wpath, i );
        }
        // for drive names, just add it uppercased
        else if( length >= 2 && wpath[1] == L':' ) {
            result += towupper(wpath[0]);
            result += L':';
            if( length >= 3 && wpath[2] == kSeparator ){
                result += kSeparator;
                i = 3; // start after drive, colon and separator
            } else {
                i = 2; // start after drive and colon
            }
        }
        
        size_t lastComponentStart = i;
        bool addSeparator = false;
        
        while( i < length ) {
            // skip until path separator
            while( i < length && wpath[i] != kSeparator ) {
                ++i;
            }
            if( addSeparator ) {
                result += kSeparator;
            }
            
            // if we found path separator, get real filename of this
            // last path name component
            bool foundSeparator = (i < length);
            wpath[i] = 0;
            SHFILEINFOW info;
            
            // nuke the path separator so that we get real name of current path component
            info.szDisplayName[0] = 0;
            if( SHGetFileInfoW( wpath, 0, &info, sizeof(info), SHGFI_DISPLAYNAME ) ) {
                result += info.szDisplayName;
            } else {
                // most likely file does not exist.
                // So just append original path name component.
                result.append( wpath + lastComponentStart, i - lastComponentStart );
            }
            
            // restore path separator that we might have nuked before
            if( foundSeparator ){
                wpath[i] = kSeparator;
            }
            
            ++i;
            lastComponentStart = i;
            addSeparator = true;
        }
        
        length = ::WideCharToMultiByte(codepage, 0,  &result[0], result.size(), NULL, 0, NULL, NULL);
        if(length >= 0){
            std::vector<char> converted(length + 1);
            ::WideCharToMultiByte(codepage, 0,  &result[0], result.size(), &converted[0], length + 1, NULL, NULL);
            return std::string(&converted[0], length);
        }
    }
    return path; // failed
}
Beispiel #8
0
static void test_mbcp(void)
{
    int mb_orig_max = *p__mb_cur_max;
    int curr_mbcp = _getmbcp();
    unsigned char *mbstring = (unsigned char *)"\xb0\xb1\xb2 \xb3\xb4 \xb5"; /* incorrect string */
    unsigned char *mbstring2 = (unsigned char *)"\xb0\xb1\xb2\xb3Q\xb4\xb5"; /* correct string */
    unsigned char *mbsonlylead = (unsigned char *)"\xb0\0\xb1\xb2 \xb3";
    unsigned char buf[16];
    int step;

    /* _mbtype tests */

    /* An SBCS codepage test. The ctype of characters on e.g. CP1252 or CP1250 differs slightly
     * between versions of Windows. Also Windows 9x seems to ignore the codepage and always uses
     * CP1252 (or the ACP?) so we test only a few ASCII characters */
    _setmbcp(1252);
    expect_eq(p_mbctype[10], 0, char, "%x");
    expect_eq(p_mbctype[50], 0, char, "%x");
    expect_eq(p_mbctype[66], _SBUP, char, "%x");
    expect_eq(p_mbctype[100], _SBLOW, char, "%x");
    expect_eq(p_mbctype[128], 0, char, "%x");
    _setmbcp(1250);
    expect_eq(p_mbctype[10], 0, char, "%x");
    expect_eq(p_mbctype[50], 0, char, "%x");
    expect_eq(p_mbctype[66], _SBUP, char, "%x");
    expect_eq(p_mbctype[100], _SBLOW, char, "%x");
    expect_eq(p_mbctype[128], 0, char, "%x");

    /* double byte code pages */
    test_codepage(932);
    test_codepage(936);
    test_codepage(949);
    test_codepage(950);

    _setmbcp(936);
    ok(*p__mb_cur_max == mb_orig_max, "__mb_cur_max shouldn't be updated (is %d != %d)\n", *p__mb_cur_max, mb_orig_max);
    ok(_ismbblead('\354'), "\354 should be a lead byte\n");
    ok(_ismbblead(' ') == FALSE, "' ' should not be a lead byte\n");
    ok(_ismbblead(0x1234b0), "0x1234b0 should not be a lead byte\n");
    ok(_ismbblead(0x123420) == FALSE, "0x123420 should not be a lead byte\n");
    ok(_ismbbtrail('\xb0'), "\xa0 should be a trail byte\n");
    ok(_ismbbtrail(' ') == FALSE, "' ' should not be a trail byte\n");

    /* _ismbslead */
    expect_eq(_ismbslead(mbstring, &mbstring[0]), -1, int, "%d");
    expect_eq(_ismbslead(mbstring, &mbstring[1]), FALSE, int, "%d");
    expect_eq(_ismbslead(mbstring, &mbstring[2]), -1, int, "%d");
    expect_eq(_ismbslead(mbstring, &mbstring[3]), FALSE, int, "%d");
    expect_eq(_ismbslead(mbstring, &mbstring[4]), -1, int, "%d");
    expect_eq(_ismbslead(mbstring, &mbstring[5]), FALSE, int, "%d");
    expect_eq(_ismbslead(mbstring, &mbstring[6]), FALSE, int, "%d");
    expect_eq(_ismbslead(mbstring, &mbstring[7]), -1, int, "%d");
    expect_eq(_ismbslead(mbstring, &mbstring[8]), FALSE, int, "%d");

    expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[0]), -1, int, "%d");
    expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[1]), FALSE, int, "%d");
    expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[2]), FALSE, int, "%d");
    expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[5]), FALSE, int, "%d");

    /* _ismbstrail */
    expect_eq(_ismbstrail(mbstring, &mbstring[0]), FALSE, int, "%d");
    expect_eq(_ismbstrail(mbstring, &mbstring[1]), -1, int, "%d");
    expect_eq(_ismbstrail(mbstring, &mbstring[2]), FALSE, int, "%d");
    expect_eq(_ismbstrail(mbstring, &mbstring[3]), -1, int, "%d");
    expect_eq(_ismbstrail(mbstring, &mbstring[4]), FALSE, int, "%d");
    expect_eq(_ismbstrail(mbstring, &mbstring[5]), -1, int, "%d");
    expect_eq(_ismbstrail(mbstring, &mbstring[6]), FALSE, int, "%d");
    expect_eq(_ismbstrail(mbstring, &mbstring[7]), FALSE, int, "%d");
    expect_eq(_ismbstrail(mbstring, &mbstring[8]), -1, int, "%d");

    expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[0]), FALSE, int, "%d");
    expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[1]), -1, int, "%d");
    expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[2]), FALSE, int, "%d");
    expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[3]), FALSE, int, "%d");
    expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[4]), FALSE, int, "%d");
    expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[5]), FALSE, int, "%d");

    /* _mbsbtype */
    expect_eq(_mbsbtype(mbstring, 0), _MBC_LEAD, int, "%d");
    expect_eq(_mbsbtype(mbstring, 1), _MBC_TRAIL, int, "%d");
    expect_eq(_mbsbtype(mbstring, 2), _MBC_LEAD, int, "%d");
    expect_eq(_mbsbtype(mbstring, 3), _MBC_ILLEGAL, int, "%d");
    expect_eq(_mbsbtype(mbstring, 4), _MBC_LEAD, int, "%d");
    expect_eq(_mbsbtype(mbstring, 5), _MBC_TRAIL, int, "%d");
    expect_eq(_mbsbtype(mbstring, 6), _MBC_SINGLE, int, "%d");
    expect_eq(_mbsbtype(mbstring, 7), _MBC_LEAD, int, "%d");
    expect_eq(_mbsbtype(mbstring, 8), _MBC_ILLEGAL, int, "%d");

    expect_eq(_mbsbtype(mbsonlylead, 0), _MBC_LEAD, int, "%d");
    expect_eq(_mbsbtype(mbsonlylead, 1), _MBC_ILLEGAL, int, "%d");
    expect_eq(_mbsbtype(mbsonlylead, 2), _MBC_ILLEGAL, int, "%d");
    expect_eq(_mbsbtype(mbsonlylead, 3), _MBC_ILLEGAL, int, "%d");
    expect_eq(_mbsbtype(mbsonlylead, 4), _MBC_ILLEGAL, int, "%d");
    expect_eq(_mbsbtype(mbsonlylead, 5), _MBC_ILLEGAL, int, "%d");

    /* _mbsnextc */
    expect_eq(_mbsnextc(mbstring), 0xb0b1, int, "%x");
    expect_eq(_mbsnextc(&mbstring[2]), 0xb220, int, "%x");  /* lead + invalid tail */
    expect_eq(_mbsnextc(&mbstring[3]), 0x20, int, "%x");    /* single char */

    /* _mbclen/_mbslen */
    expect_eq(_mbclen(mbstring), 2, int, "%d");
    expect_eq(_mbclen(&mbstring[2]), 2, int, "%d");
    expect_eq(_mbclen(&mbstring[3]), 1, int, "%d");
    expect_eq(_mbslen(mbstring2), 4, int, "%d");
    expect_eq(_mbslen(mbsonlylead), 0, int, "%d");          /* lead + NUL not counted as character */
    expect_eq(_mbslen(mbstring), 4, int, "%d");             /* lead + invalid trail counted */

    /* _mbccpy/_mbsncpy */
    memset(buf, 0xff, sizeof(buf));
    _mbccpy(buf, mbstring);
    expect_bin(buf, "\xb0\xb1\xff", 3);

    memset(buf, 0xff, sizeof(buf));
    _mbsncpy(buf, mbstring, 1);
    expect_bin(buf, "\xb0\xb1\xff", 3);
    memset(buf, 0xff, sizeof(buf));
    _mbsncpy(buf, mbstring, 2);
    expect_bin(buf, "\xb0\xb1\xb2 \xff", 5);
    memset(buf, 0xff, sizeof(buf));
    _mbsncpy(buf, mbstring, 3);
    expect_bin(buf, "\xb0\xb1\xb2 \xb3\xb4\xff", 7);
    memset(buf, 0xff, sizeof(buf));
    _mbsncpy(buf, mbstring, 4);
    expect_bin(buf, "\xb0\xb1\xb2 \xb3\xb4 \xff", 8);
    memset(buf, 0xff, sizeof(buf));
    _mbsncpy(buf, mbstring, 5);
    expect_bin(buf, "\xb0\xb1\xb2 \xb3\xb4 \0\0\xff", 10);
    memset(buf, 0xff, sizeof(buf));
    _mbsncpy(buf, mbsonlylead, 6);
    expect_bin(buf, "\0\0\0\0\0\0\0\xff", 8);

    memset(buf, 0xff, sizeof(buf));
    _mbsnbcpy(buf, mbstring2, 2);
    expect_bin(buf, "\xb0\xb1\xff", 3);
    _mbsnbcpy(buf, mbstring2, 3);
    expect_bin(buf, "\xb0\xb1\0\xff", 4);
    _mbsnbcpy(buf, mbstring2, 4);
    expect_bin(buf, "\xb0\xb1\xb2\xb3\xff", 5);
    memset(buf, 0xff, sizeof(buf));
    _mbsnbcpy(buf, mbsonlylead, 5);
    expect_bin(buf, "\0\0\0\0\0\xff", 6);

    /* _mbsinc/mbsdec */
    step = _mbsinc(mbstring) - mbstring;
    ok(step == 2, "_mbsinc adds %d (exp. 2)\n", step);
    step = _mbsinc(&mbstring[2]) - &mbstring[2];  /* lead + invalid tail */
    ok(step == 2, "_mbsinc adds %d (exp. 2)\n", step);

    step = _mbsninc(mbsonlylead, 1) - mbsonlylead;
    ok(step == 0, "_mbsninc adds %d (exp. 0)\n", step);
    step = _mbsninc(mbsonlylead, 2) - mbsonlylead;  /* lead + NUL byte + lead + char */
    ok(step == 0, "_mbsninc adds %d (exp. 0)\n", step);
    step = _mbsninc(mbstring2, 0) - mbstring2;
    ok(step == 0, "_mbsninc adds %d (exp. 2)\n", step);
    step = _mbsninc(mbstring2, 1) - mbstring2;
    ok(step == 2, "_mbsninc adds %d (exp. 2)\n", step);
    step = _mbsninc(mbstring2, 2) - mbstring2;
    ok(step == 4, "_mbsninc adds %d (exp. 4)\n", step);
    step = _mbsninc(mbstring2, 3) - mbstring2;
    ok(step == 5, "_mbsninc adds %d (exp. 5)\n", step);
    step = _mbsninc(mbstring2, 4) - mbstring2;
    ok(step == 7, "_mbsninc adds %d (exp. 7)\n", step);
    step = _mbsninc(mbstring2, 5) - mbstring2;
    ok(step == 7, "_mbsninc adds %d (exp. 7)\n", step);
    step = _mbsninc(mbstring2, 17) - mbstring2;
    ok(step == 7, "_mbsninc adds %d (exp. 7)\n", step);

    /* functions that depend on locale codepage, not mbcp.
     * we hope the current locale to be SBCS because setlocale(LC_ALL, ".1252") seems not to work yet
     * (as of Wine 0.9.43)
     */
    if (*p__mb_cur_max == 1)
    {
        expect_eq(mblen((char *)mbstring, 3), 1, int, "%x");
        expect_eq(_mbstrlen((char *)mbstring2), 7, int, "%d");
    }