Esempio n. 1
0
BOOL C4UpdatePackageCore::Save(C4Group &hGroup) {
    try {
        // decompile data
        StdStrBuf Core =
            DecompileToBuf<StdCompilerINIWrite>(mkNamingAdapt(*this, "Update"));
        char *stupid_buffer = new char[Core.getLength() + 1];
        memcpy(stupid_buffer, Core.getMData(), Core.getLength() + 1);
        // add to group
        return hGroup.Add(C4CFN_UpdateCore, stupid_buffer, Core.getLength(), FALSE,
                          TRUE);
    } catch (StdCompiler::Exception *pExc) {
        delete pExc;
        return FALSE;
    }
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
size_t C4Network2IRCClient::UnpackPacket(const StdBuf &rInBuf, const C4NetIO::addr_t &addr)
	{
	// Find line seperation
 	const char *pSep = reinterpret_cast<const char *>(memchr(rInBuf.getData(), '\n', rInBuf.getSize()));
	if(!pSep)
		return 0;
	// Check if it's actually correct seperation (rarely the case)
	int iSize = pSep - getBufPtr<char>(rInBuf) + 1,
			iLength = iSize - 1;
	if(iLength && *(pSep - 1) == '\r')
		iLength--;
	// Copy the line
	StdStrBuf Buf; Buf.Copy(getBufPtr<char>(rInBuf), iLength);
	// Ignore prefix
	const char *pMsg = Buf.getData();
	StdStrBuf Prefix;
	if(*pMsg == ':')
		{
		Prefix.CopyUntil(pMsg + 1, ' ');
		pMsg += Prefix.getLength() + 1;
		}
	// Strip whitespace
	while(*pMsg == ' ')
		pMsg++;
	// Ignore empty message
	if(!*pMsg)
		return iSize;
	// Get command
	StdStrBuf Cmd; Cmd.CopyUntil(pMsg, ' ');
	// Precess command
	const char *szParameters = SSearch(pMsg, " ");
	OnCommand(Prefix.getData(), Cmd.getData(), szParameters ? szParameters : "");
	// Consume the line
	return iSize;
	}
Esempio n. 4
0
bool C4TextureMap::SaveMap(C4Group &hGroup, const char *szEntryName)
	{
#ifdef C4ENGINE
	// build file in memory
	StdStrBuf sTexMapFile;
	// add desc
	sTexMapFile.Append("# Automatically generated texture map" LineFeed);
	sTexMapFile.Append("# Contains material-texture-combinations added at runtime" LineFeed);
	// add overload-entries
	if (fOverloadMaterials) sTexMapFile.Append("# Import materials from global file as well" LineFeed "OverloadMaterials" LineFeed);
	if (fOverloadTextures) sTexMapFile.Append("# Import textures from global file as well" LineFeed "OverloadTextures" LineFeed);
	sTexMapFile.Append(LineFeed);
	// add entries
	for (int32_t i = 0; i < C4M_MaxTexIndex; i++)
		if (!Entry[i].isNull())
			{
			// compose line
			sTexMapFile.AppendFormat("%d=%s-%s" LineFeed, i, Entry[i].GetMaterialName(), Entry[i].GetTextureName());
			}
	// create new buffer allocated with new [], because C4Group cannot handle StdStrBuf-buffers
	size_t iBufSize = sTexMapFile.getLength();
	BYTE *pBuf = new BYTE[iBufSize];
	memcpy(pBuf, sTexMapFile.getData(), iBufSize);
	// add to group
	bool fSuccess = !!hGroup.Add(szEntryName, pBuf, iBufSize, false, true);
	if (!fSuccess) delete [] pBuf;
	// done
	return fSuccess;
#else
	return FALSE;
#endif
	}
Esempio n. 5
0
// Helper for IRC command parameter parsing
StdStrBuf ircExtractPar(const char **ppPar)
	{
	// No parameter left?
	if(!ppPar || !*ppPar || !**ppPar)
		return StdStrBuf("");
	// Last parameter?
	StdStrBuf Result;
	if(**ppPar == ':')
		{
		// Reference everything after the double-colon
		Result.Ref(*ppPar + 1);
		*ppPar = NULL;
		}
	else
		{
		// Copy until next space (or end of string)
		Result.CopyUntil(*ppPar, ' ');
		// Go over parameters
		*ppPar += Result.getLength();
		if(**ppPar == ' ')
			(*ppPar)++;
		else
			*ppPar = NULL;
		}
	// Done
	return Result;
	}
Esempio n. 6
0
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;
}
Esempio n. 7
0
bool C4Network2IRCClient::Send(const char *szCommand, const char *szParameters)
	{
	if(!fConnected)
		{ SetError("not connected"); return false; }
	// Create message
	StdStrBuf Msg;
	if(szParameters)
		Msg.Format("%s %s", szCommand, szParameters);
	else
		Msg.Ref(szCommand);
	// Send
	return C4NetIOTCP::Send(C4NetIOPacket(Msg.getData(), Msg.getLength(), false, PeerAddr));
	}
