1 //=============================================================================
2 //
3 //   File : libkviwindow.cpp
4 //   Creation date : Sat Sep 01 2001 17:13:12 CEST by Szymon Stefanek
5 //
6 //   This file is part of the KVIrc IRC client distribution
7 //   Copyright (C) 2001-2010 Szymon Stefanek (pragma at kvirc dot net)
8 //
9 //   This program is FREE software. You can redistribute it and/or
10 //   modify it under the terms of the GNU General Public License
11 //   as published by the Free Software Foundation; either version 2
12 //   of the License, or (at your option) any later version.
13 //
14 //   This program is distributed in the HOPE that it will be USEFUL,
15 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
16 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 //   See the GNU General Public License for more details.
18 //
19 //   You should have received a copy of the GNU General Public License
20 //   along with this program. If not, write to the Free Software Foundation,
21 //   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 //
23 //=============================================================================
24 
25 #include "UserWindow.h"
26 
27 #include "KviModule.h"
28 #include "KviConsoleWindow.h"
29 #include "KviOptions.h"
30 #include "KviIrcSocket.h"
31 #include "KviMainWindow.h"
32 #include "KviLocale.h"
33 #include "KviApplication.h"
34 #include "KviError.h"
35 #include "KviIrcView.h"
36 #include "KviInput.h"
37 #include "KviIconManager.h"
38 #include "KviModuleManager.h"
39 #include "KviMemory.h"
40 #include "KviChannelWindow.h"
41 
42 #include <QTimer>
43 #include <map>
44 #include <vector>
45 
46 #ifdef COMPILE_CRYPT_SUPPORT
47 #include "KviCryptEngine.h"
48 #include "KviCryptController.h"
49 // KviApplication.cpp
50 extern KVIRC_API KviCryptEngineManager * g_pCryptEngineManager;
51 #endif
52 
53 // KviApplication.cpp
54 extern KVIRC_API std::map<QString, KviWindow *> g_pGlobalWindowDict;
55 std::vector<UserWindow *> g_pUserWindowList;
56 
57 // $window.caption $window.x $window.y $window.width $window.height $window.isActive $window.type
58 // $window.input.text $window.input.cursorpos $window.input.textlen
59 
60 #define GET_KVS_WINDOW_ID                                                                            \
61 	QString szWnd;                                                                                   \
62 	KviWindow * pWnd;                                                                                \
63 	KVSM_PARAMETERS_BEGIN(c)                                                                         \
64 	KVSM_PARAMETER("window_id", KVS_PT_STRING, KVS_PF_OPTIONAL, szWnd)                               \
65 	KVSM_PARAMETERS_END(c)                                                                           \
66 	if(c->parameterList()->count() == 0)                                                             \
67 	{                                                                                                \
68 		pWnd = c->window();                                                                          \
69 	}                                                                                                \
70 	else                                                                                             \
71 	{                                                                                                \
72 		pWnd = g_pApp->findWindow(szWnd.toUtf8().data());                                            \
73 		if(!pWnd)                                                                                    \
74 		{                                                                                            \
75 			if(!c->hasSwitch('q', "quiet"))                                                          \
76 				c->warning(__tr2qs("The window with ID '%s' doesn't exist"), szWnd.toUtf8().data()); \
77 			return true;                                                                             \
78 		}                                                                                            \
79 	}
80 
81 #define GET_KVS_FNC_WINDOW_ID                                          \
82 	QString szWnd;                                                     \
83 	KviWindow * pWnd;                                                  \
84 	KVSM_PARAMETERS_BEGIN(c)                                           \
85 	KVSM_PARAMETER("window_id", KVS_PT_STRING, KVS_PF_OPTIONAL, szWnd) \
86 	KVSM_PARAMETERS_END(c)                                             \
87 	if(c->parameterList()->count() == 0)                               \
88 	{                                                                  \
89 		pWnd = c->window();                                            \
90 	}                                                                  \
91 	else                                                               \
92 	{                                                                  \
93 		pWnd = g_pApp->findWindow(szWnd.toUtf8().data());              \
94 		if(!pWnd)                                                      \
95 			return true;                                               \
96 	}
97 
98 /*
99 	@doc: window.clearOutput
100 	@type:
101 		command
102 	@title:
103 		window.clearOutput
104 	@short:
105 		Clears the output a window
106 	@syntax:
107 		window.clearOutput [-q] [window_id]
108 	@switches:
109 		!sw: -q | --quiet
110 		Don't warn if the specified window doesn't exist. Just continue silently.
111 	@description:
112 		Clears the text output of the window specified by window_id. If window_id is missing then
113 		the current window is used. If the window has no text output then no operation is performed.
114 		If the specified window does not exist a warning is printed (unless the -q switch is used)
115 		but the execution continues normally.
116 	@seealso:
117 		[fnc]$window.hasOutput[/fnc]
118 */
119 
window_kvs_cmd_clearOutput(KviKvsModuleCommandCall * c)120 static bool window_kvs_cmd_clearOutput(KviKvsModuleCommandCall * c)
121 {
122 	GET_KVS_WINDOW_ID
123 	if(pWnd)
124 	{
125 		if(pWnd->view())
126 			pWnd->view()->clearBuffer();
127 		if(pWnd->type() == KviWindow::Channel)
128 		{
129 			KviChannelWindow * chan = (KviChannelWindow *)pWnd;
130 			if(chan->messageView())
131 				chan->messageView()->clearBuffer();
132 		}
133 	}
134 	return true;
135 }
136 
137 /*
138 	@doc: window.close
139 	@type:
140 		command
141 	@title:
142 		window.close
143 	@short:
144 		Closes a window
145 	@syntax:
146 		window.close [-q] [window_id]
147 	@description:
148 		Closes the window specified by window_id. If window_id is missing then
149 		the current window is closed. The close operation is asynchronous: it is
150 		performed immediately after the script has terminated the execution and
151 		the control is returned to the main KVIrc core. If the specified window
152 		does not exist a warning is printed unless the -q switch is used.
153 */
154 
window_kvs_cmd_close(KviKvsModuleCommandCall * c)155 static bool window_kvs_cmd_close(KviKvsModuleCommandCall * c)
156 {
157 	GET_KVS_WINDOW_ID
158 	if(pWnd)
159 	{
160 		pWnd->delayedClose();
161 	}
162 	return true;
163 }
164 
165 /*
166 	@doc: window.dock
167 	@type:
168 		command
169 	@title:
170 		window.dock
171 	@short:
172 		Docks a window
173 	@syntax:
174 		window.dock [-q] [window_id]
175 	@description:
176 		Docks the window specified by window_id. If window_id is missing then
177 		the current window is docked. If the specified window was already docked then
178 		no operation is performed. If the specified window
179 		does not exist a warning is printed unless the -q switch is used.
180 	@seealso:
181 		[cmd]window.undock[/cmd], [fnc]$window.isDocked[/fnc]
182 */
183 
window_kvs_cmd_dock(KviKvsModuleCommandCall * c)184 static bool window_kvs_cmd_dock(KviKvsModuleCommandCall * c)
185 {
186 	GET_KVS_WINDOW_ID
187 	if(pWnd)
188 	{
189 		pWnd->dock();
190 	}
191 	return true;
192 }
193 
194 /*
195 	@doc: window.undock
196 	@type:
197 		command
198 	@title:
199 		window.undock
200 	@short:
201 		Undocks a window
202 	@syntax:
203 		window.undock [-q] [window_id]
204 	@description:
205 		Undocks the window specified by window_id. If window_id is missing then
206 		the current window is undocked. If the specified window was already undocked then
207 		no operation is performed. If the specified window
208 		does not exist a warning is printed unless the -q switch is used.
209 	@seealso:
210 		[cmd]window.dock[/cmd], [fnc]$window.isDocked[/fnc]
211 */
212 
window_kvs_cmd_undock(KviKvsModuleCommandCall * c)213 static bool window_kvs_cmd_undock(KviKvsModuleCommandCall * c)
214 {
215 	GET_KVS_WINDOW_ID
216 	if(pWnd)
217 	{
218 		pWnd->undock();
219 	}
220 	return true;
221 }
222 
223 /*
224 	@doc: window.splitView
225 	@type:
226 		command
227 	@title:
228 		window.splitView
229 	@short:
230 		Splits the view of a channel window
231 	@syntax:
232 		window.splitView [-q] [window_id]
233 	@description:
234 		Splits the view of a channel specified by window_id. If window_id is missing then
235 		the current window is split. If the specified window was already split then no
236 		operation is performed. If the specified window does not exist or is not a channel
237 		window then a warning is printed unless the -q switch is used.
238 	@seealso:
239 		[cmd]window.unsplitView[/cmd], [fnc]$window.isSplitView[/fnc]
240 */
241 
window_kvs_cmd_splitView(KviKvsModuleCommandCall * c)242 static bool window_kvs_cmd_splitView(KviKvsModuleCommandCall * c)
243 {
244 	GET_KVS_WINDOW_ID
245 	if(pWnd && pWnd->type() == KviWindow::Channel)
246 	{
247 		KviChannelWindow * chan = (KviChannelWindow *)pWnd;
248 		if(!chan->messageView())
249 			chan->toggleDoubleView();
250 	}
251 	else
252 	{
253 		if(!c->hasSwitch('q', "quiet"))
254 			c->warning(__tr2qs("The window with ID '%s' isn't a channel window."), szWnd.toUtf8().data());
255 	}
256 	return true;
257 }
258 
259 /*
260 	@doc: window.unsplitView
261 	@type:
262 		command
263 	@title:
264 		window.unsplitView
265 	@short:
266 		Unsplits the view of a channel window
267 	@syntax:
268 		window.splitView [-q] [window_id]
269 	@description:
270 		Unsplits the view of a channel specified by window_id. If window_id is missing then
271 		the current window is unsplit. If the specified window wasn't already split then no
272 		operation is performed. If the specified window does not exist or is not a channel
273 		window then a warning is printed unless the -q switch is used.
274 	@seealso:
275 		[cmd]window.unsplitView[/cmd], [fnc]$window.isSplitView[/fnc]
276 */
277 
window_kvs_cmd_unsplitView(KviKvsModuleCommandCall * c)278 static bool window_kvs_cmd_unsplitView(KviKvsModuleCommandCall * c)
279 {
280 	GET_KVS_WINDOW_ID
281 	if(pWnd && pWnd->type() == KviWindow::Channel)
282 	{
283 		KviChannelWindow * chan = (KviChannelWindow *)pWnd;
284 		if(chan->messageView())
285 			chan->toggleDoubleView();
286 	}
287 	else
288 	{
289 		if(!c->hasSwitch('q', "quiet"))
290 			c->warning(__tr2qs("The window with ID '%s' isn't a channel window."), szWnd.toUtf8().data());
291 	}
292 	return true;
293 }
294 
295 /*
296 	@doc: window.activate
297 	@type:
298 		command
299 	@title:
300 		window.activate
301 	@short:
302 		Activates a window
303 	@syntax:
304 		window.activate [-q] [window_id]
305 	@description:
306 		Activates the window specified by window_id. If window_id is missing then
307 		the current window is activated. If the specified window
308 		does not exist a warning is printed unless the -q switch is used.
309 		Please note that if the window is currently docked to a frame then this
310 		command will [b]not[/b] raise the frame window. If you're interested in
311 		the user's attention then you might be interested in [cmd]window.demandAttention[/cmd].
312 	@seealso:
313 		[cmd]window.demandAttention[/cmd]
314 */
315 
window_kvs_cmd_activate(KviKvsModuleCommandCall * c)316 static bool window_kvs_cmd_activate(KviKvsModuleCommandCall * c)
317 {
318 	GET_KVS_WINDOW_ID
319 	if(pWnd)
320 	{
321 		pWnd->autoRaise();
322 	}
323 	return true;
324 }
325 
326 /*
327 	@doc: window.demandAttention
328 	@type:
329 		command
330 	@title:
331 		window.demandAttention
332 	@short:
333 		Flashes a window's system taskbar entry
334 	@syntax:
335 		window.demandAttention [-q] [window_id]
336 	@description:
337 		Flashes the system taskbar entry of the window
338 		specified by the window_id. If window_id is missing then
339 		the current window's system taskbar entry is flashed. If the specified window
340 		does not exist a warning is printed unless the -q switch is used.
341 		If the window is currently docked in a frame then the frame's
342 		system taskbar entry will be flashed.
343 		Please note that this command is highly system dependent:
344 		on systems that do not have a system taskbar or there
345 		is no way to flash an entry this command will do nothing.
346 		At the time of writing this command works flawlessly on
347 		Windows and in KDE compilations.
348 	@seealso:
349 		[cmd]window.demandAttention[/cmd]
350 */
351 
window_kvs_cmd_demandAttention(KviKvsModuleCommandCall * c)352 static bool window_kvs_cmd_demandAttention(KviKvsModuleCommandCall * c)
353 {
354 	GET_KVS_WINDOW_ID
355 	if(pWnd)
356 	{
357 		pWnd->demandAttention();
358 	}
359 	return true;
360 }
361 
362 /*
363 	@doc: window.activityLevel
364 	@type:
365 		function
366 	@title:
367 		$window.activityLevel
368 	@short:
369 		Returns the current activity level of a window
370 	@syntax:
371 		$window.activityLevel
372 		$window.activityLevel(<window_id>)
373 	@description:
374 		Returns the current activity level of the window specified by <window_id>.
375 		The form without parameters works on the current window.[br]
376 		The activity level is a number describing the level of traffic in the window
377 		and depends on the window type. On channels and queries it is dependent on the number
378 		and frequency of actions performed by the users.
379 	@seealso:
380 		[fnc]$window.activityTemperature[/fnc]
381 */
382 
window_kvs_fnc_activityLevel(KviKvsModuleFunctionCall * c)383 static bool window_kvs_fnc_activityLevel(KviKvsModuleFunctionCall * c)
384 {
385 	GET_KVS_FNC_WINDOW_ID
386 	if(pWnd)
387 	{
388 		unsigned int v, t;
389 		pWnd->activityMeter(&v, &t);
390 		c->returnValue()->setInteger(v);
391 	}
392 	else
393 	{
394 		c->returnValue()->setInteger(0);
395 	}
396 	return true;
397 }
398 
399 /*
400 	@doc: window.activityTemperature
401 	@type:
402 		function
403 	@title:
404 		$window.activityTemperature
405 	@short:
406 		Returns the current activity temperature of a window
407 	@syntax:
408 		$window.activityTemperature
409 		$window.activityTemperature(<window_id>)
410 	@description:
411 		Returns the current activity temperature of the window specified by <window_id>.
412 		The form without parameters works on the current window.[br]
413 		The activity temperature describes the type of traffic in the window and is
414 		strictly related to the [fnc]$window.activityLevel[/fnc].[br]
415 		On channels and queries the temperature describes the type of the actions
416 		performed by the users. High temperatures denote more "human" behaviour (like
417 		speaking to the channel, changing the topic etc...),
418 		low temperatures denote automatic behaviours (like changing the channel limit
419 		or mode: actions often performed by bots).[br]
420 	@seealso:
421 		[fnc]$window.activityLevel[/fnc]
422 */
423 
window_kvs_fnc_activityTemperature(KviKvsModuleFunctionCall * c)424 static bool window_kvs_fnc_activityTemperature(KviKvsModuleFunctionCall * c)
425 {
426 	GET_KVS_FNC_WINDOW_ID
427 	if(pWnd)
428 	{
429 		unsigned int v, t;
430 		pWnd->activityMeter(&v, &t);
431 		c->returnValue()->setInteger(t);
432 	}
433 	else
434 	{
435 		c->returnValue()->setInteger(0);
436 	}
437 	return true;
438 }
439 
440 /*
441 	@doc: window.isDocked
442 	@type:
443 		function
444 	@title:
445 		$window.isDocked
446 	@short:
447 		Checks if a window is currently docked
448 	@syntax:
449 		$window.isDocked
450 		$window.isDocked(<window_id>)
451 	@description:
452 		Returns [b]1[/b] if the window specified by <window_id> is currently docked and [b]0[/b] otherwise.
453 		The form with no parameters works on the current window. If the specified window
454 		doesn't exist then 0 is returned.
455 	@seealso:
456 		[cmd]window.dock[/cmd], [cmd]window.undock[/cmd]
457 */
458 
window_kvs_fnc_isDocked(KviKvsModuleFunctionCall * c)459 static bool window_kvs_fnc_isDocked(KviKvsModuleFunctionCall * c)
460 {
461 	GET_KVS_FNC_WINDOW_ID
462 	if(pWnd)
463 	{
464 		c->returnValue()->setBoolean(pWnd->parentWidget() ? true : false);
465 	}
466 	return true;
467 }
468 
469 /*
470 	@doc: window.isSplitView
471 	@type:
472 		function
473 	@title:
474 		$window.isSplitView
475 	@short:
476 		Checks if a window is currently in split view mode
477 	@syntax:
478 		$window.isSplitView
479 		$window.isSplitView(<window_id>)
480 	@description:
481 		Returns [b]1[/b] if the window specified by <window_id> is in split view mode and [b]0[/b] otherwise.
482 		This is only intended to apply to channel windows. If the specified window doesn't exist
483 		or is not a channel window then 0 is returned.
484 	@seealso:
485 		[cmd]window.splitView[/cmd], [cmd]window.unsplitView[/cmd]
486 */
window_kvs_fnc_isSplitView(KviKvsModuleFunctionCall * c)487 static bool window_kvs_fnc_isSplitView(KviKvsModuleFunctionCall * c)
488 {
489 	c->returnValue()->setBoolean(false);
490 	GET_KVS_FNC_WINDOW_ID
491 	if(pWnd && pWnd->type() == KviWindow::Channel)
492 		c->returnValue()->setBoolean(((KviChannelWindow *)pWnd)->messageView() ? true : false);
493 	return true;
494 }
495 
496 /*
497 	@doc: window.hasInput
498 	@type:
499 		function
500 	@title:
501 		$window.hasInput
502 	@short:
503 		Checks if a window has an input field
504 	@syntax:
505 		$window.hasInput
506 		$window.hasInput(<window_id>)
507 	@description:
508 		Returns [b]1[/b] if the window specified by <window_id> has an input field and [b]0[/b] otherwise.
509 		The form with no parameters works on the current window. If the specified window
510 		doesn't exist then 0 is returned.
511 	@seealso:
512 		[fnc]$window.hasOutput[/fnc]
513 */
514 
window_kvs_fnc_hasInput(KviKvsModuleFunctionCall * c)515 static bool window_kvs_fnc_hasInput(KviKvsModuleFunctionCall * c)
516 {
517 	GET_KVS_FNC_WINDOW_ID
518 	if(pWnd)
519 	{
520 		c->returnValue()->setBoolean(pWnd->input() ? true : false);
521 	}
522 	else
523 		c->returnValue()->setBoolean(false);
524 	return true;
525 }
526 
527 /*
528 	@doc: window.hasUserFocus
529 	@type:
530 		function
531 	@title:
532 		$window.hasUserFocus
533 	@short:
534 		Checks if a window has the user focus
535 	@syntax:
536 		$window.hasUserFocus
537 		$window.hasUserFocus(<window_id>)
538 	@description:
539 		Returns [b]1[/b] if the window specified by <window_id> has
540 		currently the user focus and [b]0[/b] otherwise.
541 		The form with no parameters works on the current window.
542 		If the specified window doesn't exist then 0 is returned.
543 		A window has the user focus if it is the KVIrc's active
544 		window and has the user's input focus (i.e. typing
545 		on the keyboard will write in this window).
546 	@seealso:
547 */
548 
window_kvs_fnc_hasUserFocus(KviKvsModuleFunctionCall * c)549 static bool window_kvs_fnc_hasUserFocus(KviKvsModuleFunctionCall * c)
550 {
551 	GET_KVS_FNC_WINDOW_ID
552 	if(pWnd)
553 	{
554 		bool b = (pWnd == g_pActiveWindow) && pWnd->isActiveWindow();
555 		c->returnValue()->setBoolean(b ? true : false);
556 	}
557 	else
558 		c->returnValue()->setBoolean(false);
559 	return true;
560 }
561 
562 /*
563 	@doc: window.console
564 	@type:
565 		function
566 	@title:
567 		$window.console
568 	@short:
569 		Returns the console that a window is attached to
570 	@syntax:
571 		$window.console
572 		$window.console(<window_id>)
573 	@description:
574 		Returns the ID of the console window that the window specified by window_id is attached to.
575 		The console is the main (and only) console of the IRC context. If window_id is missing then
576 		the current window is used. If this window does not belong to an IRC context (and thus has
577 		no attached console) then 0 is returned.
578 	@seealso:
579 */
580 
window_kvs_fnc_console(KviKvsModuleFunctionCall * c)581 static bool window_kvs_fnc_console(KviKvsModuleFunctionCall * c)
582 {
583 	GET_KVS_FNC_WINDOW_ID
584 	if(pWnd)
585 	{
586 		c->returnValue()->setInteger(pWnd->console() ? QString(pWnd->console()->id()).toInt() : 0);
587 	}
588 	return true;
589 }
590 
591 /*
592 	@doc: window.hasOutput
593 	@type:
594 		function
595 	@title:
596 		$window.hasOutput
597 	@short:
598 		Checks if a window has a text output widget
599 	@syntax:
600 		$window.hasOutput
601 		$window.hasOutput(<window_id>)
602 	@description:
603 		Returns [b]1[/b] if the window specified by <window_id> has a text output widget and [b]0[/b] otherwise.
604 		The form with no parameters works on the current window. If the specified window
605 		doesn't exist then 0 is returned.
606 	@seealso:
607 		[fnc]$window.hasInput[/fnc]
608 */
609 
window_kvs_fnc_hasOutput(KviKvsModuleFunctionCall * c)610 static bool window_kvs_fnc_hasOutput(KviKvsModuleFunctionCall * c)
611 {
612 	GET_KVS_FNC_WINDOW_ID
613 	if(pWnd)
614 	{
615 		c->returnValue()->setBoolean(pWnd->view() ? true : false);
616 	}
617 	else
618 		c->returnValue()->setBoolean(false);
619 	return true;
620 }
621 
622 /*
623 	@doc: window.exists
624 	@type:
625 		function
626 	@title:
627 		$window.exists
628 	@short:
629 		Checks for the existence of a window
630 	@syntax:
631 		$window.exists(<window_id>)
632 	@description:
633 		Returns 1 if a specified window exists
634 	@seealso:
635 */
636 
window_kvs_fnc_exists(KviKvsModuleFunctionCall * c)637 static bool window_kvs_fnc_exists(KviKvsModuleFunctionCall * c)
638 {
639 	GET_KVS_FNC_WINDOW_ID
640 	if(pWnd)
641 	{
642 		c->returnValue()->setBoolean(true);
643 	}
644 	else
645 		c->returnValue()->setBoolean(false);
646 	return true;
647 }
648 
649 /*
650 	@doc: window.highlight
651 	@type:
652 		command
653 	@title:
654 		window.highlight
655 	@short:
656 		Sets the highlight (alert) level of a window
657 	@syntax:
658 		window.highlight [-q] <level> [window_id]
659 	@switches:
660 		!sw: -q | --quiet
661 		Be quiet
662 	@description:
663 		Sets the highlight the user window specified by [window_id] to <level>.[br]
664 		If <window_id> is an empty string then the current window is assumed.[br]
665 		If the specified window does not exist a warning is printed unless the -q switch is used.[br]
666 		For more infos on this feature read the documentation about [fnc]$window.highlightLevel[/fnc].
667 	@seealso:
668 		[fnc]$window.highlightLevel[/fnc]
669 */
670 
window_kvs_cmd_highlight(KviKvsModuleCommandCall * c)671 static bool window_kvs_cmd_highlight(KviKvsModuleCommandCall * c)
672 {
673 	QString szWnd;
674 	KviWindow * pWnd;
675 	kvs_uint_t level;
676 
677 	KVSM_PARAMETERS_BEGIN(c)
678 	KVSM_PARAMETER("level", KVS_PT_UINT, 0, level)
679 	KVSM_PARAMETER("window_id", KVS_PT_STRING, KVS_PF_OPTIONAL, szWnd)
680 	KVSM_PARAMETERS_END(c)
681 	if(c->parameterList()->count() == 1)
682 	{
683 		pWnd = c->window();
684 	}
685 	else
686 	{
687 		pWnd = g_pApp->findWindow(szWnd.toUtf8().data());
688 		if(!pWnd)
689 		{
690 			if(!c->hasSwitch('q', "quiet"))
691 				c->warning(__tr2qs("The window with ID '%s' doesn't exist"), szWnd.toUtf8().data());
692 			return true;
693 		}
694 	}
695 
696 	//force the previous level to be lower
697 	pWnd->unhighlight();
698 	//level boundaries checking is done by the upstream function
699 	pWnd->highlightMe(level);
700 	return true;
701 }
702 
703 /*
704 	@doc: window.highlightLevel
705 	@type:
706 		function
707 	@title:
708 		$window.highlightLevel
709 	@short:
710 		Returns the current highlight (alert) level of a window
711 	@syntax:
712 		$window.highlightLevel
713 		$window.highlightLevel(<window_id>)
714 	@description:
715 		Every window has a current alert level; it corresponds to an highlight color of that window in the window list.
716 		There are 6 defined levels, they start from 0 (normal) to 5 (max alarm level). The classic window list and the tree window list use different colors to represent these levels. Classic task bar uses options:
717 		[ul][li]colorWindowListNormalText : normal state[/li][li]colorWindowListHighlight1Text : highlight state 1[/li][li]...[/li][li]colorWindowListHighlight5Text : highlight state 5[/li][/ul]
718 		While the tree window list uses options:
719 		[ul][li]colorTreeWindowListForeground : normal state[/li][li]colorTreeWindowListHighlight1Foreground : highlight state 1[/li][li]...[/li][li]colorTreeWindowListHighlight5Foreground : highlight state 5[/li][/ul]
720 		You can use [fnc]$option[/fnc] to read these options and the [cmd]option[/cmd] command to set them.
721 	@seealso:
722 		[fnc]$window.activityTemperature[/fnc]
723 		[fnc]$window.activityLevel[/fnc]
724 		[fnc]$option[/fnc]
725 		[cmd]option[/cmd]
726 */
727 
window_kvs_fnc_highlightLevel(KviKvsModuleFunctionCall * c)728 static bool window_kvs_fnc_highlightLevel(KviKvsModuleFunctionCall * c)
729 {
730 	GET_KVS_FNC_WINDOW_ID
731 	if(pWnd)
732 	{
733 		unsigned int v;
734 		pWnd->highlightMeter(&v);
735 		c->returnValue()->setInteger(v);
736 	}
737 	else
738 	{
739 		c->returnValue()->setInteger(0);
740 	}
741 	return true;
742 }
743 
744 /*
745 	@doc: window.type
746 	@type:
747 		function
748 	@title:
749 		$window.type
750 	@short:
751 		Returns the type of a window
752 	@syntax:
753 		$window.type
754 		$window.type(<window_id>)
755 	@description:
756 		Returns the type of the window with <window_id>.[br]
757 		The form with no parameters returns the type of the current window.[br]
758 		If the window with the specified ID does not exist, an empty string is returned.[br]
759 	@seealso:
760 */
761 
window_kvs_fnc_type(KviKvsModuleFunctionCall * c)762 static bool window_kvs_fnc_type(KviKvsModuleFunctionCall * c)
763 {
764 	GET_KVS_FNC_WINDOW_ID
765 	if(pWnd)
766 	{
767 		c->returnValue()->setString(pWnd->typeString());
768 	}
769 	return true;
770 }
771 
772 /*
773 	@doc: window.context
774 	@type:
775 		function
776 	@title:
777 		$window.context
778 	@short:
779 		Returns the IRC context of a window
780 	@syntax:
781 		$window.context
782 		$window.context(<window_id>)
783 	@description:
784 		Returns the IRC context of the window with the specified <window_id>.[br]
785 		The form with no parameters returns the IRC context of the current window.[br]
786 		If the window with the specified ID does not exist, an empty string is returned.[br]
787 	@seealso:
788 */
789 
window_kvs_fnc_context(KviKvsModuleFunctionCall * c)790 static bool window_kvs_fnc_context(KviKvsModuleFunctionCall * c)
791 {
792 	GET_KVS_FNC_WINDOW_ID
793 	if(pWnd)
794 	{
795 		c->returnValue()->setInteger(pWnd->context() ? pWnd->context()->id() : 0);
796 	}
797 	return true;
798 }
799 
800 /*
801 	@doc: window.caption
802 	@type:
803 		function
804 	@title:
805 		$window.caption
806 	@short:
807 		Returns the caption of a window
808 	@syntax:
809 		$window.caption
810 		$window.caption(<window_id>)
811 	@description:
812 		Returns the caption of the window with <window_id>.[br]
813 		The form with no parameters returns the caption of the current window.[br]
814 		If the window with the specified ID does not exist, an empty string is returned.[br]
815 	@seealso:
816 */
817 
window_kvs_fnc_caption(KviKvsModuleFunctionCall * c)818 static bool window_kvs_fnc_caption(KviKvsModuleFunctionCall * c)
819 {
820 	GET_KVS_FNC_WINDOW_ID
821 	if(pWnd)
822 	{
823 		c->returnValue()->setString(pWnd->plainTextCaption());
824 	}
825 	return true;
826 }
827 
828 /*
829 	@doc: window.listtypes
830 	@type:
831 		command
832 	@title:
833 		window.listtypes
834 	@short:
835 		Lists available types of windows
836 	@syntax:
837 		window.listtypes
838 	@description:
839 		Lists the types of windows that are built in the current release of KVIrc.[br]
840 		This is actually a command and not a static list just because new window
841 		types may be added in subsequent releases.[br]
842 	@seealso:
843 		[cmd]window.listtypes[/cmd]
844 */
845 
window_kvs_cmd_listtypes(KviKvsModuleCommandCall * c)846 static bool window_kvs_cmd_listtypes(KviKvsModuleCommandCall * c)
847 {
848 	c->window()->listWindowTypes();
849 	return true;
850 }
851 
852 /*
853 	@doc: window.list
854 	@type:
855 		function
856 	@title:
857 		$window.list
858 	@short:
859 		Generates lists of windows
860 	@syntax:
861 		$window.list(<type>[,<irc_context_id>])
862 	@description:
863 		Returns an array of window identifiers with a specified type and eventually belonging to a specified
864 		irc context.[br]
865 		<type> is a window type such as 'query' or 'channel'.[br]
866 		See [cmd]window.listtypes[/cmd] for a list of available window types in this KVIrc release.[br]
867 		If <type> is the special word 'all', all the window types are listed.[br]
868 		<irc_context_id> specifies the IRC context in which the windows are searched.[br]
869 		If no <irc_context_id> is specified, the current one is used.[br]
870 		If <irc_context_id> is the special word 'all', all the IRC context are searched.[br]
871 		If <irc_context_id> is the special word 'none' then only windows not belonging to any
872 		irc context are listed.[br]
873 		The special word 'any' used as <irc_context_id> merges the effects of 'all' and 'none'
874 		by searching all the IRC contexts AND the windows not belonging to any IRC context.[br]
875 		The windows that do not belong to any IRC context (such as DCC windows), must be searched
876 		by using 'none' or 'any' as <irc_context_id>.
877 	@examples:
878 		[example]
879 			[comment]# List all the queries of the current IRC context[/comment]
880 			[cmd]echo[/cmd] $window.list(query)
881 			[comment]# Equivalent to the above[/comment]
882 			[cmd]echo[/cmd] $window.list(query,[fnc]$ic[/fnc])
883 			[comment]# List all the channels in all the IRC contexts[/comment]
884 			[cmd]echo[/cmd] $window.list(channel,all)
885 			[comment]# List all the windows in the current IRC context[/comment]
886 			[cmd]echo[/cmd] $window.list(all)
887 			[comment]# List all the windows in all IRC contexts[/comment]
888 			[cmd]echo[/cmd] $window.list(all,all)
889 			[comment]# List all the DCC Send windows: They don't belong to any IRC context[/comment]
890 			[cmd]echo[/cmd] $window.list(dcctransfer,none)
891 			[comment]# List all the user windows created with $window.open[/comment]
892 			[comment]# They may either belong to an IRC context or not[/comment]
893 			[cmd]echo[/cmd] $window.list(userwnd,any)
894 			[comment]# Ok, let's use it[/comment]
895 			[comment]# A nice alias that allows iterating commands through all the consoles[/comment]
896 			[comment]# Note the array returned by $window.list[/comment]
897 			[comment]# This is by LatinSuD :)[/comment]
898 			[cmd]alias[/cmd](iterate)
899 			{
900 				%ctxt[]=[fnc]$window.list[/fnc](console,all)
901 				[cmd]for[/cmd](%i=0;%i<%ctxt[]#;%i++)
902 				{
903 					[cmd]eval[/cmd] -r=%ctxt[%i] $0-
904 				}
905 			}
906 			iterate [cmd]echo[/cmd] Hi ppl! :)
907 			[comment]# The returned array works nicely also in [cmd]foreach[/cmd][/comment]
908 			[comment]# Say hi to all the channels :)[/comment]
909 			[cmd]alias[/cmd](sayallchans)
910 			{
911 				[cmd]foreach[/cmd](%x,[fnc]$window.list[/fnc](channel,all))
912 						[cmd]say[/cmd] -r=%x $0-;
913 			}
914 			sayallchans Hi ppl :)
915 		[/example]
916 	@seealso:
917 		[cmd]window.listtypes[/cmd]
918 */
919 
window_kvs_fnc_list(KviKvsModuleFunctionCall * c)920 static bool window_kvs_fnc_list(KviKvsModuleFunctionCall * c)
921 {
922 	QString szType;
923 	QString szContext;
924 
925 	KVSM_PARAMETERS_BEGIN(c)
926 	KVSM_PARAMETER("type", KVS_PT_STRING, 0, szType)
927 	KVSM_PARAMETER("irc_context_id", KVS_PT_STRING, KVS_PF_OPTIONAL, szContext)
928 	KVSM_PARAMETERS_END(c)
929 	KviKvsArray * pArray = new KviKvsArray();
930 	c->returnValue()->setArray(pArray);
931 
932 	if(szType.isEmpty())
933 	{
934 		c->warning(__tr2qs("Window type or 'all' expected as first parameter"));
935 		return true;
936 	}
937 
938 	int id = 0;
939 
940 	if(KviQString::equalCI(szContext, "all"))
941 	{
942 		// all contexts but no "no_context" windows
943 		bool bAllWindows = KviQString::equalCI(szType, "all");
944 
945 		for(auto & wnd : g_pGlobalWindowDict)
946 		{
947 			if(wnd.second->context())
948 			{
949 				if(bAllWindows)
950 				{
951 					pArray->set(id, new KviKvsVariant(QString(wnd.second->id())));
952 					id++;
953 				}
954 				else
955 				{
956 					if(szType.toLower() == wnd.second->typeString())
957 					{
958 						pArray->set(id, new KviKvsVariant(QString(wnd.second->id())));
959 						id++;
960 					}
961 				}
962 			}
963 		}
964 	}
965 	else if(KviQString::equalCI(szContext, "any"))
966 	{
967 		// all contexts and also "no_context" windows
968 		bool bAllWindows = KviQString::equalCI(szType.toLower(), "all");
969 
970 		for(auto & wnd : g_pGlobalWindowDict)
971 		{
972 			if(bAllWindows)
973 			{
974 				pArray->set(id, new KviKvsVariant(QString(wnd.second->id())));
975 				id++;
976 			}
977 			else
978 			{
979 				if(szType.toLower() == wnd.second->typeString())
980 				{
981 					pArray->set(id, new KviKvsVariant(QString(wnd.second->id())));
982 					id++;
983 				}
984 			}
985 		}
986 	}
987 	else if(KviQString::equalCI(szContext, "none"))
988 	{
989 		// only "no_context" windows
990 		bool bAllWindows = KviQString::equalCI(szType.toLower(), "all");
991 
992 		for(auto & wnd : g_pGlobalWindowDict)
993 		{
994 			if(!wnd.second->context())
995 			{
996 				if(bAllWindows)
997 				{
998 					pArray->set(id, new KviKvsVariant(QString(wnd.second->id())));
999 					id++;
1000 				}
1001 				else
1002 				{
1003 					if(szType.toLower() == wnd.second->typeString())
1004 					{
1005 						pArray->set(id, new KviKvsVariant(QString(wnd.second->id())));
1006 						id++;
1007 					}
1008 				}
1009 			}
1010 		}
1011 	}
1012 	else
1013 	{
1014 		// some specified context
1015 		unsigned int uId = 0;
1016 
1017 		if(!szContext.isEmpty())
1018 		{
1019 			// specific context
1020 			bool bOk;
1021 			uId = szContext.toUInt(&bOk);
1022 			if(!bOk)
1023 			{
1024 				c->warning(__tr2qs("Invalid IRC context ID '%Q'"), &szContext);
1025 				return true;
1026 			}
1027 		}
1028 		else
1029 		{
1030 			// current irc context
1031 			if(!c->window()->console())
1032 			{
1033 				return true;
1034 			}
1035 			uId = c->window()->context()->id();
1036 		}
1037 
1038 		bool bAllWindows = KviQString::equalCI(szType.toLower(), "all");
1039 
1040 		for(auto & wnd : g_pGlobalWindowDict)
1041 		{
1042 			if(wnd.second->context())
1043 			{
1044 				if(wnd.second->context()->id() == uId)
1045 				{
1046 					if(bAllWindows)
1047 					{
1048 						pArray->set(id, new KviKvsVariant(QString(wnd.second->id())));
1049 						id++;
1050 					}
1051 					else
1052 					{
1053 						if(szType.toLower() == wnd.second->typeString())
1054 						{
1055 							pArray->set(id, new KviKvsVariant(QString(wnd.second->id())));
1056 							id++;
1057 						}
1058 					}
1059 				}
1060 			}
1061 		}
1062 	}
1063 	return true;
1064 }
1065 
1066 /*
1067 	@doc: window.open
1068 	@type:
1069 		function
1070 	@title:
1071 		$window.open
1072 	@short:
1073 		Creates and opens a new window
1074 	@syntax:
1075 		$window.open([<flags:string>[,<caption:string>[,<irc_context:integer>[,<icon:integer>]]]])
1076 	@description:
1077 		Creates a new window, opens it and returns its window identifier.
1078 		<flags> may be any combination of the following flag characters:[br]
1079 		[b]i[/b]: Causes the window to have an input field in that
1080 		the user can type commands or text. The text typed is reported
1081 		by the [event:ontextinput]OnTextInput[/event] event.[br]
1082 		[b]m[/b]: Creates a window that is initially minimized.[br]
1083 		[b]q[/b]: Don't print warning messages during the creation.[br]
1084 		If <caption> is given then the new window will have it as the initial plain text <caption>.
1085 		You can change the caption later by calling [cmd]window.setWindowTitle[/cmd].[br]
1086 		If <irc_context> is given then the new window is bound to the specified IRC context
1087 		and will be destroyed when the attached console closes.
1088 		If <irc_context> is omitted or is 0 then the window will be context free (not bound
1089 		to any context) and will exist until it is closed by the GUI, by a [cmd]window.close[/cmd]
1090 		call or until KVIrc terminates. When <irc_context> is given but is not valid
1091 		then a warning is printed (unless the q flag is used) and the created window is context free.[br]
1092 		You will generally use the [fnc]$context[/fnc] function to retrieve the current IRC context ID.[br]
1093 		[br]
1094 		<icon> is interpreted as the index of the internal icon to be used
1095 		for the window. If <icon> is omitted then a default icon is used.[br]
1096 	@examples:
1097 		[example]
1098 			%w = $window.open()
1099 			[cmd]window.close[/cmd] %w
1100 			%w = $window.open("m","My funky window")
1101 			[cmd]window.close[/cmd] %w
1102 			%w = $window.open("im","My funky window 2",$context,10)
1103 		[/example]
1104 	@seealso:
1105 		[cmd]window.close[/cmd]
1106 */
1107 
window_kvs_fnc_open(KviKvsModuleFunctionCall * c)1108 static bool window_kvs_fnc_open(KviKvsModuleFunctionCall * c)
1109 {
1110 	QString szFlags;
1111 	QString szCaption;
1112 	kvs_uint_t uCtx;
1113 	QString szIcon;
1114 
1115 	KVSM_PARAMETERS_BEGIN(c)
1116 	KVSM_PARAMETER("flags", KVS_PT_STRING, KVS_PF_OPTIONAL, szFlags)
1117 	KVSM_PARAMETER("caption", KVS_PT_STRING, KVS_PF_OPTIONAL, szCaption)
1118 	KVSM_PARAMETER("irc_context", KVS_PT_UINT, KVS_PF_OPTIONAL, uCtx)
1119 	KVSM_PARAMETER("icon", KVS_PT_STRING, KVS_PF_OPTIONAL, szIcon)
1120 	KVSM_PARAMETERS_END(c)
1121 	QPixmap * pPix = g_pIconManager->getImage(szIcon);
1122 	if(!pPix)
1123 	{
1124 
1125 		c->warning(__tr2qs("The specified icon doesn't exist: switching to 'none'"));
1126 		szIcon.prepend("$icon(");
1127 		szIcon.append(")");
1128 	}
1129 	int iFlags = 0;
1130 	if(szFlags.contains('i'))
1131 		iFlags |= UserWindow::HasInput;
1132 
1133 	KviConsoleWindow * pConsole = nullptr;
1134 	if(c->parameterList()->count() >= 3)
1135 	{
1136 		pConsole = g_pApp->findConsole(uCtx);
1137 		if(!pConsole && !szFlags.contains('q'))
1138 		{
1139 			c->warning(__tr2qs("The specified IRC context is not valid: creating a context free window"));
1140 		}
1141 	}
1142 
1143 	UserWindow * pWnd = new UserWindow(
1144 	    szCaption.toUtf8().data(),
1145 	    szIcon,
1146 	    pConsole,
1147 	    iFlags);
1148 
1149 	g_pMainWindow->addWindow(pWnd, !szFlags.contains('m'));
1150 
1151 	c->returnValue()->setInteger(QString(pWnd->id()).toUInt());
1152 	return true;
1153 }
1154 
1155 /*
1156 	@doc: window.setWindowTitle
1157 	@type:
1158 		command
1159 	@title:
1160 		window.setWindowTitle
1161 	@short:
1162 		Sets the caption of a user window
1163 	@syntax:
1164 		window.setWindowTitle [-q] <window_id> <plain_text_caption>
1165 	@switches:
1166 		!sw: -q | --quiet
1167 		Be quiet
1168 	@description:
1169 		Sets the caption of the user window specified by <window_id> to <plain_text_caption>.[br]
1170 		If <window_id> is an empty string then the current window is assumed.[br]
1171 		If the window does not exist then a warning is printed unless the -q switch is used.[br]
1172 	@seealso:
1173 */
1174 
window_kvs_cmd_setWindowTitle(KviKvsModuleCommandCall * c)1175 static bool window_kvs_cmd_setWindowTitle(KviKvsModuleCommandCall * c)
1176 {
1177 	QString szWnd;
1178 	QString szPlain;
1179 	KviWindow * pWnd;
1180 	KVSM_PARAMETERS_BEGIN(c)
1181 	KVSM_PARAMETER("window_id", KVS_PT_STRING, 0, szWnd)
1182 	KVSM_PARAMETER("plain_text_caption", KVS_PT_STRING, 0, szPlain)
1183 	KVSM_PARAMETERS_END(c)
1184 
1185 	pWnd = g_pApp->findWindow(szWnd.toUtf8().data());
1186 	if(!pWnd)
1187 	{
1188 		if(!c->hasSwitch('q', "quiet"))
1189 			c->warning(__tr2qs("The window with ID '%s' doesn't exist"), szWnd.toUtf8().data());
1190 		return true;
1191 	}
1192 
1193 	if(pWnd->type() == KviWindow::UserWindow)
1194 	{
1195 		((UserWindow *)pWnd)->setWindowTitleStrings(szPlain);
1196 	}
1197 	else
1198 	{
1199 		//store the window title (needed for functions that search windows by their captions)
1200 		((KviWindow *)pWnd)->setFixedCaption(szPlain);
1201 		((KviWindow *)pWnd)->setWindowTitle(szPlain);
1202 	}
1203 	return true;
1204 }
1205 
1206 /*
1207 	@doc: window.setInputText
1208 	@type:
1209 		command
1210 	@title:
1211 		window.setInputText
1212 	@short:
1213 		Sets the window input text to <text>
1214 	@syntax:
1215 		window.setInputText [-q] <window_id:integer> <text:string>
1216 	@switches:
1217 		!sw: -q | --quiet
1218 		Be quiet
1219 	@description:
1220 		Sets the window input text to <text>
1221 	@seealso:
1222 	[cmd]window.setInputText[/cmd] [cmd]window.insertInInputText[/cmd] [fnc]$window.inputText[/fnc]
1223 */
1224 
window_kvs_cmd_setInputText(KviKvsModuleCommandCall * c)1225 static bool window_kvs_cmd_setInputText(KviKvsModuleCommandCall * c)
1226 {
1227 	QString szWnd;
1228 	QString szText;
1229 	KviWindow * pWnd;
1230 	KVSM_PARAMETERS_BEGIN(c)
1231 	KVSM_PARAMETER("window_id", KVS_PT_STRING, 0, szWnd)
1232 	KVSM_PARAMETER("text", KVS_PT_STRING, 0, szText)
1233 	KVSM_PARAMETERS_END(c)
1234 
1235 	pWnd = g_pApp->findWindow(szWnd.toUtf8().data());
1236 	if(!pWnd)
1237 	{
1238 		if(!c->hasSwitch('q', "quiet"))
1239 			c->warning(__tr2qs("The window with ID '%s' doesn't exist"), szWnd.toUtf8().data());
1240 		return true;
1241 	}
1242 	if(pWnd->input())
1243 		pWnd->input()->setText(szText);
1244 	else if(!c->hasSwitch('q', "quiet"))
1245 		c->warning(__tr2qs("Window doesn't have input widget"));
1246 
1247 	return true;
1248 }
1249 
1250 /*
1251 	@doc: window.insertInInputText
1252 	@type:
1253 		command
1254 	@title:
1255 		window.insertInInputText
1256 	@short:
1257 		Sets the window input text to <text>
1258 	@syntax:
1259 		window.insertInInputText [-q] <window_id:integer> <text:string>
1260 	@switches:
1261 		!sw: -q | --quiet
1262 		Be quiet
1263 	@description:
1264 		Sets the window input text to <text>
1265 	@seealso:
1266 		[cmd]window.setInputText[/cmd], [fnc]$window.inputText[/fnc]
1267 */
1268 
window_kvs_cmd_insertInInputText(KviKvsModuleCommandCall * c)1269 static bool window_kvs_cmd_insertInInputText(KviKvsModuleCommandCall * c)
1270 {
1271 	QString szWnd;
1272 	QString szText;
1273 	KviWindow * pWnd;
1274 	KVSM_PARAMETERS_BEGIN(c)
1275 	KVSM_PARAMETER("window_id", KVS_PT_STRING, 0, szWnd)
1276 	KVSM_PARAMETER("text", KVS_PT_STRING, 0, szText)
1277 	KVSM_PARAMETERS_END(c)
1278 
1279 	pWnd = g_pApp->findWindow(szWnd.toUtf8().data());
1280 	if(!pWnd)
1281 	{
1282 		if(!c->hasSwitch('q', "quiet"))
1283 			c->warning(__tr2qs("The window with ID '%s' doesn't exist"), szWnd.toUtf8().data());
1284 		return true;
1285 	}
1286 	if(pWnd->input())
1287 		pWnd->input()->insertText(szText);
1288 	else if(!c->hasSwitch('q', "quiet"))
1289 		c->warning(__tr2qs("Window doesn't have input widget"));
1290 
1291 	return true;
1292 }
1293 
1294 /*
1295 	@doc: $window.inputText
1296 	@type:
1297 		function
1298 	@title:
1299 		$window.inputText
1300 	@short:
1301 		Returns the window input line text
1302 	@syntax:
1303 		$window.inputText(<window_id:integer>)
1304 	@description:
1305 		Returns the window input line text
1306 	@seealso:
1307 		[cmd]window.setInputText[/cmd],
1308 		[cmd]window.insertInInputText[/cmd]
1309 */
1310 
window_kvs_fnc_inputText(KviKvsModuleFunctionCall * c)1311 static bool window_kvs_fnc_inputText(KviKvsModuleFunctionCall * c)
1312 {
1313 	GET_KVS_FNC_WINDOW_ID
1314 	if(pWnd)
1315 	{
1316 		if(pWnd->input())
1317 			c->returnValue()->setString(pWnd->input()->text());
1318 	}
1319 	return true;
1320 }
1321 
1322 /*
1323 	@doc: window.setBackground
1324 	@type:
1325 		command
1326 	@title:
1327 		window.setBackground
1328 	@short:
1329 		Sets the background image of a window
1330 	@syntax:
1331 		window.setBackground [-q] <window_id:integer> [image_id:string]
1332 	@switches:
1333 		!sw: -q | --quiet
1334 		Be quiet
1335 	@description:
1336 		Sets the background image of the window specified by <window_id> to <image_id>.[br]
1337 		If <image_id> is not provided, then the background is cleared and reset to global setting.[br]
1338 		If the specified window or the background image does not exist a warning is printed unless the -q switch is used.
1339 	@seealso:
1340 */
1341 
window_kvs_cmd_setBackground(KviKvsModuleCommandCall * c)1342 static bool window_kvs_cmd_setBackground(KviKvsModuleCommandCall * c)
1343 {
1344 	QString szWnd;
1345 	QString szBackground;
1346 	KVSM_PARAMETERS_BEGIN(c)
1347 	KVSM_PARAMETER("window_id", KVS_PT_STRING, 0, szWnd)
1348 	KVSM_PARAMETER("background_path", KVS_PT_STRING, KVS_PF_OPTIONAL, szBackground)
1349 	KVSM_PARAMETERS_END(c)
1350 
1351 	KviWindow * pWnd = g_pApp->findWindow(szWnd.toUtf8().data());
1352 	if(!pWnd)
1353 	{
1354 		if(!c->hasSwitch('q', "quiet"))
1355 			c->warning(__tr2qs("The window with ID '%s' doesn't exist"), szWnd.toUtf8().data());
1356 		return true;
1357 	}
1358 
1359 	if(!pWnd->view())
1360 	{
1361 		if(!c->hasSwitch('q', "quiet"))
1362 			c->warning(__tr2qs("The window with ID '%s' does not support background images!"));
1363 		return true;
1364 	}
1365 
1366 	QPixmap p;
1367 	if(!szBackground.isEmpty())
1368 	{
1369 		p = QPixmap(szBackground);
1370 		if(p.isNull())
1371 		{
1372 			if(!c->hasSwitch('q', "quiet"))
1373 				c->warning(__tr2qs("Failed to load the selected image!"));
1374 			return true;
1375 		}
1376 	}
1377 
1378 	pWnd->view()->setPrivateBackgroundPixmap(p);
1379 	if(pWnd->isChannel())
1380 	{
1381 		KviChannelWindow * pChanWin = (KviChannelWindow *)pWnd;
1382 		if(pChanWin->messageView())
1383 			pChanWin->messageView()->setPrivateBackgroundPixmap(p);
1384 	}
1385 
1386 	return true;
1387 }
1388 
1389 /*
1390 	@doc: window.savePropertiesAsDefault
1391 	@type:
1392 		command
1393 	@title:
1394 		window.savePropertiesAsDefault
1395 	@short:
1396 		Saves the window properties as default
1397 	@syntax:
1398 		window.savePropertiesAsDefault [window_id]
1399 	@description:
1400 		Saves the window properties of the specified window as default for every window
1401 		of the same type (e.g. all queries, all channels, ..).
1402 		If window_id is missing then the current window properties are used.
1403 */
1404 
window_kvs_cmd_savePropertiesAsDefault(KviKvsModuleCommandCall * c)1405 static bool window_kvs_cmd_savePropertiesAsDefault(KviKvsModuleCommandCall * c)
1406 {
1407 	GET_KVS_WINDOW_ID
1408 	if(pWnd)
1409 	{
1410 		pWnd->savePropertiesAsDefault();
1411 	}
1412 	return true;
1413 }
1414 
1415 #ifdef COMPILE_CRYPT_SUPPORT
initializeCryptEngine(KviCryptEngine * eng,KviCString & szEncryptKey,KviCString & szDecryptKey,QString & szError)1416 static bool initializeCryptEngine(KviCryptEngine * eng, KviCString & szEncryptKey, KviCString & szDecryptKey, QString & szError)
1417 {
1418 	char * encKey = nullptr;
1419 
1420 	char * tmpKey;
1421 	int encKeyLen = szEncryptKey.hexToBuffer(&tmpKey, false);
1422 	if(encKeyLen > 0)
1423 	{
1424 		encKey = (char *)KviMemory::allocate(encKeyLen);
1425 		KviMemory::move(encKey, tmpKey, encKeyLen);
1426 		KviCString::freeBuffer(tmpKey);
1427 	}
1428 	else
1429 	{
1430 		szError = __tr2qs("The encryption key wasn't a valid hexadecimal string");
1431 		return false;
1432 	}
1433 
1434 	char * decKey = nullptr;
1435 
1436 	int decKeyLen = szDecryptKey.hexToBuffer(&tmpKey, false);
1437 	if(decKeyLen > 0)
1438 	{
1439 		decKey = (char *)KviMemory::allocate(decKeyLen);
1440 		KviMemory::move(decKey, tmpKey, decKeyLen);
1441 		KviCString::freeBuffer(tmpKey);
1442 	}
1443 	else
1444 	{
1445 		szError = __tr2qs("The decryption key wasn't a valid hexadecimal string");
1446 		if(encKey)
1447 			KviMemory::free(encKey);
1448 		return false;
1449 	}
1450 	bool bRet = eng->init(encKey, encKeyLen, decKey, decKeyLen);
1451 	if(!bRet)
1452 		szError = eng->lastError();
1453 	if(encKey)
1454 		KviMemory::free(encKey);
1455 	if(decKey)
1456 		KviMemory::free(decKey);
1457 	return bRet;
1458 }
1459 #endif
1460 
1461 /*
1462 	@doc: window.setCryptEngine
1463 	@type:
1464 		command
1465 	@title:
1466 		window.setCryptEngine
1467 	@short:
1468 		Sets the crypt engine for a window that supports it
1469 	@syntax:
1470 		window.setCryptEngine [-q] [-n] [-m] <window_id:integer> <enginename:string> <hex_encrypt_key:string> [hex_decrypt_key:string]
1471 	@switches:
1472 		!sw: -q | --quiet
1473 		Be quiet: do echo the raw data.
1474 		!sw: -n | --onlydecrypt
1475 		Disables encryption
1476 		!sw: -m | --onlyencrypt
1477 		Disables decryption
1478 	@description:
1479 		Sets the specified [doc:crypt_engines]cryptographic engine[/doc] for the window. If <enginename> is empty
1480 		then any current encryption engine is removed (i.e. encrypting is disabled).
1481 		The must be both expressed in hexadecimal notation and are internally transformed in bytes.
1482 		If only the encrypt key is specified then it will be used for both encrypting and
1483 		decrypting. This command works only if cryptography support is compiled in.
1484 	@examples:
1485 		[example]
1486 		[comment]# This is a really lame example :D[/comment]
1487 		alias(saylame)
1488 		{
1489 			window.setCryptEngine $window Lamerizer
1490 			say $0-
1491 			window.setCryptEngine $window
1492 		}
1493 		saylame Hello eleet!
1494 		[/example]
1495 
1496 	@seealso:
1497 		[fnc]$asciiToHex[/fnc], [fnc]$features[/fnc]
1498 */
1499 
window_kvs_cmd_setCryptEngine(KviKvsModuleCommandCall * c)1500 static bool window_kvs_cmd_setCryptEngine(KviKvsModuleCommandCall * c)
1501 {
1502 	QString szWnd;
1503 	QString szEngine;
1504 	QString szEncryptKey;
1505 	QString szDecryptKey;
1506 
1507 	KVSM_PARAMETERS_BEGIN(c)
1508 	KVSM_PARAMETER("window_id", KVS_PT_STRING, 0, szWnd)
1509 	KVSM_PARAMETER("enginename", KVS_PT_STRING, KVS_PF_OPTIONAL, szEngine)
1510 	KVSM_PARAMETER("hex_encrypt_key", KVS_PT_STRING, KVS_PF_OPTIONAL, szEncryptKey)
1511 	KVSM_PARAMETER("hex_decrypt_key", KVS_PT_STRING, KVS_PF_OPTIONAL, szDecryptKey)
1512 	KVSM_PARAMETERS_END(c)
1513 	if(szDecryptKey.isEmpty())
1514 		szDecryptKey = szEncryptKey;
1515 #ifdef COMPILE_CRYPT_SUPPORT
1516 	KviWindow * pWnd = g_pApp->findWindow(szWnd.toUtf8().data());
1517 	if(!pWnd)
1518 	{
1519 		if(!c->hasSwitch('q', "quiet"))
1520 			c->warning(__tr2qs("The window with ID '%s' doesn't exist"), szWnd.toUtf8().data());
1521 		return true;
1522 	}
1523 	if(c->hasSwitch('n', "onlydecrypt") && c->hasSwitch('m', "onlyencrypt"))
1524 	{
1525 		if(!c->hasSwitch('q', "quiet"))
1526 			c->warning(__tr2qs("Both -n and -m switches specified, -n takes precedence"));
1527 	}
1528 
1529 	if(szEngine.isEmpty())
1530 	{
1531 		pWnd->setCryptSessionInfo(nullptr);
1532 	}
1533 	else
1534 	{
1535 		if(szEncryptKey.isEmpty() || szDecryptKey.isEmpty())
1536 		{
1537 			if(!c->hasSwitch('q', "quiet"))
1538 				c->warning(__tr2qs("No encryption key specified: can't allocate engine"));
1539 			return true;
1540 		}
1541 
1542 		(void)g_pModuleManager->loadModulesByCaps("crypt");
1543 
1544 		KviCryptEngine * e = g_pCryptEngineManager->allocateEngine(szEngine.toUtf8().data());
1545 		if(e)
1546 		{
1547 			KviCString enc = KviCString(szEncryptKey.toUtf8().data());
1548 			KviCString dec = KviCString(szDecryptKey.toUtf8().data());
1549 			QString szError;
1550 			if(initializeCryptEngine(e, enc, dec, szError))
1551 			{
1552 				KviCryptSessionInfo * inf = KviCryptController::allocateCryptSessionInfo();
1553 				inf->m_pEngine = e;
1554 				inf->m_szEngineName = szEngine;
1555 
1556 				inf->m_bDoEncrypt = (!c->hasSwitch('n', "onlydecrypt"));
1557 				inf->m_bDoDecrypt = (!c->hasSwitch('m', "onlyencrypt")) || c->hasSwitch('n', "onlydecrypt");
1558 				pWnd->setCryptSessionInfo(inf);
1559 			}
1560 			else
1561 			{
1562 				if(szError.isEmpty())
1563 					szError = __tr2qs("Unknown engine error");
1564 				g_pCryptEngineManager->deallocateEngine(e);
1565 				if(!c->hasSwitch('q', "quiet"))
1566 					c->warning(__tr2qs("Failed to initialize the specified encryption engine: %Q"), &szError);
1567 			}
1568 		}
1569 		else
1570 		{
1571 			if(!c->hasSwitch('q', "quiet"))
1572 				c->warning(__tr2qs("The encryption engine \"%Q\" doesn't exist"), &szEngine);
1573 		}
1574 	}
1575 #else
1576 	if(!c->hasSwitch('q', "quiet"))
1577 		c->warning(__tr2qs("This executable has been compiled without crypt support"));
1578 #endif
1579 	return true;
1580 }
1581 
1582 /*
1583 	@doc: $window.cryptEngine
1584 	@type:
1585 		function
1586 	@title:
1587 		$window.cryptEngine
1588 	@short:
1589 		Returns the name of the encryption engine currently set in a window
1590 	@syntax:
1591 		$window.cryptEngine(<window_id:integer>)
1592 	@description:
1593 		Returns the name of the encryption engine set in the current window.
1594 		If no current engine is set then empty string is returned.
1595 	@seealso:
1596 		[cmd]window.setCryptEngine[/cmd]
1597 */
1598 
window_kvs_fnc_cryptEngine(KviKvsModuleFunctionCall * c)1599 static bool window_kvs_fnc_cryptEngine(KviKvsModuleFunctionCall * c)
1600 {
1601 	GET_KVS_FNC_WINDOW_ID
1602 	if(pWnd)
1603 	{
1604 #ifdef COMPILE_CRYPT_SUPPORT
1605 		if(KviCryptSessionInfo * pCryptSessionInfo = pWnd->cryptSessionInfo())
1606 			c->returnValue()->setString(pCryptSessionInfo->m_szEngineName);
1607 #else  //!COMPILE_CRYPT_SUPPORT
1608 // do nothing
1609 #endif //!COMPILE_CRYPT_SUPPORT
1610 	}
1611 	return true;
1612 }
1613 
window_kvs_fnc_fake(KviKvsModuleFunctionCall * c)1614 static bool window_kvs_fnc_fake(KviKvsModuleFunctionCall * c)
1615 {
1616 	return true;
1617 }
1618 
window_kvs_cmd_fake(KviKvsModuleCommandCall * c)1619 static bool window_kvs_cmd_fake(KviKvsModuleCommandCall * c)
1620 {
1621 	qDebug("This command was removed due to structural interface changes");
1622 	return true;
1623 }
1624 
window_module_init(KviModule * m)1625 static bool window_module_init(KviModule * m)
1626 {
1627 	KVSM_REGISTER_FUNCTION(m, "activityTemperature", window_kvs_fnc_activityTemperature);
1628 	KVSM_REGISTER_FUNCTION(m, "activityLevel", window_kvs_fnc_activityLevel);
1629 	KVSM_REGISTER_FUNCTION(m, "highlightLevel", window_kvs_fnc_highlightLevel);
1630 	KVSM_REGISTER_FUNCTION(m, "console", window_kvs_fnc_console);
1631 	KVSM_REGISTER_FUNCTION(m, "hasUserFocus", window_kvs_fnc_hasUserFocus);
1632 	KVSM_REGISTER_FUNCTION(m, "hasOutput", window_kvs_fnc_hasOutput);
1633 	KVSM_REGISTER_FUNCTION(m, "isDocked", window_kvs_fnc_isDocked);
1634 	KVSM_REGISTER_FUNCTION(m, "isSplitView", window_kvs_fnc_isSplitView);
1635 	KVSM_REGISTER_FUNCTION(m, "isMinimized", window_kvs_fnc_fake); // compat only
1636 	KVSM_REGISTER_FUNCTION(m, "isMaximized", window_kvs_fnc_fake); // compat only
1637 	KVSM_REGISTER_FUNCTION(m, "caption", window_kvs_fnc_caption);
1638 	KVSM_REGISTER_FUNCTION(m, "type", window_kvs_fnc_type);
1639 	KVSM_REGISTER_FUNCTION(m, "exists", window_kvs_fnc_exists);
1640 	KVSM_REGISTER_FUNCTION(m, "hasInput", window_kvs_fnc_hasInput);
1641 	KVSM_REGISTER_FUNCTION(m, "list", window_kvs_fnc_list);
1642 	KVSM_REGISTER_FUNCTION(m, "open", window_kvs_fnc_open);
1643 	KVSM_REGISTER_FUNCTION(m, "inputText", window_kvs_fnc_inputText);
1644 	KVSM_REGISTER_FUNCTION(m, "context", window_kvs_fnc_context);
1645 	KVSM_REGISTER_FUNCTION(m, "cryptEngine", window_kvs_fnc_cryptEngine);
1646 
1647 	KVSM_REGISTER_SIMPLE_COMMAND(m, "highlight", window_kvs_cmd_highlight);
1648 	KVSM_REGISTER_SIMPLE_COMMAND(m, "close", window_kvs_cmd_close);
1649 	KVSM_REGISTER_SIMPLE_COMMAND(m, "clearOutput", window_kvs_cmd_clearOutput);
1650 	KVSM_REGISTER_SIMPLE_COMMAND(m, "dock", window_kvs_cmd_dock);
1651 	KVSM_REGISTER_SIMPLE_COMMAND(m, "undock", window_kvs_cmd_undock);
1652 	KVSM_REGISTER_SIMPLE_COMMAND(m, "splitView", window_kvs_cmd_splitView);
1653 	KVSM_REGISTER_SIMPLE_COMMAND(m, "unsplitView", window_kvs_cmd_unsplitView);
1654 	KVSM_REGISTER_SIMPLE_COMMAND(m, "minimize", window_kvs_cmd_fake);
1655 	KVSM_REGISTER_SIMPLE_COMMAND(m, "maximize", window_kvs_cmd_fake);
1656 	KVSM_REGISTER_SIMPLE_COMMAND(m, "restore", window_kvs_cmd_fake);
1657 	KVSM_REGISTER_SIMPLE_COMMAND(m, "activate", window_kvs_cmd_activate);
1658 	KVSM_REGISTER_SIMPLE_COMMAND(m, "demandAttention", window_kvs_cmd_demandAttention);
1659 	KVSM_REGISTER_SIMPLE_COMMAND(m, "listtypes", window_kvs_cmd_listtypes);
1660 	KVSM_REGISTER_SIMPLE_COMMAND(m, "setBackground", window_kvs_cmd_setBackground);
1661 	KVSM_REGISTER_SIMPLE_COMMAND(m, "setWindowTitle", window_kvs_cmd_setWindowTitle);
1662 	KVSM_REGISTER_SIMPLE_COMMAND(m, "setCryptEngine", window_kvs_cmd_setCryptEngine);
1663 	KVSM_REGISTER_SIMPLE_COMMAND(m, "setInputText", window_kvs_cmd_setInputText);
1664 	KVSM_REGISTER_SIMPLE_COMMAND(m, "insertInInputText", window_kvs_cmd_insertInInputText);
1665 	KVSM_REGISTER_SIMPLE_COMMAND(m, "savePropertiesAsDefault", window_kvs_cmd_savePropertiesAsDefault);
1666 
1667 	return true;
1668 }
1669 
window_module_cleanup(KviModule *)1670 static bool window_module_cleanup(KviModule *)
1671 {
1672 	while(!g_pUserWindowList.empty())
1673 	{
1674 		auto & w = g_pUserWindowList.front();
1675 		w->close();
1676 	}
1677 	return true;
1678 }
1679 
window_module_can_unload(KviModule *)1680 static bool window_module_can_unload(KviModule *)
1681 {
1682 	return g_pUserWindowList.empty();
1683 }
1684 
1685 KVIRC_MODULE(
1686     "Window",                                                            // module name
1687     "4.0.0",                                                             // module version
1688     "Copyright (C) 2001-2004 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
1689     "KVIrc window management functions",
1690     window_module_init,
1691     window_module_can_unload,
1692     0,
1693     window_module_cleanup,
1694     0)
1695