// Phorum object. Other JavaScript code for Phorum can extend
// this one to implement functionality without risking name
// name space collissions.
Phorum = {};

/* Added by module "core", file "include/ajax/client.js.php" */
// Create the Phorum object if it's not available. It it created in the
// core javascript.php, but when loading this code from an external
// page, it might not be available.
if (!document.Phorum || Phorum == undefined) Phorum = {};

Phorum.Ajax = {};

// The version of this lib
Phorum.Ajax.version = '1.0.0';

// The URL that we use to access the Phorum Ajax layer.
Phorum.Ajax.URL = 'http://argentina.pivianforum.com/ajax/';

// Storage for Ajax call return data. This acts as a local cache
// for keeping track of already retrieved items.
Phorum.Ajax.cache = {};

/**
 * Create an XMLHttpRequest object.
 * Used internally by Phorum.Ajax.call().
 * Raise an onFailure event in case no object can be created.
 * Return either an object or null if the object creation failed.
 */
Phorum.Ajax.getXMLHttpRequest = function(req)
{
    var xhr;
    if (window.XMLHttpRequest) {
        xhr = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
        var versions = [
            'MSXML2.XMLHttp.5.0',
            'MSXML2.XMLHttp.4.0',
            'MSXML2.XMLHttp.3.0',
            'MSXML2.XMLHttp',
            'Microsoft.XMLHttp'
        ];
        for (var i=0; i < versions.length; i++) {
            try { xhr = new ActiveXObject(versions[i]); } catch (e) { }
        }
    }

    if (xhr) {
        return xhr;
    }

    if (req.onFailure) req.onFailure(
        'Phorum: Unable to create an XMLHttpRequest object',
        -1, null
    );
    return null;
};

/**
 * Execute an Ajax Phorum call.
 */
Phorum.Ajax.call = function(req)
{
    // If the store property is set for the request, then check
    // if the data for the request is already available in the
    // local cache. If yes, then return the data immediately.
    if (req.store) {
        if (req.store != null && Phorum.Ajax.cache[req.store]) {
            if (req.onSuccess) {
                // true = data retrieved from cache.
                req.onSuccess(Phorum.Ajax.cache[req.store], true);
            }
            return;
        }
    }

    // Check the request data.
    if (! req['call']) {
        if (req.onFailure) req.onFailure(
            'Phorum.Ajax.call() error: missing property ' +
            '"call" for the request object.',
            -1, null
        );
        return;
    }

    // Check if there is an XMLHttpRequest object available.
    var xhr = Phorum.Ajax.getXMLHttpRequest(req);
    if (! xhr) return;

    // Convert the request object to JSON.
    var json = Phorum.JSON.encode(req);

    // Notify the start of the request loading stage.
    if (req.onRequest) req.onRequest(json);

    xhr.open("post", Phorum.Ajax.URL, true);
    xhr.setRequestHeader("Content-Type", "text/x-json");
    xhr.onreadystatechange = function()
    {
      if (req.onReadStateChange) req.onReadyStateChange(req);

      switch (xhr.readyState)
      {
          case 1:

              if (req.onLoading) req.onLoading(xhr);
              break;

          case 2:

              if (req.onLoaded) req.onLoaded(xhr);
              break;

          case 3:

              if (req.onInteractive) req.onInteractive(xhr);
              break;

          case 4:

              if (req.onComplete)req.onComplete(xhr);

              if (req.onResponse) req.onResponse(xhr.responseText);

              if (xhr.status == 200) {

                  // Evaluate the returned JSON code. If evaluation fails,
                  // then run the onFailure event for the Phorum.Ajax.call.
                  try {
                      var res = Phorum.JSON.decode(xhr.responseText);
                  } catch (e) {
                      if (req.onFailure) req.onFailure(
                        'Ajax Phorum API call succeeded, but the return ' +
                        'data could not be parsed as JSON data.',
                        xhr.status, xhr.responseText
                      );
                      return;
                  }

                  // If the req.store property is set, then we store
                  // the result data in the Phorum cache.
                  if (req.store) Phorum.Ajax.cache[req.store] = res;

                  // false = data not retrieved from store.
                  if (req.onSuccess) req.onSuccess(res, false);

              } else {

                  if (req.onFailure) req.onFailure(xhr.responseText);
              }

              break;
      }
    };
    xhr.send(json);
};

// Invalidate a single cache item of the full cache.
Phorum.Ajax.invalidateCache = function(key)
{
    if (key) {
        Phorum.Ajax.cache[key] = null;
    } else {
        Phorum.Ajax.cache = new Array();
    }
};

// Parse out javascript blocks from the data to eval them. Adding them
// to the page using innerHTML does not invoke parsing by the browser.
Phorum.Ajax.evalJavaScript = function(data)
{
    var cursor = 0;
    var start  = 1;
    var end    = 1;

    while (cursor < data.length && start > 0 && end > 0) {
        start = data.indexOf('<script', cursor);
        end   = data.indexOf('</script', cursor);
        if (end > start && end > -1) {
            if (start > -1) {
                var res = data.substring(start, end);
                start = res.indexOf('>') + 1;
                res = res.substring(start);
                if (res.length != 0) {
                    eval(res);
                }
            }
            cursor = end + 1;
        }
    }
};