bool C4RoundResults::Save(C4Group &hGroup, const char *szFilename)
{
	// remove previous entry from group
	hGroup.DeleteEntry(szFilename);
	// decompile
	try
	{
		StdStrBuf Buf = DecompileToBuf<StdCompilerINIWrite>(mkNamingAdapt(*this, "RoundResults"));
		// save it, if not empty
		if (Buf.getLength())
			if (!hGroup.Add(szFilename, Buf, false, true))
				return false;
	}
	catch (StdCompiler::Exception *)
		{ return false; }
	// done, success
	return true;
}
Esempio n. 9
0
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);
    }
}
Esempio n. 10
0
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;
}
Esempio n. 11
0
bool CStdGL::PrepareMaterial(StdMeshMatManager& mat_manager, StdMeshMaterialLoader& loader, StdMeshMaterial& mat)
{
	// TODO: If a technique is not available, show an error message what the problem is

	// select context, if not already done
	if (!pCurrCtx) return false;

	for (unsigned int i = 0; i < mat.Techniques.size(); ++i)
	{
		StdMeshMaterialTechnique& technique = mat.Techniques[i];
		technique.Available = true;
		for (unsigned int j = 0; j < technique.Passes.size(); ++j)
		{
			StdMeshMaterialPass& pass = technique.Passes[j];

			GLint max_texture_units;
			glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_units);

			// OpenGL 3.x guarantees at least 16 TIUs. If the above returns
			// less it's probably a driver bug. So just keep going.
			assert(max_texture_units >= 16);
			max_texture_units = std::min<GLint>(max_texture_units, 16);

			unsigned int active_texture_units = 0;
			for(unsigned int k = 0; k < pass.TextureUnits.size(); ++k)
				if(pass.TextureUnits[k].HasTexture())
					++active_texture_units;

			if (active_texture_units > static_cast<unsigned int>(max_texture_units))
				technique.Available = false;

			for (unsigned int k = 0; k < pass.TextureUnits.size(); ++k)
			{
				StdMeshMaterialTextureUnit& texunit = pass.TextureUnits[k];
				for (unsigned int l = 0; l < texunit.GetNumTextures(); ++l)
				{
					const C4TexRef& texture = texunit.GetTexture(l);
					glBindTexture(GL_TEXTURE_2D, texture.texName);
					switch (texunit.TexAddressMode)
					{
					case StdMeshMaterialTextureUnit::AM_Wrap:
						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
						break;
					case StdMeshMaterialTextureUnit::AM_Border:
						glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, texunit.TexBorderColor);
						// fallthrough
					case StdMeshMaterialTextureUnit::AM_Clamp:
						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
						break;
					case StdMeshMaterialTextureUnit::AM_Mirror:
						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
						break;
					}

					switch (texunit.Filtering[0]) // min
					{
					case StdMeshMaterialTextureUnit::F_None:
						technique.Available = false;
						break;
					case StdMeshMaterialTextureUnit::F_Point:
						switch (texunit.Filtering[2]) // mip
						{
						case StdMeshMaterialTextureUnit::F_None:
							glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
							break;
						case StdMeshMaterialTextureUnit::F_Point:
							glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
							break;
						case StdMeshMaterialTextureUnit::F_Linear:
							glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
							break;
						case StdMeshMaterialTextureUnit::F_Anisotropic:
							technique.Available = false; // invalid
							break;
						}
						break;
					case StdMeshMaterialTextureUnit::F_Linear:
						switch (texunit.Filtering[2]) // mip
						{
						case StdMeshMaterialTextureUnit::F_None:
							glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
							break;
						case StdMeshMaterialTextureUnit::F_Point:
							glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
							break;
						case StdMeshMaterialTextureUnit::F_Linear:
							glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
							break;
						case StdMeshMaterialTextureUnit::F_Anisotropic:
							technique.Available = false; // invalid
							break;
						}
						break;
					case StdMeshMaterialTextureUnit::F_Anisotropic:
						// unsupported
						technique.Available = false;
						break;
					}

					switch (texunit.Filtering[1]) // max
					{
					case StdMeshMaterialTextureUnit::F_None:
						technique.Available = false; // invalid
						break;
					case StdMeshMaterialTextureUnit::F_Point:
						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
						break;
					case StdMeshMaterialTextureUnit::F_Linear:
						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
						break;
					case StdMeshMaterialTextureUnit::F_Anisotropic:
						// unsupported
						technique.Available = false;
						break;
					}
				} // loop over textures
			} // loop over texture units

			// Create fragment and/or vertex shader
			// if a custom shader is not provided.
			// Re-use existing programs if the generated
			// code is the same (determined by SHA1 hash).
			bool custom_shader = true;
			if(!pass.VertexShader.Shader)
			{
				StdStrBuf buf = GetVertexShaderCodeForPass(pass, Workarounds.LowMaxVertexUniformCount);
				StdStrBuf hash = GetSHA1HexDigest(buf.getData(), buf.getLength());
				pass.VertexShader.Shader = mat_manager.AddShader("auto-generated vertex shader", hash.getData(), "glsl", SMMS_VERTEX, buf.getData(), StdMeshMatManager::SMM_AcceptExisting);
				custom_shader = false;
			}

			if(!pass.FragmentShader.Shader)
			{
				// TODO: Should use shared_params once we introduce them
				StdStrBuf buf = GetFragmentShaderCodeForPass(pass, pass.FragmentShader.Parameters);
				StdStrBuf hash = GetSHA1HexDigest(buf.getData(), buf.getLength());
				pass.FragmentShader.Shader = mat_manager.AddShader("auto-generated fragment shader", hash.getData(), "glsl", SMMS_FRAGMENT, buf.getData(), StdMeshMatManager::SMM_AcceptExisting);
			}

			// Then, link the program, and resolve parameter locations
			StdStrBuf name(FormatString("%s:%s:%s", mat.Name.getData(), technique.Name.getData(), pass.Name.getData()));
			const StdMeshMaterialProgram* added_program = mat_manager.AddProgram(name.getData(), loader, pass.FragmentShader, pass.VertexShader, pass.GeometryShader);
			if(!added_program)
			{
				// If the program could not be compiled, try again with the LowMaxVertexUniformCount workaround.
				// See bug #1368.
				if (!custom_shader && !Workarounds.LowMaxVertexUniformCount)
				{
					StdStrBuf buf = GetVertexShaderCodeForPass(pass, true);
					StdStrBuf hash = GetSHA1HexDigest(buf.getData(), buf.getLength());
					pass.VertexShader.Shader = mat_manager.AddShader("auto-generated vertex shader", hash.getData(), "glsl", SMMS_VERTEX, buf.getData(), StdMeshMatManager::SMM_AcceptExisting);

					added_program = mat_manager.AddProgram(name.getData(), loader, pass.FragmentShader, pass.VertexShader, pass.GeometryShader);
					if(added_program)
					{
						// If this actually work, cache the result, so we don't
						// need to fail again next time before trying the workaround.
						Workarounds.LowMaxVertexUniformCount = true;
						Log("  gl: Enabling low max vertex uniform workaround");
					}
				}
			}

			if (!added_program)
			{
				technique.Available = false;
			}
			else
			{
				std::unique_ptr<StdMeshMaterialPass::ProgramInstance> program_instance(new StdMeshMaterialPass::ProgramInstance(added_program, &pass.FragmentShader, &pass.VertexShader, &pass.GeometryShader));
				pass.Program = std::move(program_instance);
			}
		}

		if (technique.Available && mat.BestTechniqueIndex == -1)
			mat.BestTechniqueIndex = i;
	}

	return mat.BestTechniqueIndex != -1;
}
Esempio n. 12
0
C4AulDebug::ProcessLineResult C4AulDebug::ProcessLine(const StdStrBuf &Line)
{
	// Get command
	StdStrBuf Cmd;
	Cmd.CopyUntil(Line.getData(), ' ');
	// Get data
	const char *szData = Line.getPtr(Cmd.getLength());
	if (*szData) szData++;
	// Identify command
	const char *szCmd = Cmd.getData();
	if (SEqualNoCase(szCmd, "HELP"))
		return ProcessLineResult(false, "Yeah, like I'm going to explain that /here/");
	else if (SEqualNoCase(szCmd, "BYE") || SEqualNoCase(szCmd, "QUIT"))
		C4NetIOTCP::Close(PeerAddr);
	else if (SEqualNoCase(szCmd, "SAY"))
		::Control.DoInput(CID_Message, new C4ControlMessage(C4CMT_Normal, szData), CDT_Direct);
	else if (SEqualNoCase(szCmd, "CMD"))
		::MessageInput.ProcessCommand(szData);
	else if (SEqualNoCase(szCmd, "STP") || SEqualNoCase(szCmd, "S"))
		eState = DS_Step;
	else if (SEqualNoCase(szCmd, "GO") || SEqualNoCase(szCmd, "G"))
		eState = DS_Go;
	else if (SEqualNoCase(szCmd, "STO") || SEqualNoCase(szCmd, "O"))
		eState = DS_StepOver;
	else if (SEqualNoCase(szCmd, "STR") || SEqualNoCase(szCmd, "R"))
		eState = DS_StepOut;
	else if (SEqualNoCase(szCmd, "EXC") || SEqualNoCase(szCmd, "E"))
	{
		C4AulScriptContext* context = pExec->GetContext(pExec->GetContextDepth()-1);
		int32_t objectNum = C4ControlScript::SCOPE_Global;
		if (context && context->Obj && context->Obj->GetObject())
			objectNum = context->Obj->GetObject()->Number;
		::Control.DoInput(CID_Script, new C4ControlScript(szData, objectNum, true), CDT_Decide);
	}
	else if (SEqualNoCase(szCmd, "PSE"))
		if (Game.IsPaused())
		{
			Game.Unpause();
			return ProcessLineResult(true, "Game unpaused.");
		}
		else
		{
			Game.Pause();
			return ProcessLineResult(true, "Game paused.");
		}
	else if (SEqualNoCase(szCmd, "LST"))
	{
		for (C4AulScript* script = ScriptEngine.Child0; script; script = script->Next)
		{
			SendLine(RelativePath(script->ScriptName));
		}
	}

	// toggle breakpoint
	else if (SEqualNoCase(szCmd, "TBR"))
	{
		using namespace std;
		// FIXME: this doesn't find functions which were included/appended
		string scriptPath = szData;
		size_t colonPos = scriptPath.find(':');
		if (colonPos == string::npos)
			return ProcessLineResult(false, "Missing line in breakpoint request");
		int line = atoi(&scriptPath[colonPos+1]);
		scriptPath.erase(colonPos);

		C4AulScript *script;
		for (script = ScriptEngine.Child0; script; script = script->Next)
		{
			if (SEqualNoCase(RelativePath(script->ScriptName), scriptPath.c_str()))
				break;
		}

		auto sh = script ? script->GetScriptHost() : NULL;
		if (sh)
		{
			C4AulBCC * found = NULL;
			for (auto script = ::ScriptEngine.Child0; script; script = script->Next)
			for (C4PropList *props = script->GetPropList(); props; props = props->GetPrototype())
			for (auto fname = props->EnumerateOwnFuncs(); fname; fname = props->EnumerateOwnFuncs(fname))
			{
				C4Value val;
				if (!props->GetPropertyByS(fname, &val)) continue;
				auto func = val.getFunction();
				if (!func) continue;
				auto sfunc = func->SFunc();
				if (!sfunc) continue;
				if (sfunc->pOrgScript != sh) continue;
				for (auto chunk = sfunc->GetCode(); chunk->bccType != AB_EOFN; chunk++)
				{
					if (chunk->bccType == AB_DEBUG)
					{
						int lineOfThisOne = sfunc->GetLineOfCode(chunk);
						if (lineOfThisOne == line)
						{
							found = chunk;
							goto Found;
						}
					}
				}
			}
			Found:
			if (found)
				found->Par.i = !found->Par.i; // activate breakpoint
			else
				return ProcessLineResult(false, "Can't set breakpoint (wrong line?)");
		}
		else
			return ProcessLineResult(false, "Can't find script");
	}
	else if (SEqualNoCase(szCmd, "SST"))
	{
		std::list<StdStrBuf*>::iterator it = StackTrace.begin();
		for (it++; it != StackTrace.end(); it++)
		{
			SendLine("AT", (*it)->getData());
		}
		SendLine("EST");
	}
	else if (SEqualNoCase(szCmd, "VAR"))
	{
		
		C4Value *val = NULL;
		int varIndex;
		C4AulScriptContext* pCtx = pExec->GetContext(pExec->GetContextDepth() - 1);
		if (pCtx)
		{
			if ((varIndex = pCtx->Func->ParNamed.GetItemNr(szData)) != -1)
			{
				val = &pCtx->Pars[varIndex];
			}
			else if ((varIndex = pCtx->Func->VarNamed.GetItemNr(szData)) != -1)
			{
				val = &pCtx->Vars[varIndex];
			}
		}
		const char* typeName = val ? GetC4VName(val->GetType()) : "any";
		StdStrBuf output = FormatString("%s %s %s", szData, typeName, val ? val->GetDataString().getData() : "Unknown");
		SendLine("VAR", output.getData());
	}
	else
		return ProcessLineResult(false, "Can't do that");
	
	return ProcessLineResult(true, "");
}
Esempio n. 13
0
bool C4ChatControl::ProcessInput(const char *szInput, ChatSheet *pChatSheet) {
  CStdLock Lock(pIRCClient->getCSec());
  // process chat input - return false if no more pasting is to be done (i.e.,
  // on /quit or /part in channel)
  bool fResult = true;
  bool fIRCSuccess = true;
  // not connected?
  if (!pIRCClient->IsConnected()) {
    pChatSheet->DoError(LoadResStr("IDS_ERR_NOTCONNECTEDTOSERVER"));
    return fResult;
  }
  // safety
  if (!szInput || !*szInput || !pChatSheet) return fResult;
  // command?
  if (*szInput == '/' && !SEqual2NoCase(szInput + 1, "me ")) {
    StdStrBuf sCommand, sParam("");
    ;
    sCommand.Copy(szInput + 1);
    sCommand.SplitAtChar(' ', &sParam);
    if (SEqualNoCase(sCommand.getData(), "quit")) {
      // query disconnect from IRC server
      fIRCSuccess = pIRCClient->Quit(sParam.getData());
      fResult = false;
    } else if (SEqualNoCase(sCommand.getData(), "part")) {
      // part channel. Default to current channel if typed within a channel
      if (!sParam.getLength() &&
          pChatSheet->GetSheetType() == ChatSheet::CS_Channel) {
        sParam.Copy(pChatSheet->GetIdent());
        fResult = false;
      }
      fIRCSuccess = pIRCClient->Part(sParam.getData());
    } else if (SEqualNoCase(sCommand.getData(), "join") ||
               SEqualNoCase(sCommand.getData(), "j")) {
      if (!sParam.getLength()) sParam.Copy(Config.IRC.Channel);
      fIRCSuccess = pIRCClient->Join(sParam.getData());
    } else if (SEqualNoCase(sCommand.getData(), "notice") ||
               SEqualNoCase(sCommand.getData(), "msg")) {
      bool fMsg = SEqualNoCase(sCommand.getData(), "msg");
      StdStrBuf sMsg;
      if (!sParam.SplitAtChar(' ', &sMsg) || !sMsg.getLength()) {
        pChatSheet->DoError(
            FormatString(LoadResStr("IDS_ERR_INSUFFICIENTPARAMETERS"),
                         sCommand.getData()).getData());
      } else {
        if (fMsg)
          fIRCSuccess = pIRCClient->Message(sParam.getData(), sMsg.getData());
        else
          fIRCSuccess = pIRCClient->Notice(sParam.getData(), sMsg.getData());
      }
    } else if (SEqualNoCase(sCommand.getData(), "raw")) {
      if (!sParam.getLength())
        pChatSheet->DoError(
            FormatString(LoadResStr("IDS_ERR_INSUFFICIENTPARAMETERS"),
                         sCommand.getData()).getData());
      else
        fIRCSuccess = pIRCClient->Send(sParam.getData());
    } else if (SEqualNoCase(sCommand.getData(), "ns") ||
               SEqualNoCase(sCommand.getData(), "cs") ||
               SEqualNoCase(sCommand.getData(), "ms")) {
      if (!sParam.getLength())
        pChatSheet->DoError(
            FormatString(LoadResStr("IDS_ERR_INSUFFICIENTPARAMETERS"),
                         sCommand.getData()).getData());
      else {
        const char *szMsgTarget;
        if (SEqualNoCase(sCommand.getData(), "ns"))
          szMsgTarget = "NickServ";
        else if (SEqualNoCase(sCommand.getData(), "cs"))
          szMsgTarget = "ChanServ";
        else
          szMsgTarget = "MemoServ";
        fIRCSuccess = pIRCClient->Message(szMsgTarget, sParam.getData());
      }
    } else if (SEqualNoCase(sCommand.getData(), "query") ||
               SEqualNoCase(sCommand.getData(), "q")) {
      if (!sParam.getLength())
        pChatSheet->DoError(
            FormatString(LoadResStr("IDS_ERR_INSUFFICIENTPARAMETERS"),
                         sCommand.getData()).getData());
      else
        OpenQuery(sParam.getData(), true, NULL);
    } else if (SEqualNoCase(sCommand.getData(), "nick")) {
      if (C4InVal::ValidateString(sParam, C4InVal::VAL_IRCName))
        pChatSheet->DoError(FormatString(LoadResStr("IDS_ERR_INVALIDNICKNAME2"),
                                         sCommand.getData()).getData());
      else
        fIRCSuccess = pIRCClient->ChangeNick(sParam.getData());
    } else {
      // unknown command
      pChatSheet->DoError(FormatString(LoadResStr("IDS_ERR_UNKNOWNCMD"),
                                       sCommand.getData()).getData());
    }
  } else {
    // regular chat input: Send as message to current channel/user
    const char *szMsgTarget;
    ChatSheet::SheetType eSheetType = pChatSheet->GetSheetType();
    if (eSheetType == ChatSheet::CS_Server) {
      pChatSheet->DoError(LoadResStr("IDS_ERR_NOTONACHANNEL"));
    } else {
      szMsgTarget = pChatSheet->GetTitle();
      if (*szInput == '/')  // action
        fIRCSuccess = pIRCClient->Action(szMsgTarget, szInput + 4);
      else
        fIRCSuccess = pIRCClient->Message(szMsgTarget, szInput);
    }
  }
  // IRC sending error? log it
  if (!fIRCSuccess) {
    pChatSheet->DoError(pIRCClient->GetError());
  }
  return fResult;
}
Esempio n. 14
0
	bool ValidateString(StdStrBuf &rsString, ValidationOption eOption)
		{
		bool fValid = true;
		// validation depending on option
		// check min length
		if (!rsString.getLength())
			{
			// empty if not allowed?
			if (eOption != VAL_NameAllowEmpty && eOption != VAL_NameExAllowEmpty && eOption != VAL_Comment)
				{
				rsString.Copy("empty");
				fValid = false;
				}
			}
		switch (eOption)
			{
			case VAL_Filename: // regular filenames only
				// absolutely no directory traversal
				if (rsString.ReplaceChar('/', '_')) fValid = false;
				if (rsString.ReplaceChar('\\', '_')) fValid = false;

				// fallthrough to general file name validation
			case VAL_SubPathFilename: // filenames and optional subpath
				// do not traverse upwards in file hierarchy
				if (rsString.Replace("..", "__")) fValid = false;
				if (*rsString.getData() == '/' || *rsString.getData() == '\\') { *rsString.getMData() = '_'; fValid = false; }

				// fallthrough to general file name validation
			case VAL_FullPath:        // full filename paths
				// some characters are prohibited in filenames in general
				if (rsString.ReplaceChar('*', '_')) fValid = false;
				if (rsString.ReplaceChar('?', '_')) fValid = false;
				if (rsString.ReplaceChar('<', '_')) fValid = false;
				if (rsString.ReplaceChar('>', '_')) fValid = false;
				// ';' and '|' is never allowed in filenames, because it would cause problems in many engine internal file lists
				if (rsString.ReplaceChar(';', '_')) fValid = false;
				if (rsString.ReplaceChar('|', '_')) fValid = false;
				// the colon is generally prohibited except at pos 2 (C:\...), because it could lead to creation of (invisible) streams on NTFS
				if (rsString.ReplaceChar(':', '_', 2)) fValid = false;
				if (*rsString.getData() == ':') { *rsString.getMData() = '_'; fValid = false; }
				// validate drive letter
				if (rsString.getLength()>=2 && *rsString.getPtr(1) == ':')
					{
					if (eOption != VAL_FullPath)
						{
						*rsString.getMPtr(1)='_'; fValid = false;
						}
					else if (!isalpha((unsigned char)*rsString.getData()) || (*rsString.getPtr(2)!='\\' && *rsString.getPtr(2)!='/'))
						{
						*rsString.getMData()=*rsString.getMPtr(1)='_'; fValid = false;
						}
					}
				break;

			case VAL_NameNoEmpty:
			case VAL_NameAllowEmpty:
				// no markup
				if (CMarkup::StripMarkup(&rsString)) { fValid = false; }
				// trim spaces
				if (rsString.TrimSpaces()) fValid = false;
				// min length
				if (eOption == VAL_NameNoEmpty) if (!rsString.getLength()) { fValid = false; rsString.Copy("Unknown"); }
				// max length
				if (rsString.getLength() > C4MaxName) { fValid = false; rsString.SetLength(C4MaxName); }
				break;

			case VAL_NameExNoEmpty:
			case VAL_NameExAllowEmpty:
				// trim spaces
				if (rsString.TrimSpaces()) fValid = false;
				// min length
				if (eOption == VAL_NameExNoEmpty) if (!rsString.getLength()) { fValid = false; rsString.Copy("Unknown"); }
				// max length
				if (rsString.getLength() > C4MaxLongName) { fValid = false; rsString.SetLength(C4MaxLongName); }
				break;

			case VAL_IRCName: // nickname for IRC. a-z, A-Z, _^{[]} only; 0-9|- inbetween; max 30 characters
				if (rsString.getLength() > 30) fValid = false;
				if (rsString.getLength() < 2) fValid = false;
				if (!rsString.ValidateChars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_^{[]}", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_^{[]}0123456789|-")) { fValid = false; rsString.Copy("Guest"); }
				if (SEqualNoCase(rsString.getData(), "NickServ")
				 || SEqualNoCase(rsString.getData(), "ChanServ")
				 || SEqualNoCase(rsString.getData(), "MemoServ")
				 || SEqualNoCase(rsString.getData(), "OperServ")
				 || SEqualNoCase(rsString.getData(), "HelpServ")) fValid = false;
				if (!fValid) rsString.Copy("Guest");
				break;

			case VAL_IRCPass: // password for IRC; max 31 characters
				// max length; no spaces
				if (rsString.getLength() > 31) { fValid = false; rsString.SetLength(31); }
				if (rsString.getLength() < 2) { fValid = false; rsString.Copy("secret"); }
				if (rsString.ReplaceChar(' ', '_')) fValid = false;
				break;

			case VAL_IRCChannel: // IRC channel name
				if (rsString.getLength() > 32) { fValid = false; rsString.SetLength(32); }
				else if (rsString.getLength() < 2) { fValid = false; rsString.Copy("#clonken"); }
				else if (*rsString.getData() != '#' && *rsString.getData() != '+') { fValid = false; *rsString.getMData() = '#'; }
				if (rsString.ReplaceChar(' ', '_')) fValid = false;
				break;

			case VAL_Comment: // comment - just limit length
				if (rsString.getLength() > C4MaxComment) { fValid = false; rsString.SetLength(C4MaxComment); }
				break;

			default:
				assert(!"not yet implemented");
			}
		// issue warning for invalid adjustments
		if (!fValid)
			{
			const char *szOption = "unknown";
			switch (eOption)
				{
				case VAL_Filename:         szOption = "filename";         break;
				case VAL_SubPathFilename:  szOption = "(sub-)filename";   break;
				case VAL_FullPath:         szOption = "free filename";    break;
				case VAL_NameNoEmpty:      szOption = "strict name";      break;
				case VAL_NameExNoEmpty:    szOption = "name";             break;
				case VAL_NameAllowEmpty:   szOption = "strict name*";     break;
				case VAL_NameExAllowEmpty: szOption = "name*";            break;
				case VAL_IRCName:          szOption = "IRC nick";         break;
				case VAL_IRCPass:          szOption = "IRC password";     break;
				case VAL_IRCChannel:       szOption = "IRC channel";      break;
				case VAL_Comment:          szOption = "Comment";          break;
				}
			//LogF("WARNING: Adjusted invalid user input for \"%s\" to \"%s\"", szOption, rsString.getData());
			}
		return !fValid;
		}
