Index: src/main/java/com/xpn/xwiki/wysiwyg/server/DefaultWysiwygService.java
===================================================================
--- src/main/java/com/xpn/xwiki/wysiwyg/server/DefaultWysiwygService.java	(revision 13966)
+++ src/main/java/com/xpn/xwiki/wysiwyg/server/DefaultWysiwygService.java	(working copy)
@@ -20,12 +20,19 @@
 package com.xpn.xwiki.wysiwyg.server;
 
 import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
 
+import org.suigeneris.jrcs.rcs.Version;
 import org.xwiki.bridge.DocumentAccessBridge;
 import org.xwiki.xml.XMLUtils;
 import org.xwiki.xml.html.HTMLCleaner;
 
-import com.google.gwt.user.server.rpc.RemoteServiceServlet;
+import com.xpn.xwiki.XWikiContext;
+import com.xpn.xwiki.XWikiException;
+import com.xpn.xwiki.doc.XWikiAttachment;
+import com.xpn.xwiki.doc.XWikiDocument;
+import com.xpn.xwiki.gwt.api.server.XWikiServiceImpl;
 import com.xpn.xwiki.web.Utils;
 import com.xpn.xwiki.wysiwyg.client.WysiwygService;
 import com.xpn.xwiki.wysiwyg.client.diff.Revision;
@@ -40,7 +47,7 @@
  * 
  * @version $Id$
  */
