aboutsummaryrefslogblamecommitdiffstats
path: root/embed/mozilla/PromptService.cpp
blob: 38434f1f91ec7dae42f0ffa07e0649a557125ab9 (plain) (tree)


































































                                                                              

                                                        












































































                                                                         
                                                                               














































































                                                                               

                                                            



                                                                    






























                                                  



                                                                              



















                                                                       
                                         
















                                                                               

                                                                      





                                                               
                                                     
                                                      
                                                     
                                               
                                                     





                                                                

                                                                   













































































































































































































































































































































                                                                                  
                                                               



























































                                                                          
                                                         


















































                                                                           
/*
 *  Copyright (C) 2000 Marco Pesenti Gritti
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *
 *  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.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include "ephy-glade.h"
#include "PromptService.h"

#include "nsCOMPtr.h"
#include "nsIFactory.h"
#include "nsString.h"
#include "nsReadableUtils.h"
#include "nsIServiceManager.h"
#include "nsXPComFactory.h"
#include "MozillaPrivate.h"

#include "nsIPromptService.h"
#include "nsIUnicodeEncoder.h"

#include <gtk/gtkentry.h>
#include <gtk/gtktogglebutton.h>
#include <gtk/gtklist.h>
#include <libgnomeui/gnome-dialog.h>
#include <libgnome/gnome-i18n.h>
#include <libgnome/gnome-triggers.h>

/* local function prototypes */
static void set_title (GtkWidget *dialog, const PRUnichar *title);
static void set_label_text (GtkWidget *label, const PRUnichar *text);
static void set_check_button_text (GtkWidget *check_button, 
                   const PRUnichar *text);
static void set_check_button (GtkWidget *button, PRBool *value);
static void set_check_button_size_to_label (GtkWidget *check_button,
                        GtkWidget *label);
static void set_editable (GtkWidget *entry, PRUnichar **text);
static void get_check_button (GtkWidget *button, PRBool *value);
static void get_editable (GtkWidget *editable, PRUnichar **text);

/**
 * class CPromptService: an GNOME implementation of prompt dialogs for
 * Mozilla
 */
class CPromptService: public nsIPromptService
{
    public:
        CPromptService();
        virtual ~CPromptService();

        NS_DECL_ISUPPORTS
        NS_DECL_NSIPROMPTSERVICE
    private:
        nsresult AddButton (GtkWidget *dialog, 
                    char type, 
                    const PRUnichar *title,
                    int id,
                    GtkWidget **widget);
};

NS_IMPL_ISUPPORTS1 (CPromptService, nsIPromptService)

/**
 * CPromptService::CPromptService: constructor
 */
CPromptService::CPromptService ()
{
    NS_INIT_ISUPPORTS();
}

/**
 * CPromptService::~CPromptService: destructor
 */
CPromptService::~CPromptService ()
{
}

/**
 * CPromptService::Alert: show an alert box
 */
NS_IMETHODIMP CPromptService::Alert (nsIDOMWindow *parent, 
                     const PRUnichar *dialogTitle,
                     const PRUnichar *text)
{    
    GtkWidget *dialog;
    GtkWidget *gparent;

    gparent = MozillaFindGtkParent (parent);
    const nsACString &msg = NS_ConvertUCS2toUTF8 (text);
    dialog = gtk_message_dialog_new (GTK_WINDOW(gparent),
                     GTK_DIALOG_MODAL,
                     GTK_MESSAGE_WARNING,
                     GTK_BUTTONS_OK,
                     "%s",
                     PromiseFlatCString(msg).get ());
    set_title (dialog, dialogTitle);

    gtk_dialog_run (GTK_DIALOG (dialog));
    gtk_widget_destroy (dialog);

    return NS_OK;
}

/**
 * CPromptService::AlertCheck: show an alert box with a checkbutton,
 * (typically for things like "dont show this warning again")
 */