// ======================================================================
// JSON encoder and decoder
// Based on byteson by Andrea Giammarchi
// (http://www.devpro.it/byteson/)
// ======================================================================

Phorum.JSON = {};

Phorum.JSON.common =
{
  // characters object, useful to convert some char in a JSON compatible way
  c:{'\b':'b','\t':'t','\n':'n','\f':'f','\r':'r','"':'"','\\':'\\','/':'/'},

  // decimal function, returns a string with length === 2 for date convertion
  d:function(n){return n < 10 ? '0'.concat(n) : n},

  // integer function, returns integer value from a piece of string
  i:function(e, p, l){return parseInt(e.substr(p, l))},

  // slash function, add a slash before a common.c char
  s:function(i,d){return '\\'.concat(Phorum.JSON.common.c[d])},

  // unicode function, return respective unicode string
  u:function(i,d){var n = d.charCodeAt(0).toString(16);return '\\u'.concat(n.length < 2 ? '000' : '00', n)}
};

Phorum.JSON.convert = function(params, result)
{
    switch(params.constructor) {
        case Number:
            result = isFinite(params) ? String(params) : 'null';
            break;
        case Boolean:
            result = String(params);
            break;
        case Date:
            result = concat(
                '"',
                params.getFullYear(), '-',
                Phorum.JSON.common.d(params.getMonth() + 1), '-',
                Phorum.JSON.common.d(params.getDate()), 'T',
                Phorum.JSON.common.d(params.getHours()), ':',
                Phorum.JSON.common.d(params.getMinutes()), ':',
                Phorum.JSON.common.d(params.getSeconds()),
                '"'
            );
            break;
        case String:
            if(/^[0-9]{4}\-[0-9]{2}\-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}$/.test(params)){
                result = new Date;
                result.setHours(Phorum.JSON.common.i(params, 11, 2));
                result.setMinutes(Phorum.JSON.common.i(params, 14, 2));
                result.setSeconds(Phorum.JSON.common.i(params, 17, 2));
                result.setMonth(Phorum.JSON.common.i(params, 5, 2) - 1);
                result.setDate(Phorum.JSON.common.i(params, 9, 2));
                result.setFullYear(Phorum.JSON.common.i(params, 0, 4));
            };
            break;
        default:
            var n, tmp = [];
            if(result) {
                for(n in params) result[n] = params[n];
            } else {
                for(n in params) {
                    if(params.hasOwnProperty(n) && !!(result = Phorum.JSON.encode(params[n])))
                        tmp.push(Phorum.JSON.encode(n).concat(':', result));
                };
                result = '{'.concat(tmp.join(','), '}');
            };
            break;
    };
    return result;
};

Phorum.JSON.encode = function(params)
{
    var result = '';

    if(params === null)
    {
        result = 'null';
    }
    else if(!{'function':1,'undefined':1,'unknown':1}[typeof(params)])
    {
        switch(params.constructor)
        {
            case Array:
                for(var i = 0, j = params.length, tmp = []; i < j; i++) {
                    if(!!(result = Phorum.JSON.encode(params[i])))
                        tmp.push(result);
                };
                result = '['.concat(tmp.join(','), ']');
                break;

            case String:
                result = '"'.concat(params.replace(
                        /(\x5c|\x2F|\x22|[\x0c-\x0d]|[\x08-\x0a])/g, Phorum.JSON.common.s
                    ).replace(
                        /([\x00-\x07]|\x0b|[\x0e-\x1f])/g, Phorum.JSON.common.u
                    ), '"');
                break;

            default:
                result = Phorum.JSON.convert(params);
                break;
        };
    };
    return result;
};

Phorum.JSON.decode = function(json)
{
    eval('var res = '+json);
    if (res === undefined) {
        throw new SyntaxError('The Phorum JSON data cannot be parsed');
    }
    return res;
};



/* Added by module "editor_tools", file "mods/editor_tools/editor_tools.js" */
///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// Copyright (C) 2008  Phorum Development Team                               //
// http://www.phorum.org                                                     //
//                                                                           //
// This program is free software. You can redistribute it and/or modify      //
// it under the terms of either the current Phorum License (viewable at      //
// phorum.org) or the Phorum License that was distributed with this file     //
//                                                                           //
// This program is distributed in the hope that it will be useful,           //
// but WITHOUT ANY WARRANTY, without even the implied warranty of            //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                      //
//                                                                           //
// You should have received a copy of the Phorum License                     //
// along with this program.                                                  //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

// Javascript code for the Phorum editor_tools module.

// Valid object ids for textarea objects to handle. The first object
// that can be matched will be use as the object to work with.
// This is done to arrange for backward compatibility between
// Phorum versions.
var editor_tools_textarea_ids = new Array(
    'phorum_textarea',  // Phorum 5.1
    'body',             // Phorum 5.2
    'message'           // PM interface
);

