1 /*
2  *      irctabitem.cpp
3  *
4  *      Copyright 2008 David Vachulka <arch_dvx@users.sourceforge.net>
5  *
6  *      This program is free software; you can redistribute it and/or modify
7  *      it under the terms of the GNU General Public License as published by
8  *      the Free Software Foundation; either version 2 of the License, or
9  *      (at your option) any later version.
10  *
11  *      This program is distributed in the hope that it will be useful,
12  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *      GNU General Public License for more details.
15  *
16  *      You should have received a copy of the GNU General Public License
17  *      along with this program; if not, write to the Free Software
18  *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  *      MA 02110-1301, USA.
20  */
21 
22 #ifdef WIN32
23 #define WIN32_LEAN_AND_MEAN
24 #include <windows.h>
25 #include <shellapi.h>
26 #endif
27 #include <string>
28 #include "irctabitem.h"
29 #include "tetristabitem.h"
30 #include "icons.h"
31 #include "config.h"
32 #include "i18n.h"
33 #include "dxirc.h"
34 
35 #define ICON_SPACING             4    // Spacing between icon and label
36 #define SIDE_SPACING             6    // Left or right spacing between items
37 #define LINE_SPACING             4    // Line spacing between items
38 
39 #define preferences dxirc::instance()->getPreferences()
40 
41 //Get away color
makeAwayColor(FXColor clr)42 FXColor makeAwayColor(FXColor clr)
43 {
44     FXuint r,g,b;
45     r=FXREDVAL(clr);
46     g=FXGREENVAL(clr);
47     b=FXBLUEVAL(clr);
48     if(r==g && r==b && !r)
49     {
50         r=255;
51         g=255;
52         b=255;
53     }
54     r=(50*r)/100;
55     g=(50*g)/100;
56     b=(50*b)/100;
57     return FXRGB(r,g,b);
58 }
59 
60 //Sort by UserMode and nick
sortNick(const FXListItem * a,const FXListItem * b)61 FXint sortNick(const FXListItem *a, const FXListItem *b)
62 {
63     return comparecase((FXchar)((NickListItem*)a)->getUserMode()+a->getText(), (FXchar)((NickListItem*)b)->getUserMode()+b->getText());
64 }
65 
66 FXDEFMAP(DccSendDialog) DccSendDialogMap[] = {
67     FXMAPFUNC(SEL_COMMAND,  DccSendDialog_FILE,     DccSendDialog::onFile),
68     FXMAPFUNC(SEL_COMMAND,  DccSendDialog_SEND,     DccSendDialog::onSend),
69     FXMAPFUNC(SEL_COMMAND,  DccSendDialog_CANCEL,   DccSendDialog::onCancel),
70     FXMAPFUNC(SEL_CLOSE,    0,                      DccSendDialog::onCancel),
71     FXMAPFUNC(SEL_KEYPRESS, 0,                      DccSendDialog::onKeyPress)
72 };
73 
FXIMPLEMENT(DccSendDialog,FXDialogBox,DccSendDialogMap,ARRAYNUMBER (DccSendDialogMap))74 FXIMPLEMENT(DccSendDialog, FXDialogBox, DccSendDialogMap, ARRAYNUMBER(DccSendDialogMap))
75 
76 DccSendDialog::DccSendDialog(FXMainWindow* owner, FXString nick)
77         : FXDialogBox(owner, FXStringFormat(_("Send file to %s"), nick.text()), DECOR_RESIZE|DECOR_TITLE|DECOR_BORDER, 0,0,0,0, 0,0,0,0, 0,0)
78 {
79     m_mainFrame = new FXVerticalFrame(this, LAYOUT_FILL_X|LAYOUT_FILL_Y);
80 
81     m_fileFrame = new FXHorizontalFrame(m_mainFrame, LAYOUT_FILL_X);
82     new FXLabel(m_fileFrame, _("File:"));
83     m_fileText = new FXTextField(m_fileFrame, 25, NULL, 0, TEXTFIELD_READONLY|FRAME_THICK|FRAME_SUNKEN|LAYOUT_FILL_X);
84     m_buttonFile = new dxEXButton(m_fileFrame, "...", NULL, this, DccSendDialog_FILE, FRAME_RAISED|FRAME_THICK|LAYOUT_CENTER_X, 0,0,0,0, 10,10,2,2);
85 
86     m_passiveFrame = new FXHorizontalFrame(m_mainFrame, LAYOUT_FILL_X);
87     m_checkPassive = new FXCheckButton(m_passiveFrame, _("Send passive"), NULL, 0);
88 
89     m_buttonFrame = new FXHorizontalFrame(m_mainFrame, LAYOUT_FILL_X|PACK_UNIFORM_WIDTH);
90     m_buttonCancel = new dxEXButton(m_buttonFrame, _("&Cancel"), NULL, this, DccSendDialog_CANCEL, FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT, 0,0,0,0, 10,10,2,2);
91     m_buttonSend = new dxEXButton(m_buttonFrame, _("&Send file"), NULL, this, DccSendDialog_SEND, BUTTON_INITIAL|BUTTON_DEFAULT|FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT, 0,0,0,0, 10,10,2,2);
92 }
93 
~DccSendDialog()94 DccSendDialog::~DccSendDialog()
95 {
96 }
97 
execute(FXuint placement)98 FXuint DccSendDialog::execute(FXuint placement)
99 {
100     create();
101     show(placement);
102     getApp()->refresh();
103     dxEXFileDialog dialog(this, _("Select file"));
104     if(dialog.execute())
105     {
106         m_fileText->setText(dialog.getFilename());
107     }
108     return getApp()->runModalFor(this);
109 }
110 
onFile(FXObject *,FXSelector,void *)111 long DccSendDialog::onFile(FXObject*, FXSelector, void*)
112 {
113     dxEXFileDialog dialog(this, _("Select file"));
114     if(dialog.execute())
115     {
116         m_fileText->setText(dialog.getFilename());
117     }
118     return 1;
119 }
120 
onSend(FXObject *,FXSelector,void *)121 long DccSendDialog::onSend(FXObject*, FXSelector, void*)
122 {
123     getApp()->stopModal(this,TRUE);
124     hide();
125     return 1;
126 }
127 
onCancel(FXObject *,FXSelector,void *)128 long DccSendDialog::onCancel(FXObject*, FXSelector, void*)
129 {
130     getApp()->stopModal(this,FALSE);
131     hide();
132     return 1;
133 }
134 
onKeyPress(FXObject * sender,FXSelector sel,void * ptr)135 long DccSendDialog::onKeyPress(FXObject *sender, FXSelector sel, void *ptr)
136 {
137     if(FXTopWindow::onKeyPress(sender,sel,ptr)) return 1;
138     if(((FXEvent*)ptr)->code == KEY_Escape)
139     {
140         handle(this,FXSEL(SEL_COMMAND,DccSendDialog_CANCEL),NULL);
141         return 1;
142     }
143     return 0;
144 }
145 
146 FXDEFMAP(NickList) NickListMap [] = {
147     FXMAPFUNC(SEL_QUERY_TIP, 0, NickList::onQueryTip)
148 };
149 
FXIMPLEMENT(NickList,FXList,NickListMap,ARRAYNUMBER (NickListMap))150 FXIMPLEMENT(NickList, FXList, NickListMap, ARRAYNUMBER(NickListMap))
151 
152 NickList::NickList(FXComposite* p, IrcTabItem* tgt, FXSelector sel, FXuint opts, FXint x, FXint y, FXint w, FXint h)
153         : FXList(p, tgt, sel, opts, x, y, w, h), m_parent(tgt)
154 {
155 }
156 
onQueryTip(FXObject * sender,FXSelector sel,void * ptr)157 long NickList::onQueryTip(FXObject *sender, FXSelector sel, void *ptr)
158 {
159     if(FXWindow::onQueryTip(sender, sel, ptr)) return 1;
160     if((flags&FLAG_TIP) && !(options&LIST_AUTOSELECT) && (0<=cursor)) // No tip when autoselect!
161     {
162         FXString string = items[cursor]->getText();
163         string.append('\n');
164         NickInfo nick = m_parent->m_engine->getNickInfo(items[cursor]->getText());
165         string.append(FXStringFormat(_("User: %s@%s\n"), nick.user.text(), nick.host.text()));
166         string.append(FXStringFormat(_("Realname: %s"), nick.real.text()));
167         sender->handle(this, FXSEL(SEL_COMMAND,ID_SETSTRINGVALUE), (void*)&string);
168         return 1;
169     }
170     return 0;
171 }
172 
173 FXIMPLEMENT(NickListItem, FXListItem, NULL, 0)
174 
175 // Draw item
draw(const FXList * list,FXDC & dc,FXint xx,FXint yy,FXint ww,FXint hh)176 void NickListItem::draw(const FXList* list, FXDC& dc, FXint xx, FXint yy, FXint ww, FXint hh)
177 {
178     FXFont *font=list->getFont();
179     FXint ih=0,th=0;
180     if(icon) ih=icon->getHeight();
181     if(!label.empty()) th=font->getFontHeight();
182     dc.setForeground(list->getBackColor());     // FIXME maybe paint background in onPaint?
183     dc.fillRectangle(xx,yy,ww,hh);
184     if(isSelected())
185     {
186         dc.drawFocusRectangle(xx+1,yy+1,ww-2,hh-2);
187     }
188     xx+=SIDE_SPACING/2;
189     if(icon)
190     {
191         dc.drawIcon(icon,xx,yy+(hh-ih)/2);
192         xx+=ICON_SPACING+icon->getWidth();
193     }
194     else
195     {
196         FXString mode = "";
197         switch(m_mode){
198             case ADMIN: mode = "!";break;
199             case OWNER: mode = "*";break;
200             case OP: mode = "@";break;
201             case HALFOP: mode = "%";break;
202             case VOICE: mode= "+";break;
203             case NONE: mode = " ";break;
204         }
205         dc.setFont(font);
206         dc.setForeground(list->getTextColor());
207         dc.drawText(xx,yy+(hh-th)/2+font->getFontAscent(),mode);
208         xx+=ICON_SPACING+font->getTextWidth("@");
209     }
210     if(!label.empty())
211     {
212         dc.setFont(font);
213         if(m_away)
214             dc.setForeground(makeAwayColor(list->getTextColor()));
215         else
216             dc.setForeground(list->getTextColor());
217         dc.drawText(xx,yy+(hh-th)/2+font->getFontAscent(),label);
218     }
219 }
220 
221 // Get width of item
getWidth(const FXList * list) const222 FXint NickListItem::getWidth(const FXList* list) const
223 {
224     FXFont *font=list->getFont();
225     FXint w=0;
226     if(icon)
227     {
228         w=icon->getWidth();
229     }
230     else
231     {
232         w=font->getTextWidth("@");
233     }
234     if(!label.empty())
235     {
236         if(w) w+=ICON_SPACING;
237         w+=font->getTextWidth(label.text(),label.length());
238     }
239     return SIDE_SPACING+w;
240 }
241 
setUserMode(UserMode mode)242 void NickListItem::setUserMode(UserMode mode)
243 {
244     m_mode = mode;
245     m_parent->recalc();
246     if(icon)
247     {
248         switch(m_mode){
249             case ADMIN: setIcon(m_away? ICO_IRCAWAYADMIN:ICO_IRCADMIN);break;
250             case OWNER: setIcon(m_away? ICO_IRCAWAYOWNER:ICO_IRCOWNER);break;
251             case OP: setIcon(m_away? ICO_IRCAWAYOP:ICO_IRCOP);break;
252             case HALFOP: setIcon(m_away? ICO_IRCAWAYHALFOP:ICO_IRCHALFOP);break;
253             case VOICE: setIcon(m_away? ICO_IRCAWAYVOICE:ICO_IRCVOICE);break;
254             case NONE: setIcon(m_away? ICO_IRCAWAYNORMAL:ICO_IRCNORMAL);break;
255         }
256     }
257 }
258 
changeAway(FXbool away)259 void NickListItem::changeAway(FXbool away)
260 {
261     if(m_away == away) return;
262     m_away = away;
263     m_parent->recalc();
264     if(icon)
265     {
266         switch(m_mode){
267             case ADMIN: setIcon(m_away? ICO_IRCAWAYADMIN:ICO_IRCADMIN);break;
268             case OWNER: setIcon(m_away? ICO_IRCAWAYOWNER:ICO_IRCOWNER);break;
269             case OP: setIcon(m_away? ICO_IRCAWAYOP:ICO_IRCOP);break;
270             case HALFOP: setIcon(m_away? ICO_IRCAWAYHALFOP:ICO_IRCHALFOP);break;
271             case VOICE: setIcon(m_away? ICO_IRCAWAYVOICE:ICO_IRCVOICE);break;
272             case NONE: setIcon(m_away? ICO_IRCAWAYNORMAL:ICO_IRCNORMAL);break;
273         }
274     }
275 }
276 
277 //Clear icon, usefull for nick icon theme change
clearIcon()278 void NickListItem::clearIcon()
279 {
280     if(icon)
281         setIcon(NULL);
282 }
283 
284 //Apply new theme icon, usefull for nick icon theme change
restoreIcon()285 void NickListItem::restoreIcon()
286 {
287     m_parent->recalc();
288     switch(m_mode){
289         case ADMIN: setIcon(m_away? ICO_IRCAWAYADMIN:ICO_IRCADMIN);break;
290         case OWNER: setIcon(m_away? ICO_IRCAWAYOWNER:ICO_IRCOWNER);break;
291         case OP: setIcon(m_away? ICO_IRCAWAYOP:ICO_IRCOP);break;
292         case HALFOP: setIcon(m_away? ICO_IRCAWAYHALFOP:ICO_IRCHALFOP);break;
293         case VOICE: setIcon(m_away? ICO_IRCAWAYVOICE:ICO_IRCVOICE);break;
294         case NONE: setIcon(m_away? ICO_IRCAWAYNORMAL:ICO_IRCNORMAL);break;
295     }
296 }
297 
298 FXDEFMAP(IrcTabItem) IrcTabItemMap[] = {
299     FXMAPFUNC(SEL_COMMAND,              IrcTabItem_COMMANDLINE,     IrcTabItem::onCommandline),
300     FXMAPFUNC(SEL_KEYPRESS,             IrcTabItem_COMMANDLINE,     IrcTabItem::onKeyPress),
301     FXMAPFUNC(SEL_COMMAND,              IrcEngine_SERVER,           IrcTabItem::onIrcEvent),
302     FXMAPFUNC(SEL_TIMEOUT,              IrcTabItem_PTIME,           IrcTabItem::onPipeTimeout),
303     FXMAPFUNC(SEL_TIMEOUT,              IrcTabItem_ETIME,           IrcTabItem::onEggTimeout),
304     FXMAPFUNC(SEL_RIGHTBUTTONRELEASE,   IrcTabItem_USERS,           IrcTabItem::onRightMouse),
305     FXMAPFUNC(SEL_DOUBLECLICKED,        IrcTabItem_USERS,           IrcTabItem::onDoubleclick),
306     FXMAPFUNC(SEL_COMMAND,              IrcTabItem_NEWQUERY,        IrcTabItem::onNewQuery),
307     FXMAPFUNC(SEL_COMMAND,              IrcTabItem_WHOIS,           IrcTabItem::onWhois),
308     FXMAPFUNC(SEL_COMMAND,              IrcTabItem_DCCCHAT,         IrcTabItem::onDccChat),
309     FXMAPFUNC(SEL_COMMAND,              IrcTabItem_DCCSEND,         IrcTabItem::onDccSend),
310     FXMAPFUNC(SEL_COMMAND,              IrcTabItem_OP,              IrcTabItem::onOp),
311     FXMAPFUNC(SEL_COMMAND,              IrcTabItem_DEOP,            IrcTabItem::onDeop),
312     FXMAPFUNC(SEL_COMMAND,              IrcTabItem_VOICE,           IrcTabItem::onVoice),
313     FXMAPFUNC(SEL_COMMAND,              IrcTabItem_DEVOICE,         IrcTabItem::onDevoice),
314     FXMAPFUNC(SEL_COMMAND,              IrcTabItem_KICK,            IrcTabItem::onKick),
315     FXMAPFUNC(SEL_COMMAND,              IrcTabItem_BAN,             IrcTabItem::onBan),
316     FXMAPFUNC(SEL_COMMAND,              IrcTabItem_KICKBAN,         IrcTabItem::onKickban),
317     FXMAPFUNC(SEL_COMMAND,              IrcTabItem_IGNORE,          IrcTabItem::onIgnore),
318     FXMAPFUNC(SEL_COMMAND,              IrcTabItem_TOPIC,           IrcTabItem::onTopic),
319     FXMAPFUNC(SEL_LINK,                 IrcTabItem_TOPIC,           IrcTabItem::onTopicLink),
320     FXMAPFUNC(SEL_COMMAND,              dxPipe::ID_PIPE,            IrcTabItem::onPipe),
321     FXMAPFUNC(SEL_COMMAND,              IrcTabItem_AWAY,            IrcTabItem::onSetAway),
322     FXMAPFUNC(SEL_COMMAND,              IrcTabItem_DEAWAY,          IrcTabItem::onRemoveAway),
323     FXMAPFUNC(SEL_COMMAND,              IrcTabItem_SPELL,           IrcTabItem::onSpellLang),
324     FXMAPFUNC(SEL_COMMAND,              LogThread_LIST,             IrcTabItem::onListLogThread),
325     FXMAPFUNC(SEL_COMMAND,              LogThread_LINES,            IrcTabItem::onLinesLogThread)
326 };
327 
FXIMPLEMENT(IrcTabItem,dxTabItem,IrcTabItemMap,ARRAYNUMBER (IrcTabItemMap))328 FXIMPLEMENT(IrcTabItem, dxTabItem, IrcTabItemMap, ARRAYNUMBER(IrcTabItemMap))
329 
330 IrcTabItem::IrcTabItem(dxTabBook *tab, const FXString &tabtext, FXIcon *icon, FXuint opts,
331         FXint id, TYPE type, IrcEngine *socket, FXFont *font, FXbool useNickIcon)
332     : dxTabItem(tab, tabtext, icon, opts, id), m_engine(socket), m_parent(tab), m_type(type),
333         m_useNickIcon(useNickIcon), m_logstream(NULL)
334 {
335     m_currentPosition = 0;
336     m_historyMax = 25;
337     m_numberUsers = 0;
338     m_maxLen = 460;
339     m_iamOp = FALSE;
340     m_topic = _("No topic is set");
341     m_editableTopic = TRUE;
342     m_pipe = NULL;
343     m_sendPipe = FALSE;
344     m_scriptHasAll = FALSE;
345     m_scriptHasOwnMsg = FALSE;
346     m_loadLog = FALSE;
347 
348     if(m_type == CHANNEL && m_engine && m_engine->getConnected())
349     {
350         m_engine->sendMode(getText());
351     }
352 
353     m_mainframe = new FXVerticalFrame(m_parent, FRAME_RAISED|LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y);
354 
355     m_splitter = new FXSplitter(m_mainframe, LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y|SPLITTER_REVERSED|SPLITTER_TRACKING);
356 
357     m_textframe = new FXVerticalFrame(m_splitter, FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y);
358     m_topicline = new dxTextField(m_textframe, 50, this, IrcTabItem_TOPIC, FRAME_SUNKEN|TEXTFIELD_ENTER_ONLY|JUSTIFY_LEFT|LAYOUT_FILL_X);
359     m_topicline->setFont(font);
360     m_topicline->setLinkColor(preferences.m_colors.link);
361     m_topicline->setText(m_topic);
362     m_topicline->setUseLink(TRUE);
363     m_topicline->setTopicline(TRUE);
364     if(m_type != CHANNEL)
365     {
366         m_topicline->hide();
367     }
368     m_text->reparent(m_textframe);
369     m_text->setFont(font);
370     m_text->setSelTextColor(getApp()->getSelforeColor());
371     m_text->setSelBackColor(getApp()->getSelbackColor());
372 
373     m_usersframe = new FXVerticalFrame(m_splitter, FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_FIX_WIDTH);
374     m_users = new NickList(m_usersframe, this, IrcTabItem_USERS, LAYOUT_FILL_X|LAYOUT_FILL_Y);
375     m_users->setSortFunc(preferences.m_sortUserMode ? sortNick : FXList::ascendingCase);
376     m_users->setScrollStyle(HSCROLLING_OFF);
377     if(preferences.m_sameList) m_users->setFont(font);
378     if(m_type != CHANNEL || !preferences.m_usersShown)
379     {
380         m_usersframe->hide();
381         m_users->hide();
382     }
383 
384     m_commandframe = new FXHorizontalFrame(m_mainframe, LAYOUT_FILL_X, 0,0,0,0, 0,0,0,0);
385     m_commandline = new dxTextField(m_commandframe, 25, this, IrcTabItem_COMMANDLINE, TEXTFIELD_ENTER_ONLY|FRAME_SUNKEN|JUSTIFY_LEFT|LAYOUT_FILL_X|LAYOUT_BOTTOM, 0, 0, 0, 0, 1, 1, 1, 1);
386     if(preferences.m_sameCmd) m_commandline->setFont(font);
387     m_spellLangs = new FXComboBox(m_commandframe, 6, this, IrcTabItem_SPELL, FRAME_SUNKEN|COMBOBOX_STATIC);
388     m_spellLangs->setTipText(_("Spellchecking language list"));
389     m_spellLangs->hide();
390     if(preferences.m_sameCmd) m_spellLangs->setFont(font);
391     if(preferences.m_useSpell && (m_type==CHANNEL || m_type==QUERY) && dxUtils.getAvailableSpellLangsNum())
392     {
393         dxStringArray langs = dxUtils.getAvailableSpellLangs();
394         FXString lang = dxUtils.getChannelLang(getText());
395         for(FXint i=0; i<langs.no(); i++)
396         {
397             m_spellLangs->appendItem(langs[i]);
398             if(langs[i]==lang) m_spellLangs->setCurrentItem(i);;
399         }
400         if(preferences.m_showSpellCombo) m_spellLangs->show();
401         m_commandline->setUseSpell(TRUE);
402         m_commandline->setLanguage(lang);
403         m_commandline->setTipText(FXStringFormat(_("Current spellchecking language: %s"),lang.text()));
404     }
405 
406     dxHiliteStyle style = {preferences.m_colors.text,preferences.m_colors.back,getApp()->getSelforeColor(),getApp()->getSelbackColor(),0,FALSE};
407     for(int i=0; i<19; i++)
408     {
409         m_textStyleList.append(style);
410     }
411     //gray text - user commands
412     m_textStyleList[0].normalForeColor = preferences.m_colors.user;
413     //orange text - Actions
414     m_textStyleList[1].normalForeColor = preferences.m_colors.action;
415     //blue text - Notice
416     m_textStyleList[2].normalForeColor = preferences.m_colors.notice;
417     //red text - Errors
418     m_textStyleList[3].normalForeColor = preferences.m_colors.error;
419     //bold style
420     m_textStyleList[4].style = FXText::STYLE_BOLD;
421     //underline style
422     m_textStyleList[5].style = FXText::STYLE_UNDERLINE;
423     //bold & underline
424     m_textStyleList[6].style = FXText::STYLE_UNDERLINE;
425     m_textStyleList[6].style ^=FXText::STYLE_BOLD;
426     //highlight text
427     m_textStyleList[7].normalForeColor = preferences.m_colors.hilight;
428     //link style
429     m_textStyleList[8].normalForeColor = preferences.m_colors.link;
430     m_textStyleList[8].link = TRUE;
431     //mymsg style
432     m_textStyleList[9].normalForeColor = preferences.m_colors.mymsg;
433     //log line style
434     m_textStyleList[10].normalForeColor = preferences.m_colors.log;
435     //next styles for colored nicks
436     m_textStyleList[11].normalForeColor = FXRGB(196, 160, 0);
437     m_textStyleList[12].normalForeColor = FXRGB(206, 92, 0);
438     m_textStyleList[13].normalForeColor = FXRGB(143, 89, 2);
439     m_textStyleList[14].normalForeColor = FXRGB(78, 154, 6);
440     m_textStyleList[15].normalForeColor = FXRGB(32, 74, 135);
441     m_textStyleList[16].normalForeColor = FXRGB(117, 80, 123);
442     m_textStyleList[17].normalForeColor = FXRGB(164, 0, 0);
443     m_textStyleList[18].normalForeColor = FXRGB(85, 87, 83);
444 
445     //text->setStyled(TRUE);
446     m_text->setHiliteStyles(m_textStyleList.data());
447 
448     m_text->setBackColor(preferences.m_colors.back);
449     m_commandline->setBackColor(preferences.m_colors.back);
450     m_topicline->setBackColor(preferences.m_colors.back);
451     m_users->setBackColor(preferences.m_colors.back);
452     m_text->setTextColor(preferences.m_colors.text);
453     m_commandline->setTextColor(preferences.m_colors.text);
454     m_commandline->setCursorColor(preferences.m_colors.text);
455     m_topicline->setTextColor(preferences.m_colors.text);
456     m_topicline->setCursorColor(preferences.m_colors.text);
457     m_users->setTextColor(preferences.m_colors.text);
458     m_spellLangs->setBackColor(preferences.m_colors.back);
459     m_spellLangs->setTextColor(preferences.m_colors.text);
460 
461     this->setIconPosition(ICON_BEFORE_TEXT);
462 
463     if(m_engine) m_logThread = new LogThread(this, getApp(), preferences.m_logPath+PATHSEPSTRING+m_engine->getNetworkName()+PATHSEPSTRING+getText());
464 }
465 
~IrcTabItem()466 IrcTabItem::~IrcTabItem()
467 {
468     this->stopLogging();
469     if(m_pipe) m_pipe->closePipe();
470     m_pipeStrings.clear();
471     getApp()->removeTimeout(this, IrcTabItem_PTIME);
472 }
473 
createGeom()474 void IrcTabItem::createGeom()
475 {
476     m_mainframe->create();
477     loadLogLines();
478     m_commandline->setFocus();
479 }
480 
clearChat()481 void IrcTabItem::clearChat()
482 {
483     m_textStyleList.no(19);
484     m_text->setHiliteStyles(m_textStyleList.data());
485     m_text->clearText();
486 }
487 
488 //usefull for set tab current
makeLastRowVisible()489 void IrcTabItem::makeLastRowVisible()
490 {
491     m_text->makeLastRowVisible(TRUE);
492 }
493 
getSpellLang()494 FXString IrcTabItem::getSpellLang()
495 {
496 #ifdef HAVE_ENCHANT
497     if(m_spellLangs->getNumItems()) return m_spellLangs->getItemText(m_spellLangs->getCurrentItem());
498 #endif
499     return "";
500 }
501 
reparentTab()502 void IrcTabItem::reparentTab()
503 {
504     reparent(m_parent);
505     m_mainframe->reparent(m_parent);
506     recalc();
507     m_mainframe->recalc();
508 }
509 
hideUsers()510 void IrcTabItem::hideUsers()
511 {
512     if(m_type == CHANNEL)
513     {
514         m_usersframe->hide();
515         m_users->hide();
516         m_splitter->setSplit(1, 0);
517     }
518 }
519 
showUsers()520 void IrcTabItem::showUsers()
521 {
522     if(m_type == CHANNEL)
523     {
524         m_usersframe->show();
525         m_users->show();
526         m_splitter->recalc();
527     }
528 }
529 
setType(const TYPE & typ,const FXString & tabtext)530 void IrcTabItem::setType(const TYPE &typ, const FXString &tabtext)
531 {
532     if(typ == CHANNEL)
533     {
534         if(preferences.m_usersShown) m_usersframe->show();
535         if(preferences.m_usersShown) m_users->show();
536         m_topicline->show();
537         m_topicline->setText(m_topic);
538         m_splitter->recalc();
539         setText(tabtext);
540         if(m_engine->getConnected()) m_engine->sendMode(getText());
541         m_type = typ;
542     }
543     else if(typ == SERVER || typ == QUERY)
544     {
545         m_usersframe->hide();
546         m_users->hide();
547         m_topicline->setText("");
548         m_topicline->hide();
549         m_topic = _("No topic is set");
550         setText(tabtext);
551         m_splitter->setSplit(1, 0);
552         if(m_type == CHANNEL)
553         {
554             m_users->clearItems();
555             m_numberUsers = 0;
556         }
557         m_type = typ;
558     }
559     this->stopLogging();
560     if(m_type == SERVER) this->setIcon(ICO_SERVER);
561     else if(m_type == CHANNEL) this->setIcon(ICO_CHANNEL);
562     else this->setIcon(ICO_QUERY);
563     if(m_type==CHANNEL || m_type==QUERY)
564         loadLogLines();
565     if(preferences.m_useSpell && (m_type==CHANNEL || m_type==QUERY) && dxUtils.getAvailableSpellLangsNum())
566     {
567         dxStringArray langs = dxUtils.getAvailableSpellLangs();
568         FXString lang = dxUtils.getChannelLang(getText());
569         for(FXint i=0; i<langs.no(); i++)
570         {
571             m_spellLangs->appendItem(langs[i]);
572             if(langs[i]==lang) m_spellLangs->setCurrentItem(i);
573         }
574         if(preferences.m_showSpellCombo) m_spellLangs->show();
575         m_commandline->setUseSpell(TRUE);
576         m_commandline->setLanguage(lang);
577         m_commandline->setTipText(FXStringFormat(_("Current spellchecking language: %s"),lang.text()));
578     }
579     else
580     {
581         m_commandline->setUseSpell(FALSE);
582         m_commandline->setTipText("");
583         m_spellLangs->hide();
584     }
585     m_commandframe->recalc();
586 }
587 
preferencesUpdated()588 void IrcTabItem::preferencesUpdated()
589 {
590     setTextForeColor(preferences.m_colors.text);
591     setTextBackColor(preferences.m_colors.back);
592     setUserColor(preferences.m_colors.user);
593     setActionsColor(preferences.m_colors.action);
594     setNoticeColor(preferences.m_colors.notice);
595     setErrorColor(preferences.m_colors.error);
596     setHilightColor(preferences.m_colors.hilight);
597     setLinkColor(preferences.m_colors.link);
598     setMymsgColor(preferences.m_colors.mymsg);
599     setLogColor(preferences.m_colors.log);
600     stopLogging();
601     if(preferences.m_useSpell && (m_type==CHANNEL || m_type==QUERY) && dxUtils.getAvailableSpellLangsNum())
602     {
603         dxStringArray langs = dxUtils.getAvailableSpellLangs();
604         FXString lang = dxUtils.getChannelLang(getText());
605         for(FXint i=0; i<langs.no(); i++)
606         {
607             m_spellLangs->appendItem(langs[i]);
608             if(langs[i]==lang) m_spellLangs->setCurrentItem(i);;
609         }
610         if(preferences.m_showSpellCombo) m_spellLangs->show();
611         m_commandline->setUseSpell(TRUE);
612         m_commandline->setLanguage(lang);
613         m_commandline->setTipText(FXStringFormat(_("Current spellchecking language: %s"),lang.text()));
614     }
615     else
616     {
617         m_commandline->setUseSpell(FALSE);
618         m_commandline->setTipText("");
619         m_spellLangs->hide();
620     }
621     m_users->setSortFunc(preferences.m_sortUserMode ? sortNick : FXList::ascendingCase);
622     m_users->sortItems();
623     m_commandframe->recalc();
624 }
625 
setTextBackColor(FXColor clr)626 void IrcTabItem::setTextBackColor(FXColor clr)
627 {
628     for(FXint i=0; i<m_textStyleList.no(); i++)
629     {
630         m_textStyleList[i].normalBackColor = clr;
631     }
632     m_text->setBackColor(clr);
633     m_commandline->setBackColor(clr);
634     m_topicline->setBackColor(clr);
635     m_users->setBackColor(clr);
636     m_spellLangs->setBackColor(clr);
637 }
638 
setTextForeColor(FXColor clr)639 void IrcTabItem::setTextForeColor(FXColor clr)
640 {
641     m_textStyleList[4].normalForeColor = clr;
642     m_textStyleList[5].normalForeColor = clr;
643     m_textStyleList[6].normalForeColor = clr;
644     m_text->setTextColor(clr);
645     m_commandline->setTextColor(clr);
646     m_commandline->setCursorColor(clr);
647     m_topicline->setTextColor(clr);
648     m_topicline->setCursorColor(clr);
649     m_users->setTextColor(clr);
650     m_spellLangs->setTextColor(clr);
651 }
652 
setUserColor(FXColor clr)653 void IrcTabItem::setUserColor(FXColor clr)
654 {
655     m_textStyleList[0].normalForeColor = clr;
656 }
657 
setActionsColor(FXColor clr)658 void IrcTabItem::setActionsColor(FXColor clr)
659 {
660     m_textStyleList[1].normalForeColor = clr;
661 }
662 
setNoticeColor(FXColor clr)663 void IrcTabItem::setNoticeColor(FXColor clr)
664 {
665     m_textStyleList[2].normalForeColor = clr;
666 }
667 
setErrorColor(FXColor clr)668 void IrcTabItem::setErrorColor(FXColor clr)
669 {
670     m_textStyleList[3].normalForeColor = clr;
671 }
672 
setHilightColor(FXColor clr)673 void IrcTabItem::setHilightColor(FXColor clr)
674 {
675     m_textStyleList[7].normalForeColor = clr;
676 }
677 
setLinkColor(FXColor clr)678 void IrcTabItem::setLinkColor(FXColor clr)
679 {
680     m_textStyleList[8].normalForeColor = clr;
681     m_topicline->setLinkColor(clr);
682 }
683 
setMymsgColor(FXColor clr)684 void IrcTabItem::setMymsgColor(FXColor clr)
685 {
686     m_textStyleList[9].normalForeColor = clr;
687 }
688 
setLogColor(FXColor clr)689 void IrcTabItem::setLogColor(FXColor clr)
690 {
691     m_textStyleList[10].normalForeColor = clr;
692 }
693 
setIrcFont(FXFont * fnt)694 void IrcTabItem::setIrcFont(FXFont *fnt)
695 {
696     m_text->setFont(fnt);
697     m_text->recalc();
698     m_topicline->setFont(fnt);
699     m_topicline->recalc();
700     if(preferences.m_sameCmd)
701     {
702         m_commandline->setFont(fnt);
703         m_commandline->recalc();
704         m_spellLangs->setFont(fnt);
705         m_spellLangs->recalc();
706     }
707     else
708     {
709         m_commandline->setFont(getApp()->getNormalFont());
710         m_commandline->recalc();
711         m_spellLangs->setFont(getApp()->getNormalFont());
712         m_spellLangs->recalc();
713     }
714     if(preferences.m_sameList)
715     {
716         m_users->setFont(fnt);
717         m_users->recalc();
718     }
719     else
720     {
721         m_users->setFont(getApp()->getNormalFont());
722         m_users->recalc();
723     }
724 }
725 
setSmileys(FXbool smiley,dxSmileyArray nsmileys)726 void IrcTabItem::setSmileys(FXbool smiley, dxSmileyArray nsmileys)
727 {
728     m_text->setSmileys(smiley, nsmileys);
729 }
730 
showSpellComboUpdated()731 void IrcTabItem::showSpellComboUpdated()
732 {
733     if(m_type == CHANNEL || m_type == QUERY)
734     {
735         if(preferences.m_showSpellCombo) m_spellLangs->show();
736         else m_spellLangs->hide();
737         m_commandframe->recalc();
738     }
739 }
740 
removeSmileys()741 void IrcTabItem::removeSmileys()
742 {
743     m_text->removeSmileys();
744 }
745 
746 //if highlight==TRUE, highlight tab
appendText(FXString msg,FXbool highlight,FXbool logLine)747 void IrcTabItem::appendText(FXString msg, FXbool highlight, FXbool logLine)
748 {
749     appendIrcText(msg, 0, FALSE, logLine);
750     if(highlight && preferences.m_highlightColor != this->getTextColor() && m_parent->getCurrent()*2 != m_parent->indexOfChild(this))
751     {
752         if(highlightNeeded(msg))
753         {
754             this->setTextColor(preferences.m_highlightColor);
755             if(m_type == CHANNEL) this->setIcon(ICO_CHANNELNEWMSG);
756         }
757         else this->setTextColor(preferences.m_unreadColor);
758         if(m_type == QUERY) this->setIcon(ICO_QUERYNEWMSG);
759     }
760 }
761 
appendIrcText(FXString msg,FXTime time,FXbool disableStrip,FXbool logLine)762 void IrcTabItem::appendIrcText(FXString msg, FXTime time, FXbool disableStrip, FXbool logLine)
763 {
764     if(!time) time = FXSystem::now();
765     if(m_type != OTHER) m_text->appendText(FXSystem::time("[%H:%M:%S] ", time));
766     if(preferences.m_stripColors && !disableStrip) msg = dxutils::stripColors(msg, FALSE);
767     appendLinkText(msg, 0);
768     if(logLine) this->logLine(msg, time);
769 }
770 
appendIrcNickText(FXString nick,FXString msg,FXint style,FXTime time,FXbool logLine)771 void IrcTabItem::appendIrcNickText(FXString nick, FXString msg, FXint style, FXTime time, FXbool logLine)
772 {
773     if(!time) time = FXSystem::now();
774     if(m_type != OTHER) m_text->appendText(FXSystem::time("[%H:%M:%S] ", time));
775     m_text->appendStyledText(nick+": ", style);
776     if(preferences.m_stripColors) msg = dxutils::stripColors(msg, FALSE);
777     appendLinkText(msg, 0);
778     if(logLine) this->logLine("<"+nick+"> "+msg, time);
779 }
780 
appendMyMsg(FXString msg,FXTime time)781 void IrcTabItem::appendMyMsg(FXString msg, FXTime time)
782 {
783     if(!time) time = FXSystem::now();
784     m_text->appendText(FXSystem::time("[%H:%M:%S] ", time));
785     m_text->appendStyledText(getNickName()+": ", preferences.m_coloredNick?10:5);
786     if(preferences.m_stripColors) msg = dxutils::stripColors(msg, FALSE);
787     appendLinkText(msg, 10);
788     this->logLine("\01410\014<"+getNickName()+"> "+msg, time);
789 }
790 
791 /* if highlight==TRUE, highlight tab
792  * disableStrip is for dxirc.Print
793 */
appendStyledText(FXString text,FXint style,FXbool highlight,FXbool disableStrip,FXbool logLine)794 void IrcTabItem::appendStyledText(FXString text, FXint style, FXbool highlight, FXbool disableStrip, FXbool logLine)
795 {
796     if(style) appendIrcStyledText(text, style, 0, disableStrip, logLine);
797     else appendIrcText(text, 0, disableStrip, logLine);
798     if(highlight && preferences.m_highlightColor != this->getTextColor() && m_parent->getCurrent()*2 != m_parent->indexOfChild(this))
799     {
800         if(m_type != OTHER && highlightNeeded(text))
801         {
802             this->setTextColor(preferences.m_highlightColor);
803             if(m_type == CHANNEL) this->setIcon(ICO_CHANNELNEWMSG);
804         }
805         else this->setTextColor(preferences.m_unreadColor);
806         if(m_type == QUERY) this->setIcon(ICO_QUERYNEWMSG);
807     }
808 }
809 
appendIrcStyledText(FXString styled,FXint stylenum,FXTime time,FXbool disableStrip,FXbool logLine)810 void IrcTabItem::appendIrcStyledText(FXString styled, FXint stylenum, FXTime time, FXbool disableStrip, FXbool logLine)
811 {
812     if(!time) time = FXSystem::now();
813     if(m_type != OTHER) m_text->appendText(FXSystem::time("[%H:%M:%S] ", time));
814     if(preferences.m_stripColors && !disableStrip) styled = dxutils::stripColors(styled, TRUE);
815     appendLinkText(styled, stylenum);
816     if(logLine)
817     {
818         if(stylenum==8) //highlight msg
819         {
820             this->logLine("\0148\014<"+styled.before(':')+">"+styled.after(':'), time);
821         }
822         else this->logLine(FXStringFormat("\014%d\014%s", stylenum, styled.text()), time);
823     }
824 }
825 
isBadchar(FXchar c)826 static FXbool isBadchar(FXchar c)
827 {
828     switch(c) {
829         case ' ':
830         case ',':
831         case '\0':
832         case '\02':
833         case '\03':
834         case '\017':
835         case '\021':
836         case '\026':
837         case '\035':
838         case '\037':
839         case '\n':
840         case '\r':
841         case '<':
842         case '>':
843         case '"':
844         case '\'':
845             return TRUE;
846         default:
847             return FALSE;
848     }
849 }
850 
851 // checks is char nick/word delimiter
isDelimiter(FXchar c)852 static FXbool isDelimiter(FXchar c)
853 {
854     switch(c) {
855         case ' ':
856         case '.':
857         case ',':
858         case '/':
859         case '\\':
860         case '`':
861         case '\'':
862         case '!':
863         case '(':
864         case ')':
865         case '{':
866         case '}':
867         case '|':
868         case '[':
869         case ']':
870         case '\"':
871         case ':':
872         case ';':
873         case '<':
874         case '>':
875         case '?':
876             return TRUE;
877         default:
878             return FALSE;
879     }
880 }
881 
appendLinkText(const FXString & txt,FXint stylenum)882 void IrcTabItem::appendLinkText(const FXString &txt, FXint stylenum)
883 {
884     FXint i = 0;
885     FXint linkLength = 0;
886     FXbool bold = FALSE;
887     FXbool under = FALSE;
888     FXint lastStyle = stylenum;
889     FXColor foreColor = stylenum && stylenum<=m_textStyleList.no() ? m_textStyleList[stylenum-1].normalForeColor : preferences.m_colors.text;
890     FXColor backColor = stylenum && stylenum<=m_textStyleList.no() ? m_textStyleList[stylenum-1].normalBackColor : preferences.m_colors.back;
891     FXString normalText = "";
892     FXint length = txt.length();
893     while(i<length)
894     {
895         if(txt[i]=='h' && !comparecase(txt.mid(i,7),"http://"))
896         {
897             if(!normalText.empty())
898             {
899                 m_text->appendStyledText(normalText, lastStyle);
900                 normalText.clear();
901             }
902             for(FXint j=i; j<length; j++)
903             {
904                 if(isBadchar(txt[j]))
905                 {
906                     break;
907                 }
908                 linkLength++;
909             }
910             m_text->appendStyledText(txt.mid(i, linkLength), linkLength>7 ? 9 : stylenum);
911             i+=linkLength-1;
912             linkLength=0;
913         }
914         else if(txt[i]=='h' && !comparecase(txt.mid(i,8),"https://"))
915         {
916             if(!normalText.empty())
917             {
918                 m_text->appendStyledText(normalText, lastStyle);
919                 normalText.clear();
920             }
921             for(FXint j=i; j<length; j++)
922             {
923                 if(isBadchar(txt[j]))
924                 {
925                     break;
926                 }
927                 linkLength++;
928             }
929             m_text->appendStyledText(txt.mid(i, linkLength), linkLength>8 ? 9 : stylenum);
930             i+=linkLength-1;
931             linkLength=0;
932         }
933         else if(txt[i]=='f' && !comparecase(txt.mid(i,6),"ftp://"))
934         {
935             if(!normalText.empty())
936             {
937                 m_text->appendStyledText(normalText, lastStyle);
938                 normalText.clear();
939             }
940             for(FXint j=i; j<length; j++)
941             {
942                 if(isBadchar(txt[j]))
943                 {
944                     break;
945                 }
946                 linkLength++;
947             }
948             m_text->appendStyledText(txt.mid(i, linkLength), linkLength>6 ? 9 : stylenum);
949             i+=linkLength-1;
950             linkLength=0;
951         }
952         else if(txt[i]=='w' && !comparecase(txt.mid(i,4),"www."))
953         {
954             if(!normalText.empty())
955             {
956                 m_text->appendStyledText(normalText, lastStyle);
957                 normalText.clear();
958             }
959             for(FXint j=i; j<length; j++)
960             {
961                 if(isBadchar(txt[j]))
962                 {
963                     break;
964                 }
965                 linkLength++;
966             }
967             m_text->appendStyledText(txt.mid(i, linkLength), linkLength>4 ? 9 : stylenum);
968             i+=linkLength-1;
969             linkLength=0;
970         }
971         else
972         {
973             if(txt[i] == '\002') //bold
974             {
975                 if(!normalText.empty())
976                 {
977                     m_text->appendStyledText(normalText, lastStyle);
978                     normalText.clear();
979                 }
980                 bold = !bold;
981                 FXuint style = 0;
982                 if(bold && under) style = FXText::STYLE_BOLD|FXText::STYLE_UNDERLINE;
983                 else if(bold && !under) style = FXText::STYLE_BOLD;
984                 else if(!bold && under) style = FXText::STYLE_UNDERLINE;
985                 lastStyle = hiliteStyleExist(foreColor, backColor, style);
986                 if(lastStyle == -1)
987                 {
988                     //dxText has available max. 255 styles
989                     if(m_textStyleList.no()<256)
990                     {
991                         createHiliteStyle(foreColor, backColor, style);
992                         lastStyle = m_textStyleList.no();
993                     }
994                     else lastStyle = 0;
995                 }
996             }
997             else if(txt[i] == '\026') //reverse
998             {
999                 if(!normalText.empty())
1000                 {
1001                     m_text->appendStyledText(normalText, lastStyle);
1002                     normalText.clear();
1003                 }
1004                 FXuint style = 0;
1005                 if(bold && under) style = FXText::STYLE_BOLD|FXText::STYLE_UNDERLINE;
1006                 else if(bold && !under) style = FXText::STYLE_BOLD;
1007                 else if(!bold && under) style = FXText::STYLE_UNDERLINE;
1008                 FXColor tempColor = foreColor;
1009                 foreColor = backColor;
1010                 backColor = tempColor;
1011                 lastStyle = hiliteStyleExist(foreColor, backColor, style);
1012                 if(lastStyle == -1)
1013                 {
1014                     //dxText has available max. 255 styles
1015                     if(m_textStyleList.no()<256)
1016                     {
1017                         createHiliteStyle(foreColor, backColor, style);
1018                         lastStyle = m_textStyleList.no();
1019                     }
1020                     else lastStyle = 0;
1021                 }
1022             }
1023             else if(txt[i] == '\037') //underline
1024             {
1025                 if(!normalText.empty())
1026                 {
1027                     m_text->appendStyledText(normalText, lastStyle);
1028                     normalText.clear();
1029                 }
1030                 under = !under;
1031                 FXuint style = 0;
1032                 if(bold && under) style = FXText::STYLE_BOLD|FXText::STYLE_UNDERLINE;
1033                 else if(bold && !under) style = FXText::STYLE_BOLD;
1034                 else if(!bold && under) style = FXText::STYLE_UNDERLINE;
1035                 lastStyle = hiliteStyleExist(foreColor, backColor, style);
1036                 if(lastStyle == -1)
1037                 {
1038                     //dxText has available max. 255 styles
1039                     if(m_textStyleList.no()<256)
1040                     {
1041                         createHiliteStyle(foreColor, backColor, style);
1042                         lastStyle = m_textStyleList.no();
1043                     }
1044                     else lastStyle = 0;
1045                 }
1046             }
1047             else if(txt[i] == '\021') //fixed
1048             {
1049                 dxutils::debugLine("Poslan fixed styl");
1050             }
1051             else if(txt[i] == '\035') //italic
1052             {
1053                 dxutils::debugLine("Poslan italic styl");
1054             }
1055             else if(txt[i] == '\003') //color
1056             {
1057                 if(!normalText.empty())
1058                 {
1059                     m_text->appendStyledText(normalText, lastStyle);
1060                     normalText.clear();
1061                 }
1062                 FXuint style=0;
1063                 if(bold && under) style = FXText::STYLE_BOLD|FXText::STYLE_UNDERLINE;
1064                 else if(bold && !under) style = FXText::STYLE_BOLD;
1065                 else if(!bold && under) style = FXText::STYLE_UNDERLINE;
1066                 FXbool isHexColor = FALSE;
1067                 FXint colorLength = 0;
1068                 foreColor = preferences.m_colors.text;
1069                 backColor = preferences.m_colors.back;
1070                 if(i+1<length)
1071                 {
1072                     if(txt[i+1] == '#') isHexColor = TRUE;
1073                 }
1074                 if(isHexColor)
1075                 {
1076                     if(FXRex("^\\h\\h\\h\\h\\h\\h+$").match(txt.mid(i+2,6)))
1077                     {
1078                         foreColor = fxcolorfromname(txt.mid(i+1,7).text());
1079                         colorLength +=7;
1080                     }
1081                     if(i+8 < length && txt[i+8] == ',' && FXRex("^\\h\\h\\h\\h\\h\\h+$").match(txt.mid(i+10,6)))
1082                     {
1083                         backColor = fxcolorfromname(txt.mid(i+9,7).text());
1084                         colorLength +=8;
1085                     }
1086                 }
1087                 else
1088                 {
1089                     if(i+2<length)
1090                     {
1091                         FXint code = -1;
1092                         if(isdigit(txt[i+1]))
1093                         {
1094                             if(isdigit(txt[i+2]))
1095                             {
1096                                 code = (txt[i+1]-48)*10+txt[i+2]-48;
1097                                 colorLength +=2;
1098                             }
1099                             else
1100                             {
1101                                 code = txt[i+1]-48;
1102                                 colorLength ++;
1103                             }
1104                         }
1105                         if(code!=-1)
1106                             foreColor = dxutils::getIrcColor(code, true);
1107                     }
1108                     if(i+colorLength+1 < length && txt[i+colorLength+1] == ',')
1109                     {
1110                         FXint code = -1;
1111                         if(isdigit(txt[i+colorLength+2]))
1112                         {
1113                             if(isdigit(txt[i+colorLength+3]))
1114                             {
1115                                 code = (txt[i+colorLength+2]-48)*10+txt[i+colorLength+3]-48;
1116                                 colorLength +=3;
1117                             }
1118                             else
1119                             {
1120                                 code = txt[i+colorLength+2]-48;
1121                                 colorLength +=2;
1122                             }
1123                         }
1124                         if(code!=-1)
1125                             backColor = dxutils::getIrcColor(code, false);
1126                     }
1127                 }
1128                 lastStyle = hiliteStyleExist(foreColor, backColor, style);
1129                 if(lastStyle == -1)
1130                 {
1131                     //dxText has available max. 255 styles
1132                     if(m_textStyleList.no()<256)
1133                     {
1134                         createHiliteStyle(foreColor, backColor, style);
1135                         lastStyle = m_textStyleList.no();
1136                     }
1137                     else lastStyle = 0;
1138                 };
1139                 i +=colorLength;
1140             }
1141             else if(txt[i] == '\004') // hex color
1142             {
1143                 if(!normalText.empty())
1144                 {
1145                     m_text->appendStyledText(normalText, lastStyle);
1146                     normalText.clear();
1147                 }
1148                 FXuint style=0;
1149                 if(bold && under) style = FXText::STYLE_BOLD|FXText::STYLE_UNDERLINE;
1150                 else if(bold && !under) style = FXText::STYLE_BOLD;
1151                 else if(!bold && under) style = FXText::STYLE_UNDERLINE;
1152                 FXint colorLength = 0;
1153                 foreColor = preferences.m_colors.text;
1154                 backColor = preferences.m_colors.back;
1155                 if(FXRex("^\\h\\h\\h\\h\\h\\h+$").match(txt.mid(i+1,6)))
1156                 {
1157                     FXString color = "#";
1158                     color.append(txt.mid(i+1,6));
1159                     foreColor = fxcolorfromname(color.text());
1160                     colorLength +=6;
1161                 }
1162                 if(i+7 < length && txt[i+7] == ',' && FXRex("^\\h\\h\\h\\h\\h\\h+$").match(txt.mid(i+8,6)))
1163                 {
1164                     FXString color = "#";
1165                     color.append(txt.mid(i+8,6));
1166                     backColor = fxcolorfromname(color.text());
1167                     colorLength +=7;
1168                 }
1169                 lastStyle = hiliteStyleExist(foreColor, backColor, style);
1170                 if(lastStyle == -1)
1171                 {
1172                     //dxText has available max. 255 styles
1173                     if(m_textStyleList.no()<256)
1174                     {
1175                         createHiliteStyle(foreColor, backColor, style);
1176                         lastStyle = m_textStyleList.no();
1177                     }
1178                     else lastStyle = 0;
1179                 };
1180                 i +=colorLength;
1181             }
1182             else if(txt[i] == '\017') //reset
1183             {
1184                 if(!normalText.empty())
1185                 {
1186                     m_text->appendStyledText(normalText, lastStyle);
1187                     normalText.clear();
1188                 }
1189                 bold = FALSE;
1190                 under = FALSE;
1191                 foreColor = preferences.m_colors.text;
1192                 backColor = preferences.m_colors.back;
1193                 lastStyle = stylenum;
1194             }
1195             else
1196             {
1197                 normalText.append(txt[i]);
1198             }
1199         }
1200         i++;
1201     }
1202     if(!normalText.empty())
1203     {
1204         m_text->appendStyledText(normalText, lastStyle);
1205     }
1206     m_text->appendText("\n");
1207 }
1208 
startLogging()1209 void IrcTabItem::startLogging()
1210 {
1211     if(m_logstream && FXStat::exists(preferences.m_logPath+PATHSEPSTRING+m_engine->getNetworkName()+PATHSEPSTRING+getText()+PATHSEPSTRING+FXSystem::time("%Y-%m-%d", FXSystem::now())))
1212         return;
1213     if(preferences.m_logging && m_type != SERVER)
1214     {
1215         if(!FXStat::exists(preferences.m_logPath+PATHSEPSTRING+m_engine->getNetworkName())) FXDir::create(preferences.m_logPath+PATHSEPSTRING+m_engine->getNetworkName());
1216         if(!FXStat::exists(preferences.m_logPath+PATHSEPSTRING+m_engine->getNetworkName()+PATHSEPSTRING+getText())) FXDir::create(preferences.m_logPath+PATHSEPSTRING+m_engine->getNetworkName()+PATHSEPSTRING+getText());
1217         m_logstream = new std::ofstream(FXString(preferences.m_logPath+PATHSEPSTRING+m_engine->getNetworkName()+PATHSEPSTRING+getText()+PATHSEPSTRING+FXSystem::time("%Y-%m-%d", FXSystem::now())).text(), std::ios::out|std::ios::app);
1218     }
1219 }
1220 
stopLogging()1221 void IrcTabItem::stopLogging()
1222 {
1223     if(m_logstream)
1224     {
1225         m_logstream->close();
1226         delete m_logstream;
1227         m_logstream = NULL;
1228     }
1229 }
1230 
logLine(const FXString & line,const FXTime & time)1231 void IrcTabItem::logLine(const FXString &line, const FXTime &time)
1232 {
1233     if(preferences.m_logging && m_type != SERVER)
1234     {
1235         this->startLogging();
1236         *m_logstream << FXSystem::time("[%H:%M:%S] ", time).text() << line.text() << std::endl;
1237     }
1238 }
1239 
isChannel(const FXString & text)1240 FXbool IrcTabItem::isChannel(const FXString &text)
1241 {
1242     if(text.length()) return m_engine->getChanTypes().contains(text[0]);
1243     return FALSE;
1244 }
1245 
onCommandline(FXObject *,FXSelector,void *)1246 long IrcTabItem::onCommandline(FXObject *, FXSelector, void *)
1247 {
1248     FXString commandtext = m_commandline->getText();
1249     if(commandtext.empty())
1250         return 1;
1251     m_commandsHistory.append(commandtext);
1252     if (m_commandsHistory.no() > m_historyMax)
1253         m_commandsHistory.erase(0);
1254     m_currentPosition = m_commandsHistory.no()-1;
1255     m_commandline->setText("");
1256     if(comparecase(commandtext.left(4),"/say") != 0)
1257         commandtext.substitute("^B", "\002").substitute("^C", "\003").substitute("^O", "\017").substitute("^V", "\026").substitute("^_", "\037");
1258     for(FXint i=0; i<=commandtext.contains('\n'); i++)
1259     {
1260         FXString text = commandtext.section('\n', i).before('\r');
1261         if(comparecase(text.after('/').before(' '), "quit") == 0 ||
1262                 comparecase(text.after('/').before(' '), "lua") == 0)
1263         {
1264             processLine(text);
1265             return 1;
1266         }
1267 #ifdef HAVE_LUA
1268         if(text[0] != '/') m_parent->getParent()->getParent()->handle(this, FXSEL(SEL_COMMAND, IrcTabItem_OWNMSG), &text);
1269         m_parent->getParent()->getParent()->handle(this, FXSEL(SEL_COMMAND, IrcTabItem_COMMAND), &text);
1270         if(text[0] == '/' && !m_scriptHasAll) processLine(text);
1271         else if(!m_scriptHasOwnMsg && !m_scriptHasAll) processLine(text);
1272 #else
1273         processLine(text);
1274 #endif
1275     }
1276     return 1;
1277 }
1278 
processLine(const FXString & commandtext)1279 FXbool IrcTabItem::processLine(const FXString& commandtext)
1280 {
1281     FXString command = (commandtext[0] == '/' ? commandtext.before(' ') : "");
1282     if(!dxUtils.getAlias(command).empty())
1283     {
1284         FXString acommand = dxUtils.getAlias(command);
1285         if(acommand.contains("%s"))
1286             acommand.substitute("%s", commandtext.after(' '));
1287         else
1288             acommand += commandtext.after(' ');
1289         FXint num = acommand.contains("&&");
1290         if(num)
1291         {
1292             FXbool result = FALSE;
1293             for(FXint i=0; i<=acommand.contains('&'); i++)
1294             {
1295                 if(!acommand.section('&',i).trim().empty()) result = processCommand(acommand.section('&',i).trim());
1296             }
1297             return result;
1298         }
1299         else
1300         {
1301             return processCommand(acommand);
1302         }
1303     }
1304     return processCommand(commandtext);
1305 }
1306 
processCommand(const FXString & commandtext)1307 FXbool IrcTabItem::processCommand(const FXString& commandtext)
1308 {
1309     FXString command = (commandtext[0] == '/' ? commandtext.after('/').before(' ').lower() : "");
1310     if(m_type == OTHER)
1311     {
1312         if(dxUtils.isScriptCommand(command))
1313         {
1314             return commandScript(commandtext);
1315         }
1316         if(command == "commands")
1317         {
1318             return commandCommands();
1319         }
1320         if(command == "egg")
1321         {
1322             return commandEgg();
1323         }
1324         if(command == "help")
1325         {
1326             return commandHelp(commandtext);
1327         }
1328         if(command == "tetris")
1329         {
1330             return commandTetris();
1331         }
1332         return TRUE;
1333     }
1334     if(commandtext[0] == '/')
1335     {
1336         if(dxUtils.isScriptCommand(command))
1337         {
1338             return commandScript(commandtext);
1339         }
1340         if(command == "admin")
1341         {
1342             return commandAdmin(commandtext);
1343         }
1344         if(command == "away")
1345         {
1346             return commandAway(commandtext);
1347         }
1348         if(command == "banlist")
1349         {
1350             return commandBanlist(commandtext);
1351         }
1352         if(command == "boats")
1353         {
1354             return commandBoats(commandtext);
1355         }
1356         if(command == "connect")
1357         {
1358             return commandConnect(commandtext);
1359         }
1360         if(command == "commands")
1361         {
1362             return commandCommands();
1363         }
1364         if(command == "ctcp")
1365         {
1366             return commandCtcp(commandtext);
1367         }
1368         if(command == "cycle")
1369         {
1370             return commandCycle(commandtext);
1371         }
1372         if(command == "dcc")
1373         {
1374             return commandDcc(commandtext);
1375         }
1376         if(command == "deop")
1377         {
1378             return commandDeop(commandtext);
1379         }
1380         if(command == "devoice")
1381         {
1382             return commandDevoice(commandtext);
1383         }
1384         if(command == "disconnect")
1385         {
1386             return commandDisconnect(commandtext);
1387         }
1388         if(command == "dxirc")
1389         {
1390             return commandDxirc();
1391         }
1392         if(command == "egg")
1393         {
1394             return commandEgg();
1395         }
1396         if(command == "exec")
1397         {
1398             return commandExec(commandtext);
1399         }
1400         if(command == "help")
1401         {
1402             return commandHelp(commandtext);
1403         }
1404         if(command == "ignore")
1405         {
1406             return commandIgnore(commandtext);
1407         }
1408         if(command == "invite")
1409         {
1410             return commandInvite(commandtext);
1411         }
1412         if(command == "join")
1413         {
1414             return commandJoin(commandtext);
1415         }
1416         if(command == "kick")
1417         {
1418             return commandKick(commandtext);
1419         }
1420         if(command == "kill")
1421         {
1422             return commandKill(commandtext);
1423         }
1424         if(command == "list")
1425         {
1426             return commandList(commandtext);
1427         }
1428         if(command == "log")
1429         {
1430             return commandLog(commandtext);
1431         }
1432         if(command == "lua")
1433         {
1434             return commandLua(commandtext);
1435         }
1436         if(command == "me")
1437         {
1438             return commandMe(commandtext);
1439         }
1440         if(command == "mode")
1441         {
1442             return commandMode(commandtext);
1443         }
1444         if(command == "msg")
1445         {
1446             return commandMsg(commandtext);
1447         }
1448         if(command == "names")
1449         {
1450             return commandNames(commandtext);
1451         }
1452         if(command == "nick")
1453         {
1454             return commandNick(commandtext);
1455         }
1456         if(command == "notice")
1457         {
1458             return commandNotice(commandtext);
1459         }
1460         if(command == "op")
1461         {
1462             return commandOp(commandtext);
1463         }
1464         if(command == "oper")
1465         {
1466             return commandOper(commandtext);
1467         }
1468         if(command == "part")
1469         {
1470             return commandPart(commandtext);
1471         }
1472         if(command == "query")
1473         {
1474             return commandQuery(commandtext);
1475         }
1476         if(command == "quit")
1477         {
1478             return commandQuit();
1479         }
1480         if(command == "quote")
1481         {
1482             return commandQuote(commandtext);
1483         }
1484         if(command == "say")
1485         {
1486             return commandSay(commandtext);
1487         }
1488         if(command == "stats")
1489         {
1490             return commandStats(commandtext);
1491         }
1492         if(command == "tetris")
1493         {
1494             return commandTetris();
1495         }
1496         if(command == "time")
1497         {
1498             return commandTime();
1499         }
1500         if(command == "topic")
1501         {
1502             return commandTopic(commandtext);
1503         }
1504         if(command == "voice")
1505         {
1506             return commandVoice(commandtext);
1507         }
1508         if(command == "wallops")
1509         {
1510             return commandWallops(commandtext);
1511         }
1512         if(command == "who")
1513         {
1514             return commandWho(commandtext);
1515         }
1516         if(command == "whoami")
1517         {
1518             return commandWhoami();
1519         }
1520         if(command == "whois")
1521         {
1522             return commandWhois(commandtext);
1523         }
1524         if(command == "whowas")
1525         {
1526             return commandWhowas(commandtext);
1527         }
1528         appendIrcStyledText(FXStringFormat(_("Unknown command '%s', type /commands for available commands"), command.text()), 4, FXSystem::now(), FALSE, FALSE);
1529         return FALSE;
1530     }
1531     else
1532     {
1533         if(command.empty() && m_type != SERVER && !commandtext.empty() && m_engine->getConnected())
1534         {
1535             if(commandtext.length() > m_maxLen-10-getText().length())
1536             {
1537                 dxStringArray messages = cutText(commandtext, m_maxLen-10-getText().length());
1538                 FXbool result = TRUE;
1539                 for(FXint i=0; i<messages.no(); i++)
1540                 {
1541                     appendMyMsg(messages[i], FXSystem::now());
1542                     IrcEvent ev;
1543                     ev.eventType = IRC_PRIVMSG;
1544                     ev.param1 = getNickName();
1545                     ev.param2 = getText();
1546                     ev.param3 = messages[i];
1547                     m_parent->getParent()->getParent()->handle(m_engine, FXSEL(SEL_COMMAND, IrcEngine_SERVER), &ev);
1548                     result = m_engine->sendMsg(getText(), messages[i]) &result;
1549                 }
1550                 return result;
1551             }
1552             else
1553             {
1554                 appendMyMsg(commandtext, FXSystem::now());
1555                 IrcEvent ev;
1556                 ev.eventType = IRC_PRIVMSG;
1557                 ev.param1 = getNickName();
1558                 ev.param2 = getText();
1559                 ev.param3 = commandtext;
1560                 m_parent->getParent()->getParent()->handle(m_engine, FXSEL(SEL_COMMAND, IrcEngine_SERVER), &ev);
1561                 return m_engine->sendMsg(getText(), commandtext);
1562             }
1563         }
1564         if(!m_engine->getConnected())
1565         {
1566             appendIrcStyledText(_("You aren't connected"), 4, FXSystem::now(), FALSE, FALSE);
1567             m_parent->getParent()->getParent()->handle(this, FXSEL(SEL_COMMAND, IrcTabItem_CDIALOG), NULL);
1568             return TRUE;
1569         }
1570         return FALSE;
1571     }
1572     return FALSE;
1573 }
1574 
showHelp(FXString command)1575 FXbool IrcTabItem::showHelp(FXString command)
1576 {
1577     if(dxUtils.isScriptCommand(command))
1578     {
1579         appendIrcStyledText(dxUtils.getHelpText(command), 3, FXSystem::now(), FALSE, FALSE);
1580         return TRUE;
1581     }
1582     if(command == "admin")
1583     {
1584         appendIrcStyledText(_("ADMIN [server], finds information about administrator for current server or [server]."), 3, FXSystem::now(), FALSE, FALSE);
1585         return TRUE;
1586     }
1587     if(command == "away")
1588     {
1589         appendIrcStyledText(_("AWAY [message], sets away status."), 3, FXSystem::now(), FALSE, FALSE);
1590         return TRUE;
1591     }
1592     if(command == "banlist")
1593     {
1594         appendIrcStyledText(_("BANLIST <channel>, shows banlist for channel."), 3, FXSystem::now(), FALSE, FALSE);
1595         return TRUE;
1596     }
1597     if(command == "boats")
1598     {
1599         appendIrcStyledText(_("BOATS <nick>, invites someone to a boats game."), 3, FXSystem::now(), FALSE, FALSE);
1600         return TRUE;
1601     }
1602     if(command == "commands")
1603     {
1604         appendIrcStyledText(_("COMMANDS, shows available commands"), 3, FXSystem::now(), FALSE, FALSE);
1605         return TRUE;
1606     }
1607     if(command == "connect")
1608     {
1609         appendIrcStyledText(_("CONNECT <server> [port] [nick] [password] [realname] [channels], connects for given server."), 3, FXSystem::now(), FALSE, FALSE);
1610         return TRUE;
1611     }
1612     if(command == "ctcp")
1613     {
1614         appendIrcStyledText(_("CTCP <nick> <message>, sends a CTCP message to a user."), 3, FXSystem::now(), FALSE, FALSE);
1615         return TRUE;
1616     }
1617     if(command == "cycle")
1618     {
1619         appendIrcStyledText(_("CYCLE <channel> [message], leaves and join channel."), 3, FXSystem::now(), FALSE, FALSE);
1620         return TRUE;
1621     }
1622     if(command == "dcc")
1623     {
1624         appendIrcStyledText(_("DCC chat <nick>, starts DCC chat."), 3, FXSystem::now(), FALSE, FALSE);
1625         appendIrcStyledText(_("DCC send <nick> <filename>, sends file over DCC."), 3, FXSystem::now(), FALSE, FALSE);
1626         appendIrcStyledText(_("DCC psend <nick> <filename>, sends file passive over DCC."), 3, FXSystem::now(), FALSE, FALSE);
1627         appendIrcStyledText(_("More information about passive DCC on http://en.wikipedia.org/wiki/Direct_Client-to-Client#Passive_DCC"), 3, FXSystem::now(), FALSE, FALSE);
1628         return TRUE;
1629     }
1630     if(command == "deop")
1631     {
1632         appendIrcStyledText(_("DEOP <channel> <nicks>, removes operator status from one or more nicks."), 3, FXSystem::now(), FALSE, FALSE);
1633         return TRUE;
1634     }
1635     if(command == "devoice")
1636     {
1637         appendIrcStyledText(_("DEVOICE <channel> <nicks>, removes voice from one or more nicks."), 3, FXSystem::now(), FALSE, FALSE);
1638         return TRUE;
1639     }
1640     if(command == "disconnect")
1641     {
1642         appendIrcStyledText(_("DISCONNECT [reason], leaves server."), 3, FXSystem::now(), FALSE, FALSE);
1643         return TRUE;
1644     }
1645 #ifndef WIN32
1646     if(command == "exec")
1647     {
1648         appendIrcStyledText(_("EXEC [-o|-c] <command>, executes command, -o sends output to channel/query, -c closes running command."), 3, FXSystem::now(), FALSE, FALSE);
1649         return TRUE;
1650     }
1651 #endif
1652     if(command == "help")
1653     {
1654         appendIrcStyledText(_("HELP <command>, shows help for command."), 3, FXSystem::now(), FALSE, FALSE);
1655         return TRUE;
1656     }
1657     if(command == "ignore")
1658     {
1659         appendIrcStyledText(_("IGNORE list, shows list ignored commands and users."), 3, FXSystem::now(), FALSE, FALSE);
1660         appendIrcStyledText(_("IGNORE addcmd <command>, adds command to ignored commands."), 3, FXSystem::now(), FALSE, FALSE);
1661         appendIrcStyledText(_("IGNORE rmcmd <command>, removes command from ignored commands."), 3, FXSystem::now(), FALSE, FALSE);
1662         appendIrcStyledText(_("IGNORE addusr <user> [channel] [server], adds user to ignored users."), 3, FXSystem::now(), FALSE, FALSE);
1663         appendIrcStyledText(_("IGNORE rmusr <user>, removes user from ignored users."), 3, FXSystem::now(), FALSE, FALSE);
1664         return TRUE;
1665     }
1666     if(command == "invite")
1667     {
1668         appendIrcStyledText(_("INVITE <nick> <channel>, invites someone to a channel."), 3, FXSystem::now(), FALSE, FALSE);
1669         return TRUE;
1670     }
1671     if(command == "join")
1672     {
1673         appendIrcStyledText(_("JOIN <channel>, joins a channel."), 3, FXSystem::now(), FALSE, FALSE);
1674         return TRUE;
1675     }
1676     if(command == "kick")
1677     {
1678         appendIrcStyledText(_("KICK <channel> <nick>, kicks a user from a channel."), 3, FXSystem::now(), FALSE, FALSE);
1679         return TRUE;
1680     }
1681     if(command == "kill")
1682     {
1683         appendIrcStyledText(_("KILL <user> [reason], kills a user from the network."), 3, FXSystem::now(), FALSE, FALSE);
1684         return TRUE;
1685     }
1686     if(command == "list")
1687     {
1688         appendIrcStyledText(_("LIST [channel], lists channels and their topics."), 3, FXSystem::now(), FALSE, FALSE);
1689         return TRUE;
1690     }
1691     if(command == "log")
1692     {
1693         appendIrcStyledText(_("LOG list, shows list of log files for current tab"), 3, FXSystem::now(), FALSE, FALSE);
1694         appendIrcStyledText(_("LOG show [date], shows last log file for current tab, if date is empty"), 3, FXSystem::now(), FALSE, FALSE);
1695         appendIrcStyledText(_("else file for given date"), 3, FXSystem::now(), FALSE, FALSE);
1696         appendIrcStyledText(_("date example: 2011-01-31"), 3, FXSystem::now(), FALSE, FALSE);
1697         return TRUE;
1698     }
1699 #ifdef HAVE_LUA
1700     if(command == "lua")
1701     {
1702         appendIrcStyledText(_("LUA help, shows help for lua scripting."), 3, FXSystem::now(), FALSE, FALSE);
1703         appendIrcStyledText(_("LUA load <path>, loads script."), 3, FXSystem::now(), FALSE, FALSE);
1704         appendIrcStyledText(_("Example: /lua load /home/dvx/test.lua"), 3, FXSystem::now(), FALSE, FALSE);
1705         appendIrcStyledText(_("LUA unload <name>, unloads script."), 3, FXSystem::now(), FALSE, FALSE);
1706         appendIrcStyledText(_("Example: /lua unload test"), 3, FXSystem::now(), FALSE, FALSE);
1707         appendIrcStyledText(_("LUA list, shows list of loaded scripts"), 3, FXSystem::now(), FALSE, FALSE);
1708         return TRUE;
1709     }
1710 #else
1711     if(command == "lua")
1712     {
1713         appendIrcStyledText(_("dxirc is compiled without support for Lua scripting"), 4, FXSystem::now(), FALSE, FALSE);
1714         return TRUE;
1715     }
1716 #endif
1717     if(command == "me")
1718     {
1719         appendIrcStyledText(_("ME <to> <message>, sends the action."), 3, FXSystem::now(), FALSE, FALSE);
1720         return TRUE;
1721     }
1722     if(command == "mode")
1723     {
1724         appendIrcStyledText(_("MODE <channel> <modes>, sets modes for a channel."), 3, FXSystem::now(), FALSE, FALSE);
1725         return TRUE;
1726     }
1727     if(command == "msg")
1728     {
1729         appendIrcStyledText(_("MSG <nick/channel> <message>, sends a normal message."), 3, FXSystem::now(), FALSE, FALSE);
1730         return TRUE;
1731     }
1732     if(command == "names")
1733     {
1734         appendIrcStyledText(_("NAMES <channel>, for nicks on a channel."), 3, FXSystem::now(), FALSE, FALSE);
1735         return TRUE;
1736     }
1737     if(command == "nick")
1738     {
1739         appendIrcStyledText(_("NICK <nick>, changes nick."), 3, FXSystem::now(), FALSE, FALSE);
1740         return TRUE;
1741     }
1742     if(command == "notice")
1743     {
1744         appendIrcStyledText(_("NOTICE <nick/channel> <message>, sends a notice."), 3, FXSystem::now(), FALSE, FALSE);
1745         return TRUE;
1746     }
1747     if(command == "op")
1748     {
1749         appendIrcStyledText(_("OP <channel> <nicks>, gives operator status for one or more nicks."), 3, FXSystem::now(), FALSE, FALSE);
1750         return TRUE;
1751     }
1752     if(command == "oper")
1753     {
1754         appendIrcStyledText(_("OPER <login> <password>, oper up."), 3, FXSystem::now(), FALSE, FALSE);
1755         return TRUE;
1756     }
1757     if(command == "part")
1758     {
1759         appendIrcStyledText(_("PART <channel> [reason], leaves channel."), 3, FXSystem::now(), FALSE, FALSE);
1760         return TRUE;
1761     }
1762     if(command == "query")
1763     {
1764         appendIrcStyledText(_("QUERY <nick>, opens query with nick."), 3, FXSystem::now(), FALSE, FALSE);
1765         return TRUE;
1766     }
1767     if(command == "quit")
1768     {
1769         appendIrcStyledText(_("QUIT, closes application."), 3, FXSystem::now(), FALSE, FALSE);
1770         return TRUE;
1771     }
1772     if(command == "quote")
1773     {
1774         appendIrcStyledText(_("QUOTE [text], sends text to server."), 3, FXSystem::now(), FALSE, FALSE);
1775         return TRUE;
1776     }
1777     if(command == "say")
1778     {
1779         appendIrcStyledText(_("SAY [text], sends text to current tab."), 3, FXSystem::now(), FALSE, FALSE);
1780         return TRUE;
1781     }
1782     if(command == "stats")
1783     {
1784         appendIrcStyledText(_("STATS <type>, shows some irc server usage statistics. Available types vary slightly per server; some common ones are:"), 3, FXSystem::now(), FALSE, FALSE);
1785         appendIrcStyledText(_("c - shows C and N lines for a given server.  These are the names of the servers that are allowed to connect."), 3, FXSystem::now(), FALSE, FALSE);
1786         appendIrcStyledText(_("h - shows H and L lines for a given server (Hubs and Leaves)."), 3, FXSystem::now(), FALSE, FALSE);
1787         appendIrcStyledText(_("k - show K lines for a server.  This shows who is not allowed to connect and possibly at what time they are not allowed to connect."), 3, FXSystem::now(), FALSE, FALSE);
1788         appendIrcStyledText(_("i - shows I lines. This is who CAN connect to a server."), 3, FXSystem::now(), FALSE, FALSE);
1789         appendIrcStyledText(_("l - shows information about amount of information passed to servers and users."), 3, FXSystem::now(), FALSE, FALSE);
1790         appendIrcStyledText(_("m - shows a count for the number of times the various commands have been used since the server was booted."), 3, FXSystem::now(), FALSE, FALSE);
1791         appendIrcStyledText(_("o - shows the list of authorized operators on the server."), 3, FXSystem::now(), FALSE, FALSE);
1792         appendIrcStyledText(_("p - shows online operators and their idle times."), 3, FXSystem::now(), FALSE, FALSE);
1793         appendIrcStyledText(_("u - shows the uptime for a server."), 3, FXSystem::now(), FALSE, FALSE);
1794         appendIrcStyledText(_("y - shows Y lines, which lists the various connection classes for a given server."), 3, FXSystem::now(), FALSE, FALSE);
1795 
1796         return TRUE;
1797     }
1798     if(command == "tetris")
1799     {
1800         appendIrcStyledText(_("TETRIS, start small easteregg."), 3, FXSystem::now(), FALSE, FALSE);
1801         appendIrcStyledText(_("Keys for playing:"), 3, FXSystem::now(), FALSE, FALSE);
1802         appendIrcStyledText(_("n .. new game"), 3, FXSystem::now(), FALSE, FALSE);
1803         appendIrcStyledText(_("p .. pause game"), 3, FXSystem::now(), FALSE, FALSE);
1804         appendIrcStyledText(_("i .. rotate piece"), 3, FXSystem::now(), FALSE, FALSE);
1805         appendIrcStyledText(_("l .. move piece right"), 3, FXSystem::now(), FALSE, FALSE);
1806         appendIrcStyledText(_("k .. drop piece"), 3, FXSystem::now(), FALSE, FALSE);
1807         appendIrcStyledText(_("j .. move piece left"), 3, FXSystem::now(), FALSE, FALSE);
1808         return TRUE;
1809     }
1810     if(command == "time")
1811     {
1812         appendIrcStyledText(_("TIME, displays the time of day, local to server."), 3, FXSystem::now(), FALSE, FALSE);
1813         return TRUE;
1814     }
1815     if(command == "topic")
1816     {
1817         appendIrcStyledText(_("TOPIC [topic], sets or shows topic."), 3, FXSystem::now(), FALSE, FALSE);
1818         return TRUE;
1819     }
1820     if(command == "voice")
1821     {
1822         appendIrcStyledText(_("VOICE <channel> <nicks>, gives voice for one or more nicks."), 3, FXSystem::now(), FALSE, FALSE);
1823         return TRUE;
1824     }
1825     if(command == "wallops")
1826     {
1827         appendIrcStyledText(_("WALLOPS <message>, sends wallop message."), 3, FXSystem::now(), FALSE, FALSE);
1828         return TRUE;
1829     }
1830     if(command == "who")
1831     {
1832         appendIrcStyledText(_("WHO <mask> [o], searchs for mask on network, if o is supplied, only search for opers."), 3, FXSystem::now(), FALSE, FALSE);
1833         return TRUE;
1834     }
1835     if(command == "whoami")
1836     {
1837         appendIrcStyledText(_("WHOAMI, whois about you."), 3, FXSystem::now(), FALSE, FALSE);
1838         return TRUE;
1839     }
1840     if(command == "whois")
1841     {
1842         appendIrcStyledText(_("WHOIS <nick>, whois nick."), 3, FXSystem::now(), FALSE, FALSE);
1843         return TRUE;
1844     }
1845     if(command == "whowas")
1846     {
1847         appendIrcStyledText(_("WHOWAS <nick>, whowas nick."), 3, FXSystem::now(), FALSE, FALSE);
1848         return TRUE;
1849     }
1850     if(!dxUtils.getAlias(command[0] == '/' ? command:"/"+command).empty())
1851     {
1852         appendIrcStyledText(FXStringFormat("%s: %s", command.upper().text(), dxUtils.getAlias(command[0] == '/' ? command:"/"+command).text()), 3, FXSystem::now(), FALSE, FALSE);
1853         return TRUE;
1854     }
1855     if(command.empty()) appendIrcStyledText(_("Command is empty, type /commands for available commands"), 4, FXSystem::now(), FALSE, FALSE);
1856     else appendIrcStyledText(FXStringFormat(_("Unknown command '%s', type /commands for available commands"), command.text()), 4, FXSystem::now(), FALSE, FALSE);
1857     return FALSE;
1858 }
1859 
onKeyPress(FXObject *,FXSelector,void * ptr)1860 long IrcTabItem::onKeyPress(FXObject *, FXSelector, void *ptr)
1861 {
1862     if(m_commandline->hasFocus())
1863     {
1864         FXString line = m_commandline->getText();
1865         FXString key = dxutils::getKeybinding((FXEvent*)ptr);
1866         if(comparecase(key, "Tab")==0) //tab completion
1867         {
1868             if(comparecase(line.before(' '), "/help") == 0 && !line.after(' ').empty())
1869             {
1870                 completeHelpCommand();
1871                 return 1;
1872             }
1873             if(line[0] == '/' && line.after(' ').empty())
1874             {
1875                 for(FXint i = 0; i < dxUtils.commandsNo(); i++)
1876                 {
1877                     if(comparecase(line.after('/').before(' '), dxUtils.commandsAt(i)) == 0)
1878                     {
1879                         if((i+1) < dxUtils.commandsNo()) m_commandline->setText("/"+dxUtils.commandsAt(++i)+" ");
1880                         else m_commandline->setText("/"+dxUtils.commandsAt(0)+" ");
1881                         break;
1882                     }
1883                     else if(comparecase(line.after('/'), dxUtils.commandsAt(i).left(line.after('/').length())) == 0)
1884                     {
1885                         m_commandline->setText("/"+dxUtils.commandsAt(i)+" ");
1886                         break;
1887                     }
1888                 }
1889                 return 1;
1890             }
1891             if(line[0] != '/' && line.after(' ').empty() && m_type == CHANNEL)
1892             {
1893                 if(line.empty())
1894                 {
1895                     m_commandline->setText(getNick(0)+preferences.m_nickCompletionChar+" ");
1896                     return 1;
1897                 }
1898                 for(FXint j = 0; j < m_users->getNumItems() ; j++)
1899                 {
1900                     if(comparecase(line, getNick(j).left(line.length())) == 0)
1901                     {
1902                         m_commandline->setText(getNick(j)+preferences.m_nickCompletionChar+" ");
1903                         break;
1904                     }
1905                     else if(comparecase(line.section(preferences.m_nickCompletionChar, 0, 1), getNick(j)) == 0)
1906                     {
1907                         if((j+1) < m_users->getNumItems()) m_commandline->setText(getNick(++j)+preferences.m_nickCompletionChar+" ");
1908                         else m_commandline->setText(getNick(0)+preferences.m_nickCompletionChar+" ");
1909                         break;
1910                     }
1911                 }
1912                 return 1;
1913             }
1914             if(line.find(' ') != -1 && m_type == CHANNEL)
1915             {
1916                 FXint curpos;
1917                 line[m_commandline->getCursorPos()] == ' ' ? curpos = m_commandline->getCursorPos()-1 : curpos = m_commandline->getCursorPos();
1918                 FXint pos = line.rfind(' ', curpos)+1;
1919                 FXint n = line.find(' ', curpos)>0 ? line.find(' ', curpos)-pos : line.length()-pos;
1920                 FXString toCompletion = line.mid(pos, n);
1921                 for(FXint j = 0; j < m_users->getNumItems(); j++)
1922                 {
1923                     if(comparecase(toCompletion, getNick(j)) == 0)
1924                     {
1925                         if((j+1) < m_users->getNumItems())
1926                         {
1927                             m_commandline->setText(line.replace(pos, n, getNick(j+1)));
1928                             m_commandline->setCursorPos(pos+getNick(j+1).length());
1929                         }
1930                         else
1931                         {
1932                             m_commandline->setText(line.replace(pos, n, getNick(0)));
1933                             m_commandline->setCursorPos(pos+getNick(0).length());
1934                         }
1935                         break;
1936                     }
1937                     else if(comparecase(toCompletion, getNick(j).left(toCompletion.length())) == 0)
1938                     {
1939                         m_commandline->setText(line.replace(pos, n, getNick(j)));
1940                         m_commandline->setCursorPos(pos+getNick(j).length());
1941                         break;
1942                     }
1943                 }
1944                 return 1;
1945             }
1946             return 1;
1947         }
1948         else if(comparecase(key, "Up")==0) //append history command backward
1949         {
1950             if(m_currentPosition!=-1 && m_currentPosition<m_commandsHistory.no())
1951             {
1952                 if(!line.empty() && line!=m_commandsHistory[m_currentPosition])
1953                 {
1954                     m_commandsHistory.append(line);
1955                     if(m_commandsHistory.no() > m_historyMax)
1956                         m_commandsHistory.erase(0);
1957                     m_currentPosition = m_commandsHistory.no()-1;
1958                 }
1959                 if(m_currentPosition > 0 && !line.empty())
1960                     --m_currentPosition;
1961                 m_commandline->setText(m_commandsHistory[m_currentPosition]);
1962             }
1963             return 1;
1964         }
1965         else if(comparecase(key, "Down")==0) //append history command forward
1966         {
1967             if(m_currentPosition!=-1 && m_currentPosition<m_commandsHistory.no())
1968             {
1969                 if(!line.empty() && line!=m_commandsHistory[m_currentPosition])
1970                 {
1971                     m_commandsHistory.append(line);
1972                     if(m_commandsHistory.no() > m_historyMax)
1973                         m_commandsHistory.erase(0);
1974                     m_currentPosition = m_commandsHistory.no()-1;
1975                 }
1976                 if(m_currentPosition < m_commandsHistory.no()-1)
1977                 {
1978                     ++m_currentPosition;
1979                     m_commandline->setText(m_commandsHistory[m_currentPosition]);
1980                 }
1981                 else
1982                     m_commandline->setText("");
1983             }
1984             return 1;
1985         }
1986         else if(comparecase(key, preferences.getBinding("colorControlChar"))==0) //color control char
1987         {
1988             FXint pos = m_commandline->getCursorPos();
1989             m_commandline->setText(line.insert(pos, "^C")); //color
1990             m_commandline->setCursorPos(pos+2);
1991             return 1;
1992         }
1993         else if(comparecase(key, preferences.getBinding("boldControlChar"))==0) //bold control char
1994         {
1995             FXint pos = m_commandline->getCursorPos();
1996             m_commandline->setText(line.insert(pos, "^B")); //bold
1997             m_commandline->setCursorPos(pos+2);
1998             return 1;
1999         }
2000         else if(comparecase(key, preferences.getBinding("underlineControlChar"))==0) //underline control char
2001         {
2002             FXint pos = m_commandline->getCursorPos();
2003             m_commandline->setText(line.insert(pos, "^_")); //underline
2004             m_commandline->setCursorPos(pos+2);
2005             return 1;
2006         }
2007         else if(comparecase(key, preferences.getBinding("reverseControlChar"))==0) //reverse control char
2008         {
2009             FXint pos = m_commandline->getCursorPos();
2010             m_commandline->setText(line.insert(pos, "^V")); //reverse
2011             m_commandline->setCursorPos(pos+2);
2012             return 1;
2013         }
2014         else if(comparecase(key, preferences.getBinding("resetControlChar"))==0) //reset control char
2015         {
2016             FXint pos = m_commandline->getCursorPos();
2017             m_commandline->setText(line.insert(m_commandline->getCursorPos(), "^O")); //reset
2018             m_commandline->setCursorPos(pos+2);
2019             return 1;
2020         }
2021     }
2022     return 0;
2023 }
2024 
2025 //Check is this tab right for server message (e.g. not for IRC_SERVERREPLY)
isRightForServerMsg()2026 FXbool IrcTabItem::isRightForServerMsg()
2027 {
2028     //Check if current tab is in server targets
2029     if(m_engine->findTarget(m_parent->childAtIndex(m_parent->getCurrent()*2)))
2030     {
2031         return m_parent->indexOfChild(this) == m_parent->getCurrent()*2;
2032     }
2033     else
2034     {
2035         FXint indexOfThis = m_parent->indexOfChild(this);
2036         for(FXint i = 0; i<m_parent->numChildren(); i+=2)
2037         {
2038             if(m_engine->findTarget(m_parent->childAtIndex(i)))
2039             {
2040                 if(i == indexOfThis) return TRUE;
2041                 else return FALSE;
2042             }
2043         }
2044     }
2045     return FALSE;
2046 }
2047 
isCommandIgnored(const FXString & command)2048 FXbool IrcTabItem::isCommandIgnored(const FXString &command)
2049 {
2050     if(preferences.m_ignoreCommandsList.contains(command)) return TRUE;
2051     return FALSE;
2052 }
2053 
addUser(const FXString & user,UserMode mode)2054 void IrcTabItem::addUser(const FXString& user, UserMode mode)
2055 {
2056     if(mode == ADMIN && m_users->findItem(user) == -1)
2057     {
2058         NickListItem *item = new NickListItem(user, m_users, mode, m_useNickIcon?ICO_IRCADMIN:NULL);
2059         m_users->appendItem(item);
2060         m_numberUsers++;
2061         m_users->sortItems();
2062         return;
2063     }
2064     if(mode == OWNER && m_users->findItem(user) == -1)
2065     {
2066         NickListItem *item = new NickListItem(user, m_users, mode, m_useNickIcon?ICO_IRCOWNER:NULL);
2067         m_users->appendItem(item);
2068         m_numberUsers++;
2069         m_users->sortItems();
2070         return;
2071     }
2072     if(mode == OP && m_users->findItem(user) == -1)
2073     {
2074         NickListItem *item = new NickListItem(user, m_users, mode, m_useNickIcon?ICO_IRCOP:NULL);
2075         m_users->appendItem(item);
2076         m_numberUsers++;
2077         m_users->sortItems();
2078         return;
2079     }
2080     if(mode == VOICE && m_users->findItem(user) == -1)
2081     {
2082         NickListItem *item = new NickListItem(user, m_users, mode, m_useNickIcon?ICO_IRCVOICE:NULL);
2083         m_users->appendItem(item);
2084         m_numberUsers++;
2085         m_users->sortItems();
2086         return;
2087     }
2088     if(mode == HALFOP && m_users->findItem(user) == -1)
2089     {
2090         NickListItem *item = new NickListItem(user, m_users, mode, m_useNickIcon?ICO_IRCHALFOP:NULL);
2091         m_users->appendItem(item);
2092         m_numberUsers++;
2093         m_users->sortItems();
2094         return;
2095     }
2096     if(mode == NONE && m_users->findItem(user) == -1)
2097     {
2098         NickListItem *item = new NickListItem(user, m_users, mode, m_useNickIcon?ICO_IRCNORMAL:NULL);
2099         m_users->appendItem(item);
2100         m_numberUsers++;
2101         m_users->sortItems();
2102         return;
2103     }
2104 }
2105 
removeUser(const FXString & user)2106 void IrcTabItem::removeUser(const FXString& user)
2107 {
2108     if(m_users->findItem(user) != -1)
2109     {
2110         m_users->removeItem(m_users->findItem(user));
2111     }
2112     m_numberUsers--;
2113     m_users->sortItems();
2114 }
2115 
changeNickUser(const FXString & nick,const FXString & newnick)2116 void IrcTabItem::changeNickUser(const FXString& nick, const FXString& newnick)
2117 {
2118     FXint i = m_users->findItem(nick);
2119     if(i != -1)
2120     {
2121         m_users->recalc();
2122         m_users->getItem(i)->setText(newnick);
2123         m_users->sortItems();
2124     }
2125 }
2126 
setUserMode(const FXString & nick,UserMode mode)2127 void IrcTabItem::setUserMode(const FXString& nick, UserMode mode)
2128 {
2129     FXint i = m_users->findItem(nick);
2130     if(i != -1)
2131     {
2132         ((NickListItem*)m_users->getItem(i))->setUserMode(mode);
2133     }
2134 }
2135 
getUserMode(const FXchar mode)2136 UserMode IrcTabItem::getUserMode(const FXchar mode)
2137 {
2138     if(mode == m_engine->getAdminPrefix())
2139         return ADMIN;
2140     if(mode == m_engine->getOwnerPrefix())
2141         return OWNER;
2142     if(mode == m_engine->getOpPrefix())
2143         return OP;
2144     if(mode == m_engine->getHalfopPrefix())
2145         return HALFOP;
2146     if(mode == m_engine->getVoicePrefix())
2147         return VOICE;
2148     return NONE;
2149 }
2150 
2151 //Clear theme icons, usefull for nick icon theme change
clearNickIcons()2152 void IrcTabItem::clearNickIcons()
2153 {
2154     for(FXint i=0; i<m_users->getNumItems(); i++)
2155     {
2156         ((NickListItem*)m_users->getItem(i))->clearIcon();
2157     }
2158 }
2159 
2160 //Apply new theme icon, usefull for nick icon theme change
recreateNickIcons(FXbool useNickIcon)2161 void IrcTabItem::recreateNickIcons(FXbool useNickIcon)
2162 {
2163     m_useNickIcon = useNickIcon;
2164     if(m_useNickIcon)
2165     {
2166         for(FXint i=0; i<m_users->getNumItems(); i++)
2167         {
2168             ((NickListItem*)m_users->getItem(i))->restoreIcon();
2169         }
2170     }
2171 }
2172 
2173 //return names
getNicks()2174 dxStringArray IrcTabItem::getNicks()
2175 {
2176     dxStringArray names;
2177     for(FXint i=0; i<m_users->getNumItems(); i++)
2178         names.append(m_users->getItemText(i));
2179     return names;
2180 }
2181 
hasNick(const FXString & nick)2182 FXbool IrcTabItem::hasNick(const FXString& nick)
2183 {
2184     return m_users->findItem(nick) != -1;
2185 }
2186 
onIrcEvent(FXObject *,FXSelector,void * data)2187 long IrcTabItem::onIrcEvent(FXObject *, FXSelector, void *data)
2188 {
2189     IrcEvent ev = *(IrcEvent *)data;
2190     if(m_loadLog)
2191     {
2192         m_storedEvents.append(ev);
2193         return 1;
2194     }
2195     parseIrcEvent(ev);
2196     return 1;
2197 }
2198 
parseIrcEvent(IrcEvent & ev)2199 void IrcTabItem::parseIrcEvent(IrcEvent &ev)
2200 {
2201     if(ev.eventType == IRC_PRIVMSG)
2202     {
2203         onIrcPrivmsg(ev);
2204     }
2205     else if(ev.eventType == IRC_ACTION)
2206     {
2207         onIrcAction(ev);
2208     }
2209     else if(ev.eventType == IRC_CTCPREPLY)
2210     {
2211         onIrcCtpcReply(ev);
2212     }
2213     else if(ev.eventType == IRC_CTCPREQUEST)
2214     {
2215         onIrcCtcpRequest(ev);
2216     }
2217     else if(ev.eventType == IRC_JOIN)
2218     {
2219         onIrcJoin(ev);
2220     }
2221     else if(ev.eventType == IRC_QUIT)
2222     {
2223         onIrcQuit(ev);
2224     }
2225     else if(ev.eventType == IRC_PART)
2226     {
2227         onIrcPart(ev);
2228     }
2229     else if(ev.eventType == IRC_CHNOTICE)
2230     {
2231         onIrcChnotice(ev);
2232     }
2233     else if(ev.eventType == IRC_NOTICE)
2234     {
2235         onIrcNotice(ev);
2236     }
2237     else if(ev.eventType == IRC_NICK)
2238     {
2239         onIrcNick(ev);
2240     }
2241     else if(ev.eventType == IRC_TOPIC)
2242     {
2243         onIrcTopic(ev);
2244     }
2245     else if(ev.eventType == IRC_KICK)
2246     {
2247         onIrcKick(ev);
2248     }
2249     else if(ev.eventType == IRC_MODE)
2250     {
2251         onIrcMode(ev);
2252     }
2253     else if(ev.eventType == IRC_UMODE)
2254     {
2255         onIrcUmode(ev);
2256     }
2257     else if(ev.eventType == IRC_CHMODE)
2258     {
2259         onIrcChmode(ev);
2260     }
2261     else if(ev.eventType == IRC_SERVERREPLY)
2262     {
2263         onIrcServerReply(ev);
2264     }
2265     else if(ev.eventType == IRC_CONNECT)
2266     {
2267         onIrcConnect(ev);
2268     }
2269     else if(ev.eventType == IRC_ERROR)
2270     {
2271         onIrcError(ev);
2272     }
2273     else if(ev.eventType == IRC_SERVERERROR)
2274     {
2275         onIrcServerError(ev);
2276     }
2277     else if(ev.eventType == IRC_DISCONNECT)
2278     {
2279         onIrcDisconnect(ev);
2280     }
2281     else if(ev.eventType == IRC_RECONNECT)
2282     {
2283         onIrcReconnect(ev);
2284     }
2285     else if(ev.eventType == IRC_RECONNECTALL)
2286     {
2287         onIrcReconnectAll(ev);
2288     }
2289     else if(ev.eventType == IRC_UNKNOWN)
2290     {
2291         onIrcUnknown(ev);
2292     }
2293     else if(ev.eventType == IRC_301)
2294     {
2295         onIrc301(ev);
2296     }
2297     else if(ev.eventType == IRC_305)
2298     {
2299         onIrc305(ev);
2300     }
2301     else if(ev.eventType == IRC_306)
2302     {
2303         onIrc306(ev);
2304     }
2305     else if(ev.eventType == IRC_331 || ev.eventType == IRC_332 || ev.eventType == IRC_333)
2306     {
2307         onIrc331332333(ev);
2308     }
2309     else if(ev.eventType == IRC_353)
2310     {
2311         onIrc353(ev);
2312     }
2313     else if(ev.eventType == IRC_366)
2314     {
2315         onIrc366(ev);
2316     }
2317     else if(ev.eventType == IRC_372)
2318     {
2319         onIrc372(ev);
2320     }
2321     else if(ev.eventType == IRC_AWAY)
2322     {
2323         onIrcAway(ev);
2324     }
2325     else if(ev.eventType == IRC_ENDMOTD)
2326     {
2327         onIrcEndMotd();
2328     }
2329 }
2330 
2331 //handle IrcEvent IRC_PRIVMSG
onIrcPrivmsg(IrcEvent & ev)2332 void IrcTabItem::onIrcPrivmsg(IrcEvent &ev)
2333 {
2334     if((comparecase(ev.param2, getText()) == 0 && m_type == CHANNEL) || (ev.param1 == getText() && m_type == QUERY && ev.param2 == getNickName()))
2335     {
2336         FXbool needHighlight = FALSE;
2337         if(ev.param3.contains(getNickName()))
2338             needHighlight = highlightNeeded(ev.param3);
2339         if(needHighlight) appendIrcStyledText(ev.param1+": "+ev.param3, 8, ev.time);
2340         else appendIrcNickText(ev.param1, ev.param3, getNickStyle(ev.param1), ev.time);
2341         if(preferences.m_highlightColor != this->getTextColor() && m_parent->getCurrent()*2 != m_parent->indexOfChild(this))
2342         {
2343             if(needHighlight)
2344             {
2345                 this->setTextColor(preferences.m_highlightColor);
2346                 if(m_type == CHANNEL) this->setIcon(ICO_CHANNELNEWMSG);
2347             }
2348             else this->setTextColor(preferences.m_unreadColor);
2349             if(m_type == QUERY) this->setIcon(ICO_QUERYNEWMSG);
2350         }
2351         if((m_type == CHANNEL && needHighlight) || m_type == QUERY)
2352             m_parent->getParent()->getParent()->handle(this, FXSEL(SEL_COMMAND, IrcTabItem_NEWMSG), NULL);
2353     }
2354 }
2355 
2356 //handle IrcEvent IRC_ACTION
onIrcAction(IrcEvent & ev)2357 void IrcTabItem::onIrcAction(IrcEvent &ev)
2358 {
2359     if((comparecase(ev.param2, getText()) == 0 && m_type == CHANNEL) || (ev.param1 == getText() && m_type == QUERY && ev.param2 == getNickName()))
2360     {
2361         if(!isCommandIgnored("me"))
2362         {
2363             FXbool needHighlight = FALSE;
2364             if(ev.param3.contains(getNickName()))
2365                 needHighlight = highlightNeeded(ev.param3);
2366             appendIrcStyledText(ev.param1+" "+ev.param3, 2, ev.time);
2367             if(preferences.m_highlightColor != this->getTextColor() && m_parent->getCurrent()*2 != m_parent->indexOfChild(this))
2368             {
2369                 if(needHighlight)
2370                 {
2371                     this->setTextColor(preferences.m_highlightColor);
2372                     if(m_type == CHANNEL) this->setIcon(ICO_CHANNELNEWMSG);
2373                 }
2374                 else this->setTextColor(preferences.m_unreadColor);
2375                 if(m_type == QUERY) this->setIcon(ICO_QUERYNEWMSG);
2376             }
2377             if((m_type == CHANNEL && needHighlight) || m_type == QUERY)
2378                 m_parent->getParent()->getParent()->handle(this, FXSEL(SEL_COMMAND, IrcTabItem_NEWMSG), NULL);
2379         }
2380     }
2381 }
2382 
2383 //handle IrcEvent IRC_CTCPREPLY
onIrcCtpcReply(IrcEvent & ev)2384 void IrcTabItem::onIrcCtpcReply(IrcEvent &ev)
2385 {
2386     if(isRightForServerMsg())
2387     {
2388         if(!isCommandIgnored("ctcp"))
2389         {
2390             appendIrcStyledText(FXStringFormat(_("CTCP %s reply from %s: %s"), dxutils::getParam(ev.param2, 1, FALSE).text(), ev.param1.text(), dxutils::getParam(ev.param2, 2, TRUE).text()), 2, ev.time, FALSE, FALSE);
2391             if(preferences.m_highlightColor != this->getTextColor() && m_parent->getCurrent()*2 != m_parent->indexOfChild(this)) this->setTextColor(preferences.m_unreadColor);
2392         }
2393     }
2394 }
2395 
2396 //handle IrcEvent IRC_CTCPREQUEST
onIrcCtcpRequest(IrcEvent & ev)2397 void IrcTabItem::onIrcCtcpRequest(IrcEvent &ev)
2398 {
2399     if(isRightForServerMsg())
2400     {
2401         if(!isCommandIgnored("ctcp"))
2402         {
2403             appendIrcStyledText(FXStringFormat(_("CTCP %s request from %s"), ev.param2.text(), ev.param1.text()), 2, ev.time, FALSE, FALSE);
2404             if(preferences.m_highlightColor != this->getTextColor() && m_parent->getCurrent()*2 != m_parent->indexOfChild(this)) this->setTextColor(preferences.m_unreadColor);
2405         }
2406     }
2407 }
2408 
2409 //handle IrcEvent IRC_JOIN
onIrcJoin(IrcEvent & ev)2410 void IrcTabItem::onIrcJoin(IrcEvent &ev)
2411 {
2412     if(comparecase(ev.param2, getText()) == 0 && ev.param1 != getNickName())
2413     {
2414         if(!isCommandIgnored("join") && !m_engine->isUserIgnored(ev.param1, getText())) appendIrcStyledText(FXStringFormat(_("%s has joined to %s"), ev.param1.text(), ev.param2.text()), 1, ev.time);
2415         addUser(ev.param1, NONE);
2416     }
2417 }
2418 
2419 //handle IrcEvent IRC_QUIT
onIrcQuit(IrcEvent & ev)2420 void IrcTabItem::onIrcQuit(IrcEvent &ev)
2421 {
2422     if(m_type == CHANNEL && m_users->findItem(ev.param1) != -1)
2423     {
2424         IrcEvent pev;
2425         pev.eventType = IRC_PART;
2426         pev.param1 = ev.param1;
2427         pev.param2 = getText();
2428         pev.param3 = "";
2429         pev.param4 = "";
2430         pev.dccFile = DccFile();
2431         pev.time = FXSystem::now();
2432         m_parent->getParent()->getParent()->handle(m_engine, FXSEL(SEL_COMMAND, IrcEngine_SERVER), &pev);
2433         removeUser(ev.param1);
2434         if(ev.param2.empty())
2435         {
2436             if(!isCommandIgnored("quit") && !m_engine->isUserIgnored(ev.param1, getText())) appendIrcStyledText(FXStringFormat(_("%s has quit"), ev.param1.text()), 1, ev.time);
2437         }
2438         else
2439         {
2440             if(!isCommandIgnored("quit") && !m_engine->isUserIgnored(ev.param1, getText())) appendIrcStyledText(FXStringFormat(_("%s has quit (%s)"), ev.param1.text(), ev.param2.text()), 1, ev.time);
2441         }
2442     }
2443     else if(m_type == QUERY && getText() == ev.param1)
2444     {
2445         appendIrcStyledText(FXStringFormat(_("%s has quit"), ev.param1.text()), 1, ev.time, FALSE, FALSE);
2446     }
2447 }
2448 
2449 //handle IrcEvent IRC_PART
onIrcPart(IrcEvent & ev)2450 void IrcTabItem::onIrcPart(IrcEvent &ev)
2451 {
2452     if(comparecase(ev.param2, getText()) == 0)
2453     {
2454         if(ev.param3.empty() && !isCommandIgnored("part") && !m_engine->isUserIgnored(ev.param1, getText())) appendIrcStyledText(FXStringFormat(_("%s has parted %s"), ev.param1.text(), ev.param2.text()), 1, ev.time);
2455         else if(!isCommandIgnored("part") && !m_engine->isUserIgnored(ev.param1, getText())) appendIrcStyledText(FXStringFormat(_("%s has parted %s (%s)"), ev.param1.text(), ev.param2.text(), ev.param3.text()), 1, ev.time);
2456         removeUser(ev.param1);
2457     }
2458 }
2459 
2460 //handle IrcEvent IRC_CHNOTICE
onIrcChnotice(IrcEvent & ev)2461 void IrcTabItem::onIrcChnotice(IrcEvent &ev)
2462 {
2463     if(!isCommandIgnored("notice"))
2464     {
2465         FXbool tabExist = FALSE;
2466         for(FXint i = 0; i<m_parent->numChildren(); i+=2)
2467         {
2468             if(m_parent->childAtIndex(i)->getMetaClass()==&IrcTabItem::metaClass && m_engine->findTarget(static_cast<IrcTabItem*>(m_parent->childAtIndex(i))))
2469             {
2470                 if((comparecase(ev.param2, static_cast<IrcTabItem*>(m_parent->childAtIndex(i))->getText()) == 0 && static_cast<IrcTabItem*>(m_parent->childAtIndex(i))->getType() == CHANNEL)
2471                     || (ev.param1 == static_cast<IrcTabItem*>(m_parent->childAtIndex(i))->getText() && static_cast<IrcTabItem*>(m_parent->childAtIndex(i))->getType() == QUERY && ev.param2 == static_cast<IrcTabItem*>(m_parent->childAtIndex(i))->getNickName()))
2472                 {
2473                     tabExist = TRUE;
2474                     break;
2475                 }
2476             }
2477         }
2478         if(tabExist)
2479         {
2480             if((comparecase(ev.param2, getText()) == 0 && m_type == CHANNEL) || (ev.param1 == getText() && m_type == QUERY && ev.param2 == getNickName()))
2481             {
2482                 FXbool needHighlight = FALSE;
2483                 if(ev.param3.contains(getNickName()))
2484                     needHighlight = highlightNeeded(ev.param3);
2485                 appendIrcStyledText(FXStringFormat(_("%s's NOTICE: %s"), ev.param1.text(), ev.param3.text()), 2, ev.time);
2486                 if(preferences.m_highlightColor != this->getTextColor() && m_parent->getCurrent()*2 != m_parent->indexOfChild(this))
2487                 {
2488                     if(needHighlight)
2489                     {
2490                         this->setTextColor(preferences.m_highlightColor);
2491                         if(m_type == CHANNEL) this->setIcon(ICO_CHANNELNEWMSG);
2492                     }
2493                     else this->setTextColor(preferences.m_unreadColor);
2494                     if(m_type == QUERY) this->setIcon(ICO_QUERYNEWMSG);
2495                 }
2496                 if((m_type == CHANNEL && needHighlight) || m_type == QUERY)
2497                     m_parent->getParent()->getParent()->handle(this, FXSEL(SEL_COMMAND, IrcTabItem_NEWMSG), NULL);
2498             }
2499         }
2500         else
2501         {
2502             if(isRightForServerMsg())
2503             {
2504                 appendIrcStyledText(FXStringFormat(_("%s's NOTICE: %s"), ev.param1.text(), ev.param3.text()), 3, ev.time);
2505             }
2506         }
2507     }
2508 }
2509 
2510 //handle IrcEvent IRC_NOTICE
onIrcNotice(IrcEvent & ev)2511 void IrcTabItem::onIrcNotice(IrcEvent &ev)
2512 {
2513     if(isRightForServerMsg())
2514     {
2515         if(ev.param1 == getNickName() && !isCommandIgnored("notice"))
2516         {
2517             appendIrcStyledText(FXStringFormat(_("NOTICE for you: %s"), ev.param2.text()), 3, ev.time);
2518             if(preferences.m_highlightColor != this->getTextColor() && m_parent->getCurrent()*2 != m_parent->indexOfChild(this)) this->setTextColor(preferences.m_unreadColor);
2519         }
2520         else if(!isCommandIgnored("notice"))
2521         {
2522             appendIrcStyledText(FXStringFormat(_("%s's NOTICE: %s"), ev.param1.text(), ev.param2.text()), 3, ev.time);
2523             if(preferences.m_highlightColor != this->getTextColor() && m_parent->getCurrent()*2 != m_parent->indexOfChild(this)) this->setTextColor(preferences.m_unreadColor);
2524         }
2525     }
2526 }
2527 
2528 //handle IrcEvent IRC_NICK
onIrcNick(IrcEvent & ev)2529 void IrcTabItem::onIrcNick(IrcEvent &ev)
2530 {
2531     if(m_users->findItem(ev.param1) != -1)
2532     {
2533         if(ev.param2 == getNickName() && !isCommandIgnored("nick")) appendIrcStyledText(FXStringFormat(_("You're now known as %s"), ev.param2.text()), 1, ev.time);
2534         else if(!isCommandIgnored("nick") && !m_engine->isUserIgnored(ev.param1, getText())) appendIrcStyledText(FXStringFormat(_("%s is now known as %s"), ev.param1.text(), ev.param2.text()), 1, ev.time);
2535         changeNickUser(ev.param1, ev.param2);
2536     }
2537     if(m_type == QUERY && ev.param1 == getText())
2538     {
2539         this->setText(ev.param2);
2540         stopLogging();
2541     }
2542 }
2543 
2544 //handle IrcEvent IRC_TOPIC
onIrcTopic(IrcEvent & ev)2545 void IrcTabItem::onIrcTopic(IrcEvent &ev)
2546 {
2547     if(comparecase(ev.param2, getText()) == 0)
2548     {
2549         appendIrcText(FXStringFormat(_("%s set new topic for %s: %s"), ev.param1.text(), ev.param2.text(), ev.param3.text()), ev.time);
2550         m_topic = dxutils::stripColors(ev.param3, TRUE);
2551         m_topicline->setText(m_topic);
2552         m_topicline->setCursorPos(0);
2553         m_topicline->makePositionVisible(0);
2554     }
2555 }
2556 
2557 //handle IrcEvent IRC_KICK
onIrcKick(IrcEvent & ev)2558 void IrcTabItem::onIrcKick(IrcEvent &ev)
2559 {
2560     if(comparecase(ev.param3, getText()) == 0)
2561     {
2562         if(ev.param2 != getNickName())
2563         {
2564             if(ev.param4.empty()) appendIrcStyledText(FXStringFormat(_("%s was kicked from %s by %s"), ev.param2.text(), ev.param3.text(), ev.param1.text()), 1, ev.time, FALSE, FALSE);
2565             else appendIrcStyledText(FXStringFormat(_("%s was kicked from %s by %s (%s)"), ev.param2.text(), ev.param3.text(), ev.param1.text(), ev.param4.text()), 1, ev.time, FALSE, FALSE);
2566             removeUser(ev.param2);
2567         }
2568     }
2569     if(ev.param2 == getNickName() && isRightForServerMsg())
2570     {
2571         if(ev.param4.empty()) appendIrcStyledText(FXStringFormat(_("You were kicked from %s by %s"), ev.param3.text(), ev.param1.text()), 1, ev.time, FALSE, FALSE);
2572         else appendIrcStyledText(FXStringFormat(_("You were kicked from %s by %s (%s)"), ev.param3.text(), ev.param1.text(), ev.param4.text()), 1, ev.time, FALSE, FALSE);
2573         if(preferences.m_highlightColor != this->getTextColor() && m_parent->getCurrent()*2 != m_parent->indexOfChild(this)) this->setTextColor(preferences.m_unreadColor);
2574     }
2575 }
2576 
2577 //handle IrcEvent IRC_MODE
onIrcMode(IrcEvent & ev)2578 void IrcTabItem::onIrcMode(IrcEvent &ev)
2579 {
2580     if(isRightForServerMsg())
2581     {
2582         appendIrcStyledText(FXStringFormat(_("Mode change [%s] for %s"), ev.param1.text(), ev.param2.text()), 1, ev.time, FALSE, FALSE);
2583         if(preferences.m_highlightColor != this->getTextColor() && m_parent->getCurrent()*2 != m_parent->indexOfChild(this)) this->setTextColor(preferences.m_unreadColor);
2584     }
2585 }
2586 
2587 //handle IrcEvent IRC_UMODE
onIrcUmode(IrcEvent & ev)2588 void IrcTabItem::onIrcUmode(IrcEvent &ev)
2589 {
2590     FXString moderator = ev.param1;
2591     FXString channel = ev.param2;
2592     FXString modes = ev.param3;
2593     FXString args = ev.param4;
2594     if(comparecase(channel, getText()) == 0)
2595     {
2596         FXbool sign = FALSE;
2597         int argsiter = 1;
2598         for(int i =0; i < modes.count(); i++) {
2599             switch(modes[i]) {
2600                 case '+':
2601                     sign = TRUE;
2602                     break;
2603                 case '-':
2604                     sign = FALSE;
2605                     break;
2606                 case 'a': //admin
2607                 {
2608                     FXString nick = dxutils::getParam(args, argsiter, FALSE);
2609                     setUserMode(nick, sign?ADMIN:NONE);
2610                     if(sign)
2611                     {
2612                         if(!isCommandIgnored("mode") && !m_engine->isUserIgnored(nick, getText()))
2613                         {
2614                             if(nick == getNickName()) appendIrcStyledText(FXStringFormat(_("%s gave you admin"), moderator.text()), 1, ev.time, FALSE, FALSE);
2615                             else appendIrcStyledText(FXStringFormat(_("%s gave %s admin"), moderator.text(), nick.text()), 1, ev.time, FALSE, FALSE);
2616                         }
2617                     }
2618                     else
2619                     {
2620                         if(!isCommandIgnored("mode") && !m_engine->isUserIgnored(nick, getText()))
2621                         {
2622                             if(nick == getNickName()) appendIrcStyledText(FXStringFormat(_("%s removed you admin"), moderator.text()), 1, ev.time, FALSE, FALSE);
2623                             else appendIrcStyledText(FXStringFormat(_("%s removed %s admin"), moderator.text(), nick.text()), 1, ev.time, FALSE, FALSE);
2624                         }
2625                     }
2626                     argsiter++;
2627                 }break;
2628                 case 'o': //op
2629                 {
2630                     FXString nick = dxutils::getParam(args, argsiter, FALSE);
2631                     setUserMode(nick, sign?OP:NONE);
2632                     if(sign)
2633                     {
2634                         if(!isCommandIgnored("mode") && !m_engine->isUserIgnored(nick, getText()))
2635                         {
2636                             if(nick == getNickName()) appendIrcStyledText(FXStringFormat(_("%s gave you op"), moderator.text()), 1, ev.time, FALSE, FALSE);
2637                             else appendIrcStyledText(FXStringFormat(_("%s gave %s op"), moderator.text(), nick.text()), 1, ev.time, FALSE, FALSE);
2638                         }
2639                     }
2640                     else
2641                     {
2642                         if(!isCommandIgnored("mode") && !m_engine->isUserIgnored(nick, getText()))
2643                         {
2644                             if(nick == getNickName()) appendIrcStyledText(FXStringFormat(_("%s removed you op"), moderator.text()), 1, ev.time, FALSE, FALSE);
2645                             else appendIrcStyledText(FXStringFormat(_("%s removed %s op"), moderator.text(), nick.text()), 1, ev.time, FALSE, FALSE);
2646                         }
2647                     }
2648                     if(getNickName() == nick) sign ? m_iamOp = TRUE : m_iamOp = FALSE;
2649                     argsiter++;
2650                 }break;
2651                 case 'v': //voice
2652                 {
2653                     FXString nick = dxutils::getParam(args, argsiter, FALSE);
2654                     setUserMode(nick, sign?VOICE:NONE);
2655                     if(sign)
2656                     {
2657                         if(!isCommandIgnored("mode") && !m_engine->isUserIgnored(nick, getText()))
2658                         {
2659                             if(nick == getNickName()) appendIrcStyledText(FXStringFormat(_("%s gave you voice"), moderator.text()), 1, ev.time, FALSE, FALSE);
2660                             else appendIrcStyledText(FXStringFormat(_("%s gave %s voice"), moderator.text(), nick.text()), 1, ev.time, FALSE, FALSE);
2661                         }
2662                     }
2663                     else
2664                     {
2665                         if(!isCommandIgnored("mode") && !m_engine->isUserIgnored(nick, getText()))
2666                         {
2667                             if(nick == getNickName()) appendIrcStyledText(FXStringFormat(_("%s removed you voice"), moderator.text()), 1, ev.time, FALSE, FALSE);
2668                             else appendIrcStyledText(FXStringFormat(_("%s removed %s voice"), moderator.text(), nick.text()), 1, ev.time, FALSE, FALSE);
2669                         }
2670                     }
2671                     argsiter++;
2672                 }break;
2673                 case 'h': //halfop
2674                 {
2675                     FXString nick = dxutils::getParam(args, argsiter, FALSE);
2676                     setUserMode(nick, sign?HALFOP:NONE);
2677                     if(sign)
2678                     {
2679                         if(!isCommandIgnored("mode") && !m_engine->isUserIgnored(nick, getText()))
2680                         {
2681                             if(nick == getNickName()) appendIrcStyledText(FXStringFormat(_("%s gave you halfop"), moderator.text()), 1, ev.time, FALSE, FALSE);
2682                             else appendIrcStyledText(FXStringFormat(_("%s gave %s halfop"), moderator.text(), nick.text()), 1, ev.time, FALSE, FALSE);
2683                         }
2684                     }
2685                     else
2686                     {
2687                         if(!isCommandIgnored("mode") && !m_engine->isUserIgnored(nick, getText()))
2688                         {
2689                             if(nick == getNickName()) appendIrcStyledText(FXStringFormat(_("%s removed you halfop"), moderator.text()), 1, ev.time, FALSE, FALSE);
2690                             else appendIrcStyledText(FXStringFormat(_("%s removed %s halfop"), moderator.text(), nick.text()), 1, ev.time, FALSE, FALSE);
2691                         }
2692                     }
2693                     argsiter++;
2694                 }break;
2695                 case 'b': //ban
2696                 {
2697                     FXString banmask = dxutils::getParam(args, argsiter, FALSE);
2698                     onBan(banmask, sign, moderator, ev.time);
2699                     argsiter++;
2700                 }break;
2701                 case 't': //topic settable by channel operator
2702                 {
2703                     sign ? m_editableTopic = FALSE : m_editableTopic = TRUE;
2704                 }break;
2705                 default:
2706                 {
2707                     appendIrcStyledText(FXStringFormat(_("%s set Mode: %s"), moderator.text(), FXString(modes+" "+args).text()), 1, ev.time, FALSE, FALSE);
2708                 }
2709             }
2710         }
2711         if(preferences.m_sortUserMode) m_users->sortItems();
2712     }
2713 }
2714 
2715 //handle IrcEvent IRC_CHMODE
onIrcChmode(IrcEvent & ev)2716 void IrcTabItem::onIrcChmode(IrcEvent &ev)
2717 {
2718     FXString channel = ev.param1;
2719     FXString modes = ev.param2;
2720     if(comparecase(channel, getText()) == 0)
2721     {
2722         if(modes.contains('t')) m_editableTopic = FALSE;
2723         appendIrcStyledText(FXStringFormat(_("Mode for %s: %s"), channel.text(), modes.text()), 1, ev.time, FALSE, FALSE);
2724     }
2725 }
2726 
2727 //handle IrcEvent IRC_SERVERREPLY
onIrcServerReply(IrcEvent & ev)2728 void IrcTabItem::onIrcServerReply(IrcEvent &ev)
2729 {
2730     if(m_type == SERVER)
2731     {
2732         //this->setText(server->GetRealServerName());
2733         appendIrcText(ev.param1, ev.time);
2734         if(getApp()->getForeColor() == this->getTextColor() && m_parent->getCurrent()*2 != m_parent->indexOfChild(this)) this->setTextColor(preferences.m_unreadColor);
2735     }
2736     else
2737     {
2738         if(isRightForServerMsg())
2739         {
2740             appendIrcText(ev.param1, ev.time, FALSE, FALSE);
2741             if(preferences.m_highlightColor != this->getTextColor() && m_parent->getCurrent()*2 != m_parent->indexOfChild(this)) this->setTextColor(preferences.m_unreadColor);
2742         }
2743     }
2744 }
2745 
2746 //handle IrcEvent IRC_CONNECT
onIrcConnect(IrcEvent & ev)2747 void IrcTabItem::onIrcConnect(IrcEvent &ev)
2748 {
2749     appendIrcStyledText(ev.param1, 3, ev.time, FALSE, FALSE);
2750 }
2751 
2752 //handle IrcEvent IRC_ERROR
onIrcError(IrcEvent & ev)2753 void IrcTabItem::onIrcError(IrcEvent &ev)
2754 {
2755     appendIrcStyledText(ev.param1, 4, ev.time, FALSE, FALSE);
2756 }
2757 
2758 //handle IrcEvent IRC_SERVERERROR
onIrcServerError(IrcEvent & ev)2759 void IrcTabItem::onIrcServerError(IrcEvent &ev)
2760 {
2761     if(isRightForServerMsg())
2762     {
2763         appendIrcStyledText(ev.param1, 4, ev.time, FALSE, FALSE);
2764         if(preferences.m_highlightColor != this->getTextColor() && m_parent->getCurrent()*2 != m_parent->indexOfChild(this)) this->setTextColor(preferences.m_unreadColor);
2765     }
2766 }
2767 
2768 //handle IrcEvent IRC_DISCONNECT
onIrcDisconnect(IrcEvent & ev)2769 void IrcTabItem::onIrcDisconnect(IrcEvent &ev)
2770 {
2771     appendIrcStyledText(ev.param1, 4, ev.time, FALSE, FALSE);
2772     if(isRightForServerMsg())
2773     {
2774         if(m_parent->getCurrent()*2 != m_parent->indexOfChild(this)) this->setTextColor(preferences.m_highlightColor);
2775     }
2776     if(m_type == CHANNEL)
2777     {
2778         m_users->clearItems();
2779         m_iamOp = FALSE;
2780     }
2781 }
2782 
2783 //handle IrcEvent IRC_RECONNECT
onIrcReconnect(IrcEvent & ev)2784 void IrcTabItem::onIrcReconnect(IrcEvent &ev)
2785 {
2786     appendIrcStyledText(ev.param1, 4, ev.time, FALSE, FALSE);
2787     if(isRightForServerMsg())
2788     {
2789         if(m_parent->getCurrent()*2 != m_parent->indexOfChild(this)) this->setTextColor(preferences.m_highlightColor);
2790     }
2791     if(m_type == CHANNEL)
2792     {
2793         m_users->clearItems();
2794         m_iamOp = FALSE;
2795     }
2796 }
2797 
2798 //handle IrcEvent IRC_RECONNECTALL
onIrcReconnectAll(IrcEvent & ev)2799 void IrcTabItem::onIrcReconnectAll(IrcEvent &ev)
2800 {
2801     appendIrcStyledText(ev.param1, 3, ev.time, FALSE, FALSE);
2802     if(m_type == CHANNEL)
2803     {
2804         m_users->clearItems();
2805         m_iamOp = FALSE;
2806     }
2807 }
2808 
2809 //handle IrcEvent IRC_UNKNOWN
onIrcUnknown(IrcEvent & ev)2810 void IrcTabItem::onIrcUnknown(IrcEvent &ev)
2811 {
2812     if(isRightForServerMsg())
2813     {
2814         appendIrcStyledText(FXStringFormat(_("Unhandled command '%s' params: %s"), ev.param1.text(), ev.param2.text()), 4, ev.time, FALSE, FALSE);
2815         if(preferences.m_highlightColor != this->getTextColor() && m_parent->getCurrent()*2 != m_parent->indexOfChild(this)) this->setTextColor(preferences.m_unreadColor);
2816     }
2817 }
2818 
2819 //handle IrcEvent IRC_301
onIrc301(IrcEvent & ev)2820 void IrcTabItem::onIrc301(IrcEvent &ev)
2821 {
2822     if(m_parent->getCurrent()*2 == m_parent->indexOfChild(this) || getText() == ev.param1)
2823     {
2824         if(!isCommandIgnored("away") && !m_engine->isUserIgnored(ev.param1, getText())) appendIrcStyledText(FXStringFormat(_("%s is away: %s"),ev.param1.text(), ev.param2.text()), 1, ev.time);
2825     }
2826 }
2827 
2828 //handle IrcEvent IRC_305
onIrc305(IrcEvent & ev)2829 void IrcTabItem::onIrc305(IrcEvent &ev)
2830 {
2831     FXint i = m_users->findItem(getNickName());
2832     if(i != -1)
2833     {
2834         appendIrcStyledText(ev.param1, 1, ev.time, FALSE, FALSE);
2835         ((NickListItem*)m_users->getItem(i))->changeAway(FALSE);
2836     }
2837 }
2838 
2839 //handle IrcEvent IRC_306
onIrc306(IrcEvent & ev)2840 void IrcTabItem::onIrc306(IrcEvent &ev)
2841 {
2842     FXint i = m_users->findItem(getNickName());
2843     if(i != -1)
2844     {
2845         appendIrcStyledText(ev.param1, 1, ev.time, FALSE, FALSE);
2846         ((NickListItem*)m_users->getItem(i))->changeAway(TRUE);
2847     }
2848 }
2849 
2850 //handle IrcEvent IRC_331, IRC_332 and IRC_333
onIrc331332333(IrcEvent & ev)2851 void IrcTabItem::onIrc331332333(IrcEvent &ev)
2852 {
2853     if(comparecase(ev.param1, getText()) == 0)
2854     {
2855         appendIrcText(ev.param2, ev.time);
2856         if(ev.eventType == IRC_331)
2857         {
2858             m_topic = dxutils::stripColors(ev.param2, TRUE);
2859             m_topicline->setText(m_topic);
2860             m_topicline->setCursorPos(0);
2861             m_topicline->makePositionVisible(0);
2862         }
2863         if(ev.eventType == IRC_332)
2864         {
2865             m_topic = dxutils::stripColors(dxutils::getParam(ev.param2, 2, TRUE, ':').after(' '), TRUE);
2866             m_topicline->setText(m_topic);
2867             m_topicline->setCursorPos(0);
2868             m_topicline->makePositionVisible(0);
2869         }
2870     }
2871 }
2872 
2873 //handle IrcEvent IRC_353
onIrc353(IrcEvent & ev)2874 void IrcTabItem::onIrc353(IrcEvent &ev)
2875 {
2876     FXString channel = ev.param1;
2877     FXString usersStr = ev.param2;
2878     bool list = ev.param3=="list";
2879     FXString myNick = getNickName();
2880     if(usersStr.right(1) != " ") usersStr.append(" ");
2881     if(comparecase(channel, getText()) == 0)
2882     {
2883         if(list && !isCommandIgnored("numeric")) appendIrcText(FXStringFormat(_("Users on %s: %s"), channel.text(), usersStr.text()), ev.time, FALSE, FALSE);
2884         while(usersStr.contains(' '))
2885         {
2886             FXString nick = usersStr.before(' ');
2887             UserMode mode = getUserMode(nick[0]);
2888             if(mode != NONE) nick = nick.after(nick[0]);
2889             addUser(nick, mode);
2890             if(mode == OP && nick == myNick) m_iamOp = TRUE;
2891             usersStr = usersStr.after(' ');
2892         }
2893     }
2894     else
2895     {
2896         if(list && !isCommandIgnored("numeric"))
2897         {
2898             FXbool channelOn = FALSE;
2899             for(FXint i = 0; i<m_parent->numChildren(); i+=2)
2900             {
2901                 if(m_engine->findTarget(static_cast<IrcTabItem*>(m_parent->childAtIndex(i))) && comparecase(static_cast<FXTabItem*>(m_parent->childAtIndex(i))->getText(), channel) == 0)
2902                 {
2903                     channelOn = TRUE;
2904                     break;
2905                 }
2906             }
2907             if(!channelOn)
2908             {
2909                 if(m_type == SERVER)
2910                 {
2911                     appendIrcText(FXStringFormat(_("Users on %s: %s"), channel.text(), usersStr.text()), ev.time, FALSE, FALSE);
2912                     if(preferences.m_highlightColor != this->getTextColor() && m_parent->getCurrent()*2 != m_parent->indexOfChild(this)) this->setTextColor(preferences.m_unreadColor);
2913                 }
2914                 else
2915                 {
2916                     if(isRightForServerMsg())
2917                     {
2918                         appendIrcText(FXStringFormat(_("Users on %s: %s"), channel.text(), usersStr.text()), ev.time, FALSE, FALSE);
2919                         if(preferences.m_highlightColor != this->getTextColor() && m_parent->getCurrent()*2 != m_parent->indexOfChild(this)) this->setTextColor(preferences.m_unreadColor);
2920                     }
2921                 }
2922             }
2923         }
2924     }
2925 }
2926 
2927 //handle IrcEvent IRC_366
onIrc366(IrcEvent & ev)2928 void IrcTabItem::onIrc366(IrcEvent &ev)
2929 {
2930     bool list = ev.param3=="list";
2931     if(comparecase(ev.param1, getText()) == 0)
2932     {
2933         if(list && !isCommandIgnored("numeric")) appendIrcText(FXStringFormat("%s: %s", ev.param1.text(), ev.param2.text()), ev.time, FALSE, FALSE);
2934         else m_engine->addIgnoreWho(getText());
2935     }
2936     else
2937     {
2938         if(list && !isCommandIgnored("numeric"))
2939         {
2940             FXbool channelOn = FALSE;
2941             for(FXint i = 0; i<m_parent->numChildren(); i+=2)
2942             {
2943                 if(m_engine->findTarget(static_cast<IrcTabItem*>(m_parent->childAtIndex(i))) && comparecase(static_cast<FXTabItem*>(m_parent->childAtIndex(i))->getText(), ev.param1) == 0)
2944                 {
2945                     channelOn = TRUE;
2946                     break;
2947                 }
2948             }
2949             if(!channelOn)
2950             {
2951                 if(m_type == SERVER)
2952                 {
2953                     appendIrcText(FXStringFormat("%s: %s", ev.param1.text(), ev.param2.text()), ev.time, FALSE, FALSE);
2954                     if(preferences.m_highlightColor != this->getTextColor() && m_parent->getCurrent()*2 != m_parent->indexOfChild(this)) this->setTextColor(preferences.m_unreadColor);
2955                 }
2956                 else
2957                 {
2958                     if(isRightForServerMsg())
2959                     {
2960                         appendIrcText(FXStringFormat("%s: %s", ev.param1.text(), ev.param2.text()), ev.time, FALSE, FALSE);
2961                         if(preferences.m_highlightColor != this->getTextColor() && m_parent->getCurrent()*2 != m_parent->indexOfChild(this)) this->setTextColor(preferences.m_unreadColor);
2962                     }
2963                 }
2964             }
2965         }
2966     }
2967 }
2968 
2969 //handle IrcEvent IRC_372
onIrc372(IrcEvent & ev)2970 void IrcTabItem::onIrc372(IrcEvent &ev)
2971 {
2972     if(m_type == SERVER)
2973     {
2974         appendIrcText(ev.param1, ev.time);
2975         if(getApp()->getForeColor() == this->getTextColor() && m_parent->getCurrent()*2 != m_parent->indexOfChild(this)) this->setTextColor(preferences.m_unreadColor);
2976     }
2977     else
2978     {
2979         if(isRightForServerMsg())
2980         {
2981             appendIrcText(ev.param1, ev.time, FALSE, FALSE);
2982             if(preferences.m_highlightColor != this->getTextColor() && m_parent->getCurrent()*2 != m_parent->indexOfChild(this)) this->setTextColor(preferences.m_unreadColor);
2983         }
2984     }
2985 }
2986 
2987 //handle IrcEvent IRC_AWAY
onIrcAway(IrcEvent & ev)2988 void IrcTabItem::onIrcAway(IrcEvent &ev)
2989 {
2990     if(comparecase(ev.param1, getText()) == 0)
2991     {
2992         onAway();
2993         return;
2994     }
2995     //hack for &bitlbee
2996     if(comparecase("&bitlbee", getText()) == 0 && m_users->findItem(ev.param1)!=-1)
2997     {
2998         onAway();
2999         return;
3000     }
3001 }
3002 
3003 //handle IrcEvent IRC_ENDMOTD
onIrcEndMotd()3004 void IrcTabItem::onIrcEndMotd()
3005 {
3006     m_text->makeLastRowVisible(TRUE);
3007     if(m_type == SERVER && !m_engine->getNetworkName().empty())
3008         setText(m_engine->getNetworkName());
3009 }
3010 
onPipe(FXObject *,FXSelector,void * ptr)3011 long IrcTabItem::onPipe(FXObject*, FXSelector, void *ptr)
3012 {
3013     FXString text = *(FXString*)ptr;
3014     if(m_sendPipe && (m_type == CHANNEL || m_type == QUERY))
3015     {
3016         if(!getApp()->hasTimeout(this, IrcTabItem_PTIME)) getApp()->addTimeout(this, IrcTabItem_PTIME);
3017         m_pipeStrings.append(text);
3018     }
3019     else appendIrcText(text, FXSystem::now(), TRUE, FALSE);
3020     return 1;
3021 }
3022 
3023 //checking away in channel
checkAway()3024 void IrcTabItem::checkAway()
3025 {
3026     if(m_type == CHANNEL && m_engine->getConnected() && m_numberUsers < preferences.m_maxAway)
3027     {
3028         m_engine->addIgnoreWho(getText());
3029     }
3030 }
3031 
onPipeTimeout(FXObject *,FXSelector,void *)3032 long IrcTabItem::onPipeTimeout(FXObject*, FXSelector, void*)
3033 {
3034     if(m_type == CHANNEL || m_type == QUERY)
3035     {
3036         if(m_pipeStrings.no() > 3)
3037         {
3038             if(m_pipeStrings[0].empty()) m_pipeStrings[0] = " ";
3039             if(m_pipeStrings[0].length() > m_maxLen-10-getText().length())
3040             {
3041                 dxStringArray messages = cutText(m_pipeStrings[0], m_maxLen-10-getText().length());
3042                 for(FXint i=0; i<messages.no(); i++)
3043                 {
3044 #ifdef HAVE_LUA
3045                     m_parent->getParent()->getParent()->handle(this, FXSEL(SEL_COMMAND, IrcTabItem_OWNMSG), &messages[i]);
3046                     if(!m_scriptHasOwnMsg)
3047                     {
3048                         appendMyMsg(messages[i], FXSystem::now());
3049                         m_engine->sendMsg(getText(), messages[i]);
3050                     }
3051 #else
3052                     appendMyMsg(messages[i], FXSystem::now());
3053                     m_engine->sendMsg(getText(), messages[i]);
3054 #endif
3055                 }
3056             }
3057             else
3058             {
3059 #ifdef HAVE_LUA
3060                 m_parent->getParent()->getParent()->handle(this, FXSEL(SEL_COMMAND, IrcTabItem_OWNMSG), &m_pipeStrings[0]);
3061                 if(!m_scriptHasOwnMsg)
3062                 {
3063                     appendMyMsg(m_pipeStrings[0], FXSystem::now());
3064                     m_engine->sendMsg(getText(), m_pipeStrings[0]);
3065                 }
3066 #else
3067                 appendMyMsg(m_pipeStrings[0], FXSystem::now());
3068                 m_engine->sendMsg(getText(), m_pipeStrings[0]);
3069 #endif
3070             }
3071             m_pipeStrings.erase(0);
3072             getApp()->addTimeout(this, IrcTabItem_PTIME, 3000);
3073         }
3074         else
3075         {
3076             while(m_pipeStrings.no())
3077             {
3078                 if(m_pipeStrings[0].empty()) m_pipeStrings[0] = " ";
3079                 if(m_pipeStrings[0].length() > m_maxLen-10-getText().length())
3080                 {
3081                     dxStringArray messages = cutText(m_pipeStrings[0], m_maxLen-10-getText().length());
3082                     for(FXint i=0; i<messages.no(); i++)
3083                     {
3084 #ifdef HAVE_LUA
3085                         m_parent->getParent()->getParent()->handle(this, FXSEL(SEL_COMMAND, IrcTabItem_OWNMSG), &messages[i]);
3086                         if(!m_scriptHasOwnMsg)
3087                         {
3088                             appendMyMsg(messages[i], FXSystem::now());
3089                             m_engine->sendMsg(getText(), messages[i]);
3090                         }
3091 #else
3092                         appendMyMsg(messages[i], FXSystem::now());
3093                         m_engine->sendMsg(getText(), messages[i]);
3094 #endif
3095                     }
3096                 }
3097                 else
3098                 {
3099 #ifdef HAVE_LUA
3100                     m_parent->getParent()->getParent()->handle(this, FXSEL(SEL_COMMAND, IrcTabItem_OWNMSG), &m_pipeStrings[0]);
3101                     if(!m_scriptHasOwnMsg)
3102                     {
3103                         appendMyMsg(m_pipeStrings[0], FXSystem::now());
3104                         m_engine->sendMsg(getText(), m_pipeStrings[0]);
3105                     }
3106 #else
3107                     appendMyMsg(m_pipeStrings[0], FXSystem::now());
3108                     m_engine->sendMsg(getText(), m_pipeStrings[0]);
3109 #endif
3110                 }
3111                 m_pipeStrings.erase(0);
3112             }
3113         }
3114     }
3115     return 1;
3116 }
3117 
onEggTimeout(FXObject *,FXSelector,void *)3118 long IrcTabItem::onEggTimeout(FXObject*, FXSelector, void*)
3119 {
3120     if(m_pics<24)
3121     {
3122         getApp()->addTimeout(this, IrcTabItem_ETIME, 222);
3123         FXString replace = "\n";
3124         FXint max = rand()%30;
3125         for(FXint i=0; i<max; i++)
3126             replace.append(' ');
3127         FXString pic = "\n  oooooooooo\n o          o\no            o\no   o    o   o\no   o    o   o\no            o\no  o      o  o\no   oooooo   o\n o          o\n  oooooooooo";
3128         pic.substitute("\n", replace);
3129         pic.append('\n');
3130         m_text->clearText();
3131         max = rand()%15;
3132         for(FXint i=0; i<max; i++)
3133             pic.prepend('\n');
3134         max = rand()%7;
3135         m_text->appendStyledText(pic, max+12);
3136         m_pics++;
3137     }
3138     return 1;
3139 }
3140 
onAway()3141 void IrcTabItem::onAway()
3142 {
3143     if(m_numberUsers < preferences.m_maxAway)
3144     {
3145         for(FXint i = 0; i < m_users->getNumItems(); i++)
3146         {
3147             FXbool away = m_engine->getNickInfo(m_users->getItemText(i)).away;
3148             ((NickListItem*)m_users->getItem(i))->changeAway(away);
3149         }
3150     }
3151     else
3152     {
3153         for(FXint i = 0; i < m_users->getNumItems(); i++)
3154         {
3155             ((NickListItem*)m_users->getItem(i))->changeAway(FALSE);
3156         }
3157     }
3158 }
3159 
onRightMouse(FXObject *,FXSelector,void * ptr)3160 long IrcTabItem::onRightMouse(FXObject *, FXSelector, void *ptr)
3161 {
3162     //focus();
3163     FXEvent* event = (FXEvent*)ptr;
3164     if(event->moved) return 1;
3165     FXint index = m_users->getItemAt(event->win_x,event->win_y);
3166     if(index >= 0)
3167     {
3168         UserMode mode = ((NickListItem*)m_users->getItem(index))->getUserMode();
3169         NickInfo nick = m_engine->getNickInfo(m_users->getItemText(index));
3170         m_nickOnRight = nick;
3171         FXString flagpath = DXIRC_DATADIR PATHSEPSTRING "icons" PATHSEPSTRING "flags";
3172         delete ICO_FLAG;
3173         ICO_FLAG = NULL;
3174         if(FXStat::exists(flagpath+PATHSEPSTRING+nick.host.rafter('.')+".png")) ICO_FLAG = makeIcon(getApp(), flagpath, nick.host.rafter('.')+".png", TRUE);
3175         else ICO_FLAG = makeIcon(getApp(), flagpath, "unknown.png", TRUE);
3176         FXMenuPane opmenu(this);
3177         if(mode != OP) new FXMenuCommand(&opmenu, _("Give op"), NULL, this, IrcTabItem_OP);
3178         if(mode == OP) new FXMenuCommand(&opmenu, _("Remove op"), NULL, this, IrcTabItem_DEOP);
3179         new FXMenuSeparator(&opmenu);
3180         if(mode != VOICE) new FXMenuCommand(&opmenu, _("Give voice"), NULL, this, IrcTabItem_VOICE);
3181         if(mode == VOICE) new FXMenuCommand(&opmenu, _("Remove voice"), NULL, this, IrcTabItem_DEVOICE);
3182         new FXMenuSeparator(&opmenu);
3183         new FXMenuCommand(&opmenu, _("Kick"), NULL, this, IrcTabItem_KICK);
3184         new FXMenuSeparator(&opmenu);
3185         new FXMenuCommand(&opmenu, _("Ban"), NULL, this, IrcTabItem_BAN);
3186         new FXMenuCommand(&opmenu, _("KickBan"), NULL, this, IrcTabItem_KICKBAN);
3187         FXMenuPane popup(this);
3188         new FXMenuCommand(&popup, FXStringFormat(_("User: %s@%s"), nick.user.text(), nick.host.text()), ICO_FLAG);
3189         new FXMenuCommand(&popup, FXStringFormat(_("Realname: %s"), nick.real.text()));
3190         if(nick.nick != getNickName())
3191         {
3192             new FXMenuSeparator(&popup);
3193             new FXMenuCommand(&popup, _("Query"), NULL, this, IrcTabItem_NEWQUERY);
3194             new FXMenuCommand(&popup, _("User information (WHOIS)"), NULL, this, IrcTabItem_WHOIS);
3195             new FXMenuCommand(&popup, _("DCC chat"), NULL, this, IrcTabItem_DCCCHAT);
3196             new FXMenuCommand(&popup, _("Send file"), NULL, this, IrcTabItem_DCCSEND);
3197             new FXMenuCommand(&popup, _("Ignore"), NULL, this, IrcTabItem_IGNORE);
3198             if(m_iamOp) new FXMenuCascade(&popup, _("Operator actions"), NULL, &opmenu);
3199         }
3200         else
3201         {
3202             new FXMenuSeparator(&popup);
3203             if(m_engine->isAway(getNickName())) new FXMenuCommand(&popup, _("Remove Away"), NULL, this, IrcTabItem_DEAWAY);
3204             else new FXMenuCommand(&popup, _("Set Away"), NULL, this, IrcTabItem_AWAY);
3205         }
3206         popup.create();
3207         popup.popup(NULL,event->root_x,event->root_y);
3208         getApp()->runModalWhileShown(&popup);
3209     }
3210     return 1;
3211 }
3212 
onDoubleclick(FXObject *,FXSelector,void *)3213 long IrcTabItem::onDoubleclick(FXObject*, FXSelector, void*)
3214 {
3215     FXint index = m_users->getCursorItem();
3216     if(index >= 0)
3217     {
3218         if(m_users->getItemText(index) == getNickName()) return 1;
3219         IrcEvent ev;
3220         ev.eventType = IRC_QUERY;
3221         ev.param1 = m_users->getItemText(index);
3222         ev.param2 = getNickName();
3223         m_parent->getParent()->getParent()->handle(m_engine, FXSEL(SEL_COMMAND, IrcEngine_SERVER), &ev);
3224     }
3225     return 1;
3226 }
3227 
onNewQuery(FXObject *,FXSelector,void *)3228 long IrcTabItem::onNewQuery(FXObject *, FXSelector, void *)
3229 {
3230     IrcEvent ev;
3231     ev.eventType = IRC_QUERY;
3232     ev.param1 = m_nickOnRight.nick;
3233     ev.param2 = getNickName();
3234     m_parent->getParent()->getParent()->handle(m_engine, FXSEL(SEL_COMMAND, IrcEngine_SERVER), &ev);
3235     return 1;
3236 }
3237 
onWhois(FXObject *,FXSelector,void *)3238 long IrcTabItem::onWhois(FXObject *, FXSelector, void *)
3239 {
3240     m_engine->sendWhois(m_nickOnRight.nick);
3241     return 1;
3242 }
3243 
onDccChat(FXObject *,FXSelector,void *)3244 long IrcTabItem::onDccChat(FXObject*, FXSelector, void*)
3245 {
3246     IrcEvent ev;
3247     ev.eventType = IRC_DCCSERVER;
3248     ev.param1 = m_nickOnRight.nick;
3249     m_parent->getParent()->getParent()->handle(m_engine, FXSEL(SEL_COMMAND, IrcEngine_SERVER), &ev);
3250     return 1;
3251 }
3252 
onDccSend(FXObject *,FXSelector,void *)3253 long IrcTabItem::onDccSend(FXObject*, FXSelector, void*)
3254 {
3255     DccSendDialog dialog((FXMainWindow*)m_parent->getParent()->getParent(), m_nickOnRight.nick);
3256     if(dialog.execute())
3257     {
3258         IrcEvent ev;
3259         ev.eventType = dialog.getPassive() ? IRC_DCCPOUT: IRC_DCCOUT;
3260         ev.param1 = m_nickOnRight.nick;
3261         ev.param2 = dialog.getFilename();
3262         m_parent->getParent()->getParent()->handle(m_engine, FXSEL(SEL_COMMAND, IrcEngine_SERVER), &ev);
3263     }
3264     return 1;
3265 }
3266 
onOp(FXObject *,FXSelector,void *)3267 long IrcTabItem::onOp(FXObject *, FXSelector, void *)
3268 {
3269     m_engine->sendMode(getText()+" +o "+m_nickOnRight.nick);
3270     return 1;
3271 }
3272 
onDeop(FXObject *,FXSelector,void *)3273 long IrcTabItem::onDeop(FXObject *, FXSelector, void *)
3274 {
3275     m_engine->sendMode(getText()+" -o "+m_nickOnRight.nick);
3276     return 1;
3277 }
3278 
onVoice(FXObject *,FXSelector,void *)3279 long IrcTabItem::onVoice(FXObject *, FXSelector, void *)
3280 {
3281     m_engine->sendMode(getText()+" +v "+m_nickOnRight.nick);
3282     return 1;
3283 }
3284 
onDevoice(FXObject *,FXSelector,void *)3285 long IrcTabItem::onDevoice(FXObject *, FXSelector, void *)
3286 {
3287     m_engine->sendMode(getText()+" -v "+m_nickOnRight.nick);
3288     return 1;
3289 }
3290 
onKick(FXObject *,FXSelector,void *)3291 long IrcTabItem::onKick(FXObject *, FXSelector, void *)
3292 {
3293     FXDialogBox kickDialog(this, _("Kick dialog"), DECOR_TITLE|DECOR_BORDER, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
3294     FXVerticalFrame *contents = new FXVerticalFrame(&kickDialog, LAYOUT_SIDE_LEFT|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0, 0, 0, 0, 10, 10, 10, 10, 0, 0);
3295 
3296     FXHorizontalFrame *kickframe = new FXHorizontalFrame(contents, LAYOUT_FILL_X|LAYOUT_FILL_Y);
3297     new FXLabel(kickframe, _("Kick reason:"), 0, JUSTIFY_LEFT|LAYOUT_FILL_X|LAYOUT_FILL_Y);
3298     FXTextField *reasonEdit = new FXTextField(kickframe, 25, NULL, 0, FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
3299 
3300     FXHorizontalFrame *buttonframe = new FXHorizontalFrame(contents, LAYOUT_FILL_X|LAYOUT_FILL_Y|PACK_UNIFORM_WIDTH);
3301     new dxEXButton(buttonframe, _("&Cancel"), NULL, &kickDialog, FXDialogBox::ID_CANCEL, FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT, 0, 0, 0, 0, 10, 10, 2, 2);
3302     new dxEXButton(buttonframe, _("&OK"), NULL, &kickDialog, FXDialogBox::ID_ACCEPT, BUTTON_INITIAL|BUTTON_DEFAULT|FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT, 0, 0, 0, 0, 10, 10, 2, 2);
3303 
3304     if(kickDialog.execute(PLACEMENT_CURSOR))
3305     {
3306         m_engine->sendKick(getText(), m_nickOnRight.nick, reasonEdit->getText());
3307     }
3308     return 1;
3309 }
3310 
onBan(FXObject *,FXSelector,void *)3311 long IrcTabItem::onBan(FXObject *, FXSelector, void *)
3312 {
3313     FXDialogBox banDialog(this, _("Ban dialog"), DECOR_TITLE|DECOR_BORDER, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
3314     FXVerticalFrame *contents = new FXVerticalFrame(&banDialog, LAYOUT_SIDE_LEFT|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0, 0, 0, 0, 10, 10, 10, 10, 0, 0);
3315 
3316     FXHorizontalFrame *banframe = new FXHorizontalFrame(contents, LAYOUT_FILL_X|LAYOUT_FILL_Y);
3317     new FXLabel(banframe, _("Banmask:"), 0, JUSTIFY_LEFT|LAYOUT_FILL_X|LAYOUT_FILL_Y);
3318     FXTextField *banEdit = new FXTextField(banframe, 25, NULL, 0, FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
3319     banEdit->setText(m_nickOnRight.nick+"!"+m_nickOnRight.user+"@"+m_nickOnRight.host);
3320 
3321     FXHorizontalFrame *buttonframe = new FXHorizontalFrame(contents, LAYOUT_FILL_X|LAYOUT_FILL_Y|PACK_UNIFORM_WIDTH);
3322     new dxEXButton(buttonframe, _("&Cancel"), NULL, &banDialog, FXDialogBox::ID_CANCEL, FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT, 0, 0, 0, 0, 10, 10, 2, 2);
3323     new dxEXButton(buttonframe, _("&OK"), NULL, &banDialog, FXDialogBox::ID_ACCEPT, BUTTON_INITIAL|BUTTON_DEFAULT|FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT, 0, 0, 0, 0, 10, 10, 2, 2);
3324 
3325     if(banDialog.execute(PLACEMENT_CURSOR))
3326     {
3327         m_engine->sendMode(getText()+" +b "+banEdit->getText());
3328     }
3329     return 1;
3330 }
3331 
onKickban(FXObject *,FXSelector,void *)3332 long IrcTabItem::onKickban(FXObject *, FXSelector, void *)
3333 {
3334     FXDialogBox banDialog(this, _("Kick/Ban dialog"), DECOR_TITLE|DECOR_BORDER, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
3335     FXVerticalFrame *contents = new FXVerticalFrame(&banDialog, LAYOUT_SIDE_LEFT|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0, 0, 0, 0, 10, 10, 10, 10, 0, 0);
3336 
3337     FXHorizontalFrame *kickframe = new FXHorizontalFrame(contents, LAYOUT_FILL_X|LAYOUT_FILL_Y);
3338     new FXLabel(kickframe, _("Kick reason:"), 0, JUSTIFY_LEFT|LAYOUT_FILL_X|LAYOUT_FILL_Y);
3339     FXTextField *reasonEdit = new FXTextField(kickframe, 25, NULL, 0, FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
3340 
3341     FXHorizontalFrame *banframe = new FXHorizontalFrame(contents, LAYOUT_FILL_X|LAYOUT_FILL_Y);
3342     new FXLabel(banframe, _("Banmask:"), 0, JUSTIFY_LEFT|LAYOUT_FILL_X|LAYOUT_FILL_Y);
3343     FXTextField *banEdit = new FXTextField(banframe, 25, NULL, 0, FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
3344     banEdit->setText(m_nickOnRight.nick+"!"+m_nickOnRight.user+"@"+m_nickOnRight.host);
3345 
3346     FXHorizontalFrame *buttonframe = new FXHorizontalFrame(contents, LAYOUT_FILL_X|LAYOUT_FILL_Y|PACK_UNIFORM_WIDTH);
3347     new dxEXButton(buttonframe, _("&Cancel"), NULL, &banDialog, FXDialogBox::ID_CANCEL, FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT, 0, 0, 0, 0, 10, 10, 2, 2);
3348     new dxEXButton(buttonframe, _("&OK"), NULL, &banDialog, FXDialogBox::ID_ACCEPT, BUTTON_INITIAL|BUTTON_DEFAULT|FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT, 0, 0, 0, 0, 10, 10, 2, 2);
3349 
3350     if(banDialog.execute(PLACEMENT_CURSOR))
3351     {
3352         m_engine->sendKick(getText(), m_nickOnRight.nick, reasonEdit->getText());
3353         m_engine->sendMode(getText()+" +b "+banEdit->getText());
3354     }
3355     return 1;
3356 }
3357 
3358 //handle popup Ignore
onIgnore(FXObject *,FXSelector,void *)3359 long IrcTabItem::onIgnore(FXObject*, FXSelector, void*)
3360 {
3361     FXDialogBox dialog(this, _("Add ignore user"), DECOR_TITLE|DECOR_BORDER, 0,0,0,0, 0,0,0,0, 0,0);
3362     FXVerticalFrame *contents = new FXVerticalFrame(&dialog, LAYOUT_SIDE_LEFT|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0,0,0,0, 10,10,10,10, 0,0);
3363     FXMatrix *matrix = new FXMatrix(contents,2,MATRIX_BY_COLUMNS|LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y);
3364 
3365     new FXLabel(matrix, _("Nick:"), NULL, JUSTIFY_LEFT|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
3366     FXTextField *nick = new FXTextField(matrix, 25, NULL, 0, FRAME_THICK|FRAME_SUNKEN|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
3367     nick->setText(m_nickOnRight.nick+"!"+m_nickOnRight.user+"@"+m_nickOnRight.host);
3368     new FXLabel(matrix, _("Channel(s):\tChannels need to be comma separated"), NULL,JUSTIFY_LEFT|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
3369     FXTextField *channel = new FXTextField(matrix, 25, NULL, 0, FRAME_THICK|FRAME_SUNKEN|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
3370     channel->setText(getText());
3371     channel->setTipText(_("Channels need to be comma separated"));
3372     new FXLabel(matrix, _("Server:"), NULL,JUSTIFY_LEFT|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
3373     FXTextField *server = new FXTextField(matrix, 25, NULL, 0, FRAME_THICK|FRAME_SUNKEN|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
3374     server->setText(getServerName());
3375 
3376     FXHorizontalFrame *buttonframe = new FXHorizontalFrame(contents,LAYOUT_FILL_X|LAYOUT_FILL_Y|PACK_UNIFORM_WIDTH);
3377     new dxEXButton(buttonframe, _("&Cancel"), NULL, &dialog, FXDialogBox::ID_CANCEL, FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT, 0,0,0,0, 10,10,2,2);
3378     new dxEXButton(buttonframe, _("&OK"), NULL, &dialog, FXDialogBox::ID_ACCEPT, BUTTON_INITIAL|BUTTON_DEFAULT|FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT, 0,0,0,0, 10,10,2,2);
3379 
3380     if(dialog.execute(PLACEMENT_CURSOR))
3381     {
3382         FXString ignoretext = nick->getText()+" "+channel->getText()+" "+server->getText();
3383         m_parent->getParent()->getParent()->handle(this, FXSEL(SEL_COMMAND, IrcTabItem_ADDIUSER), &ignoretext);
3384     }
3385     return 1;
3386 }
3387 
3388 //handle IrcTabItem_AWAY
onSetAway(FXObject *,FXSelector,void *)3389 long IrcTabItem::onSetAway(FXObject*, FXSelector, void*)
3390 {
3391     FXDialogBox awayDialog(this, _("Away dialog"), DECOR_TITLE|DECOR_BORDER, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
3392     FXVerticalFrame *contents = new FXVerticalFrame(&awayDialog, LAYOUT_SIDE_LEFT|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0, 0, 0, 0, 10, 10, 10, 10, 0, 0);
3393 
3394     FXHorizontalFrame *msgframe = new FXHorizontalFrame(contents, LAYOUT_FILL_X|LAYOUT_FILL_Y);
3395     new FXLabel(msgframe, _("Message:"), 0, JUSTIFY_LEFT|LAYOUT_FILL_X|LAYOUT_FILL_Y);
3396     FXTextField *msgEdit = new FXTextField(msgframe, 25, NULL, 0, FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
3397     msgEdit->setText(_("away"));
3398 
3399     FXHorizontalFrame *buttonframe = new FXHorizontalFrame(contents, LAYOUT_FILL_X|LAYOUT_FILL_Y|PACK_UNIFORM_WIDTH);
3400     new dxEXButton(buttonframe, _("&Cancel"), NULL, &awayDialog, FXDialogBox::ID_CANCEL, FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT, 0, 0, 0, 0, 10, 10, 2, 2);
3401     new dxEXButton(buttonframe, _("&OK"), NULL, &awayDialog, FXDialogBox::ID_ACCEPT, BUTTON_INITIAL|BUTTON_DEFAULT|FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT, 0, 0, 0, 0, 10, 10, 2, 2);
3402 
3403     if(awayDialog.execute(PLACEMENT_CURSOR))
3404     {
3405         m_engine->sendAway(msgEdit->getText().empty() ? _("away"): msgEdit->getText());
3406     }
3407     return 1;
3408 }
3409 
3410 //handle IrcTabItem_DEAWAY
onRemoveAway(FXObject *,FXSelector,void *)3411 long IrcTabItem::onRemoveAway(FXObject*, FXSelector, void*)
3412 {
3413     m_engine->sendAway("");
3414     return 1;
3415 }
3416 
3417 //handle change in spellLang combobox
onSpellLang(FXObject *,FXSelector,void *)3418 long IrcTabItem::onSpellLang(FXObject*, FXSelector, void*)
3419 {
3420     m_commandline->setLanguage(m_spellLangs->getItemText(m_spellLangs->getCurrentItem()));
3421     m_commandline->setTipText(FXStringFormat(_("Current spellchecking language: %s"),m_spellLangs->getItemText(m_spellLangs->getCurrentItem()).text()));
3422     return 1;
3423 }
3424 
3425 //handle LogThread_LIST
onListLogThread(FXObject *,FXSelector,void *)3426 long IrcTabItem::onListLogThread(FXObject*, FXSelector, void*)
3427 {
3428     dxStringArray files = m_logThread->getResult();
3429     if(!files.no())
3430     {
3431         appendIrcStyledText(FXStringFormat(_("No log files for %s-%s."), m_engine->getNetworkName().text(), getText().text()), 4, FXSystem::now(), FALSE, FALSE);
3432         return 1;
3433     }
3434     appendIrcStyledText(_("Log files:"), 7, FXSystem::now(), FALSE, FALSE);
3435     FXString lastYear = dxutils::getParam(files[0], 1, FALSE, '-');
3436     FXint lastMonth = FXIntVal(dxutils::getParam(files[0], 2, FALSE, '-'));
3437     appendIrcStyledText(FXStringFormat("%s:", lastYear.text()), 5, FXSystem::now(), FALSE, FALSE);
3438     appendIrcStyledText(FXStringFormat("%s:", dxutils::getMonth(lastMonth).text()), 5, FXSystem::now(), FALSE, FALSE);
3439     FXString list = "";
3440     for(FXint i=0; i<files.no(); i++)
3441     {
3442         if(lastYear!=dxutils::getParam(files[i], 1, FALSE, '-'))
3443         {
3444             lastYear = dxutils::getParam(files[i], 1, FALSE, '-');
3445             lastMonth = FXIntVal(dxutils::getParam(files[i], 2, FALSE, '-'));
3446             appendIrcText(list.rbefore(','), FXSystem::now(), FALSE, FALSE);
3447             appendIrcStyledText(FXStringFormat("%s:", lastYear.text()), 5, FXSystem::now(), FALSE, FALSE);
3448             appendIrcStyledText(FXStringFormat("%s:", dxutils::getMonth(lastMonth).text()), 5, FXSystem::now(), FALSE, FALSE);
3449             list.clear();
3450             list.append(dxutils::getParam(files[i], 3, FALSE, '-')+", ");
3451         }
3452         else if(lastMonth!=FXIntVal(dxutils::getParam(files[i], 2, FALSE, '-')))
3453         {
3454             lastMonth = FXIntVal(dxutils::getParam(files[i], 2, FALSE, '-'));
3455             appendIrcText(list.rbefore(','), FXSystem::now(), FALSE, FALSE);
3456             appendIrcStyledText(FXStringFormat("%s:", dxutils::getMonth(lastMonth).text()), 5, FXSystem::now(), FALSE, FALSE);
3457             list.clear();
3458             list.append(dxutils::getParam(files[i], 3, FALSE, '-')+", ");
3459         }
3460         else list.append(dxutils::getParam(files[i], 3, FALSE, '-')+", ");
3461     }
3462     if(!list.empty()) appendIrcText(list.rbefore(','), FXSystem::now(), FALSE, FALSE);
3463     return 1;
3464 }
3465 
3466 //handle LogThread_LINES
onLinesLogThread(FXObject *,FXSelector,void *)3467 long IrcTabItem::onLinesLogThread(FXObject*, FXSelector, void*)
3468 {
3469     m_loadLog = FALSE;
3470     clearChat();
3471     dxStringArray lines = m_logThread->getResult();
3472     for(FXint i=0; i<lines.no(); i++)
3473     {
3474         if(lines[i].after(']')[1]=='\014') //log style mark
3475         {
3476             if(lines[i].after('\014',2)[0]=='<') //has nick
3477             {
3478                 m_text->appendStyledText(lines[i].before('\014'), 11); //timestamp
3479                 FXString nick = lines[i].after('<').before('>');
3480                 m_text->appendStyledText(nick+":", getNickStyle(nick));
3481                 appendLinkText(dxutils::stripColors(lines[i].after('>'), TRUE), 11);
3482             }
3483             else appendLinkText(dxutils::stripLogMark(dxutils::stripColors(lines[i], TRUE)), 11);
3484         }
3485         else
3486         {
3487             if(lines[i].after(']')[1]=='<') //has nick
3488             {
3489                 m_text->appendStyledText(lines[i].before('<'), 11); //timestamp
3490                 FXString nick = lines[i].after('<').before('>');
3491                 m_text->appendStyledText(nick+":", getNickStyle(nick));
3492                 appendLinkText(dxutils::stripColors(lines[i].after('>'), TRUE), 11);
3493             }
3494             else appendLinkText(dxutils::stripColors(lines[i], TRUE), 11);
3495         }
3496     }
3497     while(m_storedEvents.no())
3498     {
3499         parseIrcEvent(m_storedEvents[0]);
3500         m_storedEvents.erase(0);
3501     }
3502     return 1;
3503 }
3504 
onTopic(FXObject *,FXSelector,void *)3505 long IrcTabItem::onTopic(FXObject*, FXSelector, void*)
3506 {
3507     if(m_editableTopic || m_iamOp)
3508     {
3509         if(m_topicline->getText().length() > m_engine->getTopicLen())
3510         {
3511             appendIrcStyledText(FXStringFormat(_("Warning: topic is too long. Max. topic length is %d."), m_engine->getTopicLen()), 4, FXSystem::now(), FALSE, FALSE);
3512             m_engine->sendTopic(getText(), m_topicline->getText());
3513             return 1;
3514         }
3515         m_engine->sendTopic(getText(), m_topicline->getText());
3516     }
3517     else
3518     {
3519         m_topicline->setText(m_topic);
3520         m_topicline->setCursorPos(0);
3521         m_topicline->makePositionVisible(0);
3522     }
3523     return 1;
3524 }
3525 
onTopicLink(FXObject *,FXSelector,void * data)3526 long IrcTabItem::onTopicLink(FXObject*, FXSelector, void *data)
3527 {
3528     dxutils::launchLink(static_cast<FXchar*>(data));
3529     return 1;
3530 }
3531 
onBan(const FXString & banmask,const FXbool & sign,const FXString & sender,const FXTime & time)3532 void IrcTabItem::onBan(const FXString &banmask, const FXbool &sign, const FXString &sender, const FXTime &time)
3533 {
3534     if(sign)
3535     {
3536         FXString nicks = m_engine->getBannedNick(banmask);
3537         FXString myNick = getNickName();
3538         while(nicks.contains(';'))
3539         {
3540             for(FXint i=m_users->getNumItems()-1; i>-1; i--)
3541             {
3542                 if(nicks.before(';') == m_users->getItemText(i))
3543                 {
3544                     if(m_users->getItemText(i) == myNick) appendIrcStyledText(FXStringFormat(_("You was banned by %s"), sender.text()), 1, time, FALSE, FALSE);
3545                     else
3546                     {
3547                         if(!isCommandIgnored("ban") && !m_engine->isUserIgnored(m_users->getItemText(i), getText())) appendIrcStyledText(FXStringFormat(_("%s was banned by %s"), m_users->getItemText(i).text(), sender.text()), 1, time, FALSE, FALSE);
3548                         //RemoveUser(users->getItemText(i));
3549                     }
3550                 }
3551             }
3552             nicks = nicks.after(';');
3553         }
3554     }
3555 }
3556 
getNick(FXint i)3557 FXString IrcTabItem::getNick(FXint i)
3558 {
3559     if(m_users->getNumItems()) return m_users->getItemText(i);
3560     return "";
3561 }
3562 
getNickStyle(const FXString & nick)3563 FXint IrcTabItem::getNickStyle(const FXString &nick)
3564 {
3565     if(preferences.m_coloredNick) return 12+nick.hash()%8; //12 is first colored nick style
3566     return 5; //bold
3567 }
3568 
hiliteStyleExist(FXColor foreColor,FXColor backColor,FXuint style)3569 FXint IrcTabItem::hiliteStyleExist(FXColor foreColor, FXColor backColor, FXuint style)
3570 {
3571     for(FXint i=0; i<m_textStyleList.no(); i++)
3572     {
3573         if(m_textStyleList[i].normalForeColor == foreColor
3574                 && m_textStyleList[i].normalBackColor == backColor
3575                 && m_textStyleList[i].style == style)
3576             return i+1;
3577     }
3578     return -1;
3579 }
3580 
createHiliteStyle(FXColor foreColor,FXColor backColor,FXuint style)3581 void IrcTabItem::createHiliteStyle(FXColor foreColor, FXColor backColor, FXuint style)
3582 {
3583     dxHiliteStyle nstyle = {foreColor,backColor,getApp()->getSelforeColor(),getApp()->getSelbackColor(),style,FALSE};
3584     m_textStyleList.append(nstyle);
3585     m_text->setHiliteStyles(m_textStyleList.data());
3586 }
3587 
cutText(FXString text,FXint len)3588 dxStringArray IrcTabItem::cutText(FXString text, FXint len)
3589 {
3590     FXint previous = 0;
3591     FXint s = -1;
3592     FXint lw = 0;
3593     dxStringArray texts;
3594     for(FXint i = 0; i<text.length(); i++)
3595     {
3596         if(text[i] == ' ') s = i;
3597         if(lw>len)
3598         {
3599             if(s!=-1)
3600             {
3601                 texts.append(text.mid(previous, s));
3602                 i = s+1;
3603                 s = -1;
3604                 previous = i;
3605             }
3606             else
3607             {
3608                 texts.append(text.mid(previous, lw));
3609                 previous = previous+lw;
3610             }
3611             lw = 0;
3612         }
3613         lw++;
3614     }
3615     if(previous<text.length()) texts.append(text.right(text.length()-previous));
3616     return texts;
3617 }
3618 
setCommandFocus()3619 void IrcTabItem::setCommandFocus()
3620 {
3621     m_commandline->setFocus();
3622 }
3623 
3624 //for "handle" checking, if script contains "all". Send from dxirc.
setHasAllCommand(FXbool hasAll)3625 void IrcTabItem::setHasAllCommand(FXbool hasAll)
3626 {
3627     m_scriptHasAll = hasAll;
3628 }
3629 
3630 //for "handle" checking, if script contains "ownmsg". Send from dxirc.
setHasOwnMsg(FXbool hasOwn)3631 void IrcTabItem::setHasOwnMsg(FXbool hasOwn)
3632 {
3633     m_scriptHasOwnMsg = hasOwn;
3634 }
3635 
3636 //check need of highlight in msg
highlightNeeded(const FXString & msg)3637 FXbool IrcTabItem::highlightNeeded(const FXString &msg)
3638 {
3639     FXint pos = msg.find(getNickName());
3640     if(pos==-1) return FALSE;
3641     FXbool before = TRUE;
3642     FXbool after = FALSE;
3643     if(pos) before = isDelimiter(msg[pos-1]);
3644     if(pos+getNickName().length() == msg.length()) after = TRUE;
3645     if(pos+getNickName().length() < msg.length()) after = isDelimiter(msg[pos+getNickName().length()]);
3646     return before && after;
3647 }
3648 
3649 //Load lines from logs
loadLogLines()3650 void IrcTabItem::loadLogLines()
3651 {
3652     if(m_type != CHANNEL && m_type != QUERY)
3653         return;
3654     if(!m_engine)
3655         return;
3656     if(!preferences.m_loadLog)
3657         return;
3658     if(m_logThread->running())
3659     {
3660         appendStyledText(_("Thread running, try again after some seconds"), 7, false, false, false);
3661         return;
3662     }
3663     appendIrcStyledText(_("Loading log..."), 11, FXSystem::now(), FALSE, FALSE);
3664     m_loadLog = TRUE;
3665     m_logThread->setList(false);
3666     m_logThread->setDirectory(preferences.m_logPath+PATHSEPSTRING+m_engine->getNetworkName()+PATHSEPSTRING+getText());
3667     m_logThread->start();
3668 }
3669 
3670 //List log files for tab
listLogFiles()3671 void IrcTabItem::listLogFiles()
3672 {
3673     if(m_logThread->running())
3674     {
3675         appendStyledText(_("Thread running, try again after some seconds"), 7, false, false, false);
3676         return;
3677     }
3678     m_logThread->setList(true);
3679     m_logThread->setDirectory(preferences.m_logPath+PATHSEPSTRING+m_engine->getNetworkName()+PATHSEPSTRING+getText());
3680     m_logThread->start();
3681 }
3682 
showLog(const FXString & path)3683 void IrcTabItem::showLog(const FXString& path)
3684 {
3685     if(FXStat::exists(path))
3686     {
3687         FXString name = FXPath::name(path);
3688         clearChat();
3689         appendStyledText(FXStringFormat(_("Log from %s:"), name.text()), 7, FALSE, FALSE, FALSE);
3690         std::ifstream file(path.text());
3691         std::string line;
3692         FXString fxline;
3693         while(getline(file, line))
3694         {
3695             fxline = line.c_str();
3696             if(fxline.length()>12 && fxline[11]=='\014') //log style mark
3697             {
3698                 FXint style = FXIntVal(fxline.after('\014').before('\014'));
3699                 m_text->appendText(fxline.before('\014'));
3700                 if(fxline.after('\014',2)[0]=='<') //has nick
3701                 {
3702                     FXString nick = fxline.after('<').before('>');
3703                     FXString msg = fxline.after('>');
3704                     appendLinkText(nick+":"+msg, style);
3705                 }
3706                 else appendLinkText(fxline.after('\014', 2), style);
3707             }
3708             else
3709             {
3710                 if(fxline.length()>12 && fxline[11]=='<') //line with nick
3711                 {
3712                     m_text->appendText(fxline.before('<'));
3713                     FXString nick = fxline.after('<').before('>');
3714                     FXString msg = fxline.after('>').trimBegin();
3715                     m_text->appendStyledText(nick+": ", getNickStyle(nick));
3716                     if(preferences.m_stripColors) msg = dxutils::stripColors(msg, FALSE);
3717                     appendLinkText(msg, 0);
3718                 }
3719                 else appendIrcText(fxline, 0, FALSE, FALSE);
3720             }
3721         }
3722         file.close();
3723     }
3724     else
3725     {
3726         appendStyledText(FXStringFormat(_("'%s' path doesn't exist"), path.text()), 4, false, false, false);
3727     }
3728 }
3729 
completeHelpCommand()3730 void IrcTabItem::completeHelpCommand()
3731 {
3732     FXString line = m_commandline->getText();
3733     for(FXint i = 0; i < dxUtils.commandsNo(); i++)
3734     {
3735         if(comparecase(line.after(' '), dxUtils.commandsAt(i)) == 0)
3736         {
3737             if((i+1) < dxUtils.commandsNo()) m_commandline->setText("/HELP "+dxUtils.commandsAt(++i));
3738             else m_commandline->setText("/HELP "+dxUtils.commandsAt(0));
3739             break;
3740         }
3741         else if(comparecase(line.after(' '), dxUtils.commandsAt(i).left(line.after(' ').length())) == 0)
3742         {
3743             m_commandline->setText("/HELP "+dxUtils.commandsAt(i));
3744             break;
3745         }
3746     }
3747 }
3748 
commandScript(const FXString & commandtext)3749 FXbool IrcTabItem::commandScript(const FXString &commandtext)
3750 {
3751     LuaRequest lua;
3752     lua.type = LUA_COMMAND;
3753     lua.text = commandtext.after('/');
3754     m_parent->getParent()->getParent()->handle(this, FXSEL(SEL_COMMAND, IrcTabItem_LUA), &lua);
3755     return TRUE;
3756 }
3757 
commandAdmin(const FXString & commandtext)3758 FXbool IrcTabItem::commandAdmin(const FXString &commandtext)
3759 {
3760     if(m_engine->getConnected())
3761     {
3762         return m_engine->sendAdmin(commandtext.after(' '));
3763     }
3764     else
3765     {
3766         return notConnected();
3767     }
3768 }
3769 
commandAway(const FXString & commandtext)3770 FXbool IrcTabItem::commandAway(const FXString &commandtext)
3771 {
3772     if(m_engine->getConnected())
3773     {
3774         if(commandtext.after(' ').length() > m_engine->getAwayLen())
3775         {
3776             appendIrcStyledText(FXStringFormat(_("Warning: Away message is too long. Max. away message length is %d."), m_engine->getAwayLen()), 4, FXSystem::now(), FALSE, FALSE);
3777         }
3778         return m_engine->sendAway(commandtext.after(' '));
3779     }
3780     else
3781     {
3782         return notConnected();
3783     }
3784 }
3785 
commandBanlist(const FXString & commandtext)3786 FXbool IrcTabItem::commandBanlist(const FXString &commandtext)
3787 {
3788     if(m_engine->getConnected())
3789     {
3790         FXString channel = commandtext.after(' ');
3791         if(channel.empty() && m_type == CHANNEL)
3792         {
3793             return m_engine->sendBanlist(getText());
3794         }
3795         else if(!isChannel(channel) && m_type != CHANNEL)
3796         {
3797             appendIrcStyledText(_("/banlist <channel>, shows banlist for channel."), 4, FXSystem::now(), FALSE, FALSE);
3798             return FALSE;
3799         }
3800         else
3801         {
3802             return m_engine->sendBanlist(channel);
3803         }
3804     }
3805     else
3806     {
3807         return notConnected();
3808     }
3809 }
3810 
commandBoats(const FXString & commandtext)3811 FXbool IrcTabItem::commandBoats(const FXString &commandtext)
3812 {
3813     if(m_engine->getConnected())
3814     {
3815         FXString to = commandtext.after(' ');
3816         if(to.empty())
3817         {
3818             appendIrcStyledText(_("/boats <nick>, invites someone to a boats game."), 4, FXSystem::now(), FALSE, FALSE);
3819             return FALSE;
3820         }
3821         else
3822         {
3823             return m_engine->sendCtcp(to, "BOATS INVITE");
3824         }
3825     }
3826     else
3827     {
3828         return notConnected();
3829     }
3830 }
3831 
commandConnect(const FXString & commandtext)3832 FXbool IrcTabItem::commandConnect(const FXString &commandtext)
3833 {
3834     if(commandtext.after(' ').empty())
3835     {
3836         appendIrcStyledText(_("/connect <server> [port] [nick] [password] [realname] [channels], connects for given server."), 4, FXSystem::now(), FALSE, FALSE);
3837         return FALSE;
3838     }
3839     else
3840     {
3841         ServerInfo srv;
3842         srv.hostname = commandtext.after(' ').section(' ', 0);
3843         srv.port = commandtext.after(' ').section(' ', 1).empty() ? 6667 : FXIntVal(commandtext.after(' ').section(' ', 1));
3844         srv.nick = commandtext.after(' ').section(' ', 2).empty() ? FXSystem::currentUserName() : commandtext.after(' ').section(' ', 2);
3845         srv.passwd = commandtext.after(' ').section(' ', 3).empty() ? "" : commandtext.after(' ').section(' ', 3);
3846         srv.realname = commandtext.after(' ').section(' ', 4).empty() ? FXSystem::currentUserName() : commandtext.after(' ').section(' ', 4);
3847         srv.channels = commandtext.after(' ').section(' ', 5).empty() ? "" : commandtext.after(' ').section(' ', 5);
3848         m_parent->getParent()->getParent()->handle(this, FXSEL(SEL_COMMAND, IrcTabItem_CSERVER), &srv);
3849         return TRUE;
3850     }
3851 }
3852 
commandCommands()3853 FXbool IrcTabItem::commandCommands()
3854 {
3855     appendIrcStyledText(dxUtils.availableCommands(), 3, FXSystem::now(), FALSE, FALSE);
3856     return TRUE;
3857 }
3858 
commandCtcp(const FXString & commandtext)3859 FXbool IrcTabItem::commandCtcp(const FXString &commandtext)
3860 {
3861     if(m_engine->getConnected())
3862     {
3863         FXString to = commandtext.after(' ').before(' ');
3864         FXString msg = commandtext.after(' ', 2);
3865         if(to.empty() || msg.empty())
3866         {
3867             appendIrcStyledText(_("/ctcp <nick> <message>, sends a CTCP message to a user."), 4, FXSystem::now(), FALSE, FALSE);
3868             return FALSE;
3869         }
3870         if(msg.length() > m_maxLen-12-to.length())
3871         {
3872             appendIrcStyledText(FXStringFormat(_("Warning: ctcp message is too long. Max. ctcp message length is %d."), m_maxLen-12-to.length()), 4, FXSystem::now(), FALSE, FALSE);
3873         }
3874         return m_engine->sendCtcp(to, msg);
3875     }
3876     else
3877     {
3878         return notConnected();
3879     }
3880 }
3881 
commandCycle(const FXString & commandtext)3882 FXbool IrcTabItem::commandCycle(const FXString &commandtext)
3883 {
3884     if(m_engine->getConnected())
3885     {
3886         if(m_type == CHANNEL)
3887         {
3888             if(isChannel(commandtext.after(' ')))
3889             {
3890                 FXString channel = commandtext.after(' ').before(' ');
3891                 FXString reason = commandtext.after(' ', 2);
3892                 reason.empty() ? m_engine->sendPart(channel) : m_engine->sendPart(channel, reason);
3893                 return m_engine->sendJoin(channel);
3894             }
3895             else
3896             {
3897                 commandtext.after(' ').empty() ? m_engine->sendPart(getText()) : m_engine->sendPart(getText(), commandtext.after(' '));
3898                 return m_engine->sendJoin(getText());
3899             }
3900         }
3901         else
3902         {
3903             if(isChannel(commandtext.after(' ')))
3904             {
3905                 FXString channel = commandtext.after(' ').before(' ');
3906                 FXString reason = commandtext.after(' ', 2);
3907                 reason.empty() ? m_engine->sendPart(channel) : m_engine->sendPart(channel, reason);
3908                 return m_engine->sendJoin(channel);
3909             }
3910             else
3911             {
3912                 appendIrcStyledText(_("/cycle <channel> [message], leaves and join channel."), 4, FXSystem::now(), FALSE, FALSE);
3913                 return FALSE;
3914             }
3915         }
3916     }
3917     else
3918     {
3919         return notConnected();
3920     }
3921 }
3922 
commandDcc(const FXString & commandtext)3923 FXbool IrcTabItem::commandDcc(const FXString &commandtext)
3924 {
3925     if(m_engine->getConnected())
3926     {
3927         FXString dccCommand = dxutils::getParam(commandtext, 2, FALSE).lower();
3928         if(dccCommand == "chat")
3929         {
3930             FXString nick = dxutils::getParam(commandtext, 3, FALSE);
3931             if(!comparecase(nick, "chat"))
3932             {
3933                 appendIrcStyledText(_("Nick for chat wasn't entered."), 4, FXSystem::now(), FALSE, FALSE);
3934                 return FALSE;
3935             }
3936             if(!comparecase(nick, getNickName()))
3937             {
3938                 appendIrcStyledText(_("Chat with yourself isn't good idea."), 4, FXSystem::now(), FALSE, FALSE);
3939                 return FALSE;
3940             }
3941             IrcEvent ev;
3942             ev.eventType = IRC_DCCSERVER;
3943             ev.param1 = nick;
3944             m_parent->getParent()->getParent()->handle(m_engine, FXSEL(SEL_COMMAND, IrcEngine_SERVER), &ev);
3945             return TRUE;
3946         }
3947         else if(dccCommand == "send")
3948         {
3949             FXString nick = dxutils::getParam(commandtext, 3, FALSE);
3950             FXString file = dxutils::getParam(commandtext, 4, TRUE);
3951             if(!comparecase(nick, "send"))
3952             {
3953                 appendIrcStyledText(_("Nick for sending file wasn't entered."), 4, FXSystem::now(), FALSE, FALSE);
3954                 return FALSE;
3955             }
3956             if(!comparecase(nick, getNickName()))
3957             {
3958                 appendIrcStyledText(_("Sending to yourself isn't good idea."), 4, FXSystem::now(), FALSE, FALSE);
3959                 return FALSE;
3960             }
3961             if(!comparecase(nick, file))
3962             {
3963                 appendIrcStyledText(_("Filename wasn't entered"), 4, FXSystem::now(), FALSE, FALSE);
3964                 return FALSE;
3965             }
3966             if(!FXStat::exists(file))
3967             {
3968                 appendIrcStyledText(FXStringFormat(_("File '%s' doesn't exist"), file.text()), 4, FXSystem::now(), FALSE, FALSE);
3969                 return FALSE;
3970             }
3971             IrcEvent ev;
3972             ev.eventType = IRC_DCCOUT;
3973             ev.param1 = nick;
3974             ev.param2 = file;
3975             m_parent->getParent()->getParent()->handle(m_engine, FXSEL(SEL_COMMAND, IrcEngine_SERVER), &ev);
3976             return TRUE;
3977         }
3978         else if(dccCommand == "psend")
3979         {
3980             FXString nick = dxutils::getParam(commandtext, 3, FALSE);
3981             FXString file = dxutils::getParam(commandtext, 4, TRUE);
3982             if(!comparecase(nick, "psend"))
3983             {
3984                 appendIrcStyledText(_("Nick for sending file wasn't entered."), 4, FXSystem::now(), FALSE, FALSE);
3985                 return FALSE;
3986             }
3987             if(!comparecase(nick, getNickName()))
3988             {
3989                 appendIrcStyledText(_("Sending to yourself isn't good idea."), 4, FXSystem::now(), FALSE, FALSE);
3990                 return FALSE;
3991             }
3992             if(!comparecase(nick, file))
3993             {
3994                 appendIrcStyledText(_("Filename wasn't entered"), 4, FXSystem::now(), FALSE, FALSE);
3995                 return FALSE;
3996             }
3997             if(!FXStat::exists(file))
3998             {
3999                 appendIrcStyledText(FXStringFormat(_("File '%s' doesn't exist"), file.text()), 4, FXSystem::now(), FALSE, FALSE);
4000                 return FALSE;
4001             }
4002             IrcEvent ev;
4003             ev.eventType = IRC_DCCPOUT;
4004             ev.param1 = nick;
4005             ev.param2 = file;
4006             m_parent->getParent()->getParent()->handle(m_engine, FXSEL(SEL_COMMAND, IrcEngine_SERVER), &ev);
4007             return TRUE;
4008         }
4009         else
4010         {
4011             appendIrcStyledText(FXStringFormat(_("'%s' isn't dcc command <chat|send|psend>"), dccCommand.text()), 4, FXSystem::now(), FALSE, FALSE);
4012             return FALSE;
4013         }
4014     }
4015     else
4016     {
4017         return notConnected();
4018     }
4019 }
4020 
commandDeop(const FXString & commandtext)4021 FXbool IrcTabItem::commandDeop(const FXString &commandtext)
4022 {
4023     if(m_engine->getConnected())
4024     {
4025         FXString params = commandtext.after(' ');
4026         if(m_type == CHANNEL)
4027         {
4028             if(params.empty())
4029             {
4030                 appendIrcStyledText(_("/deop <nicks>, removes operator status from one or more nicks."), 4, FXSystem::now(), FALSE, FALSE);
4031                 return FALSE;
4032             }
4033             else if(isChannel(params) && params.after(' ').empty())
4034             {
4035                 appendIrcStyledText(_("/deop <channel> <nicks>, removes operator status from one or more nicks."), 4, FXSystem::now(), FALSE, FALSE);
4036                 return FALSE;
4037             }
4038             else if(isChannel(params) && !params.after(' ').empty())
4039             {
4040                 FXString channel = params.before(' ');
4041                 FXString nicks = params.after(' ');
4042                 FXString modeparams = dxutils::createModes('-', 'o', nicks);
4043                 return m_engine->sendMode(channel+" "+modeparams);
4044             }
4045             else
4046             {
4047                 FXString channel = getText();
4048                 FXString nicks = params;
4049                 FXString modeparams = dxutils::createModes('-', 'o', nicks);
4050                 return m_engine->sendMode(channel+" "+modeparams);
4051             }
4052         }
4053         else
4054         {
4055             if(isChannel(params) && !params.after(' ').empty())
4056             {
4057                 FXString channel = params.before(' ');
4058                 FXString nicks = params.after(' ');
4059                 FXString modeparams = dxutils::createModes('-', 'o', nicks);
4060                 return m_engine->sendMode(channel+" "+modeparams);
4061             }
4062             else
4063             {
4064                 appendIrcStyledText(_("/deop <channel> <nicks>, removes operator status from one or more nicks."), 4, FXSystem::now(), FALSE, FALSE);
4065                 return FALSE;
4066             }
4067         }
4068     }
4069     else
4070     {
4071         return notConnected();
4072     }
4073 }
4074 
commandDevoice(const FXString & commandtext)4075 FXbool IrcTabItem::commandDevoice(const FXString &commandtext)
4076 {
4077     if(m_engine->getConnected())
4078     {
4079         FXString params = commandtext.after(' ');
4080         if(m_type == CHANNEL)
4081         {
4082             if(params.empty())
4083             {
4084                 appendIrcStyledText(_("/devoice <nicks>, removes voice from one or more nicks."), 4, FXSystem::now(), FALSE, FALSE);
4085                 return FALSE;
4086             }
4087             else if(isChannel(params) && params.after(' ').empty())
4088             {
4089                 appendIrcStyledText(_("/devoice <channel> <nicks>, removes voice from one or more nicks."), 4, FXSystem::now(), FALSE, FALSE);
4090                 return FALSE;
4091             }
4092             else if(isChannel(params) && !params.after(' ').empty())
4093             {
4094                 FXString channel = params.before(' ');
4095                 FXString nicks = params.after(' ');
4096                 FXString modeparams = dxutils::createModes('-', 'v', nicks);
4097                 return m_engine->sendMode(channel+" "+modeparams);
4098             }
4099             else
4100             {
4101                 FXString channel = getText();
4102                 FXString nicks = params;
4103                 FXString modeparams = dxutils::createModes('-', 'v', nicks);
4104                 return m_engine->sendMode(channel+" "+modeparams);
4105             }
4106         }
4107         else
4108         {
4109             if(isChannel(params) && !params.after(' ').empty())
4110             {
4111                 FXString channel = params.before(' ');
4112                 FXString nicks = params.after(' ');
4113                 FXString modeparams = dxutils::createModes('-', 'v', nicks);
4114                 return m_engine->sendMode(channel+" "+modeparams);
4115             }
4116             else
4117             {
4118                 appendIrcStyledText(_("/devoice <channel> <nicks>, removes voice from one or more nicks."), 4, FXSystem::now(), FALSE, FALSE);
4119                 return FALSE;
4120             }
4121         }
4122     }
4123     else
4124     {
4125         return notConnected();
4126     }
4127 }
4128 
commandDisconnect(const FXString & commandtext)4129 FXbool IrcTabItem::commandDisconnect(const FXString &commandtext)
4130 {
4131     if(m_engine->getConnected())
4132     {
4133         if(commandtext.after(' ').empty()) m_engine->disconnect();
4134         else m_engine->disconnect(commandtext.after(' '));
4135         return TRUE;
4136     }
4137     else
4138     {
4139         m_engine->closeConnection(TRUE);
4140         return TRUE;
4141     }
4142 }
4143 
commandDxirc()4144 FXbool IrcTabItem::commandDxirc()
4145 {
4146     for(FXint i=0; i<5+rand()%5; i++)
4147     {
4148         appendIrcText("", FXSystem::now(), FALSE, FALSE);
4149     }
4150     appendIrcText("     __  __         _", FXSystem::now(), FALSE, FALSE);
4151     appendIrcText("  _/__//__/|_      | |       _", FXSystem::now(), FALSE, FALSE);
4152     appendIrcText(" /_| |_| |/_/|   __| |__  __|_| _ _  ___", FXSystem::now(), FALSE, FALSE);
4153     appendIrcText(" |_   _   _|/   / _  |\\ \\/ /| || '_)/ __)", FXSystem::now(), FALSE, FALSE);
4154     appendIrcText(" /_| |_| |/_/| | (_| | |  | | || | | (__", FXSystem::now(), FALSE, FALSE);
4155     appendIrcText(" |_   _   _|/   \\____|/_/\\_\\|_||_|  \\___)", FXSystem::now(), FALSE, FALSE);
4156     appendIrcText("   |_|/|_|/     (c) 2008~ David Vachulka", FXSystem::now(), FALSE, FALSE);
4157     appendIrcText("   http://dxirc.org", FXSystem::now(), FALSE, FALSE);
4158     for(FXint i=0; i<5+rand()%5; i++)
4159     {
4160         appendIrcText("", FXSystem::now(), FALSE, FALSE);
4161     }
4162     return TRUE;
4163 }
4164 
commandEgg()4165 FXbool IrcTabItem::commandEgg()
4166 {
4167     m_text->clearText();
4168     m_text->appendStyledText(FXString("ahoj sem pan Vajíčko.\n"), 3);
4169     getApp()->addTimeout(this, IrcTabItem_ETIME, 1000);
4170     m_pics = 0;
4171     return TRUE;
4172 }
4173 
commandExec(const FXString & commandtext)4174 FXbool IrcTabItem::commandExec(const FXString &commandtext)
4175 {
4176     FXString params = commandtext.after(' ');
4177     if(params.empty())
4178     {
4179         appendIrcStyledText(_("/exec [-o|-c] <command>, executes command, -o sends output to channel/query, -c closes running command."), 4, FXSystem::now(), FALSE, FALSE);
4180         return FALSE;
4181     }
4182     else
4183     {
4184         if(!m_pipe) m_pipe = new dxPipe(getApp(), this);
4185         m_pipeStrings.clear();
4186         if(params.before(' ').contains("-o"))
4187         {
4188             m_sendPipe = TRUE;
4189             m_pipe->execCmd(params.after(' '));
4190         }
4191         else if(params.before(' ').contains("-c"))
4192         {
4193             m_sendPipe = FALSE;
4194             m_pipeStrings.clear();
4195             m_pipe->stopCmd();
4196         }
4197         else
4198         {
4199             m_sendPipe = FALSE;
4200             m_pipe->execCmd(params);
4201         }
4202         return TRUE;
4203     }
4204 }
4205 
commandHelp(const FXString & commandtext)4206 FXbool IrcTabItem::commandHelp(const FXString &commandtext)
4207 {
4208     return showHelp(commandtext.after(' ').lower().trim());
4209 }
4210 
commandIgnore(const FXString & commandtext)4211 FXbool IrcTabItem::commandIgnore(const FXString &commandtext)
4212 {
4213     FXString ignorecommand = commandtext.after(' ').before(' ');
4214     FXString ignoretext = commandtext.after(' ').after(' ');
4215     if(ignorecommand.empty())
4216     {
4217         appendIrcStyledText(_("/ignore <list|addcmd|rmcmd|addusr|rmusr> [command|user] [channel] [server]"), 4, FXSystem::now(), FALSE, FALSE);
4218         return FALSE;
4219     }
4220     if(comparecase(ignorecommand, "list")==0)
4221     {
4222         appendIrcStyledText(_("Ignored commands:"), 7, FXSystem::now(), FALSE, FALSE);
4223         if(preferences.m_ignoreCommandsList.empty()) appendIrcText(_("No ignored commands"), FXSystem::now(), FALSE, FALSE);
4224         else appendIrcText(preferences.m_ignoreCommandsList.rbefore(';'), FXSystem::now(), FALSE, FALSE);
4225         appendIrcStyledText(_("Ignored users:"), 7, FXSystem::now(), FALSE, FALSE);
4226         if(!preferences.m_ignoreUsersList.no()) appendIrcText(_("No ignored users"), FXSystem::now(), FALSE, FALSE);
4227         else
4228         {
4229             for(FXint i=0; i<preferences.m_ignoreUsersList.no(); i++)
4230             {
4231                 appendIrcText(FXStringFormat(_("%s on channel(s): %s and network: %s"), preferences.m_ignoreUsersList[i].nick.text(), preferences.m_ignoreUsersList[i].channel.text(), preferences.m_ignoreUsersList[i].network.text()), FXSystem::now(), FALSE, FALSE);
4232             }
4233         }
4234         return TRUE;
4235     }
4236     else if(comparecase(ignorecommand, "addcmd")==0)
4237     {
4238         if(ignoretext.empty())
4239         {
4240             appendIrcStyledText(_("/ignore addcmd <command>, adds command to ignored commands."), 4, FXSystem::now(), FALSE, FALSE);
4241             return FALSE;
4242         }
4243         m_parent->getParent()->getParent()->handle(this, FXSEL(SEL_COMMAND, IrcTabItem_ADDICOMMAND), &ignoretext);
4244         return TRUE;
4245     }
4246     else if(comparecase(ignorecommand, "rmcmd")==0)
4247     {
4248         if(ignoretext.empty())
4249         {
4250             appendIrcStyledText(_("/ignore rmcmd <command>, removes command from ignored commands."), 4, FXSystem::now(), FALSE, FALSE);
4251             return FALSE;
4252         }
4253         m_parent->getParent()->getParent()->handle(this, FXSEL(SEL_COMMAND, IrcTabItem_RMICOMMAND), &ignoretext);
4254         return TRUE;
4255     }
4256     else if(comparecase(ignorecommand, "addusr")==0)
4257     {
4258         if(ignoretext.empty())
4259         {
4260             appendIrcStyledText(_("/ignore addusr <user> [channel] [server], adds user to ignored users."), 4, FXSystem::now(), FALSE, FALSE);
4261             return FALSE;
4262         }
4263         m_parent->getParent()->getParent()->handle(this, FXSEL(SEL_COMMAND, IrcTabItem_ADDIUSER), &ignoretext);
4264         return TRUE;
4265     }
4266     else if(comparecase(ignorecommand, "rmusr")==0)
4267     {
4268         if(ignoretext.empty())
4269         {
4270             appendIrcStyledText(_("/ignore rmusr <user>, removes user from ignored users."), 4, FXSystem::now(), FALSE, FALSE);
4271             return FALSE;
4272         }
4273         m_parent->getParent()->getParent()->handle(this, FXSEL(SEL_COMMAND, IrcTabItem_RMIUSER), &ignoretext);
4274         return TRUE;
4275     }
4276     else
4277     {
4278         appendIrcStyledText(FXStringFormat(_("'%s' isn't <list|addcmd|rmcmd|addusr|rmusr>"), ignorecommand.text()), 4, FXSystem::now(), FALSE, FALSE);
4279         return FALSE;
4280     }
4281 }
4282 
commandInvite(const FXString & commandtext)4283 FXbool IrcTabItem::commandInvite(const FXString &commandtext)
4284 {
4285     if(m_engine->getConnected())
4286     {
4287         FXString params = commandtext.after(' ');
4288         if(params.empty())
4289         {
4290             appendIrcStyledText(_("/invite <nick> <channel>, invites someone to a channel."), 4, FXSystem::now(), FALSE, FALSE);
4291             return FALSE;
4292         }
4293         else if(isChannel(params) && params.after(' ').empty())
4294         {
4295             appendIrcStyledText(_("/invite <nick> <channel>, invites someone to a channel."), 4, FXSystem::now(), FALSE, FALSE);
4296             return FALSE;
4297         }
4298         else
4299         {
4300             FXString nick = params.before(' ');
4301             FXString channel = params.after(' ');
4302             return m_engine->sendInvite(nick, channel);
4303         }
4304     }
4305     else
4306     {
4307         return notConnected();
4308     }
4309 }
4310 
commandJoin(const FXString & commandtext)4311 FXbool IrcTabItem::commandJoin(const FXString &commandtext)
4312 {
4313     if(m_engine->getConnected())
4314     {
4315         FXString channel = commandtext.after(' ');
4316         if(!isChannel(channel))
4317         {
4318             appendIrcStyledText(_("/join <channel>, joins a channel."), 4, FXSystem::now(), FALSE, FALSE);
4319             appendIrcStyledText(FXStringFormat(_("'%c' isn't valid char for channel."), channel[0]), 4, FXSystem::now(), FALSE, FALSE);
4320             return FALSE;
4321         }
4322         else
4323         {
4324             return m_engine->sendJoin(channel);
4325         }
4326     }
4327     else
4328     {
4329         return notConnected();
4330     }
4331 }
4332 
commandKick(const FXString & commandtext)4333 FXbool IrcTabItem::commandKick(const FXString &commandtext)
4334 {
4335     if(m_engine->getConnected())
4336     {
4337         FXString params = commandtext.after(' ');
4338         if(m_type == CHANNEL)
4339         {
4340             if(params.empty())
4341             {
4342                 appendIrcStyledText(_("/kick <nick>, kicks a user from a channel."), 4, FXSystem::now(), FALSE, FALSE);
4343                 return FALSE;
4344             }
4345             else if(isChannel(params) && params.after(' ').empty())
4346             {
4347                 appendIrcStyledText(_("/kick <channel> <nick>, kicks a user from a channel."), 4, FXSystem::now(), FALSE, FALSE);
4348                 return FALSE;
4349             }
4350             else if(isChannel(params) && !params.after(' ').empty())
4351             {
4352                 FXString channel = params.before(' ');
4353                 FXString nick = params.after(' ');
4354                 FXString reason = params.after(' ', 2);
4355                 if(reason.length() > m_engine->getKickLen())
4356                 {
4357                     appendIrcStyledText(FXStringFormat(_("Warning: reason of kick is too long. Max. reason length is %d."), m_engine->getKickLen()), 4, FXSystem::now(), FALSE, FALSE);
4358                     return m_engine->sendKick(channel, nick, reason);
4359                 }
4360                 else return m_engine->sendKick(channel, nick, reason);
4361             }
4362             else
4363             {
4364                 FXString channel = getText();
4365                 FXString nick = params.before(' ');
4366                 FXString reason = params.after(' ');
4367                 if(reason.length() > m_engine->getKickLen())
4368                 {
4369                     appendIrcStyledText(FXStringFormat(_("Warning: reason of kick is too long. Max. reason length is %d."), m_engine->getKickLen()), 4, FXSystem::now(), FALSE, FALSE);
4370                     return m_engine->sendKick(channel, nick, reason);
4371                 }
4372                 else return m_engine->sendKick(channel, nick, reason);
4373             }
4374         }
4375         else
4376         {
4377             if(isChannel(params) && !params.after(' ').empty())
4378             {
4379                 FXString channel = params.before(' ');
4380                 FXString nick = params.after(' ');
4381                 FXString reason = params.after(' ', 2);
4382                 if(reason.length() > m_engine->getKickLen())
4383                 {
4384                     appendIrcStyledText(FXStringFormat(_("Warning: reason of kick is too long. Max. reason length is %d."), m_engine->getKickLen()), 4, FXSystem::now(), FALSE, FALSE);
4385                     return m_engine->sendKick(channel, nick, reason);
4386                 }
4387                 else return m_engine->sendKick(channel, nick, reason);
4388             }
4389             else
4390             {
4391                 appendIrcStyledText(_("/kick <channel> <nick>, kicks a user from a channel."), 4, FXSystem::now(), FALSE, FALSE);
4392                 return FALSE;
4393             }
4394         }
4395     }
4396     else
4397     {
4398         return notConnected();
4399     }
4400 }
4401 
commandKill(const FXString & commandtext)4402 FXbool IrcTabItem::commandKill(const FXString &commandtext)
4403 {
4404     if(m_engine->getConnected())
4405     {
4406         FXString params = commandtext.after(' ');
4407         FXString nick = params.before(' ');
4408         FXString reason = params.after(' ');
4409         if(params.empty())
4410         {
4411             appendIrcStyledText(_("/kill <user> [reason], kills a user from the network."), 4, FXSystem::now(), FALSE, FALSE);
4412             return FALSE;
4413         }
4414         if(reason.length() > m_maxLen-7-nick.length())
4415         {
4416             appendIrcStyledText(FXStringFormat(_("Warning: reason of kill is too long. Max. reason length is %d."), m_maxLen-7-nick.length()), 4, FXSystem::now(), FALSE, FALSE);
4417         }
4418         return m_engine->sendKill(nick, reason);
4419     }
4420     else
4421     {
4422         return notConnected();
4423     }
4424 }
4425 
commandList(const FXString & commandtext)4426 FXbool IrcTabItem::commandList(const FXString &commandtext)
4427 {
4428     if(m_engine->getConnected())
4429     {
4430         return m_engine->sendList(commandtext.after(' '));
4431     }
4432     else
4433     {
4434         return notConnected();
4435     }
4436 }
4437 
commandLog(const FXString & commandtext)4438 FXbool IrcTabItem::commandLog(const FXString &commandtext)
4439 {
4440     if(m_type == SERVER)
4441     {
4442         appendIrcStyledText(_("Server tab hasn't log files"), 4, FXSystem::now(), FALSE, FALSE);
4443         return TRUE;
4444     }
4445     FXString logcommand = commandtext.after(' ').before(' ');
4446     FXString logfile = commandtext.after(' ').after(' ');
4447     if(comparecase(logcommand, "list")==0)
4448     {
4449         listLogFiles();
4450         return TRUE;
4451     }
4452     else if(comparecase(logcommand, "show")==0)
4453     {
4454         if(logfile.empty())
4455         {
4456             logfile = FXSystem::time("%Y-%m-%d", FXSystem::now());
4457         }
4458         FXString logpath = preferences.m_logPath+PATHSEPSTRING+m_engine->getNetworkName()+PATHSEPSTRING+getText()+PATHSEPSTRING+logfile;
4459         if(!FXStat::exists(logpath))
4460         {
4461             appendIrcStyledText(FXStringFormat(_("Log file %s doesn't exist"), logfile.text()), 4, FXSystem::now(), FALSE, FALSE);
4462             return FALSE;
4463         }
4464         m_parent->getParent()->getParent()->handle(this, FXSEL(SEL_COMMAND, IrcTabItem_SHOWLOG), &logpath);
4465         return TRUE;
4466     }
4467     else
4468     {
4469         appendIrcStyledText(FXStringFormat(_("'%s' isn't <list|show>"), logcommand.text()), 4, FXSystem::now(), FALSE, FALSE);
4470         return FALSE;
4471     }
4472 }
4473 
commandLua(const FXString & commandtext)4474 FXbool IrcTabItem::commandLua(const FXString &commandtext)
4475 {
4476 #ifdef HAVE_LUA
4477     FXString luacommand = commandtext.after(' ').before(' ');
4478     FXString luatext = commandtext.after(' ').after(' ');
4479     LuaRequest lua;
4480     if(luacommand.empty())
4481     {
4482         appendIrcStyledText(_("/lua <help|load|unload|list> [scriptpath|scriptname]"), 4, FXSystem::now(), FALSE, FALSE);
4483         return FALSE;
4484     }
4485     if(comparecase(luacommand, "help")==0)
4486     {
4487         appendIrcStyledText(FXStringFormat(_("For help about Lua scripting visit: %s"), LUA_HELP_PATH), 3, FXSystem::now(), FALSE, FALSE);
4488         return TRUE;
4489     }
4490     else if(comparecase(luacommand, "load")==0)
4491     {
4492         lua.type = LUA_LOAD;
4493     }
4494     else if(comparecase(luacommand, "unload")==0)
4495     {
4496         lua.type = LUA_UNLOAD;
4497     }
4498     else if(comparecase(luacommand, "list")==0)
4499     {
4500         lua.type = LUA_LIST;
4501     }
4502     else
4503     {
4504         appendIrcStyledText(FXStringFormat(_("'%s' isn't <help|load|unload|list>"), luacommand.text()), 4, FXSystem::now(), FALSE, FALSE);
4505         return FALSE;
4506     }
4507     lua.text = luatext;
4508     m_parent->getParent()->getParent()->handle(this, FXSEL(SEL_COMMAND, IrcTabItem_LUA), &lua);
4509     return TRUE;
4510 #else
4511     appendIrcStyledText(_("dxirc is compiled without support for Lua scripting"), 4, FXSystem::now(), FALSE, FALSE);
4512     return FALSE;
4513 #endif
4514 }
4515 
commandMe(const FXString & commandtext)4516 FXbool IrcTabItem::commandMe(const FXString &commandtext)
4517 {
4518     if(m_engine->getConnected())
4519     {
4520         FXString params = commandtext.after(' ');
4521         if(m_type == CHANNEL)
4522         {
4523             if(params.empty())
4524             {
4525                 appendIrcStyledText(_("/me <message>, sends the action to the current channel."), 4, FXSystem::now(), FALSE, FALSE);
4526                 return FALSE;
4527             }
4528             else if(isChannel(params) && !params.after(' ').empty())
4529             {
4530                 FXString channel = params.before(' ');
4531                 FXString message = params.after(' ');
4532                 if(message.length() > m_maxLen-19-channel.length())
4533                 {
4534                     dxStringArray messages = cutText(message, m_maxLen-19-channel.length());
4535                     FXbool result = TRUE;
4536                     for(FXint i=0; i<messages.no(); i++)
4537                     {
4538                         if(channel == getText())
4539                         {
4540                             appendIrcStyledText(getNickName()+" "+messages[i], 2, FXSystem::now());
4541                             IrcEvent ev;
4542                             ev.eventType = IRC_ACTION;
4543                             ev.param1 = getNickName();
4544                             ev.param2 = channel;
4545                             ev.param3 = messages[i];
4546                             m_parent->getParent()->getParent()->handle(m_engine, FXSEL(SEL_COMMAND, IrcEngine_SERVER), &ev);
4547                         }
4548                         result = m_engine->sendMe(channel, messages[i]) &result;
4549                     }
4550                     return result;
4551                 }
4552                 else
4553                 {
4554                     if(channel == getText())
4555                     {
4556                         appendIrcStyledText(getNickName()+" "+message, 2, FXSystem::now());
4557                         IrcEvent ev;
4558                         ev.eventType = IRC_ACTION;
4559                         ev.param1 = getNickName();
4560                         ev.param2 = channel;
4561                         ev.param3 = message;
4562                         m_parent->getParent()->getParent()->handle(m_engine, FXSEL(SEL_COMMAND, IrcEngine_SERVER), &ev);
4563                     }
4564                     return m_engine->sendMe(channel, message);
4565                 }
4566             }
4567             else
4568             {
4569                 if(params.length() > m_maxLen-19-getText().length())
4570                 {
4571                     dxStringArray messages = cutText(params, m_maxLen-19-getText().length());
4572                     FXbool result = TRUE;
4573                     for(FXint i=0; i<messages.no(); i++)
4574                     {
4575                         appendIrcStyledText(getNickName()+" "+messages[i], 2, FXSystem::now());
4576                         IrcEvent ev;
4577                         ev.eventType = IRC_ACTION;
4578                         ev.param1 = getNickName();
4579                         ev.param2 = getText();
4580                         ev.param3 = messages[i];
4581                         m_parent->getParent()->getParent()->handle(m_engine, FXSEL(SEL_COMMAND, IrcEngine_SERVER), &ev);
4582                         result = m_engine->sendMe(getText(), messages[i]) &result;
4583                     }
4584                     return result;
4585                 }
4586                 else
4587                 {
4588                     appendIrcStyledText(getNickName()+" "+params, 2, FXSystem::now());
4589                     IrcEvent ev;
4590                     ev.eventType = IRC_ACTION;
4591                     ev.param1 = getNickName();
4592                     ev.param2 = getText();
4593                     ev.param3 = params;
4594                     m_parent->getParent()->getParent()->handle(m_engine, FXSEL(SEL_COMMAND, IrcEngine_SERVER), &ev);
4595                     return m_engine->sendMe(getText(), params);
4596                 }
4597             }
4598         }
4599         else if(m_type == QUERY)
4600         {
4601             if(params.empty())
4602             {
4603                 appendIrcStyledText(_("/me <message>, sends the action to the current query."), 4, FXSystem::now(), FALSE, FALSE);
4604                 return FALSE;
4605             }
4606             else
4607             {
4608                 if(params.length() > m_maxLen-19-getText().length())
4609                 {
4610                     dxStringArray messages = cutText(params, m_maxLen-19-getText().length());
4611                     FXbool result = TRUE;
4612                     for(FXint i=0; i<messages.no(); i++)
4613                     {
4614                         appendIrcStyledText(getNickName()+" "+messages[i], 2, FXSystem::now());
4615                         IrcEvent ev;
4616                         ev.eventType = IRC_ACTION;
4617                         ev.param1 = getNickName();
4618                         ev.param2 = getText();
4619                         ev.param3 = messages[i];
4620                         m_parent->getParent()->getParent()->handle(m_engine, FXSEL(SEL_COMMAND, IrcEngine_SERVER), &ev);
4621                         result = m_engine->sendMe(getText(), messages[i]) &result;
4622                     }
4623                     return result;
4624                 }
4625                 else
4626                 {
4627                     appendIrcStyledText(getNickName()+" "+params, 2, FXSystem::now());
4628                     IrcEvent ev;
4629                     ev.eventType = IRC_ACTION;
4630                     ev.param1 = getNickName();
4631                     ev.param2 = getText();
4632                     ev.param3 = params;
4633                     m_parent->getParent()->getParent()->handle(m_engine, FXSEL(SEL_COMMAND, IrcEngine_SERVER), &ev);
4634                     return m_engine->sendMe(getText(), params);
4635                 }
4636             }
4637         }
4638         else
4639         {
4640             if(!params.after(' ').empty())
4641             {
4642                 FXString to = params.before(' ');
4643                 FXString message = params.after(' ');
4644                 if(message.length() > m_maxLen-19-to.length())
4645                 {
4646                     dxStringArray messages = cutText(message, m_maxLen-19-to.length());
4647                     FXbool result = TRUE;
4648                     for(FXint i=0; i<messages.no(); i++)
4649                     {
4650                         result = m_engine->sendMe(to, messages[i]) &result;
4651                     }
4652                     return result;
4653                 }
4654                 else
4655                 {
4656                     return m_engine->sendMe(to, message);
4657                 }
4658             }
4659             else
4660             {
4661                 appendIrcStyledText(_("/me <to> <message>, sends the action."), 4, FXSystem::now(), FALSE, FALSE);
4662                 return FALSE;
4663             }
4664         }
4665     }
4666     else
4667     {
4668         return notConnected();
4669     }
4670 }
4671 
commandMode(const FXString & commandtext)4672 FXbool IrcTabItem::commandMode(const FXString &commandtext)
4673 {
4674     if(m_engine->getConnected())
4675     {
4676         FXString params = commandtext.after(' ');
4677         if(params.empty())
4678         {
4679             appendIrcStyledText(_("/mode <channel> <modes>, sets modes for a channel."), 4, FXSystem::now(), FALSE, FALSE);
4680             return FALSE;
4681         }
4682         else
4683         {
4684             return m_engine->sendMode(params);
4685         }
4686     }
4687     else
4688     {
4689         return notConnected();
4690     }
4691 }
4692 
commandMsg(const FXString & commandtext)4693 FXbool IrcTabItem::commandMsg(const FXString &commandtext)
4694 {
4695     if(m_engine->getConnected())
4696     {
4697         FXString params = commandtext.after(' ');
4698         FXString to = params.before(' ');
4699         FXString message = params.after(' ');
4700         if(!to.empty() && !message.empty())
4701         {
4702             if(message.length() > m_maxLen-10-to.length())
4703             {
4704                 dxStringArray messages = cutText(message, m_maxLen-10-to.length());
4705                 FXbool result = TRUE;
4706                 for(FXint i=0; i<messages.no(); i++)
4707                 {
4708                     if(to == getText())
4709                     {
4710                         appendIrcNickText(getNickName(), messages[i], getNickStyle(getNickName()), FXSystem::now());
4711                         IrcEvent ev;
4712                         ev.eventType = IRC_PRIVMSG;
4713                         ev.param1 = getNickName();
4714                         ev.param2 = to;
4715                         ev.param3 = messages[i];
4716                         m_parent->getParent()->getParent()->handle(m_engine, FXSEL(SEL_COMMAND, IrcEngine_SERVER), &ev);
4717                     }
4718                     result = m_engine->sendMsg(to, messages[i]) &result;
4719                 }
4720                 return result;
4721             }
4722             else
4723             {
4724                 if(to == getText())
4725                 {
4726                     appendIrcNickText(getNickName(), message, getNickStyle(getNickName()), FXSystem::now());
4727                     IrcEvent ev;
4728                     ev.eventType = IRC_PRIVMSG;
4729                     ev.param1 = getNickName();
4730                     ev.param2 = to;
4731                     ev.param3 = message;
4732                     m_parent->getParent()->getParent()->handle(m_engine, FXSEL(SEL_COMMAND, IrcEngine_SERVER), &ev);
4733                 }
4734                 return m_engine->sendMsg(to, message);
4735             }
4736         }
4737         else
4738         {
4739             appendIrcStyledText(_("/msg <nick/channel> <message>, sends a normal message."), 4, FXSystem::now(), FALSE, FALSE);
4740             return FALSE;
4741         }
4742     }
4743     else
4744     {
4745         return notConnected();
4746     }
4747 }
4748 
commandNames(const FXString & commandtext)4749 FXbool IrcTabItem::commandNames(const FXString &commandtext)
4750 {
4751     if(m_engine->getConnected())
4752     {
4753         FXString params = commandtext.after(' ');
4754         if(m_type == CHANNEL)
4755         {
4756             if(params.empty())
4757             {
4758                 return m_engine->sendNames(getText(), true);
4759             }
4760             else
4761             {
4762                 return m_engine->sendNames(params, true);
4763             }
4764         }
4765         else
4766         {
4767             if(params.empty())
4768             {
4769                 appendIrcStyledText(_("/names <channel>, for nicks on a channel."), 4, FXSystem::now(), FALSE, FALSE);
4770                 return FALSE;
4771             }
4772             else
4773             {
4774                 return m_engine->sendNames(params, true);
4775             }
4776         }
4777     }
4778     else
4779     {
4780         return notConnected();
4781     }
4782 }
4783 
commandNick(const FXString & commandtext)4784 FXbool IrcTabItem::commandNick(const FXString &commandtext)
4785 {
4786     if(m_engine->getConnected())
4787     {
4788         FXString nick = commandtext.after(' ');
4789         if(nick.empty())
4790         {
4791             appendIrcStyledText(_("/nick <nick>, changes nick."), 4, FXSystem::now(), FALSE, FALSE);
4792             return FALSE;
4793         }
4794         else if(nick.length() > m_engine->getNickLen())
4795         {
4796             appendIrcStyledText(FXStringFormat(_("Warning: nick is too long. Max. nick length is %d."), m_engine->getNickLen()), 4, FXSystem::now(), FALSE, FALSE);
4797             return m_engine->sendNick(nick);
4798         }
4799         else
4800         {
4801             return m_engine->sendNick(nick);
4802         }
4803     }
4804     else
4805     {
4806         return notConnected();
4807     }
4808 }
4809 
commandNotice(const FXString & commandtext)4810 FXbool IrcTabItem::commandNotice(const FXString &commandtext)
4811 {
4812     if(m_engine->getConnected())
4813     {
4814         FXString params = commandtext.after(' ');
4815         FXString to = params.before(' ');
4816         FXString message = params.after(' ');
4817         if(!to.empty() && !message.empty())
4818         {
4819             if(message.length() > m_maxLen-9-to.length())
4820             {
4821                 dxStringArray messages = cutText(message, m_maxLen-9-to.length());
4822                 FXbool result = TRUE;
4823                 for(FXint i=0; i<messages.no(); i++)
4824                 {
4825                     appendIrcStyledText(FXStringFormat(_("NOTICE to %s: %s"), to.text(), messages[i].text()), 2, FXSystem::now());
4826                     result = m_engine->sendNotice(to, messages[i]) &result;
4827                 }
4828                 return result;
4829             }
4830             else
4831             {
4832                 appendIrcStyledText(FXStringFormat(_("NOTICE to %s: %s"), to.text(), message.text()), 2, FXSystem::now());
4833                 return m_engine->sendNotice(to, message);
4834             }
4835         }
4836         else
4837         {
4838             appendIrcStyledText(_("/notice <nick/channel> <message>, sends a notice."), 4, FXSystem::now(), FALSE, FALSE);
4839             return FALSE;
4840         }
4841     }
4842     else
4843     {
4844         return notConnected();
4845     }
4846 }
4847 
commandOp(const FXString & commandtext)4848 FXbool IrcTabItem::commandOp(const FXString &commandtext)
4849 {
4850     if(m_engine->getConnected())
4851     {
4852         FXString params = commandtext.after(' ');
4853         if(m_type == CHANNEL)
4854         {
4855             if(params.empty())
4856             {
4857                 appendIrcStyledText(_("/op <nicks>, gives operator status for one or more nicks."), 4, FXSystem::now(), FALSE, FALSE);
4858                 return FALSE;
4859             }
4860             else if(isChannel(params) && params.after(' ').empty())
4861             {
4862                 appendIrcStyledText(_("/op <channel> <nicks>, gives operator status for one or more nicks."), 4, FXSystem::now(), FALSE, FALSE);
4863                 return FALSE;
4864             }
4865             else if(isChannel(params) && !params.after(' ').empty())
4866             {
4867                 FXString channel = params.before(' ');
4868                 FXString nicks = params.after(' ');
4869                 FXString modeparams = dxutils::createModes('+', 'o', nicks);
4870                 return m_engine->sendMode(channel+" "+modeparams);
4871             }
4872             else
4873             {
4874                 FXString channel = getText();
4875                 FXString nicks = params;
4876                 FXString modeparams = dxutils::createModes('+', 'o', nicks);
4877                 return m_engine->sendMode(channel+" "+modeparams);
4878             }
4879         }
4880         else
4881         {
4882             if(isChannel(params) && !params.after(' ').empty())
4883             {
4884                 FXString channel = params.before(' ');
4885                 FXString nicks = params.after(' ');
4886                 FXString modeparams = dxutils::createModes('+', 'o', nicks);
4887                 return m_engine->sendMode(channel+" "+modeparams);
4888             }
4889             else
4890             {
4891                 appendIrcStyledText(_("/op <channel> <nicks>, gives operator status for one or more nicks."), 4, FXSystem::now(), FALSE, FALSE);
4892                 return FALSE;
4893             }
4894         }
4895     }
4896     else
4897     {
4898         return notConnected();
4899     }
4900 }
4901 
commandOper(const FXString & commandtext)4902 FXbool IrcTabItem::commandOper(const FXString &commandtext)
4903 {
4904     if(m_engine->getConnected())
4905     {
4906         FXString params = commandtext.after(' ');
4907         FXString login = params.before(' ');
4908         FXString password = params.after(' ');
4909         if(!login.empty() && !password.empty())
4910         {
4911             return m_engine->sendOper(login, password);
4912         }
4913         else
4914         {
4915             appendIrcStyledText(_("/oper <login> <password>, oper up."), 4, FXSystem::now(), FALSE, FALSE);
4916             return FALSE;
4917         }
4918     }
4919     else
4920     {
4921         return notConnected();
4922     }
4923 }
4924 
commandPart(const FXString & commandtext)4925 FXbool IrcTabItem::commandPart(const FXString &commandtext)
4926 {
4927     if(m_engine->getConnected())
4928     {
4929         if(m_type == CHANNEL)
4930         {
4931             if(commandtext.after(' ').empty())
4932             {
4933                 return m_engine->sendPart(getText());
4934             }
4935             else
4936             {
4937                 return m_engine->sendPart(getText(), commandtext.after(' '));
4938             }
4939         }
4940         else
4941         {
4942             if(isChannel(commandtext.after(' ')))
4943             {
4944                 FXString channel = commandtext.after(' ').before(' ');
4945                 FXString reason = commandtext.after(' ', 2);
4946                 if(reason.empty())
4947                 {
4948                     return m_engine->sendPart(channel);
4949                 }
4950                 else
4951                 {
4952                     return m_engine->sendPart(channel, reason);
4953                 }
4954             }
4955             else
4956             {
4957                 appendIrcStyledText(_("/part <channel> [reason], leaves channel."), 4, FXSystem::now(), FALSE, FALSE);
4958                 return FALSE;
4959             }
4960         }
4961     }
4962     else
4963     {
4964         return notConnected();
4965     }
4966 }
4967 
commandQuery(const FXString & commandtext)4968 FXbool IrcTabItem::commandQuery(const FXString &commandtext)
4969 {
4970     if(m_engine->getConnected())
4971     {
4972         if(commandtext.after(' ').empty())
4973         {
4974             appendIrcStyledText(_("/query <nick>, opens query with nick."), 4, FXSystem::now(), FALSE, FALSE);
4975             return FALSE;
4976         }
4977         else
4978         {
4979             IrcEvent ev;
4980             ev.eventType = IRC_QUERY;
4981             ev.param1 = commandtext.after(' ').before(' ');
4982             ev.param2 = getNickName();
4983             m_parent->getParent()->getParent()->handle(m_engine, FXSEL(SEL_COMMAND, IrcEngine_SERVER), &ev);
4984             return TRUE;
4985         }
4986     }
4987     else
4988     {
4989         return notConnected();
4990     }
4991 }
4992 
commandQuit()4993 FXbool IrcTabItem::commandQuit()
4994 {
4995     m_parent->getParent()->getParent()->handle(this, FXSEL(SEL_COMMAND, IrcTabItem_CQUIT), NULL);
4996     return TRUE;
4997 }
4998 
commandQuote(const FXString & commandtext)4999 FXbool IrcTabItem::commandQuote(const FXString &commandtext)
5000 {
5001     if(m_engine->getConnected())
5002     {
5003         return m_engine->sendQuote(commandtext.after(' '));
5004     }
5005     else
5006     {
5007         return notConnected();
5008     }
5009 }
5010 
commandSay(const FXString & commandtext)5011 FXbool IrcTabItem::commandSay(const FXString &commandtext)
5012 {
5013     if(m_engine->getConnected())
5014     {
5015         if (m_type != SERVER && !commandtext.after(' ').empty())
5016         {
5017             if(commandtext.after(' ').length() > m_maxLen-10-getText().length())
5018             {
5019                 dxStringArray messages = cutText(commandtext.after(' '), m_maxLen-10-getText().length());
5020                 FXbool result = TRUE;
5021                 for(FXint i=0; i<messages.no(); i++)
5022                 {
5023                     appendMyMsg(messages[i], FXSystem::now());
5024                     IrcEvent ev;
5025                     ev.eventType = IRC_PRIVMSG;
5026                     ev.param1 = getNickName();
5027                     ev.param2 = getText();
5028                     ev.param3 = messages[i];
5029                     m_parent->getParent()->getParent()->handle(m_engine, FXSEL(SEL_COMMAND, IrcEngine_SERVER), &ev);
5030                     result = m_engine->sendMsg(getText(), messages[i]) &result;
5031                 }
5032                 return result;
5033             }
5034             else
5035             {
5036                 appendMyMsg(commandtext.after(' '), FXSystem::now());
5037                 IrcEvent ev;
5038                 ev.eventType = IRC_PRIVMSG;
5039                 ev.param1 = getNickName();
5040                 ev.param2 = getText();
5041                 ev.param3 = commandtext.after(' ');
5042                 m_parent->getParent()->getParent()->handle(m_engine, FXSEL(SEL_COMMAND, IrcEngine_SERVER), &ev);
5043                 return m_engine->sendMsg(getText(), commandtext.after(' '));
5044             }
5045         }
5046         return FALSE;
5047     }
5048     else
5049     {
5050         return notConnected();
5051     }
5052 }
5053 
commandStats(const FXString & commandtext)5054 FXbool IrcTabItem::commandStats(const FXString &commandtext)
5055 {
5056     if(m_engine->getConnected())
5057     {
5058         return m_engine->sendStats(commandtext.after(' '));
5059     }
5060     else
5061     {
5062         return notConnected();
5063     }
5064 }
5065 
commandTetris()5066 FXbool IrcTabItem::commandTetris()
5067 {
5068     m_parent->getParent()->getParent()->handle(this, FXSEL(SEL_COMMAND, IrcTabItem_NEWTETRIS), NULL);
5069     return TRUE;
5070 }
5071 
commandTime()5072 FXbool IrcTabItem::commandTime()
5073 {
5074     if(m_engine->getConnected())
5075     {
5076         return m_engine->sendQuote("TIME");
5077     }
5078     else
5079     {
5080         return notConnected();
5081     }
5082 }
5083 
commandTopic(const FXString & commandtext)5084 FXbool IrcTabItem::commandTopic(const FXString &commandtext)
5085 {
5086     if(m_engine->getConnected())
5087     {
5088         FXString params = commandtext.after(' ');
5089         if(m_type == CHANNEL)
5090         {
5091             if(params.empty())
5092             {
5093                 return m_engine->sendTopic(getText());
5094             }
5095             else if(isChannel(params) && !params.after(' ').empty())
5096             {
5097                 FXString channel = params.before(' ');
5098                 FXString topic = params.after(' ');
5099                 if(topic.length() > m_engine->getTopicLen())
5100                 {
5101                     appendIrcStyledText(FXStringFormat(_("Warning: topic is too long. Max. topic length is %d."), m_engine->getTopicLen()), 4, FXSystem::now(), FALSE, FALSE);
5102                 }
5103                 return m_engine->sendTopic(channel, topic);
5104             }
5105             else
5106             {
5107                 if(params.length() > m_engine->getTopicLen())
5108                 {
5109                     appendIrcStyledText(FXStringFormat(_("Warning: topic is too long. Max. topic length is %d."), m_engine->getTopicLen()), 4, FXSystem::now(), FALSE, FALSE);
5110                 }
5111                 return m_engine->sendTopic(getText(), params);
5112             }
5113         }
5114         else
5115         {
5116             if(isChannel(params))
5117             {
5118                 FXString channel = params.before(' ');
5119                 FXString topic = params.after(' ');
5120                 if(topic.length() > m_engine->getTopicLen())
5121                 {
5122                     appendIrcStyledText(FXStringFormat(_("Warning: topic is too long. Max. topic length is %d."), m_engine->getTopicLen()), 4, FXSystem::now(), FALSE, FALSE);
5123                 }
5124                 return m_engine->sendTopic(channel, topic);
5125             }
5126             else
5127             {
5128                 appendIrcStyledText(_("/topic <channel> [topic], views or changes channel topic."), 4, FXSystem::now(), FALSE, FALSE);
5129                 return FALSE;
5130             }
5131         }
5132     }
5133     else
5134     {
5135         return notConnected();
5136     }
5137 }
5138 
commandVoice(const FXString & commandtext)5139 FXbool IrcTabItem::commandVoice(const FXString &commandtext)
5140 {
5141     if(m_engine->getConnected())
5142     {
5143         FXString params = commandtext.after(' ');
5144         if(m_type == CHANNEL)
5145         {
5146             if(params.empty())
5147             {
5148                 appendIrcStyledText(_("/voice <nicks>, gives voice for one or more nicks."), 4, FXSystem::now(), FALSE, FALSE);
5149                 return FALSE;
5150             }
5151             else if(isChannel(params) && params.after(' ').empty())
5152             {
5153                 appendIrcStyledText(_("/voice <channel> <nicks>, gives voice for one or more nicks."), 4, FXSystem::now(), FALSE, FALSE);
5154                 return FALSE;
5155             }
5156             else if(isChannel(params) && !params.after(' ').empty())
5157             {
5158                 FXString channel = params.before(' ');
5159                 FXString nicks = params.after(' ');
5160                 FXString modeparams = dxutils::createModes('+', 'v', nicks);
5161                 return m_engine->sendMode(channel+" "+modeparams);
5162             }
5163             else
5164             {
5165                 FXString channel = getText();
5166                 FXString nicks = params;
5167                 FXString modeparams = dxutils::createModes('+', 'v', nicks);
5168                 return m_engine->sendMode(channel+" "+modeparams);
5169             }
5170         }
5171         else
5172         {
5173             if(isChannel(params) && !params.after(' ').empty())
5174             {
5175                 FXString channel = params.before(' ');
5176                 FXString nicks = params.after(' ');
5177                 FXString modeparams = dxutils::createModes('+', 'v', nicks);
5178                 return m_engine->sendMode(channel+" "+modeparams);
5179             }
5180             else
5181             {
5182                 appendIrcStyledText(_("/voice <channel> <nicks>, gives voice for one or more nicks."), 4, FXSystem::now(), FALSE, FALSE);
5183                 return FALSE;
5184             }
5185         }
5186     }
5187     else
5188     {
5189         return notConnected();
5190     }
5191 }
5192 
commandWallops(const FXString & commandtext)5193 FXbool IrcTabItem::commandWallops(const FXString &commandtext)
5194 {
5195     if(m_engine->getConnected())
5196     {
5197         FXString params = commandtext.after(' ');
5198         if(params.empty())
5199         {
5200             appendIrcStyledText(_("/wallops <message>, sends wallop message."), 4, FXSystem::now(), FALSE, FALSE);
5201             return FALSE;
5202         }
5203         else
5204         {
5205             if(params.length() > m_maxLen-9)
5206             {
5207                 dxStringArray messages = cutText(params, m_maxLen-9);
5208                 FXbool result = TRUE;
5209                 for(FXint i=0; i<messages.no(); i++)
5210                 {
5211                     result = m_engine->sendWallops(messages[i]) &result;
5212                 }
5213                 return result;
5214             }
5215             else return m_engine->sendWallops(params);
5216         }
5217     }
5218     else
5219     {
5220         return notConnected();
5221     }
5222 }
5223 
commandWho(const FXString & commandtext)5224 FXbool IrcTabItem::commandWho(const FXString &commandtext)
5225 {
5226     if(m_engine->getConnected())
5227     {
5228         FXString params = commandtext.after(' ');
5229         if(params.empty())
5230         {
5231             appendIrcStyledText(_("/who <mask> [o], searchs for mask on network, if o is supplied, only search for opers."), 4, FXSystem::now(), FALSE, FALSE);
5232             return FALSE;
5233         }
5234         else
5235         {
5236             return m_engine->sendWho(params);
5237         }
5238     }
5239     else
5240     {
5241         return notConnected();
5242     }
5243 }
5244 
commandWhoami()5245 FXbool IrcTabItem::commandWhoami()
5246 {
5247     if(m_engine->getConnected())
5248     {
5249         return m_engine->sendWhoami();
5250     }
5251     else
5252     {
5253         return notConnected();
5254     }
5255 }
5256 
commandWhois(const FXString & commandtext)5257 FXbool IrcTabItem::commandWhois(const FXString &commandtext)
5258 {
5259     if(m_engine->getConnected())
5260     {
5261         FXString params = commandtext.after(' ');
5262         if(params.empty())
5263         {
5264             if(m_type == QUERY)
5265             {
5266                 return m_engine->sendWhois(getText());
5267             }
5268             appendIrcStyledText(_("/whois <nick>, whois nick."), 4, FXSystem::now(), FALSE, FALSE);
5269             return FALSE;
5270         }
5271         else
5272         {
5273             return m_engine->sendWhois(params);
5274         }
5275     }
5276     else
5277     {
5278         return notConnected();
5279     }
5280 }
5281 
commandWhowas(const FXString & commandtext)5282 FXbool IrcTabItem::commandWhowas(const FXString &commandtext)
5283 {
5284     if(m_engine->getConnected())
5285     {
5286         FXString params = commandtext.after(' ');
5287         if(params.empty())
5288         {
5289             appendIrcStyledText(_("/whowas <nick>, whowas nick."), 4, FXSystem::now(), FALSE, FALSE);
5290             return FALSE;
5291         }
5292         else
5293         {
5294             return m_engine->sendWhowas(params);
5295         }
5296     }
5297     else
5298     {
5299         return notConnected();
5300     }
5301 }
5302 
5303 //fire request for connect dialog
notConnected()5304 FXbool IrcTabItem::notConnected()
5305 {
5306     appendIrcStyledText(_("You aren't connected"), 4, FXSystem::now(), FALSE, FALSE);
5307     m_parent->getParent()->getParent()->handle(this, FXSEL(SEL_COMMAND, IrcTabItem_CDIALOG), NULL);
5308     return TRUE;
5309 }
5310 
5311