Esempio n. 15
0
StdStrBuf C4KeyCodeEx::KeyCode2String(C4KeyCode wCode, bool fHumanReadable, bool fShort)
{
    // Gamepad keys
    if (Key_IsGamepad(wCode))
    {
        int iGamepad = Key_GetGamepad(wCode);
        int gamepad_event = Key_GetGamepadEvent(wCode);
        switch (gamepad_event)
        {
        case KEY_JOY_Left:
            return FormatString("Joy%dLeft", iGamepad+1);
        case KEY_JOY_Up:
            return FormatString("Joy%dUp", iGamepad+1);
        case KEY_JOY_Down:
            return FormatString("Joy%dDown", iGamepad+1);
        case KEY_JOY_Right:
            return FormatString("Joy%dRight", iGamepad+1);
        default:
            if (Key_IsGamepadAxis(wCode))
            {
                if (fHumanReadable)
                    // This is still not great, but it is not really possible to assign unknown axes to "left/right" "up/down"...
                    return FormatString("[%d] %s", int(1 + Key_GetGamepadAxisIndex(wCode)), Key_IsGamepadAxisHigh(wCode) ? "Max" : "Min");
                else
                    return FormatString("Joy%dAxis%d%s", iGamepad+1, static_cast<int>(Key_GetGamepadAxisIndex(wCode)+1), Key_IsGamepadAxisHigh(wCode) ? "Max" : "Min");
            }
            else
            {
                // button
                if (fHumanReadable)
                    // If there should be gamepads around with A B C D... on the buttons, we might create a display option to show letters instead...
                    return FormatString("< %d >", int(1 + Key_GetGamepadButtonIndex(wCode)));
                else
                    return FormatString("Joy%d%c", iGamepad+1, static_cast<char>(Key_GetGamepadButtonIndex(wCode) + 'A'));
            }
        }
    }
    // Mouse keys
    if (Key_IsMouse(wCode))
    {
        int mouse_id = Key_GetMouse(wCode);
        int mouse_event = Key_GetMouseEvent(wCode);
        const char *mouse_str = "Mouse";
        switch (mouse_event)
        {
        case KEY_MOUSE_Move:
            return FormatString("%s%dMove", mouse_str, mouse_id);
        case KEY_MOUSE_Wheel1Up:
            return FormatString("%s%dWheel1Up", mouse_str, mouse_id);
        case KEY_MOUSE_Wheel1Down:
            return FormatString("%s%dWheel1Down", mouse_str, mouse_id);
        case KEY_MOUSE_ButtonLeft:
            return FormatString("%s%dLeft", mouse_str, mouse_id);
        case KEY_MOUSE_ButtonRight:
            return FormatString("%s%dRight", mouse_str, mouse_id);
        case KEY_MOUSE_ButtonMiddle:
            return FormatString("%s%dMiddle", mouse_str, mouse_id);
        case KEY_MOUSE_ButtonLeftDouble:
            return FormatString("%s%dLeftDouble", mouse_str, mouse_id);
        case KEY_MOUSE_ButtonRightDouble:
            return FormatString("%s%dRightDouble", mouse_str, mouse_id);
        case KEY_MOUSE_ButtonMiddleDouble:
            return FormatString("%s%dMiddleDouble", mouse_str, mouse_id);
        default:
            // extended mouse button
        {
            uint8_t btn = Key_GetMouseEvent(wCode);
            if (btn >= KEY_MOUSE_Button1Double)
                return FormatString("%s%dButton%dDouble", mouse_str, mouse_id, int(btn-KEY_MOUSE_Button1Double));
            else
                return FormatString("%s%dButton%d", mouse_str, mouse_id, int(btn-KEY_MOUSE_Button1));
        }
        }
    }

    // it's a keyboard key
    if (!fHumanReadable) {
        // for config files and such: dump scancode
        return FormatString("$%x", static_cast<unsigned int>(wCode));
    }
#if defined(USE_WIN32_WINDOWS) || (defined(_WIN32) && defined(USE_GTK))

    // Query map
    const C4KeyCodeMapEntry *pCheck = KeyCodeMap;
    while (pCheck->szName)
        if (wCode == pCheck->wCode) return StdStrBuf((pCheck->szShortName && fShort) ? pCheck->szShortName : pCheck->szName);
        else ++pCheck;

//  TODO: Works?
//  StdStrBuf Name; Name.SetLength(1000);
//  int res = GetKeyNameText(wCode, Name.getMData(), Name.getSize());
//  if(!res)
//    // not found: Compose as direct code
//    return FormatString("\\x%x", (DWORD) wCode);
//  // Set size
//  Name.SetLength(res);
//  return Name;

    wchar_t buf[100];
    int len = GetKeyNameText(wCode<<16, buf, 100);
    if (len > 0) {
        // buf is nullterminated name
        return StdStrBuf(buf);
    }
#elif defined (USE_COCOA)
    // query map
    const C4KeyCodeMapEntry *pCheck = KeyCodeMap;
    while (pCheck->szName)
        if (wCode == pCheck->wCode) return StdStrBuf((pCheck->szShortName && fShort) ? pCheck->szShortName : pCheck->szName);
        else ++pCheck;
    // not found: Compose as direct code
    return FormatString("\\x%x", static_cast<unsigned int>(wCode));
#elif defined(USE_GTK)
    Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default());
    KeySym keysym = (KeySym)XkbKeycodeToKeysym(dpy,wCode+8,0,0);
    char* name = NULL;
    if (keysym != NoSymbol) { // is the keycode without shift modifiers mapped to a symbol?
        name = gtk_accelerator_get_label_with_keycode(gdk_display_get_default(), keysym, wCode+8, (GdkModifierType)0);
    }
    if (name) { // is there a string representation of the keysym?
        // prevent memleak
        StdStrBuf buf;
        buf.Copy(name);
        g_free(name);
        return buf;
    }
