void CGUITextLayout::AppendToUTF32(const CStdStringW &utf16, character_t colStyle, vecText &utf32) { // NOTE: Assumes a single line of text utf32.reserve(utf32.size() + utf16.size()); for (unsigned int i = 0; i < utf16.size(); i++) utf32.push_back(utf16[i] | colStyle); }
void TestDocReader::TestTOCFields() { DocReader dr; dr.OpenFile(TEST_TOC_DOC); CStdStringW sGot = dr.GetMainDocumentText(); CStdStringW sExp = L"Table of Contents\rTable of Contents\t1\rNote\t4\rAppendix B – Calculation of font (FTC) and language (LID)\t178\r\r"; for (unsigned int i=0; i<(x64_int_cast)sGot.size(); i++) { switch (sGot[i]) { case 19: OutputDebugString(_T("<start>")); break; case 20: OutputDebugString(_T("<result>")); break; case 21: OutputDebugString(_T("<end>")); break; default: { CStdStringW s = sGot.Mid(i,1); OutputDebugString(CStdString(s)); } } } assertTest(sGot.Left(sExp.length()) == sExp); }
void CKeyboardLayoutConfiguration::readByteMapFromXML(const TiXmlElement* pXMLMap, map<BYTE, WCHAR>& charToCharMap, const char* mapRootElement) { if (pXMLMap && !pXMLMap->NoChildren()) { // map keys const TiXmlElement* pEntry = pXMLMap->FirstChildElement(); while (pEntry) { CStdString strInHex = XMLUtils::GetAttribute(pEntry, "inhex"); CStdString strOutChar = XMLUtils::GetAttribute(pEntry, "outchar"); if (!strInHex.empty() && !strOutChar.empty()) { CStdString hexValue = strInHex; CStdStringW toStr; g_charsetConverter.utf8ToW(strOutChar, toStr); int from; if (sscanf(hexValue.c_str(), "%x", (unsigned int *)&from)) { if (from != 0) // eats nearly any typing error as 0: catch it: { if (from < 256) { if (toStr.size()==1) { charToCharMap.insert(pair<BYTE, WCHAR>(from, toStr[0])); CLog::Log(LOGDEBUG, "insert map entry from %d to %c ", from, toStr[0]); } else { CLog::Log(LOGERROR, "String to %ls does not have the expected length of >=1", toStr.c_str()); } } else { CLog::Log(LOGERROR, "From value %d was greater than 255! ", from); } } else { CLog::Log(LOGERROR, "Scanned from-value %d as 0 probably a (typing?) error! ", from); } } else { CLog::Log(LOGERROR, "Could not scan from-value %s (was no valid hex value) ", hexValue.c_str()); } } else { CLog::Log(LOGERROR, "map entry misses attribute <inhex> or <outchar> or content of them"); } pEntry = pEntry->NextSiblingElement(); } } else { CLog::Log(LOGERROR, "XML-Configuration doesn't contain expected map root element %s", mapRootElement); } }
void CHTMLUtil::ConvertHTMLToW(const CStdStringW& strHTML, CStdStringW& strStripped) { if (strHTML.size() == 0) { strStripped.Empty(); return ; } int iPos = 0; strStripped = strHTML; while (mappings[iPos].html) { strStripped.Replace(mappings[iPos].html,CStdStringW(1, mappings[iPos].w)); iPos++; } iPos = strStripped.Find(L"&#"); while (iPos > 0 && iPos < (int)strStripped.size()-4) { int iStart = iPos + 1; iPos += 2; CStdStringW num; int base = 10; if (strStripped[iPos+1] == L'x') { base = 16; iPos++; } int i=iPos; while ( iPos < (int)strStripped.size() && (base==16?iswxdigit(strStripped[iPos]):iswdigit(strStripped[iPos]))) iPos++; num = strStripped.Mid(i,iPos-i); wchar_t val = (wchar_t)wcstol(num.c_str(),NULL,base); if (base == 10) num.Format(L"&#%ls;",num.c_str()); else num.Format(L"&#x%ls;",num.c_str()); strStripped.Replace(num,CStdStringW(1,val)); iPos = strStripped.Find(L"&#", iStart); } }
// BidiTransform is used to handle RTL text flipping in the string void CGUITextLayout::BidiTransform(vector<CGUIString> &lines, bool forceLTRReadingOrder) { for (unsigned int i=0; i<lines.size(); i++) { CGUIString &line = lines[i]; // reserve enough space in the flipped text vecText flippedText; flippedText.reserve(line.m_text.size()); character_t sectionStyle = 0xffff0000; // impossible to achieve CStdStringW sectionText; for (vecText::iterator it = line.m_text.begin(); it != line.m_text.end(); ++it) { character_t style = *it & 0xffff0000; if (style != sectionStyle) { if (!sectionText.IsEmpty()) { // style has changed, bidi flip text CStdStringW sectionFlipped = BidiFlip(sectionText, forceLTRReadingOrder); for (unsigned int j = 0; j < sectionFlipped.size(); j++) flippedText.push_back(sectionStyle | sectionFlipped[j]); } sectionStyle = style; sectionText.clear(); } sectionText.push_back( (wchar_t)(*it & 0xffff) ); } // handle the last section if (!sectionText.IsEmpty()) { CStdStringW sectionFlipped = BidiFlip(sectionText, forceLTRReadingOrder); for (unsigned int j = 0; j < sectionFlipped.size(); j++) flippedText.push_back(sectionStyle | sectionFlipped[j]); } // replace the original line with the proccessed one lines[i] = CGUIString(flippedText.begin(), flippedText.end(), line.m_carriageReturn); } }
void CGUIDialogKeyboardGeneric::InputText(const CStdString& aTextString) { CStdStringW newStr; g_charsetConverter.utf8ToW(aTextString, newStr); if (!newStr.empty()) { m_strEditing.clear(); m_iEditingOffset = 0; m_strEdit.insert(GetCursorPos(), newStr); UpdateLabel(); MoveCursor(newStr.size()); } }
void CKeyboardLayoutConfiguration::readCharMapFromXML(const TiXmlElement* pXMLMap, map<WCHAR, WCHAR>& charToCharMap, const char* mapRootElement) { if (pXMLMap && !pXMLMap->NoChildren()) { // map keys const TiXmlElement* pEntry = pXMLMap->FirstChildElement(); while (pEntry) { CStdString strInChar = XMLUtils::GetAttribute(pEntry, "inchar"); CStdString strOutChar = XMLUtils::GetAttribute(pEntry, "outchar"); if (!strInChar.empty() && !strOutChar.empty()) { CStdStringW fromStr; g_charsetConverter.utf8ToW(strInChar, fromStr); CStdStringW toStr; g_charsetConverter.utf8ToW(strOutChar, toStr); if (fromStr.size()==1 && toStr.size()==1) { charToCharMap.insert(pair<WCHAR, WCHAR>(fromStr[0], toStr[0])); CLog::Log(LOGDEBUG, "insert map entry from %c to %c ", fromStr[0], toStr[0]); } else { CLog::Log(LOGERROR, "String from %ls or to %ls does not have the expected length of 1", fromStr.c_str(), toStr.c_str()); } } else { CLog::Log(LOGERROR, "map entry misses attribute <inchar> or <outchar> or content of them"); } pEntry = pEntry->NextSiblingElement(); } } else { CLog::Log(LOGDEBUG, "XML-Configuration doesn't contain expected map root element %s", mapRootElement); } }
void CRssReader::AddString(CStdStringW aString, int aColour, int iFeed) { if (m_rtlText) m_strFeed[iFeed] = aString + m_strFeed[iFeed]; else m_strFeed[iFeed] += aString; size_t nStringLength = aString.size(); for (size_t i = 0;i < nStringLength;i++) aString[i] = (CHAR) (48 + aColour); if (m_rtlText) m_strColors[iFeed] = aString + m_strColors[iFeed]; else m_strColors[iFeed] += aString; }
bool CWIN32Util::IsUsbDevice(const CStdStringW &strWdrive) { if (strWdrive.size() < 2) return false; CStdStringW strWDevicePath = StringUtils::Format(L"\\\\.\\%s",strWdrive.substr(0, 2).c_str()); HANDLE deviceHandle = CreateFileW( strWDevicePath.c_str(), 0, // no access to the drive FILE_SHARE_READ | // share mode FILE_SHARE_WRITE, NULL, // default security attributes OPEN_EXISTING, // disposition 0, // file attributes NULL); // do not copy file attributes if(deviceHandle == INVALID_HANDLE_VALUE) return false; // setup query STORAGE_PROPERTY_QUERY query; memset(&query, 0, sizeof(query)); query.PropertyId = StorageDeviceProperty; query.QueryType = PropertyStandardQuery; // issue query DWORD bytes; STORAGE_DEVICE_DESCRIPTOR devd; STORAGE_BUS_TYPE busType = BusTypeUnknown; if (DeviceIoControl(deviceHandle, IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(query), &devd, sizeof(devd), &bytes, NULL)) { busType = devd.BusType; } CloseHandle(deviceHandle); return BusTypeUsb == busType; }
void TestDocReader::TestCommentsWithTrackChanges() { DocReader dr; dr.OpenFile(TEST_COMMENTS_TC_DOC); CStdStringW sExp = L"Lots of the - the only actual change from this story is that the w3 file appear next to the revolving document,"; sExp += " not in a dms folder, plus it create dms \05folders where there isn't one already.\r"; sExp += "QA IanX> 2X integration sheets received 03/10/03\05. No visable change\05, change \05is to development tests only.\r"; CStdStringW sGot = dr.GetMainDocumentText(); for (unsigned int i=0; i<(x64_int_cast)sExp.size(); i++) { OutputDebugString(CStdString(sGot.substr(i,1))); assertTest(sGot[i] == sExp[i]); } assertTest(dr.GetMainDocumentText() == sExp); }
void TestDocReader::TestAMoreCompicatedDocumentWithDeletedTextAndFastSaves() { DocReader dr; dr.OpenFile(TEST_COMPLEX_FS_DOC); CStdStringW sExp = L"Marbles Reunited shows those pictures removed from Greece last year by Lord Elgin next to those which remained in Athens. \r"; sExp += "The London marbles are shown in colour while the others are depicted in white. \r"; sExp += "The exhibition was shown at the Houses of Parliament earlier in the year. \r"; sExp += "The marbles, ancient sculptures which once adorned the Parthenon in Athens, have been held in the Parthenon since 1811. \r\r"; sExp += "A whole new paragraph after first fast save. A whole new paragraph after first fast save. A whole new paragraph after first fast save. A whole new paragraph after first fast save.\r"; sExp += "\"However, this ws that this is not the case\". \r"; sExp += "Other are using the forthcoming athletics, due to be held in Greece next millenium, to raise the question of ownership.\r\r"; CStdStringW sGot = dr.GetMainDocumentText(); for (unsigned int i=0; i<(x64_int_cast)sExp.size(); i++) { // OutputDebugString(CStdString(sGot.substr(i,1))); assertTest(sGot[i] == sExp[i]); } assertTest(dr.GetMainDocumentText() == sExp); }
void TestDocReader::TestTabChanges() { DocReader dr; dr.OpenFile(TEST_TABS_TC_DOC); CStdStringW sExp = L"\t\t\t\t\t\t\t\t\t\tABC\t1.23\tDEF\tGHI\tFFF\r"; sExp += "Abc\t222.23\t\t\t\t\tdef\tghi\tddd\r"; sExp += "Aaa\t10.87 b\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcb\tccc\txxx\r"; sExp += "Ddd\t1.44994\t\t\t\t\t\t\r"; sExp += "ABC\t1.23 DEF GHI aaa\t\t\t\r"; sExp += "Abc\t222.\t\t\txxx\r"; sExp += "Aaa\t10.87\tbcb\tccc\tzzz\r"; sExp += "Ddd\t1.44994\teEEee\tfffLeft\tright\r"; sExp += "Left\tRIGHT\r"; CStdStringW sGot = dr.GetMainDocumentText(); for (unsigned int i=0; i<(x64_int_cast)sExp.size(); i++) { OutputDebugString(CStdString(sGot.substr(i,1))); assertTest(sGot[i] == sExp[i]); } assertTest(dr.GetMainDocumentText() == sExp); }
void CGUITextLayout::ParseText(const CStdStringW &text, uint32_t defaultStyle, color_t defaultColor, vecColors &colors, vecText &parsedText) { // run through the string, searching for: // [B] or [/B] -> toggle bold on and off // [I] or [/I] -> toggle italics on and off // [COLOR ffab007f] or [/COLOR] -> toggle color on and off // [CAPS <option>] or [/CAPS] -> toggle capatilization on and off uint32_t currentStyle = defaultStyle; // start with the default font's style color_t currentColor = 0; colors.push_back(defaultColor); stack<color_t> colorStack; colorStack.push(0); // these aren't independent, but that's probably not too much of an issue // eg [UPPERCASE]Glah[LOWERCASE]FReD[/LOWERCASE]Georeg[/UPPERCASE] will work (lower case >> upper case) // but [LOWERCASE]Glah[UPPERCASE]FReD[/UPPERCASE]Georeg[/LOWERCASE] won't int startPos = 0; size_t pos = text.Find(L'['); while (pos != CStdString::npos && pos + 1 < text.size()) { uint32_t newStyle = 0; color_t newColor = currentColor; bool colorTagChange = false; bool newLine = false; // have a [ - check if it's an ON or OFF switch bool on(true); int endPos = pos++; // finish of string if (text[pos] == L'/') { on = false; pos++; } // check for each type if (text.Mid(pos,2) == L"B]") { // bold - finish the current text block and assign the bold state pos += 2; if ((on && text.Find(L"[/B]",pos) >= 0) || // check for a matching end point (!on && (currentStyle & FONT_STYLE_BOLD))) // or matching start point newStyle = FONT_STYLE_BOLD; } else if (text.Mid(pos,2) == L"I]") { // italics pos += 2; if ((on && text.Find(L"[/I]",pos) >= 0) || // check for a matching end point (!on && (currentStyle & FONT_STYLE_ITALICS))) // or matching start point newStyle = FONT_STYLE_ITALICS; } else if (text.Mid(pos,10) == L"UPPERCASE]") { pos += 10; if ((on && text.Find(L"[/UPPERCASE]",pos) >= 0) || // check for a matching end point (!on && (currentStyle & FONT_STYLE_UPPERCASE))) // or matching start point newStyle = FONT_STYLE_UPPERCASE; } else if (text.Mid(pos,10) == L"LOWERCASE]") { pos += 10; if ((on && text.Find(L"[/LOWERCASE]",pos) >= 0) || // check for a matching end point (!on && (currentStyle & FONT_STYLE_LOWERCASE))) // or matching start point newStyle = FONT_STYLE_LOWERCASE; } else if (text.Mid(pos,3) == L"CR]" && on) { newLine = true; pos += 3; } else if (text.Mid(pos,5) == L"COLOR") { // color size_t finish = text.Find(L']', pos + 5); if (on && finish != CStdString::npos && (size_t)text.Find(L"[/COLOR]",finish) != CStdString::npos) { color_t color = g_colorManager.GetColor(text.Mid(pos + 5, finish - pos - 5)); vecColors::const_iterator it = std::find(colors.begin(), colors.end(), color); if (it == colors.end()) { // create new color if (colors.size() <= 0xFF) { newColor = colors.size(); colors.push_back(color); } else // we have only 8 bits for color index, fallback to first color if reach max. newColor = 0; } else // reuse existing color newColor = it - colors.begin(); colorStack.push(newColor); colorTagChange = true; } else if (!on && finish == pos + 5 && colorStack.size() > 1) { // revert to previous color colorStack.pop(); newColor = colorStack.top(); colorTagChange = true; } if (finish != CStdString::npos) pos = finish + 1; } if (newStyle || colorTagChange || newLine) { // we have a new style or a new color, so format up the previous segment CStdStringW subText = text.Mid(startPos, endPos - startPos); if (currentStyle & FONT_STYLE_UPPERCASE) subText.ToUpper(); if (currentStyle & FONT_STYLE_LOWERCASE) subText.ToLower(); AppendToUTF32(subText, ((currentStyle & 3) << 24) | (currentColor << 16), parsedText); if (newLine) parsedText.push_back(L'\n'); // and switch to the new style startPos = pos; currentColor = newColor; if (on) currentStyle |= newStyle; else currentStyle &= ~newStyle; } pos = text.Find(L'[',pos); } // now grab the remainder of the string CStdStringW subText = text.Mid(startPos, text.GetLength() - startPos); if (currentStyle & FONT_STYLE_UPPERCASE) subText.ToUpper(); if (currentStyle & FONT_STYLE_LOWERCASE) subText.ToLower(); AppendToUTF32(subText, ((currentStyle & 3) << 24) | (currentColor << 16), parsedText); }
void CWIN32Util::GetDrivesByType(VECSOURCES &localDrives, Drive_Types eDriveType, bool bonlywithmedia) { WCHAR* pcBuffer= NULL; DWORD dwStrLength= GetLogicalDriveStringsW( 0, pcBuffer ); if( dwStrLength != 0 ) { CMediaSource share; dwStrLength+= 1; pcBuffer= new WCHAR [dwStrLength]; GetLogicalDriveStringsW( dwStrLength, pcBuffer ); int iPos= 0; WCHAR cVolumeName[100]; do{ int nResult = 0; cVolumeName[0]= L'\0'; CStdStringW strWdrive = pcBuffer + iPos; UINT uDriveType= GetDriveTypeW( strWdrive.c_str() ); // don't use GetVolumeInformation on fdd's as the floppy controller may be enabled in Bios but // no floppy HW is attached which causes huge delays. if(strWdrive.size() >= 2 && strWdrive.substr(0,2) != L"A:" && strWdrive.substr(0,2) != L"B:") nResult= GetVolumeInformationW( strWdrive.c_str() , cVolumeName, 100, 0, 0, 0, NULL, 25); if(nResult == 0 && bonlywithmedia) { iPos += (wcslen( pcBuffer + iPos) + 1 ); continue; } // usb hard drives are reported as DRIVE_FIXED and won't be returned by queries with REMOVABLE_DRIVES set // so test for usb hard drives /*if(uDriveType == DRIVE_FIXED) { if(IsUsbDevice(strWdrive)) uDriveType = DRIVE_REMOVABLE; }*/ share.strPath= share.strName= ""; bool bUseDCD= false; if( uDriveType > DRIVE_UNKNOWN && (( eDriveType == ALL_DRIVES && (uDriveType == DRIVE_FIXED || uDriveType == DRIVE_REMOTE || uDriveType == DRIVE_CDROM || uDriveType == DRIVE_REMOVABLE )) || ( eDriveType == LOCAL_DRIVES && (uDriveType == DRIVE_FIXED || uDriveType == DRIVE_REMOTE)) || ( eDriveType == REMOVABLE_DRIVES && ( uDriveType == DRIVE_REMOVABLE )) || ( eDriveType == DVD_DRIVES && ( uDriveType == DRIVE_CDROM )))) { //share.strPath = strWdrive; g_charsetConverter.wToUTF8(strWdrive, share.strPath); if( cVolumeName[0] != L'\0' ) g_charsetConverter.wToUTF8(cVolumeName, share.strName); if( uDriveType == DRIVE_CDROM && nResult) { // Has to be the same as auto mounted devices share.strStatus = share.strName; share.strName = share.strPath; share.m_iDriveType= CMediaSource::SOURCE_TYPE_LOCAL; bUseDCD= true; } else { // Lets show it, like Windows explorer do... TODO: sorting should depend on driver letter switch(uDriveType) { case DRIVE_CDROM: share.strName = StringUtils::Format( "%s (%s)", share.strPath.c_str(), g_localizeStrings.Get(218).c_str()); break; case DRIVE_REMOVABLE: if(share.strName.empty()) share.strName = StringUtils::Format( "%s (%s)", g_localizeStrings.Get(437).c_str(), share.strPath.c_str()); break; case DRIVE_UNKNOWN: share.strName = StringUtils::Format( "%s (%s)", share.strPath.c_str(), g_localizeStrings.Get(13205).c_str()); break; default: if(share.strName.empty()) share.strName = share.strPath; else share.strName = StringUtils::Format( "%s (%s)", share.strPath.c_str(), share.strName.c_str()); break; } } StringUtils::Replace(share.strName, ":\\", ":"); StringUtils::Replace(share.strPath, ":\\", ":"); share.m_ignore= true; if( !bUseDCD ) { share.m_iDriveType= ( ( uDriveType == DRIVE_FIXED ) ? CMediaSource::SOURCE_TYPE_LOCAL : ( uDriveType == DRIVE_REMOTE ) ? CMediaSource::SOURCE_TYPE_REMOTE : ( uDriveType == DRIVE_CDROM ) ? CMediaSource::SOURCE_TYPE_DVD : ( uDriveType == DRIVE_REMOVABLE ) ? CMediaSource::SOURCE_TYPE_REMOVABLE : CMediaSource::SOURCE_TYPE_UNKNOWN ); } AddOrReplace(localDrives, share); } iPos += (wcslen( pcBuffer + iPos) + 1 ); } while( wcslen( pcBuffer + iPos ) > 0 ); delete[] pcBuffer; } }
void CGUITextLayout::ParseText(const CStdStringW &text, uint32_t defaultStyle, vecColors &colors, vecText &parsedText) { // run through the string, searching for: // [B] or [/B] -> toggle bold on and off // [I] or [/I] -> toggle italics on and off // [COLOR ffab007f] or [/COLOR] -> toggle color on and off // [CAPS <option>] or [/CAPS] -> toggle capatilization on and off // uint32_t currentStyle = defaultStyle; // start with the default font's style // color_t currentColor = 0; stack<color_t> colorStack; colorStack.push(0); // these aren't independent, but that's probably not too much of an issue // eg [UPPERCASE]Glah[LOWERCASE]FReD[/LOWERCASE]Georeg[/UPPERCASE] will work (lower case >> upper case) // but [LOWERCASE]Glah[UPPERCASE]FReD[/UPPERCASE]Georeg[/LOWERCASE] won't #define FONT_STYLE_UPPERCASE 4 #define FONT_STYLE_LOWERCASE 8 int boldCounter = 0; int italicsCoutner = 0; int upperCounter = 0; int lowerCounter = 0; color_t color = 0; int startPos = 0; size_t pos = text.Find(L'['); while (pos != CStdString::npos && pos + 1 < text.size()) { int style = 0; if (pos - startPos > 0) { if (boldCounter) style |= FONT_STYLE_BOLD; if (italicsCoutner) style |= FONT_STYLE_ITALICS; CStdStringW subText = text.Mid(startPos, pos - startPos); if (upperCounter) { #if defined(_LINUX) && !defined(__APPLE__) std::transform(subText.begin(), subText.end(), subText.begin(), (gunichar(*)(gunichar)) g_unichar_toupper); #else subText.ToUpper(); #endif } if (lowerCounter) { #if defined(_LINUX) && !defined(__APPLE__) std::transform(subText.begin(), subText.end(), subText.begin(), (gunichar(*)(gunichar)) g_unichar_tolower); #else subText.ToLower(); #endif } AppendToUTF32(subText, ((style & 3) << 24) | (color << 16), parsedText); startPos = pos; } // have a [ - check if it's an ON or OFF switch bool ignoreTag = false; ++pos; bool on = true; if (text[pos] == L'/') { on = false; pos++; } // check for each type if (text.Mid(pos,2) == L"B]") { // bold - finish the current text block and assign the bold state pos += 2; on ? ++boldCounter : --boldCounter; } else if (text.Mid(pos,2) == L"I]") { // italics pos += 2; on ? ++italicsCoutner : --italicsCoutner; } else if (text.Mid(pos,10) == L"UPPERCASE]") { pos += 10; on ? ++upperCounter : --upperCounter; } else if (text.Mid(pos,10) == L"LOWERCASE]") { pos += 10; on ? ++lowerCounter : --lowerCounter; } else if (text.Mid(pos,3) == L"CR]" && on) { pos += 3; parsedText.push_back(L'\n'); } else if (text.Mid(pos,5) == L"COLOR") { // color size_t finish = text.Find(L']', pos + 5); if (on && finish != CStdString::npos && (size_t) text.Find(L"[/COLOR]",finish) != CStdString::npos) { // create new color color = colors.size(); colors.push_back(g_colorManager.GetColor(text.Mid(pos + 5, finish - pos - 5))); colorStack.push(color); } else if (!on && finish == pos + 5 && colorStack.size() > 1) { // revert to previous color colorStack.pop(); color = colorStack.top(); } pos = finish + 1; } else { ignoreTag = true; } if (!ignoreTag) { startPos = pos; } pos = text.Find(L'[',pos); } // now grab the remainder of the string CStdStringW subText = text.Mid(startPos, text.GetLength() - startPos); int style = 0; if (upperCounter) { #if defined(_LINUX) && !defined(__APPLE__) std::transform(subText.begin(), subText.end(), subText.begin(), (gunichar(*)(gunichar)) g_unichar_toupper); #else subText.ToUpper(); #endif } if (lowerCounter) { #if defined(_LINUX) && !defined(__APPLE__) std::transform(subText.begin(), subText.end(), subText.begin(), (gunichar(*)(gunichar)) g_unichar_tolower); #else subText.ToLower(); #endif } if (boldCounter) style |= FONT_STYLE_BOLD; if (italicsCoutner) style |= FONT_STYLE_ITALICS; AppendToUTF32(subText, ((style & 3) << 24) | (color << 16), parsedText); }
void CGUITextLayout::ParseText(const CStdStringW &text, DWORD defaultStyle, vector<DWORD> &colors, vector<DWORD> &parsedText) { // run through the string, searching for: // [B] or [/B] -> toggle bold on and off // [I] or [/I] -> toggle italics on and off // [COLOR ffab007f] or [/COLOR] -> toggle color on and off // [CAPS <option>] or [/CAPS] -> toggle capatilization on and off DWORD currentStyle = defaultStyle; // start with the default font's style DWORD currentColor = 0; stack<DWORD> colorStack; colorStack.push(0); // these aren't independent, but that's probably not too much of an issue // eg [UPPERCASE]Glah[LOWERCASE]FReD[/LOWERCASE]Georeg[/UPPERCASE] will work (lower case >> upper case) // but [LOWERCASE]Glah[UPPERCASE]FReD[/UPPERCASE]Georeg[/LOWERCASE] won't #define FONT_STYLE_UPPERCASE 4 #define FONT_STYLE_LOWERCASE 8 int startPos = 0; size_t pos = text.Find(L'['); while (pos != CStdString::npos && pos + 1 < text.size()) { DWORD newStyle = 0; DWORD newColor = currentColor; bool newLine = false; // have a [ - check if it's an ON or OFF switch bool on(true); int endPos = pos++; // finish of string if (text[pos] == L'/') { on = false; pos++; } // check for each type if (text.Mid(pos,2) == L"B]") { // bold - finish the current text block and assign the bold state newStyle = FONT_STYLE_BOLD; pos += 2; } else if (text.Mid(pos,2) == L"I]") { // italics newStyle = FONT_STYLE_ITALICS; pos += 2; } else if (text.Mid(pos,10) == L"UPPERCASE]") { newStyle = FONT_STYLE_UPPERCASE; pos += 10; } else if (text.Mid(pos,10) == L"LOWERCASE]") { newStyle = FONT_STYLE_LOWERCASE; pos += 10; } else if (text.Mid(pos,3) == L"CR]" && on) { newLine = true; pos += 3; } else if (text.Mid(pos,5) == L"COLOR") { // color size_t finish = text.Find(L']', pos + 5); if (on && finish != CStdString::npos) { // create new color newColor = colors.size(); colors.push_back(g_colorManager.GetColor(text.Mid(pos + 5, finish - pos - 5))); colorStack.push(newColor); } else if (!on && finish == pos + 5) { // revert to previous color if (colorStack.size() > 1) colorStack.pop(); newColor = colorStack.top(); } pos = finish + 1; } if (newStyle || newColor != currentColor || newLine) { // we have a new style or a new color, so format up the previous segment CStdStringW subText = text.Mid(startPos, endPos - startPos); if (currentStyle & FONT_STYLE_UPPERCASE) subText.ToUpper(); if (currentStyle & FONT_STYLE_LOWERCASE) subText.ToLower(); AppendToUTF32(subText, ((currentStyle & 3) << 24) | (currentColor << 16), parsedText); if (newLine) parsedText.push_back(L'\n'); // and switch to the new style startPos = pos; currentColor = newColor; if (on) currentStyle |= newStyle; else currentStyle &= ~newStyle; } pos = text.Find(L'[',pos); } // now grab the remainder of the string CStdStringW subText = text.Mid(startPos, text.GetLength() - startPos); if (currentStyle & FONT_STYLE_UPPERCASE) subText.ToUpper(); if (currentStyle & FONT_STYLE_LOWERCASE) subText.ToLower(); AppendToUTF32(subText, ((currentStyle & 3) << 24) | (currentColor << 16), parsedText); }