static const char *StrUTF8Ltrim(const char *pStr) { while(*pStr) { const char *pStrOld = pStr; int Code = str_utf8_decode(&pStr); // check if unicode is not empty if(Code > 0x20 && Code != 0xA0 && Code != 0x034F && (Code < 0x2000 || Code > 0x200F) && (Code < 0x2028 || Code > 0x202F) && (Code < 0x205F || Code > 0x2064) && (Code < 0x206A || Code > 0x206F) && (Code < 0xFE00 || Code > 0xFE0F) && Code != 0xFEFF && (Code < 0xFFF9 || Code > 0xFFFC)) { return pStrOld; } } return pStr; }
int str_utf8_skeleton_next(struct SKELETON *skel) { int ch = 0; while(skel->skeleton_len == 0) { ch = str_utf8_decode(&skel->str); if(ch == 0) { return 0; } str_utf8_skeleton(ch, &skel->skeleton, &skel->skeleton_len); } skel->skeleton_len--; if(skel->skeleton != NULL) { ch = *skel->skeleton; skel->skeleton++; } return ch; }
static void StrUTF8Rtrim(char *pStr) { const char *p = pStr; const char *pEnd = 0; while(*p) { const char *pStrOld = p; int Code = str_utf8_decode(&p); // check if unicode is not empty if(Code > 0x20 && Code != 0xA0 && Code != 0x034F && (Code < 0x2000 || Code > 0x200F) && (Code < 0x2028 || Code > 0x202F) && (Code < 0x205F || Code > 0x2064) && (Code < 0x206A || Code > 0x206F) && (Code < 0xFE00 || Code > 0xFE0F) && Code != 0xFEFF && (Code < 0xFFF9 || Code > 0xFFFC)) { pEnd = 0; } else if(pEnd == 0) pEnd = pStrOld; } if(pEnd != 0) *(const_cast<char *>(pEnd)) = 0; }
void CChat::AddLine(int ClientID, int Team, const char *pLine) { if(*pLine == 0 || (ClientID != -1 && (m_pClient->m_aClients[ClientID].m_aName[0] == '\0' || // unknown client m_pClient->m_aClients[ClientID].m_ChatIgnore || (m_pClient->m_Snap.m_LocalClientID != ClientID && g_Config.m_ClShowChatFriends && !m_pClient->m_aClients[ClientID].m_Friend) || (m_pClient->m_Snap.m_LocalClientID != ClientID && m_pClient->m_aClients[ClientID].m_Foe)))) return; // trim right and set maximum length to 256 utf8-characters int Length = 0; const char *pStr = pLine; const char *pEnd = 0; while(*pStr) { const char *pStrOld = pStr; int Code = str_utf8_decode(&pStr); // check if unicode is not empty if(str_utf8_isspace(Code)) { pEnd = 0; } else if(pEnd == 0) pEnd = pStrOld; if(++Length >= 256) { *(const_cast<char *>(pStr)) = 0; break; } } if(pEnd != 0) *(const_cast<char *>(pEnd)) = 0; bool Highlighted = false; char *p = const_cast<char*>(pLine); while(*p) { Highlighted = false; pLine = p; // find line seperator and strip multiline while(*p) { if(*p++ == '\n') { *(p-1) = 0; break; } } m_CurrentLine = (m_CurrentLine+1)%MAX_LINES; m_aLines[m_CurrentLine].m_Time = time_get(); m_aLines[m_CurrentLine].m_YOffset[0] = -1.0f; m_aLines[m_CurrentLine].m_YOffset[1] = -1.0f; m_aLines[m_CurrentLine].m_ClientID = ClientID; m_aLines[m_CurrentLine].m_Team = Team; m_aLines[m_CurrentLine].m_NameColor = -2; // check for highlighted name if (Client()->State() != IClient::STATE_DEMOPLAYBACK) { if(ClientID != m_pClient->Client()->m_LocalIDs[0]) { // main character if (LineShouldHighlight(pLine, m_pClient->m_aClients[m_pClient->Client()->m_LocalIDs[0]].m_aName)) Highlighted = true; // dummy if(m_pClient->Client()->DummyConnected() && LineShouldHighlight(pLine, m_pClient->m_aClients[m_pClient->Client()->m_LocalIDs[1]].m_aName)) Highlighted = true; } } else { // on demo playback use local id from snap directly, // since m_LocalIDs isn't valid there if (LineShouldHighlight(pLine, m_pClient->m_aClients[m_pClient->m_Snap.m_LocalClientID].m_aName)) Highlighted = true; } m_aLines[m_CurrentLine].m_Highlighted = Highlighted; if(ClientID == -1) // server message { str_copy(m_aLines[m_CurrentLine].m_aName, "*** ", sizeof(m_aLines[m_CurrentLine].m_aName)); str_format(m_aLines[m_CurrentLine].m_aText, sizeof(m_aLines[m_CurrentLine].m_aText), "%s", pLine); } else { if(m_pClient->m_aClients[ClientID].m_Team == TEAM_SPECTATORS) m_aLines[m_CurrentLine].m_NameColor = TEAM_SPECTATORS; if(m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags&GAMEFLAG_TEAMS) { if(m_pClient->m_aClients[ClientID].m_Team == TEAM_RED) m_aLines[m_CurrentLine].m_NameColor = TEAM_RED; else if(m_pClient->m_aClients[ClientID].m_Team == TEAM_BLUE) m_aLines[m_CurrentLine].m_NameColor = TEAM_BLUE; } if (Team == 2) // whisper send { str_format(m_aLines[m_CurrentLine].m_aName, sizeof(m_aLines[m_CurrentLine].m_aName), "→ %s", m_pClient->m_aClients[ClientID].m_aName); m_aLines[m_CurrentLine].m_NameColor = TEAM_BLUE; m_aLines[m_CurrentLine].m_Highlighted = false; m_aLines[m_CurrentLine].m_Team = 0; Highlighted = false; } else if (Team == 3) // whisper recv { str_format(m_aLines[m_CurrentLine].m_aName, sizeof(m_aLines[m_CurrentLine].m_aName), "← %s", m_pClient->m_aClients[ClientID].m_aName); m_aLines[m_CurrentLine].m_NameColor = TEAM_RED; m_aLines[m_CurrentLine].m_Highlighted = true; m_aLines[m_CurrentLine].m_Team = 0; Highlighted = true; } else { str_copy(m_aLines[m_CurrentLine].m_aName, m_pClient->m_aClients[ClientID].m_aName, sizeof(m_aLines[m_CurrentLine].m_aName)); } str_format(m_aLines[m_CurrentLine].m_aText, sizeof(m_aLines[m_CurrentLine].m_aText), ": %s", pLine); } char aBuf[1024]; str_format(aBuf, sizeof(aBuf), "%s%s", m_aLines[m_CurrentLine].m_aName, m_aLines[m_CurrentLine].m_aText); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, Team >= 2?"whisper":(m_aLines[m_CurrentLine].m_Team?"teamchat":"chat"), aBuf, Highlighted); } // play sound int64 Now = time_get(); if(ClientID == -1) { if(Now-m_aLastSoundPlayed[CHAT_SERVER] >= time_freq()*3/10) { if(g_Config.m_SndServerMessage) { m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_SERVER, 0); m_aLastSoundPlayed[CHAT_SERVER] = Now; } } } else if(Highlighted) { if(Now-m_aLastSoundPlayed[CHAT_HIGHLIGHT] >= time_freq()*3/10) { #ifdef CONF_PLATFORM_MACOSX char aBuf[1024]; str_format(aBuf, sizeof(aBuf), "%s%s", m_aLines[m_CurrentLine].m_aName, m_aLines[m_CurrentLine].m_aText); CNotification::notify("DDNet-Chat", aBuf); #else Graphics()->NotifyWindow(); #endif if(g_Config.m_SndHighlight) { m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_HIGHLIGHT, 0); m_aLastSoundPlayed[CHAT_HIGHLIGHT] = Now; } } } else if(Team != 2) { if(Now-m_aLastSoundPlayed[CHAT_CLIENT] >= time_freq()*3/10) { if ((g_Config.m_SndTeamChat || !m_aLines[m_CurrentLine].m_Team) && (g_Config.m_SndChat || m_aLines[m_CurrentLine].m_Team)) { m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_CLIENT, 0); m_aLastSoundPlayed[CHAT_CLIENT] = Now; } } } }
void CChat::AddLine(int ClientID, int Team, const char *pLine) { if(*pLine == 0 || (ClientID != -1 && (!g_Config.m_ClShowsocial || m_pClient->m_aClients[ClientID].m_aName[0] == '\0' || // unknown client m_pClient->m_aClients[ClientID].m_ChatIgnore || (m_pClient->m_LocalClientID != ClientID && g_Config.m_ClShowChatFriends && !m_pClient->m_aClients[ClientID].m_Friend)))) return; // trim right and set maximum length to 128 utf8-characters int Length = 0; const char *pStr = pLine; const char *pEnd = 0; while(*pStr) { const char *pStrOld = pStr; int Code = str_utf8_decode(&pStr); // check if unicode is not empty if(Code > 0x20 && Code != 0xA0 && Code != 0x034F && (Code < 0x2000 || Code > 0x200F) && (Code < 0x2028 || Code > 0x202F) && (Code < 0x205F || Code > 0x2064) && (Code < 0x206A || Code > 0x206F) && (Code < 0xFE00 || Code > 0xFE0F) && Code != 0xFEFF && (Code < 0xFFF9 || Code > 0xFFFC)) { pEnd = 0; } else if(pEnd == 0) pEnd = pStrOld; if(++Length >= 127) { *(const_cast<char *>(pStr)) = 0; break; } } if(pEnd != 0) *(const_cast<char *>(pEnd)) = 0; bool Highlighted = false; char *p = const_cast<char*>(pLine); while(*p) { Highlighted = false; pLine = p; // find line seperator and strip multiline while(*p) { if(*p++ == '\n') { *(p-1) = 0; break; } } m_CurrentLine = (m_CurrentLine+1)%MAX_LINES; m_aLines[m_CurrentLine].m_Time = time_get(); m_aLines[m_CurrentLine].m_YOffset[0] = -1.0f; m_aLines[m_CurrentLine].m_YOffset[1] = -1.0f; m_aLines[m_CurrentLine].m_ClientID = ClientID; m_aLines[m_CurrentLine].m_Team = Team; m_aLines[m_CurrentLine].m_NameColor = -2; // check for highlighted name const char *pHL = str_find_nocase(pLine, m_pClient->m_aClients[m_pClient->m_LocalClientID].m_aName); if(pHL) { int Length = str_length(m_pClient->m_aClients[m_pClient->m_LocalClientID].m_aName); if((pLine == pHL || pHL[-1] == ' ') && (pHL[Length] == 0 || pHL[Length] == ' ' || (pHL[Length] == ':' && pHL[Length+1] == ' '))) Highlighted = true; m_CompletionFav = ClientID; } m_aLines[m_CurrentLine].m_Highlighted = Highlighted; if(ClientID == -1) // server message { str_copy(m_aLines[m_CurrentLine].m_aName, "*** ", sizeof(m_aLines[m_CurrentLine].m_aName)); str_format(m_aLines[m_CurrentLine].m_aText, sizeof(m_aLines[m_CurrentLine].m_aText), "%s", pLine); } else { if(m_pClient->m_aClients[ClientID].m_Team == TEAM_SPECTATORS) m_aLines[m_CurrentLine].m_NameColor = TEAM_SPECTATORS; if(m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS) { if(m_pClient->m_aClients[ClientID].m_Team == TEAM_RED) m_aLines[m_CurrentLine].m_NameColor = TEAM_RED; else if(m_pClient->m_aClients[ClientID].m_Team == TEAM_BLUE) m_aLines[m_CurrentLine].m_NameColor = TEAM_BLUE; } str_format(m_aLines[m_CurrentLine].m_aName, sizeof(m_aLines[m_CurrentLine].m_aName), "%2d: %s", ClientID, m_pClient->m_aClients[ClientID].m_aName); str_format(m_aLines[m_CurrentLine].m_aText, sizeof(m_aLines[m_CurrentLine].m_aText), ": %s", pLine); } char aBuf[1024]; str_format(aBuf, sizeof(aBuf), "%s%s", m_aLines[m_CurrentLine].m_aName, m_aLines[m_CurrentLine].m_aText); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, m_aLines[m_CurrentLine].m_Team?"teamchat":"chat", aBuf, Highlighted); } // play sound int64 Now = time_get(); if(ClientID == -1) { if(Now-m_aLastSoundPlayed[CHAT_SERVER] >= time_freq()*3/10) { m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_SERVER, 0); m_aLastSoundPlayed[CHAT_SERVER] = Now; } } else if(Highlighted) { if(Now-m_aLastSoundPlayed[CHAT_HIGHLIGHT] >= time_freq()*3/10) { m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_HIGHLIGHT, 0); m_aLastSoundPlayed[CHAT_HIGHLIGHT] = Now; } } else { if(Now-m_aLastSoundPlayed[CHAT_CLIENT] >= time_freq()*3/10) { m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_CLIENT, 0); m_aLastSoundPlayed[CHAT_CLIENT] = Now; } } }