#elif defined(USE_SDL_MAINLOOP)
    StdStrBuf buf;
    buf.Copy(SDL_GetScancodeName(static_cast<SDL_Scancode>(wCode)));
    if (!buf.getLength()) buf.Format("\\x%x", wCode);
    return buf;
#endif
    return FormatString("$%x", static_cast<unsigned int>(wCode));
}
Esempio n. 16
0
C4KeyCode C4KeyCodeEx::String2KeyCode(const StdStrBuf &sName)
{
    // direct key code?
    if (sName.getLength() > 2)
    {
        unsigned int dwRVal;
        if (sscanf(sName.getData(), "\\x%x", &dwRVal) == 1) return dwRVal;
        // scan code
        if (*sName.getData() == '$') return GetKeyByScanCode(sName.getData());
        // direct gamepad code
#ifdef _WIN32
        if (!strnicmp(sName.getData(), "Joy", 3))
#else
        if (!strncasecmp(sName.getData(), "Joy", 3))
#endif
        {
            int iGamepad;
            if (sscanf(sName.getData(), "Joy%d",  &iGamepad) == 1)
            {
                // skip Joy[number]
                const char *key_str = sName.getData()+4;
                while (isdigit(*key_str)) ++key_str;
                // check for button (single, uppercase letter) (e.g. Joy1A)
                if (*key_str && !key_str[1])
                {
                    char cGamepadButton = toupper(*key_str);
                    if (Inside(cGamepadButton, 'A', 'Z'))
                    {
                        cGamepadButton = cGamepadButton - 'A';
                        return KEY_Gamepad(iGamepad-1, KEY_JOY_Button(cGamepadButton));
                    }
                }
                else
                {
                    // check for standard axis (e.g. Joy1Left)
                    if (!stricmp(key_str, "Left")) return KEY_Gamepad(iGamepad-1, KEY_JOY_Left);
                    if (!stricmp(key_str, "Up")) return KEY_Gamepad(iGamepad-1, KEY_JOY_Up);
                    if (!stricmp(key_str, "Down")) return KEY_Gamepad(iGamepad-1, KEY_JOY_Down);
                    if (!stricmp(key_str, "Right")) return KEY_Gamepad(iGamepad-1, KEY_JOY_Right);
                    // check for specific axis (e.g. Joy1Axis1Min)
                    int iAxis;
                    if (sscanf(key_str, "Axis%d", &iAxis) == 1 && iAxis>0)
                    {
                        --iAxis; // axis is 0-based internally but written 1-based in config
                        key_str += 5;
                        while (isdigit(*key_str)) ++key_str;
                        if (!stricmp(key_str, "Min")) return KEY_Gamepad(iGamepad-1, KEY_JOY_Axis(iAxis, false));
                        if (!stricmp(key_str, "Max")) return KEY_Gamepad(iGamepad-1, KEY_JOY_Axis(iAxis, true));
                    }
                }
            }
        }
        bool is_mouse_key;
#ifdef _WIN32
        is_mouse_key = !strnicmp(sName.getData(), "Mouse", 5);
#else
        is_mouse_key = !strncasecmp(sName.getData(), "Mouse", 5);
#endif
        if (is_mouse_key)
        {
            // skip Mouse/GameMouse
            const char *key_str = sName.getData()+5;
            int mouse_id;
            if (sscanf(key_str, "%d",  &mouse_id) == 1)
            {
                // skip number
                while (isdigit(*key_str)) ++key_str;
                // check for known mouse events (e.g. Mouse1Move or GameMouse1Wheel)
                if (!stricmp(key_str, "Move")) return KEY_Mouse(mouse_id-1, KEY_MOUSE_Move);
                if (!stricmp(key_str, "Wheel1Up")) return KEY_Mouse(mouse_id-1, KEY_MOUSE_Wheel1Up);
                if (!stricmp(key_str, "Wheel1Down")) return KEY_Mouse(mouse_id-1, KEY_MOUSE_Wheel1Down);
                if (SEqualNoCase(key_str, "Button", 6)) // e.g. Mouse1ButtonLeft or GameMouse1ButtonRightDouble
                {
                    // check for known mouse button events
                    uint8_t mouseevent_id = 0;
                    key_str += 6;
                    if (SEqualNoCase(key_str, "Left",4)) {
                        mouseevent_id=KEY_MOUSE_ButtonLeft;
                        key_str += 4;
                    }
                    else if (SEqualNoCase(key_str, "Right",5)) {
                        mouseevent_id=KEY_MOUSE_ButtonRight;
                        key_str += 5;
                    }
                    else if (SEqualNoCase(key_str, "Middle",6)) {
                        mouseevent_id=KEY_MOUSE_ButtonMiddle;
                        key_str += 6;
                    }
                    else if (isdigit(*key_str))
                    {
                        // indexed mouse button (e.g. Mouse1Button4 or Mouse1Button4Double)
                        int button_index;
                        if (sscanf(key_str, "%d",  &button_index) == 1)
                        {
                            mouseevent_id=static_cast<uint8_t>(KEY_MOUSE_Button1+button_index-1);
                            while (isdigit(*key_str)) ++key_str;
                        }
                    }
                    if (mouseevent_id)
                    {
                        // valid event if finished or followed by "Double"
                        if (!*key_str) return KEY_Mouse(mouse_id-1, mouseevent_id);
                        if (!stricmp(key_str, "Double")) return KEY_Mouse(mouse_id-1, mouseevent_id+(KEY_MOUSE_Button1Double-KEY_MOUSE_Button1));
                        // invalid mouse key...
                    }
                }
            }
        }

    }
    // query map
    const C4KeyCodeMapEntry *pCheck = KeyCodeMap;
    while (pCheck->szName) {
        if (SEqualNoCase(sName.getData(), pCheck->szName)) {
            return(pCheck->wCode);
        }
        ++pCheck;
    }
#if defined(USE_SDL_MAINLOOP)
    SDL_Scancode s = SDL_GetScancodeFromName(sName.getData());
    if (s != SDL_SCANCODE_UNKNOWN) return s;
#endif
    return KEY_Undefined;
}
Esempio n. 17
0
// Copy the text to the clipboard or the primary selection
bool C4AbstractApp::Copy(const StdStrBuf & text, bool fClipboard)
{
	gtk_clipboard_set_text(gtk_clipboard_get(fClipboard ? GDK_SELECTION_CLIPBOARD : GDK_SELECTION_PRIMARY),
	                       text.getData(), text.getLength());
	return true;
}
Esempio n. 18
0
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);
		}
	}