// Valid object ids for subject text field objects to handle.
var editor_tools_subject_ids = new Array(
    'phorum_subject',   // Phorum 5.1
    'subject'           // Phorum 5.2
);

// Storage for language translation strings from the Phorum language system.
var editor_tools_lang = new Array();

// Some variables for storing objects that we need globally.
var editor_tools_textarea_obj = null;
var editor_tools_subject_obj = null;
var editor_tools_help_picker_obj = null;

// A variable for storing the current selection range of the 
// textarea. Needed for working around an MSIE problem.
var editor_tools_textarea_range = null;

// A variable for storing all popup objects that we have, so we
// can hide them all at once.
var editor_tools_popup_objects = new Array();

// Storage for the tools that have to be added to the editor tools panel.
// The array value contains the following fields:
//
// 1) the id for the tool (must be unique)
// 2) a description to use as the tooltip title for the button
// 3) the icon image to display as a button.
// 4) the javascript action to run when the user clicks the button
// 5) optional: the width of the icon image
// 6) optional: the height of the icon image (presumed 20px by default)
//
// This array will be filled from PHP-generated javascript.
var editor_tools = new Array();

// Storage for help chapters that must be put under the editor tools
// help button. The array value contains the following fields:
//
// 1) a description that will be used as the clickable link text.
// 2) the url for the help page (absolute or relative to the Phorum dir).
//
// This array will be filled from PHP-generated javascript.
var editor_tools_help_chapters = new Array();

// The dimensions of the help window.
var editor_tools_help_width = '400px';
var editor_tools_help_height = '400px';

// The default height for our icons.
// This one is filled from PHP-generated javascript.
var editor_tools_default_iconheight;

// A simple browser check. We need to know the browser version, because
// the color picker won't work on at least MacOS MSIE 5.
var OLD_MSIE =
    navigator.userAgent.indexOf('MSIE')>=0 &&
    navigator.appVersion.replace(/.*MSIE (\d\.\d).*/g,'$1')/1 < 6;

// ----------------------------------------------------------------------
// Uitilty functions
// ----------------------------------------------------------------------

// Find the Phorum textarea object and return it. In case of
// problems, null will be returned.
function editor_tools_get_textarea()
{
    if (editor_tools_textarea_obj != null) {
        return editor_tools_textarea_obj;
    }

    for (var i=0; editor_tools_textarea_ids[i]; i++) {
        editor_tools_textarea_obj =
            document.getElementById(editor_tools_textarea_ids[i]);
        if (editor_tools_textarea_obj) break;
    }

    if (! editor_tools_textarea_obj) {
        alert('editor_tools.js library reports: ' +
              'no textarea found on the current page.');
        return null;
    }

    return editor_tools_textarea_obj;
}

// Find the Phorum subject field object and return it. In case of
// problems, null will be returned.
function editor_tools_get_subjectfield()
{
    if (editor_tools_subject_obj != null) {
        return editor_tools_subject_obj;
    }

    for (var i=0; editor_tools_subject_ids[i]; i++) {
        editor_tools_subject_obj =
            document.getElementById(editor_tools_subject_ids[i]);
        if (editor_tools_subject_obj) break;
    }

    if (! editor_tools_subject_obj) {
        return null;
    }

    return editor_tools_subject_obj;
}

// Return a translated string, based on the Phorum language system.
function editor_tools_translate(str)
{
    if (editor_tools_lang[str]) {
        return editor_tools_lang[str];
    } else {
        return str;
    }
}

// Strip whitespace from the start and end of a string.
function editor_tools_strip_whitespace(str, return_stripped)
{
    var strip_pre = '';
    var strip_post = '';

    // Strip whitespace from end of string.
    for (;;) {
        var lastchar = str.substring(str.length-1, str.length);
        if (lastchar == ' '  || lastchar == '\r' ||
            lastchar == '\n' || lastchar == '\t') {
            strip_post = lastchar + strip_post;

            str = str.substring(0, str.length-1);
        } else {
            break;
        }
    }

    // Strip whitespace from start of string.
    for (;;) {
        var firstchar = str.substring(0,1);
        if (firstchar == ' '  || firstchar == '\r' ||
            firstchar == '\n' || firstchar == '\t') {
            strip_pre += firstchar;
            str = str.substring(1);
        } else {
            break;
        }
    }

    if (return_stripped) {
        return new Array(str, strip_pre, strip_post);
    } else {
        return str;
    }
} 

// Close all popup windows and move the focus to the textarea.
function editor_tools_focus_textarea()
{
    var textarea_obj = editor_tools_get_textarea();
    if (textarea_obj == null) return;
    editor_tools_hide_all_popups();
    textarea_obj.focus();
}

// Close all popup windows and move the focus to the subject field.
function editor_tools_focus_subjectfield()
{
    var subjectfield_obj = editor_tools_get_subjectfield();
    if (subjectfield_obj == null) return;
    editor_tools_hide_all_popups();
    subjectfield_obj.focus();
}

