void C4SDefinitions::SetModules(const char *szList, const char *szRelativeToPath, const char *szRelativeToPath2) { int32_t cnt; // Empty list: local only if (!SModuleCount(szList)) { LocalOnly=TRUE; for (cnt=0; cnt<C4S_MaxDefinitions; cnt++) Definition[cnt][0]=0; return; } // Set list LocalOnly=FALSE; for (cnt=0; cnt<C4S_MaxDefinitions; cnt++) { SGetModule(szList,cnt,Definition[cnt],_MAX_PATH); // Make relative path if (szRelativeToPath && *szRelativeToPath) if (SEqualNoCase(Definition[cnt],szRelativeToPath,SLen(szRelativeToPath))) SCopy(Definition[cnt]+SLen(szRelativeToPath),Definition[cnt]); if (szRelativeToPath2 && *szRelativeToPath2) if (SEqualNoCase(Definition[cnt],szRelativeToPath2,SLen(szRelativeToPath2))) SCopy(Definition[cnt]+SLen(szRelativeToPath2),Definition[cnt]); } }
void C4Language::LoadInfos(C4Group &hGroup) { char strEntry[_MAX_FNAME + 1]; char *strTable; // Look for language string tables hGroup.ResetSearch(); while (hGroup.FindNextEntry(C4CFN_Language, strEntry)) // For now, we will only load info on the first string table found for a given // language code as there is currently no handling for selecting different string tables // of the same code - the system always loads the first string table found for a given code if (!FindInfo(GetFilenameOnly(strEntry) + SLen(GetFilenameOnly(strEntry)) - 2)) // Load language string table if (hGroup.LoadEntry(strEntry, &strTable, 0, 1)) { // New language info C4LanguageInfo *pInfo = new C4LanguageInfo; // Get language code by entry name SCopy(GetFilenameOnly(strEntry) + SLen(GetFilenameOnly(strEntry)) - 2, pInfo->Code, 2); SCapitalize(pInfo->Code); // Get language name, info, fallback from table CopyResStr("IDS_LANG_NAME", strTable, pInfo->Name); CopyResStr("IDS_LANG_INFO", strTable, pInfo->Info); CopyResStr("IDS_LANG_FALLBACK", strTable, pInfo->Fallback); // Safety: pipe character is not allowed in any language info string SReplaceChar(pInfo->Name, '|', ' '); SReplaceChar(pInfo->Info, '|', ' '); SReplaceChar(pInfo->Fallback, '|', ' '); // Delete table delete [] strTable; // Add info to list pInfo->Next = Infos; Infos = pInfo; } }
bool C4Network2Res::SetByCore(const C4Network2ResCore &nCore, bool fSilent, const char *szAsFilename, int32_t iRecursion) // by main thread { StdStrBuf sFilename; // try open local file const char *szFilename = szAsFilename ? szAsFilename : GetC4Filename(nCore.getFileName()); if (SetByFile(szFilename, false, nCore.getType(), nCore.getID(), nCore.getFileName(), fSilent)) { // check contents checksum if (Core.getContentsCRC() == nCore.getContentsCRC()) { // set core fDirty = true; Core = nCore; // ok then return true; } } // get and search for filename without specified folder (e.g., Castle.ocs when the opened game is Easy.ocf\Castle.ocs) const char *szFilenameOnly = GetFilename(szFilename); const char *szFilenameC4 = GetC4Filename(szFilename); if (szFilenameOnly != szFilenameC4) { sFilename.Copy(szFilename, SLen(szFilename) - SLen(szFilenameC4)); sFilename.Append(szFilenameOnly); if (SetByCore(nCore, fSilent, szFilenameOnly, Config.Network.MaxResSearchRecursion)) return true; } // if it could still not be set, try within all folders of root (ignoring special folders), and try as file outside the folder // but do not recurse any deeper than set by config (default: One folder) if (iRecursion >= Config.Network.MaxResSearchRecursion) return false; StdStrBuf sSearchPath; const char *szSearchPath; if (!iRecursion) szSearchPath = Config.General.ExePath.getData(); else { sSearchPath.Copy(szFilename, SLen(szFilename) - SLen(szFilenameC4)); szSearchPath = sSearchPath.getData(); } StdStrBuf sNetPath; sNetPath.Copy(Config.Network.WorkPath); char *szNetPath = sNetPath.GrabPointer(); TruncateBackslash(szNetPath); sNetPath.Take(szNetPath); for (DirectoryIterator i(szSearchPath); *i; ++i) if (DirectoryExists(*i)) if (!*GetExtension(*i)) // directories without extension only if (!szNetPath || !*szNetPath || !ItemIdentical(*i, szNetPath)) // ignore network path { // search for complete name at subpath (e.g. MyFolder\Easy.ocf\Castle.ocs) sFilename.Format("%s%c%s", *i, DirectorySeparator, szFilenameC4); if (SetByCore(nCore, fSilent, sFilename.getData(), iRecursion + 1)) return true; } // file could not be found locally return false; }
void C4GraphicsOverlay::Read(const char **ppInput) { // deprecated assert(false && "C4GraphicsOverlay::Read: deprecated"); #if 0 const char *szReadFrom = *ppInput; // defaults eMode = MODE_None; pSourceGfx = NULL; *Action=0; dwBlitMode = 0; iPhase = 0; iID=0; // read ID SCopyUntil(szReadFrom, OSTR, ',', C4MaxName); szReadFrom += strlen(OSTR); if (*szReadFrom) ++szReadFrom; sscanf(OSTR, "%i", &iID); // read C4ID::Gfxname int32_t iLineLength = SLen(szReadFrom); // not C4ID::Name? if (iLineLength < 6 || szReadFrom[4]!=':' || szReadFrom[5]!=':') { DebugLog("C4Compiler error: Malformed graphics overlay definition!"); return; } // get ID char id[5]; SCopy(szReadFrom, id, 4); szReadFrom += 6; C4Def *pSrcDef = ::Definitions.ID2Def(C4Id(id)); // defaults to NULL for unloaded def if (pSrcDef) { char GfxName[C4MaxName+1]; SCopyUntil(szReadFrom, GfxName, ',', C4MaxName); szReadFrom += strlen(GfxName); if (*szReadFrom) ++szReadFrom; // get graphics - "C4ID::" leads to *szLine == NULL, and thus the default graphic of pSrcDef! pSourceGfx = pSrcDef->Graphics.Get(GfxName); } // read mode DWORD dwRead; SCopyUntil(szReadFrom, OSTR, ',', C4MaxName); szReadFrom += strlen(OSTR); if (*szReadFrom) ++szReadFrom; sscanf(OSTR, "%i", &dwRead); eMode = (Mode) dwRead; // read action SCopyUntil(szReadFrom, Action, ',', C4MaxName); szReadFrom += strlen(Action); if (*szReadFrom) ++szReadFrom; // read blit mode SCopyUntil(szReadFrom, OSTR, ',', C4MaxName); szReadFrom += strlen(OSTR); if (*szReadFrom) ++szReadFrom; sscanf(OSTR, "%i", &dwBlitMode); // read phase SCopyUntil(szReadFrom, OSTR, ',', C4MaxName); szReadFrom += strlen(OSTR); if (*szReadFrom) ++szReadFrom; sscanf(OSTR, "%i", &iPhase); // read transform if (*szReadFrom) ++szReadFrom; // '(' int32_t iScanCnt = sscanf(szReadFrom, "%f,%f,%f,%f,%f,%f,%d", &Transform.mat[0], &Transform.mat[1], &Transform.mat[2], &Transform.mat[3], &Transform.mat[4], &Transform.mat[5], &Transform.FlipDir); if (iScanCnt != 7) { DebugLog("C4Compiler: malformed C4CV_Transform"); } iScanCnt = SCharPos(')', szReadFrom); if (iScanCnt>=0) szReadFrom += iScanCnt+1; // assign ptr immediately after read overlay *ppInput = szReadFrom; // update used facet according to read data UpdateFacet(); #endif }
bool LogSilent(const char *szMessage, bool fConsole) { if (!Application.AssertMainThread()) return false; // security if (!szMessage) return false; // add timestamp time_t timenow; time(&timenow); StdStrBuf TimeMessage; TimeMessage.SetLength(11 + SLen(szMessage) + 1); strftime(TimeMessage.getMData(), 11 + 1, "[%H:%M:%S] ", localtime(&timenow)); // output until all data is written const char *pSrc = szMessage; do { // timestamp will always be that length char *pDest = TimeMessage.getMData() + 11; // copy rest of message, skip tags CMarkup Markup(false); while (*pSrc) { Markup.SkipTags(&pSrc); // break on crlf while (*pSrc == '\r') pSrc++; if (*pSrc == '\n') { pSrc++; break; } // copy otherwise if (*pSrc) *pDest++ = *pSrc++; } *pDest++ = '\n'; *pDest = '\0'; #ifdef HAVE_ICONV StdStrBuf Line = Languages.IconvSystem(TimeMessage.getData()); #else StdStrBuf &Line = TimeMessage; #endif // Save into log file if (C4LogFile) { fputs(Line.getData(), C4LogFile); fflush(C4LogFile); } // Write to console if (fConsole || Game.Verbose) { #if defined(_DEBUG) && defined(_WIN32) // debug: output to VC console OutputDebugString(Line.getData()); #endif fputs(Line.getData(), stdout); fflush(stdout); } } while (*pSrc); return true; }
bool C4MaterialMap::LoadEnumeration(C4Group &hGroup) { // Load enumeration map (from savegame), succeed if not present StdStrBuf mapbuf; if (!hGroup.LoadEntryString(C4CFN_MatMap, &mapbuf)) return true; // Sort material array by enumeration map, fail if some missing const char *csearch; char cmatname[C4M_MaxName+1]; int32_t cmat=0; if (!(csearch = SSearch(mapbuf.getData(),"[Enumeration]"))) { return false; } csearch=SAdvanceSpace(csearch); while (IsIdentifier(*csearch)) { SCopyIdentifier(csearch,cmatname,C4M_MaxName); if (!SortEnumeration(cmat,cmatname)) { // Output error message! return false; } cmat++; csearch+=SLen(cmatname); csearch=SAdvanceSpace(csearch); } return true; }
bool C4Application::SetGameFont(const char *szFontFace, int32_t iFontSize) { #ifndef USE_CONSOLE // safety if (!szFontFace || !*szFontFace || iFontSize<1 || SLen(szFontFace)>=static_cast<int>(sizeof Config.General.RXFontName)) return false; // first, check if the selected font can be created at all // check regular font only - there's no reason why the other fonts couldn't be created CStdFont TestFont; if (!::FontLoader.InitFont(&TestFont, szFontFace, C4FontLoader::C4FT_Main, iFontSize, &::GraphicsResource.Files)) return false; // OK; reinit all fonts StdStrBuf sOldFont; sOldFont.Copy(Config.General.RXFontName); int32_t iOldFontSize = Config.General.RXFontSize; SCopy(szFontFace, Config.General.RXFontName); Config.General.RXFontSize = iFontSize; if (!::GraphicsResource.InitFonts() || !C4Startup::Get()->Graphics.InitFonts()) { // failed :o // shouldn't happen. Better restore config. SCopy(sOldFont.getData(), Config.General.RXFontName); Config.General.RXFontSize = iOldFontSize; return false; } #endif // save changes return true; }
void C4Network2IRCClient::OnMessage(bool fNotice, const char *szSender, const char *szTarget, const char *szText) { // Find channel, if not private. C4Network2IRCChannel *pChan = NULL; if(!SEqualNoCase(szTarget, Nick.getData())) pChan = getChannel(szTarget); // CTCP tagged data? const char X_DELIM = '\001'; if(szText[0] == X_DELIM) { // Process messages (it's very rarely more than one, but the spec allows it) const char *pMsg = szText + 1; while(*pMsg) { // Find end const char *pEnd = strchr(pMsg, X_DELIM); if(!pEnd) pEnd = pMsg + SLen(pMsg); // Copy CTCP query/reply, get tag StdStrBuf CTCP; CTCP.Copy(pMsg, pEnd - pMsg); StdStrBuf Tag; Tag.CopyUntil(CTCP.getData(), ' '); const char *szData = SSearch(CTCP.getData(), " "); StdStrBuf Sender; Sender.CopyUntil(szSender, '!'); // Process if(SEqualNoCase(Tag.getData(), "ACTION")) PushMessage(MSG_Action, szSender, szTarget, szData ? szData : ""); if(SEqualNoCase(Tag.getData(), "FINGER") && !fNotice) { StdStrBuf Answer; if(Config.Registered()) { Answer = Config.GetRegistrationData("Cuid"); } else { Answer = LoadResStr("IDS_PRC_UNREGUSER"); } Send("NOTICE", FormatString("%s :%cFINGER %s%c", Sender.getData(), X_DELIM, Answer.getData(), X_DELIM).getData()); } if(SEqualNoCase(Tag.getData(), "VERSION") && !fNotice) Send("NOTICE", FormatString("%s :%cVERSION " C4ENGINECAPTION ":" C4VERSION ":" C4_OS "%c", Sender.getData(), X_DELIM, X_DELIM).getData()); if(SEqualNoCase(Tag.getData(), "PING") && !fNotice) Send("NOTICE", FormatString("%s :%cPING %s%c", Sender.getData(), X_DELIM, szData, X_DELIM).getData()); // Get next message pMsg = pEnd; if(*pMsg == X_DELIM) pMsg++; } } // Standard message (not CTCP tagged): Push else PushMessage(fNotice ? MSG_Notice : MSG_Message, szSender, szTarget, szText); }
String::String(StringBuffer& b) { int l = b.GetLength(); if(l <= 14) { Zero(); memcpy(chr, b.begin, l); SLen() = l; b.Free(); } else { ptr = b.begin; ptr[l] = 0; SLen() = 15; LLen() = l; chr[KIND] = min(b.GetAlloc(), 255); } b.Zero(); }
String::String(StringBuffer& b) { int l = b.GetLength(); if(l <= 14) { Zero(); memcpy(chr, b.begin, l); SLen() = l; b.Free(); } else { ptr = b.begin; ptr[l] = 0; SLen() = 15; LLen() = l; chr[KIND] = b.limit - b.begin == 31 ? MEDIUM : REF; } b.Zero(); }
bool C4ChatInputDialog::KeyCompleteNick() { if (!pEdit) return false; char IncompleteNick[256 + 1]; // get current word in edit if (!pEdit->GetCurrentWord(IncompleteNick, 256)) return false; if (!*IncompleteNick) return false; C4Player *plr = Game.Players.First; while (plr) { // Compare name and input if (SEqualNoCase(plr->GetName(), IncompleteNick, SLen(IncompleteNick))) { pEdit->InsertText(plr->GetName() + SLen(IncompleteNick), true); return true; } else plr = plr->Next; } // no match found return false; }
void String0::Cat(const char *s, int len) { if(IsSmall()) { if(SLen() + len < 14) { memcpy(chr + SLen(), s, len); SLen() += len; chr[SLen()] = 0; return; } } else if((int)LLen() + len < LAlloc() && !IsSharedRef()) { memcpy(ptr + LLen(), s, len); LLen() += len; ptr[LLen()] = 0; return; } Insert(GetCount(), len, s); }
void C4ValueMapNames::ChangeNameList(const char **pnNames, int32_t *pnExtra, int32_t nSize) { // safe old name list char **pOldNames = pNames; int32_t *pOldExtra = pExtra; int32_t iOldSize = iSize; // create new lists pNames = new char *[nSize]; pExtra = new int32_t [nSize]; // copy names int32_t i; for(i = 0; i < nSize; i++) { pNames[i] = new char [SLen(pnNames[i]) + 1]; SCopy(pnNames[i], pNames[i], SLen(pnNames[i]) + 1); if(pnExtra) pExtra[i] = pnExtra[i]; } if(!pnExtra) ZeroMem(pExtra, sizeof (*pExtra) * nSize); // set new size iSize = nSize; // call OnNameListChanged list for all "child" lists C4ValueMapData *pAktData = pFirst; while(pAktData) { pAktData->OnNameListChanged(const_cast<const char **>(pOldNames), iOldSize); pAktData = pAktData->pNext; } // delete old list for(i = 0; i < iOldSize; i++) delete[] pOldNames[i]; delete[] pOldNames; delete[] pOldExtra; // ok. }
void String0::Set(const char *s, int len) { w[0] = w[1] = w[2] = w[3] = 0; switch(len) { #define MOV(x) case x: chr[x - 1] = s[x - 1]; MOV(14) MOV(13) MOV(12) MOV(11) MOV(10) MOV(9) MOV(8) MOV(7) MOV(6) MOV(5) MOV(4) MOV(3) MOV(2) MOV(1) case 0: SLen() = len; break; default: char *p = Alloc(len, chr[KIND]); memcpy(p, s, len); p[len] = 0; ptr = p; LLen() = len; SLen() = 15; }; }
void String0::Remove(int pos, int count) { ASSERT(pos >= 0 && count >= 0 && pos + count <= GetCount()); UnShare(); char *s = (char *)Begin(); memmove(s + pos, s + pos + count, GetCount() - pos - count + 1); if(IsSmall()) SetSLen(SLen() - count); else LLen() -= count; }
bool C4MaterialMap::SaveEnumeration(C4Group &hGroup) { char *mapbuf = new char [1000]; mapbuf[0]=0; SAppend("[Enumeration]",mapbuf); SAppend(LineFeed,mapbuf); for (int32_t cnt=0; cnt<Num; cnt++) { SAppend(Map[cnt].Name,mapbuf); SAppend(LineFeed,mapbuf); } return hGroup.Add(C4CFN_MatMap,mapbuf,SLen(mapbuf),false,true); }
static bool Helper(const char *szPath) { if (szPath[SLen(szPath)-1] == '.') return false; if (iSize > iMaxSize) return false; if (DirectoryExists(szPath)) ForEachFile(szPath, &Helper); else if (FileExists(szPath)) iSize += FileSize(szPath); return true; }
void String0::LCat(int c) { if(IsSmall()) { qword *x = (qword *)MAlloc_S(); x[0] = q[0]; x[1] = q[1]; LLen() = SLen(); SLen() = 15; chr[KIND] = MEDIUM; qptr = x; } int l = LLen(); if(IsRef() ? !IsShared() && l < (int)Ref()->alloc : l < 31) { ptr[l] = c; ptr[LLen() = l + 1] = 0; } else { char *s = Insert(l, 1, NULL); s[0] = c; s[1] = 0; } }
force_inline void String0::Set(const char *s, int len) { Clear(); if(len < 14) { SVO_MEMCPY(chr, s, len); SLen() = len; Dsyn(); return; } SetL(s, len); Dsyn(); }
bool C4RankSystem::Check(int iRank, const char *szDefRankName) { #ifdef _WIN32 char keyname[30]; sprintf(keyname,"Rank%03d",iRank); if (!GetRegistryString(Register,keyname).isNull()) return false; if (!szDefRankName || (SLen(szDefRankName)>C4MaxName)) return false; return SetRegistryString(Register,keyname,szDefRankName); #else return true; #endif }
void SetClientPrefix(char *szFilename, const char *szClient) { char szTemp[1024+1]; // Compose prefix char szPrefix[1024+1]; SCopy(szClient,szPrefix); SAppendChar('-',szPrefix); // Prefix already set? SCopy(GetFilename(szFilename),szTemp,SLen(szPrefix)); if (SEqualNoCase(szTemp,szPrefix)) return; // Insert prefix SCopy(GetFilename(szFilename),szTemp); SCopy(szPrefix,GetFilename(szFilename)); SAppend(szTemp,szFilename); }
BOOL C4RankSystem::Check(int iRank, const char *szDefRankName) { #ifdef _WIN32 char rankname[C4MaxName+1],keyname[30]; sprintf(keyname,"Rank%03d",iRank); if (GetRegistryString(Register,keyname,rankname,C4MaxName+1)) return FALSE; if (!szDefRankName || (SLen(szDefRankName)>C4MaxName)) return FALSE; return SetRegistryString(Register,keyname,szDefRankName); #else return TRUE; #endif }
char *String0::Insert(int pos, int count, const char *s) { ASSERT(pos >= 0 && count >= 0 && pos <= GetCount()); int len = GetCount(); int newlen = len + count; char *str = (char *)Begin(); if(newlen < GetAlloc() && !IsSharedRef()/* && !(s >= str && s <= str + len)*/) { if(s >= str + pos && s <= str + len) s += count; if(pos < len) memmove(str + pos + count, str + pos, len - pos); if(IsSmall()) SLen() = newlen; else LLen() = newlen; str[newlen] = 0; if(s) memcpy(str + pos, s, count); return str + pos; } char kind; char *p = Alloc(max(2 * len, newlen), kind); if(pos > 0) memcpy(p, str, pos); if(pos < len) memcpy(p + pos + count, str + pos, len - pos); if(s) memcpy(p + pos, s, count); p[newlen] = 0; Free(); ptr = p; LLen() = newlen; SLen() = 15; chr[KIND] = kind; return ptr + pos; }
bool EraseItemSafe(const char *szFilename) { char Filename[_MAX_PATH+1]; SCopy(szFilename, Filename, _MAX_PATH); Filename[SLen(Filename)+1]=0; SHFILEOPSTRUCTW shs; shs.hwnd=0; shs.wFunc=FO_DELETE; shs.pFrom=GetWideChar(Filename); shs.pTo=NULL; shs.fFlags=FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_SILENT; shs.fAnyOperationsAborted=false; shs.hNameMappings=0; shs.lpszProgressTitle=NULL; return !SHFileOperationW(&shs); }
void C4GraphicsSystem::FlashMessage(const char *szMessage) { // Store message SCopy(szMessage, FlashMessageText, C4MaxTitle); // Calculate message time FlashMessageTime = SLen(FlashMessageText) * 2; // Initial position FlashMessageX = -1; FlashMessageY = 10; // Upper board active: stay below upper board if (Config.Graphics.UpperBoard) FlashMessageY += C4UpperBoardHeight; // More than one viewport: try to stay below portraits etc. if (GetViewportCount() > 1) FlashMessageY += 64; // New flash message: redraw background (might be drawing one message on top of another) InvalidateBg(); }
void C4FileMonitor::HandleNotify(const char *szDir, const _FILE_NOTIFY_INFORMATION *pNotify) { // Get filename length UINT iCodePage = CP_UTF8; int iFileNameBytes = WideCharToMultiByte(iCodePage, 0, pNotify->FileName, pNotify->FileNameLength / 2, NULL, 0, NULL, NULL); // Set up filename buffer StdCopyStrBuf Path(szDir); Path.AppendChar(DirectorySeparator); Path.Grow(iFileNameBytes); char *pFilename = Path.getMPtr(SLen(Path.getData())); // Convert filename int iWritten = WideCharToMultiByte(iCodePage, 0, pNotify->FileName, pNotify->FileNameLength / 2, pFilename, iFileNameBytes, NULL, NULL); if (iWritten != iFileNameBytes) Path.Shrink(iFileNameBytes+1); // Send notification Application.InteractiveThread.PushEvent(Ev_FileChange, Path.GrabPointer()); }
void C4Network2IRCClient::OnCommand(const char *szSender, const char *szCommand, const char *szParameters) { CStdLock Lock(&CSec); // Numeric command? if(isdigit((unsigned char)*szCommand) && SLen(szCommand) == 3) { OnNumericCommand(szSender, atoi(szCommand), szParameters); return; } // Sender's nick StdStrBuf SenderNick; if(szSender) SenderNick.CopyUntil(szSender, '!'); // Ping? if(SEqualNoCase(szCommand, "PING")) Send("PONG", szParameters); // Message? if(SEqualNoCase(szCommand, "NOTICE") || SEqualNoCase(szCommand, "PRIVMSG")) { // Get target StdStrBuf Target = ircExtractPar(&szParameters); // Get text StdStrBuf Text = ircExtractPar(&szParameters); // Process message OnMessage(SEqualNoCase(szCommand, "NOTICE"), szSender, Target.getData(), Text.getData()); } // Channel join? if(SEqualNoCase(szCommand, "JOIN")) { // Get channel StdStrBuf Channel = ircExtractPar(&szParameters); C4Network2IRCChannel *pChan = AddChannel(Channel.getData()); // Add user pChan->OnJoin(SenderNick.getData()); // Myself? if(SenderNick == Nick) PushMessage(MSG_Status, szSender, Channel.getData(), FormatString(LoadResStr("IDS_MSG_YOUHAVEJOINEDCHANNEL"), Channel.getData()).getData()); else PushMessage(MSG_Status, szSender, Channel.getData(), FormatString(LoadResStr("IDS_MSG_HASJOINEDTHECHANNEL"), SenderNick.getData()).getData()); } // Channel part? if(SEqualNoCase(szCommand, "PART")) { // Get channel StdStrBuf Channel = ircExtractPar(&szParameters); C4Network2IRCChannel *pChan = AddChannel(Channel.getData()); // Get message StdStrBuf Comment = ircExtractPar(&szParameters); // Remove user pChan->OnPart(SenderNick.getData(), Comment.getData()); // Myself? if(SenderNick == Nick) { DeleteChannel(pChan); PushMessage(MSG_Status, szSender, Nick.getData(), FormatString(LoadResStr("IDS_MSG_YOUHAVELEFTCHANNEL"), Channel.getData(), Comment.getData()).getData()); } else PushMessage(MSG_Status, szSender, Channel.getData(), FormatString(LoadResStr("IDS_MSG_HASLEFTTHECHANNEL"), SenderNick.getData(), Comment.getData()).getData()); } // Kick? if(SEqualNoCase(szCommand, "KICK")) { // Get channel StdStrBuf Channel = ircExtractPar(&szParameters); C4Network2IRCChannel *pChan = AddChannel(Channel.getData()); // Get kicked user StdStrBuf Kicked = ircExtractPar(&szParameters); // Get message StdStrBuf Comment = ircExtractPar(&szParameters); // Remove user pChan->OnKick(Kicked.getData(), Comment.getData()); // Myself? if(Kicked == Nick) { DeleteChannel(pChan); PushMessage(MSG_Status, szSender, Nick.getData(), FormatString(LoadResStr("IDS_MSG_YOUWEREKICKEDFROMCHANNEL"), Channel.getData(), Comment.getData()).getData()); } else PushMessage(MSG_Status, szSender, Channel.getData(), FormatString(LoadResStr("IDS_MSG_WASKICKEDFROMTHECHANNEL"), Kicked.getData(), Comment.getData()).getData()); } // Quit? if(SEqualNoCase(szCommand, "QUIT")) { // Get comment StdStrBuf Comment = ircExtractPar(&szParameters); // Format status message StdStrBuf Message = FormatString(LoadResStr("IDS_MSG_HASDISCONNECTED"), SenderNick.getData(), Comment.getData()); // Remove him from all channels for(C4Network2IRCChannel *pChan = pChannels; pChan; pChan = pChan->Next) if(pChan->getUser(SenderNick.getData())) { pChan->OnPart(SenderNick.getData(), "Quit"); PushMessage(MSG_Status, szSender, pChan->getName(), Message.getData()); } } // Topic change? if(SEqualNoCase(szCommand, "TOPIC")) { // Get channel and topic StdStrBuf Channel = ircExtractPar(&szParameters); StdStrBuf Topic = ircExtractPar(&szParameters); // Set topic AddChannel(Channel.getData())->OnTopic(Topic.getData()); // Message PushMessage(MSG_Status, szSender, Channel.getData(), FormatString(LoadResStr("IDS_MSG_CHANGESTHETOPICTO"), SenderNick.getData(), Topic.getData()).getData()); } // Mode? if(SEqualNoCase(szCommand, "MODE")) { // Get all data StdStrBuf Channel = ircExtractPar(&szParameters); StdStrBuf Flags = ircExtractPar(&szParameters); StdStrBuf What = ircExtractPar(&szParameters); // Make sure it's a channel C4Network2IRCChannel *pChan = getChannel(Channel.getData()); if(pChan) // Ask for names, because user prefixes might be out of sync Send("NAMES", Channel.getData()); // Show Message PushMessage(MSG_Status, szSender, Channel.getData(), FormatString(LoadResStr("IDS_MSG_SETSMODE"), SenderNick.getData(), Flags.getData(), What.getData()).getData()); } // Error? if(SEqualNoCase(szCommand, "ERROR")) { // Get message StdStrBuf Message = ircExtractPar(&szParameters); // Push it PushMessage(MSG_Server, szSender, Nick.getData(), Message.getData()); } // Nickchange? if(SEqualNoCase(szCommand, "NICK")) { // Get new nick StdStrBuf NewNick = ircExtractPar(&szParameters); // Format status message StdStrBuf Message = FormatString(LoadResStr("IDS_MSG_ISNOWKNOWNAS"), SenderNick.getData(), NewNick.getData()); // Rename on all channels for(C4Network2IRCChannel *pChan = pChannels; pChan; pChan = pChan->Next) if(pChan->getUser(SenderNick.getData())) { pChan->OnPart(SenderNick.getData(), "Nickchange"); pChan->OnJoin(NewNick.getData()); PushMessage(MSG_Status, szSender, pChan->getName(), Message.getData()); } // Self? if(SenderNick == Nick) Nick = NewNick; } }
void C4Application::ParseCommandLine(int argc, char * argv[]) { StdStrBuf CmdLine("Command line:"); for(int i = 0; i < argc; ++i) { CmdLine.Append(" "); CmdLine.Append(argv[i]); } Log(CmdLine.getData()); ClearCommandLine(); Game.NetworkActive = false; isEditor = 2; int c; while (1) { static struct option long_options[] = { // option, w/ argument?, set directly, set to... {"editor", no_argument, &isEditor, 1}, {"fullscreen", no_argument, &isEditor, 0}, {"debugwait", no_argument, &Game.DebugWait, 1}, {"update", no_argument, &CheckForUpdates, 1}, {"noruntimejoin", no_argument, &Config.Network.NoRuntimeJoin, 1}, {"runtimejoin", no_argument, &Config.Network.NoRuntimeJoin, 0}, {"noleague", no_argument, &Config.Network.LeagueServerSignUp, 0}, {"league", no_argument, &Config.Network.LeagueServerSignUp, 1}, {"nosignup", no_argument, &Config.Network.MasterServerSignUp, 0}, {"signup", no_argument, &Config.Network.MasterServerSignUp, 1}, {"debugrecread", required_argument, 0, 'K'}, {"debugrecwrite", required_argument, 0, 'w'}, {"client", required_argument, 0, 'c'}, {"host", no_argument, 0, 'h'}, {"debughost", required_argument, 0, 'H'}, {"debugpass", required_argument, 0, 'P'}, {"debug", required_argument, 0, 'D'}, {"data", required_argument, 0, 'd'}, {"startup", required_argument, 0, 's'}, {"stream", required_argument, 0, 'e'}, {"recdump", required_argument, 0, 'R'}, {"comment", required_argument, 0, 'm'}, {"pass", required_argument, 0, 'p'}, {"udpport", required_argument, 0, 'u'}, {"tcpport", required_argument, 0, 't'}, {"join", required_argument, 0, 'j'}, {"language", required_argument, 0, 'L'}, {"scenpar", required_argument, 0, 'S'}, {"observe", no_argument, 0, 'o'}, {"nonetwork", no_argument, 0, 'N'}, {"network", no_argument, 0, 'n'}, {"record", no_argument, 0, 'r'}, {"lobby", required_argument, 0, 'l'}, {"debug-opengl", no_argument, &Config.Graphics.DebugOpenGL, 1}, {0, 0, 0, 0} }; int option_index = 0; c = getopt_long (argc, argv, "abc:d:f:", long_options, &option_index); // no more options if (c == -1) break; switch (c) { case 0: // Signup if (SEqualNoCase(long_options[option_index].name, "signup")) { Game.NetworkActive = true; } // League if (SEqualNoCase(long_options[option_index].name, "league")) { Game.NetworkActive = true; Config.Network.MasterServerSignUp = true; } break; // Lobby case 'l': Game.fLobby = true; // lobby timeout specified? (e.g. --lobby=120) if (optarg) { Game.iLobbyTimeout = atoi(optarg); if (Game.iLobbyTimeout < 0) Game.iLobbyTimeout = 0; } break; case 'o': Game.fObserve = true; break; // Direct join case 'j': Game.NetworkActive = true; SCopy(optarg, Game.DirectJoinAddress, _MAX_PATH); break; case 'K': if (optarg && optarg[0]) { LogF("Reading from DebugRec file '%s'", optarg); SCopy(optarg, Config.General.DebugRecExternalFile, _MAX_PATH); } else Log("Reading DebugRec from CtrlRec file in scenario record"); Config.General.DebugRec = 1; Config.General.DebugRecWrite = 0; break; case 'w': if (optarg && optarg[0]) { LogF("Writing to DebugRec file '%s'", optarg); SCopy(optarg, Config.General.DebugRecExternalFile, _MAX_PATH); } else Log("Writing DebugRec to CtrlRec file in scenario record"); Config.General.DebugRec = 1; Config.General.DebugRecWrite = 1; break; case 'r': Game.Record = true; break; case 'n': Game.NetworkActive = true; break; case 'N': Game.NetworkActive = false; break; // Language override by parameter case 'L': SCopy(optarg, Config.General.LanguageEx, CFG_MaxString); // port overrides case 't': Config.Network.PortTCP = atoi(optarg); break; case 'u': Config.Network.PortUDP = atoi(optarg); break; // network game password case 'p': Network.SetPassword(optarg); break; // network game comment case 'm': Config.Network.Comment.CopyValidated(optarg); break; // record dump case 'R': Game.RecordDumpFile.Copy(optarg); break; // record stream case 'e': Game.RecordStream.Copy(optarg); break; // startup start screen case 's': C4Startup::SetStartScreen(optarg); break; // additional read-only data path case 'd': Reloc.AddPath(optarg); break; // debug options case 'D': Game.DebugPort = atoi(optarg); break; case 'P': Game.DebugPassword = optarg; break; case 'H': Game.DebugHost = optarg; break; // set custom scenario parameter by command line case 'S': { StdStrBuf sopt, soptval; sopt.Copy(optarg); int32_t val=1; if (sopt.SplitAtChar('=', &soptval)) val=atoi(soptval.getData()); Game.StartupScenarioParameters.SetValue(sopt.getData(), val, false); } break; // debug configs case 'h': Game.NetworkActive = true; Game.fLobby = true; Config.Network.PortTCP = 11112; Config.Network.PortUDP = 11113; Config.Network.MasterServerSignUp = Config.Network.LeagueServerSignUp = false; break; case 'c': Game.NetworkActive = true; SCopy("localhost", Game.DirectJoinAddress, _MAX_PATH); Game.fLobby = true; Config.Network.PortTCP = 11112 + 2*(atoi(optarg)+1); Config.Network.PortUDP = 11113 + 2*(atoi(optarg)+1); break; case '?': /* getopt_long already printed an error message. */ break; default: assert(!"unexpected getopt_long return value"); } } if (!Config.Network.MasterServerSignUp) Config.Network.LeagueServerSignUp = false; if (Game.fObserve || Game.fLobby) Game.NetworkActive = true; while (optind < argc) { char * szParameter = argv[optind++]; { // Strip trailing / that result from tab-completing unpacked c4groups int iLen = SLen(szParameter); if (iLen > 5 && szParameter[iLen-1] == '/' && szParameter[iLen-5] == '.' && szParameter[iLen-4] == 'o' && szParameter[iLen-3] == 'c') { szParameter[iLen-1] = '\0'; } } // Scenario file if (SEqualNoCase(GetExtension(szParameter),"ocs")) { if(IsGlobalPath(szParameter)) Game.SetScenarioFilename(szParameter); else Game.SetScenarioFilename((std::string(GetWorkingDirectory()) + DirSep + szParameter).c_str()); continue; } if (SEqualNoCase(GetFilename(szParameter),"scenario.txt")) { Game.SetScenarioFilename(szParameter); continue; } // Player file if (SEqualNoCase(GetExtension(szParameter),"ocp")) { if(IsGlobalPath(szParameter)) SAddModule(Game.PlayerFilenames, szParameter); else SAddModule(Game.PlayerFilenames, (std::string(GetWorkingDirectory()) + DirSep + szParameter).c_str()); continue; } // Definition file if (SEqualNoCase(GetExtension(szParameter),"ocd")) { SAddModule(Game.DefinitionFilenames,szParameter); continue; } // Key file if (SEqualNoCase(GetExtension(szParameter),"c4k")) { Application.IncomingKeyfile.Copy(szParameter); continue; } // Update file if (SEqualNoCase(GetExtension(szParameter),"ocu")) { Application.IncomingUpdate.Copy(szParameter); continue; } // record stream if (SEqualNoCase(GetExtension(szParameter),"c4r")) { Game.RecordStream.Copy(szParameter); } // Direct join by URL if (SEqual2NoCase(szParameter, "clonk:")) { // Store address SCopy(szParameter + 6, Game.DirectJoinAddress, _MAX_PATH); SClearFrontBack(Game.DirectJoinAddress, '/'); // Special case: if the target address is "update" then this is used for update initiation by url if (SEqualNoCase(Game.DirectJoinAddress, "update")) { Application.CheckForUpdates = true; Game.DirectJoinAddress[0] = 0; continue; } // Self-enable network Game.NetworkActive = true; continue; } } #ifdef _WIN32 // Clean up some forward/backward slach confusion since many internal OC file functions cannot handle both SReplaceChar(Game.ScenarioFilename, AltDirectorySeparator, DirectorySeparator); SReplaceChar(Game.PlayerFilenames, AltDirectorySeparator, DirectorySeparator); SReplaceChar(Game.DefinitionFilenames, AltDirectorySeparator, DirectorySeparator); Application.IncomingKeyfile.ReplaceChar(AltDirectorySeparator, DirectorySeparator); Application.IncomingUpdate.ReplaceChar(AltDirectorySeparator, DirectorySeparator); Game.RecordStream.ReplaceChar(AltDirectorySeparator, DirectorySeparator); #endif // Default to editor if scenario given, player mode otherwise if (isEditor == 2) isEditor = !!*Game.ScenarioFilename && !Config.General.OpenScenarioInGameMode; // record? Game.Record = Game.Record || (Config.Network.LeagueServerSignUp && Game.NetworkActive); // startup dialog required? QuitAfterGame = !isEditor && Game.HasScenario(); }
bool LogSilent(const char *szMessage, bool fConsole) { if (!Application.AssertMainThread()) return false; // security if (!szMessage) return false; // add timestamp time_t timenow; time(&timenow); StdStrBuf TimeMessage; TimeMessage.SetLength(11 + SLen(szMessage) + 1); strftime(TimeMessage.getMData(), 11 + 1, "[%H:%M:%S] ", localtime(&timenow)); // output until all data is written const char *pSrc = szMessage; do { // timestamp will always be that length char *pDest = TimeMessage.getMData() + 11; // copy rest of message, skip tags C4Markup Markup(false); while (*pSrc) { Markup.SkipTags(&pSrc); // break on crlf while (*pSrc == '\r') pSrc++; if (*pSrc == '\n') { pSrc++; break; } // copy otherwise if (*pSrc) *pDest++ = *pSrc++; } *pDest++='\n'; *pDest = '\0'; // Save into log file if (C4LogFile) { fputs(TimeMessage.getData(),C4LogFile); fflush(C4LogFile); } // Save into record log file, if available if(Control.GetRecord()) { Control.GetRecord()->GetLogFile()->Write(TimeMessage.getData(), TimeMessage.getLength()); #ifdef IMMEDIATEREC Control.GetRecord()->GetLogFile()->Flush(); #endif } // Write to console if (fConsole) { #if defined(_WIN32) // debug: output to VC console OutputDebugString(TimeMessage.GetWideChar()); #endif #if !defined(_WIN32) || defined(USE_CONSOLE) fputs(TimeMessage.getData(),stdout); fflush(stdout); #endif } } while (*pSrc); return true; }
C4Group *C4GroupSet::RegisterParentFolders(const char *szScenFilename) { // the scenario filename may be a scenario or directly a group folder C4Group *pParentGroup=nullptr; bool fParentC4F; char szParentfolder[_MAX_PATH+1]; if (SEqualNoCase(GetExtension(szScenFilename), "ocf")) { fParentC4F = true; SCopy(szScenFilename, szParentfolder, _MAX_PATH); } else { GetParentPath(szScenFilename,szParentfolder); fParentC4F = SEqualNoCase(GetExtension(szParentfolder), "ocf"); } if (fParentC4F) { // replace all (back)slashes with zero-fields int32_t iOriginalLen=SLen(szParentfolder); for (int32_t i=0; i<iOriginalLen; ++i) if (szParentfolder[i]==DirectorySeparator || szParentfolder[i]=='/') szParentfolder[i]=0; // trace back until the file extension is no more .ocf int32_t iPos=iOriginalLen-1; while (iPos) { // ignore additional zero fields (double-backslashes) while (iPos && !szParentfolder[iPos]) --iPos; // break if end has been reached if (!iPos) break; // trace back until next zero field while (iPos && szParentfolder[iPos]) --iPos; // check extension of this folder if (!SEqualNoCase(GetExtension(szParentfolder+iPos+1), "ocf", 3)) break; // continue } // trace backwards, putting the (back)slashes in place again if (iPos) { szParentfolder[iPos+1+SLen(szParentfolder+iPos+1)]=szParentfolder[iPos]=DirectorySeparator; while (iPos--) if (!szParentfolder[iPos]) szParentfolder[iPos]=DirectorySeparator; ++iPos; } // trace forward again, opening all folders (iPos is 0 again) int32_t iGroupIndex=0; while (iPos<iOriginalLen) { // ignore additional zero-fields while (iPos<iOriginalLen && !szParentfolder[iPos]) ++iPos; // break if end has been reached if (iPos>=iOriginalLen) break; // open this folder C4Group *pGroup = new C4Group(); if (pParentGroup) { if (!pGroup->OpenAsChild(pParentGroup, szParentfolder+iPos)) { LogFatal(FormatString("%s: %s", LoadResStr("IDS_PRC_FILENOTFOUND"), szParentfolder+iPos).getData()); delete pGroup; return nullptr; } } else if (!Reloc.Open(*pGroup, szParentfolder+iPos)) { LogFatal(FormatString("%s: %s", LoadResStr("IDS_PRC_FILENOTFOUND"), szParentfolder+iPos).getData()); delete pGroup; return nullptr; } // set this group as new parent pParentGroup=pGroup; // add to group set, if this is a true scenario folder int32_t iContentsMask; if (WildcardMatch(C4CFN_FolderFiles, pParentGroup->GetName())) iContentsMask = C4GSCnt_Folder; else iContentsMask = C4GSCnt_Directory; if (!RegisterGroup(*pParentGroup, true, C4GSPrio_Folder+iGroupIndex++, iContentsMask)) { delete pParentGroup; LogFatal ("RegGrp: internal error"); return nullptr; } // advance by file name length iPos+=SLen(szParentfolder+iPos); } } return pParentGroup; }