StdStrBuf C4FileSelDlg::GetSelection(const char *szFixedSelection, bool fFilenameOnly) const { StdStrBuf sResult; if (!IsMultiSelection()) { // get single selected file for single selection dlg if (pSelection) sResult.Copy(fFilenameOnly ? GetFilename(pSelection->GetFilename()) : pSelection->GetFilename()); } else { // force fixed selection first if (szFixedSelection) sResult.Append(szFixedSelection); // get ';'-seperated list for multi selection dlg for (ListItem *pFileItem = static_cast<ListItem *>(pFileListBox->GetFirst()); pFileItem; pFileItem = static_cast<ListItem *>(pFileItem->GetNext())) if (pFileItem->IsChecked()) { const char *szAppendFilename = pFileItem->GetFilename(); if (fFilenameOnly) szAppendFilename = GetFilename(szAppendFilename); // prevent adding entries twice (especially those from the fixed // selection list) if (!SIsModule(sResult.getData(), szAppendFilename)) { if (sResult.getLength()) sResult.AppendChar(';'); sResult.Append(szAppendFilename); } } } return sResult; }
StdStrBuf C4MusicFileOgg::GetDebugInfo() const { StdStrBuf result; result.Append(FileName); result.AppendFormat("[%.0lf]", last_playback_pos_sec); result.AppendChar('['); bool sec = false; for (auto i = categories.cbegin(); i != categories.cend(); ++i) { if (sec) result.AppendChar(','); result.Append(i->getData()); sec = true; } result.AppendChar(']'); return result; }
StdStrBuf C4Shader::Build(const ShaderSliceList &Slices, bool fDebug) { // At the start of the shader set the #version and number of // available uniforms StdStrBuf Buf; #ifndef USE_CONSOLE GLint iMaxFrags = 0, iMaxVerts = 0; glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &iMaxFrags); glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &iMaxVerts); #else int iMaxFrags = INT_MAX, iMaxVerts = INT_MAX; #endif Buf.Format("#version %d\n" "#define MAX_FRAGMENT_UNIFORM_COMPONENTS %d\n" "#define MAX_VERTEX_UNIFORM_COMPONENTS %d\n", C4Shader_Version, iMaxFrags, iMaxVerts); // Put slices int iPos = -1, iNextPos = -1; do { iPos = iNextPos; iNextPos = C4Shader_LastPosition+1; // Add all slices at the current level if (fDebug && iPos > 0) Buf.AppendFormat("\t// Position %d:\n", iPos); for (ShaderSliceList::const_iterator pSlice = Slices.begin(); pSlice != Slices.end(); pSlice++) { if (pSlice->Position < iPos) continue; if (pSlice->Position > iPos) { iNextPos = Min(iNextPos, pSlice->Position); continue; } // Same position - add slice! if (fDebug) { if (pSlice->Source.getLength()) Buf.AppendFormat("\t// Slice from %s:\n", pSlice->Source.getData()); else Buf.Append("\t// Built-in slice:\n"); } Buf.Append(pSlice->Text); if (Buf[Buf.getLength()-1] != '\n') Buf.AppendChar('\n'); } // Add seperator - only priority (-1) is top-level if (iPos == -1) { Buf.Append("void main() {\n"); } } while (iNextPos <= C4Shader_LastPosition); // Terminate Buf.Append("}\n"); return Buf; }
bool LogFatal(const char *szMessage) { if (!szMessage) szMessage = "(null)"; // add to fatal error message stack - if not already in there (avoid duplication) if (!SSearch(sFatalError.getData(), szMessage)) { if (!sFatalError.isNull()) sFatalError.AppendChar('|'); sFatalError.Append(szMessage); } // write to log - note that Log might overwrite a static buffer also used in szMessage return !!Log(FormatString(LoadResStr("IDS_ERR_FATAL"), szMessage).getData()); }
bool C4VectorFont::Init(C4Group &hGrp, const char *szFilename, C4Config &rCfg) { // name by file Name.Copy(GetFilenameOnly(szFilename)); #if defined(_WIN32) && !defined(HAVE_FREETYPE) // check whether group is directory or packed if (!hGrp.IsPacked()) { // it's open: use the file directly SCopy(hGrp.GetFullName().getData(), FileName, _MAX_PATH); AppendBackslash(FileName); SAppend(szFilename, FileName); if (!FileExists(FileName)) { *FileName=0; return false; } fIsTempFile = false; } else { // it's packed: extract to temp path SCopy(rCfg.AtTempPath(szFilename), FileName, _MAX_PATH); // make sure the filename is not in use, in case multiple instances of the engine are run if (FileExists(FileName)) { RemoveExtension(FileName); StdStrBuf sNewFilename; for (int i=0; i<1000; ++i) { sNewFilename.Format("%s%x", FileName, (int)rand()); if (*GetExtension(szFilename)) { sNewFilename.AppendChar('.'); sNewFilename.Append(GetExtension(szFilename)); } if (!FileExists(sNewFilename.getData())) break; } SCopy(sNewFilename.getData(), FileName, _MAX_PATH); } if (!hGrp.ExtractEntry(szFilename, FileName)) { *FileName=0; return false; } fIsTempFile = true; } // add the font resource //if (!AddFontResourceEx(FileName, FR_PRIVATE, NULL)) requires win2k if (!AddFontResource(FileName)) { if (fIsTempFile) EraseFile(FileName); *FileName='\0'; return false; } #else if (!hGrp.LoadEntry(szFilename, Data)) return false; #endif // success return true; }
StdStrBuf C4PropListStatic::GetDataString() const { StdStrBuf r; if (Parent) { r.Take(Parent->GetDataString()); r.AppendChar('.'); } assert(ParentKeyName); if (ParentKeyName) r.Append(ParentKeyName->GetData()); return r; }
bool C4MusicSystem::InitForScenario(C4Group & hGroup) { // check if the scenario contains music bool fLocalMusic = false; StdStrBuf MusicDir; if (GrpContainsMusic(hGroup)) { // clear global songs ClearSongs(); fLocalMusic = true; // add songs MusicDir.Take(Game.ScenarioFile.GetFullName()); LoadDir(MusicDir.getData()); // log LogF(LoadResStr("IDS_PRC_LOCALMUSIC"), MusicDir.getData()); } // check for music folders in group set C4Group *pMusicFolder = NULL; while ((pMusicFolder = Game.GroupSet.FindGroup(C4GSCnt_Music, pMusicFolder))) { if (!fLocalMusic) { // clear global songs ClearSongs(); fLocalMusic = true; } // add songs MusicDir.Take(pMusicFolder->GetFullName()); MusicDir.AppendChar(DirectorySeparator); MusicDir.Append(C4CFN_Music); LoadDir(MusicDir.getData()); // log LogF(LoadResStr("IDS_PRC_LOCALMUSIC"), MusicDir.getData()); } // no music? if (!SongCount) return false; // set play list SetPlayList(0); // ok return true; }
StdStrBuf C4KeyCodeEx::ToString(bool fHumanReadable, bool fShort) const { static StdStrBuf sResult; sResult.Clear(); // Add shift for (DWORD dwShiftCheck = KEYS_First; dwShiftCheck <= KEYS_Max; dwShiftCheck <<= 1) if (dwShiftCheck & dwShift) { sResult.Append(KeyShift2String((C4KeyShiftState) dwShiftCheck)); sResult.AppendChar('+'); } // Add key if (sResult.getLength()) { sResult.Append(KeyCode2String(Key, fHumanReadable, fShort)); return sResult; } else { return KeyCode2String(Key, fHumanReadable, fShort); } }
StdStrBuf C4Team::GetNameWithParticipants() const { // compose team name like "Team 1 (boni, GhostBear, Clonko)" // or just "Team 1" for empty team StdStrBuf sTeamName; sTeamName.Copy(GetName()); if (GetPlayerCount()) { sTeamName.Append(" ("); int32_t iTeamPlrCount=0; for (int32_t j=0; j<GetPlayerCount(); ++j) { int32_t iPlr = GetIndexedPlayer(j); C4PlayerInfo *pPlrInfo; if (iPlr) if ((pPlrInfo = Game.PlayerInfos.GetPlayerInfoByID(iPlr))) { if (iTeamPlrCount++) sTeamName.Append(", "); sTeamName.Append(pPlrInfo->GetName()); } } sTeamName.AppendChar(')'); } return sTeamName; }
void C4Network2IRCClient::OnNumericCommand(const char *szSender, int iCommand, const char *szParameters) { bool fShowMessage = true; // Get target StdStrBuf Target = ircExtractPar(&szParameters); // Handle command switch(iCommand) { case 433: // Nickname already in use { StdStrBuf DesiredNick = ircExtractPar(&szParameters); // Automatically try to choose a new one DesiredNick.AppendChar('_'); Send("NICK", DesiredNick.getData()); break; } case 376: // End of MOTD case 422: // MOTD missing // Let's take this a sign that the connection is established. OnConnected(); break; case 331: // No topic set case 332: // Topic notify / change { // Get Channel name and topic StdStrBuf Channel = ircExtractPar(&szParameters); StdStrBuf Topic = (iCommand == 332 ? ircExtractPar(&szParameters) : StdStrBuf("")); // Set it AddChannel(Channel.getData())->OnTopic(Topic.getData()); // Log if(Topic.getLength()) PushMessage(MSG_Status, szSender, Channel.getData(), FormatString(LoadResStr("IDS_MSG_TOPICIN"), Channel.getData(), Topic.getData()).getData()); } break; case 333: // Last topic change fShowMessage = false; // ignore break; case 353: // Names in channel { // Get Channel name and name list StdStrBuf Junk = ircExtractPar(&szParameters); // ??! StdStrBuf Channel = ircExtractPar(&szParameters); StdStrBuf Names = ircExtractPar(&szParameters); // Set it AddChannel(Channel.getData())->OnUsers(Names.getData(), Prefixes.getData()); fShowMessage = false; } break; case 366: // End of names list { // Get Channel name StdStrBuf Channel = ircExtractPar(&szParameters); // Finish AddChannel(Channel.getData())->OnUsersEnd(); fShowMessage = false; // Notify if(pNotify) pNotify->PushEvent(Ev_IRC_Message, this); } break; case 4: // Server version fShowMessage = false; // ignore break; case 5: // Server support string { while(szParameters && *szParameters) { // Get support-token. StdStrBuf Token = ircExtractPar(&szParameters); StdStrBuf Parameter; Parameter.CopyUntil(Token.getData(), '='); // Check if it's interesting and safe data if so. if(SEqualNoCase(Parameter.getData(), "PREFIX")) Prefixes.Copy(SSearch(Token.getData(), "=")); } fShowMessage = false; } break; } // Show embedded message, if any? if(fShowMessage) { // Check if first parameter is some sort of channel name C4Network2IRCChannel *pChannel = NULL; if(szParameters && *szParameters && *szParameters != ':') pChannel = getChannel(ircExtractPar(&szParameters).getData()); // Go over other parameters const char *pMsg = szParameters; while(pMsg && *pMsg && *pMsg != ':') pMsg = SSearch(pMsg, " "); // Show it if(pMsg && *pMsg) if(!pChannel) PushMessage(MSG_Server, szSender, Nick.getData(), pMsg + 1); else PushMessage(MSG_Status, szSender, pChannel->getName(), pMsg + 1); } }
bool C4MessageInput::ProcessCommand(const char *szCommand) { C4GameLobby::MainDlg *pLobby = Game.Network.GetLobby(); // command char szCmdName[C4MaxName + 1]; SCopyUntil(szCommand + 1, szCmdName, ' ', C4MaxName); // parameter const char *pCmdPar = SSearch(szCommand, " "); if (!pCmdPar) pCmdPar = ""; // dev-scripts if (SEqual(szCmdName, "help")) { LogF(LoadResStr("IDS_TEXT_COMMANDSAVAILABLEDURINGGA")); LogF("/private [player] [message] - %s", LoadResStr("IDS_MSG_SENDAPRIVATEMESSAGETOTHES")); LogF("/team [message] - %s", LoadResStr("IDS_MSG_SENDAPRIVATEMESSAGETOYOUR")); LogF("/me [action] - %s", LoadResStr("IDS_TEXT_PERFORMANACTIONINYOURNAME")); LogF("/sound [sound] - %s", LoadResStr("IDS_TEXT_PLAYASOUNDFROMTHEGLOBALSO")); LogF("/kick [client] - %s", LoadResStr("IDS_TEXT_KICKTHESPECIFIEDCLIENT")); LogF("/observer [client] - %s", LoadResStr("IDS_TEXT_SETTHESPECIFIEDCLIENTTOOB")); LogF("/fast [x] - %s", LoadResStr("IDS_TEXT_SETTOFASTMODESKIPPINGXFRA")); LogF("/slow - %s", LoadResStr("IDS_TEXT_SETTONORMALSPEEDMODE")); LogF("/chart - %s", LoadResStr("IDS_TEXT_DISPLAYNETWORKSTATISTICS")); LogF("/nodebug - %s", LoadResStr("IDS_TEXT_PREVENTDEBUGMODEINTHISROU")); LogF("/set comment [comment] - %s", LoadResStr("IDS_TEXT_SETANEWNETWORKCOMMENT")); LogF("/set password [password] - %s", LoadResStr("IDS_TEXT_SETANEWNETWORKPASSWORD")); LogF("/set faircrew [on/off] - %s", LoadResStr("IDS_TEXT_ENABLEORDISABLEFAIRCREW")); LogF("/set maxplayer [4] - %s", LoadResStr("IDS_TEXT_SETANEWMAXIMUMNUMBEROFPLA")); LogF("/script [script] - %s", LoadResStr("IDS_TEXT_EXECUTEASCRIPTCOMMAND")); LogF("/clear - %s", LoadResStr("IDS_MSG_CLEARTHEMESSAGEBOARD")); return TRUE; } // dev-scripts if (SEqual(szCmdName, "script")) { if (!Game.IsRunning) return FALSE; if (!Game.DebugMode) return FALSE; if (!Game.Network.isEnabled() && !SEqual(Game.ScenarioFile.GetMaker(), Config.General.Name) && Game.ScenarioFile.GetStatus() != GRPF_Folder) return FALSE; if (Game.Network.isEnabled() && !Game.Network.isHost()) return FALSE; Game.Control.DoInput( CID_Script, new C4ControlScript(pCmdPar, C4ControlScript::SCOPE_Console, false), CDT_Decide); return TRUE; } // set runtimte properties if (SEqual(szCmdName, "set")) { if (SEqual2(pCmdPar, "maxplayer ")) { if (Game.Control.isCtrlHost()) { if (atoi(pCmdPar + 10) == 0 && !SEqual(pCmdPar + 10, "0")) { Log("Syntax: /set maxplayer count"); return FALSE; } Game.Control.DoInput( CID_Set, new C4ControlSet(C4CVT_MaxPlayer, atoi(pCmdPar + 10)), CDT_Decide); return TRUE; } } if (SEqual2(pCmdPar, "comment ") || SEqual(pCmdPar, "comment")) { if (!Game.Network.isEnabled() || !Game.Network.isHost()) return FALSE; // Set in configuration, update reference Config.Network.Comment.CopyValidated(pCmdPar[7] ? (pCmdPar + 8) : ""); Game.Network.InvalidateReference(); Log(LoadResStr("IDS_NET_COMMENTCHANGED")); return TRUE; } if (SEqual2(pCmdPar, "password ") || SEqual(pCmdPar, "password")) { if (!Game.Network.isEnabled() || !Game.Network.isHost()) return FALSE; Game.Network.SetPassword(pCmdPar[8] ? (pCmdPar + 9) : NULL); if (pLobby) pLobby->UpdatePassword(); return TRUE; } if (SEqual2(pCmdPar, "faircrew ")) { if (!Game.Control.isCtrlHost() || Game.Parameters.isLeague()) return FALSE; C4ControlSet *pSet = NULL; if (SEqual(pCmdPar + 9, "on")) pSet = new C4ControlSet(C4CVT_FairCrew, Config.General.FairCrewStrength); else if (SEqual(pCmdPar + 9, "off")) pSet = new C4ControlSet(C4CVT_FairCrew, -1); else if (isdigit((unsigned char)pCmdPar[9])) pSet = new C4ControlSet(C4CVT_FairCrew, atoi(pCmdPar + 9)); else return FALSE; Game.Control.DoInput(CID_Set, pSet, CDT_Decide); return TRUE; } // unknown property return FALSE; } // get szen from network folder - not in lobby; use res tab there if (SEqual(szCmdName, "netgetscen")) { if (Game.Network.isEnabled() && !Game.Network.isHost() && !pLobby) { const C4Network2ResCore *pResCoreScen = Game.Parameters.Scenario.getResCore(); if (pResCoreScen) { C4Network2Res::Ref pScenario = Game.Network.ResList.getRefRes(pResCoreScen->getID()); if (pScenario) if (C4Group_CopyItem( pScenario->getFile(), Config.AtExePath(GetFilename(Game.ScenarioFilename)))) { LogF(LoadResStr("IDS_MSG_CMD_NETGETSCEN_SAVED"), Config.AtExePath(GetFilename(Game.ScenarioFilename))); return TRUE; } } } return FALSE; } // clear message board if (SEqual(szCmdName, "clear")) { // lobby if (pLobby) { pLobby->ClearLog(); } // fullscreen else if (Game.GraphicsSystem.MessageBoard.Active) Game.GraphicsSystem.MessageBoard.ClearLog(); else { // EM mode Console.ClearLog(); } return TRUE; } // kick client if (SEqual(szCmdName, "kick")) { if (Game.Network.isEnabled() && Game.Network.isHost()) { // find client C4Client *pClient = Game.Clients.getClientByName(pCmdPar); if (!pClient) { LogF(LoadResStr("IDS_MSG_CMD_NOCLIENT"), pCmdPar); return FALSE; } // league: Kick needs voting if (Game.Parameters.isLeague() && Game.Players.GetAtClient(pClient->getID())) Game.Network.Vote(VT_Kick, true, pClient->getID()); else // add control Game.Clients.CtrlRemove(pClient, LoadResStr("IDS_MSG_KICKFROMMSGBOARD")); } return TRUE; } // set fast mode if (SEqual(szCmdName, "fast")) { if (!Game.IsRunning) return FALSE; if (Game.Parameters.isLeague()) { Log(LoadResStr("IDS_LOG_COMMANDNOTALLOWEDINLEAGUE")); return FALSE; } int32_t iFS; if ((iFS = atoi(pCmdPar)) == 0) return FALSE; // set frameskip and fullspeed flag Game.FrameSkip = BoundBy<int32_t>(iFS, 1, 500); Game.FullSpeed = TRUE; // start calculation immediatly Application.NextTick(false); return TRUE; } // reset fast mode if (SEqual(szCmdName, "slow")) { if (!Game.IsRunning) return FALSE; Game.FullSpeed = FALSE; Game.FrameSkip = 1; return TRUE; } if (SEqual(szCmdName, "nodebug")) { if (!Game.IsRunning) return FALSE; Game.Control.DoInput(CID_Set, new C4ControlSet(C4CVT_AllowDebug, false), CDT_Decide); return TRUE; } if (SEqual(szCmdName, "msgboard")) { if (!Game.IsRunning) return FALSE; // get line cnt int32_t iLineCnt = BoundBy(atoi(pCmdPar), 0, 20); if (iLineCnt == 0) Game.GraphicsSystem.MessageBoard.ChangeMode(2); else if (iLineCnt == 1) Game.GraphicsSystem.MessageBoard.ChangeMode(0); else { Game.GraphicsSystem.MessageBoard.iLines = iLineCnt; Game.GraphicsSystem.MessageBoard.ChangeMode(1); } return TRUE; } // kick/activate/deactivate/observer if (SEqual(szCmdName, "activate") || SEqual(szCmdName, "deactivate") || SEqual(szCmdName, "observer")) { if (!Game.Network.isEnabled() || !Game.Network.isHost()) { Log(LoadResStr("IDS_MSG_CMD_HOSTONLY")); return FALSE; } // search for client C4Client *pClient = Game.Clients.getClientByName(pCmdPar); if (!pClient) { LogF(LoadResStr("IDS_MSG_CMD_NOCLIENT"), pCmdPar); return FALSE; } // what to do? C4ControlClientUpdate *pCtrl = NULL; if (szCmdName[0] == 'a') // activate pCtrl = new C4ControlClientUpdate(pClient->getID(), CUT_Activate, true); else if (szCmdName[0] == 'd' && !Game.Parameters.isLeague()) // deactivate pCtrl = new C4ControlClientUpdate(pClient->getID(), CUT_Activate, false); else if (szCmdName[0] == 'o' && !Game.Parameters.isLeague()) // observer pCtrl = new C4ControlClientUpdate(pClient->getID(), CUT_SetObserver); // perform it if (pCtrl) Game.Control.DoInput(CID_ClientUpdate, pCtrl, CDT_Sync); else Log(LoadResStr("IDS_LOG_COMMANDNOTALLOWEDINLEAGUE")); return TRUE; } // control mode if (SEqual(szCmdName, "centralctrl") || SEqual(szCmdName, "decentralctrl") || SEqual(szCmdName, "asyncctrl")) { if (!Game.Network.isEnabled() || !Game.Network.isHost()) { Log(LoadResStr("IDS_MSG_CMD_HOSTONLY")); return FALSE; } if (Game.Parameters.isLeague() && *szCmdName == 'a') { Log(LoadResStr("IDS_LOG_COMMANDNOTALLOWEDINLEAGUE")); return FALSE; } Game.Network.SetCtrlMode( *szCmdName == 'c' ? CNM_Central : *szCmdName == 'd' ? CNM_Decentral : CNM_Async); return TRUE; } // show chart if (Game.IsRunning) if (SEqual(szCmdName, "chart")) return Game.ToggleChart(); // custom command C4MessageBoardCommand *pCmd; if (Game.IsRunning) if (pCmd = GetCommand(szCmdName)) { StdStrBuf Script, CmdScript; // replace %player% by calling player number if (SSearch(pCmd->Script, "%player%")) { int32_t iLocalPlr = NO_OWNER; C4Player *pLocalPlr = Game.Players.GetLocalByIndex(0); if (pLocalPlr) iLocalPlr = pLocalPlr->Number; StdStrBuf sLocalPlr; sLocalPlr.Format("%d", iLocalPlr); CmdScript.Copy(pCmd->Script); CmdScript.Replace("%player%", sLocalPlr.getData()); } else { CmdScript.Ref(pCmd->Script); } // insert parameters if (SSearch(CmdScript.getData(), "%d")) { // make sure it's a number by converting Script.Format(CmdScript.getData(), (int)atoi(pCmdPar)); } else if (SSearch(CmdScript.getData(), "%s")) { // Unrestricted parameters? // That's kind of a security risk as it will allow anyone to execute // code switch (pCmd->eRestriction) { case C4MessageBoardCommand::C4MSGCMDR_Escaped: { // escape strings StdStrBuf Par; Par.Copy(pCmdPar); Par.EscapeString(); // compose script Script.Format(CmdScript.getData(), Par.getData()); } break; case C4MessageBoardCommand::C4MSGCMDR_Plain: // unescaped Script.Format(CmdScript.getData(), pCmdPar); break; case C4MessageBoardCommand::C4MSGCMDR_Identifier: { // only allow identifier-characters StdStrBuf Par; while (IsIdentifier(*pCmdPar) || isspace((unsigned char)*pCmdPar)) Par.AppendChar(*pCmdPar++); // compose script Script.Format(CmdScript.getData(), Par.getData()); } break; } } else Script = CmdScript.getData(); // add script Game.Control.DoInput(CID_Script, new C4ControlScript(Script.getData()), CDT_Decide); // ok return TRUE; } // unknown command StdStrBuf sErr; sErr.Format(LoadResStr("IDS_ERR_UNKNOWNCMD"), szCmdName); if (pLobby) pLobby->OnError(sErr.getData()); else Log(sErr.getData()); return FALSE; }
void StdCompilerINIRead::CreateNameTree() { FreeNameTree(); // Create root node pName = pNameRoot = new NameNode(); // No input? Stop if (!Buf) return; // Start scanning pPos = Buf.getPtr(0); while (*pPos) { // Go over whitespace int iIndent = 0; while (*pPos == ' ' || *pPos == '\t') { pPos++; iIndent++; } // Name/Section? bool fSection = *pPos == '[' && isalpha((unsigned char)*(pPos+1)); if (fSection || isalpha((unsigned char)*pPos)) { // Treat values as if they had more indention // (so they become children of sections on the same level) if (!fSection) iIndent++; else pPos++; // Go up in tree structure if there is less indention while (pName->Parent && pName->Indent >= iIndent) pName = pName->Parent; // Copy name StdStrBuf Name; while (isalnum((unsigned char)*pPos) || *pPos == ' ' || *pPos == '_') Name.AppendChar(*pPos++); while (*pPos == ' ' || *pPos == '\t') pPos++; if ( *pPos != (fSection ? ']' : '=') ) // Warn, ignore Warn(isprint((unsigned char)*pPos) ? "Unexpected character ('%c'): %s ignored" : "Unexpected character ('0x%02x'): %s ignored", unsigned(*pPos), fSection ? "section" : "value"); else { pPos++; // Create new node NameNode *pPrev = pName->LastChild; pName = pName->LastChild = (pName->LastChild ? pName->LastChild->NextChild : pName->FirstChild) = new NameNode(pName); pName->PrevChild = pPrev; pName->Name.Take(std::move(Name)); pName->Pos = pPos; pName->Indent = iIndent; pName->Section = fSection; // Values don't have children (even if the indention looks like it) if (!fSection) pName = pName->Parent; } } // Skip line while (*pPos && (*pPos != '\n' && *pPos != '\r')) pPos++; while (*pPos == '\n' || *pPos == '\r') pPos++; } // Set pointer back pName = pNameRoot; }
BOOL C4UpdatePackage::MkUp(C4Group *pGrp1, C4Group *pGrp2, C4GroupEx *pUpGrp, BOOL *fModified) { // (CAUTION: pGrp1 may be NULL - that means that there is no counterpart for // Grp2 // in the base group) // compare headers if (!pGrp1 || pGrp1->GetCreation() != pGrp2->GetCreation() || pGrp1->GetOriginal() != pGrp2->GetOriginal() || !SEqual(pGrp1->GetMaker(), pGrp2->GetMaker()) || !SEqual(pGrp1->GetPassword(), pGrp2->GetPassword())) *fModified = TRUE; // set header pUpGrp->SetHead(*pGrp2); // compare entries char strItemName[_MAX_PATH], strItemName2[_MAX_PATH]; StdStrBuf EntryList; strItemName[0] = strItemName2[0] = 0; pGrp2->ResetSearch(); if (!*fModified) pGrp1->ResetSearch(); int iChangedEntries = 0; while (pGrp2->FindNextEntry("*", strItemName, NULL, NULL, !!strItemName[0])) { // add to entry list if (!!EntryList) EntryList.AppendChar('|'); EntryList.AppendFormat("%s=%d", strItemName, pGrp2->EntryTime(strItemName)); // no modification detected yet? then check order if (!*fModified) { if (!pGrp1->FindNextEntry("*", strItemName2, NULL, NULL, !!strItemName2[0])) *fModified = TRUE; else if (!SEqual(strItemName, strItemName2)) *fModified = TRUE; } // TODO: write DeleteEntries.txt // a child group? C4GroupEx ChildGrp2; if (ChildGrp2.OpenAsChild(pGrp2, strItemName)) { // open in Grp1 C4Group *pChildGrp1 = new C4GroupEx(); if (!pGrp1 || !pChildGrp1->OpenAsChild(pGrp1, strItemName)) { delete pChildGrp1; pChildGrp1 = NULL; } // open group for update data C4GroupEx UpdGroup; char strTempGroupName[_MAX_FNAME + 1]; strTempGroupName[0] = 0; if (!UpdGroup.OpenAsChild(pUpGrp, strItemName)) { // create new group (may be temporary) // SCopy(GetCfg()->AtTempPath("~upd"), strTempGroupName, _MAX_FNAME); MakeTempFilename(strTempGroupName); if (!UpdGroup.Open(strTempGroupName, TRUE)) { delete pChildGrp1; WriteLog("Error: could not create temp group\n"); return FALSE; } } // do nested MkUp-search BOOL Modified = FALSE; BOOL fSuccess = MkUp(pChildGrp1, &ChildGrp2, &UpdGroup, &Modified); // sort & close extern const char **C4Group_SortList; UpdGroup.SortByList(C4Group_SortList, ChildGrp2.GetName()); UpdGroup.Close(FALSE); // check entry times if (!pGrp1 || (pGrp1->EntryTime(strItemName) != pGrp2->EntryTime(strItemName))) Modified = TRUE; // add group (if modified) if (fSuccess && Modified) { if (strTempGroupName[0]) if (!pUpGrp->Move(strTempGroupName, strItemName)) { WriteLog("Error: could not add modified group\n"); return FALSE; } // copy core pUpGrp->SaveEntryCore(*pGrp2, strItemName); pUpGrp->SetSavedEntryCore(strItemName); // got a modification in a subgroup *fModified = TRUE; iChangedEntries++; } else // delete group (do not remove groups that existed before!) if (strTempGroupName[0]) if (remove(strTempGroupName)) if (rmdir(strTempGroupName)) { WriteLog("Error: could not delete temporary directory\n"); return FALSE; } delete pChildGrp1; } else { // compare them (size & crc32) if (!pGrp1 || pGrp1->EntrySize(strItemName) != pGrp2->EntrySize(strItemName) || pGrp1->EntryCRC32(strItemName) != pGrp2->EntryCRC32(strItemName)) { BOOL fCopied = FALSE; // save core (EntryCRC32 might set additional fields) pUpGrp->SaveEntryCore(*pGrp2, strItemName); // already in update grp? if (pUpGrp->EntryTime(strItemName) != pGrp2->EntryTime(strItemName) || pUpGrp->EntrySize(strItemName) != pGrp2->EntrySize(strItemName) || pUpGrp->EntryCRC32(strItemName) != pGrp2->EntryCRC32(strItemName)) { // copy it if (!C4Group_CopyEntry(pGrp2, pUpGrp, strItemName)) { WriteLog("Error: could not add changed entry to update group\n"); return FALSE; } // set entry core pUpGrp->SetSavedEntryCore(strItemName); // modified... *fModified = TRUE; fCopied = TRUE; } iChangedEntries++; WriteLog("%s\\%s: update%s\n", pGrp2->GetFullName().getData(), strItemName, fCopied ? "" : " (already in group)"); } } } // write entries list (always) if (!pUpGrp->Add(C4CFN_UpdateEntries, EntryList, FALSE, TRUE)) { WriteLog("Error: could not save entry list!"); return FALSE; } if (iChangedEntries > 0) WriteLog("%s: %d/%d changed (%s)\n", pGrp2->GetFullName().getData(), iChangedEntries, pGrp2->EntryCount(), *fModified ? "update" : "skip"); // success return TRUE; }