/** * Create a new detail message for the GUI. * * @param type General message type * @param level Detailed message type * @param text Body of the message * @param data Optional field, used for auxiliary data */ void XmppClient::CreateSimpleMessage(const std::string& type, const std::string& text, const std::string& level, const std::string& data) { GUIMessage message; message.type = wstring_from_utf8(type); message.level = wstring_from_utf8(level); message.text = wstring_from_utf8(text); message.data = wstring_from_utf8(data); PushGuiMessage(message); }
/** * Handle a standard MUC textual message. */ void XmppClient::handleMUCMessage(glooxwrapper::MUCRoom*, const glooxwrapper::Message& msg, bool) { DbgXMPP(msg.from().resource() << " said " << msg.body()); GUIMessage message; message.type = L"mucmessage"; message.from = wstring_from_utf8(msg.from().resource().to_string()); message.text = wstring_from_utf8(msg.body().to_string()); PushGuiMessage(message); }
/** * Handle a standard textual message. */ void XmppClient::handleMessage(const glooxwrapper::Message& msg, glooxwrapper::MessageSession *) { DbgXMPP("type " << msg.subtype() << ", subject " << msg.subject() << ", message " << msg.body() << ", thread id " << msg.thread()); GUIMessage message; message.from = wstring_from_utf8(msg.from().username().to_string()); message.message = wstring_from_utf8(msg.body().to_string()); PushGuiMessage(message); }
void CNetTurnManager::DisplayOOSError(u32 turn, const std::string& hash, const std::string& expectedHash, bool isReplay, OsPath* path = NULL) { m_HasSyncError = true; std::stringstream msg; msg << "Out of sync on turn " << turn << ": expected hash " << expectedHash << "\n"; if (expectedHash != hash || m_CurrentTurn != turn) msg << "\nCurrent state: turn " << m_CurrentTurn << ", hash " << hash << "\n\n"; if (isReplay) msg << "\nThe current game state is different from the original game state.\n\n"; else { if (expectedHash == hash) msg << "Your game state is identical to the hosts game state.\n\n"; else msg << "Your game state is different from the hosts game state.\n\n"; } if (path) msg << "Dumping current state to " << utf8_from_wstring(OsPath(*path).string()); LOGERROR("%s", msg.str()); if (g_GUI) g_GUI->DisplayMessageBox(600, 350, L"Sync error", wstring_from_utf8(msg.str())); }
bool ScriptInterface::LoadGlobalScriptFile(const VfsPath& path) { JSAutoRequest rq(m->m_cx); JS::RootedObject global(m->m_cx, m->m_glob); if (!VfsFileExists(path)) { LOGERROR("File '%s' does not exist", path.string8()); return false; } CVFSFile file; PSRETURN ret = file.Load(g_VFS, path); if (ret != PSRETURN_OK) { LOGERROR("Failed to load file '%s': %s", path.string8(), GetErrorString(ret)); return false; } std::wstring code = wstring_from_utf8(file.DecodeUTF8()); // assume it's UTF-8 utf16string codeUtf16(code.begin(), code.end()); uint lineNo = 1; // CompileOptions does not copy the contents of the filename string pointer. // Passing a temporary string there will cause undefined behaviour, so we create a separate string to avoid the temporary. std::string filenameStr = path.string8(); JS::RootedValue rval(m->m_cx); JS::CompileOptions opts(m->m_cx); opts.setFileAndLine(filenameStr.c_str(), lineNo); return JS::Evaluate(m->m_cx, global, opts, reinterpret_cast<const char16_t*>(codeUtf16.c_str()), (uint)(codeUtf16.length()), &rval); }
CScriptValRooted ScriptInterface::ParseJSON(const std::string& string_utf8) { std::wstring attrsW = wstring_from_utf8(string_utf8); utf16string string(attrsW.begin(), attrsW.end()); jsval vp; JSONParser* parser = JS_BeginJSONParse(m->m_cx, &vp); if (!parser) { LOGERROR(L"ParseJSON failed to begin"); return CScriptValRooted(); } if (!JS_ConsumeJSONText(m->m_cx, parser, reinterpret_cast<const jschar*>(string.c_str()), (uint32)string.size())) { LOGERROR(L"ParseJSON failed to consume"); return CScriptValRooted(); } if (!JS_FinishJSONParse(m->m_cx, parser, JSVAL_NULL)) { LOGERROR(L"ParseJSON failed to finish"); return CScriptValRooted(); } return CScriptValRooted(m->m_cx, vp); }
bool ScriptInterface::LoadGlobalScriptFile(const VfsPath& path) { if (!VfsFileExists(path)) { LOGERROR(L"File '%ls' does not exist", path.string().c_str()); return false; } CVFSFile file; PSRETURN ret = file.Load(g_VFS, path); if (ret != PSRETURN_OK) { LOGERROR(L"Failed to load file '%ls': %hs", path.string().c_str(), GetErrorString(ret)); return false; } std::wstring code = wstring_from_utf8(file.DecodeUTF8()); // assume it's UTF-8 // Compile the code in strict mode, to encourage better coding practices and // to possibly help SpiderMonkey with optimisations std::wstring codeStrict = L"\"use strict\";\n" + code; utf16string codeUtf16(codeStrict.begin(), codeStrict.end()); uintN lineNo = 0; // put the automatic 'use strict' on line 0, so the real code starts at line 1 jsval rval; JSBool ok = JS_EvaluateUCScript(m->m_cx, m->m_glob, reinterpret_cast<const jschar*> (codeUtf16.c_str()), (uintN)(codeUtf16.length()), utf8_from_wstring(path.string()).c_str(), lineNo, &rval); return ok ? true : false; }
bool ScriptInterface::ParseJSON(const std::string& string_utf8, JS::MutableHandleValue out) { JSAutoRequest rq(m->m_cx); std::wstring attrsW = wstring_from_utf8(string_utf8); utf16string string(attrsW.begin(), attrsW.end()); if (JS_ParseJSON(m->m_cx, reinterpret_cast<const jschar*>(string.c_str()), (u32)string.size(), out)) return true; LOGERROR("JS_ParseJSON failed!"); if (!JS_IsExceptionPending(m->m_cx)) return false; JS::RootedValue exc(m->m_cx); if (!JS_GetPendingException(m->m_cx, &exc)) return false; JS_ClearPendingException(m->m_cx); // We expect an object of type SyntaxError if (!exc.isObject()) return false; JS::RootedValue rval(m->m_cx); JS::RootedObject excObj(m->m_cx, &exc.toObject()); if (!JS_CallFunctionName(m->m_cx, excObj, "toString", JS::HandleValueArray::empty(), &rval)) return false; std::wstring error; ScriptInterface::FromJSVal(m->m_cx, rval, error); LOGERROR("%s", utf8_from_wstring(error)); return false; }
bool ScriptInterface::LoadGlobalScriptFile(const VfsPath& path) { JSAutoRequest rq(m->m_cx); JS::RootedObject global(m->m_cx, m->m_glob); if (!VfsFileExists(path)) { LOGERROR("File '%s' does not exist", path.string8()); return false; } CVFSFile file; PSRETURN ret = file.Load(g_VFS, path); if (ret != PSRETURN_OK) { LOGERROR("Failed to load file '%s': %s", path.string8(), GetErrorString(ret)); return false; } std::wstring code = wstring_from_utf8(file.DecodeUTF8()); // assume it's UTF-8 utf16string codeUtf16(code.begin(), code.end()); uint lineNo = 1; JS::RootedValue rval(m->m_cx); return JS_EvaluateUCScript(m->m_cx, global, reinterpret_cast<const jschar*> (codeUtf16.c_str()), (uint)(codeUtf16.length()), utf8_from_wstring(path.string()).c_str(), lineNo, &rval); }
void CTemplateLoader::ConstructTemplateActor(const std::string& actorName, CParamNode& out) { // Load the base actor template if necessary const char* templateName = "special/actor"; if (!LoadTemplateFile(templateName, 0)) { LOGERROR("Failed to load entity template '%s'", templateName); return; } // Copy the actor template out = m_TemplateFileData[templateName]; // Initialise the actor's name and make it an Atlas selectable entity. std::wstring actorNameW = wstring_from_utf8(actorName); std::string name = utf8_from_wstring(CParamNode::EscapeXMLString(actorNameW)); std::string xml = "<Entity>" "<VisualActor><Actor>" + name + "</Actor><ActorOnly/></VisualActor>" // arbitrary-sized Footprint definition to make actors' selection outlines show up in Atlas "<Footprint><Circle radius='2.0'/><Height>1.0</Height></Footprint>" "<Selectable>" "<EditorOnly/>" "<Overlay><Texture><MainTexture>actor.png</MainTexture><MainTextureMask>actor_mask.png</MainTextureMask></Texture></Overlay>" "</Selectable>" "</Entity>"; CParamNode::LoadXMLString(out, xml.c_str(), actorNameW.c_str()); }
// Return a translated version of the items in the specified array. std::vector<std::wstring> JSI_L10n::TranslateArray(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const std::vector<std::wstring>& sourceArray) { std::vector<std::wstring> translatedArray; for (const std::wstring& elem : sourceArray) translatedArray.push_back(wstring_from_utf8(g_L10n.Translate(utf8_from_wstring(elem)))); return translatedArray; }
VfsPath L10n::LocalizePath(const VfsPath& sourcePath) const { VfsPath localizedPath = sourcePath.Parent() / L"l10n" / wstring_from_utf8(currentLocale.getLanguage()) / sourcePath.Filename(); if (!VfsFileExists(localizedPath)) return sourcePath; return localizedPath; }
std::wstring JSI_Lobby::LobbyGetNick(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) { if (!g_XmppClient) return L""; std::string nick; g_XmppClient->GetNick(nick); return wstring_from_utf8(nick); }
/** * Handle requests from the GUI for the list of players. * * @return A JS array containing all known players and their presences */ CScriptValRooted XmppClient::GUIGetPlayerList(ScriptInterface& scriptInterface) { std::string presence; CScriptValRooted playerList; scriptInterface.Eval("({})", playerList); for(std::map<std::string, gloox::Presence::PresenceType>::const_iterator it = m_PlayerMap.begin(); it != m_PlayerMap.end(); ++it) { CScriptValRooted player; GetPresenceString(it->second, presence); scriptInterface.Eval("({})", player); scriptInterface.SetProperty(player.get(), "name", wstring_from_utf8(it->first)); scriptInterface.SetProperty(player.get(), "presence", wstring_from_utf8(presence)); scriptInterface.SetProperty(playerList.get(), wstring_from_utf8(it->first).c_str(), player); } return playerList; }
std::wstring JSI_Lobby::LobbyGetRoomSubject(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) { if (!g_XmppClient) return L""; std::string subject; g_XmppClient->GetSubject(subject); return wstring_from_utf8(subject); }
std::wstring JSI_Lobby::LobbyGetPlayerRole(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::wstring nickname) { if (!g_XmppClient) return L""; std::string role; g_XmppClient->GetRole(utf8_from_wstring(nickname), role); return wstring_from_utf8(role); }
/** * Handle requests from the GUI for the list of players. * * @return A JS array containing all known players and their presences */ CScriptValRooted XmppClient::GUIGetPlayerList(ScriptInterface& scriptInterface) { CScriptValRooted playerList; scriptInterface.Eval("([])", playerList); // Convert the internal data structure to a Javascript object. for (std::map<std::string, std::vector<std::string> >::const_iterator it = m_PlayerMap.begin(); it != m_PlayerMap.end(); ++it) { CScriptValRooted player; scriptInterface.Eval("({})", player); scriptInterface.SetProperty(player.get(), "name", wstring_from_utf8(it->first)); scriptInterface.SetProperty(player.get(), "presence", wstring_from_utf8(it->second[0])); scriptInterface.SetProperty(player.get(), "rating", wstring_from_utf8(it->second[1])); scriptInterface.SetProperty(player.get(), "role", wstring_from_utf8(it->second[2])); scriptInterface.CallFunctionVoid(playerList.get(), "push", player); } return playerList; }
std::vector<std::wstring> L10n::GetSupportedLocaleDisplayNames() const { std::vector<std::wstring> supportedLocaleDisplayNames; for (Locale* const& locale : availableLocales) { if (strcmp(locale->getBaseName(), "long") == 0) { if (InDevelopmentCopy()) supportedLocaleDisplayNames.push_back(wstring_from_utf8(Translate("Long strings"))); continue; } UnicodeString utf16LocaleDisplayName; locale->getDisplayName(*locale, utf16LocaleDisplayName); char localeDisplayName[512]; CheckedArrayByteSink sink(localeDisplayName, ARRAY_SIZE(localeDisplayName)); utf16LocaleDisplayName.toUTF8(sink); ENSURE(!sink.Overflowed()); supportedLocaleDisplayNames.push_back(wstring_from_utf8(std::string(localeDisplayName, sink.NumberOfBytesWritten()))); } return supportedLocaleDisplayNames; }
bool ScriptInterface::LoadGlobalScript(const VfsPath& filename, const std::string& code) { // Compile the code in strict mode, to encourage better coding practices and // to possibly help SpiderMonkey with optimisations std::wstring codeStrict = L"\"use strict\";\n" + wstring_from_utf8(code); utf16string codeUtf16(codeStrict.begin(), codeStrict.end()); uintN lineNo = 0; // put the automatic 'use strict' on line 0, so the real code starts at line 1 jsval rval; JSBool ok = JS_EvaluateUCScript(m->m_cx, m->m_glob, reinterpret_cast<const jschar*> (codeUtf16.c_str()), (uintN)(codeUtf16.length()), utf8_from_wstring(filename.string()).c_str(), lineNo, &rval); return ok ? true : false; }
wchar_t* sys_clipboard_get() { wchar_t* ret = NULL; std::string str; bool ok = osx_GetStringFromPasteboard(str); if (ok) { // TODO: this is yucky, why are we passing around wchar_t*? std::wstring wstr = wstring_from_utf8(str); size_t len = wcslen(wstr.c_str()); ret = (wchar_t*)malloc((len+1)*sizeof(wchar_t)); std::copy(wstr.c_str(), wstr.c_str()+len, ret); ret[len] = 0; } return ret; }
void IDeserializer::String(const char* name, std::wstring& out, uint32_t minlength, uint32_t maxlength) { std::string str; uint32_t len; NumberU32_Unbounded("string length", len); RequireBytesInStream(len); str.resize(len); Get(name, (u8*)str.data(), len); Status err; out = wstring_from_utf8(str, &err); if (err) throw PSERROR_Deserialize_InvalidCharInString(); if (!(minlength <= out.length() && out.length() <= maxlength)) throw PSERROR_Deserialize_OutOfBounds(name); }
/** * Handle requests from the GUI for the list of all active games. * * @return A JS array containing all known games */ CScriptValRooted XmppClient::GUIGetGameList(ScriptInterface& scriptInterface) { CScriptValRooted gameList; scriptInterface.Eval("([])", gameList); for(std::vector<const glooxwrapper::Tag*>::const_iterator it = m_GameList.begin(); it != m_GameList.end(); ++it) { CScriptValRooted game; scriptInterface.Eval("({})", game); const char* stats[] = { "name", "ip", "state", "nbp", "tnbp", "players", "mapName", "niceMapName", "mapSize", "mapType", "victoryCondition" }; short stats_length = 11; for (short i = 0; i < stats_length; i++) scriptInterface.SetProperty(game.get(), stats[i], wstring_from_utf8((*it)->findAttribute(stats[i]).to_string())); scriptInterface.CallFunctionVoid(gameList.get(), "push", game); } return gameList; }
/** * Handle requests from the GUI for leaderboard data. * * @return A JS array containing all known leaderboard data */ CScriptValRooted XmppClient::GUIGetBoardList(ScriptInterface& scriptInterface) { CScriptValRooted boardList; scriptInterface.Eval("([])", boardList); for(std::vector<const glooxwrapper::Tag*>::const_iterator it = m_BoardList.begin(); it != m_BoardList.end(); ++it) { CScriptValRooted board; scriptInterface.Eval("({})", board); const char* attributes[] = { "name", "rank", "rating" }; short attributes_length = 3; for (short i = 0; i < attributes_length; i++) scriptInterface.SetProperty(board.get(), attributes[i], wstring_from_utf8((*it)->findAttribute(attributes[i]).to_string())); scriptInterface.CallFunctionVoid(boardList.get(), "push", board); } return boardList; }
// globalObject defaults to 0 (in which case we use our m_GlobalObject). void ScriptingHost::RunScript(const VfsPath& pathname, JSObject* globalObject) { if(!globalObject) globalObject = m_GlobalObject; shared_ptr<u8> buf; size_t size; if(g_VFS->LoadFile(pathname, buf, size) != INFO::OK) // ERRTODO: translate/pass it on throw PSERROR_Scripting_LoadFile_OpenFailed(); std::wstring scriptw = wstring_from_utf8(std::string(buf.get(), buf.get() + size)); utf16string script(scriptw.begin(), scriptw.end()); jsval rval; JSBool ok = JS_EvaluateUCScript(m_Context, globalObject, reinterpret_cast<const jschar*>(script.c_str()), (uintN)script.size(), utf8_from_wstring(pathname.string()).c_str(), 1, &rval); if (ok == JS_FALSE) throw PSERROR_Scripting_LoadFile_EvalErrors(); }
void CConsole::InsertMessage(const std::string& message) { // (TODO: this text-wrapping is rubbish since we now use variable-width fonts) //Insert newlines to wraparound text where needed std::wstring wrapAround = wstring_from_utf8(message.c_str()); std::wstring newline(L"\n"); size_t oldNewline=0; size_t distance; //make sure everything has been initialized if ( m_charsPerPage != 0 ) { while ( oldNewline+m_charsPerPage < wrapAround.length() ) { distance = wrapAround.find(newline, oldNewline) - oldNewline; if ( distance > m_charsPerPage ) { oldNewline += m_charsPerPage; wrapAround.insert( oldNewline++, newline ); } else oldNewline += distance+1; } } // Split into lines and add each one individually oldNewline = 0; { CScopeLock lock(m_Mutex); // needed for safe access to m_deqMsgHistory while ( (distance = wrapAround.find(newline, oldNewline)) != wrapAround.npos) { distance -= oldNewline; m_deqMsgHistory.push_front(wrapAround.substr(oldNewline, distance)); oldNewline += distance+1; } m_deqMsgHistory.push_front(wrapAround.substr(oldNewline)); } }
void CNetTurnManager::DisplayOOSError(u32 turn, const CStr& hash, const CStr& expectedHash, bool isReplay, std::vector<CSyncErrorMessage::S_m_PlayerNames>* playerNames = NULL, OsPath* path = NULL) { m_HasSyncError = true; std::stringstream msg; msg << "Out of sync on turn " << turn; if (playerNames) for (size_t i = 0; i < playerNames->size(); ++i) msg << (i == 0 ? "\nPlayers: " : ", ") << utf8_from_wstring((*playerNames)[i].m_Name); if (isReplay) msg << "\n\n" << "The current game state is different from the original game state."; else msg << "\n\n" << "Your game state is " << (expectedHash == hash ? "identical to" : "different from") << " the hosts game state."; if (path) msg << "\n\n" << "Dumping current state to " << CStr(path->string8()).EscapeToPrintableASCII(); LOGERROR("%s", msg.str()); if (g_GUI) g_GUI->DisplayMessageBox(600, 350, L"Sync error", wstring_from_utf8(msg.str())); }
void debug_puts(const char* text) { OutputDebugStringW(wstring_from_utf8(text).c_str()); }
bool CShaderManager::NewProgram(const char* name, const CShaderDefines& baseDefines, CShaderProgramPtr& program) { PROFILE2("loading shader"); PROFILE2_ATTR("name: %s", name); if (strncmp(name, "fixed:", 6) == 0) { program = CShaderProgramPtr(CShaderProgram::ConstructFFP(name+6, baseDefines)); if (!program) return false; program->Reload(); return true; } VfsPath xmlFilename = L"shaders/" + wstring_from_utf8(name) + L".xml"; CXeromyces XeroFile; PSRETURN ret = XeroFile.Load(g_VFS, xmlFilename); if (ret != PSRETURN_OK) return false; #if USE_SHADER_XML_VALIDATION { TIMER_ACCRUE(tc_ShaderValidation); // Serialize the XMB data and pass it to the validator XML_Start(); XML_SetPrettyPrint(false); XML_WriteXMB(XeroFile); bool ok = m_Validator.ValidateEncoded(wstring_from_utf8(name), XML_GetOutput()); if (!ok) return false; } #endif // Define all the elements and attributes used in the XML file #define EL(x) int el_##x = XeroFile.GetElementID(#x) #define AT(x) int at_##x = XeroFile.GetAttributeID(#x) EL(attrib); EL(define); EL(fragment); EL(stream); EL(uniform); EL(vertex); AT(file); AT(if); AT(loc); AT(name); AT(semantics); AT(type); AT(value); #undef AT #undef EL CPreprocessorWrapper preprocessor; preprocessor.AddDefines(baseDefines); XMBElement Root = XeroFile.GetRoot(); bool isGLSL = (Root.GetAttributes().GetNamedItem(at_type) == "glsl"); VfsPath vertexFile; VfsPath fragmentFile; CShaderDefines defines = baseDefines; std::map<CStrIntern, int> vertexUniforms; std::map<CStrIntern, CShaderProgram::frag_index_pair_t> fragmentUniforms; std::map<CStrIntern, int> vertexAttribs; int streamFlags = 0; XERO_ITER_EL(Root, Child) { if (Child.GetNodeName() == el_define) { defines.Add(CStrIntern(Child.GetAttributes().GetNamedItem(at_name)), CStrIntern(Child.GetAttributes().GetNamedItem(at_value))); } else if (Child.GetNodeName() == el_vertex) { vertexFile = L"shaders/" + Child.GetAttributes().GetNamedItem(at_file).FromUTF8(); XERO_ITER_EL(Child, Param) { XMBAttributeList Attrs = Param.GetAttributes(); CStr cond = Attrs.GetNamedItem(at_if); if (!cond.empty() && !preprocessor.TestConditional(cond)) continue; if (Param.GetNodeName() == el_uniform) { vertexUniforms[CStrIntern(Attrs.GetNamedItem(at_name))] = Attrs.GetNamedItem(at_loc).ToInt(); } else if (Param.GetNodeName() == el_stream) { CStr StreamName = Attrs.GetNamedItem(at_name); if (StreamName == "pos") streamFlags |= STREAM_POS; else if (StreamName == "normal") streamFlags |= STREAM_NORMAL; else if (StreamName == "color") streamFlags |= STREAM_COLOR; else if (StreamName == "uv0") streamFlags |= STREAM_UV0; else if (StreamName == "uv1") streamFlags |= STREAM_UV1; else if (StreamName == "uv2") streamFlags |= STREAM_UV2; else if (StreamName == "uv3") streamFlags |= STREAM_UV3; } else if (Param.GetNodeName() == el_attrib) { int attribLoc = ParseAttribSemantics(Attrs.GetNamedItem(at_semantics)); vertexAttribs[CStrIntern(Attrs.GetNamedItem(at_name))] = attribLoc; } } }
/** * Convert UTF-8 to CStr * * @return CStrW converted string **/ CStrW CStr8::FromUTF8() const { Status err; return wstring_from_utf8(*this, &err); }
InReaction conInputHandler(const SDL_Event_* ev) { if ((int)ev->ev.type == SDL_HOTKEYDOWN) { std::string hotkey = static_cast<const char*>(ev->ev.user.data1); if (hotkey == "console.toggle") { g_Console->ToggleVisible(); return IN_HANDLED; } else if (g_Console->IsActive() && hotkey == "copy") { sys_clipboard_set(g_Console->GetBuffer()); return IN_HANDLED; } else if (g_Console->IsActive() && hotkey == "paste") { wchar_t* text = sys_clipboard_get(); if (text) { for (wchar_t* c = text; *c; c++) g_Console->InsertChar(0, *c); sys_clipboard_free(text); } return IN_HANDLED; } } if (!g_Console->IsActive()) return IN_PASS; // In SDL2, we no longer get Unicode wchars via SDL_Keysym // we use text input events instead and they provide UTF-8 chars if (ev->ev.type == SDL_TEXTINPUT && !HotkeyIsPressed("console.toggle")) { // TODO: this could be more efficient with an interface to insert UTF-8 strings directly std::wstring wstr = wstring_from_utf8(ev->ev.text.text); for (size_t i = 0; i < wstr.length(); ++i) g_Console->InsertChar(0, wstr[i]); return IN_HANDLED; } // TODO: text editing events for IME support if (ev->ev.type != SDL_KEYDOWN) return IN_PASS; int sym = ev->ev.key.keysym.sym; // Stop unprintable characters (ctrl+, alt+ and escape), // also prevent ` and/or ~ appearing in console every time it's toggled. if (!isUnprintableChar(ev->ev.key.keysym) && !HotkeyIsPressed("console.toggle")) { g_Console->InsertChar(sym, 0); return IN_HANDLED; } return IN_PASS; }