~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/extensions/irc/js/lib/utils.js

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 
2
 *
 
3
 * The contents of this file are subject to the Mozilla Public
 
4
 * License Version 1.1 (the "License"); you may not use this file
 
5
 * except in compliance with the License. You may obtain a copy of
 
6
 * the License at http://www.mozilla.org/MPL/
 
7
 *
 
8
 * Software distributed under the License is distributed on an "AS
 
9
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 
10
 * implied. See the License for the specific language governing
 
11
 * rights and limitations under the License.
 
12
 *
 
13
 * The Original Code is JSIRC Library
 
14
 *
 
15
 * The Initial Developer of the Original Code is New Dimensions Consulting,
 
16
 * Inc. Portions created by New Dimensions Consulting, Inc. are
 
17
 * Copyright (C) 1999 New Dimenstions Consulting, Inc. All
 
18
 * Rights Reserved.
 
19
 *
 
20
 * Contributor(s):
 
21
 *  Robert Ginda, rginda@ndcico.com, original author
 
22
 *
 
23
 *
 
24
 * JavaScript utility functions.
 
25
 *
 
26
 * 1999-08-15 rginda@ndcico.com           v1.0
 
27
 */
 
28
 
 
29
var utils = new Object();
 
30
 
 
31
var DEBUG = true;
 
32
var dd;
 
33
 
 
34
if (DEBUG) {
 
35
    var _dd_pfx = "";
 
36
    var _dd_singleIndent = "  ";
 
37
    var _dd_indentLength = _dd_singleIndent.length;
 
38
    var _dd_currentIndent = "";
 
39
    var _dd_lastDumpWasOpen = false;
 
40
    var _dd_timeStack = new Array();
 
41
    var _dd_disableDepth = Number.MAX_VALUE;
 
42
    var _dd_currentDepth = 0;
 
43
    dd = function _dd(str) {
 
44
             if (typeof str != "string") {
 
45
                 dump(str + "\n");
 
46
             } else if (str == "") {
 
47
                 dump("<empty-string>\n");
 
48
             } else if (str[str.length - 1] == "{") {
 
49
                 ++_dd_currentDepth;
 
50
                 if (_dd_currentDepth >= _dd_disableDepth)
 
51
                     return;
 
52
                 if (str.indexOf("OFF") == 0)
 
53
                     _dd_disableDepth = _dd_currentDepth;
 
54
                 _dd_timeStack.push (new Date());
 
55
                 if (_dd_lastDumpWasOpen)
 
56
                     dump("\n");
 
57
                 dump (_dd_pfx + _dd_currentIndent + str);
 
58
                 _dd_currentIndent += _dd_singleIndent;
 
59
                 _dd_lastDumpWasOpen = true;
 
60
             } else if (str[0] == "}") {
 
61
                 if (--_dd_currentDepth >= _dd_disableDepth)
 
62
                     return;
 
63
                 _dd_disableDepth = Number.MAX_VALUE;
 
64
                 var sufx = (new Date() - _dd_timeStack.pop()) / 1000 + " sec";
 
65
                 _dd_currentIndent = 
 
66
                     _dd_currentIndent.substr(0, _dd_currentIndent.length -
 
67
                                              _dd_indentLength);
 
68
                 if (_dd_lastDumpWasOpen)
 
69
                     dump(str + " " + sufx + "\n");
 
70
                 else
 
71
                     dump(_dd_pfx + _dd_currentIndent + str + " " +
 
72
                          sufx + "\n");
 
73
                 _dd_lastDumpWasOpen = false;
 
74
             } else {
 
75
                 if (_dd_currentDepth >= _dd_disableDepth)
 
76
                     return;
 
77
                 if (_dd_lastDumpWasOpen)
 
78
                     dump("\n");
 
79
                 dump(_dd_pfx + _dd_currentIndent + str + "\n");
 
80
                 _dd_lastDumpWasOpen = false;
 
81
             }    
 
82
         }
 
83
} else {
 
84
    dd = function (){};
 
85
}
 
86
 
 
87
var jsenv = new Object();
 
88
jsenv.HAS_SECURITYMANAGER = ((typeof netscape == "object") &&
 
89
                             (typeof netscape.security == "object"));
 
90
jsenv.HAS_XPCOM = ((typeof Components == "object") &&
 
91
                   (typeof Components.classes == "object"));
 