-public class DefaultWysiwygService extends RemoteServiceServlet implements WysiwygService
+public class DefaultWysiwygService extends XWikiServiceImpl implements WysiwygService
 {
     /**
      * The object used to synchronize the content edited by multiple users when the real time feature of the editor is
@@ -133,4 +140,202 @@
             throw new RuntimeException(t);
         }
     }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see WysiwygService#isMultiWiki()
+     */
+    public Boolean isMultiWiki()
+    {
+        return getXWikiContext().getWiki().isVirtualMode();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see WysiwygService#getVirtualWikiNames()
+     */
+    public List<String> getVirtualWikiNames()
+    {
+        List<String> virtualWikiNamesList = new ArrayList<String>();
+        try {
+            virtualWikiNamesList = getXWikiContext().getWiki().getVirtualWikisDatabaseNames(getXWikiContext());
+            virtualWikiNamesList.add("xwiki");
+        } catch (XWikiException e) {
+            e.printStackTrace();
+        }
+        return virtualWikiNamesList;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see WysiwygService#getSpaceNames(String)
+     */
+    public List<String> getSpaceNames(String wikiName)
+    {
+        List<String> spaceNamesList = new ArrayList<String>();
+        String database = getXWikiContext().getDatabase();
+        try {
+            getXWikiContext().setDatabase(wikiName);
+            spaceNamesList = getXWikiContext().getWiki().getSpaces(getXWikiContext());
+        } catch (XWikiException e) {
+            e.printStackTrace();
+        } finally {
+            getXWikiContext().setDatabase(database);
+        }
+        return spaceNamesList;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see WysiwygService#getPageNames(String, String)
+     */
+    public List<String> getPageNames(String wikiName, String spaceName)
+    {
+        String database = getXWikiContext().getDatabase();
+        List<String> pagesFullNameList = null;
+        List<String> pagesNameList = new ArrayList<String>();
+        List<String> params = new ArrayList<String>();
+        params.add(spaceName);
+        String query = "where doc.space = ?";
+        try {
+            getXWikiContext().setDatabase(wikiName);
+            pagesFullNameList =
+                getXWikiContext().getWiki().getStore().searchDocumentsNames(query, params, getXWikiContext());
+
+        } catch (XWikiException e) {
+            e.printStackTrace();
+        } finally {
+            getXWikiContext().setDatabase(database);
+        }
+        if (pagesFullNameList != null) {
+            for (String p : pagesFullNameList) {
+                pagesNameList.add(p.substring(params.get(0).length() + 1));
+            }
+        }
+        return pagesNameList;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see WysiwygService#getAttachments(String)
+     */
+    public List<String> getAttachments(String wikiName, String pageName)
+    {
+        String database = getXWikiContext().getDatabase();
+        List<String> attachmentsList = new ArrayList<String>();
+        List<XWikiAttachment> xwikiAttachmentsList = new ArrayList<XWikiAttachment>();
+        try {
+            getXWikiContext().setDatabase(wikiName);
+            xwikiAttachmentsList =
+                getXWikiContext().getWiki().getDocument(pageName, getXWikiContext()).getAttachmentList();
+        } catch (XWikiException e) {
+            e.printStackTrace();
+        } finally {
+            getXWikiContext().setDatabase(database);
+        }
+        for (XWikiAttachment a : xwikiAttachmentsList) {
+            attachmentsList.add(a.getFilename());
+        }
+        return attachmentsList;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see WysiwygService#getHistory(String)
+     */
+    public List<String> getHistory(String wikiName, String pageName)
+    {
+        String database = getXWikiContext().getDatabase();
+        List<String> historyList = new ArrayList<String>();
+        Version[] versions = null;
+        try {
+            getXWikiContext().setDatabase(wikiName);
+            versions =
+                getXWikiContext().getWiki().getDocument(pageName, getXWikiContext()).getRevisions(getXWikiContext());
+        } catch (XWikiException e) {
+            e.printStackTrace();
+        } finally {
+            getXWikiContext().setDatabase(database);
+        }
+        for (int i = 0; i < versions.length; i++) {
+            historyList.add(versions[i].toString());
+        }
+
+        return historyList;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see WysiwygService#createPageURL(String, String, String, String)
+     */
+    public String createPageURL(String wikiName, String spaceName, String pageName, String revision, String anchor)
+    {
+        XWikiContext context = getXWikiContext();
+        String database = context.getDatabase();
+        String newPageName = pageName;
+        String newSpaceName = spaceName;
+        String pageURL = null;
+        try {
+            context.setDatabase(wikiName);
+            // if we have no page name, link to the WebHome of whatever space
+            if (newPageName == null || newPageName.length() == 0) {
+                newPageName = "WebHome";
+            }
+            // if we have no space, link to the current doc's space
+            if (newSpaceName == null && newSpaceName.length() == 0) {
+                if ((newPageName == null || newPageName.length() == 0) && wikiName != null && wikiName.length() > 0) {
+                    // if we have no space set and no page but we have a wiki, then create a link to the mainpage of the
+                    // wiki
+                    newSpaceName = "Main";
+                } else {
+                    newSpaceName = context.getDoc().getSpace();
+                }
+            }
+
+            XWikiDocument requestedDocument = context.getWiki().getDocument(newSpaceName + "." + newPageName, context);
+            pageURL = requestedDocument.getURL("view", context);
+            // if we have revision, get document with revision, otherwise get simple document
+            if (revision != null && revision.length() > 0) {
+                requestedDocument = context.getWiki().getDocument(newSpaceName + "." + newPageName, context);
+                pageURL = requestedDocument.getURL("viewrev", "rev=" + revision, context);
+            }
+            if (anchor != null && anchor.length() > 0) {
+                pageURL += "#" + anchor;
+            }
+        } catch (XWikiException e) {
+            e.printStackTrace();
+        } finally {
+            getXWikiContext().setDatabase(database);
+        }
+        return pageURL;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see WysiwygService#createAttachmentURL(String, String, String)
+     */
+    public String createAttachmentURL(String wikiName, String pageName, String fileName)
+    {
+        String database = getXWikiContext().getDatabase();
+        String attachmentURL = null;
+        try {
+            getXWikiContext().setDatabase(wikiName);
+            attachmentURL =
+                getXWikiContext().getWiki().getDocument(pageName, getXWikiContext()).getExternalAttachmentURL(fileName,
+                    "download", getXWikiContext());
+        } catch (XWikiException e) {
+            e.printStackTrace();
+        } finally {
+            getXWikiContext().setDatabase(database);
+        }
+        return attachmentURL;
+    }
 }
Index: src/main/java/com/xpn/xwiki/wysiwyg/client/WysiwygServiceAsync.java
===================================================================
--- src/main/java/com/xpn/xwiki/wysiwyg/client/WysiwygServiceAsync.java	(revision 13966)
+++ src/main/java/com/xpn/xwiki/wysiwyg/client/WysiwygServiceAsync.java	(working copy)
@@ -19,6 +19,8 @@
  */
 package com.xpn.xwiki.wysiwyg.client;
 
+import java.util.List;
+
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.xpn.xwiki.wysiwyg.client.diff.Revision;
 import com.xpn.xwiki.wysiwyg.client.sync.SyncResult;
@@ -66,4 +68,80 @@
      * @param async The callback to be used for notifying the caller after receiving the response from the server.
      */
     void syncEditorContent(Revision syncedRevision, String pageName, int version, AsyncCallback<SyncResult> async);
+
+    /**
+     * Check if the current wiki is a multiwiki.
+     * 
+     * @param async object used for asynchronous communication between server and client
+     */
+    void isMultiWiki(AsyncCallback<Boolean> async);
+
+    /**
+     * Returns a list containing the names of all wikis.
+     * 
+     * @param async async object used for asynchronous communication between server and client
+     */
+    void getVirtualWikiNames(AsyncCallback<List<String>> async);
+
+    /**
+     * Returns a list containing the names of all spaces from a given wiki.
+     * 
+     * @param wikiName the name of a certain wiki
+     * @param async object used for asynchronous communication between server and client
+     */
+    void getSpaceNames(String wikiName, AsyncCallback<List<String>> async);
+
+    /**
+     * Returns a list containing the names of all pages from a given space and from a certain wiki.
+     * 
+     * @param wikiName the name of the wiki
+     * @param spaceName the name of the space
+     * @param async object used for asynchronous communication between server and client
+     */
+    void getPageNames(String wikiName, String spaceName, AsyncCallback<List<String>> async);
+
+    /**
+     * Returns a list containing the names of all attachments from a given page and from a certain wiki.
+     * 
+     * @param wikiName the name of the wiki
+     * @param pageName the fullname of page
+     * @param async object used for asynchronous communication between server and client
+     */
+    void getAttachments(String wikiName, String pageName, AsyncCallback<List<String>> async);
+
+    /**
+     * Returns a list containing the names of all versions from a given page and from a certain wiki.
+     * 
+     * @param wikiName the name of the wiki
+     * @param pageName the fullname of the page
+     * @param async object used for asynchronous communication between server and client
+     */
+    void getHistory(String wikiName, String pageName, AsyncCallback<List<String>> async);
+
+    /**
+     * Creates a page url from the given parameters. None of them are mandatory, if one misses, it if replaced with a
+     * default value.
+     * 
+     * @param wikiName the name of the wiki to which to link
+     * @param spaceName the name of the space of the page. If this parameter is missing, it is replaced with the space
+     *            of the current document in the context.
+     * @param pageName the name of the page to which to link to. If it's missing, it is replaced with "WebHome".
+     * @param revision the value for the page revision to which to link to. If this is missing, the link is made to the
+     *            latest revision, the default view action for the document.
+     * @param anchor the name of the anchor type.
+     * @param async object used for asynchronous communication between server and client.
+     * @return the relative url to the resulted document.
+     */
+    void createPageURL(String wikiName, String spaceName, String pageName, String revision, String anchor,
+        AsyncCallback<String> async);
+    
+    /**
+     * Returns the external URL to an attachment from a given page and from a certain wiki.
+     * 
+     * @param wikiName the name of the wiki
+     * @param pageName the fullname of the page
+     * @param fileName the name of the attachment file
+     * @param async object used for asynchronous communication between server and client
+     */
+    void createAttachmentURL(String wikiName, String pageName, String fileName, AsyncCallback<String> async);
 }
Index: src/main/java/com/xpn/xwiki/wysiwyg/client/WysiwygService.java
===================================================================
--- src/main/java/com/xpn/xwiki/wysiwyg/client/WysiwygService.java	(revision 13966)
+++ src/main/java/com/xpn/xwiki/wysiwyg/client/WysiwygService.java	(working copy)
@@ -19,6 +19,8 @@
  */
 package com.xpn.xwiki.wysiwyg.client;
 
+import java.util.List;
+
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.user.client.rpc.RemoteService;
 import com.google.gwt.user.client.rpc.ServiceDefTarget;
@@ -95,4 +97,80 @@
      * @return The result of synchronizing this editor with others editing the same page.
      */
     SyncResult syncEditorContent(Revision syncedRevision, String pageName, int version);
+
+    /**
+     * Check if the current wiki is a multiwiki.
+     * 
+     * @return true if the current wiki is a multiwiki, and false in the other case
+     */
+    Boolean isMultiWiki();
+
+    /**
+     * Returns a list containing the names of all wikis.
+     * 
+     * @return the list of strings containing the wikis's names
+     */
+    List<String> getVirtualWikiNames();
+
+    /**
+     * Returns a list containing the names of all spaces from a given wiki.
+     * 
+     * @param wikiName the name of a certain wiki
+     * @return the list of strings containing the spaces's names
+     */
+    List<String> getSpaceNames(String wikiName);
+
+    /**
+     * Returns a list containing the names of all pages from a given space and from a certain wiki.
+     * 
+     * @param wikiName the name of the wiki
+     * @param spaceName the name of the space
+     * @return the list of strings containing the pages's names
+     */
+    List<String> getPageNames(String wikiName, String spaceName);
+
+    /**
+     * Returns a list containing the names of all attachments from a given page and from a certain wiki.
+     * 
+     * @param wikiName the name of the wiki
+     * @param pageName the fullname of page
+     * @return the list of strings containing the attachments's names
+     */
+    List<String> getAttachments(String wikiName, String pageName);
+
+    /**
+     * Returns a list containing the names of all versions from a given page and from a certain wiki.
+     * 
+     * @param wikiName the name of the wiki
+     * @param pageName the fullname of the page
+     * @return the list of strings containing the versions of a page
+     */
+    List<String> getHistory(String wikiName, String pageName);
+
+   
+    /**
+     * Creates a page url from the given parameters. None of them are mandatory, if one misses, it if replaced with a
+     * default value.
+     * 
+     * @param wikiName the name of the wiki to which to link
+     * @param spaceName the name of the space of the page. If this parameter is missing, it is replaced with the space
+     *            of the current document in the context.
+     * @param pageName the name of the page to which to link to. If it's missing, it is replaced with "WebHome".
+     * @param revision the value for the page revision to which to link to. If this is missing, the link is made to the
+     *            latest revision, the default view action for the document.
+     * @param anchor the name of the anchor type.
+     * @return the relative url to the resulted document.
+     */
+    String createPageURL(String wikiName, String spaceName, String pageName, String revision, String anchor);
+
+   
+    /**
+     * Returns the external URL to an attachment from a given page and from a certain wiki.
+     * 
+     * @param wikiName the name of the wiki
+     * @param pageName the fullname of the page
+     * @param fileName the name of the attachment file
+     * @return the URL of attachment
+     */
+    String createAttachmentURL(String wikiName, String pageName, String fileName);
 }
Index: src/main/java/com/xpn/xwiki/wysiwyg/client/WysiwygServiceAsyncCacheProxy.java
===================================================================
--- src/main/java/com/xpn/xwiki/wysiwyg/client/WysiwygServiceAsyncCacheProxy.java	(revision 13966)
+++ src/main/java/com/xpn/xwiki/wysiwyg/client/WysiwygServiceAsyncCacheProxy.java	(working copy)
@@ -19,6 +19,8 @@
  */
 package com.xpn.xwiki.wysiwyg.client;
 
+import java.util.List;
+
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.xpn.xwiki.wysiwyg.client.diff.Revision;
 import com.xpn.xwiki.wysiwyg.client.sync.SyncResult;
@@ -35,6 +37,10 @@
      */
     private final WysiwygServiceAsync service;
 
+    private Boolean isMultiWiki;
+
+    private List<String> virtualWikiNamesList;
+
     /**
      * Creates a new cache proxy for the given service.
      * 
@@ -70,8 +76,7 @@
      * 
      * @see WysiwygServiceAsync#syncEditorContent(Revision, String, int, AsyncCallback)
      */
-    public void syncEditorContent(Revision syncedRevision, String pageName, int version, 
-        AsyncCallback<SyncResult> async)
+    public void syncEditorContent(Revision syncedRevision, String pageName, int version, AsyncCallback<SyncResult> async)
     {
         service.syncEditorContent(syncedRevision, pageName, version, async);
     }
@@ -85,4 +90,117 @@
     {
         service.toHTML(source, syntax, async);
     }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see WysiwygServiceAsync#createAttachmentURL(String, String, String, AsyncCallback)
+     */
+    public void createAttachmentURL(String wikiName, String pageName, String fileName, AsyncCallback<String> async)
+    {
+        service.createAttachmentURL(wikiName, pageName, fileName, async);
+    }
+    
+    /**
+     * {@inheritDoc}
+     * 
+     * @see WysiwygServiceAsync#getAttachments(String, String, AsyncCallback)
+     */
+    public void getAttachments(String wikiName, String pageName, AsyncCallback<List<String>> async)
+    {
+        service.getAttachments(wikiName, pageName, async);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see WysiwygServiceAsync#getHistory(String, String, AsyncCallback)
+     */
+    public void getHistory(String wikiName, String pageName, AsyncCallback<List<String>> async)
+    {
+        service.getHistory(wikiName, pageName, async);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see WysiwygServiceAsync#getPageNames(String, String, AsyncCallback)
+     */
+    public void getPageNames(String wikiName, String spaceName, AsyncCallback<List<String>> async)
+    {
+        service.getPageNames(wikiName, spaceName, async);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see WysiwygServiceAsync#getSpaceNames(String, AsyncCallback)
+     */
+    public void getSpaceNames(String wikiName, AsyncCallback<List<String>> async)
+    {
+        service.getSpaceNames(wikiName, async);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see WysiwygServiceAsync#getVirtualWikiNames(AsyncCallback)
+     */
+    public void getVirtualWikiNames(final AsyncCallback<List<String>> async)
+    {
+        if (virtualWikiNamesList == null) {
+            service.getVirtualWikiNames(new AsyncCallback<List<String>>()
+            {
+                public void onFailure(Throwable caught)
+                {
+                    async.onFailure(caught);
+                }
+
+                public void onSuccess(List<String> result)
+                {
+                    virtualWikiNamesList = result;
+                    async.onSuccess(virtualWikiNamesList);
+                }
+            });
+        } else {
+            async.onSuccess(virtualWikiNamesList);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see WysiwygServiceAsync#isMultiWiki(AsyncCallback)
+     */
+    public void isMultiWiki(final AsyncCallback<Boolean> async)
+    {
+        if (isMultiWiki == null) {
+            service.isMultiWiki(new AsyncCallback<Boolean>()
+            {
+                public void onFailure(Throwable caught)
+                {
+                    async.onFailure(caught);
+                }
+
+                public void onSuccess(Boolean result)
+                {
+                    isMultiWiki = result;
+                    async.onSuccess(isMultiWiki);
+                }
+            });
+        } else {
+            async.onSuccess(isMultiWiki);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see WysiwygServiceAsync#createPageURL(String, String, String, String, String, AsyncCallback)
+     */
+    public void createPageURL(String wikiName, String spaceName, String pageName, String revision, String anchor,
+        AsyncCallback<String> async)
+    {
+        service.createPageURL(wikiName, spaceName, pageName, revision, anchor, async);
+    }
 }
Index: src/main/java/com/xpn/xwiki/wysiwyg/client/widget/rta/cmd/internal/DefaultCommandManager.java
===================================================================
--- src/main/java/com/xpn/xwiki/wysiwyg/client/widget/rta/cmd/internal/DefaultCommandManager.java	(revision 13966)
+++ src/main/java/com/xpn/xwiki/wysiwyg/client/widget/rta/cmd/internal/DefaultCommandManager.java	(working copy)
@@ -57,6 +57,7 @@
         EXECUTABLES = new HashMap<Command, Executable>();
         EXECUTABLES.put(Command.BACK_COLOR, (Executable) GWT.create(BackColorExecutable.class));
         EXECUTABLES.put(Command.BOLD, new BoldExecutable());
+        EXECUTABLES.put(Command.CREATE_LINK, new CreateLinkExecutable());
         EXECUTABLES.put(Command.FONT_NAME, new DefaultExecutable(Command.FONT_NAME.toString()));
         EXECUTABLES.put(Command.FONT_SIZE, new DefaultExecutable(Command.FONT_SIZE.toString()));
         EXECUTABLES.put(Command.FORE_COLOR, new DefaultExecutable(Command.FORE_COLOR.toString()));
Index: src/main/java/com/xpn/xwiki/wysiwyg/client/widget/rta/cmd/Command.java
===================================================================
--- src/main/java/com/xpn/xwiki/wysiwyg/client/widget/rta/cmd/Command.java	(revision 13966)
+++ src/main/java/com/xpn/xwiki/wysiwyg/client/widget/rta/cmd/Command.java	(working copy)
@@ -41,6 +41,12 @@
     public static final Command BOLD = new Command("bold");
 
     /**
+     * This command will not do anything if no selection is made. If there is a selection, a link will be inserted
+     * around the selection with the url parameter as the href of the link.
+     */
+    public static final Command CREATE_LINK = new Command("createlink");
+    
+    /**
      * This command will set the font face for a selection or at the insertion point if there is no selection.<br/>
      * The given string is such as would be used in the "name" attribute of the font tag.
      */
@@ -205,6 +211,12 @@
     public static final Command UNDO = new Command("undo");
 
     /**
+     * If the insertion point is within a link or if the current selection contains a link, the link will be removed and
+     * the text will remain.
+     */
+    public static final Command UNLINK = new Command("unlink");
+
+    /**
      * The name of the command. For predefined commands (supported by the built-in rich text editor, the one offered by
      * the browser) this is the name of the command execute with the native API. For the rest (custom commands) this is
      * just a string identifier.
Index: src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/LinkGenerator.java
===================================================================
--- src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/LinkGenerator.java	(revision 0)
+++ src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/LinkGenerator.java	(revision 0)
@@ -0,0 +1,221 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package com.xpn.xwiki.wysiwyg.client.plugin.link;
+
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.xpn.xwiki.wysiwyg.client.WysiwygService;
+
+public class LinkGenerator
+{
+    /**
+     * The singleton instance of this class.
+     */
+    private static LinkGenerator instance;
+
+    /**
+     * Class constructor, private so that the class is a singleton.
+     */
+    private LinkGenerator()
+    {
+    }
+
+    /**
+     * @return the instance of this class.
+     */
+    public static synchronized LinkGenerator getInstance()
+    {
+        if (instance == null) {
+            instance = new LinkGenerator();
+        }
+        return instance;
+    }
+
+    /**
+     * Generates link to an external url (web page or email address).
+     * 
+     * @param label link label
+     * @param externalURL external url to link to
+     * @return the html link block.
+     */
+    public String getExternalLink(String label, String externalURL)
+    {
+        // <!--startwikilink:http://xwiki.org-->
+        // <span class="wikiexternallink">
+        // <a href="http://xwiki.org">label</a>
+        // </span>
+        // <!--stopwikilink-->
+
+        // <!--startwikilink:mailto:john@doe.com-->
+        // <span class="wikiexternallink">
+        // <a href="mailto:john@doe.com">label</a>
+        // </span>
+        // <!--stopwikilink-->
+        return "<!--startwikilink:" + externalURL + "--><span class=\"wikiexternallink\"><a href=\"" + externalURL
+            + "\">" + label + "</a></span><!--stopwikilink-->";
+    }
+
+    /**
+     * Generates link to a new wiki page.
+     * 
+     * @param label link label
+     * @param wikiName wiki of the targeted page
+     * @param spaceName TODO
+     * @param async callback to handle async call on the caller side
+     * @param spaceName space of the targeted page
+     * @param pageName name of the targeted page
+     * @return the html link block.
+     */
+    public String getNewPageLink(final String label, String wikiName, final String spaceName, final String pageName,
+        final AsyncCallback<String> async)
+    {
+        // <!--startwikilink:Space.UnknownPage-->
+        // <span class="wikicreatelink">
+        // <a href="/xwiki/bin/view/Space/UnknownPage">
+        // <span class="wikicreatelinktext">label</span>
+        // <span class="wikicreatelinkqm">?</span>
+        // </a>
+        // </span>
+        // <!--stopwikilink-->
+
+        WysiwygService.Singleton.getInstance().createPageURL(wikiName, spaceName, pageName, null, null,
+            new AsyncCallback<String>()
+            {
+
+                public void onFailure(Throwable arg0)
+                {
+                    async.onFailure(arg0);
+                }
+
+                public void onSuccess(String result)
+                {
+                    String link =
+                        "<!--startwikilink:" + spaceName + "." + pageName
+                            + "--><span class=\"wikicreatelink\"><a href=\"" + result
+                            + "\"><span class=\"wikicreatelinktext\">" + label
+                            + "</span><span class=\"wikicreatelinkqm\">?</span></a></span><!--stopwikilink-->";
+                    async.onSuccess(link);
+                }
+            });
+        return "";
+    }
+
+    /**
+     * Generates link to an existing page.
+     * 
+     * @param label link label
+     * @param wikiName wiki of the targeted page
+     * @param spaceName space of the targeted page
+     * @param pageName name of the targeted page
+     * @param revision TODO
+     * @param anchor TODO
+     * @param async callback to handle async call on the caller side
+     * @return the html link block.
+     */
+    public String getExistingPageLink(final String label, String wikiName, final String spaceName,
+        final String pageName, String revision, String anchor, final AsyncCallback<String> async)
+    {
+        // <!--startwikilink:Space.ExistingPage--><span class="wikilink"><a
+        // href="/xwiki/bin/view/Space/ExistingPage">label</a></span><!--stopwikilink-->
+        final String reference;
+        if (spaceName == null && pageName == null) {
+            // is multiwiki
+            reference = wikiName + ":Main.WebHome";
+        } else if (pageName == null) {
+            // I don't know if it is multiwiki....
+            reference = spaceName + ".WebHome";
+        } else {
+            reference = spaceName + "." + pageName;
+        }
+        WysiwygService.Singleton.getInstance().createPageURL(wikiName, spaceName, pageName, revision, anchor,
+            new AsyncCallback<String>()
+            {
+                public void onFailure(Throwable arg0)
+                {
+                    async.onFailure(arg0);
+                }
+
+                public void onSuccess(String result)
+                {
+                    String link =
+                        "<!--startwikilink:" + getReferenceByUrl(result, reference)
+                            + "--><span class=\"wikilink\"><a href=\"" + result + "\">" + label
+                            + "</a></span><!--stopwikilink-->";
+                    async.onSuccess(link);
+                }
+            });
+        return "";
+    }
+
+    /**
+     * Create the reference adding at the end, if is necessary, the version or an anchor type.
+     * 
+     * @param url
+     * @param reference
+     * @return
+     */
+    private String getReferenceByUrl(String url, String reference)
+    {
+        String referenceWithParams = "";
+        if (url.indexOf("?") != -1) {
+            referenceWithParams = reference.concat(url.substring(url.indexOf("?")));
+        } else if (url.indexOf("#") != -1) {
+            referenceWithParams = reference.concat(url.substring(url.indexOf("#")));
+        }
+        if (referenceWithParams.length() == 0) {
+            return reference;
+        } else {
+            return referenceWithParams;
+        }
+    }
+
+    /**
+     * Generates link to an attachment of a document.
+     * 
+     * @param label link label
+     * @param wikiName wiki of the targeted attachment
+     * @param spaceName space of the targeted attachment
+     * @param pageName page of the targeted attachment
+     * @param attachmentName name of the targeted attachment
+     * @param async callback to handle async call on the caller side
+     * @return the html link block.
+     */
+    public String getAttachmentLink(final String label, String wikiName, final String spaceName, final String pageName,
+        final String attachmentName, final AsyncCallback<String> async)
+    {
+        WysiwygService.Singleton.getInstance().createAttachmentURL(wikiName, spaceName + "." + pageName,
+            attachmentName, new AsyncCallback<String>()
+            {
+                public void onFailure(Throwable caught)
+                {
+                    throw new RuntimeException(caught.getMessage());
+                }
+
+                public void onSuccess(String result)
+                {
+                    String link =
+                        "<!--startwikilink:" + spaceName + "." + pageName + "/" + attachmentName
+                            + "--><span class=\"wikilink\"><a href=\"" + result + "\">" + label
+                            + "</a></span><!--stopwikilink-->";
+                    async.onSuccess(link);
+                }
+            });
+        return "";
+    }
+}
Index: src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/LinkPlugin.java
===================================================================
--- src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/LinkPlugin.java	(revision 13966)
+++ src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/LinkPlugin.java	(working copy)
@@ -20,6 +20,7 @@
 package com.xpn.xwiki.wysiwyg.client.plugin.link;
 
 import com.google.gwt.user.client.ui.ClickListener;
+import com.google.gwt.user.client.ui.PopupPanel;
 import com.google.gwt.user.client.ui.PushButton;
 import com.google.gwt.user.client.ui.Widget;
 import com.xpn.xwiki.wysiwyg.client.Wysiwyg;
@@ -27,15 +28,51 @@
 import com.xpn.xwiki.wysiwyg.client.editor.Strings;
 import com.xpn.xwiki.wysiwyg.client.plugin.internal.AbstractPlugin;
 import com.xpn.xwiki.wysiwyg.client.plugin.internal.FocusWidgetUIExtension;
+import com.xpn.xwiki.wysiwyg.client.plugin.link.ui.LinkDialog;
 import com.xpn.xwiki.wysiwyg.client.util.Config;
+import com.xpn.xwiki.wysiwyg.client.widget.PopupListener;
+import com.xpn.xwiki.wysiwyg.client.widget.SourcesPopupEvents;
 import com.xpn.xwiki.wysiwyg.client.widget.rta.RichTextArea;
+import com.xpn.xwiki.wysiwyg.client.widget.rta.cmd.Command;
 
-public class LinkPlugin extends AbstractPlugin implements ClickListener
+/**
+ * Extends {@link com.xpn.xwiki.wysiwyg.client.plugin.internal.AbstractPlugin}.
+ * 
+ * @version $Id$
+ */
+public class LinkPlugin extends AbstractPlugin implements ClickListener, PopupListener
 {
+
+    /**
+     * The button from the toolbar for create a link.
+     */
     private PushButton link;
 
+    /**
+     * The button from the toolbar for destroy a link.
+     */
     private PushButton unlink;
 
+    /**
+     * The dialog for create a link.
+     */
+    private LinkDialog linkDialog;
+
+    /**
+     * The name of current wiki.
+     */
+    private String currentWiki;
+
+    /**
+     * The name of current space.
+     */
+    private String currentSpace;
+
+    /**
+     * The name of current page.
+     */
+    private String currentPage;
+
     private final FocusWidgetUIExtension toolBarExtension = new FocusWidgetUIExtension("toolbar");
 
     /**
@@ -47,15 +84,26 @@
     {
         super.init(wysiwyg, textArea, config);
 
-        link = new PushButton(Images.INSTANCE.link().createImage(), this);
-        link.setTitle(Strings.INSTANCE.link());
-        toolBarExtension.addFeature("link", link);
+        if (getTextArea().getCommandManager().isSupported(Command.CREATE_LINK)) {
+            link = new PushButton(Images.INSTANCE.link().createImage(), this);
+            link.setTitle(Strings.INSTANCE.link());
+            toolBarExtension.addFeature("link", link);
 
-        unlink = new PushButton(Images.INSTANCE.unlink().createImage(), this);
-        unlink.setTitle(Strings.INSTANCE.unlink());
-        toolBarExtension.addFeature("unlink", unlink);
+            currentWiki = config.getParameter("wiki", "xwiki");
+            currentSpace = config.getParameter("space", "Main");
+            currentPage = config.getParameter("page", "WebHome");
+        }
 
-        getUIExtensionList().add(toolBarExtension);
+        if (getTextArea().getCommandManager().isSupported(Command.UNLINK)) {
+            unlink = new PushButton(Images.INSTANCE.unlink().createImage(), this);
+            unlink.setTitle(Strings.INSTANCE.unlink());
+            toolBarExtension.addFeature("unlink", unlink);
+        }
+
+        if (toolBarExtension.getFeatures().length > 0) {
+            getTextArea().addClickListener(this);
+            getUIExtensionList().add(toolBarExtension);
+        }
     }
 
     /**
@@ -65,16 +113,29 @@
      */
     public void destroy()
     {
-        link.removeFromParent();
-        link.removeClickListener(this);
-        link = null;
+        if (link != null) {
+            link.removeFromParent();
+            link.removeClickListener(this);
+            link = null;
 
-        unlink.removeFromParent();
-        unlink.removeClickListener(this);
-        unlink = null;
+            if (linkDialog != null) {
+                linkDialog.hide();
+                linkDialog.removeFromParent();
+                linkDialog.removePopupListener(this);
+                linkDialog = null;
+            }
+        }
 
-        toolBarExtension.clearFeatures();
+        if (unlink != null) {
+            unlink.removeFromParent();
+            unlink.removeClickListener(this);
+            unlink = null;
+        }
 
+        if (toolBarExtension.getFeatures().length > 0) {
+            getTextArea().removeClickListener(this);
+            toolBarExtension.clearFeatures();
+        }
         super.destroy();
     }
 
@@ -86,19 +147,64 @@
     public void onClick(Widget sender)
     {
         if (sender == link) {
-            onLink();
+            onLink(true);
         } else if (sender == unlink) {
             onUnlink();
         }
     }
 
-    public void onLink()
+    /**
+     * If condition is true, the dialog is display, else gets the URL and create link to it.
+     * 
+     * @param show Condition.
+     */
+    public void onLink(boolean show)
     {
-        // TODO
+        if (show) {
+            getLinkDialog().center();
+            // use only the first range in the user selection
+            String linkLabel = getTextArea().getDocument().getSelection().getRangeAt(0).toHTML();
+            getLinkDialog().setLabelHTML(linkLabel);
+        } else {
+            String url = getLinkDialog().getLink();
+            if (url != null) {
+                getTextArea().getCommandManager().execute(Command.CREATE_LINK, url);
+            } else {
+                // We get here if the symbol picker has been closed by clicking the close button.
+                // In this case we return the focus to the text area.
+                getTextArea().setFocus(true);
+            }
+        }
     }
 
     public void onUnlink()
     {
-        // TODO
+        getTextArea().getCommandManager().execute(Command.UNLINK);
     }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see PopupListener#onPopupClosed(PopupPanel, boolean)
+     */
+    public void onPopupClosed(SourcesPopupEvents sender, boolean autoHide)
+    {
+        if (sender == getLinkDialog() && !autoHide) {
+            onLink(false);
+        }
+    }
+
+    /**
+     * We use lazy loading in case of the link dialog to optimize editor loading time.
+     * 
+     * @return the link dialog to be used for inserting the link.
+     */
+    private LinkDialog getLinkDialog()
+    {
+        if (linkDialog == null) {
+            linkDialog = new LinkDialog(currentWiki, currentSpace, currentPage);
+            linkDialog.addPopupListener(this);
+        }
+        return linkDialog;
+    }
 }
Index: src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkToExistingPageTab.java
===================================================================
--- src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkToExistingPageTab.java	(revision 0)
+++ src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkToExistingPageTab.java	(revision 0)
@@ -0,0 +1,615 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package com.xpn.xwiki.wysiwyg.client.plugin.link.ui;
+
+import java.util.List;
+
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.ChangeListener;
+import com.google.gwt.user.client.ui.ClickListener;
+import com.google.gwt.user.client.ui.ClickListenerCollection;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.ListBox;
+import com.google.gwt.user.client.ui.SourcesClickEvents;
+import com.google.gwt.user.client.ui.Widget;
+import com.xpn.xwiki.wysiwyg.client.WysiwygService;
+import com.xpn.xwiki.wysiwyg.client.editor.Strings;
+import com.xpn.xwiki.wysiwyg.client.plugin.link.LinkGenerator;
+
+/**
+ * Extends {@link com.google.gwt.user.client.ui.Composite}.
+ * 
+ * @version $Id$
+ */
+public class LinkToExistingPageTab extends Composite implements HasLink, ChangeListener, ClickListener
+{
+    /**
+     * A listener collection.
+     */
+    private final ClickListenerCollection clickListeners = new ClickListenerCollection();
+
+    /**
+     * The main panel of the composite.
+     */
+    private final FlowPanel mainPanel;
+
+    /**
+     * The panel with the information about wikis.
+     */
+    private final FlowPanel wikiPanel;
+
+    /**
+     * The panel with the information about spaces.
+     */
+    private final FlowPanel spacePanel;
+
+    /**
+     * The panel with the information about pages.
+     */
+    private final FlowPanel pagePanel;
+
+    /**
+     * The panel with the information about anchors.
+     */
+    private final FlowPanel anchorsPanel;
+
+    /**
+     * The panel with the information about a specific type of anchor.
+     */
+    private final FlowPanel anchorsTypePanel;
+
+    private final Label chooseAnchorsTypeLabel;
+
+    private final ListBox chooseWikiListBox;
+
+    private final ListBox chooseSpaceListBox;
+
+    private final ListBox choosePageListBox;
+
+    private final ListBox chooseAnchorListBox;
+
+    private final ListBox chooseAnchorsTypeListBox;
+
+    private final Button createLinkToWikiButton;
+
+    private final Button createLinkToSpaceButton;
+
+    private final Button createLinkToPageButton;
+
+    private final Button createLinkToAnchorButton;
+
+    private final Button createLinkToAnchorTypeButton;
+
+    private String url;
+
+    private String labelHTML;
+
+    private String spaceName;
+
+    private String pageName;
+
+    private String wikiName;
+
+    /**
+     * The name of current wiki.
+     */
+    private String currentWikiName;
+
+    /**
+     * Class constructor specifying name of current wiki.
+     * 
+     * @param currentWikiName the name of current wiki.
+     */
+    public LinkToExistingPageTab(String currentWikiName)
+    {
+        this.currentWikiName = currentWikiName;
+        wikiPanel = new FlowPanel();
+        spacePanel = new FlowPanel();
+        pagePanel = new FlowPanel();
+        anchorsPanel = new FlowPanel();
+        anchorsTypePanel = new FlowPanel();
+
+        createLinkToWikiButton = new Button(Strings.INSTANCE.linkCreateLinkButon());
+        createLinkToWikiButton.addClickListener(this);
+        createLinkToSpaceButton = new Button(Strings.INSTANCE.linkCreateLinkButon());
+        createLinkToSpaceButton.addClickListener(this);
+        createLinkToPageButton = new Button(Strings.INSTANCE.linkCreateLinkButon());
+        createLinkToPageButton.addClickListener(this);
+        createLinkToAnchorTypeButton = new Button(Strings.INSTANCE.linkCreateLinkButon());
+        createLinkToAnchorTypeButton.addClickListener(this);
+        createLinkToAnchorButton = new Button(Strings.INSTANCE.linkCreateLinkButon());
+        createLinkToAnchorButton.addClickListener(this);
+
+        chooseAnchorsTypeLabel = new Label();
+        chooseWikiListBox = new ListBox();
+        chooseWikiListBox.addChangeListener(this);
+        chooseWikiListBox.addKeyboardListener(new EnterListener(createLinkToWikiButton));
+        chooseSpaceListBox = new ListBox();
+        chooseSpaceListBox.addChangeListener(this);
+        chooseSpaceListBox.addKeyboardListener(new EnterListener(createLinkToSpaceButton));
+        choosePageListBox = new ListBox();
+        choosePageListBox.addChangeListener(this);
+        choosePageListBox.addKeyboardListener(new EnterListener(createLinkToPageButton));
+        chooseAnchorListBox = new ListBox();
+        chooseAnchorListBox.addChangeListener(this);
+        chooseAnchorListBox.addKeyboardListener(new EnterListener(createLinkToAnchorButton));
+        chooseAnchorsTypeListBox = new ListBox();
+        chooseAnchorsTypeListBox.addKeyboardListener(new EnterListener(createLinkToAnchorTypeButton));
+
+        mainPanel = new FlowPanel();
+        buildMainPanel();
+        initWidget(mainPanel);
+        addStyleName("xLinkToExistingPage");
+    }
+
+    /**
+     * Setter for value of field <i>labelHTML</i>.
+     * 
+     * @param label the new value for <i>labelHTML</i>
+     */
+    public void setLabelHTML(String label)
+    {
+        this.labelHTML = label;
+    }
+
+    /**
+     * Builds the panel with information about wiki.
+     */
+    private void buildWikiPanel()
+    {
+        Label chooseWikiLabel = new Label(Strings.INSTANCE.chooseWiki());
+        wikiPanel.add(chooseWikiLabel);
+        wikiPanel.add(chooseWikiListBox);
+        wikiPanel.add(createLinkToWikiButton);
+    }
+
+    /**
+     * Builds the panel with information about space.
+     */
+    private void buildSpacePanel()
+    {
+        Label chooseSpaceLabel = new Label(Strings.INSTANCE.chooseSpace());
+        spacePanel.add(chooseSpaceLabel);
+        spacePanel.add(chooseSpaceListBox);
+        spacePanel.add(createLinkToSpaceButton);
+    }
+
+    /**
+     * Builds the panel with information about page.
+     */
+    private void buildPagePanel()
+    {
+        Label choosePageLabel = new Label(Strings.INSTANCE.choosePage());
+        pagePanel.add(choosePageLabel);
+        pagePanel.add(choosePageListBox);
+        pagePanel.add(createLinkToPageButton);
+    }
+
+    /**
+     * Builds the panel with information about anchors.
+     */
+    private void buildAnchorsPanel()
+    {
+        Label chooseAnchorLabel = new Label(Strings.INSTANCE.chooseAnchor());
+        chooseAnchorListBox.addItem("Anchors...");
+        chooseAnchorListBox.addItem("Comments");
+        chooseAnchorListBox.addItem("Attachments");
+        chooseAnchorListBox.addItem("History");
+        chooseAnchorListBox.addItem("Information");
+        anchorsPanel.add(chooseAnchorLabel);
+        anchorsPanel.add(chooseAnchorListBox);
+        anchorsPanel.add(createLinkToAnchorButton);
+        createLinkToAnchorButton.setVisible(false);
+    }
+
+    /**
+     * Builds the panel with information about types of anchors.
+     */
+    private void buildAnchorsTypePanel()
+    {
+        anchorsTypePanel.add(chooseAnchorsTypeLabel);
+        anchorsTypePanel.add(chooseAnchorsTypeListBox);
+        anchorsTypePanel.add(createLinkToAnchorTypeButton);
+        anchorsTypePanel.setVisible(false);
+    }
+
+    /**
+     * Builds the main panel.
+     */
+    private void buildMainPanel()
+    {
+        buildWikiPanel();
+        buildSpacePanel();
+        buildPagePanel();
+        buildAnchorsPanel();
+        buildAnchorsTypePanel();
+
+        mainPanel.add(wikiPanel);
+        mainPanel.add(spacePanel);
+        mainPanel.add(pagePanel);
+        mainPanel.add(anchorsPanel);
+        mainPanel.add(anchorsTypePanel);
+    }
+
+    /**
+     * If the current wiki is multiwiki, the panel for wikis will be display.
+     * 
+     * @param isMultiwiki Is or not a wiki farm.
+     */
+    public void showWikis(boolean isMultiwiki)
+    {
+        if (!isMultiwiki) {
+            wikiPanel.setVisible(false);
+        }
+    }
+
+    /**
+     * Receive the wiki list, and populate the list box.
+     * 
+     * @param wikiList The list of all wikis.
+     */
+    public void populateWikiListBox(List<String> wikiList)
+    {
+        chooseWikiListBox.addItem(currentWikiName);
+        for (String s : wikiList) {
+            if (!s.equals(currentWikiName)) {
+                chooseWikiListBox.addItem(s);
+            }
+        }
+    }
+
+    /**
+     * Make a request to the server for all the spaces from a wiki, and populate the list box. When is need, the current
+     * space will be selected.
+     * 
+     * @param currentSpace The name of the current space.
+     */
+    public void populateSpaceListBox(final String currentSpace)
+    {
+        chooseSpaceListBox.clear();
+        WysiwygService.Singleton.getInstance().getSpaceNames(currentWikiName, new AsyncCallback<List<String>>()
+        {
+            public void onFailure(Throwable caught)
+            {
+                throw new RuntimeException(caught.getMessage());
+            }
+
+            public void onSuccess(List<String> result)
+            {
+                for (String s : result) {
+                    chooseSpaceListBox.addItem(s);
+                }
+                if (currentSpace != null) {
+                    int positionOfCurrentSpace = -1;
+                    for (int i = 0; i < chooseSpaceListBox.getItemCount(); i++) {
+                        if (chooseSpaceListBox.getItemText(i).equals(currentSpace)) {
+                            positionOfCurrentSpace = i;
+                        }
+                    }
+                    if (positionOfCurrentSpace != -1) {
+                        chooseSpaceListBox.setSelectedIndex(positionOfCurrentSpace);
+                    }
+                } else {
+                    populatePageListBox(chooseSpaceListBox.getItemText(0), null);
+                }
+            }
+        });
+    }
+
+    /**
+     * Make a request to the server for all the pages from a space, and populate the list box. When is need, the current
+     * page will be selected.
+     * 
+     * @param spaceName The name of the space.
+     * @param currentPage The name of the current page.
+     */
+    public void populatePageListBox(String spaceName, final String currentPage)
+    {
+        choosePageListBox.clear();
+
+        WysiwygService.Singleton.getInstance().getPageNames(currentWikiName, spaceName,
+            new AsyncCallback<List<String>>()
+            {
+                public void onFailure(Throwable caught)
+                {
+                    throw new RuntimeException(caught.getMessage());
+                }
+
+                public void onSuccess(List<String> result)
+                {
+                    for (String s : result) {
+                        choosePageListBox.addItem(s);
+                    }
+                    if (currentPage != null) {
+                        int positionOfCurrentPage = -1;
+                        for (int i = 0; i < choosePageListBox.getItemCount(); i++) {
+                            if (choosePageListBox.getItemText(i).equals(currentPage)) {
+                                positionOfCurrentPage = i;
+                            }
+                        }
+                        if (positionOfCurrentPage != -1) {
+                            choosePageListBox.setSelectedIndex(positionOfCurrentPage);
+                        }
+                    }
+                }
+            });
+    }
+
+    /**
+     * Make a request to the server for all the attachments from a page, and populate the list box.
+     * 
+     * @param pageName The name of the page.
+     */
+    public void populateAttachmentsListBox(String pageName)
+    {
+        WysiwygService.Singleton.getInstance().getAttachments(currentWikiName, pageName,
+            new AsyncCallback<List<String>>()
+            {
+                public void onFailure(Throwable caught)
+                {
+                    throw new RuntimeException(caught.getMessage());
+                }
+
+                public void onSuccess(List<String> result)
+                {
+                    chooseAnchorsTypeListBox.clear();
+                    for (String s : result) {
+                        chooseAnchorsTypeListBox.addItem(s);
+                    }
+                }
+            });
+    }
+
+    /**
+     * Make a request to the server for all the versions of a page, and populate the list box.
+     * 
+     * @param pageName The name of the page.
+     */
+    public void populateHistoryListBox(String pageName)
+    {
+        WysiwygService.Singleton.getInstance().getHistory(currentWikiName, pageName, new AsyncCallback<List<String>>()
+        {
+            public void onFailure(Throwable caught)
+            {
+                throw new RuntimeException(caught.getMessage());
+            }
+
+            public void onSuccess(List<String> result)
+            {
+                chooseAnchorsTypeListBox.clear();
+                for (String s : result) {
+                    chooseAnchorsTypeListBox.addItem(s);
+                }
+            }
+        });
+    }
+
+    /**
+     * Set the value for <i>url</i> field and notify the listeners.
+     * 
+     * @param url The url received from server.
+     */
+    public void getResponseFromServer(String url)
+    {
+        this.url = url;
+        clickListeners.fireClick(this);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see ClickListener#onClick(Widget)
+     */
+    public void onClick(Widget sender)
+    {
+        if (!wikiPanel.isVisible()) {
+            wikiName = currentWikiName;
+        } else {
+            wikiName = chooseWikiListBox.getItemText(chooseWikiListBox.getSelectedIndex());
+        }
+        spaceName = chooseSpaceListBox.getItemText(chooseSpaceListBox.getSelectedIndex());
+        pageName = choosePageListBox.getItemText(choosePageListBox.getSelectedIndex());
+        String version = null;
+        String anchor = null;
+
+        if (sender == createLinkToWikiButton) {
+            spaceName = null;
+            pageName = null;
+            version = null;
+            anchor = null;
+        } else if (sender == createLinkToPageButton) {
+            version = null;
+            anchor = null;
+        } else if (sender == createLinkToSpaceButton) {
+            pageName = null;
+            version = null;
+            anchor = null;
+        } else if (sender == createLinkToAnchorTypeButton) {
+            int index = chooseAnchorListBox.getSelectedIndex();
+            switch (index) {
+                case 2:
+                    LinkGenerator.getInstance().getAttachmentLink(labelHTML, wikiName, spaceName, pageName,
+                        chooseAnchorsTypeListBox.getItemText(chooseAnchorsTypeListBox.getSelectedIndex()),
+                        new AsyncCallback<String>()
+                        {
+
+                            public void onFailure(Throwable caught)
+                            {
+                                throw new RuntimeException(caught.getMessage());
+                            }
+
+                            public void onSuccess(String result)
+                            {
+                                getResponseFromServer(result);
+                                return;
+                            }
+                        });
+                    break;
+                case 3:
+                    version = chooseAnchorsTypeListBox.getItemText(chooseAnchorsTypeListBox.getSelectedIndex());
+                    anchor = null;
+                    break;
+                default:
+                    break;
+            }
+        } else if (sender == createLinkToAnchorButton) {
+            version = null;
+            anchor = chooseAnchorListBox.getItemText(chooseAnchorListBox.getSelectedIndex());
+        }
+        LinkGenerator.getInstance().getExistingPageLink(labelHTML, wikiName, spaceName, pageName, version, anchor,
+            new AsyncCallback<String>()
+            {
+                public void onFailure(Throwable caught)
+                {
+                    throw new RuntimeException(caught.getMessage());
+                }
+
+                public void onSuccess(String result)
+                {
+                    getResponseFromServer(result);
+                }
+            });
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see HasLink#getLink()
+     */
+    public String getLink()
+    {
+        return url;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see SourcesClickEvents#addClickListener(ClickListener)
+     */
+    public void addClickListener(ClickListener listener)
+    {
+        clickListeners.add(listener);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see SourcesClickEvents#removeClickListener(ClickListener)
+     */
+    public void removeClickListener(ClickListener listener)
+    {
+        clickListeners.remove(listener);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see ChangeListener#onChange(Widget)
+     */
+    public void onChange(Widget sender)
+    {
+        int selectedIndex;
+        String pageName =
+            chooseSpaceListBox.getItemText(chooseSpaceListBox.getSelectedIndex()) + "."
+                + choosePageListBox.getItemText(choosePageListBox.getSelectedIndex());
+        if (sender == chooseWikiListBox) {
+            selectedIndex = chooseWikiListBox.getSelectedIndex();
+            currentWikiName = chooseWikiListBox.getItemText(selectedIndex);
+            populateSpaceListBox(null);
+            populatePageListBox(chooseSpaceListBox.getItemText(0), null);
+
+        } else if (sender == chooseSpaceListBox) {
+            selectedIndex = chooseSpaceListBox.getSelectedIndex();
+            populatePageListBox(chooseSpaceListBox.getItemText(selectedIndex), null);
+
+        } else if (sender == choosePageListBox && anchorsTypePanel.isVisible()) {
+            selectedIndex = choosePageListBox.getSelectedIndex();
+            if (chooseAnchorListBox.getItemText(chooseAnchorListBox.getSelectedIndex()).equals("Attachments")) {
+                populateAttachmentsListBox(pageName);
+            } else {
+                populateHistoryListBox(pageName);
+            }
+
+        } else if (sender == chooseAnchorListBox) {
+            selectedIndex = chooseAnchorListBox.getSelectedIndex();
+            displayAnchorsTypePanel(selectedIndex, pageName);
+        }
+    }
+
+    /**
+     * Depending of what type of anchor was selected, the coresponding panel will be display.
+     * 
+     * @param selectedIndex index of what anchor was selected.
+     * @param pageName the name of page.
+     */
+    private void displayAnchorsTypePanel(int selectedIndex, String pageName)
+    {
+        switch (selectedIndex) {
+            case 0:
+                anchorsTypePanel.setVisible(false);
+                createLinkToAnchorButton.setVisible(false);
+                break;
+            case 1:
+            case 4:
+                anchorsTypePanel.setVisible(false);
+                createLinkToAnchorButton.setVisible(true);
+                break;
+            case 2:
+                populateAttachmentsListBox(pageName);
+                chooseAnchorsTypeLabel.setText(Strings.INSTANCE.chooseAttachment());
+                anchorsTypePanel.setVisible(true);
+                createLinkToAnchorButton.setVisible(true);
+                break;
+            case 3:
+                populateHistoryListBox(pageName);
+                chooseAnchorsTypeLabel.setText(Strings.INSTANCE.chooseVersion());
+                anchorsTypePanel.setVisible(true);
+                createLinkToAnchorButton.setVisible(true);
+                break;
+            default:
+                break;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see HasLink#setUp()
+     */
+    public void setUp()
+    {
+        url = null;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see HasLink#validateUserInput()
+     */
+    public boolean validateUserInput()
+    {
+        // TODO: all parameters for an existing page can be void, but not all at once. Check that doesn't happen
+        return true;
+    }
+}
Index: src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkToWebPageTab.java
===================================================================
--- src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkToWebPageTab.java	(revision 0)
+++ src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkToWebPageTab.java	(revision 0)
@@ -0,0 +1,173 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package com.xpn.xwiki.wysiwyg.client.plugin.link.ui;
+
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.ClickListener;
+import com.google.gwt.user.client.ui.ClickListenerCollection;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.KeyboardListenerAdapter;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.SourcesClickEvents;
+import com.google.gwt.user.client.ui.TextBox;
+import com.google.gwt.user.client.ui.Widget;
+import com.xpn.xwiki.wysiwyg.client.editor.Strings;
+import com.xpn.xwiki.wysiwyg.client.plugin.link.LinkGenerator;
+
+/**
+ * Extends {@link com.google.gwt.user.client.ui.Composite}.
+ * 
+ * @version $Id$
+ */
+public class LinkToWebPageTab extends Composite implements HasLink, ClickListener
+{
+    private final ClickListenerCollection clickListeners = new ClickListenerCollection();
+
+    /**
+     * The text box where the user will introduce the address of the web page.
+     */
+    private final TextBox urlTextBox;
+
+    private final Button createLinkButton;
+
+    private String labelHTML;
+
+    private String link;
+
+    /**
+     * Class constructor.
+     */
+    public LinkToWebPageTab()
+    {
+        Label infoLabel = new Label(Strings.INSTANCE.linkWebPageLabel());
+        createLinkButton = new Button(Strings.INSTANCE.linkCreateLinkButon());
+        createLinkButton.addClickListener(this);
+
+        EnterListener enterListener = new EnterListener(createLinkButton);
+        urlTextBox = new TextBox();
+        urlTextBox.setText(Strings.INSTANCE.linkWebPageTextBox());
+        urlTextBox.addClickListener(this);
+        urlTextBox.addKeyboardListener(enterListener);
+
+        FlowPanel mainPanel = new FlowPanel();
+        mainPanel.addStyleName("xLinkToUrl");
+        mainPanel.add(infoLabel);
+        mainPanel.add(urlTextBox);
+        mainPanel.add(createLinkButton);
+        initWidget(mainPanel);
+    }
+
+    /**
+     * Setter for value of field <i>labelHTML</i>.
+     * 
+     * @param label the new value for <i>labelHTML</i>
+     */
+    public void setLabelHTML(String label)
+    {
+        this.labelHTML = label;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see ClickListener#onClick(Widget)
+     */
+    public void onClick(Widget sender)
+    {
+        if (sender == createLinkButton) {
+            String url;
+            String webPageAddress = urlTextBox.getText();
+            if (!validateUserInput()) {
+                url = null;
+            } else {
+                // check if any protocol is use
+                if (webPageAddress.contains("://")) {
+                    url = webPageAddress;
+                } else {
+                    url = "http://" + webPageAddress;
+                }
+                link = LinkGenerator.getInstance().getExternalLink(labelHTML, url);
+                clickListeners.fireClick(this);
+            }
+        }
+        if (sender == urlTextBox) {
+            urlTextBox.setText("");
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see SourcesClickEvents#addClickListener(ClickListener)
+     */
+    public void addClickListener(ClickListener listener)
+    {
+        clickListeners.add(listener);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see SourcesClickEvents#removeClickListener(ClickListener)
+     */
+    public void removeClickListener(ClickListener listener)
+    {
+        clickListeners.remove(listener);
+    }
+
+    /**
+     * @return the url give by user.
+     */
+    public String getLink()
+    {
+        return link;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see HasLink#setUp()
+     */
+    public void setUp()
+    {
+        urlTextBox.setText(Strings.INSTANCE.linkWebPageTextBox());
+        urlTextBox.setFocus(true);
+        urlTextBox.selectAll();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see HasLink#validateUserInput()
+     */
+    public boolean validateUserInput()
+    {
+        // The url inserted by the user must not be void. Check that
+        if (this.urlTextBox.getText().trim().length() == 0
+            || this.urlTextBox.getText().equals(Strings.INSTANCE.linkWebPageTextBox())) {
+            Window.alert(Strings.INSTANCE.linkWebPageAddressError());
+            return false;
+        }
+        return true;
+    }
+}
Index: src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/EnterListener.java
===================================================================
--- src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/EnterListener.java	(revision 0)
+++ src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/EnterListener.java	(revision 0)
@@ -0,0 +1,60 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package com.xpn.xwiki.wysiwyg.client.plugin.link.ui;
+
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.KeyboardListenerAdapter;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * Extends {@link com.google.gwt.user.client.ui.KeyboardListenerAdapter}.
+ * 
+ * @version $Id$
+ */
+public class EnterListener extends KeyboardListenerAdapter
+{
+    /**
+     * The button which will be click when enter key will be press.
+     */
+    private Button button;
+
+    /**
+     * Class constructor.
+     * 
+     * @param button which will be click when enter key will be press.
+     */
+    public EnterListener(Button button)
+    {
+        this.button = button;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see KeyboardListenerAdapter#onKeyPress(Widget, char, int)
+     */
+    public void onKeyPress(Widget sender, char c, int i)
+    {
+        super.onKeyPress(sender, c, i);
+        if (c == 13) {
+            button.click();
+        }
+    }
+}
Index: src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkToEmailAddressTab.java
===================================================================
--- src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkToEmailAddressTab.java	(revision 0)
+++ src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkToEmailAddressTab.java	(revision 0)
@@ -0,0 +1,176 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package com.xpn.xwiki.wysiwyg.client.plugin.link.ui;
+
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.ClickListener;
+import com.google.gwt.user.client.ui.ClickListenerCollection;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.KeyboardListenerAdapter;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.SourcesClickEvents;
+import com.google.gwt.user.client.ui.TextBox;
+import com.google.gwt.user.client.ui.Widget;
+import com.xpn.xwiki.wysiwyg.client.editor.Strings;
+import com.xpn.xwiki.wysiwyg.client.plugin.link.LinkGenerator;
+
+/**
+ * Extends {@link com.google.gwt.user.client.ui.Composite}.
+ * 
+ * @version $Id$
+ */
+public class LinkToEmailAddressTab extends Composite implements HasLink, ClickListener
+{
+    private static final String MAILTO = "mailto:";
+
+    private final ClickListenerCollection clickListeners = new ClickListenerCollection();
+
+    /**
+     * The text box where the user will introduce the address of the web page.
+     */
+    private final TextBox urlTextBox;
+
+    private final Button createLinkButton;
+
+    private String labelHTML;
+
+    private String link;
+
+    /**
+     * Class constructor.
+     */
+    public LinkToEmailAddressTab()
+    {
+        Label infoLabel = new Label(Strings.INSTANCE.linkEmailLabel());
+        createLinkButton = new Button(Strings.INSTANCE.linkCreateLinkButon());
+        createLinkButton.addClickListener(this);
+
+        EnterListener enterListener = new EnterListener(createLinkButton);
+        urlTextBox = new TextBox();
+        urlTextBox.setText(Strings.INSTANCE.linkEmailAddressTextBox());
+        urlTextBox.addClickListener(this);
+        urlTextBox.addKeyboardListener(enterListener);
+
+        FlowPanel mainPanel = new FlowPanel();
+        mainPanel.addStyleName("xLinkToUrl");
+        mainPanel.add(infoLabel);
+        mainPanel.add(urlTextBox);
+        mainPanel.add(createLinkButton);
+
+        initWidget(mainPanel);
+    }
+
+    /**
+     * Setter for value of field <i>labelHTML</i>.
+     * 
+     * @param label the new value for <i>labelHTML</i>
+     */
+    public void setLabelHTML(String label)
+    {
+        this.labelHTML = label;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see ClickListener#onClick(Widget)
+     */
+    public void onClick(Widget sender)
+    {
+        if (sender == createLinkButton) {
+            // try to create the link and close the dialog. Fail if the input does not validate
+            String url;
+            String emailAddress = urlTextBox.getText();
+            if (!validateUserInput()) {
+                url = null;
+            } else {
+                if (emailAddress.startsWith(MAILTO)) {
+                    url = emailAddress;
+                } else {
+                    url = MAILTO + emailAddress;
+                }
+                this.link = LinkGenerator.getInstance().getExternalLink(labelHTML, url);
+                clickListeners.fireClick(this);
+            }
+        }
+        if (sender == urlTextBox) {
+            urlTextBox.setText("");
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see SourcesClickEvents#addClickListener(ClickListener)
+     */
+    public void addClickListener(ClickListener listener)
+    {
+        clickListeners.add(listener);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see SourcesClickEvents#removeClickListener(ClickListener)
+     */
+    public void removeClickListener(ClickListener listener)
+    {
+        clickListeners.remove(listener);
+    }
+
+    /**
+     * @return the email address give by user.
+     */
+    public String getLink()
+    {
+        return link;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see HasLink#setUp()
+     */
+    public void setUp()
+    {
+        urlTextBox.setText(Strings.INSTANCE.linkEmailAddressTextBox());
+        urlTextBox.setFocus(true);
+        urlTextBox.selectAll();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see HasLink#validateUserInput()
+     */
+    public boolean validateUserInput()
+    {
+        // the email address must not be void. Check if this happens
+        if (this.urlTextBox.getText().trim().length() == 0
+            || this.urlTextBox.getText().equals(Strings.INSTANCE.linkEmailAddressTextBox())) {
+            Window.alert(Strings.INSTANCE.linkEmailAddressError());
+            return false;
+        }
+        return true;
+    }
+}
Index: src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/HasLink.java
===================================================================
--- src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/HasLink.java	(revision 0)
+++ src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/HasLink.java	(revision 0)
@@ -0,0 +1,49 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package com.xpn.xwiki.wysiwyg.client.plugin.link.ui;
+
+import com.google.gwt.user.client.ui.SourcesClickEvents;
+
+/**
+ * Interface for widgets that return a link html block from user input and are clickable.
+ * 
+ * @version $Id$
+ */
+public interface HasLink extends SourcesClickEvents
+{
+    /**
+     * Returns the link html block to use with the <i>create_link</i> command.
+     * 
+     * @return the link html block
+     */
+    String getLink();
+
+    /**
+     * Some setup need for the moment when the widget will be display.
+     */
+    void setUp();
+
+    /**
+     * Validates the user input for this widget, to be used for validation before the link is created / returned. 
+     * 
+     * @return true if the user input for this widget is valid, false otherwise.
+     */
+    boolean validateUserInput();
+}
Index: src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkDialog.java
===================================================================
--- src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkDialog.java	(revision 0)
+++ src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkDialog.java	(revision 0)
@@ -0,0 +1,251 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package com.xpn.xwiki.wysiwyg.client.plugin.link.ui;
+
+import java.util.List;
+
+import com.google.gwt.user.client.DeferredCommand;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwt.user.client.ui.ClickListener;
+import com.google.gwt.user.client.ui.SourcesTabEvents;
+import com.google.gwt.user.client.ui.TabListener;
+import com.google.gwt.user.client.ui.TabPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.xpn.xwiki.wysiwyg.client.WysiwygService;
+import com.xpn.xwiki.wysiwyg.client.editor.Strings;
+import com.xpn.xwiki.wysiwyg.client.widget.CompositeDialogBox;
+
+/**
+ * Extends {@link com.xpn.xwiki.wysiwyg.client.widget.CompositeDialogBox}.
+ * 
+ * @version $Id$
+ */
+public class LinkDialog extends CompositeDialogBox implements ClickListener, TabListener
+{
+    private class SelectCommand implements com.google.gwt.user.client.Command
+    {
+        public void execute()
+        {
+            tabs.selectTab(selectedTabIndex);
+        }
+    }
+
+    private final TabPanel tabs;
+
+    private final LinkToWebPageTab linkToWebPageTab;
+
+    private final LinkToEmailAddressTab linkToEmailAddressTab;
+
+    private final LinkToNewPageTab linkToNewPageTab;
+
+    private final LinkToExistingPageTab linkToExistingPageTab;
+
+    /**
+     * This variable contains the index of the selected tab.
+     */
+    private int selectedTabIndex;
+
+    /**
+     * True if the dialog is close by the close button, and false if the dialog is close by <i>Create link</i> button.
+     */
+    private boolean closeByCreateLink;
+
+    /**
+     * Store the value of the label to create this link for.
+     */
+    private String labelHTML;
+
+    /**
+     * @param currentWiki The name of current wiki.
+     * @param currentSpace The name of current space.
+     * @param currentPage The name of current page.
+     */
+    public LinkDialog(final String currentWiki, String currentSpace, String currentPage)
+    {
+        super(false, true);
+        linkToWebPageTab = new LinkToWebPageTab();
+        linkToEmailAddressTab = new LinkToEmailAddressTab();
+        linkToNewPageTab = new LinkToNewPageTab(currentWiki);
+        linkToExistingPageTab = new LinkToExistingPageTab(currentWiki);
+
+        WysiwygService.Singleton.getInstance().isMultiWiki(new AsyncCallback<Boolean>()
+        {
+            public void onFailure(Throwable caught)
+            {
+                throw new RuntimeException(caught.getMessage());
+            }
+
+            public void onSuccess(Boolean result)
+            {
+                linkToNewPageTab.showWikis(result);
+                linkToExistingPageTab.showWikis(result);
+                if (result) {
+                    getWikiNamesList(currentWiki);
+                }
+            }
+        });
+
+        linkToNewPageTab.populateSpaceListBox(currentSpace);
+        linkToExistingPageTab.populateSpaceListBox(currentSpace);
+        linkToExistingPageTab.populatePageListBox(currentSpace, currentPage);
+
+        tabs = new TabPanel();
+        tabs.addTabListener(this);
+
+        addTab(linkToWebPageTab, Strings.INSTANCE.linkWebPageTab());
+        addTab(linkToEmailAddressTab, Strings.INSTANCE.linkEmailTab());
+        addTab(linkToNewPageTab, Strings.INSTANCE.linkNewPageTab());
+        addTab(linkToExistingPageTab, Strings.INSTANCE.linkExistingPageTab());
+
+        tabs.selectTab(0);
+        selectedTabIndex = 0;
+
+        getDialog().setText(Strings.INSTANCE.link());
+        getDialog().setAnimationEnabled(false);
+        getDialog().addStyleName("linkDialog");
+
+        initWidget(tabs);
+
+        // set the initial label HTML to void string, as if no selection was made.
+        setLabelHTML("");
+    }
+
+    public void setLabelHTML(String label)
+    {
+        this.labelHTML = label;
+        if (linkToWebPageTab != null) {
+            linkToWebPageTab.setLabelHTML(label);
+        }
+        if (linkToEmailAddressTab != null) {
+            linkToEmailAddressTab.setLabelHTML(label);
+        }
+        if (linkToNewPageTab != null) {
+            linkToNewPageTab.setLabelHTML(label);
+        }
+        if (linkToExistingPageTab != null) {
+            linkToExistingPageTab.setLabelHTML(label);
+        }
+    }
+
+    /**
+     * Call the service for obtaining the list of wiki names.
+     * 
+     * @param currentWiki The name of current Wiki.
+     */
+    private void getWikiNamesList(final String currentWiki)
+    {
+        WysiwygService.Singleton.getInstance().getVirtualWikiNames(new AsyncCallback<List<String>>()
+        {
+            public void onFailure(Throwable caught)
+            {
+                throw new RuntimeException(caught.getMessage());
+            }
+
+            public void onSuccess(List<String> result)
+            {
+                linkToNewPageTab.populateWikiListBox(result);
+                linkToExistingPageTab.populateWikiListBox(result);
+            }
+        });
+    }
+
+    /**
+     * @param content Widget that would be add in tab.
+     * @param tabName The name of the tab.
+     */
+    private void addTab(Widget content, String tabName)
+    {
+        if (content instanceof HasLink) {
+            tabs.add(content, tabName);
+            ((HasLink) content).addClickListener(this);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see ClickListener#onClick(Widget)
+     */
+    public void onClick(Widget sender)
+    {
+        if (sender instanceof HasLink) {
+            closeByCreateLink = true;
+            hide();
+        }
+    }
+
+    /**
+     * @return the url from the selected tab.
+     */
+    public String getLink()
+    {
+        if (closeByCreateLink) {
+            closeByCreateLink = false;
+            return getSelectedTab().getLink();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see TabListener#onBeforeTabSelected(SourcesTabEvents, int)
+     */
+    public boolean onBeforeTabSelected(SourcesTabEvents sender, int tabIndex)
+    {
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see TabListener#onTabSelected(SourcesTabEvents, int)
+     */
+    public void onTabSelected(SourcesTabEvents sender, int tabIndex)
+    {
+        if (sender == tabs) {
+            selectedTabIndex = tabIndex;
+            getSelectedTab().setUp();
+        }
+    }
+
+    /**
+     * Gets the widget from the tab corresponding with the selected index.
+     * 
+     * @return the widget from the current tab.
+     */
+    private HasLink getSelectedTab()
+    {
+        return (HasLink) tabs.getWidget(selectedTabIndex);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see CompositeDialog#center()
+     */
+    public void center()
+    {
+        super.center();
+        DeferredCommand.addCommand(new SelectCommand());
+    }
+}
Index: src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkToNewPageTab.java
===================================================================
--- src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkToNewPageTab.java	(revision 0)
+++ src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkToNewPageTab.java	(revision 0)
@@ -0,0 +1,347 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package com.xpn.xwiki.wysiwyg.client.plugin.link.ui;
+
+import java.util.List;
+
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.ChangeListener;
+import com.google.gwt.user.client.ui.ClickListener;
+import com.google.gwt.user.client.ui.ClickListenerCollection;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.KeyboardListenerAdapter;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.ListBox;
+import com.google.gwt.user.client.ui.SourcesClickEvents;
+import com.google.gwt.user.client.ui.TextBox;
+import com.google.gwt.user.client.ui.Widget;
+import com.xpn.xwiki.wysiwyg.client.WysiwygService;
+import com.xpn.xwiki.wysiwyg.client.editor.Strings;
+import com.xpn.xwiki.wysiwyg.client.plugin.link.LinkGenerator;
+
+/**
+ * Extends {@link com.google.gwt.user.client.ui.Composite}.
+ * 
+ * @version $Id$
+ */
+public class LinkToNewPageTab extends Composite implements HasLink, ChangeListener, ClickListener
+{
+    private final Label chooseWikiLabel = new Label(Strings.INSTANCE.chooseWiki());
+
+    private final Label chooseSpaceLabel = new Label(Strings.INSTANCE.chooseSpace());
+
+    private final Label newSpaceLabel = new Label(Strings.INSTANCE.linkNewSpaceLabel());
+
+    private final Label newPageLabel = new Label(Strings.INSTANCE.linkNewPageLabel());
+
+    private final ClickListenerCollection clickListeners = new ClickListenerCollection();
+
+    private final FlowPanel mainPanel;
+
+    private final FlowPanel spacePanel;
+
+    private final FlowPanel newSpacePanel;
+
+    private final FlowPanel newPagePanel;
+
+    private final FlowPanel wikiPanel;
+
+    private final ListBox chooseWikiListBox;
+
+    private final ListBox chooseSpaceListBox;
+
+    private final TextBox newSpaceNameTextBox;
+
+    private final TextBox newPageNameTextBox;
+
+    private final Button createLinkButton;
+
+    private String link;
+
+    private String labelHTML;
+
+    private String currentWikiName;
+
+    private String spaceName;
+
+    private String pageName;
+
+    /**
+     * Class constructor specifying name of current wiki.
+     * 
+     * @param currentWikiName the name of current wiki.
+     */
+    public LinkToNewPageTab(String currentWikiName)
+    {
+        this.currentWikiName = currentWikiName;
+        wikiPanel = new FlowPanel();
+        spacePanel = new FlowPanel();
+        newSpacePanel = new FlowPanel();
+        newSpacePanel.setVisible(false);
+        newPagePanel = new FlowPanel();
+
+        chooseWikiListBox = new ListBox();
+        chooseWikiListBox.addChangeListener(this);
+        chooseSpaceListBox = new ListBox();
+        chooseSpaceListBox.addChangeListener(this);
+        newSpaceNameTextBox = new TextBox();
+        newSpaceNameTextBox.setText(Strings.INSTANCE.linkNewSpaceTextBox());
+        newSpaceNameTextBox.addClickListener(this);
+
+        createLinkButton = new Button(Strings.INSTANCE.linkCreateLinkButon(), this);
+        newPageNameTextBox = new TextBox();
+        newPageNameTextBox.setText(Strings.INSTANCE.linkNewPageTextBox());
+        newPageNameTextBox.addClickListener(this);
+        newPageNameTextBox.addKeyboardListener(new EnterListener(createLinkButton));
+
+        wikiPanel.add(chooseWikiLabel);
+        wikiPanel.add(chooseWikiListBox);
+
+        spacePanel.add(chooseSpaceLabel);
+        spacePanel.add(chooseSpaceListBox);
+
+        newSpacePanel.add(newSpaceLabel);
+        newSpacePanel.add(newSpaceNameTextBox);
+
+        newPagePanel.add(newPageLabel);
+        newPagePanel.add(newPageNameTextBox);
+        newPagePanel.add(createLinkButton);
+
+        mainPanel = new FlowPanel();
+        buildMainPanel();
+        initWidget(mainPanel);
+        addStyleName("xLinkToNewPage");
+    }
+
+    /**
+     * Set the value of <i>labelHtml</i> variable.
+     * 
+     * @param label the new value for labelHTML
+     */
+    public void setLabelHTML(String label)
+    {
+        this.labelHTML = label;
+    }
+
+    /**
+     * Build the main panel.
+     */
+    private void buildMainPanel()
+    {
+        mainPanel.add(wikiPanel);
+        mainPanel.add(spacePanel);
+        mainPanel.add(newSpacePanel);
+        mainPanel.add(newPagePanel);
+    }
+
+    /**
+     * If the current wiki is multiwiki, the panel for wikis will be display.
+     * 
+     * @param isMultiwiki Is or not a wiki farm.
+     */
+    public void showWikis(boolean isMultiwiki)
+    {
+        if (!isMultiwiki) {
+            wikiPanel.setVisible(false);
+        }
+    }
+
+    /**
+     * Receive the wiki list, and populate the list box.
+     * 
+     * @param wikiList The list of all wikis.
+     */
+    public void populateWikiListBox(List<String> wikiList)
+    {
+        chooseWikiListBox.addItem(currentWikiName);
+        for (String s : wikiList) {
+            if (!s.equals(currentWikiName)) {
+                chooseWikiListBox.addItem(s);
+            }
+        }
+    }
+
+    /**
+     * Make a request to the server for all the spaces from a wiki, and populate the list box. When is need, the current
+     * space will be selected.
+     * 
+     * @param currentSpace The name of the current space.
+     */
+    public void populateSpaceListBox(final String currentSpace)
+    {
+        chooseSpaceListBox.clear();
+        WysiwygService.Singleton.getInstance().getSpaceNames(currentWikiName, new AsyncCallback<List<String>>()
+        {
+            public void onFailure(Throwable caught)
+            {
+                throw new RuntimeException(caught.getMessage());
+            }
+
+            public void onSuccess(List<String> result)
+            {
+                chooseSpaceListBox.addItem(Strings.INSTANCE.linkCreateNewSpaceText());
+                for (String s : result) {
+                    chooseSpaceListBox.addItem(s);
+                }
+                if (currentSpace != null) {
+                    int positionOfCurrentSpace = -1;
+                    for (int i = 0; i < chooseSpaceListBox.getItemCount(); i++) {
+                        if (chooseSpaceListBox.getItemText(i).equals(currentSpace)) {
+                            positionOfCurrentSpace = i;
+                        }
+                    }
+                    if (positionOfCurrentSpace != -1) {
+                        chooseSpaceListBox.setSelectedIndex(positionOfCurrentSpace);
+                    }
+                }
+            }
+        });
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see ClickListener#onClick(Widget)
+     */
+    public void onClick(Widget sender)
+    {
+        if (sender == createLinkButton) {
+            if (newPageNameTextBox.getText().equals(Strings.INSTANCE.linkNewPageTextBox())) {
+                pageName = "";
+            } else {
+                pageName = newPageNameTextBox.getText();
+            }
+            if (chooseSpaceListBox.getSelectedIndex() != 0) {
+                spaceName = chooseSpaceListBox.getItemText(chooseSpaceListBox.getSelectedIndex());
+            } else if (newSpaceNameTextBox.getText().equals(Strings.INSTANCE.linkNewSpaceTextBox())) {
+                spaceName = "";
+            } else {
+                spaceName = newSpaceNameTextBox.getText();
+            }
+
+            if (validateUserInput()) {
+                LinkGenerator.getInstance().getNewPageLink(labelHTML, currentWikiName, spaceName, pageName,
+                    new AsyncCallback<String>()
+                    {
+                        public void onFailure(Throwable caught)
+                        {
+                            throw new RuntimeException(caught.getMessage());
+                        }
+
+                        public void onSuccess(String result)
+                        {
+                            link = result;
+                            clickListeners.fireClick(LinkToNewPageTab.this);
+                        }
+                    });
+            }
+        } else if (sender == newSpaceNameTextBox) {
+            newSpaceNameTextBox.setText("");
+        } else if (sender == newPageNameTextBox) {
+            newPageNameTextBox.setText("");
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see SourcesClickEvents#addClickListener(ClickListener)
+     */
+    public void addClickListener(ClickListener listener)
+    {
+        clickListeners.add(listener);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see SourcesClickEvents#removeClickListener(ClickListener)
+     */
+    public void removeClickListener(ClickListener listener)
+    {
+        clickListeners.remove(listener);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see ChangeListener#onChange(Widget)
+     */
+    public void onChange(Widget sender)
+    {
+        if (sender == chooseWikiListBox) {
+            int selectedIndex = chooseWikiListBox.getSelectedIndex();
+            currentWikiName = chooseWikiListBox.getItemText(selectedIndex);
+            populateSpaceListBox(null);
+        }
+        if (sender == chooseSpaceListBox && chooseSpaceListBox.getSelectedIndex() == 0) {
+            newSpacePanel.setVisible(true);
+        } else {
+            newSpacePanel.setVisible(false);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see HasLink#getLink()
+     */
+    public String getLink()
+    {
+        return link;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see HasLink#setUp()
+     */
+    public void setUp()
+    {
+        link = null;
+        newPageNameTextBox.setText(Strings.INSTANCE.linkNewPageTextBox());
+        newPageNameTextBox.setFocus(true);
+        newPageNameTextBox.selectAll();
+        newSpaceNameTextBox.setText(Strings.INSTANCE.linkNewSpaceTextBox());
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see HasLink#validateUserInput()
+     */
+    public boolean validateUserInput()
+    {
+        if (pageName.trim().length() == 0) {
+            Window.alert(Strings.INSTANCE.linkNewPageError());
+            return false;
+        } else {
+            if (spaceName.trim().length() == 0) {
+                Window.alert(Strings.INSTANCE.linkNewSpaceError());
+                return false;
+            }
+        }
+        return true;
+    }
+}
Index: src/main/resources/com/xpn/xwiki/wysiwyg/public/Wysiwyg.css
===================================================================
--- src/main/resources/com/xpn/xwiki/wysiwyg/public/Wysiwyg.css	(revision 13966)
+++ src/main/resources/com/xpn/xwiki/wysiwyg/public/Wysiwyg.css	(working copy)
@@ -215,3 +215,107 @@
   /* IE6 */
   width: 1px; 
 }
+/********styles for link********/
+.gwt-TabBar {
+}
+.gwt-TabBar .gwt-TabBarFirst {
+  width: 5px;  /* first tab distance from the left */
+}
+.gwt-TabBar .gwt-TabBarRest {
+}
+.gwt-TabBar .gwt-TabBarItem {
+  margin-left: 6px;
+  padding: 3px 6px 3px 6px;
+  cursor: pointer;
+  cursor: hand;
+  color: black;
+  font-weight: bold;
+  text-align: center;
+  background: #d0e4f6; 
+}
+.gwt-TabBar .gwt-TabBarItem-selected {
+  cursor: default;
+  background: #92c1f0;
+} 
+.gwt-TabPanel {
+  padding: 6px;
+}
+.gwt-TabPanelBottom {
+  border-color: #92c1f0;
+  border-style: solid;
+  border-width: 3px 2px 2px;
+  overflow: hidden;
+  padding: 6px;
+}
+.gwt-PopupPanel {
+  background: white;
+}
+
+.xLinkToUrl .gwt-Label{
+	font-weight: bold;
+	width: 300px;
+	padding: 8px;
+	
+}
+.xLinkToUrl .gwt-TextBox{
+	font-size: x-small;		
+	margin: 8px;
+}
+.xLinkToUrl .gwt-Button{
+	font-size: x-small;	
+	margin: 8px;
+}
+.xLinkToNewPage .gwt-FlowPanel{
+	padding: 8px;	
+}
+.xLinkToNewPage .gwt-ListBox{
+	margin: 8px;
+}
+.xLinkToNewPage .gwt-Label{	
+	display: inline;
+	font-weight: bold;
+	width: 0px;
+	margin: 8px;
+}
+.xLinkToNewPage .gwt-TextBox{
+	font-size: x-small;
+	margin: 8px;		
+}
+.xLinkToNewPage .gwt-Button{
+	font-size: x-small;	
+}
+.xLinkToExistingPage .gwt-FlowPanel{
+	margin: 18px;	
+}
+.xLinkToExistingPage .gwt-Label {
+	margin-top: 5px;
+	font-weight: bold;
+}
+.xLinkToExistingPage .gwt-Button {
+	font-size: small;
+	margin-left: 10px;
+}
+.xLinkToNewPage .gwt-Label{	
+	display: inline;
+	font-weight: bold;
+	width: 0px;
+	margin: 8px;
+}
+.xLinkToNewPage .gwt-TextBox{
+	font-size: x-small;
+	margin: 8px;		
+}
+.xLinkToNewPage .gwt-Button{
+	font-size: x-small;	
+}
+.xLinkToExistingPage .gwt-FlowPanel{
+	margin: 18px;	
+}
+.xLinkToExistingPage .gwt-Label {
+	margin-top: 5px;
+	font-weight: bold;
+}
+.xLinkToExistingPage .gwt-Button {
+	font-size: small;
+	margin-left: 10px;
+}
Index: src/main/java/com/xpn/xwiki/wysiwyg/client/widget/rta/cmd/internal/CreateLinkExecutable.java
===================================================================
--- src/main/java/com/xpn/xwiki/wysiwyg/client/widget/rta/cmd/internal/CreateLinkExecutable.java	(revision 0)
+++ src/main/java/com/xpn/xwiki/wysiwyg/client/widget/rta/cmd/internal/CreateLinkExecutable.java	(revision 0)
@@ -0,0 +1,11 @@
+package com.xpn.xwiki.wysiwyg.client.widget.rta.cmd.internal;
+
+import com.xpn.xwiki.wysiwyg.client.widget.rta.cmd.Command;
+
+public class CreateLinkExecutable extends DefaultExecutable
+{
+    public CreateLinkExecutable()
+    {
+        super(Command.INSERT_HTML.toString());
+    }
+}
Index: src/main/java/com/xpn/xwiki/wysiwyg/client/editor/WysiwygEditorFactory.java
===================================================================
--- src/main/java/com/xpn/xwiki/wysiwyg/client/editor/WysiwygEditorFactory.java	(revision 13966)
+++ src/main/java/com/xpn/xwiki/wysiwyg/client/editor/WysiwygEditorFactory.java	(working copy)
@@ -27,6 +27,7 @@
 import com.xpn.xwiki.wysiwyg.client.plugin.indent.IndentPluginFactory;
 import com.xpn.xwiki.wysiwyg.client.plugin.internal.DefaultPluginFactoryManager;
 import com.xpn.xwiki.wysiwyg.client.plugin.justify.JustifyPluginFactory;
+import com.xpn.xwiki.wysiwyg.client.plugin.link.LinkPluginFactory;
 import com.xpn.xwiki.wysiwyg.client.plugin.list.ListPluginFactory;
 import com.xpn.xwiki.wysiwyg.client.plugin.separator.SeparatorPluginFactory;
 import com.xpn.xwiki.wysiwyg.client.plugin.symbol.SymbolPluginFactory;
@@ -68,6 +69,7 @@
         pfm.addPluginFactory(ColorPluginFactory.getInstance());
         pfm.addPluginFactory(SyncPluginFactory.getInstance());
         pfm.addPluginFactory(SymbolPluginFactory.getInstance());
+        pfm.addPluginFactory(LinkPluginFactory.getInstance());
         // add additional PluginFactory for other plug-ins
     }
 
Index: src/main/resources/com/xpn/xwiki/wysiwyg/client/editor/Strings.properties
===================================================================
--- src/main/resources/com/xpn/xwiki/wysiwyg/client/editor/Strings.properties	(revision 13966)
+++ src/main/resources/com/xpn/xwiki/wysiwyg/client/editor/Strings.properties	(working copy)
@@ -28,7 +28,6 @@
 justifyFull=Align full
 justifyLeft=Align left
 justifyRight=Align right
-link=Insert/edit link
 ol=Ordered list
 outdent=Outdent
 paste=Paste
@@ -49,4 +48,31 @@
 insertTable=Inserts a new table
 underline=Underline (CTRL+U)
 undo=Undo (CTRL+Z)
-unlink=Unlink
\ No newline at end of file
+
+chooseWiki=Choose a wiki: 
+chooseSpace=Choose a space: 
+choosePage=Choose a page: 
+chooseAnchor=Choose an anchor: 
+chooseVersion=Choose a version: 
+chooseAttachment=Choose an attachment: 
+ 
+link=Insert link
+unlink=Unlink
+linkCreateLinkButon=Create Link
+linkNewPageTab=New page
+linkEmailTab=Email address
+linkExistingPageTab=Existing page
+linkWebPageTab=Web page
+linkWebPageLabel=Webpage address: 
+linkEmailLabel=Email address: 
+linkNewSpaceLabel=New space name: 
+linkNewPageLabel=New page name: 
+linkEmailAddressTextBox=Type here the email address you want to link to...
+linkWebPageTextBox=Type here the address of the webpage you want to link to...
+linkNewSpaceTextBox=Type the name of the new space...
+linkNewPageTextBox=Type the title of the new page...
+linkCreateNewSpaceText=Create a new space... 
+linkNewSpaceError=The name of the new space wasn't set!
+linkNewPageError=The name of the new page wasn't set!
+linkEmailAddressError=The email address wasn't set!
+linkWebPageAddressError=The web page address wasn't set!
\ No newline at end of file
Index: src/main/java/com/xpn/xwiki/wysiwyg/client/editor/Strings.java
===================================================================
--- src/main/java/com/xpn/xwiki/wysiwyg/client/editor/Strings.java	(revision 13966)
+++ src/main/java/com/xpn/xwiki/wysiwyg/client/editor/Strings.java	(working copy)
@@ -80,8 +80,6 @@
 
     String justifyRight();
 
-    String link();
-
     String macro();
 
     String normal();
@@ -112,5 +110,55 @@
 
     String undo();
 
+    String chooseWiki();
+
+    String chooseSpace();
+
+    String choosePage();
+
+    String chooseAnchor();
+
+    String chooseVersion();
+
+    String chooseAttachment();
+
+    String link();
+
     String unlink();
+
+    String linkCreateLinkButon();
+
+    String linkNewPageTab();
+
+    String linkEmailTab();
+
+    String linkExistingPageTab();
+
+    String linkWebPageTab();
+
+    String linkWebPageLabel();
+
+    String linkEmailLabel();
+
+    String linkNewSpaceLabel();
+
+    String linkNewPageLabel();
+
+    String linkEmailAddressTextBox();
+
+    String linkWebPageTextBox();
+
+    String linkNewSpaceTextBox();
+
+    String linkNewPageTextBox();
+
+    String linkCreateNewSpaceText();
+
+    String linkNewSpaceError();
+
+    String linkNewPageError();
+
+    String linkEmailAddressError();
+
+    String linkWebPageAddressError();
 }