// ----------------------------------------------------------------------
// Construction of the editor tools
// ----------------------------------------------------------------------

// Add the editor tools panel to the page.
function editor_tools_construct()
{
    var textarea_obj;
    var div_obj;
    var parent_obj;
    var a_obj;
    var img_obj;

    // If the browser does not support document.getElementById,
    // then the javascript code won't run. Do not display the
    // editor tools at all in that case.
    if (! document.getElementById) return;

    // No editor tools selected to display? Then we're done.
    if (editor_tools.length == 0) return;

    // Find the textarea and subject field object.
    textarea_obj = editor_tools_get_textarea();
    if (textarea_obj == null) return; // we consider this fatal.
    var subjectfield_obj = editor_tools_get_subjectfield();

    // Insert a <div> for containing the buttons, just before the textarea,
    // unless there is already an object with id "editor-tools". In that
    // case, the existing object is used instead.
    div_obj = document.getElementById('editor-tools');
    if (! div_obj) {
        parent_obj = textarea_obj.parentNode;
        div_obj = document.createElement('div');
        div_obj.id = 'editor-tools';
        parent_obj.insertBefore(div_obj, textarea_obj);
    }

    // Add the buttons to the new <div> for the editor tools.
    for (var i = 0; i < editor_tools.length; i++)
    {
        var toolinfo    = editor_tools[i];
        var tool        = toolinfo[0];
        var description = toolinfo[1];
        var icon        = toolinfo[2];
        var jsaction    = toolinfo[3];
        var iwidth      = toolinfo[4];
        var iheight     = toolinfo[5];
        var target      = toolinfo[6];

        // Do not use the color picker on MSIE 5. I tested this on a
        // Macintosh OS9 system and the color picker about hung MSIE.
        if (tool == 'color' && OLD_MSIE) continue;

        a_obj = document.createElement('a');
        a_obj.id = 'editor-tools-a-' + tool;
        a_obj.href = 'javascript:' + jsaction;

        img_obj = document.createElement('img');
        img_obj.id = 'editor-tools-img-' + tool;
        img_obj.className = 'editor-tools-button';
        img_obj.src = icon;
        img_obj.width = iwidth;
        img_obj.height = iheight;
        img_obj.style.padding = '2px';
        img_obj.alt = description;
	img_obj.title = description;

        // If an icon is added that is less high than our default icon
        // height, we try to make the button the same height as the
        // others by adding some dynamic padding to it.
        if (iheight < editor_tools_default_iconheight) {
            var fill = editor_tools_default_iconheight - iheight;
            var addbottom = Math.round(fill / 2);
            var addtop = fill - addbottom;
            img_obj.style.paddingTop = (addtop + 2) + 'px';
            img_obj.style.paddingBottom = (addbottom + 2) + 'px';
        }
        a_obj.appendChild(img_obj);

        // Add the button to the page.
        // target = subject is a feature that was added for supporting
        // the subjectsmiley tool. This one is added to the subject field
        // instead of the textarea. 
        if (target == 'subject') {
            // Find the subject text field. If we can't find one,
            // then simply ignore this tool.
            if (subjectfield_obj) {
                img_obj.style.verticalAlign = 'top';
                var parent = subjectfield_obj.parentNode;
                var sibling = subjectfield_obj.nextSibling;
                parent.insertBefore(a_obj, sibling);
            }
        } else {
            div_obj.appendChild(a_obj);
        }
    }

    // Hide any open popup when the user clicks the textarea or subject field.
    textarea_obj.onclick = function() {
        editor_tools_hide_all_popups();
    };
    if (subjectfield_obj) {
        subjectfield_obj.onclick = function() {
            editor_tools_hide_all_popups();
        }
    }
}

// ----------------------------------------------------------------------
// Popup window utilities
// ----------------------------------------------------------------------

// Create a popup window.
function editor_tools_construct_popup(create_id, anchor)
{
    // Create the outer div for the popup window.
    var popup_obj = document.createElement('div');
    popup_obj.id = create_id;
    popup_obj.className = 'editor-tools-popup';
    popup_obj.style.display = 'none';
    document.getElementById('editor-tools').appendChild(popup_obj);

    popup_obj._anchor = anchor;

    // Create the inner content div.
    var content_obj = document.createElement('div');
    content_obj.id = create_id + '-content';
    popup_obj.appendChild(content_obj);

    return new Array(popup_obj, content_obj);
}