NS_IMETHODIMP CPromptService::AlertCheck (nsIDOMWindow *parent, 
                      const PRUnichar *dialogTitle,
                      const PRUnichar *text,
                      const PRUnichar *checkMsg, 
                      PRBool *checkValue)
{
    GtkWidget *dialog;
    GtkWidget *gparent;
    GtkWidget *check_button;
    
    gparent = MozillaFindGtkParent (parent);
    const nsACString &msg = NS_ConvertUCS2toUTF8 (text);
    dialog = gtk_message_dialog_new (GTK_WINDOW(gparent),
                     GTK_DIALOG_MODAL,
                     GTK_MESSAGE_WARNING,
                     GTK_BUTTONS_OK,
                     "%s",
                     PromiseFlatCString(msg).get ());

    check_button = gtk_check_button_new_with_label ("");
    gtk_widget_show (check_button);
    gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dialog)->vbox), 
                check_button, FALSE, FALSE, 5);
    set_check_button_text (check_button, checkMsg);
    set_check_button (check_button, checkValue);

    set_title (dialog, dialogTitle);

    gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
    gtk_dialog_run (GTK_DIALOG (dialog));
    get_check_button (check_button, checkValue);
    gtk_widget_destroy (dialog);
    
    return NS_OK;
}

/**
 * CPromptService::Confirm: for simple yes/no dialogs
 */
NS_IMETHODIMP CPromptService::Confirm (nsIDOMWindow *parent, 
                       const PRUnichar *dialogTitle,
                       const PRUnichar *text,
                       PRBool *_retval)
{
    GtkWidget *dialog;
    GtkWidget *gparent;
    int res;

    gparent = MozillaFindGtkParent (parent);
    const nsACString &msg = NS_ConvertUCS2toUTF8 (text);
    dialog = gtk_message_dialog_new (GTK_WINDOW(gparent),
                     GTK_DIALOG_MODAL,
                     GTK_MESSAGE_QUESTION,
                     GTK_BUTTONS_YES_NO,
                     "%s", PromiseFlatCString(msg).get ());
    set_title (dialog, dialogTitle);

    res = gtk_dialog_run (GTK_DIALOG (dialog));
    *_retval = (res == GTK_RESPONSE_YES);
    gtk_widget_destroy (dialog);
    
    return NS_OK;
}

/**
 * CPromptService::Confirm: for simple yes/no dialogs, with an additional
 * check button
 */
NS_IMETHODIMP CPromptService::ConfirmCheck (nsIDOMWindow *parent, 
                        const PRUnichar *dialogTitle,
                        const PRUnichar *text,
                        const PRUnichar *checkMsg, 
                        PRBool *checkValue,
                        PRBool *_retval)
{
    GtkWidget *dialog;
    GtkWidget *gparent;
    GtkWidget *check_button;
    int res;

    gparent = MozillaFindGtkParent (parent);
    const nsACString &msg = NS_ConvertUCS2toUTF8 (text);
    dialog = gtk_message_dialog_new (GTK_WINDOW(gparent),
                     GTK_DIALOG_MODAL,
                     GTK_MESSAGE_QUESTION,
                     GTK_BUTTONS_YES_NO,
                     "%s", PromiseFlatCString(msg).get ());

    check_button = gtk_check_button_new_with_label ("");
    gtk_widget_show (check_button);
    gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dialog)->vbox), 
                check_button, FALSE, FALSE, 5);
    set_check_button_text (check_button, checkMsg);
    set_check_button (check_button, checkValue);
    
    set_title (dialog, dialogTitle);

    res = gtk_dialog_run (GTK_DIALOG (dialog));
    *_retval = (res == GTK_RESPONSE_YES);
    get_check_button (check_button, checkValue);
    gtk_widget_destroy (dialog);

    return NS_OK;
}

