StdStrBuf C4RankSystem::GetRankName(int iRank, bool fReturnLastIfOver)
{
	if (iRank<0) return StdStrBuf();
	// if a new-style ranklist is loaded, seek there
	if (pszRankNames)
	{
		if (iRankNum<=0) return StdStrBuf();
		// overflow check
		if (iRank>=iRankNum*(iRankExtNum+1))
		{
			// rank undefined: Fallback to last rank
			if (!fReturnLastIfOver) return StdStrBuf();
			iRank = iRankNum*(iRankExtNum+1)-1;
		}
		StdStrBuf sResult;
		if (iRank >= iRankNum)
		{
			// extended rank composed of two parts
			int iExtension = iRank / iRankNum - 1;
			iRank = iRank % iRankNum;
			sResult.Format(pszRankExtensions[iExtension], pszRankNames[iRank]);
		}
		else
		{
			// simple rank
			sResult.Ref(pszRankNames[iRank]);
		}
		return sResult;
	}
#ifdef _WIN32
	// old-style registry fallback
	while (iRank>=0)
	{
		char keyname[30];
		StdCopyStrBuf rankname;
		sprintf(keyname,"Rank%03d",iRank+1);
		rankname = GetRegistryString(Register,keyname);
		if (!rankname.isNull())
			return rankname;
		if (!fReturnLastIfOver) return StdStrBuf();
		--iRank;
	}
#endif
	return StdStrBuf();
}
bool RestoreWindowPosition(HWND hwnd,
                           const char *szWindowName,
                           const char *szSubKey,
                           bool fHidden)
{
	char buffer2[5];
	int x,y,wdt,hgt;
	bool fSetSize=true;
	StdCopyStrBuf regstr = GetRegistryString(szSubKey,szWindowName);
	// No position stored: cannot restore
	if (regstr.isNull())
		return false;
	if (regstr == "Maximized")
		return !!ShowWindow(hwnd,SW_MAXIMIZE | SW_NORMAL);
	if (regstr == "Minimized")
		return !!ShowWindow(hwnd,SW_MINIMIZE | SW_NORMAL);
	SCopySegment(regstr.getData(),0,buffer2,',',4); sscanf(buffer2,"%i",&x);
	SCopySegment(regstr.getData(),1,buffer2,',',4); sscanf(buffer2,"%i",&y);
	if (SCopySegment(regstr.getData(),2,buffer2,',',4)) sscanf(buffer2,"%i",&wdt); else fSetSize=false;
	if (SCopySegment(regstr.getData(),3,buffer2,',',4)) sscanf(buffer2,"%i",&hgt); else fSetSize=false;
	if (!fSetSize)
	{
		RECT winpos; if (!GetWindowRect(hwnd,&winpos)) return false;
		wdt=winpos.right-winpos.left; hgt=winpos.bottom-winpos.top;
	}
	// Move window
	WINDOWPLACEMENT wp; memset(&wp, 0, sizeof(WINDOWPLACEMENT)); wp.length = sizeof(WINDOWPLACEMENT);
	GetWindowPlacement(hwnd, &wp);
	RECT normalpos;
	normalpos.left = x; normalpos.right  = wdt + x;
	normalpos.top  = y; normalpos.bottom = hgt + y;
	wp.rcNormalPosition = normalpos;
	if (SetWindowPlacement(hwnd, &wp))
		return false;
	// Hide window
	if (fHidden)
		return !!ShowWindow(hwnd, SW_HIDE);
	// Show window
	return !!ShowWindow(hwnd, SW_NORMAL);
}
int C4RankSystem::Init(const char *szRegister,
                       const char *szDefRanks,
                       int iRankBase)
{

	// Init
	SCopy(szRegister,Register,256);
	RankBase=iRankBase;

	// Check registry for present rank names and set defaults
#ifdef _WIN32
	int crank=0;
	char keyname[30];
	StdCopyStrBuf rankname;
	bool Checking=true;
	while (Checking)
	{
		sprintf(keyname,"Rank%03d",crank+1);
		rankname = GetRegistryString(Register,keyname);
		if (!rankname.isNull())
		{
			// Rank present
			crank++;
		}
		else
		{
			// Rank not defined, check for default
			rankname.AppendChars('\0', C4MaxName);
			if (SCopySegment(szDefRanks,crank,rankname.getMData(),'|',C4MaxName)
			    && SetRegistryString(Register,keyname,rankname.getData()))
				crank++;
			else
				Checking=false;
		}
	}
	return crank;
#else
	// clear any loaded rank names
	Clear();
	if (!szDefRanks) return 0;
	// make a copy
	szRankNames = new char[strlen(szDefRanks) + 1];
	strcpy (szRankNames, szDefRanks);
	// split into substrings by replacing the | with zeros
	for (char * p = szRankNames; *p; ++p) if (*p == '|')
		{
			*p = 0;
			++iRankNum;
		}
	++ iRankNum; // The last rank is already terminated by zero
	// build a list of substrings
	pszRankNames = new char *[iRankNum];
	char * p = szRankNames;
	for (int i = 0; i < iRankNum; ++i)
	{
		pszRankNames[i] = p;
		p += strlen(p) + 1;
	}
	return iRankNum;
#endif
}