// Toggle a popup window.
function editor_tools_toggle_popup(popup_obj, button_obj, width, leftoffset)
{
    // Determine where to show the popup on screen.
    var work_obj = button_obj;
    var top = work_obj.offsetTop + work_obj.offsetHeight + 2;
    var left = work_obj.offsetLeft;

    while (work_obj.offsetParent != null) {
        work_obj = work_obj.offsetParent;
        left += work_obj.offsetLeft;
        top += work_obj.offsetTop;
    }

    if (leftoffset) left -= leftoffset;
    if (width) popup_obj.style.width = width;

    // Move the popup window to the right place.
    if (popup_obj._anchor == 'r')
    {
        // Determine the screen width.
        var scrwidth = null;
        if (document.documentElement.clientWidth) {
            // Firefox screen width.
            scrwidth = document.documentElement.clientWidth;
        } else {
            scrwidth = document.body.clientWidth;
            // -16 for scrollbar that is counted in in some browsers.
            if (document.getElementById && !document.all) {
                scrwidth -= 16;
            }
        }

        var right = scrwidth - left - button_obj.offsetWidth;

        popup_obj.style.right = right + 'px';
        popup_obj.style.top = top + 'px';
    } else {
        popup_obj.style.left = left + 'px';
        popup_obj.style.top = top + 'px';
    }

    // Toggle the popup window's visibility.
    if (popup_obj.style.display == 'none') {
        editor_tools_hide_all_popups();
        popup_obj.style.display = 'block';
    } else {
        popup_obj.style.display = 'none';
        editor_tools_focus_textarea();
    }
}

// Register an object as a popup, so editor_tools_hide_all_popups() 
// can hide it.
function editor_tools_register_popup_object(object)
{
    if (! object) return;
    editor_tools_popup_objects[editor_tools_popup_objects.length] = object;
}

// Hide all objects that were registered as a popup.
function editor_tools_hide_all_popups()
{
    for (var i = 0; i < editor_tools_popup_objects.length; i++) {
        var object = editor_tools_popup_objects[i];
        object.style.display = 'none';
    }
}

// Save the selection range of the textarea. This is needed because
// sometimes clicking in a popup can clear the selection in MSIE.
function editor_tools_store_range()
{
    var ta = editor_tools_get_textarea();
    if (ta == null || ta.setSelectionRange || ! document.selection) return;
    ta.focus();
    editor_tools_textarea_range = document.selection.createRange();
}

// Restored a saved textarea selection range.
function editor_tools_restore_range()
{
    if (editor_tools_textarea_range != null)
    {
        editor_tools_textarea_range.select();
        editor_tools_textarea_range = null;
    }
}

// ----------------------------------------------------------------------
// Textarea manipulation
// ----------------------------------------------------------------------

// Add tags to the textarea. If some text is selected, then place the
// tags around the selected text. If no text is selected and a prompt_str
// is provided, then prompt the user for the data to place inside
// the tags.
function editor_tools_add_tags(pre, post, target, prompt_str)
{
    var text;
    var pretext;
    var posttext;
    var range;
    var ta = target ? target : editor_tools_get_textarea();
    if (ta == null) return;

    // Store the current scroll offset, so we can restore it after
    // adding the tags to its contents.
    var offset = ta.scrollTop;

    if (ta.setSelectionRange)
    {
        // Get the currently selected text.
        pretext = ta.value.substring(0, ta.selectionStart);
        text = ta.value.substring(ta.selectionStart, ta.selectionEnd);
        posttext = ta.value.substring(ta.selectionEnd, ta.value.length);

        // Prompt for input if no text was selected and a prompt is set.
        if (text == '' && prompt_str) {
            text = prompt(prompt_str, '');
            if (text == null) return;
        }

        // Strip whitespace from text selection and move it to the
        // pre- and post.
        var res = editor_tools_strip_whitespace(text, true);
        text = res[0];
        pre = res[1] + pre;
        post = post + res[2];

        ta.value = pretext + pre + text + post + posttext;

        // Reselect the selected text.
        var cursorpos1 = pretext.length + pre.length;
        var cursorpos2 = cursorpos1 + text.length;
        ta.setSelectionRange(cursorpos1, cursorpos2);
        ta.focus();
    }
    else if (document.selection) /* MSIE support */
    {
        // Get the currently selected text.
        ta.focus();
        range = document.selection.createRange();

        // Fumbling to work around newline selections at the end of
        // the text selection. MSIE does not include them in the
        // range.text, but it does replace them when setting range.text
        // to a new value :-/
        var virtlen = range.text.length;
        if (virtlen > 0) {
            while (range.text.length == virtlen) {
                range.moveEnd('character', -1);
            }
            range.moveEnd('character', +1);
        }

        // Prompt for input if no text was selected and a prompt is set.
        text = range.text;
        if (text == '' && prompt_str) {
            text = prompt(prompt_str, '');
            if (text == null) return;
        }

        // Strip whitespace from text selection and move it to the
        // pre- and post.
        var res = editor_tools_strip_whitespace(text, true);
        text = res[0];
        pre = res[1] + pre;
        post = post + res[2];

        // Add pre and post to the text.
        range.text = pre + text + post;

        // Reselect the selected text. Another MSIE anomaly has to be
        // taken care of here. MSIE will include carriage returns
        // in the text.length, but it does not take them into account
        // when using selection range moving methods :-/
        // By setting the range.text before, the cursor is now after
        // the replaced code, so we will move the start and the end
        // back in the text.
        var mvstart = post.length + text.length -
                      ((text + post).split('\r').length - 1);
        var mvend   = post.length +
                      (post.split('\r').length - 1);
        range.moveStart('character', -mvstart);
        range.moveEnd('character', -mvend);
        range.select();
    }
    else /* Support for really limited browsers, e.g. MSIE5 on MacOS */
    {
        ta.value = ta.value + pre + post;
    }

    ta.scrollTop = offset;
}