NS_IMETHODIMP CPromptService::AddButton (GtkWidget *dialog, 
                     char type, 
                     const PRUnichar *title,
                     int id,
                     GtkWidget **widget)
{
    const char *btitle;
    const nsACString &utf8string = NS_ConvertUCS2toUTF8 (title);

    switch (type)
    {
        case BUTTON_TITLE_OK:
            btitle = GTK_STOCK_OK;
            break;
        case BUTTON_TITLE_CANCEL:
            btitle = GTK_STOCK_CANCEL;
            break;
        case BUTTON_TITLE_YES:
            btitle = GTK_STOCK_YES;
            break;
        case BUTTON_TITLE_NO:
            btitle = GTK_STOCK_NO;
            break;
        case BUTTON_TITLE_SAVE:
            btitle = _("Save");
            break;
        case BUTTON_TITLE_REVERT:
            btitle = _("Revert");
            break;
        case BUTTON_TITLE_DONT_SAVE:
            btitle = _("Don't save");
            break;
        case BUTTON_TITLE_IS_STRING:
            btitle = NULL;
            break;

        default:
            return NS_ERROR_FAILURE;
    }

    *widget = gtk_dialog_add_button (GTK_DIALOG(dialog),
                             btitle ? btitle : 
                             PromiseFlatCString(utf8string).get(),
                             id);

    return NS_OK;
}

/**
 * CPromptService::ConfirmEx: For fancy confirmation dialogs
 */
NS_IMETHODIMP CPromptService::ConfirmEx (nsIDOMWindow *parent, 
                     const PRUnichar *dialogTitle,
                     const PRUnichar *text,
                     PRUint32 buttonFlags, 
                     const PRUnichar *button0Title,
                     const PRUnichar *button1Title,
                     const PRUnichar *button2Title,
                     const PRUnichar *checkMsg, 
                     PRBool *checkValue,
                     PRInt32 *buttonPressed)
{
    GtkWidget *dialog;
    GtkWidget *gparent;
    GtkWidget *default_button = NULL;
    GtkWidget *check_button = NULL;
    int ret;

    gparent = MozillaFindGtkParent (parent);
    const nsACString &msg = NS_ConvertUCS2toUTF8 (text);
    dialog = gtk_message_dialog_new (GTK_WINDOW(gparent),
                     GTK_DIALOG_MODAL,
                     GTK_MESSAGE_QUESTION,
                     GTK_BUTTONS_NONE,
                     "%s", PromiseFlatCString(msg).get ());

    set_title (dialog, dialogTitle);

    if (checkMsg)
    {
        check_button = gtk_check_button_new_with_label ("");
        gtk_widget_show (check_button);
        gtk_box_pack_end (GTK_BOX (GTK_DIALOG(dialog)->vbox), 
                  check_button, FALSE, FALSE, 5);

        set_check_button_text (check_button, checkMsg);
        set_check_button (check_button, checkValue);
    }
    
    AddButton (dialog, (buttonFlags >> 16) & 0xFF, 
           button2Title, 2, &default_button);
    AddButton (dialog, (buttonFlags >> 8) & 0xFF, 
           button1Title, 1, &default_button);
    AddButton (dialog, buttonFlags & 0xFF, 
           button0Title, 0, &default_button);
    
    gtk_dialog_set_default_response (GTK_DIALOG(dialog), 0);

    /* make a suitable sound */
    gnome_triggers_vdo ("", "generic", NULL);

    gtk_window_set_focus (GTK_WINDOW (dialog), default_button);
    
    /* run dialog and capture return values */
    ret = gtk_dialog_run (GTK_DIALOG (dialog));
    
    /* handle return values */
    if (checkMsg)
    {
        get_check_button (check_button, checkValue);
    }

    *buttonPressed = ret;
    
    /* done */
    gtk_widget_destroy (dialog);
    return NS_OK;
}

/**
 * CPromptService::Prompt: show a prompt for text, with a checkbutton
 */