92
jsenv.HAS_JAVA = (typeof java == "object");
 
93
jsenv.HAS_RHINO = (typeof defineClass == "function");
 
94
jsenv.HAS_DOCUMENT = (typeof document == "object");
 
95
jsenv.HAS_NSPR_EVENTQ = jsenv.HAS_DOCUMENT;
 
96
jsenv.HAS_STREAM_PROVIDER = ("nsIStreamProvider" in Components.interfaces);
 
97
 
 
98
function dumpObject (o, pfx, sep)
 
99
{
 
100
    var p;
 
101
    var s = "";
 
102
 
 
103
    sep = (typeof sep == "undefined") ? " = " : sep;
 
104
    pfx = (typeof pfx == "undefined") ? "" : pfx;    
 
105
 
 
106
    for (p in o)
 
107
    {
 
108
        if (typeof (o[p]) != "function")
 
109
            s += pfx + p + sep + o[p] + "\n";
 
110
        else
 
111
            s += pfx + p + sep + "function\n";
 
112
    }
 
113
 
 
114
    return s;
 
115
 
 
116
}
 
117
 
 
118
/* Dumps an object in tree format, recurse specifiec the the number of objects
 
119
 * to recurse, compress is a boolean that can uncompress (true) the output
 
120
 * format, and level is the number of levels to intitialy indent (only useful
 
121
 * internally.)  A sample dumpObjectTree (o, 1) is shown below.
 
122
 *
 
123
 * + parent (object)
 
124
 * + users (object)
 
125
 * | + jsbot (object)
 
126
 * | + mrjs (object)
 
127
 * | + nakkezzzz (object)
 
128
 * | *
 
129
 * + bans (object)
 
130
 * | *
 
131
 * + topic (string) 'ircclient.js:59: nothing is not defined'
 
132
 * + getUsersLength (function) 9 lines
 
133
 * *
 
134
 */
 
135
function dumpObjectTree (o, recurse, compress, level)
 
136
{
 
137
    var s = "";
 
138
    var pfx = "";
 
139
 
 
140
    if (typeof recurse == "undefined")
 
141
        recurse = 0;
 
142
    if (typeof level == "undefined")
 
143
        level = 0;
 
144
    if (typeof compress == "undefined")
 
145
        compress = true;
 
146
    
 
147
    for (var i = 0; i < level; i++)
 
148
        pfx += (compress) ? "| " : "|  ";
 
149
 
 
150
    var tee = (compress) ? "+ " : "+- ";
 
151
 
 
152
    for (i in o)
 
153
    {
 
154
        var t, ex;
 
155
        
 
156
        try
 
157
        {
 
158
            t = typeof o[i];
 
159
        }
 
160
        catch (ex)
 
161
        {
 
162
            t = "ERROR";
 
163
        }
 
164
        
 
165
        switch (t)
 
166
        {
 
167
            case "function":
 
168
                var sfunc = String(o[i]).split("\n");
 
169
                if (sfunc[2] == "    [native code]")
 
170
                    sfunc = "[native code]";
 
171
                else
 
172
                    if (sfunc.length == 1)
 
173
                        sfunc = String(sfunc);
 
174
                    else
 
175
                        sfunc = sfunc.length + " lines";
 
176
                s += pfx + tee + i + " (function) " + sfunc + "\n";
 
177
                break;
 
178
 
 
179
            case "object":
 
180
                s += pfx + tee + i + " (object)";
 
181
                if (o[i] == null)
 
182
                {
 
183
                    s += " null\n";
 
184
                    break;
 
185
                }
 
186
                
 
187
                s += "\n";
 
188
                
 
189
                if (!compress)
 
190
                    s += pfx + "|\n";
 
191
                if ((i != "parent") && (recurse))
 
192
                    s += dumpObjectTree (o[i], recurse - 1,
 
193
                                         compress, level + 1);
 
194
                break;
 
195
 
 
196
            case "string":
 
197
                if (o[i].length > 200)
 
198
                    s += pfx + tee + i + " (" + t + ") " + 
 
199
                        o[i].length + " chars\n";
 
200
                else
 
201
                    s += pfx + tee + i + " (" + t + ") '" + o[i] + "'\n";
 
202
                break;
 
203
 
 
204
            case "ERROR":
 
205
                s += pfx + tee + i + " (" + t + ") ?\n";
 
206
                break;
 
207
                
 
208
            default:
 
209
                s += pfx + tee + i + " (" + t + ") " + o[i] + "\n";
 
210
                
 
211
        }
 
212
 
 
213
        if (!compress)
 
214
            s += pfx + "|\n";
 
215
 
 
216
    }
 
217
 
 
218
    s += pfx + "*\n";
 
219
    
 
220
    return s;
 
221
    
 
222
}
 