// ----------------------------------------------------------------------
// Tool: Help
// ----------------------------------------------------------------------

function editor_tools_handle_help()
{
    var c = editor_tools_help_chapters;

    // Shouldn't happen.
    if (c.length == 0) {
        alert('No help chapters available');
        return;
    }

    // Exactly one help chapter available. Immediately open the chapter.
    if (c.length == 1) {
        editor_tools_handle_help_select(c[0][1]);
        return;
    }

    // Multiple chapters available. Show a help picker menu with some
    // choices. Create the help picker on first access.
    if (!editor_tools_help_picker_obj)
    {
        // Create a new popup.
        var popup = editor_tools_construct_popup('editor-tools-help-picker','r');
        editor_tools_help_picker_obj = popup[0];
        var content_obj = popup[1];

        // Populate the new popup.
        for (var i = 0; i < editor_tools_help_chapters.length; i++) 
        {
            var helpinfo = editor_tools_help_chapters[i];
            var a_obj = document.createElement('a');
            a_obj.href = 'javascript:editor_tools_handle_help_select("' + helpinfo[1] + '")';
            a_obj.innerHTML = helpinfo[0];
            content_obj.appendChild(a_obj);
            content_obj.appendChild(document.createElement('br'));
        }

        // Register the popup with the editor tools.
        editor_tools_register_popup_object(editor_tools_help_picker_obj);
    }

    // Display the popup.
    var button_obj = document.getElementById('editor-tools-img-help');
    editor_tools_toggle_popup(editor_tools_help_picker_obj, button_obj);
}

function editor_tools_handle_help_select(url)
{
    var help_window = window.open(
        url,
        'editor_tools_help',
        'resizable=yes,' +
        'menubar=no,' +
        'directories=no,' +
        'scrollbars=yes,' +
        'toolbar=no,' +
        'status=no,' +
        'width=' + editor_tools_help_width + ',' +
        'height=' + editor_tools_help_height
    );

    editor_tools_focus_textarea();
    help_window.focus();
}



/* Added by module "bbcode", file "mods/bbcode/bbcode_editor_tools.js" */
///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// Copyright (C) 2008  Phorum Development Team                               //
// http://www.phorum.org                                                     //
//                                                                           //
// This program is free software. You can redistribute it and/or modify      //
// it under the terms of either the current Phorum License (viewable at      //
// phorum.org) or the Phorum License that was distributed with this file     //
//                                                                           //
// This program is distributed in the hope that it will be useful,           //
// but WITHOUT ANY WARRANTY, without even the implied warranty of            //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                      //
//                                                                           //
// You should have received a copy of the Phorum License                     //
// along with this program.                                                  //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

// Javascript code for BBcode support in the Phorum editor_tools module.

// Some variables for storing objects that we need globally.
var editor_tools_size_picker_obj = null;
var editor_tools_list_picker_obj = null;

// Valid sizes to select from for the size picker. If you add or change sizes,
// remember to change the module language file to supply some display strings.
var editor_tools_size_picker_sizes = new Array(
    'x-large',
    'large',
    'medium',
    'small',
    'x-small'
);

// Valid list types to select from for the list picker. If you add or change
// types, remember to change the module language file to supply some
// display strings.
var editor_tools_list_picker_types = new Array(
    'b', // bullets
    '1', // numbers
    'a', // letters
    'A', // capital letters
    'i', // roman numbers
    'I'  // capital roman numbers
);

// Helper function: quote a bbcode argument if needed.
function quote_bbcode_argument(str)
{
    // Check if quoting is required.
    if (str.indexOf(' ') != -1 ||
        str.indexOf('"') != -1 ||
        str.indexOf(']') != -1)
    {
        var quoted = '';
        for (var i = 0; i < str.length; i++) {
            var c = str[i];
            if (c == '\\' || c == '"') {
                quoted += '\\';
            }
            quoted += c;
        }

        return '"' + quoted + '"';
    }
    else
    {
        return str;
    }
}

// ----------------------------------------------------------------------
// Tool: [hr] or [hline] (horizontal line)
// ----------------------------------------------------------------------

function editor_tools_handle_hr() {
    editor_tools_add_tags('\n[hr]\n', '');
    editor_tools_focus_textarea();
}

// ----------------------------------------------------------------------
// Tool: [b]...[/b] (bold)
// ----------------------------------------------------------------------

function editor_tools_handle_b() {
    editor_tools_add_tags('[b]', '[/b]');
    editor_tools_focus_textarea();
}

// ----------------------------------------------------------------------
// Tool: [s]...[/s] (strike through)
// ----------------------------------------------------------------------