NS_IMETHODIMP CPromptService::Prompt (nsIDOMWindow *parent, 
                      const PRUnichar *dialogTitle,
                      const PRUnichar *text, 
                      PRUnichar **value,
                      const PRUnichar *checkMsg, 
                      PRBool *checkValue,
                      PRBool *_retval)
{
    GtkWidget *dialog;
    GtkWidget *entry;
    GtkWidget *label;
    GtkWidget *check_button;
    GtkWidget *gparent;
    GladeXML *gxml;
    gint ret;

    /* build and show the dialog */
    gxml = ephy_glade_widget_new ("prompts.glade", "prompt_dialog", 
                 &dialog, NULL);
    entry = glade_xml_get_widget (gxml, "entry");
    label = glade_xml_get_widget (gxml, "label");
    check_button = glade_xml_get_widget (gxml, "check_button");
    g_object_unref (G_OBJECT (gxml));

    /* parent the dialog */
    gparent = MozillaFindGtkParent (parent);
    gtk_window_set_transient_for (GTK_WINDOW (dialog),
                                      GTK_WINDOW (gparent));
    
    /* set dynamic attributes */
    set_title (dialog, dialogTitle);
    set_label_text (label, text);
    set_check_button_text (check_button, checkMsg);
    set_editable (entry, value);
    set_check_button (check_button, checkValue);
    set_check_button_size_to_label (check_button, label);
    
    /* make a suitable sound */
    /* NB: should be question, but this is missing in many
     * of the current gnome sound packages that I've tried... */
    gnome_triggers_vdo ("", "generic", NULL);

    /* run dialog and capture return values */
    ret = gtk_dialog_run (GTK_DIALOG (dialog));

    /* handle return values */
    get_check_button (check_button, checkValue);
    get_editable (entry, value);
    *_retval = (ret == GTK_RESPONSE_OK);

    /* done */
    gtk_widget_destroy (dialog);
    return NS_OK;
}

/**
 * CPromptService::PromptUsernameAndPassword: show a prompt for username
 * and password with an additional check button.
 */
NS_IMETHODIMP CPromptService::PromptUsernameAndPassword 
                                        (nsIDOMWindow *parent, 
                     const PRUnichar *dialogTitle,
                     const PRUnichar *text,
                     PRUnichar **username,
                     PRUnichar **password,
                     const PRUnichar *checkMsg,
                     PRBool *checkValue,
                     PRBool *_retval)
{
    GtkWidget *dialog;
    GtkWidget *check_button;
    GtkWidget *label;
    GtkWidget *username_entry;
    GtkWidget *password_entry;
    GtkWidget *gparent;
    GladeXML *gxml;
    gint ret;

    /* build and show the dialog */
    gxml = ephy_glade_widget_new ("prompts.glade", "prompt_user_pass_dialog", 
                 &dialog, NULL);
    check_button = glade_xml_get_widget (gxml, "check_button");
    label = glade_xml_get_widget (gxml, "label");
    username_entry = glade_xml_get_widget (gxml, "username_entry");
    password_entry = glade_xml_get_widget (gxml, "password_entry");
    g_object_unref (G_OBJECT (gxml));

    /* parent the dialog */
    gparent = MozillaFindGtkParent (parent);
    gtk_window_set_transient_for (GTK_WINDOW (dialog),
                                      GTK_WINDOW (gparent));

    /* set dynamic attributes */
    set_title (dialog, dialogTitle);
    set_check_button_text (check_button, checkMsg);
    set_editable (username_entry, username);
    set_editable (password_entry, password);
    set_check_button (check_button, checkValue);
    set_label_text (label, text);
    set_check_button_size_to_label (check_button, label);
    
    /* make a suitable sound */
    gnome_triggers_vdo ("", "question", NULL);

    /* run dialog and capture return values */
    ret = gtk_dialog_run (GTK_DIALOG (dialog));

    /* handle return values */
    get_check_button (check_button, checkValue);
    get_editable (username_entry, username);
    get_editable (password_entry, password);
    *_retval = (ret == GTK_RESPONSE_OK);

    /* done */
    gtk_widget_destroy (dialog);
    return NS_OK;
}

/**
 * CPromptService::PromptPassword: show a prompt for just
 * a password with an additional check button.
 */