223
 
 
224
function ecmaEscape(str)
 
225
{
 
226
    function replaceNonPrintables(ch)
 
227
    {
 
228
        var rv = ch.charCodeAt().toString(16);
 
229
        if (rv.length == 1)
 
230
            rv = "0" + rv;
 
231
        else if (rv.length == 3)
 
232
            rv = "u0" + rv;
 
233
        else if (rv.length == 4)
 
234
            rv = "u" + rv;
 
235
      
 
236
        return "%" + rv;
 
237
    };
 
238
 
 
239
    // Replace any character that is not in the 69 character set
 
240
    // [ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@*_+-./]
 
241
    // with an escape sequence.  Two digit sequences in the form %XX are used
 
242
    // for characters whose codepoint is less than 255, %uXXXX for all others.
 
243
    // See section B.2.1 of ECMA-262 rev3 for more information.
 
244
    return str.replace(/[^A-Za-z0-9@*_+.\-\/]/g, replaceNonPrintables);
 
245
}
 
246
 
 
247
function ecmaUnescape(str)
 
248
{
 
249
    function replaceEscapes(seq)
 
250
    {
 
251
        var ary = seq.match(/([\da-f]{1,2})(.*)|u([\da-f]{1,4})/);
 
252
        if (!ary)
 
253
            return "<ERROR>";
 
254
 
 
255
        var rv;
 
256
        if (ary[1])
 
257
        {
 
258
            // two digit escape, possibly with cruft after
 
259
            rv = String.fromCharCode(parseInt(ary[1], 16)) + ary[2];
 
260
        }
 
261
        else
 
262
        {
 
263
            // four digits, no cruft
 
264
            rv = String.fromCharCode(parseInt(ary[3], 16));
 
265
        }
 
266
 
 
267
        return rv;
 
268
    };
 
269
 
 
270
    // Replace the escape sequences %X, %XX, %uX, %uXX, %uXXX, and %uXXXX with
 
271
    // the characters they represent, where X is a hexadecimal digit.
 
272
    // See section B.2.2 of ECMA-262 rev3 for more information.
 
273
    return str.replace(/%u?([\da-f]{1,4})/ig, replaceEscapes);
 
274
}
 
275
 
 
276
function replaceVars(str, vars)
 
277
{
 
278
    // replace "string $with a $variable", with
 
279
    // "string " + vars["with"] + " with a " + vars["variable"]
 
280
 
 
281
    function doReplace(symbol)
 
282
    {
 
283
        var name = symbol.substr(1);
 
284
        if (name in vars)
 
285
            return vars[name];
 
286
        
 
287
        return "$" + name;
 
288
    };
 
289
    
 
290
    return str.replace(/(\$\w[\w\d\-]+)/g, doReplace);
 
291
}
 
292
    
 
293
function formatException (ex)
 
294
{
 
295
    if (ex instanceof Error)
 
296
        return getMsg (MSG_FMT_JSEXCEPTION, [ex.name, ex.message, ex.fileName, 
 
297
                                             ex.lineNumber]);
 
298
 
 
299
    return String(ex);
 
300
}
 
301
 
 
302
/*
 
303
 * Clones an existing object (Only the enumerable properties
 
304
 * of course.) use as a function..
 
305
 * var c = Clone (obj);
 
306
 * or a constructor...
 
307
 * var c = new Clone (obj);
 
308
 */
 
309
function Clone (obj)
 
310
{
 
311
    var robj = new Object();
 
312
 
 
313
    for (var p in obj)
 
314
        robj[p] = obj[p];
 
315
 
 
316
    return robj;
 
317
    
 
318
}
 
319
 
 
320
function Copy(source, dest, overwrite)
 