function editor_tools_handle_s() {
    editor_tools_add_tags('[s]', '[/s]');
    editor_tools_focus_textarea();
}

// ----------------------------------------------------------------------
// Tool: [u]...[/u] (underline)
// ----------------------------------------------------------------------

function editor_tools_handle_u() {
    editor_tools_add_tags('[u]', '[/u]');
    editor_tools_focus_textarea();
}

// ----------------------------------------------------------------------
// Tool: [i]...[/i] (italic)
// ----------------------------------------------------------------------

function editor_tools_handle_i() {
    editor_tools_add_tags('[i]', '[/i]');
    editor_tools_focus_textarea();
}

// ----------------------------------------------------------------------
// Tool: [center]...[/center] (center text)
// ----------------------------------------------------------------------

function editor_tools_handle_center() {
    editor_tools_add_tags('[center]', '[/center]');
    editor_tools_focus_textarea();
}

// ----------------------------------------------------------------------
// Tool: [sub]...[/sub] (subscript)
// ----------------------------------------------------------------------

function editor_tools_handle_sub() {
    editor_tools_add_tags('[sub]', '[/sub]');
    editor_tools_focus_textarea();
}

// ----------------------------------------------------------------------
// Tool: [sup]...[/sup] (superscript)
// ----------------------------------------------------------------------

function editor_tools_handle_sup() {
    editor_tools_add_tags('[sup]', '[/sup]');
    editor_tools_focus_textarea();
}

// ----------------------------------------------------------------------
// Tool: [small]...[/small] (small font)
// ----------------------------------------------------------------------

function editor_tools_handle_small() {
    editor_tools_add_tags('[small]', '[/small]');
    editor_tools_focus_textarea();
}

// ----------------------------------------------------------------------
// Tool: [large]...[/large] (large font)
// ----------------------------------------------------------------------

function editor_tools_handle_large() {
    editor_tools_add_tags('[large]', '[/large]');
    editor_tools_focus_textarea();
}

// ----------------------------------------------------------------------
// Tool: [code]...[/code] (formatted code)
// ----------------------------------------------------------------------

function editor_tools_handle_code() {
    editor_tools_add_tags('[code]\n', '\n[/code]\n');
    editor_tools_focus_textarea();
}

// ----------------------------------------------------------------------
// Tool: [email]...[/email] (email address link)
// ----------------------------------------------------------------------

function editor_tools_handle_email()
{
    var email = prompt(editor_tools_translate("enter email"), '');
    if (email == null) return;
    email = editor_tools_strip_whitespace(email);

    var subject = prompt(editor_tools_translate("enter subject"), '');
    if (subject == null) return;
    subject = editor_tools_strip_whitespace(subject);
    if (subject != '') {
        subject = ' subject=' + quote_bbcode_argument(subject);
    }

    if (email == '') {
        editor_tools_add_tags('[email'+subject+']', '[/email]');
    } else {
        editor_tools_add_tags('[email'+subject+']'+email+'[/email]', '');
    }

    editor_tools_focus_textarea();
}

// ----------------------------------------------------------------------
// Tool: [url=...]...[/url] (URL link)
// ----------------------------------------------------------------------

function editor_tools_handle_url()
{
    var url = 'http://';

    for (;;)
    {
        // Read input.
        url = prompt(editor_tools_translate("enter url"), url);
        if (url == null) return; // Cancel clicked.
        url = editor_tools_strip_whitespace(url);

        // Check the URL scheme (http, https, ftp and mailto are allowed).
        copy = url.toLowerCase();
        if (copy == 'http://' || (
            copy.substring(0,7) != 'http://' &&
            copy.substring(0,8) != 'https://' &&
            copy.substring(0,6) != 'ftp://' &&
            copy.substring(0,7) != 'mailto:')) {
            alert(editor_tools_translate("invalid url"));
            continue;
        }

        break;
    }

    editor_tools_add_tags('[url=' + url + ']', '[/url]', null, editor_tools_translate("enter url description"));
    editor_tools_focus_textarea();
}

// ----------------------------------------------------------------------
// Tool: [color=...]...[/color] (text color)
// ----------------------------------------------------------------------

function editor_tools_handle_color()
{
    editor_tools_store_range();

    // Display the color picker.
    var img_obj = document.getElementById('editor-tools-img-color');
    showColorPicker(img_obj);
    return;
}

// Called by the color picker library.
function editor_tools_handle_color_select(color)
{
    editor_tools_restore_range();

    editor_tools_add_tags('[color=' + color + ']', '[/color]');
    editor_tools_focus_textarea();
}

// ----------------------------------------------------------------------
// Tool: [size=...]...[/size] (text size)
// ----------------------------------------------------------------------