Esempio n. 19
0
void C4KeyCodeEx::CompileFunc(StdCompiler *pComp, StdStrBuf *pOutBuf)
{
    if (pComp->isCompiler())
    {
        // reading from file
        StdStrBuf sCode;
        bool is_scan_code;
        // read shifts
        DWORD dwSetShift = 0;
        for (;;)
        {
            is_scan_code = pComp->Separator(StdCompiler::SEP_DOLLAR);
            if (!is_scan_code) pComp->NoSeparator();
            pComp->Value(mkParAdapt(sCode, StdCompiler::RCT_Idtf));
            if (is_scan_code) // scan codes start with $. Reassamble the two tokens that were split by StdCompiler
            {
                sCode.Take(FormatString("$%s", sCode.getData()));
                break;
            }
            if (!pComp->Separator(StdCompiler::SEP_PLUS)) break; // no more separator: Parse this as keyboard code
            // try to convert to shift state
            C4KeyShiftState eAddState = String2KeyShift(sCode);
            if (eAddState == KEYS_Undefined)
                pComp->excCorrupt("undefined key shift state: %s", sCode.getData());
            dwSetShift |= eAddState;
        }
        // any code given? Otherwise, keep default
        if (sCode.getLength())
        {
            // last section: convert to key code
            C4KeyCode eCode = String2KeyCode(sCode);
            if (eCode == KEY_Undefined)
            {
                if (pOutBuf)
                {
                    // unknown key, but an output buffer for unknown keys was provided. No failure; caller might resolve key.
                    eCode = KEY_Default;
                }
                else
                {
                    pComp->excCorrupt("undefined key code: %s", sCode.getData());
                }
            }
            dwShift = dwSetShift;
            Key = eCode;
            if (pOutBuf) pOutBuf->Take(std::move(sCode));
        }
    }
    else
    {
        // write shift states
        for (DWORD dwShiftCheck = KEYS_First; dwShiftCheck <= KEYS_Max; dwShiftCheck <<= 1)
            if (dwShiftCheck & dwShift)
            {
                pComp->Value(mkDecompileAdapt(KeyShift2String((C4KeyShiftState) dwShiftCheck)));
                pComp->Separator(StdCompiler::SEP_PLUS);
            }
        // write key
        pComp->Value(mkDecompileAdapt(KeyCode2String(Key, false, false)));
    }
}