321
{
 
322
    if (!dest)
 
323
        dest = new Object();
 
324
    
 
325
    for (var p in source)
 
326
    {
 
327
        if (overwrite || !(p in dest))
 
328
            dest[p] = source[p];
 
329
    }
 
330
    
 
331
    return dest;
 
332
}
 
333
 
 
334
/*
 
335
 * matches a real object against one or more pattern objects.
 
336
 * if you pass an array of pattern objects, |negate| controls wether to check
 
337
 * if the object matches ANY of the patterns, or NONE of the patterns.
 
338
 */
 
339
function matchObject (o, pattern, negate)
 
340
{
 
341
    negate = Boolean(negate);
 
342
    
 
343
    function _match (o, pattern)
 
344
    {
 
345
        if (pattern instanceof Function)
 
346
            return pattern(o);
 
347
        
 
348
        for (p in pattern)
 
349
        {
 
350
            var val;
 
351
                /* nice to have, but slow as molases, allows you to match
 
352
                 * properties of objects with obj$prop: "foo" syntax      */
 
353
                /*
 
354
                  if (p[0] == "$")
 
355
                  val = eval ("o." + 
 
356
                  p.substr(1,p.length).replace (/\$/g, "."));
 
357
                  else
 
358
                */
 
359
            val = o[p];
 
360
            
 
361
            if (pattern[p] instanceof Function)
 
362
            {
 
363
                if (!pattern[p](val))
 
364
                    return false;
 
365
            }
 
366
            else
 
367
            {
 
368
                var ary = (new String(val)).match(pattern[p]);
 
369
                if (ary == null)
 
370
                    return false;
 
371
                else
 
372
                    o.matchresult = ary;
 
373
            }
 
374
        }
 
375
 
 
376
        return true;
 
377
 
 
378
    }
 
379
 
 
380
    if (!(pattern instanceof Array))
 
381
        return Boolean (negate ^ _match(o, pattern));
 
382
            
 
383
    for (var i in pattern)
 
384
        if (_match (o, pattern[i]))
 
385
            return !negate;
 
386
 
 
387
    return negate;
 
388
    
 
389
}
 
390
 
 
391
function matchEntry (partialName, list)
 
392
{
 
393
    
 
394
    if ((typeof partialName == "undefined") ||
 
395
        (String(partialName) == ""))
 
396
        return list;
 
397
 
 
398
    var ary = new Array();
 
399
 
 
400
    for (var i in list)
 
401
    {
 
402
        if (list[i].indexOf(partialName) == 0)
 
403
            ary.push (list[i]);
 
404
    }
 
405
 
 
406
    return ary;
 
407
    
 
408
}
 
409
 
 
410
function encodeChar(ch)
 
411
{
 
412
   return "%" + ch.charCodeAt(0).toString(16);
 
413
}
 
414
 
 
415
function escapeFileName(fileName)
 
