1 //============================================================================= 2 // 3 // File : KviKvsCoreFunctions_sz.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 "kvi_sourcesdate.h" 26 #include "kvi_socket.h" 27 #include "kvi_out.h" 28 #include "KviKvsCoreFunctions.h" 29 #include "KviKvsKernel.h" 30 #include "KviKvsArrayCast.h" 31 #include "KviKvsObjectController.h" 32 #include "KviWindow.h" 33 #include "KviLocale.h" 34 #include "KviApplication.h" 35 #include "KviOptions.h" 36 #include "KviChannelWindow.h" 37 #include "KviConsoleWindow.h" 38 #include "KviTimeUtils.h" 39 #include "KviIrcUserDataBase.h" 40 #include "KviModuleManager.h" 41 #include "KviControlCodes.h" 42 #include "KviBuildInfo.h" 43 44 /* 45 Data types: 46 47 <variant> 48 <nothing> 49 <scalar> 50 <boolean> 51 <string> 52 <numeric> 53 <integer> 54 <real> 55 <array> 56 <hash> 57 <object> 58 59 $isEmpty(<nothing>) == $true 60 61 <nothing> == <empty string> 62 <null> == <null object> 63 64 65 */ 66 67 namespace KviKvsCoreFunctions 68 { 69 70 /* 71 @doc: scriptContextName 72 @type: 73 function 74 @title: 75 $scriptContextName 76 @short: 77 Returns the actual script context's name.. 78 @syntax: 79 <string> $scriptContextName() 80 @description: 81 Returns the actual script context's name. Useful only for custom debug. 82 @seealso: 83 [cmd]debug[/cmd] 84 */ 85 KVSCF(scriptContextName)86 KVSCF(scriptContextName) 87 { 88 KVSCF_pRetBuffer->setString(KVSCF_pContext->script()->name()); 89 return true; 90 } 91 92 /* 93 @doc: selected 94 @type: 95 function 96 @title: 97 $selected 98 @short: 99 Returns the list of selected nicknames in the channel 100 @syntax: 101 <array> $selected 102 <array> $selected(<window id:string>) 103 @description: 104 This is an internal alias for [fnc]$userlist.selected[/fnc].[br] 105 This function is deprecated and its use is discouraged. 106 @seealso: 107 [fnc]$userlist.selected[/fnc] 108 */ 109 KVSCF(selected)110 KVSCF(selected) 111 { 112 KviKvsScript::evaluate("$userlist.selected", KVSCF_pContext->window(), KVSCF_pParams, KVSCF_pRetBuffer); 113 return true; 114 } 115 116 /* 117 @doc: sentBytes 118 @type: 119 function 120 @title: 121 $sentBytes 122 @short: 123 Returns total sent bytes 124 @syntax: 125 <uint> $sentBytes() 126 @description: 127 Returns total sent bytes 128 @seealso: 129 [fnc]$receivedBytes[/fnc] 130 */ 131 KVSCF(sentBytes)132 KVSCF(sentBytes) 133 { 134 KVSCF_pRetBuffer->setInteger(g_uOutgoingTraffic); 135 return true; 136 } 137 138 /* 139 @doc: serialize 140 @type: 141 function 142 @title: 143 $serialize 144 @short: 145 Encodes variable to JSON string 146 @syntax: 147 <string> $serialize(<data:mixed>) 148 @description: 149 Decodes JSON-encoded string 150 $serialize() returns a string containing a byte-stream representation of value that can be stored anywhere. 151 @seealso: 152 [fnc]$unserialize[/fnc] 153 */ 154 KVSCF(serialize)155 KVSCF(serialize) 156 { 157 KviKvsVariant * pVar = nullptr; 158 QString szBuffer; 159 160 KVSCF_PARAMETERS_BEGIN 161 KVSCF_PARAMETER("data", KVS_PT_VARIANT, 0, pVar) 162 KVSCF_PARAMETERS_END 163 164 if(!pVar) 165 return false; 166 pVar->serialize(szBuffer); 167 KVSCF_pRetBuffer->setString(szBuffer); 168 return true; 169 } 170 171 /* 172 @doc: server 173 @type: 174 function 175 @title: 176 $server 177 @short: 178 Returns the current server name (if any) 179 @syntax: 180 <string> $server[(irc_context_id:uint)] 181 @description: 182 Returns the current server name of the specified IRC context.[br] 183 If no <irc_context_id> is specified, the current IRC context is used.[br] 184 If you are not connected to a server, this function will return an empty string.[br] 185 If the current window does not belong to any IRC context and no irc_context_id 186 is specified, this function prints a warning and also returns an empty string.[br] 187 */ 188 KVSCF(server)189 KVSCF(server) 190 { 191 kvs_uint_t uCntx; 192 193 KVSCF_PARAMETERS_BEGIN 194 KVSCF_PARAMETER("irc_context_id", KVS_PT_UINT, KVS_PF_OPTIONAL, uCntx) 195 KVSCF_PARAMETERS_END 196 197 KviConsoleWindow * cns; 198 199 if(KVSCF_pParams->count() > 0) 200 { 201 cns = g_pApp->findConsole(uCntx); 202 if(cns && (cns->context()->isConnected() || cns->context()->isLoggingIn())) 203 KVSCF_pRetBuffer->setString(cns->connection()->currentServerName()); 204 else 205 KVSCF_pRetBuffer->setNothing(); 206 } 207 else 208 { 209 cns = KVSCF_pContext->window()->console(); 210 if(cns) 211 { 212 if(cns->context()->isConnected() || cns->context()->isLoggingIn()) 213 KVSCF_pRetBuffer->setString(cns->connection()->currentServerName()); 214 else 215 KVSCF_pRetBuffer->setNothing(); 216 } 217 else 218 { 219 KVSCF_pContext->warning(__tr2qs_ctx("This window has no associated IRC context", "kvs")); 220 KVSCF_pRetBuffer->setNothing(); 221 } 222 } 223 return true; 224 } 225 226 /* 227 @doc: sort 228 @type: 229 function 230 @title: 231 $sort 232 @short: 233 Sorts an array 234 @syntax: 235 <array> $sort(<data:array>) 236 @description: 237 Sorts an array in ascending order. 238 @seealso: 239 [fnc]$rsort[/fnc] 240 */ 241 KVSCF(sort)242 KVSCF(sort) 243 { 244 KviKvsArrayCast a; 245 246 KVSCF_PARAMETERS_BEGIN 247 KVSCF_PARAMETER("data", KVS_PT_ARRAYCAST, 0, a) 248 KVSCF_PARAMETERS_END 249 250 if(a.array()) 251 { 252 KviKvsArray * arry = new KviKvsArray(*(a.array())); 253 arry->sort(); 254 KVSCF_pRetBuffer->setArray(arry); 255 } 256 else 257 { 258 KVSCF_pRetBuffer->setArray(new KviKvsArray()); 259 } 260 return true; 261 } 262 263 /* 264 @doc: string 265 @type: 266 function 267 @title: 268 $string 269 @short: 270 Casts a variable to a string 271 @syntax: 272 <integer> $string(<data:variant>) 273 @description: 274 Forces <data> to be a string data type with the following semantics: 275 [ul] 276 [li]If <data> is a string then <data> itself is returned.[/li] 277 [li]If <data> is an integer then its decimal representation is returned.[/li] 278 [li]If <data> is a real then its decimal floating-point representation is returned.[/li] 279 [li]If <data> is a boolean then the string [b]1[/b] is returned for a true value and the string [b]0[/b] for a false value.[/li] 280 [li]If <data> is nothing (unset) then an empty string is returned[/li] 281 [li]If <data> is an array then a string with all the items converted to strings and separated by commas is returned[/li] 282 [li]If <data> is a hash then a string with all the values converted to strings and separated by commas is returned[/li] 283 [li]If <data> is a hobject then the string "object" is returned[/li] 284 [/ul] 285 Note that since KVIrc does most of the casting work automatically 286 you shouldn't need to use this function. 287 @seealso: 288 [fnc]$real[/fnc] 289 [fnc]$integer[/fnc] 290 */ 291 KVSCF(string)292 KVSCF(string) 293 { 294 KviKvsVariant * v; 295 KVSCF_PARAMETERS_BEGIN 296 KVSCF_PARAMETER("data", KVS_PT_VARIANT, 0, v) 297 KVSCF_PARAMETERS_END 298 299 QString szVal; 300 v->asString(szVal); 301 KVSCF_pRetBuffer->setString(szVal); 302 return true; 303 } 304 305 /* 306 @doc: sw 307 @type: 308 function 309 @title: 310 $sw 311 @short: 312 Returns the value of a switch for an alias 313 @syntax: 314 <variant> $sw(<switch_name:string>[,<long_switch_name:string>]) 315 @description: 316 This function is valid and useful only in aliases. 317 It allows an alias to handle switches just like any other 318 KVIrc command. If a switch in the form -<letter> was 319 passed to the current alias then $sw(<letter>) 320 returns 1 (true). If a switch in the form -<letter>=<value> 321 was passed to the current alias then <value> is returned. 322 If the switch was not present at all then this function 323 returns an empty string (that evaluates to false in an expression). 324 A warning is printed if this function is used non-alias code. 325 @seealso: 326 [fnc]$insideAlias[/fnc] 327 @examples: 328 [example] 329 [cmd]alias[/cmd](test){ 330 if($sw(a,append)) [cmd]echo[/cmd] "Switch -a was passed" 331 %x = $sw(x); 332 if(%x) [cmd]echo[/cmd] "Switch -x=%x was passed" 333 } 334 test -a 335 test -x 336 test --append -x 337 test -a -x 338 test -a -x=test 339 test -a=10 -x=test 340 [/example] 341 */ 342 KVSCF(sw)343 KVSCF(sw) 344 { 345 QString szSwitch; 346 QString szLongSwitch; 347 348 KVSCF_PARAMETERS_BEGIN 349 KVSCF_PARAMETER("switch_name", KVS_PT_STRING, 0, szSwitch) 350 KVSCF_PARAMETER("long_name", KVS_PT_STRING, KVS_PF_OPTIONAL, szLongSwitch) 351 KVSCF_PARAMETERS_END 352 353 KviKvsSwitchList * sl = KVSCF_pContext->aliasSwitchList(); 354 if(!sl) 355 { 356 KVSCF_pContext->warning(__tr2qs_ctx("The $sw() function can be used only in aliases", "kvs")); 357 return true; 358 } 359 360 KviKvsVariant * v; 361 362 if(szSwitch.length() > 1) 363 { 364 if(szLongSwitch.isEmpty()) 365 v = sl->find(szSwitch); 366 else 367 v = sl->find(szSwitch[0].unicode(), szLongSwitch); 368 } 369 else 370 { 371 if(szLongSwitch.isEmpty()) 372 v = sl->find(szSwitch[0]); 373 else 374 v = sl->find(szSwitch[0].unicode(), szLongSwitch); 375 } 376 377 if(v) 378 KVSCF_pRetBuffer->copyFrom(*v); 379 else 380 KVSCF_pRetBuffer->setNothing(); 381 return true; 382 } 383 384 /* 385 @doc: target 386 @type: 387 function 388 @title: 389 $target 390 @short: 391 Returns the target of the current window 392 @syntax: 393 <string> $target 394 <string> $target(<window id>) 395 @description: 396 The form with the <window id> parameter returns the target 397 of the channel,query or DCC that has the specified ID. 398 The form without parameters returns the target of the current window, 399 thus it is equivalent to calling $target([fnc]$window[/fnc]). 400 For channel windows the target is the channel name, 401 for query windows it is the list of the "queried" users, for the 402 DCC windows it is the remote end of the connection. 403 The other windows have an empty target. 404 @examples: 405 [example] 406 [cmd]echo[/cmd] $target 407 [/example] 408 @seealso: 409 [fnc]$window[/fnc], 410 [fnc]$console[/fnc], 411 [fnc]$channel[/fnc], 412 [fnc]$query[/fnc], 413 [doc:window_naming_conventions]Window naming conventions[/doc] 414 */ 415 KVSCF(target)416 KVSCF(target) 417 { 418 QString winId; 419 KVSCF_PARAMETERS_BEGIN 420 KVSCF_PARAMETER("winId", KVS_PT_NONEMPTYSTRING, KVS_PF_OPTIONAL, winId) 421 KVSCF_PARAMETERS_END 422 423 KviWindow * wnd = nullptr; 424 if(KVSCF_pParams->count() > 0) 425 { 426 wnd = g_pApp->findWindow(winId.toUtf8().data()); 427 if(!wnd) 428 { 429 KVSCF_pContext->warning(__tr2qs_ctx("Window with ID '%s' not found, returning empty string", "kvs"), winId.toUtf8().data()); 430 KVSCF_pRetBuffer->setNothing(); 431 return true; 432 } 433 } 434 else 435 { 436 wnd = KVSCF_pContext->window(); 437 } 438 439 //qDebug("CALLING $target on window %s",wnd->name()); 440 QString szTa = wnd->target(); 441 442 KVSCF_pRetBuffer->setString(wnd->target()); 443 return true; 444 } 445 446 /* 447 @doc: this 448 @type: 449 function 450 @title: 451 $this 452 @short: 453 Retrieves the ID of the current object 454 @syntax: 455 $this 456 @description: 457 Returns the ID of the current object or [b]0[/b] if there is 458 none. This function has a [i]quick[/i] version with syntax: 459 [b]$$[/b][br] 460 */ 461 462 /* 463 @doc: $ 464 @type: 465 function 466 @title: 467 $$ 468 @short: 469 Retrieves the ID of the current object 470 @syntax: 471 $$ 472 @description: 473 Returns the ID of the current object or [b]0[/b] if there is 474 none. This function is equivalent to [fnc]$this[/fnc] 475 */ 476 KVSCF(thisCKEYWORDWORKAROUND)477 KVSCF(thisCKEYWORDWORKAROUND) 478 { 479 // prologue: parameter handling 480 KviKvsObject * o = KVSCF_pContext->thisObject(); 481 KVSCF_pRetBuffer->setHObject(o ? o->handle() : ((kvs_hobject_t) nullptr)); 482 return true; 483 } 484 485 /* 486 @doc: script_localization 487 @type: 488 generic 489 @title: 490 Localization of scripts 491 @short: 492 Explains how to add translation capabilities to your scripts 493 @body: 494 [big]Introduction[/big] 495 Adding the translated versions of the strings adds a great 496 value to your scripts. The process of translating a part of 497 software is called localization. KVIrc offers some commands 498 and functions for this purpose and this document explains 499 briefly how to use them. 500 [big]The big picture[/big] 501 [br] 502 All of the strings in your script are written in a [i]primary language[/i]. 503 The most common [i]primary language[/i] is English, but theoretically 504 it can be any language of your choice. 505 [br] 506 By the means of the gettext package programs you extract 507 the strings from your script and produce a translation file. 508 [br] 509 The translation file is then effectively translated in another 510 language and later compiled in a binary form. 511 [br] 512 The binary form translations are then loaded in the KVIrc 513 executable at runtime and a function is used to look up the 514 translations. 515 [big]How to translate scripts[/big] 516 [br] 517 Your strings should be surrounded by the [fnc]$tr[/fnc]() function in the following way: 518 [example] 519 [fnc]$tr[/fnc]("your default language text") 520 [/example] 521 [br] 522 Then you should run the xgettext command on your script files. 523 This is done by a shell commandline similar to the following: 524 [example] 525 xgettext -o myscript.pot -ktr mykvsfile1.kvs mykvsfile2.kvs ... 526 [/example] 527 [br] 528 Copy the translation file obtained in the following way: 529 [example] 530 cp myscript.pot myscript_XX.po 531 [/example] 532 Where the XX is your country/language code. For example, for Italian 533 it would be: 534 [example] 535 cp myscript.pot myscript_it.po 536 [/example] 537 [br] 538 Translate mytranslation_it.po. The format of the po file is straightforward. 539 There are msgid lines with the original English text and immediately 540 following msgstr lines that must be filled with the corresponding translation. 541 For example in Italian you would translate:[br] 542 msgid "your default language text" 543 msgstr "il tuo testo in linguaggio predefinito" 544 [br] 545 Compile your translation to binary form with the following command: 546 [example] 547 msgfmt -o myscript_it.mo myscript_it.po 548 [/example] 549 Copy the generated *.mo file to the [i]locale[/i] subdirectory 550 in the KVIrc's local directory (usually $HOME/.kvirc/locale/). 551 [br] 552 Set the system language to the XX above with the following command: 553 [example] 554 export LANG="XX" 555 [/example] 556 For Italian it would be: 557 [example]export LANG="it"[/example] 558 [br] 559 Start KVIrc and type in the commandline: 560 [example] 561 [cmd]echo[/cmd] [fnc]$tr[/fnc]("your default language text","myscript") 562 [/example] 563 If you did everything well, you should see the translated 564 text echoed in the window :)[br] 565 [br] 566 Obviously if you don't set LANG="XX", the same command will 567 output the original string unchanged. 568 [br] 569 You can manage translations in several languages by producing 570 several *.mo files all with the proper language/country code appended. 571 The right *.mo file will be magically loaded by KVIrc that 572 will look up the user's LANG variable. (If you don't want 573 to use LANG, you can use KVIRC_LANG instead, it will still work). 574 [big]Caveats[/big] 575 [br] 576 You should [b]never[/b] use variables or identifiers inside the $tr() function. 577 This because the translation files are generated offline, 578 when the string is not evaluated yet (i.e variables ad identifiers 579 are not substituted by their actual return values). 580 The translation process, instead, happens at runtime, when 581 the variables and identifiers have been substituted by their 582 actual values. This would lead to a mismatch between the 583 string you look up in the translation catalog and the 584 effectively translated one. If you need to include variables 585 in your strings you should compose the string with smaller pieces 586 [example] 587 [cmd]echo[/cmd] [fnc]$tr[/fnc]("On this channel") %number [fnc]$tr[/fnc]("users are operators") 588 [/example] 589 The translation process can be realized only if your 590 scripts are written in external files. This makes sense since 591 if you're translating the script then you will probably want to 592 distribute it and the only way to distribute it is on files. 593 But well.. this is a caveat. 594 */ 595 596 /* 597 @doc: tr 598 @type: 599 function 600 @title: 601 $tr 602 @short: 603 Translates an English string to the current language 604 @syntax: 605 <string> $tr(<default_language_string:string>[,<catalogue:string>]) 606 @description: 607 This function searches for the translation of <default_language_string> 608 in the specified translation <catalogue> or in the main 609 KVIrc translation file if <catalogue> is omitted.[br] 610 If no translation is found then <english_string> is returned.[br] 611 <default_language_string> is a string in your script default 612 language (which should probably be English since it is the 613 most common language spoken by the translators).[br] 614 If the <catalogue> is not loaded yet, KVIrc will attempt to load it, 615 but only the first time that the catalogue is accessed (i.e. a load 616 failure will cause the catalogue to be ignored completely until [cmd]trunload[/cmd] 617 is explicitly used.[br] 618 KVIrc will search the catalogue only in [fnc]$file.localdir[/fnc]/locale/ 619 and in [fnc]$file.globaldir[/fnc]/locale/. If your catalogues are 620 in some other place then you must load them explicitly by the 621 means of [cmd]trload[/cmd]. 622 For more information see the documentation about [doc:script_localization]script localization[/doc]. 623 @examples: 624 [example] 625 [cmd]echo[/cmd] $tr("Hello World!") 626 [/example] 627 @seealso: 628 [cmd]trload[/cmd], [cmd]trunload[/cmd] 629 */ 630 KVSCF(tr)631 KVSCF(tr) 632 { 633 // prologue: parameter handling 634 QString szString; 635 QString szCatalogue; 636 637 KVSCF_PARAMETERS_BEGIN 638 KVSCF_PARAMETER("default_language_string", KVS_PT_STRING, 0, szString) 639 KVSCF_PARAMETER("catalogue", KVS_PT_STRING, KVS_PF_OPTIONAL, szCatalogue) 640 KVSCF_PARAMETERS_END 641 if(szString.isEmpty()) 642 return true; 643 // body: the real job 644 QString translation; 645 646 if(!szCatalogue.isEmpty()) 647 { 648 KviMessageCatalogue * pCat = KviLocale::instance()->getLoadedCatalogue(szCatalogue); 649 if(pCat) 650 { 651 translation = pCat->translateToQString(szString.toUtf8().data()); 652 } 653 else 654 { 655 // attempt to load it automatically 656 QString szDir; 657 g_pApp->getLocalKvircDirectory(szDir, KviApplication::Locale); 658 if(!KviLocale::instance()->loadCatalogue(szCatalogue, szDir)) 659 { 660 g_pApp->getGlobalKvircDirectory(szDir, KviApplication::Locale); 661 KviLocale::instance()->loadCatalogue(szCatalogue, szDir); 662 } 663 // If the code above fails to load the catalogue 664 // then __tr2qs_ctx_no_xgettext will place 665 // a dummy catalogue in its place 666 // This means that the next call to getLoadedCatalogue will 667 // not fail unless /trunload is explicitly used 668 // This will avoid trashing the user's disk too much 669 // when a catalogue for a given language is not available 670 translation = __tr2qs_ctx_no_xgettext(szString.toUtf8().data(), szCatalogue.toUtf8().data()); 671 } 672 } 673 else 674 { 675 translation = __tr2qs_no_xgettext(szString.toUtf8().data()); 676 } 677 678 // epilogue: set the return value 679 KVSCF_pRetBuffer->setString(translation); 680 return true; 681 } 682 683 /* 684 @doc: true 685 @type: 686 function 687 @title: 688 $true 689 @short: 690 The boolean true constant 691 @syntax: 692 <boolean> $true 693 @description: 694 Evaluates to the true boolean constant. True 695 is equivalent to the integer 1 too. This function/constant 696 is useful to keep your code readable: when you 697 have a variable that can assume boolean values it's 698 nicer to use $true and [fnc]$false[/fnc] instead of 699 the integer constants 1 and 0. The reader will 700 understand immediately that the variable simply can't 701 assume any other value. 702 @examples: 703 [example] 704 %a = $true 705 [cmd]echo[/cmd] $typeof(%a) 706 [cmd]echo[/cmd] $(%a + 1) 707 [/example] 708 @seealso: 709 [fnc]$false[/fnc] 710 */ 711 KVSCF(trueCKEYWORDWORKAROUND)712 KVSCF(trueCKEYWORDWORKAROUND) 713 { 714 KVSCF_pRetBuffer->setBoolean(true); 715 return true; 716 } 717 718 /* 719 @doc: typeof 720 @type: 721 function 722 @title: 723 $typeof 724 @short: 725 Returns the internal data type of a variable 726 @syntax: 727 <string> $typeof(<data:variant>) 728 @description: 729 Returns the internal data type of the <data>. 730 @examples: 731 [example] 732 [cmd]echo[/cmd] $typeof("test") 733 %a = "test" 734 [cmd]echo[/cmd] $typeof(%a) 735 %a = 1 736 [cmd]echo[/cmd] $typeof(%a) 737 %a = $(1 + 2) 738 [cmd]echo[/cmd] $typeof(%a) 739 [cmd]echo[/cmd] $typeof($typeof(%a)) 740 [/example] 741 */ 742 KVSCF(typeofCKEYWORDWORKAROUND)743 KVSCF(typeofCKEYWORDWORKAROUND) 744 { 745 KviKvsVariant * v; 746 747 KVSCF_PARAMETERS_BEGIN 748 KVSCF_PARAMETER("data", KVS_PT_VARIANT, 0, v) 749 KVSCF_PARAMETERS_END 750 751 QString szType; 752 v->getTypeName(szType); 753 KVSCF_pRetBuffer->setString(szType); 754 return true; 755 } 756 757 /* 758 @doc: u 759 @type: 760 function 761 @title: 762 $u 763 @short: 764 Returns the UNDERLINE mIRC control character 765 @syntax: 766 <string> $u 767 @description: 768 Returns the UNDERLINE mIRC control character (Ctrl+U).[br] 769 @seealso: 770 [fnc]$k[/fnc], [fnc]$b[/fnc], [fnc]$i[/fnc], [fnc]$r[/fnc], [fnc]$o[/fnc] 771 */ 772 KVSCF(u)773 KVSCF(u) 774 { 775 KVSCF_pRetBuffer->setString(QString(QChar(KviControlCodes::Underline))); 776 return true; 777 } 778 779 /* 780 @doc: uflags 781 @type: 782 function 783 @title: 784 $uflags 785 @short: 786 Retrieves the user flags of a user 787 @syntax: 788 $uflags[(<nickname>[,<irc context id>])] 789 @description: 790 Returns the user flags of the user with <nickname>.[br] 791 If the <nickname> is not given it is assumed to be the current nickname.[br] 792 If this information is not known yet or the user with <nickname> is not found 793 in the current IRC context user database, an empty string is returned.[br] 794 @examples: 795 @seealso: 796 */ 797 KVSCF(uflags)798 KVSCF(uflags) 799 { 800 QString szNick; 801 kvs_uint_t uContextId; 802 803 KVSCF_PARAMETERS_BEGIN 804 KVSCF_PARAMETER("nickname", KVS_PT_STRING, KVS_PF_OPTIONAL, szNick) 805 KVSCF_PARAMETER("context_id", KVS_PT_UINT, KVS_PF_OPTIONAL, uContextId) 806 KVSCF_PARAMETERS_END 807 808 KviConsoleWindow * cons = nullptr; 809 if(KVSCF_pParams->count() > 1) 810 { 811 cons = g_pApp->findConsole(uContextId); 812 if(!cons) 813 KVSCF_pContext->warning(__tr2qs_ctx("No such IRC context (%u)", "kvs"), uContextId); 814 } 815 else 816 { 817 cons = KVSCF_pContext->window()->console(); 818 if(!cons) 819 KVSCF_pContext->warning(__tr2qs_ctx("This window is not associated to an IRC context", "kvs")); 820 } 821 822 if(cons && cons->isConnected()) 823 { 824 KviIrcUserEntry * e = cons->connection()->userDataBase()->find(szNick.isEmpty() ? cons->connection()->currentNickName() : szNick); 825 if(e) 826 { 827 KVSCF_pRetBuffer->setString(e->userFlags()); 828 return true; 829 } 830 } 831 832 KVSCF_pRetBuffer->setNothing(); 833 return true; 834 } 835 836 /* 837 @doc: unicode 838 @type: 839 function 840 @title: 841 $unicode 842 @short: 843 Returns the Unicode code of a set of characters 844 @syntax: 845 <variant> $unicode(<char:string>) 846 @description: 847 If <char> is composed only of a single character 848 then returns its Unicode code point as an integer. 849 If <char> is composed of more than one character 850 then an array of Unicode code points is returned. 851 @seealso: 852 [fnc]$cr[/fnc], [fnc]$lf[/fnc], [fnc]$char[/fnc] 853 */ 854 KVSCF(unicode)855 KVSCF(unicode) 856 { 857 QString sz; 858 KVSCF_PARAMETERS_BEGIN 859 KVSCF_PARAMETER("char", KVS_PT_NONEMPTYSTRING, 0, sz) 860 KVSCF_PARAMETERS_END 861 862 if(sz.length() > 1) 863 { 864 KviKvsArray * a = new KviKvsArray(); 865 for(auto&& c : sz) 866 a->append(new KviKvsVariant((kvs_int_t)(c.unicode()))); 867 KVSCF_pRetBuffer->setArray(a); 868 } 869 else 870 { 871 KVSCF_pRetBuffer->setInteger((kvs_int_t)(sz[0].unicode())); 872 } 873 return true; 874 } 875 876 /* 877 @doc: unixtime 878 @type: 879 function 880 @title: 881 $unixTime 882 @short: 883 Returns the current UNIX time 884 @syntax: 885 <integer> $unixtime 886 @description: 887 Returns the time since the Epoch (00:00:00 UTC, January 1, 1970), 888 measured in seconds. 889 @seealso: 890 [fnc]$date[/fnc], [fnc]$hpTimeStamp[/fnc] 891 */ 892 KVSCF(unixtime)893 KVSCF(unixtime) 894 { 895 KVSCF_pRetBuffer->setInteger((kvs_int_t)(time(nullptr))); 896 return true; 897 } 898 899 /* 900 @doc: unserialize 901 @type: 902 function 903 @title: 904 $unserialize 905 @short: 906 Decodes JSON-encoded string 907 @syntax: 908 <mixed> $unserialize(<data:string>) 909 @description: 910 Decodes JSON-encoded string 911 @seealso: 912 [fnc]$serialize[/fnc] 913 */ 914 KVSCF(unserialize)915 KVSCF(unserialize) 916 { 917 QString szData; 918 919 KVSCF_PARAMETERS_BEGIN 920 KVSCF_PARAMETER("data", KVS_PT_NONEMPTYSTRING, 0, szData) 921 KVSCF_PARAMETERS_END 922 923 KviKvsVariant * pVar = KviKvsVariant::unserialize(szData); 924 if(pVar) 925 { 926 KVSCF_pRetBuffer->copyFrom(pVar); 927 delete pVar; 928 } 929 return true; 930 } 931 932 /* 933 @doc: username 934 @type: 935 function 936 @title: 937 $username 938 @short: 939 Returns the username of the specified user 940 @syntax: 941 <string> $username(<nickname:string>) 942 @description: 943 Returns the username of the specified IRC user IF it is known.[br] 944 The username is known if [fnc]$isWellKnown[/fnc] returns 1.[br] 945 The username is generally known if the user is on a channel with you 946 or has an open query with you.[br] 947 Detailed explanation:[br] 948 KVIrc has an internal database of users that are currently 949 visible by [i][b]this client[/b][/i]: this includes users on open channels 950 and queries.[br] The other IRC users are [b]not[/b] in the database: 951 this means that KVIrc knows NOTHING about them and can't return 952 any information immediately. In this case this function will return 953 an EMPTY string.[br] 954 If a user is in the database, at least his nickname is known.[br] 955 The username and hostname are known only if the server provides that information 956 spontaneously or after a KVIrc request.[br] 957 KVIrc requests user information for all the users in open queries 958 and channels. This information takes some time to be retrieved, 959 in this interval of time KVIrc knows only the user's nickname. 960 This function will return the string "*" in this case.[br] 961 @seealso: 962 [fnc]$isWellKnown[/fnc], [fnc]$hostname[/fnc], [fnc]$realname[/fnc], [cmd]awhois[/cmd] 963 */ 964 KVSCF(username)965 KVSCF(username) 966 { 967 QString szNick; 968 969 KVSCF_PARAMETERS_BEGIN 970 KVSCF_PARAMETER("nick", KVS_PT_NONEMPTYSTRING, 0, szNick) 971 KVSCF_PARAMETERS_END 972 973 KviConsoleWindow * c = KVSCF_pContext->window()->console(); 974 if(c && c->isConnected()) 975 { 976 KviIrcUserEntry * e = KVSCF_pContext->window()->connection()->userDataBase()->find(szNick); 977 if(e) 978 { 979 KVSCF_pRetBuffer->setString(e->user()); 980 return true; 981 } 982 } 983 984 KVSCF_pRetBuffer->setNothing(); 985 return true; 986 } 987 988 /* 989 @doc: version 990 @type: 991 function 992 @title: 993 $version 994 @short: 995 Returns information about the version of KVIrc. 996 @syntax: 997 <string> $version() 998 <string> $version(<type:string>) 999 @description: 1000 Returns information about the version of the currently running KVIrc.[br] 1001 Type can be one of: 1002 [ul] 1003 [li]a: return the application name[/li] 1004 [li]b: return the build date in human readable form[/li] 1005 [li]n: return the release name[/li] 1006 [li]r: return the revision number[/li] 1007 [li]s: return the current sources date[/li] 1008 [li]v: return the current numeric version[/li] 1009 [/ul] 1010 1011 If <type> is omitted a full string is returned.[br] 1012 @examples: 1013 [example] 1014 [cmd]echo[/cmd] $version $version(r) 1015 [/example] 1016 @seealso: 1017 [fnc]$features[/fnc] 1018 */ 1019 full_version_helper()1020 static QString full_version_helper() 1021 { 1022 QString szVersion; 1023 1024 szVersion = "KVIrc"; 1025 szVersion += " " KVI_RELEASE_NAME " " KVI_VERSION; 1026 szVersion += ", revision: "; 1027 szVersion += KviBuildInfo::buildRevision(); 1028 szVersion += ", build type: "; 1029 szVersion += KviBuildInfo::buildType(); 1030 szVersion += ", sources date: "; 1031 szVersion += KviBuildInfo::buildSourcesDate(); 1032 szVersion += ", built on: "; 1033 szVersion += KviBuildInfo::buildDate(); 1034 1035 return szVersion; 1036 } 1037 KVSCF(version)1038 KVSCF(version) 1039 { 1040 QString szType; 1041 1042 KVSCF_PARAMETERS_BEGIN 1043 KVSCF_PARAMETER("type", KVS_PT_STRING, KVS_PF_OPTIONAL, szType) 1044 KVSCF_PARAMETERS_END 1045 1046 if(szType.isEmpty()) 1047 KVSCF_pRetBuffer->setString(full_version_helper()); 1048 else 1049 { 1050 QString szRetValue; 1051 if(szType.contains('b')) 1052 szRetValue = KviBuildInfo::buildDate(); 1053 else if(szType.contains('a')) 1054 szRetValue = "KVIrc"; 1055 else if(szType.contains('n')) 1056 szRetValue = KVI_RELEASE_NAME; 1057 else if(szType.contains('r')) 1058 szRetValue = KviBuildInfo::buildRevision(); 1059 else if(szType.contains('s')) 1060 szRetValue = KviBuildInfo::buildSourcesDate(); 1061 else if(szType.contains('t')) 1062 szRetValue = KviBuildInfo::buildType(); 1063 else if(szType.contains('v')) 1064 szRetValue = KVI_VERSION; 1065 else 1066 szRetValue = full_version_helper(); 1067 1068 KVSCF_pRetBuffer->setString(szRetValue); 1069 } 1070 return true; 1071 } 1072 1073 /* 1074 @doc: window 1075 @type: 1076 function 1077 @title: 1078 $window 1079 @short: 1080 Retrieve the ID of a specified window. 1081 @syntax: 1082 <string> $window 1083 <string> $window([<caption_text:hash>[,<context_id:uint>]]) 1084 @description: 1085 Returns the [b]window ID[/b] of the first window that 1086 has the specified <caption text>.[br] 1087 If no window matches the specified <caption text>, an invalid 1088 window ID is returned (0).[br] 1089 If no <caption text> is specified, this function returns the ID 1090 of the current window.[br] 1091 <context_id> restricts search in only one IRC context. 1092 @examples: 1093 [example] 1094 [cmd]echo[/cmd] This is the window with ID $window 1095 [/example] 1096 @seealso: 1097 [fnc]$channel[/fnc], 1098 [fnc]$query[/fnc], 1099 [fnc]$console[/fnc], 1100 [doc:window_naming_conventions]Window naming conventions[/doc] 1101 */ 1102 KVSCF(window)1103 KVSCF(window) 1104 { 1105 //#warning "FIXME: the window identifiers could be numbers!" 1106 QString szCaption; 1107 kvs_int_t iContextId; // kvs_int_t is 64bit while int is 32 (and thus KVSCF_PARAMETER() crashes) 1108 1109 KVSCF_PARAMETERS_BEGIN 1110 KVSCF_PARAMETER("caption_text", KVS_PT_STRING, KVS_PF_OPTIONAL, szCaption) 1111 KVSCF_PARAMETER("context_id", KVS_PT_INTEGER, KVS_PF_OPTIONAL, iContextId) 1112 KVSCF_PARAMETERS_END 1113 1114 KviWindow * pWnd = nullptr; 1115 if(szCaption.isEmpty()) 1116 { 1117 pWnd = KVSCF_pContext->window(); 1118 } 1119 else 1120 { 1121 if(KVSCF_pParams->count() < 2) 1122 iContextId = -1; 1123 1124 pWnd = g_pApp->findWindowByCaption(szCaption, iContextId); 1125 } 1126 KVSCF_pRetBuffer->setInteger(pWnd ? pWnd->numericId() : 0); 1127 return true; 1128 } 1129 }; 1130