NS_IMETHODIMP CPromptService::PromptPassword (nsIDOMWindow *parent, 
                          const PRUnichar *dialogTitle,
                          const PRUnichar *text,
                          PRUnichar **password,
                          const PRUnichar *checkMsg, 
                          PRBool *checkValue,
                          PRBool *_retval)
{
    GtkWidget *dialog;
    GtkWidget *label;
    GtkWidget *check_button;
    GtkWidget *password_entry;
    GtkWidget *gparent;
    GladeXML *gxml;
    gint ret;

    /* build and show the dialog */
    gxml = ephy_glade_widget_new ("prompts.glade", "prompt_pass_dialog", 
                 &dialog, NULL);
    check_button = glade_xml_get_widget (gxml, "check_button");
    label = glade_xml_get_widget (gxml, "label");
    password_entry = glade_xml_get_widget (gxml, "password_entry");
    g_object_unref (G_OBJECT (gxml));

    /* parent the dialog */
    gparent = MozillaFindGtkParent (parent);
    gtk_window_set_transient_for (GTK_WINDOW (dialog),
                                      GTK_WINDOW (gparent));

    /* set dynamic attributes */
    set_title (dialog, dialogTitle);
    set_check_button_text (check_button, checkMsg);
    set_editable (password_entry, password);
    set_check_button (check_button, checkValue);
    set_label_text (label, text);
    set_check_button_size_to_label (check_button, label);

    /* make a suitable sound */
    gnome_triggers_vdo ("", "question", NULL);

    /* run dialog and capture return values */
    ret = gtk_dialog_run (GTK_DIALOG (dialog));

    /* handle return values */
    get_check_button (check_button, checkValue);
    get_editable (password_entry, password);
    *_retval = (ret == GTK_RESPONSE_OK);

    /* done */
    gtk_widget_destroy (dialog);
    return NS_OK;
}


/**
 * CPromptService::Select:
 */
NS_IMETHODIMP CPromptService::Select (nsIDOMWindow *parent, 
                      const PRUnichar *dialogTitle,
                      const PRUnichar *text, PRUint32 count,
                      const PRUnichar **selectList, 
                      PRInt32 *outSelection,
                      PRBool *_retval)
{
    GtkWidget *dialog;
    GtkWidget *gparent;
    GtkWidget *label;
    GladeXML *gxml;
    GtkWidget *treeview;
    gint ret;
    
    /* build and show the dialog */
    gxml = ephy_glade_widget_new ("prompts.glade", "select_dialog", 
                 &dialog, NULL);
    treeview = glade_xml_get_widget (gxml, "treeview");
    label   = glade_xml_get_widget (gxml, "label");
    g_object_unref (G_OBJECT (gxml));

    /* parent the dialog */
    gparent = MozillaFindGtkParent (parent);
    gtk_window_set_transient_for (GTK_WINDOW (dialog),
                                      GTK_WINDOW (gparent));

    /* set dynamic attributes */
    set_title (dialog, dialogTitle);
    set_label_text (label, text);

    /* setup treeview */
        GtkCellRenderer *renderer;
        GtkListStore *liststore;
    GtkTreeSelection *selection;
    GtkTreeModel *model;
    GtkTreeIter iter;

        gtk_tree_view_set_reorderable (GTK_TREE_VIEW(treeview), TRUE);

        liststore = gtk_list_store_new (2,
                                        G_TYPE_STRING,
                    G_TYPE_INT);

        model = GTK_TREE_MODEL (liststore);

        gtk_tree_view_set_model (GTK_TREE_VIEW(treeview), 
                                 model);
        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(treeview),
                                           FALSE);

        renderer = gtk_cell_renderer_text_new ();

        gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW(treeview),
                                                     0, "Items",
                                                     renderer,
                                                     "text", 0,
                             NULL);

    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(treeview));
    
    for (PRUint32 i = 0 ; i < count ; i++)
    {
        char *itemText = 
            ToNewCString(NS_ConvertUCS2toUTF8 (selectList[i])); 
            gtk_list_store_append (GTK_LIST_STORE (model), 
                                       &iter);
            gtk_list_store_set (GTK_LIST_STORE (model),
                                    &iter,
                                    0, itemText,
                    1, i,
                                    -1);
        nsMemory::Free(itemText);
    }

    gtk_tree_model_get_iter_first (model, &iter);
    gtk_tree_selection_select_iter (selection, &iter);

    /* make a suitable sound */
    gnome_triggers_vdo ("", "question", NULL);

    /* run dialog and capture return values */
    ret = gtk_dialog_run (GTK_DIALOG (dialog));

    /* handle return values */
    if (gtk_tree_selection_get_selected (selection,
                         &model,
                         &iter))
    {
        GValue val = {0, };
        gtk_tree_model_get_value (model, &iter, 1, &val);
            *outSelection = g_value_get_int (&val);

        *_retval = (ret == GTK_RESPONSE_OK) ? PR_TRUE : PR_FALSE;
    }
    else
    {
        *_retval = PR_FALSE;
    }

    gtk_widget_destroy (dialog);

    return NS_OK;
}