416
{
 
417
    return fileName.replace(/[^\w\d.,#\-_]/g, encodeChar);
 
418
}
 
419
 
 
420
function getCommonPfx (list)
 
421
{
 
422
    var pfx = list[0];
 
423
    var l = list.length;
 
424
    
 
425
    for (var i = 0; i < l; i++)
 
426
    {
 
427
        for (var c = 0; c < pfx.length; ++c)
 
428
        {
 
429
            if (c >= list[i].length)
 
430
            {
 
431
                pfx = pfx.substr (0, c);
 
432
                break;
 
433
            }
 
434
            else
 
435
            {
 
436
                if (pfx[c] != list[i][c])
 
437
                    pfx = pfx.substr (0, c);
 
438
            }
 
439
        }
 
440
    }
 
441
 
 
442
    return pfx;
 
443
 
 
444
}
 
445
 
 
446
function openTopWin (url)
 
447
{
 
448
    return openDialog (getBrowserURL(), "_blank", "chrome,all,dialog=no", url);
 
449
}
 
450
    
 
451
function getWindowByType (windowType)
 
452
{
 
453
    const MEDIATOR_CONTRACTID =
 
454
        "@mozilla.org/appshell/window-mediator;1";
 
455
    const nsIWindowMediator  = Components.interfaces.nsIWindowMediator;
 
456
 
 
457
    var windowManager =
 
458
        Components.classes[MEDIATOR_CONTRACTID].getService(nsIWindowMediator);
 
459
 
 
460
    return windowManager.getMostRecentWindow(windowType);
 
461
}
 
462
 
 
463
function renameProperty (obj, oldname, newname)
 
464
{
 
465
 
 
466
    if (oldname == newname)
 
467
        return;
 
468
    
 
469
    obj[newname] = obj[oldname];
 
470
    delete obj[oldname];
 
471
    
 
472
}
 
473
 
 
474
function newObject(contractID, iface)
 
475
{
 
476
    if (!jsenv.HAS_XPCOM)
 
477
        return null;
 
478
 
 
479
    var obj = Components.classes[contractID].createInstance();
 
480
    var rv;
 
481
 
 
482
    switch (typeof iface)
 
483
    {
 
484
        case "string":
 
485
            rv = obj.QueryInterface(Components.interfaces[iface]);
 
486
            break;
 
487
 
 
488
        case "object":
 
489
            rv = obj.QueryInterface[iface];
 
490
            break;
 
491
 
 
492
        default:
 
493
            rv = null;
 
494
            break;
 
495
    }
 
496
 
 
497
    return rv;
 
498
    
 
499
}
 
500
 
 
501
function getContentWindow(frame)
 
502
{
 
503
    try
 
504
    {
 
505
        if (!frame || !("contentWindow" in frame))
 
506
            return false;
 
507
 
 
508
        return frame.contentWindow;
 
509
    }
 
510
    catch (ex)
 
511
    {
 
512
        // throws exception is contentWindow is gone
 
513
        return null;
 
514
    }
 
515
}
 
516
 
 
517
function getPriv (priv)
 
518
{
 
519
    if (!jsenv.HAS_SECURITYMANAGER)
 
520
        return true;
 
521
 
 
522
    var rv = true;
 
523
 
 
524
    try
 
525
    {
 
526
        netscape.security.PrivilegeManager.enablePrivilege(priv);
 
527
    }
 
528
    catch (e)
 
529
    {
 
530
        dd ("getPriv: unable to get privlege '" + priv + "': " + e);
 
531
        rv = false;
 
532
    }
 
533
    
 
534
    return rv;
 
535
    
 
536
}
 
537
 
 
538
function len(o)
 
539
{
 
540
    var l = 0;
 
541
    
 
542
    for (var p in o)
 
543
        ++l;
 
544
    
 
545
    return l;
 
546
}
 
547
 
 
548
function keys (o)
 
549
{
 
550
    var rv = new Array();
 
551
    
 
552
    for (var p in o)
 
553
        rv.push(p);
 
554
 
 
555
    return rv;
 
556
    
 
557
}
 
558
 
 
559
function stringTrim (s)
 
560
{
 
561
    if (!s)
 
562
        return "";
 
563
    s = s.replace (/^\s+/, "");
 
564
    return s.replace (/\s+$/, "");
 
565
    
 
566
}
 
567
 
 
568
/* the offset should be in seconds, it will be rounded to 2 decimal places */
 
569
function formatDateOffset (offset, format)
 
570
{
 
571
    var seconds = roundTo(offset % 60, 2);
 
572
    var minutes = Math.floor(offset / 60);
 
573
    var hours = Math.floor(minutes / 60);
 
574
    minutes = minutes % 60;
 
575
    var days = Math.floor(hours / 24);
 
576
    hours = hours % 24;
 
577
 
 
578
    if (!format)
 
579
    {
 
580
        var ary = new Array();
 
581
        if (days > 0)
 
582
            ary.push (getMsg(MSG_DAYS, days));
 
583
        if (hours > 0)
 
584
            ary.push (getMsg(MSG_HOURS, hours));
 
585
        if (minutes > 0)
 
586
            ary.push (getMsg(MSG_MINUTES, minutes));
 
587
        if (seconds > 0 || offset == 0)
 
588
            ary.push (getMsg(MSG_SECONDS, seconds));
 
589
 
 
590
        format = ary.join(", ");
 
591
    }
 
592
    else
 
593
    {
 
594
        format = format.replace ("%d", days);
 
595
        format = format.replace ("%h", hours);
 
596
        format = format.replace ("%m", minutes);
 
597
        format = format.replace ("%s", seconds);
 
598
    }
 
599
    
 
600
    return format;
 
601
}
 
602
 
 
603
function arrayHasElementAt(ary, i)
 
604
{
 
605
    return typeof ary[i] != "undefined";
 
606
}
 
607
 
 
608
function arrayContains (ary, elem)
 
609
{
 
610
    return (arrayIndexOf (ary, elem) != -1);
 
611
}
 
612
 
 
613
function arrayIndexOf (ary, elem)
 
614
{
 
615
    for (var i in ary)
 
616
        if (ary[i] == elem)
 
617
            return i;
 
618
 
 
619
    return -1;
 
620
}
 
621
    
 
622
function arrayInsertAt (ary, i, o)
 
623
{
 
624
    ary.splice (i, 0, o);
 
625
}
 
626
 
 
627
function arrayRemoveAt (ary, i)
 
628
{
 
629
    ary.splice (i, 1);
 
630
}
 
631
 
 
632
/* length should be an even number >= 6 */
 
633
function abbreviateWord (str, length)
 
634
{
 
635
    if (str.length <= length || length < 6)
 
636
        return str;
 
637
 
 
638
    var left = str.substr (0, (length / 2) - 1);
 
639
    var right = str.substr (str.length - (length / 2) + 1);
 
640
 
 
641
    return left + "..." + right;
 
642
}
 
643
 
 
644
/*
 
645
 * Inserts the string |hyphen| into string |str| every |pos| characters.
 
646
 * If there are any wordbreaking characters in |str| within -/+5 characters of
 
647
 * of a |pos| then the hyphen is inserted there instead, in order to produce a
 
648
 * "cleaner" break.
 
649
 */
 
650
function hyphenateWord (str, pos, hyphen)
 
651
{
 
652
    if (str.length <= pos)
 
653
        return str;
 
654
    if (typeof hyphen == "undefined")
 
655
        hyphen = " ";
 
656
 
 
657
    /* search for a nice place to break the word, fuzzfactor of +/-5, centered
 
658
     * around |pos| */
 
659
    var splitPos =
 
660
        str.substring(pos - 5, pos + 5).search(/[^A-Za-z0-9]/);
 
661
 
 
662
    splitPos = (splitPos != -1) ? pos - 4 + splitPos : pos;
 
663
    var left = str.substr (0, splitPos);
 
664
    var right = hyphenateWord(str.substr (splitPos), pos, hyphen);
 
665
 
 
666
    return left + hyphen + right;
 
667
}
 
668
 
 
669
/*
 
670
 * Like hyphenateWord, except individual chunks of the word are returned as
 
671
 * elements of an array.
 
672
 */
 
673
function splitLongWord (str, pos)
 
674
{
 
675
    if (str.length <= pos)
 
676
        return [str];
 
677
 
 
678
    var ary = new Array();
 
679
    var right = str;
 
680
    
 
681
    while (right.length > pos)
 
682
    {
 
683
        /* search for a nice place to break the word, fuzzfactor of +/-5, 
 
684
         * centered around |pos| */
 
685
        var splitPos =
 
686
            right.substring(pos - 5, pos + 5).search(/[^A-Za-z0-9]/);
 
687
 
 
688
        splitPos = (splitPos != -1) ? pos - 4 + splitPos : pos;
 
689
        ary.push(right.substr (0, splitPos));
 
690
        right = right.substr (splitPos);
 
691
    }
 
692
 
 
693
    ary.push (right);
 
694
 
 
695
    return ary;
 
696
}
 
697
 
 
698
function getRandomElement (ary)
 
699
{
 
700
 
 
701
    return ary[Math.floor(Math.random() * ary.length)];
 
702
 
 
703
}
 
704
 
 
705
function roundTo (num, prec)
 
706
{
 
707
 
 
708
    return Math.round(num * Math.pow (10, prec)) / Math.pow (10, prec);   
 
709
 
 
710
}
 
711
 
 
712
function randomRange (min, max)
 
713
{
 
714
 
 
715
    if (typeof min == "undefined")
 
716
        min = 0;
 
717
 
 
718
    if (typeof max == "undefined")
 
719
        max = 1;
 
720
 
 
721
    return Math.floor(Math.random() * (max - min + 1)) + min;
 
722
 
 
723
}
 
724
 
 
725
function getStackTrace ()
 
726
{
 
727
 
 
728
    if (!jsenv.HAS_XPCOM)
 
729
        return "No stack trace available.";
 
730
 
 
731
    var frame = Components.stack.caller;
 
732
    var str = "<top>";
 
733
 
 
734
    while (frame)
 
735
    {
 
736
        var name = frame.name ? frame.name : "[anonymous]";
 
737
        str += "\n" + name + "@" + frame.lineNumber;
 
738
        frame = frame.caller;
 
739
    }
 
740
 
 
741
    return str;
 
742
    
 
743
}
 
744
 
 
745
function getInterfaces (cls)
 
746
{
 
747
    if (!jsenv.HAS_XPCOM)
 
748
        return null;
 
749
 
 
750
    var rv = new Object();
 
751
    var e;
 
752
 
 
753
    for (var i in Components.interfaces)
 
754
    {
 
755
        try
 
756
        {
 
757
            var ifc = Components.interfaces[i];
 
758
            cls.QueryInterface(ifc);
 
759
            rv[i] = ifc;
 
760
        }
 
761
        catch (e)
 
762
        {
 
763
            /* nada */
 
764
        }
 
765
    }
 
766
 
 
767
    return rv;
 
768
    
 
769
}
 
770
 
 
771
/**
 
772
 * Calls a named function for each element in an array, sending
 
773
 * the same parameter each call.
 
774
 *
 
775
 * @param ary           an array of objects
 
776
 * @param func_name     string name of function to call.
 
777
 * @param data          data object to pass to each object.
 
778
 */      
 
779
function mapObjFunc(ary, func_name, data)
 
780
{
 
781
    /* 
 
782
     * WARNING: Caller assumes resonsibility to verify ary
 
783
     * and func_name
 
784
     */
 
785
 
 
786
    for (var i in ary)
 
787
        ary[i][func_name](data);
 
788
}
 
789
 
 
790
/**
 
791
 * Passes each element of an array to a given function object.
 
792
 *
 
793
 * @param func  a function object.
 
794
 * @param ary   an array of values.
 
795
 */
 
796
function map(func, ary) {
 
797
 
 
798
    /*
 
799
     * WARNING: Caller assumnes responsibility to verify
 
800
     * func and ary.
 
801
     */
 
802
 
 
803
    for (var i in ary)
 
804
        func(ary[i]);
 
805
 
 
806
}
 
807
 
 
808
function getSpecialDirectory(name)
 
809
{
 
810
    if (!("directoryService" in utils))
 
811
    {
 
812
        const DS_CTR = "@mozilla.org/file/directory_service;1";
 
813
        const nsIProperties = Components.interfaces.nsIProperties;
 
814
 
 
815
        utils.directoryService =
 
816
            Components.classes[DS_CTR].getService(nsIProperties);
 
817
    }
 
818
 
 
819
    return utils.directoryService.get(name, Components.interfaces.nsIFile);
 
820
}
 
821
 
 
822
function getFileFromURLSpec(url)
 
823
{
 
824
    const FILE_CTRID = "@mozilla.org/network/protocol;1?name=file";
 
825
    const nsIFileProtocolHandler = Components.interfaces.nsIFileProtocolHandler;
 
826
    
 
827
    var handler = Components.classes[FILE_CTRID].createInstance();
 
828
    handler = handler.QueryInterface(nsIFileProtocolHandler);
 
829
    return handler.getFileFromURLSpec(url);
 
830
}
 
831
 
 
832
function getURLSpecFromFile (file)
 
833
{
 
834
    if (!file)
 
835
        return null;
 
836
 
 
837
    const IOS_CTRID = "@mozilla.org/network/io-service;1";
 
838
    const LOCALFILE_CTRID = "@mozilla.org/file/local;1";
 
839
 
 
840
    const nsIIOService = Components.interfaces.nsIIOService;
 
841
    const nsILocalFile = Components.interfaces.nsILocalFile;
 
842
    
 
843
    if (typeof file == "string")
 
844
    {
 
845
        var fileObj =
 
846
            Components.classes[LOCALFILE_CTRID].createInstance(nsILocalFile);
 
847
        fileObj.initWithPath(file);
 
848
        file = fileObj;
 
849
    }
 
850
    
 
851
    var service = Components.classes[IOS_CTRID].getService(nsIIOService);
 
852
    /* In sept 2002, bug 166792 moved this method to the nsIFileProtocolHandler
 
853
     * interface, but we need to support older versions too. */
 
854
    if ("getURLSpecFromFile" in service)
 
855
        return service.getURLSpecFromFile(file);
 
856
 
 
857
    var nsIFileProtocolHandler = Components.interfaces.nsIFileProtocolHandler;
 
858
    var fileHandler = service.getProtocolHandler("file");
 
859
    fileHandler = fileHandler.QueryInterface(nsIFileProtocolHandler);
 
860
    return fileHandler.getURLSpecFromFile(file);
 
861
}
 
862
 
 
863
function alert(msg, parent, title)
 
864
{
 
865
    var PROMPT_CTRID = "@mozilla.org/embedcomp/prompt-service;1";
 
866
    var nsIPromptService = Components.interfaces.nsIPromptService;
 
867
    var ps = Components.classes[PROMPT_CTRID].getService(nsIPromptService);
 
868
    if (!parent)
 
869
        parent = window;
 
870
    if (!title)
 
871
        title = MSG_ALERT;
 
872
    ps.alert (parent, title, msg);
 
873
}
 
874
 
 
875
function confirm(msg, parent, title)
 
876
{
 
877
    var PROMPT_CTRID = "@mozilla.org/embedcomp/prompt-service;1";
 
878
    var nsIPromptService = Components.interfaces.nsIPromptService;
 
879
    var ps = Components.classes[PROMPT_CTRID].getService(nsIPromptService);
 
880
    if (!parent)
 
881
        parent = window;
 
882
    if (!title)
 
883
        title = MSG_CONFIRM;
 
884
    return ps.confirm (parent, title, msg);
 
885
}
 
886
 
 
887
function prompt(msg, initial, parent, title)
 
888
{
 
889
    var PROMPT_CTRID = "@mozilla.org/embedcomp/prompt-service;1";
 
890
    var nsIPromptService = Components.interfaces.nsIPromptService;
 
891
    var ps = Components.classes[PROMPT_CTRID].getService(nsIPromptService);
 
892
    if (!parent)
 
893
        parent = window;
 
894
    if (!title)
 
895
        title = MSG_PROMPT;
 
896
    rv = { value: initial };
 
897
 
 
898
    if (!ps.prompt (parent, title, msg, rv, null, {value: null}))
 
899
        return null;
 
900
 
 
901
    return rv.value;
 
902
}
 
903
 
 
904
function promptPassword(msg, initial, parent, title)
 
905
{
 
906
    var PROMPT_CTRID = "@mozilla.org/embedcomp/prompt-service;1";
 
907
    var nsIPromptService = Components.interfaces.nsIPromptService;
 
908
    var ps = Components.classes[PROMPT_CTRID].getService(nsIPromptService);
 
909
    if (!parent)
 
910
        parent = window;
 
911
    if (!title)
 
912
        title = MSG_PROMPT;
 
913
    rv = { value: initial };
 
914
 
 
915
    if (!ps.promptPassword (parent, title, msg, rv, null, {value: null}))
 
916
        return null;
 
917
 
 
918
    return rv.value;
 
919
}
 
920
 
 
921
function getHostmaskParts(hostmask)
 
922
{
 
923
    var rv;
 
924
    // A bit cheeky this, we try the matches here, and then branch
 
925
    // according to the ones we like.
 
926
    var ary1 = hostmask.match(/(\S*)!(\S*)@(.*)/);
 
927
    var ary2 = hostmask.match(/(\S*)@(.*)/);
 
928
    var ary3 = hostmask.match(/(\S*)!(.*)/);
 
929
    if (ary1)
 
930
        rv = { nick: ary1[1],  user: ary1[2], host: ary1[3] };
 
931
    else if (ary2)
 
932
        rv = { nick: "*",      user: ary2[1], host: ary2[2] };
 
933
    else if (ary3)
 
934
        rv = { nick: ary3[1],  user: ary3[2], host: "*"     };
 
935
    else
 
936
        rv = { nick: hostmask, user: "*",     host: "*"     };
 
937
    // Make sure we got something for all fields.
 
938
    if (!rv.nick)
 
939
        rv.nick = "*";
 
940
    if (!rv.user)
 
941
        rv.user = "*";
 
942
    if (!rv.host)
 
943
        rv.host = "*";
 
944
    // And re-construct the 'parsed' hostmask.
 
945
    rv.mask = rv.nick + "!" + rv.user + "@" + rv.host;
 
946
    return rv;
 
947
}