GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* |
||
2 |
* The ManaPlus Client |
||
3 |
* Copyright (C) 2004-2009 The Mana World Development Team |
||
4 |
* Copyright (C) 2009-2010 The Mana Developers |
||
5 |
* Copyright (C) 2011-2019 The ManaPlus Developers |
||
6 |
* Copyright (C) 2019-2021 Andrei Karas |
||
7 |
* |
||
8 |
* This file is part of The ManaPlus Client. |
||
9 |
* |
||
10 |
* This program is free software; you can redistribute it and/or modify |
||
11 |
* it under the terms of the GNU General Public License as published by |
||
12 |
* the Free Software Foundation; either version 2 of the License, or |
||
13 |
* any later version. |
||
14 |
* |
||
15 |
* This program is distributed in the hope that it will be useful, |
||
16 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
17 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
18 |
* GNU General Public License for more details. |
||
19 |
* |
||
20 |
* You should have received a copy of the GNU General Public License |
||
21 |
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
22 |
*/ |
||
23 |
|||
24 |
#include "gui/windows/chatwindow.h" |
||
25 |
|||
26 |
#include "actormanager.h" |
||
27 |
#include "game.h" |
||
28 |
#include "guild.h" |
||
29 |
#include "party.h" |
||
30 |
#include "settings.h" |
||
31 |
#include "spellmanager.h" |
||
32 |
|||
33 |
#include "being/localplayer.h" |
||
34 |
#include "being/playerinfo.h" |
||
35 |
#include "being/playerrelations.h" |
||
36 |
|||
37 |
#include "const/gui/chat.h" |
||
38 |
|||
39 |
#include "fs/virtfs/tools.h" |
||
40 |
|||
41 |
#include "input/inputmanager.h" |
||
42 |
|||
43 |
#include "gui/focushandler.h" |
||
44 |
#include "gui/gui.h" |
||
45 |
#include "gui/skin.h" |
||
46 |
#include "gui/viewport.h" |
||
47 |
|||
48 |
#include "gui/models/colorlistmodel.h" |
||
49 |
|||
50 |
#include "gui/popups/popupmenu.h" |
||
51 |
|||
52 |
#include "gui/windows/setupwindow.h" |
||
53 |
#include "gui/windows/whoisonline.h" |
||
54 |
|||
55 |
#include "gui/widgets/button.h" |
||
56 |
#include "gui/widgets/chatinput.h" |
||
57 |
#include "gui/widgets/createwidget.h" |
||
58 |
#include "gui/widgets/dropdown.h" |
||
59 |
#include "gui/widgets/itemlinkhandler.h" |
||
60 |
#include "gui/widgets/scrollarea.h" |
||
61 |
#include "gui/widgets/tabbedarea.h" |
||
62 |
|||
63 |
#include "gui/widgets/tabs/chat/battletab.h" |
||
64 |
#include "gui/widgets/tabs/chat/channeltab.h" |
||
65 |
#include "gui/widgets/tabs/chat/gmtab.h" |
||
66 |
#include "gui/widgets/tabs/chat/langtab.h" |
||
67 |
#include "gui/widgets/tabs/chat/tradetab.h" |
||
68 |
#include "gui/widgets/tabs/chat/whispertab.h" |
||
69 |
|||
70 |
#include "render/opengl/opengldebug.h" |
||
71 |
|||
72 |
#include "resources/db/textdb.h" |
||
73 |
|||
74 |
#include "net/chathandler.h" |
||
75 |
#include "net/net.h" |
||
76 |
|||
77 |
#include "utils/copynpaste.h" |
||
78 |
#include "utils/delete2.h" |
||
79 |
#include "utils/foreach.h" |
||
80 |
|||
81 |
#include "utils/translation/podict.h" |
||
82 |
|||
83 |
#include <sys/stat.h> |
||
84 |
|||
85 |
#include <fstream> |
||
86 |
#include <sstream> |
||
87 |
|||
88 |
#ifdef __SWITCH__ |
||
89 |
#include "enums/input/keyvalue.h" |
||
90 |
#endif |
||
91 |
|||
92 |
#include "debug.h" |
||
93 |
|||
94 |
ChatWindow *chatWindow = nullptr; |
||
95 |
|||
96 |
static const char *const ACTION_COLOR_PICKER = "color picker"; |
||
97 |
|||
98 |
2 |
ChatWindow::ChatWindow(const std::string &name) : |
|
99 |
// TRANSLATORS: chat window name |
||
100 |
2 |
Window(_("Chat"), Modal_false, nullptr, "chat.xml"), |
|
101 |
ActionListener(), |
||
102 |
KeyListener(), |
||
103 |
AttributeListener(), |
||
104 |
✓✗✓✗ |
2 |
mItemLinkHandler(new ItemLinkHandler), |
105 |
✓✗✓✗ ✓✗✓✗ ✓✗ |
2 |
mChatTabs(CREATEWIDGETR(TabbedArea, this)), |
106 |
✓✗✓✗ |
2 |
mChatInput(new ChatInput(this)), |
107 |
mRainbowColor(0U), |
||
108 |
mWhispers(), |
||
109 |
mChannels(), |
||
110 |
mHistory(), |
||
111 |
mCurHist(), |
||
112 |
mCommands(), |
||
113 |
mCustomWords(), |
||
114 |
mTradeFilter(), |
||
115 |
✓✗ | 4 |
mColorListModel(new ColorListModel), |
116 |
2 |
mColorPicker(new DropDown(this, mColorListModel, |
|
117 |
✓✗✓✗ |
6 |
false, Modal_false, nullptr, std::string())), |
118 |
✓✗✓✗ |
2 |
mChatButton(new Button(this, ":)", "openemote", BUTTON_SKIN, this)), |
119 |
mAwayLog(), |
||
120 |
mHighlights(), |
||
121 |
mGlobalsFilter(), |
||
122 |
✓✗✓✗ |
8 |
mChatColor(config.getIntValue("chatColor")), |
123 |
✓✗✓✗ |
4 |
mEmoteButtonSpacing(mSkin != nullptr ? |
124 |
✓✗✓✗ ✗✗ |
8 |
mSkin->getOption("emoteButtonSpacing", 2) : 2), |
125 |
✓✗✓✗ |
4 |
mEmoteButtonY(mSkin != nullptr ? |
126 |
✓✗✓✗ ✗✗ |
8 |
mSkin->getOption("emoteButtonY", -2) : -2), |
127 |
mChatHistoryIndex(0), |
||
128 |
✓✗✓✗ |
8 |
mReturnToggles(config.getBoolValue("ReturnToggles")), |
129 |
mGMLoaded(false), |
||
130 |
mHaveMouse(false), |
||
131 |
✓✗✓✗ |
6 |
mAutoHide(config.getBoolValue("autohideChat")), |
132 |
✓✗✓✗ |
8 |
mShowBattleEvents(config.getBoolValue("showBattleEvents")), |
133 |
✓✗✓✗ |
8 |
mShowAllLang(serverConfig.getValue("showAllLang", 0) != 0), |
134 |
✓✗✓✗ |
8 |
mEnableTradeFilter(config.getBoolValue("enableTradeFilter")), |
135 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
88 |
mTmpVisible(false) |
136 |
{ |
||
137 |
4 |
setWindowName(name); |
|
138 |
|||
139 |
✓✓ | 2 |
if (setupWindow != nullptr) |
140 |
✓✗ | 1 |
setupWindow->registerWindowForReset(this); |
141 |
|||
142 |
4 |
setShowTitle(false); |
|
143 |
✓✗ | 2 |
setResizable(true); |
144 |
4 |
setDefaultVisible(true); |
|
145 |
4 |
setSaveVisible(true); |
|
146 |
✓✗ | 2 |
setStickyButtonLock(true); |
147 |
|||
148 |
2 |
int w = 600; |
|
149 |
#ifdef ANDROID |
||
150 |
if (mainGraphics->getWidth() < 710) |
||
151 |
w = mainGraphics->getWidth() - 110; |
||
152 |
if (w < 100) |
||
153 |
w = 100; |
||
154 |
if (mainGraphics->getHeight() < 480) |
||
155 |
setDefaultSize(w, 90, ImagePosition::UPPER_LEFT, -110, -35); |
||
156 |
else |
||
157 |
setDefaultSize(w, 123, ImagePosition::UPPER_LEFT, -110, -35); |
||
158 |
#else // ANDROID |
||
159 |
|||
160 |
✓✗✗✓ |
2 |
if (mainGraphics->getWidth() < 600) |
161 |
w = mainGraphics->getWidth() - 10; |
||
162 |
✗✓ | 2 |
if (w < 100) |
163 |
w = 100; |
||
164 |
✓✗ | 2 |
setDefaultSize(w, 123, ImagePosition::LOWER_LEFT, 0, 0); |
165 |
#endif // ANDROID |
||
166 |
|||
167 |
✓✗ | 2 |
setMinWidth(150); |
168 |
✓✗ | 2 |
setMinHeight(90); |
169 |
|||
170 |
6 |
setTitleBarHeight(getPadding() + getTitlePadding()); |
|
171 |
|||
172 |
✗✓ | 2 |
if (emoteWindow != nullptr) |
173 |
emoteWindow->addListeners(this); |
||
174 |
|||
175 |
✓✗ | 2 |
mChatButton->adjustSize(); |
176 |
|||
177 |
✓✗ | 2 |
mChatTabs->enableScrollButtons(true); |
178 |
4 |
mChatTabs->setFollowDownScroll(true); |
|
179 |
4 |
mChatTabs->setResizeHeight(false); |
|
180 |
|||
181 |
✓✗ | 10 |
mChatInput->setActionEventId("chatinput"); |
182 |
✓✗ | 2 |
mChatInput->addActionListener(this); |
183 |
4 |
mChatInput->setAllowSpecialActions(false); |
|
184 |
|||
185 |
✓✗ | 10 |
mColorPicker->setActionEventId(ACTION_COLOR_PICKER); |
186 |
✓✗ | 2 |
mColorPicker->addActionListener(this); |
187 |
✓✗ | 2 |
mColorPicker->setSelected(mChatColor); |
188 |
|||
189 |
4 |
mItemLinkHandler->setAllowCommands(false); |
|
190 |
|||
191 |
✓✗ | 2 |
loadWindowState(); |
192 |
|||
193 |
8 |
mColorPicker->setPosition(this->getWidth() - mColorPicker->getWidth() |
|
194 |
✓✗ | 4 |
- 2 * mPadding - 8 - 16, mPadding); |
195 |
|||
196 |
// Add key listener to chat input to be able to respond to up/down |
||
197 |
✓✗ | 2 |
mChatInput->addKeyListener(this); |
198 |
4 |
mCurHist = mHistory.end(); |
|
199 |
✓✗✓✗ ✗✓ |
8 |
mColorPicker->setVisible(fromBool(config.getBoolValue( |
200 |
✓✗ | 2 |
"showChatColorsList"), Visible)); |
201 |
2 |
updateTabsMargin(); |
|
202 |
|||
203 |
✓✗ | 2 |
fillCommands(); |
204 |
✓✗✓✗ ✗✓ |
4 |
if ((localPlayer != nullptr) && localPlayer->isGM()) |
205 |
loadGMCommands(); |
||
206 |
✓✗ | 2 |
initTradeFilter(); |
207 |
✓✗ | 2 |
loadCustomList(); |
208 |
✓✗ | 2 |
parseHighlights(); |
209 |
✓✗ | 2 |
parseGlobalsFilter(); |
210 |
|||
211 |
✓✗✓✗ |
8 |
config.addListener("autohideChat", this); |
212 |
✓✗✓✗ |
8 |
config.addListener("showBattleEvents", this); |
213 |
✓✗✓✗ |
8 |
config.addListener("globalsFilter", this); |
214 |
✓✗✓✗ |
8 |
config.addListener("enableTradeFilter", this); |
215 |
|||
216 |
4 |
enableVisibleSound(true); |
|
217 |
2 |
} |
|
218 |
|||
219 |
24 |
ChatWindow::~ChatWindow() |
|
220 |
{ |
||
221 |
2 |
config.removeListeners(this); |
|
222 |
CHECKLISTENERS |
||
223 |
2 |
saveState(); |
|
224 |
10 |
config.setValue("ReturnToggles", mReturnToggles); |
|
225 |
2 |
removeAllWhispers(); |
|
226 |
2 |
removeAllChannels(); |
|
227 |
✓✗ | 2 |
delete2(mItemLinkHandler) |
228 |
✓✗ | 2 |
delete2(mColorPicker) |
229 |
✓✗ | 4 |
delete2(mColorListModel) |
230 |
4 |
} |
|
231 |
|||
232 |
2 |
void ChatWindow::postInit() |
|
233 |
{ |
||
234 |
2 |
Window::postInit(); |
|
235 |
✓✗ | 2 |
add(mChatTabs); |
236 |
2 |
add(mChatInput); |
|
237 |
✓✗ | 2 |
add(mColorPicker); |
238 |
2 |
add(mChatButton); |
|
239 |
2 |
updateVisibility(); |
|
240 |
2 |
} |
|
241 |
|||
242 |
2 |
void ChatWindow::loadCommandsFile(const std::string &name) |
|
243 |
{ |
||
244 |
4 |
StringVect list; |
|
245 |
✓✗ | 2 |
VirtFs::loadTextFile(name, list); |
246 |
4 |
StringVectCIter it = list.begin(); |
|
247 |
4 |
const StringVectCIter it_end = list.end(); |
|
248 |
|||
249 |
✗✓ | 2 |
while (it != it_end) |
250 |
{ |
||
251 |
const std::string str = *it; |
||
252 |
if (!str.empty()) |
||
253 |
mCommands.push_back(str); |
||
254 |
++ it; |
||
255 |
} |
||
256 |
2 |
} |
|
257 |
|||
258 |
2 |
void ChatWindow::fillCommands() |
|
259 |
{ |
||
260 |
✓✗ | 8 |
loadCommandsFile("chatcommands.txt"); |
261 |
2 |
InputManager::addChatCommands(mCommands); |
|
262 |
2 |
} |
|
263 |
|||
264 |
void ChatWindow::loadGMCommands() |
||
265 |
{ |
||
266 |
if (mGMLoaded) |
||
267 |
return; |
||
268 |
|||
269 |
loadCommandsFile("gmcommands.txt"); |
||
270 |
mGMLoaded = true; |
||
271 |
} |
||
272 |
|||
273 |
void ChatWindow::updateTabsMargin() |
||
274 |
{ |
||
275 |
✓✗✗✗ ✓✗ |
4 |
if (mColorPicker->mVisible == Visible_true) |
276 |
8 |
mChatTabs->setRightMargin(mColorPicker->getWidth() + 16 + 8); |
|
277 |
else |
||
278 |
mChatTabs->setRightMargin(8); |
||
279 |
} |
||
280 |
|||
281 |
2 |
void ChatWindow::adjustTabSize() |
|
282 |
{ |
||
283 |
4 |
const Rect area = getChildrenArea(); |
|
284 |
|||
285 |
2 |
const int aw = area.width; |
|
286 |
2 |
const int ah = area.height; |
|
287 |
4 |
const int frame = mChatInput->getFrameSize(); |
|
288 |
4 |
const int inputHeight = mChatInput->getHeight(); |
|
289 |
✓✗ | 8 |
const bool showEmotes = config.getBoolValue("showEmotesButton"); |
290 |
2 |
int maxHeight = inputHeight; |
|
291 |
✓✗ | 2 |
if (showEmotes) |
292 |
{ |
||
293 |
4 |
const int buttonHeight = mChatButton->getHeight(); |
|
294 |
✓✗ | 2 |
if (buttonHeight > maxHeight) |
295 |
2 |
maxHeight = buttonHeight; |
|
296 |
} |
||
297 |
2 |
const int frame2 = 2 * frame; |
|
298 |
2 |
const int awFrame2 = aw - frame2; |
|
299 |
2 |
int y = ah - maxHeight - frame; |
|
300 |
2 |
mChatInput->setPosition(frame, y); |
|
301 |
2 |
mChatTabs->setWidth(awFrame2); |
|
302 |
2 |
const int height = ah - frame2 - (maxHeight + frame2); |
|
303 |
✓✗✗✓ ✗✓ |
6 |
if (mChatInput->mVisible == Visible_true || |
304 |
✓✗✓✗ ✓✗✗✗ |
8 |
!config.getBoolValue("hideChatInput")) |
305 |
{ |
||
306 |
mChatTabs->setHeight(height); |
||
307 |
} |
||
308 |
else |
||
309 |
{ |
||
310 |
2 |
mChatTabs->setHeight(height + maxHeight); |
|
311 |
} |
||
312 |
2 |
updateTabsMargin(); |
|
313 |
|||
314 |
✓✗ | 2 |
if (showEmotes) |
315 |
{ |
||
316 |
4 |
const int chatButtonSize = mChatButton->getWidth(); |
|
317 |
2 |
int w = awFrame2 - chatButtonSize; |
|
318 |
2 |
const int x = aw - frame - chatButtonSize; |
|
319 |
2 |
w -= mEmoteButtonSpacing; |
|
320 |
2 |
y += mEmoteButtonY; |
|
321 |
2 |
mChatInput->setWidth(w); |
|
322 |
2 |
mChatButton->setVisible(mChatInput->mVisible); |
|
323 |
2 |
mChatButton->setPosition(x, y); |
|
324 |
} |
||
325 |
else |
||
326 |
{ |
||
327 |
mChatInput->setWidth(awFrame2); |
||
328 |
mChatButton->setVisible(Visible_false); |
||
329 |
} |
||
330 |
|||
331 |
2 |
const ChatTab *const tab = getFocused(); |
|
332 |
✗✓ | 2 |
if (tab != nullptr) |
333 |
{ |
||
334 |
Widget *const content = tab->mScrollArea; |
||
335 |
if (content != nullptr) |
||
336 |
{ |
||
337 |
const int contentFrame2 = 2 * content->getFrameSize(); |
||
338 |
content->setSize(mChatTabs->getWidth() - contentFrame2, |
||
339 |
mChatTabs->getContainerHeight() - contentFrame2); |
||
340 |
content->logic(); |
||
341 |
} |
||
342 |
} |
||
343 |
|||
344 |
8 |
mColorPicker->setPosition(this->getWidth() - mColorPicker->getWidth() |
|
345 |
4 |
- 2 * mPadding - 8 - 16, mPadding); |
|
346 |
|||
347 |
2 |
mChatTabs->adjustSize(); |
|
348 |
2 |
} |
|
349 |
|||
350 |
2 |
void ChatWindow::widgetResized(const Event &event) |
|
351 |
{ |
||
352 |
2 |
Window::widgetResized(event); |
|
353 |
|||
354 |
2 |
adjustTabSize(); |
|
355 |
2 |
} |
|
356 |
|||
357 |
ChatTab *ChatWindow::getFocused() const |
||
358 |
{ |
||
359 |
4 |
return static_cast<ChatTab*>(mChatTabs->getSelectedTab()); |
|
360 |
} |
||
361 |
|||
362 |
void ChatWindow::clearTab(ChatTab *const tab) |
||
363 |
{ |
||
364 |
if (tab != nullptr) |
||
365 |
tab->clearText(); |
||
366 |
} |
||
367 |
|||
368 |
void ChatWindow::clearTab() const |
||
369 |
{ |
||
370 |
clearTab(getFocused()); |
||
371 |
} |
||
372 |
|||
373 |
void ChatWindow::prevTab() |
||
374 |
{ |
||
375 |
if (mChatTabs == nullptr) |
||
376 |
return; |
||
377 |
|||
378 |
int tab = mChatTabs->getSelectedTabIndex(); |
||
379 |
|||
380 |
if (tab <= 0) |
||
381 |
tab = mChatTabs->getNumberOfTabs(); |
||
382 |
tab--; |
||
383 |
|||
384 |
mChatTabs->setSelectedTabByIndex(tab); |
||
385 |
} |
||
386 |
|||
387 |
void ChatWindow::nextTab() |
||
388 |
{ |
||
389 |
if (mChatTabs == nullptr) |
||
390 |
return; |
||
391 |
|||
392 |
int tab = mChatTabs->getSelectedTabIndex(); |
||
393 |
|||
394 |
tab++; |
||
395 |
if (tab == mChatTabs->getNumberOfTabs()) |
||
396 |
tab = 0; |
||
397 |
|||
398 |
mChatTabs->setSelectedTabByIndex(tab); |
||
399 |
} |
||
400 |
|||
401 |
void ChatWindow::selectTabByType(const ChatTabTypeT &type) |
||
402 |
{ |
||
403 |
if (mChatTabs == nullptr) |
||
404 |
return; |
||
405 |
|||
406 |
int sz = mChatTabs->getNumberOfTabs(); |
||
407 |
for (int f = 0; f < sz; f ++) |
||
408 |
{ |
||
409 |
ChatTab *const tab = dynamic_cast<ChatTab*>( |
||
410 |
mChatTabs->getTabByIndex(f)); |
||
411 |
if ((tab != nullptr) && tab->getType() == type) |
||
412 |
{ |
||
413 |
mChatTabs->setSelectedTab(tab); |
||
414 |
break; |
||
415 |
} |
||
416 |
} |
||
417 |
} |
||
418 |
|||
419 |
void ChatWindow::closeTab() const |
||
420 |
{ |
||
421 |
if (mChatTabs == nullptr) |
||
422 |
return; |
||
423 |
|||
424 |
ChatTab *const tab = dynamic_cast<ChatTab*>(mChatTabs->getTabByIndex( |
||
425 |
mChatTabs->getSelectedTabIndex())); |
||
426 |
if (tab == nullptr) |
||
427 |
return; |
||
428 |
const ChatTabTypeT &type = tab->getType(); |
||
429 |
if (type == ChatTabType::WHISPER || type == ChatTabType::CHANNEL) |
||
430 |
tab->handleCommand("close", ""); |
||
431 |
} |
||
432 |
|||
433 |
void ChatWindow::defaultTab() |
||
434 |
{ |
||
435 |
if (mChatTabs != nullptr) |
||
436 |
mChatTabs->setSelectedTabByIndex(CAST_U32(0)); |
||
437 |
} |
||
438 |
|||
439 |
void ChatWindow::action(const ActionEvent &event) |
||
440 |
{ |
||
441 |
const std::string &eventId = event.getId(); |
||
442 |
if (eventId == "chatinput") |
||
443 |
{ |
||
444 |
std::string message = mChatInput->getText(); |
||
445 |
|||
446 |
if (!message.empty()) |
||
447 |
{ |
||
448 |
// If message different from previous, put it in the history |
||
449 |
if (mHistory.empty() || message != mHistory.back()) |
||
450 |
mHistory.push_back(message); |
||
451 |
|||
452 |
// Reset history iterator |
||
453 |
mCurHist = mHistory.end(); |
||
454 |
|||
455 |
// Send the message to the server |
||
456 |
chatInput(addColors(message)); |
||
457 |
|||
458 |
// Clear the text from the chat input |
||
459 |
mChatInput->setText(""); |
||
460 |
} |
||
461 |
|||
462 |
if (message.empty() || !mReturnToggles) |
||
463 |
{ |
||
464 |
// Remove focus and hide input |
||
465 |
mChatInput->unprotectFocus(); |
||
466 |
if (mFocusHandler != nullptr) |
||
467 |
mFocusHandler->focusNone(); |
||
468 |
|||
469 |
// If the chatWindow is shown up because you want to send a message |
||
470 |
// It should hide now |
||
471 |
if (mTmpVisible) |
||
472 |
setVisible(Visible_false); |
||
473 |
} |
||
474 |
} |
||
475 |
else if (eventId == "emote") |
||
476 |
{ |
||
477 |
if (emoteWindow != nullptr) |
||
478 |
{ |
||
479 |
const std::string str = emoteWindow->getSelectedEmote(); |
||
480 |
if (!str.empty()) |
||
481 |
{ |
||
482 |
addInputText(str, false); |
||
483 |
emoteWindow->clearEmote(); |
||
484 |
} |
||
485 |
} |
||
486 |
} |
||
487 |
else if (eventId == "openemote") |
||
488 |
{ |
||
489 |
if (emoteWindow != nullptr) |
||
490 |
{ |
||
491 |
if (emoteWindow->mVisible == Visible_true) |
||
492 |
emoteWindow->hide(); |
||
493 |
else |
||
494 |
emoteWindow->show(); |
||
495 |
} |
||
496 |
} |
||
497 |
else if (eventId == "color") |
||
498 |
{ |
||
499 |
if (emoteWindow != nullptr) |
||
500 |
{ |
||
501 |
const std::string str = emoteWindow->getSelectedColor(); |
||
502 |
if (!str.empty()) |
||
503 |
{ |
||
504 |
addInputText(str, false); |
||
505 |
emoteWindow->clearColor(); |
||
506 |
} |
||
507 |
} |
||
508 |
} |
||
509 |
else if (eventId == "font") |
||
510 |
{ |
||
511 |
if (emoteWindow != nullptr) |
||
512 |
{ |
||
513 |
const std::string str = emoteWindow->getSelectedFont(); |
||
514 |
if (!str.empty()) |
||
515 |
{ |
||
516 |
addInputText(str, false); |
||
517 |
emoteWindow->clearFont(); |
||
518 |
} |
||
519 |
} |
||
520 |
} |
||
521 |
else if (eventId == "text") |
||
522 |
{ |
||
523 |
if ((emoteWindow != nullptr) && (reverseDictionary != nullptr)) |
||
524 |
{ |
||
525 |
const int idx = emoteWindow->getSelectedTextIndex(); |
||
526 |
if (idx >= 0) |
||
527 |
{ |
||
528 |
const std::string str = TextDb::getByIndex(idx); |
||
529 |
const std::string enStr = reverseDictionary->getStr(str); |
||
530 |
addInputText(enStr, false); |
||
531 |
} |
||
532 |
emoteWindow->clearText(); |
||
533 |
} |
||
534 |
} |
||
535 |
else if (eventId == ACTION_COLOR_PICKER) |
||
536 |
{ |
||
537 |
if (mColorPicker != nullptr) |
||
538 |
{ |
||
539 |
mChatColor = mColorPicker->getSelected(); |
||
540 |
config.setValue("chatColor", mChatColor); |
||
541 |
} |
||
542 |
} |
||
543 |
|||
544 |
if (mColorPicker != nullptr) |
||
545 |
{ |
||
546 |
const Visible vis = fromBool(config.getBoolValue( |
||
547 |
"showChatColorsList"), Visible); |
||
548 |
if (mColorPicker->mVisible != vis) |
||
549 |
mColorPicker->setVisible(vis); |
||
550 |
} |
||
551 |
} |
||
552 |
|||
553 |
bool ChatWindow::requestChatFocus() |
||
554 |
{ |
||
555 |
// Make sure chatWindow is visible |
||
556 |
if (!isWindowVisible()) |
||
557 |
{ |
||
558 |
setVisible(Visible_true); |
||
559 |
|||
560 |
/* |
||
561 |
* This is used to hide chatWindow after sending the message. There is |
||
562 |
* a trick here, because setVisible will set mTmpVisible to false, you |
||
563 |
* have to put this sentence *after* setVisible, not before it |
||
564 |
*/ |
||
565 |
mTmpVisible = true; |
||
566 |
} |
||
567 |
|||
568 |
// Don't do anything else if the input is already visible and has focus |
||
569 |
if (mChatInput->isVisible() && mChatInput->isFocused()) |
||
570 |
return false; |
||
571 |
|||
572 |
// Give focus to the chat input |
||
573 |
mChatInput->processVisible(Visible_true); |
||
574 |
unHideWindow(); |
||
575 |
mChatInput->requestFocus(); |
||
576 |
return true; |
||
577 |
} |
||
578 |
|||
579 |
bool ChatWindow::isInputFocused() const |
||
580 |
{ |
||
581 |
return mChatInput->isFocused(); |
||
582 |
} |
||
583 |
|||
584 |
1 |
void ChatWindow::removeTab(ChatTab *const tab) |
|
585 |
{ |
||
586 |
1 |
mChatTabs->removeTab(tab); |
|
587 |
1 |
} |
|
588 |
|||
589 |
1 |
void ChatWindow::addTab(ChatTab *const tab) |
|
590 |
{ |
||
591 |
✓✗ | 1 |
if (tab == nullptr) |
592 |
return; |
||
593 |
|||
594 |
1 |
mChatTabs->addTab(tab, tab->mScrollArea); |
|
595 |
1 |
logic(); |
|
596 |
} |
||
597 |
|||
598 |
void ChatWindow::removeWhisper(const std::string &nick) |
||
599 |
{ |
||
600 |
std::string tempNick = nick; |
||
601 |
toLower(tempNick); |
||
602 |
mWhispers.erase(tempNick); |
||
603 |
} |
||
604 |
|||
605 |
void ChatWindow::removeChannel(const std::string &name) |
||
606 |
{ |
||
607 |
std::string tempName = name; |
||
608 |
toLower(tempName); |
||
609 |
mChannels.erase(tempName); |
||
610 |
chatHandler->partChannel(name); |
||
611 |
} |
||
612 |
|||
613 |
2 |
void ChatWindow::removeAllWhispers() |
|
614 |
{ |
||
615 |
4 |
std::list<ChatTab*> tabs; |
|
616 |
|||
617 |
✗✓ | 6 |
FOR_EACH (TabMap::iterator, iter, mWhispers) |
618 |
tabs.push_back(iter->second); |
||
619 |
|||
620 |
✗✓ | 6 |
for (std::list<ChatTab*>::iterator it = tabs.begin(); |
621 |
2 |
it != tabs.end(); ++it) |
|
622 |
{ |
||
623 |
delete *it; |
||
624 |
} |
||
625 |
|||
626 |
4 |
mWhispers.clear(); |
|
627 |
2 |
} |
|
628 |
|||
629 |
2 |
void ChatWindow::removeAllChannels() |
|
630 |
{ |
||
631 |
4 |
std::list<ChatTab*> tabs; |
|
632 |
|||
633 |
✗✓ | 6 |
FOR_EACH (ChannelMap::iterator, iter, mChannels) |
634 |
tabs.push_back(iter->second); |
||
635 |
|||
636 |
✗✓ | 6 |
for (std::list<ChatTab*>::iterator it = tabs.begin(); |
637 |
2 |
it != tabs.end(); ++it) |
|
638 |
{ |
||
639 |
delete *it; |
||
640 |
} |
||
641 |
|||
642 |
4 |
mChannels.clear(); |
|
643 |
2 |
} |
|
644 |
|||
645 |
void ChatWindow::ignoreAllWhispers() |
||
646 |
{ |
||
647 |
for (TabMap::iterator iter = mWhispers.begin(); |
||
648 |
iter != mWhispers.end(); |
||
649 |
++ iter) |
||
650 |
{ |
||
651 |
WhisperTab *const tab = iter->second; |
||
652 |
if (tab != nullptr) |
||
653 |
{ |
||
654 |
if (playerRelations.getRelation(tab->getNick()) |
||
655 |
!= Relation::IGNORED) |
||
656 |
{ |
||
657 |
playerRelations.setRelation(tab->getNick(), |
||
658 |
Relation::IGNORED); |
||
659 |
} |
||
660 |
tab->handleCommand("close", ""); |
||
661 |
} |
||
662 |
} |
||
663 |
} |
||
664 |
|||
665 |
void ChatWindow::chatInput(const std::string &message) const |
||
666 |
{ |
||
667 |
ChatTab *tab = nullptr; |
||
668 |
std::string msg = message; |
||
669 |
trim(msg); |
||
670 |
|||
671 |
if (config.getBoolValue("allowCommandsInChatTabs") |
||
672 |
&& msg.length() > 1 |
||
673 |
&& ((msg.at(0) == '#' && msg.at(1) != '#') || msg.at(0) == '@') |
||
674 |
&& (localChatTab != nullptr)) |
||
675 |
{ |
||
676 |
tab = localChatTab; |
||
677 |
} |
||
678 |
else |
||
679 |
{ |
||
680 |
tab = getFocused(); |
||
681 |
if (tab == nullptr) |
||
682 |
tab = localChatTab; |
||
683 |
} |
||
684 |
if (tab != nullptr) |
||
685 |
tab->chatInput(msg); |
||
686 |
Game *const game = Game::instance(); |
||
687 |
if (game != nullptr) |
||
688 |
game->setValidSpeed(); |
||
689 |
} |
||
690 |
|||
691 |
void ChatWindow::localChatInput(const std::string &msg) const |
||
692 |
{ |
||
693 |
if (localChatTab != nullptr) |
||
694 |
localChatTab->chatInput(msg); |
||
695 |
else |
||
696 |
chatInput(msg); |
||
697 |
} |
||
698 |
|||
699 |
void ChatWindow::doPresent() const |
||
700 |
{ |
||
701 |
if (actorManager == nullptr) |
||
702 |
return; |
||
703 |
|||
704 |
const ActorSprites &actors = actorManager->getAll(); |
||
705 |
std::string response; |
||
706 |
int playercount = 0; |
||
707 |
|||
708 |
FOR_EACH (ActorSpritesIterator, it, actors) |
||
709 |
{ |
||
710 |
if ((*it)->getType() == ActorType::Player) |
||
711 |
{ |
||
712 |
if (!response.empty()) |
||
713 |
response.append(", "); |
||
714 |
response.append(static_cast<Being*>(*it)->getName()); |
||
715 |
playercount ++; |
||
716 |
} |
||
717 |
} |
||
718 |
|||
719 |
ChatTab *const tab = getFocused(); |
||
720 |
if (tab != nullptr) |
||
721 |
{ |
||
722 |
const std::string log = strprintf( |
||
723 |
// TRANSLATORS: chat message |
||
724 |
_("Present: %s; %d players are present."), |
||
725 |
response.c_str(), playercount); |
||
726 |
tab->chatLog(log, |
||
727 |
ChatMsgType::BY_SERVER, |
||
728 |
IgnoreRecord_false, |
||
729 |
TryRemoveColors_true); |
||
730 |
} |
||
731 |
} |
||
732 |
|||
733 |
void ChatWindow::scroll(const int amount) const |
||
734 |
{ |
||
735 |
if (!isWindowVisible()) |
||
736 |
return; |
||
737 |
|||
738 |
ChatTab *const tab = getFocused(); |
||
739 |
if (tab != nullptr) |
||
740 |
tab->scroll(amount); |
||
741 |
} |
||
742 |
|||
743 |
void ChatWindow::mousePressed(MouseEvent &event) |
||
744 |
{ |
||
745 |
if (event.isConsumed()) |
||
746 |
return; |
||
747 |
|||
748 |
if (event.getButton() == MouseButton::RIGHT) |
||
749 |
{ |
||
750 |
if (popupMenu != nullptr) |
||
751 |
{ |
||
752 |
ChatTab *const cTab = dynamic_cast<ChatTab*>( |
||
753 |
mChatTabs->getSelectedTab()); |
||
754 |
if (cTab != nullptr) |
||
755 |
{ |
||
756 |
event.consume(); |
||
757 |
if (inputManager.isActionActive(InputAction::CHAT_MOD)) |
||
758 |
{ |
||
759 |
inputManager.executeChatCommand( |
||
760 |
InputAction::CLOSE_CHAT_TAB, |
||
761 |
std::string(), cTab); |
||
762 |
} |
||
763 |
else |
||
764 |
{ |
||
765 |
popupMenu->showChatPopup(viewport->mMouseX, |
||
766 |
viewport->mMouseY, |
||
767 |
cTab); |
||
768 |
} |
||
769 |
} |
||
770 |
} |
||
771 |
} |
||
772 |
|||
773 |
Window::mousePressed(event); |
||
774 |
|||
775 |
if (event.isConsumed()) |
||
776 |
return; |
||
777 |
|||
778 |
if (event.getButton() == MouseButton::LEFT) |
||
779 |
{ |
||
780 |
const int clicks = event.getClickCount(); |
||
781 |
if (clicks == 2) |
||
782 |
{ |
||
783 |
toggleChatFocus(); |
||
784 |
if (gui != nullptr) |
||
785 |
gui->resetClickCount(); |
||
786 |
} |
||
787 |
else if (clicks == 1) |
||
788 |
{ |
||
789 |
const ChatTab *const tab = getFocused(); |
||
790 |
if (tab != nullptr) |
||
791 |
mMoved = !isResizeAllowed(event); |
||
792 |
} |
||
793 |
} |
||
794 |
|||
795 |
mDragOffsetX = event.getX(); |
||
796 |
mDragOffsetY = event.getY(); |
||
797 |
} |
||
798 |
|||
799 |
void ChatWindow::mouseDragged(MouseEvent &event) |
||
800 |
{ |
||
801 |
Window::mouseDragged(event); |
||
802 |
|||
803 |
if (event.isConsumed()) |
||
804 |
return; |
||
805 |
|||
806 |
if (canMove() && isMovable() && mMoved) |
||
807 |
{ |
||
808 |
int newX = std::max(0, getX() + event.getX() - mDragOffsetX); |
||
809 |
int newY = std::max(0, getY() + event.getY() - mDragOffsetY); |
||
810 |
newX = std::min(mainGraphics->mWidth - getWidth(), newX); |
||
811 |
newY = std::min(mainGraphics->mHeight - getHeight(), newY); |
||
812 |
setPosition(newX, newY); |
||
813 |
} |
||
814 |
} |
||
815 |
|||
816 |
#define ifKey(key, str) \ |
||
817 |
else if (actionId == (key)) \ |
||
818 |
{ \ |
||
819 |
temp = str; \ |
||
820 |
} |
||
821 |
|||
822 |
void ChatWindow::keyPressed(KeyEvent &event) |
||
823 |
{ |
||
824 |
const InputActionT actionId = event.getActionId(); |
||
825 |
std::string temp; |
||
826 |
#ifdef __SWITCH__ |
||
827 |
if (event.getKey().getValue() == KeyValue::TEXTINPUT) |
||
828 |
{ |
||
829 |
action(ActionEvent(this, "chatinput")); |
||
830 |
return; |
||
831 |
} |
||
832 |
else |
||
833 |
#endif |
||
834 |
if (actionId == InputAction::GUI_DOWN) |
||
835 |
{ |
||
836 |
if (mCurHist != mHistory.end()) |
||
837 |
{ |
||
838 |
// Move forward through the history |
||
839 |
const HistoryIterator prevHist = mCurHist++; |
||
840 |
addCurrentToHistory(); |
||
841 |
|||
842 |
if (mCurHist != mHistory.end()) |
||
843 |
{ |
||
844 |
mChatInput->setText(*mCurHist); |
||
845 |
mChatInput->setCaretPosition(CAST_U32( |
||
846 |
mChatInput->getText().length())); |
||
847 |
} |
||
848 |
else |
||
849 |
{ |
||
850 |
mChatInput->setText(""); |
||
851 |
mCurHist = prevHist; |
||
852 |
} |
||
853 |
} |
||
854 |
else if (!mChatInput->getText().empty()) |
||
855 |
{ |
||
856 |
if (addCurrentToHistory()) |
||
857 |
mCurHist = mHistory.end(); |
||
858 |
mChatInput->setText(""); |
||
859 |
} |
||
860 |
} |
||
861 |
else if (actionId == InputAction::GUI_UP && |
||
862 |
mCurHist != mHistory.begin() && |
||
863 |
!mHistory.empty()) |
||
864 |
{ |
||
865 |
// Move backward through the history |
||
866 |
--mCurHist; |
||
867 |
addCurrentToHistory(); |
||
868 |
mChatInput->setText(*mCurHist); |
||
869 |
mChatInput->setCaretPosition(CAST_U32( |
||
870 |
mChatInput->getText().length())); |
||
871 |
} |
||
872 |
else if (actionId == InputAction::GUI_INSERT && |
||
873 |
!mChatInput->getText().empty()) |
||
874 |
{ |
||
875 |
const std::string str = mChatInput->getText(); |
||
876 |
// Add the current message to the history and clear the text |
||
877 |
if (mHistory.empty() || str != mHistory.back()) |
||
878 |
mHistory.push_back(str); |
||
879 |
mCurHist = mHistory.end(); |
||
880 |
mChatInput->setText(std::string()); |
||
881 |
} |
||
882 |
else if (actionId == InputAction::GUI_TAB && |
||
883 |
!mChatInput->getText().empty()) |
||
884 |
{ |
||
885 |
autoComplete(); |
||
886 |
return; |
||
887 |
} |
||
888 |
else if (actionId == InputAction::GUI_CANCEL && |
||
889 |
mChatInput->mVisible == Visible_true) |
||
890 |
{ |
||
891 |
mChatInput->processVisible(Visible_false); |
||
892 |
} |
||
893 |
else if (actionId == InputAction::CHAT_PREV_HISTORY && |
||
894 |
mChatInput->mVisible == Visible_true) |
||
895 |
{ |
||
896 |
const ChatTab *const tab = getFocused(); |
||
897 |
if ((tab != nullptr) && tab->hasRows()) |
||
898 |
{ |
||
899 |
if (mChatHistoryIndex == 0U) |
||
900 |
{ |
||
901 |
mChatHistoryIndex = CAST_U32( |
||
902 |
tab->getRows().size()); |
||
903 |
|||
904 |
mChatInput->setText(""); |
||
905 |
mChatInput->setCaretPosition(0); |
||
906 |
return; |
||
907 |
} |
||
908 |
|||
909 |
mChatHistoryIndex --; |
||
910 |
|||
911 |
unsigned int f = 0; |
||
912 |
const std::list<std::string> &rows = tab->getRows(); |
||
913 |
for (std::list<std::string>::const_iterator it = rows.begin(), |
||
914 |
it_end = rows.end(); it != it_end; ++ it, f ++) |
||
915 |
{ |
||
916 |
if (f == mChatHistoryIndex) |
||
917 |
mChatInput->setText(*it); |
||
918 |
} |
||
919 |
mChatInput->setCaretPosition(CAST_U32( |
||
920 |
mChatInput->getText().length())); |
||
921 |
} |
||
922 |
} |
||
923 |
else if (actionId == InputAction::CHAT_NEXT_HISTORY && |
||
924 |
mChatInput->mVisible == Visible_true) |
||
925 |
{ |
||
926 |
const ChatTab *const tab = getFocused(); |
||
927 |
if ((tab != nullptr) && tab->hasRows()) |
||
928 |
{ |
||
929 |
const std::list<std::string> &rows = tab->getRows(); |
||
930 |
const size_t &tabSize = rows.size(); |
||
931 |
if (CAST_SIZE(mChatHistoryIndex) + 1 < tabSize) |
||
932 |
{ |
||
933 |
mChatHistoryIndex ++; |
||
934 |
} |
||
935 |
else if (CAST_SIZE(mChatHistoryIndex) < tabSize) |
||
936 |
{ |
||
937 |
mChatHistoryIndex ++; |
||
938 |
mChatInput->setText(""); |
||
939 |
mChatInput->setCaretPosition(0); |
||
940 |
return; |
||
941 |
} |
||
942 |
else |
||
943 |
{ |
||
944 |
mChatHistoryIndex = 0; |
||
945 |
} |
||
946 |
|||
947 |
unsigned int f = 0; |
||
948 |
for (std::list<std::string>::const_iterator |
||
949 |
it = rows.begin(), it_end = rows.end(); |
||
950 |
it != it_end; ++it, f++) |
||
951 |
{ |
||
952 |
if (f == mChatHistoryIndex) |
||
953 |
mChatInput->setText(*it); |
||
954 |
} |
||
955 |
mChatInput->setCaretPosition(CAST_U32( |
||
956 |
mChatInput->getText().length())); |
||
957 |
} |
||
958 |
} |
||
959 |
else if (actionId == InputAction::GUI_F1) |
||
960 |
{ |
||
961 |
if (emoteWindow != nullptr) |
||
962 |
{ |
||
963 |
if (emoteWindow->mVisible == Visible_true) |
||
964 |
emoteWindow->hide(); |
||
965 |
else |
||
966 |
emoteWindow->show(); |
||
967 |
} |
||
968 |
} |
||
969 |
ifKey(InputAction::GUI_F2, "\u2318") |
||
970 |
ifKey(InputAction::GUI_F3, "\u263A") |
||
971 |
ifKey(InputAction::GUI_F4, "\u2665") |
||
972 |
ifKey(InputAction::GUI_F5, "\u266A") |
||
973 |
ifKey(InputAction::GUI_F6, "\u266B") |
||
974 |
ifKey(InputAction::GUI_F7, "\u26A0") |
||
975 |
ifKey(InputAction::GUI_F8, "\u2622") |
||
976 |
ifKey(InputAction::GUI_F9, "\u262E") |
||
977 |
ifKey(InputAction::GUI_F10, "\u2605") |
||
978 |
ifKey(InputAction::GUI_F11, "\u2618") |
||
979 |
ifKey(InputAction::GUI_F12, "\u2592") |
||
980 |
|||
981 |
if (inputManager.isActionActive(InputAction::GUI_CTRL)) |
||
982 |
{ |
||
983 |
if (actionId == InputAction::GUI_B) |
||
984 |
{ |
||
985 |
std::string inputText = mChatInput->getTextBeforeCaret(); |
||
986 |
toLower(inputText); |
||
987 |
const size_t idx = inputText.rfind("##b"); |
||
988 |
if (idx == std::string::npos |
||
989 |
|| mChatInput->getTextBeforeCaret().substr(idx, 3) == "##b") |
||
990 |
{ |
||
991 |
temp = "##B"; |
||
992 |
} |
||
993 |
else |
||
994 |
{ |
||
995 |
temp = "##b"; |
||
996 |
} |
||
997 |
} |
||
998 |
} |
||
999 |
|||
1000 |
if (!temp.empty()) |
||
1001 |
addInputText(temp, false); |
||
1002 |
} |
||
1003 |
|||
1004 |
#undef ifKey |
||
1005 |
|||
1006 |
bool ChatWindow::addCurrentToHistory() |
||
1007 |
{ |
||
1008 |
const std::string &str = mChatInput->getText(); |
||
1009 |
if (str.empty()) |
||
1010 |
return false; |
||
1011 |
FOR_EACH (HistoryIterator, it, mHistory) |
||
1012 |
{ |
||
1013 |
if (*it == str) |
||
1014 |
return false; |
||
1015 |
} |
||
1016 |
mHistory.push_back(str); |
||
1017 |
return true; |
||
1018 |
} |
||
1019 |
|||
1020 |
void ChatWindow::attributeChanged(const AttributesT id, |
||
1021 |
const int64_t oldVal, |
||
1022 |
const int64_t newVal) |
||
1023 |
{ |
||
1024 |
if (!mShowBattleEvents) |
||
1025 |
return; |
||
1026 |
PRAGMA45(GCC diagnostic push) |
||
1027 |
PRAGMA45(GCC diagnostic ignored "-Wswitch-enum") |
||
1028 |
switch (id) |
||
1029 |
{ |
||
1030 |
case Attributes::PLAYER_EXP: |
||
1031 |
{ |
||
1032 |
if (oldVal > newVal) |
||
1033 |
break; |
||
1034 |
const int64_t change = newVal - oldVal; |
||
1035 |
if (change != 0) |
||
1036 |
{ |
||
1037 |
battleChatLog(std::string("+").append(toString( |
||
1038 |
CAST_U64(change))).append(" xp"), |
||
1039 |
ChatMsgType::BY_SERVER, |
||
1040 |
IgnoreRecord_false, |
||
1041 |
TryRemoveColors_true); |
||
1042 |
} |
||
1043 |
break; |
||
1044 |
} |
||
1045 |
case Attributes::PLAYER_BASE_LEVEL: |
||
1046 |
battleChatLog(std::string( |
||
1047 |
"Level: ").append(toString(CAST_S32( |
||
1048 |
newVal))), |
||
1049 |
ChatMsgType::BY_SERVER, |
||
1050 |
IgnoreRecord_false, |
||
1051 |
TryRemoveColors_true); |
||
1052 |
break; |
||
1053 |
case Attributes::PLAYER_JOB_EXP: |
||
1054 |
{ |
||
1055 |
if (!config.getBoolValue("showJobExp")) |
||
1056 |
return; |
||
1057 |
if (oldVal > newVal || |
||
1058 |
PlayerInfo::getAttribute( |
||
1059 |
Attributes::PLAYER_JOB_EXP_NEEDED) == 0) |
||
1060 |
{ |
||
1061 |
return; |
||
1062 |
} |
||
1063 |
const int64_t change = newVal - oldVal; |
||
1064 |
if (change != 0) |
||
1065 |
{ |
||
1066 |
battleChatLog(std::string("+").append(toString(CAST_U64( |
||
1067 |
change))).append(" job"), |
||
1068 |
ChatMsgType::BY_SERVER, |
||
1069 |
IgnoreRecord_false, |
||
1070 |
TryRemoveColors_true); |
||
1071 |
} |
||
1072 |
break; |
||
1073 |
} |
||
1074 |
default: |
||
1075 |
break; |
||
1076 |
} |
||
1077 |
PRAGMA45(GCC diagnostic pop) |
||
1078 |
} |
||
1079 |
|||
1080 |
void ChatWindow::addInputText(const std::string &text, |
||
1081 |
const bool space) |
||
1082 |
{ |
||
1083 |
const int caretPos = mChatInput->getCaretPosition(); |
||
1084 |
const std::string &inputText = mChatInput->getText(); |
||
1085 |
|||
1086 |
std::ostringstream ss; |
||
1087 |
ss << inputText.substr(0, caretPos) << text; |
||
1088 |
if (space) |
||
1089 |
ss << " "; |
||
1090 |
|||
1091 |
ss << inputText.substr(caretPos); |
||
1092 |
mChatInput->setText(ss.str()); |
||
1093 |
mChatInput->setCaretPosition(caretPos + CAST_S32( |
||
1094 |
text.length()) + CAST_S32(space)); |
||
1095 |
requestChatFocus(); |
||
1096 |
} |
||
1097 |
|||
1098 |
void ChatWindow::addItemText(const std::string &item) |
||
1099 |
{ |
||
1100 |
std::ostringstream text; |
||
1101 |
text << "[" << item << "]"; |
||
1102 |
addInputText(text.str(), |
||
1103 |
true); |
||
1104 |
} |
||
1105 |
|||
1106 |
3 |
void ChatWindow::setVisible(Visible visible) |
|
1107 |
{ |
||
1108 |
✗✗ | 3 |
Window::setVisible(visible); |
1109 |
|||
1110 |
/* |
||
1111 |
* For whatever reason, if setVisible is called, the mTmpVisible effect |
||
1112 |
* should be disabled. |
||
1113 |
*/ |
||
1114 |
3 |
mTmpVisible = false; |
|
1115 |
3 |
} |
|
1116 |
|||
1117 |
void ChatWindow::addWhisper(const std::string &restrict nick, |
||
1118 |
const std::string &restrict mes, |
||
1119 |
const ChatMsgTypeT own) |
||
1120 |
{ |
||
1121 |
if (mes.empty() || (localPlayer == nullptr)) |
||
1122 |
return; |
||
1123 |
|||
1124 |
std::string playerName = localPlayer->getName(); |
||
1125 |
std::string tempNick = nick; |
||
1126 |
|||
1127 |
toLower(playerName); |
||
1128 |
toLower(tempNick); |
||
1129 |
|||
1130 |
if (tempNick == playerName) |
||
1131 |
return; |
||
1132 |
|||
1133 |
WhisperTab *tab = nullptr; |
||
1134 |
const TabMap::const_iterator i = mWhispers.find(tempNick); |
||
1135 |
|||
1136 |
if (i != mWhispers.end()) |
||
1137 |
{ |
||
1138 |
tab = i->second; |
||
1139 |
} |
||
1140 |
else if (config.getBoolValue("whispertab")) |
||
1141 |
{ |
||
1142 |
tab = addWhisperTab(nick, nick, false); |
||
1143 |
if (tab != nullptr) |
||
1144 |
saveState(); |
||
1145 |
} |
||
1146 |
|||
1147 |
if (tab != nullptr) |
||
1148 |
{ |
||
1149 |
if (own == ChatMsgType::BY_PLAYER) |
||
1150 |
{ |
||
1151 |
tab->chatInput(mes); |
||
1152 |
} |
||
1153 |
else if (own == ChatMsgType::BY_SERVER) |
||
1154 |
{ |
||
1155 |
tab->chatLog(mes, |
||
1156 |
ChatMsgType::BY_SERVER, |
||
1157 |
IgnoreRecord_false, |
||
1158 |
TryRemoveColors_true); |
||
1159 |
} |
||
1160 |
else |
||
1161 |
{ |
||
1162 |
if (tab->getRemoveNames()) |
||
1163 |
{ |
||
1164 |
std::string msg = mes; |
||
1165 |
const size_t idx = mes.find(':'); |
||
1166 |
if (idx != std::string::npos && idx > 0) |
||
1167 |
{ |
||
1168 |
std::string nick2 = msg.substr(0, idx); |
||
1169 |
msg = msg.substr(idx + 1); |
||
1170 |
nick2 = removeColors(nick2); |
||
1171 |
nick2 = trim(nick2); |
||
1172 |
if (config.getBoolValue("removeColors")) |
||
1173 |
msg = removeColors(msg); |
||
1174 |
msg = trim(msg); |
||
1175 |
tab->chatLog(nick2, msg); |
||
1176 |
} |
||
1177 |
else |
||
1178 |
{ |
||
1179 |
if (config.getBoolValue("removeColors")) |
||
1180 |
msg = removeColors(msg); |
||
1181 |
tab->chatLog(msg, |
||
1182 |
ChatMsgType::BY_SERVER, |
||
1183 |
IgnoreRecord_false, |
||
1184 |
TryRemoveColors_true); |
||
1185 |
} |
||
1186 |
} |
||
1187 |
else |
||
1188 |
{ |
||
1189 |
tab->chatLog(nick, mes); |
||
1190 |
} |
||
1191 |
localPlayer->afkRespond(tab, nick); |
||
1192 |
} |
||
1193 |
} |
||
1194 |
else if (localChatTab != nullptr) |
||
1195 |
{ |
||
1196 |
if (own == ChatMsgType::BY_PLAYER) |
||
1197 |
{ |
||
1198 |
chatHandler->privateMessage(nick, mes); |
||
1199 |
|||
1200 |
// TRANSLATORS: chat message |
||
1201 |
localChatTab->chatLog(strprintf(_("Whispering to %s: %s"), |
||
1202 |
nick.c_str(), mes.c_str()), |
||
1203 |
ChatMsgType::BY_PLAYER, |
||
1204 |
IgnoreRecord_false, |
||
1205 |
TryRemoveColors_true); |
||
1206 |
} |
||
1207 |
else |
||
1208 |
{ |
||
1209 |
localChatTab->chatLog(std::string(nick).append( |
||
1210 |
" : ").append(mes), |
||
1211 |
ChatMsgType::ACT_WHISPER, |
||
1212 |
IgnoreRecord_false, |
||
1213 |
TryRemoveColors_true); |
||
1214 |
if (localPlayer != nullptr) |
||
1215 |
localPlayer->afkRespond(nullptr, nick); |
||
1216 |
} |
||
1217 |
} |
||
1218 |
} |
||
1219 |
|||
1220 |
WhisperTab *ChatWindow::addWhisperTab(const std::string &caption, |
||
1221 |
const std::string &nick, |
||
1222 |
const bool switchTo) |
||
1223 |
{ |
||
1224 |
if (localPlayer == nullptr) |
||
1225 |
return nullptr; |
||
1226 |
|||
1227 |
std::string playerName = localPlayer->getName(); |
||
1228 |
std::string tempNick = nick; |
||
1229 |
|||
1230 |
toLower(playerName); |
||
1231 |
toLower(tempNick); |
||
1232 |
|||
1233 |
const TabMap::const_iterator i = mWhispers.find(tempNick); |
||
1234 |
WhisperTab *ret = nullptr; |
||
1235 |
|||
1236 |
if (tempNick == playerName) |
||
1237 |
return nullptr; |
||
1238 |
|||
1239 |
if (i != mWhispers.end()) |
||
1240 |
{ |
||
1241 |
ret = i->second; |
||
1242 |
} |
||
1243 |
else |
||
1244 |
{ |
||
1245 |
ret = new WhisperTab(this, caption, nick); |
||
1246 |
if ((gui != nullptr) && !playerRelations.isGoodName(nick)) |
||
1247 |
ret->setLabelFont(gui->getSecureFont()); |
||
1248 |
mWhispers[tempNick] = ret; |
||
1249 |
if (config.getBoolValue("showChatHistory")) |
||
1250 |
ret->loadFromLogFile(nick); |
||
1251 |
} |
||
1252 |
|||
1253 |
if (switchTo) |
||
1254 |
mChatTabs->setSelectedTab(ret); |
||
1255 |
|||
1256 |
return ret; |
||
1257 |
} |
||
1258 |
|||
1259 |
WhisperTab *ChatWindow::getWhisperTab(const std::string &nick) const |
||
1260 |
{ |
||
1261 |
if (localPlayer == nullptr) |
||
1262 |
return nullptr; |
||
1263 |
|||
1264 |
std::string playerName = localPlayer->getName(); |
||
1265 |
std::string tempNick = nick; |
||
1266 |
|||
1267 |
toLower(playerName); |
||
1268 |
toLower(tempNick); |
||
1269 |
|||
1270 |
const TabMap::const_iterator i = mWhispers.find(tempNick); |
||
1271 |
WhisperTab *ret = nullptr; |
||
1272 |
|||
1273 |
if (tempNick == playerName) |
||
1274 |
return nullptr; |
||
1275 |
|||
1276 |
if (i != mWhispers.end()) |
||
1277 |
ret = i->second; |
||
1278 |
|||
1279 |
return ret; |
||
1280 |
} |
||
1281 |
|||
1282 |
ChatTab *ChatWindow::addSpecialChannelTab(const std::string &name, |
||
1283 |
const bool switchTo) |
||
1284 |
{ |
||
1285 |
ChatTab *ret = nullptr; |
||
1286 |
if (name == TRADE_CHANNEL) |
||
1287 |
{ |
||
1288 |
if (tradeChatTab == nullptr) |
||
1289 |
{ |
||
1290 |
tradeChatTab = new TradeTab(chatWindow); |
||
1291 |
tradeChatTab->setAllowHighlight(false); |
||
1292 |
chatHandler->joinChannel(tradeChatTab->getChannelName()); |
||
1293 |
} |
||
1294 |
ret = tradeChatTab; |
||
1295 |
} |
||
1296 |
else if (name == GM_CHANNEL) |
||
1297 |
{ |
||
1298 |
if (gmChatTab == nullptr) |
||
1299 |
{ |
||
1300 |
gmChatTab = new GmTab(chatWindow); |
||
1301 |
chatHandler->joinChannel(gmChatTab->getChannelName()); |
||
1302 |
} |
||
1303 |
ret = gmChatTab; |
||
1304 |
} |
||
1305 |
if (switchTo) |
||
1306 |
mChatTabs->setSelectedTab(ret); |
||
1307 |
|||
1308 |
return ret; |
||
1309 |
} |
||
1310 |
|||
1311 |
ChatTab *ChatWindow::addChannelTab(const std::string &name, |
||
1312 |
const bool switchTo) |
||
1313 |
{ |
||
1314 |
std::string tempName = name; |
||
1315 |
toLower(tempName); |
||
1316 |
|||
1317 |
ChatTab *const tab = addSpecialChannelTab(name, switchTo); |
||
1318 |
if (tab != nullptr) |
||
1319 |
return tab; |
||
1320 |
|||
1321 |
const ChannelMap::const_iterator i = mChannels.find(tempName); |
||
1322 |
ChannelTab *ret = nullptr; |
||
1323 |
|||
1324 |
if (i != mChannels.end()) |
||
1325 |
{ |
||
1326 |
ret = i->second; |
||
1327 |
} |
||
1328 |
else |
||
1329 |
{ |
||
1330 |
ret = new ChannelTab(this, name); |
||
1331 |
mChannels[tempName] = ret; |
||
1332 |
ret->setAllowHighlight(false); |
||
1333 |
if (config.getBoolValue("showChatHistory")) |
||
1334 |
ret->loadFromLogFile(name); |
||
1335 |
} |
||
1336 |
|||
1337 |
if (switchTo) |
||
1338 |
mChatTabs->setSelectedTab(ret); |
||
1339 |
|||
1340 |
return ret; |
||
1341 |
} |
||
1342 |
|||
1343 |
ChatTab *ChatWindow::addChatTab(const std::string &name, |
||
1344 |
const bool switchTo, |
||
1345 |
const bool join) |
||
1346 |
{ |
||
1347 |
if (Net::getNetworkType() != ServerType::TMWATHENA && |
||
1348 |
name.size() > 1 && |
||
1349 |
name[0] == '#') |
||
1350 |
{ |
||
1351 |
ChatTab *const tab = addChannelTab(name, switchTo); |
||
1352 |
if ((tab != nullptr) && join) |
||
1353 |
chatHandler->joinChannel(name); |
||
1354 |
return tab; |
||
1355 |
} |
||
1356 |
return addWhisperTab(name, name, switchTo); |
||
1357 |
} |
||
1358 |
|||
1359 |
void ChatWindow::postConnection() |
||
1360 |
{ |
||
1361 |
FOR_EACH (ChannelMap::const_iterator, iter, mChannels) |
||
1362 |
{ |
||
1363 |
ChatTab *const tab = iter->second; |
||
1364 |
if (tab == nullptr) |
||
1365 |
return; |
||
1366 |
chatHandler->joinChannel(tab->getChannelName()); |
||
1367 |
} |
||
1368 |
if (langChatTab != nullptr) |
||
1369 |
chatHandler->joinChannel(langChatTab->getChannelName()); |
||
1370 |
} |
||
1371 |
|||
1372 |
#define changeColor(fun) \ |
||
1373 |
{ \ |
||
1374 |
msg = removeColors(msg); \ |
||
1375 |
int skip = 0; \ |
||
1376 |
const size_t sz = msg.length(); \ |
||
1377 |
for (size_t f = 0; f < sz; f ++) \ |
||
1378 |
{ \ |
||
1379 |
if (skip > 0) \ |
||
1380 |
{ \ |
||
1381 |
newMsg += msg.at(f); \ |
||
1382 |
skip --; \ |
||
1383 |
continue; \ |
||
1384 |
} \ |
||
1385 |
const unsigned char ch = CAST_U8(msg.at(f)); \ |
||
1386 |
if (f + 2 < sz && msg.substr(f, 2) == "%%") \ |
||
1387 |
{ \ |
||
1388 |
newMsg += msg.at(f); \ |
||
1389 |
skip = 2; \ |
||
1390 |
} \ |
||
1391 |
else if (ch > 0xc0 || ch < 0x80) \ |
||
1392 |
{ \ |
||
1393 |
newMsg += "##" + toString(fun) + msg.at(f); \ |
||
1394 |
if (mRainbowColor > 9U) \ |
||
1395 |
mRainbowColor = 0U; \ |
||
1396 |
} \ |
||
1397 |
else \ |
||
1398 |
{ \ |
||
1399 |
newMsg += msg.at(f); \ |
||
1400 |
} \ |
||
1401 |
} \ |
||
1402 |
} |
||
1403 |
|||
1404 |
std::string ChatWindow::addColors(std::string &msg) |
||
1405 |
{ |
||
1406 |
// default color or chat command |
||
1407 |
if (mChatColor == 0 || msg.length() == 0 || msg.at(0) == '#' |
||
1408 |
|| msg.at(0) == '/' || msg.at(0) == '@' || msg.at(0) == '!') |
||
1409 |
{ |
||
1410 |
return msg; |
||
1411 |
} |
||
1412 |
|||
1413 |
std::string newMsg; |
||
1414 |
const int cMap[] = {1, 4, 5, 2, 3, 6, 7, 9, 0, 8}; |
||
1415 |
|||
1416 |
// rainbow |
||
1417 |
switch (mChatColor) |
||
1418 |
{ |
||
1419 |
case 11: |
||
1420 |
changeColor(mRainbowColor++) |
||
1421 |
return newMsg; |
||
1422 |
case 12: |
||
1423 |
changeColor(cMap[mRainbowColor++]) |
||
1424 |
return newMsg; |
||
1425 |
case 13: |
||
1426 |
changeColor(cMap[9-mRainbowColor++]) |
||
1427 |
return newMsg; |
||
1428 |
default: |
||
1429 |
break; |
||
1430 |
} |
||
1431 |
|||
1432 |
// simple colors |
||
1433 |
return std::string("##").append(toString(mChatColor - 1)).append(msg); |
||
1434 |
} |
||
1435 |
|||
1436 |
#undef changeColor |
||
1437 |
|||
1438 |
void ChatWindow::autoComplete() |
||
1439 |
{ |
||
1440 |
const int caretPos = mChatInput->getCaretPosition(); |
||
1441 |
int startName = 0; |
||
1442 |
const std::string &inputText = mChatInput->getText(); |
||
1443 |
std::string name = inputText.substr(0, caretPos); |
||
1444 |
|||
1445 |
for (int f = caretPos - 1; f > -1; f --) |
||
1446 |
{ |
||
1447 |
if (isWordSeparator(inputText[f])) |
||
1448 |
{ |
||
1449 |
startName = f + 1; |
||
1450 |
name = inputText.substr(f + 1, caretPos - f); |
||
1451 |
break; |
||
1452 |
} |
||
1453 |
} |
||
1454 |
|||
1455 |
if (caretPos - 1 + 1 == startName) |
||
1456 |
return; |
||
1457 |
|||
1458 |
const ChatTab *const cTab = static_cast<ChatTab*>( |
||
1459 |
mChatTabs->getSelectedTab()); |
||
1460 |
StringVect nameList; |
||
1461 |
|||
1462 |
if (cTab != nullptr) |
||
1463 |
cTab->getAutoCompleteList(nameList); |
||
1464 |
std::string newName = autoComplete(nameList, name); |
||
1465 |
if (!newName.empty() && (startName == 0)) |
||
1466 |
secureChatCommand(newName); |
||
1467 |
|||
1468 |
if ((cTab != nullptr) && newName.empty()) |
||
1469 |
{ |
||
1470 |
cTab->getAutoCompleteCommands(nameList); |
||
1471 |
newName = autoComplete(nameList, name); |
||
1472 |
} |
||
1473 |
|||
1474 |
if (newName.empty() && (actorManager != nullptr)) |
||
1475 |
{ |
||
1476 |
actorManager->getPlayerNames(nameList, NpcNames_true); |
||
1477 |
newName = autoComplete(nameList, name); |
||
1478 |
if (!newName.empty() && (startName == 0)) |
||
1479 |
secureChatCommand(newName); |
||
1480 |
} |
||
1481 |
if (newName.empty()) |
||
1482 |
newName = autoCompleteHistory(name); |
||
1483 |
if (newName.empty() && (spellManager != nullptr)) |
||
1484 |
newName = spellManager->autoComplete(name); |
||
1485 |
if (newName.empty()) |
||
1486 |
newName = autoComplete(name, &mCommands); |
||
1487 |
if (newName.empty() && (actorManager != nullptr)) |
||
1488 |
{ |
||
1489 |
actorManager->getMobNames(nameList); |
||
1490 |
newName = autoComplete(nameList, name); |
||
1491 |
} |
||
1492 |
if (newName.empty()) |
||
1493 |
newName = autoComplete(name, &mCustomWords); |
||
1494 |
if (newName.empty()) |
||
1495 |
{ |
||
1496 |
whoIsOnline->getPlayerNames(nameList); |
||
1497 |
newName = autoComplete(nameList, name); |
||
1498 |
} |
||
1499 |
|||
1500 |
if (!newName.empty()) |
||
1501 |
{ |
||
1502 |
mChatInput->setText(inputText.substr(0, startName).append(newName) |
||
1503 |
.append(inputText.substr(caretPos, |
||
1504 |
inputText.length() - caretPos))); |
||
1505 |
|||
1506 |
const int len = caretPos - CAST_S32(name.length()) |
||
1507 |
+ CAST_S32(newName.length()); |
||
1508 |
|||
1509 |
if (startName > 0) |
||
1510 |
mChatInput->setCaretPosition(len + 1); |
||
1511 |
else |
||
1512 |
mChatInput->setCaretPosition(len); |
||
1513 |
} |
||
1514 |
} |
||
1515 |
|||
1516 |
std::string ChatWindow::autoComplete(const StringVect &names, |
||
1517 |
std::string partName) |
||
1518 |
{ |
||
1519 |
StringVectCIter i = names.begin(); |
||
1520 |
const StringVectCIter i_end = names.end(); |
||
1521 |
toLower(partName); |
||
1522 |
std::string newName; |
||
1523 |
|||
1524 |
while (i != i_end) |
||
1525 |
{ |
||
1526 |
if (!i->empty()) |
||
1527 |
{ |
||
1528 |
std::string name = *i; |
||
1529 |
toLower(name); |
||
1530 |
|||
1531 |
const size_t pos = name.find(partName, 0); |
||
1532 |
if (pos == 0) |
||
1533 |
{ |
||
1534 |
if (!newName.empty()) |
||
1535 |
newName = findSameSubstringI(*i, newName); |
||
1536 |
else |
||
1537 |
newName = *i; |
||
1538 |
} |
||
1539 |
} |
||
1540 |
++i; |
||
1541 |
} |
||
1542 |
|||
1543 |
return newName; |
||
1544 |
} |
||
1545 |
|||
1546 |
std::string ChatWindow::autoComplete(const std::string &partName, |
||
1547 |
const History *const words) |
||
1548 |
{ |
||
1549 |
if (words == nullptr) |
||
1550 |
return ""; |
||
1551 |
|||
1552 |
ChatCommands::const_iterator i = words->begin(); |
||
1553 |
const ChatCommands::const_iterator i_end = words->end(); |
||
1554 |
StringVect nameList; |
||
1555 |
|||
1556 |
while (i != i_end) |
||
1557 |
{ |
||
1558 |
const std::string line = *i; |
||
1559 |
if (line.find(partName, 0) == 0) |
||
1560 |
nameList.push_back(line); |
||
1561 |
++i; |
||
1562 |
} |
||
1563 |
return autoComplete(nameList, partName); |
||
1564 |
} |
||
1565 |
|||
1566 |
/* |
||
1567 |
void ChatWindow::moveTabLeft(ChatTab *tab) |
||
1568 |
{ |
||
1569 |
mChatTabs->moveLeft(tab); |
||
1570 |
} |
||
1571 |
|||
1572 |
void ChatWindow::moveTabRight(ChatTab *tab) |
||
1573 |
{ |
||
1574 |
mChatTabs->moveRight(tab); |
||
1575 |
} |
||
1576 |
*/ |
||
1577 |
|||
1578 |
std::string ChatWindow::autoCompleteHistory(const std::string &partName) const |
||
1579 |
{ |
||
1580 |
History::const_iterator i = mHistory.begin(); |
||
1581 |
const History::const_iterator i_end = mHistory.end(); |
||
1582 |
StringVect nameList; |
||
1583 |
|||
1584 |
while (i != i_end) |
||
1585 |
{ |
||
1586 |
std::string line = *i; |
||
1587 |
unsigned int f = 0; |
||
1588 |
while (f < line.length() && !isWordSeparator(line.at(f))) |
||
1589 |
f++; |
||
1590 |
|||
1591 |
line = line.substr(0, f); |
||
1592 |
if (!line.empty()) |
||
1593 |
nameList.push_back(line); |
||
1594 |
|||
1595 |
++i; |
||
1596 |
} |
||
1597 |
return autoComplete(nameList, partName); |
||
1598 |
} |
||
1599 |
|||
1600 |
bool ChatWindow::resortChatLog(std::string line, |
||
1601 |
ChatMsgTypeT own, |
||
1602 |
const std::string &channel, |
||
1603 |
const IgnoreRecord ignoreRecord, |
||
1604 |
const TryRemoveColors tryRemoveColors) |
||
1605 |
{ |
||
1606 |
if (own == ChatMsgType::BY_UNKNOWN) |
||
1607 |
{ |
||
1608 |
const size_t pos = line.find(" : "); |
||
1609 |
if (pos != std::string::npos) |
||
1610 |
{ |
||
1611 |
if (line.length() <= pos + 3) |
||
1612 |
own = ChatMsgType::BY_SERVER; |
||
1613 |
else if (line.substr(0, pos) == localPlayer->getName()) |
||
1614 |
own = ChatMsgType::BY_PLAYER; |
||
1615 |
else |
||
1616 |
own = ChatMsgType::BY_OTHER; |
||
1617 |
} |
||
1618 |
else |
||
1619 |
{ |
||
1620 |
own = ChatMsgType::BY_SERVER; |
||
1621 |
} |
||
1622 |
} |
||
1623 |
|||
1624 |
std::string prefix; |
||
1625 |
if (!channel.empty()) |
||
1626 |
{ |
||
1627 |
prefix = std::string("##3").append(channel).append("##0"); |
||
1628 |
} |
||
1629 |
else if (mEnableTradeFilter && |
||
1630 |
(tradeChatTab != nullptr) && |
||
1631 |
findI(line, mTradeFilter) != std::string::npos) |
||
1632 |
{ |
||
1633 |
// TRANSLATORS: prefix for moved message to trade tab. |
||
1634 |
tradeChatTab->chatLog(std::string("##S") + _("Moved: ") + line, |
||
1635 |
own, |
||
1636 |
ignoreRecord, |
||
1637 |
tryRemoveColors); |
||
1638 |
if (own == ChatMsgType::BY_PLAYER) |
||
1639 |
{ |
||
1640 |
own = ChatMsgType::BY_SERVER; |
||
1641 |
// TRANSLATORS: moved message to trade tab warning. |
||
1642 |
line = _("Your message was moved to trade tab"); |
||
1643 |
} |
||
1644 |
else |
||
1645 |
{ |
||
1646 |
return false; |
||
1647 |
} |
||
1648 |
} |
||
1649 |
|||
1650 |
size_t idx2 = line.find(": "); |
||
1651 |
if (idx2 != std::string::npos) |
||
1652 |
{ |
||
1653 |
std::string tmpNick = line.substr(0, idx2); |
||
1654 |
if (tmpNick.find('#') != std::string::npos || |
||
1655 |
tmpNick.find(':') != std::string::npos || |
||
1656 |
tmpNick.find('%') != std::string::npos || |
||
1657 |
tmpNick.find('@') != std::string::npos || |
||
1658 |
tmpNick.size() < 5 || |
||
1659 |
tmpNick[0] == '@' || |
||
1660 |
tmpNick[0] == '/' || |
||
1661 |
tmpNick[0] == '!' |
||
1662 |
) |
||
1663 |
{ |
||
1664 |
replaceAll(tmpNick, "#", "_"); |
||
1665 |
replaceAll(tmpNick, "%", "_"); |
||
1666 |
// TRANSLATORS: error message |
||
1667 |
line = _("Broken nick detected: ") + line; |
||
1668 |
own = ChatMsgType::BY_SERVER; |
||
1669 |
} |
||
1670 |
const size_t idx = line.find(": \302\202"); |
||
1671 |
if (idx == idx2) |
||
1672 |
{ |
||
1673 |
if (line.find(": \302\202\302") != std::string::npos) |
||
1674 |
{ |
||
1675 |
if (line.find(": \302\202\302e") != std::string::npos) |
||
1676 |
{ |
||
1677 |
// Do nothing. Before was local pet emote |
||
1678 |
} |
||
1679 |
else if (line.find(": \302\202\302m") != std::string::npos) |
||
1680 |
{ |
||
1681 |
// Do nothing. Before was local pet move |
||
1682 |
} |
||
1683 |
else if (line.find(": \302\202\302d") != std::string::npos) |
||
1684 |
{ |
||
1685 |
// Do nothing. Before was local pet direction |
||
1686 |
} |
||
1687 |
else if (line.find(": \302\202\302a") != std::string::npos) |
||
1688 |
{ |
||
1689 |
// Do nothing. Before was local pet ai enable/disable |
||
1690 |
} |
||
1691 |
// ignore other special message formats. |
||
1692 |
return false; |
||
1693 |
} |
||
1694 |
|||
1695 |
// pet talk message detected |
||
1696 |
if (line.find(": \302\202\303 ") != std::string::npos) |
||
1697 |
{ |
||
1698 |
// Do nothing. Before was local pet talk |
||
1699 |
return false; |
||
1700 |
} |
||
1701 |
if (line.find(": \302\202\304") != std::string::npos) |
||
1702 |
{ |
||
1703 |
replaceAll(line, ": \302\202\304", ": "); |
||
1704 |
} |
||
1705 |
|||
1706 |
if (tradeChatTab != nullptr) |
||
1707 |
{ |
||
1708 |
line = line.erase(idx + 2, 2); |
||
1709 |
tradeChatTab->chatLog(prefix + line, |
||
1710 |
own, |
||
1711 |
ignoreRecord, |
||
1712 |
tryRemoveColors); |
||
1713 |
} |
||
1714 |
else if (localChatTab != nullptr) |
||
1715 |
{ |
||
1716 |
line = line.erase(idx + 2, 2); |
||
1717 |
localChatTab->chatLog(prefix + line, |
||
1718 |
own, |
||
1719 |
ignoreRecord, |
||
1720 |
tryRemoveColors); |
||
1721 |
} |
||
1722 |
return false; |
||
1723 |
} |
||
1724 |
} |
||
1725 |
|||
1726 |
if (!channel.empty()) |
||
1727 |
{ |
||
1728 |
if (langChatTab != nullptr) |
||
1729 |
{ |
||
1730 |
if (langChatTab->getChannelName() == channel) |
||
1731 |
{ |
||
1732 |
langChatTab->chatLog(line, |
||
1733 |
own, |
||
1734 |
ignoreRecord, |
||
1735 |
tryRemoveColors); |
||
1736 |
} |
||
1737 |
else if (mShowAllLang) |
||
1738 |
{ |
||
1739 |
langChatTab->chatLog(prefix + line, |
||
1740 |
own, |
||
1741 |
ignoreRecord, |
||
1742 |
tryRemoveColors); |
||
1743 |
} |
||
1744 |
} |
||
1745 |
else if (Net::getNetworkType() != ServerType::TMWATHENA) |
||
1746 |
{ |
||
1747 |
channelChatLog(channel, line, own, ignoreRecord, tryRemoveColors); |
||
1748 |
return false; |
||
1749 |
} |
||
1750 |
else if (mShowAllLang) |
||
1751 |
{ |
||
1752 |
localChatTab->chatLog(prefix + line, |
||
1753 |
own, |
||
1754 |
ignoreRecord, |
||
1755 |
tryRemoveColors); |
||
1756 |
} |
||
1757 |
} |
||
1758 |
else if (localChatTab != nullptr) |
||
1759 |
{ |
||
1760 |
localChatTab->chatLog(line, own, ignoreRecord, tryRemoveColors); |
||
1761 |
} |
||
1762 |
return true; |
||
1763 |
} |
||
1764 |
|||
1765 |
void ChatWindow::battleChatLog(const std::string &line, ChatMsgTypeT own, |
||
1766 |
const IgnoreRecord ignoreRecord, |
||
1767 |
const TryRemoveColors tryRemoveColors) |
||
1768 |
{ |
||
1769 |
if (own == ChatMsgType::BY_UNKNOWN) |
||
1770 |
own = ChatMsgType::BY_SERVER; |
||
1771 |
if (battleChatTab != nullptr) |
||
1772 |
battleChatTab->chatLog(line, own, ignoreRecord, tryRemoveColors); |
||
1773 |
else if (debugChatTab != nullptr) |
||
1774 |
debugChatTab->chatLog(line, own, ignoreRecord, tryRemoveColors); |
||
1775 |
} |
||
1776 |
|||
1777 |
void ChatWindow::channelChatLog(const std::string &channel, |
||
1778 |
const std::string &line, |
||
1779 |
ChatMsgTypeT own, |
||
1780 |
const IgnoreRecord ignoreRecord, |
||
1781 |
const TryRemoveColors tryRemoveColors) |
||
1782 |
{ |
||
1783 |
std::string tempChannel = channel; |
||
1784 |
toLower(tempChannel); |
||
1785 |
|||
1786 |
ChatTab *tab = nullptr; |
||
1787 |
const ChannelMap::const_iterator i = mChannels.find(tempChannel); |
||
1788 |
|||
1789 |
if (i != mChannels.end()) |
||
1790 |
{ |
||
1791 |
tab = i->second; |
||
1792 |
} |
||
1793 |
else |
||
1794 |
{ |
||
1795 |
tab = addChannelTab(channel, false); |
||
1796 |
if (tab != nullptr) |
||
1797 |
saveState(); |
||
1798 |
} |
||
1799 |
|||
1800 |
if (tab != nullptr) |
||
1801 |
tab->chatLog(line, own, ignoreRecord, tryRemoveColors); |
||
1802 |
} |
||
1803 |
|||
1804 |
2 |
void ChatWindow::initTradeFilter() |
|
1805 |
{ |
||
1806 |
const std::string tradeListName = settings.serverConfigDir |
||
1807 |
4 |
+ "/tradefilter.txt"; |
|
1808 |
|||
1809 |
✓✗ | 4 |
std::ifstream tradeFile; |
1810 |
struct stat statbuf; |
||
1811 |
|||
1812 |
✗✓✗✗ ✗✓ |
4 |
if (stat(tradeListName.c_str(), &statbuf) == 0 && |
1813 |
S_ISREG(statbuf.st_mode)) |
||
1814 |
{ |
||
1815 |
tradeFile.open(tradeListName.c_str(), std::ios::in); |
||
1816 |
if (tradeFile.is_open()) |
||
1817 |
{ |
||
1818 |
char line[100]; |
||
1819 |
while (tradeFile.getline(line, 100)) |
||
1820 |
{ |
||
1821 |
const std::string str = line; |
||
1822 |
if (!str.empty()) |
||
1823 |
mTradeFilter.push_back(str); |
||
1824 |
} |
||
1825 |
} |
||
1826 |
tradeFile.close(); |
||
1827 |
} |
||
1828 |
2 |
} |
|
1829 |
|||
1830 |
void ChatWindow::updateOnline(const std::set<std::string> &onlinePlayers) const |
||
1831 |
{ |
||
1832 |
const Party *party = nullptr; |
||
1833 |
const Guild *guild = nullptr; |
||
1834 |
if (localPlayer != nullptr) |
||
1835 |
{ |
||
1836 |
party = localPlayer->getParty(); |
||
1837 |
guild = localPlayer->getGuild(); |
||
1838 |
} |
||
1839 |
FOR_EACH (TabMap::const_iterator, iter, mWhispers) |
||
1840 |
{ |
||
1841 |
if (iter->second == nullptr) |
||
1842 |
return; |
||
1843 |
|||
1844 |
WhisperTab *const tab = static_cast<WhisperTab*>(iter->second); |
||
1845 |
if (tab == nullptr) |
||
1846 |
continue; |
||
1847 |
|||
1848 |
if (onlinePlayers.find(tab->getNick()) != onlinePlayers.end()) |
||
1849 |
{ |
||
1850 |
tab->setWhisperTabColors(); |
||
1851 |
} |
||
1852 |
else |
||
1853 |
{ |
||
1854 |
const std::string &nick = tab->getNick(); |
||
1855 |
if (actorManager != nullptr) |
||
1856 |
{ |
||
1857 |
const Being *const being = actorManager->findBeingByName( |
||
1858 |
nick, ActorType::Player); |
||
1859 |
if (being != nullptr) |
||
1860 |
{ |
||
1861 |
tab->setWhisperTabColors(); |
||
1862 |
continue; |
||
1863 |
} |
||
1864 |
} |
||
1865 |
if (party != nullptr) |
||
1866 |
{ |
||
1867 |
const PartyMember *const pm = party->getMember(nick); |
||
1868 |
if ((pm != nullptr) && pm->getOnline()) |
||
1869 |
{ |
||
1870 |
tab->setWhisperTabColors(); |
||
1871 |
continue; |
||
1872 |
} |
||
1873 |
} |
||
1874 |
if (guild != nullptr) |
||
1875 |
{ |
||
1876 |
const GuildMember *const gm = guild->getMember(nick); |
||
1877 |
if ((gm != nullptr) && gm->getOnline()) |
||
1878 |
{ |
||
1879 |
tab->setWhisperTabColors(); |
||
1880 |
continue; |
||
1881 |
} |
||
1882 |
} |
||
1883 |
tab->setWhisperTabOfflineColors(); |
||
1884 |
} |
||
1885 |
} |
||
1886 |
} |
||
1887 |
|||
1888 |
void ChatWindow::loadState() |
||
1889 |
{ |
||
1890 |
int num = 0; |
||
1891 |
while (num < 50) |
||
1892 |
{ |
||
1893 |
const std::string nick = serverConfig.getValue( |
||
1894 |
"chatWhisper" + toString(num), ""); |
||
1895 |
|||
1896 |
if (nick.empty()) |
||
1897 |
break; |
||
1898 |
|||
1899 |
ChatTab *const tab = addChatTab(nick, false, false); |
||
1900 |
if (tab != nullptr) |
||
1901 |
{ |
||
1902 |
const int flags = serverConfig.getValue( |
||
1903 |
"chatWhisperFlags" + toString(num), 1); |
||
1904 |
|||
1905 |
tab->setAllowHighlight((flags & 1) != 0); |
||
1906 |
tab->setRemoveNames(((flags & 2) / 2) != 0); |
||
1907 |
tab->setNoAway(((flags & 4) / 4) != 0); |
||
1908 |
} |
||
1909 |
num ++; |
||
1910 |
} |
||
1911 |
} |
||
1912 |
|||
1913 |
2 |
void ChatWindow::saveState() const |
|
1914 |
{ |
||
1915 |
2 |
int num = 0; |
|
1916 |
✗✓ | 6 |
for (ChannelMap::const_iterator iter = mChannels.begin(), |
1917 |
✗✓✗✗ |
4 |
iter_end = mChannels.end(); iter != iter_end && num < 50; ++iter) |
1918 |
{ |
||
1919 |
if (iter->second == nullptr) |
||
1920 |
return; |
||
1921 |
if (!saveTab(num, iter->second)) |
||
1922 |
continue; |
||
1923 |
num ++; |
||
1924 |
} |
||
1925 |
|||
1926 |
✓✗ | 6 |
for (TabMap::const_iterator iter = mWhispers.begin(), |
1927 |
✗✓✗✗ |
4 |
iter_end = mWhispers.end(); iter != iter_end && num < 50; ++iter) |
1928 |
{ |
||
1929 |
if (iter->second == nullptr) |
||
1930 |
return; |
||
1931 |
if (!saveTab(num, iter->second)) |
||
1932 |
continue; |
||
1933 |
num ++; |
||
1934 |
} |
||
1935 |
|||
1936 |
✓✓ | 202 |
while (num < 50) |
1937 |
{ |
||
1938 |
✓✗✓✗ |
300 |
serverConfig.deleteKey("chatWhisper" + toString(num)); |
1939 |
✓✗✓✗ |
300 |
serverConfig.deleteKey("chatWhisperFlags" + toString(num)); |
1940 |
100 |
num ++; |
|
1941 |
} |
||
1942 |
} |
||
1943 |
|||
1944 |
bool ChatWindow::saveTab(const int num, |
||
1945 |
const ChatTab *const tab) |
||
1946 |
{ |
||
1947 |
if (tab == nullptr) |
||
1948 |
return false; |
||
1949 |
|||
1950 |
serverConfig.setValue("chatWhisper" + toString(num), |
||
1951 |
tab->getChannelName()); |
||
1952 |
|||
1953 |
serverConfig.setValue("chatWhisperFlags" + toString(num), |
||
1954 |
CAST_S32(tab->getAllowHighlight()) |
||
1955 |
+ (2 * CAST_S32(tab->getRemoveNames())) |
||
1956 |
+ (4 * CAST_S32(tab->getNoAway()))); |
||
1957 |
|||
1958 |
return true; |
||
1959 |
} |
||
1960 |
|||
1961 |
std::string ChatWindow::doReplace(const std::string &msg) |
||
1962 |
{ |
||
1963 |
std::string str = msg; |
||
1964 |
replaceSpecialChars(str); |
||
1965 |
return str; |
||
1966 |
} |
||
1967 |
|||
1968 |
2 |
void ChatWindow::loadCustomList() |
|
1969 |
{ |
||
1970 |
4 |
std::ifstream listFile; |
|
1971 |
struct stat statbuf; |
||
1972 |
|||
1973 |
std::string listName = settings.serverConfigDir |
||
1974 |
✓✗ | 4 |
+ "/customwords.txt"; |
1975 |
|||
1976 |
✗✓✗✗ ✗✓ |
4 |
if ((stat(listName.c_str(), &statbuf) == 0) && S_ISREG(statbuf.st_mode)) |
1977 |
{ |
||
1978 |
listFile.open(listName.c_str(), std::ios::in); |
||
1979 |
if (listFile.is_open()) |
||
1980 |
{ |
||
1981 |
char line[101]; |
||
1982 |
while (listFile.getline(line, 100)) |
||
1983 |
{ |
||
1984 |
std::string str = line; |
||
1985 |
if (!str.empty()) |
||
1986 |
mCustomWords.push_back(str); |
||
1987 |
} |
||
1988 |
} |
||
1989 |
listFile.close(); |
||
1990 |
} |
||
1991 |
2 |
} |
|
1992 |
|||
1993 |
void ChatWindow::addToAwayLog(const std::string &line) |
||
1994 |
{ |
||
1995 |
if (!settings.awayMode) |
||
1996 |
return; |
||
1997 |
|||
1998 |
if (mAwayLog.size() > 20) |
||
1999 |
mAwayLog.pop_front(); |
||
2000 |
|||
2001 |
if (findI(line, mHighlights) != std::string::npos) |
||
2002 |
mAwayLog.push_back("##aaway:" + line); |
||
2003 |
} |
||
2004 |
|||
2005 |
void ChatWindow::displayAwayLog() const |
||
2006 |
{ |
||
2007 |
if (localChatTab == nullptr) |
||
2008 |
return; |
||
2009 |
|||
2010 |
std::list<std::string>::const_iterator i = mAwayLog.begin(); |
||
2011 |
const std::list<std::string>::const_iterator i_end = mAwayLog.end(); |
||
2012 |
|||
2013 |
while (i != i_end) |
||
2014 |
{ |
||
2015 |
std::string str = *i; |
||
2016 |
localChatTab->addNewRow(str); |
||
2017 |
++i; |
||
2018 |
} |
||
2019 |
} |
||
2020 |
|||
2021 |
2 |
void ChatWindow::parseHighlights() |
|
2022 |
{ |
||
2023 |
2 |
mHighlights.clear(); |
|
2024 |
✓✗ | 2 |
if (localPlayer == nullptr) |
2025 |
return; |
||
2026 |
|||
2027 |
✓✗ | 10 |
splitToStringVector(mHighlights, config.getStringValue( |
2028 |
✓✗ | 2 |
"highlightWords"), ','); |
2029 |
|||
2030 |
4 |
mHighlights.push_back(localPlayer->getName()); |
|
2031 |
} |
||
2032 |
|||
2033 |
2 |
void ChatWindow::parseGlobalsFilter() |
|
2034 |
{ |
||
2035 |
2 |
mGlobalsFilter.clear(); |
|
2036 |
✓✗ | 2 |
if (localPlayer == nullptr) |
2037 |
return; |
||
2038 |
|||
2039 |
✓✗ | 10 |
splitToStringVector(mGlobalsFilter, config.getStringValue( |
2040 |
✓✗ | 2 |
"globalsFilter"), ','); |
2041 |
|||
2042 |
4 |
mHighlights.push_back(localPlayer->getName()); |
|
2043 |
} |
||
2044 |
|||
2045 |
bool ChatWindow::findHighlight(const std::string &str) |
||
2046 |
{ |
||
2047 |
return findI(str, mHighlights) != std::string::npos; |
||
2048 |
} |
||
2049 |
|||
2050 |
void ChatWindow::copyToClipboard(const int x, const int y) const |
||
2051 |
{ |
||
2052 |
const ChatTab *const tab = getFocused(); |
||
2053 |
if (tab == nullptr) |
||
2054 |
return; |
||
2055 |
|||
2056 |
const BrowserBox *const text = tab->mTextOutput; |
||
2057 |
if (text == nullptr) |
||
2058 |
return; |
||
2059 |
|||
2060 |
std::string str = text->getTextAtPos(x, y); |
||
2061 |
sendBuffer(str); |
||
2062 |
} |
||
2063 |
|||
2064 |
void ChatWindow::optionChanged(const std::string &name) |
||
2065 |
{ |
||
2066 |
if (name == "autohideChat") |
||
2067 |
mAutoHide = config.getBoolValue("autohideChat"); |
||
2068 |
else if (name == "showBattleEvents") |
||
2069 |
mShowBattleEvents = config.getBoolValue("showBattleEvents"); |
||
2070 |
else if (name == "globalsFilter") |
||
2071 |
parseGlobalsFilter(); |
||
2072 |
else if (name == "enableTradeFilter") |
||
2073 |
mEnableTradeFilter = config.getBoolValue("enableTradeFilter"); |
||
2074 |
} |
||
2075 |
|||
2076 |
void ChatWindow::mouseMoved(MouseEvent &event) |
||
2077 |
{ |
||
2078 |
mHaveMouse = true; |
||
2079 |
Window::mouseMoved(event); |
||
2080 |
} |
||
2081 |
|||
2082 |
void ChatWindow::mouseEntered(MouseEvent& event) |
||
2083 |
{ |
||
2084 |
mHaveMouse = true; |
||
2085 |
Window::mouseEntered(event); |
||
2086 |
} |
||
2087 |
|||
2088 |
void ChatWindow::mouseExited(MouseEvent& event) |
||
2089 |
{ |
||
2090 |
updateVisibility(); |
||
2091 |
Window::mouseExited(event); |
||
2092 |
} |
||
2093 |
|||
2094 |
1 |
void ChatWindow::draw(Graphics *const graphics) |
|
2095 |
{ |
||
2096 |
BLOCK_START("ChatWindow::draw") |
||
2097 |
✗✓✗✗ |
1 |
if (!mAutoHide || mHaveMouse) |
2098 |
{ |
||
2099 |
GLDEBUG_START("ChatWindow::draw"); |
||
2100 |
1 |
Window::draw(graphics); |
|
2101 |
GLDEBUG_END(); |
||
2102 |
} |
||
2103 |
BLOCK_END("ChatWindow::draw") |
||
2104 |
1 |
} |
|
2105 |
|||
2106 |
void ChatWindow::safeDraw(Graphics *const graphics) |
||
2107 |
{ |
||
2108 |
BLOCK_START("ChatWindow::draw") |
||
2109 |
if (!mAutoHide || mHaveMouse) |
||
2110 |
{ |
||
2111 |
GLDEBUG_START("ChatWindow::draw"); |
||
2112 |
Window::safeDraw(graphics); |
||
2113 |
GLDEBUG_END(); |
||
2114 |
} |
||
2115 |
BLOCK_END("ChatWindow::draw") |
||
2116 |
} |
||
2117 |
|||
2118 |
2 |
void ChatWindow::updateVisibility() |
|
2119 |
{ |
||
2120 |
✓✗ | 2 |
if (gui == nullptr) |
2121 |
return; |
||
2122 |
|||
2123 |
2 |
int mouseX = 0; |
|
2124 |
2 |
int mouseY = 0; |
|
2125 |
2 |
int x = 0; |
|
2126 |
2 |
int y = 0; |
|
2127 |
2 |
Gui::getMouseState(mouseX, mouseY); |
|
2128 |
2 |
getAbsolutePosition(x, y); |
|
2129 |
✗✓ | 4 |
if (mChatInput->isVisible()) |
2130 |
{ |
||
2131 |
mHaveMouse = true; |
||
2132 |
} |
||
2133 |
else |
||
2134 |
{ |
||
2135 |
✓✗ | 8 |
mHaveMouse = mouseX >= x && mouseX <= x + getWidth() |
2136 |
✓✗✗✓ ✗✗ |
4 |
&& mouseY >= y && mouseY <= y + getHeight(); |
2137 |
} |
||
2138 |
} |
||
2139 |
|||
2140 |
void ChatWindow::unHideWindow() |
||
2141 |
{ |
||
2142 |
mHaveMouse = true; |
||
2143 |
} |
||
2144 |
|||
2145 |
#ifdef USE_PROFILER |
||
2146 |
void ChatWindow::logicChildren() |
||
2147 |
{ |
||
2148 |
BLOCK_START("ChatWindow::logicChildren") |
||
2149 |
BasicContainer::logicChildren(); |
||
2150 |
BLOCK_END("ChatWindow::logicChildren") |
||
2151 |
} |
||
2152 |
#endif // USE_PROFILER |
||
2153 |
|||
2154 |
void ChatWindow::addGlobalMessage(const std::string &line) |
||
2155 |
{ |
||
2156 |
if (debugChatTab != nullptr && |
||
2157 |
findI(line, mGlobalsFilter) != std::string::npos) |
||
2158 |
{ |
||
2159 |
debugChatTab->chatLog(line, |
||
2160 |
ChatMsgType::BY_OTHER, |
||
2161 |
IgnoreRecord_false, |
||
2162 |
TryRemoveColors_true); |
||
2163 |
} |
||
2164 |
else |
||
2165 |
{ |
||
2166 |
localChatTab->chatLog(line, |
||
2167 |
ChatMsgType::BY_GM, |
||
2168 |
IgnoreRecord_false, |
||
2169 |
TryRemoveColors_true); |
||
2170 |
} |
||
2171 |
} |
||
2172 |
|||
2173 |
bool ChatWindow::isTabPresent(const ChatTab *const tab) const |
||
2174 |
{ |
||
2175 |
return mChatTabs->isTabPresent(tab); |
||
2176 |
} |
||
2177 |
|||
2178 |
void ChatWindow::debugMessage(const std::string &msg) |
||
2179 |
{ |
||
2180 |
if (debugChatTab != nullptr) |
||
2181 |
{ |
||
2182 |
debugChatTab->chatLog(msg, |
||
2183 |
ChatMsgType::BY_SERVER, |
||
2184 |
IgnoreRecord_false, |
||
2185 |
TryRemoveColors_true); |
||
2186 |
} |
||
2187 |
} |
||
2188 |
|||
2189 |
void ChatWindow::showGMTab() |
||
2190 |
{ |
||
2191 |
if ((gmChatTab == nullptr) && |
||
2192 |
config.getBoolValue("enableGmTab") && |
||
2193 |
localPlayer->getGroupId() >= paths.getIntValue("gmTabMinimalLevel")) |
||
2194 |
{ |
||
2195 |
addSpecialChannelTab(GM_CHANNEL, false); |
||
2196 |
} |
||
2197 |
} |
||
2198 |
|||
2199 |
void ChatWindow::toggleChatFocus() |
||
2200 |
{ |
||
2201 |
if (mChatInput->isVisible() && mChatInput->isFocused()) |
||
2202 |
mChatInput->processVisible(Visible_false); |
||
2203 |
else |
||
2204 |
requestChatFocus(); |
||
2205 |
} |
||
2206 |
|||
2207 |
void ChatWindow::joinRoom(const bool isJoin) |
||
2208 |
{ |
||
2209 |
Tab *const tab = mChatTabs->getTabByIndex(0); |
||
2210 |
if (tab != nullptr) |
||
2211 |
{ |
||
2212 |
std::string name; |
||
2213 |
if (isJoin) |
||
2214 |
{ |
||
2215 |
name = PlayerInfo::getRoomName(); |
||
2216 |
} |
||
2217 |
else |
||
2218 |
{ |
||
2219 |
// TRANSLATORS: chat tab name |
||
2220 |
name = _("General"); |
||
2221 |
} |
||
2222 |
tab->setCaption(name); |
||
2223 |
} |
||
2224 |
} |
||
2225 |
|||
2226 |
void ChatWindow::scheduleDelete() |
||
2227 |
{ |
||
2228 |
DebugMessageListener::removeListener(this); |
||
2229 |
Window::scheduleDelete(); |
||
2230 |
✓✗✓✗ |
3 |
} |
Generated by: GCOVR (Version 3.3) |