NS_DEF_FACTORY (CPromptService, CPromptService);

/**
 * NS_NewPromptServiceFactory:
 */ 
nsresult NS_NewPromptServiceFactory(nsIFactory** aFactory)
{
    NS_ENSURE_ARG_POINTER(aFactory);
    *aFactory = nsnull;

    nsCPromptServiceFactory *result = new nsCPromptServiceFactory;
    if (result == NULL)
    {
        return NS_ERROR_OUT_OF_MEMORY;
    }
    
    NS_ADDREF(result);
    *aFactory = result;
  
    return NS_OK;
}

/**
 * set_title: set a dialog title to a unicode string
 */
static void
set_title (GtkWidget *dialog, const PRUnichar *title)
{
    const nsACString &utf8string = NS_ConvertUCS2toUTF8 (title);

    /* set it */
    gtk_window_set_title (GTK_WINDOW (dialog), 
                  (title == NULL ? N_("Epiphany") :
                  PromiseFlatCString(utf8string).get()));
}

/**
 * set_label_text: set a labels text to a unicode string
 */
static void
set_label_text (GtkWidget *label, const PRUnichar *text)
{
    const nsACString &utf8string = NS_ConvertUCS2toUTF8 (text);
    
    /* set it */
    gtk_label_set_text (GTK_LABEL (label),
                PromiseFlatCString(utf8string).get());
}

/**
 * set_check_button_text: set a check buttons text to a unicode string
 */
static void
set_check_button_text (GtkWidget *check_button, const PRUnichar *text)
{
    const nsACString &utf8string = NS_ConvertUCS2toUTF8 (text);
    
    /* set it */
    gtk_label_set_text (GTK_LABEL (GTK_BIN (check_button)->child),
                PromiseFlatCString(utf8string).get());
}
    
/**
 * set_check_button: set a togglebutton to an initial state
 */
static void
set_check_button (GtkWidget *button, PRBool *value)
{
    /* check pointer is valid */
    if (value == NULL)
    {
        gtk_widget_hide (GTK_WIDGET (button));
        return;
    }

    /* set the value of the check button */
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), *value);
}

/**
 * se_check_button_size_to_label: sync text widgets sizes
 */
static void
set_check_button_size_to_label (GtkWidget *check_button,
                    GtkWidget *label)
{
    GtkRequisition r, label_r;

    gtk_widget_size_request (check_button, &r);
    gtk_widget_size_request (label, &label_r);

    if (r.width <= label_r.width) return;
    
    gtk_widget_set_size_request (label, r.width, -1);
}

/**
 * set_editable: set an editable to a unicode string
 */
static void
set_editable (GtkWidget *entry, PRUnichar **text)
{
    const nsACString &utf8string = NS_ConvertUCS2toUTF8 (*text);

    /* set this string value in the widget */
    gtk_entry_set_text (GTK_ENTRY (entry),
                PromiseFlatCString(utf8string).get());
}

/**
 * get_check_button: get value of a toggle button and store it in a PRBool
 */
static void
get_check_button (GtkWidget *button, PRBool *value)
{
    /* check we can write */
    if (value == NULL)
    {
        return;
    }

    /* set the value from the check button */
    *value = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
}

/**
 * get_editable: get a string from an editable and store it as unicode
 */
static void
get_editable (GtkWidget *editable, PRUnichar **text)
{
    char *edited;
    
    /* check we can write */
    if (text == NULL)
    {
        return;
    }

    /* get the text */
    edited = gtk_editable_get_chars (GTK_EDITABLE (editable), 0, -1);

    /* decode and set it as the return value */
    *text = ToNewUnicode(NS_ConvertUTF8toUCS2(edited));
}