home *** CD-ROM | disk | FTP | other *** search
/ Chip 2011 November / CHIP_2011_11.iso / Programy / Narzedzia / AIMP2 / aimp_2.61.583.exe / $TEMP / YandexPackSetup.msi / filCE527DEABCC69D5FF44711863445D162 < prev    next >
Text File  |  2010-07-12  |  41KB  |  1,228 lines

  1. XB._functions = {};
  2.  
  3. XB._functions.CN_assign = XB._calcNodes.ProcNode.extend({
  4.     $name: "CN_assign",
  5.     
  6.     expectedArgNames: ["name", "value"],
  7.     
  8.     _proc: function Fassign_proc(eventInfo) {
  9.         var refName = this._argManager.getValByName("name", "String");
  10.         var refNode = this._parentWidget.findVariable(refName);
  11.         if (!refNode)
  12.             refNode = this._parentWidget.findSetting(refName);
  13.         if (!refNode)
  14.             throw new Error(XB._base.consts.ERR_DATA_UNDEFINED + " (" + refName + ")");
  15.         var newValue = this._argManager.getValByName("value");
  16.         refNode.setValue(newValue);
  17.     }
  18. });
  19.  
  20. XB._functions.CN_cast = XB._calcNodes.FuncNode.extend({
  21.     $name: "CN_cast",
  22.     
  23.     expectedArgNames: ["type", "value"],
  24.     
  25.     _calculate: function Fcast_calculate(changedArgs) {
  26.         let preferedType = this._argManager.getValByName("type", "String");
  27.         let value = this._argManager.getValByName("value");
  28.         
  29.         switch(preferedType) {
  30.             case "empty":
  31.                 return XB.types.empty;
  32.             case "bool":
  33.                 return XB._base.runtime.xToBool(value);
  34.             case "number":
  35.                 return XB._base.runtime.xToNumber(value);
  36.             case "string":
  37.                 return XB._base.runtime.xToString(value);
  38.             default:
  39.                 throw new Error("Unknown cast type: " + preferedType);
  40.         }
  41.     }
  42. });
  43.  
  44. XB._functions.RegEx = XB._calcNodes.FuncNode.extend({
  45.     $name: "RegEx",
  46.     
  47.     _calculate: function FRegex_calculate(changedArgs) {
  48.         if (!this._compiledRegExp || this._argManager.argInArray("expression", changedArgs))
  49.             this._compiledRegExp = new RegExp(this._argManager.getValByName("expression", "String"), "m");
  50.     },
  51.     
  52.     _compiledRegExp: null
  53. });
  54.  
  55. XB._functions["CN_regex-test"] = XB._functions.RegEx.extend({
  56.     $name: "CN_regex-test",
  57.     
  58.     expectedArgNames: ["expression", "value"],
  59.     
  60.     _calculate: function FRegexTest_calculate(changedArgs) {
  61.         this.base(changedArgs);
  62.         let string = this._argManager.getValByName("value", "String");
  63.         return this._compiledRegExp.test(string);
  64.     }
  65. });
  66.  
  67. XB._functions["CN_regex-search"] = XB._functions.RegEx.extend({
  68.     $name: "CN_regex-search",
  69.     
  70.     expectedArgNames: ["expression", "value"],
  71.     
  72.     _calculate: function FRegexSearch_calculate(changedArgs) {
  73.         this.base(changedArgs);
  74.         
  75.         let string = this._argManager.getValByName("value", "String");
  76.         let match = string.match(this._compiledRegExp);
  77.         if (!match)
  78.             return XB.types.empty;
  79.         return match.length > 1 ? match[1] : match[0];
  80.     }
  81. });
  82.  
  83. XB._functions["CN_regex-escape"] = XB._functions.RegEx.extend({
  84.     $name: "CN_regex-escape",
  85.     
  86.     expectedArgNames: ["value"],
  87.     
  88.     _calculate: function FRegexEscape_calculate(changedArgs) {
  89.         let string = this._argManager.getValByName("value", "String");
  90.         return sysutils.RegExp.escape(string);
  91.     }
  92. });
  93.  
  94. XB._functions.Arithmetical = XB._calcNodes.FuncNode.extend({
  95.     $name: "Arithmetical",
  96.     
  97.     _calculate: function FArithmetical_calculate(changedArgs) {
  98.         return Number( this._applyOp(this._operation).toFixed(XB._functions.Arithmetical.PRECISION) );
  99.     },
  100.     
  101.     _applyOp: function FArithmetical_applyOp(op) {
  102.         var result = undefined;
  103.         for (let valIndex = 0, len = this._argManager.argsCount; valIndex < len; valIndex++) {
  104.             var num = this._argManager.getValByIndex(valIndex, "Number");
  105.             if (result == undefined)
  106.                 result = num;
  107.             else
  108.                 result = op(result, num);
  109.         }
  110.         return result;
  111.     }
  112. });
  113.  
  114. XB._functions.Arithmetical.PRECISION = 6;
  115.  
  116. XB._functions.CN_add = XB._functions.Arithmetical.extend({
  117.     $name: "CN_add",
  118.     
  119.     _operation: function Fadd_operation(p1, p2) {
  120.         return p1 + p2;
  121.     }
  122. });
  123.  
  124. XB._functions.CN_sub = XB._functions.Arithmetical.extend({
  125.     $name: "CN_sub",
  126.     
  127.     _operation: function Fsub_operation(p1, p2) {
  128.         return p1 - p2;
  129.     }
  130. });
  131.  
  132. XB._functions.CN_mul = XB._functions.Arithmetical.extend({
  133.     $name: "CN_mul",
  134.     
  135.     _operation: function Fmul_operation(p1, p2) {
  136.         return p1 * p2;
  137.     }
  138. });
  139.  
  140. XB._functions.CN_div = XB._functions.Arithmetical.extend({
  141.     $name: "CN_div",
  142.     
  143.     _operation: function Fdiv_operation(p1, p2) {
  144.         if (p2 == 0)
  145.             throw new Error("Division by zero");
  146.         return p1 / p2;
  147.     }
  148. });
  149.  
  150. XB._functions.CN_mod = XB._functions.Arithmetical.extend({
  151.     $name: "CN_mod",
  152.     
  153.     _operation: function Fmod_operation(p1, p2) {
  154.         if (p2 == 0)
  155.             throw new Error("Division by zero");
  156.         return p1 % p2;
  157.     }
  158. });
  159.  
  160. XB._functions["CN_format-number"] = XB._calcNodes.FuncNode.extend({
  161.     $name: "CN_format-number",
  162.     
  163.     expectedArgNames: ["value", "precision", "separate-groups", "positive-sign"],
  164.     
  165.     _calculate: function FFormatNumber_calculate(changedArgs) {
  166.         var num = this._argManager.getValByName("value", "Number");
  167.         var precision = this._argManager.getValByNameDef("precision", "Number", undefined);
  168.         if (precision !== undefined) {
  169.             precision = parseInt(precision, 10);
  170.             if (precision < 0)
  171.                 throw new RangeError("Precision must be positive");
  172.         }
  173.         
  174.         var posSign = this._argManager.getValByNameDef("positive-sign", "Bool", false);
  175.         
  176.         var sign = "";
  177.         if (num < 0)
  178.             sign = "-";
  179.         else {
  180.             if (posSign && (num > 0))
  181.                 sign = "+";
  182.         }
  183.         
  184.         var result;
  185.         
  186.         if (precision == undefined) {
  187.             result = sign + Math.abs(num).toLocaleString();
  188.         } else {
  189.             var order = Math.pow(10, precision);
  190.             var rounded = Math.round(Math.abs(num) * order);
  191.             
  192.             result = sign + parseInt(rounded / order, 10).toLocaleString();
  193.             if (precision > 0) {
  194.                 var fracStr = rounded.toString().substr(-precision);
  195.                 fracStr = sysutils.strdup("0", precision - fracStr.length) + fracStr;
  196.                 result += XB._base.consts.STR_LOCALE_DECIMAL_SEPARATOR + fracStr;
  197.             }
  198.         }
  199.         
  200.         if (!this._argManager.getValByNameDef("separate-groups", "Bool", true)) {
  201.             result = result.replace(/\s+/g, "");
  202.         }
  203.         
  204.         return result;
  205.     }
  206. });
  207.  
  208. XB._functions.Periodic = XB._calcNodes.FuncNode.extend({
  209.     $name: "Periodic",
  210.     
  211.     expectedArgNames: ["interval"],
  212.     
  213.     constructor: function FPeriodic_constructor() {
  214.         this.base.apply(this, arguments);
  215.         this._timer = XB._Cc["@mozilla.org/timer;1"].createInstance(XB._Ci.nsITimer);
  216.     },
  217.     
  218.     _resetTimer: function FPeriodic_resetTimer() {
  219.         var expireTime = this._argManager.getValByNameDef(this.expectedArgNames[0], "Number", Number.POSITIVE_INFINITY);
  220.         if (expireTime == Number.POSITIVE_INFINITY) {
  221.             this._timerSet = true;
  222.             return;
  223.         }
  224.         
  225.         if (expireTime <= 0)
  226.             throw new RangeError(this._consts.ERR_INVALID_INTERVAL);
  227.         expireTime = Math.max(expireTime, XB._functions.Periodic.MIN_INTERVAL);
  228.         
  229.         this._timer.initWithCallback(this, expireTime * 1000, this._timer.TYPE_REPEATING_SLACK);
  230.         this._timerSet = true;
  231.         this._timerInterval = expireTime;
  232.     },
  233.     
  234.     _cancelTimer: function FPeriodic_cancelTimer() {
  235.         this._timer.cancel();
  236.         this._timerSet = false;
  237.     },
  238.     
  239.     _calculate: function FPeriodic_calculate(changedArgs) {
  240.         if (this._hasSubscribers() &&
  241.             (!this._timerSet || this._argManager.argInArray(this.expectedArgNames[0], changedArgs))) {
  242.             this._resetTimer();
  243.         }
  244.         else {
  245.             this._cancelTimer();
  246.         }
  247.         return this._storedValue;
  248.     },
  249.     
  250.     _notNeeded: function FPeriodic_notNeeded() {
  251.         this._cancelTimer();
  252.     },
  253.     
  254.     _timer: null,
  255.     _timerInterval: undefined,
  256.     _timerSet: false
  257. }, {
  258.     MIN_INTERVAL: 1
  259. });
  260.  
  261. XB._functions.CN_timestamp = XB._functions.Periodic.extend({
  262.     $name: "CN_timestamp",
  263.     
  264.     QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsITimerCallback]),
  265.     
  266.     notify: function Ftimestamp_notify() {
  267.         try {
  268.             this._setNewVal( parseInt(Date.now() / 1000, 10) );
  269.             this._notifyDeps();
  270.         }
  271.         catch (e) {
  272.             this._parentWidget.logger.error("CN_timestamp.notify() failed. " + e.message);
  273.         }
  274.     },
  275.     
  276.     _calculate: function Ftimestamp_calculate(changedArgs) {
  277.         this.base(changedArgs);
  278.         return parseInt(Date.now() / 1000, 10);
  279.     }
  280. });
  281.  
  282. XB._functions.CN_meander = XB._functions.Periodic.extend({
  283.     $name: "CN_meander",
  284.     
  285.     notify: function Fmeander_notify() {
  286.         try {
  287.             this._setNewVal(!this._storedValue);
  288.             this._notifyDeps();
  289.         }
  290.         catch (e) {
  291.             this._parentWidget.logger.error("CN_meander.notify() failed. " + e.message);
  292.         }
  293.     }
  294. });
  295.  
  296. XB._functions["CN_time-arrived"] = XB._calcNodes.FuncNode.extend({
  297.     $name: "CN_time-arrived",
  298.     
  299.     expectedArgNames: ["time"],
  300.     
  301.     constructor: function Ftimearrived_constructor() {
  302.         this.base.apply(this, arguments);
  303.         this._timer = XB._Cc["@mozilla.org/timer;1"].createInstance(XB._Ci.nsITimer);
  304.     },
  305.     
  306.     QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsITimerCallback]),
  307.     
  308.     notify: function Fwait_notify() {
  309.         try {
  310.             if (this._setNewVal(true))
  311.                 this._notifyDeps();
  312.         }
  313.         catch (e) {
  314.             this._parentWidget.logger.error("CN_time-arrived.notify() failed. " + e.message);
  315.         }
  316.     },
  317.     
  318.     _timer: null,
  319.     
  320.     _calculate: function Ftimearrived_calculate(changedArgs) {
  321.         var moreToWait = this._argManager.getValByName("time", "Number") - parseInt(Date.now() / 1000, 10);
  322.         if (moreToWait > 0)
  323.             this._timer.initWithCallback(this, moreToWait * 1000, this._timer.TYPE_ONE_SHOT);
  324.         return moreToWait <= 0;
  325.     }
  326. });
  327.  
  328. XB._functions["CN_format-time"] = XB._calcNodes.FuncNode.extend({
  329.     $name: "CN_format-time",
  330.     
  331.     expectedArgNames: ["value", "format"],
  332.     
  333.     _calculate: function FFormatTime_calculate(changedArgs) {
  334.         return this._formatTimestamp(this._argManager.getValByName("value", "Number") * 1000,
  335.                                      this._argManager.getValByName("format", "String"));
  336.     },
  337.     
  338.     _formatTimestamp: function format(timestamp, format) {
  339.         var date = new Date(timestamp);
  340.         if (date == "Invalid Date")
  341.             throw new RangeError("Invalid date timestamp (" + timestamp + ")");
  342.         var components = [];
  343.         
  344.         function leadZero(str) {
  345.             return str.length > 1 ? str : "0" + str;
  346.         }
  347.         
  348.         function formatCode(code) {
  349.             switch (code) {
  350.                 case "d":
  351.                     return date.getDate();
  352.                 case "D":
  353.                     return leadZero("" + date.getDate());
  354.                 case "m":
  355.                     return date.getMonth() + 1;
  356.                 case "M":
  357.                     return leadZero("" + (date.getMonth() + 1));
  358.                 case "y":
  359.                     return ("" + date.getFullYear()).substr(2, 2);
  360.                 case "Y":
  361.                     return date.getFullYear();
  362.                 case "h":
  363.                     return date.getHours();
  364.                 case "H":
  365.                     return leadZero("" + date.getHours());
  366.                 case "n":
  367.                     return date.getMinutes();
  368.                 case "N":
  369.                     return leadZero("" + date.getMinutes());
  370.                 case "s":
  371.                     return date.getSeconds();
  372.                 case "S":
  373.                     return leadZero("" + date.getSeconds());
  374.                 default:
  375.                     throw new SyntaxError("Unknown format code " + code);
  376.             }
  377.         }
  378.         
  379.         function makeComponents(str, start, accum) {
  380.             var occur = str.indexOf("%", start);
  381.             
  382.             if (occur == -1) {
  383.                 accum.push(str.substring(start));
  384.                 return;
  385.             }
  386.             accum.push(str.substring(start, occur));
  387.             accum.push(formatCode(str.substr(occur + 1, 1)));
  388.             
  389.             makeComponents(str, occur + 2, accum);
  390.         }
  391.         
  392.         makeComponents(format, 0, components);
  393.         return components.join("");
  394.     }
  395. });
  396.  
  397. XB._functions.CN_if = XB._calcNodes.FuncNode.extend({
  398.     $name: "CN_if",
  399.     
  400.     expectedArgNames: ["condition", "ontrue", "onfalse"],
  401.     
  402.     _calculate: function Fif_calculate(changedArgs) {
  403.         if ( this._argManager.getValByName("condition", "Bool") )
  404.             return this._argManager.getValByNameDef("ontrue", undefined, XB.types.empty);
  405.         return this._argManager.getValByNameDef("onfalse", undefined, XB.types.empty);
  406.     }
  407. });
  408.  
  409. XB._functions.CN_concat = XB._calcNodes.FuncNode.extend({
  410.     $name: "CN_concat",
  411.     
  412.     _calculate: function Fconcat_calculate(changedArgs) {
  413.         var numArgs = this._argManager.argsCount;
  414.         if (numArgs > 0)
  415.             return XB._functions.CN_concat.concatArgs(this, 0, numArgs - 1);
  416.         return XB.types.empty;
  417.     }
  418. });
  419.  
  420. // Practically an alias with another class name for debugging purpose
  421. XB._functions.Data = XB._functions.CN_concat.extend({
  422.     $name: "Data"
  423. });
  424.  
  425. XB._functions.CN_concat.concatArgs = function ConcatArgs (funcNode, start, end) {
  426.     if (end - start < 1)
  427.         return funcNode._argManager.getValByIndex(start);
  428.     
  429.     var resultIsXML = false;
  430.     var argXValues = [];
  431.     
  432.     for (; start <= end; start++) {
  433.         var xv = funcNode._argManager.getValByIndex(start);
  434.         argXValues.push(xv);
  435.         resultIsXML = resultIsXML || XB._base.runtime.isXML(xv);
  436.     }
  437.     
  438.     return XB._functions.CN_concat.glue(argXValues, resultIsXML);
  439. };
  440.  
  441. XB._functions.CN_concat.glue = function ConcatGlue (valuesArray, xmlOutput) {
  442.     if (!xmlOutput) {
  443.         var result = "";
  444.         
  445.         for each (let value in valuesArray) {
  446.             result += XB._base.runtime.xToString(value);
  447.         }
  448.         
  449.         return result;
  450.     }
  451.     else {
  452.         var result = new XB.types.XML();
  453.         
  454.         for each (let value in valuesArray) {
  455.             if (XB._base.runtime.isXML(value))
  456.                 result.append(value);
  457.             else {
  458.                 var node = XB._base.runtime.tempXMLDoc.createTextNode(XB._base.runtime.xToString(value));
  459.                 result.append(node);
  460.             }
  461.         }
  462.         
  463.         return result;
  464.     }
  465. };
  466.  
  467. XB._functions.CN_xpath = XB._calcNodes.FuncNode.extend({
  468.     $name: "CN_xpath",
  469.     
  470.     expectedArgNames: ["expression", "source"],
  471.     
  472.     _calculate: function Fxpath_calculate(changedArgs) {
  473.         var expr = this._argManager.getValByName("expression", "String");
  474.         var src = this._argManager.getValByName("source");
  475.         if (!XB._base.runtime.isXML(src))
  476.             return new XB.types.Exception(this._getHumanReadableID(), XB.types.Exception.types.E_TYPE,
  477.                                           "Not XML, " + XB._base.runtime.describeValue(src));
  478.         return src.query(expr);
  479.     }
  480. });
  481.  
  482. XB._functions.CN_xslt = XB._calcNodes.FuncNode.extend({
  483.     $name: "CN_xslt",
  484.     
  485.     expectedArgNames: ["stylesheet", "source"],
  486.     
  487.     _calculate: function Fxslt_calculate(changedArgs) {
  488.         var stylesheetPath = this._argManager.getValByName("stylesheet", "String");
  489.         var stylesheetFile = this._parentWidget.prototype.unit.unitPackage.findFile(stylesheetPath);
  490.         if (!stylesheetFile)
  491.             throw new Error("File no found: " + stylesheetPath);
  492.         var stylesheet = sysutils.xmlDocFromFile(stylesheetFile);
  493.         var src = this._argManager.getValByName("source");
  494.         if (!XB._base.runtime.isXML(src))
  495.             return new XB.types.Exception(this._getHumanReadableID(), XB.types.Exception.types.E_TYPE,
  496.                                           "Not XML, " + XB._base.runtime.describeValue(src));
  497.         return src.transform(stylesheet);
  498.     }
  499. });
  500.  
  501. XB._functions.CN_attribute = XB._calcNodes.FuncNode.extend({
  502.     $name: "CN_attribute",
  503.     
  504.     expectedArgNames: ["name", "value"],
  505.     
  506.     _calculate: function FAttribute_calculate(changedArgs) {
  507.         var name = this._argManager.getValByName(this.expectedArgNames[0], "String");
  508.         var value = this._argManager.getValByName(this.expectedArgNames[1], "String");
  509.         var result = new XB.types.XML();
  510.         result.addAttribute("", name, value);
  511.         return result;
  512.     }
  513. });
  514.  
  515. XB._functions["CN_serialize-xml"] = XB._calcNodes.FuncNode.extend({
  516.     $name: "CN_serialize-xml",
  517.     
  518.     expectedArgNames: ["source"],
  519.     
  520.     _calculate: function FSerializeXml_calculate(changedArgs) {
  521.         var src = this._argManager.getValByName("source");
  522.         if (!XB._base.runtime.isXML(src))
  523.             return new XB.types.Exception(this._getHumanReadableID(), XB.types.Exception.types.E_TYPE,
  524.                                           "Not XML, " + XB._base.runtime.describeValue(src));
  525.         return src.serialize();
  526.     }
  527. });
  528.  
  529. XB._functions["CN_value-of"] = XB._calcNodes.FuncNode.extend({
  530.     $name: "CN_value-of",
  531.     
  532.     expectedArgNames: ["name"],
  533.     
  534.     _calculate: function Fvalueof_calculate(changedArgs) {
  535.         if (!this._refNode || this._argManager.argInArray("name", changedArgs))
  536.             this._findRefNode();
  537.         return this._refNode.getValue(this._hasSubscribers()? this: null);
  538.     },
  539.     
  540.     _notNeeded: function Fvalueof__notNeeded() {
  541.         if (this._refNode) {
  542.             this._refNode.unsubscribe(this);
  543.             this._refNode = null;
  544.         }
  545.     },
  546.     
  547.     _findRefNode: function Fvalueof_findRefNode() {
  548.         var refName = this._argManager.getValByName("name", "String");
  549.         
  550.         var refNode = this._parentWidget.findData(refName);
  551.         
  552.         if (!refNode)
  553.             refNode = this._parentWidget.findVariable(refName);
  554.         
  555.         if (!refNode)
  556.             refNode = this._parentWidget.findSetting(refName);
  557.         
  558.         if (!refNode)
  559.             throw new Error(XB._base.consts.ERR_DATA_UNDEFINED + " (" + refName + ")");
  560.         
  561.         if (this._refNode != refNode) {
  562.             if (this._refNode)
  563.                 this._refNode.unsubscribe(this);
  564.             this._refNode = refNode;
  565.         }
  566.     },
  567.     
  568.     _refNode: null
  569. });
  570.  
  571. XB._functions["CN_is-empty"] = XB._calcNodes.FuncNode.extend({
  572.     $name: "CN_is-empty",
  573.     
  574.     expectedArgNames: ["value", "mode"],
  575.     
  576.     _calculate: function Fisempty_calculate(changedArgs) {
  577.         var what = this._argManager.getValByName("value");
  578.         var modeStr = this._argManager.getValByNameDef("mode", "String", "default");
  579.         var strict = false;
  580.         switch (modeStr) {
  581.             case "strict":
  582.                 strict = true;
  583.                 break;
  584.             case "default":
  585.                 strict = false;
  586.                 break;
  587.             default:
  588.                 throw new SyntaxError("Unknown mode \"" + modeStr + "\"");
  589.         }
  590.         return XB._functions["CN_is-empty"].test(what, strict);
  591.     }
  592. });
  593.  
  594. XB._functions["CN_is-empty"].test = function EmptyTest(what, strict) {
  595.     if (strict)
  596.         return what === XB.types.empty;
  597.     
  598.     return ( sysutils.strcmp(XB._base.runtime.xToString(what), "") == 0 )
  599. };
  600.  
  601. XB._functions.Comparision = XB._calcNodes.FuncNode.extend({
  602.     $name: "Comparision",
  603.     
  604.     expectedArgNames: ["left", "right", "mode"],
  605.     
  606.     _calculate: function FComparision_calculate(changedArgs) {
  607.         var mode = this._argManager.getValByNameDef("mode", "String", "default");
  608.         var cmpMode;
  609.         switch (mode) {
  610.             case "strict":
  611.                 cmpMode = XB._base.runtime.cmpModes.CMP_STRICT;
  612.                 break;
  613.             case "default":
  614.                 cmpMode = XB._base.runtime.cmpModes.CMP_FREE;
  615.                 break;
  616.             default:
  617.                 throw new Error("Unknown mode \"" + mode + "\"");
  618.         }
  619.         
  620.         var left = this._argManager.getValByName("left");
  621.         var right = this._argManager.getValByName("right");
  622.         return this._op( XB._base.runtime.compareValues(left, right, cmpMode) );
  623.     }
  624. });
  625.  
  626. XB._functions.CN_eq = XB._functions.Comparision.extend({
  627.     $name: "CN_eq",
  628.     
  629.     _op: function Feq_op(compResult) {
  630.         return compResult == 0;
  631.     }
  632. });
  633.  
  634. XB._functions.CN_equal = XB._functions.CN_eq;
  635.  
  636. XB._functions.CN_neq = XB._functions.CN_eq.extend({
  637.     $name: "CN_neq",
  638.     
  639.     _op: function Fneq_op(compResult) {
  640.         return !this.base(compResult);
  641.     }
  642. });
  643.  
  644. XB._functions["CN_not-equal"] = XB._functions.CN_neq;
  645.  
  646. XB._functions.Relation = XB._calcNodes.FuncNode.extend({
  647.     $name: "Relation",
  648.     
  649.     expectedArgNames: ["left", "right", "mode"],
  650.     
  651.     _calculate: function FRelation_calculate(changedArgs) {
  652.         var convType = undefined;
  653.         var mode = this._argManager.getValByNameDef("mode", "String", "number");
  654.         switch (mode) {
  655.             case "number":
  656.                 convType = "Number";
  657.                 break;
  658.             case "string":
  659.                 convType = "String";
  660.                 break;
  661.             case "smart":
  662.                 break;
  663.             default:
  664.                 throw new Error("Unknown mode \"" + mode + "\"");
  665.         }
  666.         
  667.         var left = this._argManager.getValByName("left", convType);
  668.         var right = this._argManager.getValByName("right", convType);
  669.         var cmpMode = XB._base.runtime.cmpModes[!!convType ? "CMP_STRICT" : "CMP_SMART"];
  670.         return this._op( XB._base.runtime.compareValues(left, right, cmpMode) );
  671.     }
  672. });
  673.  
  674. XB._functions.CN_lt = XB._functions.Relation.extend({
  675.     $name: "CN_lt",
  676.     
  677.     _op: function Flt_op(compResult) {
  678.         return compResult < 0;
  679.     }
  680. });
  681.  
  682. XB._functions.CN_lte = XB._functions.Relation.extend({
  683.     $name: "CN_lte",
  684.     
  685.     _op: function Flte_op(compResult) {
  686.         return compResult <= 0;
  687.     }
  688. });
  689.  
  690. XB._functions.CN_gt = XB._functions.Relation.extend({
  691.     $name: "CN_gt",
  692.     
  693.     _op: function Fgt_op(compResult) {
  694.         return compResult > 0;
  695.     }
  696. });
  697.  
  698. XB._functions.CN_gte = XB._functions.Relation.extend({
  699.     $name: "CN_gte",
  700.     
  701.     _op: function Fgte_op(compResult) {
  702.         return compResult >= 0;
  703.     }
  704. });
  705.  
  706. XB._functions.CN_not = XB._calcNodes.FuncNode.extend({
  707.     $name: "CN_not",
  708.     
  709.     _calculate: function Fnot_calculate(changedArgs) {
  710.         return !(this._argManager.getValByIndex(0, "Bool"));
  711.     }
  712. });
  713.  
  714. XB._functions.CN_or = XB._calcNodes.FuncNode.extend({
  715.     $name: "CN_or",
  716.     
  717.     _calculate: function For_calculate(changedArgs) {
  718.         if (this._argManager.argsCount < 1)
  719.             throw new Error("No arguments");
  720.         for (let i = 0, len = this._argManager.argsCount; i < len; i++) {
  721.             var val = this._argManager.getValByIndex(i);
  722.             if (XB._base.runtime.xToBool(val))
  723.                 return true;
  724.         }
  725.         return false;
  726.     }
  727. });
  728.  
  729. XB._functions.CN_coalesce = XB._calcNodes.FuncNode.extend({
  730.     $name: "CN_coalesce",
  731.     
  732.     _calculate: function Fcoalesce_calculate(changedArgs) {
  733.         let strictMode = false;
  734.         var modeStr = this._argManager.getValByNameDef("mode", "String", "default");
  735.         switch (modeStr) {
  736.             case "default":
  737.                 strictMode = false;
  738.                 break;
  739.             case "strict":
  740.                 strictMode = true;
  741.                 break;
  742.             default:
  743.                 throw new SyntacError("Unknown mode \"" + modeStr + "\"");
  744.         }
  745.         
  746.         for each (let argName in this._argManager.argsNames) {
  747.             if (argName == "mode")
  748.                 continue;
  749.             
  750.             var val = this._argManager.getValByName(argName);
  751.             if (!XB._functions["CN_is-empty"].test(val, strictMode))
  752.                 return val;
  753.         }
  754.         
  755.         return XB.types.empty;
  756.     }
  757. });
  758.  
  759. XB._functions.CN_and = XB._calcNodes.FuncNode.extend({
  760.     $name: "CN_and",
  761.     
  762.     _calculate: function Fand_calculate(changedArgs) {
  763.         if (this._argManager.argsCount < 1)
  764.             throw new Error("No arguments");
  765.         for (let i = 0, len = this._argManager.argsCount; i < len; i++) {
  766.             let val = this._argManager.getValByIndex(i);
  767.             let asBool = XB._base.runtime.xToBool(val);
  768.             
  769.             if (!asBool)
  770.                 return false;
  771.         }
  772.         return true;
  773.     }
  774. });
  775.  
  776. XB._functions.CN_try = XB._calcNodes.FuncNode.extend({
  777.     $name: "CN_try",
  778.     
  779.     expectedArgNames: ["expression", "..."],
  780.     
  781.     _calculate: function Ftry_calculate(changedArgs) {
  782.         try {
  783.             return this._argManager.getValByName(this.expectedArgNames[0]);
  784.         }
  785.         catch (origException) {
  786.             if (!(origException instanceof XB.types.Exception))
  787.                 throw origException;
  788.             
  789.             if (origException.type == XB.types.Exception.types.E_RETHROW) {
  790.                 origException = new XB.types.Exception(origException.srcNodeUid, XB.types.Exception.types.E_GENERIC, origException.message);
  791.             }
  792.             if (this._debugMode)
  793.                 this._parentWidget.logger.debug(this._getHumanReadableID() + " cought exception: " + origException.toString());
  794.             
  795.             this._findHandler(origException.type);
  796.             if (this._usedHandler) {
  797.                 var handlerVal = this._usedHandler.getValue(this._hasSubscribers()? this: null);
  798.                 if (handlerVal instanceof XB.types.Exception) {
  799.                     if (this._debugMode)
  800.                         this._parentWidget.logger.debug(this._getHumanReadableID() + " exception rethrown with type " + handlerVal.type);
  801.                     switch (handlerVal.type) {
  802.                         case XB.types.Exception.types.E_RETHROW:
  803.                             handlerVal = origException;
  804.                             break;
  805.                         case XB.types.Exception.types.E_LASTVALUE:
  806.                             handlerVal = this._storedValue;
  807.                             break;
  808.                     }
  809.                 }
  810.                 if (this._debugMode)
  811.                     this._parentWidget.logger.debug(this._getHumanReadableID() + " exception handler returned " + handlerVal);
  812.                 return handlerVal;
  813.             }
  814.             
  815.             return origException;
  816.         }
  817.     },
  818.     
  819.     _findHandler: function (exceptionType) {
  820.         var handler = this._argManager.findNodeByName(exceptionType) ||
  821.                       this._argManager.findNodeByName(this._consts.STR_ALL_EXCEPTIONS);
  822.         if (this._usedHandler != handler) {
  823.             if (this._usedHandler)
  824.                 this._usedHandler.unsubscribe(this);
  825.             this._usedHandler = handler;
  826.         }
  827.     },
  828.     
  829.     _notNeeded: function Ftry__notNeeded() {
  830.         if (this._usedHandler) {
  831.             this._usedHandler.unsubscribe(this);
  832.             this._usedHandler = null;
  833.         }
  834.     },
  835.     
  836.     _usedHandler: null,
  837.     
  838.     _consts: {
  839.         STR_ALL_EXCEPTIONS: "..."
  840.     }
  841. });
  842.  
  843. XB._functions.CN_throw = XB._calcNodes.FuncNode.extend({
  844.     $name: "CN_throw",
  845.     
  846.     expectedArgNames: ["type"],
  847.     
  848.     _calculate: function Fthrow_calculate(changedArgs) {
  849.         var eType = this._argManager.getValByNameDef("type", "String", XB.types.Exception.types.E_RETHROW);
  850.         
  851.         var Exception = new XB.types.Exception(this._getHumanReadableID(), eType, "XBTHROW");
  852.         var excPropVal;
  853.         var excPropsNames = this._argManager.argsNames;
  854.         for each (let propName in excPropsNames) {
  855.             if (propName == "type")
  856.                 continue;
  857.             excPropVal = this._argManager.getValByName(propName);
  858.             Exception[propName] = excPropVal;
  859.         }
  860.         
  861.         return Exception;
  862.     }
  863. });
  864.  
  865. XB._functions.CN_lastvalue = XB._calcNodes.FuncNode.extend({
  866.     $name: "CN_lastvalue",
  867.     
  868.     _calculate: function Flastvalue_calculate(changedArgs) {
  869.         var lastValException = new XB.types.Exception(this._getHumanReadableID(), XB.types.Exception.types.E_LASTVALUE,
  870.                                                       "XBLASTVAL");
  871.         return lastValException;
  872.     }
  873. });
  874.  
  875. XB._functions.CN_optional = XB._calcNodes.FuncNode.extend({
  876.     $name: "CN_optional",
  877.     
  878.     expectedArgNames: ["condition"],
  879.     
  880.     _calculate: function Foptional_calculate(changedArgs) {
  881.         var numArgs = this._argManager.argsCount;
  882.         if (numArgs > 1 && this._argManager.getValByName("condition", "Bool") ) {
  883.             return XB._functions.CN_concat.concatArgs(this, 1, numArgs - 1);
  884.         }
  885.         return XB.types.empty;
  886.     }
  887. });
  888.  
  889. XB._functions.CN_cookie = XB._calcNodes.FuncNode.extend({
  890.     $name: "CN_cookie",
  891.     
  892.     expectedArgNames: ["url", "name"],
  893.     
  894.     QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIObserver, Ci.nsITimerCallback]),
  895.     
  896.     observe: function Fcookie_observe(subject, topic, data) {
  897.         switch (topic) {
  898.             case "cookie-changed":
  899.                 this._timer = XB._Cc["@mozilla.org/timer;1"].createInstance(XB._Ci.nsITimer);
  900.                 this._timer.initWithCallback(this, 10, this._timer.TYPE_ONE_SHOT);
  901.                 break;
  902.             default:
  903.                 break;
  904.         }
  905.     },
  906.     
  907.     notify: function () {
  908.         try {
  909.             if (this._setNewVal(this._cookie()))
  910.                 this._notifyDeps();
  911.         }
  912.         catch (e) {
  913.             this._parentWidget.logger.error("CN_cookie.notify() failed. " + e.message);
  914.         }
  915.         finally {
  916.             this._timer = null;
  917.         }
  918.     },
  919.     
  920.     _ioService: Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService),
  921.     _cookieService: Cc["@mozilla.org/cookieService;1"].getService().QueryInterface(Ci.nsICookieService),
  922.     _observerService: Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService),
  923.     _observing: false,
  924.     _url: undefined,
  925.     _cookieName: undefined,
  926.     _timer: null,
  927.     
  928.     _cookie: function Fcookie__cookie() {
  929.         var uri = this._ioService.newURI(this._url, null, null);
  930.         var cookieString = this._cookieService.getCookieString(uri, null);
  931.         if (!cookieString)
  932.             return XB.types.empty;
  933.         
  934.         var cookies = cookieString.split(";");
  935.         for each (let cookie in cookies) {
  936.             let separatorPos = cookie.indexOf("=");
  937.             if (separatorPos == -1)
  938.                 continue;
  939.             
  940.             let cookieName = sysutils.trimAllSpaces( cookie.substring(0, separatorPos) );
  941.             if (cookieName == this._cookieName)
  942.                 return unescape( cookie.substring(separatorPos + 1) );
  943.         }
  944.         
  945.         return XB.types.empty;
  946.     },
  947.     
  948.     _calculate: function Fcookie__calculate(changedArgs) {
  949.         if (this._argManager.argInArray("url", changedArgs) || this._url == undefined)
  950.             this._url = this._argManager.getValByName("url", "String");
  951.         if (this._argManager.argInArray("name", changedArgs) || !this._cookiePattern) {
  952.             this._cookieName = this._argManager.getValByName("name", "String");
  953.         }
  954.         
  955.         if (!this._observing) {
  956.             this._observerService.addObserver(this, "cookie-changed", false);
  957.             this._observing = true;
  958.         }
  959.         
  960.         return this._cookie();
  961.     },
  962.     
  963.     _notNeeded: function Fcookie__notNeeded() {
  964.         if (this._observing) {
  965.             this._observerService.removeObserver(this, "cookie-changed");
  966.             this._observing = false;
  967.         }
  968.     }
  969. });
  970.  
  971. XB._functions.CN_request = XB._calcNodes.FuncNode.extend({
  972.     $name: "CN_request",
  973.     
  974.     expectedArgNames: ["url", "update", "expire", "format", "valid-status", "valid-xpath"],
  975.     
  976.     _calculate: function Frequest_calculate(changedArgs) {
  977.         var format;
  978.         var formatStr = this._argManager.getValByNameDef("format", "String", "xml");
  979.         switch (formatStr) {
  980.             case "text":
  981.                 format = XB.types.RequestData.Format.FMT_TEXT;
  982.                 break;
  983.             case "xml":
  984.                 format = XB.types.RequestData.Format.FMT_XML;
  985.                 break;
  986.             case "json":
  987.                 format = XB.types.RequestData.Format.FMT_JSON;
  988.                 break;
  989.             default:
  990.                 throw new Error("Unknown format specification: " + formatStr);
  991.         }
  992.         
  993.         var validStatusRange = {start: 100, end: 399};
  994.         var statusesExpr = this._argManager.getValByNameDef("valid-status", "String", "");
  995.         if (statusesExpr) {
  996.             var matches = statusesExpr.match(/^(\d+)?\.\.(\d+)?$/);
  997.             if (matches != null) {
  998.                 validStatusRange.start = matches[1]? parseInt(matches[1], 10) : 100;
  999.                 validStatusRange.end = matches[2]? parseInt(matches[2], 10) : 399;
  1000.             }
  1001.             else {
  1002.                 this._parentWidget.logger.warn("Could not parse request status validation expression (" + statusesExpr + ")");
  1003.             }
  1004.         }
  1005.         
  1006.         var updateInterval = this._argManager.getValByNameDef("update", "Number", 0)
  1007.                              || Number.POSITIVE_INFINITY;
  1008.         
  1009.         var reqData = new XB.types.RequestData(this._argManager.getValByName("url", "String"),
  1010.                                                "GET",
  1011.                                                updateInterval,
  1012.                                                this._argManager.getValByNameDef("expire", "Number", 0),
  1013.                                                format,
  1014.                                                validStatusRange,
  1015.                                                this._argManager.getValByNameDef("valid-xpath", "String"));
  1016.         return reqData;
  1017.     }
  1018. });
  1019.  
  1020.  
  1021. XB._functions.NetworkData = XB._calcNodes.FuncNode.extend({
  1022.     $name: "NetworkData",
  1023.     
  1024.     expectedArgNames: ["request"],
  1025.     
  1026.     update: function FNetworkData_update(netResource, netData) {
  1027.         if (netResource !== this._resource) {
  1028.             this._parentWidget.logger.warn("Update notification from a martian network resource! " + this._getHumanReadableID());
  1029.             return;
  1030.         }
  1031.         if (this._setNewVal(this._processResData(netData)))
  1032.             this._notifyDeps();
  1033.     },
  1034.     
  1035.     _calculate: function FNetworkData_calculate(changedArgs) {
  1036.         var reqData = this._argManager.getValByName("request", "RequestData");
  1037.         var netResource = XB.network.getResource(reqData);
  1038.         if (this._resource != netResource) {
  1039.             if (this._resource)
  1040.                 try {
  1041.                     this._resource.unsubscribe(this, this._dataType);
  1042.                 }
  1043.                 catch (e) {
  1044.                     this._parentWidget.logger.error("Could not unsubscribe from a network resource. " +
  1045.                                                     misc.formatError(e));
  1046.                     this._parentWidget.logger.debug(e.stack);
  1047.                 }
  1048.             this._resource = netResource;
  1049.         }
  1050.         
  1051.         var rawData = this._resource.requestData(this, this._dataType);
  1052.         this._parentWidget.logger.trace("FNetworkData_calculate raw data is " + rawData);
  1053.         return this._processResData(rawData) || XB.types.empty;
  1054.     },
  1055.     
  1056.     _resource: null,
  1057.     
  1058.     _notNeeded: function FNetworkData_notNeeded() {
  1059.         if (this._resource) {
  1060.             this._resource.unsubscribe(this, this._dataType);
  1061.             delete this._resource;
  1062.         }
  1063.     }
  1064. });
  1065.  
  1066. XB._functions.CN_content = XB._functions.NetworkData.extend({
  1067.     $name: "CN_content",
  1068.     
  1069.     _dataType: XB.network.ResourceDataType.NRDT_CONTENT,
  1070.     
  1071.     _processResData: function Fcontent_processResData(content) {
  1072.         if (!content)
  1073.             return XB.types.empty;
  1074.         
  1075.         if (content instanceof XB._Ci.nsIDOMDocument) {
  1076.             return new XB.types.XML(content);
  1077.         }
  1078.         
  1079.         if (!sysutils.isString(content))
  1080.             throw new TypeError("Network resource sent not an XML document, nor a String");
  1081.         
  1082.         return content;
  1083.     }
  1084. });
  1085.  
  1086. XB._functions.CN_header = XB._functions.NetworkData.extend({
  1087.     $name: "CN_header",
  1088.     
  1089.     expectedArgNames: ["request", "name"],
  1090.     
  1091.     _dataType: XB.network.ResourceDataType.NRDT_HEADERS,
  1092.     
  1093.     _calculate: function Fheader_calculate(changedArgs) {
  1094.         if (this._argManager.argInArray("name", changedArgs) || !this._headerName) {
  1095.             this._headerName = this._argManager.getValByName("name", "String");
  1096.         }
  1097.         return this.base(changedArgs);
  1098.     },
  1099.     
  1100.     _processResData: function Fheader_processResData(resHeaders) {
  1101.         if (resHeaders)
  1102.             return resHeaders[this._headerName];
  1103.     },
  1104.     
  1105.     _headerName: undefined
  1106. });
  1107.  
  1108. XB._functions.CN_finished = XB._calcNodes.FuncNode.extend({
  1109.     $name: "CN_finished",
  1110.     
  1111.     expectedArgNames: ["try-id"],
  1112.     
  1113.     onRequestFinished: function Ffinished_onRequestFinished(requestID) {
  1114.         if (this._requestID == requestID)
  1115.             if (this._setNewVal(true))
  1116.                 this._notifyDeps();
  1117.         this._requestID = undefined;
  1118.     },
  1119.     
  1120.     _calculate: function Ffinished_calculate(changedArgs) {
  1121.         var requestID = this._argManager.getValByName(this.expectedArgNames[0], "Number");
  1122.         if (XB.network.requestFinished(requestID)) return true;
  1123.         
  1124.         XB.network.subscribeToRequestFinish(requestID, this);
  1125.         this._requestID = requestID;
  1126.         return false;
  1127.     },
  1128.     
  1129.     _requestID: undefined
  1130. });
  1131.  
  1132. XB._functions.CN_update = XB._calcNodes.ProcNode.extend({
  1133.     $name: "CN_update",
  1134.     
  1135.     expectedArgNames: ["request"],
  1136.     
  1137.     _proc: function Fupdate_proc(eventInfo) {
  1138.         var requestData = this._argManager.getValByName("request", "RequestData");
  1139.         var netResource = XB.network.getResource(requestData);
  1140.         return netResource.update(true);
  1141.     }
  1142. });
  1143.  
  1144. XB._functions.CN_file = XB._calcNodes.FuncNode.extend({
  1145.     $name: "CN_file",
  1146.     
  1147.     expectedArgNames: ["path", "type"],
  1148.     
  1149.     _calculate: function Ffile_calculate(changedArgs) {
  1150.         var path = this._argManager.getValByName("path", "String");
  1151.         var type = this._argManager.getValByNameDef("type", "String", "text");
  1152.         var file = this._parentWidget.prototype.unit.unitPackage.findFile(path);
  1153.         
  1154.         switch (type) {
  1155.             case "xml":
  1156.                 return new XB.types.XML( sysutils.xmlDocFromFile(file) );
  1157.             case "text":
  1158.                 return sysutils.readTextFile(file);
  1159.             default:
  1160.                 throw new Error("Unsupported file output type");
  1161.         }
  1162.     }
  1163. });
  1164.  
  1165. XB._functions["CN_copy-to-clipboard"] = XB._calcNodes.ProcNode.extend({
  1166.     $name: "CN_copy-to-clipboard",
  1167.     
  1168.     constructor: function FCopyToClipboard_constructor() {
  1169.         this.base.apply(this, arguments);
  1170.         this._helper = XB._Cc["@mozilla.org/widget/clipboardhelper;1"].getService(XB._Ci.nsIClipboardHelper);
  1171.     },
  1172.     
  1173.     _helper: null,
  1174.     
  1175.     _proc: function FcopyToClipboard_proc(eventInfo) {
  1176.         this._helper.copyString(this._argManager.getValByIndex(0, "String"));
  1177.     }
  1178. });
  1179.  
  1180. XB._functions.CN_navigate = XB._calcNodes.ProcNode.extend({
  1181.     $name: "CN_navigate",
  1182.     
  1183.     expectedArgNames: ["url", "target"],
  1184.     
  1185.     _proc: function Fnavigate_proc(eventInfo) {
  1186.         var url = this._argManager.getValByName("url", "String");
  1187.         var target = this._argManager.getValByNameDef("target", "String", "");
  1188.         
  1189.         if (eventInfo.keys.ctrl || eventInfo.keys.meta || eventInfo.mouse.button == 1)
  1190.             target = "new tab";
  1191.         else if (eventInfo.keys.shift)
  1192.             target = "new window";
  1193.         
  1194.         var yandexAction = this._argManager.getValByNameDef("action", "String", "");
  1195.         var windowWidth = this._argManager.getValByNameDef("width", "Number", 50);
  1196.         var windowHeight = this._argManager.getValByNameDef("height", "Number", 50);
  1197.         
  1198.         this._parentWidget.host.navigate(url, target, windowWidth, windowHeight, yandexAction,
  1199.                                          this._parentWidget.prototype);
  1200.     }
  1201. });
  1202.  
  1203. XB._functions["CN_setup-widget"] = XB._calcNodes.ProcNode.extend({
  1204.     $name: "CN_setup-widget",
  1205.     
  1206.     _proc: function FSetupWidget_proc(eventInfo) {
  1207.         this._parentWidget.host.setupWidget(this._parentWidget);
  1208.     }
  1209. });
  1210.  
  1211. XB._functions["CN_add-widget"] = XB._calcNodes.ProcNode.extend({
  1212.     $name: "CN_add-widget",
  1213.     
  1214.     _proc: function FAddWidget_proc(eventInfo) {
  1215.         if (this._parentWidget.prototype.isUnique)
  1216.             throw new Error("This widget is unique!");
  1217.         this._parentWidget.host.addWidget(this._parentWidget.prototype.id, undefined, this._parentWidget, true);
  1218.     }
  1219. });
  1220.  
  1221. XB._functions["CN_remove-widget"] = XB._calcNodes.ProcNode.extend({
  1222.     $name: "CN_remove-widget",
  1223.     
  1224.     _proc: function FRemoveWidget_proc(eventInfo) {
  1225.         this._parentWidget.host.removeWidget(this._parentWidget.id);
  1226.     }
  1227. });
  1228.