function editor_tools_handle_size()
{
    editor_tools_store_range();

    // Create the size picker on first access.
    if (!editor_tools_size_picker_obj)
    {
        // Create a new popup.
        var popup = editor_tools_construct_popup('editor-tools-size-picker','l');
        editor_tools_size_picker_obj = popup[0];
        var content_obj = popup[1];

        // Populate the new popup.
        for (var i = 0; i < editor_tools_size_picker_sizes.length; i++)
        {
            var size = editor_tools_size_picker_sizes[i];
            var a_obj = document.createElement('a');
            a_obj.href = 'javascript:editor_tools_handle_size_select("' + size + '")';
            a_obj.style.fontSize = size;
            a_obj.innerHTML = editor_tools_translate(size);
            content_obj.appendChild(a_obj);

            var br_obj = document.createElement('br');
            content_obj.appendChild(br_obj);
        }

        // Register the popup with the editor tools.
        editor_tools_register_popup_object(editor_tools_size_picker_obj);
    }

    // Display the popup.
    var button_obj = document.getElementById('editor-tools-img-size');
    editor_tools_toggle_popup(editor_tools_size_picker_obj, button_obj);
}

function editor_tools_handle_size_select(size)
{
    editor_tools_hide_all_popups();
    editor_tools_restore_range();
    size = editor_tools_strip_whitespace(size);
    editor_tools_add_tags('[size=' + size + ']', '[/size]');
    editor_tools_focus_textarea();
}

// ----------------------------------------------------------------------
// Tool: [img]...[/img] (Image URL)
// ----------------------------------------------------------------------

function editor_tools_handle_img()
{
    var url = 'http://';

    for (;;)
    {
        // Read input.
        url = prompt(editor_tools_translate("enter image url"), url);
        if (url == null) return; // Cancel clicked.
        url = editor_tools_strip_whitespace(url);

        // Check the URL scheme (http, https, ftp and mailto are allowed).
        var copy = url.toLowerCase();
        if (copy == 'http://' || (
            copy.substring(0,7) != 'http://' &&
            copy.substring(0,8) != 'https://' &&
            copy.substring(0,6) != 'ftp://')) {
            alert(editor_tools_translate("invalid image url"));
            continue;
        }

        break;
    }

    editor_tools_add_tags('[img]' + url + '[/img]', '');
    editor_tools_focus_textarea();
}

// ----------------------------------------------------------------------
// Tool: [quote]...[/quote] (add a quote)
// ----------------------------------------------------------------------

function editor_tools_handle_quote()
{
    // Read input.
    var who = prompt(editor_tools_translate("enter who you quote"), '');
    if (who == null) return;
    who = editor_tools_strip_whitespace(who);

    if (who == '') {
        editor_tools_add_tags('[quote]', '[/quote]');
    }
    else
    {
        who = quote_bbcode_argument(who);
        editor_tools_add_tags('[quote=' + who + "]\n", "\n[/quote]");
    }

    editor_tools_focus_textarea();
}

// ----------------------------------------------------------------------
// Tool: [list] [*]item1 [*]item2 [/list]
// ----------------------------------------------------------------------

function editor_tools_handle_list()
{
    // Create the list picker on first access.
    if (!editor_tools_list_picker_obj)
    {
        // Create a new popup.
        var popup = editor_tools_construct_popup('editor-tools-list-picker', 'l');
        editor_tools_list_picker_obj = popup[0];
        var content_obj = popup[1];

        // Populate the new popup.
        var wrapper = document.createElement('div');
        wrapper.style.marginLeft = '1em';
        for (var i = 0; i < editor_tools_list_picker_types.length; i++)
        {
            var type = editor_tools_list_picker_types[i];

            var list;
            if (type == 'b') {
                list = document.createElement('ul');
            } else {
                list = document.createElement('ol');
                list.type = type;
            }
            list.style.padding = 0;
            list.style.margin = 0;
            var item = document.createElement('li');

            var a_obj = document.createElement('a');
            a_obj.href = 'javascript:editor_tools_handle_list_select("' + type + '")';
            a_obj.innerHTML = editor_tools_translate('list type ' + type);

            item.appendChild(a_obj);
            list.appendChild(item);
            wrapper.appendChild(list);
        }
        content_obj.appendChild(wrapper);

        // Register the popup with the editor tools.
        editor_tools_register_popup_object(editor_tools_list_picker_obj);
    }

    // Display the popup.
    var button_obj = document.getElementById('editor-tools-img-list');
    editor_tools_toggle_popup(editor_tools_list_picker_obj, button_obj);
}

function editor_tools_handle_list_select(type)
{
    editor_tools_hide_all_popups();

    var items = new Array();
    var idx = 0;

    // Read items.
    for (;;)
    {
        var item = prompt(editor_tools_translate('enter new list item'), '');
        if (item == null) return;
        item = editor_tools_strip_whitespace(item);
        if (item == '') break;
        items[idx++] = item;
    }

    if (items.length == 0) {
        items = new Array(
            '...',
            '...'
        );
    }

    var itemlist = '';
    for (var i = 0; i < items.length; i++) {
        itemlist += '[*] ' + items[i] + "\n";
    }

    if (type == 'b') {
        type = '';
    } else {
        type = '='+type;
    }

    editor_tools_add_tags("[list"+type+"]\n"+itemlist+"[/list]\n", '');
}


