1 //=============================================================================
2 //
3 //   File : KviKvsCoreFunctions_gl.cpp
4 //   Creation date : Fri 31 Oct 2003 01:52:04 by Szymon Stefanek
5 //
6 //   This file is part of the KVIrc IRC client distribution
7 //   Copyright (C) 2003-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 "KviKvsCoreFunctions.h"
26 #include "KviKvsKernel.h"
27 #include "KviKvsTimerManager.h"
28 #include "KviKvsArrayCast.h"
29 #include "KviLocale.h"
30 #include "KviInput.h"
31 #include "KviApplication.h"
32 #include "KviChannelWindow.h"
33 #include "KviConsoleWindow.h"
34 #include "KviIconManager.h"
35 #include "KviControlCodes.h"
36 #include "KviMainWindow.h"
37 #include "KviTimeUtils.h"
38 #include "KviKvsEventManager.h"
39 #include "KviKvsEventHandler.h"
40 #include "KviLagMeter.h"
41 #include "KviIrcUserEntry.h"
42 
43 #include <QRegExp>
44 
45 namespace KviKvsCoreFunctions
46 {
47 	/*
48 		@doc:	gender
49 		@type:
50 			function
51 		@title:
52 			$gender
53 		@short:
54 			Returns the gender of the specified user
55 		@syntax:
56 			<string> $gender(<nickname:string>)
57 		@description:
58 			Returns the gender, or 'unknown' if not set from remote user, of the specified IRC user IF it is known.[br]
59 			The gender is known if [fnc]$isWellKnown[/fnc] returns 1.[br]
60 			The gender is generally known if the user is on a channel with you
61 			or has an open query with you.[br]
62 			Detailed explanation:[br]
63 			KVIrc has an internal database of users that are currently
64 			visible by *this client*: this includes users on open channels
65 			and queries.[br] The other IRC users are [b]not[/b] in the database:
66 			this means that KVIrc knows [b]nothing[/b] about them and can't return
67 			any information immediately. In this case this function will return
68 			an EMPTY string.[br]
69 			If a user is in the database, at least his nickname is known.[br]
70 			The username and hostname are known only if the server provides that information
71 			spontaneously or after a KVIrc request.[br]
72 			KVIrc requests user information for all the users in open queries
73 			and channels. This information takes some time to be retrieved,
74 			in this interval of time KVIrc knows only the user's nickname.
75 			This function will return the string [b]*[/b] in this case.[br]
76 		@seealso:
77 			[fnc]$isWellKnown[/fnc], [fnc]$hostname[/fnc], [fnc]$realname[/fnc], [cmd]$username[/cmd]
78 	*/
79 
KVSCF(gender)80 	KVSCF(gender)
81 	{
82 		QString szNick;
83 
84 		KVSCF_PARAMETERS_BEGIN
85 		KVSCF_PARAMETER("nick", KVS_PT_NONEMPTYSTRING, 0, szNick)
86 		KVSCF_PARAMETERS_END
87 
88 		KviConsoleWindow * c = KVSCF_pContext->window()->console();
89 		if(c && c->isConnected())
90 		{
91 			KviIrcUserEntry * e = KVSCF_pContext->window()->connection()->userDataBase()->find(szNick);
92 			if(e)
93 			{
94 				switch(e->gender())
95 				{
96 					case KviIrcUserEntry::Male:
97 						KVSCF_pRetBuffer->setString(QStringLiteral("male"));
98 						break;
99 					case KviIrcUserEntry::Female:
100 						KVSCF_pRetBuffer->setString(QStringLiteral("female"));
101 						break;
102 					default:
103 						KVSCF_pRetBuffer->setString(QStringLiteral("unknown"));
104 				}
105 				return true;
106 			}
107 		}
108 
109 		KVSCF_pRetBuffer->setNothing();
110 		return true;
111 	}
112 
113 	/*
114 		@doc: globals
115 		@type:
116 			function
117 		@title:
118 			$globals
119 		@short:
120 			Dump globals variables
121 		@syntax:
122 			<hash> $globals()
123 		@description:
124 			Returns an hashtable of all global variables set.
125 		@examples:
126 			[example]
127 				echo $globals
128 			[/example]
129 		@seealso:
130 			[cmd]global[/cmd]
131 			[cmd]unset[/cmd]
132 			[fnc]$hash[/fnc]
133 	*/
134 
KVSCF(globals)135 	KVSCF(globals)
136 	{
137 		KVSCF_pRetBuffer->setHash(new KviKvsHash(*(KviKvsKernel::instance()->globalVariables())));
138 		return true;
139 	}
140 
141 	/*
142 		@doc: hash
143 		@type:
144 			function
145 		@title:
146 			$hash
147 		@short:
148 			Explicitly creates a hash
149 		@syntax:
150 			<hash> $hash([<key:string>,<value:variant>,[<key:string>,<value:variant>]],...)
151 		@description:
152 			Returns a hash with the specified items. Each <value> is indexed by the preceding <key>.
153 			This is just an explicit way of creating a hash with a defined set of items,
154 			useful for increasing readability.
155 		@examples:
156 			[example]
157 				[cmd]alias[/cmd](test){ [cmd]return[/cmd] $hash(1,X,2,Y,3,Z); };
158 				%x = $test();
159 				[cmd]foreach[/cmd](%y,%x)
160 				{
161 					[cmd]echo[/cmd] %y;
162 				}
163 				[cmd]foreach[/cmd](%y,[fnc]$keys[/fnc](%x))
164 				{
165 					[cmd]echo[/cmd] %y
166 				}
167 			[/example]
168 		@seealso:
169 			[fnc]$array[/fnc]
170 	*/
171 
KVSCF(hash)172 	KVSCF(hash)
173 	{
174 		KviKvsHash * a = new KviKvsHash();
175 
176 		for(KviKvsVariant * key = KVSCF_pParams->first(); key; key = KVSCF_pParams->next())
177 		{
178 			KviKvsVariant * val = KVSCF_pParams->next();
179 			if(!val)
180 				break;
181 			QString sz;
182 			key->asString(sz);
183 			a->set(sz, new KviKvsVariant(*val));
184 		}
185 
186 		KVSCF_pRetBuffer->setHash(a);
187 		return true;
188 	}
189 
190 	/*
191 		@doc: hextoAscii
192 		@type:
193 			function
194 		@title:
195 			$hexToAscii
196 		@short:
197 			Returns a decoded hex string
198 		@syntax:
199 			$hexToAscii(<hex_encoded_string>)
200 		@description:
201 			Decodes the <hex_encoded_string> to its ASCII representation.
202 		@examples:
203 			[example]
204 				[cmd]echo[/cmd] $hexToAscii(6B76697263)
205 			[/example]
206 		@seealso:
207 			[fnc]$asciiToHex[/fnc]
208 	*/
209 
KVSCF(hexToAscii)210 	KVSCF(hexToAscii)
211 	{
212 		QString szHex;
213 		KVSCF_PARAMETERS_BEGIN
214 		KVSCF_PARAMETER("hex_encoded_string", KVS_PT_STRING, 0, szHex)
215 		KVSCF_PARAMETERS_END
216 
217 		KviCString tmp1(szHex);
218 		char * buf;
219 		int len = tmp1.hexToBuffer(&buf, true);
220 		KVSCF_pRetBuffer->setString(QString(QByteArray(buf, len)));
221 		KviCString::freeBuffer(buf);
222 		return true;
223 	}
224 
225 	/*
226 		@doc: hostname
227 		@type:
228 			function
229 		@title:
230 			$hostname
231 		@short:
232 			Returns the hostname of the specified user
233 		@syntax:
234 			<string> $hostname(<nickname:string>)
235 		@description:
236 			Returns the hostname of the specified IRC user IF it is known.[br]
237 			The hostname is known if [fnc]$isWellKnown[/fnc] returns 1.[br]
238 			The hostname is generally known if the user is on a channel with you
239 			or has an open query with you.[br]
240 			Detailed explanation:[br]
241 			KVIrc has an internal database of users that are currently
242 			visible by *this client*: this includes users on open channels
243 			and queries.[br] The other IRC users are [b]not[/b] in the database:
244 			this means that KVIrc knows NOTHING about them and can't return
245 			any information immediately. In this case this function will return
246 			an EMPTY string.[br]
247 			If a user is in the database, at least his nickname is known.[br]
248 			The username and hostname are known only if the server provides that information
249 			spontaneously or after a KVIrc request.[br]
250 			KVIrc requests user information for all the users in open queries
251 			and channels. This information takes some time to be retrieved,
252 			in this interval of time KVIrc knows only the user's nickname.
253 			This function will return the string [b]*[/b] in this case.[br]
254 		@seealso:
255 			[fnc]$isWellKnown[/fnc], [fnc]$username[/fnc], [cmd]awhois[/cmd]
256 	*/
257 
KVSCF(hostname)258 	KVSCF(hostname)
259 	{
260 		QString szNick;
261 
262 		KVSCF_PARAMETERS_BEGIN
263 		KVSCF_PARAMETER("nick", KVS_PT_NONEMPTYSTRING, 0, szNick)
264 		KVSCF_PARAMETERS_END
265 
266 		KviConsoleWindow * c = KVSCF_pContext->window()->console();
267 		if(c && c->isConnected())
268 		{
269 			KviIrcUserEntry * e = KVSCF_pContext->window()->connection()->userDataBase()->find(szNick);
270 			if(e)
271 			{
272 				KVSCF_pRetBuffer->setString(e->host());
273 				return true;
274 			}
275 		}
276 
277 		KVSCF_pRetBuffer->setNothing();
278 		return true;
279 	}
280 
281 	/*
282 		@doc: lag
283 		@type:
284 			function
285 		@title:
286 			$lag
287 		@short:
288 			Returns the lag on the current server
289 		@syntax:
290 			<integer> $lag
291 		@description:
292 			This function returns the lag in the current server, in milliseconds.[br]
293 	*/
294 
KVSCF(lag)295 	KVSCF(lag)
296 	{
297 		if(!KVSCF_pContext->window()->console())
298 			return KVSCF_pContext->errorNoIrcContext();
299 		if(!KVSCF_pContext->window()->console()->connection())
300 			return KVSCF_pContext->warningNoIrcConnection();
301 		if(!KVSCF_pContext->window()->console()->connection()->lagMeter())
302 		{
303 			KVSCF_pContext->warning(__tr2qs_ctx("Lag meter was not enabled", "kvs"));
304 			return false;
305 		}
306 
307 		KVSCF_pRetBuffer->setInteger(KVSCF_pContext->window()->console()->connection()->lagMeter()->lag());
308 		return true;
309 	}
310 
311 	/*
312 		@doc: hptimestamp
313 		@type:
314 			function
315 		@title:
316 			$hptimestamp
317 		@short:
318 			Returns a high precision timestamp
319 		@syntax:
320 			<float> $hptimestamp
321 		@description:
322 			Returns a high precision timestamp as a floating point value.
323 			The timestamp represents the number of seconds elapsed since
324 			a certain moment in the past. The number of seconds
325 			contains a [i]high precision[/i] fractional part. The [i]certain moment[/i] definition
326 			depends on the platform KVIrc is executed. This means that
327 			this timestamp is totally useless to represent a time value
328 			but is useful to compute time intervals with sub-second precision.
329 		@examples:
330 			[example]
331 				%tmp = $hptimestamp
332 				[cmd]echo[/cmd] $($hptimestamp - %tmp)
333 			[/example]
334 		@seealso:
335 			[fnc]$unixTime[/fnc], [fnc]$date[/fnc]
336 	*/
337 
KVSCF(hptimestamp)338 	KVSCF(hptimestamp)
339 	{
340 		struct timeval tv;
341 		kvi_gettimeofday(&tv);
342 		kvs_real_t dTimestamp = (kvs_real_t)(tv.tv_sec);
343 		dTimestamp += (((kvs_real_t)(tv.tv_usec)) / 1000000.0);
344 		KVSCF_pRetBuffer->setReal(dTimestamp);
345 		return true;
346 	}
347 
348 	/*
349 		@doc: i
350 		@type:
351 			function
352 		@title:
353 			$i
354 		@short:
355 			Returns the ITALIC mIRC control character
356 		@syntax:
357 			<string> $i
358 		@description:
359 			Returns the ITALIC mIRC control character (Ctrl+I).[br]
360 		@seealso:
361 			[fnc]$k[/fnc], [fnc]$b[/fnc], [fnc]$u[/fnc], [fnc]$r[/fnc], [fnc]$o[/fnc]
362 	*/
363 
KVSCF(i)364 	KVSCF(i)
365 	{
366 		KVSCF_pRetBuffer->setString(QString(QChar(KviControlCodes::Italic)));
367 		return true;
368 	}
369 
370 	/*
371 		@doc: icon
372 		@type:
373 			function
374 		@title:
375 			$icon
376 		@short:
377 			Returns the ID of an icon
378 		@syntax:
379 			<integer> $icon(<iconname:string>)
380 		@description:
381 			Returns the ID of the icon <iconname>.
382 			You should always use this function where an <image_id> is required
383 			and you want to use an internal icon.
384 			See [fnc]$iconname[/fnc] for a list of the icon names supported by KVIrc.[br]
385 		@examples:
386 			[example]
387 				[cmd]echo[/cmd] $icon(linux)
388 			[/example]
389 		@seealso:
390 			[fnc]$iconName[/fnc]
391 	*/
392 
KVSCF(icon)393 	KVSCF(icon)
394 	{
395 		QString szName;
396 		KVSCF_PARAMETERS_BEGIN
397 		KVSCF_PARAMETER("iconName", KVS_PT_NONEMPTYSTRING, 0, szName)
398 		KVSCF_PARAMETERS_END
399 
400 		KVSCF_pRetBuffer->setInteger(g_pIconManager->getSmallIconIdFromName(szName));
401 		return true;
402 	}
403 
404 	/*
405 		@doc: iconname
406 		@type:
407 			function
408 		@title:
409 			$iconname
410 		@short:
411 			Returns the name of an icon
412 		@syntax:
413 			$iconname(<iconid>)
414 		@description:
415 			Returns the name of a builtin icon given an <iconid>.
416 			The <iconid> is returned by the function [fnc]$icon[/fnc].
417 			If the <iconid> is not valid, an empty name is returned.[br]
418 			The following code will list all the available icon names:
419 			[example]
420 				%i = 0
421 				[cmd]do[/cmd] {
422 					%name = $iconname(%i)
423 					echo The icon by ID %i is named %name
424 					%i++
425 				} [cmd]while[/cmd](%name != "")
426 			[/example]
427 		@examples:
428 			[example]
429 				[cmd]echo[/cmd] $iconname(24)
430 				[cmd]echo[/cmd] $iconname([fnc]$icon[/fnc](linux))
431 			[/example]
432 		@seealso:
433 			[fnc]$icon[/fnc]
434 	*/
435 
KVSCF(iconName)436 	KVSCF(iconName)
437 	{
438 		kvs_uint_t uIco;
439 		KVSCF_PARAMETERS_BEGIN
440 		KVSCF_PARAMETER("iconid", KVS_PT_UINT, 0, uIco)
441 		KVSCF_PARAMETERS_END
442 
443 		if(uIco < KviIconManager::IconCount)
444 			KVSCF_pRetBuffer->setString(g_pIconManager->getSmallIconName(uIco));
445 		else
446 			KVSCF_pRetBuffer->setNothing();
447 		return true;
448 	}
449 
450 	/*
451 		@doc: insideAlias
452 		@type:
453 			function
454 		@title:
455 			$insideAlias
456 		@short:
457 			Returns true if kvs is executing an alias
458 		@syntax:
459 			<bool> $insideAlias()
460 		@description:
461 			This function can be used to know if the code is currently being
462 			executed in the context of an alias.
463 			If $insideAlias is called from inside an alias, it returns true.
464 			If $insideAlias is called from inside a function, event handler or
465 			everything else not being a direct /alias call, it will return false.
466 		@seealso:
467 			[fnc]$sw[/fnc]
468 	*/
469 
KVSCF(insideAlias)470 	KVSCF(insideAlias)
471 	{
472 		KVSCF_pRetBuffer->setBoolean(KVSCF_pContext->aliasSwitchList());
473 		return true;
474 	}
475 
476 	/*
477 		@doc: integer
478 		@type:
479 			function
480 		@title:
481 			$integer
482 		@short:
483 			Casts a variable to an integer
484 		@syntax:
485 			<integer> $integer(<data:variant>)
486 		@description:
487 			Forces <data> to be an integer data type with the following
488 			semantics:
489 			[ul]
490 				[li]If <data> is an integer, <data> itself is returned.[/li]
491 				[li]If <data> is a boolean, its numeric value is returned (either 1 or 0).[/li]
492 				[li]If <data> is a real, its integer part is returned.[/li]
493 				[li]If <data> is an array, the count of its items is returned.[/li]
494 				[li]If <data> is a hash, the count of its items is returned.[/li]
495 				[li]If <data> is a string, its length is returned.[/li]
496 				[li]If <data> is an object, 0 is returned if the reference is null (invalid) and 1 otherwise[/li]
497 			[/ul]
498 			This function is similar to the C (int) cast and is internally
499 			aliased to [fnc]$int[/fnc]() too.
500 			Note that since KVIrc does most of the casting work automatically
501 			you shouldn't need to use this function.
502 		@seealso:
503 			[fnc]$real[/fnc]
504 			[fnc]$boolean[/fnc]
505 	*/
506 
507 	/*
508 		@doc: int
509 		@type:
510 			function
511 		@title:
512 			$int
513 		@short:
514 			Casts a variable to an integer
515 		@syntax:
516 			<integer> $int(<data:variant>)
517 		@description:
518 			This is an internal alias to [fnc]$integer[/fnc]().
519 		@seealso:
520 			[fnc]$real[/fnc]
521 			[fnc]$boolean[/fnc]
522 	*/
523 
KVSCF(integer)524 	KVSCF(integer)
525 	{
526 		KviKvsVariant * v;
527 		KVSCF_PARAMETERS_BEGIN
528 		KVSCF_PARAMETER("data", KVS_PT_VARIANT, 0, v)
529 		KVSCF_PARAMETERS_END
530 
531 		kvs_int_t iVal;
532 		v->castToInteger(iVal);
533 		KVSCF_pRetBuffer->setInteger(iVal);
534 		return true;
535 	}
536 
537 	/*
538 		@doc:	isbot
539 		@type:
540 			function
541 		@title:
542 			$isbot
543 		@short:
544 			Returns [b]1[/b] if the user is a bot. Otherwise return 0.
545 		@syntax:
546 			<string> $isbot(<nickname:string>)
547 		@description:
548 			Returns [b]1[/b] if the user is a bot. Otherwise return 0.[br]
549 			This info  is known if [fnc]$isWellKnown[/fnc] returns 1.[br]
550 			This info is generally known if the user is on a channel with you
551 			or has an open query with you.[br]
552 			Detailed explanation:[br]
553 			KVIrc has an internal database of users that are currently
554 			visible by *this client*: this includes users on open channels
555 			and queries.[br] The other IRC users are [b]not[/b] in the database:
556 			this means that KVIrc knows [b]nothing[/b] about them and can't return
557 			any information immediately. In this case this function will return
558 			an EMPTY string.[br]
559 			If a user is in the database, at least his nickname is known.[br]
560 			The username and hostname are known only if the server provides that information
561 			spontaneously or after a KVIrc request.[br]
562 			KVIrc requests user information for all the users in open queries
563 			and channels. This information takes some time to be retrieved,
564 			in this interval of time KVIrc knows only the user's nickname.
565 			This function will return the string [b]*[/b] in this case.[br]
566 		@seealso:
567 			[fnc]$isWellKnown[/fnc], [fnc]$hostname[/fnc], [fnc]$realname[/fnc], [cmd]$username[/cmd]
568 	*/
569 
KVSCF(isBot)570 	KVSCF(isBot)
571 	{
572 		QString szNick;
573 
574 		KVSCF_PARAMETERS_BEGIN
575 		KVSCF_PARAMETER("nick", KVS_PT_NONEMPTYSTRING, 0, szNick)
576 		KVSCF_PARAMETERS_END
577 
578 		KviConsoleWindow * c = KVSCF_pContext->window()->console();
579 		if(c && c->isConnected())
580 		{
581 			KviIrcUserEntry * e = KVSCF_pContext->window()->connection()->userDataBase()->find(szNick);
582 			if(e)
583 			{
584 				KVSCF_pRetBuffer->setBoolean(e->isBot());
585 				return true;
586 			}
587 		}
588 		KVSCF_pRetBuffer->setNothing();
589 		return true;
590 	}
591 
592 	/*
593 		@doc: isMainWindowActive
594 		@type:
595 			function
596 		@title:
597 			$isMainWindowActive
598 		@short:
599 			Checks if main KVirc window is active
600 		@syntax:
601 			<boolean> $isMainWindowActive()
602 		@description:
603 			Returns true if the KVIrc's window is currently
604 			the active window on the current desktop.
605 	*/
606 
KVSCF(isMainWindowActive)607 	KVSCF(isMainWindowActive)
608 	{
609 		KVSCF_pRetBuffer->setBoolean(g_pMainWindow->isActiveWindow());
610 		return true;
611 	}
612 
613 	/*
614 		@doc: isMainWindowMinimized
615 		@type:
616 			function
617 		@title:
618 			$isMainWindowMinimized
619 		@short:
620 			Checks if main KVirc window is minimized
621 		@syntax:
622 			<boolean> $isMainWindowMinimized()
623 		@description:
624 			Returns true if main KVIrc window is minimized and false otherwise.
625 	*/
626 
KVSCF(isMainWindowMinimized)627 	KVSCF(isMainWindowMinimized)
628 	{
629 		KVSCF_pRetBuffer->setBoolean(g_pMainWindow->isMinimized());
630 		return true;
631 	}
632 
633 	/*
634 		@doc: isempty
635 		@type:
636 			function
637 		@title:
638 			$isEmpty
639 		@short:
640 			Checks if a variable is set (empty or non empty)
641 		@syntax:
642 			<boolean> $isEmpty(<data:variant>)
643 		@description:
644 			Returns 0 if <data> is actually set to some non-empty value
645 			and 1 otherwise. Since KVIrc treats unset variables as empty
646 			ones then this function is the exact opposite of [fnc]$isSet[/fnc].
647 		@seealso:
648 			[fnc]$isSet[/fnc]
649 	*/
650 
KVSCF(isEmpty)651 	KVSCF(isEmpty)
652 	{
653 		KviKvsVariant * v;
654 		KVSCF_PARAMETERS_BEGIN
655 		KVSCF_PARAMETER("data", KVS_PT_VARIANT, 0, v)
656 		KVSCF_PARAMETERS_END
657 
658 		KVSCF_pRetBuffer->setBoolean(v->isEmpty());
659 		return true;
660 	}
661 	//FIXME: documentation
662 
663 	/*
664 		@doc: iseventenabled
665 		@type:
666 			function
667 		@title:
668 			$isEventEnabled
669 		@short:
670 			Checks if an event enabled
671 		@syntax:
672 			<boolean> $isEventEnabled(<event_name:string>,<handler_name:string>)
673 		@description:
674 			Returns [b]1[/b] if the event handler is enabled.
675 		@seealso:
676 			[cmd]event[/cmd] [cmd]eventctl[/cmd]
677 	*/
678 
KVSCF(isEventEnabled)679 	KVSCF(isEventEnabled)
680 	{
681 		QString szEventName, szHandlerName;
682 		KviKvsScriptEventHandler * h = nullptr;
683 
684 		KVSCF_PARAMETERS_BEGIN
685 		KVSCF_PARAMETER("event_name", KVS_PT_NONEMPTYSTRING, 0, szEventName)
686 		KVSCF_PARAMETER("handler_name", KVS_PT_NONEMPTYSTRING, 0, szHandlerName)
687 		KVSCF_PARAMETERS_END
688 
689 		bool bOk;
690 		int iNumber = szEventName.toInt(&bOk);
691 
692 		// is raw event?
693 		if(bOk && (iNumber >= 0) && (iNumber < 1000))
694 		{
695 			if(KviKvsEventManager::instance()->isValidRawEvent(iNumber))
696 				h = KviKvsEventManager::instance()->findScriptRawHandler(iNumber, szHandlerName);
697 			else
698 				KVSCF_pContext->warning(__tr2qs_ctx("No such event (%Q)", "kvs"), &szEventName);
699 		}
700 		else
701 		{
702 			iNumber = KviKvsEventManager::instance()->findAppEventIndexByName(szEventName);
703 			if(KviKvsEventManager::instance()->isValidAppEvent(iNumber))
704 				h = KviKvsEventManager::instance()->findScriptAppHandler(iNumber, szHandlerName);
705 			else
706 				KVSCF_pContext->warning(__tr2qs_ctx("No such event (%Q)", "kvs"), &szEventName);
707 		}
708 
709 		if(h)
710 			KVSCF_pRetBuffer->setBoolean(h->isEnabled());
711 		else
712 			KVSCF_pContext->warning(__tr2qs_ctx("No such event handler (%Q) for event %Q", "kvs"), &szHandlerName, &szEventName);
713 
714 		return true;
715 	}
716 
717 	/*
718 		@doc: isnumeric
719 		@type:
720 			function
721 		@title:
722 			$isNumeric
723 		@syntax:
724 			<boolean> $isNumeric(<data:variant>)
725 		@short:
726 			Finds whether a variable contains a representation of a number
727 		@description:
728 			Returns [b]1[/b] if the <data> is an integer or a real number, and [b]0[/b] otherwise.
729 	*/
730 
KVSCF(isNumeric)731 	KVSCF(isNumeric)
732 	{
733 		KviKvsVariant * v;
734 		KVSCF_PARAMETERS_BEGIN
735 		KVSCF_PARAMETER("data", KVS_PT_VARIANT, 0, v)
736 		KVSCF_PARAMETERS_END
737 
738 		KviKvsNumber n;
739 		KVSCF_pRetBuffer->setBoolean(v->asNumber(n));
740 		return true;
741 	}
742 
743 	/*
744 		@doc: isset
745 		@type:
746 			function
747 		@title:
748 			$isSet
749 		@short:
750 			Checks if a variable is set (non-empty)
751 		@syntax:
752 			<boolean> $isSet(<data:variant>)
753 		@description:
754 			Returns 1 if <data> is actually set to some non-empty value
755 			and [b]0[/b] otherwise. If <data> is a variable, then this function
756 			simply checks if the variable is set. If <data> is a constant
757 			then this function checks if the constant is non empty.
758 			Since KVIrc treats empty strings as [i]unset[/i] values then
759 			this function could be also called [i]isNonEmpty[/i] and it is
760 			the perfect opposite of [fnc]$isEmpty[/fnc]
761 		@seealso:
762 			[fnc]$isEmpty[/fnc], [cmd]unset[/cmd]
763 	*/
764 
KVSCF(isSet)765 	KVSCF(isSet)
766 	{
767 		KviKvsVariant * v;
768 		KVSCF_PARAMETERS_BEGIN
769 		KVSCF_PARAMETER("data", KVS_PT_VARIANT, 0, v)
770 		KVSCF_PARAMETERS_END
771 
772 		KVSCF_pRetBuffer->setBoolean(!v->isEmpty());
773 		return true;
774 	}
775 
776 	/*
777 		@doc: istimer
778 		@type:
779 			function
780 		@title:
781 			$isTimer
782 		@short:
783 			Checks for a timer existence
784 		@syntax:
785 			<boolean> $istimer(<name:string>)
786 		@description:
787 			Returns [b]1[/b] if the timer named <name> is actually running, and [b]0[/b] otherwise.
788 		@seealso:
789 			[cmd]timer[/cmd], [cmd]killtimer[/cmd]
790 	*/
791 
KVSCF(isTimer)792 	KVSCF(isTimer)
793 	{
794 		QString szName;
795 
796 		KVSCF_PARAMETERS_BEGIN
797 		KVSCF_PARAMETER("timerName", KVS_PT_NONEMPTYSTRING, 0, szName)
798 		KVSCF_PARAMETERS_END
799 		KVSCF_pRetBuffer->setBoolean(KviKvsTimerManager::instance()->timerExists(szName));
800 		return true;
801 	}
802 
803 	/*
804 		@doc: iswellknown
805 		@type:
806 			function
807 		@title:
808 			$isWellKnown
809 		@short:
810 			Returns $true if the specified user is well known
811 		@syntax:
812 			<bool> $isWellKnown(<nickname:string>)
813 		@description:
814 			Returns 1 if KVIrc has the basic user information about the specified <nickname>.[br]
815 			The basic information include the username and hostname.[br]
816 			This is almost always true if the user is on a channel with you or
817 			you have an open query with him.[br]
818 			If $isWellKnown returns 0, [fnc]$username[/fnc] and [fnc]$hostname[/fnc]
819 			will return empty strings.[br]
820 			In this case you must use [cmd]awhois[/cmd] to obtain the user basic information.[br]
821 	*/
822 
KVSCF(isWellKnown)823 	KVSCF(isWellKnown)
824 	{
825 		QString szNick;
826 
827 		KVSCF_PARAMETERS_BEGIN
828 		KVSCF_PARAMETER("nick", KVS_PT_NONEMPTYSTRING, 0, szNick)
829 		KVSCF_PARAMETERS_END
830 
831 		KviConsoleWindow * c = KVSCF_pContext->window()->console();
832 		if(c && c->isConnected())
833 		{
834 			KviIrcUserEntry * e = KVSCF_pContext->window()->connection()->userDataBase()->find(szNick);
835 			if(e)
836 			{
837 				KVSCF_pRetBuffer->setBoolean(e->hasHost() && e->hasUser());
838 				return true;
839 			}
840 		}
841 
842 		KVSCF_pRetBuffer->setBoolean(false);
843 		return true;
844 	}
845 
846 	/*
847 		@doc: k
848 		@type:
849 			function
850 		@title:
851 			$k
852 		@short:
853 			Returns the COLOR mIRC control character
854 		@syntax:
855 			<string> $k(<foreground:integer>[,<background:integer>])
856 			<string> $k
857 		@description:
858 			Returns the COLOR mIRC control character (Ctrl+K).[br]
859 			If <foreground> and <background> are passed, a standard mIRC
860 			color escape is returned.[br]
861 		@seealso:
862 			[fnc]$b[/fnc], [fnc]$i[/fnc], [fnc]$u[/fnc], [fnc]$r[/fnc], [fnc]$o[/fnc]
863 	*/
864 
KVSCF(k)865 	KVSCF(k)
866 	{
867 		kvs_uint_t iFore, iBack;
868 		KVSCF_PARAMETERS_BEGIN
869 		KVSCF_PARAMETER("foreground", KVS_PT_UINT, KVS_PF_OPTIONAL, iFore)
870 		KVSCF_PARAMETER("background", KVS_PT_UINT, KVS_PF_OPTIONAL, iBack)
871 		KVSCF_PARAMETERS_END
872 
873 		QString szRet = QChar(KviControlCodes::Color);
874 		if(KVSCF_pParams->count() > 0)
875 		{
876 			KviQString::appendFormatted(szRet, "%u", iFore);
877 			if(KVSCF_pParams->count() > 1)
878 				KviQString::appendFormatted(szRet, ",%u", iBack);
879 		}
880 		KVSCF_pRetBuffer->setString(szRet);
881 		return true;
882 	}
883 
884 	/*
885 		@doc: keys
886 		@type:
887 			function
888 		@title:
889 			$keys
890 		@short:
891 			Returns the array of keys of a hash
892 		@syntax:
893 			<array> $keys(<hash_value:hash>)
894 		@description:
895 			Returns an array with the keys of the <hash> parameter.
896 			<hash> must be obviously a hash (or eventually an empty variable
897 			that is treated as an empty hash).
898 		@seealso:
899 			[cmd]foreach[/cmd]
900 	*/
901 
KVSCF(keys)902 	KVSCF(keys)
903 	{
904 		KviKvsHash * pHash = nullptr;
905 		KVSCF_PARAMETERS_BEGIN
906 		KVSCF_PARAMETER("hash", KVS_PT_HASH, KVS_PF_OPTIONAL, pHash)
907 		KVSCF_PARAMETERS_END
908 
909 		KviKvsArray * a = new KviKvsArray();
910 
911 		// we have to support an empty hash, returning an empty array (ticket #940)
912 		if(pHash)
913 		{
914 			KviKvsHashIterator it(*(pHash->dict()));
915 			while(it.current())
916 			{
917 				a->append(new KviKvsVariant(it.currentKey()));
918 				++it;
919 			}
920 		}
921 		KVSCF_pRetBuffer->setArray(a);
922 		return true;
923 	}
924 
925 	/*
926 		@doc: lang
927 		@type:
928 			function
929 		@title:
930 			$lang
931 		@short:
932 			Returns name of currently used language
933 		@syntax:
934 			<string> $lang([<type:string>])
935 		@description:
936 			Returns the short name of currently used language.[br]
937 			Type <type> should be one of: [br]
938 			[i]full[/i]  - returns full locale name, such as ru_RU.UTF-8 (default).[br]
939 			[i]lang[/i]  - return language name, such as ru_RU.[br]
940 			[i]short[/i] - returns only language group such as ru.[br]
941 	*/
942 
KVSCF(lang)943 	KVSCF(lang)
944 	{
945 		QString szType;
946 
947 		KVSCF_PARAMETERS_BEGIN
948 		KVSCF_PARAMETER("type", KVS_PT_NONEMPTYSTRING, KVS_PF_OPTIONAL, szType)
949 		KVSCF_PARAMETERS_END
950 
951 		QString szLocale = KviLocale::instance()->localeName();
952 		if(szType == QLatin1String("lang"))
953 			KVSCF_pRetBuffer->setString(szLocale.left(5));
954 		else if(szType == QLatin1String("short"))
955 			KVSCF_pRetBuffer->setString(szLocale.left(2));
956 		else
957 			KVSCF_pRetBuffer->setString(szLocale);
958 		return true;
959 	}
960 
961 	/*
962 		@doc: length
963 		@type:
964 			function
965 		@title:
966 			$length
967 		@short:
968 			Returns the length of a variable
969 		@syntax:
970 			<integer> $length(<value:variant>)
971 		@description:
972 			When <value> is an array or a hash, it returns the number
973 			of its elements. When <value> is an object reference it returns 0.
974 			In all the other cases <value> is interpreted
975 			as a string and its length is returned.
976 		@seealso:
977 			[fnc]$str.len[/fnc]
978 	*/
979 
KVSCF(length)980 	KVSCF(length)
981 	{
982 		KviKvsVariant * pVar;
983 		KVSCF_PARAMETERS_BEGIN
984 		KVSCF_PARAMETER("value", KVS_PT_VARIANT, 0, pVar)
985 		KVSCF_PARAMETERS_END
986 
987 		switch(pVar->type())
988 		{
989 			case KviKvsVariantData::Array:
990 				KVSCF_pRetBuffer->setInteger(pVar->array()->size());
991 				break;
992 			case KviKvsVariantData::Hash:
993 				KVSCF_pRetBuffer->setInteger(pVar->hash()->size());
994 				break;
995 			case KviKvsVariantData::HObject:
996 				KVSCF_pRetBuffer->setInteger(0);
997 				break;
998 			default:
999 			{
1000 				QString tmp;
1001 				pVar->asString(tmp);
1002 				KVSCF_pRetBuffer->setInteger(tmp.length());
1003 			}
1004 		}
1005 		return true;
1006 	}
1007 
1008 	/*
1009 		@doc: lf
1010 		@type:
1011 			function
1012 		@title:
1013 			$lf
1014 		@short:
1015 			Returns a line feed character
1016 		@syntax:
1017 			<string> $lf
1018 		@description:
1019 			Returns a line feed character.
1020 		@seealso:
1021 			[fnc]$cr[/fnc], [fnc]$ascii[/fnc], [fnc]$char[/fnc]
1022 	*/
1023 
KVSCF(lf)1024 	KVSCF(lf)
1025 	{
1026 		KVSCF_pRetBuffer->setString(QString(QChar('\n')));
1027 		return true;
1028 	}
1029 
1030 	/*
1031 		@doc: link
1032 		@type:
1033 			function
1034 		@title:
1035 			$link
1036 		@short:
1037 			Returns the text specified as a link
1038 		@syntax:
1039 			<string> $link(<text:string>[,<type:string>])
1040 		@description:
1041 			Gets the text you pass as the first parameter and formats it
1042 			so that KVIrc will display it as a link. You can specify the
1043 			type of the link as the second parameter. Valid values for the
1044 			second parameter are:
1045 			[ul]
1046 				[li]nick	link to a nickname[/li]
1047 				[li]channel	link to a channel name[/li]
1048 				[li]host	link to an host[/li]
1049 				[li]URL		(default) link to an URL[/li]
1050 			[/ul]
1051 			Please note that the text you get as the output is valid only
1052 			when interpreted locally. Sending this text to the server you can
1053 			get unpredictable results, depending on the IRC client other people
1054 			is using.
1055 			The returned string format is described by [doc:escape_sequences]the escape sequences documentation[/doc]
1056 			and you might also take a look at [fnc]$fmtlink[/fnc] which has related functionality.
1057 		@examples:
1058 			echo $link(pragma,nick)
1059 		@seealso:
1060 			[cmd]echo[/cmd], [fnc]$fmtlink[/fnc].
1061 	*/
1062 
KVSCF(link)1063 	KVSCF(link)
1064 	{
1065 		QString szData, szType;
1066 		KVSCF_PARAMETERS_BEGIN
1067 		KVSCF_PARAMETER("text", KVS_PT_NONEMPTYSTRING, 0, szData)
1068 		KVSCF_PARAMETER("type", KVS_PT_NONEMPTYSTRING, KVS_PF_OPTIONAL, szType)
1069 		KVSCF_PARAMETERS_END
1070 
1071 		QString szRet("\r!");
1072 		if(szType == QLatin1String("nick"))
1073 			szRet.append("n\r");
1074 		else if(szType == QLatin1String("channel"))
1075 			szRet.append("c\r");
1076 		else if(szType == QLatin1String("host"))
1077 			szRet.append("h\r");
1078 		else
1079 			szRet.append("u\r");
1080 
1081 		szRet.append(szData);
1082 		szRet.append("\r");
1083 		KVSCF_pRetBuffer->setString(szRet);
1084 		return true;
1085 	}
1086 
1087 	/*
1088 		@doc: listtimers
1089 		@title:
1090 			$listtimers
1091 		@type:
1092 			function
1093 		@short:
1094 			Returns a list of the active timers
1095 		@syntax:
1096 			<array> $listtimers([<name:string>][,<flags:string>])
1097 		@description:
1098 			Returns a list of all the active timers.[br]
1099 			If you specify a <name>, only timers matching that name are returned;
1100 			You can use the [b]*[/b] and [b]?[/b] wildcards in <name>.[br]
1101 			<flags> can be any combination of the characters [b]s[/b] and [b]r[/b][br]
1102 			If the flag [b]r[/b] is specified then <name> is assumed to be a standard regular expression.
1103 			If the flag [b]s[/b] is specified the matches are case sensitive.[br]
1104 
1105 		@seealso:
1106 			[cmd]timer[/cmd], [fnc]$isTimer[/fnc], [cmd]killtimer[/cmd], [cmd]listtimers[/cmd]
1107 	*/
1108 
KVSCF(listtimers)1109 	KVSCF(listtimers)
1110 	{
1111 		QString szText, szFlags;
1112 		KVSCF_PARAMETERS_BEGIN
1113 		KVSCF_PARAMETER("text", KVS_PT_STRING, KVS_PF_OPTIONAL, szText)
1114 		KVSCF_PARAMETER("flags", KVS_PT_STRING, KVS_PF_OPTIONAL, szFlags)
1115 		KVSCF_PARAMETERS_END
1116 
1117 		bool bCaseSensitive = szFlags.indexOf('s', 0, Qt::CaseInsensitive) != -1;
1118 		bool bRegexp = szFlags.indexOf('r', 0, Qt::CaseInsensitive) != -1;
1119 		bool bMatch = !szText.isEmpty();
1120 
1121 		KviPointerHashTable<QString, KviKvsTimer> * pTimerDict = KviKvsTimerManager::instance()->timerDict();
1122 
1123 		if(!pTimerDict)
1124 			return true;
1125 
1126 		KviKvsArray * a = new KviKvsArray();
1127 		QRegExp re(szText, bCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive, bRegexp ? QRegExp::RegExp : QRegExp::Wildcard);
1128 		KviPointerHashTableIterator<QString, KviKvsTimer> it(*pTimerDict);
1129 
1130 		while(KviKvsTimer * pTimer = it.current())
1131 		{
1132 			if(bMatch && !re.exactMatch(pTimer->name()))
1133 			{
1134 				++it;
1135 				continue;
1136 			}
1137 
1138 			a->append(new KviKvsVariant(pTimer->name()));
1139 			++it;
1140 		}
1141 
1142 		KVSCF_pRetBuffer->setArray(a);
1143 		return true;
1144 	}
1145 };
1146